usbhost_enumerate.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /****************************************************************************
  2. * drivers/usbhost/usbhost_enumerate.c
  3. *
  4. * Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
  5. * Authors: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <stdint.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43. #include <errno.h>
  44. #include <assert.h>
  45. #include <debug.h>
  46. #include <nuttx/arch.h>
  47. #include <nuttx/usb/usb.h>
  48. #include <nuttx/usb/usbhost.h>
  49. #include <nuttx/usb/hub.h>
  50. #include <nuttx/usb/usbhost_devaddr.h>
  51. #include "usbhost_composite.h"
  52. /****************************************************************************
  53. * Private Function Prototypes
  54. ****************************************************************************/
  55. static inline uint16_t usbhost_getle16(const uint8_t *val);
  56. static void usbhost_putle16(uint8_t *dest, uint16_t val);
  57. static inline int usbhost_devdesc(const struct usb_devdesc_s *devdesc,
  58. FAR struct usbhost_id_s *id);
  59. static inline int usbhost_configdesc(const uint8_t *configdesc, int desclen,
  60. FAR struct usbhost_id_s *id);
  61. static inline int usbhost_classbind(FAR struct usbhost_hubport_s *hport,
  62. FAR const uint8_t *configdesc, int desclen,
  63. FAR struct usbhost_id_s *id,
  64. FAR struct usbhost_class_s **devclass);
  65. /****************************************************************************
  66. * Private Functions
  67. ****************************************************************************/
  68. /****************************************************************************
  69. * Name: usbhost_getle16
  70. *
  71. * Description:
  72. * Get a (possibly unaligned) 16-bit little endian value.
  73. *
  74. ****************************************************************************/
  75. static inline uint16_t usbhost_getle16(const uint8_t *val)
  76. {
  77. return (uint16_t)val[1] << 8 | (uint16_t)val[0];
  78. }
  79. /****************************************************************************
  80. * Name: usbhost_putle16
  81. *
  82. * Description:
  83. * Put a (possibly unaligned) 16-bit little endian value.
  84. *
  85. ****************************************************************************/
  86. static void usbhost_putle16(uint8_t *dest, uint16_t val)
  87. {
  88. dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
  89. dest[1] = val >> 8;
  90. }
  91. /****************************************************************************
  92. * Name: usbhost_devdesc
  93. *
  94. * Description:
  95. * A configuration descriptor has been obtained from the device. Find the
  96. * ID information for the class that supports this device.
  97. *
  98. ****************************************************************************/
  99. static inline int usbhost_devdesc(FAR const struct usb_devdesc_s *devdesc,
  100. FAR struct usbhost_id_s *id)
  101. {
  102. /* Clear the ID info */
  103. memset(id, 0, sizeof(struct usbhost_id_s));
  104. /* Pick off the class ID info */
  105. id->base = devdesc->classid;
  106. id->subclass = devdesc->subclass;
  107. id->proto = devdesc->protocol;
  108. /* Pick off the VID and PID as well (for vendor specfic devices) */
  109. id->vid = usbhost_getle16(devdesc->vendor);
  110. id->pid = usbhost_getle16(devdesc->product);
  111. uinfo("class:%d subclass:%04x protocol:%04x vid:%d pid:%d\n",
  112. id->base, id->subclass, id->proto, id->vid, id->pid);
  113. return OK;
  114. }
  115. /****************************************************************************
  116. * Name: usbhost_configdesc
  117. *
  118. * Description:
  119. * A configuration descriptor has been obtained from the device. Find the
  120. * ID information for the class that supports this device.
  121. *
  122. ****************************************************************************/
  123. static inline int usbhost_configdesc(const uint8_t *configdesc, int cfglen,
  124. struct usbhost_id_s *id)
  125. {
  126. FAR struct usb_cfgdesc_s *cfgdesc;
  127. FAR struct usb_ifdesc_s *ifdesc;
  128. int remaining;
  129. DEBUGASSERT(configdesc != NULL && cfglen >= USB_SIZEOF_CFGDESC);
  130. /* Verify that we were passed a configuration descriptor */
  131. cfgdesc = (struct usb_cfgdesc_s *)configdesc;
  132. uinfo("cfg len:%d total len:%d\n", cfgdesc->len, cfglen);
  133. if (cfgdesc->type != USB_DESC_TYPE_CONFIG)
  134. {
  135. return -EINVAL;
  136. }
  137. /* Skip to the next entry descriptor */
  138. configdesc += cfgdesc->len;
  139. remaining = cfglen - cfgdesc->len;
  140. /* Loop while there are more descriptors to examine */
  141. memset(id, 0, sizeof(FAR struct usb_desc_s));
  142. while (remaining >= sizeof(struct usb_desc_s))
  143. {
  144. /* What is the next descriptor? Is it an interface descriptor? */
  145. ifdesc = (struct usb_ifdesc_s *)configdesc;
  146. if (ifdesc->type == USB_DESC_TYPE_INTERFACE)
  147. {
  148. /* Yes, extract the class information from the interface descriptor.
  149. * Typically these values are zero meaning that the "real" ID
  150. * information resides in the device descriptor.
  151. */
  152. DEBUGASSERT(remaining >= sizeof(struct usb_ifdesc_s));
  153. id->base = ifdesc->classid;
  154. id->subclass = ifdesc->subclass;
  155. id->proto = ifdesc->protocol;
  156. uinfo("class:%d subclass:%d protocol:%d\n",
  157. id->base, id->subclass, id->proto);
  158. return OK;
  159. }
  160. /* Increment the address of the next descriptor */
  161. configdesc += ifdesc->len;
  162. remaining -= ifdesc->len;
  163. }
  164. return -ENOENT;
  165. }
  166. /****************************************************************************
  167. * Name: usbhost_classbind
  168. *
  169. * Description:
  170. * A configuration descriptor has been obtained from the device. Try to
  171. * bind this configuration descriptor with a supported class.
  172. *
  173. ****************************************************************************/
  174. static inline int usbhost_classbind(FAR struct usbhost_hubport_s *hport,
  175. const uint8_t *configdesc, int desclen,
  176. struct usbhost_id_s *id,
  177. FAR struct usbhost_class_s **usbclass)
  178. {
  179. FAR struct usbhost_class_s *devclass;
  180. FAR const struct usbhost_registry_s *reg;
  181. int ret = -EINVAL;
  182. /* Is there is a class implementation registered to support this device. */
  183. reg = usbhost_findclass(id);
  184. uinfo("usbhost_findclass: %p\n", reg);
  185. if (reg != NULL)
  186. {
  187. /* Yes.. there is a class for this device. Get an instance of
  188. * its interface.
  189. */
  190. ret = -ENOMEM;
  191. devclass = CLASS_CREATE(reg, hport, id);
  192. uinfo("CLASS_CREATE: %p\n", devclass);
  193. if (devclass != NULL)
  194. {
  195. /* Then bind the newly instantiated class instance */
  196. ret = CLASS_CONNECT(devclass, configdesc, desclen);
  197. if (ret < 0)
  198. {
  199. /* On failures, call the class disconnect method which
  200. * should then free the allocated devclass instance.
  201. */
  202. uerr("ERROR: CLASS_CONNECT failed: %d\n", ret);
  203. CLASS_DISCONNECTED(devclass);
  204. }
  205. else
  206. {
  207. *usbclass = devclass;
  208. }
  209. }
  210. }
  211. uinfo("Returning: %d\n", ret);
  212. return ret;
  213. }
  214. /****************************************************************************
  215. * Public Functions
  216. ****************************************************************************/
  217. /****************************************************************************
  218. * Name: usbhost_enumerate
  219. *
  220. * Description:
  221. * Enumerate the connected device. As part of this enumeration process,
  222. * the driver will (1) get the device's configuration descriptor, (2)
  223. * extract the class ID info from the configuration descriptor, (3) call
  224. * usbhost_findclass() to find the class that supports this device, (4)
  225. * call the create() method on the struct usbhost_registry_s interface
  226. * to get a class instance, and finally (5) call the configdesc() method
  227. * of the struct usbhost_class_s interface. After that, the class is in
  228. * charge of the sequence of operations.
  229. *
  230. * Input Parameters:
  231. * hport - The hub port that manages the new class.
  232. * devclass - If the class driver for the device is successful located
  233. * and bound to the hub port, the allocated class instance is returned
  234. * into this caller-provided memory location.
  235. *
  236. * Returned Values:
  237. * On success, zero (OK) is returned. On a failure, a negated errno value is
  238. * returned indicating the nature of the failure
  239. *
  240. * Assumptions:
  241. * - Only a single class bound to a single device is supported.
  242. * - Called from a single thread so no mutual exclusion is required.
  243. * - Never called from an interrupt handler.
  244. *
  245. ****************************************************************************/
  246. int usbhost_enumerate(FAR struct usbhost_hubport_s *hport,
  247. FAR struct usbhost_class_s **devclass)
  248. {
  249. FAR struct usb_ctrlreq_s *ctrlreq = NULL;
  250. struct usbhost_id_s id;
  251. size_t maxlen;
  252. unsigned int cfglen;
  253. uint8_t maxpacketsize;
  254. uint8_t descsize;
  255. uint8_t funcaddr = 0;
  256. FAR uint8_t *buffer = NULL;
  257. int ret;
  258. DEBUGASSERT(hport != NULL && hport->drvr != NULL);
  259. /* Allocate descriptor buffers for use in this function. We will need two:
  260. * One for the request and one for the data buffer.
  261. */
  262. ret = DRVR_ALLOC(hport->drvr, (FAR uint8_t **)&ctrlreq, &maxlen);
  263. if (ret < 0)
  264. {
  265. uerr("ERROR: DRVR_ALLOC failed: %d\n", ret);
  266. return ret;
  267. }
  268. ret = DRVR_ALLOC(hport->drvr, &buffer, &maxlen);
  269. if (ret < 0)
  270. {
  271. uerr("ERROR: DRVR_ALLOC failed: %d\n", ret);
  272. goto errout;
  273. }
  274. /* Pick an appropriate packet size for this device
  275. *
  276. * USB 2.0, Paragraph 5.5.3 "Control Transfer Packet Size Constraints"
  277. *
  278. * "An endpoint for control transfers specifies the maximum data
  279. * payload size that the endpoint can accept from or transmit to
  280. * the bus. The allowable maximum control transfer data payload
  281. * sizes for full-speed devices is 8, 16, 32, or 64 bytes; for
  282. * high-speed devices, it is 64 bytes and for low-speed devices,
  283. * it is 8 bytes. This maximum applies to the data payloads of the
  284. * Data packets following a Setup..."
  285. */
  286. if (hport->speed == USB_SPEED_HIGH)
  287. {
  288. /* For high-speed, we must use 64 bytes */
  289. maxpacketsize = 64;
  290. descsize = USB_SIZEOF_DEVDESC;
  291. }
  292. else
  293. {
  294. /* Eight will work for both low- and full-speed */
  295. maxpacketsize = 8;
  296. descsize = 8;
  297. }
  298. /* Configure EP0 with the initial maximum packet size */
  299. DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, 0, hport->speed,
  300. maxpacketsize);
  301. /* Read first bytes of the device descriptor */
  302. ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE;
  303. ctrlreq->req = USB_REQ_GETDESCRIPTOR;
  304. usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8));
  305. usbhost_putle16(ctrlreq->index, 0);
  306. usbhost_putle16(ctrlreq->len, descsize);
  307. ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer);
  308. if (ret < 0)
  309. {
  310. uerr("ERROR: Failed to get device descriptor, length=%d: %d\n",
  311. descsize, ret);
  312. goto errout;
  313. }
  314. /* Extract the correct max packetsize from the device descriptor */
  315. maxpacketsize = ((struct usb_devdesc_s *)buffer)->mxpacketsize;
  316. uinfo("maxpacksetsize: %d\n", maxpacketsize);
  317. /* And reconfigure EP0 with the correct maximum packet size */
  318. DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, 0, hport->speed,
  319. maxpacketsize);
  320. /* Now read the full device descriptor (if we have not already done so) */
  321. if (descsize < USB_SIZEOF_DEVDESC)
  322. {
  323. ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE;
  324. ctrlreq->req = USB_REQ_GETDESCRIPTOR;
  325. usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_DEVICE << 8));
  326. usbhost_putle16(ctrlreq->index, 0);
  327. usbhost_putle16(ctrlreq->len, USB_SIZEOF_DEVDESC);
  328. ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer);
  329. if (ret < 0)
  330. {
  331. uerr("ERROR: Failed to get device descriptor, length=%d: %d\n",
  332. USB_SIZEOF_DEVDESC, ret);
  333. goto errout;
  334. }
  335. }
  336. /* Get class identification information from the device descriptor. Most
  337. * devices set this to USB_CLASS_PER_INTERFACE (zero) and provide the
  338. * identification information in the interface descriptor(s). That allows
  339. * a device to support multiple, different classes.
  340. */
  341. (void)usbhost_devdesc((struct usb_devdesc_s *)buffer, &id);
  342. /* Assign a function address to the device connected to this port */
  343. funcaddr = usbhost_devaddr_create(hport);
  344. if (funcaddr < 0)
  345. {
  346. uerr("ERROR: usbhost_devaddr_create failed: %d\n", ret);
  347. goto errout;
  348. }
  349. /* Set the USB device address */
  350. ctrlreq->type = USB_REQ_DIR_OUT | USB_REQ_RECIPIENT_DEVICE;
  351. ctrlreq->req = USB_REQ_SETADDRESS;
  352. usbhost_putle16(ctrlreq->value, (uint16_t)funcaddr);
  353. usbhost_putle16(ctrlreq->index, 0);
  354. usbhost_putle16(ctrlreq->len, 0);
  355. ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL);
  356. if (ret < 0)
  357. {
  358. uerr("ERROR: Failed to set address: %d\n");
  359. goto errout;
  360. }
  361. usleep(2*1000);
  362. /* Assign the function address to the port */
  363. DEBUGASSERT(hport->funcaddr == 0 && funcaddr != 0);
  364. hport->funcaddr = funcaddr;
  365. /* And reconfigure EP0 with the correct address */
  366. DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, hport->funcaddr,
  367. hport->speed, maxpacketsize);
  368. /* Get the configuration descriptor (only), index == 0. Should not be
  369. * hard-coded! More logic is needed in order to handle devices with
  370. * multiple configurations.
  371. */
  372. ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE;
  373. ctrlreq->req = USB_REQ_GETDESCRIPTOR;
  374. usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8));
  375. usbhost_putle16(ctrlreq->index, 0);
  376. usbhost_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC);
  377. ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer);
  378. if (ret < 0)
  379. {
  380. uerr("ERROR: Failed to get configuration descriptor, length=%d: %d\n",
  381. USB_SIZEOF_CFGDESC, ret);
  382. goto errout;
  383. }
  384. /* Extract the full size of the configuration data */
  385. cfglen = (unsigned int)usbhost_getle16(((struct usb_cfgdesc_s *)buffer)->totallen);
  386. uinfo("sizeof config data: %d\n", cfglen);
  387. if (cfglen > maxlen)
  388. {
  389. uerr("ERROR: Configuration doesn't fit in buffer, length=%d, maxlen=%d\n",
  390. cfglen, maxlen);
  391. ret = -E2BIG;
  392. goto errout;
  393. }
  394. /* Get all of the configuration descriptor data, index == 0 (Should not be
  395. * hard-coded!)
  396. */
  397. ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE;
  398. ctrlreq->req = USB_REQ_GETDESCRIPTOR;
  399. usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8));
  400. usbhost_putle16(ctrlreq->index, 0);
  401. usbhost_putle16(ctrlreq->len, cfglen);
  402. ret = DRVR_CTRLIN(hport->drvr, hport->ep0, ctrlreq, buffer);
  403. if (ret < 0)
  404. {
  405. uerr("ERROR: Failed to get configuration descriptor, length=%d: %d\n",
  406. cfglen, ret);
  407. goto errout;
  408. }
  409. /* Select device configuration 1 (Should not be hard-coded!) */
  410. ctrlreq->type = USB_REQ_DIR_OUT | USB_REQ_RECIPIENT_DEVICE;
  411. ctrlreq->req = USB_REQ_SETCONFIGURATION;
  412. usbhost_putle16(ctrlreq->value, 1);
  413. usbhost_putle16(ctrlreq->index, 0);
  414. usbhost_putle16(ctrlreq->len, 0);
  415. ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL);
  416. if (ret < 0)
  417. {
  418. uerr("ERROR: Failed to set configuration: %d\n", ret);
  419. goto errout;
  420. }
  421. /* Was the class identification information provided in the device
  422. * descriptor? Or do we need to find it in the interface descriptor(s)?
  423. */
  424. if (id.base == USB_CLASS_PER_INTERFACE)
  425. {
  426. /* Get the class identification information for this device from the
  427. * interface descriptor(s). Hmmm.. More logic is need to handle the
  428. * case of multiple interface descriptors.
  429. */
  430. ret = usbhost_configdesc(buffer, cfglen, &id);
  431. if (ret < 0)
  432. {
  433. uerr("ERROR: usbhost_configdesc failed: %d\n", ret);
  434. goto errout;
  435. }
  436. }
  437. /* Some devices may require some delay before initialization */
  438. usleep(100*1000);
  439. #ifdef CONFIG_USBHOST_COMPOSITE
  440. /* Check if the device attached to the downstream port if a USB composite
  441. * device and, if so, create the composite device wrapper and bind it to
  442. * the HCD.
  443. *
  444. * usbhost_composite() will return a negated errno value is on any
  445. * failure. The value -ENOENT, in particular means that the attached
  446. * device is not a composite device. Other values would indicate other
  447. * various, unexpected failures. We make no real distinction here.
  448. */
  449. ret = usbhost_composite(hport, buffer, cfglen, &id, devclass);
  450. if (ret >= 0)
  451. {
  452. uinfo("usbhost_composite has bound the composite device\n");
  453. }
  454. /* Apparently this is not a composite device */
  455. else
  456. #endif
  457. {
  458. /* Parse the configuration descriptor and bind to the class instance
  459. * for the device. This needs to be the last thing done because the
  460. * class driver will begin configuring the device.
  461. */
  462. ret = usbhost_classbind(hport, buffer, cfglen, &id, devclass);
  463. if (ret < 0)
  464. {
  465. uerr("ERROR: usbhost_classbind failed %d\n", ret);
  466. }
  467. }
  468. errout:
  469. if (ret < 0)
  470. {
  471. /* Release the device function address on any failure */
  472. usbhost_devaddr_destroy(hport, funcaddr);
  473. hport->funcaddr = 0;
  474. }
  475. /* Release temporary buffers in any event */
  476. if (buffer != NULL)
  477. {
  478. DRVR_FREE(hport->drvr, buffer);
  479. }
  480. if (ctrlreq)
  481. {
  482. DRVR_FREE(hport->drvr, (FAR uint8_t *)ctrlreq);
  483. }
  484. return ret;
  485. }