Teensy 3.1 Mouse horizontal scroll

Status
Not open for further replies.

Freakeyyy

Member
Hello guys,

I'm currently working on a gaming mouse with the teeny 3.1, I've been trying to implement the horizontal scroll but with no success. I tried changing the mouse descriptor with the one provided by microsoft Here and editing the "usb_mouse.c" and "usb_mouse.h" but still doesn't seem to work (it worked after i changed something random which i don't remember anymore, but it was not working as intended), do you have any idea on what i should do or what files should I work on and put me on the right track ? I would really appreciate it.
 
Code:
*(tx_packet->buf + 0) = 1;
        *(tx_packet->buf + 1) = usb_mouse_buttons_state;
        *(tx_packet->buf + 2) = x;
        *(tx_packet->buf + 3) = y;
        *(tx_packet->buf + 4) = wheel;
        tx_packet->len = 5;
Would need to be extended to:
Code:
*(tx_packet->buf + 0) = 1;
        *(tx_packet->buf + 1) = usb_mouse_buttons_state;
        *(tx_packet->buf + 2) = x;
        *(tx_packet->buf + 3) = y;
        *(tx_packet->buf + 4) = wheel;
        *(tx_packet->buf + 5) = acPan;
        tx_packet->len = 6;

usb_desc.c/h will probably also need to be adjusted to ensure the computer is expected the correct packet sizes
USB spec 9.6.5, page 267-269, Table 9-12
and
HID 1.11 spec, section 6.2.1
Will probably both need looking at. I recommend looking at usb_desc.c/h to get a feel for it


EDIT -
usb_desc.c
Code:
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, 0x38,                     //   Usage (Wheel)
        0x15, 0x81,                     //   Logical Minimum (-127)
        0x25, 0x7F,                     //   Logical Maximum (127)
        0x75, 0x08,                     //   Report Size (8),
        0x95, 0x03,                     //   Report Count (3),
        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
};
This would need changing to the structure suggested in the document you linked. This is beyond me though I'm afraid.
I believe:
Code:
INPUT (Var, Rel)			;Vertical wheel scroll
      END COLLECTION (Logical)
      COLLECTION (Logical)
        REPORT ID (0x02)
        USAGE (Resolution Multiplier)
        REPORT SIZE (2) 			;OS requires > 1
        LOGICAL MINIMUM (0)
        LOGICAL MAXIMUM (1)
Needs adding. Report ID will need to be unique I should imagine

EDIT EDIT -
This page looks very useful
I'm not on windows but go here and download the HID descriptor tool. Use that to reconstruct the HID header from wheel-1.docx

EDIT EDIT EDIT -
Tomorrow I'll try and add the forward and back buttons to get myself slowly involved in the USB side of things. I'll submit a pull request if it works

EDIT EDIT EDIT EDIT -
This tool can confirm if what you are doing is correct
 
Last edited:
This is good, sending the extra byte for the new scroll data.

Would need to be extended to:
Code:
*(tx_packet->buf + 0) = 1;
        *(tx_packet->buf + 1) = usb_mouse_buttons_state;
        *(tx_packet->buf + 2) = x;
        *(tx_packet->buf + 3) = y;
        *(tx_packet->buf + 4) = wheel;
        *(tx_packet->buf + 5) = acPan;
        tx_packet->len = 6;


Two things need to changed in the report descriptor, so the PC knows to expect 1 more byte and knows what it means.

Code:
        0x09, 0x30,                     //   Usage (X)
        0x09, 0x31,                     //   Usage (Y)
        0x09, 0x38,                     //   Usage (Wheel)

These three lines tell your PC that the 2nd, 3rd, 4th bytes are the X & Y and normal wheel movement data. Another line needs to be added here to tell the PC how the use the extra byte. I'm honestly not sure which usage number is should be.

The this other part needs to be updated.

Code:
        0x75, 0x08,                     //   Report Size (8),
        0x95, 0x03,                     //   Report Count (3),

This informs your PC to expect three numbers, each 8 bits. Obviously this 3 needs to be increased to 4, so your PC knows there's 1 more byte. You need both the usage info, which tells the PC how to use the data (but not how many bits/bytes it is) and this to tell it how many bits of actual data to expect.
 
Oh, looks like "AC Pan" is in a different usage table "consumer devices" rather than "generic desktop". Not nice.

Maybe try keeping these the same, and then add another group just for the last byte.

Code:
        0x05, 0x01,                     //   Usage Page (Generic Desktop)
        0x09, 0x30,                     //   Usage (X)
        0x09, 0x31,                     //   Usage (Y)
        0x09, 0x38,                     //   Usage (Wheel)
        0x15, 0x81,                     //   Logical Minimum (-127)
        0x25, 0x7F,                     //   Logical Maximum (127)
        0x75, 0x08,                     //   Report Size (8),
        0x95, 0x03,                     //   Report Count (3),
        0x81, 0x06,                     //   Input (Data, Variable, Relative)

Then try adding these lines immediately after:

Code:
        0x05, 0x0C,                     //   Usage Page (Consumer Devices)
        0x09, 0xEE,                     //   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)

The HID usage tables spec says Consumer Devices is 12, and "AC Pan" is 238.
 
Okay well implementing the forward/backwards buttons were simple so I've created a pull request for this.

Thanks for the input Paul!
Would implementing another usage table potentially break the mouse's compatibility with certain systems? If not I'd be happy to pull request it into the core

EDIT -
After testing of course
 
Last edited:
Hello guys, It's finally working, i had to change the descriptor to the one here : http://www.keil.com/forum/15671/usb-mouse-with-scroll-wheel/
Here's the code :
Code:
static uint8_t mouse_report_desc[] = {		
		0x05, 0x01,        // USAGE_PAGE (Generic Desktop)
		0x09, 0x02,        // USAGE (Mouse)
		0xa1, 0x01,        // COLLECTION (Application)
		0x09, 0x02,        //   USAGE (Mouse)
		0xa1, 0x02,        //   COLLECTION (Logical)
		0x09, 0x01,        //     USAGE (Pointer)
		0xa1, 0x00,        //     COLLECTION (Physical)
						// ------------------------------  Buttons
		0x05, 0x09,        //       USAGE_PAGE (Button)
		0x19, 0x01,        //       USAGE_MINIMUM (Button 1)
		0x29, 0x05,        //       USAGE_MAXIMUM (Button 5)
		0x15, 0x00,        //       LOGICAL_MINIMUM (0)
		0x25, 0x01,        //       LOGICAL_MAXIMUM (1)
		0x75, 0x01,        //       REPORT_SIZE (1)
		0x95, 0x05,        //       REPORT_COUNT (5)
		0x81, 0x02,        //       INPUT (Data,Var,Abs)
						// ------------------------------  Padding
		0x75, 0x03,        //       REPORT_SIZE (3)
		0x95, 0x01,        //       REPORT_COUNT (1)
		0x81, 0x03,        //       INPUT (Cnst,Var,Abs)
						// ------------------------------  X,Y position
		0x05, 0x01,        //       USAGE_PAGE (Generic Desktop)
		0x09, 0x30,        //       USAGE (X)
		0x09, 0x31,        //       USAGE (Y)
		0x15, 0x81,        //       LOGICAL_MINIMUM (-127)
		0x25, 0x7f,        //       LOGICAL_MAXIMUM (127)
		0x75, 0x08,        //       REPORT_SIZE (8)
		0x95, 0x02,        //       REPORT_COUNT (2)
		0x81, 0x06,        //       INPUT (Data,Var,Rel)
		0xa1, 0x02,        //       COLLECTION (Logical)
						// ------------------------------  Vertical wheel res multiplier
		0x09, 0x48,        //         USAGE (Resolution Multiplier)
		0x15, 0x00,        //         LOGICAL_MINIMUM (0)
		0x25, 0x01,        //         LOGICAL_MAXIMUM (1)
		0x35, 0x01,        //         PHYSICAL_MINIMUM (1)
		0x45, 0x04,        //         PHYSICAL_MAXIMUM (4)
		0x75, 0x02,        //         REPORT_SIZE (2)
		0x95, 0x01,        //         REPORT_COUNT (1)
		0xa4,              //         PUSH
		0xb1, 0x02,        //         FEATURE (Data,Var,Abs)
                       // ------------------------------  Vertical wheel
		0x09, 0x38,        //         USAGE (Wheel)
		0x15, 0x81,        //         LOGICAL_MINIMUM (-127)
		0x25, 0x7f,        //         LOGICAL_MAXIMUM (127)
		0x35, 0x00,        //         PHYSICAL_MINIMUM (0)        - reset physical
		0x45, 0x00,        //         PHYSICAL_MAXIMUM (0)
		0x75, 0x08,        //         REPORT_SIZE (8)
		0x81, 0x06,        //         INPUT (Data,Var,Rel)
		0xc0,              //       END_COLLECTION
		0xa1, 0x02,        //       COLLECTION (Logical)
						// ------------------------------  Horizontal wheel res multiplier
		0x09, 0x48,        //         USAGE (Resolution Multiplier)
		0xb4,              //         POP
		0xb1, 0x02,        //         FEATURE (Data,Var,Abs)
						// ------------------------------  Padding for Feature report
		0x35, 0x00,        //         PHYSICAL_MINIMUM (0)        - reset physical
		0x45, 0x00,        //         PHYSICAL_MAXIMUM (0)
		0x75, 0x04,        //         REPORT_SIZE (4)
		0xb1, 0x03,        //         FEATURE (Cnst,Var,Abs)
						// ------------------------------  Horizontal wheel
		0x05, 0x0c,        //         USAGE_PAGE (Consumer Devices)
		0x0a, 0x38, 0x02,  //         USAGE (AC Pan)
		0x15, 0x81,        //         LOGICAL_MINIMUM (-127)
		0x25, 0x7f,        //         LOGICAL_MAXIMUM (127)
		0x75, 0x08,        //         REPORT_SIZE (8)
		0x81, 0x06,        //         INPUT (Data,Var,Rel)
		0xc0,              //       END_COLLECTION
		0xc0,              //     END_COLLECTION
		0xc0,              //   END_COLLECTION
		0xc0               // END_COLLECTION
};

Then I had to change this :

Code:
*(tx_packet->buf + 0) = 1;
        *(tx_packet->buf + 1) = usb_mouse_buttons_state;
        *(tx_packet->buf + 2) = x;
        *(tx_packet->buf + 3) = y;
        *(tx_packet->buf + 4) = wheel;
        tx_packet->len = 5;

to this :

Code:
*(tx_packet->buf + 0) = usb_mouse_buttons_state;
        *(tx_packet->buf + 1) = x;
        *(tx_packet->buf + 2) = y;
        *(tx_packet->buf + 3) = wheel;
        *(tx_packet->buf + 4) = pan;
        tx_packet->len = 5;

Then it was just a matter of editing the other functions to add the pan, now the 5 buttons and the horizontal scroll are all working
Thank you guys so much for the help
Here are the files : View attachment usb_mouse.c View attachment usb_mouse.h View attachment usb_de.c
 
I'll have a crack at this on Monday Freakeyyy providing the hardware team still have nothing for me to program

Try adding Paul's changes. Changing the entire descriptor is bound to cause some real issues
 
Okay I've added acPan. To use it use Mouse.pan(val); Where val lies between -127 and 127

The basic change was the addition of:
Code:
         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, Absolute)

I've attached the modified files.
View attachment usb_de.c <- this should be "usb_desc.c" For some reason the attachment process is renaming it
View attachment usb_mouse.c
View attachment usb_mouse.h

Do you want me to make a pull request for this Paul?
It's questionable if this goes beyond being just a mouse and doesn't actually belong in the core

Tested on Ubuntu 15.01
mouse.moveTo() confirmed to still work

FYI these files do not contain the MOUSE_BACK, MOUSE_FORWARD additions I made prior
 
Last edited:
Hello,
Just added that part to the descriptor and now everything is working great, the Pan, moveTo, mouse_backward and mouse_forward too, tested on windows 7. Thank you guys so much
 
I merged this today.

https://github.com/PaulStoffregen/cores/commit/8b85a32552c8d95b8072d5375817651df1d93215

In testing, I couldn't find any programs on Ubuntu 14.04 which respond to the horizontal scroll. Likewise on Windows, for a while I though it wasn't working. Then I tried IE, which does support it. Macintosh seems to be the only system where it's widely supported.

Does anyone know of any programs on Linux which respond to horizontal scroll (AC Pan) input?
 
Status
Not open for further replies.
Back
Top