Bluetooth Driver services

btdrv

This is "nn::bluetooth::IBluetoothDriver".

Support for "nn::bluetooth::*" was added to sdknso with 6.x.

btdrv appears to be designed to only be used by the two sysmodules which use it, hid and btm. This service uses global state, nothing service-session-specific.

This has max_sessions 30. IPC handling is done by the main-thread.

[11.0.0+] sdknso moved various functions/etc from "nn::bluetooth::" into "nn::bluetooth::hal::". This includes all functions exposing btdrv. These btdrv functions now automatically initialize the service if needed, the dedicated initialization function is now a stub since calling it is no longer needed. The internal "nn::bluetooth::user::" functions implementing #bt were moved to "nn::bluetooth::hal::user::", these are called by the the user-facing "nn::bluetooth::" functions.

Cmd Name
0 #InitializeBluetoothDriver
1 #InitializeBluetooth
2 #EnableBluetooth
3 #DisableBluetooth
4 #FinalizeBluetooth ([?-8.1.1] CleanupBluetooth)
5 #GetAdapterProperties
6 #GetAdapterProperty
7 #SetAdapterProperty
8 #StartInquiry ([?-8.1.1] StartDiscovery)
9 #StopInquiry ([?-8.1.1] CancelDiscovery)
10 #CreateBond
11 #RemoveBond
12 #CancelBond
13 #RespondToPinRequest ([?-8.1.1] PinReply)
14 #RespondToSspRequest ([?-8.1.1] SspReply)
15 #GetEventInfo
16 #InitializeHid
17 #OpenHidConnection ([?-8.1.1] HidConnect)
18 #CloseHidConnection ([?-8.1.1] HidDisconnect)
19 #WriteHidData ([?-8.1.1] HidSendData)
20 #WriteHidData2 ([?-8.1.1] HidSendData2)
21 #SetHidReport ([?-8.1.1] #HidSetReport)
22 #GetHidReport ([?-8.1.1] HidGetReport)
23 #TriggerConnection ([?-8.1.1] #HidWakeController)
24 #AddPairedDeviceInfo ([?-8.1.1] HidAddPairedDevice)
25 #GetPairedDeviceInfo ([?-8.1.1] HidGetPairedDevice)
26 #FinalizeHid ([?-8.1.1] CleanupHid)
27 #GetHidEventInfo ([?-8.1.1] HidGetEventInfo)
28 #SetTsi ([?-8.1.1]] ExtSetTsi)
29 #EnableBurstMode ([?-8.1.1] ExtSetBurstMode)
30 #SetZeroRetransmission ([?-8.1.1] ExtSetZeroRetran)
31 #EnableMcMode ([?-8.1.1] ExtSetMcMode)
32 #EnableLlrScan ([?-8.1.1] ExtStartLlrMode)
33 #DisableLlrScan ([?-8.1.1] ExtExitLlrMode)
34 #EnableRadio ([?-8.1.1] ExtSetRadio)
35 #SetVisibility ([?-8.1.1] ExtSetVisibility)
36 [4.0.0+] #EnableTbfcScan ([4.0.0-8.1.1] ExtSetTbfcScan)
37 ([1.0.0-3.0.2] 36) #RegisterHidReportEvent
38 ([1.0.0-3.0.2] 37) #GetHidReportEventInfo ([?-8.1.1] HidGetReportEventInfo)
39 ([1.0.0-3.0.2] 38) #GetLatestPlr
40 ([3.0.0-3.0.2] 39) [3.0.0+] #GetPendingConnections ([?-8.1.1] ExtGetPendingConnections)
41 ([3.0.0-3.0.2] 40) [3.0.0+] #GetChannelMap
42 ([3.0.0-3.0.2] 41) [3.0.0+] #EnableTxPowerBoostSetting ([?-8.1.1] EnableBluetoothBoostSetting)
43 ([3.0.0-3.0.2] 42) [3.0.0+] #IsTxPowerBoostSettingEnabled ([?-8.1.1] IsBluetoothBoostSettingEnabled)
44 ([3.0.0-3.0.2] 43) [3.0.0+] #EnableAfhSetting ([?-8.1.1] EnableBluetoothAfhSetting)
45 ([3.0.0-3.0.2] 44) [3.0.0+] #IsAfhSettingEnabled ([?-8.1.1] IsBluetoothAfhSettingEnabled)
46 [5.0.0+] #InitializeBle ([5.0.0-8.1.1] InitializeBluetoothLe)
47 [5.0.0+] #EnableBle ([5.0.0-8.1.1] EnableBluetoothLe)
48 [5.0.0+] #DisableBle ([5.0.0-8.1.1] DisableBluetoothLe)
49 [5.0.0+] #FinalizeBle ([5.0.0-8.1.1] CleanupBluetoothLe)
50 [5.0.0+] #SetBleVisibility ([5.0.0-8.1.1] SetLeVisibility)
51 [5.0.0+] #SetBleConnectionParameter ([5.0.0-8.1.1] #SetLeConnectionParameter)
52 [5.0.0+] #SetBleDefaultConnectionParameter ([5.0.0-8.1.1] #SetLeDefaultConnectionParameter)
53 [5.0.0+] #SetBleAdvertiseData ([5.0.0-8.1.1] SetLeAdvertiseData)
54 [5.0.0+] #SetBleAdvertiseParameter ([5.0.0-8.1.1] SetLeAdvertiseParameter)
55 [5.0.0+] #StartBleScan ([5.0.0-8.1.1] StartLeScan)
56 [5.0.0+] #StopBleScan ([5.0.0-8.1.1] StopLeScan)
57 [5.0.0+] #AddBleScanFilterCondition ([5.0.0-8.1.1] AddLeScanFilterCondition)
58 [5.0.0+] #DeleteBleScanFilterCondition ([5.0.0-8.1.1] DeleteLeScanFilterCondition)
59 [5.0.0+] #DeleteBleScanFilter ([5.0.0-8.1.1] DeleteLeScanFilter)
60 [5.0.0+] #ClearBleScanFilters ([5.0.0-8.1.1] ClearLeScanFilters)
61 [5.0.0+] #EnableBleScanFilter ([5.0.0-8.1.1] EnableLeScanFilter)
62 [5.0.0+] #RegisterGattClient ([5.0.0-8.1.1] RegisterLeClient)
63 [5.0.0+] #UnregisterGattClient ([5.0.0-8.1.1] UnregisterLeClient)
64 [5.0.0+] #UnregisterAllGattClients ([5.0.0-8.1.1] UnregisterLeClientAll)
65 [5.0.0+] #ConnectGattServer ([5.0.0-8.1.1] LeClientConnect)
66 [5.1.0+] #CancelConnectGattServer ([5.1.0-8.1.1] LeClientCancelConnection)
67 ([5.0.0-5.0.2] 66) [5.0.0+] #DisconnectGattServer ([?-8.1.1] LeClientCancelConnection)
68 ([5.0.0-5.0.2] 67) [5.0.0+] #GetGattAttribute ([5.0.0-8.1.1] LeClientGetAttributes)
69 ([5.0.0-5.0.2] 68) [5.0.0+] #GetGattService ([5.0.0-8.1.1] LeClientDiscoverService)
70 ([5.0.0-5.0.2] 69) [5.0.0+] #ConfigureAttMtu ([5.0.0-8.1.1] LeClientConfigureMtu)
71 ([5.0.0-5.0.2] 70) [5.0.0+] #RegisterGattServer ([5.0.0-8.1.1] RegisterLeServer)
72 ([5.0.0-5.0.2] 71) [5.0.0+] #UnregisterGattServer ([5.0.0-8.1.1] UnregisterLeServer)
73 ([5.0.0-5.0.2] 72) [5.0.0+] #ConnectGattClient ([5.0.0-8.1.1] LeServerConnect)
74 ([5.0.0-5.0.2] 73) [5.0.0+] #DisconnectGattClient ([5.0.0-8.1.1] #LeServerDisconnect)
75 [5.0.0+] #AddGattService ([5.0.0-8.1.1] CreateLeService)
76 ([5.0.0-5.0.2] 74) [5.0.0+] #EnableGattService ([5.0.0-8.1.1] StartLeService)
77 [5.0.0+] #AddGattCharacteristic ([5.0.0-8.1.1] AddLeCharacteristic)
78 ([5.0.0-5.0.2] 76) [5.0.0+] #AddGattDescriptor ([5.0.0-8.1.1] AddLeDescriptor)
79 ([5.0.0-5.0.2] 78) [5.0.0+] #GetBleManagedEventInfo ([5.0.0-8.1.1] GetLeCoreEventInfo)
80 ([5.0.0-5.0.2] 79) [5.0.0+] #GetGattFirstCharacteristic ([5.0.0-8.1.1] LeGetFirstCharacteristic)
81 ([5.0.0-5.0.2] 80) [5.0.0+] #GetGattNextCharacteristic ([5.0.0-8.1.1] LeGetNextCharacteristic)
82 ([5.0.0-5.0.2] 81) [5.0.0+] #GetGattFirstDescriptor ([5.0.0-8.1.1] LeGetFirstDescriptor)
83 ([5.0.0-5.0.2] 82) [5.0.0+] #GetGattNextDescriptor ([5.0.0-8.1.1] LeGetNextDescriptor)
84 [5.0.0+] #RegisterGattManagedDataPath ([5.0.0-8.1.1] RegisterLeCoreDataPath)
85 [5.0.0+] #UnregisterGattManagedDataPath ([5.0.0-8.1.1] UnregisterLeCoreDataPath)
86 [5.0.0+] #RegisterGattHidDataPath ([5.0.0-8.1.1] RegisterLeHidDataPath)
87 [5.0.0+] #UnregisterGattHidDataPath ([5.0.0-8.1.1] UnregisterLeHidDataPath)
88 [5.0.0+] #RegisterGattDataPath ([5.0.0-8.1.1] RegisterLeDataPath)
89 ([5.0.0-5.0.2] 83) [5.0.0+] #UnregisterGattDataPath ([5.0.0-8.1.1] UnregisterLeDataPath)
90 ([5.0.0-5.0.2] 89) [5.0.0+] #ReadGattCharacteristic ([5.0.0-8.1.1] LeClientReadCharacteristic)
91 ([5.0.0-5.0.2] 90) [5.0.0+] #ReadGattDescriptor ([5.0.0-8.1.1] LeClientReadDescriptor)
92 ([5.0.0-5.0.2] 91) [5.0.0+] #WriteGattCharacteristic ([5.0.0-8.1.1] LeClientWriteCharacteristic)
93 ([5.0.0-5.0.2] 92) [5.0.0+] #WriteGattDescriptor ([5.0.0-8.1.1] LeClientWriteDescriptor)
94 [5.0.0+] #RegisterGattNotification ([5.0.0-8.1.1] LeClientRegisterNotification)
95 ([5.0.0-5.0.2] 93) [5.0.0+] #UnregisterGattNotification ([5.0.0-8.1.1] LeClientDeregisterNotification)
96 ([5.0.0-5.0.2] 95) [5.0.0+] #GetLeHidEventInfo
97 ([5.0.0-5.0.2] 96) [5.0.0+] #RegisterBleHidEvent
98 [5.1.0+] #SetBleScanParameter ([5.1.0-8.1.1] SetLeScanParameter)
99 [10.0.0+] #MoveToSecondaryPiconet
100 [12.0.0+] #IsBluetoothEnabled
101 [15.0.0+] ForceEnableBluetooth
102 [15.0.0+] EnableBluetoothStub
128 [12.0.0+] #AcquireAudioEvent
129 [12.0.0+] #GetAudioEventInfo
130 [12.0.0+] #OpenAudioConnection
131 [12.0.0+] #CloseAudioConnection
132 [12.0.0+] #OpenAudioOut
133 [12.0.0+] #CloseAudioOut
134 [12.0.0+] #AcquireAudioOutStateChangedEvent
135 [12.0.0+] #StartAudioOut
136 [12.0.0+] #StopAudioOut
137 [12.0.0+] #GetAudioOutState
138 [12.0.0+] #GetAudioOutFeedingCodec
139 [12.0.0+] #GetAudioOutFeedingParameter
140 [12.0.0+] #AcquireAudioOutBufferAvailableEvent
141 [12.0.0+] #SendAudioData
142 [12.0.0+] #AcquireAudioControlInputStateChangedEvent
143 [12.0.0+] #GetAudioControlInputState
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
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
257 [7.0.0+] #EmulateBluetoothCrash
258 [9.0.0+] #GetBleChannelMap

Cmds 46-83 were added with [4.0.0+].

Various cmds were moved/etc starting with #InitializeBle with [5.0.0+].

InitializeBluetoothDriver

No input/output.

[1.0.0-10.2.0] This is the first cmd used during service init.

This just returns 0.

InitializeBluetooth

No input, returns an output Event handle with EventClearMode=1.

This is used by btm, this should not be used by other processes.

[1.0.0-11.0.1] This first initializes the funcptr table interfaces to the defaults (same as #DisableBluetooth). GetConfigurationId1 is used, an error is thrown if the output string is empty, or if it matches "SDEV_00_01_00".

If the flag for #IsManufacturingMode is 0, or if this cmd was already used where that flag was 1, an interface funcptr is called. This is passed a ptr to a table of funcptrs. The ret is converted to a Result and returned if needed. [12.0.0+] A normal func is called instead, with no params/ret. This cmd always returns 0.

The above called func does the following:

  • [1.0.0-11.0.1] A func is called, which copies the input funcptr table into global state. These are used for writing events into #EventInfo.
  • A func is called 5 times with input param = [1-5]. This initializes the specified nn::bluetooth::CircularBuffer (sharedmem and internal). [12.0.0+] This functionality is now inlined.
  • A func is called for creating the "nn.bluetooth.HidMessageHandler" thread. [12.0.0+] This functionality is now inlined.

Lastly, the Event is ([1.0.0-11.0.1] created and) returned (which global state the Event is stored in depends on whether the code-path which calls the above funcptr was used).

EnableBluetooth

No input/output.

This is used by btm.

[1.0.0-11.0.1] This first calls an interface funcptr, on failure 0xCA71 is returned.

[1.0.0-11.0.1] A global fixed #Address is copied to stack, this stack data is then overwritten with the output from GetBluetoothBdAddress. If GetBluetoothBdAddress fails, this will Abort. Then the same funcptr used by #SetAdapterProperty is called with this stack data, with type2. A converted error is returned if needed.

[1.0.0-11.0.1] The last two bytes of the stack #Address are inverted (byteval = ~byteval), then the above funcptr is called with this for type3. Error conversion is handled if needed, then this returns 0.

The first funcptr called above does the following ([12.0.0+] this code is now inlined):

  • Calls a GPIO func with param=0, sleeps for 10000000 nanoseconds, then calls the GPIO func again with param=1.
  • [12.0.0+] Calls a func to update an interface object ptr to use the enabled-object. A vfunc for various interface objects are called, with Result 0xCA71 being returned if the ret is non-zero (failure after the first interface object will trigger an Abort).
  • [12.0.0+] GetBluetoothBdAddress is used, on failure this will Abort. Then the same vfunc used by #SetAdapterProperty is called with the output from GetBluetoothBdAddress, with type0. This will Abort on failure.
  • [12.0.0+] The last two bytes of the stack #Address are inverted (byteval = ~byteval), then the above vfunc is called with this for type3. This will Abort on failure, otherwise 0 is returned.
  • [12.0.0+] Various code described below was moved into the above vfunc(s), etc.
  • Calls a func for initializing the paired-devices table (empty).
  • Calls a modified version of BSA_Boot, which handles BSA server initialization.
  • Calls a func which uses nn::os::InitializeEvent and nn::os::InitializeMutex with global state.
  • Calls a func which handles BSA client initialization. This also sends a message to the "nn.bluetooth.HidMessageHandler" thread for enabling bluetooth (which updates the interface funcptr tables, etc).
  • Calls a func which enables HID-Host with BSA, and opens the UIPC channel where the registered funcptr is used for writing HID DATA reports which were received.
  • Calls a func which initializes global state and uses BSA for initializing Security.
  • If the output flag from GetBluetoothBoostEnableFlag is set, a func is called.
  • If the output flag from GetBluetoothAfhEnableFlag is not set, a func is called.

The GPIO func does the following:

  • Initializes the gpio service.
  • Uses OpenSession with value 0x03 (BtRst).
  • Uses SetDirection with value 0x1.
  • Uses SetValue with the param which was passed to this func.
  • 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 features. This is ORRed to set bit0 for "remote control target", which with [13.0.0+] is only done if system-setting bluetooth_debug!is_av_rc_tg is set to true. With [14.0.0+] this is also ORRed with value 0xA (bit1/bit3) when system-setting bluetooth_debug!is_av_rc_ct 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 fatal is triggered and 0 is returned.
  • Otherwise when successful, state init is done then 0 is returned.

DisableBluetooth

No input/output.

This is used by btm.

[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:

  • Calls a func which closes the HID-Host UIPC channel, and uses BSA for disabling HID-Host.
  • Calls a func which uses nn::os::FinalizeMutex and nn::os::FinalizeEvent with global state.
  • Uses nn::os::InitializeEvent, nn::os::InitializeTimerEvent, with a ptr for the former Event being written into global state.
  • Uses BTA_DisableBluetooth.
  • Uses nn::os::StartOneShotTimerEvent with a value of 5 seconds.
  • Waits for either of the above to trigger using nn::os::TryWaitEvent and nn::os::TryWaitTimerEvent, with each loop iteration sleeping for 5000000 nanoseconds.
    • The Event is signaled when disabling bluetooth finishes.
  • Cleanup for the above Event/TimerEvent is done.
  • Calls a func which handles BSA client cleanup.
  • Calls a func which does the following:
    • Calls a func which tells the "nn.bluetooth.TimerThread" to exit, then destroys that thread (GKI timer thread).
    • Calls a func which just returns.
    • Calls a func which handles GKI cleanup (including destroying the task threads).
    • Calls a func which waits for the UIPC threads to exit + destroys the threads and handles cleanup.
  • Calls the same GPIO func as #EnableBluetooth with param=0.
  • Sends a message to the "nn.bluetooth.HidMessageHandler" thread for disabling bluetooth (which updates the interface funcptr tables, etc).

FinalizeBluetooth

No input/output.

Not used by btm, other processes should not use this.

Calls an interface funcptr, the ret is ignored. The Event setup by #InitializeBluetooth is closed. Lastly, the same funcs used by #InitializeBluetooth are called for initializing the interface funcptr tables to the defaults, then 0 is returned.

The above interface funcptr does the following (regardless of whether bluetooth is disabled/enabled):

  • Calls a func which: uses nn::os::SignalLightEvent to tell the "nn.bluetooth.HidMessageHandler" thread to exit, then waits for the thread to exit and destroys the thread.
  • Calls the same func as #InitializeBluetooth for setting event funcptrs in global state, except in this case the content of the input table is all NULL.
  • Calls a func 5 times with param=[1-5]. This is the cleanup version of the nn::bluetooth::CircularBuffer setup func used by #InitializeBluetooth.

GetAdapterProperties

Takes a type-0x1A output buffer containing an #AdapterProperty.

[12.0.0+] Takes a type-0x1A output buffer containing an #AdapterPropertySet.

This is used by btm.

GetAdapterProperty

Takes an input #BluetoothPropertyType and a type-0xA output buffer.

[12.0.0+] Takes an input #AdapterPropertyType and a type-0x1A output buffer containing an #AdapterProperty.

SetAdapterProperty

Takes an input #BluetoothPropertyType and a type-0x9 input buffer.

[12.0.0+] Takes a type-0x19 input buffer containing an #AdapterProperty, no output.

StartInquiry

No input/output.

[12.0.0+] Takes an input BitFlagSet 32bit services and s64 nanoseconds_duration, no output.

This is used by btm.

This starts Inquiry, the output data will be available via #GetEventInfo. Inquiry will automatically stop in 10.24 seconds ([12.0.0+] calculated from the input duration instead).

[12.0.0+] When services is -1 the original defaults from pre-12.0.0 are used (besides duration). Otherwise, services is written into the parameter struct (masked with the all-allowed-BSA-services value), and the EventInfo for discovered devices are triggered when inquiry finishes instead of immediately.

StopInquiry

No input/output.

This is used by btm.

This stops Inquiry which was started by #StartInquiry, if it's still active.

CreateBond

Takes an input #Address and a type-0x19 input buffer containing a #TransportType, no output.

[9.0.0+] Now only takes an #Address and a #TransportType without a buffer, no output.

The #TransportType is unused.

This is used by btm.

RemoveBond

Takes an input #Address, no output.

This is used by btm.

CancelBond

Takes an input #Address, no output.

This is used by btm.

RespondToPinRequest

Takes an input #Address, a bool, an u8, a #BluetoothPinCode, no output.

[12.0.0+] Takes an input #Address, a #PinCode, no output.

sdknso uses an user-specified s32 for the u8.

The sysmodule impl for the funcptr used with this cmd only uses the #Address - this and hard-coded PIN "0000" are written into the parameter struct (and a size field for the PIN).

[12.0.0+] The input #PinCode is now actually used and passed to BSA, instead of hard-coding the PIN.

RespondToSspRequest

Takes an input #Address, a #BluetoothSspVariant, a bool, an u32, no output.

[12.0.0+] Takes an input #Address, a bool, a #BluetoothSspVariant, an u32, no output.

This is used by btm.

The sysmodule impl for the funcptr/vfunc used with this cmd only uses the #Address and bool - the parameter struct size is only 0x7-bytes. The bool indicates whether the request is accepted.

GetEventInfo

Takes a type-0xA output buffer and returns an output #EventType.

This copies 0x400-bytes from state to the output buffer, copies the #EventType from state to output, and signals an event.

[12.0.0+] Mutex locking is now used, with the code prior to the event-signal. If a size field in state is 0, writing the output #EventType/buffer is skipped. Otherwise, the size field is reset to 0, the #EventType from state is copied to output, and the original size field is used to memcpy to the output buffer from state.

This is used by btm.

See #EventInfo.

InitializeHid

Takes an input u16, returns an output Event with EventClearMode=1.

Originally sdknso used an user-specified value for the u16, however with [9.0.0+] it uses hard-coded value 0x1 instead.

This is used by btm, this should not be used by other processes.

OpenHidConnection

Takes an input #Address, no output.

This just returns 0.

This is used by btm.

CloseHidConnection

Takes an input #Address, no output.

This is used by btm.

HidSendData

Takes an input #Address and a type-0x19 input buffer containing a #HidData, no output.

WriteHidData

Takes an input #Address and a type-0x19 input buffer containing a #HidReport, no output.

This is used by hid.

This sends a HID DATA transaction packet with report-type Output.

WriteHidData2

Takes an input #Address and a type-0x9 input buffer, no output.

This is internally the same as #WriteHidData, with the input buffer being directly passed to the funcptr instead of a tmp copy of the input #HidReport.

HidSetReport

Takes an input #Address, a #BluetoothHhReportType, a type-0x19 input buffer containing a #HidData, no output.

SetHidReport

Takes an input #Address, a #BluetoothHhReportType, a type-0x19 input buffer containing a #HidReport, no output.

This is used by hid.

This sends a HID SET_REPORT transaction packet.

GetHidReport

Takes an input #Address, an u8 report_id, a #BluetoothHhReportType, no output.

This is used by hid.

This sends a HID GET_REPORT transaction packet. The report_id is sent in the packet for the Report Id, when non-zero.

HidWakeController

Takes an input #Address, no output.

TriggerConnection

Takes an input #Address and an u16, no output.

This is used by btm.

This calls an interface funcptr, then returns the converted ret as needed.

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.
  • 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:

  • 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.

AddPairedDeviceInfo

Takes a type-0x19 input buffer containing BluetoothDevicesSettings, no output.

This is used by btm.

[12.0.0+] If TrustedServices is 0, value 0x100000 is used. When bit20 is set, HID is initialized for this device, otherwise when bitmask 0xC0000 is set (if((TrustedServices & 0xC0000) != 0)) audio is initialized for this device.

GetPairedDeviceInfo

Takes an input #Address and a type-0x1A output buffer containing BluetoothDevicesSettings.

This is used by btm.

FinalizeHid

No input/output.

Not used by btm, other processes should not use this.

GetHidEventInfo

Takes a type-0xA output buffer, returns an output #HidEventType.

This copies 0x480-bytes from state to the output buffer. #HidEventType is set to: stateval!=0 ? 7 : 0. Once finished, this signals an event.

[12.0.0+] Mutex locking is now used, with the code prior to the event-signal. If a size field in state is 0, writing the output #HidEventType/buffer is skipped. Otherwise, the size field is reset to 0, the #HidEventType from state is copied to output, and the original size field is used to memcpy to the output buffer from state.

This is used by btm.

See #HidEventInfo.

SetTsi

Takes an input #Address and an u8 Tsi, no output.

This is used by btm.

The response will be available via #GetHidEventInfo ([12.0.0+] #GetEventInfo).

This uses a BSA extension.

Tsi: non-value-0xFF to Set (BSA message 0x8CA), value 0xFF to Exit (BSA message 0x8CB).

Set: this uses command HCI_Set_MWS_Signaling with data determined using the input u8. Then this uses Broadcom HCI vendor command 0xFD95 with param_len=0x2: param +0x0 = 0x1, +0x1 = {Tsi value}. When this vendor command is successful, it then uses command HCI_Sniff_Mode with data selected using the Tsi value as the array-index. If the remote device doesn't support this (status indicating error with Mode Change Event for the response to HCI_Sniff_Mode), an error will be thrown via the EventInfo. That error can be resolved if the remote device uses the HCI_Sniff_Mode command prior to the Switch doing so.

Exit: this uses command HCI_Exit_Sniff_Mode.

EnableBurstMode

Takes an input #Address and a bool, no output.

This is used by btm.

The response will be available via #GetHidEventInfo ([12.0.0+] #GetEventInfo).

This uses a BSA extension.

bool flag: true = Set (BSA message 0x8CC), false = Exit (BSA message 0x8CD).

SetZeroRetransmission

Takes an input #Address and a type-0x9 input buffer containing an array of u8s, no output.

The entry-count is clamped to a maximum of 5, the count can be 0. This buffer contains ReportIds.

This is used by btm.

The response will be available via #GetHidEventInfo ([12.0.0+] #GetEventInfo).

This uses a BSA extension (message 0x8CF).

EnableMcMode

Takes an input bool, no output.

This is used by btm.

This uses a BSA extension (message 0x8CE).

EnableLlrScan

No input/output.

This is used by btm.

This uses a BSA extension (message 0x8CE).

DisableLlrScan

No input/output.

This is used by btm.

This uses a BSA extension (message 0x8CE).

EnableRadio

Takes an input bool, no output.

This is used by btm.

This uses a BSA extension (message 0x8CE).

The message is handled by using HCI vendor command 0xFC34 with param_len=0x1: param +0 = {input bool}.

SetVisibility

Takes two input bools, no output.

The first bool controls Inquiry Scan, whether the device can be discovered during Inquiry. The second bool controls Page Scan, whether the device accepts connections.

This is used by btm.

EnableTbfcScan

Takes an input bool, no output.

This is used by btm.

RegisterHidReportEvent

No input, returns an output Event handle with EventClearMode=1.

This gets the Event handle for a previously created Event.

This is used by hid.

The Event is signaled when data is available with #GetHidReportEventInfo.

GetHidReportEventInfo

No input, takes a type-0xA output buffer and returns a #HidEventType.

[7.0.0+] No longer takes a buffer or returns output, now returns an output sharedmem handle. sdknso maps this with size=0x3000 and permissions=RW-.

Originally this was used in a dedicated sdknso func, with [7.0.0+] this is now used at the start of the sdknso impl for #RegisterHidReportEvent if the above sharedmem was not mapped yet.

The [7.0.0+] GetHidReportEventInfo sdknso func loads data using the above sharedmem.

This is used by hid.

GetLatestPlr

Takes a type-0x16 output buffer containing a #PlrList ([1.0.0-8.1.1] #PlrStatistics).

[12.0.0+] Takes a type-0xA output buffer containing an array of #PacketLostRate, returns an output s32.

This calls an interface funcptr then returns 0.

The interface funcptr impl will Abort if the output struct ptr is NULL. Then data is copied from global state to output, doing double->u32 conversion as needed.

GetPendingConnections

No input/output.

This is used by btm.

The output data will be available via #GetHidEventInfo ([12.0.0+] #GetEventInfo).

GetChannelMap

Takes a type-0x16 output buffer containing a #ChannelMapList.

[12.0.0+] Takes two type-0xA output buffers, returns an output s32. The first buffer contains an array of #Address, the second buffer contains an array of BitFlagSet with #Channel and bit-count=79.

This calls an interface funcptr then returns 0.

EnableTxPowerBoostSetting

Takes an input bool, no output.

sdknso ignores errors from this. sdknso exposes this under "nn::bluetooth::debug::".

IsTxPowerBoostSettingEnabled

No input, returns an output bool.

sdknso sets the tmpout_bool to 1, and uses that with the cmd. The sdknso func directly returns tmpout_bool, errors from the cmd are ignored.

sdknso exposes this under "nn::bluetooth::debug::".

EnableAfhSetting

Takes an input bool, no output.

sdknso ignores errors from this. sdknso exposes this under "nn::bluetooth::debug::".

IsAfhSettingEnabled

sdknso sets the tmpout_bool to 1, and uses that with the cmd. The sdknso func directly returns tmpout_bool, errors from the cmd are ignored.

sdknso exposes this under "nn::bluetooth::debug::".

InitializeBle

No input, returns an output Event handle with EventClearMode=1.

This is used by btm.

EnableBle

No input/output.

This is used by btm.

DisableBle

No input/output.

This is used by btm.

FinalizeBle

No input/output.

SetBleVisibility

Takes two input bools, no output.

First bool: whether the BLE device is discoverable. Second bool: whether the BLE device is connectable.

SetLeConnectionParameter

Takes a #LeConnectionParams, no output.

SetBleConnectionParameter

Takes an input #Address, a bool, a #BleConnectionParameter, no output.

This is used by btm.

SetLeDefaultConnectionParameter

Takes a #LeConnectionParams, no output.

SetBleDefaultConnectionParameter

Takes a #BleConnectionParameter, no output.

This is used by btm.

SetBleAdvertiseData

Takes a type-0x19 input buffer containing a #BleAdvertisePacketData, no output.

SetBleAdvertiseParameter

Takes an input #Address, two u16s, no output.

StartBleScan

No input/output.

This is used by btm.

StopBleScan

No input/output.

This is used by btm.

AddBleScanFilterCondition

Takes a type-0x19 input buffer containing a #BleAdvertiseFilter, no output.

This is used by btm.

DeleteBleScanFilterCondition

Takes a type-0x19 input buffer containing a #BleAdvertiseFilter, no output.

This is used by btm.

DeleteBleScanFilter

Takes an input u8, no output.

Originally the sdknso func used an u8 for the user-specified param, with [9.0.0+] it's a s32.

ClearBleScanFilters

No input/output.

This is used by btm.

EnableBleScanFilter

Takes an input bool, no output.

This is used by btm.

RegisterGattClient

Takes an input #GattAttributeUuid, no output.

This is used by btm.

UnregisterGattClient

Takes an input u8, no output.

UnregisterAllGattClients

No input/output.

ConnectGattServer

Takes an input u8 client_if, an #Address, a bool, an AppletResourceUserId, no output.

This is used by btm.

The input bool and AppletResourceUserId are unused.

The is_direct field passed to BSA is value 1.

CancelConnectGattServer

Takes an input u8, an #Address, a bool, no output.

This is used by btm.

DisconnectGattServer

Takes an input u32, no output.

This is used by btm.

GetGattAttribute

Takes an #Address and an u32, no output.

[9.0.0+] Now takes an input u32, no output.

GetGattService

Takes an input u32 and a #GattAttributeUuid, no output.

ConfigureAttMtu

Takes an input u16 and u32, no output.

This is used by btm.

RegisterGattServer

Takes an input #GattAttributeUuid, no output.

UnregisterGattServer

Takes an input u8, no output.

ConnectGattClient

Takes an input u8, an #Address, a bool, no output.

LeServerDisconnect

Takes an input u8, an #Address, no output.

DisconnectGattClient

Takes an input u8, no output.

AddGattService

Takes an input u8, an u8, a bool, a #GattAttributeUuid, no output.

Originally sdknso used an user-specified u8 for the second u8, with [9.0.0+] that func param is now a s32.

EnableGattService

Takes an input u8, a #GattAttributeUuid, no output.

AddGattCharacteristic

Takes an input u8, an u8, an u16, a #GattAttributeUuid, a #GattAttributeUuid, no output.

AddGattDescriptor

Takes an input u8, an u16, a #GattAttributeUuid, a #GattAttributeUuid, no output.

GetBleManagedEventInfo

Takes a type-0xA output buffer, returns an output #BleEventType.

This copies 0x400-bytes from state to the output buffer, and copies the #BleEventType from state to output.

This is used by btm.

GetGattFirstCharacteristic

Takes an input bool, an u32, a #GattId, a #GattAttributeUuid, returns an output u8 Property and CharacteristicId.

GetGattNextCharacteristic

Takes an input bool, an u32, a #GattId, a #GattId, a #GattAttributeUuid, returns an output u8 Property and CharacteristicId.

GetGattFirstDescriptor

Takes an input bool, an u32, a #GattId, a #GattId, a #GattAttributeUuid, returns an output DescriptorId.

GetGattNextDescriptor

Takes an input bool, an u32, a #GattId, a #GattId, a #GattId, a #GattAttributeUuid, returns an output DescriptorId.

RegisterGattManagedDataPath

Takes an input #GattAttributeUuid, no output.

This is used by btm.

UnregisterGattManagedDataPath

Takes an input #GattAttributeUuid, no output.

RegisterGattHidDataPath

Takes an input #GattAttributeUuid, no output.

This is used by btm.

UnregisterGattHidDataPath

Takes an input #GattAttributeUuid, no output.

This is used by btm.

RegisterGattDataPath

Takes an input #GattAttributeUuid, no output.

This is used by btm.

UnregisterGattDataPath

Takes an input #GattAttributeUuid, no output.

This is used by btm.

ReadGattCharacteristic

Takes an input bool PrimaryService, an u8, an u32 ConnectionHandle, a #GattId, a #GattId, no output.

This is used by hid and btm.

ReadGattDescriptor

Takes an input bool PrimaryService, an u8, an u32 ConnectionHandle, a #GattId, a #GattId, a #GattId, no output.

This is used by hid.

WriteGattCharacteristic

Takes a type-0x9 input buffer, a bool PrimaryService, an u8, a bool, an u32 ConnectionHandle, a #GattId, a #GattId, no output.

The buffer size must be <=0x258.

This is used by hid and btm.

WriteGattDescriptor

Takes a type-0x9 input buffer, a bool PrimaryService, an u8, an u32 ConnectionHandle, a #GattId, a #GattId, a #GattId, no output.

The buffer size must be <=0x258.

This is used by hid and btm.

RegisterGattNotification

Takes an input bool, an u32 ConnectionHandle, a #GattId, a #GattId, no output.

This is used by hid and btm.

UnregisterGattNotification

Takes an input bool, an u32 ConnectionHandle, a #GattId, a #GattId, no output.

This is used by hid.

GetLeHidEventInfo

Takes a type-0xA output buffer, returns an output #BleEventType.

This copies 0x400-bytes from state to the output buffer, and copies the #BleEventType from state to output. This also resets the state which was used for the outbuf-copy. Once finished, this signals an event.

This is used by hid.

See #LeEventInfo for the output buffer.

RegisterBleHidEvent

No input, returns an output Event handle with EventClearMode=1.

This is used by hid.

SetBleScanParameter

Takes two input u16s, no output.

The first u16 is scan_interval, the second u16 is scan_window.

This is used by btm.

MoveToSecondaryPiconet

Takes an input #Address, no output.

The response will be available via #GetHidEventInfo ([12.0.0+] #GetEventInfo).

This uses a BSA extension (message 0x8D0).

IsBluetoothEnabled

No input, returns an output bool.

AcquireAudioEvent

No input, returns an output Event handle.

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

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

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

Takes an input #Address, no output.

This goes through state and eventually uses BSA to close an AV connection.

OpenAudioOut

Takes an input #Address, returns an output u32 audio_handle.

CloseAudioOut

Takes an input u32 audio_handle, no output.

AcquireAudioOutStateChangedEvent

Takes an input u32 audio_handle, returns an output Event handle.

sdknso uses an user-specified EventClearMode.

StartAudioOut

Takes an input u32 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

Takes an input u32 audio_handle, no output.

This eventually uses BSA to stop an AV stream. The pause flag is set to false.

GetAudioOutState

Takes an input u32 audio_handle, returns an output #AudioOutState.

GetAudioOutFeedingCodec

Takes an input u32 audio_handle, returns an output #AudioCodec.

GetAudioOutFeedingParameter

Takes an input u32 audio_handle, returns an output #PcmParameter.

AcquireAudioOutBufferAvailableEvent

Takes an input u32 audio_handle, returns an output Event handle.

sdknso uses an user-specified EventClearMode.

This gets an Event which was previously initialized.

SendAudioData

Takes an input u32 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

No input, returns an output Event handle.

sdknso uses an user-specified EventClearMode.

This gets an Event which was previously initialized.

GetAudioControlInputState

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

No input, returns an output Event handle.

sdknso uses an user-specified EventClearMode.

This gets an Event which was previously initialized.

GetConnectedAudioDevice

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 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 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

No input, returns an output bool.

sdknso will Abort if this fails, the bool is returned instead of a Result. sdknso exposes this under "nn::bluetooth::debug::".

This calls the same two funcs as various other cmds etc. This writes the bool returned by the second func to output, then returns 0. The second func loads the bool from system-setting "bluetooth_debug!skip_boot". The first func is the same as the second one, except it writes the bool into global state. [12.0.0+] These two funcs now additionally load system-setting "bluetooth_config!skip_boot", which is ORRed with the first setting, then that's used for storing in state / returning the value.

This is used by btm.

EmulateBluetoothCrash

Takes an input #FatalReason, no output.

sdknso masks the FatalReason with an u16-mask before passing it to the cmd. sdknso exposes this under "nn::bluetooth::debug::".

This writes data into a CircularBuffer (seperate from sharedmem) with type=0x29, where the data is an u16 determined using the input #FatalReason. This is only done if a state field is value 0x3, after calling the func for this the field is set to value 0. The thread handling that sent message then converts the u16 back into a #FatalReason for writing into #EventInfo.

GetBleChannelMap

Takes a type-0x16 output buffer containing a #ChannelMapList.

[12.0.0+] Takes two type-0xA output buffers, returns an output s32. The first buffer contains an array of #Address, the second buffer contains an array of BitFlagSet with #LeChannel and bit-count=40.

bt

This is "nn::bluetooth::IBluetoothUser".

This has max_sessions 30. IPC handling is done by the main-thread.

Cmd Name
0 #LeClientReadCharacteristic
1 #LeClientReadDescriptor
2 #LeClientWriteCharacteristic
3 #LeClientWriteDescriptor
4 #LeClientRegisterNotification
5 #LeClientDeregisterNotification
6 #SetLeResponse
7 #LeSendIndication
8 #GetLeEventInfo
9 #RegisterBleEvent

LeClientReadCharacteristic

Takes a PID, a bool, an u8, an u32, a #GattId, a #GattId, an AppletResourceUserId, no output.

This is essentially the same as #ReadGattCharacteristic, the AppletResourceUserId is unused.

LeClientReadDescriptor

Takes a PID, a bool, an u8, an u32, a #GattId, a #GattId, a #GattId, an AppletResourceUserId, no output.

This is essentially the same as #ReadGattDescriptor, the AppletResourceUserId is unused.

LeClientWriteCharacteristic

Takes a PID, a type-0x9 input buffer, a bool, an u8, a bool, an u32, a #GattId, a #GattId, an AppletResourceUserId, no output.

This is essentially the same as #WriteGattCharacteristic, the AppletResourceUserId is unused.

LeClientWriteDescriptor

Takes a PID, a type-0x9 input buffer, a bool, an u8, an u32, a #GattId, a #GattId, a #GattId, an AppletResourceUserId, no output.

This is essentially the same as #WriteGattDescriptor, the AppletResourceUserId is unused.

LeClientRegisterNotification

Takes a PID, an input bool, an u32, a #GattId, a #GattId, an AppletResourceUserId, no output.

This is essentially the same as #RegisterGattNotification, the AppletResourceUserId is unused.

LeClientDeregisterNotification

Takes a PID, an input bool, an u32, a #GattId, a #GattId, an AppletResourceUserId, no output.

This is essentially the same as #UnregisterGattNotification, the AppletResourceUserId is unused.

SetLeResponse

Takes a PID, a type-0x9 input buffer, an u8, a #GattAttributeUuid, a #GattAttributeUuid, an AppletResourceUserId, no output.

The AppletResourceUserId is unused.

The buffer size must be <=0x258.

LeSendIndication

Takes a PID, a type-0x9 input buffer, an u8, a bool, a #GattAttributeUuid, a #GattAttributeUuid, an AppletResourceUserId, no output.

The AppletResourceUserId is unused.

The buffer size used internally is clamped to max size 0x258.

GetLeEventInfo

Takes a PID, a type-0xA output buffer, an AppletResourceUserId, returns an output #BleEventType.

This is identical to #GetLeHidEventInfo except different state is used. The AppletResourceUserId is unused. See #LeEventInfo for the output buffer.

RegisterBleEvent

Takes a PID, an AppletResourceUserId, returns an output Event handle with EventClearMode=1.

This is identical to #RegisterBleHidEvent except different Event state is used. The AppletResourceUserId is unused.

BluetoothPropertyType

This is u32 enum "nn::bluetooth::BluetoothPropertyType".

The sysmodule will Abort if the input type is unavailable / not recognized.

Value Description Buffer contents
1 Name String, max length 0xF8 excluding NUL-terminator.
2 Address #Address
3 Only available with #SetAdapterProperty. Unknown, #Address. The default is the same as type2, with the last two bytes inverted.

This uses a BSA extension (message 0x8CE), the message handler which is used here uses HCI vendor command 0xFD98 with param_len=0x7: u8 param+0 = {whether the #Address is non-zero}, +1 6-bytes = {#Address with byte-order swapped}.

5 3-bytes, Class of Device.
6 1-byte, FeatureSet. The default is value 0x68.

AdapterPropertyType

This is u32 enum "nn::bluetooth::hal::AdapterPropertyType".

The sysmodule will Abort if the input type is unavailable / not recognized.

Value Description Data contents
0 Address #Address
1 Name String, max length 0xF8 excluding NUL-terminator.
2 3-bytes, Class of Device.
3 Only available with #SetAdapterProperty. Same as #BluetoothPropertyType type3.

TransportType

This is u32 enum "nn::bluetooth::TransportType".

BluetoothSspVariant

This is u8 enum "nn::bluetooth::BluetoothSspVariant". [12.0.0+] This is u32 enum "nn::bluetooth::hal::BluetoothSspVariant".

EventType

This is u32 enum "nn::bluetooth::EventType".

Value Name Description
[1.0.0-11.0.1] 0 The funcptr which writes the data into state for this event is not called (only checked on [10.0.0]).
0 ([1.0.0-11.0.1] 3) New device found during Inquiry.
1 ([1.0.0-11.0.1] 4) Inquiry status changed.
2 ([1.0.0-11.0.1] 5) Triggered by BSA_SEC_PIN_REQ_EVT: PIN code request for pairing.
3 ([1.0.0-11.0.1] 6) Triggered by BSA_SEC_SP_CFM_REQ_EVT/BSA_SEC_SP_KEY_NOTIF_EVT: SSP confirm request / SSP passkey notification.
4 ([1.0.0-11.0.1] 7) Connection
5 [12.0.0+] Tsi
6 [12.0.0+] BurstMode
7 [12.0.0+] #SetZeroRetransmission
8 [12.0.0+] #GetPendingConnections
9 [12.0.0+] #MoveToSecondaryPiconet
10 ([1.0.0-11.0.1] 13) BluetoothCrash. Triggered by #EmulateBluetoothCrash and BSA_MGT_DISCONNECT_EVT.

ConnectionEventType

This is the event value in #EventInfo when #EventType is type4 ([1.0.0-11.0.1] type7).

Value Name Description
0 [1.0.0-11.0.1] Connection status.
1 [1.0.0-11.0.1] Triggered by BSA_SEC_SP_CFM_REQ_EVT: SSP confirm request.
2 [12.0.0+] Triggered by BSA_SEC_RESUMED_EVT: ACL Link is now Resumed.
3 ([1.0.0-11.0.1] 2) Triggered by BSA_SEC_SUSPENDED_EVT: ACL Link is now Suspended.

BluetoothHhReportType

This is u32 enum "nn::bluetooth::BluetoothHhReportType".

Bit0-1 directly control the HID bluetooth transaction report-type value. Bit2-3: these directly control the Parameter Reserved field for SetReport, for GetReport these control the Parameter Reserved and Size bits.

Value Description
0 Other
1 Input
2 Output
3 Feature

HidEventType

This is u32 enum "nn::bluetooth::HidEventType".

Value Name Description
0 Connection. Only used with #GetHidEventInfo.
1 ([1.0.0-11.0.1] 4) DATA report on the Interrupt channel.
2 ([1.0.0-11.0.1] 8) Response to SET_REPORT.
3 ([1.0.0-11.0.1] 9) Response to GET_REPORT.
[1.0.0-11.0.1] 7 Response for extensions. Only used with #GetHidEventInfo.

BleEventType

This is u32 enum "nn::bluetooth::BleEventType".

FatalReason

This is u32 enum "nn::bluetooth::FatalReason".

This determines the u16 data to write into the CircularBuffer. #EmulateBluetoothCrash handles values outside of 1-2 the same as value 3.

Value Description
0 Only for #EventInfo: invalid.
1 u16 data = 0x850. Can only be triggered by #EmulateBluetoothCrash, not triggered by the sysmodule otherwise.
2 u16 data = 0x851. HCI command timeout.
3 u16 data = 0x852. HCI event HCI_Hardware_Error occurred.
7 Only for #EventInfo: triggered after enabling bluetooth, when a global state field is value 4 or 2.
9 [12.0.0+] Only for #EventInfo: triggered when bluetooth errors occur in a certain range, with various Audio interface vfuncs.

AdapterProperty

This is "nn::bluetooth::AdapterProperty" ([12.0.0+] "nn::bluetooth::hal::AdapterProperty"). This is a 0x103-byte ([12.0.0+] 0x102-byte) struct.

Offset Size Description
0x0 0x6 Same as the data for #BluetoothPropertyType type2.
0x6 0x3 Same as the data for #BluetoothPropertyType type5.
0x9 0xF9 Same as the data for #BluetoothPropertyType type1 (last byte is not initialized).
0x102 0x1 Set to hard-coded value 0x68 (same as the data for #BluetoothPropertyType type6).

[12.0.0+]:

Offset Size Description
0x0 0x1 #AdapterPropertyType
0x1 0x1 Data size
0x2 {Above size} Data, as specified by the type.

AdapterPropertySet

This is "nn::bluetooth::hal::AdapterPropertySet". This is a 0x102-byte struct.

Offset Size Description
0x0 0x6 Same as the data for #AdapterPropertyType type0.
0x6 0x3 Same as the data for #AdapterPropertyType type2.
0x9 0xF9 Same as the data for #AdapterPropertyType type1.

Address

This is "nn::bluetooth::Address". This is a 0x6-byte struct with 1-byte alignment.

EventInfo

This is the output buffer for #GetEventInfo. The data stored here depends on the #EventType.

Type0:

Offset Size Description
0x0 0x4

[12.0.0+] Type0:

Offset Size Description
0x0 0x6 Device address.
0x6 0xF9 Device name, NUL-terminated string.
0xFF 0x3 Class of Device.
0x102 0x6 Reserved

[12.0.0+] Type1:

Offset Size Description
0x0 0x1 Status: 0 = stopped, 1 = started.
0x1 0x3 Padding
0x4 0x4 services value from #StartInquiry when starting, otherwise this is value 0.

[1.0.0-11.0.1] Type3:

Offset Size Description
0x0 0xF9 Device name, NUL-terminated string.
0xF9 0x6 Device address.
0xFF 0x10 Reserved
0x10F 0x3 Class of Device.
0x112 0x4 Set to fixed value u32 0x1.
0x116 0xFA Reserved
0x210 0x5C Reserved
0x26C 0xF9 Device name, NUL-terminated string. Same as name above, except starting at index 1.
0x365 0x4 s32 RSSI
0x369 0x4 Two bytes which are the same as name[11-12].
0x36D 0x10 Reserved

[1.0.0-11.0.1] Type4:

Offset Size Description
0x0 0x4 Status: 0 = stopped, 1 = started.

Type2 ([1.0.0-11.0.1] type5):

Offset Size Description
0x0 0x6 Device address.
0x6 0xF9 Device name, NUL-terminated string.
0xFF 0x3 Class of Device.

[1.0.0-11.0.1] Type6:

Offset Size Description
0x0 0x6 Device address.
0x6 0xF9 Device name, NUL-terminated string.
0xFF 0x3 Class of Device.
0x102 0x2 Padding
0x104 0x4 0 = SSP confirm request, 3 = SSP passkey notification.
0x108 0x4 s32 Passkey, only set when the above field is value 3.

[12.0.0+] Type3:

Offset Size Description
0x0 0x6 Device address.
0x6 0xF9 Device name, NUL-terminated string.
0xFF 0x3 Class of Device.
0x102 0x1 bool flag for Just Works. With SSP passkey notification this is always 0.
0x103 0x1 Padding
0x104 0x4 s32 Passkey

[1.0.0-8.1.1] Type7:

Offset Size Description
0x0 0x6 Device address.
0x6 0x2 Padding
0x8 0x4 Status, always 0 except with 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

[9.0.0-11.0.1] Type7:

Offset Size Description
0x0 0x4 Status, always 0 except with 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.
0xA 0x2 Padding
0xC 0x4 #ConnectionEventType

[12.0.0+] Type4:

Offset Size Description
0x0 0x4 #ConnectionEventType
0x4 0x6 Device address.
0xA 0xFE Reserved

[12.0.0+] Type5:

Offset Size Description
0x0 0x6 Device address.
0x6 0x1 Status flag: 1 = success, 0 = failure.
0x7 0x1 Tsi value, when the above indicates success.


[12.0.0+] Type6:

Offset Size Description
0x0 0x6 Device address.
0x6 0x1 Status flag: 1 = success, 0 = failure.
0x7 0x1 Input bool value from #EnableBurstMode, when the above indicates success.


[12.0.0+] Type7:

Offset Size Description
0x0 0x6 Device address.
0x6 0x1 Status flag: 1 = success, 0 = failure.
0x7 0x1 Bool flag, when the above indicates success.

[12.0.0+] Type8:

Offset Size Description
0x0 0x1 Status flag: 0 = failure, 1 = success.
0x1 0x3 Padding
0x4 0x4 Count value.

[12.0.0+] Type9:

Offset Size Description
0x0 0x6 Device address.
0x6 0x1 Status flag: 1 = success, 0 = failure.

Type10 ([1.0.0-11.0.1] type13):

Offset Size Description
0x0 0x2 #FatalReason

HidEventInfo

This is the output buffer for #GetHidEventInfo / events in sharedmem. The data stored here depends on the #HidEventType.

Type0, for #GetHidEventInfo:

[1.0.0-11.0.1]

Offset Size Description
0x0 0x6 Device address.
0x6 0x2 Padding
0x8 0x4 Status: 0 = hid connection opened, 2 = hid connection closed, 8 = failed to open hid connection.

[12.0.0+]

Offset Size Description
0x0 0x4 Status: 0 = hid connection closed, 1 = hid connection opened, 2 = failed to open hid connection.
0x4 0x6 Device address.

BluetoothPinCode

This is "nn::bluetooth::BluetoothPinCode". This is a 0x10-byte struct with 1-byte alignment.

PinCode

This is "nn::bluetooth::hal::PinCode". This is a 0x11-byte struct with 1-byte alignment.

Offset Size Description
0x0 0xF PinCode
0xF 0x1 PinCode length, must be 0x1-0xF otherwise the sysmodule will Abort.

ServiceFlag

This is "nn::bluetooth::hal::ServiceFlag". This is the same as the BSA service-mask.

HidData

This is "nn::bluetooth::HidData". This is a 0x282-byte struct.

Offset Size Description
0x0 0x2 Size of the following data.
0x2 0x280 Data

HidReport

This is "nn::bluetooth::HidReport". This is a 0x2BE-byte struct.

Offset Size Description
0x0 0x2 Size of the following data.
0x2 0x2BC Data

PlrStatistics

This is "nn::bluetooth::PlrStatistics". This is a 0x84-byte struct.

PlrList

This is "nn::bluetooth::PlrList". This is a 0xA4-byte struct.

PacketLostRate

This is "nn::bluetooth::hal::PacketLostRate".

ChannelMapList

This is "nn::bluetooth::ChannelMapList". This is a 0x88-byte struct.

Channel

This is "nn::bluetooth::hal::Channel".

LeChannel

This is "nn::bluetooth::hal::LeChannel".

LeConnectionParams

This is "nn::bluetooth::LeConnectionParams". This is a 0x14-byte struct with 2-byte alignment.

BleConnectionParameter

This is "nn::bluetooth::BleConnectionParameter". This is a 0xC-byte struct with 2-byte alignment.

BleAdvertisePacketData

This is "nn::bluetooth::BleAdvertisePacketData" ([5.0.0-8.1.1] "nn::bluetooth::LeAdvertiseData"). This is a 0xCC-byte struct.

Offset Size Description
0x0 0x4
0x4 0x1
0x5 0x1 Size of the data at +0x6.
0x6 0x1F
0x25 0x3 Padding
0x28 0x1 Total array entries for the below array, can be 0.
0x29 0x7 Padding
0x30 count*0x14 Array entries, see below.
0xA4 0x1 Size of the data at +0xA8.
0xA5 0x1
0xA6 0x2 Padding
0xA8 0x1F
0xC7 0x1
0xC8 0x1
0xC9 0x3 Padding

Array entry:

Offset Size Description
0x0 0x2
0x2 0x12 Unused

BleAdvertiseFilter

This is "nn::bluetooth::BleAdvertiseFilter". This is a 0x3E-byte struct.

Offset Size Description
0x0 0x1 FilterId
0x1 0x1 CondDataSize. Only used with CondType Manu.
0x2 0x1 CondType
0x3 0x1D CondData, content depends on CondType.
0x20 0x1D Mask. Only used with CondType Manu. +0 = u16 CompanyIdMask, then {pattern mask}.
0x3D 0x1 MaskSize. Only used with CondType Manu.

CondType:

Value Name Description
2-3 ServiceUuid16. CondData = 16bit UUID which is byteswapped.
4-5 ServiceUuid32. CondData = 32bit UUID which is byteswapped.
6-7 ServiceUuid128. CondData = 128bit UUID which is copied raw into the param struct.
255 Manu. CondData: u16 CompanyId, then {pattern data}.

To pass filtering, the BLE advert data should be: data & Mask == CondData (following the type field in the advert entry with the matching type).

BleAdvertisePacketParameter

This is "nn::bluetooth::BleAdvertisePacketParameter". This is a 8-byte struct with 1-byte alignment.

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}.

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}.

Offset Size Description
0x0 0x2 CompanyId
0x2 0x6 PatternData

BleScanResult

This is "nn::bluetooth::BleScanResult". This is a 0x148-byte struct.

Offset Size Description
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 GetBleScanParameterGeneral (entry+0x4 is skipped over).
0x140 0x4 s32 Total entries in the array at 0x8.
0x144 0x4 s32

BleConnectionInfo

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

Offset Size Description
0x0 0x4 ConnectionHandle, 0xFFFFFFFF ([5.0.0-5.0.2] 0xFFFF) is invalid.
0x4 0x6 #Address
0xA 0x2 Padding

GattAttributeUuid

This is "nn::bluetooth::GattAttributeUuid". This is a 0x14-byte struct with 4-byte alignment.

Offset Size Description
0x0 0x4 #BleGattUuid size. Must be 0x2, 0x4, or 0x10.
0x4 0x10 #BleGattUuid with the above size.

GattId

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

Offset Size Description
0x0 0x1 InstanceId
0x1 0x3 Padding
0x4 0x14 #GattAttributeUuid

BleGattUuid

This is an enum of u16, u32 and u128 values.

Value Description
0x2902 ClientConfigUuid16
0x2908 ReportReferenceUuid16
0x1B666C080A578E83994EA7F7BF50DDA3 PalmaOtafuControlPointUuid128
0x26FE2EE709244FB7914061D97A6CE8A2 PalmaOtafuDataUuid128
0x45CEF889AF8E0784664404737C7FBE2B NbatUuid128
0x46CEF889AF8E0784664404737C7FBE2B BatteryLevelUuid128
0x47CEF889AF8E0784664404737C7FBE2B BatteryStateUuid128
0xD88B7646729DBDA17A4425F4101126C7 PalmaOtafuUuid128
0xE5237AE2516B55BB67456DF36CE17566 NhogUuid128
0xE6237AE2516B55BB67456DF36CE17566 InputReportUuid128
0xE7237AE2516B55BB67456DF36CE17566 OutputCommandUuid128
0xE8237AE2516B55BB67456DF36CE17566 CommandResponseUuid128

BleClientGattOperationStatus

This is an u8 enum. This is converted from the #LeEventInfo status field.

Value Name Description
0 Same as #LeEventInfo status 0.
1 Same as #LeEventInfo status 55.
2 Same as #LeEventInfo status 25, 52.
3 Same as #LeEventInfo status 4, 16, 21, 50.
4 Same as #LeEventInfo status 5.
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.

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.

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.

Value Name Description
0 None
1 Connection

AudioEventInfo

This is the output buffer for #GetAudioEventInfo. The data stored here depends on the #AudioEventType.

Type1:

Offset Size Description
0x0 0x4 Status: 0 = AV connection closed, 1 = AV connection opened, 2 = failed to open AV connection.
0x4 0x6 Device 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.

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.

Value Description
0 Stopped
1 Started

AudioCodec

This is "nn::bluetooth::system::AudioCodec". This is an u32 enum.

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 sudo hcitool info {BDADDR} 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> 
   <EV4 packets> <EV5 packets> <AFH cap. slave> 
   <AFH class. slave> <LE support> <3-slot EDR ACL> 
   <5-slot EDR ACL> <sniff subrating> <pause encryption> 
   <AFH cap. master> <AFH class. master> <EDR eSCO 2 Mbps> 
   <EDR eSCO 3 Mbps> <3-slot EDR eSCO> <extended inquiry> 
   <LE and BR/EDR> <simple pairing> <encapsulated PDU> 
   <err. data report> <non-flush flag> <LSTO> <inquiry TX power> 
   <EPC> <extended features> 
 Features page 1: 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
 Features page 2: 0x7f 0x0b 0x00 0x00 0x00 0x00 0x00 0x00

The bluetooth driver implements the bluetooth protocol over h4/uart. It interfaces with the uart service to actually talk with the bluetooth hardware.

The bluetooth stack is Broadcom/Cypress brcm BSA (for example, see here).

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), [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.

l2cu_send_peer_echo_rsp is called with p_data=NULL and data_len=0, therefore no data is returned in the L2CAP ECHO response.

The following HID transaction types are supported (by hidh_l2cif_data_ind): HANDSHAKE, CONTROL (only param VIRTUAL_CABLE_UNPLUG is supported), DATA, DATAC.

  • DATAC is not actually supported, since the callback function (bta_hh_cback) just frees the message and returns.

Versions

System Version bsa_version_string bsa_version_info_string Config string
[1.0.0] BSA0106_01.60.00_ Hayward_J3_Patch_20161118 BCM4356A3_001.004.009.0045.0000
[2.0.0] BSA0106_01.60.00_ Hayward_J5_RC_20161227 BCM4356A3_001.004.009.0047.0049
[3.0.0-3.0.1] BSA0106_01.60.00_ Hayward_K4_RC_20170504 BCM4356A3_001.004.009.0054.0056
[4.0.0] BSA0106_01.60.00_ Hayward_L4_RC_20170815 CYW4356A3_001.004.009.0057.0059
[5.0.0] BSA0106_01.60.00_ Hayward_M2_RC_20180109 CYW4356A3_001.004.009.0059.0061
[5.1.0] BSA0106_01.60.00_ Hayward_N1_RC_20180226 CYW4356A3_001.004.009.0062.0064
[6.0.0-6.2.0] BSA0106_01.60.00_ Hayward_N3_RC_20180612 CYW4356A3_001.004.009.0062.0064
[7.0.0] BSA0106_01.60.00_ Hayward_O1_RC_20180829 CYW4356A3_001.004.009.0076.0077
[8.0.0-9.0.0] BSA0106_01.60.00_ Hayward_P1_RC_20190121 CYW4356A3_001.004.009.0076.0077
[10.0.0-11.0.0] BSA0106_01.60.00_ Hayward_R2_RC_20191119 CYW4356A3_001.004.009.0092.0095
[12.0.0-14.1.2] BSA0106_01.60.00_ Hayward_T3_RC_20210224 CYW4356A3_001.004.009.0092.0095
[15.0.0-18.0.0] BSA0106_01.60.00_ Hayward_T3_RC_20210224 BCM4356A3 UART 37.4 MHz wlbga_bu

bsa_sv_tm_read_version_excback copies bsa_version_string and concats with bsa_version_info_string to generate tBSA_TM_READ_VERSION.bsa_server_version.

  • [15.0.0]: In the HCI memwrite data, only config data was changed, no code changes.