Play-/Source/iop/Iop_Usbd.cpp

228 lines
6.9 KiB
C++
Raw Normal View History

2024-05-09 17:22:26 -04:00
#include "Iop_Usbd.h"
2024-07-17 19:30:07 -04:00
#include <cstring>
2024-05-09 17:22:26 -04:00
#include "IopBios.h"
2025-03-11 12:48:26 -04:00
#include "Log.h"
2024-06-18 17:00:13 -04:00
#include "string_format.h"
#include "lexical_cast_ex.h"
#include "UsbBuzzerDevice.h"
2024-06-18 17:00:13 -04:00
#include "states/RegisterStateCollectionFile.h"
2024-05-09 17:22:26 -04:00
using namespace Iop;
#define LOG_NAME "iop_usbd"
2024-06-18 17:00:13 -04:00
#define STATE_XML ("iop_usbd/state.xml")
2024-05-09 17:22:26 -04:00
#define FUNCTION_REGISTERLLD "RegisterLld"
#define FUNCTION_SCANSTATICDESCRIPTOR "ScanStaticDescriptor"
#define FUNCTION_OPENPIPE "OpenPipe"
#define FUNCTION_TRANSFERPIPE "TransferPipe"
#define FUNCTION_GETDEVICELOCATION "GetDeviceLocation"
CUsbd::CUsbd(CIopBios& bios, uint8* ram)
: m_bios(bios)
, m_ram(ram)
{
RegisterDevice(std::make_unique<CBuzzerUsbDevice>(bios, ram));
2024-05-09 17:22:26 -04:00
}
std::string CUsbd::GetId() const
{
return "usbd";
}
std::string CUsbd::GetFunctionName(unsigned int functionId) const
{
switch(functionId)
{
case 4:
return FUNCTION_REGISTERLLD;
case 6:
return FUNCTION_SCANSTATICDESCRIPTOR;
case 9:
return FUNCTION_OPENPIPE;
case 11:
return FUNCTION_TRANSFERPIPE;
case 13:
return FUNCTION_GETDEVICELOCATION;
default:
return "unknown";
}
}
void CUsbd::Invoke(CMIPS& context, unsigned int functionId)
{
switch(functionId)
{
case 4:
context.m_State.nGPR[CMIPS::V0].nD0 = RegisterLld(
context.m_State.nGPR[CMIPS::A0].nV0);
break;
case 6:
context.m_State.nGPR[CMIPS::V0].nD0 = ScanStaticDescriptor(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0);
break;
case 9:
context.m_State.nGPR[CMIPS::V0].nD0 = OpenPipe(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0);
break;
case 11:
2024-05-13 16:09:41 -04:00
context.m_State.nGPR[CMIPS::V0].nD0 = TransferPipe(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0,
context.m_State.nGPR[CMIPS::A3].nV0,
context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10),
context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x14));
2024-05-09 17:22:26 -04:00
break;
case 13:
context.m_State.nGPR[CMIPS::V0].nD0 = GetDeviceLocation(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0);
break;
default:
CLog::GetInstance().Warn(LOG_NAME, "Unknown function called (%d).\r\n", functionId);
break;
}
}
2024-06-18 17:00:13 -04:00
void CUsbd::SaveState(Framework::CZipArchiveWriter& writer) const
{
auto devicesStateFile = std::make_unique<CRegisterStateCollectionFile>(STATE_XML);
for(auto activeDeviceId : m_activeDeviceIds)
{
auto devicePairIterator = m_devices.find(activeDeviceId);
assert(devicePairIterator != m_devices.end());
auto& device = devicePairIterator->second;
auto deviceStateId = string_format("%08x", device->GetId());
CRegisterState deviceState;
device->SaveState(deviceState);
devicesStateFile->InsertRegisterState(deviceStateId.c_str(), std::move(deviceState));
}
writer.InsertFile(std::move(devicesStateFile));
}
void CUsbd::LoadState(Framework::CZipArchiveReader& reader)
{
m_activeDeviceIds.clear();
auto deviceStateFile = CRegisterStateCollectionFile(*reader.BeginReadFile(STATE_XML));
for(const auto& deviceStatePair : deviceStateFile)
{
uint32 deviceId = lexical_cast_hex<std::string>(deviceStatePair.first);
auto devicePairIterator = m_devices.find(deviceId);
if(devicePairIterator == std::end(m_devices)) continue;
const auto& deviceState = deviceStatePair.second;
auto& device = devicePairIterator->second;
device->LoadState(deviceState);
m_activeDeviceIds.push_back(deviceId);
}
}
2024-05-13 16:09:41 -04:00
void CUsbd::CountTicks(uint32 ticks)
{
for(auto activeDeviceId : m_activeDeviceIds)
2024-05-13 16:09:41 -04:00
{
assert(m_devices.find(activeDeviceId) != std::end(m_devices));
auto& device = m_devices[activeDeviceId];
device->CountTicks(ticks);
2024-05-13 16:09:41 -04:00
}
}
void CUsbd::RegisterDevice(UsbDevicePtr device)
2024-05-13 16:09:41 -04:00
{
auto result = m_devices.insert(std::make_pair(device->GetId(), std::move(device)));
assert(result.second);
2024-05-13 16:09:41 -04:00
}
2024-05-09 17:22:26 -04:00
int32 CUsbd::RegisterLld(uint32 lldOpsPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_REGISTERLLD "(lldOpsPtr = 0x%08X);\r\n",
lldOpsPtr);
auto lldOps = reinterpret_cast<const LLDOPS*>(m_ram + lldOpsPtr);
const char* name = reinterpret_cast<const char*>(m_ram + lldOps->namePtr);
for(const auto& devicePair : m_devices)
2024-05-09 17:22:26 -04:00
{
auto& device = devicePair.second;
if(!strcmp(name, device->GetLldName()))
{
device->OnLldRegistered();
m_activeDeviceIds.push_back(device->GetId());
m_bios.TriggerCallback(lldOps->connectFctPtr, device->GetId());
}
2024-05-09 17:22:26 -04:00
}
return 0;
}
int32 CUsbd::ScanStaticDescriptor(uint32 deviceId, uint32 descriptorPtr, uint32 descriptorType)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_SCANSTATICDESCRIPTOR "(deviceId = 0x%08X, descriptorPtr = 0x%08X, descriptorType = %d);\r\n",
deviceId, descriptorPtr, descriptorType);
auto deviceIteratorPair = m_devices.find(deviceId);
if(deviceIteratorPair != std::end(m_devices))
2024-05-09 17:22:26 -04:00
{
auto& device = deviceIteratorPair->second;
return device->ScanStaticDescriptor(deviceId, descriptorPtr, descriptorType);
2024-05-09 17:22:26 -04:00
}
else
2024-05-09 17:22:26 -04:00
{
CLog::GetInstance().Warn(LOG_NAME, FUNCTION_SCANSTATICDESCRIPTOR " called on unknown device id 0x%08X.\r\n", deviceId);
return 0;
2024-05-09 17:22:26 -04:00
}
}
int32 CUsbd::OpenPipe(uint32 deviceId, uint32 descriptorPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_OPENPIPE "(deviceId = 0x%08X, descriptorPtr = 0x%08X);\r\n",
deviceId, descriptorPtr);
auto deviceIteratorPair = m_devices.find(deviceId);
if(deviceIteratorPair != std::end(m_devices))
2024-05-13 16:09:41 -04:00
{
auto& device = deviceIteratorPair->second;
uint16 pipeId = device->OpenPipe(deviceId, descriptorPtr);
assert(pipeId < 0x8000);
return (static_cast<uint32>(pipeId) << 16) | deviceId;
2024-05-13 16:09:41 -04:00
}
else
{
CLog::GetInstance().Warn(LOG_NAME, FUNCTION_OPENPIPE " called on unknown device id 0x%08X.\r\n", deviceId);
return -1;
2024-05-13 16:09:41 -04:00
}
2024-05-09 17:22:26 -04:00
}
2024-05-13 16:09:41 -04:00
int32 CUsbd::TransferPipe(uint32 pipeId, uint32 bufferPtr, uint32 size, uint32 optionPtr, uint32 doneCb, uint32 arg)
2024-05-09 17:22:26 -04:00
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_TRANSFERPIPE "(pipeId = 0x%08X, bufferPtr = 0x%08X, length = %d, optionPtr = 0x%08X, doneCb = 0x%08X, arg = 0x%08X);\r\n",
pipeId, bufferPtr, size, optionPtr, doneCb, arg);
uint16 deviceId = (pipeId & 0xFFFF);
auto deviceIteratorPair = m_devices.find(deviceId);
if(deviceIteratorPair != std::end(m_devices))
2024-05-13 16:09:41 -04:00
{
auto& device = deviceIteratorPair->second;
return device->TransferPipe(pipeId, bufferPtr, size, optionPtr, doneCb, arg);
2024-05-13 16:09:41 -04:00
}
else
{
CLog::GetInstance().Warn(LOG_NAME, FUNCTION_TRANSFERPIPE " called on unknown device id 0x%08X.\r\n", deviceId);
return -1;
2024-05-13 16:09:41 -04:00
}
2024-05-09 17:22:26 -04:00
}
int32 CUsbd::GetDeviceLocation(uint32 deviceId, uint32 locationPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_GETDEVICELOCATION "(deviceId = 0x%08X, locationPtr = 0x%08X);\r\n",
deviceId, locationPtr);
auto location = reinterpret_cast<uint8*>(m_ram + locationPtr);
2024-05-09 17:22:26 -04:00
memset(location, 0, 7);
location[0] = 1;
return 0;
}