[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