Bluetooth Driver services: Difference between revisions

No edit summary
 
(67 intermediate revisions by 5 users not shown)
Line 215: Line 215:
|-
|-
| 100 || [12.0.0+] [[#IsBluetoothEnabled]]
| 100 || [12.0.0+] [[#IsBluetoothEnabled]]
|-
| 101 || [15.0.0+] ForceEnableBluetooth
|-
| 102 || [15.0.0+] EnableBluetoothStub
|-
|-
| 128 || [12.0.0+] [[#AcquireAudioEvent]]
| 128 || [12.0.0+] [[#AcquireAudioEvent]]
Line 248: Line 252:
| 143 || [12.0.0+] [[#GetAudioControlInputState]]
| 143 || [12.0.0+] [[#GetAudioControlInputState]]
|-
|-
| 144 || [12.0.0+] [[#AcquireAudioConnectionStateChangedEvent]]
| 144 || [12.0.0-13.2.1] [[#AcquireAudioConnectionStateChangedEvent]]
|-
| 145 || [12.0.0-13.2.1] [[#GetConnectedAudioDevice]]
|-
| 146 || [13.0.0+] [[#CloseAudioControlInput]]
|-
| 147 || [13.0.0+] [[#RegisterAudioControlNotification]]
|-
| 148 || [13.0.0+] [[#SendAudioControlPassthroughCommand]]
|-
| 149 || [13.0.0+] [[#SendAudioControlSetAbsoluteVolumeCommand]]
|-
|-
| 145 || [12.0.0+] [[#GetConnectedAudioDevice]]
| 150 || [14.0.0+] AcquireAudioSinkVolumeLocallyChangedEvent
|-
| 151 || [14.0.0+] AcquireAudioSinkVolumeUpdateRequestCompletedEvent
|-
| 152 || [14.0.0+] GetAudioSinkVolume
|-
| 153 || [14.0.0+] RequestUpdateAudioSinkVolume
|-
| 154 || [14.0.0+] IsAudioSinkVolumeSupported
|-
| 155 || [15.0.0+] IsAudioSinkVolumeSupported2
|-
|-
| 256 || [5.0.0+] [[#IsManufacturingMode]]
| 256 || [5.0.0+] [[#IsManufacturingMode]]
Line 318: Line 342:
* Uses SetValue with the param which was passed to this func.
* Uses SetValue with the param which was passed to this func.
* Does cleanup for the session object and exits the service.
* Does cleanup for the session object and exits the service.
[12.0.0+] The Enable vfunc called above for Audio does the following:
* Calls a func which does the following:
** Uses BSA to enable AV. Besides the callback, the only field in the passed struct which is set is <code>features</code>. This is ORRed to set bit0 for "remote control target", which with [13.0.0+] is only done if [[System_Settings|system-setting]] <code>bluetooth_debug!is_av_rc_tg</code> is set to true. With [14.0.0+] this is also ORRed with value 0xA (bit1/bit3) when [[System_Settings|system-setting]] <code>bluetooth_debug!is_av_rc_ct</code> is set to true (which is the case for [14.0.0+]).
** Error handling + state setup is done.
** Uses BSA to register AV twice, with the default input struct.
** Error handling + state setup is done.
* If an error occurred in a certain range, a [[#FatalReason|fatal]] is triggered and 0 is returned.
* Otherwise when successful, state init is done then 0 is returned.


== DisableBluetooth ==
== DisableBluetooth ==
Line 324: Line 357:
This is used by [[BTM_services|btm]].
This is used by [[BTM_services|btm]].


This calls an interface funcptr. On success, the funcs for updating the interface funcptr tables are called (same as [[#InitializeBluetooth]]). Then the converted ret is returned as needed.
[1.0.0-11.0.1] This calls an interface funcptr. On success, the funcs for updating the interface funcptr tables are called (same as [[#InitializeBluetooth]]). Then the converted ret is returned as needed.
 
* [12.0.0+] Vfuncs for various interface objects are called, with failure triggering an Abort in some cases.
* [12.0.0+] Calls funcs to update interfaces object ptrs to use the disabled-object.
* [12.0.0+] Calls the same GPIO func as [[#EnableBluetooth]] with param=0, then 0 is returned.
* [12.0.0+] Various code described below was moved into the above vfunc(s), etc.


When bluetooth is already disabled, that funcptr just returns 0. Otherwise when it's already enabled, it does the following:
When bluetooth is already disabled, that funcptr just returns 0. Otherwise when it's already enabled, it does the following:
Line 496: Line 534:


== TriggerConnection ==
== TriggerConnection ==
Takes an input [[#Address]] and an u16, no output.
Takes an input [[#Address]] and a u16 timeout, no output.


This is used by [[BTM_services|btm]].
This is used by [[BTM_services|btm]].
Line 503: Line 541:


The funcptr does the following:
The funcptr does the following:
* Calls a func, returning the ret on failure. This uses a BSA extension (message 0x8CE), with the input u16 being used with this.
* Calls a func, returning the ret on failure. This uses a BSA extension (message 0x8CE), with the u16 timeout being used with this.
* Then another func is called, with the input [[#Address]], with the ret from here being returned. This throws an error if the device isn't paired. This opens a HID-Host connection to the specified [[#Address]]. The passed sec_mask is 0x12 (Inbound/outbound authentication required), and brcm_mask is set for enabling TBFC Page.
* Then another func is called, with the input [[#Address]], with the ret from here being returned. This throws an error if the device isn't paired. This opens a HID-Host connection to the specified [[#Address]]. The passed sec_mask is 0x12 (Inbound/outbound authentication required), and brcm_mask is set for enabling TBFC Page.


The handler for the above message with the used bit flag does the following:
The handler for the above message with the used bit flag does the following:
* Uses HCI vendor command 0xFCC2 with param_len=0xE. Param data: u32 +0 = 0x14E18, u16 +4 = 0x20, u8 +6 = 0x2, u16 +7 = {input u16 message param value} (written via u8 writes), u32 +9 = 0x30200, u8 +0xD = 0.
* Uses HCI vendor command 0xFCC2 (TBFC Write Parameters) with param_len=0xE. Param data: u16 timeout value is inserted into the following tAPP_TM_TBFC_PARAM structure initialized with default values. The default host trigger timeout used elsewhere is 0x1800.
 
{| class="wikitable" border="1"
== AddPairedDeviceInfo ==
|-
Takes a type-0x19 input buffer containing [[Settings_services#BluetoothDevicesSettings|BluetoothDevicesSettings]], no output.
! Offset
 
! Size
This is used by [[BTM_services|btm]].
! Description
 
! Value
|-
| 0x0
| 0x1
| BfcEnable
| 0x1
|-
| 0x1
| 0x1
| Frequency1
| 0x0
|-
| 0x2
| 0x1
| Frequency2
| 0x18
|-
| 0x3
| 0x1
| Frequency3
| 0x4E
|-
| 0x4
| 0x1
| AccessCodeLength
| 0x20
|-
| 0x5
| 0x2
| HostScanInterval
| 0x200
|-
| 0x7
| 0x2
| HostTriggerTimeout
| timeout
|-
| 0x9
| 0x2
| HidScanInterval
| 0x200
|-
| 0xB
| 0x1
| HidScanRetry
| 0x3
|-
| 0xC
| 0x1
| DontDisturb
| 0x0
|-
| 0xD
| 0x1
| WakeUpMask
| 0x0
|}
 
== AddPairedDeviceInfo ==
Takes a type-0x19 input buffer containing [[Settings_services#BluetoothDevicesSettings|BluetoothDevicesSettings]], no output.
 
This is used by [[BTM_services|btm]].
 
[12.0.0+] If [[Settings_services#BluetoothDevicesSettings|TrustedServices]] is 0, value 0x100000 is used. When bit20 is set, HID is initialized for this device, otherwise when bitmask 0xC0000 is set (<code>if((TrustedServices & 0xC0000) != 0)</code>) [[#OpenAudioConnection|audio]] is initialized for this device.
 
== GetPairedDeviceInfo ==
== GetPairedDeviceInfo ==
Takes an input [[#Address]] and a type-0x1A output buffer containing [[Settings_services#BluetoothDevicesSettings|BluetoothDevicesSettings]].
Takes an input [[#Address]] and a type-0x1A output buffer containing [[Settings_services#BluetoothDevicesSettings|BluetoothDevicesSettings]].
Line 771: Line 873:


== ConnectGattServer ==
== ConnectGattServer ==
Takes an input u8, an [[#Address]], a bool, an [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], no output.
Takes an input u8 client_if, an [[#Address]], a bool, an [[Applet_Manager_services#AppletResourceUserId|AppletResourceUserId]], no output.


This is used by [[BTM_services|btm]].
This is used by [[BTM_services|btm]].
The input bool and AppletResourceUserId are unused.
The is_direct field passed to BSA is value 1.


== CancelConnectGattServer ==
== CancelConnectGattServer ==
Line 924: Line 1,030:
== SetBleScanParameter ==
== SetBleScanParameter ==
Takes two input u16s, no output.
Takes two input u16s, no output.
The first u16 is scan_interval, the second u16 is scan_window.


This is used by [[BTM_services|btm]].
This is used by [[BTM_services|btm]].
Line 941: Line 1,049:


sdknso uses an user-specified EventClearMode.
sdknso uses an user-specified EventClearMode.
This just gets a previously-initialized Event from global state, [[#IsManufacturingMode]] is used to select which Event to use.


== GetAudioEventInfo ==
== GetAudioEventInfo ==
Takes a type-0xA output buffer, returns an output [[#AudioEventType]].
Takes a type-0xA output buffer, returns an output [[#AudioEventType]].
This is essentially the same as the other [12.0.0+] Get*EventInfo cmds, however in this case the output type is set to value 0 when no event is available.
See [[#AudioEventInfo]].


== OpenAudioConnection ==
== OpenAudioConnection ==
Takes an input [[#Address]], no output.
Takes an input [[#Address]], no output.
This goes through state and eventually uses BSA to open an AV connection. The input struct has the RC flag set to true. sec_mask is set to require authentication and encryption.


== CloseAudioConnection ==
== CloseAudioConnection ==
Takes an input [[#Address]], no output.
Takes an input [[#Address]], no output.
This goes through state and eventually uses BSA to close an AV connection.


== OpenAudioOut ==
== OpenAudioOut ==
Takes an input [[#Address]], returns an output u32.
Takes an input [[#Address]], returns an output u32 audio_handle.


== CloseAudioOut ==
== CloseAudioOut ==
Takes an input u32, no output.
Takes an input u32 [[#OpenAudioOut|audio_handle]], no output.


== AcquireAudioOutStateChangedEvent ==
== AcquireAudioOutStateChangedEvent ==
Takes an input u32, returns an output Event handle.
Takes an input u32 [[#OpenAudioOut|audio_handle]], returns an output Event handle.


sdknso uses an user-specified EventClearMode.
sdknso uses an user-specified EventClearMode.


== StartAudioOut ==
== StartAudioOut ==
Takes an input u32, a [[#PcmParameter]], a nn::TimeSpan, returns an output nn::TimeSpan and u64.
Takes an input u32 [[#OpenAudioOut|audio_handle]], a [[#PcmParameter]], a nn::TimeSpan latency, returns an output nn::TimeSpan latency and u64.
 
This eventually uses BSA to start an AV stream. The codec is "Raw PCM". Synchronous feeding mode is used.


== StopAudioOut ==
== StopAudioOut ==
Takes an input u32, no output.
Takes an input u32 [[#OpenAudioOut|audio_handle]], no output.
 
This eventually uses BSA to stop an AV stream. The pause flag is set to false.


== GetAudioOutState ==
== GetAudioOutState ==
Takes an input u32, returns an output [[#AudioOutState]].
Takes an input u32 [[#OpenAudioOut|audio_handle]], returns an output [[#AudioOutState]].


== GetAudioOutFeedingCodec ==
== GetAudioOutFeedingCodec ==
Takes an input u32, returns an output [[#AudioCodec]].
Takes an input u32 [[#OpenAudioOut|audio_handle]], returns an output [[#AudioCodec]].


== GetAudioOutFeedingParameter ==
== GetAudioOutFeedingParameter ==
Takes an input u32, returns an output [[#PcmParameter]].
Takes an input u32 [[#OpenAudioOut|audio_handle]], returns an output [[#PcmParameter]].


== AcquireAudioOutBufferAvailableEvent ==
== AcquireAudioOutBufferAvailableEvent ==
Takes an input u32, returns an output Event handle.
Takes an input u32 [[#OpenAudioOut|audio_handle]], returns an output Event handle.


sdknso uses an user-specified EventClearMode.
sdknso uses an user-specified EventClearMode.
This gets an Event which was previously initialized.


== SendAudioData ==
== SendAudioData ==
Takes an input u32, a type-0x9 input buffer, returns an output u64.
Takes an input u32 [[#OpenAudioOut|audio_handle]], a type-0x9 input buffer, returns an output u64 transferred_size.
 
This eventually uses BSA to send the specified buffer to the required UIPC channel. If transferred_size doesn't match the buffer size, error 0x177A71 is returned. transferred_size is always either 0 (error occured) or the buffer size.


== AcquireAudioControlInputStateChangedEvent ==
== AcquireAudioControlInputStateChangedEvent ==
Line 989: Line 1,115:


sdknso uses an user-specified EventClearMode.
sdknso uses an user-specified EventClearMode.
This gets an Event which was previously initialized.


== GetAudioControlInputState ==
== GetAudioControlInputState ==
Takes a type-0xA output buffer containing an array of [[#AudioControlButtonState]], returns an output s32.
Takes a type-0xA output buffer containing an array of [[#AudioControlButtonState]], returns an output s32 total_out.
 
A maximum of 0xF entries can be returned.


== AcquireAudioConnectionStateChangedEvent ==
== AcquireAudioConnectionStateChangedEvent ==
Line 997: Line 1,127:


sdknso uses an user-specified EventClearMode.
sdknso uses an user-specified EventClearMode.
This gets an Event which was previously initialized.


== GetConnectedAudioDevice ==
== GetConnectedAudioDevice ==
Takes a type-0xA output buffer containing an array of [[#Address]], returns an output s32.
Takes a type-0xA output buffer containing an array of [[#Address]], returns an output s32 total_out.
 
A maximum of 0x8 entries can be returned.
 
== CloseAudioControlInput ==
Takes an input [[#Address]], no output.
 
This uses the BSA AV API to close the AVRCP connection.
 
== RegisterAudioControlNotification ==
Takes an input [[#Address]] and an u32 [[#AvrcEventType]], no output.
 
This uses the BSA AV API to send a vendor control command: ctype=0x3, label={counter which is incremented}, length=0x9, data=[0x31, 0x00, 0x00, 0x05, {u8 [[#AvrcEventType]]}, {rest is zeros}].
 
This does nothing since BSA requires [[#EnableBluetooth|features]] bit1 and bit3 to be set in order to use this.
 
== SendAudioControlPassthroughCommand ==
Takes an input [[#Address]], an u32 [[#AvrcOperationId]], an u32 [[#AvrcStateType]], no output.
 
This uses the BSA AV API to send a remote control command: label={counter which is incremented}, rc_id=[[#AvrcOperationId]], key_state=[[#AvrcStateType]].
 
This does nothing since BSA requires [[#EnableBluetooth|features]] bit1 to be set in order to use this.
 
== SendAudioControlSetAbsoluteVolumeCommand ==
Takes an input [[#Address]] and a s32, no output.
 
This uses the BSA AV API to send a vendor control command: ctype=0x0, label={counter which is incremented}, length=0x5, data=[0x50, 0x00, 0x00, 0x01, {input s32 value written as an u8}].
 
See [[#RegisterAudioControlNotification]] regarding the usage requirement.


== IsManufacturingMode ==
== IsManufacturingMode ==
Line 1,469: Line 1,629:
|}
|}


[1.0.0-11.0.1] [[#EventType|Type7]]:
[1.0.0-8.1.1] [[#EventType|Type7]]:


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,476: Line 1,636:
! Size
! Size
! Description
! Description
|-
|-
| 0x0 || 0x4 || Status, always 0 except with [[#ConnectionEventType|event0]]: 2 = ACL Link is now Resumed (BSA_SEC_RESUMED_EVT), 9 = connection failed (pairing/authentication failed, or opening the hid connection failed).
| 0x0 || 0x6 || Device [[#Address|address]].
|-
|-
| 0x4 || 0x6 || Device [[#Address|address]].
| 0x6 || 0x2 || Padding
|-
|-
| 0xA || 0x2 || Padding
| 0x8 || 0x4 || Status, always 0 except with [[#ConnectionEventType|event0]]: 2 = ACL Link is now Resumed (BSA_SEC_RESUMED_EVT), 9 = connection failed (pairing/authentication failed, or opening the hid connection failed).
|-
|-
| 0xC || 0x4 || [[#ConnectionEventType]]
| 0xC || 0x4 || [[#ConnectionEventType]]
|}
|}


[12.0.0+] [[#EventType|Type4]]:
[9.0.0-11.0.1] [[#EventType|Type7]]:


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,494: Line 1,655:
! Description
! Description
|-
|-
| 0x0 || 0x4 || [[#ConnectionEventType]]
| 0x0 || 0x4 || Status, always 0 except with [[#ConnectionEventType|event0]]: 2 = ACL Link is now Resumed (BSA_SEC_RESUMED_EVT), 9 = connection failed (pairing/authentication failed, or opening the hid connection failed).
|-
|-
| 0x4 || 0x6 || Device [[#Address|address]].
| 0x4 || 0x6 || Device [[#Address|address]].
|-
|-
| 0xA || 0xFE || Reserved
| 0xA || 0x2 || Padding
|-
| 0xC || 0x4 || [[#ConnectionEventType]]
|}
 
[12.0.0+] [[#EventType|Type4]]:
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || [[#ConnectionEventType]]
|-
| 0x4 || 0x6 || Device [[#Address|address]].
|-
| 0xA || 0xFE || Reserved
|}
|}


Line 1,592: Line 1,770:
[[#HidEventType|Type0]], for [[#GetHidEventInfo]]:
[[#HidEventType|Type0]], for [[#GetHidEventInfo]]:


[1.0.0-11.0.1]
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
Line 1,602: Line 1,781:
| 0x6 || 0x2 || Padding
| 0x6 || 0x2 || Padding
|-
|-
| 0x8 || 0x4 || Status:
| 0x8 || 0x4 || Status: 0 = hid connection opened, 2 = hid connection closed, 8 = failed to open hid connection.
[1.0.0-11.0.1] 0 = hid connection opened, 2 = hid connection closed, 8 = failed to open hid connection.
|}


[12.0.0+] 0 = hid connection closed, 1 = hid connection opened, 2 = failed to open hid connection.
[12.0.0+]
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Status: 0 = hid connection closed, 1 = hid connection opened, 2 = failed to open hid connection.
|-
| 0x4 || 0x6 || Device [[#Address|address]].
|}
|}


Line 1,736: Line 1,924:
This is "nn::bluetooth::BleAdvertiseFilter". This is a 0x3E-byte struct.
This is "nn::bluetooth::BleAdvertiseFilter". This is a 0x3E-byte struct.


= BleAdvertisePacketParameter =
{| class="wikitable" border="1"
This is "nn::bluetooth::BleAdvertisePacketParameter". This is a 8-byte struct with 1-byte alignment.
|-
 
= BleScanResult =
This is "nn::bluetooth::BleScanResult". This is a 0x148-byte struct.
 
{| class="wikitable" border="1"
|-
! Offset
! Offset
! Size
! Size
! Description
! Description
|-
|-
| 0x0 || 0x1 ||  
| 0x0 || 0x1 || FilterId
|-
| 0x1 || 0x1 || CondDataSize. Only used with CondType Manu.
|-
|-
| 0x1 || 0x6 || [[#Address]]
| 0x2 || 0x1 || CondType
|-
|-
| 0x7 || 0x139 ||  
| 0x3 || 0x1D || CondData, content depends on CondType.
|-
|-
| 0x140 || 0x4 || s32
| 0x20 || 0x1D || Mask. Only used with CondType Manu. +0 = u16 CompanyIdMask, then {pattern mask}.
|-
|-
| 0x144 || 0x4 || s32
| 0x3D || 0x1 || MaskSize. Only used with CondType Manu.
|}
|}


= BleConnectionInfo =
CondType:
This is "nn::bluetooth::BleConnectionInfo". This is a 0xC-byte struct.
 
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Offset
! Value
! Size
! Name
! Description
! Description
|-
|-
| 0x0 || 0x4 || ConnectionHandle, 0xFFFFFFFF ([5.0.0-5.0.2] 0xFFFF) is invalid.
| 2-3 || || ServiceUuid16. CondData = 16bit UUID which is byteswapped.
|-
|-
| 0x4 || 0x6 || [[#Address]]
| 4-5 || || ServiceUuid32. CondData = 32bit UUID which is byteswapped.
|-
|-
| 0xA || 0x2 || Padding
| 6-7 || || ServiceUuid128. CondData = 128bit UUID which is copied raw into the param struct.
|-
|-
| 255 || || Manu. CondData: u16 CompanyId, then {pattern data}.
|}
|}


= GattAttributeUuid =
To pass filtering, the BLE advert data should be: data & Mask == CondData (following the type field in the advert entry with the matching type).
This is "nn::bluetooth::GattAttributeUuid". This is a 0x14-byte struct with 4-byte alignment.


{| class="wikitable" border="1"
= BleAdvertisePacketParameter =
|-
This is "nn::bluetooth::BleAdvertisePacketParameter". This is a 8-byte struct with 1-byte alignment.
 
[[BTM_services#StartBleScanForGeneral|StartBleScanForGeneral]] generates a [[#BleAdvertiseFilter]] from this. CondType = Manu, CondDataSize = 0xA. CondData: +0 = u16 CompanyId, u8 +2 = 0x1, +3 = {data copied from PatternData, then an u8 with value 0x0}. MaskSize = 0x9, Mask = {all 0xFF}.
 
[[BTM_services#StartBleScanForPaired|StartBleScanForPaired]] generates a [[#BleAdvertiseFilter]] from this, similar to the above. CondType = Manu, CondDataSize = 0x11. CondData: +0 = u16 CompanyId, u8 +2 = 0x1, +3 = {data copied from PatternData, then an u8 with value 0x0, then {6-byte system btaddr}}. MaskSize = 0x10, Mask = {all 0xFF except u8 +0x9 which is 0x0}.
 
{| class="wikitable" border="1"
|-
! Offset
! Offset
! Size
! Size
! Description
! Description
|-
|-
| 0x0 || 0x4 || UUID size, must be 0x2, 0x4, or 0x10.
| 0x0 || 0x2 || CompanyId
|-
|-
| 0x4 || 0x10 || UUID with the above size.
| 0x2 || 0x6 || PatternData
|}
|}


= GattId =
= BleScanResult =
This is "nn::bluetooth::GattId". This is a 0x18-byte struct with 4-byte alignment.
This is "nn::bluetooth::BleScanResult". This is a 0x148-byte struct.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,799: Line 1,988:
! Description
! Description
|-
|-
| 0x0 || 0x1 || InstanceId
| 0x0 || 0x1 ||  
|-
| 0x1 || 0x6 || [[#Address]]
|-
| 0x7 || || Array of entries where each entry is 0x1F-bytes. hid compares +1 with 0xFF and +0x2 with the cached output from [[#BTM_services#GetBleScanParameterGeneral|GetBleScanParameterGeneral]] (entry+0x4 is skipped over).
|-
|-
| 0x1 || 0x3 || Padding
| 0x140 || 0x4 || s32 Total entries in the array at 0x8.
|-
|-
| 0x4 || 0x14 || [[#GattAttributeUuid]]
| 0x144 || 0x4 || s32
|}
|}


= LeEventInfo =
= BleConnectionInfo =
This is a 0x400-byte struct.
This is "nn::bluetooth::BleConnectionInfo". This is a 0xC-byte struct.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,815: Line 2,008:
! Description
! Description
|-
|-
| 0x0 || 0x4 ||  
| 0x0 || 0x4 || ConnectionHandle, 0xFFFFFFFF ([5.0.0-5.0.2] 0xFFFF) is invalid.
|-
|-
| 0x4 || 0x4 ||  
| 0x4 || 0x6 || [[#Address]]
|-
|-
| 0x8 || 0x1 ||  
| 0xA || 0x2 || Padding
|-
|-
| 0x9 || 0x3 || Padding
|}
|-
 
| 0xC || 0x14 || [[#GattAttributeUuid]]
= GattAttributeUuid =
This is "nn::bluetooth::GattAttributeUuid". This is a 0x14-byte struct with 4-byte alignment.
 
{| class="wikitable" border="1"
|-
|-
| 0x20 || 0x14 || [[#GattAttributeUuid]]
! Offset
! Size
! Description
|-
|-
| 0x34 || 0x14 || [[#GattAttributeUuid]]
| 0x0 || 0x4 || [[#BleGattUuid]] size. Must be 0x2, 0x4, or 0x10.
|-
|-
| 0x48 || 0x2 || Size of the below data.
| 0x4 || 0x10 || [[#BleGattUuid]] with the above size.
|-
| 0x4A || {above size} || Data.
|}
|}


= BleClientGattOperationInfo =
= GattId =
This is "nn::bluetooth::BleClientGattOperationInfo". This is converted from [[#LeEventInfo]].
This is "nn::bluetooth::GattId". This is a 0x18-byte struct with 4-byte alignment.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 1,843: Line 2,039:
! Description
! Description
|-
|-
| 0x0 || 0x1 || Converted from [[#LeEventInfo]]+0x0.
| 0x0 || 0x1 || InstanceId
|-
|-
| 0x1 || 0x3 || Padding
| 0x1 || 0x3 || Padding
|-
|-
| 0x4 || 0x4 || Same as [[#LeEventInfo]]+0x4.
| 0x4 || 0x14 || [[#GattAttributeUuid]]
|}
 
= BleGattUuid =
This is an enum of u16, u32 and u128 values.
 
{| class="wikitable" border="1"
|-
!  Value
!  Description
|-
|-
| 0x8 || 0x1 || Same as [[#LeEventInfo]]+0x8.
| 0x2902 || ClientConfigUuid16
|-
|-
| 0x9 || 0x3 || Padding
| 0x2908 || ReportReferenceUuid16
|-
|-
| 0xC || 0x14 || Same as [[#LeEventInfo]]+0xC.
| 0x1B666C080A578E83994EA7F7BF50DDA3 || PalmaOtafuControlPointUuid128
|-
|-
| 0x20 || 0x14 || Same as [[#LeEventInfo]]+0x20.
| 0x26FE2EE709244FB7914061D97A6CE8A2 || PalmaOtafuDataUuid128
|-
|-
| 0x34 || 0x14 || Same as [[#LeEventInfo]]+0x34.
| 0x45CEF889AF8E0784664404737C7FBE2B || NbatUuid128
|-
|-
| 0x48 || 0x8 || Same as [[#LeEventInfo]]+0x48.
| 0x46CEF889AF8E0784664404737C7FBE2B || BatteryLevelUuid128
|-
|-
| 0x50 || {above size} || Same as [[#LeEventInfo]]+0x4A.
| 0x47CEF889AF8E0784664404737C7FBE2B || BatteryStateUuid128
|}
|-
 
| 0xD88B7646729DBDA17A4425F4101126C7 || PalmaOtafuUuid128
= AudioEventType =
|-
This is "nn::bluetooth::hal::AudioEventType". This is an u32 enum.
| 0xE5237AE2516B55BB67456DF36CE17566 || NhogUuid128
 
|-
= PcmParameter =
| 0xE6237AE2516B55BB67456DF36CE17566 || InputReportUuid128
This is "nn::bluetooth::system::PcmParameter". This is a 0xC-byte struct with 4-byte alignment.
|-
 
| 0xE7237AE2516B55BB67456DF36CE17566 || OutputCommandUuid128
= AudioOutState =
|-
This is "nn::bluetooth::system::AudioOutState". This is an u32 enum.
| 0xE8237AE2516B55BB67456DF36CE17566 || CommandResponseUuid128
 
|}
= AudioCodec =
 
This is "nn::bluetooth::system::AudioCodec". This is an u32 enum.
= BleClientGattOperationStatus =
 
This is an u8 enum. This is converted from the [[#LeEventInfo]] status field.
= AudioControlButtonState =
 
This is "nn::bluetooth::system::AudioControlButtonState". This is a 0x10-byte struct.
{| class="wikitable" border="1"
 
|-
= Notes =
!  Value
The output from <code>sudo hcitool info {BDADDR}</code> is identical for [1.0.0-11.0.0]:
!  Name
 
!  Description
   BD Address:  {BDADDR}
|-
   OUI Company: Nintendo Co.,Ltd (98-B6-E9)
| 0 || || Same as [[#LeEventInfo]] status 0.
   Device Name: Nintendo Switch
|-
   LMP Version: 4.2 (0x8) LMP Subversion: 0x2409
| 1 || || Same as [[#LeEventInfo]] status 55.
   Manufacturer: Broadcom Corporation (15)
|-
   Features page 0: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
| 2 || || Same as [[#LeEventInfo]] status 25, 52.
     <3-slot packets> <5-slot packets> <encryption> <slot offset>  
|-
     <timing accuracy> <role switch> <sniff mode> <RSSI>  
| 3 || || Same as [[#LeEventInfo]] status 4, 16, 21, 50.
     <channel quality> <SCO link> <HV2 packets> <HV3 packets>  
|-
     <u-law log> <A-law log> <CVSD> <paging scheme> <power control>  
| 4 || || Same as [[#LeEventInfo]] status 5.
     <transparent SCO> <broadcast encrypt> <EDR ACL 2 Mbps>  
|-
     <EDR ACL 3 Mbps> <enhanced iscan> <interlaced iscan>  
| 5 || || Same as [[#LeEventInfo]] status 6.
|-
| 6 || || Same as [[#LeEventInfo]] status 7.
|-
| 7 || || Same as [[#LeEventInfo]] status 9.
|-
| 8 || || Same as [[#LeEventInfo]] status 13.
|-
| 9 || || Used as the default case when the [[#LeEventInfo]] status is unrecognized.
|-
| 10 || || Same as [[#LeEventInfo]] status 35.
|}
 
= LeEventInfo =
This is a 0x400-byte struct.
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Status. 0 = success, non-zero = error.
|-
| 0x4 || 0x4 || ConnectionId
|-
| 0x8 || 0x1 || Flags. Bit0 = IsWrite, bit1 = IsDescriptor, bit2 = IsNotify.
When bit2 is set, bit0 = IsIndication.
|-
| 0x9 || 0x3 || Padding
|-
| 0xC || 0x14 || Service [[#GattAttributeUuid]]
|-
| 0x20 || 0x14 || Characteristic [[#GattAttributeUuid]]
|-
| 0x34 || 0x14 || Descriptor [[#GattAttributeUuid]]
|-
| 0x48 || 0x2 || Size of the below data.
|-
| 0x4A || 0x200 || Data with the above size.
|}
 
= BleClientGattOperationInfo =
This is "nn::bluetooth::BleClientGattOperationInfo". This is converted from [[#LeEventInfo]].
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x1 || [[#BleClientGattOperationStatus]]
|-
| 0x1 || 0x3 || Padding
|-
| 0x4 || 0x4 || Same as [[#LeEventInfo]]+0x4.
|-
| 0x8 || 0x1 || Same as [[#LeEventInfo]]+0x8.
|-
| 0x9 || 0x3 || Padding
|-
| 0xC || 0x14 || Same as [[#LeEventInfo]]+0xC.
|-
| 0x20 || 0x14 || Same as [[#LeEventInfo]]+0x20.
|-
| 0x34 || 0x14 || Same as [[#LeEventInfo]]+0x34.
|-
| 0x48 || 0x8 || Same as [[#LeEventInfo]]+0x48.
|-
| 0x50 || {above size} || Same as [[#LeEventInfo]]+0x4A.
|}
 
= AudioEventType =
This is "nn::bluetooth::hal::AudioEventType". This is an u32 enum.
 
{| class="wikitable" border="1"
|-
!  Value
!  Name
!  Description
|-
| 0 || || None
|-
| 1 || || Connection
|}
 
= AudioEventInfo =
This is the output buffer for [[#GetAudioEventInfo]]. The data stored here depends on the [[#AudioEventType]].
 
[[#AudioEventType|Type1]]:
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Status: 0 = AV connection closed, 1 = AV connection opened, 2 = failed to open AV connection.
|-
| 0x4 || 0x6 || Device [[#Address|address]].
|-
| 0xA || 0x2 || Padding
|}
 
= PcmParameter =
This is "nn::bluetooth::system::PcmParameter". This is a 0xC-byte struct with 4-byte alignment.
 
The sysmodule will Abort if any of these fields are invalid.
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || Must be 0-3. Controls number of channels: 0 = mono, non-zero = stereo.
|-
| 0x4 || 0x4 || s32 SampleRate. Must be one of the following: 16000, 32000, 44100, 48000.
|-
| 0x8 || 0x4 || Bits per sample. Must be 8 or 16.
|}
 
= AudioOutState =
This is "nn::bluetooth::system::AudioOutState". This is an u32 enum.
 
{| class="wikitable" border="1"
|-
!  Value
!  Description
|-
| 0 || Stopped
|-
| 1 || Started
|}
 
= AudioCodec =
This is "nn::bluetooth::system::AudioCodec". This is an u32 enum.
 
{| class="wikitable" border="1"
|-
!  Value
!  Description
|-
| 0 || Raw PCM
|}
 
= AudioControlButtonState =
This is "nn::bluetooth::system::AudioControlButtonState". This is a 0x10-byte struct.
 
= AvrcEventType =
This is "nn::bluetooth::hal::AvrcEventType".
 
= AvrcOperationId =
This is "nn::bluetooth::hal::AvrcOperationId". This is the same as tBSA_AV_RC.
 
= AvrcStateType =
This is "nn::bluetooth::hal::AvrcStateType". This is the same as tBSA_AV_STATE.
 
= Notes =
The output from <code>sudo hcitool info {BDADDR}</code> is identical for [1.0.0-11.0.0]:
 
   BD Address:  {BDADDR}
   OUI Company: Nintendo Co.,Ltd (98-B6-E9)
   Device Name: Nintendo Switch
   LMP Version: 4.2 (0x8) LMP Subversion: 0x2409
   Manufacturer: Broadcom Corporation (15)
   Features page 0: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
     <3-slot packets> <5-slot packets> <encryption> <slot offset>  
     <timing accuracy> <role switch> <sniff mode> <RSSI>  
     <channel quality> <SCO link> <HV2 packets> <HV3 packets>  
     <u-law log> <A-law log> <CVSD> <paging scheme> <power control>  
     <transparent SCO> <broadcast encrypt> <EDR ACL 2 Mbps>  
     <EDR ACL 3 Mbps> <enhanced iscan> <interlaced iscan>  
     <interlaced pscan> <inquiry with RSSI> <extended SCO>  
     <interlaced pscan> <inquiry with RSSI> <extended SCO>  
     <EV4 packets> <EV5 packets> <AFH cap. slave>  
     <EV4 packets> <EV5 packets> <AFH cap. slave>  
Line 1,910: Line 2,287:
The bluetooth stack is Broadcom/Cypress brcm BSA (for example, see [https://github.com/hardkernel/buildroot_linux_amlogic_brcm-bsa here]).
The bluetooth stack is Broadcom/Cypress brcm BSA (for example, see [https://github.com/hardkernel/buildroot_linux_amlogic_brcm-bsa here]).


Various btdrv service commands use a custom BSA extension (message-ids based at 0x8CA/2250), this is referred to as "robson".
Various btdrv service commands use a custom BSA extension (message-ids based at 0x8CA/2250), this is referred to as "robson". The following BSA modules are supported by the BSA server task thread (including the aforementioned robson): sys, dm, disc, sec, hh, [12.0.0+] av, dg, tm, ble.


The following L2CAP services are registered (dynamic channels): SDP, ATT (GATT), RFCOMM, HID (PSMs: 0x11, 0x13, 0x8001, 0x8003).
The following L2CAP services are registered (dynamic channels): SDP, ATT (GATT), RFCOMM, HID (PSMs: 0x11, 0x13, 0x8001, 0x8003), [12.0.0+] AVCTP/AVCTP_Browsing (only when the features bitfield passed to BSA_AvEnable by [[#EnableBluetooth]] has bit0 ("remote control target") or bit1 set), [12.0.0+] AVDTP.


<code>l2cu_send_peer_echo_rsp</code> is called with p_data=NULL and data_len=0, therefore no data is returned in the L2CAP ECHO response.
<code>l2cu_send_peer_echo_rsp</code> is called with p_data=NULL and data_len=0, therefore no data is returned in the L2CAP ECHO response.
Line 1,977: Line 2,354:
| CYW4356A3_001.004.009.0092.0095
| CYW4356A3_001.004.009.0092.0095
|-
|-
| [12.0.0]
| [12.0.0-14.1.2]
| BSA0106_01.60.00_
| BSA0106_01.60.00_
| Hayward_T3_RC_20210224
| Hayward_T3_RC_20210224
| CYW4356A3_001.004.009.0092.0095
| CYW4356A3_001.004.009.0092.0095
|-
| [15.0.0-20.1.0]
| BSA0106_01.60.00_
| Hayward_T3_RC_20210224
| BCM4356A3 UART 37.4 MHz wlbga_bu
|}
|}


<code>bsa_sv_tm_read_version_excback</code> copies bsa_version_string and concats with bsa_version_info_string to generate <code>tBSA_TM_READ_VERSION.bsa_server_version</code>.
<code>bsa_sv_tm_read_version_excback</code> copies bsa_version_string and concats with bsa_version_info_string to generate <code>tBSA_TM_READ_VERSION.bsa_server_version</code>.
* [15.0.0]: In the HCI memwrite data, only config data was changed, no code changes.


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