Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Which of the two "hidraw" devices is my RawHID?

  1. #1
    Senior Member
    Join Date
    Dec 2014
    Posts
    217

    Which of the two "hidraw" devices is my RawHID?

    When I use the RawHID USB type on a Teensy 3.2, and plug it into my Raspberry Pi, I see two rawhid devices show up:

    Code:
    pi@crunch:~/hidinfo $ ./hidinfo /dev/hidraw*
    /dev/hidraw0: Permission denied
    /dev/hidraw1: Permission denied
    /dev/hidraw2: Permission denied
    /dev/hidraw3: USB,16c0,0486 Teensyduino Teensyduino RawHID
    /dev/hidraw4: USB,16c0,0486 Teensyduino Teensyduino RawHID
    I presume one of these is the "programming" endpoint, and one of them is the endpoint I actually add.
    How can I tell which is for programming, and which is for my sketch?

    (It seems to be the one with INPUT endpoint number 0 -- is this always correct?)

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,115
    One is RawHID and the other is the HID interface used for emulating Serial, so you can still use Serial.print() to send to the Arduino Serial Monitor.

  3. #3
    Senior Member
    Join Date
    Dec 2014
    Posts
    217
    Quote Originally Posted by PaulStoffregen View Post
    One is RawHID and the other is the HID interface used for emulating Serial, so you can still use Serial.print() to send to the Arduino Serial Monitor.
    But how do I tell, from the Linux machine, which one is which?
    Should I attempt to talk to rawhid3 or rawhid4?

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,115
    To tell them apart, you're probably going to need to open each and use the HIDIOCGRDESC ioctl to tell them apart. If you discover you've opened the wrong one, just close the file descriptor and move on.

  5. #5
    Senior Member
    Join Date
    Dec 2014
    Posts
    217
    Gotcha; thanks!

  6. #6
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    You can use usage page / usage:

    cat /sys/class/hidraw/hidraw0/device/report_descriptor | hidrd-convert -o spec
    Usage Page (FFC9h), ; FFC9h, vendor-defined
    Usage (04h),

    Collection (92),
    Report Size (8),
    Logical Minimum (0),
    Logical Maximum (255),
    Report Count (64),
    Usage (75h),
    Input (Variable),
    Report Count (32),
    Usage (76h),
    Output (Variable),
    Report Count (4),
    Usage (76h),
    Feature (Variable),
    End Collection

    cat /sys/class/hidraw/hidraw1/device/report_descriptor | hidrd-convert -o spec
    Usage Page (FFABh), ; FFABh, vendor-defined
    Usage (0200h),

    Collection (Application),
    Report Size (8),
    Logical Minimum (0),
    Logical Maximum (255),
    Report Count (64),
    Usage (01h),
    Input (Variable),
    Report Count (64),
    Usage (02h),
    Output (Variable),
    End Collection

  7. #7
    Senior Member
    Join Date
    Dec 2014
    Posts
    217
    Thanks! It's actually easier than that; I look for USB VID/PID of the Teensy, and then pick the endpoint that has a descriptor length of 28.
    Some may call this a hack, but it works well enough for me :-)

    Code:
    #include <linux/input.h>
    #include <linux/hidraw.h>
    
    #define TEENSY_VENDOR 0x16c0
    #define TEENSY_PRODUCT 0x0486
    #define TEENSY_RAWHID_ENDPOINT_DESC_SIZE 28
    
    static int verify_open(char const *name) {
        int fd;
        int sz[2] = { 0 };
        hidraw_devinfo hrdi = { 0 };
    
        fd = open(name, O_RDWR | O_NONBLOCK);
        if (fd < 0) {
            return -1;
        }
        if (ioctl(fd, HIDIOCGRAWINFO, &hrdi) < 0) {
            goto bad_fd;
        }
        if (hrdi.vendor != TEENSY_VENDOR || hrdi.product != TEENSY_PRODUCT) {
            goto bad_fd;
        }
        if (ioctl(fd, HIDIOCGRDESCSIZE, sz) < 0) {
            goto bad_fd;
        }
        //  A magical size found by examination
        if (sz[0] != TEENSY_RAWHID_ENDPOINT_DESC_SIZE) {
            goto bad_fd;
        }
        fprintf(stderr, "serial/hidraw open %s returns fd %d\n", name, fd);
        return fd;
    
    bad_fd:
        if (fd >= 0) {
            close(fd);
        }
        return -1;
    }
    And, using HidRAW, my application works well. The Linux USB serial driver has some kind of problem that makes it wedge more than work for anything that has a higher packet rate :-(
    (I've seen this on more than one device, not just Teensys. Or maybe just all the devices have some kind of bug... but trying on Windows, it doesn't wedge.)

Posting Permissions

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