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

Thread: Teensy 4: Trouble with claiming USB Raw HID

  1. #1
    Junior Member
    Join Date
    Jun 2020
    Posts
    3

    Teensy 4: Trouble with claiming USB Raw HID

    Hello,

    I'm new to this forum and have a question on using the Teensy 4.1.

    I have a project I am porting from a Cypress PSoC 5LP to the Teensy 4.1 to make use of the much faster Teensy part.

    The PSoC part has code which is working. I'm using its USB interface to talk to a Jetson Xavier NX running Linux. This works.

    In the Teensy 4.1 project I've configured it to Tools-> USB Type: "Raw HID".

    On the Linux board I can run lsusb in a terminal. It lists all the USB devices and does show the Teensy board.

    Then I run my program on the Linux board which is written in C++. When that code starts up it opens the USB device (the Teensy) with code that looks like this:

    Code:
    dev = libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);
    The return value dev is not NULL so it found and opened the device. The next line of code is where the trouble is:

    Code:
    err = libusb_claim_interface(dev, INTERFACE);
    This returns an error and when I print the error text I get
    Code:
    Error: LIBUSB_ERROR_BUSY
    So somehow the Linux system is claiming the Teensy USB. The same code works fine with the PSoC. Why is my Linux system claiming the Teensy but not the PSoC? I've tried changing these in the file "usb_desc.h":

    #define VENDOR_ID 0x16C0
    #define PRODUCT_ID 0x0486
    #define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF
    #define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF

    and adjusting the code on the Linux side to match. It finds the device but still gives LIBUSB_ERROR_BUSY

    I don't understand enough of the USB to know why this works for the PSoC but not the Teensy.

    Can anyone point me to the culprit?

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,110
    Quote Originally Posted by Bob Randall View Post
    So somehow the Linux system is claiming the Teensy USB. The same code works fine with the PSoC. Why is my Linux system claiming the Teensy but not the PSoC?
    I can't answer for PSoC, but I can tell you Teensy's descriptors say the interface is HID. Most Linux systems have a "hidraw" driver which loads automatically for all HID interfaces which aren't recognized by other drivers. That is (probably) why.

    You can check by watching the kernel's syslog messages. On Ubuntu 18, use "tail -f /var/log/syslog". The kernel gives info about the loading and unloading of drivers, so you should what's happening.

    Probably the simplest solution is to call libusb_detach_kernel_driver(). In no programs have opened the device, this should work. Hopefully then you can just reuse the rest of that libusb code.

    Alternately, you could open the /dev/hidraw# device, and use ordinary read() and write(). But that requires rewriting more code than staying with libusb and just detaching the hidraw driver.

    Another (maybe) possible alternative would be to craft a special udev rule which tells the kernel not to load a driver. But I'm not sure how to do that, or even 100% sure it's possible. Still, might be worth a try if you want to use that libusb code without any changes.

    Or if you want to leave the PC side unchanged, but you're willing to edit Teensy's core library code, you could edit usb_desc.c to change the protocol byte for this interface, so it's not marked as HID.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,110
    One more detail to keep in mind is Teensy creates 2 HID interfaces. One is RawHID. The other is meant to emulate Serial, so you can still use Serial.print() to the Arduino Serial Monitor. In your libusb code, make sure you're opening the right interface.

  4. #4
    Junior Member
    Join Date
    Jun 2020
    Posts
    3
    With a little more searching on the internet I found this code:

    Code:
      /* Check whether a kernel driver is attached to interface #0. If so, we'll 
       * need to detach it.
       */
      if (libusb_kernel_driver_active(handle, 0))
      {
        res = libusb_detach_kernel_driver(handle, 0);
        if (res == 0)
        {
          kernelDriverDetached = 1;
        }
        else
        {
          fprintf(stderr, "Error detaching kernel driver.\n");
          return 1;
        }
      }
    This successfully released the kernel driver, so I got past that step. Now I can transmit to the Teensy, but having trouble receiving. I'm checking that now. Almost have it all working...

  5. #5
    Junior Member
    Join Date
    Jun 2020
    Posts
    3
    Got it all working. The input endpoint (for this Linux interface implementation) needed to be 0x83, not 0x03.

Posting Permissions

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