Supporting HID objects in Arduino_USBHostMbed5

As I mentioned in the other thread:

I was curious about how hard it would be to support some different USB Objects like Mouse and Keyboards using the Arduino_USBHostMbed5 library. There is some support in the library USBHostGIGA. I am assuming you cannot use both of these libraries within a single sketch.

support USBLS (low speed) devices within Arduino_USBHostMbed5. I have a version that is at least somewhat working. It is a fork/branch based off of @BobTheDog fork/branch that is associated with a current Pull request.

Once I clean up the changes and his PR or other derivation of it is pulled in, I will issue PR for the LS devices.

HID Support
Sorry not sure if anyone else will be interested in this stuff, and this first pass information is probably disjoint and the like, but...

There is a simple HID Call back class:

class USBHostHIDParserCB {
public:
  virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) {};
  virtual void hid_input_data(uint32_t usage, int32_t value);
  virtual void hid_input_end() {};
};

And simple HID parser class:

class USBHostHIDParser {
public:
  bool init(USBHost *host, USBDeviceConnected *dev, uint8_t index, uint16_t len);
  void parse(const uint8_t *data, uint16_t len);

  inline void attach(USBHostHIDParserCB *hidCB) {
    hidCB_ = hidCB;
  }
...
private:
...
};

My mouse and keyboard objects contain an instance of this class and are derived from the call back class.

USBHostHIDParser hidParser;

class USBHostMouseEx : public IUSBEnumerator, public USBHostHIDParserCB {
public:

When a device is connected code initializes the hidParser object:

bool USBHostMouseEx::connect() {

  if (dev_connected) {
    return true;
  }
  host = USBHost::getHostInst();

  for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
    if ((dev = host->getDevice(i)) != NULL) {

      int ret = host->enumerate(dev, this);
      if (ret) {
        break;
      }


      if (mouse_device_found) {
        {
          /* As this is done in a specific thread
                     * this lock is taken to avoid to process the device
                     * disconnect in usb process during the device registering */
          USBHost::Lock Lock(host);

          int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN);

          if (!int_in) {
            break;
          }

          USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf);
          dev->setName("Mouse", mouse_intf);
          host->registerDriver(dev, mouse_intf, this, &USBHostMouseEx::init);

          int_in->attach(this, &USBHostMouseEx::rxHandler);
          size_in_ = int_in->getSize();

          hidParser.init(host, dev, mouse_intf, hid_descriptor_size_);
          hidParser.attach(this);
        }
        host->interruptRead(dev, int_in, buf_in_, size_in_, false);

        dev_connected = true;
        return true;
      }
    }
  }
  init();
  return false;
}

Most of this is pretty much like boiler plate stuff, except the two lines:

          hidParser.init(host, dev, mouse_intf, hid_descriptor_size_);
          hidParser.attach(this);

The init call, is passed in the interface number, for the HID. Note you potentially might have multiple HID interfaces. For Mouse I pass in the information from the first Interface and for Keyboard I pass it in for the second.

You also pass in the size of the HID descriptor (Or some larger value).

The USBHost code in the main library, when it detects a Config item that contains the size of the HID Descriptor, it stores it away. I know normally devices, first declare their interface descriptor, followed by the End points.

So in the function asking if we want to use some end point, I ask for this and store it away:
/virtual/ bool USBHostMouseEx::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type,

ENDPOINT_DIRECTION dir)  //Must return true if the endpoint will be used
{
  printf("intf_nb: %d\n", intf_nb);
  printf(" ??? HID Report size: %u\n", host->getLengthReportDescr());
  if (intf_nb == mouse_intf) {
    if (type == INTERRUPT_ENDPOINT && dir == IN) {
      mouse_device_found = true;
      hid_descriptor_size_ = host->getLengthReportDescr();
      return true;
    }
  }
  return false;
}

The call: hidParser.attach(this); will then give a pointer to our main object to the parser object.

The Mouse object implements all three of the main call back functions:

/*virtual*/ void USBHostMouseEx::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) {
  //printf("Mouse HID Begin(%lx %lx %d %d)\n", topusage, type, lgmin, lgmax);
  hid_input_begin_ = true;
}

/*virtual*/ void USBHostMouseEx::hid_input_end() {
  //printf("Mouse HID end()\n");
  if (hid_input_begin_) {
    mouseEvent = true;
    hid_input_begin_ = false;
  }
}

/*virtual*/ void USBHostMouseEx::hid_input_data(uint32_t usage, int32_t value) {
  //printf("Mouse: usage=%lX, value=%ld\n", usage, value);
  uint32_t usage_page = usage >> 16;
  usage &= 0xFFFF;
  if (usage_page == 9 && usage >= 1 && usage <= 8) {
    if (value == 0) {
      buttons &= ~(1 << (usage - 1));
    } else {
      buttons |= (1 << (usage - 1));
    }
  } else if (usage_page == 1) {
    switch (usage) {
      case 0x30:
        mouseX = value;
        break;
      case 0x31:
        mouseY = value;
        break;
      case 0x32:  // Apple uses this for horizontal scroll
        wheelH = value;
        break;
      case 0x38:
        wheel = value;
        break;
    }
  } else if (usage_page == 12) {
    if (usage == 0x238) {  // Microsoft uses this for horizontal scroll
      wheelH = value;
    }
  }
}

When the device sends us a new data record, my RX Handler code passes it off to the parser like:

void USBHostMouseEx::rxHandler() {
  int len = int_in->getLengthTransferred();

  if (len) {
    //Serial.println("$$$ Extras HID RX $$$");
    //MemoryHexDump(Serial, buf_in_, len, true, nullptr, -1, 0);
    hidParser.parse(buf_in_, len);
  }

  host->interruptRead(dev, int_in, buf_in_, size_in_, false);
}

The Parser code will walk through the data.
The most important part is for each field it sees it will call our method:
/virtual/ void USBHostMouseEx::hid_input_data(uint32_t usage, int32_t value) {

The usage values are the upper 2 bytes is the Usage Page and the bottom two is the usage number within that page:

These numbers are defined in the USB Hid Usage Table document (HUT)
Which you can download from:
HID Usage Tables 1.4 | USB-IF

In the case of a Mouse, most of the details are from
Usage 1 - General Desktop page: including X, Y...
Usage 9 - Button Page: the buttons on the mouse

Probably enough for first draft:
The code is up at:
KurtE/GIGA_USBHostMBed5_devices: Some USB Host device extension to Arduino_USBHostMBed5 library (github.com)

And again this is just an experiment!

2 Likes

When we were playing on the Teensy with USBHost one of the things we tested was Logitech type devices that use 2.4ghz dongles like:

Amazon.com: Logitech Wireless Touch Keyboard K400 Plus with Built-In Touchpad for Internet-Connected TVs (Renewed) : Electronics

and worked with no issues so gave it a try with your Keyboard example and it WORKED!!!!

Example output

Key pressed: 61(a)
Keycode: 4 mod: 0
Key released: 61(a)
Key pressed: 73(s)
Keycode: 16 mod: 0
Key released: 73(s)
Key pressed: 64(d)
Keycode: 7 mod: 0
Key released: 64(d)
Key pressed: 66(f)
Keycode: 9 mod: 0
Key released: 66(f)
Key pressed: 67(g)
Keycode: A mod: 0
Key released: 67(g)
1 Like

Sounds like fun.

At some point, will probably try a few more of the dongles. Many of them are setup that handle a mouse and/or keyboard, and some may not have worked unless you initialized both parts. Been awhile!

Also since we are mostly doing this for our own fun, not sure how far to take it.

For example I have at least two keyboards, that do N-Key rollover. If I remember correctly one of them, always returned the data in none boot format. i.e. using their own HID descriptor.

The other one worked like other keyboards in boot mode, where first byte is the modifiers, 2nd byte ignored and 2-7 were keycodes. But if more keys were pressed fhe first N were in the Boot record and others came through the 2nd HID interface...

Maybe I should plug one in and see what it does

Gigabyte:



*** starting Device information sketch ***
Device:0x2400c72c
VID: 4D9, PID: a06b

----------------------------------------
Device Descriptor:
  bcdUSB: 512
  bDeviceClass: 0
  bDeviceSubClass: 0
  bDeviceProtocol: 0
  bMaxPacketSize: 8
  idVendor: 0x4d9
  idProduct: 0xa06b
  bcdDevice: 770
  iManufacturer: 1
  iProduct: 2
  iSerialNumber: 0
  bNumConfigurations: 1
Manufacturer: E-Signal
Product: GIGABYTE Keyboard
Speed: 0

----------------------------------------
Size of configuration Descriptor: 84
Configuration Descriptor
2400E8E8 - 09 02 54 00 03 01 00 A0  32 09 04 00 00 01 03 01  : ..T..... 2.......
2400E8F8 - 01 00 09 21 10 01 00 01  22 3B 00 07 05 81 03 08  : ...!.... ";......
2400E908 - 00 08 09 04 01 00 01 03  00 00 00 09 21 10 01 00  : ........ ....!...
2400E918 - 01 22 51 00 07 05 82 03  10 00 08 09 04 02 00 01  : ."Q..... ........
2400E928 - 03 00 00 00 09 21 10 01  00 01 22 25 00 07 05 83  : .....!.. .."%....
2400E938 - 03 10 00 01                                       : ....
Config:
 wTotalLength: 84
 bNumInterfaces: 3
 bConfigurationValue: 1
 iConfiguration: 0
 bmAttributes: 160
 bMaxPower: 50
****************************************
** Interface level **
  bInterfaceNumber: 0
  bAlternateSetting: 0
  Number of endpoints: 1
  bInterfaceClass: 3
  bInterfaceSubClass: 1
    HID (BOOT)
  bInterfaceProtocol: 1
    Keyboard
  iInterface: 0
  HID Descriptor size: 59
  Endpoint: 81 In
    Attrributes: 3 Interrupt
    Size: 8
    Interval: 8
>>>>> USBDumperDevice::getHIDDesc(0) called <<<<< 
2400E948 - 05 01 09 06 A1 01 05 08  15 00 25 01 19 01 29 03  : ........ ..%...).
2400E958 - 75 01 95 03 91 02 95 05  91 01 05 07 19 E0 29 E7  : u....... ......).
2400E968 - 75 01 95 08 81 02 95 08  81 01 15 00 26 FF 00 19  : u....... ....&...
2400E978 - 00 2A FF 00 75 08 95 06  81 00 C0 00 00 00 00 00  : .*..u... ........

HID Report Descriptor (0x2400e948) size: 64
  05 01	// Usage Page(1) - Generic Desktop
  09 06	// Usage(6) -(Keyboard)
  A1 01	// Collection(1) top Usage(10000)
    05 08	// Usage Page(8) - LEDs
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    19 01	// Usage Minimum(1) - 
    29 03	// Usage Maximum(3) - 
    75 01	// Report Size(1)
    95 03	// Report Count(3)
    91 02	// Output(2)	// (Data, Variable, Absolute)
    95 05	// Report Count(5)
    91 01	// Output(1)	// (Constant, Array, Absolute)
    05 07	// Usage Page(7) - Keycode
    19 E0	// Usage Minimum(e0) - (Left Control)
    29 E7	// Usage Maximum(e7) - (Right GUI)
    75 01	// Report Size(1)
    95 08	// Report Count(8)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    95 08	// Report Count(8)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    15 00	// Logical Minimum(0)
    26 FF 00	// Logical maximum(ff)
    19 00	// Usage Minimum(0) - (Keycode 0)
    2A FF 00	// Usage Maximum(ff) - (Keycode 255)
    75 08	// Report Size(8)
    95 06	// Report Count(6)
    81 00	// Input(0)	// (Data, Array, Absolute)
    C0	// End Collection
  00
  00
  00
  00
  00

--------------------
* Top usage summary
--------------------
Report ID: 0: 10000
--------------------
****************************************
** Interface level **
  bInterfaceNumber: 1
  bAlternateSetting: 0
  Number of endpoints: 1
  bInterfaceClass: 3
  bInterfaceSubClass: 0
    HID
  bInterfaceProtocol: 0
    None
  iInterface: 0
  HID Descriptor size: 81
  Endpoint: 82 In
    Attrributes: 3 Interrupt
    Size: 16
    Interval: 8
>>>>> USBDumperDevice::getHIDDesc(1) called <<<<< 
2400E948 - 05 01 09 80 A1 01 85 02  19 81 29 83 15 00 25 01  : ........ ..)...%.
2400E958 - 75 01 95 03 81 02 95 05  81 01 C0 05 0C 09 01 A1  : u....... ........
2400E968 - 01 85 03 19 00 2A FF 02  15 00 26 FF 7F 95 01 75  : .....*.. ..&....u
2400E978 - 10 81 00 C0 06 00 FF 09  01 A1 01 85 06 15 00 26  : ........ .......&
2400E988 - FF 00 09 2F 75 08 95 03  81 02 09 30 95 07 B1 02  : .../u... ...0....
2400E998 - C0 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........
2400E9A8 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........
2400E9B8 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........

HID Report Descriptor (0x2400e948) size: 128
  05 01	// Usage Page(1) - Generic Desktop
  09 80	// Usage(80) -(?)
  A1 01	// Collection(1) top Usage(10080)
    85 02	// Report ID(2)
    19 81	// Usage Minimum(81) - (System Power Down)
    29 83	// Usage Maximum(83) - (System Wake Up)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    75 01	// Report Size(1)
    95 03	// Report Count(3)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    95 05	// Report Count(5)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    C0	// End Collection
  05 0C	// Usage Page(c) - Consumer
  09 01	// Usage(1) -(Consumer Controls)
  A1 01	// Collection(1) top Usage(c0000)
    85 03	// Report ID(3)
    19 00	// Usage Minimum(0) - (?)
    2A FF 02	// Usage Maximum(2ff) - (?)
    15 00	// Logical Minimum(0)
    26 FF 7F	// Logical maximum(7fff)
    95 01	// Report Count(1)
    75 10	// Report Size(10)
    81 00	// Input(0)	// (Data, Array, Absolute)
    C0	// End Collection
  06 00 FF	// Usage Page(ff00) - Vendor Defined
  09 01	// Usage(1) -
  A1 01	// Collection(1) top Usage(ff000000)
    85 06	// Report ID(6)
    15 00	// Logical Minimum(0)
    26 FF 00	// Logical maximum(ff)
    09 2F	// Usage(2f) -
    75 08	// Report Size(8)
    95 03	// Report Count(3)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    09 30	// Usage(30) -
    95 07	// Report Count(7)
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    C0	// End Collection
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00

--------------------
* Top usage summary
--------------------
Report ID: 0: 10080
Report ID: 2: c0000
Report ID: 3: ff000000
--------------------
****************************************
** Interface level **
  bInterfaceNumber: 2
  bAlternateSetting: 0
  Number of endpoints: 1
  bInterfaceClass: 3
  bInterfaceSubClass: 0
    HID
  bInterfaceProtocol: 0
    None
  iInterface: 0
  HID Descriptor size: 37
  Endpoint: 83 In
    Attrributes: 3 Interrupt
    Size: 16
    Interval: 1
>>>>> USBDumperDevice::getHIDDesc(2) called <<<<< 
2400E948 - 05 01 09 06 A1 01 05 07  19 E0 29 E7 15 00 25 01  : ........ ..)...%.
2400E958 - 75 01 95 08 81 02 19 00  29 6F 15 00 25 01 75 01  : u....... )o..%.u.
2400E968 - 95 70 81 02 C0 2A FF 02  15 00 26 FF 7F 95 01 75  : .p...*.. ..&....u
2400E978 - 10 81 00 C0 06 00 FF 09  01 A1 01 85 06 15 00 26  : ........ .......&

HID Report Descriptor (0x2400e948) size: 64
  05 01	// Usage Page(1) - Generic Desktop
  09 06	// Usage(6) -(Keyboard)
  A1 01	// Collection(1) top Usage(10000)
    05 07	// Usage Page(7) - Keycode
    19 E0	// Usage Minimum(e0) - (Left Control)
    29 E7	// Usage Maximum(e7) - (Right GUI)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    75 01	// Report Size(1)
    95 08	// Report Count(8)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    19 00	// Usage Minimum(0) - (Keycode 0)
    29 6F	// Usage Maximum(6f) - (F20)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    75 01	// Report Size(1)
    95 70	// Report Count(70)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    C0	// End Collection
  2A FF 02	// Usage Maximum(2ff) - (Keycode 767)
  15 00	// Logical Minimum(0)
  26 FF 7F	// Logical maximum(7fff)
  95 01	// Report Count(1)
  75 10	// Report Size(10)
  81 00	// Input(0)	// (Data, Array, Absolute)
  C0	// End Collection
  06 00 FF	// Usage Page(ff00) - Vendor Defined
  09 01	// Usage(1) -
  A1 01	// Collection(1) top Usage(ff000000)
    85 06	// Report ID(6)
    15 00	// Logical Minimum(0)
    26 FF 00
--------------------
* Top usage summary
--------------------
Report ID: 0: 10000 ff000000
--------------------
parseInterface nb:0
 bInterfaceClass = 3
 bInterfaceSubClass = 1
    HID (BOOT)
 bProtocol = 1
    Keyboard
useEndpoint(0, 3, 2)
parseInterface nb:1
 bInterfaceClass = 3
 bInterfaceSubClass = 0
    HID
 bProtocol = 0
    None
parseInterface nb:2
 bInterfaceClass = 3
 bInterfaceSubClass = 0
    HID
 bProtocol = 0
    None
New Debug device: VID:04d9 PID:a06b [dev: 0x2400c72c - intf: 0]
USB host device(4d9:a06b) connected
Manufacturer: E-Signal
Product: GIGABYTE Keyboard

Does not respond...

1 Like

:slight_smile:
quote="KurtE, post:3, topic:1189281"]
Also since we are mostly doing this for our own fun, not sure how far to take it.
[/quote]

Ditto. Unfortunately my gigabyte keyboard is attached to my PC so can't be of much help there.:slight_smile:

My PC has the other one... The Kenesis ....
Tomorrow...

Pushed up some changes that allows the gigabyte keyboard to work.
I added the table I had with other USB Host for which keyboards to force into boot mode...
This was the main one...

I also pushed up some changes to the HID Dumper sketch, it was not properly showing the top level usages...

One of the next things I am curious about...
Is does the system support physical devices which have multiple Interfaces for different things.

For example I have a dongle from Microsoft that handles both a mouse and a keyboard.
Can I define a Mouse object and a Keyboard object and both of them connect up to this same hardware device...

Here is a HID dump...

No USB host device connected
No USB host device connected
Device:0x2400c72c
VID: 45E, PID: 7a5

----------------------------------------
Device Descriptor:
  bcdUSB: 512
  bDeviceClass: 0
  bDeviceSubClass: 0
  bDeviceProtocol: 0
  bMaxPacketSize: 64
  idVendor: 0x45e
  idProduct: 0x7a5
  bcdDevice: 1943
  iManufacturer: 1
  iProduct: 2
  iSerialNumber: 0
  bNumConfigurations: 1
Manufacturer: Microsoft
Product: Microsoftďż˝ 2.4GHz Transceiver v9.0
Speed: 0

----------------------------------------
Size of configuration Descriptor: 84
Configuration Descriptor
2400E8E8 - 09 02 54 00 03 01 00 A0  32 09 04 00 00 01 03 01  : ..T..... 2.......
2400E8F8 - 01 00 09 21 11 01 00 01  22 4B 00 07 05 81 03 08  : ...!.... "K......
2400E908 - 00 04 09 04 01 00 01 03  01 02 00 09 21 11 01 00  : ........ ....!...
2400E918 - 01 22 DF 00 07 05 82 03  0A 00 01 09 04 02 00 01  : ."...... ........
2400E928 - 03 00 00 00 09 21 11 01  00 01 22 28 01 07 05 83  : .....!.. .."(....
2400E938 - 03 20 00 01                                       : . ..
Config:
 wTotalLength: 84
 bNumInterfaces: 3
 bConfigurationValue: 1
 iConfiguration: 0
 bmAttributes: 160
 bMaxPower: 50
****************************************
** Interface level **
  bInterfaceNumber: 0
  bAlternateSetting: 0
  Number of endpoints: 1
  bInterfaceClass: 3
  bInterfaceSubClass: 1
    HID (BOOT)
  bInterfaceProtocol: 1
    Keyboard
  iInterface: 0
  HID Descriptor size: 75
  Endpoint: 81 In
    Attrributes: 3 Interrupt
    Size: 8
    Interval: 4
>>>>> USBDumperDevice::getHIDDesc(0) called <<<<< 
2400E948 - 05 01 09 06 A1 01 05 08  19 01 29 03 15 00 25 01  : ........ ..)...%.
2400E958 - 75 01 95 03 91 02 95 05  91 01 05 07 1A E0 00 2A  : u....... .......*
2400E968 - E7 00 95 08 81 02 75 08  95 01 81 01 19 00 2A 91  : ......u. ......*.
2400E978 - 00 26 FF 00 95 06 81 00  05 0C 0A C0 02 A1 02 1A  : .&...... ........
2400E988 - C1 02 2A C6 02 95 06 B1  03 C0 C0 00 00 00 00 00  : ..*..... ........
2400E998 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........
...	 1 duplicate line(s) removed.
2400E9B8 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........

HID Report Descriptor (0x2400e948) size: 128
  05 01	// Usage Page(1) - Generic Desktop
  09 06	// Usage(6) -(Keyboard)
  A1 01	// Collection(1) top Usage(10006)
    05 08	// Usage Page(8) - LEDs
    19 01	// Usage Minimum(1) - 
    29 03	// Usage Maximum(3) - 
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    75 01	// Report Size(1)
    95 03	// Report Count(3)
    91 02	// Output(2)	// (Data, Variable, Absolute)
    95 05	// Report Count(5)
    91 01	// Output(1)	// (Constant, Array, Absolute)
    05 07	// Usage Page(7) - Keycode
    1A E0 00	// Usage Minimum(e0) - (Left Control)
    2A E7 00	// Usage Maximum(e7) - (Right GUI)
    95 08	// Report Count(8)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    75 08	// Report Size(8)
    95 01	// Report Count(1)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    19 00	// Usage Minimum(0) - (Keycode 0)
    2A 91 00	// Usage Maximum(91) - (Keycode 145)
    26 FF 00	// Logical maximum(ff)
    95 06	// Report Count(6)
    81 00	// Input(0)	// (Data, Array, Absolute)
    05 0C	// Usage Page(c) - Consumer
    0A C0 02	// Usage(2c0) -(?)
    A1 02	// Collection(2)
    1A C1 02	// Usage Minimum(2c1) - (?)
    2A C6 02	// Usage Maximum(2c6) - (?)
    95 06	// Report Count(6)
    B1 03	// Feature(3)	// (Constant, Variable, Absolute)
    C0	// End Collection
  C0	// End Collection
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00

--------------------
* Top usage summary
--------------------
Report ID: 0: 10006
--------------------
****************************************
** Interface level **
  bInterfaceNumber: 1
  bAlternateSetting: 0
  Number of endpoints: 1
  bInterfaceClass: 3
  bInterfaceSubClass: 1
    HID (BOOT)
  bInterfaceProtocol: 2
    Mouse
  iInterface: 0
  HID Descriptor size: 223
  Endpoint: 82 In
    Attrributes: 3 Interrupt
    Size: 10
    Interval: 1
>>>>> USBDumperDevice::getHIDDesc(1) called <<<<< 
2400E948 - 05 01 09 02 A1 01 05 01  09 02 A1 02 85 1A 09 01  : ........ ........
2400E958 - A1 00 05 09 19 01 29 05  95 05 75 01 15 00 25 01  : ......). ..u...%.
2400E968 - 81 02 75 03 95 01 81 01  05 01 09 30 09 31 95 02  : ..u..... ...0.1..
2400E978 - 75 10 16 01 80 26 FF 7F  81 06 A1 02 85 12 09 48  : u....&.. .......H
2400E988 - 95 01 75 02 15 00 25 01  35 01 45 0C B1 02 85 1A  : ..u...%. 5.E.....
2400E998 - 09 38 35 00 45 00 95 01  75 10 16 01 80 26 FF 7F  : .85.E... u....&..
2400E9A8 - 81 06 C0 A1 02 85 12 09  48 75 02 15 00 25 01 35  : ........ Hu...%.5
2400E9B8 - 01 45 0C B1 02 35 00 45  00 75 04 B1 01 85 1A 05  : .E...5.E .u......
2400E9C8 - 0C 95 01 75 10 16 01 80  26 FF 7F 0A 38 02 81 06  : ...u.... &...8...
2400E9D8 - C0 C0 C0 C0 05 0C 09 01  A1 01 05 01 09 02 A1 02  : ........ ........
2400E9E8 - 85 1F 05 0C 0A 38 02 95  01 75 10 16 01 80 26 FF  : .....8.. .u....&.
2400E9F8 - 7F 81 06 85 17 06 00 FF  0A 06 FF 0A 0F FF 15 00  : ........ ........
2400EA08 - 25 01 35 01 45 0C 95 02  75 02 B1 02 0A 04 FF 35  : %.5.E... u......5
2400EA18 - 00 45 00 95 01 75 01 B1  02 75 03 B1 01 C0 C0 00  : .E...u.. .u......
2400EA28 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........
2400EA38 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........

HID Report Descriptor (0x2400e948) size: 256
  05 01	// Usage Page(1) - Generic Desktop
  09 02	// Usage(2) -(Mouse)
  A1 01	// Collection(1) top Usage(10002)
    05 01	// Usage Page(1) - Generic Desktop
    09 02	// Usage(2) -(Mouse)
    A1 02	// Collection(2)
    85 1A	// Report ID(1a)
    09 01	// Usage(1) -(?)
    A1 00	// Collection(0)
    05 09	// Usage Page(9) - Button
    19 01	// Usage Minimum(1) -  (BUTTON 1)
    29 05	// Usage Maximum(5) -  (BUTTON 5)
    95 05	// Report Count(5)
    75 01	// Report Size(1)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    75 03	// Report Size(3)
    95 01	// Report Count(1)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    05 01	// Usage Page(1) - Generic Desktop
    09 30	// Usage(30) -(X)
    09 31	// Usage(31) -(Y)
    95 02	// Report Count(2)
    75 10	// Report Size(10)
    16 01 80	// Logical Minimum(8001)
    26 FF 7F	// Logical maximum(7fff)
    81 06	// Input(6)	// (Data, Variable, Relative)
    A1 02	// Collection(2)
    85 12	// Report ID(12)
    09 48	// Usage(48) -(?)
    95 01	// Report Count(1)
    75 02	// Report Size(2)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    35 01	// Physical Minimum(1)
    45 0C	// Physical Maximum(c)
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 1A	// Report ID(1a)
    09 38	// Usage(38) -(Wheel)
    35 00	// Physical Minimum(0)
    45 00	// Physical Maximum(0)
    95 01	// Report Count(1)
    75 10	// Report Size(10)
    16 01 80	// Logical Minimum(8001)
    26 FF 7F	// Logical maximum(7fff)
    81 06	// Input(6)	// (Data, Variable, Relative)
    C0	// End Collection
  A1 02	// Collection(2) top Usage(10038)
    85 12	// Report ID(12)
    09 48	// Usage(48) -(?)
    75 02	// Report Size(2)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    35 01	// Physical Minimum(1)
    45 0C	// Physical Maximum(c)
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    35 00	// Physical Minimum(0)
    45 00	// Physical Maximum(0)
    75 04	// Report Size(4)
    B1 01	// Feature(1)	// (Constant, Array, Absolute)
    85 1A	// Report ID(1a)
    05 0C	// Usage Page(c) - Consumer
    95 01	// Report Count(1)
    75 10	// Report Size(10)
    16 01 80	// Logical Minimum(8001)
    26 FF 7F	// Logical maximum(7fff)
    0A 38 02	// Usage(238) -(AC Pan)
    81 06	// Input(6)	// (Data, Variable, Relative)
    C0	// End Collection
  C0	// End Collection
  C0	// End Collection
  C0	// End Collection
  05 0C	// Usage Page(c) - Consumer
  09 01	// Usage(1) -(Consumer Controls)
  A1 01	// Collection(1) top Usage(c0001)
    05 01	// Usage Page(1) - Generic Desktop
    09 02	// Usage(2) -(Mouse)
    A1 02	// Collection(2)
    85 1F	// Report ID(1f)
    05 0C	// Usage Page(c) - Consumer
    0A 38 02	// Usage(238) -(AC Pan)
    95 01	// Report Count(1)
    75 10	// Report Size(10)
    16 01 80	// Logical Minimum(8001)
    26 FF 7F	// Logical maximum(7fff)
    81 06	// Input(6)	// (Data, Variable, Relative)
    85 17	// Report ID(17)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 06 FF	// Usage(ff06) -
    0A 0F FF	// Usage(ff0f) -
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    35 01	// Physical Minimum(1)
    45 0C	// Physical Maximum(c)
    95 02	// Report Count(2)
    75 02	// Report Size(2)
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    0A 04 FF	// Usage(ff04) -
    35 00	// Physical Minimum(0)
    45 00	// Physical Maximum(0)
    95 01	// Report Count(1)
    75 01	// Report Size(1)
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    75 03	// Report Size(3)
    B1 01	// Feature(1)	// (Constant, Array, Absolute)
    C0	// End Collection
  C0	// End Collection
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00

--------------------
* Top usage summary
--------------------
Report ID: 0: 10002
Report ID: 1a: 10038 c0001
--------------------
****************************************
** Interface level **
  bInterfaceNumber: 2
  bAlternateSetting: 0
  Number of endpoints: 1
  bInterfaceClass: 3
  bInterfaceSubClass: 0
    HID
  bInterfaceProtocol: 0
    None
  iInterface: 0
  HID Descriptor size: 296
  Endpoint: 83 In
    Attrributes: 3 Interrupt
    Size: 32
    Interval: 1
>>>>> USBDumperDevice::getHIDDesc(2) called <<<<< 
2400E948 - 05 0C 09 01 A1 01 85 20  06 00 FF 15 00 26 FF 00  : .......  .....&..
2400E958 - 75 08 95 12 0A 0A FA B1  02 85 21 06 00 FF 15 00  : u....... ..!.....
2400E968 - 25 01 75 01 95 10 1A 10  FA 2A 1F FA 81 02 85 28  : %.u..... .*.....(
2400E978 - 06 00 FF 75 01 95 18 1A  10 FA 2A 1F FA B1 02 85  : ...u.... ..*.....
2400E988 - 22 06 00 FF 15 00 26 FF  00 75 08 95 1A 0A 0A FA  : ".....&. .u......
2400E998 - B1 02 85 23 06 00 FF 0A  0A FA B1 02 85 A2 06 00  : ...#.... ........
2400E9A8 - FF 0A 0A FA B1 02 85 A3  06 00 FF 0A 0A FA B1 02  : ........ ........
2400E9B8 - 85 24 06 00 FF 95 1F 0A  0A FA B1 02 85 25 06 00  : .$...... .....%..
2400E9C8 - FF 0A 0A FA B1 02 85 A4  06 00 FF 95 1F 0A 0A FA  : ........ ........
2400E9D8 - B1 02 85 A5 06 00 FF 0A  0A FA B1 02 85 26 06 00  : ........ .....&..
2400E9E8 - FF 0A 0A FA B1 02 85 27  06 00 FF 0A 0A FA 81 02  : .......' ........
2400E9F8 - C0 05 0C 09 01 A1 01 85  07 05 0C 19 00 2A FF 03  : ........ .....*..
2400EA08 - 95 01 75 10 15 00 26 FF  03 81 00 05 07 19 00 29  : ..u...&. .......)
2400EA18 - FF 75 08 26 FF 00 81 00  81 01 06 00 FF 0A 03 FE  : .u.&.... ........
2400EA28 - 0A 04 FE 75 01 95 02 25  01 81 02 0A 05 FF 95 01  : ...u...% ........
2400EA38 - 75 05 25 1F 81 02 75 01  81 01 1A 01 FD 2A FF FD  : u.%...u. .....*..
2400EA48 - 15 01 26 FF 00 75 08 81  00 0A 02 FF 26 FF 00 15  : ..&..u.. ....&...
2400EA58 - 00 81 02 C0 05 01 09 80  A1 01 85 03 19 00 29 FF  : ........ ......).
2400EA68 - 15 00 26 FF 00 81 00 C0  00 00 00 00 00 00 00 00  : ..&..... ........
2400EA78 - 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  : ........ ........

HID Report Descriptor (0x2400e948) size: 320
  05 0C	// Usage Page(c) - Consumer
  09 01	// Usage(1) -(Consumer Controls)
  A1 01	// Collection(1) top Usage(c0001)
    85 20	// Report ID(20)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    15 00	// Logical Minimum(0)
    26 FF 00	// Logical maximum(ff)
    75 08	// Report Size(8)
    95 12	// Report Count(12)
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 21	// Report ID(21)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    75 01	// Report Size(1)
    95 10	// Report Count(10)
    1A 10 FA	// Usage Minimum(fa10) - 
    2A 1F FA	// Usage Maximum(fa1f) - 
    81 02	// Input(2)	// (Data, Variable, Absolute)
    85 28	// Report ID(28)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    75 01	// Report Size(1)
    95 18	// Report Count(18)
    1A 10 FA	// Usage Minimum(fa10) - 
    2A 1F FA	// Usage Maximum(fa1f) - 
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 22	// Report ID(22)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    15 00	// Logical Minimum(0)
    26 FF 00	// Logical maximum(ff)
    75 08	// Report Size(8)
    95 1A	// Report Count(1a)
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 23	// Report ID(23)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 A2	// Report ID(a2)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 A3	// Report ID(a3)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 24	// Report ID(24)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    95 1F	// Report Count(1f)
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 25	// Report ID(25)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 A4	// Report ID(a4)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    95 1F	// Report Count(1f)
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 A5	// Report ID(a5)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 26	// Report ID(26)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    85 27	// Report ID(27)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 0A FA	// Usage(fa0a) -
    81 02	// Input(2)	// (Data, Variable, Absolute)
    C0	// End Collection
  05 0C	// Usage Page(c) - Consumer
  09 01	// Usage(1) -(Consumer Controls)
  A1 01	// Collection(1) top Usage(c0001)
    85 07	// Report ID(7)
    05 0C	// Usage Page(c) - Consumer
    19 00	// Usage Minimum(0) - (?)
    2A FF 03	// Usage Maximum(3ff) - (?)
    95 01	// Report Count(1)
    75 10	// Report Size(10)
    15 00	// Logical Minimum(0)
    26 FF 03	// Logical maximum(3ff)
    81 00	// Input(0)	// (Data, Array, Absolute)
    05 07	// Usage Page(7) - Keycode
    19 00	// Usage Minimum(0) - (Keycode 0)
    29 FF	// Usage Maximum(ff) - (Keycode 255)
    75 08	// Report Size(8)
    26 FF 00	// Logical maximum(ff)
    81 00	// Input(0)	// (Data, Array, Absolute)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    0A 03 FE	// Usage(fe03) -
    0A 04 FE	// Usage(fe04) -
    75 01	// Report Size(1)
    95 02	// Report Count(2)
    25 01	// Logical maximum(1)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    0A 05 FF	// Usage(ff05) -
    95 01	// Report Count(1)
    75 05	// Report Size(5)
    25 1F	// Logical maximum(1f)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    75 01	// Report Size(1)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    1A 01 FD	// Usage Minimum(fd01) - 
    2A FF FD	// Usage Maximum(fdff) - 
    15 01	// Logical Minimum(1)
    26 FF 00	// Logical maximum(ff)
    75 08	// Report Size(8)
    81 00	// Input(0)	// (Data, Array, Absolute)
    0A 02 FF	// Usage(ff02) -
    26 FF 00	// Logical maximum(ff)
    15 00	// Logical Minimum(0)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    C0	// End Collection
  05 01	// Usage Page(1) - Generic Desktop
  09 80	// Usage(80) -(System Control)
  A1 01	// Collection(1) top Usage(10080)
    85 03	// Report ID(3)
    19 00	// Usage Minimum(0) - (?)
    29 FF	// Usage Maximum(ff) - (?)
    15 00	// Logical Minimum(0)
    26 FF 00	// Logical maximum(ff)
    81 00	// Input(0)	// (Data, Array, Absolute)
    C0	// End Collection
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00
  00

--------------------
* Top usage summary
--------------------
Report ID: 0: c0001
Report ID: 27: c0001
Report ID: 7: 10080
--------------------
parseInterface nb:0
 bInterfaceClass = 3
 bInterfaceSubClass = 1
    HID (BOOT)
 bProtocol = 1
    Keyboard
useEndpoint(0, 3, 2)
parseInterface nb:1
 bInterfaceClass = 3
 bInterfaceSubClass = 1
    HID (BOOT)
 bProtocol = 2
    Mouse
parseInterface nb:2
 bInterfaceClass = 3
 bInterfaceSubClass = 0
    HID
 bProtocol = 0
    None
New Debug device: VID:045e PID:07a5 [dev: 0x2400c72c - intf: 0]
USB host device(45e:7a5) connected
Manufacturer: Microsoft
Product: Microsoftďż˝ 2.4GHz Transceiver v9.0

@KurtE - I finally have the right combo of libraries downloaded to try out the keyboard and mouse parts. Nice work. Both Wired keyboard and wired mouse work great without a HUB in between (Dell). Also wireless keyboard and mouse combo (Logitech). But when I install a HUB in between there are issues.
First the Logitech wireless mouse works fine but the keyboard will hang after a few keystrokes sometimes quite a few of them.
Here is some info:

-Logitech wireless keyboard/mouse combo-

Without 4 port HUB:
Device:0x2400c724
VID: 46D, PID: c52b

----------------------------------------
Device Descriptor:
  bcdUSB: 512
  bDeviceClass: 0
  bDeviceSubClass: 0
  bDeviceProtocol: 0
  bMaxPacketSize: 32
  idVendor: 0x46d
  idProduct: 0xc52b
  bcdDevice: 9216
  iManufacturer: 1
  iProduct: 2
  iSerialNumber: 0
  bNumConfigurations: 1
Manufacturer: Logitech
Product: USB Receiver
Speed: 0

With 4 port HUB:
Device:0x2400c724
New Debug device: VID:05e3 PID:0608 [dev: 0x2400c724 - intf: 255]
Hangs up after a few keystrokes. Usually 5-8 sometimes more when using GIGA_USBHost_Keyboard_test.
Crashes (red led) when using GIGA_USBHost_DeviceInfo sketch.

And the Dell wired keyboard and mouse:

-Dell wired keyboard -
With 4 port HUB:
[USB_ERR: /home/wwatson/Arduino/libraries/Arduino_USBHostMbed5-usb_host_fixes_lowspeed/src/USBHost/USBHost.cpp:170]usb_thread could not read dev descr

Without 4 port HUB:
Device:0x2400c724
New Debug device: VID:05e3 PID:0608 [dev: 0x2400c724 - intf: 255]
Device:0x2400c724
VID: 461, PID: 10

----------------------------------------
Device Descriptor:
  bcdUSB: 512
  bDeviceClass: 0
  bDeviceSubClass: 0
  bDeviceProtocol: 0
  bMaxPacketSize: 8
  idVendor: 0x461
  idProduct: 0x10
  bcdDevice: 272
  iManufacturer: 0
  iProduct: 2
  iSerialNumber: 0
  bNumConfigurations: 1
Product: USB Keyboard
Speed: 1

-Dell wired mouse-
With 4 port HUB:
Device:0x2400c724
New Debug device: VID:05e3 PID:0608 [dev: 0x2400c724 - intf: 255]
Crashes with red leds of doom. GIGA_USBHost_DeviceInfo sketch.

GIGA_USBHost_Mouse_test.
Mouse (4f2:923): connected
Manufacturer: PixArt
Product: HP USB Optical Mouse
At this point the GIGA is hung.

Without  4 port HUB:
Works as expected.

I am retired now so have lots of time to play :grinning:

EDIT: I have narrowed it down to the key mapping of the modifiers. if I comment out the Serial.prints in:

void kbd_keycode_cb(uint8_t keycode, uint8_t mod) {
//  Serial.print("Keycode: ");
//  Serial.print(keycode, HEX);
//  Serial.print(" mod: ");
//  Serial.println(mod, HEX);
}

then there is no lockup. If I un-comment the Serial.prints one at a time then the less time it take for the GIGA to hang. I think it is some sort of timing issue. I the keyboard cpp file I see:

      uint8_t modifier = report[0];
      modifiers_ = modifier;

      // first check for new key presses
      for (uint8_t i = 2; i < 8; i++) {
        uint8_t keycode = report[i];
        if (keycode == 0) break;  // no more keys pressed
        if (!contains(keycode, prev_report)) {
          // new key press
          keyOEM_ = keycode; 
          if (onKey) {
            // This is pretty lame... and buggy
            key = mapKeycodeToKey(modifier, keycode);
            //printf("key: %x(%c)\n", key, key);
            if (key) (*onKey)(key);
          }
          ******if (onKeyCode) (*onKeyCode)(report[i], modifier);*******
        }
      }
  

I think maybe a ring buffer would help?

1 Like

Congratulations on your retirement. Be careful though you might get addicted like the rest of us - or is that obsessed :slight_smile:

I have not tried HUBs yet... Should.

Do you have a sample sketch you are trying with both, or is simply using the HUB fails with some of our current sketches.

Ditto to what @Merlin513 said :laughing:

Note: I synced up with @BobTheDog latest changes to his PR, into my fork/branch and pushed them up. So far not noticing any differences. for the Wacom tablet that can not read it's hid descriptor... The funny thing is our tablet code does not actually read it in. As we found earlier that their HID output does not fully match their descriptors...

EDIT: I see you are using the ones that are part of the library...

@KurtE @Merlin513 - Thanks guys. Feels like I am supposed to be at work :smile:
@KurtE - I am using two of your libraries. Arduino_USBHostMbed5_usb_host_fixes_lowspeed and GIGA_USBHostMbed5_devices. I am using the your keyboard and mouse sketches. I now have both wired and wireless keyboard and mouse working with HUB's. The only hangup is in the keyboard sketch (GIGA_USBHost_Keyboard_test.ino) there is:

void kbd_keycode_cb(uint8_t keycode, uint8_t mod) {
//  Serial.print("Keycode: ");
//  Serial.print(keycode, HEX);
//  Serial.print(" mod: ");
//  Serial.println(mod, HEX);
}

This where it hangs with a HUB attached. If I comment out the Serial.prints is does not hang and as I uncomment them one at time the number of key presses before the hang becomes less. As I stated in post #8 the HUBS slow down keyboard responses and then adding the delays of the Serial.prints are enough to cause the hang... I think :blush:

Thanks for responding

Still playing with joysticks here - picked up a XBOX 360 controller with the MS 2.4ghz dongle but neglected to read the fine print about no battery - Argh. Anyways attached the dongle and using the updated device info sketch:

Device:0x2400c72c
VID: 62A, PID: 38da

----------------------------------------
Device Descriptor:
  bcdUSB: 512
  bDeviceClass: 0
  bDeviceSubClass: 0
  bDeviceProtocol: 0
  bMaxPacketSize: 8
  idVendor: 0x62a
  idProduct: 0x38da
  bcdDevice: 5
  iManufacturer: 1
  iProduct: 2
  iSerialNumber: 0
  bNumConfigurations: 1
Manufacturer: MosArt
Product: Wireless Gamepad
Speed: 0

----------------------------------------
Size of configuration Descriptor: 41
Configuration Descriptor
2400EAA8 - 09 02 29 00 01 01 00 80  32 09 04 00 00 02 03 00  : ..)..... 2.......
2400EAB8 - 00 00 09 21 11 01 00 01  22 91 00 07 05 02 03 40  : ...!.... "......@
2400EAC8 - 00 0A 07 05 81 03 40 00  0A                       : ......@. .
Config:
 wTotalLength: 41
 bNumInterfaces: 1
 bConfigurationValue: 1
 iConfiguration: 0
 bmAttributes: 128
 bMaxPower: 50
****************************************
** Interface level **
  bInterfaceNumber: 0
  bAlternateSetting: 0
  Number of endpoints: 2
  bInterfaceClass: 3
  bInterfaceSubClass: 0
    HID
  bInterfaceProtocol: 0
    None
  iInterface: 0
  HID Descriptor size: 145
  Endpoint: 2 Out
    Attrributes: 3 Interrupt
    Size: 64
    Interval: 10
  Endpoint: 81 In
    Attrributes: 3 Interrupt
    Size: 64
    Interval: 10
>>>>> USBDumperDevice::getHIDDesc(0) called <<<<< 
2400EAE0 - 05 01 09 05 A1 01 15 00  25 01 35 00 45 01 75 01  : ........ %.5.E.u.
2400EAF0 - 95 0D 05 09 19 01 29 0D  81 02 95 03 81 01 05 01  : ......). ........
2400EB00 - 25 07 46 3B 01 75 04 95  01 65 14 09 39 81 42 65  : %.F;.u.. .e..9.Be
2400EB10 - 00 95 01 81 01 26 FF 00  46 FF 00 09 30 09 31 09  : .....&.. F...0.1.
2400EB20 - 32 09 35 75 08 95 04 81  02 06 00 FF 09 20 09 21  : 2.5u.... ..... .!
2400EB30 - 09 22 09 23 09 24 09 25  09 26 09 27 09 28 09 29  : .".#.$.% .&.'.(.)
2400EB40 - 09 2A 09 2B 95 0C 81 02  26 FF 03 46 FF 03 09 2C  : .*.+.... &..F...,
2400EB50 - 09 2D 09 2E 09 2F 75 10  95 04 81 02 26 FF 00 46  : .-.../u. ....&..F
2400EB60 - FF 00 75 08 0A 21 26 95  08 B1 02 0A 21 26 91 02  : ..u..!&. ....!&..
2400EB70 - C0 00 00 00 6D AE 04 08  34 C8 2B A7 C9 00 00 00  : ....m... 4.+.....
2400EB80 - BC 00 00 00 EF BE AD DE  B4 43 06 08 C0 14 00 24  : ........ .C.....$
2400EB90 - 35 20 04 08 00 00 00 00  0C 1C 06 08 00 EC 00 24  : 5 ...... .......$

HID Report Descriptor (0x2400eae0) size: 192
  05 01	// Usage Page(1) - Generic Desktop
  09 05	// Usage(5) -(?)
  A1 01	// Collection(1) top Usage(10005)
    15 00	// Logical Minimum(0)
    25 01	// Logical maximum(1)
    35 00	// Physical Minimum(0)
    45 01	// Physical Maximum(1)
    75 01	// Report Size(1)
    95 0D	// Report Count(d)
    05 09	// Usage Page(9) - Button
    19 01	// Usage Minimum(1) -  (BUTTON 1)
    29 0D	// Usage Maximum(d) -  (BUTTON 13)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    95 03	// Report Count(3)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    05 01	// Usage Page(1) - Generic Desktop
    25 07	// Logical maximum(7)
    46 3B 01	// Physical Maximum(13b)
    75 04	// Report Size(4)
    95 01	// Report Count(1)
    65 14	// Unit(14)
    09 39	// Usage(39) -(Hat)
    81 42	// Input(42)	// (Data, Variable, Absolute, Null State)
    65 00	// Unit(0)
    95 01	// Report Count(1)
    81 01	// Input(1)	// (Constant, Array, Absolute)
    26 FF 00	// Logical maximum(ff)
    46 FF 00	// Physical Maximum(ff)
    09 30	// Usage(30) -(X)
    09 31	// Usage(31) -(Y)
    09 32	// Usage(32) -(Z)
    09 35	// Usage(35) -(Rz)
    75 08	// Report Size(8)
    95 04	// Report Count(4)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    06 00 FF	// Usage Page(ff00) - Vendor Defined
    09 20	// Usage(20) -
    09 21	// Usage(21) -
    09 22	// Usage(22) -
    09 23	// Usage(23) -
    09 24	// Usage(24) -
    09 25	// Usage(25) -
    09 26	// Usage(26) -
    09 27	// Usage(27) -
    09 28	// Usage(28) -
    09 29	// Usage(29) -
    09 2A	// Usage(2a) -
    09 2B	// Usage(2b) -
    95 0C	// Report Count(c)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    26 FF 03	// Logical maximum(3ff)
    46 FF 03	// Physical Maximum(3ff)
    09 2C	// Usage(2c) -
    09 2D	// Usage(2d) -
    09 2E	// Usage(2e) -
    09 2F	// Usage(2f) -
    75 10	// Report Size(10)
    95 04	// Report Count(4)
    81 02	// Input(2)	// (Data, Variable, Absolute)
    26 FF 00	// Logical maximum(ff)
    46 FF 00	// Physical Maximum(ff)
    75 08	// Report Size(8)
    0A 21 26	// Usage(2621) -
    95 08	// Report Count(8)
    B1 02	// Feature(2)	// (Data, Variable, Absolute)
    0A 21 26	// Usage(2621) -
    91 02	// Output(2)	// (Data, Variable, Absolute)
    C0	// End Collection
  00
  00
  00
  6D AE
  04	// Usage Page(0) - Other ?
  08	// Usage(0) -
  34	// Physical Minimum(0)
  C8
  2B A7 C9 00 00	// Usage Maximum(c9a7) - 
  00
  BC
  00
  00
  00
  EF BE AD DE B4
  43 06 08 C0 14
  00
  24	// Logical maximum(0)
  35 20	// Physical Minimum(20)
  04	// Usage Page(0) - Other ?
  08	// Usage(0) -
  00
  00
  00
  00
  0C
  1C
  06 08 00	// Usage Page(8) - LEDs
  EC
  00
  24	// Logical maximum(0)

--------------------
* Top usage summary
--------------------
Report ID: 0: 10005
--------------------
[USB_ERR: d:\Users\Merli\Documents\Arduino\libraries\Arduino_USBHostMbed5-usb_host_fixes_lowspeed\src\USBHost\USBHost.cpp:886]GET CONF 1 DESCR FAILED
Enumerate returned status not OKNo USB host device connected
No USB host device connected
No USB host device connected

So hopefully tomorrow when I get the batteries I can check another joystick/gamepad.

I have a Logitech F310. Maybe I'll try that out and see if that works...

Do we need to do something to enable a hub in a sketch?

Nope, It just works :slightly_smiling_face:

These are what i used from your repositories:


/*
  USBHost Keyboard test


  The circuit:
   - Arduino GIGA

  This example code is in the public domain.
*/

#include <Arduino_USBHostMbed5.h>
#include "USBHostKeyboardEx.h"
#include <LibPrintf.h>

REDIRECT_STDOUT_TO(Serial)

USBHostKeyboardEx kbd;

// If you are using a Portenta Machine Control uncomment the following line
// mbed::DigitalOut otg(PB_14, 0);

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 5000) {}

  Serial.println("Starting Keyboard test...");
  // Enable the USBHost
  pinMode(PA_15, OUTPUT);
  digitalWrite(PA_15, HIGH);

  // if you are using a Max Carrier uncomment the following line
  // start_hub();

  while (!kbd.connect()) {
    Serial.println("No keyboard connected");
    delay(5000);
  }

  printf("\nKeyboard (%x:%x): connected\n", kbd.idVendor(), kbd.idProduct());

  uint8_t string_buffer[80];
  if (kbd.manufacturer(string_buffer, sizeof(string_buffer))) {
    Serial.print("Manufacturer: ");
    Serial.println((char*)string_buffer);
  }

  if (kbd.product(string_buffer, sizeof(string_buffer))) {
    Serial.print("Product: ");
    Serial.println((char*)string_buffer);
  }
  if (kbd.serialNumber(string_buffer, sizeof(string_buffer))) {
    Serial.print("Serial Number: ");
    Serial.println((char*)string_buffer);
  }

  kbd.attachPress(&kbd_key_cb);
  kbd.attachRawPress(&kbd_keycode_cb);
  kbd.attachRelease(&kbd_key_release_cb);
  kbd.attachHIDPress(&kbd_hid_key_press_cb);
  kbd.attachHIDRelease(&kbd_hid_key_release_cb);
  Serial.println("End of Setup");
}

void loop() {
  delay(1000);
}

// If uncommented keyboard will hang after a few keystrokes
void kbd_keycode_cb(uint8_t keycode, uint8_t mod) {
//  Serial.print("Keycode: ");
//  Serial.print(keycode, HEX);
//  Serial.print(" mod: ");
//  Serial.println(mod, HEX);
}

void kbd_key_cb(uint8_t key) {
  Serial.print("Key pressed: ");
  Serial.print(key, HEX);
  Serial.print("(");
  if ((key >= ' ') && (key <= '~')) {
    Serial.write(key);
  } else {
    switch (key) {
      case USBHostKeyboardEx::KEYD_UP: Serial.print("UP"); break;
      case USBHostKeyboardEx::KEYD_DOWN: Serial.print("DN"); break;
      case USBHostKeyboardEx::KEYD_LEFT: Serial.print("LEFT"); break;
      case USBHostKeyboardEx::KEYD_RIGHT: Serial.print("RIGHT"); break;
      case USBHostKeyboardEx::KEYD_INSERT: Serial.print("Ins"); break;
      case USBHostKeyboardEx::KEYD_DELETE: Serial.print("Del"); break;
      case USBHostKeyboardEx::KEYD_PAGE_UP: Serial.print("PUP"); break;
      case USBHostKeyboardEx::KEYD_PAGE_DOWN: Serial.print("PDN"); break;
      case USBHostKeyboardEx::KEYD_HOME: Serial.print("HOME"); break;
      case USBHostKeyboardEx::KEYD_END: Serial.print("END"); break;
      case USBHostKeyboardEx::KEYD_F1: Serial.print("F1"); break;
      case USBHostKeyboardEx::KEYD_F2: Serial.print("F2"); break;
      case USBHostKeyboardEx::KEYD_F3: Serial.print("F3"); break;
      case USBHostKeyboardEx::KEYD_F4: Serial.print("F4"); break;
      case USBHostKeyboardEx::KEYD_F5: Serial.print("F5"); break;
      case USBHostKeyboardEx::KEYD_F6: Serial.print("F6"); break;
      case USBHostKeyboardEx::KEYD_F7: Serial.print("F7"); break;
      case USBHostKeyboardEx::KEYD_F8: Serial.print("F8"); break;
      case USBHostKeyboardEx::KEYD_F9: Serial.print("F9"); break;
      case USBHostKeyboardEx::KEYD_F10: Serial.print("F10"); break;
      case USBHostKeyboardEx::KEYD_F11: Serial.print("F11"); break;
      case USBHostKeyboardEx::KEYD_F12: Serial.print("F12"); break;
      default: Serial.print((char)key); break;
    }
  }
  Serial.println(")");
}

void kbd_key_release_cb(uint8_t key) {
  Serial.print("Key released: ");
  Serial.print(key, HEX);
  Serial.print("(");
  if ((key >= ' ') && (key <= '~')) {
    Serial.write(key);
  } else {
    switch (key) {
      case USBHostKeyboardEx::KEYD_UP: Serial.print("UP"); break;
      case USBHostKeyboardEx::KEYD_DOWN: Serial.print("DN"); break;
      case USBHostKeyboardEx::KEYD_LEFT: Serial.print("LEFT"); break;
      case USBHostKeyboardEx::KEYD_RIGHT: Serial.print("RIGHT"); break;
      case USBHostKeyboardEx::KEYD_INSERT: Serial.print("Ins"); break;
      case USBHostKeyboardEx::KEYD_DELETE: Serial.print("Del"); break;
      case USBHostKeyboardEx::KEYD_PAGE_UP: Serial.print("PUP"); break;
      case USBHostKeyboardEx::KEYD_PAGE_DOWN: Serial.print("PDN"); break;
      case USBHostKeyboardEx::KEYD_HOME: Serial.print("HOME"); break;
      case USBHostKeyboardEx::KEYD_END: Serial.print("END"); break;
      case USBHostKeyboardEx::KEYD_F1: Serial.print("F1"); break;
      case USBHostKeyboardEx::KEYD_F2: Serial.print("F2"); break;
      case USBHostKeyboardEx::KEYD_F3: Serial.print("F3"); break;
      case USBHostKeyboardEx::KEYD_F4: Serial.print("F4"); break;
      case USBHostKeyboardEx::KEYD_F5: Serial.print("F5"); break;
      case USBHostKeyboardEx::KEYD_F6: Serial.print("F6"); break;
      case USBHostKeyboardEx::KEYD_F7: Serial.print("F7"); break;
      case USBHostKeyboardEx::KEYD_F8: Serial.print("F8"); break;
      case USBHostKeyboardEx::KEYD_F9: Serial.print("F9"); break;
      case USBHostKeyboardEx::KEYD_F10: Serial.print("F10"); break;
      case USBHostKeyboardEx::KEYD_F11: Serial.print("F11"); break;
      case USBHostKeyboardEx::KEYD_F12: Serial.print("F12"); break;
      default: Serial.print((char)key); break;
    }
  }
  Serial.println(")");
}

void kbd_hid_key_press_cb(uint32_t top, uint16_t code) {
  Serial.print("Press: HID Key: Page:0x");
  print_hid_data(top, code);
}

void kbd_hid_key_release_cb(uint32_t top, uint16_t code) {
  Serial.print("Release: HID Key: Page:0x");
  print_hid_data(top, code);
}


void print_hid_data(uint32_t top, uint32_t code) {
  Serial.print(top, HEX);
  Serial.print(" Code: 0x");
  Serial.print(code, HEX);
  if (top == 0x0c) {
    switch (code) {
      case 0x20: Serial.println(" - +10"); return;
      case 0x21: Serial.println(" - +100"); return;
      case 0x22: Serial.println(" - AM/PM"); return;
      case 0x23: Serial.println(" - Home"); return;
      case 0x30: Serial.println(" - Power"); return;
      case 0x31: Serial.println(" - Reset"); return;
      case 0x32: Serial.println(" - Sleep"); return;
      case 0x33: Serial.println(" - Sleep After"); return;
      case 0x34: Serial.println(" - Sleep Mode"); return;
      case 0x35: Serial.println(" - Illumination"); return;
      case 0x36: Serial.println(" - Function Buttons"); return;
      case 0x40: Serial.println(" - Menu"); return;
      case 0x41: Serial.println(" - Menu  Pick"); return;
      case 0x42: Serial.println(" - Menu Up"); return;
      case 0x43: Serial.println(" - Menu Down"); return;
      case 0x44: Serial.println(" - Menu Left"); return;
      case 0x45: Serial.println(" - Menu Right"); return;
      case 0x46: Serial.println(" - Menu Escape"); return;
      case 0x47: Serial.println(" - Menu Value Increase"); return;
      case 0x48: Serial.println(" - Menu Value Decrease"); return;
      case 0x60: Serial.println(" - Data On Screen"); return;
      case 0x61: Serial.println(" - Closed Caption"); return;
      case 0x62: Serial.println(" - Closed Caption Select"); return;
      case 0x63: Serial.println(" - VCR/TV"); return;
      case 0x64: Serial.println(" - Broadcast Mode"); return;
      case 0x65: Serial.println(" - Snapshot"); return;
      case 0x66: Serial.println(" - Still"); return;
      case 0x80: Serial.println(" - Selection"); return;
      case 0x81: Serial.println(" - Assign Selection"); return;
      case 0x82: Serial.println(" - Mode Step"); return;
      case 0x83: Serial.println(" - Recall Last"); return;
      case 0x84: Serial.println(" - Enter Channel"); return;
      case 0x85: Serial.println(" - Order Movie"); return;
      case 0x86: Serial.println(" - Channel"); return;
      case 0x87: Serial.println(" - Media Selection"); return;
      case 0x88: Serial.println(" - Media Select Computer"); return;
      case 0x89: Serial.println(" - Media Select TV"); return;
      case 0x8A: Serial.println(" - Media Select WWW"); return;
      case 0x8B: Serial.println(" - Media Select DVD"); return;
      case 0x8C: Serial.println(" - Media Select Telephone"); return;
      case 0x8D: Serial.println(" - Media Select Program Guide"); return;
      case 0x8E: Serial.println(" - Media Select Video Phone"); return;
      case 0x8F: Serial.println(" - Media Select Games"); return;
      case 0x90: Serial.println(" - Media Select Messages"); return;
      case 0x91: Serial.println(" - Media Select CD"); return;
      case 0x92: Serial.println(" - Media Select VCR"); return;
      case 0x93: Serial.println(" - Media Select Tuner"); return;
      case 0x94: Serial.println(" - Quit"); return;
      case 0x95: Serial.println(" - Help"); return;
      case 0x96: Serial.println(" - Media Select Tape"); return;
      case 0x97: Serial.println(" - Media Select Cable"); return;
      case 0x98: Serial.println(" - Media Select Satellite"); return;
      case 0x99: Serial.println(" - Media Select Security"); return;
      case 0x9A: Serial.println(" - Media Select Home"); return;
      case 0x9B: Serial.println(" - Media Select Call"); return;
      case 0x9C: Serial.println(" - Channel Increment"); return;
      case 0x9D: Serial.println(" - Channel Decrement"); return;
      case 0x9E: Serial.println(" - Media Select SAP"); return;
      case 0xA0: Serial.println(" - VCR Plus"); return;
      case 0xA1: Serial.println(" - Once"); return;
      case 0xA2: Serial.println(" - Daily"); return;
      case 0xA3: Serial.println(" - Weekly"); return;
      case 0xA4: Serial.println(" - Monthly"); return;
      case 0xB0: Serial.println(" - Play"); return;
      case 0xB1: Serial.println(" - Pause"); return;
      case 0xB2: Serial.println(" - Record"); return;
      case 0xB3: Serial.println(" - Fast Forward"); return;
      case 0xB4: Serial.println(" - Rewind"); return;
      case 0xB5: Serial.println(" - Scan Next Track"); return;
      case 0xB6: Serial.println(" - Scan Previous Track"); return;
      case 0xB7: Serial.println(" - Stop"); return;
      case 0xB8: Serial.println(" - Eject"); return;
      case 0xB9: Serial.println(" - Random Play"); return;
      case 0xBA: Serial.println(" - Select DisC"); return;
      case 0xBB: Serial.println(" - Enter Disc"); return;
      case 0xBC: Serial.println(" - Repeat"); return;
      case 0xBD: Serial.println(" - Tracking"); return;
      case 0xBE: Serial.println(" - Track Normal"); return;
      case 0xBF: Serial.println(" - Slow Tracking"); return;
      case 0xC0: Serial.println(" - Frame Forward"); return;
      case 0xC1: Serial.println(" - Frame Back"); return;
      case 0xC2: Serial.println(" - Mark"); return;
      case 0xC3: Serial.println(" - Clear Mark"); return;
      case 0xC4: Serial.println(" - Repeat From Mark"); return;
      case 0xC5: Serial.println(" - Return To Mark"); return;
      case 0xC6: Serial.println(" - Search Mark Forward"); return;
      case 0xC7: Serial.println(" - Search Mark Backwards"); return;
      case 0xC8: Serial.println(" - Counter Reset"); return;
      case 0xC9: Serial.println(" - Show Counter"); return;
      case 0xCA: Serial.println(" - Tracking Increment"); return;
      case 0xCB: Serial.println(" - Tracking Decrement"); return;
      case 0xCD: Serial.println(" - Pause/Continue"); return;
      case 0xE0: Serial.println(" - Volume"); return;
      case 0xE1: Serial.println(" - Balance"); return;
      case 0xE2: Serial.println(" - Mute"); return;
      case 0xE3: Serial.println(" - Bass"); return;
      case 0xE4: Serial.println(" - Treble"); return;
      case 0xE5: Serial.println(" - Bass Boost"); return;
      case 0xE6: Serial.println(" - Surround Mode"); return;
      case 0xE7: Serial.println(" - Loudness"); return;
      case 0xE8: Serial.println(" - MPX"); return;
      case 0xE9: Serial.println(" - Volume Up"); return;
      case 0xEA: Serial.println(" - Volume Down"); return;
      case 0xF0: Serial.println(" - Speed Select"); return;
      case 0xF1: Serial.println(" - Playback Speed"); return;
      case 0xF2: Serial.println(" - Standard Play"); return;
      case 0xF3: Serial.println(" - Long Play"); return;
      case 0xF4: Serial.println(" - Extended Play"); return;
      case 0xF5: Serial.println(" - Slow"); return;
      case 0x100: Serial.println(" - Fan Enable"); return;
      case 0x101: Serial.println(" - Fan Speed"); return;
      case 0x102: Serial.println(" - Light"); return;
      case 0x103: Serial.println(" - Light Illumination Level"); return;
      case 0x104: Serial.println(" - Climate Control Enable"); return;
      case 0x105: Serial.println(" - Room Temperature"); return;
      case 0x106: Serial.println(" - Security Enable"); return;
      case 0x107: Serial.println(" - Fire Alarm"); return;
      case 0x108: Serial.println(" - Police Alarm"); return;
      case 0x150: Serial.println(" - Balance Right"); return;
      case 0x151: Serial.println(" - Balance Left"); return;
      case 0x152: Serial.println(" - Bass Increment"); return;
      case 0x153: Serial.println(" - Bass Decrement"); return;
      case 0x154: Serial.println(" - Treble Increment"); return;
      case 0x155: Serial.println(" - Treble Decrement"); return;
      case 0x160: Serial.println(" - Speaker System"); return;
      case 0x161: Serial.println(" - Channel Left"); return;
      case 0x162: Serial.println(" - Channel Right"); return;
      case 0x163: Serial.println(" - Channel Center"); return;
      case 0x164: Serial.println(" - Channel Front"); return;
      case 0x165: Serial.println(" - Channel Center Front"); return;
      case 0x166: Serial.println(" - Channel Side"); return;
      case 0x167: Serial.println(" - Channel Surround"); return;
      case 0x168: Serial.println(" - Channel Low Frequency Enhancement"); return;
      case 0x169: Serial.println(" - Channel Top"); return;
      case 0x16A: Serial.println(" - Channel Unknown"); return;
      case 0x170: Serial.println(" - Sub-channel"); return;
      case 0x171: Serial.println(" - Sub-channel Increment"); return;
      case 0x172: Serial.println(" - Sub-channel Decrement"); return;
      case 0x173: Serial.println(" - Alternate Audio Increment"); return;
      case 0x174: Serial.println(" - Alternate Audio Decrement"); return;
      case 0x180: Serial.println(" - Application Launch Buttons"); return;
      case 0x181: Serial.println(" - AL Launch Button Configuration Tool"); return;
      case 0x182: Serial.println(" - AL Programmable Button Configuration"); return;
      case 0x183: Serial.println(" - AL Consumer Control Configuration"); return;
      case 0x184: Serial.println(" - AL Word Processor"); return;
      case 0x185: Serial.println(" - AL Text Editor"); return;
      case 0x186: Serial.println(" - AL Spreadsheet"); return;
      case 0x187: Serial.println(" - AL Graphics Editor"); return;
      case 0x188: Serial.println(" - AL Presentation App"); return;
      case 0x189: Serial.println(" - AL Database App"); return;
      case 0x18A: Serial.println(" - AL Email Reader"); return;
      case 0x18B: Serial.println(" - AL Newsreader"); return;
      case 0x18C: Serial.println(" - AL Voicemail"); return;
      case 0x18D: Serial.println(" - AL Contacts/Address Book"); return;
      case 0x18E: Serial.println(" - AL Calendar/Schedule"); return;
      case 0x18F: Serial.println(" - AL Task/Project Manager"); return;
      case 0x190: Serial.println(" - AL Log/Journal/Timecard"); return;
      case 0x191: Serial.println(" - AL Checkbook/Finance"); return;
      case 0x192: Serial.println(" - AL Calculator"); return;
      case 0x193: Serial.println(" - AL A/V Capture/Playback"); return;
      case 0x194: Serial.println(" - AL Local Machine Browser"); return;
      case 0x195: Serial.println(" - AL LAN/WAN Browser"); return;
      case 0x196: Serial.println(" - AL Internet Browser"); return;
      case 0x197: Serial.println(" - AL Remote Networking/ISP Connect"); return;
      case 0x198: Serial.println(" - AL Network Conference"); return;
      case 0x199: Serial.println(" - AL Network Chat"); return;
      case 0x19A: Serial.println(" - AL Telephony/Dialer"); return;
      case 0x19B: Serial.println(" - AL Logon"); return;
      case 0x19C: Serial.println(" - AL Logoff"); return;
      case 0x19D: Serial.println(" - AL Logon/Logoff"); return;
      case 0x19E: Serial.println(" - AL Terminal Lock/Screensaver"); return;
      case 0x19F: Serial.println(" - AL Control Panel"); return;
      case 0x1A0: Serial.println(" - AL Command Line Processor/Run"); return;
      case 0x1A1: Serial.println(" - AL Process/Task Manager"); return;
      case 0x1A2: Serial.println(" - AL Select Tast/Application"); return;
      case 0x1A3: Serial.println(" - AL Next Task/Application"); return;
      case 0x1A4: Serial.println(" - AL Previous Task/Application"); return;
      case 0x1A5: Serial.println(" - AL Preemptive Halt Task/Application"); return;
      case 0x200: Serial.println(" - Generic GUI Application Controls"); return;
      case 0x201: Serial.println(" - AC New"); return;
      case 0x202: Serial.println(" - AC Open"); return;
      case 0x203: Serial.println(" - AC Close"); return;
      case 0x204: Serial.println(" - AC Exit"); return;
      case 0x205: Serial.println(" - AC Maximize"); return;
      case 0x206: Serial.println(" - AC Minimize"); return;
      case 0x207: Serial.println(" - AC Save"); return;
      case 0x208: Serial.println(" - AC Print"); return;
      case 0x209: Serial.println(" - AC Properties"); return;
      case 0x21A: Serial.println(" - AC Undo"); return;
      case 0x21B: Serial.println(" - AC Copy"); return;
      case 0x21C: Serial.println(" - AC Cut"); return;
      case 0x21D: Serial.println(" - AC Paste"); return;
      case 0x21E: Serial.println(" - AC Select All"); return;
      case 0x21F: Serial.println(" - AC Find"); return;
      case 0x220: Serial.println(" - AC Find and Replace"); return;
      case 0x221: Serial.println(" - AC Search"); return;
      case 0x222: Serial.println(" - AC Go To"); return;
      case 0x223: Serial.println(" - AC Home"); return;
      case 0x224: Serial.println(" - AC Back"); return;
      case 0x225: Serial.println(" - AC Forward"); return;
      case 0x226: Serial.println(" - AC Stop"); return;
      case 0x227: Serial.println(" - AC Refresh"); return;
      case 0x228: Serial.println(" - AC Previous Link"); return;
      case 0x229: Serial.println(" - AC Next Link"); return;
      case 0x22A: Serial.println(" - AC Bookmarks"); return;
      case 0x22B: Serial.println(" - AC History"); return;
      case 0x22C: Serial.println(" - AC Subscriptions"); return;
      case 0x22D: Serial.println(" - AC Zoom In"); return;
      case 0x22E: Serial.println(" - AC Zoom Out"); return;
      case 0x22F: Serial.println(" - AC Zoom"); return;
      case 0x230: Serial.println(" - AC Full Screen View"); return;
      case 0x231: Serial.println(" - AC Normal View"); return;
      case 0x232: Serial.println(" - AC View Toggle"); return;
      case 0x233: Serial.println(" - AC Scroll Up"); return;
      case 0x234: Serial.println(" - AC Scroll Down"); return;
      case 0x235: Serial.println(" - AC Scroll"); return;
      case 0x236: Serial.println(" - AC Pan Left"); return;
      case 0x237: Serial.println(" - AC Pan Right"); return;
      case 0x238: Serial.println(" - AC Pan"); return;
      case 0x239: Serial.println(" - AC New Window"); return;
      case 0x23A: Serial.println(" - AC Tile Horizontally"); return;
      case 0x23B: Serial.println(" - AC Tile Vertically"); return;
      case 0x23C: Serial.println(" - AC Format"); return;
    }
  }
  Serial.println();
}

And the mouse sketch:

// Simple test of USB Host Mouse/Keyboard
//
// This example is in the public domain

#include <Arduino_USBHostMbed5.h>
#include "USBHostMouseEx.h"
REDIRECT_STDOUT_TO(Serial)

USBHostMouseEx mouse;
bool show_changed_only = false;

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 5000) {}

  Serial.println("Starting mouse test...");

  // Enable the USBHost
  pinMode(PA_15, OUTPUT);
  digitalWrite(PA_15, HIGH);

  // if you are using a Max Carrier uncomment the following line
  // start_hub();

  while (!mouse.connect()) {
    Serial.println("No mouse connected");
    delay(5000);
  }
  printf("\nMouse (%x:%x): connected\n", mouse.idVendor(), mouse.idProduct());

  uint8_t string_buffer[80];
  if (mouse.manufacturer(string_buffer, sizeof(string_buffer))) {
    Serial.print("Manufacturer: ");
    Serial.println((char*)string_buffer);
  }

  if (mouse.product(string_buffer, sizeof(string_buffer))) {
    Serial.print("Product: ");
    Serial.println((char*)string_buffer);
  }
  if (mouse.serialNumber(string_buffer, sizeof(string_buffer))) {
    Serial.print("Serial Number: ");
    Serial.println((char*)string_buffer);
  }
}


void loop() {
  if (mouse.available()) {
    Serial.print("Mouse: buttons = ");
    Serial.print(mouse.getButtons());
    Serial.print(",  mouseX = ");
    Serial.print(mouse.getMouseX());
    Serial.print(",  mouseY = ");
    Serial.print(mouse.getMouseY());
    Serial.print(",  wheel = ");
    Serial.print(mouse.getWheel());
    Serial.print(",  wheelH = ");
    Serial.print(mouse.getWheelH());
    Serial.println();
    mouse.mouseDataClear();
  }
}

Also I found that you do not need this:

  // Enable the USBHost
  pinMode(PA_15, OUTPUT);
  digitalWrite(PA_15, HIGH);

I have a belkin 4 port HUB with a power indicator and it lit up without the above.
Out of curiosity I plugged in a USB stick as well and ran the FileRead sketch without issue.
Probably will write a sketch that tests all three devices together...

Thanks, It looks like my USB LS stuff is not sufficient to handle them on a HUB. Have not played much with hub code before, but...

They are still workable. I am going try setting up a keyboard buffer on the GIGA that I have working on a Teensy and also the key repeat function as well as a workaround for now. Again I don't think it is an actual HUB code problem. I ran into the same delays or slowdowns using a HUB when I was testing USB drive speeds with MSC...

@KurtE and all
Just added a xbox 360 wireless controller to the mix for joystick and seems to be working.
Amazon.com: VOYEE Wireless Controller with Receiver Compatible with Microsoft Xbox 360/Slim/Windows 11/10/8/7, with Upgraded Joystick/Dual Shock (Black) : Video Games

also tested several controllers with a USB 3.0 HUB
Amazon.com: UGREEN Powered USB 3.0 Hub, 4 Ports Aluminum Ultra-Slim USB Multiport Adapter with USB C Power Ports Compatible with MacBook, iMac, Surface, Laptop, PC, Mouse, Keyboard, Flash Drive, and More : Electronics

and they are recognized and work. Only issue I ran into is with our disconnect/reconnect code. Doesn't seem to work with the hub in between.

1 Like

Took a break from Joystick and tried my logitech keyboard/mouse combo ( Logitech Wireless Touch Keyboard K400 Plus with Built-In Touchpad) by creating both a mouse and keyboard object on the same receiver.

On start up I get:

Starting Keyboard test...

Keyboard (46d:c52b): connected
Manufacturer: Logitech
Product: USB Receiver
End of KBD Setup

Mouse (46d:c52b): connected
Manufacturer: Logitech
Product: USB Receiver

with Keyboard output for asdfg

Key pressed: 61(a)
Keycode: 4 mod: 0
Key released: 61(a)
Key pressed: 73(s)
Keycode: 16 mod: 0
Key released: 73(s)
Key pressed: 64(d)
Keycode: 7 mod: 0
Key released: 64(d)
Key pressed: 66(f)
Keycode: 9 mod: 0
Key released: 66(f)
Key pressed: 67(g)
Keycode: A mod: 0
Key released: 67(g)

and mouse:

Mouse: buttons = 3,  mouseX = 3,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 3,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 3,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 2,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 2,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 2,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 2,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 1,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 2,  mouseY = 1,  wheel = 0,  wheelH = 0
Mouse: buttons = 3,  mouseX = 1,  mouseY = 0,  wheel = 0,  wheelH = 0

Note - had both buttons pressed on the mouse so got the 3 for buttons.

But the weirdness comes in with special function keys on the keyboard:

Key pressed: 1B(e)
Keycode: 29 mod: 0
Key released: 1B(e)
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Key pressed: 9(	)
Keycode: 2B mod: 4
Key released: 9(	)
Keycode: 65 mod: 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Keycode: 7 mod: 8
Key pressed: DA(UP)
Keycode: 52 mod: 8
Key released: DA(UP)
Keycode: 13 mod: 8
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0
Mouse: buttons = 0,  mouseX = 0,  mouseY = 0,  wheel = 0,  wheelH = 0

the key press correspond to top rows:

Function keys work by pressing holding the FN button and associated function key on the top row.

Heres the sketch I am using:


/*
  USBHost Keyboard test


  The circuit:
   - Arduino GIGA

  This example code is in the public domain.
*/

#include <Arduino_USBHostMbed5.h>
#include "USBHostKeyboardEx.h"
#include "USBHostMouseEx.h"

REDIRECT_STDOUT_TO(Serial)

USBHostKeyboardEx kbd;
USBHostMouseEx mouse;
bool show_changed_only = false;


// If you are using a Portenta Machine Control uncomment the following line
// mbed::DigitalOut otg(PB_14, 0);

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 5000) {}

  Serial.println("Starting Keyboard test...");

  // Enable the USBHost
  pinMode(PA_15, OUTPUT);
  digitalWrite(PA_15, HIGH);

  // if you are using a Max Carrier uncomment the following line
  // start_hub();

  while (!kbd.connect()) {
    Serial.println("No keyboard connected");
    delay(5000);
  }

  printf("\nKeyboard (%x:%x): connected\n", kbd.idVendor(), kbd.idProduct());

  uint8_t string_buffer[80];
  if (kbd.manufacturer(string_buffer, sizeof(string_buffer))) {
    Serial.print("Manufacturer: ");
    Serial.println((char*)string_buffer);
  }

  if (kbd.product(string_buffer, sizeof(string_buffer))) {
    Serial.print("Product: ");
    Serial.println((char*)string_buffer);
  }
  if (kbd.serialNumber(string_buffer, sizeof(string_buffer))) {
    Serial.print("Serial Number: ");
    Serial.println((char*)string_buffer);
  }

  kbd.attachPress(&kbd_key_cb);
  kbd.attachRawPress(&kbd_keycode_cb);
  kbd.attachRelease(&kbd_key_release_cb);
  kbd.attachHIDPress(&kbd_hid_key_press_cb);
  kbd.attachHIDRelease(&kbd_hid_key_release_cb);
  Serial.println("End of KBD Setup");
  

  while (!mouse.connect()) {
    Serial.println("No mouse connected");
    delay(5000);
  }
  printf("\nMouse (%x:%x): connected\n", mouse.idVendor(), mouse.idProduct());

  if (mouse.manufacturer(string_buffer, sizeof(string_buffer))) {
    Serial.print("Manufacturer: ");
    Serial.println((char*)string_buffer);
  }

  if (mouse.product(string_buffer, sizeof(string_buffer))) {
    Serial.print("Product: ");
    Serial.println((char*)string_buffer);
  }
  if (mouse.serialNumber(string_buffer, sizeof(string_buffer))) {
    Serial.print("Serial Number: ");
    Serial.println((char*)string_buffer);
  }
  
}

void loop() {
  if (mouse.available()) {
    Serial.print("Mouse: buttons = ");
    Serial.print(mouse.getButtons());
    Serial.print(",  mouseX = ");
    Serial.print(mouse.getMouseX());
    Serial.print(",  mouseY = ");
    Serial.print(mouse.getMouseY());
    Serial.print(",  wheel = ");
    Serial.print(mouse.getWheel());
    Serial.print(",  wheelH = ");
    Serial.print(mouse.getWheelH());
    Serial.println();
    mouse.mouseDataClear();
  }

}

void kbd_key_cb(uint8_t key) {
  Serial.print("Key pressed: ");
  Serial.print(key, HEX);
  Serial.print("(");
  if ((key >= ' ') && (key <= '~')) {
    Serial.write(key);
  } else {
    switch (key) {
      case USBHostKeyboardEx::KEYD_UP: Serial.print("UP"); break;
      case USBHostKeyboardEx::KEYD_DOWN: Serial.print("DN"); break;
      case USBHostKeyboardEx::KEYD_LEFT: Serial.print("LEFT"); break;
      case USBHostKeyboardEx::KEYD_RIGHT: Serial.print("RIGHT"); break;
      case USBHostKeyboardEx::KEYD_INSERT: Serial.print("Ins"); break;
      case USBHostKeyboardEx::KEYD_DELETE: Serial.print("Del"); break;
      case USBHostKeyboardEx::KEYD_PAGE_UP: Serial.print("PUP"); break;
      case USBHostKeyboardEx::KEYD_PAGE_DOWN: Serial.print("PDN"); break;
      case USBHostKeyboardEx::KEYD_HOME: Serial.print("HOME"); break;
      case USBHostKeyboardEx::KEYD_END: Serial.print("END"); break;
      case USBHostKeyboardEx::KEYD_F1: Serial.print("F1"); break;
      case USBHostKeyboardEx::KEYD_F2: Serial.print("F2"); break;
      case USBHostKeyboardEx::KEYD_F3: Serial.print("F3"); break;
      case USBHostKeyboardEx::KEYD_F4: Serial.print("F4"); break;
      case USBHostKeyboardEx::KEYD_F5: Serial.print("F5"); break;
      case USBHostKeyboardEx::KEYD_F6: Serial.print("F6"); break;
      case USBHostKeyboardEx::KEYD_F7: Serial.print("F7"); break;
      case USBHostKeyboardEx::KEYD_F8: Serial.print("F8"); break;
      case USBHostKeyboardEx::KEYD_F9: Serial.print("F9"); break;
      case USBHostKeyboardEx::KEYD_F10: Serial.print("F10"); break;
      case USBHostKeyboardEx::KEYD_F11: Serial.print("F11"); break;
      case USBHostKeyboardEx::KEYD_F12: Serial.print("F12"); break;
      default: Serial.print((char)key); break;
    }
  }
  Serial.println(")");
}

void kbd_key_release_cb(uint8_t key) {
  Serial.print("Key released: ");
  Serial.print(key, HEX);
  Serial.print("(");
  if ((key >= ' ') && (key <= '~')) {
    Serial.write(key);
  } else {
    switch (key) {
      case USBHostKeyboardEx::KEYD_UP: Serial.print("UP"); break;
      case USBHostKeyboardEx::KEYD_DOWN: Serial.print("DN"); break;
      case USBHostKeyboardEx::KEYD_LEFT: Serial.print("LEFT"); break;
      case USBHostKeyboardEx::KEYD_RIGHT: Serial.print("RIGHT"); break;
      case USBHostKeyboardEx::KEYD_INSERT: Serial.print("Ins"); break;
      case USBHostKeyboardEx::KEYD_DELETE: Serial.print("Del"); break;
      case USBHostKeyboardEx::KEYD_PAGE_UP: Serial.print("PUP"); break;
      case USBHostKeyboardEx::KEYD_PAGE_DOWN: Serial.print("PDN"); break;
      case USBHostKeyboardEx::KEYD_HOME: Serial.print("HOME"); break;
      case USBHostKeyboardEx::KEYD_END: Serial.print("END"); break;
      case USBHostKeyboardEx::KEYD_F1: Serial.print("F1"); break;
      case USBHostKeyboardEx::KEYD_F2: Serial.print("F2"); break;
      case USBHostKeyboardEx::KEYD_F3: Serial.print("F3"); break;
      case USBHostKeyboardEx::KEYD_F4: Serial.print("F4"); break;
      case USBHostKeyboardEx::KEYD_F5: Serial.print("F5"); break;
      case USBHostKeyboardEx::KEYD_F6: Serial.print("F6"); break;
      case USBHostKeyboardEx::KEYD_F7: Serial.print("F7"); break;
      case USBHostKeyboardEx::KEYD_F8: Serial.print("F8"); break;
      case USBHostKeyboardEx::KEYD_F9: Serial.print("F9"); break;
      case USBHostKeyboardEx::KEYD_F10: Serial.print("F10"); break;
      case USBHostKeyboardEx::KEYD_F11: Serial.print("F11"); break;
      case USBHostKeyboardEx::KEYD_F12: Serial.print("F12"); break;
      default: Serial.print((char)key); break;
    }
  }
  Serial.println(")");
}


void kbd_keycode_cb(uint8_t keycode, uint8_t mod) {
  Serial.print("Keycode: ");
  Serial.print(keycode, HEX);
  Serial.print(" mod: ");
  Serial.println(mod, HEX);
}

void kbd_hid_key_press_cb(uint32_t top, uint16_t code) {
  Serial.print("Press: HID Key: Page:0x");
  print_hid_data(top, code);
}

void kbd_hid_key_release_cb(uint32_t top, uint16_t code) {
  Serial.print("Release: HID Key: Page:0x");
  print_hid_data(top, code);
}


void print_hid_data(uint32_t top, uint32_t code) {
  Serial.print(top, HEX);
  Serial.print(" Code: 0x");
  Serial.print(code, HEX);
  if (top == 0x0c) {
    switch (code) {
      case 0x20: Serial.println(" - +10"); return;
      case 0x21: Serial.println(" - +100"); return;
      case 0x22: Serial.println(" - AM/PM"); return;
      case 0x23: Serial.println(" - Home"); return;
      case 0x30: Serial.println(" - Power"); return;
      case 0x31: Serial.println(" - Reset"); return;
      case 0x32: Serial.println(" - Sleep"); return;
      case 0x33: Serial.println(" - Sleep After"); return;
      case 0x34: Serial.println(" - Sleep Mode"); return;
      case 0x35: Serial.println(" - Illumination"); return;
      case 0x36: Serial.println(" - Function Buttons"); return;
      case 0x40: Serial.println(" - Menu"); return;
      case 0x41: Serial.println(" - Menu  Pick"); return;
      case 0x42: Serial.println(" - Menu Up"); return;
      case 0x43: Serial.println(" - Menu Down"); return;
      case 0x44: Serial.println(" - Menu Left"); return;
      case 0x45: Serial.println(" - Menu Right"); return;
      case 0x46: Serial.println(" - Menu Escape"); return;
      case 0x47: Serial.println(" - Menu Value Increase"); return;
      case 0x48: Serial.println(" - Menu Value Decrease"); return;
      case 0x60: Serial.println(" - Data On Screen"); return;
      case 0x61: Serial.println(" - Closed Caption"); return;
      case 0x62: Serial.println(" - Closed Caption Select"); return;
      case 0x63: Serial.println(" - VCR/TV"); return;
      case 0x64: Serial.println(" - Broadcast Mode"); return;
      case 0x65: Serial.println(" - Snapshot"); return;
      case 0x66: Serial.println(" - Still"); return;
      case 0x80: Serial.println(" - Selection"); return;
      case 0x81: Serial.println(" - Assign Selection"); return;
      case 0x82: Serial.println(" - Mode Step"); return;
      case 0x83: Serial.println(" - Recall Last"); return;
      case 0x84: Serial.println(" - Enter Channel"); return;
      case 0x85: Serial.println(" - Order Movie"); return;
      case 0x86: Serial.println(" - Channel"); return;
      case 0x87: Serial.println(" - Media Selection"); return;
      case 0x88: Serial.println(" - Media Select Computer"); return;
      case 0x89: Serial.println(" - Media Select TV"); return;
      case 0x8A: Serial.println(" - Media Select WWW"); return;
      case 0x8B: Serial.println(" - Media Select DVD"); return;
      case 0x8C: Serial.println(" - Media Select Telephone"); return;
      case 0x8D: Serial.println(" - Media Select Program Guide"); return;
      case 0x8E: Serial.println(" - Media Select Video Phone"); return;
      case 0x8F: Serial.println(" - Media Select Games"); return;
      case 0x90: Serial.println(" - Media Select Messages"); return;
      case 0x91: Serial.println(" - Media Select CD"); return;
      case 0x92: Serial.println(" - Media Select VCR"); return;
      case 0x93: Serial.println(" - Media Select Tuner"); return;
      case 0x94: Serial.println(" - Quit"); return;
      case 0x95: Serial.println(" - Help"); return;
      case 0x96: Serial.println(" - Media Select Tape"); return;
      case 0x97: Serial.println(" - Media Select Cable"); return;
      case 0x98: Serial.println(" - Media Select Satellite"); return;
      case 0x99: Serial.println(" - Media Select Security"); return;
      case 0x9A: Serial.println(" - Media Select Home"); return;
      case 0x9B: Serial.println(" - Media Select Call"); return;
      case 0x9C: Serial.println(" - Channel Increment"); return;
      case 0x9D: Serial.println(" - Channel Decrement"); return;
      case 0x9E: Serial.println(" - Media Select SAP"); return;
      case 0xA0: Serial.println(" - VCR Plus"); return;
      case 0xA1: Serial.println(" - Once"); return;
      case 0xA2: Serial.println(" - Daily"); return;
      case 0xA3: Serial.println(" - Weekly"); return;
      case 0xA4: Serial.println(" - Monthly"); return;
      case 0xB0: Serial.println(" - Play"); return;
      case 0xB1: Serial.println(" - Pause"); return;
      case 0xB2: Serial.println(" - Record"); return;
      case 0xB3: Serial.println(" - Fast Forward"); return;
      case 0xB4: Serial.println(" - Rewind"); return;
      case 0xB5: Serial.println(" - Scan Next Track"); return;
      case 0xB6: Serial.println(" - Scan Previous Track"); return;
      case 0xB7: Serial.println(" - Stop"); return;
      case 0xB8: Serial.println(" - Eject"); return;
      case 0xB9: Serial.println(" - Random Play"); return;
      case 0xBA: Serial.println(" - Select DisC"); return;
      case 0xBB: Serial.println(" - Enter Disc"); return;
      case 0xBC: Serial.println(" - Repeat"); return;
      case 0xBD: Serial.println(" - Tracking"); return;
      case 0xBE: Serial.println(" - Track Normal"); return;
      case 0xBF: Serial.println(" - Slow Tracking"); return;
      case 0xC0: Serial.println(" - Frame Forward"); return;
      case 0xC1: Serial.println(" - Frame Back"); return;
      case 0xC2: Serial.println(" - Mark"); return;
      case 0xC3: Serial.println(" - Clear Mark"); return;
      case 0xC4: Serial.println(" - Repeat From Mark"); return;
      case 0xC5: Serial.println(" - Return To Mark"); return;
      case 0xC6: Serial.println(" - Search Mark Forward"); return;
      case 0xC7: Serial.println(" - Search Mark Backwards"); return;
      case 0xC8: Serial.println(" - Counter Reset"); return;
      case 0xC9: Serial.println(" - Show Counter"); return;
      case 0xCA: Serial.println(" - Tracking Increment"); return;
      case 0xCB: Serial.println(" - Tracking Decrement"); return;
      case 0xCD: Serial.println(" - Pause/Continue"); return;
      case 0xE0: Serial.println(" - Volume"); return;
      case 0xE1: Serial.println(" - Balance"); return;
      case 0xE2: Serial.println(" - Mute"); return;
      case 0xE3: Serial.println(" - Bass"); return;
      case 0xE4: Serial.println(" - Treble"); return;
      case 0xE5: Serial.println(" - Bass Boost"); return;
      case 0xE6: Serial.println(" - Surround Mode"); return;
      case 0xE7: Serial.println(" - Loudness"); return;
      case 0xE8: Serial.println(" - MPX"); return;
      case 0xE9: Serial.println(" - Volume Up"); return;
      case 0xEA: Serial.println(" - Volume Down"); return;
      case 0xF0: Serial.println(" - Speed Select"); return;
      case 0xF1: Serial.println(" - Playback Speed"); return;
      case 0xF2: Serial.println(" - Standard Play"); return;
      case 0xF3: Serial.println(" - Long Play"); return;
      case 0xF4: Serial.println(" - Extended Play"); return;
      case 0xF5: Serial.println(" - Slow"); return;
      case 0x100: Serial.println(" - Fan Enable"); return;
      case 0x101: Serial.println(" - Fan Speed"); return;
      case 0x102: Serial.println(" - Light"); return;
      case 0x103: Serial.println(" - Light Illumination Level"); return;
      case 0x104: Serial.println(" - Climate Control Enable"); return;
      case 0x105: Serial.println(" - Room Temperature"); return;
      case 0x106: Serial.println(" - Security Enable"); return;
      case 0x107: Serial.println(" - Fire Alarm"); return;
      case 0x108: Serial.println(" - Police Alarm"); return;
      case 0x150: Serial.println(" - Balance Right"); return;
      case 0x151: Serial.println(" - Balance Left"); return;
      case 0x152: Serial.println(" - Bass Increment"); return;
      case 0x153: Serial.println(" - Bass Decrement"); return;
      case 0x154: Serial.println(" - Treble Increment"); return;
      case 0x155: Serial.println(" - Treble Decrement"); return;
      case 0x160: Serial.println(" - Speaker System"); return;
      case 0x161: Serial.println(" - Channel Left"); return;
      case 0x162: Serial.println(" - Channel Right"); return;
      case 0x163: Serial.println(" - Channel Center"); return;
      case 0x164: Serial.println(" - Channel Front"); return;
      case 0x165: Serial.println(" - Channel Center Front"); return;
      case 0x166: Serial.println(" - Channel Side"); return;
      case 0x167: Serial.println(" - Channel Surround"); return;
      case 0x168: Serial.println(" - Channel Low Frequency Enhancement"); return;
      case 0x169: Serial.println(" - Channel Top"); return;
      case 0x16A: Serial.println(" - Channel Unknown"); return;
      case 0x170: Serial.println(" - Sub-channel"); return;
      case 0x171: Serial.println(" - Sub-channel Increment"); return;
      case 0x172: Serial.println(" - Sub-channel Decrement"); return;
      case 0x173: Serial.println(" - Alternate Audio Increment"); return;
      case 0x174: Serial.println(" - Alternate Audio Decrement"); return;
      case 0x180: Serial.println(" - Application Launch Buttons"); return;
      case 0x181: Serial.println(" - AL Launch Button Configuration Tool"); return;
      case 0x182: Serial.println(" - AL Programmable Button Configuration"); return;
      case 0x183: Serial.println(" - AL Consumer Control Configuration"); return;
      case 0x184: Serial.println(" - AL Word Processor"); return;
      case 0x185: Serial.println(" - AL Text Editor"); return;
      case 0x186: Serial.println(" - AL Spreadsheet"); return;
      case 0x187: Serial.println(" - AL Graphics Editor"); return;
      case 0x188: Serial.println(" - AL Presentation App"); return;
      case 0x189: Serial.println(" - AL Database App"); return;
      case 0x18A: Serial.println(" - AL Email Reader"); return;
      case 0x18B: Serial.println(" - AL Newsreader"); return;
      case 0x18C: Serial.println(" - AL Voicemail"); return;
      case 0x18D: Serial.println(" - AL Contacts/Address Book"); return;
      case 0x18E: Serial.println(" - AL Calendar/Schedule"); return;
      case 0x18F: Serial.println(" - AL Task/Project Manager"); return;
      case 0x190: Serial.println(" - AL Log/Journal/Timecard"); return;
      case 0x191: Serial.println(" - AL Checkbook/Finance"); return;
      case 0x192: Serial.println(" - AL Calculator"); return;
      case 0x193: Serial.println(" - AL A/V Capture/Playback"); return;
      case 0x194: Serial.println(" - AL Local Machine Browser"); return;
      case 0x195: Serial.println(" - AL LAN/WAN Browser"); return;
      case 0x196: Serial.println(" - AL Internet Browser"); return;
      case 0x197: Serial.println(" - AL Remote Networking/ISP Connect"); return;
      case 0x198: Serial.println(" - AL Network Conference"); return;
      case 0x199: Serial.println(" - AL Network Chat"); return;
      case 0x19A: Serial.println(" - AL Telephony/Dialer"); return;
      case 0x19B: Serial.println(" - AL Logon"); return;
      case 0x19C: Serial.println(" - AL Logoff"); return;
      case 0x19D: Serial.println(" - AL Logon/Logoff"); return;
      case 0x19E: Serial.println(" - AL Terminal Lock/Screensaver"); return;
      case 0x19F: Serial.println(" - AL Control Panel"); return;
      case 0x1A0: Serial.println(" - AL Command Line Processor/Run"); return;
      case 0x1A1: Serial.println(" - AL Process/Task Manager"); return;
      case 0x1A2: Serial.println(" - AL Select Tast/Application"); return;
      case 0x1A3: Serial.println(" - AL Next Task/Application"); return;
      case 0x1A4: Serial.println(" - AL Previous Task/Application"); return;
      case 0x1A5: Serial.println(" - AL Preemptive Halt Task/Application"); return;
      case 0x200: Serial.println(" - Generic GUI Application Controls"); return;
      case 0x201: Serial.println(" - AC New"); return;
      case 0x202: Serial.println(" - AC Open"); return;
      case 0x203: Serial.println(" - AC Close"); return;
      case 0x204: Serial.println(" - AC Exit"); return;
      case 0x205: Serial.println(" - AC Maximize"); return;
      case 0x206: Serial.println(" - AC Minimize"); return;
      case 0x207: Serial.println(" - AC Save"); return;
      case 0x208: Serial.println(" - AC Print"); return;
      case 0x209: Serial.println(" - AC Properties"); return;
      case 0x21A: Serial.println(" - AC Undo"); return;
      case 0x21B: Serial.println(" - AC Copy"); return;
      case 0x21C: Serial.println(" - AC Cut"); return;
      case 0x21D: Serial.println(" - AC Paste"); return;
      case 0x21E: Serial.println(" - AC Select All"); return;
      case 0x21F: Serial.println(" - AC Find"); return;
      case 0x220: Serial.println(" - AC Find and Replace"); return;
      case 0x221: Serial.println(" - AC Search"); return;
      case 0x222: Serial.println(" - AC Go To"); return;
      case 0x223: Serial.println(" - AC Home"); return;
      case 0x224: Serial.println(" - AC Back"); return;
      case 0x225: Serial.println(" - AC Forward"); return;
      case 0x226: Serial.println(" - AC Stop"); return;
      case 0x227: Serial.println(" - AC Refresh"); return;
      case 0x228: Serial.println(" - AC Previous Link"); return;
      case 0x229: Serial.println(" - AC Next Link"); return;
      case 0x22A: Serial.println(" - AC Bookmarks"); return;
      case 0x22B: Serial.println(" - AC History"); return;
      case 0x22C: Serial.println(" - AC Subscriptions"); return;
      case 0x22D: Serial.println(" - AC Zoom In"); return;
      case 0x22E: Serial.println(" - AC Zoom Out"); return;
      case 0x22F: Serial.println(" - AC Zoom"); return;
      case 0x230: Serial.println(" - AC Full Screen View"); return;
      case 0x231: Serial.println(" - AC Normal View"); return;
      case 0x232: Serial.println(" - AC View Toggle"); return;
      case 0x233: Serial.println(" - AC Scroll Up"); return;
      case 0x234: Serial.println(" - AC Scroll Down"); return;
      case 0x235: Serial.println(" - AC Scroll"); return;
      case 0x236: Serial.println(" - AC Pan Left"); return;
      case 0x237: Serial.println(" - AC Pan Right"); return;
      case 0x238: Serial.println(" - AC Pan"); return;
      case 0x239: Serial.println(" - AC New Window"); return;
      case 0x23A: Serial.println(" - AC Tile Horizontally"); return;
      case 0x23B: Serial.println(" - AC Tile Vertically"); return;
      case 0x23C: Serial.println(" - AC Format"); return;
    }
  }
  Serial.println();
}

On the other hand the RII Keyboard/mouse combo ( Rii RKM709 2.4 Gigahertz Ultra-Slim Wireless Keyboard and Mouse Combo) shows as:

Starting Keyboard test...

Keyboard (276d:3257): connected
Product: 2.4G RF Keyboard & Mouse
End of KBD Setup

Mouse (276d:3257): connected
Product: 2.4G RF Keyboard & Mouse

but only one or the other will work continuously. Keeps loosing the keyboard after a few strokes and mouse then doesn;t work

If i use only the mouse or keyboard it works fine if its on a hub. If I try the same thing directly connected it hangs after a few strokes but I then connect the mouse it works - ARGH?