usbd_core.c
   1  /**
   2    ******************************************************************************
   3    * @file    usbd_core.c
   4    * @author  MCD Application Team
   5    * @brief   This file provides all the USBD core functions.
   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_core.h"
  21  
  22  #ifdef USE_USBD_COMPOSITE
  23  #include "usbd_composite_builder.h"
  24  #endif /* USE_USBD_COMPOSITE */
  25  
  26  /** @addtogroup STM32_USBD_DEVICE_LIBRARY
  27    * @{
  28    */
  29  
  30  
  31  /** @defgroup USBD_CORE
  32    * @brief usbd core module
  33    * @{
  34    */
  35  
  36  /** @defgroup USBD_CORE_Private_TypesDefinitions
  37    * @{
  38    */
  39  
  40  /**
  41    * @}
  42    */
  43  
  44  
  45  /** @defgroup USBD_CORE_Private_Defines
  46    * @{
  47    */
  48  
  49  /**
  50    * @}
  51    */
  52  
  53  
  54  /** @defgroup USBD_CORE_Private_Macros
  55    * @{
  56    */
  57  
  58  /**
  59    * @}
  60    */
  61  
  62  
  63  /** @defgroup USBD_CORE_Private_FunctionPrototypes
  64    * @{
  65    */
  66  
  67  /**
  68    * @}
  69    */
  70  
  71  /** @defgroup USBD_CORE_Private_Variables
  72    * @{
  73    */
  74  
  75  /**
  76    * @}
  77    */
  78  
  79  
  80  /** @defgroup USBD_CORE_Private_Functions
  81    * @{
  82    */
  83  
  84  /**
  85    * @brief  USBD_Init
  86    *         Initializes the device stack and load the class driver
  87    * @param  pdev: device instance
  88    * @param  pdesc: Descriptor structure address
  89    * @param  id: Low level core index
  90    * @retval None
  91    */
  92  USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev,
  93                               USBD_DescriptorsTypeDef *pdesc, uint8_t id)
  94  {
  95    USBD_StatusTypeDef ret;
  96  
  97    /* Check whether the USB Host handle is valid */
  98    if (pdev == NULL)
  99    {
 100  #if (USBD_DEBUG_LEVEL > 1U)
 101      USBD_ErrLog("Invalid Device handle");
 102  #endif /* (USBD_DEBUG_LEVEL > 1U) */
 103      return USBD_FAIL;
 104    }
 105  
 106  #ifdef USE_USBD_COMPOSITE
 107    /* Parse the table of classes in use */
 108    for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
 109    {
 110      /* Unlink previous class*/
 111      pdev->pClass[i] = NULL;
 112      pdev->pUserData[i] = NULL;
 113  
 114      /* Set class as inactive */
 115      pdev->tclasslist[i].Active = 0;
 116      pdev->NumClasses = 0;
 117      pdev->classId = 0;
 118    }
 119  #else
 120    /* Unlink previous class*/
 121    pdev->pClass[0] = NULL;
 122    pdev->pUserData[0] = NULL;
 123  #endif /* USE_USBD_COMPOSITE */
 124  
 125    pdev->pConfDesc = NULL;
 126  
 127    /* Assign USBD Descriptors */
 128    if (pdesc != NULL)
 129    {
 130      pdev->pDesc = pdesc;
 131    }
 132  
 133    /* Set Device initial State */
 134    pdev->dev_state = USBD_STATE_DEFAULT;
 135    pdev->id = id;
 136  
 137    /* Initialize low level driver */
 138    ret = USBD_LL_Init(pdev);
 139  
 140    return ret;
 141  }
 142  
 143  /**
 144    * @brief  USBD_DeInit
 145    *         Re-Initialize the device library
 146    * @param  pdev: device instance
 147    * @retval status: status
 148    */
 149  USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
 150  {
 151    USBD_StatusTypeDef ret;
 152  
 153    /* Disconnect the USB Device */
 154    (void)USBD_LL_Stop(pdev);
 155  
 156    /* Set Default State */
 157    pdev->dev_state = USBD_STATE_DEFAULT;
 158  
 159  #ifdef USE_USBD_COMPOSITE
 160    /* Parse the table of classes in use */
 161    for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
 162    {
 163      /* Check if current class is in use */
 164      if ((pdev->tclasslist[i].Active) == 1U)
 165      {
 166        if (pdev->pClass[i] != NULL)
 167        {
 168          pdev->classId = i;
 169          /* Free Class Resources */
 170          pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
 171        }
 172      }
 173    }
 174  #else
 175    /* Free Class Resources */
 176    if (pdev->pClass[0] != NULL)
 177    {
 178      pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
 179    }
 180  
 181    pdev->pUserData[0] = NULL;
 182  
 183  #endif /* USE_USBD_COMPOSITE */
 184  
 185    /* Free Device descriptors resources */
 186    pdev->pDesc = NULL;
 187    pdev->pConfDesc = NULL;
 188  
 189    /* DeInitialize low level driver */
 190    ret = USBD_LL_DeInit(pdev);
 191  
 192    return ret;
 193  }
 194  
 195  /**
 196    * @brief  USBD_RegisterClass
 197    *         Link class driver to Device Core.
 198    * @param  pDevice : Device Handle
 199    * @param  pclass: Class handle
 200    * @retval USBD Status
 201    */
 202  USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
 203  {
 204    uint16_t len = 0U;
 205  
 206    if (pclass == NULL)
 207    {
 208  #if (USBD_DEBUG_LEVEL > 1U)
 209      USBD_ErrLog("Invalid Class handle");
 210  #endif /* (USBD_DEBUG_LEVEL > 1U) */
 211      return USBD_FAIL;
 212    }
 213  
 214    /* link the class to the USB Device handle */
 215    pdev->pClass[0] = pclass;
 216  
 217    /* Get Device Configuration Descriptor */
 218  #ifdef USE_USB_HS
 219    if (pdev->pClass[pdev->classId]->GetHSConfigDescriptor != NULL)
 220    {
 221      pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetHSConfigDescriptor(&len);
 222    }
 223  #else /* Default USE_USB_FS */
 224    if (pdev->pClass[pdev->classId]->GetFSConfigDescriptor != NULL)
 225    {
 226      pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetFSConfigDescriptor(&len);
 227    }
 228  #endif /* USE_USB_FS */
 229  
 230    /* Increment the NumClasses */
 231    pdev->NumClasses ++;
 232  
 233    return USBD_OK;
 234  }
 235  
 236  #ifdef USE_USBD_COMPOSITE
 237  /**
 238    * @brief  USBD_RegisterClassComposite
 239    *         Link class driver to Device Core.
 240    * @param  pdev : Device Handle
 241    * @param  pclass: Class handle
 242    * @param  classtype: Class type
 243    * @param  EpAddr: Endpoint Address handle
 244    * @retval USBD Status
 245    */
 246  USBD_StatusTypeDef  USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
 247                                                  USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr)
 248  {
 249    USBD_StatusTypeDef   ret = USBD_OK;
 250    uint16_t len = 0U;
 251  
 252    if ((pdev->classId < USBD_MAX_SUPPORTED_CLASS) && (pdev->NumClasses < USBD_MAX_SUPPORTED_CLASS))
 253    {
 254      if ((uint32_t)pclass != 0U)
 255      {
 256        /* Link the class to the USB Device handle */
 257        pdev->pClass[pdev->classId] = pclass;
 258        ret = USBD_OK;
 259  
 260        pdev->tclasslist[pdev->classId].EpAdd = EpAddr;
 261  
 262        /* Call the composite class builder */
 263        (void)USBD_CMPSIT_AddClass(pdev, pclass, classtype, 0);
 264  
 265        /* Increment the ClassId for the next occurrence */
 266        pdev->classId ++;
 267        pdev->NumClasses ++;
 268      }
 269      else
 270      {
 271  #if (USBD_DEBUG_LEVEL > 1U)
 272        USBD_ErrLog("Invalid Class handle");
 273  #endif /* (USBD_DEBUG_LEVEL > 1U) */
 274        ret = USBD_FAIL;
 275      }
 276    }
 277  
 278    if (ret == USBD_OK)
 279    {
 280      /* Get Device Configuration Descriptor */
 281  #ifdef USE_USB_HS
 282      pdev->pConfDesc = USBD_CMPSIT.GetHSConfigDescriptor(&len);
 283  #else /* Default USE_USB_FS */
 284      pdev->pConfDesc = USBD_CMPSIT.GetFSConfigDescriptor(&len);
 285  #endif /* USE_USB_FS */
 286    }
 287  
 288    return ret;
 289  }
 290  
 291  /**
 292    * @brief  USBD_UnRegisterClassComposite
 293    *         UnLink all composite class drivers from Device Core.
 294    * @param  pDevice : Device Handle
 295    * @retval USBD Status
 296    */
 297  USBD_StatusTypeDef  USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev)
 298  {
 299    USBD_StatusTypeDef   ret = USBD_FAIL;
 300    uint8_t idx1;
 301    uint8_t idx2;
 302  
 303    /* Unroll all activated classes */
 304    for (idx1 = 0; idx1 < pdev->NumClasses; idx1++)
 305    {
 306      /* Check if the class correspond to the requested type and if it is active */
 307      if (pdev->tclasslist[idx1].Active == 1U)
 308      {
 309        /* Set the new class ID */
 310        pdev->classId = idx1;
 311  
 312        /* Free resources used by the selected class */
 313        if (pdev->pClass[pdev->classId] != NULL)
 314        {
 315          /* Free Class Resources */
 316          if (pdev->pClass[pdev->classId]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
 317          {
 318  #if (USBD_DEBUG_LEVEL > 1U)
 319            USBD_ErrLog("Class DeInit didn't succeed!, can't unregister selected class");
 320  #endif /* (USBD_DEBUG_LEVEL > 1U) */
 321  
 322            ret = USBD_FAIL;
 323          }
 324        }
 325  
 326        /* Free the class pointer */
 327        pdev->pClass[pdev->classId] = NULL;
 328  
 329        /* Free the class location in classes table and reset its parameters to zero */
 330        pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_NONE;
 331        pdev->tclasslist[pdev->classId].ClassId = 0U;
 332        pdev->tclasslist[pdev->classId].Active = 0U;
 333        pdev->tclasslist[pdev->classId].NumEps = 0U;
 334        pdev->tclasslist[pdev->classId].NumIf = 0U;
 335        pdev->tclasslist[pdev->classId].CurrPcktSze = 0U;
 336  
 337        for (idx2 = 0U; idx2 < USBD_MAX_CLASS_ENDPOINTS; idx2++)
 338        {
 339          pdev->tclasslist[pdev->classId].Eps[idx2].add = 0U;
 340          pdev->tclasslist[pdev->classId].Eps[idx2].type = 0U;
 341          pdev->tclasslist[pdev->classId].Eps[idx2].size = 0U;
 342          pdev->tclasslist[pdev->classId].Eps[idx2].is_used = 0U;
 343        }
 344  
 345        for (idx2 = 0U; idx2 < USBD_MAX_CLASS_INTERFACES; idx2++)
 346        {
 347          pdev->tclasslist[pdev->classId].Ifs[idx2] = 0U;
 348        }
 349      }
 350    }
 351  
 352    /* Reset the configuration descriptor */
 353    (void)USBD_CMPST_ClearConfDesc(pdev);
 354  
 355    /* Reset the class ID and number of classes */
 356    pdev->classId = 0U;
 357    pdev->NumClasses = 0U;
 358  
 359    return ret;
 360  }
 361  #endif /* USE_USBD_COMPOSITE */
 362  
 363  #if (USBD_USER_REGISTER_CALLBACK == 1U)
 364  /**
 365    * @brief  USBD_RegisterDevStateCallback
 366    * @param  pdev : Device Handle
 367    * @param  pUserCallback: User Callback
 368    * @retval USBD Status
 369    */
 370  USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback)
 371  {
 372    pdev->DevStateCallback = pUserCallback;
 373  
 374    return USBD_OK;
 375  }
 376  #endif /* USBD_USER_REGISTER_CALLBACK */
 377  /**
 378    * @brief  USBD_Start
 379    *         Start the USB Device Core.
 380    * @param  pdev: Device Handle
 381    * @retval USBD Status
 382    */
 383  USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev)
 384  {
 385  #ifdef USE_USBD_COMPOSITE
 386    pdev->classId = 0U;
 387  #endif /* USE_USBD_COMPOSITE */
 388  
 389    /* Start the low level driver  */
 390    return USBD_LL_Start(pdev);
 391  }
 392  
 393  /**
 394    * @brief  USBD_Stop
 395    *         Stop the USB Device Core.
 396    * @param  pdev: Device Handle
 397    * @retval USBD Status
 398    */
 399  USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev)
 400  {
 401    /* Disconnect USB Device */
 402    (void)USBD_LL_Stop(pdev);
 403  
 404    /* Free Class Resources */
 405  #ifdef USE_USBD_COMPOSITE
 406    /* Parse the table of classes in use */
 407    for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
 408    {
 409      /* Check if current class is in use */
 410      if ((pdev->tclasslist[i].Active) == 1U)
 411      {
 412        if (pdev->pClass[i] != NULL)
 413        {
 414          pdev->classId = i;
 415          /* Free Class Resources */
 416          (void)pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
 417        }
 418      }
 419    }
 420  
 421    /* Reset the class ID */
 422    pdev->classId = 0U;
 423  #else
 424    if (pdev->pClass[0] != NULL)
 425    {
 426      (void)pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
 427    }
 428  #endif /* USE_USBD_COMPOSITE */
 429  
 430    return USBD_OK;
 431  }
 432  
 433  /**
 434    * @brief  USBD_RunTestMode
 435    *         Launch test mode process
 436    * @param  pdev: device instance
 437    * @retval status
 438    */
 439  USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev)
 440  {
 441  #ifdef USBD_HS_TESTMODE_ENABLE
 442    USBD_StatusTypeDef ret;
 443  
 444    /* Run USB HS test mode */
 445    ret = USBD_LL_SetTestMode(pdev, pdev->dev_test_mode);
 446  
 447    return ret;
 448  #else
 449    /* Prevent unused argument compilation warning */
 450    UNUSED(pdev);
 451  
 452    return USBD_OK;
 453  #endif /* USBD_HS_TESTMODE_ENABLE */
 454  }
 455  
 456  /**
 457    * @brief  USBD_SetClassConfig
 458    *        Configure device and start the interface
 459    * @param  pdev: device instance
 460    * @param  cfgidx: configuration index
 461    * @retval status
 462    */
 463  
 464  USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
 465  {
 466    USBD_StatusTypeDef ret = USBD_OK;
 467  
 468  #ifdef USE_USBD_COMPOSITE
 469    /* Parse the table of classes in use */
 470    for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
 471    {
 472      /* Check if current class is in use */
 473      if ((pdev->tclasslist[i].Active) == 1U)
 474      {
 475        if (pdev->pClass[i] != NULL)
 476        {
 477          pdev->classId = i;
 478          /* Set configuration  and Start the Class*/
 479          if (pdev->pClass[i]->Init(pdev, cfgidx) != 0U)
 480          {
 481            ret = USBD_FAIL;
 482          }
 483        }
 484      }
 485    }
 486  #else
 487    if (pdev->pClass[0] != NULL)
 488    {
 489      /* Set configuration and Start the Class */
 490      ret = (USBD_StatusTypeDef)pdev->pClass[0]->Init(pdev, cfgidx);
 491    }
 492  #endif /* USE_USBD_COMPOSITE */
 493  
 494    return ret;
 495  }
 496  
 497  /**
 498    * @brief  USBD_ClrClassConfig
 499    *         Clear current configuration
 500    * @param  pdev: device instance
 501    * @param  cfgidx: configuration index
 502    * @retval status: USBD_StatusTypeDef
 503    */
 504  USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
 505  {
 506    USBD_StatusTypeDef ret = USBD_OK;
 507  
 508  #ifdef USE_USBD_COMPOSITE
 509    /* Parse the table of classes in use */
 510    for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
 511    {
 512      /* Check if current class is in use */
 513      if ((pdev->tclasslist[i].Active) == 1U)
 514      {
 515        if (pdev->pClass[i] != NULL)
 516        {
 517          pdev->classId = i;
 518          /* Clear configuration  and De-initialize the Class process */
 519          if (pdev->pClass[i]->DeInit(pdev, cfgidx) != 0U)
 520          {
 521            ret = USBD_FAIL;
 522          }
 523        }
 524      }
 525    }
 526  #else
 527    /* Clear configuration  and De-initialize the Class process */
 528    if (pdev->pClass[0]->DeInit(pdev, cfgidx) != 0U)
 529    {
 530      ret = USBD_FAIL;
 531    }
 532  #endif /* USE_USBD_COMPOSITE */
 533  
 534    return ret;
 535  }
 536  
 537  
 538  /**
 539    * @brief  USBD_LL_SetupStage
 540    *         Handle the setup stage
 541    * @param  pdev: device instance
 542    * @retval status
 543    */
 544  USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
 545  {
 546    USBD_StatusTypeDef ret;
 547  
 548    USBD_ParseSetupRequest(&pdev->request, psetup);
 549  
 550    pdev->ep0_state = USBD_EP0_SETUP;
 551  
 552    pdev->ep0_data_len = pdev->request.wLength;
 553  
 554    switch (pdev->request.bmRequest & 0x1FU)
 555    {
 556      case USB_REQ_RECIPIENT_DEVICE:
 557        ret = USBD_StdDevReq(pdev, &pdev->request);
 558        break;
 559  
 560      case USB_REQ_RECIPIENT_INTERFACE:
 561        ret = USBD_StdItfReq(pdev, &pdev->request);
 562        break;
 563  
 564      case USB_REQ_RECIPIENT_ENDPOINT:
 565        ret = USBD_StdEPReq(pdev, &pdev->request);
 566        break;
 567  
 568      default:
 569        ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
 570        break;
 571    }
 572  
 573    return ret;
 574  }
 575  
 576  /**
 577    * @brief  USBD_LL_DataOutStage
 578    *         Handle data OUT stage
 579    * @param  pdev: device instance
 580    * @param  epnum: endpoint index
 581    * @param  pdata: data pointer
 582    * @retval status
 583    */
 584  USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev,
 585                                          uint8_t epnum, uint8_t *pdata)
 586  {
 587    USBD_EndpointTypeDef *pep;
 588    USBD_StatusTypeDef ret = USBD_OK;
 589    uint8_t idx;
 590  
 591    if (epnum == 0U)
 592    {
 593      pep = &pdev->ep_out[0];
 594  
 595      if (pdev->ep0_state == USBD_EP0_DATA_OUT)
 596      {
 597        if (pep->rem_length > pep->maxpacket)
 598        {
 599          pep->rem_length -= pep->maxpacket;
 600  
 601          (void)USBD_CtlContinueRx(pdev, pdata, MIN(pep->rem_length, pep->maxpacket));
 602        }
 603        else
 604        {
 605          /* Find the class ID relative to the current request */
 606          switch (pdev->request.bmRequest & 0x1FU)
 607          {
 608            case USB_REQ_RECIPIENT_DEVICE:
 609              /* Device requests must be managed by the first instantiated class
 610                 (or duplicated by all classes for simplicity) */
 611              idx = 0U;
 612              break;
 613  
 614            case USB_REQ_RECIPIENT_INTERFACE:
 615              idx = USBD_CoreFindIF(pdev, LOBYTE(pdev->request.wIndex));
 616              break;
 617  
 618            case USB_REQ_RECIPIENT_ENDPOINT:
 619              idx = USBD_CoreFindEP(pdev, LOBYTE(pdev->request.wIndex));
 620              break;
 621  
 622            default:
 623              /* Back to the first class in case of doubt */
 624              idx = 0U;
 625              break;
 626          }
 627  
 628          if (idx < USBD_MAX_SUPPORTED_CLASS)
 629          {
 630            /* Setup the class ID and route the request to the relative class function */
 631            if (pdev->dev_state == USBD_STATE_CONFIGURED)
 632            {
 633              if (pdev->pClass[idx]->EP0_RxReady != NULL)
 634              {
 635                pdev->classId = idx;
 636                pdev->pClass[idx]->EP0_RxReady(pdev);
 637              }
 638            }
 639          }
 640  
 641          (void)USBD_CtlSendStatus(pdev);
 642        }
 643      }
 644    }
 645    else
 646    {
 647      /* Get the class index relative to this interface */
 648      idx = USBD_CoreFindEP(pdev, (epnum & 0x7FU));
 649  
 650      if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
 651      {
 652        /* Call the class data out function to manage the request */
 653        if (pdev->dev_state == USBD_STATE_CONFIGURED)
 654        {
 655          if (pdev->pClass[idx]->DataOut != NULL)
 656          {
 657            pdev->classId = idx;
 658            ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataOut(pdev, epnum);
 659          }
 660        }
 661        if (ret != USBD_OK)
 662        {
 663          return ret;
 664        }
 665      }
 666    }
 667  
 668    return USBD_OK;
 669  }
 670  
 671  /**
 672    * @brief  USBD_LL_DataInStage
 673    *         Handle data in stage
 674    * @param  pdev: device instance
 675    * @param  epnum: endpoint index
 676    * @retval status
 677    */
 678  USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev,
 679                                         uint8_t epnum, uint8_t *pdata)
 680  {
 681    USBD_EndpointTypeDef *pep;
 682    USBD_StatusTypeDef ret;
 683    uint8_t idx;
 684  
 685    if (epnum == 0U)
 686    {
 687      pep = &pdev->ep_in[0];
 688  
 689      if (pdev->ep0_state == USBD_EP0_DATA_IN)
 690      {
 691        if (pep->rem_length > pep->maxpacket)
 692        {
 693          pep->rem_length -= pep->maxpacket;
 694  
 695          (void)USBD_CtlContinueSendData(pdev, pdata, pep->rem_length);
 696  
 697          /* Prepare endpoint for premature end of transfer */
 698          (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
 699        }
 700        else
 701        {
 702          /* last packet is MPS multiple, so send ZLP packet */
 703          if ((pep->maxpacket == pep->rem_length) &&
 704              (pep->total_length >= pep->maxpacket) &&
 705              (pep->total_length < pdev->ep0_data_len))
 706          {
 707            (void)USBD_CtlContinueSendData(pdev, NULL, 0U);
 708            pdev->ep0_data_len = 0U;
 709  
 710            /* Prepare endpoint for premature end of transfer */
 711            (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
 712          }
 713          else
 714          {
 715            if (pdev->dev_state == USBD_STATE_CONFIGURED)
 716            {
 717              if (pdev->pClass[0]->EP0_TxSent != NULL)
 718              {
 719                pdev->classId = 0U;
 720                pdev->pClass[0]->EP0_TxSent(pdev);
 721              }
 722            }
 723            (void)USBD_LL_StallEP(pdev, 0x80U);
 724            (void)USBD_CtlReceiveStatus(pdev);
 725          }
 726        }
 727      }
 728  
 729      if (pdev->dev_test_mode != 0U)
 730      {
 731        (void)USBD_RunTestMode(pdev);
 732        pdev->dev_test_mode = 0U;
 733      }
 734    }
 735    else
 736    {
 737      /* Get the class index relative to this interface */
 738      idx = USBD_CoreFindEP(pdev, ((uint8_t)epnum | 0x80U));
 739  
 740      if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
 741      {
 742        /* Call the class data out function to manage the request */
 743        if (pdev->dev_state == USBD_STATE_CONFIGURED)
 744        {
 745          if (pdev->pClass[idx]->DataIn != NULL)
 746          {
 747            pdev->classId = idx;
 748            ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataIn(pdev, epnum);
 749  
 750            if (ret != USBD_OK)
 751            {
 752              return ret;
 753            }
 754          }
 755        }
 756      }
 757    }
 758  
 759    return USBD_OK;
 760  }
 761  
 762  /**
 763    * @brief  USBD_LL_Reset
 764    *         Handle Reset event
 765    * @param  pdev: device instance
 766    * @retval status
 767    */
 768  
 769  USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
 770  {
 771    USBD_StatusTypeDef ret = USBD_OK;
 772  
 773    /* Upon Reset call user call back */
 774    pdev->dev_state = USBD_STATE_DEFAULT;
 775    pdev->ep0_state = USBD_EP0_IDLE;
 776    pdev->dev_config = 0U;
 777    pdev->dev_remote_wakeup = 0U;
 778    pdev->dev_test_mode = 0U;
 779  
 780  #ifdef USE_USBD_COMPOSITE
 781    /* Parse the table of classes in use */
 782    for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
 783    {
 784      /* Check if current class is in use */
 785      if ((pdev->tclasslist[i].Active) == 1U)
 786      {
 787        if (pdev->pClass[i] != NULL)
 788        {
 789          pdev->classId = i;
 790          /* Clear configuration  and De-initialize the Class process*/
 791  
 792          if (pdev->pClass[i]->DeInit != NULL)
 793          {
 794            if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
 795            {
 796              ret = USBD_FAIL;
 797            }
 798          }
 799        }
 800      }
 801    }
 802  #else
 803  
 804    if (pdev->pClass[0] != NULL)
 805    {
 806      if (pdev->pClass[0]->DeInit != NULL)
 807      {
 808        if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
 809        {
 810          ret = USBD_FAIL;
 811        }
 812      }
 813    }
 814  #endif /* USE_USBD_COMPOSITE */
 815  
 816    /* Open EP0 OUT */
 817    (void)USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
 818    pdev->ep_out[0x00U & 0xFU].is_used = 1U;
 819  
 820    pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
 821  
 822    /* Open EP0 IN */
 823    (void)USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
 824    pdev->ep_in[0x80U & 0xFU].is_used = 1U;
 825  
 826    pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
 827  
 828    return ret;
 829  }
 830  
 831  /**
 832    * @brief  USBD_LL_SetSpeed
 833    *         Handle Reset event
 834    * @param  pdev: device instance
 835    * @retval status
 836    */
 837  USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev,
 838                                      USBD_SpeedTypeDef speed)
 839  {
 840    pdev->dev_speed = speed;
 841  
 842    return USBD_OK;
 843  }
 844  
 845  /**
 846    * @brief  USBD_LL_Suspend
 847    *         Handle Suspend event
 848    * @param  pdev: device instance
 849    * @retval status
 850    */
 851  
 852  USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
 853  {
 854    if (pdev->dev_state != USBD_STATE_SUSPENDED)
 855    {
 856      pdev->dev_old_state = pdev->dev_state;
 857    }
 858  
 859    pdev->dev_state = USBD_STATE_SUSPENDED;
 860  
 861    return USBD_OK;
 862  }
 863  
 864  /**
 865    * @brief  USBD_LL_Resume
 866    *         Handle Resume event
 867    * @param  pdev: device instance
 868    * @retval status
 869    */
 870  
 871  USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
 872  {
 873    if (pdev->dev_state == USBD_STATE_SUSPENDED)
 874    {
 875      pdev->dev_state = pdev->dev_old_state;
 876    }
 877  
 878    return USBD_OK;
 879  }
 880  
 881  /**
 882    * @brief  USBD_LL_SOF
 883    *         Handle SOF event
 884    * @param  pdev: device instance
 885    * @retval status
 886    */
 887  
 888  USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
 889  {
 890    /* The SOF event can be distributed for all classes that support it */
 891    if (pdev->dev_state == USBD_STATE_CONFIGURED)
 892    {
 893  #ifdef USE_USBD_COMPOSITE
 894      /* Parse the table of classes in use */
 895      for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
 896      {
 897        /* Check if current class is in use */
 898        if ((pdev->tclasslist[i].Active) == 1U)
 899        {
 900          if (pdev->pClass[i] != NULL)
 901          {
 902            if (pdev->pClass[i]->SOF != NULL)
 903            {
 904              pdev->classId = i;
 905              (void)pdev->pClass[i]->SOF(pdev);
 906            }
 907          }
 908        }
 909      }
 910  #else
 911      if (pdev->pClass[0] != NULL)
 912      {
 913        if (pdev->pClass[0]->SOF != NULL)
 914        {
 915          (void)pdev->pClass[0]->SOF(pdev);
 916        }
 917      }
 918  #endif /* USE_USBD_COMPOSITE */
 919    }
 920  
 921    return USBD_OK;
 922  }
 923  
 924  /**
 925    * @brief  USBD_LL_IsoINIncomplete
 926    *         Handle iso in incomplete event
 927    * @param  pdev: device instance
 928    * @retval status
 929    */
 930  USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev,
 931                                             uint8_t epnum)
 932  {
 933    if (pdev->pClass[pdev->classId] == NULL)
 934    {
 935      return USBD_FAIL;
 936    }
 937  
 938    if (pdev->dev_state == USBD_STATE_CONFIGURED)
 939    {
 940      if (pdev->pClass[pdev->classId]->IsoINIncomplete != NULL)
 941      {
 942        (void)pdev->pClass[pdev->classId]->IsoINIncomplete(pdev, epnum);
 943      }
 944    }
 945  
 946    return USBD_OK;
 947  }
 948  
 949  /**
 950    * @brief  USBD_LL_IsoOUTIncomplete
 951    *         Handle iso out incomplete event
 952    * @param  pdev: device instance
 953    * @retval status
 954    */
 955  USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev,
 956                                              uint8_t epnum)
 957  {
 958    if (pdev->pClass[pdev->classId] == NULL)
 959    {
 960      return USBD_FAIL;
 961    }
 962  
 963    if (pdev->dev_state == USBD_STATE_CONFIGURED)
 964    {
 965      if (pdev->pClass[pdev->classId]->IsoOUTIncomplete != NULL)
 966      {
 967        (void)pdev->pClass[pdev->classId]->IsoOUTIncomplete(pdev, epnum);
 968      }
 969    }
 970  
 971    return USBD_OK;
 972  }
 973  
 974  /**
 975    * @brief  USBD_LL_DevConnected
 976    *         Handle device connection event
 977    * @param  pdev: device instance
 978    * @retval status
 979    */
 980  USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
 981  {
 982    /* Prevent unused argument compilation warning */
 983    UNUSED(pdev);
 984  
 985    return USBD_OK;
 986  }
 987  
 988  /**
 989    * @brief  USBD_LL_DevDisconnected
 990    *         Handle device disconnection event
 991    * @param  pdev: device instance
 992    * @retval status
 993    */
 994  USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
 995  {
 996    USBD_StatusTypeDef   ret = USBD_OK;
 997  
 998    /* Free Class Resources */
 999    pdev->dev_state = USBD_STATE_DEFAULT;
1000  
1001  #ifdef USE_USBD_COMPOSITE
1002    /* Parse the table of classes in use */
1003    for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
1004    {
1005      /* Check if current class is in use */
1006      if ((pdev->tclasslist[i].Active) == 1U)
1007      {
1008        if (pdev->pClass[i] != NULL)
1009        {
1010          pdev->classId = i;
1011          /* Clear configuration  and De-initialize the Class process*/
1012          if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
1013          {
1014            ret = USBD_FAIL;
1015          }
1016        }
1017      }
1018    }
1019  #else
1020    if (pdev->pClass[0] != NULL)
1021    {
1022      if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
1023      {
1024        ret = USBD_FAIL;
1025      }
1026    }
1027  #endif /* USE_USBD_COMPOSITE */
1028  
1029    return ret;
1030  }
1031  
1032  /**
1033    * @brief  USBD_CoreFindIF
1034    *         return the class index relative to the selected interface
1035    * @param  pdev: device instance
1036    * @param  index : selected interface number
1037    * @retval index of the class using the selected interface number. OxFF if no class found.
1038    */
1039  uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index)
1040  {
1041  #ifdef USE_USBD_COMPOSITE
1042    /* Parse the table of classes in use */
1043    for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
1044    {
1045      /* Check if current class is in use */
1046      if ((pdev->tclasslist[i].Active) == 1U)
1047      {
1048        /* Parse all interfaces listed in the current class */
1049        for (uint32_t j = 0U; j < pdev->tclasslist[i].NumIf; j++)
1050        {
1051          /* Check if requested Interface matches the current class interface */
1052          if (pdev->tclasslist[i].Ifs[j] == index)
1053          {
1054            if (pdev->pClass[i]->Setup != NULL)
1055            {
1056              return (uint8_t)i;
1057            }
1058          }
1059        }
1060      }
1061    }
1062  
1063    return 0xFFU;
1064  #else
1065    UNUSED(pdev);
1066    UNUSED(index);
1067  
1068    return 0x00U;
1069  #endif /* USE_USBD_COMPOSITE */
1070  }
1071  
1072  /**
1073    * @brief  USBD_CoreFindEP
1074    *         return the class index relative to the selected endpoint
1075    * @param  pdev: device instance
1076    * @param  index : selected endpoint number
1077    * @retval index of the class using the selected endpoint number. 0xFF if no class found.
1078    */
1079  uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index)
1080  {
1081  #ifdef USE_USBD_COMPOSITE
1082    /* Parse the table of classes in use */
1083    for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
1084    {
1085      /* Check if current class is in use */
1086      if ((pdev->tclasslist[i].Active) == 1U)
1087      {
1088        /* Parse all endpoints listed in the current class */
1089        for (uint32_t j = 0U; j < pdev->tclasslist[i].NumEps; j++)
1090        {
1091          /* Check if requested endpoint matches the current class endpoint */
1092          if (pdev->tclasslist[i].Eps[j].add == index)
1093          {
1094            if (pdev->pClass[i]->Setup != NULL)
1095            {
1096              return (uint8_t)i;
1097            }
1098          }
1099        }
1100      }
1101    }
1102  
1103    return 0xFFU;
1104  #else
1105    UNUSED(pdev);
1106    UNUSED(index);
1107  
1108    return 0x00U;
1109  #endif /* USE_USBD_COMPOSITE */
1110  }
1111  
1112  #ifdef USE_USBD_COMPOSITE
1113  /**
1114    * @brief  USBD_CoreGetEPAdd
1115    *         Get the endpoint address relative to a selected class
1116    * @param  pdev: device instance
1117    * @param  ep_dir: USBD_EP_IN or USBD_EP_OUT
1118    * @param  ep_type: USBD_EP_TYPE_CTRL, USBD_EP_TYPE_ISOC, USBD_EP_TYPE_BULK or USBD_EP_TYPE_INTR
1119    * @param  ClassId: The Class ID
1120    * @retval Address of the selected endpoint or 0xFFU if no endpoint found.
1121    */
1122  uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId)
1123  {
1124    uint8_t idx;
1125  
1126    /* Find the EP address in the selected class table */
1127    for (idx = 0; idx < pdev->tclasslist[ClassId].NumEps; idx++)
1128    {
1129      if (((pdev->tclasslist[ClassId].Eps[idx].add & USBD_EP_IN) == ep_dir) && \
1130          (pdev->tclasslist[ClassId].Eps[idx].type == ep_type) && \
1131          (pdev->tclasslist[ClassId].Eps[idx].is_used != 0U))
1132      {
1133        return (pdev->tclasslist[ClassId].Eps[idx].add);
1134      }
1135    }
1136  
1137    /* If reaching this point, then no endpoint was found */
1138    return 0xFFU;
1139  }
1140  #endif /* USE_USBD_COMPOSITE */
1141  
1142  /**
1143    * @brief  USBD_GetEpDesc
1144    *         This function return the Endpoint descriptor
1145    * @param  pdev: device instance
1146    * @param  pConfDesc:  pointer to Bos descriptor
1147    * @param  EpAddr:  endpoint address
1148    * @retval pointer to video endpoint descriptor
1149    */
1150  void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr)
1151  {
1152    USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
1153    USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
1154    USBD_EpDescTypeDef *pEpDesc = NULL;
1155    uint16_t ptr;
1156  
1157    if (desc->wTotalLength > desc->bLength)
1158    {
1159      ptr = desc->bLength;
1160  
1161      while (ptr < desc->wTotalLength)
1162      {
1163        pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
1164  
1165        if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
1166        {
1167          pEpDesc = (USBD_EpDescTypeDef *)(void *)pdesc;
1168  
1169          if (pEpDesc->bEndpointAddress == EpAddr)
1170          {
1171            break;
1172          }
1173          else
1174          {
1175            pEpDesc = NULL;
1176          }
1177        }
1178      }
1179    }
1180  
1181    return (void *)pEpDesc;
1182  }
1183  
1184  /**
1185    * @brief  USBD_GetNextDesc
1186    *         This function return the next descriptor header
1187    * @param  buf: Buffer where the descriptor is available
1188    * @param  ptr: data pointer inside the descriptor
1189    * @retval next header
1190    */
1191  USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr)
1192  {
1193    USBD_DescHeaderTypeDef *pnext = (USBD_DescHeaderTypeDef *)(void *)pbuf;
1194  
1195    *ptr += pnext->bLength;
1196    pnext = (USBD_DescHeaderTypeDef *)(void *)(pbuf + pnext->bLength);
1197  
1198    return (pnext);
1199  }
1200  
1201  /**
1202    * @}
1203    */
1204  
1205  
1206  /**
1207    * @}
1208    */
1209  
1210  
1211  /**
1212    * @}
1213    */
1214