Browse Source

Merge pull request #2 from KurtE/WIP2-Bluetooth

BT - Try extended information on bind query
main
Mike S 5 years ago
parent
commit
12adca9b73
No account linked to committer's email address
4 changed files with 148 additions and 27 deletions
  1. +4
    -0
      USBHost_t36.h
  2. +111
    -13
      bluetooth.cpp
  3. +1
    -1
      examples/JoystickBT/helperPS.ino
  4. +32
    -13
      joystick.cpp

+ 4
- 0
USBHost_t36.h View File

joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices); joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices);
bool transmitPS4UserFeedbackMsg(); bool transmitPS4UserFeedbackMsg();
bool transmitPS3UserFeedbackMsg(); bool transmitPS3UserFeedbackMsg();
bool mapNameToJoystickType(const uint8_t *remoteName);


bool anychange = false; bool anychange = false;
volatile bool joystickEvent = false; volatile bool joystickEvent = false;
void inline sendHCIReadBDAddr(); void inline sendHCIReadBDAddr();
void inline sendHCIReadLocalVersionInfo(); void inline sendHCIReadLocalVersionInfo();
void inline sendHCIWriteScanEnable(uint8_t scan_op); void inline sendHCIWriteScanEnable(uint8_t scan_op);
void inline sendHCIHCIWriteInquiryMode(uint8_t inquiry_mode);
void inline sendHCISetEventMask();


void inline sendHCIRemoteNameRequest(); void inline sendHCIRemoteNameRequest();
void inline sendHCIRemoteVersionInfoRequest(); void inline sendHCIRemoteVersionInfoRequest();
void handle_hci_command_complete(); void handle_hci_command_complete();
void handle_hci_command_status(); void handle_hci_command_status();
void handle_hci_inquiry_result(); void handle_hci_inquiry_result();
void handle_hci_extended_inquiry_result();
void handle_hci_inquiry_complete(); void handle_hci_inquiry_complete();
void handle_hci_incoming_connect(); void handle_hci_incoming_connect();
void handle_hci_connection_complete(); void handle_hci_connection_complete();

+ 111
- 13
bluetooth.cpp View File

,EV_AUTHENTICATION_COMPLETE= 0x06,EV_REMOTE_NAME_COMPLETE= 0x07,EV_ENCRYPTION_CHANGE= 0x08,EV_CHANGE_CONNECTION_LINK= 0x09,EV_ROLE_CHANGED= 0x12 ,EV_AUTHENTICATION_COMPLETE= 0x06,EV_REMOTE_NAME_COMPLETE= 0x07,EV_ENCRYPTION_CHANGE= 0x08,EV_CHANGE_CONNECTION_LINK= 0x09,EV_ROLE_CHANGED= 0x12
,EV_NUM_COMPLETE_PKT= 0x13,EV_PIN_CODE_REQUEST= 0x16,EV_LINK_KEY_REQUEST= 0x17,EV_LINK_KEY_NOTIFICATION= 0x18,EV_DATA_BUFFER_OVERFLOW= 0x1A ,EV_NUM_COMPLETE_PKT= 0x13,EV_PIN_CODE_REQUEST= 0x16,EV_LINK_KEY_REQUEST= 0x17,EV_LINK_KEY_NOTIFICATION= 0x18,EV_DATA_BUFFER_OVERFLOW= 0x1A
,EV_MAX_SLOTS_CHANGE= 0x1B,EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE= 0x0C,EV_QOS_SETUP_COMPLETE= 0x0D,EV_COMMAND_COMPLETE= 0x0E,EV_COMMAND_STATUS= 0x0F ,EV_MAX_SLOTS_CHANGE= 0x1B,EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE= 0x0C,EV_QOS_SETUP_COMPLETE= 0x0D,EV_COMMAND_COMPLETE= 0x0E,EV_COMMAND_STATUS= 0x0F
,EV_LOOPBACK_COMMAND= 0x19,EV_PAGE_SCAN_REP_MODE= 0x20 };
,EV_LOOPBACK_COMMAND= 0x19,EV_PAGE_SCAN_REP_MODE= 0x20, HCI_Extended_Inquiry_Result=0x2F };








// different modes // different modes
enum {PC_RESET = 1, PC_WRITE_CLASS_DEVICE, PC_READ_BDADDR, PC_READ_LOCAL_VERSION, enum {PC_RESET = 1, PC_WRITE_CLASS_DEVICE, PC_READ_BDADDR, PC_READ_LOCAL_VERSION,
PC_SEND_INQUIRE, PC_INQUIRE_CANCEL=100, PC_AUTHENTICATION_REQUESTED=110, PC_LINK_KEY_NEGATIVE=120, PC_PIN_CODE_REPLY=130,
PC_SEND_WRITE_INQUIRE_MODE, PC_SEND_SET_EVENT_MASK, PC_SEND_INQUIRE,
PC_INQUIRE_CANCEL=100, PC_AUTHENTICATION_REQUESTED=110, PC_LINK_KEY_NEGATIVE=120, PC_PIN_CODE_REPLY=130,
PC_WRITE_SCAN_PAGE=200}; PC_WRITE_SCAN_PAGE=200};
////////////// //////////////


break; break;
case EV_LINK_KEY_NOTIFICATION: // 0x18 case EV_LINK_KEY_NOTIFICATION: // 0x18
handle_hci_link_key_notification(); handle_hci_link_key_notification();
break;
case HCI_Extended_Inquiry_Result:
handle_hci_extended_inquiry_result();
break;
default: default:
break; break;
} }
case HCI_Read_Local_Version_Information: //0x1001 case HCI_Read_Local_Version_Information: //0x1001
hciVersion = rxbuf_[6]; // Should do error checking above... hciVersion = rxbuf_[6]; // Should do error checking above...
DBGPrintf(" Local Version: %x\n", hciVersion); DBGPrintf(" Local Version: %x\n", hciVersion);
pending_control_ = (do_pair_device_)? PC_SEND_INQUIRE : PC_WRITE_SCAN_PAGE;
pending_control_ = (do_pair_device_)? PC_SEND_WRITE_INQUIRE_MODE : PC_WRITE_SCAN_PAGE;
break; break;
case HCI_Read_Local_Supported_Commands: //0x1002 case HCI_Read_Local_Supported_Commands: //0x1002
break; break;
DBGPrintf("Write_Scan_enable Completed\n"); DBGPrintf("Write_Scan_enable Completed\n");
// See if we have driver and a remote // See if we have driver and a remote
if (device_driver_ && connection_complete_) { // We have a driver call their if (device_driver_ && connection_complete_) { // We have a driver call their

// Now see if we have the remote name or not?
if (device_driver_->remote_name_[0]) {
device_driver_->connectionComplete();
connection_complete_ = false; // only call once
} else {
sendHCIRemoteNameRequest();
}
device_driver_->connectionComplete();
connection_complete_ = false; // only call once
} }
break; break;
case HCI_WRITE_SSP_MODE: //0x0c56 case HCI_WRITE_SSP_MODE: //0x0c56
break; break;


// These are used when we are pairing. // These are used when we are pairing.
case PC_SEND_WRITE_INQUIRE_MODE:
sendHCIHCIWriteInquiryMode(2); // lets set into extended inquire mode
pending_control_++;
break;

case PC_SEND_SET_EVENT_MASK:
sendHCISetEventMask(); // Set the event mask to include extend inquire event
pending_control_++;
break;

case PC_SEND_INQUIRE: case PC_SEND_INQUIRE:
sendHCI_INQUIRY(); sendHCI_INQUIRY();
pending_control_++; pending_control_++;
} }
} }


void BluetoothController::handle_hci_extended_inquiry_result()
{
DBGPrintf(" Extended Inquiry Result - Count: %d\n", rxbuf_[2]);
// Should always be only one result here.
uint8_t index_bd = 3;
uint8_t index_ps = 9;
uint8_t index_class = 11;
uint8_t index_clock_offset = 14;
//uint8_t index_rssi = 16;
uint8_t index_eir_data = 17;
uint8_t index_local_name = 0;
uint8_t size_local_name = 0;
uint32_t bluetooth_class = rxbuf_[index_class] + ((uint32_t)rxbuf_[index_class+1] << 8) + ((uint32_t)rxbuf_[index_class+2] << 16);
DBGPrintf(" BD:%x:%x:%x:%x:%x:%x, PS:%d, class: %x\n",
rxbuf_[index_bd],rxbuf_[index_bd+1],rxbuf_[index_bd+2],rxbuf_[index_bd+3],rxbuf_[index_bd+4],rxbuf_[index_bd+5],
rxbuf_[index_ps], bluetooth_class);
// Lets see if we can find a name
while (index_eir_data < 256) {
if (rxbuf_[index_eir_data] == 0) break; // no more data
switch (rxbuf_[index_eir_data+1]) {
case 0x08: // Shortened local name
case 0x09: // complete local name
index_local_name = index_eir_data+2;
size_local_name = rxbuf_[index_eir_data]-1;
break;
}
index_eir_data += rxbuf_[index_eir_data] + 1; // point to the next item

}
if (index_local_name && size_local_name) {
// Hack lets null teminate the string
rxbuf_[index_local_name+size_local_name] = 0;

DBGPrintf(" Local Name: %s\n", &rxbuf_[index_local_name]);
}

// See if we know the class
if (((bluetooth_class & 0xff00) == 0x2500) || ((bluetooth_class & 0xff00) == 0x500)) {
DBGPrintf(" Peripheral device\n");
if (bluetooth_class & 0x80) DBGPrintf(" Mouse\n");
if (bluetooth_class & 0x40) DBGPrintf(" Keyboard\n");
switch(bluetooth_class & 0x3c) {
case 4: DBGPrintf(" Joystick\n"); break;
case 8: DBGPrintf(" Gamepad\n"); break;
case 0xc: DBGPrintf(" Remote Control\n"); break;
}

// 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_, index_local_name? &rxbuf_[index_local_name] : nullptr);

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];

// and if we found a driver, save away the name
if (device_driver_ && index_local_name && size_local_name) {
uint8_t buffer_index;
for (buffer_index = 0; size_local_name && (buffer_index < BTHIDInput::REMOTE_NAME_SIZE-1); buffer_index++) {
device_driver_->remote_name_[buffer_index] = rxbuf_[index_local_name+buffer_index];
size_local_name--;
}
device_driver_->remote_name_[buffer_index] = 0; // make sure null terminated
}

// Now we need to bail from inquiry and setup to try to connect...
sendHCIInquiryCancel();
pending_control_ = PC_INQUIRE_CANCEL;
}
}

void BluetoothController::handle_hci_inquiry_complete() { void BluetoothController::handle_hci_inquiry_complete() {
VDBGPrintf(" Inquiry Complete - status: %d\n", rxbuf_[2]); VDBGPrintf(" Inquiry Complete - status: %d\n", rxbuf_[2]);
} }
// The PS4 requires a connection request to it. // The PS4 requires a connection request to it.
delay(1); delay(1);
sendl2cap_ConnectionRequest(device_connection_handle_, connection_rxid_, control_dcid_, HID_CTRL_PSM); sendl2cap_ConnectionRequest(device_connection_handle_, connection_rxid_, control_dcid_, HID_CTRL_PSM);
#if 0
delay(1); delay(1);
uint8_t packet[2]; uint8_t packet[2];
packet[1] = 0x02; // Report ID packet[1] = 0x02; // Report ID
USBHDBGSerial.printf("SixAxis Command Issued!\r\n"); USBHDBGSerial.printf("SixAxis Command Issued!\r\n");
sendL2CapCommand(packet, sizeof(packet), 0x40); sendL2CapCommand(packet, sizeof(packet), 0x40);
#endif
} }
} }


} }
} }
if (device_driver_) { if (device_driver_) {
// lets allocate a string object
// lets save away the string.
uint8_t buffer_index; uint8_t buffer_index;
for (buffer_index = 0; buffer_index < BTHIDInput::REMOTE_NAME_SIZE-1; buffer_index++) { for (buffer_index = 0; buffer_index < BTHIDInput::REMOTE_NAME_SIZE-1; buffer_index++) {
device_driver_->remote_name_[buffer_index] = rxbuf_[9+buffer_index]; device_driver_->remote_name_[buffer_index] = rxbuf_[9+buffer_index];
queue_Control_Transfer(device, &setup, txbuf_, this); queue_Control_Transfer(device, &setup, txbuf_, this);
} }


//---------------------------------------------
void BluetoothController::sendHCIHCIWriteInquiryMode(uint8_t inquiry_mode) {
// Setup Inquiry mode
DBGPrintf("HCI_WRITE_INQUIRY_MODE called (");
sendHCICommand(HCI_WRITE_INQUIRY_MODE, 1, &inquiry_mode);
}

void BluetoothController::sendHCISetEventMask() {
// Setup Inquiry mode
DBGPrintf("HCI_Set_Event_Mask called (");
static const uint8_t hci_event_mask_data[8] = {
// Default: 0x0000 1FFF FFFF FFFF
0xff,0xff, 0xff,0xff, 0xff,0x5f, 0x00,0x00}; // default plus extended inquiry mode
sendHCICommand(HCI_Set_Event_Mask, sizeof(hci_event_mask_data), hci_event_mask_data);
}

//--------------------------------------------- //---------------------------------------------
void BluetoothController::sendHCI_INQUIRY() { void BluetoothController::sendHCI_INQUIRY() {
// Start unlimited inqury, set timeout to max and // Start unlimited inqury, set timeout to max and

+ 1
- 1
examples/JoystickBT/helperPS.ino View File

void getCoords(uint16_t &xc, uint16_t &yc, uint8_t &isTouch){ void getCoords(uint16_t &xc, uint16_t &yc, uint8_t &isTouch){


//uint8_t finger = 0; //only getting finger 1 //uint8_t finger = 0; //only getting finger 1
uint8_t Id = 0;
//uint8_t Id = 0;




// Trackpad touch 1: id, active, x, y // Trackpad touch 1: id, active, x, y

+ 32
- 13
joystick.cpp View File

DBGPrintf("JoystickController::claim_bluetooth TRUE\n"); DBGPrintf("JoystickController::claim_bluetooth TRUE\n");
btdriver_ = driver; btdriver_ = driver;
btdevice = (Device_t*)driver; // remember this way btdevice = (Device_t*)driver; // remember this way
if (remoteName) mapNameToJoystickType(remoteName);
return true; return true;
} }
if (remoteName && (strncmp((const char *)remoteName, "PLAYSTATION(R)3", 15) == 0)) {
DBGPrintf("JoystickController::claim_bluetooth TRUE PS3 hack...\n");
btdriver_ = driver;
btdevice = (Device_t*)driver; // remember this way
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS.
joystickType_ = PS3;
return true;

if (remoteName && mapNameToJoystickType(remoteName)) {
if (joystickType_ == PS3) {
DBGPrintf("JoystickController::claim_bluetooth TRUE PS3 hack...\n");
btdriver_ = driver;
btdevice = (Device_t*)driver; // remember this way
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS.
return true;
}
} }
return false; return false;
} }
return false; return false;
} }


bool JoystickController::remoteNameComplete(const uint8_t *remoteName)
bool JoystickController::mapNameToJoystickType(const uint8_t *remoteName)
{ {
// Sort of a hack, but try to map the name given from remote to a type... // Sort of a hack, but try to map the name given from remote to a type...
if (strncmp((const char *)remoteName, "Wireless Controller", 19) == 0) { if (strncmp((const char *)remoteName, "Wireless Controller", 19) == 0) {
DBGPrintf(" JoystickController::remoteNameComplete %s - set to PS4\n", remoteName);
special_process_required = SP_NEED_CONNECT; // We need to force this.
DBGPrintf(" JoystickController::mapNameToJoystickType %s - set to PS4\n", remoteName);
joystickType_ = PS4; joystickType_ = PS4;
} else if (strncmp((const char *)remoteName, "PLAYSTATION(R)3", 15) == 0) { } else if (strncmp((const char *)remoteName, "PLAYSTATION(R)3", 15) == 0) {
DBGPrintf(" JoystickController::remoteNameComplete %x %s - set to PS3\n", (uint32_t)this, remoteName);
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS.
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3\n", (uint32_t)this, remoteName);
joystickType_ = PS3; joystickType_ = PS3;
} else if (strncmp((const char *)remoteName, "Xbox Wireless", 13) == 0) {
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to XBOXONE\n", (uint32_t)this, remoteName);
joystickType_ = XBOXONE;
} else { } else {
DBGPrintf(" JoystickController::remoteNameComplete %s - Unknown\n", remoteName);
DBGPrintf(" JoystickController::mapNameToJoystickType %s - Unknown\n", remoteName);
} }
DBGPrintf(" Joystick Type: %d\n", joystickType_); DBGPrintf(" Joystick Type: %d\n", joystickType_);
return true; return true;
} }



bool JoystickController::remoteNameComplete(const uint8_t *remoteName)
{
// Sort of a hack, but try to map the name given from remote to a type...
if (mapNameToJoystickType(remoteName)) {
switch (joystickType_) {
case PS4: special_process_required = SP_NEED_CONNECT; break;
case PS3: special_process_required = SP_PS3_IDS; break;
default:
break;
}
}
return true;
}

void JoystickController::connectionComplete() void JoystickController::connectionComplete()
{ {
DBGPrintf(" JoystickController::connectionComplete %x joystick type %d\n", (uint32_t)this, joystickType_); DBGPrintf(" JoystickController::connectionComplete %x joystick type %d\n", (uint32_t)this, joystickType_);

Loading…
Cancel
Save