usb_host.c 47 KB

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