请教各位大佬,我最近使用F405芯片,用stm32CubeMX默认创建了一个USBHID的例程,这个例程默认就是一个HID模拟鼠标移动的程序,我创建之后也是可以正常枚举并且鼠标正常移动的,说明生成的工程是没有问题的,然后我把报告描述符修改成了一个多点触摸的描述符,这个描述符是以前项目使用的,是没有问题的。变量也没有改变,只是把报告描述符的内容替换了,如下图: 这个报告描述符字节比较大,又474个字节,然后我又把相应的配置描述符修改了,如下图所示:! {! {0 C! B( S% v( g* q 把配置描述符集合里HID描述符中描述报告描述符大小的字节改成我们修改后的大小,如下图 , k# r Q+ Q( D 按道理,将这些修改之后,就相当于重新约定了HID上报数据的协议,随后,我又按照新规定的报告描述符的协议模拟上报触控点的数据。2 B' q) w5 o* w2 K+ K 通过Bus hound显示枚举是成功的,也一直在按照报告描述符规定的协议向主机发送数据,但是没有模拟触控的现象,我使用以前的工程是有明显 的触控屏幕的现象的。通过设备管理器查看设备是正常运行的,然后用Bus hound观察枚举过程,发现一直在上报数据,但是在枚举过程中在主机 发送GET_REPORT之后出现了USTS c0000004 stall pid 错误,出现之后枚举也没有停止,而是正常运行的,数据也是正常上报的,& d: G1 U& U( f5 w/ I4 j3 p 但就是没有现象,我感觉是主机没有接收到报告描述符,或者接收错误了,导致虽然数据是正常上报的,但是系统不知道上报的数据的含义,. T( {. ]" n2 g' w: L2 Z 有没有大佬懂得这方面的错误,还请指导一下,工程其他地方都没有动,就是修改了配置、报告描述符等信息。4 R8 m g1 e2 i |
最全USB HID开发资料,悉心整理一个月,亲自测试
USB Audio设计与实现
【MCU实战经验】+STM32F107的USB使用
圈圈发布USB图书第二版有感,以及分享一些我学习USB过程...
STM32F4-DISC 实现USB主机(U盘)和USB设备(虚拟串口)自动切换
STM32 USB-HID通信移植步骤STM32 USB HID键盘例程
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
如何让CDC类USB设备批量接收64字节以上数据
用STM32F4实现的USB摄像头UVC,配合上位机可识别车牌
STM32 USB CDC 虚拟多串口
{% P; u9 J+ G" ]6 a
//Below is the report descriptor for an example multi-touch device, which can support " w0 W' I$ X3 K0 Y! S# G
//up to 5 simultaneous contacts. This report descriptor also supports multiple device modes.
//The OS may select the device mode (ex: mouse, single-touch digitizer, multi-touch digitizer)3 _+ m' r" X E( ?2 T! i
//by sending a SET_REPORT (feature) control transfer. In each mode, the device firmware
//should behave differently and send input packets on the HID IN endpoint, formatted( L$ T2 T+ n3 L9 o+ q4 R; ^
//based on the report descriptor collections associated with that mode.
3 }1 o( N' {* ]( X0 a9 ^3 U
//Each IN packet (HID report) sent to the host (in multi-touch digitizer mode) is ?? bytes long (Bytes 0-13). & z# a' o; `1 m- E0 b2 z
//The data is sent in little endian format. To send the report to the host, verify s2 W: U$ V( [; f& n
//that the HID IN endpoint buffer is not already busy, then place the data in the HID ) }) S" x. t5 u6 P! {$ M' a/ A
//IN endpoint buffer SRAM, and then call the UsbSendEP5Report() function. The data will 9 s% r! Z! I4 {/ Q* O8 e
//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).! n- C h9 ~1 b: b% f
! `. I/ U9 S% d) z
//NOTE (Contact identifier number): For a multi-touch device, the firmware needs to
//keep track of each contact point separately and independantly. For example, suppose
//a human first presses one finger to the screen. The firmware would detect this, and 1 a* P/ P; C7 m. z% A1 W: q
//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
//information for this contact, but the contact ID byte should always be = "1" for
//this contact.
//7 O) {+ H6 F$ F P/ J
//Now suppose the human places a second finger onto the touch surface, so there are 2 W# J& o2 X( ]
//two simultanous contacts. The firmware should assign this second contact a new ? E# q! L2 z9 h) G) p- \
//contact ID, for instance, contact ID = "2". So long as the first contact is still
//valid, the firmware needs to continue reporting ID = "1" for the first contact. ' I) \! z- q- `( M, N/ I3 y7 ]! D0 _
//The firmware will continue to report information using these contact ID numbers % _8 x; I9 g+ b; T
//until such time as a contact becomes invalid (human removes their finger from the
//screen).
$ l( Q7 H! W9 @; S: r5 `2 C
- q+ d1 D& u9 Q h/ D: y3 D& m
//Top level collection for use in Multi-Touch Digitizer device mode.
//-------------------------------------------------------------------: P5 c/ T6 i1 v- U9 M0 k" _5 p
//Format for multi-touch digitizer input reports Using this report descriptor:! x% w3 V0 L/ B& m$ v3 M
//Byte[0] = Report ID == MULTI_TOUCH_DATA_REPORT_ID' z% y+ G2 `4 [4 V* l
//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)
//Byte[3] = X-coordinate LSB" g5 Q5 l6 Q$ t& i
//Byte[4] = X-coordinate MSB2 Q% }8 G4 ]9 P1 L4 }6 i
//Byte[5] = Y-coordinate LSB/ b5 C. k# G; `' J e) v3 U
//Byte[6] = Y-coordinate MSB, G/ X Z% h" J' L* B* J
//2nd contact point info in bytes 7-12. Y$ @& l) Q" _3 s" P y- Z. B: o n) ?
//Byte[7] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch& A0 H# e' R% D/ `' u, n
//Byte[8] = Contact identifier number (see note above)6 y7 D1 x+ O& j0 T
//Byte[9] = X-coordinate LSB
//Byte[10]= X-coordinate MSB
//Byte[11]= Y-coordinate LSB
//Byte[12]= Y-coordinate MSB
, Z6 w+ F; T$ v0 S6 s9 O# b, P/ T
//3rd contact point info in bytes 13-18
//Byte[13] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch9 J* Z$ R% Q% s7 {3 W
//Byte[14] = Contact identifier number (see note above)
//Byte[15] = X-coordinate LSB! I- z* b5 \# u$ N* X$ E+ e
//Byte[16] = X-coordinate MSB
//Byte[17] = Y-coordinate LSB6 R# i" T+ J X7 v
//Byte[18] = Y-coordinate MSB5 b) ?6 L- m- F4 |) c* e# h# S
//4th contact point info in bytes 19-249 `5 @+ A- ?3 l1 x5 H
//Byte[19] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch
//Byte[20] = Contact identifier number (see note above)
//Byte[21] = X-coordinate LSB' C+ j5 L: h) W5 Y
//Byte[22] = X-coordinate MSB
//Byte[23] = Y-coordinate LSB" n( L) d$ r1 H) ?* D* [
//Byte[24] = Y-coordinate MSB. V8 Z5 m# ^) z# L
' j$ i* ?4 n; E
//5th contact point info in bytes 25-30. {9 H, g4 o" y
//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* b" g& {$ @! S8 u+ w4 g! T' ]1 O
//Byte[28]= X-coordinate MSB- f6 B' w. ?- m
//Byte[29]= Y-coordinate LSB( n1 o% c- O$ p
//Byte[30]= Y-coordinate MSB, \1 E9 W. a9 h" F" v/ b: F) Z
0 X/ @+ P/ H% Z
//Byte[31]= 8-bit number indicating how many of the above contact points are valid. # X% f6 a9 j, u' {
// If only the first contact is valid, send "1" here. If both are valid, send "2".......etc.. @- V& ?# H9 W- y& r
a% u0 ^3 m" S% J
//HID Report descriptor for an example Multi-Touch (5 simultaneous contacts), multi-modes device.# e" E) S: r! o0 m( [
//------------------------------------------------------------------------------------------------
//Note: In a real application, at a minimum, certain terms in the report descriptor 6 G7 G( Q3 @0 I" C F
//(ex: UNIT, UNIT_EXPONENT, PHYSICAL_MAXIMUM and LOGICAL_MAXIMUM) will need to be modified to
//match the characteristics (ex: size) of the actual application being developed. See the HID1_11.pdf* { h$ d' R7 _6 x
//specifications regarding these terms.* p" L( j% Q2 B( @' v
! W' ?& ]/ w ]8 J, O1 V& b U
//contact point9 W! c7 C$ E) _5 b( X% c
0x05, 0x0D, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xA1, 0x01, // COLLECTION (Application)
0x85, MULTI_TOUCH_DATA_REPORT_ID, // REPORT_ID (Touch) " P# y& J9 l# Q; M5 B( l% O
0x09, 0x22, // USAGE (Finger)8 x' P1 |' R5 _% C
//Finger 0 1 u6 {% Z! S& i" t8 `: s5 ^$ D6 z
FINGER_USAGE, 7 z+ y( ~- `5 F6 p( I( P6 M" Q
//Finger 1
FINGER_USAGE,& f1 c' T. Y+ k( a1 p
//Finger 2 1 z6 Y- b2 X0 t
FINGER_USAGE,
//Finger 3
FINGER_USAGE, & M* [7 f0 c v: g, t# K1 X
//Finger 4 ! K& u% V6 z# K0 c: D
FINGER_USAGE,
//Finger 5
FINGER_USAGE,- D, P* ~; \ m# ^8 u9 J7 P2 n
//Finger 6 ! n) D: W/ ?" J2 Q/ P# y) N
FINGER_USAGE,
//Finger 7 " Z& n, D( j+ p! r
FINGER_USAGE,4 v/ P& L! _( U+ H8 \. D
//Finger 8 4 @) P$ y0 N( t6 F& X
FINGER_USAGE,; d, {3 P5 d/ \) {- q
//Finger 9
FINGER_USAGE,
' e4 ?) h4 |4 A: x* m" g
//Timestamp in relative time - Scan Time
$ Y$ _: s/ ^% ] @5 B, d
0x05, 0x0D, // Usage Page (Digitizer)
0x55, 0x0C, // Unit Exponent (-4)
0x66, 0x01, 0x10, // Unit (Seconds) & k: |9 s0 l! V0 s6 |
0x47, 0xFF, 0xFF, 0x00, 0x00, // Physical Maximum (65535)
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65535) & z6 X6 F$ P9 S# b) I
0x75, 0x10, // Report Size (16) ; n# f, Y: S, i) H" u; X
0x95, 0x01, // Report Count (1) - |. C' o( {5 N
0x09, 0x56, // Usage (0x56, Relative Scan Time)
0x81, 0x02, // Input (Data,Var,Abs)
. l3 }0 Y$ m$ K$ A l
//indicating how many of the above contact points+ k. n- {! U7 Y
0x05, 0x0D, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual (contact) count)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8) / I# s1 `: I+ h+ K' q% C
0x25, 0x0A, // LOGICAL_MAXIMUM (10)
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. # m( y/ j, D, b. O. c
//Feature reports lets the host know information about the firmware/hardware
//application design. The host will typically request a feature report by sending " I4 Y- q8 n8 v0 F7 z( h/ b
//a GET_REPORT control transfer, with the bRequest = REPORT, but with wIndex (MSB) = 0x035 m. P6 D' `6 N
//(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 . k& G9 o9 t& K! N5 H& w6 C0 a
//this example project), formatted like follows:
//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 points7 L& f0 h! m: X+ s$ N: K7 B
//See the UserGetReportHandler() function that sends this type of packet in the MultiTouch.c file.
0 `& i5 g a2 ]6 ^, `1 r
//GET_REPORT CTL : A1 01 52 03 04 00 02 00; q- t% P+ E, K) H
// IN : 52 056 P- X) S% W; q, I7 K9 e
4 c8 a9 l4 j0 C7 u, u* C( f7 `0 d
0x85, VALID_CONTACTS_FEATURE_REPORT_ID, // REPORT_ID (Feature)
0x09, 0x55, // USAGE(Maximum Count). h! f# `; k: s
0xB1, 0x02, // FEATURE (Data,Var,Abs)
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined)
0x09, 0xC5, // USAGE (Vendor Usage 0xC5)1 v& h# i9 x W0 f
0x85, VALID_CONTACTS_FEATURE_REPORT_ID, // REPORT_ID (VALID_CONTACTS_FEATURE_REPORT_ID) 8 ?7 P) }1 ~4 f# ]/ U1 g1 N0 X
0x15, 0x00, // LOGICAL_MINIMUM (0) " f: A& Y2 g9 o$ @9 Y+ J, r
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (0xff) ; x* s1 c M% G5 K9 ~: j, A+ f
0x75, 0x08, // REPORT_SIZE (8) 1 T0 @! F' @- p- Z$ r* w2 x0 w
0x96, 0x00, 0x01, // REPORT_COUNT (0x100) (256)
0xB1, 0x02, // FEATURE (Data,Var,Abs)) Q: J, ^+ |& o* u. \
0x05, 0x0d, // USAGE_PAGE (Digitizer)
0x85, Latency_Mode_Feature_Report_ID, // REPORT_ID (Latency)
0x09, 0x60, // USAGE(Latency Mode)2 I1 K4 ]7 o$ {5 |; U }8 `
0x75, 0x01, // REPORT_SIZE (1) , d5 T( s7 D( e% {0 U
0x95, 0x01, // REPORT_COUNT (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)+ j: o' N9 S9 F- z% q
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x95, 0x07, // REPORT_COUNT (7) 4 D/ m4 c& I) S
0xb1, 0x03, // FEATURE (Cnst,Var,Abs) ; \7 E; f( h9 h/ p0 {9 D8 y
0xC0, // END_COLLECTION
9 t* l' d6 `1 C* \) r6 D/ M$ J* l7 f
//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)
//-------------------------------------------------------------------
//Format of the feature report output data that the host will send to the device (when it wants to change the device mode):% T {% y! W% E7 l( u
//byte[0] = Report ID = DEVICE_MODE_FEATURE_REPORT_ID: n; s! n8 s. g$ y; j3 N
//byte[1] = Device Mode (that the device should switch into)
//byte[2] = Device Identifier
//SET_REPORT CTL : 21 09 53 03 04 00 03 00& `- j4 G( ~" V/ A" t
// IN : 53 02 001 i* T- `2 J; x, n. u
& t: h* [% j% p. T$ t( M2 d
0x09, 0x0E, // USAGE (Device Configuration)
0xa1, 0x01, // COLLECTION (Application)
0x85, DEVICE_MODE_FEATURE_REPORT_ID, // REPORT_ID (Configuration) % `6 i! Y# M8 L
0x09, 0x23, // USAGE (Device Settings) 8 E& @9 E1 m( x3 F* F5 B* j
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) * w3 h0 C7 J& K' Q( z. Z7 [: t
0x95, 0x02, // REPORT_COUNT (2) ) a0 @4 I c; e& ]4 ~
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION (logical)4 u9 c: j8 C2 q! U% P+ p' ]
0xc0, // END_COLLECTION (application): d$ ^1 m) ?6 X3 z8 M& A
! }% P, E) _) D
//Top level collection for use in Mouse device mode. 8 _3 \- b) A4 k. E% V) b$ ^
//-------------------------------------------------------------------
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application) 2 ^5 A2 M9 Z* }1 i
0x85, MOUSE_DATA_REPORT_ID, // REPORT_ID (mouse)% ?' l" \, Z h i
0x09, 0x01, // Usage (Pointer) 8 g/ Z. }) K" ]* q% [
0xA1, 0x00, // Collection (Physical) + W+ [+ c2 j* t/ r: l7 B" D- b
0x05, 0x09, // Usage Page (Buttons)
0x19, 0x01, // Usage Minimum (01) |3 D- A0 L. H
0x29, 0x03, // Usage Maximum (03) + |' i$ q8 g4 J3 _6 {
0x15, 0x00, // Logical Minimum (0) # B* Y' x/ F; J) u J' M( [
0x25, 0x01, // Logical Maximum (1)
0x45, 0x00, // Physical Maximum (0)
0x65, 0x00, // Unit (none) ( \, `/ C% S, \& P" N$ ]/ B, o
0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1) I6 i& _4 y8 F
0x81, 0x02, // Input (Data, Variable, Absolute) $ p* @9 m- [+ J( X4 O0 c
0x95, 0x01, // Report Count (1) $ P+ v. z8 b7 T) J3 C$ F
0x75, 0x05, // Report Size (5) 4 M- x6 z1 K9 P) j
0x81, 0x01, // Input (Constant) ;5 bit padding ^) j5 \" h: Z* ]
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y) 3 ~- d# }8 w' w& G0 Q; T! Z$ v
0x15, 0x81, // Logical Minimum (-127) ! e1 B/ b8 }1 s8 _1 z0 t2 d
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data, Variable, Relative) ) F& j3 f. h! {7 [* \+ _
0xC0, // End Collection
0xC0, // End Collection
};% m" \- C" Y6 E6 ]) d; s
#define FINGER_USAGE \) ~6 |, A, M& K1 A
0xA1, 0x02, /* COLLECTION (Logical) */ \
0x05, 0x0D, /* USAGE_PAGE (Digitizers) */ \2 Z) t: w' t) |# l
0x09, 0x42, /* USAGE (Tip Switch) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \) V! w; o. O5 O
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \
0x75, 0x01, /* REPORT_SIZE (1) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \. K) M L2 ~) {2 a
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x09, 0x32, /* USAGE (In Range) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x09, 0x51, /* Usage(Contact ID) */ \- p8 S" g6 x0 K
0x75, 0x06, /* REPORT_SIZE (6) */ \5 E& _2 y9 t8 `. P
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \* ~% ^( U% n, P, C/ s+ `. r
0x25, 0x3F, /* LOGICAL_MAXIMUM (63) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x05, 0x01, /* USAGE_PAGE (Generic Desk.. */ \
0x26, 0x20, 0x35, /* LOGICAL_MAXIMUM (13600) */ \2 f" N, ^8 A" P0 |0 U
0x75, 0x10, /* REPORT_SIZE (16) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x55, 0x0E, /* UNIT_EXPONENT (-2) */ \* b- o1 h6 f8 c1 `& G
0x65, 0x33, /* UNIT (Inches, English Linear) */ \# p; e, {9 J6 c" l5 j
0x09, 0x30, /* USAGE (X) */ \
0x35, 0x00, /* PHYSICAL_MINIMUM (0) */ \
0x46, 0x50, 0x05, /* PHYSICAL_MAXIMUM (0x550 = 1360) */ \6 Q& D8 Q7 \3 g- C' n
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x26, 0xE2, 0x1D, /* LOGICAL_MAXIMUM (7650) */ \
0x46, 0xFD, 0x02, /* PHYSICAL_MAXIMUM (0x2FD = 765) */ \
0x09, 0x31, /* USAGE (Y) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \. v& [2 w" o: H( u& b# X4 l
0xC0 /* END_COLLECTION */
#endif
你可以試試看這是我寫的觸控描述