diff --git a/ControllerUSB/include/IUSBInterface.h b/ControllerUSB/include/IUSBInterface.h index 119391d..66464a6 100644 --- a/ControllerUSB/include/IUSBInterface.h +++ b/ControllerUSB/include/IUSBInterface.h @@ -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(); diff --git a/ControllerUSB/source/Controllers/Dualshock3Controller.cpp b/ControllerUSB/source/Controllers/Dualshock3Controller.cpp index e5d8ccd..6bea656 100644 --- a/ControllerUSB/source/Controllers/Dualshock3Controller.cpp +++ b/ControllerUSB/source/Controllers/Dualshock3Controller.cpp @@ -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> &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(input_bytes); - if (type == XBONEINPUT_BUTTON) //Button data - { - m_buttonData = *reinterpret_cast(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) diff --git a/ControllerUSB/source/Controllers/Xbox360Controller.cpp b/ControllerUSB/source/Controllers/Xbox360Controller.cpp index 28ca5b1..01b796e 100644 --- a/ControllerUSB/source/Controllers/Xbox360Controller.cpp +++ b/ControllerUSB/source/Controllers/Xbox360Controller.cpp @@ -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)); } \ No newline at end of file diff --git a/ControllerUSB/source/Controllers/XboxOneController.cpp b/ControllerUSB/source/Controllers/XboxOneController.cpp index ab1c554..f3c2640 100644 --- a/ControllerUSB/source/Controllers/XboxOneController.cpp +++ b/ControllerUSB/source/Controllers/XboxOneController.cpp @@ -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)) diff --git a/SwitchUSB/include/SwitchUSBEndpoint.h b/SwitchUSB/include/SwitchUSBEndpoint.h index 1a6dfd3..62a949c 100644 --- a/SwitchUSB/include/SwitchUSBEndpoint.h +++ b/SwitchUSB/include/SwitchUSBEndpoint.h @@ -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); diff --git a/SwitchUSB/include/SwitchUSBInterface.h b/SwitchUSB/include/SwitchUSBInterface.h index dd32e88..d50f811 100644 --- a/SwitchUSB/include/SwitchUSBInterface.h +++ b/SwitchUSB/include/SwitchUSBInterface.h @@ -11,8 +11,10 @@ private: UsbHsClientIfSession m_session{}; UsbHsInterface m_interface{}; - std::vector> m_inEndpoints; - std::vector> m_outEndpoints; + std::array, 15> m_inEndpoints; + std::array, 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); diff --git a/SwitchUSB/source/SwitchUSBEndpoint.cpp b/SwitchUSB/source/SwitchUSBEndpoint.cpp index b4de61a..6ca87e9 100644 --- a/SwitchUSB/source/SwitchUSBEndpoint.cpp +++ b/SwitchUSB/source/SwitchUSBEndpoint.cpp @@ -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(tmpbuf)[byte] = static_cast(inBuffer)[byte]; + static_cast(m_buffer)[byte] = static_cast(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(outBuffer)[byte] = static_cast(tmpbuf)[byte]; + static_cast(outBuffer)[byte] = static_cast(m_buffer)[byte]; } } - - free(tmpbuf); return rc; } diff --git a/SwitchUSB/source/SwitchUSBInterface.cpp b/SwitchUSB/source/SwitchUSBInterface.cpp index 4b0868b..1e72690 100644 --- a/SwitchUSB/source/SwitchUSBInterface.cpp +++ b/SwitchUSB/source/SwitchUSBInterface.cpp @@ -1,13 +1,17 @@ #include "SwitchUSBInterface.h" #include "SwitchUSBEndpoint.h" +#include +#include 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(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(m_session, epdesc); + } } for (int i = 0; i != 15; ++i) { - m_outEndpoints.push_back(std::make_unique(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(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(m_controlTransferBuffer)[byte] = static_cast(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(buffer)[byte] = static_cast(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 diff --git a/source/mainLoop.cpp b/source/mainLoop.cpp index fd3115f..904040c 100644 --- a/source/mainLoop.cpp +++ b/source/mainLoop.cpp @@ -15,7 +15,7 @@ struct VendorEvent Result mainLoop() { - Result rc; + Result rc = 0; UsbHsInterface interfaces[16]; s32 total_entries; std::vector 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);