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