usbd.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /*
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2019 Ha Thach (tinyusb.org)
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. *
  24. * This file is part of the TinyUSB stack.
  25. */
  26. #include "tusb_option.h"
  27. #if TUSB_OPT_DEVICE_ENABLED
  28. #include "tusb.h"
  29. #include "usbd.h"
  30. #include "device/usbd_pvt.h"
  31. #include "dcd.h"
  32. #ifndef CFG_TUD_TASK_QUEUE_SZ
  33. #define CFG_TUD_TASK_QUEUE_SZ 16
  34. #endif
  35. //--------------------------------------------------------------------+
  36. // Device Data
  37. //--------------------------------------------------------------------+
  38. typedef struct {
  39. struct TU_ATTR_PACKED
  40. {
  41. volatile uint8_t connected : 1;
  42. volatile uint8_t addressed : 1;
  43. volatile uint8_t configured : 1;
  44. volatile uint8_t suspended : 1;
  45. uint8_t remote_wakeup_en : 1; // enable/disable by host
  46. uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute
  47. uint8_t self_powered : 1; // configuration descriptor's attribute
  48. };
  49. uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
  50. uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
  51. struct TU_ATTR_PACKED
  52. {
  53. volatile bool busy : 1;
  54. volatile bool stalled : 1;
  55. // TODO merge ep2drv here, 4-bit should be sufficient
  56. }ep_status[8][2];
  57. }usbd_device_t;
  58. static usbd_device_t _usbd_dev;
  59. // Invalid driver ID in itf2drv[] ep2drv[][] mapping
  60. enum { DRVID_INVALID = 0xFFu };
  61. //--------------------------------------------------------------------+
  62. // Class Driver
  63. //--------------------------------------------------------------------+
  64. #if CFG_TUSB_DEBUG >= 2
  65. #define DRIVER_NAME(_name) .name = _name,
  66. #else
  67. #define DRIVER_NAME(_name)
  68. #endif
  69. typedef struct
  70. {
  71. #if CFG_TUSB_DEBUG >= 2
  72. char const* name;
  73. #endif
  74. void (* init ) (void);
  75. void (* reset ) (uint8_t rhport);
  76. bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length);
  77. bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request);
  78. bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request);
  79. bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
  80. void (* sof ) (uint8_t rhport);
  81. } usbd_class_driver_t;
  82. static usbd_class_driver_t const _usbd_driver[] =
  83. {
  84. #if CFG_TUD_CDC
  85. {
  86. DRIVER_NAME("CDC")
  87. .init = cdcd_init,
  88. .reset = cdcd_reset,
  89. .open = cdcd_open,
  90. .control_request = cdcd_control_request,
  91. .control_complete = cdcd_control_complete,
  92. .xfer_cb = cdcd_xfer_cb,
  93. .sof = NULL
  94. },
  95. #endif
  96. #if CFG_TUD_MSC
  97. {
  98. DRIVER_NAME("MSC")
  99. .init = mscd_init,
  100. .reset = mscd_reset,
  101. .open = mscd_open,
  102. .control_request = mscd_control_request,
  103. .control_complete = mscd_control_complete,
  104. .xfer_cb = mscd_xfer_cb,
  105. .sof = NULL
  106. },
  107. #endif
  108. #if CFG_TUD_HID
  109. {
  110. DRIVER_NAME("HID")
  111. .init = hidd_init,
  112. .reset = hidd_reset,
  113. .open = hidd_open,
  114. .control_request = hidd_control_request,
  115. .control_complete = hidd_control_complete,
  116. .xfer_cb = hidd_xfer_cb,
  117. .sof = NULL
  118. },
  119. #endif
  120. #if CFG_TUD_MIDI
  121. {
  122. DRIVER_NAME("MIDI")
  123. .init = midid_init,
  124. .open = midid_open,
  125. .reset = midid_reset,
  126. .control_request = midid_control_request,
  127. .control_complete = midid_control_complete,
  128. .xfer_cb = midid_xfer_cb,
  129. .sof = NULL
  130. },
  131. #endif
  132. #if CFG_TUD_VENDOR
  133. {
  134. DRIVER_NAME("VENDOR")
  135. .init = vendord_init,
  136. .reset = vendord_reset,
  137. .open = vendord_open,
  138. .control_request = tud_vendor_control_request_cb,
  139. .control_complete = tud_vendor_control_complete_cb,
  140. .xfer_cb = vendord_xfer_cb,
  141. .sof = NULL
  142. },
  143. #endif
  144. #if CFG_TUD_USBTMC
  145. {
  146. DRIVER_NAME("TMC")
  147. .init = usbtmcd_init_cb,
  148. .reset = usbtmcd_reset_cb,
  149. .open = usbtmcd_open_cb,
  150. .control_request = usbtmcd_control_request_cb,
  151. .control_complete = usbtmcd_control_complete_cb,
  152. .xfer_cb = usbtmcd_xfer_cb,
  153. .sof = NULL
  154. },
  155. #endif
  156. #if CFG_TUD_DFU_RT
  157. {
  158. DRIVER_NAME("DFU-RT")
  159. .init = dfu_rtd_init,
  160. .reset = dfu_rtd_reset,
  161. .open = dfu_rtd_open,
  162. .control_request = dfu_rtd_control_request,
  163. .control_complete = dfu_rtd_control_complete,
  164. .xfer_cb = dfu_rtd_xfer_cb,
  165. .sof = NULL
  166. },
  167. #endif
  168. #if CFG_TUD_NET
  169. {
  170. DRIVER_NAME("NET")
  171. .init = netd_init,
  172. .reset = netd_reset,
  173. .open = netd_open,
  174. .control_request = netd_control_request,
  175. .control_complete = netd_control_complete,
  176. .xfer_cb = netd_xfer_cb,
  177. .sof = NULL,
  178. },
  179. #endif
  180. };
  181. enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
  182. //--------------------------------------------------------------------+
  183. // DCD Event
  184. //--------------------------------------------------------------------+
  185. // Event queue
  186. // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr)
  187. OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t);
  188. static osal_queue_t _usbd_q;
  189. //--------------------------------------------------------------------+
  190. // Prototypes
  191. //--------------------------------------------------------------------+
  192. static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
  193. static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
  194. static bool process_set_config(uint8_t rhport, uint8_t cfg_num);
  195. static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request);
  196. void usbd_control_reset(void);
  197. void usbd_control_set_request(tusb_control_request_t const *request);
  198. void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) );
  199. bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
  200. //--------------------------------------------------------------------+
  201. // Debugging
  202. //--------------------------------------------------------------------+
  203. #if CFG_TUSB_DEBUG >= 2
  204. static char const* const _usbd_event_str[DCD_EVENT_COUNT] =
  205. {
  206. "INVALID" ,
  207. "BUS_RESET" ,
  208. "UNPLUGGED" ,
  209. "SOF" ,
  210. "SUSPEND" ,
  211. "RESUME" ,
  212. "SETUP_RECEIVED" ,
  213. "XFER_COMPLETE" ,
  214. "FUNC_CALL"
  215. };
  216. static char const* const _tusb_std_request_str[] =
  217. {
  218. "Get Status" ,
  219. "Clear Feature" ,
  220. "Reserved" ,
  221. "Set Feature" ,
  222. "Reserved" ,
  223. "Set Address" ,
  224. "Get Descriptor" ,
  225. "Set Descriptor" ,
  226. "Get Configuration" ,
  227. "Set Configuration" ,
  228. "Get Interface" ,
  229. "Set Interface" ,
  230. "Synch Frame"
  231. };
  232. #endif
  233. //--------------------------------------------------------------------+
  234. // Application API
  235. //--------------------------------------------------------------------+
  236. bool tud_mounted(void)
  237. {
  238. return _usbd_dev.configured;
  239. }
  240. bool tud_suspended(void)
  241. {
  242. return _usbd_dev.suspended;
  243. }
  244. bool tud_remote_wakeup(void)
  245. {
  246. // only wake up host if this feature is supported and enabled and we are suspended
  247. TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en );
  248. dcd_remote_wakeup(TUD_OPT_RHPORT);
  249. return true;
  250. }
  251. //--------------------------------------------------------------------+
  252. // USBD Task
  253. //--------------------------------------------------------------------+
  254. bool tud_init (void)
  255. {
  256. TU_LOG2("USBD init\r\n");
  257. tu_varclr(&_usbd_dev);
  258. // Init device queue & task
  259. _usbd_q = osal_queue_create(&_usbd_qdef);
  260. TU_ASSERT(_usbd_q != NULL);
  261. // Init class drivers
  262. for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++)
  263. {
  264. TU_LOG2("%s init\r\n", _usbd_driver[i].name);
  265. _usbd_driver[i].init();
  266. }
  267. // Init device controller driver
  268. dcd_init(TUD_OPT_RHPORT);
  269. tud_connect();
  270. dcd_int_enable(TUD_OPT_RHPORT);
  271. return true;
  272. }
  273. static void usbd_reset(uint8_t rhport)
  274. {
  275. tu_varclr(&_usbd_dev);
  276. memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
  277. memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping
  278. usbd_control_reset();
  279. for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++)
  280. {
  281. if ( _usbd_driver[i].reset ) _usbd_driver[i].reset( rhport );
  282. }
  283. }
  284. /* USB Device Driver task
  285. * This top level thread manages all device controller event and delegates events to class-specific drivers.
  286. * This should be called periodically within the mainloop or rtos thread.
  287. *
  288. @code
  289. int main(void)
  290. {
  291. application_init();
  292. tusb_init();
  293. while(1) // the mainloop
  294. {
  295. application_code();
  296. tud_task(); // tinyusb device task
  297. }
  298. }
  299. @endcode
  300. */
  301. void tud_task (void)
  302. {
  303. // Skip if stack is not initialized
  304. if ( !tusb_inited() ) return;
  305. // Loop until there is no more events in the queue
  306. while (1)
  307. {
  308. dcd_event_t event;
  309. if ( !osal_queue_receive(_usbd_q, &event) ) return;
  310. TU_LOG2("USBD: event %s\r\n", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED");
  311. switch ( event.event_id )
  312. {
  313. case DCD_EVENT_BUS_RESET:
  314. usbd_reset(event.rhport);
  315. break;
  316. case DCD_EVENT_UNPLUGGED:
  317. usbd_reset(event.rhport);
  318. // invoke callback
  319. if (tud_umount_cb) tud_umount_cb();
  320. break;
  321. case DCD_EVENT_SETUP_RECEIVED:
  322. TU_LOG2_MEM(&event.setup_received, 8, 2);
  323. // Mark as connected after receiving 1st setup packet.
  324. // But it is easier to set it every time instead of wasting time to check then set
  325. _usbd_dev.connected = 1;
  326. // Process control request
  327. if ( !process_control_request(event.rhport, &event.setup_received) )
  328. {
  329. TU_LOG2(" Stall EP0\r\n");
  330. // Failed -> stall both control endpoint IN and OUT
  331. dcd_edpt_stall(event.rhport, 0);
  332. dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK);
  333. }
  334. break;
  335. case DCD_EVENT_XFER_COMPLETE:
  336. {
  337. // Invoke the class callback associated with the endpoint address
  338. uint8_t const ep_addr = event.xfer_complete.ep_addr;
  339. uint8_t const epnum = tu_edpt_number(ep_addr);
  340. uint8_t const ep_dir = tu_edpt_dir(ep_addr);
  341. TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
  342. _usbd_dev.ep_status[epnum][ep_dir].busy = false;
  343. if ( 0 == epnum )
  344. {
  345. usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
  346. }
  347. else
  348. {
  349. uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir];
  350. TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
  351. TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name);
  352. _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
  353. }
  354. }
  355. break;
  356. case DCD_EVENT_SUSPEND:
  357. if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
  358. break;
  359. case DCD_EVENT_RESUME:
  360. if (tud_resume_cb) tud_resume_cb();
  361. break;
  362. case DCD_EVENT_SOF:
  363. for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ )
  364. {
  365. if ( _usbd_driver[i].sof )
  366. {
  367. _usbd_driver[i].sof(event.rhport);
  368. }
  369. }
  370. break;
  371. case USBD_EVENT_FUNC_CALL:
  372. if ( event.func_call.func ) event.func_call.func(event.func_call.param);
  373. break;
  374. default:
  375. TU_BREAKPOINT();
  376. break;
  377. }
  378. }
  379. }
  380. //--------------------------------------------------------------------+
  381. // Control Request Parser & Handling
  382. //--------------------------------------------------------------------+
  383. // Helper to invoke class driver control request handler
  384. static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request)
  385. {
  386. TU_ASSERT(_usbd_driver[drvid].control_request);
  387. usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete);
  388. TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name);
  389. return _usbd_driver[drvid].control_request(rhport, request);
  390. }
  391. // This handles the actual request and its response.
  392. // return false will cause its caller to stall control endpoint
  393. static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
  394. {
  395. usbd_control_set_complete_callback(NULL);
  396. TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID);
  397. // Vendor request
  398. if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR )
  399. {
  400. TU_VERIFY(tud_vendor_control_request_cb);
  401. if (tud_vendor_control_complete_cb) usbd_control_set_complete_callback(tud_vendor_control_complete_cb);
  402. return tud_vendor_control_request_cb(rhport, p_request);
  403. }
  404. #if CFG_TUSB_DEBUG > 1
  405. if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME)
  406. {
  407. TU_LOG2(" %s\r\n", _tusb_std_request_str[p_request->bRequest]);
  408. }
  409. #endif
  410. switch ( p_request->bmRequestType_bit.recipient )
  411. {
  412. //------------- Device Requests e.g in enumeration -------------//
  413. case TUSB_REQ_RCPT_DEVICE:
  414. if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
  415. {
  416. // Non standard request is not supported
  417. TU_BREAKPOINT();
  418. return false;
  419. }
  420. switch ( p_request->bRequest )
  421. {
  422. case TUSB_REQ_SET_ADDRESS:
  423. // Depending on mcu, status phase could be sent either before or after changing device address,
  424. // or even require stack to not response with status at all
  425. // Therefore DCD must take full responsibility to response and include zlp status packet if needed.
  426. usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API
  427. dcd_set_address(rhport, (uint8_t) p_request->wValue);
  428. // skip tud_control_status()
  429. _usbd_dev.addressed = 1;
  430. break;
  431. case TUSB_REQ_GET_CONFIGURATION:
  432. {
  433. uint8_t cfgnum = _usbd_dev.configured ? 1 : 0;
  434. tud_control_xfer(rhport, p_request, &cfgnum, 1);
  435. }
  436. break;
  437. case TUSB_REQ_SET_CONFIGURATION:
  438. {
  439. uint8_t const cfg_num = (uint8_t) p_request->wValue;
  440. dcd_set_config(rhport, cfg_num);
  441. if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
  442. _usbd_dev.configured = cfg_num ? 1 : 0;
  443. tud_control_status(rhport, p_request);
  444. }
  445. break;
  446. case TUSB_REQ_GET_DESCRIPTOR:
  447. TU_VERIFY( process_get_descriptor(rhport, p_request) );
  448. break;
  449. case TUSB_REQ_SET_FEATURE:
  450. // Only support remote wakeup for device feature
  451. TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
  452. // Host may enable remote wake up before suspending especially HID device
  453. _usbd_dev.remote_wakeup_en = true;
  454. tud_control_status(rhport, p_request);
  455. break;
  456. case TUSB_REQ_CLEAR_FEATURE:
  457. // Only support remote wakeup for device feature
  458. TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
  459. // Host may disable remote wake up after resuming
  460. _usbd_dev.remote_wakeup_en = false;
  461. tud_control_status(rhport, p_request);
  462. break;
  463. case TUSB_REQ_GET_STATUS:
  464. {
  465. // Device status bit mask
  466. // - Bit 0: Self Powered
  467. // - Bit 1: Remote Wakeup enabled
  468. uint16_t status = (_usbd_dev.self_powered ? 1 : 0) | (_usbd_dev.remote_wakeup_en ? 2 : 0);
  469. tud_control_xfer(rhport, p_request, &status, 2);
  470. }
  471. break;
  472. // Unknown/Unsupported request
  473. default: TU_BREAKPOINT(); return false;
  474. }
  475. break;
  476. //------------- Class/Interface Specific Request -------------//
  477. case TUSB_REQ_RCPT_INTERFACE:
  478. {
  479. uint8_t const itf = tu_u16_low(p_request->wIndex);
  480. TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
  481. uint8_t const drvid = _usbd_dev.itf2drv[itf];
  482. TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
  483. // all requests to Interface (STD or Class) is forwarded to class driver.
  484. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE
  485. if ( !invoke_class_control(rhport, drvid, p_request) )
  486. {
  487. // For GET_INTERFACE, it is mandatory to respond even if the class
  488. // driver doesn't use alternate settings.
  489. TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type &&
  490. TUSB_REQ_GET_INTERFACE == p_request->bRequest);
  491. uint8_t alternate = 0;
  492. tud_control_xfer(rhport, p_request, &alternate, 1);
  493. }
  494. }
  495. break;
  496. //------------- Endpoint Request -------------//
  497. case TUSB_REQ_RCPT_ENDPOINT:
  498. {
  499. uint8_t const ep_addr = tu_u16_low(p_request->wIndex);
  500. uint8_t const ep_num = tu_edpt_number(ep_addr);
  501. uint8_t const ep_dir = tu_edpt_dir(ep_addr);
  502. TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
  503. uint8_t const drvid = _usbd_dev.ep2drv[ep_num][ep_dir];
  504. bool ret = false;
  505. // Handle STD request to endpoint
  506. if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
  507. {
  508. // force return true for standard request
  509. ret = true;
  510. switch ( p_request->bRequest )
  511. {
  512. case TUSB_REQ_GET_STATUS:
  513. {
  514. uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000;
  515. tud_control_xfer(rhport, p_request, &status, 2);
  516. }
  517. break;
  518. case TUSB_REQ_CLEAR_FEATURE:
  519. if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
  520. {
  521. usbd_edpt_clear_stall(rhport, ep_addr);
  522. }
  523. tud_control_status(rhport, p_request);
  524. break;
  525. case TUSB_REQ_SET_FEATURE:
  526. if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
  527. {
  528. usbd_edpt_stall(rhport, ep_addr);
  529. }
  530. tud_control_status(rhport, p_request);
  531. break;
  532. // Unknown/Unsupported request
  533. default: TU_BREAKPOINT(); return false;
  534. }
  535. }
  536. if (drvid < 0xFF) {
  537. TU_ASSERT(drvid < USBD_CLASS_DRIVER_COUNT);
  538. // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
  539. // We will forward all request targeted endpoint to class drivers after
  540. // - For class-type requests: driver is fully responsible to reply to host
  541. // - For std-type requests : driver init/re-init internal variable/buffer only, and
  542. // must not call tud_control_status(), driver's return value will have no effect.
  543. // EP state has already affected (stalled/cleared)
  544. if ( invoke_class_control(rhport, drvid, p_request) ) ret = true;
  545. }
  546. if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
  547. {
  548. // Set complete callback = NULL since it can also stall the request.
  549. usbd_control_set_complete_callback(NULL);
  550. }
  551. return ret;
  552. }
  553. break;
  554. // Unknown recipient
  555. default: TU_BREAKPOINT(); return false;
  556. }
  557. return true;
  558. }
  559. // Process Set Configure Request
  560. // This function parse configuration descriptor & open drivers accordingly
  561. static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
  562. {
  563. tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1
  564. TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION);
  565. // Parse configuration descriptor
  566. _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0;
  567. _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0;
  568. // Parse interface descriptor
  569. uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t);
  570. uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength;
  571. while( p_desc < desc_end )
  572. {
  573. tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL;
  574. // Class will always starts with Interface Association (if any) and then Interface descriptor
  575. if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
  576. {
  577. desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc;
  578. p_desc = tu_desc_next(p_desc); // next to Interface
  579. }
  580. TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) );
  581. tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc;
  582. uint8_t drv_id;
  583. uint16_t drv_len;
  584. for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++)
  585. {
  586. usbd_class_driver_t const *driver = &_usbd_driver[drv_id];
  587. drv_len = 0;
  588. if ( driver->open(rhport, desc_itf, &drv_len) )
  589. {
  590. // Interface number must not be used already
  591. TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] );
  592. TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name);
  593. _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
  594. // If IAD exist, assign all interfaces to the same driver
  595. if (desc_itf_assoc)
  596. {
  597. // IAD's first interface number and class/subclass/protocol should match with opened interface
  598. TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber &&
  599. desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass &&
  600. desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass &&
  601. desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol);
  602. for(uint8_t i=1; i<desc_itf_assoc->bInterfaceCount; i++)
  603. {
  604. _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id;
  605. }
  606. }
  607. break;
  608. }
  609. }
  610. // Assert if cannot find supported driver
  611. TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) );
  612. mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor
  613. p_desc += drv_len; // next interface
  614. }
  615. // invoke callback
  616. if (tud_mount_cb) tud_mount_cb();
  617. return true;
  618. }
  619. // Helper marking endpoint of interface belongs to class driver
  620. static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id)
  621. {
  622. uint16_t len = 0;
  623. while( len < desc_len )
  624. {
  625. if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
  626. {
  627. uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
  628. ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
  629. }
  630. len = (uint16_t)(len + tu_desc_len(p_desc));
  631. p_desc = tu_desc_next(p_desc);
  632. }
  633. }
  634. // return descriptor's buffer and update desc_len
  635. static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request)
  636. {
  637. tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue);
  638. uint8_t const desc_index = tu_u16_low( p_request->wValue );
  639. switch(desc_type)
  640. {
  641. case TUSB_DESC_DEVICE:
  642. {
  643. uint16_t len = sizeof(tusb_desc_device_t);
  644. // Only send up to EP0 Packet Size if not addressed
  645. // This only happens with the very first get device descriptor and EP0 size = 8 or 16.
  646. if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed)
  647. {
  648. len = CFG_TUD_ENDPOINT0_SIZE;
  649. // Hack here: we modify the request length to prevent usbd_control response with zlp
  650. ((tusb_control_request_t*) p_request)->wLength = CFG_TUD_ENDPOINT0_SIZE;
  651. }
  652. return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len);
  653. }
  654. break;
  655. case TUSB_DESC_BOS:
  656. {
  657. // requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
  658. if (!tud_descriptor_bos_cb) return false;
  659. tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb();
  660. uint16_t total_len;
  661. memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory
  662. return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len);
  663. }
  664. break;
  665. case TUSB_DESC_CONFIGURATION:
  666. {
  667. tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index);
  668. TU_ASSERT(desc_config);
  669. uint16_t total_len;
  670. memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory
  671. return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len);
  672. }
  673. break;
  674. case TUSB_DESC_STRING:
  675. // String Descriptor always uses the desc set from user
  676. if ( desc_index == 0xEE )
  677. {
  678. // The 0xEE index string is a Microsoft OS Descriptors.
  679. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
  680. return false;
  681. }else
  682. {
  683. uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex);
  684. TU_ASSERT(desc_str);
  685. // first byte of descriptor is its size
  686. return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]);
  687. }
  688. break;
  689. case TUSB_DESC_DEVICE_QUALIFIER:
  690. // TODO If not highspeed capable stall this request otherwise
  691. // return the descriptor that could work in highspeed
  692. return false;
  693. break;
  694. default: return false;
  695. }
  696. return true;
  697. }
  698. //--------------------------------------------------------------------+
  699. // DCD Event Handler
  700. //--------------------------------------------------------------------+
  701. void dcd_event_handler(dcd_event_t const * event, bool in_isr)
  702. {
  703. switch (event->event_id)
  704. {
  705. case DCD_EVENT_UNPLUGGED:
  706. _usbd_dev.connected = 0;
  707. _usbd_dev.addressed = 0;
  708. _usbd_dev.configured = 0;
  709. _usbd_dev.suspended = 0;
  710. osal_queue_send(_usbd_q, event, in_isr);
  711. break;
  712. case DCD_EVENT_SOF:
  713. return; // skip SOF event for now
  714. break;
  715. case DCD_EVENT_SUSPEND:
  716. // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the
  717. // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well.
  718. // We will skip handling SUSPEND/RESUME event if not currently connected
  719. if ( _usbd_dev.connected )
  720. {
  721. _usbd_dev.suspended = 1;
  722. osal_queue_send(_usbd_q, event, in_isr);
  723. }
  724. break;
  725. case DCD_EVENT_RESUME:
  726. // skip event if not connected (especially required for SAMD)
  727. if ( _usbd_dev.connected )
  728. {
  729. _usbd_dev.suspended = 0;
  730. osal_queue_send(_usbd_q, event, in_isr);
  731. }
  732. break;
  733. default:
  734. osal_queue_send(_usbd_q, event, in_isr);
  735. break;
  736. }
  737. }
  738. void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
  739. {
  740. dcd_event_t event = { .rhport = rhport, .event_id = eid, };
  741. dcd_event_handler(&event, in_isr);
  742. }
  743. void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
  744. {
  745. dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED };
  746. memcpy(&event.setup_received, setup, 8);
  747. dcd_event_handler(&event, in_isr);
  748. }
  749. void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
  750. {
  751. dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE };
  752. event.xfer_complete.ep_addr = ep_addr;
  753. event.xfer_complete.len = xferred_bytes;
  754. event.xfer_complete.result = result;
  755. dcd_event_handler(&event, in_isr);
  756. }
  757. //--------------------------------------------------------------------+
  758. // Helper
  759. //--------------------------------------------------------------------+
  760. // Parse consecutive endpoint descriptors (IN & OUT)
  761. bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in)
  762. {
  763. for(int i=0; i<ep_count; i++)
  764. {
  765. tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
  766. TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer);
  767. TU_ASSERT(dcd_edpt_open(rhport, desc_ep));
  768. if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
  769. {
  770. (*ep_in) = desc_ep->bEndpointAddress;
  771. }else
  772. {
  773. (*ep_out) = desc_ep->bEndpointAddress;
  774. }
  775. p_desc = tu_desc_next(p_desc);
  776. }
  777. return true;
  778. }
  779. // Helper to defer an isr function
  780. void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr)
  781. {
  782. dcd_event_t event =
  783. {
  784. .rhport = 0,
  785. .event_id = USBD_EVENT_FUNC_CALL,
  786. };
  787. event.func_call.func = func;
  788. event.func_call.param = param;
  789. dcd_event_handler(&event, in_isr);
  790. }
  791. //--------------------------------------------------------------------+
  792. // USBD Endpoint API
  793. //--------------------------------------------------------------------+
  794. bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
  795. {
  796. uint8_t const epnum = tu_edpt_number(ep_addr);
  797. uint8_t const dir = tu_edpt_dir(ep_addr);
  798. TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) );
  799. _usbd_dev.ep_status[epnum][dir].busy = true;
  800. TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, total_bytes);
  801. return true;
  802. }
  803. bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
  804. {
  805. (void) rhport;
  806. uint8_t const epnum = tu_edpt_number(ep_addr);
  807. uint8_t const dir = tu_edpt_dir(ep_addr);
  808. return _usbd_dev.ep_status[epnum][dir].busy;
  809. }
  810. void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
  811. {
  812. uint8_t const epnum = tu_edpt_number(ep_addr);
  813. uint8_t const dir = tu_edpt_dir(ep_addr);
  814. dcd_edpt_stall(rhport, ep_addr);
  815. _usbd_dev.ep_status[epnum][dir].stalled = true;
  816. _usbd_dev.ep_status[epnum][dir].busy = true;
  817. }
  818. void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
  819. {
  820. uint8_t const epnum = tu_edpt_number(ep_addr);
  821. uint8_t const dir = tu_edpt_dir(ep_addr);
  822. dcd_edpt_clear_stall(rhport, ep_addr);
  823. _usbd_dev.ep_status[epnum][dir].stalled = false;
  824. _usbd_dev.ep_status[epnum][dir].busy = false;
  825. }
  826. bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
  827. {
  828. (void) rhport;
  829. uint8_t const epnum = tu_edpt_number(ep_addr);
  830. uint8_t const dir = tu_edpt_dir(ep_addr);
  831. return _usbd_dev.ep_status[epnum][dir].stalled;
  832. }
  833. /**
  834. * usbd_edpt_close will disable an endpoint.
  835. *
  836. * In progress transfers on this EP may be delivered after this call.
  837. *
  838. */
  839. void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr)
  840. {
  841. TU_ASSERT(dcd_edpt_close, /**/);
  842. TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr);
  843. dcd_edpt_close(rhport, ep_addr);
  844. return;
  845. }
  846. #endif