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