Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 4 FirstFirst 1 2 3 4 LastLast
Results 26 to 50 of 85

Thread: USB Host Mouse Driver

  1. #26
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Thanks @defragster and @tni!

    I am looking at trying to handle the Teensy configured as an USB mouse as a mouse to the T3.6...

    The first issue, is the USBHost code is not currently claiming the Mouse. This is because it is not marked as a Boot device nor as mouse.

    From ...cores\teensy3\usb_desc.c
    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)
            0x00,                                   // bInterfaceSubClass (0x01 = Boot)
            0x00,                                   // bInterfaceProtocol (0x02 = Mouse)
            0,                                      // iInterface
            // HID interface descriptor, HID 1.11 spec, section 6.2.1
            9,                                      // bLength
            0x21,                                   // bDescriptorType
            0x11, 0x01,                             // bcdHID
            0,                                      // bCountryCode
            1,                                      // bNumDescriptors
            0x22,                                   // bDescriptorType
            LSB(sizeof(mouse_report_desc)),         // wDescriptorLength
            MSB(sizeof(mouse_report_desc)),
            // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
            7,                                      // bLength
            5,                                      // bDescriptorType
            MOUSE_ENDPOINT | 0x80,                  // bEndpointAddress
            0x03,                                   // bmAttributes (0x03=intr)
            MOUSE_SIZE, 0,                          // wMaxPacketSize
            MOUSE_INTERVAL,                         // bInterval
    #endif // MOUSE_INTERFACE
    Again as you can see it is not setup as boot device...

    Currently the USBHost mouse claim code checks these values:
    Code:
    	if (descriptors[5] != 3) return false; // bInterfaceClass, 3 = HID
    	if (descriptors[6] != 1) return false; // bInterfaceSubClass, 1 = Boot Device
    	if (descriptors[7] != 2) return false; // bInterfaceProtocol, 2 = Mouse
    And bails from trying to claim it... So the mouse does not work...

    I obviously may know enough here... But how does Windows know that this is a mouse? As I can plug it in to my PC and with the Triangle example sketch, my mouse moves itself around in a triangle pattern.

    Suggestions?

  2. #27
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    I don't think you are supposed to use the interface subclass to identify the device type. Per USB HID spec (Device Class Definition for Human Interface Devices (HID) Version 1.11):
    4.2 Subclass
    ...
    The HID committee agreed on the improbability that subclass protocols for all
    possible (and yet to be conceived) devices could be defined. In addition, many
    known devices seemed to straddle multiple classifications—for example,
    keyboards with locators, or locators that provided keystrokes. Consequently, the
    HID class does not use subclasses to define most protocols. Instead, a HID class
    device identifies its data protocol and the type of data provided within its Report
    descriptor.
    ...


    The Teensy mouse device is somewhat unusual anyway and combines mouse and touchpad. The Teensy mouse report descriptor has mouse usage.

  3. #28
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Thanks @tni,

    I read that also.

    So far the Keyboard and Mouse code looks at the subclass for boot device and works with that.

    What I am trying to figure out, is what is the more generic way (at least for mouse).

    The USB Claim code is walking through the Descriptors trying to decide if any of them should be claimed by the Mouse.

    Loops through each section asking the Mouse if it wants to claim it: So it calls it with ...
    Code:
     Actual whole data : 08 0B 00 02 02 02 01 04 09 04 00 00 01 02 02 01 00 05 24 00 10 01 05 24 01 01 01 04 24 02 06 05 24 06 00 01 07 05 82 03 10 00 40 09 04 01 00 02 0A 00 00 00 07 05 03 02 40 00 00 07 05 84 02 40 00 00 09 04 02 00 01 03 01 01 00 09 21 11 01 00 01 22 3F 00 07 05 81 03 08 00 01 09 04 03 00 01 03 00 00 00 09 21 11 01 00 01 22 54 00 07 05 85 03 08 00 02 09 04 04 00 01 03 00 00 00 09 21 11 01 00 01 22 55 00 07 05 86 03 0C 00 01 09 04 05 00 01 03 00 00 00 09 21 11 01 00 01 22 28 00 07 05 87 03 08 00 04 
    
    ... Loops a few times
    Probably Keyboard entry which has the Boot subclass
      : 09 04 02 00 01 03 01 01 00 09 21 11 01 00 01 22 3F 00 07 05 81 03 08 00 01 
    
    Probably Mouse entry which in this case does not have Boot sublass
     : 09 04 03 00 01 03 00 00 00 09 21 11 01 00 01 22 54 00 07 05 85 03 08 00 02
    I am sort of talking this out, out-laud, so pardon the ramblings.

    So I need to keep reading some parts of the HID stuff to hopefully sink in. But I wonder if I might need to do something like:
    See the entry above - Since it is not marked as subclass or like, do I maybe see the beginning of the data:
    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)
            0x00,                                   // bInterfaceSubClass (0x01 = Boot)
            0x00,                                   // bInterfaceProtocol (0x02 = Mouse)
    So We see the interface number And retrieve the HID report descriptor. I do this to process later. Currently I start reading index 0 and if it is not the right one increment until I find it, but
    should maybe check if the bInterfaceNumber has the right one?

    Currently reading in starting with index 0 like:
    Code:
    	mk_setup(descriptor_setup, 0x81, 6, 0x2200, 0, descriptors[16]);  // bugbug... need to get the right one... 
    	queue_Control_Transfer(dev, &descriptor_setup, mouse_report_desc, this);
    But assuming the data above has the actual correct index. If I would then check the start of the report descriptor, which for all of the mice I have seen start off with:
    Code:
    static uint8_t mouse_report_desc[] = {
            0x05, 0x01,                     // Usage Page (Generic Desktop)
            0x09, 0x02,                     // Usage (Mouse)
    If this is the more generic approach, wonder if that implies that we should change the enumeration step# state table that gets to case 14, which calls claim_drivers, that we may need to go through multiple steps (waiting for next USB packet to be processed). ...

    Still investigating

  4. #29
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Another update:

    I modified the claim code: first I split out the code that a driver can claim a whole device, as it's own method.

    Then setup the claim for Interface code to allow the code to be called multiple times. Then the code is setup that this function can now return 3 values:
    Does not claim, Does Claim, or needs HID descriptor...

    If the device returns needs HID descriptor, the main enum sets up to retrieve it. When data is returned, it re-enters into the Claim code. So the mouse code now checks to see if everything is else is OK for it to maybe claim... If so and the HID descriptor had not been returned it will ask for it... When it reenters, it looks at the beginning of this data and if correct continues else bails... Then parses the HID data...

    So with this: I tested again with the 4 mice I mentioned earlier. It also now appears to work with T-LC running as Mouse (Triangle test app).
    I also updated test app to simply print out Raw mouse data (like the Mouse/Keyboard app) and not try the scaling stuff...

    So again would be great if any has other mice to try...

    Github updated

    Kurt

    Update: fixed a problem with a Dell mouse I found sitting around
    Last edited by KurtE; 09-03-2017 at 03:10 PM.

  5. #30
    Junior Member
    Join Date
    Aug 2017
    Posts
    9
    Hi KurtE, I downloaded your latest work on the mouse driver. I've got some time this weekend so I can't wait to go through it!

    Awesome stuff

  6. #31
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Warning: WIP - But playing around right now with Joystick plugged into USB.. Actually currently playing with Sony PS4 controller (DS4).

    I started off from my Mouse code reading in HID information and then try to extract data. It is getting most of the data now. Need to fix my extract field from stream code to handle more of the issues with signed vs unsigned, plus how I handle where it says mouse is 12 bits...

    I decided to upload the WIP to Github as I don't think Paul would take a Pull request until current IDE is released...

    Start of hacked up test program (from mouse only... Currently has mouse and joystick...)

    Code:
    // Simple test of USB Host Mouse
    //
    // This example is in the public domain
    //
    // Information on this driver can be found in mouse.cpp
    // and USBHost_t36.h.
    // It is an initial attempt.
    //
    #include "USBHost_t36.h"
    
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    USBHub hub3(myusb);
    
    MouseController mouse1(myusb);
    JoystickController joystick1(myusb);
    bool mouse_connected = false;
    bool joystick_connected = false; 
    
    void setup()
    {
      while (!Serial) ; // wait for Arduino Serial Monitor
      Serial.println("USB Host Mouse Testing");
      myusb.begin();
    }
    
    void loop()
    {
      myusb.Task();
    
      // See if a mouse is now connected?
      bool mouse_currently_connected = mouse1.connected();
      if (mouse_currently_connected != mouse_connected) {
        mouse_connected = mouse_currently_connected;
        if (mouse_connected) {
          Serial.println("\n\n*** Mouse Connected ***");
          mouse1.printDeviceInfo();
        } else {
          Serial.println("\n\n*** Mouse Disconnected ***");
        }
      }
    
      bool joystick_currently_connected = joystick1.connected();
      if (joystick_currently_connected != joystick_connected) {
        joystick_connected = joystick_currently_connected;
        if (joystick_connected) {
          Serial.println("\n\n*** joystick Connected ***");
          joystick1.printDeviceInfo();
        } else {
          Serial.println("\n\n*** joystick Disconnected ***");
        }
      }
    
      if (mouse1.available()) {
        Serial.print("buttons = ");
        Serial.print(mouse1.getButtons(), DEC);
        Serial.print(",  wheel = ");
        Serial.print(mouse1.getWheel(), DEC);
        Serial.print(",  mouseX = ");
        Serial.print(mouse1.getMouseX(), DEC);
        Serial.print(",  mouseY = ");
        Serial.println(mouse1.getMouseY(), DEC);
        mouse1.mouseDataClear();
      }
      if (joystick1.available()) {
        uint8_t count_axes = joystick1.countAxes();
        Serial.print("Joy buttons = ");
        Serial.print(joystick1.buttons(), DEC);
    
        for (uint8_t i = 0; i < count_axes; i++) {
          Serial.print(" ");
          Serial.print(joystick1.axes(i), DEC);
        }
        Serial.println();
        joystick1.dataClear();
      }
    
      
      delay(5);
    }
    Some Debug output:
    Code:
    *** joystick Connected ***
    
    Mouse Information
      Packet Size: 64
      Report: 1
      Buttons:  Bit offset:44 Bit Size:14
    0 - X(10030):  Bit offset:8 Bit Size:8
    1 - Y(10031):  Bit offset:16 Bit Size:8
    2 - Z(10032):  Bit offset:24 Bit Size:8
    3 - Rz(10035):  Bit offset:32 Bit Size:8
    4 - Hat(10039):  Bit offset:40 Bit Size:4
    5 - <user>(20):  Bit offset:58 Bit Size:6
    6 - Rx(10033):  Bit offset:64 Bit Size:8
    7 - Ry(10034):  Bit offset:72 Bit Size:8
    8 - <user>(21):  Bit offset:80 Bit Size:8
    9 - <user>(0):  Bit offset:88 Bit Size:8
    10 - <user>(0):  Bit offset:96 Bit Size:8
    11 - <user>(0):  Bit offset:104 Bit Size:8
    12 - <user>(0):  Bit offset:112 Bit Size:8
    13 - <user>(0):  Bit offset:120 Bit Size:8
    14 - <user>(0):  Bit offset:128 Bit Size:8
    15 - <user>(0):  Bit offset:136 Bit Size:8
    Joy buttons = 8 126 123 126 127 8 0 0 0 78 95 13 27 0 4 0 2
    Joy buttons = 8 126 122 126 127 8 8 0 0 95 223 14 27 0 5 0 2
    Joy buttons = 8 126 122 126 127 8 12 0 0 76 226 14 29 0 5 0 1
    Joy buttons = 8 126 123 126 127 8 16 0 0 57 229 14 27 0 3 0 1
    Joy buttons = 8 126 123 126 127 8 20 0 0 39 232 14 23 0 4 0 4
    Joy buttons = 8 126 123 126 127 8 28 0 0 2 238 14 29 0 5 0 1
    Joy buttons = 8 126 123 126 127 8 32 0 0 239 240 14 27 0 7 0 2
    Joy buttons = 8 126 122 126 127 8 36 0 0 220 243 14 28 0 5 0 5
    Joy buttons = 8 126 122 126 127 8 44 0 0 183 249 14 25 0 4 0 2
    Joy buttons = 8 126 123 126 127 8 48 0 0 164 252 14 28 0 5 0 4
    Joy buttons = 8 126 123 126 127 8 52 0 0 146 255 14 28 0 5 0 4
    Joy buttons = 8 126 123 126 127 8 56 0 0 127 2 14 26 0 5 0 3
    Joy buttons = 8 126 123 126 127 8 64 0 0 90 8 14 29 0 4 0 3
    Joy buttons = 8 126 122 126 127 8 68 0 0 71 11 14 27 0 4 0 3
    Joy buttons = 8 126 123 126 127 8 72 0 0 53 14 14 27 0 5 0 3
    Joy buttons = 8 126 123 126 127 8 76 0 0 34 17 14 27 0
    Again WIP Buttons should be 8 not 8... encoding of other data... Also the joysticks should probably be signed... Will fix tomorrow or the next day...

    --------------------------------------------

    Also wondering about how all of these classes should work for user to get the new data...

    That is currently the Keyboard class, has the user attach functions: attachPress() and attachRelease()... With function pointers.

    Currently Mouse and Joystick are setup are Polled. Do you have data for me... If so ask for it...

    Wondering if all of these should optionally transition over to using Events?

  7. #32
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Quick update: I think I have the PS4 joystick (plugged into USB host) working pretty well. I reworked the code to extract the fields when they are off byte boundaries. Also now look for logical Min/Max values for field(s) to deduce that the field is signed or not. At some point soon may try to merge some of this code with the Mouse code base. Updated github if anyone wants to try with PS4 or other USB joystick (please)

    Maybe generate a HIDUSB sub class that both derive from...

    I tried plugging in a PS3 controller, but it is not Liking it: I believe it has to due with the order of the ENDPOINTS in the descriptions:
    For example if you look at a hex dump of the data passed to the claim function for PS4 and PS3 you see:
    Code:
            00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
    PS4: 09 04 00 00 02 03 00 00 00 09 21 11 01 00 01 22 E3 01 07 05 84 03 40 00 05 07 05 03 03 40 00 05 
    PS3: 09 04 00 00 02 03 00 00 00 09 21 11 01 00 01 22 94 00 07 05 02 03 40 00 01 07 05 81 03 40 00 01 
             |                                        |                                        |                               |
    Swapped the end points
    PS3: 09 04 00 00 02 03 00 00 00 09 21 11 01 00 01 22 94 00 07 05 81 03 40 00 01 07 05 02 03 40 00 01
    The two end points are starting at bytes 18 and 25. The code verifies that byte 19 is a 5 (end point) and that byte 20 has the high bit set to mark it as input... Which PS4 does PS3 does not.
    But if you look where I swapped the end points in the data than it would...

    So will see what happens if I have the code check both end points and work off of them...

  8. #33
    Senior Member defragster's Avatar
    Join Date
    Feb 2015
    Posts
    4,685
    Kurt, been busy - would like to run all my mice for you. If you could open an SD file and save WHATEVER you want to a file for each device I could carry my Teensy around on a battery pack plug it in and plug each mouse or whatever I find? How about an Xbox controller?

    Then I could return to my PC and zip the files and upload without as much cut and paste overhead and error and not have to drag out all the mice from where they sit at various workstations.

    Offhand my K66 Proto doesn't show me battery terminal to run RTC - but with USB battery the MILLIS would stay increasing. I could plug in a keyboard between mice and supply a text name for each device and the USB data could be ordered by timestamp.

  9. #34
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Hi defragster... Yes I should try an xbox plugged in and see if it works...
    Will see about setting up other test that stores results.

    Right now still trying to figure out PS3... I figured out that I think I need to use the 2nd end point as that one has the 0x80 bit set for which endpoint. So I use that and try to then base everything else off of using data out of that end point and not the first...

    I have the code then read in the HID description report and parse it... I think I have it understanding the data, from the trace. (USB print data...)...

    But then the last thing we do is set idle, which fails. And I am not getting anything back... Still investigating.

    But my Up2 kickstarter board arrived today

    Code:
    JoystickController claim descriptors
      : 09 04 00 00 02 03 00 00 00 09 21 11 01 00 01 22 94 00 07 05 02 03 40 00 01 07 05 81 03 40 00 01 
    ep(joystick) = 1
    Joystick Parse HID Descriptor: Size:148
    05 01 09 04 A1 01 A1 02 85 01 75 08 95 01 15 00 26 FF 00 81 03 75 01 95 13 15 00 25 01 35 00 45 01 05 09 19 01 29 13 81 02 75 01 95 0D 06 00 FF 81 03 15 00 26 FF 00 05 01 09 01 A1 00 75 08 95 04 35 00 46 FF 00 09 30 09 31 09 32 09 35 81 02 C0 05 01 75 08 95 27 09 01 81 02 75 08 95 30 09 01 91 02 75 08 95 30 09 01 B1 02 C0 A1 02 85 02 75 08 95 30 09 01 B1 02 C0 A1 02 85 EE 75 08 95 30 09 01 B1 02 C0 A1 02 85 EF 75 08 95 30 09 01 B1 02 C0 C0 
      Collection: Application
        Collection: Logical
          Report ID: 1 0  *** Main Report ***
          Report size: 8
          Report count: 1
          Logical Min: 0
          Logical Max: FF
          Input: Constant Variable 2B
          Report size: 1
          Report count: 13
          Logical Min: 0
          Logical Max: 1
          Other:35 0
          Other:45 1
          Usage page: 9
          Other:19 1
          Other:29 13
          Input: Variable 2A
          ### Button: 16 1
          Report size: 1
          Report count: D
          Usage page: FF00
          Input: Constant Variable 2B
          Logical Min: 0
          Logical Max: FF
          Usage page: 1
          Usage: 1 +
          Collection: Physical
            Report size: 8
            Report count: 4
            Other:35 0
            Other:46 FF
            Usage: 30 +
            Usage: 31 +
            Usage: 32 +
            Usage: 35 +
            Input: Variable 2A
            0 - #X(10030): 48 8
            1 - #Y(10031): 56 8
            2 - #Z(10032): 64 8
            3 - #Rz(10035): 72 8
            End Collection
          Usage page: 1
          Report size: 8
          Report count: 27
          Usage: 1 +
          Input: Variable 2A
          4 - #<user>(10001): 80 8
          5 - #<user>(10000): 88 8
          6 - #<user>(10000): 96 8
          7 - #<user>(10000): 104 8
          8 - #<user>(10000): 112 8
          9 - #<user>(10000): 120 8
          10 - #<user>(10000): 128 8
          11 - #<user>(10000): 136 8
          12 - #<user>(10000): 144 8
          13 - #<user>(10000): 152 8
          14 - #<user>(10000): 160 8
          15 - #<user>(10000): 168 8
          Report size: 8
          Report count: 30
          Usage: 1 +
          Other:91 2
          Report size: 8
          Report count: 30
          Usage: 1 +
          Other:B1 2
          End Collection
        Collection: Logical
          Report ID: 2 --- Secondary ---
          Report size: 8
          Report count: 30
          Usage: 1 -
          Other:B1 2
          End Collection
        Collection: Logical
          Report ID: EE --- Secondary ---
          Report size: 8
          Report count: 30
          Usage: 1 -
          Other:B1 2
          End Collection
        Collection: Logical
          Report ID: EF --- Secondary ---
          Report size: 8
          Report count: 30
          Usage: 1 -
          Other:B1 2
          End Collection
        End Collection
    packet size(Joystick) = 64
    polling interval = 1
    new_Pipe
    allocate_interrupt_pipe_bandwidth
     best_bandwidth = 5
    , at offset = 0, shift= 0
    add_qh_to_periodic_schedule:
      interval = 1
      offset =   0
      add to slot 0
      add to slot 1
      add to slot 2
      add to slot 3
      add to slot 4
      add to slot 5
      add to slot 6
      add to slot 7
      add to slot 8
      add to slot 9
      add to slot 10
      add to slot 11
      add to slot 12
      add to slot 13
      add to slot 14
      add to slot 15
      add to slot 16
      add to slot 17
      add to slot 18
      add to slot 19
      add to slot 20
      add to slot 21
      add to slot 22
      add to slot 23
      add to slot 24
      add to slot 25
      add to slot 26
      add to slot 27
      add to slot 28
      add to slot 29
      add to slot 30
      add to slot 31
    Periodic Schedule:
     0: 1FFF2C00
     1: 1FFF2C00
     2: 1FFF2C00
     3: 1FFF2C00
     4: 1FFF2C00
     5: 1FFF2C00
     6: 1FFF2C00
     7: 1FFF2C00
     8: 1FFF2C00
     9: 1FFF2C00
    10: 1FFF2C00
    11: 1FFF2C00
    12: 1FFF2C00
    13: 1FFF2C00
    14: 1FFF2C00
    15: 1FFF2C00
    16: 1FFF2C00
    17: 1FFF2C00
    18: 1FFF2C00
    19: 1FFF2C00
    20: 1FFF2C00
    21: 1FFF2C00
    22: 1FFF2C00
    23: 1FFF2C00
    24: 1FFF2C00
    25: 1FFF2C00
    26: 1FFF2C00
    27: 1FFF2C00
    28: 1FFF2C00
    29: 1FFF2C00
    30: 1FFF2C00
    31: 1FFF2C00
    new_Data_Transfer
    new_Control_Transfer
    ************** Joystick Claim Connected ******************
    Descriptor 33 = HID
    Descriptor 5 = ENDPOINT
    Descriptor 5 = ENDPOINT
      Followup 1FFF3500    token=80000200
      Followup 1FFF2DA0    token=80008180
    
    ISR: 4C08B
     USB Error
     USB Async
    Async Followup
      Followup 1FFF2DA0    token=80008140
    JoystickController control (static)
    1FFF2A40
      Setup: A21 0 0 0
    ERROR Followup
    
    
    *** joystick Connected ***
    
    Joystick Information
      Packet Size: 64
      Report: 1
      Buttons:  Bit offset:16 Bit Size:19
    0 - X(10030):  Bit offset:48 Bit Size:8
    1 - Y(10031):  Bit offset:56 Bit Size:8
    2 - Z(10032):  Bit offset:64 Bit Size:8
    3 - Rz(10035):  Bit offset:72 Bit Size:8
    4 - <user>(10001):  Bit offset:80 Bit Size:8
    5 - <user>(10000):  Bit offset:88 Bit Size:8
    6 - <user>(10000):  Bit offset:96 Bit Size:8
    7 - <user>(10000):  Bit offset:104 Bit Size:8
    8 - <user>(10000):  Bit offset:112 Bit Size:8
    9 - <user>(10000):  Bit offset:120 Bit Size:8
    10 - <user>(10000):  Bit offset:128 Bit Size:8
    11 - <user>(10000):  Bit offset:136 Bit Size:8
    12 - <user>(10000):  Bit offset:144 Bit Size:8
    13 - <user>(10000):  Bit offset:152 Bit Size:8
    14 - <user>(10000):  Bit offset:160 Bit Size:8
    15 - <user>(10000):  Bit offset:168 Bit Size:8

  10. #35
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    This morning for the fun of it I tried plugging in an XBOX one controller into my USB Host to see if the USB Joystick hid code would work...

    Turns out the XBox one is not a HID setup... So currently the joystick code does not try to claim it...
    Here is an edited output showing the descriptors passed into the claim code.
    Code:
    USBHub claim_device this=1FFF2020
    JoystickController claim this=1FFF2A40
    JoystickController claim descriptors
      : 09 04 00 00 02 FF 47 D0 00 07 05 02 03 40 00 04 07 05 82 03 40 00 04 09 04 01 00 00 FF 47 D0 00 
      : 09 04 01 01 02 FF 47 D0 00 07 05 03 01 E4 00 01 07 05 83 01 40 00 01 09 04 02 00 00 FF 47 D0 00 
      : 09 04 02 01 02 FF 47 D0 00 07 05 04 02 40 00 00 07 05 84 02 40 00 00
    Code checks byte index 5 for value 3 (HID) and in this case they are 0xFF so no match.

    To verify this I plugged it into my UP board with Linux and tried to do HID dump and the like which fails.
    Here is some of DMESG and lsusb output
    Code:
    [   99.745378] usb 1-3: USB disconnect, device number 6
    [  202.033842] usb 1-3: new full-speed USB device number 7 using xhci_hcd
    [  202.163342] usb 1-3: New USB device found, idVendor=045e, idProduct=02ea
    [  202.163356] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [  202.163364] usb 1-3: Product: Controller
    [  202.163372] usb 1-3: Manufacturer: Microsoft
    [  202.163379] usb 1-3: SerialNumber: 3033363030303332393035363234
    [  202.165003] input: Generic X-Box pad as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/input/input5
    
    kurt@kurt-UP-CHT01:~$ lsusb
    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 005: ID 0424:2530 Standard Microsystems Corp.
    Bus 001 Device 004: ID 0bda:8178 Realtek Semiconductor Corp. RTL8192CU 802.11n WLAN Adapter
    Bus 001 Device 003: ID 0424:4603 Standard Microsystems Corp.
    Bus 001 Device 007: ID 045e:02ea Microsoft Corp.
    Bus 001 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    
    kurt@kurt-UP-CHT01:~$ sudo usbhid-dump
    No matching HID interfaces
    
    kurt@kurt-UP-CHT01:~$ ls /dev/input
    by-id  by-path  event0  event1  event2  event3  event4  js0  mice
    So not HID, but still creates Joystick...

  11. #36
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    Quote Originally Posted by KurtE View Post
    So not HID, but still creates Joystick...
    Yes, this is the nightmare of a full USB host implementation... the world is filled with products that don't follow the standards, so they need special drivers.

  12. #37
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    Quote Originally Posted by KurtE View Post
    I decided to upload the WIP to Github as I don't think Paul would take a Pull request until current IDE is released...

    Start of hacked up test program (from mouse only... Currently has mouse and joystick...)
    Sorry, I really should have looked at this earlier. I'm only just now getting to it, after releasing 1.39.

    I probably should have explained how I'd planned to address the "rabbit hole". I see you've started going down the path of deferring the interface claim, until the extra descriptor can be read. That's not the way I want to approach this. I really should have written an explanation days ago before you started this work... but only just now getting the time.

    The long-term solution I'd like to see involves a special HID driver which always unconditionally claims any interface with bInterfaceClass = 3, unless of course one of the other drivers has claimed it first because it had bInterfaceSubClass = 1. The idea is a tricky mix of C++ object-scope functionality for each HID interface claimed, and static scope functionality with linked lists of active drivers where it's sending the HID events. Did I mention this is a deep rabbit hole?

    Also wondering about how all of these classes should work for user to get the new data...

    That is currently the Keyboard class, has the user attach functions: attachPress() and attachRelease()... With function pointers.

    Currently Mouse and Joystick are setup are Polled. Do you have data for me... If so ask for it...

    Wondering if all of these should optionally transition over to using Events?
    Yes, my long-term goal is for all of this stuff to use (still experimental) EventResponder. In fact, that's the main reason I paused on USB host. Well, that and writing the EHCI driver was pretty exhausting. I'm still not looking forward to someday adding isochronous pipe support.

    This HID stuff was something I kinda swept under the rug, kinda hoping boot protocol devices would be good enough for a while. That's probably true for keyboards, but mice and joysticks & gamepads vary way too much.

  13. #38
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Thanks Paul,

    I think I have been slowly converging over to a common driver for Joystick and Mouse and ???. I already figured and sort of mentioned, that I thought the two drivers (Mouse and Joystick) could converge as most of the code is the same. The mouse is sort of a sub-set...

    I have not played much with the keyboard stuff, but with the mouse quickly decided the boot information was probably not enough as I saw several mice that all said they reported 8 bytes back, but they all had different formats. Some had a report ID, others did not. Some reported 8 bit values some 12 bit, and some 16 bit for X, Y...

    As you mentioned, very deep Rabbit Hole! Was just still trying to figure out why the PS3 errors out... Still need to learn more about USB errors and the like. Also need to learn things like:
    the PS3: has two end points, 1 is input and the other output? When do you use them? the PS4 also has two, but the input and output ones are reversed in order...

    As I sort of deduced, it seemed to be logical to convert all of this to use the EventResponder.

    So the question is, does my experimentation and prototyping here help, or would you rather have the fun?

    Edit: Also with the HID, at times wondering how much of the information to keep and use.
    Example: Should we keep the logical Min/Max values? Likewise should we keep the Physical Min/Max values and then do the conversions?

  14. #39
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    I've got your parseHIDDescriptor code on my screen right now. Let me play with this for a couple days....

    Some of the seldom used HID stuff like physical units, long format items, push/pop may never get implemented.

  15. #40
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Sounds good... Note: the joystick parse code is probably in better state than the mouse one currently...

    Also I punted so far on things like multiple reports, I assume first one. And not really sure how to properly handle collections...

    So I will play with some other things for now.

  16. #41
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    Here's the HID report descriptors from all the non-keyboard devices I have here for testing.

    Coda (small/cheap) mouse:
    05 01 09 02 A1 01 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 03 05 01 09 01 A1 00 09 30 09 31 09 38 15 81 25 7F 75 08 95 03 81 06 C0 C0

    Apple Mighty Mouse:
    05 01 09 02 A1 01 05 09 19 01 29 04 15 00 25 01 95 04 75 01 81 02 95 01 75 04 81 01 05 01 09 01 A1 00 09 30 09 31 09 32 09 38 15 81 25 7F 75 08 95 04 81 06 C0 05 FF 09 C0 75 08 95 01 81 02 C0

    Logitech Wireless Trackball, interface #0 (keyboard)
    05 01 09 06 A1 01 95 08 75 01 15 00 25 01 05 07 19 E0 29 E7 81 02 81 03 95 05 05 08 19 01 29 05 91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 FF 00 05 07 19 00 2A FF 00 81 00 C0

    Logitech Wireless Trackball, interface #1 (mouse)
    05 01 09 02 A1 01 85 02 09 01 A1 00 95 10 75 01 15 00 25 01 05 09 19 01 29 10 81 02 95 02 75 0C 16 01 F8 26 FF 07 05 01 09 30 09 31 81 06 95 01 75 08 15 81 25 7F 09 38 81 06 95 01 05 0C 0A 38 02 81 06 C0 C0 05 0C 09 01 A1 01 85 03 95 02 75 10 15 01 26 FF 02 19 01 2A FF 02 81 00 C0 05 01 09 80 A1 01 85 04 95 01 75 02 15 01 25 03 09 82 09 81 09 83 81 00 75 06 81 03 C0 06 BC FF 09 88 A1 01 85 08 95 01 75 08 15 01 26 FF 00 19 01 29 FF 81 00 C0

    Logitech Wireless Trackball, interface #2 (unknown)
    06 00 FF 09 01 A1 01 85 10 95 06 75 08 15 00 26 FF 00 09 01 81 00 09 01 91 00 C0 06 00 FF 09 02 A1 01 85 11 95 13 75 08 15 00 26 FF 00 09 02 81 00 09 02 91 00 C0 06 00 FF 09 04 A1 01 85 20 95 0E 75 08 15 00 26 FF 00 09 41 81 00 09 41 91 00 85 21 95 1F 09 42 81 00 09 42 91 00 C0

    Microsoft Intellimouse
    05 01 09 02 A1 01 09 01 A1 00 05 09 19 01 29 05 15 00 25 01 75 01 95 05 81 02 75 03 95 01 81 01 05 01 09 30 09 31 09 38 15 81 25 7F 75 08 95 03 81 06 C0 05 FF 09 02 15 00 25 01 75 01 95 01 B1 22 75 07 95 01 B1 01 C0

    Logitech M100
    05 01 09 02 A1 01 09 01 A1 00 05 09 19 01 29 03 15 00 25 01 95 08 75 01 81 02 05 01 09 30 09 31 09 38 15 81 25 7F 75 08 95 03 81 06 C0 C0

    Logitech M-U0007
    05 01 09 02 A1 01 09 01 A1 00 05 09 19 01 29 08 15 00 25 01 95 08 75 01 81 02 95 00 81 03 05 01 09 30 09 31 16 01 F8 26 FF 07 75 0C 95 02 81 06 09 38 15 81 25 7F 75 08 95 01 81 06 05 0C 0A 38 02 95 01 81 06 C0 C0

    Sony Dualshock3 Sixaxis (gamepad):
    05 01 09 04 A1 01 A1 02 85 01 75 08 95 01 15 00 26 FF 00 81 03 75 01 95 13 15 00 25 01 35 00 45 01 05 09 19 01 29 13 81 02 75 01 95 0D 06 00 FF 81 03 15 00 26 FF 00 05 01 09 01 A1 00 75 08 95 04 35 00 46 FF 00 09 30 09 31 09 32 09 35 81 02 C0 05 01 75 08 95 27 09 01 81 02 75 08 95 30 09 01 91 02 75 08 95 30 09 01 B1 02 C0 A1 02 85 02 75 08 95 30 09 01 B1 02 C0 A1 02 85 EE 75 08 95 30 09 01 B1 02 C0 A1 02 85 EF 75 08 95 30 09 01 B1 02 C0 C0

  17. #42
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Looks good, I have a few of the same ones as I mentioned throughout the thread. Also have for example Sony DualShock 4:
    Code:
    001:006:000:DESCRIPTOR         1504880944.787596
     05 01 09 05 A1 01 85 01 09 30 09 31 09 32 09 35 
     15 00 26 FF 00 75 08 95 04 81 02 09 39 15 00 25
     07 35 00 46 3B 01 65 14 75 04 95 01 81 42 65 00
     05 09 19 01 29 0E 15 00 25 01 75 01 95 0E 81 02
     06 00 FF 09 20 75 06 95 01 15 00 25 7F 81 02 05
     01 09 33 09 34 15 00 26 FF 00 75 08 95 02 81 02
     06 00 FF 09 21 95 36 81 02 85 05 09 22 95 1F 91
     02 85 04 09 23 95 24 B1 02 85 02 09 24 95 24 B1
     02 85 08 09 25 95 03 B1 02 85 10 09 26 95 04 B1
     02 85 11 09 27 95 02 B1 02 85 12 06 02 FF 09 21
     95 0F B1 02 85 13 09 22 95 16 B1 02 85 14 06 05
     FF 09 20 95 10 B1 02 85 15 09 21 95 2C B1 02 06
     80 FF 85 80 09 20 95 06 B1 02 85 81 09 21 95 06
     B1 02 85 82 09 22 95 05 B1 02 85 83 09 23 95 01
     B1 02 85 84 09 24 95 04 B1 02 85 85 09 25 95 06
     B1 02 85 86 09 26 95 06 B1 02 85 87 09 27 95 23
     B1 02 85 88 09 28 95 22 B1 02 85 89 09 29 95 02
     B1 02 85 90 09 30 95 05 B1 02 85 91 09 31 95 03
     B1 02 85 92 09 32 95 03 B1 02 85 93 09 33 95 0C
     B1 02 85 A0 09 40 95 06 B1 02 85 A1 09 41 95 01
     B1 02 85 A2 09 42 95 01 B1 02 85 A3 09 43 95 30
     B1 02 85 A4 09 44 95 0D B1 02 85 A5 09 45 95 15
     B1 02 85 A6 09 46 95 15 B1 02 85 F0 09 47 95 3F
     B1 02 85 F1 09 48 95 3F B1 02 85 F2 09 49 95 0F
     B1 02 85 A7 09 4A 95 01 B1 02 85 A8 09 4B 95 01
     B1 02 85 A9 09 4C 95 08 B1 02 85 AA 09 4E 95 01
     B1 02 85 AB 09 4F 95 39 B1 02 85 AC 09 50 95 39
     B1 02 85 AD 09 51 95 0B B1 02 85 AE 09 52 95 01
     B1 02 85 AF 09 53 95 02 B1 02 85 B0 09 54 95 3F
     B1 02 85 B1 09 55 95 02 B1 02 85 B2 09 56 95 02
     B1 02 C0
    And it helps me to use the linux tools to visually see what all of this is:
    Code:
    kurt@kurt-UP-CHT01:~$ sudo usbhid-dump  -i0 | grep -v : | xxd -r -p | hidrd-convert -o spec
    Usage Page (Desktop),               ; Generic desktop controls (01h)
    Usage (Gamepad),                    ; Gamepad (05h, application collection)
    Collection (Application),
        Report ID (1),
        Usage (X),                      ; X (30h, dynamic value)
        Usage (Y),                      ; Y (31h, dynamic value)
        Usage (Z),                      ; Z (32h, dynamic value)
        Usage (Rz),                     ; Rz (35h, dynamic value)
        Logical Minimum (0),
        Logical Maximum (255),
        Report Size (8),
        Report Count (4),
        Input (Variable),
        Usage (Hat Switch),             ; Hat switch (39h, dynamic value)
        Logical Minimum (0),
        Logical Maximum (7),
        Physical Minimum (0),
        Physical Maximum (315),
        Unit (Degrees),
        Report Size (4),
        Report Count (1),
        Input (Variable, Null State),
        Unit,
        Usage Page (Button),            ; Button (09h)
        Usage Minimum (01h),
        Usage Maximum (0Eh),
        Logical Minimum (0),
        Logical Maximum (1),
        Report Size (1),
        Report Count (14),
        Input (Variable),
        Usage Page (FF00h),             ; FF00h, vendor-defined
        Usage (20h),
        Report Size (6),
        Report Count (1),
        Logical Minimum (0),
        Logical Maximum (127),
        Input (Variable),
        Usage Page (Desktop),           ; Generic desktop controls (01h)
        Usage (Rx),                     ; Rx (33h, dynamic value)
        Usage (Ry),                     ; Ry (34h, dynamic value)
        Logical Minimum (0),
        Logical Maximum (255),
        Report Size (8),
        Report Count (2),
        Input (Variable),
        Usage Page (FF00h),             ; FF00h, vendor-defined
        Usage (21h),
        Report Count (54),
        Input (Variable),
        Report ID (5),
        Usage (22h),
        Report Count (31),
        Output (Variable),
        Report ID (4),
        Usage (23h),
        Report Count (36),
        Feature (Variable),
        Report ID (2),
        Usage (24h),
        Report Count (36),
        Feature (Variable),
        Report ID (8),
        Usage (25h),
        Report Count (3),
        Feature (Variable),
        Report ID (16),
        Usage (26h),
        Report Count (4),
        Feature (Variable),
        Report ID (17),
        Usage (27h),
        Report Count (2),
        Feature (Variable),
        Report ID (18),
        Usage Page (FF02h),             ; FF02h, vendor-defined
        Usage (21h),
        Report Count (15),
        Feature (Variable),
        Report ID (19),
        Usage (22h),
        Report Count (22),
        Feature (Variable),
        Report ID (20),
        Usage Page (FF05h),             ; FF05h, vendor-defined
        Usage (20h),
        Report Count (16),
        Feature (Variable),
        Report ID (21),
        Usage (21h),
        Report Count (44),
        Feature (Variable),
        Usage Page (FF80h),             ; FF80h, vendor-defined
        Report ID (128),
        Usage (20h),
        Report Count (6),
        Feature (Variable),
        Report ID (129),
        Usage (21h),
        Report Count (6),
        Feature (Variable),
        Report ID (130),
        Usage (22h),
        Report Count (5),
        Feature (Variable),
        Report ID (131),
        Usage (23h),
        Report Count (1),
        Feature (Variable),
        Report ID (132),
        Usage (24h),
        Report Count (4),
        Feature (Variable),
        Report ID (133),
        Usage (25h),
        Report Count (6),
        Feature (Variable),
        Report ID (134),
        Usage (26h),
        Report Count (6),
        Feature (Variable),
        Report ID (135),
        Usage (27h),
        Report Count (35),
        Feature (Variable),
        Report ID (136),
        Usage (28h),
        Report Count (34),
        Feature (Variable),
        Report ID (137),
        Usage (29h),
        Report Count (2),
        Feature (Variable),
        Report ID (144),
        Usage (30h),
        Report Count (5),
        Feature (Variable),
        Report ID (145),
        Usage (31h),
        Report Count (3),
        Feature (Variable),
        Report ID (146),
        Usage (32h),
        Report Count (3),
        Feature (Variable),
        Report ID (147),
        Usage (33h),
        Report Count (12),
        Feature (Variable),
        Report ID (160),
        Usage (40h),
        Report Count (6),
        Feature (Variable),
        Report ID (161),
        Usage (41h),
        Report Count (1),
        Feature (Variable),
        Report ID (162),
        Usage (42h),
        Report Count (1),
        Feature (Variable),
        Report ID (163),
        Usage (43h),
        Report Count (48),
        Feature (Variable),
        Report ID (164),
        Usage (44h),
        Report Count (13),
        Feature (Variable),
        Report ID (165),
        Usage (45h),
        Report Count (21),
        Feature (Variable),
        Report ID (166),
        Usage (46h),
        Report Count (21),
        Feature (Variable),
        Report ID (240),
        Usage (47h),
        Report Count (63),
        Feature (Variable),
        Report ID (241),
        Usage (48h),
        Report Count (63),
        Feature (Variable),
        Report ID (242),
        Usage (49h),
        Report Count (15),
        Feature (Variable),
        Report ID (167),
        Usage (4Ah),
        Report Count (1),
        Feature (Variable),
        Report ID (168),
        Usage (4Bh),
        Report Count (1),
        Feature (Variable),
        Report ID (169),
        Usage (4Ch),
        Report Count (8),
        Feature (Variable),
        Report ID (170),
        Usage (4Eh),
        Report Count (1),
        Feature (Variable),
        Report ID (171),
        Usage (4Fh),
        Report Count (57),
        Feature (Variable),
        Report ID (172),
        Usage (50h),
        Report Count (57),
        Feature (Variable),
        Report ID (173),
        Usage (51h),
        Report Count (11),
        Feature (Variable),
        Report ID (174),
        Usage (52h),
        Report Count (1),
        Feature (Variable),
        Report ID (175),
        Usage (53h),
        Report Count (2),
        Feature (Variable),
        Report ID (176),
        Usage (54h),
        Report Count (63),
        Feature (Variable),
        Report ID (177),
        Usage (55h),
        Report Count (2),
        Feature (Variable),
        Report ID (178),
        Usage (56h),
        Report Count (2),
        Feature (Variable),
    End Collection
    kurt@kurt-UP-CHT01:~$
    Which my debug code sort of outputs a subset of this...
    Note: I highlighted in RED in the above where it appears like it generates multiple different reports... I stopped marking after the first few... Currently the code ignores data for reports that don't match the first one... But for some devices may need multiple? That is currently my Mouse version handles the Teensy as Mouse, again only for the first report, but I think using a teensy for mouse, there is a 2nd usage, where you can set absolute position and it probably outputs report 2...

    As I mentioned earlier the Microsoft wireless one I have, is a little more complicated as it looks like it intermixed stuff from multiple reports. That is is started the main report, went into some form of collection, output some other report and then went back to the first report to add more fields.

    So for the fun of it I took your wireless trackball data saved to a file on my linux machine (up board) and then used the hiddump with it...
    Code:
    kurt@kurt-UP-CHT01:~$ vi foo
    kurt@kurt-UP-CHT01:~$ cat foo |  xxd -r -p | hidrd-convert -o spec                          Usage Page (Desktop),                   ; Generic desktop controls (01h)
    Usage (Mouse),                          ; Mouse (02h, application collection)
    Collection (Application),
        Report ID (2),
        Usage (Pointer),                    ; Pointer (01h, physical collection)
        Collection (Physical),
            Report Count (16),
            Report Size (1),
            Logical Minimum (0),
            Logical Maximum (1),
            Usage Page (Button),            ; Button (09h)
            Usage Minimum (01h),
            Usage Maximum (10h),
            Input (Variable),
            Report Count (2),
            Report Size (12),
            Logical Minimum (-2047),
            Logical Maximum (2047),
            Usage Page (Desktop),           ; Generic desktop controls (01h)
            Usage (X),                      ; X (30h, dynamic value)
            Usage (Y),                      ; Y (31h, dynamic value)
            Input (Variable, Relative),
            Report Count (1),
            Report Size (8),
            Logical Minimum (-127),
            Logical Maximum (127),
            Usage (Wheel),                  ; Wheel (38h, dynamic value)
            Input (Variable, Relative),
            Report Count (1),
            Usage Page (Consumer),          ; Consumer (0Ch)
            Usage (AC Pan),                 ; AC pan (0238h, linear control)
            Input (Variable, Relative),
        End Collection,
    End Collection,
    Usage Page (Consumer),                  ; Consumer (0Ch)
    Usage (Consumer Control),               ; Consumer control (01h, application collection)
    Collection (Application),
        Report ID (3),
        Report Count (2),
        Report Size (16),
        Logical Minimum (1),
        Logical Maximum (767),
        Usage Minimum (Consumer Control),   ; Consumer control (01h, application collection)
        Usage Maximum (02FFh),
        Input,
    End Collection,
    Usage Page (Desktop),                   ; Generic desktop controls (01h)
    Usage (Sys Control),                    ; System control (80h, application collection)
    Collection (Application),
        Report ID (4),
        Report Count (1),
        Report Size (2),
        Logical Minimum (1),
        Logical Maximum (3),
        Usage (Sys Sleep),                  ; System sleep (82h, one-shot control)
        Usage (Sys Power Down),             ; System power down (81h, one-shot control)
        Usage (Sys Wake Up),                ; System wake up (83h, one-shot control)
        Input,
        Report Size (6),
        Input (Constant, Variable),
    End Collection,
    Usage Page (FFBCh),                     ; FFBCh, vendor-defined
    Usage (88h),
    Collection (Application),
        Report ID (8),
        Report Count (1),
        Report Size (8),
        Logical Minimum (1),
        Logical Maximum (255),
        Usage Minimum (01h),
        Usage Maximum (FFh),
        Input,
    End Collection
    kurt@kurt-UP-CHT01:~$

  18. #43
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Found another device to test out. I have a Watcom Bamboo fun tablet.
    Mouse descriptor:
    Code:
     : 09 04 00 00 01 03 01 02 00 09 21 00 01 00 01 22 B0 00 07 05 81 03 09 00 04 09 04 01 00 01 03 00 00 00 09 21 00 01 00 01 22 4B 00 07 05 82 03 40 00 04
    HID Report descriptor:
    Code:
    05 01 09 02 A1 01 85 01 09 01 A1 00 05 09 19 01 29 05 15 00 25 01 95 05 75 01 81 02 95 01 75 03 81 01 05 01 09 30 09 31 15 81 25 7F 75 08 95 02 81 06 C0 C0 05 0D 09 01 A1 01 85 02 A1 00 06 00 FF 09 01 15 00 26 FF 00 75 08 95 08 81 02 C0 09 01 85 02 95 01 B1 02 09 01 85 03 95 01 B1 02 09 01 85 04 95 01 B1 02 09 01 85 05 95 01 B1 02 09 01 85 10 95 02 B1 02 09 01 85 11 95 10 B1 02 09 01 85 13 95 01 B1 02 09 01 85 20 95 01 B1 02 09 01 85 21 95 01 B1 02 09 01 85 06 95 01 B1 02 09 01 85 07 95 01 B1 02 09 01 85 14 95 01 B1 02 C0
    Some of the debug decoding:
    Code:
      Collection: Application
        Report ID: 1 0  *** Main Report ***
        Usage: 1 +
        Collection: Physical
          Usage page: 9
          Other:19 1
          Other:29 5
          Other:15 0
          Other:25 1
          Report count: 5
          Report size: 1
          Input: Variable 2
          ### Button: 8 1
          Report count: 1
          Report size: 3
          Input: Constant 1
          Usage page: 1
          Usage: 30 +
          Usage: 31 +
          Other:15 81
          Other:25 7F
          Report size: 8
          Report count: 2
          Input: Variable Relative 6
          ### X: 16 8
          ### Y: 24 8
          End Collection
        End Collection
      Usage page: D
      Usage: 1 +
      Collection: Application
        Report ID: 2 --- Secondary ---
        Collection: Physical
          Usage page: FF00
          Usage: 1 -
          Other:15 0
    ...
    So looks pretty standard: Except it does not have wheel... (my current code will probably five bogus value here... Should probably init the offset to
    something and check it when the user does a query for the data. Actually I do init to 0xff and assume that the X, Y, wheel and buttons will be within 256 bits of the report. Which for Mouse probably all reports will probably be less than 256/8= 32 bytes long so probably not an issue.

    My info output shows:
    Code:
    Mouse Information
      Packet Size: 9
      Report: 1
      Buttons: Bit offset:8 Bit Size:8
      X: Bit offset:16 Bit Size:8 Relative 
      Y: Bit offset:24 Bit Size:8 Relative 
      Wheel: Bit offset:255 Bit Size:0
    Edit:
    Should mention looking at this device on Linux I see it creates two interfaces:
    Code:
    
    
    Code:
    kurt@kurt-UP-CHT01:~$ lsusb
    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 005: ID 0424:2530 Standard Microsystems Corp.
    Bus 001 Device 004: ID 0bda:8178 Realtek Semiconductor Corp. RTL8192CU 802.11n WLAN Adapter
    Bus 001 Device 003: ID 0424:4603 Standard Microsystems Corp.
    Bus 001 Device 007: ID 056a:00d8 Wacom Co., Ltd
    Bus 001 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    kurt@kurt-UP-CHT01:~$ sudo usbhid-dump
    001:007:001:DESCRIPTOR         1504887181.952739
     06 00 FF 09 01 A1 01 85 02 05 0D 09 22 A1 00 06
     00 FF 09 01 15 00 26 FF 00 75 08 95 02 81 02 05
     01 09 30 35 00 46 44 48 26 E4 02 75 10 95 01 81
     02 09 31 46 D4 30 26 F4 01 81 02 06 00 FF 09 01
     26 FF 00 75 08 95 0D 81 02 C0 C0
    
    001:007:000:DESCRIPTOR         1504887181.956943
     05 01 09 02 A1 01 85 01 09 01 A1 00 05 09 19 01
     29 05 15 00 25 01 95 05 75 01 81 02 95 01 75 03
     81 01 05 01 09 30 09 31 15 81 25 7F 75 08 95 02
     81 06 C0 C0 05 0D 09 01 A1 01 85 02 A1 00 06 00
     FF 09 01 15 00 26 FF 00 75 08 95 08 81 02 C0 09
     01 85 02 95 01 B1 02 09 01 85 03 95 01 B1 02 09
     01 85 04 95 01 B1 02 09 01 85 05 95 01 B1 02 09
     01 85 10 95 02 B1 02 09 01 85 11 95 10 B1 02 09
     01 85 13 95 01 B1 02 09 01 85 20 95 01 B1 02 09
     01 85 21 95 01 B1 02 09 01 85 06 95 01 B1 02 09
     01 85 07 95 01 B1 02 09 01 85 14 95 01 B1 02 C0
    
    kurt@kurt-UP-CHT01:~$ sudo usbhid-dump  -i0 | grep -v : | xxd -r -p | hidrd-convert -o spec
    Usage Page (Desktop),               ; Generic desktop controls (01h)
    Usage (Mouse),                      ; Mouse (02h, application collection)
    Collection (Application),
        Report ID (1),
        Usage (Pointer),                ; Pointer (01h, physical collection)
        Collection (Physical),
            Usage Page (Button),        ; Button (09h)
            Usage Minimum (01h),
            Usage Maximum (05h),
            Logical Minimum (0),
            Logical Maximum (1),
            Report Count (5),
            Report Size (1),
            Input (Variable),
            Report Count (1),
            Report Size (3),
            Input (Constant),
            Usage Page (Desktop),       ; Generic desktop controls (01h)
            Usage (X),                  ; X (30h, dynamic value)
            Usage (Y),                  ; Y (31h, dynamic value)
            Logical Minimum (-127),
            Logical Maximum (127),
            Report Size (8),
            Report Count (2),
            Input (Variable, Relative),
        End Collection,
    End Collection,
    Usage Page (Digitizer),             ; Digitizer (0Dh)
    Usage (Digitizer),                  ; Digitizer (01h, application collection)
    Collection (Application),
        Report ID (2),
        Collection (Physical),
            Usage Page (FF00h),         ; FF00h, vendor-defined
            Usage (01h),
            Logical Minimum (0),
            Logical Maximum (255),
            Report Size (8),
            Report Count (8),
            Input (Variable),
        End Collection,
        Usage (01h),
        Report ID (2),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (3),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (4),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (5),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (16),
        Report Count (2),
        Feature (Variable),
        Usage (01h),
        Report ID (17),
        Report Count (16),
        Feature (Variable),
        Usage (01h),
        Report ID (19),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (32),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (33),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (6),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (7),
        Report Count (1),
        Feature (Variable),
        Usage (01h),
        Report ID (20),
        Report Count (1),
        Feature (Variable),
    End Collection
    kurt@kurt-UP-CHT01:~$ sudo usbhid-dump  -i1 | grep -v : | xxd -r -p | hidrd-convert -o spec Usage Page (FF00h),                 ; FF00h, vendor-defined
    Usage (01h),
    Collection (Application),
        Report ID (2),
        Usage Page (Digitizer),         ; Digitizer (0Dh)
        Usage (Finger),                 ; Finger (22h, logical collection)
        Collection (Physical),
            Usage Page (FF00h),         ; FF00h, vendor-defined
            Usage (01h),
            Logical Minimum (0),
            Logical Maximum (255),
            Report Size (8),
            Report Count (2),
            Input (Variable),
            Usage Page (Desktop),       ; Generic desktop controls (01h)
            Usage (X),                  ; X (30h, dynamic value)
            Physical Minimum (0),
            Physical Maximum (18500),
            Logical Maximum (740),
            Report Size (16),
            Report Count (1),
            Input (Variable),
            Usage (Y),                  ; Y (31h, dynamic value)
            Physical Maximum (12500),
            Logical Maximum (500),
            Input (Variable),
            Usage Page (FF00h),         ; FF00h, vendor-defined
            Usage (01h),
            Logical Maximum (255),
            Report Size (8),
            Report Count (13),
            Input (Variable),
        End Collection,
    End Collection
    kurt@kurt-UP-CHT01:~$
    Last edited by KurtE; 09-08-2017 at 04:19 PM.

  19. #44
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    I've been falling down the HID rabbit hole for the last few days. It is deep indeed.

    My goal has been a single generic HID parser that lets the drivers claim top-level collections, and delivers the data as value/usage pairs. I think I'm getting pretty close, but today I'm starting to get a little concerned about performance. A callback for each item, and walking the report descriptor data every time might be too much overhead. Or maybe Teensy 3.6 is plenty fast enough? Haven't done benchmarking yet, and the code is still filled with tons of slow printing.

    Going to commit this stuff to github today, so everyone can look at it. Kurt, your code was extremely helpful to get me started. I must admit, I've been kinda procrastinating even starting to work in this HID parser stuff.

  20. #45
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Sounds great!

    Will look for it later today, to see what all you have done.

    The HID stuff is interesting. It will be fun to see how to use it, especially with some different devices.

    Example the Watcom tablet has two Interfaces.
    The first one acts like mouse and the second a digitizer.

    It will also be interesting to see how your value usage pairs work, That is for a mouse would I ask for
    something like: 0x10030 to get the X value for the mouse, 0x10031 for Y and 0x90000 for Buttons....

    If so and worried about performance, might want to introduce some shortcuts, where I can ask for index for some key and then have extract by index...

    Also any luck with PS3?

  21. #46
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    Quote Originally Posted by KurtE View Post
    Example the Watcom tablet has two Interfaces.
    The first one acts like mouse and the second a digitizer.
    Yup. The HID drivers in Windows and Linux allow top level collections to appear as if they were separate devices. That's why I tried to do something similar, allowing drivers to claim only a part of the report based on the top level collections.

    Also any luck with PS3?
    Nope. Looks like it's triggering a bug deep within the EHCI or periodic bandwidth scheduling code.

  22. #47
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Do you have a test app with the current stuff?

    Will tryout the different stuff I have.

    Also trying to figure out XBox one, but I am still learning stuff, like how to send it a command... I believe you need to send it a command to tell it to go into sending reports with buttons and axes... One source on this (https://github.com/JRHeaton/XboxOneControllerDev) ... There was another with conflicting commands...
    Mine is a XBox one S controller so the PID is 0x2ea and not 0x2d1...

    With PS3 - I believe I read that you also need to tell the PS3 to start sending Report 1 to get it to work...
    I think the command bytes is:
    Code:
    static const uint8_t ps3_feature_F4_report[]  = {0x42, 0x0c, 0x00, 0x00};
    I tried a few different things like:
    Code:
    	if ((dev->idVendor == 0x54c) && (dev->idProduct == 0x268)) {
    		println("*** Sony PS3");
    		mk_setup(setup, 0x21, 9, 0x3f4, 0, 4); // ps3 tell it to send report 1?
    		print_hexbytes((uint8_t*)&setup, 8);
    		queue_Control_Transfer(dev, &setup, (void*)ps3_feature_F4_report, this);		
    	}
    But that appears to crash the USB, so probably wrong...

    Will look more at your stuff to see if you have stuff that sends out command data like this...

  23. #48
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,144
    I just committed the first mouse code using the hid parsing. The main function is hid_input_data(), where the parser gives the driver usage/value pairs.

    https://github.com/PaulStoffregen/US...ster/mouse.cpp

    This should be able to recognize the scroll wheel on any mouse, and properly find horizontal scroll, if the mouse has it.

  24. #49
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Great,

    I just synced up. Now trying with my mice, let me know if you want more details on each device... I think I have most of the information in previous posts.

    Belkin wired - Appears to work

    Dell wired - Appears to work, but shows WheelH, but I am not seeing any mouse H data coming out

    HP wired - Like Dell. (fewer buttons)

    Logitech wireless combo - appears to work - again not sure about wheelH

    Microsoft wireless combo - works and I gett wheelH

    Wacom Bambo tablet - appears to have issues. It worked once I think, but tried again and hangs... Also appears to hang USB...

    Teensy 3.2 with Mouse triangle move - does not output...

    Also maybe having some init issues (maybe some race condition). That sometimes if I reset the Teensy, the mouse does not work. It may work again if I unplug it and plug it back in... Maybe time to turn debug back on...

  25. #50
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Wacom Bambo:
    Debug info:
    Code:
    USB Host Testing
    sizeof Device = 32
    sizeof Pipe = 96
    sizeof Transfer = 64
    power up USBHS PHY
    
    ISR: 408C
     Port Change
    port change: 10001803
        connect
    
    ISR: 4084
     Port Change
    port change: 1C001002
        disconnect
    
    ISR: 1004088
     Timer0
    
    ISR: 408C
     Port Change
    port change: 10001803
        connect
    
    ISR: 4084
     Port Change
    port change: 1C001002
        disconnect
    
    ISR: 1004088
     Timer0
    
    ISR: 408C
     Port Change
    port change: 10001803
        connect
    
    ISR: 4084
     Port Change
    port change: 1C001002
        disconnect
    
    ISR: 1004088
     Timer0
    
    ISR: 408C
     Port Change
    port change: 10001803
        connect
    
    ISR: 4084
     Port Change
    port change: 1C001002
        disconnect
    
    ISR: 1004088
     Timer0
    
    ISR: 408C
     Port Change
    port change: 10001803
        connect
    
    ISR: 1004088
     Timer0
      begin reset
    
    ISR: 408C
     Port Change
    port change: 10001805
      port enabled
    
    ISR: 1004080
     Timer0
      end recovery
    new_Device: 12 Mbit/sec
    new_Pipe
    new_Control_Transfer
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF5420    token=80000200
      Followup 1FFF5360    token=100
      Followup 1FFF53A0    token=8000
    enumeration:
    new_Control_Transfer
      Followup 1FFF53E0    token=80280
      Followup 1FFF5420    token=80008180
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF53E0    token=80000200
      Followup 1FFF5420    token=8100
    enumeration:
    new_Control_Transfer
      Followup 1FFF5360    token=80280
      Followup 1FFF2EC0    token=80120180
      Followup 1FFF53A0    token=80008080
    
    ISR: 4E089
     USB Async
    Async Followup
      Followup 1FFF5360    token=80000200
      Followup 1FFF2EC0    token=100
      Followup 1FFF53A0    token=8000
    enumeration:
    new_Control_Transfer
      Followup 1FFF53E0    token=80280
      Followup 1FFF5420    token=80FC0180
      Followup 1FFF5360    token=80008080
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF53E0    token=80000200
      Followup 1FFF5420    token=F80100
      Followup 1FFF5360    token=8000
    enumeration:
    new_Control_Transfer
      Followup 1FFF2EC0    token=80280
      Followup 1FFF53A0    token=80FC0180
      Followup 1FFF53E0    token=80008080
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF2EC0    token=80000200
      Followup 1FFF53A0    token=DE0100
      Followup 1FFF53E0    token=8000
    enumeration:
    new_Control_Transfer
      Followup 1FFF5420    token=80280
      Followup 1FFF5360    token=80FC0180
      Followup 1FFF2EC0    token=80008080
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF5420    token=80000200
      Followup 1FFF5360    token=EC0100
      Followup 1FFF2EC0    token=8000
    enumeration:
    new_Control_Transfer
      Followup 1FFF53A0    token=80280
      Followup 1FFF53E0    token=80090180
      Followup 1FFF5420    token=80008080
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF53A0    token=80000200
      Followup 1FFF53E0    token=100
      Followup 1FFF5420    token=8000
    enumeration:
    Config data length = 59
    new_Control_Transfer
      Followup 1FFF5360    token=80280
      Followup 1FFF2EC0    token=803B0180
      Followup 1FFF53A0    token=80008080
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF5360    token=80000200
      Followup 1FFF2EC0    token=100
      Followup 1FFF53A0    token=8000
    enumeration:
    bNumInterfaces = 2
    bConfigurationValue = 1
    new_Control_Transfer
      Followup 1FFF53E0    token=80280
      Followup 1FFF5360    token=80008180
    
    ISR: 4E081
     USB Async
    Async Followup
      Followup 1FFF53E0    token=80000200
      Followup 1FFF5360    token=8100
    enumeration:
    USBHub memory usage = 864
    USBHub claim_device this=1FFF2F00
    USBHub memory usage = 864
    USBHub claim_device this=1FFF3260
    USBHub memory usage = 864
    USBHub claim_device this=1FFF35C0
    KeyboardController claim this=1FFF2020
    KeyboardController claim this=1FFF2220
    HIDParser claim this=1FFF3940
    HIDParser claim this=1FFF3CE0
    HIDParser claim this=1FFF2420
    HIDParser claim this=1FFF27C0
    HIDParser claim this=1FFF2B60
    Descriptor 4 = INTERFACE
    KeyboardController claim this=1FFF2020
    KeyboardController claim this=1FFF2220
    HIDParser claim this=1FFF3940
     bInterfaceClass =    3
     bInterfaceSubClass = 1
     bInterfaceProtocol = 2
    report descriptor size = 176
    Single endpoint HID:
      endpoint = 81
       size = 9
       interval = 4
    new_Pipe
    allocate_interrupt_pipe_bandwidth
     best_bandwidth = 3
    , at offset = 0, shift= 0
    add_qh_to_periodic_schedule:
      interval = 4
      offset =   0
      add to slot 0
      add to slot 4
      add to slot 8
      add to slot 12
      add to slot 16
      add to slot 20
      add to slot 24
      add to slot 28
    Periodic Schedule:
     0: 1FFF2DA0
     1: (empty)
     2: (empty)
     3: (empty)
     4: 1FFF2DA0
     5: (empty)
     6: (empty)
     7: (empty)
     8: 1FFF2DA0
     9: (empty)
    10: (empty)
    11: (empty)
    12: 1FFF2DA0
    13: (empty)
    14: (empty)
    15: (empty)
    16: 1FFF2DA0
    17: (empty)
    18: (empty)
    19: (empty)
    20: 1FFF2DA0
    21: (empty)
    22: (empty)
    23: (empty)
    24: 1FFF2DA0
    25: (empty)
    26: (empty)
    27: (empty)
    28: 1FFF2DA0
    29: (empty)
    30: (empty)
    31: (empty)
    new_Control_Transfer
    Descriptor 33 = HID
    Descriptor 5 = ENDPOINT
    Descriptor 4 = INTERFACE
    KeyboardController claim this=1FFF2020
    KeyboardController claim this=1FFF2220
    HIDParser claim this=1FFF3CE0
     bInterfaceClass =    3
     bInterfaceSubClass = 0
     bInterfaceProtocol = 0
    report descriptor size = 75
    Single endpoint HID:
      endpoint = 82
       size = 64
       interval = 4
    new_Pipe
    allocate_interrupt_pipe_bandwidth
     best_bandwidth = 5
    , at offset = 0, shift= 3
    add_qh_to_periodic_schedule:
      interval = 4
      offset =   0
      traverse list 0
      traverse list 4
    More details about this device up in #43. Now to start debugging.

    Update: looks like, it is dying in the second Hid Interface for this device. That is there are two Interfaces,
    The first is for MOUSE, second is for DIGITIZER, looks like both report single End point.

    The first one looks like it completes, the new pipe call. That is I have prints on both sides:
    Code:
    		println(" *** before new pipe ***");
    		in_pipe = new_Pipe(dev, 3, endpoint & 0x0F, 1, size, interval);
    		out_pipe = NULL;
    		in_size = size;
    		println("    pipe =", (uint32_t)in_pipe, HEX);
    And not getting the println with the Pipe = ...

    2nd Edit: It is hanging in: void USBHost::add_qh_to_periodic_schedule(Pipe_t *pipe).

    I am thinking it uses the pointer to Pipe with the knowledge that the pointers are aligned on 32 bit boundary, so that the lower 5 bits will always be zero... So you can maybe encode information into these bits. Wondering how that works with the
    horizontal_link variable in the Pipe_struct. That is if this is a linked list? If so how does it work with the different time slots.
    That is at Timer 0 slot it finds that it needs to link... So maybe it encodes that data, but what happens when it needs to link again at Slot 4... Again need to see how this all works.
    Last edited by KurtE; 09-10-2017 at 04:03 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •