Custom HID Gamepad works on Windows, has some inverted buttons in Linux - usb

I've designed a custom gamepad using an STM32. It has four analog axes, and 22 buttons. I have written firmware for it, including the USB Descriptor (that took a few tries).
It works exactly as expected on Windows, but on Linux (Raspbian specifically) the last 5 buttons are inverted ("on" by default, "off" when pressed)
It is critical to my product that it work on both platforms (Mac too, but I don't have one to test right now)
Any ideas why this would be, and what to do about it?
Here's the output of lsusb -v for this device:
Bus 001 Device 003: ID 0483:5750 STMicroelectronics
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x5750
bcdDevice 2.00
iManufacturer 1 STMicroelectronics
iProduct 2 STM32 Custom Human interface
iSerial 3 74E79C303734
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0029
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 53
Report Descriptor: (length is 53)
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x05 ] 5
Gamepad
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Local ): Usage, data= [ 0x01 ] 1
Pointer
Item(Main ): Collection, data= [ 0x00 ] 0
Physical
Item(Local ): Usage, data= [ 0x30 ] 48
Direction-X
Item(Local ): Usage, data= [ 0x31 ] 49
Direction-Y
Item(Local ): Usage, data= [ 0x32 ] 50
Direction-Z
Item(Local ): Usage, data= [ 0x33 ] 51
Rotate-X
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x0f ] 4095
Item(Global): Report Size, data= [ 0x10 ] 16
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(Main ): End Collection, data=none
Item(Global): Usage Page, data= [ 0x09 ] 9
Buttons
Item(Local ): Usage Minimum, data= [ 0x01 ] 1
Button 1 (Primary)
Item(Local ): Usage Maximum, data= [ 0x16 ] 22
(null)
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= [ 0x16 ] 22
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x02 ] 2
Item(Main ): Input, data= [ 0x03 ] 3
Constant Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
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 0x0002 1x 2 bytes
bInterval 10
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0002 1x 2 bytes
bInterval 10
Device Status: 0x0001
Self Powered
I also just noticed that the stick positions are different (again, correct on Windows, and wrong on Linux.)
I did read something about Linux having a kernel driver that does something to these values? jstest-gtk lets me control some aspects of the axes (scaling, dead zones, inversion) maybe that's a clue?

Related

Increasing the volume of an HID device using feature reports

What hex code do I need to send to the device (and what report index) to trigger a volume change?
I'm trying to use HID feature reports to increase the volume of a Jabra 410 headset. The Jabra provides the following interface and report description:
https://pastebin.com/ES8ivMym
Report Descriptor: (length is 273)
Item(Global): Usage Page, data= [ 0x0c ] 12
Consumer
Item(Local ): Usage, data= [ 0x01 ] 1
Consumer Control
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x01 ] 1
Item(Global): Usage Page, data= [ 0x0c ] 12
Consumer
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0xea ] 234
Volume Decrement
Item(Local ): Usage, data= [ 0xe9 ] 233
Volume Increment
Item(Local ): Usage, data= [ 0xe2 ] 226
Mute
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x03 ] 3
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x01 ] 1
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(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x02 ] 2
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
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= [ 0x20 ] 32
Item(Main ): Output, data= [ 0x02 0x01 ] 258
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Buffered Bytes
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
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= [ 0x20 ] 32
Item(Main ): Input, data= [ 0x02 0x01 ] 258
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Buffered Bytes
Item(Global): Report ID, data= [ 0x04 ] 4
Item(Global): Usage Page, data= [ 0x30 0xff ] 65328
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0x20 ] 32
(null)
Item(Local ): Usage, data= [ 0x97 ] 151
(null)
Item(Local ): Usage, data= [ 0x2b ] 43
(null)
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x03 ] 3
Item(Main ): Input, data= [ 0x23 ] 35
Constant Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Local ): Usage, data= [ 0x2f ] 47
(null)
Item(Local ): Usage, data= [ 0x21 ] 33
(null)
Item(Local ): Usage, data= [ 0x24 ] 36
(null)
Item(Local ): Usage, data= [ 0xfd 0xff ] 65533
(null)
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x04 ] 4
Item(Main ): Input, data= [ 0x07 ] 7
Constant Variable Relative No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x09 ] 9
Item(Main ): Input, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Local ): Usage, data= [ 0xff 0xff ] 65535
(null)
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Main ): Feature, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x07 ] 7
Item(Main ): Feature, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Usage Page, data= [ 0x40 0xff ] 65344
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0x17 ] 23
(null)
Item(Local ): Usage, data= [ 0x1e ] 30
(null)
Item(Local ): Usage, data= [ 0x09 ] 9
(null)
Item(Local ): Usage, data= [ 0x18 ] 24
(null)
Item(Local ): Usage, data= [ 0x20 ] 32
(null)
Item(Local ): Usage, data= [ 0x21 ] 33
(null)
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x06 ] 6
Item(Main ): Output, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Usage Page, data= [ 0x30 0xff ] 65328
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0x9e ] 158
(null)
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Main ): Output, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x09 ] 9
Item(Main ): Output, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Item(Global): Usage Page, data= [ 0x0b ] 11
Telephony
Item(Local ): Usage, data= [ 0x05 ] 5
Headset
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x03 ] 3
Item(Global): Usage Page, data= [ 0x0b ] 11
Telephony
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0x20 ] 32
Hook Switch
Item(Local ): Usage, data= [ 0x97 ] 151
Line Busy Tone
Item(Local ): Usage, data= [ 0x2b ] 43
Speaker Phone
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x03 ] 3
Item(Main ): Input, data= [ 0x23 ] 35
Constant Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Local ): Usage, data= [ 0x2f ] 47
Phone Mute
Item(Local ): Usage, data= [ 0x21 ] 33
Flash
Item(Local ): Usage, data= [ 0x24 ] 36
Redial
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x03 ] 3
Item(Main ): Input, data= [ 0x07 ] 7
Constant Variable Relative No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Local ): Usage, data= [ 0x07 ] 7
Programmable Button
Item(Global): Usage Page, data= [ 0x09 ] 9
Buttons
Item(Local ): Usage, data= [ 0x01 ] 1
Button 1 (Primary)
Item(Global): Report Size, data= [ 0x01 ] 1
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): Report Count, data= [ 0x09 ] 9
Item(Main ): Input, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Usage Page, data= [ 0x08 ] 8
LEDs
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0x17 ] 23
Off-Hook
Item(Local ): Usage, data= [ 0x1e ] 30
Speaker
Item(Local ): Usage, data= [ 0x09 ] 9
Mute
Item(Local ): Usage, data= [ 0x18 ] 24
Ring
Item(Local ): Usage, data= [ 0x20 ] 32
Hold
Item(Local ): Usage, data= [ 0x21 ] 33
Microphone
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x06 ] 6
Item(Main ): Output, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Usage Page, data= [ 0x0b ] 11
Telephony
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Local ): Usage, data= [ 0x9e ] 158
(null)
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Main ): Output, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x09 ] 9
Item(Main ): Output, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
I have successfully used feature report #3 to interact with the device, including the manipulation of some LEDs and call states. However, no combination of data changes the volume, and I get no response whatsoever when interacting with feature report #1, which should be responsible for volume if I'm reading the report properly.
For example, sending a hex value of 05 (as in 00000101) to page #3 results in the device going to a muted state.
I decoded the report descriptor and it appears that the volume increment/decrement reports are sent from the device (headset) to the host (PC or whatever) using an input report, not a feature report. That is, the device tells the host to increment/decrement the volume - not the other way around.
BTW, I only see one feature report defined and it uses REPORT_ID 0x04.
Specifically, the input report with REPORT_ID 0x01 is used for volume control:
//--------------------------------------------------------------------------------
// Consumer Device Page inputReport 01 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
// Collection: ConsumerControl
uint8_t CD_ConsumerControlVolumeDecrement : 1; // Usage 0x000C00EA: Volume Decrement, Value = 0 to 1
uint8_t CD_ConsumerControlVolumeIncrement : 1; // Usage 0x000C00E9: Volume Increment, Value = 0 to 1
uint8_t CD_ConsumerControlMute : 1; // Usage 0x000C00E2: Mute, Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} inputReport01_t;
The full decoded report descriptor is shown below...
hidrdd git:master ❯ rexx rd.rex --dump -dsa samples/headset-jabra410.rd
//--------------------------------------------------------------------------------
// Report descriptor data in hex (length 273 bytes)
//--------------------------------------------------------------------------------
// 050C0901 A1018501 050C1500 250109EA 09E909E2 75019503 81027501 95058101
// C00600FF 0901A101 85020901 150026FF 00750895 20920201 09011500 26FF0075
// 08952082 02018504 0630FF15 00250109 20099709 2B750195 03812309 2F092109
// 240AFDFF 75019504 81077501 95098101 0AFFFF75 019501B1 22750195 07B10106
// 40FF1500 25010917 091E0909 09180920 09217501 95069122 0630FF15 00250109
// 9E750195 01912275 01950991 01C0050B 0905A101 8503050B 15002501 09200997
// 092B7501 95038123 092F0921 09247501 95038107 09070509 09017501 95018102
// 95098101 05081500 25010917 091E0909 09180920 09217501 95069122 050B1500
// 2501099E 75019501 91227501 95099101 C0
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 0C (GLOBAL) USAGE_PAGE 0x000C Consumer Device Page
09 01 (LOCAL) USAGE 0x000C0001 Consumer Control (CA=Application Collection)
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0x000C0001: Page=Consumer Device Page, Usage=Consumer Control, Type=CA)
85 01 (GLOBAL) REPORT_ID 0x01 (1)
05 0C (GLOBAL) USAGE_PAGE 0x000C Consumer Device Page <-- Redundant: USAGE_PAGE is already 0x000C
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
09 EA (LOCAL) USAGE 0x000C00EA Volume Decrement (RTC=Re-trigger Control)
09 E9 (LOCAL) USAGE 0x000C00E9 Volume Increment (RTC=Re-trigger Control)
09 E2 (LOCAL) USAGE 0x000C00E2 Mute (OOC=On/Off Control)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
95 03 (GLOBAL) REPORT_COUNT 0x03 (3) Number of fields
81 02 (MAIN) INPUT 0x00000002 (3 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 05 (GLOBAL) REPORT_COUNT 0x05 (5) Number of fields
81 01 (MAIN) INPUT 0x00000001 (5 fields x 1 bit) 1=Constant 0=Array 0=Absolute
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Consumer Device Page inputReport 01 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
// Collection: ConsumerControl
uint8_t CD_ConsumerControlVolumeDecrement : 1; // Usage 0x000C00EA: Volume Decrement, Value = 0 to 1
uint8_t CD_ConsumerControlVolumeIncrement : 1; // Usage 0x000C00E9: Volume Increment, Value = 0 to 1
uint8_t CD_ConsumerControlMute : 1; // Usage 0x000C00E2: Mute, Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} inputReport01_t;
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
06 00FF (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
09 01 (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0xFF000001: Page=Vendor-defined, Usage=, Type=)
85 02 (GLOBAL) REPORT_ID 0x02 (2)
09 01 (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
95 20 (GLOBAL) REPORT_COUNT 0x20 (32) Number of fields
92 0201 (MAIN) OUTPUT 0x00000102 (32 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 1=Buffer
09 01 (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255) <-- Redundant: LOGICAL_MAXIMUM is already 255
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
95 20 (GLOBAL) REPORT_COUNT 0x20 (32) Number of fields <-- Redundant: REPORT_COUNT is already 32
82 0201 (MAIN) INPUT 0x00000102 (32 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 1=Buffer
85 04 (GLOBAL) REPORT_ID 0x04 (4)
06 30FF (GLOBAL) USAGE_PAGE 0xFF30 Vendor-defined
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
09 20 (LOCAL) USAGE 0xFF300020 <-- Warning: Undocumented usage
09 97 (LOCAL) USAGE 0xFF300097 <-- Warning: Undocumented usage
09 2B (LOCAL) USAGE 0xFF30002B <-- Warning: Undocumented usage
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
95 03 (GLOBAL) REPORT_COUNT 0x03 (3) Number of fields
81 23 (MAIN) INPUT 0x00000023 (3 fields x 1 bit) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 2F (LOCAL) USAGE 0xFF30002F <-- Warning: Undocumented usage
09 21 (LOCAL) USAGE 0xFF300021 <-- Warning: Undocumented usage
09 24 (LOCAL) USAGE 0xFF300024 <-- Warning: Undocumented usage
0A FDFF (LOCAL) USAGE 0xFF30FFFD <-- Warning: Undocumented usage
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 07 (MAIN) INPUT 0x00000007 (4 fields x 1 bit) 1=Constant 1=Variable 1=Relative 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 09 (GLOBAL) REPORT_COUNT 0x09 (9) Number of fields
81 01 (MAIN) INPUT 0x00000001 (9 fields x 1 bit) 1=Constant 0=Array 0=Absolute
0A FFFF (LOCAL) USAGE 0xFF30FFFF <-- Warning: Undocumented usage
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
B1 22 (MAIN) FEATURE 0x00000022 (1 field x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 07 (GLOBAL) REPORT_COUNT 0x07 (7) Number of fields
B1 01 (MAIN) FEATURE 0x00000001 (7 fields x 1 bit) 1=Constant 0=Array 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
06 40FF (GLOBAL) USAGE_PAGE 0xFF40 Vendor-defined
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1) <-- Redundant: LOGICAL_MAXIMUM is already 1
09 17 (LOCAL) USAGE 0xFF400017 <-- Warning: Undocumented usage
09 1E (LOCAL) USAGE 0xFF40001E <-- Warning: Undocumented usage
09 09 (LOCAL) USAGE 0xFF400009 <-- Warning: Undocumented usage
09 18 (LOCAL) USAGE 0xFF400018 <-- Warning: Undocumented usage
09 20 (LOCAL) USAGE 0xFF400020 <-- Warning: Undocumented usage
09 21 (LOCAL) USAGE 0xFF400021 <-- Warning: Undocumented usage
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 06 (GLOBAL) REPORT_COUNT 0x06 (6) Number of fields
91 22 (MAIN) OUTPUT 0x00000022 (6 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
06 30FF (GLOBAL) USAGE_PAGE 0xFF30 Vendor-defined
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1) <-- Redundant: LOGICAL_MAXIMUM is already 1
09 9E (LOCAL) USAGE 0xFF30009E <-- Warning: Undocumented usage
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
91 22 (MAIN) OUTPUT 0x00000022 (1 field x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 09 (GLOBAL) REPORT_COUNT 0x09 (9) Number of fields
91 01 (MAIN) OUTPUT 0x00000001 (9 fields x 1 bit) 1=Constant 0=Array 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Vendor-defined featureReport 04 (Device <-> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x04 (4)
uint8_t VEN_VendorDefinedFFFF : 1; // Usage 0xFF30FFFF: , Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} featureReport04_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 02 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
uint8_t VEN_VendorDefined0001[32]; // Usage 0xFF000001: , Value = 0 to 255
} inputReport02_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 04 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x04 (4)
uint8_t VEN_VendorDefined0020 : 1; // Usage 0xFF300020: , Value = 0 to 1
uint8_t VEN_VendorDefined0097 : 1; // Usage 0xFF300097: , Value = 0 to 1
uint8_t VEN_VendorDefined002B : 1; // Usage 0xFF30002B: , Value = 0 to 1
uint8_t VEN_VendorDefined002F : 1; // Usage 0xFF30002F: , Value = 0 to 1
uint8_t VEN_VendorDefined0021 : 1; // Usage 0xFF300021: , Value = 0 to 1
uint8_t VEN_VendorDefined0024 : 1; // Usage 0xFF300024: , Value = 0 to 1
uint8_t VEN_VendorDefinedFFFD : 1; // Usage 0xFF30FFFD: , Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} inputReport04_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 02 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
uint8_t VEN_VendorDefined0001[32]; // Usage 0xFF000001: , Value = 0 to 255
} outputReport02_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 04 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x04 (4)
uint8_t VEN_VendorDefined0017 : 1; // Usage 0xFF400017: , Value = 0 to 1
uint8_t VEN_VendorDefined001E : 1; // Usage 0xFF40001E: , Value = 0 to 1
uint8_t VEN_VendorDefined0009 : 1; // Usage 0xFF400009: , Value = 0 to 1
uint8_t VEN_VendorDefined0018 : 1; // Usage 0xFF400018: , Value = 0 to 1
uint8_t VEN_VendorDefined0020 : 1; // Usage 0xFF400020: , Value = 0 to 1
uint8_t VEN_VendorDefined0021 : 1; // Usage 0xFF400021: , Value = 0 to 1
uint8_t VEN_VendorDefined009E : 1; // Usage 0xFF30009E: , Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} outputReport04_t;
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 0B (GLOBAL) USAGE_PAGE 0x000B Telephony Device Page
09 05 (LOCAL) USAGE 0x000B0005 Headset (CL=Logical Collection)
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0x000B0005: Page=Telephony Device Page, Usage=Headset, Type=CL) <-- Warning: USAGE type should be CA (Application)
85 03 (GLOBAL) REPORT_ID 0x03 (3)
05 0B (GLOBAL) USAGE_PAGE 0x000B Telephony Device Page <-- Redundant: USAGE_PAGE is already 0x000B
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1) <-- Redundant: LOGICAL_MAXIMUM is already 1
09 20 (LOCAL) USAGE 0x000B0020 Hook Switch (OOC=On/Off Control)
09 97 (LOCAL) USAGE 0x000B0097 Line Busy Tone (MC=Momentary Control)
09 2B (LOCAL) USAGE 0x000B002B Speaker Phone (OOC=On/Off Control)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 03 (GLOBAL) REPORT_COUNT 0x03 (3) Number of fields
81 23 (MAIN) INPUT 0x00000023 (3 fields x 1 bit) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 2F (LOCAL) USAGE 0x000B002F Phone Mute (OOC=On/Off Control)
09 21 (LOCAL) USAGE 0x000B0021 Flash (MC=Momentary Control)
09 24 (LOCAL) USAGE 0x000B0024 Redial (OSC=One Shot Control)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 03 (GLOBAL) REPORT_COUNT 0x03 (3) Number of fields <-- Redundant: REPORT_COUNT is already 3
81 07 (MAIN) INPUT 0x00000007 (3 fields x 1 bit) 1=Constant 1=Variable 1=Relative 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 07 (LOCAL) USAGE 0x000B0007 Programmable Button (NAry=Named Array)
05 09 (GLOBAL) USAGE_PAGE 0x0009 Button Page
09 01 (LOCAL) USAGE 0x00090001 Button 1 Primary/trigger (MULTI=Selector, On/Off, Momentary, or One Shot)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
81 02 (MAIN) INPUT 0x00000002 (1 field x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 09 (GLOBAL) REPORT_COUNT 0x09 (9) Number of fields
81 01 (MAIN) INPUT 0x00000001 (9 fields x 1 bit) 1=Constant 0=Array 0=Absolute
05 08 (GLOBAL) USAGE_PAGE 0x0008 LED Indicator Page
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1) <-- Redundant: LOGICAL_MAXIMUM is already 1
09 17 (LOCAL) USAGE 0x00080017 Off-Hook (OOC=On/Off Control)
09 1E (LOCAL) USAGE 0x0008001E Speaker (OOC=On/Off Control)
09 09 (LOCAL) USAGE 0x00080009 Mute (OOC=On/Off Control)
09 18 (LOCAL) USAGE 0x00080018 Ring (OOC=On/Off Control)
09 20 (LOCAL) USAGE 0x00080020 Hold (OOC=On/Off Control)
09 21 (LOCAL) USAGE 0x00080021 Microphone (OOC=On/Off Control)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 06 (GLOBAL) REPORT_COUNT 0x06 (6) Number of fields
91 22 (MAIN) OUTPUT 0x00000022 (6 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 0B (GLOBAL) USAGE_PAGE 0x000B Telephony Device Page
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1) <-- Redundant: LOGICAL_MAXIMUM is already 1
09 9E (LOCAL) USAGE 0x000B009E Ringer (OOC=On/Off Control)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
91 22 (MAIN) OUTPUT 0x00000022 (1 field x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1
95 09 (GLOBAL) REPORT_COUNT 0x09 (9) Number of fields
91 01 (MAIN) OUTPUT 0x00000001 (9 fields x 1 bit) 1=Constant 0=Array 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Telephony Device Page inputReport 03 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x03 (3)
// Collection: Headset
uint8_t TEL_HeadsetHookSwitch : 1; // Usage 0x000B0020: Hook Switch, Value = 0 to 1
uint8_t TEL_HeadsetLineBusyTone : 1; // Usage 0x000B0097: Line Busy Tone, Value = 0 to 1
uint8_t TEL_HeadsetSpeakerPhone : 1; // Usage 0x000B002B: Speaker Phone, Value = 0 to 1
uint8_t TEL_HeadsetPhoneMute : 1; // Usage 0x000B002F: Phone Mute, Value = 0 to 1
uint8_t TEL_HeadsetFlash : 1; // Usage 0x000B0021: Flash, Value = 0 to 1
uint8_t TEL_HeadsetRedial : 1; // Usage 0x000B0024: Redial, Value = 0 to 1
uint8_t TEL_HeadsetProgrammableButton : 1; // Usage 0x000B0007: Programmable Button, Value = 0 to 1
// Usage 0x00090001 Button 1 Primary/trigger (MULTI=Selector, On/Off, Momentary, or One Shot) Value = 0 to 1 <-- Ignored: REPORT_COUNT (1) is too small
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} inputReport03_t;
//--------------------------------------------------------------------------------
// LED Indicator Page outputReport 03 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x03 (3)
// Collection: Headset
uint8_t LED_HeadsetOffHook : 1; // Usage 0x00080017: Off-Hook, Value = 0 to 1
uint8_t LED_HeadsetSpeaker : 1; // Usage 0x0008001E: Speaker, Value = 0 to 1
uint8_t LED_HeadsetMute : 1; // Usage 0x00080009: Mute, Value = 0 to 1
uint8_t LED_HeadsetRing : 1; // Usage 0x00080018: Ring, Value = 0 to 1
uint8_t LED_HeadsetHold : 1; // Usage 0x00080020: Hold, Value = 0 to 1
uint8_t LED_HeadsetMicrophone : 1; // Usage 0x00080021: Microphone, Value = 0 to 1
uint8_t TEL_HeadsetRinger : 1; // Usage 0x000B009E: Ringer, Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
uint8_t : 1; // Pad
} outputReport03_t;

Custom HID device HID report descriptor report count

I simply want to send from device to host with two report ID.These reports must have different Report Count(First report id has 4 report count, second report id has 40).This is what I have done so far:
//14 bytes
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
// -------- common global items ---------
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
// 10 bytes | Input message 1 (sent from device to host)
0x85, 5, // Global Report ID (cannot be 0)
0x95, 4, // Global Report Count (number of Report Size fields)
0x19, 0x01, // USAGE_MINIMUM (Vendor Usage 1)
0x29, 5, // USAGE_MAXIMUM (Vendor Usage 64)
0x81, 0x02, // Main Input (data, array, absolute)
// 10 bytes | Input message 1 (sent from device to host)
0x85, 6, // Global Report ID (cannot be 0)
0x95, 40, // Global Report Count (number of Report Size fields)
0x19, 0x01, // USAGE_MINIMUM (Vendor Usage 1)
0x29, 41, // USAGE_MAXIMUM (Vendor Usage 64)
0x81, 0x02, // Main Input (data, array, absolute)
0xC0
But first report id is sending 40 bayt.Where is my mistake?
HID Terminal output:
R 02 0C 16 20 2A 34 3E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 01 0B 15 1F 29 34 3E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
I believe #Nipo has given you the correct answer: the report descriptor indicates what each report should look like, but it is still the responsibility of your code to send reports with the correct length specified.
For report id 5 that would be 5 (1 for the report id + 4 for the payload), and
for report it 6 it would be 41 (1 for the report id + 40 for the payload).
BTW, your report descriptor may need a little tweaking. As it stands, it decodes as:
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
PROGMEM char usbHidReportDescriptor[] =
{
0x06, 0x00, 0xFF, // (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
0x09, 0x01, // (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
0xA1, 0x01, // (MAIN) COLLECTION 0x00000001 Application (Usage=0xFF000001: Page=Vendor-defined, Usage=, Type=)
0x15, 0x00, // (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
0x26, 0xFF, 0x00, // (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
0x75, 0x08, // (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
0x85, 0x05, // (GLOBAL) REPORT_ID 0x05 (5)
0x95, 0x04, // (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
0x19, 0x01, // (LOCAL) USAGE_MINIMUM 0xFF000001 <-- Warning: Undocumented usage
0x29, 0x05, // (LOCAL) USAGE_MAXIMUM 0xFF000005 <-- Warning: Undocumented usage
0x81, 0x02, // (MAIN) INPUT 0x00000002 (4 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
0x85, 0x06, // (GLOBAL) REPORT_ID 0x06 (6)
0x95, 0x28, // (GLOBAL) REPORT_COUNT 0x28 (40) Number of fields
0x19, 0x01, // (LOCAL) USAGE_MINIMUM 0xFF000001 <-- Warning: Undocumented usage
0x29, 0x29, // (LOCAL) USAGE_MAXIMUM 0xFF000029 <-- Warning: Undocumented usage
0x81, 0x02, // (MAIN) INPUT 0x00000002 (40 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
0xC0, // (MAIN) END_COLLECTION Application
};
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 05 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x05 (5)
uint8_t VEN_VendorDefined0001; // Usage 0xFF000001: , Value = 0 to 255
uint8_t VEN_VendorDefined0002; // Usage 0xFF000002: , Value = 0 to 255
uint8_t VEN_VendorDefined0003; // Usage 0xFF000003: , Value = 0 to 255
uint8_t VEN_VendorDefined0004; // Usage 0xFF000004: , Value = 0 to 255
// Usage 0xFF000005 Value = 0 to 255 <-- Ignored: REPORT_COUNT (4) is too small
} inputReport05_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 06 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x06 (6)
uint8_t VEN_VendorDefined0001; // Usage 0xFF000001: , Value = 0 to 255
uint8_t VEN_VendorDefined0002; // Usage 0xFF000002: , Value = 0 to 255
uint8_t VEN_VendorDefined0003; // Usage 0xFF000003: , Value = 0 to 255
uint8_t VEN_VendorDefined0004; // Usage 0xFF000004: , Value = 0 to 255
uint8_t VEN_VendorDefined0005; // Usage 0xFF000005: , Value = 0 to 255
uint8_t VEN_VendorDefined0006; // Usage 0xFF000006: , Value = 0 to 255
uint8_t VEN_VendorDefined0007; // Usage 0xFF000007: , Value = 0 to 255
uint8_t VEN_VendorDefined0008; // Usage 0xFF000008: , Value = 0 to 255
uint8_t VEN_VendorDefined0009; // Usage 0xFF000009: , Value = 0 to 255
uint8_t VEN_VendorDefined000A; // Usage 0xFF00000A: , Value = 0 to 255
uint8_t VEN_VendorDefined000B; // Usage 0xFF00000B: , Value = 0 to 255
uint8_t VEN_VendorDefined000C; // Usage 0xFF00000C: , Value = 0 to 255
uint8_t VEN_VendorDefined000D; // Usage 0xFF00000D: , Value = 0 to 255
uint8_t VEN_VendorDefined000E; // Usage 0xFF00000E: , Value = 0 to 255
uint8_t VEN_VendorDefined000F; // Usage 0xFF00000F: , Value = 0 to 255
uint8_t VEN_VendorDefined0010; // Usage 0xFF000010: , Value = 0 to 255
uint8_t VEN_VendorDefined0011; // Usage 0xFF000011: , Value = 0 to 255
uint8_t VEN_VendorDefined0012; // Usage 0xFF000012: , Value = 0 to 255
uint8_t VEN_VendorDefined0013; // Usage 0xFF000013: , Value = 0 to 255
uint8_t VEN_VendorDefined0014; // Usage 0xFF000014: , Value = 0 to 255
uint8_t VEN_VendorDefined0015; // Usage 0xFF000015: , Value = 0 to 255
uint8_t VEN_VendorDefined0016; // Usage 0xFF000016: , Value = 0 to 255
uint8_t VEN_VendorDefined0017; // Usage 0xFF000017: , Value = 0 to 255
uint8_t VEN_VendorDefined0018; // Usage 0xFF000018: , Value = 0 to 255
uint8_t VEN_VendorDefined0019; // Usage 0xFF000019: , Value = 0 to 255
uint8_t VEN_VendorDefined001A; // Usage 0xFF00001A: , Value = 0 to 255
uint8_t VEN_VendorDefined001B; // Usage 0xFF00001B: , Value = 0 to 255
uint8_t VEN_VendorDefined001C; // Usage 0xFF00001C: , Value = 0 to 255
uint8_t VEN_VendorDefined001D; // Usage 0xFF00001D: , Value = 0 to 255
uint8_t VEN_VendorDefined001E; // Usage 0xFF00001E: , Value = 0 to 255
uint8_t VEN_VendorDefined001F; // Usage 0xFF00001F: , Value = 0 to 255
uint8_t VEN_VendorDefined0020; // Usage 0xFF000020: , Value = 0 to 255
uint8_t VEN_VendorDefined0021; // Usage 0xFF000021: , Value = 0 to 255
uint8_t VEN_VendorDefined0022; // Usage 0xFF000022: , Value = 0 to 255
uint8_t VEN_VendorDefined0023; // Usage 0xFF000023: , Value = 0 to 255
uint8_t VEN_VendorDefined0024; // Usage 0xFF000024: , Value = 0 to 255
uint8_t VEN_VendorDefined0025; // Usage 0xFF000025: , Value = 0 to 255
uint8_t VEN_VendorDefined0026; // Usage 0xFF000026: , Value = 0 to 255
uint8_t VEN_VendorDefined0027; // Usage 0xFF000027: , Value = 0 to 255
uint8_t VEN_VendorDefined0028; // Usage 0xFF000028: , Value = 0 to 255
// Usage 0xFF000029 Value = 0 to 255 <-- Ignored: REPORT_COUNT (40) is too small
} inputReport06_t;
You may want to try the following instead:
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
PROGMEM char usbHidReportDescriptor[] =
{
0x06, 0x00, 0xFF, // (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
0x09, 0x01, // (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
0xA1, 0x01, // (MAIN) COLLECTION 0x00000001 Application (Usage=0xFF000001: Page=Vendor-defined, Usage=, Type=)
0x15, 0x00, // (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
0x26, 0xFF, 0x00, // (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
0x75, 0x08, // (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
0x85, 0x05, // (GLOBAL) REPORT_ID 0x05 (5)
0x95, 0x04, // (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
0x19, 0x01, // (LOCAL) USAGE_MINIMUM 0xFF000001 <-- Warning: Undocumented usage
0x29, 0x04, // (LOCAL) USAGE_MAXIMUM 0xFF000004 <-- Warning: Undocumented usage
0x81, 0x00, // (MAIN) INPUT 0x00000000 (4 fields x 8 bits) 0=Data 0=Array 0=Absolute 0=Ignored 0=Ignored 0=PrefState 0=NoNull
0x85, 0x06, // (GLOBAL) REPORT_ID 0x06 (6)
0x95, 0x28, // (GLOBAL) REPORT_COUNT 0x28 (40) Number of fields
0x19, 0x01, // (LOCAL) USAGE_MINIMUM 0xFF000001 <-- Warning: Undocumented usage
0x29, 0x28, // (LOCAL) USAGE_MAXIMUM 0xFF000028 <-- Warning: Undocumented usage
0x81, 0x00, // (MAIN) INPUT 0x00000000 (40 fields x 8 bits) 0=Data 0=Array 0=Absolute 0=Ignored 0=Ignored 0=PrefState 0=NoNull
0xC0, // (MAIN) END_COLLECTION Application
};
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 05 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x05 (5)
uint8_t VEN_VendorDefined[4]; // Value = 0 to 255
} inputReport05_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 06 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x06 (6)
uint8_t VEN_VendorDefined[40]; // Value = 0 to 255
} inputReport06_t;

Reverse-engineering a HID handshake by examining bytes over USB

I'm trying to extract real-time data from a Wacom Inkling
Roel Janssen has already examined the packets 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);
I'm trying to rewrite this code using HID API which has a very minimal API (here)
I'm going to attempt to just use hid_write for now, but there is maybe a chance this handshake is sending a feature report...?
Is there anyone out there who can look at that bytestream and see what is going on?
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?
EDIT: I have it working! Both hid_write and hid_send_feature_report work!
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);
... However I would still like to understand what is going on. This is rather hacky.
EDIT: Output of lsusb (from Roel, I don't have Linux to 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)
1) Verify that the Inkling uses HID USB device class. Try lsusb -v and check the bDeviceClass or bInterfaceClass field in the output (The USB human interface device class can be used to describe both device and interface classes. The interface class is used when a USB device can contain more than one function. from https://en.wikipedia.org/wiki/USB_human_interface_device_class) In the manual (https://www.wacom.com/~/media/files/store-manuals/inkling-manual-english.pdf) is said that it is a USB flash drive, in this case it uses USB mass storage device class (BULK transfer)
2) If it is a USB HID device class you can try to get the feature reports (if the inkling sends any) similar to this website http://libusb.6.n5.nabble.com/How-to-get-HID-report-td4628.html
libusb_get_descriptor makes standard GET_DESCRIPTOR requests, where the
bmRequestType field is 0x80. The DT_REPORT descriptor request must
indicate that the recipient is an interface, which requires
bmRequestType to be 0x81.
You have two good choices. The report descriptors are all included in
the configuration descriptor, so you should be able to fetch the whole
configuration descriptor en masse and parse it to extract the report
descriptors.
Alternatively, libusb_get_descriptor is a very thin layer over
libusb_control_transfer , so you could just expand it by hand:
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);
more links:
- http://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/
http://www.beyondlogic.org/usbnutshell/usb1.shtml
---------------------------------------------------------------------------------
libusb_control_transfer performs USB control transfers. Control transfers are used for command and status operations, see this http://libusb.sourceforge.net/api-1.0/group__syncio.html and this http://www.beyondlogic.org/usbnutshell/usb4.shtml#Control
USB control requests are a subtype of USB requests, see http://www.beyondlogic.org/usbnutshell/usb6.shtml
usb_data seems to be the USB send buffer, it is always filled with the data bytes, then the libusb_control_transfer is send
This is the commented form of the USB control request (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
This is the short form of the USB control request
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 the byte sequences like "\x80\x01\x03\x01\x02\x00\x00\x00" are commands codes that are used to configure the Inkling ('handshake') and only the Inkling and the Wacom folks understand...
So this is one single report you send over USB:
80 01 03 01 02 00 00 00 .... (in total the buffer is 1+32 = 33 bytes)
^^ Report ID
This is the relevant part from the 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
This says that your data for Report ID 0x80 has to be interpreted as 32 times one byte (it's meaning is up to the driver I guess). It is a Feature which means that it can configure the device via GET_FEATURE/SET_FEATURE reports over the control endpoint.
For more information about how to interpret this descriptor, see the HID v1.1 specification from http://www.usb.org/developers/hidpage/.

Openstack VM instance SHUTOFF after few minute

For learning purpose i have build openstack on VirtualBox with 2 vCPU and 4GB Memory. It installed successfully and i am able to start VM instances but what happened is guest VM got SHUTOFF status after few minutes. I have google this issue but didn't get proper answer. I have check logs and i didn't find anything suspicious.
How do i check VM console so i can see what is going on there?
Where should i check SHUTOFF specific error logs, i meant in which file?
EDIT:
Following is output of nova console-log but it stuck there not going ahead and i can't see login screen too
openstack#openstack1:~$ nova console-log 970a3722-0fb3-4db6-862b-2aa626cc68a8
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Linux version 3.0.0-12-virtual (buildd#crested) (gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) ) #20-Ubuntu SMP Fri Oct 7 18:19:02 UTC 2011 (Ubuntu 3.0.0-12.20-virtual 3.0.4)
[ 0.000000] Command line: LABEL=cirros-rootfs ro console=tty0 console=ttyS0 console=hvc0
[ 0.000000] KERNEL supported cpus:
[ 0.000000] Intel GenuineIntel
[ 0.000000] AMD AuthenticAMD
[ 0.000000] Centaur CentaurHauls
[ 0.000000] BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: 0000000000000000 - 000000000009dc00 (usable)
[ 0.000000] BIOS-e820: 000000000009dc00 - 00000000000a0000 (reserved)
[ 0.000000] BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved)
[ 0.000000] BIOS-e820: 0000000000100000 - 000000001fffd000 (usable)
[ 0.000000] BIOS-e820: 000000001fffd000 - 0000000020000000 (reserved)
[ 0.000000] BIOS-e820: 00000000fffc0000 - 0000000100000000 (reserved)
[ 0.000000] NX (Execute Disable) protection: active
[ 0.000000] DMI 2.4 present.
[ 0.000000] No AGP bridge found
[ 0.000000] last_pfn = 0x1fffd max_arch_pfn = 0x400000000
[ 0.000000] x86 PAT enabled: cpu 0, old 0x7040600070406, new 0x7010600070106
[ 0.000000] found SMP MP-table at [ffff8800000fdaf0] fdaf0
[ 0.000000] init_memory_mapping: 0000000000000000-000000001fffd000
[ 0.000000] RAMDISK: 1fdf9000 - 1ffed000
[ 0.000000] ACPI: RSDP 00000000000fd990 00014 (v00 BOCHS )
[ 0.000000] ACPI: RSDT 000000001fffd7b0 00034 (v01 BOCHS BXPCRSDT 00000001 BXPC 00000001)
[ 0.000000] ACPI: FACP 000000001fffff80 00074 (v01 BOCHS BXPCFACP 00000001 BXPC 00000001)
[ 0.000000] ACPI: DSDT 000000001fffd9b0 02589 (v01 BXPC BXDSDT 00000001 INTL 20100528)
[ 0.000000] ACPI: FACS 000000001fffff40 00040
[ 0.000000] ACPI: SSDT 000000001fffd910 0009E (v01 BOCHS BXPCSSDT 00000001 BXPC 00000001)
[ 0.000000] ACPI: APIC 000000001fffd830 00072 (v01 BOCHS BXPCAPIC 00000001 BXPC 00000001)
[ 0.000000] ACPI: HPET 000000001fffd7f0 00038 (v01 BOCHS BXPCHPET 00000001 BXPC 00000001)
[ 0.000000] No NUMA configuration found
[ 0.000000] Faking a node at 0000000000000000-000000001fffd000
[ 0.000000] Initmem setup node 0 0000000000000000-000000001fffd000
[ 0.000000] NODE_DATA [000000001fff5000 - 000000001fff9fff]
[ 0.000000] Zone PFN ranges:
[ 0.000000] DMA 0x00000010 -> 0x00001000
[ 0.000000] DMA32 0x00001000 -> 0x00100000
[ 0.000000] Normal empty
[ 0.000000] Movable zone start PFN for each node
[ 0.000000] early_node_map[2] active PFN ranges
[ 0.000000] 0: 0x00000010 -> 0x0000009d
[ 0.000000] 0: 0x00000100 -> 0x0001fffd
[ 0.000000] ACPI: PM-Timer IO Port: 0xb008
[ 0.000000] ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
[ 0.000000] ACPI: IOAPIC (id[0x01] address[0xfec00000] gsi_base[0])
[ 0.000000] IOAPIC[0]: apic_id 1, version 17, address 0xfec00000, GSI 0-23
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level)
[ 0.000000] Using ACPI (MADT) for SMP configuration information
[ 0.000000] ACPI: HPET id: 0x8086a201 base: 0xfed00000
[ 0.000000] SMP: Allowing 1 CPUs, 0 hotplug CPUs
[ 0.000000] PM: Registered nosave memory: 000000000009d000 - 000000000009e000
[ 0.000000] PM: Registered nosave memory: 000000000009e000 - 00000000000a0000
[ 0.000000] PM: Registered nosave memory: 00000000000a0000 - 00000000000f0000
[ 0.000000] PM: Registered nosave memory: 00000000000f0000 - 0000000000100000
[ 0.000000] Allocating PCI resources starting at 20000000 (gap: 20000000:dffc0000)
[ 0.000000] Booting paravirtualized kernel on bare hardware
[ 0.000000] setup_percpu: NR_CPUS:64 nr_cpumask_bits:64 nr_cpu_ids:1 nr_node_ids:1
[ 0.000000] PERCPU: Embedded 27 pages/cpu #ffff88001fa00000 s79296 r8192 d23104 u2097152
[ 0.000000] Built 1 zonelists in Node order, mobility grouping on. Total pages: 129157
[ 0.000000] Policy zone: DMA32
[ 0.000000] Kernel command line: LABEL=cirros-rootfs ro console=tty0 console=ttyS0 console=hvc0
[ 0.000000] PID hash table entries: 2048 (order: 2, 16384 bytes)
[ 0.000000] Checking aperture...
[ 0.000000] No AGP bridge found
[ 0.000000] Memory: 497852k/524276k available (6206k kernel code, 460k absent, 25964k reserved, 6907k data, 900k init)
[ 0.000000] SLUB: Genslabs=15, HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] Hierarchical RCU implementation.
[ 0.000000] RCU dyntick-idle grace-period acceleration is enabled.
[ 0.000000] NR_IRQS:4352 nr_irqs:256 16
[ 0.000000] Console: colour VGA+ 80x25
[ 0.000000] console [tty0] enabled
[ 0.000000] console [ttyS0] enabled
[ 0.000000] allocated 4194304 bytes of page_cgroup
[ 0.000000] please try 'cgroup_disable=memory' option if you don't want memory cgroups
[ 0.000000] Fast TSC calibration failed
[ 0.000000] TSC: Unable to calibrate against PIT
[ 0.000000] TSC: using PMTIMER reference calibration
[ 0.000000] Detected 2486.018 MHz processor.
[ 0.024490] Calibrating delay loop (skipped), value calculated using timer frequency.. 4972.03 BogoMIPS (lpj=9944072)
[ 0.025939] pid_max: default: 32768 minimum: 301
[ 0.029903] Security Framework initialized
[ 0.033041] AppArmor: AppArmor initialized
[ 0.033539] Yama: becoming mindful.
[ 0.037514] Dentry cache hash table entries: 65536 (order: 7, 524288 bytes)
[ 0.039560] Inode-cache hash table entries: 32768 (order: 6, 262144 bytes)
[ 0.040693] Mount-cache hash table entries: 256
[ 0.054301] Initializing cgroup subsys cpuacct
[ 0.054957] Initializing cgroup subsys memory
[ 0.056108] Initializing cgroup subsys devices
[ 0.056838] Initializing cgroup subsys freezer
[ 0.057341] Initializing cgroup subsys net_cls
[ 0.057824] Initializing cgroup subsys blkio
[ 0.058338] Initializing cgroup subsys perf_event
[ 0.060182] mce: CPU supports 10 MCE banks
[ 0.062116] SMP alternatives: switching to UP code
[ 0.236105] Freeing SMP alternatives: 24k freed
[ 0.237129] ACPI: Core revision 20110413
[ 0.270578] ftrace: allocating 26075 entries in 103 pages
[ 0.289821] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[ 0.332667] CPU0: AMD QEMU Virtual CPU version 1.0 stepping 03
[ 0.336020] APIC calibration not consistent with PM-Timer: 103ms instead of 100ms
[ 0.336020] APIC delta adjusted to PM-Timer: 6249961 (6456813)
[ 0.336020] Performance Events: Broken PMU hardware detected, using software events only.
[ 0.341160] Brought up 1 CPUs
[ 0.341596] Total of 1 processors activated (4972.03 BogoMIPS).
[ 0.348508] devtmpfs: initialized
[ 0.370265] print_constraints: dummy:
[ 0.370818] Time: 22:32:35 Date: 07/31/13
[ 0.373184] NET: Registered protocol family 16
[ 0.377862] ACPI: bus type pci registered
[ 0.379805] PCI: Using configuration type 1 for base access
[ 0.394436] bio: create slab <bio-0> at 0
[ 0.441293] ACPI: Interpreter enabled
[ 0.441749] ACPI: (supports S0 S3 S4 S5)
[ 0.442853] ACPI: Using IOAPIC for interrupt routing
[ 0.504949] ACPI: No dock devices found.
[ 0.505458] HEST: Table not found.
[ 0.505922] PCI: Ignoring host bridge windows from ACPI; if necessary, use "pci=use_crs" and report a bug
[ 0.508456] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[ 0.514427] pci 0000:00:01.3: quirk: [io 0xb000-0xb03f] claimed by PIIX4 ACPI
[ 0.515222] pci 0000:00:01.3: quirk: [io 0xb100-0xb10f] claimed by PIIX4 SMB
[ 0.526520] pci0000:00: Unable to request _OSC control (_OSC support mask: 0x1e)
[ 0.612644] ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11)
[ 0.614063] ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11)
[ 0.615312] ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11)
[ 0.616918] ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11)
[ 0.618197] ACPI: PCI Interrupt Link [LNKS] (IRQs 9) *0
[ 0.622888] vgaarb: device added: PCI:0000:00:02.0,decodes=io+mem,owns=io+mem,locks=none
[ 0.623734] vgaarb: loaded
[ 0.624235] vgaarb: bridge control possible 0000:00:02.0
[ 0.627513] SCSI subsystem initialized
[ 0.629754] usbcore: registered new interface driver usbfs
[ 0.630590] usbcore: registered new interface driver hub
[ 0.632126] usbcore: registered new device driver usb
[ 0.634610] PCI: Using ACPI for IRQ routing
[ 0.640771] NetLabel: Initializing
[ 0.641144] NetLabel: domain hash size = 128
[ 0.641570] NetLabel: protocols = UNLABELED CIPSOv4
[ 0.642769] NetLabel: unlabeled traffic allowed by default
[ 0.744929] AppArmor: AppArmor Filesystem Enabled
[ 0.746522] pnp: PnP ACPI init
[ 0.748377] ACPI: bus type pnp registered
[ 0.761838] pnp: PnP ACPI: found 8 devices
[ 0.762440] ACPI: ACPI bus type pnp unregistered
[ 0.791325] Switching to clocksource acpi_pm
[ 0.791325] NET: Registered protocol family 2
[ 0.792984] Switched to NOHz mode on CPU #0
[ 0.794980] IP route cache hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.800380] TCP established hash table entries: 16384 (order: 6, 262144 bytes)
[ 0.802008] TCP bind hash table entries: 16384 (order: 6, 262144 bytes)
[ 0.803089] TCP: Hash tables configured (established 16384 bind 16384)
[ 0.803751] TCP reno registered
[ 0.804373] UDP hash table entries: 256 (order: 1, 8192 bytes)
[ 0.805192] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
[ 0.806852] NET: Registered protocol family 1
[ 0.807530] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
[ 0.808586] pci 0000:00:01.0: PIIX3: Enabling Passive Release
[ 0.809327] pci 0000:00:01.0: Activating ISA DMA hang workarounds
[ 0.816560] audit: initializing netlink socket (disabled)
[ 0.817591] type=2000 audit(1375309954.816:1): initialized
[ 0.903327] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[ 0.928384] VFS: Disk quotas dquot_6.5.2
[ 0.929484] Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 0.938210] fuse init (API version 7.16)
[ 0.940982] msgmni has been set to 972
[ 0.949280] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[ 0.950562] io scheduler noop registered
[ 0.951008] io scheduler deadline registered (default)
[ 0.951941] io scheduler cfq registered
[ 0.955245] pci_hotplug: PCI Hot Plug PCI Core version: 0.5
[ 0.956970] pciehp: PCI Express Hot Plug Controller Driver version: 0.4
[ 0.960881] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
[ 0.962211] ACPI: Power Button [PWRF]
[ 0.979110] ERST: Table is not found!
[ 0.982891] ACPI: PCI Interrupt Link [LNKC] enabled at IRQ 11
[ 0.983651] virtio-pci 0000:00:03.0: PCI INT A -> Link[LNKC] -> GSI 11 (level, high) -> IRQ 11
[ 0.986746] ACPI: PCI Interrupt Link [LNKD] enabled at IRQ 10
[ 0.987395] virtio-pci 0000:00:04.0: PCI INT A -> Link[LNKD] -> GSI 10 (level, high) -> IRQ 10
[ 0.993533] Trying to unpack rootfs image as initramfs...
[ 1.017633] ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 10
[ 1.018210] virtio-pci 0000:00:05.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, high) -> IRQ 10
[ 1.020389] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
[ 1.052583] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 1.082516] serial8250: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
[ 1.165489] 00:05: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 1.244653] 00:06: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
[ 1.248018] hpet_acpi_add: no address or irqs in _CRS
[ 1.249922] Linux agpgart interface v0.103
[ 1.279474] brd: module loaded
[ 1.287981] loop: module loaded
[ 1.597690] vda: vda1
[ 1.624125] Freeing initrd memory: 2000k freed
[ 1.626790] scsi0 : ata_piix
[ 1.629007] scsi1 : ata_piix
[ 1.629910] ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc0a0 irq 14
[ 1.630652] ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc0a8 irq 15
[ 1.636489] Fixed MDIO Bus: probed
[ 1.637469] PPP generic driver version 2.4.2
[ 1.638209] tun: Universal TUN/TAP device driver, 1.6
[ 1.638756] tun: (C) 1999-2004 Max Krasnyansky <maxk#qualcomm.com>
openstack#openstack1:~$
You can get guest console on the dashboard or with this command:
nova get-vnc-console <instance id> novnc
If your guest image redirects console messages (like the ubuntu cloud image), you can see boot messages on dashboard or with the command:
nova console-log <instance id>
You may get clues in /var/log/nova/nova-compute.log and in your hypervisor logs (/var/log/libvirt/libvirtd.log for QEMU/KVM).
A possible cause is that your guest can't boot on its primary disk and get stuck on boot sequence. Try other images, like the ones proposed in OpenStack documentation.

How to set the UsbInterface (isochronous) manually for a USB device (Kinect) [duplicate]

I try to run the Asus xtion on a ARM Board (Pandaboard) and I already installed and used the samples (e.g NiSimpleRead) provided by openni. To get these samples running on this Platform it needed some tweaks, one of them is to set the UsbInterface manually to isochronous (in the GlobalDefaults.ini). But after that everything runs smoothly
Now I want to use PCL (which is based on openni) to grab some frames but PCL doesn't work. I believe that pcl tries to set the USB-Interface on its own (it probably uses XnUSBLinux.cpp to be generic) and tries to bypass the GlobalDefaults.ini, respectively does not use my manually set USB-Interface.
My question is if I can set the option for the USB-Interface to isochronous globaly for a device? or how I could change the XnUSBLinux.cpp to make it run.
This is the output from lsusb -v (reduced to the asus device part) and shows the two operation option (bulk and isochronous)
Bus 001 Device 006: ID 1d27:0600
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1d27
idProduct 0x0600
bcdDevice 0.01
iManufacturer 2 PrimeSense
iProduct 1 PrimeSense Device
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 69
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0b70 2x 880 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x135c 3x 860 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x1040 3x 64 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 1
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
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 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 1
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 1
Device Status: 0x0000
(Bus Powered)
Would be great to get your help on how to set one option manually.