api_device.rst 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. 设备协议栈
  2. =========================
  3. 关于设备协议栈 API 的实现过程,有兴趣的可以看我的 B 站视频。设备协议栈的 API 使用了大量的链表,如何使用相关 API,参考下面一张图,并且总结如下:
  4. - 有多少个 class 就调用多少次 `usbd_class_register`
  5. - 每个 class 有多少个接口就调用多少次 `usbd_class_add_interface`,已经支持的 class 接口就调用对应的 `usbd_xxx_class_add_interface`
  6. - 每个接口有多少个端点就调用多少次 `usbd_interface_add_endpoint`
  7. .. figure:: img/api_device1.png
  8. CORE
  9. -----------------
  10. 端点结构体
  11. """"""""""""""""""""""""""""""""""""
  12. 端点结构体主要用于注册不同端点地址的中断完成回调函数。
  13. .. code-block:: C
  14. typedef struct usbd_endpoint {
  15. usb_slist_t list;
  16. uint8_t ep_addr;
  17. usbd_endpoint_callback ep_cb;
  18. } usbd_endpoint_t;
  19. - **list** 端点的链表节点
  20. - **ep_addr** 端点地址(带方向)
  21. - **ep_cb** 端点完成中断回调函数。
  22. .. note:: 总结一句话:in 回调函数等价于 dma 发送完成中断回调函数;out 回调函数等价于 dma 接收完成中断回调函数
  23. 接口结构体
  24. """"""""""""""""""""""""""""""""""""
  25. 接口结构体主要用于注册不同类设备除了标准设备请求外的其他请求,包括类设备请求、厂商设备请求和自定义设备请求。以及协议栈中的相关通知回调函数。
  26. .. code-block:: C
  27. typedef struct usbd_interface {
  28. usb_slist_t list;
  29. /** Handler for USB Class specific commands*/
  30. usbd_request_handler class_handler;
  31. /** Handler for USB Vendor specific commands */
  32. usbd_request_handler vendor_handler;
  33. /** Handler for USB custom specific commands */
  34. usbd_request_handler custom_handler;
  35. /** Handler for USB event notify commands */
  36. usbd_notify_handler notify_handler;
  37. uint8_t intf_num;
  38. usb_slist_t ep_list;
  39. } usbd_interface_t;
  40. - **list** 接口的链表节点
  41. - **class_handler** class setup 请求回调函数
  42. - **vendor_handler** vendor setup 请求回调函数
  43. - **custom_handler** custom setup 请求回调函数
  44. - **notify_handler** 中断标志、协议栈相关状态回调函数
  45. - **intf_num** 当前接口偏移
  46. - **ep_list** 端点的链表节点
  47. 类结构体
  48. """"""""""""""""""""""""""""""""""""
  49. 类结构体主要用于挂载接口链表。后期可能会删除,因为这个部分跟接口其实是有关系的。
  50. .. code-block:: C
  51. typedef struct usbd_class {
  52. usb_slist_t list;
  53. const char *name;
  54. usb_slist_t intf_list;
  55. } usbd_class_t;
  56. - **list** 类的链表节点
  57. - **name** 类的名称
  58. - **intf_list** 接口的链表节点
  59. usbd_desc_register
  60. """"""""""""""""""""""""""""""""""""
  61. ``usbd_desc_register`` 用来注册 USB 描述符,描述符种类包括:设备描述符、配置描述符(包含配置描述符、接口描述符、class 类描述符、端点描述符)、字符串描述符、设备限定描述符。
  62. .. code-block:: C
  63. void usbd_desc_register(const uint8_t *desc);
  64. - **desc** 描述符的句柄
  65. usbd_msosv1_desc_register
  66. """"""""""""""""""""""""""""""""""""
  67. ``usbd_msosv1_desc_register`` 用来注册一个 WINUSB 1.0 描述符。
  68. .. code-block:: C
  69. void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
  70. - **desc** 描述符句柄
  71. usbd_msosv2_desc_register
  72. """"""""""""""""""""""""""""""""""""
  73. ``usbd_msosv2_desc_register`` 用来注册一个 WINUSB 2.0 描述符。
  74. .. code-block:: C
  75. void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc);
  76. - **desc** 描述符句柄
  77. usbd_bos_desc_register
  78. """"""""""""""""""""""""""""""""""""
  79. ``usbd_bos_desc_register`` 用来注册一个 BOS 描述符, USB 2.1 版本以上必须注册。
  80. .. code-block:: C
  81. void usbd_bos_desc_register(struct usb_bos_descriptor *desc);
  82. - **desc** 描述符句柄
  83. usbd_class_register
  84. """"""""""""""""""""""""""""""""""""
  85. ``usbd_class_register`` 用来注册一个 class,该 class 中的接口链表成员,用于后续挂载多个接口。
  86. .. code-block:: C
  87. void usbd_class_register(usbd_class_t *devclass);
  88. - **devclass** USB 设备类的句柄
  89. usbd_class_add_interface
  90. """"""""""""""""""""""""""""""""""""
  91. ``usbd_class_add_interface`` 用来给 USB 设备类增加接口,并将接口信息挂载在类的链表上。
  92. .. code-block:: C
  93. void usbd_class_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
  94. - **devclass** USB 设备类的句柄
  95. - **intf** USB 设备接口的句柄
  96. usbd_interface_add_endpoint
  97. """"""""""""""""""""""""""""""""""""
  98. ``usbd_interface_add_endpoint`` 用来给 USB 接口增加端点,并将端点信息挂载在接口的链表上。
  99. .. code-block:: C
  100. void usbd_interface_add_endpoint(usbd_interface_t *intf, usbd_endpoint_t *ep);
  101. - **intf** USB 设备接口的句柄
  102. - **ep** USB 设备端点的句柄
  103. usb_device_is_configured
  104. """"""""""""""""""""""""""""""""""""
  105. ``usb_device_is_configured`` 用来检查 USB 设备是否被配置(枚举)。
  106. .. code-block:: C
  107. bool usb_device_is_configured(void);
  108. - **return** 配置状态, 0 表示未配置, 1 表示配置成功
  109. usbd_configure_done_callback
  110. """"""""""""""""""""""""""""""""""""
  111. ``usbd_configure_done_callback`` 在执行 set_configuration 命令后触发,表示配置完成,用户需要实现该函数, **此函数一般用作启动第一次数据接收**,如果没有使用到 out 端点,则函数为空即可。
  112. .. code-block:: C
  113. bool usbd_configure_done_callback(void);
  114. .. warning:: msc 端点不需要在该函数中手动启动,协议栈会自动启动第一次接收
  115. usbd_initialize
  116. """"""""""""""""""""""""""""""""""""
  117. ``usbd_initialize`` 用来初始化 usb device 寄存器配置、usb 时钟、中断等,需要注意,此函数必须在所有列出的 API 最后。
  118. .. code-block:: C
  119. int usbd_initialize(void);
  120. CDC ACM
  121. -----------------
  122. usbd_cdc_add_acm_interface
  123. """"""""""""""""""""""""""""""""""""
  124. ``usbd_cdc_add_acm_interface`` 用来给 USB CDC ACM 类添加接口,并实现该接口相关的函数。
  125. - ``cdc_acm_class_request_handler`` 用来处理 USB CDC ACM 类 Setup 请求。
  126. - ``cdc_notify_handler`` 用来处理 USB CDC 其他中断回调函数。
  127. .. code-block:: C
  128. void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf);
  129. - **devclass** 类的句柄
  130. - **intf** 接口句柄
  131. usbd_cdc_acm_set_line_coding
  132. """"""""""""""""""""""""""""""""""""
  133. ``usbd_cdc_acm_set_line_coding`` 用来对串口进行配置,如果仅使用 USB 而不用 串口,该接口不用用户实现,使用默认。
  134. .. code-block:: C
  135. void usbd_cdc_acm_set_line_coding(uint8_t intf, uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits);
  136. - **intf** 控制接口号
  137. - **baudrate** 波特率
  138. - **databits** 数据位
  139. - **parity** 校验位
  140. - **stopbits** 停止位
  141. usbd_cdc_acm_set_dtr
  142. """"""""""""""""""""""""""""""""""""
  143. ``usbd_cdc_acm_set_dtr`` 用来控制串口 DTR 。如果仅使用 USB 而不用 串口,该接口不用用户实现,使用默认。
  144. .. code-block:: C
  145. void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
  146. - **intf** 控制接口号
  147. - **dtr** dtr 为1表示拉低电平,为0表示拉高电平
  148. usbd_cdc_acm_set_rts
  149. """"""""""""""""""""""""""""""""""""
  150. ``usbd_cdc_acm_set_rts`` 用来控制串口 RTS 。如果仅使用 USB 而不用 串口,该接口不用用户实现,使用默认。
  151. .. code-block:: C
  152. void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
  153. - **intf** 控制接口号
  154. - **rts** rts 为1表示拉低电平,为0表示拉高电平
  155. CDC_ACM_DESCRIPTOR_INIT
  156. """"""""""""""""""""""""""""""""""""
  157. ``CDC_ACM_DESCRIPTOR_INIT`` 配置了默认的 cdc acm 需要的描述符以及参数,方便用户使用。总长度为 `CDC_ACM_DESCRIPTOR_LEN` 。
  158. .. code-block:: C
  159. CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx);
  160. - **bFirstInterface** 表示该 cdc acm 第一个接口所在所有接口的偏移
  161. - **int_ep** 表示中断端点地址(带方向)
  162. - **out_ep** 表示 bulk out 端点地址(带方向)
  163. - **in_ep** 表示 bulk in 端点地址(带方向)
  164. - **str_idx** 控制接口对应的字符串 id
  165. HID
  166. -----------------
  167. usbd_hid_add_interface
  168. """"""""""""""""""""""""""""""""""""
  169. ``usbd_hid_add_interface`` 用来给 USB HID 类添加接口,并实现该接口相关的函数:
  170. - ``hid_class_request_handler`` 用来处理 USB HID 类的 Setup 请求。
  171. - ``hid_custom_request_handler`` 用来处理 USB HID 获取报告描述符请求。
  172. - ``hid_notify_handler`` 用来处理 USB HID 其他中断回调函数。
  173. .. code-block:: C
  174. void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
  175. - **devclass** 类的句柄
  176. - **intf** 接口句柄
  177. usbd_hid_report_descriptor_register
  178. """"""""""""""""""""""""""""""""""""""""""""
  179. ``usbd_hid_report_descriptor_register`` 用来注册 hid 报告描述符。
  180. .. code-block:: C
  181. void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
  182. - **intf_num** 当前 hid 报告描述符所在接口偏移
  183. - **desc** 报告描述符
  184. - **desc_len** 报告描述符长度
  185. MSC
  186. -----------------
  187. usbd_msc_class_init
  188. """"""""""""""""""""""""""""""""""""
  189. ``usbd_msc_class_init`` 用来给 MSC 类添加接口,并实现该接口相关函数,并且注册端点回调函数。(因为 msc bot 协议是固定的,所以不需要用于实现,因此端点回调函数自然不需要用户实现)。
  190. - ``msc_storage_class_request_handler`` 用于处理 USB MSC Setup 中断请求。
  191. - ``msc_storage_notify_handler`` 用于实现 USB MSC 其他中断回调函数。
  192. - ``mass_storage_bulk_out`` 用于处理 USB MSC 端点 out 中断。
  193. - ``mass_storage_bulk_in`` 用于处理 USB MSC 端点 in 中断。
  194. .. code-block:: C
  195. void usbd_msc_class_init(uint8_t out_ep, uint8_t in_ep);
  196. - **out_ep** out 端点地址
  197. - **in_ep** in 端点地址
  198. usbd_msc_get_cap
  199. """"""""""""""""""""""""""""""""""""
  200. ``usbd_msc_get_cap`` 用来获取存储器的 lun、扇区个数和每个扇区大小。用户必须实现该函数。
  201. .. code-block:: C
  202. void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
  203. - **lun** 存储逻辑单元,暂时无用,默认支持一个
  204. - **block_num** 存储扇区个数
  205. - **block_size** 存储扇区大小
  206. usbd_msc_sector_read
  207. """"""""""""""""""""""""""""""""""""
  208. ``usbd_msc_sector_read`` 用来对存储器某个扇区开始的地址进行数据读取。用户必须实现该函数。
  209. .. code-block:: C
  210. int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
  211. - **sector** 扇区偏移
  212. - **buffer** 存储读取的数据的指针
  213. - **length** 读取长度,当前为1个扇区的大小
  214. usbd_msc_sector_write
  215. """"""""""""""""""""""""""""""""""""
  216. ``usbd_msc_sector_write`` 用来对存储器某个扇区开始写入数据。用户必须实现该函数。
  217. .. code-block:: C
  218. int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
  219. - **sector** 扇区偏移
  220. - **buffer** 写入数据指针
  221. - **length** 写入长度,当前为1个扇区的大小
  222. UAC
  223. -----------------
  224. usbd_audio_add_interface
  225. """"""""""""""""""""""""""""""""""""
  226. ``usbd_audio_add_interface`` 用来给 USB Audio 类添加接口,并实现该接口相关的函数:
  227. - ``audio_class_request_handler`` 用于处理 USB Audio Setup 中断请求。
  228. - ``audio_notify_handler`` 用于实现 USB Audio 其他中断回调函数。
  229. .. code-block:: C
  230. void usbd_audio_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
  231. - **class** 类的句柄
  232. - **intf** 接口句柄
  233. usbd_audio_open
  234. """"""""""""""""""""""""""""""""""""
  235. ``usbd_audio_open`` 用来开启音频数据传输。
  236. .. code-block:: C
  237. void usbd_audio_open(uint8_t intf);
  238. - **intf** 开启的接口号
  239. usbd_audio_close
  240. """"""""""""""""""""""""""""""""""""
  241. ``usbd_audio_close`` 用来关闭音频数据传输。
  242. .. code-block:: C
  243. void usbd_audio_close(uint8_t intf);
  244. - **intf** 关闭的接口号
  245. usbd_audio_add_entity
  246. """"""""""""""""""""""""""""""""""""
  247. ``usbd_audio_add_entity`` 用来添加 unit 相关控制,例如 feature unit、clock source。
  248. .. code-block:: C
  249. void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype);
  250. - **entity_id** 要添加的 unit id
  251. - **bDescriptorSubtype** entity_id 的描述符子类型
  252. usbd_audio_set_mute
  253. """"""""""""""""""""""""""""""""""""
  254. ``usbd_audio_set_mute`` 用来设置静音。
  255. .. code-block:: C
  256. void usbd_audio_set_mute(uint8_t ch, uint8_t enable);
  257. - **ch** 要设置静音的通道
  258. - **enable** 为1 表示静音,0相反
  259. usbd_audio_set_volume
  260. """"""""""""""""""""""""""""""""""""
  261. ``usbd_audio_set_volume`` 用来设置音量。
  262. .. code-block:: C
  263. void usbd_audio_set_volume(uint8_t ch, float dB);
  264. - **ch** 要设置音量的通道
  265. - **dB** 要设置音量的分贝,其中 UAC1.0范围从 -127 ~ +127dB,UAC2.0 从 0 ~ 256dB
  266. usbd_audio_set_sampling_freq
  267. """"""""""""""""""""""""""""""""""""
  268. ``usbd_audio_set_sampling_freq`` 用来设置设备上音频模块的采样率
  269. .. code-block:: C
  270. void usbd_audio_set_sampling_freq(uint8_t ep_ch, uint32_t sampling_freq);
  271. - **ch** 要设置采样率的端点或者通道,UAC1.0为端点,UAC2.0 为通道
  272. - **dB** 要设置的采样率
  273. usbd_audio_get_sampling_freq_table
  274. """"""""""""""""""""""""""""""""""""
  275. ``usbd_audio_get_sampling_freq_table`` 用来获取支持的采样率列表,如果函数没有实现,则使用默认采样率列表。
  276. .. code-block:: C
  277. void usbd_audio_get_sampling_freq_table(uint8_t **sampling_freq_table);
  278. - **sampling_freq_table** 采样率列表地址,格式参考默认采样率列表
  279. usbd_audio_set_pitch
  280. """"""""""""""""""""""""""""""""""""
  281. ``usbd_audio_set_pitch`` 用来设置音频音调,仅 UAC1.0 有这功能。
  282. .. code-block:: C
  283. void usbd_audio_set_pitch(uint8_t ep, bool enable);
  284. - **ep** 要设置音调的端点
  285. - **enable** 开启或关闭音调
  286. UVC
  287. -----------------
  288. usbd_video_add_interface
  289. """"""""""""""""""""""""""""""""""""
  290. ``usbd_video_add_interface`` 用来给 USB Video 类添加接口,并实现该接口相关的函数:
  291. - ``video_class_request_handler`` 用于处理 USB Video Setup 中断请求。
  292. - ``video_notify_handler`` 用于实现 USB Video 其他中断回调函数。
  293. .. code-block:: C
  294. void usbd_video_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
  295. - **class** 类的句柄
  296. - **intf** 接口句柄
  297. usbd_video_probe_and_commit_controls_init
  298. """"""""""""""""""""""""""""""""""""""""""""""""""""""""
  299. ``usbd_video_probe_and_commit_controls_init`` 初始化视频传输每帧最大传输长度。
  300. .. code-block:: C
  301. void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize);
  302. - **value** 为1 表示开启 stream 传输,为0 相反
  303. usbd_video_open
  304. """"""""""""""""""""""""""""""""""""
  305. ``usbd_video_open`` 用来开启视频数据传输。
  306. .. code-block:: C
  307. void usbd_video_open(uint8_t intf);
  308. - **intf** 开启的接口号
  309. usbd_video_close
  310. """"""""""""""""""""""""""""""""""""
  311. ``usbd_video_close`` 用来关闭视频数据传输。
  312. .. code-block:: C
  313. void usbd_video_open(uint8_t intf);
  314. - **intf** 关闭的接口号
  315. usbd_video_mjpeg_payload_fill
  316. """"""""""""""""""""""""""""""""""""
  317. ``usbd_video_mjpeg_payload_fill`` 用来填充 mjpeg 到新的 buffer中,其中会对 mjpeg 数据按帧进行切分,切分大小由 ``dwMaxPayloadTransferSize`` 控制,并添加头部信息,当前头部字节数为 2。头部信息见 ``struct video_mjpeg_payload_header``
  318. .. code-block:: C
  319. uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
  320. - **input** mjpeg 格式的数据包,从 FFD8~FFD9结束
  321. - **input_len** mjpeg数据包大小
  322. - **output** 输出缓冲区
  323. - **out_len** 输出实际要发送的长度大小
  324. - **return** 返回 usb 按照 ``dwMaxPayloadTransferSize`` 大小要发多少帧
  325. DFU
  326. -----------------
  327. PRINTER
  328. -----------------
  329. MTP
  330. -----------------