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