Changes

5,267 bytes added ,  20:28, 15 October 2023
no edit summary
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 =
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 ||
  −
|}
  −
 
  −
== Cmd0 ==
  −
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 || [[#GetDsInterface]]
  −
|-
  −
| 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 [[#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 ==
   
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 81: 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 [[#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]].
+
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 143: 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).
     −
== GetDsInterface ==
+
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.
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]].
  −
  −
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.
  −
|-
  −
| 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.
+
| 0 || [[#CreateDsService]]
 
|}
 
|}
   −
Only the first 0x9-bytes are used.
+
== CreateDsService ==
 +
No input. Returns an [[#IDsService]].
   −
== GetStateChangeEvent ==
+
== 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.
+
This is "nn::usb::ds::IDsService".
 
  −
== GetState ==
  −
No input. Returns an output u32. Returns an error when [[#BindDevice]] wasn't used.
  −
 
  −
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 || [[#Initialize]]
 
|-
 
|-
| 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)
 
|-
 
|-
|}
+
| 7 || [11.0.0+] SetUsbDeviceDescriptor ([5.0.0-10.2.0] DeleteUsbStringDescriptor)
 
  −
== 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
+
| 8 || [11.0.0+] SetBinaryObjectStore ([5.0.0-10.2.0] SetUsbDeviceDescriptor)
 
|-
 
|-
| 0x0 || 0x2 || VID (idVendor)
+
| 9 || [11.0.0+] EnableDevice ([5.0.0-10.2.0] SetBinaryObjectStore)
 
|-
 
|-
| 0x2 || 0x2 || PID (idProduct)
+
| 10 || [11.0.0+] DisableDevice ([5.0.0-10.2.0] EnableDevice)
 
|-
 
|-
| 0x4 || 0x2 || bcdDevice
+
| 11 || [11.0.0+] [[#GetSpeed]] ([5.0.0-10.2.0] DisableDevice)
 
|-
 
|-
| 0x6 || 0x20 || Manufacturer
+
| 12 || [8.0.0-10.2.0] [[#GetSpeed]]
|-
  −
| 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.
+
== Initialize ==
 +
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 [[#Initialize]] wasn't used.
   −
== Cmd12 ==
+
Up to 4 interfaces can be used and [[#EnableInterface|enabled]].
No input. Returns an output u32.
+
 
 +
== 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 [[#Initialize]] wasn't used.
 +
 
 +
== SetVidPidBcd ==
 +
Takes a type-0x5 input buffer containing an [[#UsbVidPidBcd]]. No output.
 +
 
 +
== GetSpeed ==
 +
No input. Returns an output [[#UsbDeviceSpeed]].
    
== IDsInterface ==
 
== IDsInterface ==
 
This is "nn::usb::ds::IDsInterface".
 
This is "nn::usb::ds::IDsInterface".
  −
Various cmds were updated/moved with [11.0.0+].
      
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 250: Line 176:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || [[#GetDsEndpoint]]
+
| 0 || [[#RegisterEndpoint]]
 
|-
 
|-
 
| 1 || [[#GetSetupEvent]]
 
| 1 || [[#GetSetupEvent]]
 
|-
 
|-
| 2 ||
+
| 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]].
 +
 
 +
[5.0.0+] This now only takes an input u8 and returns an [[#IDsEndpoint]].
   −
=== GetDsEndpoint ===
+
[[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 289: Line 217:  
** 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 300: Line 224:     
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]].
   −
=== Cmd2 ===
+
=== Enable ===
Takes a type-0x6 output buffer, no other output. Memcpys data to outbuf with outsize, uses size 0x8 if outsize is too large.
+
No input/output.
   −
=== EnableInterface ===
+
Enables the current interface.
Takes no arguments. Enables the current interface.
     −
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.
+
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 349: Line 304:  
| 0 || [[#PostBufferAsync]]
 
| 0 || [[#PostBufferAsync]]
 
|-
 
|-
| 1 ||
+
| 1 || [[#Cancel]]
 
|-
 
|-
 
| 2 || [[#GetCompletionEvent]]
 
| 2 || [[#GetCompletionEvent]]
 
|-
 
|-
| 3 || [[#GetReportData]]
+
| 3 || [[#GetUrbReport]]
 
|-
 
|-
 
| 4 || [[#Stall]]
 
| 4 || [[#Stall]]
 
|-
 
|-
| 5 ||
+
| 5 || [[#SetZlt]]
 
|-
 
|-
| 6 || [7.0.0+]
+
| 6 || [7.0.0+] [[#IsStalled]]
 
|-
 
|-
| 7 || [7.0.0+]
+
| 7 || [7.0.0+] [[#GetStallClearedEvent]]
 
|-
 
|-
| 8 || [11.0.0+]
+
| 8 || [11.0.0-14.1.2]
 
|-
 
|-
| 9 || [11.0.0+]
+
| 9 || [11.0.0-14.1.2]
 
|}
 
|}
   −
[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 [[#GetReportData]], 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 383: Line 338:  
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).
   −
==== Cmd1 ====
+
==== Cancel ====
 
No input/output.
 
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 ====
+
==== 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"
+
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.
|-
  −
! Offset || Size || Description
  −
|-
  −
| 0x0 || 0x10*0x8(0x80) || 0x8 entries 0x10-bytes each for each report.
  −
|-
  −
| 0x80 || 0x4 || u32 report count
  −
|}
  −
 
  −
Entry data:
  −
{| 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]].
   −
==== Cmd5 ====
+
==== SetZlt ====
Takes an input u8, no output.
+
Takes an input bool. No output.
   −
==== Cmd6 ====
+
==== IsStalled ====
No input, returns an output bool.
+
No input. Returns an output bool.
   −
==== Cmd7 ====
+
==== GetStallClearedEvent ====
No input, returns an output handle.
+
No input. Returns an output Event 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 447: Line 384:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| [2.0.0+] 0 || [[#BindClientProcess_2|#BindClientProcess]]
+
| 0 || [2.0.0+] [[#BindClientProcess_2|#BindClientProcess]] ([1.0.0] [[#QueryAllInterfaces]])
 
|-
 
|-
| 1 ([1.0.0] 0) || [[#QueryAllInterfaces]]
+
| 1 || [[#QueryAllInterfaces]] ([1.0.0] [[#QueryAvailableInterfaces]])
 
|-
 
|-
| 2 ([1.0.0] 1) || [[#QueryAvailableInterfaces]]
+
| 2 || [[#QueryAvailableInterfaces]] ([1.0.0] [[#QueryAcquiredInterfaces]])
 
|-
 
|-
| 3 ([1.0.0] 2) || [[#QueryAcquiredInterfaces]]
+
| 3 || [[#QueryAcquiredInterfaces]] ([1.0.0] [[#CreateInterfaceAvailableEvent]])
 
|-
 
|-
| 4 ([1.0.0] 3) || [[#CreateInterfaceAvailableEvent]]
+
| 4 || [[#CreateInterfaceAvailableEvent]] ([1.0.0] [[#DestroyInterfaceAvailableEvent]])
 
|-
 
|-
| 5 ([1.0.0] 4) || [[#DestroyInterfaceAvailableEvent]]
+
| 5 || [[#DestroyInterfaceAvailableEvent]] ([1.0.0] [[#GetInterfaceStateChangeEvent]])
 
|-
 
|-
| 6 ([1.0.0] 5) || [[#GetInterfaceStateChangeEvent]]
+
| 6 || [[#GetInterfaceStateChangeEvent]] ([1.0.0] [[#AcquireUsbIf]])
 
|-
 
|-
| 7 ([1.0.0] 6) || [[#AcquireUsbIf]]
+
| 7 || [[#AcquireUsbIf]] ([1.0.0] [[#GetDescriptorString]])
 
|-
 
|-
| 8 ([1.0.0] 7) || [6.0.0+] ([1.0.0] [[#GetDescriptorString]])
+
| 8 || [6.0.0+] SetTestMode ([1.0.0] [[#ResetDevice]])
|-
  −
| [1.0.0] 8 || [[#ResetDevice]]
   
|}
 
|}
   Line 526: Line 461:     
== ResetDevice ==
 
== ResetDevice ==
[1.0.0] Takes an input u32, no output. Stubbed, just returns 0.
+
Takes an input u32, no output. Stubbed, just returns 0.
    
== IClientIfSession ==
 
== IClientIfSession ==
Line 543: Line 478:  
| 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]])
+
| 6 || [[#GetCtrlXferCompletionEvent]] ([1.0.0] [[#SubmitControlInRequest]])
 
|-
 
|-
 
| 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]])
 
| 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]])
Line 553: Line 488:  
| 8 || [[#ResetDevice]]
 
| 8 || [[#ResetDevice]]
 
|-
 
|-
| 9 ([1.0.0] 4) || [[#OpenUsbEp]]  
+
| 9 || [[#OpenUsbEp]] ([1.0.0] [[#GetCurrentFrame]])
 
|}
 
|}
   Line 580: Line 515:  
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.
   −
=== Cmd6 ===
+
=== GetCtrlXferCompletionEvent ===
 
No input, returns an output handle. Signaled when [[#CtrlXferAsync]] finishes.
 
No input, returns an output handle. Signaled when [[#CtrlXferAsync]] finishes.
   Line 625: Line 560:  
| 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]])
 
| 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]])
 
|-
 
|-
| 2 || GetCompletionEvent ([1.0.0] Reset)
+
| 2 || [[#GetCompletionEvent_2|GetCompletionEvent]] ([1.0.0] Reset)
 
|-
 
|-
 
| 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 664: Line 599:  
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.
   −
==== Cmd2 ====
+
==== GetCompletionEvent ====
 
No input, returns an output handle. Signaled when [[#PostBufferAsync_2|#PostBufferAsync]] finishes. ([1.0.0] [[#Open]])
 
No input, returns an output handle. Signaled when [[#PostBufferAsync_2|#PostBufferAsync]] finishes. ([1.0.0] [[#Open]])
   Line 675: Line 610:     
==== PostBufferAsync ====
 
==== PostBufferAsync ====
Takes an input u32 '''size''', an input u64 '''buffer''', and an input u64 '''unk''', 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.
   −
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 ====
Line 687: Line 624:     
The buffer contains an array of [[#XferReport]].
 
The buffer contains an array of [[#XferReport]].
 +
 +
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 ====
 
==== 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'''.
   −
Takes 3 input u32s ('''urbCount''', '''unk1''', and '''unk2'''), an input u64 '''buffer''' and u64 '''unk''', 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]].
 
  −
Where '''unk''' 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'''.
 
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 ====
 
==== CreateSmmuSpace ====
Takes a total of 0x10-bytes of input, no output.
+
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 ====
 
==== ShareReportRing ====
Takes a total of 0x4-bytes of input and an input handle, no output.
+
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 =
 
= usb:pd =
Line 761: Line 724:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || [[#AccessCradleVdoWithWriteRequest]]  
+
| 0 || [[#SetCradleVdo]]  
 
|-
 
|-
| 1 || [[#AccessCradleVdoWithReadRequest]]
+
| 1 || [[#GetCradleVdo]]
 
|-
 
|-
| 2 ||  
+
| 2 || [[#ResetCradleUsbHub]]
 
|-
 
|-
| 3 || [2.0.0+] GetFwType
+
| 3 || [2.0.0+] [[#GetHostPdcFirmwareType]]
 
|-
 
|-
| 4 || [2.0.0+] GetFwRevision
+
| 4 || [2.0.0+] [[#GetHostPdcFirmwareRevision]]
 
|-
 
|-
| 5 || [2.0.0+] GetManufacturerId
+
| 5 || [2.0.0+] [[#GetHostPdcManufactureId]]
 
|-
 
|-
| 6 || [2.0.0+] GetDeviceId
+
| 6 || [2.0.0+] [[#GetHostPdcDeviceId]]
 
|-
 
|-
| 7 || [3.0.0+]
+
| 7 || [3.0.0+] [[#EnableCradleRecovery]]
 
|-
 
|-
| 8 || [3.0.0+]
+
| 8 || [3.0.0+] [[#DisableCradleRecovery]]
 
|}
 
|}
   −
=== AccessCradleVdoWithWriteRequest ===
+
=== SetCradleVdo ===
Takes two input u32s '''Value''' and '''UserId'''. No output.
+
Takes an input u32 '''Value''' and a [[#CradleVdmCommand]]. No output.
   −
'''UserId''' is translated to the actual [[#VdmCommand]] to send.
+
[[#CradleVdmCommand]] is translated to the actual [[#VdmCommand]] to send.
   −
=== AccessCradleVdoWithReadRequest ===
+
=== GetCradleVdo ===
Takes an input u32 '''UserId'''. Returns an u32 '''Value'''.
+
Takes an input [[#CradleVdmCommand]]. Returns an u32 '''Value'''.
   −
'''UserId''' is translated to the actual [[#VdmCommand]] to send.
+
[[#CradleVdmCommand]] is translated to the actual [[#VdmCommand]] to send.
   −
=== Cmd2 ===
+
=== ResetCradleUsbHub ===
 
No input/output.
 
No input/output.
    
Sends [[#VdmCommand|VdmCommands]] 32 and 30.
 
Sends [[#VdmCommand|VdmCommands]] 32 and 30.
   −
=== GetFwType ===
+
=== GetHostPdcFirmwareType ===
 
No input. Returns an output u16.
 
No input. Returns an output u16.
   −
=== GetFwRevision ===
+
=== GetHostPdcFirmwareRevision ===
 
No input. Returns an output u16.
 
No input. Returns an output u16.
   −
=== GetManufacturerId ===
+
=== GetHostPdcManufactureId ===
 
No input. Returns an output u16.
 
No input. Returns an output u16.
   −
=== GetDeviceId ===
+
=== GetHostPdcDeviceId ===
 
No input. Returns an output u16.
 
No input. Returns an output u16.
   −
=== Cmd7 ===
+
=== EnableCradleRecovery ===
 
No input. Returns an output u8.
 
No input. Returns an output u8.
   −
=== Cmd8 ===
+
=== DisableCradleRecovery ===
 
No input. Returns an output u8.
 
No input. Returns an output u8.
   Line 835: Line 798:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || GetFwType
+
| 0 || [[#GetHostPdcFirmwareType]]
 
|-
 
|-
| 1 || GetFwRevision
+
| 1 || [[#GetHostPdcFirmwareRevision]]
 
|-
 
|-
| 2 || GetManufacturerId
+
| 2 || [[#GetHostPdcManufactureId]]
 
|-
 
|-
| 3 || GetDeviceId
+
| 3 || [[#GetHostPdcDeviceId]]
 
|}
 
|}
    
= usb:pm =
 
= usb:pm =
 
This is "nn::usb::pm::IPmService".
 
This is "nn::usb::pm::IPmService".
 +
 +
[8.0.0+] This is "nn::usb::pm::IPmMainService".
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 851: Line 816:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 ||
+
| 0 || GetPowerEvent
 
|-
 
|-
| 1 ||
+
| 1 || GetPowerState
 
|-
 
|-
| 2 ||
+
| 2 || GetDataEvent
 
|-
 
|-
| 3 ||
+
| 3 || GetDataRole
 
|-
 
|-
| 4 ||
+
| 4 || SetDiagData
 
|-
 
|-
| 5 ||
+
| 5 || GetDiagData
 
|}
 
|}
   Line 867: Line 832:     
= usb:qdb =
 
= usb:qdb =
Added with [[7.0.0]].
+
This is "nn::usb::qdb::IQdbManager".
 +
 
 +
This was added with [7.0.0+].
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 873: Line 840:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 ||  
+
| 0 || [[#ImportQuirkDevices]]
 
|-
 
|-
| 1 ||  
+
| 1 || [[#HasQuirk]]
 
|}
 
|}
   −
== Cmd0 ==
+
== ImportQuirkDevices ==
 
No input/output, takes a type-0x5 input buffer.
 
No input/output, takes a type-0x5 input buffer.
    
This loads data for [[#HidGamepad]] with the input .json.
 
This loads data for [[#HidGamepad]] with the input .json.
   −
== Cmd1 ==
+
== HasQuirk ==
 
Takes 6-bytes of input (u16s '''vid''', '''pid''', '''bcdDevice''') and a type-0x5 input buffer, returns an output u8 bool indicating success.
 
Takes 6-bytes of input (u16s '''vid''', '''pid''', '''bcdDevice''') and a type-0x5 input buffer, returns an output u8 bool indicating success.
   Line 889: Line 856:     
= usb:obsv =
 
= usb:obsv =
Added with [8.0.0+].
+
This is "nn::usb::pm::IPmObserverService".
 +
 
 +
This was added with [8.0.0+].
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 895: Line 864:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 ||  
+
| 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
 
|-
 
|-
| 1 ||  
+
| 4 || Super
 
|}
 
|}
   Line 1,023: Line 1,123:  
| 0xC || 0x4 || transferredSize
 
| 0xC || 0x4 || transferredSize
 
|-
 
|-
| 0x10 || 0x8? || ?
+
| 0x10 || 0x8 || [[#PostBufferAsync_2|Id]]
 
|}
 
|}
   Line 1,029: Line 1,129:     
Official sw only uses the Result/size fields.
 
Official sw only uses the Result/size fields.
 +
 +
= CradleVdmCommand =
 +
This is "nn::usb::pd::CradleVdmCommand".
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value || Name
 +
|-
 +
| 0 ||
 +
|-
 +
| 1 ||
 +
|-
 +
| 2 ||
 +
|-
 +
| 3 ||
 +
|-
 +
| 4 ||
 +
|-
 +
| 5 ||
 +
|-
 +
| 6 ||
 +
|-
 +
| 7 ||
 +
|-
 +
| 8 ||
 +
|-
 +
| 9 ||
 +
|-
 +
| 10 ||
 +
|}
    
= VdmCommand =
 
= VdmCommand =
 +
This is "nn::usb::pd::driver::detail::VdmCommand".
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
! Value || UserId || Name
+
! Value || [[#CradleVdmCommand|CradleVdmCommand]] || [[#VdmCommandType|VdmCommandType]] || VdmCommandLength || Name
 +
|-
 +
| 0 || - || -1 || 0 || None
 +
|-
 +
| 1 || 0 || 0 || 3 || LedControlRequest
 +
|-
 +
| 2 || - || 1 || 3 || LedControlReply
 
|-
 
|-
| 0 || - || None
+
| 3 || 10 || 0 || 3 || DeviceTypeRequest
 
|-
 
|-
| 1 || 0 || LedControlRequest
+
| 4 || - || 1 || 3 || DeviceTypeReply
 
|-
 
|-
| 2 || - || SleepButtonNotice
+
| 5 || - || -1 || 0 || UsbPowerErrorNotice
 
|-
 
|-
| 3 || 10 || DeviceTypeRequest
+
| 6 || 1 || 0 || 2 || Dp2HdmiFwVerRequest
 
|-
 
|-
| 4 || - || DeviceTypeReply
+
| 7 || - || 1 || 3 || Dp2HdmiFwVerReply
 
|-
 
|-
| 5 || - || UsbPowerErrorNotice
+
| 8 || - || -1 || 0 || Dp2HdmiFwUpdateRequest
 
|-
 
|-
| 6 || 1 || Dp2HdmiFwVerRequest
+
| 9 || - || -1 || 0 || Dp2HdmiFwUpdateReply
 
|-
 
|-
| 7 || - || Dp2HdmiFwVerReply
+
| 10 || - || -1 || 0 || Dp2HdmiFwUpdateNotice
 
|-
 
|-
| 8 || - || Dp2HdmiFwUpdateRequest
+
| 11 || 2 || 0 || 2 || PdcHFwVerRequest
 
|-
 
|-
| 9 || - || Dp2HdmiFwUpdateReply
+
| 12 || - || 1 || 3 || PdcHFwVerReply
 
|-
 
|-
| 10 || - || Dp2HdmiFwUpdateNotice
+
| 13 || - || -1 || 0 || PdcHFwUpdateRequest
 
|-
 
|-
| 11 || 2 || PdcHFwVerRequest
+
| 14 || - || -1 || 0 || PdcHFwUpdateReply
 
|-
 
|-
| 12 || - || PdcHFwVerReply
+
| 15 || - || -1 || 0 || PdcHFwUpdateNotice
 
|-
 
|-
| 13 || - || PdcHFwUpdateRequest
+
| 16 || 3 || 0 || 2 || PdcAFwVerRequest
 
|-
 
|-
| 14 || - || PdcHFwUpdateReply
+
| 17 || - || 1 || 3 || PdcAFwVerReply
 
|-
 
|-
| 15 || - || PdcHFwUpdateNotice
+
| 18 || - || -1 || 0 || PdcAFwUpdateRequest
 
|-
 
|-
| 16 || 3 || PdcAFwVerRequest
+
| 19 || - || -1 || 0 || PdcAFwUpdateReply
 
|-
 
|-
| 17 || - || PdcAFwVerReply
+
| 20 || - || -1 || 0 || PdcAFwUpdateNotice
 
|-
 
|-
| 18 || - || PdcAFwUpdateRequest
+
| 21 || - || 0 || 3 || DeviceErrorNotice
 
|-
 
|-
| 19 || - || PdcAFwUpdateReply
+
| 22 || 4 || 0 || 2 || DeviceStateRequest
 
|-
 
|-
| 20 || - || PdcAFwUpdateNotice
+
| 23 || - || 1 || 3 || DeviceStateReply
 
|-
 
|-
| 21 || - || DeviceErrorNotice
+
| 24 || 5 || 0 || 2 || McuFwVerRequest
 
|-
 
|-
| 22 || 4 || DeviceStateRequest
+
| 25 || - || 1 || 3 || McuFwVerReply
 
|-
 
|-
| 23 || - || DeviceStateReply
+
| 26 || 6 || 0 || 2 || McuFwUpdateRequest
 
|-
 
|-
| 24 || 5 || McuFwVerRequest
+
| 27 || - || 1 || 2 || McuFwUpdateReply
 
|-
 
|-
| 25 || - || McuFwVerReply
+
| 28 || 7 || 0 || 2 || UsbHubSleepRequest
 
|-
 
|-
| 26 || 6 || McuFwUpdateRequest
+
| 29 || - || 1 || 2 || UsbHubSleepReply
 
|-
 
|-
| 27 || - || McuFwUpdateReply
+
| 30 || 8 || 0 || 2 || UsbHubResetRequest
 
|-
 
|-
| 28 || 7 || McuFwUpdateNotice
+
| 31 || - || 1 || 2 || UsbHubResetReply
 
|-
 
|-
| 29 || - ||  
+
| 32 || 9 || 0 || 2 || UsbHubControlRequest
 
|-
 
|-
| 30 || 8 ||  
+
| 33 || - || 1 || 2 || UsbHubControlReply
 +
|}
 +
 
 +
= VdmCommandType =
 +
This is "nn::usb::pd::driver::detail::VdmCommandType".
 +
 
 +
{| class="wikitable" border="1"
 
|-
 
|-
| 31 || - ||  
+
! Value || Name
 
|-
 
|-
| 32 || 9 ||  
+
| -1 || None
 +
|-
 +
| 0 || Initiator
 +
|-
 +
| 1 || Ack
 +
|-
 +
| 2 || Nak
 +
|-
 +
| 3 || Busy
 
|}
 
|}
   Line 1,120: Line 1,272:  
       <more entries>
 
       <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".
    
[[Category:Services]]
 
[[Category:Services]]