usb_host.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. Warning: The USB Host Library API is still a beta version and may be subject to change
  8. */
  9. #include <stdlib.h>
  10. #include <stdint.h>
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/task.h"
  13. #include "freertos/queue.h"
  14. #include "freertos/semphr.h"
  15. #include "esp_err.h"
  16. #include "esp_log.h"
  17. #include "esp_heap_caps.h"
  18. #include "hub.h"
  19. #include "usbh.h"
  20. #include "esp_private/usb_phy.h"
  21. #include "usb/usb_host.h"
  22. static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED;
  23. #define HOST_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&host_lock)
  24. #define HOST_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&host_lock)
  25. #define HOST_ENTER_CRITICAL() portENTER_CRITICAL(&host_lock)
  26. #define HOST_EXIT_CRITICAL() portEXIT_CRITICAL(&host_lock)
  27. #define HOST_ENTER_CRITICAL_SAFE() portENTER_CRITICAL_SAFE(&host_lock)
  28. #define HOST_EXIT_CRITICAL_SAFE() portEXIT_CRITICAL_SAFE(&host_lock)
  29. #define HOST_CHECK(cond, ret_val) ({ \
  30. if (!(cond)) { \
  31. return (ret_val); \
  32. } \
  33. })
  34. #define HOST_CHECK_FROM_CRIT(cond, ret_val) ({ \
  35. if (!(cond)) { \
  36. HOST_EXIT_CRITICAL(); \
  37. return ret_val; \
  38. } \
  39. })
  40. #define PROCESS_PENDING_FLAG_USBH 0x01
  41. #define PROCESS_PENDING_FLAG_HUB 0x02
  42. #define PROCESS_PENDING_FLAG_EVENT 0x04
  43. typedef struct endpoint_s endpoint_t;
  44. typedef struct interface_s interface_t;
  45. typedef struct client_s client_t;
  46. struct endpoint_s {
  47. //Dynamic members require a critical section
  48. struct {
  49. TAILQ_ENTRY(endpoint_s) tailq_entry;
  50. union {
  51. struct {
  52. uint32_t pending: 1;
  53. uint32_t reserved31:31;
  54. };
  55. } flags;
  56. uint32_t num_urb_inflight;
  57. hcd_pipe_event_t last_event;
  58. } dynamic;
  59. //Constant members do no change after claiming the interface thus do not require a critical section
  60. struct {
  61. hcd_pipe_handle_t pipe_hdl;
  62. const usb_ep_desc_t *ep_desc;
  63. interface_t *intf_obj;
  64. } constant;
  65. };
  66. struct interface_s {
  67. //Dynamic members require a critical section
  68. struct {
  69. TAILQ_ENTRY(interface_s) tailq_entry;
  70. } mux_protected;
  71. //Constant members do no change after claiming the interface thus do not require a critical section
  72. struct {
  73. const usb_intf_desc_t *intf_desc;
  74. usb_device_handle_t dev_hdl;
  75. client_t *client_obj;
  76. endpoint_t *endpoints[0];
  77. } constant;
  78. };
  79. struct client_s {
  80. //Dynamic members require a critical section
  81. struct {
  82. TAILQ_ENTRY(client_s) tailq_entry;
  83. TAILQ_HEAD(tailhead_pending_ep, endpoint_s) pending_ep_tailq;
  84. TAILQ_HEAD(tailhead_idle_ep, endpoint_s) idle_ep_tailq;
  85. TAILQ_HEAD(tailhead_done_ctrl_xfers, urb_s) done_ctrl_xfer_tailq;
  86. union {
  87. struct {
  88. uint32_t events_pending: 1;
  89. uint32_t handling_events: 1;
  90. uint32_t blocked: 1;
  91. uint32_t taking_mux: 1;
  92. uint32_t reserved4: 4;
  93. uint32_t num_intf_claimed: 8;
  94. uint32_t reserved16: 16;
  95. };
  96. uint32_t val;
  97. } flags;
  98. uint32_t num_done_ctrl_xfer;
  99. uint32_t opened_dev_addr_map;
  100. } dynamic;
  101. //Mux protected members must be protected by host library the mux_lock when accessed
  102. struct {
  103. TAILQ_HEAD(tailhead_interfaces, interface_s) interface_tailq;
  104. } mux_protected;
  105. //Constant members do no change after registration thus do not require a critical section
  106. struct {
  107. SemaphoreHandle_t event_sem;
  108. usb_host_client_event_cb_t event_callback;
  109. void *callback_arg;
  110. QueueHandle_t event_msg_queue;
  111. } constant;
  112. };
  113. typedef struct {
  114. //Dynamic members require a critical section
  115. struct {
  116. //Access to these should be done in a critical section
  117. uint32_t process_pending_flags;
  118. uint32_t lib_event_flags;
  119. union {
  120. struct {
  121. uint32_t process_pending: 1;
  122. uint32_t handling_events: 1;
  123. uint32_t blocked: 1;
  124. uint32_t reserved5: 5;
  125. uint32_t num_clients: 8;
  126. uint32_t reserved16: 16;
  127. };
  128. uint32_t val;
  129. } flags;
  130. } dynamic;
  131. //Mux protected members must be protected by host library the mux_lock when accessed
  132. struct {
  133. TAILQ_HEAD(tailhead_clients, client_s) client_tailq; //List of all clients registered
  134. } mux_protected;
  135. //Constant members do no change after installation thus do not require a critical section
  136. struct {
  137. SemaphoreHandle_t event_sem;
  138. SemaphoreHandle_t mux_lock;
  139. usb_phy_handle_t phy_handle; //Will be NULL if host library is installed with skip_phy_setup
  140. } constant;
  141. } host_lib_t;
  142. static host_lib_t *p_host_lib_obj = NULL;
  143. const char *USB_HOST_TAG = "USB HOST";
  144. // ----------------------------------------------------- Helpers -------------------------------------------------------
  145. static inline void _record_client_opened_device(client_t *client_obj, uint8_t dev_addr)
  146. {
  147. assert(dev_addr != 0);
  148. client_obj->dynamic.opened_dev_addr_map |= (1 << (dev_addr - 1));
  149. }
  150. static inline void _clear_client_opened_device(client_t *client_obj, uint8_t dev_addr)
  151. {
  152. assert(dev_addr != 0);
  153. client_obj->dynamic.opened_dev_addr_map &= ~(1 << (dev_addr - 1));
  154. }
  155. static inline bool _check_client_opened_device(client_t *client_obj, uint8_t dev_addr)
  156. {
  157. assert(dev_addr != 0);
  158. return (client_obj->dynamic.opened_dev_addr_map & (1 << (dev_addr - 1)));
  159. }
  160. static bool _unblock_client(client_t *client_obj, bool in_isr)
  161. {
  162. bool send_sem;
  163. if (!client_obj->dynamic.flags.events_pending && !client_obj->dynamic.flags.handling_events) {
  164. client_obj->dynamic.flags.events_pending = 1;
  165. send_sem = true;
  166. } else {
  167. send_sem = false;
  168. }
  169. HOST_EXIT_CRITICAL_SAFE();
  170. bool yield = false;
  171. if (send_sem) {
  172. if (in_isr) {
  173. BaseType_t xTaskWoken = pdFALSE;
  174. xSemaphoreGiveFromISR(client_obj->constant.event_sem, &xTaskWoken);
  175. yield = (xTaskWoken == pdTRUE);
  176. } else {
  177. xSemaphoreGive(client_obj->constant.event_sem);
  178. }
  179. }
  180. HOST_ENTER_CRITICAL_SAFE();
  181. return yield;
  182. }
  183. static bool _unblock_lib(bool in_isr)
  184. {
  185. bool send_sem;
  186. if (!p_host_lib_obj->dynamic.flags.process_pending && !p_host_lib_obj->dynamic.flags.handling_events) {
  187. p_host_lib_obj->dynamic.flags.process_pending = 1;
  188. send_sem = true;
  189. } else {
  190. send_sem = false;
  191. }
  192. HOST_EXIT_CRITICAL_SAFE();
  193. bool yield = false;
  194. if (send_sem) {
  195. if (in_isr) {
  196. BaseType_t xTaskWoken = pdFALSE;
  197. xSemaphoreGiveFromISR(p_host_lib_obj->constant.event_sem, &xTaskWoken);
  198. yield = (xTaskWoken == pdTRUE);
  199. } else {
  200. xSemaphoreGive(p_host_lib_obj->constant.event_sem);
  201. }
  202. }
  203. HOST_ENTER_CRITICAL_SAFE();
  204. return yield;
  205. }
  206. static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_msg, bool send_to_all, uint8_t opened_dev_addr)
  207. {
  208. //Lock client list
  209. xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
  210. //Send event message to relevant or all clients
  211. client_t *client_obj;
  212. TAILQ_FOREACH(client_obj, &p_host_lib_obj->mux_protected.client_tailq, dynamic.tailq_entry) {
  213. if (!send_to_all) {
  214. //Check if client opened the device
  215. HOST_ENTER_CRITICAL();
  216. bool send = _check_client_opened_device(client_obj, opened_dev_addr);
  217. HOST_EXIT_CRITICAL();
  218. if (!send) {
  219. continue;
  220. }
  221. }
  222. //Send the event message
  223. if (xQueueSend(client_obj->constant.event_msg_queue, event_msg, 0) == pdTRUE) {
  224. HOST_ENTER_CRITICAL();
  225. _unblock_client(client_obj, false);
  226. HOST_EXIT_CRITICAL();
  227. } else {
  228. ESP_LOGE(USB_HOST_TAG, "Client event message queue full");
  229. }
  230. }
  231. //Unlock client list
  232. xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
  233. }
  234. // ---------------------------------------------------- Callbacks ------------------------------------------------------
  235. // ------------------- Library Related ---------------------
  236. static bool notif_callback(usb_notif_source_t source, bool in_isr, void *arg)
  237. {
  238. HOST_ENTER_CRITICAL_SAFE();
  239. //Store notification source
  240. switch (source) {
  241. case USB_NOTIF_SOURCE_USBH:
  242. p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_PENDING_FLAG_USBH;
  243. break;
  244. case USB_NOTIF_SOURCE_HUB:
  245. p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_PENDING_FLAG_HUB;
  246. break;
  247. }
  248. bool yield = _unblock_lib(in_isr);
  249. HOST_EXIT_CRITICAL_SAFE();
  250. return yield;
  251. }
  252. static void ctrl_xfer_callback(usb_device_handle_t dev_hdl, urb_t *urb, void *arg)
  253. {
  254. assert(urb->usb_host_client != NULL);
  255. //Redistribute done control transfer to the clients that submitted them
  256. client_t *client_obj = (client_t *)urb->usb_host_client;
  257. HOST_ENTER_CRITICAL();
  258. TAILQ_INSERT_TAIL(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry);
  259. client_obj->dynamic.num_done_ctrl_xfer++;
  260. _unblock_client(client_obj, false);
  261. HOST_EXIT_CRITICAL();
  262. }
  263. static void dev_event_callback(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg)
  264. {
  265. //Check usbh_event. The data type of event_arg depends on the type of event
  266. switch (usbh_event) {
  267. case USBH_EVENT_DEV_NEW: {
  268. //Prepare a NEW_DEV client event message, the send it to all clients
  269. uint8_t dev_addr;
  270. ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
  271. usb_host_client_event_msg_t event_msg = {
  272. .event = USB_HOST_CLIENT_EVENT_NEW_DEV,
  273. .new_dev.address = dev_addr,
  274. };
  275. send_event_msg_to_clients(&event_msg, true, 0);
  276. break;
  277. }
  278. case USBH_EVENT_DEV_GONE: {
  279. //Prepare event msg, send only to clients that have opened the device
  280. uint8_t dev_addr;
  281. ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
  282. usb_host_client_event_msg_t event_msg = {
  283. .event = USB_HOST_CLIENT_EVENT_DEV_GONE,
  284. .dev_gone.dev_hdl = dev_hdl,
  285. };
  286. send_event_msg_to_clients(&event_msg, false, dev_addr);
  287. break;
  288. }
  289. case USBH_EVENT_DEV_ALL_FREE: {
  290. //Notify the lib handler that all devices are free
  291. HOST_ENTER_CRITICAL();
  292. p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE;
  293. _unblock_lib(false);
  294. HOST_EXIT_CRITICAL();
  295. break;
  296. }
  297. default:
  298. abort(); //Should never occur
  299. break;
  300. }
  301. }
  302. // ------------------- Client Related ----------------------
  303. static bool pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr)
  304. {
  305. endpoint_t *ep_obj = (endpoint_t *)user_arg;
  306. client_t *client_obj = (client_t *)ep_obj->constant.intf_obj->constant.client_obj;
  307. HOST_ENTER_CRITICAL_SAFE();
  308. //Store the event to be handled later. Note that we allow overwriting of events because more severe will halt the pipe prevent any further events.
  309. ep_obj->dynamic.last_event = pipe_event;
  310. //Add the EP to the client's pending list if it's not in the list already
  311. if (!ep_obj->dynamic.flags.pending) {
  312. ep_obj->dynamic.flags.pending = 1;
  313. TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, ep_obj, dynamic.tailq_entry);
  314. TAILQ_INSERT_TAIL(&client_obj->dynamic.pending_ep_tailq, ep_obj, dynamic.tailq_entry);
  315. }
  316. bool yield = _unblock_client(client_obj, in_isr);
  317. HOST_EXIT_CRITICAL_SAFE();
  318. return yield;
  319. }
  320. // ------------------------------------------------ Library Functions --------------------------------------------------
  321. // ----------------------- Public --------------------------
  322. esp_err_t usb_host_install(const usb_host_config_t *config)
  323. {
  324. HOST_CHECK(config != NULL, ESP_ERR_INVALID_ARG);
  325. HOST_ENTER_CRITICAL();
  326. HOST_CHECK_FROM_CRIT(p_host_lib_obj == NULL, ESP_ERR_INVALID_STATE);
  327. HOST_EXIT_CRITICAL();
  328. esp_err_t ret;
  329. host_lib_t *host_lib_obj = heap_caps_calloc(1, sizeof(host_lib_t), MALLOC_CAP_DEFAULT);
  330. SemaphoreHandle_t event_sem = xSemaphoreCreateBinary();
  331. SemaphoreHandle_t mux_lock = xSemaphoreCreateMutex();
  332. if (host_lib_obj == NULL || event_sem == NULL || mux_lock == NULL) {
  333. ret = ESP_ERR_NO_MEM;
  334. goto alloc_err;
  335. }
  336. //Initialize host library object
  337. TAILQ_INIT(&host_lib_obj->mux_protected.client_tailq);
  338. host_lib_obj->constant.event_sem = event_sem;
  339. host_lib_obj->constant.mux_lock = mux_lock;
  340. //Setup the USB PHY if necessary (USB PHY driver will also enable the underlying Host Controller)
  341. if (!config->skip_phy_setup) {
  342. //Host Library defaults to internal PHY
  343. usb_phy_config_t phy_config = {
  344. .controller = USB_PHY_CTRL_OTG,
  345. .target = USB_PHY_TARGET_INT,
  346. .otg_mode = USB_OTG_MODE_HOST,
  347. .otg_speed = USB_PHY_SPEED_UNDEFINED, //In Host mode, the speed is determined by the connected device
  348. .gpio_conf = NULL,
  349. };
  350. ret = usb_new_phy(&phy_config, &host_lib_obj->constant.phy_handle);
  351. if (ret != ESP_OK) {
  352. goto phy_err;
  353. }
  354. }
  355. //Install USBH
  356. usbh_config_t usbh_config = {
  357. .notif_cb = notif_callback,
  358. .notif_cb_arg = NULL,
  359. .ctrl_xfer_cb = ctrl_xfer_callback,
  360. .ctrl_xfer_cb_arg = NULL,
  361. .event_cb = dev_event_callback,
  362. .event_cb_arg = NULL,
  363. .hcd_config = {
  364. .intr_flags = config->intr_flags,
  365. },
  366. };
  367. ret = usbh_install(&usbh_config);
  368. if (ret != ESP_OK) {
  369. goto usbh_err;
  370. }
  371. //Install Hub
  372. hub_config_t hub_config = {
  373. .notif_cb = notif_callback,
  374. .notif_cb_arg = NULL,
  375. };
  376. ret = hub_install(&hub_config);
  377. if (ret != ESP_OK) {
  378. goto hub_err;
  379. }
  380. //Assign host library object
  381. HOST_ENTER_CRITICAL();
  382. if (p_host_lib_obj != NULL) {
  383. HOST_EXIT_CRITICAL();
  384. ret = ESP_ERR_INVALID_STATE;
  385. goto assign_err;
  386. }
  387. p_host_lib_obj = host_lib_obj;
  388. HOST_EXIT_CRITICAL();
  389. //Start the root hub
  390. ESP_ERROR_CHECK(hub_root_start());
  391. ret = ESP_OK;
  392. return ret;
  393. assign_err:
  394. ESP_ERROR_CHECK(hub_uninstall());
  395. hub_err:
  396. ESP_ERROR_CHECK(usbh_uninstall());
  397. usbh_err:
  398. if (p_host_lib_obj->constant.phy_handle) {
  399. ESP_ERROR_CHECK(usb_del_phy(p_host_lib_obj->constant.phy_handle));
  400. }
  401. phy_err:
  402. alloc_err:
  403. if (mux_lock) {
  404. vSemaphoreDelete(mux_lock);
  405. }
  406. if (event_sem) {
  407. vSemaphoreDelete(event_sem);
  408. }
  409. heap_caps_free(host_lib_obj);
  410. return ret;
  411. }
  412. esp_err_t usb_host_uninstall(void)
  413. {
  414. //All devices must have been freed at this point
  415. HOST_ENTER_CRITICAL();
  416. HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
  417. HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.process_pending_flags == 0 &&
  418. p_host_lib_obj->dynamic.lib_event_flags == 0 &&
  419. p_host_lib_obj->dynamic.flags.val == 0,
  420. ESP_ERR_INVALID_STATE);
  421. HOST_EXIT_CRITICAL();
  422. //Stop the root hub
  423. ESP_ERROR_CHECK(hub_root_stop());
  424. //Uninstall Hub and USBH
  425. ESP_ERROR_CHECK(hub_uninstall());
  426. ESP_ERROR_CHECK(usbh_uninstall());
  427. HOST_ENTER_CRITICAL();
  428. host_lib_t *host_lib_obj = p_host_lib_obj;
  429. p_host_lib_obj = NULL;
  430. HOST_EXIT_CRITICAL();
  431. //If the USB PHY was setup, then delete it
  432. if (host_lib_obj->constant.phy_handle) {
  433. ESP_ERROR_CHECK(usb_del_phy(host_lib_obj->constant.phy_handle));
  434. }
  435. //Free memory objects
  436. vSemaphoreDelete(host_lib_obj->constant.mux_lock);
  437. vSemaphoreDelete(host_lib_obj->constant.event_sem);
  438. heap_caps_free(host_lib_obj);
  439. return ESP_OK;
  440. }
  441. esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret)
  442. {
  443. esp_err_t ret;
  444. uint32_t event_flags = 0;
  445. HOST_ENTER_CRITICAL();
  446. if (!p_host_lib_obj->dynamic.flags.process_pending) {
  447. //There is currently processing that needs to be done. Wait for some processing
  448. HOST_EXIT_CRITICAL();
  449. BaseType_t sem_ret = xSemaphoreTake(p_host_lib_obj->constant.event_sem, timeout_ticks);
  450. if (sem_ret == pdFALSE) {
  451. ret = ESP_ERR_TIMEOUT;
  452. goto exit;
  453. }
  454. HOST_ENTER_CRITICAL();
  455. }
  456. //Read and clear process pending flags
  457. uint32_t process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags;
  458. p_host_lib_obj->dynamic.process_pending_flags = 0;
  459. p_host_lib_obj->dynamic.flags.handling_events = 1;
  460. while (process_pending_flags) {
  461. HOST_EXIT_CRITICAL();
  462. if (process_pending_flags & PROCESS_PENDING_FLAG_USBH) {
  463. ESP_ERROR_CHECK(usbh_process());
  464. }
  465. if (process_pending_flags & PROCESS_PENDING_FLAG_HUB) {
  466. ESP_ERROR_CHECK(hub_process());
  467. }
  468. HOST_ENTER_CRITICAL();
  469. //Read and clear process pending flags again, and loop back if there is more to process
  470. process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags;
  471. p_host_lib_obj->dynamic.process_pending_flags = 0;
  472. }
  473. p_host_lib_obj->dynamic.flags.process_pending = 0;
  474. p_host_lib_obj->dynamic.flags.handling_events = 0;
  475. event_flags = p_host_lib_obj->dynamic.lib_event_flags;
  476. p_host_lib_obj->dynamic.lib_event_flags = 0;
  477. HOST_EXIT_CRITICAL();
  478. ret = ESP_OK;
  479. exit:
  480. if (event_flags_ret != NULL) {
  481. *event_flags_ret = event_flags;
  482. }
  483. return ret;
  484. }
  485. esp_err_t usb_host_lib_unblock(void)
  486. {
  487. //All devices must have been freed at this point
  488. HOST_ENTER_CRITICAL();
  489. HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
  490. _unblock_lib(false);
  491. HOST_EXIT_CRITICAL();
  492. return ESP_OK;
  493. }
  494. esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret)
  495. {
  496. HOST_CHECK(info_ret != NULL, ESP_ERR_INVALID_ARG);
  497. int num_devs_temp;
  498. int num_clients_temp;
  499. HOST_ENTER_CRITICAL();
  500. HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
  501. num_clients_temp = p_host_lib_obj->dynamic.flags.num_clients;
  502. HOST_EXIT_CRITICAL();
  503. usbh_num_devs(&num_devs_temp);
  504. //Write back return values
  505. info_ret->num_devices = num_devs_temp;
  506. info_ret->num_clients = num_clients_temp;
  507. return ESP_OK;
  508. }
  509. // ------------------------------------------------ Client Functions ---------------------------------------------------
  510. // ----------------------- Private -------------------------
  511. static void _handle_pending_ep(client_t *client_obj)
  512. {
  513. //Handle each EP on the pending list
  514. while (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) {
  515. //Get the next pending EP.
  516. endpoint_t *ep_obj = TAILQ_FIRST(&client_obj->dynamic.pending_ep_tailq);
  517. TAILQ_REMOVE(&client_obj->dynamic.pending_ep_tailq, ep_obj, dynamic.tailq_entry);
  518. TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, ep_obj, dynamic.tailq_entry);
  519. ep_obj->dynamic.flags.pending = 0;
  520. hcd_pipe_event_t last_event = ep_obj->dynamic.last_event;
  521. uint32_t num_urb_dequeued = 0;
  522. HOST_EXIT_CRITICAL();
  523. //Handle pipe event
  524. switch (last_event) {
  525. case HCD_PIPE_EVENT_ERROR_XFER:
  526. case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL:
  527. case HCD_PIPE_EVENT_ERROR_OVERFLOW:
  528. case HCD_PIPE_EVENT_ERROR_STALL:
  529. //The pipe is now stalled. Flush all pending URBs
  530. ESP_ERROR_CHECK(hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_FLUSH));
  531. //All URBs in this pipe are now retired waiting to be dequeued. Fall through to dequeue them
  532. __attribute__((fallthrough));
  533. case HCD_PIPE_EVENT_URB_DONE: {
  534. //Dequeue all URBs and run their transfer callback
  535. urb_t *urb = hcd_urb_dequeue(ep_obj->constant.pipe_hdl);
  536. while (urb != NULL) {
  537. urb->transfer.callback(&urb->transfer);
  538. num_urb_dequeued++;
  539. urb = hcd_urb_dequeue(ep_obj->constant.pipe_hdl);
  540. }
  541. break;
  542. }
  543. default:
  544. abort(); //Should never occur
  545. break;
  546. }
  547. HOST_ENTER_CRITICAL();
  548. //Update the endpoint's number of URB's inflight
  549. assert(num_urb_dequeued <= ep_obj->dynamic.num_urb_inflight);
  550. ep_obj->dynamic.num_urb_inflight -= num_urb_dequeued;
  551. }
  552. }
  553. // ----------------------- Public --------------------------
  554. esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret)
  555. {
  556. HOST_CHECK(p_host_lib_obj, ESP_ERR_INVALID_STATE);
  557. HOST_CHECK(client_config != NULL && client_hdl_ret != NULL, ESP_ERR_INVALID_ARG);
  558. HOST_CHECK(client_config->max_num_event_msg > 0, ESP_ERR_INVALID_ARG);
  559. if (!client_config->is_synchronous) {
  560. //Asynchronous clients must provide a
  561. HOST_CHECK(client_config->async.client_event_callback != NULL, ESP_ERR_INVALID_ARG);
  562. }
  563. esp_err_t ret;
  564. //Create client object
  565. client_t *client_obj = heap_caps_calloc(1, sizeof(client_t), MALLOC_CAP_DEFAULT);
  566. SemaphoreHandle_t event_sem = xSemaphoreCreateBinary();
  567. QueueHandle_t event_msg_queue = xQueueCreate(client_config->max_num_event_msg, sizeof(usb_host_client_event_msg_t));
  568. if (client_obj == NULL || event_sem == NULL || event_msg_queue == NULL) {
  569. ret = ESP_ERR_NO_MEM;
  570. goto alloc_err;
  571. }
  572. //Initialize client object
  573. TAILQ_INIT(&client_obj->dynamic.pending_ep_tailq);
  574. TAILQ_INIT(&client_obj->dynamic.idle_ep_tailq);
  575. TAILQ_INIT(&client_obj->mux_protected.interface_tailq);
  576. TAILQ_INIT(&client_obj->dynamic.done_ctrl_xfer_tailq);
  577. client_obj->constant.event_sem = event_sem;
  578. client_obj->constant.event_callback = client_config->async.client_event_callback;
  579. client_obj->constant.callback_arg = client_config->async.callback_arg;
  580. client_obj->constant.event_msg_queue = event_msg_queue;
  581. //Add client to the host library's list of clients
  582. xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
  583. HOST_ENTER_CRITICAL();
  584. p_host_lib_obj->dynamic.flags.num_clients++;
  585. HOST_EXIT_CRITICAL();
  586. TAILQ_INSERT_TAIL(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry);
  587. xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
  588. //Write back client handle
  589. *client_hdl_ret = (usb_host_client_handle_t)client_obj;
  590. ret = ESP_OK;
  591. return ret;
  592. alloc_err:
  593. if (event_msg_queue) {
  594. vQueueDelete(event_msg_queue);
  595. }
  596. if (event_sem) {
  597. vSemaphoreDelete(event_sem);
  598. }
  599. heap_caps_free(client_obj);
  600. return ESP_OK;
  601. }
  602. esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl)
  603. {
  604. HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
  605. client_t *client_obj = (client_t *)client_hdl;
  606. esp_err_t ret;
  607. //We take the mux_lock because we need to access the host library's client_tailq
  608. xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
  609. HOST_ENTER_CRITICAL();
  610. //Check that client can currently deregistered
  611. bool can_deregister;
  612. if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) ||
  613. !TAILQ_EMPTY(&client_obj->dynamic.idle_ep_tailq) ||
  614. !TAILQ_EMPTY(&client_obj->dynamic.done_ctrl_xfer_tailq) ||
  615. client_obj->dynamic.flags.handling_events ||
  616. client_obj->dynamic.flags.blocked ||
  617. client_obj->dynamic.flags.taking_mux ||
  618. client_obj->dynamic.flags.num_intf_claimed != 0 ||
  619. client_obj->dynamic.num_done_ctrl_xfer != 0 ||
  620. client_obj->dynamic.opened_dev_addr_map != 0) {
  621. can_deregister = false;
  622. } else {
  623. can_deregister = true;
  624. }
  625. HOST_EXIT_CRITICAL();
  626. if (!can_deregister) {
  627. ret = ESP_ERR_INVALID_STATE;
  628. goto exit;
  629. }
  630. //Remove client object from the library's list of clients
  631. TAILQ_REMOVE(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry);
  632. HOST_ENTER_CRITICAL();
  633. p_host_lib_obj->dynamic.flags.num_clients--;
  634. if (p_host_lib_obj->dynamic.flags.num_clients == 0) {
  635. //This is the last client being deregistered. Notify the lib handler
  636. p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS;
  637. _unblock_lib(false);
  638. }
  639. HOST_EXIT_CRITICAL();
  640. //Free client object
  641. vQueueDelete(client_obj->constant.event_msg_queue);
  642. vSemaphoreDelete(client_obj->constant.event_sem);
  643. heap_caps_free(client_obj);
  644. ret = ESP_OK;
  645. exit:
  646. xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
  647. return ret;
  648. }
  649. esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks)
  650. {
  651. HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
  652. esp_err_t ret;
  653. client_t *client_obj = (client_t *)client_hdl;
  654. HOST_ENTER_CRITICAL();
  655. if (!client_obj->dynamic.flags.events_pending) {
  656. //There are currently no events, wait for one to occur
  657. client_obj->dynamic.flags.blocked = 1;
  658. HOST_EXIT_CRITICAL();
  659. BaseType_t sem_ret = xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks);
  660. HOST_ENTER_CRITICAL();
  661. client_obj->dynamic.flags.blocked = 0;
  662. if (sem_ret == pdFALSE) {
  663. HOST_EXIT_CRITICAL();
  664. //Timed out waiting for semaphore
  665. ret = ESP_ERR_TIMEOUT;
  666. goto exit;
  667. }
  668. }
  669. //Mark that we're processing events
  670. client_obj->dynamic.flags.handling_events = 1;
  671. while (client_obj->dynamic.flags.handling_events) {
  672. //Handle pending endpoints
  673. if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) {
  674. _handle_pending_ep(client_obj);
  675. }
  676. //Handle any done control transfers
  677. while (client_obj->dynamic.num_done_ctrl_xfer > 0) {
  678. urb_t *urb = TAILQ_FIRST(&client_obj->dynamic.done_ctrl_xfer_tailq);
  679. TAILQ_REMOVE(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry);
  680. client_obj->dynamic.num_done_ctrl_xfer--;
  681. HOST_EXIT_CRITICAL();
  682. //Call the transfer's callback
  683. urb->transfer.callback(&urb->transfer);
  684. HOST_ENTER_CRITICAL();
  685. }
  686. //Handle event messages
  687. while (uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) > 0) {
  688. HOST_EXIT_CRITICAL();
  689. //Dequeue the event message and call the client event callback
  690. usb_host_client_event_msg_t event_msg;
  691. BaseType_t queue_ret = xQueueReceive(client_obj->constant.event_msg_queue, &event_msg, 0);
  692. assert(queue_ret == pdTRUE);
  693. client_obj->constant.event_callback(&event_msg, client_obj->constant.callback_arg);
  694. HOST_ENTER_CRITICAL();
  695. }
  696. //Check each event again to see any new events occurred
  697. if (TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) &&
  698. client_obj->dynamic.num_done_ctrl_xfer == 0 &&
  699. uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) == 0) {
  700. //All pending endpoints and event messages handled
  701. client_obj->dynamic.flags.events_pending = 0;
  702. client_obj->dynamic.flags.handling_events = 0;
  703. }
  704. }
  705. HOST_EXIT_CRITICAL();
  706. ret = ESP_OK;
  707. exit:
  708. return ret;
  709. }
  710. esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl)
  711. {
  712. HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
  713. client_t *client_obj = (client_t *)client_hdl;
  714. HOST_ENTER_CRITICAL();
  715. _unblock_client(client_obj, false);
  716. HOST_EXIT_CRITICAL();
  717. return ESP_OK;
  718. }
  719. // ------------------------------------------------- Device Handling ---------------------------------------------------
  720. esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret)
  721. {
  722. HOST_CHECK(dev_addr > 0 && client_hdl != NULL && dev_hdl_ret != NULL, ESP_ERR_INVALID_ARG);
  723. client_t *client_obj = (client_t *)client_hdl;
  724. esp_err_t ret;
  725. usb_device_handle_t dev_hdl;
  726. ret = usbh_dev_open(dev_addr, &dev_hdl);
  727. if (ret != ESP_OK) {
  728. goto exit;
  729. }
  730. HOST_ENTER_CRITICAL();
  731. if (_check_client_opened_device(client_obj, dev_addr)) {
  732. //Client has already opened the device. Close it and return an error
  733. ret = ESP_ERR_INVALID_STATE;
  734. HOST_EXIT_CRITICAL();
  735. goto already_opened;
  736. }
  737. //Record in client object that we have opened the device of this address
  738. _record_client_opened_device(client_obj, dev_addr);
  739. HOST_EXIT_CRITICAL();
  740. *dev_hdl_ret = dev_hdl;
  741. ret = ESP_OK;
  742. return ret;
  743. already_opened:
  744. ESP_ERROR_CHECK(usbh_dev_close(dev_hdl));
  745. exit:
  746. return ret;
  747. }
  748. esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl)
  749. {
  750. HOST_CHECK(dev_hdl != NULL && client_hdl != NULL, ESP_ERR_INVALID_ARG);
  751. client_t *client_obj = (client_t *)client_hdl;
  752. //We take the lock because we need to walk the interface list
  753. xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
  754. esp_err_t ret;
  755. //Check that all interfaces claimed by this client do not belong to this device
  756. bool all_released = true;
  757. interface_t *intf_obj;
  758. TAILQ_FOREACH(intf_obj, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) {
  759. if (intf_obj->constant.dev_hdl == dev_hdl) {
  760. all_released = false;
  761. break;
  762. }
  763. }
  764. if (!all_released) {
  765. ret = ESP_ERR_INVALID_STATE;
  766. goto exit;
  767. }
  768. //Check that client actually opened the device in the first place
  769. HOST_ENTER_CRITICAL();
  770. uint8_t dev_addr;
  771. ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
  772. HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_NOT_FOUND);
  773. if (!_check_client_opened_device(client_obj, dev_addr)) {
  774. //Client never opened this device
  775. ret = ESP_ERR_INVALID_STATE;
  776. HOST_EXIT_CRITICAL();
  777. goto exit;
  778. }
  779. //Proceed to clear the record of the device form the client
  780. _clear_client_opened_device(client_obj, dev_addr);
  781. HOST_EXIT_CRITICAL();
  782. ESP_ERROR_CHECK(usbh_dev_close(dev_hdl));
  783. ret = ESP_OK;
  784. exit:
  785. xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
  786. return ret;
  787. }
  788. esp_err_t usb_host_device_free_all(void)
  789. {
  790. HOST_ENTER_CRITICAL();
  791. HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.flags.num_clients == 0, ESP_ERR_INVALID_STATE); //All clients must have been deregistered
  792. HOST_EXIT_CRITICAL();
  793. esp_err_t ret;
  794. ret = usbh_dev_mark_all_free();
  795. //If ESP_ERR_NOT_FINISHED is returned, caller must wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices are free
  796. return ret;
  797. }
  798. esp_err_t usb_host_device_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret)
  799. {
  800. HOST_CHECK(dev_addr_list != NULL && num_dev_ret != NULL, ESP_ERR_INVALID_ARG);
  801. return usbh_dev_addr_list_fill(list_len, dev_addr_list, num_dev_ret);
  802. }
  803. // ------------------------------------------------- Device Requests ---------------------------------------------------
  804. // ------------------- Cached Requests ---------------------
  805. esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info)
  806. {
  807. HOST_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG);
  808. return usbh_dev_get_info(dev_hdl, dev_info);
  809. }
  810. // ----------------------------------------------- Descriptor Requests -------------------------------------------------
  811. // ----------------- Cached Descriptors --------------------
  812. esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc)
  813. {
  814. HOST_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG);
  815. return usbh_dev_get_desc(dev_hdl, device_desc);
  816. }
  817. esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc)
  818. {
  819. HOST_CHECK(dev_hdl != NULL && config_desc != NULL, ESP_ERR_INVALID_ARG);
  820. return usbh_dev_get_config_desc(dev_hdl, config_desc);
  821. }
  822. // ----------------------------------------------- Interface Functions -------------------------------------------------
  823. // ----------------------- Private -------------------------
  824. static esp_err_t endpoint_alloc(usb_device_handle_t dev_hdl, const usb_ep_desc_t *ep_desc, interface_t *intf_obj, endpoint_t **ep_obj_ret)
  825. {
  826. endpoint_t *ep_obj = heap_caps_calloc(1, sizeof(endpoint_t), MALLOC_CAP_DEFAULT);
  827. if (ep_obj == NULL) {
  828. return ESP_ERR_NO_MEM;
  829. }
  830. esp_err_t ret;
  831. usbh_ep_config_t ep_config = {
  832. .ep_desc = ep_desc,
  833. .pipe_cb = pipe_callback,
  834. .pipe_cb_arg = (void *)ep_obj,
  835. .context = (void *)ep_obj,
  836. };
  837. hcd_pipe_handle_t pipe_hdl;
  838. ret = usbh_ep_alloc(dev_hdl, &ep_config, &pipe_hdl);
  839. if (ret != ESP_OK) {
  840. goto ep_alloc_err;
  841. }
  842. //Initialize endpoint object
  843. ep_obj->constant.pipe_hdl = pipe_hdl;
  844. ep_obj->constant.ep_desc = ep_desc;
  845. ep_obj->constant.intf_obj = intf_obj;
  846. //Write back result
  847. *ep_obj_ret = ep_obj;
  848. ret = ESP_OK;
  849. return ret;
  850. ep_alloc_err:
  851. heap_caps_free(ep_obj);
  852. return ret;
  853. }
  854. static void endpoint_free(usb_device_handle_t dev_hdl, endpoint_t *ep_obj)
  855. {
  856. if (ep_obj == NULL) {
  857. return;
  858. }
  859. //Free the underlying endpoint
  860. ESP_ERROR_CHECK(usbh_ep_free(dev_hdl, ep_obj->constant.ep_desc->bEndpointAddress));
  861. //Free the endpoint object
  862. heap_caps_free(ep_obj);
  863. }
  864. static interface_t *interface_alloc(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_intf_desc_t *intf_desc)
  865. {
  866. interface_t *intf_obj = heap_caps_calloc(1, sizeof(interface_t) + (sizeof(endpoint_t *) * intf_desc->bNumEndpoints), MALLOC_CAP_DEFAULT);
  867. if (intf_obj == NULL) {
  868. return NULL;
  869. }
  870. intf_obj->constant.intf_desc = intf_desc;
  871. intf_obj->constant.client_obj = client_obj;
  872. intf_obj->constant.dev_hdl = dev_hdl;
  873. return intf_obj;
  874. }
  875. static void interface_free(interface_t *intf_obj)
  876. {
  877. if (intf_obj == NULL) {
  878. return;
  879. }
  880. for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
  881. assert(intf_obj->constant.endpoints[i] == NULL);
  882. }
  883. heap_caps_free(intf_obj);
  884. }
  885. static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, interface_t **intf_obj_ret)
  886. {
  887. esp_err_t ret;
  888. //We need to walk to configuration descriptor to find the correct interface descriptor, and each of its constituent endpoint descriptors
  889. //Find the interface descriptor and allocate the interface object
  890. int offset_intf;
  891. const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
  892. if (intf_desc == NULL) {
  893. ret = ESP_ERR_NOT_FOUND;
  894. goto exit;
  895. }
  896. //Allocate interface object
  897. interface_t *intf_obj = interface_alloc(client_obj, dev_hdl, intf_desc);
  898. if (intf_obj == NULL) {
  899. ret = ESP_ERR_NO_MEM;
  900. goto exit;
  901. }
  902. //Find each endpoint descriptor in the interface by index, and allocate those endpoints
  903. for (int i = 0; i < intf_desc->bNumEndpoints; i++) {
  904. int offset_ep = offset_intf;
  905. const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, i, config_desc->wTotalLength, &offset_ep);
  906. if (ep_desc == NULL) {
  907. ret = ESP_ERR_NOT_FOUND;
  908. goto ep_alloc_err;
  909. }
  910. //Allocate the endpoint
  911. endpoint_t *ep_obj;
  912. ret = endpoint_alloc(dev_hdl, ep_desc, intf_obj, &ep_obj);
  913. if (ret != ESP_OK) {
  914. goto ep_alloc_err;
  915. }
  916. //Fill the interface object with the allocated endpoints
  917. intf_obj->constant.endpoints[i] = ep_obj;
  918. }
  919. //Add interface object to client (safe because we have already taken the mutex)
  920. TAILQ_INSERT_TAIL(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry);
  921. //Add each endpoint to the client's endpoint list
  922. HOST_ENTER_CRITICAL();
  923. for (int i = 0; i < intf_desc->bNumEndpoints; i++) {
  924. TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry);
  925. }
  926. HOST_EXIT_CRITICAL();
  927. //Write back result
  928. *intf_obj_ret = intf_obj;
  929. ret = ESP_OK;
  930. return ret;
  931. ep_alloc_err:
  932. for (int i = 0; i < intf_desc->bNumEndpoints; i++) {
  933. endpoint_free(dev_hdl, intf_obj->constant.endpoints[i]);
  934. intf_obj->constant.endpoints[i] = NULL;
  935. }
  936. interface_free(intf_obj);
  937. exit:
  938. return ret;
  939. }
  940. static esp_err_t interface_release(client_t *client_obj, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber)
  941. {
  942. esp_err_t ret;
  943. //Find the interface object
  944. interface_t *intf_obj_iter;
  945. interface_t *intf_obj = NULL;
  946. TAILQ_FOREACH(intf_obj_iter, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) {
  947. if (intf_obj_iter->constant.dev_hdl == dev_hdl && intf_obj_iter->constant.intf_desc->bInterfaceNumber == bInterfaceNumber) {
  948. intf_obj = intf_obj_iter;
  949. break;
  950. }
  951. }
  952. if (intf_obj == NULL) {
  953. ret = ESP_ERR_NOT_FOUND;
  954. goto exit;
  955. }
  956. //Check that all endpoints in the interface are in a state to be freed
  957. HOST_ENTER_CRITICAL();
  958. bool can_free = true;
  959. for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
  960. endpoint_t *ep_obj = intf_obj->constant.endpoints[i];
  961. //Endpoint must not be on the pending list and must not have inflight URBs
  962. if (ep_obj->dynamic.num_urb_inflight != 0 || ep_obj->dynamic.flags.pending) {
  963. can_free = false;
  964. break;
  965. }
  966. }
  967. if (!can_free) {
  968. HOST_EXIT_CRITICAL();
  969. ret = ESP_ERR_INVALID_STATE;
  970. goto exit;
  971. }
  972. //Proceed to remove all endpoint objects from list
  973. for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
  974. TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry);
  975. }
  976. HOST_EXIT_CRITICAL();
  977. //Remove the interface object from the list (safe because we have already taken the mutex)
  978. TAILQ_REMOVE(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry);
  979. //Free each endpoint in the interface
  980. for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
  981. endpoint_free(dev_hdl, intf_obj->constant.endpoints[i]);
  982. intf_obj->constant.endpoints[i] = NULL;
  983. }
  984. //Free the interface object itself
  985. interface_free(intf_obj);
  986. ret = ESP_OK;
  987. exit:
  988. return ret;
  989. }
  990. // ----------------------- Public --------------------------
  991. esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
  992. {
  993. HOST_CHECK(client_hdl != NULL && dev_hdl != NULL, ESP_ERR_INVALID_ARG);
  994. client_t *client_obj = (client_t *)client_hdl;
  995. HOST_ENTER_CRITICAL();
  996. uint8_t dev_addr;
  997. ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
  998. //Check if client actually opened device
  999. HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE);
  1000. client_obj->dynamic.flags.taking_mux = 1;
  1001. HOST_EXIT_CRITICAL();
  1002. //Take mux lock. This protects the client being released or other clients from claiming interfaces
  1003. xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
  1004. esp_err_t ret;
  1005. const usb_config_desc_t *config_desc;
  1006. ESP_ERROR_CHECK(usbh_dev_get_config_desc(dev_hdl, &config_desc));
  1007. interface_t *intf_obj;
  1008. //Claim interface
  1009. ret = interface_claim(client_obj, dev_hdl, config_desc, bInterfaceNumber, bAlternateSetting, &intf_obj);
  1010. if (ret != ESP_OK) {
  1011. goto exit;
  1012. }
  1013. ret = ESP_OK;
  1014. exit:
  1015. xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
  1016. HOST_ENTER_CRITICAL();
  1017. if (ret == ESP_OK) {
  1018. client_obj->dynamic.flags.num_intf_claimed++;
  1019. }
  1020. client_obj->dynamic.flags.taking_mux = 0;
  1021. HOST_EXIT_CRITICAL();
  1022. return ret;
  1023. }
  1024. esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber)
  1025. {
  1026. HOST_CHECK(client_hdl != NULL && dev_hdl != NULL, ESP_ERR_INVALID_ARG);
  1027. client_t *client_obj = (client_t *)client_hdl;
  1028. HOST_ENTER_CRITICAL();
  1029. uint8_t dev_addr;
  1030. ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
  1031. //Check if client actually opened device
  1032. HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE);
  1033. client_obj->dynamic.flags.taking_mux = 1;
  1034. HOST_EXIT_CRITICAL();
  1035. //Take mux lock. This protects the client being released or other clients from claiming interfaces
  1036. xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
  1037. esp_err_t ret = interface_release(client_obj, dev_hdl, bInterfaceNumber);
  1038. xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
  1039. HOST_ENTER_CRITICAL();
  1040. if (ret == ESP_OK) {
  1041. client_obj->dynamic.flags.num_intf_claimed--;
  1042. }
  1043. client_obj->dynamic.flags.taking_mux = 0;
  1044. HOST_EXIT_CRITICAL();
  1045. return ret;
  1046. }
  1047. esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress)
  1048. {
  1049. esp_err_t ret;
  1050. endpoint_t *ep_obj = NULL;
  1051. ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj);
  1052. if (ret != ESP_OK) {
  1053. goto exit;
  1054. }
  1055. assert(ep_obj != NULL);
  1056. ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_HALT);
  1057. exit:
  1058. return ret;
  1059. }
  1060. esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress)
  1061. {
  1062. esp_err_t ret;
  1063. endpoint_t *ep_obj = NULL;
  1064. ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj);
  1065. if (ret != ESP_OK) {
  1066. goto exit;
  1067. }
  1068. assert(ep_obj != NULL);
  1069. ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_FLUSH);
  1070. exit:
  1071. return ret;
  1072. }
  1073. esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress)
  1074. {
  1075. esp_err_t ret;
  1076. endpoint_t *ep_obj = NULL;
  1077. ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj);
  1078. if (ret != ESP_OK) {
  1079. goto exit;
  1080. }
  1081. assert(ep_obj != NULL);
  1082. ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_CLEAR);
  1083. exit:
  1084. return ret;
  1085. }
  1086. // ------------------------------------------------ Asynchronous I/O ---------------------------------------------------
  1087. // ----------------------- Private -------------------------
  1088. static bool transfer_check(usb_transfer_t *transfer, usb_transfer_type_t type, int mps, bool is_in)
  1089. {
  1090. if (transfer->callback == NULL) {
  1091. ESP_LOGE(USB_HOST_TAG, "Transfer callback is NULL");
  1092. return false;
  1093. }
  1094. //Check that the total transfer length does not exceed data buffer size
  1095. if (transfer->num_bytes > transfer->data_buffer_size) {
  1096. ESP_LOGE(USB_HOST_TAG, "Transfer num_bytes > data_buffer_size");
  1097. return false;
  1098. }
  1099. if (type == USB_TRANSFER_TYPE_CTRL) {
  1100. //Check that num_bytes and wLength are set correctly
  1101. usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)transfer->data_buffer;
  1102. if (transfer->num_bytes != sizeof(usb_setup_packet_t) + setup_pkt->wLength) {
  1103. ESP_LOGE(USB_HOST_TAG, "Control transfer num_bytes wLength mismatch");
  1104. return false;
  1105. }
  1106. } else if (type == USB_TRANSFER_TYPE_ISOCHRONOUS) {
  1107. //Check that there is at least one isochronous packet descriptor
  1108. if (transfer->num_isoc_packets <= 0) {
  1109. ESP_LOGE(USB_HOST_TAG, "ISOC transfer has 0 packet descriptors");
  1110. return false;
  1111. }
  1112. //Check that sum of all packet lengths add up to transfer length
  1113. //If IN, check that each packet length is integer multiple of MPS
  1114. int total_num_bytes = 0;
  1115. bool mod_mps_all_zero = true;
  1116. for (int i = 0; i < transfer->num_isoc_packets; i++) {
  1117. total_num_bytes += transfer->isoc_packet_desc[i].num_bytes;
  1118. if (transfer->isoc_packet_desc[i].num_bytes % mps != 0) {
  1119. mod_mps_all_zero = false;
  1120. }
  1121. }
  1122. if (transfer->num_bytes != total_num_bytes) {
  1123. ESP_LOGE(USB_HOST_TAG, "ISOC transfer num_bytes not equal to total num_bytes of all packets");
  1124. return false;
  1125. }
  1126. if (is_in && !mod_mps_all_zero) {
  1127. ESP_LOGE(USB_HOST_TAG, "ISOC IN transfer all packets num_bytes must be integer multiple of MPS");
  1128. return false;
  1129. }
  1130. } else {
  1131. //Check that IN transfers are integer multiple of MPS
  1132. if (is_in && (transfer->num_bytes % mps != 0)) {
  1133. ESP_LOGE(USB_HOST_TAG, "IN transfer num_bytes must be integer multiple of MPS");
  1134. return false;
  1135. }
  1136. }
  1137. return true;
  1138. }
  1139. // ----------------------- Public --------------------------
  1140. esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer)
  1141. {
  1142. urb_t *urb = urb_alloc(data_buffer_size, 0, num_isoc_packets);
  1143. if (urb == NULL) {
  1144. return ESP_ERR_NO_MEM;
  1145. }
  1146. *transfer = &urb->transfer;
  1147. return ESP_OK;
  1148. }
  1149. esp_err_t usb_host_transfer_free(usb_transfer_t *transfer)
  1150. {
  1151. if (transfer == NULL) {
  1152. return ESP_OK;
  1153. }
  1154. urb_t *urb = __containerof(transfer, urb_t, transfer);
  1155. urb_free(urb);
  1156. return ESP_OK;
  1157. }
  1158. esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer)
  1159. {
  1160. HOST_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG);
  1161. //Check that transfer and target endpoint are valid
  1162. HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set
  1163. HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG);
  1164. endpoint_t *ep_obj = NULL;
  1165. urb_t *urb_obj = __containerof(transfer, urb_t, transfer);
  1166. esp_err_t ret;
  1167. ret = usbh_ep_get_context(transfer->device_handle, transfer->bEndpointAddress, (void **)&ep_obj);
  1168. if (ret != ESP_OK) {
  1169. goto err;
  1170. }
  1171. assert(ep_obj != NULL);
  1172. HOST_CHECK(transfer_check(transfer,
  1173. USB_EP_DESC_GET_XFERTYPE(ep_obj->constant.ep_desc),
  1174. USB_EP_DESC_GET_MPS(ep_obj->constant.ep_desc),
  1175. transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK), ESP_ERR_INVALID_ARG);
  1176. HOST_ENTER_CRITICAL();
  1177. ep_obj->dynamic.num_urb_inflight++;
  1178. HOST_EXIT_CRITICAL();
  1179. //Check if pipe is in a state to enqueue URBs
  1180. if (hcd_pipe_get_state(ep_obj->constant.pipe_hdl) != HCD_PIPE_STATE_ACTIVE) {
  1181. ret = ESP_ERR_INVALID_STATE;
  1182. goto hcd_err;
  1183. }
  1184. ret = hcd_urb_enqueue(ep_obj->constant.pipe_hdl, urb_obj);
  1185. if (ret != ESP_OK) {
  1186. goto hcd_err;
  1187. }
  1188. ret = ESP_OK;
  1189. return ret;
  1190. hcd_err:
  1191. HOST_ENTER_CRITICAL();
  1192. ep_obj->dynamic.num_urb_inflight--;
  1193. HOST_EXIT_CRITICAL();
  1194. err:
  1195. return ret;
  1196. }
  1197. esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer)
  1198. {
  1199. HOST_CHECK(client_hdl != NULL && transfer != NULL, ESP_ERR_INVALID_ARG);
  1200. //Check that control transfer is valid
  1201. HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set
  1202. usb_device_handle_t dev_hdl = transfer->device_handle;
  1203. bool xfer_is_in = ((usb_setup_packet_t *)transfer->data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_OUT;
  1204. usb_device_info_t dev_info;
  1205. ESP_ERROR_CHECK(usbh_dev_get_info(dev_hdl, &dev_info));
  1206. HOST_CHECK(transfer_check(transfer, USB_TRANSFER_TYPE_CTRL, dev_info.bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG);
  1207. //Control transfers must be targeted at EP 0
  1208. HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) == 0, ESP_ERR_INVALID_ARG);
  1209. //Save client handle into URB
  1210. urb_t *urb_obj = __containerof(transfer, urb_t, transfer);
  1211. urb_obj->usb_host_client = (void *)client_hdl;
  1212. return usbh_dev_submit_ctrl_urb(dev_hdl, urb_obj);
  1213. }