Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

849 lines
18 KiB

  1. /**
  2. ******************************************************************************
  3. * @file usbd_req.c
  4. * @author MCD Application Team
  5. * @brief This file provides the standard USB requests following chapter 9.
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright (c) 2015 STMicroelectronics.
  10. * All rights reserved.</center></h2>
  11. *
  12. * This software component is licensed by ST under Ultimate Liberty license
  13. * SLA0044, the "License"; You may not use this file except in compliance with
  14. * the License. You may obtain a copy of the License at:
  15. * http://www.st.com/SLA0044
  16. *
  17. ******************************************************************************
  18. */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "usbd_ctlreq.h"
  21. #include "usbd_ioreq.h"
  22. /** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
  23. * @{
  24. */
  25. /** @defgroup USBD_REQ
  26. * @brief USB standard requests module
  27. * @{
  28. */
  29. /** @defgroup USBD_REQ_Private_TypesDefinitions
  30. * @{
  31. */
  32. /**
  33. * @}
  34. */
  35. /** @defgroup USBD_REQ_Private_Defines
  36. * @{
  37. */
  38. /**
  39. * @}
  40. */
  41. /** @defgroup USBD_REQ_Private_Macros
  42. * @{
  43. */
  44. /**
  45. * @}
  46. */
  47. /** @defgroup USBD_REQ_Private_Variables
  48. * @{
  49. */
  50. /**
  51. * @}
  52. */
  53. /** @defgroup USBD_REQ_Private_FunctionPrototypes
  54. * @{
  55. */
  56. static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
  57. USBD_SetupReqTypedef *req);
  58. static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
  59. USBD_SetupReqTypedef *req);
  60. static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
  61. USBD_SetupReqTypedef *req);
  62. static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
  63. USBD_SetupReqTypedef *req);
  64. static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
  65. USBD_SetupReqTypedef *req);
  66. static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
  67. USBD_SetupReqTypedef *req);
  68. static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
  69. USBD_SetupReqTypedef *req);
  70. static uint8_t USBD_GetLen(uint8_t *buf);
  71. /**
  72. * @}
  73. */
  74. /** @defgroup USBD_REQ_Private_Functions
  75. * @{
  76. */
  77. /**
  78. * @brief USBD_StdDevReq
  79. * Handle standard usb device requests
  80. * @param pdev: device instance
  81. * @param req: usb request
  82. * @retval status
  83. */
  84. USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
  85. {
  86. USBD_StatusTypeDef ret = USBD_OK;
  87. switch (req->bmRequest & USB_REQ_TYPE_MASK)
  88. {
  89. case USB_REQ_TYPE_CLASS:
  90. case USB_REQ_TYPE_VENDOR:
  91. pdev->pClass->Setup(pdev, req);
  92. break;
  93. case USB_REQ_TYPE_STANDARD:
  94. switch (req->bRequest)
  95. {
  96. case USB_REQ_GET_DESCRIPTOR:
  97. USBD_GetDescriptor (pdev, req);
  98. break;
  99. case USB_REQ_SET_ADDRESS:
  100. USBD_SetAddress (pdev, req);
  101. break;
  102. case USB_REQ_SET_CONFIGURATION:
  103. USBD_SetConfig (pdev, req);
  104. break;
  105. case USB_REQ_GET_CONFIGURATION:
  106. USBD_GetConfig (pdev, req);
  107. break;
  108. case USB_REQ_GET_STATUS:
  109. USBD_GetStatus (pdev, req);
  110. break;
  111. case USB_REQ_SET_FEATURE:
  112. USBD_SetFeature (pdev, req);
  113. break;
  114. case USB_REQ_CLEAR_FEATURE:
  115. USBD_ClrFeature (pdev, req);
  116. break;
  117. default:
  118. USBD_CtlError(pdev, req);
  119. break;
  120. }
  121. break;
  122. default:
  123. USBD_CtlError(pdev, req);
  124. break;
  125. }
  126. return ret;
  127. }
  128. /**
  129. * @brief USBD_StdItfReq
  130. * Handle standard usb interface requests
  131. * @param pdev: device instance
  132. * @param req: usb request
  133. * @retval status
  134. */
  135. USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
  136. {
  137. USBD_StatusTypeDef ret = USBD_OK;
  138. switch (req->bmRequest & USB_REQ_TYPE_MASK)
  139. {
  140. case USB_REQ_TYPE_CLASS:
  141. case USB_REQ_TYPE_VENDOR:
  142. case USB_REQ_TYPE_STANDARD:
  143. switch (pdev->dev_state)
  144. {
  145. case USBD_STATE_DEFAULT:
  146. case USBD_STATE_ADDRESSED:
  147. case USBD_STATE_CONFIGURED:
  148. if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
  149. {
  150. ret = (USBD_StatusTypeDef)pdev->pClass->Setup (pdev, req);
  151. if ((req->wLength == 0U) && (ret == USBD_OK))
  152. {
  153. USBD_CtlSendStatus(pdev);
  154. }
  155. }
  156. else
  157. {
  158. USBD_CtlError(pdev, req);
  159. }
  160. break;
  161. default:
  162. USBD_CtlError(pdev, req);
  163. break;
  164. }
  165. break;
  166. default:
  167. USBD_CtlError(pdev, req);
  168. break;
  169. }
  170. return USBD_OK;
  171. }
  172. /**
  173. * @brief USBD_StdEPReq
  174. * Handle standard usb endpoint requests
  175. * @param pdev: device instance
  176. * @param req: usb request
  177. * @retval status
  178. */
  179. USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
  180. {
  181. uint8_t ep_addr;
  182. USBD_StatusTypeDef ret = USBD_OK;
  183. USBD_EndpointTypeDef *pep;
  184. ep_addr = LOBYTE(req->wIndex);
  185. switch (req->bmRequest & USB_REQ_TYPE_MASK)
  186. {
  187. case USB_REQ_TYPE_CLASS:
  188. case USB_REQ_TYPE_VENDOR:
  189. pdev->pClass->Setup (pdev, req);
  190. break;
  191. case USB_REQ_TYPE_STANDARD:
  192. /* Check if it is a class request */
  193. if ((req->bmRequest & 0x60U) == 0x20U)
  194. {
  195. ret = (USBD_StatusTypeDef)pdev->pClass->Setup (pdev, req);
  196. return ret;
  197. }
  198. switch (req->bRequest)
  199. {
  200. case USB_REQ_SET_FEATURE :
  201. switch (pdev->dev_state)
  202. {
  203. case USBD_STATE_ADDRESSED:
  204. if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
  205. {
  206. USBD_LL_StallEP(pdev, ep_addr);
  207. USBD_LL_StallEP(pdev, 0x80U);
  208. }
  209. else
  210. {
  211. USBD_CtlError(pdev, req);
  212. }
  213. break;
  214. case USBD_STATE_CONFIGURED:
  215. if (req->wValue == USB_FEATURE_EP_HALT)
  216. {
  217. if ((ep_addr != 0x00U) && (ep_addr != 0x80U) && (req->wLength == 0x00U))
  218. {
  219. USBD_LL_StallEP(pdev, ep_addr);
  220. }
  221. }
  222. USBD_CtlSendStatus(pdev);
  223. break;
  224. default:
  225. USBD_CtlError(pdev, req);
  226. break;
  227. }
  228. break;
  229. case USB_REQ_CLEAR_FEATURE :
  230. switch (pdev->dev_state)
  231. {
  232. case USBD_STATE_ADDRESSED:
  233. if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
  234. {
  235. USBD_LL_StallEP(pdev, ep_addr);
  236. USBD_LL_StallEP(pdev, 0x80U);
  237. }
  238. else
  239. {
  240. USBD_CtlError(pdev, req);
  241. }
  242. break;
  243. case USBD_STATE_CONFIGURED:
  244. if (req->wValue == USB_FEATURE_EP_HALT)
  245. {
  246. if ((ep_addr & 0x7FU) != 0x00U)
  247. {
  248. USBD_LL_ClearStallEP(pdev, ep_addr);
  249. }
  250. USBD_CtlSendStatus(pdev);
  251. }
  252. break;
  253. default:
  254. USBD_CtlError(pdev, req);
  255. break;
  256. }
  257. break;
  258. case USB_REQ_GET_STATUS:
  259. switch (pdev->dev_state)
  260. {
  261. case USBD_STATE_ADDRESSED:
  262. if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
  263. {
  264. USBD_CtlError(pdev, req);
  265. break;
  266. }
  267. pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU]:\
  268. &pdev->ep_out[ep_addr & 0x7FU];
  269. pep->status = 0x0000U;
  270. USBD_CtlSendData (pdev, (uint8_t *)(void *)&pep->status, 2U);
  271. break;
  272. case USBD_STATE_CONFIGURED:
  273. if((ep_addr & 0x80U) == 0x80U)
  274. {
  275. if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U)
  276. {
  277. USBD_CtlError(pdev, req);
  278. break;
  279. }
  280. }
  281. else
  282. {
  283. if (pdev->ep_out[ep_addr & 0xFU].is_used == 0U)
  284. {
  285. USBD_CtlError(pdev, req);
  286. break;
  287. }
  288. }
  289. pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU]:\
  290. &pdev->ep_out[ep_addr & 0x7FU];
  291. if ((ep_addr == 0x00U) || (ep_addr == 0x80U))
  292. {
  293. pep->status = 0x0000U;
  294. }
  295. else if(USBD_LL_IsStallEP(pdev, ep_addr))
  296. {
  297. pep->status = 0x0001U;
  298. }
  299. else
  300. {
  301. pep->status = 0x0000U;
  302. }
  303. USBD_CtlSendData (pdev, (uint8_t *)(void *)&pep->status, 2U);
  304. break;
  305. default:
  306. USBD_CtlError(pdev, req);
  307. break;
  308. }
  309. break;
  310. default:
  311. USBD_CtlError(pdev, req);
  312. break;
  313. }
  314. break;
  315. default:
  316. USBD_CtlError(pdev, req);
  317. break;
  318. }
  319. return ret;
  320. }
  321. /**
  322. * @brief USBD_GetDescriptor
  323. * Handle Get Descriptor requests
  324. * @param pdev: device instance
  325. * @param req: usb request
  326. * @retval status
  327. */
  328. static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
  329. USBD_SetupReqTypedef *req)
  330. {
  331. uint16_t len;
  332. uint8_t *pbuf;
  333. switch (req->wValue >> 8)
  334. {
  335. #if (USBD_LPM_ENABLED == 1U)
  336. case USB_DESC_TYPE_BOS:
  337. pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len);
  338. break;
  339. #endif
  340. case USB_DESC_TYPE_DEVICE:
  341. pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
  342. break;
  343. case USB_DESC_TYPE_CONFIGURATION:
  344. if(pdev->dev_speed == USBD_SPEED_HIGH )
  345. {
  346. pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(&len);
  347. pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
  348. }
  349. else
  350. {
  351. pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(&len);
  352. pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
  353. }
  354. break;
  355. case USB_DESC_TYPE_STRING:
  356. switch ((uint8_t)(req->wValue))
  357. {
  358. case USBD_IDX_LANGID_STR:
  359. pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
  360. break;
  361. case USBD_IDX_MFC_STR:
  362. pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len);
  363. break;
  364. case USBD_IDX_PRODUCT_STR:
  365. pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
  366. break;
  367. case USBD_IDX_SERIAL_STR:
  368. pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
  369. break;
  370. case USBD_IDX_CONFIG_STR:
  371. pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len);
  372. break;
  373. case USBD_IDX_INTERFACE_STR:
  374. pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len);
  375. break;
  376. default:
  377. #if (USBD_SUPPORT_USER_STRING == 1U)
  378. pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len);
  379. break;
  380. #else
  381. USBD_CtlError(pdev , req);
  382. return;
  383. #endif
  384. }
  385. break;
  386. case USB_DESC_TYPE_DEVICE_QUALIFIER:
  387. if(pdev->dev_speed == USBD_SPEED_HIGH)
  388. {
  389. pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(&len);
  390. break;
  391. }
  392. else
  393. {
  394. USBD_CtlError(pdev , req);
  395. return;
  396. }
  397. case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
  398. if(pdev->dev_speed == USBD_SPEED_HIGH )
  399. {
  400. pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(&len);
  401. pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
  402. break;
  403. }
  404. else
  405. {
  406. USBD_CtlError(pdev , req);
  407. return;
  408. }
  409. default:
  410. USBD_CtlError(pdev , req);
  411. return;
  412. }
  413. if((len != 0U) && (req->wLength != 0U))
  414. {
  415. len = MIN(len, req->wLength);
  416. USBD_CtlSendData (pdev, pbuf, len);
  417. }
  418. if(req->wLength == 0U)
  419. {
  420. USBD_CtlSendStatus(pdev);
  421. }
  422. }
  423. /**
  424. * @brief USBD_SetAddress
  425. * Set device address
  426. * @param pdev: device instance
  427. * @param req: usb request
  428. * @retval status
  429. */
  430. static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
  431. USBD_SetupReqTypedef *req)
  432. {
  433. uint8_t dev_addr;
  434. if ((req->wIndex == 0U) && (req->wLength == 0U) && (req->wValue < 128U))
  435. {
  436. dev_addr = (uint8_t)(req->wValue) & 0x7FU;
  437. if (pdev->dev_state == USBD_STATE_CONFIGURED)
  438. {
  439. USBD_CtlError(pdev , req);
  440. }
  441. else
  442. {
  443. pdev->dev_address = dev_addr;
  444. USBD_LL_SetUSBAddress(pdev, dev_addr);
  445. USBD_CtlSendStatus(pdev);
  446. if (dev_addr != 0U)
  447. {
  448. pdev->dev_state = USBD_STATE_ADDRESSED;
  449. }
  450. else
  451. {
  452. pdev->dev_state = USBD_STATE_DEFAULT;
  453. }
  454. }
  455. }
  456. else
  457. {
  458. USBD_CtlError(pdev, req);
  459. }
  460. }
  461. /**
  462. * @brief USBD_SetConfig
  463. * Handle Set device configuration request
  464. * @param pdev: device instance
  465. * @param req: usb request
  466. * @retval status
  467. */
  468. static void USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
  469. {
  470. static uint8_t cfgidx;
  471. cfgidx = (uint8_t)(req->wValue);
  472. if (cfgidx > USBD_MAX_NUM_CONFIGURATION)
  473. {
  474. USBD_CtlError(pdev, req);
  475. }
  476. else
  477. {
  478. switch (pdev->dev_state)
  479. {
  480. case USBD_STATE_ADDRESSED:
  481. if (cfgidx)
  482. {
  483. pdev->dev_config = cfgidx;
  484. pdev->dev_state = USBD_STATE_CONFIGURED;
  485. if(USBD_SetClassConfig(pdev, cfgidx) == USBD_FAIL)
  486. {
  487. USBD_CtlError(pdev, req);
  488. return;
  489. }
  490. USBD_CtlSendStatus(pdev);
  491. }
  492. else
  493. {
  494. USBD_CtlSendStatus(pdev);
  495. }
  496. break;
  497. case USBD_STATE_CONFIGURED:
  498. if (cfgidx == 0U)
  499. {
  500. pdev->dev_state = USBD_STATE_ADDRESSED;
  501. pdev->dev_config = cfgidx;
  502. USBD_ClrClassConfig(pdev, cfgidx);
  503. USBD_CtlSendStatus(pdev);
  504. }
  505. else if (cfgidx != pdev->dev_config)
  506. {
  507. /* Clear old configuration */
  508. USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
  509. /* set new configuration */
  510. pdev->dev_config = cfgidx;
  511. if(USBD_SetClassConfig(pdev, cfgidx) == USBD_FAIL)
  512. {
  513. USBD_CtlError(pdev, req);
  514. return;
  515. }
  516. USBD_CtlSendStatus(pdev);
  517. }
  518. else
  519. {
  520. USBD_CtlSendStatus(pdev);
  521. }
  522. break;
  523. default:
  524. USBD_CtlError(pdev, req);
  525. USBD_ClrClassConfig(pdev, cfgidx);
  526. break;
  527. }
  528. }
  529. }
  530. /**
  531. * @brief USBD_GetConfig
  532. * Handle Get device configuration request
  533. * @param pdev: device instance
  534. * @param req: usb request
  535. * @retval status
  536. */
  537. static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
  538. {
  539. if (req->wLength != 1U)
  540. {
  541. USBD_CtlError(pdev , req);
  542. }
  543. else
  544. {
  545. switch (pdev->dev_state)
  546. {
  547. case USBD_STATE_DEFAULT:
  548. case USBD_STATE_ADDRESSED:
  549. pdev->dev_default_config = 0U;
  550. USBD_CtlSendData (pdev, (uint8_t *)(void *)&pdev->dev_default_config, 1U);
  551. break;
  552. case USBD_STATE_CONFIGURED:
  553. USBD_CtlSendData (pdev, (uint8_t *)(void *)&pdev->dev_config, 1U);
  554. break;
  555. default:
  556. USBD_CtlError(pdev , req);
  557. break;
  558. }
  559. }
  560. }
  561. /**
  562. * @brief USBD_GetStatus
  563. * Handle Get Status request
  564. * @param pdev: device instance
  565. * @param req: usb request
  566. * @retval status
  567. */
  568. static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
  569. {
  570. switch (pdev->dev_state)
  571. {
  572. case USBD_STATE_DEFAULT:
  573. case USBD_STATE_ADDRESSED:
  574. case USBD_STATE_CONFIGURED:
  575. if(req->wLength != 0x2U)
  576. {
  577. USBD_CtlError(pdev, req);
  578. break;
  579. }
  580. #if ( USBD_SELF_POWERED == 1U)
  581. pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
  582. #else
  583. pdev->dev_config_status = 0U;
  584. #endif
  585. if (pdev->dev_remote_wakeup)
  586. {
  587. pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
  588. }
  589. USBD_CtlSendData (pdev, (uint8_t *)(void *)&pdev->dev_config_status, 2U);
  590. break;
  591. default :
  592. USBD_CtlError(pdev , req);
  593. break;
  594. }
  595. }
  596. /**
  597. * @brief USBD_SetFeature
  598. * Handle Set device feature request
  599. * @param pdev: device instance
  600. * @param req: usb request
  601. * @retval status
  602. */
  603. static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
  604. USBD_SetupReqTypedef *req)
  605. {
  606. if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
  607. {
  608. pdev->dev_remote_wakeup = 1U;
  609. USBD_CtlSendStatus(pdev);
  610. }
  611. }
  612. /**
  613. * @brief USBD_ClrFeature
  614. * Handle clear device feature request
  615. * @param pdev: device instance
  616. * @param req: usb request
  617. * @retval status
  618. */
  619. static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
  620. USBD_SetupReqTypedef *req)
  621. {
  622. switch (pdev->dev_state)
  623. {
  624. case USBD_STATE_DEFAULT:
  625. case USBD_STATE_ADDRESSED:
  626. case USBD_STATE_CONFIGURED:
  627. if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
  628. {
  629. pdev->dev_remote_wakeup = 0U;
  630. USBD_CtlSendStatus(pdev);
  631. }
  632. break;
  633. default :
  634. USBD_CtlError(pdev , req);
  635. break;
  636. }
  637. }
  638. /**
  639. * @brief USBD_ParseSetupRequest
  640. * Copy buffer into setup structure
  641. * @param pdev: device instance
  642. * @param req: usb request
  643. * @retval None
  644. */
  645. void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
  646. {
  647. req->bmRequest = *(uint8_t *) (pdata);
  648. req->bRequest = *(uint8_t *) (pdata + 1);
  649. req->wValue = SWAPBYTE (pdata + 2);
  650. req->wIndex = SWAPBYTE (pdata + 4);
  651. req->wLength = SWAPBYTE (pdata + 6);
  652. }
  653. /**
  654. * @brief USBD_CtlError
  655. * Handle USB low level Error
  656. * @param pdev: device instance
  657. * @param req: usb request
  658. * @retval None
  659. */
  660. void USBD_CtlError( USBD_HandleTypeDef *pdev ,
  661. USBD_SetupReqTypedef *req)
  662. {
  663. USBD_LL_StallEP(pdev , 0x80U);
  664. USBD_LL_StallEP(pdev , 0U);
  665. }
  666. /**
  667. * @brief USBD_GetString
  668. * Convert Ascii string into unicode one
  669. * @param desc : descriptor buffer
  670. * @param unicode : Formatted string buffer (unicode)
  671. * @param len : descriptor length
  672. * @retval None
  673. */
  674. void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
  675. {
  676. uint8_t idx = 0U;
  677. if (desc != NULL)
  678. {
  679. *len = (uint16_t)USBD_GetLen(desc) * 2U + 2U;
  680. unicode[idx++] = *(uint8_t *)(void *)len;
  681. unicode[idx++] = USB_DESC_TYPE_STRING;
  682. while (*desc != '\0')
  683. {
  684. unicode[idx++] = *desc++;
  685. unicode[idx++] = 0U;
  686. }
  687. }
  688. }
  689. /**
  690. * @brief USBD_GetLen
  691. * return the string length
  692. * @param buf : pointer to the ascii string buffer
  693. * @retval string length
  694. */
  695. static uint8_t USBD_GetLen(uint8_t *buf)
  696. {
  697. uint8_t len = 0U;
  698. while (*buf != '\0')
  699. {
  700. len++;
  701. buf++;
  702. }
  703. return len;
  704. }
  705. /**
  706. * @}
  707. */
  708. /**
  709. * @}
  710. */
  711. /**
  712. * @}
  713. */
  714. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/