I'm hoping this is the right list for this question, and please forgive me if this is a dumb question or it's been asked before. I've tried google and man pages and about a day's worth of coding with little success.

I'm trying to support OpenBSD in a new version of this program http://www.pjrc.com/teensy/loader_cli.html Based on an earlier patch from Chris Kuethe, it's working great on OpenBSD. Well, except the /dev/uhid0 device name is hard-coded, and my next version will have a feature to use multiple devices at the same time (for different functions, based on their product IDs), so hard coding or expecting the user to supply the device names just isn't practical.

My question: how do I figure out which /dev/uhid device file(s), if any, corresponds to my device's product and vendor ID numbers? Basically, this is what I need to do:

int open_my_usb_device(int vid, int pid)
{
       const char *dev_name;

       // TODO: Perform some magic to figure out
       // which /dev/uhid# device is actually the
       // this vendor and product ID.

dev_name = "/dev/uhid0"; // not hard coded like this, nor from user input

       return open(dev_name, O_RDWR);
}

I've tried opening the /dev/usb devices and calling the USB_DEVICEINFO ioctl (originally suggested to me by Todd T Fries). This gets very close, but the best I've been able to do is learn which uhidev driver (but not uhid) is connected to my device. For example (this code copied at the end of this email):

$ ./test /dev/usb1
addr 1: 0x0000, 0x106b, rev 1.00, drivers:  uhub1
addr 2: 0x0478, 0x16c0, rev 1.20, drivers:  uhidev0

This tells me the uhidev0 driver is loaded for my device. But the mapping from uhidev to uhid isn't necessarily 1-to-1. I need to know which uhid device to open!

So far, the only way I've discovered to learn which uhid device corresponds to my hardware is by looking at /var/log/messages.

$ tail -3 /var/log/messages Jan 21 00:42:11 bsd /bsd: uhidev0 at uhub1 port 1 configuration 1 interface 0 "vendor 0x16c0 product 0x0478" rev 1.10/1.20 addr 2
Jan 21 00:42:11 bsd /bsd: uhidev0: iclass 3/0
Jan 21 00:42:11 bsd /bsd: uhid0 at uhidev0: input=0, output=130, feature=0

I suppose I could write code to try parsing /var/log/messages, but that seems like a horribly ugly hack that's bound to fail at some point in the future.


Here is the work in progress.

http://www.pjrc.com/tmp/teensy_loader_cli.work-in-progress.zip

I've finished Linux, Windows and Macos support, and BSD is working but the device name is hard coded. I'm truly stuck on this last bit, so I'm hoping you might tell me how I can figure out how to find the right uhid device for my product/vendor IDs. This is the last piece I need to support BSD as well as the other systems.


Thanks,

-Paul
[email protected]


// test.c
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <dev/usb/usb.h>
// originally suggested by Todd T. Fries

int
main(int argc, char **argv)
{
       struct usb_device_info   di;
       int                      i, e,f,a;

       f = open(argv[1], O_RDWR);
       if (f < 0) err(1, "%s", argv[1]);

       for (a=0; a < USB_MAX_DEVICES; a++) {
               memset(&di, 0, sizeof(struct usb_device_info));
               di.udi_addr = a;
               e = ioctl(f, USB_DEVICEINFO, &di);
               if (e) continue;
               printf("addr %d: 0x%04x, 0x%04x, rev %s, drivers: ", a,
                       di.udi_productNo, di.udi_vendorNo, di.udi_release);
               for (i=0; i < USB_MAX_DEVNAMES; i++) {
                       if (*di.udi_devnames[i] == NULL) continue;
                       printf(" %s", di.udi_devnames[i]);
               }
               printf("\n");
       }
       close(f);
       return 0;
}

Reply via email to