diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index fa0d6c82ea..54475aaef1 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -421,6 +421,9 @@ set(COMMON_SRC_FILES iop/IopBios.cpp iop/IopBios.h iop/UsbDefs.h + iop/UsbDevice.h + iop/UsbBuzzerDevice.cpp + iop/UsbBuzzerDevice.h ISO9660/BlockProvider.h ISO9660/DirectoryRecord.cpp ISO9660/DirectoryRecord.h diff --git a/Source/PS2VM.cpp b/Source/PS2VM.cpp index 05d3977b06..54507579c5 100644 --- a/Source/PS2VM.cpp +++ b/Source/PS2VM.cpp @@ -12,6 +12,7 @@ #include "ee/EeExecutor.h" #include "Ps2Const.h" #include "iop/Iop_SifManPs2.h" +#include "iop/UsbBuzzerDevice.h" #include "StdStream.h" #include "StdStreamUtils.h" #include "states/MemoryStateFile.h" @@ -851,8 +852,12 @@ void CPS2VM::RegisterModulesInPadHandler() m_pad->RemoveAllListeners(); m_pad->InsertListener(iopOs->GetPadman()); - m_pad->InsertListener(iopOs->GetUsbd()); m_pad->InsertListener(&m_iop->m_sio2); + + { + auto device = iopOs->GetUsbd()->GetDevice(); + device->SetPadHandler(m_pad); + } } void CPS2VM::ReloadExecutable(const char* executablePath, const CPS2OS::ArgumentList& arguments) diff --git a/Source/iop/Iop_Usbd.cpp b/Source/iop/Iop_Usbd.cpp index 95ffe9d519..41c88099cd 100644 --- a/Source/iop/Iop_Usbd.cpp +++ b/Source/iop/Iop_Usbd.cpp @@ -1,7 +1,7 @@ #include "Iop_Usbd.h" #include "IopBios.h" #include "../Log.h" -#include "UsbDefs.h" +#include "UsbBuzzerDevice.h" using namespace Iop; @@ -13,14 +13,11 @@ using namespace Iop; #define FUNCTION_TRANSFERPIPE "TransferPipe" #define FUNCTION_GETDEVICELOCATION "GetDeviceLocation" -static constexpr uint32 g_deviceId = 0xBEEF; -static constexpr uint32 g_controlPipeId = 0xCAFE; -static constexpr uint32 g_pipeId = 0xDEAD; - CUsbd::CUsbd(CIopBios& bios, uint8* ram) : m_bios(bios) , m_ram(ram) { + RegisterDevice(std::make_unique(bios, ram)); } std::string CUsbd::GetId() const @@ -88,55 +85,18 @@ void CUsbd::Invoke(CMIPS& context, unsigned int functionId) void CUsbd::CountTicks(uint32 ticks) { - if(m_nextTransferTicks != 0) + for(auto activeDeviceId : m_activeDeviceIds) { - m_nextTransferTicks -= ticks; - if(m_nextTransferTicks <= 0) - { - uint8* buffer = m_ram + m_transferBufferPtr; - buffer[0] = 0x7F; - buffer[1] = 0x7F; - buffer[2] = m_buttonState; - buffer[3] = 0x00; - buffer[4] = 0xF0; - m_bios.TriggerCallback(m_transferCb, 0, m_transferSize, m_transferCbArg); - m_nextTransferTicks = 0; - m_transferCb = 0; - } + assert(m_devices.find(activeDeviceId) != std::end(m_devices)); + auto& device = m_devices[activeDeviceId]; + device->CountTicks(ticks); } } -void CUsbd::SetButtonState(unsigned int padNumber, PS2::CControllerInfo::BUTTON button, bool pressed, uint8* ram) +void CUsbd::RegisterDevice(UsbDevicePtr device) { - if(padNumber == 0) - { - //Reference for data transfer: - //https://gist.github.com/Lewiscowles1986/eef220dac6f0549e4702393a7b9351f6 - uint8 mask = 0; - switch(button) - { - case PS2::CControllerInfo::CROSS: - mask = 1; //Red - break; - case PS2::CControllerInfo::CIRCLE: - mask = 2; //Yellow - break; - case PS2::CControllerInfo::SQUARE: - mask = 4; //Green - break; - case PS2::CControllerInfo::TRIANGLE: - mask = 8; //Orange - break; - case PS2::CControllerInfo::DPAD_UP: - mask = 0x10; //Blue - break; - } - if(mask != 0) - { - m_buttonState &= ~mask; - if(pressed) m_buttonState |= mask; - } - } + auto result = m_devices.insert(std::make_pair(device->GetId(), std::move(device))); + assert(result.second); } int32 CUsbd::RegisterLld(uint32 lldOpsPtr) @@ -146,10 +106,15 @@ int32 CUsbd::RegisterLld(uint32 lldOpsPtr) auto lldOps = reinterpret_cast(m_ram + lldOpsPtr); const char* name = reinterpret_cast(m_ram + lldOps->namePtr); - if(!strcmp(name, "buzzer")) + for(const auto& devicePair : m_devices) { - m_descriptorMemPtr = m_bios.GetSysmem()->AllocateMemory(0x80, 0, 0); - m_bios.TriggerCallback(lldOps->connectFctPtr, g_deviceId); + auto& device = devicePair.second; + if(!strcmp(name, device->GetLldName())) + { + device->OnLldRegistered(); + m_activeDeviceIds.push_back(device->GetId()); + m_bios.TriggerCallback(lldOps->connectFctPtr, device->GetId()); + } } return 0; } @@ -159,82 +124,56 @@ int32 CUsbd::ScanStaticDescriptor(uint32 deviceId, uint32 descriptorPtr, uint32 CLog::GetInstance().Print(LOG_NAME, FUNCTION_SCANSTATICDESCRIPTOR "(deviceId = 0x%08X, descriptorPtr = 0x%08X, descriptorType = %d);\r\n", deviceId, descriptorPtr, descriptorType); - assert(deviceId == g_deviceId); - - uint32 result = 0; - switch(descriptorType) - { - case Usb::DESCRIPTOR_TYPE_DEVICE: + auto deviceIteratorPair = m_devices.find(deviceId); + if(deviceIteratorPair != std::end(m_devices)) { - auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); - descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_DEVICE; - result = m_descriptorMemPtr; + auto& device = deviceIteratorPair->second; + return device->ScanStaticDescriptor(deviceId, descriptorPtr, descriptorType); } - break; - case Usb::DESCRIPTOR_TYPE_CONFIGURATION: - { - auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); - descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_CONFIGURATION; - descriptor->numInterfaces = 1; - result = m_descriptorMemPtr; - } - break; - case Usb::DESCRIPTOR_TYPE_INTERFACE: - { - auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); - descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_INTERFACE; - descriptor->numEndpoints = 1; - result = m_descriptorMemPtr; - } - break; - case Usb::DESCRIPTOR_TYPE_ENDPOINT: + else { - auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); - if(descriptor->base.descriptorType != Usb::DESCRIPTOR_TYPE_ENDPOINT) - { - descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_ENDPOINT; - descriptor->endpointAddress = 0x80; - descriptor->attributes = 3; //Interrupt transfer type - result = m_descriptorMemPtr; - } - } - break; + CLog::GetInstance().Warn(LOG_NAME, FUNCTION_SCANSTATICDESCRIPTOR " called on unknown device id 0x%08X.\r\n", deviceId); + return 0; } - - return result; } int32 CUsbd::OpenPipe(uint32 deviceId, uint32 descriptorPtr) { - CLog::GetInstance().Warn(LOG_NAME, FUNCTION_OPENPIPE "(deviceId = 0x%08X, descriptorPtr = 0x%08X);\r\n", - deviceId, descriptorPtr); - if(descriptorPtr != 0) + 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)) { - return g_pipeId; + auto& device = deviceIteratorPair->second; + uint16 pipeId = device->OpenPipe(deviceId, descriptorPtr); + assert(pipeId < 0x8000); + return (static_cast(pipeId) << 16) | deviceId; } else { - return g_controlPipeId; + CLog::GetInstance().Warn(LOG_NAME, FUNCTION_OPENPIPE " called on unknown device id 0x%08X.\r\n", deviceId); + return -1; } } int32 CUsbd::TransferPipe(uint32 pipeId, uint32 bufferPtr, uint32 size, uint32 optionPtr, uint32 doneCb, uint32 arg) { - CLog::GetInstance().Warn(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); - if(pipeId == g_controlPipeId) + 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)) { - m_bios.TriggerCallback(doneCb, 0, size, arg); + auto& device = deviceIteratorPair->second; + return device->TransferPipe(pipeId, bufferPtr, size, optionPtr, doneCb, arg); } else { - m_transferBufferPtr = bufferPtr; - m_transferSize = size; - m_transferCb = doneCb; - m_transferCbArg = arg; - m_nextTransferTicks = 33000000; + CLog::GetInstance().Warn(LOG_NAME, FUNCTION_TRANSFERPIPE " called on unknown device id 0x%08X.\r\n", deviceId); + return -1; } - return 0; } int32 CUsbd::GetDeviceLocation(uint32 deviceId, uint32 locationPtr) @@ -242,8 +181,7 @@ 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(m_ram + locationPtr); + auto location = reinterpret_cast(m_ram + locationPtr); memset(location, 0, 7); location[0] = 1; diff --git a/Source/iop/Iop_Usbd.h b/Source/iop/Iop_Usbd.h index 5bf76c8207..6af88c6271 100644 --- a/Source/iop/Iop_Usbd.h +++ b/Source/iop/Iop_Usbd.h @@ -1,13 +1,13 @@ #pragma once #include "Iop_Module.h" -#include "PadInterface.h" +#include "UsbDevice.h" class CIopBios; namespace Iop { - class CUsbd : public CModule, public CPadInterface + class CUsbd : public CModule { public: CUsbd(CIopBios&, uint8*); @@ -19,10 +19,19 @@ namespace Iop void CountTicks(uint32); - //CPadInterface - void SetButtonState(unsigned int, PS2::CControllerInfo::BUTTON, bool, uint8*); - void SetAxisState(unsigned int, PS2::CControllerInfo::BUTTON, uint8, uint8*) override{}; - void GetVibration(unsigned int, uint8& largeMotor, uint8& smallMotor) override{}; + template + DeviceType* GetDevice() + { + auto& devicePairIterator = m_devices.find(DeviceType::DEVICE_ID); + if(devicePairIterator == std::end(m_devices)) + { + return nullptr; + } + else + { + return static_cast(devicePairIterator->second.get()); + } + } private: struct LLDOPS @@ -37,6 +46,8 @@ namespace Iop uint32 gp; }; + void RegisterDevice(UsbDevicePtr); + int32 RegisterLld(uint32); int32 ScanStaticDescriptor(uint32, uint32, uint32); int32 OpenPipe(uint32, uint32); @@ -45,13 +56,8 @@ namespace Iop CIopBios& m_bios; uint8* m_ram = nullptr; - uint32 m_descriptorMemPtr = 0; - int32 m_nextTransferTicks = 0; - uint32 m_transferBufferPtr = 0; - uint32 m_transferSize = 0; - uint32 m_transferCb = 0; - uint32 m_transferCbArg = 0; - uint8 m_buttonState = 0; + std::unordered_map m_devices; + std::vector m_activeDeviceIds; }; typedef std::shared_ptr UsbdPtr; diff --git a/Source/iop/UsbBuzzerDevice.cpp b/Source/iop/UsbBuzzerDevice.cpp new file mode 100644 index 0000000000..ffc718a510 --- /dev/null +++ b/Source/iop/UsbBuzzerDevice.cpp @@ -0,0 +1,171 @@ +#include "UsbBuzzerDevice.h" +#include "UsbDefs.h" +#include "IopBios.h" +#include "PadHandler.h" +#include "Ps2Const.h" + +using namespace Iop; + +CBuzzerUsbDevice::CBuzzerUsbDevice(CIopBios& bios, uint8* ram) + : m_bios(bios) + , m_ram(ram) +{ +} + +void CBuzzerUsbDevice::SetPadHandler(CPadHandler* padHandler) +{ + m_padHandler = padHandler; +} + +uint16 CBuzzerUsbDevice::GetId() const +{ + return DEVICE_ID; +} + +const char* CBuzzerUsbDevice::GetLldName() const +{ + return "buzzer"; +} + +void CBuzzerUsbDevice::CountTicks(uint32 ticks) +{ + if(m_nextTransferTicks != 0) + { + m_nextTransferTicks -= ticks; + if(m_nextTransferTicks <= 0) + { + uint8* buffer = m_ram + m_transferBufferPtr; + buffer[0] = 0x7F; + buffer[1] = 0x7F; + buffer[2] = m_buttonState; + buffer[3] = 0x00; + buffer[4] = 0xF0; + m_bios.TriggerCallback(m_transferCb, 0, m_transferSize, m_transferCbArg); + m_nextTransferTicks = 0; + m_transferCb = 0; + } + } +} + +void CBuzzerUsbDevice::SetButtonState(unsigned int padNumber, PS2::CControllerInfo::BUTTON button, bool pressed, uint8* ram) +{ + if(padNumber == 0) + { + //Reference for data transfer: + //https://gist.github.com/Lewiscowles1986/eef220dac6f0549e4702393a7b9351f6 + uint8 mask = 0; + switch(button) + { + case PS2::CControllerInfo::CROSS: + mask = 1; //Red + break; + case PS2::CControllerInfo::CIRCLE: + mask = 2; //Yellow + break; + case PS2::CControllerInfo::SQUARE: + mask = 4; //Green + break; + case PS2::CControllerInfo::TRIANGLE: + mask = 8; //Orange + break; + case PS2::CControllerInfo::DPAD_UP: + mask = 0x10; //Blue + break; + } + if(mask != 0) + { + m_buttonState &= ~mask; + if(pressed) m_buttonState |= mask; + } + } +} + +void CBuzzerUsbDevice::OnLldRegistered() +{ + m_descriptorMemPtr = m_bios.GetSysmem()->AllocateMemory(0x80, 0, 0); + m_padHandler->InsertListener(this); +} + +uint32 CBuzzerUsbDevice::ScanStaticDescriptor(uint32 deviceId, uint32 descriptorPtr, uint32 descriptorType) +{ + assert(deviceId == DEVICE_ID); + uint32 result = 0; + switch(descriptorType) + { + case Usb::DESCRIPTOR_TYPE_DEVICE: + { + auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); + descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_DEVICE; + result = m_descriptorMemPtr; + } + break; + case Usb::DESCRIPTOR_TYPE_CONFIGURATION: + { + auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); + descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_CONFIGURATION; + descriptor->numInterfaces = 1; + result = m_descriptorMemPtr; + } + break; + case Usb::DESCRIPTOR_TYPE_INTERFACE: + { + auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); + descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_INTERFACE; + descriptor->numEndpoints = 1; + result = m_descriptorMemPtr; + } + break; + case Usb::DESCRIPTOR_TYPE_ENDPOINT: + { + auto descriptor = reinterpret_cast(m_ram + m_descriptorMemPtr); + if(descriptor->base.descriptorType != Usb::DESCRIPTOR_TYPE_ENDPOINT) + { + descriptor->base.descriptorType = Usb::DESCRIPTOR_TYPE_ENDPOINT; + descriptor->endpointAddress = 0x80; + descriptor->attributes = 3; //Interrupt transfer type + result = m_descriptorMemPtr; + } + } + break; + } + return result; +} + +int32 CBuzzerUsbDevice::OpenPipe(uint32 deviceId, uint32 descriptorPtr) +{ + assert(deviceId == DEVICE_ID); + if(descriptorPtr != 0) + { + assert(descriptorPtr == m_descriptorMemPtr); + return PIPE_ID; + } + else + { + return CONTROL_PIPE_ID; + } +} + +int32 CBuzzerUsbDevice::TransferPipe(uint32 pipeId, uint32 bufferPtr, uint32 size, uint32 optionPtr, uint32 doneCb, uint32 arg) +{ + uint16 deviceId = (pipeId & 0xFFFF); + uint16 internalPipeId = (pipeId >> 16) & 0xFFF; + assert(deviceId == DEVICE_ID); + switch(internalPipeId) + { + case CONTROL_PIPE_ID: + m_bios.TriggerCallback(doneCb, 0, size, arg); + return 0; + break; + case PIPE_ID: + //Interrupt transfer + m_transferBufferPtr = bufferPtr; + m_transferSize = size; + m_transferCb = doneCb; + m_transferCbArg = arg; + m_nextTransferTicks = PS2::IOP_CLOCK_OVER_FREQ / 60; + return 0; + default: + assert(false); + return -1; + } +} diff --git a/Source/iop/UsbBuzzerDevice.h b/Source/iop/UsbBuzzerDevice.h new file mode 100644 index 0000000000..a78b47cbed --- /dev/null +++ b/Source/iop/UsbBuzzerDevice.h @@ -0,0 +1,54 @@ +#pragma once + +#include "UsbDevice.h" +#include "PadInterface.h" + +class CIopBios; +class CPadHandler; + +namespace Iop +{ + class CBuzzerUsbDevice : public CUsbDevice, public CPadInterface + { + public: + enum + { + DEVICE_ID = 0xBEEF, + CONTROL_PIPE_ID = 0x123, + PIPE_ID = 0x456, + }; + + CBuzzerUsbDevice(CIopBios&, uint8*); + + void SetPadHandler(CPadHandler*); + + uint16 GetId() const override; + const char* GetLldName() const override; + + void CountTicks(uint32) override; + + void OnLldRegistered() override; + uint32 ScanStaticDescriptor(uint32, uint32, uint32) override; + int32 OpenPipe(uint32, uint32) override; + int32 TransferPipe(uint32, uint32, uint32, uint32, uint32, uint32) override; + + //CPadInterface + void SetButtonState(unsigned int, PS2::CControllerInfo::BUTTON, bool, uint8*); + void SetAxisState(unsigned int, PS2::CControllerInfo::BUTTON, uint8, uint8*) override{}; + void GetVibration(unsigned int, uint8& largeMotor, uint8& smallMotor) override{}; + + private: + CIopBios& m_bios; + uint8* m_ram = nullptr; + + CPadHandler* m_padHandler = nullptr; + + uint8 m_buttonState = 0; + uint32 m_descriptorMemPtr = 0; + int32 m_nextTransferTicks = 0; + uint32 m_transferBufferPtr = 0; + uint32 m_transferSize = 0; + uint32 m_transferCb = 0; + uint32 m_transferCbArg = 0; + }; +} diff --git a/Source/iop/UsbDevice.h b/Source/iop/UsbDevice.h new file mode 100644 index 0000000000..4d72543bf7 --- /dev/null +++ b/Source/iop/UsbDevice.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Types.h" +#include + +namespace Iop +{ + class CUsbDevice + { + public: + virtual ~CUsbDevice() = default; + + virtual uint16 GetId() const = 0; + virtual const char* GetLldName() const = 0; + + virtual void CountTicks(uint32) = 0; + + virtual void OnLldRegistered() = 0; + virtual uint32 ScanStaticDescriptor(uint32, uint32, uint32) = 0; + virtual int32 OpenPipe(uint32, uint32) = 0; + virtual int32 TransferPipe(uint32, uint32, uint32, uint32, uint32, uint32) = 0; + }; + typedef std::unique_ptr UsbDevicePtr; +}