diff --git a/BTD.cpp b/BTD.cpp index 6ada433a..59982298 100644 --- a/BTD.cpp +++ b/BTD.cpp @@ -639,11 +639,24 @@ void BTD::HCI_event_task() { } break; - case EV_LINK_KEY_REQUEST: + case EV_LINK_KEY_REQUEST: //For the Xbox One S Controller we can't use the negative reply, other controllers use negative_reply #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nReceived Key Request"), 0x80); #endif - hci_link_key_request_negative_reply(); + if ((!pairWithHIDDevice || incomingHIDDevice) && incomingXboxOneS) { + for(uint8_t i = 0; i < 16; i ++) { + link_key[i] = EEPROM.read(i+6); + } + hci_link_key_request_reply(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nhci_link_key_request_reply"), 0x80); +#endif + } else { + hci_link_key_request_negative_reply(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nhci_link_key_request_negative_reply"), 0x80); +#endif + } break; case EV_AUTHENTICATION_COMPLETE: @@ -717,6 +730,39 @@ void BTD::HCI_event_task() { } #endif break; + + case EV_LINK_KEY_NOTIFICATION: //Xbox One S BT Controller, when pairing write the address and link key to EEPROM + if(incomingXboxOneS) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nLink Key Notification"), 0x80); +#endif + for(uint8_t i = 0; i < 16; i++) { + link_key[i] = hcibuf[8 + i]; + } + + for(uint8_t i = 0; i < 6; i++) { + EEPROM.write(i, disc_bdaddr[i]); + } + + for(uint8_t i = 0; i < 16; i++) { + EEPROM.write(i + 6, link_key[i]); + } + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nBD_ADDR: "), 0x80); + for(uint8_t i = 0; i < 6; i++) { + Notify(PSTR(" "), 0x80); + D_PrintHex (hcibuf[2 + i], 0x80); + } + Notify(PSTR("\r\nLink Key for the associated BD_ADDR: "), 0x80); + for(uint8_t i = 0; i < 16; i++) { + Notify(PSTR(" "), 0x80); + D_PrintHex (hcibuf[8 + i], 0x80); + } +#endif + } + + break; /* We will just ignore the following events */ case EV_MAX_SLOTS_CHANGE: @@ -728,7 +774,6 @@ void BTD::HCI_event_task() { case EV_DATA_BUFFER_OVERFLOW: case EV_CHANGE_CONNECTION_LINK: case EV_QOS_SETUP_COMPLETE: - case EV_LINK_KEY_NOTIFICATION: case EV_ENCRYPTION_CHANGE: case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE: #ifdef EXTRADEBUG @@ -1015,8 +1060,37 @@ void BTD::HCI_task() { #endif incomingPSController = true; } - if((pairWithWii || pairWithHIDDevice) && checkRemoteName) + + if(strncmp((const char*)remote_name, "Xbox Wireless Controller", 24 ) == 0) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox One S controller is connecting"), 0x80); +#endif + incomingXboxOneS = true; + if(!pairWithHIDDevice) { //If an Xbox One S BT Controller is connecting and it is not in pair mode, check EEPROM for the controller's address + pairedDevice = true; + for(uint8_t i = 0; i < 6; i++) { + if(disc_bdaddr[i] != EEPROM.read(i)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox One S Controller did not match EEPROM"), 0x80); +#endif + pairedDevice = false; + break; + } + } + if(!pairedDevice) { + hci_state = HCI_SCANNING_STATE; + } else { + hci_accept_connection(); + hci_state = HCI_CONNECTED_STATE; + } + } else { //If the Xbox One S BT controlelr is in pair mode instead + hci_state = HCI_CONNECT_DEVICE_STATE; + } + } + + else if((pairWithWii || pairWithHIDDevice) && checkRemoteName) { hci_state = HCI_CONNECT_DEVICE_STATE; + } else { hci_accept_connection(); hci_state = HCI_CONNECTED_STATE; @@ -1059,6 +1133,8 @@ void BTD::HCI_task() { if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) { #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80); + disconnect(); //xbox one bt s <- doesn't work without this! + //Need for the controller to be able to reconnect #endif hci_event_flag = 0; // Clear all flags @@ -1069,10 +1145,11 @@ void BTD::HCI_task() { connectToWii = incomingWii = pairWithWii = false; connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false; incomingPSController = false; - + incomingXboxOneS = false; hci_state = HCI_SCANNING_STATE; } break; + default: break; } @@ -1341,6 +1418,38 @@ void BTD::hci_pin_code_negative_request_reply() { HCI_Command(hcibuf, 9); } +void BTD::hci_link_key_request_reply() { + hcibuf[0] = 0x0B; // HCI OCF = 0B + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x16; // parameter length 22 + //for(uint8_t i = 0; i < 6; i++) hcibuf[i + 3] = disc_bdaddr[i]; // 6 octet bdaddr + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + //for(uint8_t i = 0; i < 16; i++) hcibuf[i + 9] = link_key[i]; // 16 octet link_key + hcibuf[9] = link_key[0]; // 16 octet link_key + hcibuf[10] = link_key[1]; + hcibuf[11] = link_key[2]; + hcibuf[12] = link_key[3]; + hcibuf[13] = link_key[4]; + hcibuf[14] = link_key[5]; + hcibuf[15] = link_key[6]; + hcibuf[16] = link_key[7]; + hcibuf[17] = link_key[8]; + hcibuf[18] = link_key[9]; + hcibuf[19] = link_key[10]; + hcibuf[20] = link_key[11]; + hcibuf[21] = link_key[12]; + hcibuf[22] = link_key[13]; + hcibuf[23] = link_key[14]; + hcibuf[24] = link_key[15]; + + HCI_Command(hcibuf, 25); +} + void BTD::hci_link_key_request_negative_reply() { hcibuf[0] = 0x0C; // HCI OCF = 0C hcibuf[1] = 0x01 << 2; // HCI OGF = 1 diff --git a/BTD.h b/BTD.h index a070cb58..a9e6e72f 100644 --- a/BTD.h +++ b/BTD.h @@ -20,6 +20,7 @@ #include "Usb.h" #include "usbhid.h" +#include //PID and VID of the Sony PS3 devices #define PS3_VID 0x054C // Sony Corporation @@ -372,6 +373,8 @@ public: void hci_pin_code_request_reply(); /** Respons when no pin was set. */ void hci_pin_code_negative_request_reply(); + /** Used when we have already been paired, we will use the key in eeprom */ + void hci_link_key_request_reply(); /** * Command is used to reply to a Link Key Request event from the BR/EDR Controller * if the Host does not have a stored Link Key for the connection. @@ -486,6 +489,10 @@ public: uint8_t disc_bdaddr[6]; /** First 30 chars of last remote name. */ char remote_name[30]; + /** Link key **/ + uint8_t link_key[16]; + /** Stored Bluetooth address. */ + uint8_t stored_bdaddr[6]; /** * The supported HCI Version read from the Bluetooth dongle. * Used by the PS3BT library to check the HCI Version of the Bluetooth dongle, @@ -509,6 +516,9 @@ public: /** True if it's a Wii U Pro Controller. */ bool wiiUProController; + /** True if an Xbox One S Controller is Connecting. */ + bool incomingXboxOneS; + /** Call this function to pair with a HID device */ void pairWithHID() { waitingForConnection = false; @@ -521,6 +531,8 @@ public: bool incomingHIDDevice; /** True when it should pair with a device like a mouse or keyboard. */ bool pairWithHIDDevice; + /** True when the device is paired. */ + bool pairedDevice; /** * Read the poll interval taken from the endpoint descriptors.