usb_stub_dev.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * USB Stub Device (Bulk-Transfer) class core.
  3. *
  4. * Copyright (c) 2018 Intel Corporation
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. */
  8. #include <kernel.h>
  9. #include <init.h>
  10. #include <string.h>
  11. #include <sys/byteorder.h>
  12. #include <usb/usb_device.h>
  13. #include <usb/usb_common.h>
  14. #include "usb_stub_descriptor.h"
  15. #ifdef CONFIG_NVRAM_CONFIG
  16. #include <drivers/nvram_config.h>
  17. #endif
  18. #define LOG_LEVEL CONFIG_SYS_LOG_USB_STUB_LEVEL
  19. #include <logging/log.h>
  20. LOG_MODULE_REGISTER(usb_stub_dev);
  21. #define USB_STUB_ENABLED BIT(0)
  22. #define USB_STUB_CONFIGURED BIT(1)
  23. static u8_t usb_stub_state;
  24. static struct k_sem stub_write_sem;
  25. static struct k_sem stub_read_sem;
  26. static void usb_stub_ep_write_cb(u8_t ep, enum usb_dc_ep_cb_status_code ep_status)
  27. {
  28. LOG_DBG("stub_ep_write_cb");
  29. k_sem_give(&stub_write_sem);
  30. }
  31. static void usb_stub_ep_read_cb(u8_t ep, enum usb_dc_ep_cb_status_code ep_status)
  32. {
  33. k_sem_give(&stub_read_sem);
  34. }
  35. /* USB endpoint configuration */
  36. static const struct usb_ep_cfg_data stub_ep_cfg[] = {
  37. {
  38. .ep_cb = usb_stub_ep_write_cb,
  39. .ep_addr = CONFIG_STUB_IN_EP_ADDR
  40. },
  41. {
  42. .ep_cb = usb_stub_ep_read_cb,
  43. .ep_addr = CONFIG_STUB_OUT_EP_ADDR
  44. },
  45. };
  46. bool usb_stub_enabled(void)
  47. {
  48. return usb_stub_state & USB_STUB_ENABLED;
  49. }
  50. bool usb_stub_configured(void)
  51. {
  52. return usb_stub_state & USB_STUB_CONFIGURED;
  53. }
  54. static void usb_stub_status_cb(enum usb_dc_status_code status, u8_t *param)
  55. {
  56. switch (status) {
  57. case USB_DC_ERROR:
  58. LOG_DBG("USB device error");
  59. break;
  60. case USB_DC_RESET:
  61. LOG_DBG("USB device reset detected");
  62. break;
  63. case USB_DC_CONNECTED:
  64. LOG_DBG("USB device connected");
  65. break;
  66. case USB_DC_CONFIGURED:
  67. usb_stub_state |= USB_STUB_CONFIGURED;
  68. LOG_DBG("USB device configured");
  69. break;
  70. case USB_DC_DISCONNECTED:
  71. LOG_DBG("USB device disconnected");
  72. break;
  73. case USB_DC_SUSPEND:
  74. LOG_DBG("USB device suspended");
  75. break;
  76. case USB_DC_RESUME:
  77. LOG_DBG("USB device resumed");
  78. break;
  79. case USB_DC_HIGHSPEED:
  80. LOG_DBG("USB device high-speed");
  81. break;
  82. case USB_DC_SOF:
  83. LOG_DBG("USB device sof-inter");
  84. break;
  85. case USB_DC_UNKNOWN:
  86. default:
  87. LOG_DBG("USB unknown state");
  88. break;
  89. }
  90. }
  91. static int usb_stub_class_handle_req(struct usb_setup_packet *setup, s32_t *len,
  92. u8_t **data)
  93. {
  94. LOG_DBG("class request bRequest: 0x%x bmRequestType: 0x%x len: %d",
  95. setup->bRequest, setup->bmRequestType, *len);
  96. return 0;
  97. }
  98. static int usb_stub_custom_handle_req(struct usb_setup_packet *setup, s32_t *len,
  99. u8_t **data)
  100. {
  101. LOG_DBG("custom request bRequest: 0x%x bmRequestType: 0x%x len: %d",
  102. setup->bRequest, setup->bmRequestType, *len);
  103. return -1;
  104. }
  105. static int usb_stub_vendor_handle_req(struct usb_setup_packet *setup, s32_t *len,
  106. u8_t **data)
  107. {
  108. LOG_DBG("vendor request bRequest: 0x%x bmRequestType: 0x%x len: %d",
  109. setup->bRequest, setup->bmRequestType, *len);
  110. return 0;
  111. }
  112. static const struct usb_cfg_data usb_stub_config = {
  113. .usb_device_description = NULL,
  114. .cb_usb_status = usb_stub_status_cb,
  115. .interface = {
  116. .class_handler = usb_stub_class_handle_req,
  117. .custom_handler = usb_stub_custom_handle_req,
  118. .vendor_handler = usb_stub_vendor_handle_req,
  119. },
  120. .num_endpoints = ARRAY_SIZE(stub_ep_cfg),
  121. .endpoint = stub_ep_cfg,
  122. };
  123. int usb_stub_ep_read(u8_t *data_buffer, u32_t data_len, k_timeout_t timeout)
  124. {
  125. int read_bytes;
  126. int ret;
  127. while (data_len) {
  128. if (k_sem_take(&stub_read_sem, timeout) != 0) {
  129. usb_dc_ep_flush(CONFIG_STUB_OUT_EP_ADDR);
  130. LOG_ERR("timeout");
  131. return -ETIME;
  132. }
  133. ret = usb_read(CONFIG_STUB_OUT_EP_ADDR, data_buffer,
  134. data_len, &read_bytes);
  135. if (ret < 0) {
  136. usb_dc_ep_flush(CONFIG_STUB_OUT_EP_ADDR);
  137. return ret;
  138. }
  139. data_buffer += read_bytes;
  140. data_len -= read_bytes;
  141. }
  142. return 0;
  143. }
  144. int usb_stub_ep_write(u8_t *data_buffer, u32_t data_len, k_timeout_t timeout)
  145. {
  146. int write_bytes;
  147. int ret;
  148. u8_t need_zero = 0;
  149. u8_t zero;
  150. switch (usb_device_speed()) {
  151. case USB_SPEED_FULL:
  152. if (data_len % CONFIG_STUB_EP_MPS == 0) {
  153. need_zero = 1;
  154. }
  155. break;
  156. case USB_SPEED_HIGH:
  157. if (data_len % USB_MAX_HS_BULK_MPS == 0) {
  158. need_zero = 1;
  159. }
  160. break;
  161. default:
  162. break;
  163. }
  164. while (data_len) {
  165. ret = usb_write(CONFIG_STUB_IN_EP_ADDR, data_buffer, data_len,
  166. &write_bytes);
  167. if (ret < 0) {
  168. usb_dc_ep_flush(CONFIG_STUB_IN_EP_ADDR);
  169. return ret;
  170. }
  171. if (k_sem_take(&stub_write_sem, timeout) != 0) {
  172. LOG_ERR("timeout");
  173. usb_dc_ep_flush(CONFIG_STUB_IN_EP_ADDR);
  174. return -ETIME;
  175. }
  176. data_buffer += write_bytes;
  177. data_len -= write_bytes;
  178. }
  179. if (need_zero) {
  180. ret = usb_write(CONFIG_STUB_IN_EP_ADDR, &zero, 0, NULL);
  181. if (ret < 0) {
  182. usb_dc_ep_flush(CONFIG_STUB_IN_EP_ADDR);
  183. return ret;
  184. }
  185. if (k_sem_take(&stub_write_sem, timeout) != 0) {
  186. printk("zero timeout");
  187. usb_dc_ep_flush(CONFIG_STUB_IN_EP_ADDR);
  188. return -ETIME;
  189. }
  190. }
  191. return 0;
  192. }
  193. static int usb_stub_fix_dev_sn(void)
  194. {
  195. int ret;
  196. #ifdef CONFIG_NVRAM_CONFIG
  197. int read_len;
  198. u8_t mac_str[CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN];
  199. read_len = nvram_config_get(CONFIG_USB_STUB_DEVICE_SN_NVRAM, mac_str, CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN);
  200. if (read_len < 0) {
  201. LOG_DBG("no sn data in nvram: %d", read_len);
  202. ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_STUB_DEVICE_SN, strlen(CONFIG_USB_STUB_DEVICE_SN));
  203. if (ret)
  204. return ret;
  205. } else {
  206. ret = usb_device_register_string_descriptor(DEV_SN_DESC, mac_str, read_len);
  207. if (ret)
  208. return ret;
  209. }
  210. #else
  211. ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_STUB_DEVICE_SN, strlen(CONFIG_USB_STUB_DEVICE_SN));
  212. if (ret)
  213. return ret;
  214. #endif
  215. return 0;
  216. }
  217. /*
  218. * API: initialize USB STUB
  219. */
  220. int usb_stub_init(struct device *dev)
  221. {
  222. int ret;
  223. k_sem_init(&stub_write_sem, 0, 1);
  224. k_sem_init(&stub_read_sem, 0, 1);
  225. /* register string descriptor */
  226. ret = usb_device_register_string_descriptor(MANUFACTURE_STR_DESC, CONFIG_USB_STUB_DEVICE_MANUFACTURER, strlen(CONFIG_USB_STUB_DEVICE_MANUFACTURER));
  227. if (ret) {
  228. return ret;
  229. }
  230. ret = usb_device_register_string_descriptor(PRODUCT_STR_DESC, CONFIG_USB_STUB_DEVICE_PRODUCT, strlen(CONFIG_USB_STUB_DEVICE_PRODUCT));
  231. if (ret) {
  232. return ret;
  233. }
  234. ret = usb_stub_fix_dev_sn();
  235. if (ret) {
  236. return ret;
  237. }
  238. /* register device descriptor */
  239. usb_device_register_descriptors(usb_stub_fs_descriptor, usb_stub_hs_descriptor);
  240. /* initialize the USB driver with the right configuration */
  241. ret = usb_set_config(&usb_stub_config);
  242. if (ret < 0) {
  243. return ret;
  244. }
  245. /* enable USB driver */
  246. ret = usb_enable(&usb_stub_config);
  247. if (ret < 0) {
  248. return ret;
  249. }
  250. usb_stub_state = USB_STUB_ENABLED;
  251. return 0;
  252. }
  253. /*
  254. * API: deinitialize USB Stub
  255. */
  256. int usb_stub_exit(void)
  257. {
  258. int ret;
  259. usb_stub_state = 0;
  260. ret = usb_disable();
  261. if (ret) {
  262. LOG_ERR("failed to disable USB Stub device");
  263. return ret;
  264. }
  265. usb_deconfig();
  266. return 0;
  267. }