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.

This commit is contained in:
yellows8 2019-10-29 16:48:20 -04:00
parent ccea53c837
commit 28e06a94ec
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 41 additions and 8 deletions

View File

@ -43,6 +43,7 @@ typedef struct {
} UsbHsInterfaceFilter; } UsbHsInterfaceFilter;
/// Descriptors which are not available are set to all-zero. /// 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 { typedef struct {
s32 ID; s32 ID;
u32 deviceID_2; u32 deviceID_2;
@ -50,13 +51,13 @@ typedef struct {
struct usb_interface_descriptor interface_desc; struct usb_interface_descriptor interface_desc;
u8 pad_x15[0x7]; u8 pad_x15[0x7];
struct usb_endpoint_descriptor output_endpoint_descs[15];
u8 pad_x85[0x7];
struct usb_endpoint_descriptor input_endpoint_descs[15]; struct usb_endpoint_descriptor input_endpoint_descs[15];
u8 pad_x85[0x7];
struct usb_endpoint_descriptor output_endpoint_descs[15];
u8 pad_xf5[0x6]; 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]; 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]; u8 pad_x1b5[0x3];
} PACKED UsbHsInterfaceInfo; } PACKED UsbHsInterfaceInfo;

View File

@ -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; i<total_entries; i++) {
_usbHsConvertInterfaceInfoToV8(&interfaces[i].inf);
}
}
static Result _usbHsQueryInterfaces(u32 base_cmdid, const UsbHsInterfaceFilter* filter, UsbHsInterface* interfaces, size_t interfaces_maxsize, s32* total_entries) { static Result _usbHsQueryInterfaces(u32 base_cmdid, const UsbHsInterfaceFilter* filter, UsbHsInterface* interfaces, size_t interfaces_maxsize, s32* total_entries) {
serviceAssumeDomain(&g_usbHsSrv); serviceAssumeDomain(&g_usbHsSrv);
return serviceDispatchInOut(&g_usbHsSrv, hosversionAtLeast(2,0,0) ? base_cmdid+1 : base_cmdid, *filter, *total_entries, s32 tmp=0;
Result rc = serviceDispatchInOut(&g_usbHsSrv, hosversionAtLeast(2,0,0) ? base_cmdid+1 : base_cmdid, *filter, tmp,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { interfaces, interfaces_maxsize } }, .buffers = { { interfaces, interfaces_maxsize } },
); );
if (R_SUCCEEDED(rc) && total_entries) *total_entries = tmp;
if (R_SUCCEEDED(rc)) _usbHsConvertInterfacesToV8(interfaces, tmp);
return rc;
} }
Result usbHsQueryAllInterfaces(const UsbHsInterfaceFilter* filter, UsbHsInterface* interfaces, size_t interfaces_maxsize, s32* total_entries) { Result usbHsQueryAllInterfaces(const UsbHsInterfaceFilter* filter, UsbHsInterface* interfaces, size_t interfaces_maxsize, s32* total_entries) {
@ -112,10 +135,14 @@ Result usbHsQueryAvailableInterfaces(const UsbHsInterfaceFilter* filter, UsbHsIn
Result usbHsQueryAcquiredInterfaces(UsbHsInterface* interfaces, size_t interfaces_maxsize, s32* total_entries) { Result usbHsQueryAcquiredInterfaces(UsbHsInterface* interfaces, size_t interfaces_maxsize, s32* total_entries) {
serviceAssumeDomain(&g_usbHsSrv); serviceAssumeDomain(&g_usbHsSrv);
return serviceDispatchOut(&g_usbHsSrv, hosversionAtLeast(2,0,0) ? 3 : 2, *total_entries, s32 tmp=0;
Result rc = serviceDispatchOut(&g_usbHsSrv, hosversionAtLeast(2,0,0) ? 3 : 2, tmp,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { interfaces, interfaces_maxsize } }, .buffers = { { interfaces, interfaces_maxsize } },
); );
if (R_SUCCEEDED(rc) && total_entries) *total_entries = tmp;
if (R_SUCCEEDED(rc)) _usbHsConvertInterfacesToV8(interfaces, tmp);
return rc;
} }
Result usbHsCreateInterfaceAvailableEvent(Event* out_event, bool autoclear, u8 index, const UsbHsInterfaceFilter* filter) { Result usbHsCreateInterfaceAvailableEvent(Event* out_event, bool autoclear, u8 index, const UsbHsInterfaceFilter* filter) {
@ -181,6 +208,7 @@ Result usbHsAcquireUsbIf(UsbHsClientIfSession* s, UsbHsInterface *interface) {
rc = _usbHsAcquireUsbIfOld(s, interface); rc = _usbHsAcquireUsbIfOld(s, interface);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
_usbHsConvertInterfaceInfoToV8(&interface->inf);
rc = _usbHsGetEvent(&s->s, &s->event0, false, 0); rc = _usbHsGetEvent(&s->s, &s->event0, false, 0);
if (hosversionAtLeast(2,0,0)) rc = _usbHsGetEvent(&s->s, &s->eventCtrlXfer, false, 6); 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; if (inf==NULL) inf = &s->inf.inf;
serviceAssumeDomain(&s->s); serviceAssumeDomain(&s->s);
return serviceDispatchIn(&s->s, cmd_id, id, Result rc = serviceDispatchIn(&s->s, cmd_id, id,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { inf, sizeof(UsbHsInterfaceInfo) } }, .buffers = { { inf, sizeof(UsbHsInterfaceInfo) } },
); );
if (R_SUCCEEDED(rc)) _usbHsConvertInterfaceInfoToV8(inf);
return rc;
} }
Result usbHsIfSetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id) { Result usbHsIfSetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id) {
@ -219,7 +249,9 @@ Result usbHsIfGetAlternateInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo*
Result usbHsIfGetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf) { Result usbHsIfGetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf) {
if (inf==NULL) inf = &s->inf.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) { Result usbHsIfGetCurrentFrame(UsbHsClientIfSession* s, u32* out) {