Ps3 motion wip2 bluetoothmain
| @@ -58,7 +58,7 @@ | |||
| //#define USBHOST_PRINT_DEBUG | |||
| #define USBHDBGSerial Serial1 | |||
| //#define USBHDBGSerial Serial1 | |||
| #ifndef USBHDBGSerial | |||
| @@ -911,10 +911,11 @@ public: | |||
| // set functions functionality depends on underlying joystick. | |||
| bool setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeout=0xff); | |||
| // setLEDs on PS4(RGB), PS3 simple LED setting (only uses lr) | |||
| bool setLEDs(uint8_t lr, uint8_t lg=0, uint8_t lb=0); // sets Leds, | |||
| // setLEDs on PS4(RGB), PS3 simple LED setting (only uses lb) | |||
| bool setLEDs(uint8_t lr, uint8_t lg, uint8_t lb); // sets Leds, | |||
| bool inline setLEDs(uint32_t leds) {return setLEDs((leds >> 16) & 0xff, (leds >> 8) & 0xff, leds & 0xff);} // sets Leds - passing one arg for all leds | |||
| 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, PS3_MOTION} joytype_t; | |||
| 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... | |||
| @@ -954,6 +955,7 @@ private: | |||
| joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices); | |||
| bool transmitPS4UserFeedbackMsg(); | |||
| bool transmitPS3UserFeedbackMsg(); | |||
| bool transmitPS3MotionUserFeedbackMsg(); | |||
| bool mapNameToJoystickType(const uint8_t *remoteName); | |||
| bool anychange = false; | |||
| @@ -1685,7 +1687,7 @@ public: | |||
| const uint8_t* myBDAddr(void) {return my_bdaddr_;} | |||
| // BUGBUG version to allow some of the controlled objects to call? | |||
| enum {CONTROL_SCID=-1}; | |||
| enum {CONTROL_SCID=-1, INTERRUPT_SCID=-2}; | |||
| void sendL2CapCommand(uint8_t* data, uint8_t nbytes, int channel = (int)0x0001); | |||
| protected: | |||
| @@ -31,7 +31,7 @@ | |||
| #define println USBHost::println_//#define DEBUG_BT | |||
| //#define DEBUG_BT | |||
| #define DEBUG_BT_VERBOSE | |||
| //#define DEBUG_BT_VERBOSE | |||
| #ifndef DEBUG_BT | |||
| #undef DEBUG_BT_VERBOSE | |||
| @@ -1343,6 +1343,9 @@ void BluetoothController::sendL2CapCommand(uint8_t* data, uint8_t nbytes, int ch | |||
| case CONTROL_SCID: | |||
| channel_out = control_scid_; | |||
| break; | |||
| case INTERRUPT_SCID: | |||
| channel_out = interrupt_scid_; | |||
| break; | |||
| default: | |||
| channel_out = (uint16_t)channel; | |||
| } | |||
| @@ -745,21 +745,23 @@ bool USBHost::queue_Data_Transfer(Pipe_t *pipe, void *buffer, uint32_t len, USBD | |||
| transfer = allocate_Transfer(); | |||
| if (!transfer) return false; | |||
| data = transfer; | |||
| for (count=(len >> 14); count; count--) { | |||
| next = allocate_Transfer(); | |||
| if (!next) { | |||
| // free already-allocated qTDs | |||
| while (1) { | |||
| next = (Transfer_t *)transfer->qtd.next; | |||
| free_Transfer(transfer); | |||
| if (transfer == data) break; | |||
| transfer = next; | |||
| if (len) { | |||
| for (count=((len-1) >> 14); count; count--) { | |||
| next = allocate_Transfer(); | |||
| if (!next) { | |||
| // free already-allocated qTDs | |||
| while (1) { | |||
| next = (Transfer_t *)transfer->qtd.next; | |||
| free_Transfer(transfer); | |||
| if (transfer == data) break; | |||
| transfer = next; | |||
| } | |||
| return false; | |||
| } | |||
| return false; | |||
| data->qtd.next = (uint32_t)next; | |||
| data = next; | |||
| } | |||
| data->qtd.next = (uint32_t)next; | |||
| data = next; | |||
| } | |||
| } | |||
| // last qTD needs info for followup | |||
| data->qtd.next = 1; | |||
| data->pipe = pipe; | |||
| @@ -37,6 +37,13 @@ USBHIDInput *hiddrivers[] = {&joystick1, &rawhid1, &rawhid2}; | |||
| const char * hid_driver_names[CNT_DEVICES] = {"Joystick1", "RawHid1", "RawHid2"}; | |||
| bool hid_driver_active[CNT_DEVICES] = {false, false, false}; | |||
| BTHIDInput *bthiddrivers[] = {&joystick1}; | |||
| #define CNT_BTHIDDEVICES (sizeof(bthiddrivers)/sizeof(bthiddrivers[0])) | |||
| const char * bthid_driver_names[CNT_HIDDEVICES] = {"joystick"}; | |||
| bool bthid_driver_active[CNT_HIDDEVICES] = {false}; | |||
| bool show_changed_only = false; | |||
| bool show_raw_data = false; | |||
| bool show_changed_data = false; | |||
| @@ -49,6 +56,15 @@ int psAxis[64]; | |||
| bool first_joystick_message = true; | |||
| uint8_t last_bdaddr[6] = {0, 0, 0, 0, 0, 0}; | |||
| // ps3 motion on USB does not do much, but see if we can pair it and maybe change | |||
| // color of bulb... | |||
| uint32_t PS3_MOTION_timer = 0; | |||
| uint8_t PS3_MOTION_tried_to_pair_state = 0; | |||
| #define PS3_MOTION_PERIOD 2500 // not sure yet what would be good period for this.. | |||
| //============================================================================= | |||
| // Setup | |||
| //============================================================================= | |||
| void setup() | |||
| { | |||
| @@ -65,7 +81,9 @@ void setup() | |||
| rawhid2.attachReceive(OnReceiveHidData); | |||
| } | |||
| //============================================================================= | |||
| // Loop | |||
| //============================================================================= | |||
| void loop() | |||
| { | |||
| myusb.Task(); | |||
| @@ -90,51 +108,9 @@ void loop() | |||
| } | |||
| } | |||
| } | |||
| for (uint8_t i = 0; i < CNT_DEVICES; i++) { | |||
| if (*drivers[i] != driver_active[i]) { | |||
| if (driver_active[i]) { | |||
| Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]); | |||
| driver_active[i] = false; | |||
| } else { | |||
| Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct()); | |||
| driver_active[i] = true; | |||
| const uint8_t *psz = drivers[i]->manufacturer(); | |||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||
| psz = drivers[i]->product(); | |||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||
| psz = drivers[i]->serialNumber(); | |||
| 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]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) { | |||
| if (*hiddrivers[i] != hid_driver_active[i]) { | |||
| if (hid_driver_active[i]) { | |||
| Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]); | |||
| hid_driver_active[i] = false; | |||
| } else { | |||
| Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||
| hid_driver_active[i] = true; | |||
| const uint8_t *psz = hiddrivers[i]->manufacturer(); | |||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||
| psz = hiddrivers[i]->product(); | |||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||
| psz = hiddrivers[i]->serialNumber(); | |||
| if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||
| } | |||
| } | |||
| } | |||
| // check to see if the device list has changed: | |||
| UpdateActiveDeviceInfo(); | |||
| processPS3MotionTimer(); | |||
| if (joystick1.available()) { | |||
| if (first_joystick_message) { | |||
| @@ -164,6 +140,9 @@ void loop() | |||
| case JoystickController::PS3: | |||
| displayPS3Data(); | |||
| break; | |||
| case JoystickController::PS3_MOTION: | |||
| displayPS3MotionData(); | |||
| break; | |||
| case JoystickController::XBOXONE: | |||
| case JoystickController::XBOX360: | |||
| displayXBoxData(); | |||
| @@ -196,13 +175,96 @@ void loop() | |||
| } | |||
| } | |||
| //============================================================================= | |||
| // UpdateActiveDeviceInfo | |||
| //============================================================================= | |||
| void UpdateActiveDeviceInfo() { | |||
| for (uint8_t i = 0; i < CNT_DEVICES; i++) { | |||
| if (*drivers[i] != driver_active[i]) { | |||
| if (driver_active[i]) { | |||
| Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]); | |||
| driver_active[i] = false; | |||
| } else { | |||
| Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct()); | |||
| driver_active[i] = true; | |||
| const uint8_t *psz = drivers[i]->manufacturer(); | |||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||
| psz = drivers[i]->product(); | |||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||
| psz = drivers[i]->serialNumber(); | |||
| 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]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) { | |||
| if (*hiddrivers[i] != hid_driver_active[i]) { | |||
| if (hid_driver_active[i]) { | |||
| Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]); | |||
| hid_driver_active[i] = false; | |||
| } else { | |||
| Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||
| hid_driver_active[i] = true; | |||
| const uint8_t *psz = hiddrivers[i]->manufacturer(); | |||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||
| psz = hiddrivers[i]->product(); | |||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||
| psz = hiddrivers[i]->serialNumber(); | |||
| if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||
| // See if this is our joystick object... | |||
| if (hiddrivers[i] == &joystick1) { | |||
| Serial.printf(" Joystick type: %d\n", joystick1.joystickType()); | |||
| if (joystick1.joystickType() == JoystickController::PS3_MOTION) { | |||
| Serial.println(" PS3 Motion detected"); | |||
| PS3_MOTION_timer = millis(); // set time for last event | |||
| PS3_MOTION_tried_to_pair_state = 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // Then Bluetooth devices | |||
| for (uint8_t i = 0; i < CNT_BTHIDDEVICES; i++) { | |||
| if (*bthiddrivers[i] != bthid_driver_active[i]) { | |||
| if (bthid_driver_active[i]) { | |||
| Serial.printf("*** BTHID Device %s - disconnected ***\n", hid_driver_names[i]); | |||
| bthid_driver_active[i] = false; | |||
| } else { | |||
| Serial.printf("*** BTHID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||
| bthid_driver_active[i] = true; | |||
| const uint8_t *psz = bthiddrivers[i]->manufacturer(); | |||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||
| psz = bthiddrivers[i]->product(); | |||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||
| psz = bthiddrivers[i]->serialNumber(); | |||
| if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //============================================================================= | |||
| // displayPS4Data | |||
| //============================================================================= | |||
| void displayPS4Data() | |||
| { | |||
| buttons = joystick1.getButtons(); | |||
| 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[3], psAxis[4]); | |||
| Serial.printf("Buttons: %x\r\n", buttons); | |||
| Serial.printf("Battery Status: %d\n", ((psAxis[30] & (1 << 4) - 1)*10)); | |||
| Serial.printf("Battery Status: %d\n", ((psAxis[30] & ((1 << 4) - 1))*10)); | |||
| printAngles(); | |||
| Serial.println(); | |||
| @@ -244,6 +306,9 @@ void displayPS4Data() | |||
| } | |||
| //============================================================================= | |||
| // displayPS3Data | |||
| //============================================================================= | |||
| void displayPS3Data() | |||
| { | |||
| @@ -305,7 +370,61 @@ void displayPS3Data() | |||
| buttons_prev = buttons; | |||
| } | |||
| } | |||
| //============================================================================= | |||
| // displayPS3MotionData | |||
| //============================================================================= | |||
| void displayPS3MotionData() | |||
| { | |||
| buttons = joystick1.getButtons(); | |||
| // Hard to know what is best here. for now just copy raw data over... | |||
| // will do this for now... Format of thought to be data. | |||
| // data[1-3] Buttons (mentioned 4 as well but appears to be counter | |||
| // axis[0-1] data[5] Trigger, Previous trigger value | |||
| // 2-5 Unknown probably place holders for Axis like data for other PS3 | |||
| // 6 - Time stamp | |||
| // 7 - Battery | |||
| // 8-19 - Accel: XL, XH, YL, YH, ZL, ZH, XL2, XH2, YL2, YH2, ZL2, ZH2 | |||
| // 20-31 - Gyro: Xl,Xh,Yl,Yh,Zl,Zh,Xl2,Xh2,Yl2,Yh2,Zl2,Zh2 | |||
| // 32 - Temp High | |||
| // 33 - Temp Low (4 bits) Maybe Magneto x High on other?? | |||
| // Use Select button to choose raw or not | |||
| if ((buttons & 0x01) && !(buttons_prev & 0x01)) show_raw_data = !show_raw_data; | |||
| if ((buttons & 0x04) && !(buttons_prev & 0x04)) show_changed_data = !show_changed_data; | |||
| if (show_raw_data) { | |||
| displayRawData(); | |||
| } else { | |||
| uint64_t changed_mask = joystick1.axisChangedMask(); | |||
| Serial.printf("Changed: %08x Buttons: %x: Trig: %d\r\n", (uint32_t)changed_mask, buttons, psAxis[0]); | |||
| Serial.printf("Battery Status: %d\n", psAxis[7]); | |||
| printPS3MotionAngles(); | |||
| Serial.println(); | |||
| } | |||
| uint8_t ltv = psAxis[0]; | |||
| if ((ltv != joystick_left_trigger_value) ) { | |||
| joystick_left_trigger_value = ltv; | |||
| Serial.printf("Rumbling: %d\r\n", ltv); | |||
| joystick1.setRumble(ltv, 0); | |||
| } | |||
| if (buttons != buttons_prev) { | |||
| uint8_t ledsR = (buttons & 0x8000)? 0xff : 0; //Srq | |||
| uint8_t ledsG = (buttons & 0x2000)? 0xff : 0; //Cir | |||
| uint8_t ledsB = (buttons & 0x1000)? 0xff : 0; //Tri | |||
| Serial.printf("Set Leds %x %x %x\r\n", ledsR, ledsG, ledsB ); | |||
| joystick1.setLEDs(ledsR, ledsG, ledsB); | |||
| buttons_prev = buttons; | |||
| } | |||
| } | |||
| //============================================================================= | |||
| // displayXBoxData | |||
| //============================================================================= | |||
| void displayXBoxData() | |||
| { | |||
| buttons = joystick1.getButtons(); | |||
| @@ -345,6 +464,9 @@ void displayXBoxData() | |||
| } | |||
| } | |||
| //============================================================================= | |||
| // displayRawData | |||
| //============================================================================= | |||
| void displayRawData() { | |||
| uint64_t axis_mask = joystick1.axisMask(); | |||
| uint64_t changed_mask = joystick1.axisChangedMask(); | |||
| @@ -380,6 +502,9 @@ void displayRawData() { | |||
| } | |||
| //============================================================================= | |||
| // OnReceiveHidData | |||
| //============================================================================= | |||
| 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 | |||
| // to output to Serial. while still having Raw Hid... | |||
| @@ -413,4 +538,49 @@ bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| //============================================================================= | |||
| // processPS3MotionTimer | |||
| //============================================================================= | |||
| static const uint32_t PS3_MOTION_colors[] = {0, 0xff, 0xff00, 0xff0000, 0xffff, 0xff00ff, 0xffff00, 0xffffff}; | |||
| uint8_t PS3_MOTION_colors_index = 0; | |||
| void processPS3MotionTimer() { | |||
| // See if we have a PS3_MOTION connected and we have run for a certain amount of time | |||
| if (PS3_MOTION_timer && ((millis()-PS3_MOTION_timer) >= PS3_MOTION_PERIOD)) { | |||
| Serial.println("PS3 Motion Timer"); Serial.flush(); | |||
| if (joystick1) { | |||
| PS3_MOTION_timer = millis(); // joystick not there any more... | |||
| // We will first try to set feedback color for the PS3, maybe alternate colors | |||
| if (++PS3_MOTION_colors_index >= sizeof(PS3_MOTION_colors)/sizeof(PS3_MOTION_colors[0])) PS3_MOTION_colors_index = 0; | |||
| joystick1.setLEDs(PS3_MOTION_colors[PS3_MOTION_colors_index]); | |||
| // Next see if we can try to pair. | |||
| if (PS3_MOTION_tried_to_pair_state == 0) { | |||
| Serial.println("PS3_MOTION Connected"); | |||
| if (!last_bdaddr[0] && !last_bdaddr[1] && !last_bdaddr[2] && !last_bdaddr[3] && !last_bdaddr[4] && !last_bdaddr[5]) { | |||
| Serial.println(" - No Bluetooth adapter has been plugged in - so will not try to pair"); | |||
| PS3_MOTION_tried_to_pair_state = 1; | |||
| } | |||
| } | |||
| if ((PS3_MOTION_tried_to_pair_state < 2) && | |||
| (last_bdaddr[0] || last_bdaddr[1] || last_bdaddr[2] || last_bdaddr[3] || last_bdaddr[4] || last_bdaddr[5])) { | |||
| Serial.println(" - Bluetooth device detected, will try to pair"); | |||
| // Lets try to pair | |||
| 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"); | |||
| } | |||
| PS3_MOTION_tried_to_pair_state = 2; // don't try again... | |||
| } | |||
| } else { | |||
| Serial.println("PS3 Motion Joystick no longer detected"); | |||
| PS3_MOTION_timer = 0; // joystick not there any more... | |||
| } | |||
| } | |||
| } | |||
| @@ -1,10 +1,17 @@ | |||
| float pitch, roll; | |||
| float gx, gy, gz; | |||
| int16_t mx, my, mz; | |||
| uint16_t xc, yc; | |||
| uint8_t isTouch; | |||
| float ax, ay, az; | |||
| int16_t xc_old, yc_old; | |||
| /* Decode 12-bit signed value (assuming two's complement) */ | |||
| #define TWELVE_BIT_SIGNED(x) (((x) & 0x800)?(-(((~(x)) & 0xFFF) + 1)):(x)) | |||
| #define Model_ZCM1 1 | |||
| //#define Model_ZCM2 0 | |||
| void printAngles(){ | |||
| //test function calls | |||
| float gx, gy, gz; | |||
| @@ -22,8 +29,6 @@ void printAngles(){ | |||
| void getCoords(uint16_t &xc, uint16_t &yc, uint8_t &isTouch){ | |||
| //uint8_t finger = 0; //only getting finger 1 | |||
| uint8_t Id = 0; | |||
| // Trackpad touch 1: id, active, x, y | |||
| xc = ((psAxis[37] & 0x0f) << 8) | psAxis[36]; | |||
| @@ -62,4 +67,80 @@ void getGyro(float &gx, float &gy, float &gz){ | |||
| gy = (float) gyroy * RAD_TO_DEG/1024; | |||
| gz = (float) gyroz * RAD_TO_DEG/1024; | |||
| } | |||
| void printPS3MotionAngles(){ | |||
| //test function calls | |||
| float gx, gy, gz; | |||
| getPS3MotionAccel(ax, ay, az); | |||
| Serial.printf("Accel-g's: %f, %f, %f\n", ax, ay, az); | |||
| getPS3MotionGyro(gx, gy, gz); | |||
| Serial.printf("Gyro-deg/sec: %f, %f, %f\n", gx, gy, gz); | |||
| getPS3MotionMag(mx, my, mz); | |||
| Serial.printf("Mag: %d, %d, %d\n", mx, my, mz); | |||
| getPS3MotionAngles(pitch, roll); | |||
| Serial.printf("Pitch/Roll: %f, %f\n", pitch, roll); | |||
| } | |||
| void getPS3MotionAccel( float &ax, float &ay, float &az){ | |||
| int accelx = (psAxis[15]<<8 | psAxis[14]); | |||
| int accely = (psAxis[17]<<8 | psAxis[16]); | |||
| int accelz = (psAxis[19]<<8 | psAxis[18]); | |||
| #if defined(Model_ZCM1) | |||
| accelx = accelx-0x8000; | |||
| accely = accely-0x8000; | |||
| accelz = accelz-0x8000; | |||
| #elif defined(Model_ZCM2) | |||
| accelx = (accelx & 0x8000) ? (-(~accelx & 0xFFFF) + 1) : accelx; | |||
| accely = (accely & 0x8000) ? (-(~accely & 0xFFFF) + 1) : accely; | |||
| accelz = (accelz & 0x8000) ? (-(~accelz & 0xFFFF) + 1) : accelz; | |||
| #endif | |||
| ax = (float) accelx/4096; | |||
| ay = (float) accely/4096; | |||
| az = (float) accelz/4096; | |||
| } | |||
| void getPS3MotionAngles(float &p, float &r){ | |||
| getAccel( ax, ay, az); | |||
| p = (atan2f(ay, az) + PI) * RAD_TO_DEG; | |||
| r = (atan2f(ax, az) + PI) * RAD_TO_DEG; | |||
| } | |||
| void getPS3MotionGyro(float &gx, float &gy, float &gz){ | |||
| int gyrox = (psAxis[21]<<8 | psAxis[20]); | |||
| int gyroy = (psAxis[23]<<8 | psAxis[22]); | |||
| int gyroz = (psAxis[25]<<8 | psAxis[24]); | |||
| #if defined(Model_ZCM1) | |||
| gyrox = gyrox-0x8000; | |||
| gyroy = gyroy-0x8000; | |||
| gyroz = gyroz-0x8000; | |||
| #elif defined(Model_ZCM2) | |||
| gyrox = (gyrox & 0x8000) ? (-(~gyrox & 0xFFFF) + 1) : gyrox; | |||
| gyroy = (gyroy & 0x8000) ? (-(~gyroy & 0xFFFF) + 1) : gyroy; | |||
| gyroz = (gyroz & 0x8000) ? (-(~gyroz & 0xFFFF) + 1) : gyroz; | |||
| #endif | |||
| gx = (float) gyrox * RAD_TO_DEG/1024; | |||
| gy = (float) gyroy * RAD_TO_DEG/1024; | |||
| gz = (float) gyroz * RAD_TO_DEG/1024; | |||
| } | |||
| void getPS3MotionMag(int16_t &mx, int16_t &my, int16_t &mz){ | |||
| #if defined(Model_ZCM1) | |||
| mx = TWELVE_BIT_SIGNED(((psAxis[33] & 0x0F) << 8) | | |||
| psAxis[34]); | |||
| my = TWELVE_BIT_SIGNED((psAxis[35] << 4) | | |||
| (psAxis[36] & 0xF0) >> 4); | |||
| mz = TWELVE_BIT_SIGNED(((psAxis[36] & 0x0F) << 8) | | |||
| psAxis[37]); | |||
| #elif defined(Model_ZCM2) | |||
| // NOTE: This model does not have magnetometers | |||
| Serial.println("Not avail for ZCM2!"); | |||
| #endif | |||
| } | |||
| @@ -251,7 +251,7 @@ void UpdateActiveDeviceInfo() { | |||
| if (*bthiddrivers[i] != bthid_driver_active[i]) { | |||
| if (bthid_driver_active[i]) { | |||
| Serial.printf("*** BTHID Device %s - disconnected ***\n", hid_driver_names[i]); | |||
| hid_driver_active[i] = false; | |||
| bthid_driver_active[i] = false; | |||
| } else { | |||
| new_device_detected = true; | |||
| Serial.printf("*** BTHID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||
| @@ -166,7 +166,7 @@ void USBHIDParser::control(const Transfer_t *transfer) | |||
| parse(); | |||
| queue_Data_Transfer(in_pipe, report, in_size, this); | |||
| if (device->idVendor == 0x054C && | |||
| ((device->idProduct == 0x0268) || (device->idProduct == 0x042F) || (device->idProduct == 0x03D5))) { | |||
| ((device->idProduct == 0x0268) || (device->idProduct == 0x042F)/* || (device->idProduct == 0x03D5)*/)) { | |||
| println("send special PS3 feature command"); | |||
| mk_setup(setup, 0x21, 9, 0x03F4, 0, 4); // ps3 tell to send report 1? | |||
| static uint8_t ps3_feature_F4_report[] = {0x42, 0x0c, 0x00, 0x00}; | |||
| @@ -42,7 +42,7 @@ JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping | |||
| { 0x045e, 0x0719, XBOX360, false}, | |||
| { 0x054C, 0x0268, PS3, true}, | |||
| { 0x054C, 0x042F, PS3, true}, // PS3 Navigation controller | |||
| { 0x054C, 0x03D5, PS3, true}, // PS3 Motion controller | |||
| { 0x054C, 0x03D5, PS3_MOTION, true}, // PS3 Motion controller | |||
| { 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true } | |||
| }; | |||
| @@ -127,6 +127,8 @@ bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeo | |||
| break; | |||
| case PS3: | |||
| return transmitPS3UserFeedbackMsg(); | |||
| case PS3_MOTION: | |||
| return transmitPS3MotionUserFeedbackMsg(); | |||
| case PS4: | |||
| return transmitPS4UserFeedbackMsg(); | |||
| case XBOXONE: | |||
| @@ -169,6 +171,7 @@ bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeo | |||
| return false; | |||
| } | |||
| bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb) | |||
| { | |||
| // Need to know which joystick we are on. Start off with XBox support - maybe need to add some enum value for the known | |||
| @@ -181,6 +184,8 @@ bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb) | |||
| switch (joystickType_) { | |||
| case PS3: | |||
| return transmitPS3UserFeedbackMsg(); | |||
| case PS3_MOTION: | |||
| return transmitPS3MotionUserFeedbackMsg(); | |||
| case PS4: | |||
| return transmitPS4UserFeedbackMsg(); | |||
| case XBOX360: | |||
| @@ -272,7 +277,7 @@ bool JoystickController::transmitPS3UserFeedbackMsg() { | |||
| 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 | |||
| txbuf_[9] = leds_[2] << 1; // RGB value // using third led now... | |||
| //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_) { | |||
| @@ -284,7 +289,7 @@ bool JoystickController::transmitPS3UserFeedbackMsg() { | |||
| 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 | |||
| txbuf_[11] = leds_[2] << 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; | |||
| @@ -292,6 +297,33 @@ bool JoystickController::transmitPS3UserFeedbackMsg() { | |||
| return false; | |||
| } | |||
| #define MOVE_REPORT_BUFFER_SIZE 7 | |||
| #define MOVE_HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller | |||
| bool JoystickController::transmitPS3MotionUserFeedbackMsg() { | |||
| if (driver_) { | |||
| txbuf_[0] = 0x02; // Set report ID, this is needed for Move commands to work | |||
| txbuf_[2] = leds_[0]; | |||
| txbuf_[3] = leds_[1]; | |||
| txbuf_[4] = leds_[2]; | |||
| txbuf_[6] = rumble_lValue_; // Set the rumble value into the write buffer | |||
| //return driver_->sendControlPacket(0x21, 9, 0x201, 0, MOVE_REPORT_BUFFER_SIZE, txbuf_); | |||
| return driver_->sendPacket(txbuf_, MOVE_REPORT_BUFFER_SIZE); | |||
| } else if (btdriver_) { | |||
| txbuf_[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) | |||
| txbuf_[1] = 0x02; // Report ID | |||
| txbuf_[3] = leds_[0]; | |||
| txbuf_[4] = leds_[1]; | |||
| txbuf_[5] = leds_[2]; | |||
| txbuf_[7] = rumble_lValue_; | |||
| btdriver_->sendL2CapCommand(txbuf_, MOVE_HID_BUFFERSIZE, BluetoothController::INTERRUPT_SCID); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| //***************************************************************************** | |||
| // Support for Joysticks that Use HID data. | |||
| //***************************************************************************** | |||
| @@ -318,6 +350,7 @@ hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t * | |||
| DBGPrintf("JoystickController::claim_collection joystickType_=%d\n", joystickType_); | |||
| switch (joystickType_) { | |||
| case PS3: | |||
| case PS3_MOTION: // not sure yet | |||
| additional_axis_usage_page_ = 0x1; | |||
| additional_axis_usage_start_ = 0x100; | |||
| additional_axis_usage_count_ = 39; | |||
| @@ -711,7 +744,7 @@ bool JoystickController::claim_bluetooth(BluetoothController *driver, uint32_t b | |||
| } | |||
| if (remoteName && mapNameToJoystickType(remoteName)) { | |||
| if (joystickType_ == PS3) { | |||
| if ((joystickType_ == PS3) || (joystickType_ == PS3_MOTION)) { | |||
| DBGPrintf("JoystickController::claim_bluetooth TRUE PS3 hack...\n"); | |||
| btdriver_ = driver; | |||
| btdevice = (Device_t*)driver; // remember this way | |||
| @@ -728,13 +761,15 @@ bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_ | |||
| // Example data from PS4 controller | |||
| //01 7e 7f 82 84 08 00 00 00 00 | |||
| // LX LY RX RY BT BT PS LT RT | |||
| //DBGPrintf("JoystickController::process_bluetooth_HID_data\n"); | |||
| DBGPrintf("JoystickController::process_bluetooth_HID_data: data[0]=%x\n", data[0]); | |||
| // May have to look at this one with other controllers... | |||
| if (data[0] == 1) { | |||
| //print(" Joystick Data: "); | |||
| //print_hexbytes(data, length); | |||
| // DBGPrintf(" Joystick Data: "); | |||
| // print_hexbytes(data, length); | |||
| if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays... | |||
| DBGPrintf(" Joystick Data: "); | |||
| for(uint16_t i =0; i < length; i++) DBGPrintf("%02x ", data[i]); | |||
| DBGPrintf("\r\n"); | |||
| 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); | |||
| @@ -777,6 +812,37 @@ bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_ | |||
| } | |||
| mask <<= 1; // shift down the mask. | |||
| } | |||
| } else if (joystickType_ == PS3_MOTION) { | |||
| // Quick and dirty PS3_Motion data. | |||
| uint32_t cur_buttons = data[1] | ((uint16_t)data[2] << 8) | ((uint32_t)data[3] << 16); | |||
| if (cur_buttons != buttons) { | |||
| buttons = cur_buttons; | |||
| joystickEvent = true; // something changed. | |||
| } | |||
| // Hard to know what is best here. for now just copy raw data over... | |||
| // will do this for now... Format of thought to be data. | |||
| // data[1-3] Buttons (mentioned 4 as well but appears to be counter | |||
| // axis[0-1] data[5] Trigger, Previous trigger value | |||
| // 2-5 Unknown probably place holders for Axis like data for other PS3 | |||
| // 6 - Time stamp | |||
| // 7 - Battery | |||
| // 8-19 - Accel: XL, XH, YL, YH, ZL, ZH, XL2, XH2, YL2, YH2, ZL2, ZH2 | |||
| // 20-31 - Gyro: Xl,Xh,Yl,Yh,Zl,Zh,Xl2,Xh2,Yl2,Yh2,Zl2,Zh2 | |||
| // 32 - Temp High | |||
| // 33 - Temp Low (4 bits) Maybe Magneto x High on other?? | |||
| uint64_t mask = 0x1; | |||
| axis_mask_ = 0; // assume bits 0, 1, 2, 5 | |||
| // Then rest of data | |||
| mask = 0x1 << 10; // setup for other bits | |||
| for (uint16_t i = 5; i < length; i++ ) { | |||
| axis_mask_ |= mask; | |||
| if(data[i] != axis[i-5]) { | |||
| axis_changed_mask_ |= mask; | |||
| axis[i-5] = data[i]; | |||
| } | |||
| mask <<= 1; // shift down the mask. | |||
| } | |||
| } else { | |||
| uint64_t mask = 0x1; | |||
| @@ -800,116 +866,92 @@ bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_ | |||
| return true; | |||
| } else if(data[0] == 0x11){ | |||
| if (data[0] == 1) { | |||
| //print(" Joystick Data: "); | |||
| //print_hexbytes(data, length); | |||
| // 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... | |||
| 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; | |||
| connected_ = true; | |||
| return true; | |||
| } else if(data[0] == 0x11){ | |||
| DBGPrintf("\n Joystick Data: "); | |||
| uint64_t mask = 0x1; | |||
| axis_mask_ = 0; | |||
| axis_changed_mask_ = 0; | |||
| //This moves data to be equivalent to what we see for | |||
| //data[0] = 0x01 | |||
| uint8_t tmp_data[length-2]; | |||
| for (uint16_t i = 0; i < (length-2); i++ ) { | |||
| tmp_data[i] = 0; | |||
| tmp_data[i] = data[i+2]; | |||
| } | |||
| /* | |||
| * [1] LX, [2] = LY, [3] = RX, [4] = RY | |||
| * [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3 | |||
| * [6] R3,L3, opt, share, R2, L2, R1, L1 | |||
| * [7] Counter (bit7-2), T-PAD, PS | |||
| * [8] Left Trigger, [9] Right Trigger | |||
| * [10-11] Timestamp | |||
| * [12] Battery (0 to 0xff) | |||
| * [13-14] acceleration x | |||
| * [15-16] acceleration y | |||
| * [17-18] acceleration z | |||
| * [19-20] gyro x | |||
| * [21-22] gyro y | |||
| * [23-24] gyro z | |||
| * [25-29] unknown | |||
| * [30] 0x00,phone,mic, usb, battery level (4bits) | |||
| * rest is trackpad? to do implement? | |||
| */ | |||
| //PS Bit | |||
| tmp_data[7] = (tmp_data[7] >> 0) & 1; | |||
| //set arrow buttons to axis[0] | |||
| tmp_data[10] = tmp_data[5] & ((1 << 4) - 1); | |||
| //set buttons for last 4bits in the axis[5] | |||
| tmp_data[5] = tmp_data[5] >> 4; | |||
| DBGPrintf("\n Joystick Data: "); | |||
| uint64_t mask = 0x1; | |||
| axis_mask_ = 0; | |||
| axis_changed_mask_ = 0; | |||
| // Quick and dirty hack to match PS4 HID data | |||
| uint32_t cur_buttons = tmp_data[7] | (tmp_data[10]) | ((tmp_data[6]*10)) | ((uint16_t)tmp_data[5] << 16) ; | |||
| if (cur_buttons != buttons) { | |||
| buttons = cur_buttons; | |||
| joystickEvent = true; // something changed. | |||
| } | |||
| mask = 0x1; | |||
| axis_mask_ = 0x27; // assume bits 0, 1, 2, 5 | |||
| for (uint16_t i = 0; i < 3; i++) { | |||
| if (axis[i] != tmp_data[i+1]) { | |||
| axis_changed_mask_ |= mask; | |||
| axis[i] = tmp_data[i+1]; | |||
| } | |||
| mask <<= 1; // shift down the mask. | |||
| } | |||
| if (axis[5] != tmp_data[4]) { | |||
| axis_changed_mask_ |= (1<<5); | |||
| axis[5] = tmp_data[4]; | |||
| } | |||
| if (axis[3] != tmp_data[8]) { | |||
| axis_changed_mask_ |= (1<<3); | |||
| axis[3] = tmp_data[8]; | |||
| } | |||
| if (axis[4] != tmp_data[9]) { | |||
| axis_changed_mask_ |= (1<<4); | |||
| axis[4] = tmp_data[9]; | |||
| //This moves data to be equivalent to what we see for | |||
| //data[0] = 0x01 | |||
| uint8_t tmp_data[length-2]; | |||
| for (uint16_t i = 0; i < (length-2); i++ ) { | |||
| tmp_data[i] = 0; | |||
| tmp_data[i] = data[i+2]; | |||
| } | |||
| /* | |||
| * [1] LX, [2] = LY, [3] = RX, [4] = RY | |||
| * [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3 | |||
| * [6] R3,L3, opt, share, R2, L2, R1, L1 | |||
| * [7] Counter (bit7-2), T-PAD, PS | |||
| * [8] Left Trigger, [9] Right Trigger | |||
| * [10-11] Timestamp | |||
| * [12] Battery (0 to 0xff) | |||
| * [13-14] acceleration x | |||
| * [15-16] acceleration y | |||
| * [17-18] acceleration z | |||
| * [19-20] gyro x | |||
| * [21-22] gyro y | |||
| * [23-24] gyro z | |||
| * [25-29] unknown | |||
| * [30] 0x00,phone,mic, usb, battery level (4bits) | |||
| * rest is trackpad? to do implement? | |||
| */ | |||
| //PS Bit | |||
| tmp_data[7] = (tmp_data[7] >> 0) & 1; | |||
| //set arrow buttons to axis[0] | |||
| tmp_data[10] = tmp_data[5] & ((1 << 4) - 1); | |||
| //set buttons for last 4bits in the axis[5] | |||
| tmp_data[5] = tmp_data[5] >> 4; | |||
| // Quick and dirty hack to match PS4 HID data | |||
| uint32_t cur_buttons = tmp_data[7] | (tmp_data[10]) | ((tmp_data[6]*10)) | ((uint16_t)tmp_data[5] << 16) ; | |||
| if (cur_buttons != buttons) { | |||
| buttons = cur_buttons; | |||
| joystickEvent = true; // something changed. | |||
| } | |||
| mask = 0x1; | |||
| axis_mask_ = 0x27; // assume bits 0, 1, 2, 5 | |||
| for (uint16_t i = 0; i < 3; i++) { | |||
| if (axis[i] != tmp_data[i+1]) { | |||
| axis_changed_mask_ |= mask; | |||
| axis[i] = tmp_data[i+1]; | |||
| } | |||
| //limit for masking | |||
| mask = 0x1; | |||
| for (uint16_t i = 6; i < (64); i++ ) { | |||
| axis_mask_ |= mask; | |||
| if(tmp_data[i] != axis[i]) { | |||
| axis_changed_mask_ |= mask; | |||
| axis[i] = tmp_data[i]; | |||
| } | |||
| mask <<= 1; // shift down the mask. | |||
| DBGPrintf("%02x ", axis[i]); | |||
| mask <<= 1; // shift down the mask. | |||
| } | |||
| if (axis[5] != tmp_data[4]) { | |||
| axis_changed_mask_ |= (1<<5); | |||
| axis[5] = tmp_data[4]; | |||
| } | |||
| if (axis[3] != tmp_data[8]) { | |||
| axis_changed_mask_ |= (1<<3); | |||
| axis[3] = tmp_data[8]; | |||
| } | |||
| if (axis[4] != tmp_data[9]) { | |||
| axis_changed_mask_ |= (1<<4); | |||
| axis[4] = tmp_data[9]; | |||
| } | |||
| //limit for masking | |||
| mask = 0x1; | |||
| for (uint16_t i = 6; i < (64); i++ ) { | |||
| axis_mask_ |= mask; | |||
| if(tmp_data[i] != axis[i]) { | |||
| axis_changed_mask_ |= mask; | |||
| axis[i] = tmp_data[i]; | |||
| } | |||
| DBGPrintf("\n"); | |||
| //DBGPrintf("Axis Mask (axis_mask_, axis_changed_mask_; %d, %d\n", axis_mask_,axis_changed_mask_); | |||
| joystickEvent = true; | |||
| connected_ = true; | |||
| mask <<= 1; // shift down the mask. | |||
| DBGPrintf("%02x ", axis[i]); | |||
| } | |||
| DBGPrintf("\n"); | |||
| //DBGPrintf("Axis Mask (axis_mask_, axis_changed_mask_; %d, %d\n", axis_mask_,axis_changed_mask_); | |||
| joystickEvent = true; | |||
| connected_ = true; | |||
| } | |||
| return false; | |||
| } | |||
| @@ -926,6 +968,9 @@ bool JoystickController::mapNameToJoystickType(const uint8_t *remoteName) | |||
| } else if (strncmp((const char *)remoteName, "Navigation Controller", 21) == 0) { | |||
| DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3\n", (uint32_t)this, remoteName); | |||
| joystickType_ = PS3; | |||
| } else if (strncmp((const char *)remoteName, "Motion Controller", 17) == 0) { | |||
| DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3 Motion\n", (uint32_t)this, remoteName); | |||
| joystickType_ = PS3_MOTION; | |||
| } 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; | |||
| @@ -944,6 +989,7 @@ bool JoystickController::remoteNameComplete(const uint8_t *remoteName) | |||
| switch (joystickType_) { | |||
| case PS4: special_process_required = SP_NEED_CONNECT; break; | |||
| case PS3: special_process_required = SP_PS3_IDS; break; | |||
| case PS3_MOTION: special_process_required = SP_PS3_IDS; break; | |||
| default: | |||
| break; | |||
| } | |||
| @@ -954,28 +1000,37 @@ bool JoystickController::remoteNameComplete(const uint8_t *remoteName) | |||
| void JoystickController::connectionComplete() | |||
| { | |||
| DBGPrintf(" JoystickController::connectionComplete %x joystick type %d\n", (uint32_t)this, 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); | |||
| switch (joystickType_) { | |||
| case 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); | |||
| } | |||
| break; | |||
| case 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); | |||
| } | |||
| break; | |||
| case PS3_MOTION: | |||
| setLEDs(0, 0xff, 0); // Maybe try setting to green? | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| void JoystickController::release_bluetooth() | |||
| @@ -989,15 +1044,29 @@ void JoystickController::release_bluetooth() | |||
| 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_); | |||
| if (!driver_) return false; | |||
| if (joystickType_ == PS3) { | |||
| /* 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_); | |||
| } else if (joystickType_ == PS3_MOTION) { | |||
| // Slightly different than other PS3 units... | |||
| txbuf_[0] = 0x05; | |||
| for(uint8_t i = 0; i < 6; i++) | |||
| txbuf_[i + 1] = bdaddr[i]; // Order different looks like LSB First? | |||
| txbuf_[7] = 0x10; | |||
| txbuf_[8] = 0x01; | |||
| txbuf_[9] = 0x02; | |||
| txbuf_[10] = 0x12; | |||
| // 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, 0x305, 0, 11, txbuf_); | |||
| } | |||
| return false; | |||
| } | |||
| @@ -90,6 +90,7 @@ setRumbleOn KEYWORD2 | |||
| setLEDs KEYWORD2 | |||
| joystickType KEYWORD2 | |||
| PS3 LITERAL1 | |||
| PS3_MOTION LITERAL1 | |||
| PS4 LITERAL1 | |||
| XBOXONE LITERAL1 | |||
| XBOX360 LITERAL1 | |||
| @@ -35,7 +35,7 @@ void MouseController::init() | |||
| hidclaim_t MouseController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | |||
| { | |||
| // only claim Desktop/Mouse | |||
| if (topusage != 0x10002) return CLAIM_NO; | |||
| if ((topusage != 0x10002) && (topusage != 0x10001)) return CLAIM_NO; | |||
| // only claim from one physical device | |||
| if (mydevice != NULL && dev != mydevice) return CLAIM_NO; | |||
| mydevice = dev; | |||