2016-05-11 33 views
2

Prüfung Ich versuche, von einem Wacom Inklingdurch eine HID-Handshake Reverse-Engineering-Bytes über USB

Roel Janssen Echtzeitdaten zu extrahieren hat bereits untersucht die Pakete here:

// Some kind of handshaking. 
// Values obtained by sniffing the USB connection between SketchManager and the device. 
unsigned char usb_data[33]; 
memset (&usb_data, '\0', 33); 
int bytes = 0; 

memcpy (&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 (&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 (&usb_data, '\0', 33); 
bytes += libusb_control_transfer (handle, 0xa1, 1, 0x0380, 0, usb_data, 33, 0); 

memcpy (&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 (&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 (&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 (&usb_data, '\0', 33); 
bytes += libusb_control_transfer (handle, 0xa1, 1, 0x0380, 0, usb_data, 33, 0); 

Ich bin versuchen, diesen Code mit HID API neu zu schreiben, die eine sehr minimalen API (here)

nur

ich werde versuchen muss hid_write jetzt verwenden, aber es ist vielleicht eine Chance dieser handsh ake sendet eine feature report ...?

Gibt es jemanden da draußen, der den Bytestrom betrachten kann und sieht, was vor sich geht?

EDIT: Es scheint, dass das Inkling eine FlashDrive und HID-Schnittstelle exponiert, so dass ich denke, dass dieser Bytecode die HID-Schnittstelle auswählen muss und es mit dem Senden von Daten zu sagen. Aber kann ich es in einer eleganteren/menschlicheren Form kodieren?

EDIT: Ich habe es funktioniert! Sowohl hid_write als auch hid_send_feature_report funktionieren!

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

... Allerdings würde ich immer noch gerne verstehen, was vor sich geht. Das ist ziemlich hacky.

EDIT: Ausgabe von lsusb (von Roel, ich habe keine Linux zur Hand):

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) 

Antwort

2

1) Stellen Sie sicher, dass die Inkling HID USB-Geräte-Klasse verwendet. Versuchen Sie lsusb -v und überprüfen Sie die bDeviceClass oder bInterfaceClass Feld in der Ausgabe (Die USB-Human-Interface-Geräteklasse kann verwendet werden, um Geräte-und Interface-Klassen zu beschreiben. Die Interface-Klasse wird verwendet, wenn ein USB-Gerät mehr als eine Funktion enthalten kann. von https://en.wikipedia.org/wiki/USB_human_interface_device_class) In der Bedienungsanleitung (https://www.wacom.com/~/media/files/store-manuals/inkling-manual-english.pdf) wird gesagt, dass es ein USB-Flash-Laufwerk ist, in diesem Fall verwendet es USB-Massenspeichergerät Klasse (BULK-Transfer)

2) Wenn es eine USB HID-Geräteklasse ist, können Sie versuchen, zu bekommen die Funktion berichtet (wenn die Ahnung etwas sendet) ähnlich wie diese Website http://libusb.6.n5.nabble.com/How-to-get-HID-report-td4628.html

libusb_get_descriptormacht Standard GET_DESCRIPTOR Anfragen, wo das bmRequestTypeFeld ist 0x80. Der DT_REPORT Descriptor Antrag muss zeigen an, dass der Empfänger eine Schnittstelle, die bmRequestTypeerfordert 0x81 zu sein.

Sie haben zwei gute Möglichkeiten. Die Berichtsdeskriptoren sind alle im Konfigurationsdeskriptor enthalten. Sie sollten daher den gesamten Konfigurationsdeskriptor in Massen abrufen und analysieren können, um den Bericht Deskriptoren zu extrahieren.

Alternativlibusb_get_descriptorist eine sehr dünne Schicht über libusb_control_transfer, so konnte man es nur von Hand erweitern:

res = libusb_control_transfer(devh, LIBUSB_ENDPOINT_IN | 
LIBUSB_RECIPIENT_INTERFACE, 
LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8) | 0, 0, buf, 
sizeof(buf), 1000); 

weitere Links: - http://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/ http://www.beyondlogic.org/usbnutshell/usb1.shtml

---------------------------------------------------------------------------------

libusb_control_transfer führt USB-Steuerelement überträgt. Die Steuerung geht für Befehls- und Statusoperationen verwendet finden diese http://libusb.sourceforge.net/api-1.0/group__syncio.html und diese http://www.beyondlogic.org/usbnutshell/usb4.shtml#Control

USB Steuerungsanforderungen sind ein Subtyp von USB fordert finden http://www.beyondlogic.org/usbnutshell/usb6.shtml

usb_data scheint die USB zu sein Sendepuffer, es wird immer mit den Datenbytes gefüllt, dann wird die libusb_control_transfer gesendet

Dies ist die kommentierten Form der USB-Steueranforderung (http://www.beyondlogic.org/usbnutshell/usb6.shtml)

memcpy (&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 

Dies ist die Kurzform der USB-Steueranforderung

memcpy (&usb_data, "\x80\x01\x0a\x01\x01\x0b\x01\x00", 8); 
bytes += libusb_control_transfer (handle, 0x21, 9, 0x0380, 0, usb_data, 33, 0); 

So all Byte-Sequenzen wie "\x80\x01\x03\x01\x02\x00\x00\x00" sind Befehle Codes, die sind verwendet, um die Inkling ("Handshake") zu konfigurieren und nur die Inkling und die Wacom Völker verstehen ...

+0

Danke dafür, während ich die Informationen hier verdauen, habe ich meine Frage hauptsächlich aktualisiert, um zu bestätigen, was Sie bezüglich lsusb gesagt haben. –

+0

aktualisierte Antwort ... –

1

Also das ist eine einzige berichten Sie über USB senden:

80 01 03 01 02 00 00 00 .... (in total the buffer is 1+32 = 33 bytes) 
^^      Report ID 

Dies ist der relevante Teil aus dem HID-Descriptor:

... 
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 

Diese besagt, dass Ihre Daten für die Report-ID 0x80 als 32-mal ein Byte interpretiert werden muss (es ist Bedeutung ist Sache des Fahrers, denke ich). Es ist ein Feature, das bedeutet, dass es das Gerät über GET_FEATURE/SET_FEATURE Berichte über den Kontrollendpunkt konfigurieren kann. Weitere Informationen zum Interpretieren dieses Deskriptors finden Sie in der HID 1.1-Spezifikation von http://www.usb.org/developers/hidpage/.