CfgUSBLoader/cios/sdhc/main.c

224 lines
4.5 KiB
C
Raw Permalink Normal View History

/*
Custom IOS Module (SDHC)
Copyright (C) 2008 neimod.
Copyright (C) 2009 WiiGator.
Copyright (C) 2009 Waninkoko.
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 <string.h>
#include "es.h"
#include "ipc.h"
#include "mem.h"
#include "module.h"
#include "sdio.h"
#include "syscalls.h"
#include "timer.h"
#include "types.h"
#include "wbfs.h"
s32 __SDHC_Ioctlv(u32 cmd, ioctlv *vector, u32 inlen, u32 iolen)
{
s32 ret = IPC_EINVAL;
/* Invalidate cache */
InvalidateVector(vector, inlen, iolen);
/* Parse IOCTLV command */
switch (cmd) {
/** Initialize SDHC **/
case IOCTL_SDHC_INIT: {
/* Initialize SDIO */
ret = !sdio_Startup();
break;
}
/** Read sectors **/
case IOCTL_SDHC_READ: {
u32 sector = *(u32 *)(vector[0].data);
u32 numSectors = *(u32 *)(vector[1].data);
void *buffer = vector[2].data;
/* Read sectors */
ret = !sdio_ReadSectors(sector, numSectors, buffer);
break;
}
/** Write sectors **/
case IOCTL_SDHC_WRITE: {
u32 sector = *(u32 *)(vector[0].data);
u32 numSectors = *(u32 *)(vector[1].data);
void *buffer = vector[2].data;
/* Write sectors */
ret = !sdio_WriteSectors(sector, numSectors, buffer);
break;
}
/** Check for SD card **/
case IOCTL_SDHC_ISINSERTED: {
/* Check if SD card is inserted */
ret = !sdio_IsInserted();
break;
}
/** Open WBFS disc **/
case IOCTL_WBFS_OPEN_DISC: {
u8 *discid = (u8 *)(vector[0].data);
/* Open WBFS disc */
ret = WBFS_OpenDisc(discid);
break;
}
/** Read WBFS disc **/
case IOCTL_WBFS_READ_DISC: {
u32 offset = *(u32 *)(vector[0].data);
u32 len = *(u32 *)(vector[1].data);
void *buffer = vector[2].data;
/* Read WBFS disc */
ret = WBFS_Read(buffer, len, offset);
if (ret)
ret = 0x8000;
break;
}
default:
break;
}
/* Flush cache */
FlushVector(vector, inlen, iolen);
return ret;
}
s32 __SDHC_Initialize(u32 *queuehandle)
{
void *buffer = NULL;
s32 ret;
/* Initialize memory heap */
Mem_Init();
/* Initialize timer subsystem */
Timer_Init();
/* Allocate queue buffer */
buffer = Mem_Alloc(0x80);
if (!buffer)
return IPC_ENOMEM;
/* Create message queue */
ret = os_message_queue_create(buffer, 32);
if (ret < 0)
return ret;
/* Register devices */
os_device_register(DEVICE_NAME, ret);
/* Copy queue handler */
*queuehandle = ret;
return 0;
}
int main(void)
{
u32 queuehandle;
s32 ret;
/* Print info */
write("$IOSVersion: SDHC: " __DATE__ " " __TIME__ " 64M$\n");
/* Initialize module */
ret = __SDHC_Initialize(&queuehandle);
if (ret < 0)
return ret;
/* Main loop */
while (1) {
ipcmessage *message = NULL;
/* Wait for message */
os_message_queue_receive(queuehandle, (void *)&message, 0);
switch (message->command) {
case IOS_OPEN: {
u64 tid;
/* Get title ID */
ret = ES_GetTitleID(&tid);
/* Check title ID */
if (ret >= 0) {
write("SDHC: Title identified. Blocking opening request.\n");
ret = IPC_ENOENT;
break;
}
/* Check device path */
if (!strcmp(message->open.device, DEVICE_NAME))
ret = message->open.resultfd;
else
ret = IPC_ENOENT;
break;
}
case IOS_CLOSE: {
/* Close SDIO */
ret = !sdio_Shutdown();
break;
}
case IOS_IOCTLV: {
ioctlv *vector = message->ioctlv.vector;
u32 inlen = message->ioctlv.num_in;
u32 iolen = message->ioctlv.num_io;
u32 cmd = message->ioctlv.command;
/* Parse IOCTLV message */
ret = __SDHC_Ioctlv(cmd, vector, inlen, iolen);
break;
}
default:
/* Unknown command */
ret = IPC_EINVAL;
}
/* Acknowledge message */
os_message_queue_ack(message, ret);
}
return 0;
}