Subversion Repositories DashDisplay

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/**
2
  ******************************************************************************
3
  * @file    usbd_req.c
4
  * @author  MCD Application Team
5
  * @version V2.4.1
6
  * @date    19-June-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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
 
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
 
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
  */
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
  */
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****/