title: Reverse-engineering a HID handshake by examining bytes over USB
body: <p>I'm trying to extract real-time data from a <a href="http://inkling.wacom.eu/" rel="nofollow">Wacom Inkling</a></p>
  
  <p>Roel Janssen has already examined the packets <a href="https://github.com/roelj/inklingreader/blob/master/src/usb/online-mode.c#L113-L138" rel="nofollow">here</a>:</p>
  
  <pre><code>// Some kind of handshaking.
  // Values obtained by sniffing the USB connection between SketchManager and the device.
  unsigned char usb_data[33];
  memset (&amp;usb_data, '\0', 33);
  int bytes = 0;
  
  memcpy (&amp;usb_data, "\x80\x01\x03\x01\x02\x00\x00\x00", 8);
  bytes += libusb_control_transfer (handle,
                                    0x21,         // bmRequestType
                                    9,            // bRequest
                                    0x0380,       // wValue
                                    0,            // wIndex
                                    usb_data,     // data
                                    33,           // wLength
                                    0);           // timeout
  
  memcpy (&amp;usb_data, "\x80\x01\x0a\x01\x01\x0b\x01\x00", 8);
  bytes += libusb_control_transfer (handle, 0x21, 9, 0x0380, 0, usb_data, 33, 0);
  
  memset (&amp;usb_data, '\0', 33);
  bytes += libusb_control_transfer (handle, 0xa1, 1, 0x0380, 0, usb_data, 33, 0);
  
  memcpy (&amp;usb_data, "\x80\x01\x0b\x01\x00\x00\x00\x00", 8);
  bytes += libusb_control_transfer (handle, 0x21, 9, 0x0380, 0, usb_data, 33, 0);
  
  memcpy (&amp;usb_data, "\x80\x01\x02\x01\x01\x00\x00\x00", 8);
  bytes += libusb_control_transfer (handle, 0x21, 9, 0x0380, 0, usb_data, 33, 0);
  
  memcpy (&amp;usb_data, "\x80\x01\x0a\x01\x01\x02\x01\x00", 8);
  bytes += libusb_control_transfer (handle, 0x21, 9, 0x0380, 0, usb_data, 33, 0);
  
  memset (&amp;usb_data, '\0', 33);
  bytes += libusb_control_transfer (handle, 0xa1, 1, 0x0380, 0, usb_data, 33, 0);
  </code></pre>
  
  <p>I'm trying to rewrite this code using <a href="http://www.signal11.us/oss/hidapi/" rel="nofollow">HID API</a> which has a very minimal API (<a href="http://www.signal11.us/oss/hidapi/hidapi/doxygen/html/group__API.html" rel="nofollow">here</a>)</p>
  
  <p>I'm going to attempt to just use <code>hid_write</code> for now, but there is maybe a chance this handshake is sending a <a href="http://www.signal11.us/oss/hidapi/hidapi/doxygen/html/group__API.html#gae43ab80f741786ac4374216658fd5ab3" rel="nofollow">feature report</a>...?</p>
  
  <p>Is there anyone out there who can look at that bytestream and see what is going on?</p>
  
  <p>EDIT: It appears the Inkling exposes a FlashDrive and HID interface, so I am guessing this bytecode must be selecting the HID interface and telling it to start sending data. But can I code it in a more elegant / human readable form?</p>
  
  <p>EDIT: I have it working!  Both <code>hid_write</code> and <code>hid_send_feature_report</code> work!</p>
  
  <pre><code>hid_device* handle = hid_open(inklingVendorId, inklingProductId, NULL);
  jassert(handle != nullptr);
  
  int bytes_written =
      hid_send_feature_report(handle, (const unsigned char *)"\x80\x01\x03\x01\x02\x00\x00\x00", 8) +
      hid_send_feature_report(handle, (const unsigned char *)"\x80\x01\x0a\x01\x01\x0b\x01\x00", 8) +
      hid_send_feature_report(handle, (const unsigned char *)"\x80\x01\x0b\x01\x00\x00\x00\x00", 8) +
      hid_send_feature_report(handle, (const unsigned char *)"\x80\x01\x02\x01\x01\x00\x00\x00", 8) +
      hid_send_feature_report(handle, (const unsigned char *)"\x80\x01\x0a\x01\x01\x02\x01\x00", 8);
  jassert(bytes_written == 5*8);
  
  const int enable_nonblocking = 1, disable_nonblocking = 0;
  jassert( hid_set_nonblocking(handle, disable_nonblocking) != FAIL); // want to block
  
  while(true) {
      int bytes_got = hid_read(handle, usb_data, 10);
  </code></pre>
  
  <p>... However I would still like to understand what is going on. This is rather hacky.</p>
  
  <p>EDIT: Output of lsusb (from Roel, I don't have Linux to hand):</p>
  
  <pre><code>Bus 003 Device 002: ID 056a:0221 Wacom Co., Ltd 
  Device Descriptor:
    bLength                18
    bDescriptorType         1
    bcdUSB               2.00
    bDeviceClass            0 (Defined at Interface level)
    bDeviceSubClass         0 
    bDeviceProtocol         0 
    bMaxPacketSize0        64
    idVendor           0x056a Wacom Co., Ltd
    idProduct          0x0221 
    bcdDevice           12.56
    iManufacturer           1 (error)
    iProduct                2 MSC Device
    iSerial                 5 4833000045C5549C0002DD012DA5549C
    bNumConfigurations      1
    Configuration Descriptor:
      bLength                 9
      bDescriptorType         2
      wTotalLength           57
      bNumInterfaces          2
      bConfigurationValue     1
      iConfiguration          3 USB/MSC Inkling
      bmAttributes         0x80
        (Bus Powered)
      MaxPower              500mA
      Interface Descriptor:
        bLength                 9
        bDescriptorType         4
        bInterfaceNumber        0
        bAlternateSetting       0
        bNumEndpoints           1
        bInterfaceClass         3 Human Interface Device
        bInterfaceSubClass      0 No Subclass
        bInterfaceProtocol      2 Mouse
        iInterface              0 
          HID Device Descriptor:
            bLength                 9
            bDescriptorType        33
            bcdHID               1.01
            bCountryCode            0 Not supported
            bNumDescriptors         1
            bDescriptorType        34 Report
            wDescriptorLength     215
            Report Descriptor: (length is 215)
              Item(Global): Usage Page, data= [ 0x0d ] 13
                              Digitizer
              Item(Local ): Usage, data= [ 0x02 ] 2
                              Pen
              Item(Main  ): Collection, data= [ 0x01 ] 1
                              Application
              Item(Global): Report ID, data= [ 0x02 ] 2
              Item(Local ): Usage, data= [ 0x02 ] 2
                              Pen
              Item(Main  ): Collection, data= [ 0x00 ] 0
                              Physical
              Item(Global): Usage Page, data= [ 0x01 ] 1
                              Generic Desktop Controls
              Item(Local ): Usage, data= [ 0x30 ] 48
                              Direction-X
              Item(Local ): Usage, data= [ 0x31 ] 49
                              Direction-Y
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0x80 0x07 ] 1920
              Item(Global): Physical Minimum, data= [ 0x00 ] 0
              Item(Global): Physical Maximum, data= [ 0x00 0x78 ] 30720
              Item(Global): Unit, data= [ 0x11 ] 17
                              System: SI Linear, Unit: Centimeter
              Item(Global): Unit Exponent, data= [ 0x0e ] 14
                              Unit Exponent: 14
              Item(Global): Report Size, data= [ 0x10 ] 16
              Item(Global): Report Count, data= [ 0x02 ] 2
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Usage Page, data= [ 0x0d ] 13
                              Digitizer
              Item(Local ): Usage, data= [ 0x42 ] 66
                              Tip Switch
              Item(Local ): Usage, data= [ 0x45 ] 69
                              Eraser
              Item(Local ): Usage, data= [ 0x44 ] 68
                              Barrel Switch
              Item(Local ): Usage, data= [ 0x32 ] 50
                              In Range
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0x01 ] 1
              Item(Global): Report Size, data= [ 0x01 ] 1
              Item(Global): Report Count, data= [ 0x04 ] 4
              Item(Global): Unit, data= [ 0x00 ] 0
                              System: None, Unit: (None)
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Usage Page, data= [ 0x09 ] 9
                              Buttons
              Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                              Button 1 (Primary)
              Item(Local ): Usage Maximum, data= [ 0x04 ] 4
                              Button 4
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0x01 ] 1
              Item(Global): Report Size, data= [ 0x01 ] 1
              Item(Global): Report Count, data= [ 0x04 ] 4
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Usage Page, data= [ 0x0d ] 13
                              Digitizer
              Item(Local ): Usage, data= [ 0x30 ] 48
                              Tip Pressure
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0x00 0x04 ] 1024
              Item(Global): Report Size, data= [ 0x10 ] 16
              Item(Global): Report Count, data= [ 0x01 ] 1
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Usage Page, data= [ 0x0d ] 13
                              Digitizer
              Item(Local ): Usage, data= [ 0x3d ] 61
                              X Tilt
              Item(Local ): Usage, data= [ 0x3e ] 62
                              Y Tilt
              Item(Global): Logical Minimum, data= [ 0x81 ] 129
              Item(Global): Logical Maximum, data= [ 0x7f ] 127
              Item(Global): Report Size, data= [ 0x08 ] 8
              Item(Global): Report Count, data= [ 0x02 ] 2
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Main  ): End Collection, data=none
              Item(Global): Usage Page, data= [ 0x01 ] 1
                              Generic Desktop Controls
              Item(Local ): Usage, data= [ 0x00 ] 0
                              Undefined
              Item(Global): Report ID, data= [ 0x04 ] 4
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
              Item(Global): Report Size, data= [ 0x08 ] 8
              Item(Global): Report Count, data= [ 0x0c ] 12
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Usage Page, data= [ 0x01 ] 1
                              Generic Desktop Controls
              Item(Local ): Usage, data= [ 0x00 ] 0
                              Undefined
              Item(Global): Report ID, data= [ 0x08 ] 8
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
              Item(Global): Report Size, data= [ 0x08 ] 8
              Item(Global): Report Count, data= [ 0x3b ] 59
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Local ): Usage, data= [ 0x01 ] 1
                              Pointer
              Item(Global): Report ID, data= [ 0x80 ] 128
              Item(Global): Report Size, data= [ 0x08 ] 8
              Item(Global): Report Count, data= [ 0x20 ] 32
              Item(Main  ): Feature, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Main  ): End Collection, data=none
              Item(Global): Usage Page, data= [ 0x01 ] 1
                              Generic Desktop Controls
              Item(Local ): Usage, data= [ 0x02 ] 2
                              Mouse
              Item(Main  ): Collection, data= [ 0x01 ] 1
                              Application
              Item(Global): Report ID, data= [ 0x01 ] 1
              Item(Local ): Usage, data= [ 0x01 ] 1
                              Pointer
              Item(Main  ): Collection, data= [ 0x00 ] 0
                              Physical
              Item(Global): Usage Page, data= [ 0x01 ] 1
                              Generic Desktop Controls
              Item(Local ): Usage, data= [ 0x30 ] 48
                              Direction-X
              Item(Local ): Usage, data= [ 0x31 ] 49
                              Direction-Y
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0x80 0x07 ] 1920
              Item(Global): Physical Minimum, data= [ 0x00 ] 0
              Item(Global): Physical Maximum, data= [ 0x00 0x78 ] 30720
              Item(Global): Unit, data= [ 0x11 ] 17
                              System: SI Linear, Unit: Centimeter
              Item(Global): Unit Exponent, data= [ 0x0e ] 14
                              Unit Exponent: 14
              Item(Global): Report Size, data= [ 0x10 ] 16
              Item(Global): Report Count, data= [ 0x02 ] 2
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Usage Page, data= [ 0x09 ] 9
                              Buttons
              Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                              Button 1 (Primary)
              Item(Local ): Usage Maximum, data= [ 0x03 ] 3
                              Button 3 (Tertiary)
              Item(Global): Logical Minimum, data= [ 0x00 ] 0
              Item(Global): Logical Maximum, data= [ 0x01 ] 1
              Item(Global): Report Size, data= [ 0x01 ] 1
              Item(Global): Report Count, data= [ 0x03 ] 3
              Item(Global): Unit, data= [ 0x00 ] 0
                              System: None, Unit: (None)
              Item(Main  ): Input, data= [ 0x02 ] 2
                              Data Variable Absolute No_Wrap Linear
                              Preferred_State No_Null_Position Non_Volatile Bitfield
              Item(Global): Report Count, data= [ 0x05 ] 5
              Item(Main  ): Input, data= [ 0x01 ] 1
                              Constant Array Absolute 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     0x83  EP 3 IN
          bmAttributes            3
            Transfer Type            Interrupt
            Synch Type               None
            Usage Type               Data
          wMaxPacketSize     0x0040  1x 64 bytes
          bInterval               4
      Interface Descriptor:
        bLength                 9
        bDescriptorType         4
        bInterfaceNumber        1
        bAlternateSetting       0
        bNumEndpoints           2
        bInterfaceClass         8 Mass Storage
        bInterfaceSubClass      6 SCSI
        bInterfaceProtocol     80 Bulk-Only
        iInterface              4 USB/MSC Inkling
        Endpoint Descriptor:
          bLength                 7
          bDescriptorType         5
          bEndpointAddress     0x81  EP 1 IN
          bmAttributes            2
            Transfer Type            Bulk
            Synch Type               None
            Usage Type               Data
          wMaxPacketSize     0x0200  1x 512 bytes
          bInterval               0
        Endpoint Descriptor:
          bLength                 7
          bDescriptorType         5
          bEndpointAddress     0x02  EP 2 OUT
          bmAttributes            2
            Transfer Type            Bulk
            Synch Type               None
            Usage Type               Data
          wMaxPacketSize     0x0200  1x 512 bytes
          bInterval               0
  Device Qualifier (for other device speed):
    bLength                10
    bDescriptorType         6
    bcdUSB               2.00
    bDeviceClass            0 (Defined at Interface level)
    bDeviceSubClass         0 
    bDeviceProtocol         0 
    bMaxPacketSize0        64
    bNumConfigurations      2
  Device Status:     0x0000
    (Bus Powered)
  </code></pre>