2 * storage.c -- Bulk-only USB mass storage support
4 * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
5 * Copyright (C) 2008, Sven Peter (svpe) <svpe@gmx.net>
6 * Copyright (C) 2010, Bernhard Urban <lewurm@gmx.net>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * * Neither the name of the FH Augsburg nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include "../../core/core.h"
38 #include "../../core/usb.h"
39 #include "../../usbspec/usb11spec.h"
40 #include "../../../malloc.h"
41 #include "../../../string.h"
42 #include "../../../irq.h"
49 void usb_storage_probe();
50 void usb_storage_check();
52 struct usb_device *massstorage[MAX_DEVICES];
53 u16 sectorsize[MAX_DEVICES];
54 u8 massstorage_in_use;
56 struct usb_driver storage = {
58 .probe = usb_storage_probe,
59 .check = usb_storage_check,
63 void usb_storage_init()
65 massstorage_in_use = 0;
66 usb_register_driver(&storage);
70 void usb_storage_probe()
72 // schaue ob aktuell enumeriertes geraet ein storage ist
74 core.stdout("Probe: Storage\r\n");
77 /* read interface descriptor for class code */
80 struct usb_device* dev;
81 struct element * iterator = core.devices->head;
83 while(iterator != NULL) {
84 dev = (struct usb_device*)iterator->data;
86 /* get interface descriptor */
87 usb_control_msg(dev, 0x80, GET_DESCRIPTOR,2, 0, 32, buf, 0);
89 if(buf[14]==MASS_STORAGE_CLASSCODE){
90 massstorage[massstorage_in_use] = dev;
93 core.stdout("Storage: Found Storage Device\r\n");
96 /* here is only my lib driver test */
98 usb_storage_inquiry(0);
99 usb_storage_read_capacity(0);
101 //char * buf = (char*)malloc(512);
104 //usb_storage_read_sector(0,1,buf);
106 /* end of driver test */
109 iterator=iterator->next;
114 void usb_storage_check()
116 // wird periodisch augerufen
117 // da ein mass storage aber keinen interrupt oder isochronen endpunkt
118 // hat passiert hier nichts
123 u8 usb_storage_inquiry(u8 device)
125 /* send cwb "usbc" */
127 usb_storage_cbw *cbw = (usb_storage_cbw*)malloc(sizeof(usb_storage_cbw));
128 cbw->dCBWSignature= 0x43425355;
129 cbw->dCBWTag=0x826A6008;
130 cbw->dCBWDataTransferLength=0x00000024;
133 cbw->bCBWCBLength=0x01;
139 cbw->CBWCB[0]=0x12; // 0x12 = INQUIRY
141 usb_bulk_write(massstorage[device], 2, (u8*)cbw, 31, 0);
142 usb_bulk_read(massstorage[device], 1, (u8*)cbw, 36, 0);
143 usb_bulk_read(massstorage[device], 1, (u8*)cbw, 13, 0);
151 u8 usb_storage_read_capacity(u8 device)
153 /* send cwb "usbc" */
157 usb_storage_cbw * cbw = (usb_storage_cbw*)malloc(sizeof(usb_storage_cbw));
159 usb_control_msg(massstorage[device], 0x02,1,0, 0x8100, 0,tmp, 0);
161 cbw->dCBWSignature= 0x43425355;
162 cbw->dCBWTag=0x826A6008;
163 cbw->dCBWDataTransferLength=0x00000008;
166 cbw->bCBWCBLength=0x0A;
171 cbw->CBWCB[0]=0x25; // 0x12 = INQUIRY
173 usb_bulk_write(massstorage[device], 2, (u8*)cbw, 31, 0);
174 usb_bulk_read(massstorage[device], 1, (u8*)cbw, 8, 0);
175 usb_bulk_read(massstorage[device], 1, (u8*)cbw, 13, 0);
183 u8 usb_storage_read_sector(u8 device, u32 sector, char * buf)
185 /* send cwb "usbc" */
186 u8 tmpbuf[] = {0x55,0x53,0x42,0x43,0x08,
187 0xE0,0x63,0x82,0x00,0x02,
188 0x00,0x00,0x80,0x00,0x0A,
189 0x28,0x00,0x00,0x00,0x00,
190 0x00,0x00,0x00,0x01,0x00,
191 0x00,0x00,0x00,0x00,0x00,
193 0x00,0x00,0x00,0x00,0x00};
195 usb_bulk_write(massstorage[device], 2, tmpbuf, 31, 0);
196 //usb_bulk_read(massstorage[device], 1, buf,64,0);
197 //usb_bulk_read(massstorage[device], 1, buf, 13, 0);
204 u8 usb_storage_write_sector(u8 device, u32 sector, char * buf)
210 #define TAG_START 0x0BADC0DE
213 #define CBW_SIGNATURE 0x43425355
214 #define CBW_IN (1 << 7)
218 #define CSW_SIGNATURE 0x53425355
220 #define SCSI_TEST_UNIT_READY 0x00
221 #define SCSI_REQUEST_SENSE 0x03
222 #define SCSI_READ_CAPACITY 0x25
223 #define SCSI_READ_10 0x28
224 #define SCSI_WRITE_10 0x2A
226 #define SCSI_SENSE_REPLY_SIZE 18
227 #define SCSI_SENSE_NOT_READY 0x02
228 #define SCSI_SENSE_MEDIUM_ERROR 0x03
229 #define SCSI_SENSE_HARDWARE_ERROR 0x04
231 #define USB_CLASS_MASS_STORAGE 0x08
232 #define MASS_STORAGE_SCSI_COMMANDS 0x06
233 #define MASS_STORAGE_BULK_ONLY 0x50
235 #define USBSTORAGE_GET_MAX_LUN 0xFE
236 #define USBSTORAGE_RESET 0xFF
238 #define USB_ENDPOINT_BULK 0x02
240 #define USBSTORAGE_CYCLE_RETRIES 3
242 #define MAX_TRANSFER_SIZE 4096
244 #define DEVLIST_MAXSIZE 8
247 The following is for implementing a DISC_INTERFACE
251 static usbstorage_handle __usbfd;
253 static u8 __mounted = 0;
254 static u16 __vid = 0;
255 static u16 __pid = 0;
257 static s32 __usbstorage_reset(usbstorage_handle *dev);
258 static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun);
260 /* XXX: this is a *really* dirty and ugly way to send a bulkmessage with a timeout
261 * but there's currently no other known way of doing this and it's in my humble
262 * opinion still better than having a function blocking forever while waiting
263 * for the USB data/IOS reply..
266 static s32 __usb_deviceremoved_cb(s32 retval,void *arg)
271 static s32 __USB_BlkMsgTimeout(usbstorage_handle *dev, u8 bEndpoint, u16 wLength, void *rpData)
275 dev->retval = USBSTORAGE_PROCESSING;
276 retval = USB_WriteBlkMsgAsync(dev->usb_fd, bEndpoint, wLength, rpData, (void *)dev);
277 dev->retval = retval;
279 if(retval==USBSTORAGE_ETIMEDOUT)
280 USBStorage_Close(dev);
284 static s32 __USB_CtrlMsgTimeout(usbstorage_handle *dev, u8 bmRequestType, u8 bmRequest, u16 wValue, u16 wIndex, u16 wLength, void *rpData)
288 dev->retval = USBSTORAGE_PROCESSING;
289 retval = USB_WriteCtrlMsgAsync(dev->usb_fd, bmRequestType, bmRequest, wValue, wIndex, wLength, rpData, (void *)dev);
290 dev->retval = retval;
292 if(retval==USBSTORAGE_ETIMEDOUT)
293 USBStorage_Close(dev);
297 s32 USBStorage_Initialize()
302 static s32 __send_cbw(usbstorage_handle *dev, u8 lun, u32 len, u8 flags, const u8 *cb, u8 cbLen)
304 s32 retval = USBSTORAGE_OK;
306 if(cbLen == 0 || cbLen > 16)
309 memset(dev->buffer, 0, CBW_SIZE);
311 __stwbrx(dev->buffer, 0, CBW_SIGNATURE);
312 __stwbrx(dev->buffer, 4, dev->tag);
313 __stwbrx(dev->buffer, 8, len);
314 dev->buffer[12] = flags;
315 dev->buffer[13] = lun;
316 dev->buffer[14] = (cbLen > 6 ? 0x10 : 6);
318 memcpy(dev->buffer + 15, cb, cbLen);
320 if(dev->suspended == 1)
322 USB_ResumeDevice(dev->usb_fd);
326 retval = __USB_BlkMsgTimeout(dev, dev->ep_out, CBW_SIZE, (void *)dev->buffer);
328 if(retval == CBW_SIZE) return USBSTORAGE_OK;
329 else if(retval > 0) return USBSTORAGE_ESHORTWRITE;
334 static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue)
336 s32 retval = USBSTORAGE_OK;
337 u32 signature, tag, _dataResidue, _status;
339 memset(dev->buffer, 0, CSW_SIZE);
341 retval = __USB_BlkMsgTimeout(dev, dev->ep_in, CSW_SIZE, dev->buffer);
342 if(retval > 0 && retval != CSW_SIZE) return USBSTORAGE_ESHORTREAD;
343 else if(retval < 0) return retval;
345 signature = __lwbrx(dev->buffer, 0);
346 tag = __lwbrx(dev->buffer, 4);
347 _dataResidue = __lwbrx(dev->buffer, 8);
348 _status = dev->buffer[12];
350 if(signature != CSW_SIGNATURE) return USBSTORAGE_ESIGNATURE;
352 if(dataResidue != NULL)
353 *dataResidue = _dataResidue;
357 if(tag != dev->tag) return USBSTORAGE_ETAG;
360 return USBSTORAGE_OK;
363 static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, u8 cbLen, u8 write, u8 *_status, u32 *_dataResidue)
365 s32 retval = USBSTORAGE_OK;
371 s8 retries = USBSTORAGE_CYCLE_RETRIES + 1;
377 if(retval == USBSTORAGE_ETIMEDOUT)
382 retval = __send_cbw(dev, lun, len, CBW_OUT, cb, cbLen);
383 if(retval == USBSTORAGE_ETIMEDOUT)
387 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
388 retval = USBSTORAGE_ETIMEDOUT;
393 thisLen = len > MAX_TRANSFER_SIZE ? MAX_TRANSFER_SIZE : len;
394 memset(dev->buffer, 0, MAX_TRANSFER_SIZE);
395 memcpy(dev->buffer, buffer, thisLen);
396 retval = __USB_BlkMsgTimeout(dev, dev->ep_out, thisLen, dev->buffer);
398 if(retval == USBSTORAGE_ETIMEDOUT)
403 retval = USBSTORAGE_EDATARESIDUE;
408 if(retval != thisLen && len > 0)
410 retval = USBSTORAGE_EDATARESIDUE;
419 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
420 retval = USBSTORAGE_ETIMEDOUT;
426 retval = __send_cbw(dev, lun, len, CBW_IN, cb, cbLen);
428 if(retval == USBSTORAGE_ETIMEDOUT)
433 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
434 retval = USBSTORAGE_ETIMEDOUT;
439 thisLen = len > MAX_TRANSFER_SIZE ? MAX_TRANSFER_SIZE : len;
440 retval = __USB_BlkMsgTimeout(dev, dev->ep_in, thisLen, dev->buffer);
444 memcpy(buffer, dev->buffer, retval);
448 if(retval != thisLen)
454 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
455 retval = USBSTORAGE_ETIMEDOUT;
460 retval = __read_csw(dev, &status, &dataResidue);
462 if(retval == USBSTORAGE_ETIMEDOUT)
467 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
468 retval = USBSTORAGE_ETIMEDOUT;
472 retval = USBSTORAGE_OK;
473 } while(retval < 0 && retries > 0);
475 if(retval < 0 && retval != USBSTORAGE_ETIMEDOUT)
477 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
478 retval = USBSTORAGE_ETIMEDOUT;
484 if(_dataResidue != NULL)
485 *_dataResidue = dataResidue;
490 static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun)
494 u8 sense[SCSI_SENSE_REPLY_SIZE];
497 memset(cmd, 0, sizeof(cmd));
498 cmd[0] = SCSI_TEST_UNIT_READY;
500 retval = __cycle(dev, lun, NULL, 0, cmd, 1, 0, &status, NULL);
501 if(retval < 0) return retval;
505 cmd[0] = SCSI_REQUEST_SENSE;
507 cmd[4] = SCSI_SENSE_REPLY_SIZE;
509 memset(sense, 0, SCSI_SENSE_REPLY_SIZE);
510 retval = __cycle(dev, lun, sense, SCSI_SENSE_REPLY_SIZE, cmd, 6, 0, NULL, NULL);
511 if(retval < 0) return retval;
513 status = sense[2] & 0x0F;
514 if(status == SCSI_SENSE_NOT_READY || status == SCSI_SENSE_MEDIUM_ERROR || status == SCSI_SENSE_HARDWARE_ERROR) return USBSTORAGE_ESENSE;
520 static s32 __usbstorage_reset(usbstorage_handle *dev)
524 if(dev->suspended == 1)
526 USB_ResumeDevice(dev->usb_fd);
530 /* control message request type bitmask */
531 #define USB_CTRLTYPE_DIR_HOST2DEVICE (0<<7)
532 #define USB_CTRLTYPE_DIR_DEVICE2HOST (1<<7)
533 #define USB_CTRLTYPE_TYPE_STANDARD (0<<5)
534 #define USB_CTRLTYPE_TYPE_CLASS (1<<5)
535 #define USB_CTRLTYPE_TYPE_VENDOR (2<<5)
536 #define USB_CTRLTYPE_TYPE_RESERVED (3<<5)
537 #define USB_CTRLTYPE_REC_DEVICE 0
538 #define USB_CTRLTYPE_REC_INTERFACE 1
539 #define USB_CTRLTYPE_REC_ENDPOINT 2
540 #define USB_CTRLTYPE_REC_OTHER 3
541 retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL);
543 /* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */
544 if(retval < 0 && retval != -7004)
547 /* gives device enough time to process the reset */
550 retval = USB_ClearHalt(dev->usb_fd, dev->ep_in);
553 retval = USB_ClearHalt(dev->usb_fd, dev->ep_out);
559 s32 USBStorage_Open(usbstorage_handle *dev, const char *bus, u16 vid, u16 pid)
562 u8 conf,*max_lun = NULL;
563 u32 iConf, iInterface, iEp;
565 usb_configurationdesc *ucd;
566 usb_interfacedesc *uid;
567 usb_endpointdesc *ued;
570 if(max_lun==NULL) return IPC_ENOMEM;
572 memset(dev, 0, sizeof(*dev));
574 dev->tag = TAG_START;
576 retval = USB_OpenDevice(bus, vid, pid, &dev->usb_fd);
578 goto free_and_return;
580 retval = USB_GetDescriptors(dev->usb_fd, &udd);
582 goto free_and_return;
584 for(iConf = 0; iConf < udd.bNumConfigurations; iConf++)
586 ucd = &udd.configurations[iConf];
587 for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++)
589 uid = &ucd->interfaces[iInterface];
590 if(uid->bInterfaceClass == USB_CLASS_MASS_STORAGE &&
591 uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS &&
592 uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY)
594 if(uid->bNumEndpoints < 2)
597 dev->ep_in = dev->ep_out = 0;
598 for(iEp = 0; iEp < uid->bNumEndpoints; iEp++)
600 ued = &uid->endpoints[iEp];
601 if(ued->bmAttributes != USB_ENDPOINT_BULK)
604 if(ued->bEndpointAddress & USB_ENDPOINT_IN)
605 dev->ep_in = ued->bEndpointAddress;
607 dev->ep_out = ued->bEndpointAddress;
609 if(dev->ep_in != 0 && dev->ep_out != 0)
611 dev->configuration = ucd->bConfigurationValue;
612 dev->interface = uid->bInterfaceNumber;
613 dev->altInterface = uid->bAlternateSetting;
620 USB_FreeDescriptors(&udd);
621 retval = USBSTORAGE_ENOINTERFACE;
622 goto free_and_return;
625 USB_FreeDescriptors(&udd);
627 retval = USBSTORAGE_EINIT;
628 if(USB_GetConfiguration(dev->usb_fd, &conf) < 0)
629 goto free_and_return;
630 if(conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0)
631 goto free_and_return;
632 if(dev->altInterface != 0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0)
633 goto free_and_return;
636 retval = USBStorage_Reset(dev);
638 goto free_and_return;
640 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);
644 dev->max_lun = *max_lun;
647 if(retval == USBSTORAGE_ETIMEDOUT)
648 goto free_and_return;
650 retval = USBSTORAGE_OK;
651 dev->sector_size = (u32 *)calloc(dev->max_lun, sizeof(u32));
652 if(dev->sector_size == NULL)
655 goto free_and_return;
658 if(dev->max_lun == 0)
661 /* taken from linux usbstorage module (drivers/usb/storage/transport.c) */
663 * Some devices (i.e. Iomega Zip100) need this -- apparently
664 * the bulk pipes get STALLed when the GetMaxLUN request is
665 * processed. This is, in theory, harmless to all other devices
666 * (regardless of if they stall or not).
668 USB_ClearHalt(dev->usb_fd, dev->ep_in);
669 USB_ClearHalt(dev->usb_fd, dev->ep_out);
671 dev->buffer = malloc(MAX_TRANSFER_SIZE);
673 if(dev->buffer == NULL) retval = IPC_ENOMEM;
675 USB_DeviceRemovalNotifyAsync(dev->usb_fd,__usb_deviceremoved_cb,dev);
676 retval = USBSTORAGE_OK;
680 if(max_lun!=NULL) free(max_lun);
683 USB_CloseDevice(&dev->usb_fd);
684 if(dev->buffer != NULL)
686 if(dev->sector_size != NULL)
687 free(dev->sector_size);
688 memset(dev, 0, sizeof(*dev));
694 s32 USBStorage_Close(usbstorage_handle *dev)
696 USB_CloseDevice(&dev->usb_fd);
697 if(dev->sector_size!=NULL)
698 free(dev->sector_size);
699 if(dev->buffer!=NULL)
701 memset(dev, 0, sizeof(*dev));
705 s32 USBStorage_Reset(usbstorage_handle *dev)
709 retval = __usbstorage_reset(dev);
714 s32 USBStorage_GetMaxLUN(usbstorage_handle *dev)
719 s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun)
723 if(lun >= dev->max_lun)
726 retval = __usbstorage_clearerrors(dev, lun);
730 retval = USBStorage_ReadCapacity(dev, lun, &dev->sector_size[lun], NULL);
734 s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors)
737 u8 cmd[] = {SCSI_READ_CAPACITY, lun << 5};
740 retval = __cycle(dev, lun, response, 8, cmd, 2, 0, NULL, NULL);
743 if(n_sectors != NULL)
744 memcpy(n_sectors, response, 4);
745 if(sector_size != NULL)
746 memcpy(sector_size, response + 4, 4);
747 retval = USBSTORAGE_OK;
753 s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer)
769 if(lun >= dev->max_lun || dev->sector_size[lun] == 0)
771 retval = __cycle(dev, lun, buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 0, &status, NULL);
772 if(retval > 0 && status != 0)
773 retval = USBSTORAGE_ESTATUS;
777 s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer)
793 if(lun >= dev->max_lun || dev->sector_size[lun] == 0)
795 retval = __cycle(dev, lun, (u8 *)buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 1, &status, NULL);
796 if(retval > 0 && status != 0)
797 retval = USBSTORAGE_ESTATUS;
801 s32 USBStorage_Suspend(usbstorage_handle *dev)
803 if(dev->suspended == 1)
804 return USBSTORAGE_OK;
806 USB_SuspendDevice(dev->usb_fd);
809 return USBSTORAGE_OK;
814 The following is for implementing a DISC_INTERFACE
818 static BOOL __usbstorage_IsInserted(void);
820 static BOOL __usbstorage_Startup(void)
823 USBStorage_Initialize();
824 return __usbstorage_IsInserted();
827 static BOOL __usbstorage_IsInserted(void)
836 __mounted = 0; //reset it here and check if device is still attached
838 buffer = malloc(DEVLIST_MAXSIZE << 3);
841 memset(buffer, 0, DEVLIST_MAXSIZE << 3);
843 if(USB_GetDeviceList("/dev/usb/oh0", buffer, DEVLIST_MAXSIZE, 0, &dummy) < 0)
845 if(__vid!=0 || __pid!=0) USBStorage_Close(&__usbfd);
846 memset(&__usbfd, 0, sizeof(__usbfd));
855 if(__vid!=0 || __pid!=0)
857 for(i = 0; i < DEVLIST_MAXSIZE; i++)
859 memcpy(&vid, (buffer + (i << 3) + 4), 2);
860 memcpy(&pid, (buffer + (i << 3) + 6), 2);
861 if(vid != 0 || pid != 0)
864 if( (vid == __vid) && (pid == __pid))
868 usleep(50); // I don't know why I have to wait but it's needed
873 USBStorage_Close(&__usbfd);
876 memset(&__usbfd, 0, sizeof(__usbfd));
881 for(i = 0; i < DEVLIST_MAXSIZE; i++)
883 memcpy(&vid, (buffer + (i << 3) + 4), 2);
884 memcpy(&pid, (buffer + (i << 3) + 6), 2);
885 if(vid == 0 || pid == 0)
888 if(USBStorage_Open(&__usbfd, "oh0", vid, pid) < 0)
891 maxLun = USBStorage_GetMaxLUN(&__usbfd);
892 for(j = 0; j < maxLun; j++)
894 retval = USBStorage_MountLUN(&__usbfd, j);
895 if(retval == USBSTORAGE_ETIMEDOUT)
917 static BOOL __usbstorage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
924 retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer);
925 if(retval == USBSTORAGE_ETIMEDOUT)
934 static BOOL __usbstorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
941 retval = USBStorage_Write(&__usbfd, __lun, sector, numSectors, buffer);
942 if(retval == USBSTORAGE_ETIMEDOUT)
951 static BOOL __usbstorage_ClearStatus(void)
956 static BOOL __usbstorage_Shutdown(void)
958 //if(__mounted == 1) USBStorage_Close(&__usbfd);
963 const DISC_INTERFACE __io_usbstorage = {
965 FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
966 (FN_MEDIUM_STARTUP)&__usbstorage_Startup,
967 (FN_MEDIUM_ISINSERTED)&__usbstorage_IsInserted,
968 (FN_MEDIUM_READSECTORS)&__usbstorage_ReadSectors,
969 (FN_MEDIUM_WRITESECTORS)&__usbstorage_WriteSectors,
970 (FN_MEDIUM_CLEARSTATUS)&__usbstorage_ClearStatus,
971 (FN_MEDIUM_SHUTDOWN)&__usbstorage_Shutdown