Changes

218 bytes added ,  21:00, 14 February 2021
no edit summary
Line 465: Line 465:  
| 8 ([1.0.0] 7) || [6.0.0+] ([1.0.0] [[#GetDescriptorString]])
 
| 8 ([1.0.0] 7) || [6.0.0+] ([1.0.0] [[#GetDescriptorString]])
 
|-
 
|-
| [1.0.0] 8 ||
+
| [1.0.0] 8 || [[#ResetDevice]]
 
|}
 
|}
   Line 476: Line 476:     
== QueryAllInterfaces ==
 
== QueryAllInterfaces ==
Takes an [[#UsbHsInterfaceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.
+
Takes an [[#DeviceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.
   −
The output buffer contains an array of [[#UsbHsInterface]]. This returns the same interfaces as [[#QueryAvailableInterfaces]], followed by the interfaces also returned by [[#QueryAcquiredInterfaces]]. Except for the ID field in [[#UsbHsInterface]], which is set to -1.
+
The output buffer contains an array of [[#InterfaceQueryOutput]]. This returns the same interfaces as [[#QueryAvailableInterfaces]], followed by the interfaces also returned by [[#QueryAcquiredInterfaces]]. Except for the ID field in [[#InterfaceQueryOutput]], which is set to -1.
    
== QueryAvailableInterfaces ==
 
== QueryAvailableInterfaces ==
Takes an [[#UsbHsInterfaceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.
+
Takes an [[#DeviceFilter]] and a type-0x6 output buffer, returns an output s32 total_entries.
   −
The output buffer contains an array of [[#UsbHsInterface]]. This only returns interfaces which are not acquired by any process.
+
The output buffer contains an array of [[#InterfaceQueryOutput]]. This only returns interfaces which are not acquired by any process.
    
== QueryAcquiredInterfaces ==
 
== QueryAcquiredInterfaces ==
 
Takes a type-0x6 output buffer and returns an output s32 total_entries.
 
Takes a type-0x6 output buffer and returns an output s32 total_entries.
   −
The output buffer contains an array of [[#UsbHsInterface]], for each interface which was acquired with [[#AcquireUsbIf]].
+
The output buffer contains an array of [[#InterfaceQueryOutput]], for each interface which was acquired with [[#AcquireUsbIf]].
    
== CreateInterfaceAvailableEvent ==
 
== CreateInterfaceAvailableEvent ==
Takes an input u8 and an [[#UsbHsInterfaceFilter]], and returns an output handle. The input value must be 0..2. This is used as an index in a table.
+
Takes an input u8 and an [[#DeviceFilter]], and returns an output handle. The input value must be 0..2. This is used as an index in a table.
    
The struct is located at +2 from the u8 in IPC rawdata.
 
The struct is located at +2 from the u8 in IPC rawdata.
Line 505: Line 505:  
No input, returns an output event handle with autoclear disabled.
 
No input, returns an output event handle with autoclear disabled.
   −
When signaled, this indicates that the user-process should use [[#QueryAcquiredInterfaces]] and cleanup state for interfaces which were already initialized and don't have any matching ID in [[#UsbHsInterface]] +0x0. When total_entries is less than 1, this indicates that cleanup should be done for all currently open interfaces.
+
When signaled, this indicates that the user-process should use [[#QueryAcquiredInterfaces]] and cleanup state for interfaces which were already initialized and don't have any matching ID in [[#InterfaceProfile]] +0x0. When total_entries is less than 1, this indicates that cleanup should be done for all currently open interfaces.
    
== AcquireUsbIf ==
 
== AcquireUsbIf ==
Takes an input u32 and a type-0x6 output buffer, returns an [[#IClientIfSession]]. 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]].
+
Takes an input u32 and a type-0x6 output buffer, returns an [[#IClientIfSession]]. On [3.0.0+] this takes an additional type-0x6 output buffer, before the original buffer. On [3.0.0+] the first buffer is 0x70-bytes, while the second one is 0x1B8. The user-process has the second buffer address immediately after the first one, which allows getting a complete [[#InterfaceProfile]].
   −
The input u32 is from the u32 at entry+0 from the associated [[#QueryAvailableInterfaces]] output entry. User-processes use size 0x1B8 for the first output buffer. The first output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]].
+
The input u32 is from the u32 at entry+0 from the associated [[#QueryAvailableInterfaces]] output entry. User-processes use size 0x1B8 for the first output buffer. The first output buffer contains an [[#InterfaceProfile]].
    
This returns an error if the interface was already acquired by another process.
 
This returns an error if the interface was already acquired by another process.
Line 525: Line 525:  
Official sw doesn't use this, [[#SubmitControlInRequest]] is used instead.
 
Official sw doesn't use this, [[#SubmitControlInRequest]] is used instead.
   −
== Cmd8 ==
+
== ResetDevice ==
 
[1.0.0] Takes an input u32, no output. Stubbed, just returns 0.
 
[1.0.0] Takes an input u32, no output. Stubbed, just returns 0.
   Line 535: Line 535:  
! Cmd || Name  
 
! Cmd || Name  
 
|-
 
|-
| 0 ||
+
| 0 || [[#GetStateChangeEvent]]
 
|-
 
|-
 
| 1 || [[#SetInterface]]
 
| 1 || [[#SetInterface]]
Line 543: Line 543:  
| 3 || [[#GetAlternateInterface]]
 
| 3 || [[#GetAlternateInterface]]
 
|-
 
|-
| 4 [1.0.0] 5) || [[#GetCurrentFrame]]
+
| 4 ([1.0.0] 5) || [[#GetCurrentFrame]]
 
|-
 
|-
 
| [2.0.0+] 5 || [[#CtrlXferAsync]]
 
| [2.0.0+] 5 || [[#CtrlXferAsync]]
 
|-
 
|-
| 6 || ([1.0.0] [[#SubmitControlInRequest]])  
+
| 6 || ([1.0.0] [[#SubmitControlInRequest]])
 
|-
 
|-
 
| 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]])
 
| 7 || [[#GetCtrlXferReport]] ([1.0.0] [[#SubmitControlOutRequest]])
Line 560: Line 560:  
Immediately after opening the session, official sw uses cmd0 and cmd6.
 
Immediately after opening the session, official sw uses cmd0 and cmd6.
   −
=== Cmd0 ===
+
=== GetStateChangeEvent ===
 
No input, returns an output handle.
 
No input, returns an output handle.
    
=== SetInterface ===
 
=== SetInterface ===
Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]].
+
Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]].
    
=== GetInterface ===
 
=== GetInterface ===
Takes a type-0x6 output buffer, no output. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]].
+
Takes a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]].
    
=== GetAlternateInterface ===
 
=== GetAlternateInterface ===
Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains the first 0x1B8-bytes from [[#UsbHsInterface]]. The buffer size must match 0x1B8.
+
Takes an input u8 and a type-0x6 output buffer, no output. The output buffer contains an [[#InterfaceProfile]]. The buffer size must match 0x1B8.
    
=== GetCurrentFrame ===
 
=== GetCurrentFrame ===
Line 625: Line 625:  
| 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]])
 
| 1 || [[#Close]] ([1.0.0] [[#SubmitInRequest]])
 
|-
 
|-
| 2 ||
+
| 2 || ([1.0.0] Reset)
 
|-
 
|-
 
| 3 || [[#Populate]] ([1.0.0] [[#Close]])
 
| 3 || [[#Populate]] ([1.0.0] [[#Close]])
Line 901: Line 901:  
|}
 
|}
   −
= UsbHsInterface =
+
= InterfaceQueryOutput =
 +
This is "nn::usb::InterfaceQueryOutput".
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description
 +
|-
 +
| 0x0 || 0x1B8 || [[#InterfaceProfile|InterfaceProfile]]
 +
|-
 +
| 0x1B8 || 0x40 || "HsDevice-/L<unk0>/P<portnum>/A<unk1>" string (this is "FsDevice..." for the Dock USB 3.0 bus).
 +
|-
 +
| 0x1F8 || 0x4 || busID
 +
|-
 +
| 0x1FC || 0x4 || deviceID
 +
|-
 +
| 0x200 || 0x12+0x9(0x1B) || usb_device_descriptor, then usb_config_descriptor immediately afterwards.
 +
|-
 +
| 0x21B || 0x5 || Padding
 +
|-
 +
| 0x220 || 0x8 || Unknown u64 timestamp for when the device was inserted?
 +
|}
 +
 
 +
The INPUT/OUTPUT endpoint descriptors (usb_endpoint_descriptors/usb_ss_endpoint_companion_descriptors) were swapped with [8.0.0+] (above layout has the pre-8.0.0 layout), however the sysmodule code which writes this output struct was basically unchanged.
 +
 
 +
= InterfaceProfile =
 +
This is "nn::usb::InterfaceProfile".
 +
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 931: Line 957:  
|-
 
|-
 
| 0x1B5 || 0x3 || Padding
 
| 0x1B5 || 0x3 || Padding
|-
  −
| 0x1B8 || 0x40 || "HsDevice-/L<unk0>/P<portnum>/A<unk1>" string (this is "FsDevice..." for the Dock USB 3.0 bus).
  −
|-
  −
| 0x1F8 || 0x4 || busID
  −
|-
  −
| 0x1FC || 0x4 || deviceID
  −
|-
  −
| 0x200 || 0x12+0x9(0x1B) || usb_device_descriptor, then usb_config_descriptor immediately afterwards.
  −
|-
  −
| 0x21B || 0x5 || Padding
  −
|-
  −
| 0x220 || 0x8 || Unknown u64 timestamp for when the device was inserted?
   
|}
 
|}
   −
This is a 0x228-byte struct (unofficial name).
+
= DeviceFilter =
 
+
This is "nn::usb::DeviceFilter".
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"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 979: Line 991:  
This is a 0x10-byte struct (unofficial name).
 
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.
+
This is used to filter [[#InterfaceQueryOutput]], the query commands will only return the interface when these checks pass. This is also used for events with [[#CreateInterfaceAvailableEvent]]. When a bit in Flags is set, the associated descriptor field and the field in this struct are compared, on mismatch the interface will be filtered out. Passing Flags=0 is equivalent to disabling filtering since none of these checks will run.
    
[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).
 
[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).