PS4 starting to work, Still some rumble issues. Also some WIP parts for caching remote name Some of these changes also came from @mjs513main
| //#define USBHOST_PRINT_DEBUG | //#define USBHOST_PRINT_DEBUG | ||||
| #define USBHDBGSerial Serial1 | |||||
| /************************************************/ | /************************************************/ | ||||
| /* Data Types */ | /* Data Types */ | ||||
| static void print_config_descriptor(const uint8_t *p, uint32_t maxlen); | static void print_config_descriptor(const uint8_t *p, uint32_t maxlen); | ||||
| static void print_string_descriptor(const char *name, const uint8_t *p); | static void print_string_descriptor(const char *name, const uint8_t *p); | ||||
| static void print_hexbytes(const void *ptr, uint32_t len); | static void print_hexbytes(const void *ptr, uint32_t len); | ||||
| static void print_(const char *s) { Serial.print(s); } | |||||
| static void print_(int n) { Serial.print(n); } | |||||
| static void print_(unsigned int n) { Serial.print(n); } | |||||
| static void print_(long n) { Serial.print(n); } | |||||
| static void print_(unsigned long n) { Serial.print(n); } | |||||
| static void println_(const char *s) { Serial.println(s); } | |||||
| static void println_(int n) { Serial.println(n); } | |||||
| static void println_(unsigned int n) { Serial.println(n); } | |||||
| static void println_(long n) { Serial.println(n); } | |||||
| static void println_(unsigned long n) { Serial.println(n); } | |||||
| static void println_() { Serial.println(); } | |||||
| static void print_(uint32_t n, uint8_t b) { Serial.print(n, b); } | |||||
| static void println_(uint32_t n, uint8_t b) { Serial.println(n, b); } | |||||
| static void print_(const char *s) { USBHDBGSerial.print(s); } | |||||
| static void print_(int n) { USBHDBGSerial.print(n); } | |||||
| static void print_(unsigned int n) { USBHDBGSerial.print(n); } | |||||
| static void print_(long n) { USBHDBGSerial.print(n); } | |||||
| static void print_(unsigned long n) { USBHDBGSerial.print(n); } | |||||
| static void println_(const char *s) { USBHDBGSerial.println(s); } | |||||
| static void println_(int n) { USBHDBGSerial.println(n); } | |||||
| static void println_(unsigned int n) { USBHDBGSerial.println(n); } | |||||
| static void println_(long n) { USBHDBGSerial.println(n); } | |||||
| static void println_(unsigned long n) { USBHDBGSerial.println(n); } | |||||
| static void println_() { USBHDBGSerial.println(); } | |||||
| static void print_(uint32_t n, uint8_t b) { USBHDBGSerial.print(n, b); } | |||||
| static void println_(uint32_t n, uint8_t b) { USBHDBGSerial.println(n, b); } | |||||
| static void print_(const char *s, int n, uint8_t b = DEC) { | static void print_(const char *s, int n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.print(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
| static void print_(const char *s, unsigned int n, uint8_t b = DEC) { | static void print_(const char *s, unsigned int n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.print(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
| static void print_(const char *s, long n, uint8_t b = DEC) { | static void print_(const char *s, long n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.print(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
| static void print_(const char *s, unsigned long n, uint8_t b = DEC) { | static void print_(const char *s, unsigned long n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.print(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
| static void println_(const char *s, int n, uint8_t b = DEC) { | static void println_(const char *s, int n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.println(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
| static void println_(const char *s, unsigned int n, uint8_t b = DEC) { | static void println_(const char *s, unsigned int n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.println(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
| static void println_(const char *s, long n, uint8_t b = DEC) { | static void println_(const char *s, long n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.println(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
| static void println_(const char *s, unsigned long n, uint8_t b = DEC) { | static void println_(const char *s, unsigned long n, uint8_t b = DEC) { | ||||
| Serial.print(s); Serial.println(n, b); } | |||||
| USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
| friend class USBDriverTimer; // for access to print & println | friend class USBDriverTimer; // for access to print & println | ||||
| #else | #else | ||||
| static void print_(const Transfer_t *transfer) {} | static void print_(const Transfer_t *transfer) {} | ||||
| virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class) {return false;} | virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class) {return false;} | ||||
| 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) {}; | |||||
| void add_to_list(); | void add_to_list(); | ||||
| BTHIDInput *next = NULL; | BTHIDInput *next = NULL; | ||||
| friend class BluetoothController; | friend class BluetoothController; | ||||
| protected: | protected: | ||||
| strbuf_t *btstrbuf; | |||||
| Device_t *btdevice = NULL; | Device_t *btdevice = NULL; | ||||
| }; | }; | ||||
| 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 = UNKNOWN; | ||||
| //Bluetooth PS4 | |||||
| int getAxisPS4(uint32_t index) { return (index < (sizeof(axisPS4)/sizeof(axisPS4[0]))) ? axisPS4[index] : 0; } | |||||
| int getOnChangePS4() {return ps4OnChange; } | |||||
| int getAxisChangePS4(uint32_t index) { return (index < (sizeof(axisChange)/sizeof(axisChange[0]))) ? axisChange[index] : 0; } | |||||
| bool setRumblePS4(uint8_t lValue, uint8_t rValue, uint8_t timeout=0xff); | |||||
| bool setPS4LEDs(uint8_t lr, uint8_t lg, uint8_t lb); | |||||
| protected: | protected: | ||||
| // From USBDriver | // From USBDriver | ||||
| virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class); | virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class); | ||||
| 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); | |||||
| private: | private: | ||||
| bool hidDevice; | bool hidDevice; | ||||
| } product_vendor_mapping_t; | } product_vendor_mapping_t; | ||||
| static product_vendor_mapping_t pid_vid_mapping[]; | static product_vendor_mapping_t pid_vid_mapping[]; | ||||
| //Bluetooth PS4 | |||||
| int axisPS4[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |||||
| int axisChange[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |||||
| int ps4OnChange; | |||||
| }; | }; | ||||
| enum {BT_CLASS_DEVICE= 0x0804}; // Toy - Robot | enum {BT_CLASS_DEVICE= 0x0804}; // Toy - Robot | ||||
| static void driver_ready_for_bluetooth(BTHIDInput *driver); | static void driver_ready_for_bluetooth(BTHIDInput *driver); | ||||
| 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) { | void sendL2CapCommand(uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00) { | ||||
| //sendL2CapCommand(device_connection_handle_, data, nbytes, control_scid_ & 0xff, control_scid_ >> 8); | |||||
| sendL2CapCommand (device_connection_handle_, data, nbytes, channelLow, channelHigh); | sendL2CapCommand (device_connection_handle_, data, nbytes, channelLow, channelHigh); | ||||
| } | } | ||||
| 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 | ||||
| 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_bdaddr_[6];// remember devices address | uint8_t device_bdaddr_[6];// remember devices address |
| #undef DEBUG_BT_VERBOSE | #undef DEBUG_BT_VERBOSE | ||||
| void DBGPrintf(...) {}; | void DBGPrintf(...) {}; | ||||
| #else | #else | ||||
| #define DBGPrintf Serial.printf | |||||
| #define DBGPrintf USBHDBGSerial.printf | |||||
| #endif | #endif | ||||
| #ifndef DEBUG_BT_VERBOSE | #ifndef DEBUG_BT_VERBOSE | ||||
| void VDBGPrintf(...) {}; | void VDBGPrintf(...) {}; | ||||
| #else | #else | ||||
| #define VDBGPrintf Serial.printf | |||||
| #define VDBGPrintf USBHDBGSerial.printf | |||||
| #endif | #endif | ||||
| // collection is returned, or NULL if no driver wants it. | // collection is returned, or NULL if no driver wants it. | ||||
| BTHIDInput * BluetoothController::find_driver(uint32_t device_type) | BTHIDInput * BluetoothController::find_driver(uint32_t device_type) | ||||
| { | { | ||||
| Serial.printf("BluetoothController::find_driver"); | |||||
| USBHDBGSerial.printf("BluetoothController::find_driver"); | |||||
| BTHIDInput *driver = available_bthid_drivers_list; | BTHIDInput *driver = available_bthid_drivers_list; | ||||
| while (driver) { | while (driver) { | ||||
| Serial.printf(" driver %x\n", (uint32_t)driver); | |||||
| USBHDBGSerial.printf(" driver %x\n", (uint32_t)driver); | |||||
| if (driver->claim_bluetooth(this, device_type)) { | if (driver->claim_bluetooth(this, device_type)) { | ||||
| Serial.printf(" *** Claimed ***\n"); | |||||
| USBHDBGSerial.printf(" *** Claimed ***\n"); | |||||
| return driver; | return driver; | ||||
| } | } | ||||
| driver = driver->next; | driver = driver->next; | ||||
| descriptor_index += 7; // setup to look at next one... | descriptor_index += 7; // setup to look at next one... | ||||
| } | } | ||||
| if ((rxep == 0) || (txep == 0)) { | if ((rxep == 0) || (txep == 0)) { | ||||
| Serial.printf("Bluetooth end points not found: %d %d\n", rxep, txep); | |||||
| USBHDBGSerial.printf("Bluetooth end points not found: %d %d\n", rxep, txep); | |||||
| return false; // did not find two end points. | return false; // did not find two end points. | ||||
| } | } | ||||
| DBGPrintf(" rxep=%d(%d) txep=%d(%d) rx2ep=%d(%d)\n", rxep&15, rx_size_, txep, tx_size_, | DBGPrintf(" rxep=%d(%d) txep=%d(%d) rx2ep=%d(%d)\n", rxep&15, rx_size_, txep, tx_size_, | ||||
| void BluetoothController::disconnect() | void BluetoothController::disconnect() | ||||
| { | { | ||||
| Serial.printf("Bluetooth Disconnect"); | |||||
| USBHDBGSerial.printf("Bluetooth Disconnect"); | |||||
| if (device_driver_) { | if (device_driver_) { | ||||
| device_driver_->release_bluetooth(); | device_driver_->release_bluetooth(); | ||||
| device_driver_ = nullptr; | device_driver_ = nullptr; | ||||
| // received name back... | // received name back... | ||||
| { | { | ||||
| //BUGBUG:: probably want to grab string object and copy to | //BUGBUG:: probably want to grab string object and copy to | ||||
| Serial.printf(" Local name: %s\n", &rxbuf_[6]); | |||||
| USBHDBGSerial.printf(" Local name: %s\n", &rxbuf_[6]); | |||||
| /* | /* | ||||
| uint8_t len = rxbuf_[1]+2; // Length field +2 for total bytes read | uint8_t len = rxbuf_[1]+2; // Length field +2 for total bytes read | ||||
| for (uint8_t i=6; i < len; i++) { | for (uint8_t i=6; i < len; i++) { | ||||
| if (rxbuf_[i] == 0) { | if (rxbuf_[i] == 0) { | ||||
| break; | break; | ||||
| } | } | ||||
| Serial.printf("%c", rxbuf_[i]); | |||||
| USBHDBGSerial.printf("%c", rxbuf_[i]); | |||||
| } | } | ||||
| Serial.printf("\n"); */ | |||||
| USBHDBGSerial.printf("\n"); */ | |||||
| } | } | ||||
| break; | break; | ||||
| case Write_Connection_Accept_Timeout: //0x0c16 | case Write_Connection_Accept_Timeout: //0x0c16 | ||||
| { | { | ||||
| DBGPrintf(" BD Addr"); | DBGPrintf(" BD Addr"); | ||||
| for(uint8_t i = 0; i < 6; i++) { | for(uint8_t i = 0; i < 6; i++) { | ||||
| my_bdaddr[i] = rxbuf_[6 + i]; | |||||
| DBGPrintf(":%x", my_bdaddr[i]); | |||||
| my_bdaddr_[i] = rxbuf_[6 + i]; | |||||
| DBGPrintf(":%x", my_bdaddr_[i]); | |||||
| } | } | ||||
| DBGPrintf("\n"); | DBGPrintf("\n"); | ||||
| } | } | ||||
| 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"); | ||||
| } | } | ||||
| if (device_driver_) device_driver_->remoteNameComplete(&rxbuf_[9]); | |||||
| // Lets now try to accept the connection. | // Lets now try to accept the connection. | ||||
| sendHCIAcceptConnectionRequest(); | sendHCIAcceptConnectionRequest(); | ||||
| } | } |
| return; | return; | ||||
| } | } | ||||
| uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; | uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; | ||||
| //Serial.print("remain = "); | |||||
| //Serial.println(remain); | |||||
| //USBHDBGSerial.print("remain = "); | |||||
| //USBHDBGSerial.println(remain); | |||||
| if (microseconds < remain) { | if (microseconds < remain) { | ||||
| // this timer event is before any on the schedule | // this timer event is before any on the schedule | ||||
| __disable_irq(); | __disable_irq(); |
| USBHIDParser hid4(myusb); | USBHIDParser hid4(myusb); | ||||
| USBHIDParser hid5(myusb); | USBHIDParser hid5(myusb); | ||||
| JoystickController joystick1(myusb); | JoystickController joystick1(myusb); | ||||
| BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
| //BluetoothController bluet(myusb); // version assumes it already was paired | |||||
| //BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
| BluetoothController bluet(myusb); // version assumes it already was paired | |||||
| int user_axis[64]; | int user_axis[64]; | ||||
| uint32_t buttons_prev = 0; | uint32_t buttons_prev = 0; | ||||
| RawHIDController rawhid1(myusb); | RawHIDController rawhid1(myusb); | ||||
| #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | ||||
| const char * hid_driver_names[CNT_DEVICES] = {"Joystick1", "RawHid1", "RawHid2"}; | const char * hid_driver_names[CNT_DEVICES] = {"Joystick1", "RawHid1", "RawHid2"}; | ||||
| 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; | ||||
| uint64_t joystick_full_notify_mask = (uint64_t)-1; | uint64_t joystick_full_notify_mask = (uint64_t)-1; | ||||
| int psAxis[10]; | int psAxis[10]; | ||||
| bool first_joystick_message = true; | |||||
| void setup() | void setup() | ||||
| { | { | ||||
| Serial1.begin(115200); | |||||
| while (!Serial) ; // wait for Arduino Serial Monitor | while (!Serial) ; // wait for Arduino Serial Monitor | ||||
| Serial.println("\n\nUSB Host Testing"); | Serial.println("\n\nUSB Host Testing"); | ||||
| Serial.println(sizeof(USBHub), DEC); | Serial.println(sizeof(USBHub), DEC); | ||||
| } | } | ||||
| if (joystick1.available()) { | if (joystick1.available()) { | ||||
| if (first_joystick_message) { | |||||
| Serial.printf("*** First Joystick message %x:%x ***\n", | |||||
| joystick1.idVendor(), joystick1.idProduct()); | |||||
| first_joystick_message = false; | |||||
| const uint8_t *psz = joystick1.manufacturer(); | |||||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||||
| psz = joystick1.product(); | |||||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||||
| psz =joystick1.serialNumber(); | |||||
| if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||||
| } | |||||
| for (uint8_t i = 0; i<10; i++) { | for (uint8_t i = 0; i<10; i++) { | ||||
| psAxis[i] = joystick1.getAxisPS4(i); | |||||
| psAxis[i] = joystick1.getAxis(i); | |||||
| } | } | ||||
| Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[1], psAxis[2], psAxis[3], psAxis[4]); | Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[1], psAxis[2], psAxis[3], psAxis[4]); | ||||
| uint8_t ltv; | uint8_t ltv; | ||||
| uint8_t rtv; | uint8_t rtv; | ||||
| ltv = joystick1.getAxisPS4(8); | |||||
| rtv = joystick1.getAxisPS4(9); | |||||
| ltv = joystick1.getAxis(8); | |||||
| rtv = joystick1.getAxis(9); | |||||
| if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | ||||
| joystick_left_trigger_value = ltv; | joystick_left_trigger_value = ltv; | ||||
| joystick_right_trigger_value = rtv; | joystick_right_trigger_value = rtv; | ||||
| joystick1.setRumblePS4(ltv, rtv); | |||||
| joystick1.setRumble(ltv, rtv); | |||||
| } | } | ||||
| //tr=136,sq=24, cir=72, x=40 | |||||
| //lar=6, up=0, dw=4 rgt=2 | |||||
| //ltrb=1, rt =2 | |||||
| if (psAxis[6] != buttons_prev) { | |||||
| uint8_t lr = (psAxis[6] & 136) ? 0xff : 0; | |||||
| uint8_t lg = (psAxis[6] & 24) ? 0xff : 0; | |||||
| uint8_t lb = (psAxis[6] & 72) ? 0xff : 0; | |||||
| joystick1.setPS4LEDs(lr, lg, lb); | |||||
| buttons_prev = psAxis[6]; | |||||
| } | |||||
| joystick1.joystickDataClear(); | joystick1.joystickDataClear(); | ||||
| } | } | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | |||||
| } |
| USBHub hub1(myusb); | USBHub hub1(myusb); | ||||
| USBHub hub2(myusb); | USBHub hub2(myusb); | ||||
| KeyboardController keyboard1(myusb); | KeyboardController keyboard1(myusb); | ||||
| //KeyboardController keyboard2(myusb); | |||||
| KeyboardController keyboard2(myusb); | |||||
| USBHIDParser hid1(myusb); | USBHIDParser hid1(myusb); | ||||
| USBHIDParser hid2(myusb); | USBHIDParser hid2(myusb); | ||||
| USBHIDParser hid3(myusb); | USBHIDParser hid3(myusb); | ||||
| USBHIDParser hid4(myusb); | USBHIDParser hid4(myusb); | ||||
| USBHIDParser hid5(myusb); | USBHIDParser hid5(myusb); | ||||
| //MouseController mouse1(myusb); | |||||
| //JoystickController joystick1(myusb); | |||||
| BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
| //BluetoothController bluet(myusb); // version assumes it already was paired | |||||
| MouseController mouse1(myusb); | |||||
| JoystickController joystick1(myusb); | |||||
| //BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
| BluetoothController bluet(myusb); // version assumes it already was paired | |||||
| int user_axis[64]; | int user_axis[64]; | ||||
| uint32_t buttons_prev = 0; | uint32_t buttons_prev = 0; | ||||
| RawHIDController rawhid1(myusb); | RawHIDController rawhid1(myusb); | ||||
| RawHIDController rawhid2(myusb, 0xffc90004); | RawHIDController rawhid2(myusb, 0xffc90004); | ||||
| //USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
| USBDriver *drivers[] = {&hub1, &hub2, &keyboard1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
| USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
| #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | ||||
| //const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
| const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
| const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
| bool driver_active[CNT_DEVICES] = {false, false, false, false}; | bool driver_active[CNT_DEVICES] = {false, false, false, false}; | ||||
| // Lets also look at HID Input devices | // Lets also look at HID Input devices | ||||
| //USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2}; | |||||
| USBHIDInput *hiddrivers[] = {&rawhid1, &rawhid2}; | |||||
| USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2}; | |||||
| #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | ||||
| //const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1", "RawHid1", "RawHid2"}; | |||||
| const char * hid_driver_names[CNT_DEVICES] = {"RawHid1", "RawHid2"}; | |||||
| bool hid_driver_active[CNT_DEVICES] = {false, false, false}; | |||||
| const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1", "RawHid1", "RawHid2"}; | |||||
| bool hid_driver_active[CNT_DEVICES] = {false, false}; | |||||
| bool show_changed_only = false; | bool show_changed_only = false; | ||||
| uint8_t joystick_left_trigger_value = 0; | uint8_t joystick_left_trigger_value = 0; | ||||
| Serial.println(sizeof(USBHub), DEC); | Serial.println(sizeof(USBHub), DEC); | ||||
| myusb.begin(); | myusb.begin(); | ||||
| keyboard1.attachPress(OnPress); | keyboard1.attachPress(OnPress); | ||||
| //keyboard2.attachPress(OnPress); | |||||
| keyboard2.attachPress(OnPress); | |||||
| keyboard1.attachExtrasPress(OnHIDExtrasPress); | keyboard1.attachExtrasPress(OnHIDExtrasPress); | ||||
| keyboard1.attachExtrasRelease(OnHIDExtrasRelease); | keyboard1.attachExtrasRelease(OnHIDExtrasRelease); | ||||
| //keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||||
| //keyboard2.attachExtrasRelease(OnHIDExtrasRelease); | |||||
| keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||||
| keyboard2.attachExtrasRelease(OnHIDExtrasRelease); | |||||
| rawhid1.attachReceive(OnReceiveHidData); | rawhid1.attachReceive(OnReceiveHidData); | ||||
| rawhid2.attachReceive(OnReceiveHidData); | rawhid2.attachReceive(OnReceiveHidData); | ||||
| void loop() | void loop() | ||||
| { | { | ||||
| myusb.Task(); | myusb.Task(); | ||||
| /* | |||||
| if (Serial.available()) { | if (Serial.available()) { | ||||
| int ch = Serial.read(); // get the first char. | int ch = Serial.read(); // get the first char. | ||||
| while (Serial.read() != -1) ; | while (Serial.read() != -1) ; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| */ | |||||
| for (uint8_t i = 0; i < CNT_DEVICES; i++) { | for (uint8_t i = 0; i < CNT_DEVICES; i++) { | ||||
| if (*drivers[i] != driver_active[i]) { | if (*drivers[i] != driver_active[i]) { | ||||
| if (driver_active[i]) { | if (driver_active[i]) { | ||||
| } | } | ||||
| /* | |||||
| if(mouse1.available()) { | if(mouse1.available()) { | ||||
| Serial.print("Mouse: buttons = "); | Serial.print("Mouse: buttons = "); | ||||
| Serial.print(mouse1.getButtons()); | Serial.print(mouse1.getButtons()); | ||||
| Serial.println(); | Serial.println(); | ||||
| joystick1.joystickDataClear(); | joystick1.joystickDataClear(); | ||||
| } | } | ||||
| */ | |||||
| // See if we have some RAW data | // See if we have some RAW data | ||||
| if (rawhid1) { | if (rawhid1) { | ||||
| int ch; | int ch; | ||||
| Serial.print(keyboard1.getOemKey(), HEX); | Serial.print(keyboard1.getOemKey(), HEX); | ||||
| Serial.print(" LEDS: "); | Serial.print(" LEDS: "); | ||||
| Serial.println(keyboard1.LEDS(), HEX); | Serial.println(keyboard1.LEDS(), HEX); | ||||
| //} else { | |||||
| //Serial.print(keyboard2.getModifiers(), HEX); | |||||
| //Serial.print(" OEM: "); | |||||
| //Serial.print(keyboard2.getOemKey(), HEX); | |||||
| //Serial.print(" LEDS: "); | |||||
| //Serial.println(keyboard2.LEDS(), HEX); | |||||
| } else { | |||||
| Serial.print(keyboard2.getModifiers(), HEX); | |||||
| Serial.print(" OEM: "); | |||||
| Serial.print(keyboard2.getOemKey(), HEX); | |||||
| Serial.print(" LEDS: "); | |||||
| Serial.println(keyboard2.LEDS(), HEX); | |||||
| } | } | ||||
| //Serial.print("key "); | //Serial.print("key "); |
| // Called when the HID device sends a report | // Called when the HID device sends a report | ||||
| void USBHIDParser::in_data(const Transfer_t *transfer) | void USBHIDParser::in_data(const Transfer_t *transfer) | ||||
| { | { | ||||
| /*Serial.printf("HID: "); | |||||
| /*USBHDBGSerial.printf("HID: "); | |||||
| uint8_t *pb = (uint8_t*)transfer->buffer; | uint8_t *pb = (uint8_t*)transfer->buffer; | ||||
| for (uint8_t i = 0; i < transfer->length; i++) { | for (uint8_t i = 0; i < transfer->length; i++) { | ||||
| Serial.printf("%x ",pb[i]); | |||||
| USBHDBGSerial.printf("%x ",pb[i]); | |||||
| } | } | ||||
| Serial.printf("\n"); */ | |||||
| USBHDBGSerial.printf("\n"); */ | |||||
| print("HID: "); | print("HID: "); | ||||
| print(use_report_id); | print(use_report_id); | ||||
| } | } | ||||
| uminmax = true; | uminmax = true; | ||||
| } | } | ||||
| //Serial.printf("TU:%x US:%x %x %d %d: C:%d, %d, MM:%d, %x %x\n", topusage, usage_page, val, logical_min, logical_max, | |||||
| //USBHDBGSerial.printf("TU:%x US:%x %x %d %d: C:%d, %d, MM:%d, %x %x\n", topusage, usage_page, val, logical_min, logical_max, | |||||
| // report_count, usage_count, uminmax, usage[0], usage[1]); | // report_count, usage_count, uminmax, usage[0], usage[1]); | ||||
| for (uint32_t i=0; i < report_count; i++) { | for (uint32_t i=0; i < report_count; i++) { | ||||
| uint32_t u; | uint32_t u; |
| const uint8_t *JoystickController::manufacturer() | const uint8_t *JoystickController::manufacturer() | ||||
| { | { | ||||
| if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | ||||
| if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | |||||
| //if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | |||||
| if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| packet[6] = leds_[0]; // RGB value | packet[6] = leds_[0]; // RGB value | ||||
| 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 sedond? 2.5 seconds = 255 | |||||
| Serial.printf("Joystick update Rumble/LEDs"); | |||||
| // 9, 10 flash ON, OFF times in 100ths of second? 2.5 seconds = 255 | |||||
| USBHDBGSerial.printf("Joystick update Rumble/LEDs\n"); | |||||
| return driver_->sendPacket(packet, 32); | return driver_->sendPacket(packet, 32); | ||||
| } else if (btdriver_) { | } else if (btdriver_) { | ||||
| uint8_t packet[32]; | |||||
| uint8_t packet[79]; | |||||
| memset(packet, 0, sizeof(packet)); | memset(packet, 0, sizeof(packet)); | ||||
| //0xa2, 0x11, 0xc0, 0x20, 0xf0, 0x04, 0x00 | |||||
| packet[0] = 0x52; | |||||
| packet[1] = 0x11; // Report ID | |||||
| packet[2] = 0x80; | |||||
| //packet[3] = 0x20; | |||||
| packet[4] = 0xFF; | |||||
| packet[0] = 0x05; // Report ID | |||||
| packet[1]= 0xFF; | |||||
| packet[7] = rumble_lValue_; // Small Rumble | |||||
| packet[8] = rumble_rValue_; // Big rumble | |||||
| packet[9] = leds_[0]; // RGB value | |||||
| packet[10] = leds_[1]; | |||||
| packet[11] = leds_[2]; | |||||
| packet[4] = rumble_lValue_; // Small Rumble | |||||
| packet[5] = rumble_rValue_; // Big rumble | |||||
| packet[6] = leds_[0]; // RGB value | |||||
| packet[7] = leds_[1]; | |||||
| packet[8] = leds_[2]; | |||||
| // 9, 10 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 | // 9, 10 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 | ||||
| Serial.printf("Joystick update Rumble/LEDs"); | |||||
| btdriver_->sendL2CapCommand(packet, sizeof(packet)); | |||||
| USBHDBGSerial.printf("Joystick update Rumble/LEDs\n"); | |||||
| btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x42, 0x00); | |||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0; | txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0; | ||||
| txbuf_[4] = rumble_rValue_; // Big rumble | txbuf_[4] = rumble_rValue_; // Big rumble | ||||
| txbuf_[9] = leds_[0] << 1; // RGB value | txbuf_[9] = leds_[0] << 1; // RGB value | ||||
| //Serial.printf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[1], txbuf_[2], txbuf_[3], txbuf_[4], txbuf_[9]); | |||||
| //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_); | return driver_->sendControlPacket(0x21, 9, 0x201, 0, 48, txbuf_); | ||||
| } | } | ||||
| 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... | ||||
| } | } | ||||
| Serial.printf("Claim Additional axis: %x %x %d\n", additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_); | |||||
| USBHDBGSerial.printf("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) | ||||
| { | { | ||||
| //Serial.printf("Joystick: usage=%X, value=%d\n", usage, value); | |||||
| //USBHDBGSerial.printf("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. | ||||
| //Serial.printf("UP: usage_page=%x usage=%x User: %x %d\n", usage_page, usage, user_buttons_usage_start, user_buttons_count_); | |||||
| //USBHDBGSerial.printf("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. | ||||
| } | } | ||||
| //Serial.printf("UB: index=%x value=%x\n", usage_index, value); | |||||
| //USBHDBGSerial.printf("UB: index=%x value=%x\n", usage_index, value); | |||||
| } | } | ||||
| } else { | } else { | ||||
| Serial.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_); | |||||
| 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_); | |||||
| } | } | ||||
| // 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) | ||||
| { | { | ||||
| //Serial.printf("JoystickController::hid_process_out_data\n"); | |||||
| //USBHDBGSerial.printf("JoystickController::hid_process_out_data\n"); | |||||
| return true; | return true; | ||||
| } | } | ||||
| anychange = false; | anychange = false; | ||||
| axis_changed_mask_ = 0; | axis_changed_mask_ = 0; | ||||
| axis_mask_ = 0; | axis_mask_ = 0; | ||||
| ps4OnChange = 0; | |||||
| for(uint8_t i=0; i<10;i++) {axisChange[i] = 0; } | |||||
| } | } | ||||
| //***************************************************************************** | //***************************************************************************** | ||||
| 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++) Serial.printf("%02x ", pbuffer[i]); | |||||
| //Serial.printf("\n"); | |||||
| //for (uint8_t i = 0; i < transfer->length; i++) USBHDBGSerial.printf("%02x ", pbuffer[i]); | |||||
| //USBHDBGSerial.printf("\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)) { | ||||
| Serial.printf("JoystickController::claim_bluetooth TRUE\n"); | |||||
| USBHDBGSerial.printf("JoystickController::claim_bluetooth TRUE\n"); | |||||
| btdriver_ = driver; | btdriver_ = driver; | ||||
| btdevice = (Device_t*)driver; // remember this way | |||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| // 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 | ||||
| //Serial.printf("JoystickController::process_bluetooth_HID_data\n"); | |||||
| //USBHDBGSerial.printf("JoystickController::process_bluetooth_HID_data\n"); | |||||
| // May have to look at this one with other controllers... | |||||
| if (data[0] != 1) return false; | if (data[0] != 1) return false; | ||||
| //print(" Joystick Data: "); | //print(" Joystick Data: "); | ||||
| //print_hexbytes(data, length); | //print_hexbytes(data, length); | ||||
| //Serial.printf(" Joystick Data: "); | |||||
| //USBHDBGSerial.printf(" Joystick Data: "); | |||||
| uint64_t mask = 0x1; | |||||
| axis_mask_ = 0; | |||||
| axis_changed_mask_ = 0; | |||||
| for (uint16_t i = 0; i < length; i++ ) { | for (uint16_t i = 0; i < length; i++ ) { | ||||
| if(data[i] != axisPS4[i]) { ps4OnChange = 1; axisChange[i] = 1; } | |||||
| axisPS4[i] = data[i]; | |||||
| //Serial.printf("%02x ", axis[i]); | |||||
| axis_mask_ |= mask; | |||||
| if(data[i] != axis[i]) { | |||||
| axis_changed_mask_ |= mask; | |||||
| axis[i] = data[i]; | |||||
| } | |||||
| mask <<= 1; // shift down the mask. | |||||
| //USBHDBGSerial.printf("%02x ", axisPS4[i]); | |||||
| } | } | ||||
| //Serial.printf("\n"); | |||||
| joystickEvent = true; | |||||
| //USBHDBGSerial.printf("\n"); | |||||
| joystickEvent = true; | |||||
| connected_ = true; | connected_ = true; | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool JoystickController::setRumblePS4(uint8_t lValue, uint8_t rValue, uint8_t timeout) | |||||
| void JoystickController::remoteNameComplete(const uint8_t *remoteName) | |||||
| { | { | ||||
| /* uint8_t buf[79]; | |||||
| memset(buf, 0, sizeof(buf)); | |||||
| buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) | |||||
| buf[1] = 0x11; // Report ID | |||||
| buf[2] = 0x80; | |||||
| buf[4]= 0xFF; | |||||
| buf[7] = rumble_lValue_; // Small Rumble | |||||
| buf[8] = rumble_rValue_; // Big rumble | |||||
| buf[9] = leds_[0]; // Red | |||||
| buf[10] = leds_[1]; // Green | |||||
| buf[11] = leds_[2]; // Blue | |||||
| // 9, 10 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 | |||||
| Serial.printf("Joystick update Rumble/LEDs"); | |||||
| btdriver_->sendL2CapCommand(buf, sizeof(buf)); | |||||
| */ | |||||
| uint8_t packet[32]; | |||||
| memset(packet, 0, sizeof(packet)); | |||||
| //0xa2, 0x11, 0xc0, 0x20, 0xf0, 0x04, 0x00 | |||||
| packet[0] = 0x52; | |||||
| packet[1] = 0x11; // Report ID | |||||
| packet[2] = 0x80; | |||||
| //packet[3] = 0x20; | |||||
| packet[4] = 0xFF; | |||||
| // Sort of a hack, but try to map the name given from remote to a type... | |||||
| if (!remoteName) return; | |||||
| packet[7] = rumble_lValue_; // Small Rumble | |||||
| packet[8] = rumble_rValue_; // Big rumble | |||||
| packet[9] = leds_[0]; // RGB value | |||||
| packet[10] = leds_[1]; | |||||
| packet[11] = leds_[2]; | |||||
| // 9, 10 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 | |||||
| Serial.printf("Joystick update Rumble/LEDs"); | |||||
| btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x45, 0x00); | |||||
| if (strncmp((const char *)remoteName, "Wireless Controller", 19) == 0) { | |||||
| USBHDBGSerial.printf(" JoystickController::remoteNameComplete %s - set to PS4\n", remoteName); | |||||
| joystickType = PS4; | |||||
| } | |||||
| return true; | |||||
| } | } | ||||
| bool JoystickController::setPS4LEDs(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 | |||||
| // joystick types. | |||||
| if ((leds_[0] != lr) || (leds_[1] != lg) || (leds_[2] != lb)) { | |||||
| leds_[0] = lr; | |||||
| leds_[1] = lg; | |||||
| leds_[2] = lb; | |||||
| uint8_t packet[32]; | |||||
| memset(packet, 0, sizeof(packet)); | |||||
| //0xa2, 0x11, 0xc0, 0x20, 0xf0, 0x04, 0x00 | |||||
| packet[0] = 0x52; | |||||
| packet[1] = 0x11; // Report ID | |||||
| packet[2] = 0x80; | |||||
| packet[3] = 0x20; | |||||
| packet[4] = 0xFF; | |||||
| packet[7] = 0; // Small Rumble | |||||
| packet[8] = 0; // Big rumble | |||||
| packet[9] = leds_[0]; // RGB value | |||||
| packet[10] = leds_[1]; | |||||
| packet[11] = leds_[2]; | |||||
| // 9, 10 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 | |||||
| Serial.printf("Joystick update Rumble/LEDs"); | |||||
| btdriver_->sendL2CapCommand(packet, sizeof(packet)); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| void JoystickController::release_bluetooth() | void JoystickController::release_bluetooth() | ||||
| { | { | ||||
| btdevice = nullptr; // remember this way | |||||
| btdriver_ = nullptr; | btdriver_ = nullptr; | ||||
| connected_ = false; | connected_ = false; | ||||
| hidclaim_t KeyboardController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | hidclaim_t KeyboardController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | ||||
| { | { | ||||
| // Lets try to claim a few specific Keyboard related collection/reports | // Lets try to claim a few specific Keyboard related collection/reports | ||||
| //Serial.printf("KBH Claim %x\n", topusage); | |||||
| //USBHDBGSerial.printf("KBH Claim %x\n", topusage); | |||||
| if ((topusage != TOPUSAGE_SYS_CONTROL) | if ((topusage != TOPUSAGE_SYS_CONTROL) | ||||
| && (topusage != TOPUSAGE_CONSUMER_CONTROL) | && (topusage != TOPUSAGE_CONSUMER_CONTROL) | ||||
| ) return CLAIM_NO; | ) return CLAIM_NO; | ||||
| // only claim from one physical device | // only claim from one physical device | ||||
| //Serial.println("KeyboardController claim collection"); | |||||
| //USBHDBGSerial.println("KeyboardController claim collection"); | |||||
| // Lets only claim if this is the same device as claimed Keyboard... | // Lets only claim if this is the same device as claimed Keyboard... | ||||
| if (dev != device) return CLAIM_NO; | if (dev != device) return CLAIM_NO; | ||||
| if (mydevice != NULL && dev != mydevice) return CLAIM_NO; | if (mydevice != NULL && dev != mydevice) return CLAIM_NO; | ||||
| void KeyboardController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) | void KeyboardController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) | ||||
| { | { | ||||
| //Serial.printf("KPC:hid_input_begin TUSE: %x TYPE: %x Range:%x %x\n", topusage, type, lgmin, lgmax); | |||||
| //USBHDBGSerial.printf("KPC:hid_input_begin TUSE: %x TYPE: %x Range:%x %x\n", topusage, type, lgmin, lgmax); | |||||
| topusage_ = topusage; // remember which report we are processing. | topusage_ = topusage; // remember which report we are processing. | ||||
| hid_input_begin_ = true; | hid_input_begin_ = true; | ||||
| hid_input_data_ = false; | hid_input_data_ = false; | ||||
| { | { | ||||
| // Hack ignore 0xff00 high words as these are user values... | // Hack ignore 0xff00 high words as these are user values... | ||||
| if ((usage & 0xffff0000) == 0xff000000) return; | if ((usage & 0xffff0000) == 0xff000000) return; | ||||
| //Serial.printf("KeyboardController: topusage= %x usage=%X, value=%d\n", topusage_, usage, value); | |||||
| //USBHDBGSerial.printf("KeyboardController: topusage= %x usage=%X, value=%d\n", topusage_, usage, value); | |||||
| // See if the value is in our keys_down list | // See if the value is in our keys_down list | ||||
| usage &= 0xffff; // only keep the actual key | usage &= 0xffff; // only keep the actual key | ||||
| void KeyboardController::hid_input_end() | void KeyboardController::hid_input_end() | ||||
| { | { | ||||
| //Serial.println("KPC:hid_input_end"); | |||||
| //USBHDBGSerial.println("KPC:hid_input_end"); | |||||
| if (hid_input_begin_) { | if (hid_input_begin_) { | ||||
| // See if we received any data from parser if not, assume all keys released... | // See if we received any data from parser if not, assume all keys released... | ||||
| bool KeyboardController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class) | bool KeyboardController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class) | ||||
| { | { | ||||
| Serial.printf("Keyboard Controller::claim_bluetooth - Class %x\n", bluetooth_class); | |||||
| USBHDBGSerial.printf("Keyboard Controller::claim_bluetooth - Class %x\n", bluetooth_class); | |||||
| if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && (bluetooth_class & 0x40)) { | if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && (bluetooth_class & 0x40)) { | ||||
| Serial.printf("KeyboardController::claim_bluetooth TRUE\n"); | |||||
| USBHDBGSerial.printf("KeyboardController::claim_bluetooth TRUE\n"); | |||||
| //btdevice = driver; | //btdevice = driver; | ||||
| return true; | return true; | ||||
| } | } | ||||
| //BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 4 0 0 0 0 0 | //BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 4 0 0 0 0 0 | ||||
| //BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 0 0 0 0 0 0 | //BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 0 0 0 0 0 0 | ||||
| // So Len=9 passed in data starting at report ID=1... | // So Len=9 passed in data starting at report ID=1... | ||||
| Serial.printf("KeyboardController::process_bluetooth_HID_data\n"); | |||||
| USBHDBGSerial.printf("KeyboardController::process_bluetooth_HID_data\n"); | |||||
| if (data[0] != 1) return false; | if (data[0] != 1) return false; | ||||
| print(" KB Data: "); | print(" KB Data: "); | ||||
| print_hexbytes(data, length); | print_hexbytes(data, length); |
| void MouseController::hid_input_data(uint32_t usage, int32_t value) | void MouseController::hid_input_data(uint32_t usage, int32_t value) | ||||
| { | { | ||||
| //Serial.printf("Mouse: usage=%X, value=%d\n", usage, value); | |||||
| //USBHDBGSerial.printf("Mouse: 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 <= 8) { | if (usage_page == 9 && usage >= 1 && usage <= 8) { |
| void USBHost::print_(const Transfer_t *transfer) | void USBHost::print_(const Transfer_t *transfer) | ||||
| { | { | ||||
| if (!((uint32_t)transfer & 0xFFFFFFE0)) return; | if (!((uint32_t)transfer & 0xFFFFFFE0)) return; | ||||
| Serial.print("Transfer @ "); | |||||
| Serial.println(((uint32_t)transfer & 0xFFFFFFE0), HEX); | |||||
| Serial.print(" next: "); | |||||
| Serial.println(transfer->qtd.next, HEX); | |||||
| Serial.print(" anext: "); | |||||
| Serial.println(transfer->qtd.alt_next, HEX); | |||||
| Serial.print(" token: "); | |||||
| Serial.println(transfer->qtd.token, HEX); | |||||
| Serial.print(" bufs: "); | |||||
| USBHDBGSerial.print("Transfer @ "); | |||||
| USBHDBGSerial.println(((uint32_t)transfer & 0xFFFFFFE0), HEX); | |||||
| USBHDBGSerial.print(" next: "); | |||||
| USBHDBGSerial.println(transfer->qtd.next, HEX); | |||||
| USBHDBGSerial.print(" anext: "); | |||||
| USBHDBGSerial.println(transfer->qtd.alt_next, HEX); | |||||
| USBHDBGSerial.print(" token: "); | |||||
| USBHDBGSerial.println(transfer->qtd.token, HEX); | |||||
| USBHDBGSerial.print(" bufs: "); | |||||
| for (int i=0; i < 5; i++) { | for (int i=0; i < 5; i++) { | ||||
| Serial.print(transfer->qtd.buffer[i], HEX); | |||||
| if (i < 4) Serial.print(','); | |||||
| USBHDBGSerial.print(transfer->qtd.buffer[i], HEX); | |||||
| if (i < 4) USBHDBGSerial.print(','); | |||||
| } | } | ||||
| Serial.println(); | |||||
| USBHDBGSerial.println(); | |||||
| } | } | ||||
| void USBHost::print_(const Transfer_t *first, const Transfer_t *last) | void USBHost::print_(const Transfer_t *first, const Transfer_t *last) | ||||
| { | { | ||||
| Serial.print("Transfer Followup List "); | |||||
| Serial.print((uint32_t)first, HEX); | |||||
| Serial.print(" to "); | |||||
| Serial.println((uint32_t)last, HEX); | |||||
| Serial.println(" forward:"); | |||||
| USBHDBGSerial.print("Transfer Followup List "); | |||||
| USBHDBGSerial.print((uint32_t)first, HEX); | |||||
| USBHDBGSerial.print(" to "); | |||||
| USBHDBGSerial.println((uint32_t)last, HEX); | |||||
| USBHDBGSerial.println(" forward:"); | |||||
| while (first) { | while (first) { | ||||
| Serial.print(" "); | |||||
| Serial.print((uint32_t)first, HEX); | |||||
| USBHDBGSerial.print(" "); | |||||
| USBHDBGSerial.print((uint32_t)first, HEX); | |||||
| print_token(first->qtd.token); | print_token(first->qtd.token); | ||||
| first = first->next_followup; | first = first->next_followup; | ||||
| } | } | ||||
| Serial.println(" backward:"); | |||||
| USBHDBGSerial.println(" backward:"); | |||||
| while (last) { | while (last) { | ||||
| Serial.print(" "); | |||||
| Serial.print((uint32_t)last, HEX); | |||||
| USBHDBGSerial.print(" "); | |||||
| USBHDBGSerial.print((uint32_t)last, HEX); | |||||
| print_token(last->qtd.token); | print_token(last->qtd.token); | ||||
| last = last->prev_followup; | last = last->prev_followup; | ||||
| } | } | ||||
| { | { | ||||
| switch ((token >> 8) & 3) { | switch ((token >> 8) & 3) { | ||||
| case 0: | case 0: | ||||
| Serial.print(" OUT "); | |||||
| Serial.println((token >> 16) & 0x7FFF); | |||||
| USBHDBGSerial.print(" OUT "); | |||||
| USBHDBGSerial.println((token >> 16) & 0x7FFF); | |||||
| break; | break; | ||||
| case 1: | case 1: | ||||
| Serial.print(" IN "); | |||||
| Serial.println((token >> 16) & 0x7FFF); | |||||
| USBHDBGSerial.print(" IN "); | |||||
| USBHDBGSerial.println((token >> 16) & 0x7FFF); | |||||
| break; | break; | ||||
| case 2: | case 2: | ||||
| Serial.println(" SETUP"); | |||||
| USBHDBGSerial.println(" SETUP"); | |||||
| break; | break; | ||||
| default: | default: | ||||
| Serial.println(" unknown"); | |||||
| USBHDBGSerial.println(" unknown"); | |||||
| } | } | ||||
| } | } | ||||
| void USBHost::print_(const Pipe_t *pipe) | void USBHost::print_(const Pipe_t *pipe) | ||||
| { | { | ||||
| if (!((uint32_t)pipe & 0xFFFFFFE0)) return; | if (!((uint32_t)pipe & 0xFFFFFFE0)) return; | ||||
| Serial.print("Pipe "); | |||||
| if (pipe->type == 0) Serial.print("control"); | |||||
| else if (pipe->type == 1) Serial.print("isochronous"); | |||||
| else if (pipe->type == 2) Serial.print("bulk"); | |||||
| else if (pipe->type == 3) Serial.print("interrupt"); | |||||
| Serial.print(pipe->direction ? " IN" : " OUT"); | |||||
| Serial.print(" @ "); | |||||
| Serial.println((uint32_t)pipe, HEX); | |||||
| Serial.print(" horiz link: "); | |||||
| Serial.println(pipe->qh.horizontal_link, HEX); | |||||
| Serial.print(" capabilities: "); | |||||
| Serial.print(pipe->qh.capabilities[0], HEX); | |||||
| Serial.print(','); | |||||
| Serial.println(pipe->qh.capabilities[1], HEX); | |||||
| Serial.println(" overlay:"); | |||||
| Serial.print(" cur: "); | |||||
| Serial.println(pipe->qh.current, HEX); | |||||
| Serial.print(" next: "); | |||||
| Serial.println(pipe->qh.next, HEX); | |||||
| Serial.print(" anext: "); | |||||
| Serial.println(pipe->qh.alt_next, HEX); | |||||
| Serial.print(" token: "); | |||||
| Serial.println(pipe->qh.token, HEX); | |||||
| Serial.print(" bufs: "); | |||||
| USBHDBGSerial.print("Pipe "); | |||||
| if (pipe->type == 0) USBHDBGSerial.print("control"); | |||||
| else if (pipe->type == 1) USBHDBGSerial.print("isochronous"); | |||||
| else if (pipe->type == 2) USBHDBGSerial.print("bulk"); | |||||
| else if (pipe->type == 3) USBHDBGSerial.print("interrupt"); | |||||
| USBHDBGSerial.print(pipe->direction ? " IN" : " OUT"); | |||||
| USBHDBGSerial.print(" @ "); | |||||
| USBHDBGSerial.println((uint32_t)pipe, HEX); | |||||
| USBHDBGSerial.print(" horiz link: "); | |||||
| USBHDBGSerial.println(pipe->qh.horizontal_link, HEX); | |||||
| USBHDBGSerial.print(" capabilities: "); | |||||
| USBHDBGSerial.print(pipe->qh.capabilities[0], HEX); | |||||
| USBHDBGSerial.print(','); | |||||
| USBHDBGSerial.println(pipe->qh.capabilities[1], HEX); | |||||
| USBHDBGSerial.println(" overlay:"); | |||||
| USBHDBGSerial.print(" cur: "); | |||||
| USBHDBGSerial.println(pipe->qh.current, HEX); | |||||
| USBHDBGSerial.print(" next: "); | |||||
| USBHDBGSerial.println(pipe->qh.next, HEX); | |||||
| USBHDBGSerial.print(" anext: "); | |||||
| USBHDBGSerial.println(pipe->qh.alt_next, HEX); | |||||
| USBHDBGSerial.print(" token: "); | |||||
| USBHDBGSerial.println(pipe->qh.token, HEX); | |||||
| USBHDBGSerial.print(" bufs: "); | |||||
| for (int i=0; i < 5; i++) { | for (int i=0; i < 5; i++) { | ||||
| Serial.print(pipe->qh.buffer[i], HEX); | |||||
| if (i < 4) Serial.print(','); | |||||
| USBHDBGSerial.print(pipe->qh.buffer[i], HEX); | |||||
| if (i < 4) USBHDBGSerial.print(','); | |||||
| } | } | ||||
| Serial.println(); | |||||
| USBHDBGSerial.println(); | |||||
| const Transfer_t *t = (Transfer_t *)pipe->qh.next; | const Transfer_t *t = (Transfer_t *)pipe->qh.next; | ||||
| while (((uint32_t)t & 0xFFFFFFE0)) { | while (((uint32_t)t & 0xFFFFFFE0)) { | ||||
| print_(t); | print_(t); | ||||
| t = (Transfer_t *)t->qtd.next; | t = (Transfer_t *)t->qtd.next; | ||||
| } | } | ||||
| //Serial.print(); | |||||
| //USBHDBGSerial.print(); | |||||
| } | } | ||||
| void USBHost::print_driverlist(const char *name, const USBDriver *driver) | void USBHost::print_driverlist(const char *name, const USBDriver *driver) | ||||
| { | { | ||||
| Serial.print("USBDriver ("); | |||||
| Serial.print(name); | |||||
| Serial.print(") list: "); | |||||
| USBHDBGSerial.print("USBDriver ("); | |||||
| USBHDBGSerial.print(name); | |||||
| USBHDBGSerial.print(") list: "); | |||||
| if (driver == NULL) { | if (driver == NULL) { | ||||
| Serial.println("(empty"); | |||||
| USBHDBGSerial.println("(empty"); | |||||
| return; | return; | ||||
| } | } | ||||
| uint32_t count=0; | uint32_t count=0; | ||||
| for (const USBDriver *p = driver; p; p = p->next) { | for (const USBDriver *p = driver; p; p = p->next) { | ||||
| Serial.print((uint32_t)p, HEX); | |||||
| if (p->next) Serial.print(" -> "); | |||||
| USBHDBGSerial.print((uint32_t)p, HEX); | |||||
| if (p->next) USBHDBGSerial.print(" -> "); | |||||
| if (++count > 30) { | if (++count > 30) { | ||||
| Serial.println("abort:list too long"); | |||||
| USBHDBGSerial.println("abort:list too long"); | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| Serial.println(); | |||||
| USBHDBGSerial.println(); | |||||
| } | } | ||||
| void USBHost::print_qh_list(const Pipe_t *list) | void USBHost::print_qh_list(const Pipe_t *list) | ||||
| { | { | ||||
| if (!list) { | if (!list) { | ||||
| Serial.println("(empty)"); | |||||
| USBHDBGSerial.println("(empty)"); | |||||
| return; | return; | ||||
| } | } | ||||
| const Pipe_t *node = list; | const Pipe_t *node = list; | ||||
| while (1) { | while (1) { | ||||
| Serial.print((uint32_t)node, HEX); | |||||
| USBHDBGSerial.print((uint32_t)node, HEX); | |||||
| node = (const Pipe_t *)(node->qh.horizontal_link & 0xFFFFFFE0); | node = (const Pipe_t *)(node->qh.horizontal_link & 0xFFFFFFE0); | ||||
| if (!node) break; | if (!node) break; | ||||
| if (node == list) { | if (node == list) { | ||||
| Serial.print(" (loops)"); | |||||
| USBHDBGSerial.print(" (loops)"); | |||||
| break; | break; | ||||
| } | } | ||||
| Serial.print(" -> "); | |||||
| USBHDBGSerial.print(" -> "); | |||||
| } | } | ||||
| Serial.println(); | |||||
| USBHDBGSerial.println(); | |||||
| } | } | ||||
| static void print_class_subclass_protocol(uint8_t c, uint8_t s, uint8_t p) | static void print_class_subclass_protocol(uint8_t c, uint8_t s, uint8_t p) | ||||
| { | { | ||||
| Serial.print(c); | |||||
| if (c == 3) Serial.print("(HID)"); | |||||
| if (c == 8) Serial.print("(Mass Storage)"); | |||||
| if (c == 9) Serial.print("(Hub)"); | |||||
| Serial.print(" / "); | |||||
| Serial.print(s); | |||||
| if (c == 3 && s == 1) Serial.print("(Boot)"); | |||||
| if (c == 8 && s == 6) Serial.print("(SCSI)"); | |||||
| Serial.print(" / "); | |||||
| Serial.print(p); | |||||
| if (c == 3 && s == 1 && p == 1) Serial.print("(Keyboard)"); | |||||
| if (c == 3 && s == 1 && p == 2) Serial.print("(Mouse)"); | |||||
| if (c == 8 && s == 6 && p == 0x50) Serial.print("(Bulk Only)"); | |||||
| if (c == 8 && s == 6 && p == 0x62) Serial.print("(UAS)"); | |||||
| if (c == 9 && s == 0 && p == 1) Serial.print("(Single-TT)"); | |||||
| if (c == 9 && s == 0 && p == 2) Serial.print("(Multi-TT)"); | |||||
| Serial.println(); | |||||
| USBHDBGSerial.print(c); | |||||
| if (c == 3) USBHDBGSerial.print("(HID)"); | |||||
| if (c == 8) USBHDBGSerial.print("(Mass Storage)"); | |||||
| if (c == 9) USBHDBGSerial.print("(Hub)"); | |||||
| USBHDBGSerial.print(" / "); | |||||
| USBHDBGSerial.print(s); | |||||
| if (c == 3 && s == 1) USBHDBGSerial.print("(Boot)"); | |||||
| if (c == 8 && s == 6) USBHDBGSerial.print("(SCSI)"); | |||||
| USBHDBGSerial.print(" / "); | |||||
| USBHDBGSerial.print(p); | |||||
| if (c == 3 && s == 1 && p == 1) USBHDBGSerial.print("(Keyboard)"); | |||||
| if (c == 3 && s == 1 && p == 2) USBHDBGSerial.print("(Mouse)"); | |||||
| if (c == 8 && s == 6 && p == 0x50) USBHDBGSerial.print("(Bulk Only)"); | |||||
| if (c == 8 && s == 6 && p == 0x62) USBHDBGSerial.print("(UAS)"); | |||||
| if (c == 9 && s == 0 && p == 1) USBHDBGSerial.print("(Single-TT)"); | |||||
| if (c == 9 && s == 0 && p == 2) USBHDBGSerial.print("(Multi-TT)"); | |||||
| USBHDBGSerial.println(); | |||||
| } | } | ||||
| void USBHost::print_device_descriptor(const uint8_t *p) | void USBHost::print_device_descriptor(const uint8_t *p) | ||||
| { | { | ||||
| Serial.println("Device Descriptor:"); | |||||
| Serial.print(" "); | |||||
| USBHDBGSerial.println("Device Descriptor:"); | |||||
| USBHDBGSerial.print(" "); | |||||
| print_hexbytes(p, p[0]); | print_hexbytes(p, p[0]); | ||||
| if (p[0] != 18) { | if (p[0] != 18) { | ||||
| Serial.println("error: device must be 18 bytes"); | |||||
| USBHDBGSerial.println("error: device must be 18 bytes"); | |||||
| return; | return; | ||||
| } | } | ||||
| if (p[1] != 1) { | if (p[1] != 1) { | ||||
| Serial.println("error: device must type 1"); | |||||
| USBHDBGSerial.println("error: device must type 1"); | |||||
| return; | return; | ||||
| } | } | ||||
| Serial.printf(" VendorID = %04X, ProductID = %04X, Version = %04X", | |||||
| USBHDBGSerial.printf(" VendorID = %04X, ProductID = %04X, Version = %04X", | |||||
| p[8] | (p[9] << 8), p[10] | (p[11] << 8), p[12] | (p[13] << 8)); | p[8] | (p[9] << 8), p[10] | (p[11] << 8), p[12] | (p[13] << 8)); | ||||
| Serial.println(); | |||||
| Serial.print(" Class/Subclass/Protocol = "); | |||||
| USBHDBGSerial.println(); | |||||
| USBHDBGSerial.print(" Class/Subclass/Protocol = "); | |||||
| print_class_subclass_protocol(p[4], p[5], p[6]); | print_class_subclass_protocol(p[4], p[5], p[6]); | ||||
| Serial.print(" Number of Configurations = "); | |||||
| Serial.println(p[17]); | |||||
| USBHDBGSerial.print(" Number of Configurations = "); | |||||
| USBHDBGSerial.println(p[17]); | |||||
| } | } | ||||
| void USBHost::print_config_descriptor(const uint8_t *p, uint32_t maxlen) | void USBHost::print_config_descriptor(const uint8_t *p, uint32_t maxlen) | ||||
| { | { | ||||
| // Descriptor Types: (USB 2.0, page 251) | // Descriptor Types: (USB 2.0, page 251) | ||||
| Serial.println("Configuration Descriptor:"); | |||||
| Serial.print(" "); | |||||
| USBHDBGSerial.println("Configuration Descriptor:"); | |||||
| USBHDBGSerial.print(" "); | |||||
| print_hexbytes(p, p[0]); | print_hexbytes(p, p[0]); | ||||
| if (p[0] != 9) { | if (p[0] != 9) { | ||||
| Serial.println("error: config must be 9 bytes"); | |||||
| USBHDBGSerial.println("error: config must be 9 bytes"); | |||||
| return; | return; | ||||
| } | } | ||||
| if (p[1] != 2) { | if (p[1] != 2) { | ||||
| Serial.println("error: config must type 2"); | |||||
| USBHDBGSerial.println("error: config must type 2"); | |||||
| return; | return; | ||||
| } | } | ||||
| Serial.print(" NumInterfaces = "); | |||||
| Serial.println(p[4]); | |||||
| Serial.print(" ConfigurationValue = "); | |||||
| Serial.println(p[5]); | |||||
| USBHDBGSerial.print(" NumInterfaces = "); | |||||
| USBHDBGSerial.println(p[4]); | |||||
| USBHDBGSerial.print(" ConfigurationValue = "); | |||||
| USBHDBGSerial.println(p[5]); | |||||
| uint32_t len = p[2] | (p[3] << 8); | uint32_t len = p[2] | (p[3] << 8); | ||||
| if (len > maxlen) len = maxlen; | if (len > maxlen) len = maxlen; | ||||
| while (len > 0) { | while (len > 0) { | ||||
| if (p[0] > len) { | if (p[0] > len) { | ||||
| Serial.print(" "); | |||||
| USBHDBGSerial.print(" "); | |||||
| print_hexbytes(p, len); | print_hexbytes(p, len); | ||||
| Serial.println(" error: length beyond total data size"); | |||||
| USBHDBGSerial.println(" error: length beyond total data size"); | |||||
| break; | break; | ||||
| } | } | ||||
| Serial.print(" "); | |||||
| USBHDBGSerial.print(" "); | |||||
| print_hexbytes(p, p[0]); | print_hexbytes(p, p[0]); | ||||
| if (p[0] == 9 && p[1] == 4) { // Interface Descriptor | if (p[0] == 9 && p[1] == 4) { // Interface Descriptor | ||||
| Serial.print(" Interface = "); | |||||
| Serial.println(p[2]); | |||||
| Serial.print(" Number of endpoints = "); | |||||
| Serial.println(p[4]); | |||||
| Serial.print(" Class/Subclass/Protocol = "); | |||||
| USBHDBGSerial.print(" Interface = "); | |||||
| USBHDBGSerial.println(p[2]); | |||||
| USBHDBGSerial.print(" Number of endpoints = "); | |||||
| USBHDBGSerial.println(p[4]); | |||||
| USBHDBGSerial.print(" Class/Subclass/Protocol = "); | |||||
| print_class_subclass_protocol(p[5], p[6], p[7]); | print_class_subclass_protocol(p[5], p[6], p[7]); | ||||
| } else if (p[0] >= 7 && p[0] <= 9 && p[1] == 5) { // Endpoint Descriptor | } else if (p[0] >= 7 && p[0] <= 9 && p[1] == 5) { // Endpoint Descriptor | ||||
| Serial.print(" Endpoint = "); | |||||
| Serial.print(p[2] & 15); | |||||
| Serial.println((p[2] & 128) ? " IN" : " OUT"); | |||||
| Serial.print(" Type = "); | |||||
| USBHDBGSerial.print(" Endpoint = "); | |||||
| USBHDBGSerial.print(p[2] & 15); | |||||
| USBHDBGSerial.println((p[2] & 128) ? " IN" : " OUT"); | |||||
| USBHDBGSerial.print(" Type = "); | |||||
| switch (p[3] & 3) { | switch (p[3] & 3) { | ||||
| case 0: Serial.println("Control"); break; | |||||
| case 1: Serial.println("Isochronous"); break; | |||||
| case 2: Serial.println("Bulk"); break; | |||||
| case 3: Serial.println("Interrupt"); break; | |||||
| case 0: USBHDBGSerial.println("Control"); break; | |||||
| case 1: USBHDBGSerial.println("Isochronous"); break; | |||||
| case 2: USBHDBGSerial.println("Bulk"); break; | |||||
| case 3: USBHDBGSerial.println("Interrupt"); break; | |||||
| } | } | ||||
| Serial.print(" Max Size = "); | |||||
| Serial.println(p[4] | (p[5] << 8)); | |||||
| Serial.print(" Polling Interval = "); | |||||
| Serial.println(p[6]); | |||||
| USBHDBGSerial.print(" Max Size = "); | |||||
| USBHDBGSerial.println(p[4] | (p[5] << 8)); | |||||
| USBHDBGSerial.print(" Polling Interval = "); | |||||
| USBHDBGSerial.println(p[6]); | |||||
| } else if (p[0] == 8 && p[1] == 11) { // IAD | } else if (p[0] == 8 && p[1] == 11) { // IAD | ||||
| Serial.print(" Interface Association = "); | |||||
| Serial.print(p[2]); | |||||
| Serial.print(" through "); | |||||
| Serial.println(p[2] + p[3] - 1); | |||||
| Serial.print(" Class / Subclass / Protocol = "); | |||||
| USBHDBGSerial.print(" Interface Association = "); | |||||
| USBHDBGSerial.print(p[2]); | |||||
| USBHDBGSerial.print(" through "); | |||||
| USBHDBGSerial.println(p[2] + p[3] - 1); | |||||
| USBHDBGSerial.print(" Class / Subclass / Protocol = "); | |||||
| print_class_subclass_protocol(p[4], p[5], p[7]); | print_class_subclass_protocol(p[4], p[5], p[7]); | ||||
| } else if (p[0] >= 9 && p[1] == 0x21) { // HID | } else if (p[0] >= 9 && p[1] == 0x21) { // HID | ||||
| Serial.print(" HID, "); | |||||
| Serial.print(p[5]); | |||||
| Serial.print(" report descriptor"); | |||||
| if (p[5] != 1) Serial.print('s'); | |||||
| Serial.println(); | |||||
| USBHDBGSerial.print(" HID, "); | |||||
| USBHDBGSerial.print(p[5]); | |||||
| USBHDBGSerial.print(" report descriptor"); | |||||
| if (p[5] != 1) USBHDBGSerial.print('s'); | |||||
| USBHDBGSerial.println(); | |||||
| } | } | ||||
| len -= p[0]; | len -= p[0]; | ||||
| p += p[0]; | p += p[0]; | ||||
| { | { | ||||
| uint32_t len = p[0]; | uint32_t len = p[0]; | ||||
| if (len < 4) return; | if (len < 4) return; | ||||
| Serial.print(name); | |||||
| USBHDBGSerial.print(name); | |||||
| len -= 2; | len -= 2; | ||||
| p += 2; | p += 2; | ||||
| while (len >= 2) { | while (len >= 2) { | ||||
| uint32_t c = p[0] | (p[1] << 8); | uint32_t c = p[0] | (p[1] << 8); | ||||
| if (c < 0x80) { | if (c < 0x80) { | ||||
| Serial.write(c); | |||||
| USBHDBGSerial.write(c); | |||||
| } else if (c < 0x800) { | } else if (c < 0x800) { | ||||
| Serial.write((c >> 6) | 0xC0); | |||||
| Serial.write((c & 0x3F) | 0x80); | |||||
| USBHDBGSerial.write((c >> 6) | 0xC0); | |||||
| USBHDBGSerial.write((c & 0x3F) | 0x80); | |||||
| } else { | } else { | ||||
| Serial.write((c >> 12) | 0xE0); | |||||
| Serial.write(((c >> 6) & 0x3F) | 0x80); | |||||
| Serial.write((c & 0x3F) | 0x80); | |||||
| USBHDBGSerial.write((c >> 12) | 0xE0); | |||||
| USBHDBGSerial.write(((c >> 6) & 0x3F) | 0x80); | |||||
| USBHDBGSerial.write((c & 0x3F) | 0x80); | |||||
| } | } | ||||
| len -= 2; | len -= 2; | ||||
| p += 2; | p += 2; | ||||
| } | } | ||||
| Serial.println(); | |||||
| USBHDBGSerial.println(); | |||||
| //print_hexbytes(p, p[0]); | //print_hexbytes(p, p[0]); | ||||
| } | } | ||||
| if (ptr == NULL || len == 0) return; | if (ptr == NULL || len == 0) return; | ||||
| const uint8_t *p = (const uint8_t *)ptr; | const uint8_t *p = (const uint8_t *)ptr; | ||||
| do { | do { | ||||
| if (*p < 16) Serial.print('0'); | |||||
| Serial.print(*p++, HEX); | |||||
| Serial.print(' '); | |||||
| if (*p < 16) USBHDBGSerial.print('0'); | |||||
| USBHDBGSerial.print(*p++, HEX); | |||||
| USBHDBGSerial.print(' '); | |||||
| } while (--len); | } while (--len); | ||||
| Serial.println(); | |||||
| USBHDBGSerial.println(); | |||||
| } | } | ||||
| #endif | #endif |
| { | { | ||||
| // only claim RAWHID devices currently: 16c0:0486 | // only claim RAWHID devices currently: 16c0:0486 | ||||
| #ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
| Serial.printf("Rawhid Claim: %x:%x usage: %x\n", dev->idVendor, dev->idProduct, topusage); | |||||
| USBHDBGSerial.printf("Rawhid Claim: %x:%x usage: %x\n", dev->idVendor, dev->idProduct, topusage); | |||||
| #endif | #endif | ||||
| if ((dev->idVendor != 0x16c0 || (dev->idProduct) != 0x486)) return CLAIM_NO; | if ((dev->idVendor != 0x16c0 || (dev->idProduct) != 0x486)) return CLAIM_NO; | ||||
| bool RawHIDController::hid_process_in_data(const Transfer_t *transfer) | bool RawHIDController::hid_process_in_data(const Transfer_t *transfer) | ||||
| { | { | ||||
| #ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
| Serial.printf("RawHIDController::hid_process_in_data: %x\n", usage_); | |||||
| USBHDBGSerial.printf("RawHIDController::hid_process_in_data: %x\n", usage_); | |||||
| #endif | #endif | ||||
| if (receiveCB) { | if (receiveCB) { | ||||
| bool RawHIDController::hid_process_out_data(const Transfer_t *transfer) | bool RawHIDController::hid_process_out_data(const Transfer_t *transfer) | ||||
| { | { | ||||
| #ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
| Serial.printf("RawHIDController::hid_process_out_data: %x\n", usage_); | |||||
| USBHDBGSerial.printf("RawHIDController::hid_process_out_data: %x\n", usage_); | |||||
| #endif | #endif | ||||
| return true; | return true; | ||||
| } | } | ||||
| // These should not be called as we are claiming the whole interface and not | // These should not be called as we are claiming the whole interface and not | ||||
| // allowing the parse to happen | // allowing the parse to happen | ||||
| #ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
| Serial.printf("RawHID::hid_input_begin %x %x %x %x\n", topusage, type, lgmin, lgmax); | |||||
| USBHDBGSerial.printf("RawHID::hid_input_begin %x %x %x %x\n", topusage, type, lgmin, lgmax); | |||||
| #endif | #endif | ||||
| //hid_input_begin_ = true; | //hid_input_begin_ = true; | ||||
| } | } | ||||
| // These should not be called as we are claiming the whole interface and not | // These should not be called as we are claiming the whole interface and not | ||||
| // allowing the parse to happen | // allowing the parse to happen | ||||
| #ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
| Serial.printf("RawHID: usage=%X, value=%d", usage, value); | |||||
| if ((value >= ' ') && (value <='~')) Serial.printf("(%c)", value); | |||||
| Serial.println(); | |||||
| USBHDBGSerial.printf("RawHID: usage=%X, value=%d", usage, value); | |||||
| if ((value >= ' ') && (value <='~')) USBHDBGSerial.printf("(%c)", value); | |||||
| USBHDBGSerial.println(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| // These should not be called as we are claiming the whole interface and not | // These should not be called as we are claiming the whole interface and not | ||||
| // allowing the parse to happen | // allowing the parse to happen | ||||
| #ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
| Serial.println("RawHID::hid_input_end"); | |||||
| USBHDBGSerial.println("RawHID::hid_input_end"); | |||||
| #endif | #endif | ||||
| // if (hid_input_begin_) { | // if (hid_input_begin_) { | ||||
| // hid_input_begin_ = false; | // hid_input_begin_ = false; |