1 /**
2 **************************************************************************
3 * @file usbd_core.c
4 * @brief usb driver
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
25 #include "usbd_core.h"
26 #include "usbd_sdr.h"
27 #include "usbd_int.h"
28
29 /** @defgroup USBD_drivers_core
30 * @brief usb device drivers core
31 * @{
32 */
33
34 /** @defgroup USBD_core_private_functions
35 * @{
36 */
37
38 #ifdef BSP_USING_USBD
39
40 /**
41 * @brief usb core in transfer complete handler
42 * @param udev: to the structure of usbd_core_type
43 * @param ept_addr: endpoint number
44 * @retval none
45 */
usbd_core_in_handler(usbd_core_type * udev,uint8_t ept_addr)46 void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_addr)
47 {
48 /* get endpoint info*/
49 usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F];
50
51 if(ept_addr == 0)
52 {
53 if(udev->ept0_sts == USB_EPT0_DATA_IN)
54 {
55 if(ept_info->rem0_len > ept_info->maxpacket)
56 {
57 ept_info->rem0_len -= ept_info->maxpacket;
58 usbd_ept_send(udev, 0, ept_info->trans_buf,
59 MIN(ept_info->rem0_len, ept_info->maxpacket));
60 }
61 /* endpoint 0 */
62 else if(ept_info->last_len == ept_info->maxpacket
63 && ept_info->ept0_slen >= ept_info->maxpacket
64 && ept_info->ept0_slen < udev->ept0_wlength)
65 {
66 ept_info->last_len = 0;
67 usbd_ept_send(udev, 0, 0, 0);
68 usbd_ept_recv(udev, ept_addr, 0, 0);
69 }
70 else
71 {
72
73 usbd_ctrl_recv_status(udev);
74
75 }
76 usbd_data_in_stage_callback(udev,0);
77 }
78 }
79 else if(udev->class_handler->in_handler != 0 &&
80 udev->conn_state == USB_CONN_STATE_CONFIGURED)
81 {
82 /* other user define endpoint */
83 usbd_data_in_stage_callback(udev,ept_addr);
84 }
85 }
86
87 /**
88 * @brief usb core out transfer complete handler
89 * @param udev: to the structure of usbd_core_type
90 * @param ept_addr: endpoint number
91 * @retval none
92 */
usbd_core_out_handler(usbd_core_type * udev,uint8_t ept_addr)93 void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_addr)
94 {
95 /* get endpoint info*/
96 usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F];
97
98 if(ept_addr == 0)
99 {
100 /* endpoint 0 */
101 if(udev->ept0_sts == USB_EPT0_DATA_OUT)
102 {
103 if(ept_info->rem0_len > ept_info->maxpacket)
104 {
105 ept_info->rem0_len -= ept_info->maxpacket;
106 usbd_ept_recv(udev, ept_addr, ept_info->trans_buf,
107 MIN(ept_info->rem0_len, ept_info->maxpacket));
108 }
109 else
110 {
111 usbd_ctrl_send_status(udev);
112 }
113
114 usbd_data_out_stage_callback(udev, 0);
115 }
116 }
117 else if(udev->class_handler->out_handler != 0 &&
118 udev->conn_state == USB_CONN_STATE_CONFIGURED)
119 {
120 /* other user define endpoint */
121 usbd_data_out_stage_callback(udev, ept_addr);
122 }
123 }
124
125 /**
126 * @brief usb core setup transfer complete handler
127 * @param udev: to the structure of usbd_core_type
128 * @param ept_addr: endpoint number
129 * @retval none
130 */
usbd_core_setup_handler(usbd_core_type * udev,uint8_t ept_num)131 void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num)
132 {
133 /* setup parse */
134 usbd_setup_request_parse(&udev->setup, udev->setup_buffer);
135
136 /* set ept0 status */
137 udev->ept0_sts = USB_EPT0_SETUP;
138 udev->ept0_wlength = udev->setup.wLength;
139
140 switch(udev->setup.bmRequestType & USB_REQ_RECIPIENT_MASK)
141 {
142 case USB_REQ_RECIPIENT_DEVICE:
143 /* recipient device request */
144 usbd_device_request(udev);
145 break;
146 case USB_REQ_RECIPIENT_INTERFACE:
147 /* recipient interface request */
148 usbd_interface_request(udev);
149 break;
150 case USB_REQ_RECIPIENT_ENDPOINT:
151 /* recipient endpoint request */
152 usbd_endpoint_request(udev);
153 break;
154 default:
155 break;
156 }
157 }
158
159 /**
160 * @brief usb control endpoint send data
161 * @param udev: to the structure of usbd_core_type
162 * @param ept_addr: endpoint number
163 * @param buffer: send data buffer
164 * @param len: send data length
165 * @retval none
166 */
usbd_ctrl_send(usbd_core_type * udev,uint8_t * buffer,uint16_t len)167 void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len)
168 {
169 usb_ept_info *ept_info = &udev->ept_in[0];
170
171 ept_info->ept0_slen = len;
172 ept_info->rem0_len = len;
173 udev->ept0_sts = USB_EPT0_DATA_IN;
174 }
175
176 /**
177 * @brief usb control endpoint receive data
178 * @param udev: to the structure of usbd_core_type
179 * @param ept_addr: endpoint number
180 * @param buffer: recv data buffer
181 * @param len: recv data length
182 * @retval none
183 */
usbd_ctrl_recv(usbd_core_type * udev,uint8_t * buffer,uint16_t len)184 void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len)
185 {
186 usb_ept_info *ept_info = &udev->ept_out[0];
187
188 ept_info->ept0_slen = len;
189 ept_info->rem0_len = len;
190 udev->ept0_sts = USB_EPT0_DATA_OUT;
191
192 usbd_ept_recv(udev, 0, buffer, len);
193 }
194
195 /**
196 * @brief usb control endpoint send in status
197 * @param udev: to the structure of usbd_core_type
198 * @retval none
199 */
usbd_ctrl_send_status(usbd_core_type * udev)200 void usbd_ctrl_send_status(usbd_core_type *udev)
201 {
202 udev->ept0_sts = USB_EPT0_STATUS_IN;
203
204 usbd_ept_send(udev, 0, 0, 0);
205 }
206
207 /**
208 * @brief usb control endpoint send out status
209 * @param udev: usb device core handler type
210 * @retval none
211 */
usbd_ctrl_recv_status(usbd_core_type * udev)212 void usbd_ctrl_recv_status(usbd_core_type *udev)
213 {
214 udev->ept0_sts = USB_EPT0_STATUS_OUT;
215
216 usbd_ept_recv(udev, 0, 0, 0);
217 }
218
219 /**
220 * @brief clear endpoint stall
221 * @param udev: to the structure of usbd_core_type
222 * @param ept_addr: endpoint number
223 * @retval none
224 */
usbd_clear_stall(usbd_core_type * udev,uint8_t ept_addr)225 void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr)
226 {
227 usb_ept_info *ept_info;
228
229 if(ept_addr & 0x80)
230 {
231 /* in endpoint */
232 ept_info = &udev->ept_in[ept_addr & 0x7F];
233 USB_SET_TXSTS(ept_info->eptn, USB_TX_VALID);
234 }
235 else
236 {
237 /* out endpoint */
238 ept_info = &udev->ept_out[ept_addr & 0x7F];
239 USB_SET_RXSTS(ept_info->eptn, USB_RX_VALID);
240 }
241 ept_info->stall = 0;
242 }
243
244 /**
245 * @brief usb set endpoint to stall.
246 * @param udev: to the structure of usbd_core_type
247 * @param ept_addr: endpoint number
248 * @retval none
249 */
usbd_set_stall(usbd_core_type * udev,uint8_t ept_addr)250 void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr)
251 {
252 usb_ept_info *ept_info;
253
254 if(ept_addr & 0x80)
255 {
256 /* in endpoint */
257 ept_info = &udev->ept_in[ept_addr & 0x7F];
258 USB_SET_TXSTS(ept_info->eptn, USB_TX_STALL);
259 }
260 else
261 {
262 /* out endpoint */
263 ept_info = &udev->ept_out[ept_addr & 0x7F];
264 USB_SET_RXSTS(ept_info->eptn, USB_RX_STALL)
265 }
266
267 ept_info->stall = 1;
268 }
269
270 /**
271 * @brief un-support device request
272 * @param udev: usb device core handler type
273 * @retval none
274 */
usbd_ctrl_unsupport(usbd_core_type * udev)275 void usbd_ctrl_unsupport(usbd_core_type *udev)
276 {
277 /* return stall status */
278 usbd_set_stall(udev, 0x00);
279 usbd_set_stall(udev, 0x80);
280 }
281
282 /**
283 * @brief usb endpoint send data
284 * @param udev: to the structure of usbd_core_type
285 * @param ept_addr: endpoint number
286 * @param buffer: send data buffer
287 * @param len: send data length
288 * @retval none
289 */
usbd_ept_send(usbd_core_type * udev,uint8_t ept_addr,uint8_t * buffer,uint16_t len)290 void usbd_ept_send(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len)
291 {
292 /* get endpoint info struct and register */
293 usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F];
294 uint16_t trs_len = 0;
295 usbd_type *usbx = udev->usb_reg;
296
297 /* set send data buffer and length */
298 ept_info->trans_buf = buffer;
299 ept_info->total_len = len;
300 ept_info->trans_len = 0;
301
302 if(ept_info->total_len > ept_info->maxpacket)
303 {
304 trs_len = ept_info->maxpacket;
305 ept_info->total_len -= trs_len;
306 }
307 else
308 {
309 trs_len = len;
310 ept_info->total_len = 0;
311 }
312
313 ept_info->last_len = trs_len;
314
315 if(ept_info->is_double_buffer == 0)
316 {
317 /* write data to endpoint buffer */
318 usb_write_packet(ept_info->trans_buf, ept_info->tx_addr, trs_len);
319
320 /* set send data length */
321 USB_SET_TXLEN((ept_addr & 0x7F), trs_len);
322 }
323 else
324 {
325 if(usbx->ept_bit[ept_addr & 0x7F].txdts)
326 {
327 USB_SET_EPT_DOUBLE_BUF1_LEN((ept_addr & 0x7F), trs_len, DATA_TRANS_IN);
328 usb_write_packet(ept_info->trans_buf, ept_info->rx_addr, trs_len);
329 }
330 else
331 {
332 USB_SET_EPT_DOUBLE_BUF0_LEN((ept_addr & 0x7F), trs_len, DATA_TRANS_IN);
333 usb_write_packet(ept_info->trans_buf, ept_info->tx_addr, trs_len);
334 }
335 USB_FREE_DB_USER_BUFFER((ept_addr & 0x7F), DATA_TRANS_IN);
336 }
337
338 /* set tx status valid */
339 USB_SET_TXSTS((ept_addr & 0x7F), USB_TX_VALID);
340 }
341
342 /**
343 * @brief usb endpoint receive data
344 * @param udev: to the structure of usbd_core_type
345 * @param ept_addr: endpoint number
346 * @param buffer: receive data buffer
347 * @param len: receive data length
348 * @retval none
349 */
usbd_ept_recv(usbd_core_type * udev,uint8_t ept_addr,uint8_t * buffer,uint16_t len)350 void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len)
351 {
352 /* get endpoint info struct and register */
353 usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F];
354 uint32_t trs_len = 0;
355
356 /* set receive data buffer and length */
357 ept_info->trans_buf = buffer;
358 ept_info->total_len = len;
359 ept_info->trans_len = 0;
360
361 if(ept_info->total_len > ept_info->maxpacket)
362 {
363 trs_len = ept_info->maxpacket;
364 ept_info->total_len -= trs_len;
365 }
366 else
367 {
368 trs_len = len;
369 ept_info->total_len = 0;
370 }
371
372 /* set rx status valid */
373 USB_SET_RXSTS((ept_addr & 0x7F), USB_RX_VALID);
374 }
375
376
377 /**
378 * @brief usb endpoint get receive data length
379 * @param udev: to the structure of usbd_core_type
380 * @param ept_addr: endpoint number
381 * @retval none
382 */
usbd_get_recv_len(usbd_core_type * udev,uint8_t ept_addr)383 uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr)
384 {
385 usb_ept_info *ept = &udev->ept_out[ept_addr & 0x7F];
386 return ept->trans_len;
387 }
388
389 /**
390 * @brief enable endpoint double buffer.
391 * @param udev: to the structure of usbd_core_type
392 * @param ept_addr: endpoint number
393 * @retval none
394 */
usbd_ept_dbuffer_enable(usbd_core_type * udev,uint8_t ept_addr)395 void usbd_ept_dbuffer_enable(usbd_core_type *udev, uint8_t ept_addr)
396 {
397 usb_ept_info *ept_info;
398 if((ept_addr & 0x80) == 0)
399 {
400 /* out endpoint info */
401 ept_info = &udev->ept_out[ept_addr & 0x7F];
402 }
403 else
404 {
405 /* in endpoint info */
406 ept_info = &udev->ept_in[ept_addr & 0x7F];
407 }
408 ept_info->is_double_buffer = TRUE;
409 }
410
411 /**
412 * @brief usb auto define endpoint buffer
413 * @param usb_ept_info: endpoint information
414 * @retval none
415 */
usbd_ept_buf_auto_define(usb_ept_info * ept_info)416 void usbd_ept_buf_auto_define(usb_ept_info *ept_info)
417 {
418 if(ept_info->is_double_buffer == 0)
419 {
420 if( ept_info->inout == DATA_TRANS_IN )
421 {
422 if(ept_info->tx_addr == 0)
423 ept_info->tx_addr = usb_buffer_malloc(ept_info->maxpacket);
424 }
425 else
426 {
427 if(ept_info->rx_addr == 0)
428 ept_info->rx_addr = usb_buffer_malloc(ept_info->maxpacket);
429 }
430 }
431 else
432 {
433 /* double buffer auto define */
434 if(ept_info->tx_addr == 0)
435 ept_info->tx_addr = usb_buffer_malloc(ept_info->maxpacket);
436 if(ept_info->rx_addr == 0)
437 ept_info->rx_addr = usb_buffer_malloc(ept_info->maxpacket);
438 }
439 }
440
441
442
443 /**
444 * @brief usb custom define endpoint buffer
445 * @param udev: to the structure of usbd_core_type
446 * @param ept_addr: endpoint number
447 * @param addr: usb fifo offset address
448 * @retval none
449 */
usbd_ept_buf_custom_define(usbd_core_type * udev,uint8_t ept_addr,uint32_t addr)450 void usbd_ept_buf_custom_define(usbd_core_type *udev, uint8_t ept_addr,
451 uint32_t addr)
452 {
453 usb_ept_info *ept_info;
454 if((ept_addr & 0x80) == 0)
455 {
456 /* out endpoint info */
457 ept_info = &udev->ept_out[ept_addr & 0x7F];
458 }
459 else
460 {
461 /* in endpoint info */
462 ept_info = &udev->ept_in[ept_addr & 0x7F];
463 }
464
465 if(ept_info->is_double_buffer == 0)
466 {
467 if( ept_info->inout == DATA_TRANS_IN )
468 {
469 ept_info->tx_addr = addr;
470 }
471 else
472 {
473 ept_info->rx_addr = addr;
474 }
475 }
476 else
477 {
478 /* double buffer malloc */
479 ept_info->tx_addr = addr & 0xFFFF;
480 ept_info->rx_addr = (addr >> 16) & 0xFFFF;
481 }
482 }
483
484 /**
485 * @brief usb open endpoint
486 * @param udev: to the structure of usbd_core_type
487 * @param ept_addr: endpoint number
488 * @param ept_type: endpoint type
489 * @param maxpacket: endpoint support max buffer size
490 * @retval none
491 */
usbd_ept_open(usbd_core_type * udev,uint8_t ept_addr,uint8_t ept_type,uint16_t maxpacket)492 void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket)
493 {
494 usbd_type *usbx = udev->usb_reg;
495 usb_ept_info *ept_info;
496
497 if((ept_addr & 0x80) == 0)
498 {
499 /* out endpoint info */
500 ept_info = &udev->ept_out[ept_addr & 0x7F];
501 ept_info->inout = DATA_TRANS_OUT;
502 }
503 else
504 {
505 /* in endpoint info */
506 ept_info = &udev->ept_in[ept_addr & 0x7F];
507 ept_info->inout = DATA_TRANS_IN;
508 }
509
510 /* set endpoint maxpacket and type */
511 ept_info->maxpacket = (maxpacket + 1) & 0xFFFE;
512 ept_info->trans_type = ept_type;
513
514 #ifdef USB_EPT_AUTO_MALLOC_BUFFER
515 usbd_ept_buf_auto_define(ept_info);
516 #endif
517 /* open endpoint */
518 usb_ept_open(usbx, ept_info);
519 }
520
521 /**
522 * @brief usb close endpoint
523 * @param udev: to the structure of usbd_core_type
524 * @param ept_addr: endpoint number
525 * @retval none
526 */
usbd_ept_close(usbd_core_type * udev,uint8_t ept_addr)527 void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr)
528 {
529 usb_ept_info *ept_info;
530 if(ept_addr & 0x80)
531 {
532 /* in endpoint */
533 ept_info = &udev->ept_in[ept_addr & 0x7F];
534 }
535 else
536 {
537 /* out endpoint */
538 ept_info = &udev->ept_out[ept_addr & 0x7F];
539 }
540
541 /* close endpoint */
542 usb_ept_close(udev->usb_reg, ept_info);
543 }
544
545 /**
546 * @brief usb device connect to host
547 * @param udev: to the structure of usbd_core_type
548 * @retval none
549 */
usbd_connect(usbd_core_type * udev)550 void usbd_connect(usbd_core_type *udev)
551 {
552 usb_connect(udev->usb_reg);
553 }
554
555 /**
556 * @brief usb device disconnect to host
557 * @param udev: to the structure of usbd_core_type
558 * @retval none
559 */
usbd_disconnect(usbd_core_type * udev)560 void usbd_disconnect(usbd_core_type *udev)
561 {
562 usb_disconnect(udev->usb_reg);
563 }
564
565 /**
566 * @brief usb device set device address.
567 * @param udev: to the structure of usbd_core_type
568 * @param address: host assignment address
569 * @retval none
570 */
usbd_set_device_addr(usbd_core_type * udev,uint8_t address)571 void usbd_set_device_addr(usbd_core_type *udev, uint8_t address)
572 {
573 if(address == 0)
574 usb_set_address(udev->usb_reg, address);
575 }
576
577 /**
578 * @brief get usb connect state
579 * @param udev: to the structure of usbd_core_type
580 * @retval usb connect state
581 */
usbd_connect_state_get(usbd_core_type * udev)582 usbd_conn_state usbd_connect_state_get(usbd_core_type *udev)
583 {
584 return udev->conn_state;
585 }
586
587 /**
588 * @brief usb device remote wakeup
589 * @param udev: to the structure of usbd_core_type
590 * @retval none
591 */
usbd_remote_wakeup(usbd_core_type * udev)592 void usbd_remote_wakeup(usbd_core_type *udev)
593 {
594 /* set connect state */
595 udev->conn_state = udev->old_conn_state;
596
597 usb_exit_suspend(udev->usb_reg);
598
599 usb_remote_wkup_set(udev->usb_reg);
600
601 rt_thread_mdelay(10);
602
603 usb_remote_wkup_clear(udev->usb_reg);
604
605 }
606
607 /**
608 * @brief usb device enter suspend mode
609 * @param udev: to the structure of usbd_core_type
610 * @retval none
611 */
usbd_enter_suspend(usbd_core_type * udev)612 void usbd_enter_suspend(usbd_core_type *udev)
613 {
614 usb_enter_suspend(udev->usb_reg);
615 }
616
617 /**
618 * @brief usb endpoint structure initialization
619 * @param udev: to the structure of usbd_core_type
620 * @retval none
621 */
usbd_ept_defaut_init(usbd_core_type * udev)622 void usbd_ept_defaut_init(usbd_core_type *udev)
623 {
624 uint8_t i_index = 0;
625 /* init in endpoint info structure */
626 for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
627 {
628 udev->ept_in[i_index].eptn = i_index;
629 udev->ept_in[i_index].ept_address = i_index;
630 udev->ept_in[i_index].inout = DATA_TRANS_IN;
631 udev->ept_in[i_index].maxpacket = 0;
632 udev->ept_in[i_index].trans_buf = 0;
633 udev->ept_in[i_index].total_len = 0;
634 udev->ept_in[i_index].tx_addr = 0;
635 udev->ept_in[i_index].rx_addr = 0;
636 }
637
638 /* init out endpoint info structure */
639 for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
640 {
641 udev->ept_out[i_index].eptn = i_index;
642 udev->ept_out[i_index].ept_address = i_index;
643 udev->ept_out[i_index].inout = DATA_TRANS_OUT;
644 udev->ept_out[i_index].maxpacket = 0;
645 udev->ept_out[i_index].trans_buf = 0;
646 udev->ept_out[i_index].total_len = 0;
647 udev->ept_out[i_index].rx_addr = 0;
648 udev->ept_out[i_index].tx_addr = 0;
649 }
650 return;
651 }
652
653 /**
654 * @brief initializes the usb core
655 * @param udev: to the structure of usbd_core_type
656 * @param usb_reg: usb register pointer (USB)
657 * @param class_handler: usb class handler
658 * @param desc_handler: device config handler
659 * @param core_id: usb core id number
660 * @retval none
661 */
usbd_core_init(usbd_core_type * udev,usb_reg_type * usb_reg,uint8_t core_id)662 void usbd_core_init(usbd_core_type *udev,
663 usb_reg_type *usb_reg,
664 uint8_t core_id)
665 {
666 /* set usb register type */
667 udev->usb_reg = usb_reg;
668
669 /* set usb connect state to default */
670 udev->conn_state = USB_CONN_STATE_DEFAULT;
671
672 /* init in endpoint info structure */
673 usbd_ept_defaut_init(udev);
674
675 #ifdef USB_BUFFER_SIZE_EX
676 /* usb buffer size extend 768-1280 byte */
677 usb_usbbufs_enable(usb_reg, TRUE);
678 #endif
679
680 /*usb register config */
681 usb_dev_init(udev->usb_reg);
682 }
683
684 #endif
685
686 /**
687 * @}
688 */
689
690 /**
691 * @}
692 */
693
694