static bool __usbstorage_Shutdown(void) { if (__vid != 0 || __pid != 0) USBStorage_Close(&__usbfd); return true; }
/* 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_Write_Sectors(u32 sector, u32 numSectors, const void *buffer) { s32 retval; if(__mounted != 1) return false; retval = USBStorage_Write(&__usbfd, __lun, sector, numSectors, buffer); if(retval == USBSTORAGE_ETIMEDOUT) { __mounted = 0; USBStorage_Close(&__usbfd); } if(retval < 0) return false; return true; }
void USBStorage_Umount(void) { if (!ums_init_done) return; ehci_device_data * device_data = find_ehci_data(ehci); if (__mounted && !unplug_device) { if (__usbstorage_start_stop(&__usbfd, __lun, 0x0) == 0) // stop ehci_msleep(1000); } USBStorage_Close(&__usbfd); __lun = 16; __mounted = 0; ums_init_done = 0; unplug_device = 0; //unregister_bdev(__bdev); }
/* 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; }
/* perform 512 time the same read */ s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer) { s32 retval; int i; ehci_device_data * device_data = find_ehci_data(ehci); if (__mounted != 1) return FALSE; for (i = 0; i < 512; i++) { retval = USBStorage_Read(__ehci, &__usbfd, __lun, sector, numSectors, buffer); sector += numSectors; if (retval == USBSTORAGE_ETIMEDOUT) { __mounted = 0; USBStorage_Close(&__usbfd); } if (retval < 0) return FALSE; } return TRUE; }
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, 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; }
static s32 __usb_deviceremoved_cb(s32 retval,void *arg) { __mounted = false; if(__vid != 0) USBStorage_Close(&__usbfd); return 0; }
static bool __usbstorage_IsInserted(void) { usb_device_entry *buffer; u8 device_count; u8 i, j; u16 vid, pid; s32 maxLun; s32 retval; #ifdef DEBUG_USB usb_log("__usbstorage_IsInserted\n"); if(__mounted) usb_log("device previously mounted.\n"); #endif if(__mounted) return true; if(!__inited) return false; buffer = (usb_device_entry*)__lwp_heap_allocate(&__heap, DEVLIST_MAXSIZE * sizeof(usb_device_entry)); if (!buffer) return false; memset(buffer, 0, DEVLIST_MAXSIZE * sizeof(usb_device_entry)); if (USB_GetDeviceList(buffer, DEVLIST_MAXSIZE, USB_CLASS_MASS_STORAGE, &device_count) < 0) { if (__vid != 0 || __pid != 0) USBStorage_Close(&__usbfd); __lwp_heap_free(&__heap, buffer); usb_log("Error in USB_GetDeviceList\n"); return false; } usleep(100); if (__vid != 0 || __pid != 0) { for(i = 0; i < device_count; i++) { vid = buffer[i].vid; pid = buffer[i].pid; if(vid != 0 || pid != 0) { if((vid == __vid) && (pid == __pid)) { __mounted = true; __lwp_heap_free(&__heap,buffer); usleep(50); // I don't know why I have to wait but it's needed return true; } } } USBStorage_Close(&__usbfd); // device changed or unplugged, return false the first time to notify to the client that he must unmount devices __lwp_heap_free(&__heap,buffer); usb_log("USB_GetDeviceList. device_count: %i\n",device_count); return false; } usb_log("USB_GetDeviceList. device_count: %i\n",device_count); for (i = 0; i < device_count; i++) { vid = buffer[i].vid; pid = buffer[i].pid; if (vid == 0 || pid == 0) continue; if (USBStorage_Open(&__usbfd, buffer[i].device_id, vid, pid) < 0) { usb_log("Error USBStorage_Open (%i,%i)\n",vid, pid); continue; } maxLun = USBStorage_GetMaxLUN(&__usbfd); usb_log("GetMaxLUN: %i\n",maxLun); for (j = 0; j < maxLun; j++) { retval = USBStorage_MountLUN(&__usbfd, j); if(retval<0) usb_log("Error USBStorage_MountLUN(%i): %i\n",j,retval); else usb_log("USBStorage_MountLUN(%i) Ok\n",j); //if (retval == USBSTORAGE_ETIMEDOUT) // break; if (retval < 0) { __usbstorage_reset(&__usbfd); continue; } __mounted = true; __lun = j; __vid = vid; __pid = pid; usb_last_used = gettime()-secs_to_ticks(100); usleep(100); #ifdef DEBUG_USB { u8 bf[2048]; if(USBStorage_Read(&__usbfd, __lun, 0, 1, bf)<0) { usb_log("Error reading sector 0\n"); USBStorage_Close(&__usbfd); return false; } else usb_log("Read sector 0 ok\n"); } #endif break; } if (__mounted) break; USBStorage_Close(&__usbfd); } __lwp_heap_free(&__heap, buffer); return __mounted; }