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