You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 line
5.8KB

  1. /* USB EHCI Host for Teensy 3.6
  2. * Copyright 2017 Paul Stoffregen (paul@pjrc.com)
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included
  13. * in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <Arduino.h>
  24. #include "USBHost.h"
  25. MIDIDevice::MIDIDevice()
  26. {
  27. // TODO: free Device_t, Pipe_t & Transfer_t we will need
  28. driver_ready_for_device(this);
  29. }
  30. // Audio Class-Specific Descriptor Types (audio 1.0, page 99)
  31. // CS_UNDEFINED 0x20
  32. // CS_DEVICE 0x21
  33. // CS_CONFIGURATION 0x22
  34. // CS_STRING 0x23
  35. // CS_INTERFACE 0x24
  36. // CS_ENDPOINT 0x25
  37. // MS Class-Specific Interface Descriptor Subtypes (midi 1.0, page 36)
  38. // MS_DESCRIPTOR_UNDEFINED 0x00
  39. // MS_HEADER 0x01
  40. // MIDI_IN_JACK 0x02
  41. // MIDI_OUT_JACK 0x03
  42. // ELEMENT 0x04
  43. // MS Class-Specific Endpoint Descriptor Subtypes (midi 1.0, page 36)
  44. // DESCRIPTOR_UNDEFINED 0x00
  45. // MS_GENERAL 0x01
  46. // MS MIDI IN and OUT Jack types (midi 1.0, page 36)
  47. // JACK_TYPE_UNDEFINED 0x00
  48. // EMBEDDED 0x01
  49. // EXTERNAL 0x02
  50. // Endpoint Control Selectors (midi 1.0, page 36)
  51. // EP_CONTROL_UNDEFINED 0x00
  52. // ASSOCIATION_CONTROL 0x01
  53. bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
  54. {
  55. // only claim at interface level
  56. if (type != 1) return false;
  57. println("MIDIDevice claim this=", (uint32_t)this, HEX);
  58. println("len = ", len);
  59. const uint8_t *p = descriptors;
  60. const uint8_t *end = p + len;
  61. if (p[0] != 9 || p[1] != 4) return false; // interface descriptor
  62. //println(" bInterfaceClass=", p[5]);
  63. //println(" bInterfaceSubClass=", p[6]);
  64. if (p[5] != 1) return false; // bInterfaceClass: 1 = Audio class
  65. if (p[6] != 3) return false; // bInterfaceSubClass: 3 = MIDI
  66. p += 9;
  67. println(" Interface is MIDI");
  68. rx_ep = 0;
  69. tx_ep = 0;
  70. while (p < end) {
  71. len = *p;
  72. if (len < 4) return false; // all audio desc are at least 4 bytes
  73. if (p + len > end) return false; // reject if beyond end of data
  74. uint32_t type = p[1];
  75. //println("type: ", type);
  76. if (type == 4 || type == 11) break; // interface or IAD, not for us
  77. if (type == 0x24) { // 0x24 = Audio CS_INTERFACE, audio 1.0, page 99
  78. uint32_t subtype = p[2];
  79. //println("subtype: ", subtype);
  80. if (subtype == 1) {
  81. // Interface Header, midi 1.0, page 21
  82. println(" MIDI Header (ignored)");
  83. } else if (subtype == 2) {
  84. // MIDI IN Jack, midi 1.0, page 22
  85. println(" MIDI IN Jack (ignored)");
  86. } else if (subtype == 3) {
  87. // MIDI OUT Jack, midi 1.0, page 22
  88. println(" MIDI OUT Jack (ignored)");
  89. } else if (subtype == 4) {
  90. // Element Descriptor, midi 1.0, page 23-24
  91. println(" MIDI Element (ignored)");
  92. } else {
  93. return false; // unknown
  94. }
  95. } else if (type == 5) {
  96. // endpoint descriptor
  97. if (p[0] < 7) return false; // at least 7 bytes
  98. if (p[3] != 2) return false; // must be bulk type
  99. println(" MIDI Endpoint: ", p[2], HEX);
  100. switch (p[2] & 0xF0) {
  101. case 0x80:
  102. // IN endpoint
  103. if (rx_ep == 0) {
  104. rx_ep = p[2] & 0x0F;
  105. rx_size = p[4] | (p[5] << 8);
  106. println(" rx_size = ", rx_size);
  107. }
  108. break;
  109. case 0x00:
  110. // OUT endpoint
  111. if (tx_ep == 0) {
  112. tx_ep = p[2];
  113. tx_size = p[4] | (p[5] << 8);
  114. println(" tx_size = ", tx_size);
  115. }
  116. break;
  117. default:
  118. return false;
  119. }
  120. } else if (type == 37) {
  121. // MIDI endpoint info, midi 1.0: 6.2.2, page 26
  122. println(" MIDI Endpoint Jack Association (ignored)");
  123. } else {
  124. return false; // unknown
  125. }
  126. p += len;
  127. }
  128. // if an IN endpoint was found, create its pipe
  129. if (rx_ep && rx_size <= BUFFERSIZE) {
  130. rxpipe = new_Pipe(dev, 2, rx_ep, 1, rx_size);
  131. if (rxpipe) {
  132. rxpipe->callback_function = rx_callback;
  133. queue_Data_Transfer(rxpipe, buffer, rx_size, this);
  134. }
  135. } else {
  136. rxpipe = NULL;
  137. }
  138. // if an OUT endpoint was found, create its pipe
  139. if (tx_ep && tx_size <= BUFFERSIZE) {
  140. txpipe = new_Pipe(dev, 2, tx_ep, 0, tx_size);
  141. if (txpipe) {
  142. txpipe->callback_function = tx_callback;
  143. }
  144. } else {
  145. rxpipe = NULL;
  146. }
  147. // claim if either pipe created
  148. return (rxpipe || txpipe);
  149. }
  150. void MIDIDevice::rx_callback(const Transfer_t *transfer)
  151. {
  152. if (transfer->driver) {
  153. ((MIDIDevice *)(transfer->driver))->rx_data(transfer);
  154. }
  155. }
  156. void MIDIDevice::tx_callback(const Transfer_t *transfer)
  157. {
  158. if (transfer->driver) {
  159. ((MIDIDevice *)(transfer->driver))->tx_data(transfer);
  160. }
  161. }
  162. void MIDIDevice::rx_data(const Transfer_t *transfer)
  163. {
  164. println("MIDIDevice Receive");
  165. print(" MIDI Data: ");
  166. print_hexbytes(transfer->buffer, rx_size);
  167. // TODO: parse the new data
  168. queue_Data_Transfer(rxpipe, buffer, rx_size, this);
  169. }
  170. void MIDIDevice::tx_data(const Transfer_t *transfer)
  171. {
  172. println("MIDIDevice transmit complete");
  173. print(" MIDI Data: ");
  174. print_hexbytes(transfer->buffer, tx_size);
  175. // TODO: return the buffer to the pool...
  176. }
  177. void MIDIDevice::disconnect()
  178. {
  179. // TODO: free resources
  180. }