Teensy-based mouse can't connect to CircuitsAtHome USBhost

Status
Not open for further replies.

PhilK

Member
A bit of a surprise, but I have a Teensy 3.6-based mouse (i.e. USB HID device) which works fine on windows machines. I also have an Arduino Due-based USB host, which is running the Arduino-official USBhost library (the inner code is labelled with the CircuitsAtHome signature). When I connect any generic mouse to the Due USBhost, it works fine. Amazon mouse--fine. Any gaming mouse--fine. But the only USB mouse that I've found that *doesn't* work with USBhost is my Teensy mouse.

I thought it might have something to do with all the extra interfaces and endpoints (i.e. mouse is bundled with keyboard and joystick and serial) that Teensy presents, but after much pain of eliminating the the keyboard and joystick, it still does not connect. USBhost internally runs into a problem where bNumEP=1, and if bNumEP is not 2, it declares ERROR, device not supported.

I tried with both a Teensy LC and Teensy 3.6, same problem same error in both cases. I've tried all the other USB type menu selections for Teensy that include mouse, same error.

The Due is running the built-in examples/USBhost/MouseController.ino with an OTG cable on the native USB port (works fine with other mice). The Teensy LC or 3.6 is running a simple demo code that sends a mouse movement of 5 pixels every 2 seconds. (The problem occurs when you first plug in the Teeny mouse into the USBhost.) Should be very easy for anyone to reproduce.

I'm aware that there are other USBhosts I could use (like the USBhost_t36 library), but I'm looking for something super-cheapo. Plus, it's curious to me that such a widely-used host library would fail with such a widely-used USB device platform.

Can anyone else duplicate/explain this? I would also be interested if anyone knows of a different low-cost $12-ish USBhost library/platform that *does* work with Teensy HID devices.

Many thanks,
Phil
 
Since it appears the error occurs in the CircuitsAtHome code, I would think this issue could be duplicated by using a Teensy USB host shield and then plugging a Teensy LC or Teensy 3.6 HID device into it. (It would be odd that no one had tried that before? Plugging a Teensy into a Teensy?)
 
I would think this issue could be duplicated by using a Teensy USB host shield

There is no "Teensy USB host shield". But there are lots of host shield projects out there, none of which (as far as I know) are specifically meant for Teensy. I probably still have a couple sitting in a box somewhere, though it's been quite a long time since I've done any testing with that library.

Recommend you create a bug report on that project, since it's almost certainly a bug or limitation in their code. Might be worthwhile putting very specific info into that report of exactly which boards & shields you're using for testing.

Plugging a Teensy into a Teensy?

Have you tried it with the USBHost_t36 library, of course using Teensy 3.6's USB host port?
 
The USB Host Shield (UHS2) library looks for the USB interface triplet (class ID=3, subclass ID=1, protocol=2) for mouse devices but the Teensy USB device library reports (3, 0, 0). I assume other USB host stacks infer the HID mouse interface by parsing the HID report descriptor associated with each interface. UHS2 does not.

Try changing the interface subclass ID and protocol in usb_desc.c. This may only get you one step further because UHS2 may have other problems with unusual USB devices.

Code:
#ifdef MOUSE_INTERFACE
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
        MOUSE_INTERFACE,                        // bInterfaceNumber
        0,                                      // bAlternateSetting
        1,                                      // bNumEndpoints
        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x01,                                   // bInterfaceSubClass (0x01 = Boot)
+        0x02,                                   // bInterfaceProtocol (0x02 = Mouse)
-        0x00,                                   // bInterfaceSubClass (0x01 = Boot)
-        0x00,                                   // bInterfaceProtocol (0x02 = Mouse)
        0,                                      // iInterface
 
If you change the descriptor to say we're sending boot protocol reports, you'll also need to edit the code which sends the HID reports.

We're currently using report IDs to send 2 different report formats. One is for relative movement and the other is for absolute coordinates. The relative one is probably close enough to the boot protocol report, as long as you delete the first byte and move all the other bytes 1 place. The absolute coordinates report is nothing like the boot protocol report, so there's no way to keep Mouse.moveTo(x, y) with the boot protocol.
 
If you change the descriptor to say we're sending boot protocol reports, you'll also need to edit the code which sends the HID reports.

We're currently using report IDs to send 2 different report formats. One is for relative movement and the other is for absolute coordinates. The relative one is probably close enough to the boot protocol report, as long as you delete the first byte and move all the other bytes 1 place. The absolute coordinates report is nothing like the boot protocol report, so there's no way to keep Mouse.moveTo(x, y) with the boot protocol.

Thank you both for your guidance. Pointed by you in the correct direction to meander, I think I am coming to an improved understanding. As I understand it, a USB mouse may operate in two different modes; (1) a BOOT-mouse mode, which is designed to provide simple mouse functionality, for example for PC BIOS, with very small host-side code, and (2) a more fully-featured REPORT-mode, which uses a flexibly-defined report, but requires the host code to parse and understand the table sent from the mouse to define what its reports will look like.

It appears that the USBHOST code can only use the BOOT-mode, and the Teensyduino USB implementation can only use the REPORT-mode. Is that correct?


I have identified in the USB host code https://github.com/arduino-libraries/USBHost/blob/master/src/confdescparser.h
that when the Teensy mouse is first plugged in, this condition in confdescparser.h is tripped:

if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID)
break;

which, as you said, indicates that the host code is expecting a SUBCLASS_ID of 1 but the Teensy is sending SUBCLASS_ID of 0. The host then bails out and no connection is made. All the other mice, when plugged in, have the expected SUBCLASS_ID of 1 and so don't trip this condition.

Please let me know if/where I'm off-base. I will investigate adapting the Teensyduino code to use boot mode, to the extent I'm able. Many thanks,

Phil
 
As I understand it, a USB mouse may operate in two different modes; (1) a BOOT-mouse mode, which is designed to provide simple mouse functionality, for example for PC BIOS, with very small host-side code, and (2) a more fully-featured REPORT-mode, which uses a flexibly-defined report, but requires the host code to parse and understand the table sent from the mouse to define what its reports will look like.
.....
Please let me know if/where I'm off-base.

That's close. All HID devices operate by sending a fixed-size message called a "report". Boot protocol is no different.

But the first several bytes of the report have fixed meaning. Boot protocol is meant for simple hosts (the boot BIOS on older PCs) to be able to use the most basic mouse functionality without reading & parsing the HID report descriptor.

The decision to not use the boot protocol HID report format wasn't made lightly. Today the cheapest mice still use it, but more fully featured ones are pretty common these days. Such mice won't work with UHS either.

Teensy's Mouse.moveTo(x, y) function was the main reason to go with a generic HID report.
 
Have you tried it with the USBHost_t36 library, of course using Teensy 3.6's USB host port?

Just gave this a try; using the USBHost_t36 on the second port of a Teensy 3.6, all the USB mice I have work perfectly, including the Teensy-based mouse and also a MKRZERO-based mouse, (both of which did not work with UHS2.0). Very impressive!
 
Status
Not open for further replies.
Back
Top