s32 USB_GetDeviceList(const char *devpath,void *descr_buffer,u8 num_descr,u8 b0,u8 *cnt_descr) { s32 fd,ret; char *path; u32 cntdevs; 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) { iosFree(hId,path); return fd; } cntdevs = 0; ret = IOS_IoctlvFormat(hId,fd,USB_IOCTL_GETDEVLIST,"bb:bd",num_descr,b0,&cntdevs,descr_buffer,(num_descr<<3)); if(ret>=0) *cnt_descr = cntdevs; iosFree(hId,path); IOS_Close(fd); return ret; }
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; }
s32 ssl_new(u8 * CN, u32 ssl_verify_options){ s32 ret; s32 aContext[8] ATTRIBUTE_ALIGN(32); u32 aVerify_options[8] ATTRIBUTE_ALIGN(32); ret = ssl_open(); if(ret){ return ret; } aVerify_options[0] = ssl_verify_options; if(ISALIGNED(CN)){ //Avoid alignment if the input is aligned ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, CN, 0x100); }else{ u8 *aCN = NULL; aCN = iosAlloc(__ssl_hid, 0x100); if (!aCN) { return IPC_ENOMEM; } memcpy(aCN, CN, 0x100); ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, aCN, 0x100); if(aCN){ iosFree(__ssl_hid, aCN); } } ssl_close(); return (ret ? ret : aContext[0]); }
s32 ssl_read(s32 ssl_context, void* buffer, s32 length){ s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); s32 aResponse[8] ATTRIBUTE_ALIGN(32); s32 ret; ret = ssl_open(); if(ret){ return ret; } if(!buffer){ return IPC_EINVAL; } u8 *aBuffer = NULL; aBuffer = iosAlloc(__ssl_hid, length); if (!aBuffer) { return IPC_ENOMEM; } aSsl_context[0] = ssl_context; ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_READ, "dd:d", aResponse, 0x20, aBuffer, length, aSsl_context, 0x20); ssl_close(); if(ret == IPC_OK){ memcpy(buffer, aBuffer, aResponse[0]); } if(aBuffer){ iosFree(__ssl_hid, aBuffer); } return (ret ? ret : aResponse[0]); }
s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length){ s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); s32 aResponse[8] ATTRIBUTE_ALIGN(32); s32 ret; ret = ssl_open(); if(ret){ return ret; } aSsl_context[0] = ssl_context; if(ISALIGNED(root)){ //Avoid alignment if the input is aligned ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, root, length); }else{ u8 *aRoot = NULL; aRoot = iosAlloc(__ssl_hid, length); if (!aRoot) { return IPC_ENOMEM; } memcpy(aRoot, root, length); ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aRoot, length); if(aRoot){ iosFree(__ssl_hid, aRoot); } } ssl_close(); return (ret ? ret : aResponse[0]); }
bool SDHC_ReadSectors(u32 sector, u32 count, void *buffer) { void *buf = (void *)buffer; u32 len = (sector_size * count); s32 ret; /* Device not opened */ if (fd < 0) return false; /* Buffer not aligned */ if ((u32)buffer & 0x1F) { /* Allocate memory */ buf = iosAlloc(hid, len); if (!buf) return false; } /* Read data */ ret = IOS_IoctlvFormat(hid, fd, IOCTL_SDHC_READ, "ii:d", sector, count, buf, len); /* Copy data */ if (buf != buffer) { memcpy(buffer, buf, len); iosFree(hid, buf); } return (!ret) ? true : false; }
s32 USB_GetAsciiString(s32 fd,u16 wIndex,u16 wLangID,u16 wLength,void *rpData) { s32 ret; u8 bo, ro; u8 *buf; u8 *rp = (u8 *)rpData; if(wLength > 255) wLength = 255; buf = iosAlloc(hId, 255); /* 255 is the highest possible length of a descriptor */ if(buf == NULL) return IPC_ENOMEM; ret = __usb_control_message(fd, USB_ENDPOINT_IN, USB_REQ_GETDESCRIPTOR, ((USB_DT_STRING << 8) + wIndex), wLangID, 255, buf, NULL, NULL); /* index 0 gets a list of supported languages */ if(wIndex == 0) { if(ret > 0) memcpy(rpData, buf, wLength); iosFree(hId, buf); return ret; } if(ret > 0) { bo = 2; ro = 0; while(ro < (wLength - 1) && bo < buf[0]) { if(buf[bo + 1]) rp[ro++] = '?'; else rp[ro++] = buf[bo]; bo += 2; } rp[ro] = 0; ret = ro - 1; } iosFree(hId, buf); return ret; }
static s32 __usb_bulk_messageCB(s32 result,void *usrdata) { ioctlv *vec = NULL; struct _usb_cb *msgcb = (struct _usb_cb*)usrdata; if(msgcb==NULL) return IPC_EINVAL; if(msgcb->cb!=NULL) msgcb->cb(result,msgcb->usrdata); vec = msgcb->vec; if(vec==NULL) return IPC_EINVAL; if(vec[0].data!=NULL) iosFree(hId,vec[0].data); if(vec[1].data!=NULL) iosFree(hId,vec[1].data); iosFree(hId,vec); iosFree(hId,msgcb); return IPC_OK; }
static s32 __usb_device_notificationCB(s32 result,void *usrdata) { ioctlv *vec = NULL; struct _usb_cb *msgcb = (struct _usb_cb*)usrdata; if(msgcb==NULL) return IPC_EINVAL; if(msgcb->cb!=NULL) msgcb->cb(result,msgcb->usrdata); if(msgcb->fd>=0) IOS_Close(msgcb->fd); vec = msgcb->vec; if(vec==NULL) return IPC_EINVAL; if(vec[0].data!=NULL) iosFree(hId,vec[0].data); if(vec[1].data!=NULL) iosFree(hId,vec[1].data); iosFree(hId,vec); iosFree(hId,msgcb); return IPC_OK; }
s32 USB_GetDeviceDescription(s32 fd,usb_devdesc *devdesc) { s32 ret; usb_devdesc *p; p = iosAlloc(hId,USB_DT_DEVICE_SIZE); if(p==NULL) return IPC_ENOMEM; ret = __usb_control_message(fd,USB_ENDPOINT_IN,USB_REQ_GETDESCRIPTOR,(USB_DT_DEVICE<<8),0,USB_DT_DEVICE_SIZE,p,NULL,NULL); if(ret>=0) memcpy(devdesc,p,USB_DT_DEVICE_SIZE); devdesc->configurations = NULL; if(p!=NULL) iosFree(hId,p); return ret; }
s32 USB_GetConfiguration(s32 fd, u8 *configuration) { u8 *_configuration; s32 retval; _configuration = iosAlloc(hId, 1); if(_configuration == NULL) return IPC_ENOMEM; retval = __usb_control_message(fd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_DEVICE), USB_REQ_GETCONFIG, 0, 0, 1, _configuration, NULL, NULL); if(retval >= 0) *configuration = *_configuration; iosFree(hId, _configuration); return retval; }
s32 USB_OpenDevice(const char *device,u16 vid,u16 pid,s32 *fd) { s32 _fd = -1; s32 ret = USB_OK; char *devicepath = NULL; devicepath = iosAlloc(hId,USB_MAXPATH); if(devicepath==NULL) return IPC_ENOMEM; snprintf(devicepath,USB_MAXPATH,"/dev/usb/%s/%x/%x",device,vid,pid); _fd = IOS_Open(devicepath,0); if(_fd<0) ret = _fd; *fd = _fd; if(devicepath!=NULL) iosFree(hId,devicepath); return ret; }
s32 USB_GetDescriptors(s32 fd, usb_devdesc *udd) { u8 *buffer = NULL; u8 *ptr = NULL; usb_configurationdesc *ucd = NULL; usb_interfacedesc *uid = NULL; usb_endpointdesc *ued = NULL; s32 retval = 0; u32 iConf, iInterface, iEndpoint; buffer = iosAlloc(hId, sizeof(*udd)); if(buffer == NULL) { retval = IPC_ENOHEAP; goto free_and_error; } retval = __usb_getdesc(fd, buffer, USB_DT_DEVICE, 0, USB_DT_DEVICE_SIZE); if(retval < 0) goto free_and_error; memcpy(udd, buffer, USB_DT_DEVICE_SIZE); iosFree(hId, buffer); udd->bcdUSB = bswap16(udd->bcdUSB); udd->idVendor = bswap16(udd->idVendor); udd->idProduct = bswap16(udd->idProduct); udd->bcdDevice = bswap16(udd->bcdDevice); udd->configurations = calloc(udd->bNumConfigurations, sizeof(*udd->configurations)); if(udd->configurations == NULL) { retval = IPC_ENOMEM; goto free_and_error; } for(iConf = 0; iConf < udd->bNumConfigurations; iConf++) { buffer = iosAlloc(hId, USB_DT_CONFIG_SIZE); if(buffer == NULL) { retval = IPC_ENOHEAP; goto free_and_error; } retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, USB_DT_CONFIG_SIZE); ucd = &udd->configurations[iConf]; memcpy(ucd, buffer, USB_DT_CONFIG_SIZE); iosFree(hId, buffer); ucd->wTotalLength = bswap16(ucd->wTotalLength); buffer = iosAlloc(hId, ucd->wTotalLength); if(buffer == NULL) { retval = IPC_ENOHEAP; goto free_and_error; } retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, ucd->wTotalLength); if(retval < 0) goto free_and_error; ptr = buffer; ptr += ucd->bLength; retval = IPC_ENOMEM; ucd->interfaces = calloc(ucd->bNumInterfaces, sizeof(*ucd->interfaces)); if(ucd->interfaces == NULL) goto free_and_error; for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; memcpy(uid, ptr, USB_DT_INTERFACE_SIZE); ptr += uid->bLength; uid->endpoints = calloc(uid->bNumEndpoints, sizeof(*uid->endpoints)); if(uid->endpoints == NULL) goto free_and_error; for(iEndpoint = 0; iEndpoint < uid->bNumEndpoints; iEndpoint++) { ued = &uid->endpoints[iEndpoint]; memcpy(ued, ptr, USB_DT_ENDPOINT_SIZE); ptr += ued->bLength; ued->wMaxPacketSize = bswap16(ued->wMaxPacketSize); } } iosFree(hId, buffer); buffer = NULL; } retval = IPC_OK; free_and_error: if(buffer != NULL) iosFree(hId, buffer); if(retval < 0) USB_FreeDescriptors(udd); return retval; }
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; }
s32 IOS_GetPreferredVersion() { int ver = IOS_EBADVERSION; s32 res; u32 count; u64 *titles; u32 tmd_size; u32 i; u32 a,b; res = __IOS_InitHeap(); if(res<0) return res; res = ES_GetNumTitles(&count); if(res < 0) { #ifdef DEBUG_IOS printf(" GetNumTitles failed: %d\n",res); #endif return res; } #ifdef DEBUG_IOS printf(" %d titles on card:\n",count); #endif titles = iosAlloc(__ios_hid, sizeof(u64)*count); if(!titles) { printf(" iosAlloc titles failed\n"); return -1; } res = ES_GetTitles(titles, count); if(res < 0) { #ifdef DEBUG_IOS printf(" GetTitles failed: %d\n",res); #endif iosFree(__ios_hid, titles); return res; } u32 *tmdbuffer = memalign(32, MAX_SIGNED_TMD_SIZE); if(!tmdbuffer) { iosFree(__ios_hid, titles); return -1; } for(i=0; i<count; i++) { a = titles[i]>>32; b = titles[i]&0xFFFFFFFF; if(a != 1) continue; if(b < IOS_MIN_VERSION) continue; if(b > IOS_MAX_VERSION) continue; if (ES_GetStoredTMDSize(titles[i], &tmd_size) < 0) continue; if (tmd_size < 0 || tmd_size > 4096) continue; if(ES_GetStoredTMD(titles[i], (signed_blob *)tmdbuffer, tmd_size) < 0) continue; if (!tmdbuffer[1] && !tmdbuffer[2]) continue; if((((s32)b) > ((s32)ver) && ver != 58) || b == 58) ver = b; } #ifdef DEBUG_IOS printf(" Preferred verson: %d\n",ver); #endif iosFree(__ios_hid, titles); free(tmdbuffer); return ver; }