PS2SDK
PS2 Homebrew Libraries
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 
52 typedef 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
61 } cbw_packet;
62 
63 typedef struct _csw_packet
64 {
65  unsigned int signature;
66  unsigned int tag;
67  unsigned int dataResidue;
68  unsigned char status;
69 } csw_packet;
70 
71 typedef 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];
82 } inquiry_data;
83 
84 typedef 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];
95 } sense_data;
96 
97 typedef struct _read_capacity_data
98 {
99  u8 last_lba[4];
100  u8 block_length[4];
102 
103 static sceUsbdLddOps driver;
104 
105 typedef 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
124 static mass_dev g_mass_device[NUM_DEVICES];
125 
126 static void usb_callback(int resultCode, int bytes, void *arg);
127 static int perform_bulk_transfer(usb_transfer_callback_data *data);
128 static void usb_transfer_callback(int resultCode, int bytes, void *arg);
129 static void mass_stor_release(mass_dev *dev);
130 
131 static void usb_callback(int resultCode, int bytes, void *arg)
132 {
133  usb_callback_data *data = (usb_callback_data *)arg;
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 
140 static 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 
154 static 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 
177 static 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 
195 static 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 
213 static 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 
238 static 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 
277 static 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 */
318 static 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 
341 static 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 
378 static 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 
409 static 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 
434 static 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 
473 static 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 
518 static 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 
563 static 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 
604 static 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 
648 static 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 
700 static 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 
752 static 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 
770 int 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 
782 int 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 */
795 static 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 
817 int 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 
873 int 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 
955 static 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 
971 int 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 
999 static int mass_stor_warmup(mass_dev *dev)
1000 {
1001  inquiry_data id;
1002  sense_data sd;
1003  read_capacity_data rcd;
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 
1059 static 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). */
1082 int 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 
1120 int 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 
1146 int 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 
1165 int 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 
1183 int 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 
1194 void 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 }
UsbDeviceDescriptor
Definition: usbd.h:63
_inquiry_data
Definition: scsi.c:15
USB_RC_OK
#define USB_RC_OK
Definition: usbd.h:238
USBMASS_DEV_STAT_CONN
#define USBMASS_DEV_STAT_CONN
Definition: usbhdfsd-common.h:49
iop_sema_t
Definition: thsemap.h:38
sysclib.h
_mass_dev
Definition: usbhdfsd.h:64
s_info
Definition: xprintf.c:78
_UsbDriver
Definition: usbd.h:47
_usb_callback_data
Definition: usb_driver.c:105
EIO
#define EIO
Definition: errno.h:29
USBMASS_DEV_STAT_ERR
#define USBMASS_DEV_STAT_ERR
Definition: usbhdfsd-common.h:53
_read_capacity_data
Definition: scsi.c:41
UsbEndpointDescriptor
Definition: usbd.h:108
usbd.h
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
USBMASS_DEV_STAT_CONF
#define USBMASS_DEV_STAT_CONF
Definition: usbhdfsd-common.h:51
_cbw_packet
Definition: usb_driver.c:52
USB_RC_STALL
#define USB_RC_STALL
Definition: usbd.h:246
thsemap.h
usbd_macro.h
_csw_packet
Definition: usb_driver.c:63
stdio.h
_UsbDriver::name
char * name
Definition: usbd.h:51
UsbMassDeviceInfo
Definition: usbhdfsd.h:23
UsbConfigDescriptor
Definition: usbd.h:81
_usb_transfer_callback_data
Definition: usb_driver.c:114
_sense_data
Definition: scsi.c:28
UsbInterfaceDescriptor
Definition: usbd.h:95
errno.h
ENODEV
#define ENODEV
Definition: errno.h:57
usbhdfsd.h