19#include "module_debug.h"
21#define USB_SUBCLASS_MASS_RBC 0x01
22#define USB_SUBCLASS_MASS_ATAPI 0x02
23#define USB_SUBCLASS_MASS_QIC 0x03
24#define USB_SUBCLASS_MASS_UFI 0x04
25#define USB_SUBCLASS_MASS_SFF_8070I 0x05
26#define USB_SUBCLASS_MASS_SCSI 0x06
28#define USB_PROTOCOL_MASS_CBI 0x00
29#define USB_PROTOCOL_MASS_CBI_NO_CCI 0x01
30#define USB_PROTOCOL_MASS_BULK_ONLY 0x50
32#define USB_BLK_EP_IN 0
33#define USB_BLK_EP_OUT 1
35#define USB_XFER_MAX_RETRIES 8
37#define CBW_TAG 0x43425355
38#define CSW_TAG 0x53425355
46 unsigned char configId;
48 unsigned char interfaceNumber;
49 unsigned char interfaceAlt;
56 unsigned int signature;
58 unsigned int dataTransferLength;
61 unsigned char comLength;
62 unsigned char comData[16];
67 unsigned int signature;
69 unsigned int dataResidue;
82#define USB_BLOCK_SIZE 4096
90 unsigned int remaining;
94static mass_dev g_mass_device[NUM_DEVICES];
95static int usb_mass_update_sema;
97static void usb_callback(
int resultCode,
int bytes,
void *arg);
100static void usb_transfer_callback(
int resultCode,
int bytes,
void *arg);
102static void usb_mass_release(
mass_dev *dev);
104static void usb_callback(
int resultCode,
int bytes,
void *arg)
107 data->returnCode = resultCode;
108 data->returnSize = bytes;
109 M_DEBUG(
"callback: res %d, bytes %d, arg %p \n", resultCode, bytes, arg);
110 SignalSema(data->sema);
118 len = data->remaining > USB_BLOCK_SIZE ? USB_BLOCK_SIZE : data->remaining;
119 ret = sceUsbdBulkTransfer(
123 &usb_transfer_callback,
128static void usb_transfer_callback(
int resultCode,
int bytes,
void *arg)
132 data->returnCode = resultCode;
134 data->remaining -= bytes;
135 data->buffer += bytes;
138 if ((resultCode ==
USB_RC_OK) && (data->remaining > 0)) {
141 ret = perform_bulk_transfer(data);
143 data->returnCode = ret;
144 SignalSema(data->sema);
147 SignalSema(data->sema);
152static int usb_set_configuration(
mass_dev *dev,
int configNumber)
157 cb_data.sema = dev->ioSema;
159 M_DEBUG(
"setting configuration controlEp=%i, confNum=%i \n", dev->controlEp, configNumber);
160 ret = sceUsbdSetConfiguration(dev->controlEp, configNumber, usb_callback, (
void *)&cb_data);
163 WaitSema(cb_data.sema);
164 ret = cb_data.returnCode;
170static int usb_set_interface(
mass_dev *dev,
int interface,
int altSetting)
175 cb_data.sema = dev->ioSema;
177 M_DEBUG(
"setting interface controlEp=%i, interface=%i altSetting=%i\n", dev->controlEp, interface, altSetting);
178 ret = sceUsbdSetInterface(dev->controlEp, interface, altSetting, usb_callback, (
void *)&cb_data);
181 WaitSema(cb_data.sema);
182 ret = cb_data.returnCode;
188static int usb_bulk_clear_halt(
mass_dev *dev,
int endpoint)
193 cb_data.sema = dev->ioSema;
195 ret = sceUsbdClearEndpointFeature(
198 (endpoint == USB_BLK_EP_IN) ? dev->bulkEpI : dev->bulkEpO,
203 WaitSema(cb_data.sema);
204 ret = cb_data.returnCode;
207 M_DEBUG(
"ERROR: sending clear halt %d\n", ret);
214static void usb_bulk_reset(
mass_dev *dev,
int mode)
219 cb_data.sema = dev->ioSema;
222 ret = sceUsbdControlTransfer(
227 dev->interfaceNumber,
234 WaitSema(cb_data.sema);
235 ret = cb_data.returnCode;
240 ret = usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
245 ret = usb_bulk_clear_halt(dev, USB_BLK_EP_OUT);
248 M_DEBUG(
"ERROR: sending reset %d to device %d.\n", ret, dev->devId);
258 cb_data.sema = dev->ioSema;
260 csw->signature = CSW_TAG;
262 csw->dataResidue = 0;
265 ret = sceUsbdBulkTransfer(
273 WaitSema(cb_data.sema);
274 ret = cb_data.returnCode;
277 if (cb_data.returnSize != 13)
278 M_DEBUG(
"bulk csw.status returnSize: %i != 13\n", cb_data.returnSize);
279 if (csw->dataResidue != 0)
280 M_DEBUG(
"bulk csw.status residue: %i\n", csw->dataResidue);
281 M_DEBUG(
"bulk csw result: %d, csw.status: %i\n", ret, csw->status);
296static int usb_bulk_manage_status(
mass_dev *dev,
unsigned int tag)
302 ret = usb_bulk_status(dev, &csw, tag);
304 usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
306 M_DEBUG(
"ERROR: usb_bulk_manage_status error %d ...\n", ret);
307 ret = usb_bulk_status(dev, &csw, tag);
311 if (ret !=
USB_RC_OK || csw.signature != CSW_TAG || csw.tag != tag || csw.status == 2) {
312 M_DEBUG(
"ERROR: usb_bulk_manage_status call reset recovery ...\n");
313 usb_bulk_reset(dev, 3);
316 return ((ret ==
USB_RC_OK && csw.signature == CSW_TAG && csw.tag == tag) ? csw.status : -1);
327 cb_data.sema = dev->ioSema;
330 ret = sceUsbdControlTransfer(
335 dev->interfaceNumber,
342 WaitSema(cb_data.sema);
343 ret = cb_data.returnCode;
349 usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
350 usb_bulk_clear_halt(dev, USB_BLK_EP_OUT);
376 M_DEBUG(
"Rejecting I/O to offline device %d.\n", dev->devId);
380 cb_data.sema = dev->ioSema;
382 ret = sceUsbdBulkTransfer(
390 WaitSema(cb_data.sema);
391 ret = cb_data.returnCode;
394 M_DEBUG(
"ERROR: sending bulk command %d. Calling reset recovery.\n", ret);
395 usb_bulk_reset(dev, 3);
401static int usb_bulk_transfer(
mass_dev *dev,
int direction,
void *buffer,
unsigned int transferSize)
406 cb_data.sema = dev->ioSema;
407 cb_data.pipe = (direction == USB_BLK_EP_IN) ? dev->bulkEpI : dev->bulkEpO;
408 cb_data.buffer = buffer;
409 cb_data.returnCode = 0;
410 cb_data.remaining = transferSize;
412 ret = perform_bulk_transfer(&cb_data);
414 WaitSema(cb_data.sema);
415 ret = cb_data.returnCode;
419 M_DEBUG(
"ERROR: bulk data transfer %d. Clearing HALT state.\n", ret);
420 usb_bulk_clear_halt(dev, direction);
428static void scsi_cmd_callback(
int resultCode,
int bytes,
void *arg)
433 M_DEBUG(
"%s, result=%d\n", __func__, resultCode);
436 if ((resultCode !=
USB_RC_OK) || (ucmd->cmd_count == 0)) {
438 ucmd->returnCode = resultCode;
439 SignalSema(dev->ioSema);
444int usb_queue_cmd(
struct scsi_interface *scsi,
const unsigned char *cmd,
unsigned int cmd_len,
unsigned char *data,
unsigned int data_len,
unsigned int data_wr)
452 static unsigned int tag = 0;
454 M_DEBUG(
"%s\n", __func__);
463 ucmd.cbw.signature = CBW_TAG;
465 ucmd.cbw.dataTransferLength = data_len;
466 ucmd.cbw.flags = data_wr ? 0 : 0x80;
468 ucmd.cbw.comLength = cmd_len;
469 memcpy(ucmd.cbw.comData, cmd, cmd_len);
472 ucmd.csw.signature = CSW_TAG;
474 ucmd.csw.dataResidue = 0;
479 if (usb_bulk_command(dev, &ucmd.cbw) ==
USB_RC_OK) {
481 rcode = usb_bulk_transfer(dev, data_wr ? USB_BLK_EP_OUT : USB_BLK_EP_IN, data, data_len);
485 result = usb_bulk_manage_status(dev, tag);
495 result = sceUsbdBulkTransfer(dev->bulkEpO, &ucmd.cbw, 31, scsi_cmd_callback, (
void *)&ucmd);
500 while (data_len > 0) {
501 unsigned int tr_len = (data_len < USB_BLOCK_SIZE) ? data_len : USB_BLOCK_SIZE;
503 result = sceUsbdBulkTransfer(data_wr ? dev->bulkEpO : dev->bulkEpI, data, tr_len, scsi_cmd_callback, (
void *)&ucmd);
512 result = sceUsbdBulkTransfer(dev->bulkEpI, &ucmd.csw, 13, scsi_cmd_callback, (
void *)&ucmd);
517 WaitSema(dev->ioSema);
525static mass_dev *usb_mass_findDevice(
int devId,
int create)
529 M_DEBUG(
"usb_mass_findDevice devId %i\n", devId);
530 for (i = 0; i < NUM_DEVICES; ++i) {
531 if (g_mass_device[i].devId == devId) {
532 M_DEBUG(
"usb_mass_findDevice exists %i\n", i);
533 dev = &g_mass_device[i];
535 }
else if (create && dev == NULL && g_mass_device[i].devId == -1) {
536 dev = &g_mass_device[i];
546 if (endpoint->bmAttributes == USB_ENDPOINT_XFER_BULK) {
547 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT && dev->bulkEpO < 0) {
550 dev->bulkEpO = sceUsbdOpenPipeAligned(devId, endpoint);
551 M_DEBUG(
"register Output endpoint id =%i addr=%02X packetSize=%i\n", dev->bulkEpO, endpoint->bEndpointAddress, (
unsigned short int)endpoint->wMaxPacketSizeHB << 8 | endpoint->wMaxPacketSizeLB);
557 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN && dev->bulkEpI < 0) {
558 dev->bulkEpI = sceUsbdOpenPipe(devId, endpoint);
559 M_DEBUG(
"register Input endpoint id =%i addr=%02X packetSize=%i\n", dev->bulkEpI, endpoint->bEndpointAddress, (
unsigned short int)endpoint->wMaxPacketSizeHB << 8 | endpoint->wMaxPacketSizeLB);
564static int usb_mass_probe(
int devId)
570 M_DEBUG(
"probe: devId=%i\n", devId);
572 mass_dev *mass_device = usb_mass_findDevice(devId, 0);
576 M_PRINTF(
"ERROR: Only one mass storage device allowed!\n");
582 if (device == NULL) {
583 M_DEBUG(
"ERROR: Couldn't get device descriptor\n");
588 if (device->bNumConfigurations < 1) {
594 if (config == NULL) {
595 M_DEBUG(
"ERROR: Couldn't get configuration descriptor\n");
599 M_DEBUG(
"bNumInterfaces %d\n", config->bNumInterfaces);
601 M_DEBUG(
"ERROR: No interfaces available\n");
606 M_DEBUG(
"bInterfaceClass %X bInterfaceSubClass %X bInterfaceProtocol %X\n",
607 intf->bInterfaceClass, intf->bInterfaceSubClass, intf->bInterfaceProtocol);
609 if ((intf->bInterfaceClass != USB_CLASS_MASS_STORAGE) || (intf->bInterfaceSubClass != USB_SUBCLASS_MASS_SCSI && intf->bInterfaceSubClass != USB_SUBCLASS_MASS_SFF_8070I) || (intf->bInterfaceProtocol != USB_PROTOCOL_MASS_BULK_ONLY) || (intf->bNumEndpoints < 2)) {
616static int usb_mass_connect(
int devId)
627 M_PRINTF(
"connect: devId=%i\n", devId);
628 dev = usb_mass_findDevice(devId, 1);
631 M_PRINTF(
"ERROR: Unable to allocate space!\n");
636 if (dev->devId != -1) {
637 M_PRINTF(
"ERROR: Only one mass storage device allowed!\n");
646 dev->controlEp = sceUsbdOpenPipe(devId, NULL);
655 dev->interfaceNumber = interface->bInterfaceNumber;
656 dev->interfaceAlt = interface->bAlternateSetting;
658 epCount = interface->bNumEndpoints;
660 usb_bulk_probeEndpoint(devId, dev, endpoint);
662 for (i = 1; i < epCount; i++) {
664 usb_bulk_probeEndpoint(devId, dev, endpoint);
668 if (dev->bulkEpI < 0 || dev->bulkEpO < 0) {
669 usb_mass_release(dev);
670 M_PRINTF(
"ERROR: connect failed: not enough bulk endpoints!\n");
674 SemaData.initial = 0;
678 if ((dev->ioSema = CreateSema(&SemaData)) < 0) {
679 M_PRINTF(
"ERROR: Failed to allocate I/O semaphore\n");
684 dev->configId = config->bConfigurationValue;
687 __asm__ __volatile__(
"" : : :
"memory");
689 M_DEBUG(
"connect ok: epI=%i, epO=%i\n", dev->bulkEpI, dev->bulkEpO);
691 SignalSema(usb_mass_update_sema);
696static void usb_mass_release(
mass_dev *dev)
698 if (dev->bulkEpI >= 0)
699 sceUsbdClosePipe(dev->bulkEpI);
701 if (dev->bulkEpO >= 0)
702 sceUsbdClosePipe(dev->bulkEpO);
710static int usb_mass_disconnect(
int devId)
713 dev = usb_mass_findDevice(devId, 0);
715 M_PRINTF(
"disconnect: devId=%i\n", devId);
718 M_PRINTF(
"ERROR: disconnect: no device storage!\n");
723 usb_mass_release(dev);
726 DeleteSema(dev->ioSema);
730 scsi_disconnect(&dev->scsi);
736static void usb_mass_update(
void *arg)
742 M_DEBUG(
"update thread running\n");
749 WaitSema(usb_mass_update_sema);
754 for (i = 0; i < NUM_DEVICES; i += 1) {
757 new_devs[new_devs_count] = dev;
764 for (i = 0; i < new_devs_count; i += 1) {
768 if ((ret = usb_set_configuration(dev, dev->configId)) !=
USB_RC_OK) {
769 M_PRINTF(
"ERROR: sending set_configuration %d\n", ret);
770 usb_mass_release(dev);
774 if ((ret = usb_set_interface(dev, dev->interfaceNumber, dev->interfaceAlt)) !=
USB_RC_OK) {
775 M_PRINTF(
"ERROR: sending set_interface %d\n", ret);
779 usb_bulk_clear_halt(dev, USB_BLK_EP_IN);
780 usb_bulk_clear_halt(dev, USB_BLK_EP_OUT);
782 usb_mass_release(dev);
788 scsi_connect(&dev->scsi);
798int usb_mass_init(
void)
805 M_DEBUG(
"%s\n", __func__);
807 for (i = 0; i < NUM_DEVICES; ++i) {
808 g_mass_device[i].status = 0;
809 g_mass_device[i].devId = -1;
811 g_mass_device[i].scsi.priv = &g_mass_device[i];
812 g_mass_device[i].scsi.name =
"usb";
815 g_mass_device[i].scsi.max_sectors = 128;
816 g_mass_device[i].scsi.get_max_lun = usb_bulk_get_max_lun;
817 g_mass_device[i].scsi.queue_cmd = usb_queue_cmd;
824 usb_mass_update_sema = CreateSema(&sema);
828 driver.
name =
"mass-stor";
829 driver.probe = usb_mass_probe;
830 driver.connect = usb_mass_connect;
831 driver.disconnect = usb_mass_disconnect;
833 ret = sceUsbdRegisterLdd(&driver);
834 M_DEBUG(
"sceUsbdRegisterLdd=%i\n", ret);
836 M_PRINTF(
"ERROR: register driver failed! ret=%d\n", ret);
842 thread.thread = usb_mass_update;
843 thread.stacksize = 2 * 1024;
846 ret = CreateThread(&
thread);
848 M_PRINTF(
"ERROR: CreateThread failed! ret=%d\n", ret);
852 ret = StartThread(ret, 0);
854 M_PRINTF(
"ERROR: StartThread failed! ret=%d\n", ret);
#define USBMASS_DEV_STAT_CONN
#define USBMASS_DEV_STAT_ERR
#define USBMASS_DEV_STAT_CONF