Added the hidapi_enumerate() interface on Linux.

Added manufacturer and product strings to the hid_device struct.
This commit is contained in:
Alan Ott
2010-07-01 17:39:24 -04:00
parent a7160b8f49
commit ebc18502b7
5 changed files with 184 additions and 69 deletions
+2
View File
@@ -230,6 +230,8 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device *devs)
struct hid_device *next = d->next;
free(d->path);
free(d->serial_number);
free(d->manufacturer_string);
free(d->product_string);
free(d);
d = next;
}
+4
View File
@@ -36,6 +36,10 @@ extern "C" {
unsigned short product_id;
/** Serial Number */
wchar_t *serial_number;
/** Manufacturer String */
wchar_t *manufacturer_string;
/** Product string */
wchar_t *product_string;
/** Pointer to the next device */
struct hid_device *next;
+4 -1
View File
@@ -39,7 +39,10 @@ int main(int argc, char* argv[])
cur_dev = devs;
while (cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
printf("\n\n");
printf("\n");
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
printf(" Product: %ls\n", cur_dev->product_string);
printf("\n");
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
+1 -1
View File
@@ -1,3 +1,3 @@
gcc -Wall -g -c hid.c -I ../hidapi
gcc -Wall -g -c ../hidtest/hidtest.cpp -I ../hidapi
g++ -Wall -g -o test hid.o hidtest.o /usr/lib/libudev.so.0.8.0
g++ -Wall -g -o test hid.o hidtest.o -ludev
+173 -67
View File
@@ -16,15 +16,22 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include "/usr/include/libudev.h"
/* Unix */
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "libudev.h"
#include "hidapi.h"
struct Device {
int valid;
int device_handle;
int blocking;
int valid;
int device_handle;
int blocking;
};
@@ -37,6 +44,24 @@ static void register_error(struct Device *device, const char *op)
}
/* Get an attribute value from a udev_device and return it as a whar_t
string. The returned string must be freed with free() when done.*/
static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
{
const char *str;
wchar_t *ret = NULL;
str = udev_device_get_sysattr_value(dev, udev_name);
if (str) {
/* Convert the string from UTF-8 to wchar_t */
size_t wlen = mbstowcs(NULL, str, 0);
ret = calloc(wlen+1, sizeof(wchar_t));
mbstowcs(ret, str, wlen+1);
ret[wlen] = 0x0000;
}
return ret;
}
struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
struct udev *udev;
@@ -46,12 +71,14 @@ struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsig
struct hid_device *root = NULL; // return object
struct hid_device *cur_dev = NULL;
setlocale(LC_ALL,"");
/* Create the udev object */
udev = udev_new();
if (!udev) {
printf("Can't create udev\n");
exit(1);
return NULL;
}
/* Create a list of the devices in the 'hidraw' subsystem. */
@@ -59,46 +86,21 @@ struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsig
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
/* For each item enumerated, print out its information.
udev_list_entry_foreach is a macro which expands to
a loop. The loop will be executed for each member in
devices, setting dev_list_entry to a list entry
which contains the device's path in /sys. */
/* For each item, see if it matches the vid/pid, and if so
create a udev_device record for it */
udev_list_entry_foreach(dev_list_entry, devices) {
const char *path;
const char *sysfs_path;
const char *dev_path;
const char *str;
size_t len;
struct hid_device *tmp;
unsigned short dev_vid;
unsigned short dev_pid;
/* Get the filename of the /sys entry for the device
and create a udev_device object (dev) representing it */
path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev, path);
/* usb_device_get_devnode() returns the path to the device node
itself in /dev. */
printf("Device Node Path: %s\n", udev_device_get_devnode(dev));
sysfs_path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev, sysfs_path);
dev_path = udev_device_get_devnode(dev);
tmp = malloc(sizeof(struct hid_device));
if (cur_dev) {
cur_dev->next = tmp;
}
else {
root = tmp;
}
cur_dev = tmp;
cur_dev->next = NULL;
str = udev_device_get_devnode(dev);
if (str) {
len = strlen(str);
cur_dev->path = calloc(len+1, sizeof(char));
strncpy(cur_dev->path, str, len+1);
cur_dev->path[len] = '\0';
}
else
cur_dev->path = NULL;
/* The device pointed to by dev contains information about
the hidraw device. In order to get information about the
USB device, get the parent device with the
@@ -110,49 +112,121 @@ struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsig
"usb",
"usb_device");
if (!dev) {
printf("Unable to find parent usb device.");
exit(1);
/* Unable to find parent usb device. */
goto next;
}
/* Get the VID/PID of the device */
str = udev_device_get_sysattr_value(dev,"idVendor");
cur_dev->vendor_id = (str)? strtol(str, NULL, 16): 0x0;
dev_vid = (str)? strtol(str, NULL, 16): 0x0;
str = udev_device_get_sysattr_value(dev, "idProduct");
cur_dev->product_id = (str)? strtol(str, NULL, 16): 0x0;
dev_pid = (str)? strtol(str, NULL, 16): 0x0;
/* Check the VID/PID against the arguments */
if ((vendor_id == 0x0 && product_id == 0x0) ||
(vendor_id == dev_vid && product_id == dev_pid)) {
struct hid_device *tmp;
size_t len;
/* From here, we can call get_sysattr_value() for each file
in the device's /sys entry. The strings passed into these
functions (idProduct, idVendor, serial, etc.) correspond
directly to the files in the /sys directory which
represents the USB device. Note that USB strings are
Unicode, UCS2 encoded, but the strings returned from
udev_device_get_sysattr_value() are UTF-8 encoded. */
printf(" VID/PID: %s %s\n",
udev_device_get_sysattr_value(dev,"idVendor"),
udev_device_get_sysattr_value(dev, "idProduct"));
printf(" %s\n %s\n",
udev_device_get_sysattr_value(dev,"manufacturer"),
udev_device_get_sysattr_value(dev,"product"));
printf(" serial: %s\n",
udev_device_get_sysattr_value(dev, "serial"));
/* VID/PID match. Create the record. */
tmp = malloc(sizeof(struct hid_device));
if (cur_dev) {
cur_dev->next = tmp;
}
else {
root = tmp;
}
cur_dev = tmp;
/* Fill out the record */
cur_dev->next = NULL;
str = dev_path;
if (str) {
len = strlen(str);
cur_dev->path = calloc(len+1, sizeof(char));
strncpy(cur_dev->path, str, len+1);
cur_dev->path[len] = '\0';
}
else
cur_dev->path = NULL;
/* Serial Number */
cur_dev->serial_number
= copy_udev_string(dev, "serial");
/* Manufacturer and Product strings */
cur_dev->manufacturer_string
= copy_udev_string(dev, "manufacturer");
cur_dev->product_string
= copy_udev_string(dev, "product");
/* VID/PID */
cur_dev->vendor_id = dev_vid;
cur_dev->product_id = dev_pid;
}
else
goto next;
next:
udev_device_unref(dev);
}
/* Free the enumerator object */
/* Free the enumerator and udev objects. */
udev_enumerate_unref(enumerate);
udev_unref(udev);
return root;
}
void HID_API_EXPORT hid_free_enumeration(struct hid_device *devs)
{
struct hid_device *d = devs;
while (d) {
struct hid_device *next = d->next;
free(d->path);
free(d->serial_number);
free(d->manufacturer_string);
free(d->product_string);
free(d);
d = next;
}
}
int HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number)
{
struct hid_device *devs, *cur_dev;
const char *path_to_open = NULL;
int handle = -1;
devs = hid_enumerate(vendor_id, product_id);
cur_dev = devs;
while (cur_dev) {
if (cur_dev->vendor_id == vendor_id &&
cur_dev->product_id == product_id) {
if (serial_number) {
if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
path_to_open = cur_dev->path;
break;
}
}
else {
path_to_open = cur_dev->path;
break;
}
}
cur_dev = cur_dev->next;
}
if (path_to_open) {
/* Open the device */
handle = hid_open_path(path_to_open);
}
hid_free_enumeration(devs);
return handle;
}
int HID_API_EXPORT hid_open_path(const char *path)
{
int i;
int handle = -1;
@@ -183,6 +257,9 @@ int HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id,
return -1;
}
// OPEN HERE //
dev->device_handle = open(path, O_RDWR);
// If we have a good handle, return it.
if (dev->device_handle > 0) {
return handle;
@@ -192,13 +269,14 @@ int HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id,
dev->valid = 0;
return -1;
}
}
int HID_API_EXPORT hid_write(int device, const unsigned char *data, size_t length)
{
struct Device *dev = NULL;
int bytes_written;
int res;
// Get the handle
if (device < 0 || device >= MAX_DEVICES)
@@ -206,6 +284,8 @@ int HID_API_EXPORT hid_write(int device, const unsigned char *data, size_t lengt
if (devices[device].valid == 0)
return -1;
dev = &devices[device];
bytes_written = write(dev->device_handle, data, length);
return bytes_written;
}
@@ -215,7 +295,6 @@ int HID_API_EXPORT hid_read(int device, unsigned char *data, size_t length)
{
struct Device *dev = NULL;
int bytes_read;
int res;
// Get the handle
if (device < 0 || device >= MAX_DEVICES)
@@ -224,11 +303,14 @@ int HID_API_EXPORT hid_read(int device, unsigned char *data, size_t length)
return -1;
dev = &devices[device];
bytes_read = read(dev->device_handle, data, length);
return bytes_read;
}
int HID_API_EXPORT hid_set_nonblocking(int device, int nonblock)
{
int flags, res;
struct Device *dev = NULL;
// Get the handle
@@ -238,8 +320,23 @@ int HID_API_EXPORT hid_set_nonblocking(int device, int nonblock)
return -1;
dev = &devices[device];
dev->blocking = !nonblock;
return 0; /* Success */
flags = fcntl(dev->device_handle, F_GETFL, 0);
if (flags >= 0) {
if (nonblock)
res = fcntl(dev->device_handle, F_SETFL, flags | O_NONBLOCK);
else
res = fcntl(dev->device_handle, F_SETFL, flags & ~O_NONBLOCK);
}
else
return -1;
if (res < 0) {
return -1;
}
else {
dev->blocking = !nonblock;
return 0; /* Success */
}
}
void HID_API_EXPORT hid_close(int device)
@@ -253,6 +350,8 @@ void HID_API_EXPORT hid_close(int device)
return;
dev = &devices[device];
close(dev->device_handle);
dev->valid = 0;
}
@@ -268,6 +367,7 @@ int HID_API_EXPORT_CALL hid_get_manufacturer_string(int device, wchar_t *string,
return -1;
dev = &devices[device];
// TODO:
return 0;
}
@@ -284,6 +384,7 @@ int HID_API_EXPORT_CALL hid_get_product_string(int device, wchar_t *string, size
return -1;
dev = &devices[device];
// TODO:
return 0;
}
@@ -300,6 +401,8 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(int device, wchar_t *string
return -1;
dev = &devices[device];
// TODO:
return 0;
}
@@ -315,6 +418,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(int device, int string_index, wch
return -1;
dev = &devices[device];
// TODO:
return 0;
}
@@ -331,5 +435,7 @@ HID_API_EXPORT const char * HID_API_CALL hid_error(int device)
return NULL;
dev = &devices[device];
// TODO:
return NULL;
}