[solved] two strange USB mouses

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

[solved] two strange USB mouses

Post 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
Last edited by Klakap on Sat Apr 08, 2023 1:12 am, edited 1 time in total.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: two strange USB mouses

Post 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
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: two strange USB mouses

Post 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.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: two strange USB mouses

Post 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
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: two strange USB mouses

Post 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.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: two strange USB mouses

Post 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
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: two strange USB mouses

Post 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
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: two strange USB mouses

Post 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?
sounds
Member
Member
Posts: 112
Joined: Sat Feb 04, 2012 5:03 pm

Re: two strange USB mouses

Post 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
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: two strange USB mouses

Post 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.
Carpe diem!
rdos
Member
Member
Posts: 3296
Joined: Wed Oct 01, 2008 1:55 pm

Re: two strange USB mouses

Post 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.
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: two strange USB mouses

Post 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.
Post Reply