请教各位大佬,我最近使用F405芯片,用stm32CubeMX默认创建了一个USBHID的例程,这个例程默认就是一个HID模拟鼠标移动的程序,我创建之后也是可以正常枚举并且鼠标正常移动的,说明生成的工程是没有问题的,然后我把报告描述符修改成了一个多点触摸的描述符,这个描述符是以前项目使用的,是没有问题的。变量也没有改变,只是把报告描述符的内容替换了,如下图: 这个报告描述符字节比较大,又474个字节,然后我又把相应的配置描述符修改了,如下图所示: 把配置描述符集合里HID描述符中描述报告描述符大小的字节改成我们修改后的大小,如下图4 E) |: F+ i% X6 {+ Z' D0 w : e) P S+ s7 [4 r: Q# E 按道理,将这些修改之后,就相当于重新约定了HID上报数据的协议,随后,我又按照新规定的报告描述符的协议模拟上报触控点的数据。! A# B; S% G0 }& H# A0 d, B& X% U 通过Bus hound显示枚举是成功的,也一直在按照报告描述符规定的协议向主机发送数据,但是没有模拟触控的现象,我使用以前的工程是有明显 的触控屏幕的现象的。通过设备管理器查看设备是正常运行的,然后用Bus hound观察枚举过程,发现一直在上报数据,但是在枚举过程中在主机: ^9 J* u/ S: X/ e' m! q8 Y 发送GET_REPORT之后出现了USTS c0000004 stall pid 错误,出现之后枚举也没有停止,而是正常运行的,数据也是正常上报的, 但就是没有现象,我感觉是主机没有接收到报告描述符,或者接收错误了,导致虽然数据是正常上报的,但是系统不知道上报的数据的含义, s; ^ J- N/ y& ~ 有没有大佬懂得这方面的错误,还请指导一下,工程其他地方都没有动,就是修改了配置、报告描述符等信息。 |
最全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 虚拟多串口
{, X) a* b- Z$ i- @( ]
//Below is the report descriptor for an example multi-touch device, which can support 6 z. V3 g0 P8 l& s# P' A. Q. j
//up to 5 simultaneous contacts. This report descriptor also supports multiple device modes.8 Z2 H$ }, G% m) q" B+ M
//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$ I* h; R3 t% V. _ K6 i
//should behave differently and send input packets on the HID IN endpoint, formatted1 L- A- X* R/ l9 O
//based on the report descriptor collections associated with that mode.9 n% t2 d! \- b1 t0 X
8 j/ \# N+ X" J/ J8 v" x- i% ]
//Each IN packet (HID report) sent to the host (in multi-touch digitizer mode) is ?? bytes long (Bytes 0-13). 7 W6 I# x! K! ^
//The data is sent in little endian format. To send the report to the host, verify
//that the HID IN endpoint buffer is not already busy, then place the data in the HID ) l+ K1 _6 b: L
//IN endpoint buffer SRAM, and then call the UsbSendEP5Report() function. The data will & w, t' Q* |( C. @% z* H
//then get sent to the host, at the next opportunity when the host polls that endpoint / ]3 h# R G0 F# ~/ `. l, H
//(by sending an IN token packet to the endpoint)./ P, Q. O- j$ s7 \% ^ _1 p5 ~
i8 z- w) X4 n" X- {/ R7 v
//NOTE (Contact identifier number): For a multi-touch device, the firmware needs to + J. y/ u$ w2 [3 A2 m" u
//keep track of each contact point separately and independantly. For example, suppose & i% I& I4 K. \/ [5 M5 K
//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 . m, m+ }3 J+ _2 F. M
//around on the contact surface the firmware will report new X and Y coordinate # H1 ` d g [8 e6 r- I8 H( z
//information for this contact, but the contact ID byte should always be = "1" for
//this contact.- o; r s& G' |: D+ S" Q% r
//& q/ B9 o# t2 F( I% Z
//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
//contact ID, for instance, contact ID = "2". So long as the first contact is still) `/ m# j6 }$ a+ ^
//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 6 p/ L; H% o" a
//until such time as a contact becomes invalid (human removes their finger from the + F7 B( f. T: s
//screen).8 o' @/ |# S/ n& O( A }) j0 x0 A2 Q% |
/ L# j! x! N E
//Top level collection for use in Multi-Touch Digitizer device mode.* ^( r& U/ Q- P; i2 i- a7 @
//-------------------------------------------------------------------) g2 N! x) K6 M1 M' ]2 b% R
//Format for multi-touch digitizer input reports Using this report descriptor:9 F" @; U$ t; T7 s
//Byte[0] = Report ID == MULTI_TOUCH_DATA_REPORT_ID
//1st contact point info in bytes 1-6., T% W5 d( Q; A! S) y
//Byte[1] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch: b7 j" y: w5 b6 c) ]7 D, Y5 ]9 L6 v
//Byte[2] = Contact identifier number (see note above)
//Byte[3] = X-coordinate LSB
//Byte[4] = X-coordinate MSB% e/ M% N6 i- J
//Byte[5] = Y-coordinate LSB
//Byte[6] = Y-coordinate MSB9 J9 q1 Z1 a3 n; k2 C9 } B o+ k
( ~- R- Q$ u3 N- I0 V& V3 i b
//2nd contact point info in bytes 7-12* N0 b$ o0 c: _. f5 T
//Byte[7] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch
//Byte[8] = Contact identifier number (see note above)) i3 m5 w1 h3 e0 k
//Byte[9] = X-coordinate LSB
//Byte[10]= X-coordinate MSB0 m% U2 ^6 I0 q, m9 @6 U( }
//Byte[11]= Y-coordinate LSB
//Byte[12]= Y-coordinate MSB, }; u- a) J4 X
, p6 A7 p& I0 _( ^8 w4 F; J
//3rd contact point info in bytes 13-18
//Byte[13] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch
//Byte[14] = Contact identifier number (see note above)9 v6 i6 C8 F& n9 m
//Byte[15] = X-coordinate LSB
//Byte[16] = X-coordinate MSB
//Byte[17] = Y-coordinate LSB
//Byte[18] = Y-coordinate MSB
8 o0 D' i0 D& }8 }" ^2 Q* T
//4th contact point info in bytes 19-243 G$ X$ R1 B) G3 M8 X* \
//Byte[19] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch5 ~) l% V, A- y. A9 B+ p. `6 e
//Byte[20] = Contact identifier number (see note above)9 o' [, B4 k `" T
//Byte[21] = X-coordinate LSB; _% X2 {' b+ Z( D) P" _
//Byte[22] = X-coordinate MSB
//Byte[23] = Y-coordinate LSB
//Byte[24] = Y-coordinate MSB& v( m7 _5 i7 b. Q+ e
//5th contact point info in bytes 25-30! ^' \3 ^1 ]+ w' W6 Y' M! ^
//Byte[25] = Bits7-3: pad bits (unused), Bit1:In Range, Bit0:Tip Switch. P N/ d2 v& [% ]/ L8 ?3 V3 P
//Byte[26] = Contact identifier number (see note above)/ M% o3 t, u: _8 _
//Byte[27] = X-coordinate LSB
//Byte[28]= X-coordinate MSB
//Byte[29]= Y-coordinate LSB) p3 h1 o b+ z$ I
//Byte[30]= Y-coordinate MSB' F: d. A5 W- r$ ^/ v' w
//Byte[31]= 8-bit number indicating how many of the above contact points are valid. " `3 s, i' U3 ~$ o% m
// If only the first contact is valid, send "1" here. If both are valid, send "2".......etc.
2 k* @4 J0 L' ? n% p
//HID Report descriptor for an example Multi-Touch (5 simultaneous contacts), multi-modes device.
//------------------------------------------------------------------------------------------------3 X; v3 o. f0 D9 }6 ]. d
//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 to/ D* x6 y7 b- D7 M8 {
//match the characteristics (ex: size) of the actual application being developed. See the HID1_11.pdf
//specifications regarding these terms.
; z1 l1 _4 P; U- L* O" T
//contact point8 `5 G% R, p& E$ ^$ e4 k
0x05, 0x0D, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen) . v& J( h8 X& y9 a/ p9 u% C+ B: w) [
0xA1, 0x01, // COLLECTION (Application)
0x85, MULTI_TOUCH_DATA_REPORT_ID, // REPORT_ID (Touch) ; y U/ Z2 L; F* o/ g8 ~: M
0x09, 0x22, // USAGE (Finger)
//Finger 0 6 r3 U+ q" _) D! s! `- p4 \
FINGER_USAGE,
//Finger 1
FINGER_USAGE,
//Finger 2 - l7 R: }2 `' X- `( A5 ~1 ]$ r
FINGER_USAGE,6 b% ]3 f* l I4 a: f9 T" k2 \' G
//Finger 3 9 N/ S4 X/ y; m5 B* a, j5 M
FINGER_USAGE, # }3 |9 Q8 Z) |7 I" Z0 T; w: B
//Finger 4 ( u8 I% ~/ e# }6 ?7 M9 W! n
FINGER_USAGE,
//Finger 5
FINGER_USAGE,
//Finger 6 5 ^7 p- ^/ L$ Z9 ?% X2 x+ B! u
FINGER_USAGE,
//Finger 7 2 Z& S' }7 y. E' M$ j* C
FINGER_USAGE,
//Finger 8 2 \. `/ O% A& @3 o
FINGER_USAGE,0 C* h8 ~7 e) y! I; Y# [! q. Z
//Finger 9 & m2 F6 B: s) b( z* b- X' _! _
FINGER_USAGE,# W# u* r0 @4 t$ u% H% C
( q" T. K8 r# I5 z& \2 Q& N7 k
//Timestamp in relative time - Scan Time3 d! |+ H7 S/ B$ ?
0x05, 0x0D, // Usage Page (Digitizer)
0x55, 0x0C, // Unit Exponent (-4)
0x66, 0x01, 0x10, // Unit (Seconds)
0x47, 0xFF, 0xFF, 0x00, 0x00, // Physical Maximum (65535)+ D8 G( k' `, C1 n, @& C1 ?
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65535)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x09, 0x56, // Usage (0x56, Relative Scan Time)7 l( y3 \- W& Q$ z- R) g
0x81, 0x02, // Input (Data,Var,Abs)
/ a4 y4 p: L: z Q
//indicating how many of the above contact points
! ~7 W! q$ c; p& \
0x05, 0x0D, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual (contact) count)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8) 3 i, K5 x, X! _
0x25, 0x0A, // LOGICAL_MAXIMUM (10) # x' |) G2 V8 R2 U: A
0x81, 0x02, // INPUT (Data,Var,Abs)
2 L9 N2 y/ a; Z$ N
//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. ; v4 h; X+ `# C% S1 [0 O7 ~
//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$ R- j; U2 g, ]) X
//(get feature report request as indicated in the HID1_11.pdf specifications). If a % K( e- v k$ o; z
//feature report is sent to the host, it should be sent as a 2-byte packet (for 8 V6 s# J. Q$ N& V2 r2 l
//this example project), formatted like follows:
//Byte[0]= Report ID == VALID_CONTACTS_FEATURE_REPORT_ID == Feature report ID9 n5 g. `% R s J2 b x& ?* B
//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 points& h( k+ w3 Z \
//See the UserGetReportHandler() function that sends this type of packet in the MultiTouch.c file.
//GET_REPORT CTL : A1 01 52 03 04 00 02 00- v8 r* s6 p( w9 i1 w! n! F+ o
// IN : 52 05% {+ A- L1 `7 p, `8 i
/ o5 _1 ]- E3 ]# R5 M5 d2 D" Z) m& M
0x85, VALID_CONTACTS_FEATURE_REPORT_ID, // REPORT_ID (Feature)
0x09, 0x55, // USAGE(Maximum Count)) u% ]# J& ~. q4 s9 x+ L
0xB1, 0x02, // FEATURE (Data,Var,Abs)
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined)
0x09, 0xC5, // USAGE (Vendor Usage 0xC5)! ?" z, X( o. Q
0x85, VALID_CONTACTS_FEATURE_REPORT_ID, // REPORT_ID (VALID_CONTACTS_FEATURE_REPORT_ID)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (0xff) ( `6 |) D0 D: D5 B- N
0x75, 0x08, // REPORT_SIZE (8) / E0 x W8 ~3 ]
0x96, 0x00, 0x01, // REPORT_COUNT (0x100) (256)
0xB1, 0x02, // FEATURE (Data,Var,Abs)
* S2 d. r/ W& B: o/ T2 L% N* }
0x05, 0x0d, // USAGE_PAGE (Digitizer) t/ J$ r, c! k. v' {
0x85, Latency_Mode_Feature_Report_ID, // REPORT_ID (Latency) 1 \7 {1 J$ k' {) q5 i; i
0x09, 0x60, // USAGE(Latency Mode)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)" q4 f i; o5 v
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x95, 0x07, // REPORT_COUNT (7) , @7 T) @9 x) w) g; P! F: Y
0xb1, 0x03, // FEATURE (Cnst,Var,Abs) ( g$ X1 ?& I+ G% h2 B7 I! \
0xC0, // END_COLLECTION9 X0 A+ i* }2 j. i
2 w$ Z Q7 R+ I0 A* a) ?3 w" 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)/ d# ^; w5 b# M' v. u. t
//-------------------------------------------------------------------
//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
//byte[1] = Device Mode (that the device should switch into)/ D( a" }$ W0 N" N3 ^
//byte[2] = Device Identifier: j( W# L9 ?( j7 u" R& k- r
: f5 U% a9 g" L, [8 u1 l
//SET_REPORT CTL : 21 09 53 03 04 00 03 006 j3 Y- m+ L! S8 W1 k. e# S& [
// IN : 53 02 00% p z" B! d0 f( X2 F
; _' V+ E ~7 X8 N4 L" m
0x09, 0x0E, // USAGE (Device Configuration)
0xa1, 0x01, // COLLECTION (Application)9 v* d! B7 l7 |0 u% a
0x85, DEVICE_MODE_FEATURE_REPORT_ID, // REPORT_ID (Configuration)
0x09, 0x23, // USAGE (Device Settings)
0xa1, 0x02, // COLLECTION (logical) : ]" L; L, s6 M% |* u s' Q
0x09, 0x52, // USAGE (Device Mode)
0x09, 0x53, // USAGE (Device Identifier). \3 s6 \0 i% |6 z3 e8 [5 C
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x0a, // LOGICAL_MAXIMUM (10); j% P: z" |5 \ [; c$ o, v# ?; k: e
0x75, 0x08, // REPORT_SIZE (8) / K5 y" \6 F/ O. E5 z$ m
0x95, 0x02, // REPORT_COUNT (2) ; s" s( t6 _2 r2 D9 W9 T
0xb1, 0x02, // FEATURE (Data,Var,Abs) ' K& n% |! V2 q# i8 _6 H% Z
0xc0, // END_COLLECTION (logical)
0xc0, // END_COLLECTION (application)
3 l! i4 B% q, R2 j: J3 d& }" g# H
//Top level collection for use in Mouse device mode. + H+ F, m) J1 r; ~& U3 |4 E
//-------------------------------------------------------------------2 c, N3 J+ j1 k% z; V' M7 _( L
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, MOUSE_DATA_REPORT_ID, // REPORT_ID (mouse)6 y# m- T# y! z+ B- l! z# a7 J3 z
0x09, 0x01, // Usage (Pointer) 1 v4 t- ~( _ c
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Buttons)
0x19, 0x01, // Usage Minimum (01) 3 S; ~+ N( b' x n
0x29, 0x03, // Usage Maximum (03) $ E8 q+ O9 o" o) c4 @
0x15, 0x00, // Logical Minimum (0) ; Q" N/ j( J9 G0 h
0x25, 0x01, // Logical Maximum (1) / |( ?; l- g% n& V
0x45, 0x00, // Physical Maximum (0)% h; o k+ o9 h* U! R, Y
0x65, 0x00, // Unit (none)
0x95, 0x03, // Report Count (3) 4 _/ Z: Q- N: L D9 \4 n
0x75, 0x01, // Report Size (1) " U& D& ]% T) m" T! a% q
0x81, 0x02, // Input (Data, Variable, Absolute) 5 O2 E( H4 |( Q: J
0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x01, // Input (Constant) ;5 bit padding
0x05, 0x01, // Usage Page (Generic Desktop) # P" P- a# V- v8 W1 o1 a
0x09, 0x30, // Usage (X) ( S5 \# G( m: n( D
0x09, 0x31, // Usage (Y)
0x15, 0x81, // Logical Minimum (-127) * m \+ S/ m2 H6 V3 h/ A* o
0x25, 0x7F, // Logical Maximum (127) : W6 p6 L3 ?' w( [# r; C/ \
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data, Variable, Relative) 6 i* S$ U& w( W: ~
0xC0, // End Collection3 {7 s9 T6 o- Q ^
0xC0, // End Collection
};; f9 C' z' r' n, X
+ R4 X/ U& l: b! q' I5 E1 g, v# |
#define FINGER_USAGE \7 T' b1 `! M2 {: D; o0 F' p
0xA1, 0x02, /* COLLECTION (Logical) */ \
0x05, 0x0D, /* USAGE_PAGE (Digitizers) */ \
0x09, 0x42, /* USAGE (Tip Switch) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \1 Q1 C; f' H5 A% C$ _ l* ^
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \! d* ^4 k3 C' p
0x75, 0x01, /* REPORT_SIZE (1) */ \' T9 V! B& D- r5 f# P$ R4 [. f7 T
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x09, 0x32, /* USAGE (In Range) */ \$ w+ @7 W( W$ P: z2 B( w
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \! T/ B8 A, W) H9 d+ ?/ @
0x09, 0x51, /* Usage(Contact ID) */ \- n" B" d+ S$ p0 w2 |9 p) @" }
0x75, 0x06, /* REPORT_SIZE (6) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \# \3 S6 ?" O y. x f1 d
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \: g1 p! q7 w2 U: y: p
0x25, 0x3F, /* LOGICAL_MAXIMUM (63) */ \( m- U% h5 F" c9 _8 `
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \3 G5 N! V; L$ e( G$ n
0x05, 0x01, /* USAGE_PAGE (Generic Desk.. */ \
0x26, 0x20, 0x35, /* LOGICAL_MAXIMUM (13600) */ \2 l! P4 G: r+ q7 Y* [
0x75, 0x10, /* REPORT_SIZE (16) */ \) e! D% U; z; ~+ C: O- J
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x55, 0x0E, /* UNIT_EXPONENT (-2) */ \5 A8 m) V, z0 H) Y6 d0 _% q
0x65, 0x33, /* UNIT (Inches, English Linear) */ \
0x09, 0x30, /* USAGE (X) */ \
0x35, 0x00, /* PHYSICAL_MINIMUM (0) */ \
0x46, 0x50, 0x05, /* PHYSICAL_MAXIMUM (0x550 = 1360) */ \' n( o: I& \( o" _
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
0x26, 0xE2, 0x1D, /* LOGICAL_MAXIMUM (7650) */ \) p5 x( \- Y6 x" A. e$ F$ l4 d
0x46, 0xFD, 0x02, /* PHYSICAL_MAXIMUM (0x2FD = 765) */ \& U8 \* |7 i3 X0 l: Y
0x09, 0x31, /* USAGE (Y) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \4 ~' u. V4 _9 E, z6 ?* h! P9 D* z" S
0xC0 /* END_COLLECTION */
#endif6 T6 o0 T# V% w; _$ O
1 s0 D/ f7 h/ J+ U' N2 q
你可以試試看這是我寫的觸控描述