/* ******************************************************************************* * do_usb_req_get_descriptor * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_get_descriptor(struct usb_device_request *req, uchar *buffer) { int ret = SUNXI_USB_REQ_SUCCESSED; //获取描述符 switch(req->wValue >> 8) { case USB_DT_DEVICE: //设备描述符 { struct usb_device_descriptor *dev_dscrptr; sunxi_usb_dbg("get device descriptor\n"); dev_dscrptr = (struct usb_device_descriptor *)buffer; memset((void *)dev_dscrptr, 0, sizeof(struct usb_device_descriptor)); dev_dscrptr->bLength = MIN(req->wLength, sizeof (struct usb_device_descriptor)); dev_dscrptr->bDescriptorType = USB_DT_DEVICE; #ifdef CONFIG_USB_1_1_DEVICE dev_dscrptr->bcdUSB = 0x110; #else dev_dscrptr->bcdUSB = 0x200; #endif dev_dscrptr->bDeviceClass = 0xff; //设备类:大容量存储 dev_dscrptr->bDeviceSubClass = 0xff; dev_dscrptr->bDeviceProtocol = 0xff; dev_dscrptr->bMaxPacketSize0 = 0x40; dev_dscrptr->idVendor = DEVICE_VENDOR_ID; dev_dscrptr->idProduct = DEVICE_PRODUCT_ID; dev_dscrptr->bcdDevice = DEVICE_BCD; dev_dscrptr->iManufacturer = SUNXI_FASTBOOT_DEVICE_STRING_MANUFACTURER_INDEX; dev_dscrptr->iProduct = SUNXI_FASTBOOT_DEVICE_STRING_PRODUCT_INDEX; dev_dscrptr->iSerialNumber = SUNXI_FASTBOOT_DEVICE_STRING_SERIAL_NUMBER_INDEX; dev_dscrptr->bNumConfigurations = 1; sunxi_udc_send_setup(dev_dscrptr->bLength, buffer); } break; case USB_DT_CONFIG: //配置描述符 { struct usb_configuration_descriptor *config_dscrptr; struct usb_interface_descriptor *inter_dscrptr; struct usb_endpoint_descriptor *ep_in, *ep_out; unsigned char bytes_remaining = req->wLength; unsigned char bytes_total = 0; sunxi_usb_dbg("get config descriptor\n"); bytes_total = sizeof (struct usb_configuration_descriptor) + \ sizeof (struct usb_interface_descriptor) + \ sizeof (struct usb_endpoint_descriptor) + \ sizeof (struct usb_endpoint_descriptor); memset(buffer, 0, bytes_total); config_dscrptr = (struct usb_configuration_descriptor *)(buffer + 0); inter_dscrptr = (struct usb_interface_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor)); ep_in = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor)); ep_out = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor) + \ sizeof(struct usb_endpoint_descriptor)); /* configuration */ config_dscrptr->bLength = MIN(bytes_remaining, sizeof (struct usb_configuration_descriptor)); config_dscrptr->bDescriptorType = USB_DT_CONFIG; config_dscrptr->wTotalLength = bytes_total; config_dscrptr->bNumInterfaces = 1; config_dscrptr->bConfigurationValue = 1; config_dscrptr->iConfiguration = SUNXI_FASTBOOT_DEVICE_STRING_CONFIG_INDEX; config_dscrptr->bmAttributes = 0xC0; config_dscrptr->bMaxPower = 0xFA; //最大电流500ms(0xfa * 2) bytes_remaining -= config_dscrptr->bLength; /* interface */ inter_dscrptr->bLength = MIN (bytes_remaining, sizeof(struct usb_interface_descriptor)); inter_dscrptr->bDescriptorType = USB_DT_INTERFACE; inter_dscrptr->bInterfaceNumber = 0x00; inter_dscrptr->bAlternateSetting = 0x00; inter_dscrptr->bNumEndpoints = 0x02; inter_dscrptr->bInterfaceClass = 0xff; //fastboot storage inter_dscrptr->bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS; inter_dscrptr->bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL; inter_dscrptr->iInterface = SUNXI_FASTBOOT_DEVICE_STRING_INTERFACE_INDEX; bytes_remaining -= inter_dscrptr->bLength; /* ep_in */ ep_in->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_in->bDescriptorType = USB_DT_ENDPOINT; ep_in->bEndpointAddress = sunxi_udc_get_ep_in_type(); /* IN */ ep_in->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_in->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_in->bInterval = 0x00; bytes_remaining -= ep_in->bLength; /* ep_out */ ep_out->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_out->bDescriptorType = USB_DT_ENDPOINT; ep_out->bEndpointAddress = sunxi_udc_get_ep_out_type(); /* OUT */ ep_out->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_out->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_out->bInterval = 0x00; bytes_remaining -= ep_out->bLength; sunxi_udc_send_setup(MIN(req->wLength, bytes_total), buffer); } break; case USB_DT_STRING: { unsigned char bLength = 0; unsigned char string_index = req->wValue & 0xff; sunxi_usb_dbg("get string descriptor\n"); /* Language ID */ if(string_index == 0) { bLength = MIN(4, req->wLength); sunxi_udc_send_setup(bLength, (void *)sunxi_usb_fastboot_dev[0]); } else if(string_index < SUNXI_USB_FASTBOOT_DEV_MAX) { /* Size of string in chars */ unsigned char i = 0; unsigned char str_length = strlen ((const char *)sunxi_usb_fastboot_dev[string_index]); unsigned char bLength = 2 + (2 * str_length); buffer[0] = bLength; /* length */ buffer[1] = USB_DT_STRING; /* descriptor = string */ /* Copy device string to fifo, expand to simple unicode */ for(i = 0; i < str_length; i++) { buffer[2+ 2*i + 0] = sunxi_usb_fastboot_dev[string_index][i]; buffer[2+ 2*i + 1] = 0; } bLength = MIN(bLength, req->wLength); sunxi_udc_send_setup(bLength, buffer); } else { printf("sunxi usb err: string line %d is not supported\n", string_index); } } break; case USB_DT_DEVICE_QUALIFIER: { #ifdef CONFIG_USB_1_1_DEVICE /* This is an invalid request for usb 1.1, nak it */ USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); #else struct usb_qualifier_descriptor *qua_dscrpt; sunxi_usb_dbg("get qualifier descriptor\n"); qua_dscrpt = (struct usb_qualifier_descriptor *)buffer; memset(&buffer, 0, sizeof(struct usb_qualifier_descriptor)); qua_dscrpt->bLength = MIN(req->wLength, sizeof(sizeof(struct usb_qualifier_descriptor))); qua_dscrpt->bDescriptorType = USB_DT_DEVICE_QUALIFIER; qua_dscrpt->bcdUSB = 0x200; qua_dscrpt->bDeviceClass = 0xff; qua_dscrpt->bDeviceSubClass = 0xff; qua_dscrpt->bDeviceProtocol = 0xff; qua_dscrpt->bMaxPacketSize0 = 0x40; qua_dscrpt->bNumConfigurations = 1; qua_dscrpt->bRESERVED = 0; sunxi_udc_send_setup(qua_dscrpt->bLength, buffer); #endif } break; default: printf("err: unkown wValue(%d)\n", req->wValue); ret = SUNXI_USB_REQ_OP_ERR; } return ret; }
/* ******************************************************************************* * do_usb_req_get_descriptor * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __usb_get_descriptor(struct usb_device_request *req, uchar *buffer) { int ret = SUNXI_USB_REQ_SUCCESSED; //获取描述符 switch(req->wValue >> 8) { case USB_DT_DEVICE: //设备描述符 { struct usb_device_descriptor *dev_dscrptr; sunxi_usb_dbg("get device descriptor\n"); dev_dscrptr = (struct usb_device_descriptor *)buffer; memset((void *)dev_dscrptr, 0, sizeof(struct usb_device_descriptor)); dev_dscrptr->bLength = MIN(req->wLength, sizeof (struct usb_device_descriptor)); dev_dscrptr->bDescriptorType = USB_DT_DEVICE; #ifdef CONFIG_USB_1_1_DEVICE dev_dscrptr->bcdUSB = 0x110; #else dev_dscrptr->bcdUSB = 0x200; #endif dev_dscrptr->bDeviceClass = 0; dev_dscrptr->bDeviceSubClass = 0; dev_dscrptr->bDeviceProtocol = 0; dev_dscrptr->bMaxPacketSize0 = 0x40; dev_dscrptr->idVendor = DRIVER_VENDOR_ID; dev_dscrptr->idProduct = DRIVER_PRODUCT_ID; dev_dscrptr->bcdDevice = 0xffff; //ignored //dev_dscrptr->iManufacturer = SUNXI_USB_STRING_IMANUFACTURER; //dev_dscrptr->iProduct = SUNXI_USB_STRING_IPRODUCT; //dev_dscrptr->iSerialNumber = SUNXI_USB_STRING_ISERIALNUMBER; dev_dscrptr->iManufacturer = 0; dev_dscrptr->iProduct = 0; dev_dscrptr->iSerialNumber = 0; dev_dscrptr->bNumConfigurations = 1; sunxi_udc_send_setup(dev_dscrptr->bLength, buffer); } break; case USB_DT_CONFIG: //配置描述符 { struct usb_configuration_descriptor *config_dscrptr; struct usb_interface_descriptor *inter_dscrptr; struct usb_endpoint_descriptor *ep_in, *ep_out; unsigned char bytes_remaining = req->wLength; unsigned char bytes_total = 0; sunxi_usb_dbg("get config descriptor\n"); bytes_total = sizeof (struct usb_configuration_descriptor) + \ sizeof (struct usb_interface_descriptor) + \ sizeof (struct usb_endpoint_descriptor) + \ sizeof (struct usb_endpoint_descriptor); memset(buffer, 0, bytes_total); config_dscrptr = (struct usb_configuration_descriptor *)(buffer + 0); inter_dscrptr = (struct usb_interface_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor)); ep_in = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor)); ep_out = (struct usb_endpoint_descriptor *)(buffer + \ sizeof(struct usb_configuration_descriptor) + \ sizeof(struct usb_interface_descriptor) + \ sizeof(struct usb_endpoint_descriptor)); /* configuration */ config_dscrptr->bLength = MIN(bytes_remaining, sizeof (struct usb_configuration_descriptor)); config_dscrptr->bDescriptorType = USB_DT_CONFIG; config_dscrptr->wTotalLength = bytes_total; config_dscrptr->bNumInterfaces = 1; config_dscrptr->bConfigurationValue = 1; config_dscrptr->iConfiguration = 0; config_dscrptr->bmAttributes = 0x80; //not self powered config_dscrptr->bMaxPower = 0xFA; //最大电流500ms(0xfa * 2) bytes_remaining -= config_dscrptr->bLength; /* interface */ inter_dscrptr->bLength = MIN (bytes_remaining, sizeof(struct usb_interface_descriptor)); inter_dscrptr->bDescriptorType = USB_DT_INTERFACE; inter_dscrptr->bInterfaceNumber = 0x00; inter_dscrptr->bAlternateSetting = 0x00; inter_dscrptr->bNumEndpoints = 0x02; inter_dscrptr->bInterfaceClass = 0xff; inter_dscrptr->bInterfaceSubClass = 0xff; inter_dscrptr->bInterfaceProtocol = 0xff; inter_dscrptr->iInterface = 0; bytes_remaining -= inter_dscrptr->bLength; /* ep_in */ ep_in->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_in->bDescriptorType = USB_DT_ENDPOINT; ep_in->bEndpointAddress = sunxi_udc_get_ep_in_type(); /* IN */ ep_in->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_in->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_in->bInterval = 0x00; bytes_remaining -= ep_in->bLength; /* ep_out */ ep_out->bLength = MIN (bytes_remaining, sizeof (struct usb_endpoint_descriptor)); ep_out->bDescriptorType = USB_DT_ENDPOINT; ep_out->bEndpointAddress = sunxi_udc_get_ep_out_type(); /* OUT */ ep_out->bmAttributes = USB_ENDPOINT_XFER_BULK; ep_out->wMaxPacketSize = sunxi_udc_get_ep_max(); ep_out->bInterval = 0x00; bytes_remaining -= ep_out->bLength; sunxi_udc_send_setup(MIN(req->wLength, bytes_total), buffer); } break; case USB_DT_STRING: { unsigned char bLength = 0; unsigned char string_index = req->wValue & 0xff; sunxi_usb_dbg("get string descriptor\n"); /* Language ID */ if(string_index == 0) { bLength = MIN(4, req->wLength); buffer[0] = bLength; buffer[1] = USB_DT_STRING; buffer[2] = 9; buffer[3] = 4; sunxi_udc_send_setup(bLength, (void *)buffer); } else { printf("sunxi usb err: string line %d is not supported\n", string_index); } } break; case USB_DT_DEVICE_QUALIFIER: { #ifdef CONFIG_USB_1_1_DEVICE /* This is an invalid request for usb 1.1, nak it */ USBC_Dev_EpSendStall(sunxi_udc_source.usbc_hd, USBC_EP_TYPE_EP0); #else struct usb_qualifier_descriptor *qua_dscrpt; sunxi_usb_dbg("get qualifier descriptor\n"); qua_dscrpt = (struct usb_qualifier_descriptor *)buffer; memset(&buffer, 0, sizeof(struct usb_qualifier_descriptor)); qua_dscrpt->bLength = MIN(req->wLength, sizeof(sizeof(struct usb_qualifier_descriptor))); qua_dscrpt->bDescriptorType = USB_DT_DEVICE_QUALIFIER; qua_dscrpt->bcdUSB = 0x200; qua_dscrpt->bDeviceClass = 0xff; qua_dscrpt->bDeviceSubClass = 0xff; qua_dscrpt->bDeviceProtocol = 0xff; qua_dscrpt->bMaxPacketSize0 = 0x40; qua_dscrpt->bNumConfigurations = 1; qua_dscrpt->breserved = 0; sunxi_udc_send_setup(qua_dscrpt->bLength, buffer); #endif } break; default: printf("err: unkown wValue(%d)\n", req->wValue); ret = SUNXI_USB_REQ_OP_ERR; } return ret; }