diff --git a/USBHost_t36.h b/USBHost_t36.h index e47408d..0d406bf 100644 --- a/USBHost_t36.h +++ b/USBHost_t36.h @@ -603,7 +603,11 @@ class USBHIDParser : public USBDriver { public: USBHIDParser(USBHost &host) { init(); } static void driver_ready_for_hid_collection(USBHIDInput *driver); - bool sendPacket(const uint8_t *buffer); + bool sendPacket(const uint8_t *buffer, int cb=-1); + void setTXBuffers(uint8_t *buffer1, uint8_t *buffer2, uint8_t cb); + + bool sendControlPacket(uint32_t bmRequestType, uint32_t bRequest, + uint32_t wValue, uint32_t wIndex, uint32_t wLength, void *buf); protected: enum { TOPUSAGE_LIST_LEN = 4 }; enum { USAGE_LIST_LEN = 24 }; @@ -783,9 +787,19 @@ public: bool available() { return joystickEvent; } void joystickDataClear(); uint32_t getButtons() { return buttons; } - int getAxis(uint32_t index) { return (index < (sizeof(axis)/sizeof(axis[0]))) ? axis[index] : 0; } - uint32_t axisMask() {return axis_mask_;} - enum { AXIS_COUNT = 10 }; + int getAxis(uint32_t index) { return (index < (sizeof(axis)/sizeof(axis[0]))) ? axis[index] : 0; } + uint64_t axisMask() {return axis_mask_;} + uint64_t axisChangedMask() { return axis_changed_mask_;} + uint64_t axisChangeNotifyMask() {return axis_change_notify_mask_;} + void axisChangeNotifyMask(uint64_t notify_mask) {axis_change_notify_mask_ = notify_mask;} + + // 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, + 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} joytype_t; + joytype_t joystickType = UNKNOWN; protected: // From USBDriver virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); @@ -798,16 +812,34 @@ protected: virtual void hid_input_data(uint32_t usage, int32_t value); virtual void hid_input_end(); virtual void disconnect_collection(Device_t *dev); + virtual bool hid_process_out_data(const Transfer_t *transfer); private: // Class specific void init(); + USBHIDParser *driver_ = nullptr; + joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices); + bool transmitPS4UserFeedbackMsg(); + bool transmitPS3UserFeedbackMsg(); bool anychange = false; volatile bool joystickEvent = false; uint32_t buttons = 0; - int axis[AXIS_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t axis_mask_ = 0; // which axis have valid data + int axis[TOTAL_AXIS_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint64_t axis_mask_ = 0; // which axis have valid data + uint64_t axis_changed_mask_ = 0; + uint64_t axis_change_notify_mask_ = 0x3ff; // assume the low 10 values only. + + uint16_t additional_axis_usage_page_ = 0; + uint16_t additional_axis_usage_start_ = 0; + uint16_t additional_axis_usage_count_ = 0; + + // State values to output to Joystick. + uint8_t rumble_lValue_ = 0; + uint8_t rumble_rValue_ = 0; + uint8_t rumble_timeout_ = 0; + uint8_t leds_[3] = {0,0,0}; + // Used by HID code uint8_t collections_claimed = 0; @@ -827,11 +859,13 @@ private: Pipe_t *rxpipe_; Pipe_t *txpipe_; uint8_t rxbuf_[64]; // receive circular buffer - + uint8_t txbuf_[64]; // buffer to use to send commands to joystick // Mapping table to say which devices we handle typedef struct { uint16_t idVendor; uint16_t idProduct; + joytype_t joyType; + bool hidDevice; } product_vendor_mapping_t; static product_vendor_mapping_t pid_vid_mapping[]; diff --git a/examples/Mouse/Mouse.ino b/examples/Mouse/Mouse.ino index 8950e2f..d98d00c 100644 --- a/examples/Mouse/Mouse.ino +++ b/examples/Mouse/Mouse.ino @@ -9,7 +9,6 @@ USBHub hub1(myusb); USBHub hub2(myusb); KeyboardController keyboard1(myusb); KeyboardController keyboard2(myusb); -//KeyboardHIDExtrasController hidextras(myusb); USBHIDParser hid1(myusb); USBHIDParser hid2(myusb); USBHIDParser hid3(myusb); @@ -17,6 +16,8 @@ USBHIDParser hid4(myusb); USBHIDParser hid5(myusb); MouseController mouse1(myusb); JoystickController joystick1(myusb); +int user_axis[64]; +uint32_t buttons_prev = 0; RawHIDController rawhid1(myusb); RawHIDController rawhid2(myusb, 0xffc90004); @@ -30,7 +31,11 @@ USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2}; #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1", "RawHid1", "RawHid2"}; bool hid_driver_active[CNT_DEVICES] = {false, false}; +bool show_changed_only = false; +uint8_t joystick_left_trigger_value = 0; +uint8_t joystick_right_trigger_value = 0; +uint64_t joystick_full_notify_mask = (uint64_t)-1; void setup() { @@ -54,6 +59,27 @@ void loop() { myusb.Task(); + if (Serial.available()) { + int ch = Serial.read(); // get the first char. + while (Serial.read() != -1) ; + if ((ch == 'b') || (ch == 'B')) { + Serial.println("Only notify on Basic Axis changes"); + joystick1.axisChangeNotifyMask(0x3ff); + } else if ((ch == 'f') || (ch == 'F')) { + Serial.println("Only notify on Full Axis changes"); + joystick1.axisChangeNotifyMask(joystick_full_notify_mask); + + } else { + if (show_changed_only) { + show_changed_only = false; + Serial.println("\n*** Show All fields mode ***"); + } else { + show_changed_only = true; + Serial.println("\n*** Show only changed fields mode ***"); + } + } + } + for (uint8_t i = 0; i < CNT_DEVICES; i++) { if (*drivers[i] != driver_active[i]) { if (driver_active[i]) { @@ -109,14 +135,75 @@ void loop() mouse1.mouseDataClear(); } if (joystick1.available()) { - uint32_t axis_mask = joystick1.axisMask(); + uint64_t axis_mask = joystick1.axisMask(); + uint64_t axis_changed_mask = joystick1.axisChangedMask(); Serial.print("Joystick: buttons = "); - Serial.print(joystick1.getButtons(), HEX); - for (uint8_t i = 0; axis_mask != 0; i++, axis_mask >>= 1) { - if (axis_mask & 1) { - Serial.printf(" %d:%d", i, joystick1.getAxis(i)); + uint32_t buttons = joystick1.getButtons(); + Serial.print(buttons, HEX); + //Serial.printf(" AMasks: %x %x:%x", axis_mask, (uint32_t)(user_axis_mask >> 32), (uint32_t)(user_axis_mask & 0xffffffff)); + //Serial.printf(" M: %lx %lx", axis_mask, joystick1.axisChangedMask()); + if (show_changed_only) { + for (uint8_t i = 0; axis_changed_mask != 0; i++, axis_changed_mask >>= 1) { + if (axis_changed_mask & 1) { + Serial.printf(" %d:%d", i, joystick1.getAxis(i)); + } + } + + } else { + for (uint8_t i = 0; axis_mask != 0; i++, axis_mask >>= 1) { + if (axis_mask & 1) { + Serial.printf(" %d:%d", i, joystick1.getAxis(i)); + } } } + uint8_t ltv; + uint8_t rtv; + switch (joystick1.joystickType) { + default: + break; + case JoystickController::PS4: + ltv = joystick1.getAxis(3); + rtv = joystick1.getAxis(4); + if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { + joystick_left_trigger_value = ltv; + joystick_right_trigger_value = rtv; + joystick1.setRumble(ltv, rtv); + } + break; + + case JoystickController::PS3: + ltv = joystick1.getAxis(18); + rtv = joystick1.getAxis(19); + if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { + joystick_left_trigger_value = ltv; + joystick_right_trigger_value = rtv; + joystick1.setRumble(ltv, rtv, 50); + } + break; + + case JoystickController::XBOXONE: + ltv = joystick1.getAxis(4); + rtv = joystick1.getAxis(5); + if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { + joystick_left_trigger_value = ltv; + joystick_right_trigger_value = rtv; + joystick1.setRumble(ltv, rtv); + Serial.printf(" Set Rumble %d %d", ltv, rtv); + } + break; + } + if (buttons != buttons_prev) { + if (joystick1.joystickType == JoystickController::PS3) { + joystick1.setLEDs((buttons>>12) & 0xf); // try to get to TRI/CIR/X/SQuare + } else { + uint8_t lr = (buttons & 1)? 0xff : 0; + uint8_t lg = (buttons & 2)? 0xff : 0; + uint8_t lb = (buttons & 4)? 0xff : 0; + joystick1.setLEDs(lr, lg, lb); + } + buttons_prev = buttons; + } + Serial.println(); joystick1.joystickDataClear(); } diff --git a/hid.cpp b/hid.cpp index 3a8bd0a..367558a 100644 --- a/hid.cpp +++ b/hid.cpp @@ -205,13 +205,12 @@ void USBHIDParser::disconnect() // Called when the HID device sends a report void USBHIDParser::in_data(const Transfer_t *transfer) { - /*Serial.print("HID: "); + /*Serial.printf("HID: "); uint8_t *pb = (uint8_t*)transfer->buffer; for (uint8_t i = 0; i < transfer->length; i++) { - Serial.print(pb[i], HEX); - Serial.print(" "); + Serial.printf("%x ",pb[i]); } - Serial.println(); */ + Serial.printf("\n"); */ print("HID: "); print(use_report_id); @@ -249,7 +248,7 @@ void USBHIDParser::out_data(const Transfer_t *transfer) } } -bool USBHIDParser::sendPacket(const uint8_t *buffer) { +bool USBHIDParser::sendPacket(const uint8_t *buffer, int cb) { if (!out_size || !out_pipe) return false; if (!tx1) { // Was not init before, for now lets put it at end of descriptor @@ -259,22 +258,40 @@ bool USBHIDParser::sendPacket(const uint8_t *buffer) { tx2 = tx1 - out_size; } if ((txstate & 3) == 3) return false; // both transmit buffers are full + if (cb == -1) + cb = out_size; uint8_t *p = tx1; if ((txstate & 1) == 0) { txstate |= 1; } else { + if (!tx2) + return false; // only one buffer txstate |= 2; p = tx2; } // copy the users data into our out going buffer - memcpy(p, buffer, out_size); + memcpy(p, buffer, cb); println("USBHIDParser Send packet"); - print_hexbytes(buffer, out_size); - queue_Data_Transfer(out_pipe, p, out_size, this); + print_hexbytes(buffer, cb); + queue_Data_Transfer(out_pipe, p, cb, this); println(" Queue_data transfer returned"); return true; } +void USBHIDParser::setTXBuffers(uint8_t *buffer1, uint8_t *buffer2, uint8_t cb) +{ + tx1 = buffer1; + tx2 = buffer2; +} + +bool USBHIDParser::sendControlPacket(uint32_t bmRequestType, uint32_t bRequest, + uint32_t wValue, uint32_t wIndex, uint32_t wLength, void *buf) +{ + // Use setup structure to build packet + mk_setup(setup, bmRequestType, bRequest, wValue, wIndex, wLength); // ps3 tell to send report 1? + return queue_Control_Transfer(device, &setup, buf, this); +} + // This no-inputs parse is meant to be used when we first get the // HID report descriptor. It finds all the top level collections @@ -444,6 +461,7 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3 uint16_t report_size = 0; uint16_t report_count = 0; uint16_t usage_page = 0; + uint32_t last_usage = 0; int32_t logical_min = 0; int32_t logical_max = 0; uint32_t bitindex = 0; @@ -551,23 +569,38 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3 if ((val & 2)) { // ordinary variable format uint32_t uindex = 0; + uint32_t uindex_max = 0xffff; // assume no MAX bool uminmax = false; - if (usage_count > USAGE_LIST_LEN || usage_count == 0) { + if (usage_count > USAGE_LIST_LEN) { // usage numbers by min/max, not from list uindex = usage[0]; + uindex_max = usage[1]; + uminmax = true; + } else if ((report_count > 1) && (usage_count <= 1)) { + // Special cases: Either only one or no usages specified and there are more than one + // report counts . + if (usage_count == 1) { + uindex = usage[0]; + } else { + // BUGBUG:: Not sure good place to start? maybe round up from last usage to next higher group up of 0x100? + uindex = (last_usage & 0xff00) + 0x100; + } 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, + // report_count, usage_count, uminmax, usage[0], usage[1]); for (uint32_t i=0; i < report_count; i++) { uint32_t u; if (uminmax) { u = uindex; - if (uindex < usage[1]) uindex++; + if (uindex < uindex_max) uindex++; } else { u = usage[uindex++]; if (uindex >= USAGE_LIST_LEN-1) { uindex = USAGE_LIST_LEN-1; } } + last_usage = u; // remember the last one we used... u |= (uint32_t)usage_page << 16; print(" usage = ", u, HEX); diff --git a/joystick.cpp b/joystick.cpp index 9513127..7df3a7d 100644 --- a/joystick.cpp +++ b/joystick.cpp @@ -27,6 +27,18 @@ #define print USBHost::print_ #define println USBHost::println_ +// PID/VID to joystick mapping - Only the XBOXOne is used to claim the USB interface directly, +// The others are used after claim-hid code to know which one we have and to use it for +// doing other features. +JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = { + { 0x045e, 0x02ea, XBOXONE, false },{ 0x045e, 0x02dd, XBOXONE, false }, + { 0x054C, 0x0268, PS3, true}, + { 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true } +}; + + + +//----------------------------------------------------------------------------- void JoystickController::init() { contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); @@ -36,6 +48,19 @@ void JoystickController::init() USBHIDParser::driver_ready_for_hid_collection(this); } +//----------------------------------------------------------------------------- +JoystickController::joytype_t JoystickController::mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices) +{ + for (uint8_t i = 0; i < (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0])); i++) { + if ((idVendor == pid_vid_mapping[i].idVendor) && (idProduct == pid_vid_mapping[i].idProduct)) { + println("Match PID/VID: ", i, DEC); + if (exclude_hid_devices && pid_vid_mapping[i].hidDevice) return UNKNOWN; + return pid_vid_mapping[i].joyType; + } + } + return UNKNOWN; // Not in our list +} + //***************************************************************************** // Some simple query functions depend on which interface we are using... //***************************************************************************** @@ -76,9 +101,109 @@ const uint8_t *JoystickController::serialNumber() } +bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeout) +{ + // 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. + rumble_lValue_ = lValue; + rumble_rValue_ = rValue; + rumble_timeout_ = timeout; + + switch (joystickType) { + default: + break; + case PS3: + return transmitPS3UserFeedbackMsg(); + case PS4: + return transmitPS4UserFeedbackMsg(); + case XBOXONE: + // Lets try sending a request to the XBox 1. + txbuf_[0] = 0x9; + txbuf_[1] = 0x8; + txbuf_[2] = 0x0; + txbuf_[3] = 0x08; // Substructure (what substructure rest of this packet has) + txbuf_[4] = 0x00; // Mode + txbuf_[5] = 0x0f; // Rumble mask (what motors are activated) (0000 lT rT L R) + txbuf_[6] = 0x0; // lT force + txbuf_[7] = 0x0; // rT force + txbuf_[8] = lValue; // L force + txbuf_[9] = rValue; // R force + txbuf_[10] = 0x80; // Length of pulse + txbuf_[11] = 0x00; // Period between pulses + if (!queue_Data_Transfer(txpipe_, txbuf_, 12, this)) { + println("XBoxOne rumble transfer fail"); + } + return true; // + } + 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 + // joystick types. + if ((leds_[0] != lr) || (leds_[1] != lg) || (leds_[2] != lb)) { + leds_[0] = lr; + leds_[1] = lg; + leds_[2] = lb; + + switch (joystickType) { + case PS3: + return transmitPS3UserFeedbackMsg(); + case PS4: + return transmitPS4UserFeedbackMsg(); + default: + return false; + } + } + return false; +} + +bool JoystickController::transmitPS4UserFeedbackMsg() { +if (!driver_) return false; + uint8_t packet[32]; + memset(packet, 0, sizeof(packet)); + + packet[0] = 0x05; // Report ID + packet[1]= 0xFF; + + 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 + Serial.printf("Joystick update Rumble/LEDs"); + return driver_->sendPacket(packet, 32); +} + +static const uint8_t PS3_USER_FEEDBACK_INIT[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + +bool JoystickController::transmitPS3UserFeedbackMsg() { +if (!driver_) return false; + memcpy(txbuf_, PS3_USER_FEEDBACK_INIT, 48); + + txbuf_[1] = rumble_lValue_? rumble_timeout_ : 0; + txbuf_[2] = rumble_lValue_; // Small Rumble + txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0; + txbuf_[4] = rumble_rValue_; // Big rumble + txbuf_[9] = leds_[0] << 1; // RGB value + //Serial.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_); +} //***************************************************************************** -// Support for Joysticks that USe HID data. +// Support for Joysticks that Use HID data. //***************************************************************************** hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) @@ -90,6 +215,31 @@ hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t * mydevice = dev; collections_claimed++; anychange = true; // always report values on first read + driver_ = driver; // remember the driver. + driver_->setTXBuffers(txbuf_, nullptr, sizeof(txbuf_)); + + // Lets see if we know what type of joystick this is. That is, is it a PS3 or PS4 or ... + joystickType = mapVIDPIDtoJoystickType(mydevice->idVendor, mydevice->idProduct, false); + switch (joystickType) { + case PS3: + additional_axis_usage_page_ = 0x1; + additional_axis_usage_start_ = 0x100; + additional_axis_usage_count_ = 39; + axis_change_notify_mask_ = (uint64_t)-1; // Start off assume all bits + break; + case PS4: + additional_axis_usage_page_ = 0xFF00; + additional_axis_usage_start_ = 0x21; + additional_axis_usage_count_ = 54; + axis_change_notify_mask_ = (uint64_t)0xfffffffffffff3ffl; // Start off assume all bits - 10 and 11 + break; + default: + additional_axis_usage_page_ = 0; + additional_axis_usage_start_ = 0; + additional_axis_usage_count_ = 0; + 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_); return CLAIM_REPORT; } @@ -97,7 +247,9 @@ void JoystickController::disconnect_collection(Device_t *dev) { if (--collections_claimed == 0) { mydevice = NULL; + driver_ = nullptr; axis_mask_ = 0; + axis_changed_mask_ = 0; } } @@ -131,8 +283,32 @@ void JoystickController::hid_input_data(uint32_t usage, int32_t value) axis_mask_ |= (1 << i); // Keep record of which axis we have data on. if (axis[i] != value) { axis[i] = value; - anychange = true; + axis_changed_mask_ |= (1 << i); + if (axis_changed_mask_ & axis_change_notify_mask_) + anychange = true; } + } else if (usage_page == additional_axis_usage_page_) { + // 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_); + if ((usage >= additional_axis_usage_start_) && (usage < (additional_axis_usage_start_ + additional_axis_usage_count_))) { + // We are in the user range. + uint16_t usage_index = usage - additional_axis_usage_start_ + STANDARD_AXIS_COUNT; + if (usage_index < (sizeof(axis)/sizeof(axis[0]))) { + if (axis[usage_index] != value) { + axis[usage_index] = value; + if (usage_index > 63) usage_index = 63; // don't overflow our mask + axis_changed_mask_ |= ((uint64_t)1 << usage_index); // Keep track of which ones changed. + if (axis_changed_mask_ & axis_change_notify_mask_) + anychange = true; // We have changes... + } + 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); + } + + } 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_); + } // TODO: hat switch? } @@ -144,18 +320,23 @@ void JoystickController::hid_input_end() } } +bool JoystickController::hid_process_out_data(const Transfer_t *transfer) +{ + Serial.printf("JoystickController::hid_process_out_data\n"); + return true; +} + void JoystickController::joystickDataClear() { joystickEvent = false; anychange = false; + axis_changed_mask_ = 0; + axis_mask_ = 0; } //***************************************************************************** // Support for Joysticks that are class specific and do not use HID // Example: XBox One controller. //***************************************************************************** -// Note: currently just XBOX one. -JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = { - { 0x045e, 0x02ea },{ 0x045e, 0x02dd } }; static uint8_t start_input[] = {0x05, 0x20, 0x00, 0x01, 0x00}; @@ -167,15 +348,12 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto if (type != 0) return false; print_hexbytes(descriptors, len); - uint8_t i = 0; - for (; i < (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0])); i++) { - if ((dev->idVendor == pid_vid_mapping[i].idVendor) && (dev->idProduct == pid_vid_mapping[i].idProduct)) { - break; - } - } - if (i == (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0]))) return false; // Not in our list + JoystickController::joytype_t jtype = mapVIDPIDtoJoystickType(dev->idVendor, dev->idProduct, true); + println("Jtype=", (uint8_t)jtype, DEC); + if (jtype == UNKNOWN) + return false; - // 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 4 5 *6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1... + // 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 4 5 *6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1... // 09 04 00 00 02 FF 47 D0 00 07 05 02 03 40 00 04 07 05 82 03 40 00 04 09 04 01 00 00 FF 47 D0 00 // Lets do some verifications to make sure. @@ -226,6 +404,7 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto queue_Data_Transfer(txpipe_, start_input, sizeof(start_input), this); memset(axis, 0, sizeof(axis)); // clear out any data. + joystickType = jtype; // remember we are an XBox One. return true; } @@ -280,6 +459,7 @@ void JoystickController::rx_data(const Transfer_t *transfer) // print("JoystickController::rx_data: "); // print_hexbytes((uint8_t*)transfer->buffer, transfer->length); axis_mask_ = 0x3f; + axis_changed_mask_ = 0; // assume none for now xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer; if ((xb1d->type == 0x20) && (transfer->length >= sizeof (xbox1data20_t))) { // We have a data transfer. Lets see what is new... @@ -309,6 +489,7 @@ void JoystickController::tx_data(const Transfer_t *transfer) void JoystickController::disconnect() { axis_mask_ = 0; + axis_changed_mask_ = 0; // TODO: free resources } diff --git a/keywords.txt b/keywords.txt index 5df2d68..8cbfb19 100644 --- a/keywords.txt +++ b/keywords.txt @@ -81,6 +81,15 @@ getWheelH KEYWORD2 joystickDataClear KEYWORD2 getAxis KEYWORD2 axisMask KEYWORD2 +axisChangedMask KEYWORD2 +axisChangeNotifyMask KEYWORD2 +userAxisMask KEYWORD2 +setRumbleOn KEYWORD2 +setLEDs KEYWORD2 +joystickType KEYWORD2 +PS3 LITERAL1 +PS4 LITERAL1 +XBOXONE LITERAL1 # USBSerial USBHOST_SERIAL_7E1 LITERAL1