cdcacm_desc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /****************************************************************************
  2. * drivers/usbdev/cdcacm_desc.c
  3. *
  4. * Copyright (C) 2011-2012, 2015, 2017 Gregory Nutt. All rights reserved.
  5. * Author: 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 <errno.h>
  43. #include <debug.h>
  44. #include <nuttx/usb/usb.h>
  45. #include <nuttx/usb/usbdev.h>
  46. #include <nuttx/usb/cdc.h>
  47. #include <nuttx/usb/cdcacm.h>
  48. #include <nuttx/usb/usbdev_trace.h>
  49. #include "cdcacm.h"
  50. /****************************************************************************
  51. * Private Data
  52. ****************************************************************************/
  53. /* USB descriptor templates these will be copied and modified **************/
  54. /* Device Descriptor. If the USB serial device is configured as part of
  55. * composite device, then the device descriptor will be provided by the
  56. * composite device logic.
  57. */
  58. #ifndef CONFIG_CDCACM_COMPOSITE
  59. static const struct usb_devdesc_s g_devdesc =
  60. {
  61. USB_SIZEOF_DEVDESC, /* len */
  62. USB_DESC_TYPE_DEVICE, /* type */
  63. { /* usb */
  64. LSBYTE(0x0200),
  65. MSBYTE(0x0200)
  66. },
  67. USB_CLASS_CDC, /* class */
  68. CDC_SUBCLASS_NONE, /* subclass */
  69. CDC_PROTO_NONE, /* protocol */
  70. CONFIG_CDCACM_EP0MAXPACKET, /* maxpacketsize */
  71. {
  72. LSBYTE(CONFIG_CDCACM_VENDORID), /* vendor */
  73. MSBYTE(CONFIG_CDCACM_VENDORID)
  74. },
  75. {
  76. LSBYTE(CONFIG_CDCACM_PRODUCTID), /* product */
  77. MSBYTE(CONFIG_CDCACM_PRODUCTID)
  78. },
  79. {
  80. LSBYTE(CDCACM_VERSIONNO), /* device */
  81. MSBYTE(CDCACM_VERSIONNO)
  82. },
  83. CDCACM_MANUFACTURERSTRID, /* imfgr */
  84. CDCACM_PRODUCTSTRID, /* iproduct */
  85. CDCACM_SERIALSTRID, /* serno */
  86. CDCACM_NCONFIGS /* nconfigs */
  87. };
  88. #endif
  89. #if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
  90. static const struct usb_qualdesc_s g_qualdesc =
  91. {
  92. USB_SIZEOF_QUALDESC, /* len */
  93. USB_DESC_TYPE_DEVICEQUALIFIER, /* type */
  94. { /* usb */
  95. LSBYTE(0x0200),
  96. MSBYTE(0x0200)
  97. },
  98. USB_CLASS_VENDOR_SPEC, /* class */
  99. 0, /* subclass */
  100. 0, /* protocol */
  101. CONFIG_CDCACM_EP0MAXPACKET, /* mxpacketsize */
  102. CDCACM_NCONFIGS, /* nconfigs */
  103. 0, /* reserved */
  104. };
  105. #endif
  106. /****************************************************************************
  107. * Public Functions
  108. ****************************************************************************/
  109. /****************************************************************************
  110. * Name: cdcacm_mkstrdesc
  111. *
  112. * Description:
  113. * Construct a string descriptor
  114. *
  115. ****************************************************************************/
  116. int cdcacm_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc)
  117. {
  118. #if !defined(CONFIG_CDCACM_COMPOSITE) || defined(CONFIG_CDCACM_NOTIFSTR) || \
  119. defined(CONFIG_CDCACM_DATAIFSTR)
  120. const char *str;
  121. int len;
  122. int ndata;
  123. int i;
  124. switch (id)
  125. {
  126. #ifndef CONFIG_CDCACM_COMPOSITE
  127. case 0:
  128. {
  129. /* Descriptor 0 is the language id */
  130. strdesc->len = 4;
  131. strdesc->type = USB_DESC_TYPE_STRING;
  132. strdesc->data[0] = LSBYTE(CDCACM_STR_LANGUAGE);
  133. strdesc->data[1] = MSBYTE(CDCACM_STR_LANGUAGE);
  134. return 4;
  135. }
  136. case CDCACM_MANUFACTURERSTRID:
  137. str = CONFIG_CDCACM_VENDORSTR;
  138. break;
  139. case CDCACM_PRODUCTSTRID:
  140. str = CONFIG_CDCACM_PRODUCTSTR;
  141. break;
  142. case CDCACM_SERIALSTRID:
  143. str = CONFIG_CDCACM_SERIALSTR;
  144. break;
  145. case CDCACM_CONFIGSTRID:
  146. str = CONFIG_CDCACM_CONFIGSTR;
  147. break;
  148. #endif
  149. #ifdef CONFIG_CDCACM_NOTIFSTR
  150. case CDCACM_NOTIFSTRID:
  151. str = CONFIG_CDCACM_NOTIFSTR;
  152. break;
  153. #endif
  154. #ifdef CONFIG_CDCACM_DATAIFSTR
  155. case CDCACM_DATAIFSTRID:
  156. str = CONFIG_CDCACM_DATAIFSTR;
  157. break;
  158. #endif
  159. default:
  160. return -EINVAL;
  161. }
  162. /* The string is utf16-le. The poor man's utf-8 to utf16-le
  163. * conversion below will only handle 7-bit en-us ascii
  164. */
  165. len = strlen(str);
  166. if (len > (CDCACM_MAXSTRLEN / 2))
  167. {
  168. len = (CDCACM_MAXSTRLEN / 2);
  169. }
  170. for (i = 0, ndata = 0; i < len; i++, ndata += 2)
  171. {
  172. strdesc->data[ndata] = str[i];
  173. strdesc->data[ndata+1] = 0;
  174. }
  175. strdesc->len = ndata+2;
  176. strdesc->type = USB_DESC_TYPE_STRING;
  177. return strdesc->len;
  178. #else
  179. return -EINVAL;
  180. #endif
  181. }
  182. /****************************************************************************
  183. * Name: cdcacm_getdevdesc
  184. *
  185. * Description:
  186. * Return a pointer to the raw device descriptor
  187. *
  188. ****************************************************************************/
  189. #ifndef CONFIG_CDCACM_COMPOSITE
  190. FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void)
  191. {
  192. return &g_devdesc;
  193. }
  194. #endif
  195. /****************************************************************************
  196. * Name: cdcacm_copy_epdesc
  197. *
  198. * Description:
  199. * Copies the requested Endpoint Description into the buffer given.
  200. * Returns the number of Bytes filled in (sizeof(struct usb_epdesc_s)).
  201. *
  202. ****************************************************************************/
  203. int cdcacm_copy_epdesc(enum cdcacm_epdesc_e epid,
  204. FAR struct usb_epdesc_s *epdesc,
  205. FAR struct usbdev_devinfo_s *devinfo,
  206. bool hispeed)
  207. {
  208. #ifndef CONFIG_USBDEV_DUALSPEED
  209. UNUSED(hispeed);
  210. #endif
  211. switch (epid)
  212. {
  213. case CDCACM_EPINTIN: /* Interrupt IN endpoint */
  214. {
  215. epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
  216. epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
  217. epdesc->addr = CDCACM_MKEPINTIN(devinfo); /* Endpoint address */
  218. epdesc->attr = CDCACM_EPINTIN_ATTR; /* Endpoint attributes */
  219. #ifdef CONFIG_USBDEV_DUALSPEED
  220. if (hispeed)
  221. {
  222. /* Maximum packet size (high speed) */
  223. epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPINTIN_HSSIZE);
  224. epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPINTIN_HSSIZE);
  225. }
  226. else
  227. #endif
  228. {
  229. /* Maximum packet size (full speed) */
  230. epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE);
  231. epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE);
  232. }
  233. epdesc->interval = 10; /* Interval */
  234. }
  235. break;
  236. case CDCACM_EPBULKOUT: /* Bulk OUT endpoint */
  237. {
  238. epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
  239. epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
  240. epdesc->addr = CDCACM_MKEPBULKOUT(devinfo); /* Endpoint address */
  241. epdesc->attr = CDCACM_EPOUTBULK_ATTR; /* Endpoint attributes */
  242. #ifdef CONFIG_USBDEV_DUALSPEED
  243. if (hispeed)
  244. {
  245. /* Maximum packet size (high speed) */
  246. epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKOUT_HSSIZE);
  247. epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKOUT_HSSIZE);
  248. }
  249. else
  250. #endif
  251. {
  252. /* Maximum packet size (full speed) */
  253. epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE);
  254. epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE);
  255. }
  256. epdesc->interval = 1; /* Interval */
  257. }
  258. break;
  259. case CDCACM_EPBULKIN: /* Bulk IN endpoint */
  260. {
  261. epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
  262. epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
  263. epdesc->addr = CDCACM_MKEPBULKIN(devinfo); /* Endpoint address */
  264. epdesc->attr = CDCACM_EPINBULK_ATTR; /* Endpoint attributes */
  265. #ifdef CONFIG_USBDEV_DUALSPEED
  266. if (hispeed)
  267. {
  268. /* Maximum packet size (high speed) */
  269. epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKIN_HSSIZE);
  270. epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKIN_HSSIZE);
  271. }
  272. else
  273. #endif
  274. {
  275. /* Maximum packet size (full speed) */
  276. epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE);
  277. epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE);
  278. }
  279. epdesc->interval = 1; /* Interval */
  280. }
  281. break;
  282. default:
  283. return 0;
  284. }
  285. return sizeof(struct usb_epdesc_s);
  286. }
  287. /****************************************************************************
  288. * Name: cdcacm_mkcfgdesc
  289. *
  290. * Description:
  291. * Construct the configuration descriptor
  292. *
  293. ****************************************************************************/
  294. #ifdef CONFIG_USBDEV_DUALSPEED
  295. int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf,
  296. FAR struct usbdev_devinfo_s *devinfo,
  297. uint8_t speed, uint8_t type)
  298. #else
  299. int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf,
  300. FAR struct usbdev_devinfo_s *devinfo)
  301. #endif
  302. {
  303. int length = 0;
  304. bool hispeed = false;
  305. #ifdef CONFIG_USBDEV_DUALSPEED
  306. hispeed = (speed == USB_SPEED_HIGH);
  307. /* Check for switches between high and full speed */
  308. if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG)
  309. {
  310. hispeed = !hispeed;
  311. }
  312. #endif
  313. /* Fill in all descriptors directly to the buf */
  314. /* Configuration Descriptor. If the serial device is used in as part
  315. * or a composite device, then the configuration descriptor is
  316. * provided by the composite device logic.
  317. */
  318. #if !defined(CONFIG_CDCACM_COMPOSITE)
  319. if (buf != NULL)
  320. {
  321. /* Configuration descriptor. If the USB serial device is configured as part of
  322. * composite device, then the configuration descriptor will be provided by the
  323. * composite device logic.
  324. */
  325. FAR struct usb_cfgdesc_s *dest = (FAR struct usb_cfgdesc_s *)buf;
  326. /* Let's calculate the size... */
  327. #ifdef CONFIG_USBDEV_DUALSPEED
  328. int16_t size = cdcacm_mkcfgdesc(NULL, NULL, speed, type);
  329. #else
  330. int16_t size = cdcacm_mkcfgdesc(NULL, NULL);
  331. #endif
  332. dest->len = USB_SIZEOF_CFGDESC; /* Descriptor length */
  333. dest->type = USB_DESC_TYPE_CONFIG; /* Descriptor type */
  334. dest->totallen[0] = LSBYTE(size); /* LS Total length */
  335. dest->totallen[1] = MSBYTE(size); /* MS Total length */
  336. dest->ninterfaces = CDCACM_NINTERFACES; /* Number of interfaces */
  337. dest->cfgvalue = CDCACM_CONFIGID; /* Configuration value */
  338. dest->icfg = CDCACM_CONFIGSTRID; /* Configuration */
  339. dest->attr = USB_CONFIG_ATTR_ONE | /* Attributes */
  340. CDCACM_SELFPOWERED |
  341. CDCACM_REMOTEWAKEUP;
  342. dest->mxpower = (CONFIG_USBDEV_MAXPOWER + 1) / 2; /* Max power (mA/2) */
  343. buf += sizeof(struct usb_cfgdesc_s);
  344. }
  345. length += sizeof(struct usb_cfgdesc_s);
  346. /* If the serial device is part of a composite device, then it should
  347. * begin with an interface association descriptor (IAD) because the
  348. * CDC/ACM device consists of more than one interface. The IAD associates
  349. * the two CDC/ACM interfaces with the same CDC/ACM device.
  350. */
  351. #elif defined(CONFIG_COMPOSITE_IAD)
  352. /* Interface association descriptor */
  353. if (buf != NULL)
  354. {
  355. FAR struct usb_iaddesc_s *dest = (FAR struct usb_iaddesc_s *)buf;
  356. dest->len = USB_SIZEOF_IADDESC; /* Descriptor length */
  357. dest->type = USB_DESC_TYPE_INTERFACEASSOCIATION; /* Descriptor type */
  358. dest->firstif = devinfo->ifnobase; /* Number of first interface of the function */
  359. dest->nifs = devinfo->ninterfaces; /* Number of interfaces associated with the function */
  360. dest->classid = USB_CLASS_CDC; /* Class code */
  361. dest->subclass = CDC_SUBCLASS_ACM; /* Sub-class code */
  362. dest->protocol = CDC_PROTO_NONE; /* Protocol code */
  363. dest->ifunction = 0; /* Index to string identifying the function */
  364. buf += sizeof(struct usb_iaddesc_s);
  365. }
  366. length += sizeof(struct usb_iaddesc_s);
  367. #endif
  368. /* Notification interface */
  369. if (buf != NULL)
  370. {
  371. FAR struct usb_ifdesc_s *dest = (FAR struct usb_ifdesc_s *)buf;
  372. dest->len = USB_SIZEOF_IFDESC; /* Descriptor length */
  373. dest->type = USB_DESC_TYPE_INTERFACE; /* Descriptor type */
  374. dest->ifno = devinfo->ifnobase; /* Interface number */
  375. dest->alt = CDCACM_NOTALTIFID; /* Alternate setting */
  376. dest->neps = 1; /* Number of endpoints */
  377. dest->classid = USB_CLASS_CDC; /* Interface class */
  378. dest->subclass = CDC_SUBCLASS_ACM; /* Interface sub-class */
  379. dest->protocol = CDC_PROTO_ATM; /* Interface protocol */
  380. #ifdef CONFIG_CDCACM_NOTIFSTR
  381. dest->iif = devinfo->strbase + CDCACM_NOTIFSTRID; /* iInterface */
  382. #else
  383. dest->iif = 0; /* iInterface */
  384. #endif
  385. buf += sizeof(struct usb_ifdesc_s);
  386. }
  387. length += sizeof(struct usb_ifdesc_s);
  388. /* Header functional descriptor */
  389. if (buf != NULL)
  390. {
  391. FAR struct cdc_hdr_funcdesc_s *dest = (FAR struct cdc_hdr_funcdesc_s *)buf;
  392. dest->size = SIZEOF_HDR_FUNCDESC; /* Descriptor length */
  393. dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
  394. dest->subtype = CDC_DSUBTYPE_HDR; /* Descriptor sub-type */
  395. dest->cdc[0] = LSBYTE(CDC_VERSIONNO); /* CDC release number in BCD */
  396. dest->cdc[1] = MSBYTE(CDC_VERSIONNO);
  397. buf += sizeof(struct cdc_hdr_funcdesc_s);
  398. }
  399. length += sizeof(struct cdc_hdr_funcdesc_s);
  400. /* ACM functional descriptor */
  401. if (buf != NULL)
  402. {
  403. FAR struct cdc_acm_funcdesc_s *dest = (FAR struct cdc_acm_funcdesc_s *)buf;
  404. dest->size = SIZEOF_ACM_FUNCDESC; /* Descriptor length */
  405. dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
  406. dest->subtype = CDC_DSUBTYPE_ACM; /* Descriptor sub-type */
  407. dest->caps = 0x06; /* Bit encoded capabilities */
  408. buf += sizeof(struct cdc_acm_funcdesc_s);
  409. }
  410. length += sizeof(struct cdc_acm_funcdesc_s);
  411. /* This codeblock is just for future use - currently we didn't need it */
  412. #ifdef OPTIONAL_UNION_FUNCTIONAL_DESCRIPTOR
  413. /* Union functional descriptor */
  414. if (buf != NULL)
  415. {
  416. FAR struct cdc_union_funcdesc_s *dest = (FAR struct cdc_union_funcdesc_s *)buf;
  417. dest->size = SIZEOF_UNION_FUNCDESC(1); /* Descriptor length */
  418. dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
  419. dest->subtype = CDC_DSUBTYPE_UNION; /* Descriptor sub-type */
  420. dest->master = devinfo->ifnobase; /* Master interface number */
  421. dest->slave[0] = devinfo->ifnobase + 1; /* Slave[0] interface number */
  422. buf += sizeof(struct cdc_union_funcdesc_s);
  423. }
  424. length += sizeof(struct cdc_union_funcdesc_s);
  425. #endif
  426. /* Call Management functional descriptor */
  427. if (buf != NULL)
  428. {
  429. FAR struct cdc_callmgmt_funcdesc_s *dest = (FAR struct cdc_callmgmt_funcdesc_s *)buf;
  430. dest->size = SIZEOF_CALLMGMT_FUNCDESC; /* Descriptor length */
  431. dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
  432. dest->subtype = CDC_DSUBTYPE_CALLMGMT; /* Descriptor sub-type */
  433. dest->caps = 3; /* Bit encoded capabilities */
  434. dest->ifno = devinfo->ifnobase + 1; /* Interface number of Data Class interface */
  435. buf += sizeof(struct cdc_callmgmt_funcdesc_s);
  436. }
  437. length += sizeof(struct cdc_callmgmt_funcdesc_s);
  438. /* Interrupt IN endpoint descriptor */
  439. if (buf != NULL)
  440. {
  441. cdcacm_copy_epdesc(CDCACM_EPINTIN, (struct usb_epdesc_s *)buf, devinfo, hispeed);
  442. buf += USB_SIZEOF_EPDESC;
  443. }
  444. length += USB_SIZEOF_EPDESC;
  445. /* Data interface descriptor */
  446. if (buf != NULL)
  447. {
  448. FAR struct usb_ifdesc_s *dest = (FAR struct usb_ifdesc_s *)buf;
  449. dest->len = USB_SIZEOF_IFDESC; /* Descriptor length */
  450. dest->type = USB_DESC_TYPE_INTERFACE; /* Descriptor type */
  451. dest->ifno = devinfo->ifnobase + 1; /* Interface number */
  452. dest->alt = CDCACM_DATAALTIFID; /* Alternate setting */
  453. dest->neps = 2; /* Number of endpoints */
  454. dest->classid = USB_CLASS_CDC_DATA; /* Interface class */
  455. dest->subclass = CDC_DATA_SUBCLASS_NONE; /* Interface sub-class */
  456. dest->protocol = CDC_DATA_PROTO_NONE; /* Interface protocol */
  457. #ifdef CONFIG_CDCACM_DATAIFSTR
  458. dest->iif = devinfo->strbase + CDCACM_DATAIFSTRID; /* iInterface */
  459. #else
  460. dest->iif = 0; /* iInterface */
  461. #endif
  462. buf += sizeof(struct usb_ifdesc_s);
  463. }
  464. length += sizeof(struct usb_ifdesc_s);
  465. /* Bulk OUT endpoint descriptor */
  466. if (buf != NULL)
  467. {
  468. cdcacm_copy_epdesc(CDCACM_EPBULKOUT, (struct usb_epdesc_s *)buf, devinfo, hispeed);
  469. buf += USB_SIZEOF_EPDESC;
  470. }
  471. length += USB_SIZEOF_EPDESC;
  472. /* Bulk IN endpoint descriptor */
  473. if (buf != NULL)
  474. {
  475. cdcacm_copy_epdesc(CDCACM_EPBULKIN, (struct usb_epdesc_s *)buf, devinfo, hispeed);
  476. buf += USB_SIZEOF_EPDESC;
  477. }
  478. length += USB_SIZEOF_EPDESC;
  479. return length;
  480. }
  481. /****************************************************************************
  482. * Name: cdcacm_getqualdesc
  483. *
  484. * Description:
  485. * Return a pointer to the raw qual descriptor
  486. *
  487. ****************************************************************************/
  488. #if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
  489. FAR const struct usb_qualdesc_s *cdcacm_getqualdesc(void)
  490. {
  491. return &g_qualdesc;
  492. }
  493. #endif