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;
}