PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
usb_driver.c
1/*
2 * usb_driver.c - USB Mass Storage Driver
3 * See usbmass-ufi10.pdf and usbmassbulk_10.pdf
4 */
5
6#include <errno.h>
7#include <sysclib.h>
8#include <thsemap.h>
9#include <stdio.h>
10#include <usbd.h>
11#include <usbd_macro.h>
12
13// #define DEBUG //comment out this line when not debugging
14
15#include "mass_debug.h"
16#include <usbhdfsd.h>
17#include "usbhd_common.h"
18#include "mass_stor.h"
19#include "scache.h"
20#include "part_driver.h"
21
22#define getBI32(__buf) ((((u8 *)(__buf))[3] << 0) | (((u8 *)(__buf))[2] << 8) | (((u8 *)(__buf))[1] << 16) | (((u8 *)(__buf))[0] << 24))
23
24#define USB_SUBCLASS_MASS_RBC 0x01
25#define USB_SUBCLASS_MASS_ATAPI 0x02
26#define USB_SUBCLASS_MASS_QIC 0x03
27#define USB_SUBCLASS_MASS_UFI 0x04
28#define USB_SUBCLASS_MASS_SFF_8070I 0x05
29#define USB_SUBCLASS_MASS_SCSI 0x06
30
31#define USB_PROTOCOL_MASS_CBI 0x00
32#define USB_PROTOCOL_MASS_CBI_NO_CCI 0x01
33#define USB_PROTOCOL_MASS_BULK_ONLY 0x50
34
35#define TAG_TEST_UNIT_READY 0
36#define TAG_REQUEST_SENSE 3
37#define TAG_INQUIRY 18
38#define TAG_READ_CAPACITY 37
39#define TAG_READ 40
40#define TAG_START_STOP_UNIT 33
41#define TAG_WRITE 42
42
43#define USB_BLK_EP_IN 0
44#define USB_BLK_EP_OUT 1
45
46#define USB_XFER_MAX_RETRIES 8
47#define USB_IO_MAX_RETRIES 16
48
49#define CBW_TAG 0x43425355
50#define CSW_TAG 0x53425355
51
52typedef struct _cbw_packet
53{
54 unsigned int signature;
55 unsigned int tag;
56 unsigned int dataTransferLength;
57 unsigned char flags; // 80->data in, 00->out
58 unsigned char lun;
59 unsigned char comLength; // command data length
60 unsigned char comData[16]; // command data
62
63typedef struct _csw_packet
64{
65 unsigned int signature;
66 unsigned int tag;
67 unsigned int dataResidue;
68 unsigned char status;
70
71typedef struct _inquiry_data
72{
73 u8 peripheral_device_type; // 00h - Direct access (Floppy), 1Fh none (no FDD connected)
74 u8 removable_media; // 80h - removeable
75 u8 iso_ecma_ansi;
76 u8 response_data_format;
77 u8 additional_length;
78 u8 res[3];
79 u8 vendor[8];
80 u8 product[16];
81 u8 revision[4];
83
84typedef struct _sense_data
85{
86 u8 error_code;
87 u8 res1;
88 u8 sense_key;
89 u8 information[4];
90 u8 add_sense_len;
91 u8 res3[4];
92 u8 add_sense_code;
93 u8 add_sense_qual;
94 u8 res4[4];
96
97typedef struct _read_capacity_data
98{
99 u8 last_lba[4];
100 u8 block_length[4];
102
103static sceUsbdLddOps driver;
104
105typedef struct _usb_callback_data
106{
107 int sema;
108 int returnCode;
109 int returnSize;
111
112#define USB_BLOCK_SIZE 4096 // Maximum single USB 1.1 transfer length.
113
115{
116 int sema;
117 int pipe;
118 u8 *buffer;
119 int returnCode;
120 unsigned int remaining;
122
123#define NUM_DEVICES 2
124static mass_dev g_mass_device[NUM_DEVICES];
125
126static void usb_callback(int resultCode, int bytes, void *arg);
127static int perform_bulk_transfer(usb_transfer_callback_data *data);
128static void usb_transfer_callback(int resultCode, int bytes, void *arg);
129static void mass_stor_release(mass_dev *dev);
130
131static void usb_callback(int resultCode, int bytes, void *arg)
132{
134 data->returnCode = resultCode;
135 data->returnSize = bytes;
136 XPRINTF("callback: res %d, bytes %d, arg %p \n", resultCode, bytes, arg);
137 SignalSema(data->sema);
138}
139
140static int perform_bulk_transfer(usb_transfer_callback_data *data)
141{
142 int ret, len;
143
144 len = data->remaining > USB_BLOCK_SIZE ? USB_BLOCK_SIZE : data->remaining;
145 ret = sceUsbdBulkTransfer(
146 data->pipe, // bulk pipe epI (Read) or epO (Write)
147 data->buffer, // data ptr
148 len, // data length
149 &usb_transfer_callback,
150 (void *)data);
151 return ret;
152}
153
154static void usb_transfer_callback(int resultCode, int bytes, void *arg)
155{
157
158 data->returnCode = resultCode;
159 if (resultCode == USB_RC_OK) { // Update transfer progress if successful.
160 data->remaining -= bytes;
161 data->buffer += bytes;
162 }
163
164 if ((resultCode == USB_RC_OK) && (data->remaining > 0)) { // OK to continue.
165 int ret;
166
167 ret = perform_bulk_transfer(data);
168 if (ret != USB_RC_OK) {
169 data->returnCode = ret;
170 SignalSema(data->sema);
171 }
172 } else {
173 SignalSema(data->sema);
174 }
175}
176
177static int usb_set_configuration(mass_dev *dev, int configNumber)
178{
179 int ret;
180 usb_callback_data cb_data;
181
182 cb_data.sema = dev->ioSema;
183
184 XPRINTF("setting configuration controlEp=%i, confNum=%i \n", dev->controlEp, configNumber);
185 ret = sceUsbdSetConfiguration(dev->controlEp, configNumber, usb_callback, (void *)&cb_data);
186
187 if (ret == USB_RC_OK) {
188 WaitSema(cb_data.sema);
189 ret = cb_data.returnCode;
190 }
191
192 return ret;
193}
194
195static int usb_set_interface(mass_dev *dev, int interface, int altSetting)
196{
197 int ret;
198 usb_callback_data cb_data;
199
200 cb_data.sema = dev->ioSema;
201
202 XPRINTF("setting interface controlEp=%i, interface=%i altSetting=%i\n", dev->controlEp, interface, altSetting);
203 ret = sceUsbdSetInterface(dev->controlEp, interface, altSetting, usb_callback, (void *)&cb_data);
204
205 if (ret == USB_RC_OK) {
206 WaitSema(cb_data.sema);
207 ret = cb_data.returnCode;
208 }
209
210 return ret;
211}
212
213static int usb_bulk_clear_halt(mass_dev *dev, int endpoint)
214{
215 int ret;
216 usb_callback_data cb_data;
217
218 cb_data.sema = dev->ioSema;
219
220 ret = sceUsbdClearEndpointFeature(
221 dev->controlEp, // Config pipe
222 0, // HALT feature
223 (endpoint == USB_BLK_EP_IN) ? dev->bulkEpI : dev->bulkEpO,
224 usb_callback,
225 (void *)&cb_data);
226
227 if (ret == USB_RC_OK) {
228 WaitSema(cb_data.sema);
229 ret = cb_data.returnCode;
230 }
231 if (ret != USB_RC_OK) {
232 printf("USBHDFSD: Error - sending clear halt %d\n", ret);
233 }
234
235 return ret;
236}
237
238static void usb_bulk_reset(mass_dev *dev, int mode)
239{
240 int ret;
241 usb_callback_data cb_data;
242
243 cb_data.sema = dev->ioSema;
244
245 // Call Bulk only mass storage reset
246 ret = sceUsbdControlTransfer(
247 dev->controlEp, // default pipe
248 0x21, // bulk reset
249 0xFF,
250 0,
251 dev->interfaceNumber, // interface number
252 0, // length
253 NULL, // data
254 usb_callback,
255 (void *)&cb_data);
256
257 if (ret == USB_RC_OK) {
258 WaitSema(cb_data.sema);
259 ret = cb_data.returnCode;
260 }
261 if (ret == USB_RC_OK) {
262 // clear bulk-in endpoint
263 if (mode & 0x01)
264 ret = usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
265 }
266 if (ret == USB_RC_OK) {
267 // clear bulk-out endpoint
268 if (mode & 0x02)
269 ret = usb_bulk_clear_halt(dev, USB_BLK_EP_OUT);
270 }
271 if (ret != USB_RC_OK) {
272 printf("USBHDFSD: Error - sending reset %d to device %d.\n", ret, dev->devId);
273 dev->status |= USBMASS_DEV_STAT_ERR;
274 }
275}
276
277static int usb_bulk_status(mass_dev *dev, csw_packet *csw, unsigned int tag)
278{
279 int ret;
280 usb_callback_data cb_data;
281
282 cb_data.sema = dev->ioSema;
283
284 csw->signature = CSW_TAG;
285 csw->tag = tag;
286 csw->dataResidue = 0;
287 csw->status = 0;
288
289 ret = sceUsbdBulkTransfer(
290 dev->bulkEpI, // bulk input pipe
291 csw, // data ptr
292 13, // data length
293 usb_callback,
294 (void *)&cb_data);
295
296 if (ret == USB_RC_OK) {
297 WaitSema(cb_data.sema);
298 ret = cb_data.returnCode;
299
300 if (cb_data.returnSize != 13)
301 printf("USBHDFSD: bulk csw.status returnSize: %i != 13\n", cb_data.returnSize);
302 if (csw->dataResidue != 0)
303 printf("USBHDFSD: bulk csw.status residue: %u\n", csw->dataResidue);
304 XPRINTF("bulk csw result: %d, csw.status: %u\n", ret, csw->status);
305 }
306
307 return ret;
308}
309
310/* see flow chart in the usbmassbulk_10.pdf doc (page 15)
311
312 Returned values:
313 <0 Low-level USBD error.
314 0 = Command completed successfully.
315 1 = Command failed.
316 2 = Phase error.
317*/
318static int usb_bulk_manage_status(mass_dev *dev, unsigned int tag)
319{
320 int ret;
321 csw_packet csw;
322
323 // XPRINTF("usb_bulk_manage_status 1 ...\n");
324 ret = usb_bulk_status(dev, &csw, tag); /* Attempt to read CSW from bulk in endpoint */
325 if (ret != USB_RC_OK) { /* STALL bulk in -OR- Bulk error */
326 usb_bulk_clear_halt(dev, USB_BLK_EP_IN); /* clear the stall condition for bulk in */
327
328 printf("USBHDFSD: usb_bulk_manage_status error %d ...\n", ret);
329 ret = usb_bulk_status(dev, &csw, tag); /* Attempt to read CSW from bulk in endpoint */
330 }
331
332 /* CSW not valid or stalled or phase error */
333 if (ret != USB_RC_OK || csw.signature != CSW_TAG || csw.tag != tag || csw.status == 2) {
334 printf("USBHDFSD: usb_bulk_manage_status call reset recovery ...\n");
335 usb_bulk_reset(dev, 3); /* Perform reset recovery */
336 }
337
338 return ((ret == USB_RC_OK && csw.signature == CSW_TAG && csw.tag == tag) ? csw.status : -1);
339}
340
341static int usb_bulk_get_max_lun(mass_dev *dev)
342{
343 int ret;
344 usb_callback_data cb_data;
345 char max_lun;
346
347 cb_data.sema = dev->ioSema;
348
349 // Call Bulk only mass storage reset
350 ret = sceUsbdControlTransfer(
351 dev->controlEp, // default pipe
352 0xA1,
353 0xFE,
354 0,
355 dev->interfaceNumber, // interface number
356 1, // length
357 &max_lun, // data
358 usb_callback,
359 (void *)&cb_data);
360
361 if (ret == USB_RC_OK) {
362 WaitSema(cb_data.sema);
363 ret = cb_data.returnCode;
364 }
365 if (ret == USB_RC_OK) {
366 ret = max_lun;
367 } else {
368 // Devices that do not support multiple LUNs may STALL this command.
369 usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
370 usb_bulk_clear_halt(dev, USB_BLK_EP_OUT);
371
372 ret = -ret;
373 }
374
375 return ret;
376}
377
378static int usb_bulk_command(mass_dev *dev, cbw_packet *packet)
379{
380 int ret;
381 usb_callback_data cb_data;
382
383 if (dev->status & USBMASS_DEV_STAT_ERR) {
384 printf("USBHDFSD: Rejecting I/O to offline device %d.\n", dev->devId);
385 return -1;
386 }
387
388 cb_data.sema = dev->ioSema;
389
390 ret = sceUsbdBulkTransfer(
391 dev->bulkEpO, // bulk output pipe
392 packet, // data ptr
393 31, // data length
394 usb_callback,
395 (void *)&cb_data);
396
397 if (ret == USB_RC_OK) {
398 WaitSema(cb_data.sema);
399 ret = cb_data.returnCode;
400 }
401 if (ret != USB_RC_OK) {
402 printf("USBHDFSD: Error - sending bulk command %d. Calling reset recovery.\n", ret);
403 usb_bulk_reset(dev, 3);
404 }
405
406 return ret;
407}
408
409static int usb_bulk_transfer(mass_dev *dev, int direction, void *buffer, unsigned int transferSize)
410{
411 int ret;
413
414 cb_data.sema = dev->ioSema;
415 cb_data.pipe = (direction == USB_BLK_EP_IN) ? dev->bulkEpI : dev->bulkEpO;
416 cb_data.buffer = buffer;
417 cb_data.returnCode = 0;
418 cb_data.remaining = transferSize;
419
420 ret = perform_bulk_transfer(&cb_data);
421 if (ret == USB_RC_OK) {
422 WaitSema(cb_data.sema);
423 ret = cb_data.returnCode;
424 }
425
426 if (ret != USB_RC_OK) {
427 printf("USBHDFSD: Error - bulk data transfer %d. Clearing HALT state.\n", cb_data.returnCode);
428 usb_bulk_clear_halt(dev, direction);
429 }
430
431 return ret;
432}
433
434static int cbw_scsi_test_unit_ready(mass_dev *dev)
435{
436 int result, retries;
437 static cbw_packet cbw = {
438 CBW_TAG, // cbw.signature
439 -TAG_TEST_UNIT_READY, // cbw.tag
440 0, // cbw.dataTransferLength
441 0x80, // cbw.flags
442 0, // cbw.lun
443 12, // cbw.comLength
444
445 /* scsi command packet */
446 {
447 0x00, // test unit ready operation code
448 0, // lun/reserved
449 0, // reserved
450 0, // reserved
451 0, // reserved
452 0, // reserved
453 0, // reserved
454 0, // reserved
455 0, // reserved
456 0, // reserved
457 0, // reserved
458 0, // reserved
459 }};
460
461 XPRINTF("cbw_scsi_test_unit_ready\n");
462
463 for (result = -EIO, retries = USB_XFER_MAX_RETRIES; retries > 0; retries--) {
464 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
465 if ((result = usb_bulk_manage_status(dev, -TAG_TEST_UNIT_READY)) >= 0)
466 break;
467 }
468 }
469
470 return result;
471}
472
473static int cbw_scsi_request_sense(mass_dev *dev, void *buffer, int size)
474{
475 int rcode, result, retries;
476 static cbw_packet cbw = {
477 CBW_TAG, // cbw.signature
478 -TAG_REQUEST_SENSE, // cbw.tag
479 0, // cbw.dataTransferLength
480 0x80, // cbw.flags
481 0, // cbw.lun
482 12, // cbw.comLength
483
484 /* scsi command packet */
485 {
486 0x03, // request sense operation code
487 0, // lun/reserved
488 0, // reserved
489 0, // reserved
490 0, // allocation length
491 0, // reserved
492 0, // reserved
493 0, // reserved
494 0, // reserved
495 0, // reserved
496 0, // reserved
497 0, // reserved
498 }};
499
500 cbw.dataTransferLength = size;
501 cbw.comData[4] = size;
502
503 XPRINTF("cbw_scsi_request_sense\n");
504
505 for (retries = USB_XFER_MAX_RETRIES; retries > 0; retries--) {
506 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
507 rcode = usb_bulk_transfer(dev, USB_BLK_EP_IN, buffer, size);
508 result = usb_bulk_manage_status(dev, -TAG_REQUEST_SENSE);
509
510 if (rcode == USB_RC_OK && result == 0)
511 return 0;
512 }
513 }
514
515 return -EIO;
516}
517
518static int cbw_scsi_inquiry(mass_dev *dev, void *buffer, int size)
519{
520 int rcode, result, retries;
521 static cbw_packet cbw = {
522 CBW_TAG, // cbw.signature
523 -TAG_INQUIRY, // cbw.tag
524 0, // cbw.dataTransferLength
525 0x80, // cbw.flags
526 0, // cbw.lun
527 12, // cbw.comLength
528
529 /* scsi command packet */
530 {
531 0x12, // inquiry operation code
532 0, // lun/reserved
533 0, // reserved
534 0, // reserved
535 0, // inquiry reply length
536 0, // reserved
537 0, // reserved
538 0, // reserved
539 0, // reserved
540 0, // reserved
541 0, // reserved
542 0, // reserved
543 }};
544
545 XPRINTF("cbw_scsi_inquiry\n");
546
547 cbw.dataTransferLength = size; // INQUIRY_REPLY_LENGTH
548 cbw.comData[4] = size; // inquiry reply length
549
550 for (retries = USB_XFER_MAX_RETRIES; retries > 0; retries--) {
551 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
552 rcode = usb_bulk_transfer(dev, USB_BLK_EP_IN, buffer, size);
553 result = usb_bulk_manage_status(dev, -TAG_INQUIRY);
554
555 if (rcode == USB_RC_OK && result == 0)
556 return 0;
557 }
558 }
559
560 return -EIO;
561}
562
563static int cbw_scsi_start_stop_unit(mass_dev *dev, u8 param)
564{
565 int result, retries;
566 static cbw_packet cbw = {
567 CBW_TAG, // cbw.signature
568 -TAG_START_STOP_UNIT, // cbw.tag
569 0, // cbw.dataTransferLength
570 0x80, // cbw.flags
571 0, // cbw.lun
572 12, // cbw.comLength
573
574 /* scsi command packet */
575 {
576 0x1B, // start stop unit operation code
577 0, // lun/reserved/immed
578 0, // reserved
579 0, // reserved
580 1, // reserved/LoEj/Start "Start the media and acquire the format type"
581 0, // reserved
582 0, // reserved
583 0, // reserved
584 0, // reserved
585 0, // reserved
586 0, // reserved
587 0, // reserved
588 }};
589
590 XPRINTF("cbw_scsi_start_stop_unit. param: %02x\n", param);
591
592 cbw.comData[4] = param;
593
594 for (result = -EIO, retries = USB_XFER_MAX_RETRIES; retries > 0; retries--) {
595 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
596 if ((result = usb_bulk_manage_status(dev, -TAG_START_STOP_UNIT)) == 0)
597 break;
598 }
599 }
600
601 return result;
602}
603
604static int cbw_scsi_read_capacity(mass_dev *dev, void *buffer, int size)
605{
606 int rcode, result, retries;
607 static cbw_packet cbw = {
608 CBW_TAG, // cbw.signature
609 -TAG_READ_CAPACITY, // cbw.tag
610 0, // cbw.dataTransferLength
611 0x80, // cbw.flags
612 0, // cbw.lun
613 12, // cbw.comLength
614
615 /* scsi command packet */
616 {
617 0x25, // read capacity operation code
618 0, // lun/reserved/RelAdr
619 0, // LBA 1
620 0, // LBA 2
621 0, // LBA 3
622 0, // LBA 4
623 0, // reserved
624 0, // reserved
625 0, // reserved/PMI
626 0, // reserved
627 0, // reserved
628 0, // reserved
629 }};
630
631 cbw.dataTransferLength = size;
632
633 XPRINTF("cbw_scsi_read_capacity\n");
634
635 for (retries = USB_XFER_MAX_RETRIES; retries > 0; retries--) {
636 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
637 rcode = usb_bulk_transfer(dev, USB_BLK_EP_IN, buffer, size);
638 result = usb_bulk_manage_status(dev, -TAG_READ_CAPACITY);
639
640 if (rcode == USB_RC_OK && result == 0)
641 return 0;
642 }
643 }
644
645 return -EIO;
646}
647
648static int cbw_scsi_read_sector(mass_dev *dev, unsigned int lba, void *buffer, unsigned short int sectorCount)
649{
650 int result;
651 static cbw_packet cbw = {
652 CBW_TAG, // cbw.signature
653 -TAG_READ, // cbw.tag
654 0, // cbw.dataTransferLength
655 0x80, // cbw.flags
656 0, // cbw.lun
657 12, // cbw.comLength
658
659 /* scsi command packet */
660 {
661 0x28, // Operation code
662 0, // LUN/DPO/FUA/Reserved/Reldr
663 0, // lba 1 (MSB)
664 0, // lba 2
665 0, // lba 3
666 0, // lba 4 (LSB)
667 0, // reserved
668 0, // Transfer length MSB
669 0, // Transfer length LSB
670 0, // reserved
671 0, // reserved
672 0, // reserved
673 }};
674 XPRINTF("cbw_scsi_read_sector - 0x%08x %p 0x%04x\n", lba, buffer, sectorCount);
675
676 cbw.dataTransferLength = dev->sectorSize * sectorCount;
677
678 // scsi command packet
679 cbw.comData[2] = (lba & 0xFF000000) >> 24; // lba 1 (MSB)
680 cbw.comData[3] = (lba & 0xFF0000) >> 16; // lba 2
681 cbw.comData[4] = (lba & 0xFF00) >> 8; // lba 3
682 cbw.comData[5] = (lba & 0xFF); // lba 4 (LSB)
683 cbw.comData[7] = (sectorCount & 0xFF00) >> 8; // Transfer length MSB
684 cbw.comData[8] = (sectorCount & 0xFF); // Transfer length LSB
685
686 result = -EIO;
687 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
688 int rcode;
689
690 rcode = usb_bulk_transfer(dev, USB_BLK_EP_IN, buffer, dev->sectorSize * sectorCount);
691 result = usb_bulk_manage_status(dev, -TAG_READ);
692
693 if (rcode != USB_RC_OK)
694 result = -EIO;
695 }
696
697 return result;
698}
699
700static int cbw_scsi_write_sector(mass_dev *dev, unsigned int lba, const void *buffer, unsigned short int sectorCount)
701{
702 int result;
703 static cbw_packet cbw = {
704 CBW_TAG, // cbw.signature
705 -TAG_WRITE, // cbw.tag
706 0, // cbw.dataTransferLength
707 0, // cbw.flags
708 0, // cbw.lun
709 12, // cbw.comLength
710
711 /* scsi command packet */
712 {
713 0x2A, // write operation code
714 0, // LUN/DPO/FUA/Reserved/Reldr
715 0, // lba 1 (MSB)
716 0, // lba 2
717 0, // lba 3
718 0, // lba 4 (LSB)
719 0, // Reserved
720 0, // Transfer length MSB
721 0, // Transfer length LSB
722 0, // reserved
723 0, // reserved
724 0, // reserved
725 }};
726 XPRINTF("cbw_scsi_write_sector - 0x%08x %p 0x%04x\n", lba, buffer, sectorCount);
727
728 cbw.dataTransferLength = dev->sectorSize * sectorCount;
729
730 // scsi command packet
731 cbw.comData[2] = (lba & 0xFF000000) >> 24; // lba 1 (MSB)
732 cbw.comData[3] = (lba & 0xFF0000) >> 16; // lba 2
733 cbw.comData[4] = (lba & 0xFF00) >> 8; // lba 3
734 cbw.comData[5] = (lba & 0xFF); // lba 4 (LSB)
735 cbw.comData[7] = (sectorCount & 0xFF00) >> 8; // Transfer length MSB
736 cbw.comData[8] = (sectorCount & 0xFF); // Transfer length LSB
737
738 result = -EIO;
739 if (usb_bulk_command(dev, &cbw) == USB_RC_OK) {
740 int rcode;
741
742 rcode = usb_bulk_transfer(dev, USB_BLK_EP_OUT, (void *)buffer, dev->sectorSize * sectorCount);
743 result = usb_bulk_manage_status(dev, -TAG_WRITE);
744
745 if (rcode != USB_RC_OK)
746 result = -EIO;
747 }
748
749 return result;
750}
751
752static mass_dev *mass_stor_findDevice(int devId, int create)
753{
754 mass_dev *dev = NULL;
755 int i;
756 XPRINTF("mass_stor_findDevice devId %i\n", devId);
757 for (i = 0; i < NUM_DEVICES; ++i) {
758 if (g_mass_device[i].devId == devId) {
759 XPRINTF("mass_stor_findDevice exists %i\n", i);
760 dev = &g_mass_device[i];
761 break;
762 } else if (create && dev == NULL && g_mass_device[i].devId == -1) {
763 dev = &g_mass_device[i];
764 break;
765 }
766 }
767 return dev;
768}
769
770int mass_stor_readSector(mass_dev *dev, unsigned int sector, unsigned char *buffer, unsigned short int count)
771{
772 int retries;
773
774 for (retries = USB_IO_MAX_RETRIES; retries > 0; retries--) {
775 if (cbw_scsi_read_sector(dev, sector, buffer, count) == 0)
776 return 0;
777 }
778
779 return -EIO;
780}
781
782int mass_stor_writeSector(mass_dev *dev, unsigned int sector, const unsigned char *buffer, unsigned short int count)
783{
784 int retries;
785
786 for (retries = USB_IO_MAX_RETRIES; retries > 0; retries--) {
787 if (cbw_scsi_write_sector(dev, sector, buffer, count) == 0)
788 return 0;
789 }
790
791 return -EIO;
792}
793
794/* test that endpoint is bulk endpoint and if so, update device info */
795static void usb_bulk_probeEndpoint(int devId, mass_dev *dev, UsbEndpointDescriptor *endpoint)
796{
797 if (endpoint->bmAttributes == USB_ENDPOINT_XFER_BULK) {
798 /* out transfer */
799 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT && dev->bulkEpO < 0) {
800 /* When sceUsbdOpenPipe() is used to work around the hardware errata that occurs when an unaligned memory address is specified,
801 some USB devices become incompatible. Hence it is preferable to do alignment correction in software instead. */
802 dev->bulkEpO = sceUsbdOpenPipeAligned(devId, endpoint);
803 XPRINTF("register Output endpoint id =%i addr=%02X packetSize=%i\n", dev->bulkEpO, endpoint->bEndpointAddress, (unsigned short int)endpoint->wMaxPacketSizeHB << 8 | endpoint->wMaxPacketSizeLB);
804 } else
805 /* in transfer */
806 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN && dev->bulkEpI < 0) {
807 /* Open this pipe with sceUsbdOpenPipe, to allow unaligned addresses to be used.
808 According to the Sony documentation and the USBD code,
809 there is always an alignment check if the pipe is opened with the sceUsbdOpenPipeAligned(),
810 even when there is never any correction for the bulk out pipe. */
811 dev->bulkEpI = sceUsbdOpenPipe(devId, endpoint);
812 XPRINTF("register Input endpoint id =%i addr=%02X packetSize=%i\n", dev->bulkEpI, endpoint->bEndpointAddress, (unsigned short int)endpoint->wMaxPacketSizeHB << 8 | endpoint->wMaxPacketSizeLB);
813 }
814 }
815}
816
817int mass_stor_probe(int devId)
818{
819 UsbDeviceDescriptor *device = NULL;
820 UsbConfigDescriptor *config = NULL;
821 UsbInterfaceDescriptor *intf = NULL;
822
823 XPRINTF("probe: devId=%i\n", devId);
824
825 mass_dev *mass_device = mass_stor_findDevice(devId, 0);
826
827 /* Check that a device descriptor was successfully allocated and the device was not already connected. */
828 if ((mass_device != NULL) && (mass_device->status & USBMASS_DEV_STAT_CONN)) {
829 printf("USBHDFSD: Error - no free device descriptors!\n");
830 return 0;
831 }
832
833 /* get device descriptor */
834 device = (UsbDeviceDescriptor *)sceUsbdScanStaticDescriptor(devId, NULL, USB_DT_DEVICE);
835 if (device == NULL) {
836 printf("USBHDFSD: Error - Couldn't get device descriptor\n");
837 return 0;
838 }
839
840 /* Check if the device has at least one configuration */
841 if (device->bNumConfigurations < 1) {
842 return 0;
843 }
844
845 /* read configuration */
846 config = (UsbConfigDescriptor *)sceUsbdScanStaticDescriptor(devId, device, USB_DT_CONFIG);
847 if (config == NULL) {
848 printf("USBHDFSD: Error - Couldn't get configuration descriptor\n");
849 return 0;
850 }
851 /* check that at least one interface exists */
852 XPRINTF("bNumInterfaces %d\n", config->bNumInterfaces);
853 if ((config->bNumInterfaces < 1) ||
854 (config->wTotalLength < (sizeof(UsbConfigDescriptor) + sizeof(UsbInterfaceDescriptor)))) {
855 printf("USBHDFSD: Error - No interfaces available\n");
856 return 0;
857 }
858 /* get interface */
859 intf = (UsbInterfaceDescriptor *)((char *)config + config->bLength); /* Get first interface */
860 XPRINTF("bInterfaceClass %X bInterfaceSubClass %X bInterfaceProtocol %X\n",
861 intf->bInterfaceClass, intf->bInterfaceSubClass, intf->bInterfaceProtocol);
862
863 if ((intf->bInterfaceClass != USB_CLASS_MASS_STORAGE) ||
864 (intf->bInterfaceSubClass != USB_SUBCLASS_MASS_SCSI &&
865 intf->bInterfaceSubClass != USB_SUBCLASS_MASS_SFF_8070I) ||
866 (intf->bInterfaceProtocol != USB_PROTOCOL_MASS_BULK_ONLY) ||
867 (intf->bNumEndpoints < 2)) { // 4.3: There shall be at least 2 endpoints, for bulk in and bulk out.
868 return 0;
869 }
870 return 1;
871}
872
873int mass_stor_connect(int devId)
874{
875 int i;
876 int epCount;
877 UsbDeviceDescriptor *device;
878 UsbConfigDescriptor *config;
879 UsbInterfaceDescriptor *interface;
880 UsbEndpointDescriptor *endpoint;
881 iop_sema_t SemaData;
882 mass_dev *dev;
883
884 printf("USBHDFSD: connect: devId=%i\n", devId);
885 dev = mass_stor_findDevice(devId, 1);
886
887 if (dev == NULL) {
888 printf("USBHDFSD: Error - no free device descriptors!\n");
889 return 1;
890 }
891
892 /* Device cannot be registered twice. */
893 if (dev->devId != -1) {
894 printf("USBHDFSD: Error - device descriptor in use!\n");
895 return 1;
896 }
897
898 dev->status = 0;
899 dev->sectorSize = 0;
900
901 dev->bulkEpI = -1;
902 dev->bulkEpO = -1;
903
904 /* open the config endpoint */
905 dev->controlEp = sceUsbdOpenPipe(devId, NULL);
906
907 device = (UsbDeviceDescriptor *)sceUsbdScanStaticDescriptor(devId, NULL, USB_DT_DEVICE);
908
909 config = (UsbConfigDescriptor *)sceUsbdScanStaticDescriptor(devId, device, USB_DT_CONFIG);
910
911 interface = (UsbInterfaceDescriptor *)((char *)config + config->bLength); /* Get first interface */
912
913 // store interface numbers
914 dev->interfaceNumber = interface->bInterfaceNumber;
915 dev->interfaceAlt = interface->bAlternateSetting;
916
917 epCount = interface->bNumEndpoints;
918 endpoint = (UsbEndpointDescriptor *)sceUsbdScanStaticDescriptor(devId, NULL, USB_DT_ENDPOINT);
919 usb_bulk_probeEndpoint(devId, dev, endpoint);
920
921 for (i = 1; i < epCount; i++) {
922 endpoint = (UsbEndpointDescriptor *)((char *)endpoint + endpoint->bLength);
923 usb_bulk_probeEndpoint(devId, dev, endpoint);
924 }
925
926 // Bail out if we do NOT have enough bulk endpoints.
927 if (dev->bulkEpI < 0 || dev->bulkEpO < 0) {
928 mass_stor_release(dev);
929 printf("USBHDFSD: Error - connect failed: not enough bulk endpoints! \n");
930 return -1;
931 }
932
933 SemaData.initial = 0;
934 SemaData.max = 1;
935 SemaData.option = 0;
936 SemaData.attr = 0;
937 if ((dev->ioSema = CreateSema(&SemaData)) < 0) {
938 mass_stor_release(dev);
939 printf("USBHDFSD: Failed to allocate I/O semaphore.\n");
940 return -1;
941 }
942
943 /*store current configuration id - can't call set_configuration here */
944 dev->devId = devId;
945 dev->configId = config->bConfigurationValue;
946 dev->status = USBMASS_DEV_STAT_CONN;
947 XPRINTF("connect ok: epI=%i, epO=%i \n", dev->bulkEpI, dev->bulkEpO);
948
949 if (dev->callback != NULL)
950 dev->callback(USBMASS_DEV_EV_CONN);
951
952 return 0;
953}
954
955static void mass_stor_release(mass_dev *dev)
956{
957 if (dev->bulkEpI >= 0) {
958 sceUsbdClosePipe(dev->bulkEpI);
959 }
960
961 if (dev->bulkEpO >= 0) {
962 sceUsbdClosePipe(dev->bulkEpO);
963 }
964
965 dev->bulkEpI = -1;
966 dev->bulkEpO = -1;
967 dev->controlEp = -1;
968 dev->status = 0;
969}
970
971int mass_stor_disconnect(int devId)
972{
973 mass_dev *dev;
974 dev = mass_stor_findDevice(devId, 0);
975
976 printf("USBHDFSD: disconnect: devId=%i\n", devId);
977
978 if (dev == NULL) {
979 printf("USBHDFSD: Error - disconnect: no device storage!\n");
980 return 0;
981 }
982
983 if (dev->status & USBMASS_DEV_STAT_CONN) {
984 mass_stor_release(dev);
985 part_disconnect(dev);
986 scache_kill(dev->cache);
987 dev->cache = NULL;
988 dev->devId = -1;
989
990 DeleteSema(dev->ioSema);
991
992 if (dev->callback != NULL)
993 dev->callback(USBMASS_DEV_EV_DISCONN);
994 }
995
996 return 0;
997}
998
999static int mass_stor_warmup(mass_dev *dev)
1000{
1001 inquiry_data id;
1002 sense_data sd;
1004 int stat;
1005
1006 XPRINTF("mass_stor_warmup\n");
1007
1008 if (!(dev->status & USBMASS_DEV_STAT_CONN)) {
1009 printf("USBHDFSD: Error - no mass storage device found!\n");
1010 return -1;
1011 }
1012
1013 stat = usb_bulk_get_max_lun(dev);
1014 printf("USBHDFSD: usb_bulk_get_max_lun %d\n", stat);
1015
1016 memset(&id, 0, sizeof(inquiry_data));
1017 if ((stat = cbw_scsi_inquiry(dev, &id, sizeof(inquiry_data))) < 0) {
1018 printf("USBHDFSD: Error - cbw_scsi_inquiry %d\n", stat);
1019 return -1;
1020 }
1021
1022 printf("USBHDFSD:\tVendor: %.8s\n"
1023 "\t\tProduct: %.16s\n"
1024 "\t\tRevision: %.4s\n",
1025 id.vendor, id.product, id.revision);
1026
1027 while ((stat = cbw_scsi_test_unit_ready(dev)) != 0) {
1028 printf("USBHDFSD: cbw_scsi_test_unit_ready %d\n", stat);
1029
1030 stat = cbw_scsi_request_sense(dev, &sd, sizeof(sense_data));
1031 if (stat != 0)
1032 printf("USBHDFSD: Error - cbw_scsi_request_sense %d\n", stat);
1033
1034 if ((sd.error_code == 0x70) && (sd.sense_key != 0x00)) {
1035 printf("USBHDFSD: Sense Data key: %02X code: %02X qual: %02X\n", sd.sense_key, sd.add_sense_code, sd.add_sense_qual);
1036
1037 if ((sd.sense_key == 0x02) && (sd.add_sense_code == 0x04) && (sd.add_sense_qual == 0x02)) {
1038 printf("USBHDFSD: Error - Additional initalization is required for this device!\n");
1039 if ((stat = cbw_scsi_start_stop_unit(dev, 1)) != 0) {
1040 printf("USBHDFSD: Error - cbw_scsi_start_stop_unit %d\n", stat);
1041 return -1;
1042 }
1043 }
1044 }
1045 }
1046
1047 if ((stat = cbw_scsi_read_capacity(dev, &rcd, sizeof(read_capacity_data))) != 0) {
1048 printf("USBHDFSD: Error - cbw_scsi_read_capacity %d\n", stat);
1049 return -1;
1050 }
1051
1052 dev->sectorSize = getBI32(&rcd.block_length);
1053 dev->maxLBA = getBI32(&rcd.last_lba);
1054 printf("USBHDFSD: sectorSize %u maxLBA %u\n", dev->sectorSize, dev->maxLBA);
1055
1056 return 0;
1057}
1058
1059static int mass_store_configureDevice(mass_dev *dev)
1060{
1061 int ret;
1062 if ((ret = usb_set_configuration(dev, dev->configId)) != USB_RC_OK) {
1063 printf("USBHDFSD: Error - sending set_configuration %d\n", ret);
1064 return ret;
1065 }
1066
1067 if ((ret = usb_set_interface(dev, dev->interfaceNumber, dev->interfaceAlt)) != USB_RC_OK) {
1068 printf("USBHDFSD: Error - sending set_interface %d\n", ret);
1069 if (ret == USB_RC_STALL) { /* USB Specification 1.1, section 9.4.10: Devices that only support a default setting for the specified interface may return a STALL.
1070 As with Linux, we shall clear the halt state of the interface's pipes and continue. */
1071 usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
1072 usb_bulk_clear_halt(dev, USB_BLK_EP_OUT);
1073 ret = USB_RC_OK;
1074 }
1075 }
1076
1077 return ret;
1078}
1079
1080/* Do this outside of mass_stor_connect() as callback functions do not work,
1081 causing the PS2 to hang while setting configuration (which does control transfer). */
1082int mass_stor_configureNextDevice(void)
1083{
1084 int i;
1085
1086 XPRINTF("configuring devices... \n");
1087
1088 for (i = 0; i < NUM_DEVICES; ++i) {
1089 mass_dev *dev = &g_mass_device[i];
1090 if (dev->devId != -1 && (dev->status & USBMASS_DEV_STAT_CONN) && !(dev->status & USBMASS_DEV_STAT_CONF)) {
1091 int ret;
1092 ret = mass_store_configureDevice(dev);
1093 if (ret != USB_RC_OK) {
1094 mass_stor_release(dev);
1095 continue;
1096 }
1097
1098 dev->status |= USBMASS_DEV_STAT_CONF;
1099
1100 ret = mass_stor_warmup(dev);
1101 if (ret < 0) {
1102 printf("USBHDFSD: Error - failed to warmup device %d\n", dev->devId);
1103 mass_stor_release(dev);
1104 continue;
1105 }
1106
1107 dev->cache = scache_init(dev, dev->sectorSize); // modified by Hermes
1108 if (dev->cache == NULL) {
1109 printf("USBHDFSD: Error - scache_init failed \n");
1110 mass_stor_release(dev);
1111 continue;
1112 }
1113
1114 return part_connect(dev) >= 0;
1115 }
1116 }
1117 return 0;
1118}
1119
1120int InitUSB(void)
1121{
1122 int i;
1123 int ret = 0;
1124 for (i = 0; i < NUM_DEVICES; ++i) {
1125 g_mass_device[i].status = 0;
1126 g_mass_device[i].devId = -1;
1127 }
1128
1129 driver.next = NULL;
1130 driver.prev = NULL;
1131 driver.name = "mass-stor";
1132 driver.probe = mass_stor_probe;
1133 driver.connect = mass_stor_connect;
1134 driver.disconnect = mass_stor_disconnect;
1135
1136 ret = sceUsbdRegisterLdd(&driver);
1137 XPRINTF("registerDriver=%i \n", ret);
1138 if (ret < 0) {
1139 printf("USBHDFSD: register driver failed! ret=%d\n", ret);
1140 return (-1);
1141 }
1142
1143 return (0);
1144}
1145
1146int UsbMassGetDeviceInfo(int device, UsbMassDeviceInfo_t *info)
1147{
1148 int result;
1149 mass_dev *pDev;
1150
1151 if (device >= 0 && device < NUM_DEVICES) {
1152 pDev = &g_mass_device[device];
1153
1154 info->status = pDev->status;
1155 info->SectorSize = pDev->sectorSize;
1156 info->MaxLBA = pDev->maxLBA;
1157
1158 result = 0;
1159 } else
1160 result = -ENODEV;
1161
1162 return result;
1163}
1164
1165int UsbMassRegisterCallback(int device, usbmass_cb_t callback)
1166{
1167 int result;
1168
1169 if (device >= 0 && device < NUM_DEVICES) {
1170 g_mass_device[device].callback = callback;
1171 result = 0;
1172
1173 if (g_mass_device[device].status & USBMASS_DEV_STAT_CONN) { // If the device is already connected, let the callback know.
1174 if (callback != NULL)
1175 callback(USBMASS_DEV_EV_CONN);
1176 }
1177 } else
1178 result = -ENODEV;
1179
1180 return result;
1181}
1182
1183int mass_stor_stop_unit(mass_dev *dev)
1184{
1185 int stat;
1186
1187 if ((stat = cbw_scsi_start_stop_unit(dev, 0)) != 0) {
1188 printf("USBHDFSD: Error - cbw_scsi_start_stop_unit %d\n", stat);
1189 }
1190
1191 return stat;
1192}
1193
1194void mass_store_stop_all(void)
1195{
1196 int i;
1197
1198 for (i = 0; i < NUM_DEVICES; ++i) {
1199 mass_dev *dev = &g_mass_device[i];
1200 if (dev->devId != -1 && (dev->status & USBMASS_DEV_STAT_CONN)) {
1201 if (!(dev->status & USBMASS_DEV_STAT_CONF)) { // Configure unconfigured devices, to be able to shut them down.
1202 if (mass_store_configureDevice(dev) != USB_RC_OK)
1203 continue;
1204 }
1205
1206 mass_stor_stop_unit(dev);
1207 }
1208 }
1209}
#define EIO
Definition errno.h:29
#define ENODEV
Definition errno.h:57
#define USB_RC_STALL
Definition usbd.h:246
#define USB_RC_OK
Definition usbd.h:238
char * name
Definition usbd.h:51
u32 count
start sector of fragmented bd/file
#define USBMASS_DEV_STAT_CONN
#define USBMASS_DEV_STAT_ERR
#define USBMASS_DEV_STAT_CONF