s32 USB_GetDescriptors(struct ehci_hcd * ehci,struct ehci_device * fd, usb_devdesc *udd) { u8 *buffer = NULL; u8 *ptr = NULL; usb_configurationdesc *ucd = NULL; usb_interfacedesc *uid = NULL; usb_endpointdesc *ued = NULL; s32 retval = 0; u32 size,i; u32 iConf, iInterface, iEndpoint; buffer = USB_Alloc(sizeof(*udd)); if(buffer == NULL) { retval = -ENOMEM; goto free_and_error; } retval = __usb_getdesc(ehci, fd, buffer, USB_DT_DEVICE, 0, USB_DT_DEVICE_SIZE); if(retval < 0) goto free_and_error; memcpy(udd, buffer, USB_DT_DEVICE_SIZE); USB_Free(buffer); udd->bcdUSB = cpu_to_le16(udd->bcdUSB); udd->idVendor = cpu_to_le16(udd->idVendor); udd->idProduct = cpu_to_le16(udd->idProduct); udd->bcdDevice = cpu_to_le16(udd->bcdDevice); udd->configurations = USB_Alloc(udd->bNumConfigurations* sizeof(*udd->configurations)); if(udd->configurations == NULL) { retval = -ENOMEM; goto free_and_error; } memset(udd->configurations,0,udd->bNumConfigurations* sizeof(*udd->configurations)); for(iConf = 0; iConf < udd->bNumConfigurations; iConf++) { buffer = USB_Alloc( USB_DT_CONFIG_SIZE); if(buffer == NULL) { retval = -ENOMEM; goto free_and_error; } retval = __usb_getdesc(ehci, fd, buffer, USB_DT_CONFIG, iConf, USB_DT_CONFIG_SIZE); ucd = &udd->configurations[iConf]; memcpy(ucd, buffer, USB_DT_CONFIG_SIZE); USB_Free( buffer); ucd->wTotalLength = cpu_to_le16(ucd->wTotalLength); size = ucd->wTotalLength; buffer = USB_Alloc( ucd->wTotalLength); if(buffer == NULL) { retval = -ENOMEM; goto free_and_error; } retval = __usb_getdesc(ehci, fd, buffer, USB_DT_CONFIG, iConf, ucd->wTotalLength); if(retval < 0) goto free_and_error; ptr = buffer; ptr += ucd->bLength; size -= ucd->bLength; retval = -ENOMEM; ucd->interfaces = USB_Alloc(ucd->bNumInterfaces* sizeof(*ucd->interfaces)); if(ucd->interfaces == NULL) goto free_and_error; memset(ucd->interfaces,0,ucd->bNumInterfaces* sizeof(*ucd->interfaces)); for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; memcpy(uid, ptr, USB_DT_INTERFACE_SIZE); ptr += uid->bLength; size -= uid->bLength; uid->endpoints = USB_Alloc(uid->bNumEndpoints* sizeof(*uid->endpoints)); if(uid->endpoints == NULL) goto free_and_error; memset(uid->endpoints,0,uid->bNumEndpoints* sizeof(*uid->endpoints)); // This skips vendor and class specific descriptors i = __find_next_endpoint(ptr, size); uid->extra_size = i; if(i>0) { uid->extra = USB_Alloc(i); if(uid->extra == NULL) goto free_and_error; memcpy(uid->extra, ptr, i); ptr += i; size -= i; } for(iEndpoint = 0; iEndpoint < uid->bNumEndpoints; iEndpoint++) { ued = &uid->endpoints[iEndpoint]; memcpy(ued, ptr, USB_DT_ENDPOINT_SIZE); ptr += ued->bLength; ued->wMaxPacketSize = cpu_to_le16(ued->wMaxPacketSize); } } USB_Free( buffer); buffer = NULL; } retval = 0; free_and_error: if(buffer != NULL) USB_Free(buffer); if(retval < 0) USB_FreeDescriptors(udd); return retval; }
s32 USB_GetDescriptors(s32 fd, usb_devdesc *udd) { u8 *buffer = NULL; u8 *ptr = NULL; usb_configurationdesc *ucd = NULL; usb_interfacedesc *uid = NULL; usb_endpointdesc *ued = NULL; s32 retval = 0; u32 iConf, iInterface, iEndpoint; buffer = iosAlloc(hId, sizeof(*udd)); if(buffer == NULL) { retval = IPC_ENOHEAP; goto free_and_error; } retval = __usb_getdesc(fd, buffer, USB_DT_DEVICE, 0, USB_DT_DEVICE_SIZE); if(retval < 0) goto free_and_error; memcpy(udd, buffer, USB_DT_DEVICE_SIZE); iosFree(hId, buffer); udd->bcdUSB = bswap16(udd->bcdUSB); udd->idVendor = bswap16(udd->idVendor); udd->idProduct = bswap16(udd->idProduct); udd->bcdDevice = bswap16(udd->bcdDevice); udd->configurations = calloc(udd->bNumConfigurations, sizeof(*udd->configurations)); if(udd->configurations == NULL) { retval = IPC_ENOMEM; goto free_and_error; } for(iConf = 0; iConf < udd->bNumConfigurations; iConf++) { buffer = iosAlloc(hId, USB_DT_CONFIG_SIZE); if(buffer == NULL) { retval = IPC_ENOHEAP; goto free_and_error; } retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, USB_DT_CONFIG_SIZE); ucd = &udd->configurations[iConf]; memcpy(ucd, buffer, USB_DT_CONFIG_SIZE); iosFree(hId, buffer); ucd->wTotalLength = bswap16(ucd->wTotalLength); buffer = iosAlloc(hId, ucd->wTotalLength); if(buffer == NULL) { retval = IPC_ENOHEAP; goto free_and_error; } retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, ucd->wTotalLength); if(retval < 0) goto free_and_error; ptr = buffer; ptr += ucd->bLength; retval = IPC_ENOMEM; ucd->interfaces = calloc(ucd->bNumInterfaces, sizeof(*ucd->interfaces)); if(ucd->interfaces == NULL) goto free_and_error; for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; memcpy(uid, ptr, USB_DT_INTERFACE_SIZE); ptr += uid->bLength; uid->endpoints = calloc(uid->bNumEndpoints, sizeof(*uid->endpoints)); if(uid->endpoints == NULL) goto free_and_error; for(iEndpoint = 0; iEndpoint < uid->bNumEndpoints; iEndpoint++) { ued = &uid->endpoints[iEndpoint]; memcpy(ued, ptr, USB_DT_ENDPOINT_SIZE); ptr += ued->bLength; ued->wMaxPacketSize = bswap16(ued->wMaxPacketSize); } } iosFree(hId, buffer); buffer = NULL; } retval = IPC_OK; free_and_error: if(buffer != NULL) iosFree(hId, buffer); if(retval < 0) USB_FreeDescriptors(udd); return retval; }