From dce315ba8f0349135793931ba185b230e10d0527 Mon Sep 17 00:00:00 2001 From: dborth Date: Thu, 11 Mar 2010 06:02:56 +0000 Subject: [PATCH] add usb2/dvd support via ios 202, kill dvdx support --- Makefile.wii | 8 +- source/ngc/button_mapping.h | 2 - source/ngc/fileop.cpp | 8 + source/ngc/snes9xGX.cpp | 55 +++- source/ngc/utils/ehcmodule_elf.h | 3 + source/ngc/utils/mload.c | 276 +++++++++++++++++++ source/ngc/utils/mload.h | 33 +++ source/ngc/utils/usb2storage.c | 451 +++++++++++++++++++++++++++++++ source/ngc/utils/usb2storage.h | 16 ++ 9 files changed, 846 insertions(+), 6 deletions(-) create mode 100644 source/ngc/utils/ehcmodule_elf.h create mode 100644 source/ngc/utils/mload.c create mode 100644 source/ngc/utils/mload.h create mode 100644 source/ngc/utils/usb2storage.c create mode 100644 source/ngc/utils/usb2storage.h diff --git a/Makefile.wii b/Makefile.wii index f48746b..9c73bc0 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -19,7 +19,8 @@ TARGET := snes9xgx-wii TARGETDIR := executables BUILD := build_wii SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts source/ngc/lang \ - source/ngc/gui source/ngc source/snes9x source/snes9x/apu \ + source/ngc/gui source/ngc source/ngc/utils \ + source/snes9x source/snes9x/apu \ source/sz source/unzip INCLUDES := source/snes9x source/ngc source/unzip @@ -41,7 +42,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -ldb -ldi -liso9660 -lpng -lmxml \ +LIBS := -ldi -liso9660 -lpng -lmxml \ -lfat -lwiiuse -lz -lbte -lasnd -logc -lvorbisidec -lfreetype -ltinysmb #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing @@ -86,7 +87,8 @@ export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ $(sFILES:.s=.o) $(SFILES:.S=.o) \ $(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \ $(PNGFILES:.png=.png.o) \ - $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) + $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) \ + $(CURDIR)/source/ngc/utils/ehcmodule.elf.o #--------------------------------------------------------------------------------- # build a list of include paths diff --git a/source/ngc/button_mapping.h b/source/ngc/button_mapping.h index fa9f1fa..ed5ee1f 100644 --- a/source/ngc/button_mapping.h +++ b/source/ngc/button_mapping.h @@ -34,8 +34,6 @@ typedef struct _ctrlr_map { BtnMap map[15]; // controller button map } CtrlrMap; -// externs: - extern CtrlrMap ctrlr_def[4]; #endif diff --git a/source/ngc/fileop.cpp b/source/ngc/fileop.cpp index 3fe9c8d..de10f32 100644 --- a/source/ngc/fileop.cpp +++ b/source/ngc/fileop.cpp @@ -321,6 +321,14 @@ void MountAllFAT() ***************************************************************************/ bool MountDVD(bool silent) { + #ifdef HW_RVL + if(IOS_GetVersion() != 202) + { + ErrorPrompt("Please install IOS 202 for DVD support."); + return false; + } + #endif + bool mounted = false; int retry = 1; diff --git a/source/ngc/snes9xGX.cpp b/source/ngc/snes9xGX.cpp index 54285bb..6da30e0 100644 --- a/source/ngc/snes9xGX.cpp +++ b/source/ngc/snes9xGX.cpp @@ -34,6 +34,8 @@ #include "apu/apu.h" #include "controls.h" +#include "utils/usb2storage.h" +#include "utils/mload.h" #include "snes9xGX.h" #include "networkop.h" #include "video.h" @@ -280,6 +282,48 @@ emulate () } // main loop } +/**************************************************************************** + * IOS 202 + ***************************************************************************/ +#ifdef HW_RVL +static bool FindIOS(u32 ios) +{ + s32 ret; + u32 n; + + u64 *titles = NULL; + u32 num_titles=0; + + ret = ES_GetNumTitles(&num_titles); + if (ret < 0) + return false; + + if(num_titles < 1) + return false; + + titles = (u64 *)memalign(32, num_titles * sizeof(u64) + 32); + if (!titles) + return false; + + ret = ES_GetTitles(titles, num_titles); + if (ret < 0) + { + free(titles); + return false; + } + + for(n=0; n < num_titles; n++) + { + if((titles[n] & 0xFFFFFFFF)==ios) + { + free(titles); + return true; + } + } + free(titles); + return false; +} +#endif /**************************************************************************** * USB Gecko Debugging ***************************************************************************/ @@ -345,7 +389,16 @@ main(int argc, char *argv[]) #endif #ifdef HW_RVL - DI_Init(); // first + // try to load IOS 202 + if(IOS_GetVersion() != 202 && FindIOS(202)) + IOS_ReloadIOS(202); + + DI_LoadDVDX(false); + DI_Init(); + + // load usb2 driver + if(mload_init() >= 0 && load_ehci_module()) + USB2Enable(true); #endif InitDeviceThread(); diff --git a/source/ngc/utils/ehcmodule_elf.h b/source/ngc/utils/ehcmodule_elf.h new file mode 100644 index 0000000..e2729ca --- /dev/null +++ b/source/ngc/utils/ehcmodule_elf.h @@ -0,0 +1,3 @@ +extern const u8 ehcmodule_elf_end[]; +extern const u8 ehcmodule_elf[]; +extern const u32 ehcmodule_elf_size; diff --git a/source/ngc/utils/mload.c b/source/ngc/utils/mload.c new file mode 100644 index 0000000..4ff589e --- /dev/null +++ b/source/ngc/utils/mload.c @@ -0,0 +1,276 @@ +/* mload.c (for PPC) (c) 2009, Hermes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "unistd.h" +#include "ehcmodule_elf.h" + +#define MLOAD_MLOAD_THREAD_ID 0x4D4C4400 +#define MLOAD_LOAD_MODULE 0x4D4C4480 +#define MLOAD_RUN_MODULE 0x4D4C4481 +#define MLOAD_RUN_THREAD 0x4D4C4482 + +#define MLOAD_STOP_THREAD 0x4D4C4484 +#define MLOAD_CONTINUE_THREAD 0x4D4C4485 + +#define MLOAD_GET_LOAD_BASE 0x4D4C4490 +#define MLOAD_MEMSET 0x4D4C4491 + +#define MLOAD_GET_EHCI_DATA 0x4D4C44A0 + +#define MLOAD_SET_ES_IOCTLV 0x4D4C44B0 + +#define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3])) + +typedef struct +{ + u32 ident0; + u32 ident1; + u32 ident2; + u32 ident3; + u32 machinetype; + u32 version; + u32 entry; + u32 phoff; + u32 shoff; + u32 flags; + u16 ehsize; + u16 phentsize; + u16 phnum; + u16 shentsize; + u16 shnum; + u16 shtrndx; +} elfheader; + +typedef struct +{ + u32 type; + u32 offset; + u32 vaddr; + u32 paddr; + u32 filesz; + u32 memsz; + u32 flags; + u32 align; +} elfphentry; + +typedef struct +{ + void *start; + int prio; + void *stack; + int size_stack; +} data_elf; + +static const char mload_fs[] ATTRIBUTE_ALIGN(32) = "/dev/mload"; +static s32 mload_fd = -1; + +// to init/test if the device is running +int mload_init() +{ + int n; + + if (mload_fd >= 0) + return 0; + + for (n = 0; n < 10; n++) // try 2.5 seconds + { + mload_fd = IOS_Open(mload_fs, 0); + + if (mload_fd >= 0) + break; + + usleep(250 * 1000); + } + + return mload_fd; +} + +// to close the device (remember call it when rebooting the IOS!) +int mload_close() +{ + int ret; + + if (mload_fd < 0) + return -1; + + ret = IOS_Close(mload_fd); + + mload_fd = -1; + + return ret; +} + +// fix starlet address to read/write (uses SEEK_SET, etc as mode) +static int mload_seek(int offset, int mode) +{ + if (mload_init() < 0) + return -1; + return IOS_Seek(mload_fd, offset, mode); +} + +// write bytes from starlet (it update the offset) +static int mload_write(const void * buf, u32 size) +{ + if (mload_init() < 0) + return -1; + return IOS_Write(mload_fd, buf, size); +} + +// fill a block (similar to memset) +static int mload_memset(void *starlet_addr, int set, int len) +{ + int ret; + s32 hid = -1; + + if (mload_init() < 0) + return -1; + + hid = iosCreateHeap(0x800); + + if (hid < 0) + return hid; + + ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_MEMSET, "iii:", starlet_addr, + set, len); + + iosDestroyHeap(hid); + + return ret; +} + +// load a module from the PPC +// the module must be a elf made with stripios +static int mload_elf(void *my_elf, data_elf *data_elf) +{ + int n, m; + int p; + u8 *adr; + u32 elf = (u32) my_elf; + + if (elf & 3) + return -1; // aligned to 4 please! + + elfheader *head = (void *) elf; + elfphentry *entries; + + if (head->ident0 != 0x7F454C46) + return -1; + if (head->ident1 != 0x01020161) + return -1; + if (head->ident2 != 0x01000000) + return -1; + + p = head->phoff; + + data_elf->start = (void *) head->entry; + + for (n = 0; n < head->phnum; n++) + { + entries = (void *) (elf + p); + p += sizeof(elfphentry); + + if (entries->type == 4) + { + adr = (void *) (elf + entries->offset); + + if (getbe32(0) != 0) + return -2; // bad info (sure) + + for (m = 4; m < entries->memsz; m += 8) + { + switch (getbe32(m)) + { + case 0x9: + data_elf->start = (void *) getbe32(m+4); + break; + case 0x7D: + data_elf->prio = getbe32(m+4); + break; + case 0x7E: + data_elf->size_stack = getbe32(m+4); + break; + case 0x7F: + data_elf->stack = (void *) (getbe32(m+4)); + break; + + } + } + } + else if (entries->type == 1 && entries->memsz != 0 && entries->vaddr != 0) + { + + if (mload_memset((void *) entries->vaddr, 0, entries->memsz) < 0) + return -1; + if (mload_seek(entries->vaddr, SEEK_SET) < 0) + return -1; + if (mload_write((void *) (elf + entries->offset), entries->filesz) < 0) + return -1; + } + } + + return 0; +} + +// run one thread (you can use to load modules or binary files) +static int mload_run_thread(void *starlet_addr, void *starlet_top_stack, + int stack_size, int priority) +{ + int ret; + s32 hid = -1; + + if (mload_init() < 0) + return -1; + + hid = iosCreateHeap(0x800); + + if (hid < 0) + return hid; + + ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_THREAD, "iiii:", + starlet_addr, starlet_top_stack, stack_size, priority); + + iosDestroyHeap(hid); + + return ret; +} + +bool load_ehci_module() +{ + data_elf my_data_elf; + my_data_elf.start = NULL; + my_data_elf.prio = 0; + my_data_elf.stack = NULL; + my_data_elf.size_stack = 0; + + if(mload_elf((void *) ehcmodule_elf, &my_data_elf) != 0) + return false; + + if (mload_run_thread(my_data_elf.start, my_data_elf.stack, + my_data_elf.size_stack, my_data_elf.prio) < 0) + { + usleep(1000); + if (mload_run_thread(my_data_elf.start, my_data_elf.stack, + my_data_elf.size_stack, 0x47) < 0) + return false; + } + return true; +} diff --git a/source/ngc/utils/mload.h b/source/ngc/utils/mload.h new file mode 100644 index 0000000..db6bb5b --- /dev/null +++ b/source/ngc/utils/mload.h @@ -0,0 +1,33 @@ +/* mload.c (for PPC) (c) 2009, Hermes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __MLOAD_H__ +#define __MLOAD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int mload_init(); +bool load_ehci_module(); +int mload_close(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/ngc/utils/usb2storage.c b/source/ngc/utils/usb2storage.c new file mode 100644 index 0000000..3e49689 --- /dev/null +++ b/source/ngc/utils/usb2storage.c @@ -0,0 +1,451 @@ +/*------------------------------------------------------------- + +usb2storage.c -- USB mass storage support, inside starlet +Copyright (C) 2008 Kwiirk +Improved for homebrew by rodries + +If this driver is linked before libogc, this will replace the original +usbstorage driver by svpe from libogc + +CIOS_usb2 must be loaded! + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + + -------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG_USB2 + +#ifdef DEBUG_USB2 +#define debug_printf(fmt, args...) \ + fprintf(stderr, "%s:%d:" fmt, __FUNCTION__, __LINE__, ##args) +#else +#define debug_printf(fmt, args...) +#endif // DEBUG_USB2 + +#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8)) +#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1) +#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2) +#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3) +#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4) +#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5) +#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6) +#define USB_IOCTL_UMS_IS_INSERTED (UMS_BASE+0x7) + +#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10) +#define USB_IOCTL_UMS_START (UMS_BASE+0x11) +#define USB_IOCTL_UMS_STOP (UMS_BASE+0x12) +#define USB_IOCTL_UMS_EXIT (UMS_BASE+0x16) + +#define UMS_HEAPSIZE 2*1024 +#define UMS_MAXPATH 16 + +static s32 hId = -1; +static s32 fd = -1; +static u32 sector_size; +static s32 usb2 = -1; +static mutex_t usb2_mutex = LWP_MUTEX_NULL; +static u8 *fixed_buffer = NULL; +static s32 usb2_inited = 0; + +#define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f) +#define USB2_BUFFER 128*1024 +static heap_cntrl usb2_heap; +static u8 __usb2_heap_created = 0; + +static DISC_INTERFACE __io_usb1storage; +static int usb1disc_inited = 0; +extern const DISC_INTERFACE __io_usb2storage; +static int currentMode = 2; // 1 = use USB1 interface, 2 = use USB2 interface + +static s32 USB2CreateHeap() +{ + u32 level; + void *usb2_heap_ptr; + + _CPU_ISR_Disable(level); + + if (__usb2_heap_created != 0) + { + _CPU_ISR_Restore(level); + return IPC_OK; + } + + usb2_heap_ptr = (void *) ROUNDDOWN32(((u32)SYS_GetArena2Hi() - (USB2_BUFFER+(4*1024)))); + if ((u32) usb2_heap_ptr < (u32) SYS_GetArena2Lo()) + { + _CPU_ISR_Restore(level); + return IPC_ENOMEM; + } + SYS_SetArena2Hi(usb2_heap_ptr); + __lwp_heap_init(&usb2_heap, usb2_heap_ptr, (USB2_BUFFER + (4 * 1024)), 32); + __usb2_heap_created = 1; + _CPU_ISR_Restore(level); + return IPC_OK; +} + +static s32 USB2Storage_Initialize(int verbose) +{ + s32 ret = USB_OK; + u32 size = 0; + char *devicepath = NULL; + + //if(usb2_inited) return ret; + + if (usb2_mutex == LWP_MUTEX_NULL) + LWP_MutexInit(&usb2_mutex, false); + + LWP_MutexLock(usb2_mutex); + + if (hId == -1) + hId = iosCreateHeap(UMS_HEAPSIZE); + + if (hId < 0) + { + LWP_MutexUnlock(usb2_mutex); + debug_printf("error IPC_ENOMEM\n",fd); + return IPC_ENOMEM; + } + + if (USB2CreateHeap() != IPC_OK) + { + debug_printf("error USB2 IPC_ENOMEM\n",fd); + return IPC_ENOMEM; + } + + if (fixed_buffer == NULL) + fixed_buffer = __lwp_heap_allocate(&usb2_heap, USB2_BUFFER); + + if (fd < 0) + { + devicepath = iosAlloc(hId, UMS_MAXPATH); + if (devicepath == NULL) + { + LWP_MutexUnlock(usb2_mutex); + return IPC_ENOMEM; + } + + snprintf(devicepath, USB_MAXPATH, "/dev/usb2"); + fd = IOS_Open(devicepath, 0); + iosFree(hId, devicepath); + } + + ret = fd; + debug_printf("usb2 fd: %d\n",fd); + usleep(500); + + if (fd > 0) + { + if (verbose) + ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_SET_VERBOSE, ":"); + ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_INIT, ":"); + debug_printf("usb2 init value: %i\n", ret); + + if (ret < 0) + debug_printf("usb2 error init\n"); + else + size = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", + §or_size); + debug_printf("usb2 GET_CAPACITY: %d\n", size); + + if (size == 0) + ret = -2012; + else + ret = 1; + } + else + { + ret = -1; + } + + LWP_MutexUnlock(usb2_mutex); + + if(ret >= 0) + usb2_inited = 1; + + return ret; +} + +static inline int is_MEM2_buffer(const void *buffer) +{ + u32 high_addr = ((u32) buffer) >> 24; + return (high_addr == 0x90) || (high_addr == 0xD0); +} + +void USB2Enable(bool enable) +{ + if(!usb1disc_inited) + { + usb1disc_inited = 1; + memcpy(&__io_usb1storage, &__io_usbstorage, sizeof(DISC_INTERFACE)); + } + + if(!enable) + { + __io_usbstorage = __io_usb1storage; + } + else + { + //USB2Storage_Initialize(0); + __io_usbstorage = __io_usb2storage; + } +} + +/* +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",§or_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) +{ + bool ret; + + usb2 = USB2Storage_Initialize(0); + + if(usb2 >= 0) + { + currentMode = 2; + ret = true; + } + else if (usb2 < 0) + { + ret = __io_usb1storage.startup(); + + if(ret) + currentMode = 1; + } + return ret; +} + +static bool __usb2storage_IsInserted(void) +{ + int retval; + bool ret = false; + + if (usb2 == -1) + { + retval = __usb2storage_Startup(); + debug_printf("__usb2storage_Startup ret: %d fd: %i\n",retval,fd); + } + //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); + + if (retval > 0) + { + 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) + { + debug_printf("isinserted usb1 retval: %d\n",retval); + currentMode = 1; + ret = true; + } + } + debug_printf("final isinserted usb2 retval: %d ret: %d\n",retval,ret); + LWP_MutexUnlock(usb2_mutex); + return ret; +} + +static bool __usb2storage_ReadSectors(u32 sector, u32 numSectors, void *buffer) +{ + s32 ret = 1; + u32 sectors = 0; + uint8_t *dest = buffer; + + if (currentMode == 1) + return __io_usb1storage.readSectors(sector, numSectors, buffer); + + if (fd < 1) + return IPC_ENOENT; + + LWP_MutexLock(usb2_mutex); + + while (numSectors > 0) + { + if (numSectors * sector_size > USB2_BUFFER) + sectors = USB2_BUFFER / sector_size; + else + sectors = numSectors; + + if (!is_MEM2_buffer(dest)) //libfat is not providing us good buffers :-( + { + ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", + sector, sectors, fixed_buffer, sector_size * sectors); + memcpy(dest, fixed_buffer, sector_size * sectors); + } + else + ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", + sector, sectors, dest, sector_size * sectors); + + dest += sector_size * sectors; + if (ret < 1) break; + + sector += sectors; + numSectors -= sectors; + } + if(ret<1)usb2 = -1; + LWP_MutexUnlock(usb2_mutex); + if (ret < 1) return false; + return true; +} + +static bool __usb2storage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) +{ + s32 ret = 1; + u32 sectors = 0; + uint8_t *dest = (uint8_t *) buffer; + + if (currentMode == 1) + return __io_usb1storage.writeSectors(sector, numSectors, buffer); + + if (fd < 1) + return IPC_ENOENT; + + LWP_MutexLock(usb2_mutex); + while (numSectors > 0 && ret > 0) + { + if (numSectors * sector_size > USB2_BUFFER) + sectors = USB2_BUFFER / sector_size; + else + sectors = numSectors; + + numSectors -= sectors; + + if (!is_MEM2_buffer(dest)) // libfat is not providing us good buffers :-( + { + memcpy(fixed_buffer, dest, sector_size * sectors); + ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_WRITE_SECTORS, + "ii:d", sector, sectors, fixed_buffer, sector_size + * sectors); + } + else + ret = IOS_IoctlvFormat(hId, fd, USB_IOCTL_UMS_WRITE_SECTORS, + "ii:d", sector, sectors, dest, sector_size * sectors); + if (ret < 1)break; + + dest += sector_size * sectors; + sector += sectors; + } + LWP_MutexUnlock(usb2_mutex); + if(ret < 1 ) return false; + return true; +} + +static bool __usb2storage_ClearStatus(void) +{ + if (currentMode == 1) + return __io_usb1storage.clearStatus(); + + return true; +} + +static bool __usb2storage_Shutdown(void) +{ + if (currentMode == 1) + return __io_usb1storage.shutdown(); + + LWP_MutexLock(usb2_mutex); + debug_printf("__usb2storage_Shutdown\n"); + usb2 = -1; + LWP_MutexUnlock(usb2_mutex); + return true; +} + +const DISC_INTERFACE __io_usb2storage = { + DEVICE_TYPE_WII_USB, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB, + (FN_MEDIUM_STARTUP) & __usb2storage_Startup, + (FN_MEDIUM_ISINSERTED) & __usb2storage_IsInserted, + (FN_MEDIUM_READSECTORS) & __usb2storage_ReadSectors, + (FN_MEDIUM_WRITESECTORS) & __usb2storage_WriteSectors, + (FN_MEDIUM_CLEARSTATUS) & __usb2storage_ClearStatus, + (FN_MEDIUM_SHUTDOWN) & __usb2storage_Shutdown +}; diff --git a/source/ngc/utils/usb2storage.h b/source/ngc/utils/usb2storage.h new file mode 100644 index 0000000..7193a30 --- /dev/null +++ b/source/ngc/utils/usb2storage.h @@ -0,0 +1,16 @@ + +#ifndef __USB2STORAGE_H__ +#define __USB2STORAGE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void USB2Enable(bool enable); + +#ifdef __cplusplus + } +#endif + + +#endif