s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun) { s32 retval; if(lun >= dev->max_lun) return IPC_EINVAL; usleep(50); retval = __usbstorage_clearerrors(dev, lun); if (retval<0) { usb_log("Error __usbstorage_clearerrors: %i. Reset & retry again.\n",retval); USBStorage_Reset(dev); retval = __usbstorage_clearerrors(dev, lun); if (retval<0) usb_log("Error __usbstorage_clearerrors(2): %i.\n",retval); //return retval; } else usb_log("__usbstorage_clearerrors Ok\n"); retval = USBStorage_Inquiry(dev, lun); usb_log("USBStorage_Inquiry: %i\n", retval); retval = USBStorage_ReadCapacity(dev, lun, &dev->sector_size[lun], NULL); usb_log("USBStorage_ReadCapacity: %i sector size: %i\n", retval,dev->sector_size[lun]); return retval; }
/* perform 512 time the same read */ s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer) { s32 retval; int i; if(__mounted != 1) return false; for(i=0;i<512;i++){ retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer); sector+=numSectors; if(retval == USBSTORAGE_ETIMEDOUT) { __mounted = 0; USBStorage_Close(&__usbfd); } if(retval < 0) return false; } return true; } // temp function before libfat is available */ s32 USBStorage_Try_Device(struct ehci_device *fd) { int maxLun,j,retval; if(USBStorage_Open(&__usbfd, fd) < 0) return -EINVAL; maxLun = USBStorage_GetMaxLUN(&__usbfd); if(maxLun == USBSTORAGE_ETIMEDOUT) return -EINVAL; for(j = 0; j < maxLun; j++) { retval = USBStorage_MountLUN(&__usbfd, j); if(retval == USBSTORAGE_ETIMEDOUT) { USBStorage_Reset(&__usbfd); USBStorage_Close(&__usbfd); break; } if(retval < 0) continue; (*context.device)->GetDeviceVendor(context.device, &__vid); (*context.device)->GetDeviceProduct(context.device, &__pid); __mounted = 1; __lun = j; return 0; } return -EINVAL; }
s32 USBStorage_Open(ehci_device_data * device_data) { s32 retval = -1; u8 conf, *max_lun = NULL; u32 iConf, iInterface, iEp; static usb_devdesc udd; usb_configurationdesc *ucd; usb_interfacedesc *uid; usb_endpointdesc *ued; struct ehci_hcd * ehci = device_data->__ehci; usbstorage_handle *dev = &device_data->__usbfd; struct ehci_device *fd = device_data->__dev; device_data->__lun = 16; // select bad LUN 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(ehci, dev->usb_fd, &udd); #ifdef MEM_PRINT s_printf("USBStorage_Open(): USB_GetDescriptors %i\n", retval); #ifdef MEM_PRINT log_status(ehci, "after USB_GetDescriptors"); #endif #endif if (retval < 0) goto free_and_return; /* // test device changed without unmount (prevent device write corruption) if (ums_init_done) { if (my_memcmp((void *) &_old_udd, (void *) &udd, sizeof (usb_devdesc) - 4)) { USB_Free(max_lun); USB_FreeDescriptors(&udd); #ifdef MEM_PRINT s_printf("USBStorage_Open(): device changed!!!\n"); #endif return -ENODEV; } } */ _old_udd = udd; try_status = -128; for (iConf = 0; iConf < udd.bNumConfigurations; iConf++) { ucd = &udd.configurations[iConf]; for (iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; // debug_printf("interface %d, class:%x subclass %x protocol %x\n",iInterface,uid->bInterfaceClass,uid->bInterfaceSubClass, uid->bInterfaceProtocol); 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 && uid->bNumEndpoints >= 2) { dev->ata_protocol = 0; if (uid->bInterfaceSubClass != MASS_STORAGE_SCSI_COMMANDS || uid->bInterfaceSubClass != MASS_STORAGE_RBC_COMMANDS) dev->ata_protocol = 1; #ifdef MEM_PRINT s_printf("USBStorage_Open(): interface subclass %i ata_prot %i \n", uid->bInterfaceSubClass, dev->ata_protocol); #endif 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; } } else { if (uid->endpoints != NULL) USB_Free(uid->endpoints); uid->endpoints = NULL; if (uid->extra != NULL) USB_Free(uid->extra); uid->extra = NULL; if (uid->bInterfaceClass == USB_CLASS_HUB) { retval = USBSTORAGE_ENOINTERFACE; try_status = -20000; USB_FreeDescriptors(&udd); goto free_and_return; } if (uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY && uid->bNumEndpoints >= 2) { try_status = -(10000 + uid->bInterfaceSubClass); } } } } #ifdef MEM_PRINT s_printf("USBStorage_Open(): cannot find any interface!!!\n"); #endif USB_FreeDescriptors(&udd); retval = USBSTORAGE_ENOINTERFACE; debug_printf("cannot find any interface\n"); goto free_and_return; found: USB_FreeDescriptors(&udd); retval = USBSTORAGE_EINIT; try_status = -1201; #ifdef MEM_PRINT s_printf("USBStorage_Open(): conf: %x altInterface: %x\n", dev->configuration, dev->altInterface); #endif if (USB_GetConfiguration(ehci, dev->usb_fd, &conf) < 0) goto free_and_return; try_status = -1202; #ifdef MEM_PRINT log_status(ehci, "after USB_GetConfiguration"); #endif #ifdef MEM_PRINT if (conf != dev->configuration) s_printf("USBStorage_Open(): changing conf from %x\n", conf); #endif if (/*conf != dev->configuration &&*/ USB_SetConfiguration(ehci, dev->usb_fd, dev->configuration) < 0) goto free_and_return; try_status = -1203; if (dev->altInterface != 0 && USB_SetAlternativeInterface(ehci, dev->usb_fd, dev->interface, dev->altInterface) < 0) goto free_and_return; try_status = -1204; #ifdef MEM_PRINT log_status(ehci, "Before USBStorage_Reset"); #endif retval = USBStorage_Reset(ehci, dev); #ifdef MEM_PRINT log_status(ehci, "After USBStorage_Reset"); #endif 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+1); if(retval == USBSTORAGE_ETIMEDOUT)*/ /* NOTE: from usbmassbulk_10.pdf "Devices that do not support multiple LUNs may STALL this command." */ dev->max_lun = 8; // max_lun can be from 1 to 16, but some devices do not support lun 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 + 16); if (dev->buffer == NULL) { retval = -ENOMEM; try_status = -1205; } 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)); #ifdef MEM_PRINT s_printf("USBStorage_Open(): try_status %i\n", try_status); #endif return retval; } #ifdef MEM_PRINT s_printf("USBStorage_Open(): return 0\n"); #endif return 0; }
s32 USBStorage_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; bool reset_flag = false; 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; usb_log("USBStorage_Open id: %i\n",device_id); if (LWP_MutexInit(&dev->lock, false) < 0) goto free_and_return; if (SYS_CreateAlarm(&dev->alarm) < 0) goto free_and_return; retry_init: retval = USB_OpenDevice(device_id, vid, pid, &dev->usb_fd); usb_log("USB_OpenDevice, ret: %i\n",retval); if (retval < 0) goto free_and_return; retval = USB_GetDescriptors(dev->usb_fd, &udd); if (retval < 0) { usb_log("USB_GetDescriptors error, ret: %i\n",retval); goto free_and_return; } else usb_log("USB_GetDescriptors OK, configurations: %i\n",udd.bNumConfigurations); for (iConf = 0; iConf < udd.bNumConfigurations; iConf++) { ucd = &udd.configurations[iConf]; usb_log(" Configuration: %i\n",iConf); for (iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; usb_log(" Interface: %i InterfaceClass: 0x%x numendpoints: %i\n",iInterface,uid->bInterfaceClass,uid->bNumEndpoints); 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; usb_log(" USB_ENDPOINT_BULK found: 0x%x MaxPacketSize: %i\n",ued->bEndpointAddress,ued->wMaxPacketSize); 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_log("Device not found device\n"); USB_FreeDescriptors(&udd); retval = USBSTORAGE_ENOINTERFACE; goto free_and_return; found: usb_log("Found device, InterfaceSubClass: %i\n",uid->bInterfaceSubClass); dev->bInterfaceSubClass = uid->bInterfaceSubClass; USB_FreeDescriptors(&udd); retval = USBSTORAGE_EINIT; // some devices return an error, ignore it USB_GetConfiguration(dev->usb_fd, &conf); if(method==0 || method==4) { if (conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) { usb_log("Error USB_SetConfiguration\n"); goto free_and_return; } else usb_log("USB_SetConfiguration ok\n"); if (dev->altInterface !=0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) { usb_log("Error USB_SetAlternativeInterface, alt: %i int: %i\n",dev->altInterface,dev->interface); goto free_and_return; } else usb_log("USB_SetAlternativeInterface ok, alt: %i int: %i\n",dev->altInterface,dev->interface); dev->suspended = 0; if(!reset_flag && dev->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS) { reset_flag = true; retval = USBStorage_Reset(dev); usb_log("USBStorage_Open, USBStorage_Reset: %i\n",retval); if (retval < 0) { USB_CloseDevice(&dev->usb_fd); goto retry_init; } } } else if(method==1) { if ( USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) { usb_log("Error USB_SetConfiguration\n"); } else usb_log("USB_SetConfiguration ok\n"); if (USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) { usb_log("Error USB_SetAlternativeInterface, alt: %i int: %i\n",dev->altInterface,dev->interface); } else usb_log("USB_SetAlternativeInterface ok, alt: %i int: %i\n",dev->altInterface,dev->interface); dev->suspended = 0; } else if(method==2) { if ( USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) { usb_log("Error USB_SetConfiguration\n"); } else usb_log("USB_SetConfiguration ok\n"); if (USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) { usb_log("Error USB_SetAlternativeInterface, alt: %i int: %i\n",dev->altInterface,dev->interface); } else usb_log("USB_SetAlternativeInterface ok, alt: %i int: %i\n",dev->altInterface,dev->interface); dev->suspended = 0; if(!reset_flag && dev->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS) { reset_flag = true; retval = USBStorage_Reset(dev); usb_log("USBStorage_Open, USBStorage_Reset: %i\n",retval); if (retval < 0) { USB_CloseDevice(&dev->usb_fd); goto retry_init; } } } else if(method==3) { if (USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) { usb_log("Error USB_SetConfiguration\n"); goto free_and_return; } else usb_log("USB_SetConfiguration ok\n"); if (dev->altInterface !=0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) { usb_log("Error USB_SetAlternativeInterface, alt: %i int: %i\n",dev->altInterface,dev->interface); goto free_and_return; } else usb_log("USB_SetAlternativeInterface ok, alt: %i int: %i\n",dev->altInterface,dev->interface); dev->suspended = 0; retval = USBStorage_Reset(dev); usb_log("USBStorage_Open, USBStorage_Reset: %i\n",retval); } else if(method==5 || method==6) { if (conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) { usb_log("Error USB_SetConfiguration\n"); //goto free_and_return; } else usb_log("USB_SetConfiguration ok\n"); if (dev->altInterface !=0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) { usb_log("Error USB_SetAlternativeInterface, alt: %i int: %i\n",dev->altInterface,dev->interface); //goto free_and_return; } else usb_log("USB_SetAlternativeInterface ok, alt: %i int: %i\n",dev->altInterface,dev->interface); if(!usb2_mode) { retval = USBStorage_Reset(dev); usb_log("USBStorage_Open, USBStorage_Reset: %i\n",retval); } dev->suspended = 0; } if(method==6) { dev->max_lun = 2; usb_log("No get max lun call, max_lun: %i\n",dev->max_lun); } else { 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; usb_log("USBSTORAGE_GET_MAX_LUN, ret: %i max_lun: %i\n",retval,dev->max_lun); } 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_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) { USBStorage_Close(dev); return retval; } return 0; }
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; }