Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xbox One S BT Controller patch so it can reconnect #624

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 114 additions & 5 deletions BTD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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<uint8_t > (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<uint8_t > (hcibuf[8 + i], 0x80);
}
#endif
}

break;

/* We will just ignore the following events */
case EV_MAX_SLOTS_CHANGE:
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand All @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions BTD.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "Usb.h"
#include "usbhid.h"
#include <EEPROM.h>

//PID and VID of the Sony PS3 devices
#define PS3_VID 0x054C // Sony Corporation
Expand Down Expand Up @@ -372,6 +373,8 @@ class BTD : public USBDeviceConfig, public UsbConfigXtracter {
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.
Expand Down Expand Up @@ -486,6 +489,10 @@ class BTD : public USBDeviceConfig, public UsbConfigXtracter {
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,
Expand All @@ -509,6 +516,9 @@ class BTD : public USBDeviceConfig, public UsbConfigXtracter {
/** 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;
Expand All @@ -521,6 +531,8 @@ class BTD : public USBDeviceConfig, public UsbConfigXtracter {
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.
Expand Down