From 28a53bde17a90fa93c907d4533332fd048dccd1a Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Sun, 4 May 2008 23:21:18 +0200 Subject: [PATCH] usbstorage: error handling and better return codes --- usbstorage.c | 241 ++++++++++++++++++++++++++++------------------------------- usbstorage.h | 25 ++++++- 2 files changed, 135 insertions(+), 131 deletions(-) diff --git a/usbstorage.c b/usbstorage.c index f24430c..4a8e730 100644 --- a/usbstorage.c +++ b/usbstorage.c @@ -56,23 +56,16 @@ distribution. #define USB_ENDPOINT_BULK 0x02 -#ifdef DEBUG -#include -#define TRACE printf(" %d@%s\n", __LINE__, __FUNCTION__); -#else -#define TRACE -#endif - static s32 hId; -static inline s32 __usb_getdesc(s32 fd, u8 *buffer, u8 type, u8 index, u8 size) +static inline u16 bswap16(u16 s) { - return USB_WriteCtrlMsg(fd, USB_ENDPOINT_IN, USB_REQ_GETDESCRIPTOR, (type << 8) | index, 0, size, buffer); + return (s >> 8) | ((s & 0xFF) << 8); } -static inline u16 bswap16(u16 s) +static inline s32 __usb_getdesc(s32 fd, u8 *buffer, u8 type, u8 index, u8 size) { - return (s >> 8) | ((s & 0xFF) << 8); + return USB_WriteCtrlMsg(fd, USB_ENDPOINT_IN, USB_REQ_GETDESCRIPTOR, (type << 8) | index, 0, size, buffer); } s32 USB_GetDescriptors(s32 fd, _usb_devdesc *udd) @@ -158,7 +151,6 @@ s32 USB_GetDescriptors(s32 fd, _usb_devdesc *udd) ptr += ued->bLength; ued->wMaxPacketSize = bswap16(ued->wMaxPacketSize); } - } } @@ -181,7 +173,7 @@ void USB_FreeDescriptors(_usb_devdesc *udd) { for(iConf = 0; iConf < udd->bNumConfigurations; iConf++) { - ucd = &udd->configurations[iConf]; + ucd = &udd->configurations[iConf]; if(ucd->interfaces != NULL) { for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) @@ -196,7 +188,6 @@ void USB_FreeDescriptors(_usb_devdesc *udd) free(udd->configurations); } } - s32 USBStorage_Initialize() { hId = iosCreateHeap(HEAP_SIZE); @@ -229,7 +220,7 @@ static inline u32 __read32(u8 *p) static s32 __send_cbw(usbstorage_handle *dev, u32 len, u8 flags, const u8 *cb, u8 cbLen) { u8 *cbw = NULL; - s32 retval; + s32 retval = USBSTORAGE_OK; if(cbLen == 0 || cbLen > 16) return IPC_EINVAL; @@ -237,7 +228,6 @@ static s32 __send_cbw(usbstorage_handle *dev, u32 len, u8 flags, const u8 *cb, u cbw = iosAlloc(hId, CBW_SIZE); if(cbw == NULL) { - TRACE retval = IPC_ENOHEAP; goto free_and_return; } @@ -257,9 +247,9 @@ static s32 __send_cbw(usbstorage_handle *dev, u32 len, u8 flags, const u8 *cb, u retval = USB_WriteBlkMsg(dev->usb_fd, dev->ep_out, CBW_SIZE, (void *)cbw); if(retval == CBW_SIZE) - retval = 0; + retval = USBSTORAGE_OK; else if(retval > CBW_SIZE) - retval = IPC_EINVAL; + retval = USBSTORAGE_ESHORTWRITE; free_and_return: if(cbw != NULL) @@ -275,13 +265,12 @@ static s32 __send_cbw(usbstorage_handle *dev, u32 len, u8 flags, const u8 *cb, u static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue) { u8 *csw = NULL; - s32 retval; + s32 retval = USBSTORAGE_OK; u32 signature, tag, _dataResidue, _status; csw = iosAlloc(hId, CSW_SIZE); if(csw == NULL) { - TRACE retval = IPC_ENOHEAP; goto free_and_return; } @@ -291,11 +280,14 @@ static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue) retval = USB_ReadBlkMsg(dev->usb_fd, dev->ep_in, CSW_SIZE, csw); if(retval != CSW_SIZE) { - TRACE if(retval > 0) retval = IPC_EINVAL; + else + retval = USBSTORAGE_ESHORTREAD; goto free_and_return; } + else + retval = USBSTORAGE_OK; signature = __read32(csw); tag = __read32(csw + 4); @@ -304,8 +296,7 @@ static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue) if(signature != CSW_SIGNATURE) { - TRACE - retval = IPC_EINVAL; + retval = USBSTORAGE_ESIGNATURE; goto free_and_return; } @@ -316,8 +307,7 @@ static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue) if(tag != dev->tag) { - TRACE - retval = IPC_EINVAL; + retval = USBSTORAGE_ETAG; goto free_and_return; } @@ -335,7 +325,7 @@ static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue) static s32 __read_cycle(usbstorage_handle *dev, u8 *buffer, u32 len, u8 *cb, u8 cbLen) { - s32 retval; + s32 retval = USBSTORAGE_OK; u8 *bfr; u8 status; @@ -344,7 +334,6 @@ static s32 __read_cycle(usbstorage_handle *dev, u8 *buffer, u32 len, u8 *cb, u8 bfr = iosAlloc(hId, dev->ep_in_size); if(bfr == NULL) { - TRACE retval = IPC_ENOHEAP; goto free_and_error; } @@ -355,11 +344,9 @@ static s32 __read_cycle(usbstorage_handle *dev, u8 *buffer, u32 len, u8 *cb, u8 while(len > 0) { - TRACE retval = USB_ReadBlkMsg(dev->usb_fd, dev->ep_in, dev->ep_in_size, bfr); if(retval < 0) { - TRACE goto free_and_error; } @@ -374,20 +361,26 @@ static s32 __read_cycle(usbstorage_handle *dev, u8 *buffer, u32 len, u8 *cb, u8 retval = __read_csw(dev, &status, &dataResidue); if(retval < 0) { - TRACE goto free_and_error; } - if(status || dataResidue) + if(status) + { + retval = USBSTORAGE_ESTATUS; + USBStorage_Reset(dev); + goto free_and_error; + } + + if(dataResidue) { - TRACE - // TODO error handling - retval = -1; + retval = USBSTORAGE_EDATARESIDUE; + USBStorage_Reset(dev); goto free_and_error; } + retval = USBSTORAGE_OK; + free_and_error: - TRACE if(bfr != NULL) iosFree(hId, bfr); return retval; @@ -395,7 +388,7 @@ static s32 __read_cycle(usbstorage_handle *dev, u8 *buffer, u32 len, u8 *cb, u8 static s32 __write_cycle(usbstorage_handle *dev, const u8 *buffer, u32 len, u8 *cb, u8 cbLen) { - s32 retval; + s32 retval = USBSTORAGE_OK; u8 *bfr; u32 thisLen; @@ -405,7 +398,6 @@ static s32 __write_cycle(usbstorage_handle *dev, const u8 *buffer, u32 len, u8 * bfr = iosAlloc(hId, dev->ep_out_size); if(bfr == NULL) { - TRACE retval = IPC_ENOHEAP; goto free_and_error; } @@ -416,14 +408,14 @@ static s32 __write_cycle(usbstorage_handle *dev, const u8 *buffer, u32 len, u8 * while(len > 0) { - TRACE thisLen = len > dev->ep_out_size ? dev->ep_out_size : len; memset(bfr, 0, dev->ep_out_size); memcpy(bfr, buffer, thisLen); retval = USB_WriteBlkMsg(dev->usb_fd, dev->ep_out, thisLen, bfr); if(retval < 0) { - TRACE + retval = USBSTORAGE_EDATARESIDUE; + USBStorage_Reset(dev); goto free_and_error; } @@ -432,7 +424,8 @@ static s32 __write_cycle(usbstorage_handle *dev, const u8 *buffer, u32 len, u8 * if(retval != thisLen && len > 0) { - retval = -1; + retval = USBSTORAGE_EDATARESIDUE; + USBStorage_Reset(dev); goto free_and_error; } } @@ -440,31 +433,36 @@ static s32 __write_cycle(usbstorage_handle *dev, const u8 *buffer, u32 len, u8 * retval = __read_csw(dev, &status, &dataResidue); if(retval < 0) { - TRACE + USBStorage_Reset(dev); goto free_and_error; } - if(status || dataResidue) + if(status) + { + retval = USBSTORAGE_ESTATUS; + USBStorage_Reset(dev); + goto free_and_error; + } + + if(dataResidue) { - TRACE - // TODO error handling - retval = -1; + retval = USBSTORAGE_EDATARESIDUE; + USBStorage_Reset(dev); goto free_and_error; } + retval = USBSTORAGE_OK; + free_and_error: - TRACE if(buffer != NULL) iosFree(hId, bfr); return retval; } -usbstorage_handle *USBStorage_Open(const char *bus, u16 vid, u16 pid) +s32 USBStorage_Open(usbstorage_handle *dev, const char *bus, u16 vid, u16 pid) { - usbstorage_handle *dev = NULL; u8 cmd[16]; u8 *sense = NULL; - u8 status = 0; s32 retval = -1; u32 iConf, iInterface, iEp; @@ -473,13 +471,8 @@ usbstorage_handle *USBStorage_Open(const char *bus, u16 vid, u16 pid) usb_interfacedesc *uid; usb_endpointdesc *ued; - dev = calloc(1, sizeof(*dev)); - if(dev == NULL) - { - retval = IPC_ENOMEM; - goto free_and_return; - } - + memset(dev, 0, sizeof(*dev)); + dev->tag = TAG_START; if(LWP_MutexInit(&dev->lock, true) < 0) goto free_and_return; @@ -540,68 +533,16 @@ usbstorage_handle *USBStorage_Open(const char *bus, u16 vid, u16 pid) } USB_FreeDescriptors(&udd); + retval = USBSTORAGE_ENOINTERFACE; goto free_and_return; found: USB_FreeDescriptors(&udd); // TODO support for non-default configurations - - /* some devices needs this (TEST_UNIT_READY -> REQUEST_SENSE - * to be working... */ - memset(cmd, 0, sizeof(cmd)); - cmd[0] = SCSI_TEST_UNIT_READY; - - TRACE - retval = __send_cbw(dev, 0, CBW_IN, cmd, 1); - + retval = USBStorage_Reset(dev); if(retval < 0) - { - /* fatal error */ - TRACE - retval = -1; - goto free_and_return; - } - - retval = __read_csw(dev, &status, NULL); - if(status != 0) - { - TRACE - cmd[0] = SCSI_REQUEST_SENSE; - cmd[4] = SCSI_SENSE_REPLY_SIZE; - cmd[5] = 0; - retval = __send_cbw(dev, 0, CBW_IN, cmd, 6); - if(retval < 0) - { - /* fatal error */ - TRACE - retval = -1; - goto free_and_return; - } - - memset(sense, 0, SCSI_SENSE_REPLY_SIZE); - retval = USB_ReadBlkMsg(dev->usb_fd, dev->ep_in, SCSI_SENSE_REPLY_SIZE, sense); -#if 0 - if(retval < SCSI_SENSE_REPLY_SIZE) -#else - if(retval < 0) /* this retruns 0 on one of my sticks.. :/ */ -#endif - { - /* fatal error again */ - TRACE - retval = -1; - goto free_and_return; - } - - retval = __read_csw(dev, NULL, NULL); - if(retval < 0) - { - /* fatal error again */ - TRACE - retval = -1; - goto free_and_return; - } - } + goto free_and_error; memset(cmd, 0, sizeof(cmd)); memset(sense, 0, 8); @@ -609,7 +550,7 @@ usbstorage_handle *USBStorage_Open(const char *bus, u16 vid, u16 pid) retval = __read_cycle(dev, sense, 8, cmd, 1); if(retval < 0) { - TRACE + retval = USBSTORAGE_ECAPACITY; goto free_and_return; } memcpy(&dev->n_sectors, sense, 4); @@ -621,48 +562,92 @@ usbstorage_handle *USBStorage_Open(const char *bus, u16 vid, u16 pid) iosFree(hId, sense); if(retval < 0) { - TRACE LWP_MutexDestroy(dev->lock); - free(dev); - return NULL; + return retval; } - return dev; + return 0; } s32 USBStorage_Close(usbstorage_handle *dev) { USB_CloseDevice(&dev->usb_fd); LWP_MutexDestroy(dev->lock); - free(dev); + memset(dev, 0, sizeof(*dev)); return 0; } -// FIXME: remove the (void *)32 stuff when libogc gets updated s32 USBStorage_Reset(usbstorage_handle *dev) { s32 retval; + u8 status = 0; + u8 cmd[16]; + u8 *sense = NULL; + LWP_MutexLock(dev->lock); -#if 0 retval = USB_WriteCtrlMsg(dev->usb_fd, 33, 0xFF, dev->interface, 0, 0, NULL); -#else - retval = USB_WriteCtrlMsg(dev->usb_fd, 33, 0xFF, dev->interface, 0, 0, (void *)32); -#endif if(retval < 0) goto end; -#if 0 retval = USB_WriteCtrlMsg(dev->usb_fd, 2, 0x1, 0, dev->ep_in, 0, NULL); -#else - retval = USB_WriteCtrlMsg(dev->usb_fd, 2, 0x1, 0, dev->ep_in, 0, (void *)32); -#endif if(retval < 0) goto end; -#if 0 retval = USB_WriteCtrlMsg(dev->usb_fd, 2, 0x1, 0, dev->ep_out, 0, NULL); + + /* some devices needs this (TEST_UNIT_READY -> REQUEST_SENSE + * to be working... */ + sense = iosAlloc(hId, SCSI_SENSE_REPLY_SIZE); + if(sense == NULL) + { + retval = IPC_ENOMEM; + goto end; + } + + memset(cmd, 0, sizeof(cmd)); + cmd[0] = SCSI_TEST_UNIT_READY; + + retval = __send_cbw(dev, 0, CBW_IN, cmd, 1); + + if(retval < 0) + { + /* fatal error */ + goto end; + } + + retval = __read_csw(dev, &status, NULL); + if(status != 0) + { + cmd[0] = SCSI_REQUEST_SENSE; + cmd[4] = SCSI_SENSE_REPLY_SIZE; + cmd[5] = 0; + retval = __send_cbw(dev, 0, CBW_IN, cmd, 6); + if(retval < 0) + { + /* fatal error */ + goto end; + } + + memset(sense, 0, SCSI_SENSE_REPLY_SIZE); + retval = USB_ReadBlkMsg(dev->usb_fd, dev->ep_in, SCSI_SENSE_REPLY_SIZE, sense); +#if 0 + if(retval < SCSI_SENSE_REPLY_SIZE) #else - retval = USB_WriteCtrlMsg(dev->usb_fd, 2, 0x1, 0, dev->ep_out, 0, (void *)32); + if(retval < 0) /* this retruns 0 on one of my sticks.. :/ */ #endif + { + /* fatal error again */ + retval = USBSTORAGE_ESENSE; + goto end; + } + + retval = __read_csw(dev, NULL, NULL); + if(retval < 0) + { + /* fatal error again */ + goto end; + } + } end: + iosFree(hId, sense); LWP_MutexUnlock(dev->lock); return retval; } diff --git a/usbstorage.h b/usbstorage.h index a598157..94f74d0 100644 --- a/usbstorage.h +++ b/usbstorage.h @@ -1,8 +1,23 @@ #ifndef __USBSTORAGE_H #define __USBSTORAGE_H 1 +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + #include +#define USBSTORAGE_OK 0 +#define USBSTORAGE_ENOINTERFACE -10000 +#define USBSTORAGE_ESENSE -10001 +#define USBSTORAGE_ECAPACITY -10002 +#define USBSTORAGE_ESHORTWRITE -10003 +#define USBSTORAGE_ESHORTREAD -10004 +#define USBSTORAGE_ESIGNATURE -10005 +#define USBSTORAGE_ETAG -10006 +#define USBSTORAGE_ESTATUS -10007 +#define USBSTORAGE_EDATARESIDUE -10008 + #pragma pack(1) typedef struct _usbendpointdesc { @@ -41,7 +56,7 @@ typedef struct _usbconfdesc struct _usbinterfacedesc *interfaces; } usb_configurationdesc; -typedef struct __usbdevdesc +typedef struct _usbdevdesc { u8 bLength; u8 bDescriptorType; @@ -53,7 +68,7 @@ typedef struct __usbdevdesc u16 idVendor; u16 idProduct; u16 bcdDevice; - u8 iManufacturer; + u8 iManufactor; u8 iProduct; u8 iSerialNumber; u8 bNumConfigurations; @@ -89,7 +104,7 @@ void USB_FreeDescriptors(_usb_devdesc *udd); s32 USBStorage_Initialize(); s32 USBStorage_Deinitialize(); -usbstorage_handle *USBStorage_Open(const char *bus, u16 vid, u16 pid); +s32 USBStorage_Open(usbstorage_handle *dev, const char *bus, u16 vid, u16 pid); s32 USBStorage_Close(usbstorage_handle *dev); s32 USBStorage_Reset(usbstorage_handle *dev); @@ -98,4 +113,8 @@ s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u32 *sector_size, u32 *n_sec s32 USBStorage_Read(usbstorage_handle *dev, u32 sector, u8 *buffer, u16 n_sectors); s32 USBStorage_Write(usbstorage_handle *dev, u32 sector, const u8 *buffer, u16 n_sectors); +#ifdef __cplusplus + } +#endif /* __cplusplus */ + #endif -- 2.11.4.GIT