Page 1 of 1

[solved] two strange USB mouses

Posted: Sat Apr 01, 2023 10:33 am
by Klakap
I am testing my new code for USB mouses. So far many mouses worked perfectly, however I found two mouses that are not working correctly under my code. However they are working correctly under classic operating systems. These two mouses have some things common. Both are low speed devices, both report only first 8 bytes from USB descriptor and both are reporting mouse movement in 12 bytes.
First mouse reports only very small movement. When I move mouse quicker, it stops sending packets. It looks like it is reporting only movement to four or three bits instead of twelve bits.
Second mouse reports only four bits instead of twelve, and these bits are high bits of 12 bit space for report. So normal report of change 1 should be 0x001, but mouse report is 0x100.

What I tried so far:
- I read that some low speed devices repot only first 8 bytes from USB descriptor and than need to be reset and than they return full 18 bytes of descriptor. I tried this procedure, however nothing changed.
- I tried to send SET_IDLE request

Does anybody has experience with similar problem and know what I missed?

Here is HID descriptor of first mouse:

Code: Select all

 0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x02,        // Usage (Mouse)
0xA1, 0x01,        // Collection (Application)
0x09, 0x01,        //   Usage (Pointer)
0xA1, 0x00,        //   Collection (Physical)
0x05, 0x09,        //     Usage Page (Button)
0x19, 0x01,        //     Usage Minimum (0x01)
0x29, 0x05,        //     Usage Maximum (0x05)
0x15, 0x00,        //     Logical Minimum (0)
0x25, 0x01,        //     Logical Maximum (1)
0x95, 0x05,        //     Report Count (5)
0x75, 0x01,        //     Report Size (1)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01,        //     Report Count (1)
0x75, 0x03,        //     Report Size (3)
0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x30,        //     Usage (X)
0x09, 0x31,        //     Usage (Y)
0x16, 0x00, 0xF8,  //     Logical Minimum (-2048)
0x26, 0xFF, 0x07,  //     Logical Maximum (2047)
0x75, 0x0C,        //     Report Size (12)
0x95, 0x02,        //     Report Count (2)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x38,        //     Usage (Wheel)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x75, 0x08,        //     Report Size (8)
0x95, 0x01,        //     Report Count (1)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //   End Collection
0xC0,              // End Collection
And here is HID descriptor of second mouse:

Code: Select all

 0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x02,        // Usage (Mouse)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x09, 0x01,        //   Usage (Pointer)
0xA1, 0x00,        //   Collection (Physical)
0x05, 0x09,        //     Usage Page (Button)
0x19, 0x01,        //     Usage Minimum (0x01)
0x29, 0x03,        //     Usage Maximum (0x03)
0x15, 0x00,        //     Logical Minimum (0)
0x25, 0x01,        //     Logical Maximum (1)
0x95, 0x03,        //     Report Count (3)
0x75, 0x01,        //     Report Size (1)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01,        //     Report Count (1)
0x75, 0x05,        //     Report Size (5)
0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x30,        //     Usage (X)
0x09, 0x31,        //     Usage (Y)
0x16, 0x00, 0xF8,  //     Logical Minimum (-2048)
0x26, 0xFF, 0x07,  //     Logical Maximum (2047)
0x75, 0x0C,        //     Report Size (12)
0x95, 0x02,        //     Report Count (2)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x38,        //     Usage (Wheel)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x75, 0x08,        //     Report Size (8)
0x95, 0x01,        //     Report Count (1)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //   End Collection
0xC0,              // End Collection
Note: code in my repository is not my actual new code

Re: two strange USB mouses

Posted: Sat Apr 01, 2023 1:10 pm
by BenLunt
My first thought is:
- A mouse is suppose to start out with the HID Protocol interrupt packet, however some can do the Boot Protocol interrupt packet instead. Have you set the Protocol to use beforehand? i.e.: Don't assume one or the other report. Always use the SET_PROTOCOL request beforehand.

Code: Select all

 HID 1.11, section 7.2.6, page 54(64):
  "When initialized, all devices default to report protocol. However the host should not make any assumptions about the device’s state and should set the desired protocol whenever initializing a device."
I am guessing, without looking further, that you are assuming the HID report, but receiving the BOOT report. This is why your values don't make sense.

Just a thought,
Ben
- https://www.fysnet.net/the_universal_serial_bus.htm

Re: two strange USB mouses

Posted: Sat Apr 01, 2023 1:56 pm
by Klakap
yes, I send SET_PROTOCOL after receiving HID protocol. and problem is not only with values, but also that with faster movement mouses do not send data. It looks like it is somehow stucked to send only movement within range 1-8 positive or negative, and all bigger values are not reported.

Re: two strange USB mouses

Posted: Sat Apr 01, 2023 2:25 pm
by BenLunt
What do you calculate the reports to be?

I see them as: (first device followed by second device)

Code: Select all

byte 0: 000BBBBB
byte 1: XXXXXXXX
byte 2: YYYYXXXX
byte 3: YYYYYYYY
byte 4: ZZZZZZZZ
byte 5 --> max_packet_size - 1: unused

byte 0: 00000BBB
byte 1: XXXXXXXX
byte 2: YYYYXXXX
byte 3: YYYYYYYY
byte 4: ZZZZZZZZ
byte 5 --> max_packet_size - 1: unused
The low order byte of X is in byte 1, with the high order nibble (of a 12-bit word) in the low order nibble of byte 2.
The low order nibble of Y is in the high order nibble of byte 2 with the high order byte (of a 12-bit word) in byte 3.
All of Z is in byte 4.

X = ((byte2 & 0x0F) << 8) | byte1;
Y = ((byte3 << 4) | (byte2 >> 4));
Z = byte4;
// assuming that your compiler promotes byte2 and byte3 to the platform's word size
// i.e.: don't let the shift drop off the bits
// also, you need to promote a 12-bit value to a 16, 32, or 64-bit signed value using bit 11 of X and Y

Do you agree with this report format?

Ben

Re: two strange USB mouses

Posted: Sat Apr 01, 2023 2:52 pm
by Klakap
yes, thats exactly how my code interpret this report. but it seems like first mouse sends something like this:

Code: Select all

byte 0: 000BBBBB
byte 1: 0000XXXX
byte 2: YYYY0000
byte 3: 00000000
and second mouse something like this:

Code: Select all

byte 0: 00000BBB
byte 1: 00000000
byte 2: 0000XXXX
byte 3: YYYY0000
I did not tested Z value yet, so I can not say how is it reported.

Re: two strange USB mouses

Posted: Sun Apr 02, 2023 8:13 am
by BenLunt
You have me for a loss then. I can only think of a few things then:
- check that your packet buffer isn't being overwritten by another packet
- make sure you aren't reading the packet before the interrupt fires

That's it, I can't think of anything else at the moment. I am sure it is something simple, it just will be difficult to find it.

Good luck,
Ben

Re: two strange USB mouses

Posted: Tue Apr 04, 2023 3:55 pm
by BenLunt
Klakap wrote: And here is HID descriptor of second mouse:

Code: Select all

 0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x02,        // Usage (Mouse)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x09, 0x01,        //   Usage (Pointer)
I was thinking of something, came back and saw that the second mouse uses the Report ID.
This means that the value of 1 (current report id given above) will be prepended to your input report.

Code: Select all

byte 0:  00000001
byte 1:  00000BBB
byte 2:  XXXXXXXX
byte 3:  YYYYXXXX
byte 4:  YYYYYYYY
byte 5:  WWWWWWWW
I completely missed the following line in the second mouse's report. The first mouse doesn't have it.

Code: Select all

0x85, 0x01,        //   Report ID (1)
Sorry I missed this before.
Ben

Re: two strange USB mouses

Posted: Thu Apr 06, 2023 2:56 am
by Klakap
thank you. When I add this to my HID parser, I found that second mouse is reporting correct values, but it looks like it do not send some packets. Faster I move, more packets are not send. When I move really fast, no packets are send. And on first mouse it is same, but it drops packets much faster, so with little faster movement it already do not report anything. When I move mouses really slowly, it looks like it report everything perfectly. I tried to change period of receiving packets. configuration descriptor states that I should pool interrupt endpoint every 10 ms. I tried to pool it for 4, 8, 10 and 16 ms. 4, 8 and 10 ms showed same results, in 16 even more packets were dropped, as expected. Is there some command that I forgot to send to prevent dropping packets or something like this?

Re: two strange USB mouses

Posted: Thu Apr 06, 2023 9:32 am
by sounds
It's possible they require vendor-specific commands to configure them, and prevent the drop-outs you're seeing.

Just as an example, here's a Logitech mouse and the customer reverse engineered the custom command to change its polling rate:

https://askubuntu.com/questions/624075

Re: two strange USB mouses

Posted: Thu Apr 06, 2023 11:45 am
by nullplan
Well, if it's that then you can plug these things into a Windows computer and use Wireshark to capture the USB packets. If the mice work correctly in Windows, then check what it is doing different from you.

Re: two strange USB mouses

Posted: Thu Apr 06, 2023 3:27 pm
by rdos
I think for serious USB development there is a need to have a hardware analyser. I have one at work that can analyse up to USB 2. They are a bit expensive though.

Re: two strange USB mouses

Posted: Sat Apr 08, 2023 1:12 am
by Klakap
nullplan wrote:Well, if it's that then you can plug these things into a Windows computer and use Wireshark to capture the USB packets. If the mice work correctly in Windows, then check what it is doing different from you.
thank you, I didin’t know that Wireshark can capture USB comunication as well, and it is really usefull to know. Anyway, I found that Linux initalize that mouse in same way as I.
But I finally found the mistake. It was something so simple that it was really hard to find. It was because I thougth that for interrupt transfers you have to take care about toggle bit. And I thougth that I found clever way how to get rid of it. I chained two TD, first with toggle 0 and transferring data and second with toggle 1 and transferring zero data and I was pointing in frame list just to first one. But it was stupid idea, because some hardware, as those two mouses do not care if you transfer something or not, if there is some packet they assume you get data. So that was how packets were lost. And they were lost even that this second TD was directly chained to first TD. So when I realize this, I just simply removed second TD and all USB mouses now works perfectly.
//edit: you have to take care about toggle bit in interrupt transfers, but do not do it like me here. much better idea is change toggle bit of transfer descriptor when you receive packet.