furi_hal_usb.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. #include "furi_hal_version.h"
  2. #include "furi_hal_usb_i.h"
  3. #include "furi_hal_usb.h"
  4. #include <furi_hal_power.h>
  5. #include <stm32wbxx_ll_pwr.h>
  6. #include <furi.h>
  7. #include <toolbox/api_lock.h>
  8. #include "usb.h"
  9. #define TAG "FuriHalUsb"
  10. #define USB_RECONNECT_DELAY 500
  11. typedef enum {
  12. UsbApiEventTypeSetConfig,
  13. UsbApiEventTypeGetConfig,
  14. UsbApiEventTypeLock,
  15. UsbApiEventTypeUnlock,
  16. UsbApiEventTypeIsLocked,
  17. UsbApiEventTypeEnable,
  18. UsbApiEventTypeDisable,
  19. UsbApiEventTypeReinit,
  20. UsbApiEventTypeSetStateCallback,
  21. } UsbApiEventType;
  22. typedef struct {
  23. FuriHalUsbStateCallback callback;
  24. void* context;
  25. } UsbApiEventDataStateCallback;
  26. typedef struct {
  27. FuriHalUsbInterface* interface;
  28. void* context;
  29. } UsbApiEventDataInterface;
  30. typedef union {
  31. UsbApiEventDataStateCallback state_callback;
  32. UsbApiEventDataInterface interface;
  33. } UsbApiEventData;
  34. typedef union {
  35. bool bool_value;
  36. void* void_value;
  37. } UsbApiEventReturnData;
  38. typedef struct {
  39. FuriApiLock lock;
  40. UsbApiEventType type;
  41. UsbApiEventData data;
  42. UsbApiEventReturnData* return_data;
  43. } UsbApiEventMessage;
  44. typedef struct {
  45. FuriThread* thread;
  46. FuriMessageQueue* queue;
  47. bool enabled;
  48. bool connected;
  49. bool mode_lock;
  50. bool request_pending;
  51. FuriHalUsbInterface* interface;
  52. void* interface_context;
  53. FuriHalUsbStateCallback callback;
  54. void* callback_context;
  55. } UsbSrv;
  56. typedef enum {
  57. UsbEventReset = (1 << 0),
  58. UsbEventRequest = (1 << 1),
  59. UsbEventMessage = (1 << 2),
  60. } UsbEvent;
  61. #define USB_SRV_ALL_EVENTS (UsbEventReset | UsbEventRequest | UsbEventMessage)
  62. PLACE_IN_SECTION("MB_MEM2") static UsbSrv usb = {0};
  63. static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
  64. static uint32_t ubuf[0x20];
  65. usbd_device udev;
  66. static int32_t furi_hal_usb_thread(void* context);
  67. static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length);
  68. static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep);
  69. static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep);
  70. static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
  71. /* Low-level init */
  72. void furi_hal_usb_init(void) {
  73. LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  74. LL_PWR_EnableVddUSB();
  75. GPIO_InitStruct.Pin = LL_GPIO_PIN_11 | LL_GPIO_PIN_12;
  76. GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  77. GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  78. GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  79. GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  80. GPIO_InitStruct.Alternate = LL_GPIO_AF_10;
  81. LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  82. usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf));
  83. usbd_enable(&udev, true);
  84. usbd_reg_descr(&udev, usb_descriptor_get);
  85. usbd_reg_event(&udev, usbd_evt_susp, susp_evt);
  86. usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt);
  87. // Reset callback will be enabled after first mode change to avoid getting false reset events
  88. usb.enabled = false;
  89. usb.interface = NULL;
  90. NVIC_SetPriority(USB_LP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
  91. NVIC_SetPriority(USB_HP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
  92. NVIC_EnableIRQ(USB_LP_IRQn);
  93. NVIC_EnableIRQ(USB_HP_IRQn);
  94. usb.queue = furi_message_queue_alloc(1, sizeof(UsbApiEventMessage));
  95. usb.thread = furi_thread_alloc_ex("UsbDriver", 1024, furi_hal_usb_thread, NULL);
  96. furi_thread_mark_as_service(usb.thread);
  97. furi_thread_start(usb.thread);
  98. FURI_LOG_I(TAG, "Init OK");
  99. }
  100. static void furi_hal_usb_send_message(UsbApiEventMessage* message) {
  101. furi_message_queue_put(usb.queue, message, FuriWaitForever);
  102. furi_thread_flags_set(furi_thread_get_id(usb.thread), UsbEventMessage);
  103. api_lock_wait_unlock_and_free(message->lock);
  104. }
  105. bool furi_hal_usb_set_config(FuriHalUsbInterface* new_if, void* ctx) {
  106. UsbApiEventReturnData return_data = {
  107. .bool_value = false,
  108. };
  109. UsbApiEventMessage msg = {
  110. .lock = api_lock_alloc_locked(),
  111. .type = UsbApiEventTypeSetConfig,
  112. .data.interface =
  113. {
  114. .interface = new_if,
  115. .context = ctx,
  116. },
  117. .return_data = &return_data,
  118. };
  119. furi_hal_usb_send_message(&msg);
  120. return return_data.bool_value;
  121. }
  122. FuriHalUsbInterface* furi_hal_usb_get_config() {
  123. UsbApiEventReturnData return_data = {
  124. .void_value = NULL,
  125. };
  126. UsbApiEventMessage msg = {
  127. .lock = api_lock_alloc_locked(),
  128. .type = UsbApiEventTypeGetConfig,
  129. .return_data = &return_data,
  130. };
  131. furi_hal_usb_send_message(&msg);
  132. return return_data.void_value;
  133. }
  134. void furi_hal_usb_lock() {
  135. UsbApiEventMessage msg = {
  136. .lock = api_lock_alloc_locked(),
  137. .type = UsbApiEventTypeLock,
  138. };
  139. furi_hal_usb_send_message(&msg);
  140. }
  141. void furi_hal_usb_unlock() {
  142. UsbApiEventMessage msg = {
  143. .lock = api_lock_alloc_locked(),
  144. .type = UsbApiEventTypeUnlock,
  145. };
  146. furi_hal_usb_send_message(&msg);
  147. }
  148. bool furi_hal_usb_is_locked() {
  149. UsbApiEventReturnData return_data = {
  150. .bool_value = false,
  151. };
  152. UsbApiEventMessage msg = {
  153. .lock = api_lock_alloc_locked(),
  154. .type = UsbApiEventTypeIsLocked,
  155. .return_data = &return_data,
  156. };
  157. furi_hal_usb_send_message(&msg);
  158. return return_data.bool_value;
  159. }
  160. void furi_hal_usb_disable() {
  161. UsbApiEventMessage msg = {
  162. .lock = api_lock_alloc_locked(),
  163. .type = UsbApiEventTypeDisable,
  164. };
  165. furi_hal_usb_send_message(&msg);
  166. }
  167. void furi_hal_usb_enable() {
  168. UsbApiEventMessage msg = {
  169. .lock = api_lock_alloc_locked(),
  170. .type = UsbApiEventTypeEnable,
  171. };
  172. furi_hal_usb_send_message(&msg);
  173. }
  174. void furi_hal_usb_reinit() {
  175. UsbApiEventMessage msg = {
  176. .lock = api_lock_alloc_locked(),
  177. .type = UsbApiEventTypeReinit,
  178. };
  179. furi_hal_usb_send_message(&msg);
  180. }
  181. void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx) {
  182. UsbApiEventMessage msg = {
  183. .lock = api_lock_alloc_locked(),
  184. .type = UsbApiEventTypeSetStateCallback,
  185. .data.state_callback =
  186. {
  187. .callback = cb,
  188. .context = ctx,
  189. },
  190. };
  191. furi_hal_usb_send_message(&msg);
  192. }
  193. /* Get device / configuration descriptors */
  194. static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length) {
  195. const uint8_t dtype = req->wValue >> 8;
  196. const uint8_t dnumber = req->wValue & 0xFF;
  197. const void* desc;
  198. uint16_t len = 0;
  199. if(usb.interface == NULL) return usbd_fail;
  200. switch(dtype) {
  201. case USB_DTYPE_DEVICE:
  202. furi_thread_flags_set(furi_thread_get_id(usb.thread), UsbEventRequest);
  203. if(usb.callback != NULL) {
  204. usb.callback(FuriHalUsbStateEventDescriptorRequest, usb.callback_context);
  205. }
  206. desc = usb.interface->dev_descr;
  207. break;
  208. case USB_DTYPE_CONFIGURATION:
  209. desc = usb.interface->cfg_descr;
  210. len = ((struct usb_string_descriptor*)(usb.interface->cfg_descr))->wString[0];
  211. break;
  212. case USB_DTYPE_STRING:
  213. if(dnumber == UsbDevLang) {
  214. desc = &dev_lang_desc;
  215. } else if((dnumber == UsbDevManuf) && (usb.interface->str_manuf_descr != NULL)) {
  216. desc = usb.interface->str_manuf_descr;
  217. } else if((dnumber == UsbDevProduct) && (usb.interface->str_prod_descr != NULL)) {
  218. desc = usb.interface->str_prod_descr;
  219. } else if((dnumber == UsbDevSerial) && (usb.interface->str_serial_descr != NULL)) {
  220. desc = usb.interface->str_serial_descr;
  221. } else
  222. return usbd_fail;
  223. break;
  224. default:
  225. return usbd_fail;
  226. }
  227. if(desc == NULL) return usbd_fail;
  228. if(len == 0) {
  229. len = ((struct usb_header_descriptor*)desc)->bLength;
  230. }
  231. *address = (void*)desc;
  232. *length = len;
  233. return usbd_ack;
  234. }
  235. static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
  236. UNUSED(dev);
  237. UNUSED(event);
  238. UNUSED(ep);
  239. furi_thread_flags_set(furi_thread_get_id(usb.thread), UsbEventReset);
  240. if(usb.callback != NULL) {
  241. usb.callback(FuriHalUsbStateEventReset, usb.callback_context);
  242. }
  243. }
  244. static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
  245. UNUSED(dev);
  246. UNUSED(event);
  247. UNUSED(ep);
  248. if((usb.interface != NULL) && (usb.connected == true)) {
  249. usb.connected = false;
  250. usb.interface->suspend(&udev);
  251. furi_hal_power_insomnia_exit();
  252. }
  253. if(usb.callback != NULL) {
  254. usb.callback(FuriHalUsbStateEventSuspend, usb.callback_context);
  255. }
  256. }
  257. static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
  258. UNUSED(dev);
  259. UNUSED(event);
  260. UNUSED(ep);
  261. if((usb.interface != NULL) && (usb.connected == false)) {
  262. usb.connected = true;
  263. usb.interface->wakeup(&udev);
  264. furi_hal_power_insomnia_enter();
  265. }
  266. if(usb.callback != NULL) {
  267. usb.callback(FuriHalUsbStateEventWakeup, usb.callback_context);
  268. }
  269. }
  270. static void usb_process_mode_start(FuriHalUsbInterface* interface, void* context) {
  271. if(usb.interface != NULL) {
  272. usb.interface->deinit(&udev);
  273. }
  274. __disable_irq();
  275. usb.interface = interface;
  276. usb.interface_context = context;
  277. __enable_irq();
  278. if(interface != NULL) {
  279. interface->init(&udev, interface, context);
  280. usbd_reg_event(&udev, usbd_evt_reset, reset_evt);
  281. FURI_LOG_I(TAG, "USB Mode change done");
  282. usb.enabled = true;
  283. }
  284. }
  285. static void usb_process_mode_change(FuriHalUsbInterface* interface, void* context) {
  286. if(interface != usb.interface) {
  287. if(usb.enabled) {
  288. // Disable current interface
  289. susp_evt(&udev, 0, 0);
  290. usbd_connect(&udev, false);
  291. usb.enabled = false;
  292. furi_delay_ms(USB_RECONNECT_DELAY);
  293. }
  294. usb_process_mode_start(interface, context);
  295. }
  296. }
  297. static void usb_process_mode_reinit() {
  298. // Temporary disable callback to avoid getting false reset events
  299. usbd_reg_event(&udev, usbd_evt_reset, NULL);
  300. FURI_LOG_I(TAG, "USB Reinit");
  301. susp_evt(&udev, 0, 0);
  302. usbd_connect(&udev, false);
  303. usb.enabled = false;
  304. usbd_enable(&udev, false);
  305. usbd_enable(&udev, true);
  306. furi_delay_ms(USB_RECONNECT_DELAY);
  307. usb_process_mode_start(usb.interface, usb.interface_context);
  308. }
  309. static bool usb_process_set_config(FuriHalUsbInterface* interface, void* context) {
  310. if(usb.mode_lock) {
  311. return false;
  312. } else {
  313. usb_process_mode_change(interface, context);
  314. return true;
  315. }
  316. }
  317. static void usb_process_enable(bool enable) {
  318. if(enable) {
  319. if((!usb.enabled) && (usb.interface != NULL)) {
  320. usbd_connect(&udev, true);
  321. usb.enabled = true;
  322. FURI_LOG_I(TAG, "USB Enable");
  323. }
  324. } else {
  325. if(usb.enabled) {
  326. susp_evt(&udev, 0, 0);
  327. usbd_connect(&udev, false);
  328. usb.enabled = false;
  329. usb.request_pending = false;
  330. FURI_LOG_I(TAG, "USB Disable");
  331. }
  332. }
  333. }
  334. static void usb_process_message(UsbApiEventMessage* message) {
  335. switch(message->type) {
  336. case UsbApiEventTypeSetConfig:
  337. message->return_data->bool_value = usb_process_set_config(
  338. message->data.interface.interface, message->data.interface.context);
  339. break;
  340. case UsbApiEventTypeGetConfig:
  341. message->return_data->void_value = usb.interface;
  342. break;
  343. case UsbApiEventTypeLock:
  344. FURI_LOG_I(TAG, "Mode lock");
  345. usb.mode_lock = true;
  346. break;
  347. case UsbApiEventTypeUnlock:
  348. FURI_LOG_I(TAG, "Mode unlock");
  349. usb.mode_lock = false;
  350. break;
  351. case UsbApiEventTypeIsLocked:
  352. message->return_data->bool_value = usb.mode_lock;
  353. break;
  354. case UsbApiEventTypeDisable:
  355. usb_process_enable(false);
  356. break;
  357. case UsbApiEventTypeEnable:
  358. usb_process_enable(true);
  359. break;
  360. case UsbApiEventTypeReinit:
  361. usb_process_mode_reinit();
  362. break;
  363. case UsbApiEventTypeSetStateCallback:
  364. usb.callback = message->data.state_callback.callback;
  365. usb.callback_context = message->data.state_callback.context;
  366. break;
  367. }
  368. api_lock_unlock(message->lock);
  369. }
  370. static int32_t furi_hal_usb_thread(void* context) {
  371. UNUSED(context);
  372. uint8_t usb_wait_time = 0;
  373. if(furi_message_queue_get_count(usb.queue) > 0) {
  374. furi_thread_flags_set(furi_thread_get_id(usb.thread), UsbEventMessage);
  375. }
  376. while(true) {
  377. uint32_t flags = furi_thread_flags_wait(USB_SRV_ALL_EVENTS, FuriFlagWaitAny, 500);
  378. {
  379. UsbApiEventMessage message;
  380. if(furi_message_queue_get(usb.queue, &message, 0) == FuriStatusOk) {
  381. usb_process_message(&message);
  382. }
  383. }
  384. if((flags & FuriFlagError) == 0) {
  385. if(flags & UsbEventReset) {
  386. if(usb.enabled) {
  387. usb.request_pending = true;
  388. usb_wait_time = 0;
  389. }
  390. }
  391. if(flags & UsbEventRequest) {
  392. usb.request_pending = false;
  393. }
  394. } else if(usb.request_pending) {
  395. usb_wait_time++;
  396. if(usb_wait_time > 4) {
  397. usb_process_mode_reinit();
  398. usb.request_pending = false;
  399. }
  400. }
  401. }
  402. return 0;
  403. }