Subversion Repositories DashDisplay

Rev

Blame | Last modification | View Log | Download | RSS feed

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