
请教各位大佬,我最近使用F405芯片,用stm32CubeMX默认创建了一个USBHID的例程,这个例程默认就是一个HID模拟鼠标移动的程序,我创建之后也是可以正常枚举并且鼠标正常移动的,说明生成的工程是没有问题的,然后我把报告描述符修改成了一个多点触摸的描述符,这个描述符是以前项目使用的,是没有问题的。变量也没有改变,只是把报告描述符的内容替换了,如下图:4 G$ D1 O9 }0 ]![]() 这个报告描述符字节比较大,又474个字节,然后我又把相应的配置描述符修改了,如下图所示:) I& i1 Z- |3 b, V5 J3 X 把配置描述符集合里HID描述符中描述报告描述符大小的字节改成我们修改后的大小,如下图 ![]() 按道理,将这些修改之后,就相当于重新约定了HID上报数据的协议,随后,我又按照新规定的报告描述符的协议模拟上报触控点的数据。 通过Bus hound显示枚举是成功的,也一直在按照报告描述符规定的协议向主机发送数据,但是没有模拟触控的现象,我使用以前的工程是有明显 的触控屏幕的现象的。通过设备管理器查看设备是正常运行的,然后用Bus hound观察枚举过程,发现一直在上报数据,但是在枚举过程中在主机! M* Z. g& F6 a6 [, a 发送GET_REPORT之后出现了USTS c0000004 stall pid 错误,出现之后枚举也没有停止,而是正常运行的,数据也是正常上报的, 但就是没有现象,我感觉是主机没有接收到报告描述符,或者接收错误了,导致虽然数据是正常上报的,但是系统不知道上报的数据的含义,: [" Q( j( F6 ^ C( N8 e 有没有大佬懂得这方面的错误,还请指导一下,工程其他地方都没有动,就是修改了配置、报告描述符等信息。& X5 q4 f- ^6 y/ G ![]() ![]() : B' i* c# H6 c( b |
最全USB HID开发资料,悉心整理一个月,亲自测试
实战经验 | 选择USBX模块生成USB CDC ACM无PD的项目
STM32 USB HID键盘例程
刘氓兔的杂谈【001】-片上USB 高速PHY
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
【源码】STLINK-V3MINI 高速USB仿真器,成功改刷【高速CMSIS-DAP】
在线直播|无需编写任何代码即可在STM32上实现USB-C Power Delivery
STM32 USB CDC 虚拟多串口
圈圈发布USB图书第二版有感,以及分享一些我学习USB过程...
USB Audio设计与实现
{& V; [9 A6 |9 ]8 X0 q! s
//Below is the report descriptor for an example multi-touch device, which can support ! {5 X( \! h. J0 j/ O0 X* \, I
//up to 5 simultaneous contacts. This report descriptor also supports multiple device modes.) [9 ~* {8 ~, `) g5 M1 d$ A0 ?
//The OS may select the device mode (ex: mouse, single-touch digitizer, multi-touch digitizer)
//by sending a SET_REPORT (feature) control transfer. In each mode, the device firmware- M& R& b& d% }
//should behave differently and send input packets on the HID IN endpoint, formatted1 v. V/ L* q ]+ D' A
//based on the report descriptor collections associated with that mode.) V0 g9 H' U0 b B
//Each IN packet (HID report) sent to the host (in multi-touch digitizer mode) is ?? bytes long (Bytes 0-13).
//The data is sent in little endian format. To send the report to the host, verify / Z+ z% f, ^8 O+ ^& }6 n' f1 h# \" v k
//that the HID IN endpoint buffer is not already busy, then place the data in the HID 4 ^+ V# ]8 [) I) A; W. z9 h
//IN endpoint buffer SRAM, and then call the UsbSendEP5Report() function. The data will 7 {/ r5 Y0 `2 h) }* Y; H2 f
//then get sent to the host, at the next opportunity when the host polls that endpoint
//(by sending an IN token packet to the endpoint).. q& f e4 Y) q
//NOTE (Contact identifier number): For a multi-touch device, the firmware needs to * E2 h4 i) D( P- Q
//keep track of each contact point separately and independantly. For example, suppose 1 T3 E$ x9 Z# W9 Z# W- L& u
//a human first presses one finger to the screen. The firmware would detect this, and
//it should arbitrarily assign a contact identifier number for this contact. Typically
//it would be assigned something like contact ID = "1". As the human moves their finger
//around on the contact surface the firmware will report new X and Y coordinate ' v- v4 W$ B+ U( H
//information for this contact, but the contact ID byte should always be = "1" for
//this contact.
//! v4 P, J- D. c( ]
//Now suppose the human places a second finger onto the touch surface, so there are
//two simultanous contacts. The firmware should assign this second contact a new " c! O2 ?: J3 B7 k8 a2 @
//contact ID, for instance, contact ID = "2". So long as the first contact is still) M- v L% K% I. ~7 h7 s
//valid, the firmware needs to continue reporting ID = "1" for the first contact.
//The firmware will continue to report information using these contact ID numbers s2 F9 S( `" ?+ E' v f
//until such time as a contact becomes invalid (human removes their finger from the
//screen).- S2 ^, b! Y( P
, F/ x: r, b* j* K
( k! l2 z9 s* |* W/ a( O" I M9 y
//Top level collection for use in Multi-Touch Digitizer device mode.# F9 u# q8 m- C* ~
//-------------------------------------------------------------------: [; y0 ?6 B: R% @8 L. q q
//Format for multi-touch digitizer input reports Using this report descriptor:3 p4 J, q. `! H: i3 N
//Byte[0] = Report ID == MULTI_TOUCH_DATA_REPORT_ID0 H) e" Q3 f' b, C9 f8 k
//1st contact point info in bytes 1-6.
//Byte[1] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch
//Byte[2] = Contact identifier number (see note above): Q7 H" e6 K* ^) I o5 {
//Byte[3] = X-coordinate LSB
//Byte[4] = X-coordinate MSB
//Byte[5] = Y-coordinate LSB4 Y# w* ~ f0 U
//Byte[6] = Y-coordinate MSB
( I1 y& z" G3 [4 ]2 c( E- l
//2nd contact point info in bytes 7-12
//Byte[7] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch
//Byte[8] = Contact identifier number (see note above)
//Byte[9] = X-coordinate LSB
//Byte[10]= X-coordinate MSB
//Byte[11]= Y-coordinate LSB( f4 N4 @* ?' _; O! Q3 V5 u
//Byte[12]= Y-coordinate MSB7 k: ^1 ~* j( h, j# P! j
, M: ?# A6 v+ N1 i
//3rd contact point info in bytes 13-18# c/ o$ B& c, n' b9 V' @2 @
//Byte[13] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch6 f# P) R8 G/ Q- l* `
//Byte[14] = Contact identifier number (see note above)5 e0 k% Z6 l) E, \2 r
//Byte[15] = X-coordinate LSB: u" X0 O! X: i
//Byte[16] = X-coordinate MSB
//Byte[17] = Y-coordinate LSB: Q W+ J5 i5 z3 _; w; `6 n
//Byte[18] = Y-coordinate MSB8 u7 t- R$ c+ B( f7 l1 q: o) G
//4th contact point info in bytes 19-24- I' V4 e6 f% p% }' O
//Byte[19] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch4 v+ w" y$ X; q% j) l3 }) D
//Byte[20] = Contact identifier number (see note above)( l9 h8 w; y$ p
//Byte[21] = X-coordinate LSB
//Byte[22] = X-coordinate MSB
//Byte[23] = Y-coordinate LSB
//Byte[24] = Y-coordinate MSB
//5th contact point info in bytes 25-30
//Byte[25] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch
//Byte[26] = Contact identifier number (see note above)
//Byte[27] = X-coordinate LSB
//Byte[28]= X-coordinate MSB
//Byte[29]= Y-coordinate LSB/ H+ r4 p; F' l. _( x. N0 i& r5 Q
//Byte[30]= Y-coordinate MSB8 H8 R) ]3 i2 U# l/ e/ S
+ V' H3 S @1 ]6 A" c) z: ^
//Byte[31]= 8-bit number indicating how many of the above contact points are valid.
// If only the first contact is valid, send "1" here. If both are valid, send "2".......etc.6 F7 W4 o- @: j0 i) N, a
//HID Report descriptor for an example Multi-Touch (5 simultaneous contacts), multi-modes device.( v: u# s/ ^& O$ K0 c8 z/ r" _
//------------------------------------------------------------------------------------------------
//Note: In a real application, at a minimum, certain terms in the report descriptor
//(ex: UNIT, UNIT_EXPONENT, PHYSICAL_MAXIMUM and LOGICAL_MAXIMUM) will need to be modified to4 q" z Z7 b) {
//match the characteristics (ex: size) of the actual application being developed. See the HID1_11.pdf
//specifications regarding these terms.
8 n% I' Y) g* L1 S2 P
//contact point* Y1 b* r3 B: ~& y7 W+ C, b; L
0x05, 0x0D, // USAGE_PAGE (Digitizers) 0 @ l3 M! S. q r
0x09, 0x04, // USAGE (Touch Screen)
0xA1, 0x01, // COLLECTION (Application)
0x85, MULTI_TOUCH_DATA_REPORT_ID, // REPORT_ID (Touch)
0x09, 0x22, // USAGE (Finger)
//Finger 0 ) j9 k& k9 k7 ]4 I5 S% a7 |& w( O" i: {
FINGER_USAGE,
//Finger 1 . N4 L# F3 D8 \$ j
FINGER_USAGE,$ G- v4 W' ~* y9 g) k
//Finger 2
FINGER_USAGE,+ A) V. M1 h' f4 Z7 j5 T4 z
//Finger 3 + J: u! Z' k1 z$ u0 @- B5 Q! ~) H
FINGER_USAGE,
//Finger 4
FINGER_USAGE,- K, s e9 O/ z! f( k
//Finger 5
FINGER_USAGE,9 h0 a& o3 `& |- x! v4 \
//Finger 6 $ |' J1 u9 o9 c# r1 B
FINGER_USAGE,
//Finger 7 , |0 I* l+ s! L& @9 p7 ~0 ]9 k/ m# q
FINGER_USAGE,2 r" B( o7 J6 g! m9 x; L
//Finger 8
FINGER_USAGE,8 z) ?. p5 g6 m* }( }' a8 r
//Finger 9 5 K' v% B9 v9 ?, G% m" ?2 S Q8 }
FINGER_USAGE,
//Timestamp in relative time - Scan Time
0x05, 0x0D, // Usage Page (Digitizer)
0x55, 0x0C, // Unit Exponent (-4)
0x66, 0x01, 0x10, // Unit (Seconds) / u/ j1 C: w, H8 U m" b
0x47, 0xFF, 0xFF, 0x00, 0x00, // Physical Maximum (65535)8 L0 [; D; p' J a1 ^
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65535) ! M* I/ v% ]( I9 G, i, K
0x75, 0x10, // Report Size (16) % z0 A9 `# |4 R1 a6 F
0x95, 0x01, // Report Count (1) & Y5 W3 m9 K# U0 w" n8 V4 m4 x
0x09, 0x56, // Usage (0x56, Relative Scan Time)3 Y* @6 O. y( n( |
0x81, 0x02, // Input (Data,Var,Abs)
# v! b/ t1 d( z% `7 A
//indicating how many of the above contact points
0x05, 0x0D, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual (contact) count)
0x95, 0x01, // REPORT_COUNT (1), F$ ^' u0 u# ^
0x75, 0x08, // REPORT_SIZE (8) : B5 M8 h' F6 Z+ O1 H- \+ S
0x25, 0x0A, // LOGICAL_MAXIMUM (10) 6 J7 Q5 ?7 ^1 t7 K
0x81, 0x02, // INPUT (Data,Var,Abs)
//In addition to standard HID reports (containing contact X/Y/tip-switch/in-range
//information), the firmware can send feature report information to the host.
//Feature reports lets the host know information about the firmware/hardware
//application design. The host will typically request a feature report by sending
//a GET_REPORT control transfer, with the bRequest = REPORT, but with wIndex (MSB) = 0x03
//(get feature report request as indicated in the HID1_11.pdf specifications). If a
//feature report is sent to the host, it should be sent as a 2-byte packet (for 3 h" R# P$ x- [! P5 {
//this example project), formatted like follows:) I/ m o# h8 W* Y/ b! y# H
//Byte[0]= Report ID == VALID_CONTACTS_FEATURE_REPORT_ID == Feature report ID
//Byte[1]= Maximum number of contacts simultaneously supported by this application. Always == 2 in this demo, since this report descriptor only has input fields for 2 contact points6 I3 f7 C, A# E7 Z4 `8 G+ d" T8 J
//See the UserGetReportHandler() function that sends this type of packet in the MultiTouch.c file.& i2 w' T z3 c5 A* b
//GET_REPORT CTL : A1 01 52 03 04 00 02 00; p) }9 r% `* n- H+ S# F8 b
// IN : 52 05
2 L$ m; P% {. \( l8 k
0x85, VALID_CONTACTS_FEATURE_REPORT_ID, // REPORT_ID (Feature) " s+ ]5 n# D6 @! |' h
0x09, 0x55, // USAGE(Maximum Count)# A) I- ~ M; s" n, a! w6 u
0xB1, 0x02, // FEATURE (Data,Var,Abs) 3 R+ X8 p/ ]. j1 j1 a
: d2 d, t( b" ]' y
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined)
0x09, 0xC5, // USAGE (Vendor Usage 0xC5)
0x85, VALID_CONTACTS_FEATURE_REPORT_ID, // REPORT_ID (VALID_CONTACTS_FEATURE_REPORT_ID)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (0xff)
0x75, 0x08, // REPORT_SIZE (8)
0x96, 0x00, 0x01, // REPORT_COUNT (0x100) (256)
0xB1, 0x02, // FEATURE (Data,Var,Abs)
9 E/ e! v8 ~' p- n& N% \
0x05, 0x0d, // USAGE_PAGE (Digitizer)7 s, T. u. Q/ N o0 S' J' }
0x85, Latency_Mode_Feature_Report_ID, // REPORT_ID (Latency)
0x09, 0x60, // USAGE(Latency Mode)( r2 J3 i# {# `0 B) g. |& n
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1) o; y# A! M1 c
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x95, 0x07, // REPORT_COUNT (7)
0xb1, 0x03, // FEATURE (Cnst,Var,Abs) : c' R# O3 t& F* [7 ^$ p( n# k6 `
; O# }: c! B ^8 @. ?6 Y- _7 k
0xC0, // END_COLLECTION1 `4 ?" j9 h! K7 b
0 u1 H E/ l- j
1 G8 G% \, z5 j0 D0 c. c
//Top level collection describing the feature report that the host will use (SET_REPORT (feature) control transfer) to set the device mode (ex: mouse, single-touch digitizer, multi-touch digitizer)
//-------------------------------------------------------------------! b7 I, F) f( `1 r) I
//Format of the feature report output data that the host will send to the device (when it wants to change the device mode):
//byte[0] = Report ID = DEVICE_MODE_FEATURE_REPORT_ID& W8 E; `* d+ L
//byte[1] = Device Mode (that the device should switch into)
//byte[2] = Device Identifier q# v: `, e! [) _' e
' B4 l1 a- ~; r) s
//SET_REPORT CTL : 21 09 53 03 04 00 03 00. B( { T- `% B# T
// IN : 53 02 00 I/ t+ N9 \) ]" I( l. |6 v, F- y. h
0x09, 0x0E, // USAGE (Device Configuration)
0xa1, 0x01, // COLLECTION (Application)8 U8 y/ s3 v$ M1 R5 p0 T0 f
0x85, DEVICE_MODE_FEATURE_REPORT_ID, // REPORT_ID (Configuration)
0x09, 0x23, // USAGE (Device Settings) : n( z* a( [' \
0xa1, 0x02, // COLLECTION (logical)
0x09, 0x52, // USAGE (Device Mode)
0x09, 0x53, // USAGE (Device Identifier)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x0a, // LOGICAL_MAXIMUM (10)
0x75, 0x08, // REPORT_SIZE (8) 8 R- |- E# a) A% Y. E' j, X
0x95, 0x02, // REPORT_COUNT (2)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION (logical)% M+ q3 b9 `7 Y6 `
0xc0, // END_COLLECTION (application). A [; }% {$ ^2 W/ i$ b7 ?
//Top level collection for use in Mouse device mode.
//-------------------------------------------------------------------
0x05, 0x01, // Usage Page (Generic Desktop) 0 w% t) W% Y; p, d0 R6 M
0x09, 0x02, // Usage (Mouse) 4 v8 f1 d4 o" a. u' k1 E3 E$ O
0xA1, 0x01, // Collection (Application)
0x85, MOUSE_DATA_REPORT_ID, // REPORT_ID (mouse)& T" w1 m( @! }
0x09, 0x01, // Usage (Pointer) P2 h0 j1 S% F5 m6 Q( K$ t$ g
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Buttons)
0x19, 0x01, // Usage Minimum (01)
0x29, 0x03, // Usage Maximum (03)
0x15, 0x00, // Logical Minimum (0) 0 ^+ F4 Y4 k$ g2 [( ~
0x25, 0x01, // Logical Maximum (1)
0x45, 0x00, // Physical Maximum (0)
0x65, 0x00, // Unit (none) 3 U0 U8 Y6 M( |2 ~
0x95, 0x03, // Report Count (3) 4 \7 a0 y( v: h/ C. ? Z" Y
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x01, // Input (Constant) ;5 bit padding
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X) 6 i: X v$ g& z7 P4 J
0x09, 0x31, // Usage (Y) + a5 x. L4 Y: F8 }* g, K. q1 J4 a
0x15, 0x81, // Logical Minimum (-127) : V3 }8 f6 Z; d3 S/ V2 d
0x25, 0x7F, // Logical Maximum (127) ) ^2 f7 d5 p% }1 _2 b$ `7 k* y
0x75, 0x08, // Report Size (8) ( A3 l4 S: `, W! g) q5 s- P. x
0x95, 0x02, // Report Count (2) - `- R+ I/ f: u1 G' a. M* n
0x81, 0x06, // Input (Data, Variable, Relative)
0xC0, // End Collection
0xC0, // End Collection 4 J# j2 @( x4 n
};4 u7 q# h6 j: o3 J
#define FINGER_USAGE \8 I$ n6 a" Z8 D ~/ f
0xA1, 0x02, /* COLLECTION (Logical) */ \! {' D$ b0 _# N2 d: Z
0x05, 0x0D, /* USAGE_PAGE (Digitizers) */ \
0x09, 0x42, /* USAGE (Tip Switch) */ \* ?( ~9 s2 O4 ?. S+ `) |
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \9 y' b; Y6 P9 n
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \
0x75, 0x01, /* REPORT_SIZE (1) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x09, 0x32, /* USAGE (In Range) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \6 U$ O/ \$ d' Z I9 M5 B
0x09, 0x51, /* Usage(Contact ID) */ \( H q7 V" T q* @' ?! _+ G: H
0x75, 0x06, /* REPORT_SIZE (6) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \) g u- k4 `$ [% j
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x25, 0x3F, /* LOGICAL_MAXIMUM (63) */ \% j1 x& }3 g, h5 E$ [
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \# ?' I3 ?1 ~. f% ~3 ?4 ^
0x05, 0x01, /* USAGE_PAGE (Generic Desk.. */ \
0x26, 0x20, 0x35, /* LOGICAL_MAXIMUM (13600) */ \( {+ b* P/ t9 B
0x75, 0x10, /* REPORT_SIZE (16) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x55, 0x0E, /* UNIT_EXPONENT (-2) */ \% J( K0 r/ }, S. P" N1 l
0x65, 0x33, /* UNIT (Inches, English Linear) */ \
0x09, 0x30, /* USAGE (X) */ \
0x35, 0x00, /* PHYSICAL_MINIMUM (0) */ \
0x46, 0x50, 0x05, /* PHYSICAL_MAXIMUM (0x550 = 1360) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \9 s3 s3 u8 n* s. ]$ B" z; c( S
0x26, 0xE2, 0x1D, /* LOGICAL_MAXIMUM (7650) */ \
0x46, 0xFD, 0x02, /* PHYSICAL_MAXIMUM (0x2FD = 765) */ \
0x09, 0x31, /* USAGE (Y) */ \% v: K8 Z8 J/ R! C: A
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \" M9 |0 }6 h8 b- E6 z) H
0xC0 /* END_COLLECTION */ 7 x+ J, S' r$ o
#endif
你可以試試看這是我寫的觸控描述