usb.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #include "main.h"
  2. #include "usb.h"
  3. #include "usbd_core.h"
  4. #include "usb_std.h"
  5. #include "usb_desc.h"
  6. #include <furi.h>
  7. #include <furi_hal.h>
  8. #include <furi_hal_usb.h>
  9. #include "mtp.h"
  10. AppMTP* global_mtp;
  11. typedef enum {
  12. EventExit = 1 << 0,
  13. EventReset = 1 << 1,
  14. EventTx = 1 << 2,
  15. EventRx = 1 << 3,
  16. EventInterrupt = 1 << 4,
  17. EventAll = EventExit | EventReset | EventRx | EventTx | EventInterrupt,
  18. } MTPEvent;
  19. int32_t usb_mtp_worker(void* ctx) {
  20. AppMTP* mtp = ctx;
  21. usbd_device* dev = mtp->dev;
  22. uint8_t buffer[MTP_MAX_PACKET_SIZE];
  23. while(true) {
  24. MTPEvent flags = furi_thread_flags_wait(EventAll, FuriFlagWaitAny, FuriWaitForever);
  25. if(flags & EventExit) {
  26. FURI_LOG_W("MTP", "Worker thread exit");
  27. break;
  28. }
  29. if(flags & EventReset) {
  30. FURI_LOG_W("MTP", "USB reset");
  31. // Handle USB reset if necessary
  32. }
  33. if(flags & EventTx) {
  34. FURI_LOG_W("MTP", "USB Tx event");
  35. // Handle MTP RX/TX data here
  36. // Implement the logic for processing MTP requests, sending responses, etc.
  37. mtp->write_pending = false;
  38. }
  39. if(flags & EventRx) {
  40. FURI_LOG_W("MTP", "USB Rx event");
  41. int32_t readBytes = usbd_ep_read(dev, MTP_EP_IN_ADDR, buffer, MTP_MAX_PACKET_SIZE);
  42. FURI_LOG_I("MTP", "Received %ld bytes", readBytes);
  43. if(readBytes > 0) {
  44. mtp_handle_bulk(mtp, buffer, readBytes);
  45. }
  46. // Handle MTP RX/TX data here
  47. // Implement the logic for processing MTP requests, sending responses, etc.
  48. }
  49. if(flags & EventInterrupt) {
  50. FURI_LOG_W("MTP", "USB Interrupt event");
  51. // Handle MTP RX/TX data here
  52. // Implement the logic for processing MTP requests, sending responses, etc.
  53. }
  54. }
  55. return 0;
  56. }
  57. usbd_respond usb_mtp_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  58. UNUSED(callback);
  59. AppMTP* mtp = global_mtp;
  60. int value = -1;
  61. uint16_t w_index = req->wIndex;
  62. uint16_t w_value = req->wValue;
  63. uint16_t w_length = req->wLength;
  64. FURI_LOG_I(
  65. "MTP",
  66. "Control Request: bmRequestType=0x%02x, bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=0x%04x",
  67. req->bmRequestType,
  68. req->bRequest,
  69. w_value,
  70. w_index,
  71. w_length);
  72. if(req->bRequest == USB_STD_GET_DESCRIPTOR) {
  73. if((w_value >> 8) == USB_DTYPE_STRING && (w_value & 0xff) == 0xee) {
  74. FURI_LOG_I("MTP", "GET_DESCRIPTOR OS_STRING");
  75. value = (w_length < usb_mtp_os_string_len ? w_length : usb_mtp_os_string_len);
  76. memcpy(req->data, usb_mtp_os_string, value);
  77. return usbd_ack;
  78. }
  79. } else if((req->bmRequestType & USB_REQ_TYPE) == USB_REQ_VENDOR) {
  80. if(req->bRequest == 1 && (req->bmRequestType & USB_EPDIR_IN) &&
  81. (w_index == 4 || w_index == 5)) {
  82. FURI_LOG_I("MTP", "REQ_VENDOR - OS Descriptor");
  83. value =
  84. (w_length < sizeof(mtp_ext_config_desc) ? w_length : sizeof(mtp_ext_config_desc));
  85. memcpy(req->data, &mtp_ext_config_desc, value);
  86. return usbd_ack;
  87. }
  88. } else if((req->bmRequestType & USB_REQ_TYPE) == USB_REQ_CLASS) {
  89. value = mtp_handle_class_control(mtp, dev, req);
  90. }
  91. if(value >= 0) {
  92. if(value > w_length) {
  93. value = w_length;
  94. }
  95. usbd_ep_write(dev, 0x00, req->data, value);
  96. return usbd_ack;
  97. }
  98. return usbd_fail;
  99. }
  100. void usb_mtp_txrx(usbd_device* dev, uint8_t event, uint8_t ep) {
  101. UNUSED(ep);
  102. UNUSED(event);
  103. FURI_LOG_I("MTP", "USB Tx/Rx event");
  104. AppMTP* mtp = global_mtp;
  105. if(!mtp || mtp->dev != dev) return;
  106. if(ep == MTP_EP_OUT_ADDR) {
  107. furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventTx);
  108. } else if(ep == MTP_EP_IN_ADDR) {
  109. furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventRx);
  110. }
  111. }
  112. void usb_mtp_interrupt(usbd_device* dev, uint8_t event, uint8_t ep) {
  113. UNUSED(ep);
  114. UNUSED(event);
  115. FURI_LOG_I("MTP", "USB Interrupt");
  116. AppMTP* mtp = global_mtp;
  117. if(!mtp || mtp->dev != dev) return;
  118. furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventInterrupt);
  119. }
  120. usbd_respond usb_mtp_ep_config(usbd_device* dev, uint8_t cfg) {
  121. AppMTP* mtp = global_mtp;
  122. FURI_LOG_I("MTP", "USB EP config: cfg=%d", cfg);
  123. switch(cfg) {
  124. case 0: // deconfigure
  125. FURI_LOG_I("MTP", "USB deconfigure");
  126. usbd_ep_deconfig(dev, MTP_EP_IN_ADDR);
  127. usbd_ep_deconfig(dev, MTP_EP_OUT_ADDR);
  128. usbd_ep_deconfig(dev, MTP_EP_INT_IN_ADDR);
  129. usbd_reg_endpoint(dev, MTP_EP_IN_ADDR, NULL);
  130. usbd_reg_endpoint(dev, MTP_EP_OUT_ADDR, NULL);
  131. usbd_reg_endpoint(dev, MTP_EP_INT_IN_ADDR, NULL);
  132. if(mtp != NULL) mtp->usb_connected = false;
  133. break;
  134. case 1: // configure
  135. FURI_LOG_I("MTP", "USB configure");
  136. usbd_ep_config(dev, MTP_EP_OUT_ADDR, USB_EPTYPE_BULK, MTP_MAX_PACKET_SIZE);
  137. usbd_ep_config(dev, MTP_EP_IN_ADDR, USB_EPTYPE_BULK, MTP_MAX_PACKET_SIZE);
  138. usbd_ep_config(dev, MTP_EP_INT_IN_ADDR, USB_EPTYPE_INTERRUPT, USB_MAX_INTERRUPT_SIZE);
  139. usbd_reg_endpoint(dev, MTP_EP_OUT_ADDR, usb_mtp_txrx);
  140. usbd_reg_endpoint(dev, MTP_EP_IN_ADDR, usb_mtp_txrx);
  141. usbd_reg_endpoint(dev, MTP_EP_INT_IN_ADDR, usb_mtp_interrupt);
  142. if(mtp != NULL) mtp->usb_connected = true;
  143. //usbd_ep_write(dev, MTP_MAX_PACKET_SIZE, 0, 0);
  144. break;
  145. default:
  146. return usbd_fail;
  147. }
  148. return usbd_ack;
  149. }
  150. void usb_mtp_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
  151. UNUSED(intf);
  152. if(dev == NULL) {
  153. FURI_LOG_E("MTP", "dev is NULL");
  154. }
  155. // Disconnect the device first.
  156. usbd_connect(dev, false);
  157. AppMTP* mtp = ctx;
  158. global_mtp = mtp;
  159. mtp->dev = dev;
  160. FURI_LOG_I("MTP", "Initializing MTP device");
  161. // Register the configuration and control handlers
  162. usbd_reg_config(dev, usb_mtp_ep_config);
  163. usbd_reg_control(dev, usb_mtp_control);
  164. FURI_LOG_I("MTP", "Registered configuration and control handlers");
  165. // Connect the device
  166. usbd_connect(dev, true);
  167. FURI_LOG_I("MTP", "Connected device");
  168. // Initialize worker thread
  169. mtp->worker_thread = furi_thread_alloc();
  170. furi_thread_set_name(mtp->worker_thread, "FlipperMTPUsb");
  171. furi_thread_set_stack_size(mtp->worker_thread, 1024);
  172. furi_thread_set_context(mtp->worker_thread, ctx);
  173. furi_thread_set_callback(mtp->worker_thread, usb_mtp_worker);
  174. furi_thread_start(mtp->worker_thread);
  175. FURI_LOG_I("MTP", "Started worker thread");
  176. }
  177. void usb_mtp_deinit(usbd_device* dev) {
  178. usbd_reg_config(dev, NULL);
  179. usbd_reg_control(dev, NULL);
  180. FURI_LOG_I("MTP", "Unregistered configuration and control handlers");
  181. AppMTP* mtp = global_mtp;
  182. if(!mtp || mtp->dev != dev) {
  183. FURI_LOG_E("MTP", "deinit mtp_cur leak");
  184. return;
  185. }
  186. global_mtp = NULL;
  187. furi_assert(mtp->worker_thread);
  188. FURI_LOG_I("MTP", "Worker thread Condition pass");
  189. furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventExit);
  190. furi_thread_join(mtp->worker_thread);
  191. furi_thread_free(mtp->worker_thread);
  192. mtp->worker_thread = NULL;
  193. mtp->usb_connected = false;
  194. mtp->is_working = false;
  195. FURI_LOG_I("MTP", "Deinit worker thread");
  196. }
  197. void usb_mtp_wakeup(usbd_device* dev) {
  198. AppMTP* mtp = global_mtp;
  199. if(!mtp || mtp->dev != dev) return;
  200. FURI_LOG_I("MTP", "USB wakeup");
  201. mtp->usb_connected = true;
  202. UNUSED(dev);
  203. }
  204. void usb_mtp_suspend(usbd_device* dev) {
  205. AppMTP* mtp = global_mtp;
  206. if(!mtp || mtp->dev != dev) return;
  207. FURI_LOG_I("MTP", "USB suspend");
  208. mtp->usb_connected = false;
  209. furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventReset);
  210. }