仅基于DESCRIPTOR HID报告访问USB设备数据

时间:2019-05-26 05:17:24

标签: usb driver reverse-engineering hid usb-hid

我有一个带USB的数字声级计(超声波计)GM1356。在Windows上有一些软件可以处理它,但是我没有CD,并且在Internet上不可用。我要做的是读取有关Linux上当前噪声水平的数据。

我已经找到了一个库,可以使用我所知道的语言(红宝石,libusb)来执行此操作。在下一步中,我安装了Wireshark来检查发送的PC。它不会发送太多。我发现的最有趣的数据包是DESCRIPTOR HID Report。我想知道我应该采取哪些下一步措施来读取对我来说有趣的数据。如何确定我应该发送什么请求才能得到它?

HID Report
    Global item (Usage)
        Header
            .... ..10 = bSize: 2 bytes (2)
            .... 01.. = bType: Global (1)
            0000 .... = bTag: Usage (0x0)
        Usage page: [Vendor-defined] (0xffa0)
    Local item (Usage)
        Header
            .... ..01 = bSize: 1 byte (1)
            .... 10.. = bType: Local (2)
            0000 .... = bTag: Usage (0x0)
        Usage: [Vendor-defined] (0xffa00001)
    Main item (Collection)
        Header
            .... ..01 = bSize: 1 byte (1)
            .... 00.. = bType: Main (0)
            1010 .... = bTag: Collection (0xa)
        Collection type: Application (0x01)
        Local item (Usage)
            Header
                .... ..01 = bSize: 1 byte (1)
                .... 10.. = bType: Local (2)
                0000 .... = bTag: Usage (0x0)
            Usage: [Vendor-defined] (0xffa00002)
        Main item (Collection)
            Header
                .... ..01 = bSize: 1 byte (1)
                .... 00.. = bType: Main (0)
                1010 .... = bTag: Collection (0xa)
            Collection type: Physical (0x00)
            Global item (Usage)
                Header
                    .... ..10 = bSize: 2 bytes (2)
                    .... 01.. = bType: Global (1)
                    0000 .... = bTag: Usage (0x0)
                Usage page: [Vendor-defined] (0xffa1)
            Local item (Usage)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 10.. = bType: Local (2)
                    0000 .... = bTag: Usage (0x0)
                Usage: [Vendor-defined] (0xffa10003)
            Local item (Usage)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 10.. = bType: Local (2)
                    0000 .... = bTag: Usage (0x0)
                Usage: [Vendor-defined] (0xffa10004)
            Global item (Logical minimum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0001 .... = bTag: Logical minimum (0x1)
                Logical minimum: 128
            Global item (Logical maximum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0010 .... = bTag: Logical maximum (0x2)
                Logical maximum: 127
            Global item (Physical minimum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0011 .... = bTag: Physical minimum (0x3)
                Physical minimum: 0
            Global item (Physical maximum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0100 .... = bTag: Physical maximum (0x4)
                Physical maximum: 255
            Global item (Report size)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0111 .... = bTag: Report size (0x7)
                Report size: 8
            Global item (Report count)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    1001 .... = bTag: Report count (0x9)
                Report count: 8
            Main item (Input)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 00.. = bType: Main (0)
                    1000 .... = bTag: Input (0x8)
                .... .... 0 = Data/constant: Data
                .... ...1 . = Data type: Variable
                .... ..0. . = Coordinates: Absolute
                .... .0.. . = Min/max wraparound: No Wrap
                .... 0... . = Physical relationship to data: Linear
                ...0 .... . = Preferred state: Preferred State
                ..0. .... . = Has null position: No Null position
                .0.. .... . = [Reserved]: False
                0... .... . = Bits or bytes: Buffered bytes (default, no second byte present)
            Local item (Usage)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 10.. = bType: Local (2)
                    0000 .... = bTag: Usage (0x0)
                Usage: [Vendor-defined] (0xffa10005)
            Local item (Usage)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 10.. = bType: Local (2)
                    0000 .... = bTag: Usage (0x0)
                Usage: [Vendor-defined] (0xffa10006)
            Global item (Logical minimum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0001 .... = bTag: Logical minimum (0x1)
                Logical minimum: 128
            Global item (Logical maximum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0010 .... = bTag: Logical maximum (0x2)
                Logical maximum: 127
            Global item (Physical minimum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0011 .... = bTag: Physical minimum (0x3)
                Physical minimum: 0
            Global item (Physical maximum)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0100 .... = bTag: Physical maximum (0x4)
                Physical maximum: 255
            Global item (Report size)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    0111 .... = bTag: Report size (0x7)
                Report size: 8
            Global item (Report count)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 01.. = bType: Global (1)
                    1001 .... = bTag: Report count (0x9)
                Report count: 8
            Main item (Output)
                Header
                    .... ..01 = bSize: 1 byte (1)
                    .... 00.. = bType: Main (0)
                    1001 .... = bTag: Output (0x9)
                .... .... 0 = Data/constant: Data
                .... ...1 . = Data type: Variable
                .... ..0. . = Coordinates: Absolute
                .... .0.. . = Min/max wraparound: No Wrap
                .... 0... . = Physical relationship to data: Linear
                ...0 .... . = Preferred state: Preferred State
                ..0. .... . = Has null position: No Null position
                .0.. .... . = (Non)-volatile: Non Volatile
                0... .... . = Bits or bytes: Buffered bytes (default, no second byte present)
            Main item (End collection)
                Header
                    .... ..00 = bSize: 0 bytes (0)
                    .... 00.. = bType: Main (0)
                    1100 .... = bTag: End collection (0xc)
        Main item (End collection)
            Header
                .... ..00 = bSize: 0 bytes (0)
                .... 00.. = bType: Main (0)
                1100 .... = bTag: End collection (0xc)

2 个答案:

答案 0 :(得分:1)

解码HID描述符时,它将显示数据包格式。不幸的是,在这种情况下,用法页面是由供应商定义的,因此无法确切地说出每种用法的解释方式。

我使用hidrdd对其进行了解码(免责声明:我编写了它,但是它是免费的开放源代码,因此没有利益冲突),

//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------

/*
06 A0FF      (GLOBAL) USAGE_PAGE         0xFFA0 Vendor-defined 
09 01        (LOCAL)  USAGE              0xFFA00001 <-- Warning: Undocumented usage (document it by inserting 0001 into file FFA0.conf)
A1 01        (MAIN)   COLLECTION         0x01 Application (Usage=0xFFA00001: Page=Vendor-defined, Usage=, Type=) <-- Error: COLLECTION must be preceded by a known USAGE
09 02          (LOCAL)  USAGE              0xFFA00002 <-- Warning: Undocumented usage (document it by inserting 0002 into file FFA0.conf)
A1 00          (MAIN)   COLLECTION         0x00 Physical (Usage=0xFFA00002: Page=Vendor-defined, Usage=, Type=) <-- Error: COLLECTION must be preceded by a known USAGE
06 A1FF          (GLOBAL) USAGE_PAGE         0xFFA1 Vendor-defined 
09 03            (LOCAL)  USAGE              0xFFA10003 <-- Warning: Undocumented usage (document it by inserting 0003 into file FFA1.conf)
09 04            (LOCAL)  USAGE              0xFFA10004 <-- Warning: Undocumented usage (document it by inserting 0004 into file FFA1.conf)
15 80            (GLOBAL) LOGICAL_MINIMUM    0x80 (-128)  
25 7F            (GLOBAL) LOGICAL_MAXIMUM    0x7F (127)  
35 00            (GLOBAL) PHYSICAL_MINIMUM   0x00 (0)  <-- Info: Consider replacing 35 00 with 34
45 FF            (GLOBAL) PHYSICAL_MAXIMUM   0xFF (-1)  
75 08            (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field  
95 08            (GLOBAL) REPORT_COUNT       0x08 (8) Number of fields  
81 02            (MAIN)   INPUT              0x00000002 (8 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap  <-- Error: PHYSICAL_MAXIMUM (-1) is less than PHYSICAL_MINIMUM (0)
09 05            (LOCAL)  USAGE              0xFFA10005 <-- Warning: Undocumented usage (document it by inserting 0005 into file FFA1.conf)
09 06            (LOCAL)  USAGE              0xFFA10006 <-- Warning: Undocumented usage (document it by inserting 0006 into file FFA1.conf)
15 80            (GLOBAL) LOGICAL_MINIMUM    0x80 (-128) <-- Redundant: LOGICAL_MINIMUM is already -128 
25 7F            (GLOBAL) LOGICAL_MAXIMUM    0x7F (127) <-- Redundant: LOGICAL_MAXIMUM is already 127 
35 00            (GLOBAL) PHYSICAL_MINIMUM   0x00 (0) <-- Redundant: PHYSICAL_MINIMUM is already 0 <-- Info: Consider replacing 35 00 with 34
45 FF            (GLOBAL) PHYSICAL_MAXIMUM   0xFF (-1) <-- Redundant: PHYSICAL_MAXIMUM is already -1 
75 08            (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8 
95 08            (GLOBAL) REPORT_COUNT       0x08 (8) Number of fields <-- Redundant: REPORT_COUNT is already 8 
91 02            (MAIN)   OUTPUT             0x00000002 (8 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap  <-- Error: PHYSICAL_MAXIMUM (-1) is less than PHYSICAL_MINIMUM (0)
C0             (MAIN)   END_COLLECTION     Physical  <-- Warning: Physical units are still in effect PHYSICAL(MIN=0,MAX=-1) UNIT(0x,EXP=0)
C0           (MAIN)   END_COLLECTION     Application  <-- Warning: Physical units are still in effect PHYSICAL(MIN=0,MAX=-1) UNIT(0x,EXP=0)
*/

//--------------------------------------------------------------------------------
// Vendor-defined inputReport (Device --> Host)
//--------------------------------------------------------------------------------

typedef struct
{
                                                     // No REPORT ID byte
                                                     // Collection: CA: CP:
  int8_t   VEN_0003;                                 // Usage 0xFFA10003: , Value = -128 to 127, Physical = (Value + 128) x -1 / 255
  int8_t   VEN_0004[7];                              // Usage 0xFFA10004: , Value = -128 to 127, Physical = (Value + 128) x -1 / 255
} inputReport_t;


//--------------------------------------------------------------------------------
// Vendor-defined outputReport (Device <-- Host)
//--------------------------------------------------------------------------------

typedef struct
{
                                                     // No REPORT ID byte
                                                     // Collection: CA: CP:
  int8_t   VEN_0005;                                 // Usage 0xFFA10005: , Value = -128 to 127, Physical = (Value + 128) x -1 / 255
  int8_t   VEN_0006[7];                              // Usage 0xFFA10006: , Value = -128 to 127, Physical = (Value + 128) x -1 / 255
} outputReport_t;

如您所见,上面的HID描述符存在一些问题(例如,物理最大值45 FF为-1,但我认为它们的意思是255-应该表示为46 FF 00),但问题仍然在于它告诉我们您对用法的含义一无所知。顺便说一句,即使Wireshark也没有正确报告逻辑最小值:15 80是-128而不是128。

我们所能知道的是报告的长度为8个字节,而第一个字节似乎是某种ID(好吧,它的用法与其余7个字节不同)。

只有供应商的驱动程序知道如何解释报告,但是在受控条件下获得足够数量的Wireshark数据包捕获后,您便可以对工程解释进行反向工程。

对不起,但这是我能做到的最好的事情。

答案 1 :(得分:0)

我也买了分贝计,它恰好与您的型号兼容。我目前正在尝试将此代码移植到bash脚本:https://github.com/dobra-noc/gm1356,该代码对于我的设备(对btw甚至不是gm1356)也很适合我,并且我猜想它也对您有用。 >