usb_host.c 47 KB

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