usbd_ctlreq.c
   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    * Copyright (c) 2015 STMicroelectronics.
  10    * All rights reserved.
  11    *
  12    * This software is licensed under terms that can be found in the LICENSE file
  13    * in the root directory of this software component.
  14    * If no LICENSE file comes with this software, it is provided AS-IS.
  15    *
  16    ******************************************************************************
  17    */
  18  
  19  /* Includes ------------------------------------------------------------------*/
  20  #include "usbd_ctlreq.h"
  21  #include "usbd_ioreq.h"
  22  
  23  #ifdef USE_USBD_COMPOSITE
  24  #include "usbd_composite_builder.h"
  25  #endif /* USE_USBD_COMPOSITE */
  26  
  27  /** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
  28    * @{
  29    */
  30  
  31  
  32  /** @defgroup USBD_REQ
  33    * @brief USB standard requests module
  34    * @{
  35    */
  36  
  37  /** @defgroup USBD_REQ_Private_TypesDefinitions
  38    * @{
  39    */
  40  
  41  /**
  42    * @}
  43    */
  44  
  45  
  46  /** @defgroup USBD_REQ_Private_Defines
  47    * @{
  48    */
  49  
  50  /**
  51    * @}
  52    */
  53  
  54  
  55  /** @defgroup USBD_REQ_Private_Macros
  56    * @{
  57    */
  58  
  59  /**
  60    * @}
  61    */
  62  
  63  
  64  /** @defgroup USBD_REQ_Private_Variables
  65    * @{
  66    */
  67  
  68  /**
  69    * @}
  70    */
  71  
  72  
  73  /** @defgroup USBD_REQ_Private_FunctionPrototypes
  74    * @{
  75    */
  76  static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  77  static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  78  static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  79  static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  80  static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  81  static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  82  static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
  83  static uint8_t USBD_GetLen(uint8_t *buf);
  84  
  85  /**
  86    * @}
  87    */
  88  
  89  
  90  /** @defgroup USBD_REQ_Private_Functions
  91    * @{
  92    */
  93  
  94  
  95  /**
  96    * @brief  USBD_StdDevReq
  97    *         Handle standard usb device requests
  98    * @param  pdev: device instance
  99    * @param  req: usb request
 100    * @retval status
 101    */
 102  USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 103  {
 104    USBD_StatusTypeDef ret = USBD_OK;
 105  
 106    switch (req->bmRequest & USB_REQ_TYPE_MASK)
 107    {
 108      case USB_REQ_TYPE_CLASS:
 109      case USB_REQ_TYPE_VENDOR:
 110        ret = (USBD_StatusTypeDef)pdev->pClass[pdev->classId]->Setup(pdev, req);
 111        break;
 112  
 113      case USB_REQ_TYPE_STANDARD:
 114        switch (req->bRequest)
 115        {
 116          case USB_REQ_GET_DESCRIPTOR:
 117            USBD_GetDescriptor(pdev, req);
 118            break;
 119  
 120          case USB_REQ_SET_ADDRESS:
 121            USBD_SetAddress(pdev, req);
 122            break;
 123  
 124          case USB_REQ_SET_CONFIGURATION:
 125            ret = USBD_SetConfig(pdev, req);
 126            break;
 127  
 128          case USB_REQ_GET_CONFIGURATION:
 129            USBD_GetConfig(pdev, req);
 130            break;
 131  
 132          case USB_REQ_GET_STATUS:
 133            USBD_GetStatus(pdev, req);
 134            break;
 135  
 136          case USB_REQ_SET_FEATURE:
 137            USBD_SetFeature(pdev, req);
 138            break;
 139  
 140          case USB_REQ_CLEAR_FEATURE:
 141            USBD_ClrFeature(pdev, req);
 142            break;
 143  
 144          default:
 145            USBD_CtlError(pdev, req);
 146            break;
 147        }
 148        break;
 149  
 150      default:
 151        USBD_CtlError(pdev, req);
 152        break;
 153    }
 154  
 155    return ret;
 156  }
 157  
 158  /**
 159    * @brief  USBD_StdItfReq
 160    *         Handle standard usb interface requests
 161    * @param  pdev: device instance
 162    * @param  req: usb request
 163    * @retval status
 164    */
 165  USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 166  {
 167    USBD_StatusTypeDef ret = USBD_OK;
 168    uint8_t idx;
 169  
 170    switch (req->bmRequest & USB_REQ_TYPE_MASK)
 171    {
 172      case USB_REQ_TYPE_CLASS:
 173      case USB_REQ_TYPE_VENDOR:
 174      case USB_REQ_TYPE_STANDARD:
 175        switch (pdev->dev_state)
 176        {
 177          case USBD_STATE_DEFAULT:
 178          case USBD_STATE_ADDRESSED:
 179          case USBD_STATE_CONFIGURED:
 180  
 181            if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
 182            {
 183              /* Get the class index relative to this interface */
 184              idx = USBD_CoreFindIF(pdev, LOBYTE(req->wIndex));
 185              if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
 186              {
 187                /* Call the class data out function to manage the request */
 188                if (pdev->pClass[idx]->Setup != NULL)
 189                {
 190                  pdev->classId = idx;
 191                  ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req));
 192                }
 193                else
 194                {
 195                  /* should never reach this condition */
 196                  ret = USBD_FAIL;
 197                }
 198              }
 199              else
 200              {
 201                /* No relative interface found */
 202                ret = USBD_FAIL;
 203              }
 204  
 205              if ((req->wLength == 0U) && (ret == USBD_OK))
 206              {
 207                (void)USBD_CtlSendStatus(pdev);
 208              }
 209            }
 210            else
 211            {
 212              USBD_CtlError(pdev, req);
 213            }
 214            break;
 215  
 216          default:
 217            USBD_CtlError(pdev, req);
 218            break;
 219        }
 220        break;
 221  
 222      default:
 223        USBD_CtlError(pdev, req);
 224        break;
 225    }
 226  
 227    return ret;
 228  }
 229  
 230  /**
 231    * @brief  USBD_StdEPReq
 232    *         Handle standard usb endpoint requests
 233    * @param  pdev: device instance
 234    * @param  req: usb request
 235    * @retval status
 236    */
 237  USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 238  {
 239    USBD_EndpointTypeDef *pep;
 240    uint8_t ep_addr;
 241    uint8_t idx;
 242    USBD_StatusTypeDef ret = USBD_OK;
 243  
 244    ep_addr = LOBYTE(req->wIndex);
 245  
 246    switch (req->bmRequest & USB_REQ_TYPE_MASK)
 247    {
 248      case USB_REQ_TYPE_CLASS:
 249      case USB_REQ_TYPE_VENDOR:
 250        /* Get the class index relative to this endpoint */
 251        idx = USBD_CoreFindEP(pdev, ep_addr);
 252        if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
 253        {
 254          pdev->classId = idx;
 255          /* Call the class data out function to manage the request */
 256          if (pdev->pClass[idx]->Setup != NULL)
 257          {
 258            ret = (USBD_StatusTypeDef)pdev->pClass[idx]->Setup(pdev, req);
 259          }
 260        }
 261        break;
 262  
 263      case USB_REQ_TYPE_STANDARD:
 264        switch (req->bRequest)
 265        {
 266          case USB_REQ_SET_FEATURE:
 267            switch (pdev->dev_state)
 268            {
 269              case USBD_STATE_ADDRESSED:
 270                if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
 271                {
 272                  (void)USBD_LL_StallEP(pdev, ep_addr);
 273                  (void)USBD_LL_StallEP(pdev, 0x80U);
 274                }
 275                else
 276                {
 277                  USBD_CtlError(pdev, req);
 278                }
 279                break;
 280  
 281              case USBD_STATE_CONFIGURED:
 282                if (req->wValue == USB_FEATURE_EP_HALT)
 283                {
 284                  if ((ep_addr != 0x00U) && (ep_addr != 0x80U) && (req->wLength == 0x00U))
 285                  {
 286                    (void)USBD_LL_StallEP(pdev, ep_addr);
 287                  }
 288                }
 289                (void)USBD_CtlSendStatus(pdev);
 290  
 291                break;
 292  
 293              default:
 294                USBD_CtlError(pdev, req);
 295                break;
 296            }
 297            break;
 298  
 299          case USB_REQ_CLEAR_FEATURE:
 300  
 301            switch (pdev->dev_state)
 302            {
 303              case USBD_STATE_ADDRESSED:
 304                if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
 305                {
 306                  (void)USBD_LL_StallEP(pdev, ep_addr);
 307                  (void)USBD_LL_StallEP(pdev, 0x80U);
 308                }
 309                else
 310                {
 311                  USBD_CtlError(pdev, req);
 312                }
 313                break;
 314  
 315              case USBD_STATE_CONFIGURED:
 316                if (req->wValue == USB_FEATURE_EP_HALT)
 317                {
 318                  if ((ep_addr & 0x7FU) != 0x00U)
 319                  {
 320                    (void)USBD_LL_ClearStallEP(pdev, ep_addr);
 321                  }
 322                  (void)USBD_CtlSendStatus(pdev);
 323  
 324                  /* Get the class index relative to this interface */
 325                  idx = USBD_CoreFindEP(pdev, ep_addr);
 326                  if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
 327                  {
 328                    pdev->classId = idx;
 329                    /* Call the class data out function to manage the request */
 330                    if (pdev->pClass[idx]->Setup != NULL)
 331                    {
 332                      ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req));
 333                    }
 334                  }
 335                }
 336                break;
 337  
 338              default:
 339                USBD_CtlError(pdev, req);
 340                break;
 341            }
 342            break;
 343  
 344          case USB_REQ_GET_STATUS:
 345            switch (pdev->dev_state)
 346            {
 347              case USBD_STATE_ADDRESSED:
 348                if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
 349                {
 350                  USBD_CtlError(pdev, req);
 351                  break;
 352                }
 353                pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \
 354                      &pdev->ep_out[ep_addr & 0x7FU];
 355  
 356                pep->status = 0x0000U;
 357  
 358                (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
 359                break;
 360  
 361              case USBD_STATE_CONFIGURED:
 362                if ((ep_addr & 0x80U) == 0x80U)
 363                {
 364                  if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U)
 365                  {
 366                    USBD_CtlError(pdev, req);
 367                    break;
 368                  }
 369                }
 370                else
 371                {
 372                  if (pdev->ep_out[ep_addr & 0xFU].is_used == 0U)
 373                  {
 374                    USBD_CtlError(pdev, req);
 375                    break;
 376                  }
 377                }
 378  
 379                pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \
 380                      &pdev->ep_out[ep_addr & 0x7FU];
 381  
 382                if ((ep_addr == 0x00U) || (ep_addr == 0x80U))
 383                {
 384                  pep->status = 0x0000U;
 385                }
 386                else if (USBD_LL_IsStallEP(pdev, ep_addr) != 0U)
 387                {
 388                  pep->status = 0x0001U;
 389                }
 390                else
 391                {
 392                  pep->status = 0x0000U;
 393                }
 394  
 395                (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
 396                break;
 397  
 398              default:
 399                USBD_CtlError(pdev, req);
 400                break;
 401            }
 402            break;
 403  
 404          default:
 405            USBD_CtlError(pdev, req);
 406            break;
 407        }
 408        break;
 409  
 410      default:
 411        USBD_CtlError(pdev, req);
 412        break;
 413    }
 414  
 415    return ret;
 416  }
 417  
 418  
 419  /**
 420    * @brief  USBD_GetDescriptor
 421    *         Handle Get Descriptor requests
 422    * @param  pdev: device instance
 423    * @param  req: usb request
 424    * @retval status
 425    */
 426  static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 427  {
 428    uint16_t len = 0U;
 429    uint8_t *pbuf = NULL;
 430    uint8_t err = 0U;
 431  
 432    switch (req->wValue >> 8)
 433    {
 434  #if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U))
 435      case USB_DESC_TYPE_BOS:
 436        if (pdev->pDesc->GetBOSDescriptor != NULL)
 437        {
 438          pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len);
 439        }
 440        else
 441        {
 442          USBD_CtlError(pdev, req);
 443          err++;
 444        }
 445        break;
 446  #endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U) */
 447      case USB_DESC_TYPE_DEVICE:
 448        pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
 449        break;
 450  
 451      case USB_DESC_TYPE_CONFIGURATION:
 452        if (pdev->dev_speed == USBD_SPEED_HIGH)
 453        {
 454  #ifdef USE_USBD_COMPOSITE
 455          if ((uint8_t)(pdev->NumClasses) > 0U)
 456          {
 457            pbuf = (uint8_t *)USBD_CMPSIT.GetHSConfigDescriptor(&len);
 458          }
 459          else
 460  #endif /* USE_USBD_COMPOSITE */
 461          {
 462            pbuf = (uint8_t *)pdev->pClass[0]->GetHSConfigDescriptor(&len);
 463          }
 464          pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
 465        }
 466        else
 467        {
 468  #ifdef USE_USBD_COMPOSITE
 469          if ((uint8_t)(pdev->NumClasses) > 0U)
 470          {
 471            pbuf = (uint8_t *)USBD_CMPSIT.GetFSConfigDescriptor(&len);
 472          }
 473          else
 474  #endif /* USE_USBD_COMPOSITE */
 475          {
 476            pbuf = (uint8_t *)pdev->pClass[0]->GetFSConfigDescriptor(&len);
 477          }
 478          pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
 479        }
 480        break;
 481  
 482      case USB_DESC_TYPE_STRING:
 483        switch ((uint8_t)(req->wValue))
 484        {
 485          case USBD_IDX_LANGID_STR:
 486            if (pdev->pDesc->GetLangIDStrDescriptor != NULL)
 487            {
 488              pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
 489            }
 490            else
 491            {
 492              USBD_CtlError(pdev, req);
 493              err++;
 494            }
 495            break;
 496  
 497          case USBD_IDX_MFC_STR:
 498            if (pdev->pDesc->GetManufacturerStrDescriptor != NULL)
 499            {
 500              pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len);
 501            }
 502            else
 503            {
 504              USBD_CtlError(pdev, req);
 505              err++;
 506            }
 507            break;
 508  
 509          case USBD_IDX_PRODUCT_STR:
 510            if (pdev->pDesc->GetProductStrDescriptor != NULL)
 511            {
 512              pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
 513            }
 514            else
 515            {
 516              USBD_CtlError(pdev, req);
 517              err++;
 518            }
 519            break;
 520  
 521          case USBD_IDX_SERIAL_STR:
 522            if (pdev->pDesc->GetSerialStrDescriptor != NULL)
 523            {
 524              pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
 525            }
 526            else
 527            {
 528              USBD_CtlError(pdev, req);
 529              err++;
 530            }
 531            break;
 532  
 533          case USBD_IDX_CONFIG_STR:
 534            if (pdev->pDesc->GetConfigurationStrDescriptor != NULL)
 535            {
 536              pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len);
 537            }
 538            else
 539            {
 540              USBD_CtlError(pdev, req);
 541              err++;
 542            }
 543            break;
 544  
 545          case USBD_IDX_INTERFACE_STR:
 546            if (pdev->pDesc->GetInterfaceStrDescriptor != NULL)
 547            {
 548              pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len);
 549            }
 550            else
 551            {
 552              USBD_CtlError(pdev, req);
 553              err++;
 554            }
 555            break;
 556  
 557          default:
 558  #if (USBD_SUPPORT_USER_STRING_DESC == 1U)
 559            pbuf = NULL;
 560  
 561            for (uint32_t idx = 0U; (idx < pdev->NumClasses); idx++)
 562            {
 563              if (pdev->pClass[idx]->GetUsrStrDescriptor != NULL)
 564              {
 565                pdev->classId = idx;
 566                pbuf = pdev->pClass[idx]->GetUsrStrDescriptor(pdev, LOBYTE(req->wValue), &len);
 567  
 568                if (pbuf == NULL) /* This means that no class recognized the string index */
 569                {
 570                  continue;
 571                }
 572                else
 573                {
 574                  break;
 575                }
 576              }
 577            }
 578  #endif /* USBD_SUPPORT_USER_STRING_DESC  */
 579  
 580  #if (USBD_CLASS_USER_STRING_DESC == 1U)
 581            if (pdev->pDesc->GetUserStrDescriptor != NULL)
 582            {
 583              pbuf = pdev->pDesc->GetUserStrDescriptor(pdev->dev_speed, LOBYTE(req->wValue), &len);
 584            }
 585            else
 586            {
 587              USBD_CtlError(pdev, req);
 588              err++;
 589            }
 590  #endif /* USBD_SUPPORT_USER_STRING_DESC  */
 591  
 592  #if ((USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U))
 593            USBD_CtlError(pdev, req);
 594            err++;
 595  #endif /* (USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U) */
 596            break;
 597        }
 598        break;
 599  
 600      case USB_DESC_TYPE_DEVICE_QUALIFIER:
 601        if (pdev->dev_speed == USBD_SPEED_HIGH)
 602        {
 603  #ifdef USE_USBD_COMPOSITE
 604          if ((uint8_t)(pdev->NumClasses) > 0U)
 605          {
 606            pbuf = (uint8_t *)USBD_CMPSIT.GetDeviceQualifierDescriptor(&len);
 607          }
 608          else
 609  #endif /* USE_USBD_COMPOSITE */
 610          {
 611            pbuf = (uint8_t *)pdev->pClass[0]->GetDeviceQualifierDescriptor(&len);
 612          }
 613        }
 614        else
 615        {
 616          USBD_CtlError(pdev, req);
 617          err++;
 618        }
 619        break;
 620  
 621      case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
 622        if (pdev->dev_speed == USBD_SPEED_HIGH)
 623        {
 624  #ifdef USE_USBD_COMPOSITE
 625          if ((uint8_t)(pdev->NumClasses) > 0U)
 626          {
 627            pbuf = (uint8_t *)USBD_CMPSIT.GetOtherSpeedConfigDescriptor(&len);
 628          }
 629          else
 630  #endif /* USE_USBD_COMPOSITE */
 631          {
 632            pbuf = (uint8_t *)pdev->pClass[0]->GetOtherSpeedConfigDescriptor(&len);
 633          }
 634          pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
 635        }
 636        else
 637        {
 638          USBD_CtlError(pdev, req);
 639          err++;
 640        }
 641        break;
 642  
 643      default:
 644        USBD_CtlError(pdev, req);
 645        err++;
 646        break;
 647    }
 648  
 649    if (err != 0U)
 650    {
 651      return;
 652    }
 653  
 654    if (req->wLength != 0U)
 655    {
 656      if (len != 0U)
 657      {
 658        len = MIN(len, req->wLength);
 659        (void)USBD_CtlSendData(pdev, pbuf, len);
 660      }
 661      else
 662      {
 663        USBD_CtlError(pdev, req);
 664      }
 665    }
 666    else
 667    {
 668      (void)USBD_CtlSendStatus(pdev);
 669    }
 670  }
 671  
 672  
 673  /**
 674    * @brief  USBD_SetAddress
 675    *         Set device address
 676    * @param  pdev: device instance
 677    * @param  req: usb request
 678    * @retval status
 679    */
 680  static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 681  {
 682    uint8_t  dev_addr;
 683  
 684    if ((req->wIndex == 0U) && (req->wLength == 0U) && (req->wValue < 128U))
 685    {
 686      dev_addr = (uint8_t)(req->wValue) & 0x7FU;
 687  
 688      if (pdev->dev_state == USBD_STATE_CONFIGURED)
 689      {
 690        USBD_CtlError(pdev, req);
 691      }
 692      else
 693      {
 694        pdev->dev_address = dev_addr;
 695        (void)USBD_LL_SetUSBAddress(pdev, dev_addr);
 696        (void)USBD_CtlSendStatus(pdev);
 697  
 698        if (dev_addr != 0U)
 699        {
 700          pdev->dev_state = USBD_STATE_ADDRESSED;
 701        }
 702        else
 703        {
 704          pdev->dev_state = USBD_STATE_DEFAULT;
 705        }
 706      }
 707    }
 708    else
 709    {
 710      USBD_CtlError(pdev, req);
 711    }
 712  }
 713  
 714  /**
 715    * @brief  USBD_SetConfig
 716    *         Handle Set device configuration request
 717    * @param  pdev: device instance
 718    * @param  req: usb request
 719    * @retval status
 720    */
 721  static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 722  {
 723    USBD_StatusTypeDef ret = USBD_OK;
 724    static uint8_t cfgidx;
 725  
 726    cfgidx = (uint8_t)(req->wValue);
 727  
 728    if (cfgidx > USBD_MAX_NUM_CONFIGURATION)
 729    {
 730      USBD_CtlError(pdev, req);
 731      return USBD_FAIL;
 732    }
 733  
 734    switch (pdev->dev_state)
 735    {
 736      case USBD_STATE_ADDRESSED:
 737        if (cfgidx != 0U)
 738        {
 739          pdev->dev_config = cfgidx;
 740  
 741          ret = USBD_SetClassConfig(pdev, cfgidx);
 742  
 743          if (ret != USBD_OK)
 744          {
 745            USBD_CtlError(pdev, req);
 746            pdev->dev_state = USBD_STATE_ADDRESSED;
 747          }
 748          else
 749          {
 750            (void)USBD_CtlSendStatus(pdev);
 751            pdev->dev_state = USBD_STATE_CONFIGURED;
 752  
 753  #if (USBD_USER_REGISTER_CALLBACK == 1U)
 754            if (pdev->DevStateCallback != NULL)
 755            {
 756              pdev->DevStateCallback(USBD_STATE_CONFIGURED, cfgidx);
 757            }
 758  #endif /* USBD_USER_REGISTER_CALLBACK */
 759          }
 760        }
 761        else
 762        {
 763          (void)USBD_CtlSendStatus(pdev);
 764        }
 765        break;
 766  
 767      case USBD_STATE_CONFIGURED:
 768        if (cfgidx == 0U)
 769        {
 770          pdev->dev_state = USBD_STATE_ADDRESSED;
 771          pdev->dev_config = cfgidx;
 772          (void)USBD_ClrClassConfig(pdev, cfgidx);
 773          (void)USBD_CtlSendStatus(pdev);
 774        }
 775        else if (cfgidx != pdev->dev_config)
 776        {
 777          /* Clear old configuration */
 778          (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
 779  
 780          /* set new configuration */
 781          pdev->dev_config = cfgidx;
 782  
 783          ret = USBD_SetClassConfig(pdev, cfgidx);
 784  
 785          if (ret != USBD_OK)
 786          {
 787            USBD_CtlError(pdev, req);
 788            (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
 789            pdev->dev_state = USBD_STATE_ADDRESSED;
 790          }
 791          else
 792          {
 793            (void)USBD_CtlSendStatus(pdev);
 794          }
 795        }
 796        else
 797        {
 798          (void)USBD_CtlSendStatus(pdev);
 799        }
 800        break;
 801  
 802      default:
 803        USBD_CtlError(pdev, req);
 804        (void)USBD_ClrClassConfig(pdev, cfgidx);
 805        ret = USBD_FAIL;
 806        break;
 807    }
 808  
 809    return ret;
 810  }
 811  
 812  /**
 813    * @brief  USBD_GetConfig
 814    *         Handle Get device configuration request
 815    * @param  pdev: device instance
 816    * @param  req: usb request
 817    * @retval status
 818    */
 819  static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 820  {
 821    if (req->wLength != 1U)
 822    {
 823      USBD_CtlError(pdev, req);
 824    }
 825    else
 826    {
 827      switch (pdev->dev_state)
 828      {
 829        case USBD_STATE_DEFAULT:
 830        case USBD_STATE_ADDRESSED:
 831          pdev->dev_default_config = 0U;
 832          (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_default_config, 1U);
 833          break;
 834  
 835        case USBD_STATE_CONFIGURED:
 836          (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config, 1U);
 837          break;
 838  
 839        default:
 840          USBD_CtlError(pdev, req);
 841          break;
 842      }
 843    }
 844  }
 845  
 846  /**
 847    * @brief  USBD_GetStatus
 848    *         Handle Get Status request
 849    * @param  pdev: device instance
 850    * @param  req: usb request
 851    * @retval status
 852    */
 853  static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 854  {
 855    switch (pdev->dev_state)
 856    {
 857      case USBD_STATE_DEFAULT:
 858      case USBD_STATE_ADDRESSED:
 859      case USBD_STATE_CONFIGURED:
 860        if (req->wLength != 0x2U)
 861        {
 862          USBD_CtlError(pdev, req);
 863          break;
 864        }
 865  
 866  #if (USBD_SELF_POWERED == 1U)
 867        pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
 868  #else
 869        pdev->dev_config_status = 0U;
 870  #endif /* USBD_SELF_POWERED */
 871  
 872        if (pdev->dev_remote_wakeup != 0U)
 873        {
 874          pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
 875        }
 876  
 877        (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
 878        break;
 879  
 880      default:
 881        USBD_CtlError(pdev, req);
 882        break;
 883    }
 884  }
 885  
 886  
 887  /**
 888    * @brief  USBD_SetFeature
 889    *         Handle Set device feature request
 890    * @param  pdev: device instance
 891    * @param  req: usb request
 892    * @retval status
 893    */
 894  static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 895  {
 896    if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
 897    {
 898      pdev->dev_remote_wakeup = 1U;
 899      (void)USBD_CtlSendStatus(pdev);
 900    }
 901    else if (req->wValue == USB_FEATURE_TEST_MODE)
 902    {
 903      pdev->dev_test_mode = (uint8_t)(req->wIndex >> 8);
 904      (void)USBD_CtlSendStatus(pdev);
 905    }
 906    else
 907    {
 908      USBD_CtlError(pdev, req);
 909    }
 910  }
 911  
 912  
 913  /**
 914    * @brief  USBD_ClrFeature
 915    *         Handle clear device feature request
 916    * @param  pdev: device instance
 917    * @param  req: usb request
 918    * @retval status
 919    */
 920  static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 921  {
 922    switch (pdev->dev_state)
 923    {
 924      case USBD_STATE_DEFAULT:
 925      case USBD_STATE_ADDRESSED:
 926      case USBD_STATE_CONFIGURED:
 927        if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
 928        {
 929          pdev->dev_remote_wakeup = 0U;
 930          (void)USBD_CtlSendStatus(pdev);
 931        }
 932        break;
 933  
 934      default:
 935        USBD_CtlError(pdev, req);
 936        break;
 937    }
 938  }
 939  
 940  
 941  /**
 942    * @brief  USBD_ParseSetupRequest
 943    *         Copy buffer into setup structure
 944    * @param  pdev: device instance
 945    * @param  req: usb request
 946    * @retval None
 947    */
 948  void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
 949  {
 950    uint8_t *pbuff = pdata;
 951  
 952    req->bmRequest = *(uint8_t *)(pbuff);
 953  
 954    pbuff++;
 955    req->bRequest = *(uint8_t *)(pbuff);
 956  
 957    pbuff++;
 958    req->wValue = SWAPBYTE(pbuff);
 959  
 960    pbuff++;
 961    pbuff++;
 962    req->wIndex = SWAPBYTE(pbuff);
 963  
 964    pbuff++;
 965    pbuff++;
 966    req->wLength = SWAPBYTE(pbuff);
 967  }
 968  
 969  
 970  /**
 971    * @brief  USBD_CtlError
 972    *         Handle USB low level Error
 973    * @param  pdev: device instance
 974    * @param  req: usb request
 975    * @retval None
 976    */
 977  void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
 978  {
 979    UNUSED(req);
 980  
 981    (void)USBD_LL_StallEP(pdev, 0x80U);
 982    (void)USBD_LL_StallEP(pdev, 0U);
 983  }
 984  
 985  
 986  /**
 987    * @brief  USBD_GetString
 988    *         Convert Ascii string into unicode one
 989    * @param  desc : descriptor buffer
 990    * @param  unicode : Formatted string buffer (unicode)
 991    * @param  len : descriptor length
 992    * @retval None
 993    */
 994  void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
 995  {
 996    uint8_t idx = 0U;
 997    uint8_t *pdesc;
 998  
 999    if (desc == NULL)
1000    {
1001      return;
1002    }
1003  
1004    pdesc = desc;
1005    *len = ((uint16_t)USBD_GetLen(pdesc) * 2U) + 2U;
1006  
1007    unicode[idx] = *(uint8_t *)len;
1008    idx++;
1009    unicode[idx] = USB_DESC_TYPE_STRING;
1010    idx++;
1011  
1012    while (*pdesc != (uint8_t)'\0')
1013    {
1014      unicode[idx] = *pdesc;
1015      pdesc++;
1016      idx++;
1017  
1018      unicode[idx] = 0U;
1019      idx++;
1020    }
1021  }
1022  
1023  
1024  /**
1025    * @brief  USBD_GetLen
1026    *         return the string length
1027     * @param  buf : pointer to the ascii string buffer
1028    * @retval string length
1029    */
1030  static uint8_t USBD_GetLen(uint8_t *buf)
1031  {
1032    uint8_t  len = 0U;
1033    uint8_t *pbuff = buf;
1034  
1035    while (*pbuff != (uint8_t)'\0')
1036    {
1037      len++;
1038      pbuff++;
1039    }
1040  
1041    return len;
1042  }
1043  /**
1044    * @}
1045    */
1046  
1047  
1048  /**
1049    * @}
1050    */
1051  
1052  
1053  /**
1054    * @}
1055    */
1056