USB services: Difference between revisions

No edit summary
 
(7 intermediate revisions by one other user not shown)
Line 1: Line 1:
USB provides services for interacting with the USB stack.
USB provides services for interacting with the USB stack.
= Configuration =
The following is the default USB config strings, while the usbds service isn't being used. All of the below configuration will reset to the defaults when all usbds-related sessions are closed. These can be set with [[#SetVidPidBcd]]. The default string for Product is loaded from [[Settings_services|settings]] config. The default is referred to by usb-sysmodule as "Dummy".
  Product: Nintendo Switch
  Manufacturer: Nintendo
  SerialNumber: SerialNumber
The following is the default <code>lsusb -v {...}</code> output when the usbds service wasn't used.
pre-5.0.0: The endpoints are configured using [[#RegisterEndpoint]], the total number of endpoints is the number of open [[#IDsEndpoint]] sessions. bInterfaceNumber is {0-based index for the enabled [[#IDsInterface]] session.} Some of the interface fields are configured using [[#RegisterInterface]].
When usbds is in use where [[#SetVidPidBcd]] wasn't used, the VID/PID is 057e:3000.
  Bus 003 Device 006: ID 057e:2000 Nintendo Co., Ltd
  Couldn't open device, some information will be missing
  Device Descriptor:
    bLength                18
    bDescriptorType        1
    bcdUSB              2.00
    bDeviceClass            0 (Defined at Interface level)
    bDeviceSubClass        0
    bDeviceProtocol        0
    bMaxPacketSize0        64
    idVendor          0x057e Nintendo Co., Ltd
    idProduct          0x2000
    bcdDevice            1.00
    iManufacturer          1
    iProduct                2
    iSerial                3
    bNumConfigurations      1
    Configuration Descriptor:
      bLength                9
      bDescriptorType        2
      wTotalLength          34
      bNumInterfaces          1
      bConfigurationValue    1
      iConfiguration          0
      bmAttributes        0xc0
        Self Powered
      MaxPower              {...}
      Interface Descriptor:
        bLength                9
        bDescriptorType        4
        bInterfaceNumber        0
        bAlternateSetting      0
        bNumEndpoints          1
        bInterfaceClass        3 Human Interface Device
        bInterfaceSubClass      0 No Subclass
        bInterfaceProtocol      0 None
        iInterface              0
          HID Device Descriptor:
            bLength                9
            bDescriptorType        33
            bcdHID              2.00
            bCountryCode            0 Not supported
            bNumDescriptors        1
            bDescriptorType        34 Report
            wDescriptorLength      26
          Report Descriptors:
            ** UNAVAILABLE **
        Endpoint Descriptor:
          bLength                7
          bDescriptorType        5
          bEndpointAddress    0x81  EP 1 IN
          bmAttributes            3
            Transfer Type            Interrupt
            Synch Type              None
            Usage Type              Data
          wMaxPacketSize    0x0001  1x 1 bytes
          bInterval              16


= usb:ds =
= usb:ds =
Line 86: Line 16:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 || [[#OpenDsService]]
| 0 || [[#CreateDsService]]
|}
|}


== OpenDsService ==
== CreateDsService ==
Unofficial name.
 
No input. Returns an [[#IDsService]].
No input. Returns an [[#IDsService]].


Line 101: Line 29:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 || [[#BindComplex]]
| 0 || [[#Initialize]]
|-
|-
| 1 || [11.0.0+] [[#RegisterInterface]] ([1.0.0-10.2.0] [[#BindClientProcess]]))
| 1 || [11.0.0+] [[#RegisterInterface]] ([1.0.0-10.2.0] [[#BindClientProcess]]))
Line 119: Line 47:
| 8 || [11.0.0+] SetBinaryObjectStore ([5.0.0-10.2.0] SetUsbDeviceDescriptor)
| 8 || [11.0.0+] SetBinaryObjectStore ([5.0.0-10.2.0] SetUsbDeviceDescriptor)
|-
|-
| 9 || [11.0.0+] Enable ([5.0.0-10.2.0] SetBinaryObjectStore)
| 9 || [11.0.0+] EnableDevice ([5.0.0-10.2.0] SetBinaryObjectStore)
|-
|-
| 10 || [11.0.0+] Disable ([5.0.0-10.2.0] Enable)
| 10 || [11.0.0+] DisableDevice ([5.0.0-10.2.0] EnableDevice)
|-
|-
| 11 || [11.0.0+] [[#GetUsbDeviceSpeed]] ([5.0.0-10.2.0] Disable)
| 11 || [11.0.0+] [[#GetSpeed]] ([5.0.0-10.2.0] DisableDevice)
|-
|-
| 12 || [8.0.0-10.2.0] [[#GetUsbDeviceSpeed]]
| 12 || [8.0.0-10.2.0] [[#GetSpeed]]
|}
|}


== BindComplex ==
== Initialize ==
Takes an input u32 '''ComplexId'''. No output.
Takes an input u32 '''ComplexId'''. No output.


Line 151: Line 79:
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.


Returns an error when [[#BindComplex]] wasn't used.
Returns an error when [[#Initialize]] wasn't used.


Up to 4 interfaces can be used and [[#EnableInterface|enabled]].
Up to 4 interfaces can be used and [[#EnableInterface|enabled]].
Line 163: Line 91:
No input. Returns an output [[#UsbState]].
No input. Returns an output [[#UsbState]].


Returns an error when [[#BindComplex]] wasn't used.
Returns an error when [[#Initialize]] wasn't used.


== SetVidPidBcd ==
== SetVidPidBcd ==
Takes a type-0x5 input buffer containing an [[#UsbVidPidBcd]]. No output.
Takes a type-0x5 input buffer containing an [[#UsbVidPidBcd]]. No output.


== GetUsbDeviceSpeed ==
== GetSpeed ==
Unofficial name.
 
No input. Returns an output [[#UsbDeviceSpeed]].
No input. Returns an output [[#UsbDeviceSpeed]].


Line 186: Line 112:
| 2 || [[#GetSetupPacket]]
| 2 || [[#GetSetupPacket]]
|-
|-
| 3 || [11.0.0+] [[#CtrlIn]] ([1.0.0-10.2.0] [[#Enable]])
| 3 || [11.0.0+] [[#CtrlInAsync]] ([1.0.0-10.2.0] [[#Enable]])
|-
|-
| 4 || [11.0.0+] [[#CtrlOut]] ([1.0.0-10.2.0] [[#Disable]])
| 4 || [11.0.0+] [[#CtrlOutAsync]] ([1.0.0-10.2.0] [[#Disable]])
|-
|-
| 5 || [11.0.0+] [[#GetCtrlInCompletionEvent]] ([1.0.0-10.2.0] [[#CtrlIn]])
| 5 || [11.0.0+] [[#GetCtrlInCompletionEvent]] ([1.0.0-10.2.0] [[#CtrlInAsync]])
|-
|-
| 6 || [11.0.0+] [[#GetCtrlInUrbReport]] ([1.0.0-10.2.0] [[#CtrlOut]])
| 6 || [11.0.0+] [[#GetCtrlInUrbReport]] ([1.0.0-10.2.0] [[#CtrlOutAsync]])
|-
|-
| 7 || [11.0.0+] [[#GetCtrlOutCompletionEvent]] ([1.0.0-10.2.0] [[#GetCtrlInCompletionEvent]])
| 7 || [11.0.0+] [[#GetCtrlOutCompletionEvent]] ([1.0.0-10.2.0] [[#GetCtrlInCompletionEvent]])
Line 202: Line 128:
| 10 || [11.0.0+] [[#AppendConfigurationData]] ([1.0.0-10.2.0] [[#GetCtrlOutUrbReport]])
| 10 || [11.0.0+] [[#AppendConfigurationData]] ([1.0.0-10.2.0] [[#GetCtrlOutUrbReport]])
|-
|-
| 11 || [13.0.0+] ([1.0.0-10.2.0] [[#CtrlStall]])
| 11 || [13.0.0+] [[#SetGuid]] ([1.0.0-10.2.0] [[#CtrlStall]])
|-
|-
| 12 || [15.0.0+] ([5.0.0-10.2.0] [[#AppendConfigurationData]])
| 12 || [15.0.0+] [[#RegisterTransferMemory]] ([5.0.0-10.2.0] [[#AppendConfigurationData]])
|}
|}


Line 257: Line 183:
Disables the current interface.
Disables the current interface.


=== CtrlIn ===
=== CtrlInAsync ===
Same as [[#PostBufferAsync]], 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]].
Throws an error if the interface is not [[#EnableInterface|enabled]].


=== CtrlOut ===
=== CtrlOutAsync ===
Same as [[#PostBufferAsync]], except this uses control output endpoint 0x00.
Same as [[#PostBufferAsync]], except this uses control output endpoint 0x00.


Line 290: Line 216:


[5.0.0+] This now only takes an input [[#UsbDeviceSpeed]] and a type-0x5 input buffer.
[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 308: Line 242:
| 4 || [[#Stall]]
| 4 || [[#Stall]]
|-
|-
| 5 || [[#SetZeroLengthTransfer]]
| 5 || [[#SetZlt]]
|-
|-
| 6 || [7.0.0+]
| 6 || [7.0.0+] [[#IsStalled]]
|-
|-
| 7 || [7.0.0+]
| 7 || [7.0.0+] [[#GetStallClearedEvent]]
|-
|-
| 8 || [11.0.0-14.1.2]
| 8 || [11.0.0-14.1.2]
Line 352: Line 286:
Stops in-progress data-transfer done by [[#PostBufferAsync]].
Stops in-progress data-transfer done by [[#PostBufferAsync]].


==== SetZeroLengthTransfer ====
==== SetZlt ====
Takes an input bool. 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 ====
Line 380: Line 314:
! 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]]
|-
|-
| 2 ([1.0.0] 1) || [[#QueryAvailableInterfaces]]
| 1 || [[#QueryAllInterfaces]] ([1.0.0] [[#QueryAvailableInterfaces]])
|-
|-
| 3 ([1.0.0] 2) || [[#QueryAcquiredInterfaces]]
| 2 || [[#QueryAvailableInterfaces]] ([1.0.0] [[#QueryAcquiredInterfaces]])
|-
|-
| 4 ([1.0.0] 3) || [[#CreateInterfaceAvailableEvent]]
| 3 || [[#QueryAcquiredInterfaces]] ([1.0.0] [[#CreateInterfaceAvailableEvent]])
|-
|-
| 5 ([1.0.0] 4) || [[#DestroyInterfaceAvailableEvent]]
| 4 || [[#CreateInterfaceAvailableEvent]] ([1.0.0] [[#DestroyInterfaceAvailableEvent]])
|-
|-
| 6 ([1.0.0] 5) || [[#GetInterfaceStateChangeEvent]]
| 5 || [[#DestroyInterfaceAvailableEvent]] ([1.0.0] [[#GetInterfaceStateChangeEvent]])
|-
|-
| 7 ([1.0.0] 6) || [[#AcquireUsbIf]]
| 6 || [[#GetInterfaceStateChangeEvent]] ([1.0.0] [[#AcquireUsbIf]])
|-
|-
| 8 ([1.0.0] 7) || [6.0.0+] SetTestMode ([1.0.0] [[#GetDescriptorString]])
| 7 || [[#AcquireUsbIf]] ([1.0.0] [[#GetDescriptorString]])
|-
|-
| [1.0.0] 8 || [[#ResetDevice]]
| 8 || [6.0.0+] SetTestMode ([1.0.0] [[#ResetDevice]])
|}
|}


Line 459: Line 391:


== 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 476: Line 408:
| 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 || [[#GetCtrlXferCompletionEvent]] ([1.0.0] [[#SubmitControlInRequest]])
| 6 || [[#GetCtrlXferCompletionEvent]] ([1.0.0] [[#SubmitControlInRequest]])
Line 486: Line 418:
| 8 || [[#ResetDevice]]
| 8 || [[#ResetDevice]]
|-
|-
| 9 ([1.0.0] 4) || [[#OpenUsbEp]]  
| 9 || [[#OpenUsbEp]] ([1.0.0] [[#GetCurrentFrame]])
|}
|}


Line 592: Line 524:
This is similar to [[#OpenUsbEp]] with the params being loaded from state instead.
This is similar to [[#OpenUsbEp]] with the params being loaded from state instead.


This is likely intended for re-opening after [[#Close]] was used, but this is not known to be used by any official user-processes.
This is for re-opening after [[#Close]] was used.


==== Close ====
==== Close ====
Line 626: Line 558:


==== 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 '''Id''', and a type-0x5 ([3.0.0+] type-0x21) input buffer, returns an output u32 '''xferId'''.


Line 815: Line 746:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 || GetPowerEvent
| 0 || [[#GetPowerEvent|GetPowerEvent]]
|-
|-
| 1 || GetPowerState
| 1 || [[#GetPowerState|GetPowerState]]
|-
|-
| 2 || GetDataEvent
| 2 || [[#GetDataEvent|GetDataEvent]]
|-
|-
| 3 || GetDataRole
| 3 || [[#GetDataRole|GetDataRole]]
|-
|-
| 4 || SetDiagData
| 4 || [[#SetDiagData|SetDiagData]]
|-
|-
| 5 || GetDiagData
| 5 || [[#GetDiagData|GetDiagData]]
|}
|}


USB Port Manager, only system-title using this is [[PTM_services|ptm]].
USB Port Manager, only system-title using this is [[PTM_services|ptm]].
== GetPowerEvent ==
No input. Returns an output Event handle.
== GetPowerState ==
Takes a type-0x6 output buffer containing an [[#UsbPowerState]]. No output.
== GetDataEvent ==
No input. Returns an output Event handle.
== GetDataRole ==
No input. Returns an output [[#UsbDataRole]].
== SetDiagData ==
Takes two input u32s. No output.
[8.0.0+] Stubbed, just returns 0.
== GetDiagData ==
Takes an input u32. Returns an output u32.
[8.0.0+] Stubbed, just returns 0.


= usb:qdb =
= usb:qdb =
Line 863: Line 816:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 ||  
| 0 || GetTopologyChangeEvent
|-
|-
| 1 ||  
| 1 || GetFlattenedTopology
|}
|}


Line 1,086: Line 1,039:
| 0xF || 0x1 || bInterfaceProtocol
| 0xF || 0x1 || bInterfaceProtocol
|}
|}
This is a 0x10-byte struct (unofficial name).


This is used to filter [[#InterfaceQueryOutput]], the query commands will only return the interface when these checks pass. This is also used for events with [[#CreateInterfaceAvailableEvent]]. When a bit in Flags is set, the associated descriptor field and the field in this struct are compared, on mismatch the interface will be filtered out. Passing Flags=0 is equivalent to disabling filtering since none of these checks will run.
This is used to filter [[#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.
Line 1,251: Line 1,202:
|-
|-
| 3 || Busy
| 3 || Busy
|}
= UsbPowerState =
This is "nn::usb::UsbPowerState".
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x4 || [[#UsbPowerRole|UsbPowerRole]]
|-
| 0x4 || 0x4 || [[#UsbChargerType|UsbChargerType]]
|-
| 0x8 || 0x4 || Voltage
|-
| 0xC || 0x4 || Current
|-
| 0x10 || 0x4 || [[#Pdo|Pdo]]
|-
| 0x14 || 0x4 || [[#Rdo|Rdo]]
|}
= UsbPowerRole =
This is "nn::usb::UsbPowerRole".
{| class="wikitable" border="1"
|-
! Value || Name
|-
| 0 || Unknown
|-
| 1 || Sink
|-
| 2 || Source
|}
= UsbChargerType =
This is "nn::usb::UsbChargerType".
{| class="wikitable" border="1"
|-
! Value || Name
|-
| 0 || Unknown
|-
| 1 || Pd
|-
| 2 || TypeC15
|-
| 3 || TypeC30
|-
| 4 || Dcp
|-
| 5 || Cdp
|-
| 6 || Sdp
|-
| 7 || Apple500
|-
| 8 || Apple1000
|-
| 9 || Apple2000
|}
= SupplyType =
{| class="wikitable" border="1"
|-
! Value || Name
|-
| 0 || Fixed
|-
| 1 || Battery
|-
| 2 || Variable
|}
= Pdo =
When [[#SupplyType|SupplyType]] is Fixed this is:
{| class="wikitable" border="1"
!  Bits
!  Description
|-
| 0-9
| MaximumCurrent
|-
| 10-19
| Voltage
|-
| 20-21
| PeakCurrent
|-
| 22-24
| Reserved
|-
| 25
| DataRoleSwap
|-
| 26
| UsbCommunicationsCapable
|-
| 27
| ExternallyPowered
|-
| 28
| UsbSuspendSupported
|-
| 29
| DualRolePower
|-
| 30-31
| [[#SupplyType|SupplyType]]
|}
When [[#SupplyType|SupplyType]] is Battery this is:
{| class="wikitable" border="1"
!  Bits
!  Description
|-
| 0-9
| MaximumAllowablePower
|-
| 10-19
| MinimumVoltage
|-
| 20-29
| MaximumVoltage
|-
| 30-31
| [[#SupplyType|SupplyType]]
|}
When [[#SupplyType|SupplyType]] is Variable this is:
{| class="wikitable" border="1"
!  Bits
!  Description
|-
| 0-9
| MaximumCurrent
|-
| 10-19
| MinimumVoltage
|-
| 20-29
| MaximumVoltage
|-
| 30-31
| [[#SupplyType|SupplyType]]
|}
= Rdo =
When Pdo's [[#SupplyType|SupplyType]] is Fixed or Variable this is:
{| class="wikitable" border="1"
!  Bits
!  Description
|-
| 0-9
| MaximumOperatingCurrent (GiveBackFlag is true) or MinimumOperatingCurrent (GiveBackFlag is false)
|-
| 10-19
| OperatingCurrent
|-
| 20-23
| Reserved
|-
| 24
| NoUsbSuspend
|-
| 25
| UsbCommunicationsCapable
|-
| 26
| CapabilityMismatch
|-
| 27
| GiveBackFlag
|-
| 28-30
| ObjectPosition
|-
| 31
| Reserved
|}
When Pdo's [[#SupplyType|SupplyType]] is Battery this is:
{| class="wikitable" border="1"
!  Bits
!  Description
|-
| 0-9
| MaximumOperatingPower (GiveBackFlag is true) or MinimumOperatingPower (GiveBackFlag is false)
|-
| 10-19
| OperatingPower
|-
| 20-23
| Reserved
|-
| 24
| NoUsbSuspend
|-
| 25
| UsbCommunicationsCapable
|-
| 26
| CapabilityMismatch
|-
| 27
| GiveBackFlag
|-
| 28-30
| ObjectPosition
|-
| 31
| Reserved
|}
= UsbDataRole =
This is "nn::usb::UsbDataRole".
{| class="wikitable" border="1"
|-
! Value || Name
|-
| 0 || Unknown
|-
| 1 || DFP
|-
| 2 || UFP
|}
|}


Line 1,275: Line 1,454:
** vid "0F0D", where pid is "0200" - "022F".
** vid "0F0D", where pid is "0200" - "022F".
** vid "33DD", where pid is "0001" - "000B".
** vid "33DD", where pid is "0001" - "000B".
= Configuration =
The following is the default USB config strings, while the usbds service isn't being used. All of the below configuration will reset to the defaults when all usbds-related sessions are closed. These can be set with [[#SetVidPidBcd]]. The default string for Product is loaded from [[Settings_services|settings]] config. The default is referred to by usb-sysmodule as "Dummy".
  Product: Nintendo Switch
  Manufacturer: Nintendo
  SerialNumber: SerialNumber
The following is the default <code>lsusb -v {...}</code> output when the usbds service wasn't used.
pre-5.0.0: The endpoints are configured using [[#RegisterEndpoint]], the total number of endpoints is the number of open [[#IDsEndpoint]] sessions. bInterfaceNumber is {0-based index for the enabled [[#IDsInterface]] session.} Some of the interface fields are configured using [[#RegisterInterface]].
When usbds is in use where [[#SetVidPidBcd]] wasn't used, the VID/PID is 057e:3000.
  Bus 003 Device 006: ID 057e:2000 Nintendo Co., Ltd
  Couldn't open device, some information will be missing
  Device Descriptor:
    bLength                18
    bDescriptorType        1
    bcdUSB              2.00
    bDeviceClass            0 (Defined at Interface level)
    bDeviceSubClass        0
    bDeviceProtocol        0
    bMaxPacketSize0        64
    idVendor          0x057e Nintendo Co., Ltd
    idProduct          0x2000
    bcdDevice            1.00
    iManufacturer          1
    iProduct                2
    iSerial                3
    bNumConfigurations      1
    Configuration Descriptor:
      bLength                9
      bDescriptorType        2
      wTotalLength          34
      bNumInterfaces          1
      bConfigurationValue    1
      iConfiguration          0
      bmAttributes        0xc0
        Self Powered
      MaxPower              {...}
      Interface Descriptor:
        bLength                9
        bDescriptorType        4
        bInterfaceNumber        0
        bAlternateSetting      0
        bNumEndpoints          1
        bInterfaceClass        3 Human Interface Device
        bInterfaceSubClass      0 No Subclass
        bInterfaceProtocol      0 None
        iInterface              0
          HID Device Descriptor:
            bLength                9
            bDescriptorType        33
            bcdHID              2.00
            bCountryCode            0 Not supported
            bNumDescriptors        1
            bDescriptorType        34 Report
            wDescriptorLength      26
          Report Descriptors:
            ** UNAVAILABLE **
        Endpoint Descriptor:
          bLength                7
          bDescriptorType        5
          bEndpointAddress    0x81  EP 1 IN
          bmAttributes            3
            Transfer Type            Interrupt
            Synch Type              None
            Usage Type              Data
          wMaxPacketSize    0x0001  1x 1 bytes
          bInterval              16


[[Category:Services]]
[[Category:Services]]