usb_midi_driver.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #include <furi.h>
  2. #include <furi_hal_console.h>
  3. #include <usb.h>
  4. #include <usb_std.h>
  5. #include "usb_midi_driver.h"
  6. #include "cm3_usb_audio.h"
  7. #include "cm3_usb_midi.h"
  8. // Appendix B. "Example: Simple MIDI Adapter" from "Universal Serial Bus Device Class Definition for MIDI Devices", Revision 1.0
  9. #define USB_VID 0x6666
  10. #define USB_PID 0x5119
  11. #define USB_EP0_SIZE 8
  12. #define USB_MIDI_EP_SIZE 64
  13. #define USB_MIDI_EP_IN 0x81
  14. #define USB_MIDI_EP_OUT 0x01
  15. #define EP_CFG_DECONFIGURE 0
  16. #define EP_CFG_CONFIGURE 1
  17. enum {
  18. USB_STR_ZERO,
  19. USB_STR_MANUFACTURER,
  20. USB_STR_PRODUCT,
  21. USB_STR_SERIAL_NUMBER,
  22. };
  23. /*
  24. B.1 Device Descriptor
  25. */
  26. static const struct usb_device_descriptor device_descriptor = {
  27. .bLength = sizeof(struct usb_device_descriptor),
  28. .bDescriptorType = USB_DTYPE_DEVICE,
  29. .bcdUSB = VERSION_BCD(2, 0, 0), // was 0x0110, 1.10 - current revision of USBspecification.
  30. .bDeviceClass = USB_CLASS_PER_INTERFACE,
  31. .bDeviceSubClass = USB_SUBCLASS_NONE,
  32. .bDeviceProtocol = USB_PROTO_NONE,
  33. .bMaxPacketSize0 = USB_EP0_SIZE,
  34. .idVendor = USB_VID,
  35. .idProduct = USB_PID,
  36. .bcdDevice = VERSION_BCD(1, 0, 0),
  37. .iManufacturer = USB_STR_MANUFACTURER,
  38. .iProduct = USB_STR_PRODUCT,
  39. .iSerialNumber = USB_STR_SERIAL_NUMBER,
  40. .bNumConfigurations = 1,
  41. };
  42. struct usb_audio_header_descriptor {
  43. struct usb_audio_header_descriptor_head head;
  44. struct usb_audio_header_descriptor_body body;
  45. } __attribute__((packed));
  46. struct usb_midi_jacks_descriptor {
  47. struct usb_midi_header_descriptor header;
  48. struct usb_midi_in_jack_descriptor in_embedded;
  49. struct usb_midi_in_jack_descriptor in_external;
  50. struct usb_midi_out_jack_descriptor out_embedded;
  51. struct usb_midi_out_jack_descriptor out_external;
  52. } __attribute__((packed));
  53. struct MidiConfigDescriptor {
  54. /*
  55. B.2 Configuration Descriptor
  56. */
  57. struct usb_config_descriptor config;
  58. /*
  59. B.3 AudioControl Interface Descriptors
  60. The AudioControl interface describes the device structure (audio function topology)
  61. and is used to manipulate the Audio Controls. This device has no audio function incorporated.
  62. However, the AudioControl interface is mandatory and therefore both the standard AC interface
  63. descriptor and the classspecific AC interface descriptor must be present.
  64. The class-specific AC interface descriptor only contains the header descriptor.
  65. */
  66. // B.3.1 Standard AC Interface Descriptor
  67. struct usb_interface_descriptor audio_control_iface;
  68. // B.3.2 Class-specific AC Interface Descriptor
  69. struct usb_audio_header_descriptor audio_control_header;
  70. /*
  71. B.4 MIDIStreaming Interface Descriptors
  72. */
  73. // B.4.1 Standard MS Interface Descriptor
  74. struct usb_interface_descriptor midi_streaming_iface;
  75. // B.4.2 Class-specific MS Interface Descriptor
  76. // B.4.3 MIDI IN Jack Descriptor
  77. // B.4.4 MIDI OUT Jack Descriptor
  78. struct usb_midi_jacks_descriptor midi_jacks;
  79. /*
  80. B.5 Bulk OUT Endpoint Descriptors
  81. */
  82. // B.5.1 Standard Bulk OUT Endpoint Descriptor
  83. struct usb_endpoint_descriptor bulk_out;
  84. // B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor
  85. struct usb_midi_endpoint_descriptor midi_bulk_out;
  86. /*
  87. B.6 Bulk IN Endpoint Descriptors
  88. */
  89. // B.6.1 Standard Bulk IN Endpoint Descriptor
  90. struct usb_endpoint_descriptor bulk_in;
  91. // B.6.2 Class-specific MS Bulk IN Endpoint Descriptor
  92. struct usb_midi_endpoint_descriptor midi_bulk_in;
  93. } __attribute__((packed));
  94. static const struct MidiConfigDescriptor config_descriptor = {
  95. .config =
  96. {
  97. .bLength = sizeof(struct usb_config_descriptor),
  98. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  99. .wTotalLength = sizeof(struct MidiConfigDescriptor),
  100. .bNumInterfaces = 2, /* control and data */
  101. .bConfigurationValue = 1,
  102. .iConfiguration = 0,
  103. .bmAttributes = USB_CFG_ATTR_RESERVED,
  104. .bMaxPower = USB_CFG_POWER_MA(100),
  105. },
  106. .audio_control_iface =
  107. {
  108. .bLength = sizeof(struct usb_interface_descriptor),
  109. .bDescriptorType = USB_DTYPE_INTERFACE,
  110. .bInterfaceNumber = 0,
  111. .bAlternateSetting = 0,
  112. .bNumEndpoints = 0,
  113. .bInterfaceClass = USB_CLASS_AUDIO,
  114. .bInterfaceSubClass = USB_AUDIO_SUBCLASS_CONTROL,
  115. .bInterfaceProtocol = USB_PROTO_NONE,
  116. .iInterface = 0,
  117. },
  118. .audio_control_header =
  119. {
  120. .head =
  121. {
  122. .bLength = sizeof(struct usb_audio_header_descriptor),
  123. .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
  124. .bDescriptorSubtype = USB_AUDIO_TYPE_HEADER,
  125. .bcdADC = VERSION_BCD(1, 0, 0),
  126. .wTotalLength = sizeof(struct usb_audio_header_descriptor),
  127. .bInCollection = 1,
  128. },
  129. .body =
  130. {
  131. .baInterfaceNr = 1,
  132. },
  133. },
  134. .midi_streaming_iface =
  135. {
  136. .bLength = sizeof(struct usb_interface_descriptor),
  137. .bDescriptorType = USB_DTYPE_INTERFACE,
  138. .bInterfaceNumber = 1,
  139. .bAlternateSetting = 0,
  140. .bNumEndpoints = 2,
  141. .bInterfaceClass = USB_CLASS_AUDIO,
  142. .bInterfaceSubClass = USB_AUDIO_SUBCLASS_MIDISTREAMING,
  143. .bInterfaceProtocol = USB_PROTO_NONE,
  144. .iInterface = 0,
  145. },
  146. .midi_jacks =
  147. {
  148. .header =
  149. {
  150. .bLength = sizeof(struct usb_midi_header_descriptor),
  151. .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
  152. .bDescriptorSubtype = USB_MIDI_SUBTYPE_MS_HEADER,
  153. .bcdMSC = VERSION_BCD(1, 0, 0),
  154. .wTotalLength = sizeof(struct usb_midi_jacks_descriptor),
  155. },
  156. .in_embedded =
  157. {
  158. .bLength = sizeof(struct usb_midi_in_jack_descriptor),
  159. .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
  160. .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_IN_JACK,
  161. .bJackType = USB_MIDI_JACK_TYPE_EMBEDDED,
  162. .bJackID = 0x01,
  163. .iJack = 0x00,
  164. },
  165. .in_external =
  166. {
  167. .bLength = sizeof(struct usb_midi_in_jack_descriptor),
  168. .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
  169. .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_IN_JACK,
  170. .bJackType = USB_MIDI_JACK_TYPE_EXTERNAL,
  171. .bJackID = 0x02,
  172. .iJack = 0x00,
  173. },
  174. .out_embedded =
  175. {
  176. .head =
  177. {
  178. .bLength = sizeof(struct usb_midi_out_jack_descriptor),
  179. .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
  180. .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_OUT_JACK,
  181. .bJackType = USB_MIDI_JACK_TYPE_EMBEDDED,
  182. .bJackID = 0x03,
  183. .bNrInputPins = 1,
  184. },
  185. .source[0] =
  186. {
  187. .baSourceID = 0x02,
  188. .baSourcePin = 0x01,
  189. },
  190. .tail =
  191. {
  192. .iJack = 0x00,
  193. },
  194. },
  195. .out_external =
  196. {
  197. .head =
  198. {
  199. .bLength = sizeof(struct usb_midi_out_jack_descriptor),
  200. .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
  201. .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_OUT_JACK,
  202. .bJackType = USB_MIDI_JACK_TYPE_EXTERNAL,
  203. .bJackID = 0x04,
  204. .bNrInputPins = 1,
  205. },
  206. .source[0] =
  207. {
  208. .baSourceID = 0x01,
  209. .baSourcePin = 0x01,
  210. },
  211. .tail =
  212. {
  213. .iJack = 0x00,
  214. },
  215. },
  216. },
  217. .bulk_out =
  218. {
  219. .bLength = sizeof(struct usb_endpoint_descriptor),
  220. .bDescriptorType = USB_DTYPE_ENDPOINT,
  221. .bEndpointAddress = USB_MIDI_EP_OUT,
  222. .bmAttributes = USB_EPTYPE_BULK,
  223. .wMaxPacketSize = USB_MIDI_EP_SIZE,
  224. .bInterval = 0,
  225. },
  226. .midi_bulk_out =
  227. {
  228. .head =
  229. {
  230. .bLength = sizeof(struct usb_midi_endpoint_descriptor),
  231. .bDescriptorType = USB_AUDIO_DT_CS_ENDPOINT,
  232. .bDescriptorSubType = USB_MIDI_SUBTYPE_MS_GENERAL,
  233. .bNumEmbMIDIJack = 1,
  234. },
  235. .jack[0] =
  236. {
  237. .baAssocJackID = 0x01,
  238. },
  239. },
  240. .bulk_in =
  241. {
  242. .bLength = sizeof(struct usb_endpoint_descriptor),
  243. .bDescriptorType = USB_DTYPE_ENDPOINT,
  244. .bEndpointAddress = USB_MIDI_EP_IN,
  245. .bmAttributes = USB_EPTYPE_BULK,
  246. .wMaxPacketSize = USB_MIDI_EP_SIZE,
  247. .bInterval = 0,
  248. },
  249. .midi_bulk_in =
  250. {
  251. .head =
  252. {
  253. .bLength = sizeof(struct usb_midi_endpoint_descriptor),
  254. .bDescriptorType = USB_AUDIO_DT_CS_ENDPOINT,
  255. .bDescriptorSubType = USB_MIDI_SUBTYPE_MS_GENERAL,
  256. .bNumEmbMIDIJack = 1,
  257. },
  258. .jack[0] =
  259. {
  260. .baAssocJackID = 0x03,
  261. },
  262. },
  263. };
  264. static const struct usb_string_descriptor dev_manufacturer_string =
  265. USB_STRING_DESC("Flipper Devices Inc.");
  266. static const struct usb_string_descriptor dev_product_string =
  267. USB_STRING_DESC("Flipper MIDI Device");
  268. static const struct usb_string_descriptor dev_serial_number_string =
  269. USB_STRING_DESC("Serial Number");
  270. static void midi_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
  271. static void midi_deinit(usbd_device* dev);
  272. static void midi_on_wakeup(usbd_device* dev);
  273. static void midi_on_suspend(usbd_device* dev);
  274. static usbd_respond midi_ep_config(usbd_device* dev, uint8_t cfg);
  275. static usbd_respond midi_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  276. FuriHalUsbInterface midi_usb_interface = {
  277. .init = midi_init,
  278. .deinit = midi_deinit,
  279. .wakeup = midi_on_wakeup,
  280. .suspend = midi_on_suspend,
  281. .dev_descr = (struct usb_device_descriptor*)&device_descriptor,
  282. .cfg_descr = (void*)&config_descriptor,
  283. };
  284. typedef struct {
  285. usbd_device* dev;
  286. MidiRxCallback rx_callback;
  287. void* context;
  288. FuriSemaphore* semaphore_tx;
  289. bool connected;
  290. } MidiUsb;
  291. static MidiUsb midi_usb;
  292. void midi_usb_set_context(void* context) {
  293. midi_usb.context = context;
  294. }
  295. void midi_usb_set_rx_callback(MidiRxCallback callback) {
  296. midi_usb.rx_callback = callback;
  297. }
  298. size_t midi_usb_rx(uint8_t* buffer, size_t size) {
  299. size_t len = usbd_ep_read(midi_usb.dev, USB_MIDI_EP_OUT, buffer, size);
  300. return len;
  301. }
  302. size_t midi_usb_tx(uint8_t* buffer, uint8_t size) {
  303. if((midi_usb.semaphore_tx == NULL) || (midi_usb.connected == false)) return 0;
  304. furi_check(furi_semaphore_acquire(midi_usb.semaphore_tx, FuriWaitForever) == FuriStatusOk);
  305. if(midi_usb.connected) {
  306. int32_t len = usbd_ep_write(midi_usb.dev, USB_MIDI_EP_IN, buffer, size);
  307. return len;
  308. } else {
  309. return 0;
  310. }
  311. }
  312. static void midi_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
  313. UNUSED(intf);
  314. UNUSED(ctx);
  315. midi_usb_interface.str_manuf_descr = (void*)&dev_manufacturer_string;
  316. midi_usb_interface.str_prod_descr = (void*)&dev_product_string;
  317. midi_usb_interface.str_serial_descr = (void*)&dev_serial_number_string;
  318. midi_usb_interface.dev_descr->idVendor = USB_VID;
  319. midi_usb_interface.dev_descr->idProduct = USB_PID;
  320. midi_usb.dev = dev;
  321. if(midi_usb.semaphore_tx == NULL) midi_usb.semaphore_tx = furi_semaphore_alloc(1, 1);
  322. usbd_reg_config(dev, midi_ep_config);
  323. usbd_reg_control(dev, midi_control);
  324. usbd_connect(dev, true);
  325. }
  326. static void midi_deinit(usbd_device* dev) {
  327. midi_usb.connected = false;
  328. midi_usb.dev = NULL;
  329. furi_semaphore_free(midi_usb.semaphore_tx);
  330. usbd_reg_config(dev, NULL);
  331. usbd_reg_control(dev, NULL);
  332. }
  333. static void midi_on_wakeup(usbd_device* dev) {
  334. UNUSED(dev);
  335. if(!midi_usb.connected) {
  336. midi_usb.connected = true;
  337. }
  338. }
  339. static void midi_on_suspend(usbd_device* dev) {
  340. UNUSED(dev);
  341. if(midi_usb.connected) {
  342. midi_usb.connected = false;
  343. }
  344. }
  345. static void midi_tx_rx(usbd_device* dev, uint8_t event, uint8_t ep) {
  346. UNUSED(dev);
  347. UNUSED(ep);
  348. switch(event) {
  349. case usbd_evt_eptx:
  350. furi_semaphore_release(midi_usb.semaphore_tx);
  351. break;
  352. case usbd_evt_eprx:
  353. if(midi_usb.rx_callback != NULL) {
  354. midi_usb.rx_callback(midi_usb.context);
  355. }
  356. break;
  357. default:
  358. break;
  359. }
  360. }
  361. static usbd_respond midi_ep_config(usbd_device* dev, uint8_t cfg) {
  362. switch(cfg) {
  363. case EP_CFG_DECONFIGURE:
  364. usbd_ep_deconfig(dev, USB_MIDI_EP_OUT);
  365. usbd_ep_deconfig(dev, USB_MIDI_EP_IN);
  366. usbd_reg_endpoint(dev, USB_MIDI_EP_OUT, NULL);
  367. usbd_reg_endpoint(dev, USB_MIDI_EP_IN, NULL);
  368. return usbd_ack;
  369. case EP_CFG_CONFIGURE:
  370. usbd_ep_config(dev, USB_MIDI_EP_OUT, USB_EPTYPE_BULK, USB_MIDI_EP_SIZE);
  371. usbd_ep_config(dev, USB_MIDI_EP_IN, USB_EPTYPE_BULK, USB_MIDI_EP_SIZE);
  372. usbd_reg_endpoint(dev, USB_MIDI_EP_OUT, midi_tx_rx);
  373. usbd_reg_endpoint(dev, USB_MIDI_EP_IN, midi_tx_rx);
  374. return usbd_ack;
  375. default:
  376. return usbd_fail;
  377. }
  378. }
  379. static usbd_respond midi_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  380. UNUSED(dev);
  381. UNUSED(req);
  382. UNUSED(callback);
  383. return usbd_fail;
  384. }