port-work; won't compile or even work
[ppcskel.git] / usb / drivers / class / storage.c
1 /*
2  * storage.c -- Bulk-only USB mass storage support
3  *
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>
7  * All rights reserved.
8  *
9  *
10  * Redistribution and use in source and binary forms, with or without 
11  * modification, are permitted provided that the following conditions 
12  * are met:
13  *
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.
23  *
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.
35  */
36
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"
43
44 #include "storage.h"
45
46
47 #define MAX_DEVICES 2
48
49 void usb_storage_probe();
50 void usb_storage_check();
51
52 struct usb_device *massstorage[MAX_DEVICES];
53 u16 sectorsize[MAX_DEVICES];
54 u8 massstorage_in_use;
55
56 struct usb_driver storage = {
57         .name     = "storage",
58         .probe  = usb_storage_probe,
59         .check  = usb_storage_check,
60         .data     = NULL
61 };
62
63 void usb_storage_init()
64 {
65         massstorage_in_use = 0;
66         usb_register_driver(&storage);  
67 }
68
69
70 void usb_storage_probe()
71 {
72         // schaue ob aktuell enumeriertes geraet ein storage ist
73         #if DEBUG
74         core.stdout("Probe: Storage\r\n");
75         #endif
76  
77         /* read interface descriptor for class code */
78         u8 buf[32];
79         
80         struct usb_device* dev;
81         struct element * iterator = core.devices->head;
82         
83         while(iterator != NULL) {
84                 dev = (struct usb_device*)iterator->data;
85
86                 /* get interface descriptor */
87                 usb_control_msg(dev, 0x80, GET_DESCRIPTOR,2, 0, 32, buf, 0);
88
89                 if(buf[14]==MASS_STORAGE_CLASSCODE){
90                         massstorage[massstorage_in_use] = dev;
91                         massstorage_in_use++;
92                         #if DEBUG
93                         core.stdout("Storage: Found Storage Device\r\n");
94                         #endif 
95
96                         /* here is only my lib driver test */
97                         usb_storage_open(0);
98                         usb_storage_inquiry(0);
99                         usb_storage_read_capacity(0);
100
101                         //char * buf = (char*)malloc(512);
102                         //free(buf);
103                         //char buf[512];
104                         //usb_storage_read_sector(0,1,buf);
105
106                         /* end of driver test */
107                 }
108
109                 iterator=iterator->next;
110         }
111 }
112
113
114 void usb_storage_check()
115 {
116         // wird periodisch augerufen
117         // da ein mass storage aber keinen interrupt oder isochronen endpunkt
118         // hat passiert hier nichts
119 }
120
121
122
123 u8 usb_storage_inquiry(u8 device)
124 {
125         /* send cwb "usbc" */
126         
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;
131         cbw->bCWDFlags=0x80;
132         cbw->bCBWLun=0x00;
133         cbw->bCBWCBLength=0x01;
134
135         u8 i;
136         for(i=0;i<16;i++)
137                 cbw->CBWCB[i]=0x00;
138
139         cbw->CBWCB[0]=0x12; // 0x12 = INQUIRY
140
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); 
144
145         free(cbw);
146
147         return 0;
148 }
149
150
151 u8 usb_storage_read_capacity(u8 device)
152 {
153         /* send cwb "usbc" */
154
155         u8 tmp[8];
156         u8 i;
157         usb_storage_cbw  * cbw = (usb_storage_cbw*)malloc(sizeof(usb_storage_cbw));
158
159         usb_control_msg(massstorage[device], 0x02,1,0, 0x8100, 0,tmp, 0);
160
161         cbw->dCBWSignature= 0x43425355;
162         cbw->dCBWTag=0x826A6008;
163         cbw->dCBWDataTransferLength=0x00000008;
164         cbw->bCWDFlags=0x80;
165         cbw->bCBWLun=0x00;
166         cbw->bCBWCBLength=0x0A;
167
168         for(i=0;i<16;i++)
169                 cbw->CBWCB[i]=0x00;
170
171         cbw->CBWCB[0]=0x25; // 0x12 = INQUIRY
172
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); 
176
177         free(cbw);
178
179         return 0;
180 }
181
182
183 u8 usb_storage_read_sector(u8 device, u32 sector, char * buf)
184 {
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,
192                 0x00,
193                 0x00,0x00,0x00,0x00,0x00};
194
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); 
198
199         
200         return 0;
201 }
202
203
204 u8 usb_storage_write_sector(u8 device, u32 sector, char * buf)
205 {
206
207         return 0;
208 }
209
210 #define TAG_START                       0x0BADC0DE
211
212 #define CBW_SIZE                        31
213 #define CBW_SIGNATURE                   0x43425355
214 #define CBW_IN                          (1 << 7)
215 #define CBW_OUT                         0
216
217 #define CSW_SIZE                        13
218 #define CSW_SIGNATURE                   0x53425355
219
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
225
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
230
231 #define USB_CLASS_MASS_STORAGE          0x08
232 #define MASS_STORAGE_SCSI_COMMANDS      0x06
233 #define MASS_STORAGE_BULK_ONLY          0x50
234
235 #define USBSTORAGE_GET_MAX_LUN          0xFE
236 #define USBSTORAGE_RESET                0xFF
237
238 #define USB_ENDPOINT_BULK               0x02
239
240 #define USBSTORAGE_CYCLE_RETRIES        3
241
242 #define MAX_TRANSFER_SIZE                       4096
243
244 #define DEVLIST_MAXSIZE    8
245
246 /*
247 The following is for implementing a DISC_INTERFACE 
248 as used by libfat
249 */
250
251 static usbstorage_handle __usbfd;
252 static u8 __lun = 0;
253 static u8 __mounted = 0;
254 static u16 __vid = 0;
255 static u16 __pid = 0;
256
257 static s32 __usbstorage_reset(usbstorage_handle *dev);
258 static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun);
259
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..
264  */
265
266 static s32 __usb_deviceremoved_cb(s32 retval,void *arg)
267 {
268         return 0;
269 }
270
271 static s32 __USB_BlkMsgTimeout(usbstorage_handle *dev, u8 bEndpoint, u16 wLength, void *rpData)
272 {
273         s32 retval;
274
275         dev->retval = USBSTORAGE_PROCESSING;
276         retval = USB_WriteBlkMsgAsync(dev->usb_fd, bEndpoint, wLength, rpData, (void *)dev);
277         dev->retval = retval;
278
279         if(retval==USBSTORAGE_ETIMEDOUT) 
280                 USBStorage_Close(dev);
281         return retval;
282 }
283
284 static s32 __USB_CtrlMsgTimeout(usbstorage_handle *dev, u8 bmRequestType, u8 bmRequest, u16 wValue, u16 wIndex, u16 wLength, void *rpData)
285 {
286         s32 retval;
287
288         dev->retval = USBSTORAGE_PROCESSING;
289         retval = USB_WriteCtrlMsgAsync(dev->usb_fd, bmRequestType, bmRequest, wValue, wIndex, wLength, rpData, (void *)dev);
290         dev->retval = retval;
291
292         if(retval==USBSTORAGE_ETIMEDOUT)
293                 USBStorage_Close(dev);
294         return retval;
295 }
296
297 s32 USBStorage_Initialize()
298 {
299         return 0;
300 }
301
302 static s32 __send_cbw(usbstorage_handle *dev, u8 lun, u32 len, u8 flags, const u8 *cb, u8 cbLen)
303 {
304         s32 retval = USBSTORAGE_OK;
305
306         if(cbLen == 0 || cbLen > 16)
307                 return -1;
308         
309         memset(dev->buffer, 0, CBW_SIZE);
310
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);
317
318         memcpy(dev->buffer + 15, cb, cbLen);
319
320         if(dev->suspended == 1)
321         {
322                 USB_ResumeDevice(dev->usb_fd);
323                 dev->suspended = 0;
324         }
325
326         retval = __USB_BlkMsgTimeout(dev, dev->ep_out, CBW_SIZE, (void *)dev->buffer);
327
328         if(retval == CBW_SIZE) return USBSTORAGE_OK;
329         else if(retval > 0) return USBSTORAGE_ESHORTWRITE;
330
331         return retval;
332 }
333
334 static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue)
335 {
336         s32 retval = USBSTORAGE_OK;
337         u32 signature, tag, _dataResidue, _status;
338
339         memset(dev->buffer, 0, CSW_SIZE);
340
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;
344
345         signature = __lwbrx(dev->buffer, 0);
346         tag = __lwbrx(dev->buffer, 4);
347         _dataResidue = __lwbrx(dev->buffer, 8);
348         _status = dev->buffer[12];
349
350         if(signature != CSW_SIGNATURE) return USBSTORAGE_ESIGNATURE;
351
352         if(dataResidue != NULL)
353                 *dataResidue = _dataResidue;
354         if(status != NULL)
355                 *status = _status;
356
357         if(tag != dev->tag) return USBSTORAGE_ETAG;
358         dev->tag++;
359
360         return USBSTORAGE_OK;
361 }
362
363 static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, u8 cbLen, u8 write, u8 *_status, u32 *_dataResidue)
364 {
365         s32 retval = USBSTORAGE_OK;
366
367         u8 status = 0;
368         u32 dataResidue = 0;
369         u32 thisLen;
370
371         s8 retries = USBSTORAGE_CYCLE_RETRIES + 1;
372
373         do
374         {
375                 retries--;
376
377                 if(retval == USBSTORAGE_ETIMEDOUT)
378                         break;
379
380                 if(write)
381                 {
382                         retval = __send_cbw(dev, lun, len, CBW_OUT, cb, cbLen);
383                         if(retval == USBSTORAGE_ETIMEDOUT)
384                                 break;
385                         if(retval < 0)
386                         {
387                                 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
388                                         retval = USBSTORAGE_ETIMEDOUT;
389                                 continue;
390                         }
391                         while(len > 0)
392                         {
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);
397
398                                 if(retval == USBSTORAGE_ETIMEDOUT)
399                                         break;
400
401                                 if(retval < 0)
402                                 {
403                                         retval = USBSTORAGE_EDATARESIDUE;
404                                         break;
405                                 }
406
407
408                                 if(retval != thisLen && len > 0)
409                                 {
410                                         retval = USBSTORAGE_EDATARESIDUE;
411                                         break;
412                                 }
413                                 len -= retval;
414                                 buffer += retval;
415                         }
416
417                         if(retval < 0)
418                         {
419                                 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
420                                         retval = USBSTORAGE_ETIMEDOUT;
421                                 continue;
422                         }
423                 }
424                 else
425                 {
426                         retval = __send_cbw(dev, lun, len, CBW_IN, cb, cbLen);
427
428                         if(retval == USBSTORAGE_ETIMEDOUT)
429                                 break;
430
431                         if(retval < 0)
432                         {
433                                 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
434                                         retval = USBSTORAGE_ETIMEDOUT;
435                                 continue;
436                         }
437                         while(len > 0)
438                         {
439                                 thisLen = len > MAX_TRANSFER_SIZE ? MAX_TRANSFER_SIZE : len;
440                                 retval = __USB_BlkMsgTimeout(dev, dev->ep_in, thisLen, dev->buffer);
441                                 if(retval < 0)
442                                         break;
443
444                                 memcpy(buffer, dev->buffer, retval);
445                                 len -= retval;
446                                 buffer += retval;
447
448                                 if(retval != thisLen)
449                                         break;
450                         }
451
452                         if(retval < 0)
453                         {
454                                 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
455                                         retval = USBSTORAGE_ETIMEDOUT;
456                                 continue;
457                         }
458                 }
459
460                 retval = __read_csw(dev, &status, &dataResidue);
461
462                 if(retval == USBSTORAGE_ETIMEDOUT)
463                         break;
464
465                 if(retval < 0)
466                 {
467                         if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
468                                 retval = USBSTORAGE_ETIMEDOUT;
469                         continue;
470                 }
471
472                 retval = USBSTORAGE_OK;
473         } while(retval < 0 && retries > 0);
474
475         if(retval < 0 && retval != USBSTORAGE_ETIMEDOUT)
476         {
477                 if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT)
478                         retval = USBSTORAGE_ETIMEDOUT;
479         }
480
481
482         if(_status != NULL)
483                 *_status = status;
484         if(_dataResidue != NULL)
485                 *_dataResidue = dataResidue;
486
487         return retval;
488 }
489
490 static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun)
491 {
492         s32 retval;
493         u8 cmd[16];
494         u8 sense[SCSI_SENSE_REPLY_SIZE];
495         u8 status = 0;
496
497         memset(cmd, 0, sizeof(cmd));
498         cmd[0] = SCSI_TEST_UNIT_READY;
499
500         retval = __cycle(dev, lun, NULL, 0, cmd, 1, 0, &status, NULL);
501         if(retval < 0) return retval;
502
503         if(status != 0)
504         {
505                 cmd[0] = SCSI_REQUEST_SENSE;
506                 cmd[1] = lun << 5;
507                 cmd[4] = SCSI_SENSE_REPLY_SIZE;
508                 cmd[5] = 0;
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;
512
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;
515         }
516
517         return retval;
518 }
519
520 static s32 __usbstorage_reset(usbstorage_handle *dev)
521 {
522         s32 retval;
523
524         if(dev->suspended == 1)
525         {
526                 USB_ResumeDevice(dev->usb_fd);
527                 dev->suspended = 0;
528         }
529
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);
542
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)
545                 goto end;
546
547         /* gives device enough time to process the reset */
548         usleep(60);
549
550         retval = USB_ClearHalt(dev->usb_fd, dev->ep_in);
551         if(retval < 0)
552                 goto end;
553         retval = USB_ClearHalt(dev->usb_fd, dev->ep_out);
554
555 end:
556         return retval;
557 }
558
559 s32 USBStorage_Open(usbstorage_handle *dev, const char *bus, u16 vid, u16 pid)
560 {
561         s32 retval = -1;
562         u8 conf,*max_lun = NULL;
563         u32 iConf, iInterface, iEp;
564         usb_devdesc udd;
565         usb_configurationdesc *ucd;
566         usb_interfacedesc *uid;
567         usb_endpointdesc *ued;
568
569         max_lun = malloc(1);
570         if(max_lun==NULL) return IPC_ENOMEM;
571
572         memset(dev, 0, sizeof(*dev));
573
574         dev->tag = TAG_START;
575
576         retval = USB_OpenDevice(bus, vid, pid, &dev->usb_fd);
577         if(retval < 0)
578                 goto free_and_return;
579
580         retval = USB_GetDescriptors(dev->usb_fd, &udd);
581         if(retval < 0)
582                 goto free_and_return;
583
584         for(iConf = 0; iConf < udd.bNumConfigurations; iConf++)
585         {
586                 ucd = &udd.configurations[iConf];               
587                 for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++)
588                 {
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)
593                         {
594                                 if(uid->bNumEndpoints < 2)
595                                         continue;
596
597                                 dev->ep_in = dev->ep_out = 0;
598                                 for(iEp = 0; iEp < uid->bNumEndpoints; iEp++)
599                                 {
600                                         ued = &uid->endpoints[iEp];
601                                         if(ued->bmAttributes != USB_ENDPOINT_BULK)
602                                                 continue;
603
604                                         if(ued->bEndpointAddress & USB_ENDPOINT_IN)
605                                                 dev->ep_in = ued->bEndpointAddress;
606                                         else
607                                                 dev->ep_out = ued->bEndpointAddress;
608                                 }
609                                 if(dev->ep_in != 0 && dev->ep_out != 0)
610                                 {
611                                         dev->configuration = ucd->bConfigurationValue;
612                                         dev->interface = uid->bInterfaceNumber;
613                                         dev->altInterface = uid->bAlternateSetting;
614                                         goto found;
615                                 }
616                         }
617                 }
618         }
619
620         USB_FreeDescriptors(&udd);
621         retval = USBSTORAGE_ENOINTERFACE;
622         goto free_and_return;
623
624 found:
625         USB_FreeDescriptors(&udd);
626
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;
634         dev->suspended = 0;
635
636         retval = USBStorage_Reset(dev);
637         if(retval < 0)
638                 goto free_and_return;
639
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);
641         if(retval < 0)
642                 dev->max_lun = 1;
643         else
644                 dev->max_lun = *max_lun;
645
646         
647         if(retval == USBSTORAGE_ETIMEDOUT)
648                 goto free_and_return;
649
650         retval = USBSTORAGE_OK;
651         dev->sector_size = (u32 *)calloc(dev->max_lun, sizeof(u32));
652         if(dev->sector_size == NULL)
653         {
654                 retval = IPC_ENOMEM;
655                 goto free_and_return;
656         }
657
658         if(dev->max_lun == 0)
659                 dev->max_lun++;
660
661         /* taken from linux usbstorage module (drivers/usb/storage/transport.c) */
662         /*
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).
667          */
668         USB_ClearHalt(dev->usb_fd, dev->ep_in);
669         USB_ClearHalt(dev->usb_fd, dev->ep_out);
670
671         dev->buffer = malloc(MAX_TRANSFER_SIZE);
672         
673         if(dev->buffer == NULL) retval = IPC_ENOMEM;
674         else {
675                 USB_DeviceRemovalNotifyAsync(dev->usb_fd,__usb_deviceremoved_cb,dev);
676                 retval = USBSTORAGE_OK;
677         }
678
679 free_and_return:
680         if(max_lun!=NULL) free(max_lun);
681         if(retval < 0)
682         {
683                 USB_CloseDevice(&dev->usb_fd);
684                 if(dev->buffer != NULL)
685                         free(dev->buffer);
686                 if(dev->sector_size != NULL)
687                         free(dev->sector_size);
688                 memset(dev, 0, sizeof(*dev));
689                 return retval;
690         }
691         return 0;
692 }
693
694 s32 USBStorage_Close(usbstorage_handle *dev)
695 {
696         USB_CloseDevice(&dev->usb_fd);
697         if(dev->sector_size!=NULL)
698                 free(dev->sector_size);
699         if(dev->buffer!=NULL)
700                 free(dev->buffer);
701         memset(dev, 0, sizeof(*dev));
702         return 0;
703 }
704
705 s32 USBStorage_Reset(usbstorage_handle *dev)
706 {
707         s32 retval;
708
709         retval = __usbstorage_reset(dev);
710
711         return retval;
712 }
713
714 s32 USBStorage_GetMaxLUN(usbstorage_handle *dev)
715 {
716         return dev->max_lun;
717 }
718
719 s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun)
720 {
721         s32 retval;
722
723         if(lun >= dev->max_lun)
724                 return IPC_EINVAL;
725
726         retval = __usbstorage_clearerrors(dev, lun);
727         if(retval < 0)
728                 return retval;
729
730         retval = USBStorage_ReadCapacity(dev, lun, &dev->sector_size[lun], NULL);
731         return retval;
732 }
733
734 s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors)
735 {
736         s32 retval;
737         u8 cmd[] = {SCSI_READ_CAPACITY, lun << 5};
738         u8 response[8];
739
740         retval = __cycle(dev, lun, response, 8, cmd, 2, 0, NULL, NULL);
741         if(retval >= 0)
742         {
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;
748         }
749
750         return retval;
751 }
752
753 s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer)
754 {
755         u8 status = 0;
756         s32 retval;
757         u8 cmd[] = {
758                 SCSI_READ_10,
759                 lun << 5,
760                 sector >> 24,
761                 sector >> 16,
762                 sector >>  8,
763                 sector,
764                 0,
765                 n_sectors >> 8,
766                 n_sectors,
767                 0
768                 };
769         if(lun >= dev->max_lun || dev->sector_size[lun] == 0)
770                 return IPC_EINVAL;
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;
774         return retval;
775 }
776
777 s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer)
778 {
779         u8 status = 0;
780         s32 retval;
781         u8 cmd[] = {
782                 SCSI_WRITE_10,
783                 lun << 5,
784                 sector >> 24,
785                 sector >> 16,
786                 sector >> 8,
787                 sector,
788                 0,
789                 n_sectors >> 8,
790                 n_sectors,
791                 0
792                 };
793         if(lun >= dev->max_lun || dev->sector_size[lun] == 0)
794                 return IPC_EINVAL;
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;
798         return retval;
799 }
800
801 s32 USBStorage_Suspend(usbstorage_handle *dev)
802 {
803         if(dev->suspended == 1)
804                 return USBSTORAGE_OK;
805
806         USB_SuspendDevice(dev->usb_fd);
807         dev->suspended = 1;
808
809         return USBSTORAGE_OK;
810
811 }
812
813 /*
814 The following is for implementing a DISC_INTERFACE 
815 as used by libfat
816 */
817
818 static BOOL __usbstorage_IsInserted(void);
819
820 static BOOL __usbstorage_Startup(void)
821 {
822         USB_Initialize();
823         USBStorage_Initialize();
824         return __usbstorage_IsInserted();
825 }
826
827 static BOOL __usbstorage_IsInserted(void)
828 {
829    u8 *buffer;
830    u8 dummy;
831    u8 i, j;
832    u16 vid, pid;
833    s32 maxLun;
834    s32 retval;
835
836    __mounted = 0;               //reset it here and check if device is still attached
837
838    buffer = malloc(DEVLIST_MAXSIZE << 3);
839    if(buffer == NULL)
840        return FALSE;
841    memset(buffer, 0, DEVLIST_MAXSIZE << 3);
842
843    if(USB_GetDeviceList("/dev/usb/oh0", buffer, DEVLIST_MAXSIZE, 0, &dummy) < 0)
844    {
845        if(__vid!=0 || __pid!=0) USBStorage_Close(&__usbfd);
846        memset(&__usbfd, 0, sizeof(__usbfd));
847        __lun = 0;
848        __vid = 0;
849        __pid = 0;
850
851        free(buffer);
852        return FALSE;
853    }
854
855    if(__vid!=0 || __pid!=0)
856    {
857        for(i = 0; i < DEVLIST_MAXSIZE; i++)
858        {
859            memcpy(&vid, (buffer + (i << 3) + 4), 2);
860            memcpy(&pid, (buffer + (i << 3) + 6), 2);
861            if(vid != 0 || pid != 0)
862            {
863
864                if( (vid == __vid) && (pid == __pid))
865                {
866                    __mounted = 1;
867                                    free(buffer);
868                    usleep(50); // I don't know why I have to wait but it's needed
869                    return TRUE;
870                }
871            }
872        }
873        USBStorage_Close(&__usbfd);
874    }
875
876    memset(&__usbfd, 0, sizeof(__usbfd));
877    __lun = 0;
878    __vid = 0;
879    __pid = 0;
880
881    for(i = 0; i < DEVLIST_MAXSIZE; i++)
882    {
883        memcpy(&vid, (buffer + (i << 3) + 4), 2);
884        memcpy(&pid, (buffer + (i << 3) + 6), 2);
885        if(vid == 0 || pid == 0)
886            continue;
887
888        if(USBStorage_Open(&__usbfd, "oh0", vid, pid) < 0)
889            continue;
890
891        maxLun = USBStorage_GetMaxLUN(&__usbfd);
892        for(j = 0; j < maxLun; j++)
893        {
894            retval = USBStorage_MountLUN(&__usbfd, j);
895            if(retval == USBSTORAGE_ETIMEDOUT)
896            {
897                break;
898            }
899
900            if(retval < 0)
901                continue;
902
903            __mounted = 1;
904            __lun = j;
905            __vid = vid;
906            __pid = pid;
907            i = DEVLIST_MAXSIZE;
908            break;
909        }
910    }
911    free(buffer);
912    if(__mounted == 1)
913        return TRUE;
914    return FALSE;
915 }
916
917 static BOOL __usbstorage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
918 {
919    s32 retval;
920
921    if(__mounted != 1)
922        return FALSE;
923
924    retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer);
925    if(retval == USBSTORAGE_ETIMEDOUT)
926    {
927        __mounted = 0;
928    }
929    if(retval < 0)
930        return FALSE;
931    return TRUE;
932 }
933
934 static BOOL __usbstorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
935 {
936    s32 retval;
937
938    if(__mounted != 1)
939        return FALSE;
940
941    retval = USBStorage_Write(&__usbfd, __lun, sector, numSectors, buffer);
942    if(retval == USBSTORAGE_ETIMEDOUT)
943    {
944        __mounted = 0;
945    }
946    if(retval < 0)
947        return FALSE;
948    return TRUE;
949 }
950
951 static BOOL __usbstorage_ClearStatus(void)
952 {
953    return TRUE;
954 }
955
956 static BOOL __usbstorage_Shutdown(void)
957 {
958    //if(__mounted == 1) USBStorage_Close(&__usbfd);
959    __mounted = 0;
960    return TRUE;
961 }
962
963 const DISC_INTERFACE __io_usbstorage = {
964    DEVICE_TYPE_WII_USB,
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
972 };
973