static s32 __send_cbw(usbstorage_handle *dev, u8 lun, u32 len, u8 flags, const u8 *cb, u8 cbLen) { s32 retval = USBSTORAGE_OK; if(cbLen == 0 || cbLen > 16) return IPC_EINVAL; memset(dev->buffer, 0, CBW_SIZE); __stwbrx(dev->buffer, 0, CBW_SIGNATURE); __stwbrx(dev->buffer, 4, ++dev->tag); __stwbrx(dev->buffer, 8, len); dev->buffer[12] = flags; dev->buffer[13] = lun; dev->buffer[14] = (cbLen > 6 ? 10 : 6); memcpy(dev->buffer + 15, cb, cbLen); if(dev->suspended == 1) { USB_ResumeDevice(dev->usb_fd); dev->suspended = 0; } retval = __USB_BlkMsgTimeout(dev, dev->ep_out, CBW_SIZE, (void *)dev->buffer, usbtimeout); if(retval == CBW_SIZE) return USBSTORAGE_OK; else if(retval > 0) return USBSTORAGE_ESHORTWRITE; 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; }
s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer) { u8 status = 0; s32 retval; u8 cmd[] = { SCSI_WRITE_10, lun << 5, sector >> 24, sector >> 16, sector >> 8, sector, 0, n_sectors >> 8, n_sectors, 0 }; if(lun >= dev->max_lun || dev->sector_size[lun] == 0) return IPC_EINVAL; // more than 60s since last use - make sure drive is awake if(ticks_to_secs(gettime() - usb_last_used) > 60) { usbtimeout = 10; if(method==0) { USB_ResumeDevice(dev->usb_fd); if(dev->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS) { retval = __usbstorage_clearerrors(dev, lun); if (retval < 0) return retval; retval = USBStorage_StartStop(dev, lun, 0, 1, 0); if (retval < 0) return retval; } } else if(method==2) { __usbstorage_clearerrors(dev, lun); } } retval = __cycle(dev, lun, (u8 *)buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 1, &status, NULL); if(retval > 0 && status != 0) retval = USBSTORAGE_ESTATUS; usb_last_used = gettime(); usbtimeout = USBSTORAGE_TIMEOUT; return retval; }
s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer) { u8 status = 0; s32 retval; u8 cmd[] = { SCSI_READ_10, lun << 5, sector >> 24, sector >> 16, sector >> 8, sector, 0, n_sectors >> 8, n_sectors, 0 }; usb_log("USBStorage_Read sector: %i num: %i\n",sector,n_sectors); if(lun >= dev->max_lun || dev->sector_size[lun] == 0) return IPC_EINVAL; // more than 60s since last use - make sure drive is awake if(ticks_to_secs(gettime() - usb_last_used) > 60) { usbtimeout = 10; usb_log("usbtimeout = 10\n"); if(method==0) { retval = USB_ResumeDevice(dev->usb_fd); usb_log("USB_ResumeDevice ret: %i\n",retval); if(dev->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS) { retval = __usbstorage_clearerrors(dev, lun); usb_log("__usbstorage_clearerrors ret: %i\n",retval); if (retval < 0) return retval; retval = USBStorage_StartStop(dev, lun, 0, 1, 0); usb_log("USBStorage_StartStop ret: %i\n",retval); if (retval < 0) return retval; } } else if(method==2) { retval = __usbstorage_clearerrors(dev, lun); usb_log("__usbstorage_clearerrors ret: %i\n",retval); } else if(method==3) { retval = __usbstorage_clearerrors(dev, lun); usb_log("__usbstorage_clearerrors ret: %i\n",retval); retval = USBStorage_StartStop(dev, lun, 0, 1, 0); usb_log("USBStorage_StartStop ret: %i\n",retval); usleep(100); } } retval = __cycle(dev, lun, buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 0, &status, NULL); usb_log("USBStorage_Read __cycle ret: %i status: %i\n",retval,status); if(retval > 0 && status != 0) retval = USBSTORAGE_ESTATUS; usb_last_used = gettime(); usbtimeout = USBSTORAGE_TIMEOUT; usb_log("usbtimeout = %i\n",usbtimeout); return retval; }