/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int eprx_recv_op(void) { uint old_ep_index; uint this_len; uint fifo; old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); if (USBC_Dev_IsEpStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { USBC_Dev_EpClearStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); printf("sunxi ubs read error: usb rx ep is busy already\n"); } else { if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); if(fastboot_data_flag == 1) { fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); sunxi_ubuf.rx_req_length = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, sunxi_ubuf.rx_req_buffer); sunxi_ubuf.rx_req_buffer += this_len; sunxi_usb_dbg("special read ep bytes 0x%x\n", sunxi_ubuf.rx_req_length); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } else if(!sunxi_ubuf.rx_ready_for_data) { fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); memset(sunxi_ubuf.rx_req_buffer, 0, 64); sunxi_ubuf.rx_req_length = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, sunxi_ubuf.rx_req_buffer); sunxi_ubuf.rx_ready_for_data = 1; sunxi_usb_dbg("read ep bytes 0x%x\n", sunxi_ubuf.rx_req_length); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } else { sunxi_usb_dbg("eprx do nothing and left it to dma\n"); } } else { sunxi_usb_dbg("sunxi usb rxdata not ready\n"); } } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index); return 0; }
/* ******************************************************************************* * fastboot_tx_status * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_write_fifo(uchar *buffer, unsigned int buffer_size) { u32 old_ep_idx = 0; u32 fifo = 0; u32 transfered = 0; u32 left = 0; u32 this_len; /* Save index */ old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_IN_EP_INDEX); left = buffer_size; fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_IN_EP_INDEX); while(left) { this_len = MIN(sunxi_udc_source.fifo_size, left); this_len = USBC_WritePacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer + transfered); transfered += this_len; left -= this_len; __usb_writecomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_TX, 1); } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); return 0; }
/* ******************************************************************************* * __usb_read_ep0_data * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_read_ep0_data(void *buffer, uint data_type) { u32 fifo_count = 0; u32 fifo = 0; int ret = 0; u32 old_ep_index = 0; old_ep_index = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_CTRL_EP_INDEX); fifo_count = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); if(!data_type) { if(fifo_count != 8 ) { printf("err: ep0 fifo_count %d is not 8\n", fifo_count); return -1; } } USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, fifo_count, (void *)buffer); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0, 1); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_index); return ret; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void __usb_recv_by_dma_isr(void *p_arg) { u32 old_ep_idx; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择RXEP //选择使用IO方式搬运数据 sunxi_usb_dbg("select io mode to transfer data\n"); USBC_Dev_ClearEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); if(usb_dma_trans_unaliged_bytes) { uint fifo, this_len; this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, usb_dma_trans_unaligned_buf); __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 usb_dma_trans_unaliged_bytes = 0; } //如果当前dma传输的不是完整包,则需要手动清除中断 if(sunxi_ubuf.request_size % sunxi_udc_source.bulk_ep_max) { USBC_Dev_ReadDataStatus(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //printf("clear rx pending manually\n"); } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); sunxi_udev_active->dma_rx_isr(p_arg); }
static int __usb_read_fifo(void *buffer, unsigned int buffer_size) { u32 old_ep_idx = 0; u32 fifo = 0; u32 transfered = 0; u32 left = 0; u32 this_len; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择当前EP fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择fifo left = buffer_size; if(left) { while(left) { if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); this_len = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer + transfered); transfered += this_len; left -= this_len; __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } } USBC_INT_ClearEpPending(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, SUNXI_USB_BULK_OUT_EP_INDEX); } else { if(USBC_Dev_IsReadDataReady(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX)) { this_len = USBC_ReadLenFromFifo(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); this_len = USBC_ReadPacket(sunxi_udc_source.usbc_hd, fifo, this_len, buffer); transfered = this_len; __usb_readcomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX, 1); //返回状态 } else { sunxi_usb_dbg("sunxi usb rxdata not ready\n"); } } USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); sunxi_usb_dbg("read bytes 0x%x\n", transfered); return transfered; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void sunxi_udc_send_setup(uint bLength, void *buffer) { u32 fifo = 0; if(!bLength) { /* sent zero packet */ __usb_writecomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0, 1); } else { fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_CTRL_EP_INDEX); USBC_WritePacket(sunxi_udc_source.usbc_hd, fifo, bLength, (void *)buffer); __usb_writecomplete(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0, 1); } }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_udc_start_recv_by_dma(uint mem_buf, uint length) { uint old_ep_idx; uint fifo; old_ep_idx = USBC_GetActiveEp(sunxi_udc_source.usbc_hd); USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //选择当前EP //usb控制器选择dma传输方式 USBC_Dev_ConfigEpDma(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_RX); //选择buffer fifo = USBC_SelectFIFO(sunxi_udc_source.usbc_hd, SUNXI_USB_BULK_OUT_EP_INDEX); //刷掉cache flush_cache(mem_buf, length); //使能dma传输 sunxi_ubuf.request_size = length; sunxi_usb_dbg("dma start\n"); sunxi_dma_start(sunxi_udc_source.dma_recv_channal, fifo, mem_buf, length); //恢复EP USBC_SelectActiveEp(sunxi_udc_source.usbc_hd, old_ep_idx); //恢复原有EP return 0; }
/* ******************************************************************************* * read_request * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int read_request(struct usb_device_request *req) { u32 fifo_count = 0; u32 fifo = 0; int ret = FASTBOOT_OK; u8 old_ep_index = 0; old_ep_index = USBC_GetActiveEp(udc.bsp); USBC_SelectActiveEp(udc.bsp, CTRL_EP_INDEX); fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX); fifo_count = USBC_ReadLenFromFifo(udc.bsp, USBC_EP_TYPE_EP0); if(fifo_count != 8 ){ DMSG_PANIC("err: ep0 fifo_count is not 8\n", fifo_count); return FASTBOOT_ERROR; } USBC_ReadPacket(udc.bsp, fifo, fifo_count, (void *)req); ReadDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 0); USBC_SelectActiveEp(udc.bsp, old_ep_index); return ret; }
/* ******************************************************************************* * do_usb_req_get_descriptor * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int do_usb_req_get_descriptor(void) { int ret = FASTBOOT_OK; u32 fifo = 0; if(0 == udc.req.wLength){ DMSG_PANIC("wrn: req.wLength is zero\n"); return FASTBOOT_OK; } if(udc.req.bmRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)){ DMSG_PANIC("err: invalid bmRequestType, (0, %d), (0, %d)\n", udc.req.bmRequestType); return FASTBOOT_ERROR; } switch(udc.req.wValue >> 8){ case USB_DT_DEVICE: { struct usb_device_descriptor d; memset(&d, 0, sizeof(struct usb_device_descriptor)); d.bLength = MIN(udc.req.wLength, sizeof (d)); d.bDescriptorType = USB_DT_DEVICE; #ifdef CONFIG_USB_1_1_DEVICE d.bcdUSB = 0x110; #else d.bcdUSB = 0x200; #endif d.bDeviceClass = 0xff; d.bDeviceSubClass = 0xff; d.bDeviceProtocol = 0xff; d.bMaxPacketSize0 = 0x40; d.idVendor = DEVICE_VENDOR_ID; d.idProduct = DEVICE_PRODUCT_ID; d.bcdDevice = DEVICE_BCD; d.iManufacturer = DEVICE_STRING_MANUFACTURER_INDEX; d.iProduct = DEVICE_STRING_PRODUCT_INDEX; d.iSerialNumber = DEVICE_STRING_SERIAL_NUMBER_INDEX; d.bNumConfigurations = 1; fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX); memcpy(fastboot_fifo_ep0, &d, d.bLength); USBC_WritePacket(udc.bsp, fifo, d.bLength, (void *)fastboot_fifo_ep0); WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1); } break; case USB_DT_CONFIG: { struct usb_configuration_descriptor c; struct usb_interface_descriptor i; struct usb_endpoint_descriptor ep_in, ep_out; unsigned char bytes_remaining = udc.req.wLength; unsigned char bytes_total = 0; memset(&c, 0, sizeof(struct usb_configuration_descriptor)); memset(&i, 0, sizeof(struct usb_interface_descriptor)); memset(&ep_in, 0, sizeof(struct usb_endpoint_descriptor)); memset(&ep_out, 0, sizeof(struct usb_endpoint_descriptor)); memset(fastboot_fifo_ep0, 0, sizeof(EP0_FIFOSIZE)); /* configuration */ c.bLength = MIN(bytes_remaining, sizeof (c)); c.bDescriptorType = USB_DT_CONFIG; c.wTotalLength = sizeof (c) + sizeof (i) + sizeof (ep_in) + sizeof (ep_out); c.bNumInterfaces = 1; c.bConfigurationValue = CONFIGURATION_NORMAL; c.iConfiguration = DEVICE_STRING_CONFIG_INDEX; c.bmAttributes = 0xc0; c.bMaxPower = 0x32; bytes_remaining -= c.bLength; memcpy (&fastboot_fifo_ep0[0], &c, c.bLength); bytes_total += c.bLength; /* interface */ i.bLength = MIN (bytes_remaining, sizeof(i)); i.bDescriptorType = USB_DT_INTERFACE; i.bInterfaceNumber = 0x00; i.bAlternateSetting = 0x00; i.bNumEndpoints = 0x02; i.bInterfaceClass = FASTBOOT_INTERFACE_CLASS; i.bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS; i.bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL; i.iInterface = DEVICE_STRING_INTERFACE_INDEX; bytes_remaining -= i.bLength; memcpy (&fastboot_fifo_ep0[bytes_total], &i, i.bLength); bytes_total += i.bLength; /* ep_in */ ep_in.bLength = MIN (bytes_remaining, sizeof (ep_in)); ep_in.bDescriptorType = USB_DT_ENDPOINT; ep_in.bEndpointAddress = 0x80 | BULK_IN_EP_INDEX; /* IN */ ep_in.bmAttributes = USB_ENDPOINT_XFER_BULK; if(fastboot_is_highspeed()){ ep_in.wMaxPacketSize = HIGH_SPEED_EP_MAX_PACKET_SIZE; }else{ ep_in.wMaxPacketSize = FULL_SPEED_EP_MAX_PACKET_SIZE; } ep_in.bInterval = 0x00; bytes_remaining -= ep_in.bLength; memcpy (&fastboot_fifo_ep0[bytes_total], &ep_in, ep_in.bLength); bytes_total += ep_in.bLength; /* ep_out */ ep_out.bLength = MIN (bytes_remaining, sizeof (ep_out)); ep_out.bDescriptorType = USB_DT_ENDPOINT; ep_out.bEndpointAddress = BULK_OUT_EP_INDEX; /* OUT */ ep_out.bmAttributes = USB_ENDPOINT_XFER_BULK; if(fastboot_is_highspeed()){ ep_out.wMaxPacketSize = HIGH_SPEED_EP_MAX_PACKET_SIZE; }else{ ep_out.wMaxPacketSize = FULL_SPEED_EP_MAX_PACKET_SIZE; } ep_out.bInterval = 0x00; bytes_remaining -= ep_out.bLength; memcpy (&fastboot_fifo_ep0[bytes_total], &ep_out, ep_out.bLength); bytes_total += ep_out.bLength; fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX); USBC_WritePacket(udc.bsp, fifo, bytes_total, (void *)fastboot_fifo_ep0); WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1); } break; case USB_DT_STRING: { unsigned char bLength = 0; unsigned char string_index = udc.req.wValue & 0xff; if(string_index > DEVICE_STRING_MAX_INDEX){ /* Windows XP asks for an invalid string index. Fail silently instead of doing NAK_REQ(); */ }else if(0 == string_index){ /* Language ID */ bLength = MIN(4, udc.req.wLength); memset(fastboot_fifo_ep0, 0, sizeof(EP0_FIFOSIZE)); fastboot_fifo_ep0[0] = bLength; /* length */ fastboot_fifo_ep0[1] = USB_DT_STRING; /* descriptor = string */ fastboot_fifo_ep0[2] = DEVICE_STRING_LANGUAGE_ID & 0xff; fastboot_fifo_ep0[3] = DEVICE_STRING_LANGUAGE_ID >> 8; fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX); USBC_WritePacket(udc.bsp, fifo, bLength, (void *)fastboot_fifo_ep0); WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1); }else{ /* Size of string in chars */ unsigned char s = 0; unsigned char sl = strlen (&device_strings[string_index][0]); unsigned char bLength = 2 + (2 * sl); bLength = MIN(bLength, udc.req.wLength); memset(fastboot_fifo_ep0, 0, sizeof(EP0_FIFOSIZE)); fastboot_fifo_ep0[0] = bLength; /* length */ fastboot_fifo_ep0[1] = USB_DT_STRING; /* descriptor = string */ /* Copy device string to fifo, expand to simple unicode */ for(s = 0; s < sl; s++){ fastboot_fifo_ep0[2+ 2*s + 0] = device_strings[string_index][s]; fastboot_fifo_ep0[2+ 2*s + 1] = 0; } fifo = USBC_SelectFIFO(udc.bsp, CTRL_EP_INDEX); USBC_WritePacket(udc.bsp, fifo, bLength, (void *)fastboot_fifo_ep0); WriteDataStatusComplete(udc.bsp, USBC_EP_TYPE_EP0, 1); } }