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