Update TinyUSB to latest / Xbox One Auth fix (#1002)
* Update tinyusb to latest * TinyUSB update to latest (removed hack for get_report) * Moving a single shared 1024 byte auth buffer to a queue system in-case of race condition (which seemed to be happening) * Fixed a legit bug with Xbox One authentication. .init, .reset, and .open are called multiple times during USB discovery initial announcement code was moved from .init to .open AFTER the xbox one interface type is declared. Also moved shared buffers to more sane areas and used two instead of one buffer for sharing. * Update xgip_protocol.h Extra spaces
This commit is contained in:
@@ -110,9 +110,9 @@ private:
|
||||
bool chunkEnded; // did we hit the end of the chunk successfully?
|
||||
uint8_t packet[64]; // for output packets
|
||||
uint16_t packetLength; // LAST SENT packet length
|
||||
uint8_t * data; // Total data in this packet
|
||||
uint8_t data[1024]; // Total data in this packet
|
||||
uint16_t dataLength; // actual length of data
|
||||
bool isValidPacket; // is this a valid packet or did we get an error?
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ TU_ATTR_WEAK void tuh_xinput_report_sent_cb(uint8_t dev_addr, uint8_t instance,
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void xinputh_init(void);
|
||||
bool xinputh_init(void);
|
||||
bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len);
|
||||
bool xinputh_set_config(uint8_t dev_addr, uint8_t itf_num);
|
||||
bool xinputh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
|
||||
@@ -12,6 +12,44 @@ typedef enum {
|
||||
wait_auth_dongle_to_console = 4,
|
||||
} XboxOneState;
|
||||
|
||||
class XBOneAuthBuffer {
|
||||
public:
|
||||
XBOneAuthBuffer() {
|
||||
data = nullptr;
|
||||
sequence = 0;
|
||||
length = 0;
|
||||
type = 0;
|
||||
}
|
||||
~XBOneAuthBuffer(){
|
||||
if ( data != nullptr ) {
|
||||
delete [] data;
|
||||
}
|
||||
}
|
||||
|
||||
void setBuffer(uint8_t * inData, uint16_t inLen, uint8_t inSeq, uint8_t inType) {
|
||||
data = new uint8_t[inLen];
|
||||
length = inLen;
|
||||
sequence = inSeq;
|
||||
type = inType;
|
||||
memcpy(data, inData, inLen);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if ( data != nullptr ) {
|
||||
delete [] data;
|
||||
}
|
||||
data = nullptr;
|
||||
sequence = 0;
|
||||
length = 0;
|
||||
type = 0;
|
||||
}
|
||||
|
||||
uint8_t * data;
|
||||
uint8_t sequence;
|
||||
uint16_t length;
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
XboxOneState xboneState;
|
||||
|
||||
@@ -19,11 +57,9 @@ typedef struct {
|
||||
// Note: the Xbox One Passthrough can call send_xbone_report() directly but not the other way around
|
||||
bool authCompleted;
|
||||
|
||||
// Auth Buffer
|
||||
uint8_t authBuffer[1024];
|
||||
uint8_t authSequence;
|
||||
uint16_t authLen;
|
||||
uint8_t authType;
|
||||
// Auth Buffer Queue
|
||||
XBOneAuthBuffer consoleBuffer;
|
||||
XBOneAuthBuffer dongleBuffer;
|
||||
} XboxOneAuthData;
|
||||
|
||||
class XBOneAuth : public GPAuthDriver {
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
bool getAuthSent();
|
||||
private:
|
||||
virtual void update();
|
||||
void process_report_queue(uint32_t now);
|
||||
bool send_xbone_usb(uint8_t const *buffer, uint16_t bufsize);
|
||||
void set_ack_wait();
|
||||
uint8_t last_report[CFG_TUD_ENDPOINT0_SIZE] = { };
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
// USB Host manager decides on TinyUSB Host driver
|
||||
usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t *driver_count);
|
||||
|
||||
// Missing TinyUSB call
|
||||
bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len);
|
||||
|
||||
class USBHostManager {
|
||||
public:
|
||||
USBHostManager(USBHostManager const&) = delete;
|
||||
|
||||
Submodule lib/tinyusb updated: 9474db8b0f...a435befcde
@@ -28,15 +28,11 @@
|
||||
|
||||
// Default Constructor
|
||||
XGIPProtocol::XGIPProtocol() {
|
||||
data = nullptr;
|
||||
reset();
|
||||
}
|
||||
|
||||
// Default Destructor
|
||||
XGIPProtocol::~XGIPProtocol() {
|
||||
if ( data != nullptr ) {
|
||||
delete [] data;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset packet information
|
||||
@@ -50,10 +46,7 @@ void XGIPProtocol::reset() {
|
||||
numberOfChunksSent = 0; // How many actual chunks have we sent?
|
||||
chunkEnded = false; // Are we at the end of the chunk?
|
||||
isValidPacket = false; // Is this a valid packet?
|
||||
if ( data != nullptr ) { // Delete our data if its not null
|
||||
delete [] data;
|
||||
}
|
||||
data = nullptr;
|
||||
memset(data, 0, 1024);
|
||||
dataLength = 0; // Set data length to 0
|
||||
memset(packet, 0, sizeof(packet)); // Set our packet to 0
|
||||
packetLength = 0; // Set packet length to 0
|
||||
@@ -116,12 +109,8 @@ bool XGIPProtocol::parse(const uint8_t * buffer, uint16_t len) {
|
||||
dataLength = dataLength - ((dataLength / 0x100)*0x80);
|
||||
}
|
||||
|
||||
// Ensure we clear data if its set to something else
|
||||
if ( data != nullptr )
|
||||
delete [] data;
|
||||
data = new uint8_t[dataLength];
|
||||
actualDataReceived = 0; // haven't received anything yet
|
||||
totalChunkReceived = header.length; //
|
||||
// Set our chunk received to the header length
|
||||
totalChunkReceived = header.length;
|
||||
} else {
|
||||
totalChunkReceived += header.length; // not actual data length, but chunk value
|
||||
}
|
||||
@@ -137,9 +126,6 @@ bool XGIPProtocol::parse(const uint8_t * buffer, uint16_t len) {
|
||||
reset();
|
||||
memcpy((void*)&header, buffer, sizeof(GipHeader_t));
|
||||
if ( header.length > 0 ) {
|
||||
if (data != nullptr)
|
||||
delete [] data;
|
||||
data = new uint8_t[header.length];
|
||||
memcpy(data, &buffer[4], header.length); // copy incoming data
|
||||
}
|
||||
actualDataReceived = header.length;
|
||||
@@ -177,9 +163,6 @@ bool XGIPProtocol::setData(const uint8_t * buffer, uint16_t len) {
|
||||
if ( len > 0x3000) { // arbitrary but this should cover us if something bad happens
|
||||
return false;
|
||||
}
|
||||
if ( data != nullptr )
|
||||
delete [] data;
|
||||
data = new uint8_t[len];
|
||||
memcpy(data, buffer, len);
|
||||
dataLength = len;
|
||||
return true;
|
||||
|
||||
@@ -150,8 +150,9 @@ bool tuh_xinput_ready(uint8_t dev_addr, uint8_t instance) {
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH API
|
||||
//--------------------------------------------------------------------+
|
||||
void xinputh_init(void) {
|
||||
bool xinputh_init(void) {
|
||||
tu_memclr(_xinputh_dev, sizeof(_xinputh_dev));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool xinputh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
|
||||
|
||||
@@ -15,8 +15,6 @@ void XBOneAuth::initialize() {
|
||||
if ( available() ) {
|
||||
listener = new XBOneAuthUSBListener();
|
||||
xboxOneAuthData.xboneState = auth_idle_state;
|
||||
xboxOneAuthData.authLen = 0;
|
||||
xboxOneAuthData.authSequence = 0;
|
||||
xboxOneAuthData.authCompleted = false;
|
||||
((XBOneAuthUSBListener*)listener)->setup();
|
||||
((XBOneAuthUSBListener*)listener)->setAuthData(&xboxOneAuthData);
|
||||
|
||||
@@ -24,7 +24,7 @@ typedef struct {
|
||||
} report_queue_t;
|
||||
|
||||
static std::queue<report_queue_t> report_queue;
|
||||
static uint32_t lastReportQueueSent = 0;
|
||||
static uint32_t lastReportQueue = 0;
|
||||
#define REPORT_QUEUE_INTERVAL 15
|
||||
|
||||
void XBOneAuthUSBListener::setup() {
|
||||
@@ -38,27 +38,36 @@ void XBOneAuthUSBListener::setAuthData(XboxOneAuthData * authData ) {
|
||||
}
|
||||
|
||||
void XBOneAuthUSBListener::process() {
|
||||
if ( mounted == false || xboxOneAuthData == nullptr) // do nothing if we have not mounted an xbox one dongle
|
||||
// Process the report queue
|
||||
process_report_queue();
|
||||
|
||||
// Do nothing if auth data or dongle are not ready
|
||||
if ( xboxOneAuthData == nullptr || dongle_ready == false) // do nothing if we have not mounted an xbox one dongle
|
||||
return;
|
||||
|
||||
// Do not begin processing console auth unless we have the dongle ready
|
||||
if ( dongle_ready == true ) {
|
||||
if ( xboxOneAuthData->xboneState == XboxOneState::send_auth_console_to_dongle ) {
|
||||
uint8_t isChunked = ( xboxOneAuthData->authLen > GIP_MAX_CHUNK_SIZE );
|
||||
uint8_t needsAck = (xboxOneAuthData->authLen > 2);
|
||||
outgoingXGIP.reset();
|
||||
outgoingXGIP.setAttributes(xboxOneAuthData->authType, xboxOneAuthData->authSequence, 1, isChunked, needsAck);
|
||||
outgoingXGIP.setData(xboxOneAuthData->authBuffer, xboxOneAuthData->authLen);
|
||||
xboxOneAuthData->xboneState = XboxOneState::wait_auth_console_to_dongle;
|
||||
} else if ( xboxOneAuthData->xboneState == XboxOneState::wait_auth_console_to_dongle) {
|
||||
queue_host_report(outgoingXGIP.generatePacket(), outgoingXGIP.getPacketLength());
|
||||
if ( outgoingXGIP.getChunked() == false || outgoingXGIP.endOfChunk() == true ) {
|
||||
xboxOneAuthData->xboneState = XboxOneState::auth_idle_state;
|
||||
}
|
||||
}
|
||||
// Received a packet from the console (or Windows) to dongle
|
||||
if ( xboxOneAuthData->xboneState == XboxOneState::send_auth_console_to_dongle ) {
|
||||
uint8_t * buffer = xboxOneAuthData->consoleBuffer.data;
|
||||
uint8_t type = xboxOneAuthData->consoleBuffer.type;
|
||||
uint16_t len = xboxOneAuthData->consoleBuffer.length;
|
||||
uint8_t sequence = xboxOneAuthData->consoleBuffer.sequence;
|
||||
uint8_t isChunked = ( len > GIP_MAX_CHUNK_SIZE );
|
||||
uint8_t needsAck = (len > 2);
|
||||
outgoingXGIP.reset();
|
||||
outgoingXGIP.setAttributes(type, sequence, 1, isChunked, needsAck);
|
||||
outgoingXGIP.setData(buffer, len);
|
||||
xboxOneAuthData->consoleBuffer.reset();
|
||||
xboxOneAuthData->xboneState = XboxOneState::wait_auth_console_to_dongle;
|
||||
}
|
||||
|
||||
process_report_queue();
|
||||
// Process waiting (always on first frame)
|
||||
if ( xboxOneAuthData->xboneState == XboxOneState::wait_auth_console_to_dongle) {
|
||||
queue_host_report(outgoingXGIP.generatePacket(), outgoingXGIP.getPacketLength());
|
||||
if ( outgoingXGIP.getChunked() == false ||
|
||||
(outgoingXGIP.getChunked() == true && outgoingXGIP.endOfChunk() == true) ) {
|
||||
xboxOneAuthData->xboneState = XboxOneState::auth_idle_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XBOneAuthUSBListener::xmount(uint8_t dev_addr, uint8_t instance, uint8_t controllerType, uint8_t subtype) {
|
||||
@@ -74,11 +83,16 @@ void XBOneAuthUSBListener::xmount(uint8_t dev_addr, uint8_t instance, uint8_t co
|
||||
void XBOneAuthUSBListener::unmount(uint8_t dev_addr) {
|
||||
// Do not reset dongle_ready on unmount (Magic-X will remount but still be ready)
|
||||
mounted = false;
|
||||
incomingXGIP.reset();
|
||||
outgoingXGIP.reset();
|
||||
dongle_ready = false; // not ready for auth if we unmounted
|
||||
xboxOneAuthData->xboneState = XboxOneState::auth_idle_state;
|
||||
}
|
||||
|
||||
void XBOneAuthUSBListener::report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
|
||||
if ( mounted == false || xboxOneAuthData == nullptr)
|
||||
if ( mounted == false || xboxOneAuthData == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
incomingXGIP.parse(report, len);
|
||||
if ( incomingXGIP.validate() == false ) {
|
||||
@@ -104,26 +118,28 @@ void XBOneAuthUSBListener::report_received(uint8_t dev_addr, uint8_t instance, u
|
||||
outgoingXGIP.setAttributes(GIP_POWER_MODE_DEVICE_CONFIG, 2, 1, false, 0);
|
||||
outgoingXGIP.setData(xb1_power_on, sizeof(xb1_power_on));
|
||||
queue_host_report((uint8_t*)outgoingXGIP.generatePacket(), outgoingXGIP.getPacketLength());
|
||||
|
||||
outgoingXGIP.reset(); // Power-on with 0x00
|
||||
outgoingXGIP.setAttributes(GIP_POWER_MODE_DEVICE_CONFIG, 3, 1, false, 0);
|
||||
outgoingXGIP.setData(xb1_power_on_single, sizeof(xb1_power_on_single));
|
||||
queue_host_report((uint8_t*)outgoingXGIP.generatePacket(), outgoingXGIP.getPacketLength());
|
||||
|
||||
outgoingXGIP.reset(); // Rumble Support to enable dongle
|
||||
outgoingXGIP.setAttributes(GIP_CMD_RUMBLE, 1, 0, false, 0); // not internal function
|
||||
outgoingXGIP.setData(xb1_rumble_on, sizeof(xb1_rumble_on));
|
||||
queue_host_report((uint8_t*)outgoingXGIP.generatePacket(), outgoingXGIP.getPacketLength());
|
||||
|
||||
// Dongle is ready!
|
||||
dongle_ready = true;
|
||||
}
|
||||
break;
|
||||
case GIP_AUTH:
|
||||
case GIP_FINAL_AUTH:
|
||||
if ( incomingXGIP.getChunked() == false ||
|
||||
(incomingXGIP.getChunked() == true && incomingXGIP.endOfChunk() == true )) {
|
||||
memcpy(xboxOneAuthData->authBuffer, incomingXGIP.getData(), incomingXGIP.getDataLength());
|
||||
xboxOneAuthData->authLen = incomingXGIP.getDataLength();
|
||||
xboxOneAuthData->authType = incomingXGIP.getCommand();
|
||||
xboxOneAuthData->authSequence = incomingXGIP.getSequence();
|
||||
xboxOneAuthData->xboneState = XboxOneState::send_auth_dongle_to_console;
|
||||
if ( incomingXGIP.getChunked() == false ||
|
||||
(incomingXGIP.getChunked() == true && incomingXGIP.endOfChunk() == true )) {
|
||||
xboxOneAuthData->dongleBuffer.setBuffer(incomingXGIP.getData(), incomingXGIP.getDataLength(),
|
||||
incomingXGIP.getSequence(), incomingXGIP.getCommand());
|
||||
xboxOneAuthData->xboneState = XboxOneState::send_auth_dongle_to_console;
|
||||
incomingXGIP.reset();
|
||||
}
|
||||
break;
|
||||
@@ -142,12 +158,10 @@ void XBOneAuthUSBListener::queue_host_report(void* report, uint16_t len) {
|
||||
|
||||
void XBOneAuthUSBListener::process_report_queue() {
|
||||
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||||
if ( !report_queue.empty() && (now - lastReportQueueSent) > REPORT_QUEUE_INTERVAL ) {
|
||||
if ( !report_queue.empty() && (now - lastReportQueue) > REPORT_QUEUE_INTERVAL ) {
|
||||
if ( tuh_xinput_send_report(xbone_dev_addr, xbone_instance, report_queue.front().report, report_queue.front().len) ) {
|
||||
report_queue.pop();
|
||||
lastReportQueueSent = now;
|
||||
} else { // FAILED: Keeping it on the queue to send again
|
||||
sleep_ms(REPORT_QUEUE_INTERVAL);
|
||||
lastReportQueue = now; // last time we checked report queue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#define DESC_EXTENDED_PROPERTIES_DESCRIPTOR 0x0005
|
||||
#define REQ_GET_XGIP_HEADER 0x90
|
||||
|
||||
// Sent report queue every 15 milliseconds
|
||||
static uint32_t lastReportQueueSent = 0;
|
||||
#define REPORT_QUEUE_INTERVAL 15
|
||||
// Check report queue every 35 milliseconds
|
||||
static uint32_t lastReportQueue = 0;
|
||||
#define REPORT_QUEUE_INTERVAL 35
|
||||
|
||||
typedef enum {
|
||||
IDLE_STATE = 0,
|
||||
@@ -150,7 +150,8 @@ static void xbone_reset(uint8_t rhport) {
|
||||
while(!report_queue.empty())
|
||||
report_queue.pop();
|
||||
|
||||
xboneDriverState = XboxOneDriverState::READY_ANNOUNCE;
|
||||
// make sure xbox driver state is doing nothing
|
||||
xboneDriverState = XboxOneDriverState::IDLE_STATE;
|
||||
|
||||
// close any endpoints that are open
|
||||
tu_memclr(&_xboned_itf, sizeof(_xboned_itf));
|
||||
@@ -160,7 +161,6 @@ static void xbone_init(void) {
|
||||
xbone_reset(TUD_OPT_RHPORT);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t xbone_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) {
|
||||
uint16_t drv_len = 0;
|
||||
if (TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) {
|
||||
@@ -197,6 +197,13 @@ static uint16_t xbone_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc
|
||||
TU_BREAKPOINT();
|
||||
}
|
||||
}
|
||||
|
||||
// Setting up XGIPs and driver state
|
||||
if (incomingXGIP != nullptr && outgoingXGIP != nullptr ) {
|
||||
xboneDriverState = XboxOneDriverState::READY_ANNOUNCE;
|
||||
incomingXGIP->reset();
|
||||
outgoingXGIP->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,14 +277,13 @@ bool xbone_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
|
||||
} else if ( command == GIP_POWER_MODE_DEVICE_CONFIG || command == GIP_CMD_WAKEUP || command == GIP_CMD_RUMBLE ) {
|
||||
xbox_one_powered_on = true;
|
||||
} else if ( command == GIP_AUTH || command == GIP_FINAL_AUTH) {
|
||||
if (incomingXGIP->getDataLength() == 2 && memcmp(incomingXGIP->getData(), authReady, sizeof(authReady))==0 )
|
||||
if (incomingXGIP->getDataLength() == 2 && memcmp(incomingXGIP->getData(), authReady, sizeof(authReady))==0 ) {
|
||||
xboxOneAuthData->authCompleted = true;
|
||||
}
|
||||
if ( (incomingXGIP->getChunked() == true && incomingXGIP->endOfChunk() == true) ||
|
||||
(incomingXGIP->getChunked() == false )) {
|
||||
memcpy(xboxOneAuthData->authBuffer, incomingXGIP->getData(), incomingXGIP->getDataLength());
|
||||
xboxOneAuthData->authLen = incomingXGIP->getDataLength();
|
||||
xboxOneAuthData->authType = incomingXGIP->getCommand();
|
||||
xboxOneAuthData->authSequence = incomingXGIP->getSequence();
|
||||
xboxOneAuthData->consoleBuffer.setBuffer(incomingXGIP->getData(), incomingXGIP->getDataLength(),
|
||||
incomingXGIP->getSequence(), incomingXGIP->getCommand());
|
||||
xboxOneAuthData->xboneState = XboxOneState::send_auth_console_to_dongle;
|
||||
incomingXGIP->reset();
|
||||
}
|
||||
@@ -585,20 +591,8 @@ void XBOneDriver::set_ack_wait() {
|
||||
void XBOneDriver::update() {
|
||||
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
if ( !report_queue.empty() ) {
|
||||
if ( (now - lastReportQueueSent) > REPORT_QUEUE_INTERVAL ) {
|
||||
report_queue_t & report_front = report_queue.front();
|
||||
uint16_t xboneReportSize = report_front.len;
|
||||
if ( send_xbone_usb(report_front.report, xboneReportSize) ) {
|
||||
lastReportQueueSent = now;
|
||||
// Set last report queue sent to our report sent by the queue
|
||||
memcpy(last_report, &report_front.report, xboneReportSize);
|
||||
report_queue.pop();
|
||||
} else {
|
||||
sleep_ms(REPORT_QUEUE_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process our report queue
|
||||
process_report_queue(now);
|
||||
|
||||
// Do not add logic until our ACK returns
|
||||
if ( waiting_ack == true ) {
|
||||
@@ -617,7 +611,7 @@ void XBOneDriver::update() {
|
||||
outgoingXGIP->setAttributes(GIP_ANNOUNCE, 1, 1, 0, 0);
|
||||
outgoingXGIP->setData(announcePacket, sizeof(announcePacket));
|
||||
queue_xbone_report(outgoingXGIP->generatePacket(), outgoingXGIP->getPacketLength());
|
||||
xboneDriverState = WAIT_DESCRIPTOR_REQUEST;
|
||||
xboneDriverState = IDLE_STATE;
|
||||
}
|
||||
break;
|
||||
case SEND_DESCRIPTOR:
|
||||
@@ -630,13 +624,22 @@ void XBOneDriver::update() {
|
||||
}
|
||||
break;
|
||||
case SETUP_AUTH:
|
||||
// Received packet from dongle to console / PC
|
||||
if ( xboxOneAuthData->xboneState == XboxOneState::send_auth_dongle_to_console ) {
|
||||
bool isChunked = (xboxOneAuthData->authLen > GIP_MAX_CHUNK_SIZE);
|
||||
uint16_t len = xboxOneAuthData->dongleBuffer.length;
|
||||
uint8_t type = xboxOneAuthData->dongleBuffer.type;
|
||||
uint8_t sequence = xboxOneAuthData->dongleBuffer.sequence;
|
||||
uint8_t * buffer = xboxOneAuthData->dongleBuffer.data;
|
||||
bool isChunked = (len > GIP_MAX_CHUNK_SIZE);
|
||||
outgoingXGIP->reset();
|
||||
outgoingXGIP->setAttributes(xboxOneAuthData->authType, xboxOneAuthData->authSequence, 1, isChunked, 1);
|
||||
outgoingXGIP->setData(xboxOneAuthData->authBuffer, xboxOneAuthData->authLen);
|
||||
outgoingXGIP->setAttributes(type, sequence, 1, isChunked, 1);
|
||||
outgoingXGIP->setData(buffer, len);
|
||||
xboxOneAuthData->xboneState = wait_auth_dongle_to_console;
|
||||
} else if ( xboxOneAuthData->xboneState == XboxOneState::wait_auth_dongle_to_console ) {
|
||||
xboxOneAuthData->dongleBuffer.reset();
|
||||
}
|
||||
|
||||
// Process auth dongle to console
|
||||
if ( xboxOneAuthData->xboneState == XboxOneState::wait_auth_dongle_to_console ) {
|
||||
queue_xbone_report(outgoingXGIP->generatePacket(), outgoingXGIP->getPacketLength());
|
||||
if ( outgoingXGIP->getChunked() == false || outgoingXGIP->endOfChunk() == true ) {
|
||||
xboxOneAuthData->xboneState = XboxOneState::auth_idle_state;
|
||||
@@ -652,6 +655,19 @@ void XBOneDriver::update() {
|
||||
};
|
||||
}
|
||||
|
||||
void XBOneDriver::process_report_queue(uint32_t now) {
|
||||
if ( !report_queue.empty() && (now - lastReportQueue) > REPORT_QUEUE_INTERVAL ) {
|
||||
if ( send_xbone_usb(report_queue.front().report, report_queue.front().len) ) {
|
||||
memcpy(last_report, &report_queue.front().report, report_queue.front().len);
|
||||
report_queue.pop();
|
||||
lastReportQueue = now;
|
||||
} else {
|
||||
// THIS IS REQUIRED FOR TIMING ON PC / CONSOLE
|
||||
sleep_ms(REPORT_QUEUE_INTERVAL); // sleep while we wait, never happens during input only auth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t XBOneDriver::GetJoystickMidValue() {
|
||||
return GAMEPAD_JOYSTICK_MID;
|
||||
}
|
||||
|
||||
@@ -249,48 +249,3 @@ usbh_class_driver_t const *usbh_app_driver_get_cb(uint8_t *driver_count) {
|
||||
*driver_count = 1;
|
||||
return driver_host;
|
||||
}
|
||||
|
||||
// Request for HID_REQ_CONTROL_GET_REPORT missing from TinyUSB
|
||||
static void get_report_complete(tuh_xfer_t* xfer)
|
||||
{
|
||||
if (tuh_hid_get_report_complete_cb)
|
||||
{
|
||||
uint8_t const instance = 0;
|
||||
|
||||
uint8_t const report_type = tu_u16_high(xfer->setup->wValue);
|
||||
uint8_t const report_id = tu_u16_low(xfer->setup->wValue);
|
||||
|
||||
tuh_hid_get_report_complete_cb(xfer->daddr, instance, report_id, report_type,
|
||||
(xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len)
|
||||
{
|
||||
tusb_control_request_t const request =
|
||||
{
|
||||
.bmRequestType_bit =
|
||||
{
|
||||
.recipient = TUSB_REQ_RCPT_INTERFACE,
|
||||
.type = TUSB_REQ_TYPE_CLASS,
|
||||
.direction = TUSB_DIR_IN
|
||||
},
|
||||
.bRequest = HID_REQ_CONTROL_GET_REPORT,
|
||||
.wValue = tu_u16(report_type, report_id),
|
||||
.wIndex = _intf_num, // pulled in from tuh_hid_mount_cb()
|
||||
.wLength = len
|
||||
};
|
||||
|
||||
tuh_xfer_t xfer =
|
||||
{
|
||||
.daddr = dev_addr,
|
||||
.ep_addr = 0,
|
||||
.setup = &request,
|
||||
.buffer = (uint8_t*)report,
|
||||
.complete_cb = get_report_complete,
|
||||
.user_data = 0
|
||||
};
|
||||
|
||||
TU_ASSERT( tuh_control_xfer(&xfer) );
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user