Reputation: 9
I'm using a stm32f103 board to simulate multi-touch hid device. currently the board is recognized as touch screen device correctly, however, touch action is not executed at the host when touch event is sent. (it works with 1 finger before adding the contract id to support multi-touch)
This is bushound snapshot the 0x40..
IN data is response to tell 2 fingers touch is supported:
the partial report descriptor:
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x04, // 报告ID (4)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x42, // USAGE (Tip Switch)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x32, // Usage (In Range)
0x09, 0x47, // Usage (Confidence)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x42, // USAGE (Tip Switch)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x32, // Usage (In Range)
0x09, 0x47, // Usage (Confidence)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual count)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x0D, // Usage Page (Digitizer)
0x85, 0x02, // Report ID (2)
0x09, 0x55, // Usage (0x55)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
The event data structure:
The last 2 lines of bushound above is stm 32 sent touch event data.
Not sure if I'm missing something.
Upvotes: 0
Views: 39
Reputation: 1720
I processed your HID report descriptor with the free hidrdd report descriptor decoder and it showed a few errors - the main one being that 16-bit fields need to be aligned on a 16-bit boundary so you need add some padding bytes. I've marked all the things I have changed to fix it with "TODO:" in the following:
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x04, // REPORT ID (4)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x02, // COLLECTION (Logical) TODO: Change to logical from physical
0x09, 0x42, // USAGE (Tip Switch)
0x15, 0x00, // LOGICAL_MINIMUM (0) TODO: Insert
0x25, 0x01, // LOGICAL_MAXIMUM (1) TODO: Insert
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x32, // Usage (In Range)
0x09, 0x47, // Usage (Confidence)
// 0x75, 0x01, // REPORT_SIZE (1) TODO: Remove (already 1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x75, 0x08, // ReportSize(8) TODO: Insert (8 bits of padding)
0x81, 0x03, // Input (Const) TODO: Insert (padding)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
// 0x15, 0x00, // LOGICAL_MINIMUM (0) TODO: Remove (already 0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
// 0x35, 0x00, // PHYSICAL_MINIMUM (0) TODO: Remove (not needed - no physical units)
// 0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095) TODO: Remove (not needed - no physcal units)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x02, // COLLECTION (Logical) TODO: Change to logical from physical
0x09, 0x42, // USAGE (Tip Switch)
0x25, 0x01, // LOGICAL_MAXIMUM (1) TODO: Insert
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x32, // Usage (In Range)
0x09, 0x47, // Usage (Confidence)
// 0x75, 0x01, // REPORT_SIZE (1) TODO: Remove (already 1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x75, 0x08, // ReportSize(8) TODO: Insert (8 bits of padding)
0x81, 0x03, // Input (Const) TODO: Insert (padding)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
// 0x15, 0x00, // LOGICAL_MINIMUM (0) TODO: Remove (already 0)
// 0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095) TODO: Remove (already 4095)
//0x35, 0x00, // PHYSICAL_MINIMUM (0) TODO: Remove (not needed - no physical units)
//0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095) TODO: Remove (not needed - no physical units)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual count)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 0x05, 0x0D, // Usage Page (Digitizer) TODO: Remove (already on Digitizer page)
0x85, 0x02, // Report ID (2)
0x09, 0x55, // Usage (0x55)
// 0x95, 0x01, // REPORT_COUNT (1) TODO: Remove (already 1)
// 0x75, 0x08, // REPORT_SIZE (8) TODO: Remove (already 8)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xc0, // END_COLLECTION TODO: Insert (terminates application collection)
Running hidrdd against the fixed report descriptor reports no errors now - but whether it actually works is another thing:
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 0D (GLOBAL) USAGE_PAGE 0x000D Digitizer Page
09 04 (LOCAL) USAGE 0x000D0004 Touch Screen (Application Collection)
A1 01 (MAIN) COLLECTION 0x01 Application (Usage=0x000D0004: Page=Digitizer Page, Usage=Touch Screen, Type=Application Collection)
85 04 (GLOBAL) REPORT_ID 0x04 (4)
09 22 (LOCAL) USAGE 0x000D0022 Finger (Logical Collection)
A1 02 (MAIN) COLLECTION 0x02 Logical (Usage=0x000D0022: Page=Digitizer Page, Usage=Finger, Type=Logical Collection)
09 42 (LOCAL) USAGE 0x000D0042 Tip Switch (Momentary Control)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
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
09 32 (LOCAL) USAGE 0x000D0032 In Range (Momentary Control)
09 47 (LOCAL) USAGE 0x000D0047 Touch Valid (Momentary Control)
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 02 (MAIN) INPUT 0x00000002 (2 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 51 (LOCAL) USAGE 0x000D0051 Contact Identifier (Dynamic Value)
75 05 (GLOBAL) REPORT_SIZE 0x05 (5) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
81 02 (MAIN) INPUT 0x00000002 (1 field x 5 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
81 03 (MAIN) INPUT 0x00000003 (1 field x 8 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 30 (LOCAL) USAGE 0x00010030 X (Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (Dynamic Value)
26 FF0F (GLOBAL) LOGICAL_MAXIMUM 0x0FFF (4095)
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 02 (MAIN) INPUT 0x00000002 (2 fields x 16 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Logical
05 0D (GLOBAL) USAGE_PAGE 0x000D Digitizer Page
09 22 (LOCAL) USAGE 0x000D0022 Finger (Logical Collection)
A1 02 (MAIN) COLLECTION 0x02 Logical (Usage=0x000D0022: Page=Digitizer Page, Usage=Finger, Type=Logical Collection)
09 42 (LOCAL) USAGE 0x000D0042 Tip Switch (Momentary Control)
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
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
09 32 (LOCAL) USAGE 0x000D0032 In Range (Momentary Control)
09 47 (LOCAL) USAGE 0x000D0047 Touch Valid (Momentary Control)
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 02 (MAIN) INPUT 0x00000002 (2 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 51 (LOCAL) USAGE 0x000D0051 Contact Identifier (Dynamic Value)
75 05 (GLOBAL) REPORT_SIZE 0x05 (5) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
81 02 (MAIN) INPUT 0x00000002 (1 field x 5 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
81 03 (MAIN) INPUT 0x00000003 (1 field x 8 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 30 (LOCAL) USAGE 0x00010030 X (Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (Dynamic Value)
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 02 (MAIN) INPUT 0x00000002 (2 fields x 16 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Logical
05 0D (GLOBAL) USAGE_PAGE 0x000D Digitizer Page
09 54 (LOCAL) USAGE 0x000D0054 Contact Count (Dynamic Value)
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
85 02 (GLOBAL) REPORT_ID 0x02 (2)
09 55 (LOCAL) USAGE 0x000D0055 Contact Count Maximum (Static Value)
B1 02 (MAIN) FEATURE 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
// All structure fields should be byte-aligned...
#pragma pack(push,1)
//--------------------------------------------------------------------------------
// Digitizer Page featureReport 02 (Device <-> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
// Collection: CA:TouchScreen
uint8_t DIG_TouchScreenContactCountMaximum; // Usage 0x000D0055: Contact Count Maximum, Value = 0 to 1
} featureReport02_t;
//--------------------------------------------------------------------------------
// Digitizer Page inputReport 04 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x04 (4)
// Collection: CA:TouchScreen CL:Finger
uint8_t DIG_TouchScreenFingerTipSwitch : 1; // Usage 0x000D0042: Tip Switch, Value = 0 to 1
uint8_t DIG_TouchScreenFingerInRange : 1; // Usage 0x000D0032: In Range, Value = 0 to 1
uint8_t DIG_TouchScreenFingerTouchValid : 1; // Usage 0x000D0047: Touch Valid, Value = 0 to 1
uint8_t DIG_TouchScreenFingerContactIdentifier : 5; // Usage 0x000D0051: Contact Identifier, Value = 0 to 1
uint8_t pad_4; // Pad
uint16_t GD_TouchScreenFingerX; // Usage 0x00010030: X, Value = 0 to 4095
uint16_t GD_TouchScreenFingerY; // Usage 0x00010031: Y, Value = 0 to 4095
uint8_t DIG_TouchScreenFingerTipSwitch_1 : 1; // Usage 0x000D0042: Tip Switch, Value = 0 to 1
uint8_t DIG_TouchScreenFingerInRange_1 : 1; // Usage 0x000D0032: In Range, Value = 0 to 1
uint8_t DIG_TouchScreenFingerTouchValid_1 : 1; // Usage 0x000D0047: Touch Valid, Value = 0 to 1
uint8_t DIG_TouchScreenFingerContactIdentifier_1 : 5; // Usage 0x000D0051: Contact Identifier, Value = 0 to 1
uint8_t pad_9; // Pad
uint16_t GD_TouchScreenFingerX_1; // Usage 0x00010030: X, Value = 0 to 1
uint16_t GD_TouchScreenFingerY_1; // Usage 0x00010031: Y, Value = 0 to 1
// Collection: CA:TouchScreen
uint8_t DIG_TouchScreenContactCount; // Usage 0x000D0054: Contact Count, Value = 0 to 1
} inputReport04_t;
#pragma pack(pop)
Upvotes: 1