From 28e06a94ec79edde8959f98fa9ed1551ca43b326 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 29 Oct 2019 16:48:20 -0400 Subject: [PATCH] usbhs: Swapped the INPUT/OUTPUT endpoint descriptors in UsbHsInterfaceInfo to support [8.0.0+], and convert that struct to the new layout internally when running on pre-8.0.0. Closes #341. --- nx/include/switch/services/usbhs.h | 9 ++++--- nx/source/services/usbhs.c | 40 +++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/nx/include/switch/services/usbhs.h b/nx/include/switch/services/usbhs.h index 32e840ca..88cef72b 100644 --- a/nx/include/switch/services/usbhs.h +++ b/nx/include/switch/services/usbhs.h @@ -43,6 +43,7 @@ typedef struct { } UsbHsInterfaceFilter; /// Descriptors which are not available are set to all-zero. +/// The INPUT/OUTPUT endpoint descriptors were swapped with [8.0.0+], libnx converts this struct to the newer layout when running on pre-8.0.0. typedef struct { s32 ID; u32 deviceID_2; @@ -50,13 +51,13 @@ typedef struct { struct usb_interface_descriptor interface_desc; u8 pad_x15[0x7]; - struct usb_endpoint_descriptor output_endpoint_descs[15]; - u8 pad_x85[0x7]; struct usb_endpoint_descriptor input_endpoint_descs[15]; + u8 pad_x85[0x7]; + struct usb_endpoint_descriptor output_endpoint_descs[15]; u8 pad_xf5[0x6]; - struct usb_ss_endpoint_companion_descriptor output_ss_endpoint_companion_descs[15]; ///< ? + struct usb_ss_endpoint_companion_descriptor input_ss_endpoint_companion_descs[15]; ///< ? u8 pad_x155[0x6]; - struct usb_ss_endpoint_companion_descriptor input_ss_endpoint_companion_descs[15]; ///< ? + struct usb_ss_endpoint_companion_descriptor output_ss_endpoint_companion_descs[15]; ///< ? u8 pad_x1b5[0x3]; } PACKED UsbHsInterfaceInfo; diff --git a/nx/source/services/usbhs.c b/nx/source/services/usbhs.c index 6f715989..1f8b315b 100644 --- a/nx/source/services/usbhs.c +++ b/nx/source/services/usbhs.c @@ -94,12 +94,35 @@ static Result _usbHsBindClientProcess(Handle prochandle) { ); } +// The INPUT/OUTPUT endpoint descriptors were swapped with [8.0.0+], however the sysmodule code which writes this output struct was basically unchanged. +static void _usbHsConvertInterfaceInfoToV8(UsbHsInterfaceInfo *info) { + UsbHsInterfaceInfo tmp; + if (hosversionAtLeast(8,0,0) || info==NULL) return; + + memcpy(&tmp, info, sizeof(UsbHsInterfaceInfo)); + + memcpy(info->output_endpoint_descs, tmp.input_endpoint_descs, sizeof(tmp.input_endpoint_descs)); + memcpy(info->input_endpoint_descs, tmp.output_endpoint_descs, sizeof(tmp.output_endpoint_descs)); + memcpy(info->output_ss_endpoint_companion_descs, tmp.input_ss_endpoint_companion_descs, sizeof(tmp.input_ss_endpoint_companion_descs)); + memcpy(info->input_ss_endpoint_companion_descs, tmp.output_ss_endpoint_companion_descs, sizeof(tmp.output_ss_endpoint_companion_descs)); +} + +static void _usbHsConvertInterfacesToV8(UsbHsInterface* interfaces, s32 total_entries) { + for (s32 i=0; iinf); rc = _usbHsGetEvent(&s->s, &s->event0, false, 0); if (hosversionAtLeast(2,0,0)) rc = _usbHsGetEvent(&s->s, &s->eventCtrlXfer, false, 6); @@ -202,10 +230,12 @@ static Result _usbHsIfGetInf(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u if (inf==NULL) inf = &s->inf.inf; serviceAssumeDomain(&s->s); - return serviceDispatchIn(&s->s, cmd_id, id, + Result rc = serviceDispatchIn(&s->s, cmd_id, id, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { inf, sizeof(UsbHsInterfaceInfo) } }, ); + if (R_SUCCEEDED(rc)) _usbHsConvertInterfaceInfoToV8(inf); + return rc; } Result usbHsIfSetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id) { @@ -219,7 +249,9 @@ Result usbHsIfGetAlternateInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* Result usbHsIfGetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf) { if (inf==NULL) inf = &s->inf.inf; - return _usbHsCmdRecvBufNoOut(&s->s, inf, sizeof(UsbHsInterfaceInfo), 2); + Result rc = _usbHsCmdRecvBufNoOut(&s->s, inf, sizeof(UsbHsInterfaceInfo), 2); + if (R_SUCCEEDED(rc)) _usbHsConvertInterfaceInfoToV8(inf); + return rc; } Result usbHsIfGetCurrentFrame(UsbHsClientIfSession* s, u32* out) {