Changes

Jump to navigation Jump to search
6,862 bytes added ,  20:55, 29 October 2019
Line 40: Line 40:  
|-
 
|-
 
| 11 || [5.0.0+] Disable
 
| 11 || [5.0.0+] Disable
 +
|-
 +
| 12 || [8.0.0+]
 
|}
 
|}
   Line 137: Line 139:     
== GetDsInterface ==
 
== GetDsInterface ==
Takes 2 type-5 buffers and returns an [[#IDsInterface]]. [[Manu_Services|Manu]] sends a 0x09-byte command (e.g.: 0x09, 0x04, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00) in the first buffer and a string ("usb") in the second buffer.
+
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.
 
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.
Line 243: Line 245:     
=== GetDsEndpoint ===
 
=== GetDsEndpoint ===
Takes a type-5 buffer and returns an [[#IDsEndpoint]]. [[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 318: Line 320:  
|-
 
|-
 
| 5 || || Takes an input u8, no output.
 
| 5 || || Takes an input u8, no output.
 +
|-
 +
| 6 || [7.0.0+] || No input, returns an output u8.
 +
|-
 +
| 7 || [7.0.0+] || No input, returns an output handle.
 
|}
 
|}
   Line 370: Line 376:  
Stops in-progress data-transfer done by [[#PostBufferAsync]].
 
Stops in-progress data-transfer done by [[#PostBufferAsync]].
   −
= usb:hs =
+
= 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"
Line 406: Line 414:     
== QueryAllInterfaces ==
 
== QueryAllInterfaces ==
Takes a 0x10-byte input struct and a type-0x6 output buffer, returns an output u32 total_entries.
+
Takes an [[#UsbHsInterfaceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.
   −
The output buffer contains an array of [[#UsbHsInterface]].
+
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.
    
== QueryAvailableInterfaces ==
 
== QueryAvailableInterfaces ==
Takes a 0x10-byte input struct and a type-0x6 output buffer, returns an output s32 total_entries.
+
Takes an [[#UsbHsInterfaceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.
 
  −
The output buffer contains an array of [[#UsbHsInterface]].
     −
HID-sysmodule uses the following for the input struct: <code>80 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00</code>
+
The output buffer contains an array of [[#UsbHsInterface]]. This only returns interfaces which are not acquired by any process.
    
== QueryAcquiredInterfaces ==
 
== QueryAcquiredInterfaces ==
Line 423: Line 429:     
== CreateInterfaceAvailableEvent ==
 
== CreateInterfaceAvailableEvent ==
Takes an input u8 and a 0x10-byte struct, 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 [[#UsbHsInterfaceFilter]], 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. This struct is the same as the one used for [[#QueryAvailableInterfaces]].
+
The struct is located at +2 from the u8 in IPC rawdata.
    
When signaled, this indicates that the user-process should use [[#QueryAvailableInterfaces]] and [[#AcquireUsbIf]] with the output interfaces (and the rest of interface setup).
 
When signaled, this indicates that the user-process should use [[#QueryAvailableInterfaces]] and [[#AcquireUsbIf]] with the output interfaces (and the rest of interface setup).
Line 437: Line 443:  
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 with a 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 [[#UsbHsInterface]] +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 [[#UsbHsInterface]].
   −
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 the first 0x1B8-bytes from [[#UsbHsInterface]].
 +
 
 +
This returns an error if the interface was already acquired by another process.
    
== GetDescriptorString ==
 
== GetDescriptorString ==
Line 494: Line 502:     
=== GetAlternateInterface ===
 
=== GetAlternateInterface ===
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 the first 0x1B8-bytes from [[#UsbHsInterface]]. The buffer size must match 0x1B8.
    
=== GetCurrentFrame ===
 
=== GetCurrentFrame ===
Line 506: Line 514:  
=== GetCtrlXferReport ===
 
=== GetCtrlXferReport ===
 
Takes a type-0x6 output buffer, no output. The output buffer contains a [[#XferReport]].
 
Takes a type-0x6 output buffer, no output. The output buffer contains a [[#XferReport]].
 +
 +
=== SubmitControlInRequest ===
 +
Takes a type-0x6 output buffer, 2 input u8s ('''bRequest''' and '''bRequestType'''), 3 input u16s ('''wValue''', '''wIndex''', and '''wLength'''), and an input u32 '''timeoutInMs'''. Returns an output u32 for the actual transferred size.
 +
 +
Official user-processes uses a buffer where the buffer address/size is page-aligned, where '''wLength''' is the original size before alignment. The user-process also flushes dcache for this buffer using '''wLength''', before/after using this command. Official sw passes value 0 for '''timeoutInMs'''.
 +
 +
=== SubmitControlOutRequest ===
 +
Takes a type-0x5 input buffer, 2 input u8s ('''bRequest''' and '''bRequestType'''), 3 input u16s ('''wValue''', '''wIndex''', and '''wLength'''), and an input u32 '''timeoutInMs'''. Returns an output u32 for the actual transferred size.
 +
 +
Official user-processes uses a buffer where the buffer address/size is page-aligned, where '''wLength''' is the original size before alignment. The user-process also flushes dcache for this buffer using '''wLength''', before using this command. Official sw passes value 0 for '''timeoutInMs'''.
    
=== ResetDevice ===
 
=== ResetDevice ===
 
No input/output.
 
No input/output.
 +
 +
Resets the device: has the same affect as unplugging the device and plugging it back in.
    
=== OpenUsbEp ===
 
=== OpenUsbEp ===
Line 542: Line 562:  
| [2.0.0+] 5 || [[#GetXferReport]] ||  
 
| [2.0.0+] 5 || [[#GetXferReport]] ||  
 
|-
 
|-
| [2.0.0+] 6 || || Takes 3 input u32s, 2 input u64s, and a type-0x5 input buffer, returns an output u32.
+
| [2.0.0+] 6 || [[#PostBufferMultiAsync]] ||  
 
|-
 
|-
| [4.0.0+] 7 || ||  
+
| [4.0.0+] 7 || || Takes a total of 0x10-bytes of input, no output.
 
|-
 
|-
| [4.0.0+] 8 || ||  
+
| [4.0.0+] 8 || || Takes a total of 0x4-bytes of input and an input handle, no output.
 
|}
 
|}
   Line 581: Line 601:     
==== 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 '''unk''', returns an output u32 '''xferId'''.
    
HID-sysmodule passes value 0 for the last u64.
 
HID-sysmodule passes value 0 for the last u64.
 +
 +
Starts a data transfer with a single urb.
    
==== 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.
    
The buffer contains an array of [[#XferReport]].
 
The buffer contains an array of [[#XferReport]].
 +
 +
==== PostBufferMultiAsync ====
 +
Unofficial name.
 +
 +
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 '''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'''.
    
= UsbHsInterface =
 
= UsbHsInterface =
Line 599: Line 630:  
| 0x0 || 0x4 || ID value passed to other cmds. This is -1 with [[#QueryAllInterfaces]] output, hence this field is unused with that cmd.
 
| 0x0 || 0x4 || ID value passed to other cmds. This is -1 with [[#QueryAllInterfaces]] output, hence this field is unused with that cmd.
 
|-
 
|-
| 0x4 || 0x4? || deviceID
+
| 0x4 || 0x4 || deviceID
 +
|-
 +
| 0x8 || 0x4 || ?
 +
|-
 +
| 0xC || 0x9 || usb_interface_descriptor
 
|-
 
|-
| 0x8 || 0x4? || ?
+
| 0x15 || 0x7 || Padding
 
|-
 
|-
| 0xC || || usb_interface_descriptor
+
| 0x1C || 0x69 || OUTPUT usb_endpoint_descriptors, 15 max.
 
|-
 
|-
| 0x23 || 0x69 || OUTPUT usb_endpoint_descriptors, 15 max.
+
| 0x85 || 0x7 || Padding
 
|-
 
|-
 
| 0x8C || 0x69 || INPUT usb_endpoint_descriptors, 15 max.
 
| 0x8C || 0x69 || INPUT usb_endpoint_descriptors, 15 max.
 
|-
 
|-
| 0x1B8 || ? || "HsDevice-/L<unk0>/P<portnum>/A<unk1>" string (this is "FsDevice..." for the Dock USB 3.0 bus).
+
| 0xF5 || 0x6 || Padding
 +
|-
 +
| 0xFB || 0x5A || OUTPUT usb_ss_endpoint_companion_descriptors(?), 15 max.
 +
|-
 +
| 0x155 || 0x6 || Padding
 +
|-
 +
| 0x15B || 0x5A || INPUT usb_ss_endpoint_companion_descriptors(?), 15 max.
 +
|-
 +
| 0x1B5 || 0x3 || Padding
 
|-
 
|-
| 0x1F8 || 0x4? || busID
+
| 0x1B8 || 0x40 || "HsDevice-/L<unk0>/P<portnum>/A<unk1>" string (this is "FsDevice..." for the Dock USB 3.0 bus).
 
|-
 
|-
| 0x1FC || 0x4? || Duplicate of +0x4.
+
| 0x1F8 || 0x4 || busID
 
|-
 
|-
| 0x200 || || usb_device_descriptor, then usb_config_descriptor immediately afterwards.
+
| 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?
 
| 0x220 || 0x8 || Unknown u64 timestamp for when the device was inserted?
Line 621: Line 668:     
This is a 0x228-byte struct (unofficial name).
 
This is a 0x228-byte struct (unofficial name).
 +
 +
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.
 +
 +
= UsbHsInterfaceFilter =
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description
 +
|-
 +
| 0x0 || 0x2 || Flags
 +
|-
 +
| 0x2 || 0x2 ||idVendor
 +
|-
 +
| 0x4 || 0x2 || idProduct
 +
|-
 +
| 0x6 || 0x2 || bcdDevice_Min
 +
|-
 +
| 0x8 || 0x2 || bcdDevice_Max
 +
|-
 +
| 0xA || 0x1 || bDeviceClass
 +
|-
 +
| 0xB || 0x1 || bDeviceSubClass
 +
|-
 +
| 0xC || 0x1 || bDeviceProtocol
 +
|-
 +
| 0xD || 0x1 || bInterfaceClass
 +
|-
 +
| 0xE || 0x1 || bInterfaceSubClass
 +
|-
 +
| 0xF || 0x1 || bInterfaceProtocol
 +
|}
 +
 +
This is a 0x10-byte struct (unofficial name).
 +
 +
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: idVendor
 +
* 1: idProduct
 +
* 2: bcdDevice (Descriptor value must be >= struct bcdDevice_Min)
 +
* 3: bcdDevice (Descriptor value must be <= struct bcdDevice_Max)
 +
* 4: bDeviceClass
 +
* 5: bDeviceSubClass
 +
* 6: bDeviceProtocol
 +
* 7: bInterfaceClass
 +
* 8: bInterfaceSubClass
 +
* 9: bInterfaceProtocol
 +
 +
HID-sysmodule uses the following for the input struct: <code>80 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00</code>
    
= XferReport =
 
= XferReport =
Line 627: Line 726:  
! Offset || Size || Description
 
! Offset || Size || Description
 
|-
 
|-
| 0x0 || 0x4 || ?
+
| 0x0 || 0x4 || xferId (Only set for [[#GetXferReport]])
 
|-
 
|-
 
| 0x4 || 0x4 || Result
 
| 0x4 || 0x4 || Result
 
|-
 
|-
| 0x8 || 0x4 || ?
+
| 0x8 || 0x4 || requestedSize
 
|-
 
|-
| 0xC || 0x4 || Actual transferred size.
+
| 0xC || 0x4 || transferredSize
 
|-
 
|-
 
| 0x10 || 0x8? || ?
 
| 0x10 || 0x8? || ?
Line 769: Line 868:     
USB Port Manager, only system-title using this is [[PTM_services|ptm]].
 
USB Port Manager, only system-title using this is [[PTM_services|ptm]].
 +
 +
= usb:qdb =
 +
Added with [[7.0.0]].
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
! Cmd || Name
 +
|-
 +
| 0 ||
 +
|-
 +
| 1 ||
 +
|}
 +
 +
== Cmd0 ==
 +
No input/output, takes a type-0x5 input buffer.
 +
 +
This loads data for [[#HidGamepad]] with the input .json.
 +
 +
== Cmd1 ==
 +
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 =
 +
Added with [8.0.0+].
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
! Cmd || Name
 +
|-
 +
| 0 ||
 +
|-
 +
| 1 ||
 +
|}
 +
 +
= 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>
 +
  ]
    
[[Category:Services]]
 
[[Category:Services]]

Navigation menu