improved USB code

This commit is contained in:
dborth 2010-04-28 05:59:19 +00:00
parent e92a333f17
commit a4208bb19a
2 changed files with 139 additions and 198 deletions

View File

@ -1,36 +1,31 @@
/*------------------------------------------------------------- /****************************************************************************
* WiiMC
usb2storage.c -- USB mass storage support, inside starlet * usb2storage.c -- USB mass storage support, inside starlet
Copyright (C) 2008 Kwiirk * Copyright (C) 2008 Kwiirk
Improved for homebrew by rodries * Improved for homebrew by rodries and Tantric
*
If this driver is linked before libogc, this will replace the original * IOS 202 and the ehcmodule must be loaded before using this!
usbstorage driver by svpe from libogc *
* This software is provided 'as-is', without any express or implied
CIOS_usb2 must be loaded! * warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
This software is provided 'as-is', without any express or implied *
warranty. In no event will the authors be held liable for any * Permission is granted to anyone to use this software for any
damages arising from the use of this software. * purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
Permission is granted to anyone to use this software for any *
purpose, including commercial applications, and to alter it and * 1. The origin of this software must not be misrepresented; you
redistribute it freely, subject to the following restrictions: * must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
1. The origin of this software must not be misrepresented; you * documentation would be appreciated but is not required.
must not claim that you wrote the original software. If you use *
this software in a product, an acknowledgment in the product * 2. Altered source versions must be plainly marked as such, and
documentation would be appreciated but is not required. * must not be misrepresented as being the original software.
*
2. Altered source versions must be plainly marked as such, and * 3. This notice may not be removed or altered from any source
must not be misrepresented as being the original software. * distribution.
*
3. This notice may not be removed or altered from any source ***************************************************************************/
distribution.
-------------------------------------------------------------*/
#ifdef HW_RVL
#include <gccore.h> #include <gccore.h>
@ -43,7 +38,6 @@ distribution.
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <ogc/machine/processor.h> #include <ogc/machine/processor.h>
#include <ogc/ipc.h>
//#define DEBUG_USB2 //#define DEBUG_USB2
@ -72,12 +66,10 @@ distribution.
#define UMS_MAXPATH 16 #define UMS_MAXPATH 16
static s32 hId = -1; static s32 hId = -1;
static s32 fd = -1; static s32 __usb2fd = -1;
static u32 sector_size; static u32 sector_size;
static s32 usb2 = -1;
static mutex_t usb2_mutex = LWP_MUTEX_NULL; static mutex_t usb2_mutex = LWP_MUTEX_NULL;
static u8 *fixed_buffer = NULL; static u8 *fixed_buffer = NULL;
static s32 usb2_inited = 0;
#define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f) #define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f)
#define USB2_BUFFER 128*1024 #define USB2_BUFFER 128*1024
@ -94,13 +86,10 @@ static s32 USB2CreateHeap()
u32 level; u32 level;
void *usb2_heap_ptr; void *usb2_heap_ptr;
_CPU_ISR_Disable(level);
if (__usb2_heap_created != 0) if (__usb2_heap_created != 0)
{
_CPU_ISR_Restore(level);
return IPC_OK; return IPC_OK;
}
_CPU_ISR_Disable(level);
usb2_heap_ptr = (void *) ROUNDDOWN32(((u32)SYS_GetArena2Hi() - (USB2_BUFFER+(4*1024)))); usb2_heap_ptr = (void *) ROUNDDOWN32(((u32)SYS_GetArena2Hi() - (USB2_BUFFER+(4*1024))));
if ((u32) usb2_heap_ptr < (u32) SYS_GetArena2Lo()) if ((u32) usb2_heap_ptr < (u32) SYS_GetArena2Lo())
@ -115,39 +104,53 @@ static s32 USB2CreateHeap()
return IPC_OK; return IPC_OK;
} }
static s32 USB2Storage_Initialize(int verbose) static s32 USB2Storage_Initialize()
{ {
s32 ret = USB_OK; static bool inited = false;
u32 size = 0;
char *devicepath = NULL; if(inited)
return 0;
//if(usb2_inited) return ret;
if (usb2_mutex == LWP_MUTEX_NULL) if (usb2_mutex == LWP_MUTEX_NULL)
LWP_MutexInit(&usb2_mutex, false); LWP_MutexInit(&usb2_mutex, false);
LWP_MutexLock(usb2_mutex);
if (hId == -1) if (hId == -1)
hId = iosCreateHeap(UMS_HEAPSIZE); hId = iosCreateHeap(UMS_HEAPSIZE);
if (hId < 0) if (hId < 0)
{ {
LWP_MutexUnlock(usb2_mutex); debug_printf("error IPC_ENOMEM\n");
debug_printf("error IPC_ENOMEM\n",fd);
return IPC_ENOMEM; return IPC_ENOMEM;
} }
if (USB2CreateHeap() != IPC_OK) if (USB2CreateHeap() != IPC_OK)
{ {
debug_printf("error USB2 IPC_ENOMEM\n",fd); debug_printf("error USB2 IPC_ENOMEM\n");
return IPC_ENOMEM; return IPC_ENOMEM;
} }
if (fixed_buffer == NULL) if (fixed_buffer == NULL)
fixed_buffer = __lwp_heap_allocate(&usb2_heap, USB2_BUFFER); fixed_buffer = __lwp_heap_allocate(&usb2_heap, USB2_BUFFER);
if (fd < 0) inited = true;
return 0;
}
static s32 USB2Storage_Open(int verbose)
{
char *devicepath = NULL;
s32 ret = USB_OK;
u32 size = 0;
if(__usb2fd > 0)
return 0;
if(USB2Storage_Initialize() < 0)
return -1;
LWP_MutexLock(usb2_mutex);
if (__usb2fd <= 0)
{ {
devicepath = iosAlloc(hId, UMS_MAXPATH); devicepath = iosAlloc(hId, UMS_MAXPATH);
if (devicepath == NULL) if (devicepath == NULL)
@ -157,46 +160,42 @@ static s32 USB2Storage_Initialize(int verbose)
} }
snprintf(devicepath, USB_MAXPATH, "/dev/usb2"); snprintf(devicepath, USB_MAXPATH, "/dev/usb2");
fd = IOS_Open(devicepath, 0); __usb2fd = IOS_Open(devicepath, 0);
iosFree(hId, devicepath); iosFree(hId, devicepath);
} }
ret = fd; if(__usb2fd <= 0)
debug_printf("usb2 fd: %d\n",fd); return -1;
usleep(500);
if (fd > 0) if (verbose)
{ ret = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_SET_VERBOSE, ":");
if (verbose) ret = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_INIT, ":");
ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_SET_VERBOSE, ":"); debug_printf("usb2 init value: %i\n", ret);
ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_INIT, ":");
debug_printf("usb2 init value: %i\n", ret);
if (ret < 0) if (ret < 0)
debug_printf("usb2 error init\n"); debug_printf("usb2 error init\n");
else
size = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i",
&sector_size);
debug_printf("usb2 GET_CAPACITY: %d\n", size);
if (size == 0)
ret = -2012;
else
ret = 1;
}
else else
{ size = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_GET_CAPACITY, ":i",
ret = -1; &sector_size);
} debug_printf("usb2 GET_CAPACITY: %d\n", size);
LWP_MutexUnlock(usb2_mutex); if (size == 0)
ret = -2012;
if(ret >= 0) else
usb2_inited = 1; ret = 1;
return ret; return ret;
} }
static void USB2Storage_Close()
{
if(__usb2fd <= 0)
return;
IOS_Close(__usb2fd);
__usb2fd = -1;
}
static inline int is_MEM2_buffer(const void *buffer) static inline int is_MEM2_buffer(const void *buffer)
{ {
u32 high_addr = ((u32) buffer) >> 24; u32 high_addr = ((u32) buffer) >> 24;
@ -213,128 +212,61 @@ void USB2Enable(bool enable)
if(!enable) if(!enable)
{ {
__io_usbstorage = __io_usb1storage; memcpy(&__io_usbstorage, &__io_usb1storage, sizeof(DISC_INTERFACE));
} }
else else
{ {
//USB2Storage_Initialize(0); USB2Storage_Initialize();
__io_usbstorage = __io_usb2storage; memcpy(&__io_usbstorage, &__io_usb2storage, sizeof(DISC_INTERFACE));
} }
} }
/*
static s32 USB2Storage_Get_Capacity(u32*_sector_size)
{
if(fd>0)
{
LWP_MutexLock(usb2_mutex);
s32 ret = IOS_IoctlvFormat(hId,fd,USB_IOCTL_UMS_GET_CAPACITY,":i",&sector_size);
if(_sector_size)
*_sector_size = sector_size;
LWP_MutexUnlock(usb2_mutex);
return ret;
}
else
return IPC_ENOENT;
}
s32 GetInitValue()
{
return usb2_init_value;
}
s32 USB2Unmount()
{
return IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_UMOUNT, ":");
}
s32 USB2Start()
{
return IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_START, ":");
}
s32 USB2Stop()
{
return IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_STOP, ":");
}
void USB2Close()
{
if (fd > 0)
IOS_Close(fd);
fd = -1;
}
int USB2ReadSector(u32 sector)
{
void *b;
s32 ret;
b = malloc(1024);
ret = USBStorage_Read_Sectors(sector, 1, b);
free(b);
return ret;
}
*/
static bool __usb2storage_Startup(void) static bool __usb2storage_Startup(void)
{ {
bool ret; if(__usb2fd > 0)
return true;
usb2 = USB2Storage_Initialize(0); USB2Storage_Open(0);
if(usb2 >= 0) if(__usb2fd > 0)
{ {
currentMode = 2; currentMode = 2;
ret = true; return true;
} }
else if (usb2 < 0)
if(__io_usb1storage.startup())
{ {
ret = __io_usb1storage.startup(); currentMode = 1;
return true;
if(ret)
currentMode = 1;
} }
return ret; return false;
} }
static bool __usb2storage_IsInserted(void) static bool __usb2storage_IsInserted(void)
{ {
int retval; if (!__usb2storage_Startup())
bool ret = false; return false;
if (usb2 == -1) if(usb2_mutex == LWP_MUTEX_NULL)
return false;
if (__usb2fd > 0)
{ {
retval = __usb2storage_Startup(); LWP_MutexLock(usb2_mutex);
debug_printf("__usb2storage_Startup ret: %d fd: %i\n",retval,fd); int retval = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_IS_INSERTED, ":");
} LWP_MutexUnlock(usb2_mutex);
//else
LWP_MutexLock(usb2_mutex);
if (fd > 0)
{
retval = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_IS_INSERTED, ":");
debug_printf("isinserted usb2 retval: %d ret: %d\n",retval,ret); debug_printf("isinserted usb2 retval: %d ret: %d\n",retval,ret);
if (retval > 0) if (retval > 0)
{ return true;
currentMode = 2;
ret = true;
debug_printf("isinserted(2) usb2 retval: %d ret: %d\n",retval,ret);
}
} }
if(ret==false)
{
retval = __io_usb1storage.isInserted();
if (retval > 0) if (__io_usb1storage.isInserted() > 0)
{ {
debug_printf("isinserted usb1 retval: %d\n",retval); debug_printf("isinserted usb1 retval: %d\n",retval);
currentMode = 1; return true;
ret = true;
}
} }
debug_printf("final isinserted usb2 retval: %d ret: %d\n",retval,ret); return false;
LWP_MutexUnlock(usb2_mutex);
return ret;
} }
static bool __usb2storage_ReadSectors(u32 sector, u32 numSectors, void *buffer) static bool __usb2storage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
@ -342,12 +274,12 @@ static bool __usb2storage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
s32 ret = 1; s32 ret = 1;
u32 sectors = 0; u32 sectors = 0;
uint8_t *dest = buffer; uint8_t *dest = buffer;
if (currentMode == 1) if (currentMode == 1)
return __io_usb1storage.readSectors(sector, numSectors, buffer); return __io_usb1storage.readSectors(sector, numSectors, buffer);
if (fd < 1) if (__usb2fd < 1 || usb2_mutex == LWP_MUTEX_NULL)
return IPC_ENOENT; return false;
LWP_MutexLock(usb2_mutex); LWP_MutexLock(usb2_mutex);
@ -360,12 +292,12 @@ static bool __usb2storage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
if (!is_MEM2_buffer(dest)) //libfat is not providing us good buffers :-( if (!is_MEM2_buffer(dest)) //libfat is not providing us good buffers :-(
{ {
ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", ret = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d",
sector, sectors, fixed_buffer, sector_size * sectors); sector, sectors, fixed_buffer, sector_size * sectors);
memcpy(dest, fixed_buffer, sector_size * sectors); memcpy(dest, fixed_buffer, sector_size * sectors);
} }
else else
ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", ret = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d",
sector, sectors, dest, sector_size * sectors); sector, sectors, dest, sector_size * sectors);
dest += sector_size * sectors; dest += sector_size * sectors;
@ -374,7 +306,7 @@ static bool __usb2storage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
sector += sectors; sector += sectors;
numSectors -= sectors; numSectors -= sectors;
} }
if(ret<1)usb2 = -1; if(ret<1) USB2Storage_Close();
LWP_MutexUnlock(usb2_mutex); LWP_MutexUnlock(usb2_mutex);
if (ret < 1) return false; if (ret < 1) return false;
return true; return true;
@ -385,12 +317,12 @@ static bool __usb2storage_WriteSectors(u32 sector, u32 numSectors, const void *b
s32 ret = 1; s32 ret = 1;
u32 sectors = 0; u32 sectors = 0;
uint8_t *dest = (uint8_t *) buffer; uint8_t *dest = (uint8_t *) buffer;
if (currentMode == 1) if (currentMode == 1)
return __io_usb1storage.writeSectors(sector, numSectors, buffer); return __io_usb1storage.writeSectors(sector, numSectors, buffer);
if (fd < 1) if (__usb2fd < 1 || usb2_mutex == LWP_MUTEX_NULL)
return IPC_ENOENT; return false;
LWP_MutexLock(usb2_mutex); LWP_MutexLock(usb2_mutex);
while (numSectors > 0 && ret > 0) while (numSectors > 0 && ret > 0)
@ -405,12 +337,12 @@ static bool __usb2storage_WriteSectors(u32 sector, u32 numSectors, const void *b
if (!is_MEM2_buffer(dest)) // libfat is not providing us good buffers :-( if (!is_MEM2_buffer(dest)) // libfat is not providing us good buffers :-(
{ {
memcpy(fixed_buffer, dest, sector_size * sectors); memcpy(fixed_buffer, dest, sector_size * sectors);
ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_WRITE_SECTORS, ret = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_WRITE_SECTORS,
"ii:d", sector, sectors, fixed_buffer, sector_size "ii:d", sector, sectors, fixed_buffer, sector_size
* sectors); * sectors);
} }
else else
ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_WRITE_SECTORS, ret = IOS_IoctlvFormat(hId, __usb2fd, USB_IOCTL_UMS_WRITE_SECTORS,
"ii:d", sector, sectors, dest, sector_size * sectors); "ii:d", sector, sectors, dest, sector_size * sectors);
if (ret < 1)break; if (ret < 1)break;
@ -435,9 +367,12 @@ static bool __usb2storage_Shutdown(void)
if (currentMode == 1) if (currentMode == 1)
return __io_usb1storage.shutdown(); return __io_usb1storage.shutdown();
if(usb2_mutex == LWP_MUTEX_NULL)
return false;
LWP_MutexLock(usb2_mutex); LWP_MutexLock(usb2_mutex);
USB2Storage_Close();
debug_printf("__usb2storage_Shutdown\n"); debug_printf("__usb2storage_Shutdown\n");
usb2 = -1;
LWP_MutexUnlock(usb2_mutex); LWP_MutexUnlock(usb2_mutex);
return true; return true;
} }
@ -452,4 +387,3 @@ const DISC_INTERFACE __io_usb2storage = {
(FN_MEDIUM_CLEARSTATUS) & __usb2storage_ClearStatus, (FN_MEDIUM_CLEARSTATUS) & __usb2storage_ClearStatus,
(FN_MEDIUM_SHUTDOWN) & __usb2storage_Shutdown (FN_MEDIUM_SHUTDOWN) & __usb2storage_Shutdown
}; };
#endif

View File

@ -1,16 +1,23 @@
/****************************************************************************
* WiiMC
* usb2storage.h -- USB mass storage support, inside starlet
* Copyright (C) 2008 Kwiirk
* Improved for homebrew by rodries and Tantric
*
* IOS 202 and the ehcimodule must be loaded before using this!
***************************************************************************/
#ifndef __USB2STORAGE_H__ #ifndef __USB2STORAGE_H__
#define __USB2STORAGE_H__ #define __USB2STORAGE_H__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void USB2Enable(bool enable); void USB2Enable(bool e);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif