PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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_t36.h" // Read this header first for key info
  25. // Printing of specific data structures. When this is enabled,
  26. // a tremendous amount of debug printing occurs. It's done all
  27. // from interrupt context, so this should never normally be
  28. // enabled for regular programs that print from the Arduino sketch.
  29. #ifdef USBHOST_PRINT_DEBUG
  30. void USBHost::print_(const Transfer_t *transfer)
  31. {
  32. if (!((uint32_t)transfer & 0xFFFFFFE0)) return;
  33. USBHDBGSerial.print("Transfer @ ");
  34. USBHDBGSerial.println(((uint32_t)transfer & 0xFFFFFFE0), HEX);
  35. USBHDBGSerial.print(" next: ");
  36. USBHDBGSerial.println(transfer->qtd.next, HEX);
  37. USBHDBGSerial.print(" anext: ");
  38. USBHDBGSerial.println(transfer->qtd.alt_next, HEX);
  39. USBHDBGSerial.print(" token: ");
  40. USBHDBGSerial.println(transfer->qtd.token, HEX);
  41. USBHDBGSerial.print(" bufs: ");
  42. for (int i=0; i < 5; i++) {
  43. USBHDBGSerial.print(transfer->qtd.buffer[i], HEX);
  44. if (i < 4) USBHDBGSerial.print(',');
  45. }
  46. USBHDBGSerial.println();
  47. }
  48. void USBHost::print_(const Transfer_t *first, const Transfer_t *last)
  49. {
  50. USBHDBGSerial.print("Transfer Followup List ");
  51. USBHDBGSerial.print((uint32_t)first, HEX);
  52. USBHDBGSerial.print(" to ");
  53. USBHDBGSerial.println((uint32_t)last, HEX);
  54. USBHDBGSerial.println(" forward:");
  55. while (first) {
  56. USBHDBGSerial.print(" ");
  57. USBHDBGSerial.print((uint32_t)first, HEX);
  58. print_token(first->qtd.token);
  59. first = first->next_followup;
  60. }
  61. USBHDBGSerial.println(" backward:");
  62. while (last) {
  63. USBHDBGSerial.print(" ");
  64. USBHDBGSerial.print((uint32_t)last, HEX);
  65. print_token(last->qtd.token);
  66. last = last->prev_followup;
  67. }
  68. }
  69. void USBHost::print_token(uint32_t token)
  70. {
  71. switch ((token >> 8) & 3) {
  72. case 0:
  73. USBHDBGSerial.print(" OUT ");
  74. USBHDBGSerial.println((token >> 16) & 0x7FFF);
  75. break;
  76. case 1:
  77. USBHDBGSerial.print(" IN ");
  78. USBHDBGSerial.println((token >> 16) & 0x7FFF);
  79. break;
  80. case 2:
  81. USBHDBGSerial.println(" SETUP");
  82. break;
  83. default:
  84. USBHDBGSerial.println(" unknown");
  85. }
  86. }
  87. void USBHost::print_(const Pipe_t *pipe)
  88. {
  89. if (!((uint32_t)pipe & 0xFFFFFFE0)) return;
  90. USBHDBGSerial.print("Pipe ");
  91. if (pipe->type == 0) USBHDBGSerial.print("control");
  92. else if (pipe->type == 1) USBHDBGSerial.print("isochronous");
  93. else if (pipe->type == 2) USBHDBGSerial.print("bulk");
  94. else if (pipe->type == 3) USBHDBGSerial.print("interrupt");
  95. USBHDBGSerial.print(pipe->direction ? " IN" : " OUT");
  96. USBHDBGSerial.print(" @ ");
  97. USBHDBGSerial.println((uint32_t)pipe, HEX);
  98. USBHDBGSerial.print(" horiz link: ");
  99. USBHDBGSerial.println(pipe->qh.horizontal_link, HEX);
  100. USBHDBGSerial.print(" capabilities: ");
  101. USBHDBGSerial.print(pipe->qh.capabilities[0], HEX);
  102. USBHDBGSerial.print(',');
  103. USBHDBGSerial.println(pipe->qh.capabilities[1], HEX);
  104. USBHDBGSerial.println(" overlay:");
  105. USBHDBGSerial.print(" cur: ");
  106. USBHDBGSerial.println(pipe->qh.current, HEX);
  107. USBHDBGSerial.print(" next: ");
  108. USBHDBGSerial.println(pipe->qh.next, HEX);
  109. USBHDBGSerial.print(" anext: ");
  110. USBHDBGSerial.println(pipe->qh.alt_next, HEX);
  111. USBHDBGSerial.print(" token: ");
  112. USBHDBGSerial.println(pipe->qh.token, HEX);
  113. USBHDBGSerial.print(" bufs: ");
  114. for (int i=0; i < 5; i++) {
  115. USBHDBGSerial.print(pipe->qh.buffer[i], HEX);
  116. if (i < 4) USBHDBGSerial.print(',');
  117. }
  118. USBHDBGSerial.println();
  119. const Transfer_t *t = (Transfer_t *)pipe->qh.next;
  120. while (((uint32_t)t & 0xFFFFFFE0)) {
  121. print_(t);
  122. t = (Transfer_t *)t->qtd.next;
  123. }
  124. //USBHDBGSerial.print();
  125. }
  126. void USBHost::print_driverlist(const char *name, const USBDriver *driver)
  127. {
  128. USBHDBGSerial.print("USBDriver (");
  129. USBHDBGSerial.print(name);
  130. USBHDBGSerial.print(") list: ");
  131. if (driver == NULL) {
  132. USBHDBGSerial.println("(empty");
  133. return;
  134. }
  135. uint32_t count=0;
  136. for (const USBDriver *p = driver; p; p = p->next) {
  137. USBHDBGSerial.print((uint32_t)p, HEX);
  138. if (p->next) USBHDBGSerial.print(" -> ");
  139. if (++count > 30) {
  140. USBHDBGSerial.println("abort:list too long");
  141. return;
  142. }
  143. }
  144. USBHDBGSerial.println();
  145. }
  146. void USBHost::print_qh_list(const Pipe_t *list)
  147. {
  148. if (!list) {
  149. USBHDBGSerial.println("(empty)");
  150. return;
  151. }
  152. const Pipe_t *node = list;
  153. while (1) {
  154. USBHDBGSerial.print((uint32_t)node, HEX);
  155. node = (const Pipe_t *)(node->qh.horizontal_link & 0xFFFFFFE0);
  156. if (!node) break;
  157. if (node == list) {
  158. USBHDBGSerial.print(" (loops)");
  159. break;
  160. }
  161. USBHDBGSerial.print(" -> ");
  162. }
  163. USBHDBGSerial.println();
  164. }
  165. static void print_class_subclass_protocol(uint8_t c, uint8_t s, uint8_t p)
  166. {
  167. USBHDBGSerial.print(c);
  168. if (c == 3) USBHDBGSerial.print("(HID)");
  169. if (c == 8) USBHDBGSerial.print("(Mass Storage)");
  170. if (c == 9) USBHDBGSerial.print("(Hub)");
  171. USBHDBGSerial.print(" / ");
  172. USBHDBGSerial.print(s);
  173. if (c == 3 && s == 1) USBHDBGSerial.print("(Boot)");
  174. if (c == 8 && s == 6) USBHDBGSerial.print("(SCSI)");
  175. USBHDBGSerial.print(" / ");
  176. USBHDBGSerial.print(p);
  177. if (c == 3 && s == 1 && p == 1) USBHDBGSerial.print("(Keyboard)");
  178. if (c == 3 && s == 1 && p == 2) USBHDBGSerial.print("(Mouse)");
  179. if (c == 8 && s == 6 && p == 0x50) USBHDBGSerial.print("(Bulk Only)");
  180. if (c == 8 && s == 6 && p == 0x62) USBHDBGSerial.print("(UAS)");
  181. if (c == 9 && s == 0 && p == 1) USBHDBGSerial.print("(Single-TT)");
  182. if (c == 9 && s == 0 && p == 2) USBHDBGSerial.print("(Multi-TT)");
  183. USBHDBGSerial.println();
  184. }
  185. void USBHost::print_device_descriptor(const uint8_t *p)
  186. {
  187. USBHDBGSerial.println("Device Descriptor:");
  188. USBHDBGSerial.print(" ");
  189. print_hexbytes(p, p[0]);
  190. if (p[0] != 18) {
  191. USBHDBGSerial.println("error: device must be 18 bytes");
  192. return;
  193. }
  194. if (p[1] != 1) {
  195. USBHDBGSerial.println("error: device must type 1");
  196. return;
  197. }
  198. USBHDBGSerial.printf(" VendorID = %04X, ProductID = %04X, Version = %04X",
  199. p[8] | (p[9] << 8), p[10] | (p[11] << 8), p[12] | (p[13] << 8));
  200. USBHDBGSerial.println();
  201. USBHDBGSerial.print(" Class/Subclass/Protocol = ");
  202. print_class_subclass_protocol(p[4], p[5], p[6]);
  203. USBHDBGSerial.print(" Number of Configurations = ");
  204. USBHDBGSerial.println(p[17]);
  205. }
  206. void USBHost::print_config_descriptor(const uint8_t *p, uint32_t maxlen)
  207. {
  208. // Descriptor Types: (USB 2.0, page 251)
  209. USBHDBGSerial.println("Configuration Descriptor:");
  210. USBHDBGSerial.print(" ");
  211. print_hexbytes(p, p[0]);
  212. if (p[0] != 9) {
  213. USBHDBGSerial.println("error: config must be 9 bytes");
  214. return;
  215. }
  216. if (p[1] != 2) {
  217. USBHDBGSerial.println("error: config must type 2");
  218. return;
  219. }
  220. USBHDBGSerial.print(" NumInterfaces = ");
  221. USBHDBGSerial.println(p[4]);
  222. USBHDBGSerial.print(" ConfigurationValue = ");
  223. USBHDBGSerial.println(p[5]);
  224. uint32_t len = p[2] | (p[3] << 8);
  225. if (len > maxlen) len = maxlen;
  226. len -= p[0];
  227. p += 9;
  228. while (len > 0) {
  229. if (p[0] > len) {
  230. USBHDBGSerial.print(" ");
  231. print_hexbytes(p, len);
  232. USBHDBGSerial.println(" error: length beyond total data size");
  233. break;
  234. }
  235. USBHDBGSerial.print(" ");
  236. print_hexbytes(p, p[0]);
  237. if (p[0] == 9 && p[1] == 4) { // Interface Descriptor
  238. USBHDBGSerial.print(" Interface = ");
  239. USBHDBGSerial.println(p[2]);
  240. USBHDBGSerial.print(" Number of endpoints = ");
  241. USBHDBGSerial.println(p[4]);
  242. USBHDBGSerial.print(" Class/Subclass/Protocol = ");
  243. print_class_subclass_protocol(p[5], p[6], p[7]);
  244. } else if (p[0] >= 7 && p[0] <= 9 && p[1] == 5) { // Endpoint Descriptor
  245. USBHDBGSerial.print(" Endpoint = ");
  246. USBHDBGSerial.print(p[2] & 15);
  247. USBHDBGSerial.println((p[2] & 128) ? " IN" : " OUT");
  248. USBHDBGSerial.print(" Type = ");
  249. switch (p[3] & 3) {
  250. case 0: USBHDBGSerial.println("Control"); break;
  251. case 1: USBHDBGSerial.println("Isochronous"); break;
  252. case 2: USBHDBGSerial.println("Bulk"); break;
  253. case 3: USBHDBGSerial.println("Interrupt"); break;
  254. }
  255. USBHDBGSerial.print(" Max Size = ");
  256. USBHDBGSerial.println(p[4] | (p[5] << 8));
  257. USBHDBGSerial.print(" Polling Interval = ");
  258. USBHDBGSerial.println(p[6]);
  259. } else if (p[0] == 8 && p[1] == 11) { // IAD
  260. USBHDBGSerial.print(" Interface Association = ");
  261. USBHDBGSerial.print(p[2]);
  262. USBHDBGSerial.print(" through ");
  263. USBHDBGSerial.println(p[2] + p[3] - 1);
  264. USBHDBGSerial.print(" Class / Subclass / Protocol = ");
  265. print_class_subclass_protocol(p[4], p[5], p[7]);
  266. } else if (p[0] >= 9 && p[1] == 0x21) { // HID
  267. USBHDBGSerial.print(" HID, ");
  268. USBHDBGSerial.print(p[5]);
  269. USBHDBGSerial.print(" report descriptor");
  270. if (p[5] != 1) USBHDBGSerial.print('s');
  271. USBHDBGSerial.println();
  272. }
  273. len -= p[0];
  274. p += p[0];
  275. }
  276. }
  277. void USBHost::print_string_descriptor(const char *name, const uint8_t *p)
  278. {
  279. uint32_t len = p[0];
  280. if (len < 4) return;
  281. USBHDBGSerial.print(name);
  282. len -= 2;
  283. p += 2;
  284. while (len >= 2) {
  285. uint32_t c = p[0] | (p[1] << 8);
  286. if (c < 0x80) {
  287. USBHDBGSerial.write(c);
  288. } else if (c < 0x800) {
  289. USBHDBGSerial.write((c >> 6) | 0xC0);
  290. USBHDBGSerial.write((c & 0x3F) | 0x80);
  291. } else {
  292. USBHDBGSerial.write((c >> 12) | 0xE0);
  293. USBHDBGSerial.write(((c >> 6) & 0x3F) | 0x80);
  294. USBHDBGSerial.write((c & 0x3F) | 0x80);
  295. }
  296. len -= 2;
  297. p += 2;
  298. }
  299. USBHDBGSerial.println();
  300. //print_hexbytes(p, p[0]);
  301. }
  302. void USBHost::print_hexbytes(const void *ptr, uint32_t len)
  303. {
  304. if (ptr == NULL || len == 0) return;
  305. const uint8_t *p = (const uint8_t *)ptr;
  306. do {
  307. if (*p < 16) USBHDBGSerial.print('0');
  308. USBHDBGSerial.print(*p++, HEX);
  309. USBHDBGSerial.print(' ');
  310. } while (--len);
  311. USBHDBGSerial.println();
  312. }
  313. #endif