Browse Source

WIP - Start PS3 support

I have some PS3 support working... Hope I did not break PS4.... ;)

Also This assumes that you did a bind of the dongle to PS3 external, no support yet, I did this on RPI3...

Rumble needs work!
main
Kurt Eckhardt 5 years ago
parent
commit
9e3621f111
4 changed files with 278 additions and 110 deletions
  1. +19
    -13
      USBHost_t36.h
  2. +45
    -19
      bluetooth.cpp
  3. +119
    -44
      examples/JoystickBT/JoystickBT.ino
  4. +95
    -34
      joystick.cpp

+ 19
- 13
USBHost_t36.h View File

virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length) {return false;} virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length) {return false;}
virtual void release_bluetooth() {}; virtual void release_bluetooth() {};
virtual void remoteNameComplete(const uint8_t *remoteName) {}; virtual void remoteNameComplete(const uint8_t *remoteName) {};
virtual void connectionComplete(void) {};
void add_to_list(); void add_to_list();
BTHIDInput *next = NULL; BTHIDInput *next = NULL;
friend class BluetoothController; friend class BluetoothController;
protected: protected:
uint8_t needs_connect_to_device = false;
enum {SP_NEED_CONNECT=0x1, SP_PS3_IDS=0x2};
uint8_t special_process_required = 0;
Device_t *btdevice = NULL; Device_t *btdevice = NULL;


}; };
virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length); virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length);
virtual void release_bluetooth(); virtual void release_bluetooth();
virtual void remoteNameComplete(const uint8_t *remoteName); virtual void remoteNameComplete(const uint8_t *remoteName);
virtual void connectionComplete(void);


private: private:




class BluetoothController: public USBDriver { class BluetoothController: public USBDriver {
public: public:
BluetoothController(USBHost &host, bool pair = false, const char *pin = "0000") : do_pair_device_(pair), pair_pincode_(pin)
BluetoothController(USBHost &host, bool pair = false, const char *pin = "0000") : do_pair_device_(pair), pair_pincode_(pin), delayTimer_(this)
{ init(); } { init(); }


enum {MAX_ENDPOINTS=4, NUM_SERVICES=4, }; // Max number of Bluetooth services - if you need more than 4 simply increase this number enum {MAX_ENDPOINTS=4, NUM_SERVICES=4, }; // Max number of Bluetooth services - if you need more than 4 simply increase this number
const uint8_t* myBDAddr(void) {return my_bdaddr_;} const uint8_t* myBDAddr(void) {return my_bdaddr_;}


// BUGBUG version to allow some of the controlled objects to call? // BUGBUG version to allow some of the controlled objects to call?

void sendL2CapCommand(uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00) {
USBHDBGSerial.printf("sendL2CapCommand: %x %d %x %x : control: %x\n", (uint32_t)data, nbytes, channelLow, channelHigh, control_scid_);
sendL2CapCommand (device_connection_handle_, data, nbytes, channelLow, channelHigh);
}
enum {CONTROL_SCID=-1};
void sendL2CapCommand(uint8_t* data, uint8_t nbytes, int channel = (int)0x0001);


protected: protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
virtual void control(const Transfer_t *transfer); virtual void control(const Transfer_t *transfer);
virtual void disconnect(); virtual void disconnect();
//virtual void timer_event(USBDriverTimer *whichTimer);
virtual void timer_event(USBDriverTimer *whichTimer);


BTHIDInput * find_driver(uint32_t device_type); BTHIDInput * find_driver(uint32_t device_type);

// Hack to allow PS3 to maybe change values
uint16_t connection_rxid_ = 0;
uint16_t control_dcid_ = 0x70;
uint16_t interrupt_dcid_ = 0x71;
uint16_t interrupt_scid_;
uint16_t control_scid_;


private: private:
friend class BTHIDInput; friend class BTHIDInput;
static void rx_callback(const Transfer_t *transfer); static void rx_callback(const Transfer_t *transfer);


bool do_pair_device_; // Should we do a pair for a new device? bool do_pair_device_; // Should we do a pair for a new device?
const char *pair_pincode_; // What pin code to use for the pairing const char *pair_pincode_; // What pin code to use for the pairing
USBDriverTimer delayTimer_;
uint8_t my_bdaddr_[6]; // The bluetooth dongles Bluetooth address. uint8_t my_bdaddr_[6]; // The bluetooth dongles Bluetooth address.
uint8_t features[8]; // remember our local features. uint8_t features[8]; // remember our local features.
BTHIDInput * device_driver_ = nullptr;; BTHIDInput * device_driver_ = nullptr;;
uint8_t device_clock_offset_[2]; uint8_t device_clock_offset_[2];
uint32_t device_class_; // class of device. uint32_t device_class_; // class of device.
uint16_t device_connection_handle_; // handle to connection uint16_t device_connection_handle_; // handle to connection
uint16_t connection_rxid_ = 0;
uint16_t control_dcid_ = 0x70;
uint16_t interrupt_dcid_ = 0x71;
uint16_t interrupt_scid_;
uint16_t control_scid_;
uint8_t remote_ver_; uint8_t remote_ver_;
uint16_t remote_man_; uint16_t remote_man_;
uint8_t remote_subv_; uint8_t remote_subv_;
uint8_t connection_complete_ = false; //


typedef struct { typedef struct {
uint16_t idVendor; uint16_t idVendor;

+ 45
- 19
bluetooth.cpp View File

#define print USBHost::print_ #define print USBHost::print_
#define println USBHost::println_//#define DEBUG_BT #define println USBHost::println_//#define DEBUG_BT


#define DEBUG_BT
#define DEBUG_BT_VERBOSE
//#define DEBUG_BT
//#define DEBUG_BT_VERBOSE


#ifndef DEBUG_BT #ifndef DEBUG_BT
#undef DEBUG_BT_VERBOSE #undef DEBUG_BT_VERBOSE
void DBGPrintf(...) {};
void inline DBGPrintf(...) {};
#else #else
#define DBGPrintf USBHDBGSerial.printf #define DBGPrintf USBHDBGSerial.printf
#endif #endif


#ifndef DEBUG_BT_VERBOSE #ifndef DEBUG_BT_VERBOSE
void VDBGPrintf(...) {};
void inline VDBGPrintf(...) {};
#else #else
#define VDBGPrintf USBHDBGSerial.printf #define VDBGPrintf USBHDBGSerial.printf
#endif #endif
device_driver_->release_bluetooth(); device_driver_->release_bluetooth();
device_driver_ = nullptr; device_driver_ = nullptr;
} }
connection_complete_ = false;
} }


void BluetoothController::timer_event(USBDriverTimer *whichTimer)
{
}




void BluetoothController::control(const Transfer_t *transfer) void BluetoothController::control(const Transfer_t *transfer)
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");
if (device_connection_handle_) {
// Lets see if we can get the remote information
//sendHCIRemoteVersionInfoRequest();

if (device_driver_ && connection_complete_) { // We have a driver call their
device_driver_->connectionComplete();
connection_complete_ = false; // only call once
} }
break; break;
case HCI_WRITE_SSP_MODE: //0x0c56 case HCI_WRITE_SSP_MODE: //0x0c56
if (do_pair_device_) { if (do_pair_device_) {
sendHCIAuthenticationRequested(); sendHCIAuthenticationRequested();
pending_control_ = PC_AUTHENTICATION_REQUESTED; pending_control_ = PC_AUTHENTICATION_REQUESTED;
} else if (device_driver_ && device_driver_->needs_connect_to_device) {
} else if (device_driver_ && (device_driver_->special_process_required & BTHIDInput::SP_NEED_CONNECT)) {
DBGPrintf(" Needs connect to device(PS4?)\n"); DBGPrintf(" Needs connect to device(PS4?)\n");
// The PS4 requires a connection request to it. // The PS4 requires a connection request to it.
delay(1); delay(1);
packet[0] = 0x43; packet[0] = 0x43;
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, 0x00);
sendL2CapCommand(packet, sizeof(packet), 0x40);
} }
} }


if (device_driver_) { if (device_driver_) {
device_driver_->release_bluetooth(); device_driver_->release_bluetooth();
device_driver_ = nullptr; device_driver_ = nullptr;
// Restore to normal...
control_dcid_ = 0x70;
interrupt_dcid_ = 0x71;
} }
// Probably should clear out connection data. // Probably should clear out connection data.
device_connection_handle_ = 0; device_connection_handle_ = 0;
DBGPrintf("\n"); DBGPrintf("\n");
} }
if (device_driver_) { if (device_driver_) {
/*
if (!device_driver_->btstrbuf) {
device_driver_->btstrbuf = USBHost::allocate_string_buffer();
if (device_driver_->btstrbuf) {

}
}
*/
device_driver_->remoteNameComplete(&rxbuf_[9]); device_driver_->remoteNameComplete(&rxbuf_[9]);
if (device_driver_->special_process_required & BTHIDInput::SP_PS3_IDS) {
// Real hack see if PS3...
control_dcid_ = 0x40;
interrupt_dcid_ = 0x41;
}
} }


// Lets now try to accept the connection. // Lets now try to accept the connection.
/************************************************************/ /************************************************************/
/* L2CAP Commands */ /* L2CAP Commands */


// Public wrrapper function
void BluetoothController::sendL2CapCommand(uint8_t* data, uint8_t nbytes, int channel) {
uint16_t channel_out;
switch (channel) {
case CONTROL_SCID:
channel_out = control_scid_;
break;
default:
channel_out = (uint16_t)channel;
}
DBGPrintf("sendL2CapCommand: %x %d %x\n", (uint32_t)data, nbytes, channel, channel_out);
sendL2CapCommand (device_connection_handle_, data, nbytes, channel_out & 0xff, (channel_out >> 8) & 0xff);
}


void BluetoothController::sendL2CapCommand(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) void BluetoothController::sendL2CapCommand(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh)
{ {
txbuf_[0] = handle & 0xff; // HCI handle with PB,BC flag txbuf_[0] = handle & 0xff; // HCI handle with PB,BC flag
data[8]+((uint16_t)data[9] << 8), data[10]+((uint16_t)data[11] << 8)); data[8]+((uint16_t)data[9] << 8), data[10]+((uint16_t)data[11] << 8));
if (scid == control_dcid_) { if (scid == control_dcid_) {
// Set HID Boot mode // Set HID Boot mode
setHIDProtocol(HID_BOOT_PROTOCOL); //
// Don't do if PS3...
if (!(device_driver_->special_process_required & BTHIDInput::SP_PS3_IDS)) {
setHIDProtocol(HID_BOOT_PROTOCOL); //
}
//setHIDProtocol(HID_RPT_PROTOCOL); //HID_RPT_PROTOCOL //setHIDProtocol(HID_RPT_PROTOCOL); //HID_RPT_PROTOCOL
if (do_pair_device_) { if (do_pair_device_) {
pending_control_tx_ = STATE_TX_SEND_CONNECT_INT; pending_control_tx_ = STATE_TX_SEND_CONNECT_INT;
} else if (device_driver_ && device_driver_->needs_connect_to_device) {
} else if (device_driver_ && (device_driver_->special_process_required & BTHIDInput::SP_NEED_CONNECT)) {
DBGPrintf(" Needs connect to device INT(PS4?)\n"); DBGPrintf(" Needs connect to device INT(PS4?)\n");
// The PS4 requires a connection request to it. // The PS4 requires a connection request to it.
pending_control_tx_ = STATE_TX_SEND_CONNECT_INT; pending_control_tx_ = STATE_TX_SEND_CONNECT_INT;
} else if (scid == interrupt_dcid_) { } else if (scid == interrupt_dcid_) {
// Enable SCan to page mode // Enable SCan to page mode
sendHCIWriteScanEnable(2); sendHCIWriteScanEnable(2);
connection_complete_ = true;
} }
} }



+ 119
- 44
examples/JoystickBT/JoystickBT.ino View File

//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];
uint8_t buttons_prev = 0;
uint8_t button;
uint16_t buttons_prev = 0;
uint16_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;


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;
Serial4.println("\n" __FILE__ " " __DATE__ " " __TIME__); Serial4.println("\n" __FILE__ " " __DATE__ " " __TIME__);
Serial4.println("\n********\n T4 connected Serial4 *******\n"); Serial4.println("\n********\n T4 connected Serial4 *******\n");
*/ */
Serial1.begin(1843200);
Serial1.begin(2000000);
while (!Serial) ; // wait for Arduino Serial Monitor while (!Serial) ; // wait for Arduino Serial Monitor
//debTraceShow_tt( -2, "", "", "" ); //debTraceShow_tt( -2, "", "", "" );
//Serial4.println("\n" __FILE__ " " __DATE__ " " __TIME__); //Serial4.println("\n" __FILE__ " " __DATE__ " " __TIME__);
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) {
case JoystickController::UNKNOWN:
case JoystickController::PS4:
displayPS4Data();
break;
case JoystickController::PS3:
displayPS3Data();
break;
case JoystickController::XBOXONE:
case JoystickController::XBOX360:;
displayRawData();
break;
}
//for (uint8_t i = 0; i < 24; i++) { //for (uint8_t i = 0; i < 24; i++) {
// Serial.printf(" %d:%d", i, psAxis[i]); // Serial.printf(" %d:%d", i, psAxis[i]);
//} //}
//Serial.println(); //Serial.println();
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[1], psAxis[2], psAxis[3], psAxis[4]);
Serial.printf("L-Trig: %d, R-Trig: %d, Trig-Button: %d \r\n", psAxis[8], psAxis[9], psAxis[6]);
Serial.printf("Buttons: %d, PS: %d\r\n", psAxis[5], psAxis[7]);
Serial.printf("Arrows: %d\r\n", psAxis[0]);
Serial.printf("Battery level percentage: %2f.0 \r\n", (((float) psAxis[12])/255.0f)*100.0f);
Serial.println();

uint8_t ltv;
uint8_t rtv;

ltv = psAxis[8];
rtv = psAxis[9];

if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv;
Serial.printf("Rumbling: %d, %d\r\n", ltv, rtv);
joystick1.setRumble(ltv, rtv);
}
/* Arrow Buttons (psAxis[0]):
* 0x08 is released,
* 0=N, 1=NE, 2=E, 3=SE, 4=S,
* 5=SW, 6=W, 7=NW)
*/

if (psAxis[5] != buttons_prev) {
uint8_t lr = (psAxis[5] & 1) ? 0xff : 0; //Srq
uint8_t lg = (psAxis[5] & 4) ? 0xff : 0; //Cir
uint8_t lb = (psAxis[5] & 8) ? 0xff : 0; //Tri
//Cross = 2
Serial.print(psAxis[5]); Serial.print(", ");
Serial.print(lr); Serial.print(", ");
Serial.print(lg); Serial.print(", ");
Serial.println(lb);

joystick1.setLEDs(lr, lg, lb);
}
buttons_prev =psAxis[5];


joystick1.joystickDataClear(); joystick1.joystickDataClear();
} }
} }
} }


void displayPS4Data()
{
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[1], psAxis[2], psAxis[3], psAxis[4]);
Serial.printf("L-Trig: %d, R-Trig: %d, Trig-Button: %d \r\n", psAxis[8], psAxis[9], psAxis[6]);
Serial.printf("Buttons: %d, PS: %d\r\n", psAxis[5], psAxis[7]);
Serial.printf("Arrows: %d\r\n", psAxis[0]);
Serial.printf("Battery level percentage: %2f.0 \r\n", (((float) psAxis[12])/255.0f)*100.0f);

Serial.println();

uint8_t ltv;
uint8_t rtv;

ltv = psAxis[8];
rtv = psAxis[9];

if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv;
Serial.printf("Rumbling: %d, %d\r\n", ltv, rtv);
joystick1.setRumble(ltv, rtv);
}
/* Arrow Buttons (psAxis[0]):
* 0x08 is released,
* 0=N, 1=NE, 2=E, 3=SE, 4=S,
* 5=SW, 6=W, 7=NW)
*/

if (psAxis[5] != buttons_prev) {
uint8_t lr = (psAxis[5] & 1) ? 0xff : 0; //Srq
uint8_t lg = (psAxis[5] & 4) ? 0xff : 0; //Cir
uint8_t lb = (psAxis[5] & 8) ? 0xff : 0; //Tri
//Cross = 2
Serial.print(psAxis[5]); Serial.print(", ");
Serial.print(lr); Serial.print(", ");
Serial.print(lg); Serial.print(", ");
Serial.println(lb);

joystick1.setLEDs(lr, lg, lb);
buttons_prev =psAxis[5];
}
}

void displayPS3Data()

{
buttons = psAxis[2] | ((uint16_t)psAxis[3] << 8);

// Use L3 (Left joystick button) to toggle Show Raw or not...
if ((buttons & 0x02) && !(buttons_prev & 0x02)) show_raw_data = !show_raw_data;
if (show_raw_data) {
displayRawData();
} else {
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[6], psAxis[7], psAxis[8], psAxis[9]);
Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[18], psAxis[19]);
Serial.printf("Buttons: %x\r\n", buttons);
}
uint8_t ltv;
uint8_t rtv;

ltv = psAxis[18];
rtv = psAxis[19];

if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv;
Serial.printf("Rumbling: %d, %d\r\n", ltv, rtv);
joystick1.setRumble(ltv, rtv);
}

if (buttons != buttons_prev) {
uint8_t leds = 0;
if (buttons & 0x8000) leds = 1; //Srq
if (buttons & 0x2000) leds = 2; //Cir
if (buttons & 0x1000) leds = 3; //Tri
//Cross = 2
joystick1.setLEDs(leds);
buttons_prev = buttons;
}
}

void displayRawData() {
uint64_t axis_mask = joystick1.axisMask();
uint64_t changed_mask = joystick1.axisChangedMask();
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;
}
Serial.println();
//for (uint8_t i = 0; i < 24; i++) {
// Serial.printf(" %d:%d", i, psAxis[i]);
//}
//Serial.println();
}


bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) {
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy // Called for maybe both HIDS for rawhid basic test. One is for the Teensy
// to output to Serial. while still having Raw Hid... // to output to Serial. while still having Raw Hid...

+ 95
- 34
joystick.cpp View File

#define print USBHost::print_ #define print USBHost::print_
#define println USBHost::println_ #define println USBHost::println_


#define DEBUG_JOYSTICK
#ifdef DEBUG_JOYSTICK
#define DBGPrintf USBHDBGSerial.printf
#else
#define DBGPrintf(...)
#endif

// PID/VID to joystick mapping - Only the XBOXOne is used to claim the USB interface directly, // PID/VID to joystick mapping - Only the XBOXOne is used to claim the USB interface directly,
// The others are used after claim-hid code to know which one we have and to use it for // The others are used after claim-hid code to know which one we have and to use it for
// doing other features. // doing other features.
packet[7] = leds_[1]; packet[7] = leds_[1];
packet[8] = leds_[2]; packet[8] = leds_[2];
// 9, 10 flash ON, OFF times in 100ths of second? 2.5 seconds = 255 // 9, 10 flash ON, OFF times in 100ths of second? 2.5 seconds = 255
USBHDBGSerial.printf("Joystick update Rumble/LEDs\n");
DBGPrintf("Joystick update Rumble/LEDs\n");
return driver_->sendPacket(packet, 32); return driver_->sendPacket(packet, 32);
} else if (btdriver_) { } else if (btdriver_) {
uint8_t packet[79]; uint8_t packet[79];
packet[11] = leds_[2]; packet[11] = leds_[2];


// 12, 13 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 // 12, 13 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255
USBHDBGSerial.printf("Joystick update Rumble/LEDs\n");
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40, 0x00);
DBGPrintf("Joystick update Rumble/LEDs\n");
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40);


return true; return true;
} }
0x00, 0x00, 0x00 }; 0x00, 0x00, 0x00 };


bool JoystickController::transmitPS3UserFeedbackMsg() { bool JoystickController::transmitPS3UserFeedbackMsg() {
if (!driver_) return false;
memcpy(txbuf_, PS3_USER_FEEDBACK_INIT, 48);

txbuf_[1] = rumble_lValue_? rumble_timeout_ : 0;
txbuf_[2] = rumble_lValue_; // Small Rumble
txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0;
txbuf_[4] = rumble_rValue_; // Big rumble
txbuf_[9] = leds_[0] << 1; // RGB value
//USBHDBGSerial.printf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[1], txbuf_[2], txbuf_[3], txbuf_[4], txbuf_[9]);
return driver_->sendControlPacket(0x21, 9, 0x201, 0, 48, txbuf_);
if (driver_) {
memcpy(txbuf_, PS3_USER_FEEDBACK_INIT, 48);

txbuf_[1] = rumble_lValue_? rumble_timeout_ : 0;
txbuf_[2] = rumble_lValue_; // Small Rumble
txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0;
txbuf_[4] = rumble_rValue_; // Big rumble
txbuf_[9] = leds_[0] << 1; // RGB value
//DBGPrintf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[1], txbuf_[2], txbuf_[3], txbuf_[4], txbuf_[9]);
return driver_->sendControlPacket(0x21, 9, 0x201, 0, 48, txbuf_);
} else if (btdriver_) {
txbuf_[0] = 0x52;
txbuf_[1] = 0x1;
memcpy(&txbuf_[2], PS3_USER_FEEDBACK_INIT, 48);

txbuf_[3] = rumble_lValue_? rumble_timeout_ : 0;
txbuf_[4] = rumble_lValue_; // Small Rumble
txbuf_[5] = rumble_rValue_? rumble_timeout_ : 0;
txbuf_[6] = rumble_rValue_; // Big rumble
txbuf_[11] = leds_[0] << 1; // RGB value
DBGPrintf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[3], txbuf_[4], txbuf_[5], txbuf_[6], txbuf_[11]);
btdriver_->sendL2CapCommand(txbuf_, 50, BluetoothController::CONTROL_SCID);
return true;
}
return false;
} }


//***************************************************************************** //*****************************************************************************
additional_axis_usage_count_ = 0; additional_axis_usage_count_ = 0;
axis_change_notify_mask_ = 0x3ff; // Start off assume only the 10 bits... axis_change_notify_mask_ = 0x3ff; // Start off assume only the 10 bits...
} }
USBHDBGSerial.printf("Claim Additional axis: %x %x %d\n", additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_);
DBGPrintf("Claim Additional axis: %x %x %d\n", additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_);
return CLAIM_REPORT; return CLAIM_REPORT;
} }




void JoystickController::hid_input_data(uint32_t usage, int32_t value) void JoystickController::hid_input_data(uint32_t usage, int32_t value)
{ {
//USBHDBGSerial.printf("Joystick: usage=%X, value=%d\n", usage, value);
//DBGPrintf("Joystick: usage=%X, value=%d\n", usage, value);
uint32_t usage_page = usage >> 16; uint32_t usage_page = usage >> 16;
usage &= 0xFFFF; usage &= 0xFFFF;
if (usage_page == 9 && usage >= 1 && usage <= 32) { if (usage_page == 9 && usage >= 1 && usage <= 32) {
} }
} else if (usage_page == additional_axis_usage_page_) { } else if (usage_page == additional_axis_usage_page_) {
// see if the usage is witin range. // see if the usage is witin range.
//USBHDBGSerial.printf("UP: usage_page=%x usage=%x User: %x %d\n", usage_page, usage, user_buttons_usage_start, user_buttons_count_);
//DBGPrintf("UP: usage_page=%x usage=%x User: %x %d\n", usage_page, usage, user_buttons_usage_start, user_buttons_count_);
if ((usage >= additional_axis_usage_start_) && (usage < (additional_axis_usage_start_ + additional_axis_usage_count_))) { if ((usage >= additional_axis_usage_start_) && (usage < (additional_axis_usage_start_ + additional_axis_usage_count_))) {
// We are in the user range. // We are in the user range.
uint16_t usage_index = usage - additional_axis_usage_start_ + STANDARD_AXIS_COUNT; uint16_t usage_index = usage - additional_axis_usage_start_ + STANDARD_AXIS_COUNT;
} }
axis_mask_ |= ((uint64_t)1 << usage_index); // Keep record of which axis we have data on. axis_mask_ |= ((uint64_t)1 << usage_index); // Keep record of which axis we have data on.
} }
//USBHDBGSerial.printf("UB: index=%x value=%x\n", usage_index, value);
//DBGPrintf("UB: index=%x value=%x\n", usage_index, value);
} }


} else { } else {
USBHDBGSerial.printf("UP: usage_page=%x usage=%x add: %x %x %d\n", usage_page, usage, additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_);
DBGPrintf("UP: usage_page=%x usage=%x add: %x %x %d\n", usage_page, usage, additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_);


} }
// TODO: hat switch? // TODO: hat switch?


bool JoystickController::hid_process_out_data(const Transfer_t *transfer) bool JoystickController::hid_process_out_data(const Transfer_t *transfer)
{ {
//USBHDBGSerial.printf("JoystickController::hid_process_out_data\n");
//DBGPrintf("JoystickController::hid_process_out_data\n");
return true; return true;
} }


println("XBox360w - controllerStatus: ", xb360d->controller_status, HEX); println("XBox360w - controllerStatus: ", xb360d->controller_status, HEX);
} else if(xb360d->id_or_type == 0x01) { // Lets only process report 1. } else if(xb360d->id_or_type == 0x01) { // Lets only process report 1.
//const uint8_t *pbuffer = (uint8_t*)transfer->buffer; //const uint8_t *pbuffer = (uint8_t*)transfer->buffer;
//for (uint8_t i = 0; i < transfer->length; i++) USBHDBGSerial.printf("%02x ", pbuffer[i]);
//USBHDBGSerial.printf("\n");
//for (uint8_t i = 0; i < transfer->length; i++) DBGPrintf("%02x ", pbuffer[i]);
//DBGPrintf("\n");
if (buttons != xb360d->buttons) { if (buttons != xb360d->buttons) {
buttons = xb360d->buttons; buttons = xb360d->buttons;
bool JoystickController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class) bool JoystickController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class)
{ {
if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && ((bluetooth_class & 0x3C) == 0x08)) { if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && ((bluetooth_class & 0x3C) == 0x08)) {
USBHDBGSerial.printf("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
return true; return true;
// Example data from PS4 controller // Example data from PS4 controller
//01 7e 7f 82 84 08 00 00 00 00 //01 7e 7f 82 84 08 00 00 00 00
// LX LY RX RY BT BT PS LT RT // LX LY RX RY BT BT PS LT RT
//USBHDBGSerial.printf("JoystickController::process_bluetooth_HID_data\n");
//DBGPrintf("JoystickController::process_bluetooth_HID_data\n");
// May have to look at this one with other controllers... // May have to look at this one with other controllers...
if (data[0] == 1) { if (data[0] == 1) {
//print(" Joystick Data: "); //print(" Joystick Data: ");
//print_hexbytes(data, length); //print_hexbytes(data, length);
USBHDBGSerial.printf(" Joystick Data: ");
// DBGPrintf(" Joystick Data: ");
uint64_t mask = 0x1; uint64_t mask = 0x1;
axis_mask_ = 0; axis_mask_ = 0;
axis_changed_mask_ = 0; axis_changed_mask_ = 0;

if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays...
for (uint16_t i = 0; i < length; i++ ) { for (uint16_t i = 0; i < length; i++ ) {
axis_mask_ |= mask; axis_mask_ |= mask;
if(data[i] != axis[i]) { if(data[i] != axis[i]) {
axis[i] = data[i]; axis[i] = data[i];
} }
mask <<= 1; // shift down the mask. mask <<= 1; // shift down the mask.
USBHDBGSerial.printf("%02x ", axis[i]);
// DBGPrintf("%02x ", axis[i]);
} }
USBHDBGSerial.printf("\n");
// DBGPrintf("\n");
joystickEvent = true; joystickEvent = true;
connected_ = true; connected_ = true;
return true; return true;
} else if(data[0] == 0x11){ } else if(data[0] == 0x11){
USBHDBGSerial.printf(" Joystick Data: ");
DBGPrintf(" Joystick Data: ");
uint64_t mask = 0x1; uint64_t mask = 0x1;
axis_mask_ = 0; axis_mask_ = 0;
axis_changed_mask_ = 0; axis_changed_mask_ = 0;
//set arrow buttons to axis[0] //set arrow buttons to axis[0]
tmp_data[0] = tmp_data[5] & ((1 << 4) - 1); tmp_data[0] = tmp_data[5] & ((1 << 4) - 1);
//set buttons for last 4bits in the axis[5] //set buttons for last 4bits in the axis[5]
tmp_data[5] = tmp_data[5] >> 4;
tmp_data[5] = tmp_data[5] >> 4;

for (uint16_t i = 0; i < (length-2); i++ ) { for (uint16_t i = 0; i < (length-2); i++ ) {
if(tmp_data[i] != axis[i]) { if(tmp_data[i] != axis[i]) {
axis_changed_mask_ |= mask; axis_changed_mask_ |= mask;
axis[i] = tmp_data[i]; axis[i] = tmp_data[i];
} }
mask <<= 1; // shift down the mask. mask <<= 1; // shift down the mask.
USBHDBGSerial.printf("%02x ", axis[i]);
DBGPrintf("%02x ", axis[i]);
} }
USBHDBGSerial.printf("\n");
DBGPrintf("\n");
joystickEvent = true; joystickEvent = true;
connected_ = true; connected_ = true;
} }
if (!remoteName) return; if (!remoteName) return;


if (strncmp((const char *)remoteName, "Wireless Controller", 19) == 0) { if (strncmp((const char *)remoteName, "Wireless Controller", 19) == 0) {
USBHDBGSerial.printf(" JoystickController::remoteNameComplete %s - set to PS4\n", remoteName);
needs_connect_to_device = true; // We need to force this.
joystickType = PS4;
DBGPrintf(" JoystickController::remoteNameComplete %s - set to PS4\n", remoteName);
special_process_required = SP_NEED_CONNECT; // We need to force this.
joystickType = PS4;
} else if (strncmp((const char *)remoteName, "PLAYSTATION(R)3 Controller", 26) == 0) {
DBGPrintf(" JoystickController::remoteNameComplete %s - set to PS3\n", remoteName);
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS.
joystickType = PS3;

// Hack to see if setting control/interrupt ids will help on PS3...
// btdriver_->control_dcid_ = 0x40;
// btdriver_->interrupt_dcid_ = 0x41;

}

}

void JoystickController::connectionComplete()
{
DBGPrintf(" JoystickController::connectionComplete joystick type %d\n", joystickType);
if (joystickType == PS4) {
uint8_t packet[2];
packet[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)
packet[1] = 0x02; // Report ID
DBGPrintf("Set PS4 report\n");
delay(1);
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40);

} else if (joystickType == PS3) {
uint8_t packet[6];
packet[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
packet[1] = 0xF4; // Report ID
packet[2] = 0x42; // Special PS3 Controller enable commands
packet[3] = 0x03;
packet[4] = 0x00;
packet[5] = 0x00;

DBGPrintf("enable six axis\n");
delay(1);
btdriver_->sendL2CapCommand(packet, sizeof(packet), BluetoothController::CONTROL_SCID);
} }


} }
btdevice = nullptr; // remember this way btdevice = nullptr; // remember this way
btdriver_ = nullptr; btdriver_ = nullptr;
connected_ = false; connected_ = false;
needs_connect_to_device = false;
special_process_required = false;


} }



Loading…
Cancel
Save