1
0
mirror of https://github.com/cathery/sys-con.git synced 2025-03-14 01:27:37 +00:00

USB memory optimizations + progress on #3

This commit is contained in:
cathery 2019-11-04 15:32:43 +03:00
parent 3baa0ad672
commit f3d8991710
9 changed files with 96 additions and 103 deletions

View File

@ -24,6 +24,8 @@ public:
virtual Status Open() = 0;
virtual void Close() = 0;
virtual Status ControlTransfer(uint8_t bmRequestType, uint8_t bmRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, void *buffer) = 0;
virtual IUSBEndpoint *GetEndpoint(IUSBEndpoint::Direction direction, uint8_t index);
virtual InterfaceDescriptor *GetDescriptor();

View File

@ -19,9 +19,6 @@ Status Dualshock3Controller::Initialize()
if (S_FAILED(rc))
return rc;
rc = SendInitBytes();
if (S_FAILED(rc))
return rc;
return rc;
}
void Dualshock3Controller::Exit()
@ -36,52 +33,54 @@ Status Dualshock3Controller::OpenInterfaces()
if (S_FAILED(rc))
return rc;
//This will open each interface and try to acquire Xbox One controller's in and out endpoints, if it hasn't already
//Open each interface, send it a setup packet and get the endpoints if it succeeds
std::vector<std::unique_ptr<IUSBInterface>> &interfaces = m_device->GetInterfaces();
for (auto &&interface : interfaces)
{
rc = interface->Open();
if (S_FAILED(rc))
return rc;
//TODO: check for numEndpoints before trying to open them!
if (interface->GetDescriptor()->bNumEndpoints >= 2)
{
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, 1);
if (inEndpoint->GetDescriptor()->bLength != 0)
uint8_t initBytes[] = {0x42, 0x0C, 0x00, 0x00};
rc = interface->ControlTransfer(0x21, 0x09, 0x03F4, 0, 0x04, initBytes);
if (S_FAILED(rc))
return 60;
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, 0);
if (inEndpoint)
{
rc = inEndpoint->Open();
if (S_FAILED(rc))
return 5555;
return 61;
m_inPipe = inEndpoint;
}
IUSBEndpoint *outEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_OUT, 1);
if (outEndpoint->GetDescriptor()->bLength != 0)
if (outEndpoint)
{
rc = outEndpoint->Open();
if (S_FAILED(rc))
return 6666;
return 62;
m_outPipe = outEndpoint;
}
if (!m_inPipe || !m_outPipe)
return 69;
}
}
if (!m_inPipe || !m_outPipe)
return 69;
return rc;
}
void Dualshock3Controller::CloseInterfaces()
{
m_device->Reset();
//m_device->Reset();
m_device->Close();
}
Status Dualshock3Controller::GetInput()
{
return 9;
/*
uint8_t input_bytes[64];
@ -89,55 +88,11 @@ Status Dualshock3Controller::GetInput()
if (S_FAILED(rc))
return rc;
uint8_t type = input_bytes[0];
m_buttonData = *reinterpret_cast<Dualshock3ButtonData *>(input_bytes);
if (type == XBONEINPUT_BUTTON) //Button data
{
m_buttonData = *reinterpret_cast<Dualshock3ButtonData *>(input_bytes);
}
else if (type == XBONEINPUT_GUIDEBUTTON) //Guide button status
{
m_buttonData.sync = input_bytes[4];
//Xbox one S needs to be sent an ack report for guide buttons
//TODO: needs testing
if (input_bytes[1] == 0x30)
{
rc = WriteAckGuideReport(input_bytes[2]);
if (S_FAILED(rc))
return rc;
}
//TODO: add ack check and send ack report!
}
return rc;
*/
}
Status Dualshock3Controller::SendInitBytes()
{
/*
UCHAR hidCommandEnable[DS3_HID_COMMAND_ENABLE_SIZE] =
{
0x42, 0x0C, 0x00, 0x00
};
Context,
BmRequestHostToDevice,
BmRequestClass,
SetReport,
Ds3FeatureStartDevice,
0,
hidCommandEnable,
DS3_HID_COMMAND_ENABLE_SIZE
*/
uint8_t init_bytes[]{
0x05,
0x20, 0x00, 0x01, 0x00};
Status rc = m_outPipe->Write(init_bytes, sizeof(init_bytes));
return rc;
return 9;
}
float Dualshock3Controller::NormalizeTrigger(uint16_t value)

View File

@ -46,7 +46,7 @@ Status Xbox360Controller::OpenInterfaces()
if (!m_inPipe)
{
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, 0);
if (inEndpoint->GetDescriptor()->bLength != 0)
if (inEndpoint)
{
rc = inEndpoint->Open();
if (S_FAILED(rc))
@ -59,7 +59,7 @@ Status Xbox360Controller::OpenInterfaces()
if (!m_outPipe)
{
IUSBEndpoint *outEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_OUT, 0);
if (outEndpoint->GetDescriptor()->bLength != 0)
if (outEndpoint)
{
rc = outEndpoint->Open();
if (S_FAILED(rc))
@ -191,8 +191,8 @@ NormalizedButtonData Xbox360Controller::GetNormalizedButtonData()
return normalData;
}
Status Xbox360Controller::SetRumble(uint8_t strong_magnitude,uint8_t weak_magnitude)
Status Xbox360Controller::SetRumble(uint8_t strong_magnitude, uint8_t weak_magnitude)
{
uint8_t rumbleData[]{0x00,sizeof(Xbox360RumbleData), 0x00, strong_magnitude, weak_magnitude, 0x00, 0x00, 0x00};
uint8_t rumbleData[]{0x00, sizeof(Xbox360RumbleData), 0x00, strong_magnitude, weak_magnitude, 0x00, 0x00, 0x00};
return m_outPipe->Write(rumbleData, sizeof(rumbleData));
}

View File

@ -47,7 +47,7 @@ Status XboxOneController::OpenInterfaces()
if (interface->GetDescriptor()->bNumEndpoints >= 2)
{
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, 1);
if (inEndpoint->GetDescriptor()->bLength != 0)
if (inEndpoint)
{
rc = inEndpoint->Open();
if (S_FAILED(rc))
@ -57,7 +57,7 @@ Status XboxOneController::OpenInterfaces()
}
IUSBEndpoint *outEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_OUT, 1);
if (outEndpoint->GetDescriptor()->bLength != 0)
if (outEndpoint)
{
rc = outEndpoint->Open();
if (S_FAILED(rc))

View File

@ -10,6 +10,8 @@ private:
UsbHsClientIfSession m_ifSession;
usb_endpoint_descriptor m_descriptor;
void *m_buffer;
public:
//Pass the necessary information to be able to open the endpoint
SwitchUSBEndpoint(UsbHsClientIfSession &if_session, usb_endpoint_descriptor &desc);

View File

@ -11,8 +11,10 @@ private:
UsbHsClientIfSession m_session{};
UsbHsInterface m_interface{};
std::vector<std::unique_ptr<IUSBEndpoint>> m_inEndpoints;
std::vector<std::unique_ptr<IUSBEndpoint>> m_outEndpoints;
std::array<std::unique_ptr<IUSBEndpoint>, 15> m_inEndpoints;
std::array<std::unique_ptr<IUSBEndpoint>, 15> m_outEndpoints;
void *m_controlTransferBuffer;
public:
//Pass the specified interface to allow for opening the session
@ -23,6 +25,8 @@ public:
virtual Result Open();
virtual void Close();
virtual Result ControlTransfer(u8 bmRequestType, u8 bmRequest, u16 wValue, u16 wIndex, u16 wLength, void *buffer);
// There are a total of 15 endpoints on a switch interface for each direction, get them by passing the desired parameters
virtual IUSBEndpoint *GetEndpoint(IUSBEndpoint::Direction direction, uint8_t index);

View File

@ -7,10 +7,12 @@ SwitchUSBEndpoint::SwitchUSBEndpoint(UsbHsClientIfSession &if_session, usb_endpo
: m_ifSession(if_session),
m_descriptor(desc)
{
m_buffer = memalign(0x1000, 0x100);
}
SwitchUSBEndpoint::~SwitchUSBEndpoint()
{
free(m_buffer);
Close();
}
@ -30,47 +32,38 @@ void SwitchUSBEndpoint::Close()
Result SwitchUSBEndpoint::Write(void *inBuffer, size_t bufferSize)
{
Result rc = -1;
void *tmpbuf = memalign(0x1000, bufferSize);
if (tmpbuf != nullptr)
if (m_buffer != nullptr)
{
u32 transferredSize = 0;
memset(tmpbuf, 0, bufferSize);
memset(m_buffer, 0, bufferSize);
for (size_t byte = 0; byte != bufferSize; ++byte)
{
static_cast<uint8_t *>(tmpbuf)[byte] = static_cast<uint8_t *>(inBuffer)[byte];
static_cast<uint8_t *>(m_buffer)[byte] = static_cast<uint8_t *>(inBuffer)[byte];
}
rc = usbHsEpPostBuffer(&m_epSession, tmpbuf, bufferSize, &transferredSize);
if (rc == 0xcc8c)
rc = 0;
free(tmpbuf);
rc = usbHsEpPostBuffer(&m_epSession, m_buffer, bufferSize, &transferredSize);
}
return rc;
}
Result SwitchUSBEndpoint::Read(void *outBuffer, size_t bufferSize)
{
void *tmpbuf = memalign(0x1000, bufferSize);
if (tmpbuf == nullptr)
if (m_buffer == nullptr)
return -1;
u32 transferredSize;
Result rc = usbHsEpPostBuffer(&m_epSession, tmpbuf, bufferSize, &transferredSize);
memset(m_buffer, 0, bufferSize);
if (rc == 0xcc8c)
rc = 0;
Result rc = usbHsEpPostBuffer(&m_epSession, m_buffer, bufferSize, &transferredSize);
if (R_SUCCEEDED(rc))
{
for (size_t byte = 0; byte != bufferSize; ++byte)
for (u32 byte = 0; byte != transferredSize; ++byte)
{
static_cast<uint8_t *>(outBuffer)[byte] = static_cast<uint8_t *>(tmpbuf)[byte];
static_cast<uint8_t *>(outBuffer)[byte] = static_cast<uint8_t *>(m_buffer)[byte];
}
}
free(tmpbuf);
return rc;
}

View File

@ -1,13 +1,17 @@
#include "SwitchUSBInterface.h"
#include "SwitchUSBEndpoint.h"
#include <malloc.h>
#include <cstring>
SwitchUSBInterface::SwitchUSBInterface(UsbHsInterface &interface)
: m_interface(interface)
{
m_controlTransferBuffer = memalign(0x1000, 0x100);
}
SwitchUSBInterface::~SwitchUSBInterface()
{
free(m_controlTransferBuffer);
Close();
}
@ -23,22 +27,22 @@ Result SwitchUSBInterface::Open()
if (R_SUCCEEDED(rc))
{
m_inEndpoints.clear();
m_outEndpoints.clear();
m_inEndpoints.reserve(15);
m_outEndpoints.reserve(15);
//For some reason output_endpoint_descs contains IN endpoints and input_endpoint_descs contains OUT endpoints
//we're adjusting appropriately
for (int i = 0; i != 15; ++i)
{
m_inEndpoints.push_back(std::make_unique<SwitchUSBEndpoint>(m_session, m_session.inf.inf.input_endpoint_descs[i]));
usb_endpoint_descriptor &epdesc = m_session.inf.inf.input_endpoint_descs[i];
if (epdesc.bLength != 0)
{
m_inEndpoints[i] = std::make_unique<SwitchUSBEndpoint>(m_session, epdesc);
}
}
for (int i = 0; i != 15; ++i)
{
m_outEndpoints.push_back(std::make_unique<SwitchUSBEndpoint>(m_session, m_session.inf.inf.output_endpoint_descs[i]));
usb_endpoint_descriptor &epdesc = m_session.inf.inf.output_endpoint_descs[i];
if (epdesc.bLength != 0)
{
m_outEndpoints[i] = std::make_unique<SwitchUSBEndpoint>(m_session, epdesc);
}
}
}
return rc;
@ -47,18 +51,50 @@ void SwitchUSBInterface::Close()
{
for (auto &&endpoint : m_inEndpoints)
{
endpoint->Close();
if (endpoint)
{
endpoint->Close();
endpoint.release();
}
}
for (auto &&endpoint : m_outEndpoints)
{
endpoint->Close();
if (endpoint)
{
endpoint->Close();
endpoint.release();
}
}
usbHsIfClose(&m_session);
}
Result SwitchUSBInterface::ControlTransfer(u8 bmRequestType, u8 bmRequest, u16 wValue, u16 wIndex, u16 wLength, void *buffer)
{
if (m_controlTransferBuffer == nullptr)
return -1;
u32 transferredSize;
for (u16 byte = 0; byte != wLength; ++byte)
{
static_cast<uint8_t *>(m_controlTransferBuffer)[byte] = static_cast<uint8_t *>(buffer)[byte];
}
Result rc = usbHsIfCtrlXfer(&m_session, bmRequestType, bmRequest, wValue, wIndex, wLength, m_controlTransferBuffer, &transferredSize);
if (R_SUCCEEDED(rc))
{
memset(buffer, 0, wLength);
for (u32 byte = 0; byte != transferredSize; ++byte)
{
static_cast<uint8_t *>(buffer)[byte] = static_cast<uint8_t *>(m_controlTransferBuffer)[byte];
}
}
return rc;
}
IUSBEndpoint *SwitchUSBInterface::GetEndpoint(IUSBEndpoint::Direction direction, uint8_t index)
{
//TODO: replace this with a control transfer to get endpoint descriptor
if (direction == IUSBEndpoint::USB_ENDPOINT_IN)
return m_inEndpoints[index].get();
else

View File

@ -15,7 +15,7 @@ struct VendorEvent
Result mainLoop()
{
Result rc;
Result rc = 0;
UsbHsInterface interfaces[16];
s32 total_entries;
std::vector<uint16_t> vendors = GetVendors();
@ -120,7 +120,8 @@ Result mainLoop()
}
UsbHsInterfaceFilter tempFilter;
tempFilter.Flags = UsbHsInterfaceFilterFlags_idProduct;
tempFilter.Flags = UsbHsInterfaceFilterFlags_idVendor | UsbHsInterfaceFilterFlags_idProduct;
tempFilter.idVendor = event.vendor;
tempFilter.idProduct = product;
rc = usbHsQueryAvailableInterfaces(&tempFilter, interfaces, sizeof(interfaces), &total_entries);