Line 1: |
Line 1: |
− | One symbol in USB-sysmodule is: "vtable for nn::usb::detail::UsbComplexTegra21x".
| + | USB provides services for interacting with the USB stack. |
| | | |
| = usb:ds = | | = usb:ds = |
− | This is "nn::usb::ds::IDsService". | + | [1.0.0-10.2.0] This is "nn::usb::ds::IDsService". |
| + | |
| + | [11.0.0+] This is "nn::usb::ds::IDsRootSession". |
| | | |
− | Used for Switch<>PC USB comms, aka Switch-as-device. This seems to only be usable in handheld-mode with the Switch directly connected to a host via an USB cable, not(?) in docked-mode.
| + | This service is used during [[Factory Setup|factory setup]] by [[Manu Services|manu]]. This is also used by [[Capmtp_services|capmtp]]. |
− | This service is used during [[Factory Setup|factory setup]] by [[Manu Services|manu]]. | |
| | | |
− | This service session is used as an IPC [[IPC_Marshalling|domain]] by [[Manu Services|manu]]. All of these {get-session} commands also return an output u8 and the u32 [[IPC_Marshalling|domainID]], for using those sessions as domains. | + | This service session is used as an IPC [[IPC_Marshalling|domain]] by [[Manu Services|manu]]. |
| | | |
− | This service can be used by multiple processes at the same time, with separate interfaces. However, if one process does usbds shutdown, usbds will reset to defaults even if there's a process still using it. | + | This service can be used by multiple processes at the same time, with separate interfaces. However, if one process does usbds shutdown, usbds will reset to defaults even if there's a process still using it. |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 15: |
Line 16: |
| ! Cmd || Name | | ! Cmd || Name |
| |- | | |- |
− | | 0 || [[#BindDevice]] | + | | 0 || [[#CreateDsService]] |
| + | |} |
| + | |
| + | == CreateDsService == |
| + | No input. Returns an [[#IDsService]]. |
| + | |
| + | == IDsService == |
| + | This is "nn::usb::ds::IDsService". |
| + | |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | 1 || [[#BindClientProcess]] | + | ! Cmd || Name |
| |- | | |- |
− | | 2 || [[#GetDsInterface]] | + | | 0 || [[#Initialize]] |
| |- | | |- |
− | | 3 || [[#GetStateChangeEvent]] | + | | 1 || [11.0.0+] [[#RegisterInterface]] ([1.0.0-10.2.0] [[#BindClientProcess]])) |
| |- | | |- |
− | | 4 || [[#GetState]] | + | | 2 || [11.0.0+] [[#GetStateChangeEvent]] ([1.0.0-10.2.0] [[#RegisterInterface]]) |
| |- | | |- |
− | | [2.0.0-4.1.0] 5 || [[#SetVidPidBcd]] | + | | 3 || [11.0.0+] [[#GetState]] ([1.0.0-10.2.0] [[#GetStateChangeEvent]]) |
| |- | | |- |
− | | [5.0.0+] 5 || ClearDeviceData | + | | 4 || [11.0.0+] ClearDeviceData ([1.0.0-10.2.0] [[#GetState]]) |
| |- | | |- |
− | | 6 || [5.0.0+] AddUsbStringDescriptor | + | | 5 || [11.0.0+] AddUsbStringDescriptor ([5.0.0-10.2.0] ClearDeviceData, [2.0.0-4.1.0] [[#SetVidPidBcd]]) |
| |- | | |- |
− | | 7 || [5.0.0+] DeleteUsbStringDescriptor | + | | 6 || [11.0.0+] DeleteUsbStringDescriptor ([5.0.0-10.2.0] AddUsbStringDescriptor) |
| |- | | |- |
− | | 8 || [5.0.0+] SetUsbDeviceDescriptor | + | | 7 || [11.0.0+] SetUsbDeviceDescriptor ([5.0.0-10.2.0] DeleteUsbStringDescriptor) |
| |- | | |- |
− | | 9 || [5.0.0+] SetBinaryObjectStore | + | | 8 || [11.0.0+] SetBinaryObjectStore ([5.0.0-10.2.0] SetUsbDeviceDescriptor) |
| |- | | |- |
− | | 10 || [5.0.0+] Enable | + | | 9 || [11.0.0+] EnableDevice ([5.0.0-10.2.0] SetBinaryObjectStore) |
| |- | | |- |
− | | 11 || [5.0.0+] Disable | + | | 10 || [11.0.0+] DisableDevice ([5.0.0-10.2.0] EnableDevice) |
| + | |- |
| + | | 11 || [11.0.0+] [[#GetSpeed]] ([5.0.0-10.2.0] DisableDevice) |
| + | |- |
| + | | 12 || [8.0.0-10.2.0] [[#GetSpeed]] |
| |} | | |} |
| | | |
− | Initialization done by [[Manu Services|manu]]:
| + | == Initialize == |
− | * Initial service init:
| + | Takes an input u32 '''ComplexId'''. No output. |
− | ** Get service/etc.
| |
− | ** Uses [[#BindDevice]].
| |
− | ** Uses [[#BindClientProcess]].
| |
− | ** Uses [[#GetStateChangeEvent]].
| |
− | ** Uses [[#SetVidPidBcd]].
| |
− | * Interface init:
| |
− | ** Uses [[#GetDsInterface]], then uses commands from that with the rest of the following.
| |
− | ** Uses [[#GetSetupEvent]].
| |
− | ** Uses [[#GetCtrlInCompletionEvent]].
| |
− | ** Uses [[#GetCtrlOutCompletionEvent]].
| |
− | * Initializes two endpoints via using [[#GetDsEndpoint]] twice.
| |
| | | |
− | == Configuration ==
| + | [11.0.0+] Now takes an additional input Process handle. |
− | The following is the default USB config strings, while the usbds service isn't being used. All of the below configuration will reset to the defaults when all usbds-related sessions are closed. These can be set with [[#SetVidPidBcd]]. The default string for Product is loaded from [[Settings_services|settings]] config. The default is referred to by usb-sysmodule as "Dummy".
| |
− | Product: Nintendo Switch
| |
− | Manufacturer: Nintendo
| |
− | SerialNumber: SerialNumber
| |
− | | |
− | The following is the default <code>lsusb -v {...}</code> output when the usbds service wasn't used.
| |
− | | |
− | pre-5.0.0: The endpoints are configured using [[#GetDsEndpoint]], the total number of endpoints is the number of open [[#IDsEndpoint]] sessions. bInterfaceNumber is {0-based index for the enabled [[#IDsInterface]] session.} Some of the interface fields are configured using [[#GetDsInterface]].
| |
− | | |
− | When usbds is in use where [[#SetVidPidBcd]] wasn't used, the VID/PID is 057e:3000.
| |
− | | |
− | Bus 003 Device 006: ID 057e:2000 Nintendo Co., Ltd
| |
− | Couldn't open device, some information will be missing
| |
− | Device Descriptor:
| |
− | bLength 18
| |
− | bDescriptorType 1
| |
− | bcdUSB 2.00
| |
− | bDeviceClass 0 (Defined at Interface level)
| |
− | bDeviceSubClass 0
| |
− | bDeviceProtocol 0
| |
− | bMaxPacketSize0 64
| |
− | idVendor 0x057e Nintendo Co., Ltd
| |
− | idProduct 0x2000
| |
− | bcdDevice 1.00
| |
− | iManufacturer 1
| |
− | iProduct 2
| |
− | iSerial 3
| |
− | bNumConfigurations 1
| |
− | Configuration Descriptor:
| |
− | bLength 9
| |
− | bDescriptorType 2
| |
− | wTotalLength 34
| |
− | bNumInterfaces 1
| |
− | bConfigurationValue 1
| |
− | iConfiguration 0
| |
− | bmAttributes 0xc0
| |
− | Self Powered
| |
− | MaxPower {...}
| |
− | Interface Descriptor:
| |
− | bLength 9
| |
− | bDescriptorType 4
| |
− | bInterfaceNumber 0
| |
− | bAlternateSetting 0
| |
− | bNumEndpoints 1
| |
− | bInterfaceClass 3 Human Interface Device
| |
− | bInterfaceSubClass 0 No Subclass
| |
− | bInterfaceProtocol 0 None
| |
− | iInterface 0
| |
− | HID Device Descriptor:
| |
− | bLength 9
| |
− | bDescriptorType 33
| |
− | bcdHID 2.00
| |
− | bCountryCode 0 Not supported
| |
− | bNumDescriptors 1
| |
− | bDescriptorType 34 Report
| |
− | wDescriptorLength 26
| |
− | Report Descriptors:
| |
− | ** UNAVAILABLE **
| |
− | Endpoint Descriptor:
| |
− | bLength 7
| |
− | bDescriptorType 5
| |
− | bEndpointAddress 0x81 EP 1 IN
| |
− | bmAttributes 3
| |
− | Transfer Type Interrupt
| |
− | Synch Type None
| |
− | Usage Type Data
| |
− | wMaxPacketSize 0x0001 1x 1 bytes
| |
− | bInterval 16
| |
| | | |
− | == BindDevice ==
| + | [[Manu_Services|Manu]] uses '''ComplexId''' 0x02. |
− | Takes an u32 ('''complexId'''). [[Manu_Services|Manu]] sends 0x02.
| |
| | | |
| Binding more than once with the current session is not allowed. Once this command is used, the USB device will not be listed with <code>lsusb</code> until [[#EnableInterface]] is used. | | Binding more than once with the current session is not allowed. Once this command is used, the USB device will not be listed with <code>lsusb</code> until [[#EnableInterface]] is used. |
| | | |
− | Returns a not-found error when complexId isn't 0x02, for values 0x0-0x4 at least. | + | Returns a not-found error when '''ComplexId''' isn't 0x02, for values 0x0-0x4 at least. |
| | | |
| == BindClientProcess == | | == BindClientProcess == |
− | Takes 1 copy-handle for the current process (0xFFFF8001). | + | Takes an input Process handle. No output. |
| | | |
− | == GetDsInterface == | + | == RegisterInterface == |
− | Takes 2 type-5 buffers and returns an output u8 and an [[#IDsInterface]]. [[Manu_Services|Manu]] sends a 0x09-byte descriptor (e.g.: 0x09, 0x04, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00) in the first buffer and a string ("usb") in the second buffer. | + | Takes two type-0x5 input buffers containing an [[#UsbInterfaceDescriptor]] and an [[#UsbStringDescriptor]], respectively. Returns an output u8 '''InterfaceNumber''' and an [[#IDsInterface]]. |
| | | |
− | When the strlen output for the second buffer is >=0x40, size 0x40 is used instead for copying the string. This is the interface name, it's not sent over USB.
| + | [5.0.0+] This now only takes an input u8 and returns an [[#IDsInterface]]. |
| | | |
− | Returns an error when [[#BindDevice]] wasn't used.
| + | [[Manu_Services|Manu]] sends a 0x09-byte descriptor (e.g.: 0x09, 0x04, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00) in the first buffer and a string ("usb") in the second buffer. |
| | | |
− | Up to 4 interfaces can be used+[[#EnableInterface|enabled]].
| + | When the strlen output for the second buffer is >=0x40, size 0x40 is used instead for copying the string. This is the interface name, it's not sent over USB. |
| | | |
− | Structure of the first buffer(this is the same as [http://libusb.sourceforge.net/api-1.0/structlibusb__interface__descriptor.html libusb__interface__descriptor]):
| + | Returns an error when [[#Initialize]] wasn't used. |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! Offset || Size || Description
| |
− | |-
| |
− | | 0x0 || 0x1 || bLength. Must match 0x9.
| |
− | |-
| |
− | | 0x1 || 0x1 || bDescriptorType. Must match 0x4.
| |
− | |-
| |
− | | 0x2 || 0x1 || bInterfaceNumber. When 0x4, the bInterfaceNumber is automatically allocated(error will be thrown if no space). Otherwise, it's used directly and must be <=3.
| |
− | |-
| |
− | | 0x3 || 0x1 || bAlternateSetting. Must match 0x0.
| |
− | |-
| |
− | | 0x4 || 0x1 || bNumEndpoints. Ignored.
| |
− | |-
| |
− | | 0x5 || 0x1 || bInterfaceClass
| |
− | |-
| |
− | | 0x6 || 0x1 || bInterfaceSubClass
| |
− | |-
| |
− | | 0x7 || 0x1 || bInterfaceProtocol
| |
− | |-
| |
− | | 0x8 || 0x1 || iInterface. Ignored.
| |
− | |}
| |
| | | |
− | Only the first 0x9-bytes are used.
| + | Up to 4 interfaces can be used and [[#EnableInterface|enabled]]. |
| | | |
| == GetStateChangeEvent == | | == GetStateChangeEvent == |
− | Returns an event handle for when the state returned by [[#GetState]] changes. Signalled when Switch<->host USB comms change between started/stopped. USB cable connected/disconnected while at least 1 interface was enabled, or interface enabled/disabled while the USB cable was connected which then caused USB-comms state to change. | + | No input. Returns an output Event handle. |
| + | |
| + | Signalled when Switch<->host USB comms change between started/stopped. USB cable connected/disconnected while at least 1 interface was enabled, or interface enabled/disabled while the USB cable was connected which then caused USB-comms state to change. |
| | | |
| == GetState == | | == GetState == |
− | No input. Returns an output u32. Returns an error when [[#BindDevice]] wasn't used. | + | No input. Returns an output [[#UsbState]]. |
| | | |
− | Returns the current state. Values: | + | Returns an error when [[#Initialize]] wasn't used. |
− | * 0: Initial state.
| |
− | * 6: Device init starting.
| |
− | * 3: {Initialization}, previous state is 6.
| |
− | * 4: {Initialization}, previous state is 3.
| |
− | * 5: Initialization done, data-transfer is now available.
| |
| | | |
| == SetVidPidBcd == | | == SetVidPidBcd == |
− | Takes a type-5 buffer with 0x66 bytes of USB descriptor data (see [[Manu_Services#manu|manu]]). | + | Takes a type-0x5 input buffer containing an [[#UsbVidPidBcd]]. No output. |
| | | |
− | {| class="wikitable" border="1"
| + | == GetSpeed == |
− | |-
| + | No input. Returns an output [[#UsbDeviceSpeed]]. |
− | ! Offset || Size || Description
| |
− | |-
| |
− | | 0x0 || 0x2 || VID (idVendor)
| |
− | |-
| |
− | | 0x2 || 0x2 || PID (idProduct)
| |
− | |-
| |
− | | 0x4 || 0x2 || bcdDevice
| |
− | |-
| |
− | | 0x6 || 0x20 || Manufacturer
| |
− | |-
| |
− | | 0x26 || 0x20 || Product
| |
− | |-
| |
− | | 0x46 || 0x20 || SerialNumber
| |
− | |}
| |
− | | |
− | The last 3 blocks are ASCII strings. The data following each string is all-zero, for padding to size 0x20.
| |
| | | |
| == IDsInterface == | | == IDsInterface == |
Line 211: |
Line 104: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Cmd || Name |
| |- | | |- |
− | | 0 || [[#GetDsEndpoint]] || | + | | 0 || [[#RegisterEndpoint]] |
| |- | | |- |
− | | 1 || [[#GetSetupEvent]] || | + | | 1 || [[#GetSetupEvent]] |
| |- | | |- |
− | | 2 || || Takes a type-0x6 output buffer, no other output. Memcpys data to outbuf with outsize, uses size 0x8 if outsize is too large. | + | | 2 || [[#GetSetupPacket]] |
| |- | | |- |
− | | 3 || [[#EnableInterface]] || | + | | 3 || [11.0.0+] [[#CtrlInAsync]] ([1.0.0-10.2.0] [[#Enable]]) |
| |- | | |- |
− | | 4 || [[#DisableInterface]] || | + | | 4 || [11.0.0+] [[#CtrlOutAsync]] ([1.0.0-10.2.0] [[#Disable]]) |
| |- | | |- |
− | | 5 || [[#CtrlInPostBufferAsync]] || | + | | 5 || [11.0.0+] [[#GetCtrlInCompletionEvent]] ([1.0.0-10.2.0] [[#CtrlInAsync]]) |
| |- | | |- |
− | | 6 || [[#CtrlOutPostBufferAsync]] || | + | | 6 || [11.0.0+] [[#GetCtrlInUrbReport]] ([1.0.0-10.2.0] [[#CtrlOutAsync]]) |
| |- | | |- |
− | | 7 || [[#GetCtrlInCompletionEvent]] || | + | | 7 || [11.0.0+] [[#GetCtrlOutCompletionEvent]] ([1.0.0-10.2.0] [[#GetCtrlInCompletionEvent]]) |
| |- | | |- |
− | | 8 || [[#GetCtrlInReportData]] || | + | | 8 || [11.0.0+] [[#GetCtrlOutUrbReport]] ([1.0.0-10.2.0] [[#GetCtrlInUrbReport]]) |
| |- | | |- |
− | | 9 || [[#GetCtrlOutCompletionEvent]] || | + | | 9 || [11.0.0+] [[#CtrlStall]] ([1.0.0-10.2.0] [[#GetCtrlOutCompletionEvent]]) |
| |- | | |- |
− | | 10 || [[#GetCtrlOutReportData]] || | + | | 10 || [11.0.0+] [[#AppendConfigurationData]] ([1.0.0-10.2.0] [[#GetCtrlOutUrbReport]]) |
| |- | | |- |
− | | 11 || [[#StallCtrl]] || | + | | 11 || [13.0.0+] [[#SetGuid]] ([1.0.0-10.2.0] [[#CtrlStall]]) |
| |- | | |- |
− | | 12 || [5.0.0+] AppendConfigurationData || | + | | 12 || [15.0.0+] [[#RegisterTransferMemory]] ([5.0.0-10.2.0] [[#AppendConfigurationData]]) |
| |} | | |} |
| | | |
− | Commands cmd2, [[#CtrlInPostBufferAsync]], [[#CtrlOutPostBufferAsync]], and [[#StallCtrl]], will throw an error if the interface is not [[#EnableInterface|enabled]]. [[#GetDsEndpoint]] will throw an error if the interface is [[#EnableInterface|enabled]].
| + | === RegisterEndpoint === |
| + | Takes a type-0x5 input buffer containing an [[#UsbEndpointDescriptor]]. Returns an output u8 '''EndpointNumber''' and an [[#IDsEndpoint]]. |
| | | |
− | === GetDsEndpoint ===
| + | [5.0.0+] This now only takes an input u8 and returns an [[#IDsEndpoint]]. |
− | Takes a type-5 buffer and returns an output u8 and an [[#IDsEndpoint]]. [[Manu_Services|Manu]] uses this twice for getting two endpoint sessions, with the following 0x7-byte buffer data:
| + | |
| + | [[Manu_Services|Manu]] uses this twice for getting two endpoint sessions, with the following 0x7-byte buffer data: |
| * First endpoint: 0x07, 0x05, 0x80, 0x02, 0x00, 0x02, 0x00 | | * First endpoint: 0x07, 0x05, 0x80, 0x02, 0x00, 0x02, 0x00 |
| ** bLength=0x7 | | ** bLength=0x7 |
Line 252: |
Line 147: |
| ** bInterval=0 | | ** bInterval=0 |
| * Second endpoint: Same as above except byte2 is 0x00(bEndpointAddress=LIBUSB_ENDPOINT_OUT). | | * Second endpoint: Same as above except byte2 is 0x00(bEndpointAddress=LIBUSB_ENDPOINT_OUT). |
− |
| |
− | Each field is an u8, except for offset 0x4-0x5 which is an u16.
| |
− |
| |
− | This structure matches [http://libusb.sourceforge.net/api-1.0/structlibusb__endpoint__descriptor.html libusb_endpoint_descriptor], with audio-only-devices fields bRefresh and bSynchAddress removed.
| |
| | | |
| The buffer size must be >=0x7. Only the first 0x7-bytes from the buffer are used. | | The buffer size must be >=0x7. Only the first 0x7-bytes from the buffer are used. |
Line 263: |
Line 154: |
| | | |
| From the Tegra datasheet: "The maximum packet size supported on any endpoint is 1024 bytes in high-speed mode, for both device and host modes." | | From the Tegra datasheet: "The maximum packet size supported on any endpoint is 1024 bytes in high-speed mode, for both device and host modes." |
| + | |
| + | Throws an error if the interface is [[#EnableInterface|enabled]]. |
| | | |
| === GetSetupEvent === | | === GetSetupEvent === |
− | Returns an event handle. Unknown what triggers signalling, not signalled during interface-enable / device<>host USB-comms init. | + | No input. Returns an output Event handle. |
| + | |
| + | Unknown what triggers signalling, not signalled during interface-enable / device<>host USB-comms init. |
| + | |
| + | === GetSetupPacket === |
| + | Takes a type-0x6 output buffer. No output. |
| + | |
| + | Memcpys data to outbuf with outsize, uses size 0x8 if outsize is too large. |
| + | |
| + | Throws an error if the interface is not [[#EnableInterface|enabled]]. |
| | | |
− | === EnableInterface === | + | === Enable === |
− | Takes no arguments. Enables the current interface.
| + | No input/output. |
| | | |
− | Only one interface can be enabled at a time per bInterfaceNumber. When bInterfaceNumber is auto-allocate(0x4) for [[#GetDsEndpoint]] this isn't an issue since the final bInterfaceNumber will be unique. | + | Enables the current interface. |
| + | |
| + | Only one interface can be enabled at a time per bInterfaceNumber. When bInterfaceNumber is auto-allocate(0x4) for [[#RegisterEndpoint]] this isn't an issue since the final bInterfaceNumber will be unique. |
| | | |
| Once enabled, the device/interface can then actually be used over USB. | | Once enabled, the device/interface can then actually be used over USB. |
| | | |
− | === DisableInterface === | + | === Disable === |
− | Takes no arguments. Disables the current interface.
| + | No input/output. |
| | | |
− | === CtrlInPostBufferAsync ===
| + | Disables the current interface. |
− | Same as [[#PostBufferAsync]](with same input/output), except this uses control input endpoint 0x80.
| |
| | | |
− | === CtrlOutPostBufferAsync === | + | === CtrlInAsync === |
− | Same as [[#PostBufferAsync]](with same input/output), except this uses control output endpoint 0x00. | + | Same as [[#PostBufferAsync]], except this uses control input endpoint 0x80. |
| + | |
| + | Throws an error if the interface is not [[#EnableInterface|enabled]]. |
| + | |
| + | === CtrlOutAsync === |
| + | Same as [[#PostBufferAsync]], except this uses control output endpoint 0x00. |
| + | |
| + | Throws an error if the interface is not [[#EnableInterface|enabled]]. |
| | | |
| === GetCtrlInCompletionEvent === | | === GetCtrlInCompletionEvent === |
− | Returns an event handle for polling the completion of input control commands. Same as [[#GetCompletionEvent]], except this uses control input endpoint 0x80.
| + | Same as [[#GetCompletionEvent]], except this uses control input endpoint 0x80. |
| | | |
− | === GetCtrlInReportData === | + | === GetCtrlInUrbReport === |
− | Same as [[#GetReportData]](with same input/output), except this uses control input endpoint 0x80. | + | Same as [[#GetUrbReport]], except this uses control input endpoint 0x80. |
| | | |
| === GetCtrlOutCompletionEvent === | | === GetCtrlOutCompletionEvent === |
− | Returns an event handle for polling the completion of output control commands. Same as [[#GetCompletionEvent]], except this uses control output endpoint 0x00.
| + | Same as [[#GetCompletionEvent]], except this uses control output endpoint 0x00. |
| | | |
− | === GetCtrlOutReportData === | + | === GetCtrlOutUrbReport === |
− | Same as [[#GetReportData]](with same input/output), except this uses control output endpoint 0x00. | + | Same as [[#GetUrbReport]], except this uses control output endpoint 0x00. |
| | | |
− | === StallCtrl === | + | === CtrlStall === |
| No input/output. | | No input/output. |
| | | |
− | Calls a function with both control endpoints(0x80 and 0x00) with the same function. From strings: "m_pProtocol->Stall(0x80)" "m_pProtocol->Stall(0x00)". | + | Calls a function with both control endpoints (0x80 and 0x00) with the same function. From strings: "m_pProtocol->Stall(0x80)" "m_pProtocol->Stall(0x00)". |
| + | |
| + | Throws an error if the interface is not [[#EnableInterface|enabled]]. |
| + | |
| + | === AppendConfigurationData === |
| + | Takes an input u32 '''InterfaceNumber''', an input [[#UsbDeviceSpeed]] and a type-0x5 input buffer. No output. |
| + | |
| + | [5.0.0+] This now only takes an input [[#UsbDeviceSpeed]] and a type-0x5 input buffer. |
| + | |
| + | === SetGuid === |
| + | Takes a type-0x5 input buffer. No output. |
| + | |
| + | === RegisterTransferMemory === |
| + | Takes an input u64 and an input handle. No output. |
| + | |
| + | Stubbed, just returns an error. |
| | | |
| === IDsEndpoint === | | === IDsEndpoint === |
Line 305: |
Line 230: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#PostBufferAsync]] |
| + | |- |
| + | | 1 || [[#Cancel]] |
| + | |- |
| + | | 2 || [[#GetCompletionEvent]] |
| |- | | |- |
− | | 0 || [[#PostBufferAsync]] || | + | | 3 || [[#GetUrbReport]] |
| |- | | |- |
− | | 1 || || No input/output. | + | | 4 || [[#Stall]] |
| |- | | |- |
− | | 2 || [[#GetCompletionEvent]] || | + | | 5 || [[#SetZlt]] |
| |- | | |- |
− | | 3 || [[#GetReportData]] || | + | | 6 || [7.0.0+] [[#IsStalled]] |
| |- | | |- |
− | | 4 || [[#Stall]] || | + | | 7 || [7.0.0+] [[#GetStallClearedEvent]] |
| |- | | |- |
− | | 5 || || Takes an input u8, no output. | + | | 8 || [11.0.0-14.1.2] |
| + | |- |
| + | | 9 || [11.0.0-14.1.2] |
| |} | | |} |
| | | |
| ==== PostBufferAsync ==== | | ==== PostBufferAsync ==== |
− | Takes an u32 ('''size''') and an u64 ('''buffer'''). Returns an output u32 ('''urbId'''). The output urbId can then be used while parsing the output of [[#GetReportData]], after waiting for the CompletionEvent to be signalled. | + | Takes an input u32 '''Size''' and an input u64 '''Buffer'''. Returns an output u32 '''UrbId'''. |
| + | |
| + | The output urbId can then be used while parsing the output of [[#GetUrbReport]], after waiting for the CompletionEvent to be signalled. |
| | | |
| The buffer address must be 0x1000-byte aligned. The input size doesn't matter. It helps to use svcSetMemoryAttribute to turn off caching on the buffer. | | The buffer address must be 0x1000-byte aligned. The input size doesn't matter. It helps to use svcSetMemoryAttribute to turn off caching on the buffer. |
Line 332: |
Line 267: |
| | | |
| For receiving data, if size is less than {actual received USB packet size} the rest of the packet will be discarded. Later PostBufferAsync cmd(s) will only return data from new packets, not the remainder of the earlier packet(s). | | For receiving data, if size is less than {actual received USB packet size} the rest of the packet will be discarded. Later PostBufferAsync cmd(s) will only return data from new packets, not the remainder of the earlier packet(s). |
| + | |
| + | ==== Cancel ==== |
| + | No input/output. |
| | | |
| ==== GetCompletionEvent ==== | | ==== GetCompletionEvent ==== |
− | No input. Returns an output event handle for polling the completion of [[#PostBufferAsync]], even when it finished via [[#Stall]]. | + | No input. Returns an output Event handle. |
− | | |
− | ==== GetReportData ====
| |
− | No input. Returns 0x84 bytes of report data from the endpoint. Seems to be eventually loaded from state, since this doesn't trigger any USB bus activity. All-zero before PostBufferAsync was used at least once.
| |
| | | |
− | {| class="wikitable" border="1"
| + | ==== GetUrbReport ==== |
− | |-
| + | No input. Returns an output [[#UrbReport]]. |
− | ! Offset || Size || Description
| |
− | |-
| |
− | | 0x0 || 0x10*0x8(0x80) || 0x8 entries 0x10-bytes each for each report.
| |
− | |-
| |
− | | 0x80 || 0x4 || u32 report count
| |
− | |}
| |
| | | |
− | Entry data:
| + | Seems to be eventually loaded from state, since this doesn't trigger any USB bus activity. All-zero before PostBufferAsync was used at least once. |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! Offset || Size || Description
| |
− | |-
| |
− | | 0x0 || 0x4 || u32 id (urbId from post-buffer commands)
| |
− | |-
| |
− | | 0x4 || 0x4 || u32 requestedSize
| |
− | |-
| |
− | | 0x8 || 0x4 || u32 transferredSize
| |
− | |-
| |
− | | 0xC || 0x4 || u32 urb status, converted to error-codes. 0x3 = success, 0x4 = 0x828c, 0x5 = 0x748c. All other values are invalid.
| |
− | |-
| |
− | |}
| |
| | | |
| ==== Stall ==== | | ==== Stall ==== |
| No input/output. | | No input/output. |
| | | |
− | Calls the same function used by [[#StallCtrl]], except this uses the endpoint associated with the current session. | + | Calls the same function used by [[#CtrlStall]], except this uses the endpoint associated with the current session. |
| | | |
| Stops in-progress data-transfer done by [[#PostBufferAsync]]. | | Stops in-progress data-transfer done by [[#PostBufferAsync]]. |
| | | |
− | = usb:hs = | + | ==== SetZlt ==== |
| + | Takes an input bool. No output. |
| + | |
| + | ==== IsStalled ==== |
| + | No input. Returns an output bool. |
| + | |
| + | ==== GetStallClearedEvent ==== |
| + | No input. Returns an output Event handle. |
| + | |
| + | ==== Cmd8 ==== |
| + | Takes an input u64 and an input handle. No output. |
| + | |
| + | Stubbed, just returns an error. |
| + | |
| + | ==== Cmd9 ==== |
| + | Takes an input u32 '''Size''' and an input u64 '''Offset'''. Returns an u32 '''UrbId'''. |
| + | |
| + | Stubbed, just returns an error. |
| + | |
| + | = usb:hs, usb:hs:a = |
| This is "nn::usb::hs::IClientRootSession". | | This is "nn::usb::hs::IClientRootSession". |
| + | |
| + | [7.0.0+] usb:hs:a opens an nn::usb::hs::IClientRootSession, but sets an "isSystemClient" field in the object (and in interfaces/eps opened by the session) to false. |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Cmd || Name |
− | |-
| |
− | | [2.0.0+] 0 || [[#BindClientProcess_2|#BindClientProcess]] ||
| |
| |- | | |- |
− | | 1 ([1.0.0] 0) || [[#QueryAllInterfaces]] || | + | | 0 || [2.0.0+] [[#BindClientProcess_2|#BindClientProcess]] ([1.0.0] [[#QueryAllInterfaces]]) |
| |- | | |- |
− | | 2 ([1.0.0] 1) || [[#QueryAvailableInterfaces]] || | + | | 1 || [[#QueryAllInterfaces]] ([1.0.0] [[#QueryAvailableInterfaces]]) |
| |- | | |- |
− | | 3 ([1.0.0] 2) || [[#QueryAcquiredInterfaces]] || | + | | 2 || [[#QueryAvailableInterfaces]] ([1.0.0] [[#QueryAcquiredInterfaces]]) |
| |- | | |- |
− | | 4 ([1.0.0] 3) || [[#CreateInterfaceAvailableEvent]] || | + | | 3 || [[#QueryAcquiredInterfaces]] ([1.0.0] [[#CreateInterfaceAvailableEvent]]) |
| |- | | |- |
− | | 5 ([1.0.0] 4) || [[#DestroyInterfaceAvailableEvent]] || | + | | 4 || [[#CreateInterfaceAvailableEvent]] ([1.0.0] [[#DestroyInterfaceAvailableEvent]]) |
| |- | | |- |
− | | 6 ([1.0.0] 5) || [[#GetInterfaceStateChangeEvent]] || | + | | 5 || [[#DestroyInterfaceAvailableEvent]] ([1.0.0] [[#GetInterfaceStateChangeEvent]]) |
| |- | | |- |
− | | 7 ([1.0.0] 6) || [[#AcquireUsbIf]] || | + | | 6 || [[#GetInterfaceStateChangeEvent]] ([1.0.0] [[#AcquireUsbIf]]) |
| |- | | |- |
− | | 8 ([1.0.0] 7) || [6.0.0+] ([1.0.0] [[#GetDescriptorString]]) || | + | | 7 || [[#AcquireUsbIf]] ([1.0.0] [[#GetDescriptorString]]) |
| |- | | |- |
− | | [1.0.0] 8 || || Takes an input u32, no output. Stubbed, just returns 0. | + | | 8 || [6.0.0+] SetTestMode ([1.0.0] [[#ResetDevice]]) |
| |} | | |} |
| | | |
Line 406: |
Line 341: |
| | | |
| == QueryAllInterfaces == | | == QueryAllInterfaces == |
− | Takes an [[#UsbHsInterfaceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries. | + | Takes an [[#DeviceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries. |
| | | |
− | The output buffer contains an array of [[#UsbHsInterface]]. This returns the same interfaces as [[#QueryAvailableInterfaces]], followed by the interfaces also returned by [[#QueryAcquiredInterfaces]]. Except for the ID field in [[#UsbHsInterface]], which is set to -1. | + | The output buffer contains an array of [[#InterfaceQueryOutput]]. This returns the same interfaces as [[#QueryAvailableInterfaces]], followed by the interfaces also returned by [[#QueryAcquiredInterfaces]]. Except for the ID field in [[#InterfaceQueryOutput]], which is set to -1. |
| | | |
| == QueryAvailableInterfaces == | | == QueryAvailableInterfaces == |
− | Takes an [[#UsbHsInterfaceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries. | + | Takes an [[#DeviceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries. |
| | | |
− | The output buffer contains an array of [[#UsbHsInterface]]. This only returns interfaces which are not acquired by any process. | + | The output buffer contains an array of [[#InterfaceQueryOutput]]. This only returns interfaces which are not acquired by any process. |
| | | |
| == QueryAcquiredInterfaces == | | == QueryAcquiredInterfaces == |
| Takes a type-0x6 output buffer and returns an output s32 total_entries. | | Takes a type-0x6 output buffer and returns an output s32 total_entries. |
| | | |
− | The output buffer contains an array of [[#UsbHsInterface]], for each interface which was acquired with [[#AcquireUsbIf]]. | + | The output buffer contains an array of [[#InterfaceQueryOutput]], for each interface which was acquired with [[#AcquireUsbIf]]. |
| | | |
| == CreateInterfaceAvailableEvent == | | == CreateInterfaceAvailableEvent == |
− | Takes an input u8 and an [[#UsbHsInterfaceFilter]], and returns an output handle. The input value must be 0..2. This is used as an index in a table. | + | Takes an input u8 and an [[#DeviceFilter]], and returns an output handle. The input value must be 0..2. This is used as an index in a table. |
| | | |
| The struct is located at +2 from the u8 in IPC rawdata. | | The struct is located at +2 from the u8 in IPC rawdata. |
Line 435: |
Line 370: |
| No input, returns an output event handle with autoclear disabled. | | No input, returns an output event handle with autoclear disabled. |
| | | |
− | When signaled, this indicates that the user-process should use [[#QueryAcquiredInterfaces]] and cleanup state for interfaces which were already initialized and don't have any matching ID in [[#UsbHsInterface]] +0x0. When total_entries is less than 1, this indicates that cleanup should be done for all currently open interfaces. | + | When signaled, this indicates that the user-process should use [[#QueryAcquiredInterfaces]] and cleanup state for interfaces which were already initialized and don't have any matching ID in [[#InterfaceProfile]] +0x0. When total_entries is less than 1, this indicates that cleanup should be done for all currently open interfaces. |
| | | |
| == AcquireUsbIf == | | == AcquireUsbIf == |
− | Takes an input u32 and a type-0x6 output buffer, returns an [[#IClientIfSession]]. | + | Takes an input u32 and a type-0x6 output buffer, returns an [[#IClientIfSession]]. On [3.0.0+] this takes an additional type-0x6 output buffer, before the original buffer. On [3.0.0+] the first buffer is 0x70-bytes, while the second one is 0x1B8. The user-process has the second buffer address immediately after the first one, which allows getting a complete [[#InterfaceProfile]]. |
| | | |
− | The input u32 is from the u32 at entry+0 from the associated [[#QueryAvailableInterfaces]] output entry. User-processes use size 0x1B8 for the output buffer. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]]. | + | The input u32 is from the u32 at entry+0 from the associated [[#QueryAvailableInterfaces]] output entry. User-processes use size 0x1B8 for the first output buffer. The first output buffer contains an [[#InterfaceProfile]]. |
| | | |
| This returns an error if the interface was already acquired by another process. | | This returns an error if the interface was already acquired by another process. |
Line 454: |
Line 389: |
| | | |
| Official sw doesn't use this, [[#SubmitControlInRequest]] is used instead. | | Official sw doesn't use this, [[#SubmitControlInRequest]] is used instead. |
| + | |
| + | == ResetDevice == |
| + | Takes an input u32, no output. Stubbed, just returns 0. |
| | | |
| == IClientIfSession == | | == IClientIfSession == |
Line 460: |
Line 398: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Cmd || Name |
| |- | | |- |
− | | 0 || || No input, returns an output handle. | + | | 0 || [[#GetStateChangeEvent]] |
| |- | | |- |
− | | 1 || [[#SetInterface]] || | + | | 1 || [[#SetInterface]] |
| |- | | |- |
− | | 2 || [[#GetInterface]] || | + | | 2 || [[#GetInterface]] |
| |- | | |- |
− | | 3 || [[#GetAlternateInterface]] || | + | | 3 || [[#GetAlternateInterface]] |
| |- | | |- |
− | | 4 [1.0.0] 5) || [[#GetCurrentFrame]] || | + | | 4 || [[#GetCurrentFrame]] ([1.0.0] [[#CtrlXferAsync]]) |
| |- | | |- |
− | | [2.0.0+] 5 || [[#CtrlXferAsync]] || | + | | 5 || [2.0.0+] [[#CtrlXferAsync]] |
| |- | | |- |
− | | 6 || ([1.0.0] [[#SubmitControlInRequest]]) || No input, returns an output handle. Signaled when [[#CtrlXferAsync]] finishes. | + | | 6 || [[#GetCtrlXferCompletionEvent]] ([1.0.0] [[#SubmitControlInRequest]]) |
| |- | | |- |
− | | 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]]) || | + | | 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]]) |
| |- | | |- |
− | | 8 || [[#ResetDevice]] || | + | | 8 || [[#ResetDevice]] |
| |- | | |- |
− | | 9 ([1.0.0] 4) || [[#OpenUsbEp]] || | + | | 9 || [[#OpenUsbEp]] ([1.0.0] [[#GetCurrentFrame]]) |
| |} | | |} |
| | | |
Line 486: |
Line 424: |
| | | |
| Immediately after opening the session, official sw uses cmd0 and cmd6. | | Immediately after opening the session, official sw uses cmd0 and cmd6. |
| + | |
| + | === GetStateChangeEvent === |
| + | No input, returns an output handle. |
| | | |
| === SetInterface === | | === SetInterface === |
− | Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]]. | + | Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]]. |
| | | |
| === GetInterface === | | === GetInterface === |
− | Takes a type-0x6 output buffer, no output. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]]. | + | Takes a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]]. |
| | | |
| === GetAlternateInterface === | | === GetAlternateInterface === |
− | Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]]. The buffer size must match 0x1B8. | + | Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]]. The buffer size must match 0x1B8. |
| | | |
| === GetCurrentFrame === | | === GetCurrentFrame === |
Line 503: |
Line 444: |
| === CtrlXferAsync === | | === CtrlXferAsync === |
| Takes 2 input u8s ('''bmRequestType''' and '''bRequest'''), 3 input u16s ('''wValue''', '''wIndex''', and '''wLength'''), and an input u64 '''buffer''', no output. | | Takes 2 input u8s ('''bmRequestType''' and '''bRequest'''), 3 input u16s ('''wValue''', '''wIndex''', and '''wLength'''), and an input u64 '''buffer''', no output. |
| + | |
| + | === GetCtrlXferCompletionEvent === |
| + | No input, returns an output handle. Signaled when [[#CtrlXferAsync]] finishes. |
| | | |
| === GetCtrlXferReport === | | === GetCtrlXferReport === |
Line 540: |
Line 484: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Cmd || Name |
| |- | | |- |
− | | 0 || [[#Open]] ([1.0.0] [[#SubmitOutRequest]]) || | + | | 0 || [[#ReOpen]] ([1.0.0] [[#SubmitOutRequest]]) |
| |- | | |- |
− | | 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]]) || | + | | 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]]) |
| |- | | |- |
− | | 2 || || No input, returns an output handle. Signaled when [[#PostBufferAsync_2|#PostBufferAsync]] finishes. ([1.0.0] [[#Open]]) | + | | 2 || [[#GetCompletionEvent_2|GetCompletionEvent]] ([1.0.0] Reset) |
| |- | | |- |
− | | 3 || [[#Populate]] ([1.0.0] [[#Close]]) || | + | | 3 || [[#PopulateRing]] ([1.0.0] [[#Close]]) |
| |- | | |- |
− | | [2.0.0+] 4 || [[#PostBufferAsync_2|#PostBufferAsync]] || | + | | 4 || [2.0.0+] [[#PostBufferAsync_2|#PostBufferAsync]] |
| |- | | |- |
− | | [2.0.0+] 5 || [[#GetXferReport]] || | + | | 5 || [2.0.0+] [[#GetXferReport]] |
| |- | | |- |
− | | [2.0.0+] 6 || || Takes 3 input u32s, 2 input u64s, and a type-0x5 input buffer, returns an output u32. | + | | 6 || [2.0.0+] [[#BatchBufferAsync]] |
| |- | | |- |
− | | [4.0.0+] 7 || || | + | | 7 || [4.0.0+] [[#CreateSmmuSpace]] |
| |- | | |- |
− | | [4.0.0+] 8 || || | + | | 8 || [4.0.0+] [[#ShareReportRing]] |
| |} | | |} |
| | | |
Line 575: |
Line 519: |
| Official user-processes uses a buffer where the buffer address/size is page-aligned, where '''size''' is the original size before alignment. The user-process also flushes dcache for this buffer using '''size''', before/after using this command. Official sw passes value 0 for '''unk'''. | | Official user-processes uses a buffer where the buffer address/size is page-aligned, where '''size''' is the original size before alignment. The user-process also flushes dcache for this buffer using '''size''', before/after using this command. Official sw passes value 0 for '''unk'''. |
| | | |
− | ==== Open ==== | + | ==== ReOpen ==== |
| No input/output. | | No input/output. |
| | | |
| This is similar to [[#OpenUsbEp]] with the params being loaded from state instead. | | This is similar to [[#OpenUsbEp]] with the params being loaded from state instead. |
| | | |
− | This is likely intended for re-opening after [[#Close]] was used, but this is not known to be used by any official user-processes. | + | This is for re-opening after [[#Close]] was used. |
| | | |
| ==== Close ==== | | ==== Close ==== |
| No input/output. | | No input/output. |
| | | |
− | Used by official sw prior to closing the endpoint session. | + | Used by official sw prior to closing the endpoint session. The func for this is also called automatically by the sysmodule during the IClientEpSession dtor. |
| | | |
− | ==== Populate ==== | + | ==== GetCompletionEvent ==== |
| + | No input, returns an output handle. Signaled when [[#PostBufferAsync_2|#PostBufferAsync]] finishes. ([1.0.0] [[#Open]]) |
| + | |
| + | ==== PopulateRing ==== |
| No input/output. | | No input/output. |
| | | |
Line 593: |
Line 540: |
| | | |
| ==== PostBufferAsync ==== | | ==== PostBufferAsync ==== |
− | Takes an input u32 '''size''', an input u64 '''buffer''', and an input u64, returns an output u32 '''xferId'''. | + | Takes an input u32 '''size''', an input u64 '''buffer''', and an input u64 '''Id''', returns an output u32 '''xferId'''. |
| | | |
− | HID-sysmodule passes value 0 for the last u64.
| + | Starts a data transfer with a single urb. |
| + | |
| + | The official sw func which uses this cmd and handles waiting on the Event passes value 0 for the '''Id'''. The async version which exposes this cmd directly uses '''Id''' from user input - the user funcs pass a value starting at 0 then increment it each time (for sending multiple requests at once, with 0 for the first request in this set of requests). Note that '''Id''' can be arbitrary, the sysmodule doesn't require a certain range for this. |
| + | |
| + | On newer sysvers the state fields setup by [[#CreateSmmuSpace]] are compared with '''buffer'''. If it's within bounds of the SmmuSpace (which won't be the case when [[#CreateSmmuSpace]] wasn't used), it will then verify that buffer+buffer_size is within bounds throwing an error otherwise. Note that a buffer from [[#CreateSmmuSpace]] can't be reused by another endpoint with PostBufferAsync. |
| | | |
| ==== GetXferReport ==== | | ==== GetXferReport ==== |
− | Takes an input u32 and a type-0x6 output buffer, returns an output u32 '''count'''. | + | Takes an input u32 and a type-0x6 ([3.0.0+] type-0x22) output buffer, returns an output u32 '''count'''. |
| | | |
| The input u32 specifies the total number of entries to read, this must fit within the specified buffer size. The output u32 is the total actual output entries. | | The input u32 specifies the total number of entries to read, this must fit within the specified buffer size. The output u32 is the total actual output entries. |
Line 604: |
Line 555: |
| The buffer contains an array of [[#XferReport]]. | | The buffer contains an array of [[#XferReport]]. |
| | | |
− | = UsbHsInterface = | + | On newer sysvers this runs code which is the same as the user-process code handling the tmem from [[#ShareReportRing]]. This cmd can handle getting reports from that tmem as well, however normally user-processes would just access the tmem [[#ShareReportRing|directly]]. |
| + | |
| + | ==== BatchBufferAsync ==== |
| + | Takes 3 input u32s ('''urbCount''', '''unk1''', and '''unk2'''), an input u64 '''buffer''' and u64 '''Id''', and a type-0x5 ([3.0.0+] type-0x21) input buffer, returns an output u32 '''xferId'''. |
| + | |
| + | Where '''Id''' is the same as [[#PostBufferAsync_2|#PostBufferAsync]]. |
| + | |
| + | This uses the same func internally as [[#PostBufferAsync_2|#PostBufferAsync]] except multiple urbs are specified by the user: the input buffer contains an array of u32s for the size of each urb, where '''urbCount''' is the total number of entries in this array. With [[#PostBufferAsync_2|#PostBufferAsync]] the last 2 params passed to the internal func are hard-coded to 0, while with this command it's '''unk1''' and '''unk2'''. |
| + | |
| + | ==== CreateSmmuSpace ==== |
| + | Takes an input u32 '''size''' and an u64 '''buffer''', no output. |
| + | |
| + | This validates that both input params are page-aligned. Official user-processes also validate this. |
| + | |
| + | This maps the specified buffer as devicemem and stores the fields for this in object state. If this was already used with this IClientEpSession object, an error is thrown. |
| + | |
| + | ==== ShareReportRing ==== |
| + | Takes an input u32 '''size''' and an input TransferMemory handle, no output. |
| + | |
| + | Official user-processes create the TransferMemory with permissions=RW. This validates that the input size is page-aligned, and this is also validated against data from state. Official user-processes also do this same validation. |
| + | |
| + | When this was used, official user-processes read data from this TransferMemory buffer instead of using [[#GetXferReport]]. |
| + | |
| + | This maps a TransferMemory buffer which is used for the [[#XferReport]] Ring, replacing the heap Ring buffer which was setup during [[#PopulateRing]]. |
| + | |
| + | Structure of the tmem: |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x8 || Write index |
| + | |- |
| + | | 0x8 || 0x8 || Read index |
| + | |- |
| + | | 0x10 || 0x18*count || Array of [[#XferReport]] |
| + | |} |
| + | |
| + | write_index!=read_index indicates that report data is available. The index fields are updated with: <code>index = index+1 % count;</code> write_index is updated by sysmodule, read_index is updated by the user-process. If the index field being used is >=count, this will Abort. |
| + | |
| + | = usb:pd = |
| + | This is "nn::usb::pd::detail::IPdManager". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#OpenSession]] |
| + | |} |
| + | |
| + | Only system-titles with access to this are [[PTM_services|ptm]] and [[AM_services|am]]. |
| + | |
| + | == OpenSession == |
| + | No input. Returns an [[#IPdSession]]. |
| + | |
| + | == IPdSession == |
| + | This is "nn::usb::pd::detail::IPdSession". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || BindNoticeEvent |
| + | |- |
| + | | 1 || UnbindNoticeEvent |
| + | |- |
| + | | 2 || GetStatus |
| + | |- |
| + | | 3 || GetNotice |
| + | |- |
| + | | 4 || EnablePowerRequestNotice |
| + | |- |
| + | | 5 || DisablePowerRequestNotice |
| + | |- |
| + | | 6 || ReplyPowerRequest |
| + | |} |
| + | |
| + | = usb:pd:c = |
| + | This is "nn::usb::pd::detail::IPdCradleManager". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#OpenCradleSession]] |
| + | |} |
| + | |
| + | USB-sysmodule symbols for this refer to "Cradle", which is the [[Dock]]. |
| + | |
| + | == OpenCradleSession == |
| + | No input. Returns an [[#IPdCradleSession]]. |
| + | |
| + | == IPdCradleSession == |
| + | This is "nn::usb::pd::detail::IPdCradleSession". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#SetCradleVdo]] |
| + | |- |
| + | | 1 || [[#GetCradleVdo]] |
| + | |- |
| + | | 2 || [[#ResetCradleUsbHub]] |
| + | |- |
| + | | 3 || [2.0.0+] [[#GetHostPdcFirmwareType]] |
| + | |- |
| + | | 4 || [2.0.0+] [[#GetHostPdcFirmwareRevision]] |
| + | |- |
| + | | 5 || [2.0.0+] [[#GetHostPdcManufactureId]] |
| + | |- |
| + | | 6 || [2.0.0+] [[#GetHostPdcDeviceId]] |
| + | |- |
| + | | 7 || [3.0.0+] [[#EnableCradleRecovery]] |
| + | |- |
| + | | 8 || [3.0.0+] [[#DisableCradleRecovery]] |
| + | |} |
| + | |
| + | === SetCradleVdo === |
| + | Takes an input u32 '''Value''' and a [[#CradleVdmCommand]]. No output. |
| + | |
| + | [[#CradleVdmCommand]] is translated to the actual [[#VdmCommand]] to send. |
| + | |
| + | === GetCradleVdo === |
| + | Takes an input [[#CradleVdmCommand]]. Returns an u32 '''Value'''. |
| + | |
| + | [[#CradleVdmCommand]] is translated to the actual [[#VdmCommand]] to send. |
| + | |
| + | === ResetCradleUsbHub === |
| + | No input/output. |
| + | |
| + | Sends [[#VdmCommand|VdmCommands]] 32 and 30. |
| + | |
| + | === GetHostPdcFirmwareType === |
| + | No input. Returns an output u16. |
| + | |
| + | === GetHostPdcFirmwareRevision === |
| + | No input. Returns an output u16. |
| + | |
| + | === GetHostPdcManufactureId === |
| + | No input. Returns an output u16. |
| + | |
| + | === GetHostPdcDeviceId === |
| + | No input. Returns an output u16. |
| + | |
| + | === EnableCradleRecovery === |
| + | No input. Returns an output u8. |
| + | |
| + | === DisableCradleRecovery === |
| + | No input. Returns an output u8. |
| + | |
| + | = usb:pd:m = |
| + | This is "nn::usb::pd::detail::IPdManufactureManager". |
| + | |
| + | [2.0.0+] This service was merged into [[#usb:pd:c|usb:pd:c]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#OpenManufactureSession]] |
| + | |} |
| + | |
| + | == OpenManufactureSession == |
| + | No input. Returns an [[#IPdManufactureSession]]. |
| + | |
| + | == IPdManufactureSession == |
| + | This is "nn::usb::pd::detail::IPdManufactureSession". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#GetHostPdcFirmwareType]] |
| + | |- |
| + | | 1 || [[#GetHostPdcFirmwareRevision]] |
| + | |- |
| + | | 2 || [[#GetHostPdcManufactureId]] |
| + | |- |
| + | | 3 || [[#GetHostPdcDeviceId]] |
| + | |} |
| + | |
| + | = usb:pm = |
| + | This is "nn::usb::pm::IPmService". |
| + | |
| + | [8.0.0+] This is "nn::usb::pm::IPmMainService". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#GetPowerEvent|GetPowerEvent]] |
| + | |- |
| + | | 1 || [[#GetPowerState|GetPowerState]] |
| + | |- |
| + | | 2 || [[#GetDataEvent|GetDataEvent]] |
| + | |- |
| + | | 3 || [[#GetDataRole|GetDataRole]] |
| + | |- |
| + | | 4 || [[#SetDiagData|SetDiagData]] |
| + | |- |
| + | | 5 || [[#GetDiagData|GetDiagData]] |
| + | |} |
| + | |
| + | USB Port Manager, only system-title using this is [[PTM_services|ptm]]. |
| + | |
| + | == GetPowerEvent == |
| + | No input. Returns an output Event handle. |
| + | |
| + | == GetPowerState == |
| + | Takes a type-0x6 output buffer containing an [[#UsbPowerState]]. No output. |
| + | |
| + | == GetDataEvent == |
| + | No input. Returns an output Event handle. |
| + | |
| + | == GetDataRole == |
| + | No input. Returns an output [[#UsbDataRole]]. |
| + | |
| + | == SetDiagData == |
| + | Takes two input u32s. No output. |
| + | |
| + | [8.0.0+] Stubbed, just returns 0. |
| + | |
| + | == GetDiagData == |
| + | Takes an input u32. Returns an output u32. |
| + | |
| + | [8.0.0+] Stubbed, just returns 0. |
| + | |
| + | = usb:qdb = |
| + | This is "nn::usb::qdb::IQdbManager". |
| + | |
| + | This was added with [7.0.0+]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || [[#ImportQuirkDevices]] |
| + | |- |
| + | | 1 || [[#HasQuirk]] |
| + | |} |
| + | |
| + | == ImportQuirkDevices == |
| + | No input/output, takes a type-0x5 input buffer. |
| + | |
| + | This loads data for [[#HidGamepad]] with the input .json. |
| + | |
| + | == HasQuirk == |
| + | Takes 6-bytes of input (u16s '''vid''', '''pid''', '''bcdDevice''') and a type-0x5 input buffer, returns an output u8 bool indicating success. |
| + | |
| + | Locates an entry in the [[#HidGamepad]] state with the input u16s, and checks for a '''quirks''' array entry where '''name''' matches the input buffer string. Returns 1 when found, 0 otherwise. |
| + | |
| + | = usb:obsv = |
| + | This is "nn::usb::pm::IPmObserverService". |
| + | |
| + | This was added with [8.0.0+]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Cmd || Name |
| + | |- |
| + | | 0 || GetTopologyChangeEvent |
| + | |- |
| + | | 1 || GetFlattenedTopology |
| + | |} |
| + | |
| + | = UsbInterfaceDescriptor = |
| + | This is "nn::usb::UsbInterfaceDescriptor". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x1 || bLength |
| + | |- |
| + | | 0x1 || 0x1 || bDescriptorType |
| + | |- |
| + | | 0x2 || 0x1 || bInterfaceNumber |
| + | |- |
| + | | 0x3 || 0x1 || bAlternateSetting |
| + | |- |
| + | | 0x4 || 0x1 || bNumEndpoints |
| + | |- |
| + | | 0x5 || 0x1 || bInterfaceClass |
| + | |- |
| + | | 0x6 || 0x1 || bInterfaceSubClass |
| + | |- |
| + | | 0x7 || 0x1 || bInterfaceProtocol |
| + | |- |
| + | | 0x8 || 0x1 || iInterface |
| + | |} |
| + | |
| + | = UsbStringDescriptor = |
| + | This is "nn::usb::UsbStringDescriptor". This is a string. |
| + | |
| + | = UsbEndpointDescriptor = |
| + | This is "nn::usb::UsbEndpointDescriptor". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x1 || bLength |
| + | |- |
| + | | 0x1 || 0x1 || bDescriptorType |
| + | |- |
| + | | 0x2 || 0x1 || bEndpointAddress |
| + | |- |
| + | | 0x3 || 0x1 || bmAttributes |
| + | |- |
| + | | 0x4 || 0x2 || wMaxPacketSize |
| + | |- |
| + | | 0x6 || 0x1 || bInterval |
| + | |- |
| + | | 0x7 || 0x1 || bRefresh |
| + | |- |
| + | | 0x8 || 0x1 || bSynchAddress |
| + | |} |
| + | |
| + | = UsbState = |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value || Name || Description |
| + | |- |
| + | | 0 || Detached || Device is not attached to USB. |
| + | |- |
| + | | 1 || Attached || Device is attached, but is not powered. |
| + | |- |
| + | | 2 || Powered || Device is attached and powered, but has not been reset. |
| + | |- |
| + | | 3 || Default || Device is attached, powered, and has been reset, but does not have an address. |
| + | |- |
| + | | 4 || Address || Device is attached, powered, has been reset, has an address, but is not configured. |
| + | |- |
| + | | 5 || Configured || Device is attached, powered, has been reset, has an address, configured, and may be used. |
| + | |- |
| + | | 6 || Suspended || Device is attached and powered, but has not seen bus activity for 3ms. Device is suspended and cannot be used. |
| + | |} |
| + | |
| + | = UsbVidPidBcd = |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x2 || Vid (idVendor) |
| + | |- |
| + | | 0x2 || 0x2 || Pid (idProduct) |
| + | |- |
| + | | 0x4 || 0x2 || bcdDevice |
| + | |- |
| + | | 0x6 || 0x20 || Manufacturer (ASCII string padded to 0x20 bytes) |
| + | |- |
| + | | 0x26 || 0x20 || Product (ASCII string padded to 0x20 bytes) |
| + | |- |
| + | | 0x46 || 0x20 || SerialNumber (ASCII string padded to 0x20 bytes) |
| + | |} |
| + | |
| + | = UrbReport = |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x10 * 8 || Array of [[#UrbReportEntry]] |
| + | |- |
| + | | 0x80 || 0x4 || ReportEntryCount |
| + | |} |
| + | |
| + | = UrbReportEntry = |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x4 || Id |
| + | |- |
| + | | 0x4 || 0x4 || RequestedSize |
| + | |- |
| + | | 0x8 || 0x4 || TransferredSize |
| + | |- |
| + | | 0xC || 0x4 || Status (converted to error-codes: 0x3 = success, 0x4 = 0x828c, 0x5 = 0x748c; all other values are invalid) |
| + | |} |
| + | |
| + | = UsbDeviceSpeed = |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value || Name |
| + | |- |
| + | | 0 || None |
| + | |- |
| + | | 1 || Low |
| + | |- |
| + | | 2 || Full |
| + | |- |
| + | | 3 || High |
| + | |- |
| + | | 4 || Super |
| + | |} |
| + | |
| + | = InterfaceQueryOutput = |
| + | This is "nn::usb::InterfaceQueryOutput". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset || Size || Description |
| + | |- |
| + | | 0x0 || 0x1B8 || [[#InterfaceProfile|InterfaceProfile]] |
| + | |- |
| + | | 0x1B8 || 0x40 || "HsDevice-/L<unk0>/P<portnum>/A<unk1>" string (this is "FsDevice..." for the Dock USB 3.0 bus). |
| + | |- |
| + | | 0x1F8 || 0x4 || busID |
| + | |- |
| + | | 0x1FC || 0x4 || deviceID |
| + | |- |
| + | | 0x200 || 0x12+0x9(0x1B) || usb_device_descriptor, then usb_config_descriptor immediately afterwards. |
| + | |- |
| + | | 0x21B || 0x5 || Padding |
| + | |- |
| + | | 0x220 || 0x8 || Unknown u64 timestamp for when the device was inserted? |
| + | |} |
| + | |
| + | The INPUT/OUTPUT endpoint descriptors (usb_endpoint_descriptors/usb_ss_endpoint_companion_descriptors) were swapped with [8.0.0+] (above layout has the pre-8.0.0 layout), however the sysmodule code which writes this output struct was basically unchanged. |
| + | |
| + | = InterfaceProfile = |
| + | This is "nn::usb::InterfaceProfile". |
| + | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 634: |
Line 1,008: |
| |- | | |- |
| | 0x1B5 || 0x3 || Padding | | | 0x1B5 || 0x3 || Padding |
− | |-
| |
− | | 0x1B8 || 0x40 || "HsDevice-/L<unk0>/P<portnum>/A<unk1>" string (this is "FsDevice..." for the Dock USB 3.0 bus).
| |
− | |-
| |
− | | 0x1F8 || 0x4 || busID
| |
− | |-
| |
− | | 0x1FC || 0x4 || deviceID
| |
− | |-
| |
− | | 0x200 || 0x12+0x9(0x1B) || usb_device_descriptor, then usb_config_descriptor immediately afterwards.
| |
− | |-
| |
− | | 0x21B || 0x5 || Padding
| |
− | |-
| |
− | | 0x220 || 0x8 || Unknown u64 timestamp for when the device was inserted?
| |
| |} | | |} |
| | | |
− | This is a 0x228-byte struct (unofficial name). | + | = DeviceFilter = |
| + | This is "nn::usb::DeviceFilter". |
| | | |
− | = UsbHsInterfaceFilter =
| |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 678: |
Line 1,040: |
| |} | | |} |
| | | |
− | This is a 0x10-byte struct (unofficial name). | + | This is used to filter [[#InterfaceQueryOutput]], the query commands will only return the interface when these checks pass. This is also used for events with [[#CreateInterfaceAvailableEvent]]. When a bit in Flags is set, the associated descriptor field and the field in this struct are compared, on mismatch the interface will be filtered out. Passing Flags=0 is equivalent to disabling filtering since none of these checks will run. |
| | | |
− | This is used to filter [[#UsbHsInterface]], the query commands will only return the interface when these checks pass. This is also used for events with [[#CreateInterfaceAvailableEvent]]. When a bit in Flags is set, the associated descriptor field and the field in this struct are compared, on mismatch the interface will be filtered out. Passing Flags=0 is equivalent to disabling filtering since none of these checks will run.
| + | [7.0.0+]: The filter struct has to be unique, it can't match any existing filter structs used by [[#CreateInterfaceAvailableEvent]] (including other processes). Hence, Flags has to be non-zero. When initialized with usb:hs:a and VID and/or PID filtering is enabled, the VID/PID will be checked [[#HidGamepad]], with an error being throw if a matching device is found with quirk "ApplicationBlacklist" ([[#usb:qdb|usb:qdb]] cmd1 is used internally for this with bcdDevice=0). |
| | | |
| Flags bits 0..6 use usb_device_descriptor, while 7..9 use usb_interface_descriptor. Support for bits 2..6 and the associated fields was added with [6.0.0+]. | | Flags bits 0..6 use usb_device_descriptor, while 7..9 use usb_interface_descriptor. Support for bits 2..6 and the associated fields was added with [6.0.0+]. |
Line 711: |
Line 1,073: |
| | 0xC || 0x4 || transferredSize | | | 0xC || 0x4 || transferredSize |
| |- | | |- |
− | | 0x10 || 0x8? || ? | + | | 0x10 || 0x8 || [[#PostBufferAsync_2|Id]] |
| |} | | |} |
| | | |
Line 718: |
Line 1,080: |
| Official sw only uses the Result/size fields. | | Official sw only uses the Result/size fields. |
| | | |
− | = usb:pd = | + | = CradleVdmCommand = |
− | This is "nn::usb::pd::detail::IPdManager". | + | This is "nn::usb::pd::CradleVdmCommand". |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name | + | ! Value || Name |
| + | |- |
| + | | 0 || |
| + | |- |
| + | | 1 || |
| + | |- |
| + | | 2 || |
| + | |- |
| + | | 3 || |
| + | |- |
| + | | 4 || |
| + | |- |
| + | | 5 || |
| + | |- |
| + | | 6 || |
| + | |- |
| + | | 7 || |
| + | |- |
| + | | 8 || |
| + | |- |
| + | | 9 || |
| |- | | |- |
− | | 0 || GetPdSession | + | | 10 || |
| |} | | |} |
| | | |
− | Only system-titles with access to this are [[PTM_services|ptm]] and [[AM_services|am]].
| + | = VdmCommand = |
| + | This is "nn::usb::pd::driver::detail::VdmCommand". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value || [[#CradleVdmCommand|CradleVdmCommand]] || [[#VdmCommandType|VdmCommandType]] || VdmCommandLength || Name |
| + | |- |
| + | | 0 || - || -1 || 0 || None |
| + | |- |
| + | | 1 || 0 || 0 || 3 || LedControlRequest |
| + | |- |
| + | | 2 || - || 1 || 3 || LedControlReply |
| + | |- |
| + | | 3 || 10 || 0 || 3 || DeviceTypeRequest |
| + | |- |
| + | | 4 || - || 1 || 3 || DeviceTypeReply |
| + | |- |
| + | | 5 || - || -1 || 0 || UsbPowerErrorNotice |
| + | |- |
| + | | 6 || 1 || 0 || 2 || Dp2HdmiFwVerRequest |
| + | |- |
| + | | 7 || - || 1 || 3 || Dp2HdmiFwVerReply |
| + | |- |
| + | | 8 || - || -1 || 0 || Dp2HdmiFwUpdateRequest |
| + | |- |
| + | | 9 || - || -1 || 0 || Dp2HdmiFwUpdateReply |
| + | |- |
| + | | 10 || - || -1 || 0 || Dp2HdmiFwUpdateNotice |
| + | |- |
| + | | 11 || 2 || 0 || 2 || PdcHFwVerRequest |
| + | |- |
| + | | 12 || - || 1 || 3 || PdcHFwVerReply |
| + | |- |
| + | | 13 || - || -1 || 0 || PdcHFwUpdateRequest |
| + | |- |
| + | | 14 || - || -1 || 0 || PdcHFwUpdateReply |
| + | |- |
| + | | 15 || - || -1 || 0 || PdcHFwUpdateNotice |
| + | |- |
| + | | 16 || 3 || 0 || 2 || PdcAFwVerRequest |
| + | |- |
| + | | 17 || - || 1 || 3 || PdcAFwVerReply |
| + | |- |
| + | | 18 || - || -1 || 0 || PdcAFwUpdateRequest |
| + | |- |
| + | | 19 || - || -1 || 0 || PdcAFwUpdateReply |
| + | |- |
| + | | 20 || - || -1 || 0 || PdcAFwUpdateNotice |
| + | |- |
| + | | 21 || - || 0 || 3 || DeviceErrorNotice |
| + | |- |
| + | | 22 || 4 || 0 || 2 || DeviceStateRequest |
| + | |- |
| + | | 23 || - || 1 || 3 || DeviceStateReply |
| + | |- |
| + | | 24 || 5 || 0 || 2 || McuFwVerRequest |
| + | |- |
| + | | 25 || - || 1 || 3 || McuFwVerReply |
| + | |- |
| + | | 26 || 6 || 0 || 2 || McuFwUpdateRequest |
| + | |- |
| + | | 27 || - || 1 || 2 || McuFwUpdateReply |
| + | |- |
| + | | 28 || 7 || 0 || 2 || UsbHubSleepRequest |
| + | |- |
| + | | 29 || - || 1 || 2 || UsbHubSleepReply |
| + | |- |
| + | | 30 || 8 || 0 || 2 || UsbHubResetRequest |
| + | |- |
| + | | 31 || - || 1 || 2 || UsbHubResetReply |
| + | |- |
| + | | 32 || 9 || 0 || 2 || UsbHubControlRequest |
| + | |- |
| + | | 33 || - || 1 || 2 || UsbHubControlReply |
| + | |} |
| | | |
− | == IPdSession == | + | = VdmCommandType = |
− | This is "nn::usb::pd::detail::IPdSession". | + | This is "nn::usb::pd::driver::detail::VdmCommandType". |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name | + | ! Value || Name |
| + | |- |
| + | | -1 || None |
| + | |- |
| + | | 0 || Initiator |
| + | |- |
| + | | 1 || Ack |
| + | |- |
| + | | 2 || Nak |
| + | |- |
| + | | 3 || Busy |
| + | |} |
| + | |
| + | = UsbPowerState = |
| + | This is "nn::usb::UsbPowerState". |
| + | |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | 0 || BindNoticeEvent | + | ! Offset || Size || Description |
| |- | | |- |
− | | 1 || UnbindNoticeEvent | + | | 0x0 || 0x4 || [[#UsbPowerRole|UsbPowerRole]] |
| |- | | |- |
− | | 2 || GetStatus | + | | 0x4 || 0x4 || [[#UsbChargerType|UsbChargerType]] |
| |- | | |- |
− | | 3 || GetNotice | + | | 0x8 || 0x4 || Voltage |
| |- | | |- |
− | | 4 || EnablePowerRequestNotice | + | | 0xC || 0x4 || Current |
| |- | | |- |
− | | 5 || DisablePowerRequestNotice | + | | 0x10 || 0x4 || [[#Pdo|Pdo]] |
| |- | | |- |
− | | 6 || ReplyPowerRequest | + | | 0x14 || 0x4 || [[#Rdo|Rdo]] |
| |} | | |} |
| | | |
− | = usb:pd:c = | + | = UsbPowerRole = |
− | This is "nn::usb::pd::detail::IPdCradleManager". | + | This is "nn::usb::UsbPowerRole". |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Value || Name |
| |- | | |- |
− | | 0 || GetPdCradleSession || Returns a session handle for the below. | + | | 0 || Unknown |
| + | |- |
| + | | 1 || Sink |
| + | |- |
| + | | 2 || Source |
| |} | | |} |
| | | |
− | USB-sysmodule symbols for this refer to "Cradle", which is the [[Dock]].
| + | = UsbChargerType = |
− | | + | This is "nn::usb::UsbChargerType". |
− | == IPdCradleSession ==
| |
− | This is "nn::usb::pd::detail::IPdCradleSession". | |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Cmd || Name || Notes | + | ! Value || Name |
| + | |- |
| + | | 0 || Unknown |
| |- | | |- |
− | | 0 || VdmUserWrite || Input { u32 value; u32 VdmUserId; }. Output {}. | + | | 1 || Pd |
− | If Cradle or RelayBox is connected, issues given VDM with value.
| |
| |- | | |- |
− | | 1 || VdmUserRead || Input { u32 VdmUserId; }. Output { u32 value; }. | + | | 2 || TypeC15 |
− | If Cradle or RelayBox is connected, returns u32 response from issuing given VDM.
| |
| |- | | |- |
− | | 2 || Vdm20Init || No input/output. | + | | 3 || TypeC30 |
− | If Cradle or RelayBox is connected, caches result of VDM 0x20.
| |
| |- | | |- |
− | | 3 || [2.0.0+] GetFwType || No input. Returns an output u16. | + | | 4 || Dcp |
| |- | | |- |
− | | 4 || [2.0.0+] GetFwRevision || No input. Returns an output u16. | + | | 5 || Cdp |
| |- | | |- |
− | | 5 || [2.0.0+] GetManufacturerId || No input. Returns an output u16. | + | | 6 || Sdp |
| |- | | |- |
− | | 6 || [2.0.0+] GetDeviceId || No input. Returns an output u16. | + | | 7 || Apple500 |
| |- | | |- |
− | | 7 || [3.0.0+] || | + | | 8 || Apple1000 |
| |- | | |- |
− | | 8 || [3.0.0+] || | + | | 9 || Apple2000 |
| |} | | |} |
| | | |
− | Note: The VdmUserId given to VdmUserRead/VdmUserWrite is translated from the given (enum) value to the actual cmd to send.
| + | = SupplyType = |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value || Name |
| + | |- |
| + | | 0 || Fixed |
| + | |- |
| + | | 1 || Battery |
| + | |- |
| + | | 2 || Variable |
| + | |} |
| | | |
− | = usb:pd:m = | + | = Pdo = |
− | This is "nn::usb::pd::detail::IPdManufactureManager". This is only available on 1.0.0.
| + | When [[#SupplyType|SupplyType]] is Fixed this is: |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-9 |
| + | | MaximumCurrent |
| + | |- |
| + | | 10-19 |
| + | | Voltage |
| + | |- |
| + | | 20-21 |
| + | | PeakCurrent |
| + | |- |
| + | | 22-24 |
| + | | Reserved |
| + | |- |
| + | | 25 |
| + | | DataRoleSwap |
| + | |- |
| + | | 26 |
| + | | UsbCommunicationsCapable |
| + | |- |
| + | | 27 |
| + | | ExternallyPowered |
| + | |- |
| + | | 28 |
| + | | UsbSuspendSupported |
| + | |- |
| + | | 29 |
| + | | DualRolePower |
| + | |- |
| + | | 30-31 |
| + | | [[#SupplyType|SupplyType]] |
| + | |} |
| | | |
| + | When [[#SupplyType|SupplyType]] is Battery this is: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| |- | | |- |
− | ! Cmd || Name || Notes
| + | | 0-9 |
| + | | MaximumAllowablePower |
| |- | | |- |
− | | 0 || || No input, returns an [[#IPdManufactureSession]]. | + | | 10-19 |
| + | | MinimumVoltage |
| + | |- |
| + | | 20-29 |
| + | | MaximumVoltage |
| + | |- |
| + | | 30-31 |
| + | | [[#SupplyType|SupplyType]] |
| |} | | |} |
| | | |
− | == IPdManufactureSession == | + | When [[#SupplyType|SupplyType]] is Variable this is: |
− | This is "nn::usb::pd::detail::IPdManufactureSession".
| + | {| class="wikitable" border="1" |
− | | + | ! Bits |
− | These commands just load the u16 from global state.
| + | ! Description |
| + | |- |
| + | | 0-9 |
| + | | MaximumCurrent |
| + | |- |
| + | | 10-19 |
| + | | MinimumVoltage |
| + | |- |
| + | | 20-29 |
| + | | MaximumVoltage |
| + | |- |
| + | | 30-31 |
| + | | [[#SupplyType|SupplyType]] |
| + | |} |
| | | |
| + | = Rdo = |
| + | When Pdo's [[#SupplyType|SupplyType]] is Fixed or Variable this is: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-9 |
| + | | MaximumOperatingCurrent (GiveBackFlag is true) or MinimumOperatingCurrent (GiveBackFlag is false) |
| + | |- |
| + | | 10-19 |
| + | | OperatingCurrent |
| + | |- |
| + | | 20-23 |
| + | | Reserved |
| |- | | |- |
− | ! Cmd || Name || Notes
| + | | 24 |
| + | | NoUsbSuspend |
| |- | | |- |
− | | 0 || || No input, returns an output u16. | + | | 25 |
| + | | UsbCommunicationsCapable |
| |- | | |- |
− | | 1 || || No input, returns an output u16. | + | | 26 |
| + | | CapabilityMismatch |
| |- | | |- |
− | | 2 || || No input, returns an output u16. | + | | 27 |
| + | | GiveBackFlag |
| |- | | |- |
− | | 3 || || No input, returns an output u16. | + | | 28-30 |
| + | | ObjectPosition |
| |- | | |- |
| + | | 31 |
| + | | Reserved |
| |} | | |} |
| | | |
− | = usb:pm =
| + | When Pdo's [[#SupplyType|SupplyType]] is Battery this is: |
− | This is "nn::usb::pm::IPmService".
| |
− | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| |- | | |- |
− | ! Cmd || Name
| + | | 0-9 |
| + | | MaximumOperatingPower (GiveBackFlag is true) or MinimumOperatingPower (GiveBackFlag is false) |
| + | |- |
| + | | 10-19 |
| + | | OperatingPower |
| + | |- |
| + | | 20-23 |
| + | | Reserved |
| |- | | |- |
− | | 0 || | + | | 24 |
| + | | NoUsbSuspend |
| |- | | |- |
− | | 1 || | + | | 25 |
| + | | UsbCommunicationsCapable |
| |- | | |- |
− | | 2 || | + | | 26 |
| + | | CapabilityMismatch |
| |- | | |- |
− | | 3 || | + | | 27 |
| + | | GiveBackFlag |
| |- | | |- |
− | | 4 || | + | | 28-30 |
| + | | ObjectPosition |
| |- | | |- |
− | | 5 || | + | | 31 |
| + | | Reserved |
| |} | | |} |
| | | |
− | USB Port Manager, only system-title using this is [[PTM_services|ptm]]. | + | = UsbDataRole = |
| + | This is "nn::usb::UsbDataRole". |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value || Name |
| + | |- |
| + | | 0 || Unknown |
| + | |- |
| + | | 1 || DFP |
| + | |- |
| + | | 2 || UFP |
| + | |} |
| + | |
| + | = HidGamepad = |
| + | With [7.0.0+] usb-sysmodule now has .json data embedded in the codebin. |
| + | |
| + | This contains a list of USB devices' VID/PID, with the following structure: |
| + | |
| + | [ |
| + | { |
| + | "vid" : "<VID>", |
| + | "pid" : "<PID>", |
| + | "quirks" : [ |
| + | { |
| + | "name" : "<string>" //The .json has the following for <string> for various devices: "HidGamepadWhitelist", "ApplicationBlacklist", and "NoClearHaltOnEpInit". |
| + | } |
| + | //There can be multiple entries here. |
| + | ] |
| + | }, |
| + | <more entries> |
| + | ] |
| + | |
| + | [12.1.0+]: The following entries were added in this json, all of which have quirks set for "HidGamepadWhitelist". |
| + | ** vid "0F0D", where pid is "0200" - "022F". |
| + | ** vid "33DD", where pid is "0001" - "000B". |
| + | |
| + | = Configuration = |
| + | The following is the default USB config strings, while the usbds service isn't being used. All of the below configuration will reset to the defaults when all usbds-related sessions are closed. These can be set with [[#SetVidPidBcd]]. The default string for Product is loaded from [[Settings_services|settings]] config. The default is referred to by usb-sysmodule as "Dummy". |
| + | Product: Nintendo Switch |
| + | Manufacturer: Nintendo |
| + | SerialNumber: SerialNumber |
| + | |
| + | The following is the default <code>lsusb -v {...}</code> output when the usbds service wasn't used. |
| + | |
| + | pre-5.0.0: The endpoints are configured using [[#RegisterEndpoint]], the total number of endpoints is the number of open [[#IDsEndpoint]] sessions. bInterfaceNumber is {0-based index for the enabled [[#IDsInterface]] session.} Some of the interface fields are configured using [[#RegisterInterface]]. |
| + | |
| + | When usbds is in use where [[#SetVidPidBcd]] wasn't used, the VID/PID is 057e:3000. |
| + | |
| + | Bus 003 Device 006: ID 057e:2000 Nintendo Co., Ltd |
| + | Couldn't open device, some information will be missing |
| + | Device Descriptor: |
| + | bLength 18 |
| + | bDescriptorType 1 |
| + | bcdUSB 2.00 |
| + | bDeviceClass 0 (Defined at Interface level) |
| + | bDeviceSubClass 0 |
| + | bDeviceProtocol 0 |
| + | bMaxPacketSize0 64 |
| + | idVendor 0x057e Nintendo Co., Ltd |
| + | idProduct 0x2000 |
| + | bcdDevice 1.00 |
| + | iManufacturer 1 |
| + | iProduct 2 |
| + | iSerial 3 |
| + | bNumConfigurations 1 |
| + | Configuration Descriptor: |
| + | bLength 9 |
| + | bDescriptorType 2 |
| + | wTotalLength 34 |
| + | bNumInterfaces 1 |
| + | bConfigurationValue 1 |
| + | iConfiguration 0 |
| + | bmAttributes 0xc0 |
| + | Self Powered |
| + | MaxPower {...} |
| + | Interface Descriptor: |
| + | bLength 9 |
| + | bDescriptorType 4 |
| + | bInterfaceNumber 0 |
| + | bAlternateSetting 0 |
| + | bNumEndpoints 1 |
| + | bInterfaceClass 3 Human Interface Device |
| + | bInterfaceSubClass 0 No Subclass |
| + | bInterfaceProtocol 0 None |
| + | iInterface 0 |
| + | HID Device Descriptor: |
| + | bLength 9 |
| + | bDescriptorType 33 |
| + | bcdHID 2.00 |
| + | bCountryCode 0 Not supported |
| + | bNumDescriptors 1 |
| + | bDescriptorType 34 Report |
| + | wDescriptorLength 26 |
| + | Report Descriptors: |
| + | ** UNAVAILABLE ** |
| + | Endpoint Descriptor: |
| + | bLength 7 |
| + | bDescriptorType 5 |
| + | bEndpointAddress 0x81 EP 1 IN |
| + | bmAttributes 3 |
| + | Transfer Type Interrupt |
| + | Synch Type None |
| + | Usage Type Data |
| + | wMaxPacketSize 0x0001 1x 1 bytes |
| + | bInterval 16 |
| | | |
| [[Category:Services]] | | [[Category:Services]] |