Browse Source

BT - Try extended information on bind query

Trying out using the extended Inquiry data search instead of the real simple one.  This allows us to hopefully get the name of the device as part of this, which now allows the PS4 to know it is a PS4 on the Pair type constructor.

Still WIP to understand XBox one...
main
Kurt Eckhardt 5 years ago
parent
commit
299257b4ab
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