1 /******************************************************************************
2 ** File Name: DRV_usb.c *
3 ** Author: JiaYong.Yang *
5 ** Copyright: 2010 Spreatrum, Incoporated. All Rights Reserved. *
7 ******************************************************************************/
8 /**---------------------------------------------------------------------------*
10 **---------------------------------------------------------------------------*/
12 #include <asm/arch/common.h>
13 #include <asm/arch/usb200_fdl.h>
14 #include <asm/arch/drv_usb20.h>
15 #include <asm/arch/virtual_com.h>
16 #include <asm/arch/packet.h>
17 #include <asm/arch/usb20_reg_v3.h>
21 PUBLIC void Dcache_InvalRegion(unsigned int addr, unsigned int length);
22 PUBLIC void Dcache_CleanRegion(unsigned int addr, unsigned int length);
24 extern uint8 *UCOM_Get_DevDesc(void);
25 extern uint8 *UCOM_Get_CfgDesc(void);
27 static __inline void usb_handler (void);
28 /**---------------------------------------------------------------------------*
30 **---------------------------------------------------------------------------*/
31 #define MAX_RECV_LENGTH (64*64)//640*64 0xa000
32 #define USB_TIMEOUT (1000)
34 /**---------------------------------------------------------------------------*
36 **---------------------------------------------------------------------------*/
38 static int currentDmaBufferIndex = 0;
39 LOCAL __align(64) uint32 s_setup_packet[8] = {0};
40 LOCAL uint32 enum_speed = 0;
41 LOCAL uint32 recv_length = 0;
42 LOCAL uint32 nIndex = 0;
43 LOCAL uint32 readIndex = 0;
45 PUBLIC __align (64) unsigned char usb_out_endpoint_buf[2] [MAX_RECV_LENGTH];
50 /*****************************************************************************/
51 // Description: configure out endpoint0 to receive setup message.
52 // Global resource dependence:
53 // Author: jiayong.yang
55 /*****************************************************************************/
56 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
58 // Programs DOEPTSIZ0 register with Packet Count and Transfer Size
59 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_29|BIT_30); //setup packet count , 3 packet
60 * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_3|BIT_4); //set Transfer Size ,24 bytes
64 * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
67 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26; // set clear NAK
68 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
71 /*****************************************************************************/
72 // Description: configure in endpoint0 to send message.
73 // Global resource dependence:
74 // Author: jiayong.yang
76 /*****************************************************************************/
77 void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
79 volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
81 diep0tsiz_ptr->mBits.transfer_size = transfer_size;
82 diep0tsiz_ptr->mBits.packet_count = packet_count;
86 #if defined CONFIG_SC8810 || defined CONFIG_SC8825 || defined CONFIG_SC8830 || defined(CONFIG_SC9630)
87 Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
89 * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
92 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
94 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26; // clear NAK
96 * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31; // set endpoint enable
98 /*****************************************************************************/
99 // Description: usb reset interrupt handler.
100 // Global resource dependence:
101 // Author: jiayong.yang
103 /*****************************************************************************/
104 void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
106 if (dir) // out endpoint
108 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
109 * (volatile uint32 *) USB_DOEPMSK = (unsigned int) (BIT_13|BIT_12|BIT_3);
113 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_15; //lint !e718// endpoint active
114 * (volatile uint32 *) USB_DIEPMSK = 0xffffffff;
117 /*****************************************************************************/
118 // Description: configure specified endpoint to send/receive message.
119 // Global resource dependence:
120 // Author: jiayong.yang
122 /*****************************************************************************/
123 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
128 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
130 doepctl_ptr->mBits.ep_type = ep_type;
131 doepctl_ptr->mBits.mps =mps;
132 doepctl_ptr->mBits.set_nak = 0x1;
136 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
138 diepctl_ptr->mBits.ep_type = ep_type;
139 diepctl_ptr->mBits.mps = mps;
140 diepctl_ptr->mBits.set_nak = 0x1;
144 /*****************************************************************************/
145 // Description: start endpoint transfer.
146 // Global resource dependence:
147 // Author: jiayong.yang
149 /*****************************************************************************/
150 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
152 uint16 packet_count = 0;
156 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
157 volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
161 // Dcache_InvalRegion((unsigned int)buffer, MAX_RECV_LENGTH);
162 * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
165 doeptsiz_ptr->mBits.transfer_size = MAX_RECV_LENGTH; // transfer size
166 doeptsiz_ptr->mBits.packet_count = (MAX_RECV_LENGTH+doepctl_ptr->mBits.mps-1)/doepctl_ptr->mBits.mps;
167 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
168 * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
172 volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U *) USB_DIEPTSIZ (ep_num);
173 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
178 #if defined CONFIG_SC8810 || defined CONFIG_SC8825 || defined CONFIG_SC8830 || defined(CONFIG_SC9630)
179 Dcache_CleanRegion((unsigned int)buffer, transfer_size);
181 * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
184 dieptsiz_ptr->mBits.transfer_size = transfer_size; // transfer size
185 packet_count = (transfer_size+diepctl_ptr->mBits.mps-1) /diepctl_ptr->mBits.mps;
186 dieptsiz_ptr->mBits.packet_count = packet_count; // packet count
187 diepctl_ptr->mBits.tx_fifo_number = ep_num; // tx fifo number
189 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
190 * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
195 /*****************************************************************************/
196 // Description: process desecriptor request.
197 // Global resource dependence:
198 // Author: jiayong.yang
200 /*****************************************************************************/
201 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
204 uint8 *send_data=NULL;
207 length = (uint32) request2->mBits.length_l;
209 switch (request1->mBits.value_m)
212 case USB_DEVICE_DESCRIPTOR_TYPE:
214 send_data = (uint8 *) UCOM_Get_DevDesc();//lint !e718
215 EPI0_config (0x12, 0x1, TRUE, (uint32 *) send_data);
219 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
221 send_data = (uint8 *) UCOM_Get_CfgDesc();//lint !e718
225 EPI0_config (0x20, 0x1, TRUE, (uint32 *) send_data);
229 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
238 /*****************************************************************************/
239 // Description: process setup transaction.
240 // Global resource dependence:
241 // Author: jiayong.yang
243 /*****************************************************************************/
245 LOCAL void usb_setup_handle (void)
247 uint32 vendor_ack = 0;
248 USB_REQUEST_1_U *request1;
249 USB_REQUEST_2_U *request2;
251 request1 = (USB_REQUEST_1_U *) (unsigned int) (&s_setup_packet[0]);
252 request2 = (USB_REQUEST_2_U *) (unsigned int) (&s_setup_packet[1]);
254 switch (request1->mBits.type)
257 case USB_REQ_STANDARD://standard
259 switch (request1->mBits.brequest)
261 case USB_REQUEST_SET_ADDRESS:
263 volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
265 dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
266 EPI0_config (0, 1, FALSE, NULL);
269 case USB_REQUEST_GET_DESCRIPTOR:
271 usb_get_descriptor (request1, request2);
274 case USB_REQUEST_SET_CONFIGURATION:
275 EPI0_config (0, 1, FALSE, NULL);
278 EPI0_config (0, 1, TRUE, &vendor_ack);
284 case USB_REQ_CLASS://class
286 switch (request1->mBits.recipient)
288 case USB_REC_INTERFACE:
290 if ( (0x01 == request1->mBits.value_l)
291 && (0x06 == request1->mBits.value_m))
294 usb_EPActive (USB_EP5, USB_EP_DIR_IN);
295 usb_EPActive (USB_EP6, USB_EP_DIR_OUT);
298 EPI0_config (0, 1, FALSE, NULL);
301 EPI0_config (0, 1, TRUE, NULL);
307 EPI0_config (4, 1, TRUE, &vendor_ack);
310 EPI0_config (0, 1, TRUE, NULL);
315 /*****************************************************************************/
316 // Description: usb reset interrupt handler.
317 // Global resource dependence:
318 // Author: jiayong.yang
320 /*****************************************************************************/
322 LOCAL void usb_reset_handler (void)
327 //SCI_TraceLow("enter usb reset.\r\n");
329 * (volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_12); // disable reset interrupt
331 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27; // set NAK for all OUT endpoint
333 * (volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
335 * (volatile uint32 *) USB_DAINTMSK |= (unsigned int) (BIT_0|BIT_16);
336 * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_2|BIT_1);
337 * (volatile uint32 *) USB_DIEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_1|BIT_2|BIT_5);//lint !e718
339 * (volatile uint32 *) USB_GRXFSIZ = (unsigned int) (BIT_2|BIT_4|BIT_9); //RX fifo ,276 Dword,start address is 0
340 * (volatile uint32 *) USB_GNPTXFSIZ = (unsigned int) ( (BIT_2|BIT_4|BIT_9) |BIT_21); //EP0 TX fifo, 32 Dword, start address is 0+276=276
341 * (volatile uint32 *) USB_DIEPTXF (5) = (unsigned int) ( (BIT_2|BIT_4|BIT_5|BIT_9) |BIT_23); //lint !e718//EP5 TX fifo, 64 Dword, start address is 276+32 = 308
343 * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5; //reflush tx fifo
345 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
349 if (timeout >= USB_TIMEOUT)
356 * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4; //reflush rx fifo
358 while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
362 if (timeout >= USB_TIMEOUT)
368 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
369 EPO0_config (TRUE, s_setup_packet);
371 * (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12; // enable reset interrupt
373 * (volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12; //clear reset interrupt
377 /*****************************************************************************/
378 // Description: usb enumeration done handler.
379 // Global resource dependence:
380 // Author: jiayong.yang
382 /*****************************************************************************/
384 void usb_enumeration_done (void)
386 volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
388 enum_speed = dsts_ptr->mBits.enumspd; //read enumration speed
389 //SCI_TraceLow("usb_enumeration_done: device_speed = %d\r\n",enum_speed);
391 * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
393 EPn_config (USB_EP5, USB_EP_TYPE_BULK, USB_EP_DIR_IN, USB_PACKET_64);
394 EPn_config (USB_EP6, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, USB_PACKET_64);
396 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
397 EPO0_config (TRUE, s_setup_packet);
399 * (volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
401 * (volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
404 /*****************************************************************************/
405 // Description: out endpoint6 handler.
406 // Global resource dependence:
407 // Author: jiayong.yang
409 /*****************************************************************************/
410 LOCAL void usb_EP6_handle (void)
412 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (USB_EP6);
413 volatile USB_DOEPINT_U doepint;
414 volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (USB_EP6);
415 volatile uint32 mask;
417 mask = * (volatile uint32 *) USB_DOEPMSK;
418 doepint.dwValue = doepint_ptr->dwValue;
420 doepint.dwValue &= (unsigned int) mask;
422 if (doepint.mBits.transfer_com)
424 doepint_ptr->mBits.transfer_com = 1;
425 recv_length = MAX_RECV_LENGTH - doeptsiz_ptr->mBits.transfer_size;
426 Dcache_InvalRegion((unsigned int)(&usb_out_endpoint_buf[currentDmaBufferIndex][0]), MAX_RECV_LENGTH);
428 * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_13;
429 * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_4;
430 * (volatile uint32 *) USB_DOEPMSK &= (unsigned int) (~BIT_0);
432 else if (doepint.mBits.nak)
434 usb_start_transfer (USB_EP6, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) usb_out_endpoint_buf[currentDmaBufferIndex]);
435 * (volatile uint32 *) USB_DOEPMSK &= (unsigned int) (~BIT_13);
436 * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_0;
437 doepint_ptr->mBits.nak = 0x1;
440 else if (doepint.mBits.bbleerr)
442 doepint_ptr->mBits.bbleerr = 0x01;
445 /*****************************************************************************/
446 // Description: out endpoint0 handler.
447 // Global resource dependence:
448 // Author: jiayong.yang
450 /*****************************************************************************/
452 LOCAL void usb_EP0_out_handle (void)
454 volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
456 if (doepint_ptr->mBits.timeout_condi)
461 if (doepint_ptr->mBits.transfer_com)
463 * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
464 doepint_ptr->mBits.transfer_com = 0x1;
467 if (doepint_ptr->mBits.outtokenfifoemp)
469 doepint_ptr->mBits.outtokenfifoemp = 0x1;
472 doepint_ptr->dwValue = 0xffffffff;// clear all interrupt
474 Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
475 EPO0_config (TRUE, s_setup_packet); //renable ep0 nd set packet count
478 /*****************************************************************************/
479 // Description: out endpoint handler.
480 // Global resource dependence:
481 // Author: jiayong.yang
483 /*****************************************************************************/
484 LOCAL void usb_EP_out_handle (void)
486 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
489 daint.dwValue = daint_ptr->dwValue; // disable EP out interrupt
490 * (volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_19);
492 if (daint.mBits.outepint_0)
494 usb_EP0_out_handle();
497 if (daint.mBits.outepint_6)
502 * (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
504 /*****************************************************************************/
505 // Description: in endpoint handler.
506 // Global resource dependence:
507 // Author: jiayong.yang
509 /*****************************************************************************/
510 LOCAL void usb_EP_in_handle (void)
512 volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
516 * (volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_18); // disable EP in interrupt
517 daint.dwValue = daint_ptr->dwValue;
519 if (daint.mBits.inepint_0)
521 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (0);
523 diepint_ptr->dwValue = 0xFFFFFFFF;
526 if (daint.mBits.inepint_5)
528 volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (5);
530 diepint_ptr->dwValue = 0xFFFFFFFF;
533 * (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_18; // enable EP in interrupt
536 /*****************************************************************************/
537 // Description: usb interrupt handler.
538 // Global resource dependence:
539 // Author: jiayong.yang
541 /*****************************************************************************/
542 static __inline void usb_handler (void)
544 volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
545 volatile USB_INTSTS_U usb_int;
547 usb_int.dwValue = usb_int_ptr->dwValue;
549 // in endpoint interrupt
550 if (usb_int.mBits.iepint)
555 // out endpoint interrupt
556 if (usb_int.mBits.oepint)
561 // enumeration done interrupt
562 if (usb_int.mBits.enumdone)
564 usb_enumeration_done();
568 if (usb_int.mBits.usbrst)
573 /*****************************************************************************/
574 // Description: configure in endpoint ep_id to send message.
575 // Global resource dependence:
576 // Author: jiayong.yang
578 /*****************************************************************************/
579 #define USB_SEND_MAX_TIME 1000
580 PUBLIC int USB_EPxSendData (char ep_id ,unsigned int *pBuf, int len)
582 volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U*)USB_DIEPTSIZ(ep_id);
583 volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_id);
584 uint32 old_tick, new_tick;
585 uint32 split_len = 0;
590 usb_start_transfer ( (USB_EP_NUM_E) ep_id, USB_EP_DIR_IN, len - split_len, TRUE, (uint32 *) pBuf);
591 old_tick = new_tick = SCI_GetTickCount();
592 while(dieptsiz_ptr->dwValue){
593 new_tick = SCI_GetTickCount();
594 if(new_tick - old_tick > USB_SEND_MAX_TIME){
597 dieptsiz_ptr = (USB_DIEPTSIZ_U*)USB_DIEPTSIZ(ep_id);
599 usb_start_transfer ( (USB_EP_NUM_E) ep_id, USB_EP_DIR_IN, split_len, TRUE, (uint32 *) ((uint32)pBuf + len - split_len));
601 usb_start_transfer ( (USB_EP_NUM_E) ep_id, USB_EP_DIR_IN, len, TRUE, (uint32 *) pBuf);
603 old_tick = new_tick = SCI_GetTickCount();
604 while(dieptsiz_ptr->dwValue){
605 new_tick = SCI_GetTickCount();
606 if(new_tick - old_tick > USB_SEND_MAX_TIME){
609 dieptsiz_ptr = (USB_DIEPTSIZ_U*)USB_DIEPTSIZ(ep_id);
610 if(diepctl_ptr->mBits.nak_status) {
611 if(dieptsiz_ptr->mBits.transfer_size ==0)
612 * (volatile uint32 *) USB_DIEPCTL (ep_id) |= (unsigned int) BIT_26;
614 * (volatile uint32 *) USB_DIEPCTL (ep_id) |= (unsigned int) BIT_30;
615 * (volatile uint32 *) USB_DIEPCTL (ep_id) |= (unsigned int) (BIT_31|BIT_26);
622 /*****************************************************************************/
623 // Description: initialize the usb core.
624 // Global resource dependence:
625 // Author: jiayong.yang
627 /*****************************************************************************/
628 PUBLIC void usb_core_init (void)
630 * (volatile uint32 *) USB_GAHBCFG |= (unsigned int) BIT_5;
631 * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_13;
638 char VCOM_GetChar (void)
641 if (readIndex == recv_length)
650 nIndex = currentDmaBufferIndex;
651 //Dcache_InvalRegion((unsigned int)(&usb_out_endpoint_buf[nIndex][0]), MAX_RECV_LENGTH);
653 currentDmaBufferIndex ^= 0x1;
661 return usb_out_endpoint_buf[nIndex][readIndex++];
664 int VCOM_GetSingleChar (void)
666 if (readIndex == recv_length)
675 nIndex = currentDmaBufferIndex;
676 currentDmaBufferIndex ^= 0x1;
685 //printf("readIndex = %d recv_length = %d nIndex = %d error_count = %d\n", readIndex, recv_length, nIndex, error_count);
687 /*if ((error_count >= 6583) && (error_count <= 6585)) {
689 printf("%s %d error_count = %d\n", __FUNCTION__, __LINE__, error_count);
690 for (aaa = 0; aaa < recv_length; aaa ++) {
693 printf(" %02x", usb_out_endpoint_buf[nIndex][aaa]);
701 return (int)usb_out_endpoint_buf[nIndex][readIndex++];
704 int VCOM_Read(unsigned char* buf, unsigned int len)
706 unsigned char *src, *dest = buf;
707 unsigned escape_flag = 0;
710 if(readIndex == recv_length){
716 if (recv_length > 0){
717 nIndex = currentDmaBufferIndex;
718 currentDmaBufferIndex ^= 0x1;
722 /* We reach an agreement that host can't send
723 a packet whose size exceeds MAX_PKT_SIZE;
725 len = recv_length < len ? recv_length : len;
726 src = usb_out_endpoint_buf[nIndex] + readIndex;
727 /* The last byte is HDLC_FLAG in most cases,
728 so it's picked out from escape process.
730 for(; readIndex < len - 1; readIndex++, src++)
732 if(*src == HDLC_ESCAPE){
735 }else if(escape_flag){
736 *dest++ = *src ^ HDLC_ESCAPE_MASK;
741 /* Check whether it's an entire packet,
742 if so exit this function,
743 otherwise continue to receive data from host.
746 if(*src == HDLC_FLAG)
748 if(*src == HDLC_ESCAPE)
750 else if(escape_flag){
751 *dest++ = *src ^ HDLC_ESCAPE_MASK;