1 /**
2   **************************************************************************
3   * @file     usbd_sdr.c
4   * @brief    usb standard device request
5   **************************************************************************
6   *                       Copyright notice & Disclaimer
7   *
8   * The software Board Support Package (BSP) that is made available to
9   * download from Artery official website is the copyrighted work of Artery.
10   * Artery authorizes customers to use, copy, and distribute the BSP
11   * software and its related documentation for the purpose of design and
12   * development in conjunction with Artery microcontrollers. Use of the
13   * software is governed by this copyright notice and the following disclaimer.
14   *
15   * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
16   * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
17   * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
18   * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
19   * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
21   *
22   **************************************************************************
23   */
24 #include "usbd_sdr.h"
25 
26 /** @defgroup USBD_drivers_standard_request
27   * @brief usb device standard_request
28   * @{
29   */
30 
31 /** @defgroup USBD_sdr_private_functions
32   * @{
33   */
34 
35 #ifdef USE_OTG_DEVICE_MODE
36 
37 static usb_sts_type usbd_get_descriptor(usbd_core_type *udev);
38 static usb_sts_type usbd_set_address(usbd_core_type *udev);
39 static usb_sts_type usbd_get_status(usbd_core_type *udev);
40 static usb_sts_type usbd_clear_feature(usbd_core_type *udev);
41 static usb_sts_type usbd_set_feature(usbd_core_type *udev);
42 static usb_sts_type usbd_get_configuration(usbd_core_type *udev);
43 static usb_sts_type usbd_set_configuration(usbd_core_type *udev);
44 
45 /**
46   * @brief  usb parse standard setup request
47   * @param  setup: setup structure
48   * @param  buf: setup buffer
49   * @retval none
50   */
usbd_setup_request_parse(usb_setup_type * setup,uint8_t * buf)51 void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf)
52 {
53   setup->bmRequestType         = *(uint8_t *) buf;
54   setup->bRequest              = *(uint8_t *) (buf + 1);
55   setup->wValue                = SWAPBYTE(buf + 2);
56   setup->wIndex                = SWAPBYTE(buf + 4);
57   setup->wLength               = SWAPBYTE(buf + 6);
58 }
59 
60 /**
61   * @brief  get usb standard device description request
62   * @param  udev: to the structure of usbd_core_type
63   * @retval status of usb_sts_type
64   */
usbd_get_descriptor(usbd_core_type * udev)65 static usb_sts_type usbd_get_descriptor(usbd_core_type *udev)
66 {
67   usb_sts_type ret = USB_OK;
68   uint16_t len = 0;
69   usbd_desc_t *desc = RT_NULL;
70   uint8_t desc_type = udev->setup.wValue >> 8;
71   switch(desc_type)
72   {
73     case USB_DESCIPTOR_TYPE_DEVICE:
74       desc = udev->desc_handler->get_device_descriptor();
75       break;
76     case USB_DESCIPTOR_TYPE_CONFIGURATION:
77       if(udev->speed == USB_HIGH_SPEED)
78       {
79         desc = udev->desc_handler->get_hs_device_configuration();
80       }
81       else
82       {
83         desc = udev->desc_handler->get_device_configuration();
84       }
85       break;
86     case USB_DESCIPTOR_TYPE_STRING:
87     {
88       uint8_t str_desc = (uint8_t)udev->setup.wValue;
89       switch(str_desc)
90       {
91         case USB_LANGID_STRING:
92           desc = udev->desc_handler->get_device_lang_id();
93           break;
94         case USB_MFC_STRING:
95           desc = udev->desc_handler->get_device_manufacturer_string();
96           break;
97         case USB_PRODUCT_STRING:
98           desc = udev->desc_handler->get_device_product_string();
99           break;
100         case USB_SERIAL_STRING:
101           desc = udev->desc_handler->get_device_serial_string();
102           break;
103         case USB_CONFIG_STRING:
104           desc = udev->desc_handler->get_device_config_string();
105           break;
106         case USB_INTERFACE_STRING:
107           desc = udev->desc_handler->get_device_interface_string();
108           break;
109         default:
110           udev->class_handler->setup_handler(udev, &udev->setup);
111           return ret;
112       }
113       break;
114     }
115     case USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER:
116       if(udev->speed == USB_HIGH_SPEED)
117       {
118         desc = udev->desc_handler->get_device_qualifier();
119       }
120       else
121       {
122         usbd_ctrl_unsupport(udev);
123       }
124       break;
125     case USB_DESCIPTOR_TYPE_OTHER_SPEED:
126       if(udev->speed == USB_HIGH_SPEED)
127       {
128         desc = udev->desc_handler->get_device_other_speed();
129 		desc->descriptor[1] = USB_DESCIPTOR_TYPE_OTHER_SPEED;
130       }
131       else
132       {
133         usbd_ctrl_unsupport(udev);
134       }
135       break;
136     default:
137       usbd_ctrl_unsupport(udev);
138       return ret;
139   }
140 
141   if(desc != RT_NULL)
142   {
143     if((desc->length != 0) && (udev->setup.wLength != 0))
144     {
145       len = MIN(desc->length , udev->setup.wLength);
146       usbd_ctrl_send(udev, desc->descriptor, len);
147     }
148   }
149   return ret;
150 }
151 
152 /**
153   * @brief  this request sets the device address
154   * @param  udev: to the structure of usbd_core_type
155   * @retval status of usb_sts_type
156   */
usbd_set_address(usbd_core_type * udev)157 static usb_sts_type usbd_set_address(usbd_core_type *udev)
158 {
159   usb_sts_type ret = USB_OK;
160   usb_setup_type *setup = &udev->setup;
161   uint8_t dev_addr;
162 
163   /* if wIndex or wLength are non-zero, then the behavior of
164      the device is not specified
165   */
166   if(setup->wIndex == 0 && setup->wLength == 0)
167   {
168     dev_addr = (uint8_t)(setup->wValue) & 0x7f;
169 
170     /* device behavior when this request is received
171        while the device is in the configured state is not specified.*/
172     if(udev->conn_state == USB_CONN_STATE_CONFIGURED )
173     {
174       usbd_ctrl_unsupport(udev);
175     }
176     else
177     {
178       udev->device_addr = dev_addr;
179       usbd_set_device_addr(udev, udev->device_addr);
180 
181       if(dev_addr != 0)
182       {
183         udev->conn_state = USB_CONN_STATE_ADDRESSED;
184       }
185       else
186       {
187         udev->conn_state = USB_CONN_STATE_DEFAULT;
188       }
189       usbd_ctrl_send_status(udev);
190     }
191   }
192   else
193   {
194     usbd_ctrl_unsupport(udev);
195   }
196   return ret;
197 }
198 
199 /**
200   * @brief  get usb status request
201   * @param  udev: to the structure of usbd_core_type
202   * @retval status of usb_sts_type
203   */
usbd_get_status(usbd_core_type * udev)204 static usb_sts_type usbd_get_status(usbd_core_type *udev)
205 {
206   usb_sts_type ret = USB_OK;
207   switch(udev->conn_state)
208   {
209     case USB_CONN_STATE_ADDRESSED:
210     case USB_CONN_STATE_CONFIGURED:
211       if(udev->remote_wakup)
212       {
213         udev->config_status |= USB_CONF_REMOTE_WAKEUP;
214       }
215       usbd_ctrl_send(udev, (uint8_t *)(&udev->config_status), 2);
216       break;
217     default:
218       usbd_ctrl_unsupport(udev);
219       break;
220   }
221   return ret;
222 }
223 
224 /**
225   * @brief  clear usb feature request
226   * @param  udev: to the structure of usbd_core_type
227   * @retval status of usb_sts_type
228   */
usbd_clear_feature(usbd_core_type * udev)229 static usb_sts_type usbd_clear_feature(usbd_core_type *udev)
230 {
231   usb_sts_type ret = USB_OK;
232   usb_setup_type *setup = &udev->setup;
233   switch(udev->conn_state)
234   {
235     case USB_CONN_STATE_ADDRESSED:
236     case USB_CONN_STATE_CONFIGURED:
237       if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
238       {
239         udev->remote_wakup = 0;
240         udev->config_status &= ~USB_CONF_REMOTE_WAKEUP;
241         udev->class_handler->setup_handler(udev, &udev->setup);
242         usbd_ctrl_send_status(udev);
243       }
244       break;
245     default:
246       usbd_ctrl_unsupport(udev);
247       break;
248   }
249   return ret;
250 }
251 
252 /**
253   * @brief  set usb feature request
254   * @param  udev: to the structure of usbd_core_type
255   * @retval status of usb_sts_type
256   */
usbd_set_feature(usbd_core_type * udev)257 static usb_sts_type usbd_set_feature(usbd_core_type *udev)
258 {
259   usb_sts_type ret = USB_OK;
260   usb_setup_type *setup = &udev->setup;
261   if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
262   {
263     udev->remote_wakup = 1;
264     udev->class_handler->setup_handler(udev, &udev->setup);
265     usbd_ctrl_send_status(udev);
266   }
267   else
268   {
269     usbd_ctrl_unsupport(udev);
270   }
271   return ret;
272 }
273 
274 /**
275   * @brief  get usb configuration request
276   * @param  udev: to the structure of usbd_core_type
277   * @retval status of usb_sts_type
278   */
usbd_get_configuration(usbd_core_type * udev)279 static usb_sts_type usbd_get_configuration(usbd_core_type *udev)
280 {
281   usb_sts_type ret = USB_OK;
282   usb_setup_type *setup = &udev->setup;
283   if(setup->wLength != 1)
284   {
285     usbd_ctrl_unsupport(udev);
286   }
287   else
288   {
289     switch(udev->conn_state)
290     {
291       case USB_CONN_STATE_ADDRESSED:
292         udev->default_config = 0;
293         usbd_ctrl_send(udev, (uint8_t *)(&udev->default_config), 1);
294         break;
295       case USB_CONN_STATE_CONFIGURED:
296         usbd_ctrl_send(udev, (uint8_t *)(&udev->dev_config), 1);
297         break;
298       default:
299         usbd_ctrl_unsupport(udev);
300         break;
301     }
302   }
303   return ret;
304 }
305 
306 /**
307   * @brief  sets the usb device configuration request
308   * @param  udev: to the structure of usbd_core_type
309   * @retval status of usb_sts_type
310   */
usbd_set_configuration(usbd_core_type * udev)311 static usb_sts_type usbd_set_configuration(usbd_core_type *udev)
312 {
313   usb_sts_type ret = USB_OK;
314   static uint8_t config_value;
315   usb_setup_type *setup = &udev->setup;
316   config_value = (uint8_t)setup->wValue;
317 
318   if(setup->wIndex == 0 && setup->wLength == 0)
319   {
320     switch(udev->conn_state)
321     {
322       case USB_CONN_STATE_ADDRESSED:
323         if(config_value)
324         {
325           udev->dev_config = config_value;
326           udev->conn_state = USB_CONN_STATE_CONFIGURED;
327           udev->class_handler->init_handler(udev);
328           usbd_ctrl_send_status(udev);
329         }
330         else
331         {
332           usbd_ctrl_send_status(udev);
333         }
334 
335         break;
336       case USB_CONN_STATE_CONFIGURED:
337         if(config_value == 0)
338         {
339           udev->conn_state = USB_CONN_STATE_ADDRESSED;
340           udev->dev_config = config_value;
341           udev->class_handler->clear_handler(udev);
342           usbd_ctrl_send_status(udev);
343         }
344         else if(config_value == udev->dev_config)
345         {
346           udev->class_handler->clear_handler(udev);
347           udev->dev_config = config_value;
348           udev->class_handler->init_handler(udev);
349           usbd_ctrl_send_status(udev);
350         }
351         else
352         {
353           usbd_ctrl_send_status(udev);
354         }
355         break;
356       default:
357         usbd_ctrl_unsupport(udev);
358         break;
359     }
360   }
361   else
362   {
363     usbd_ctrl_unsupport(udev);
364   }
365   return ret;
366 }
367 
368 /**
369   * @brief  standard usb device requests
370   * @param  udev: to the structure of usbd_core_type
371   * @retval status of usb_sts_type
372   */
usbd_device_request(usbd_core_type * udev)373 usb_sts_type usbd_device_request(usbd_core_type *udev)
374 {
375   usb_sts_type ret = USB_OK;
376   usb_setup_type *setup = &udev->setup;
377   if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) != USB_REQ_TYPE_STANDARD)
378   {
379     udev->class_handler->setup_handler(udev, &udev->setup);
380     return ret;
381   }
382   switch(udev->setup.bRequest)
383   {
384     case USB_STD_REQ_GET_STATUS:
385       usbd_get_status(udev);
386       break;
387     case USB_STD_REQ_CLEAR_FEATURE:
388       usbd_clear_feature(udev);
389       break;
390     case USB_STD_REQ_SET_FEATURE:
391       usbd_set_feature(udev);
392       break;
393     case USB_STD_REQ_SET_ADDRESS:
394       usbd_set_address(udev);
395       break;
396     case USB_STD_REQ_GET_DESCRIPTOR:
397       usbd_get_descriptor(udev);
398       break;
399     case USB_STD_REQ_GET_CONFIGURATION:
400       usbd_get_configuration(udev);
401       break;
402     case USB_STD_REQ_SET_CONFIGURATION:
403       usbd_set_configuration(udev);
404       break;
405     default:
406       usbd_ctrl_unsupport(udev);
407       break;
408   }
409   return ret;
410 }
411 
412 /**
413   * @brief  standard usb interface requests
414   * @param  udev: to the structure of usbd_core_type
415   * @retval status of usb_sts_type
416   */
usbd_interface_request(usbd_core_type * udev)417 usb_sts_type usbd_interface_request(usbd_core_type *udev)
418 {
419   usb_sts_type ret = USB_OK;
420   usb_setup_type *setup = &udev->setup;
421   switch(udev->conn_state)
422   {
423     case USB_CONN_STATE_DEFAULT:
424     case USB_CONN_STATE_ADDRESSED:
425     case USB_CONN_STATE_CONFIGURED:
426       ret = udev->class_handler->setup_handler(udev, &udev->setup);
427       if(setup->wLength == 0 && ret == USB_OK)
428       {
429         usbd_ctrl_send_status(udev);
430       }
431       break;
432     default:
433       usbd_ctrl_unsupport(udev);
434       break;
435   }
436   return ret;
437 }
438 
439 /**
440   * @brief  standard usb endpoint requests
441   * @param  udev: to the structure of usbd_core_type
442   * @retval status of usb_sts_type
443   */
usbd_endpoint_request(usbd_core_type * udev)444 usb_sts_type usbd_endpoint_request(usbd_core_type *udev)
445 {
446   usb_sts_type ret = USB_OK;
447   usb_setup_type *setup = &udev->setup;
448   uint8_t ept_addr = LBYTE(setup->wIndex);
449   usb_ept_info *ept_info;
450 
451   if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) != USB_REQ_TYPE_STANDARD)
452   {
453     udev->class_handler->setup_handler(udev, &udev->setup);
454     return ret;
455   }
456   switch(setup->bRequest)
457   {
458     case USB_STD_REQ_GET_STATUS:
459       switch(udev->conn_state)
460       {
461         case USB_CONN_STATE_ADDRESSED:
462           if((ept_addr & 0x7F) != 0)
463           {
464             usbd_set_stall(udev, ept_addr);
465           }
466           if((ept_addr & 0x80) != 0)
467           {
468            ept_info = &udev->ept_in[ept_addr & 0x7F];
469           }
470           else
471           {
472             ept_info = &udev->ept_out[ept_addr & 0x7F];
473           }
474           ept_info->status = 0x0000;
475           usbd_ctrl_send(udev, (uint8_t *)(&ept_info->status), 2);
476 
477           break;
478         case USB_CONN_STATE_CONFIGURED:
479         {
480           if((ept_addr & 0x80) != 0)
481           {
482            ept_info = &udev->ept_in[ept_addr & 0x7F];
483           }
484           else
485           {
486             ept_info = &udev->ept_out[ept_addr & 0x7F];
487           }
488           if(ept_info->stall == 1)
489           {
490             ept_info->status = 0x0001;
491           }
492           else
493           {
494             ept_info->status = 0x0000;
495           }
496           usbd_ctrl_send(udev, (uint8_t *)(&ept_info->status), 2);
497         }
498           break;
499         default:
500           usbd_ctrl_unsupport(udev);
501           break;
502       }
503       break;
504     case USB_STD_REQ_CLEAR_FEATURE:
505       switch(udev->conn_state)
506       {
507         case USB_CONN_STATE_ADDRESSED:
508           if((ept_addr != 0x00) && (ept_addr != 0x80))
509           {
510             usbd_set_stall(udev, ept_addr);
511           }
512           break;
513         case USB_CONN_STATE_CONFIGURED:
514           if(setup->wValue == USB_FEATURE_EPT_HALT)
515           {
516             if((ept_addr & 0x7F) != 0x00 )
517             {
518               usbd_clear_stall(udev, ept_addr);
519               udev->class_handler->setup_handler(udev, &udev->setup);
520             }
521             usbd_ctrl_send_status(udev);
522           }
523           break;
524         default:
525           usbd_ctrl_unsupport(udev);
526           break;
527       }
528       break;
529     case USB_STD_REQ_SET_FEATURE:
530       switch(udev->conn_state)
531       {
532         case USB_CONN_STATE_ADDRESSED:
533           if((ept_addr != 0x00) && (ept_addr != 0x80))
534           {
535             usbd_set_stall(udev, ept_addr);
536           }
537           break;
538         case USB_CONN_STATE_CONFIGURED:
539           if(setup->wValue == USB_FEATURE_EPT_HALT)
540           {
541             if((ept_addr != 0x00) && (ept_addr != 0x80))
542             {
543               usbd_set_stall(udev, ept_addr);
544             }
545           }
546           udev->class_handler->setup_handler(udev, &udev->setup);
547           usbd_ctrl_send_status(udev);
548           break;
549         default:
550           usbd_ctrl_unsupport(udev);
551           break;
552       }
553       break;
554     default:
555       usbd_ctrl_unsupport(udev);
556       break;
557   }
558   return ret;
559 }
560 
561 #endif
562 
563 /**
564   * @}
565   */
566 
567 /**
568   * @}
569   */
570 
571