usb_mouse_move 16 bit x and y request

Trip

Member
I have a bit of a strange request.

Maybe someone saw in my last thread that I wanted to implement an adjustable polling rate for the mouse. To do a double blind test.
I never really intended to add this feature but since the first comment was immediatly about that it is not perceivable and all, I kind of want to add it now.

The problem I was running into is that at lower polling rates the 8 bit x and y value start to overflow of the int usb_mouse_move(int16_t x, int16_t y, int8_t wheel, int8_t horiz) function in the cores/teensy4/usb_mouse.c file.
At higher polling rates this is not a problem since 8 values of 64 do not go over the limit of 128 but one value of 512 obviously does.
This already started to become a problem at a 1000Hz if I move the mouse very quickly it would spin out and malfunction at 125Hz I can only move it really slow.

So I implemented the function to support 16 bit values by changing the HID mouse descriptor and the functions.
Now everything works fine for me but I was wondering if this change could be added in the next update of teensyduino. ​
It still works properly with 8 bit values, well with the exception of my very specific issue.
So I dont think there are incompatibility issues with older code.

Parts of the code that I changed full code is also attached in the .zip:

usb_mouse.h
int usb_mouse_move(int16_t x, int16_t y, int8_t wheel, int8_t horiz);

usb_mouse.c
// Move the mouse. x, y and wheel are -32767 to 32767. Use 0 for no movement.
int usb_mouse_move(int16_t x, int16_t y, int8_t wheel, int8_t horiz)
{
//printf("move\n");
if (x == -32768) x = -32767;
if (y == -32768) y = -32767;
if (wheel == -128) wheel = -127;
if (horiz == -128) horiz = -127;

int8_t buffer[8];
buffer[0] = 1;
buffer[1] = usb_mouse_buttons_state;
buffer[2] = x;
buffer[3] = (x >> 8);
buffer[4] = y;
buffer[5] = (y >> 8);
buffer[6] = wheel;
buffer[7] = horiz;
return usb_mouse_transmit(buffer, 8);
}

usb_desc.c

#ifdef MOUSE_INTERFACE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x08, // Usage Maximum (Button #8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x16, 0x01, 0x80, // Logical Minimum (-32767)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x02, // Report Count (2),
0x81, 0x06, // Input (Data, Variable, Relative)
0x05, 0x01, // Usage Page (Generic Desktop)
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, Variable, Relative)
0x05, 0x0C, // Usage Page (Consumer)
0x0A, 0x38, 0x02, // Usage (AC Pan)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8),
0x95, 0x01, // Report Count (1),
0x81, 0x06, // Input (Data, Variable, Relative)
0xC0, // End Collection
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // REPORT_ID (2)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x02, // Report Count (2),
0x81, 0x02, // Input (Data, Variable, Absolute)
0xC0 // End Collection
};
#endif
 

Attachments

  • usb_mouse_changes.zip
    19.9 KB · Views: 64
So I've been trying to follow along, but the USB HID Definition is giving me headaches, as I want to add another 16 Bit axis, identical to X and Y, so I added one, like this but it's not working, if I try and leave most things alone with "wheel" and just increase the range it's predictable as it works, but doesn't increase resolution, if I add another axis to the pair x and y, I get nothig works.
Code:
#ifdef MOUSE_INTERFACE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x08, // Usage Maximum (Button #8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x16, 0x01, 0x80, // Logical Minimum (-32767)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x03, // Report Count (3),
0x81, 0x06, // Input (Data, Variable, Relative)
//0x05, 0x01, // Usage Page (Generic Desktop)
//0x09, 0x38, // Usage (Wheel)
//0x15, 0x81, // Logical Minimum (-127)
//0x25, 0x7F, // Logical Maximum (127)
//0x16, 0x01, 0x80, // Logical Minimum (-32767)
//0x26, 0xFF, 0x7F, // Logical Maximum (32767)
//0x75, 0x08, // Report Size (8),
//0x75, 0x10, // Report Size (16),
//0x95, 0x01, // Report Count (1),
//0x81, 0x06, // Input (Data, Variable, Relative)
0x05, 0x0C, // Usage Page (Consumer)
0x0A, 0x38, 0x02, // Usage (AC Pan)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8),
0x95, 0x01, // Report Count (1),
0x81, 0x06, // Input (Data, Variable, Relative)
0xC0, // End Collection
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // REPORT_ID (2)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x02, // Report Count (2),
0x81, 0x02, // Input (Data, Variable, Absolute)
0xC0 // End Collection
};
#endif

Anybody know what I'm missing I'm going through the HID Definition, but I'm making assumptions that may be wrong like the left column of hexes are feature definitions, and the right are specific values appropriate to that feature.
 
After confirming the value for the third axis is in fact 0x32, I needed to stop spewing data around and terminate that block... this "Works" as in the cursor moves again, but still lacks the same precision functionality as X and Y

Code:
#ifdef MOUSE_INTERFACE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x08, // Usage Maximum (Button #8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x16, 0x01, 0x80, // Logical Minimum (-32767)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x03, // Report Count (3),
0x81, 0x06, // Input (Data, Variable, Relative)
//0x05, 0x01, // Usage Page (Generic Desktop)
//0x09, 0x38, // Usage (Wheel)
//0x15, 0x81, // Logical Minimum (-127)
//0x25, 0x7F, // Logical Maximum (127)
//0x16, 0x01, 0x80, // Logical Minimum (-32767)
//0x26, 0xFF, 0x7F, // Logical Maximum (32767)
//0x75, 0x08, // Report Size (8),
//0x75, 0x10, // Report Size (16),
//0x95, 0x01, // Report Count (1),
//0x81, 0x06, // Input (Data, Variable, Relative)
//0x05, 0x0C, // Usage Page (Consumer)
//0x0A, 0x38, 0x02, // Usage (AC Pan)
//0x15, 0x81, // Logical Minimum (-127)
//0x25, 0x7F, // Logical Maximum (127)
//0x75, 0x08, // Report Size (8),
//0x95, 0x01, // Report Count (1),
//0x81, 0x06, // Input (Data, Variable, Relative)
0xC0, // End Collection
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // REPORT_ID (2)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x02, // Report Count (2),
0x81, 0x02, // Input (Data, Variable, Absolute)
0xC0 // End Collection
};
#endif
 
So I've condensed it down to this is what you need at a bare minimum to have all 3 axes show up in windows, linux etc....

Code:
#ifdef MOUSE_INTERFACE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // Usage Page (Button)(9)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x08, // Usage Maximum (Button #8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x16, 0x01, 0x80, // Logical Minimum (-32767)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x03, // Report Count (3),
0x81, 0x06, // Input (Data, Variable, Relative)
0xC0 // End Collection
};
#endif

But for better or worse the data I get is still inconsistent... at least from an end result perspective.
 
So I've condensed it down to this is what you need at a bare minimum to have all 3 axes show up in windows, linux etc....

Code:
#ifdef MOUSE_INTERFACE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // Usage Page (Button)(9)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x08, // Usage Maximum (Button #8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x16, 0x01, 0x80, // Logical Minimum (-32767)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x75, 0x10, // Report Size (16),
0x95, 0x03, // Report Count (3),
0x81, 0x06, // Input (Data, Variable, Relative)
0xC0 // End Collection
};
#endif

But for better or worse the data I get is still inconsistent... at least from an end result perspective.

Hey,

Did you have a look at this page (https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/) it helped me a lot to get my problem fixed.
There is also a tool linked on this page (https://www.usb.org/hid) which is incredibly helpful. The interface is a bit windows xp era and its not that user friendly but if you know how to use it its pretty good.
HID descriptors are a bit hard to understand you have to know what each hex value represents in its specific domain. So the tool helps a lot in minimizing user errors.
I also saw this video recently in my feed (https://www.youtube.com/watch?v=7DKmMXRq_Xc) which is a diy 3D mouse considering I see a z-axis in your code I guess you are trying to create something similar?
I guess you also need to adjust other parts of the code other then just the descriptor as the usual functions only support 2D navigation.
 
Back
Top