static int usb_bulk_command(mass_dev* dev, cbw_packet* packet ) { int ret; usb_callback_data cb_data; if(dev->status & USBMASS_DEV_STAT_ERR){ printf("USBHDFSD: Rejecting I/O to offline device %d.\n", dev->devId); return -1; } cb_data.semh = dev->ioSema; ret = UsbBulkTransfer( dev->bulkEpO, //bulk output pipe packet, //data ptr 31, //data length usb_callback, (void*)&cb_data ); if (ret == USB_RC_OK) { WaitSema(cb_data.semh); ret = cb_data.returnCode; } if (ret != USB_RC_OK) { XPRINTF("USBHDFSD: Error - sending bulk command %d. Calling reset recovery.\n", ret); usb_bulk_reset(dev, 3); } return ret; }
inline int cbw_scsi_read_capacity(mass_dev* dev, void *buffer, int size) { int ret; cbw_packet cbw; int retryCount; XPRINTF("USBHDFSD: cbw_scsi_read_capacity\n"); cbw.signature = CBW_TAG; cbw.lun = 0; cbw.tag = -TAG_READ_CAPACITY; cbw.dataTransferLength = size; //READ_CAPACITY_REPLY_LENGTH cbw.flags = 0x80; //inquiry data will flow In cbw.comLength = 12; //scsi command packet cbw.comData[0] = 0x25; //read capacity operation code cbw.comData[1] = 0; //lun/reserved/RelAdr cbw.comData[2] = 0; //LBA 1 cbw.comData[3] = 0; //LBA 2 cbw.comData[4] = 0; //LBA 3 cbw.comData[5] = 0; //LBA 4 cbw.comData[6] = 0; //Reserved cbw.comData[7] = 0; //Reserved cbw.comData[8] = 0; //Reserved/PMI cbw.comData[9] = 0; //reserved cbw.comData[10] = 0; //reserved cbw.comData[11] = 0; //reserved ret = 1; retryCount = 6; while (ret != 0 && retryCount > 0) { usb_bulk_command(dev, &cbw); ret = usb_bulk_transfer(dev->bulkEpI, buffer, size); if (ret != 0) printf("USBHDFSD: cbw_scsi_read_capacity error from usb_bulk_transfer %d\n", ret); //HACK HACK HACK !!! //according to usb doc we should allways //attempt to read the CSW packet. But in some cases //reading of CSW packet just freeze ps2....:-( if (ret == USB_RC_STALL) { XPRINTF("USBHDFSD: call reset recovery ...\n"); usb_bulk_reset(dev, 1); } else { ret = usb_bulk_manage_status(dev, -TAG_READ_CAPACITY); } retryCount--; } return ret; }
/* see flow chart in the usbmassbulk_10.pdf doc (page 15) Returned values: <0 Low-level USBD error. 0 = Command completed successfully. 1 = Command failed. 2 = Phase error. */ static int usb_bulk_manage_status(mass_dev* dev, unsigned int tag) { int ret; csw_packet csw; //XPRINTF("USBHDFSD: usb_bulk_manage_status 1 ...\n"); ret = usb_bulk_status(dev, &csw, tag); /* Attempt to read CSW from bulk in endpoint */ if (ret != USB_RC_OK) { /* STALL bulk in -OR- Bulk error */ usb_bulk_clear_halt(dev, USB_BLK_EP_IN); /* clear the stall condition for bulk in */ XPRINTF("USBHDFSD: usb_bulk_manage_status error %d ...\n", ret); ret = usb_bulk_status(dev, &csw, tag); /* Attempt to read CSW from bulk in endpoint */ } /* CSW not valid or stalled or phase error */ if (ret != USB_RC_OK || csw.signature != CSW_TAG || csw.tag != tag || csw.status == 2) { printf("USBHDFSD: usb_bulk_manage_status call reset recovery ...\n"); usb_bulk_reset(dev, 3); /* Perform reset recovery */ } return((ret == USB_RC_OK && csw.signature == CSW_TAG && csw.tag == tag) ? csw.status : -1); }
/* see flow chart in the usbmassbulk_10.pdf doc (page 15) */ int usb_bulk_manage_status(mass_dev* dev, int tag) { int ret; csw_packet csw; //XPRINTF("USBHDFSD: usb_bulk_manage_status 1 ...\n"); ret = usb_bulk_status(dev, &csw, tag); /* Attempt to read CSW from bulk in endpoint */ if (ret < 0) { /* STALL bulk in -OR- Bulk error */ usb_bulk_clear_halt(dev, 0); /* clear the stall condition for bulk in */ XPRINTF("USBHDFSD: usb_bulk_manage_status stall ...\n"); ret = usb_bulk_status(dev, &csw, tag); /* Attempt to read CSW from bulk in endpoint */ } /* CSW not valid or stalled or phase error */ if (csw.signature != CSW_TAG || csw.tag != tag || ret == 2) { printf("USBHDFSD: usb_bulk_manage_status call reset recovery ...\n"); usb_bulk_reset(dev, 3); /* Perform reset recovery */ } return ret; }