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 =
| + | = Configuration = |
− | This is "nn::usb::ds::IDsRootSession".
| |
− | | |
− | Pre-11.0.0 this was [[#IDsService]].
| |
− | | |
− | 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 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.
| |
− | | |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! Cmd || Name
| |
− | |-
| |
− | | 0 || [[#OpenDsService]]
| |
− | |}
| |
− | | |
− | == OpenDsService ==
| |
− | Unofficial name.
| |
− | | |
− | No input. Returns an [[#IDsService]].
| |
− | | |
− | == IDsService ==
| |
− | This is "nn::usb::ds::IDsService".
| |
− | | |
− | Various cmds were updated/moved with [11.0.0+].
| |
− | | |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! Cmd || Name
| |
− | |-
| |
− | | 0 || [[#BindDevice]]
| |
− | |-
| |
− | | 1 || [[#BindClientProcess]]
| |
− | |-
| |
− | | 2 || [[#AddInterface]]
| |
− | |-
| |
− | | 3 || [[#GetStateChangeEvent]]
| |
− | |-
| |
− | | 4 || [[#GetState]]
| |
− | |-
| |
− | | [2.0.0-4.1.0] 5 || [[#SetVidPidBcd]]
| |
− | |-
| |
− | | [5.0.0+] 5 || ClearDeviceData
| |
− | |-
| |
− | | 6 || [5.0.0+] AddUsbStringDescriptor
| |
− | |-
| |
− | | 7 || [5.0.0+] DeleteUsbStringDescriptor
| |
− | |-
| |
− | | 8 || [5.0.0+] SetUsbDeviceDescriptor
| |
− | |-
| |
− | | 9 || [5.0.0+] SetBinaryObjectStore
| |
− | |-
| |
− | | 10 || [5.0.0+] Enable
| |
− | |-
| |
− | | 11 || [5.0.0+] Disable
| |
− | |-
| |
− | | 12 || [8.0.0+]
| |
− | |}
| |
− | | |
− | Initialization done by [[Manu Services|manu]]:
| |
− | * Initial service init:
| |
− | ** Get service/etc.
| |
− | ** Uses [[#BindDevice]].
| |
− | ** Uses [[#BindClientProcess]].
| |
− | ** Uses [[#GetStateChangeEvent]].
| |
− | ** Uses [[#SetVidPidBcd]].
| |
− | * Interface init:
| |
− | ** Uses [[#AddInterface]], then uses commands from that with the rest of the following.
| |
− | ** Uses [[#GetSetupEvent]].
| |
− | ** Uses [[#GetCtrlInCompletionEvent]].
| |
− | ** Uses [[#GetCtrlOutCompletionEvent]].
| |
− | * Initializes two endpoints via using [[#AddEndpoint]] twice.
| |
− | | |
− | == 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". | | 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 | | Product: Nintendo Switch |
Line 85: |
Line 9: |
| The following is the default <code>lsusb -v {...}</code> output when the usbds service wasn't used. | | 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 [[#AddEndpoint]], 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 [[#AddInterface]]. | + | 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. | | When usbds is in use where [[#SetVidPidBcd]] wasn't used, the VID/PID is 057e:3000. |
Line 147: |
Line 71: |
| bInterval 16 | | bInterval 16 |
| | | |
− | == BindDevice == | + | = usb:ds = |
− | Takes an u32 ('''complexId'''). [[Manu_Services|Manu]] sends 0x02.
| + | [1.0.0-10.2.0] This is "nn::usb::ds::IDsService". |
| | | |
− | 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.
| + | [11.0.0+] This is "nn::usb::ds::IDsRootSession". |
| | | |
− | Returns a not-found error when complexId isn't 0x02, for values 0x0-0x4 at least.
| + | This service is used during [[Factory Setup|factory setup]] by [[Manu Services|manu]]. This is also used by [[Capmtp_services|capmtp]]. |
| | | |
− | == BindClientProcess ==
| + | This service session is used as an IPC [[IPC_Marshalling|domain]] by [[Manu Services|manu]]. |
− | Takes 1 copy-handle for the current process (0xFFFF8001).
| |
− | | |
− | == AddInterface ==
| |
− | 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.
| |
− | | |
− | 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.
| |
− | | |
− | Returns an error when [[#BindDevice]] wasn't used.
| |
| | | |
− | Up to 4 interfaces can be used+[[#EnableInterface|enabled]].
| + | 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. |
| | | |
− | Structure of the first buffer(this is the same as [http://libusb.sourceforge.net/api-1.0/structlibusb__interface__descriptor.html libusb__interface__descriptor]):
| |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Offset || Size || Description | + | ! Cmd || Name |
| |- | | |- |
− | | 0x0 || 0x1 || bLength. Must match 0x9. | + | | 0 || [[#OpenDsService]] |
− | |-
| |
− | | 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.
| + | == OpenDsService == |
| + | Unofficial name. |
| | | |
− | == GetStateChangeEvent ==
| + | No input. Returns an [[#IDsService]]. |
− | 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. | |
| | | |
− | == GetState == | + | == IDsService == |
− | No input. Returns an output u32. Returns an error when [[#BindDevice]] wasn't used.
| + | This is "nn::usb::ds::IDsService". |
− | | |
− | Returns the current state.
| |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Value || Name || Description | + | ! Cmd || Name |
| |- | | |- |
− | | 0 || Detached || Device is not attached to USB. | + | | 0 || [[#BindComplex]] |
| |- | | |- |
− | | 1 || Attached || Device is attached, but is not powered. | + | | 1 || [11.0.0+] [[#RegisterInterface]] ([1.0.0-10.2.0] [[#BindClientProcess]])) |
| |- | | |- |
− | | 2 || Powered || Device is attached and powered, but has not been reset. | + | | 2 || [11.0.0+] [[#GetStateChangeEvent]] ([1.0.0-10.2.0] [[#RegisterInterface]]) |
| |- | | |- |
− | | 3 || Default || Device is attached, powered, and has been reset, but does not have an address. | + | | 3 || [11.0.0+] [[#GetState]] ([1.0.0-10.2.0] [[#GetStateChangeEvent]]) |
| |- | | |- |
− | | 4 || Address || Device is attached, powered, has been reset, has an address, but is not configured. | + | | 4 || [11.0.0+] ClearDeviceData ([1.0.0-10.2.0] [[#GetState]]) |
| |- | | |- |
− | | 5 || Configured || Device is attached, powered, has been reset, has an address, configured, and may be used. | + | | 5 || [11.0.0+] AddUsbStringDescriptor ([5.0.0-10.2.0] ClearDeviceData, [2.0.0-4.1.0] [[#SetVidPidBcd]]) |
| |- | | |- |
− | | 6 || Suspended || Device is attached and powered, but has not seen bus activity for 3ms. Device is suspended and cannot be used. | + | | 6 || [11.0.0+] DeleteUsbStringDescriptor ([5.0.0-10.2.0] AddUsbStringDescriptor) |
− | |}
| |
− | | |
− | == SetVidPidBcd ==
| |
− | Takes a type-5 buffer with 0x66 bytes of USB descriptor data (see [[Manu_Services#manu|manu]]).
| |
− | | |
− | {| class="wikitable" border="1"
| |
| |- | | |- |
− | ! Offset || Size || Description
| + | | 7 || [11.0.0+] SetUsbDeviceDescriptor ([5.0.0-10.2.0] DeleteUsbStringDescriptor) |
| |- | | |- |
− | | 0x0 || 0x2 || VID (idVendor) | + | | 8 || [11.0.0+] SetBinaryObjectStore ([5.0.0-10.2.0] SetUsbDeviceDescriptor) |
| |- | | |- |
− | | 0x2 || 0x2 || PID (idProduct) | + | | 9 || [11.0.0+] Enable ([5.0.0-10.2.0] SetBinaryObjectStore) |
| |- | | |- |
− | | 0x4 || 0x2 || bcdDevice | + | | 10 || [11.0.0+] Disable ([5.0.0-10.2.0] Enable) |
| |- | | |- |
− | | 0x6 || 0x20 || Manufacturer | + | | 11 || [11.0.0+] ([5.0.0-10.2.0] Disable) |
| |- | | |- |
− | | 0x26 || 0x20 || Product | + | | 12 || [8.0.0-10.2.0] |
− | |-
| |
− | | 0x46 || 0x20 || SerialNumber
| |
| |} | | |} |
| | | |
− | The last 3 blocks are ASCII strings. The data following each string is all-zero, for padding to size 0x20.
| + | == BindComplex == |
| + | Takes an input u32 '''ComplexId'''. No output. |
| + | |
| + | [11.0.0+] Now takes an additional input Process handle. |
| + | |
| + | [[Manu_Services|Manu]] uses '''ComplexId''' 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. |
| + | |
| + | Returns a not-found error when '''ComplexId''' isn't 0x02, for values 0x0-0x4 at least. |
| + | |
| + | == BindClientProcess == |
| + | Takes an input Process handle. No output. |
| + | |
| + | == RegisterInterface == |
| + | Takes two type-0x5 input buffers containing an [[#UsbInterfaceDescriptor]] and an [[#UsbStringDescriptor]], respectively. Returns an output u8 '''InterfaceNumber''' and an [[#IDsInterface]]. |
| + | |
| + | [5.0.0+] This now only takes an input u8 and returns 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. |
| + | |
| + | 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. |
| + | |
| + | Returns an error when [[#BindComplex]] wasn't used. |
| + | |
| + | Up to 4 interfaces can be used and [[#EnableInterface|enabled]]. |
| + | |
| + | == GetStateChangeEvent == |
| + | 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 == |
| + | No input. Returns an output [[#UsbState]]. |
| + | |
| + | Returns an error when [[#BindComplex]] wasn't used. |
| + | |
| + | == SetVidPidBcd == |
| + | Takes a type-0x5 input buffer containing an [[#UsbVidPidBcd]]. No output. |
| | | |
| == Cmd12 == | | == Cmd12 == |
Line 246: |
Line 173: |
| == IDsInterface == | | == IDsInterface == |
| This is "nn::usb::ds::IDsInterface". | | This is "nn::usb::ds::IDsInterface". |
− |
| |
− | Various cmds were updated/moved with [11.0.0+]. New Cmd11 was added with [13.0.0+].
| |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 253: |
Line 178: |
| ! Cmd || Name | | ! Cmd || Name |
| |- | | |- |
− | | 0 || [[#AddEndpoint]] | + | | 0 || [[#RegisterEndpoint]] |
| |- | | |- |
| | 1 || [[#GetSetupEvent]] | | | 1 || [[#GetSetupEvent]] |
Line 259: |
Line 184: |
| | 2 || [[#GetSetupPacket]] | | | 2 || [[#GetSetupPacket]] |
| |- | | |- |
− | | 3 || [[#Enable]] | + | | 3 || [11.0.0+] [[#CtrlIn]] ([1.0.0-10.2.0] [[#Enable]]) |
| |- | | |- |
− | | 4 || [[#Disable]] | + | | 4 || [11.0.0+] [[#CtrlOut]] ([1.0.0-10.2.0] [[#Disable]]) |
| |- | | |- |
− | | 5 || [[#CtrlIn]] | + | | 5 || [11.0.0+] [[#GetCtrlInCompletionEvent]] ([1.0.0-10.2.0] [[#CtrlIn]]) |
| |- | | |- |
− | | 6 || [[#CtrlOut]] | + | | 6 || [11.0.0+] [[#GetCtrlInUrbReport]] ([1.0.0-10.2.0] [[#CtrlOut]]) |
| |- | | |- |
− | | 7 || [[#GetCtrlInCompletionEvent]] | + | | 7 || [11.0.0+] [[#GetCtrlOutCompletionEvent]] ([1.0.0-10.2.0] [[#GetCtrlInCompletionEvent]]) |
| |- | | |- |
− | | 8 || [[#GetCtrlInUrbReport]] | + | | 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 || [[#GetCtrlOutUrbReport]] | + | | 10 || [11.0.0+] AppendConfigurationData ([1.0.0-10.2.0] [[#GetCtrlOutUrbReport]]) |
| |- | | |- |
− | | 11 || [[#CtrlStall]] | + | | 11 || [13.0.0+] ([1.0.0-10.2.0] [[#CtrlStall]]) |
| |- | | |- |
− | | 12 || [5.0.0+] AppendConfigurationData | + | | 12 || [15.0.0+] ([5.0.0-10.2.0] AppendConfigurationData) |
| |} | | |} |
| | | |
− | Commands [[#GetSetupPacket]], [[#CtrlIn]], [[#CtrlOut]], and [[#CtrlStall]], will throw an error if the interface is not [[#EnableInterface|enabled]]. [[#AddEndpoint]] 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]]. |
| + | |
| + | [5.0.0+] This now only takes an input u8 and returns an [[#IDsEndpoint]]. |
| | | |
− | === AddEndpoint ===
| + | [[Manu_Services|Manu]] uses this twice for getting two endpoint sessions, with the following 0x7-byte buffer data: |
− | 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:
| |
| * First endpoint: 0x07, 0x05, 0x80, 0x02, 0x00, 0x02, 0x00 | | * First endpoint: 0x07, 0x05, 0x80, 0x02, 0x00, 0x02, 0x00 |
| ** bLength=0x7 | | ** bLength=0x7 |
Line 292: |
Line 219: |
| ** 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 303: |
Line 226: |
| | | |
| 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 === | | === GetSetupPacket === |
− | Takes a type-0x6 output buffer, no other output. Memcpys data to outbuf with outsize, uses size 0x8 if outsize is too large. | + | 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]]. |
| | | |
| === Enable === | | === Enable === |
− | Takes no arguments. Enables the current interface.
| + | No input/output. |
| + | |
| + | Enables the current interface. |
| | | |
− | Only one interface can be enabled at a time per bInterfaceNumber. When bInterfaceNumber is auto-allocate(0x4) for [[#AddEndpoint]] this isn't an issue since the final bInterfaceNumber will be unique. | + | 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. |
| | | |
| === Disable === | | === Disable === |
− | Takes no arguments. Disables the current interface.
| + | No input/output. |
| + | |
| + | Disables the current interface. |
| | | |
| === CtrlIn === | | === CtrlIn === |
− | Same as [[#PostBufferAsync]](with same input/output), except this uses control input endpoint 0x80. | + | Same as [[#PostBufferAsync]], except this uses control input endpoint 0x80. |
| + | |
| + | Throws an error if the interface is not [[#EnableInterface|enabled]]. |
| | | |
| === CtrlOut === | | === CtrlOut === |
− | Same as [[#PostBufferAsync]](with same input/output), except this uses control output endpoint 0x00. | + | 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. |
| | | |
| === GetCtrlInUrbReport === | | === GetCtrlInUrbReport === |
− | Same as [[#GetUrbReport]](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. |
| | | |
| === GetCtrlOutUrbReport === | | === GetCtrlOutUrbReport === |
− | Same as [[#GetUrbReport]](with same input/output), except this uses control output endpoint 0x00. | + | Same as [[#GetUrbReport]], except this uses control output endpoint 0x00. |
| | | |
| === CtrlStall === | | === 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]]. |
| | | |
| === IDsEndpoint === | | === IDsEndpoint === |
Line 371: |
Line 312: |
| |} | | |} |
| | | |
− | [11.0.0+] The official sw wrapper for PostBufferAsync can optionally use cmd9 instead, if an object state flag is set. offset=input_addr-object_addr_field, this will Abort if offset is >= object_size_field.
| + | ==== PostBufferAsync ==== |
| + | Takes an input u32 '''Size''' and an input u64 '''Buffer'''. Returns an output u32 '''UrbId'''. |
| | | |
− | ==== PostBufferAsync ====
| + | The output urbId can then be used while parsing the output of [[#GetUrbReport]], after waiting for the CompletionEvent to be signalled. |
− | 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 [[#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 390: |
Line 331: |
| | | |
| ==== 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. |
| | | |
| ==== GetUrbReport ==== | | ==== GetUrbReport ==== |
− | 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. | + | No input. Returns an output [[#UrbReport]]. |
− | | |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! 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 ==== |
Line 427: |
Line 346: |
| | | |
| ==== SetZeroLengthTransfer ==== | | ==== SetZeroLengthTransfer ==== |
− | Takes an input u8, no output. | + | Takes an input bool. No output. |
| | | |
| ==== Cmd6 ==== | | ==== Cmd6 ==== |
− | No input, returns an output bool. | + | No input. Returns an output bool. |
| | | |
| ==== Cmd7 ==== | | ==== Cmd7 ==== |
− | No input, returns an output handle. | + | No input. Returns an output handle. |
| | | |
| ==== Cmd8 ==== | | ==== Cmd8 ==== |
− | Takes an input u64 and a handle, no output. Stubbed, just returns an error. | + | Takes an input u64 and an input handle. No output. |
| + | |
| + | Stubbed, just returns an error. |
| | | |
| ==== Cmd9 ==== | | ==== Cmd9 ==== |
− | Takes an input u32 size, an u64 offset, returns an u32 urbId. Stubbed, just returns an error. | + | Takes an input u32 '''Size''' and an input u64 '''Offset'''. Returns an u32 '''UrbId'''. |
| + | |
| + | Stubbed, just returns an error. |
| | | |
| = usb:hs, usb:hs:a = | | = usb:hs, usb:hs:a = |
Line 632: |
Line 555: |
| | 3 || [[#PopulateRing]] ([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 || [[#BatchBufferAsync]] | + | | 6 || [2.0.0+] [[#BatchBufferAsync]] |
| |- | | |- |
− | | [4.0.0+] 7 || [[#CreateSmmuSpace]] | + | | 7 || [4.0.0+] [[#CreateSmmuSpace]] |
| |- | | |- |
− | | [4.0.0+] 8 || [[#ShareReportRing]] | + | | 8 || [4.0.0+] [[#ShareReportRing]] |
| |} | | |} |
| | | |
Line 936: |
Line 859: |
| |- | | |- |
| | 1 || | | | 1 || |
| + | |} |
| + | |
| + | = 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) |
| |} | | |} |
| | | |