IPCCommandResult CWII_IPC_HLE_Device_usb_oh0_46d_a03::IOCtl(u32 CommandAddress) { IPCCommandResult SendReply = GetNoReply(); SIOCtlVBuffer CommandBuffer(CommandAddress); switch (CommandBuffer.Parameter) { case USBV0_IOCTL_DEVREMOVALHOOK: // Reply is sent when device is removed //SendReply = true; break; default: WARN_LOG(OSHLE, "%s - IOCtl:", GetDeviceName().c_str()); WARN_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); WARN_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); WARN_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); WARN_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); break; } Memory::Write_U32(0, CommandAddress + 4); return SendReply; }
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress) { // PPC sending commands SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution // to avoid returning bad values for (const auto& buffer : CommandBuffer.PayloadBuffer) Memory::Memset(buffer.m_Address, 0, buffer.m_Size); u32 ReturnValue = 0; switch (CommandBuffer.Parameter) { case IOCTLV_SENDCMD: DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address)); ReturnValue = ExecuteCommand( CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size, CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size, CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size); break; default: ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter); break; } // DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, // CommandBuffer.NumberPayloadBuffer, LogTypes::WII_IPC_SD); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); return GetDefaultReply(); }
IPCCommandResult CWII_IPC_HLE_Device_usb_oh0::IOCtlV(u32 CommandAddress) { IPCCommandResult SendReply = GetNoReply(); SIOCtlVBuffer CommandBuffer(CommandAddress); switch (CommandBuffer.Parameter) { case USBV0_IOCTL_DEVINSERTHOOKID: case USBV0_IOCTL_DEVINSERTHOOK: { u16 vid = Memory::Read_U16(CommandBuffer.InBuffer[0].m_Address); u16 pid = Memory::Read_U16(CommandBuffer.InBuffer[1].m_Address); WARN_LOG(OSHLE, "DEVINSERTHOOK %x/%x", vid, pid); // It is inserted SendReply = GetDefaultReply(); } break; default: WARN_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str()); WARN_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); WARN_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); WARN_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); WARN_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer, LogTypes::OSHLE, LogTypes::LWARNING); break; } Memory::Write_U32(0, CommandAddress + 4); return SendReply; }
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtlV(u32 CommandAddress) { IPCCommandResult SendReply = GetNoReply(); SIOCtlVBuffer CommandBuffer(CommandAddress); /*switch (CommandBuffer.Parameter) { default: WARN_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str()); WARN_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); WARN_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); WARN_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); WARN_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); break; }*/ WARN_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str()); WARN_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); WARN_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); WARN_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); WARN_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); Memory::Write_U32(0, CommandAddress + 4); return SendReply; }
void Clean_Exit(int val) { char *command; command = CommandBuffer("","",SORT_PATH); sprintf(command,"rm -r %s",SORT_PATH); if (system(command) != 0) { fprintf(stderr,"%s: Command Failed:\n%*s %s\n", Prog_Name,(int) strlen(Prog_Name),"",command); exit (1); } exit (val); }
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtlV(u32 _CommandAddress) { SIOCtlVBuffer CommandBuffer(_CommandAddress); INFO_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str()); INFO_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); INFO_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); INFO_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); INFO_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); Memory::Write_U32(0, _CommandAddress + 4); return GetNoReply(); }
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) { SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution // to avoid returning bad values for (u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++) { Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0, CommandBuffer.PayloadBuffer[i].m_Size); } u32 ReturnValue = 0; switch (CommandBuffer.Parameter) { case DVDInterface::DVDLowOpenPartition: { _dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[1].m_Address == 0, "DVDLowOpenPartition with ticket"); _dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[2].m_Address == 0, "DVDLowOpenPartition with cert chain"); u64 const partition_offset = ((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2); DVDInterface::ChangePartition(partition_offset); INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset); // Read TMD to the buffer u32 tmd_size; std::unique_ptr<u8[]> tmd_buf = DVDInterface::GetVolume().GetTMD(&tmd_size); Memory::CopyToEmu(CommandBuffer.PayloadBuffer[0].m_Address, tmd_buf.get(), tmd_size); WII_IPC_HLE_Interface::ES_DIVerify(tmd_buf.get(), tmd_size); ReturnValue = 1; } break; default: ERROR_LOG(WII_IPC_DVD, "IOCtlV: %i", CommandBuffer.Parameter); _dbg_assert_msg_(WII_IPC_DVD, 0, "IOCtlV: %i", CommandBuffer.Parameter); break; } Memory::Write_U32(ReturnValue, _CommandAddress + 4); return GetDefaultReply(); }
bool CWII_IPC_HLE_Device_hid::IOCtlV(u32 _CommandAddress) { Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING); u32 ReturnValue = 0; SIOCtlVBuffer CommandBuffer(_CommandAddress); DEBUG_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str()); DEBUG_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter); DEBUG_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); DEBUG_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); DEBUG_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector); DEBUG_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address); DEBUG_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size); #if defined(_DEBUG) || defined(DEBUGFAST) DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); #endif Memory::Write_U32(ReturnValue, _CommandAddress + 4); return true; }
bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress) { u32 ReturnValue = FS_RESULT_OK; SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution // to avoid returning bad values for(u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++) { Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0, CommandBuffer.PayloadBuffer[i].m_Size); } switch(CommandBuffer.Parameter) { case IOCTLV_READ_DIR: { // the wii uses this function to define the type (dir or file) std::string DirName(HLE_IPC_BuildFilename((const char*)Memory::GetPointer( CommandBuffer.InBuffer[0].m_Address), CommandBuffer.InBuffer[0].m_Size)); INFO_LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str()); if (!File::Exists(DirName)) { WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str()); ReturnValue = FS_FILE_NOT_EXIST; break; } else if (!File::IsDirectory(DirName)) { // It's not a directory, so error. // Games don't usually seem to care WHICH error they get, as long as it's < // Well the system menu CARES! WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_RESULT_FATAL"); ReturnValue = FS_RESULT_FATAL; break; } // make a file search CFileSearch::XStringVector Directories; Directories.push_back(DirName); CFileSearch::XStringVector Extensions; Extensions.push_back("*.*"); CFileSearch FileSearch(Extensions, Directories); // it is one if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1)) { size_t numFile = FileSearch.GetFileNames().size(); INFO_LOG(WII_IPC_FILEIO, "\t%lu files found", (unsigned long)numFile); Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address); } else { u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address); memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size); size_t numFiles = 0; char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address)); for (size_t i=0; i<FileSearch.GetFileNames().size(); i++) { if (i >= MaxEntries) break; std::string name, ext; SplitPath(FileSearch.GetFileNames()[i], NULL, &name, &ext); std::string FileName = name + ext; // Decode entities of invalid file system characters so that // games (such as HP:HBP) will be able to find what they expect. for (const Common::replace_t& r : replacements) { for (size_t j = 0; (j = FileName.find(r.second, j)) != FileName.npos; ++j) FileName.replace(j, r.second.length(), 1, r.first); } strcpy(pFilename, FileName.c_str()); pFilename += FileName.length(); *pFilename++ = 0x00; // termination numFiles++; INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str()); } Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address); } ReturnValue = FS_RESULT_OK; } break; case IOCTLV_GETUSAGE: { _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2); _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4); _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4); // this command sucks because it asks of the number of used // fsBlocks and inodes // It should be correct, but don't count on it... const char *relativepath = (const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address); std::string path(HLE_IPC_BuildFilename(relativepath, CommandBuffer.InBuffer[0].m_Size)); u32 fsBlocks = 0; u32 iNodes = 0; INFO_LOG(WII_IPC_FILEIO, "IOCTL_GETUSAGE %s", path.c_str()); if (File::IsDirectory(path)) { // LPFaint99: After I found that setting the number of inodes to the number of children + 1 for the directory itself // I decided to compare with sneek which has the following 2 special cases which are // Copyright (C) 2009-2011 crediar http://code.google.com/p/sneek/ if ((memcmp(relativepath, "/title/00010001", 16 ) == 0 ) || (memcmp(relativepath, "/title/00010005", 16) == 0 )) { fsBlocks = 23; // size is size/0x4000 iNodes = 42; // empty folders return a FileCount of 1 } else { File::FSTEntry parentDir; // add one for the folder itself, allows some games to create their save files // R8XE52 (Jurassic: The Hunted), STEETR (Tetris Party Deluxe) now create their saves with this change iNodes = 1 + File::ScanDirectoryTree(path, parentDir); u64 totalSize = ComputeTotalFileSize(parentDir); // "Real" size, to be converted to nand blocks fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb } ReturnValue = FS_RESULT_OK; INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes); } else { fsBlocks = 0; iNodes = 0; ReturnValue = FS_RESULT_OK; WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str()); } Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address); Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address); } break; default: PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter); break; } Memory::Write_U32(ReturnValue, _CommandAddress+4); return true; }
void WiiSocket::Update(bool read, bool write, bool except) { auto it = pending_sockops.begin(); while (it != pending_sockops.end()) { s32 ReturnValue = 0; bool forceNonBlock = false; IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(it->_CommandAddress)); if (!it->is_ssl && ct == IPC_CMD_IOCTL) { u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10); u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14); u32 BufferOut = Memory::Read_U32(it->_CommandAddress + 0x18); u32 BufferOutSize = Memory::Read_U32(it->_CommandAddress + 0x1C); switch (it->net_type) { case IOCTL_SO_FCNTL: { u32 cmd = Memory::Read_U32(BufferIn + 4); u32 arg = Memory::Read_U32(BufferIn + 8); ReturnValue = FCntl(cmd, arg); break; } case IOCTL_SO_BIND: { //u32 has_addr = Memory::Read_U32(BufferIn + 0x04); sockaddr_in local_name; WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08); WiiSockMan::Convert(*wii_name, local_name); int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name)); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_BIND", false); INFO_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%08X %s:%d) = %d ", fd, inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port), ret); break; } case IOCTL_SO_CONNECT: { //u32 has_addr = Memory::Read_U32(BufferIn + 0x04); sockaddr_in local_name; WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08); WiiSockMan::Convert(*wii_name, local_name); int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name)); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_CONNECT", false); INFO_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)", fd, inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port)); break; } case IOCTL_SO_ACCEPT: { if (BufferOutSize > 0) { sockaddr_in local_name; WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut); WiiSockMan::Convert(*wii_name, local_name); socklen_t addrlen = sizeof(sockaddr_in); int ret = (s32)accept(fd, (sockaddr*)&local_name, &addrlen); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true); WiiSockMan::Convert(local_name, *wii_name, addrlen); } else { int ret = (s32)accept(fd, nullptr, nullptr); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true); } WiiSockMan::GetInstance().AddSocket(ReturnValue); INFO_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT " "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); break; } default: break; } // Fix blocking error codes if (!nonBlock) { if (it->net_type == IOCTL_SO_CONNECT && ReturnValue == -SO_EISCONN) { ReturnValue = SO_SUCCESS; } } } else if (ct == IPC_CMD_IOCTLV) { SIOCtlVBuffer CommandBuffer(it->_CommandAddress); u32 BufferIn = 0, BufferIn2 = 0; u32 BufferInSize = 0, BufferInSize2 = 0; u32 BufferOut = 0, BufferOut2 = 0; u32 BufferOutSize = 0, BufferOutSize2 = 0; if (CommandBuffer.InBuffer.size() > 0) { BufferIn = CommandBuffer.InBuffer.at(0).m_Address; BufferInSize = CommandBuffer.InBuffer.at(0).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 0) { BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address; BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 1) { BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size; } if (CommandBuffer.InBuffer.size() > 1) { BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; } if (it->is_ssl) { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { switch (it->ssl_type) { case IOCTLV_NET_SSL_DOHANDSHAKE: { int ret = mbedtls_ssl_handshake(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx); switch (ret) { case 0: Memory::Write_U32(SSL_OK, BufferIn); break; case MBEDTLS_ERR_SSL_WANT_READ: Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_RAGAIN; break; case MBEDTLS_ERR_SSL_WANT_WRITE: Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_WAGAIN; break; default: Memory::Write_U32(SSL_ERR_FAILED, BufferIn); break; } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)", ret, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2); break; } case IOCTLV_NET_SSL_WRITE: { int ret = mbedtls_ssl_write(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferOut2), BufferOutSize2); #ifdef DEBUG_SSL File::IOFile("ssl_write.bin", "ab").WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2); #endif if (ret >= 0) { // Return bytes written or SSL_ERR_ZERO if none Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } else { switch (ret) { case MBEDTLS_ERR_SSL_WANT_READ: Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_RAGAIN; break; case MBEDTLS_ERR_SSL_WANT_WRITE: Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_WAGAIN; break; default: Memory::Write_U32(SSL_ERR_FAILED, BufferIn); break; } } break; } case IOCTLV_NET_SSL_READ: { int ret = mbedtls_ssl_read(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferIn2), BufferInSize2); #ifdef DEBUG_SSL if (ret > 0) { File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(BufferIn2), ret); } #endif if (ret >= 0) { // Return bytes read or SSL_ERR_ZERO if none Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } else { switch (ret) { case MBEDTLS_ERR_SSL_WANT_READ: Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_RAGAIN; break; case MBEDTLS_ERR_SSL_WANT_WRITE: Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_WAGAIN; break; default: Memory::Write_U32(SSL_ERR_FAILED, BufferIn); break; } } break; } default: break; } } else { Memory::Write_U32(SSL_ERR_ID, BufferIn); } } else { switch (it->net_type) { case IOCTLV_SO_SENDTO: { u32 flags = Memory::Read_U32(BufferIn2 + 0x04); u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08); // Not a string, Windows requires a const char* for sendto const char* data = (const char*)Memory::GetPointer(BufferIn); // Act as non blocking when SO_MSG_NONBLOCK is specified forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK); // send/sendto only handles MSG_OOB flags &= SO_MSG_OOB; sockaddr_in local_name = {0}; if (has_destaddr) { WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn2 + 0x0C); WiiSockMan::Convert(*wii_name, local_name); } int ret = sendto(fd, data, BufferInSize, flags, has_destaddr ? (struct sockaddr*)&local_name : nullptr, has_destaddr ? sizeof(sockaddr) : 0); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true); INFO_LOG(WII_IPC_NET, "%s = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u", has_destaddr ? "IOCTLV_SO_SENDTO " : "IOCTLV_SO_SEND ", ReturnValue, fd, BufferIn, BufferInSize, BufferIn2, BufferInSize2, local_name.sin_addr.s_addr & 0xFF, (local_name.sin_addr.s_addr >> 8) & 0xFF, (local_name.sin_addr.s_addr >> 16) & 0xFF, (local_name.sin_addr.s_addr >> 24) & 0xFF ); break; } case IOCTLV_SO_RECVFROM: { u32 flags = Memory::Read_U32(BufferIn + 0x04); // Not a string, Windows requires a char* for recvfrom char* data = (char*)Memory::GetPointer(BufferOut); int data_len = BufferOutSize; sockaddr_in local_name; memset(&local_name, 0, sizeof(sockaddr_in)); if (BufferOutSize2 != 0) { WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2); WiiSockMan::Convert(*wii_name, local_name); } // Act as non blocking when SO_MSG_NONBLOCK is specified forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK); // recv/recvfrom only handles PEEK/OOB flags &= SO_MSG_PEEK | SO_MSG_OOB; #ifdef _WIN32 if (flags & SO_MSG_PEEK) { unsigned long totallen = 0; ioctlsocket(fd, FIONREAD, &totallen); ReturnValue = totallen; break; } #endif socklen_t addrlen = sizeof(sockaddr_in); int ret = recvfrom(fd, data, data_len, flags, BufferOutSize2 ? (struct sockaddr*) &local_name : nullptr, BufferOutSize2 ? &addrlen : nullptr); ReturnValue = WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true); INFO_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)", BufferOutSize2 ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ", ReturnValue, data, fd, flags, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2); if (BufferOutSize2 != 0) { WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2); WiiSockMan::Convert(local_name, *wii_name, addrlen); } break; } default: break; } } } if (nonBlock || forceNonBlock || (!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS && ReturnValue != -SO_EALREADY) || (it->is_ssl && ReturnValue != SSL_ERR_WAGAIN && ReturnValue != SSL_ERR_RAGAIN)) { DEBUG_LOG(WII_IPC_NET, "IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", fd, it->is_ssl ? (int) it->ssl_type : (int) it->net_type, ReturnValue, nonBlock, forceNonBlock); WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue, ct); it = pending_sockops.erase(it); } else { ++it; } }
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress) { SIOCtlVBuffer CommandBuffer(_CommandAddress); u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0; u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0; u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0; u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0; if (CommandBuffer.InBuffer.size() > 0) { _BufferIn = CommandBuffer.InBuffer.at(0).m_Address; BufferInSize = CommandBuffer.InBuffer.at(0).m_Size; } if (CommandBuffer.InBuffer.size() > 1) { _BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; } if (CommandBuffer.InBuffer.size() > 2) { _BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address; BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 0) { BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address; BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 1) { BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 2) { BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address; BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size; } // I don't trust SSL to be deterministic, and this is never going to sync // as such (as opposed to forwarding IPC results or whatever), so - if (Core::g_want_determinism) { Memory::Write_U32(-1, _CommandAddress + 0x4); return IPC_DEFAULT_REPLY; } switch (CommandBuffer.Parameter) { case IOCTLV_NET_SSL_NEW: { int verifyOption = Memory::Read_U32(BufferOut); std::string hostname = Memory::GetString(BufferOut2, BufferOutSize2); int freeSSL = GetSSLFreeID(); if (freeSSL) { int sslID = freeSSL - 1; WII_SSL* ssl = &_SSL[sslID]; int ret = ssl_init(&ssl->ctx); if (ret) { goto _SSL_NEW_ERROR; } entropy_init(&ssl->entropy); const char* pers = "dolphin-emu"; ret = ctr_drbg_init(&ssl->ctr_drbg, entropy_func, &ssl->entropy, (const unsigned char*)pers, strlen(pers)); if (ret) { ssl_free(&ssl->ctx); entropy_free(&ssl->entropy); goto _SSL_NEW_ERROR; } ssl_set_rng(&ssl->ctx, ctr_drbg_random, &ssl->ctr_drbg); // For some reason we can't use TLSv1.2, v1.1 and below are fine! ssl_set_max_version(&ssl->ctx, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); ssl_set_session(&ssl->ctx, &ssl->session); ssl_set_endpoint(&ssl->ctx, SSL_IS_CLIENT); ssl_set_authmode(&ssl->ctx, SSL_VERIFY_NONE); ssl_set_renegotiation(&ssl->ctx, SSL_RENEGOTIATION_ENABLED); ssl->hostname = hostname; ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str()); ssl->active = true; Memory::Write_U32(freeSSL, _BufferIn); } else { _SSL_NEW_ERROR: Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW (%d, %s) " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", verifyOption, hostname.c_str(), _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SHUTDOWN: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; ssl_close_notify(&ssl->ctx); ssl_session_free(&ssl->session); ssl_free(&ssl->ctx); entropy_free(&ssl->entropy); x509_crt_free(&ssl->cacert); x509_crt_free(&ssl->clicert); ssl->hostname.clear(); ssl->active = false; Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETROOTCA: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; int ret = x509_crt_parse_der( &ssl->cacert, Memory::GetPointer(BufferOut2), BufferOutSize2); if (ret) { Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } else { ssl_set_ca_chain(&ssl->ctx, &ssl->cacert, nullptr, ssl->hostname.c_str()); Memory::Write_U32(SSL_OK, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA = %d", ret); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } break; } case IOCTLV_NET_SSL_SETBUILTINCLIENTCERT: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; std::string cert_base_path = File::GetUserPath(D_SESSION_WIIROOT_IDX); int ret = x509_crt_parse_file(&ssl->clicert, (cert_base_path + "clientca.pem").c_str()); int pk_ret = pk_parse_keyfile(&ssl->pk, (cert_base_path + "clientcakey.pem").c_str(), nullptr); if (ret || pk_ret) { x509_crt_free(&ssl->clicert); pk_free(&ssl->pk); Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } else { ssl_set_own_cert(&ssl->ctx, &ssl->clicert, &ssl->pk); Memory::Write_U32(SSL_OK, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = (%d, %d)", ret, pk_ret); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID); } break; } case IOCTLV_NET_SSL_REMOVECLIENTCERT: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_REMOVECLIENTCERT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; x509_crt_free(&ssl->clicert); pk_free(&ssl->pk); ssl_set_own_cert(&ssl->ctx, nullptr, nullptr); Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID); } break; } case IOCTLV_NET_SSL_SETBUILTINROOTCA: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; int ret = x509_crt_parse_file(&ssl->cacert, (File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/rootca.pem").c_str()); if (ret) { x509_crt_free(&ssl->clicert); Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } else { ssl_set_ca_chain(&ssl->ctx, &ssl->cacert, nullptr, ssl->hostname.c_str()); Memory::Write_U32(SSL_OK, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA = %d", ret); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_CONNECT: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; ssl->sockfd = Memory::Read_U32(BufferOut2); INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", ssl->sockfd); ssl_set_bio(&ssl->ctx, net_recv, &ssl->sockfd, net_send, &ssl->sockfd); Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_DOHANDSHAKE: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WiiSockMan &sm = WiiSockMan::GetInstance(); sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_DOHANDSHAKE); return IPC_NO_REPLY; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } break; } case IOCTLV_NET_SSL_WRITE: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WiiSockMan &sm = WiiSockMan::GetInstance(); sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_WRITE); return IPC_NO_REPLY; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); INFO_LOG(WII_IPC_SSL, "%s", Memory::GetString(BufferOut2).c_str()); break; } case IOCTLV_NET_SSL_READ: { int ret = 0; int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WiiSockMan &sm = WiiSockMan::GetInstance(); sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_READ); return IPC_NO_REPLY; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)" "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", ret, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETROOTCADEFAULT: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } break; } default: ERROR_LOG(WII_IPC_SSL, "%i " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } // SSL return codes are written to BufferIn Memory::Write_U32(0, _CommandAddress+4); return IPC_DEFAULT_REPLY; }
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress) { u32 ReturnValue = FS_RESULT_OK; SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution // to avoid returning bad values for (u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++) { Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0, CommandBuffer.PayloadBuffer[i].m_Size); } switch (CommandBuffer.Parameter) { case IOCTLV_READ_DIR: { const std::string relative_path = Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size); if (!IsValidWiiPath(relative_path)) { WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relative_path.c_str()); ReturnValue = FS_RESULT_FATAL; break; } // the Wii uses this function to define the type (dir or file) std::string DirName(HLE_IPC_BuildFilename(relative_path)); INFO_LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str()); if (!File::Exists(DirName)) { WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str()); ReturnValue = FS_FILE_NOT_EXIST; break; } else if (!File::IsDirectory(DirName)) { // It's not a directory, so error. // Games don't usually seem to care WHICH error they get, as long as it's < // Well the system menu CARES! WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_RESULT_FATAL"); ReturnValue = FS_RESULT_FATAL; break; } File::FSTEntry entry = File::ScanDirectoryTree(DirName, false); // it is one if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1)) { size_t numFile = entry.children.size(); INFO_LOG(WII_IPC_FILEIO, "\t%zu files found", numFile); Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address); } else { for (File::FSTEntry& child : entry.children) { // Decode escaped invalid file system characters so that games (such as // Harry Potter and the Half-Blood Prince) can find what they expect. child.virtualName = Common::UnescapeFileName(child.virtualName); } std::sort(entry.children.begin(), entry.children.end(), [](const File::FSTEntry& one, const File::FSTEntry& two) { return one.virtualName < two.virtualName; }); u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address); memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size); size_t numFiles = 0; char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address)); for (size_t i = 0; i < entry.children.size() && i < MaxEntries; i++) { const std::string& FileName = entry.children[i].virtualName; strcpy(pFilename, FileName.c_str()); pFilename += FileName.length(); *pFilename++ = 0x00; // termination numFiles++; INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str()); } Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address); } ReturnValue = FS_RESULT_OK; } break; case IOCTLV_GETUSAGE: { _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2); _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4); _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4); // this command sucks because it asks of the number of used // fsBlocks and inodes // It should be correct, but don't count on it... std::string relativepath = Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size); if (!IsValidWiiPath(relativepath)) { WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relativepath.c_str()); ReturnValue = FS_RESULT_FATAL; break; } std::string path(HLE_IPC_BuildFilename(relativepath)); u32 fsBlocks = 0; u32 iNodes = 0; INFO_LOG(WII_IPC_FILEIO, "IOCTL_GETUSAGE %s", path.c_str()); if (File::IsDirectory(path)) { // LPFaint99: After I found that setting the number of inodes to the number of children + 1 // for the directory itself // I decided to compare with sneek which has the following 2 special cases which are // Copyright (C) 2009-2011 crediar http://code.google.com/p/sneek/ if ((relativepath.compare(0, 16, "/title/00010001") == 0) || (relativepath.compare(0, 16, "/title/00010005") == 0)) { fsBlocks = 23; // size is size/0x4000 iNodes = 42; // empty folders return a FileCount of 1 } else { File::FSTEntry parentDir = File::ScanDirectoryTree(path, true); // add one for the folder itself iNodes = 1 + (u32)parentDir.size; u64 totalSize = ComputeTotalFileSize(parentDir); // "Real" size, to be converted to nand blocks fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb } ReturnValue = FS_RESULT_OK; INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes); } else { fsBlocks = 0; iNodes = 0; ReturnValue = FS_RESULT_OK; WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str()); } Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address); Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address); } break; default: PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter); break; } Memory::Write_U32(ReturnValue, _CommandAddress + 4); return GetFSReply(); }
bool CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress) { SIOCtlVBuffer CommandBuffer(_CommandAddress); u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0; u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0; u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0; u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0; if (CommandBuffer.InBuffer.size() > 0) { _BufferIn = CommandBuffer.InBuffer.at(0).m_Address; BufferInSize = CommandBuffer.InBuffer.at(0).m_Size; } if (CommandBuffer.InBuffer.size() > 1) { _BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; } if (CommandBuffer.InBuffer.size() > 2) { _BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address; BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 0) { BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address; BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 1) { BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 2) { BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address; BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size; } switch (CommandBuffer.Parameter) { case IOCTLV_NET_SSL_NEW: { int verifyOption = Memory::Read_U32(BufferOut); const char * hostname = (const char*) Memory::GetPointer(BufferOut2); int freeSSL = this->getSSLFreeID(); if (freeSSL) { int sslID = freeSSL - 1; int ret = ssl_init(&_SSL[sslID].ctx); if (ret) { // Cleanup possibly dirty ctx memset(&_SSL[sslID].ctx, 0, sizeof(ssl_context)); goto _SSL_NEW_ERROR; } entropy_init(&_SSL[sslID].entropy); const char* pers = "dolphin-emu"; ret = ctr_drbg_init(&_SSL[sslID].ctr_drbg, entropy_func, &_SSL[sslID].entropy, (const unsigned char*)pers, strlen(pers)); if (ret) { ssl_free(&_SSL[sslID].ctx); // Cleanup possibly dirty ctx memset(&_SSL[sslID].ctx, 0, sizeof(ssl_context)); entropy_free(&_SSL[sslID].entropy); goto _SSL_NEW_ERROR; } ssl_set_rng(&_SSL[sslID].ctx, ctr_drbg_random, &_SSL[sslID].ctr_drbg); // For some reason we can't use TLSv1.2, v1.1 and below are fine! ssl_set_max_version(&_SSL[sslID].ctx, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); ssl_set_session(&_SSL[sslID].ctx, &_SSL[sslID].session); ssl_set_endpoint(&_SSL[sslID].ctx, SSL_IS_CLIENT); ssl_set_authmode(&_SSL[sslID].ctx, SSL_VERIFY_NONE); ssl_set_renegotiation(&_SSL[sslID].ctx, SSL_RENEGOTIATION_ENABLED); memcpy(_SSL[sslID].hostname, hostname, min((int)BufferOutSize2, NET_SSL_MAX_HOSTNAME_LEN)); _SSL[sslID].hostname[NET_SSL_MAX_HOSTNAME_LEN-1] = '\0'; ssl_set_hostname(&_SSL[sslID].ctx, _SSL[sslID].hostname); _SSL[sslID].active = true; Memory::Write_U32(freeSSL, _BufferIn); } else { _SSL_NEW_ERROR: Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW (%d, %s) " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", verifyOption, hostname, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SHUTDOWN: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { ssl_close_notify(&_SSL[sslID].ctx); ssl_session_free(&_SSL[sslID].session); ssl_free(&_SSL[sslID].ctx); entropy_free(&_SSL[sslID].entropy); x509_crt_free(&_SSL[sslID].cacert); x509_crt_free(&_SSL[sslID].clicert); memset(&_SSL[sslID].ctx, 0, sizeof(ssl_context)); memset(&_SSL[sslID].session, 0, sizeof(ssl_session)); memset(&_SSL[sslID].entropy, 0, sizeof(entropy_context)); memset(_SSL[sslID].hostname, 0, NET_SSL_MAX_HOSTNAME_LEN); _SSL[sslID].active = false; Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETROOTCA: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { int ret = x509_crt_parse_der( &_SSL[sslID].cacert, Memory::GetPointer(BufferOut2), BufferOutSize2); if (ret) { Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } else { ssl_set_ca_chain(&_SSL[sslID].ctx, &_SSL[sslID].cacert, NULL, _SSL[sslID].hostname); Memory::Write_U32(SSL_OK, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA = %d", ret); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } break; } case IOCTLV_NET_SSL_SETBUILTINCLIENTCERT: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); int ret = x509_crt_parse_file(&_SSL[sslID].clicert, (cert_base_path + "clientca.pem").c_str()); int pk_ret = pk_parse_keyfile(&_SSL[sslID].pk, (cert_base_path + "clientcakey.pem").c_str(), NULL); if (ret || pk_ret) { x509_crt_free(&_SSL[sslID].clicert); pk_free(&_SSL[sslID].pk); memset(&_SSL[sslID].clicert, 0, sizeof(x509_crt)); memset(&_SSL[sslID].pk, 0, sizeof(pk_context)); Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } else { ssl_set_own_cert(&_SSL[sslID].ctx, &_SSL[sslID].clicert, &_SSL[sslID].pk); Memory::Write_U32(SSL_OK, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = (%d, %d)", ret, pk_ret); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID); } break; } case IOCTLV_NET_SSL_REMOVECLIENTCERT: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_REMOVECLIENTCERT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { x509_crt_free(&_SSL[sslID].clicert); pk_free(&_SSL[sslID].pk); memset(&_SSL[sslID].clicert, 0, sizeof(x509_crt)); memset(&_SSL[sslID].pk, 0, sizeof(pk_context)); ssl_set_own_cert(&_SSL[sslID].ctx, NULL, NULL); Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID); } break; } case IOCTLV_NET_SSL_SETBUILTINROOTCA: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); int ret = x509_crt_parse_file(&_SSL[sslID].cacert, (cert_base_path + "rootca.pem").c_str()); if (ret) { x509_crt_free(&_SSL[sslID].clicert); Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); } else { ssl_set_ca_chain(&_SSL[sslID].ctx, &_SSL[sslID].cacert, NULL, _SSL[sslID].hostname); Memory::Write_U32(SSL_OK, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA = %d", ret); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_CONNECT: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { _SSL[sslID].sockfd = Memory::Read_U32(BufferOut2); INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", _SSL[sslID].sockfd); ssl_set_bio(&_SSL[sslID].ctx, net_recv, &_SSL[sslID].sockfd, net_send, &_SSL[sslID].sockfd); Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_DOHANDSHAKE: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WiiSockMan &sm = WiiSockMan::getInstance(); sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_DOHANDSHAKE); return false; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } break; } case IOCTLV_NET_SSL_WRITE: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WiiSockMan &sm = WiiSockMan::getInstance(); sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_WRITE); return false; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); INFO_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(BufferOut2)); break; } case IOCTLV_NET_SSL_READ: { int ret = 0; int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { WiiSockMan &sm = WiiSockMan::getInstance(); sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_READ); return false; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)" "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", ret, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETROOTCADEFAULT: { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT: { INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { Memory::Write_U32(SSL_OK, _BufferIn); } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } break; } default: ERROR_LOG(WII_IPC_SSL, "%i " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } // SSL return codes are written to BufferIn Memory::Write_U32(0, _CommandAddress+4); return true; }
void WiiSocket::Update(bool read, bool write, bool except) { auto it = pending_sockops.begin(); while (it != pending_sockops.end()) { s32 ReturnValue = 0; bool forceNonBlock = false; IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(it->_CommandAddress)); if (!it->is_ssl && ct == IPC_CMD_IOCTL) { u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10); u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14); u32 BufferOut = Memory::Read_U32(it->_CommandAddress + 0x18); u32 BufferOutSize = Memory::Read_U32(it->_CommandAddress + 0x1C); switch (it->net_type) { case IOCTL_SO_FCNTL: { u32 cmd = Memory::Read_U32(BufferIn + 4); u32 arg = Memory::Read_U32(BufferIn + 8); ReturnValue = FCntl(cmd, arg); break; } case IOCTL_SO_BIND: { // u32 has_addr = Memory::Read_U32(BufferIn + 0x04); sockaddr_in local_name; WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08); WiiSockMan::Convert(*wii_name, local_name); int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name)); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_BIND", false); INFO_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%08X %s:%d) = %d ", fd, inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port), ret); break; } case IOCTL_SO_CONNECT: { // u32 has_addr = Memory::Read_U32(BufferIn + 0x04); sockaddr_in local_name; WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08); WiiSockMan::Convert(*wii_name, local_name); int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name)); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_CONNECT", false); INFO_LOG(WII_IPC_NET, "IOCTL_SO_CONNECT (%08x, %s:%d)", fd, inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port)); break; } case IOCTL_SO_ACCEPT: { if (BufferOutSize > 0) { sockaddr_in local_name; WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut); WiiSockMan::Convert(*wii_name, local_name); socklen_t addrlen = sizeof(sockaddr_in); int ret = (s32)accept(fd, (sockaddr*)&local_name, &addrlen); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true); WiiSockMan::Convert(local_name, *wii_name, addrlen); } else { int ret = (s32)accept(fd, nullptr, nullptr); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true); } WiiSockMan::GetInstance().AddSocket(ReturnValue); INFO_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT " "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); break; } default: break; } // Fix blocking error codes if (!nonBlock) { if (it->net_type == IOCTL_SO_CONNECT && ReturnValue == -SO_EISCONN) { ReturnValue = SO_SUCCESS; } } } else if (ct == IPC_CMD_IOCTLV) { SIOCtlVBuffer CommandBuffer(it->_CommandAddress); u32 BufferIn = 0, BufferIn2 = 0; u32 BufferInSize = 0, BufferInSize2 = 0; u32 BufferOut = 0, BufferOut2 = 0; u32 BufferOutSize = 0, BufferOutSize2 = 0; if (CommandBuffer.InBuffer.size() > 0) { BufferIn = CommandBuffer.InBuffer.at(0).m_Address; BufferInSize = CommandBuffer.InBuffer.at(0).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 0) { BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address; BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size; } if (CommandBuffer.PayloadBuffer.size() > 1) { BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size; } if (CommandBuffer.InBuffer.size() > 1) { BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; } if (it->is_ssl) { int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { switch (it->ssl_type) { case IOCTLV_NET_SSL_DOHANDSHAKE: { mbedtls_ssl_context* ctx = &CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx; int ret = mbedtls_ssl_handshake(ctx); if (ret) { char error_buffer[256] = ""; mbedtls_strerror(ret, error_buffer, sizeof(error_buffer)); ERROR_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE: %s", error_buffer); } switch (ret) { case 0: Memory::Write_U32(SSL_OK, BufferIn); break; case MBEDTLS_ERR_SSL_WANT_READ: Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_RAGAIN; break; case MBEDTLS_ERR_SSL_WANT_WRITE: Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_WAGAIN; break; case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: { char error_buffer[256] = ""; int res = mbedtls_ssl_get_verify_result(ctx); mbedtls_x509_crt_verify_info(error_buffer, sizeof(error_buffer), "", res); ERROR_LOG(WII_IPC_SSL, "MBEDTLS_ERR_X509_CERT_VERIFY_FAILED (verify_result = %d): %s", res, error_buffer); if (res & MBEDTLS_X509_BADCERT_CN_MISMATCH) res = SSL_ERR_VCOMMONNAME; else if (res & MBEDTLS_X509_BADCERT_NOT_TRUSTED) res = SSL_ERR_VROOTCA; else if (res & MBEDTLS_X509_BADCERT_REVOKED) res = SSL_ERR_VCHAIN; else if (res & MBEDTLS_X509_BADCERT_EXPIRED || res & MBEDTLS_X509_BADCERT_FUTURE) res = SSL_ERR_VDATE; else res = SSL_ERR_FAILED; Memory::Write_U32(res, BufferIn); if (!nonBlock) ReturnValue = res; break; } default: Memory::Write_U32(SSL_ERR_FAILED, BufferIn); break; } // mbedtls_ssl_get_peer_cert(ctx) seems not to work if handshake failed // Below is an alternative to dump the peer certificate if (SConfig::GetInstance().m_SSLDumpPeerCert && ctx->session_negotiate != nullptr) { const mbedtls_x509_crt* cert = ctx->session_negotiate->peer_cert; if (cert != nullptr) { std::string filename = File::GetUserPath(D_DUMPSSL_IDX) + ((ctx->hostname != nullptr) ? ctx->hostname : "") + "_peercert.der"; File::IOFile(filename, "wb").WriteBytes(cert->raw.p, cert->raw.len); } } INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)", ret, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2); break; } case IOCTLV_NET_SSL_WRITE: { int ret = mbedtls_ssl_write(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferOut2), BufferOutSize2); if (SConfig::GetInstance().m_SSLDumpWrite && ret > 0) { std::string filename = File::GetUserPath(D_DUMPSSL_IDX) + SConfig::GetInstance().GetGameID() + "_write.bin"; File::IOFile(filename, "ab").WriteBytes(Memory::GetPointer(BufferOut2), ret); } if (ret >= 0) { // Return bytes written or SSL_ERR_ZERO if none Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } else { switch (ret) { case MBEDTLS_ERR_SSL_WANT_READ: Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_RAGAIN; break; case MBEDTLS_ERR_SSL_WANT_WRITE: Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_WAGAIN; break; default: Memory::Write_U32(SSL_ERR_FAILED, BufferIn); break; } } break; } case IOCTLV_NET_SSL_READ: { int ret = mbedtls_ssl_read(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferIn2), BufferInSize2); if (SConfig::GetInstance().m_SSLDumpRead && ret > 0) { std::string filename = File::GetUserPath(D_DUMPSSL_IDX) + SConfig::GetInstance().GetGameID() + "_read.bin"; File::IOFile(filename, "ab").WriteBytes(Memory::GetPointer(BufferIn2), ret); } if (ret >= 0) { // Return bytes read or SSL_ERR_ZERO if none Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } else { switch (ret) { case MBEDTLS_ERR_SSL_WANT_READ: Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_RAGAIN; break; case MBEDTLS_ERR_SSL_WANT_WRITE: Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); if (!nonBlock) ReturnValue = SSL_ERR_WAGAIN; break; default: Memory::Write_U32(SSL_ERR_FAILED, BufferIn); break; } } break; } default: break; } } else { Memory::Write_U32(SSL_ERR_ID, BufferIn); } } else { switch (it->net_type) { case IOCTLV_SO_SENDTO: { u32 flags = Memory::Read_U32(BufferIn2 + 0x04); u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08); // Not a string, Windows requires a const char* for sendto const char* data = (const char*)Memory::GetPointer(BufferIn); // Act as non blocking when SO_MSG_NONBLOCK is specified forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK); // send/sendto only handles MSG_OOB flags &= SO_MSG_OOB; sockaddr_in local_name = {0}; if (has_destaddr) { WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn2 + 0x0C); WiiSockMan::Convert(*wii_name, local_name); } int ret = sendto(fd, data, BufferInSize, flags, has_destaddr ? (struct sockaddr*)&local_name : nullptr, has_destaddr ? sizeof(sockaddr) : 0); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true); DEBUG_LOG( WII_IPC_NET, "%s = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u", has_destaddr ? "IOCTLV_SO_SENDTO " : "IOCTLV_SO_SEND ", ReturnValue, fd, BufferIn, BufferInSize, BufferIn2, BufferInSize2, local_name.sin_addr.s_addr & 0xFF, (local_name.sin_addr.s_addr >> 8) & 0xFF, (local_name.sin_addr.s_addr >> 16) & 0xFF, (local_name.sin_addr.s_addr >> 24) & 0xFF); break; } case IOCTLV_SO_RECVFROM: { u32 flags = Memory::Read_U32(BufferIn + 0x04); // Not a string, Windows requires a char* for recvfrom char* data = (char*)Memory::GetPointer(BufferOut); int data_len = BufferOutSize; sockaddr_in local_name; memset(&local_name, 0, sizeof(sockaddr_in)); if (BufferOutSize2 != 0) { WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2); WiiSockMan::Convert(*wii_name, local_name); } // Act as non blocking when SO_MSG_NONBLOCK is specified forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK); // recv/recvfrom only handles PEEK/OOB flags &= SO_MSG_PEEK | SO_MSG_OOB; #ifdef _WIN32 if (flags & SO_MSG_PEEK) { unsigned long totallen = 0; ioctlsocket(fd, FIONREAD, &totallen); ReturnValue = totallen; break; } #endif socklen_t addrlen = sizeof(sockaddr_in); int ret = recvfrom(fd, data, data_len, flags, BufferOutSize2 ? (struct sockaddr*)&local_name : nullptr, BufferOutSize2 ? &addrlen : nullptr); ReturnValue = WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true); INFO_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)", BufferOutSize2 ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ", ReturnValue, data, fd, flags, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2); if (BufferOutSize2 != 0) { WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2); WiiSockMan::Convert(local_name, *wii_name, addrlen); } break; } default: break; } } } if (nonBlock || forceNonBlock || (!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS && ReturnValue != -SO_EALREADY) || (it->is_ssl && ReturnValue != SSL_ERR_WAGAIN && ReturnValue != SSL_ERR_RAGAIN)) { DEBUG_LOG(WII_IPC_NET, "IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", fd, it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock, forceNonBlock); Memory::Write_U32(ReturnValue, it->_CommandAddress + 4); WII_IPC_HLE_Interface::EnqueueReply(it->_CommandAddress); it = pending_sockops.erase(it); } else { ++it; } }
IPCCommandResult CWII_IPC_HLE_Device_usb_oh0_46d_a03::IOCtlV(u32 CommandAddress) { IPCCommandResult SendReply = GetNoReply(); SIOCtlVBuffer CommandBuffer(CommandAddress); switch (CommandBuffer.Parameter) { case USBV0_IOCTL_CTRLMSG: { USBSetupPacket setup_packet; setup_packet.bmRequestType = *( u8*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address); setup_packet.bRequest = *( u8*)Memory::GetPointer(CommandBuffer.InBuffer[1].m_Address); setup_packet.wValue = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[2].m_Address); setup_packet.wIndex = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[3].m_Address); setup_packet.wLength = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[4].m_Address); const u32 payload_addr = CommandBuffer.PayloadBuffer[0].m_Address; #define DIR_TO_DEV 0 #define DIR_TO_HOST 1 #define TYPE_STANDARD 0 #define TYPE_CLASS 1 #define TYPE_VENDOR 2 #define RECP_DEV 0 #define RECP_INT 1 #define RECP_ENDP 2 #define USBHDR(dir, type, recipient, request) \ ((((dir << 7) | (type << 5) | recipient) << 8) | request) switch (((u16)setup_packet.bmRequestType << 8) | setup_packet.bRequest) { case USBHDR(DIR_TO_HOST, TYPE_STANDARD, RECP_DEV, 6): // GET_DESCRIPTOR switch (setup_packet.wValue >> 8) { // CONFIGURATION case 2: { const usb_configurationdesc config = { 9, 2, 121, 2, 1, 3, 0x80, 30 }; if (setup_packet.wLength == 9) { memcpy(Memory::GetPointer(payload_addr), &config, setup_packet.wLength); } else { #define LE24(x) (x & 0xff), ((x >> 8) & 0xff), (x >> 16) #pragma pack(push, 1) struct { usb_configurationdesc config; usb_interfacedesc int0; struct audiocontrol_hdr { u8 bLength; u8 bDescriptorType; u8 bDescriptorSubtype; }; struct { audiocontrol_hdr hdr; u16 bcdADC; u16 wTotalLength; u8 bInCollection; u8 baInterfaceNr; } audiocontrol_header; struct { audiocontrol_hdr hdr; u8 bTerminalID; u16 wTerminalType; u8 bAssocTerminal; u8 bNrChannels; u16 wChannelConfig; u8 iChannelNames; u8 iTerminal; } audiocontrol_input_terminal; struct { audiocontrol_hdr hdr; u8 bUnitID; u8 bSourceID; u8 bControlSize; u8 bmaControls0; u8 bmaControls1; u8 iFeature; } audiocontrol_feature_unit; struct { audiocontrol_hdr hdr; u8 bTerminalID; u16 wTerminalType; u8 bAssocTerminal; u8 bSourceID; u8 iTerminal; } audiocontrol_output_terminal; usb_interfacedesc int1; usb_interfacedesc int2; struct { audiocontrol_hdr hdr; u8 bTerminalLink; u8 bDelay; u16 wFormatTag; } audiocontrol_as_general; struct { audiocontrol_hdr hdr; u8 bFormatType; u8 bNrChannels; u8 bSubframeSize; u8 bBitResolution; u8 bSamFreqType; u8 tSamFreq[3 * 5]; } audiocontrol_format_type; usb_endpointdesc endp; struct { audiocontrol_hdr hdr; u8 bmAttributes; u8 bLockDelayUnits; u16 wLockDelay; } audiocontrol_ep_general; } const fullconfig = { config, { 9, 4, 0, 0, 0, 1, 1, 0, 0 }, { 9, 36, 1, 0x100, 39, 1, 1 }, { 12, 36, 2, 13, 0x201, 0, 1, 0, 0, 0 }, { 9, 36, 6, 2, 13, 1, 3, 0 }, { 9, 36, 3, 10, 0x101, 0, 2, 0 }, { 9, 4, 1, 0, 0, 1, 2, 0, 0 }, { 9, 4, 1, 1, 1, 1, 2, 0, 0 }, { 7, 36, 1, 10, 0, 1 }, { 23, 36, 2, 1, 1, 2, 16, 5, LE24(8000), LE24(11025), LE24(22050), LE24(44100), LE24(48000) }, { 9, 5, 0x84, 13, 0x60, 1, 0, 0 }, { 7, 37, 1, 1, 2, 1 } }; #pragma pack(pop) #undef LE24 memcpy(Memory::GetPointer(payload_addr), &fullconfig, setup_packet.wLength); } Memory::Write_U32(sizeof(USBSetupPacket) + setup_packet.wLength, CommandAddress + 4); return GetDefaultReply(); } break; default: goto outerdefault; } break; case USBHDR(DIR_TO_HOST, TYPE_CLASS, RECP_INT, 0x82): case USBHDR(DIR_TO_HOST, TYPE_CLASS, RECP_INT, 0x83): if (setup_packet.bRequest & 1) Memory::Write_U16(0x7fff, payload_addr); else Memory::Write_U16(0x8000, payload_addr); break; case USBHDR(DIR_TO_DEV, TYPE_CLASS, RECP_ENDP, 1): { u32 freq = *(u32*)Memory::GetPointer(payload_addr) & 0xffffff; WARN_LOG(OSHLE, "set freq: %x", freq); } break; case USBHDR(DIR_TO_DEV, TYPE_STANDARD, RECP_INT, 11): break; outerdefault: default: WARN_LOG(OSHLE, "UNK %02x %02x %04x %04x", setup_packet.bmRequestType, setup_packet.bRequest, setup_packet.wValue, setup_packet.wLength); break; } // command finished, send a reply to command WII_IPC_HLE_Interface::EnqueueReply(CommandBuffer.m_Address); } break; case USBV0_IOCTL_ISOMSG: { // endp 81 = mic -> console // endp 03 = console -> mic u8 endpoint = Memory::Read_U8(CommandBuffer.InBuffer[0].m_Address); u16 length = Memory::Read_U16(CommandBuffer.InBuffer[1].m_Address); u8 num_packets = Memory::Read_U8(CommandBuffer.InBuffer[2].m_Address); u16 *packet_sizes = (u16*)Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address); u8 *packets = Memory::GetPointer(CommandBuffer.PayloadBuffer[1].m_Address); u16 packet_len = Common::swap16(packet_sizes[0]); WARN_LOG(OSHLE, "%i to endpoint %02x", packet_len, endpoint); /* for (int i = 0; i < num_packets; i++) { u16 packet_len = Common::swap16(packet_sizes[i]); WARN_LOG(OSHLE, "packet %i [%i] to endpoint %02x", i, packet_len, endpoint); WARN_LOG(OSHLE, "%s", ArrayToString(packets, packet_len, 16).c_str()); packets += packet_len; } */ if (endpoint == AUDIO_IN) for (u16 *sample = (u16*)packets; sample != (u16*)(packets + length); sample++) *sample = 0; // TODO actual responses should obey some kinda timey thing SendReply = GetDefaultReply(); } break; default: WARN_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str()); WARN_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); WARN_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); WARN_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); WARN_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); //DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer, LogTypes::OSHLE, LogTypes::LWARNING); break; } Memory::Write_U32(0, CommandAddress + 4); return SendReply; }
IPCCommandResult CWII_IPC_HLE_Device_usb_oh0_57e_308::IOCtlV(u32 CommandAddress) { IPCCommandResult SendReply = GetNoReply(); SIOCtlVBuffer CommandBuffer(CommandAddress); switch (CommandBuffer.Parameter) { case USBV0_IOCTL_CTRLMSG: { USBSetupPacket setup_packet; setup_packet.bmRequestType = *( u8*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address); setup_packet.bRequest = *( u8*)Memory::GetPointer(CommandBuffer.InBuffer[1].m_Address); setup_packet.wValue = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[2].m_Address); setup_packet.wIndex = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[3].m_Address); setup_packet.wLength = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[4].m_Address); const u32 payload_addr = CommandBuffer.PayloadBuffer[0].m_Address; static bool initialized = false; #define DIR_TO_DEV 0 #define DIR_TO_HOST 1 #define TYPE_STANDARD 0 #define TYPE_VENDOR 2 #define RECP_DEV 0 #define RECP_INT 1 #define RECP_ENDP 2 #define USBHDR(dir, type, recipient, request) \ ((((dir << 7) | (type << 5) | recipient) << 8) | request) switch (((u16)setup_packet.bmRequestType << 8) | setup_packet.bRequest) { case USBHDR(DIR_TO_DEV, TYPE_STANDARD, RECP_INT, 11): _dbg_assert_(OSHLE, setup_packet.wValue == 1); break; case USBHDR(DIR_TO_HOST, TYPE_STANDARD, RECP_INT, 10): Memory::Write_U8(1, payload_addr); break; case USBHDR(DIR_TO_HOST, TYPE_VENDOR, RECP_INT, 6): if (!initialized) Memory::Write_U8(0, payload_addr), initialized = true; else Memory::Write_U8(1, payload_addr); break; case USBHDR(DIR_TO_DEV, TYPE_VENDOR, RECP_INT, 1): SetRegister(payload_addr); break; case USBHDR(DIR_TO_HOST, TYPE_VENDOR, RECP_INT, 2): GetRegister(payload_addr); break; case USBHDR(DIR_TO_DEV, TYPE_VENDOR, RECP_INT, 0): initialized = false; break; default: WARN_LOG(OSHLE, "UNK %02x %02x %04x %04x", setup_packet.bmRequestType, setup_packet.bRequest, setup_packet.wValue, setup_packet.wLength); break; } // command finished, send a reply to command WII_IPC_HLE_Interface::EnqueueReply(CommandBuffer.m_Address); } break; case USBV0_IOCTL_BLKMSG: { u8 Command = Memory::Read_U8(CommandBuffer.InBuffer[0].m_Address); switch (Command) { // used for sending firmware case DATA_OUT: { u16 len = Memory::Read_U16(CommandBuffer.InBuffer[1].m_Address); WARN_LOG(OSHLE, "SEND DATA %x %x %x", len, CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size); SendReply = GetDefaultReply(); } break; default: WARN_LOG(OSHLE, "UNK BLKMSG %i", Command); break; } } break; case USBV0_IOCTL_ISOMSG: { // endp 81 = mic -> console // endp 03 = console -> mic u8 endpoint = Memory::Read_U8(CommandBuffer.InBuffer[0].m_Address); u16 length = Memory::Read_U16(CommandBuffer.InBuffer[1].m_Address); u8 num_packets = Memory::Read_U8(CommandBuffer.InBuffer[2].m_Address); u16 *packet_sizes = (u16*)Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address); u8 *packets = Memory::GetPointer(CommandBuffer.PayloadBuffer[1].m_Address); /* for (int i = 0; i < num_packets; i++) { u16 packet_len = Common::swap16(packet_sizes[i]); WARN_LOG(OSHLE, "packet %i [%i] to endpoint %02x", i, packet_len, endpoint); WARN_LOG(OSHLE, "%s", ArrayToString(packets, packet_len, 16).c_str()); packets += packet_len; } */ if (endpoint == AUDIO_IN) for (u16 *sample = (u16*)packets; sample != (u16*)(packets + length); sample++) *sample = 0x8000; // TODO actual responses should obey some kinda timey thing SendReply = GetDefaultReply(); } break; default: WARN_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str()); WARN_LOG(OSHLE, " Parameter: 0x%x", CommandBuffer.Parameter); WARN_LOG(OSHLE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); WARN_LOG(OSHLE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); WARN_LOG(OSHLE, " BufferVector: 0x%08x", CommandBuffer.BufferVector); //DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer, LogTypes::OSHLE, LogTypes::LWARNING); break; } Memory::Write_U32(0, CommandAddress + 4); return SendReply; }