Browse Source

WIP - USB starting to talk to Keyboard

Again still WIP - but now have the Bluetooth object talking through a keyboard object...
main
Kurt Eckhardt 6 years ago
parent
commit
c7f793244c
3 changed files with 213 additions and 51 deletions
  1. +49
    -35
      USBHost_t36.h
  2. +70
    -14
      bluetooth.cpp
  3. +94
    -2
      keyboard.cpp

+ 49
- 35
USBHost_t36.h View File

@@ -56,7 +56,7 @@
// your best effort to read chapter 4 before asking USB questions!


//#define USBHOST_PRINT_DEBUG
#define USBHOST_PRINT_DEBUG

/************************************************/
/* Data Types */
@@ -516,6 +516,35 @@ protected:
Device_t *mydevice = NULL;
};


// Device drivers may inherit from this base class, if they wish to receive
// HID input like data from Bluetooth HID device.
class BluetoothController;

class BTHIDInput {
public:
operator bool() { return (btdevice != nullptr); }
uint16_t idVendor() { return (btdevice != nullptr) ? btdevice->idVendor : 0; }
uint16_t idProduct() { return (btdevice != nullptr) ? btdevice->idProduct : 0; }
const uint8_t *manufacturer()
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; }
const uint8_t *product()
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; }
const uint8_t *serialNumber()
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; }

private:
virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class) {return false;}
virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length) {return false;}
virtual void release_bluetooth() {};
void add_to_list();
BTHIDInput *next;
friend class BluetoothController;
protected:
Device_t *btdevice = NULL;
};


/************************************************/
/* USB Device Drivers */
/************************************************/
@@ -655,7 +684,7 @@ private:

//--------------------------------------------------------------------------

class KeyboardController : public USBDriver , public USBHIDInput {
class KeyboardController : public USBDriver , public USBHIDInput, public BTHIDInput {
public:
typedef union {
struct {
@@ -673,7 +702,13 @@ public:
KeyboardController(USBHost *host) { init(); }

// Some methods are in both public classes so we need to figure out which one to use
operator bool() { return (device != nullptr); }
uint16_t idVendor();
uint16_t idProduct();

const uint8_t *manufacturer();
const uint8_t *product();
const uint8_t *serialNumber();
operator bool() { return ((device != nullptr) || (btdevice != nullptr)); }
// Main boot keyboard functions.
uint16_t getKey() { return keyCode; }
uint8_t getModifiers() { return modifiers; }
@@ -704,6 +739,12 @@ protected:
void new_data(const Transfer_t *transfer);
void init();

// Bluetooth data
bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class);
bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length);
void release_bluetooth();


protected: // HID functions for extra keyboard data.
virtual hidclaim_t claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage);
virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax);
@@ -1546,12 +1587,15 @@ public:

enum {MAX_ENDPOINTS=4, NUM_SERVICES=4, }; // Max number of Bluetooth services - if you need more than 4 simply increase this number
enum {BT_CLASS_DEVICE= 0x0804}; // Toy - Robot
static void driver_ready_for_bluetooth(BTHIDInput *driver);

protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
virtual void control(const Transfer_t *transfer);
virtual void disconnect();
//virtual void timer_event(USBDriverTimer *whichTimer);

BTHIDInput * find_driver(uint32_t device_type);
private:
static void rx_callback(const Transfer_t *transfer);
static void rx2_callback(const Transfer_t *transfer);
@@ -1580,38 +1624,6 @@ private:

void inline sendHCIRemoteNameRequest();

//void inline sendHCIReadBufferSize();
//void inline sendHCIReadClassOfDevice();
//void inline sendHCIReadLocalSupportedCommands();
//void inline sendHCIReadLocalName();
//void inline sendHCIReadVoiceSettings();
//void inline sendHCICommandReadNumberSupportedIAC();
//void inline sendHCICommandReadCurrentIACLAP();
//void inline sendHCIClearAllEventFilters();
//void inline sendHCIWriteConnectionAcceptTimeout();
//void inline sendHCILEReadBufferSize();
//void inline sendHCILEReadLocalSupportedFeatures();
//void inline sendHCILEReadSupportedStates();
//void inline sendHCIWriteInquiryMode();
//void inline sendHCIReadInquiryResponseTransmitPowerLevel();
//void inline sendHCIReadLocalExtendedFeatures(uint8_t page);
//void inline sendHCISetEventMask();
//void inline sendHCIReadStoredLinkKey();
//void inline sendHCIWriteDefaultLinkPolicySettings();
//void inline sendHCIReadPageScanActivity();
//void inline sendHCIReadPageScanType();
//void inline sendHCILESetEventMask();
//void inline sendHCILEReadADVTXPower();
//void inline sendHCIEReadWhiteListSize();
//void inline sendHCILEClearWhiteList();
//void inline sendHCIDeleteStoredLinkKey();
//void inline sendHCIWriteLocalName();
//void inline sendHCIWriteSSPMode(uint8_t ssp_mode);
//void inline sendHCIWriteEIR();
//void inline sendHCIWriteLEHostSupported();
//void inline sendHCILESetAdvData () ;
//void inline sendHCILESetScanRSPData();

void handle_hci_command_complete();
void handle_hci_command_status();
void handle_hci_inquiry_result();
@@ -1639,6 +1651,7 @@ private:

void setHIDProtocol(uint8_t protocol);
void handleHIDTHDRData(uint8_t *buffer); // Pass the whole buffer...
static BTHIDInput *available_bthid_drivers_list;


setup_t setup;
@@ -1663,6 +1676,7 @@ private:
const char *pair_pincode_; // What pin code to use for the pairing
uint8_t my_bdaddr[6]; // The bluetooth dongles Bluetooth address.
uint8_t features[8]; // remember our local features.
BTHIDInput * device_driver_ = nullptr;;
uint8_t device_bdaddr_[6];// remember devices address
uint8_t device_ps_repetion_mode_ ; // mode
uint8_t device_clock_offset_[2];

+ 70
- 14
bluetooth.cpp View File

@@ -149,6 +149,42 @@ enum {PC_RESET = 1, PC_WRITE_CLASS_DEVICE, PC_READ_BDADDR, PC_READ_LOCAL_VERSION
// Setup some states for the TX pipe where we need to chain messages
enum {STATE_TX_SEND_CONNECT_INT=200, STATE_TX_SEND_CONECT_RSP_SUCCESS, STATE_TX_SEND_CONFIG_REQ};

// This is a list of all the drivers inherited from the BTHIDInput class.
// Unlike the list of USBDriver (managed in enumeration.cpp), drivers stay
// on this list even when they have claimed a top level collection.
BTHIDInput * BluetoothController::available_bthid_drivers_list = NULL;

void BluetoothController::driver_ready_for_bluetooth(BTHIDInput *driver)
{
driver->next = NULL;
if (available_bthid_drivers_list == NULL) {
available_bthid_drivers_list = driver;
} else {
BTHIDInput *last = available_bthid_drivers_list;
while (last->next) last = last->next;
last->next = driver;
}
}

// When a new top level collection is found, this function asks drivers
// if they wish to claim it. The driver taking ownership of the
// collection is returned, or NULL if no driver wants it.
BTHIDInput * BluetoothController::find_driver(uint32_t device_type)
{
Serial.printf("BluetoothController::find_driver");
BTHIDInput *driver = available_bthid_drivers_list;
while (driver) {
Serial.printf(" driver %x\n", (uint32_t)driver);
if (driver->claim_bluetooth(this, device_type)) {
Serial.printf(" *** Claimed ***\n");
return driver;
}
driver = driver->next;
}
return NULL;
}


/************************************************************/
// Initialization and claiming of devices & interfaces
/************************************************************/
@@ -265,6 +301,11 @@ bool BluetoothController::claim(Device_t *dev, int type, const uint8_t *descript

void BluetoothController::disconnect()
{
Serial.printf("Bluetooth Disconnect");
if (device_driver_) {
device_driver_->release_bluetooth();
device_driver_ = nullptr;
}
}


@@ -739,6 +780,8 @@ void BluetoothController::handle_hci_inquiry_result()
// BUGBUG, lets hard code to go to new state...
for (uint8_t i = 0; i < 6; i++) device_bdaddr_[i] = rxbuf_[index_bd+i];
device_class_ = bluetooth_class;
device_driver_ = find_driver(device_class_);

device_ps_repetion_mode_ = rxbuf_[index_ps]; // mode
device_clock_offset_[0] = rxbuf_[index_clock_offset];
device_clock_offset_[1] = rxbuf_[index_clock_offset+1];
@@ -777,6 +820,7 @@ void BluetoothController::handle_hci_incoming_connect() {
DBGPrintf(" Peripheral device\n");
if (class_of_device & 0x80) DBGPrintf(" Mouse\n");
if (class_of_device & 0x40) DBGPrintf(" Keyboard\n");
device_driver_ = find_driver(class_of_device);

// We need to save away the BDADDR and class link type?
for(uint8_t i=0; i<6; i++) device_bdaddr_[i] = rxbuf_[i+2];
@@ -826,6 +870,14 @@ void BluetoothController::handle_hci_disconnect_complete()
//5 4 0 48 0 13
DBGPrintf(" Event: HCI Disconnect complete(%d): handle: %x, reason:%x\n", rxbuf_[2],
rxbuf_[3]+(rxbuf_[4]<<8), rxbuf_[5]);
if (device_driver_) {
device_driver_->release_bluetooth();
device_driver_ = nullptr;
}
// Probably should clear out connection data.
device_class_ = 0;
memset(device_bdaddr_, 0, sizeof(device_bdaddr_));
//...
}

void BluetoothController::handle_hci_authentication_complete()
@@ -1249,7 +1301,8 @@ void BluetoothController::process_l2cap_config_response(uint8_t *data) {
data[8]+((uint16_t)data[9] << 8), data[10]+((uint16_t)data[11] << 8));
if (scid == control_dcid_) {
// Set HID Boot mode
setHIDProtocol(HID_BOOT_PROTOCOL);
//setHIDProtocol(HID_BOOT_PROTOCOL); //
setHIDProtocol(HID_RPT_PROTOCOL); //HID_RPT_PROTOCOL
if (do_pair_device_) {
// Tell system we will next need to setup connection for the interrupt
pending_control_tx_ = STATE_TX_SEND_CONNECT_INT;
@@ -1276,18 +1329,21 @@ void BluetoothController::handleHIDTHDRData(uint8_t *data) {
DBGPrintf("HID HDR Data: len: %d, Type: %d\n", len, data[9]);

// ??? How to parse??? Use HID object???
switch (data[9]) {
case 1:
DBGPrintf(" Keyboard report type\n");
break;
case 2:
DBGPrintf(" Mouse report type\n");
break;
case 3:
DBGPrintf(" Combo keyboard/pointing\n");
break;
default:
DBGPrintf(" Unknown report\n");
if (device_driver_) {
device_driver_->process_bluetooth_HID_data(&data[9], len-1); // We skip the first byte...
} else {
switch (data[9]) {
case 1:
DBGPrintf(" Keyboard report type\n");
break;
case 2:
DBGPrintf(" Mouse report type\n");
break;
case 3:
DBGPrintf(" Combo keyboard/pointing\n");
break;
default:
DBGPrintf(" Unknown report\n");
}
}

}

+ 94
- 2
keyboard.cpp View File

@@ -92,6 +92,44 @@ keycode_numlock_t keycode_numlock[] = {
#define print USBHost::print_
#define println USBHost::println_


uint16_t KeyboardController::idVendor()
{
if (device != nullptr) return device->idVendor;
if (btdevice != nullptr) return btdevice->idVendor;
return 0;
}

uint16_t KeyboardController::idProduct()
{
if (device != nullptr) return device->idProduct;
if (btdevice != nullptr) return btdevice->idProduct;
return 0;
}

const uint8_t *KeyboardController::manufacturer()
{
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
return nullptr;
}

const uint8_t *KeyboardController::product()
{
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
return nullptr;
}

const uint8_t *KeyboardController::serialNumber()
{
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
return nullptr;
}



void KeyboardController::init()
{
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
@@ -99,6 +137,7 @@ void KeyboardController::init()
contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t));
driver_ready_for_device(this);
USBHIDParser::driver_ready_for_hid_collection(this);
BluetoothController::driver_ready_for_bluetooth(this);
}

bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
@@ -323,8 +362,13 @@ void KeyboardController::LEDS(uint8_t leds) {

void KeyboardController::updateLEDS() {
// Now lets tell keyboard new state.
mk_setup(setup, 0x21, 9, 0x200, 0, sizeof(leds_.byte)); // hopefully this sets leds
queue_Control_Transfer(device, &setup, &leds_.byte, this);
if (device != nullptr) {
// Only do it this way if we are a standard USB device
mk_setup(setup, 0x21, 9, 0x200, 0, sizeof(leds_.byte)); // hopefully this sets leds
queue_Control_Transfer(device, &setup, &leds_.byte, this);
} else {
// Bluetooth, need to setup back channel to Bluetooth controller.
}
}

//=============================================================================
@@ -426,3 +470,51 @@ void KeyboardController::hid_input_end()
hid_input_begin_ = false;
}
}

bool KeyboardController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class)
{
Serial.printf("Keyboard Controller::claim_bluetooth - Class %x\n", bluetooth_class);
if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && (bluetooth_class & 0x40)) {
Serial.printf("KeyboardController::claim_bluetooth TRUE\n");
//btdevice = driver;
return true;
}
return false;
}

bool KeyboardController::process_bluetooth_HID_data(const uint8_t *data, uint16_t length)
{
// Example DATA from bluetooth keyboard:
// 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7
// LEN D
//BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 0 0 0 0 0 0
//BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 4 0 0 0 0 0
//BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 0 0 0 0 0 0
// So Len=9 passed in data starting at report ID=1...
Serial.printf("KeyboardController::process_bluetooth_HID_data\n");
if (data[0] != 1) return false;
print(" KB Data: ");
print_hexbytes(data, length);
for (int i=2; i < length; i++) {
uint32_t key = prev_report[i];
if (key >= 4 && !contains(key, report)) {
key_release(prev_report[0], key);
}
}
for (int i=2; i < 8; i++) {
uint32_t key = data[i];
if (key >= 4 && !contains(key, prev_report)) {
key_press(data[1], key);
}
}
// Save away the data.. But shift down one byte... Don't need the report number
memcpy(prev_report, &data[1], 8);
return true;
}

void KeyboardController::release_bluetooth()
{
//btdevice = nullptr;

}


Loading…
Cancel
Save