[libhid-discuss] Not sure what to do next
alfredo alvarez
zeus2003 at yahoo.com
Fri Mar 14 04:38:58 UTC 2008
Hello,
I'm a computer engineering student and working on my capstone project i'm developing a hid device to read sensor data. I'm using libhid to build the driver. While i wait for the device to be completed i was playing around with a usb mouse trying to read the X value to see how does getting data works in my real application i don't have interrupts since it's a pull mechanism therefore those wouldnt be used below are my modification of the test class and my output.The current problem i have is that i get a broken pipe method while trying to send a packet(i need to do this in order to keep the device active right ?) and if i don't do that i seem to get nothing on the data. I tried to install usbview in ubuntu but is failing in order to find out what is wrong with the device.But it doesn't want to load and its dying silently. Thanks ahead.
#include <hid.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> /* for getopt() */
bool match_serial_number(struct usb_dev_handle* usbdev, void* custom, unsigned int len)
{
bool ret;
char* buffer = (char*)malloc(len);
usb_get_string_simple(usbdev, usb_device(usbdev)->descriptor.iSerialNumber,
buffer, len);
ret = strncmp(buffer, (char*)custom, len) == 0;
free(buffer);
return ret;
}
int main(int argc, char *argv[])
{
HIDInterface* hid;
int iface_num = 0;
hid_return ret;
unsigned short vendor_id = 0x046d;//0x51d;0x046d
unsigned short product_id = 0xc016;//0x0002;0xc016
char *vendor, *product;
int flag;
/* Parse command-line options.
*
* Currently, we only accept the "-d" flag, which works like "lsusb", and the
* "-i" flag to select the interface (default 0). The syntax is one of the
* following:
*
* $ test_libhid -d 1234:
* $ test_libhid -d :5678
* $ test_libhid -d 1234:5678
*
* Product and vendor IDs are assumed to be in hexadecimal.
*
* TODO: error checking and reporting.
*/
while((flag = getopt(argc, argv, "d:i:")) != -1) {
switch (flag) {
case 'd':
product = optarg;
vendor = strsep(&product, ":");
if(vendor && *vendor) {
vendor_id = strtol(vendor, NULL, 16);
}
if(product && *product) {
product_id = strtol(product, NULL, 16);
}
break;
case 'i':
iface_num = atoi(optarg);
break;
}
}
/* How to use a custom matcher function:
*
* The third member of the HIDInterfaceMatcher is a function pointer, and
* the forth member will be passed to it on invocation, together with the
* USB device handle. The fifth member holds the length of the buffer
* passed. See above. This can be used to do custom selection e.g. if you
* have multiple identical devices which differ in the serial number.
*
* char const* const serial = "01518";
* HIDInterfaceMatcher matcher = {
* 0x06c2, // vendor ID
* 0x0038, // product ID
* match_serial_number, // custom matcher function pointer
* (void*)serial, // custom matching data
* strlen(serial)+1 // length of custom data
* };
*
* If you do not want to use this, set the third member to NULL.
* Then the match will only be on vendor and product ID.
*/
// HIDInterfaceMatcher matcher = { 0x0925, 0x1237, NULL, NULL, 0 };
HIDInterfaceMatcher matcher = { vendor_id, product_id, NULL, NULL, 0 };
/* see include/debug.h for possible values */
hid_set_debug(HID_DEBUG_ALL);
hid_set_debug_stream(stderr);
/* passed directly to libusb */
hid_set_usb_debug(0);
ret = hid_init();
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_init failed with return code %d\n", ret);
return 1;
}
hid = hid_new_HIDInterface();
if (hid == 0) {
fprintf(stderr, "hid_new_HIDInterface() failed, out of memory?\n");
return 1;
}
/* How to detach a device from the kernel HID driver:
*
* The hid.o or usbhid.ko kernel modules claim a HID device on insertion,
* usually. To be able to use it with libhid, you need to blacklist the
* device (which requires a kernel recompilation), or simply tell libhid to
* detach it for you. hid_open just opens the device, hid_force_open will
* try n times to detach the device before failing.
* In the following, n == 3.
*
* To open the HID, you need permission to the file in the /proc usbfs
* (which must be mounted -- most distros do that by default):
* mount -t usbfs none /proc/bus/usb
* You can use hotplug to automatically give permissions to the device on
* connection. Please see
* http://cvs.ailab.ch/cgi-bin/viewcvs.cgi/external/libphidgets/hotplug/
* for an example. Try NOT to work as root!
*/
ret = hid_force_open(hid, iface_num, &matcher, 3);
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_force_open failed with return code %d\n", ret);
return 1;
}
ret = hid_write_identification(stdout, hid);
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_write_identification failed with return code %d\n", ret);
return 1;
}
ret = hid_dump_tree(stdout, hid);
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_dump_tree failed with return code %d\n", ret);
return 1;
}
/* How to write to and read from a device:
*
* Writing to a device requires the HID usage path, a buffer, and the length
* of the latter. You must also know the exact length of a packet expected
* by the device, and the protocol to speak over HID.
*
* libhid uses the MGE hidparser, which parses the HID usage tree and places
* the available usages at its leafs (leaves?). The path information can be
* read from the `lsusb -vvv` output, or by inspecting the output of
* hid_dump_tree. In the output, 0x80 denotes an input endoint (sent by the
* device), and 0x90 an output endpoint (sent to the device). These are then
* used to communicate with the device.
*
* In the example of the Phidgets QuadServoController (www.phidgets.com, and
* libphidgets.alioth.debian.org), the following two paths identify the
* input and output descriptors respectively.
*
* unsigned char const PATHLEN = 3;
* int const PATH_IN[PATHLEN] = { 0xffa00001, 0xffa00002, 0xffa10003 };
* int const PATH_OUT[PATHLEN] = { 0xffa00001, 0xffa00002, 0xffa10004 };
*
* This is derived from the output of `lsusb -d 0x06c2:0x0038 -vvv` as
* follows. You need to run `libhid_detach_device 06c2:0038` before lsusb
* will output this info:
*
* Bus 001 Device 028: ID 06c2:0038 GLAB Chester 4-Motor PhidgetServo v3.0
* Device Descriptor:
* [...]
* Configuration Descriptor:
* [...]
* Interface Descriptor:
* [...]
* iInterface
* HID Device Descriptor:
* [...]
* Report Descriptor:
* [...]
* Item(Global): Usage Page, data= [ 0xa0 0xff ] 65440
* [...]
* Item(Local ): Usage, data= [ 0x01 ] 1
* [...]
*
* Item(Local ): Usage, data= [ 0x02 ] 2
* [...]
*
* Item(Global): Usage Page, data= [ 0xa1 0xff ] 65441
* [...]
*
* Item(Local ): Usage, data= [ 0x03 ] 3
* [...]
* Item(Main ): Input, data= [ 0x02 ] 2
* [...]
*
* Item(Local ): Usage, data= [ 0x04 ] 4
* [...]
* Item(Main ): Output, data= [ 0x02 ] 2
* [...]
*
* So working backwards,
* "Item(Main) Output" is usage 4 of usage page 65441,
* which is rooted at "Item(Local) ... 2" of usage page 65440,
* which is rooted at "Item(Local) ... 1" of usage page 65440
*
* A path component is 32 bits, the high 16 bits identify the usage page,
* and the low 16 bits the item number. Thus (now working forwards):
*
* 65440 << 16 + 1 -> 0xffa00001
* 65440 << 16 + 2 -> 0xffa00002
* 65441 << 16 + 4 -> 0xffa10004
*
* which gives the path the the output usage of the HID. The input usage may
* be found analogously.
*
* Now, to send 6 bytes:
*
* unsigned char const SEND_PACKET_LEN = 6;
* // fill an example packet:
* char const PACKET[SEND_PACKET_LEN] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5 };
*
* ret = hid_set_output_report(hid, PATH_IN, PATHLEN, PACKET, SEND_PACKET_LEN);
* if (ret != HID_RET_SUCCESS) {
* fprintf(stderr, "hid_set_output_report failed with return code %d\n", ret);
* }
*
* And reading works similarly:
* char packet[RECV_PACKET_LEN];
* ret = hid_get_input_report(hid, PATH_OUT, PATHLEN, packet, RECV_PACKET_LEN);
* if (ret != HID_RET_SUCCESS) {
* fprintf(stderr, "hid_get_input_report failed with return code %d\n", ret);
* }
* // now use the RECV_PACKET_LEN bytes starting at *packet.
*/
/** this code is for the logitech mouse it might not work yet
.*/
printf("Writing");
//int PATH_IN[3] = { 0x00010002,0x00010001 , 0x00000000};
//int pathinlen = 3;
int pathinlen = 3;
//int PATH_IN[3] = { 0x00010002 , 0x00010001 , 0x00010030};
//int PATH_IN[3] = { 0x00010002 , 0x00010001 , 0x00010031};
int PATH_IN[3] = { 0x00010002, 0x00010001, 0x00010038 } ;
//int PATH_IN[2] = { 0x00010002,0x00010001};
//int pathinlen = 2;
int const WRITE_PACKET_LEN = 8;
char write_packet[5] = { 0x01,0x00,0x00,0x00,0x00};
ret = hid_set_output_report(hid,
PATH_IN,
pathinlen,
write_packet,
WRITE_PACKET_LEN);
/** this code is for the logitech mouse*/
int pathlen = 1;
int RECV_PACKET_LEN = 4;
int PATH_OUT[1] = { 0x00010031 };
unsigned char packet[RECV_PACKET_LEN];
ret = hid_get_input_report(hid, PATH_OUT, pathlen, packet, RECV_PACKET_LEN);
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_get_input_report failed with return code %d\n", ret);
}
printf("LOOK HEre \n");
printf("%s ", packet);
printf("LOOK HEre \n");
ret = hid_close(hid);
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_close failed with return code %d\n", ret);
return 1;
}
hid_delete_HIDInterface(&hid);
ret = hid_cleanup();
if (ret != HID_RET_SUCCESS) {
fprintf(stderr, "hid_cleanup failed with return code %d\n", ret);
return 1;
}
return 0;
}
My output
Para el mouse USB
Bus 002 Device 002: ID 046d:c016 Logitech, Inc. M-UV69a Optical Wheel Mouse VendorId and ProductId o46d:c016
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x046d Logitech, Inc.
idProduct 0xc016 M-UV69a Optical Wheel Mouse
bcdDevice 3.40
iManufacturer 1 Logitech
iProduct 2 Optical USB Mouse
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1 Number of endpoints besides the 0 endpoint
bInterfaceClass 3 Human Interface Devices Determines if it is an HID device
bInterfaceSubClass 1 Boot Interface Subclass Means that it has code in it to be used at boot time - unless is a keyboard or mouse probably not needed.
bInterfaceProtocol 2 Mouse 0 - for none 1 - for keyboard 2 - for mouse
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 52
Report Descriptor: (length is 52)
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x02 ] 2
Mouse
Item(Main ): Collection, data= [ 0x01 ] 1 Empieza una coleccion
Application
Item(Local ): Usage, data= [ 0x01 ] 1 Esta conexion va a ser un pointer uso de la coleccion
Pointer
Item(Main ): Collection, data= [ 0x00 ] 0 lo que es el objeto empieza otra coleccion
Physical
Item(Global): Usage Page, data= [ 0x09 ] 9 empieza el tag de buttons
Buttons
Item(Local ): Usage Minimum, data= [ 0x01 ] 1 El minimo en la collecion de botones cuantos botones son
Button 1 (Primary)
Item(Local ): Usage Maximum, data= [ 0x03 ] 3 El maximo
Button 3 (Tertiary)
Item(Global): Logical Minimum, data= [ 0x00 ] 0 El range de valores por cada button
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Global): Report Size, data= [ 0x01 ] 1 cada buton va a tener un bit
Item(Global): Report Count, data= [ 0x03 ] 3 cantidad de reportes/butones
Item(Main ): Input, data= [ 0x02 ] 2 //define una variable para rellenar el byte 8-3 =5
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x05 ] 5
Item(Global): Report Count, data= [ 0x01 ] 1 //final del relleno
Item(Main ): Input, data= [ 0x01 ] 1 //resetea la data
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Usage Page, data= [ 0x01 ] 1 //le entra el usage page y se controles d desktop
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x30 ] 48 // especificas los que el boton segun usage table
Direction-X
Item(Local ): Usage, data= [ 0x31 ] 49
Direction-Y
Item(Local ): Usage, data= [ 0x38 ] 56
Wheel
Item(Global): Logical Minimum, data= [ 0x81 ] 129 // minimo valor para todos los butones anteriores
Item(Global): Logical Maximum, data= [ 0x7f ] 127 // valor maximo para todos los botones anteriores
Item(Global): Report Size, data= [ 0x08 ] 8 //cada uno es tamana un byte = 8 bits
Item(Global): Report Count, data= [ 0x03 ] 3 // hay 3 uno por cada valor
Item(Main ): Input, data= [ 0x06 ] 6
Data Variable Relative No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Item(Main ): End Collection, data=none
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0004 1x 4 bytes
bInterval 10
Device Status: 0x0000
(Bus Powered)
*______**DATA prog
NOTICE: hid_init(): libhid 0.2.15+20060325.0.0 is being initialized.
TRACE: hid_init(): initialising USB subsystem...
TRACE: hid_init(): scanning for USB busses...
TRACE: hid_init(): scanning for USB devices...
NOTICE: hid_init(): successfully initialised HID library.
TRACE: hid_new_HIDInterface(): creating a new HIDInterface instance...
TRACE: hid_force_open(): forcefully opening a device interface according to matching criteria...
TRACE: hid_get_usb_handle(): acquiring handle for a USB device...
TRACE: hid_find_usb_device(): enumerating USB busses...
TRACE: hid_find_usb_device(): enumerating USB devices on bus 004...
TRACE: hid_find_usb_device(): inspecting USB device 004/001[0]...
TRACE: hid_compare_usb_device(): comparing match specifications to USB device...
TRACE: hid_compare_usb_device(): inspecting vendor ID...
TRACE: hid_compare_usb_device(): no match on vendor ID.
TRACE: hid_compare_usb_device(): inspecting product ID...
TRACE: hid_compare_usb_device(): no match on product ID.
TRACE: hid_compare_usb_device(): no custom matching function supplied.
NOTICE: hid_find_usb_device(): vendor 0x0000 of USB device 004/001[0] does not match 0x046d.
TRACE: hid_find_usb_device(): enumerating USB devices on bus 002...
TRACE: hid_find_usb_device(): inspecting USB device 002/002[0]...
TRACE: hid_compare_usb_device(): comparing match specifications to USB device...
TRACE: hid_compare_usb_device(): inspecting vendor ID...
TRACE: hid_compare_usb_device(): match on vendor ID: 0x046d.
TRACE: hid_compare_usb_device(): inspecting product ID...
TRACE: hid_compare_usb_device(): match on product ID: 0xc016.
TRACE: hid_compare_usb_device(): no custom matching function supplied.
NOTICE: hid_find_usb_device(): found a matching USB device 002/002[0].
TRACE: hid_force_open(): claiming USB device 002/002[0].
TRACE: hid_os_force_claim(): failed to claim USB device 002/002[0], trying 2 more time(s)...
TRACE: hid_os_force_claim(): detaching kernel driver from USB device 002/002[0]...
TRACE: hid_os_force_claim(): trying again to claim USB device 002/002[0]...
NOTICE: hid_force_open(): successfully claimed USB device 002/002[0].
TRACE: hid_init_parser(): initialising the HID parser for USB Device 002/002[0]...
TRACE: hid_init_parser(): allocating space for HIDData structure...
TRACE: hid_init_parser(): successfully allocated memory for HIDData strcture.
TRACE: hid_init_parser(): allocating space for HIDParser structure...
TRACE: hid_init_parser(): successfully allocated memory for HIDParser strcture.
NOTICE: hid_init_parser(): successfully initialised the HID parser for USB Device 002/002[0].
TRACE: hid_prepare_hid_descriptor(): initialising the HID descriptor for USB device 002/002[0]...
TRACE: hid_prepare_hid_descriptor(): retrieving HID descriptor for USB device 002/002[0]...
NOTICE: hid_prepare_hid_descriptor(): successfully initialised HID descriptor for USB device 002/002[0] (52 bytes).
TRACE: hid_prepare_report_descriptor(): initialising the report descriptor for USB device 002/002[0]...
TRACE: hid_prepare_report_descriptor(): retrieving report descriptor for USB device 002/002[0]...
NOTICE: hid_prepare_report_descriptor(): successfully initialised report descriptor for USB device 002/002[0].
TRACE: hid_prepare_parser(): setting up the HID parser for USB device 002/002[0]...
TRACE: hid_reset_parser(): resetting the HID parser for USB device 002/002[0]...
TRACE: hid_prepare_parser(): dumping the raw report descriptor
TRACE: hid_prepare_parser(): 0x000: 0x05 0x01 0x09 0x02 0xa1 0x01 0x09 0x01
TRACE: hid_prepare_parser(): 0x008: 0xa1 0x00 0x05 0x09 0x19 0x01 0x29 0x03
TRACE: hid_prepare_parser(): 0x010: 0x15 0x00 0x25 0x01 0x75 0x01 0x95 0x03
TRACE: hid_prepare_parser(): 0x018: 0x81 0x02 0x75 0x05 0x95 0x01 0x81 0x01
TRACE: hid_prepare_parser(): 0x020: 0x05 0x01 0x09 0x30 0x09 0x31 0x09 0x38
TRACE: hid_prepare_parser(): 0x028: 0x15 0x81 0x25 0x7f 0x75 0x08 0x95 0x03
TRACE: hid_prepare_parser(): 0x030: 0x81 0x06 0xc0 0xc0
TRACE: hid_prepare_parser(): parsing the HID tree of USB device 002/002[0]...
NOTICE: hid_prepare_parser(): successfully set up the HID parser for USB device 002/002[0].
NOTICE: hid_force_open(): successfully opened USB device 002/002[0].
device identification of HIDInterface 002/002[0]:
dev_handle: 0x0804b188
device: 0x08052188
location: 002/002
manufacturer: Logitech
product: Optical USB Mouse
TRACE: hid_reset_parser(): resetting the HID parser for USB device 002/002[0]...
TRACE: hid_dump_tree(): iterating the parse tree for USB device 002/002[0]...
parse tree of HIDInterface 002/002[0]:
path: 0x00010002.0x00010001.0x00000000; type: 0x80
path: 0x00010002.0x00010001.0x00000000; type: 0x80
path: 0x00010002.0x00010001.0x00000000; type: 0x80
path: 0x00010002.0x00010001.0x00000000; type: 0x80
path: 0x00010002.0x00010001.0x00010030; type: 0x80
path: 0x00010002.0x00010001.0x00010031; type: 0x80
path: 0x00010002.0x00010001.0x00010038; type: 0x80
TRACE: hid_reset_parser(): resetting the HID parser for USB device 002/002[0]...
TRACE: hid_close(): closing USB device 002/002[0]...
TRACE: hid_close(): closing handle of USB device 002/002[0]...
NOTICE: hid_close(): successfully closed USB device 002/002[0].
TRACE: hid_reset_parser(): resetting the HID parser for USB device 002/002[0]...
TRACE: hid_close(): freeing memory allocated for HID parser...
TRACE: hid_close(): resetting HIDInterface...
NOTICE: hid_cleanup(): successfully deinitialised HID library.
---------------------------------
Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now.
More information about the libhid-discuss
mailing list