Support to pair PS3 if it knows the BTADDR and user presses select and PS button and plugged in USB. Remembers remote name, and tries to get it when PAIR version of code is running. (Currently fails). Does some mapping of PS3 Bluetooth data to match USB HID data. Warning: as part of debuggigng why joystickType value was changing, I changed the class to make it a function you call instead of just a member variable. Should mark it inline... I think I caught all of the places in example code that was accessing it. If we find we want ability for user probram to update it, should add another member to explicityly set it.main
const uint8_t *manufacturer() | const uint8_t *manufacturer() | ||||
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; } | { return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; } | ||||
const uint8_t *product() | const uint8_t *product() | ||||
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; } | |||||
{ return remote_name_; } | |||||
const uint8_t *serialNumber() | const uint8_t *serialNumber() | ||||
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; } | { return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; } | ||||
private: | private: | ||||
friend class BluetoothController; | friend class BluetoothController; | ||||
protected: | protected: | ||||
enum {SP_NEED_CONNECT=0x1, SP_PS3_IDS=0x2}; | enum {SP_NEED_CONNECT=0x1, SP_PS3_IDS=0x2}; | ||||
enum {REMOTE_NAME_SIZE=32}; | |||||
uint8_t special_process_required = 0; | uint8_t special_process_required = 0; | ||||
Device_t *btdevice = NULL; | Device_t *btdevice = NULL; | ||||
strbuf_t *btstrbuf = NULL; | |||||
uint8_t remote_name_[REMOTE_NAME_SIZE] = {0}; | |||||
}; | }; | ||||
bool setLEDs(uint8_t lr, uint8_t lg=0, uint8_t lb=0); // sets Leds, | bool setLEDs(uint8_t lr, uint8_t lg=0, uint8_t lb=0); // sets Leds, | ||||
enum { STANDARD_AXIS_COUNT = 10, ADDITIONAL_AXIS_COUNT = 54, TOTAL_AXIS_COUNT = (STANDARD_AXIS_COUNT+ADDITIONAL_AXIS_COUNT) }; | enum { STANDARD_AXIS_COUNT = 10, ADDITIONAL_AXIS_COUNT = 54, TOTAL_AXIS_COUNT = (STANDARD_AXIS_COUNT+ADDITIONAL_AXIS_COUNT) }; | ||||
typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE, XBOX360} joytype_t; | typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE, XBOX360} joytype_t; | ||||
joytype_t joystickType = UNKNOWN; | |||||
joytype_t joystickType() {return joystickType_;} | |||||
// PS3 pair function. hack, requires that it be connect4ed by USB and we have the address of the Bluetooth dongle... | |||||
bool PS3Pair(uint8_t* bdaddr); | |||||
protected: | protected: | ||||
virtual bool remoteNameComplete(const uint8_t *remoteName); | virtual bool remoteNameComplete(const uint8_t *remoteName); | ||||
virtual void connectionComplete(void); | virtual void connectionComplete(void); | ||||
joytype_t joystickType_ = UNKNOWN; | |||||
private: | private: | ||||
// Class specific | // Class specific |
USBHDBGSerial.printf("Bluetooth Disconnect"); | USBHDBGSerial.printf("Bluetooth Disconnect"); | ||||
if (device_driver_) { | if (device_driver_) { | ||||
device_driver_->release_bluetooth(); | device_driver_->release_bluetooth(); | ||||
device_driver_->remote_name_[0] = 0; | |||||
device_driver_ = nullptr; | device_driver_ = nullptr; | ||||
} | } | ||||
connection_complete_ = false; | connection_complete_ = false; | ||||
break; | break; | ||||
case HCI_WRITE_SCAN_ENABLE: //0x0c1a | case HCI_WRITE_SCAN_ENABLE: //0x0c1a | ||||
DBGPrintf("Write_Scan_enable Completed\n"); | DBGPrintf("Write_Scan_enable Completed\n"); | ||||
// 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 | ||||
device_driver_->connectionComplete(); | |||||
connection_complete_ = false; // only call once | |||||
// 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(); | |||||
} | |||||
} | } | ||||
break; | break; | ||||
case HCI_WRITE_SSP_MODE: //0x0c56 | case HCI_WRITE_SSP_MODE: //0x0c56 | ||||
rxbuf_[3]+(rxbuf_[4]<<8), rxbuf_[5]); | rxbuf_[3]+(rxbuf_[4]<<8), rxbuf_[5]); | ||||
if (device_driver_) { | if (device_driver_) { | ||||
device_driver_->release_bluetooth(); | device_driver_->release_bluetooth(); | ||||
device_driver_->remote_name_[0] = 0; | |||||
device_driver_ = nullptr; | device_driver_ = nullptr; | ||||
// Restore to normal... | // Restore to normal... | ||||
device_connection_handle_ = 0; | device_connection_handle_ = 0; | ||||
device_class_ = 0; | device_class_ = 0; | ||||
memset(device_bdaddr_, 0, sizeof(device_bdaddr_)); | memset(device_bdaddr_, 0, sizeof(device_bdaddr_)); | ||||
//... | |||||
} | } | ||||
void BluetoothController::handle_hci_authentication_complete() | void BluetoothController::handle_hci_authentication_complete() | ||||
sendl2cap_ConnectionRequest(device_connection_handle_, connection_rxid_, control_dcid_, HID_CTRL_PSM); | sendl2cap_ConnectionRequest(device_connection_handle_, connection_rxid_, control_dcid_, HID_CTRL_PSM); | ||||
} | } | ||||
void BluetoothController::handle_hci_remote_name_complete() { | void BluetoothController::handle_hci_remote_name_complete() { | ||||
// STAT bd bd bd bd bd bd | // STAT bd bd bd bd bd bd | ||||
// 0x07 0xFF 0x00 0x79 0x22 0x23 0x0A 0xC5 0xCC 0x42 0x6C 0x75 0x65 0x74 0x6F 0x6F ... | // 0x07 0xFF 0x00 0x79 0x22 0x23 0x0A 0xC5 0xCC 0x42 0x6C 0x75 0x65 0x74 0x6F 0x6F ... | ||||
for (uint8_t *psz = &rxbuf_[9]; *psz; psz++) DBGPrintf("%c", *psz); | for (uint8_t *psz = &rxbuf_[9]; *psz; psz++) DBGPrintf("%c", *psz); | ||||
DBGPrintf("\n"); | DBGPrintf("\n"); | ||||
} | } | ||||
// Lets try to allocate a string buffer to store the name out... | |||||
if (device_driver_) { | if (device_driver_) { | ||||
if (!device_driver_->remoteNameComplete(&rxbuf_[9])) { | if (!device_driver_->remoteNameComplete(&rxbuf_[9])) { | ||||
device_driver_->release_bluetooth(); | device_driver_->release_bluetooth(); | ||||
if (!device_driver_) { | if (!device_driver_) { | ||||
device_driver_ = find_driver(device_class_, &rxbuf_[9]); | device_driver_ = find_driver(device_class_, &rxbuf_[9]); | ||||
// not sure I should call remote name again, but they already process... | // not sure I should call remote name again, but they already process... | ||||
if (device_driver_) { | |||||
device_driver_->remoteNameComplete(&rxbuf_[9]); | |||||
} | |||||
} | } | ||||
if (device_driver_) { | if (device_driver_) { | ||||
// lets allocate a string object | |||||
uint8_t 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]; | |||||
if (!device_driver_->remote_name_[buffer_index]) break; | |||||
} | |||||
device_driver_->remote_name_[buffer_index] = 0; // make sure null terminated | |||||
if (device_driver_->special_process_required & BTHIDInput::SP_PS3_IDS) { | if (device_driver_->special_process_required & BTHIDInput::SP_PS3_IDS) { | ||||
// Real hack see if PS3... | // Real hack see if PS3... | ||||
control_dcid_ = 0x40; | control_dcid_ = 0x40; | ||||
} | } | ||||
} | } | ||||
// Lets now try to accept the connection. | |||||
sendHCIAcceptConnectionRequest(); | |||||
// If we are in the connection complete mode, then this is a pairing state and needed to call | |||||
// get remote name later. | |||||
if (connection_complete_) { | |||||
if (device_driver_) { // We have a driver call their | |||||
device_driver_->connectionComplete(); | |||||
connection_complete_ = false; // only call once | |||||
} | |||||
} else { | |||||
sendHCIAcceptConnectionRequest(); | |||||
} | |||||
} | } | ||||
void BluetoothController::handle_hci_remote_version_information_complete() { | void BluetoothController::handle_hci_remote_version_information_complete() { |
} | } | ||||
uint8_t ltv; | uint8_t ltv; | ||||
uint8_t rtv; | uint8_t rtv; | ||||
switch (joysticks[joystick_index].joystickType) { | |||||
switch (joysticks[joystick_index].joystickType()) { | |||||
default: | default: | ||||
break; | break; | ||||
case JoystickController::PS4: | case JoystickController::PS4: | ||||
break; | break; | ||||
} | } | ||||
if (buttons != buttons_prev) { | if (buttons != buttons_prev) { | ||||
if (joysticks[joystick_index].joystickType == JoystickController::PS3) { | |||||
if (joysticks[joystick_index].joystickType() == JoystickController::PS3) { | |||||
joysticks[joystick_index].setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | joysticks[joystick_index].setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | ||||
} else { | } else { | ||||
uint8_t lr = (buttons & 1) ? 0xff : 0; | uint8_t lr = (buttons & 1) ? 0xff : 0; |
//BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | //BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | ||||
BluetoothController bluet(myusb); // version assumes it already was paired | BluetoothController bluet(myusb); // version assumes it already was paired | ||||
int user_axis[64]; | int user_axis[64]; | ||||
uint16_t buttons_prev = 0; | |||||
uint16_t buttons; | |||||
uint32_t buttons_prev = 0; | |||||
uint32_t buttons; | |||||
RawHIDController rawhid1(myusb); | RawHIDController rawhid1(myusb); | ||||
RawHIDController rawhid2(myusb, 0xffc90004); | RawHIDController rawhid2(myusb, 0xffc90004); | ||||
bool hid_driver_active[CNT_DEVICES] = {false, false, false}; | bool hid_driver_active[CNT_DEVICES] = {false, false, false}; | ||||
bool show_changed_only = false; | bool show_changed_only = false; | ||||
bool show_raw_data = false; | bool show_raw_data = false; | ||||
bool show_changed_data = false; | |||||
uint8_t joystick_left_trigger_value = 0; | uint8_t joystick_left_trigger_value = 0; | ||||
uint8_t joystick_right_trigger_value = 0; | uint8_t joystick_right_trigger_value = 0; | ||||
int psAxis[64]; | int psAxis[64]; | ||||
bool first_joystick_message = true; | bool first_joystick_message = true; | ||||
uint8_t last_bdaddr[6]={0,0,0,0,0,0}; | |||||
void setup() | void setup() | ||||
{ | { | ||||
if (psz && *psz) Serial.printf(" product: %s\n", psz); | if (psz && *psz) Serial.printf(" product: %s\n", psz); | ||||
psz = drivers[i]->serialNumber(); | psz = drivers[i]->serialNumber(); | ||||
if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | ||||
if (drivers[i] == &bluet) { | |||||
const uint8_t *bdaddr = bluet.myBDAddr(); | |||||
// remember it... | |||||
Serial.printf(" BDADDR: %x:%x:%x:%x:%x:%x\n", bdaddr[0], bdaddr[1], bdaddr[2], bdaddr[3], bdaddr[4], bdaddr[5]); | |||||
for (uint8_t i=0;i<6;i++) last_bdaddr[i] = bdaddr[i]; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
psz = joystick1.product(); | psz = joystick1.product(); | ||||
if (psz && *psz) Serial.printf(" product: %s\n", psz); | if (psz && *psz) Serial.printf(" product: %s\n", psz); | ||||
psz =joystick1.serialNumber(); | psz =joystick1.serialNumber(); | ||||
if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||||
if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||||
// lets try to reduce number of fields that update | |||||
joystick1.axisChangeNotifyMask(0xFFFFFl); | |||||
} | } | ||||
for (uint8_t i = 0; i<64; i++) { | for (uint8_t i = 0; i<64; i++) { | ||||
psAxis[i] = joystick1.getAxis(i); | psAxis[i] = joystick1.getAxis(i); | ||||
} | } | ||||
switch (joystick1.joystickType) { | |||||
switch (joystick1.joystickType()) { | |||||
/* | |||||
case JoystickController::UNKNOWN: | case JoystickController::UNKNOWN: | ||||
case JoystickController::PS4: | case JoystickController::PS4: | ||||
displayPS4Data(); | displayPS4Data(); | ||||
break; | break; | ||||
*/ | |||||
case JoystickController::PS3: | case JoystickController::PS3: | ||||
displayPS3Data(); | displayPS3Data(); | ||||
break; | break; | ||||
default: | |||||
case JoystickController::XBOXONE: | case JoystickController::XBOXONE: | ||||
case JoystickController::XBOX360:; | case JoystickController::XBOX360:; | ||||
displayRawData(); | displayRawData(); | ||||
void displayPS3Data() | void displayPS3Data() | ||||
{ | { | ||||
buttons = psAxis[2] | ((uint16_t)psAxis[3] << 8); | |||||
buttons = joystick1.getButtons(); | |||||
//buttons = psAxis[2] | ((uint16_t)psAxis[3] << 8); | |||||
// Use L3 (Left joystick button) to toggle Show Raw or not... | // Use L3 (Left joystick button) to toggle Show Raw or not... | ||||
if ((buttons & 0x02) && !(buttons_prev & 0x02)) show_raw_data = !show_raw_data; | if ((buttons & 0x02) && !(buttons_prev & 0x02)) show_raw_data = !show_raw_data; | ||||
if ((buttons & 0x04) && !(buttons_prev & 0x04)) show_changed_data = !show_changed_data; | |||||
// See about maybe pair... | |||||
if ((buttons & 0x10000) && !(buttons_prev & 0x10000) && (buttons & 0x0001)) { | |||||
// PS button just pressed and select button pressed act like PS4 share like... | |||||
Serial.print("\nPS3 Pairing Request"); | |||||
if (!last_bdaddr[0] && !last_bdaddr[1] && !last_bdaddr[2] && !last_bdaddr[3] && !last_bdaddr[4] && !last_bdaddr[5]) { | |||||
Serial.println(" - failed - no Bluetooth adapter has been plugged in"); | |||||
} else if (!hiddrivers[0]) { // Kludge see if we are connected as HID? | |||||
Serial.println(" - failed - PS3 device not plugged into USB"); | |||||
} else { | |||||
Serial.printf(" - Attempt pair to: %x:%x:%x:%x:%x:%x\n", last_bdaddr[0], last_bdaddr[1], last_bdaddr[2], last_bdaddr[3], last_bdaddr[4], last_bdaddr[5]); | |||||
if (! joystick1.PS3Pair(last_bdaddr)) { | |||||
Serial.println(" Pairing call Failed"); | |||||
} else { | |||||
Serial.println(" Pairing complete (I hope), make sure Bluetooth adapter is plugged in and try PS3 without USB"); | |||||
} | |||||
} | |||||
} | |||||
if (show_raw_data) { | if (show_raw_data) { | ||||
displayRawData(); | displayRawData(); | ||||
} else { | } else { | ||||
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[6], psAxis[7], psAxis[8], psAxis[9]); | |||||
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[0], psAxis[1], psAxis[2], psAxis[5]); | |||||
Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[18], psAxis[19]); | Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[18], psAxis[19]); | ||||
Serial.printf("Buttons: %x\r\n", buttons); | Serial.printf("Buttons: %x\r\n", buttons); | ||||
} | } | ||||
uint64_t changed_mask = joystick1.axisChangedMask(); | uint64_t changed_mask = joystick1.axisChangedMask(); | ||||
if (!changed_mask) return; | if (!changed_mask) return; | ||||
Serial.printf("%lx %lx:", axis_mask, changed_mask); | |||||
for (uint16_t index=0; axis_mask; index++) { | |||||
Serial.printf("%02x ", psAxis[index]); | |||||
axis_mask >>= 1; | |||||
if (show_changed_data) { | |||||
if (!changed_mask) return; | |||||
changed_mask &= 0xfffffffffL; // try reducing which ones show... | |||||
Serial.printf("%0x - ", joystick1.getButtons()); | |||||
for (uint16_t index=0; changed_mask; index++) { | |||||
if (changed_mask & 1) { | |||||
Serial.printf("%d:%02x ", index, psAxis[index]); | |||||
} | |||||
changed_mask >>= 1; | |||||
} | |||||
} else { | |||||
axis_mask &= 0xffffff; | |||||
Serial.printf("%06x%06x: %06x - ", (uint32_t)(changed_mask >> 32), (uint32_t)(changed_mask & 0xffffffff), joystick1.getButtons()); | |||||
for (uint16_t index=0; axis_mask; index++) { | |||||
Serial.printf("%02x ", psAxis[index]); | |||||
axis_mask >>= 1; | |||||
} | |||||
} | } | ||||
Serial.println(); | |||||
//for (uint8_t i = 0; i < 24; i++) { | |||||
// Serial.printf(" %d:%d", i, psAxis[i]); | |||||
//} | |||||
//Serial.println(); | |||||
Serial.println(); | |||||
} | } | ||||
} | } | ||||
uint8_t ltv; | uint8_t ltv; | ||||
uint8_t rtv; | uint8_t rtv; | ||||
switch (joystick1.joystickType) { | |||||
switch (joystick1.joystickType()) { | |||||
default: | default: | ||||
break; | break; | ||||
case JoystickController::PS4: | case JoystickController::PS4: | ||||
break; | break; | ||||
} | } | ||||
if (buttons != buttons_prev) { | if (buttons != buttons_prev) { | ||||
if (joystick1.joystickType == JoystickController::PS3) { | |||||
if (joystick1.joystickType() == JoystickController::PS3) { | |||||
joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | ||||
} else { | } else { | ||||
uint8_t lr = (buttons & 1) ? 0xff : 0; | uint8_t lr = (buttons & 1) ? 0xff : 0; |
} | } | ||||
uint8_t ltv; | uint8_t ltv; | ||||
uint8_t rtv; | uint8_t rtv; | ||||
switch (joystick1.joystickType) { | |||||
switch (joystick1.joystickType()) { | |||||
default: | default: | ||||
break; | break; | ||||
case JoystickController::PS4: | case JoystickController::PS4: | ||||
break; | break; | ||||
} | } | ||||
if (buttons != buttons_prev) { | if (buttons != buttons_prev) { | ||||
if (joystick1.joystickType == JoystickController::PS3) { | |||||
if (joystick1.joystickType() == JoystickController::PS3) { | |||||
joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | ||||
} else { | } else { | ||||
uint8_t lr = (buttons & 1) ? 0xff : 0; | uint8_t lr = (buttons & 1) ? 0xff : 0; |
{ | { | ||||
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | ||||
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | ||||
if (btdevice != nullptr) return remote_name_; | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
rumble_rValue_ = rValue; | rumble_rValue_ = rValue; | ||||
rumble_timeout_ = timeout; | rumble_timeout_ = timeout; | ||||
switch (joystickType) { | |||||
switch (joystickType_) { | |||||
default: | default: | ||||
break; | break; | ||||
case PS3: | case PS3: | ||||
leds_[1] = lg; | leds_[1] = lg; | ||||
leds_[2] = lb; | leds_[2] = lb; | ||||
switch (joystickType) { | |||||
switch (joystickType_) { | |||||
case PS3: | case PS3: | ||||
return transmitPS3UserFeedbackMsg(); | return transmitPS3UserFeedbackMsg(); | ||||
case PS4: | case PS4: | ||||
connected_ = true; // remember that hardware is actually connected... | connected_ = true; // remember that hardware is actually connected... | ||||
// Lets see if we know what type of joystick this is. That is, is it a PS3 or PS4 or ... | // Lets see if we know what type of joystick this is. That is, is it a PS3 or PS4 or ... | ||||
joystickType = mapVIDPIDtoJoystickType(mydevice->idVendor, mydevice->idProduct, false); | |||||
switch (joystickType) { | |||||
joystickType_ = mapVIDPIDtoJoystickType(mydevice->idVendor, mydevice->idProduct, false); | |||||
DBGPrintf("JoystickController::claim_collection joystickType_=%d\n", joystickType_); | |||||
switch (joystickType_) { | |||||
case PS3: | case PS3: | ||||
additional_axis_usage_page_ = 0x1; | additional_axis_usage_page_ = 0x1; | ||||
additional_axis_usage_start_ = 0x100; | additional_axis_usage_start_ = 0x100; | ||||
connected_ = 0; // remember that hardware is actually connected... | connected_ = 0; // remember that hardware is actually connected... | ||||
} | } | ||||
memset(axis, 0, sizeof(axis)); // clear out any data. | memset(axis, 0, sizeof(axis)); // clear out any data. | ||||
joystickType = jtype; // remember we are an XBox One. | |||||
joystickType_ = jtype; // remember we are an XBox One. | |||||
DBGPrintf(" JoystickController::claim joystickType_ %d\n", joystickType_); | |||||
return true; | return true; | ||||
} | } | ||||
print("JoystickController::rx_data: "); | print("JoystickController::rx_data: "); | ||||
print_hexbytes((uint8_t*)transfer->buffer, transfer->length); | print_hexbytes((uint8_t*)transfer->buffer, transfer->length); | ||||
if (joystickType == XBOXONE) { | |||||
if (joystickType_ == XBOXONE) { | |||||
// Process XBOX One data | // Process XBOX One data | ||||
axis_mask_ = 0x3f; | axis_mask_ = 0x3f; | ||||
axis_changed_mask_ = 0; // assume none for now | axis_changed_mask_ = 0; // assume none for now | ||||
joystickEvent = true; | joystickEvent = true; | ||||
} | } | ||||
} else if (joystickType == XBOX360) { | |||||
} else if (joystickType_ == XBOX360) { | |||||
// First byte appears to status - if the byte is 0x8 it is a connect or disconnect of the controller. | // First byte appears to status - if the byte is 0x8 it is a connect or disconnect of the controller. | ||||
xbox360data_t *xb360d = (xbox360data_t *)transfer->buffer; | xbox360data_t *xb360d = (xbox360data_t *)transfer->buffer; | ||||
if (xb360d->state == 0x08) { | if (xb360d->state == 0x08) { | ||||
btdriver_ = driver; | btdriver_ = driver; | ||||
btdevice = (Device_t*)driver; // remember this way | btdevice = (Device_t*)driver; // remember this way | ||||
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS. | special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS. | ||||
joystickType = PS3; | |||||
joystickType_ = PS3; | |||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
//print(" Joystick Data: "); | //print(" Joystick Data: "); | ||||
//print_hexbytes(data, length); | //print_hexbytes(data, length); | ||||
// DBGPrintf(" Joystick Data: "); | // DBGPrintf(" Joystick Data: "); | ||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0; | |||||
axis_changed_mask_ = 0; | |||||
if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays... | if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays... | ||||
for (uint16_t i = 0; i < length; i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(data[i] != axis[i]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
// DBGPrintf("%02x ", axis[i]); | |||||
if (joystickType_ == PS3) { | |||||
// Quick and dirty hack to match PS3 HID data | |||||
uint32_t cur_buttons = data[2] | ((uint16_t)data[3] << 8) | ((uint32_t)data[4] << 16); | |||||
if (cur_buttons != buttons) { | |||||
buttons = cur_buttons; | |||||
joystickEvent = true; // something changed. | |||||
} | |||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0x27; // assume bits 0, 1, 2, 5 | |||||
for (uint16_t i = 0; i < 3; i++) { | |||||
if (axis[i] != data[i+6]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i+6]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
} | |||||
if (axis[5] != data[9]) { | |||||
axis_changed_mask_ |= (1<<5); | |||||
axis[5] = data[9]; | |||||
} | |||||
// Then rest of data | |||||
mask = 0x1 << 10; // setup for other bits | |||||
for (uint16_t i = 10; i < length; i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(data[i] != axis[i]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
} | |||||
} else { | |||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0; | |||||
for (uint16_t i = 0; i < length; i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(data[i] != axis[i]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
// DBGPrintf("%02x ", axis[i]); | |||||
} | |||||
} | } | ||||
// DBGPrintf("\n"); | |||||
joystickEvent = true; | |||||
if (axis_changed_mask_ & axis_change_notify_mask_) | |||||
joystickEvent = true; | |||||
connected_ = true; | connected_ = true; | ||||
return true; | return true; | ||||
} else if(data[0] == 0x11){ | } else if(data[0] == 0x11){ | ||||
DBGPrintf(" Joystick Data: "); | DBGPrintf(" Joystick Data: "); | ||||
uint64_t mask = 0x1; | uint64_t mask = 0x1; | ||||
uint8_t tmp_data[length-2]; | uint8_t tmp_data[length-2]; | ||||
for (uint16_t i = 0; i < (length-2); i++ ) { | for (uint16_t i = 0; i < (length-2); i++ ) { | ||||
tmp_data[i] = data[i+2]; | tmp_data[i] = data[i+2]; | ||||
DBGPrintf("%02x ",tmp_data[i]); | |||||
} | } | ||||
DBGPrintf("\n"); | |||||
/* | /* | ||||
* [1] LX, [2] = LY, [3] = RX, [4] = RY | * [1] LX, [2] = LY, [3] = RX, [4] = RY | ||||
* [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3 | * [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3 | ||||
axis[i] = tmp_data[i]; | axis[i] = tmp_data[i]; | ||||
} | } | ||||
mask <<= 1; // shift down the mask. | mask <<= 1; // shift down the mask. | ||||
DBGPrintf("%02x ", axis[i]); | |||||
//DBGPrintf("%02x ", axis[i]); | |||||
} | } | ||||
DBGPrintf("\n"); | |||||
//DBGPrintf("\n"); | |||||
joystickEvent = true; | joystickEvent = true; | ||||
connected_ = true; | connected_ = true; | ||||
} | } | ||||
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); | DBGPrintf(" JoystickController::remoteNameComplete %s - set to PS4\n", remoteName); | ||||
special_process_required = SP_NEED_CONNECT; // We need to force this. | special_process_required = SP_NEED_CONNECT; // We need to force this. | ||||
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 %s - set to PS3\n", remoteName); | |||||
DBGPrintf(" JoystickController::remoteNameComplete %x %s - set to PS3\n", (uint32_t)this, remoteName); | |||||
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS. | special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS. | ||||
joystickType = PS3; | |||||
joystickType_ = PS3; | |||||
} else { | } else { | ||||
DBGPrintf(" JoystickController::remoteNameComplete %s - Unknown\n", remoteName); | DBGPrintf(" JoystickController::remoteNameComplete %s - Unknown\n", remoteName); | ||||
} | } | ||||
DBGPrintf(" Joystick Type: %d\n", joystickType_); | |||||
return true; | return true; | ||||
} | } | ||||
void JoystickController::connectionComplete() | void JoystickController::connectionComplete() | ||||
{ | { | ||||
DBGPrintf(" JoystickController::connectionComplete joystick type %d\n", joystickType); | |||||
if (joystickType == PS4) { | |||||
DBGPrintf(" JoystickController::connectionComplete %x joystick type %d\n", (uint32_t)this, joystickType_); | |||||
if (joystickType_ == PS4) { | |||||
uint8_t packet[2]; | uint8_t packet[2]; | ||||
packet[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03) | packet[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03) | ||||
packet[1] = 0x02; // Report ID | packet[1] = 0x02; // Report ID | ||||
delay(1); | delay(1); | ||||
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40); | btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40); | ||||
} else if (joystickType == PS3) { | |||||
} else if (joystickType_ == PS3) { | |||||
uint8_t packet[6]; | uint8_t packet[6]; | ||||
packet[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) | packet[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) | ||||
packet[1] = 0xF4; // Report ID | packet[1] = 0xF4; // Report ID | ||||
} | } | ||||
bool JoystickController::PS3Pair(uint8_t* bdaddr) { | |||||
if ((joystickType_ != PS3) || !driver_) return false; // not a PS2 nor plugged into USB... | |||||
/* Set the internal Bluetooth address */ | |||||
txbuf_[0] = 0x01; | |||||
txbuf_[1] = 0x00; | |||||
for(uint8_t i = 0; i < 6; i++) | |||||
txbuf_[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first | |||||
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data | |||||
return driver_->sendControlPacket(0x21, 9, 0x3f5, 0, 8, txbuf_); | |||||
} |