static s32 __usbstorage_reset(usbstorage_handle *dev) { s32 retval; /* retval = ehci_reset_device(dev->usb_fd); if(retval < 0 && retval != -7004) goto end; */ //debug_printf("usbstorage reset..\n"); USB_LOG("Resetting device.\n"); retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL); /* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */ if(retval < 0 && retval != -7004) goto end; /* gives device enough time to process the reset */ usleep(10); USB_LOG("Clearing halts on both endpoints\n"); //debug_printf("cleat halt on bulk ep..\n"); retval = (*context.interface)->ClearPipeStallBothEnds(context.interface, dev->ep_in); if(retval < 0) goto end; retval = (*context.interface)->ClearPipeStallBothEnds(context.interface, dev->ep_out); end: return retval; }
static s32 __usbstorage_reset(usbstorage_handle *dev) { s32 retval; if(dev->suspended == 1) { USB_ResumeDevice(dev->usb_fd); dev->suspended = 0; } /* retval = ehci_reset_device(dev->usb_fd); if(retval < 0 && retval != -7004) goto end; */ //debug_printf("usbstorage reset..\n"); retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL); /* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */ if(retval < 0 && retval != -7004) goto end; /* gives device enough time to process the reset */ msleep(10); //debug_printf("cleat halt on bulk ep..\n"); retval = USB_ClearHalt(dev->usb_fd, dev->ep_in); if(retval < 0) goto end; retval = USB_ClearHalt(dev->usb_fd, dev->ep_out); end: return retval; }
static s32 __usbstorage_reset(usbstorage_handle *dev) { u32 t = usbtimeout; usbtimeout = 1; s32 retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL); usbtimeout = t; usleep(60*1000); USB_OGC_ClearHalt(dev->usb_fd, dev->ep_in);usleep(10000); //from http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf USB_OGC_ClearHalt(dev->usb_fd, dev->ep_out);usleep(10000); return retval; }
s32 USBStorageOGC_Open(usbstorage_handle *dev, s32 device_id, u16 vid, u16 pid) { s32 retval = -1; u8 conf = -1; u8 *max_lun; u32 iConf, iInterface, iEp; usb_devdesc udd; usb_configurationdesc *ucd; usb_interfacedesc *uid; usb_endpointdesc *ued; max_lun = __lwp_heap_allocate(&__heap, 1); if (!max_lun) return IPC_ENOMEM; memset(dev, 0, sizeof(*dev)); dev->usb_fd = -1; dev->tag = TAG_START; if (LWP_MutexInit(&dev->lock, false) < 0) goto free_and_return; if (SYS_CreateAlarm(&dev->alarm) < 0) goto free_and_return; retval = USB_OGC_OpenDevice(device_id, vid, pid, &dev->usb_fd); if (retval < 0) goto free_and_return; retval = USB_OGC_GetDescriptors(dev->usb_fd, &udd); if (retval < 0) goto free_and_return; for (iConf = 0; iConf < udd.bNumConfigurations; iConf++) { ucd = &udd.configurations[iConf]; for (iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; if(uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && /* (uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_RBC_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_ATA_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_QIC_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_UFI_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_SFF8070_COMMANDS) &&*/ uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY) { if (uid->bNumEndpoints < 2) continue; dev->ep_in = dev->ep_out = 0; for (iEp = 0; iEp < uid->bNumEndpoints; iEp++) { ued = &uid->endpoints[iEp]; if (ued->bmAttributes != USB_ENDPOINT_BULK) continue; if (ued->bEndpointAddress & USB_ENDPOINT_IN) { dev->ep_in = ued->bEndpointAddress; } else { dev->ep_out = ued->bEndpointAddress; if(ued->wMaxPacketSize > 64 && (dev->usb_fd>=0x20 || dev->usb_fd<-1)) usb2_mode=true; else usb2_mode=false; } } if (dev->ep_in != 0 && dev->ep_out != 0) { dev->configuration = ucd->bConfigurationValue; dev->interface = uid->bInterfaceNumber; dev->altInterface = uid->bAlternateSetting; goto found; } } } } USB_OGC_FreeDescriptors(&udd); retval = USBSTORAGE_ENOINTERFACE; goto free_and_return; found: dev->bInterfaceSubClass = uid->bInterfaceSubClass; USB_OGC_FreeDescriptors(&udd); retval = USBSTORAGE_EINIT; // some devices return an error, ignore it USB_OGC_GetConfiguration(dev->usb_fd, &conf); if (conf != dev->configuration) USB_OGC_SetConfiguration(dev->usb_fd, dev->configuration); if (dev->altInterface !=0) USB_OGC_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface); if(!usb2_mode) retval = USBStorageOGC_Reset(dev); dev->suspended = 0; LWP_MutexLock(dev->lock); retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun); LWP_MutexUnlock(dev->lock); if (retval < 0) dev->max_lun = 1; else dev->max_lun = *max_lun + 1; if (retval == USBSTORAGE_ETIMEDOUT) goto free_and_return; retval = USBSTORAGE_OK; dev->sector_size = (u32 *) calloc(dev->max_lun, sizeof(u32)); if(!dev->sector_size) { retval = IPC_ENOMEM; goto free_and_return; } /* taken from linux usbstorage module (drivers/usb/storage/transport.c) * * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices * (regardless of if they stall or not). * * 8/9/10: If anyone wants to actually use a Zip100, they can add this back. * But for now, it seems to be breaking things more than it is helping. */ //USB_ClearHalt(dev->usb_fd, dev->ep_in); //USB_ClearHalt(dev->usb_fd, dev->ep_out); if(!dev->buffer) dev->buffer = __lwp_heap_allocate(&__heap, MAX_TRANSFER_SIZE_V5); if(!dev->buffer) { retval = IPC_ENOMEM; } else { USB_OGC_DeviceRemovalNotifyAsync(dev->usb_fd,__usb_deviceremoved_cb,dev); retval = USBSTORAGE_OK; } free_and_return: if (max_lun) __lwp_heap_free(&__heap, max_lun); if (retval < 0) { USBStorageOGC_Close(dev); return retval; } return 0; }
static s32 __usbstorage_reset(struct ehci_hcd * ehci, usbstorage_handle *dev, int hard_reset) { s32 retval; u32 old_usb_timeout = usb_timeout; usb_timeout = 1000 * 1000; //int retry = hard_reset; int retry = 0; //first try soft reset retry: if (retry >= 1) { u8 conf; debug_printf("reset device..\n"); retval = ehci_reset_device(ehci, dev->usb_fd); ehci_msleep(10); if (retval == -ENODEV) return retval; if (retval < 0 && retval != -7004) goto end; // reset configuration if (USB_GetConfiguration(ehci, dev->usb_fd, &conf) < 0) goto end; if (/*conf != dev->configuration &&*/ USB_SetConfiguration(ehci, dev->usb_fd, dev->configuration) < 0) goto end; if (dev->altInterface != 0 && USB_SetAlternativeInterface(ehci, dev->usb_fd, dev->interface, dev->altInterface) < 0) goto end; // find the device with the same ehci ptr ehci_device_data * _device_data = find_ehci_data(ehci); if (_device_data->__lun != 16) { if (USBStorage_MountLUN(ehci, &_device_data->__usbfd, _device_data->__lun) < 0) goto end; } } debug_printf("usbstorage reset..\n"); retval = __USB_CtrlMsgTimeout(ehci, dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL); #ifdef MEM_PRINT s_printf("usbstorage reset: Reset ret %i\n", retval); #endif /* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */ if (retval < 0 && retval != -7004) goto end; /* gives device enough time to process the reset */ ehci_msleep(10); debug_printf("clear halt on bulk ep..\n"); retval = USB_ClearHalt(ehci, dev->usb_fd, dev->ep_in); #ifdef MEM_PRINT s_printf("usbstorage reset: clearhalt in ret %i\n", retval); #endif if (retval < 0) goto end; ehci_msleep(10); retval = USB_ClearHalt(ehci, dev->usb_fd, dev->ep_out); #ifdef MEM_PRINT s_printf("usbstorage reset: clearhalt in ret %i\n", retval); #endif if (retval < 0) goto end; ehci_msleep(50); usb_timeout = old_usb_timeout; return retval; end: if (retval == -ENODEV) return retval; #ifdef HOMEBREW if (disable_hardreset) return retval; if (retry < 1) { //only 1 hard reset ehci_msleep(100); debug_printf("retry with hard reset..\n"); retry++; goto retry; } #else if (retry < 5) { ehci_msleep(100); debug_printf("retry with hard reset..\n"); retry++; goto retry; } #endif usb_timeout = old_usb_timeout; return retval; }
s32 USBStorage_Try_Device(ehci_device_data * device_data) { struct ehci_hcd * ehci; struct ehci_device *fd; int maxLun, j, retval; int test_max_lun = 1; ehci = device_data->__ehci; fd = device_data->__dev; try_status = -120; if (USBStorage_Open(device_data) < 0) return -EINVAL; /* maxLun = USBStorage_GetMaxLUN(&__usbfd); if(maxLun == USBSTORAGE_ETIMEDOUT) { __mounted = 0; USBStorage_Close(&__usbfd); return -EINVAL; } */ maxLun = 1; device_data->__usbfd.max_lun = 1; j = 0; //for(j = 0; j < maxLun; j++) while (1) { #ifdef MEM_PRINT s_printf("USBStorage_MountLUN %i#\n", j); #endif retval = USBStorage_MountLUN(ehci, &device_data->__usbfd, j); #ifdef MEM_PRINT s_printf("USBStorage_MountLUN: ret %i\n", retval); #endif if (retval == USBSTORAGE_ETIMEDOUT /*&& test_max_lun==0*/) { //USBStorage_Reset(&__usbfd); try_status = -121; device_data->__mounted = 0; USBStorage_Close(&device_data->__usbfd); return -EINVAL; // break; } if (retval < 0) { if (test_max_lun) { device_data->__usbfd.max_lun = 0; retval = __USB_CtrlMsgTimeout(ehci, &device_data->__usbfd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, device_data->__usbfd.interface, 1, &device_data->__usbfd.max_lun); if (retval < 0) device_data->__usbfd.max_lun = 1; else device_data->__usbfd.max_lun++; maxLun =device_data-> __usbfd.max_lun; #ifdef MEM_PRINT s_printf("USBSTORAGE_GET_MAX_LUN ret %i maxlun %i\n", retval, maxLun); #endif test_max_lun = 0; } else j++; if (j >= maxLun) break; continue; } device_data->__vid = fd->desc.idVendor; device_data->__pid = fd->desc.idProduct; device_data->__mounted = 1; device_data->__lun = j; usb_timeout = 1000 * 1000; try_status = 0; return 0; } try_status = -122; device_data->__mounted = 0; USBStorage_Close(&device_data->__usbfd); #ifdef MEM_PRINT s_printf("USBStorage_MountLUN fail!!!\n"); #endif return -EINVAL; }
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) { s32 retval = -1; u8 conf,*max_lun = NULL; u32 iConf, iInterface, iEp; usb_devdesc udd; usb_configurationdesc *ucd; usb_interfacedesc *uid; usb_endpointdesc *ued; max_lun = USB_Alloc(1); if(max_lun==NULL) return -ENOMEM; memset(dev, 0, sizeof(*dev)); dev->tag = TAG_START; dev->usb_fd = fd; retval = USB_GetDescriptors(dev->usb_fd, &udd); if(retval < 0) goto free_and_return; for(iConf = 0; iConf < udd.bNumConfigurations; iConf++) { ucd = &udd.configurations[iConf]; for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; if(uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS && uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY) { if(uid->bNumEndpoints < 2) continue; dev->ep_in = dev->ep_out = 0; for(iEp = 0; iEp < uid->bNumEndpoints; iEp++) { ued = &uid->endpoints[iEp]; if(ued->bmAttributes != USB_ENDPOINT_BULK) continue; if(ued->bEndpointAddress & USB_ENDPOINT_IN) dev->ep_in = ued->bEndpointAddress; else dev->ep_out = ued->bEndpointAddress; } if(dev->ep_in != 0 && dev->ep_out != 0) { dev->configuration = ucd->bConfigurationValue; dev->interface = uid->bInterfaceNumber; dev->altInterface = uid->bAlternateSetting; goto found; } } } } USB_FreeDescriptors(&udd); retval = USBSTORAGE_ENOINTERFACE; goto free_and_return; found: USB_FreeDescriptors(&udd); retval = USBSTORAGE_EINIT; if(USB_GetConfiguration(dev->usb_fd, &conf) < 0) goto free_and_return; if(conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) goto free_and_return; if(dev->altInterface != 0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) goto free_and_return; dev->suspended = 0; retval = USBStorage_Reset(dev); if(retval < 0) goto free_and_return; retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun); if(retval < 0) dev->max_lun = 1; else dev->max_lun = *max_lun; if(retval == USBSTORAGE_ETIMEDOUT) goto free_and_return; retval = USBSTORAGE_OK; if(dev->max_lun == 0) dev->max_lun++; /* taken from linux usbstorage module (drivers/usb/storage/transport.c) */ /* * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices * (regardless of if they stall or not). */ USB_ClearHalt(dev->usb_fd, dev->ep_in); USB_ClearHalt(dev->usb_fd, dev->ep_out); dev->buffer = USB_Alloc(MAX_TRANSFER_SIZE); if(dev->buffer == NULL) retval = -ENOMEM; else retval = USBSTORAGE_OK; free_and_return: if(max_lun!=NULL) USB_Free(max_lun); if(retval < 0) { if(dev->buffer != NULL) USB_Free(dev->buffer); memset(dev, 0, sizeof(*dev)); return retval; } return 0; }