s32 USB_DeviceInsertNotifyAsync(const char *devpath,u16 vid,u16 pid,usbcallback cb,void *usrdata) { char *path; s32 fd = -1; s32 ret = IPC_ENOMEM; u16 *pvid = NULL; u16 *ppid = NULL; ioctlv *vec = NULL; struct _usb_cb *msgcb = NULL; if(devpath==NULL || *devpath=='\0') return IPC_EINVAL; path = (char*)iosAlloc(hId,IPC_MAXPATH_LEN); if(path==NULL) return IPC_ENOMEM; strncpy(path,devpath,IPC_MAXPATH_LEN); fd = IOS_Open(path,IPC_OPEN_NONE); if(fd<0) { ret = fd; goto done; } vec = iosAlloc(hId,sizeof(ioctlv)*2); if(vec==NULL) goto done; msgcb = iosAlloc(hId,sizeof(struct _usb_cb)); if(msgcb==NULL) goto done; pvid = iosAlloc(hId,32); if(pvid==NULL) goto done; *pvid = vid; ppid = iosAlloc(hId,32); if(ppid==NULL) goto done; *ppid = pid; vec[0].data = pvid; vec[0].len = sizeof(u16); vec[1].data = ppid; vec[1].len = sizeof(u16); msgcb->fd = fd; msgcb->cb = cb; msgcb->vec = vec; msgcb->usrdata = usrdata; return IOS_IoctlvAsync(fd,USB_IOCTL_DEVINSERTHOOK,2,0,vec,__usb_device_notificationCB,msgcb); done: if(ppid!=NULL) iosFree(hId,ppid); if(pvid!=NULL) iosFree(hId,pvid); if(msgcb!=NULL) iosFree(hId,msgcb); if(vec!=NULL) iosFree(hId,vec); if(path!=NULL) iosFree(hId,path); if(fd>=0) IOS_Close(fd); return ret; }
static inline s32 __usb_interrupt_bulk_message(s32 fd,u8 ioctl,u8 bEndpoint,u16 wLength,void *rpData,usbcallback cb,void *usrdata) { s32 ret = IPC_ENOMEM; u8 *pEndP = NULL; u16 *pLength = NULL; ioctlv *vec = NULL; struct _usb_cb *msgcb = NULL; if(((s32)rpData%32)!=0) return IPC_EINVAL; if(wLength && !rpData) return IPC_EINVAL; if(!wLength && rpData) return IPC_EINVAL; vec = iosAlloc(hId,sizeof(ioctlv)*3); if(vec==NULL) return IPC_ENOMEM; pEndP = iosAlloc(hId,32); if(pEndP==NULL) goto done; *pEndP = bEndpoint; pLength = iosAlloc(hId,32); if(pLength==NULL) goto done; *pLength = wLength; vec[0].data = pEndP; vec[0].len = sizeof(u8); vec[1].data = pLength; vec[1].len = sizeof(u16); vec[2].data = rpData; vec[2].len = wLength; if(cb==NULL) ret = IOS_Ioctlv(fd,ioctl,2,1,vec); else { msgcb = iosAlloc(hId,sizeof(struct _usb_cb)); if(msgcb==NULL) goto done; msgcb->fd = -1; msgcb->cb = cb; msgcb->usrdata = usrdata; msgcb->vec = vec; return IOS_IoctlvAsync(fd,ioctl,2,1,vec,__usb_bulk_messageCB,msgcb); } done: if(pLength!=NULL) iosFree(hId,pLength); if(pEndP!=NULL) iosFree(hId,pEndP); if(vec!=NULL) iosFree(hId,vec); return ret; }
/* Log hook */ int _start(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) { /* Kernel functions */ #if VER == 532 void (*spinlock)(void *lock) = (void (*)(void*))0xFFF075BC; void (*spunlock)(void *lock) = (void (*)(void*))0xFFF075E0; int (*fd_to_handle)(unsigned int *ipcbuf, int rampid) = (int (*)(unsigned int*,int))0xFFF0C7F8; int (*IOS_IoctlvAsync)(int arg0, int fd, int cmd, int cnt_in, int cnt_out, struct iovec *vecs, void *cb, void *usrdata) = (int (*)(int,int,int,int,int,struct iovec*,void*,void*))0xFFF0BAF4; int (*IOS_WaitReply)(void *usrdata, int arg1, int arg2) = (int (*)(void*,int,int))0xFFF18150; void* (*memmove)(void *dst, void *src, int len) = (void* (*)(void*,void*,int))0xFFF09C7C; #elif VER == 550 void (*spinlock)(void *lock) = (void (*)(void*))0x0; void (*spunlock)(void *lock) = (void (*)(void*))0x0; int (*fd_to_handle)(unsigned int *ipcbuf, int rampid) = (int (*)(unsigned int*,int))0x0; int (*IOS_IoctlvAsync)(int arg0, int fd, int cmd, int cnt_in, int cnt_out, struct iovec *vecs, void *cb, void *usrdata) = (int (*)(int,int,int,int,int,struct iovec*,void*,void*))0x0; int (*IOS_WaitReply)(void *usrdata, int arg1, int arg2) = (int (*)(void*,int,int))0x0; void* (*memmove)(void *dst, void *src, int len) = (void* (*)(void*,void*,int))0x0; #else void (*spinlock)(void *lock) = (void (*)(void*))0x0; void (*spunlock)(void *lock) = (void (*)(void*))0x0; int (*fd_to_handle)(unsigned int *ipcbuf, int rampid) = (int (*)(unsigned int*,int))0x0; int (*IOS_IoctlvAsync)(int arg0, int fd, int cmd, int cnt_in, int cnt_out, struct iovec *vecs, void *cb, void *usrdata) = (int (*)(int,int,int,int,int,struct iovec*,void*,void*))0x0; int (*IOS_WaitReply)(void *usrdata, int arg1, int arg2) = (int (*)(void*,int,int))0x0; void* (*memmove)(void *dst, void *src, int len) = (void* (*)(void*,void*,int))0x0; #endif /* Only do this if socket open */ int sockfd = *((int*)0xFFF00B48); if (sockfd != -1) { /* Lock a spinlock */ spinlock((void*)(0xA0000000 + (0xFFF00B4C - 0xC0000000))); /* Get socket FD and convert to handle */ unsigned int ipcbuf[3] = {0, 0, *((unsigned int*)0xFFF00B44)}; fd_to_handle(ipcbuf, 4); /* Copy socket data to 0x40-aligned buffer */ memmove((void*)0xDFF01500, addr, len); /* Execute send() request and wait for completion */ unsigned int reqbuf[2] = {(unsigned int)sockfd, 0}; int sendlen = ((len / 0x40) * 0x40) + ((len % 0x40 == 0) ? 0 : 0x40); struct iovec vecs[4]; vecs[0].buffer = (void*)&reqbuf[0]; vecs[0].len = 8; vecs[0].unknown8[0] = vecs[0].unknown8[1] = vecs[0].unknown8[2] = vecs[0].unknown8[3] = 0; vecs[1].buffer = (void*)0xDFF01500; vecs[1].len = sendlen; vecs[1].unknown8[0] = vecs[1].unknown8[1] = vecs[1].unknown8[2] = vecs[1].unknown8[3] = 0; vecs[2].buffer = (void*)0; vecs[2].len = 0; vecs[2].unknown8[0] = vecs[2].unknown8[1] = vecs[2].unknown8[2] = vecs[2].unknown8[3] = 0; vecs[3].buffer = (void*)0; vecs[3].len = 0; vecs[3].unknown8[0] = vecs[3].unknown8[1] = vecs[3].unknown8[2] = vecs[3].unknown8[3] = 0; IOS_IoctlvAsync(0, (int)ipcbuf[2], 0xE, 4, 0, vecs, (void*)0, (void*)0x1234ABC0); IOS_WaitReply((void*)0x1234ABC0, 0xF4240, 0); /* Release the spinlock */ spunlock((void*)(0xA0000000 + (0xFFF00B4C - 0xC0000000))); } /* Pass through to real function */ #if VER == 532 int (*real_func)(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) = (int (*)(int,int,unsigned int,void*,int,int))0xFFF1AB94; #elif VER == 550 int (*real_func)(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) = (int (*)(int,int,unsigned int,void*,int,int))0x0; #else int (*real_func)(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) = (int (*)(int,int,unsigned int,void*,int,int))0x0; #endif return real_func(arg0, arg1, arg2, addr, len, arg5); }
static inline s32 __usb_control_message(s32 fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData,usbcallback cb,void *usrdata) { s32 ret = IPC_ENOMEM; u8 *pRqType = NULL; u8 *pRq = NULL; u8 *pNull = NULL; u16 *pValue = NULL; u16 *pIndex = NULL; u16 *pLength = NULL; ioctlv *vec = NULL; struct _usb_cb *msgcb = NULL; if(((s32)rpData%32)!=0) return IPC_EINVAL; if(wLength && !rpData) return IPC_EINVAL; if(!wLength && rpData) return IPC_EINVAL; vec = iosAlloc(hId,sizeof(ioctlv)*7); if(vec==NULL) return IPC_ENOMEM; pRqType = iosAlloc(hId,32); if(pRqType==NULL) goto done; *pRqType = bmRequestType; pRq = iosAlloc(hId,32); if(pRq==NULL) goto done; *pRq = bmRequest; pValue = iosAlloc(hId,32); if(pValue==NULL) goto done; *pValue = bswap16(wValue); pIndex = iosAlloc(hId,32); if(pIndex==NULL) goto done; *pIndex = bswap16(wIndex); pLength = iosAlloc(hId,32); if(pLength==NULL) goto done; *pLength = bswap16(wLength); pNull = iosAlloc(hId,32); if(pNull==NULL) goto done; *pNull = 0; vec[0].data = pRqType; vec[0].len = sizeof(u8); vec[1].data = pRq; vec[1].len = sizeof(u8); vec[2].data = pValue; vec[2].len = sizeof(u16); vec[3].data = pIndex; vec[3].len = sizeof(u16); vec[4].data = pLength; vec[4].len = sizeof(u16); vec[5].data = pNull; vec[5].len = sizeof(u8); vec[6].data = rpData; vec[6].len = wLength; if(cb==NULL) ret = IOS_Ioctlv(fd,USB_IOCTL_CTRLMSG,6,1,vec); else { msgcb = iosAlloc(hId,sizeof(struct _usb_cb)); if(msgcb==NULL) goto done; msgcb->fd = -1; msgcb->cb = cb; msgcb->usrdata = usrdata; msgcb->vec = vec; return IOS_IoctlvAsync(fd,USB_IOCTL_CTRLMSG,6,1,vec,__usb_control_messageCB,msgcb); } done: if(pNull!=NULL) iosFree(hId,pNull); if(pLength!=NULL) iosFree(hId,pLength); if(pIndex!=NULL) iosFree(hId,pIndex); if(pValue!=NULL) iosFree(hId,pValue); if(pRq!=NULL) iosFree(hId,pRq); if(pRqType!=NULL) iosFree(hId,pRqType); if(vec!=NULL) iosFree(hId,vec); return ret; }
int main(int argc, char **argv) { // Exit after 10 seconds if there is an error __exception_setreload(10); // u64 timeout = 0; CheckForGecko(); DCInvalidateRange(loader_stub, 0x1800); memcpy(loader_stub, (void*)0x80001800, 0x1800); RAMInit(); //Meh, doesnt do anything anymore anyways //STM_RegisterEventHandler(HandleSTMEvent); Initialise(); // Checking for storage devices... ShowMessageScreen("Checking storage devices..."); u32 u; //Disables MEMPROT for patches write16(MEM_PROT, 0); //Patches FS access for( u = 0x93A00000; u < 0x94000000; u+=2 ) { if( memcmp( (void*)(u), FSAccessPattern, sizeof(FSAccessPattern) ) == 0 ) { // gprintf("FSAccessPatch:%08X\r\n", u ); memcpy( (void*)u, FSAccessPatch, sizeof(FSAccessPatch) ); DCFlushRange((void*)u, sizeof(FSAccessPatch)); break; } } //for BT.c CONF_GetPadDevices((conf_pads*)0x932C0000); DCFlushRange((void*)0x932C0000, sizeof(conf_pads)); *(vu32*)0x932C0490 = CONF_GetIRSensitivity(); *(vu32*)0x932C0494 = CONF_GetSensorBarPosition(); DCFlushRange((void*)0x932C0490, 8); if(LoadKernel() < 0) { ClearScreen(); gprintf("Failed to load kernel from NAND!\r\n"); ShowMessageScreenAndExit("Failed to load kernel from NAND!", 1); } InsertModule((char*)kernel_bin, kernel_bin_size); memset( (void*)0x92f00000, 0, 0x100000 ); DCFlushRange( (void*)0x92f00000, 0x100000 ); DCInvalidateRange( (void*)0x939F02F0, 0x20 ); memcpy( (void*)0x939F02F0, Boot2Patch, sizeof(Boot2Patch) ); DCFlushRange( (void*)0x939F02F0, 0x20 ); //libogc still has that, lets close it __ES_Close(); s32 fd = IOS_Open( "/dev/es", 0 ); memset( STATUS, 0xFFFFFFFF, 0x20 ); DCFlushRange( STATUS, 0x20 ); memset( (void*)0x91000000, 0xFFFFFFFF, 0x20 ); DCFlushRange( (void*)0x91000000, 0x20 ); *(vu32*)0xD3003420 = 0; //make sure kernel doesnt reload raw_irq_handler_t irq_handler = BeforeIOSReload(); IOS_IoctlvAsync( fd, 0x1F, 0, 0, &IOCTL_Buf, NULL, NULL ); AfterIOSReload( irq_handler, FoundVersion ); while(1) { DCInvalidateRange( STATUS, 0x20 ); if((STATUS_LOADING > 0 || abs(STATUS_LOADING) > 1) && STATUS_LOADING < 20) { gprintf("Kernel sent signal\n"); break; } } /* For slow USB HDDs */ time_t timeout = time(NULL); while(time(NULL) - timeout < 10) { if(__io_custom_usbstorage.startup() && __io_custom_usbstorage.isInserted()) break; usleep(50000); } fatInitDefault(); gprintf("Nintendont at your service!\r\n%s\r\n", NIN_BUILD_STRING); KernelLoaded = 1; char* first_slash = strrchr(argv[0], '/'); if (first_slash != NULL) strncpy(launch_dir, argv[0], first_slash-argv[0]+1); gprintf("launch_dir = %s\r\n", launch_dir); FPAD_Init(); FPAD_Update(); /* Read IPL Font before doing any patches */ void *fontbuffer = memalign(32, 0x50000); __SYS_ReadROM((void*)fontbuffer,0x50000,0x1AFF00); memcpy((void*)0xD3100000, fontbuffer, 0x50000); DCInvalidateRange( (void*)0x93100000, 0x50000 ); free(fontbuffer); //gprintf("Font: 0x1AFF00 starts with %.4s, 0x1FCF00 with %.4s\n", (char*)0x93100000, (char*)0x93100000 + 0x4D000); // Simple code to autoupdate the meta.xml in Nintendont's folder FILE *meta = fopen("meta.xml", "w"); if(meta != NULL) { fprintf(meta, "%s\r\n<app version=\"1\">\r\n\t<name>%s</name>\r\n", META_XML, META_NAME); fprintf(meta, "\t<coder>%s</coder>\r\n\t<version>%d.%d</version>\r\n", META_AUTHOR, NIN_VERSION>>16, NIN_VERSION&0xFFFF); fprintf(meta, "\t<release_date>20150531000000</release_date>\r\n"); fprintf(meta, "\t<short_description>%s</short_description>\r\n", META_SHORT); fprintf(meta, "\t<long_description>%s\r\n\r\n%s</long_description>\r\n", META_LONG1, META_LONG2); fprintf(meta, "\t<ahb_access/>\r\n</app>"); fclose(meta); }