From 7871ecbc33913acb8fab185f1efefd4a7b4fb215 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 11 Oct 2018 02:16:11 -0700 Subject: [PATCH] usbComms: Auto allocate interface number. --- nx/include/switch/services/usb.h | 3 +- nx/source/runtime/devices/usb_comms.c | 18 ++-- nx/source/services/usb.c | 126 ++++++++++++++++++++------ 3 files changed, 112 insertions(+), 35 deletions(-) diff --git a/nx/include/switch/services/usb.h b/nx/include/switch/services/usb.h index 391f6830..751994b6 100644 --- a/nx/include/switch/services/usb.h +++ b/nx/include/switch/services/usb.h @@ -214,7 +214,8 @@ Result usbDsGetDsInterface(UsbDsInterface** out, struct usb_interface_descriptor Result usbDsSetVidPidBcd(const UsbDsDeviceInfo* deviceinfo); /// Added in 5.0.0 -Result usbDsRegisterInterface(UsbDsInterface** out, u32 intf_num); +Result usbDsRegisterInterface(UsbDsInterface** out); +Result usbDsRegisterInterfaceEx(UsbDsInterface** out, u32 intf_num); Result usbDsClearDeviceData(void); Result usbDsAddUsbStringDescriptor(u8* out_index, const char* string); Result usbDsAddUsbLanguageStringDescriptor(u8* out_index, const u16* lang_ids, u16 num_langs); diff --git a/nx/source/runtime/devices/usb_comms.c b/nx/source/runtime/devices/usb_comms.c index 5e859259..802e2cae 100644 --- a/nx/source/runtime/devices/usb_comms.c +++ b/nx/source/runtime/devices/usb_comms.c @@ -212,13 +212,12 @@ static Result _usbCommsInterfaceInit(u32 intf_ind, const UsbCommsInterfaceInfo * static Result _usbCommsInterfaceInit5x(u32 intf_ind, const UsbCommsInterfaceInfo *info) { Result rc = 0; - u32 ep_num = intf_ind + 1; usbCommsInterface *interface = &g_usbCommsInterfaces[intf_ind]; struct usb_interface_descriptor interface_descriptor = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = intf_ind, + .bInterfaceNumber = 4, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = USB_CLASS_VENDOR_SPEC, @@ -229,7 +228,7 @@ static Result _usbCommsInterfaceInit5x(u32 intf_ind, const UsbCommsInterfaceInfo struct usb_endpoint_descriptor endpoint_descriptor_in = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_ENDPOINT_IN + ep_num, + .bEndpointAddress = USB_ENDPOINT_IN, .bmAttributes = USB_TRANSFER_TYPE_BULK, .wMaxPacketSize = 0x40, }; @@ -237,7 +236,7 @@ static Result _usbCommsInterfaceInit5x(u32 intf_ind, const UsbCommsInterfaceInfo struct usb_endpoint_descriptor endpoint_descriptor_out = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_ENDPOINT_OUT + ep_num, + .bEndpointAddress = USB_ENDPOINT_OUT, .bmAttributes = USB_TRANSFER_TYPE_BULK, .wMaxPacketSize = 0x40, }; @@ -268,9 +267,13 @@ static Result _usbCommsInterfaceInit5x(u32 intf_ind, const UsbCommsInterfaceInfo if (R_FAILED(rc)) return rc; - rc = usbDsRegisterInterface(&interface->interface, interface_descriptor.bInterfaceNumber); + rc = usbDsRegisterInterface(&interface->interface); if (R_FAILED(rc)) return rc; + interface_descriptor.bInterfaceNumber = interface->interface->interface_index; + endpoint_descriptor_in.bEndpointAddress += interface_descriptor.bInterfaceNumber + 1; + endpoint_descriptor_out.bEndpointAddress += interface_descriptor.bInterfaceNumber + 1; + // Full Speed Config rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_Full, &interface_descriptor, USB_DT_INTERFACE_SIZE); if (R_FAILED(rc)) return rc; @@ -320,7 +323,6 @@ static Result _usbCommsInterfaceInit5x(u32 intf_ind, const UsbCommsInterfaceInfo static Result _usbCommsInterfaceInit1x(u32 intf_ind, const UsbCommsInterfaceInfo *info) { Result rc = 0; - u32 ep_num = intf_ind + 1; usbCommsInterface *interface = &g_usbCommsInterfaces[intf_ind]; struct usb_interface_descriptor interface_descriptor = { @@ -336,7 +338,7 @@ static Result _usbCommsInterfaceInit1x(u32 intf_ind, const UsbCommsInterfaceInfo struct usb_endpoint_descriptor endpoint_descriptor_in = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_ENDPOINT_IN + ep_num, + .bEndpointAddress = USB_ENDPOINT_IN, .bmAttributes = USB_TRANSFER_TYPE_BULK, .wMaxPacketSize = 0x200, }; @@ -344,7 +346,7 @@ static Result _usbCommsInterfaceInit1x(u32 intf_ind, const UsbCommsInterfaceInfo struct usb_endpoint_descriptor endpoint_descriptor_out = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_ENDPOINT_OUT + ep_num, + .bEndpointAddress = USB_ENDPOINT_OUT, .bmAttributes = USB_TRANSFER_TYPE_BULK, .wMaxPacketSize = 0x200, }; diff --git a/nx/source/services/usb.c b/nx/source/services/usb.c index 0e2869b9..5ca11f4f 100644 --- a/nx/source/services/usb.c +++ b/nx/source/services/usb.c @@ -44,7 +44,7 @@ Result usbDsInitialize(void) rc = _usbDsGetEvent(&g_usbDsSrv, &g_usbDsStateChangeEvent, 3); // Result code doesn't matter here, users can call themselves later, too. This prevents foot shooting. - if (R_SUCCEEDED(rc)) + if (R_SUCCEEDED(rc) && kernelAbove500()) usbDsClearDeviceData(); if (R_FAILED(rc)) @@ -88,24 +88,6 @@ static UsbDsInterface* _usbDsTryAllocateInterface(u32 num) { return ptr; } -static UsbDsInterface* _usbDsAllocateInterface(void) -{ - u32 pos; - UsbDsInterface* ptr = NULL; - - for(pos=0; posinitialized)continue; - memset(ptr, 0, sizeof(UsbDsInterface)); - ptr->initialized = true; - ptr->interface_index = pos; - return ptr; - } - - return NULL; -} - static UsbDsEndpoint* _usbDsAllocateEndpoint(UsbDsInterface* interface) { u32 pos; @@ -540,13 +522,31 @@ static Result _usbDsGetReport(Service* srv, u64 cmd_id, UsbDsReportData *out) { return rc; } -Result usbDsGetDsInterface(UsbDsInterface** interface, struct usb_interface_descriptor* descriptor, const char *interface_name) -{ - UsbDsInterface* ptr = _usbDsAllocateInterface(); - if(ptr == NULL) +Result usbDsGetDsInterface(UsbDsInterface** interface, struct usb_interface_descriptor* _descriptor, const char *interface_name) +{ + struct usb_interface_descriptor send_desc = *_descriptor; + Service srv; + Result rc; + for (unsigned int i = 0; i < TOTAL_INTERFACES; i++) { + send_desc.bInterfaceNumber = i; + rc = _usbDsGetSession(&g_usbDsSrv, &srv, 2, &send_desc, USB_DT_INTERFACE_SIZE, interface_name, strlen(interface_name)+1); + if (R_SUCCEEDED(rc)) { + break; + } + } + + if (R_FAILED(rc)) { + return rc; + } + + UsbDsInterface* ptr = _usbDsTryAllocateInterface(send_desc.bInterfaceNumber); + if(ptr == NULL) { + serviceClose(&srv); + _usbDsFreeInterface(ptr); return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); - - Result rc = _usbDsGetSession(&g_usbDsSrv, &ptr->h, 2, descriptor, sizeof(struct usb_interface_descriptor), interface_name, strlen(interface_name)+1); + } + + ptr->h = srv; // GetSetupEvent if (R_SUCCEEDED(rc)) @@ -567,7 +567,80 @@ Result usbDsGetDsInterface(UsbDsInterface** interface, struct usb_interface_desc return rc; } -Result usbDsRegisterInterface(UsbDsInterface** interface, u32 intf_num) +Result usbDsRegisterInterface(UsbDsInterface** interface) +{ + Service srv; + Result rc; + u32 intf_num; + for (intf_num = 0; intf_num < TOTAL_INTERFACES; intf_num++) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 intf_num; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2; + raw->intf_num = intf_num; + + rc = serviceIpcDispatch(&g_usbDsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreate(&srv, r.Handles[0]); + break; + } + } + } + + if (R_FAILED(rc)) { + return rc; + } + + UsbDsInterface* ptr = _usbDsTryAllocateInterface(intf_num); + if(ptr == NULL) { + serviceClose(&srv); + _usbDsFreeInterface(ptr); + return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); + } + + ptr->h = srv; + + // GetSetupEvent + if (R_SUCCEEDED(rc)) + rc = _usbDsGetEvent(&ptr->h, &ptr->SetupEvent, 1); + // GetCtrlInCompletionEvent + if (R_SUCCEEDED(rc)) + rc = _usbDsGetEvent(&ptr->h, &ptr->CtrlInCompletionEvent, 7); + // GetCtrlOutCompletionEvent + if (R_SUCCEEDED(rc)) + rc = _usbDsGetEvent(&ptr->h, &ptr->CtrlOutCompletionEvent, 9); + + if (R_FAILED(rc)) + _usbDsFreeInterface(ptr); + + if (R_SUCCEEDED(rc)) + *interface = ptr; + + return rc; +} + +Result usbDsRegisterInterfaceEx(UsbDsInterface** interface, u32 intf_num) { UsbDsInterface* ptr = _usbDsTryAllocateInterface(intf_num); if(ptr == NULL) @@ -625,6 +698,7 @@ Result usbDsRegisterInterface(UsbDsInterface** interface, u32 intf_num) return rc; } + Result usbDsClearDeviceData(void) { return _usbDsCmdNoParams(&g_usbDsSrv, 5); }