/* ******************************************************************************* * 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; }
/* ************************************************************************************************************ * * 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); } }
/* ******************************************************************************* * 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); } }