1 /**
2 **************************************************************************
3 * @file usbh_ctrl.c
4 * @brief usb host control 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 "usbh_ctrl.h"
25 #include "usbh_core.h"
26 #include "usb_std.h"
27
28 #ifdef USE_OTG_HOST_MODE
29
30 /** @defgroup USBH_drivers_control
31 * @brief usb host drivers control
32 * @{
33 */
34
35 /** @defgroup USBH_ctrl_private_functions
36 * @{
37 */
38
39 /* control timeout 5s */
40 #define CTRL_TIMEOUT 10000
41
42 /**
43 * @brief usb host control send setup packet
44 * @param uhost: to the structure of usbh_core_type
45 * @param buffer: usb control setup send buffer
46 * @param hc_num: channel number
47 * @retval status: usb_sts_type status
48 */
usbh_ctrl_send_setup(usbh_core_type * uhost,uint8_t * buffer,uint8_t hc_num)49 usb_sts_type usbh_ctrl_send_setup(usbh_core_type *uhost, uint8_t *buffer, uint8_t hc_num)
50 {
51 uhost->hch[hc_num].dir = 0;
52 uhost->hch[hc_num].data_pid = HCH_PID_SETUP;
53 uhost->hch[hc_num].trans_buf = buffer;
54 uhost->hch[hc_num].trans_len = 8; /*setup */
55
56 return usbh_in_out_request(uhost, hc_num);
57 }
58
59 /**
60 * @brief usb host control receive data from device
61 * @param uhost: to the structure of usbh_core_type
62 * @param buffer: usb control receive data buffer
63 * @param length: usb control receive data length
64 * @param hc_num: channel number
65 * @retval status: usb_sts_type status
66 */
usbh_ctrl_recv_data(usbh_core_type * uhost,uint8_t * buffer,uint16_t length,uint16_t hc_num)67 usb_sts_type usbh_ctrl_recv_data(usbh_core_type *uhost, uint8_t *buffer,
68 uint16_t length, uint16_t hc_num)
69 {
70 uhost->hch[hc_num].dir = 1;
71 uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
72 uhost->hch[hc_num].trans_buf = buffer;
73 uhost->hch[hc_num].trans_len = length;
74
75 return usbh_in_out_request(uhost, hc_num);
76 }
77
78 /**
79 * @brief usb host control send data packet
80 * @param uhost: to the structure of usbh_core_type
81 * @param buffer: usb control send data buffer
82 * @param length: usb control send data length
83 * @param hc_num: channel number
84 * @retval status: usb_sts_type status
85 */
usbh_ctrl_send_data(usbh_core_type * uhost,uint8_t * buffer,uint16_t length,uint16_t hc_num)86 usb_sts_type usbh_ctrl_send_data(usbh_core_type *uhost, uint8_t *buffer,
87 uint16_t length, uint16_t hc_num)
88 {
89 uhost->hch[hc_num].dir = 0;
90 uhost->hch[hc_num].trans_buf = buffer;
91 uhost->hch[hc_num].trans_len = length;
92
93 if(length == 0)
94 {
95 uhost->hch[uhost->ctrl.hch_out].toggle_out = 1;
96 }
97 if(uhost->hch[uhost->ctrl.hch_out].toggle_out == 0)
98 {
99 uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
100 }
101 else
102 {
103 uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
104 }
105 return usbh_in_out_request(uhost, hc_num);
106 }
107
108 /**
109 * @brief usb host control setup request handler
110 * @param uhost: to the structure of usbh_core_type
111 * @retval status: usb_sts_type status
112 */
usbh_ctrl_setup_handler(usbh_core_type * uhost)113 usb_sts_type usbh_ctrl_setup_handler(usbh_core_type *uhost)
114 {
115 usbh_ctrl_send_setup(uhost, (uint8_t *)(&uhost->ctrl.setup),
116 uhost->ctrl.hch_out);
117 uhost->ctrl.state = CONTROL_SETUP_WAIT;
118 return USB_OK;
119 }
120
121 /**
122 * @brief usb host control setup request wait handler
123 * @param uhost: to the structure of usbh_core_type
124 * @param timeout: pointer of wait timeout
125 * @retval status: usb_sts_type status
126 */
usbh_ctrl_setup_wait_handler(usbh_core_type * uhost,uint32_t * timeout)127 usb_sts_type usbh_ctrl_setup_wait_handler(usbh_core_type *uhost, uint32_t *timeout)
128 {
129 urb_sts_type urb_state;
130 usb_sts_type status = USB_WAIT;
131 uint8_t dir;
132 urb_state = uhost->urb_state[uhost->ctrl.hch_out];
133 if(urb_state == URB_DONE)
134 {
135 dir = uhost->ctrl.setup.bmRequestType & USB_REQUEST_DIR_MASK;
136 if(uhost->ctrl.setup.wLength != 0)
137 {
138 *timeout = DATA_STAGE_TIMEOUT;
139 if(dir == USB_DIR_D2H) //in
140 {
141 uhost->ctrl.state = CONTROL_DATA_IN;
142 }
143 else //out
144 {
145 uhost->ctrl.state = CONTROL_DATA_OUT;
146 }
147 }
148 else
149 {
150 *timeout = NODATA_STAGE_TIMEOUT;
151 if(dir == USB_DIR_D2H) //no data, send status
152 {
153 uhost->ctrl.state = CONTROL_STATUS_OUT;
154 }
155 else //out
156 {
157 uhost->ctrl.state = CONTROL_STATUS_IN;
158 }
159 }
160 uhost->ctrl.timer = uhost->timer;
161 status = USB_OK;
162 }
163 else if(urb_state == URB_ERROR || urb_state == URB_NOTREADY)
164 {
165 uhost->ctrl.state = CONTROL_ERROR;
166 uhost->ctrl.sts = CTRL_XACTERR;
167 status = USB_ERROR;
168 }
169 else
170 {
171 /* wait nak timeout 5s*/
172 if(uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT)
173 {
174 uhost->ctrl.state = CONTROL_ERROR;
175 uhost->ctrl.sts = CTRL_XACTERR;
176 status = USB_ERROR;
177 }
178 }
179 return status;
180 }
181
182 /**
183 * @brief usb host control data in request handler
184 * @param uhost: to the structure of usbh_core_type
185 * @retval status: usb_sts_type status
186 */
usbh_ctrl_data_in_handler(usbh_core_type * uhost)187 usb_sts_type usbh_ctrl_data_in_handler(usbh_core_type *uhost)
188 {
189 usb_sts_type status = USB_OK;
190 usbh_ctrl_recv_data(uhost, uhost->ctrl.buffer,
191 uhost->ctrl.len,
192 uhost->ctrl.hch_in);
193 uhost->ctrl.state = CONTROL_DATA_IN_WAIT;
194
195 return status;
196 }
197
198 /**
199 * @brief usb host control data in wait handler
200 * @param uhost: to the structure of usbh_core_type
201 * @param timeout: wait timeout
202 * @retval status: usb_sts_type status
203 */
usbh_ctrl_data_in_wait_handler(usbh_core_type * uhost,uint32_t timeout)204 usb_sts_type usbh_ctrl_data_in_wait_handler(usbh_core_type *uhost, uint32_t timeout)
205 {
206 usb_sts_type status = USB_OK;
207 urb_sts_type urb_state;
208 urb_state = uhost->urb_state[uhost->ctrl.hch_in];
209
210 if(urb_state == URB_DONE)
211 {
212 uhost->ctrl.state = CONTROL_STATUS_OUT;
213 }
214 else if(urb_state == URB_STALL)
215 {
216 uhost->ctrl.state = CONTROL_STALL;
217 }
218 else if(urb_state == URB_ERROR)
219 {
220 uhost->ctrl.state = CONTROL_ERROR;
221 }
222 else
223 {
224 /* wait nak timeout 5s*/
225 if(uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT)
226 {
227 uhost->ctrl.state = CONTROL_ERROR;
228 uhost->ctrl.sts = CTRL_XACTERR;
229 status = USB_ERROR;
230 }
231
232 }
233 return status;
234 }
235
236 /**
237 * @brief usb host control data out request handler
238 * @param uhost: to the structure of usbh_core_type
239 * @retval status: usb_sts_type status
240 */
usbh_ctrl_data_out_handler(usbh_core_type * uhost)241 usb_sts_type usbh_ctrl_data_out_handler(usbh_core_type *uhost)
242 {
243 usb_sts_type status = USB_OK;
244 uhost->hch[uhost->ctrl.hch_out].toggle_out = 1;
245
246 usbh_ctrl_send_data(uhost, uhost->ctrl.buffer,
247 uhost->ctrl.len,
248 uhost->ctrl.hch_out);
249 uhost->ctrl.state = CONTROL_DATA_OUT_WAIT;
250
251 return status;
252 }
253
254 /**
255 * @brief usb host control data out wait handler
256 * @param uhost: to the structure of usbh_core_type
257 * @param timeout: wait timeout
258 * @retval status: usb_sts_type status
259 */
usbh_ctrl_data_out_wait_handler(usbh_core_type * uhost,uint32_t timeout)260 usb_sts_type usbh_ctrl_data_out_wait_handler(usbh_core_type *uhost, uint32_t timeout)
261 {
262 usb_sts_type status = USB_OK;
263 urb_sts_type urb_state;
264 urb_state = uhost->urb_state[uhost->ctrl.hch_out];
265 if(urb_state == URB_DONE)
266 {
267 uhost->ctrl.state = CONTROL_STATUS_IN;
268 }
269 else if(urb_state == URB_STALL)
270 {
271 uhost->ctrl.state = CONTROL_STALL;
272 }
273 else if(urb_state == URB_ERROR)
274 {
275 uhost->ctrl.state = CONTROL_ERROR;
276 }
277 else if(urb_state == URB_NOTREADY)
278 {
279 uhost->ctrl.state = CONTROL_DATA_OUT;
280 }
281
282 /* wait nak timeout 5s*/
283 if((uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT) && (urb_state == URB_NOTREADY))
284 {
285 uhost->ctrl.state = CONTROL_ERROR;
286 uhost->ctrl.sts = CTRL_XACTERR;
287 status = USB_ERROR;
288 }
289 return status;
290 }
291
292 /**
293 * @brief usb host control status data in handler
294 * @param uhost: to the structure of usbh_core_type
295 * @retval status: usb_sts_type status
296 */
usbh_ctrl_status_in_handler(usbh_core_type * uhost)297 usb_sts_type usbh_ctrl_status_in_handler(usbh_core_type *uhost)
298 {
299 usb_sts_type status = USB_OK;
300 usbh_ctrl_recv_data(uhost, 0, 0,
301 uhost->ctrl.hch_in);
302 uhost->ctrl.state = CONTROL_STATUS_IN_WAIT;
303
304
305 return status;
306 }
307
308 /**
309 * @brief usb host control status data in wait handler
310 * @param uhost: to the structure of usbh_core_type
311 * @param timeout: wait timeout
312 * @retval status: usb_sts_type status
313 */
usbh_ctrl_status_in_wait_handler(usbh_core_type * uhost,uint32_t timeout)314 usb_sts_type usbh_ctrl_status_in_wait_handler(usbh_core_type *uhost, uint32_t timeout)
315 {
316 usb_sts_type status = USB_OK;
317 urb_sts_type urb_state;
318 urb_state = uhost->urb_state[uhost->ctrl.hch_in];
319 if(urb_state == URB_DONE)
320 {
321 uhost->ctrl.state = CONTROL_COMPLETE;
322 }
323 else if(urb_state == URB_STALL)
324 {
325 uhost->ctrl.state = CONTROL_STALL;
326 status = USB_NOT_SUPPORT;
327 }
328 else if(urb_state == URB_ERROR)
329 {
330 uhost->ctrl.state = CONTROL_ERROR;
331 }
332 else
333 {
334 /* wait nak timeout 5s*/
335 if(uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT)
336 {
337 uhost->ctrl.state = CONTROL_ERROR;
338 uhost->ctrl.sts = CTRL_XACTERR;
339 status = USB_ERROR;
340 }
341 }
342 return status;
343 }
344
345 /**
346 * @brief usb host control status data out wait handler
347 * @param uhost: to the structure of usbh_core_type
348 * @retval status: usb_sts_type status
349 */
usbh_ctrl_status_out_handler(usbh_core_type * uhost)350 usb_sts_type usbh_ctrl_status_out_handler(usbh_core_type *uhost)
351 {
352 usb_sts_type status = USB_OK;
353 uhost->hch[uhost->ctrl.hch_out].toggle_out ^= 1;
354
355 usbh_ctrl_send_data(uhost, 0, 0, uhost->ctrl.hch_out);
356 uhost->ctrl.state = CONTROL_STATUS_OUT_WAIT;
357
358 return status;
359 }
360
361 /**
362 * @brief usb host control status data out wait handler
363 * @param uhost: to the structure of usbh_core_type
364 * @param timeout: wait timeout
365 * @retval status: usb_sts_type status
366 */
usbh_ctrl_status_out_wait_handler(usbh_core_type * uhost,uint32_t timeout)367 usb_sts_type usbh_ctrl_status_out_wait_handler(usbh_core_type *uhost, uint32_t timeout)
368 {
369 usb_sts_type status = USB_OK;
370 urb_sts_type urb_state;
371 urb_state = uhost->urb_state[uhost->ctrl.hch_out];
372 if(urb_state == URB_DONE)
373 {
374 uhost->ctrl.state = CONTROL_COMPLETE;
375 }
376 else if(urb_state == URB_STALL)
377 {
378 uhost->ctrl.state = CONTROL_STALL;
379 }
380 else if(urb_state == URB_ERROR)
381 {
382 uhost->ctrl.state = CONTROL_ERROR;
383 }
384 else if(urb_state == URB_NOTREADY)
385 {
386 uhost->ctrl.state = CONTROL_STATUS_OUT;
387 }
388 /* wait nak timeout 5s*/
389 if((uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT) && (urb_state == URB_NOTREADY))
390 {
391 uhost->ctrl.state = CONTROL_ERROR;
392 uhost->ctrl.sts = CTRL_XACTERR;
393 status = USB_ERROR;
394 }
395 return status;
396 }
397
398 /**
399 * @brief usb host control error handler
400 * @param uhost: to the structure of usbh_core_type
401 * @retval status: usb_sts_type status
402 */
usbh_ctrl_error_handler(usbh_core_type * uhost)403 usb_sts_type usbh_ctrl_error_handler(usbh_core_type *uhost)
404 {
405 usb_sts_type status = USB_WAIT;
406 if(++ uhost->ctrl.err_cnt <= USBH_MAX_ERROR_COUNT)
407 {
408 uhost->ctrl.state = CONTROL_SETUP;
409 }
410 else
411 {
412 uhost->ctrl.sts = CTRL_FAIL;
413 uhost->global_state = USBH_ERROR_STATE;
414 uhost->ctrl.err_cnt = 0;
415 status = USB_ERROR;
416 }
417 return status;
418 }
419
420 /**
421 * @brief usb host control stall handler
422 * @param uhost: to the structure of usbh_core_type
423 * @retval usb_sts_type
424 */
usbh_ctrl_stall_handler(usbh_core_type * uhost)425 usb_sts_type usbh_ctrl_stall_handler(usbh_core_type *uhost)
426 {
427 return USB_NOT_SUPPORT;
428 }
429
430 /**
431 * @brief usb host control complete handler
432 * @param uhost: to the structure of usbh_core_type
433 * @retval status: usb_sts_type status
434 */
usbh_ctrl_complete_handler(usbh_core_type * uhost)435 usb_sts_type usbh_ctrl_complete_handler(usbh_core_type *uhost)
436 {
437 return USB_OK;
438 }
439
440 /**
441 * @brief usb host control transfer loop function
442 * @param uhost: to the structure of usbh_core_type
443 * @retval status: usb_sts_type status
444 */
usbh_ctrl_transfer_loop(usbh_core_type * uhost)445 usb_sts_type usbh_ctrl_transfer_loop(usbh_core_type *uhost)
446 {
447 usb_sts_type status = USB_WAIT;
448 static uint32_t timeout = 0;
449 uhost->ctrl.sts = CTRL_START;
450
451 switch(uhost->ctrl.state)
452 {
453 case CONTROL_SETUP:
454 usbh_ctrl_setup_handler(uhost);
455 uhost->ctrl.timer = uhost->timer;
456 break;
457
458 case CONTROL_SETUP_WAIT:
459 usbh_ctrl_setup_wait_handler(uhost, &timeout);
460 break;
461
462 case CONTROL_DATA_IN:
463 usbh_ctrl_data_in_handler(uhost);
464 break;
465
466 case CONTROL_DATA_IN_WAIT:
467 usbh_ctrl_data_in_wait_handler(uhost, timeout);
468 break;
469
470 case CONTROL_DATA_OUT:
471 usbh_ctrl_data_out_handler(uhost);
472 break;
473
474 case CONTROL_DATA_OUT_WAIT:
475 usbh_ctrl_data_out_wait_handler(uhost, timeout);
476 break;
477
478 case CONTROL_STATUS_IN:
479 usbh_ctrl_status_in_handler(uhost);
480 break;
481
482 case CONTROL_STATUS_IN_WAIT:
483 usbh_ctrl_status_in_wait_handler(uhost, timeout);
484 break;
485
486 case CONTROL_STATUS_OUT:
487 usbh_ctrl_status_out_handler(uhost);
488 break;
489
490 case CONTROL_STATUS_OUT_WAIT:
491 usbh_ctrl_status_out_wait_handler(uhost, timeout);
492 break;
493 case CONTROL_STALL:
494 status = usbh_ctrl_stall_handler(uhost);
495 break;
496 case CONTROL_ERROR:
497 status = usbh_ctrl_error_handler(uhost);
498 break;
499 case CONTROL_COMPLETE:
500 status = usbh_ctrl_complete_handler(uhost);
501 break;
502
503 default:
504 break;
505 }
506
507 return status;
508 }
509
510 /**
511 * @brief usb host control request
512 * @param uhost: to the structure of usbh_core_type
513 * @param buffer: usb request buffer
514 * @param length: usb request length
515 * @retval status: usb_sts_type status
516 */
usbh_ctrl_request(usbh_core_type * uhost,uint8_t * buffer,uint16_t length)517 usb_sts_type usbh_ctrl_request(usbh_core_type *uhost, uint8_t *buffer, uint16_t length)
518 {
519 usb_sts_type status = USB_OK;
520 if(uhost->req_state == CMD_SEND)
521 {
522 uhost->req_state = CMD_WAIT;
523 uhost->ctrl.buffer = buffer;
524 uhost->ctrl.len = length;
525 uhost->ctrl.state = CONTROL_SETUP;
526 }
527 return status;
528 }
529
530 /**
531 * @brief usb host get device descriptor
532 * @param uhost: to the structure of usbh_core_type
533 * @param length: get descriptor request length
534 * @param req_type: usb request type
535 * @param wvalue: usb wvalue
536 * @param buffer: request buffer
537 * @retval status: usb_sts_type status
538 */
usbh_get_descriptor(usbh_core_type * uhost,uint16_t length,uint8_t req_type,uint16_t wvalue,uint8_t * buffer)539 usb_sts_type usbh_get_descriptor(usbh_core_type *uhost, uint16_t length,
540 uint8_t req_type, uint16_t wvalue,
541 uint8_t *buffer)
542 {
543 usb_sts_type status;
544 uhost->ctrl.setup.bmRequestType = USB_DIR_D2H | req_type;
545 uhost->ctrl.setup.bRequest = USB_STD_REQ_GET_DESCRIPTOR;
546 uhost->ctrl.setup.wValue = wvalue;
547 uhost->ctrl.setup.wLength = length;
548
549 if((wvalue & 0xFF00) == ((USB_DESCIPTOR_TYPE_STRING << 8) & 0xFF00))
550 {
551 uhost->ctrl.setup.wIndex = 0x0409;
552 }
553 else
554 {
555 uhost->ctrl.setup.wIndex = 0;
556 }
557
558 status = usbh_ctrl_request(uhost, buffer, length);
559 return status;
560 }
561
562 /**
563 * @brief usb host parse device descriptor
564 * @param uhost: to the structure of usbh_core_type
565 * @param buffer: usb device descriptor buffer
566 * @param length: usb device descriptor length
567 * @retval status: usb_sts_type status
568 */
usbh_parse_dev_desc(usbh_core_type * uhost,uint8_t * buffer,uint16_t length)569 void usbh_parse_dev_desc(usbh_core_type *uhost, uint8_t *buffer, uint16_t length)
570 {
571 usbh_dev_desc_type *desc = &(uhost->dev);
572
573 desc->dev_desc.bLength = *(uint8_t *)(buffer + 0);
574 desc->dev_desc.bDescriptorType = *(uint8_t *)(buffer + 1);
575 desc->dev_desc.bcdUSB = SWAPBYTE(buffer + 2);
576 desc->dev_desc.bDeviceClass = *(uint8_t *)(buffer + 4);
577 desc->dev_desc.bDeviceSubClass = *(uint8_t *)(buffer + 5);
578 desc->dev_desc.bDeviceProtocol = *(uint8_t *)(buffer + 6);
579 desc->dev_desc.bMaxPacketSize0 = *(uint8_t *)(buffer + 7);
580
581 if(length > 8)
582 {
583 desc->dev_desc.idVendor = SWAPBYTE(buffer + 8);
584 desc->dev_desc.idProduct = SWAPBYTE(buffer + 10);
585 desc->dev_desc.bcdDevice = SWAPBYTE(buffer + 12);
586 desc->dev_desc.iManufacturer = *(uint8_t *)(buffer + 14);
587 desc->dev_desc.iProduct = *(uint8_t *)(buffer + 15);
588 desc->dev_desc.iSerialNumber = *(uint8_t *)(buffer + 16);
589 desc->dev_desc.bNumConfigurations = *(uint8_t *)(buffer + 17);
590 }
591 }
592
593 /**
594 * @brief usb host get next header
595 * @param buffer: usb data buffer
596 * @param index_len: pointer of index len
597 * @retval status: usb_sts_type status
598 */
usbh_get_next_header(uint8_t * buf,uint16_t * index_len)599 usb_header_desc_type *usbh_get_next_header(uint8_t *buf, uint16_t *index_len)
600 {
601 *index_len += ((usb_header_desc_type *)buf)->bLength;
602 return (usb_header_desc_type *)
603 ((uint8_t *)buf + ((usb_header_desc_type *)buf)->bLength);
604 }
605
606 /**
607 * @brief usb host parse interface descriptor
608 * @param intf: usb interface description type
609 * @param buf: interface description data buffer
610 * @retval none
611 */
usbh_parse_interface_desc(usb_interface_desc_type * intf,uint8_t * buf)612 void usbh_parse_interface_desc(usb_interface_desc_type *intf, uint8_t *buf)
613 {
614 intf->bLength = *(uint8_t *)buf;
615 intf->bDescriptorType = *(uint8_t *)(buf + 1);
616 intf->bInterfaceNumber = *(uint8_t *)(buf + 2);
617 intf->bAlternateSetting = *(uint8_t *)(buf + 3);
618 intf->bNumEndpoints = *(uint8_t *)(buf + 4);
619 intf->bInterfaceClass = *(uint8_t *)(buf + 5);
620 intf->bInterfaceSubClass = *(uint8_t *)(buf + 6);
621 intf->bInterfaceProtocol = *(uint8_t *)(buf + 7);
622 intf->iInterface = *(uint8_t *)(buf + 8);
623 }
624
625 /**
626 * @brief usb host parse endpoint descriptor
627 * @param ept_desc: endpoint type
628 * @param buf: endpoint description data buffer
629 * @retval none
630 */
usbh_parse_endpoint_desc(usb_endpoint_desc_type * ept_desc,uint8_t * buf)631 void usbh_parse_endpoint_desc(usb_endpoint_desc_type *ept_desc, uint8_t *buf)
632 {
633 ept_desc->bLength = *(uint8_t *)(buf + 0);
634 ept_desc->bDescriptorType = *(uint8_t *)(buf + 1);
635 ept_desc->bEndpointAddress = *(uint8_t *)(buf + 2);
636 ept_desc->bmAttributes = *(uint8_t *)(buf + 3);
637 ept_desc->wMaxPacketSize = SWAPBYTE(buf + 4);
638 ept_desc->bInterval = *(uint8_t *)(buf + 6);
639 }
640
641 /**
642 * @brief usb host parse configure descriptor
643 * @param uhost: to the structure of usbh_core_type
644 * @param buffer: configure buffer
645 * @param length: configure length
646 * @retval status: usb_sts_type status
647 */
usbh_parse_configure_desc(usbh_core_type * uhost,uint8_t * buffer,uint16_t length)648 usb_sts_type usbh_parse_configure_desc(usbh_core_type *uhost,
649 uint8_t *buffer, uint16_t length)
650 {
651 usb_cfg_desc_type *cfg_desc = &(uhost->dev.cfg_desc);
652 usb_interface_desc_type *intf_desc;
653 usb_endpoint_desc_type *ept_desc;
654 usb_header_desc_type *desc;
655 uint16_t index_len;
656 uint8_t index_intf = 0;
657 uint8_t index_ept = 0;
658
659 desc = (usb_header_desc_type *)buffer;
660 cfg_desc->cfg.bLength = *(uint8_t *)buffer;
661 cfg_desc->cfg.bDescriptorType = *(uint8_t *)(buffer + 1);
662 cfg_desc->cfg.wTotalLength = SWAPBYTE(buffer + 2);
663 cfg_desc->cfg.bNumInterfaces = *(uint8_t *)(buffer + 4);
664 cfg_desc->cfg.bConfigurationValue = *(uint8_t *)(buffer + 5);
665 cfg_desc->cfg.iConfiguration = *(uint8_t *)(buffer + 6);
666 cfg_desc->cfg.bmAttributes = *(uint8_t *)(buffer + 7);
667 cfg_desc->cfg.bMaxPower = *(uint8_t *)(buffer + 8);
668
669 if(length > USB_DEVICE_CFG_DESC_LEN)
670 {
671 index_len = USB_DEVICE_CFG_DESC_LEN;
672
673 while((index_intf < USBH_MAX_INTERFACE) && index_len < cfg_desc->cfg.wTotalLength)
674 {
675 desc = usbh_get_next_header((uint8_t *)desc, &index_len);
676 if(desc->bDescriptorType == USB_DESCIPTOR_TYPE_INTERFACE)
677 {
678 index_ept = 0;
679 intf_desc = &cfg_desc->interface[index_intf].interface;
680 usbh_parse_interface_desc(intf_desc, (uint8_t *)desc);
681
682 while(index_ept < intf_desc->bNumEndpoints && index_len < cfg_desc->cfg.wTotalLength)
683 {
684 desc = usbh_get_next_header((uint8_t *)desc, &index_len);
685 if(desc->bDescriptorType == USB_DESCIPTOR_TYPE_ENDPOINT)
686 {
687 ept_desc = &(cfg_desc->interface[index_intf].endpoint[index_ept]);
688 usbh_parse_endpoint_desc(ept_desc, (uint8_t *)desc);
689 index_ept ++;
690 }
691 }
692 index_intf ++;
693 }
694 }
695 }
696 return USB_OK;
697 }
698
699 /**
700 * @brief usb host find interface
701 * @param uhost: to the structure of usbh_core_type
702 * @param class_code: class code
703 * @param sub_class: subclass code
704 * @param protocol: prtocol code
705 * @retval idx: interface index
706 */
usbh_find_interface(usbh_core_type * uhost,uint8_t class_code,uint8_t sub_class,uint8_t protocol)707 uint8_t usbh_find_interface(usbh_core_type *uhost, uint8_t class_code, uint8_t sub_class, uint8_t protocol)
708 {
709 uint8_t idx = 0;
710 usb_itf_desc_type *usbitf;
711 for(idx = 0; idx < uhost->dev.cfg_desc.cfg.bNumInterfaces; idx ++)
712 {
713 usbitf = &uhost->dev.cfg_desc.interface[idx];
714 if(((usbitf->interface.bInterfaceClass == class_code) || (class_code == 0xFF)) &&
715 ((usbitf->interface.bInterfaceSubClass == sub_class) || (sub_class == 0xFF)) &&
716 ((usbitf->interface.bInterfaceProtocol == protocol) || (protocol == 0xFF))
717 )
718 {
719 return idx;
720 }
721 }
722 return 0xFF;
723 }
724
725 /**
726 * @brief usbh parse string descriptor
727 * @param src: string source pointer
728 * @param dest: string destination pointer
729 * @param length: string length
730 * @retval none
731 */
usbh_parse_string_desc(uint8_t * src,uint8_t * dest,uint16_t length)732 void usbh_parse_string_desc(uint8_t *src, uint8_t *dest, uint16_t length)
733 {
734 uint16_t len;
735 uint16_t i_index;
736
737 if(src[1] == USB_DESCIPTOR_TYPE_STRING)
738 {
739 len = ((src[0] - 2) <= length ? (src[0] - 2) : length);
740 src += 2;
741 for(i_index = 0; i_index < len; i_index += 2)
742 {
743 *dest = src[i_index];
744 dest ++;
745 }
746 *dest = 0;
747 }
748 }
749
750 /**
751 * @brief usb host get device descriptor
752 * @param uhost: to the structure of usbh_core_type
753 * @param length: get device descriptor length
754 * @retval status: usb_sts_type status
755 */
usbh_get_device_descriptor(usbh_core_type * uhost,uint16_t length)756 usb_sts_type usbh_get_device_descriptor(usbh_core_type *uhost, uint16_t length)
757 {
758 usb_sts_type status = USB_WAIT;
759 uint8_t bm_req;
760 uint16_t wvalue;
761
762 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
763 wvalue = (USB_DESCIPTOR_TYPE_DEVICE << 8) & 0xFF00;
764
765 status = usbh_get_descriptor(uhost, length, bm_req,
766 wvalue, uhost->rx_buffer);
767 return status;
768 }
769
770 /**
771 * @brief usb host get configure descriptor
772 * @param uhost: to the structure of usbh_core_type
773 * @param length: get device configure length
774 * @retval status: usb_sts_type status
775 */
usbh_get_configure_descriptor(usbh_core_type * uhost,uint16_t length)776 usb_sts_type usbh_get_configure_descriptor(usbh_core_type *uhost, uint16_t length)
777 {
778 usb_sts_type status = USB_WAIT;
779 uint8_t bm_req;
780 uint16_t wvalue;
781
782 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
783 wvalue = (USB_DESCIPTOR_TYPE_CONFIGURATION << 8) & 0xFF00;
784
785 status = usbh_get_descriptor(uhost, length, bm_req,
786 wvalue, uhost->rx_buffer);
787
788 return status;
789 }
790
791 /**
792 * @brief usb host get string descriptor
793 * @param uhost: to the structure of usbh_core_type
794 * @param string_id: string id
795 * @param buffer: receive data buffer
796 * @param length: get device string length
797 * @retval status: usb_sts_type status
798 */
usbh_get_sting_descriptor(usbh_core_type * uhost,uint8_t string_id,uint8_t * buffer,uint16_t length)799 usb_sts_type usbh_get_sting_descriptor(usbh_core_type *uhost, uint8_t string_id,
800 uint8_t *buffer, uint16_t length)
801 {
802 usb_sts_type status = USB_WAIT;
803 uint8_t bm_req;
804 uint16_t wvalue;
805
806 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
807 wvalue = (USB_DESCIPTOR_TYPE_STRING << 8) | string_id;
808
809 status = usbh_get_descriptor(uhost, length, bm_req,
810 wvalue, uhost->rx_buffer);
811
812 return status;
813 }
814
815 /**
816 * @brief usb host set configurtion
817 * @param uhost: to the structure of usbh_core_type
818 * @param config: usb configuration
819 * @retval status: usb_sts_type status
820 */
usbh_set_configuration(usbh_core_type * uhost,uint16_t config)821 usb_sts_type usbh_set_configuration(usbh_core_type *uhost, uint16_t config)
822 {
823 usb_sts_type status = USB_WAIT;
824 uint8_t bm_req;
825 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
826
827 uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
828 uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_CONFIGURATION;
829 uhost->ctrl.setup.wValue = config;
830 uhost->ctrl.setup.wLength = 0;
831 uhost->ctrl.setup.wIndex = 0;
832 status = usbh_ctrl_request(uhost, 0, 0);
833 return status;
834 }
835
836 /**
837 * @brief usb host set device address
838 * @param uhost: to the structure of usbh_core_type
839 * @param address: device address
840 * @retval status: usb_sts_type status
841 */
usbh_set_address(usbh_core_type * uhost,uint8_t address)842 usb_sts_type usbh_set_address(usbh_core_type *uhost, uint8_t address)
843 {
844 usb_sts_type status = USB_WAIT;
845 uint8_t bm_req;
846 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
847
848 uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
849 uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_ADDRESS;
850 uhost->ctrl.setup.wValue = (uint16_t)address;
851 uhost->ctrl.setup.wLength = 0;
852 uhost->ctrl.setup.wIndex = 0;
853 status = usbh_ctrl_request(uhost, 0, 0);
854 return status;
855 }
856
857 /**
858 * @brief usb host set interface
859 * @param uhost: to the structure of usbh_core_type
860 * @param ept_num: endpoint number
861 * @param altsetting: alter setting
862 * @retval status: usb_sts_type status
863 */
usbh_set_interface(usbh_core_type * uhost,uint8_t ept_num,uint8_t altsetting)864 usb_sts_type usbh_set_interface(usbh_core_type *uhost, uint8_t ept_num, uint8_t altsetting)
865 {
866 usb_sts_type status = USB_WAIT;
867 uint8_t bm_req;
868 bm_req = USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD;
869
870 uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
871 uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_INTERFACE;
872 uhost->ctrl.setup.wValue = (uint16_t)altsetting;
873 uhost->ctrl.setup.wLength = 0;
874 uhost->ctrl.setup.wIndex = ept_num;
875 status = usbh_ctrl_request(uhost, 0, 0);
876 return status;
877 }
878
879 /**
880 * @brief usb host set feature
881 * @param uhost: to the structure of usbh_core_type
882 * @param feature: feature number
883 * @param index: index number
884 * @retval status: usb_sts_type status
885 */
usbh_set_feature(usbh_core_type * uhost,uint8_t feature,uint16_t index)886 usb_sts_type usbh_set_feature(usbh_core_type *uhost, uint8_t feature, uint16_t index)
887 {
888 usb_sts_type status = USB_WAIT;
889 uint8_t bm_req;
890 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
891
892 uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
893 uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_FEATURE;
894 uhost->ctrl.setup.wValue = (uint16_t)feature;
895 uhost->ctrl.setup.wLength = 0;
896 uhost->ctrl.setup.wIndex = index;
897 status = usbh_ctrl_request(uhost, 0, 0);
898 return status;
899 }
900
901
902 /**
903 * @brief usb host clear device feature
904 * @param uhost: to the structure of usbh_core_type
905 * @param feature: feature number
906 * @param index: index number
907 * @retval status: usb_sts_type status
908 */
usbh_clear_dev_feature(usbh_core_type * uhost,uint8_t feature,uint16_t index)909 usb_sts_type usbh_clear_dev_feature(usbh_core_type *uhost, uint8_t feature, uint16_t index)
910 {
911 usb_sts_type status = USB_WAIT;
912 uint8_t bm_req;
913 bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
914
915 uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
916 uhost->ctrl.setup.bRequest = USB_STD_REQ_CLEAR_FEATURE;
917 uhost->ctrl.setup.wValue = (uint16_t)feature;
918 uhost->ctrl.setup.wLength = 0;
919 uhost->ctrl.setup.wIndex = index;
920 status = usbh_ctrl_request(uhost, 0, 0);
921 return status;
922 }
923
924 /**
925 * @brief usb host clear endpoint feature
926 * @param uhost: to the structure of usbh_core_type
927 * @param ept_num: endpoint number
928 * @param hc_num: host channel number
929 * @retval status: usb_sts_type status
930 */
usbh_clear_ept_feature(usbh_core_type * uhost,uint8_t ept_num,uint8_t hc_num)931 usb_sts_type usbh_clear_ept_feature(usbh_core_type *uhost, uint8_t ept_num, uint8_t hc_num)
932 {
933 usb_sts_type status = USB_WAIT;
934 uint8_t bm_req;
935 if(uhost->ctrl.state == CONTROL_IDLE )
936 {
937 bm_req = USB_REQ_RECIPIENT_ENDPOINT | USB_REQ_TYPE_STANDARD;
938
939 uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
940 uhost->ctrl.setup.bRequest = USB_STD_REQ_CLEAR_FEATURE;
941 uhost->ctrl.setup.wValue = USB_FEATURE_EPT_HALT;
942 uhost->ctrl.setup.wLength = 0;
943 uhost->ctrl.setup.wIndex = ept_num;
944 usbh_ctrl_request(uhost, 0, 0);
945 }
946 if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
947 {
948 status = USB_OK;
949 }
950 return status;
951 }
952
953 /**
954 * @}
955 */
956
957 /**
958 * @}
959 */
960
961 #endif
962