drv_usbd.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-07-09 QT-one first version
  9. */
  10. #include "drv_usbd.h"
  11. #ifdef RT_USING_USB_DEVICE
  12. #if !defined(BSP_USING_USBD)
  13. #error "Please define at least one BSP_USING_USBD"
  14. #endif
  15. #if defined(BSP_USING_USBD)
  16. #include "usb_port.h"
  17. #endif
  18. struct ht32_usbd
  19. {
  20. char *name;
  21. USBDCore_TypeDef *p_usbd_code;
  22. IRQn_Type irq;
  23. };
  24. __ALIGN4 USBDCore_TypeDef p_usbd;
  25. /* internal mount point */
  26. static struct ht32_usbd *p_usbd_instance = RT_NULL;
  27. /* Endpoint Function List */
  28. static struct ep_id endpoint_pool[] =
  29. {
  30. {0x00, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED },
  31. {0x01, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
  32. {0x02, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
  33. {0x03, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
  34. {0x04, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED},
  35. {0x05, USB_EP_ATTR_ISOC, USB_DIR_IN, 64, ID_UNASSIGNED},
  36. {0x06, USB_EP_ATTR_ISOC, USB_DIR_OUT, 64, ID_UNASSIGNED},
  37. {0x07, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 64, ID_UNASSIGNED},
  38. };
  39. /* usbd Peripheral List */
  40. static struct ht32_usbd usbd_config[] =
  41. {
  42. #ifdef BSP_USING_USBD
  43. {
  44. .name = BSP_USING_USBD_NAME,
  45. .p_usbd_code = NULL,
  46. .irq = USB_IRQn,
  47. },
  48. #endif
  49. };
  50. /* Start of Frame (SOF) interrupt callbacks */
  51. void usbd_sof_callback(USBDCore_TypeDef *pCore)
  52. {
  53. udcd_t udcd = (udcd_t)pCore->pdata;
  54. rt_usbd_sof_handler(udcd);
  55. }
  56. /* USB reset interrupt */
  57. void usbd_reset_callback(USBDCore_TypeDef *pCore)
  58. {
  59. udcd_t udcd = (udcd_t)pCore->pdata;
  60. rt_usbd_reset_handler(udcd);
  61. }
  62. /* USB Suspend (Disconnect) Interrupt */
  63. void usbd_suspend_callback(USBDCore_TypeDef *pCore)
  64. {
  65. udcd_t udcd = (udcd_t)pCore->pdata;
  66. rt_usbd_disconnect_handler(udcd);
  67. }
  68. /* USB recovery (reconnect) interrupt */
  69. void usbd_resume_callback(USBDCore_TypeDef *pCore)
  70. {
  71. udcd_t udcd = (udcd_t)pCore->pdata;
  72. rt_usbd_connect_handler(udcd);
  73. }
  74. /* USB endpoint 0 interrupt */
  75. void usbd_setup_callback(USBDCore_TypeDef *pCore)
  76. {
  77. udcd_t udcd = (udcd_t)pCore->pdata;
  78. rt_usbd_ep0_setup_handler(udcd, (struct urequest *)&pCore->Device.Request);
  79. }
  80. /* Endpoint 0 input interrupt£¨Can be classified as other endpoint input interrupt£© */
  81. void usbd_ep0_in_callback(USBDCore_TypeDef *pCore)
  82. {
  83. udcd_t udcd = (udcd_t)pCore->pdata;
  84. rt_usbd_ep0_in_handler(udcd);
  85. }
  86. /* Endpoint 0 output interrupt£¨Can be classified as other endpoint input interrupt£© */
  87. void usbd_ep0_out_callback(USBDCore_TypeDef *pCore)
  88. {
  89. udcd_t udcd = (udcd_t)pCore->pdata;
  90. pCore->Device.Transfer.sByteLength = pCore->Device.Request.wLength;
  91. rt_usbd_ep0_out_handler(udcd, pCore->Device.Transfer.sByteLength);
  92. }
  93. /* Other endpoint input interrupt */
  94. void usbd_ep_in_callback(USBDCore_TypeDef *pCore, USBD_EPTn_Enum EPTn)
  95. {
  96. udcd_t udcd = (udcd_t)pCore->pdata;
  97. pCore->Device.Transfer.sByteLength = 0;
  98. rt_usbd_ep_in_handler(udcd, EPTn | 0x80, pCore->Device.Transfer.sByteLength);
  99. }
  100. /* Other Endpoint Output Interrupt */
  101. void usbd_ep_out_callback(USBDCore_TypeDef *pCore, USBD_EPTn_Enum EPTn)
  102. {
  103. udcd_t udcd = (udcd_t)pCore->pdata;
  104. rt_usbd_ep_out_handler(udcd, EPTn, pCore->ept_io->trans_len);
  105. }
  106. /* Setting the address */
  107. static rt_err_t ht32_set_address(rt_uint8_t address)
  108. {
  109. /* Setting the device address */
  110. p_usbd_instance->p_usbd_code->Info.CurrentStatus = USER_USB_STATE_ADDRESS;
  111. API_USB_SET_ADDR(address);
  112. return RT_EOK;
  113. }
  114. /* Configuration settings */
  115. static rt_err_t ht32_set_config(rt_uint8_t address)
  116. {
  117. return RT_EOK;
  118. }
  119. /* endpoint pause */
  120. static rt_err_t ht32_ep_set_stall(rt_uint8_t address)
  121. {
  122. if (0 == (address & 0x7f))
  123. API_USB_EPTn_SEND_STALL((USBD_EPTn_Enum)(address & 0x7f));
  124. else
  125. API_USB_EPTn_SET_HALT((USBD_EPTn_Enum)(address & 0x7f));
  126. return RT_EOK;
  127. }
  128. /* Endpoint reboot*/
  129. static rt_err_t ht32_ep_clear_stall(rt_uint8_t address)
  130. {
  131. if (0 != (address & 0x7f))
  132. {
  133. API_USB_EPTn_CLR_HALT((USBD_EPTn_Enum)(address & 0x7f));
  134. API_USB_EPTn_CLR_DTG((USBD_EPTn_Enum)(address & 0x7f));
  135. }
  136. return RT_EOK;
  137. }
  138. /* endpoint enable */
  139. static rt_err_t ht32_ep_enable(struct uendpoint *ep)
  140. {
  141. /* Functions not found in the firmware library at the moment */
  142. RT_ASSERT(ep != RT_NULL);
  143. RT_ASSERT(ep->ep_desc != RT_NULL);
  144. usbd_ep_enable(p_usbd_instance->p_usbd_code, ep->ep_desc->bEndpointAddress);
  145. return RT_EOK;
  146. }
  147. /* endpoint incapacity */
  148. static rt_err_t ht32_ep_disable(struct uendpoint *ep)
  149. {
  150. /* Functions not found in the firmware library at the moment */
  151. RT_ASSERT(ep != RT_NULL);
  152. RT_ASSERT(ep->ep_desc != RT_NULL);
  153. usbd_ep_disable(p_usbd_instance->p_usbd_code, ep->ep_desc->bEndpointAddress);
  154. return RT_EOK;
  155. }
  156. /* Endpoint Receive Data Preparation */
  157. static rt_ssize_t ht32_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
  158. {
  159. USBDCore_EPTReadOUTData((USBD_EPTn_Enum)(address & 0x7f), (uint32_t *)buffer, size);
  160. return size;
  161. }
  162. /* Endpoint reading data */
  163. static rt_ssize_t ht32_ep_read(rt_uint8_t address, void *buffer)
  164. {
  165. /* Do not read data from this function */
  166. rt_size_t size = 0;
  167. RT_ASSERT(buffer != RT_NULL);
  168. return size;
  169. }
  170. /* Endpoint Write Data */
  171. static rt_ssize_t ht32_ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
  172. {
  173. /* Use this function to write data to a USB endpoint */
  174. return USBDCore_EPTWriteINData((USBD_EPTn_Enum)(address & 0x7f), (uint32_t *)buffer, size);
  175. }
  176. /* Endpoint 0 transmit status */
  177. static rt_err_t ht32_ep0_send_status(void)
  178. {
  179. uint8_t Date = 0;
  180. /* State of send endpoint 0 */
  181. API_USB_EPTn_WRITE_IN(USBD_EPT0, (u32*)&Date, 0);
  182. return RT_EOK;
  183. }
  184. /* USB pause */
  185. static rt_err_t ht32_suspend(void)
  186. {
  187. return RT_EOK;
  188. }
  189. /* USB awakens */
  190. static rt_err_t ht32_wakeup(void)
  191. {
  192. return RT_EOK;
  193. }
  194. /* USB device interface function */
  195. const static struct udcd_ops _udc_ops =
  196. {
  197. .set_address = ht32_set_address,
  198. .set_config = ht32_set_config,
  199. .ep_set_stall = ht32_ep_set_stall,
  200. .ep_clear_stall = ht32_ep_clear_stall,
  201. .ep_enable = ht32_ep_enable,
  202. .ep_disable = ht32_ep_disable,
  203. .ep_read_prepare = ht32_ep_read_prepare,
  204. .ep_read = ht32_ep_read,
  205. .ep_write = ht32_ep_write,
  206. .ep0_send_status = ht32_ep0_send_status,
  207. .suspend = ht32_suspend,
  208. .wakeup = ht32_wakeup,
  209. };
  210. static void usbd_mainroutine(void)
  211. {
  212. USBDCore_MainRoutine(p_usbd_instance->p_usbd_code);
  213. }
  214. /* USB Device Initialisation Functions */
  215. static rt_err_t ht32_dcd_init(rt_device_t device)
  216. {
  217. /* USB object and interface initialisation, and turning on USB interrupts */
  218. USB_Configuration(p_usbd_instance->p_usbd_code);
  219. rt_thread_idle_sethook(usbd_mainroutine);
  220. return RT_EOK;
  221. }
  222. /* USB device registration function */
  223. int ht32_usbd_register(void)
  224. {
  225. rt_size_t obj_num;
  226. rt_err_t result = 0;
  227. int index;
  228. USBDCore_TypeDef *p_usbd_core = &p_usbd;
  229. /* Calculate how many USB devices */
  230. obj_num = sizeof(usbd_config) / sizeof(struct ht32_usbd);
  231. for (index = 0; index < obj_num; index++)
  232. {
  233. /* Request a udcd object memory and clear it. */
  234. udcd_t udcd = (udcd_t)rt_malloc(sizeof(struct udcd));
  235. if (udcd == RT_NULL)
  236. {
  237. rt_kprintf("udcd malloc failed\r\n");
  238. return -RT_ERROR;
  239. }
  240. rt_memset((void *)udcd, 0, sizeof(struct udcd));
  241. /* Assigning a value to the requested udcd object */
  242. udcd->parent.type = RT_Device_Class_USBDevice;
  243. udcd->parent.init = ht32_dcd_init;
  244. udcd->parent.user_data = p_usbd_core;
  245. udcd->ops = &_udc_ops;
  246. p_usbd_core->pdata = udcd;
  247. usbd_config[index].p_usbd_code = p_usbd_core;
  248. /* register endpoint infomation */
  249. udcd->ep_pool = endpoint_pool;
  250. udcd->ep0.id = &endpoint_pool[0];
  251. result = rt_device_register((rt_device_t)udcd, usbd_config[index].name, 0);
  252. RT_ASSERT(result == RT_EOK);
  253. p_usbd_instance = &usbd_config[index];
  254. result = rt_usb_device_init();
  255. RT_ASSERT(result == RT_EOK);
  256. }
  257. return result;
  258. }
  259. INIT_DEVICE_EXPORT(ht32_usbd_register);
  260. void USB_IRQHandler(void)
  261. {
  262. /* enter interrupt */
  263. rt_interrupt_enter();
  264. /* interrupt callback function */
  265. usbd_irq_handler(p_usbd_instance->p_usbd_code);
  266. /* leave interrupt */
  267. rt_interrupt_leave();
  268. }
  269. #endif /* RT_USING_USB_DEVICE */