Skip to content

Commit

Permalink
Add preliminary USBD HLE.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpd002 committed May 9, 2024
1 parent 6818811 commit b44e458
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ set(COMMON_SRC_FILES
iop/Iop_Thvpool.h
iop/Iop_Timrman.cpp
iop/Iop_Timrman.h
iop/Iop_Usbd.cpp
iop/Iop_Usbd.h
iop/Iop_Vblank.cpp
iop/Iop_Vblank.h
iop/IopBios.cpp
Expand Down
4 changes: 4 additions & 0 deletions Source/iop/IopBios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#ifdef _IOP_EMULATE_MODULES
#include "Iop_IomanX.h"
#include "Iop_Naplink.h"
#include "Iop_Usbd.h"
#endif

#include "Iop_SifManNull.h"
Expand Down Expand Up @@ -263,6 +264,9 @@ void CIopBios::Reset(uint32 ramSize, const Iop::SifManPtr& sifMan)
m_powerOff = std::make_shared<Iop::CPowerOff>(*m_sifMan);
RegisterModule(m_powerOff);
}
{
RegisterModule(std::make_shared<Iop::CUsbd>(*this, m_ram));
}
RegisterModule(std::make_shared<Iop::CIomanX>(*m_ioman));
//RegisterModule(std::make_shared<Iop::CNaplink>(*m_sifMan, *m_ioman));
{
Expand Down
177 changes: 177 additions & 0 deletions Source/iop/Iop_Usbd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include "Iop_Usbd.h"
#include "IopBios.h"
#include "../Log.h"

using namespace Iop;

#define LOG_NAME "iop_usbd"

#define FUNCTION_REGISTERLLD "RegisterLld"
#define FUNCTION_SCANSTATICDESCRIPTOR "ScanStaticDescriptor"
#define FUNCTION_OPENPIPE "OpenPipe"
#define FUNCTION_TRANSFERPIPE "TransferPipe"
#define FUNCTION_GETDEVICELOCATION "GetDeviceLocation"

static constexpr uint32 g_deviceId = 0xBEEFBEEF;
static constexpr uint32 g_pipeId = 0xDEADEAD;

CUsbd::CUsbd(CIopBios& bios, uint8* ram)
: m_bios(bios)
, m_ram(ram)
{
}

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:
context.m_State.nGPR[CMIPS::V0].nD0 = TransferPipe();
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;
}
}

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);
if(!strcmp(name, "buzzer"))
{
m_descriptorMemPtr = m_bios.GetSysmem()->AllocateMemory(0x80, 0, 0);
m_bios.TriggerCallback(lldOps->connectFctPtr, g_deviceId);
}
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);

assert(deviceId == g_deviceId);

//Details about descriptors here:
//https://www.beyondlogic.org/usbnutshell/usb5.shtml

uint32 result = 0;
switch(descriptorType)
{
case 1:
{
//Device descriptor
uint8* descriptorMem = reinterpret_cast<uint8*>(m_ram + m_descriptorMemPtr);
descriptorMem[1] = descriptorType;
result = m_descriptorMemPtr;
}
break;
case 2:
{
//Configuration descriptor
uint8* descriptorMem = reinterpret_cast<uint8*>(m_ram + m_descriptorMemPtr);
descriptorMem[1] = descriptorType;
descriptorMem[4] = 1;
result = m_descriptorMemPtr;
}
break;
case 4:
{
//Interface descriptor
uint8* descriptorMem = reinterpret_cast<uint8*>(m_ram + m_descriptorMemPtr);
descriptorMem[1] = descriptorType;
descriptorMem[4] = 1;
result = m_descriptorMemPtr;
}
break;
case 5:
{
//Endpoint descriptor
uint8* descriptorMem = reinterpret_cast<uint8*>(m_ram + m_descriptorMemPtr);
if(descriptorMem[1] != descriptorType)
{
descriptorMem[1] = descriptorType;
descriptorMem[2] = 0x80;
descriptorMem[3] = 0x3;
result = m_descriptorMemPtr;
}
}
break;
}

return result;
}

int32 CUsbd::OpenPipe(uint32 deviceId, uint32 descriptorPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_OPENPIPE "(deviceId = 0x%08X, descriptorPtr = 0x%08X);\r\n",
deviceId, descriptorPtr);
return g_pipeId;
}

int32 CUsbd::TransferPipe()
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_TRANSFERPIPE "();\r\n");
return 0;
}

int32 CUsbd::GetDeviceLocation(uint32 deviceId, uint32 locationPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_GETDEVICELOCATION "(deviceId = 0x%08X, locationPtr = 0x%08X);\r\n",
deviceId, locationPtr);

assert(deviceId == g_deviceId);
uint8* location = reinterpret_cast<uint8*>(m_ram + locationPtr);
memset(location, 0, 7);
location[0] = 1;

return 0;
}
42 changes: 42 additions & 0 deletions Source/iop/Iop_Usbd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "Iop_Module.h"

class CIopBios;

namespace Iop
{
class CUsbd : public CModule
{
public:
CUsbd(CIopBios&, uint8*);
virtual ~CUsbd() = default;

std::string GetId() const override;
std::string GetFunctionName(unsigned int) const override;
void Invoke(CMIPS&, unsigned int) override;

private:
struct LLDOPS
{
uint32 nextPtr;
uint32 prevPtr;
uint32 namePtr;
uint32 probeFctPtr;
uint32 connectFctPtr;
uint32 disconnectFctPtr;
uint32 reserved[5];
uint32 gp;
};

int32 RegisterLld(uint32);
int32 ScanStaticDescriptor(uint32, uint32, uint32);
int32 OpenPipe(uint32, uint32);
int32 TransferPipe();
int32 GetDeviceLocation(uint32, uint32);

CIopBios& m_bios;
uint8* m_ram = nullptr;
uint32 m_descriptorMemPtr = 0;
};
}

0 comments on commit b44e458

Please sign in to comment.