0% found this document useful (0 votes)
347 views544 pages

BT Stack

Uploaded by

Funny POUM
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
347 views544 pages

BT Stack

Uploaded by

Funny POUM
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 544

master-87e52a097

December 13, 2024

BTstack Manual
Including Quickstart Guide

Dr. sc. Milanka Ringwald


Dr. sc. Matthias Ringwald
[email protected]
1

Contents
0.1. General Tools 2
0.2. Getting BTstack from GitHub 2
0.3. Let’s Go 2
0.4. Single threaded design 3
0.5. No blocking anywhere 4
0.6. No artificially limited buffers/pools 4
0.7. Statically bounded memory 4
0.8. Configuration in btstack config.h 5
0.8.1. HAVE * directives 5
0.8.2. ENABLE * directives 6
0.8.3. HCI Controller to Host Flow Control 9
0.8.4. Memory configuration directives 9
0.8.5. Non-volatile memory (NVM) directives 10
0.8.6. HCI Dump Stdout directives 11
0.8.7. SEGGER Real Time Transfer (RTT) directives 11
0.9. Run-time configuration 11
0.10. Source tree structure 12
0.11. Run loop configuration 13
0.11.1. Run Loop Embedded 14
0.11.2. Run Loop FreeRTOS 14
0.11.3. Run Loop POSIX 15
0.11.4. Run loop CoreFoundation (OS X/iOS) 15
0.11.5. Run Lop Qt 15
0.11.6. Run loop Windows 15
0.11.7. Run loop WICED 15
0.12. HCI Transport configuration 15
0.13. Services 17
0.14. Packet handlers configuration 17
0.15. Bluetooth HCI Packet Logs 19
0.16. Bluetooth Power Control 20
0.17. HCI - Host Controller Interface 22
0.17.1. Defining custom HCI command templates 22
0.17.2. Sending HCI command based on a template 23
0.18. L2CAP - Logical Link Control and Adaptation Protocol 24
0.18.1. Access an L2CAP service on a remote device 24
0.18.2. Provide an L2CAP service 25
0.18.3. Sending L2CAP Data 26
0.18.4. LE Data Channels 27
0.19. RFCOMM - Radio Frequency Communication Protocol 27
0.19.1. No RFCOMM packet boundaries 27
0.19.2. RFCOMM flow control 28
0.19.3. Access an RFCOMM service on a remote device 28
0.19.4. Provide an RFCOMM service 29
0.19.5. Slowing down RFCOMM data reception 30
0.19.6. Sending RFCOMM data 31
2

0.19.7. Optimized sending of RFCOMM data 32


0.20. SDP - Service Discovery Protocol 33
0.20.1. Create and announce SDP records 33
0.20.2. Query remote SDP service 33
0.21. BNEP - Bluetooth Network Encapsulation Protocol 35
0.21.1. Receive BNEP events 35
0.21.2. Access a BNEP service on a remote device 35
0.21.3. Provide BNEP service 35
0.21.4. Sending Ethernet packets 35
0.22. ATT - Attribute Protocol 35
0.23. SMP - Security Manager Protocol 36
0.23.1. LE Legacy Pairing and LE Secure Connections 36
0.23.2. Initialization 36
0.23.3. Configuration 37
0.23.4. Identity Resolving 37
0.23.5. User interaction during Pairing 37
0.23.6. Connection with Bonded Devices 38
0.23.7. Keypress Notifications 38
0.23.8. Cross-transport Key Derivation (CTKD) for LE Secure
Connections 38
0.23.9. Out-of-Band Data with LE Legacy Pairing 39
0.24. A2DP - Advanced Audio Distribution 39
0.25. AVRCP - Audio/Video Remote Control Profile 39
0.26. GAP - Generic Access Profile: Classic 39
0.26.1. Become discoverable 39
0.26.2. Discover remote devices 40
0.26.3. Pairing of Devices 41
0.26.4. Dedicated Bonding 42
0.27. SPP - Serial Port Profile 42
0.27.1. Accessing an SPP Server on a remote device 42
0.27.2. Providing an SPP Server 43
0.28. PAN - Personal Area Networking Profile 43
0.28.1. Accessing a remote PANU service 43
0.28.2. Providing a PANU service 43
0.29. HSP - Headset Profile 44
0.30. HFP - Hands-Free Profile 44
0.30.1. Supported Features 44
0.30.2. Audio Voice Recognition Activation 45
0.30.3. Enhanced Audio Voice Recognition 46
0.31. HID - Human-Interface Device Profile 47
0.32. GAP LE - Generic Access Profile for Low Energy 47
0.32.1. Private addresses. 47
0.32.2. Advertising and Discovery 48
0.33. GATT Client 48
0.33.1. Authentication 49
0.34. GATT Server 49
0.34.1. Implementing Standard GATT Services 51
3

0.34.2. GATT Database Hash 53


0.35. Battery Service Server 54
0.36. Bond Management Service Server 54
0.37. Cycling Power Service Server 54
0.38. Cycling Speed and Cadence Service Server 54
0.39. Device Information Service Server 55
0.40. Heart Rate Service Server 55
0.41. HIDS Device 55
0.42. Nordic SPP Service Server 55
0.43. Scan Parameters Service Server 55
0.44. Tx Power Service Server 56
0.45. u-blox SPP Service Server 56
0.46. ANCS Client 56
0.47. Battery Service Client 56
0.48. Device Information Service Client 56
0.49. HIDS Client 56
0.50. Scan Parameters Service Client 56
0.51. Hello World - Blinking an LED without Bluetooth 58
0.51.1. Periodic Timer Setup 58
0.51.2. Main Application Setup 59
0.52. GAP Classic Inquiry 59
0.52.1. Bluetooth Logic 59
0.52.2. Main Application Setup 60
0.53. GAP Link Key Management (Classic) 60
0.53.1. GAP Link Key Logic 60
0.53.2. Bluetooth Logic 60
0.53.3. Main Application Setup 60
0.54. GAP LE Advertisements Scanner 61
0.54.1. GAP LE setup for receiving advertisements 61
0.54.2. GAP LE Advertising Data Dumper 61
0.54.3. HCI packet handler 64
0.55. GATT Client - Discover Primary Services 65
0.55.1. GATT client setup 66
0.55.2. HCI packet handler 66
0.55.3. GATT Client event handler 68
0.56. GATT Server - Heartbeat Counter over GATT 68
0.56.1. Main Application Setup 69
0.56.2. Heartbeat Handler 71
0.56.3. Packet Handler 71
0.56.4. ATT Read 72
0.56.5. ATT Write 72
0.57. Performance - Stream Data over GATT (Server) 73
0.57.1. Main Application Setup 73
0.57.2. Track throughput 74
0.57.3. HCI Packet Handler 75
0.57.4. ATT Packet Handler 77
0.57.5. Streamer 78
4

0.57.6. ATT Write 79


0.58. GATT Battery Service Client 80
0.58.1. Main Application Setup 80
0.59. GATT Device Information Service Client 83
0.59.1. Main Application Setup 84
0.60. GATT Heart Rate Sensor Client 86
0.61. LE Nordic SPP-like Heartbeat Server 86
0.61.1. Main Application Setup 86
0.61.2. Heartbeat Handler 87
0.62. LE Nordic SPP-like Streamer Server 87
0.62.1. Track throughput 87
0.62.2. HCI Packet Handler 88
0.62.3. ATT Packet Handler 89
0.62.4. Streamer 90
0.63. LE u-blox SPP-like Heartbeat Server 91
0.63.1. Main Application Setup 91
0.63.2. Heartbeat Handler 92
0.63.3. Packet Handler 92
0.64. LE Central - Test Pairing Methods 93
0.64.1. GAP LE setup for receiving advertisements 93
0.64.2. HCI packet handler 95
0.64.3. HCI packet handler 95
0.65. LE Peripheral - Test Pairing Methods 98
0.65.1. Main Application Setup 99
0.65.2. Security Manager Packet Handler 101
0.65.3. HCI Packet Handler 101
0.66. LE Credit-Based Flow-Control Mode Client - Send Data over
L2CAP 105
0.66.1. Track throughput 105
0.66.2. Streamer 106
0.66.3. SM Packet Handler 106
0.67. LE Credit-Based Flow-Control Mode Server - Receive data over
L2CAP 106
0.67.1. Track throughput 107
0.67.2. Streamer 107
0.67.3. HCI + L2CAP Packet Handler 108
0.67.4. SM Packet Handler 108
0.67.5. Main Application Setup 108
0.68. LE Peripheral - Delayed Response 108
0.68.1. Main Application Setup 108
0.68.2. att invalidate value Handler 109
0.68.3. att update value Handler 109
0.68.4. ATT Read 110
0.68.5. ATT Write 110
0.69. LE ANCS Client - Apple Notification Service 112
0.70. LE Man-in-the-Middle Tool 112
0.71. Performance - Stream Data over GATT (Client) 112
5

0.71.1. Track throughput 112


0.72. Performance - Stream Data over GATT (Server) 113
0.72.1. Main Application Setup 113
0.72.2. Track throughput 114
0.72.3. HCI Packet Handler 114
0.72.4. ATT Packet Handler 117
0.72.5. Streamer 118
0.72.6. ATT Write 119
0.73. LE Credit-Based Flow-Control Mode Client - Send Data over
L2CAP 120
0.73.1. Track throughput 120
0.73.2. Streamer 121
0.73.3. SM Packet Handler 121
0.74. LE Credit-Based Flow-Control Mode Server - Receive data over
L2CAP 121
0.74.1. Track throughput 122
0.74.2. Streamer 122
0.74.3. HCI + L2CAP Packet Handler 123
0.74.4. SM Packet Handler 123
0.74.5. Main Application Setup 123
0.75. Performance - Stream Data over SPP (Client) 123
0.75.1. Track throughput 123
0.75.2. SDP Query Packet Handler 124
0.75.3. Gerenal Packet Handler 124
0.75.4. Main Application Setup 124
0.76. Performance - Stream Data over SPP (Server) 124
0.76.1. Track throughput 125
0.76.2. Packet Handler 125
0.76.3. Main Application Setup 125
0.77. A2DP Sink - Receive Audio Stream and Control Playback 126
0.77.1. Main Application Setup 127
0.77.2. Handle Media Data Packet 131
0.78. A2DP Source - Stream Audio and Control Volume 131
0.78.1. Main Application Setup 131
0.79. AVRCP Browsing - Browse Media Players and Media Information 134
0.79.1. Main Application Setup 135
0.80. HFP AG - Audio Gateway 137
0.80.1. Main Application Setup 137
0.81. HFP HF - Hands-Free 139
0.81.1. Main Application Setup 139
0.82. HSP AG - Audio Gateway 141
0.82.1. Audio Transfer Setup 141
0.82.2. Main Application Setup 141
0.83. HSP HS - Headset 142
0.83.1. Audio Transfer Setup 142
0.83.2. Main Application Setup 143
0.84. Audio Driver - Play Sine 144
6

0.85. Audio Driver - Play 80’s MOD Song 144


0.86. Audio Driver - Forward Audio from Source to Sink 144
0.87. SPP Server - Heartbeat Counter over RFCOMM 144
0.87.1. SPP Service Setup 144
0.87.2. Periodic Timer Setup 145
0.87.3. Bluetooth Logic 146
0.88. SPP Server - RFCOMM Flow Control 147
0.88.1. SPP Service Setup 147
0.88.2. Periodic Timer Setup 148
0.89. PAN - lwIP HTTP and DHCP Server 149
0.89.1. Packet Handler 149
0.89.2. PAN BNEP Setup 149
0.89.3. DHCP Server Configuration 149
0.89.4. Large File Download 149
0.89.5. DHCP Server Setup 149
0.89.6. Main 149
0.90. BNEP/PANU (Linux only) 149
0.90.1. Main application configuration 150
0.90.2. SDP parser callback 151
0.90.3. Packet Handler 151
0.90.4. Network packet handler 153
0.91. HID Keyboard Classic 153
0.91.1. Main Application Setup 153
0.92. HID Mouse Classic 155
0.92.1. Main Application Setup 155
0.93. HID Host Classic 157
0.93.1. Main application configuration 157
0.93.2. HID Report Handler 158
0.93.3. Packet Handler 158
0.94. HID Keyboard LE 161
0.95. HID Mouse LE 161
0.96. HID Boot Host LE 161
0.96.1. HOG Boot Keyboard Handler 161
0.96.2. HOG Boot Mouse Handler 161
0.96.3. Test if advertisement contains HID UUID 161
0.96.4. HCI packet handler 163
0.97. Dual Mode - SPP and LE Counter 164
0.97.1. Advertisements 164
0.97.2. Packet Handler 165
0.97.3. Heartbeat Handler 165
0.97.4. Main Application Setup 165
0.98. Performance - Stream Data over GATT (Server) 167
0.98.1. Main Application Setup 167
0.98.2. Track throughput 168
0.98.3. HCI Packet Handler 169
0.98.4. ATT Packet Handler 171
0.98.5. Streamer 172
7

0.98.6. ATT Write 173


0.99. SDP Client - Query Remote SDP Records 174
0.99.1. SDP Client Setup 174
0.99.2. SDP Client Query 175
0.99.3. Handling SDP Client Query Results 175
0.100. SDP Client - Query RFCOMM SDP record 176
0.101. SDP Client - Query BNEP SDP record 176
0.101.1. SDP Client Setup 176
0.101.2. SDP Client Query 177
0.101.3. Handling SDP Client Query Result 177
0.102. PBAP Client - Get Contacts from Phonebook Server 179
0.103. Testing - Enable Device Under Test (DUT) Mode for Classic 179
0.103.1. Bluetooth Logic 179
0.103.2. Main Application Setup 179
0.104. HCI Interface 180
0.104.1. HCI H2 180
0.104.2. HCI H4 180
0.104.3. HCI H5 181
0.104.4. BCSP 181
0.104.5. eHCILL 181
0.104.6. H4 over SPI 182
0.104.7. HCI Shortcomings 182
0.105. Documentation and Support 182
0.106. Chipset Overview 185
0.107. Atmel/Microchip 186
0.108. Broadcom/Cypress/Infineon Semiconductor 186
0.109. CSR / Qualcomm Incorporated 188
0.110. Dialog Semiconductor / Renesas 188
0.111. Espressif ESP32 189
0.112. EM Microelectronic Marin 189
0.113. Intel Dual Wireless 8260, 8265 190
0.114. Nordic nRF5 series 190
0.115. NXP Semiconductors 191
0.116. Realtek 191
0.117. Renesas Electronics 191
0.118. STMicroelectronics 192
0.118.1. STLC2500D 192
0.118.2. BlueNRG 192
0.118.3. STM32-WB5x 192
0.119. Texas Instruments CC256x series 192
0.120. Toshiba 194
0.121. Time Abstraction Layer 194
0.121.1. Tick Hardware Abstraction 194
0.121.2. Time MS Hardware Abstraction 195
0.122. Bluetooth Hardware Control API 195
0.123. HCI Transport Implementation 195
0.123.1. HCI UART Transport Layer (H4) 195
8

0.123.2. H4 with eHCILL support 196


0.123.3. H5 196
0.124. Persistent Storage APIs 196
0.124.1. Link Key DB 197
0.125. Existing ports 197
0.126. BTstack Port for Ambiq Apollo2 with EM9304 198
0.126.1. Hardware 198
0.126.2. Software 198
0.126.3. Create Example Projects 198
0.126.4. Compile & Run Example Project 199
0.126.5. Debug output 199
0.126.6. TODO 199
0.127. Archive of earlier ports 199
0.128. BTstack Port for the Espressif ESP32 Platform 200
0.128.1. Setup 200
0.128.2. Usage 200
0.128.3. Configuration 201
0.128.4. Limitations 201
0.128.5. Issues with the Bluetooth Controller Implementation 201
0.128.6. Audio playback 201
0.128.7. ESP32 printf/log 202
0.128.8. Multi-Threading 202
0.128.9. Acknowledgments 202
0.129. BTstack Port for FreeBSD Systems 202
0.129.1. Overview 202
0.129.2. Implementation details 202
0.129.3. Compilation 202
0.129.4. Running the examples 203
0.129.5. ToDO 203
0.130. BTstack Port for POSIX Systems with libusb Library 203
0.130.1. Compilation 203
0.130.2. Environment Setup 203
0.130.3. Linux 204
0.130.4. macOS 204
0.130.5. Broadcom/Cypress/Infineon Controllers 204
0.130.6. Realtek Controllers 205
0.130.7. Running the examples 205
0.131. BTstack Port for POSIX Systems with Intel Wireless 8260/8265
Controllers 206
0.131.1. Compilation 206
0.131.2. Environment 206
0.131.3. Running the examples 207
0.132. BTstack Port for the Maxim MAX32630FTHR ARM Cortex-M4F208
0.132.1. Software 208
0.132.2. Toolchain Setup 208
0.132.3. Usage 208
0.132.4. Build 208
9

0.132.5. Eclipse 208


0.132.6. Flashing Max32630 ARM Processor 208
0.132.7. Debugging 209
0.132.8. Debug output 209
0.132.9. TODOs 209
0.133. BTstack Port for MSP432P401 Launchpad with CC256x 209
0.133.1. Hardware 209
0.133.2. Software 210
0.133.3. Flash And Run The Examples 210
0.133.4. Run Example Project using Ozone 210
0.133.5. Debug output 210
0.133.6. GATT Database 210
0.134. BTstack Port with Cinnamon for Nordic nRF5 Series 210
0.134.1. Status 210
0.134.2. Requirements 211
0.134.3. Supported Hardware 211
0.134.4. Use 211
0.135. BTstack Port for POSIX Systems with H4 Bluetooth Controller 211
0.135.1. Configuration 211
0.135.2. TI CC256x 211
0.135.3. Broadcom BCM/CYW 43430 211
0.135.4. Compilation 211
0.135.5. Running the examples 212
0.136. BTstack Port for POSIX Systems with Atmel ATWILC3000
Controller 212
0.136.1. Compilation 212
0.136.2. Usage 212
0.137. BTstack Port for POSIX Systems with modern Infineon (CYW)
H4 Bluetooth Controller 214
0.137.1. Configuration 214
0.137.2. Compilation 214
0.137.3. Running the examples 214
0.137.4. ToDo 214
0.138. BTstack Port for POSIX Systems with Dialog Semiconductor
DA14531 Controller 214
0.139. Software Setup / Firmware 215
0.140. Hardware Setup - Dev Kit Pro 215
0.141. Hardware Setup - Dev Kit USB 216
0.142. BTstack Port for POSIX Systems with Dialog Semiconductor
DA14581 Controller 216
0.143. BTstack Port for POSIX Systems with Dialog Semiconductor
DA14585 Controller 216
0.144. BTstack Port for POSIX Systems with NXP/Marvel H4 Bluetooth
Controller 216
0.144.1. Configuration 216
0.144.2. Compilation 217
0.144.3. Running the examples 217
10

0.144.4. Issues 217


0.144.5. ToDo 217
0.145. BTstack Port for POSIX Systems with Zephyr-based Controller 217
0.145.1. Prepare Zephyr Controller 217
0.145.2. Configure serial port 218
0.145.3. Compile Examples 218
0.145.4. Run example 218
0.146. BTstack Port for QT with H4 Bluetooth Controller 218
0.146.1. Configuration 218
0.146.2. TI CC256x 218
0.146.3. Broadcom BCM/CYW 43430 218
0.146.4. Compilation 219
0.146.5. Running the examples 219
0.147. BTstack Port for QT with USB Bluetooth Dongle 219
0.147.1. Compilation 219
0.147.2. Environment Setup 219
0.147.3. Windows 219
0.147.4. Linux 219
0.147.5. macOS 220
0.147.6. Running the examples 220
0.148. BTstack Port for Raspberry Pi 3 with BCM4343 Bluetooth/Wifi
Controller 221
0.148.1. Raspberry Pi 3 / Zero W Setup 221
0.148.2. Install Raspian Stretch Lite: 221
0.148.3. Configure Wifi 221
0.148.4. Enable SSH 222
0.148.5. Boot 222
0.148.6. Disable bluez 222
0.148.7. Compilation 222
0.148.8. Compile using Docker 222
0.148.9. Running the examples 223
0.148.10. Bluetooth Hardware Overview 223
0.148.11. TODO 223
0.149. BTstack Port for Renesas Eval Kit EK-RA6M4 with DA14531 224
0.149.1. Hardware 224
0.149.2. Renesas Eval Kit EK-RA6M4: 224
0.149.3. Renesas DA14531 Module on MikroE BLE Tiny Click board
with 224
0.149.4. Software 225
0.149.5. Run Example Project using Ozone 225
0.149.6. Debug output 225
0.149.7. Setup 226
0.149.8. Updating HAL Configuration 226
0.150. BTstack Port for Renesas Target Board TB-S1JA with CC256x 226
0.150.1. Hardware 226
0.150.2. Software 228
0.150.3. Excluded Examples 228
11

0.150.4. Build, Flash And Run The Examples in e2 Studio 228


0.150.5. Run Example Project using Ozone 228
0.150.6. Debug output 228
0.150.7. GATT Database 228
0.150.8. Notes 229
0.150.9. Nice to have 229
0.151. BTstack Port for SAMV71 Ultra Xplained with ATWILC3000
SHIELD 229
0.151.1. Create Example Projects 229
0.151.2. Compile Example 229
0.151.3. Debug output 229
0.151.4. TODOs 229
0.151.5. Issues 230
0.152. BTstack Port for STM32 F4 Discovery Board with CC256x 230
0.152.1. Hardware 230
0.152.2. Software 230
0.152.3. Flash And Run The Examples 230
0.152.4. Run Example Project using Ozone 230
0.152.5. Debug output 231
0.152.6. GATT Database 231
0.152.7. Maintainer Notes - Updating The Port 231
0.153. BTstack Port for STM32 F4 Discovery Board with USB Bluetooth
Controller 231
0.153.1. Hardware 231
0.153.2. Software 231
0.153.3. Flash And Run The Examples 231
0.153.4. Run Example Project using Ozone 232
0.153.5. Debug output 232
0.153.6. GATT Database 232
0.153.7. Maintainer Notes - Updating The Port 232
0.154. BTstack Port for STM32 Nucleo L073RZ Board with EM9304
Controller 232
0.154.1. Hardware 232
0.154.2. Software 232
0.154.3. Flash And Run The Examples 233
0.154.4. Run Example Project using Ozone 233
0.154.5. Debug output 233
0.154.6. GATT Database 233
0.154.7. Image 235
0.155. BTstack Port with Cinnamon for Semtech SX1280 Controller on
Miromico FMLR-80 236
0.155.1. Overview 236
0.155.2. Status 236
0.155.3. Limitation 236
0.155.4. Advertising State: 236
0.155.5. Connection State: 236
0.155.6. Central Role: 236
12

0.155.7. Observer Role: 236


0.155.8. Low power mode - basically not implemented: 236
0.155.9. Getting Started 236
0.155.10. TODO 236
0.155.11. General 237
0.155.12. Low Power 237
0.156. BTstack Port with Cinnamon for Semtech SX1280 Controller on
STM32L476 Nucleo 237
0.156.1. Overview 237
0.156.2. Status 237
0.156.3. Limitation 237
0.156.4. Advertising State: 237
0.156.5. Connection State: 237
0.156.6. Central Role: 237
0.156.7. Observer Role: 238
0.156.8. Low power mode - basically not implemented: 238
0.156.9. Getting Started 238
0.156.10. TODO 238
0.156.11. General 238
0.156.12. Low Power 238
0.157. BTstack Port for STM32WB55 Nucleo Boards using FreeRTOS 240
0.157.1. Hardware 240
0.157.2. Nucleo68 240
0.157.3. USB Dongle 240
0.157.4. Software 240
0.157.5. Flash And Run The Examples 240
0.157.6. Nucleo68 241
0.157.7. USB Dongle 241
0.157.8. Run Example Project using Ozone 241
0.157.9. Debug output 241
0.157.10. GATT Database 241
0.158. BTstack Port for WICED platform 241
0.159. BTstack Port for Windows Systems with Bluetooth Controller
connected via Serial Port 242
0.159.1. Visual Studio 2022 242
0.159.2. mingw64 242
0.159.3. Compilation with CMake 243
0.159.4. Console Output 243
0.160. BTstack Port for Windows Systems with DA14585 Controller
connected via Serial Port 243
0.160.1. Visual Studio 2022 243
0.160.2. mingw64 243
0.160.3. Compilation with CMake 244
0.160.4. Console Output 244
0.161. BTstack Port for Windows Systems with Zephyr-based Controller244
0.161.1. Prepare Zephyr Controller 244
0.161.2. Configure serial port 245
13

0.161.3. Visual Studio 2022 245


0.161.4. mingw64 245
0.161.5. Compilation with CMake 245
0.161.6. Console Output 246
0.162. BTstack Port for Windows Systems using the WinUSB Driver 246
0.162.1. Access to Bluetooth USB Dongle with Zadig 246
0.162.2. Visual Studio 2022 246
0.162.3. mingw64 246
0.162.4. Compilation with CMake 247
0.162.5. Console Output 247
0.163. BTstack Port for Windows Systems with Intel Wireless 8260/8265
Controllers 248
0.163.1. Access to Bluetooth USB Dongle with Zadig 249
0.163.2. Visual Studio 2022 249
0.163.3. mingw64 249
0.163.4. Compilation with CMake 250
0.163.5. Console Output 251
0.164. BTstack Port for Zephyr RTOS 251
0.164.1. Overview 251
0.164.2. Status 251
0.164.3. Build Environment 251
0.164.4. 1. Build Environment Preconditions 251
0.164.5. 2. Prepare the build environment 251
0.164.6. Building and Running on nRF52840 251
0.164.7. 1. Build Example 252
0.164.8. 2. Flash Example 252
0.164.9. Buiding and Running on nRF5340 252
0.164.10. 1. Building the application 252
0.164.11. 2a. Using zephyr network core image 252
0.164.12. 2b. Using Packetcraft binary network core image 253
0.164.13. TODO 253
0.165. Adapting BTstack for Single-Threaded Environments 253
0.166. Adapting BTstack for Multi-Threaded Environments 254
1. APIs 256
1.1. AD Data Parser API 256
1.2. ATT Database Engine API 256
1.3. Runtine ATT Database Setup API 263
1.4. ATT Dispatch API 266
1.5. ATT Server API 266
1.6. ANCS Client API 269
1.7. Battery Service Client API 270
1.8. Battery Service Server API 271
1.9. Bond Management Service Server API 271
1.10. Cycling Power Service Server API 273
1.11. Cycling Speed and Cadence Service Server API 280
1.12. Device Information Service Client API 281
1.13. Device Information Service Server API 282
14

1.14. Heart Rate Service Server API 284


1.15. HID Service Client API 285
1.16. HID Service Server API 289
1.17. Nordic SPP Service Server API 291
1.18. Scan Parameters Service Client API 291
1.19. Scan Parameters Service Server API 293
1.20. TX Power Service Server API 293
1.21. u-blox SPP Service Server API 293
1.22. GATT Client API 294
1.23. Device Database API 316
1.24. Device Database TLV API 319
1.25. Security Manager API 319
1.26. Audio Interface API 324
1.27. base64 Decoder API 327
1.28. Chipset Driver API 328
1.29. Bluetooth Power Control API 329
1.30. Debug Messages API 329
1.31. EM9304 SPI API 329
1.32. Finite State Machine (FSM) API 331
1.33. Human Interface Device (HID) API 332
1.34. HID Parser API 332
1.35. Hierarchical State Machine (HSM) API 334
1.36. LC3 Interface API 335
1.37. LC3 Google Adapter API 337
1.38. Adapter for Fraunhofer LC3plus Coddec API 338
1.39. Linked List API 338
1.40. Linked Queue API 341
1.41. Network Interface API 341
1.42. Lienar Resampling API 342
1.43. Ring Buffer API 343
1.44. Sample rate compensation API 344
1.45. SCO Transport API 345
1.46. SLIP encoder/decoder API 346
1.47. Tag-Value-Length Persistent Storage (TLV) API 347
1.48. Empty TLV Instance API 348
1.49. UART API 348
1.50. UART Block API 350
1.51. UART SLIP Wrapper API 351
1.52. General Utility Functions API 351
1.53. A2DP Sink API 358
1.54. A2DP Source API 363
1.55. AVDTP Sink API 368
1.56. AVDTP Source API 371
1.57. AVRCP Browsing API 377
1.58. AVRCP Browsing Controller API 378
1.59. AVRCP Browsing Target API 382
1.60. AVRCP Controller API 383
15

1.61. AVRCP Cover Art Client API 390


1.62. AVRCP Media Item Iterator API 391
1.63. AVRCP Target API 392
1.64. BNEP API 397
1.65. Link Key DB API 398
1.66. In-Memory Link Key Storage API 400
1.67. Static Link Key Storage API 400
1.68. Link Key TLV Storage API 400
1.69. Device ID Server API 401
1.70. GATT SDP API 401
1.71. GOEP Client API 401
1.72. HFP Audio Gateway (AG) API 409
1.73. HFP Audio Encoder API 420
1.74. HFP GSM Model API 421
1.75. HFP Hands-Free (HF) API 422
1.76. HFP mSBC Encoder API 436
1.77. HID Device API 436
1.78. HID Host API 439
1.79. HSP Audio Gateway API 443
1.80. HSP Headset API 445
1.81. Personal Area Network (PAN) API 448
1.82. PBAP Client API 449
1.83. PBAP Client API 451
1.84. RFCOMM API 455
1.85. SDP Client API 462
1.86. SDP Client RFCOMM API 464
1.87. SDP Server API 465
1.88. SDP Utils API 466
1.89. SPP Server API 468
1.90. Genral Access Profile (GAP) API 468
1.91. Host Controler Interface (HCI) API 494
1.92. HCI Logging API 500
1.93. HCI Transport API 502
1.94. HCI Transport EM9304 API API 504
1.95. HCI Transport H4 API 504
1.96. HCI Transport H5 API 504
1.97. HCI Transport USB API 505
1.98. L2CAP API 505
1.99. Audio Stream Control Service Client API 514
1.100. Broadcast Audio Scan Service Server (BASS) API 519
1.101. Volume Offset Control Service Server API 521
1.102. Broadcast Audio Source Endpoint AD Builder API 521
1.103. Broadcast Audio Source Endpoint AD Parser API 521
1.104. LE Audio Util API 521
1.105. Mesh Provisioning Service Server API 521
1.106. Mesh Proxy Service Server API 522
1.107. L2CAP Events 522
16

1.108. RFCOMM Events 523


1.109. Errors 524
2. Changes 525
2.1. Repository structure 525
2.1.1. include/btstack folder 525
2.1.2. Plural folder names 525
2.1.3. ble and src folders 525
2.1.4. platform and port folders 525
2.1.5. Common file names 525
2.2. Defines and event names 525
2.3. Function names 525
2.4. Packet Handlers 525
2.5. Event Forwarding 526
2.6. util folder 526
2.7. btstack config.h 526
2.8. Linked List 526
2.9. Run Loop 526
2.10. HCI Setup 526
2.10.1. remote device db 526
2.10.2. bt control 526
2.11. HCI / GAP 527
2.12. RFCOMM 527
2.13. SPP Server 527
2.14. SDP Client 527
2.15. SDP Server 527
2.16. Security Manager 527
2.17. GATT Client 527
2.18. ANCS Client 527
2.19. Flow control / DAEMON EVENT HCI PACKET SENT 527
2.20. Daemon 528
2.21. Migration to v1.0 with a script 528
2.21.1. Requirements 528
2.21.2. Usage 528
2.22. Migration to v1.0 with a Web Service 528
17

Thanks for checking out BTstack!


In this manual, we first provide a ‘quick starter guide’ for common platforms
before highlighting BTstack’s main design choices and go over all implemented
protocols and profiles.
A series of examples show how BTstack can be used to implement common
use cases.
Finally, we outline the basic steps when integrating BTstack into existing
single-threaded or even multi-threaded environments.
#Quick Start
0.1. General Tools. Most ports use a regular Makefile to build the examples.
On Unix-based systems, git, make, and Python are usually installed. If not,
use the system’s packet manager to install them.
On Windows, there is no packet manager, but it’s easy to download and install
all requires development packets quickly by hand. You’ll need:
• Python for Windows. When using the official installer, please confirm
adding Python to the Windows Path.
• MSYS2 is used to provide the bash shell and most standard POSIX com-
mand line tools.
• MinGW64 GCC for Windows 64 & 32 bits incl. make. To install with
MSYS2: pacman -S mingw-w64-x86 64-gcc
• git is used to download BTstack source code. To install with MSYS2:
pacman -S git
• winpty a wrapper to allow for console input when running in MSYS2: To
install with MSYS2: pacman -S winpty
0.2. Getting BTstack from GitHub. Use git to clone the latest version:

g i t c l o n e h t t p s : // g i t h u b . com/ b l u e k i t c h e n / b t s t a c k . g i t

Alternatively, you can download it as a ZIP archive from BTstack’s page on


GitHub.
0.3. Let’s Go. The easiest way to try BTstack is on a regular desktop setup like
macOS, Linux or Windows together with a standard USB Bluetooth Controller.
Running BTstack on desktop speeds up the development cycle a lot and also
provides direct access to full packet log files in cases something doesn’t work as
expected. The same code can then later be run unmodified on an embedded
target.
For macOS and Linux, please see libusb port. For Windows, please see
windows-winusb port.
Or checkout the list of existing ports
#BTstack Architecture
As well as any other communication stack, BTstack is a collection of state
machines that interact with each other. There is one or more state machines for
each protocol and service that it implements. The rest of the architecture follows
these fundamental design guidelines:
18

Main  Applica/on  

Communica/on  Logic   PH  

add timer timer ready Bluetooth  Stack  

Run  Loop   SDP   RFCOMM   ATT  


Data   add
Source   data source
L2CAP   LE  
Data   Data  
Source   Source   data source
ready
HCI  
Timeouts  

H4  UART   eHCILL  UART     … USB  

BTstack  

Bluetooth  Single/Dual  Mode  Chipset  

Architecture of a BTstack-based application.

• Single threaded design - BTstack does not use or require multi-threading


to handle data sources and timers. Instead, it uses a single run loop.
• No blocking anywhere - If Bluetooth processing is required, its result will
be delivered as an event via registered packet handlers.
• No artificially limited buffers/pools - Incoming and outgoing data packets
are not queued.
• Statically bounded memory (optionally) - The number of maximum con-
nections/channels/services can be configured.
Figure below shows the general architecture of a BTstack-based single-threaded
application that includes the BTstack run loop. The Main Application contains
the application logic, e.g., reading a sensor value and providing it via the Com-
munication Logic as a SPP Server. The Communication Logic is often modeled
as a finite state machine with events and data coming from either the Main Ap-
plication or from BTstack via registered packet handlers (PH). BTstack’s Run
Loop is responsible for providing timers and processing incoming data.
0.4. Single threaded design. BTstack does not use or require multi-threading.
It uses a single run loop to handle data sources and timers. Data sources represent
communication interfaces like an UART or an USB driver. Timers are used
19

by BTstack to implement various Bluetooth-related timeouts. For example, to


disconnect a Bluetooth baseband channel without an active L2CAP channel after
20 seconds. They can also be used to handle periodic events. During a run loop
cycle, the callback functions of all registered data sources are called. Then, the
callback functions of timers that are ready are executed.
For adapting BTstack to multi-threaded environments check here.
0.5. No blocking anywhere. Bluetooth logic is event-driven. Therefore, all
BTstack functions are non-blocking, i.e., all functions that cannot return im-
mediately implement an asynchronous pattern. If the arguments of a function
are valid, the necessary commands are sent to the Bluetooth chipset and the
function returns with a success value. The actual result is delivered later as an
asynchronous event via registered packet handlers.
If a Bluetooth event triggers longer processing by the application, the process-
ing should be split into smaller chunks. The packet handler could then schedule
a timer that manages the sequential execution of the chunks.
0.6. No artificially limited buffers/pools. Incoming and outgoing data pack-
ets are not queued. BTstack delivers an incoming data packet to the application
before it receives the next one from the Bluetooth chipset. Therefore, it relies
on the link layer of the Bluetooth chipset to slow down the remote sender when
needed.
Similarly, the application has to adapt its packet generation to the remote
receiver for outgoing data. L2CAP relies on ACL flow control between sender and
receiver. If there are no free ACL buffers in the Bluetooth module, the application
cannot send. For RFCOMM, the mandatory credit-based flow-control limits the
data sending rate additionally. The application can only send an RFCOMM
packet if it has RFCOMM credits.
0.7. Statically bounded memory. BTstack has to keep track of services and
active connections on the various protocol layers. The number of maximum con-
nections/channels/services can be configured. In addition, the non-persistent
database for remote device names and link keys needs memory and can be be
configured, too. These numbers determine the amount of static memory alloca-
tion.
#How to configure BTstack
BTstack implements a set of Bluetooth protocols and profiles. To connect to
other Bluetooth devices or to provide a Bluetooth services, BTstack has to be
properly configured.
The configuration of BTstack is done both at compile time as well as at run
time:
• compile time configuration:
– adjust btstack config.h - this file describes the system configuration,
used functionality, and also the memory configuration
– add necessary source code files to your project
• run time configuration of:
– Bluetooth chipset
– run loop
20

– HCI transport layer


– provided services
– packet handlers
In the following, we provide an overview of the configuration that is necessary
to setup BTstack. From the point when the run loop is executed, the application
runs as a finite state machine, which processes events received from BTstack.
BTstack groups events logically and provides them via packet handlers. We
provide their overview here. For the case that there is a need to inspect the
data exchanged between BTstack and the Bluetooth chipset, we describe how to
configure packet logging mechanism. Finally, we provide an overview on power
management in Bluetooth in general and how to save energy in BTstack.
0.8. Configuration in btstack config.h. The file btstack config.h contains
three parts:
• #define HAVE * directives listed here. These directives describe available
system properties, similar to config.h in a autoconf setup.
• #define ENABLE * directives listed here. These directives list enabled
properties, most importantly ENABLE CLASSIC and ENABLE BLE.
• other #define directives for BTstack configuration, most notably static
memory, see next section and NVM configuration.
0.8.1. HAVE * directives. System properties:

#define Description
HAVE AES128 Use platform AES128 engine
HAVE BTSTACK STDIN
STDIN is available for CLI interface
HAVE LWIP lwIP is available
HAVE MALLOC Use dynamic memory
HAVE MBEDTLS ECC
mbedTLS
P256 provides NIST P-256 operations e.g. for LE
Secure Connections

Embedded platform properties:

#define Description
HAVE EMBEDDED TIME MS System provides time in milliseconds
HAVE EMBEDDED TICK System provides tick interrupt
HAVE HAL AUDIO Audio HAL is available
HAVE HAL AUDIO SINK STEREO ONLY Duplicate samples for mono playback

FreeRTOS platform properties:

#define Description
HAVE FREERTOS INCLUDE
FreeRTOS
PREFIX
headers are in ‘freertos’ folder
(e.g. ESP32’s esp-idf)

POSIX platform properties:


21

#define Description
HAVE POSIX FILE IO POSIX File i/o used for hci dump
HAVE POSIX TIME System provides time function
LINK KEY PATH Path to stored link keys
LE DEVICE DB PATH Path to stored LE device information

Chipset properties:

#define Description
HAVE BCM PCM2 PCM2 is used and requires additional configuration
HAVE BCM PCM NBS 16KHZ
NBS is up/downsampled, use 16 kHz sample rate for
NBS

0.8.2. ENABLE * directives. BTstack properties:

#define Description
ENABLE CLASSIC Enable Classic related code in HCI and
L2CAP
ENABLE BLE Enable BLE related code in HCI and L2CAP
ENABLE EHCILL Enable eHCILL low power mode on TI
CC256x/WL18xx chipsets
ENABLE H5 Enable support for SLIP mode in btstack uart .h
drivers for HCI H5 (‘Three-Wire Mode’)
ENABLE LOG DEBUG Enable log debug messages
ENABLE LOG ERROR Enable log error messages
ENABLE LOG INFO Enable log info messages
ENABLE LOG BTSTACK EVENTS
Log internal/custom BTstack events
ENABLE SCO OVER HCI Enable SCO over HCI for chipsets (if
supported)
ENABLE SCO OVER PCM Enable SCO ofer PCM/I2S for chipsets (if
supported)
ENABLE HFP WIDE BANDEnable
SPEECH support for mSBC codec used in HFP
profile for Wide-Band Speech
ENABLE HFP AT MESSAGES
Enable HFP SUBEVENT AT MESSAGE SENT
and HFP SUBEVENT AT MESSAGE RECEIVED
events
ENABLE LE PERIPHERAL Enable support for LE Peripheral Role in HCI
and Security Manager
ENABLE LE CENTRAL Enable support for LE Central Role in HCI
and Security Manager
ENABLE LE SECURE CONNECTIONS
Enable LE Secure Connections
ENABLE LE SECURE CONNECTIONS
Enable support
DEBUG
for LEKEY
Secure Connection
debug keys for testing
ENABLE LE PROACTIVE AUTHENTICATION
Enable automatic encryption for bonded
devices on re-connect
22

#define Description
ENABLE GATT CLIENT PAIRING
Enable GATT Client to start pairing and retry
operation on security error
ENABLE MICRO ECC FORUseLE micro-ecc
SECURE library
CONNECTIONS
for ECC operations
ENABLE LE DATA LENGTH Enable
EXTENSION
LE Data Length Extension support
ENABLE LE ENHANCED CONNECTION
Enable LE Enhanced
COMPLETE
Connection
EVENTComplete
Event v1 & v2
ENABLE LE EXTENDED ADVERTISING
Enable extended advertising and scanning
ENABLE LE PERIODIC ADVERTISING
Enable periodic advertising and scanning
ENABLE LE SIGNED WRITEEnable LE Signed Writes in ATT/GATT
ENABLE LE PRIVACY ADDRESS
Enable RESOLUTION
address resolution for resolvable
private addresses in Controller
ENABLE CROSS TRANSPORTEnable
KEYCross-Transport
DERIVATIONKey Derivation
(CTKD) for Secure Connections
ENABLE L2CAP ENHANCED Enable
RETRANSMISSION
Enhanced Retransmission
MODE Mode for
L2CAP Channels. Mandatory for AVRCP
Browsing
ENABLE L2CAP LE CREDITEnable
BASEDLE FLOW
credit-based
CONTROL
flow-control
MODE mode for
L2CAP channels
ENABLE L2CAP ENHANCED Enable
CREDIT
Enhanced
BASEDcredit-based
FLOW CONTROL
flow-controlMODE
mode for L2CAP Channels
ENABLE HCI CONTROLLER Enable
TO HOST
HCI Controller
FLOW CONTROL
to Host Flow Control,
see below
ENABLE HCI SERIALIZED Serialize
CONTROLLER
Inquiry, OPERATIONS
Remote Name Request, and
Create Connection operations
ENABLE ATT DELAYED RESPONSE
Enable support for delayed ATT operations,
see GATT Server
ENABLE BCM PCM WBS Enable support for Wide-Band Speech codec
in BCM controller, requires
ENABLE SCO OVER PCM
ENABLE CC256X ASSISTEDEnable
HFP support for Assisted HFP mode in
CC256x Controller, requires
ENABLE SCO OVER PCM
ENABLE RTK PCM WBS Enable support for Wide-Band Speech codec
in Realtek controller, requires
ENABLE SCO OVER PCM
ENABLE CC256X BAUDRATEEnable
CHANGE
workaround
FLOWCONTROL
for bug in CC256x
BUG Flow
WORKAROUND
Control during baud rate change, see chipset
docs.
ENABLE CYPRESS BAUDRATE
EnableCHANGE
workaroundFLOWCONTROL
for bug in CYW2070x
BUG WORKAROUND
Flow Control during baud rate change, similar
to CC256x.
ENABLE LE LIMIT ACL FRAGMENT
Force HCI toBY fragment
MAX OCTETS
ACL-LE packets to fit
into over-the-air packet
23

#define Description
ENABLE TLV FLASH EXPLICIT
EnableDELETE
use of explicit
FIELD delete field in TLV Flash
implementation - required when flash value
cannot be overwritten with zero
ENABLE TLV FLASH WRITE
Enable
ONCEstoring of emtpy tag instead of
overwriting existing tag - required when flash
value cannot be overwritten at all
ENABLE CONTROLLER WARM
EnableBOOT
stack startup without power cycle (if
supported/possible)
ENABLE SEGGER RTT Use SEGGER RTT for console output and
packet log, see additional options
ENABLE EXPLICIT CONNECTABLE
Disable calls
MODE
to control
CONTROL
Connectable Mode by
L2CAP
ENABLE EXPLICIT IO CAPABILITIES
Let application
REPLY
trigger sending IO Capabilities
(Negative) Reply
ENABLE EXPLICIT LINK KEY
Let application
REPLY trigger sending Link Key
(Negative) Response, allows for asynchronous
link key lookup
ENABLE EXPLICIT BR EDR
Report
SECURITY
BR/EDR MANAGER
Security Manager support in
L2CAP Information Response
ENABLE EXPLICIT DEDICATED
Keep connection
BONDING after
DISCONNECT
dedicated bonding is
complete
ENABLE CLASSIC OOB PAIRING
Enable support for classic Out-of-Band (OOB)
pairing
ENABLE A2DP EXPLICIT CONFIG
Let application configure stream endpoint
(skip auto-config of SBC endpoint)
ENABLE AVDTP ACCEPTORallow
EXPLICIT
accept or START
reject ofSTREAM
stream start
CONFIRMATION
on
A2DP SUBEVENT START STREAM REQUESTED
ENABLE LE WHITELIST TOUCH
Enable Workaround
AFTER RESOLVINGfor Controller
LIST bug
UPDATE
ENABLE LE SET ADV PARAMS
Send HCI
ON LE
RANDOM
Set Advertising
ADDRESS Params
CHANGEafter
HCI LE Set Random Address - workaround for
Controller Bug
ENABLE CONTROLLER DUMP
DumpPACKETS
number of packets in Controller per
type for debugging
ENABLE HCI COMMAND STATUS
Track connection
DISCARDED handleFORfor HCI
FAILED
Commands
CONNECTIONS
WORKAROUND and assume command has failed if disonnect
event for connection is received
ENABLE MUTUAL AUTHENTICATION
Re-authentication
FORafter
LEGACY
connection
SECUREwas CONNECTIONS
encrypted to avoid BIAS Attack. Not needed
for min encryption key size of 16

Notes:
• ENABLE MICRO ECC FOR LE SECURE CONNECTIONS: Only some
Bluetooth 4.2+ controllers (e.g., EM9304, ESP32) support the necessary
HCI commands for ECC. Other reason to enable the ECC software im-
plementations are if the Host is much faster or if the micro-ecc library is
24

already provided (e.g., ESP32, WICED, or if the ECC HCI Commands


are unreliable.
0.8.3. HCI Controller to Host Flow Control. In general, BTstack relies on flow
control of the HCI transport, either via Hardware CTS/RTS flow control for
UART or regular USB flow control. If this is not possible, e.g on an SoC, BTstack
can use HCI Controller to Host Flow Control by defining ENABLE HCI CONTROLLER TO HOST
If enabled, the HCI Transport implementation must be able to buffer the spec-
ified packets. In addition, it also need to be able to buffer a few HCI Events.
Using a low number of host buffers might result in less throughput.
Host buffer configuration for HCI Controller to Host Flow Control:

#define Description
HCI HOST ACL PACKET NUM Max number of ACL packets
HCI HOST ACL PACKET LEN Max size of HCI Host ACL packets
HCI HOST SCO PACKET NUM Max number of ACL packets
HCI HOST SCO PACKET LEN Max size of HCI Host SCO packets

0.8.4. Memory configuration directives. The structs for services, active connec-
tions and remote devices can be allocated in two different manners:
• statically from an individual memory pool, whose maximal number of
elements is defined in the btstack config.h file. To initialize the static
pools, you need to call at runtime btstack memory init function. An
example of memory configuration for a single SPP service with a minimal
L2CAP MTU is shown in Listing {@lst:memoryConfigurationSPP}.
• dynamically using the malloc/free functions, if HAVE MALLOC is de-
fined in btstack config.h file.
For each HCI connection, a buffer of size HCI ACL PAYLOAD SIZE is re-
served. For fast data transfer, however, a large ACL buffer of 1021 bytes is
recommended. The large ACL buffer is required for 3-DH5 packets to be used.

#define Description
HCI ACL PAYLOAD SIZE Max size of HCI ACL payloads
HCI ACL CHUNK SIZE ALIGNMENT
Alignment of ACL chunk size, can be used to
align HCI transport writes
HCI INCOMING PRE BUFFER
Number
SIZE
of bytes reserved before actual data for
incoming HCI packets
MAX NR BNEP CHANNELS Max number of BNEP channels
MAX NR BNEP SERVICESMax number of BNEP services
MAX NR GATT CLIENTS Max number of GATT clients
MAX NR HCI CONNECTIONS
Max number of HCI connections
MAX NR HFP CONNECTIONS
Max number of HFP connections
MAX NR L2CAP CHANNELSMax number of L2CAP connections
MAX NR L2CAP SERVICESMax number of L2CAP services
MAX NR RFCOMM CHANNELS
Max number of RFOMMM connections
25

#define Description
MAX NR RFCOMM MULTIPLEXERS
Max number of RFCOMM multiplexers, with
one multiplexer per HCI connection
MAX NR RFCOMM SERVICES
Max number of RFCOMM services
MAX NR SERVICE RECORD
MaxITEMS
number of SDP service records
MAX NR SM LOOKUP ENTRIES
Max number of items in Security Manager
lookup queue
MAX NR WHITELIST ENTRIES
Max number of items in GAP LE Whitelist to
connect to

The memory is set up by calling btstack memory init function:

btstack memory init () ;

Here’s the memory configuration for a basic SPP server.

#define HCI ACL PAYLOAD SIZE 52


#define MAX NR HCI CONNECTIONS 1
#define MAX NR L2CAP SERVICES 2
#define MAX NR L2CAP CHANNELS 2
#define MAX NR RFCOMM MULTIPLEXERS 1
#define MAX NR RFCOMM SERVICES 1
#define MAX NR RFCOMM CHANNELS 1
#define NVM NUM LINK KEYS 3

Listing: Memory configuration for a basic SPP server. {#lst:memoryConfigurationSPP}


In this example, the size of ACL packets is limited to the minimum of 52 bytes,
resulting in an L2CAP MTU of 48 bytes. Only a singleHCI connection can be
established at any time. On it, two L2CAP services are provided, which can be
active at the same time. Here, these two can be RFCOMM and SDP. Then,
memory for one RFCOMM multiplexer is reserved over which one connection
can be active. Finally, up to three link keys can be stored in persistent memory.
0.8.5. Non-volatile memory (NVM) directives. If implemented, bonding infor-
mation is stored in Non-volatile memory. For Classic, a single link keys and its
type is stored. For LE, the bonding information contains various values (long
term key, random number, EDIV, signing counter, identity, . . . ) Often, this is
implemented using Flash memory. Then, the number of stored entries are limited
by:

#define Description
NVM NUM LINK Max
KEYSnumber of Classic Link Keys that can be stored
NVM NUM DEVICE
MaxDB
number
ENTRIES
of LE Device DB entries that can be stored
26

#define Description
NVN NUM GATTMax
SERVER
numberCCCof ‘Client Characteristic Configuration’
values that can be stored by GATT Server

0.8.6. HCI Dump Stdout directives. Allow to truncate HCI ACL and SCO pack-
ets to reduce console output for debugging audio applications.

#define Description
HCI DUMP STDOUT MAX SIZE ACL Max size of ACL packets to log via stdout
HCI DUMP STDOUT MAX SIZE SCO Max size of SCO packets to log via stdout
HCI DUMP STDOUT MAX SIZE ISO Max size of ISO packets to log via stdout

0.8.7. SEGGER Real Time Transfer (RTT) directives. SEGGER RTT improves
on the use of an UART for debugging with higher throughput and less overhead.
In addition, it allows for direct logging in PacketLogger/BlueZ format via the
provided JLinkRTTLogger tool.
When enabled with ENABLE SEGGER RTT and hci dump init() can be called with
an hci dunp segger stdout get instance () for textual output and hci dump segger binary get instance
() for binary output. With the latter, you can select HCI DUMP BLUEZ or HCI DUMP PACKETLOGGER
, format. For RTT, the following directives are used to configure the up channel:

#define Default Description


SEGGER RTT SEGGER
PACKETLOG
RTTSEGGER
MODE NO RTTBLOCK
MODESKIPNO BLOCK SKIP to
skip messages if buffer is full, or, SEG-
GER RTT MODE BLOCK IF FIFO FULL
to block
SEGGER RTT 1PACKETLOGChannel
CHANNEL to use for packet log. Channel 0 is
used for terminal
SEGGER RTT 1024
PACKETLOGSize
BUFFER
of outgoing
SIZEring buffer. Increase if you
cannot block but get ‘message skipped’
warnings.

0.9. Run-time configuration. To allow code-reuse with different platforms as


well as with new ports, the low-level initialization of BTstack and the hardware
configuration has been extracted to the various platforms/PLATFORM/main.c
files. The examples only contain the platform-independent Bluetooth logic. But
let’s have a look at the common init code.
Listing below shows a minimal platform setup for an embedded system with
a Bluetooth chipset connected via UART.

int main ( ) {
// . . . hardware i n i t : watchdoch , IOs , t i m e r s , e t c . . .

// s e t u p BTstack memory p o o l s
27

btstack memory init () ;

// s e l e c t embedded run l o o p
btstack run loop init ( btstack run loop embedded get instance () ) ;

// e n a b l e l o g g i n g
hci dump init ( hci dump embedded stdout get instance () ) ;

// i n i t HCI
hci transport t ∗ transport = hci transport h4 instance () ;
h c i i n i t ( t r a n s p o r t , NULL) ;

// s e t u p example
b t s t a c k m a i n ( argc , argv ) ;

// go
btstack run loop execute () ;
}

First, BTstack’s memory pools are set up. Then, the standard run loop im-
plementation for embedded systems is selected.
The call to hci dump init configures BTstack to output all Bluetooth packets
and its own debug and error message using printf with BTstack’s millisecond
tiomestamps.s as tim. The Python script tools/create packet log.py can be used
to convert the console output into a Bluetooth PacketLogger format that can
be opened by the OS X PacketLogger tool as well as by Wireshark for further
inspection. When asking for help, please always include a log created with HCI
dump.
The hci init function sets up HCI to use the HCI H4 Transport implementa-
tion. It doesn’t provide a special transport configuration nor a special implemen-
tation for a particular Bluetooth chipset. It makes use of the remote device db memory
implementation that allows for re-connects without a new pairing but doesn’t
persist the bonding information.
Finally, it calls btstack main() of the actual example before executing the run
loop.
0.10. Source tree structure. The source tree has been organized to easily
setup new projects.

Path Description
chipset Support for individual Bluetooth Controller chipsets
doc Sources for BTstack documentation
example Example applications available for all ports
platform Support for special OSs and/or MCU architectures
port Complete port for a MCU + Chipset combinations
src Bluetooth stack implementation
test Unit and PTS tests
tool Helper tools for BTstack
28

The core of BTstack, including all protocol and profiles, is in src/.


Support for a particular platform is provided by the platform/ subfolder. For
most embedded ports, platform/embedded/ provides btstack run loop embedded
and the hci transport h4 embedded implementation that require hal cpu.h, hal led.h,
and hal uart dma.h plus hal tick.h or hal time ms to be implemented by the user.
To accommodate a particular Bluetooth chipset, the chipset/ subfolders pro-
vide various btstack chipset * implementations. Please have a look at the exist-
ing ports in port/.

0.11. Run loop configuration. To initialize BTstack you need to initialize the
memory and the run loop respectively, then setup HCI and all needed higher level
protocols.
BTstack uses the concept of a run loop to handle incoming data and to schedule
work. The run loop handles events from two different types of sources: data
sources and timers. Data sources represent communication interfaces like an
UART or an USB driver. Timers are used by BTstack to implement various
Bluetooth-related timeouts. They can also be used to handle periodic events. In
addition, most implementations also allow to trigger a poll of the data sources
from interrupt context, or, execute a function from a different thread.
Data sources and timers are represented by the btstack data source t and bt-
stack timer source t structs respectively. Each of these structs contain at least
a linked list node and a pointer to a callback function. All active timers and
data sources are kept in link lists. While the list of data sources is unsorted, the
timers are sorted by expiration timeout for efficient processing. Data sources
need to be configured upon what event they are called back. They can be
configured to be polled (DATA SOURCE CALLBACK POLL), on read ready
(DATA SOURCE CALLBACK READ), or on write ready (DATA SOURCE CALLBACK WRITE
Timers are single shot: a timer will be removed from the timer list before
its event handler callback is executed. If you need a periodic timer, you can
re-register the same timer source in the callback function, as shown in Listing
[PeriodicTimerHandler]. Note that BTstack expects to get called periodically
to keep its time, see Section on time abstraction for more on the tick hardware
abstraction.
BTstack provides different run loop implementations that implement the bt-
stack run loop t interface:
• CoreFoundation: implementation for iOS and OS X applications
• Embedded: the main implementation for embedded systems, especially
without an RTOS.
• FreeRTOS: implementation to run BTstack on a dedicated FreeRTOS
thread
• POSIX: implementation for POSIX systems based on the select() call.
• Qt: implementation for the Qt applications
• WICED: implementation for the Broadcom WICED SDK RTOS abstrac-
tion that wraps FreeRTOS or ThreadX.
• Windows: implementation for Windows based on Event objects and
WaitForMultipleObjects() call.
29

Depending on the platform, data sources are either polled (embedded, FreeR-
TOS), or the platform provides a way to wait for a data source to become ready
for read or write (CoreFoundation, POSIX, Qt, Windows), or, are not used as
the HCI transport driver and the run loop is implemented in a different way
(WICED). In any case, the callbacks must be explicitly enabled with the bt-
stack run loop enable data source callbacks(..) function.
In your code, you’ll have to configure the run loop before you start it as shown
in Listing [listing:btstackInit]. The application can register data sources as well
as timers, e.g., for periodical sampling of sensors, or for communication over the
UART.
The run loop is set up by calling btstack run loop init function and providing
an instance of the actual run loop. E.g. for the embedded platform, it is:

btstack run loop init ( btstack run loop embedded get instance () ) ;

If the run loop allows to trigger polling of data sources from interrupt context,
btstack run loop poll data sources from irq.
On multi-threaded environments, e.g., FreeRTOS, POSIX, WINDOWS, bt-
stack run loop execute code on main thread can be used to schedule a callback
on the main loop.
The complete Run loop API is provided here.
0.11.1. Run Loop Embedded. In the embedded run loop implementation, data
sources are constantly polled and the system is put to sleep if no IRQ happens
during the poll of all data sources.
The complete run loop cycle looks like this: first, the callback function of
all registered data sources are called in a round robin way. Then, the callback
functions of timers that are ready are executed. Finally, it will be checked if
another run loop iteration has been requested by an interrupt handler. If not,
the run loop will put the MCU into sleep mode.
Incoming data over the UART, USB, or timer ticks will generate an interrupt
and wake up the microcontroller. In order to avoid the situation where a data
source becomes ready just before the run loop enters sleep mode, an interrupt-
driven data source has to call the btstack run loop poll data sources from irq func-
tion. The call to btstack run loop poll data sources from irq sets an internal flag
that is checked in the critical section just before entering sleep mode causing
another run loop cycle.
To enable the use of timers, make sure that you defined HAVE EMBEDDED TICK
or HAVE EMBEDDED TIME MS in the config file.
While there is no threading, btstack run loop poll data sources from irq allows
to reduce stack size by scheduling a continuation.
0.11.2. Run Loop FreeRTOS. The FreeRTOS run loop is used on a dedicated
FreeRTOS thread and it uses a FreeRTOS queue to schedule callbacks on the
run loop. In each iteration:
• all data sources are polled
• all scheduled callbacks are executed
30

• all expired timers are called


• finally, it gets the next timeout. It then waits for a ‘trigger’ or the next
timeout, if set.
It supports both btstack run loop poll data sources from irq as well as btstack run loop execute cod
0.11.3. Run Loop POSIX. The data sources are standard File Descriptors. In the
run loop execute implementation, select() call is used to wait for file descriptors
to become ready to read or write, while waiting for the next timeout.
To enable the use of timers, make sure that you defined HAVE POSIX TIME
in the config file.
It supports both btstack run loop poll data sources from irq as well as btstack run loop execute cod
0.11.4. Run loop CoreFoundation (OS X/iOS). This run loop directly maps BT-
stack’s data source and timer source with CoreFoundation objects. It supports
ready to read and write similar to the POSIX implementation. The call to bt-
stack run loop execute() then just calls CFRunLoopRun().
To enable the use of timers, make sure that you defined HAVE POSIX TIME
in the config file.
It currently only supports btstack run loop execute code on main thread.
0.11.5. Run Lop Qt. This run loop directly maps BTstack’s data source and
timer source with Qt Core objects. It supports ready to read and write similar
to the POSIX implementation.
To enable the use of timers, make sure that you defined HAVE POSIX TIME
in the config file.
It supports both btstack run loop poll data sources from irq as well as btstack run loop execute cod
0.11.6. Run loop Windows. The data sources are Event objects. In the run loop
implementation WaitForMultipleObjects() call is all is used to wait for the Event
object to become ready while waiting for the next timeout.
It supports both btstack run loop poll data sources from irq as well as btstack run loop execute cod
0.11.7. Run loop WICED. WICED SDK API does not provide asynchronous
read and write to the UART and no direct way to wait for one or more peripher-
als to become ready. Therefore, BTstack does not provide direct support for data
sources. Instead, the run loop provides a message queue that allows to schedule
functions calls on its thread via btstack run loop wiced execute code on main thread().
The HCI transport H4 implementation then uses two lightweight threads to
do the blocking read and write operations. When a read or write is complete on
the helper threads, a callback to BTstack is scheduled.
It currently only supports btstack run loop execute code on main thread.
0.12. HCI Transport configuration. The HCI initialization has to adapt BT-
stack to the used platform. The first call is to hci init() and requires information
about the HCI Transport to use. The arguments are:
• HCI Transport implementation: On embedded systems, a Bluetooth mod-
ule can be connected via USB or an UART port. On embedded, BTstack
implements HCI UART Transport Layer (H4) and H4 with eHCILL sup-
port, a lightweight low-power variant by Texas Instruments. For POSIX,
31

there is an implementation for HCI H4, HCI H5 and H2 libUSB, and for
WICED HCI H4 WICED. These are accessed by linking the appropriate
file, e.g., platform/embedded/hci\_transport\_h4\_embedded.c and
then getting a pointer to HCI Transport implementation. For more in-
formation on adapting HCI Transport to different environments, see here.

hci transport t ∗ t r a n s p o r t = h c i t r a n s p o r t h 4 i n s t a n c e ( ) ;

• HCI Transport configuration: As the configuration of the UART used in


the H4 transport interface are not standardized, it has to be provided by
the main application to BTstack. In addition to the initial UART baud
rate, the main baud rate can be specified. The HCI layer of BTstack will
change the init baud rate to the main one after the basic setup of the
Bluetooth module. A baud rate change has to be done in a coordinated
way at both HCI and hardware level. For example, on the CC256x, the
HCI command to change the baud rate is sent first, then it is necessary
to wait for the confirmation event from the Bluetooth module. Only now,
can the UART baud rate changed.

h c i u a r t c o n f i g t ∗ c o n f i g = &h c i u a r t c o n f i g ;

After these are ready, HCI is initialized like this:

h c i i n i t ( transport , config ) ;

In addition to these, most UART-based Bluetooth chipset require some special


logic for correct initialization that is not covered by the Bluetooth specification.
In particular, this covers:
• setting the baudrate
• setting the BD ADDR for devices without an internal persistent storage
• upload of some firmware patches.
This is provided by the various btstack chipset t implementation in the chipset/
subfolders. As an example, the bstack chipset cc256x instance function returns
a pointer to a chipset struct suitable for the CC256x chipset.

btstack chipset t ∗ chipset = btstack chipset cc256x instance () ;


hci set chipset ( chipset ) ;

In some setups, the hardware setup provides explicit control of Bluetooth


power and sleep modes. In this case, a btstack control t struct can be set with
hci set control.
32

Finally, the HCI implementation requires some form of persistent storage for
link keys generated during either legacy pairing or the Secure Simple Pairing
(SSP). This commonly requires platform specific code to access the MCU’s EEP-
ROM of Flash storage. For the first steps, BTstack provides a (non) persistent
store in memory. For more see here.

btstack link key db t ∗ l i n k k e y d b = &


btstack link key db memory instance () ;
btstack set link key db ( link key db ) ;

The higher layers only rely on BTstack and are initialized by calling the re-
spective ** init* function. These init functions register themselves with the
underlying layer. In addition, the application can register packet handlers to get
events and data as explained in the following section.
0.13. Services. One important construct of BTstack is service. A service rep-
resents a server side component that handles incoming connections. So far,
BTstack provides L2CAP, BNEP, and RFCOMM services. An L2CAP service
handles incoming connections for an L2CAP channel and is registered with its
protocol service multiplexer ID (PSM). Similarly, an RFCOMM service handles
incoming RFCOMM connections and is registered with the RFCOMM channel
ID. Outgoing connections require no special registration, they are created by the
application when needed.
0.14. Packet handlers configuration. After the hardware and BTstack are
set up, the run loop is entered. From now on everything is event driven. The
application calls BTstack functions, which in turn may send commands to the
Bluetooth module. The resulting events are delivered back to the application.
Instead of writing a single callback handler for each possible event (as it is done
in some other Bluetooth stacks), BTstack groups events logically and provides
them over a single generic interface. Appendix Events and Errors summarizes
the parameters and event codes of L2CAP and RFCOMM events, as well as
possible errors and the corresponding error codes.
Here is summarized list of packet handlers that an application might use:
• HCI event handler - allows to observer HCI, GAP, and general BTstack
events.
• L2CAP packet handler - handles LE Connection parameter requeset up-
dates
• L2CAP service packet handler - handles incoming L2CAP connections,
i.e., channels initiated by the remote.
• L2CAP channel packet handler - handles outgoing L2CAP connections,
i.e., channels initiated internally.
• RFCOMM service packet handler - handles incoming RFCOMM connec-
tions, i.e., channels initiated by the remote.
• RFCOMM channel packet handler - handles outgoing RFCOMM connec-
tions, i.e., channels initiated internally.
These handlers are registered with the functions listed in Table below.
33

Packet Handler Registering Function


HCI packet handler hci add event handler
L2CAP packet l2cap register packet handler
handler
L2CAP service packet l2cap register service
handler
L2CAP channel l2cap create channel
packet handler
RFCOMM service rfcomm register service and
packet handler rfcomm register service with initial credits
RFCOMM channel rfcomm create channel and
packet handler rfcomm create channel with initial credits

Table: Functions for registering packet handlers.


HCI, GAP, and general BTstack events are delivered to the packet handler
specified by hci add event handler function. In L2CAP, BTstack discriminates
incoming and outgoing connections, i.e., event and data packets are delivered to
different packet handlers. Outgoing connections are used access remote services,
incoming connections are used to provide services. For incoming connections,
the packet handler specified by l2cap register service is used. For outgoing con-
nections, the handler provided by l2cap create channel is used. RFCOMM and
BNEP are similar.
The application can register a single shared packet handler for all protocols
and services, or use separate packet handlers for each protocol layer and service.
A shared packet handler is often used for stack initialization and connection
management.
Separate packet handlers can be used for each L2CAP service and outgoing
connection. For example, to connect with a Bluetooth HID keyboard, your
application could use three packet handlers: one to handle HCI events during
discovery of a keyboard registered by l2cap register packet handler ; one that will
be registered to an outgoing L2CAP channel to connect to keyboard and to
receive keyboard data registered by l2cap create channel ; after that keyboard
can reconnect by itself. For this, you need to register L2CAP services for the
HID Control and HID Interrupt PSMs using l2cap register service. In this call,
you’ll also specify a packet handler to accept and receive keyboard data.
All events names have the form MODULE EVENT NAME now, e.g., gap event -
advertising report. To facilitate working with events and get rid of manually
calculating offsets into packets, BTstack provides auto-generated getters for all
fields of all events in src/hci event.h. All functions are defined as static inline,
so they are not wasting any program memory if not used. If used, the mem-
ory footprint should be identical to accessing the field directly via offsets into
the packet. For example, to access fields address type and address from the
gap event advertising report event use following getters:
34

uint8 t a d d r e s s type = g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s t y p e
( event ) ;
bd addr t a d d r e s s ;
g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s ( event , a d d r e s s ) ;

0.15. Bluetooth HCI Packet Logs. If things don’t work as expected, having
a look at the data exchanged between BTstack and the Bluetooth chipset often
helps.
For this, BTstack provides a configurable packet logging mechanism via hci dump.h
and the following implementations:

void h c i d u m p i n i t ( const h c i d u m p t ∗ h c i d u m p i m p l e m e n t a t i o n ) ;

Platform File Description


POSIX hci dump posix fs.c HCI log file for Apple PacketLogger and
Wireshark
POSIX hci dump posix stdout.c Console output via printf
Embeddedhci dump embedded stdout Console output via printf
.c
Embeddedhci dump segger stdout.c Console output via SEGGER RTT
Embeddedhci dump segger binary.c HCI log file for Apple PacketLogger via
SEGGER RTT

On POSIX systems, you can call hci dump init with a hci dump posix fs get instance()
and configure the path and output format with hci dump posix fs open(const
char path, hci dump format t format) where format can be HCI DUMP BLUEZ*
or HCI DUMP PACKETLOGGER. The resulting file can be analyzed with Wire-
shark or the Apple’s PacketLogger tool.
On embedded systems without a file system, you either log to an UART console
via printf or use SEGGER RTT. For printf output you pass hci dump embedded stdout get instance()
to hci dump init(). With RTT, you can choose between textual output sim-
ilar to printf, and binary output. For textual output, you can provide the
hci dump segger stdout get instance().
It will log all HCI packets to the UART console via printf or RTT Terminal.
If you capture the console output, incl. your own debug messages, you can use
the create packet log.py tool in the tools folder to convert a text output into a
PacketLogger file.
For less overhead and higher logging speed, you can directly log in binary
format by passing hci dump segger rtt binary get instance() and selecting the
output format by calling hci dump segger rtt binary open(hci dump format t for-
mat) with the same format as above.
In addition to the HCI packets, you can also enable BTstack’s debug informa-
tion by adding
35

#define ENABLE LOG INFO


#define ENABLE LOG ERROR

to the btstack config.h and recompiling your application.

0.16. Bluetooth Power Control. In most BTstack examples, the device is


set to be discoverable and connectable. In this mode, even when there’s no
active connection, the Bluetooth Controller will periodically activate its receiver
in order to listen for inquiries or connecting requests from another device. The
ability to be discoverable requires more energy than the ability to be connected.
Being discoverable also announces the device to anybody in the area. Therefore,
it is a good idea to pause listening for inquiries when not needed. Other devices
that have your Bluetooth address can still connect to your device.
To enable/disable discoverability, you can call:

/∗ ∗
∗ @ b r i e f A l l o w s t o c o n t r o l i f d e v i c e i s d i s c o v e r a b l e . OFF by
default .
∗/
void g a p d i s c o v e r a b l e c o n t r o l ( uint8 t e n a b l e ) ;

If you don’t need to become connected from other devices for a longer period
of time, you can also disable the listening to connection requests.
To enable/disable connectability, you can call:

/∗ ∗
∗ @ b r i e f O v e r r i d e page scan mode . Page scan mode e n a b l e d by l 2 c a p
when s e r v i c e s a r e r e g i s t e r e d
∗ @note Might be used t o r e d u c e power consumption w h i l e B l u e t o o t h
module s t a y s powered b u t no ( new )
∗ connections are expected
∗/
void g a p c o n n e c t a b l e c o n t r o l ( uint8 t e n a b l e ) ;

For Bluetooth Low Energy, the radio is periodically used to broadcast adver-
tisements that are used for both discovery and connection establishment.
To enable/disable advertisements, you can call:

/∗ ∗
∗ @ b r i e f Enable / D i s a b l e A d v e r t i s e m e n t s . OFF by d e f a u l t .
∗ @param e n a b l e d
∗/
void g a p a d v e r t i s e m e n t s e n a b l e ( int e n a b l e d ) ;

If a Bluetooth Controller is neither discoverable nor connectable, it does not


need to periodically turn on its radio and it only needs to respond to commands
36

from the Host. In this case, the Bluetooth Controller is free to enter some kind
of deep sleep where the power consumption is minimal.
Finally, if that’s not sufficient for your application, you could request BTstack
to shutdown the Bluetooth Controller. For this, the “on” and “off” functions in
the btstack control t struct must be implemented. To shutdown the Bluetooth
Controller, you can call:

/∗ ∗
∗ @ b r i e f R e q u e s t s t h e change o f BTstack power mode .
∗/
int h c i p o w e r c o n t r o l (HCI POWER MODE mode ) ;

with mode set to HCI POWER OFF. When needed later, Bluetooth can be
started again via by calling it with mode HCI POWER ON, as seen in all exam-
ples.
#Protocols
BTstack is a modular dual-mode Bluetooth stack, supporting both Bluetooth
Basic Rate/Enhanced Date Rate (BR/EDR) as well as Bluetooth Low Energy
(LE). The BR/EDR technology, also known as Classic Bluetooth, provides a
robust wireless connection between devices designed for high data rates. In
contrast, the LE technology has a lower throughput but also lower energy con-
sumption, faster connection setup, and the ability to connect to more devices in
parallel.
Whether Classic or LE, a Bluetooth device implements one or more Bluetooth
profiles. A Bluetooth profile specifies how one or more Bluetooth protocols are
used to achieve its goals. For example, every Bluetooth device must implement
the Generic Access Profile (GAP), which defines how devices find each other
and how they establish a connection. This profile mainly make use of the Host
Controller Interface (HCI) protocol, the lowest protocol in the stack hierarchy
which implements a command interface to the Bluetooth chipset.
In addition to GAP, a popular Classic Bluetooth example would be a peripheral
devices that can be connected via the Serial Port Profile (SPP). SPP basically
specifies that a compatible device should provide a Service Discovery Protocol
(SDP) record containing an RFCOMM channel number, which will be used for
the actual communication.
Similarly, for every LE device, the Generic Attribute Profile (GATT) profile
must be implemented in addition to GAP. GATT is built on top of the Attribute
Protocol (ATT), and defines how one device can interact with GATT Services
on a remote device.
So far, the most popular use of BTstack is in peripheral devices that can be
connected via SPP (Android 2.0 or higher) and GATT (Android 4.3 or higher,
and iOS 5 or higher). If higher data rates are required between a peripheral and
iOS device, the iAP1 and iAP2 protocols of the Made for iPhone program can
be used instead of GATT. Please contact us directly for information on BTstack
and MFi.
37

PROFILES MFi
GATT SPP HSP HFP PBAP SDAP PAN A2DP AVRCP HID GAP MESH
iARP2

PROTOCOLS

SMP ATT RFCOMM SDP BNEP AVDTP AVCTP

L2CAP LE L2CAP

HCI

TRANSPORT H4 UART H5 UART eHCILL UART H2 USB


Bluetooth Single/Dual Mode Controller

Architecture of a BTstack-based application.

Figure below depicts Bluetooth protocols and profiles that are currently imple-
mented by BTstack. In the following, we first explain how the various Bluetooth
protocols are used in BTstack. In the next chapter, we go over the profiles.
0.17. HCI - Host Controller Interface. The HCI protocol provides a com-
mand interface to the Bluetooth chipset. In BTstack, the HCI implementation
also keeps track of all active connections and handles the fragmentation and
re-assembly of higher layer (L2CAP) packets.
Please note, that an application rarely has to send HCI commands on its own.
Instead, BTstack provides convenience functions in GAP and higher level proto-
cols that use HCI automatically. E.g. to set the name, you call gap set local name()
before powering up. The main use of HCI commands in application is during the
startup phase to configure special features that are not available via the GAP
API yet. How to send a custom HCI command is explained in the following
section.
0.17.1. Defining custom HCI command templates. Each HCI command is as-
signed a 2-byte OpCode used to uniquely identify different types of commands.
The OpCode parameter is divided into two fields, called the OpCode Group Field
(OGF) and OpCode Command Field (OCF), see Bluetooth Specification - Core
Version 4.0, Volume 2, Part E, Chapter 5.4.
Listing below shows the OGFs provided by BTstack in file src/hci.h:

#define OGF LINK CONTROL 0 x01


#define OGF LINK POLICY 0 x02
#define OGF CONTROLLER BASEBAND 0 x03
#define OGF INFORMATIONAL PARAMETERS 0 x04
#define OGF LE CONTROLLER 0 x08
#define OGF BTSTACK 0 x3d
#define OGF VENDOR 0 x 3 f

For all existing Bluetooth commands and their OCFs see Bluetooth Specifica-
tion - Core Version 4.0, Volume 2, Part E, Chapter 7.
In a HCI command packet, the OpCode is followed by parameter total length,
and the actual parameters. The OpCode of a command can be calculated using
38

the OPCODE macro. BTstack provides the hci cmd t struct as a compact format
to define HCI command packets, see Listing below, and src/hci cmd.h file in the
source code.

// C a l c u l a t e combined o g f / o c f v a l u e .
#define OPCODE( ogf , o c f ) ( o c f | o g f << 1 0 )

// Compact HCI Command p a c k e t d e s c r i p t i o n .


typedef struct {
uint16 t opcode ;
const char ∗ format ;
} hci cmd t ;

Listing below illustrates the hci write local name HCI command template from
library:

// S e t s l o c a l B l u e t o o t h name
const hci cmd t h c i w r i t e l o c a l n a m e = {
OPCODE(OGF CONTROLLER BASEBAND, 0 x13 ) , ”N”
// L o c a l name (UTF−8, N u l l Terminated , max 248 o c t e t s )
};

It uses OGF CONTROLLER BASEBAND as OGF, 0x13 as OCF, and has


one parameter with format “N” indicating a null terminated UTF-8 string. Ta-
ble below lists the format specifiers supported by BTstack. Check for other
predefined HCI commands and info on their parameters.

Format Specifier Description


1,2,3,4 one to four byte value
A 31 bytes advertising data
B Bluetooth Baseband Address
D 8 byte data block
E Extended Inquiry Information 240 octets
H HCI connection handle
N Name up to 248 chars, UTF8 string, null terminated
P 16 byte Pairing code, e.g. PIN code or link key
S Service Record (Data Element Sequence)

Table: Supported Format Specifiers of HCI Command Parameter.


0.17.2. Sending HCI command based on a template. You can use the hci send cmd
function to send HCI command based on a template and a list of parameters.
However, it is necessary to check that the outgoing packet buffer is empty and
that the Bluetooth module is ready to receive the next command - most modern
Bluetooth modules only allow to send a single HCI command. This can be done
by calling hci can send command packet now() function, which returns true, if
it is ok to send.
39

Listing below illustrates how to manually set the device name with the HCI
Write Local Name command.

i f ( hci can send command packet now ( ) ) {


h c i s e n d c m d (& h c i w r i t e l o c a l n a m e , ” BTstack Demo” ) ;
}

Please note, that an application rarely has to send HCI commands on its
own. Instead, BTstack provides convenience functions in GAP and higher level
protocols that use HCI automatically.

0.18. L2CAP - Logical Link Control and Adaptation Protocol. The


L2CAP protocol supports higher level protocol multiplexing and packet frag-
mentation. It provides the base for the RFCOMM and BNEP protocols. For all
profiles that are officially supported by BTstack, L2CAP does not need to be
used directly. For testing or the development of custom protocols, it’s helpful to
be able to access and provide L2CAP services however.

0.18.1. Access an L2CAP service on a remote device. L2CAP is based around


the concept of channels. A channel is a logical connection on top of a baseband
connection. Each channel is bound to a single protocol in a many-to-one fashion.
Multiple channels can be bound to the same protocol, but a channel cannot be
bound to multiple protocols. Multiple channels can share the same baseband
connection.
To communicate with an L2CAP service on a remote device, the application on
a local Bluetooth device initiates the L2CAP layer using the l2cap init function,
and then creates an outgoing L2CAP channel to the PSM of a remote device
using the l2cap create channel function. The l2cap create channel function will
initiate a new baseband connection if it does not already exist. The packet han-
dler that is given as an input parameter of the L2CAP create channel function
will be assigned to the new outgoing L2CAP channel. This handler receives the
L2CAP EVENT CHANNEL OPENED and L2CAP EVENT CHANNEL CLOSED
events and L2CAP data packets, as shown in Listing below.

btstack packet handler t l 2 c a p p a c k e t h a n d l e r ;

void l 2 c a p p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
bd addr t e v e n t a d d r ;
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case L2CAP EVENT CHANNEL OPENED:
l 2 c a p e v e n t c h a n n e l o p e n e d g e t a d d r e s s ( packet , &
event addr ) ;
psm = l2cap event channel opened get psm (
packet ) ;
40

local cid =
l2cap event channel opened get local cid (
packet ) ;
handle =
l2cap event channel opened get handle ( packet
);
i f ( l 2 c a p e v e n t c h a n n e l o p e n e d g e t s t a t u s ( packet
)) {
p r i n t f ( ” Connection f a i l e d \n\ r ” ) ;
} else
p r i n t f ( ” Connected \n\ r ” ) ;
}
break ;
case L2CAP EVENT CHANNEL CLOSED :
break ;
...
}
case L2CAP DATA PACKET:
// h a n d l e L2CAP d a t a p a c k e t
break ;
...
}
}

void c r e a t e o u t g o i n g l 2 c a p c h a n n e l ( bd addr t a d d r e s s , uint16 t psm ,


uint16 t mtu ) {
l 2 c a p c r e a t e c h a n n e l (NULL, l 2 c a p p a c k e t h a n d l e r , remote bd addr
, psm , mtu ) ;
}

void b t s t a c k s e t u p ( ) {
...
l2cap init () ;
}

0.18.2. Provide an L2CAP service. To provide an L2CAP service, the applica-


tion on a local Bluetooth device must init the L2CAP layer and register the ser-
vice with l2cap register service. From there on, it can wait for incoming L2CAP
connections. The application can accept or deny an incoming connection by
calling the l2cap accept connection and l2cap deny connection functions respec-
tively.
If a connection is accepted and the incoming L2CAP channel gets successfully
opened, the L2CAP service can send and receive L2CAP data packets to the
connected device with l2cap send.
Listing below provides L2CAP service example code.

void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel , uint8 t


∗ packet , uint16 t s i z e ) {
bd addr t e v e n t a d d r ;
switch ( p a c k e t t y p e ) {
41

case HCI EVENT PACKET :


switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case L2CAP EVENT INCOMING CONNECTION :
local cid =
l2cap event incoming connection get local cid
( packet ) ;
l2cap accept connection ( local cid ) ;
break ;
case L2CAP EVENT CHANNEL OPENED:
l 2 c a p e v e n t c h a n n e l o p e n e d g e t a d d r e s s ( packet , &
event addr ) ;
psm = l2cap event channel opened get psm (
packet ) ;
local cid =
l2cap event channel opened get local cid (
packet ) ;
handle =
l2cap event channel opened get handle ( packet
);
i f ( l 2 c a p e v e n t c h a n n e l o p e n e d g e t s t a t u s ( packet
)) {
p r i n t f ( ” Connection f a i l e d \n\ r ” ) ;
} else
p r i n t f ( ” Connected \n\ r ” ) ;
}
break ;
case L2CAP EVENT CHANNEL CLOSED :
break ;
...
}
case L2CAP DATA PACKET:
// h a n d l e L2CAP d a t a p a c k e t
break ;
...
}
}

void b t s t a c k s e t u p ( ) {
...
l2cap init () ;
l 2 c a p r e g i s t e r s e r v i c e (NULL, p a c k e t h a n d l e r , 0 x11 , 1 0 0 ) ;
}

0.18.3. Sending L2CAP Data. Sending of L2CAP data packets may fail due to
a full internal BTstack outgoing packet buffer, or if the ACL buffers in the
Bluetooth module become full, i.e., if the application is sending faster than the
packets can be transferred over the air.
Instead of directly calling l2cap send, it is recommended to call l2cap request can send now event(c
which will trigger an L2CAP EVENT CAN SEND NOW as soon as possible. It
might happen that the event is received via packet handler before the l2cap request can send now eve
function returns. The L2CAP EVENT CAN SEND NOW indicates a channel
ID on which sending is possible.
42

Please note that the guarantee that a packet can be sent is only valid when
the event is received. After returning from the packet handler, BTstack might
need to send itself.

0.18.4. LE Data Channels. The full title for LE Data Channels is actually LE
Connection-Oriented Channels with LE Credit-Based Flow-Control Mode. In
this mode, data is sent as Service Data Units (SDUs) that can be larger than an
individual HCI LE ACL packet.
LE Data Channels are similar to Classic L2CAP Channels but also provide a
credit-based flow control similar to RFCOMM Channels. Unless the LE Data
Packet Extension of Bluetooth Core 4.2 specification is used, the maximum
packet size for LE ACL packets is 27 bytes. In order to send larger packets,
each packet will be split into multiple ACL LE packets and recombined on the
receiving side.
Since multiple SDUs can be transmitted at the same time and the individual
ACL LE packets can be sent interleaved, BTstack requires a dedicated receive
buffer per channel that has to be passed when creating the channel or accepting
it. Similarly, when sending SDUs, the data provided to the l2cap cbm send data
must stay valid until the L2CAP EVENT LE PACKET SENT is received.
When creating an outgoing connection of accepting an incoming, the ini-
tial credits allows to provide a fixed number of credits to the remote side. Further
credits can be provided anytime with l2cap cbm provide credits. If L2CAP LE AUTOMATIC CRED
is used, BTstack automatically provides credits as needed - effectively trading in
the flow-control functionality for convenience.
The remainder of the API is similar to the one of L2CAP:
• l2cap cbm register service and l2cap cbm unregister service are used to
manage local services.
• l2cap cbm accept connection and l2cap cbm decline connection are used
to accept or deny an incoming connection request.
• l2cap cbm create channel creates an outgoing connections.
• l2cap cbm can send now checks if a packet can be scheduled for trans-
mission now.
• l2cap cbm request can send now event requests an L2CAP EVENT LE CAN SEND NOW
event as soon as possible.
• l2cap cbm disconnect closes the connection.

0.19. RFCOMM - Radio Frequency Communication Protocol. The Ra-


dio frequency communication (RFCOMM) protocol provides emulation of serial
ports over the L2CAP protocol and reassembly. It is the base for the Serial
Port Profile and other profiles used for telecommunication like Head-Set Profile,
Hands-Free Profile, Object Exchange (OBEX) etc.

0.19.1. No RFCOMM packet boundaries. As RFCOMM emulates a serial port,


it does not preserve packet boundaries.
On most operating systems, RFCOMM/SPP will be modeled as a pipe that
allows to write a block of bytes. The OS and the Bluetooth Stack are free to
buffer and chunk this data in any way it seems fit. In your BTstack application,
43

you will therefore receive this data in the same order, but there are no guarantees
as how it might be fragmented into multiple chunks.
If you need to preserve the concept of sending a packet with a specific size
over RFCOMM, the simplest way is to prefix the data with a 2 or 4 byte length
field and then reconstruct the packet on the receiving side.
Please note, that due to BTstack’s ‘no buffers’ policy, BTstack will send outgo-
ing RFCOMM data immediately and implicitly preserve the packet boundaries,
i.e., it will send the data as a single RFCOMM packet in a single L2CAP packet,
which will arrive in one piece. While this will hold between two BTstack in-
stances, it’s not a good idea to rely on implementation details and rather prefix
the data as described.

0.19.2. RFCOMM flow control. RFCOMM has a mandatory credit-based flow-


control. This means that two devices that established RFCOMM connection,
use credits to keep track of how many more RFCOMM data packets can be
sent to each. If a device has no (outgoing) credits left, it cannot send another
RFCOMM packet, the transmission must be paused. During the connection
establishment, initial credits are provided. BTstack tracks the number of credits
in both directions. If no outgoing credits are available, the RFCOMM send
function will return an error, and you can try later. For incoming data, BTstack
provides channels and services with and without automatic credit management
via different functions to create/register them respectively. If the management of
credits is automatic, the new credits are provided when needed relying on ACL
flow control - this is only useful if there is not much data transmitted and/or
only one physical connection is used. If the management of credits is manual,
credits are provided by the application such that it can manage its receive buffers
explicitly.

0.19.3. Access an RFCOMM service on a remote device. To communicate with


an RFCOMM service on a remote device, the application on a local Bluetooth
device initiates the RFCOMM layer using the rfcomm init function, and then
creates an outgoing RFCOMM channel to a given server channel on a remote
device using the rfcomm create channel function. The rfcomm create channel
function will initiate a new L2CAP connection for the RFCOMM multiplexer,
if it does not already exist. The channel will automatically provide enough
credits to the remote side. To provide credits manually, you have to create the
RFCOMM connection by calling rfcomm create channel with initial credits - see
Section on manual credit assignement.
The packet handler that is given as an input parameter of the RFCOMM create
channel function will be assigned to the new outgoing channel. This handler re-
ceives the RFCOMM EVENT CHANNEL OPENED and RFCOMM EVENT CHANNEL CLOSED
events, and RFCOMM data packets, as shown in Listing below.

void r f c o m m p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
44

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case RFCOMM EVENT CHANNEL OPENED:
if (
rfcomm event open channel complete get status
( packet ) ) {
p r i n t f ( ” Connection f a i l e d \n\ r ” ) ;
} else {
p r i n t f ( ” Connected \n\ r ” ) ;
}
break ;
case RFCOMM EVENT CHANNEL CLOSED:
break ;
...
}
break ;
case RFCOMM DATA PACKET:
// h a n d l e RFCOMM d a t a p a c k e t s
return ;
}
}

void c r e a t e r f c o m m c h a n n e l ( uint8 t p a c k e t t y p e , uint8 t ∗ packet ,


uint16 t s i z e ) {
r f c o m m c r e a t e c h a n n e l ( r f c o m m p a c k e t h a n d l e r , addr ,
rfcomm channel ) ;
}

void b t s t a c k s e t u p ( ) {
...
l2cap init () ;
rfcomm init () ;
}

The RFCOMM channel will stay open until either side closes it with rf-
comm disconnect. BTstack will close the multiplexer after 60 seconds without
an active RFCOMM channel.

0.19.4. Provide an RFCOMM service. To provide an RFCOMM service, the ap-


plication on a local Bluetooth device must first init the L2CAP and RFCOMM
layers and then register the service with rfcomm register service. From there on,
it can wait for incoming RFCOMM connections. The application can accept
or deny an incoming connection by calling the rfcomm accept connection and rf-
comm deny connection functions respectively. If a connection is accepted and the
incoming RFCOMM channel gets successfully opened, the RFCOMM service can
send RFCOMM data packets to the connected device with rfcomm send and re-
ceive data packets by the packet handler provided by the rfcomm register service
call.
Listing below provides the RFCOMM service example code.

void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel , uint8 t ∗


packet , uint16 t s i z e ) {
45

switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case RFCOMM EVENT INCOMING CONNECTION:
rfcomm channel id =
rfcomm event incoming connection get rfcomm cid
( packet ) ;
rfcomm accept connection ( rfcomm channel id ) ;
break ;
case RFCOMM EVENT CHANNEL OPENED:
if (
rfcomm event open channel complete get status
( packet ) ) {
p r i n t f ( ”RFCOMM c h a n n e l open f a i l e d . ” ) ;
break ;
}
rfcomm channel id =
rfcomm event open channel complete get rfcomm cid
( packet ) ;
mtu =
rfcomm event open channel complete get max frame size
( packet ) ;
p r i n t f ( ”RFCOMM c h a n n e l open s u c c e e d e d , max frame
s i z e %u . ” , mtu ) ;
break ;
case RFCOMM EVENT CHANNEL CLOSED:
p r i n t f ( ” Channel c l o s e d . ” ) ;
break ;
...
}
break ;
case RFCOMM DATA PACKET:
// h a n d l e RFCOMM d a t a p a c k e t s
return ;
...
}
...
}

void b t s t a c k s e t u p ( ) {
...
l2cap init () ;
rfcomm init () ;
r f c o m m r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , rf co m m c ha nn el nr , mtu ) ;
}

0.19.5. Slowing down RFCOMM data reception. RFCOMM’s credit-based flow-


control can be used to adapt, i.e., slow down the RFCOMM data to your process-
ing speed. For incoming data, BTstack provides channels and services with and
without automatic credit management. If the management of credits is auto-
matic, new credits are provided when needed relying on ACL flow control. This
46

is only useful if there is not much data transmitted and/or only one physical
connection is used. See Listing below.

void b t s t a c k s e t u p ( void ) {
...
// i n i t RFCOMM
rfcomm init () ;
r f c o m m r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , rf co m m c ha nn el nr , 1 0 0 ) ;
}

If the management of credits is manual, credits are provided by the application


such that it can manage its receive buffers explicitly, see Listing below.
Manual credit management is recommended when received RFCOMM data
cannot be processed immediately. In the SPP flow control example, delayed
processing of received data is simulated with the help of a periodic timer. To
provide new credits, you call the rfcomm grant credits function with the RF-
COMM channel ID and the number of credits as shown in Listing below.

void b t s t a c k s e t u p ( void ) {
...
// i n i t RFCOMM
rfcomm init () ;
// r e s e r v e d channel , mtu=100 , 1 c r e d i t
r f c o m m r e g i s t e r s e r v i c e w i t h i n i t i a l c r e d i t s ( packet handler ,
rf c om m c ha nn el n r , 1 0 0 , 1 ) ;
}

void p r o c e s s i n g ( ) {
// p r o c e s s incoming d a t a p a c k e t
...
// p r o v i d e new c r e d i t
rfcomm grant credits ( rfcomm channel id , 1) ;
}

Please note that providing single credits effectively reduces the credit-based
(sliding window) flow control to a stop-and-wait flow-control that limits the data
throughput substantially. On the plus side, it allows for a minimal memory
footprint. If possible, multiple RFCOMM buffers should be used to avoid pauses
while the sender has to wait for a new credit.
0.19.6. Sending RFCOMM data. Outgoing packets, both commands and data,
are not queued in BTstack. This section explains the consequences of this design
decision for sending data and why it is not as bad as it sounds.
Independent from the number of output buffers, packet generation has to be
adapted to the remote receiver and/or maximal link speed. Therefore, a packet
can only be generated when it can get sent. With this assumption, the single
47

output buffer design does not impose additional restrictions. In the following,
we show how this is used for adapting the RFCOMM send rate.
When there is a need to send a packet, call rcomm request can send now and
wait for the reception of the RFCOMM EVENT CAN SEND NOW event to
send the packet, as shown in Listing below.
Please note that the guarantee that a packet can be sent is only valid when
the event is received. After returning from the packet handler, BTstack might
need to send itself.

void p r e p a r e d a t a ( uint16 t r f c o m m c h a n n e l i d ) {
...
// p r e p a r e d a t a i n d a t a b u f f e r
rfcomm request can send now event ( rfcomm channel id ) ;
}

void s e n d d a t a ( uint16 t r f c o m m c h a n n e l i d ) {
rfcomm send ( r f c o m m c h a n n e l i d , d a t a b u f f e r , d a t a l e n ) ;
// p a c k e t i s handed o v e r t o BTstack , we can p r e p a r e t h e n e x t one
prepare data ( rfcomm channel id ) ;
}

void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel , uint8 t ∗


packet , uint16 t s i z e ) {
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
...
case RFCOMM EVENT CAN SEND NOW:
rfcomm channel id =
rfcomm event can send now get rfcomm cid (
packet ) ;
send data ( rfcomm channel id ) ;
break ;
...
}
...
}
}
}

0.19.7. Optimized sending of RFCOMM data. When sending RFCOMM data


via rfcomm send, BTstack needs to copy the data from the user provided buffer
into the outgoing buffer. This requires both an additional buffer for the user
data as well requires a copy operation.
To avoid this, it is possible to directly write the user data into the outgoing
buffer.
When get the RFCOMM CAN SEND NOW event, you call rfcomm reserve packet buffer
to lock the buffer for your send operation. Then, you can ask how many bytes
you can send with rfcomm get max frame size and get a pointer to BTstack’s
48

buffer with rfcomm get outgoing buffer. Now, you can fill that buffer and finally
send the data with rfcomm send prepared.

0.20. SDP - Service Discovery Protocol. The SDP protocol allows to an-
nounce services and discover services provided by a remote Bluetooth device.

0.20.1. Create and announce SDP records. BTstack contains a complete SDP
server and allows to register SDP records. An SDP record is a list of SDP
Attribute {ID, Value} pairs that are stored in a Data Element Sequence (DES).
The Attribute ID is a 16-bit number, the value can be of other simple types like
integers or strings or can itself contain other DES.
To create an SDP record for an SPP service, you can call spp create sdp record
from with a pointer to a buffer to store the record, the server channel number,
and a record name.
For other types of records, you can use the other functions in, using the data
element de functions. Listing [sdpCreate] shows how an SDP record containing
two SDP attributes can be created. First, a DES is created and then the Service
Record Handle and Service Class ID List attributes are added to it. The Service
Record Handle attribute is added by calling the de add number function twice:
the first time to add 0x0000 as attribute ID, and the second time to add the
actual record handle (here 0x1000) as attribute value. The Service Class ID
List attribute has ID 0x0001, and it requires a list of UUIDs as attribute value.
To create the list, de push sequence is called, which “opens” a sub-DES. The
returned pointer is used to add elements to this sub-DES. After adding all UUIDs,
the sub-DES is “closed” with de pop sequence.
To register an SDP record, you call sdp register service with a pointer to it.
The SDP record can be stored in FLASH since BTstack only stores the pointer.
Please note that the buffer needs to persist (e.g. global storage, dynamically
allocated from the heap or in FLASH) and cannot be used to create another
SDP record.

0.20.2. Query remote SDP service. BTstack provides an SDP client to query
SDP services of a remote device. The SDP Client API is shown in here. The
sdp client query function initiates an L2CAP connection to the remote SDP
server. Upon connect, a Service Search Attribute request with a Service Search
Pattern and a Attribute ID List is sent. The result of the Service Search Attribute
query contains a list of Service Records, and each of them contains the requested
attributes. These records are handled by the SDP parser. The parser delivers
SDP PARSER ATTRIBUTE VALUE and SDP PARSER COMPLETE events
via a registered callback. The SDP PARSER ATTRIBUTE VALUE event de-
livers the attribute value byte by byte.
On top of this, you can implement specific SDP queries. For example, BT-
stack provides a query for RFCOMM service name and channel number. This
information is needed, e.g., if you want to connect to a remote SPP service.
The query delivers all matching RFCOMM services, including its name and the
channel number, as well as a query complete event via a registered callback, as
shown in Listing below.
49

bd addr t remote = {0 x04 , 0 x0C , 0 xCE, 0 xE4 , 0 x85 , 0 xD3 } ;

void p a c k e t h a n d l e r ( void ∗ c o n n e c t i o n , uint8 t p a c k e t t y p e ,


uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) {
i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

uint8 t e v e n t = p a c k e t [ 0 ] ;
switch ( e v e n t ) {
case BTSTACK EVENT STATE:
// b t s t a c k a c t i v a t e d , g e t s t a r t e d
i f ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) ==
HCI STATE WORKING) {
sdp client query rfcomm channel and name for uuid (
remote , 0 x0003 ) ;
}
break ;
default :
break ;
}
}

s t a t i c void b t s t a c k s e t u p ( ) {
...
// i n i t L2CAP
l2cap init () ;
l2cap register packet handler ( packet handler ) ;
}

void h a n d l e q u e r y r f c o m m e v e n t ( sdp query event t ∗ event , void ∗


context ) {
sdp client query rfcomm service event t ∗ ve ;

switch ( event−>type ) {
case SDP EVENT QUERY RFCOMM SERVICE:
ve = ( sdp client query rfcomm service event t ∗ ) e v e n t ;
p r i n t f ( ” S e r v i c e name : ’% s ’ , RFCOMM p o r t %u\n” , ve−>
s e r v i c e n a m e , ve−>c h a n n e l n r ) ;
break ;
case SDP EVENT QUERY COMPLETE:
report found services () ;
p r i n t f ( ” C l i e n t query r e s p o n s e done with s t a t u s %d . \n” ,
ce−>s t a t u s ) ;
break ;
}
}

int main ( void ) {


hw setup ( ) ;
btstack setup () ;

// r e g i s t e r c a l l b a c k t o r e c e i v e matching RFCOMM S e r v i c e s and


// q u e r y c o m p l e t e e v e n t
sdp client query rfcomm register callback (
h a n d l e q u e r y r f c o m m e v e n t , NULL) ;
50

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
// go !
btstack run loop execute () ;
return 0 ;
}

0.21. BNEP - Bluetooth Network Encapsulation Protocol. The BNEP


protocol is used to transport control and data packets over standard network
protocols such as TCP, IPv4 or IPv6. It is built on top of L2CAP, and it specifies
a minimum L2CAP MTU of 1691 bytes.

0.21.1. Receive BNEP events. To receive BNEP events, please register a packet
handler with bnep register packet handler.

0.21.2. Access a BNEP service on a remote device. To connect to a remote


BNEP service, you need to know its UUID. The set of available UUIDs can
be queried by a SDP query for the PAN profile. Please see section on PAN pro-
file for details. With the remote UUID, you can create a connection using the
bnep connect function. You’ll receive a BNEP EVENT CHANNEL OPENED
on success or failure.
After the connection was opened successfully, you can send and receive Ether-
net packets. Before sending an Ethernet frame with bnep send, bnep can send packet now
needs to return true. Ethernet frames are received via the registered packet han-
dler with packet type BNEP DATA PACKET.
BTstack BNEP implementation supports both network protocol filter and
multicast filters with bnep set net type filter and bnep set multicast filter respec-
tively.
Finally, to close a BNEP connection, you can call bnep disconnect.

0.21.3. Provide BNEP service. To provide a BNEP service, call bnep register service
with the provided service UUID and a max frame size.
A BNEP EVENT INCOMING CONNECTION event will mark that an in-
coming connection is established. At this point you can start sending and re-
ceiving Ethernet packets as described in the previous section.

0.21.4. Sending Ethernet packets. Similar to L2CAP and RFOMM, directly send-
ing an Ethernet packet via BNEP might fail, if the outgoing packet buffer or the
ACL buffers in the Bluetooth module are full.
When there’s a need to send an Ethernet packet, call bnep request can send now
and send the packet when the BNEP EVENT CAN SEND NOW event gets re-
ceived.

0.22. ATT - Attribute Protocol. The ATT protocol is used by an ATT client
to read and write attribute values stored on an ATT server. In addition, the ATT
server can notify the client about attribute value changes. An attribute has a
handle, a type, and a set of properties.
51

The Generic Attribute (GATT) profile is built upon ATT and provides higher
level organization of the ATT attributes into GATT Services and GATT Char-
acteristics. In BTstack, the complete ATT client functionality is included within
the GATT Client. See GATT client for more.
On the server side, one ore more GATT profiles are converted ahead of time
into the corresponding ATT attribute database and provided by the att server
implementation. The constant data are automatically served by the ATT server
upon client request. To receive the dynamic data, such is characteristic value, the
application needs to register read and/or write callback. In addition, notifications
and indications can be sent. Please see Section on GATT server for more.

0.23. SMP - Security Manager Protocol. The SMP protocol allows to setup
authenticated and encrypted LE connection. After initialization and configura-
tion, SMP handles security related functions on its own but emits events when
feedback from the main app or the user is required. The two main tasks of the
SMP protocol are: bonding and identity resolving.

0.23.1. LE Legacy Pairing and LE Secure Connections. The original pairing al-
gorithm introduced in Bluetooth Core V4.0 does not provide security in case of
an attacker present during the initial pairing. To fix this, the Bluetooth Core
V4.2 specification introduced the new LE Secure Connections method, while
referring to the original method as LE Legacy Pairing.
BTstack supports both pairing methods. To enable the more secure LE Se-
cure Connections method, ENABLE LE SECURE CONNECTIONS needs to be
defined in btstack config.h.
LE Secure Connections are based on Elliptic Curve Diffie-Hellman (ECDH)
algorithm for the key exchange. On start, a new public/private key pair is
generated. During pairing, the Long Term Key (LTK) is generated based on
the local keypair and the remote public key. To facilitate the creation of such a
keypairs and the calculation of the LTK, the Bluetooth Core V4.2 specification
introduced appropriate commands for the Bluetooth controller.
As an alternative for controllers that don’t provide these primitives, BTstack
provides the relevant cryptographic functions in software via the BSD-2-Clause
licensed micro-ecc library. When using using LE Secure Connections, the Pe-
ripheral must store LTK in non-volatile memory.
To only allow LE Secure Connections, you can call sm set secure connections only mode(true).

0.23.2. Initialization. To activate the security manager, call sm init().


If you’re creating a product, you should also call sm set ir() and sm set er()
with a fixed random 16 byte number to create the IR and ER key seeds. If
possible use a unique random number per device instead of deriving it from the
product serial number or something similar. The encryption key generated by the
BLE peripheral will be ultimately derived from the ER key seed. See Bluetooth
Specification - Bluetooth Core V4.0, Vol 3, Part G, 5.2.2 for more details on
deriving the different keys. The IR key is used to identify a device if private,
resolvable Bluetooth addresses are used.
52

0.23.3. Configuration. To receive events from the Security Manager, a callback


is necessary. How to register this packet handler depends on your application
configuration.
When att server is used to provide a GATT/ATT service, att server registers
itself as the Security Manager packet handler. Security Manager events are then
received by the application via the att server packet handler.
If att server is not used, you can directly register your packet handler with
the security manager by calling sm register packet handler.
The default SMP configuration in BTstack is to be as open as possible:
• accept all Short Term Key (STK) Generation methods,
• accept encryption key size from 7..16 bytes,
• expect no authentication requirements,
• don’t require LE Secure Connections, and
• IO Capabilities set to IO CAPABILITY NO INPUT NO OUTPUT.
You can configure these items by calling following functions respectively:
• sm set accepted stk generation methods
• sm set encryption key size range
• sm set authentication requirements : add SM AUTHREQ SECURE CONNECTION
flag to enable LE Secure Connections
• sm set io capabilities
0.23.4. Identity Resolving. Identity resolving is the process of matching a private,
resolvable Bluetooth address to a previously paired device using its Identity Re-
solving (IR) key. After an LE connection gets established, BTstack automatically
tries to resolve the address of this device. During this lookup, BTstack will emit
the following events:
• SM EVENT IDENTITY RESOLVING STARTED to mark the start of
a lookup,
and later:
• SM EVENT IDENTITY RESOLVING SUCCEEDED on lookup success,
or
• SM EVENT IDENTITY RESOLVING FAILED on lookup failure.
0.23.5. User interaction during Pairing. BTstack will inform the app about pair-
ing via theses events:
• SM EVENT PAIRING STARTED: inform user that pairing has started
• SM EVENT PAIRING COMPLETE : inform user that pairing is com-
plete, see status
Depending on the authentication requirements, IO capabilities, available OOB
data, and the enabled STK generation methods, BTstack will request feedback
from the app in the form of an event:
• SM EVENT JUST WORKS REQUEST : request a user to accept a Just
Works pairing
• SM EVENT PASSKEY INPUT NUMBER: request user to input a passkey
• SM EVENT PASSKEY DISPLAY NUMBER: show a passkey to the user
• SM EVENT PASSKEY DISPLAY CANCEL: cancel show passkey to user
53

• SM EVENT NUMERIC COMPARISON REQUEST : show a passkey to


the user and request confirmation
To accept Just Works/Numeric Comparison, or provide a Passkey, sm just works confirm
or sm passkey input can be called respectively. Othwerise, sm bonding decline
aborts the pairing.
After the bonding process, SM EVENT PAIRING COMPLETE, is emitted.
Any active dialog can be closed on this.
0.23.6. Connection with Bonded Devices. During pairing, two devices exchange
bonding information, notably a Long-Term Key (LTK) and their respective Iden-
tity Resolving Key (IRK). On a subsequent connection, the Securit Manager will
use this information to establish an encrypted connection.
To inform about this, the following events are emitted:
• SM EVENT REENCRYPTION STARTED: we have stored bonding in-
formation and either trigger encryption (as Central), or, sent a security
request (as Peripheral).
• SM EVENT REENCRYPTION COMPLETE : re-encryption is complete.
If the remote device does not have a stored LTK, the status code will be
ERROR CODE PIN OR KEY MISSING.
The SM EVENT REENCRYPTION COMPLETE with ERROR CODE PIN OR KEY MISSIN
can be caused:
• if the remote device was reset or the bonding was removed, or,
• we’re connected to an attacker that uses the Bluetooth address of a
bonded device.
In Peripheral role, pairing will start even in case of an re-encryption error. It
might be helpful to inform the user about the lost bonding or reject it right away
due to security considerations.
0.23.7. Keypress Notifications. As part of Bluetooth Core V4.2 specification, a
device with a keyboard but no display can send keypress notifications to pro-
vide better user feedback. In BTstack, the sm keypress notification() function
is used for sending notifications. Notifications are received by BTstack via the
SM EVENT KEYPRESS NOTIFICATION event.
0.23.8. Cross-transport Key Derivation (CTKD) for LE Secure Connections. In
a dual-mode configuration, BTstack generates an BR/EDR Link Key from the
LE LTK via the Link Key Conversion functions h6 , (or h7 if supported) when
ENABLE CROSS TRANSPORT KEY DERIVATION is defined. The derived
key then stored in local LE Device DB.
The main use case for this is connections with smartphones. E.g. iOS provides
APIs for LE scanning and connection, but none for BR/EDR. This allows an
application to connect and pair with a device and also later setup a BR/EDR
connection without the need for the smartphone user to use the system Settings
menu.
To derive an LE LTK from a BR/EDR link key, the Bluetooth controller needs
to support Secure Connections via NIST P-256 elliptic curves. BTstack does not
support LE Secure Connections via LE Transport currently.
54

0.23.9. Out-of-Band Data with LE Legacy Pairing. LE Legacy Pairing can be


made secure by providing a way for both devices to acquire a pre-shared secret
16 byte key by some fancy method. In most cases, this is not an option, especially
since popular OS like iOS don’t provide a way to specify it. In some applications,
where both sides of a Bluetooth link are developed together, this could provide
a viable option.
To provide OOB data, you can register an OOB data callback with sm register oob data callback.
#Profiles
In the following, we explain how the various Bluetooth profiles are used in
BTstack.
0.24. A2DP - Advanced Audio Distribution. The A2DP profile defines how
to stream audio over a Bluetooth connection from one device, such as a mobile
phone, to another device such as a headset. A device that acts as source of audio
stream implements the A2DP Source role. Similarly, a device that receives an
audio stream implements the A2DP Sink role. As such, the A2DP service allows
uni-directional transfer of an audio stream, from single channel mono, up to
two channel stereo. Our implementation includes mandatory support for the
low-complexity SBC codec. Signaling for optional codes (FDK AAC, LDAC,
APTX) is supported as well, by you need to provide your own codec library.
0.25. AVRCP - Audio/Video Remote Control Profile. The AVRCP pro-
file defines how audio playback on a remote device (e.g. a music app on a smart-
phone) can be controlled as well as how to state changes such as volume, infor-
mation on currently played media, battery, etc. can be received from a remote
device (e.g. a speaker). Usually, each device implements two roles: - The Con-
troller role allows to query information on currently played media, such are title,
artist and album, as well as to control the playback, i.e. to play, stop, repeat,
etc. - The Target role responds to commands, e.g. playback control, and queries,
e.g. playback status, media info, from the Controller currently played media.
0.26. GAP - Generic Access Profile: Classic. The GAP profile defines how
devices find each other and establish a secure connection for other profiles. As
mentioned before, the GAP functionality is split between and . Please check
both.
0.26.1. Become discoverable. A remote unconnected Bluetooth device must be
set as “discoverable” in order to be seen by a device performing the inquiry scan.
To become discoverable, an application can call gap discoverable control with
input parameter 1. If you want to provide a helpful name for your device, the
application can set its local name by calling gap set local name. To save energy,
you may set the device as undiscoverable again, once a connection is established.
See Listing below for an example.

int main ( void ) {


...
// make d i s c o v e r a b l e
gap discoverable control (1) ;
55

btstack run loop execute () ;


return 0 ;
}
void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint8 t ∗ packet , uint16 t
size ){
...
switch ( s t a t e ) {
case W4 CHANNEL COMPLETE:
// i f c o n n e c t i o n i s s u c c e s s f u l , make d e v i c e
undiscoverable
gap discoverable control (0) ;
...
}
}

0.26.2. Discover remote devices. To scan for remote devices, the hci inquiry com-
mand is used. Found remote devices are reported as a part of:
• HCI EVENT INQUIRY RESULT,
• HCI EVENT- INQUIRY RESULT WITH RSSI, or
• HCI EVENT EXTENDED INQUIRY RESPONSE events.
Each response contains at least the Bluetooth address, the class of device, the
page scan repetition mode, and the clock offset of found device. The latter events
add information about the received signal strength or provide the Extended
Inquiry Result (EIR). A code snippet is shown in Listing below.

void p r i n t i n q u i r y r e s u l t s ( uint8 t ∗ p a c k e t ) {
int e v e n t = p a c k e t [ 0 ] ;
int numResponses = h c i e v e n t i n q u i r y r e s u l t g e t n u m r e s p o n s e s (
packet ) ;
uint16 t c l a s s O f D e v i c e , c l o c k O f f s e t ;
uint8 t r s s i , pageScanRepetitionMode ;
f o r ( i =0; i <numResponses ; i ++){
b t f l i p a d d r ( addr , &p a c k e t [3+ i ∗ 6 ] ) ;
pageScanRepetitionMode = p a c k e t [ 3 + numResponses ∗6 + i ] ;
i f ( e v e n t == HCI EVENT INQUIRY RESULT) {
c l a s s O f D e v i c e = l i t t l e e n d i a n r e a d 2 4 ( packet , 3 +
numResponses∗(6+1+1+1) + i ∗ 3 ) ;
clockOffset = l i t t l e e n d i a n r e a d 1 6 ( packet , 3 +
numResponses∗(6+1+1+1+3) + i ∗ 2 ) & 0 x 7 f f f ;
r s s i = 0;
} else {
c l a s s O f D e v i c e = l i t t l e e n d i a n r e a d 2 4 ( packet , 3 +
numResponses ∗(6+1+1) + i ∗3) ;
clockOffset = l i t t l e e n d i a n r e a d 1 6 ( packet , 3 +
numResponses∗(6+1+1+3) + i ∗2) & 0 x 7 f f f ;
r s s i = p a c k e t [ 3 + numResponses∗(6+1+1+3+2) + i ∗ 1 ] ;
}
56

p r i n t f ( ” De v ic e found : %s with COD: 0x%06x , pageScan %u ,


c l o c k o f f s e t 0x%04x , r s s i 0x%02x\n” , b d a d d r t o s t r ( addr
) , c l a s s O f D e v i c e , pageScanRepetitionMode , c l o c k O f f s e t ,
rssi ) ;
}
}

void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint8 t ∗ packet , uint16 t


size ){
...
switch ( e v e n t ) {
case HCI STATE WORKING :
h c i s e n d c m d (& h c i w r i t e i n q u i r y m o d e , 0 x01 ) ; // w i t h
RSSI
break ;
case HCI EVENT COMMAND COMPLETE:
i f (COMMAND COMPLETE EVENT( packet ,
hci write inquiry mode ) ) {
start scan () ;
}
case HCI EVENT COMMAND STATUS:
i f (COMMAND STATUS EVENT( packet , h c i w r i t e i n q u i r y m o d e )
) {
p r i n t f ( ” I g n o r i n g e r r o r ( 0 x%x ) from
h c i w r i t e i n q u i r y m o d e . \ n” , p a c k e t [ 2 ] ) ;
h c i s e n d c m d (& h c i i n q u i r y , HCI INQUIRY LAP ,
INQUIRY INTERVAL, 0 ) ;
}
break ;
case HCI EVENT INQUIRY RESULT :
case HCI EVENT INQUIRY RESULT WITH RSSI :
p r i n t i n q u i r y r e s u l t s ( packet ) ;
break ;
...
}
}

By default, neither RSSI values nor EIR are reported. If the Bluetooth de-
vice implements Bluetooth Specification 2.1 or higher, the hci write inquiry mode
command enables reporting of this advanced features (0 for standard results, 1
for RSSI, 2 for RSSI and EIR).
A complete GAP inquiry example is provided here.

0.26.3. Pairing of Devices. By default, Bluetooth communication is not authen-


ticated, and any device can talk to any other device. A Bluetooth device (for
example, cellular phone) may choose to require authentication to provide a par-
ticular service (for example, a Dial-Up service). The process of establishing
authentication is called pairing. Bluetooth provides two mechanism for this.
On Bluetooth devices that conform to the Bluetooth v2.0 or older specification,
a PIN code (up to 16 bytes ASCII) has to be entered on both sides. This isn’t
optimal for embedded systems that do not have full I/O capabilities. To support
pairing with older devices using a PIN, see Listing below.
57

void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint8 t ∗ packet , uint16 t


size ){
...
switch ( e v e n t ) {
case HCI EVENT PIN CODE REQUEST :
// inform a b o u t p i n code r e q u e s t
p r i n t f ( ” Pin code r e q u e s t − u s i n g ’ 0 0 0 0 ’ \ n\ r ” ) ;
h c i e v e n t p i n c o d e r e q u e s t g e t b d a d d r ( packet , bd addr ) ;

// b a s e b a n d a d d r e s s , p i n l e n g t h , PIN : c−s t r i n g
h c i s e n d c m d (& h c i p i n c o d e r e q u e s t r e p l y , &bd addr , 4 , ”
0000 ” ) ;
break ;
...
}
}

The Bluetooth v2.1 specification introduces Secure Simple Pairing (SSP),


which is a better approach as it both improves security and is better adapted to
embedded systems. With SSP, the devices first exchange their IO Capabilities
and then settle on one of several ways to verify that the pairing is legitimate.
If the Bluetooth device supports SSP, BTstack enables it by default and even
automatically accepts SSP pairing requests. Depending on the product in which
BTstack is used, this may not be desired and should be replaced with code to
interact with the user.
Regardless of the authentication mechanism (PIN/SSP), on success, both de-
vices will generate a link key. The link key can be stored either in the Bluetooth
module itself or in a persistent storage, see here. The next time the device
connects and requests an authenticated connection, both devices can use the
previously generated link key. Please note that the pairing must be repeated if
the link key is lost by one device.

0.26.4. Dedicated Bonding. Aside from the regular bonding, Bluetooth also pro-
vides the concept of “dedicated bonding”, where a connection is established for
the sole purpose of bonding the device. After the bonding process is over, the
connection will be automatically terminated. BTstack supports dedicated bond-
ing via the gap dedicated bonding function.

0.27. SPP - Serial Port Profile. The SPP profile defines how to set up virtual
serial ports and connect two Bluetooth enabled devices. Please keep in mind
that a serial port does not preserve packet boundaries if you try to send data as
packets and read about RFCOMM packet boundaries.

0.27.1. Accessing an SPP Server on a remote device. To access a remote SPP


server, you first need to query the remote device for its SPP services. Section
on querying remote SDP service shows how to query for all RFCOMM channels.
For SPP, you can do the same but use the SPP UUID 0x1101 for the query. After
58

you have identified the correct RFCOMM channel, you can create an RFCOMM
connection as shown here.

0.27.2. Providing an SPP Server. To provide an SPP Server, you need to provide
an RFCOMM service with a specific RFCOMM channel number as explained in
section on RFCOMM service. Then, you need to create an SDP record for
it and publish it with the SDP server by calling sdp register service. BTstack
provides the spp create sdp record function in that requires an empty buffer of
approximately 200 bytes, the service channel number, and a service name. Have
a look at the SPP Counter example.

0.28. PAN - Personal Area Networking Profile. The PAN profile uses
BNEP to provide on-demand networking capabilities between Bluetooth devices.
The PAN profile defines the following roles:
• PAN User (PANU)
• Network Access Point (NAP)
• Group Ad-hoc Network (GN)
PANU is a Bluetooth device that communicates as a client with GN, or NAP,
or with another PANU Bluetooth device, through a point-to-point connection.
Either the PANU or the other Bluetooth device may terminate the connection
at anytime.
NAP is a Bluetooth device that provides the service of routing network packets
between PANU by using BNEP and the IP routing mechanism. A NAP can also
act as a bridge between Bluetooth networks and other network technologies by
using the Ethernet packets.
The GN role enables two or more PANUs to interact with each other through
a wireless network without using additional networking hardware. The devices
are connected in a piconet where the GN acts as a master and communicates
either point-to-point or a point-to-multipoint with a maximum of seven PANU
slaves by using BNEP.
Currently, BTstack supports only PANU.

0.28.1. Accessing a remote PANU service. To access a remote PANU service,


you first need perform an SDP query to get the L2CAP PSM for the requested
PANU UUID. With these two pieces of information, you can connect BNEP to
the remote PANU service with the bnep connect function. The Section on PANU
Demo example shows how this is accomplished.

0.28.2. Providing a PANU service. To provide a PANU service, you need to


provide a BNEP service with the service UUID, e.g. the PANU UUID, and a
maximal ethernet frame size, as explained in Section on BNEP service. Then,
you need to create an SDP record for it and publish it with the SDP server
by calling sdp register service. BTstack provides the pan create panu sdp record
function in src/pan.c that requires an empty buffer of approximately 200 bytes,
a description, and a security description.
59

0.29. HSP - Headset Profile. The HSP profile defines how a Bluetooth-
enabled headset should communicate with another Bluetooth enabled device.
It relies on SCO for audio encoded in 64 kbit/s CVSD and a subset of AT com-
mands from GSM 07.07 for minimal controls including the ability to ring, answer
a call, hang up and adjust the volume.
The HSP defines two roles:
• Audio Gateway (AG) - a device that acts as the gateway of the audio,
typically a mobile phone or PC.
• Headset (HS) - a device that acts as the AG’s remote audio input and
output control.
There are following restrictions: - The CVSD is used for audio transmission.
• Between headset and audio gateway, only one audio connection at a time
is supported.
• The profile offers only basic interoperability – for example, handling of
multiple calls at the audio gateway is not included.
• The only assumption on the headset’s user interface is the possibility to
detect a user initiated action (e.g. pressing a button).
%TODO: audio paths
0.30. HFP - Hands-Free Profile. The HFP profile defines how a Bluetooth-
enabled device, e.g. a car kit or a headset, can be used to place and receive
calls via a audio gateway device, typically a mobile phone. It relies on SCO for
audio encoded in 64 kbit/s CVSD and a bigger subset of AT commands from
GSM 07.07 then HSP for controls including the ability to ring, to place and
receive calls, join a conference call, to answer, hold or reject a call, and adjust
the volume.
The HFP defines two roles:
• Audio Gateway (AG) – a device that acts as the gateway of the audio,,
typically a mobile phone.
• Hands-Free Unit (HF) – a device that acts as the AG’s remote audio
input and output control.
0.30.1. Supported Features. The supported features define the HFP capabilities
of the device. The enumeration unfortunately differs between HF and AG sides.
The AG supported features are set by combining the flags that start with
HFP AGSF xx and calling hfp ag init supported features, followed by creating
SDP record for the service using the same feature set.
Similarly, the HF supported features are a combination of HFP HFSF xx flags
and are configured by calling hfp hf init supported features, as well as creating
an SDP record.
Define for AG Supported Feature Description
HFP AGSF THREE WAY CALLING Three-way calling
HFP AGSF EC NR FUNCTION Echo Canceling and/or Noise
Reduction function
HFP AGSF VOICE RECOGNITION FUNCTION
Voice recognition function
HFP AGSF IN BAND RING TONE In-band ring tone capability
60

Define for AG Supported Feature Description


HFP AGSF
ATTACH A NUMBER TO A VOICE
AttachTAG
a number to a voice tag
HFP AGSF
ABILITY TO REJECT A CALLAbility to reject a call
HFP AGSF
ENHANCED CALL STATUS Enhanced call status
HFP AGSF
ENHANCED CALL CONTROL Enhanced call control
HFP AGSF
EXTENDED ERROR RESULT CODES
Extended Error Result Codes
HFP AGSF
CODEC NEGOTIATION Codec negotiation
HFP AGSF
HF INDICATORS HF Indicators
HFP AGSF
ESCO S4 eSCO S4 (and T2) Settings
Supported
HFP AGSF ENHANCED VOICE RECOGNITION
Enhanced
STATUS
voice recognition
status
HFP AGSF VOICE RECOGNITION TEXT Voice recognition text

Define for HF Supported Feature Description


HFP HFSF THREE WAY CALLING Three-way calling
HFP HFSF EC NR FUNCTION Echo Canceling and/or Noise
Reduction function
HFP HFSF CLI PRESENTATION CAPABILITY
CLI presentation capability
HFP HFSF VOICE RECOGNITION FUNCTION
Voice recognition function
HFP HFSF REMOTE VOLUME CONTROLRemote volume control
HFP HFSF ATTACH A NUMBER TO A VOICE
AttachTAG
a number to a voice tag
HFP HFSF ENHANCED CALL STATUS Enhanced call status
HFP HFSF ENHANCED CALL CONTROL Enhanced call control
HFP HFSF CODEC NEGOTIATION Codec negotiation
HFP HFSF HF INDICATORS HF Indicators
HFP HFSF ESCO S4 eSCO S4 (and T2) Settings
Supported
HFP HFSF ENHANCED VOICE RECOGNITION
Enhanced
STATUS
voice recognition
status
HFP HFSF VOICE RECOGNITION TEXT Voice recognition text

0.30.2. Audio Voice Recognition Activation. Audio voice recognition (AVR) re-
quires that HF and AG have the following features enabled:
• HF: HFP HFSF VOICE RECOGNITION FUNCTION and
• AG: HFP AGSF VOICE RECOGNITION FUNCTION.
It can be activated or deactivated on both sides by calling:

// AG
uint8 t h f p a g a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;
uint8 t h f p a g d e a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;
61

// HF
uint8 t h f p h f a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;
uint8 t h f p h f d e a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;

On activation change, the HFP SUBEVENT VOICE RECOGNITION (DE)ACTIVATED


event will be emitted with status field set to ERROR CODE SUCCESS on suc-
cess.
Voice recognition will stay active until either the deactivation command is
called, or until the current Service Level Connection between the AG and the
HF is dropped for any reason.

Use cases Expected behavior


No previous audio connection, AVR activated then Audio connection
deactivated will be opened by
AG upon AVR
activation, and upon
AVR deactivation
closed
AVR activated and deactivated during existing audio Audio remains
connection active upon AVR
deactivation
Call to close audio connection during active AVR The audio
session connection shut
down will be refused
AVR activated, but audio connection failed to be AVR will stay
established activated

Beyond the audio routing and voice recognition activation capabilities, the
rest of the voice recognition functionality is implementation dependent - the
stack only provides the signaling for this.

0.30.3. Enhanced Audio Voice Recognition. Similarly to AVR, Enhanced Audio


voice recognition (eAVR) requires that HF and AG have the following features
enabled:
• HF: HFP HFSF ENHANCED VOICE RECOGNITION STATUS and
• AG: HFP AGSF ENHANCED VOICE RECOGNITION STATUS.
In addition, to allow textual representation of audio that is parsed by eAVR
(note that parsing is not part of Bluetooth specification), both devices must
enable:
• HF: HFP HFSF VOICE RECOGNITION TEXT and
• AG: HFP AGSF VOICE RECOGNITION TEXT.
eAVR implements the same use cases as AVR (see previous section) and it can
be activated or deactivated using the same API as for AVR, see above.
62

When eAVR and audio channel are established there are several additional
commands that can be sent:
HFP Role eVRA API Description
HF hfp hf enhanced voice recognition
Ready to accept
reportaudio
ready for audio
input.
AG hfp ag enhanced voice recognition
Voice recognition
report engine
ready for
is audio
ready to accept audio
input.
AG hfp ag enhanced voice recognition
The voice recognition
report sending audio
engine will play a sound,
e.g. starting sound.
AG hfp ag enhanced voice recognition
Voice recognition
report engine
processing
is input
processing the audio input.
AG hfp ag enhanced voice recognition
Report textual
send message
representation from the
voice recognition engine.

0.31. HID - Human-Interface Device Profile. The HID profile allows an


HID Host to connect to one or more HID Devices and communicate with them.
Examples of Bluetooth HID devices are keyboards, mice, joysticks, gamepads,
remote controls, and also voltmeters and temperature sensors. Typical HID hosts
would be a personal computer, tablets, gaming console, industrial machine, or
data-recording device.
Please refer to:
• HID Host API and hid host demo for the HID Host role
• HID Device API, hid keyboard demo and hid mouse demo for the HID
Device role.

0.32. GAP LE - Generic Access Profile for Low Energy. As with GAP
for Classic, the GAP LE profile defines how to discover and how to connect to
a Bluetooth Low Energy device. There are several GAP roles that a Bluetooth
device can take, but the most important ones are the Central and the Peripheral
role. Peripheral devices are those that provide information or can be controlled.
Central devices are those that consume information or control the peripherals.
Before the connection can be established, devices are first going through an
advertising process.

0.32.1. Private addresses. To better protect privacy, an LE device can choose


to use a private i.e. random Bluetooth address. This address changes at a user-
specified rate. To allow for later reconnection, the central and peripheral devices
will exchange their Identity Resolving Keys (IRKs) during bonding. The IRK is
used to verify if a new address belongs to a previously bonded device.
To toggle privacy mode using private addresses, call the gap random address set mode
function. The update period can be set with gap random address set update period.
After a connection is established, the Security Manager will try to resolve the
peer Bluetooth address as explained in Section on SMP.
63

0.32.2. Advertising and Discovery. An LE device is discoverable and connectable,


only if it periodically sends out Advertisements. An advertisement contains up to
31 bytes of data. To configure and enable advertisement broadcast, the following
GAP functions can be used:
• gap advertisements set data
• gap advertisements set params
• gap advertisements enable
In addition to the Advertisement data, a device in the peripheral role can also
provide Scan Response data, which has to be explicitly queried by the central
device. It can be set with gap scan response set data.
Please have a look at the SPP and LE Counter example.
The scan parameters can be set with gap set scan parameters. The scan can
be started/stopped with gap start scan/gap stop scan.
Finally, if a suitable device is found, a connection can be initiated by calling
gap connect. In contrast to Bluetooth classic, there is no timeout for an LE
connection establishment. To cancel such an attempt, gap connect cancel has be
be called.
By default, a Bluetooth device stops sending Advertisements when it gets into
the Connected state. However, it does not start broadcasting advertisements
on disconnect again. To re-enable it, please send the hci le set advertise enable
again .

0.33. GATT Client. The GATT profile uses ATT Attributes to represent a hi-
erarchical structure of GATT Services and GATT Characteristics. Each Service
has one or more Characteristics. Each Characteristic has meta data attached
like its type or its properties. This hierarchy of Characteristics and Services are
queried and modified via ATT operations.
GATT defines both a server and a client role. A device can implement one or
both GATT roles.
The GATT Client is used to discover services, characteristics and their de-
scriptors on a peer device. It allows to subscribe for notifications or indications
that the characteristic on the GATT server has changed its value.
To perform GATT queries, it provides a rich interface. Before calling queries,
the GATT client must be initialized with gatt client init once.
To allow for modular profile implementations, GATT client can be used inde-
pendently by multiple entities.
After an LE connection was created using the GAP LE API, you can query
for the connection MTU with gatt client get mtu.
Multiple GATT queries to the same GATT Server cannot be interleaved.
Therefore, you can either use a state machine or similar to perform the queries
in sequence, or you can check if you can perform a GATT query on a particular
connection right now using gatt client is ready, and retry later if it is not ready.
As a result to a GATT query, zero to many GATT EVENT X s are returned
before a GATT EVENT QUERY COMPLETE event completes the query.
For more details on the available GATT queries, please consult GATT Client
API.
64

0.33.1. Authentication. By default, the GATT Server is responsible for security


and the GATT Client does not enforce any kind of authentication. If the GATT
Client accesses Characteristic that require encrytion or authentication, the re-
mote GATT Server will return an error, which is returned in the att status of
the GATT EVENT QUERY COMPLETE.
You can define ENABLE GATT CLIENT PAIRING to instruct the GATT
Client to trigger pairing in this case and to repeat the request.
This model allows for an attacker to spoof another device, but don’t require au-
thentication for the Characteristics. As a first improvement, you can define EN-
ABLE LE PROACTIVE AUTHENTICATION in btstack config.h. When de-
fined, the GATT Client will request the Security Manager to re-encrypt the
connection if there is stored bonding information available. If this fails, the
GATT EVENT QUERY COMPLETE will return with the att status ATT ERROR BONDING INF
With ENABLE LE PROACTIVE AUTHENTICATION defined and in Cen-
tral role, you need to delete the local bonding information if the remote lost its
bonding information, e.g. because of a device reset. See example/sm pairing central.c.
Even with the Proactive Authentication, your device may still connect to an at-
tacker that provides the same advertising data as your actual device. If the device
that you want to connect requires pairing, you can instruct the GATT Client to
automatically request an encrypted connection before sending any GATT Client
request by calling gatt client set required security level(). If the device provides
sufficient IO capabilities, a MITM attack can then be prevented. We call this
‘Mandatory Authentication’.
The following diagrams provide a detailed overview about the GATT Client
security mechanisms in different configurations:
• Reactive Authentication as Central
• Reactive Authentication as Peripheral
• Proactive Authentication as Central
• Proactive Authentication as Peripheral
• Mandatory Authentication as Central
• Mandatory Authentication as Peripheral

0.34. GATT Server. The GATT server stores data and accepts GATT client
requests, commands and confirmations. The GATT server sends responses to
requests and when configured, sends indication and notifications asynchronously
to the GATT client.
To save on both code space and memory, BTstack does not provide a GATT
Server implementation. Instead, a textual description of the GATT profile is
directly converted into a compact internal ATT Attribute database by a GATT
profile compiler. The ATT protocol server - implemented by and - answers
incoming ATT requests based on information provided in the compiled database
and provides read- and write-callbacks for dynamic attributes.
GATT profiles are defined by a simple textual comma separated value (.csv)
representation. While the description is easy to read and edit, it is compact and
can be placed in ROM.
The current format is shown in Listing below.
65

// i m p o r t s e r v i c e n a m e
#import <s e r v i c e n a m e . g a t t >

PRIMARY SERVICE, {SERVICE UUID}


CHARACTERISTIC, {ATTRIBUTE TYPE UUID} , {PROPERTIES} , {VALUE}
CHARACTERISTIC, {ATTRIBUTE TYPE UUID} , {PROPERTIES} , {VALUE}
...
PRIMARY SERVICE, {SERVICE UUID}
CHARACTERISTIC, {ATTRIBUTE TYPE UUID} , {PROPERTIES} , {VALUE}
...

UUIDs are either 16 bit (1800) or 128 bit (00001234-0000-1000-8000-00805F9B34FB).


Value can either be a string (“this is a string”), or, a sequence of hex bytes
(e.g. 01 02 03).
Properties can be a list of properties combined using ‘|’
Reads/writes to a Characteristic that is defined with the DYNAMIC flag, are
forwarded to the application via callback. Otherwise, the Characteristics cannot
be written and it will return the specified constant value.
Adding NOTIFY and/or INDICATE automatically creates an additional Client
Configuration Characteristic.

Property Description
READ Characteristic can be read
WRITE Characteristic can be written using Write Request
WRITE WITHOUT RESPONSE Characteristic can be written using Write Command
NOTIFY Characteristic allows notifications by server
INDICATE Characteristic allows indication by server
DYNAMIC Read or writes to Characteristic are handled by application

To require encryption or authentication before a Characteristic can be ac-


cessed, you can add one or more of the following properties:

Property Description
AUTHENTICATION REQUIRED Read and Write operations require Authentication
READ ENCRYPTED Read operations require Encryption
READ AUTHENTICATED Read operations require Authentication
WRITE ENCRYPTED Write operations require Encryption
WRITE AUTHENTICATED Write operations require Authentication
ENCRYPTION KEY SIZE X Require encryption size >= X, with W in [7..16]

For example, Volume State Characteristic (Voice Control Service) requires:


- Mandatory Properties: Read, Notify - Security Permissions: Encryption Re-
quired
In addition, its read is handled by application. We can model this Character-
istic as follows:
66

CHARACTERISTIC, ORG BLUETOOTH CHARACTERISTIC VOLUME STATE, DYNAMIC |


READ | NOTIFY | ENCRYPTION KEY SIZE 16

To use already implemented GATT Services, you can import it using the
#import <service name.gatt> command. See list of provided services.
BTstack only provides an ATT Server, while the GATT Server logic is mainly
provided by the GATT compiler. While GATT identifies Characteristics by
UUIDs, ATT uses Handles (16 bit values). To allow to identify a Characteristic
without hard-coding the attribute ID, the GATT compiler creates a list of defines
in the generated *.h file.
Similar to other protocols, it might be not possible to send any time. To send
a Notification, you can call att server request to send notification to request a
callback, when yuo can send the Notification.
If your application cannot handle an ATT Read Request in the att read callback
in some situations, you can enable support for this by adding ENABLE ATT DELAYED RESPONS
to btstack config.h. Now, you can store the requested attribute handle and re-
turn ATT READ RESPONSE PENDING instead of the length of the provided
data when you don’t have the data ready. For ATT operations that read more
than one attribute, your att read callback might get called multiple times as
well. To let you know that all necessary attribute handles have been ‘requested’
by the att server, you’ll get a final att read callback with the attribute handle of
ATT READ RESPONSE PENDING. When you’ve got the data for all requested
attributes ready, you can call att server response ready, which will trigger pro-
cessing of the current request. Please keep in mind that there is only one active
ATT operation and that it has a 30 second timeout after which the ATT server
is considered defunct by the GATT Client.

0.34.1. Implementing Standard GATT Services. Implementation of a standard


GATT Service consists of the following 4 steps:
1.Identify full Service Name
2.Use Service Name to fetch XML definition at Bluetooth SIG site and
convert into generic .gatt file
3. Edit .gatt file to set constant values and exclude unwanted Characteristics
4. Implement Service server, e.g., battery service server.c
Step 1:
To facilitate the creation of .gatt files for standard profiles defined by the
Bluetooth SIG, the tool/convert gatt service.py script can be used. When run
without a parameter, it queries the Bluetooth SIG website and lists the available
Services by their Specification Name, e.g., org.bluetooth.service.battery service.

$ t o o l / c o n v e r t g a t t s e r v i c e . py
F e t c h i n g l i s t o f s e r v i c e s from h t t p s : //www. b l u e t o o t h . com/
specifications / gatt / services

S p e c i f i c a t i o n Type |
S p e c i f i c a t i o n Name | UUID
67

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

org . bluetooth . s e r v i c e . a l e r t n o t i f i c a t i o n | Alert


Notification Service | 0 x1811
org . bluetooth . s e r v i c e . automation io | Automation
IO | 0 x1815
org . bluetooth . s e r v i c e . b a t t e r y s e r v i c e | Battery
Service | 0 x180F
...
org . bluetooth . s e r v i c e . w e i g h t s c a l e | Weight
Scale | 0x181D

To c o n v e r t a s e r v i c e i n t o a . g a t t f i l e template , p l e a s e c a l l t h e
s c r i p t a g a i n with t h e r e q u e s t e d S p e c i f i c a t i o n Type and t h e
output f i l e name
Usage : t o o l / c o n v e r t g a t t s e r v i c e . py SPECIFICATION TYPE [ s e r v i c e n a m e
. gatt ]

Step 2:
To convert service into .gatt file, call *tool/convert gatt service.py with the
requested Specification Type and the output file name.

$ t o o l / c o n v e r t g a t t s e r v i c e . py o r g . b l u e t o o t h . s e r v i c e . b a t t e r y s e r v i c e
battery service . gatt
F e t c h i n g o r g . b l u e t o o t h . s e r v i c e . b a t t e r y s e r v i c e from
h t t p s : //www. b l u e t o o t h . com/ a p i / g a t t / x m l f i l e ? xmlFileName=o r g . b l u e t o o t h
. s e r v i c e . b a t t e r y s e r v i c e . xml

S e r v i c e Battery S e r v i c e
− C h a r a c t e r i s t i c B a t t e r y L e v e l − p r o p e r t i e s [ ’ Read ’ , ’ N o t i f y ’ ]
−− D e s c r i p t o r C h a r a c t e r i s t i c P r e s e n t a t i o n Format − TODO:
Please set values
−− D e s c r i p t o r C l i e n t C h a r a c t e r i s t i c C o n f i g u r a t i o n

Service s u c c e s s f u l l y converted into b a t t e r y s e r v i c e . gatt


P l e a s e check f o r TODOs i n t h e . g a t t f i l e

Step 3:
In most cases, you will need to customize the .gatt file. Please pay attention
to the tool output and have a look at the generated .gatt file.
E.g. in the generated .gatt file for the Battery Service

// S p e c i f i c a t i o n Type o r g . b l u e t o o t h . s e r v i c e . b a t t e r y s e r v i c e
// h t t p s : / /www. b l u e t o o t h . com/ a p i / g a t t / x m l f i l e ? xmlFileName=o r g .
b l u e t o o t h . s e r v i c e . b a t t e r y s e r v i c e . xml

// B a t t e r y S e r v i c e 180F
PRIMARY SERVICE, ORG BLUETOOTH SERVICE BATTERY SERVICE
CHARACTERISTIC, ORG BLUETOOTH CHARACTERISTIC BATTERY LEVEL, DYNAMIC
| READ | NOTIFY,
68

// TODO: C h a r a c t e r i s t i c P r e s e n t a t i o n Format : p l e a s e s e t v a l u e s
#TODO CHARACTERISTIC FORMAT, READ, f o r m a t , e x p o n e n t , u n i t ,
name space , d e s c r i p t i o n
CLIENT CHARACTERISTIC CONFIGURATION, READ | WRITE,

you could delete the line regarding the CHARACTERISTIC FORMAT, since
it’s not required if there is a single instance of the service. Please compare the
.gatt file against the Adopted Specifications.
Step 4:
As described above all read/write requests are handled by the application. To
implement the new services as a reusable module, it’s necessary to get access to
all read/write requests related to this service.
For this, the ATT DB allows to register read/write callbacks for a specific
handle range with att server register service handler().
Since the handle range depends on the application’s .gatt file, the handle range
for Primary and Secondary Services can be queried with gatt server get get handle range for service
Similarly, you will need to know the attribute handle for particular Charac-
teristics to handle Characteristic read/writes requests. You can get the attribute
value handle for a Characteristics gatt server get value handle for characteristic with uuid16().
In addition to the attribute value handle, the handle for the Client Characteris-
tic Configuration is needed to support Indications/Notifications. You can get this
attribute handle with gatt server get client configuration handle for characteristic with uuid16()
Finally, in order to send Notifications and Indications independently from
the main application, att server register can send now callback can be used to
request a callback when it’s possible to send a Notification or Indication.
To see how this works together, please check out the Battery Service Server in
src/ble/battery service server.c.

0.34.2. GATT Database Hash. When a GATT Client connects to a GATT Server,
it cannot know if the GATT Database has changed and has to discover the pro-
vided GATT Services and Characteristics after each connect.
To speed this up, the Bluetooth specification defines a GATT Service Changed
Characteristic, with the idea that a GATT Server would notify a bonded GATT
Client if its database changed. However, this is quite fragile and it is not clear
how it can be implemented in a robust way.
The Bluetooth Core Spec 5.1 introduced the GATT Database Hash Charac-
teristic, which allows for a simple robust mechanism to cache a remote GATT
Database. The GATT Database Hash is a 16-byte value that is calculated over
the list of Services and Characteristics. If there is any change to the database,
the hash will change as well.
To support this on the GATT Server, you only need to add a GATT Service
with the GATT Database Characteristic to your .gatt file. The hash value is
then calculated by the GATT compiler.

PRIMARY SERVICE, GATT SERVICE


CHARACTERISTIC, GATT DATABASE HASH, READ,
69

Note: make sure to install the PyCryptodome python package as the hash is
calculated using AES-CMAC, e.g. with:

p i p i n s t a l l pycryptodomex

#Implemented GATT Services


BTstack allows to implement and use GATT Services in a modular way.
To use an already implemented GATT Service Server, you only have to add it
to your application’s GATT file with: - #import <service name.gatt> for .gatt files
located in src/ble/gatt-service - #import ”service name.gatt” for .gatt files located
in the same folder as your application’s .gatt file.
Each service will have an API at src/ble/gatt-service/service name server.h.
To activate it, you need to call service name init(..).
Please see the .h file for details.
0.35. Battery Service Server. The Battery Service allows to query your de-
vice’s battery level in a standardized way.
To use with your application, add #import <battery service.gatt> to your .gatt
file. After adding it to your .gatt file, you call battery service server init(value)
with the current value of your battery. The valid range for the battery level is
0-100.
If the battery level changes, you can call battery service server set battery value(value).
The service supports sending Notifications if the client enables them.
See Battery Service Server API.
0.36. Bond Management Service Server. The Bond Management service
server defines how a peer Bluetooth device can manage the storage of bond
information, especially the deletion of it, on the Bluetooth device supporting
this service.
To use with your application, add #import <bond management service.gatt> to
your .gatt file. After adding it to your .gatt file, you call bond management service server init(suppor
The input parameter “supported features” is a bitmap, which defines how the
bond information will be deleted, see BMF DELETE * flags below.
See Bond Management Service Server API.
0.37. Cycling Power Service Server. The Cycling Power Service allows to
query device’s power- and force-related data and optionally speed- and cadence-
related data for use in sports and fitness applications.
To use with your application, add #import <cycling power service.gatt> to your
.gatt file.
See Cycling Power Service Server API.
0.38. Cycling Speed and Cadence Service Server. The Cycling Speed and
Cadence Service allows to query device’s speed- and cadence-related data for use
in sports and fitness applications.
To use with your application, add #import <cycling speed and cadence service.gatt
> to your .gatt file.
See Cycling Speed and Cadence Service Server API.
70

0.39. Device Information Service Server. Th eDevice Information Service


allows to query manufacturer and/or vendor information about a device.
To use with your application, add #import <device information service.gatt> to
your .gatt file.
Note: instead of calling all setters, you can create a local copy of the .gatt
file and remove all Characteristics that are not relevant for your application and
define all fixed values in the .gatt file.
See Device Information Service Server API.

0.40. Heart Rate Service Server. The heart rate service server provides heart
rate measurements via notifications.
Each notification reports the heart rate measurement in beats per minute, and
if enabled, the total energy expended in kilo Joules, as well as RR-intervals in
1/1024 seconds resolution.
The Energy Expended field represents the accumulated energy expended in
kilo Joules since the last time it was reset. If the maximum value of 65535 kilo
Joules is reached, it will remain at this value, until a reset command from the
client is received.
The RR-Interval represents the time between two consecutive R waves in an
Electrocardiogram (ECG) waveform. If needed, the RR-Intervals are sent in
multiple notifications.
To use with your application, add #import <heart rate service.gatt> to your .gatt
file. After adding it to your .gatt file, you call heart rate server init(body sensor location,
energy expended supported) with the intended sensor location, and a flag indicat-
ing if energy expanded is supported.
If heart rate measurement changes, you can call heart rate service server update heart rate values(
service sensor contact status, rr interval count, rr intervals). This function will
trigger sending Notifications if the client enables them.
If energy expanded is supported, you can call heart rate service add energy expended(energy expen
with the newly expanded energy. The accumulated energy expended value will
be emitted with the next heart rate measurement.
See Heart Rate Service Server API.

0.41. HIDS Device. Implementation of the GATT HIDS Device To use with
your application, add ‘#import <hids.gatt>’ to your .gatt file
See HIDS Device API.

0.42. Nordic SPP Service Server. The Nordic SPP Service is implementation
of the Nordic SPP-like profile.
To use with your application, add #import <nordic spp service.gatt> to your .gatt
file and call all functions below. All strings and blobs need to stay valid after
calling the functions.
See Nordic SPP Service Server API.

0.43. Scan Parameters Service Server. The Scan Parameters Service enables
a remote GATT Client to store the LE scan parameters it is using locally. These
parameters can be utilized by the application to optimize power consumption
and/or reconnection latency.
71

To use with your application, add #import <scan parameters service.gatt> to your
.gatt file and call all functions below. All strings and blobs need to stay valid
after calling the functions.
See Scan Parameters Service Server API.
0.44. Tx Power Service Server. The TX Power service exposes a device’s
current transmit power level when in a connection. There shall only be one
instance of the Tx Power service on a device.
To use with your application, add #import <tx power service.gatt> to your .gatt
file. After adding it to your .gatt file, you call tx power service server init(value)
with the device’s current transmit power level value.
If the power level value changes, you can call tx power service server set level(tx power level dBm)
The service does not support sending Notifications.
See Tx Power Service Server API.
0.45. u-blox SPP Service Server. The u-blox SPP Service is implementation
of the u-Blox SPP-like profile.
To use with your application, add #import <ublox spp service.gatt> to your .gatt
file and call all functions below. All strings and blobs need to stay valid after
calling the functions.
See u-blox SPP Service Server API.
#Implemented GATT Clients
BTstack allows to implement and use GATT Clients in a modular way.
0.46. ANCS Client. The ANCS Client implements Notification Consumer (NC)
of the Apple Notification Center Service (ANCS).
See ANCS Client API.
0.47. Battery Service Client. The Battery Service Client connects to the Bat-
tery Services of a remote device and queries its battery level values. Level updates
are either received via notifications (if supported by the remote Battery Service),
or by manual polling.
See Battery Service Client API.
0.48. Device Information Service Client. The Device Information Service
Client retrieves the following information from a remote device: - manufacturer
name- model number - serial number - hardware revision- firmware revision-
software revision- system ID - IEEE regulatory certification- PNP ID
See Device Information Service Client API.
0.49. HIDS Client. The HID Service Client is used on the HID Host to receive
reports and other HID data.
See HIDS Client API.
0.50. Scan Parameters Service Client. The Scan Parameters Service Client
allows to store its LE scan parameters on a remote device such that the re-
mote device can utilize this information to optimize power consumption and/or
reconnection latency.
See Scan Parameters Service Client API.
#Examples
72

In this section, we will describe a number of examples from the example folder.
Here is a list of existing examples:
• Hello World example:
– led counter: Hello World - Blinking an LED without Bluetooth.
• GAP examples:
– gap inquiry: GAP Classic Inquiry.
– gap link keys: GAP Link Key Management (Classic).
• Low Energy examples:
– gap le advertisements: GAP LE Advertisements Scanner.
– gatt browser: GATT Client - Discover Primary Services.
– gatt counter: GATT Server - Heartbeat Counter over GATT.
– gatt streamer server: Performance - Stream Data over GATT (Server).
– gatt battery query: GATT Battery Service Client.
– gatt device information query: GATT Device Information Service
Client.
– gatt heart rate client: GATT Heart Rate Sensor Client .
– nordic spp le counter: LE Nordic SPP-like Heartbeat Server .
– nordic spp le streamer: LE Nordic SPP-like Streamer Server .
– ublox spp le counter: LE u-blox SPP-like Heartbeat Server.
– sm pairing central: LE Central - Test Pairing Methods.
– sm pairing peripheral: LE Peripheral - Test Pairing Methods.
– le credit based flow control mode client: LE Credit-Based Flow-Control
Mode Client - Send Data over L2CAP.
– le credit based flow control mode server: LE Credit-Based Flow-Control
Mode Server - Receive data over L2CAP.
– att delayed response: LE Peripheral - Delayed Response.
– ancs client demo: LE ANCS Client - Apple Notification Service.
– le mitm: LE Man-in-the-Middle Tool.
• Performance examples:
– le streamer client: Performance - Stream Data over GATT (Client).
– gatt streamer server: Performance - Stream Data over GATT (Server).
– le credit based flow control mode client: LE Credit-Based Flow-Control
Mode Client - Send Data over L2CAP.
– le credit based flow control mode server: LE Credit-Based Flow-Control
Mode Server - Receive data over L2CAP.
– spp streamer client: Performance - Stream Data over SPP (Client).
– spp streamer: Performance - Stream Data over SPP (Server).
• Audio examples:
– a2dp sink demo: A2DP Sink - Receive Audio Stream and Control
Playback.
– a2dp source demo: A2DP Source - Stream Audio and Control Vol-
ume.
– avrcp browsing client: AVRCP Browsing - Browse Media Players
and Media Information.
– hfp ag demo: HFP AG - Audio Gateway.
– hfp hf demo: HFP HF - Hands-Free.
– hsp ag demo: HSP AG - Audio Gateway.
73

– hsp hs demo: HSP HS - Headset.


– sine player: Audio Driver - Play Sine .
– mod player: Audio Driver - Play 80’s MOD Song.
– audio duplex: Audio Driver - Forward Audio from Source to Sink.
• SPP Server examples:
– spp counter: SPP Server - Heartbeat Counter over RFCOMM.
– spp flowcontrol: SPP Server - RFCOMM Flow Control.
• Networking examples:
– pan lwip http server: PAN - lwIP HTTP and DHCP Server .
– panu demo: BNEP/PANU (Linux only).
• HID examples:
– hid keyboard demo: HID Keyboard Classic.
– hid mouse demo: HID Mouse Classic.
– hid host demo: HID Host Classic.
– hog keyboard demo: HID Keyboard LE.
– hog mouse demo: HID Mouse LE.
– hog boot host demo: HID Boot Host LE.
• Dual Mode examples:
– spp and gatt counter: Dual Mode - SPP and LE Counter.
– gatt streamer server: Performance - Stream Data over GATT (Server).
• SDP Queries examples:
– sdp general query: SDP Client - Query Remote SDP Records.
– sdp rfcomm query: SDP Client - Query RFCOMM SDP record.
– sdp bnep query: SDP Client - Query BNEP SDP record.
• Phone Book Access example:
– pbap client demo: PBAP Client - Get Contacts from Phonebook
Server.
• Testing example:
– dut mode classic: Testing - Enable Device Under Test (DUT) Mode
for Classic.
0.51. Hello World - Blinking an LED without Bluetooth. Source Code:
led counter.c
The example demonstrates how to provide a periodic timer to toggle an LED
and send debug messages to the console as a minimal BTstack test.
0.51.1. Periodic Timer Setup. As timers in BTstack are single shot, the peri-
odic counter is implemented by re-registering the timer source in the heartbeat
handler callback function. Listing here shows heartbeat handler adapted to pe-
riodically toggle an LED and print number of toggles.

s t a t i c void h e a r t b e a t h a n d l e r ( btstack timer source t ∗ t s ) {


UNUSED( t s ) ;

// i n c r e m e n t c o u n t e r
c o u n t e r ++;

// p r i n t and l o g
74

l o g i n f o ( ” BTstack Counter %u” , counter ) ;


p r i n t f ( ” BTstack c o u n t e r %04u\n\ r ” , c o u n t e r ) ;

// t o g g l e LED
hal led toggle () ;

// re−r e g i s t e r t i m e r
b t s t a c k r u n l o o p s e t t i m e r (& h e a r t b e a t , HEARTBEAT PERIOD MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& h e a r t b e a t ) ;
}

0.51.2. Main Application Setup. Listing here shows main application code. It
configures the heartbeat tier and adds it to the run loop.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// s e t one−s h o t t i m e r
h e a r t b e a t . p r o c e s s = &h e a r t b e a t h a n d l e r ;
b t s t a c k r u n l o o p s e t t i m e r (& h e a r t b e a t , HEARTBEAT PERIOD MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& h e a r t b e a t ) ;

p r i n t f ( ” Running . . . \ n\ r ” ) ;
return 0 ;
}

0.52. GAP Classic Inquiry. Source Code: gap inquiry.c


The Generic Access Profile (GAP) defines how Bluetooth devices discover and
establish a connection with each other. In this example, the application discovers
surrounding Bluetooth devices and collects their Class of Device (CoD), page
scan mode, clock offset, and RSSI. After that, the remote name of each device is
requested. In the following section we outline the Bluetooth logic part, i.e., how
the packet handler handles the asynchronous events and data packets.

0.52.1. Bluetooth Logic. The Bluetooth logic is implemented as a state machine


within the packet handler. In this example, the following states are passed
sequentially: INIT, and ACTIVE.
In INIT, an inquiry scan is started, and the application transits to ACTIVE
state.
In ACTIVE, the following events are processed:
• GAP Inquiry result event: BTstack provides a unified inquiry result that
contain Class of Device (CoD), page scan mode, clock offset. RSSI and
name (from EIR) are optional.
75

• Inquiry complete event: the remote name is requested for devices with-
out a fetched name. The state of a remote name can be one of the fol-
lowing: REMOTE NAME REQUEST, REMOTE NAME INQUIRED,
or REMOTE NAME FETCHED.
• Remote name request complete event: the remote name is stored in the
table and the state is updated to REMOTE NAME FETCHED. The
query of remote names is continued.
For more details on discovering remote devices, please see Section on
GAP.
0.52.2. Main Application Setup. Listing here shows main application code. It
registers the HCI packet handler and starts the Bluetooth stack.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// e n a b l e d EIR
h c i s e t i n q u i r y m o d e (INQUIRY MODE RSSI AND EIR) ;

h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;

return 0 ;
}

0.53. GAP Link Key Management (Classic). Source Code: gap link keys.c
Shows how to iterate over the Classic Link Keys stored in NVS Link Keys are
per device-device bonding. If the Bluetooth Controller can be swapped, e.g. on
desktop systems, a Link Key DB for each Controller is needed. We need to wait
until the Bluetooth Stack has started up and selected the correct Link Key DB
based on the Controller’s BD ADDR.
0.53.1. GAP Link Key Logic. List stored link keys
0.53.2. Bluetooth Logic. Wait for Bluetooth startup before listing the stored link
keys
0.53.3. Main Application Setup. Listing here shows main application code. It
registers the HCI packet handler and starts the Bluetooth stack.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;
76

h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;

return 0 ;
}

0.54. GAP LE Advertisements Scanner. Source Code: gap le advertisements.c


This example shows how to scan and parse advertisements.
0.54.1. GAP LE setup for receiving advertisements. GAP LE advertisements are
received as custom HCI events of the GAP EVENT ADVERTISING REPORT
type. To receive them, you’ll need to register the HCI packet handler, as shown
in Listing here.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void g a p l e a d v e r t i s e m e n t s s e t u p ( void ) {
// A c t i v e scanning , 100% ( scan i n t e r v a l = scan window )
gap set scan parameters (1 ,48 ,48) ;
gap start scan () ;

h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
}

0.54.2. GAP LE Advertising Data Dumper. Here, we use the definition of ad-
vertising data types and flags as specified in Assigned Numbers GAP and Sup-
plement to the Bluetooth Core Specification, v4.

s t a t i c const char ∗ a d t y p e s [ ] = {
”” ,
” Flags ” ,
” I n c o m p l e t e L i s t o f 16− b i t S e r v i c e C l a s s UUIDs” ,
” Complete L i s t o f 16− b i t S e r v i c e C l a s s UUIDs” ,
” I n c o m p l e t e L i s t o f 32− b i t S e r v i c e C l a s s UUIDs” ,
” Complete L i s t o f 32− b i t S e r v i c e C l a s s UUIDs” ,
” I n c o m p l e t e L i s t o f 128− b i t S e r v i c e C l a s s UUIDs” ,
” Complete L i s t o f 128− b i t S e r v i c e C l a s s UUIDs” ,
” S h o r t e n e d L o c a l Name” ,
” Complete L o c a l Name” ,
”Tx Power L e v e l ” ,
”” ,
”” ,
” C l a s s o f D e vi ce ” ,
77

” Simple P a i r i n g Hash C” ,
” Simple P a i r i n g Randomizer R” ,
” De vi c e ID” ,
” S e c u r i t y Manager TK Value ” ,
” S l a v e Connection I n t e r v a l Range” ,
”” ,
” L i s t o f 16− b i t S e r v i c e S o l i c i t a t i o n UUIDs” ,
” L i s t o f 128− b i t S e r v i c e S o l i c i t a t i o n UUIDs” ,
” S e r v i c e Data” ,
” P u b l i c Target Address ” ,
”Random Target Address ” ,
” Appearance ” ,
” Advertising Interval ”
};

s t a t i c const char ∗ f l a g s [ ] = {
”LE L im i te d D i s c o v e r a b l e Mode” ,
”LE G e n e r a l D i s c o v e r a b l e Mode” ,
”BR/EDR Not Supported ” ,
” S i m u l t a n e o u s LE and BR/EDR t o Same De v ic e Capable ( C o n t r o l l e r ) ” ,
” S i m u l t a n e o u s LE and BR/EDR t o Same De v ic e Capable ( Host ) ” ,
” Reserved ” ,
” Reserved ” ,
” Reserved ”
};

BTstack offers an iterator for parsing sequence of advertising data (AD) struc-
tures, see BLE advertisements parser API. After initializing the iterator, each
AD structure is dumped according to its type.

s t a t i c void d u m p a d v e r t i s e m e n t d a t a ( const uint8 t ∗ adv data ,


uint8 t a d v s i z e ) {
ad context t context ;
bd addr t a d d r e s s ;
uint8 t u u i d 1 2 8 [ 1 6 ] ;
f o r ( a d i t e r a t o r i n i t (& c o n t e x t , a d v s i z e , ( uint8 t ∗ ) a d v d a t a ) ;
a d i t e r a t o r h a s m o r e (& c o n t e x t ) ; a d i t e r a t o r n e x t (& c o n t e x t ) ) {
uint8 t d a t a t y p e = a d i t e r a t o r g e t d a t a t y p e (& c o n t e x t ) ;
uint8 t s i z e = a d i t e r a t o r g e t d a t a l e n (& c o n t e x t ) ;
const uint8 t ∗ data = a d i t e r a t o r g e t d a t a (& c o n t e x t ) ;

i f ( d a t a t y p e > 0 && d a t a t y p e < 0x1B ) {


p r i n t f ( ” %s : ” , a d t y p e s [ d a t a t y p e ] ) ;
}
int i ;
// A s s i g n e d Numbers GAP

switch ( d a t a t y p e ) {
case BLUETOOTH DATA TYPE FLAGS:
// show o n l y f i r s t o c t e t , i g n o r e r e s t
f o r ( i =0; i <8; i ++){
i f ( data [ 0 ] & (1<< i ) ) {
78

p r i n t f ( ”%s ; ” , f l a g s [ i ] ) ;
}

}
break ;
case
BLUETOOTH DATA TYPE INCOMPLETE LIST OF 16 BIT SERVICE CLASS UUIDS
:
case
BLUETOOTH DATA TYPE COMPLETE LIST OF 16 BIT SERVICE CLASS UUIDS
:
case
BLUETOOTH DATA TYPE LIST OF 16 BIT SERVICE SOLICITATION UUIDS
:
f o r ( i =0; i <s i z e ; i +=2){
p r i n t f ( ”%02X ” , l i t t l e e n d i a n r e a d 1 6 ( data , i ) ) ;
}
break ;
case
BLUETOOTH DATA TYPE INCOMPLETE LIST OF 32 BIT SERVICE CLASS UUIDS
:
case
BLUETOOTH DATA TYPE COMPLETE LIST OF 32 BIT SERVICE CLASS UUIDS
:
case
BLUETOOTH DATA TYPE LIST OF 32 BIT SERVICE SOLICITATION UUIDS
:
f o r ( i =0; i <s i z e ; i +=4){
p r i n t f ( ”%04”PRIX32 , l i t t l e e n d i a n r e a d 3 2 ( data , i ) ) ;
}
break ;
case
BLUETOOTH DATA TYPE INCOMPLETE LIST OF 128 BIT SERVICE CLASS UUIDS
:
case
BLUETOOTH DATA TYPE COMPLETE LIST OF 128 BIT SERVICE CLASS UUIDS
:
case
BLUETOOTH DATA TYPE LIST OF 128 BIT SERVICE SOLICITATION UUIDS
:
r e v e r s e 1 2 8 ( data , u u i d 1 2 8 ) ;
p r i n t f ( ”%s ” , u u i d 1 2 8 t o s t r ( u u i d 1 2 8 ) ) ;
break ;
case BLUETOOTH DATA TYPE SHORTENED LOCAL NAME:
case BLUETOOTH DATA TYPE COMPLETE LOCAL NAME:
f o r ( i =0; i <s i z e ; i ++){
p r i n t f ( ”%c ” , ( char ) ( data [ i ] ) ) ;
}
break ;
case BLUETOOTH DATA TYPE TX POWER LEVEL:
p r i n t f ( ”%d dBm” , ∗ ( i n t 8 t ∗ ) data ) ;
break ;
case BLUETOOTH DATA TYPE SLAVE CONNECTION INTERVAL RANGE:
79

p r i n t f ( ” Connection I n t e r v a l Min = %u ms , Max = %u ms” ,


l i t t l e e n d i a n r e a d 1 6 ( data , 0 ) ∗ 5 / 4 ,
l i t t l e e n d i a n r e a d 1 6 ( data , 2 ) ∗ 5 / 4 ) ;
break ;
case BLUETOOTH DATA TYPE SERVICE DATA:
p r i n t f h e x d u m p ( data , s i z e ) ;
break ;
case BLUETOOTH DATA TYPE PUBLIC TARGET ADDRESS :
case BLUETOOTH DATA TYPE RANDOM TARGET ADDRESS:
r e v e r s e b d a d d r ( data , a d d r e s s ) ;
p r i n t f ( ”%s ” , b d a d d r t o s t r ( a d d r e s s ) ) ;
break ;
case BLUETOOTH DATA TYPE APPEARANCE:
// h t t p s : / / d e v e l o p e r . b l u e t o o t h . o r g / g a t t / c h a r a c t e r i s t i c s /
Pages / C h a r a c t e r i s t i c V i e w e r . a s p x ?u=o r g . b l u e t o o t h .
c h a r a c t e r i s t i c . gap . appearance . xml
p r i n t f ( ”%02X” , l i t t l e e n d i a n r e a d 1 6 ( data , 0 ) ) ;
break ;
case BLUETOOTH DATA TYPE ADVERTISING INTERVAL :
p r i n t f ( ”%u ms” , l i t t l e e n d i a n r e a d 1 6 ( data , 0 ) ∗ 5/8 ) ;
break ;
case BLUETOOTH DATA TYPE 3D INFORMATION DATA:
p r i n t f h e x d u m p ( data , s i z e ) ;
break ;
case BLUETOOTH DATA TYPE MANUFACTURER SPECIFIC DATA: //
Manufacturer S p e c i f i c Data
break ;
case BLUETOOTH DATA TYPE CLASS OF DEVICE :
case BLUETOOTH DATA TYPE SIMPLE PAIRING HASH C :
case BLUETOOTH DATA TYPE SIMPLE PAIRING RANDOMIZER R :
case BLUETOOTH DATA TYPE DEVICE ID :
case BLUETOOTH DATA TYPE SECURITY MANAGER OUT OF BAND FLAGS:
default :
p r i n t f ( ” A d v e r t i s i n g Data Type 0x%2x not handled y e t ” ,
data type ) ;
break ;
}
p r i n t f ( ” \n” ) ;
}
p r i n t f ( ” \n” ) ;
}

0.54.3. HCI packet handler. The HCI packet handler has to start the scanning,
and to handle received advertisements. Advertisements are received as HCI event
packets of the GAP EVENT ADVERTISING REPORT type, see Listing here.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;


80

bd addr t a d d r e s s ;
uint8 t a d d r e s s t y p e ;
uint8 t e v e n t t y p e ;
int8 t rssi ;
uint8 t l e n g t h ;
const uint8 t ∗ data ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case GAP EVENT ADVERTISING REPORT :
g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s ( packet , a d d r e s s ) ;
event type =
gap event advertising report get advertising event type (
packet ) ;
address type = gap event advertising report get address type (
packet ) ;
r s s i = g a p e v e n t a d v e r t i s i n g r e p o r t g e t r s s i ( packet ) ;
length = g a p e v e n t a d v e r t i s i n g r e p o r t g e t d a t a l e n g t h ( packet ) ;
data = g a p e v e n t a d v e r t i s i n g r e p o r t g e t d a t a ( p a c k e t ) ;
p r i n t f ( ” A d v e r t i s e m e n t ( l e g a c y ) e v e n t : evt−type %u , addr−type %
u , addr %s , r s s i %d , data [%u ] ” , e v e n t t y p e ,
address type , bd addr to str ( address ) , r s s i , length ) ;
p r i n t f h e x d u m p ( data , l e n g t h ) ;
d u m p a d v e r t i s e m e n t d a t a ( data , l e n g t h ) ;
break ;
#i f d e f ENABLE LE EXTENDED ADVERTISING
case GAP EVENT EXTENDED ADVERTISING REPORT:
g a p e v e n t e x t e n d e d a d v e r t i s i n g r e p o r t g e t a d d r e s s ( packet ,
address ) ;
event type =
gap event extended advertising report get advertising event type
( packet ) ;
address type =
gap event extended advertising report get address type (
packet ) ;
r s s i = g a p e v e n t e x t e n d e d a d v e r t i s i n g r e p o r t g e t r s s i ( packet ) ;
length = gap event extended advertising report get data length
( packet ) ;
data = g a p e v e n t e x t e n d e d a d v e r t i s i n g r e p o r t g e t d a t a ( p a c k e t ) ;
p r i n t f ( ” A d v e r t i s e m e n t ( extended ) e v e n t : evt−type %u , addr−type
%u , addr %s , r s s i %d , data [%u ] ” , e v e n t t y p e ,
address type , bd addr to str ( address ) , r s s i , length ) ;
p r i n t f h e x d u m p ( data , l e n g t h ) ;
d u m p a d v e r t i s e m e n t d a t a ( data , l e n g t h ) ;
break ;
#endif
default :
break ;
}
}

0.55. GATT Client - Discover Primary Services. Source Code: gatt browser.c
81

This example shows how to use the GATT Client API to discover primary
services and their characteristics of the first found device that is advertising its
services.
The logic is divided between the HCI and GATT client packet handlers. The
HCI packet handler is responsible for finding a remote device, connecting to it,
and for starting the first GATT client query. Then, the GATT client packet
handler receives all primary services and requests the characteristics of the last
one to keep the example short.

0.55.1. GATT client setup. In the setup phase, a GATT client must register the
HCI and GATT client packet handlers, as shown in Listing here. Additionally,
the security manager can be setup, if signed writes, or encrypted, or authen-
ticated connection are required, to access the characteristics, as explained in
Section on SMP.

// Handles connect , d i s c o n n e c t , and a d v e r t i s i n g r e p o r t e v e n t s ,


// s t a r t s t h e GATT c l i e n t , and s e n d s t h e f i r s t q u e r y .
s t a t i c void h a n d l e h c i e v e n t ( uint8 t p a c k e t t y p e , uint16 t channel ,
uint8 t ∗ packet , uint16 t s i z e ) ;

// Handles GATT c l i e n t q u e r y r e s u l t s , s e n d s q u e r i e s and t h e


// GAP d i s c o n n e c t command when t h e q u e r y i n g i s done .
s t a t i c void h a n d l e g a t t c l i e n t e v e n t ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void g a t t c l i e n t s e t u p ( void ) {

// I n i t i a l i z e L2CAP and r e g i s t e r HCI e v e n t h a n d l e r


l2cap init () ;

// I n i t i a l i z e GATT c l i e n t
g a t t c l i e n t i n i t () ;

// O p t i n o a l l y , Se t up s e c u r i t y manager
sm init () ;
s m s e t i o c a p a b i l i t i e s (IO CAPABILITY NO INPUT NO OUTPUT) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h a n d l e h c i e v e n t ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
}

0.55.2. HCI packet handler. The HCI packet handler has to start the scanning,
to find the first advertising device, to stop scanning, to connect to and later to dis-
connect from it, to start the GATT client upon the connection is completed, and
to send the first query - in this case the gatt client discover primary services()
is called, see Listing here.
82

s t a t i c void h a n d l e h c i e v e n t ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;


advertising report t r e p o r t ;

uint8 t e v e n t = h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ;
switch ( e v e n t ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
i f ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) != HCI STATE WORKING
) break ;
i f ( cmdline addr found ) {
p r i n t f ( ” Trying t o c o n n e c t t o %s \n” , b d a d d r t o s t r (
cmdline addr ) ) ;
gap connect ( cmdline addr , 0) ;
break ;
}
p r i n t f ( ” BTstack a c t i v a t e d , s t a r t s c a n n i n g ! \ n” ) ;
g a p s e t s c a n p a r a m e t e r s ( 0 , 0 x0030 , 0 x0030 ) ;
gap start scan () ;
break ;
case GAP EVENT ADVERTISING REPORT :
f i l l a d v e r t i s i n g r e p o r t f r o m p a c k e t (& r e p o r t , p a c k e t ) ;
d u m p a d v e r t i s i n g r e p o r t (& r e p o r t ) ;

// s t o p scanning , and c o n n e c t t o t h e d e v i c e
gap stop scan () ;
gap connect ( report . address , report . address type ) ;
break ;
case HCI EVENT META GAP :
// w a i t f o r c o n n e c t i o n c o m p l e t e
i f ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) !=
GAP SUBEVENT LE CONNECTION COMPLETE) break ;
p r i n t f ( ” \nGATT b r o w s e r − CONNECTED\n” ) ;
connection handle =
gap subevent le connection complete get connection handle (
packet ) ;
// q u e r y primary s e r v i c e s
gatt client discover primary services ( handle gatt client event
, connection handle ) ;
break ;
case HCI EVENT DISCONNECTION COMPLETE :
p r i n t f ( ” \nGATT b r o w s e r − DISCONNECTED\n” ) ;
break ;
default :
break ;
}
}
83

0.55.3. GATT Client event handler. Query results and further queries are han-
dled by the GATT client packet handler, as shown in Listing here. Here, upon re-
ceiving the primary services, the gatt client discover characteristics for service()
query for the last received service is sent. After receiving the characteristics for
the service, gap disconnect is called to terminate the connection. Upon discon-
nect, the HCI packet handler receives the disconnect complete event.

s t a t i c void h a n d l e g a t t c l i e n t e v e n t ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( p a c k e t t y p e ) ;
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

gatt client service t s e r v i c e ;


gatt client characteristic t c h a r a c t e r i s t i c ;
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case GATT EVENT SERVICE QUERY RESULT :
g a t t e v e n t s e r v i c e q u e r y r e s u l t g e t s e r v i c e ( packet , &s e r v i c e ) ;
d u m p s e r v i c e (& s e r v i c e ) ;
s e r v i c e s [ s e r v i c e c o u n t ++] = s e r v i c e ;
break ;
case GATT EVENT CHARACTERISTIC QUERY RESULT :
gatt event characteristic query result get characteristic (
packet , &c h a r a c t e r i s t i c ) ;
d u m p c h a r a c t e r i s t i c (& c h a r a c t e r i s t i c ) ;
break ;
case GATT EVENT QUERY COMPLETE:
// GATT EVENT QUERY COMPLETE o f s e a r c h c h a r a c t e r i s t i c s
if ( service index < service count ) {
s e r v i c e = s e r v i c e s [ s e r v i c e i n d e x ++];
p r i n t f ( ” \nGATT br o w s e r − CHARACTERISTIC f o r SERVICE %s , [ 0 x
%04x−0x%04x ] \ n” ,
u u i d 1 2 8 t o s t r ( s e r v i c e . uuid128 ) , s e r v i c e .
start group handle , s e r v i c e . end group handle ) ;
gatt client discover characteristics for service (
h a n d l e g a t t c l i e n t e v e n t , c o n n e c t i o n h a n d l e , &s e r v i c e ) ;
break ;
}
service index = 0;
break ;
default :
break ;
}
}

0.56. GATT Server - Heartbeat Counter over GATT. Source Code: gatt counter.c
All newer operating systems provide GATT Client functionality. The LE
Counter examples demonstrates how to specify a minimal GATT Database with
a custom GATT Service and a custom Characteristic that sends periodic notifi-
cations.
84

0.56.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager and configures the ATT Server with
the pre-compiled ATT Database generated from lec ounter.gatt. Additionally,
it enables the Battery Service Server with the current battery level. Finally, it
configures the advertisements and the heartbeat handler and boots the Bluetooth
stack. In this example, the Advertisement contains the Flags attribute and
the device name. The flag 0x06 indicates: LE General Discoverable Mode and
BR/EDR not supported.

static int l e n o t i f i c a t i o n e n a b l e d ;
static btstack timer source t h e a r t b e a t ;
static btstack packet callback registration t
hci event callback registration ;
static hci con handle t con handle ;
static uint8 t b a t t e r y = 1 0 0 ;

#i f d e f ENABLE GATT OVER CLASSIC


s t a t i c uint8 t g a t t s e r v i c e b u f f e r [ 7 0 ] ;
#endif

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c uint16 t a t t r e a d c a l l b a c k ( h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t a t t h a n d l e , uint16 t o f f s e t , uint8 t ∗ b u f f e r , uint16 t
buffer size ) ;
s t a t i c int a t t w r i t e c a l l b a c k ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
a t t h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t o f f s e t , uint8 t
∗ b u f f e r , uint16 t b u f f e r s i z e ) ;
s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) ;
s t a t i c void b e a t ( void ) ;

// F l a g s g e n e r a l d i s c o v e r a b l e , BR/EDR s u p p o r t e d (== not s u p p o r t e d


f l a g not s e t ) when ENABLE GATT OVER CLASSIC i s e n a b l e d
#i f d e f ENABLE GATT OVER CLASSIC
#define APP AD FLAGS 0 x02
#e l s e
#define APP AD FLAGS 0 x06
#endif

const uint8 t a d v d a t a [ ] = {
// F l a g s g e n e r a l d i s c o v e r a b l e
0 x02 , BLUETOOTH DATA TYPE FLAGS, APP AD FLAGS,
// Name
0x0b , BLUETOOTH DATA TYPE COMPLETE LOCAL NAME, ’L ’ , ’E ’ , ’ ’ , ’C ’ ,
’o ’ , ’u ’ , ’n ’ , ’ t ’ , ’ e ’ , ’ r ’ ,
// I n c o m p l e t e L i s t o f 16− b i t S e r v i c e C l a s s UUIDs −− FF10 − o n l y
valid for testing !
0 x03 ,
BLUETOOTH DATA TYPE INCOMPLETE LIST OF 16 BIT SERVICE CLASS UUIDS
, 0 x10 , 0 x f f ,
};
const uint8 t a d v d a t a l e n = s i z e o f ( a d v d a t a ) ;
85

s t a t i c void l e c o u n t e r s e t u p ( void ) {

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

#i f d e f ENABLE GATT OVER CLASSIC


// i n i t SDP, c r e a t e r e c o r d f o r GATT and r e g i s t e r w i t h SDP
sdp init () ;
memset ( g a t t s e r v i c e b u f f e r , 0 , s i z e o f ( g a t t s e r v i c e b u f f e r ) ) ;
gatt create sdp record ( gatt service buffer ,
sdp create service record handle () ,
ATT SERVICE GATT SERVICE START HANDLE,
ATT SERVICE GATT SERVICE END HANDLE) ;
b t s t a c k a s s e r t ( d e g e t l e n ( g a t t s e r v i c e b u f f e r ) <= s i z e o f (
gatt service buffer )) ;
sdp register service ( gatt service buffer ) ;

// c o n f i g u r e C l a s s i c GAP
g a p s e t l o c a l n a m e ( ”GATT Counter BR/EDR 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap discoverable control (1) ;
#endif

// s e t u p ATT s e r v e r
att server init ( profile data , att read callback ,
att write callback ) ;

// s e t u p b a t t e r y s e r v i c e
b a t t e r y s e r v i c e s e r v e r i n i t ( battery ) ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r ATT e v e n t
att se rver re giste r pac ket han dler ( packet handler ) ;

// s e t one−s h o t t i m e r
h e a r t b e a t . p r o c e s s = &h e a r t b e a t h a n d l e r ;
b t s t a c k r u n l o o p s e t t i m e r (& h e a r t b e a t , HEARTBEAT PERIOD MS) ;
86

b t s t a c k r u n l o o p a d d t i m e r (& h e a r t b e a t ) ;

// b e a t once
beat ( ) ;
}

0.56.2. Heartbeat Handler. The heartbeat handler updates the value of the single
Characteristic provided in this example, and request a ATT EVENT CAN SEND NOW
to send a notification if enabled see Listing here.

s t a t i c int c o u n t e r = 0 ;
s t a t i c char c o u n t e r s t r i n g [ 3 0 ] ;
s t a t i c int c o u n t e r s t r i n g l e n ;

s t a t i c void b e a t ( void ) {
c o u n t e r ++;
counter string len = snprintf ( counter string , sizeof (
c o u n t e r s t r i n g ) , ” BTstack c o u n t e r %04u” , c o u n t e r ) ;
puts ( c o u n t e r s t r i n g ) ;
}

s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {
if ( le notification enabled ) {
beat ( ) ;
att server request can send now event ( con handle ) ;
}

// s i m u l a t e b a t t e r y d r a i n
b a t t e r y −−;
i f ( battery < 50) {
battery = 100;
}
b a t t e r y s e r v i c e s e r v e r s e t b a t t e r y v a l u e ( battery ) ;

b t s t a c k r u n l o o p s e t t i m e r ( t s , HEARTBEAT PERIOD MS) ;


btstack run loop add timer ( ts ) ;
}

0.56.3. Packet Handler. The packet handler is used to:


• stop the counter after a disconnect
• send a notification when the requested ATT EVENT CAN SEND NOW
is received

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;
87

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case HCI EVENT DISCONNECTION COMPLETE :
le notification enabled = 0;
break ;
case ATT EVENT CAN SEND NOW:
a t t s e r v e r n o t i f y ( con handle ,
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
, ( uint8 t ∗ ) c o u n t e r s t r i n g , c o u n t e r s t r i n g l e n ) ;
break ;
default :
break ;
}
}

0.56.4. ATT Read. The ATT Server handles all reads to constant data. For
dynamic data like the custom characteristic, the registered att read callback is
called. To handle long characteristics and long reads, the att read callback is
first called with buffer == NULL, to request the total value length. Then it will
be called again requesting a chunk of the value. See Listing here.

// ATT C l i e n t Read C a l l b a c k f o r Dynamic Data


// − i f b u f f e r == NULL, don ’ t copy data , j u s t r e t u r n s i z e o f v a l u e
// − i f b u f f e r != NULL, copy d a t a and r e t u r n number b y t e s c o p i e d
// @param o f f s e t d e f i n e s s t a r t o f a t t r i b u t e v a l u e
s t a t i c uint16 t a t t r e a d c a l l b a c k ( h c i c o n h a n d l e t c o n n e c t i o n h a n d l e
, uint16 t a t t h a n d l e , uint16 t o f f s e t , uint8 t ∗ b u f f e r ,
uint16 t b u f f e r s i z e ) {
UNUSED( c o n n e c t i o n h a n d l e ) ;

i f ( a t t h a n d l e ==
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
){
return a t t r e a d c a l l b a c k h a n d l e b l o b ( ( const uint8 t ∗ )
counter string , counter string len , offset , buffer ,
buffer size ) ;
}
return 0 ;
}

0.56.5. ATT Write. The only valid ATT writes in this example are to the Client
Characteristic Configuration, which configures notification and indication and to
the the Characteristic Value. If the ATT handle matches the client configuration
handle, the new configuration value is stored and used in the heartbeat handler to
decide if a new value should be sent. If the ATT handle matches the characteristic
value handle, we print the write as hexdump See Listing here.
88

s t a t i c int a t t w r i t e c a l l b a c k ( h c i c o n h a n d l e t c o n n e c t i o n h a n d l e ,
uint16 t a t t h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t o f f s e t ,
uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e ) {
switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
l e n o t i f i c a t i o n e n a b l e d = l i t t l e e n d i a n r e a d 1 6 ( b u f f e r , 0 ) ==
GATT CLIENT CHARACTERISTICS CONFIGURATION NOTIFICATION ;
con handle = connection handle ;
break ;
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
p r i n t f ( ” Write : t r a n s a c t i o n mode %u , o f f s e t %u , data (%u b y t e s )
: ” , transaction mode , o f f s e t , b u f f e r s i z e ) ;
printf hexdump ( buffer , b u f f e r s i z e ) ;
break ;
default :
break ;
}
return 0 ;
}

0.57. Performance - Stream Data over GATT (Server). Source Code:


gatt streamer server.c
All newer operating systems provide GATT Client functionality. This example
shows how to get a maximal throughput via BLE:
• send whenever possible,
• use the max ATT MTU.
In theory, we should also update the connection parameters, but we
already get a connection interval of 30 ms and there’s no public way to
use a shorter interval with iOS (if we’re not implementing an HID device).
Note: To start the streaming, run the example. On remote device use
some GATT Explorer, e.g. LightBlue, BLExplr to enable notifications.
0.57.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager, and configures the ATT Server with
the pre-compiled ATT Database generated from les treamer.gatt. Finally, it
configures the advertisements and boots the Bluetooth stack.

s t a t i c void l e s t r e a m e r s e t u p ( void ) {

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

#i f d e f ENABLE GATT OVER CLASSIC


// i n i t SDP, c r e a t e r e c o r d f o r GATT and r e g i s t e r w i t h SDP
89

sdp init () ;
memset ( g a t t s e r v i c e b u f f e r , 0 , s i z e o f ( g a t t s e r v i c e b u f f e r ) ) ;
g a t t c r e a t e s d p r e c o r d ( g a t t s e r v i c e b u f f e r , 0 x10001 ,
ATT SERVICE GATT SERVICE START HANDLE,
ATT SERVICE GATT SERVICE END HANDLE) ;
sdp register service ( gatt service buffer ) ;
p r i n t f ( ”SDP s e r v i c e r e c o r d s i z e : %u\n” , d e g e t l e n (
gatt service buffer )) ;

// c o n f i g u r e C l a s s i c GAP
g a p s e t l o c a l n a m e ( ”GATT Streamer BR/EDR 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap discoverable control (1) ;
#endif

// s e t u p ATT s e r v e r
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, a t t w r i t e c a l l b a c k ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r ATT e v e n t s
att server register packet handler ( att packet handler ) ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;

// i n i t c l i e n t s t a t e
init connections () ;
}

0.57.2. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

s t a t i c void t e s t r e s e t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k s e n t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t , int
bytes sent ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s s e n t ;
90

// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s s e n t −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.57.3. HCI Packet Handler. The packet handler is used track incoming connec-
tions and to stop notifications on disconnect It is also a good place to request
the connection parameter update as indicated in the commented code block.

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

uint16 t c o n n i n t e r v a l ;
hci con handle t con handle ;
s t a t i c const char ∗ const phy names [ ] = {
” Reserved ” , ” 1 M” , ” 2 M” , ” Codec ”
};

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
) {
p r i n t f ( ”To s t a r t t h e s t r e a m i n g , p l e a s e run t h e
l e s t r e a m e r c l i e n t example on o t h e r d e v i c e , o r u s e some
GATT E x p l o r e r , e . g . LightBlue , BLExplr . \ n” ) ;
}
break ;
case HCI EVENT DISCONNECTION COMPLETE :
con handle =
hci event disconnection complete get connection handle (
packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : d i s c o n n e c t , r e a s o n %02x\n” ,
con handle , h c i e v e n t d i s c o n n e c t i o n c o m p l e t e g e t r e a s o n (
packet ) ) ;
break ;
case HCI EVENT META GAP :
91

switch ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GAP SUBEVENT LE CONNECTION COMPLETE:
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
gap subevent le connection complete get connection handle
( packet ) ;
conn interval =
gap subevent le connection complete get conn interval (
packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : c o n n e c t e d − c o n n e c t i o n
i n t e r v a l %u.%02u ms , l a t e n c y %u\n” , c o n h a n d l e ,
c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
25 ∗ ( c o n n i n t e r v a l & 3 ) ,
gap subevent le connection complete get conn latency
( packet ) ) ;

// r e q u e s t min con i n t e r v a l 15 ms f o r iOS 11+


p r i n t f ( ”− LE Connection 0x%04x : r e q u e s t 15 ms c o n n e c t i o n
i n t e r v a l \n” , c o n h a n d l e ) ;
gap request connection parameter update ( con handle , 12 ,
1 2 , 4 , 0 x0048 ) ;
break ;
default :
break ;
}
break ;
case HCI EVENT LE META :
switch ( h c i e v e n t l e m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case HCI SUBEVENT LE CONNECTION UPDATE COMPLETE :
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
hci subevent le connection update complete get connection handle
( packet ) ;
conn interval =
hci subevent le connection update complete get conn interval
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : c o n n e c t i o n update −
c o n n e c t i o n i n t e r v a l %u.%02u ms , l a t e n c y %u\n” ,
c o n h a n d l e , c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
25 ∗ ( c o n n i n t e r v a l & 3 ) ,
hci subevent le connection update complete get conn latency
( packet ) ) ;
break ;
case HCI SUBEVENT LE DATA LENGTH CHANGE :
con handle =
hci subevent le data length change get connection handle
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : data l e n g t h change − max %
u b y t e s p e r p a c k e t \n” , c o n h a n d l e ,
hci subevent le data length change get max tx octets (
packet ) ) ;
break ;
92

case HCI SUBEVENT LE PHY UPDATE COMPLETE :


con handle =
hci subevent le phy update complete get connection handle
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : PHY update − u s i n g LE %s
PHY now\n” , c o n h a n d l e ,
phy names [
hci subevent le phy update complete get tx phy (
packet ) ] ) ;
break ;
default :
break ;
}
break ;

default :
break ;
}
}

0.57.4. ATT Packet Handler. The packet handler is used to track the ATT MTU
Exchange and trigger ATT send

s t a t i c void a t t p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

int mtu ;
le streamer connection t ∗ context ;
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case ATT EVENT CONNECTED:
// s e t u p new
context = connection for conn handle (
HCI CON HANDLE INVALID) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>c o u n t e r = ’A ’ ;
c o n t e x t −>c o n n e c t i o n h a n d l e =
a t t e v e n t c o n n e c t e d g e t h a n d l e ( packet ) ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( a t t s e r v e r g e t m t u (
c o n t e x t −>c o n n e c t i o n h a n d l e ) − 3 , s i z e o f ( c o n t e x t −>
test data ) ) ;
p r i n t f ( ”%c : ATT connected , h a n d l e 0x%04x , t e s t data l e n %u
\n” , c o n t e x t −>name , c o n t e x t −>c o n n e c t i o n h a n d l e ,
c o n t e x t −>t e s t d a t a l e n ) ;
break ;
case ATT EVENT MTU EXCHANGE COMPLETE:
mtu = a t t e v e n t m t u e x c h a n g e c o m p l e t e g e t M T U ( p a c k e t ) − 3 ;
context = connection for conn handle (
att event mtu exchange complete get handle ( packet ) ) ;
93

i f ( ! c o n t e x t ) break ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( mtu − 3 , s i z e o f (
c o n t e x t −>t e s t d a t a ) ) ;
p r i n t f ( ”%c : ATT MTU = %u => u s e t e s t data o f l e n %u\n” ,
c o n t e x t −>name , mtu , c o n t e x t −>t e s t d a t a l e n ) ;
break ;
case ATT EVENT CAN SEND NOW:
streamer () ;
break ;
case ATT EVENT DISCONNECTED:
context = connection for conn handle (
a t t e v e n t d i s c o n n e c t e d g e t h a n d l e ( packet ) ) ;
i f ( ! c o n t e x t ) break ;
// f r e e c o n n e c t i o n
p r i n t f ( ”%c : ATT d i s c o n n e c t e d , h a n d l e 0x%04x\n” , c o n t e x t −>
name , c o n t e x t −>c o n n e c t i o n h a n d l e ) ;
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d = 0 ;
c o n t e x t −>c o n n e c t i o n h a n d l e = HCI CON HANDLE INVALID ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}

0.57.5. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

// f i n d n e x t a c t i v e s t r e a m i n g c o n n e c t i o n
int o l d c o n n e c t i o n i n d e x = c o n n e c t i o n i n d e x ;
while ( 1 ) {
// a c t i v e found ?
i f (( le streamer connections [ connection index ] . connection handle
!= HCI CON HANDLE INVALID) &&
( le streamer connections [ connection index ] .
l e n o t i f i c a t i o n e n a b l e d ) ) break ;

// c h e c k n e x t
next connection index () ;

// none found
i f ( c o n n e c t i o n i n d e x == o l d c o n n e c t i o n i n d e x ) return ;
}

l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t = &l e s t r e a m e r c o n n e c t i o n s [
connection index ] ;
94

// c r e a t e t e s t d a t a
c o n t e x t −>c o u n t e r ++;
i f ( c o n t e x t −>c o u n t e r > ’ Z ’ ) c o n t e x t −>c o u n t e r = ’A ’ ;
memset ( c o n t e x t −>t e s t d a t a , c o n t e x t −>c o u n t e r , c o n t e x t −>
test data len ) ;

// send
a t t s e r v e r n o t i f y ( c o n t e x t −>c o n n e c t i o n h a n d l e , c o n t e x t −>
v a l u e h a n d l e , ( uint8 t ∗ ) c o n t e x t −>t e s t d a t a , c o n t e x t −>
test data len ) ;

// t r a c k
t e s t t r a c k s e n t ( c o n t e x t , c o n t e x t −>t e s t d a t a l e n ) ;

// r e q u e s t n e x t send e v e n t
a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( c o n t e x t −>c o n n e c t i o n h a n d l e ) ;

// c h e c k n e x t
next connection index () ;
}

0.57.6. ATT Write. The only valid ATT write in this example is to the Client
Characteristic Configuration, which configures notification and indication. If
the ATT handle matches the client configuration handle, the new configuration
value is stored. If notifications get enabled, an ATT EVENT CAN SEND NOW
is requested. See Listing here.

s t a t i c int a t t w r i t e c a l l b a c k ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
a t t h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t o f f s e t , uint8 t
∗ b u f f e r , uint16 t b u f f e r s i z e ) {
UNUSED( o f f s e t ) ;

// p r i n t f (” a t t w r i t e c a l l b a c k a t t h a n d l e 0 x%04x , t r a n s a c t i o n mode
%u\n ” , a t t h a n d l e , t r a n s a c t i o n m o d e ) ;
i f ( t r a n s a c t i o n m o d e != ATT TRANSACTION MODE NONE) return 0 ;
le streamer connection t ∗ context = connection for conn handle (
con handle ) ;
switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d = l i t t l e e n d i a n r e a d 1 6 (
b u f f e r , 0 ) ==
GATT CLIENT CHARACTERISTICS CONFIGURATION NOTIFICATION ;
p r i n t f ( ”%c : N o t i f i c a t i o n s e n a b l e d %u\n” , c o n t e x t −>name ,
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d ) ;
i f ( c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d ) {
95

switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGU
:
c o n t e x t −>v a l u e h a n d l e =
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HAND
;
break ;
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGU
:
c o n t e x t −>v a l u e h a n d l e =
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 VALUE HAND
;
break ;
default :
break ;
}
a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( c o n t e x t −>
connection handle ) ;
}
t e s t r e s e t ( context ) ;
break ;
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
t e s t t r a c k s e n t ( context , b u f f e r s i z e ) ;
break ;
default :
p r i n t f ( ” Write t o 0x%04x , l e n %u\n” , a t t h a n d l e , b u f f e r s i z e ) ;
break ;
}
return 0 ;
}

0.58. GATT Battery Service Client. Source Code: gatt battery query.c
This example demonstrates how to use the GATT Battery Service client to re-
ceive battery level information. The client supports querying of multiple battery
services instances of on the remote device. The example scans for remote devices
and connects to the first found device and starts the battery service client.
0.58.1. Main Application Setup. The Listing here shows how to setup Battery
Service client. Besides calling init() method for each service, you’ll also need to
register HCI packet handler to handle advertisements, as well as connect and
disconect events.
Handling of GATT Battery Service events will be later delegated to a sepparate
packet handler, i.e. gatt client event handler.
@note There are two additional files associated with this client to allow a
remote device to query out GATT database:
96

• gatt battary query.gatt - contains the declaration of the provided GATT


Services and Characteristics.
• gatt battary query.h - contains the binary representation of gatt battary query.gatt.

s t a t i c void h c i e v e n t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void g a t t c l i e n t e v e n t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void b a t t e r y s e r v i c e c l i e n t s e t u p ( void ) {
// I n i t L2CAP
l2cap init () ;

// S et u p ATT s e r v e r − o n l y needed i f LE P e r i p h e r a l d o e s ATT


q u e r i e s on i t s own , e . g . Android phones
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, NULL) ;

// GATT C l i e n t s e t u p
g a t t c l i e n t i n i t () ;
// D e v ic e I n f o r m a t i o n S e r v i c e C l i e n t s e t u p
battery service client init () ;

sm init () ;
s m s e t i o c a p a b i l i t i e s (IO CAPABILITY NO INPUT NO OUTPUT) ;

h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i e v e n t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
}

s t a t i c void h c i e v e n t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
...

i f ( p a c k e t t y p e != HCI EVENT PACKET) {


return ;
}

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
...
case HCI EVENT META GAP :
// Wait f o r c o n n e c t i o n c o m p l e t e
if ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) !=
GAP SUBEVENT LE CONNECTION COMPLETE) break ;

...
// Get c o n n e c t i o n h a n d l e from e v e n t
connection handle =
gap subevent le connection complete get connection handle (
packet ) ;
97

// Connect t o remote B a t t e r y S e r v i c e .
// On s u c c e s f u l c o n n e c t i o n , t h e c l i e n t t r i e s t o r e g i s t e r f o r
notifications . If notifications
// a r e not s u p p o r t e d by remote B a t t e r y S e r v i c e , t h e c l i e n t
w i l l automatically p o l l the b a t t e r y l e v e l − here every 2
seconds .
// I f p o l l i n t e r v a l m s i s 0 , p o l l i n g i s d i s a b l e d , and o n l y
n o t i f i c a t i o n s w i l l be r e c e i v e d ( f o r manual p o l l i n g ,
// s e e b a t t e r y s e r v i c e c l i e n t . h ) .
// A l l GATT B a t t e r y S e r v i c e e v e n t s a r e h a n d l e d by t h e
gatt client event handler .
( void ) b a t t e r y s e r v i c e c l i e n t c o n n e c t ( c o n n e c t i o n h a n d l e ,
g a t t c l i e n t e v e n t h a n d l e r , 2 0 0 0 , &b a t t e r y s e r v i c e c i d ) ;

a p p s t a t e = APP STATE CONNECTED;


p r i n t f ( ” B a t t e r y s e r v i c e c o n n e c t e d . \ n” ) ;
break ;

case HCI EVENT DISCONNECTION COMPLETE :


c o n n e c t i o n h a n d l e = HCI CON HANDLE INVALID ;
// D i s c o n n e c t b a t t e r y s e r v i c e
battery service client disconnect ( battery service cid ) ;

...
p r i n t f ( ” D i s c o n n e c t e d %s \n” , b d a d d r t o s t r ( r e p o r t . a d d r e s s ) ) ;
p r i n t f ( ” R e s t a r t s c a n . \ n” ) ;
a p p s t a t e = APP STATE W4 SCAN RESULT ;
gap start scan () ;
break ;
default :
break ;
}
}

// The g a t t c l i e n t e v e n t h a n d l e r r e c e i v e s f o l l o w i n g e v e n t s from
remote d e v i c e :
// − GATTSERVICE SUBEVENT BATTERY SERVICE CONNECTED
// − GATTSERVICE SUBEVENT BATTERY SERVICE LEVEL
//
s t a t i c void g a t t c l i e n t e v e n t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) {
...
uint8 t s t a t u s ;
uint8 t a t t s t a t u s ;

i f ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) !=
HCI EVENT GATTSERVICE META) {
return ;
}

switch ( h c i e v e n t g a t t s e r v i c e m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GATTSERVICE SUBEVENT BATTERY SERVICE CONNECTED:
98

status =
gattservice subevent battery service connected get status (
packet ) ;
switch ( s t a t u s ) {
case ERROR CODE SUCCESS :
p r i n t f ( ” B a t t e r y s e r v i c e c l i e n t connected , found %d
s e r v i c e s , p o l l bitmap 0x%02x\n” ,
gattservice subevent battery service connected get num instances
( packet ) ,
gattservice subevent battery service connected get poll bitmap
( packet ) ) ;
battery service client read battery level (
b a t t e r y s e r v i c e c i d , 0) ;
break ;
default :
p r i n t f ( ” Battery s e r v i c e c l i e n t connection f a i l e d , s t a t u s 0
x%02x . \ n” , s t a t u s ) ;
a d d t o b l a c k l i s t ( report . address ) ;
gap disconnect ( connection handle ) ;
break ;
}
break ;

case GATTSERVICE SUBEVENT BATTERY SERVICE LEVEL :


att status =
gattservice subevent battery service level get att status (
packet ) ;
i f ( a t t s t a t u s != ATT ERROR SUCCESS) {
p r i n t f ( ” B a t t e r y l e v e l r e a d f a i l e d , ATT E r r o r 0x%02x\n” ,
att status ) ;
} else {
p r i n t f ( ” S e r v i c e i n d e x : %d , B a t t e r y l e v e l : %d\n” ,
gattservice subevent battery service level get sevice index
( packet ) ,
gattservice subevent battery service level get level (
packet ) ) ;

}
break ;

default :
break ;
}
}

0.59. GATT Device Information Service Client. Source Code: gatt device information query.
This example demonstrates how to use the GATT Device Information Service
client to receive device information such as various IDs and revisions. The exam-
ple scans for remote devices and connects to the first found device. If the remote
device provides a Device Information Service, the information is collected and
printed in console output, otherwise, the device will be blacklisted and the scan
restarted.
99

0.59.1. Main Application Setup. The Listing here shows how to setup Device
Information Service client. Besides calling init() method for each service, you’ll
also need to register HCI packet handler to handle advertisements, as well as
connect and disconect events.
Handling of GATT Device Information Service events will be later delegated
to a sepparate packet handler, i.e. gatt client event handler.
@note There are two additional files associated with this client to allow a
remote device to query out GATT database:
• gatt device information query.gatt - contains the declaration of the pro-
vided GATT Services and Characteristics.
• gatt device information query.h - contains the binary representation of
gatt device information query.gatt.

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void g a t t c l i e n t e v e n t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void d e v i c e i n f o r m a t i o n s e r v i c e c l i e n t s e t u p ( void ) {
// I n i t L2CAP
l2cap init () ;

// S et u p ATT s e r v e r − o n l y needed i f LE P e r i p h e r a l d o e s ATT


q u e r i e s on i t s own , e . g . Android phones
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, NULL) ;

// GATT C l i e n t s e t u p
g a t t c l i e n t i n i t () ;
// D e v ic e I n f o r m a t i o n S e r v i c e C l i e n t s e t u p
device information service client init () ;

sm init () ;
s m s e t i o c a p a b i l i t i e s (IO CAPABILITY NO INPUT NO OUTPUT) ;

h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
}

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) {
...
case HCI EVENT META GAP :
// w a i t f o r c o n n e c t i o n c o m p l e t e
i f ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) !=
GAP SUBEVENT LE CONNECTION COMPLETE) break ;

...
// g e t c o n n e c t i o n h a n d l e from e v e n t
100

connection handle =
gap subevent le connection complete get connection handle (
packet ) ;

// Connect t o remote D e vi c e I n f o r m a t i o n S e r v i c e . The c l i e n t


w i l l q u e r y t h e remote s e r v i c e and emit e v e n t s ,
// t h a t w i l l be p a s s e d on t o g a t t c l i e n t e v e n t h a n d l e r .
status = device information service client query (
connection handle , g a t t c l i e n t e v e n t h a n d l e r ) ;
b t s t a c k a s s e r t ( s t a t u s == ERROR CODE SUCCESS) ;

p r i n t f ( ” De v ic e I n f o r m a t i o n c o n n e c t e d . \ n” ) ;

a p p s t a t e = APP STATE CONNECTED;


break ;
...
uint8 t a t t s t a t u s = 0 ;

i f ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) !=
HCI EVENT GATTSERVICE META) {
return ;
}

switch ( h c i e v e n t g a t t s e r v i c e m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GATTSERVICE SUBEVENT DEVICE INFORMATION MANUFACTURER NAME:
att status =
gattservice subevent device information manufacturer name get att status
( packet ) ;
i f ( a t t s t a t u s != ATT ERROR SUCCESS) {
p r i n t f ( ” Manufacturer Name r e a d f a i l e d , ATT E r r o r 0x%02x\n” ,
att status ) ;
} else {
p r i n t f ( ” Manufacturer Name : %s \n” ,
gattservice subevent device information manufacturer name get value
( packet ) ) ;
}
break ;

// . . .
...
case GATTSERVICE SUBEVENT DEVICE INFORMATION DONE :
att status =
gattservice subevent device information serial number get att status
( packet ) ;
switch ( a t t s t a t u s ) {
case ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE:
p r i n t f ( ” De v ic e I n f o r m a t i o n s e r v i c e c l i e n t not found . \ n” ) ;
a d d t o b l a c k l i s t ( report . address ) ;
gap disconnect ( connection handle ) ;
break ;
case ATT ERROR SUCCESS :
p r i n t f ( ” Query done \n” ) ;
break ;
default :
101

p r i n t f ( ” Query f a i l e d , ATT E r r o r 0x%02x\n” , a t t s t a t u s ) ;


break ;

}
i f ( a t t s t a t u s != ATT ERROR SUCCESS) {
i f ( a t t s t a t u s ==
ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE)
p r i n t f ( ” Query f a i l e d , ATT E r r o r 0x%02x\n” , a t t s t a t u s ) ;
} else {
p r i n t f ( ” Query done \n” ) ;
}
break ;
default :
break ;
}
}

0.60. GATT Heart Rate Sensor Client. Source Code: gatt heart rate client.c
Connects for Heart Rate Sensor and reports measurements.

0.61. LE Nordic SPP-like Heartbeat Server. Source Code: nordic ssp le counter.c

0.61.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager and configures the ATT Server with
the pre-compiled ATT Database generated from nordics spl ec ounter.gatt. Ad-
ditionally, it enables the Battery Service Server with the current battery level.
Finally, it configures the advertisements and the heartbeat handler and boots
the Bluetooth stack. In this example, the Advertisement contains the Flags at-
tribute and the device name. The flag 0x06 indicates: LE General Discoverable
Mode and BR/EDR not supported.

s t a t i c btstack timer source t h e a r t b e a t ;


s t a t i c h c i c o n h a n d l e t c o n h a n d l e = HCI CON HANDLE INVALID ;
static b t s t a c k c o n t e x t c a l l b a c k r e g i s t r a t i o n t send request ;

const uint8 t a d v d a t a [ ] = {
// F l a g s g e n e r a l d i s c o v e r a b l e , BR/EDR not s u p p o r t e d
2 , BLUETOOTH DATA TYPE FLAGS, 0 x06 ,
// Name
8 , BLUETOOTH DATA TYPE COMPLETE LOCAL NAME, ’ n ’ , ’R ’ , ’F ’ , ’ ’ , ’ S ’
, ’P ’ , ’P ’ ,
// UUID . . .
17 ,
BLUETOOTH DATA TYPE COMPLETE LIST OF 128 BIT SERVICE CLASS UUIDS
, 0 x9e , 0 xca , 0 xdc , 0 x24 , 0 xe , 0 xe5 , 0 xa9 , 0 xe0 , 0 x93 , 0 xf3 , 0
xa3 , 0xb5 , 0x1 , 0x0 , 0 x40 , 0 x6e ,
};
const uint8 t a d v d a t a l e n = s i z e o f ( a d v d a t a ) ;
102

0.61.2. Heartbeat Handler. The heartbeat handler updates the value of the single
Characteristic provided in this example, and request a ATT EVENT CAN SEND NOW
to send a notification if enabled see Listing here.

s t a t i c int c o u n t e r = 0 ;
s t a t i c char c o u n t e r s t r i n g [ 3 0 ] ;
s t a t i c int c o u n t e r s t r i n g l e n ;

s t a t i c void b e a t ( void ) {
c o u n t e r ++;
counter string len = snprintf ( counter string , sizeof (
c o u n t e r s t r i n g ) , ” BTstack c o u n t e r %03u” , c o u n t e r ) ;
}

s t a t i c void n o r d i c c a n s e n d ( void ∗ c o n t e x t ) {
UNUSED( c o n t e x t ) ;
p r i n t f ( ”SEND: %s \n” , c o u n t e r s t r i n g ) ;
n o r d i c s p p s e r v i c e s e r v e r s e n d ( c o n h a n d l e , ( uint8 t ∗ )
counter string , counter string len ) ;
}

s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {
i f ( c o n h a n d l e != HCI CON HANDLE INVALID) {
beat ( ) ;
s e n d r e q u e s t . c a l l b a c k = &n o r d i c c a n s e n d ;
n o r d i c s p p s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w (& s e n d r e q u e s t ,
con handle ) ;
}
b t s t a c k r u n l o o p s e t t i m e r ( t s , HEARTBEAT PERIOD MS) ;
btstack run loop add timer ( ts ) ;
}

0.62. LE Nordic SPP-like Streamer Server. Source Code: nordic spp le streamer.c
All newer operating systems provide GATT Client functionality. This example
shows how to get a maximal throughput via BLE:
• send whenever possible,
• use the max ATT MTU.
In theory, we should also update the connection parameters, but we
already get a connection interval of 30 ms and there’s no public way to
use a shorter interval with iOS (if we’re not implementing an HID device).
Note: To start the streaming, run the example. On remote device use
some GATT Explorer, e.g. LightBlue, BLExplr to enable notifications.

0.62.1. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.
103

s t a t i c void t e s t r e s e t ( n o r d i c s p p l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t
){
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k s e n t ( n o r d i c s p p l e s t r e a m e r c o n n e c t i o n t ∗
c o n t e x t , int b y t e s s e n t ) {
c o n t e x t −>t e s t d a t a s e n t += b y t e s s e n t ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s s e n t −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.62.2. HCI Packet Handler. The packet handler prints the welcome message
and requests a connection paramter update for LE Connections

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

uint16 t c o n n i n t e r v a l ;
hci con handle t con handle ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
) {
p r i n t f ( ”To s t a r t t h e s t r e a m i n g , p l e a s e run nRF Toolbox −>
UART t o c o n n e c t . \ n” ) ;
}
break ;
case HCI EVENT META GAP :
switch ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GAP SUBEVENT LE CONNECTION COMPLETE:
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
104

con handle =
gap subevent le connection complete get connection handle
( packet ) ;
conn interval =
gap subevent le connection complete get conn interval (
packet ) ;
p r i n t f ( ”LE Connection − Connection I n t e r v a l : %u.%02u ms\n”
, c o n n i n t e r v a l ∗ 125 / 1 0 0 , 25 ∗ ( c o n n i n t e r v a l & 3 ) )
;
p r i n t f ( ”LE Connection − Connection Latency : %u\n” ,
gap subevent le connection complete get conn latency (
packet ) ) ;

// r e q u e s t min con i n t e r v a l 15 ms f o r iOS 11+


p r i n t f ( ”LE Connection − Request 15 ms c o n n e c t i o n i n t e r v a l \
n” ) ;
gap request connection parameter update ( con handle , 12 ,
1 2 , 4 , 0 x0048 ) ;
break ;
default :
break ;
}
break ;

case HCI EVENT LE META :


switch ( h c i e v e n t l e m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case HCI SUBEVENT LE CONNECTION UPDATE COMPLETE :
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
hci subevent le connection update complete get connection handle
( packet ) ;
conn interval =
hci subevent le connection update complete get conn interval
( packet ) ;
p r i n t f ( ”LE Connection − Connection Param update −
c o n n e c t i o n i n t e r v a l %u.%02u ms , l a t e n c y %u\n” ,
c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
25 ∗ ( c o n n i n t e r v a l & 3 ) ,
hci subevent le connection update complete get conn latency
( packet ) ) ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}

0.62.3. ATT Packet Handler. The packet handler is used to setup and tear down
the spp-over-gatt connection and its MTU
105

s t a t i c void a t t p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

int mtu ;
nordic spp le streamer connection t ∗ context ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case ATT EVENT CONNECTED:
// s e t u p new
c o n t e x t = c o n n e c t i o n f o r c o n n h a n d l e (HCI CON HANDLE INVALID) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>c o u n t e r = ’A ’ ;
c o n t e x t −>t e s t d a t a l e n = ATT DEFAULT MTU − 4 ; // −1 f o r
n o r d i c 0 x01 p a c k e t t y p e
c o n t e x t −>c o n n e c t i o n h a n d l e = a t t e v e n t c o n n e c t e d g e t h a n d l e (
packet ) ;
break ;
case ATT EVENT MTU EXCHANGE COMPLETE:
mtu = a t t e v e n t m t u e x c h a n g e c o m p l e t e g e t M T U ( p a c k e t ) − 3 ;
context = connection for conn handle (
att event mtu exchange complete get handle ( packet ) ) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( mtu − 3 , s i z e o f ( c o n t e x t −>
test data ) ) ;
p r i n t f ( ”%c : ATT MTU = %u => u s e t e s t data o f l e n %u\n” ,
c o n t e x t −>name , mtu , c o n t e x t −>t e s t d a t a l e n ) ;
break ;

default :
break ;
}
}

0.62.4. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void n o r d i c c a n s e n d ( void ∗ s o m e c o n t e x t ) {
UNUSED( s o m e c o n t e x t ) ;

// f i n d n e x t a c t i v e s t r e a m i n g c o n n e c t i o n
int o l d c o n n e c t i o n i n d e x = c o n n e c t i o n i n d e x ;
while ( 1 ) {
// a c t i v e found ?
106

i f (( nordic spp le streamer connections [ connection index ] .


c o n n e c t i o n h a n d l e != HCI CON HANDLE INVALID) &&
( nordic spp le streamer connections [ connection index ] .
l e n o t i f i c a t i o n e n a b l e d ) ) break ;

// c h e c k n e x t
next connection index () ;

// none found
i f ( c o n n e c t i o n i n d e x == o l d c o n n e c t i o n i n d e x ) return ;
}

nordic spp le streamer connection t ∗ context = &


nordic spp le streamer connections [ connection index ] ;

// c r e a t e t e s t d a t a
c o n t e x t −>c o u n t e r ++;
i f ( c o n t e x t −>c o u n t e r > ’ Z ’ ) c o n t e x t −>c o u n t e r = ’A ’ ;
memset ( c o n t e x t −>t e s t d a t a , c o n t e x t −>c o u n t e r , c o n t e x t −>
test data len ) ;

// send
n o r d i c s p p s e r v i c e s e r v e r s e n d ( c o n t e x t −>c o n n e c t i o n h a n d l e , (
uint8 t ∗ ) c o n t e x t −>t e s t d a t a , c o n t e x t −>t e s t d a t a l e n ) ;

// t r a c k
t e s t t r a c k s e n t ( c o n t e x t , c o n t e x t −>t e s t d a t a l e n ) ;

// r e q u e s t n e x t send e v e n t
n o r d i c s p p s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w (& c o n t e x t −>
s e n d r e q u e s t , c o n t e x t −>c o n n e c t i o n h a n d l e ) ;

// c h e c k n e x t
next connection index () ;
}

0.63. LE u-blox SPP-like Heartbeat Server. Source Code: ublox spp le counter.c

0.63.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager and configures the ATT Server with the
pre-compiled ATT Database generated from ubloxl ec ounter.gatt. Additionally,
it enables the Battery Service Server with the current battery level. Finally, it
configures the advertisements and the heartbeat handler and boots the Bluetooth
stack. In this example, the Advertisement contains the Flags attribute and
the device name. The flag 0x06 indicates: LE General Discoverable Mode and
BR/EDR not supported.

s t a t i c btstack timer source t h e a r t b e a t ;


s t a t i c h c i c o n h a n d l e t c o n h a n d l e = HCI CON HANDLE INVALID ;
static b t s t a c k c o n t e x t c a l l b a c k r e g i s t r a t i o n t send request ;
107

static b t s t a c k p a c k e t c a l l b a c k r e g i s t r a t i o n t
hci event callback registration ;

const uint8 t a d v d a t a [ ] = {
// F l a g s g e n e r a l d i s c o v e r a b l e , BR/EDR not s u p p o r t e d
2 , BLUETOOTH DATA TYPE FLAGS, 0 x06 ,
// Name
5 , BLUETOOTH DATA TYPE COMPLETE LOCAL NAME, ’ 6 ’ , ’− ’ , ’ 5 ’ , ’ 6 ’ ,
// UUID . . .
17 ,
BLUETOOTH DATA TYPE COMPLETE LIST OF 128 BIT SERVICE CLASS UUIDS
, 0x1 , 0xd7 , 0 xe9 , 0x1 , 0 x4f , 0 xf3 , 0 x44 , 0 xe7 , 0 x83 , 0 x8f , 0
xe2 , 0 x26 , 0xb9 , 0 xe1 , 0 x56 , 0 x24 ,
};

const uint8 t a d v d a t a l e n = s i z e o f ( a d v d a t a ) ;

0.63.2. Heartbeat Handler. The heartbeat handler updates the value of the single
Characteristic provided in this example, and request a ATT EVENT CAN SEND NOW
to send a notification if enabled see Listing here.

s t a t i c int c o u n t e r = 0 ;
s t a t i c char c o u n t e r s t r i n g [ 3 0 ] ;
s t a t i c int c o u n t e r s t r i n g l e n ;

s t a t i c void b e a t ( void ) {
c o u n t e r ++;
counter string len = snprintf ( counter string , sizeof (
c o u n t e r s t r i n g ) , ” BTstack c o u n t e r %03u” , c o u n t e r ) ;
}

s t a t i c void u b l o x c a n s e n d ( void ∗ c o n t e x t ) {
UNUSED( c o n t e x t ) ;
beat ( ) ;
p r i n t f ( ”SEND: %s \n” , c o u n t e r s t r i n g ) ;
u b l o x s p p s e r v i c e s e r v e r s e n d ( c o n h a n d l e , ( uint8 t ∗ )
counter string , counter string len ) ;
}

s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {
i f ( c o n h a n d l e != HCI CON HANDLE INVALID) {
s e n d r e q u e s t . c a l l b a c k = &u b l o x c a n s e n d ;
u b l o x s p p s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w (& s e n d r e q u e s t ,
con handle ) ;
}
b t s t a c k r u n l o o p s e t t i m e r ( t s , HEARTBEAT PERIOD MS) ;
btstack run loop add timer ( ts ) ;
}

0.63.3. Packet Handler. The packet handler is used to:


108

• stop the counter after a disconnect

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case HCI EVENT DISCONNECTION COMPLETE :
c o n h a n d l e = HCI CON HANDLE INVALID ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}

0.64. LE Central - Test Pairing Methods. Source Code: sm pairing central.c


Depending on the Authentication requiremens and IO Capabilities, the pairing
process uses different short and long term key generation method. This example
helps explore the different options incl. LE Secure Connections. It scans for
advertisements and connects to the first device that lists a random service.

0.64.1. GAP LE setup for receiving advertisements. GAP LE advertisements are


received as custom HCI events of the GAP EVENT ADVERTISING REPORT
type. To receive them, you’ll need to register the HCI packet handler, as shown
in Listing here.

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void s m p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,
uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void s m p a i r i n g c e n t r a l s e t u p ( void ) {
l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

// s e t u p ATT s e r v e r
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, NULL) ;

// s e t u p GATT C l i e n t
g a t t c l i e n t i n i t () ;
109

// r e g i s t e r h a n d l e r
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

s m e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &s m p a c k e t h a n d l e r ;
s m a d d e v e n t h a n d l e r (& s m e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// C o n f i g u r a t i o n

// Enable mandatory a u t h e n t i c a t i o n f o r GATT C l i e n t


// − i f un−e n c r y p t e d c o n n e c t i o n s a r e not s u p p o r t e d , e . g . when
c o n n e c t i n g t o own d e v i c e , t h i s e n f o r c e s a u t h e n t i c a t i o n
// g a t t c l i e n t s e t r e q u i r e d s e c u r i t y l e v e l (LEVEL 2) ;

/∗ ∗
∗ Choose ONE o f t h e f o l l o w i n g c o n f i g u r a t i o n s
∗ Bonding i s d i s a b l e d t o a l l o w f o r r e p e a t e d t e s t i n g . I t can be
e n a b l e d by or ’ i n g
∗ SM AUTHREQ BONDING t o t h e a u t h e n t i c a t i o n r e q u i r e m e n t s l i k e t h i s
:
∗ s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s ( X | SM AUTHREQ BONDING)

// LE Legacy P a i r i n g , J u s t Works
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY YES NO) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s ( 0 ) ;

// LE Legacy P a i r i n g , Passkey e n t r y i n i t i a t o r e n t e r , r e s p o n d e r ( us
) displays
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY ONLY) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ MITM PROTECTION) ;
// s m u s e f i x e d p a s s k e y i n d i s p l a y r o l e (FIXED PASSKEY) ;

#i f d e f ENABLE LE SECURE CONNECTIONS

// e n a b l e LE S e c u r e C o n n e c t i o n s Only mode − d i s a b l e s Legacy


pairing
// s m s e t s e c u r e c o n n e c t i o n s o n l y m o d e ( t r u e ) ;

// LE S e c u r e Connections , J u s t Works
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY YES NO) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION
);

// LE S e c u r e Connections , Numeric Comparison


// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY YES NO) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION
|SM AUTHREQ MITM PROTECTION) ;

// LE S e c u r e P a i r i n g , Passkey e n t r y i n i t i a t o r ( us ) e n t e r s ,
responder d i s p l a y s
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY KEYBOARD ONLY) ;
110

// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION


|SM AUTHREQ MITM PROTECTION) ;
// s m u s e f i x e d p a s s k e y i n d i s p l a y r o l e (FIXED PASSKEY) ;

// LE S e c u r e P a i r i n g , Passkey e n t r y i n i t i a t o r ( us ) d i s p l a y s ,
responder enters
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY ONLY) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION
|SM AUTHREQ MITM PROTECTION) ;
#e n d i f
}

0.64.2. HCI packet handler. The HCI packet handler has to start the scanning,
and to handle received advertisements. Advertisements are received as HCI event
packets of the GAP EVENT ADVERTISING REPORT type, see Listing here.

0.64.3. HCI packet handler.

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;


hci con handle t con handle ;
uint8 t s t a t u s ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
){
p r i n t f ( ” S t a r t s c a n i n g ! \ n” ) ;
g a p s e t s c a n p a r a m e t e r s ( 1 , 0 x0030 , 0 x0030 ) ;
gap start scan () ;
}
break ;
case GAP EVENT ADVERTISING REPORT: {
bd addr t a d d r e s s ;
g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s ( packet , a d d r e s s ) ;
uint8 t a d d r e s s t y p e =
g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s t y p e ( packet ) ;
uint8 t l e n g t h = g a p e v e n t a d v e r t i s i n g r e p o r t g e t d a t a l e n g t h (
packet ) ;
const uint8 t ∗ data = g a p e v e n t a d v e r t i s i n g r e p o r t g e t d a t a (
packet ) ;
// p r i n t f (” A d v e r t i s e m e n t e v e n t : addr−t y p e %u , addr %s , d a t a [%u
] ”,
// address type , b d a d d r t o s t r ( address ) , length ) ;
// p r i n t f h e x d u m p ( data , l e n g t h ) ;
i f ( ! a d d a t a c o n t a i n s u u i d 1 6 ( l e n g t h , ( uint8 t ∗ ) data ,
REMOTE SERVICE) ) break ;
111

p r i n t f ( ”Found remote with UUID %04x , c o n n e c t i n g . . . \ n” ,


REMOTE SERVICE) ;
gap stop scan () ;
gap connect ( address , address type ) ;
break ;
}
case HCI EVENT META GAP :
// w a i t f o r c o n n e c t i o n c o m p l e t e
i f ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) !=
GAP SUBEVENT LE CONNECTION COMPLETE) break ;
con handle =
gap subevent le connection complete get connection handle (
packet ) ;
p r i n t f ( ” Connection c o m p l e t e \n” ) ;

// f o r t e s t i n g , c h o o s e one o f t h e f o l l o w i n g a c t i o n s

// manually s t a r t p a i r i n g
sm request pairing ( con handle ) ;

// g a t t c l i e n t r e q u e s t t o authenticated c h a r a c t e r i s t i c in
sm pairing peripheral ( s h o r t cut , u s e s hard−coded v a l u e
handle )
// g a t t c l i e n t r e a d v a l u e of characteristic using value handle
(& h c i p a c k e t h a n d l e r , c o n h a n d l e , 0 x0009 ) ;

// g e n e r a l g a t t c l i e n t r e q u e s t t o t r i g g e r mandatory
authentication
// g a t t c l i e n t d i s c o v e r p r i m a r y s e r v i c e s (& h c i p a c k e t h a n d l e r ,
con handle ) ;
break ;
case GATT EVENT QUERY COMPLETE:
s t a t u s = g a t t e v e n t q u e r y c o m p l e t e g e t a t t s t a t u s ( packet ) ;
switch ( s t a t u s ) {
case ATT ERROR INSUFFICIENT ENCRYPTION :
p r i n t f ( ”GATT Query r e s u l t : I n s u f f i c i e n t E n c r y p t i o n \n” ) ;
break ;
case ATT ERROR INSUFFICIENT AUTHENTICATION :
p r i n t f ( ”GATT Query r e s u l t : I n s u f f i c i e n t A u t h e n t i c a t i o n \n” )
;
break ;
case ATT ERROR BONDING INFORMATION MISSING :
p r i n t f ( ”GATT Query r e s u l t : Bonding I n f o r m a t i o n M i s s i n g \n” )
;
break ;
case ATT ERROR SUCCESS :
p r i n t f ( ”GATT Query r e s u l t : OK\n” ) ;
break ;
default :
p r i n t f ( ”GATT Query r e s u l t : 0x%02x\n” ,
g a t t e v e n t q u e r y c o m p l e t e g e t a t t s t a t u s ( packet ) ) ;
break ;
}
break ;
112

default :
break ;
}
}

s t a t i c void s m p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

bd addr t addr ;
bd addr type t addr type ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case SM EVENT JUST WORKS REQUEST :
p r i n t f ( ” J u s t works r e q u e s t e d \n” ) ;
sm just works confirm ( sm event just works request get handle (
packet ) ) ;
break ;
case SM EVENT NUMERIC COMPARISON REQUEST:
p r i n t f ( ” Confirming numeric comparison : %”PRIu32”\n” ,
sm event numeric comparison request get passkey ( packet ) ) ;
sm numeric comparison confirm (
sm event passkey display number get handle ( packet ) ) ;
break ;
case SM EVENT PASSKEY DISPLAY NUMBER :
p r i n t f ( ” D i s p l a y Passkey : %”PRIu32” \n” ,
sm event passkey display number get passkey ( packet ) ) ;
break ;
case SM EVENT PASSKEY INPUT NUMBER :
p r i n t f ( ” Passkey Input r e q u e s t e d \n” ) ;
p r i n t f ( ” Sending f i x e d p a s s k e y %”PRIu32”\n” , ( uint32 t )
FIXED PASSKEY) ;
sm passkey input ( sm event passkey input number get handle (
p a c k e t ) , FIXED PASSKEY) ;
break ;
case SM EVENT PAIRING STARTED :
p r i n t f ( ” P a i r i n g s t a r t e d \n” ) ;
break ;
case SM EVENT PAIRING COMPLETE :
switch ( s m e v e n t p a i r i n g c o m p l e t e g e t s t a t u s ( p a c k e t ) ) {
case ERROR CODE SUCCESS :
p r i n t f ( ” P a i r i n g complete , s u c c e s s \n” ) ;
break ;
case ERROR CODE CONNECTION TIMEOUT:
p r i n t f ( ” P a i r i n g f a i l e d , t i m e o u t \n” ) ;
break ;
case ERROR CODE REMOTE USER TERMINATED CONNECTION:
p r i n t f ( ” P a i r i n g f a i l e d , d i s c o n n e c t e d \n” ) ;
113

break ;
case ERROR CODE AUTHENTICATION FAILURE :
p r i n t f ( ” P a i r i n g f a i l e d , a u t h e n t i c a t i o n f a i l u r e with r e a s o n
= %u\n” , s m e v e n t p a i r i n g c o m p l e t e g e t r e a s o n ( p a c k e t )
);
break ;
default :
break ;
}
break ;
case SM EVENT REENCRYPTION STARTED:
s m e v e n t r e e n c r y p t i o n c o m p l e t e g e t a d d r e s s ( packet , addr ) ;
p r i n t f ( ” Bonding i n f o r m a t i o n e x i s t s f o r addr type %u , i d e n t i t y
addr %s −> s t a r t re−e n c r y p t i o n \n” ,
s m e v e n t r e e n c r y p t i o n s t a r t e d g e t a d d r t y p e ( packet ) ,
b d a d d r t o s t r ( addr ) ) ;
break ;
case SM EVENT REENCRYPTION COMPLETE:
switch ( s m e v e n t r e e n c r y p t i o n c o m p l e t e g e t s t a t u s ( p a c k e t ) ) {
case ERROR CODE SUCCESS :
p r i n t f ( ”Re−e n c r y p t i o n complete , s u c c e s s \n” ) ;
break ;
case ERROR CODE CONNECTION TIMEOUT:
p r i n t f ( ”Re−e n c r y p t i o n f a i l e d , t i m e o u t \n” ) ;
break ;
case ERROR CODE REMOTE USER TERMINATED CONNECTION:
p r i n t f ( ”Re−e n c r y p t i o n f a i l e d , d i s c o n n e c t e d \n” ) ;
break ;
case ERROR CODE PIN OR KEY MISSING :
p r i n t f ( ”Re−e n c r y p t i o n f a i l e d , bonding i n f o r m a t i o n m i s s i n g \
n\n” ) ;
p r i n t f ( ” Assuming remote l o s t bonding i n f o r m a t i o n \n” ) ;
p r i n t f ( ” D e l e t i n g l o c a l bonding i n f o r m a t i o n and s t a r t new
p a i r i n g . . . \ n” ) ;
s m e v e n t r e e n c r y p t i o n c o m p l e t e g e t a d d r e s s ( packet , addr ) ;
addr type = sm event reencryption started get addr type (
packet ) ;
g a p d e l e t e b o n d i n g ( a d d r t y p e , addr ) ;
sm request pairing (
sm event reencryption complete get handle ( packet ) ) ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}

The SM packet handler receives Security Manager Events required for pairing.
It also receives events generated during Identity Resolving see Listing here.

0.65. LE Peripheral - Test Pairing Methods. Source Code: sm pairing peripheral.c


114

Depending on the Authentication requiremens and IO Capabilities, the pairing


process uses different short and long term key generation method. This example
helps explore the different options incl. LE Secure Connections.

0.65.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager and configures the ATT Server with
the pre-compiled ATT Database generated from smp airingp eripheral.gatt. Fi-
nally, it configures the advertisements and boots the Bluetooth stack. In this
example, the Advertisement contains the Flags attribute, the device name, and
a 16-bit (test) service 0x1111 The flag 0x06 indicates: LE General Discoverable
Mode and BR/EDR not supported. Various examples for IO Capabilites and
Authentication Requirements are given below.

static btstack packet callback registration t


sm event callback registration ;
static btstack packet callback registration t
hci event callback registration ;

s t a t i c void s m p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel
, uint8 t ∗ packet , uint16 t s i z e ) ;

const uint8 t a d v d a t a [ ] = {
// F l a g s g e n e r a l d i s c o v e r a b l e , BR/EDR not s u p p o r t e d
0 x02 , BLUETOOTH DATA TYPE FLAGS, 0 x06 ,
// Name
0x0b , BLUETOOTH DATA TYPE COMPLETE LOCAL NAME, ’ S ’ , ’M’ , ’ ’ , ’P ’ ,
’a ’ , ’ i ’ , ’ r ’ , ’ i ’ , ’n ’ , ’g ’ ,
// I n c o m p l e t e L i s t o f 16− b i t S e r v i c e C l a s s UUIDs −− 1111 − o n l y
valid for testing !
0 x03 ,
BLUETOOTH DATA TYPE INCOMPLETE LIST OF 16 BIT SERVICE CLASS UUIDS
, 0 x11 , 0 x11 ,
};
const uint8 t a d v d a t a l e n = s i z e o f ( a d v d a t a ) ;

s t a t i c void s m p e r i p h e r a l s e t u p ( void ) {

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

// s e t u p ATT s e r v e r
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, NULL) ;

// s e t u p GATT C l i e n t
g a t t c l i e n t i n i t () ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
115

uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;

// r e g i s t e r h a n d l e r
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

s m e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &s m p a c k e t h a n d l e r ;
s m a d d e v e n t h a n d l e r (& s m e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// C o n f i g u r a t i o n

// Enable mandatory a u t h e n t i c a t i o n f o r GATT C l i e n t


// − i f un−e n c r y p t e d c o n n e c t i o n s a r e not s u p p o r t e d , e . g . when
c o n n e c t i n g t o own d e v i c e , t h i s e n f o r c e s a u t h e n t i c a t i o n
// g a t t c l i e n t s e t r e q u i r e d s e c u r i t y l e v e l (LEVEL 2) ;

/∗ ∗
∗ Choose ONE o f t h e f o l l o w i n g c o n f i g u r a t i o n s
∗ Bonding i s d i s a b l e d t o a l l o w f o r r e p e a t e d t e s t i n g . I t can be
e n a b l e d by or ’ i n g
∗ SM AUTHREQ BONDING t o t h e a u t h e n t i c a t i o n r e q u i r e m e n t s l i k e t h i s
:
∗ s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s ( X | SM AUTHREQ BONDING)

// LE Legacy P a i r i n g , J u s t Works
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY NO INPUT NO OUTPUT) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s ( 0 ) ;

// LE Legacy P a i r i n g , Passkey e n t r y i n i t i a t o r e n t e r , r e s p o n d e r ( us
) displays
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY ONLY) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ MITM PROTECTION) ;
// s m u s e f i x e d p a s s k e y i n d i s p l a y r o l e ( 1 2 3 4 5 6 ) ;

#i f d e f ENABLE LE SECURE CONNECTIONS

// e n a b l e LE S e c u r e C o n n e c t i o n s Only mode − d i s a b l e s Legacy


pairing
// s m s e t s e c u r e c o n n e c t i o n s o n l y m o d e ( t r u e ) ;

// LE S e c u r e Connections , J u s t Works
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY NO INPUT NO OUTPUT) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION
);

// LE S e c u r e Connections , Numeric Comparison


// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY YES NO) ;
116

// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION


|SM AUTHREQ MITM PROTECTION) ;

// LE S e c u r e P a i r i n g , Passkey e n t r y i n i t i a t o r e n t e r , r e s p o n d e r ( us
) displays
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY ONLY) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION
|SM AUTHREQ MITM PROTECTION) ;
// s m u s e f i x e d p a s s k e y i n d i s p l a y r o l e ( 1 2 3 4 5 6 ) ;

// LE S e c u r e P a i r i n g , Passkey e n t r y i n i t i a t o r d i s p l a y s , r e s p o n d e r
( us ) e n t e r
// s m s e t i o c a p a b i l i t i e s (IO CAPABILITY KEYBOARD ONLY) ;
// s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION
|SM AUTHREQ MITM PROTECTION) ;
#e n d i f
}

0.65.2. Security Manager Packet Handler. The packet handler is used to handle
Security Manager events

0.65.3. HCI Packet Handler.

s t a t i c void s m p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

hci con handle t con handle ;


bd addr t addr ;
bd addr type t addr type ;
uint8 t status ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case HCI EVENT META GAP :
switch ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GAP SUBEVENT LE CONNECTION COMPLETE:
p r i n t f ( ” Connection c o m p l e t e \n” ) ;
con handle =
gap subevent le connection complete get connection handle
( packet ) ;
UNUSED( c o n h a n d l e ) ;

// f o r t e s t i n g , c h o o s e one o f t h e f o l l o w i n g a c t i o n s

// manually s t a r t p a i r i n g
// s m r e q u e s t p a i r i n g ( c o n h a n d l e ) ;

// g a t t c l i e n t r e q u e s t t o a u t h e n t i c a t e d c h a r a c t e r i s t i c i n
s m p a i r i n g c e n t r a l ( s h o r t cut , u s e s hard−coded v a l u e
handle )
117

//
gatt client read value of characteristic using value handle
(& p a c k e t h a n d l e r , c o n h a n d l e , 0 x0009 ) ;

// g e n e r a l g a t t c l i e n t r e q u e s t t o t r i g g e r mandatory
authentication
// g a t t c l i e n t d i s c o v e r p r i m a r y s e r v i c e s (& p a c k e t h a n d l e r ,
con handle ) ;
break ;
default :
break ;
}
break ;
case SM EVENT JUST WORKS REQUEST :
p r i n t f ( ” J u s t Works r e q u e s t e d \n” ) ;
sm just works confirm ( sm event just works request get handle (
packet ) ) ;
break ;
case SM EVENT NUMERIC COMPARISON REQUEST:
p r i n t f ( ” Confirming numeric comparison : %”PRIu32”\n” ,
sm event numeric comparison request get passkey ( packet ) ) ;
sm numeric comparison confirm (
sm event passkey display number get handle ( packet ) ) ;
break ;
case SM EVENT PASSKEY DISPLAY NUMBER :
p r i n t f ( ” D i s p l a y Passkey : %”PRIu32” \n” ,
sm event passkey display number get passkey ( packet ) ) ;
break ;
case SM EVENT IDENTITY CREATED :
s m e v e n t i d e n t i t y c r e a t e d g e t i d e n t i t y a d d r e s s ( packet , addr ) ;
p r i n t f ( ” I d e n t i t y c r e a t e d : type %u a d d r e s s %s \n” ,
s m e v e n t i d e n t i t y c r e a t e d g e t i d e n t i t y a d d r t y p e ( packet ) ,
b d a d d r t o s t r ( addr ) ) ;
break ;
case SM EVENT IDENTITY RESOLVING SUCCEEDED :
sm event identity resolving succeeded get identity address (
packet , addr ) ;
p r i n t f ( ” I d e n t i t y r e s o l v e d : type %u a d d r e s s %s \n” ,
sm event identity resolving succeeded get identity addr type
( p a c k e t ) , b d a d d r t o s t r ( addr ) ) ;
break ;
case SM EVENT IDENTITY RESOLVING FAILED :
s m e v e n t i d e n t i t y c r e a t e d g e t a d d r e s s ( packet , addr ) ;
p r i n t f ( ” I d e n t i t y r e s o l v i n g f a i l e d \n” ) ;
break ;
case SM EVENT PAIRING STARTED :
p r i n t f ( ” P a i r i n g s t a r t e d \n” ) ;
break ;
case SM EVENT PAIRING COMPLETE :
switch ( s m e v e n t p a i r i n g c o m p l e t e g e t s t a t u s ( p a c k e t ) ) {
case ERROR CODE SUCCESS :
p r i n t f ( ” P a i r i n g complete , s u c c e s s \n” ) ;
break ;
case ERROR CODE CONNECTION TIMEOUT:
118

p r i n t f ( ” P a i r i n g f a i l e d , t i m e o u t \n” ) ;
break ;
case ERROR CODE REMOTE USER TERMINATED CONNECTION:
p r i n t f ( ” P a i r i n g f a i l e d , d i s c o n n e c t e d \n” ) ;
break ;
case ERROR CODE AUTHENTICATION FAILURE :
p r i n t f ( ” P a i r i n g f a i l e d , a u t h e n t i c a t i o n f a i l u r e with r e a s o n
= %u\n” , s m e v e n t p a i r i n g c o m p l e t e g e t r e a s o n ( p a c k e t )
);
break ;
default :
break ;
}
break ;
case SM EVENT REENCRYPTION STARTED:
s m e v e n t r e e n c r y p t i o n c o m p l e t e g e t a d d r e s s ( packet , addr ) ;
p r i n t f ( ” Bonding i n f o r m a t i o n e x i s t s f o r addr type %u , i d e n t i t y
addr %s −> re−e n c r y p t i o n s t a r t e d \n” ,
s m e v e n t r e e n c r y p t i o n s t a r t e d g e t a d d r t y p e ( packet ) ,
b d a d d r t o s t r ( addr ) ) ;
break ;
case SM EVENT REENCRYPTION COMPLETE:
switch ( s m e v e n t r e e n c r y p t i o n c o m p l e t e g e t s t a t u s ( p a c k e t ) ) {
case ERROR CODE SUCCESS :
p r i n t f ( ”Re−e n c r y p t i o n complete , s u c c e s s \n” ) ;
break ;
case ERROR CODE CONNECTION TIMEOUT:
p r i n t f ( ”Re−e n c r y p t i o n f a i l e d , t i m e o u t \n” ) ;
break ;
case ERROR CODE REMOTE USER TERMINATED CONNECTION:
p r i n t f ( ”Re−e n c r y p t i o n f a i l e d , d i s c o n n e c t e d \n” ) ;
break ;
case ERROR CODE PIN OR KEY MISSING :
p r i n t f ( ”Re−e n c r y p t i o n f a i l e d , bonding i n f o r m a t i o n m i s s i n g \
n\n” ) ;
p r i n t f ( ” Assuming remote l o s t bonding i n f o r m a t i o n \n” ) ;
p r i n t f ( ” D e l e t i n g l o c a l bonding i n f o r m a t i o n t o a l l o w f o r
new p a i r i n g . . . \ n” ) ;
s m e v e n t r e e n c r y p t i o n c o m p l e t e g e t a d d r e s s ( packet , addr ) ;
addr type = sm event reencryption started get addr type (
packet ) ;
g a p d e l e t e b o n d i n g ( a d d r t y p e , addr ) ;
break ;
default :
break ;
}
break ;
case GATT EVENT QUERY COMPLETE:
s t a t u s = g a t t e v e n t q u e r y c o m p l e t e g e t a t t s t a t u s ( packet ) ;
switch ( s t a t u s ) {
case ATT ERROR INSUFFICIENT ENCRYPTION :
p r i n t f ( ”GATT Query f a i l e d , I n s u f f i c i e n t E n c r y p t i o n \n” ) ;
break ;
case ATT ERROR INSUFFICIENT AUTHENTICATION :
119

p r i n t f ( ”GATT Query f a i l e d , I n s u f f i c i e n t A u t h e n t i c a t i o n \n” )


;
break ;
case ATT ERROR BONDING INFORMATION MISSING :
p r i n t f ( ”GATT Query f a i l e d , Bonding I n f o r m a t i o n M i s s i n g \n” )
;
break ;
case ATT ERROR SUCCESS :
p r i n t f ( ”GATT Query s u c c e s s f u l \n” ) ;
break ;
default :
p r i n t f ( ”GATT Query f a i l e d , s t a t u s 0x%02x\n” ,
g a t t e v e n t q u e r y c o m p l e t e g e t a t t s t a t u s ( packet ) ) ;
break ;
}
break ;
default :
break ;
}
}

/∗

s t a t i c void hci packet handler ( uint8 t packet type , uint16 t
channel , u i n t 8 t ∗ p a c k e t , u i n t 1 6 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) r e t u r n ;

hci con handle t con handle ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
c a s e HCI EVENT META GAP:
switch ( hci event gap meta get subevent code ( packet ) ) {
c a s e GAP SUBEVENT LE CONNECTION COMPLETE:
p r i n t f (” Connection c o m p l e t e \n ”) ;
con handle =
gap subevent le connection complete get connection handle
( packet ) ;
UNUSED( c o n h a n d l e ) ;

// f o r t e s t i n g , c h o o s e one o f t h e f o l l o w i n g a c t i o n s

// manually s t a r t p a i r i n g
// s m r e q u e s t p a i r i n g ( c o n h a n d l e ) ;

// g a t t c l i e n t r e q u e s t t o a u t h e n t i c a t e d c h a r a c t e r i s t i c i n
s m p a i r i n g c e n t r a l ( s h o r t cut , u s e s hard−coded v a l u e
handle )
//
gatt client read value of characteristic using value handle
(& p a c k e t h a n d l e r , c o n h a n d l e , 0 x0009 ) ;
120

// g e n e r a l g a t t c l i e n t r e q u e s t t o t r i g g e r mandatory
authentication
// g a t t c l i e n t d i s c o v e r p r i m a r y s e r v i c e s (& p a c k e t h a n d l e r ,
con handle ) ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}

The packet handler is used to handle new connections, can trigger Security
Request

0.66. LE Credit-Based Flow-Control Mode Client - Send Data over


L2CAP. Source Code: le credit based flow control mode client.c
Connects to ‘LE CBM Server’ and streams data via L2CAP Channel in LE
Credit-Based Flow-Control Mode (CBM)

0.66.1. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

#define REPORT INTERVAL MS 3000

// s u p p o r t f o r m u l t i p l e c l i e n t s
typedef struct {
char name ;
hci con handle t connection handle ;
uint16 t c i d ;
int c o u n t e r ;
char t e s t d a t a [ TEST PACKET SIZE ] ;
int t e s t d a t a l e n ;
uint32 t t e s t d a t a s e n t ;
uint32 t t e s t d a t a s t a r t ;
} le cbm connection t ;

static le cbm connection t le cbm connection ;

s t a t i c void t e s t r e s e t ( l e c b m c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k d a t a ( l e c b m c o n n e c t i o n t ∗ c o n t e x t , int
bytes transferred ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s t r a n s f e r r e d ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
121

uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;


i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.66.2. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

// c r e a t e t e s t d a t a
l e c b m c o n n e c t i o n . c o u n t e r ++;
i f ( le cbm connection . counter > ’Z ’ ) le cbm connection . counter = ’
A’ ;
memset ( l e c b m c o n n e c t i o n . t e s t d a t a , l e c b m c o n n e c t i o n . c o u n t e r ,
le cbm connection . test data len ) ;

// send
l 2 c a p s e n d ( l e c b m c o n n e c t i o n . c i d , ( uint8 t ∗ ) l e c b m c o n n e c t i o n .
test data , le cbm connection . test data len ) ;

// t r a c k
t e s t t r a c k d a t a (& l e c b m c o n n e c t i o n , l e c b m c o n n e c t i o n .
test data len ) ;

// r e q u e s t a n o t h e r p a c k e t
l2cap request can send now event ( le cbm connection . cid ) ;
}

0.66.3. SM Packet Handler. The packet handler is used to handle pairing re-
quests

0.67. LE Credit-Based Flow-Control Mode Server - Receive data over


L2CAP. Source Code: le credit based flow control mode server.c
iOS 11 and newer supports L2CAP channels in LE Credit-Based Flow-Control
Mode for fast transfer over LE https://github.com/bluekitchen/CBL2CAPChannel-
Demo
122

0.67.1. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

s t a t i c void t e s t r e s e t ( l e c b m c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k d a t a ( l e c b m c o n n e c t i o n t ∗ c o n t e x t , int
bytes transferred ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s t r a n s f e r r e d ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s s e n t −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.67.2. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

i f ( l e c b m c o n n e c t i o n . c i d == 0 ) return ;

// c r e a t e t e s t d a t a
l e c b m c o n n e c t i o n . c o u n t e r ++;
i f ( le cbm connection . counter > ’Z ’ ) le cbm connection . counter = ’
A’ ;
memset ( l e c b m c o n n e c t i o n . t e s t d a t a , l e c b m c o n n e c t i o n . c o u n t e r ,
le cbm connection . test data len ) ;

// send
l 2 c a p s e n d ( l e c b m c o n n e c t i o n . c i d , ( uint8 t ∗ ) l e c b m c o n n e c t i o n .
test data , le cbm connection . test data len ) ;

// t r a c k
t e s t t r a c k d a t a (& l e c b m c o n n e c t i o n , l e c b m c o n n e c t i o n .
test data len ) ;
123

// r e q u e s t a n o t h e r p a c k e t
l2cap request can send now event ( le cbm connection . cid ) ;
}

0.67.3. HCI + L2CAP Packet Handler. The packet handler is used to stop the
notifications and reset the MTU on connect It would also be a good place to
request the connection parameter update as indicated in the commented code
block.
0.67.4. SM Packet Handler.
0.67.5. Main Application Setup.
0.68. LE Peripheral - Delayed Response. Source Code: att delayed response.c
The packet handler is used to handle pairing requests
Listing here shows main application code. It initializes L2CAP, the Security
Manager, and configures the ATT Server with the pre-compiled ATT Database
generated from lec reditb asedf lowc ontrolm odes erver.gatt. Finally, it configures
the advertisements and boots the Bluetooth stack.
If the value for a GATT Chararacteristic isn’t availabl for read, the value
ATT READ RESPONSE PENDING can be returned. When the value is avail-
able, att server response ready is then called to complete the ATT request.
Similarly, the error code ATT ERROR WRITE RESPONSE PENING can be
returned when it is unclear if a write can be performed or not. When the deci-
sion was made, att server response ready is is then called to complete the ATT
request.
0.68.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager and configures the ATT Server with
the pre-compiled ATT Database generated from attd elayedr esponse.gatt. Ad-
ditionally, it enables the Battery Service Server with the current battery level.
Finally, it configures the advertisements and boots the Bluetooth stack. In this
example, the Advertisement contains the Flags attribute and the device name.
The flag 0x06 indicates: LE General Discoverable Mode and BR/EDR not sup-
ported.

#i f d e f ENABLE ATT DELAYED RESPONSE


static btstack timer source t a t t t i m e r ;
static hci con handle t con handle ;
static int v a l u e r e a d y ;
#endif

s t a t i c uint16 t a t t r e a d c a l l b a c k ( h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t a t t h a n d l e , uint16 t o f f s e t , uint8 t ∗ b u f f e r , uint16 t
buffer size ) ;
s t a t i c int a t t w r i t e c a l l b a c k ( h c i c o n h a n d l e t c o n n e c t i o n h a n d l e ,
uint16 t a t t h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t o f f s e t ,
uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e ) ;
124

const uint8 t a d v d a t a [ ] = {
// F l a g s g e n e r a l d i s c o v e r a b l e , BR/EDR not s u p p o r t e d
0 x02 , 0 x01 , 0 x06 ,
// Name
0 x08 , 0 x09 , ’D ’ , ’ e ’ , ’ l ’ , ’ a ’ , ’ y ’ , ’ e ’ , ’ d ’ ,
};
const uint8 t a d v d a t a l e n = s i z e o f ( a d v d a t a ) ;

const char ∗ t e s t s t r i n g = ” Delayed r e s p o n s e ” ;

s t a t i c void e x a m p l e s e t u p ( void ) {

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

// s e t u p ATT s e r v e r
att server init ( profile data , att read callback ,
att write callback ) ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;
}

0.68.2. att invalidate value Handler. The att invalidate value handler ‘invalidates’
the value of the single Characteristic provided in this example
0.68.3. att update value Handler. The att update value handler ‘updates’ the
value of the single Characteristic provided in this example

#i f d e f ENABLE ATT DELAYED RESPONSE


s t a t i c void a t t u p d a t e v a l u e ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {
UNUSED( t s ) ;
value ready = 1;

// t r i g g e r ATT S e r v e r t o t r y r e q u e s t a g a i n
int s t a t u s = a t t s e r v e r r e s p o n s e r e a d y ( c o n h a n d l e ) ;

p r i n t f ( ” Value updated −> c o m p l e t e ATT r e q u e s t − s t a t u s 0x%02x\n” ,


status ) ;

// s i m u l a t e d v a l u e becoming s t a l e a g a i n
125

a t t t i m e r . p r o c e s s = &a t t i n v a l i d a t e v a l u e ;
b t s t a c k r u n l o o p s e t t i m e r (& a t t t i m e r , ATT VALUE DELAY MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& a t t t i m e r ) ;
}
#endif

0.68.4. ATT Read. The ATT Server handles all reads to constant data. For
dynamic data like the custom characteristic, the registered att read callback is
called. To handle long characteristics and long reads, the att read callback is
first called with buffer == NULL, to request the total value length. Then it will
be called again requesting a chunk of the value. See Listing here.
0.68.5. ATT Write.

// ATT C l i e n t Read C a l l b a c k f o r Dynamic Data


// − i f b u f f e r == NULL, don ’ t copy data , j u s t r e t u r n s i z e o f v a l u e
// − i f b u f f e r != NULL, copy d a t a and r e t u r n number b y t e s c o p i e d
// @param o f f s e t d e f i n e s s t a r t o f a t t r i b u t e v a l u e
s t a t i c uint16 t a t t r e a d c a l l b a c k ( h c i c o n h a n d l e t c o n n e c t i o n h a n d l e
, uint16 t a t t h a n d l e , uint16 t o f f s e t , uint8 t ∗ b u f f e r ,
uint16 t b u f f e r s i z e ) {

#i f d e f ENABLE ATT DELAYED RESPONSE


switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
i f ( value ready ){
return a t t r e a d c a l l b a c k h a n d l e b l o b ( ( const uint8 t ∗ )
test string , strlen ( t e s t s t r i n g ) , offset , buffer ,
buffer size ) ;
} else {
p r i n t f ( ”Read c a l l b a c k f o r h a n d l e 0x%02x , but v a l u e not ready
−> r e p o r t r e s p o n s e pending \n” , a t t h a n d l e ) ;
con handle = connection handle ;
return ATT READ RESPONSE PENDING ;
}
break ;
case ATT READ RESPONSE PENDING :
// v i r t u a l h a n d l e i n d i c a t i n g a l l a t t r i b u t e s have been q u e r i e d
p r i n t f ( ”Read c a l l b a c k f o r v i r t u a l h a n d l e 0x%02x − a l l
a t t r i b u t e s have been q u e r i e d ( i m p o r t a n t f o r r e a d m u l t i p l e
o r r e a d by type ) −> s t a r t u p d a t i n g v a l u e s \n” , a t t h a n d l e ) ;
// s i m u l a t e d d e l a y e d r e s p o n s e f o r example
a t t t i m e r . p r o c e s s = &a t t u p d a t e v a l u e ;
b t s t a c k r u n l o o p s e t t i m e r (& a t t t i m e r , ATT VALUE DELAY MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& a t t t i m e r ) ;
return 0 ;
default :
break ;
}
#e l s e
UNUSED( c o n n e c t i o n h a n d l e ) ;
126

// u s e l e s s code when ENABLE ATT DELAYED RESPONSE i s not d e f i n e d −


but avoids b u i l t errors
i f ( a t t h a n d l e ==
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
){
p r i n t f ( ”ENABLE ATT DELAYED RESPONSE not d e f i n e d i n
b t s t a c k c o n f i g . h , r e s p o n d i n g r i g h t away” ) ;
return a t t r e a d c a l l b a c k h a n d l e b l o b ( ( const uint8 t ∗ )
t e s t s t r i n g , ( uint16 t ) s t r l e n ( t e s t s t r i n g ) , o f f s e t , b u f f e r ,
buffer size ) ;
}
#endif

return 0 ;
}

/∗

s t a t i c int a t t w r i t e c a l l b a c k ( hci con handle t connection handle ,


u i n t 1 6 t att handle , u i n t 1 6 t transaction mode , u i n t 1 6 t o f f s e t ,
uint8 t ∗ buffer , uint16 t bu f fe r s iz e ){
UNUSED( t r a n s a c t i o n m o d e ) ;
UNUSED( o f f s e t ) ;
UNUSED( b u f f e r s i z e ) ;
UNUSED( c o n n e c t i o n h a n d l e ) ;

i f ( a t t h a n d l e ==
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
) {
p r i n t f (” Write r e q u e s t , v a l u e : ”) ;
printf hexdump ( buffer , b u f f e r s i z e ) ;
#i f d e f ENABLE ATT DELAYED RESPONSE
i f ( value ready ){
p r i n t f (” Write c a l l b a c k , v a l u e r e a d y \n ”) ;
return 0;
} else {
p r i n t f (” Write c a l l b a c k f o r h a n d l e 0 x%02x , b u t not r e a d y −>
r e t u r n r e s p o n s e p e n d i n g \n ” , a t t h a n d l e ) ;
}
// s i m u l a t e d d e l a y e d r e s p o n s e f o r example
a t t t i m e r . p r o c e s s = &a t t u p d a t e v a l u e ;
b t s t a c k r u n l o o p s e t t i m e r (& a t t t i m e r , ATT VALUE DELAY MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& a t t t i m e r ) ;
r e t u r n ATT ERROR WRITE RESPONSE PENDING;
#e l s e
p r i n t f (”ENABLE ATT DELAYED RESPONSE not d e f i n e d i n
b t s t a c k c o n f i g . h , r e s p o n d i n g r i g h t away ”) ;
return 0;
#e n d i f
}
return 0;
}
127

0.69. LE ANCS Client - Apple Notification Service. Source Code: ancs client demo.c
0.70. LE Man-in-the-Middle Tool. Source Code: le mitm.c
The example first does an LE scan and allows the user to select a Peripheral
device. Then, it connects to the Peripheral and starts advertising with the
same data as the Peripheral device. ATT Requests and responses are forwarded
between the peripheral and the central Security requests are handled locally.
@note A Bluetooth Controller that supports Central and Peripheral Role at
the same time is required for this example. See chipset/README.md
0.71. Performance - Stream Data over GATT (Client). Source Code:
le streamer client.c
Connects to ‘LE Streamer’ and subscribes to test characteristic
0.71.1. Track throughput. We calculate the throughput by setting a start time
and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

#define TEST MODE WRITE WITHOUT RESPONSE 1


#define TEST MODE ENABLE NOTIFICATIONS 2
#define TEST MODE DUPLEX 3

// c o n f i g u r e t e s t mode : send only , r e c e i v e only , f u l l d u p l e x


#define TEST MODE TEST MODE DUPLEX

#define REPORT INTERVAL MS 3000

// s u p p o r t f o r m u l t i p l e c l i e n t s
static le streamer connection t le streamer connection ;

s t a t i c void t e s t r e s e t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k d a t a ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t , int
bytes sent ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s s e n t ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
128

0.72. Performance - Stream Data over GATT (Server). Source Code:


gatt streamer server.c
All newer operating systems provide GATT Client functionality. This example
shows how to get a maximal throughput via BLE:
• send whenever possible,
• use the max ATT MTU.
In theory, we should also update the connection parameters, but we
already get a connection interval of 30 ms and there’s no public way to
use a shorter interval with iOS (if we’re not implementing an HID device).
Note: To start the streaming, run the example. On remote device use
some GATT Explorer, e.g. LightBlue, BLExplr to enable notifications.
0.72.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager, and configures the ATT Server with
the pre-compiled ATT Database generated from les treamer.gatt. Finally, it
configures the advertisements and boots the Bluetooth stack.

s t a t i c void l e s t r e a m e r s e t u p ( void ) {

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

#i f d e f ENABLE GATT OVER CLASSIC


// i n i t SDP, c r e a t e r e c o r d f o r GATT and r e g i s t e r w i t h SDP
sdp init () ;
memset ( g a t t s e r v i c e b u f f e r , 0 , s i z e o f ( g a t t s e r v i c e b u f f e r ) ) ;
g a t t c r e a t e s d p r e c o r d ( g a t t s e r v i c e b u f f e r , 0 x10001 ,
ATT SERVICE GATT SERVICE START HANDLE,
ATT SERVICE GATT SERVICE END HANDLE) ;
sdp register service ( gatt service buffer ) ;
p r i n t f ( ”SDP s e r v i c e r e c o r d s i z e : %u\n” , d e g e t l e n (
gatt service buffer )) ;

// c o n f i g u r e C l a s s i c GAP
g a p s e t l o c a l n a m e ( ”GATT Streamer BR/EDR 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap discoverable control (1) ;
#endif

// s e t u p ATT s e r v e r
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, a t t w r i t e c a l l b a c k ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
129

// r e g i s t e r f o r ATT e v e n t s
att server register packet handler ( att packet handler ) ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;

// i n i t c l i e n t s t a t e
init connections () ;
}

0.72.2. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

s t a t i c void t e s t r e s e t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k s e n t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t , int
bytes sent ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s s e n t ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s s e n t −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.72.3. HCI Packet Handler. The packet handler is used track incoming connec-
tions and to stop notifications on disconnect It is also a good place to request
the connection parameter update as indicated in the commented code block.
130

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

uint16 t c o n n i n t e r v a l ;
hci con handle t con handle ;
s t a t i c const char ∗ const phy names [ ] = {
” Reserved ” , ” 1 M” , ” 2 M” , ” Codec ”
};

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
) {
p r i n t f ( ”To s t a r t t h e s t r e a m i n g , p l e a s e run t h e
l e s t r e a m e r c l i e n t example on o t h e r d e v i c e , o r u s e some
GATT E x p l o r e r , e . g . LightBlue , BLExplr . \ n” ) ;
}
break ;
case HCI EVENT DISCONNECTION COMPLETE :
con handle =
hci event disconnection complete get connection handle (
packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : d i s c o n n e c t , r e a s o n %02x\n” ,
con handle , h c i e v e n t d i s c o n n e c t i o n c o m p l e t e g e t r e a s o n (
packet ) ) ;
break ;
case HCI EVENT META GAP :
switch ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GAP SUBEVENT LE CONNECTION COMPLETE:
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
gap subevent le connection complete get connection handle
( packet ) ;
conn interval =
gap subevent le connection complete get conn interval (
packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : c o n n e c t e d − c o n n e c t i o n
i n t e r v a l %u.%02u ms , l a t e n c y %u\n” , c o n h a n d l e ,
c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
25 ∗ ( c o n n i n t e r v a l & 3 ) ,
gap subevent le connection complete get conn latency
( packet ) ) ;

// r e q u e s t min con i n t e r v a l 15 ms f o r iOS 11+


p r i n t f ( ”− LE Connection 0x%04x : r e q u e s t 15 ms c o n n e c t i o n
i n t e r v a l \n” , c o n h a n d l e ) ;
gap request connection parameter update ( con handle , 12 ,
1 2 , 4 , 0 x0048 ) ;
131

break ;
default :
break ;
}
break ;
case HCI EVENT LE META :
switch ( h c i e v e n t l e m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case HCI SUBEVENT LE CONNECTION UPDATE COMPLETE :
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
hci subevent le connection update complete get connection handle
( packet ) ;
conn interval =
hci subevent le connection update complete get conn interval
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : c o n n e c t i o n update −
c o n n e c t i o n i n t e r v a l %u.%02u ms , l a t e n c y %u\n” ,
c o n h a n d l e , c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
25 ∗ ( c o n n i n t e r v a l & 3 ) ,
hci subevent le connection update complete get conn latency
( packet ) ) ;
break ;
case HCI SUBEVENT LE DATA LENGTH CHANGE :
con handle =
hci subevent le data length change get connection handle
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : data l e n g t h change − max %
u b y t e s p e r p a c k e t \n” , c o n h a n d l e ,
hci subevent le data length change get max tx octets (
packet ) ) ;
break ;
case HCI SUBEVENT LE PHY UPDATE COMPLETE :
con handle =
hci subevent le phy update complete get connection handle
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : PHY update − u s i n g LE %s
PHY now\n” , c o n h a n d l e ,
phy names [
hci subevent le phy update complete get tx phy (
packet ) ] ) ;
break ;
default :
break ;
}
break ;

default :
break ;
}
}
132

0.72.4. ATT Packet Handler. The packet handler is used to track the ATT MTU
Exchange and trigger ATT send

s t a t i c void a t t p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

int mtu ;
le streamer connection t ∗ context ;
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case ATT EVENT CONNECTED:
// s e t u p new
context = connection for conn handle (
HCI CON HANDLE INVALID) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>c o u n t e r = ’A ’ ;
c o n t e x t −>c o n n e c t i o n h a n d l e =
a t t e v e n t c o n n e c t e d g e t h a n d l e ( packet ) ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( a t t s e r v e r g e t m t u (
c o n t e x t −>c o n n e c t i o n h a n d l e ) − 3 , s i z e o f ( c o n t e x t −>
test data ) ) ;
p r i n t f ( ”%c : ATT connected , h a n d l e 0x%04x , t e s t data l e n %u
\n” , c o n t e x t −>name , c o n t e x t −>c o n n e c t i o n h a n d l e ,
c o n t e x t −>t e s t d a t a l e n ) ;
break ;
case ATT EVENT MTU EXCHANGE COMPLETE:
mtu = a t t e v e n t m t u e x c h a n g e c o m p l e t e g e t M T U ( p a c k e t ) − 3 ;
context = connection for conn handle (
att event mtu exchange complete get handle ( packet ) ) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( mtu − 3 , s i z e o f (
c o n t e x t −>t e s t d a t a ) ) ;
p r i n t f ( ”%c : ATT MTU = %u => u s e t e s t data o f l e n %u\n” ,
c o n t e x t −>name , mtu , c o n t e x t −>t e s t d a t a l e n ) ;
break ;
case ATT EVENT CAN SEND NOW:
streamer () ;
break ;
case ATT EVENT DISCONNECTED:
context = connection for conn handle (
a t t e v e n t d i s c o n n e c t e d g e t h a n d l e ( packet ) ) ;
i f ( ! c o n t e x t ) break ;
// f r e e c o n n e c t i o n
p r i n t f ( ”%c : ATT d i s c o n n e c t e d , h a n d l e 0x%04x\n” , c o n t e x t −>
name , c o n t e x t −>c o n n e c t i o n h a n d l e ) ;
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d = 0 ;
c o n t e x t −>c o n n e c t i o n h a n d l e = HCI CON HANDLE INVALID ;
break ;
default :
break ;
133

}
break ;
default :
break ;
}
}

0.72.5. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

// f i n d n e x t a c t i v e s t r e a m i n g c o n n e c t i o n
int o l d c o n n e c t i o n i n d e x = c o n n e c t i o n i n d e x ;
while ( 1 ) {
// a c t i v e found ?
i f (( le streamer connections [ connection index ] . connection handle
!= HCI CON HANDLE INVALID) &&
( le streamer connections [ connection index ] .
l e n o t i f i c a t i o n e n a b l e d ) ) break ;

// c h e c k n e x t
next connection index () ;

// none found
i f ( c o n n e c t i o n i n d e x == o l d c o n n e c t i o n i n d e x ) return ;
}

l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t = &l e s t r e a m e r c o n n e c t i o n s [
connection index ] ;

// c r e a t e t e s t d a t a
c o n t e x t −>c o u n t e r ++;
i f ( c o n t e x t −>c o u n t e r > ’ Z ’ ) c o n t e x t −>c o u n t e r = ’A ’ ;
memset ( c o n t e x t −>t e s t d a t a , c o n t e x t −>c o u n t e r , c o n t e x t −>
test data len ) ;

// send
a t t s e r v e r n o t i f y ( c o n t e x t −>c o n n e c t i o n h a n d l e , c o n t e x t −>
v a l u e h a n d l e , ( uint8 t ∗ ) c o n t e x t −>t e s t d a t a , c o n t e x t −>
test data len ) ;

// t r a c k
t e s t t r a c k s e n t ( c o n t e x t , c o n t e x t −>t e s t d a t a l e n ) ;

// r e q u e s t n e x t send e v e n t
a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( c o n t e x t −>c o n n e c t i o n h a n d l e ) ;

// c h e c k n e x t
next connection index () ;
}
134

0.72.6. ATT Write. The only valid ATT write in this example is to the Client
Characteristic Configuration, which configures notification and indication. If
the ATT handle matches the client configuration handle, the new configuration
value is stored. If notifications get enabled, an ATT EVENT CAN SEND NOW
is requested. See Listing here.

s t a t i c int a t t w r i t e c a l l b a c k ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
a t t h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t o f f s e t , uint8 t
∗ b u f f e r , uint16 t b u f f e r s i z e ) {
UNUSED( o f f s e t ) ;

// p r i n t f (” a t t w r i t e c a l l b a c k a t t h a n d l e 0 x%04x , t r a n s a c t i o n mode
%u\n ” , a t t h a n d l e , t r a n s a c t i o n m o d e ) ;
i f ( t r a n s a c t i o n m o d e != ATT TRANSACTION MODE NONE) return 0 ;
le streamer connection t ∗ context = connection for conn handle (
con handle ) ;
switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d = l i t t l e e n d i a n r e a d 1 6 (
b u f f e r , 0 ) ==
GATT CLIENT CHARACTERISTICS CONFIGURATION NOTIFICATION ;
p r i n t f ( ”%c : N o t i f i c a t i o n s e n a b l e d %u\n” , c o n t e x t −>name ,
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d ) ;
i f ( c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d ) {
switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGU
:
c o n t e x t −>v a l u e h a n d l e =
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HAND
;
break ;
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGU
:
c o n t e x t −>v a l u e h a n d l e =
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 VALUE HAND
;
break ;
default :
break ;
}
a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( c o n t e x t −>
connection handle ) ;
}
135

t e s t r e s e t ( context ) ;
break ;
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
t e s t t r a c k s e n t ( context , b u f f e r s i z e ) ;
break ;
default :
p r i n t f ( ” Write t o 0x%04x , l e n %u\n” , a t t h a n d l e , b u f f e r s i z e ) ;
break ;
}
return 0 ;
}

0.73. LE Credit-Based Flow-Control Mode Client - Send Data over


L2CAP. Source Code: le credit based flow control mode client.c
Connects to ‘LE CBM Server’ and streams data via L2CAP Channel in LE
Credit-Based Flow-Control Mode (CBM)

0.73.1. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

#define REPORT INTERVAL MS 3000

// s u p p o r t f o r m u l t i p l e c l i e n t s
typedef struct {
char name ;
hci con handle t connection handle ;
uint16 t c i d ;
int c o u n t e r ;
char t e s t d a t a [ TEST PACKET SIZE ] ;
int t e s t d a t a l e n ;
uint32 t t e s t d a t a s e n t ;
uint32 t t e s t d a t a s t a r t ;
} le cbm connection t ;

static le cbm connection t le cbm connection ;

s t a t i c void t e s t r e s e t ( l e c b m c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k d a t a ( l e c b m c o n n e c t i o n t ∗ c o n t e x t , int
bytes transferred ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s t r a n s f e r r e d ;
// e v a l u a t e
136

uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.73.2. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

// c r e a t e t e s t d a t a
l e c b m c o n n e c t i o n . c o u n t e r ++;
i f ( le cbm connection . counter > ’Z ’ ) le cbm connection . counter = ’
A’ ;
memset ( l e c b m c o n n e c t i o n . t e s t d a t a , l e c b m c o n n e c t i o n . c o u n t e r ,
le cbm connection . test data len ) ;

// send
l 2 c a p s e n d ( l e c b m c o n n e c t i o n . c i d , ( uint8 t ∗ ) l e c b m c o n n e c t i o n .
test data , le cbm connection . test data len ) ;

// t r a c k
t e s t t r a c k d a t a (& l e c b m c o n n e c t i o n , l e c b m c o n n e c t i o n .
test data len ) ;

// r e q u e s t a n o t h e r p a c k e t
l2cap request can send now event ( le cbm connection . cid ) ;
}

0.73.3. SM Packet Handler. The packet handler is used to handle pairing re-
quests

0.74. LE Credit-Based Flow-Control Mode Server - Receive data over


L2CAP. Source Code: le credit based flow control mode server.c
iOS 11 and newer supports L2CAP channels in LE Credit-Based Flow-Control
Mode for fast transfer over LE https://github.com/bluekitchen/CBL2CAPChannel-
Demo
137

0.74.1. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

s t a t i c void t e s t r e s e t ( l e c b m c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k d a t a ( l e c b m c o n n e c t i o n t ∗ c o n t e x t , int
bytes transferred ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s t r a n s f e r r e d ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s s e n t −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

0.74.2. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

i f ( l e c b m c o n n e c t i o n . c i d == 0 ) return ;

// c r e a t e t e s t d a t a
l e c b m c o n n e c t i o n . c o u n t e r ++;
i f ( le cbm connection . counter > ’Z ’ ) le cbm connection . counter = ’
A’ ;
memset ( l e c b m c o n n e c t i o n . t e s t d a t a , l e c b m c o n n e c t i o n . c o u n t e r ,
le cbm connection . test data len ) ;

// send
l 2 c a p s e n d ( l e c b m c o n n e c t i o n . c i d , ( uint8 t ∗ ) l e c b m c o n n e c t i o n .
test data , le cbm connection . test data len ) ;

// t r a c k
t e s t t r a c k d a t a (& l e c b m c o n n e c t i o n , l e c b m c o n n e c t i o n .
test data len ) ;
138

// r e q u e s t a n o t h e r p a c k e t
l2cap request can send now event ( le cbm connection . cid ) ;
}

0.74.3. HCI + L2CAP Packet Handler. The packet handler is used to stop the
notifications and reset the MTU on connect It would also be a good place to
request the connection parameter update as indicated in the commented code
block.
0.74.4. SM Packet Handler.
0.74.5. Main Application Setup.
0.75. Performance - Stream Data over SPP (Client). Source Code: spp streamer client.c
The packet handler is used to handle pairing requests
Listing here shows main application code. It initializes L2CAP, the Security
Manager, and configures the ATT Server with the pre-compiled ATT Database
generated from lec reditb asedf lowc ontrolm odes erver.gatt. Finally, it configures
the advertisements and boots the Bluetooth stack.
Note: The SPP Streamer Client scans for and connects to SPP Streamer, and
measures the throughput.
0.75.1. Track throughput. We calculate the throughput by setting a start time
and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

#define REPORT INTERVAL MS 3000


s t a t i c uint32 t t e s t d a t a t r a n s f e r r e d ;
s t a t i c uint32 t t e s t d a t a s t a r t ;

s t a t i c void t e s t r e s e t ( void ) {
test data start = btstack run loop get time ms () ;
test data transferred = 0;
}

s t a t i c void t e s t t r a c k t r a n s f e r r e d ( int b y t e s s e n t ) {
t e s t d a t a t r a n s f e r r e d += b y t e s s e n t ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = t e s t d a t a t r a n s f e r r e d ∗ 1000 / t i m e p a s s e d ;
p r i n t f ( ”%u b y t e s −> %u.%03u kB/ s \n” , ( int ) t e s t d a t a t r a n s f e r r e d ,
( int ) b y t e s p e r s e c o n d / 1 0 0 0 , b y t e s p e r s e c o n d % 1 0 0 0 ) ;

// r e s t a r t
t e s t d a t a s t a r t = now ;
test data transferred = 0;
}
139

0.75.2. SDP Query Packet Handler. Store RFCOMM Channel for SPP service
and initiates RFCOMM connection

0.75.3. Gerenal Packet Handler. Handles startup (BTSTACK EVENT STATE),


inquiry, pairing, starts SDP query for SPP service, and RFCOMM connection

0.75.4. Main Application Setup. As with the packet and the heartbeat handlers,
the combined app setup contains the code from the individual example setups.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
UNUSED( a r g c ) ;
( void ) argv ;

l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

rfcomm init () ;

#i f d e f ENABLE L2CAP ENHANCED RETRANSMISSION MODE FOR RFCOMM


// s e t u p ERTM management
r f c o m m e n a b l e l 2 c a p e r t m (& r f c o m m e r t m r e q u e s t h a n d l e r , &
rfcomm ertm released handler ) ;
#endif

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// i n i t SDP
g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;

return 0 ;
}

0.76. Performance - Stream Data over SPP (Server). Source Code: spp streamer.c
After RFCOMM connections gets open, request a RFCOMM EVENT CAN SEND NOW
via rfcomm request can send now event().
When we get the RFCOMM EVENT CAN SEND NOW, send data and re-
quest another one.
Note: To test, run the example, pair from a remote device, and open the
Virtual Serial Port.
140

0.76.1. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

#define REPORT INTERVAL MS 3000


s t a t i c uint32 t t e s t d a t a t r a n s f e r r e d ;
s t a t i c uint32 t t e s t d a t a s t a r t ;

s t a t i c void t e s t r e s e t ( void ) {
test data start = btstack run loop get time ms () ;
test data transferred = 0;
}

s t a t i c void t e s t t r a c k t r a n s f e r r e d ( int b y t e s s e n t ) {
t e s t d a t a t r a n s f e r r e d += b y t e s s e n t ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = t e s t d a t a t r a n s f e r r e d ∗ 1000 / t i m e p a s s e d ;
p r i n t f ( ”%u b y t e s −> %u.%03u kB/ s \n” , ( int ) t e s t d a t a t r a n s f e r r e d ,
( int ) b y t e s p e r s e c o n d / 1 0 0 0 , b y t e s p e r s e c o n d % 1 0 0 0 ) ;

// r e s t a r t
t e s t d a t a s t a r t = now ;
test data transferred = 0;
}

0.76.2. Packet Handler. The packet handler of the combined example is just the
combination of the individual packet handlers.

0.76.3. Main Application Setup. As with the packet and the heartbeat handlers,
the combined app setup contains the code from the individual example setups.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] )


{
( void ) a r g c ;
( void ) argv ;

l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

rfcomm init () ;
141

r f c o m m r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , RFCOMM SERVER CHANNEL, 0


xffff );

#i f d e f ENABLE L2CAP ENHANCED RETRANSMISSION MODE FOR RFCOMM


// s e t u p ERTM management
r f c o m m e n a b l e l 2 c a p e r t m (& r f c o m m e r t m r e q u e s t h a n d l e r , &
rfcomm ertm released handler ) ;
#endif

// i n i t SDP, c r e a t e r e c o r d f o r SPP and r e g i s t e r w i t h SDP


sdp init () ;
memset ( s p p s e r v i c e b u f f e r , 0 , s i z e o f ( s p p s e r v i c e b u f f e r ) ) ;
spp create sdp record ( spp service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , RFCOMM SERVER CHANNEL, ”
SPP Streamer ” ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s p p s e r v i c e b u f f e r ) <= s i z e o f (
spp service buffer ) ) ;
sdp register service ( spp service buffer ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// s h o r t −c u t t o f i n d o t h e r SPP Streamer
g a p s e t c l a s s o f d e v i c e (TEST COD) ;

g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;


g a p s e t l o c a l n a m e ( ”SPP Streamer 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
gap discoverable control (1) ;

spp create test data () ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;

return 0 ;
}

0.77. A2DP Sink - Receive Audio Stream and Control Playback. Source
Code: a2dp sink demo.c
This A2DP Sink example demonstrates how to use the A2DP Sink service to
receive an audio data stream from a remote A2DP Source device. In addition,
the AVRCP Controller is used to get information on currently played media, such
are title, artist and album, as well as to control the playback, i.e. to play, stop,
repeat, etc. If HAVE BTSTACK STDIN is set, press SPACE on the console to
show the available AVDTP and AVRCP commands.
To test with a remote device, e.g. a mobile phone, pair from the remote device
with the demo, then start playing music on the remote device. Alternatively,
set the device addr string to the Bluetooth address of your remote device in the
code, and call connect from the UI.
142

For more info on BTstack audio, see our blog post A2DP Sink and Source on
STM32 F4 Discovery Board.
0.77.1. Main Application Setup. The Listing here shows how to set up AD2P
Sink and AVRCP services. Besides calling init() method for each service, you’ll
also need to register several packet handlers:
• hci packet handler - handles legacy pairing, here by using fixed ‘0000’ pin
code.
• a2dp sink packet handler - handles events on stream connection status
(established, released), the media codec configuration, and, the status of
the stream itself (opened, paused, stopped).
• handle l2cap media data packet - used to receive streaming data. If STORE TO WAV FILE
directive (check btstack config.h) is used, the SBC decoder will be used
to decode the SBC data into PCM frames. The resulting PCM frames
are then processed in the SBC Decoder callback.
• avrcp packet handler - receives AVRCP connect/disconnect event.
• avrcp controller packet handler - receives answers for sent AVRCP com-
mands.
• avrcp target packet handler - receives AVRCP commands, and registered
notifications.
• stdin process - used to trigger AVRCP commands to the A2DP Source
device, such are get now playing info, start, stop, volume control. Re-
quires HAVE BTSTACK STDIN.
To announce A2DP Sink and AVRCP services, you need to create
corresponding SDP records and register them with the SDP service.
Note, currently only the SBC codec is supported. If you want to store
the audio data in a file, you’ll need to define STORE TO WAV FILE. If
STORE TO WAV FILE directive is defined, the SBC decoder needs to
get initialized when a2dp sink packet handler receives event A2DP SUBEVENT STREAM S
The initialization of the SBC decoder requires a callback that handles
PCM data:
• handle pcm data - handles PCM audio frames. Here, they are stored in
a wav file if STORE TO WAV FILE is defined, and/or played using the
audio library.

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a 2 d p s i n k p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t e v e n t s i z e ) ;
s t a t i c void h a n d l e l 2 c a p m e d i a d a t a p a c k e t ( uint8 t s e i d , uint8 t ∗
packet , uint16 t s i z e ) ;
s t a t i c void a v r c p p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a v r c p c o n t r o l l e r p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a v r c p t a r g e t p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;
#i f d e f HAVE BTSTACK STDIN
143

s t a t i c void s t d i n p r o c e s s ( char cmd) ;


#endif

s t a t i c int setup demo ( void ) {

// i n i t p r o t o c o l s
l2cap init () ;
sdp init () ;
#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif
#i f d e f ENABLE AVRCP COVER ART
goep client init () ;
avrcp cover art client init () ;
#endif

// I n i t p r o f i l e s
a2dp sink init () ;
avrcp init () ;
avrcp controller init () ;
avrcp target init () ;

// C o n f i g u r e A2DP S i n k
a 2 d p s i n k r e g i s t e r p a c k e t h a n d l e r (& a 2 d p s i n k p a c k e t h a n d l e r ) ;
a 2 d p s i n k r e g i s t e r m e d i a h a n d l e r (& h a n d l e l 2 c a p m e d i a d a t a p a c k e t ) ;
a2dp sink demo stream endpoint t ∗ stream endpoint = &
a2dp sink demo stream endpoint ;
avdtp stream endpoint t ∗ local stream endpoint =
a 2 d p s i n k c r e a t e s t r e a m e n d p o i n t (AVDTP AUDIO,
AVDTP CODEC SBC,
media sbc codec capabilities
, sizeof (
media sbc codec capabilities
),
s t r e a m e n d p o i n t −>
media sbc codec configuration
, sizeof (
s t r e a m e n d p o i n t −>
media sbc codec configuration
));
b t s t a c k a s s e r t ( l o c a l s t r e a m e n d p o i n t != NULL) ;
// − S t o r e stream e n p o i n t ’ s SEP ID , as i t i s used by A2DP API t o
i d e n t i f y t h e stream e n d p o i n t
s t r e a m e n d p o i n t −>a 2 d p l o c a l s e i d = a v d t p l o c a l s e i d (
local stream endpoint ) ;

// C o n f i g u r e AVRCP C o n t r o l l e r + Ta r g e t
a v r c p r e g i s t e r p a c k e t h a n d l e r (& a v r c p p a c k e t h a n d l e r ) ;
a v r c p c o n t r o l l e r r e g i s t e r p a c k e t h a n d l e r (&
avrcp controller packet handler ) ;
144

a v r c p t a r g e t r e g i s t e r p a c k e t h a n d l e r (& a v r c p t a r g e t p a c k e t h a n d l e r )
;

// C o n f i g u r e SDP

// − C r e a t e and r e g i s t e r A2DP S i n k s e r v i c e r e c o r d
memset ( s d p a v d t p s i n k s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avdtp sink service buffer ) ) ;
a2dp sink create sdp record ( sdp avdtp sink service buffer ,
sdp create service record handle () ,
AVDTP SINK FEATURE MASK HEADPHONE, NULL, NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a v d t p s i n k s e r v i c e b u f f e r ) <=
sizeof ( sdp avdtp sink service buffer ) ) ;
sdp register service ( sdp avdtp sink service buffer ) ;

// − C r e a t e AVRCP C o n t r o l l e r s e r v i c e r e c o r d and r e g i s t e r i t w i t h
SDP. We send C a t e g o r y 1 commands t o t h e media p l a y e r , e . g .
p l a y / pause
memset ( s d p a v r c p c o n t r o l l e r s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avrcp controller service buffer )) ;
uint16 t c o n t r o l l e r s u p p o r t e d f e a t u r e s = 1 <<
AVRCP CONTROLLER SUPPORTED FEATURE CATEGORY PLAYER OR RECORDER
;
#i f d e f AVRCP BROWSING ENABLED
c o n t r o l l e r s u p p o r t e d f e a t u r e s |= 1 <<
AVRCP CONTROLLER SUPPORTED FEATURE BROWSING;
#endif
#i f d e f ENABLE AVRCP COVER ART
c o n t r o l l e r s u p p o r t e d f e a t u r e s |= 1 <<
AVRCP CONTROLLER SUPPORTED FEATURE COVER ART GET LINKED THUMBNAIL
;
#endif
avrcp controller create sdp record (
sdp avrcp controller service buffer ,
sdp create service record handle () ,
c o n t r o l l e r s u p p o r t e d f e a t u r e s , NULL, NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a v r c p c o n t r o l l e r s e r v i c e b u f f e r ) <=
sizeof ( s d p a v r c p c o n t r o l l e r s e r v i c e b u f f e r ) ) ;
sdp register service ( sdp avrcp controller service buffer ) ;

// − C r e a t e and r e g i s t e r A2DP S i n k s e r v i c e r e c o r d
// − We r e c e i v e C a t e g o r y 2 commands from t h e media p l a y e r , e . g .
volume up/down
memset ( s d p a v r c p t a r g e t s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avrcp target service buffer ) ) ;
uint16 t t a r g e t s u p p o r t e d f e a t u r e s = 1 <<
AVRCP TARGET SUPPORTED FEATURE CATEGORY MONITOR OR AMPLIFIER;
avrcp target create sdp record ( sdp avrcp target service buffer ,
sdp create service record handle () ,
t a r g e t s u p p o r t e d f e a t u r e s , NULL, NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a v r c p t a r g e t s e r v i c e b u f f e r ) <=
sizeof ( s d p a v r c p t a r g e t s e r v i c e b u f f e r ) ) ;
sdp register service ( sdp avrcp target service buffer ) ;
145

// − C r e a t e and r e g i s t e r D ev i c e ID (PnP) s e r v i c e r e c o r d
memset ( d e v i c e i d s d p s e r v i c e b u f f e r , 0 , s i z e o f (
device id sdp service buffer )) ;
device id create sdp record ( device id sdp service buffer ,
sdp create service record handle () ,
DEVICE ID VENDOR ID SOURCE BLUETOOTH,
BLUETOOTH COMPANY ID BLUEKITCHEN GMBH, 1 , 1 ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( d e v i c e i d s d p s e r v i c e b u f f e r ) <= s i z e o f
( device id sdp service buffer )) ;
sdp register service ( device id sdp service buffer ) ;

// C o n f i g u r e GAP − d i s c o v e r y / c o n n e c t i o n

// − S e t l o c a l name w i t h a t e m p l a t e B l u e t o o t h a d d r e s s , t h a t w i l l
be a u t o m a t i c a l l y
// r e p l a c e d w i t h an a c t u a l a d d r e s s once i t i s a v a i l a b l e , i . e .
when BTstack b o o t s
// up and s t a r t s t a l k i n g t o a B l u e t o o t h module .
g a p s e t l o c a l n a m e ( ”A2DP Sink Demo 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;

// − Allow t o show up i n B l u e t o o t h i n q u i r y
gap discoverable control (1) ;

// − S e t C l a s s o f D e vi c e − S e r v i c e C l a s s : Audio , Major D e vi c e
C l a s s : Audio , Minor : Headphone
g a p s e t c l a s s o f d e v i c e ( 0 x200404 ) ;

// − Allow f o r r o l e s w i t c h i n g e n e r a l and s n i f f mode


gap set default link policy settings (
LM LINK POLICY ENABLE ROLE SWITCH |
LM LINK POLICY ENABLE SNIFF MODE ) ;

// − Allow f o r r o l e s w i t c h on o u t g o i n g c o n n e c t i o n s
// − This a l l o w s A2DP Source , e . g . smartphone , t o become master
when we re−c o n n e c t t o i t .
gap set allow role switch ( true ) ;

// R e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// Inform a b o u t a u d i o p l a y b a c k / t e s t o p t i o n s
#i f d e f HAVE POSIX FILE IO
if (! btstack audio sink get instance () ){
p r i n t f ( ”No a u d i o p l a y b a c k . \ n” ) ;
} else {
p r i n t f ( ” Audio p l a y b a c k s u p p o r t e d . \ n” ) ;
}
#i f d e f STORE TO WAV FILE
p r i n t f ( ” Audio w i l l be s t o r e d t o \’% s \ ’ f i l e . \ n” , wav filename ) ;
#endif
146

#endif
return 0 ;
}

0.77.2. Handle Media Data Packet. Here the audio data, are received through
the handle l2cap media data packet callback. Currently, only the SBC media
codec is supported. Hence, the media data consists of the media packet header
and the SBC packet. The SBC frame will be stored in a ring buffer for later
processing (instead of decoding it to PCM right away which would require a
much larger buffer). If the audio stream wasn’t started already and there are
enough SBC frames in the ring buffer, start playback.

0.78. A2DP Source - Stream Audio and Control Volume. Source Code:
a2dp source demo.c
This A2DP Source example demonstrates how to send an audio data stream to
a remote A2DP Sink device and how to switch between two audio data sources.
In addition, the AVRCP Target is used to answer queries on currently played
media, as well as to handle remote playback control, i.e. play, stop, repeat, etc.
If HAVE BTSTACK STDIN is set, press SPACE on the console to show the
available AVDTP and AVRCP commands.
To test with a remote device, e.g. a Bluetooth speaker, set the device addr string
to the Bluetooth address of your remote device in the code, and use the UI to
connect and start playback.
For more info on BTstack audio, see our blog post A2DP Sink and Source on
STM32 F4 Discovery Board.

0.78.1. Main Application Setup. The Listing here shows how to setup AD2P
Source and AVRCP services. Besides calling init() method for each service,
you’ll also need to register several packet handlers:
• hci packet handler - handles legacy pairing, here by using fixed ‘0000’ pin
code.
• a2dp source packet handler - handles events on stream connection sta-
tus (established, released), the media codec configuration, and, the com-
mands on stream itself (open, pause, stopp).
• avrcp packet handler - receives connect/disconnect event.
• avrcp controller packet handler - receives answers for sent AVRCP com-
mands.
• avrcp target packet handler - receives AVRCP commands, and registered
notifications.
• stdin process - used to trigger AVRCP commands to the A2DP Source
device, such are get now playing info, start, stop, volume control. Re-
quires HAVE BTSTACK STDIN.
To announce A2DP Source and AVRCP services, you need to create
corresponding SDP records and register them with the SDP service.
147

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel


, uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a 2 d p s o u r c e p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ event , uint16 t e v e n t s i z e ) ;
s t a t i c void a v r c p p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a v r c p t a r g e t p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a v r c p c o n t r o l l e r p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;
#i f d e f HAVE BTSTACK STDIN
s t a t i c void s t d i n p r o c e s s ( char cmd) ;
#endif

s t a t i c void a 2 d p d e m o h e x c m o d c o n f i g u r e s a m p l e r a t e ( int s a m p l e r a t e )
;

s t a t i c int a 2 d p s o u r c e a n d a v r c p s e r v i c e s i n i t ( void ) {

// R e q u e s t r o l e change on r e c o n n e c t i n g h e a d s e t t o a l w a y s use them


i n s l a v e mode
hci set master slave policy (0) ;
// e n a b l e d EIR
h c i s e t i n q u i r y m o d e (INQUIRY MODE RSSI AND EIR) ;

l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

// I n i t i a l i z e A2DP Source
a2dp source init () ;
a 2 d p s o u r c e r e g i s t e r p a c k e t h a n d l e r (& a 2 d p s o u r c e p a c k e t h a n d l e r ) ;

// C r e a t e stream e n d p o i n t
avdtp stream endpoint t ∗ local stream endpoint =
a 2 d p s o u r c e c r e a t e s t r e a m e n d p o i n t (AVDTP AUDIO,
AVDTP CODEC SBC, m e d i a s b c c o d e c c a p a b i l i t i e s , s i z e o f (
media sbc codec capabilities ) , media sbc codec configuration ,
sizeof ( media sbc codec configuration ) ) ;
if (! local stream endpoint ){
p r i n t f ( ”A2DP S o u r c e : not enough memory t o c r e a t e l o c a l stream
e n d p o i n t \n” ) ;
return 1 ;
}

avdtp set preferred sampling frequency ( local stream endpoint ,


A2DP SOURCE DEMO PREFERRED SAMPLING RATE) ;

// S t o r e stream e n p o i n t ’ s SEP ID , as i t i s used by A2DP API t o


i n d e n t i f y t h e stream e n d p o i n t
148

media tracker . l o c a l s e i d = avdtp local seid ( local stream endpoint )


;
avdtp source register delay reporting category ( media tracker .
local seid ) ;

// I n i t i a l i z e AVRCP S e r v i c e
avrcp init () ;
a v r c p r e g i s t e r p a c k e t h a n d l e r (& a v r c p p a c k e t h a n d l e r ) ;
// I n i t i a l i z e AVRCP T a r g et
avrcp target init () ;
a v r c p t a r g e t r e g i s t e r p a c k e t h a n d l e r (& a v r c p t a r g e t p a c k e t h a n d l e r )
;

// I n i t i a l i z e AVRCP C o n t r o l l e r
avrcp controller init () ;
a v r c p c o n t r o l l e r r e g i s t e r p a c k e t h a n d l e r (&
avrcp controller packet handler ) ;

// I n i t i a l i z e SDP,
sdp init () ;

// C r e a t e A2DP Source s e r v i c e r e c o r d and r e g i s t e r i t w i t h SDP


memset ( s d p a 2 d p s o u r c e s e r v i c e b u f f e r , 0 , s i z e o f (
sdp a2dp source service buffer ) ) ;
a2dp source create sdp record ( sdp a2dp source service buffer ,
sdp create service record handle () ,
AVDTP SOURCE FEATURE MASK PLAYER, NULL, NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a 2 d p s o u r c e s e r v i c e b u f f e r ) <=
sizeof ( sdp a2dp source service buffer ) ) ;
sdp register service ( sdp a2dp source service buffer ) ;

// C r e a t e AVRCP T a r g e t s e r v i c e r e c o r d and r e g i s t e r i t w i t h SDP. We


r e c e i v e C a t e g o r y 1 commands from t h e headphone , e . g . p l a y /
pause
memset ( s d p a v r c p t a r g e t s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avrcp target service buffer ) ) ;
uint16 t s u p p o r t e d f e a t u r e s =
AVRCP FEATURE MASK CATEGORY PLAYER OR RECORDER;
#i f d e f AVRCP BROWSING ENABLED
s u p p o r t e d f e a t u r e s |= AVRCP FEATURE MASK BROWSING;
#endif
avrcp target create sdp record ( sdp avrcp target service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , s u p p o r t e d f e a t u r e s , NULL,
NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a v r c p t a r g e t s e r v i c e b u f f e r ) <=
sizeof ( s d p a v r c p t a r g e t s e r v i c e b u f f e r ) ) ;
sdp register service ( sdp avrcp target service buffer ) ;

// C r e a t e AVRCP C o n t r o l l e r s e r v i c e r e c o r d and r e g i s t e r i t w i t h SDP


. We send C a t e g o r y 2 commands t o t h e headphone , e . g . volume up
/down
memset ( s d p a v r c p c o n t r o l l e r s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avrcp controller service buffer )) ;
149

uint16 t c o n t r o l l e r s u p p o r t e d f e a t u r e s =
AVRCP FEATURE MASK CATEGORY MONITOR OR AMPLIFIER;
avrcp controller create sdp record (
sdp avrcp controller service buffer ,
sdp create service record handle () ,
c o n t r o l l e r s u p p o r t e d f e a t u r e s , NULL, NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a v r c p c o n t r o l l e r s e r v i c e b u f f e r ) <=
sizeof ( s d p a v r c p c o n t r o l l e r s e r v i c e b u f f e r ) ) ;
sdp register service ( sdp avrcp controller service buffer ) ;

// R e g i s t e r D e v i ce ID (PnP) s e r v i c e SDP r e c o r d
memset ( d e v i c e i d s d p s e r v i c e b u f f e r , 0 , s i z e o f (
device id sdp service buffer )) ;
device id create sdp record ( device id sdp service buffer ,
sdp create service record handle () ,
DEVICE ID VENDOR ID SOURCE BLUETOOTH,
BLUETOOTH COMPANY ID BLUEKITCHEN GMBH, 1 , 1 ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( d e v i c e i d s d p s e r v i c e b u f f e r ) <= s i z e o f
( device id sdp service buffer )) ;
sdp register service ( device id sdp service buffer ) ;

// S e t l o c a l name w i t h a t e m p l a t e B l u e t o o t h a d d r e s s , t h a t w i l l be
automatically
// r e p l a c e d w i t h a a c t u a l a d d r e s s once i t i s a v a i l a b l e , i . e . when
BTstack b o o t s
// up and s t a r t s t a l k i n g t o a B l u e t o o t h module .
g a p s e t l o c a l n a m e ( ”A2DP S o u r c e 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
gap discoverable control (1) ;
g a p s e t c l a s s o f d e v i c e ( 0 x200408 ) ;

// R e g i s t e r f o r HCI e v e n t s .
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

d a t a s o u r c e = STREAM MOD;

// Parse human r e a d a b l e B l u e t o o t h a d d r e s s .
sscanf bd addr ( device addr string , device addr ) ;

#i f d e f HAVE BTSTACK STDIN


btstack stdin setup ( stdin process ) ;
#endif
return 0 ;
}

0.79. AVRCP Browsing - Browse Media Players and Media Informa-


tion. Source Code: avrcp browsing client.c
This example demonstrates how to use the AVRCP Controller Browsing service
to browse madia players and media information on a remote AVRCP Source
device.
To test with a remote device, e.g. a mobile phone, pair from the remote device
with the demo, then use the UI for browsing. If HAVE BTSTACK STDIN is
150

set, press SPACE on the console to show the available AVDTP and AVRCP
commands.
0.79.1. Main Application Setup. The Listing here shows how to setup AVRCP
Controller Browsing service. To announce AVRCP Controller Browsing service,
you need to create corresponding SDP record and register it with the SDP service.
You’ll also need to register several packet handlers:
• stdin process callback - used to trigger AVRCP commands, such are get
media players, playlists, albums, etc. Requires HAVE BTSTACK STDIN.
• avrcp browsing controller packet handler - used to receive answers for
AVRCP commands.

s t a t i c void a v r c p b r o w s i n g c o n t r o l l e r p a c k e t h a n d l e r ( uint8 t
p a c k e t t y p e , uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a v r c p p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void a 2 d p s i n k p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t
channel , uint8 t ∗ packet , uint16 t s i z e ) ;

#i f d e f HAVE BTSTACK STDIN


s t a t i c void s t d i n p r o c e s s ( char cmd) ;
#endif

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// I n i t i a l i z e L2CAP .
l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

a2dp sink init () ;


a 2 d p s i n k r e g i s t e r p a c k e t h a n d l e r (& a 2 d p s i n k p a c k e t h a n d l e r ) ;

avdtp stream endpoint t ∗ local stream endpoint =


a 2 d p s i n k c r e a t e s t r e a m e n d p o i n t (AVDTP AUDIO,
AVDTP CODEC SBC, m e d i a s b c c o d e c c a p a b i l i t i e s , s i z e o f (
media sbc codec capabilities ) ,
media sbc codec configuration , sizeof (
media sbc codec configuration ) ) ;
if (! local stream endpoint ){
p r i n t f ( ”A2DP Sink : not enough memory t o c r e a t e l o c a l stream
e n d p o i n t \n” ) ;
return 1 ;
}
151

a2dp local seid = avdtp local seid ( local stream endpoint ) ;

// I n i t i a l i z e AVRCP s e r v i c e .
avrcp init () ;
// I n i t i a l i z e AVRCP C o n t r o l l e r & T ar g e t S e r v i c e .
avrcp controller init () ;
avrcp target init () ;

a v r c p r e g i s t e r p a c k e t h a n d l e r (& a v r c p p a c k e t h a n d l e r ) ;
a v r c p c o n t r o l l e r r e g i s t e r p a c k e t h a n d l e r (& a v r c p p a c k e t h a n d l e r ) ;
a v r c p t a r g e t r e g i s t e r p a c k e t h a n d l e r (& a v r c p p a c k e t h a n d l e r ) ;

// I n i t i a l i z e AVRCP Browsing S e r v i c e .
avrcp browsing init () ;
avrcp browsing controller init () ;
avrcp browsing target init () ;

// R e g i s t e r f o r HCI e v e n t s .
a v r c p b r o w s i n g c o n t r o l l e r r e g i s t e r p a c k e t h a n d l e r (&
avrcp browsing controller packet handler ) ;
a v r c p b r o w s i n g t a r g e t r e g i s t e r p a c k e t h a n d l e r (&
avrcp browsing controller packet handler ) ;
a v r c p b r o w s i n g r e g i s t e r p a c k e t h a n d l e r (&
avrcp browsing controller packet handler ) ;

// I n i t i a l i z e SDP.
sdp init () ;
// s e t u p AVDTP s i n k
memset ( s d p a v d t p s i n k s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avdtp sink service buffer ) ) ;
a2dp sink create sdp record ( sdp avdtp sink service buffer ,
sdp create service record handle () ,
AVDTP SINK FEATURE MASK HEADPHONE, NULL, NULL) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s d p a v d t p s i n k s e r v i c e b u f f e r ) <=
sizeof ( sdp avdtp sink service buffer ) ) ;
sdp register service ( sdp avdtp sink service buffer ) ;

// C r e a t e AVRCP s e r v i c e r e c o r d and r e g i s t e r i t w i t h SDP.


memset ( s d p a v r c p b r o w s i n g c o n t r o l l e r s e r v i c e b u f f e r , 0 , s i z e o f (
sdp avrcp browsing controller service buffer ) ) ;

uint16 t s u p p o r t e d f e a t u r e s =
AVRCP FEATURE MASK CATEGORY PLAYER OR RECORDER;
#i f d e f AVRCP BROWSING ENABLED
s u p p o r t e d f e a t u r e s |= AVRCP FEATURE MASK BROWSING;
#endif
avrcp controller create sdp record (
sdp avrcp browsing controller service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , s u p p o r t e d f e a t u r e s , NULL,
NULL) ;
btstack assert ( de get len (
s d p a v r c p b r o w s i n g c o n t r o l l e r s e r v i c e b u f f e r ) <= s i z e o f (
sdp avrcp browsing controller service buffer ) ) ;
152

sdp register service ( sdp avrcp browsing controller service buffer )


;

// S e t l o c a l name w i t h a t e m p l a t e B l u e t o o t h a d d r e s s , t h a t w i l l be
automatically
// r e p l a c e d w i t h a a c t u a l a d d r e s s once i t i s a v a i l a b l e , i . e . when
BTstack b o o t s
// up and s t a r t s t a l k i n g t o a B l u e t o o t h module .
g a p s e t l o c a l n a m e ( ”AVRCP Browsing C l i e n t 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
gap discoverable control (1) ;
g a p s e t c l a s s o f d e v i c e ( 0 x200408 ) ;

// R e g i s t e r f o r HCI e v e n t s .
hci event callback registration . callback = &
avrcp browsing controller packet handler ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

#i f d e f HAVE BTSTACK STDIN


// Parse human r e a d a b l e B l u e t o o t h a d d r e s s .
sscanf bd addr ( device addr string , device addr ) ;
btstack stdin setup ( stdin process ) ;
#endif
p r i n t f ( ” S t a r t i n g BTstack . . . \ n” ) ;
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.80. HFP AG - Audio Gateway. Source Code: hfp ag demo.c


This HFP Audio Gateway example demonstrates how to receive an output
from a remote HFP Hands-Free (HF) unit, and, if HAVE BTSTACK STDIN is
defined, how to control the HFP HF.
0.80.1. Main Application Setup. Listing here shows main application code. To
run a HFP AG service you need to initialize the SDP, and to create and register
HFP AG record with it. The packet handler is used for sending commands to
the HFP HF. It also receives the HFP HF’s answers. The stdin process callback
allows for sending commands to the HFP HF. At the end the Bluetooth stack is
started.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

sco demo init () ;

// R e q u e s t r o l e change on r e c o n n e c t i n g h e a d s e t t o a l w a y s use them


i n s l a v e mode
hci set master slave policy (0) ;
153

g a p s e t l o c a l n a m e ( ”HFP AG Demo 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
gap discoverable control (1) ;

// L2CAP
l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

uint16 t s u p p o r t e d f e a t u r e s =
(1<<HFP AGSF ESCO S4 ) |
(1<<HFP AGSF HF INDICATORS) |
(1<<HFP AGSF CODEC NEGOTIATION) |
(1<<HFP AGSF EXTENDED ERROR RESULT CODES) |
(1<<HFP AGSF ENHANCED CALL CONTROL) |
(1<<HFP AGSF ENHANCED CALL STATUS) |
(1<<HFP AGSF ABILITY TO REJECT A CALL) |
(1<<HFP AGSF IN BAND RING TONE) |
(1<<HFP AGSF VOICE RECOGNITION FUNCTION) |
(1<<HFP AGSF ENHANCED VOICE RECOGNITION STATUS) |
(1<<HFP AGSF VOICE RECOGNITION TEXT) |
(1<<HFP AGSF EC NR FUNCTION) |
(1<<HFP AGSF THREE WAY CALLING) ;

// HFP
rfcomm init () ;
h f p a g i n i t ( rfcomm channel nr ) ;
hfp ag init supported features ( supported features ) ;
h f p a g i n i t c o d e c s ( sizeof ( codecs ) , codecs ) ;
hfp ag init ag indicators ( ag indicators nr , ag indicators ) ;
hfp ag init hf indicators ( hf indicators nr , hf indicators ) ;
hfp ag init call hold services ( call hold services nr ,
call hold services ) ;
h f p a g s e t s u b c r i b e r n u m b e r i n f o r m a t i o n (& s u b s c r i b e r n u m b e r , 1 ) ;

// SDP S e r v e r
sdp init () ;
memset ( h f p s e r v i c e b u f f e r , 0 , s i z e o f ( h f p s e r v i c e b u f f e r ) ) ;
hfp ag create sdp record with codecs ( hfp service buffer ,
sdp create service record handle () ,
r fc om m c ha nn el nr , h f p a g s e r v i c e n a m e , 0 ,
supported features , sizeof ( codecs ) , codecs
);
b t s t a c k a s s e r t ( d e g e t l e n ( h f p s e r v i c e b u f f e r ) <= s i z e o f (
hfp service buffer )) ;
sdp register service ( hfp service buffer ) ;

// r e g i s t e r f o r HCI e v e n t s and SCO p a c k e t s


h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
h c i r e g i s t e r s c o p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;
154

// r e g i s t e r f o r HFP e v e n t s
h f p a g r e g i s t e r p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;

// p a r s e human r e a d a b l e B l u e t o o t h a d d r e s s
sscanf bd addr ( device addr string , device addr ) ;

#i f d e f HAVE BTSTACK STDIN


btstack stdin setup ( stdin process ) ;
#endif
// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.81. HFP HF - Hands-Free. Source Code: hfp hs demo.c


This HFP Hands-Free example demonstrates how to receive an output from a
remote HFP audio gateway (AG), and, if HAVE BTSTACK STDIN is defined,
how to control the HFP AG.
0.81.1. Main Application Setup. Listing here shows main application code. To
run a HFP HF service you need to initialize the SDP, and to create and register
HFP HF record with it. The packet handler is used for sending commands to
the HFP AG. It also receives the HFP AG’s answers. The stdin process callback
allows for sending commands to the HFP AG. At the end the Bluetooth stack is
started.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// I n i t p r o t o c o l s
// i n i t L2CAP
l2cap init () ;
rfcomm init () ;
sdp init () ;
#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

// I n i t p r o f i l e s
uint16 t h f s u p p o r t e d f e a t u r e s =
(1<<HFP HFSF ESCO S4 ) |
(1<<HFP HFSF CLI PRESENTATION CAPABILITY) |
(1<<HFP HFSF HF INDICATORS) |
(1<<HFP HFSF CODEC NEGOTIATION) |
(1<<HFP HFSF ENHANCED CALL STATUS) |
(1<<HFP HFSF VOICE RECOGNITION FUNCTION) |
155

(1<<HFP HFSF ENHANCED VOICE RECOGNITION STATUS) |


(1<<HFP HFSF VOICE RECOGNITION TEXT) |
(1<<HFP HFSF EC NR FUNCTION) |
(1<<HFP HFSF REMOTE VOLUME CONTROL) ;

h f p h f i n i t ( rfcomm channel nr ) ;
hfp hf init supported features ( hf supported features ) ;
h f p h f i n i t h f i n d i c a t o r s ( s i z e o f ( i n d i c a t o r s ) / s i z e o f ( uint16 t ) ,
indicators ) ;
h f p h f i n i t c o d e c s ( sizeof ( codecs ) , codecs ) ;
hfp hf register packet handler ( hfp hf packet handler ) ;

// C o n f i g u r e SDP

// − C r e a t e and r e g i s t e r HFP HF s e r v i c e r e c o r d
memset ( h f p s e r v i c e b u f f e r , 0 , s i z e o f ( h f p s e r v i c e b u f f e r ) ) ;
hfp hf create sdp record with codecs ( hfp service buffer ,
sdp create service record handle () ,
rf c om m c ha nn el n r , h f p h f s e r v i c e n a m e ,
hf supported features , sizeof ( codecs ) , codecs ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( h f p s e r v i c e b u f f e r ) <= s i z e o f (
hfp service buffer )) ;
sdp register service ( hfp service buffer ) ;

// C o n f i g u r e GAP − d i s c o v e r y / c o n n e c t i o n

// − S e t l o c a l name w i t h a t e m p l a t e B l u e t o o t h a d d r e s s , t h a t w i l l
be a u t o m a t i c a l l y
// r e p l a c e d w i t h an a c t u a l a d d r e s s once i t i s a v a i l a b l e , i . e .
when BTstack b o o t s
// up and s t a r t s t a l k i n g t o a B l u e t o o t h module .
g a p s e t l o c a l n a m e ( ”HFP HF Demo 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;

// − Allow t o show up i n B l u e t o o t h i n q u i r y
gap discoverable control (1) ;

// − S e t C l a s s o f D e vi c e − S e r v i c e C l a s s : Audio , Major D e vi c e
C l a s s : Audio , Minor : Hands−Free d e v i c e
g a p s e t c l a s s o f d e v i c e ( 0 x200408 ) ;

// − Allow f o r r o l e s w i t c h i n g e n e r a l and s n i f f mode


gap set default link policy settings (
LM LINK POLICY ENABLE ROLE SWITCH |
LM LINK POLICY ENABLE SNIFF MODE ) ;

// − Allow f o r r o l e s w i t c h on o u t g o i n g c o n n e c t i o n s − t h i s a l l o w s
HFP AG, e . g . smartphone , t o become master when we re−c o n n e c t
to i t
gap set allow role switch ( true ) ;

// R e g i s t e r f o r HCI e v e n t s and SCO p a c k e t s


h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
156

h c i r e g i s t e r s c o p a c k e t h a n d l e r (& h c i p a c k e t h a n d l e r ) ;

// I n i t SCO / HFP a u d i o p r o c e s s i n g
sco demo init () ;

#i f d e f HAVE BTSTACK STDIN


// p a r s e human r e a d a b l e B l u e t o o t h a d d r e s s
sscanf bd addr ( device addr string , device addr ) ;
btstack stdin setup ( stdin process ) ;
#endif

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.82. HSP AG - Audio Gateway. Source Code: hsp ag demo.c


This example implements a HSP Audio Gateway device that sends and receives
audio signal over HCI SCO. It demonstrates how to receive an output from a
remote headset (HS), and, if HAVE BTSTACK STDIN is defined, how to control
the HS.
0.82.1. Audio Transfer Setup. A pre-computed sine wave (160Hz) is used as
the input audio signal. 160 Hz. To send and receive an audio signal, EN-
ABLE SCO OVER HCI has to be defined.
Tested working setups:
• Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter,
921600 baud
• Ubuntu 14 64-bit, CSR USB dongle
• OS X 10.11, CSR USB dongle
0.82.2. Main Application Setup. Listing here shows main application code. To
run a HSP Audio Gateway service you need to initialize the SDP, and to create
and register HSP AG record with it. In this example, the SCO over HCI is used
to receive and send an audio signal.
Two packet handlers are registered:
• The HCI SCO packet handler receives audio data.
• The HSP AG packet handler is used to trigger sending of audio data and
commands to the HS. It also receives the AG’s answers.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

sco demo init () ;


s c o d e m o s e t c o d e c (HFP CODEC CVSD) ;
157

l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

sdp init () ;

memset ( ( uint8 t ∗ ) h s p s e r v i c e b u f f e r , 0 , s i z e o f ( h s p s e r v i c e b u f f e r
));
hsp ag create sdp record ( hsp service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , rf c om m c ha nn el n r ,
hsp ag service name ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( h s p s e r v i c e b u f f e r ) <= s i z e o f (
hsp service buffer ) ) ;
sdp register service ( hsp service buffer ) ;

rfcomm init () ;

h s p a g i n i t ( rfcomm channel nr ) ;
h s p a g r e g i s t e r p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;

// r e g i s t e r f o r SCO p a c k e t s
h c i r e g i s t e r s c o p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;

// p a r s e human r e a d a b l e B l u e t o o t h a d d r e s s
sscanf bd addr ( device addr string , device addr ) ;

#i f d e f HAVE BTSTACK STDIN


btstack stdin setup ( stdin process ) ;
#endif

gap s e t l o c a l n a m e ( device name ) ;


gap discoverable control (1) ;
gap s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap s e t c l a s s o f d e v i c e ( 0 x400204 ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.83. HSP HS - Headset. Source Code: hsp hs demo.c


This example implements a HSP Headset device that sends and receives audio
signal over HCI SCO. It demonstrates how to receive an output from a remote
audio gateway (AG), and, if HAVE BTSTACK STDIN is defined, how to control
the AG.
0.83.1. Audio Transfer Setup. A pre-computed sine wave (160Hz) is used as
the input audio signal. 160 Hz. To send and receive an audio signal, EN-
ABLE SCO OVER HCI has to be defined.
158

Tested working setups:


• Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter,
921600 baud
• Ubuntu 14 64-bit, CSR USB dongle
• OS X 10.11, CSR USB dongle
0.83.2. Main Application Setup. Listing here shows main application code. To
run a HSP Headset service you need to initialize the SDP, and to create and
register HSP HS record with it. In this example, the SCO over HCI is used to
receive and send an audio signal.
Two packet handlers are registered:
• The HCI SCO packet handler receives audio data.
• The HSP HS packet handler is used to trigger sending of audio data and
commands to the AG. It also receives the AG’s answers.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

sco demo init () ;


s c o d e m o s e t c o d e c (HFP CODEC CVSD) ;

l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

sdp init () ;
memset ( h s p s e r v i c e b u f f e r , 0 , s i z e o f ( h s p s e r v i c e b u f f e r ) ) ;
hsp hs create sdp record ( hsp service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , rf c om m c ha nn el n r ,
hsp hs service name , 0) ;
b t s t a c k a s s e r t ( d e g e t l e n ( h s p s e r v i c e b u f f e r ) <= s i z e o f (
hsp service buffer ) ) ;
sdp register service ( hsp service buffer ) ;

rfcomm init () ;

h s p h s i n i t ( rfcomm channel nr ) ;

// r e g i s t e r f o r HCI e v e n t s and SCO p a c k e t s


h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
h c i r e g i s t e r s c o p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;

// r e g i s t e r f o r HSP e v e n t s
hsp hs register packet handler ( packet handler ) ;
159

#i f d e f HAVE BTSTACK STDIN


btstack stdin setup ( stdin process ) ;
#endif

gap s e t l o c a l n a m e ( ”HSP HS Demo 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;


gap discoverable control (1) ;
gap s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap s e t c l a s s o f d e v i c e ( 0 x240404 ) ;

// Parse human r e a d a b l e B l u e t o o t h a d d r e s s .
sscanf bd addr ( device addr string , device addr ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.84. Audio Driver - Play Sine. Source Code: audio duplex.c


Play sine to test and validate audio output with simple wave form.
0.85. Audio Driver - Play 80’s MOD Song. Source Code: mod player.c
0.86. Audio Driver - Forward Audio from Source to Sink. Source Code:
audio duplex.c
0.87. SPP Server - Heartbeat Counter over RFCOMM. Source Code:
spp counter.c
The Serial port profile (SPP) is widely used as it provides a serial port over
Bluetooth. The SPP counter example demonstrates how to setup an SPP service,
and provide a periodic timer over RFCOMM.
Note: To test, please run the spp counter example, and then pair from a
remote device, and open the Virtual Serial Port.
0.87.1. SPP Service Setup. To provide an SPP service, the L2CAP, RFCOMM,
and SDP protocol layers are required. After setting up an RFCOMM service with
channel nubmer RFCOMM SERVER CHANNEL, an SDP record is created and
registered with the SDP server. Example code for SPP service setup is provided
in Listing here. The SDP record created by function spp create sdp record con-
sists of a basic SPP definition that uses the provided RFCOMM channel ID and
service name. For more details, please have a look at it in src/sdp_util.c.
The SDP record is created on the fly in RAM and is deterministic. To preserve
valuable RAM, the result could be stored as constant data inside the ROM.

s t a t i c void s p p s e r v i c e s e t u p ( void ) {

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
160

l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

rfcomm init () ;
r f c o m m r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , RFCOMM SERVER CHANNEL, 0
x f f f f ) ; // r e s e r v e d channel , mtu l i m i t e d by l 2 c a p

// i n i t SDP, c r e a t e r e c o r d f o r SPP and r e g i s t e r w i t h SDP


sdp init () ;
memset ( s p p s e r v i c e b u f f e r , 0 , s i z e o f ( s p p s e r v i c e b u f f e r ) ) ;
spp create sdp record ( spp service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , RFCOMM SERVER CHANNEL, ”
SPP Counter ” ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s p p s e r v i c e b u f f e r ) <= s i z e o f (
spp service buffer ) ) ;
sdp register service ( spp service buffer ) ;
}

0.87.2. Periodic Timer Setup. The heartbeat handler increases the real counter
every second, and sends a text string with the counter value, as shown in Listing
here.

s t a t i c btstack timer source t h e a r t b e a t ;


s t a t i c char l i n e B u f f e r [ 3 0 ] ;
s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {
s t a t i c int c o u n t e r = 0 ;

i f ( rfcomm channel id ) {
s n p r i n t f ( l i n e B u f f e r , s i z e o f ( l i n e B u f f e r ) , ” BTstack c o u n t e r %04u\n
” , ++c o u n t e r ) ;
p r i n t f ( ”%s ” , l i n e B u f f e r ) ;

rfcomm request can send now event ( rfcomm channel id ) ;


}

b t s t a c k r u n l o o p s e t t i m e r ( t s , HEARTBEAT PERIOD MS) ;


btstack run loop add timer ( ts ) ;
}

s t a t i c void o n e s h o t t i m e r s e t u p ( void ) {
// s e t one−s h o t t i m e r
h e a r t b e a t . p r o c e s s = &h e a r t b e a t h a n d l e r ;
b t s t a c k r u n l o o p s e t t i m e r (& h e a r t b e a t , HEARTBEAT PERIOD MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& h e a r t b e a t ) ;
}
161

0.87.3. Bluetooth Logic. The Bluetooth logic is implemented within the packet
handler, see Listing here. In this example, the following events are passed se-
quentially:
• BTSTACK EVENT STATE,
• HCI EVENT PIN CODE REQUEST (Standard pairing) or
• HCI EVENT USER CONFIRMATION REQUEST (Secure Simple Pair-
ing),
• RFCOMM EVENT INCOMING CONNECTION,
• RFCOMM EVENT CHANNEL OPENED,
• RFCOMM EVENT CHANNEL CLOSED
Upon receiving HCI EVENT PIN CODE REQUEST event, we need
to handle authentication. Here, we use a fixed PIN code “0000”.
When HCI EVENT USER CONFIRMATION REQUEST is received, the user
will be asked to accept the pairing request. If the IO capability is set to
SSP IO CAPABILITY DISPLAY YES NO, the request will be automatically
accepted.
The RFCOMM EVENT INCOMING CONNECTION event indicates an in-
coming connection. Here, the connection is accepted. More logic is need, if
you want to handle connections from multiple clients. The incoming RFCOMM
connection event contains the RFCOMM channel number used during the SPP
setup phase and the newly assigned RFCOMM channel ID that is used by all
BTstack commands and events.
If RFCOMM EVENT CHANNEL OPENED event returns status greater then
0, then the channel establishment has failed (rare case, e.g., client crashes). On
successful connection, the RFCOMM channel ID and MTU for this channel are
made available to the heartbeat counter. After opening the RFCOMM chan-
nel, the communication between client and the application takes place. In this
example, the timer handler increases the real counter every second.
RFCOMM EVENT CAN SEND NOW indicates that it’s possible to send an
RFCOMM packet on the rfcomm cid that is include

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;

...
case HCI EVENT PIN CODE REQUEST :
// inform a b o u t p i n code r e q u e s t
p r i n t f ( ” Pin code r e q u e s t − u s i n g ’ 0 0 0 0 ’ \ n” ) ;
h c i e v e n t p i n c o d e r e q u e s t g e t b d a d d r ( packet , e v e n t a d d r )
;
g a p p i n c o d e r e s p o n s e ( e v e n t a d d r , ” 0000 ” ) ;
break ;

case HCI EVENT USER CONFIRMATION REQUEST :


// s s p : inform a b o u t u s e r c o n f i r m a t i o n r e q u e s t
p r i n t f ( ”SSP User C o n f i r m a t i o n Request with numeric v a l u e
’%06”PRIu32” ’ \ n” , l i t t l e e n d i a n r e a d 3 2 ( packet , 8 ) ) ;
162

p r i n t f ( ”SSP User C o n f i r m a t i o n Auto a c c e p t \n” ) ;


break ;

case RFCOMM EVENT INCOMING CONNECTION:


r f c o m m e v e n t i n c o m i n g c o n n e c t i o n g e t b d a d d r ( packet ,
event addr ) ;
rfcomm channel nr =
rfcomm event incoming connection get server channel (
packet ) ;
rfcomm channel id =
rfcomm event incoming connection get rfcomm cid ( packet
);
p r i n t f ( ”RFCOMM c h a n n e l %u r e q u e s t e d f o r %s \n” ,
rf c om m c ha nn el n r , b d a d d r t o s t r ( e v e n t a d d r ) ) ;
rfcomm accept connection ( rfcomm channel id ) ;
break ;

case RFCOMM EVENT CHANNEL OPENED:


i f ( rfcomm event channel opened get status ( packet ) ) {
p r i n t f ( ”RFCOMM c h a n n e l open f a i l e d , s t a t u s 0x%02x\n” ,
rfcomm event channel opened get status ( packet ) ) ;
} else {
rfcomm channel id =
rfcomm event channel opened get rfcomm cid ( packet ) ;
mtu = r f c o m m e v e n t c h a n n e l o p e n e d g e t m a x f r a m e s i z e (
packet ) ;
p r i n t f ( ”RFCOMM c h a n n e l open s u c c e e d e d . New RFCOMM
Channel ID %u , max frame s i z e %u\n” ,
r f c o m m c h a n n e l i d , mtu ) ;
}
break ;
case RFCOMM EVENT CAN SEND NOW:
rfcomm send ( r f c o m m c h a n n e l i d , ( uint8 t ∗ ) l i n e B u f f e r , (
uint16 t ) s t r l e n ( l i n e B u f f e r ) ) ;
break ;

...
}

0.88. SPP Server - RFCOMM Flow Control. Source Code: spp flowcontrol.c
This example adds explicit flow control for incoming RFCOMM data to the
SPP heartbeat counter example. We will highlight the changes compared to the
SPP counter example.

0.88.1. SPP Service Setup. Listing here shows how to provide one initial credit
during RFCOMM service initialization. Please note that providing a single credit
effectively reduces the credit-based (sliding window) flow control to a stop-and-
wait flow control that limits the data throughput substantially.

s t a t i c void s p p s e r v i c e s e t u p ( void ) {
163

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// i n i t L2CAP
l2cap init () ;

// i n i t RFCOMM
rfcomm init () ;
// r e s e r v e d channel , mtu l i m i t e d by l 2 c a p , 1 c r e d i t
r f c o m m r e g i s t e r s e r v i c e w i t h i n i t i a l c r e d i t s (& p a c k e t h a n d l e r ,
RFCOMM SERVER CHANNEL, 0 x f f f f , 1 ) ;

// i n i t SDP, c r e a t e r e c o r d f o r SPP and r e g i s t e r w i t h SDP


sdp init () ;
memset ( s p p s e r v i c e b u f f e r , 0 , s i z e o f ( s p p s e r v i c e b u f f e r ) ) ;
spp create sdp record ( spp service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , 1 , ”SPP Counter ” ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s p p s e r v i c e b u f f e r ) <= s i z e o f (
spp service buffer ) ) ;
sdp register service ( spp service buffer ) ;
}

0.88.2. Periodic Timer Setup. Explicit credit management is recommended when


received RFCOMM data cannot be processed immediately. In this example, de-
layed processing of received data is simulated with the help of a periodic timer
as follows. When the packet handler receives a data packet, it does not provide a
new credit, it sets a flag instead, see Listing here. If the flag is set, a new credit
will be granted by the heartbeat handler, introducing a delay of up to 1 second.
The heartbeat handler code is shown in Listing here.

s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {
i f ( rfcomm send credit ){
rfcomm grant credits ( rfcomm channel id , 1) ;
rfcomm send credit = 0;
}
b t s t a c k r u n l o o p s e t t i m e r ( t s , HEARTBEAT PERIOD MS) ;
btstack run loop add timer ( ts ) ;
}

// B l u e t o o t h l o g i c
s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,
uint8 t ∗ packet , uint16 t s i z e ) {
...
case RFCOMM DATA PACKET:
f o r ( i =0; i <s i z e ; i ++){
putchar ( packet [ i ] ) ;
};
164

p u t c h a r ( ’ \n ’ ) ;
rfcomm send credit = 1;
break ;
...
}

0.89. PAN - lwIP HTTP and DHCP Server. Source Code: pan lwip http server.c
Bluetooth PAN is mainly used for Internet Tethering, where e.g. a mobile
phone provides internet connection to a laptop or a tablet.
Instead of regular internet access, it’s also possible to provide a Web app
on a Bluetooth device, e.g. for configuration or maintenance. For some device,
this can be a more effective way to provide an interface compared to dedicated
smartphone applications (for Android and iOS).
Before iOS 11, accessing an HTTP server via Bluetooth PAN was not sup-
ported on the iPhone, but on iPod and iPad. With iOS 11, this works as ex-
pected.
After pairing your device, please open the URL http://192.168.7.1 in your web
browser.
0.89.1. Packet Handler. All BNEP events are handled in the platform/bnep lwip.c
BNEP-LWIP Adapter. Here, we only print status information and handle pairing
requests.
0.89.2. PAN BNEP Setup.
0.89.3. DHCP Server Configuration.
0.89.4. Large File Download.
0.89.5. DHCP Server Setup.
0.89.6. Main.
0.90. BNEP/PANU (Linux only). Source Code: panu demo.c
BNEP EVENT CHANNEL OPENED is received after a BNEP connection
was established or or when the connection fails. The status field returns the
error code.
BNEP EVENT CHANNEL CLOSED is received when the connection gets
closed.
Listing here shows the setup of the PAN setup
Listing here shows the DHCP Server configuration for network 192.168.7.0/8
Listing here Shows how a configurable test file for performance tests is gener-
ated on the fly. The filename is the number of bytes to generate, e.g. /1048576.txt
results in a 1MB file.
Listing here shows the setup of the lwIP network stack and starts the DHCP
Server
Setup the lwIP network and PAN NAP
This example implements both a PANU client and a server. In server mode, it
sets up a BNEP server and registers a PANU SDP record and waits for incoming
165

connections. In client mode, it connects to a remote device, does an SDP Query


to identify the PANU service and initiates a BNEP connection.
Note: currently supported only on Linux and provides a TAP network interface
which you can configure yourself.
To enable client mode, uncomment ENABLE PANU CLIENT below.

0.90.1. Main application configuration. In the application configuration, L2CAP


and BNEP are initialized and a BNEP service, for server mode, is registered,
before the Bluetooth stack gets started, as shown in Listing here.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void h a n d l e s d p c l i e n t q u e r y r e s u l t ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void n e t w o r k s e n d p a c k e t c a l l b a c k ( const uint8 t ∗ packet ,
uint16 t s i z e ) ;

s t a t i c void p a n u s e t u p ( void ) {

// I n i t i a l i z e L2CAP
l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

// i n i t SDP, c r e a t e r e c o r d f o r PANU and r e g i s t e r w i t h SDP


sdp init () ;
memset ( p a n u s d p r e c o r d , 0 , s i z e o f ( p a n u s d p r e c o r d ) ) ;
uint16 t n e t w o r k p a c k e t t y p e s [ ] = { NETWORK TYPE IPv4,
NETWORK TYPE ARP, 0 } ; // 0 as end o f l i s t

// I n i t i a l i s e BNEP
bnep init () ;
// Minimum L2CAP MTU f o r bnep i s 1691 b y t e s
#i f d e f ENABLE PANU CLIENT
b n e p r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , BLUETOOTH SERVICE CLASS PANU
, 1691) ;
// PANU
pan create panu sdp record ( panu sdp record ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , n e t w o r k p a c k e t t y p e s , NULL
, NULL, BNEP SECURITY NONE) ;
#e l s e
b n e p r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , BLUETOOTH SERVICE CLASS NAP,
1691) ;
// NAP Network Access Type : Other , 1 MB/ s
pan create nap sdp record ( panu sdp record ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , n e t w o r k p a c k e t t y p e s , NULL
, NULL, BNEP SECURITY NONE, PAN NET ACCESS TYPE OTHER,
1 0 0 0 0 0 0 , NULL, NULL) ;
166

#endif
b t s t a c k a s s e r t ( d e g e t l e n ( p a n u s d p r e c o r d ) <= s i z e o f (
panu sdp record ) ) ;
s d p r e g i s t e r s e r v i c e ( panu sdp record ) ;

// I n i t i a l i z e network i n t e r f a c e
b t s t a c k n e t w o r k i n i t (& n e t w o r k s e n d p a c k e t c a l l b a c k ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
}

0.90.2. SDP parser callback. The SDP parsers retrieves the BNEP PAN UUID as
explained in Section [on SDP BNEP Query example](#sec:sdpbnepqueryExample}.

0.90.3. Packet Handler. The packet handler responds to various HCI Events.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e )
{
...
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
event = h c i e v e n t p a c k e t g e t t y p e ( packet ) ;
switch ( e v e n t ) {
#i f d e f ENABLE PANU CLIENT
case BTSTACK EVENT STATE:
i f ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) ==
HCI STATE WORKING) {
p r i n t f ( ” S t a r t SDP BNEP query f o r remote PAN Network
A c c e s s Po in t (NAP) . \ n” ) ;
s d p c l i e n t q u e r y u u i d 1 6 (& h a n d l e s d p c l i e n t q u e r y r e s u l t ,
remote addr , BLUETOOTH SERVICE CLASS NAP) ;
}
break ;
#endif
...

case BNEP EVENT CHANNEL OPENED:


i f ( bnep event channel opened get status ( packet ) ) {
p r i n t f ( ”BNEP c h a n n e l open f a i l e d , s t a t u s 0x%02x\n” ,
bnep event channel opened get status ( packet ) ) ;
} else {
bnep cid = bnep event channel opened get bnep cid (
packet ) ;
uuid source = bnep event channel opened get source uuid (
packet ) ;
uuid dest =
bnep event channel opened get destination uuid (
packet ) ;
mtu = bnep event channel opened get mtu ( packet ) ;
167

b n e p e v e n t c h a n n e l o p e n e d g e t r e m o t e a d d r e s s ( packet ,
event addr ) ;
p r i n t f ( ”BNEP c o n n e c t i o n open s u c c e e d e d t o %s s o u r c e UUID
0x%04x d e s t UUID : 0x%04x , max frame s i z e %u\n” ,
bd addr to str ( event addr ) , uuid source , uuid dest ,
mtu ) ;

gap local bd addr ( local addr ) ;


btstack network up ( local addr ) ;
p r i n t f ( ” Network I n t e r f a c e %s a c t i v a t e d \n” ,
btstack network get name () ) ;
}
break ;

case BNEP EVENT CHANNEL TIMEOUT:


p r i n t f ( ”BNEP c h a n n e l t i m e o u t ! Channel w i l l be c l o s e d \n” ) ;
break ;

case BNEP EVENT CHANNEL CLOSED:


p r i n t f ( ”BNEP c h a n n e l c l o s e d \n” ) ;
btstack network down ( ) ;
break ;

case BNEP EVENT CAN SEND NOW:


i f ( n e t w o r k b u f f e r l e n > 0) {
bnep send ( b n e p c i d , ( uint8 t ∗ ) n e t w o r k b u f f e r ,
network buffer len ) ;
network buffer len = 0;
btstack network packet sent () ;
}
break ;

default :
break ;
}
break ;

case BNEP DATA PACKET:


// Write o u t t h e e t h e r n e t frame t o t h e network i n t e r f a c e
b t s t a c k n e t w o r k p r o c e s s p a c k e t ( packet , s i z e ) ;
break ;

default :
break ;
}
}

When BTSTACK EVENT STATE with state HCI STATE WORKING is re-
ceived and the example is started in client mode, the remote SDP BNEP query
is started.
BNEP EVENT CHANNEL OPENED is received after a BNEP connection
was established or or when the connection fails. The status field returns the
error code.
168

The TAP network interface is then configured. A data source is set up and
registered with the run loop to receive Ethernet packets from the TAP interface.
The event contains both the source and destination UUIDs, as well as the
MTU for this connection and the BNEP Channel ID, which is used for sending
Ethernet packets over BNEP.
If there is a timeout during the connection setup, BNEP EVENT CHANNEL TIMEOUT
will be received and the BNEP connection will be closed
BNEP EVENT CHANNEL CLOSED is received when the connection gets
closed.
BNEP EVENT CAN SEND NOW indicates that a new packet can be send.
This triggers the send of a stored network packet. The tap datas source can be
enabled again
Ethernet packets from the remote device are received in the packet handler
with type BNEP DATA PACKET. It is forwarded to the TAP interface.

0.90.4. Network packet handler. A pointer to the network packet is stored and
a BNEP EVENT CAN SEND NOW requested

s t a t i c void n e t w o r k s e n d p a c k e t c a l l b a c k ( const uint8 t ∗ packet ,


uint16 t s i z e ) {
network buffer = packet ;
network buffer len = size ;
bnep request can send now event ( bnep cid ) ;
}

0.91. HID Keyboard Classic. Source Code: hid keyboard demo.c


This HID Device example demonstrates how to implement an HID keyboard.
Without a HAVE BTSTACK STDIN, a fixed demo text is sent If HAVE BTSTACK STDIN
is defined, you can type from the terminal

0.91.1. Main Application Setup. Listing here shows main application code. To
run a HID Device service you need to initialize the SDP, and to create and
register HID Device record with it. At the end the Bluetooth stack is started.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// a l l o w t o g e t found by i n q u i r y
gap discoverable control (1) ;
// use L i m i t e d D i s c o v e r a b l e Mode ; P e r i p h e r a l ; Keyboard as CoD
g a p s e t c l a s s o f d e v i c e ( 0 x2540 ) ;
// s e t l o c a l name t o be i d e n t i f i e d − z e r o e s w i l l be r e p l a c e d by
a c t u a l BD ADDR
g a p s e t l o c a l n a m e ( ”HID Keyboard Demo 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
// a l l o w f o r r o l e s w i t c h i n g e n e r a l and s n i f f mode
169

gap set default link policy settings (


LM LINK POLICY ENABLE ROLE SWITCH |
LM LINK POLICY ENABLE SNIFF MODE ) ;
// a l l o w f o r r o l e s w i t c h on o u t g o i n g c o n n e c t i o n s − t h i s a l l o w HID
Host t o become master when we re−c o n n e c t t o i t
gap set allow role switch ( true ) ;

// L2CAP
l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

// SDP S e r v e r
sdp init () ;
memset ( h i d s e r v i c e b u f f e r , 0 , s i z e o f ( h i d s e r v i c e b u f f e r ) ) ;

uint8 t hid virtual cable = 0;


uint8 t hid remote wake = 1 ;
uint8 t hid reconnect initiate = 1;
uint8 t hid normally connectable = 1;

h i d s d p r e c o r d t hid params = {
// h i d s e v i c e s u b c l a s s 2540 Keyboard , h i d c o u n n t r y code 33 US
0 x2540 , 3 3 ,
h i d v i r t u a l c a b l e , h i d r em o te w ak e ,
hid reconnect initiate , hid normally connectable ,
hid boot device ,
host max latency , host min timeout ,
3200 ,
hid descriptor keyboard ,
sizeof ( hid descriptor keyboard ) ,
hid device name
};

hid create sdp record ( hid service buffer ,


s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , &hid params ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( h i d s e r v i c e b u f f e r ) <= s i z e o f (
hid service buffer )) ;
sdp register service ( hid service buffer ) ;

// See h t t p s : / /www. b l u e t o o t h . com/ s p e c i f i c a t i o n s / a s s i g n e d −numbers /


company−i d e n t i f i e r s i f you don ’ t have a USB Vendor ID and need
a B l u e t o o t h Vendor ID
// d e v i c e i n f o : B l u e K i t c h e n GmbH, p r o d u c t 1 , v e r s i o n 1
device id create sdp record ( device id sdp service buffer ,
sdp create service record handle () ,
DEVICE ID VENDOR ID SOURCE BLUETOOTH,
BLUETOOTH COMPANY ID BLUEKITCHEN GMBH, 1 , 1 ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( d e v i c e i d s d p s e r v i c e b u f f e r ) <= s i z e o f
( device id sdp service buffer )) ;
170

sdp register service ( device id sdp service buffer ) ;

// HID D e v i ce
h i d d e v i c e i n i t ( hid boot device , sizeof ( hid descriptor keyboard ) ,
hid descriptor keyboard ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r HID e v e n t s
h i d d e v i c e r e g i s t e r p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;

#i f d e f HAVE BTSTACK STDIN


sscanf bd addr ( device addr string , device addr ) ;
btstack stdin setup ( stdin process ) ;
#endif

b t s t a c k r i n g b u f f e r i n i t (& s e n d b u f f e r , s e n d b u f f e r s t o r a g e , s i z e o f
( send buffer storage ) ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.92. HID Mouse Classic. Source Code: hid mouse demo.c


This HID Device example demonstrates how to implement an HID keyboard.
Without a HAVE BTSTACK STDIN, a fixed demo text is sent If HAVE BTSTACK STDIN
is defined, you can type from the terminal

0.92.1. Main Application Setup. Listing here shows main application code. To
run a HID Device service you need to initialize the SDP, and to create and
register HID Device record with it. At the end the Bluetooth stack is started.

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// a l l o w t o g e t found by i n q u i r y
gap discoverable control (1) ;
// use L i m i t e d D i s c o v e r a b l e Mode ; P e r i p h e r a l ; P o i n t i n g D e v ic e as
CoD
g a p s e t c l a s s o f d e v i c e ( 0 x2580 ) ;
// s e t l o c a l name t o be i d e n t i f i e d − z e r o e s w i l l be r e p l a c e d by
a c t u a l BD ADDR
g a p s e t l o c a l n a m e ( ”HID Mouse Demo 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
// a l l o w f o r r o l e s w i t c h i n g e n e r a l and s n i f f mode
171

gap set default link policy settings (


LM LINK POLICY ENABLE ROLE SWITCH |
LM LINK POLICY ENABLE SNIFF MODE ) ;
// a l l o w f o r r o l e s w i t c h on o u t g o i n g c o n n e c t i o n s − t h i s a l l o w HID
Host t o become master when we re−c o n n e c t t o i t
gap set allow role switch ( true ) ;

// L2CAP
l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

// SDP S e r v e r
sdp init () ;

uint8 t hid virtual cable = 0;


uint8 t hid remote wake = 1 ;
uint8 t hid reconnect initiate = 1;
uint8 t hid normally connectable = 1;

h i d s d p r e c o r d t hid params = {
// h i d s e v i c e s u b c l a s s 2580 Mouse , h i d c o u n n t r y code 33 US
0 x2580 , 3 3 ,
h i d v i r t u a l c a b l e , h i d r em o te w ak e ,
hid reconnect initiate , hid normally connectable ,
hid boot device ,
0xFFFF , 0xFFFF , 3 2 0 0 ,
hid descriptor mouse boot mode ,
sizeof ( hid descriptor mouse boot mode ) ,
hid device name
};

memset ( h i d s e r v i c e b u f f e r , 0 , s i z e o f ( h i d s e r v i c e b u f f e r ) ) ;
hid create sdp record ( hid service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , &hid params ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( h i d s e r v i c e b u f f e r ) <= s i z e o f (
hid service buffer )) ;
sdp register service ( hid service buffer ) ;

// See h t t p s : / /www. b l u e t o o t h . com/ s p e c i f i c a t i o n s / a s s i g n e d −numbers /


company−i d e n t i f i e r s i f you don ’ t have a USB Vendor ID and need
a B l u e t o o t h Vendor ID
// d e v i c e i n f o : B l u e K i t c h e n GmbH, p r o d u c t 2 , v e r s i o n 1
device id create sdp record ( device id sdp service buffer ,
sdp create service record handle () ,
DEVICE ID VENDOR ID SOURCE BLUETOOTH,
BLUETOOTH COMPANY ID BLUEKITCHEN GMBH, 2 , 1 ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( d e v i c e i d s d p s e r v i c e b u f f e r ) <= s i z e o f
( device id sdp service buffer )) ;
sdp register service ( device id sdp service buffer ) ;
172

// HID D e v i ce
h i d d e v i c e i n i t ( hid boot device , sizeof (
hid descriptor mouse boot mode ) ,
hid descriptor mouse boot mode ) ;
// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r HID
h i d d e v i c e r e g i s t e r p a c k e t h a n d l e r (& p a c k e t h a n d l e r ) ;

#i f d e f HAVE BTSTACK STDIN


btstack stdin setup ( stdin process ) ;
#endif
// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;
return 0 ;
}

0.93. HID Host Classic. Source Code: hid host demo.c


This example implements a HID Host. For now, it connects to a fixed device.
It will connect in Report protocol mode if this mode is supported by the HID
Device, otherwise it will fall back to BOOT protocol mode.

0.93.1. Main application configuration. In the application configuration, L2CAP


and HID host are initialized, and the link policies are set to allow sniff mode and
role change.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void h i d h o s t s e t u p ( void ) {

// I n i t i a l i z e L2CAP
l2cap init () ;

#i f d e f ENABLE BLE
// I n i t i a l i z e LE S e c u r i t y Manager . Needed f o r c r o s s −t r a n s p o r t key
derivation
sm init () ;
#endif

// I n i t i a l i z e HID Host
h i d h o s t i n i t ( hid descriptor storage , sizeof (
hid descriptor storage ) ) ;
hid host register packet handler ( packet handler ) ;

// Allow s n i f f mode r e q u e s t s by HID d e v i c e and s u p p o r t r o l e s w i t c h


173

gap set default link policy settings (


LM LINK POLICY ENABLE SNIFF MODE |
LM LINK POLICY ENABLE ROLE SWITCH) ;

// t r y t o become master on incoming c o n n e c t i o n s


h c i s e t m a s t e r s l a v e p o l i c y (HCI ROLE MASTER) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// D i s a b l e s t d o u t b u f f e r i n g
s e t v b u f ( s t d i n , NULL, IONBF , 0 ) ;
}

0.93.2. HID Report Handler. Use BTstack’s compact HID Parser to process in-
coming HID Report in Report protocol mode. Iterate over all fields and process
fields with usage page = 0x07 / Keyboard Check if SHIFT is down and process
first character (don’t handle multiple key presses)

0.93.3. Packet Handler. The packet handler responds to various HID events.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e )
{
...
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
event = h c i e v e n t p a c k e t g e t t y p e ( packet ) ;

switch ( e v e n t ) {
#i f n d e f HAVE BTSTACK STDIN
case BTSTACK EVENT STATE:
i f ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) ==
HCI STATE WORKING) {
s t a t u s = h i d h o s t c o n n e c t ( remote addr ,
h i d h o s t r e p o r t m o d e , &h i d h o s t c i d ) ;
i f ( s t a t u s != ERROR CODE SUCCESS) {
p r i n t f ( ”HID h o s t c o n n e c t f a i l e d , s t a t u s 0x%02x . \ n” ,
status ) ;
}
}
break ;
#endif
...
case HCI EVENT HID META :
switch ( h c i e v e n t h i d m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {

case HID SUBEVENT INCOMING CONNECTION :


// There i s an incoming c o n n e c t i o n : we can a c c e p t i t
or d e c l i n e i t .
174

// The h i d h o s t r e p o r t m o d e i n t h e
hid host accept connection function
// a l l o w s t h e a p p l i c a t i o n t o r e q u e s t a p r o t o c o l mode .
// For a v a i l a b l e p r o t o c o l modes , s e e
hid protocol mode t in b t s t a c k h i d . h f i l e .
hid host accept connection (
hid subevent incoming connection get hid cid (
packet ) , hid host report mode ) ;
break ;

case HID SUBEVENT CONNECTION OPENED:


// The s t a t u s f i e l d o f t h i s e v e n t i n d i c a t e s i f t h e
c o n t r o l and i n t e r r u p t
// c o n n e c t i o n s were opened s u c c e s s f u l l y .
status = hid subevent connection opened get status (
packet ) ;
i f ( s t a t u s != ERROR CODE SUCCESS) {
p r i n t f ( ” Connection f a i l e d , s t a t u s 0x%02x\n” , s t a t u s )
;
a p p s t a t e = APP IDLE ;
hid host cid = 0;
return ;
}
a p p s t a t e = APP CONNECTED;
hid host descriptor available = false ;
hid host cid =
h i d s u b e v e n t c o n n e c t i o n o p e n e d g e t h i d c i d ( packet )
;
p r i n t f ( ”HID Host c o n n e c t e d . \ n” ) ;
break ;

case HID SUBEVENT DESCRIPTOR AVAILABLE :


// This e v e n t w i l l f o l l o w s
HID SUBEVENT CONNECTION OPENED e v e n t .
// For incoming c o n n e c t i o n s , i . e . HID D e vi c e
i n i t i a t i n g the connection ,
// t h e HID SUBEVENT DESCRIPTOR AVAILABLE i s d e l a y e d ,
and some HID
// r e p o r t s may be r e c e i v e d v i a HID SUBEVENT REPORT
e v e n t . I t i s up t o
// t h e a p p l i c a t i o n i f t h e s e r e p o r t s s h o u l d be b u f f e r e d
or i g n o r e d u n t i l
// t h e HID d e s c r i p t o r i s a v a i l a b l e .
status = hid subevent descriptor available get status (
packet ) ;
i f ( s t a t u s == ERROR CODE SUCCESS) {
h i d h o s t d e s c r i p t o r a v a i l a b l e = true ;
p r i n t f ( ”HID D e s c r i p t o r a v a i l a b l e , p l e a s e s t a r t
t y p i n g . \ n” ) ;
} else {
p r i n t f ( ” Cannot h a n d l e i n p u t r e p o r t , HID D e s c r i p t o r
i s not a v a i l a b l e , s t a t u s 0x%02x\n” , s t a t u s ) ;
}
break ;
175

case HID SUBEVENT REPORT :


// Handle i n p u t r e p o r t .
if ( hid host descriptor available ){
hid host handle interrupt report (
h i d s u b e v e n t r e p o r t g e t r e p o r t ( packet ) ,
h i d s u b e v e n t r e p o r t g e t r e p o r t l e n ( packet ) ) ;
} else {
printf hexdump ( h i d s u b e v e n t r e p o r t g e t r e p o r t ( packet
) , h i d s u b e v e n t r e p o r t g e t r e p o r t l e n ( packet ) ) ;
}
break ;

case HID SUBEVENT SET PROTOCOL RESPONSE :


// For incoming c o n n e c t i o n s , t h e l i b r a r y w i l l s e t t h e
p r o t o c o l mode o f t h e
// HID D e v ic e as r e q u e s t e d i n t h e c a l l t o
h i d h o s t a c c e p t c o n n e c t i o n . The e v e n t
// r e p o r t s t h e r e s u l t . For c o n n e c t i o n s i n i t i a t e d by
calling hid host connect ,
// t h i s e v e n t w i l l o c c u r o n l y i f t h e e s t a b l i s h e d
r e p o r t mode i s b o o t mode .
status =
hid subevent set protocol response get handshake status
( packet ) ;
i f ( s t a t u s != HID HANDSHAKE PARAM TYPE SUCCESSFUL) {
p r i n t f ( ” E r r o r s e t p r o t o c o l , s t a t u s 0x%02x\n” , s t a t u s
);
break ;
}
switch ( ( h i d p r o t o c o l m o d e t )
hid subevent set protocol response get protocol mode
( packet ) ) {
case HID PROTOCOL MODE BOOT:
p r i n t f ( ” P r o t o c o l mode s e t : BOOT. \ n” ) ;
break ;
case HID PROTOCOL MODE REPORT:
p r i n t f ( ” P r o t o c o l mode s e t : REPORT. \ n” ) ;
break ;
default :
p r i n t f ( ”Unknown p r o t o c o l mode . \ n” ) ;
break ;
}
break ;

case HID SUBEVENT CONNECTION CLOSED :


// The c o n n e c t i o n was c l o s e d .
hid host cid = 0;
hid host descriptor available = false ;
p r i n t f ( ”HID Host d i s c o n n e c t e d . \ n” ) ;
break ;

default :
break ;
176

}
break ;
default :
break ;
}
break ;
default :
break ;
}
}

When BTSTACK EVENT STATE with state HCI STATE WORKING is re-
ceived and the example is started in client mode, the remote SDP HID query is
started.
0.94. HID Keyboard LE. Source Code: hog keyboard demo.c
0.95. HID Mouse LE. Source Code: hog mouse demo.c
0.96. HID Boot Host LE. Source Code: hog boot host demo.c
This example implements a minimal HID-over-GATT Boot Host. It scans for
LE HID devices, connects to it, discovers the Characteristics relevant for the HID
Service and enables Notifications on them. It then dumps all Boot Keyboard
and Mouse Input Reports
0.96.1. HOG Boot Keyboard Handler. Boot Keyboard Input Report contains a
report of format [ modifier, reserved, 6 x usage for key 1..6 from keyboard usage]
Track new usages, map key usage to actual character and simulate terminal
0.96.2. HOG Boot Mouse Handler. Boot Mouse Input Report contains a report
of format [ buttons, dx, dy, dz = scroll wheel] Decode packet and print on stdout
@param packet type @param channel @param packet @param size
0.96.3. Test if advertisement contains HID UUID.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
...
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
event = h c i e v e n t p a c k e t g e t t y p e ( packet ) ;
switch ( e v e n t ) {
case BTSTACK EVENT STATE:
i f ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) !=
HCI STATE WORKING) break ;
b t s t a c k a s s e r t ( a p p s t a t e == W4 WORKING) ;
hog start connect () ;
break ;
case GAP EVENT ADVERTISING REPORT :
i f ( a p p s t a t e != W4 HID DEVICE FOUND) break ;
i f ( a d v e v e n t c o n t a i n s h i d s e r v i c e ( p a c k e t ) == f a l s e ) break
;
// s t o p scan
gap stop scan () ;
177

// s t o r e remote d e v i c e a d d r e s s and t y p e
g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s ( packet ,
r e m o t e d e v i c e . addr ) ;
remote device . addr type =
g a p e v e n t a d v e r t i s i n g r e p o r t g e t a d d r e s s t y p e ( packet ) ;
// c o n n e c t
p r i n t f ( ”Found , c o n n e c t t o d e v i c e with %s a d d r e s s %s . . . \ n”
, r e m o t e d e v i c e . a d d r t y p e == 0 ? ” p u b l i c ” : ”random” ,
b d a d d r t o s t r ( r e m o t e d e v i c e . addr ) ) ;
hog connect () ;
break ;
case HCI EVENT DISCONNECTION COMPLETE :
i f ( a p p s t a t e != READY) break ;

c o n n e c t i o n h a n d l e = HCI CON HANDLE INVALID ;


switch ( a p p s t a t e ) {
case READY:
p r i n t f ( ” \ nDisconnected , t r y t o r e c o n n e c t . . . \ n” ) ;
a p p s t a t e = W4 TIMEOUT THEN RECONNECT;
break ;
default :
p r i n t f ( ” \ nDisconnected , s t a r t o v e r . . . \ n” ) ;
a p p s t a t e = W4 TIMEOUT THEN SCAN ;
break ;
}
// s e t t i m e r
b t s t a c k r u n l o o p s e t t i m e r (& c o n n e c t i o n t i m e r , 1 0 0 ) ;
b t s t a c k r u n l o o p s e t t i m e r h a n d l e r (& c o n n e c t i o n t i m e r , &
hog reconnect timeout ) ;
b t s t a c k r u n l o o p a d d t i m e r (& c o n n e c t i o n t i m e r ) ;
break ;
case HCI EVENT META GAP :
// w a i t f o r c o n n e c t i o n c o m p l e t e
i f ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) !=
GAP SUBEVENT LE CONNECTION COMPLETE) break ;
i f ( a p p s t a t e != W4 CONNECTED) return ;
b t s t a c k r u n l o o p r e m o v e t i m e r (& c o n n e c t i o n t i m e r ) ;
connection handle =
gap subevent le connection complete get connection handle
( packet ) ;
// r e q u e s t s e c u r i t y
a p p s t a t e = W4 ENCRYPTED;
sm request pairing ( connection handle ) ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}
178

0.96.4. HCI packet handler. The SM packet handler receives Security Manager
Events required for pairing. It also receives events generated during Identity
Resolving see Listing here.

s t a t i c void s m p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

bool c o n n e c t t o s e r v i c e = f a l s e ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case SM EVENT JUST WORKS REQUEST :
p r i n t f ( ” J u s t works r e q u e s t e d \n” ) ;
sm just works confirm ( sm event just works request get handle (
packet ) ) ;
break ;
case SM EVENT NUMERIC COMPARISON REQUEST:
p r i n t f ( ” Confirming numeric comparison : %”PRIu32”\n” ,
sm event numeric comparison request get passkey ( packet ) ) ;
sm numeric comparison confirm (
sm event passkey display number get handle ( packet ) ) ;
break ;
case SM EVENT PASSKEY DISPLAY NUMBER :
p r i n t f ( ” D i s p l a y Passkey : %”PRIu32” \n” ,
sm event passkey display number get passkey ( packet ) ) ;
break ;
case SM EVENT PAIRING COMPLETE :
switch ( s m e v e n t p a i r i n g c o m p l e t e g e t s t a t u s ( p a c k e t ) ) {
case ERROR CODE SUCCESS :
p r i n t f ( ” P a i r i n g complete , s u c c e s s \n” ) ;
connect to service = true ;
break ;
case ERROR CODE CONNECTION TIMEOUT:
p r i n t f ( ” P a i r i n g f a i l e d , t i m e o u t \n” ) ;
break ;
case ERROR CODE REMOTE USER TERMINATED CONNECTION:
p r i n t f ( ” P a i r i n g f a i l e d , d i s c o n n e c t e d \n” ) ;
break ;
case ERROR CODE AUTHENTICATION FAILURE :
p r i n t f ( ” P a i r i n g f a i l e d , r e a s o n = %u\n” ,
s m e v e n t p a i r i n g c o m p l e t e g e t r e a s o n ( packet ) ) ;
break ;
default :
break ;
}
break ;
case SM EVENT REENCRYPTION COMPLETE:
p r i n t f ( ”Re−e n c r y p t i o n complete , s u c c e s s \n” ) ;
connect to service = true ;
break ;
179

default :
break ;
}

if ( connect to service ){
// c o n t i n u e − q u e r y primary s e r v i c e s
p r i n t f ( ” S e a r c h f o r HID s e r v i c e . \ n” ) ;
a p p s t a t e = W4 HID SERVICE FOUND ;
gatt client discover primary services by uuid16 (
handle gatt client event , connection handle ,
ORG BLUETOOTH SERVICE HUMAN INTERFACE DEVICE) ;
}
}

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;
sm s e t i o c a p a b i l i t i e s (IO CAPABILITY DISPLAY ONLY) ;
sm s e t a u t h e n t i c a t i o n r e q u i r e m e n t s (SM AUTHREQ SECURE CONNECTION |
SM AUTHREQ BONDING) ;

//
g a t t c l i e n t i n i t () ;

// r e g i s t e r f o r e v e n t s from HCI
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r e v e n t s from S e c u r i t y Manager
s m e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &s m p a c k e t h a n d l e r ;
s m a d d e v e n t h a n d l e r (& s m e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

0.97. Dual Mode - SPP and LE Counter. Source Code: spp and le counter.c
The SPP and LE Counter example combines the Bluetooth Classic SPP Counter
and the Bluetooth LE Counter into a single application.
In this Section, we only point out the differences to the individual examples
and how the stack is configured.
Note: To test, please run the example, and then:
• for SPP pair from a remote device, and open the Virtual Serial Port,
• for LE use some GATT Explorer, e.g. LightBlue, BLExplr, to enable
notifications.
0.97.1. Advertisements. The Flags attribute in the Advertisement Data indicates
if a device is dual-mode or le-only.

const uint8 t a d v d a t a [ ] = {
// F l a g s g e n e r a l d i s c o v e r a b l e
180

0 x02 , BLUETOOTH DATA TYPE FLAGS, 0 x02 ,


// Name
0x0b , BLUETOOTH DATA TYPE COMPLETE LOCAL NAME, ’L ’ , ’E ’ , ’ ’ , ’C ’ ,
’o ’ , ’u ’ , ’n ’ , ’ t ’ , ’ e ’ , ’ r ’ ,
// I n c o m p l e t e L i s t o f 16− b i t S e r v i c e C l a s s UUIDs −− FF10 − o n l y
valid for testing !
0 x03 ,
BLUETOOTH DATA TYPE INCOMPLETE LIST OF 16 BIT SERVICE CLASS UUIDS
, 0 x10 , 0 x f f ,
};

0.97.2. Packet Handler. The packet handler of the combined example is just the
combination of the individual packet handlers.
0.97.3. Heartbeat Handler. Similar to the packet handler, the heartbeat handler
is the combination of the individual ones. After updating the counter, it requests
an ATT EVENT CAN SEND NOW and/or RFCOMM EVENT CAN SEND NOW

s t a t i c void h e a r t b e a t h a n d l e r ( struct b t s t a c k t i m e r s o u r c e ∗ t s ) {

i f ( rfcomm channel id | | l e n o t i f i c a t i o n e n a b l e d ) {
beat ( ) ;
}

i f ( rfcomm channel id ) {
rfcomm request can send now event ( rfcomm channel id ) ;
}

if ( le notification enabled ) {
att server request can send now event ( att con handle ) ;
}

b t s t a c k r u n l o o p s e t t i m e r ( t s , HEARTBEAT PERIOD MS) ;


btstack run loop add timer ( ts ) ;
}

0.97.4. Main Application Setup. As with the packet and the heartbeat handlers,
the combined app setup contains the code from the individual example setups.

int b t s t a c k m a i n ( void ) ;
int b t s t a c k m a i n ( void )
{
l2cap init () ;

rfcomm init () ;
r f c o m m r e g i s t e r s e r v i c e ( p a c k e t h a n d l e r , RFCOMM SERVER CHANNEL, 0
xffff );

// i n i t SDP, c r e a t e r e c o r d f o r SPP and r e g i s t e r w i t h SDP


181

sdp init () ;
memset ( s p p s e r v i c e b u f f e r , 0 , s i z e o f ( s p p s e r v i c e b u f f e r ) ) ;
spp create sdp record ( spp service buffer ,
s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( ) , RFCOMM SERVER CHANNEL, ”
SPP Counter ” ) ;
b t s t a c k a s s e r t ( d e g e t l e n ( s p p s e r v i c e b u f f e r ) <= s i z e o f (
spp service buffer ) ) ;
sdp register service ( spp service buffer ) ;

#i f d e f ENABLE GATT OVER CLASSIC


// i n i t SDP, c r e a t e r e c o r d f o r GATT and r e g i s t e r w i t h SDP
memset ( g a t t s e r v i c e b u f f e r , 0 , s i z e o f ( g a t t s e r v i c e b u f f e r ) ) ;
g a t t c r e a t e s d p r e c o r d ( g a t t s e r v i c e b u f f e r , 0 x10001 ,
ATT SERVICE GATT SERVICE START HANDLE,
ATT SERVICE GATT SERVICE END HANDLE) ;
sdp register service ( gatt service buffer ) ;
p r i n t f ( ”SDP s e r v i c e r e c o r d s i z e : %u\n” , d e g e t l e n (
gatt service buffer )) ;
#endif

g a p s e t l o c a l n a m e ( ”SPP and LE Counter 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;


g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap discoverable control (1) ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

// s e t u p ATT s e r v e r
att server init ( profile data , att read callback ,
att write callback ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r ATT e v e n t s
att se rver re giste r pac ket han dler ( packet handler ) ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;

// s e t one−s h o t t i m e r
h e a r t b e a t . p r o c e s s = &h e a r t b e a t h a n d l e r ;
b t s t a c k r u n l o o p s e t t i m e r (& h e a r t b e a t , HEARTBEAT PERIOD MS) ;
b t s t a c k r u n l o o p a d d t i m e r (& h e a r t b e a t ) ;
182

// b e a t once
beat ( ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;

return 0 ;
}

0.98. Performance - Stream Data over GATT (Server). Source Code:


gatt streamer server.c
All newer operating systems provide GATT Client functionality. This example
shows how to get a maximal throughput via BLE:
• send whenever possible,
• use the max ATT MTU.
In theory, we should also update the connection parameters, but we
already get a connection interval of 30 ms and there’s no public way to
use a shorter interval with iOS (if we’re not implementing an HID device).
Note: To start the streaming, run the example. On remote device use
some GATT Explorer, e.g. LightBlue, BLExplr to enable notifications.
0.98.1. Main Application Setup. Listing here shows main application code. It
initializes L2CAP, the Security Manager, and configures the ATT Server with
the pre-compiled ATT Database generated from les treamer.gatt. Finally, it
configures the advertisements and boots the Bluetooth stack.

s t a t i c void l e s t r e a m e r s e t u p ( void ) {

l2cap init () ;

// s e t u p SM: D i s p l a y o n l y
sm init () ;

#i f d e f ENABLE GATT OVER CLASSIC


// i n i t SDP, c r e a t e r e c o r d f o r GATT and r e g i s t e r w i t h SDP
sdp init () ;
memset ( g a t t s e r v i c e b u f f e r , 0 , s i z e o f ( g a t t s e r v i c e b u f f e r ) ) ;
g a t t c r e a t e s d p r e c o r d ( g a t t s e r v i c e b u f f e r , 0 x10001 ,
ATT SERVICE GATT SERVICE START HANDLE,
ATT SERVICE GATT SERVICE END HANDLE) ;
sdp register service ( gatt service buffer ) ;
p r i n t f ( ”SDP s e r v i c e r e c o r d s i z e : %u\n” , d e g e t l e n (
gatt service buffer )) ;

// c o n f i g u r e C l a s s i c GAP
g a p s e t l o c a l n a m e ( ”GATT Streamer BR/EDR 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ” ) ;
g a p s s p s e t i o c a p a b i l i t y ( SSP IO CAPABILITY DISPLAY YES NO ) ;
gap discoverable control (1) ;
#endif
183

// s e t u p ATT s e r v e r
a t t s e r v e r i n i t ( p r o f i l e d a t a , NULL, a t t w r i t e c a l l b a c k ) ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &h c i p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// r e g i s t e r f o r ATT e v e n t s
att server register packet handler ( att packet handler ) ;

// s e t u p a d v e r t i s e m e n t s
uint16 t a d v i n t m i n = 0 x0030 ;
uint16 t a d v i n t m a x = 0 x0030 ;
uint8 t a d v t y p e = 0 ;
bd addr t n u l l a d d r ;
memset ( n u l l a d d r , 0 , 6 ) ;
g a p a d v e r t i s e m e n t s s e t p a r a m s ( a d v i n t m i n , adv int max , adv type ,
0 , n u l l a d d r , 0 x07 , 0 x00 ) ;
g a p a d v e r t i s e m e n t s s e t d a t a ( a d v d a t a l e n , ( uint8 t ∗ ) a d v d a t a ) ;
gap advertisements enable (1) ;

// i n i t c l i e n t s t a t e
init connections () ;
}

0.98.2. Track throughput. We calculate the throughput by setting a start time


and measuring the amount of data sent. After a configurable REPORT INTERVAL MS,
we print the throughput in kB/s and reset the counter and start time.

s t a t i c void t e s t r e s e t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t ) {
c o n t e x t −>t e s t d a t a s t a r t = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}

s t a t i c void t e s t t r a c k s e n t ( l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t , int
bytes sent ){
c o n t e x t −>t e s t d a t a s e n t += b y t e s s e n t ;
// e v a l u a t e
uint32 t now = b t s t a c k r u n l o o p g e t t i m e m s ( ) ;
uint32 t t i m e p a s s e d = now − c o n t e x t −>t e s t d a t a s t a r t ;
i f ( t i m e p a s s e d < REPORT INTERVAL MS) return ;
// p r i n t s p e e d
int b y t e s p e r s e c o n d = c o n t e x t −>t e s t d a t a s e n t ∗ 1000 /
time passed ;
p r i n t f ( ”%c : %”PRIu32” b y t e s s e n t −> %u.%03u kB/ s \n” , c o n t e x t −>name ,
c o n t e x t −>t e s t d a t a s e n t , b y t e s p e r s e c o n d / 1 0 0 0 ,
b y t e s p e r s e c o n d % 1000) ;

// r e s t a r t
c o n t e x t −>t e s t d a t a s t a r t = now ;
c o n t e x t −>t e s t d a t a s e n t = 0 ;
}
184

0.98.3. HCI Packet Handler. The packet handler is used track incoming connec-
tions and to stop notifications on disconnect It is also a good place to request
the connection parameter update as indicated in the commented code block.

s t a t i c void h c i p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;

uint16 t c o n n i n t e r v a l ;
hci con handle t con handle ;
s t a t i c const char ∗ const phy names [ ] = {
” Reserved ” , ” 1 M” , ” 2 M” , ” Codec ”
};

switch ( h c i e v e n t p a c k e t g e t t y p e ( packet ) ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
) {
p r i n t f ( ”To s t a r t t h e s t r e a m i n g , p l e a s e run t h e
l e s t r e a m e r c l i e n t example on o t h e r d e v i c e , o r u s e some
GATT E x p l o r e r , e . g . LightBlue , BLExplr . \ n” ) ;
}
break ;
case HCI EVENT DISCONNECTION COMPLETE :
con handle =
hci event disconnection complete get connection handle (
packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : d i s c o n n e c t , r e a s o n %02x\n” ,
con handle , h c i e v e n t d i s c o n n e c t i o n c o m p l e t e g e t r e a s o n (
packet ) ) ;
break ;
case HCI EVENT META GAP :
switch ( h c i e v e n t g a p m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case GAP SUBEVENT LE CONNECTION COMPLETE:
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
gap subevent le connection complete get connection handle
( packet ) ;
conn interval =
gap subevent le connection complete get conn interval (
packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : c o n n e c t e d − c o n n e c t i o n
i n t e r v a l %u.%02u ms , l a t e n c y %u\n” , c o n h a n d l e ,
c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
185

25 ∗ ( c o n n i n t e r v a l & 3 ) ,
gap subevent le connection complete get conn latency
( packet ) ) ;

// r e q u e s t min con i n t e r v a l 15 ms f o r iOS 11+


p r i n t f ( ”− LE Connection 0x%04x : r e q u e s t 15 ms c o n n e c t i o n
i n t e r v a l \n” , c o n h a n d l e ) ;
gap request connection parameter update ( con handle , 12 ,
1 2 , 4 , 0 x0048 ) ;
break ;
default :
break ;
}
break ;
case HCI EVENT LE META :
switch ( h c i e v e n t l e m e t a g e t s u b e v e n t c o d e ( p a c k e t ) ) {
case HCI SUBEVENT LE CONNECTION UPDATE COMPLETE :
// p r i n t c o n n e c t i o n p a r a m e t e r s ( w i t h o u t u s i n g f l o a t
operations )
con handle =
hci subevent le connection update complete get connection handle
( packet ) ;
conn interval =
hci subevent le connection update complete get conn interval
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : c o n n e c t i o n update −
c o n n e c t i o n i n t e r v a l %u.%02u ms , l a t e n c y %u\n” ,
c o n h a n d l e , c o n n i n t e r v a l ∗ 125 / 1 0 0 ,
25 ∗ ( c o n n i n t e r v a l & 3 ) ,
hci subevent le connection update complete get conn latency
( packet ) ) ;
break ;
case HCI SUBEVENT LE DATA LENGTH CHANGE :
con handle =
hci subevent le data length change get connection handle
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : data l e n g t h change − max %
u b y t e s p e r p a c k e t \n” , c o n h a n d l e ,
hci subevent le data length change get max tx octets (
packet ) ) ;
break ;
case HCI SUBEVENT LE PHY UPDATE COMPLETE :
con handle =
hci subevent le phy update complete get connection handle
( packet ) ;
p r i n t f ( ”− LE Connection 0x%04x : PHY update − u s i n g LE %s
PHY now\n” , c o n h a n d l e ,
phy names [
hci subevent le phy update complete get tx phy (
packet ) ] ) ;
break ;
default :
break ;
}
186

break ;

default :
break ;
}
}

0.98.4. ATT Packet Handler. The packet handler is used to track the ATT MTU
Exchange and trigger ATT send

s t a t i c void a t t p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t


channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

int mtu ;
le streamer connection t ∗ context ;
switch ( p a c k e t t y p e ) {
case HCI EVENT PACKET :
switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
case ATT EVENT CONNECTED:
// s e t u p new
context = connection for conn handle (
HCI CON HANDLE INVALID) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>c o u n t e r = ’A ’ ;
c o n t e x t −>c o n n e c t i o n h a n d l e =
a t t e v e n t c o n n e c t e d g e t h a n d l e ( packet ) ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( a t t s e r v e r g e t m t u (
c o n t e x t −>c o n n e c t i o n h a n d l e ) − 3 , s i z e o f ( c o n t e x t −>
test data ) ) ;
p r i n t f ( ”%c : ATT connected , h a n d l e 0x%04x , t e s t data l e n %u
\n” , c o n t e x t −>name , c o n t e x t −>c o n n e c t i o n h a n d l e ,
c o n t e x t −>t e s t d a t a l e n ) ;
break ;
case ATT EVENT MTU EXCHANGE COMPLETE:
mtu = a t t e v e n t m t u e x c h a n g e c o m p l e t e g e t M T U ( p a c k e t ) − 3 ;
context = connection for conn handle (
att event mtu exchange complete get handle ( packet ) ) ;
i f ( ! c o n t e x t ) break ;
c o n t e x t −>t e s t d a t a l e n = b t s t a c k m i n ( mtu − 3 , s i z e o f (
c o n t e x t −>t e s t d a t a ) ) ;
p r i n t f ( ”%c : ATT MTU = %u => u s e t e s t data o f l e n %u\n” ,
c o n t e x t −>name , mtu , c o n t e x t −>t e s t d a t a l e n ) ;
break ;
case ATT EVENT CAN SEND NOW:
streamer () ;
break ;
case ATT EVENT DISCONNECTED:
context = connection for conn handle (
a t t e v e n t d i s c o n n e c t e d g e t h a n d l e ( packet ) ) ;
i f ( ! c o n t e x t ) break ;
187

// f r e e c o n n e c t i o n
p r i n t f ( ”%c : ATT d i s c o n n e c t e d , h a n d l e 0x%04x\n” , c o n t e x t −>
name , c o n t e x t −>c o n n e c t i o n h a n d l e ) ;
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d = 0 ;
c o n t e x t −>c o n n e c t i o n h a n d l e = HCI CON HANDLE INVALID ;
break ;
default :
break ;
}
break ;
default :
break ;
}
}

0.98.5. Streamer. The streamer function checks if notifications are enabled and
if a notification can be sent now. It creates some test data - a single letter that
gets increased every time - and tracks the data sent.

s t a t i c void s t r e a m e r ( void ) {

// f i n d n e x t a c t i v e s t r e a m i n g c o n n e c t i o n
int o l d c o n n e c t i o n i n d e x = c o n n e c t i o n i n d e x ;
while ( 1 ) {
// a c t i v e found ?
i f (( le streamer connections [ connection index ] . connection handle
!= HCI CON HANDLE INVALID) &&
( le streamer connections [ connection index ] .
l e n o t i f i c a t i o n e n a b l e d ) ) break ;

// c h e c k n e x t
next connection index () ;

// none found
i f ( c o n n e c t i o n i n d e x == o l d c o n n e c t i o n i n d e x ) return ;
}

l e s t r e a m e r c o n n e c t i o n t ∗ c o n t e x t = &l e s t r e a m e r c o n n e c t i o n s [
connection index ] ;

// c r e a t e t e s t d a t a
c o n t e x t −>c o u n t e r ++;
i f ( c o n t e x t −>c o u n t e r > ’ Z ’ ) c o n t e x t −>c o u n t e r = ’A ’ ;
memset ( c o n t e x t −>t e s t d a t a , c o n t e x t −>c o u n t e r , c o n t e x t −>
test data len ) ;

// send
a t t s e r v e r n o t i f y ( c o n t e x t −>c o n n e c t i o n h a n d l e , c o n t e x t −>
v a l u e h a n d l e , ( uint8 t ∗ ) c o n t e x t −>t e s t d a t a , c o n t e x t −>
test data len ) ;

// t r a c k
188

t e s t t r a c k s e n t ( c o n t e x t , c o n t e x t −>t e s t d a t a l e n ) ;

// r e q u e s t n e x t send e v e n t
a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( c o n t e x t −>c o n n e c t i o n h a n d l e ) ;

// c h e c k n e x t
next connection index () ;
}

0.98.6. ATT Write. The only valid ATT write in this example is to the Client
Characteristic Configuration, which configures notification and indication. If
the ATT handle matches the client configuration handle, the new configuration
value is stored. If notifications get enabled, an ATT EVENT CAN SEND NOW
is requested. See Listing here.

s t a t i c int a t t w r i t e c a l l b a c k ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
a t t h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t o f f s e t , uint8 t
∗ b u f f e r , uint16 t b u f f e r s i z e ) {
UNUSED( o f f s e t ) ;

// p r i n t f (” a t t w r i t e c a l l b a c k a t t h a n d l e 0 x%04x , t r a n s a c t i o n mode
%u\n ” , a t t h a n d l e , t r a n s a c t i o n m o d e ) ;
i f ( t r a n s a c t i o n m o d e != ATT TRANSACTION MODE NONE) return 0 ;
le streamer connection t ∗ context = connection for conn handle (
con handle ) ;
switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGURATIO
:
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d = l i t t l e e n d i a n r e a d 1 6 (
b u f f e r , 0 ) ==
GATT CLIENT CHARACTERISTICS CONFIGURATION NOTIFICATION ;
p r i n t f ( ”%c : N o t i f i c a t i o n s e n a b l e d %u\n” , c o n t e x t −>name ,
c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d ) ;
i f ( c o n t e x t −>l e n o t i f i c a t i o n e n a b l e d ) {
switch ( a t t h a n d l e ) {
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGU
:
c o n t e x t −>v a l u e h a n d l e =
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HAND
;
break ;
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 CLIENT CONFIGU
:
189

c o n t e x t −>v a l u e h a n d l e =
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 VALUE HAND
;
break ;
default :
break ;
}
a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( c o n t e x t −>
connection handle ) ;
}
t e s t r e s e t ( context ) ;
break ;
case
ATT CHARACTERISTIC 0000FF11 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
case
ATT CHARACTERISTIC 0000FF12 0000 1000 8000 00805F9B34FB 01 VALUE HANDLE
:
t e s t t r a c k s e n t ( context , b u f f e r s i z e ) ;
break ;
default :
p r i n t f ( ” Write t o 0x%04x , l e n %u\n” , a t t h a n d l e , b u f f e r s i z e ) ;
break ;
}
return 0 ;
}

0.99. SDP Client - Query Remote SDP Records. Source Code: sdp general query.c
The example shows how the SDP Client is used to get a list of service records
on a remote device.
0.99.1. SDP Client Setup. SDP is based on L2CAP. To receive SDP query events
you must register a callback, i.e. query handler, with the SPD parser, as shown
in Listing here. Via this handler, the SDP client will receive the following events:
• SDP EVENT QUERY ATTRIBUTE VALUE containing the results of
the query in chunks,
• SDP EVENT QUERY COMPLETE indicating the end of the query and
the status

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void h a n d l e s d p c l i e n t q u e r y r e s u l t ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void s d p g e n e r a l q u e r y i n i t ( void ) {
// i n i t L2CAP
l2cap init () ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
190

0.99.2. SDP Client Query. To trigger an SDP query to get the a list of service
records on a remote device, you need to call sdp client query uuid16() with the
remote address and the UUID of the public browse group, as shown in Listing
here. In this example we used fixed address of the remote device shown in
Listing here. Please update it with the address of a device in your vicinity, e.g.,
one reported by the GAP Inquiry example in the previous section.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;


uint8 t e v e n t = h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ;

switch ( event ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
){
p r i n t f ( ” Connecting t o %s \n” , b d a d d r t o s t r ( r e m o t e a d d r ) ) ;
s d p c l i e n t q u e r y u u i d 1 6 (& h a n d l e s d p c l i e n t q u e r y r e s u l t ,
remote addr , BLUETOOTH PROTOCOL L2CAP) ;
}
break ;
default :
break ;
}
}

0.99.3. Handling SDP Client Query Results. The SDP Client returns the results
of the query in chunks. Each result packet contains the record ID, the Attribute
ID, and a chunk of the Attribute value. In this example, we append new chunks
for the same Attribute ID in a large buffer, see Listing here.
To save memory, it’s also possible to process these chunks directly by a custom
stream parser, similar to the way XML files are parsed by a SAX parser. Have a
look at src/sdp client rfcomm.c which retrieves the RFCOMM channel number
and the service name.

s t a t i c void h a n d l e s d p c l i e n t q u e r y r e s u l t ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( p a c k e t t y p e ) ;
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

switch ( h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ) {
191

case SDP EVENT QUERY ATTRIBUTE VALUE :


// h a n d l e new r e c o r d
i f ( s d p e v e n t q u e r y a t t r i b u t e b y t e g e t r e c o r d i d ( p a c k e t ) !=
record id ){
record id = sdp event query attribute byte get record id (
packet ) ;
p r i n t f ( ” \n−−−\nRecord nr . %u\n” , r e c o r d i d ) ;
}

assertBuffer (
s d p e v e n t q u e r y a t t r i b u t e b y t e g e t a t t r i b u t e l e n g t h ( packet
));

attribute value [ sdp event query attribute byte get data offset
( packet ) ] = s d p e v e n t q u e r y a t t r i b u t e b y t e g e t d a t a ( packet
);
i f ( ( uint16 t ) ( s d p e v e n t q u e r y a t t r i b u t e b y t e g e t d a t a o f f s e t (
p a c k e t ) +1) ==
s d p e v e n t q u e r y a t t r i b u t e b y t e g e t a t t r i b u t e l e n g t h ( packet
) ){
p r i n t f ( ” A t t r i b u t e 0x%04x : ” ,
s d p e v e n t q u e r y a t t r i b u t e b y t e g e t a t t r i b u t e i d ( packet )
);
de du mp da ta el em ent ( a t t r i b u t e v a l u e ) ;
}
break ;
case SDP EVENT QUERY COMPLETE:
i f ( s d p e v e n t q u e r y c o m p l e t e g e t s t a t u s ( packet ) ) {
p r i n t f ( ”SDP query f a i l e d 0x%02x\n” ,
s d p e v e n t q u e r y c o m p l e t e g e t s t a t u s ( packet ) ) ;
break ;
}
p r i n t f ( ”SDP query done . \ n” ) ;
break ;
default :
break ;
}
}

0.100. SDP Client - Query RFCOMM SDP record. Source Code: sdp rfcomm query.c
The example shows how the SDP Client is used to get all RFCOMM service
records from a remote device. It extracts the remote RFCOMM Server Channel,
which are needed to connect to a remote RFCOMM service.

0.101. SDP Client - Query BNEP SDP record. Source Code: sdp bnep query.c
The example shows how the SDP Client is used to get all BNEP service records
from a remote device. It extracts the remote BNEP PAN protocol UUID and
the L2CAP PSM, which are needed to connect to a remote BNEP service.

0.101.1. SDP Client Setup. As with the previous example, you must register a
callback, i.e. query handler, with the SPD parser, as shown in Listing here. Via
this handler, the SDP client will receive events:
192

• SDP EVENT QUERY ATTRIBUTE VALUE containing the results of


the query in chunks,
• SDP EVENT QUERY COMPLETE reporting the status and the end of
the query.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) ;
s t a t i c void h a n d l e s d p c l i e n t q u e r y r e s u l t ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) ;

s t a t i c void s d p b n e p q e u r y i n i t ( void ) {
// i n i t L2CAP
l2cap init () ;

// r e g i s t e r f o r HCI e v e n t s
h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;
}

0.101.2. SDP Client Query.

s t a t i c void p a c k e t h a n d l e r ( uint8 t p a c k e t t y p e , uint16 t channel ,


uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

i f ( p a c k e t t y p e != HCI EVENT PACKET) return ;


uint8 t e v e n t = h c i e v e n t p a c k e t g e t t y p e ( p a c k e t ) ;

switch ( event ) {
case BTSTACK EVENT STATE:
// BTstack a c t i v a t e d , g e t s t a r t e d
if ( b t s t a c k e v e n t s t a t e g e t s t a t e ( p a c k e t ) == HCI STATE WORKING
){
p r i n t f ( ” S t a r t SDP BNEP query . \ n” ) ;
s d p c l i e n t q u e r y u u i d 1 6 (& h a n d l e s d p c l i e n t q u e r y r e s u l t ,
remote , BLUETOOTH PROTOCOL BNEP) ;
}
break ;
default :
break ;
}
}

0.101.3. Handling SDP Client Query Result. The SDP Client returns the result
of the query in chunks. Each result packet contains the record ID, the Attribute
ID, and a chunk of the Attribute value, see Listing here. Here, we show how to
parse the Service Class ID List and Protocol Descriptor List, as they contain the
BNEP Protocol UUID and L2CAP PSM respectively.
193

s t a t i c void h a n d l e s d p c l i e n t q u e r y r e s u l t ( uint8 t p a c k e t t y p e ,
uint16 t channel , uint8 t ∗ packet , uint16 t s i z e ) {
UNUSED( p a c k e t t y p e ) ;
UNUSED( c h a n n e l ) ;
UNUSED( s i z e ) ;

...

switch ( s d p e v e n t q u e r y a t t r i b u t e b y t e g e t a t t r i b u t e i d (
packet ) ) {
// 0 x0001 ” S e r v i c e C l a s s ID L i s t ”
case BLUETOOTH ATTRIBUTE SERVICE CLASS ID LIST :
i f ( d e g e t e l e m e n t t y p e ( a t t r i b u t e v a l u e ) != DE DES)
break ;
f o r ( d e s i t e r a t o r i n i t (& d e s l i s t i t , a t t r i b u t e v a l u e ) ;
d e s i t e r a t o r h a s m o r e (& d e s l i s t i t ) ;
d e s i t e r a t o r n e x t (& d e s l i s t i t ) ) {
uint8 t ∗ e l e m e n t = d e s i t e r a t o r g e t e l e m e n t (&
des list it );
i f ( d e g e t e l e m e n t t y p e ( e l e m e n t ) != DE UUID) continue ;
uint32 t uuid = d e g e t u u i d 3 2 ( e l e m e n t ) ;
switch ( uuid ) {
case BLUETOOTH SERVICE CLASS PANU :
case BLUETOOTH SERVICE CLASS NAP :
case BLUETOOTH SERVICE CLASS GN :
p r i n t f ( ” ∗∗ A t t r i b u t e 0x%04x : BNEP PAN p r o t o c o l
UUID : %04x\n” ,
sdp event query attribute byte get attribute id
( p a c k e t ) , ( int ) uuid ) ;
break ;
default :
break ;
}
}
break ;
...
case BLUETOOTH ATTRIBUTE PROTOCOL DESCRIPTOR LIST: {
p r i n t f ( ” ∗∗ A t t r i b u t e 0x%04x : ” ,
sdp event query attribute byte get attribute id (
packet ) ) ;

uint16 t l2cap psm = 0 ;


uint16 t b n e p v e r s i o n = 0 ;
f o r ( d e s i t e r a t o r i n i t (& d e s l i s t i t , a t t r i b u t e v a l u e ) ;
d e s i t e r a t o r h a s m o r e (& d e s l i s t i t ) ;
d e s i t e r a t o r n e x t (& d e s l i s t i t ) ) {
i f ( d e s i t e r a t o r g e t t y p e (& d e s l i s t i t ) != DE DES)
continue ;
uint8 t ∗ d e s e l e m e n t = d e s i t e r a t o r g e t e l e m e n t (&
des list it );
d e s i t e r a t o r i n i t (& p r o t i t , d e s e l e m e n t ) ;
194

uint8 t ∗ e l e m e n t = d e s i t e r a t o r g e t e l e m e n t (&
prot it ) ;

i f ( d e g e t e l e m e n t t y p e ( e l e m e n t ) != DE UUID)
continue ;
uint32 t uuid = d e g e t u u i d 3 2 ( e l e m e n t ) ;
d e s i t e r a t o r n e x t (& p r o t i t ) ;
switch ( uuid ) {
case BLUETOOTH PROTOCOL L2CAP:
i f ( ! d e s i t e r a t o r h a s m o r e (& p r o t i t ) ) continue ;
d e e l e m e n t g e t u i n t 1 6 ( d e s i t e r a t o r g e t e l e m e n t (&
p r o t i t ) , &l2cap psm ) ;
break ;
case BLUETOOTH PROTOCOL BNEP:
i f ( ! d e s i t e r a t o r h a s m o r e (& p r o t i t ) ) continue ;
d e e l e m e n t g e t u i n t 1 6 ( d e s i t e r a t o r g e t e l e m e n t (&
p r o t i t ) , &b n e p v e r s i o n ) ;
break ;
default :
break ;
}
}
p r i n t f ( ” l2cap psm 0x%04x , b n e p v e r s i o n 0x%04x\n” ,
l2cap psm , b n e p v e r s i o n ) ;
}
break ;
...
}

The Service Class ID List is a Data Element Sequence (DES) of UUIDs. The
BNEP PAN protocol UUID is within this list.
The Protocol Descriptor List is DES which contains one DES for each protocol.
For PAN serivces, it contains a DES with the L2CAP Protocol UUID and a PSM,
and another DES with the BNEP UUID and the the BNEP version.

0.102. PBAP Client - Get Contacts from Phonebook Server. Source


Code: pbap client demo.c
Note: The Bluetooth address of the remote Phonbook server is hardcoded.
Change it before running example, then use the UI to connect to it, to set and
query contacts.

0.103. Testing - Enable Device Under Test (DUT) Mode for Classic.
Source Code: dut mode classic.c
DUT mode can be used for production testing. This example just configures
the Bluetooth Controller for DUT mode.

0.103.1. Bluetooth Logic. When BTstack is up and running, send Enable Device
Under Test Mode Command and print its result.
For more details on discovering remote devices, please see Section on GAP.

0.103.2. Main Application Setup. Listing here shows main application code. It
registers the HCI packet handler and starts the Bluetooth stack.
195

int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) ;


int b t s t a c k m a i n ( int argc , const char ∗ argv [ ] ) {
( void ) a r g c ;
( void ) argv ;

// d i s a b l e S e c u r e Simple P a i r i n n g
gap ssp set enable (0) ;

// make d e v i c e c o n n e c t a b l e
// @note : g a p c o n n e c t a b l e c o n t r o l w i l l be e n a b l e d when an L2CAP
service
// ( e . g . RFCOMM) i s i n i t i a l i z e d ) . T h e r e f o r e , i t ’ s not needed i n
regular applications
gap connectable control (1) ;

// make d e v i c e d i s c o v e r a b l e
gap discoverable control (1) ;

h c i e v e n t c a l l b a c k r e g i s t r a t i o n . c a l l b a c k = &p a c k e t h a n d l e r ;
h c i a d d e v e n t h a n d l e r (& h c i e v e n t c a l l b a c k r e g i s t r a t i o n ) ;

// t u r n on !
h c i p o w e r c o n t r o l (HCI POWER ON) ;

return 0 ;
}

#Chipsets
In this chapter, we first explain how Bluetooth chipsets are connected phys-
ically and then provide information about popular Bluetooth chipset and their
use with BTstack.
0.104. HCI Interface. The communication between a Host (a computer or an
MCU) and a Host Controller (the actual Bluetooth chipset) follows the Host
Controller Interface (HCI), see below. HCI defines how commands, events, asyn-
chronous and synchronous data packets are exchanged. Asynchronous packets
(ACL) are used for data transfer, while synchronous packets (SCO) are used for
Voice with the Headset and the Hands-Free Profiles.
0.104.1. HCI H2. On desktop-class computers incl. laptops, USB is mainly used
as HCI transport layer. For USB Bluetooth chipsets, there is little variation:
most USB dongles on the market currently contain a Broadcom BCM20702 or a
CSR 851x chipset. It is also called H2.
On embedded systems, UART connections are used instead, although USB
could be used as well.
For UART connections, different transport layer variants exist.
0.104.2. HCI H4. The most common one is the official “UART Transport”, also
called H4. It requires hardware flow control via the CTS/RTS lines and assumes
no errors on the UART lines.
196

Host Controller to Host connection

0.104.3. HCI H5. The “Three-Wire UART Transport”, also called H5, makes
use of the SLIP protocol to transmit a packet and can deal with packet loss and
bit-errors by retransmission. While it is possible to use H5 really with “three
wires” without hardware handshake, we recommend to use a full UART with
hardware handshake. If your design lacks the hardware handshake, H5 is your
only option.

0.104.4. BCSP. The predecessor of H5. The main difference to H5 is that Even
Parity is used for BCSP. To use BCSP with BTstack, you use the H5 transport
and can call hci transport h5 enable bcsp mode

0.104.5. eHCILL. Finally, Texas Instruments extended H4 to create the “eHCILL


transport” layer that allows both sides to enter sleep mode without loosing syn-
chronisation. While it is easier to implement than H5, it it is only supported by
TI chipsets and cannot handle packet loss or bit-errors.
197

0.104.6. H4 over SPI. Chipsets from Dialog Semiconductor and EM Marin allow
to send H4 formatted HCI packets via SPI. SPI has the benefit of a simpler
implementation for both Host Controller and Host as it does not require an
exact clock. The SPI Master, here the Host, provides the SPI Clock and the
SPI Slave (Host Controller) only has to read and update it’s data lines when the
clock line changes. The EM9304 supports an SPI clock of up to 8 Mhz. However,
an additional protocol is needed to let the Host know when the Host Controller
has HCI packet for it. Often, an additional GPIO is used to signal this.
0.104.7. HCI Shortcomings. Unfortunately, the HCI standard misses a few rele-
vant details:
• For UART based connections, the initial baud rate isn’t defined but most
Bluetooth chipsets use 115200 baud. For better throughput, a higher
baud rate is necessary, but there’s no standard HCI command to change
it. Instead, each vendor had to come up with their own set of vendor-
specific commands. Sometimes, additional steps, e.g. doing a warm reset,
are necessary to activate the baud rate change as well.
• Some Bluetooth chipsets don’t have a unique MAC address. On start,
the MAC address needs to be set, but there’s no standard HCI command
to set it.
• SCO data for Voice can either be transmitted via the HCI interface or
via an explicit PCM/I2S interface on the chipset. Most chipsets default
to the PCM/I2S interface. To use it via USB or for Wide-Band Speech in
the Hands-Free Profile, the data needs to be delivered to the host MCU.
Newer Bluetooth standards define a HCI command to configure the SCO
routing, but it is not implemented in the chipsets we’ve tested so far.
Instead, this is configured in a vendor-specific way as well.
• In addition, most vendors allow to patch or configure their chipsets at
run time by sending custom commands to the chipset. Obviously, this is
also vendor dependent.
0.105. Documentation and Support. The level of developer documentation
and support varies widely between the various Bluetooth chipset providers.
From our experience, only Texas Instruments and EM Microelectronics provide
all relevant information directly on their website. Nordic Semiconductor does not
officially have Bluetooth chipsets with HCI interface, but their documentation
on the nRF5 series is complete and very informative. TI and Nordic also provide
excellent support via their respective web forum.
Infineon acquired Cypress Semiconductor Corporation in 2020, which acquired
the Bluetooth + Wifi division of Broadcom in 2016 provides support via their
Community Forum. In addition, firmware updates (PatchRAM files) for Blue-
tooth + Wifi controllers are available via Murata’s Cypress GitHub.
CSR, which has been acquired by Qualcomm, provides all relevant information
on their Support website after signing an NDA.
198

SCO Multiple
over LE ClassicLE
HCI BD ADDR
HCI LE Roles SC Addr BTstack
Chipset (1) (2) DLE (3)
Type Transport (4) Resolution
folder Comment
Atmel LE H4 Yes n.a No No n.a. Don’t atwilc3000
BLE
ATWILC3000 know Firmware
size: 60 kB
Broadcom Dual H4, Rarely
Partially
No Maybe 43438: bcm Max UART
UART mode H5 (2) (3) Yes baudrate 2
mbps
Broadcom Dual USB Yes Yes No No BCM20702: bcm
USB mode No
Dongles
CSR Dual H4, Rarely
Partially
No No CSR8811: csr
UART mode H5, (2) No
BCSP
CSR Dual USB Mostly
Yes No No CSR8510: csr
USB mode No
Dongles
Infineon Dual H4, Don’tPartially
Yes Yes Yes Yes bcm
CYW207xxmode H5, know(2)
USB
Infineon Dual H4, Don’tPartially
Yes Yes Yes Don’t bcm Keep CTS
CYW208xxmode H5, know(2) know high during
USB power cycle
Infineon Dual H4, Don’tPartially
Don’tOn On On bcm Bluetooth
CYW43xxxmode H5 know(2) knownewer wewer newer + Wifi
+ versions
versionsversions Combo
Wifi Controller
Infineon Dual H4, No Yes Yes Yes Yes Yes bcm Bautobaud-
CYW5557xmode H5 mode
+ needed, see
Wifi posix-h4-
bcm
Cypress LE H4 Don’tn.a. Yes Don’t n.a. Don’t HCI
PSoC 4 know know know Firmware
part of
PSoC
Creator kits
examples
Dialog LE H4 No n.a. Yes Yes n.a. Don’t da145xx Official
DA14531 know HCI
firmware
included in
BTstack
199

SCO Multiple
over LE ClassicLE
HCI BD ADDR
HCI LE Roles SC Addr BTstack
Chipset (1) (2) DLE (3)
Type Transport (4) Resolution
folder Comment
Dialog LE H4, No n.a. No No n.a. Don’t da145xx
Official
DA14581 SPI know HCI
firmware
included in
BTstack
Dialog LE H4, No n.a. Yes Yes n.a. Yes da145xxOfficial
DA14585 SPI HCI
firmware
included in
BTstack
Dialog LE H4, No n.a. Yes Yes n.a. Yes da145xxHCI
DA1469x SPI Firmware
part of
DA1469x
SDK
Espressif Dual VHCI,Yes Yes Yes Yes Yes Don’t SoC with
ESP32 mode H4 know Bluetooth
+ and Wifi
Wifi
Espressif LE VHCI,Yes No Yes Yes Yes Yes SoC with
ESP32- + H4 Bluetooth
S3,C3 Wifi and Wifi
EM LE SPI, No n.a. No No n.a. Don’t em9301Custom
9301 H4 know HCI SPI
implementation
EM LE SPI, Yes n.a. Yes Yes n.a. Don’t em9301Custom
9304 H4 know HCI SPI
implementation
EM LE SPI, Yes n.a. Yes Yes n.a. Yes em9301Custom
9305 H4 HCI SPI
implementation
Intel Dual USB Yes Probably
Don’tDon’t Don’t Don’t intel Firmware
Dual mode knowknow know know size: 400
Wireless kB
3165,
8260,
8265
Nordic LE H4 Fixedn.a. Yes Yes n.a. Yes Requires
nRF Random HCI
firmware
200

SCO Multiple
over LE ClassicLE
HCI BD ADDR
HCI LE Roles SC Addr BTstack
Chipset (1) (2) DLE (3)
Type Transport (4) Resolution
folder Comment
NXP Dual H4 Yes Partially(2)
Yes Yes No Yes nxp Requires
88W8997 mode initial
firmware
NXP Dual H4 Yes No Yes Yes No Yes nxp Requires
IW416 mode initial
firmware
NXP Dual H4 Yes Partially(2)
Yes Yes No Yes nxp Requires
IW61x mode initial
firmware
STM ClassicH4 No Don’t n.a n.a. No n.a. stlc2500d
Custom
STLC2500D know deep sleep
manage-
ment not
supported
Renesas LE H4 No n.a. Yes Yes n.a . Don’t HCI
RX23W know Firmware
part of
BTTS
Realtek Dual H5 Yes Yes Don’tDon’t Don’t Don’t Requires
RTL8822CS
mode knowknow know know initial
+ firmware +
Wifi config
Realtek Dual USB Yes Yes Don’tDon’t Don’t Don’t realtekRequires
USB mode knowknow know know initial
Dongles + firmware +
Wifi config
Toshiba Dual H4 No No No No No No tc3566Only
TC35661 mode -007/009
models
provide full
HCI. See
below
TI Dual H4, Yes Yes No Yes No No cc256xAlso
CC256x, mode H5, for WL185x,
WL183x eHCILL CC256XC WL187x,
and
WL189x

0.106. Chipset Overview. Notes:


1. BD ADDR: Indicates if Bluetooth chipset comes with its own valid MAC
Address. Better Broadcom and CSR dongles usually come with a MAC
201

address from the dongle manufacturer, but cheaper ones might come with
identical addresses.
2. SCO over HCI: All Bluetooth Classic chipsets support SCO over HCI in
general. BTstack can receive SCO packets without problems. However,
only TI CC256x has support for using SCO buffers in the Controller and
a useful flow control. On CSR/Broadcom/Cypress Controllers, BTstack
cannot queue multiple SCO packets in the Controller. Instead, the SCO
packet must be sent periodically at the right time - without a clear in-
dication about when this time is. The current implementation observes
the timestamps of the received SCO packets to schedule sending packets.
With full control over the system and no other Bluetooth data, this can
be flawless, but it’s rather fragile in general. For these, it’s necessary
to use the I2S/PCM interface for stable operation. , for those that are
marked with No, we either didn’t try or didn’t found enough information
to configure it correctly.
3. Multiple LE Roles: Apple uses Broadcom Bluetooth+Wifi in their iOS
devices and newer iOS versions support multiple concurrent LE roles, so
at least some Broadcom models support multiple concurrent LE roles.
0.107. Atmel/Microchip. The ATILC3000 Bluetooth/Wifi combo controller
has been used with Linux on embedded devices by Atmel/Microchip. Drivers
and documentation are available from a GitHub repository. The ATWILC3000
has a basic HCI implementation stored in ROM and requires a firmware image
to be uploaded before it can be used. The BLE Controller is qualified as QDID
99659. Please note: the BLE firmware is around 60 kB. It might need a separate
Wifi firmware as well.
BD Addr can be set with vendor-specific command although all chipsets have
an official address stored. The BD ADDR lookup results in “Newport Media
Inc.” which was acquired by Atmel in 2014.
Baud rate can be set with a custom command.
BTstack integration: btstack chipset atwilc3000.c contains the code to down-
load the Bluetooth firmware image into the RAM of the ATWILC3000. After
that, it can be normally used by BTstack.
0.108. Broadcom/Cypress/Infineon Semiconductor. Before the Broadcom
Wifi+Bluetooth division was taken over by Cypress Semiconductor, it was not
possible to buy Broadcom chipset in low quantities. Nevertheless, module man-
ufacturers like Ampak created modules that contained Broadcom BCM chipsets
(Bluetooth as well as Bluetooth+Wifi combos) that might already have been
pre-tested for FCC and similar certifications.
A popular example is the Ampak AP6212A module that contains an BCM
43438A1 and is used on the Raspberry Pi 3, the RedBear Duo, and the RedBear
IoT pHAT for older Raspberry Pi models.
The CYW20704 A2 controller supports both DLE as well as multiple LE roles
and is available e.g. from LairdTech as UART module (BT860), USB module
(BT850), and USB dongle.
Interestingly, the CYW20704 exhibits the same UART flow control bug as the
CC2564. You can add ENABLE CYPRESS BAUDRATE CHANGE FLOWCONTROL BUG WO
202

to activate a workaround and/or read the bug & workardound description in the
TI section below.
The best source for documentation on vendor specific commands so far has
been the source code for blueZ and the Bluedroid Bluetooth stack from Android,
but with the takeover by Cypress, documentation is directly available.
Broadcom USB dongles do not require special configuration, however SCO
data is not routed over USB by default.
The PSoC 4 SoCs can be programmed with the “BLE DTM” HCI Firmware
from the PSoC Creator Kit Examples. The UART baudrate is set to 115200.
For higher baud rates, the clocks probably need to be configured differently, as
the IDE gives a warning about this.
The CYW20819 can be used as a SoC with Cypress’ Bluetooth stack. To use
it as a regular Bluetooth Controller over HCI H4, CTS must be asserted during
Power-Up / Reset.
The CYW43xxx series contains a Wifi and Bluetooth Controller. The Blue-
tooth Controller can be used independent from the Wifi part.
Newer Controller likes the CYW5557x series requires to enter a so-called au-
tobaud mode by asserting CTS (low) during reset/power-up. In this mode, only
a subset of HCI commands are available. Please see posix-h4-bcm port to get
started.
Init scripts: For UART connected chipsets, an init script has to be up-
loaded after power on. For Bluetooth chipsets that are used in Broadcom
Wifi+Bluetooth combos, this file often can be found as a binary file in Linux
distributions with the ending ‘.hcd’ or as part of the WICED SDK as C source
file that contains the init script as a data array for use without a file system.
To find the correct file, Broadcom chipsets return their model number when
asked for their local name.
BTstack supports uploading of the init script in two variants: using .hcd files
looked up by name in the posix-h4 port and by linking against the init script in
the WICED port. While the init script is processed, the chipsets RTS line goes
high, but only 2 ms after the command complete event for the last command from
the init script was sent. BTstack waits for 10 ms after receiving the command
complete event for the last command to avoid sending before RTS goes high and
the command fails.
BD Addr can be set with a custom command. A fixed address is provided
on some modules, e.g. the AP6212A, but not on others.
SCO data can be configured with a custom command found in the bluez
sources. It works with USB chipsets. The chipsets don’t implement the SCO
Flow Control that is used by BTstack for UART connected devices. A forum
suggests to send SCO packets as fast as they are received since both directions
have the same constant speed.
Baud rate can be set with custom command. The baud rate resets during the
warm start after uploading the init script. So, the overall scheme is this: start
at default baud rate, get local version info, send custom Broadcom baud rate
change command, wait for response, set local UART to high baud rate, and then
send init script. After sending the last command from the init script, reset the
203

local UART. Finally, send custom baud rate change command, wait for response,
and set local UART to high baud rate.
BTstack integration: The common code for all Broadcom chipsets is pro-
vided by btstack chipset bcm.c. During the setup, btstack chipset bcm instance
function is used to get a btstack chipset t instance and passed to hci init function.
SCO Data can be routed over HCI for both USB dongles and UART con-
nections, however BTstack only can send audio correctly over UART with newer
Controllers that support SCO Flow Control. HSP and HFP Narrow Band Speech
is supported via I2C/PCM pins. Newer Controllers provide an mSBC codec that
allows to use HSP/HFP incl. WBS over PCM/I2S with ENABLE BCM PCM WBS.

0.109. CSR / Qualcomm Incorporated. CSR plc has been acquired by Qual-
comm Incorporated in August 2015.
Similar to Broadcom, the best source for documentation is the source code for
blueZ.
CSR USB dongles do not require special configuration and SCO data is routed
over USB by default.
CSR chipset do not require an actual init script in general, but they allow to
configure the chipset via so-called PSKEYs. After setting one or more PSKEYs,
a warm reset activates the new setting.
BD Addr can be set via PSKEY. A fixed address can be provided if the
chipset has some kind of persistent memory to store it. Most USB Bluetooth
dongles have a fixed BD ADDR.
SCO data can be configured via a set of PSKEYs. We haven’t been able to
route SCO data over HCI for UART connections yet.
Baud rate can be set as part of the initial configuration and gets actived by
the warm reset.
BTstack integration: The common code for all Broadcom chipsets is pro-
vided by btstack chipset csr.c. During the setup, btstack chipset csr instance
function is used to get a btstack chipset t instance and passed to hci init function.
The baud rate is set during the general configuration.
SCO Data is routed over HCI for USB dongles, but not for UART connections.
HSP and HFP Narrow Band Speech is supported via I2C/PCM pins.

0.110. Dialog Semiconductor / Renesas. Daialo Semiconductor has been


aquired by Renesas in February 2021.
They offers the DA145xx and DA1469xx series of LE-only SoCs that can be
programmed with an HCI firmware. The HCI firmware can be uploaded on boot
into SRAM or stored in the OTP (One-time programmable) memory, or in an
external SPI.
The 581 does not implement the Data Length Extension or supports multiple
concurrent roles, while later versions support it.
The mechanism to boot a firmware via UART/SPI has mostly stayed the same,
while the set of supported interfaces and baudrates have slightly changed.
The DA1469x uses an external flash. The DA 1469x SDK contains a HCI
firmware that can be compiled and downloaded into flash using the SmartSnip-
pets Studio.
204

Unexpected issues: - DA14585 cannot scan for other devices if advertising


is enabled alhtough it supports multiple Peripheral/Central roles (last check:
6.0.14.1114)
BD Addr fixed to 80:EA:CA:00:00:01. No command in HCI firmware to set
it differently. Random addresses could be used instead.
Baud rate: The baud rate is fixed at 115200 with the provided firmware. A
higher baud rate could be achieved by re-compiling the HCI firmware.
BTstack integration: btstack chipset da145xx.c contains the code to down-
load the provided HCI firmware into the SRAM of the DA145xx. After that, it
can be used as any other HCI chipset. No special support needed for DA1469x
after compiling and flashing the HCI firmware.
0.111. Espressif ESP32. The ESP32 is a SoC with a built-in Dual mode Blue-
tooth and Wifi radio. The HCI Controller is implemented in software and ac-
cessed via a so called Virtual HCI (VHCI) interface. It supports both LE Data
Length Extensions (DLE) as well as multiple LE roles. Since ESP-IDF v4.3,
SCO-over-HCI is usable for HSP/HFP.
The newer ESP32-S3 and ESP32-C3 SoCs have a newer LE Controller that
also supports 2M-PHY, but does support Classic (BR/EDR) anymore.
ALl can either be used as an SoC with the application running on the ESP32
itself or can be configured as a regular Bluetooth HCI Controller. BTstack can
work either on the SoC itself or on another MCU with the ESP32 connected via
4-wire UART.
See Espressif’s ESP-Hosted firmware for use as Bluetooth/Wifi Ccontroller.
0.112. EM Microelectronic Marin. For a long time, the EM9301 has been the
only Bluetooth Single-Mode LE chipset with an HCI interface. The EM9301 can
be connected via SPI or UART. The UART interface does not support hardware
flow control and is not recommended for use with BTstack. The SPI mode uses
a proprietary but documented extension to implement flow control and signal if
the EM9301 has data to send.
In December 2016, EM released the new EM9304 that also features an HCI
mode and adds support for optional Bluetooth 4.2. features. It supports the
Data Length Extension and up to 8 LE roles. The EM9304 is a larger MCU that
allows to run custom code on it. For this, an advanced mechanism to upload
configuration and firmware to RAM or into an One-Time-Programmable area of
128 kB is supported. It supports a superset of the vendor specific commands of
the EM9301.
EM9304 is used by the ‘stm32-l073rz-em9304’ port in BTstack. The port.c
file also contains an IRQ+DMA-driven implementation of the SPI H4 protocol
specified in the datasheet.
BD Addr must be set during startup for EM9301 since it does not have a
stored fix address. The EM9304 comes with an valid address stored in OTP.
SCO data is not supported since it is LE only.
Baud rate can be set for UART mode. For SPI, the master controls the speed
via the SPI Clock line. With 3.3V, 16 Mhz is supported.
Init scripts are not required although it is possible to upload small firmware
patches to RAM or the OTP memory (EM9304 only).
205

BTstack integration: The common code for the EM9304 is provided by bt-
stack chipset em9301.c. During the setup, btstack chipset em9301 instance func-
tion is used to get a btstack chipset t instance and passed to hci init function.
It enables to set the BD Addr during start.

0.113. Intel Dual Wireless 8260, 8265. Wifi/Bluetooth combo cards mainly
used in mobile computers. The Bluetooth part requires the upload of a firmware
file and a configuration file. SCO, DLE, Multiple roles not tested.

0.114. Nordic nRF5 series. The Single-Mode LE chipsets from the Nordic
nRF5 series chipsets usually do not have an HCI interface. Instead, they provide
an LE Bluetooth Stack as a binary library, the so-called SoftDevices. Developer
can write their Bluetooth application on top of this library. Since the chipset can
be programmed, it can also be loaded with a firmware that provides a regular
HCI H4 interface for a Host.
An interesting feature of the nRF5 chipsets is that they can support multiple
LE roles at the same time, e.g. being Central in one connection and a Peripheral
in another connection. Also, the nRF52 SoftDevice implementation supports the
Bluetooth 4.2 Data Length Extension.
Both nRF5 series, the nRF51 and the nRF52, can be used with an HCI
firmware. The nRF51 does not support encrypted connections at the moment
(November 18th, 2016) although this might become supported as well.
BD ADDR is not set automatically. However, during production, a 64-bit
random number is stored in the each chip. Nordic uses this random number as
a random static address in their SoftDevice implementation.
SCO data is not supported since it is LE only.
Baud rate is fixed to 115200 by the patch although the firmware could be
extended to support a baud rate change.
Init script is not required.
BTstack integration: Support for a nRF5 chipset with the Zephyr Con-
troller is provided by btstack chipset zephyr.c. It queries the static random ad-
dress during init.
To use these chipsets with BTstack, you need to install an arm-none-eabi gcc
toolchain and the nRF5x Command Line Tools incl. the J-Link drivers, checkout
the Zephyr project, apply a minimal patch to help with using a random static
address, and flash it onto the chipset:
• Install J-Link Software and documentation pack.
• Get nrfjprog as part of the nRFx-Command-Line-Tools. Click on Down-
loads tab on the top and look for your OS.
• Checkout Zephyr and install toolchain. We recommend using the arm-
non-eabi gcc binaries instead of compiling it yourself. At least on OS X,
this failed for us.
• In samples/bluetooth/hci uart compile the firmware for nRF52 Dev Kit

$ make BOARD=n r f 5 2 p c a 1 0 0 4 0
206

• Upload the firmware


$ ./flash nrf52 pca10040.sh
• For the nRF51 Dev Kit, use make BOARD=nrf51 pca10028 and ./ flash nrf51 10028
.sh with the nRF51 kit.
• The nRF5 dev kit acts as an LE HCI Controller with H4 interface.
0.115. NXP Semiconductors. NXP Semiconductors acquired the Bluetooth
+ Wifi division of Marvel in 2019 and continues their products with new names.
As the Controllers contain no Bluetooth firmware, the firmware needs to be
uploaded on start. BTstack supports firmware upload for older Controllers with
bootloader version v1, like the NXP 88W8997.
BD ADDR is stored in Controller.
SCO data is routed over HCI by default but does not support flow control.
Baud rate is currently kept at 115200
Init script is required.
BTstack integration: firmware update required and implemented by bt-
stack chipset nxp.c See port/posix-h4-nxp for details on how to use it.
0.116. Realtek. Realtek provides Dual-Mode Bluetooth Controllers with USB
and UART (H4/H5) interfaces as well as combined Bluetooth/WiFi Controllers,
which are also available as M.2 modules for laptops. They commonly require to
download a patch and a configuration file. Patch and configuration file can be
found as part of their Linux drivers.
BD ADDR is stored in Controller.
SCO data can either be routed over HCI with working flow control or over
I2S/PCM. The 8822CS supports mSBC codec internally.
Baud rate is set by the config file.
Init script is required.
BTstack integration: H4/H5 Controller require firmware upload. ‘rtk attach’
can be used for this. For USB Controllers, btstack chipset realtek.c implements
the patch and config upload mechanism. See port/libusb for details on how to
use it.
0.117. Renesas Electronics. Please see Dialog Semiconducator for DA14xxx
Bluetooth SoCs above.
Renesas currently has 3 LE-only SoCs: the older 16-bit RL78 and the newer
RX23W and the RA4W1. For the newer SoCs, Renesas provides a pre-compiled
HCI firmware as well as an HCI project for their e2 Studio IDE. The HCI firmware
needs to be programmed into the SoC Flash.
Both newer SoC provide the newer Bluetooth 5.0 features like DLE, 2M-PHY,
Long Range, and Multiple Roles.
To install the HCI Firmware on the Target Board for RX23W:
• Download Bluetooth Test Tool Suite
• Install Renesas Flash Programmer
• Follow instruction in Target Board for RX23W Quick Start Guide to flash
rx23w uart hci sci8 br2000k v1.00.mot
BD Addr fixed to 74:90:50:FF:FF:FF. A Windows tool in the BTTS suite
allows to set a public Bluetooth Address.
207

Baud rate: The baud rate is fixed at 115200 resp. 2000000 with the provided
firmware images. With 2 mbps, there’s no need to update the baudrate at run-
time.
BTstack integration: No special support needed.
0.118. STMicroelectronics. STMicroelectronics has several different Bluetooth
series.
0.118.1. STLC2500D. It offers the Bluetooth V2.1 + EDR chipset STLC2500D
that supports SPI and UART H4 connection.
BD Addr can be set with custom command although all chipsets have an
official address stored.
SCO data might work. We didn’t try.
Baud rate can be set with custom command. The baud rate change of the
chipset happens within 0.5 seconds. At least on BTstack, knowning exactly when
the command was fully sent over the UART is non-trivial, so BTstack switches
to the new baud rate after 100 ms to expect the command response on the new
speed.
Init scripts are not required although it is possible to upload firmware patches.
BTstack integration: Support for the STLC2500C is provided by btstack chipset stlc.c.
During the setup, btstack chipset stlc2500d instance function is used to get a bt-
stack chipset t instance and passed to hci init function. It enables higher UART
baud rate and to set the BD Addr during startup.
0.118.2. BlueNRG. The BlueNRG series is an LE-only SoC which can be used
with an HCI Firmware over a custom SPI interface.
0.118.3. STM32-WB5x. The new STM32-WB5x series microcontroller is an SoC
with a multi-protocol 2.4 Ghz radio co-processor. It provides a virtual HCI
interface.
0.119. Texas Instruments CC256x series. The Texas Instruments CC256x
series is currently in its fourth iteration and provides a Classic-only (CC2560), a
Dual-mode (CC2564), and a Classic + ANT (CC2567) model. A variant of the
Dual-mode chipset is also integrated into TI’s WiLink 8 Wifi+Bluetooth combo
modules of the WL183x, WL185x, WL187x, and WL189x series. Some of the
latter support ANT as well.
The CC256x chipset is connected via an UART connection and supports the
H4, H5 (since third iteration), and eHCILL.
The latest generation CC256xC chipsets support multiple LE roles in parallel.
TI provides an alternative firmware that integrates an SBC Codec in the Blue-
tooth Controller itself for Assisted A2DP (A3DP) and Assisted HFP (Wide-band
speech support). While this can save computation and code size on the main
host, it cannot be used together with BLE, making it useless in most projects.
The different CC256x chipset can be identified by the LMP Subversion re-
turned by the hci read local version information command. TI also uses a nu-
meric way (AKA) to identify their chipsets. The table shows the LMP Subversion
and AKA number for the CC256x and the WL18xx series.
208

Chipset LMP Subversion AKA


CC2560 0x191f 6.2.31
CC2560A, CC2564, CC2567 0x1B0F 6.6.15
CC256xB 0x1B90 6.7.16
CC256xC 0x9a1a 6.12.26
WL18xx 0xac20 11.8.32

SCO data: Routing of SCO data can be configured with the HCI VS Write SCO Configuration
command.
Baud rate can be set with HCI VS Update UART HCI Baudrate. The chipset
confirms the change with a command complete event after which the local UART
is set to the new speed. Oddly enough, the CC256x chipsets ignore the incoming
CTS line during this particular command complete response.
If you’ve implemented the hal uart dma.h without an additional ring buffer
(as recommended!) and you have a bit of delay, e.g. because of thread switch-
ing on a RTOS, this could cause a UART overrun. If this happens, BTstack
provides a workaround in the HCI H4 transport implementation by adding
ENABLE CC256X BAUDRATE CHANGE FLOWCONTROL BUG WORKAROUND. If this
is enabled, the H4 transport layer will resort to “deep packet inspection” to first
check if its a TI controller and then wait for the HCI VS Update UART HCI Baudrate.
When detected, it will tweak the next UART read to expect the HCI Command
Complete event.
BD Addr can be set with HCI VS Write BD Addr although all chipsets have an
official address stored.
Init Scripts. In order to use the CC256x chipset an initialization script must
be obtained and converted into a C file for use with BTstack. For newer revisions,
TI provides a main.bts and a ble add on.bts that need to be combined.
The Makefile at chipset/cc256x/Makefile.inc is able to automatically download
and convert the requested file. It does this by:
• Downloading one or more BTS files for your chipset.
• Running the Python script:

. / c o n v e r t b t s i n i t s c r i p t s . py main . b t s [ b l e a d d o n . b t s ] o u t p u t f i l e .
c

BTstack integration: - The common code for all CC256x chipsets is pro-
vided by btstack chipset cc256x.c. During the setup, btstack chipset cc256x instance
function is used to get a btstack chipset t instance and passed to hci init function.
btstack chipset cc256x lmp subversion provides the LMP Subversion for the se-
lected init script. - SCO Data is be routed over HCI with ENABLE SCO OVER HCI
or to PCM/I2S with ENABLE SCO OVER PCM. Wide-band speech is supported
in both cases. For SCO-over-HCI, BTstack implements the mSBC Codec. For
SCO-over-I2S, Assisted HFP can be used. - Assisted HFP: BTstack provides sup-
port for Assisted HFP mode if enabled with ENABLE CC256X ASSISTED HFP and
SCO is routed over PCM/I2S with ENABLE SCO OVER PCM. During startup,
209

the PCM/I2S is configured and the HFP implementation will enable/disable the
mSBC Codec for Wide-band-speech when needed.
Known issues: - The CC2564C v1.5 may loose the connection in Peripheral
role with a Slave Latency > 0 when the Central updates Connection Parameters.
See https://github.com/bluekitchen/btstack/issues/429
0.120. Toshiba. The Toshiba TC35661 Dual-Mode chipset is available in three
variants: standalone incl. binary Bluetooth stack, as a module with embedded
stack or with a regular HCI interface. The HCI variant has the model number
TC35661–007 resp TC35561-009 for the newer silicon.
We first tried their USB Evaluation Stick that contains an USB-to-UART
adapter and the PAN1026 module that contains the TC35661 -501. While it does
support the HCI interface and Bluetooth Classic operations worked as expected,
LE HCI Commands are not supported. With the -007 and the -009 models,
everything works as expected.
SCO data does not seem to be supported.
Baud rate can be set with custom command.
BD Addr must be set with custom command. It does not have a stored
valid public BD Addr.
Init Script is not required. A patch file might be uploaded.
BTstack integration: Support for the TC35661 series is provided by bt-
stack chipset tc3566x.c. During the setup, btstack chipset tc3566x instance func-
tion is used to get a btstack chipset t instance and passed to hci init function.
It enables higher UART baud rate and sets the BD Addr during startup.
#Porting to Other Platforms
In this section, we highlight the BTstack components that need to be adjusted
for different hardware platforms.
0.121. Time Abstraction Layer. BTstack requires a way to learn about pass-
ing time. btstack run loop embedded.c supports two different modes: system ticks
or a system clock with millisecond resolution. BTstack’s timing requirements are
quite low as only Bluetooth timeouts in the second range need to be handled.
0.121.1. Tick Hardware Abstraction. If your platform doesn’t require a system
clock or if you already have a system tick (as it is the default with CMSIS on
ARM Cortex devices), you can use that to implement BTstack’s time abstraction
in include/btstack/hal tick.h>.
For this, you need to define HAVE EMBEDDED TICK in btstack config.h:

#define HAVE EMBEDDED TICK

Then, you need to implement the functions hal tick init and hal tick set handler,
which will be called during the initialization of the run loop.

void h a l t i c k i n i t ( void ) ;
void h a l t i c k s e t h a n d l e r ( void ( ∗ t i c k h a n d l e r ) ( void ) ) ;
int h a l t i c k g e t t i c k p e r i o d i n m s ( void ) ;
210

After BTstack calls hal tick init() and hal tick set handler(tick handler), it ex-
pects that the tick handler gets called every hal tick get tick period in ms() ms.
0.121.2. Time MS Hardware Abstraction. If your platform already has a system
clock or it is more convenient to provide such a clock, you can use the Time MS
Hardware Abstraction in include/btstack/hal time ms.h.
For this, you need to define HAVE EMBEDDED TIME MS in btstack config.h:

#define HAVE EMBEDDED TIME MS

Then, you need to implement the function hal time ms(), which will be called
from BTstack’s run loop and when setting a timer for the future. It has to return
the time in milliseconds.

uint32 t h a l t i m e m s ( void ) ;

0.122. Bluetooth Hardware Control API. The Bluetooth hardware control


API can provide the HCI layer with a custom initialization script, a vendor-
specific baud rate change command, and system power notifications. It is also
used to control the power mode of the Bluetooth module, i.e., turning it on/off
and putting to sleep. In addition, it provides an error handler hw error that is
called when a Hardware Error is reported by the Bluetooth module. The callback
allows for persistent logging or signaling of this failure.
Overall, the struct btstack control t encapsulates common functionality that is
not covered by the Bluetooth specification. As an example, the btstack chipset cc256x in-
stance function returns a pointer to a control struct suitable for the CC256x
chipset.
0.123. HCI Transport Implementation. On embedded systems, a Bluetooth
module can be connected via USB or an UART port. BTstack implements three
UART based protocols for carrying HCI commands, events and data between
a host and a Bluetooth module: HCI UART Transport Layer (H4), H4 with
eHCILL support, a lightweight low-power variant by Texas Instruments, and the
Three-Wire UART Transport Layer (H5).
0.123.1. HCI UART Transport Layer (H4). Most embedded UART interfaces
operate on the byte level and generate a processor interrupt when a byte was
received. In the interrupt handler, common UART drivers then place the received
data in a ring buffer and set a flag for further processing or notify the higher-level
code, i.e., in our case the Bluetooth stack.
Bluetooth communication is packet-based and a single packet may contain up
to 1021 bytes. Calling a data received handler of the Bluetooth stack for every
byte creates an unnecessary overhead. To avoid that, a Bluetooth packet can be
read as multiple blocks where the amount of bytes to read is known in advance.
211

Even better would be the use of on-chip DMA modules for these block reads, if
available.
The BTstack UART Hardware Abstraction Layer API reflects this design ap-
proach and the underlying UART driver has to implement the following API:

void hal uart dma i n i t ( void ) ;


void hal uart dma s e t b l o c k r e c e i v e d ( void ( ∗ b l o c k h a n d l e r ) ( void ) ) ;
void hal uart dma s e t b l o c k s e n t ( void ( ∗ b l o c k h a n d l e r ) ( void ) ) ;
int hal uart dma s e t b a u d ( uint32 t baud ) ;
void hal uart dma s e n d b l o c k ( const uint8 t ∗ b u f f e r , uint16 t l e n ) ;
void hal uart dma r e c e i v e b l o c k ( uint8 t ∗ b u f f e r , uint16 t l e n ) ;

The main HCI H4 implementations for embedded system is *hci h4 transport-


dma* function. This function calls the following sequence: hal uart dma init,
hal uart dma set block received and hal uart dma set block sent functions. this
sequence, the HCI layer will start packet processing by calling *hal uart- dma receive block*
function. The HAL implementation is responsible for reading the requested
amount of bytes, stopping incoming data via the RTS line when the requested
amount of data was received and has to call the handler. By this, the HAL
implementation can stay generic, while requiring only three callbacks per HCI
packet.
0.123.2. H4 with eHCILL support. With the standard H4 protocol interface, it is
not possible for either the host nor the baseband controller to enter a sleep mode.
Besides the official H5 protocol, various chip vendors came up with proprietary
solutions to this. The eHCILL support by Texas Instruments allows both the
host and the baseband controller to independently enter sleep mode without
loosing their synchronization with the HCI H4 Transport Layer. In addition
to the IRQ-driven block-wise RX and TX, eHCILL requires a callback for CTS
interrupts.

void h a l u a r t d m a s e t c t s i r q h a n d l e r ( void ( ∗ c t s i r q h a n d l e r ) ( void ) ) ;


void h a l u a r t d m a s e t s l e e p ( uint8 t s l e e p ) ;

0.123.3. H5. H5, makes use of the SLIP protocol to transmit a packet and can
deal with packet loss and bit-errors by retransmission. Since it can recover from
packet loss, it’s also possible for either side to enter sleep mode without loosing
synchronization.
The use of hardware flow control in H5 is optional, however, since BTstack
uses hardware flow control to avoid packet buffers, it’s recommended to only use
H5 with RTS/CTS as well.
For porting, the implementation follows the regular H4 protocol described
above.
0.124. Persistent Storage APIs. On embedded systems there is no generic
way to persist data like link keys or remote device names, as every type of a
212

device has its own capabilities, particularities and limitations. The persistent
storage APIs provides an interface to implement concrete drivers for a particular
system.

0.124.1. Link Key DB. As an example and for testing purposes, BTstack pro-
vides the memory-only implementation btstack link key db memory. An imple-
mentation has to conform to the interface in Listing below.

typedef struct {
// management
void ( ∗ open ) ( ) ;
void ( ∗ c l o s e ) ( ) ;

// l i n k key
int ( ∗ g e t l i n k k e y ) ( bd addr t bd addr , l i n k k e y t l i n k k e y ) ;
void ( ∗ p u t l i n k k e y ) ( bd addr t bd addr , l i n k k e y t key ) ;
void ( ∗ d e l e t e l i n k k e y ) ( bd addr t bd addr ) ;
} btstack link key db t ;

#Existing Ports

0.125. Existing ports.


• BTstack Port for Ambiq Apollo2 with EM9304
• Archive of earlier ports
• BTstack Port for the Espressif ESP32 Platform
• BTstack Port for FreeBSD Systems
• BTstack Port for POSIX Systems with libusb Library
• BTstack Port for POSIX Systems with Intel Wireless 8260/8265 Con-
trollers
• BTstack Port for the Maxim MAX32630FTHR ARM Cortex-M4F
• BTstack Port for MSP432P401 Launchpad with CC256x
• BTstack Port with Cinnamon for Nordic nRF5 Series
• BTstack Port for POSIX Systems with H4 Bluetooth Controller
• BTstack Port for POSIX Systems with Atmel ATWILC3000 Controller
• BTstack Port for POSIX Systems with modern Infineon (CYW) H4 Blue-
tooth Controller
• BTstack Port for POSIX Systems with Dialog Semiconductor DA14531
Controller
• BTstack Port for POSIX Systems with Dialog Semiconductor DA14581
Controller
• BTstack Port for POSIX Systems with Dialog Semiconductor DA14585
Controller
• BTstack Port for POSIX Systems with NXP/Marvel H4 Bluetooth Con-
troller
• BTstack Port for POSIX Systems with Zephyr-based Controller
• BTstack Port for QT with H4 Bluetooth Controller
• BTstack Port for QT with USB Bluetooth Dongle
213

• BTstack Port for Raspberry Pi 3 with BCM4343 Bluetooth/Wifi Con-


troller
• BTstack Port for Renesas Eval Kit EK-RA6M4 with DA14531
• BTstack Port for Renesas Target Board TB-S1JA with CC256x
• BTstack Port for SAMV71 Ultra Xplained with ATWILC3000 SHIELD
• BTstack Port for STM32 F4 Discovery Board with CC256x
• BTstack Port for STM32 F4 Discovery Board with USB Bluetooth Con-
troller
• BTstack Port for STM32 Nucleo L073RZ Board with EM9304 Controller
• BTstack Port with Cinnamon for Semtech SX1280 Controller on Miromico
FMLR-80
• BTstack Port with Cinnamon for Semtech SX1280 Controller on STM32L476
Nucleo
• BTstack Port for STM32WB55 Nucleo Boards using FreeRTOS
• BTstack Port for WICED platform
• BTstack Port for Windows Systems with Bluetooth Controller connected
via Serial Port
• BTstack Port for Windows Systems with DA14585 Controller connected
via Serial Port
• BTstack Port for Windows Systems with Zephyr-based Controller
• BTstack Port for Windows Systems using the WinUSB Driver
• BTstack Port for Windows Systems with Intel Wireless 8260/8265 Con-
trollers
• BTstack Port for Zephyr RTOS
0.126. BTstack Port for Ambiq Apollo2 with EM9304. This port uses
the Ambiq Apollo2 EVB and the Ambiq EM9304 (AM BLE) shield. HAL and
BSP from Ambiq Suite 1.2.11 were used together with the regular ARM GCC
toolchain. Firmware upload is possible via the internal J-Link interface or the
10-pin Mini ARM-JTAG Interface.
0.126.1. Hardware. Ambiq Apollo2 EVB + AM BLE Shield - http://ambiqmicro.com/apollo-
ultra-low-power-mcus/apollo2-mcu/
0.126.2. Software. AmbiqSuite: - http://ambiqmicro.com/apollo-ultra-low-power-
mcus/apollo2-mcu/
Please clone BTstack as AmbiqSuite/third-party/bstack folder into the Am-
biqSuite.
0.126.3. Create Example Projects. To create example GCC projects, go to the
Apollo2-EM9304 folder

$ cd p o r t / a p o l l o 2 −em9304

and run make

$ . / c r e a t e e x a m p l e s . py
214

All examples are placed in the boards/apollo2 evb am ble/examples folder


with btstack prefix.

0.126.4. Compile & Run Example Project. Go to to the gcc folder of one of the
example folders and run make

$ make

To upload, please follow the instructions in the Apollo Getting Started docu-
ments.

0.126.5. Debug output. printf is routed over the USB connector of the EVB at
115200.
In port/apollo2-em9304/btstack config.h additional debug information can be
enabled by uncommenting ENABLE LOG INFO.
Also, the full packet log can be enabled in src/btstack port.c by uncommenting
the hci dump init(..) line. The console output can then be converted into .pklg
files for OS X PacketLogger or WireShark by running tool/create packet log.py

0.126.6. TODO.
• BTstack’s TLV persisten storage via Flash memory is not implemented
yet.
• SPI Fullduplex: Newer Apollo 2 revisions supports SPI Full Duplex. The
Ambiq Suite 1.2.11 does not cover Full Duplex with IRQ callback. It
could be emulated by setting the Full Duplex mode and doing a regular
write operation. When the write is complete, the received data can be
read from the IOM FIFO.
• During MCU sleep without an ongoing SPI operation, the SPI could be
fully disabled, which would reduce enrgey consumption.

0.127. Archive of earlier ports. The ports in this folder are not recommended
for new designs. This does not mean that the target hardware is not suitable for
new designs, just that the ports would need to reworked/refreshed.
List of ports with reason for move to this archive:
• MSP430 ports: The ports used the not-maintained version of the com-
munity MSP430 gcc port, which does not support more than 64 kB of
FLASH RAM. A current port should use the official GCC version spon-
sored by TI. In addition, the MSP430 UART does not support hardware
RTS/CTS. For a new port, our ringbuffer approach should be used. In-
dividual ports:
– EZ430-RF256x Bluetooth Evaluation Tool for MSP430
– MSP430F5438 Experimenter Board for MSP430 with Bluetooth CC2564
Module Evaluation Board
– MSP-EXP430F5529LP LaunchPad with Bluetooth CC2564 Mod-
ule Evaluation Board and EM Adapter BoosterPack with additional
32768Hz quartz oscillator
215

• Ports for Broadcom/Cypress Controllers using HCI Transport H5: The


PatchRAM cannot be uploaded via H5. This requires to upload the
PatchRAM using H4 mode and then to start the stack using H5 transport.
In addition, several bugs have been observed in H5 mode, e.g. LE Encrypt
not wokring. Unless absolutely neccessary, it’s better to use H4 mode.
– Unix-based system connected to Broadcom/Cypress Bluetooth mod-
ule via H5 over serial port
– Broadcom platforms that support the WICED SDK via H5 UART,
see wiced-h4
• Port for MicroChip PIC32 with Harmony Framework: the original port
was for Harmony v1, while there’s a Harmony V3 out since 2019:
– Microchip’s PIC32 Bluetooth Audio Development Kit
• iOS port:
– BTstack on iOS is not supported anymore.

0.128. BTstack Port for the Espressif ESP32 Platform. Status: Basic
port incl. all examples. BTstack runs on dedicated FreeRTOS thread. Multi
threading (calling BTstack functions from a different thread) is not supported.

0.128.1. Setup.
• Follow Espressif IoT Development Framework (ESP-IDF) setup to install
XTensa toolchain and the ESP-IDF.
• Currently used for testing: ESP-IDF v4.4 or v5.0

0.128.2. Usage. In port/esp32, run

. / i n t e g r a t e b t s t a c k . py

The script will copy parts of the BTstack tree into the ESP-IDF as $IDF PATH/components/btsta
and then create project folders for all examples.
Each example project folder, e.g. port/esp32/examples/spp and le counter,
contains a CMake project file. Please run the integrate btstack .py command again
after updating the BTstack tree (e.g. by git pull) to also update the copy in the
ESP-IDF.
The examples are configure for the original ESP32. IF you want to use the
newer ESP32-C3 or ESP32-S3 - both only support Bluetooth LE - you need to:
1. set target:

‘ i d f . py s e t −t a r g e t esp32c3 ‘

or

‘ i d f . py s e t −t a r g e t e s p 3 2 s 3 ‘

2. re-enable Bluetooth Controller via menuconfig


1. idf .py menuconfig
216

2. select Component Config


3. select Bluetooth and enable
4. select Bluetooth Host
5. select Controller Only
6. exit and save config
To compile an example, run:

i d f . py

To upload the binary to your device, run:

i d f . py −p PATH−TO−DEVICE f l a s h

To get debug output, run:

i d f . py monitor

You can quit the monitor with CTRL-].


0.128.3. Configuration. The sdkconfig of the example template disables the origi-
nal Bluedroid stack by disabling the CONFIG BLUEDROID ENABLED kconfig
option.
0.128.4. Limitations.
0.128.5. Issues with the Bluetooth Controller Implementation. There are differ-
ent issues in the Bluetooth Controller of the ESP32 that is provided in bi-
nary. We’ve submitted appropriate issues on the GitHub Issues page here:
https://github.com/espressif/esp-idf/issues/created by/mringwal
0.128.6. Audio playback. Audio playback is implemented by btstack audio esp32.c
and supports generic I2S codecs as well as the ES8388 on the ESP32 LyraT v4.3
devkit.
It uses the first I2S interface with the following pin out:

ESP32 pin I2S Pin


GPIO0 MCK
GPIO5 BCLK
GPIO25 LRCK
GPIO26 DOUT
GPIO35 DIN

If support for the LyraT v4.3 is enabled via menuconfig - Example Board Con-
figuration –> ESP32 board –> ESP32-LyraT V4.3, CONFIG ESP LYRAT V4 3 BOARD
gets defined and the ES8388 will be configured as well.
217

We’ve also used the MAX98357A on the Adafruit breakout board. The sim-
plest audio example is the mod player, which plays back an 8 kB sound file and
the a2dp sink demo that implements a basic Bluetooth loudspeaker.

0.128.7. ESP32 printf/log. The BTstack port setups a buffered output for print-
f/ESP log macros. However, if that gets full, the main thread will get blocked.
If you’re playing audio, e.g. a2dp sink demo, and a lot of text is sent over the
UART, this will cause audio glitches as the I2S DMA driver isn’t re-filled on
time. If this happens, you can increase the UART baudrate, reduce the debug
output or increase the output buffer size - or any combination of these. :)

0.128.8. Multi-Threading. BTstack is not thread-safe, but you’re using a multi-


threading OS. Any function that is called from BTstack, e.g. packet handlers,
can directly call into BTstack without issues. For other situations, you need to
provide some general ‘do BTstack tasks’ function and trigger BTstack to execute
it on its own thread. To call a function from the BTstack thread, you can use
btstack run loop execute on main thread allows to directly schedule a function
callback, i.e. ‘do BTstack tasks’ function, from the BTstack thread. The called
function should check if there are any pending BTstack tasks and execute them.
We’re considering different options to make BTstack thread-safe, but for now,
please use one of the suggested options.

0.128.9. Acknowledgments. First HCI Reset was sent to Bluetooth chipset by


[@mattkelly](https://github.com/mattkelly)

0.129. BTstack Port for FreeBSD Systems.

0.129.1. Overview. This port assumes that FreeBSD provides an ng hci netgraph
node for a connected Bluetooth Controller. In most cases, these are Bluetooth
USB dongles or built-in Bluetooth Controller connected via USB.
For Bluetooth Controllers connected via UART, the POSX-H4 port might be
a better option als

0.129.2. Implementation details. In FreeBSD 13.2, the hci node is connected to


a l2cap node and a btsock hci raw node. In order to take control, this port create
a custom netgraph ng socket node and connect to the ‘acl’ and ‘raw’ hooks of
the hci node. The OS Bluetooth functionality will be interrupted.

0.129.3. Compilation. BTstack’s FeeeBSD port does not have additional depen-
dencies. To compile the cmake project with make

mkdir b u i l d
cd b u i l d
cmake . .
make

or using Ninja:
218

mkdir n i n j a
cd n i n j a
cmake . .
ninja

0.129.4. Running the examples. As the port needs to reconfigure the Bluetooth
netgraph node, it needs to run with root privileges. It tries to connect to ‘ubt0hci’
by default. If your Bluetooth Controller is different, you can select it with ‘-
u node’ On start, BTstack prints the path to the packet log and prints the
information on the detected Buetooth Controller.

$ sudo g a t t c o u n t e r
Packet Log : /tmp/ hci dump . p k l g
BTstack c o u n t e r 0001
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .

0.129.5. ToDO.
• drop privileges after startup
• auto-detect ng hci node
• support for profiles that require SCO: HFP & HSP
0.130. BTstack Port for POSIX Systems with libusb Library.
0.130.1. Compilation. The quickest way to try BTstack is on a Linux or OS X
system with an additional USB Bluetooth dongle. It requires pkg-config and
libusb-1.0 or higher to be installed.
On a recent Debian-based system, all you need is:

sudo apt−g e t i n s t a l l g c c g i t cmake n i n j a −b u i l d pkg−c o n f i g l i b u s b −1.0


p o r t a u d i o 1 9 −dev

When everything is ready, you compile all examples with make:

make

or using CMake + Ninja:

mkdir b u i l d
cd b u i l d
cmake −G N i n j a
ninja

0.130.2. Environment Setup.


219

0.130.3. Linux. On Linux, the USB Bluetooth dongle is usually not accessible
to a regular user.
You can add a udev rule for your dongle to extend access rights to user pro-
cesses.
For this, create /etc/udev/rules.d/btstack.rules and add this

# Match a l l d e v i c e s from CSR


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 a12 ” , MODE=” 0666 ”

# Match a l l d e v i c e s from R e a l t e k
SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0bda” , MODE=” 0666 ”

# Match Cypress Semiconductor / Broadcom BCM20702A , e . g . DeLOCK


Bluetooth 4.0 dongle
SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 a5c ” , ATTRS{ i d P r o d u c t}==” 21 e8 ” ,
MODE=” 0666 ”

# Match Asus BT400


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 b05 ” , ATTRS{ i d P r o d u c t}==” 17 cb ” ,
MODE=” 0666 ”

# Match L a i r d BT860 / Cypress Semiconductor CYW20704A2


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 04 b4” , ATTRS{ i d P r o d u c t}==” f 9 0 1 ” ,
MODE=” 0666 ”

0.130.4. macOS. On macOS, the OS will try to use a plugged-in Bluetooth Con-
troller if one is available. It’s best to to tell the OS to always use the internal
Bluetooth Contoller.
For this, execute:

sudo nvram b l u e t o o t h H o s t C o n t r o l l e r S w i t c h B e h a v i o r=n e v e r

and then reboot to activate the change.


Note: if you get this error,

l i b u s b : warning [ darwin open ] USBDeviceOpen : a n o t h e r p r o c e s s has


d e v i c e opened f o r e x c l u s i v e a c c e s s
l i b u s b : e r r o r [ d a r w i n r e s e t d e v i c e ] R e s e t D e v i c e : d e v i c e not opened
for e x c l u s i v e a c c e s s

and you didn’t start another instance and you didn’t assign the USB Controller
to a virtual machine, macOS uses the plugged-in Bluetooth Controller. Please
configure NVRAM as explained and try again after a reboot.

0.130.5. Broadcom/Cypress/Infineon Controllers. During startup BTstack queries


the Controlle for the Local Name, which is set to the Controller type (e.g.
220

’BCM20702A). The chipset support uses this information to look for a local
PatchRAM file of that name and uploads it.

0.130.6. Realtek Controllers. During startup, the libusb HCI transport imple-
mentations reports the USB Vendor/Product ID, which is then forwarded to the
Realtek chipset support. The chipset support contains a mapping between USB
Product ID and ( Patch, Configuration ) files. If found, these are uploaded.

0.130.7. Running the examples. BTstack’s HCI USB transport will try to find a
suitable Bluetooth module and use it.
On start, BTstack will try to find a suitable Bluetooth module. It will also
print the path to the packet log as well as the USB path.

$ ./ le counter
Packet Log : /tmp/ hci dump . p k l g
BTstack c o u n t e r 0001
Packet Log : /tmp/ hci dump 6 . p k l g
USB d e v i c e 0 x0a12 /0 x0001 , path : 06
Local version information :
− HCI V e r s i o n 0 x0006
− HCI R e v i s i o n 0 x22bb
− LMP V e r s i o n 0 x0006
− LMP S u b v e r s i o n 0 x22bb
− Manufacturer 0 x000a
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 0 1 .

If you want to run multiple examples at the same time, it helps to fix the path
to the used Bluetooth module by passing -u usb-path to the executable.
Example running le streamer and le streamer client in two processes, using
CSR Bluetooth dongles at USB path 6 and 4:

. / l e s t r e a m e r −u 6
S p e c i f i e d USB Path : 06
Packet Log : /tmp/ hci dump 6 . p k l g
USB d e v i c e 0 x0a12 /0 x0001 , path : 06
Local version information :
− HCI V e r s i o n 0 x0006
− HCI R e v i s i o n 0 x22bb
− LMP V e r s i o n 0 x0006
− LMP S u b v e r s i o n 0 x22bb
− Manufacturer 0 x000a
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 0 1 .
To s t a r t t h e s t r e a m i n g , p l e a s e run t h e l e s t r e a m e r c l i e n t example on
o t h e r d e v i c e , o r u s e some GATT E x p l o r e r , e . g . LightBlue ,
BLExplr .

$ . / l e s t r e a m e r c l i e n t −u 4
S p e c i f i e d USB Path : 04
Packet Log : /tmp/ hci dump 4 . p k l g
USB d e v i c e 0 x0a12 /0 x0001 , path : 04
221

Local version information :


− HCI V e r s i o n 0 x0006
− HCI R e v i s i o n 0 x22bb
− LMP V e r s i o n 0 x0006
− LMP S u b v e r s i o n 0 x22bb
− Manufacturer 0 x000a
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 0 2 .
Start scanning !

0.131. BTstack Port for POSIX Systems with Intel Wireless 8260/8265
Controllers. Same as port/libusb, but customized for Intel Wireless 8260 and
8265 Controllers. These controller require firmware upload and configuration to
work. Firmware and config is downloaded from the Linux firmware repository.

0.131.1. Compilation. Requirements: - pkg-config - libusb-1.0


On a recent Debian-based system, all you need is:

apt−g e t i n s t a l l g c c g i t l i b u s b −1.0 pkg−c o n f i g

When everything is ready, you compile all examples with:

make

0.131.2. Environment. On Linux, the USB Bluetooth dongle is usually not ac-
cessible to a regular user. You can either: - run the examples as root - add a
udev rule for your dongle to extend access rights to user processes
To add an udev rule, please create /etc/udev/rules.d/btstack.rules and add this

# Match a l l d e v i c e s from CSR


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 a12 ” , MODE=” 0666 ”

# Match DeLOCK B l u e t o o t h 4 . 0 d o n g l e
SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 a5c ” , ATTRS{ d e v i c e}==” 21 e8 ” ,
MODE=” 0666 ”

# Match Asus BT400


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 b05 ” , ATTRS{ d e v i c e}==” 17 cb ” ,
MODE=” 0666 ”

# Match L a i r d BT860 / Cypress Semiconductor CYW20704A2


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 04 b4” , ATTRS{ d e v i c e}==” f 9 0 1 ” ,
MODE=” 0666 ”

# Match I n t e l W i r e l e s s 8260 8265


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 8027 ” , ATTRS{ d e v i c e}==” 0a2b ,
MODE=” 0666 ”
222

On macOS, the OS will try to use a plugged-in Bluetooth Controller if one


is available. It’s best to to tell the OS to always use the internal Bluetooth
Contoller.
For this, execute:

sudo nvram b l u e t o o t h H o s t C o n t r o l l e r S w i t c h B e h a v i o r=n e v e r

and then reboot to activate the change.

0.131.3. Running the examples. BTstack’s HCI USB transport will try to find a
suitable Bluetooth module and use it.
On start, BTstack will try to find a suitable Bluetooth module. It will also
print the path to the packet log as well as the USB path.

$ ./ le counter
Packet Log : /tmp/ hci dump . p k l g
USB Path : 03−01−04−03
Firwmare . / i b t −12−16. s f i
Firmware upload c o m p l e t e
Firmware o p e r a t i o n a l
Done 1
BTstack c o u n t e r 0001
USB Path : 03−01−04−03

BTstack up and running on F8:34:41:D5:BE:6F.


If you want to run multiple examples at the same time, it helps to fix the path
to the used Bluetooth module by passing -u usb-path to the executable.
Example running le streamer and le streamer client in two processes, using
Bluetooth dongles at USB path 6 and 4:

. / l e s t r e a m e r −u 6
S p e c i f i e d USB Path : 06
Packet Log : /tmp/ hci dump 6 . p k l g
USB Path : 06
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .
To s t a r t t h e s t r e a m i n g , p l e a s e run t h e l e s t r e a m e r c l i e n t example on
o t h e r d e v i c e , o r u s e some GATT E x p l o r e r , e . g . LightBlue ,
BLExplr .

$ . / l e s t r e a m e r c l i e n t −u 4
S p e c i f i e d USB Path : 04
Packet Log : /tmp/ hci dump 4 . p k l g
USB Path : 04
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .
Start scanning !
223

0.132. BTstack Port for the Maxim MAX32630FTHR ARM Cortex-


M4F. This port uses the MAX32630FTHR ARM Cortex M4F Board with the
onboard TI CC2564B Bluetooth controller. It usually comes with the DAPLINK
Programming Adapter. The DAPLINK allows to upload firmware via a virtual
mass storage device (like mbed), provides a virtual COM port for a console, and
enables debugging via the SWD interface via OpenOCD.
The port uses non-blocking polling UART communication with hardware flow
control for Bluetooth controller. It was tested and achieved up to 1.8 Mbps
bandwidth between two Max32630FTHR boards.

0.132.1. Software. The Maxim ARM Toolchain is free software that provides
peripheral libraries, linker files, initial code and some board files. It also provides
Eclipse Neon and Maxim modified OpenOCD to program the microcontroller
together with various examples for Maxim Cortex M4F ARM processors.
For debugging, OpenOCD can be used. The regular OpenOCD does not sup-
port Maxim ARM microcontrollers yet, but a modified OpenOCD for use with
Maxim devices can be found in the Maxim ARM Toolchain.

0.132.2. Toolchain Setup. In the Maxim Toolchain installation directory, there


is a setenv.sh file that sets the MAXIM PATH. MAXIM PATH needs to point
to the root directory where the tool chain installed. If you’re lucky and have a
compatible ARM GCC Toolchain in your PATH, it might work without calling
setenv.sh script.

0.132.3. Usage. The examples can be compiled using GNU ARM Toolchain. A
firmware binary can be flashed either by copying the .bin file to the DAPLINK
mass storage drive, or by using OpenOCD on the command line, or from Eclipse
CDT.

0.132.4. Build. Checkt that MAXIM PATH points to the root directory where
the tool chain installed. Then, go to the port/max32630-fthr folder and run
“make” command in terminal to generate example projects in the example folder.
In each example folder, e.g. port/max323630-fthr/example/spp and le streamer,
you can run “make” again to build an .elf file in the build folder which is conve-
nient for debugging using Eclipse or GDB.
For flashing via the virtual USB drive, the “make release” command will gen-
erate .bin file in the build folder.

0.132.5. Eclipse. Toolchain and Eclipse guide can be found in README.pdf file
where the Maxim Toolchain is installed. Please note that this port was done
using Makefiles.

0.132.6. Flashing Max32630 ARM Processor. There are two ways to program
the board. The simplest way is drag and drop the generated .bin file to the
DAPLINK mass storage drive. Once the file is copied to the mass storage device,
the DAPLINK should program and then run the new firmware.
Alternatively, OpenOCD can be used to flash and debug the device. A suitable
programming script can be found in the scripts folder.
224

0.132.7. Debugging. OpenOCD can also be used for developing and especially
for debugging. Eclipse or GDB via OpenOCD could be used for step by step
debugging.

0.132.8. Debug output. printf messages are redirected to UART2. UART2 is


accessible via the DAPLINK Programming Adapter as a virtual COM port at
115200 baud with no flow control. If this doesn’t work for you, you can connect
P3 1 (UART TX) of the MAX32630FTHR board to a USB-to-UART adapter.
Additional debug information can be enabled by uncommenting ENABLE LOG INFO
in the src/btstack config.h header file and a clean rebuild.

0.132.9. TODOs.
• Support for BTSTACK STDIN
• Add flash-openocd to Makefile template
• Add Eclipse CDT projects for max32630fthr
• Implement hal led.h to control LED on board

0.133. BTstack Port for MSP432P401 Launchpad with CC256x. This


port is for the the TI MSP432P401R Launchpad with TI’s CC256x Bluetooth
Controller using TI’s DriverLib (without RTOS). For easy development, Ozone
project files are generated as well.
As the MSP432P401 does not have support for hardware RTS/CTS, this port
makes use of Ping Pong DMA transfer mode (similar to circular DMA on other
MCUs) to use two adjacent receive buffers and raise RTS until a completed buffer
is processed.

0.133.1. Hardware. TI MSP432P401R LaunchPad


As Bluetooth Controller, there are two BoosterPacks that can be use: 1.
BOOST-CC2564MODA CC2564B BoosterPack (USD 20) 2. Evaluation Module
(EM) Adapto (USD 20) with one of the CC256x modules: - CC2564B Dual-
mode Bluetooth Controller Evaluation Module (USD 20) - CC2564C Dual-mode
Bluetooth Controller Evaluation Module (USD 60)
The CC2564B Booster pack is around USD 20 while thhe EM Adapter with
the CC2564C module is around USD 80.
The project in the BTstack repo ‘port/msp432p401lp-cc256x’ is configured for
the EM Adapter + newer CC2564C module.
When using the CC2564B (either as BOOST-CC2564MODA or CC2564B
Dual-mode Bluetooth Controller Evaluation Module), the bluetooth init cc2564B 1.8 BT Spec 4.1.c
must be used as cc256x init script. See Makefile variable INIT SCRIPT.
When using the CC2564B Booster Pack, please use uncomment the defines for
the GPIO definition (search for BOOST−CC2564MODA)
When using the EM Adapter Booster Pack, please make sure to solder a 32.768
kHz quarz oscillator as explained in 4.7 of the EM Wireless Booster Pack User
Guide. If you don’t have an oscillator of that size, you might solder one upside
done (turtle-on-back style) to the unused upper right pad and wire GCC, VCC,
and clock with thin wires.
225

0.133.2. Software. To build all examples, you need the regular ARM GCC toolc-
ahin installed. Run make

$ make

All examples and the .jdebug Ozone project files are placed in the ‘gcc’ folder.
0.133.3. Flash And Run The Examples. The Makefile builds different versions: -
example.elf: .elf file with all debug information - example.bin: .bin file that can
be used for flashing
There are different options to flash and debug the MSP432P401R LaunchPad.
If all but the jumpers for power (the left three) are removed on J101, an external
JTAG like SEGGER’s J-Link can be connected via J8 ‘MSP432 IN’.
0.133.4. Run Example Project using Ozone. When using an external J-Link pro-
grammer, you can flash and debug using the cross-platform SEGGER Ozone
Debugger. It is included in some J-Link programmers or can be used for free for
evaluation usage.
Just start Ozone and open the .jdebug file in the build folder. When compiled
with ENABLE SEGGER RTT, the debug output shows up in the Terminal window
of Ozone.
0.133.5. Debug output. All debug output is send via SEGGER RTT or via US-
ART2. To get the console from USART2, remove ENABLE SEGGER RTT from
btstack config.h and open a terminal to the virtual serial port of the Launchpad
at 115200.
In btstack config.h resp. in example/btstack config.h of the generated projects,
additional debug information can be disabled/enabled via ENABLE LOG INFO.
Also, the full packet log can be enabled in main.c by uncommenting the
hci dump init(..) line. The output can then be converted into .pklg files for
OS X PacketLogger or WireShark by running tool/create packet log.py
0.133.6. GATT Database. In BTstack, the GATT Database is defined via the
.gatt file in the example folder. The Makefile contains rules to update the .h file
when the .gatt was modified.
0.134. BTstack Port with Cinnamon for Nordic nRF5 Series. Cinnamon
is BlueKitchen’s minimal, yet robust Controller/Link Layer implementation for
use with BTstack.
In contrast to common Link Layer implementations, our focus is on a ro-
bust and compact implementation for production use, where code size matters
(e.g. current code size about 8 kB).
0.134.1. Status. The current implementation supports a single Peripheral role,
or, passive scanning in Observer role. In the Peripheral role, channel map up-
dates, as well as connection param updates are supported.
Support for LE Central Role as well as Encryption is planned but not sup-
ported yet.
226

0.134.2. Requirements.
• arm-none-eabi toolchain
• Nordic’s nRF5-SDK

0.134.3. Supported Hardware. All nNRF5x SOCs. Built files are provided for
PCA10040 (52832 DK), but others can be supported with minimal changes.

0.134.4. Use.
• Provide path to nRF5-SDK either in NRF5 SDK ROOT environment vari-
able or directly in pca10040/armgcc/Makefile.
• run make
• All supported examples are built in the build folder.
• You can use Segger’s OZONE with the provided EXAMPLE.jdebug project
file to flash and run the examples.

0.135. BTstack Port for POSIX Systems with H4 Bluetooth Controller.

0.135.1. Configuration. Most Bluetooth Bluetooth Controllers connected via UAR-


T/H4 require some special configuration, e.g. to set the UART baud rate, and/or
require firmware patches during startup. In this port, we’ve tried to do most of
these automatically based on information gathered from the Bluetooth Con-
troller. Here’s some Controller specific details:

0.135.2. TI CC256x. The CC2564x needs the correct init script to start up. The
Makfile already has entries for most silicon revisions:
• CC2560: bluetooth init cc2564 2.14.c
• CC2564B: bluetooth init cc2564B 1.8 BT Spec 4.1.c
• CC2564C: bluetooth init cc2564C 1.5.c
Please pick the correct one. The main.c verifies that the correct script is
loaded, but the init script is linked to the executable.

0.135.3. Broadcom BCM/CYW 43430. The correct firmware file needs to be


provided in the current working directory. The Makefile downloads the one for
the BCM43430 e.g. found on later Raspberry Pi editions. Please see the separate
port/raspi, too.

0.135.4. Compilation. BTstack’s POSIX-H4 does not have additional dependen-


cies. You can directly run make.

make
227

0.135.5. Running the examples. On start, BTstack prints the path to the packet
log and prints the information on the detected Buetooth Controller.

$ ./ le counter
Packet Log : /tmp/ hci dump . p k l g
BTstack c o u n t e r 0001
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .

Please note that BTstack will increase the baudrate. Before starting again,
you should reset or power-cycle the Bluetooth Controller.

0.136. BTstack Port for POSIX Systems with Atmel ATWILC3000


Controller. This port allows to use the ATWILC3000 connected via UART
with BTstack running on a POSIX host system, see test setup below (which
lacks a proper RESET button).

0.136.1. Compilation. $ make


The Makefile downloads the wilc3000 bt firmware.bin firmware from the GitHub
atwilc3000/firmware repo.

0.136.2. Usage. Just run any of the provided examples, e.g.


$ ./le counter
At start, the firmware file is first uploaded to the ATWILC3000, before BT-
stack start up.
Please note that it configures the ATWILC3000 for a higher baud rate it does
not detect if the firmware has already been downloaded, so you need to reset the
ATWILC3000 before starting an example.
Tested with the official ATWILC3000 SHIELD on OS X.
228
229

0.137. BTstack Port for POSIX Systems with modern Infineon (CYW)
H4 Bluetooth Controller.

0.137.1. Configuration. Newer Infineon Airoc (tm) Controllers like the CYW5557x
series accept PatchRAM upload only in a so-called ‘auto-baud mode’ which is en-
tered by asserting CTS (low) and starting/resetting the controller via BT REG EN.
This port currently only supports the CYW5557x Controllers.

0.137.2. Compilation. BTstack’s posix-h4-bcm port does not have additional de-
pendencies. You can directly run cmake and then your default build system. E.g.
with Ninja:

mkdir b u i l d
cd b u i l d
cmake −G N i n j a . .
ninja

0.137.3. Running the examples. On start, BTstack opens the serial port, which
asserts CTS, and requests you to reset the Controller with a countdown.

$ ./ gatt counter
Packet Log : /tmp/ hci dump . p k l g
Phase 1 : Download f i r m w a r e
P l e a s e r e s e t B l u e t o o t h C o n t r o l l e r , e . g . v i a RESET button . Firmware
download s t a r t s i n :
3
2
1
Firmware download s t a r t e d
Local version information :
− HCI V e r s i o n 0 x000a
− HCI R e v i s i o n 0 x0b73
− LMP V e r s i o n 0 x000a
− LMP S u b v e r s i o n 0 x2257
− Manufacturer 0 x0009
Phase 2 : Main app
BTstack up and r u n n i n g a t 5 5 : 5 6 : 0A: 0A: 7 6 : 9 3
...

0.137.4. ToDo.
• select PatchRAM file based on HCI Read Local Version Information

0.138. BTstack Port for POSIX Systems with Dialog Semiconductor


DA14531 Controller. This port allows to use the DA14531 connected via
UART with BTstack running on a POSIX host system.
Instead of storing the HCI firmware in the OTP, it first downloads the hci 531 active uart 460800.h
firmware from the 6.0.16.1144 SDK, before BTstack starts up.
230

After Power Cycle, please start one of the test applications and press the Reset
button to trigger firmware download.
Please note that it does not detect if the firmware has already been down-
loaded, so you need to Power Cycle the DA14531 before starting an example
again.
Alternatively, after running one of the examples once to upload the firmware,
you can use the regular ‘posix-h4’ port and change the initial UART baud rate
to 460800 as long as you don’t power cycle the dev kit.
For production use, the DA14531 could be power cycled from the main CPU
during startup, e.g. after the call to btstack chipset da145xx download firmware with uart,
or, the HCI firmware could be burned into the OTP.

0.139. Software Setup / Firmware. On the DA14531 USB Development Kit,


the UART is configured via DIP switched. By this, the mapping to the DA14531
GPIOs is fixed. In SDK 6.0.6.1144, the GPIO mapping of RTS and CTS is
flipped. In order to be able to us the same HCI firmware on both dev kits, we’ve
used the following configuration in user perip setup .h

#d e f i n e UART1 TX PORT GPIO PORT 0


#d e f i n e UART1 TX PIN GPIO PIN 0

#d e f i n e UART1 RX PORT GPIO PORT 0


#d e f i n e UART1 RX PIN GPIO PIN 1

#d e f i n e UART1 RTSN PORT GPIO PORT 0


#d e f i n e UART1 RTSN PIN GPIO PIN 4

#d e f i n e UART1 CTSN PORT GPIO PORT 0


#d e f i n e UART1 CTSN PIN GPIO PIN 3

We also increased the UART baudrate to 460800

#define UART1 BAUDRATE UART BAUDRATE 460800

We also disabled the SLEEP mode in user config.h:

s t a t i c const s l e e p s t a t e t a p p d e f a u l t s l e e p m o d e = ARCH SLEEP OFF ;

After compilation with Keil uVision 5, the generated .hex file is copied into bt-
stack/chipset/da145xx as hci 531 active uart 460800 .hex, and then ‘convert hex files”
is used to convert it into a C data array.

0.140. Hardware Setup - Dev Kit Pro. To use the DA14531 Dev Kit Pro
with BTstack, please make the following modifications: - Follow Chapter 4.1 and
Figure 4 in the DA14531 Development Kit Pro Hardware User Manual UM-B-
114 and set SW1 of the 14531 daughter board into position “BUCK” position
231

marked with an “H” on the left side. - configure the dev kit for Full UART
(4-wire) Configuration by adding jumper wires between J1 and J2

0.141. Hardware Setup - Dev Kit USB. To use the Dev Kit USB with
BTstack, please make the following modifications: - Follow Chapter 5.6 in the
DA14531 USB Development Kit Hardware UM-B-125 and set the DIP switches
as described.
# Example Run

$ ./ gatt counter
Packet Log : /tmp/ hci dump . p k l g
Phase 1 : Download f i r m w a r e
Phase 2 : Main app
BTstack c o u n t e r 0001
BTstack up and r u n n i n g on 8 0 :EA:CA: 7 0 : 0 0 : 0 8 .

0.142. BTstack Port for POSIX Systems with Dialog Semiconductor


DA14581 Controller. This port allows to use the DA14581 connected via
UART with BTstack running on a POSIX host system.
It first downloads the hci 581 active uart.hex firmware from the DA14581 HCI 3.110.2.12
SDK packet, before BTstack starts up.
Please note that it does not detect if the firmware has already been down-
loaded, so you need to reset the DA14581 before starting an example.
For production use, the HCI firmware could be flashed into the OTP and the
firmware download could be skipped.
Tested with the official DA14581 Dev Kit on OS X.

0.143. BTstack Port for POSIX Systems with Dialog Semiconductor


DA14585 Controller. This port allows to use the DA14585 connected via
UART with BTstack running on a POSIX host system.
It first downloads the hci 581.hex firmware from the 6.0.8.509 SDK, before
BTstack starts up.
Please note that it does not detect if the firmware has already been down-
loaded, so you need to reset the DA14585 before starting an example.
For production use, the HCI firmware could be flashed into the OTP and the
firmware download could be skipped.
Tested with the official DA14585 Dev Kit Basic on OS X.

0.144. BTstack Port for POSIX Systems with NXP/Marvel H4 Blue-


tooth Controller.

0.144.1. Configuration. Most Bluetooth Bluetooth Controllers connected via UAR-


T/H4 require some special configuration, e.g. to set the UART baud rate, and/or
require firmware patches during startup. In this port, we’ve show how a NX-
P/Marvell Controller can be configured for use with BTstack. It’s unclear if
the required firmware file for older Controllers, e.g. 88W8997, can be detected
during the firmware upload. This port selects the firmware for NXP 88W8997.
232

For newer Controllers, e.g. IW416 or IW612, the firmware can be selected auto-
matically.

0.144.2. Compilation. BTstack’s posix-h4-nxp port does not have additional de-
pendencies. You can directly run cmake and then your default build system.
E.g. with Ninja:

mkdir b u i l d
cd b u i l d
cmake −G N i n j a . .
ninja

0.144.3. Running the examples. Please reset the Controller first. On start, BT-
stack prints the path to the packet log.

$ ./ gatt counter
Packet Log : /tmp/ hci dump . p k l g
BTstack c o u n t e r 0001
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .

0.144.4. Issues.
• NXP 88W8997 does not support SCO Flow Control which causes glitches
when sending audio

0.144.5. ToDo.
• increase baud rate for firmware upload
• skip firmware upload if firmware already present
• increase baud rate for application

0.145. BTstack Port for POSIX Systems with Zephyr-based Controller.


The main difference to the regular posix-h4 port is that that the Zephyr Con-
troller uses 1000000 as baud rate. In addition, the port defaults to use the fixed
static address stored during production.

0.145.1. Prepare Zephyr Controller. Please follow this blog post about how to
compile and flash samples/bluetooth/hci uart to a connected nRF5 dev kit.
In short: you need to install an arm-none-eabi gcc toolchain and the nRF5x
Command Line Tools incl. the J-Link drivers, checkout the Zephyr project, and
flash an example project onto the chipset:
• Install J-Link Software and documentation pack.
• Get nrfjprog as part of the nRFx-Command-Line-Tools. Click on Down-
loads tab on the top and look for your OS.
• Checkout Zephyr and install toolchain. We recommend using the arm-
non-eabi gcc binaries instead of compiling it yourself. At least on OS X,
this failed for us.
233

• In samples/bluetooth/hci uart, compile the firmware for nRF52 Dev Kit


$ make BOARD=nrf52 pca10040
• Upload the firmware
$ make flash
• For the nRF51 Dev Kit, use make BOARD=nrf51 pca10028.

0.145.2. Configure serial port. To set the serial port of your Zephyr Controller,
you can either update config.device name in main.c or always start the examples
with the −u /path/to/serialport option.

0.145.3. Compile Examples.

$ make

0.145.4. Run example. Just run any of the created binaries, e.g.

$ ./ le counter

The packet log will be written to /tmp/hci dump.pklg

0.146. BTstack Port for QT with H4 Bluetooth Controller. Uses libusb


Library on macOS and Linux and WinUSB on Windows. Windows is supported
with the MinGW Kit.
Windows with MSVC or Embedded (bare metal) platforms not supported yet.

0.146.1. Configuration. Most Bluetooth Bluetooth Controllers connected via UAR-


T/H4 require some special configuration, e.g. to set the UART baud rate, and/or
require firmware patches during startup. In this port, we’ve tried to do most of
these automatically based on information gathered from the Bluetooth Con-
troller. Here’s some Controller specific details:

0.146.2. TI CC256x. The CC2564x needs the correct init script to start up. The
Makfile already has entries for most silicon revisions:
• CC2560: bluetooth init cc2564 2.14.c
• CC2564B: bluetooth init cc2564B 1.8 BT Spec 4.1.c
• CC2564C: bluetooth init cc2564C 1.5.c
Please pick the correct one. The main.c verifies that the correct script is
loaded, but the init script is linked to the executable.

0.146.3. Broadcom BCM/CYW 43430. The correct firmware file needs to be


provided in the current working directory. The Makefile downloads the one for
the BCM43430 e.g. found on later Raspberry Pi editions. Please see the separate
port/raspi, too.
234

0.146.4. Compilation. On all platforms, you’ll need Qt Python 3 installed. On


macOS/Linux libusb-1.0 or higher is required, too.
When everything is ready, you can open the provided CMakelists.txt project
in Qt Creator and run any of the provided examples. See Qt documentation on
how to compile on the command line or with other IDEs
0.146.5. Running the examples. BTstack’s HCI USB transport will try to find a
suitable Bluetooth module and use it.
On start, BTstack will try to find a suitable Bluetooth module. It will also
print the path to the packet log as well as the USB path.

$ ./ le counter
Packet Log : /tmp/ hci dump . p k l g
BTstack c o u n t e r 0001
USB Path : 06
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .

0.147. BTstack Port for QT with USB Bluetooth Dongle. Uses libusb
Library on macOS and Linux and WinUSB on Windows. Windows is supported
with the MinGW Kit.
Windows with MSVC or Embedded (bare metal) platforms not supported yet.
0.147.1. Compilation. On all platforms, you’ll need Qt Python 3 installed. On
macOS/Linux libusb-1.0 or higher is required, too.
When everything is ready, you can open the provided CMakelists.txt project
in Qt Creator and run any of the provided examples. See Qt documentation on
how to compile on the command line or with other IDEs
0.147.2. Environment Setup.
0.147.3. Windows. To allow WinUSB to access an USB Bluetooth dongle, you
need to install a special device driver to make it accessible to user space processes.
It works like this:
• Download Zadig
• Start Zadig
• Select Options -> “List all devices”
• Select USB Bluetooth dongle in the big pull down list
• Select WinUSB in the right pull down list
• Select “Replace Driver”
0.147.4. Linux. On Linux, the USB Bluetooth dongle is usually not accessible
to a regular user. You can either: - run the examples as root - add a udev rule
for your dongle to extend access rights to user processes
To add an udev rule, please create /etc/udev/rules.d/btstack.rules and add this

# Match a l l d e v i c e s from CSR


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 a12 ” , MODE=” 0666 ”
235

# Match DeLOCK B l u e t o o t h 4 . 0 d o n g l e
SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 a5c ” , ATTRS{ d e v i c e}==” 21 e8 ” ,
MODE=” 0666 ”

# Match Asus BT400


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 0 b05 ” , ATTRS{ d e v i c e}==” 17 cb ” ,
MODE=” 0666 ”

# Match L a i r d BT860 / Cypress Semiconductor CYW20704A2


SUBSYSTEM==” usb ” , ATTRS{ idVendor}==” 04 b4” , ATTRS{ d e v i c e}==” f 9 0 1 ” ,
MODE=” 0666 ”

0.147.5. macOS. On macOS, the OS will try to use a plugged-in Bluetooth Con-
troller if one is available. It’s best to to tell the OS to always use the internal
Bluetooth Contoller.
For this, execute:

sudo nvram b l u e t o o t h H o s t C o n t r o l l e r S w i t c h B e h a v i o r=n e v e r

and then reboot to activate the change.


Note: if you get this error,

l i b u s b : warning [ darwin open ] USBDeviceOpen : a n o t h e r p r o c e s s has


d e v i c e opened f o r e x c l u s i v e a c c e s s
l i b u s b : e r r o r [ d a r w i n r e s e t d e v i c e ] R e s e t D e v i c e : d e v i c e not opened
for e x c l u s i v e a c c e s s

and you didn’t start another instance and you didn’t assign the USB Controller
to a virtual machine, macOS uses the plugged-in Bluetooth Controller. Please
configure NVRAM as explained and try again after a reboot.

0.147.6. Running the examples. BTstack’s HCI USB transport will try to find a
suitable Bluetooth module and use it.
On start, BTstack will try to find a suitable Bluetooth module. It will also
print the path to the packet log as well as the USB path.

$ ./ le counter
Packet Log : /tmp/ hci dump . p k l g
BTstack c o u n t e r 0001
USB Path : 06
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .

If you want to run multiple examples at the same time, it helps to fix the path
to the used Bluetooth module by passing -u usb-path to the executable.
236

Example running le streamer and le streamer client in two processes, using


Bluetooth dongles at USB path 6 and 4:

. / l e s t r e a m e r −u 6
S p e c i f i e d USB Path : 06
Packet Log : /tmp/ hci dump 6 . p k l g
USB Path : 06
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .
To s t a r t t h e s t r e a m i n g , p l e a s e run t h e l e s t r e a m e r c l i e n t example on
o t h e r d e v i c e , o r u s e some GATT E x p l o r e r , e . g . LightBlue ,
BLExplr .

$ . / l e s t r e a m e r c l i e n t −u 4
S p e c i f i e d USB Path : 04
Packet Log : /tmp/ hci dump 4 . p k l g
USB Path : 04
BTstack up and r u n n i n g on 0 0 : 1A: 7D:DA: 7 1 : 1 3 .
Start scanning !

0.148. BTstack Port for Raspberry Pi 3 with BCM4343 Bluetooth/Wifi


Controller. Tested with Raspberry Pi 3 Model B V1.2, Raspberry Pi 3 Model
B+, and Raspberry Pi Zero W V1.1.
With minor fixes, the port should also work with older Raspberry Pi models
that use the RedBear pHAT. See TODO at the end.

0.148.1. Raspberry Pi 3 / Zero W Setup. There are various options for setting
up the Raspberry Pi, have a look at the Internet. Here’s what we did:

0.148.2. Install Raspian Stretch Lite:


• Insert empty SD Card
• Download Raspian Stretch Lite from https://www.raspberrypi.org/downloads/raspbian/
• Install Etcher from https://etcher.io
• Run Etcher:
– Select the image you’ve download before
– Select your SD card
– Flash!

0.148.3. Configure Wifi. Create the file wpa supplicant.conf in the root folder of
the SD Card with your Wifi credentials:

c t r l i n t e r f a c e=DIR=/var / run / w p a s u p p l i c a n t GROUP=netdev


network={
s s i d=”YOUR NETWORK NAME”
psk=”YOUR PASSWORD”
key mgmt=WPA−PSK
}
237

Alternatively, just plug-it in via Ethernet - unless you have a Raspberry Pi


Zero W.

0.148.4. Enable SSH. Create an empty file called ‘ssh’ in the root folder of the
SD Card to enable SSH.

0.148.5. Boot. If everything was setup correctly, it should now boot up and join
your Wifi network. You can reach it via mDSN as ‘raspberrypi.local’ and log in
with user: pi, password: raspberry.

0.148.6. Disable bluez. By default, bluez will start up using the the BCM4343.
To make it available to BTstack, you can disable its system services:

$ sudo s y s t e m c t l d i s a b l e h c i u a r t
$ sudo s y s t e m c t l d i s a b l e b t h e l p e r
$ sudo s y s t e m c t l d i s a b l e b l u e t o o t h

and if you don’t want to restart, you can stop them right away. Otherwise,
please reboot here.

$ sudo s y s t e m c t l s t o p h c i u a r t
$ sudo s y s t e m c t l s t o p b t h e l p e r
$ sudo s y s t e m c t l s t o p b l u e t o o t h

If needed, they can be re-enabled later as well.

0.148.7. Compilation. The Makefile assumes cross-compilation using the regu-


lar GCC Cross Toolchain for gnueabihf: arm-linux-gnueabihf-gcc. This should
be available in your package manager. Read on for a heavy, but easy-to-use
approach.

0.148.8. Compile using Docker. For non-Linux users, we recommend to use a


Raspberry Pi Cross-Compiler in a Docker Container. Please follow the installa-
tion instructions in the README.
Then, setup a shared folder in Docker that contains the BTstack repository.
Now, go to the BTstack repository and ‘switch’ to the Raspberry Pi Cross-
Compiler container:

$ rpxc bash

The default images doesn’t have a Python installation, so we manually install


it:

$ sudo apt−g e t i n s t a l l python


238

Change to the port/raspi folder inside the BTstack repo:

$ cd b t s t a c k / p o r t / r a s p i

and compile as usual:

$ make

For regular use, it makes sense to add Python permanently to the Docker
container. See documentation at GitHub.
0.148.9. Running the examples. Copy one of the examples to the Rasperry Pi
and just run them. BTstack will power cycle the Bluetooth Controller on models
without hardware flowcontrol, i.e., Pi 3 A/B. With flowcontrol, e.g Pi Zero W
and Pi 3 A+/B+, the firmware will only uploaded on first start.

pi@raspberrypi :˜ $ ./ le counter
Packet Log : /tmp/ hci dump . p k l g
Hardware UART w i t h o u t f l o w c o n t r o l
Phase 1 : Download f i r m w a r e
Phase 2 : Main app
BTstack c o u n t e r 0001
BTstack up and r u n n i n g a t B8 : 2 7 : EB : 2 7 : AF: 5 6

UART UART HCI


Model Bluetooth Controller Type Flowcontrol
BT REG
Transport
EN Baudrate
Older None
Pi 3 Model CYW43438 Hardware
No 128 H5 921600
A, Model
B
Pi 3 Model CYW43455 Hardware
Yes 129 H4 921600
A+, Model (See (See
B+ 1) 2)
Pi Zero W CYW43438 Hardware
Yes 45 H4 921600

0.148.10. Bluetooth Hardware Overview.


1. Model A+/B+ have BT REG EN AND WL REG EN on the same (vir-
tual) GPIO 129. A Bluetooth Controller power cycle also shuts down
Wifi (temporarily). BTstack avoids a power cycle on A+/B+.
2. Model A+/B+ support 3 mbps baudrate. Not enabled/activated yet.

0.148.11. TODO.
239

• Raspberry Pi Zero W: Check if higher baud rate can be used, 3 mbps


does not work.
• Raspberry + RedBear IoT pHAT (AP6212A = BCM4343) port: IoT
pHAT need to get detected and the UART configured appropriately.
0.149. BTstack Port for Renesas Eval Kit EK-RA6M4 with DA14531.
This port uses the Renesas EK-RA6M4 and a Renesas DA14531 Controller on
the MikroeE BLE Tiny Click board
Renesas e2 Studio (Eclise-based) was used with the FSP HAL and without an
RTOS to generate project sources. Then, a new CMake buildfile was created to
allow for cross-platform development and compilation of all examples. For easy
debugging, Ozone project files are generated as well.
0.149.1. Hardware.
0.149.2. Renesas Eval Kit EK-RA6M4:
• The RA6 contains a build in J-Link programmer which supports debut
output via SEGGER RTT.
• It uses the MikroBus port for the DA1451

MikroBus MCU Function


J21/2 P115 RESET (active high)
P21/3 P205 RTS
J21/4 P204 CTS
J22/4 P613 TX
J22/3 P614 RX

• UART RTS: Manual RTS control in UART callback handler. MikroBus


slot with UART 7 does not have RTSCTS7 on the pin used by BLE Tiny
Click module.
• BSP

// 0 x1000 main s t a c k
#define BSP CFG STACK MAIN BYTES ( 0 x1000 )

// p r i n t f a l l o c a t e s memory from t h e heap


#define BSP CFG HEAP BYTES ( 0 x800 )

0.149.3. Renesas DA14531 Module on MikroE BLE Tiny Click board with.
• The board comes with some demo application and needs to be pro-
grammed with an HCI firmware to use it with a regular Bluetooth stack.
• Firmware details:
– Keil uVision project DA145xx SDK/x.x.xx.xxxx/projects/target apps/hci
on Windows
240

// C o n f i g : u s e r p e r i p h s e t u p . h
#define UART1 TX PORT GPIO PORT 0
#define UART1 TX PIN GPIO PIN 6
#define UART1 RX PORT GPIO PORT 0
#define UART1 RX PIN GPIO PIN 5
#define UART1 RTSN PORT GPIO PORT 0
#define UART1 RTSN PIN GPIO PIN 7
#define UART1 CTSN PORT GPIO PORT 0
#define UART1 CTSN PIN GPIO PIN 8
#define UART1 BAUDRATE UART BAUDRATE 460800
#define UART1 DATABITS UART DATABITS 8

// C o n f i g : u s e r c o n f i g . h
s t a t i c const s l e e p s t a t e t a p p d e f a u l t s l e e p m o d e = ARCH SLEEP OFF ;

• Firmware installation:
– Connect GND (pin 5) and VCC (pin 6) with jumper wires to the
RA6 dev board.
– Connect it with a ARM-Cortex 10-pin connector to a J-Link device
– Start SmartBond Flash Programmer
– The Programmer should auto-detect the DA14531 via the J-Link.
– Select firmware/hci 531 rx05 tx06 rts07 cts08 468000.hex as firmware file
and click Program
0.149.4. Software. The port provides a CMake project file that uses the installed
Arm Gnu Toolchain.
• Install Arm GNU Toolchain
• Install CMake
• Install Ninja
• To compile, go to the port folder:
cd btstack/port/renesas−ek−ra6me4a−da14531
• Create a build folder and go to build folder
mkdir build && cd build
• Create Ninja build files
cmake −G Ninja ..
• Build all examples
ninja
This will build all examples as .elf files as well as .jdebug Ozone debug project
files Alternatively, the CMakeLists.txt can be used to compile using Make (cmake
−G ”Unix Makefiles”.. and make) or or use the project in most modern IDEs (CLion,
Visual Studio, Visual Studio Code, . . . )
0.149.5. Run Example Project using Ozone. After building the examples, the
generated .elf file can be used with Ozone. Start Ozone and open the provided
.jdebug file. The debug output is readily available in the RTT Terminal.
0.149.6. Debug output. All debug output is send via SEGGER RTT.
In src/btstack config.h resp. in example/btstack config.h of the generated
projects.
241

Also, the full packet log with addtional log information can be enabled in
src/hal entry.c by uncommenting the hci dump init(. . . ) call.
The console output can then be converted into .pklg files by running tool/cre-
ate packet log.py. The .pklg file can be analyzed with the macOS X PacketLogger
or WireShark.

0.149.7. Setup.

0.149.8. Updating HAL Configuration.


• Start Renesas RA v3.7.0/e2-studio on Windows and open e2−project
• Open configuration .xml to get to “FSP Configuration” perspective
– to add modules, click “New Stack”
– module is configured in “Properties” view (usually below next to
‘Problems’ etc)
• Press button re-generates sources
• Copy folder e2−project into this port
• Check diff for unexpected changes
• If needed:
– Update CMakeLists.txt to add new modules
– Add code to enable (‘open’) new module in R BSP WarmStart of port
/hal entry.c

0.150. BTstack Port for Renesas Target Board TB-S1JA with CC256x.
This port uses the Renesas TB-S1JA with TI’s CC256XEM ST Adapter Kit that
allows to plug in a CC256xB or CC256xC Bluetooth module. Renesas e2 Studio
(Eclise-based) was used with the SSP HAL and without an RTOS. For easy
debugging, Ozone project files are generated as well.

0.150.1. Hardware. Renesas Target Board TB-S1JA: - TB-S1JA Target Board


Kit
• CC2564B Bluetooth Controller:
1. The best option is to get it as a BoostPack
– Info: BOOST-CC2564MODA: http://www.ti.com/tool/BOOST-
CC2564MODA
2. Alternatively, get the evaluation module together with the EM Wire-
less Booster pack and a 32.768 kHz oscillator
– EM Wireless Booster Pack:
∗ Info
∗ User Guide
– CC256x Bluetooth module:
∗ CC2564B Dual-mode Bluetooth Controller Evaluation Module
∗ CC2564C Dual-mode Bluetooth Controller Evaluation Module
∗ The module with the older CC2564B is around USD 20, while
the one with the new CC2564C costs around USD 60
The projects are configured for the CC2564C. When using the CC2564B, blue-
tooth init cc2564B 1.8 BT Spec 4.1.c should be used as cc256x init script. You
can update this in the create examples.py script.
242

Renesas Eval Kit EK-RA6M4 with DA14531


243

Connct the Target Board to the TI Boosterpack, see Booster Pack Pinout:
http://www.ti.com/ww/en/launchpad/dl/boosterpack-pinout-v2.pdf

J2 PIN S1JA PORT S1JA Signal Boosterpack


2 P301 RXD0 3 (LP1)
4 P302 TXD0 4 (LP1)
6 P304 CTS0 36 (LP2)
8 P303 RTS0 37 (LP2)
10 VCC VCC 1 (LP1)
12 VSS GND 20 (LP2)
14 P112 nShutdown 19 (LP1)

0.150.2. Software. Generate example projects

$ python c r e a t e e x a m p l e s . py

This will generate an e2 Studio project for each example.


0.150.3. Excluded Examples. The a2dp examples (a2dp source demo and a2dp sink demo)
were disabled as the C open-source SBC codec with compile option -O2 wasn’t
fast enough to provide real-time encoding/decoding.
0.150.4. Build, Flash And Run The Examples in e2 Studio. Open the e2 Studio
project and press the ‘Debug’ button. Debug output is only available via SEG-
GER RTT. You can run SEGGER’s JLinkRTTViewer or use Ozone as described
below.
0.150.5. Run Example Project using Ozone. After compiling the project with e2
Studio, the genereated .elf file can be used with Ozone (also e.g. on macOS). In
Ozone, the debug output is readily available in the terminal. A .jdebug file is
provided in the project folder.
0.150.6. Debug output. All debug output is send via SEGGER RTT.
In src/btstack config.h resp. in example/btstack config.h of the generated
projects, additional debug information can be enabled by uncommenting EN-
ABLE LOG INFO.
Also, the full packet log can be enabled in src/hal entry.c by uncommenting
the hci dump init(. . . ) call. The console output can then be converted into .pklg
files by running tool/create packet log.py. The .pklg file can be analyzed with
the macOS X PacketLogger or WireShark.
0.150.7. GATT Database. In BTstack, the GATT Database is defined via the
.gatt file in the example folder. The create examples.py script converts the .gatt
files into a corresponding .h for the project. After updating a .gatt file, the
.h can be updated manually by running the provided update gatt db.sh or up-
date gatt db.bat scripts.
Note: In theory, this can be integrated into the e2 Studio/Eclipse project.
244

0.150.8. Notes.
• HCI UART is set to 2 mbps. Using 3 or 4 mbps causes hang during
startup

0.150.9. Nice to have.


• Allow compilation using Makefile/CMake without the e2 Studio, e.g. on
the Mac.

0.151. BTstack Port for SAMV71 Ultra Xplained with ATWILC3000


SHIELD. This port uses the SAMV71 Ultra Xplained Ultra evaluation kit with
an ATWILC3000 SHIELD. The code is based on the Advanced Software Frame-
work (ASF) (previously know as Atmel Software Framework). It uses the GCC
Makefiles provided by the ASF. OpenOCD is used to upload the firmware to the
device.

0.151.1. Create Example Projects. To create all example projects in the example
folder, you can run:

$ make

0.151.2. Compile Example. In one of the example folders:

$ make

To upload the firmware:

$ make f l a s h

You need to connect the the Debug USB to your computer.

0.151.3. Debug output. printf is routed to USART1, which is connected to the


virtual serial port. To get the console output, open a terminal at 115200.
In btstack config.h, additional debug information can be enabled by uncom-
menting ENABLE LOG INFO.
Also, the full packet log can be enabled in the main() function on main.c by
uncommenting the hci dump init(..) line. The console output can then be con-
verted into .pklg files for OS X PacketLogger or WireShark by running tool/cre-
ate packet log.py

0.151.4. TODOs.

− Implement h a l f l a s h s e c t o r . h t o p e r s i s t l i n k k e y s
245

0.151.5. Issues.

− B l u e t o o t h UART d r i v e r u s e s per−byte i n t e r r u p t s and doesn ’ t work


r e l i a b l e a t h i g h e r baud r a t e s ( 9 2 1 6 0 0 seems ok , 2 mbps a l r e a d y
c a u s e s problems ) .
− An o l d e r XDMA−based i m p l e m e n t a t i o n o n l y s e n d s 0 x00 b y t e s o v e r t h e
UART. I t might be b e t t e r t o j u s t r e a d incoming data i n t o two
b u f f e r s , ( e . g . u s i n g a two e l e m e n t l i n k e d l i s t with XDMA) , and
r a i s i n g RTS when one b u f f e r i s f u l l .

0.152. BTstack Port for STM32 F4 Discovery Board with CC256x. This
port uses the STM32 F4 Discovery Board with TI’s CC256XEM ST Adapter Kit
that allows to plug in a CC256xB or CC256xC Bluetooth module. STCubeMX
was used to provide the HAL, initialize the device, and the Makefile. For easy
development, Ozone project files are generated as well.
0.152.1. Hardware. STM32 Development kit and adapter for CC256x module: -
STM32 F4 Discovery Board - CC256xEM Bluetooth Adatper Kit for ST
CC256x Bluetooth module: - CC2564B Dual-mode Bluetooth Controller Eval-
uation Module - CC2564C Dual-mode Bluetooth Controller Evaluation Module
The module with the older CC2564B is around USD 20, while the one with
the new CC2564C costs around USD 60. The projects are configured for the
CC2564C. When using the CC2564B, bluetooth init cc2564B 1.8 BT Spec 4.1.c
should be used as cc256x init script.
0.152.2. Software. To build all examples, run make

$ make

All examples and the .jedbug Ozone project files are placed in the ‘build’
folder.
0.152.3. Flash And Run The Examples. The Makefile builds different versions: -
example.elf: .elf file with all debug information - example.bin: .bin file that can
be used for flashing
There are different options to flash and debug the F4 Discovery board. The F4
Discovery boards comes with an on-board ST-Link programmer and debugger.
As an alternative, the ST-Link programmer can be replaced by an SEGGER J-
Link OB. Finally, the STM32 can be programmed with any ARM Cortex JTAG
or SWD programmer via the SWD jumper.
0.152.4. Run Example Project using Ozone. When using an external J-Link pro-
grammer or after installing J-Link OB on the F4 Discovery board, you can flash
and debug using the cross-platform SEGGER Ozone Debugger. It is included in
some J-Link programmers or can be used for free for evaluation usage.
Just start Ozone and open the .jdebug file in the build folder. When compiled
with “ENABLE SEGGER RTT”, the debug output shows up in the Terminal
window of Ozone.
246

0.152.5. Debug output. All debug output can be either send via SEGGER RTT
or via USART2. To get the console from USART2, connect PA2 (USART2
TX) of the Discovery board to an USB-2-UART adapter and open a terminal at
115200.
In src/btstack config.h resp. in example/btstack config.h of the generated
projects, additional debug information can be enabled by uncommenting EN-
ABLE LOG INFO.
Also, the full packet log can be enabled in src/port.c resp. btstack/port/stm32-
f4discovery-cc256x/src/port.c by uncommenting the hci dump init(..) line. The
console output can then be converted into .pklg files for OS X PacketLogger or
WireShark by running tool/create packet log.py

0.152.6. GATT Database. In BTstack, the GATT Database is defined via the
.gatt file in the example folder. The Makefile contains rules to update the .h file
when the .gatt was modified.

0.152.7. Maintainer Notes - Updating The Port. The Audio BSP is from the
STM32F4Cube V1.16 firmware and not generated from STM32CubeMX. To up-
date the HAL, run ‘generate code’ in CubeMX. After that, make sure to re-apply
the patches to the UART and check if the hal config was changed.

0.153. BTstack Port for STM32 F4 Discovery Board with USB Blue-
tooth Controller. This port uses the STM32 F4 Discovery Board with an USB
Bluetooth Controller plugged into its USB UTG port. See blog post for details.
STCubeMX was used to provide the HAL, initialize the device, and the Make-
file. For easy development, Ozone project files are generated as well.

0.153.1. Hardware. STM32 Development kit with USB OTG adapter and USB
CSR8510 Bluetooth Controller - STM32 F4 Discovery Board

0.153.2. Software. To build all examples, run make

$ make

All examples and the .jedbug Ozone project files are placed in the ‘build’
folder.

0.153.3. Flash And Run The Examples. The Makefile builds different versions: -
example.elf: .elf file with all debug information - example.bin: .bin file that can
be used for flashing
There are different options to flash and debug the F4 Discovery board. The F4
Discovery boards comes with an on-board ST-Link programmer and debugger.
As an alternative, the ST-Link programmer can be replaced by an SEGGER J-
Link OB. Finally, the STM32 can be programmed with any ARM Cortex JTAG
or SWD programmer via the SWD jumper.
247

0.153.4. Run Example Project using Ozone. When using an external J-Link pro-
grammer or after installing J-Link OB on the F4 Discovery board, you can flash
and debug using the cross-platform SEGGER Ozone Debugger. It is included in
some J-Link programmers or can be used for free for evaluation usage.
Just start Ozone and open the .jdebug file in the build folder. When compiled
with “ENABLE SEGGER RTT”, the debug output shows up in the Terminal
window of Ozone.

0.153.5. Debug output. The debug output can send via SEGGER RTT.
In src/btstack config.h resp. in example/btstack config.h of the generated
projects, additional debug information can be enabled by uncommenting EN-
ABLE LOG INFO.
Also, the full packet log can be enabled in src/port.c resp. btstack/port/stm32-
f4discovery-cc256x/src/port.c by uncommenting the hci dump init(..) line. The
console output can then be converted into .pklg files for OS X PacketLogger or
WireShark by running tool/create packet log.py

0.153.6. GATT Database. In BTstack, the GATT Database is defined via the
.gatt file in the example folder. The Makefile contains rules to update the .h file
when the .gatt was modified.

0.153.7. Maintainer Notes - Updating The Port. The Audio BSP is from the
STM32F4Cube V1.16 firmware and not generated from STM32CubeMX. To up-
date the HAL, run ‘generate code’ in CubeMX. After that, make sure to re-apply
the patches to the UART and check if the hal config was changed.

0.154. BTstack Port for STM32 Nucleo L073RZ Board with EM9304
Controller. This port uses the STM32 Nucleo-L073RZ Board with EM’s EM9304
Shield.
The STM32CubeMX tool was used to provide the HAL, initialize the device,
and create a basic Makefile. The Makefile has been exteneded to compile all
BTstack LE examples. For easy development, Ozone project files are generated
as well.

0.154.1. Hardware. In this port, the EM9304 is conencted via the SPI1 interface
and configured for 8 Mhz. Datasheet for the EM9304
It assumes that the EM9304 does not contain any patches and uploads the
latest Metapatch during startup.

0.154.2. Software. To build all examples, run make

$ make

All examples and the .jedbug Ozone project files are placed in the ‘build’
folder.
248

0.154.3. Flash And Run The Examples. The Makefile builds different versions: -
example.elf: .elf file with all debug information - example.bin: .bin file that can
be used for flashing
There are different options to flash and debug the F4 Discovery board. The F4
Discovery boards comes with an on-board ST-Link programmer and debugger.
As an alternative, the ST-Link programmer can be replaced by an SEGGER J-
Link OB. Finally, the STM32 can be programmed with any ARM Cortex JTAG
or SWD programmer via the SWD jumper.

0.154.4. Run Example Project using Ozone. When using an external J-Link pro-
grammer or after installing J-Link OB on the F4 Discovery board, you can flash
and debug using the cross-platform SEGGER Ozone Debugger. It is included in
some J-Link programmers or can be used for free for evaluation usage.
Just start Ozone and open the .jdebug file in the build folder. When compiled
with “ENABLE SEGGER RTT”, the debug output shows up in the Terminal
window of Ozone.

0.154.5. Debug output. All debug output can be either send via SEGGER RTT
or via USART2. To get the console from USART2, connect PA2 (USART2
TX) of the Discovery board to an USB-2-UART adapter and open a terminal at
115200.
In src/btstack config.h resp. in example/btstack config.h of the generated
projects, additional debug information can be enabled by uncommenting EN-
ABLE LOG INFO.
Also, the full packet log can be enabled in src/port.c by uncommenting the
hci dump init(..) line. The console output can then be converted into .pklg files
for OS X PacketLogger or WireShark by running tool/create packet log.py

0.154.6. GATT Database. In BTstack, the GATT Database is defined via the
.gatt file in the example folder. During the build, the .gatt file is converted into
a .h file with a binary representation of the GATT Database and useful defines
for the application.
249
250
251

0.155. BTstack Port with Cinnamon for Semtech SX1280 Controller on


Miromico FMLR-80. Cinnamon is BlueKitchen’s minimal, yet robust Con-
troller/Link Layer implementation for use with BTstack.
In contrast to common Link Layer implementations, our focus is on a ro-
bust and compact implementation for production use, where code size matters
(e.g. current code size about 8 kB).
0.155.1. Overview. This port targets the Semtech SX1280 radio controller. The
Host Stack and the Controller (incl. Link Layer) run on a STM32 MCU, with
the SX1280 connected via SPI.
It uses the SX1280 C-Driver from Semtech to communicate with the SX1280.
The main modification was to the SPI driver that uses DMA for full packets.
0.155.2. Status. Tested with the Miromico FMLR-80-P-STL4E module and our
SX1280 Shield - see (port/stm32-l476rg-nucleo-sx1280). On the FMLR-80-P-
STL4E module, the 52 Mhz clock for the SX1280 is controlled by the MCU.
SEGGER RTT is used for debug output, so a Segger J-Link programmer is
required.
Uses 32.768 kHz crytstal as LSE for timing
Support for Broadcast and Peripheral roles.
The Makefile project compiles gatt counter, gatt streamer server, hog mouse
and hog keyboard examples.
0.155.3. Limitation.
0.155.4. Advertising State:
• Only Connectable Advertising supported
• Only fixed public BD ADDR of 33:33:33:33:33:33 is used
0.155.5. Connection State:
• Encryption not implemented
• Some LL PDUs not supported
0.155.6. Central Role:
• Not implemented
0.155.7. Observer Role:
• Not implemented
0.155.8. Low power mode - basically not implemented:
• MCU does not sleep
• SPI could be disabled during sleep
• 1 ms SysTick is used for host stack although 16-bit tick time is provided
by LPTIM1 based on 32768 Hz LSE.
0.155.9. Getting Started. For the FMLR-80-P-STL4E module, just run make.
You can upload the EXAMPLE.elf file created in build folder, e.g. with Ozone
using the provided EXAMPLE.jdebug, and run it.
0.155.10. TODO.
252

0.155.11. General.
• indicate random address in advertising pdus
• allow to set random BD ADDR via HCI command and use in Advertise-
ments
• support other regular adv types
• handle Encryption
0.155.12. Low Power.
• enter STANDY RC mode when idle
• implement MCU sleep (if next wakeup isn’t immediate)
• sleep after connection request until first packet from Central
• replace SysTick with tick counter based on LPTIM1
• disable SPI on MCU sleep
0.156. BTstack Port with Cinnamon for Semtech SX1280 Controller on
STM32L476 Nucleo. Cinnamon is BlueKitchen’s minimal, yet robust Con-
troller/Link Layer implementation for use with BTstack.
In contrast to common Link Layer implementations, our focus is on a ro-
bust and compact implementation for production use, where code size matters
(e.g. current code size about 8 kB).
0.156.1. Overview. This port targets the Semtech SX1280 radio controller. The
Host Stack and the Controller (incl. Link Layer) run on a STM32 MCU, with
the SX1280 connected via SPI.
It uses the SX1280 C-Driver from Semtech to communicate with the SX1280.
The main modification was to the SPI driver that uses DMA for full packets.
0.156.2. Status. Tested with theMiromico FMLR-80-P-STL4E module (see port/stm32-
l451-miromico-sx1280) and the STM32 L476 Nucleo dev kit with our SX1280
Shield.
SEGGER RTT is used for debug output, so a Segger J-Link programmer is
required, but the on-board ST-Link programmer and debugger can be replaced
by an SEGGER J-Link OB.
Uses 32.768 kHz crytstal as LSE for timing
Support for Broadcast and Peripheral roles.
The Makefile project compiles gatt counter, gatt streamer server, hog mouse
and hog keyboard examples.
0.156.3. Limitation.
0.156.4. Advertising State:
• Only Connectable Advertising supported
• Only fixed public BD ADDR of 33:33:33:33:33:33 is used
0.156.5. Connection State:
• Encryption not implemented
• Some LL PDUs not supported
0.156.6. Central Role:
• Not implemented
253

0.156.7. Observer Role:

• Not implemented

0.156.8. Low power mode - basically not implemented:

• MCU does not sleep


• SPI could be disabled during sleep
• 1 ms SysTick is used for host stack although 16-bit tick time is provided
by LPTIM1 based on 32768 Hz LSE.

0.156.9. Getting Started. Just run make. You can upload the EXAMPLE.elf file
created in build folder, e.g. with Ozone using the provided EXAMPLE.jdebug,
and run it.

0.156.10. TODO.

0.156.11. General.

• indicate random address in advertising pdus


• allow to set random BD ADDR via HCI command and use in Advertise-
ments
• support other regular adv types
• handle Encryption

0.156.12. Low Power.

• enter STANDY RC mode when idle


• implement MCU sleep (if next wakeup isn’t immediate)
• sleep after connection request until first packet from Central
• replace SysTick with tick counter based on LPTIM1
• disable SPI on MCU sleep
254
255

0.157. BTstack Port for STM32WB55 Nucleo Boards using FreeRTOS.


This port supports the Nucleo68 and the USB dongle of the P-NUCLEO-WB55
kit. Both have 1 MB of Flash memory.
The STM32Cube FW WB V1.3.0 provides the HAL and WPAN, and initial-
izes the device and the initial Makefile. For easy development, Ozone project
files are generated as well.

0.157.1. Hardware. In this port, the Nucelo68 or the USB Dongle from the P-
NUCLEO-WB55 can be used.
Last test was done using FUS v1.2 and HCI BLE Firmware v1.13 on Nucleo68
See STM32Cube FW WB V1.13.0/Projects/STM32WB Copro Wireless Binaries/Release Notes.ht
for firmware install instructions.
Note: Segger RTT is currently not really usable. When sleep modes ared
disabled for debuggin (see port thread()) RTT works, but the output buffer
quickly overflows. In Block mode, radio stops working.

0.157.2. Nucleo68. The debug output is sent over USART1 and is available via
the ST-Link v2.

0.157.3. USB Dongle. To flash the dongle, SWD can be used via the lower 6 pins
on CN1: - 3V3 - PB3 - SWO (semi hosting not used) - PA14 - SCLK - PA13 -
SWDIO - NRST - GND
The debug output is sent over USART1 and is available via PB6.

0.157.4. Software. FreeRTOS V10.2.0 is used to run stack, you can get this ex-
ample version by checking out official repo:

$ cd Middlewares
$ g i t submodule add h t t p s : // g i t h u b . com/aws/amazon−f r e e r t o s . g i t
$ g i t submodule update
& cd amazon−f r e e r t o s && g i t c h e c k o u t v1 . 4 . 8

Or by specifying path to FreeRTOS

$ make FREERTOS ROOT=p a t h t o f r e e r t o s

To build all examples, run make

$ make

All examples and the .jedbug Ozone project files are placed in the ‘build’
folder.

0.157.5. Flash And Run The Examples. The Makefile builds different versions: -
example.elf: .elf file with all debug information - example.bin: .bin file that can
be used for flashing
256

0.157.6. Nucleo68. There are different options to flash and debug the Nucleo68
board. The Nucleo68 boards comes with an on-board ST-Link programmer and
debugger. As an alternative, the ST-Link programmer can be replaced by an
SEGGER J-Link OB. Finally, the STM32 can be programmed with any ARM
Cortex JTAG or SWD programmer via the SWD jumper.
0.157.7. USB Dongle. Please use any ARM Cortex SWD programmer via the
SWD interface desribed in the hardware section.
0.157.8. Run Example Project using Ozone. When using an external J-Link pro-
grammer or after installing J-Link OB on the Nucleo68 board, you can flash
and debug using the cross-platform SEGGER Ozone Debugger. It is included in
some J-Link programmers or can be used for free for evaluation usage.
Just start Ozone and open the .jdebug file in the build folder. When compiled
with “ENABLE SEGGER RTT”, the debug output shows up in the Terminal
window of Ozone. Note: as mentioned before, Segger RTT currently stops work-
ing when CPU2 has started up.
0.157.9. Debug output. All debug output can be either send via SEGGER RTT
or via USART1. To get the console from USART1, simply connect your board
under STLink-v2 to your PC or connect PB6 (USART1 TX) of the Nucleo board
to an USB-2-UART adapter and open a terminal at 115200.
In src/btstack config.h resp. in example/btstack config.h of the generated
projects, additional debug information can be enabled by uncommenting EN-
ABLE LOG INFO.
Also, the full packet log can be enabled in src/btstack port.c by uncommenting
the hci dump init(..) line. The console output can then be converted into .pklg
files for OS X PacketLogger or WireShark by running tool/create packet log.py
0.157.10. GATT Database. In BTstack, the GATT Database is defined via the
.gatt file in the example folder. During the build, the .gatt file is converted into
a .h file with a binary representation of the GATT Database and useful defines
for the application.
0.158. BTstack Port for WICED platform. Tested with: - WICED SDK
3.4-6.2.1 - RedBear Duo: Please install RedBear WICED Add-On - Inventek
Systems ISM4334x - Please contact Inventek Systems for WICED platform files
- Inventek Systems ISM4343 (BCM43438 A1) - Please contact Inventek Systems
for WICED platform files
To integrate BTstack into the WICED SDK, please move the BTstack project
into WICED-SDK-6.2.1/libraries.
Then create projects for BTstack examples in WICED/apps/btstack by run-
ning:

. / c r e a t e e x a m p l e s . py

Now, the BTstack examples can be build from the WICED root in the same
way as other examples, e.g.:
257

. / make b t s t a c k . s p p a n d l e c o u n t e r −RB DUO

to build the SPP-and-LE-Counter example for the RedBear Duo (or use ISM43340 M4G L44
/ ISM4343 WBM L151 for the Inventek Systems devices).
See WICED documentation about how to upload the firmware.
It should work with all WICED platforms that contain a Broadcom Bluetooth
chipset.
The maximal baud rate is currenty limited to 1 mbps.
The port uses the generated WIFI address plus 1 as Bluetooth MAC address.
It persists the LE Device DB and Classic Link Keys via the DCT mechanism.
All examples that rovide a GATT Server use the GATT DB in the .gatt file.
Therefore you need to run ./update gatt db.sh in the apps/btstack/$(EXAMPLE)
folder after modifying the .gatt file.

0.159. BTstack Port for Windows Systems with Bluetooth Controller


connected via Serial Port. The Windows-H4 port uses the native run loop
and allows to use Bluetooth Controllers connected via Serial Port.
Make sure to manually reset the Bluetooth Controller before starting any of
the examples.
The port provides both a regular Makefile as well as a CMake build file. It uses
native Win32 APIs for file access and does not require the Cygwin or mingw64
build/runtine. All examples can also be build with Visual Studio 2022 (e.g. Com-
munity Edition).

0.159.1. Visual Studio 2022. Visual Studio can directly open the provided port/
windows−windows−h4/CMakeLists.txt and allows to compile and run all examples.

0.159.2. mingw64. It can also be compiles with a regular Unix-style toolchain like
mingw-w64. mingw64-w64 is based on MinGW, which ‘. . . provides a complete
Open Source programming tool set which is suitable for the development of
native MS-Windows applications, and which do not depend on any 3rd-party
C-Runtime DLLs.’
We’ve used the Msys2 package available from the downloads page on Windows
10, 64-bit and use the MSYS2 MinGW 64-bit start menu item to compile 64-bit
binaries.
In the MSYS2 shell, you can install everything with pacman:

$ pacman −S git
$ pacman −S cmake
$ pacman −S make
$ pacman −S mingw−w64−x86 64−t o o l c h a i n
$ pacman −S mingw−w64−x86 64−p o r t a u d i o
$ pacman −S python
$ pacman −S winpty
258

0.159.3. Compilation with CMake. With mingw64-w64 installed, just go to the


port/windows-h4 directory and use CMake as usual

$ cd p o r t / windows−h4
$ mkdir b u i l d
$ cd b u i l d
$ cmake . .
$ make

Note: When compiling with msys2-32 bit and/or the 32-bit toolchain, com-
pilation fails as conio.h seems to be mission. Please use msys2-64 bit with the
64-bit toolchain for now.

0.159.4. Console Output. When running the examples in the MSYS2 shell, the
console input (via btstack stdin support) doesn’t work. It works in the older
MSYS and also the regular CMD.exe environment. Another option is to install
WinPTY and then start the example via WinPTY like this:

$ winpty . / g a t t c o u n t e r . exe

The packet log will be written to hci dump.pklg

0.160. BTstack Port for Windows Systems with DA14585 Controller


connected via Serial Port. This port allows to use the DA14585 connected
via Serial Port with BTstack running on a Win32 host system.
It first downloads the hci 585.hex firmware from the 6.0.8.509 SDK, before
BTstack starts up.
Please note that it does not detect if the firmware has already been down-
loaded, so you need to reset the DA14585 before starting an example.
For production use, the HCI firmware could be flashed into the OTP and the
firmware download could be skipped.
Tested with the official DA14585 Dev Kit Basic on OS X and Windows 10.
The port provides both a regular Makefile as well as a CMake build file. It uses
native Win32 APIs for file access and does not require the Cygwin or mingw64
build/runtine. All examples can also be build with Visual Studio 2022 (e.g. Com-
munity Edition).

0.160.1. Visual Studio 2022. Visual Studio can directly open the provided port
/windows−windows−h4−da14585/CMakeLists.txt and allows to compile and run all
examples.

0.160.2. mingw64. It can also be compiles with a regular Unix-style toolchain like
mingw-w64. mingw64-w64 is based on MinGW, which ‘. . . provides a complete
Open Source programming tool set which is suitable for the development of
native MS-Windows applications, and which do not depend on any 3rd-party
C-Runtime DLLs.’
259

We’ve used the Msys2 package available from the downloads page on Windows
10, 64-bit and use the MSYS2 MinGW 64-bit start menu item to compile 64-bit
binaries.
In the MSYS2 shell, you can install everything with pacman:

$ pacman −S git
$ pacman −S cmake
$ pacman −S make
$ pacman −S mingw−w64−x86 64−t o o l c h a i n
$ pacman −S mingw−w64−x86 64−p o r t a u d i o
$ pacman −S python
$ pacman −S winpty

0.160.3. Compilation with CMake. With mingw64-w64 installed, just go to the


port/windows-h4 directory and use CMake as usual

$ cd p o r t / windows−h4
$ mkdir b u i l d
$ cd b u i l d
$ cmake . .
$ make

Note: When compiling with msys2-32 bit and/or the 32-bit toolchain, com-
pilation fails as conio.h seems to be mission. Please use msys2-64 bit with the
64-bit toolchain for now.
0.160.4. Console Output. When running the examples in the MSYS2 shell, the
console input (via btstack stdin support) doesn’t work. It works in the older
MSYS and also the regular CMD.exe environment. Another option is to install
WinPTY and then start the example via WinPTY like this:

$ winpty . / g a t t c o u n t e r . exe

The packet log will be written to hci dump.pklg


0.161. BTstack Port for Windows Systems with Zephyr-based Con-
troller. The main difference to the regular windows-h4 port is that that the
Zephyr Contoller uses 1000000 as baud rate. In addition, the port defaults to
use the fixed static address stored during production.
The port provides both a regular Makefile as well as a CMake build file. It uses
native Win32 APIs for file access and does not require the Cygwin or mingw64
build/runtine. All examples can also be build with Visual Studio 2022 (e.g. Com-
munity Edition).
0.161.1. Prepare Zephyr Controller. Please follow this blog post about how to
compile and flash samples/bluetooth/hci uart to a connected nRF5 dev kit.
260

In short: you need to install an arm-none-eabi gcc toolchain and the nRF5x
Command Line Tools incl. the J-Link drivers, checkout the Zephyr project, and
flash an example project onto the chipset:
• Install J-Link Software and documentation pack.
• Get nrfjprog as part of the nRFx-Command-Line-Tools. Click on Down-
loads tab on the top and look for your OS.
• Checkout Zephyr and install toolchain. We recommend using the arm-
non-eabi gcc binaries instead of compiling it yourself. At least on OS X,
this failed for us.
• In samples/bluetooth/hci uart, compile the firmware for nRF52 Dev Kit
$ make BOARD=nrf52 pca10040
• Upload the firmware
$ make flash
• For the nRF51 Dev Kit, use make BOARD=nrf51 pca10028.

0.161.2. Configure serial port. To set the serial port of your Zephyr Controller,
you can either update config.device name in main.c or always start the examples
with the correct −u COMx option.

0.161.3. Visual Studio 2022. Visual Studio can directly open the provided port
/windows−windows−h4−zephyr/CMakeLists.txt and allows to compile and run all ex-
amples.

0.161.4. mingw64. It can also be compiles with a regular Unix-style toolchain like
mingw-w64. mingw64-w64 is based on MinGW, which ‘. . . provides a complete
Open Source programming tool set which is suitable for the development of
native MS-Windows applications, and which do not depend on any 3rd-party
C-Runtime DLLs.’
In the MSYS2 shell, you can install everything with pacman:

$ pacman −S git
$ pacman −S cmake
$ pacman −S make
$ pacman −S mingw−w64−x86 64−t o o l c h a i n
$ pacman −S mingw−w64−x86 64−p o r t a u d i o
$ pacman −S python
$ pacman −S winpty

0.161.5. Compilation with CMake. With mingw64-w64 installed, just go to the


port/windows-h4 directory and use CMake as usual

$ cd p o r t / windows−h4
$ mkdir b u i l d
$ cd b u i l d
$ cmake . .
$ make
261

Note: When compiling with msys2-32 bit and/or the 32-bit toolchain, com-
pilation fails as conio.h seems to be mission. Please use msys2-64 bit with the
64-bit toolchain for now.

0.161.6. Console Output. When running the examples in the MSYS2 shell, the
console input (via btstack stdin support) doesn’t work. It works in the older
MSYS and also the regular CMD.exe environment. Another option is to install
WinPTY and then start the example via WinPTY like this:

$ winpty . / g a t t c o u n t e r . exe

The packet log will be written to hci dump.pklg

0.162. BTstack Port for Windows Systems using the WinUSB Driver.
The Windows-WinUSB port uses the native run loop and WinUSB API to access
a USB Bluetooth dongle.
The port provides both a regular Makefile as well as a CMake build file. It uses
native Win32 APIs for file access and does not require the Cygwin or mingw64
build/runtine. All examples can also be build with Visual Studio 2022 (e.g. Com-
munity Edition).

0.162.1. Access to Bluetooth USB Dongle with Zadig. To allow WinUSB to access
an USB Bluetooth dongle, you need to install a special device driver to make it
accessible to user space processes.
It works like this:
• Download Zadig
• Start Zadig
• Select Options -> “List all devices”
• Select USB Bluetooth dongle in the big pull down list
• Select WinUSB in the right pull down list
• Select “Replace Driver”
After the new driver was installed, your device is shown in the Device Manager
with Device Provider ‘libwdi’

0.162.2. Visual Studio 2022. Visual Studio can directly open the provided port
/windows−winusb/CMakeLists.txt and allows to compile and run all examples. For
this, the C++ CMake tools for Windows is required. They are part of the
Desktop development with C++ workloads.

0.162.3. mingw64. It can also be compiles with a regular Unix-style toolchain like
mingw-w64. mingw64-w64 is based on MinGW, which ‘. . . provides a complete
Open Source programming tool set which is suitable for the development of
native MS-Windows applications, and which do not depend on any 3rd-party
C-Runtime DLLs.’
In the MSYS2 shell, you can install everything with pacman:
262

Zadig showing CYW20704A2

$ pacman −S git
$ pacman −S cmake
$ pacman −S make
$ pacman −S mingw−w64−x86 64−t o o l c h a i n
$ pacman −S mingw−w64−x86 64−p o r t a u d i o
$ pacman −S python
$ pacman −S winpty

0.162.4. Compilation with CMake. With mingw64-w64 installed, just go to the


port/windows-h4 directory and use CMake as usual

$ cd p o r t / windows−h4
$ mkdir b u i l d
$ cd b u i l d
$ cmake . .
$ make

Note: When compiling with msys2-32 bit and/or the 32-bit toolchain, com-
pilation fails as conio.h seems to be mission. Please use msys2-64 bit with the
64-bit toolchain for now.

0.162.5. Console Output. When running the examples in the MSYS2 shell, the
console input (via btstack stdin support) doesn’t work. It works in the older
MSYS and also the regular CMD.exe environment. Another option is to install
WinPTY and then start the example via WinPTY like this:
263

Device Manager showing CYW20704A2

$ winpty . / s p p a n d l e c o u n t e r . exe

0.163. BTstack Port for Windows Systems with Intel Wireless 8260/8265
Controllers. Same as port/windows-winusb, but customized for Intel Wireless
8260 and 8265 Controllers. These controller require firmware upload and config-
uration to work. Firmware and config is downloaded from the Linux firmware
repository.
The port provides both a regular Makefile as well as a CMake build file. It uses
native Win32 APIs for file access and does not require the Cygwin or mingw64
264

Zadig showing CYW20704A2

build/runtine. All examples can also be build with Visual Studio 2022 (e.g. Com-
munity Edition).

0.163.1. Access to Bluetooth USB Dongle with Zadig. To allow WinUSB to access
an USB Bluetooth dongle, you need to install a special device driver to make it
accessible to user space processes.
It works like this:
• Download Zadig
• Start Zadig
• Select Options -> “List all devices”
• Select USB Bluetooth dongle in the big pull down list
• Select WinUSB in the right pull down list
• Select “Replace Driver”
After the new driver was installed, your device is shown in the Device Manager
with Device Provider ‘libwdi’

0.163.2. Visual Studio 2022. Visual Studio can directly open the provided port/
windows−winusb−intel/CMakeLists.txt and allows to compile and run all examples.

0.163.3. mingw64. It can also be compiles with a regular Unix-style toolchain like
mingw-w64. mingw64-w64 is based on MinGW, which ‘. . . provides a complete
Open Source programming tool set which is suitable for the development of
native MS-Windows applications, and which do not depend on any 3rd-party
C-Runtime DLLs.’
In the MSYS2 shell, you can install everything with pacman:
265

Device Manager showing CYW20704A2

$ pacman −S git
$ pacman −S cmake
$ pacman −S make
$ pacman −S mingw−w64−x86 64−t o o l c h a i n
$ pacman −S mingw−w64−x86 64−p o r t a u d i o
$ pacman −S python
$ pacman −S winpty

0.163.4. Compilation with CMake. With mingw64-w64 installed, just go to the


port/windows-h4 directory and use CMake as usual
266

$ cd p o r t / windows−h4
$ mkdir b u i l d
$ cd b u i l d
$ cmake . .
$ make

Note: When compiling with msys2-32 bit and/or the 32-bit toolchain, com-
pilation fails as conio.h seems to be mission. Please use msys2-64 bit with the
64-bit toolchain for now.

0.163.5. Console Output. When running the examples in the MSYS2 shell, the
console input (via btstack stdin support) doesn’t work. It works in the older
MSYS and also the regular CMD.exe environment. Another option is to install
WinPTY and then start the example via WinPTY like this:

$ winpty . / g a t t c o u n t e r . exe

The packet log will be written to hci dump.pklg

0.164. BTstack Port for Zephyr RTOS.

0.164.1. Overview. This port targets any platform supported by Zephyr that
either contains a built-in Bluetooth Controller or is connected to an external
Controller via one of the supported Zephyr HCI Transports drivers (see zephyr/
drivers/bluetooth/hci)

0.164.2. Status. Tested with nRF52 DK (PCA10040), nRF52840 DK (PC10056)


and nRF5340 DK (PCA10095) boards only. It uses the fixed static random BD
ADDR stored in NRF FICR/NRF FICR S, which will not compile on non nRF
SoCs.

0.164.3. Build Environment. The first step needs to done once. Step two is
needed every time to setup the environment.

0.164.4. 1. Build Environment Preconditions. Follow the getting started guide


until you are able to build an example.
Then update the ZEPHYR ROOT variable in env.sh to point to your zephyrproject.
Defaults to ˜/zephyrproject

0.164.5. 2. Prepare the build environment. To setup your environment to build


a BTstack example, run the provided setup in env.sh.

s o u r c e env . sh

0.164.6. Building and Running on nRF52840.


267

0.164.7. 1. Build Example. You can build an example using:

west b u i l d −b n r f 5 2 8 4 0 d k n r f 5 2 8 4 0

nrf52840dk nrf52840 selected the Nordic nRF52840 DK. For the older nRF52 DK
with nRF52832, you can specify nrf52dk nrf52832. To get a list of all supported
Zephyr targets, run west boards
To change zephyr platform settings use:

west b u i l d −b n r f 5 2 8 4 0 d k n r f 5 2 8 4 0 −t menuconfig

To build a different example, e.g. the gatt streamer server , set the EXAMPLE
environment variable:

EXAMPLE=g a t t s t r e a m e r s e r v e r west b u i l d −b n r f 5 2 8 4 0 d k n r f 5 2 8 4 0

0.164.8. 2. Flash Example. To flash a connected board:

west f l a s h

0.164.9. Buiding and Running on nRF5340. The nrf5340 is a dual core SoC,
where one core is used for Bluetooth HCI functionality and the other for the high
level application logic. So both cores need to be programmed separately. Using
the nRF5340-DK for example allows debug output on both cores to separate
UART ports. For the nRF5340 a network core firmware is required, which one
depends on the use-case. With 2a and 2b two options are given.
0.164.10. 1. Building the application. build using:

west b u i l d −b n r f 5 3 4 0 d k n r f 5 3 4 0 c p u a p p

with debug:

west b u i l d −b n r f 5 3 4 0 d k n r f 5 3 4 0 c p u a p p −− −DOVERLAY CONFIG=


debug overlay . conf

0.164.11. 2a. Using zephyr network core image. the hci rgmsg application needs
to be loaded first to the network core. Configure network core by selecting the ap-
propriate config file, for example nrf5340 cpunet iso− bt ll sw split .conf. additionally
it’s required to increase the main stack size from
268

CONFIG MAIN STACK SIZE=512

to

CONFIG MAIN STACK SIZE=4096

then the network core image can be compiled and flashed

west b u i l d −b n r f 5 3 4 0 d k n r f 5 3 4 0 c p u n e t −− −DCONF FILE=


n r f 5 3 4 0 c p u n e t i s o −b t l l s w s p l i t . c o n f
west f l a s h

or with debugging

west b u i l d −b n r f 5 3 4 0 d k n r f 5 3 4 0 c p u n e t −− −DCONF FILE=


n r f 5 3 4 0 c p u n e t i s o −b t l l s w s p l i t . c o n f −DOVERLAY CONFIG=
debug overlay . conf
west f l a s h

0.164.12. 2b. Using Packetcraft binary network core image. for nrf5340 the latest
netcore firmware is located at sdk-nrf to program it:

n r f j p r o g −−program b l e 5 −c t r −rpmsg <v e r s i o n number >. hex −−c h i p e r a s e


−−c o p r o c e s s o r CP NETWORK −r

0.164.13. TODO.
• Allow/document use of Zephyr HCI Drivers
#Integrating with Existing Systems
While the run loop provided by BTstack is sufficient for new designs, BTstack
is often used with or added to existing projects. In this case, the run loop, data
sources, and timers may need to be adapted. The following two sections provides
a guideline for single and multi-threaded environments.
To simplify the discussion, we’ll consider an application split into “Main”,
“Communication Logic”, and “BTstack”. The Communication Logic contains
the packet handler (PH) that handles all asynchronous events and data packets
from BTstack. The Main Application makes use of the Communication Logic
for its Bluetooth communication.
0.165. Adapting BTstack for Single-Threaded Environments. In a single-
threaded environment, all application components run on the same (single)
thread and use direct function calls as shown in Figure below.
269

Main  Applica*on  

Communica*on.  
Logic     PH  

BTstack  

BTstack in single-threaded environment.

BTstack provides a basic run loop that supports the concept of data sources
and timers, which can be registered centrally. This works well when working with
a small MCU and without an operating system. To adapt to a basic operating
system or a different scheduler, BTstack’s run loop can be implemented based
on the functions and mechanism of the existing system.
Currently, we have two examples for this:
• btstack run loop posix.c is an implementation for POSIX compliant sys-
tems. The data sources are modeled as file descriptors and managed in
a linked list. Then, the select function is used to wait for the next file
descriptor to become ready or timer to expire.
• btstack run loop cocoa.c is an integration for the CoreFoundation Frame-
work used in OS X and iOS. All run loop functions are implemented in
terms of CoreFoundation calls, data sources and timers are modeled as
CFSockets and CFRunLoopTimer respectively.
• btstack run loop windows is an implementation for Windows environment.
The data sources are modeled with Event objects and managed in a linked
list. Then, the WaitForMultipleObjects is used to wait for the next Event
to becomre ready or timer to expire.
• btstack run loop qt is an integration for the Qt run loop. The data sources
on Windows systems use Event objects via Qt’s QEventNotifier adapter,
while a QSocketNotifier is used for Mac/Linux to handle file descriptors.
With these in place, the Windows/POSIX implemenations for HCI US-
B/H2 and HCI H4 can be used.

0.166. Adapting BTstack for Multi-Threaded Environments. The basic


execution model of BTstack is a general while loop. Aside from interrupt-driven
UART and timers, everything happens in sequence. When using BTstack in a
multi-threaded environment, this assumption has to stay valid - at least with
respect to BTstack. For this, there are two common options:
• The Communication Logic is implemented on a dedicated BTstack thread,
and the Main Application communicates with the BTstack thread via
application-specific messages over an Interprocess Communication (IPC)
as depicted in Figure below. This option results in less code and quick
adaption.
270

Communica)on  
Logic  
IPC  
Main  
PH   application custom IPC  
commands
Applica)on  

BTstack  

BTstack in multi-threaded environment - monolithic solution.

Daemon  
Main  
IPC   Applica6on  

PH   Bluetooth IPC  
commands and Communica6on  
events Logic  
BTstack   PH  
PH  

BTstack in multi-threaded environment - solution with daemon.

• BTstack must be extended to run standalone, i.e, as a Daemon, on a dedi-


cated thread and the Main Application controls this daemon via BTstack
extended HCI command over IPC - this is used for the non-embedded ver-
sion of BTstack e.g., on the iPhone and it is depicted in Figure below.
This option requires more code but provides more flexibility.
271

1. APIs
1.1. AD Data Parser API. ad parser.h : AD Data (Advertisements and
EIR) Parser

typedef struct a d c o n t e x t {
const uint8 t ∗ data ;
uint8 t offset ;
uint8 t length ;
} ad context t ;

// A d v e r t i s i n g or Scan Response d a t a i t e r a t o r
void a d i t e r a t o r i n i t ( a d c o n t e x t t ∗ c o n t e x t , uint8 t a d l e n , const
uint8 t ∗ a d d a t a ) ;
b o o l a d i t e r a t o r h a s m o r e ( const a d c o n t e x t t ∗ c o n t e x t ) ;
void a d i t e r a t o r n e x t ( a d c o n t e x t t ∗ c o n t e x t ) ;

// Access f u n c t i o n s
uint8 t a d i t e r a t o r g e t d a t a t y p e ( const a d c o n t e x t t ∗
context ) ;
uint8 t a d i t e r a t o r g e t d a t a l e n ( const a d c o n t e x t t ∗
context ) ;
const uint8 t ∗ a d i t e r a t o r g e t d a t a ( const a d c o n t e x t t ∗ c o n t e x t ) ;

// c o n v e n i e n c e f u n c t i o n on c o m p l e t e a d v e r t i s e m e n t s
b o o l a d d a t a c o n t a i n s u u i d 1 6 ( uint8 t a d l e n , const uint8 t ∗ ad data
, uint16 t uuid16 ) ;
b o o l a d d a t a c o n t a i n s u u i d 1 2 8 ( uint8 t a d l e n , const uint8 t ∗
ad data , const uint8 t ∗ uuid128 ) ;

1.2. ATT Database Engine API. att db.h

// map ATT ERROR CODES on t o a t t r e a d c a l l b a c k l e n g t h


#define ATT READ ERROR CODE OFFSET 0 xfe00u

// custom BTstack ATT Response Pending f o r a t t r e a d c a l l b a c k


#define ATT READ RESPONSE PENDING 0xffffu

// i n t e r n a l l y used t o s i g n a l w r i t e r e s p o n s e p e n d i n g
#define ATT INTERNAL WRITE RESPONSE PENDING 0 xfffeu

/∗ ∗
∗ @ b r i e f ATT C l i e n t Read C a l l b a c k f o r Dynamic Data
∗ − i f b u f f e r == NULL, don ’ t copy data , j u s t r e t u r n s i z e o f v a l u e
∗ − i f b u f f e r != NULL, copy d a t a and r e t u r n number b y t e s c o p i e d
∗ I f ENABLE ATT DELAYED READ RESPONSE i s d e f i n e d , you may r e t u r n
ATT READ RESPONSE PENDING i f d a t a i s n ’ t a v a i l a b l e y e t
∗ @param c o n h a n d l e o f h c i l e c o n n e c t i o n
∗ @param a t t r i b u t e h a n d l e t o be rea d
∗ @param o f f s e t d e f i n e s s t a r t o f a t t r i b u t e v a l u e
∗ @param b u f f e r
272

∗ @param b u f f e r s i z e
∗ @return s i z e o f v a l u e i f b u f f e r i s NULL, o t h e r w i s e number o f
bytes copied
∗/
typedef uint16 t ( ∗ a t t r e a d c a l l b a c k t ) ( h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t a t t r i b u t e h a n d l e , uint16 t o f f s e t , uint8 t ∗ b u f f e r ,
uint16 t b u f f e r s i z e ) ;

/∗ ∗
∗ @ b r i e f ATT C l i e n t Write C a l l b a c k f o r Dynamic Data
∗ Each Prepared Write R e q u e s t t r i g g e r s a c a l l b a c k w i t h t r a n s a c t i o n
mode ATT TRANSACTION MODE ACTIVE.
∗ On E x e c u t e Write , t h e c a l l b a c k w i l l be c a l l e d w i t h
ATT TRANSACTION MODE VALIDATE and a l l o w s t o v a l i d a t e a l l queued
w r i t e s and r e t u r n an a p p l i c a t i o n e r r o r .
∗ I f none o f t h e r e g i s t e r e d c a l l b a c k s r e t u r n an e r r o r f o r
ATT TRANSACTION MODE VALIDATE and t h e c a l l b a c k w i l l be c a l l e d
w i t h ATT TRANSACTION MODE EXECUTE.
∗ Otherwise , a l l c a l l b a c k s w i l l be c a l l e d w i t h
ATT TRANSACTION MODE CANCEL.

∗ I f t h e a d d i t i o n a l v a l i d a t i o n s t e p i s not needed , j u s t r e t u r n 0
f o r a l l c a l l b a c k s w i t h t r a n s a c t i o n mode
ATT TRANSACTION MODE VALIDATE.

∗ @param c o n h a n d l e o f h c i l e c o n n e c t i o n
∗ @param a t t r i b u t e h a n d l e t o be w r i t t e n
∗ @param t r a n s a c t i o n − ATT TRANSACTION MODE NONE f o r r e g u l a r w r i t e s
. For p r e p a r e d w r i t e s : ATT TRANSACTION MODE ACTIVE,
ATT TRANSACTION MODE VALIDATE, ATT TRANSACTION MODE EXECUTE,
ATT TRANSACTION MODE CANCEL
∗ @param o f f s e t i n t o t h e v a l u e − used f o r queued w r i t e s and l o n g
attributes
∗ @param b u f f e r
∗ @param b u f f e r s i z e
∗ @param s i g n a t u r e used f o r s i g n e d w r i t e commmands
∗ @return 0 i f w r i t e was ok , ATT ERROR PREPARE QUEUE FULL i f no
s p a c e i n queue , ATT ERROR INVALID OFFSET i f o f f s e t i s l a r g e r
than max b u f f e r
∗/
typedef int ( ∗ a t t w r i t e c a l l b a c k t ) ( h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t a t t r i b u t e h a n d l e , uint16 t t r a n s a c t i o n m o d e , uint16 t
o f f s e t , uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e ) ;

// Read & Write C a l l b a c k s f o r h a n d l e range


typedef struct a t t s e r v i c e h a n d l e r {
b t s t a c k l i n k e d i t e m t ∗ item ;
att read callback t read callback ;
att write callback t write callback ;
btstack packet handler t p a c k e t h a n d l e r ;
uint16 t s t a r t h a n d l e ;
uint16 t e n d h a n d l e ;
uint8 t f l a g s ;
} att service handler t ;
273

// MARK: ATT O p e r a t i o n s

/∗ ∗
∗ @ b r i e f s e t u p ATT d a t a b a s e
∗ @param db
∗/
void a t t s e t d b ( uint8 t const ∗ db ) ;

/∗
∗ @ b r i e f s e t c a l l b a c k f o r re ad o f dynamic a t t r i b u t e s
∗ @param c a l l b a c k
∗/
void a t t s e t r e a d c a l l b a c k ( a t t r e a d c a l l b a c k t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f s e t c a l l b a c k f o r w r i t e o f dynamic a t t r i b u t e s
∗ @param c a l l b a c k
∗/
void a t t s e t w r i t e c a l l b a c k ( a t t w r i t e c a l l b a c k t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f debug h e l p e r , dump ATT d a t a b a s e t o s t d o u t u s i n g l o g i n f o
∗/
void a t t d u m p a t t r i b u t e s ( void ) ;

/∗ ∗
∗ @ b r i e f p r o c e s s ATT r e q u e s t a g a i n s t d a t a b a s e and p u t r e s p o n s e i n t o
response b u f f e r
∗ @param a t t c o n n e c t i o n used f o r mtu and s e c u r i t y p r o p e r t i e s
∗ @param r e q u e s t b u f f e r , r e q u e s t l e n : ATT r e q u e s t from c l i n e t
∗ @param r e s p o n s e b u f f e r f o r r e s u l t
∗ @return l e n o f d a t a i n r e s p o n s e b u f f e r . 0 = no r e s p o n s e ,
∗ ATT READ RESPONSE PENDING i f i t was r e t u r n e d a t l e a s t
once f o r dynamic d a t a ( r e q u i r e s
ENABLE ATT DELAYED READ RESPONSE)
∗/
uint16 t a t t h a n d l e r e q u e s t ( a t t c o n n e c t i o n t ∗ a t t c o n n e c t i o n ,
uint8 t ∗ r e q u e s t b u f f e r ,
uint16 t r e q u e s t l e n ,
uint8 t ∗ r e s p o n s e b u f f e r ) ;

/∗ ∗
∗ @brief setup value n o t i f i c a t i o n in response b u f f e r for a given
h a n d l e and v a l u e
∗ @param a t t c o n n e c t i o n
∗ @param a t t r i b u t e h a n d l e
∗ @param v a l u e
∗ @param v a l u e l e n
∗ @param r e s p o n s e b u f f e r f o r n o t i f i c a t i o n
∗/
uint16 t a t t p r e p a r e h a n d l e v a l u e n o t i f i c a t i o n ( a t t c o n n e c t i o n t ∗
att connection ,
274

uint16 t
attribute handle ,
const uint8 t ∗ val ue ,
uint16 t v a l u e l e n ,
uint8 t ∗
response buffer ) ;

/∗ ∗
∗ @brief setup value n o t i f i c a t i o n in response b u f f e r for m u l t i p l e
h a n d l e s and v a l u e s
∗ @param a t t c o n n e c t i o n
∗ @param a t t r i b u t e h a n d l e
∗ @param v a l u e
∗ @param v a l u e l e n
∗ @param r e s p o n s e b u f f e r f o r n o t i f i c a t i o n
∗/
uint16 t a t t p r e p a r e h a n d l e v a l u e m u l t i p l e n o t i f i c a t i o n (
att connection t ∗ att connection ,
uint8 t
num attributes
,
const
uint16 t

attribute handles
,
const
uint8 t
∗∗
values data
,
const
uint16 t

values len
,
uint8 t ∗
response buffer
);

/∗ ∗
∗ @brief setup value i n d i c a t i o n in response b u f f e r for a given
h a n d l e and v a l u e
∗ @param a t t c o n n e c t i o n
∗ @param a t t r i b u t e h a n d l e
∗ @param v a l u e
∗ @param v a l u e l e n
∗ @param r e s p o n s e b u f f e r f o r i n d i c a t i o n
∗/
uint16 t a t t p r e p a r e h a n d l e v a l u e i n d i c a t i o n ( a t t c o n n e c t i o n t ∗
att connection ,
uint16 t
attribute handle ,
const uint8 t ∗ val ue ,
275

uint16 t v a l u e l e n ,
uint8 t ∗
response buffer ) ;

/∗ ∗
∗ @ b r i e f t r a n s c a t i o n queue o f p r e p a r e d w r i t e s , e . g . , a f t e r
disconnect
∗ @return a t t c o n n e c t i o n
∗/
void a t t c l e a r t r a n s a c t i o n q u e u e ( a t t c o n n e c t i o n t ∗ a t t c o n n e c t i o n ) ;

// a t t r e a d c a l l b a c k h e l p e r s f o r a v a r i o u s d a t a t y p e s

/∗ ∗
∗ @ b r i e f Handle read o f b l o b l i k e d a t a f o r a t t r e a d c a l l b a c k
∗ @param b l o b o f d a t a
∗ @param b l o b s i z e o f b l o b
∗ @param o f f s e t from a t t r e a d c a l l b a c k
∗ @param b u f f e r from a t t r e a d c a l l b a c k
∗ @param b u f f e r s i z e from a t t r e a d c a l l b a c k
∗ @return v a l u e s i z e f o r b u f f e r == 0 and num b y t e s c o p i e d o t h e r w i s e
∗/
uint16 t a t t r e a d c a l l b a c k h a n d l e b l o b ( const uint8 t ∗ blob ,
uint16 t b l o b s i z e , uint16 t o f f s e t , uint8 t ∗ b u f f e r , uint16 t
buffer size ) ;

/∗ ∗
∗ @ b r i e f Handle read o f l i t t l e endian u n s i g n e d 32 b i t v a l u e f o r
att read callback
∗ @param v a l u e
∗ @param o f f s e t from a t t r e a d c a l l b a c k
∗ @param b u f f e r from a t t r e a d c a l l b a c k
∗ @param b u f f e r s i z e from a t t r e a d c a l l b a c k
∗ @return v a l u e s i z e f o r b u f f e r == 0 and num b y t e s c o p i e d o t h e r w i s e
∗/
uint16 t a t t r e a d c a l l b a c k h a n d l e l i t t l e e n d i a n 3 2 ( uint32 t val ue ,
uint16 t o f f s e t , uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e ) ;

/∗ ∗
∗ @ b r i e f Handle read o f l i t t l e endian u n s i g n e d 16 b i t v a l u e f o r
att read callback
∗ @param v a l u e
∗ @param o f f s e t from a t t r e a d c a l l b a c k
∗ @param b u f f e r from a t t r e a d c a l l b a c k
∗ @param b u f f e r s i z e from a t t r e a d c a l l b a c k
∗ @return v a l u e s i z e f o r b u f f e r == 0 and num b y t e s c o p i e d o t h e r w i s e
∗/
uint16 t a t t r e a d c a l l b a c k h a n d l e l i t t l e e n d i a n 1 6 ( uint16 t val ue ,
uint16 t o f f s e t , uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e ) ;

/∗ ∗
∗ @ b r i e f Handle read o f s i n g l e b y t e f o r a t t r e a d c a l l b a c k
∗ @param b l o b o f d a t a
∗ @param b l o b s i z e o f b l o b
276

∗ @param o f f s e t from a t t r e a d c a l l b a c k
∗ @param b u f f e r from a t t r e a d c a l l b a c k
∗ @param b u f f e r s i z e from a t t r e a d c a l l b a c k
∗ @return v a l u e s i z e f o r b u f f e r == 0 and num b y t e s c o p i e d o t h e r w i s e
∗/
uint16 t a t t r e a d c a l l b a c k h a n d l e b y t e ( uint8 t val ue , uint16 t
o f f s e t , uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e ) ;

// e x p e r i m e n t a l c l i e n t API
/∗ ∗
∗ @ b r i e f Get UUID f o r h a n d l e
∗ @param a t t r i b u t e h a n d l e
∗ @return 0 i f not found
∗/
uint16 t a t t u u i d f o r h a n d l e ( uint16 t a t t r i b u t e h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Get c o n s t v a l u e f o r h a n d l e
∗ @param a t t r i b u t e h a n d l e
∗ @param o u t v a l u e l e n o u t p u t v a r i a b l e t h a t h o l d v a l u e l e n
∗ @return v a l u e
∗/

const uint8 t ∗ g a t t s e r v e r g e t c o n s t v a l u e f o r h a n d l e ( uint16 t


a t t r i b u t e h a n d l e , uint16 t ∗ o u t v a l u e l e n ) ;

// e x p e r i m e n t a l GATT S e r v e r API

/∗ ∗
∗ @ b r i e f Get h a n d l e range f o r primary s e r v i c e .
∗ @param uuid16
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @return f a l s e i f not found
∗/
b o o l g a t t s e r v e r g e t h a n d l e r a n g e f o r s e r v i c e w i t h u u i d 1 6 ( uint16 t
uuid16 , uint16 t ∗ s t a r t h a n d l e , uint16 t ∗ e n d h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Get h a n d l e range f o r i n c l u d e d s e r v i c e .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid16
∗ @param o u t i n c l u d e d s e r v i c e h a n d l e
∗ @param o u t i n c l u d e d s e r v i c e s t a r t h a n d l e
∗ @param o u t i n c l u d e d s e r v i c e e n d h a n d l e
∗ @return f a l s e i f not found
∗/
b o o l g a t t s e r v e r g e t i n c l u d e d s e r v i c e w i t h u u i d 1 6 ( uint16 t
s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t uuid16 ,
uint16 t ∗ o u t i n c l u d e d s e r v i c e h a n d l e , uint16 t ∗
o u t i n c l u d e d s e r v i c e s t a r t h a n d l e , uint16 t ∗
out included service end handle ) ;
277

/∗ ∗
∗ @ b r i e f Get v a l u e h a n d l e f o r c h a r a c t e r i s t i c .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid16
∗ @return 0 i f not found
∗/
uint16 t g a t t s e r v e r g e t v a l u e h a n d l e f o r c h a r a c t e r i s t i c w i t h u u i d 1 6
( uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t uuid16 ) ;

/∗ ∗
∗ @ b r i e f Get d e s c r i p t o r h a n d l e f o r c h a r a c t e r i s t i c .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param c h a r a c t e r i s t i c u u i d 1 6
∗ @param d e s c r i p t o r u u i d 1 6
∗ @return 0 i f not found
∗/
uint16 t
gatt server get descriptor handle for characteristic with uuid16
( uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t
c h a r a c t e r i s t i c u u i d 1 6 , uint16 t d e s c r i p t o r u u i d 1 6 ) ;

/∗ ∗
∗ @ b r i e f Get c l i e n t c o n f i g u r a t i o n h a n d l e f o r c h a r a c t e r i s t i c .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param c h a r a c t e r i s t i c u u i d 1 6
∗ @return 0 i f not found
∗/
uint16 t
gatt server get client configuration handle for characteristic with uuid16
( uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t
characteristic uuid16 ) ;

/∗ ∗
∗ @ b r i e f Get s e r v e r c o n f i g u r a t i o n h a n d l e f o r c h a r a c t e r i s t i c .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param c h a r a c t e r i s t i c u u i d 1 6
∗ @param d e s c r i p t o r u u i d 1 6
∗ @return 0 i f not found
∗/
uint16 t
gatt server get server configuration handle for characteristic with uuid16
( uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t
characteristic uuid16 ) ;

/∗ ∗
∗ @ b r i e f Get h a n d l e range f o r primary s e r v i c e .
∗ @param uuid128
∗ @param s t a r t h a n d l e
278

∗ @param e n d h a n d l e
∗ @return f a l s e i f not found
∗/
b o o l g a t t s e r v e r g e t h a n d l e r a n g e f o r s e r v i c e w i t h u u i d 1 2 8 ( const
uint8 t ∗ uuid128 , uint16 t ∗ s t a r t h a n d l e , uint16 t ∗
end handle ) ;

/∗ ∗
∗ @ b r i e f Get v a l u e h a n d l e .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid128
∗ @return 0 i f not found
∗/
uint16 t
gatt server get value handle for characteristic with uuid128 (
uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , const uint8 t ∗
uuid128 ) ;

/∗ ∗
∗ @ b r i e f Get c l i e n t c o n f i g u r a t i o n h a n d l e .
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid128
∗ @return 0 i f not found
∗/
uint16 t
gatt server get client configuration handle for characteristic with uuid128
( uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , const uint8 t ∗
uuid128 ) ;

1.3. Runtine ATT Database Setup API. att db util.h : Helper to con-
struct ATT DB at runtime (BTstack GATT Compiler is not used).

/∗ ∗
∗ @ b r i e f I n i t ATT DB s t o r a g e
∗/
void a t t d b u t i l i n i t ( void ) ;

/∗ ∗
∗ @brief Set handle value for next t a b l e entry
∗ @param h a n d l e
∗ @note new h a n d l e must be >= p r e v i o u s t o a v o i d r e u s i n g a s s i g n e d
handles
∗/
void a t t d b u t i l s e t n e x t h a n d l e ( uint16 t h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Add primary s e r v i c e f o r 16− b i t UUID
∗ @param uuid16
∗ @return a t t r i b u t e h a n d l e f o r t h e new s e r v i c e d e f i n i t i o n
∗/
279

uint16 t a t t d b u t i l a d d s e r v i c e u u i d 1 6 ( uint16 t uuid16 ) ;

/∗ ∗
∗ @ b r i e f Add primary s e r v i c e f o r 128− b i t UUID
∗ @param uuid128
∗ @return a t t r i b u t e h a n d l e f o r t h e new s e r v i c e d e f i n i t i o n
∗/
uint16 t a t t d b u t i l a d d s e r v i c e u u i d 1 2 8 ( const uint8 t ∗ uuid128 ) ;

/∗ ∗
∗ @ b r i e f Add s e c o n d a r y s e r v i c e f o r 16− b i t UUID
∗ @param uuid16
∗ @return a t t r i b u t e h a n d l e f o r t h e new s e r v i c e d e f i n i t i o n
∗/
uint16 t a t t d b u t i l a d d s e c o n d a r y s e r v i c e u u i d 1 6 ( uint16 t uuid16 ) ;

/∗ ∗
∗ @ b r i e f Add s e c o n d a r y s e r v i c e f o r 128− b i t UUID
∗ @param uuid128
∗ @return a t t r i b u t e h a n d l e f o r t h e new s e r v i c e d e f i n i t i o n
∗/
uint16 t a t t d b u t i l a d d s e c o n d a r y s e r v i c e u u i d 1 2 8 ( const uint8 t ∗
uuid128 ) ;

/∗ ∗
∗ @ b r i e f Add i n c l u d e d s e r v i c e w i t h 16− b i t UUID
∗ @param s t a r t g r o u p h a n d l e
∗ @param e n d g r o u p h a n d l e
∗ @param uuid16
∗ @return a t t r i b u t e h a n d l e f o r t h e new s e r v i c e d e f i n i t i o n
∗/
uint16 t a t t d b u t i l a d d i n c l u d e d s e r v i c e u u i d 1 6 ( uint16 t
s t a r t g r o u p h a n d l e , uint16 t e n d g r o u p h a n d l e , uint16 t uuid16 )
;

/∗ ∗
∗ @ b r i e f Add C h a r a c t e r i s t i c w i t h 16− b i t UUID, p r o p e r t i e s , and d a t a
∗ @param uuid16
∗ @param p r o p e r t i e s − s e e ATT PROPERTY ∗ i n s r c / b l u e t o o t h . h
∗ @param r e a d p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param w r i t e p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param d a t a r e t u r n e d i n re ad o p e r a t i o n s i f ATT PROPERTY DYNAMIC
i s not s p e c i f i e d
∗ @param d a t a l e n
∗ @return a t t r i b u t e h a n d l e o f t h e new c h a r a c t e r i s t i c v a l u e
declaration
∗ @note I f p r o p e r t i e s c o n t a i n s ATT PROPERTY NOTIFY or
ATT PROPERTY INDICATE f l a g s , a C l i e n t C o n f i g u r a t i o n
C h a r a c t e r i s t i c D e s c r i p t o r (CCCD)
∗ i s c r e a t e d as w e l l . The a t t r i b u t e v a l u e h a n d l e o f t h e CCCD
i s the a t t r i b u t e value handle plus 1
∗/
280

uint16 t a t t d b u t i l a d d c h a r a c t e r i s t i c u u i d 1 6 ( uint16 t uuid16 ,


uint16 t p r o p e r t i e s , uint8 t r e a d p e r m i s s i o n , uint8 t
w r i t e p e r m i s s i o n , uint8 t ∗ data , uint16 t d a t a l e n ) ;

/∗ ∗
∗ @ b r i e f Add C h a r a c t e r i s t i c w i t h 128− b i t UUID, p r o p e r t i e s , and d a t a
∗ @param uuid128
∗ @param p r o p e r t i e s − s e e ATT PROPERTY ∗ i n s r c / b l u e t o o t h . h
∗ @param r e a d p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param w r i t e p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param d a t a r e t u r n e d i n re ad o p e r a t i o n s i f ATT PROPERTY DYNAMIC
i s not s p e c i f i e d
∗ @param d a t a l e n
∗ @return a t t r i b u t e h a n d l e o f t h e new c h a r a c t e r i s t i c v a l u e
declaration
∗ @note I f p r o p e r t i e s c o n t a i n s ATT PROPERTY NOTIFY or
ATT PROPERTY INDICATE f l a g s , a C l i e n t C o n f i g u r a t i o n
C h a r a c t e r i s t i c D e s c r i p t o r (CCCD)
∗ i s c r e a t e d as w e l l . The a t t r i b u t e v a l u e h a n d l e o f t h e CCCD
i s the a t t r i b u t e value handle plus 1
∗/
uint16 t a t t d b u t i l a d d c h a r a c t e r i s t i c u u i d 1 2 8 ( const uint8 t ∗
uuid128 , uint16 t p r o p e r t i e s , uint8 t r e a d p e r m i s s i o n , uint8 t
w r i t e p e r m i s s i o n , uint8 t ∗ data , uint16 t d a t a l e n ) ;

/∗ ∗
∗ @ b r i e f Add d e s c r i p t o r w i t h 16− b i t UUID, p r o p e r t i e s , and d a t a
∗ @param uuid16
∗ @param p r o p e r t i e s − s e e ATT PROPERTY ∗ i n s r c / b l u e t o o t h . h
∗ @param r e a d p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param w r i t e p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param d a t a r e t u r n e d i n re ad o p e r a t i o n s i f ATT PROPERTY DYNAMIC i s
not s p e c i f i e d
∗ @param d a t a l e n
∗ @return a t t r i b u t e h a n d l e o f t h e new c h a r a c t e r i s t i c d e s c r i p t o r
declaration
∗/
uint16 t a t t d b u t i l a d d d e s c r i p t o r u u i d 1 6 ( uint16 t uuid16 , uint16 t
p r o p e r t i e s , uint8 t r e a d p e r m i s s i o n , uint8 t w r i t e p e r m i s s i o n ,
uint8 t ∗ data , uint16 t d a t a l e n ) ;

/∗ ∗
∗ @ b r i e f Add d e s c r i p t o r w i t h 128− b i t UUID, p r o p e r t i e s , and d a t a
∗ @param uuid128
∗ @param p r o p e r t i e s − s e e ATT PROPERTY ∗ i n s r c / b l u e t o o t h . h
∗ @param r e a d p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param w r i t e p e r m i s s i o n s − s e e ATT SECURITY ∗ i n s r c / b l u e t o o t h . h
∗ @param d a t a r e t u r n e d i n re ad o p e r a t i o n s i f ATT PROPERTY DYNAMIC i s
not s p e c i f i e d
∗ @param d a t a l e n
∗ @return a t t r i b u t e h a n d l e o f t h e new c h a r a c t e r i s t i c d e s c r i p t o r
declaration
∗/
281

uint16 t a t t d b u t i l a d d d e s c r i p t o r u u i d 1 2 8 ( const uint8 t ∗ uuid128 ,


uint16 t p r o p e r t i e s , uint8 t r e a d p e r m i s s i o n , uint8 t
w r i t e p e r m i s s i o n , uint8 t ∗ data , uint16 t d a t a l e n ) ;

/∗ ∗
∗ @ b r i e f Get a d d r e s s o f c o n s t r u c t e d ATT DB
∗/
uint8 t ∗ a t t d b u t i l g e t a d d r e s s ( void ) ;

/∗ ∗
∗ @ b r i e f Get s i z e o f c o n s t r u c t e d ATT DB
∗/
uint16 t a t t d b u t i l g e t s i z e ( void ) ;

/∗ ∗
∗ @ b r i e f Get number o f b y t e s t h a t a r e i n c l u d e d i n GATT Database
Hash
∗/
uint16 t a t t d b u t i l h a s h l e n ( void ) ;

/∗ ∗
∗ @ b r i e f i n i t g e n e r a t o r f o r GATT Database Hash
∗/
void a t t d b u t i l h a s h i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f g e t n e x t b y t e from g e n e r a t o r f o r GATT Database Hash
∗/
uint8 t a t t d b u t i l h a s h g e t n e x t ( void ) ;

/∗ ∗
∗ @ b r i e f C a l c u l a t e GATT Database Hash u s i n g c r y p t o e n g i n e
∗ @param r e q u e s t
∗ @param d b h a s h
∗ @param c a l l b a c k
∗ @param c a l l b a c k a r g
∗/
void a t t d b u t i l h a s h c a l c ( b t s t a c k c r y p t o a e s 1 2 8 c m a c t ∗ r e q u e s t ,
uint8 t ∗ db hash , void ( ∗ c a l l b a c k ) ( void ∗ a r g ) , void ∗
callback arg ) ;

1.4. ATT Dispatch API. att dispatch.h : Dispatcher for independent im-
plementation of ATT client and server.

1.5. ATT Server API. att server.h

/∗
∗ @brief s e t u p ATT s e r v e r
∗ @param db a t t r i b u t e d a t a b a s e c r e a t e d by compile −g a t t . py
∗ @param r e a d c a l l b a c k , s e e a t t d b . h , can be NULL
∗ @param w r i t e c a l l b a c k , s e e a t t l . h , can be NULL
∗/
282

void a t t s e r v e r i n i t ( uint8 t const ∗ db , a t t r e a d c a l l b a c k t


read callback , att write callback t write callback ) ;

/∗ ∗
∗ @ b r i e f Enable s u p p o r t f o r Enhanced ATT b e a r e r
∗ @note R e q u i r e s ENABLE GATT OVER EATT
∗ @param n u m e a t t b e a r e r s
∗ @param s t o r a g e b u f f e r
∗ @param s t o r a g e s i z e
∗ @return
∗/
uint8 t a t t s e r v e r e a t t i n i t ( uint8 t n u m e a t t b e a r e r s , uint8 t ∗
s t o r a g e b u f f e r , uint16 t s t o r a g e s i z e ) ;

/∗
∗ @ b r i e f r e g i s t e r p a c k e t h a n d l e r f o r ATT s e r v e r e v e n t s :
∗ − ATT EVENT CAN SEND NOW
∗ − ATT EVENT HANDLE VALUE INDICATION COMPLETE
∗ − ATT EVENT MTU EXCHANGE COMPLETE
∗ @param h a n d l e r
∗/
void a t t s e r v e r r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
handler ) ;

/∗ ∗
∗ @ b r i e f r e g i s t e r rea d / w r i t e c a l l b a c k s f o r s p e c i f i c h a n d l e range
∗ @param a t t s e r v i c e h a n d l e r t
∗/
void a t t s e r v e r r e g i s t e r s e r v i c e h a n d l e r ( a t t s e r v i c e h a n d l e r t ∗
handler ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c a l l b a c k when s e n d i n g i s p o s s i b l e
∗ @note c a l l b a c k might happend d u r i n g c a l l t o t h i s f u n c t i o n
∗ @param c a l l b a c k r e g i s t r a t i o n t o p o i n t t o c a l l b a c k f u n c t i o n and
context information
∗ @param c o n h a n d l e
∗ @return 0 i f ok , e r r o r o t h e r w i s e
∗/
uint8 t a t t s e r v e r r e g i s t e r c a n s e n d n o w c a l l b a c k (
btstack context callback registration t ∗ callback registration ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f Return ATT MTU
∗ @param c o n h a n d l e
∗ @return mtu i f ok , 0 o t h e r w i s e
∗/
uint16 t a t t s e r v e r g e t m t u ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c a l l b a c k when s e n d i n g n o t i f c a t i o n i s p o s s i b l e
∗ @note c a l l b a c k might happend d u r i n g c a l l t o t h i s f u n c t i o n
283

∗ @param c a l l b a c k r e g i s t r a t i o n t o p o i n t t o c a l l b a c k f u n c t i o n and
context information
∗ @param c o n h a n d l e
∗ @return ERROR CODE SUCCESS i f ok ,
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f h a n d l e unknown , and
ERROR CODE COMMAND DISALLOWED i f c a l l b a c k a l r e a d y r e g i s t e r e d
∗/
uint8 t a t t s e r v e r r e q u e s t t o s e n d n o t i f i c a t i o n (
btstack context callback registration t ∗ callback registration ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c a l l b a c k when s e n d i n g i n d i c a t i o n i s p o s s i b l e
∗ @note c a l l b a c k might happend d u r i n g c a l l t o t h i s f u n c t i o n
∗ @param c a l l b a c k r e g i s t r a t i o n t o p o i n t t o c a l l b a c k f u n c t i o n and
context information
∗ @param c o n h a n d l e
∗ @return ERROR CODE SUCCESS i f ok ,
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f h a n d l e unknown , and
ERROR CODE COMMAND DISALLOWED i f c a l l b a c k a l r e a d y r e g i s t e r e d
∗/
uint8 t a t t s e r v e r r e q u e s t t o s e n d i n d i c a t i o n (
btstack context callback registration t ∗ callback registration ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f n o t i f y c l i e n t a b o u t a t t r i b u t e v a l u e change
∗ @param c o n h a n d l e
∗ @param a t t r i b u t e h a n d l e
∗ @param v a l u e
∗ @param v a l u e l e n
∗ @return 0 i f ok , e r r o r o t h e r w i s e
∗/
uint8 t a t t s e r v e r n o t i f y ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
a t t r i b u t e h a n d l e , const uint8 t ∗ val ue , uint16 t v a l u e l e n ) ;

/∗ ∗
∗ @brief n o t i f y c l i e n t about m u l t i p l e a t t r i b u t e value changes
∗ @param c o n h a n d l e
∗ @param n u m a t t r i b u t e s
∗ @param a t t r i b u t e h a n d l e s [ ]
∗ @param v a l u e s d a t a [ ]
∗ @param v a l u e s l e n [ ]
∗ @return 0 i f ok , e r r o r o t h e r w i s e
∗/
uint8 t a t t s e r v e r m u l t i p l e n o t i f y ( h c i c o n h a n d l e t c o n h a n d l e ,
uint8 t n u m a t t r i b u t e s ,
const uint16 t ∗
a t t r i b u t e h a n d l e s , const
uint8 t ∗∗ v a l u e s d a t a , const
uint16 t ∗ v a l u e s l e n ) ;

/∗ ∗
284

∗ @ b r i e f i n d i c a t e v a l u e change t o c l i e n t . c l i e n t i s s u p p o s e d t o
r e p l y w i t h an i n d i c a t i o n r e s p o n s e
∗ @param c o n h a n d l e
∗ @param a t t r i b u t e h a n d l e
∗ @param v a l u e
∗ @param v a l u e l e n
∗ @return 0 i f ok , e r r o r o t h e r w i s e
∗/
uint8 t a t t s e r v e r i n d i c a t e ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
a t t r i b u t e h a n d l e , const uint8 t ∗ val ue , uint16 t v a l u e l e n ) ;

#i f d e f ENABLE ATT DELAYED RESPONSE


/∗ ∗
∗ @brief response ready − c a l l e d a f t e r r e t u r n i n g
ATT READ RESPONSE PENDING i n an a t t r e a d c a l l b a c k or
∗ ATT ERROR WRITE REQUEST PENDING IN a t t w r i t e c a l l b a c k b e f o r e t o
t r i g g e r c a l l b a c k a g a i n and c o m p l e t e t h e t r a n s a c t i o n
∗ @nore The ATT S e r v e r w i l l r e t r y h a n d l i n g t h e c u r r e n t ATT r e q u e s t
∗ @param c o n h a n d l e
∗ @return 0 i f ok , e r r o r o t h e r w i s e
∗/
uint8 t a t t s e r v e r r e s p o n s e r e a d y ( h c i c o n h a n d l e t c o n h a n d l e ) ;
#endif

/∗ ∗
∗ De−I n i t ATT S e r v e r
∗/
void a t t s e r v e r d e i n i t ( void ) ;

// t h e f o l l o w i n g f u n c t i o n s w i l l be removed soon

/∗ ∗
∗ @ b r i e f t e s t s i f a n o t i f i c a t i o n or i n d i c a t i o n can be send r i g h t
now
∗ @param c o n h a n d l e
∗ @return 1 , i f p a c k e t can be s e n t
∗/
int a t t s e r v e r c a n s e n d p a c k e t n o w ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f ATT EVENT CAN SEND NOW as soon as
possible
∗ @note ATT EVENT CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o t h i s
function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗ @param c o n h a n d l e
∗/
void a t t s e r v e r r e q u e s t c a n s e n d n o w e v e n t ( h c i c o n h a n d l e t
con handle ) ;
// end o f d e p r e c a t e d f u n c t i o n s

1.6. ANCS Client API. ancs client.h


285

void a n c s c l i e n t i n i t ( void ) ;
void a n c s c l i e n t r e g i s t e r c a l l b a c k ( btstack packet handler t c a l l b a c k
);
const char ∗ a n c s c l i e n t a t t r i b u t e n a m e f o r i d ( int i d ) ;

1.7. Battery Service Client API. battery service client.h

/∗ ∗
∗ @brief I n i t i a l i z e Battery Service .
∗/
void b a t t e r y s e r v i c e c l i e n t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Connect t o B a t t e r y S e r v i c e s o f remote d e v i c e . The c l i e n t
w i l l try to r e g i s t e r for n o t i f i c a t i o n s .
∗ I f n o t i f i c a t i o n s a r e not s u p p o r t e d by remote B a t t e r y S e r v i c e , t h e
client will poll battery level
∗ I f p o l l i n t e r v a l m s i s 0 , p o l l i n g i s d i s a b l e d , and o n l y
n o t i f i c a t i o n s w i l l be r e c e i v e d .
∗ In e i t h e r case , t h e b a t t e r y l e v e l i s r e c e i v e d v i a
GATTSERVICE SUBEVENT BATTERY SERVICE LEVEL e v e n t .
∗ The b a t t e r y l e v e l i s r e p o r t e d as p e r c e n t a g e , i . e . 100 = f u l l and
i t i s v a l i d i f t h e ATTT s t a t u s i s e q u a l t o ATT ERROR SUCCESS,
∗ s e e ATT e r r o r s ( s e e b l u e t o o t h . h ) f o r o t h e r v a l u e s .

∗ For manual p o l l i n g , s e e b a t t e r y s e r v i c e c l i e n t r e a d b a t t e r y l e v e l
below .

∗ Event GATTSERVICE SUBEVENT BATTERY SERVICE CONNECTED i s e m i t t e d
w i t h s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
∗ GATT CLIENT IN WRONG STATE,
ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no b a t t e r y
s e r v i c e i s found , or ATT e r r o r s ( s e e b l u e t o o t h . h ) .
∗ This e v e n t e v e n t a l s o r e t u r n s number o f b a t t e r y i n s t a n c e s found
on remote s e r v e r , as w e l l as p o l l bitmap t h a t i n d i c a t e s which
indexes
∗ o f s e r v i c e s r e q u i r e p o l l i n g , i . e . t h e y do not s u p p o r t
n o t i f i c a t i o n on b a t t e r y l e v e l change ,

∗ @param c o n h a n d l e
∗ @param p a c k e t h a n d l e r
∗ @param p o l l i n t e r v a l m s or 0 t o d i s a b l e p o l l i n g
∗ @param b a t t e r y s e r v i c e c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE COMMAND DISALLOWED i f t h e r e i s a l r e a d y a c l i e n t
a s s o c i a t e d w i t h c o n h a n d l e , or BTSTACK MEMORY ALLOC FAILED
∗/
uint8 t b a t t e r y s e r v i c e c l i e n t c o n n e c t ( h c i c o n h a n d l e t c o n h a n d l e ,
btstack packet handler t p a c k e t h a n d l e r , uint32 t
p o l l i n t e r v a l m s , uint16 t ∗ b a t t e r y s e r v i c e c i d ) ;
286

/∗ ∗
∗ @ b r i e f Read b a t t e r y l e v e l f o r s e r v i c e w i t h g i v e n i n d e x . Event
GATTSERVICE SUBEVENT BATTERY SERVICE LEVEL i s
∗ r e c e i v e d w i t h b a t t e r y l e v e l ( u n i t i s i n p e r c e n t a g e , i . e . 100 =
f u l l ) . The b a t t e r y l e v e l i s v a l i d i f t h e ATTT s t a t u s
∗ i s e q u a l t o ATT ERROR SUCCESS, s e e ATT e r r o r s ( s e e b l u e t o o t h . h )
for other values .
∗ @param b a t t e r y s e r v i c e c i d
∗ @param s e r v i c e i n d e x
∗ @return s t a t u s
∗/
uint8 t b a t t e r y s e r v i c e c l i e n t r e a d b a t t e r y l e v e l ( uint16 t
b a t t e r y s e r v i c e c i d , uint8 t s e r v i c e i n d e x ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t from B a t t e r y S e r v i c e .
∗ @param b a t t e r y s e r v i c e c i d
∗ @return s t a t u s
∗/
uint8 t b a t t e r y s e r v i c e c l i e n t d i s c o n n e c t ( uint16 t
battery service cid ) ;

/∗ ∗
∗ @ b r i e f De− i n i t i a l i z e B a t t e r y S e r v i c e .
∗/
void b a t t e r y s e r v i c e c l i e n t d e i n i t ( void ) ;

1.8. Battery Service Server API. battery service server.h

/∗ ∗
∗ @ b r i e f I n i t B a t t e r y S e r v i c e S e r v e r w i t h ATT DB
∗ @param b a t t e r y v a l u e i n range 0−100
∗/
void b a t t e r y s e r v i c e s e r v e r i n i t ( uint8 t b a t t e r y v a l u e ) ;

/∗ ∗
∗ @ b r i e f Update b a t t e r y v a l u e
∗ @note t r i g g e r s n o t i f i c a t i o n s i f s u b s c r i b e d
∗ @param b a t t e r y v a l u e i n range 0−100
∗/
void b a t t e r y s e r v i c e s e r v e r s e t b a t t e r y v a l u e ( uint8 t b a t t e r y v a l u e )
;

1.9. Bond Management Service Server API. bond management service server.h

#define BOND MANAGEMENT CONTROL POINT OPCODE NOT SUPPORTED 0 x80


#define BOND MANAGEMENT OPERATION FAILED 0 x81

#define BMF DELETE ACTIVE BOND CLASSIC AND LE 0


x00001
287

#define BMF DELETE ACTIVE BOND CLASSIC AND LE WITH AUTH 0


x00002
#define BMF DELETE ACTIVE BOND CLASSIC 0
x00004
#define BMF DELETE ACTIVE BOND CLASSIC WITH AUTH 0
x00008
#define BMF DELETE ACTIVE BOND LE 0
x00010
#define BMF DELETE ACTIVE BOND LE WITH AUTH 0
x00020
#define BMF DELETE ALL BONDS CLASSIC AND LE 0
x00040
#define BMF DELETE ALL BONDS CLASSIC AND LE WITH AUTH 0
x00080
#define BMF DELETE ALL BONDS CLASSIC 0
x00100
#define BMF DELETE ALL BONDS CLASSIC WITH AUTH 0
x00200
#define BMF DELETE ALL BONDS LE 0
x00400
#define BMF DELETE ALL BONDS LE WITH AUTH 0
x00800
#define BMF DELETE ALL BUT ACTIVE BOND CLASSIC AND LE 0
x01000
#define BMF DELETE ALL BUT ACTIVE BOND CLASSIC AND LE WITH AUTH 0
x02000
#define BMF DELETE ALL BUT ACTIVE BOND CLASSIC 0
x04000
#define BMF DELETE ALL BUT ACTIVE BOND CLASSIC WITH AUTH 0
x08000
#define BMF DELETE ALL BUT ACTIVE BOND LE 0
x10000
#define BMF DELETE ALL BUT ACTIVE BOND LE WITH AUT 0
x20000

typedef enum {
BOND MANAGEMENT CMD DELETE ACTIVE BOND CLASSIC AND LE = 0 x01 ,
BOND MANAGEMENT CMD DELETE ACTIVE BOND CLASSIC,
BOND MANAGEMENT CMD DELETE ACTIVE BOND LE,
BOND MANAGEMENT CMD DELETE ALL BONDS CLASSIC AND LE,
BOND MANAGEMENT CMD DELETE ALL BONDS CLASSIC,
BOND MANAGEMENT CMD DELETE ALL BONDS LE,
BOND MANAGEMENT CMD DELETE ALL BUT ACTIVE BOND CLASSIC AND LE,
BOND MANAGEMENT CMD DELETE ALL BUT ACTIVE BOND CLASSIC,
BOND MANAGEMENT CMD DELETE ALL BUT ACTIVE BOND LE
} bond management cmd t ;

/∗ ∗
∗ @ b r i e f I n i t Bond Management S e r v i c e w i t h ATT DB
∗ @param s u p p o r t e d f e a t u r e s
∗/
void b o n d m a n a g e m e n t s e r v i c e s e r v e r i n i t ( uint32 t s u p p o r t e d f e a t u r e s
);
288

/∗ ∗
∗ @brief Set a u t h o r i s a t i o n s t r i n g
∗ @note S t r i n g i s not c o p i e d
∗ @param a u t h o r i s a t i o n s t r i n g
∗/
void b o n d m a n a g e m e n t s e r v i c e s e r v e r s e t a u t h o r i s a t i o n s t r i n g ( const
char ∗ a u t h o r i s a t i o n s t r i n g ) ;

1.10. Cycling Power Service Server API. cycling power service server.h

#define CYCLING POWER MANUFACTURER SPECIFIC DATA MAX SIZE 16

typedef enum {
CP PEDAL POWER BALANCE REFERENCE UNKNOWN = 0 ,
CP PEDAL POWER BALANCE REFERENCE LEFT,
CP PEDAL POWER BALANCE REFERENCE NOT SUPPORTED
} cycling power pedal power balance reference t ;

typedef enum {
CP TORQUE SOURCE WHEEL = 0 ,
CP TORQUE SOURCE CRANK,
CP TORQUE SOURCE NOT SUPPORTED
} cycling power torque source t ;

typedef enum {
CP SENSOR MEASUREMENT CONTEXT FORCE = 0 ,
CP SENSOR MEASUREMENT CONTEXT TORQUE
} cycling power sensor measurement context t ;

typedef enum {
CP DISTRIBUTED SYSTEM UNSPECIFIED = 0 ,
CP DISTRIBUTED SYSTEM NOT SUPPORTED,
CP DISTRIBUTED SYSTEM SUPPORTED
} cycling power distributed system t ;

typedef enum {
CP MEASUREMENT FLAG PEDAL POWER BALANCE PRESENT = 0 ,
CP MEASUREMENT FLAG PEDAL POWER BALANCE REFERENCE, // 0 −
unknown , 1 − l e f t
CP MEASUREMENT FLAG ACCUMULATED TORQUE PRESENT,
CP MEASUREMENT FLAG ACCUMULATED TORQUE SOURCE, // 0 − w h e e l
based , 1 − crank b a s e d
CP MEASUREMENT FLAG WHEEL REVOLUTION DATA PRESENT,
CP MEASUREMENT FLAG CRANK REVOLUTION DATA PRESENT,
CP MEASUREMENT FLAG EXTREME FORCE MAGNITUDES PRESENT,
CP MEASUREMENT FLAG EXTREME TORQUE MAGNITUDES PRESENT,
CP MEASUREMENT FLAG EXTREME ANGLES PRESENT,
CP MEASUREMENT FLAG TOP DEAD SPOT ANGLE PRESENT,
CP MEASUREMENT FLAG BOTTOM DEAD SPOT ANGLE PRESENT,
CP MEASUREMENT FLAG ACCUMULATED ENERGY PRESENT,
CP MEASUREMENT FLAG OFFSET COMPENSATION INDICATOR,
CP MEASUREMENT FLAG RESERVED
289

} cycling power measurement flag t ;

typedef enum {
CP INSTANTANEOUS MEASUREMENT DIRECTION UNKNOWN = 0 ,
CP INSTANTANEOUS MEASUREMENT DIRECTION TANGENTIAL COMPONENT,
CP INSTANTANEOUS MEASUREMENT DIRECTION RADIAL COMPONENT,
CP INSTANTANEOUS MEASUREMENT DIRECTION LATERAL COMPONENT
} cycling power instantaneous measurement direction t ;

typedef enum {
CP VECTOR FLAG CRANK REVOLUTION DATA PRESENT = 0 ,
CP VECTOR FLAG FIRST CRANK MEASUREMENT ANGLE PRESENT,
CP VECTOR FLAG INSTANTANEOUS FORCE MAGNITUDE ARRAY PRESENT,
CP VECTOR FLAG INSTANTANEOUS TORQUE MAGNITUDE ARRAY PRESENT,
CP VECTOR FLAG INSTANTANEOUS MEASUREMENT DIRECTION = 4 , // 2 b i t
CP VECTOR FLAG RESERVED = 6
} cycling power vector flag t ;

typedef enum {
CP SENSOR LOCATION OTHER,
CP SENSOR LOCATION TOP OF SHOE,
CP SENSOR LOCATION IN SHOE ,
CP SENSOR LOCATION HIP ,
CP SENSOR LOCATION FRONT WHEEL,
CP SENSOR LOCATION LEFT CRANK,
CP SENSOR LOCATION RIGHT CRANK,
CP SENSOR LOCATION LEFT PEDAL,
CP SENSOR LOCATION RIGHT PEDAL,
CP SENSOR LOCATION FRONT HUB,
CP SENSOR LOCATION REAR DROPOUT,
CP SENSOR LOCATION CHAINSTAY,
CP SENSOR LOCATION REAR WHEEL,
CP SENSOR LOCATION REAR HUB,
CP SENSOR LOCATION CHEST,
CP SENSOR LOCATION SPIDER ,
CP SENSOR LOCATION CHAIN RING ,
CP SENSOR LOCATION RESERVED
} cycling power sensor location t ;

typedef enum {
CP FEATURE FLAG PEDAL POWER BALANCE SUPPORTED = 0 ,
CP FEATURE FLAG ACCUMULATED TORQUE SUPPORTED,
CP FEATURE FLAG WHEEL REVOLUTION DATA SUPPORTED,
CP FEATURE FLAG CRANK REVOLUTION DATA SUPPORTED,
CP FEATURE FLAG EXTREME MAGNITUDES SUPPORTED,
CP FEATURE FLAG EXTREME ANGLES SUPPORTED,
CP FEATURE FLAG TOP AND BOTTOM DEAD SPOT ANGLE SUPPORTED,
CP FEATURE FLAG ACCUMULATED ENERGY SUPPORTED,
CP FEATURE FLAG OFFSET COMPENSATION INDICATOR SUPPORTED,
CP FEATURE FLAG OFFSET COMPENSATION SUPPORTED,
CP FEATURE FLAG CYCLING POWER MEASUREMENT CHARACTERISTIC CONTENT MASKING SUPPORT
,
CP FEATURE FLAG MULTIPLE SENSOR LOCATIONS SUPPORTED,
CP FEATURE FLAG CRANK LENGTH ADJUSTMENT SUPPORTED,
290

CP FEATURE FLAG CHAIN LENGTH ADJUSTMENT SUPPORTED,


CP FEATURE FLAG CHAIN WEIGHT ADJUSTMENT SUPPORTED,
CP FEATURE FLAG SPAN LENGTH ADJUSTMENT SUPPORTED,
CP FEATURE FLAG SENSOR MEASUREMENT CONTEXT, // 0− f o r c e based , 1−
torque based
CP FEATURE FLAG INSTANTANEOUS MEASUREMENT DIRECTION SUPPORTED,
CP FEATURE FLAG FACTORY CALIBRATION DATE SUPPORTED,
CP FEATURE FLAG ENHANCED OFFSET COMPENSATION SUPPORTED,
CP FEATURE FLAG DISTRIBUTED SYSTEM SUPPORT = 2 0 , // 0−
u n s p e c i f i e d , 1−not f o r use i n d i s t r . system , 2−used i n d i s t r
. system , 3− r e s e r v e d
CP FEATURE FLAG RESERVED = 22
} cycling power feature flag t ;

typedef enum {
CP CALIBRATION STATUS INCORRECT CALIBRATION POSITION = 0 x01 ,
CP CALIBRATION STATUS MANUFACTURER SPECIFIC ERROR FOLLOWS = 0xFF
} cycling power calibration status t ;

/∗ ∗
∗ @ b r i e f I n i t S e r v e r w i t h ATT DB

∗ @param f e a t u r e f l a g s
∗ @param p e d a l p o w e r b a l a n c e r e f e r e n c e
∗ @param t o r q u e s o u r c e
∗ @param s u p p o r t e d s e n s o r l o c a t i o n s
∗ @param n u m s u p p o r t e d s e n s o r l o c a t i o n s
∗ @param c u r r e n t s e n s o r l o c a t i o n
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r i n i t ( uint32 t f e a t u r e f l a g s ,
cycling power pedal power balance reference t

pedal power balance reference


,
cycling power torque source t
torque source ,
cycling power sensor location t

supported sensor locations
, uint16 t
num supported sensor locations
,
cycling power sensor location t
current sensor location )
;

/∗ ∗
∗ @ b r i e f S e tu p measurement as a d v e r t i s e m e n t d a t a
∗ @param a d v i n t e r v a l
∗ @param a d v b u f f e r
∗ @param a d v s i z e
∗ @return
∗/
291

int c y c l i n g p o w e r g e t m e a s u r e m e n t a d v ( uint16 t a d v i n t e r v a l , uint8 t


∗ a d v b u f f e r , uint16 t a d v s i z e ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e c a l i b r a t i o n and b r o a d c a s t
updates .

∗ @param c a l l b a c k
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r p a c k e t h a n d l e r (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f Report c a l i b r a t i o n done .
∗ @param measurement type
∗ @param c a l i b r a t e d v a l u e
∗/
void c y c l i n g p o w e r s e r v e r c a l i b r a t i o n d o n e (
c y c l i n g p o w e r s e n s o r m e a s u r e m e n t c o n t e x t t measurement type ,
uint16 t c a l i b r a t e d v a l u e ) ;

/∗ ∗
∗ @ b r i e f Report enhanced c a l i b r a t i o n done .

∗ @param measurement type
∗ @param c a l i b r a t e d v a l u e
∗ @param m a n u f a c t u r e r c o m p a n y i d
∗ @param n u m m a n u f a c t u r e r s p e c i f i c d a t a
∗ @param m a n u f a c t u r e r s p e c i f i c d a t a
∗/
void c y c l i n g p o w e r s e r v e r e n h a n c e d c a l i b r a t i o n d o n e (
c y c l i n g p o w e r s e n s o r m e a s u r e m e n t c o n t e x t t measurement type ,
uint16 t
calibrated value
, uint16 t
manufacturer company id
,
uint8 t
num manufacturer specific dat
, uint8 t ∗
manufacturer specific data
);

/∗ ∗
∗ @brief Set f a c t o r y c a l i b r a t i o n date .
∗ @param d a t e
∗ @return 1 i f s u c c e s s f u l
∗/
int c y c l i n g p o w e r s e r v i c e s e r v e r s e t f a c t o r y c a l i b r a t i o n d a t e (
g a t t d a t e t i m e t date ) ;

/∗ ∗
∗ @brief Set sampling rate .
∗ @param s a m p l i n g r a t e H z
292

∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t s a m p l i n g r a t e ( uint8 t
sampling rate Hz ) ;

/∗ ∗
∗ @ b r i e f Accumulate t o r q u e v a l u e .
∗ @param torque Nm
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r a d d t o r q u e ( i n t 1 6 t torque Nm ) ;

/∗ ∗
∗ @ b r i e f Accumulate w h e e l r e v o l u t i o n v a l u e and s e t t h e time o f t h e
l a s t measurement .
∗ @param w h e e l r e v o l u t i o n
∗ @param w h e e l e v e n t t i m e s u n i t : s e c o n d s
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r a d d w h e e l r e v o l u t i o n ( i n t 3 2 t
w h e e l r e v o l u t i o n , uint16 t w h e e l e v e n t t i m e s ) ;

/∗ ∗
∗ @ b r i e f Accumulate crank r e v o l u t i o n v a l u e and s e t t h e time o f t h e
l a s t measurement .
∗ @param c r a n k r e v o l u t i o n
∗ @param c r a n k e v e n t t i m e s u n i t : s e c o n d s
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r a d d c r a n k r e v o l u t i o n ( uint16 t
c r a n k r e v o l u t i o n , uint16 t c r a n k e v e n t t i m e s ) ;

/∗ ∗
∗ @ b r i e f Accumulate e n e r g y .
∗ @param e n e r g y k J u n i t : k i l o J o u l e
∗/
void c y c l i n g p o w e r s e r v i c e a d d e n e r g y ( uint16 t e n e r g y k J ) ;

/∗ ∗
∗ @ b r i e f S e t t h e v a l u e o f t h e power . The I n s t a n t a n e o u s Power f i e l d
represents either
∗ t h e t o t a l power t h e u s e r i s p r o d u c i n g or a p a r t o f t h e t o t a l
power d e p e n d i n g on t h e
∗ t y p e o f s e n s o r ( e . g . , s i n g l e s e n s o r or d i s t r i b u t e d power s e n s o r
system ) .

∗ @param i n s t a n t a n e o u s p o w e r W u n i t : w a t t
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t i n s t a n t a n e o u s p o w e r ( i n t 1 6 t
instantaneous power W ) ;

/∗ ∗
∗ @ b r i e f S e t t h e p e d a l power b a l a n c e v a l u e . The Pedal Power Balance
f i e l d r e p r e s e n t s the r a t i o between
∗ t h e t o t a l amount o f power measured by t h e s e n s o r and a r e f e r e n c e
( e i t h e r unknown or l e f t ) .

∗ @param p e d a l p o w e r b a l a n c e p e r c e n t a g e
293

∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t p e d a l p o w e r b a l a n c e ( uint8 t
pedal power balance percentage ) ;

/∗ ∗
∗ @ b r i e f S e t t h e minimum and maximum f o r c e v a l u e measured i n a
s i n g l e crank r e v o l u t i o n .

∗ This , so c a l l e d , Extreme Force Magnitude f i e l d p a i r w i l l be
i n c l u d e d i n t h e C y c l i n g Power Measurement
∗ c h a r a c t e r i s t i c o n l y i f t h e d e v i c e s u p p o r t s t h e Extreme Magnitudes
f e a t u r e and
∗ t h e Sensor Measurement C o n t e x t o f t h e C y c l i n g Power F e a t u r e
c h a r a c t e r i s t i c i s s e t t o 0 ( Force−b a s e d ) .

∗ @param m i n f o r c e m a g n i t u d e N u n i t : newton
∗ @param m a x f o r c e m a g n i t u d e N u n i t : newton
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t f o r c e m a g n i t u d e ( i n t 1 6 t
min force magnitude N , i n t 1 6 t max force magnitude N ) ;

/∗ ∗
∗ @ b r i e f S e t t h e minimum and maximum t o r q u e v a l u e measured i n a
s i n g l e crank r e v o l u t i o n .

∗ This , so c a l l e d , Extreme Torque Magnitude f i e l d p a i r w i l l be
i n c l u d e d i n t h e C y c l i n g Power Measurement
∗ c h a r a c t e r i s t i c o n l y i f t h e d e v i c e s u p p o r t s t h e Extreme Magnitudes
f e a t u r e and
∗ t h e Sensor Measurement C o n t e x t o f t h e C y c l i n g Power F e a t u r e
c h a r a c t e r i s t i c i s s e t t o 1 ( Torque−b a s e d ) .

∗ @param min torque magnitude Nm u n i t : newton meter
∗ @param max torque magnitude Nm u n i t : newton meter
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t t o r q u e m a g n i t u d e ( i n t 1 6 t
min torque magnitude Nm , i n t 1 6 t max torque magnitude Nm ) ;

/∗ ∗
∗ @ b r i e f S e t t h e minimum and maximum a n g l e o f t h e crank measured i n
a s i n g l e crank r e v o l u t i o n ( u n i t : d e g r e e ) .

∗ This , so c a l l e d , Extreme A n g l e s Magnitude f i e l d p a i r w i l l be
i n c l u d e d i n t h e C y c l i n g Power Measurement
∗ c h a r a c t e r i s t i c o n l y i f t h e d e v i c e s u p p o r t s t h e Extreme A n g l e s
feature .

∗ @param m i n a n g l e d e g r e e
∗ @param m a x a n g l e d e g r e e
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t a n g l e ( uint16 t
m i n a n g l e d e g r e e , uint16 t m a x a n g l e d e g r e e ) ;

/∗ ∗
294

∗ @ b r i e f S e t t h e v a l u e o f t h e crank a n g l e measured when t h e v a l u e


o f t h e I n s t a n t a n e o u s Power v a l u e becomes p o s i t i v e .

∗ This f i e l d w i l l be i n c l u d e d i n t h e C y c l i n g Power Measurement
characteristic
∗ o n l y i f t h e d e v i c e s u p p o r t s t h e Top and Bottom Dead Spot A n g l e s
feature .

∗ @param t o p d e a d s p o t a n g l e d e g r e e
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t t o p d e a d s p o t a n g l e ( uint16 t
top dead spot angle degree ) ;

/∗ ∗
∗ @ b r i e f S e t t h e v a l u e o f t h e crank a n g l e measured when t h e v a l u e
o f t h e I n s t a n t a n e o u s Power v a l u e becomes n e g a t i v e .

∗ This f i e l d w i l l be i n c l u d e d i n t h e C y c l i n g Power Measurement
characteristic
∗ o n l y i f t h e d e v i c e s u p p o r t s t h e Top and Bottom Dead Spot A n g l e s
feature .

∗ @param b o t t o m d e a d s p o t a n g l e d e g r e e
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t b o t t o m d e a d s p o t a n g l e (
uint16 t b o t t o m d e a d s p o t a n g l e d e g r e e ) ;

/∗ ∗
∗ @ b r i e f S e t t h e raw s e n s o r f o r c e magnitude measurements .

∗ @param f o r c e m a g n i t u d e c o u n t
∗ @param f o r c e m a g n i t u d e N a r r a y u n i t : newton
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t f o r c e m a g n i t u d e v a l u e s ( int
force magnitude count , int16 t ∗ force magnitude N array ) ;

/∗ ∗
∗ @ b r i e f S e t t h e raw s e n s o r t o r q u e magnitude measurements .

∗ @param f o r c e m a g n i t u d e c o u n t
∗ @param f o r c e m a g n i t u d e N a r r a y u n i t : newton meter
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t t o r q u e m a g n i t u d e v a l u e s ( int
torque magnitude count , i n t 1 6 t ∗ torque magnitude Nm array ) ;

/∗ ∗
∗ @ b r i e f S e t t h e i n s t a n t a n e o u s measurement d i r e c t i o n . The f i e l d
describes
∗ t h e d i r e c t i o n o f t h e I n s t a n t a n e o u s Magnitude v a l u e s t h e S e r v e r
measures
∗ ( e . g . , Unknown , T a n g e n t i a l Component , R a d i a l Component , or
L a t e r a l Component ) .

∗ @param d i r e c t i o n
295

∗/
void
cycling power service server set instantaneous measurement direction
( cycling power instantaneous measurement direction t direction ) ;

/∗ ∗
∗ S e t f i r s t crank measurement a n g l e . The v a l u e w i l l be p r e s e n t o n l y
in the f i r s t packet of
∗ t h e C y c l i n g Power Vector n o t i f i c a t i o n .

∗ @param f i r s t c r a n k m e a s u r e m e n t a n g l e d e g r e e
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r s e t f i r s t c r a n k m e a s u r e m e n t a n g l e (
uint16 t f i r s t c r a n k m e a s u r e m e n t a n g l e d e g r e e ) ;

/∗ ∗
∗ Get measurement f l a g s b i t m a s k .
∗ @return m e a s u r e m e n t f l a g s b i t m a s k , s e e
cycling power measurement flag t
∗/
uint16 t c y c l i n g p o w e r s e r v i c e m e a s u r e m e n t f l a g s ( void ) ;

/∗ ∗
∗ Get v e c t o r f l a g s b i t m a s k .
∗ @return v e c t o r f l a g s b i t m a s k , s e e c y c l i n g p o w e r v e c t o r f l a g t
∗/
uint8 t c y c l i n g p o w e r s e r v i c e v e c t o r f l a g s ( void ) ;

/∗ ∗
∗ @brief Trigger n o t i f i c a t i o n i f subscribed
∗/
void c y c l i n g p o w e r s e r v i c e s e r v e r u p d a t e v a l u e s ( void ) ;

1.11. Cycling Speed and Cadence Service Server API. cycling speed and cadence servic

typedef enum {
CSC SERVICE SENSOR LOCATION OTHER = 0 ,
CSC SERVICE SENSOR LOCATION TOP OF SHOE ,
CSC SERVICE SENSOR LOCATION IN SHOE ,
CSC SERVICE SENSOR LOCATION HIP ,
CSC SERVICE SENSOR LOCATION FRONT WHEEL,
CSC SERVICE SENSOR LOCATION LEFT CRANK,
CSC SERVICE SENSOR LOCATION RIGHT CRANK,
CSC SERVICE SENSOR LOCATION LEFT PEDAL ,
CSC SERVICE SENSOR LOCATION RIGHT PEDAL,
CSC SERVICE SENSOR LOCATION FRONT HUB,
CSC SERVICE SENSOR LOCATION REAR DROPOUT,
CSC SERVICE SENSOR LOCATION CHAINSTAY,
CSC SERVICE SENSOR LOCATION REAR WHEEL,
CSC SERVICE SENSOR LOCATION REAR HUB,
CSC SERVICE SENSOR LOCATION CHEST,
CSC SERVICE SENSOR LOCATION SPIDER ,
296

CSC SERVICE SENSOR LOCATION CHAIN RING ,


CSC SERVICE SENSOR LOCATION RESERVED
} cycling speed and cadence sensor location t ;

typedef enum {
CSC FLAG WHEEL REVOLUTION DATA SUPPORTED = 0 ,
CSC FLAG CRANK REVOLUTION DATA SUPPORTED,
CSC FLAG MULTIPLE SENSOR LOCATIONS SUPPORTED
} csc feature flag bit t ;

typedef enum {
CSC OPCODE IDLE = 0 ,
CSC OPCODE SET CUMULATIVE VALUE = 1 ,
CSC OPCODE START SENSOR CALIBRATION,
CSC OPCODE UPDATE SENSOR LOCATION,
CSC OPCODE REQUEST SUPPORTED SENSOR LOCATIONS,
CSC OPCODE RESPONSE CODE = 16
} csc opcode t ;

/∗ ∗
∗ @ b r i e f I n i t S e r v e r w i t h ATT DB
∗/
void c y c l i n g s p e e d a n d c a d e n c e s e r v i c e s e r v e r i n i t ( uint32 t
supported sensor locations ,
uint8 t m u l t i p l e s e n s o r l o c a t i o n s s u p p o r t e d , uint8 t
w h e e l r e v o l u t i o n d a t a s u p p o r t e d , uint8 t
crank revolution data supported ) ;

/∗ ∗
∗ @ b r i e f Update h e a r t r a t e ( u n i t : b e a t s p e r minute )
∗ @note t r i g g e r s n o t i f i c a t i o n s i f s u b s c r i b e d
∗/
void c y c l i n g s p e e d a n d c a d e n c e s e r v i c e s e r v e r u p d a t e v a l u e s ( i n t 3 2 t
w h e e l r e v o l u t i o n s , uint16 t l a s t w h e e l e v e n t t i m e , uint16 t
c r a n k r e v o l u t i o n s , uint16 t l a s t c r a n k e v e n t t i m e ) ;

1.12. Device Information Service Client API. device information service client.h

/∗ ∗
∗ @ b r i e f I n i t i a l i z e D e vi c e I n f o r m a t i o n S e r v i c e .
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e c l i e n t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Query D ev i c e I n f o r m a t i o n S e r v i c e . The c l i e n t w i l l q u e r y
t h e remote s e r v i c e and emit e v e n t s :

∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION MANUFACTURER NAME
∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION MODEL NUMBER
∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION SERIAL NUMBER
∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION HARDWARE REVISION
∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION FIRMWARE REVISION
297

∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION SOFTWARE REVISION


∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION SYSTEM ID
∗ −
GATTSERVICE SUBEVENT DEVICE INFORMATION IEEE REGULATORY CERTIFICATION

∗ − GATTSERVICE SUBEVENT DEVICE INFORMATION PNP ID



∗ Event GATTSERVICE SUBEVENT DEVICE INFORMATION DONE i s r e c e i v e d
when a l l q u e r i e s a r e done , o f i f s e r v i c e was not found .
∗ The s t a t u s f i e l d o f t h i s e v e n t i n d i c a t e d ATT e r r o r s ( s e e
bluetooth . h) .

∗ @param c o n h a n d l e
∗ @param p a c k e t h a n d l e r
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
GATT CLIENT IN WRONG STATE i f q u e r y i s a l r e a d y i n p r o g r e s s
∗/
uint8 t d e v i c e i n f o r m a t i o n s e r v i c e c l i e n t q u e r y ( h c i c o n h a n d l e t
c o n h a n d l e , btstack packet handler t p a c k e t h a n d l e r ) ;

/∗ ∗
∗ @ b r i e f De− i n i t i a l i z e D e vi c e I n f o r m a t i o n S e r v i c e .
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e c l i e n t d e i n i t ( void ) ;

1.13. Device Information Service Server API. device information service server.h

/∗ ∗
∗ @ t e x t Th e D e v i c e I n f o r m a t i o n S e r v i c e a l l o w s t o q u e r y m a n u f a c t u r e r
and/ or
∗ vendor i n f o r m a t i o n a b o u t a d e v i c e .

∗ To use w i t h your a p p l i c a t i o n , add ‘# i m p o rt <
d e v i c e i n f o r m a t i o n s e r v i c e . g a t t >‘ t o your . g a t t f i l e .

∗ ∗ Note ∗ : i n s t e a d o f c a l l i n g a l l s e t t e r s , you can c r e a t e a l o c a l
copy o f t h e . g a t t f i l e and remove
∗ a l l C h a r a c t e r i s t i c s t h a t a r e not r e l e v a n t f o r your a p p l i c a t i o n
and d e f i n e a l l f i x e d v a l u e s i n t h e . g a t t f i l e .
∗/

/∗ ∗
∗ @ b r i e f I n i t D ev i c e I n f o r m a t i o n S e r v i c e S e r v e r w i t h ATT DB
∗ @param b a t t e r y v a l u e i n range 0−100
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f S e t Manufacturer Name
∗ @param manufacturer name
∗/
298

void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t m a n u f a c t u r e r n a m e ( const
char ∗ manufacturer name ) ;

/∗ ∗
∗ @ b r i e f S e t Model Number
∗ @param model number
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t m o d e l n u m b e r ( const char ∗
model number ) ;

/∗ ∗
∗ @ b r i e f S e t S e r i a l Number
∗ @param s e r i a l n u m b e r
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t s e r i a l n u m b e r ( const char
∗ serial number ) ;

/∗ ∗
∗ @ b r i e f S e t Hardware R e v i s i o n
∗ @param h a r d w a r e r e v i s i o n
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t h a r d w a r e r e v i s i o n ( const
char ∗ h a r d w a r e r e v i s i o n ) ;

/∗ ∗
∗ @ b r i e f S e t Firmware R e v i s i o n
∗ @param f i r m w a r e r e v i s i o n
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t f i r m w a r e r e v i s i o n ( const
char ∗ f i r m w a r e r e v i s i o n ) ;

/∗ ∗
∗ @brief Set Software Revision
∗ @param s o f t w a r e r e v i s i o n
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t s o f t w a r e r e v i s i o n ( const
char ∗ s o f t w a r e r e v i s i o n ) ;

/∗ ∗
∗ @ b r i e f S e t System ID
∗ @param m a n u f a c t u r e r i d e n t i f i e r u i n t 4 0
∗ @param o r g a n i z a t i o n a l l y u n i q u e i d e n t i f i e r u i n t 2 4
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t s y s t e m i d ( u i n t 6 4 t
m a n u f a c t u r e r i d e n t i f i e r , uint32 t
organizationally unique identifier ) ;

/∗ ∗
∗ @ b r i e f S e t IEEE 11073 −20601 r e g u l a t o r y c e r t i f i c a t i o n d a t a l i s t
∗ @note : f o r ma t d u i n t 1 6 . d u i n t 1 6 i s two u i n t 1 6 v a l u e s c o n c a t e n a t e d
together .
∗ @param v a l u e a
∗ @param v a l u e b
∗/
299

void
device information service server set ieee regulatory certification
( uint16 t v a l u e a , uint16 t v a l u e b ) ;

/∗ ∗
∗ @ b r i e f S e t PnP ID
∗ @param v e n d o r s o u r c e i d
∗ @param v e n d o r i d
∗ @param p r o d u c t i d
∗ @Param p r o d u c t v e r s o i n
∗/
void d e v i c e i n f o r m a t i o n s e r v i c e s e r v e r s e t p n p i d ( uint8 t
v e n d o r s o u r c e i d , uint16 t v e n d o r i d , uint16 t p r o d u c t i d ,
uint16 t p r o d u c t v e r s i o n ) ;

1.14. Heart Rate Service Server API. heart rate service server.h

typedef enum {
HEART RATE SERVICE BODY SENSOR LOCATION OTHER = 0 ,
HEART RATE SERVICE BODY SENSOR LOCATION CHEST,
HEART RATE SERVICE BODY SENSOR LOCATION WRIST,
HEART RATE SERVICE BODY SENSOR LOCATION FINGER,
HEART RATE SERVICE BODY SENSOR LOCATION HAND,
HEART RATE SERVICE BODY SENSOR LOCATION EAR LOBE,
HEART RATE SERVICE BODY SENSOR LOCATION FOOT
} heart rate service body sensor location t ;

typedef enum {
HEART RATE SERVICE SENSOR CONTACT UNKNOWN = 0 ,
HEART RATE SERVICE SENSOR CONTACT UNSUPPORTED,
HEART RATE SERVICE SENSOR CONTACT NO CONTACT,
HEART RATE SERVICE SENSOR CONTACT HAVE CONTACT
} heart rate service sensor contact status t ;

/∗ ∗
∗ @ b r i e f I n i t B a t t e r y S e r v i c e S e r v e r w i t h ATT DB
∗ @param b o d y s e n s o r l o c a t i o n
∗ @param e n e r g y e x p e n d e d s u p p o r t e d
∗/
void h e a r t r a t e s e r v i c e s e r v e r i n i t (
heart rate service body sensor location t body sensor location ,
int e n e r g y e x p e n d e d s u p p o r t e d ) ;

/∗ ∗
∗ @ b r i e f Add Energy Expended t o t h e i n t e r n a l a c c u m u l a t o r .
∗ @param e n e r g y e x p e n d e d k J e n e r g y expended i n k i l o J o u l e s s i n c e
the l a s t update
∗/
void h e a r t r a t e s e r v i c e a d d e n e r g y e x p e n d e d ( uint16 t
energy expended kJ ) ;
300

/∗ ∗
∗ @ b r i e f Update h e a r t r a t e ( u n i t : b e a t s p e r minute )
∗ @note t r i g g e r s n o t i f i c a t i o n s i f s u b s c r i b e d
∗ @param h e a r t r a t e b p m b e a t s p e r minute
∗ @param c o n t a c t
∗ @param r r i n t e r v a l c o u n t
∗ @param r r i n t e r v a l s r e s o l u t i o n i n 1/1024 s e c o n d s
∗/
void h e a r t r a t e s e r v i c e s e r v e r u p d a t e h e a r t r a t e v a l u e s ( uint16 t
heart rate bpm ,
h e a r t r a t e s e r v i c e s e n s o r c o n t a c t s t a t u s t c o n t a c t , int
r r i n t e r v a l c o u n t , uint16 t ∗ r r i n t e r v a l s ) ;

1.15. HID Service Client API. hids client.h

/∗ ∗
∗ @ b r i e f I n i t i a l i z e HID S e r v i c e C l i e n t . The HID D e s c r i p t o r s t o r a g e
i s shared between a l l connections .

∗ @param h i d d e s c r i p t o r s t o r a g e
∗ @param h i d d e s c r i p t o r s t o r a g e l e n
∗/
void h i d s c l i e n t i n i t ( uint8 t ∗ h i d d e s c r i p t o r s t o r a g e , uint16 t
hid descriptor storage len ) ;

/∗ ∗
∗ @ b r i e f Connect t o HID S e r v i c e s o f remote d e v i c e . Event
GATTSERVICE SUBEVENT HID SERVICE CONNECTED w i l l be e m i t t e d
∗ a f t e r a l l remote HID s e r v i c e s and c h a r a c t e r i s t i c s a r e found , and
n o t i f i c a t i o n s f o r a l l input r e p o r t s are enabled .
∗ S t a t u s code can be ERROR CODE SUCCES i f a t l e a s t one HID s e r v i c e
i s found , o t h e r w i s e e i t h e r ATT e r r o r s or
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no s e r v i c e
or r e p o r t map or r e p o r t a r e found .
∗ I t a l s o c o n t a i n s t h e number o f i n d i v i d u a l HIDS S e r v i c e s .

∗ @param c o n h a n d l e
∗ @param p a c k e t h a n d l e r
∗ @param p r o t o c o l m o d e s e e h i d p r o t o c o l m o d e t i n b t s t a c k h i d . h
∗ @param h i d s c i d ( o u t ) t o use f o r o t h e r f u n c t i o n s
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE COMMAND DISALLOWED i f t h e r e i s a l r e a d y a c l i e n t
∗ a s s o c i a t e d w i t h c o n h a n d l e , or
BTSTACK MEMORY ALLOC FAILED.
∗/
uint8 t h i d s c l i e n t c o n n e c t ( h c i c o n h a n d l e t c o n h a n d l e ,
btstack packet handler t p a c k e t h a n d l e r , h i d p r o t o c o l m o d e t
p r o t o c o l m o d e , uint16 t ∗ h i d s c i d ) ;

/∗ ∗
301

∗ @ b r i e f Send HID r e p o r t . Event


GATTSERVICE SUBEVENT HID REPORT WRITTEN i s e m i t t e d .

∗ @param h i d s c i d
∗ @param r e p o r t i d
∗ @param r e p o r t t y p e
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e ,
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found , or
∗ ERROR CODE PARAMETER OUT OF MANDATORY RANGE i f r e p o r t l e n g t h
e x c e e d s MTU.
∗/
uint8 t h i d s c l i e n t s e n d w r i t e r e p o r t ( uint16 t h i d s c i d , uint8 t
r e p o r t i d , h i d r e p o r t t y p e t r e p o r t t y p e , const uint8 t ∗ r e p o r t
, uint8 t r e p o r t l e n ) ;

/∗ ∗
∗ @ b r i e f Get HID r e p o r t . Event GATTSERVICE SUBEVENT HID REPORT i s
emitted .

∗ @param h i d s c i d
∗ @param r e p o r t i d
∗ @param r e p o r t t y p e
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e ,
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found , or
∗ ERROR CODE PARAMETER OUT OF MANDATORY RANGE i f r e p o r t l e n g t h
e x c e e d s MTU.
∗/
uint8 t h i d s c l i e n t s e n d g e t r e p o r t ( uint16 t h i d s c i d , uint8 t
report id , hid report type t report type ) ;

/∗ ∗
∗ @ b r i e f Get HID I n f o r m a t i o n . Event
GATTSERVICE SUBEVENT HID INFORMATION i s e m i t t e d .

∗ @param h i d s c i d
∗ @param s e r v i c e i n d e x
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e , or
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found .
∗/
uint8 t h i d s c l i e n t g e t h i d i n f o r m a t i o n ( uint16 t h i d s c i d , uint8 t
service index ) ;

/∗ ∗
302

∗ @ b r i e f Get P r o t o c o l Mode . Event


GATTSERVICE SUBEVENT HID PROTOCOL MODE i s e m i t t e d .

∗ @param h i d s c i d
∗ @param s e r v i c e i n d e x
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e , or
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found .
∗/
uint8 t h i d s c l i e n t g e t p r o t o c o l m o d e ( uint16 t h i d s c i d , uint8 t
service index ) ;

/∗ ∗
∗ @ b r i e f S e t P r o t o c o l Mode .

∗ @param h i d s c i d
∗ @param s e r v i c e i n d e x
∗ @param p r o t o c o l m o d e
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e , or
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found .
∗/
uint8 t h i d s c l i e n t s e n d s e t p r o t o c o l m o d e ( uint16 t h i d s c i d ,
uint8 t s e r v i c e i n d e x , h i d p r o t o c o l m o d e t p r o t o c o l m o d e ) ;

/∗ ∗
∗ @ b r i e f Send Suspend t o remote HID s e r v i c e .

∗ @param h i d s c i d
∗ @param s e r v i c e i n d e x
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e , or
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found .
∗/
uint8 t h i d s c l i e n t s e n d s u s p e n d ( uint16 t h i d s c i d , uint8 t
service index ) ;

/∗ ∗
∗ @ b r i e f Send E x i t Suspend t o remote HID s e r v i c e .

∗ @param h i d s c i d
∗ @param s e r v i c e i n d e x
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e , or
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f no r e p o r t
w i t h g i v e n t y p e and ID i s found .
∗/
303

uint8 t h i d s c l i e n t s e n d e x i t s u s p e n d ( uint16 t h i d s c i d , uint8 t


service index ) ;

/∗ ∗
∗ @ b r i e f Enable a l l n o t i f i c a t i o n s . Event
GATTSERVICE SUBEVENT HID SERVICE REPORTS NOTIFICATION r e p o r t s
current configuration .

∗ @param h i d s c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER, or
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e .
∗/
uint8 t h i d s c l i e n t e n a b l e n o t i f i c a t i o n s ( uint16 t h i d s c i d ) ;

/∗ ∗
∗ @ b r i e f D i s a b l e a l l n o t i f i c a t i o n s . Event
GATTSERVICE SUBEVENT HID SERVICE REPORTS NOTIFICATION r e p o r t s
current configuration .

∗ @param h i d s c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER, or
∗ ERROR CODE COMMAND DISALLOWED i f c l i e n t i s i n wrong s t a t e .
∗/
uint8 t h i d s c l i e n t d i s a b l e n o t i f i c a t i o n s ( uint16 t h i d s c i d ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t from HID S e r v i c e .

∗ @param h i d s c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER
∗/
uint8 t h i d s c l i e n t d i s c o n n e c t ( uint16 t h i d s c i d ) ;

/∗
∗ @ b r i e f Get d e s c r i p t o r d a t a . For s e r v i c e s i n b o o t mode w i t h o u t a
Report Map, a d e f a u l t HID D e s c r i p t o r f o r Keyboard /Mouse i s
provided .

∗ @param h i d c i d
∗ @return d a t a
∗/
const uint8 t ∗ h i d s c l i e n t d e s c r i p t o r s t o r a g e g e t d e s c r i p t o r d a t a (
uint16 t h i d s c i d , uint8 t s e r v i c e i n d e x ) ;

/∗
∗ @ b r i e f Get d e s c r i p t o r l e n g t h

∗ @param h i d c i d
∗ @return l e n g t h
∗/
304

uint16 t h i d s c l i e n t d e s c r i p t o r s t o r a g e g e t d e s c r i p t o r l e n ( uint16 t
h i d s c i d , uint8 t s e r v i c e i n d e x ) ;

/∗ ∗
∗ @ b r i e f De− i n i t i a l i z e HID S e r v i c e C l i e n t .

∗/
void h i d s c l i e n t d e i n i t ( void ) ;

1.16. HID Service Server API. hids device.h

typedef struct {
uint16 t v a l u e h a n d l e ;
uint16 t c l i e n t c o n f i g u r a t i o n h a n d l e ;
uint16 t c l i e n t c o n f i g u r a t i o n v a l u e ;

h i d r e p o r t t y p e t type ;
uint8 t i d ;
uint8 t s i z e ;
} hids device report t ;

/∗ ∗
∗ @ t e x t I m p l e m e n t a t i o n o f t h e GATT HIDS De v i ce
∗ To use w i t h your a p p l i c a t i o n , add ’# i m p o rt <h i d s . g a t t >’ t o your .
gatt f i l e
∗/

/∗ ∗
∗ @ b r i e f S e t up HIDS D e v ic e w i t h s i n g l e INPUT, OUTPUT and FEATURE
report
∗/
void h i d s d e v i c e i n i t ( uint8 t h i d c o u n t r y c o d e , const uint8 t ∗
h i d d e s c r i p t o r , uint16 t h i d d e s c r i p t o r s i z e ) ;

/∗ ∗
∗ @ b r i e f S e t up HIDS D e v ic e f o r m u l t i p l e i n s t a n c e s o f INPUT, OUTPUT
and FEATURE r e p o r t s
∗/
void h i d s d e v i c e i n i t w i t h s t o r a g e ( uint8 t h i d c o u n t r y c o d e , const
uint8 t ∗ h i d d e s c r i p t o r , uint16 t h i d d e s c r i p t o r s i z e ,
uint16 t num reports , h i d s d e v i c e r e p o r t t ∗ r e p o r t s t o r a g e ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e HIDS De v i ce c l i e n t .
∗ @param c a l l b a c k
∗/
void h i d s d e v i c e r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r r e p o r t c a l l b a c k f o r Get Report o p e r a t i o n
∗ @param c a l l b a c k
305

∗/
void h i d s d e v i c e r e g i s t e r g e t r e p o r t c a l l b a c k ( void ( ∗ c a l l b a c k ) (
h c i c o n h a n d l e t con handle , h i d r e p o r t t y p e t report type ,
uint16 t r e p o r t i d , uint16 t m a x r e p o r t s i z e , uint8 t ∗
out report ) ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t can send now e v e n t t o send HID Report
∗ G e n e r a t e s an HIDS SUBEVENT CAN SEND NOW s u b e v e n t
∗ @param h i d c i d
∗/
void h i d s d e v i c e r e q u e s t c a n s e n d n o w e v e n t ( h c i c o n h a n d l e t
con handle ) ;

/∗ ∗
∗ @ b r i e f Send HID I n p u t Report f o r Report ID
∗ @param c o n h a n d l e
∗ @param r e p o r t i d
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @returns s t a t u s
∗/
uint8 t h i d s d e v i c e s e n d i n p u t r e p o r t f o r i d ( h c i c o n h a n d l e t
c o n h a n d l e , uint16 t r e p o r t i d , const uint8 t ∗ r e p o r t , uint16 t
report len ) ;

/∗ ∗
∗ @ b r i e f Send HID I n p u t Report f o r f i r s t I n p u t Report
∗ @param c o n h a n d l e
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @returns s t a t u s
∗/
uint8 t h i d s d e v i c e s e n d i n p u t r e p o r t ( h c i c o n h a n d l e t c o n h a n d l e ,
const uint8 t ∗ r e p o r t , uint16 t r e p o r t l e n ) ;

/∗ ∗
∗ @ b r i e f Send HID Boot Mouse I n p u t Report
∗ @param c o n h a n d l e
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @returns s t a t u s
∗/
uint8 t h i d s d e v i c e s e n d b o o t m o u s e i n p u t r e p o r t ( h c i c o n h a n d l e t
c o n h a n d l e , const uint8 t ∗ r e p o r t , uint16 t r e p o r t l e n ) ;

/∗ ∗
∗ @ b r i e f Send HID Boot Mouse I n p u t Report
∗ @param c o n h a n d l e
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @returns s t a t u s
∗/
306

uint8 t h i d s d e v i c e s e n d b o o t k e y b o a r d i n p u t r e p o r t ( h c i c o n h a n d l e t
c o n h a n d l e , const uint8 t ∗ r e p o r t , uint16 t r e p o r t l e n ) ;

1.17. Nordic SPP Service Server API. nordic spp service server.h

/∗ ∗
∗ @ t e x t The Nordic SPP S e r v i c e i s i m p l e m e n t a t i o n o f t h e Nordic SPP−
like profile .

∗ To use w i t h your a p p l i c a t i o n , add ‘# i m p o rt <n o r d i c s p p s e r v i c e .
g a t t >‘ t o your . g a t t f i l e
∗ and c a l l a l l f u n c t i o n s b e l o w . A l l s t r i n g s and b l o b s need t o s t a y
valid aft er c a l l i n g the functions .
∗/

/∗ ∗
∗ @ b r i e f I n i t Nordic SPP S e r v i c e S e r v e r w i t h ATT DB
∗ @param p a c k e t h a n d l e r f o r e v e n t s and t x d a t a from p e e r as
RFCOMM DATA PACKET
∗/
void n o r d i c s p p s e r v i c e s e r v e r i n i t ( btstack packet handler t
packet handler ) ;

/∗ ∗
∗ @ b r i e f Queue send r e q u e s t . When c a l l e d , one p a c k e t can be send
via n o r d i c s p p s e r v i c e s e n d below
∗ @param r e q u e s t
∗ @param c o n h a n d l e
∗/
void n o r d i c s p p s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w (
b t s t a c k c o n t e x t c a l l b a c k r e g i s t r a t i o n t ∗ request ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f Send d a t a
∗ @param c o n h a n d l e
∗ @param d a t a
∗ @param s i z e
∗/
int n o r d i c s p p s e r v i c e s e r v e r s e n d ( h c i c o n h a n d l e t c o n h a n d l e ,
const uint8 t ∗ data , uint16 t s i z e ) ;

1.18. Scan Parameters Service Client API. scan parameters service client.h

/∗ ∗
∗ @ b r i e f I n i t i a l i z e Scan Parameters S e r v i c e .
∗/
void s c a n p a r a m e t e r s s e r v i c e c l i e n t i n i t ( void ) ;

/∗ ∗
307

∗ @ b r i e f S e t Scan Parameters S e r v i c e . I t w i l l u p d a t e a l l c o n n e c t e d
devices .
∗ @param s c a n i n t e r v a l
∗ @param scan window
∗/
void s c a n p a r a m e t e r s s e r v i c e c l i e n t s e t ( uint16 t s c a n i n t e r v a l ,
uint16 t scan window ) ;

/∗ ∗
∗ @ b r i e f Connect t o Scan Parameters S e r v i c e o f remote d e v i c e .

∗ The GATTSERVICE SUBEVENT SCAN PARAMETERS SERVICE CONNECTED e v e n t
completes the request .
∗ I t s s t a t u s i s s e t t o ERROR CODE SUCCESS i f remote s e r v i c e and
SCAN INTERVAL WINDOW c h a r a c t e r i s t i c a r e found .
∗ Other s t a t u s c o d e s o f t h i s e v e n t :
∗ − GATT CLIENT IN WRONG STATE : c l i e n t i n wrong s t a t e
∗ − ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE: s e r v i c e or
c h a r a c t e r i s t i c not found
∗ − ATT e r r o r s , s e e b l u e t o o t h . h

∗ @param c o n h a n d l e
∗ @param p a c k e t h a n d l e r
∗ @param s c a n p a r a m e t e r s c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c l i e n t w i t h
c o n h a n d l e not found
∗/
uint8 t s c a n p a r a m e t e r s s e r v i c e c l i e n t c o n n e c t ( h c i c o n h a n d l e t
c o n h a n d l e , btstack packet handler t p a c k e t h a n d l e r , uint16 t ∗
scan parameters cid ) ;

/∗ ∗
∗ @ b r i e f Enable n o t i f i c a t i o n s
∗ @param s c a n p a r a m e t e r s c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c l i e n t w i t h
c o n h a n d l e i s not found
∗/
uint8 t s c a n p a r a m e t e r s s e r v i c e c l i e n t e n a b l e n o t i f i c a t i o n s ( uint16 t
scan parameters cid ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t from Scan Parameters S e r v i c e .
∗ @param s c a n p a r a m e t e r s c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c l i e n t w i t h
c o n h a n d l e i s not found
∗/
uint8 t s c a n p a r a m e t e r s s e r v i c e c l i e n t d i s c o n n e c t ( uint16 t
scan parameters cid ) ;

/∗ ∗
308

∗ @ b r i e f De− i n i t i a l i z e Scan Parameters S e r v i c e .


∗/
void s c a n p a r a m e t e r s s e r v i c e c l i e n t d e i n i t ( void ) ;

1.19. Scan Parameters Service Server API. scan parameters service server.h

/∗ ∗
∗ @ t e x t The Scan Parameters S e r v i c e e n a b l e s a remote GATT C l i e n t t o
s t o r e t h e LE scan p a r a m e t e r s i t i s u s i n g l o c a l l y . These
p a r a m e t e r s can be u t i l i z e d by t h e a p p l i c a t i o n t o o p t i m i z e power
consumption and/ or r e c o n n e c t i o n l a t e n c y .

∗ To use w i t h your a p p l i c a t i o n , add ‘# i m p o rt <
s c a n p a r a m e t e r s s e r v i c e . g a t t >‘ t o your . g a t t f i l e
∗ and c a l l a l l f u n c t i o n s b e l o w . A l l s t r i n g s and b l o b s need t o s t a y
valid aft er c a l l i n g the functions .
∗/

/∗ ∗
∗ @brief I n i t Scan Parameters S e r v i c e S e r v e r w i t h ATT DB
∗ @param packet handler
∗/
void s c a n p a r a m e t e r s s e r v i c e s e r v e r i n i t ( btstack packet handler t
packet handler ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t scan p a r a m e t e r s from Scan Parameters C l i e n t .
∗/
void s c a n p a r a m e t e r s s e r v i c e s e r v e r r e q u e s t s c a n p a r a m e t e r s ( void ) ;

1.20. TX Power Service Server API. tx power service server.h

/∗ ∗
∗ @ b r i e f I n i t TX Power S e r v i c e S e r v e r w i t h ATT DB
∗ @param t x p o w e r l e v e l
∗/
void t x p o w e r s e r v i c e s e r v e r i n i t ( i n t 8 t t x p o w e r l e v e l ) ;

/∗ ∗
∗ @ b r i e f Update TX power l e v e l
∗ @param t x p o w e r l e v e l d B m range [ −100 ,20]
∗/
void t x p o w e r s e r v i c e s e r v e r s e t l e v e l ( i n t 8 t t x p o w e r l e v e l d B m ) ;

1.21. u-blox SPP Service Server API. ublox spp service server.h

/∗ ∗
309

∗ @ t e x t The u−b l o x SPP S e r v i c e i s i m p l e m e n t a t i o n o f t h e u−Blox SPP−


like profile .

∗ To use w i t h your a p p l i c a t i o n , add ‘# i m p o rt <u b l o x s p p s e r v i c e .
g a t t >‘ t o your . g a t t f i l e
∗ and c a l l a l l f u n c t i o n s b e l o w . A l l s t r i n g s and b l o b s need t o s t a y
valid aft er c a l l i n g the functions .
∗/

/∗ ∗
∗ @ b r i e f I n i t u b l o x SPP S e r v i c e S e r v e r w i t h ATT DB
∗ @param p a c k e t h a n d l e r f o r e v e n t s and t x d a t a from p e e r as
RFCOMM DATA PACKET
∗/
void u b l o x s p p s e r v i c e s e r v e r i n i t ( btstack packet handler t
packet handler ) ;

/∗ ∗
∗ @ b r i e f Queue send r e q u e s t . When c a l l e d , one p a c k e t can be send
via u b l o x s p p s e r v i c e s e n d below
∗ @param r e q u e s t
∗ @param c o n h a n d l e
∗/
void u b l o x s p p s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w (
b t s t a c k c o n t e x t c a l l b a c k r e g i s t r a t i o n t ∗ request ,
hci con handle t con handle ) ;

/∗ ∗
∗ @brief Send d a t a
∗ @param con handle
∗ @param data
∗ @param size
∗/
int u b l o x s p p s e r v i c e s e r v e r s e n d ( h c i c o n h a n d l e t c o n h a n d l e , const
uint8 t ∗ data , uint16 t s i z e ) ;

1.22. GATT Client API. gatt client.h

typedef struct {
uint16 t s t a r t g r o u p h a n d l e ;
uint16 t e n d g r o u p h a n d l e ;
uint16 t uuid16 ;
uint8 t uuid128 [ 1 6 ] ;
} gatt client service t ;

typedef struct {
uint16 t s t a r t h a n d l e ;
uint16 t v a l u e h a n d l e ;
uint16 t e n d h a n d l e ;
uint16 t p r o p e r t i e s ;
uint16 t uuid16 ;
uint8 t uuid128 [ 1 6 ] ;
310

} gatt client characteristic t ;

typedef struct {
uint16 t h a n d l e ;
uint16 t uuid16 ;
uint8 t uuid128 [ 1 6 ] ;
} gatt client characteristic descriptor t ;

/∗ ∗
∗ @ b r i e f S e t up GATT c l i e n t .
∗/
void g a t t c l i e n t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f S e t minimum r e q u i r e d s e c u r i t y l e v e l f o r GATT C l i e n t
∗ @note The B l u e t o o t h s p e c i f i c a t i o n makes t h e GATT S e r v e r
r e s p o n s i b l e to check for s e c u r i t y .
∗ This a l l o w s an a t t a c k e r t o s p o o f an e x i s t i n g d e v i c e w i t h a
GATT S e r v e r s , b u t s k i p t h e a u t h e n t i c a t i o n p a r t .
∗ I f your a p p l i c a t i o n i s e x c h a n g i n g s e n s i t i v e d a t a w i t h a
remote d e v i c e , you would need t o manually c h e c k
∗ t h e s e c u r i t y l e v e l b e f o r e s e n d i n g / r e c e i v e such d a t a .
∗ With l e v e l > 0 , t h e GATT C l i e n t t r i g g e r s a u t h e n t i c a t i o n
f o r a l l GATT R e q u e s t s and d e f e r s any e x c h a n g e
∗ u n t i l the required security l e v e l i s e s t a b l i s h e d .
∗ g a t t c l i e n t r e q u e s t c a n w r i t e w i t h o u t r e s p o n s e e v e n t does
not t r i g g e r a u t h e n t i c a t i o n
∗ g a t t c l i e n t r e q u e s t t o w r i t e w i t h o u t r e s p o n s e d o e s not
trigger authentication
∗ @pram l e v e l , d e f a u l t LEVEL 0 ( no e n c r y p t i o n r e q u i r e d )
∗/
void g a t t c l i e n t s e t r e q u i r e d s e c u r i t y l e v e l ( g a p s e c u r i t y l e v e l t
level ) ;

/∗ ∗
∗ @ b r i e f Connect t o remote GATT S e r v e r o v e r C l a s s i c (BR/EDR)
Connection
∗ GATT EVENT CONNECTED w i t h s t a t u s and c o n h a n d l e f o r o t h e r
API f u n c t i o n s
∗ i s e m i t t e d on c o n n e c t i o n c o m p l e t e .
∗ @note r e q u i r e s ENABLE GATT OVER CLASSIC .
∗ @param addr
∗ @return s t a t u s
∗/
uint8 t g a t t c l i e n t c l a s s i c c o n n e c t ( btstack packet handler t
c a l l b a c k , bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t o C l a s s i c (BR/EDR) c o n n e c t i o n t o a remote GATT
Server
∗ @note r e q u i r e s ENABLE GATT OVER CLASSIC
∗ @param c o n h a n d l e
∗ @return s t a t u s
∗/
311

uint8 t g a t t c l i e n t c l a s s i c d i s c o n n e c t ( btstack packet handler t


callback , hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f S e tu p Enhanced LE Bearer w i t h up t o 5 c h a n n e l s on e x i s t i n g
LE c o n n e c t i o n
∗ @param c a l l b a c k f o r GATT EVENT CONNECTED and
GATT EVENT DISCONNECTED e v e n t s
∗ @param c o n h a n d l e
∗ @param num channels
∗ @param s t o r a g e b u f f e r f o r L2CAP c o n n e c t i o n
∗ @param s t o r a g e s i z e − each c h a n n e l r e q u i r e s (2 ∗ ATT MTU) + 10
bytes
∗ @return
∗/
uint8 t g a t t c l i e n t l e e n h a n c e d c o n n e c t ( btstack packet handler t
c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e , uint8 t num channels ,
uint8 t ∗ s t o r a g e b u f f e r , uint16 t s t o r a g e s i z e ) ;

/∗ ∗
∗ @ b r i e f MTU i s a v a i l a b l e a f t e r t h e f i r s t q u e r y has c o m p l e t e d . I f
s t a t u s i s e q u a l t o ERROR CODE SUCCESS, i t r e t u r n s t h e r e a l
value ,
∗ o t h e r w i s e t h e d e f a u l t v a l u e ATT DEFAULT MTU ( s e e b l u e t o o t h . h ) .
∗ @param c o n h a n d l e
∗ @param mtu
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f MTU i s not e x c h a n g e d and MTU
auto−e x c h a n g e i s d i s a b l e d
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t g e t m t u ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t ∗
mtu ) ;

/∗ ∗
∗ @ b r i e f S e t s w h e t h e r a MTU Exchange R e q u e s t s h a l l be a u t o m a t i c a l l y
send b e f o r e t h e
∗ f i r s t a t t r i b u t e r ead r e q u e s t i s send . D e f a u l t i s e n a b l e d .
∗ @param e n a b l e d
∗/
void g a t t c l i e n t m t u e n a b l e a u t o n e g o t i a t i o n ( uint8 t e n a b l e d ) ;

/∗ ∗
∗ @ b r i e f Sends a MTU Exchange Request , t h i s a l l o w s f o r t h e c l i e n t
t o e x c h a n g e MTU
∗ when g a t t c l i e n t m t u e n a b l e a u t o n e g o t i a t i o n i s d i s a b l e d .
∗ @param c a l l b a c k
312

∗ @param c o n h a n d l e
∗/
void g a t t c l i e n t s e n d m t u n e g o t i a t i o n ( btstack packet handler t
callback , hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f Returns 1 i f t h e GATT c l i e n t i s r e a d y t o r e c e i v e a q u e r y .
I t i s used w i t h daemon .
∗ @param c o n h a n d l e
∗ @return i s r e a d y s t a t u s 0 − i f no GATT c l i e n t f o r c o n h a n d l e
i s found , or i s not ready , o t h e r w i s e 1
∗/
int g a t t c l i e n t i s r e a d y ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f D i s c o v e r s a l l primary s e r v i c e s .
∗ For each found s e r v i c e a GATT EVENT SERVICE QUERY RESULT e v e n t
w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r p r i m a r y s e r v i c e s (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @brief Discovers a l l secondary s e r v i c e s .
∗ For each found s e r v i c e a GATT EVENT SERVICE QUERY RESULT e v e n t
w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r s e c o n d a r y s e r v i c e s (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f D i s c o v e r s a s p e c i f i c primary s e r v i c e g i v e n i t s UUID . This
s e r v i c e may e x i s t m u l t i p l e t i m e s .
∗ For each found s e r v i c e a GATT EVENT SERVICE QUERY RESULT e v e n t
w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
313

∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param uuid16
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r p r i m a r y s e r v i c e s b y u u i d 1 6 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t uuid16 ) ;

/∗ ∗
∗ @ b r i e f D i s c o v e r s a s p e c i f i c primary s e r v i c e g i v e n i t s UUID . This
s e r v i c e may e x i s t m u l t i p l e t i m e s .
∗ For each found s e r v i c e a GATT EVENT SERVICE QUERY RESULT e v e n t
w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param uuid128
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r p r i m a r y s e r v i c e s b y u u i d 1 2 8 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
const uint8 t ∗ uuid128 ) ;

/∗ ∗
∗ @ b r i e f Finds i n c l u d e d s e r v i c e s w i t h i n t h e s p e c i f i e d s e r v i c e .
∗ For each found i n c l u d e d s e r v i c e a
GATT EVENT INCLUDED SERVICE QUERY RESULT e v e n t w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ I n f o r m a t i o n a b o u t i n c l u d e d s e r v i c e t y p e ( primary / s e c o n d a r y ) can
be r e t r i e v e d e i t h e r by s e n d i n g
∗ an ATT f i n d i n f o r m a t i o n r e q u e s t f o r t h e r e t u r n e d s t a r t group
handle
∗ ( r e t u r n i n g t h e h a n d l e and t h e UUID f o r primary or s e c o n d a r y
s e r v i c e ) or by comparing t h e s e r v i c e
∗ t o t h e l i s t o f a l l primary s e r v i c e s .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s e r v i c e
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
314

∗ ERROR CODE SUCCESS , i f query i s


successfully registered
∗/
uint8 t g a t t c l i e n t f i n d i n c l u d e d s e r v i c e s f o r s e r v i c e (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client service t ∗ s e r v i c e ) ;

/∗ ∗
∗ @brief Discovers a l l c h a r a c t e r i s t i c s within the s p e c i f i e d service
.
∗ For each found c h a r a c t e r i s t i c a
GATT EVENT CHARACTERISTIC QUERY RESULT e v e n t w i l l be e m i t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s e r v i c e
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r c h a r a c t e r i s t i c s f o r s e r v i c e (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client service t ∗ s e r v i c e ) ;

/∗ ∗
∗ @ b r i e f The f o l l o w i n g f o u r f u n c t i o n s a r e used t o d i s c o v e r a l l
characteristics within
∗ t h e s p e c i f i e d s e r v i c e or h a n d l e range , and r e t u r n t h o s e t h a t
match t h e g i v e n UUID .

∗ For each found c h a r a c t e r i s t i c a
GATT EVENT CHARACTERISTIC QUERY RESULT e v e n t w i l l e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid16
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t
gatt client discover characteristics for handle range by uuid16 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t uuid16 ) ;

/∗ ∗
315

∗ @ b r i e f The f o l l o w i n g f o u r f u n c t i o n s a r e used t o d i s c o v e r a l l
c h a r a c t e r i s t i c s within the
∗ s p e c i f i e d s e r v i c e or h a n d l e range , and r e t u r n t h o s e t h a t match
t h e g i v e n UUID .
∗ For each found c h a r a c t e r i s t i c a
GATT EVENT CHARACTERISTIC QUERY RESULT e v e n t w i l l e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid128
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t
gatt client discover characteristics for handle range by uuid128
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , const uint8 t ∗
uuid128 ) ;

/∗ ∗
∗ @ b r i e f The f o l l o w i n g f o u r f u n c t i o n s a r e used t o d i s c o v e r a l l
c h a r a c t e r i s t i c s within the
∗ s p e c i f i e d s e r v i c e or h a n d l e range , and r e t u r n t h o s e t h a t match
t h e g i v e n UUID .
∗ For each found c h a r a c t e r i s t i c a
GATT EVENT CHARACTERISTIC QUERY RESULT e v e n t w i l l e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s e r v i c e
∗ @param uuid16
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r c h a r a c t e r i s t i c s f o r s e r v i c e b y u u i d 1 6 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
g a t t c l i e n t s e r v i c e t ∗ s e r v i c e , uint16 t uuid16 ) ;

/∗ ∗
∗ @ b r i e f The f o l l o w i n g f o u r f u n c t i o n s a r e used t o d i s c o v e r a l l
c h a r a c t e r i s t i c s within the
∗ s p e c i f i e d s e r v i c e or h a n d l e range , and r e t u r n t h o s e t h a t match
t h e g i v e n UUID .
316

∗ For each found c h a r a c t e r i s t i c a


GATT EVENT CHARACTERISTIC QUERY RESULT e v e n t w i l l e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s e r v i c e
∗ @param uuid128
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r c h a r a c t e r i s t i c s f o r s e r v i c e b y u u i d 1 2 8 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
g a t t c l i e n t s e r v i c e t ∗ s e r v i c e , const uint8 t ∗ uuid128 ) ;

/∗ ∗
∗ @ b r i e f D i s c o v e r s a t t r i b u t e h a n d l e and UUID o f a c h a r a c t e r i s t i c
descriptor within the s p e c i f i e d c h a r a c t e r i s t i c .
∗ For each found d e s c r i p t o r a
GATT EVENT ALL CHARACTERISTIC DESCRIPTORS QUERY RESULT e v e n t
w i l l be e m i t t e d .

∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f d i s c o v e r y .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param c h a r a c t e r i s t i c
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t d i s c o v e r c h a r a c t e r i s t i c d e s c r i p t o r s (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client characteristic t ∗ c h a r a c t e r i s t i c ) ;

/∗ ∗
∗ @ b r i e f Reads t h e c h a r a c t e r i s t i c v a l u e u s i n g t h e c h a r a c t e r i s t i c ’ s
value handle .
∗ I f t h e c h a r a c t e r i s t i c v a l u e i s found a
GATT EVENT CHARACTERISTIC VALUE QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param c h a r a c t e r i s t i c
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
317

∗ ERROR CODE SUCCESS , i f query i s


successfully registered
∗/
uint8 t g a t t c l i e n t r e a d v a l u e o f c h a r a c t e r i s t i c (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client characteristic t ∗ c h a r a c t e r i s t i c ) ;

/∗ ∗
∗ @ b r i e f Reads t h e c h a r a c t e r i s t i c v a l u e u s i n g t h e c h a r a c t e r i s t i c ’ s
value handle .
∗ I f t h e c h a r a c t e r i s t i c v a l u e i s found a
GATT EVENT CHARACTERISTIC VALUE QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t r e a d v a l u e o f c h a r a c t e r i s t i c u s i n g v a l u e h a n d l e (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Reads t h e c h a r a c t e r i c v a l u e o f a l l c h a r a c t e r i s t i c s w i t h
the uuid .
∗ For each c h a r a c t e r i s t i c v a l u e found a
GATT EVENT CHARACTERISTIC VALUE QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid16
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t r e a d v a l u e o f c h a r a c t e r i s t i c s b y u u i d 1 6 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , uint16 t uuid16 ) ;

/∗ ∗
∗ @ b r i e f Reads t h e c h a r a c t e r i c v a l u e o f a l l c h a r a c t e r i s t i c s w i t h
the uuid .
318

∗ For each c h a r a c t e r i s t i c v a l u e found a


GATT EVENT CHARACTERISTIC VALUE QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param s t a r t h a n d l e
∗ @param e n d h a n d l e
∗ @param uuid128
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t r e a d v a l u e o f c h a r a c t e r i s t i c s b y u u i d 1 2 8 (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t s t a r t h a n d l e , uint16 t e nd h an dl e , const uint8 t ∗
uuid128 ) ;

/∗ ∗
∗ @ b r i e f Reads t h e l o n g c h a r a c t e r i s t i c v a l u e u s i n g t h e
c h a r a c t e r i s t i c ’ s value handle .
∗ The v a l u e w i l l be r e t u r n e d i n s e v e r a l b l o b s .
∗ For each b l o b , a
GATT EVENT LONG CHARACTERISTIC VALUE QUERY RESULT e v e n t w i t h
u p d a t e d v a l u e o f f s e t w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param c h a r a c t e r i s t i c
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t r e a d l o n g v a l u e o f c h a r a c t e r i s t i c (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client characteristic t ∗ c h a r a c t e r i s t i c ) ;

/∗ ∗
∗ @ b r i e f Reads t h e l o n g c h a r a c t e r i s t i c v a l u e u s i n g t h e
c h a r a c t e r i s t i c ’ s value handle .
∗ The v a l u e w i l l be r e t u r n e d i n s e v e r a l b l o b s .
∗ For each b l o b , a
GATT EVENT LONG CHARACTERISTIC VALUE QUERY RESULT e v e n t w i t h
u p d a t e d v a l u e o f f s e t w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
319

∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r


c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t
gatt client read long value of characteristic using value handle
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Reads t h e l o n g c h a r a c t e r i s t i c v a l u e u s i n g t h e
c h a r a c t e r i s t i c ’ s value handle .
∗ The v a l u e w i l l be r e t u r n e d i n s e v e r a l b l o b s .
∗ For each b l o b , a
GATT EVENT LONG CHARACTERISTIC VALUE QUERY RESULT e v e n t w i t h
u p d a t e d v a l u e o f f s e t w i l l be e m i t t e d .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param o f f s e t
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t
gatt client read long value of characteristic using value handle with offset
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e , uint16 t o f f s e t ) ;

/∗
∗ @ b r i e f Read m u l t i p l e c h a r a c t e r i s t i c v a l u e s .
∗ The a l l r e s u l t s a r e e m i t t e d v i a s i n g l e
GATT EVENT CHARACTERISTIC VALUE QUERY RESULT e v e n t ,
∗ f o l l o w e d by t h e GATT EVENT QUERY COMPLETE e v e n t , which marks t h e
end o f read .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param n u m v a l u e h a n d l e s
∗ @param v a l u e h a n d l e s l i s t o f h a n d l e s
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
320

uint8 t g a t t c l i e n t r e a d m u l t i p l e c h a r a c t e r i s t i c v a l u e s (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
int n u m v a l u e h a n d l e s , uint16 t ∗ v a l u e h a n d l e s ) ;

/∗
∗ @ b r i e f Read m u l t i p l e v a r a i b l e c h a r a c t e r i s t i c v a l u e s . Only
s u p p o r t e d o v e r LE Enhanced Bearer
∗ The a l l r e s u l t s a r e e m i t t e d v i a s i n g l e
GATT EVENT CHARACTERISTIC VALUE QUERY RESULT e v e n t ,
∗ f o l l o w e d by t h e GATT EVENT QUERY COMPLETE e v e n t , which marks t h e
end o f read .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param n u m v a l u e h a n d l e s
∗ @param v a l u e h a n d l e s l i s t o f h a n d l e s
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t r e a d m u l t i p l e v a r i a b l e c h a r a c t e r i s t i c v a l u e s (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
int n u m v a l u e h a n d l e s , uint16 t ∗ v a l u e h a n d l e s ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c v a l u e u s i n g t h e c h a r a c t e r i s t i c ’ s
value handle without
∗ an acknowledgment t h a t t h e w r i t e was s u c c e s s f u l l y performed .
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s c o p i e d on s u c c e s s and d o e s not need t o be
retained
∗ @return s t a t u s BTSTACK MEMORY ALLOC FAILED, i f no GATT c l i e n t f o r
c o n h a n d l e i s found
∗ GATT CLIENT IN WRONG STATE , i f GATT c l i e n t i s not
ready
∗ BTSTACK ACL BUFFERS FULL , i f L2CAP cannot send ,
t h e r e a r e no f r e e ACL s l o t s
∗ ERROR CODE SUCCESS , i f query i s
successfully registered
∗/
uint8 t g a t t c l i e n t w r i t e v a l u e o f c h a r a c t e r i s t i c w i t h o u t r e s p o n s e (
h c i c o n h a n d l e t c o n h a n d l e , uint16 t v a l u e h a n d l e , uint16 t
v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Writes t h e a u t h e n t i c a t e d c h a r a c t e r i s t i c v a l u e u s i n g t h e
c h a r a c t e r i s t i c ’ s value handle
∗ w i t h o u t an acknowledgment t h a t t h e w r i t e was s u c c e s s f u l l y
performed .
321

∗ @note GATT EVENT QUERY COMPLETE i s e m i t t e d w i t h ATT ERROR SUCCESS


for success ,
∗ or ATT ERROR BONDING INFORMATION MISSING i f t h e r e i s no b o n d i n g
information stored .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param m e s s a g e l e n
∗ @param message i s not c o p i e d , make s u r e memory i s a c c e s s i b l e
u n t i l w r i t e i s done
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t s i g n e d w r i t e w i t h o u t r e s p o n s e (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e , uint16 t m e s s a g e l e n , uint8 t ∗ message ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c v a l u e u s i n g t h e c h a r a c t e r i s t i c ’ s
value handle .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed , i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s set to
∗ ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t w r i t e v a l u e o f c h a r a c t e r i s t i c (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e , uint16 t v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
322

∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c v a l u e u s i n g t h e c h a r a c t e r i s t i c ’ s
value handle .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t w r i t e l o n g v a l u e o f c h a r a c t e r i s t i c (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e , uint16 t v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c v a l u e u s i n g t h e c h a r a c t e r i s t i c ’ s
value handle .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param o f f s e t o f v a l u e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
323

uint8 t g a t t c l i e n t w r i t e l o n g v a l u e o f c h a r a c t e r i s t i c w i t h o f f s e t (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e , uint16 t o f f s e t , uint16 t v a l u e l e n g t h ,
uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Writes o f t h e l o n g c h a r a c t e r i s t i c v a l u e u s i n g t h e
c h a r a c t e r i s t i c ’ s value handle .
∗ I t u s e s s e r v e r r e s p o n s e t o v a l i d a t e t h a t t h e w r i t e was c o r r e c t l y
received .
∗ The GATT EVENT QUERY COMPLETE EVENT marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed , i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param v a l u e h a n d l e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t r e l i a b l e w r i t e l o n g v a l u e o f c h a r a c t e r i s t i c (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t v a l u e h a n d l e , uint16 t v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Reads t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ I f t h e c h a r a c t e r i s t i c d e s c r i p t o r i s found , a
GATT EVENT CHARACTERISTIC DESCRIPTOR QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
324

∗/
uint8 t g a t t c l i e n t r e a d c h a r a c t e r i s t i c d e s c r i p t o r (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client characteristic descriptor t ∗ descriptor ) ;

/∗ ∗
∗ @ b r i e f Reads t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ I f t h e c h a r a c t e r i s t i c d e s c r i p t o r i s found , a
GATT EVENT CHARACTERISTIC DESCRIPTOR QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t
gatt client read characteristic descriptor using descriptor handle
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t d e s c r i p t o r h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Reads t h e l o n g c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
I t w i l l be r e t u r n e d i n s e v e r a l b l o b s .
∗ For each b l o b , a
GATT EVENT CHARACTERISTIC DESCRIPTOR QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t r e a d l o n g c h a r a c t e r i s t i c d e s c r i p t o r (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client characteristic descriptor t ∗ descriptor ) ;
325

/∗ ∗
∗ @ b r i e f Reads t h e l o n g c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
I t w i l l be r e t u r n e d i n s e v e r a l b l o b s .
∗ For each b l o b , a
GATT EVENT CHARACTERISTIC DESCRIPTOR QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r h a n d l e
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t
gatt client read long characteristic descriptor using descriptor handle
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t d e s c r i p t o r h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Reads t h e l o n g c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
I t w i l l be r e t u r n e d i n s e v e r a l b l o b s .
∗ For each b l o b , a
GATT EVENT CHARACTERISTIC DESCRIPTOR QUERY RESULT e v e n t w i l l be
emitted .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f rea d .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r h a n d l e
∗ @param o f f s e t
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t
gatt client read long characteristic descriptor using descriptor handle with offs
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t d e s c r i p t o r h a n d l e , uint16 t o f f s e t ) ;
326

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t w r i t e c h a r a c t e r i s t i c d e s c r i p t o r (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
g a t t c l i e n t c h a r a c t e r i s t i c d e s c r i p t o r t ∗ d e s c r i p t o r , uint16 t
v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r h a n d l e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
327

uint8 t
gatt client write characteristic descriptor using descriptor handle
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t d e s c r i p t o r h a n d l e , uint16 t v a l u e l e n g t h , uint8 t ∗
value ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t w r i t e l o n g c h a r a c t e r i s t i c d e s c r i p t o r (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
g a t t c l i e n t c h a r a c t e r i s t i c d e s c r i p t o r t ∗ d e s c r i p t o r , uint16 t
v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r h a n d l e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
328

∗ ERROR CODE SUCCESS


i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t
gatt client write long characteristic descriptor using descriptor handle
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t d e s c r i p t o r h a n d l e , uint16 t v a l u e l e n g t h , uint8 t ∗
value ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c h a r a c t e r i s t i c d e s c r i p t o r u s i n g i t s h a n d l e .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param d e s c r i p t o r h a n d l e
∗ @param o f f s e t o f v a l u e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t
gatt client write long characteristic descriptor using descriptor handle with off
( btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t d e s c r i p t o r h a n d l e , uint16 t o f f s e t , uint16 t
v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Writes t h e c l i e n t c h a r a c t e r i s t i c c o n f i g u r a t i o n o f t h e
specified characteristic .
∗ I t i s used t o s u b s c r i b e f o r n o t i f i c a t i o n s or i n d i c a t i o n s o f t h e
characteristic value .
∗ For n o t i f i c a t i o n s or i n d i c a t i o n s s p e c i f y :
GATT CLIENT CHARACTERISTICS CONFIGURATION NOTIFICATION
∗ r e s p . GATT CLIENT CHARACTERISTICS CONFIGURATION INDICATION as
configuration value .
∗ The GATT EVENT QUERY COMPLETE e v e n t marks t h e end o f w r i t e .
∗ The w r i t e i s s u c c e s s f u l l y performed i f t h e e v e n t ’ s a t t s t a t u s
f i e l d i s s e t t o ATT ERROR SUCCESS ( s e e b l u e t o o t h . h f o r
ATT ERROR c o d e s ) .
∗ @param c a l l b a c k
329

∗ @param con handle


∗ @param characteristic
∗ @param configuration

GATT CLIENT CHARACTERISTICS CONFIGURATION NOTIFICATION,


GATT CLIENT CHARACTERISTICS CONFIGURATION INDICATION
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER
i f no HCI c o n n e c t i o n f o r c o n h a n d l e i s found
∗ BTSTACK MEMORY ALLOC FAILED
i f no GATT c l i e n t f o r c o n h a n d l e
c o u l d be a l l o c a t e d
∗ GATT CLIENT IN WRONG STATE
i f GATT c l i e n t i s not r e a d y

GATT CLIENT CHARACTERISTIC NOTIFICATION NOT SUPPORTED if
c o n f i g u r i n g n o t i f i c a t i o n , b u t c h a r a c t e r i s t i c has no
n o t i f i c a t i o n property set

GATT CLIENT CHARACTERISTIC INDICATION NOT SUPPORTED if
c o n f i g u r i n g i n d i c a t i o n , b u t c h a r a c t e r i s t i c has no i n d i c a t i o n
property set
∗ ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE
i f configuration is invalid
∗ ERROR CODE SUCCESS
i f query i s s u c c e s s f u l l y
registered
∗/
uint8 t g a t t c l i e n t w r i t e c l i e n t c h a r a c t e r i s t i c c o n f i g u r a t i o n (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
g a t t c l i e n t c h a r a c t e r i s t i c t ∗ c h a r a c t e r i s t i c , uint16 t
configuration ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r f o r n o t i f i c a t i o n s and i n d i c a t i o n s o f a
c h a r a c t e r i s t i c e n a b l e d by
∗ the g a t t c l i e n t w r i t e c l i e n t c h a r a c t e r i s t i c c o n f i g u r a t i o n
function .
∗ @param n o t i f i c a t i o n s t r u c t used t o s t o r e r e g i s t r a t i o n
∗ @param c a l l b a c k
∗ @param c o n h a n d l e or GATT CLIENT ANY CONNECTION t o r e c e i v e
u p d a t e s from a l l c o n n e c t e d d e v i c e s
∗ @param c h a r a c t e r i s t i c or NULL t o r e c e i v e u p d a t e s f o r a l l
characteristics
∗/
void g a t t c l i e n t l i s t e n f o r c h a r a c t e r i s t i c v a l u e u p d a t e s (
gatt client notification t ∗ notification ,
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ,
gatt client characteristic t ∗ c h a r a c t e r i s t i c ) ;

/∗ ∗
∗ @ b r i e f Stop l i s t e n i n g t o c h a r a c t e r i s t i c v a l u e u p d a t e s r e g i s t e r e d
with
∗ the g a t t c l i e n t l i s t e n f o r c h a r a c t e r i s t i c v a l u e u p d a t e s function .
330

∗ @param n o t i f i c a t i o n s t r u c t used i n
gatt client listen for characteristic value updates
∗/
void g a t t c l i e n t s t o p l i s t e n i n g f o r c h a r a c t e r i s t i c v a l u e u p d a t e s (
gatt client notification t ∗ notification ) ;

/∗ ∗
∗ @ b r i e f T r a n s a c t i o n a l w r i t e . I t can be c a l l e d as many t i m e s as i t
i s needed t o w r i t e t h e c h a r a c t e r i s t i c s w i t h i n t h e same
transaction .
∗ C a l l t h e g a t t c l i e n t e x e c u t e w r i t e f u n c t i o n t o commit t h e
transaction .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @param a t t r i b u t e h a n d l e
∗ @param o f f s e t o f v a l u e
∗ @param v a l u e l e n g t h
∗ @param v a l u e i s not c o p i e d , make s u r e memory i s a c c e s s i b l e u n t i l
w r i t e i s done , i . e . GATT EVENT QUERY COMPLETE i s r e c e i v e d
∗/
uint8 t g a t t c l i e n t p r e p a r e w r i t e ( btstack packet handler t c a l l b a c k ,
h c i c o n h a n d l e t c o n h a n d l e , uint16 t a t t r i b u t e h a n d l e ,
uint16 t o f f s e t , uint16 t v a l u e l e n g t h , uint8 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f Commit t r a n s a c t i o n a l w r i t e . GATT EVENT QUERY COMPLETE i s
received .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @return s t a t u s
∗/
uint8 t g a t t c l i e n t e x e c u t e w r i t e ( btstack packet handler t c a l l b a c k ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f Abort t r a n s a c t i o n a l w r i t e . GATT EVENT QUERY COMPLETE i s
received .
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @return s t a t u s
∗/
uint8 t g a t t c l i e n t c a n c e l w r i t e ( btstack packet handler t c a l l b a c k ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c a l l b a c k when r e g u l a r g a t t q u e r y can be s e n t
∗ @note c a l l b a c k might happen d u r i n g c a l l t o t h i s f u n c t i o n
∗ @param c a l l b a c k r e g i s t r a t i o n t o p o i n t t o c a l l b a c k f u n c t i o n and
context information
∗ @param c o n h a n d l e
∗ @return ERROR CODE SUCCESS i f ok ,
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f h a n d l e unknown , and
ERROR CODE COMMAND DISALLOWED i f c a l l b a c k a l r e a d y r e g i s t e r e d
∗/
331

uint8 t g a t t c l i e n t r e q u e s t t o s e n d g a t t q u e r y (
btstack context callback registration t ∗ callback registration ,
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c a l l b a c k when w r i t i n g c h a r a c t e r i s t i c v a l u e w i t h o u t
response i s p o s s i b l e
∗ @note c a l l b a c k might happen d u r i n g c a l l t o t h i s f u n c t i o n
∗ @param c a l l b a c k r e g i s t r a t i o n t o p o i n t t o c a l l b a c k f u n c t i o n and
context information
∗ @param c o n h a n d l e
∗ @return ERROR CODE SUCCESS i f ok ,
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f h a n d l e unknown , and
ERROR CODE COMMAND DISALLOWED i f c a l l b a c k a l r e a d y r e g i s t e r e d
∗/
uint8 t g a t t c l i e n t r e q u e s t t o w r i t e w i t h o u t r e s p o n s e (
btstack context callback registration t ∗ callback registration ,
hci con handle t con handle ) ;

// t h e f o l l o w i n g f u n c t i o n s a r e marked as d e p r e c a t e d and w i l l be
removed e v e n t u a l l y
/∗ ∗
∗ @ b r i e f R e q u e s t s GATT EVENT CAN WRITE WITHOUT RESPONSE t h a t
guarantees
∗ a single successful
gatt client write value of characteristic without response call
.
∗ @ de pr e ca te d p l e a s e use
gatt client request to write without response instead
∗ @param c a l l b a c k
∗ @param c o n h a n d l e
∗ @return s t a t u s
∗/
uint8 t g a t t c l i e n t r e q u e s t c a n w r i t e w i t h o u t r e s p o n s e e v e n t (
btstack packet handler t c a l l b a c k , h c i c o n h a n d l e t c o n h a n d l e ) ;

1.23. Device Database API. le device db.h

/∗ ∗
∗ @brief i n i t
∗/
void l e d e v i c e d b i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f s e t s l o c a l bd addr . a l l o w s f o r db p e r B l u e t o o t h c o n t r o l l e r
∗ @param b d a d d r
∗/
void l e d e v i c e d b s e t l o c a l b d a d d r ( bd addr t bd addr ) ;

/∗ ∗
332

∗ @ b r i e f add d e v i c e t o db
∗ @param a d d r t y p e , a d d r e s s o f t h e d e v i c e
∗ @param i r k o f t h e d e v i c e
∗ @return i n d e x i f s u c c e s s f u l , −1 o t h e r w i s e
∗/
int l e d e v i c e d b a d d ( int a d d r t y p e , bd addr t addr , s m k e y t i r k ) ;

/∗ ∗
∗ @ b r i e f g e t number o f d e v i c e s i n db
∗ @return number o f d e v i c e i n db
∗/
int l e d e v i c e d b c o u n t ( void ) ;

/∗ ∗
∗ @ b r i e f g e t max number o f d e v i c e s i n db f o r enumeration
∗ @return max number o f d e v i c e i n db
∗/
int l e d e v i c e d b m a x c o u n t ( void ) ;

/∗ ∗
∗ @ b r i e f g e t d e v i c e i n f o r m a t i o n : addr t y p e and a d d r e s s needed t o
identify device
∗ @param i n d e x
∗ @param a d d r t y p e , a d d r e s s o f t h e d e v i c e as o u t p u t
∗ @param i r k o f t h e d e v i c e
∗/
void l e d e v i c e d b i n f o ( int index , int ∗ a d d r t y p e , bd addr t addr ,
sm key t i r k ) ;

/∗ ∗
∗ @ b r i e f s e t remote e n c r y p t i o n i n f o
∗ @brief index
∗ @brief ediv
∗ @ b r i e f rand
∗ @brief l t k
∗ @ b r i e f key s i z e
∗ @brief authenticated
∗ @brief authorized
∗ @breif secure connection
∗/
void l e d e v i c e d b e n c r y p t i o n s e t ( int index , uint16 t ediv , uint8 t
rand [ 8 ] , s m k e y t l t k , int k e y s i z e , int a u t h e n t i c a t e d , int
a u t h o r i z e d , int s e c u r e c o n n e c t i o n ) ;

/∗ ∗
∗ @brief g e t remote e n c r y p t i o n i n f o
∗ @brief index
∗ @brief ediv
∗ @brief rand
∗ @brief ltk
∗ @brief key s i z e
∗ @brief authenticated
∗ @brief authorized
333

∗ @breif secure connection


∗/
void l e d e v i c e d b e n c r y p t i o n g e t ( int index , uint16 t ∗ ediv , uint8 t
rand [ 8 ] , s m k e y t l t k , int ∗ k e y s i z e , int ∗ a u t h e n t i c a t e d ,
int ∗ a u t h o r i z e d , int ∗ s e c u r e c o n n e c t i o n ) ;

#i f d e f ENABLE LE SIGNED WRITE

/∗ ∗
∗ @ b r i e f s e t l o c a l s i g n i n g key f o r t h i s d e v i c e
∗ @param i n d e x
∗ @param s i g n i n g key as i n p u t
∗/
void l e d e v i c e d b l o c a l c s r k s e t ( int index , s m k e y t c s r k ) ;

/∗ ∗
∗ @ b r i e f g e t l o c a l s i g n i n g key f o r t h i s d e v i c e
∗ @param i n d e x
∗ @param s i g n i n g key as o u t p u t
∗/
void l e d e v i c e d b l o c a l c s r k g e t ( int index , s m k e y t c s r k ) ;

/∗ ∗
∗ @ b r i e f s e t remote s i g n i n g key f o r t h i s d e v i c e
∗ @param i n d e x
∗ @param s i g n i n g key as i n p u t
∗/
void l e d e v i c e d b r e m o t e c s r k s e t ( int index , s m k e y t c s r k ) ;

/∗ ∗
∗ @ b r i e f g e t remote s i g n i n g key f o r t h i s d e v i c e
∗ @param i n d e x
∗ @param s i g n i n g key as o u t p u t
∗/
void l e d e v i c e d b r e m o t e c s r k g e t ( int index , s m k e y t c s r k ) ;

/∗ ∗
∗ @ b r i e f q u e r y l a s t used / s e e n s i g n i n g c o u n t e r
∗ @param i n d e x
∗ @return n e x t e x p e c t e d c o u n t e r , 0 a f t e r d e v i c e s was added
∗/
uint32 t l e d e v i c e d b r e m o t e c o u n t e r g e t ( int i n d e x ) ;

/∗ ∗
∗ @brief update s i g n i n g counter
∗ @param i n d e x
∗ @param c o u n t e r t o s t o r e
∗/
void l e d e v i c e d b r e m o t e c o u n t e r s e t ( int index , uint32 t c o u n t e r ) ;

/∗ ∗
∗ @ b r i e f q u e r y l a s t used / s e e n s i g n i n g c o u n t e r
∗ @param i n d e x
∗ @return n e x t e x p e c t e d c o u n t e r , 0 a f t e r d e v i c e s was added
334

∗/
uint32 t l e d e v i c e d b l o c a l c o u n t e r g e t ( int i n d e x ) ;

/∗ ∗
∗ @brief update s i g n i n g counter
∗ @param i n d e x
∗ @param c o u n t e r t o s t o r e
∗/
void l e d e v i c e d b l o c a l c o u n t e r s e t ( int index , uint32 t c o u n t e r ) ;

#endif

/∗ ∗
∗ @brief free device
∗ @param i n d e x
∗/
void l e d e v i c e d b r e m o v e ( int i n d e x ) ;

void l e d e v i c e d b d u m p ( void ) ;

1.24. Device Database TLV API. le device db tlv.h

/∗ ∗
∗ @ b r i e f c o n f i g u r e l e d e v i c e db f o r use w i t h b t s t a c k t l v i n s t a n c e
∗ @param b t s t a c k t l v i m p l t o use
∗ @param b t s t a c k t l v c o n t e x t
∗/

void l e d e v i c e d b t l v c o n f i g u r e ( const b t s t a c k t l v t ∗
b t s t a c k t l v i m p l , void ∗ b t s t a c k t l v c o n t e x t ) ;

1.25. Security Manager API. sm.h

/∗ ∗
∗ @ b r i e f I n i t i a l i z e s t h e S e c u r i t y Manager , c o n n e c t s t o L2CAP
∗/
void s m i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f S e t s e c r e t ER key f o r key g e n e r a t i o n as d e s c r i b e d i n Core
V4 . 0 , Vol 3 , Part G, 5 . 2 . 2
∗ @note I f not s e t and b t s t a c k t l v i s c o n f i g u r e d , ER key i s
g e n e r a t e d and s t o r e d i n TLV by SM
∗ @param e r key
∗/
void s m s e t e r ( s m k e y t e r ) ;

/∗ ∗
∗ @ b r i e f S e t s e c r e t IR key f o r key g e n e r a t i o n as d e s c r i b e d i n Core
V4 . 0 , Vol 3 , Part G, 5 . 2 . 2
335

∗ @note I f not s e t and b t s t a c k t l v i s c o n f i g u r e d , IR key i s


g e n e r a t e d and s t o r e d i n TLV by SM
∗ @param i r key
∗/
void s m s e t i r ( s m k e y t i r ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s OOB Data C a l l b a c k . The c a l l b a c k s h o u l d s e t t h e
o o b d a t a and r e t u r n 1 i f OOB d a t a i s a v a i l b l e
∗ @param g e t o o b d a t a c a l l b a c k
∗/
void s m r e g i s t e r o o b d a t a c a l l b a c k ( int ( ∗ g e t o o b d a t a c a l l b a c k ) (
uint8 t a d d r e s s t y p e , bd addr t addr , uint8 t ∗ o o b d a t a ) ) ;

/∗ ∗
∗ @ b r i e f Add e v e n t p a c k e t h a n d l e r .
∗ @param c a l l b a c k h a n d l e r
∗/
void s m a d d e v e n t h a n d l e r ( b t s t a c k p a c k e t c a l l b a c k r e g i s t r a t i o n t ∗
callback handler ) ;

/∗ ∗
∗ @ b r i e f Remove e v e n t p a c k e t h a n d l e r .
∗ @param c a l l b a c k h a n d l e r
∗/
void s m r e m o v e e v e n t h a n d l e r ( b t s t a c k p a c k e t c a l l b a c k r e g i s t r a t i o n t
∗ callback handler ) ;

/∗ ∗
∗ @ b r i e f L i m i t t h e STK g e n e r a t i o n methods . Bonding i s s t o p p e d i f
t h e r e s u l t i n g one i s n ’ t i n t h e l i s t
∗ @param OR c o m b i n a t i o n o f SM STK GENERATION METHOD
∗/
void s m s e t a c c e p t e d s t k g e n e r a t i o n m e t h o d s ( uint8 t
accepted stk generation methods ) ;

/∗ ∗
∗ @ b r i e f S e t t h e a c c e p t e d e n c r y p t i o n key s i z e range . Bonding i s
s t o p p e d i f t h e r e s u l t i s n ’ t w i t h i n t h e range
∗ @param m i n s i z e ( d e f a u l t 7)
∗ @param m a x s i z e ( d e f a u l t 16)
∗/
void s m s e t e n c r y p t i o n k e y s i z e r a n g e ( uint8 t m i n s i z e , uint8 t
max size ) ;

/∗ ∗
∗ @brief Sets the r e q u e s t e d a u t h e n t i c a t i o n requirements , bonding
y e s /no , MITM y e s /no , SC y e s /no , k e y p r e s s y e s /no
∗ @param OR c o m b i n a t i o n o f SM AUTHREQ f l a g s
∗/
void s m s e t a u t h e n t i c a t i o n r e q u i r e m e n t s ( uint8 t a u t h r e q ) ;

/∗ ∗
∗ @ b r i e f S e t s t h e a v a i l a b l e IO C a p a b i l i t i e s
336

∗ @param IO CAPABILITY
∗/
void s m s e t i o c a p a b i l i t i e s ( i o c a p a b i l i t y t i o c a p a b i l i t y ) ;

/∗ ∗
∗ @ b r i e f Enable / d i s a b l e S e c u r e C o n n e c t i o n s Mode o n l y
∗ @param e n a b l e s e c u r e c o n n e c t i o n s o n l y mode
∗/
void s m s e t s e c u r e c o n n e c t i o n s o n l y m o d e ( b o o l e n a b l e ) ;

/∗ ∗
∗ @ b r i e f Let P e r i p h e r a l r e q u e s t an e n c r y p t e d c o n n e c t i o n r i g h t a f t e r
connecting
∗ @param e n a b l e
∗ @note Not used n o r m a l l y . Bonding i s t r i g g e r e d by a c c e s s t o
p r o t e c t e d a t t r i b u t e s i n ATT S e r v e r
∗/
void s m s e t r e q u e s t s e c u r i t y ( b o o l e n a b l e ) ;

/∗ ∗
∗ @brief Trigger S e c u r i t y Request
∗ @ de pr e ca te d p l e a s e use s m r e q u e s t p a i r i n g i n s t e a d
∗/
void s m s e n d s e c u r i t y r e q u e s t ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f D e c l i n e b o n d i n g t r i g g e r e d by e v e n t b e f o r e
∗ @param c o n h a n d l e
∗/
void s m b o n d i n g d e c l i n e ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Confirm J u s t Works b o n d i n g
∗ @param c o n h a n d l e
∗/
void s m j u s t w o r k s c o n f i r m ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Confirm v a l u e from SM EVENT NUMERIC COMPARISON REQUEST f o r
Numeric Comparison b o n d i n g
∗ @param c o n h a n d l e
∗/
void s m n u m e r i c c o m p a r i s o n c o n f i r m ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e p o r t s p a s s k e y i n p u t by u s e r
∗ @param c o n h a n d l e
∗ @param p a s s k e y i n [ 0 . . 9 9 9 9 9 9 ]
∗/
void s m p a s s k e y i n p u t ( h c i c o n h a n d l e t c o n h a n d l e , uint32 t p a s s k e y )
;

/∗ ∗
∗ @ b r i e f Send k e y p r e s s n o t i f i c a t i o n f o r k e y b o a r d o n l y d e v i c e s
337

∗ @param c o n h a n d l e
∗ @param a c t i o n s e e SM KEYPRESS ∗ i n b l u e t o o t h . h
∗/
void s m k e y p r e s s n o t i f i c a t i o n ( h c i c o n h a n d l e t c o n h a n d l e , uint8 t
action ) ;

/∗ ∗
∗ @ b r i e f Used by a t t s e r v e r . c and g a t t c l i e n t . c t o r e q u e s t u s e r
authentication
∗ @param c o n h a n d l e
∗/
void s m r e q u e s t p a i r i n g ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Report u s e r a u t h o r i z a t i o n d e c l i n e .
∗ @param c o n h a n d l e
∗/
void s m a u t h o r i z a t i o n d e c l i n e ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Report u s e r a u t h o r i z a t i o n g r a n t .
∗ @param c o n h a n d l e
∗/
void s m a u t h o r i z a t i o n g r a n t ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f S u p p o r t f o r s i g n e d w r i t e s , used by a t t s e r v e r .
∗ @return r e a d y
∗/
int sm cmac ready ( void ) ;

/∗ ∗
∗ @ b r i e f S u p p o r t f o r s i g n e d w r i t e s , used by a t t s e r v e r .
∗ @note Message i s i n l i t t l e endian t o a l l o w s p a s s i n g i n ATT PDU
without f l i p p i n g .
∗ @note s i g n i n g d a t a : [ opcode , a t t r i b u t e h a n d l e , message ,
sign counter ]
∗ @note c a l c u l a t e d hash i n d o n e c a l l b a c k i s b i g endian and has 16
byte .
∗ @param key
∗ @param opcde
∗ @param a t t r i b u t e h a n d l e
∗ @param m e s s a g e l e n
∗ @param message
∗ @param s i g n c o u n t e r
∗/
void s m c m a c s i g n e d w r i t e s t a r t ( const s m k e y t key , uint8 t opcode ,
uint16 t a t t r i b u t e h a n d l e , uint16 t m e s s a g e l e n , const uint8 t ∗
message , uint32 t s i g n c o u n t e r , void ( ∗ d o n e c a l l b a c k ) ( uint8 t ∗
hash ) ) ;

/∗ ∗
∗ @ b r i e f Match a d d r e s s a g a i n s t bonded d e v i c e s
∗ @param a d d r e s s t y p e
338

∗ @param a d d r e s s
∗ @return 0 i f s u c c e s s f u l l y added t o l o o k u p queue
∗ @note T r i g g e r s SM IDENTITY RESOLVING ∗ e v e n t s
∗/
int s m a d d r e s s r e s o l u t i o n l o o k u p ( uint8 t a d d r e s s t y p e , bd addr t
address ) ;

/∗ ∗
∗ @ b r i e f Get I d e n t i t y R e s o l v i n g s t a t e
∗ @param c o n h a n d l e
∗ @return i r k l o o k u p s t a t e t
∗ @note r e t u r n IRK LOOKUP IDLE i f c o n n e c t i o n d o e s not e x i s t
∗/
irk lookup state t sm identity resolving state ( hci con handle t
con handle ) ;

/∗ ∗
∗ @ b r i e f I d e n t i f y d e v i c e i n LE D e v i ce DB.
∗ @param c o n h a n d l e
∗ @return i n d e x from l e d e v i c e d b or −1 i f not found / i d e n t i f i e d
∗/
int s m l e d e v i c e i n d e x ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Get LTK f o r e n c r y p t e d c o n n e c t i o n
∗ @param c o n h a n d l e
∗ @param l t k b u f f e r t o s t o r e l o n g term key
∗ @return ERROR CODE SUCCESS ok
∗ ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f no c o n n e c t i o n
f o r t h i s con h a n d l e e x i s t s
∗ ERROR CODE PIN OR KEY MISSING i f c o n n e c t i o n i s not
encrypted
∗/
uint8 t s m g e t l t k ( h c i c o n h a n d l e t c o n h a n d l e , s m k e y t l t k ) ;

/∗ ∗
∗ @ b r i e f Use f i x e c p a s s k e y f o r Legacy and SC i n s t e a d o f g e n e r a t i n g
a random number
∗ @note Can be used t o improve s e c u r i t y o v e r J u s t Works i f no
k e y b o a r d or d i s p l a r y a r e p r e s e n t and
∗ i n d i v i d u a l random p a s s k e y can be p r i n t e d on t h e d e v i c e
during production
∗ @param p a s s k e y
∗/
void s m u s e f i x e d p a s s k e y i n d i s p l a y r o l e ( uint32 t p a s s k e y ) ;

/∗ ∗
∗ @ b r i e f Allow c o n n e c t i o n re−e n c r y p t i o n i n P e r i p h e r a l ( Responder )
r o l e f o r LE Legacy P a i r i n g
∗ w i t h o u t e n t r y f o r C e n t r a l d e v i c e s t o r e d i n LE D e v ic e DB
∗ @note BTstack i n P e r i p h e r a l Role ( Responder ) s u p p o r t s LE Legacy
P a i r i n g w i t h o u t a p e r s i s t e n t LE D e v ic e DB as
∗ t h e LTK i s r e c o n s t r u c t e d from a l o c a l s e c r e t IRK and EDIV +
Random s t o r e d on C e n t r a l ( I n i t i a t o r ) d e v i c e
339

∗ On t h e downside , i t ’ s not r e a l l y p o s s i b l e t o d e l e t e a
pairing i f t h i s i s enabled .
∗ @param a l l o w e n c r y p t i o n u s i n g r e c o n s t r u c t e d LTK w i t h o u t s t o r e d
e n t r y ( D e f a u l t : 1)
∗/
void s m a l l o w l t k r e c o n s t r u c t i o n w i t h o u t l e d e v i c e d b e n t r y ( int
allow ) ;

/∗ ∗
∗ @ b r i e f Generate OOB d a t a f o r LE S e c u r e C o n n e c t i o n s
∗ @note This g e n e r a t e s a 128 b i t random number ra and t h e n
c a l c u l a t e s Ca = f 4 (PKa, PKa, ra , 0)
∗ New OOB d a t a s h o u l d be g e n e r a t e d f o r each p a i r i n g . Ra i s
used f o r s u b s e q u e n t OOB p a i r i n g s
∗ @param c a l l b a c k
∗ @return s t a t u s
∗/
uint8 t s m g e n e r a t e s c o o b d a t a ( void ( ∗ c a l l b a c k ) ( const uint8 t ∗
c o n f i r m v a l u e , const uint8 t ∗ random value ) ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s OOB Data C a l l b a c k f o r LE Se c u r e C o n e c t i o n s . The
c a l l b a c k s h o u l d s e t a l l arguments and r e t u r n 1 i f OOB d a t a i s
availble
∗ @note t h e o o b s c l o c a l r a n d o m u s u a l l y i s t h e random value
r e t u r e n d by s m g e n e r a t e s c o o b d a t a
∗ @param g e t o o b d a t a c a l l b a c k
∗/
void s m r e g i s t e r s c o o b d a t a c a l l b a c k ( int ( ∗
g e t s c o o b d a t a c a l l b a c k ) ( uint8 t a d d r e s s t y p e , bd addr t addr ,
uint8 t ∗ o o b s c p e e r c o n f i r m , uint8 t ∗ o o b s c p e e r r a n d o m ) ) ;

/∗ ∗
∗ @ b b r i e f R e g i s t e r LTK C a l l b a c k t h a t a l l o w s t o p r o v i d e a custom LTK
on re−e n c r y p t i o n . The c a l l b a c k r e t u r n s t r u e i f LTK was
modified
∗ @param g e t l t k c a l l b a c k
∗/
void s m r e g i s t e r l t k c a l l b a c k ( b o o l ( ∗ g e t l t k c a l l b a c k ) (
h c i c o n h a n d l e t c o n h a n d l e , uint8 t a d d r e s s t y p e , bd addr t
addr , uint8 t ∗ l t k ) ) ;

1.26. Audio Interface API. btstack audio.h : Abstraction layer for 16-bit
audio playback and recording within BTstack.
Most embedded implementations, e.g. the one for ESP32, use a single I2S
interface which requires that the sample rate is the same for sink and source
roles

typedef struct {

/∗ ∗
340

∗ @ b r i e f S e tu p a u d i o co d ec f o r s p e c i f i e d s a m p l e r a t e and number
of channels
∗ @param Channels (1=mono , 2= s t e r e o )
∗ @param Sample r a t e
∗ @param P l a y b a c k c a l l b a c k
∗ @return 1 on s u c c e s s
∗/
int ( ∗ i n i t ) ( uint8 t c h a n n e l s ,
uint32 t s a m p l e r a t e ,
void ( ∗ p l a y b a c k ) ( i n t 1 6 t ∗ b u f f e r , uint16 t
num samples ) ) ;

/∗ ∗
∗ @ b r i e f Get t h e c u r r e n t p l a y b a c k sample r a t e , may d i f f e r from
the
∗ s p e c i f i e d sample r a t e
∗/
uint32 t ( ∗ g e t s a m p l e r a t e ) ( void ) ;

/∗ ∗
∗ @ b r i e f S e t volume
∗ @param Volume 0 . . 1 2 7
∗/
void ( ∗ s e t v o l u m e ) ( uint8 t volume ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream
∗/
void ( ∗ s t a r t s t r e a m ) ( void ) ;

/∗ ∗
∗ @ b r i e f Stop stream
∗/
void ( ∗ s t o p s t r e a m ) ( void ) ;

/∗ ∗
∗ @ b r i e f C l o s e a u d i o co d ec
∗/
void ( ∗ c l o s e ) ( void ) ;

} btstack audio sink t ;

typedef struct {

/∗ ∗
∗ @ b r i e f S e tu p a u d i o co d ec f o r s p e c i f i e d s a m p l e r a t e and number
of channels
∗ @param Channels (1=mono , 2= s t e r e o )
∗ @param Sample r a t e
∗ @param Recording c a l l b a c k
∗ @return 1 on s u c c e s s
∗/
int ( ∗ i n i t ) ( uint8 t c h a n n e l s ,
341

uint32 t s a m p l e r a t e ,
void ( ∗ r e c o r d i n g ) ( const i n t 1 6 t ∗ b u f f e r , uint16 t
num samples ) ) ;

/∗ ∗
∗ @ b r i e f Get t h e c u r r e n t r e c o r d i n g sample r a t e , may d i f f e r from
the
∗ s p e c i f i e d sameple r a t e
∗/
uint32 t ( ∗ g e t s a m p l e r a t e ) ( void ) ;

/∗ ∗
∗ @ b r i e f S e t Gain
∗ @param Gain 0 . . 1 2 7
∗/
void ( ∗ s e t g a i n ) ( uint8 t g a i n ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream
∗/
void ( ∗ s t a r t s t r e a m ) ( void ) ;

/∗ ∗
∗ @ b r i e f Stop stream
∗/
void ( ∗ s t o p s t r e a m ) ( void ) ;

/∗ ∗
∗ @ b r i e f C l o s e a u d i o co d ec
∗/
void ( ∗ c l o s e ) ( void ) ;

} btstack audio source t ;

/∗ ∗
∗ @ b r i e f Get BTstack Audio S i n k I n s t a n c e
∗ @return b t s t a c k a u d i o s i n k i m p l e m e n t a t i o n
∗/
const b t s t a c k a u d i o s i n k t ∗ b t s t a c k a u d i o s i n k g e t i n s t a n c e ( void ) ;

/∗ ∗
∗ @ b r i e f Get BTstack Audio Source I n s t a n c e
∗ @return b t s t a c k a u d i o s o u r c e i m p l e m e n t a t i o n
∗/
const b t s t a c k a u d i o s o u r c e t ∗ b t s t a c k a u d i o s o u r c e g e t i n s t a n c e (
void ) ;

/∗ ∗
∗ @ b r i e f Get BTstack Audio S i n k I n s t a n c e
∗ @param b t s t a c k a u d i o s i n k i m p l e m e n t a t i o n
∗/
342

void b t s t a c k a u d i o s i n k s e t i n s t a n c e ( const b t s t a c k a u d i o s i n k t ∗
audio sink impl ) ;

/∗ ∗
∗ @ b r i e f Get BTstack Audio Source I n s t a n c e
∗ @param b t s t a c k a u d i o s o u r c e i m p l e m e n t a t i o n
∗/
void b t s t a c k a u d i o s o u r c e s e t i n s t a n c e ( const b t s t a c k a u d i o s o u r c e t
∗ audio source impl ) ;

// common i m p l e m e n t a t i o n s
const b t s t a c k a u d i o s i n k t ∗
b t s t a c k a u d i o p o r t a u d i o s i n k g e t i n s t a n c e ( void ) ;
const b t s t a c k a u d i o s o u r c e t ∗
b t s t a c k a u d i o p o r t a u d i o s o u r c e g e t i n s t a n c e ( void ) ;

const b t s t a c k a u d i o s i n k t ∗
btstack audio embedded s i n k g e t i n s t a n c e ( void ) ;
const b t s t a c k a u d i o s o u r c e t ∗
btstack audio embedded s o u r c e g e t i n s t a n c e ( void ) ;

const b t s t a c k a u d i o s i n k t ∗
b t s t a c k a u d i o e s p 3 2 s i n k g e t i n s t a n c e ( void ) ;
const b t s t a c k a u d i o s o u r c e t ∗
b t s t a c k a u d i o e s p 3 2 s o u r c e g e t i n s t a n c e ( void ) ;

1.27. base64 Decoder API. btstack base64 decoder.h

#define BTSTACK BASE64 DECODER MORE −1


#define BTSTACK BASE64 DECODER COMPLETE −2
#define BTSTACK BASE64 DECODER INVALID −3
#define BTSTACK BASE64 DECODER FULL −4

/∗ ∗
∗ @brief I n i t i a l i z e base64 decoder
∗ @param c o n t e x t
∗/
void b t s t a c k b a s e 6 4 d e c o d e r i n i t ( b t s t a c k b a s e 6 4 d e c o d e r t ∗ c o n t e x t )
;

/∗ ∗
∗ @ b r i e f Decode s i n g l e b y t e
∗ @brief context
∗ @return v a l u e , or BTSTACK BASE64 DECODER MORE,
BTSTACK BASE64 DECODER COMPLETE, BTSTACK BASE64 DECODER INVALID
∗/
int b t s t a c k b a s e 6 4 d e c o d e r p r o c e s s b y t e ( b t s t a c k b a s e 6 4 d e c o d e r t ∗
c o n t e x t , uint8 t c ) ;

/∗ ∗
∗ @ b r i e f Decode b l o c k
343

∗ @ b r i e f i n p u t d a t a b a s e 6 4 encoded message
∗ @brief i n p u t s i z e
∗ @breif output buffer
∗ @brief output max size
∗ @return o u t p u t s i z e or BTSTACK BASE64 DECODER INVALID,
BTSTACK BASE64 DECODER FULL
∗/
int b t s t a c k b a s e 6 4 d e c o d e r p r o c e s s b l o c k ( const uint8 t ∗ i n p u t d a t a ,
uint32 t i n p u t s i z e , uint8 t ∗ o u t p u t b u f f e r , uint32 t
output max size ) ;

1.28. Chipset Driver API. btstack chipset.h : The API implements custom
chipset initialization and support of proprietary extensions to set UART baud
rate, Bluetooth Address, and similar.

typedef struct {
/∗ ∗
∗ c h i p s e t d r i v e r name
∗/
const char ∗ name ;

/∗ ∗
∗ init driver
∗ allows to r e s e t i n i t s c r i p t index
∗ @param t r a n s p o r t c o n f i g
∗/
void ( ∗ i n i t ) ( const void ∗ t r a n s p o r t c o n f i g ) ;

/∗ ∗
∗ s u p p o r t custom i n i t s e q u e n c e s a f t e r RESET command
∗ @param h c i c m d b u f f e r t o s t o r e g e n e r a t e d command
∗ @return r e s u l t s e e b t s t a c k c h i p s e t r e s u l t t
∗/
b t s t a c k c h i p s e t r e s u l t t ( ∗ next command ) ( uint8 t ∗
hci cmd buffer ) ;

/∗ ∗
∗ p r o v i d e UART Baud Rate change command .
∗ @param b a u d r a t e
∗ @param h c i c m d b u f f e r t o s t o r e g e n e r a t e d command
∗/
void ( ∗ set baudrate command ) ( uint32 t baudrate , uint8 t ∗
hci cmd buffer ) ;

/∗ ∗ p r o v i d e S e t BD Addr command
∗ @param b a u d r a t e
∗ @param h c i c m d b u f f e r t o s t o r e g e n e r a t e d command
∗/
void ( ∗ set bd addr command ) ( bd addr t addr , uint8 t ∗
hci cmd buffer ) ;

} btstack chipset t ;
344

1.29. Bluetooth Power Control API. btstack control.h : The Bluetooth


Hardware Control API allows HCI to manage Bluetooth chipsets via direct hard-
ware controls.

typedef struct {
void ( ∗ i n i t ) ( const void ∗ c o n f i g ) ;
int ( ∗ on ) ( void ) ; // <−− t u r n BT module on and c o n f i g u r e
int ( ∗ o f f ) ( void ) ; // <−− t u r n BT module o f f
int ( ∗ s l e e p ) ( void ) ; // <−− p u t BT module t o s l e e p − only to
be c a l l e d a f t e r ON
int ( ∗ wake ) ( void ) ; // <−− wake BT module from s l e e p − o n l y t o
be c a l l e d a f t e r SLEEP
void ( ∗ r e g i s t e r f o r p o w e r n o t i f i c a t i o n s ) ( void ( ∗ cb ) (
POWER NOTIFICATION t e v e n t ) ) ;
} btstack control t ;

1.30. Debug Messages API. btstack debug.h : Allow to funnel debug and
error messages.

/∗ ∗
∗ @ b r i e f Log S e c u r i t y Manager key v i a l o g i n f o
∗ @param name
∗ @param key t o l o g
∗/
void l o g i n f o k e y ( const char ∗ name , s m k e y t key ) ;

/∗ ∗
∗ @ b r i e f Hexdump v i a l o g i n f o
∗ @param d a t a
∗ @param s i z e
∗/
void l o g i n f o h e x d u m p ( const void ∗ data , int s i z e ) ;

/∗ ∗
∗ @ b r i e f Hexdump v i a l o g d e b u g
∗ @param d a t a
∗ @param s i z e
∗/
void log debug hexdump ( const void ∗ data , int s i z e ) ;

1.31. EM9304 SPI API. btstack em9304 spi.h : BTstack’s Hardware Ab-
straction Layer for EM9304 connected via SPI with additional RDY Interrupt
line.

#include <s t d i n t . h>


345

typedef struct {

/∗ ∗
∗ @ b r i e f Open SPI
∗/
int ( ∗ open ) ( void ) ;

/∗ ∗
∗ @ b r i e f C l o s e SPI
∗/
int ( ∗ c l o s e ) ( void ) ;

/∗ ∗
∗ @ b r i e f Check i f f u l l d u p l e x o p e r a t i o n v i a t r a n s c e i v e i s
supported
∗ @return 1 i f s u p p o r t e d
∗/
int ( ∗ g e t f u l l d u p l e x s u p p o r t ) ( void ) ;

/∗ ∗
∗ @ b r i e f S e t c a l l b a c k f o r RDY
∗ @param c a l l b a c k or NULL t o d i s a b l e c a l l b a c k
∗/
void ( ∗ s e t r e a d y c a l l b a c k ) ( void ( ∗ c a l l b a c k ) ( void ) ) ;

/∗ ∗
∗ @brief Set c a l l b a c k for t r a n s f e r complete
∗ @param c a l l b a c k
∗/
void ( ∗ s e t t r a n s f e r d o n e c a l l b a c k ) ( void ( ∗ c a l l b a c k ) ( void ) ) ;

/∗ ∗
∗ @ b r i e f S e t Chip S e l e t
∗ @param e n a b l e
∗/
void ( ∗ s e t c h i p s e l e c t ) ( int e n a b l e ) ;

/∗ ∗
∗ @ b r i e f P o l l READY s t a t e
∗/
int ( ∗ g e t r e a d y ) ( void ) ;

/∗ ∗
∗ @ b r i e f Transmit and R e c e i v e b y t e s v i a SPI
∗ @param t x d a t a b u f f e r t o t r a n s m i t
∗ @param r x d a t a b u f f e r t o r e c e i v e i n t o
∗ @param l e n
∗/
void ( ∗ t r a n s c e i v e ) ( const uint8 t ∗ t x d a t a , uint8 t ∗ r x d a t a ,
uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f Transmit b y t e s v i a SPI
∗ @param t x d a t a b u f f e r t o t r a n s m i t
346

∗ @param l e n
∗/
void ( ∗ t r a n s m i t ) ( const uint8 t ∗ t x d a t a , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f R e c e i v e b y t e s v i a SPI
∗ @param r x d a t a b u f f e r t o r e c e i v e i n t o
∗ @param l e n
∗/
void ( ∗ r e c e i v e ) ( uint8 t ∗ r x d a t a , uint16 t l e n ) ;

} btstack em9304 spi t ;

/∗ ∗
∗ @ b r i e f Get EM9304 SPI i n s t a n c e
∗/
const b t s t a c k e m 9 3 0 4 s p i t ∗ b t s t a c k e m 9 3 0 4 s p i e m b e d d e d i n s t a n c e (
void ) ;

1.32. Finite State Machine (FSM) API. btstack fsm.h

/∗
∗ @ b r i e f R e q u e s t t h e t r a n s i t i o n from t h e c u r r e n t s t a t e t o t h e g i v e n
new s t a t e
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param t a r g e t t h e new s t a t e t o t r a n s i t t o
∗ @result transition status
∗/
b t s t a c k f s m s t a t e t b t s t a c k f s m t r a n s i t ( b t s t a c k f s m t ∗ const me ,
btstack fsm state handler t target ) ;

/∗
∗ @ b r i e f C o n s t r u c t s a new s t a t e h i e r a r c h i c a l machine machine , w i t h
s t o r a g e f o r maximum h i e r a r c h y d e p t h .
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param i n i t i a l t h e i n i t i a l s t a t e
∗/
void b t s t a c k f s m c o n s t r u c t o r ( b t s t a c k f s m t ∗ const me ,
btstack fsm state handler t i n i t i a l ) ;

/∗
∗ @ b r i e f Takes t h e i n i t i a l t r a n s i t i o n o f t h e s t a t e machine and
s e n d i n g i t a BTSTACK HSM INIT SIG
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param e e v e n t
∗/
void b t s t a c k f s m i n i t ( b t s t a c k f s m t ∗ const me , b t s t a c k f s m e v e n t t
const ∗ const e ) ;

/∗
347

∗ @ b r i e f D i s p a t c h e s t h e g i v e n e v e n t t o t h e s t a t e machine , i f a
t r a n s i t i o n i s r e q u e s t e d , l e a v e t h e o l d s t a t e s and e n t e r t h e new
on .
∗ Handling e n t e r i n g / e x i t i n g a l l s t a t e s on t h e way .
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param e e v e n t
∗/
b t s t a c k f s m s t a t e t b t s t a c k f s m d i s p a t c h ( b t s t a c k f s m t ∗ const me ,
b t s t a c k f s m e v e n t t const ∗ const e ) ;

/∗
∗ @ b r i e f D i s p a t c h e s t h e g i v e n e v e n t t o t h e s t a t e machine u n t i l i t
was h a n d l e d .
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param e e v e n t
∗/
void b t s t a c k f s m d i s p a t c h u n t i l ( b t s t a c k f s m t ∗ const me ,
b t s t a c k f s m e v e n t t const ∗ const e ) ;

1.33. Human Interface Device (HID) API. btstack hid.h

/∗
∗ @ b r i e f Get b o o t d e s c r i p t o r d a t a
∗ @result data
∗/
const uint8 t ∗ b t s t a c k h i d g e t b o o t d e s c r i p t o r d a t a ( void ) ;

/∗
∗ @ b r i e f Get b o o t d e s c r i p t o r l e n g t h
∗ @result length
∗/
uint16 t b t s t a c k h i d g e t b o o t d e s c r i p t o r l e n ( void ) ;

1.34. HID Parser API. btstack hid parser.h : Single-pass HID Report Parser:
HID Report is directly parsed without preprocessing HID Descriptor to minimize
memory.

/∗ ∗
∗ @brief I n i t i a l i z e HID P a rs e r .
∗ @param parser sta te
∗ @param hid descriptor
∗ @param hid descriptor len
∗ @param hid report type
∗ @param hid report
∗ @param hid report len
∗/
348

void b t s t a c k h i d p a r s e r i n i t ( b t s t a c k h i d p a r s e r t ∗ p a r s e r , const
uint8 t ∗ h i d d e s c r i p t o r , uint16 t h i d d e s c r i p t o r l e n ,
h i d r e p o r t t y p e t h i d r e p o r t t y p e , const uint8 t ∗ h i d r e p o r t ,
uint16 t h i d r e p o r t l e n ) ;

/∗ ∗
∗ @ b r i e f Checks i f more f i e l d s a r e a v a i l a b l e
∗ @param p a r s e r
∗/
bool btstack hid parser has more ( b t s t a c k h i d p a r s e r t ∗ parser ) ;

/∗ ∗
∗ @ b r i e f Get n e x t f i e l d
∗ @param p a r s e r
∗ @param u s a g e p a g e
∗ @param u s a g e
∗ @param v a l u e p r o v i d e d i n HID r e p o r t
∗/
void b t s t a c k h i d p a r s e r g e t f i e l d ( b t s t a c k h i d p a r s e r t ∗ p a r s e r ,
uint16 t ∗ u s a g e p a g e , uint16 t ∗ usage , i n t 3 2 t ∗ v a l u e ) ;

/∗ ∗
∗ @ b r i e f P a r s e s d e s c r i p t o r item
∗ @param item
∗ @param h i d d e s c r i p t o r
∗ @param h i d d e s c r i p t o r l e n
∗ @return t r u e i f item has been p a r s e d s u c c e s s f u l l y
∗/
b o o l b t s t a c k h i d p a r s e d e s c r i p t o r i t e m ( h i d d e s c r i p t o r i t e m t ∗ item ,
const uint8 t ∗ h i d d e s c r i p t o r , uint16 t h i d d e s c r i p t o r l e n ) ;

/∗ ∗
∗ @ b r i e f P a r s e s d e s c r i p t o r and r e t u r n s r e p o r t s i z e f o r g i v e n r e p o r t
ID and r e p o r t t y p e
∗ @param r e p o r t i d
∗ @param r e p o r t t y p e
∗ @param h i d d e s c r i p t o r l e n
∗ @param h i d d e s c r i p t o r
∗ @return r e p o r t s i z e i n b y t e s or 0 on p a r s i n g e r r o r
∗/
int b t s t a c k h i d g e t r e p o r t s i z e f o r i d ( int r e p o r t i d ,
h i d r e p o r t t y p e t r e p o r t t y p e , uint16 t h i d d e s c r i p t o r l e n ,
const uint8 t ∗ h i d d e s c r i p t o r ) ;

/∗ ∗
∗ @ b r i e f P a r s e s d e s c r i p t o r and r e t u r n s s t a t u s f o r g i v e n r e p o r t ID
∗ @param r e p o r t i d
∗ @param h i d d e s c r i p t o r l e n
∗ @param h i d d e s c r i p t o r
∗ @return s t a t u s f o r r e p o r t i d
∗/
h i d r e p o r t i d s t a t u s t b t s t a c k h i d i d v a l i d ( int r e p o r t i d , uint16 t
h i d d e s c r i p t o r l e n , const uint8 t ∗ h i d d e s c r i p t o r ) ;
349

/∗ ∗
∗ @ b r i e f P a r s e s d e s c r i p t o r and r e t u r n s t r u e i f r e p o r t ID found
∗ @param h i d d e s c r i p t o r l e n
∗ @param h i d d e s c r i p t o r
∗ @return t r u e i f r e p o r t ID d e c l a r e d i n d e s c r i p t o r
∗/
b o o l b t s t a c k h i d r e p o r t i d d e c l a r e d ( uint16 t h i d d e s c r i p t o r l e n ,
const uint8 t ∗ h i d d e s c r i p t o r ) ;

1.35. Hierarchical State Machine (HSM) API. btstack hsm.h

/∗
∗ @ b r i e f R e q u e s t t h e t r a n s i t i o n from t h e c u r r e n t s t a t e t o t h e g i v e n
new s t a t e
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param t a r g e t t h e new s t a t e t o t r a n s i t t o
∗ @result transition status
∗/
b t s t a c k h s m s t a t e t b t s t a c k h s m t r a n s i t ( b t s t a c k h s m t ∗ const me ,
b t s t a c k h s m s t a t e h a n d l e r t const t a r g e t ) ;

/∗
∗ @ b r i e f S p e c i f i e s t h e upper s t a t e i n a s t a t e h i e r a r c h y
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param t a r g e t t h e n e x t p a r e n t s t a t e i n t h e h i e r a r c h y
∗ @result transition status
∗/
b t s t a c k h s m s t a t e t b t s t a c k h s m s u p e r ( b t s t a c k h s m t ∗ const me ,
b t s t a c k h s m s t a t e h a n d l e r t const t a r g e t ) ;

/∗
∗ @ b r i e f P l a c e h o l d e r s t a t e t o mark t h e t o p most s t a t e i n a s t a t e
hierarchy , the root s t a t e . Ignores a l l events .
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param e e v e n t
∗ @result ignored status
∗/
b t s t a c k h s m s t a t e t b t s t a c k h s m t o p ( b t s t a c k h s m t ∗ const me ,
b t s t a c k h s m e v e n t t const ∗ const e ) ;

/∗
∗ @ b r i e f C o n s t r u c t s a new s t a t e h i e r a r c h i c a l machine machine , w i t h
s t o r a g e f o r maximum h i e r a r c h y d e p t h .
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param i n i t i a l t h e i n i t i a l s t a t e
∗ @param a r r a y o f b t s t a c k h s m s t a t e h a n d l e r t e l e m e n t s w i t h t h e
same number o f e l e m e n t s as t h e maximum number o f n e s t e d s t a t e
machines .
∗ @param The number o f n e s t e d s t a t e machines .
∗/
350

void b t s t a c k h s m c o n s t r u c t o r ( b t s t a c k h s m t ∗ const me ,
btstack hsm state handler t initial , btstack hsm state handler t
path [ ] , i n t 8 t depth ) ;

/∗
∗ @ b r i e f Takes t h e i n i t i a l t r a n s i t i o n o f t h e s t a t e machine and
s e n d i n g i t a BTSTACK HSM INIT SIG
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param e e v e n t
∗/
void b t s t a c k h s m i n i t ( b t s t a c k h s m t ∗ const me , b t s t a c k h s m e v e n t t
const ∗ const e ) ;

/∗
∗ @ b r i e f D i s p a t c h e s t h e g i v e n e v e n t t o t h e s t a t e machine , i f a
t r a n s i t i o n i s r e q u e s t e d , l e a v e t h e o l d s t a t e s and e n t e r t h e new
on .
∗ Honoring t h e h i e r a r c h y and h a n d l i n g e n t e r i n g / e x i t i n g a l l
s t a t e s on t h e way .
∗ @param me t h e c u r r e n t s t a t e machine
∗ @param e e v e n t
∗/
b t s t a c k h s m s t a t e t b t s t a c k h s m d i s p a t c h ( b t s t a c k h s m t ∗ const me ,
b t s t a c k h s m e v e n t t const ∗ const e ) ;

1.36. LC3 Interface API. btstack lc3.h : Interface for LC3 implementations

typedef enum {
BTSTACK LC3 FRAME DURATION 10000US ,
BTSTACK LC3 FRAME DURATION 7500US
} btstack lc3 frame duration t ;

typedef struct {

/∗ ∗
∗ C o n f i g u r e Decoder
∗ @param c o n t e x t
∗ @param s a m p l e r a t e
∗ @param f r a m e d u r a t i o n
∗ @param o c t e t s p e r f r a m e
∗ @return s t a t u s
∗/
uint8 t ( ∗ c o n f i g u r e ) ( void ∗ c o n t e x t , uint32 t s a m p l e r a t e ,
b t s t a c k l c 3 f r a m e d u r a t i o n t f r a m e d u r a t i o n , uint16 t
octets per frame ) ;

/∗ ∗
∗ Decode LC3 Frame i n t o s i g n e d 16− b i t s a m p l e s
∗ @param context
∗ @param bytes
∗ @param BFI Bad Frame I n d i c a t i o n f l a g s
∗ @param pcm out b u f f e r f o r decoded PCM s a m p l e s
351

∗ @param s t r i d e c ou n t b e t w e e n two c o n s e c u t i v e s a m p l e s
∗ @param BEC detect B i t Error D e t e c t e d f l a g
∗ @return s t a t u s
∗/
uint8 t ( ∗ d e c o d e s i g n e d 1 6 ) ( void ∗ c o n t e x t , const uint8 t ∗
bytes , uint8 t BFI ,
i n t 1 6 t ∗ pcm out , uint16 t s t r i d e , uint8 t ∗
BEC detect ) ;

/∗ ∗
∗ Decode LC3 Frame i n t o s i g n e d 24− b i t samples , s i g n −e x t e n d e d t o
32− b i t
∗ @param c o n t e x t
∗ @param b y t e s
∗ @param BFI Bad Frame I n d i c a t i o n f l a g s
∗ @param pcm out b u f f e r f o r decoded PCM s a m p l e s
∗ @param s t r i d e c ou n t b e t w e e n two c o n s e c u t i v e s a m p l e s
∗ @param BEC detect B i t Error D e t e c t e d f l a g
∗ @return s t a t u s
∗/
uint8 t ( ∗ d e c o d e s i g n e d 2 4 ) ( void ∗ c o n t e x t , const uint8 t ∗ bytes
, uint8 t BFI ,
i n t 3 2 t ∗ pcm out , uint16 t s t r i d e ,
uint8 t ∗ BEC detect ) ;

} btstack lc3 decoder t ;

typedef struct {
/∗ ∗
∗ C o n f i g u r e Decoder
∗ @param c o n t e x t
∗ @param s a m p l e r a t e
∗ @param f r a m e d u r a t i o n
∗ @param o c t e t s p e r f r a m e
∗ @return s t a t u s
∗/
uint8 t ( ∗ c o n f i g u r e ) ( void ∗ c o n t e x t , uint32 t s a m p l e r a t e ,
b t s t a c k l c 3 f r a m e d u r a t i o n t f r a m e d u r a t i o n , uint16 t
octets per frame ) ;

/∗ ∗
∗ Encode LC3 Frame w i t h 16− b i t s i g n e d PCM s a m p l e s
∗ @param c o n t e x t
∗ @param pcm in b u f f e r f o r decoded PCM s a m p l e s
∗ @param s t r i d e c ou n t b e t w e e n two c o n s e c u t i v e s a m p l e s
∗ @param b y t e s
∗ @return s t a t u s
∗/
uint8 t ( ∗ e n c o d e s i g n e d 1 6 ) ( void ∗ c o n t e x t , const i n t 1 6 t ∗
pcm in , uint16 t s t r i d e , uint8 t ∗ b y t e s ) ;

/∗ ∗
∗ Encode LC3 Frame w i t h 24− b i t s i g n e d PCM samples , s i g n −
e x t e n d e d t o 32 b i t
352

∗ @param c o n t e x t
∗ @param pcm in b u f f e r f o r decoded PCM s a m p l e s
∗ @param s t r i d e c ou n t b e t w e e n two c o n s e c u t i v e s a m p l e s
∗ @param b y t e s
∗ @return s t a t u s
∗/
uint8 t ( ∗ e n c o d e s i g n e d 2 4 ) ( void ∗ c o n t e x t , const i n t 3 2 t ∗
pcm in , uint16 t s t r i d e , uint8 t ∗ b y t e s ) ;

} btstack lc3 encoder t ;

/∗ ∗
∗ @ b r i e f Map enum t o ISO I n t e r v a l i n us
∗ @param f r a m e d u r a t i o n enum
∗ @return f r a m e d u r a t o i n i n us or 0 f o r i n v a l i d f r a m e d u r a t i o n enum
∗/
uint16 t b t s t a c k l c 3 f r a m e d u r a t i o n i n u s (
btstack lc3 frame duration t frame duration ) ;

/∗ ∗
∗ @ b b r i e f C a l c u l a t e number o f s a m p l e s p e r ISO I n t e r v a l
∗ @param s a m p l e r a t e
∗ @param f r a m e d u r a t i o n
∗ @return
∗/
uint16 t b t s t a c k l c 3 s a m p l e s p e r f r a m e ( uint32 t s a m p l e r a t e ,
btstack lc3 frame duration t frame duration ) ;

1.37. LC3 Google Adapter API. btstack lc3 google.h

typedef struct {
lc3 decoder mem 48k t decoder mem ;
lc3 decoder t decoder ; // p o i n t e r
uint32 t sample rate ;
btstack lc3 frame duration t frame duration ;
uint16 t octets per frame ;
} btstack lc3 decoder google t ;

typedef struct {
lc3 encoder mem 48k t encoder mem ;
lc3 encoder t encoder ; // p o i n t e r
uint32 t sample rate ;
btstack lc3 frame duration t frame duration ;
uint16 t octets per frame ;
} btstack lc3 encoder google t ;

/∗ ∗
∗ I n i t LC3 Decoder I n s t a n c e
∗ @param c o n t e x t f o r EHIMA LC3 d e c o d e r
∗/
353

const b t s t a c k l c 3 d e c o d e r t ∗
btstack lc3 decoder google init instance (
b t s t a c k l c 3 d e c o d e r g o o g l e t ∗ context ) ;

/∗ ∗
∗ I n i t LC3 Decoder I n s t a n c e
∗ @param c o n t e x t f o r EHIMA LC3 d e c o d e r
∗/
const b t s t a c k l c 3 e n c o d e r t ∗
btstack lc3 encoder google init instance (
b t s t a c k l c 3 e n c o d e r g o o g l e t ∗ context ) ;

1.38. Adapter for Fraunhofer LC3plus Coddec API. btstack lc3plus fraunhofer.h
: only uses suitable subset for lc3 testing

typedef struct {
btstack lc3 frame duration t frame duration ;
uint16 t octets per frame ;
uint16 t samples per frame ;
uint32 t sample rate ;
// d e c o d e r must be 4− b y t e a l i g n e d
uint8 t d e c o d e r [ LC3PLUS DEC MAX SIZE ] ;
} btstack lc3plus fraunhofer decoder t ;

typedef struct {
btstack lc3 frame duration t frame duration ;
uint16 t octets per frame ;
uint32 t sample rate ;
// e n c o d e r must be 4− b y t e a l i g n e d
uint8 t e n c o d e r [ LC3PLUS ENC MAX SIZE ] ;
} btstack lc3plus fraunhofer encoder t ;

/∗ ∗
∗ I n i t LC3 Decoder I n s t a n c e
∗ @param c o n t e x t f o r F r a u n h o f e r LC3plus d e c o d e r
∗/
const b t s t a c k l c 3 d e c o d e r t ∗
btstack lc3plus fraunhofer decoder init instance (
b t s t a c k l c 3 p l u s f r a u n h o f e r d e c o d e r t ∗ context ) ;

/∗ ∗
∗ I n i t LC3 Encoder I n s t a n c e
∗ @param c o n t e x t f o r F r a u n h o f e r LC3plus e n c o d e r
∗/
const b t s t a c k l c 3 e n c o d e r t ∗
btstack lc3plus fraunhofer encoder init instance (
b t s t a c k l c 3 p l u s f r a u n h o f e r e n c o d e r t ∗ context ) ;

1.39. Linked List API. btstack linked list.h


354

typedef struct b t s t a c k l i n k e d i t e m {
struct b t s t a c k l i n k e d i t e m ∗ next ; // <−− n e x t e l e m e n t i n l i s t ,
or NULL
} btstack linked item t ;

typedef b t s t a c k l i n k e d i t e m t ∗ b t s t a c k l i n k e d l i s t t ;

typedef struct {
int a d v a n c e o n n e x t ;
b t s t a c k l i n k e d i t e m t ∗ prev ; // p o i n t s t o t h e item b e f o r e t h e
c u r r e n t one
btstack linked item t ∗ curr ; // p o i n t s t o t h e c u r r e n t item (
t o d e t e c t item removal )
} btstack linked list iterator t ;

/∗ ∗
∗ @ b r i e f Test i f l i s t i s empty .
∗ @param l i s t
∗ @return t r u e i f l i s t i s empty
∗/
bool b t s t a c k l i n k e d l i s t e m p t y ( b t s t a c k l i n k e d l i s t t ∗ l i s t ) ;

/∗ ∗
∗ @ b r i e f Add item t o l i s t as f i r s t e l e m e n t .
∗ @param l i s t
∗ @param item
∗ @return t r u e i f item was added , f a l s e i f item a l r e a d y i n l i s t
∗/
bool b t s t a c k l i n k e d l i s t a d d ( b t s t a c k l i n k e d l i s t t ∗ l i s t ,
b t s t a c k l i n k e d i t e m t ∗ item ) ;

/∗ ∗
∗ @ b r i e f Add item t o l i s t as l a s t e l e m e n t .
∗ @param l i s t
∗ @param item
∗ @return t r u e i f item was added , f a l s e i f item a l r e a d y i n l i s t
∗/
bool b t s t a c k l i n k e d l i s t a d d t a i l ( b t s t a c k l i n k e d l i s t t ∗ l i s t ,
b t s t a c k l i n k e d i t e m t ∗ item ) ;

/∗ ∗
∗ @ b r i e f Pop ( g e t + remove ) f i r s t e l e m e n t .
∗ @param l i s t
∗ @return f i r s t e l e m e n t or NULL i f l i s t i s empty
∗/
btstack linked item t ∗ btstack linked list pop (
btstack linked list t ∗ list ) ;

/∗ ∗
∗ @ b r i e f Remove item from l i s t
∗ @param l i s t
∗ @param item
∗ @return t r u e i f item was removed , f a l s e i f i t i s no ’ t i n l i s t
355

∗/
bool b t s t a c k l i n k e d l i s t r e m o v e ( b t s t a c k l i n k e d l i s t t ∗ l i s t ,
b t s t a c k l i n k e d i t e m t ∗ item ) ;

/∗ ∗
∗ @ b r i e f Get f i r s t e l e m e n t .
∗ @param l i s t
∗ @return f i r s t e l e m e n t or NULL i f l i s t i s empty
∗/
btstack linked item t ∗ btstack linked list get first item (
btstack linked list t ∗ list ) ;

/∗ ∗
∗ @ b r i e f Get l a s t e l e m e n t .
∗ @param l i s t
∗ @return f i r s t e l e m e n t or NULL i f l i s t i s empty
∗/
btstack linked item t ∗ btstack linked list get last item (
btstack linked list t ∗ list ) ;

/∗ ∗
∗ @ b r i e f Counts number o f i t e m s i n l i s t
∗ @return number o f i t e m s i n l i s t
∗/
int b t s t a c k l i n k e d l i s t c o u n t ( b t s t a c k l i n k e d l i s t t ∗ l i s t ) ;

/∗ ∗
∗ @ b r i e f I n i t i a l i z e Linked L i s t I t e r a t o r
∗ @note r o b u s t a g a i n s t removal o f c u r r e n t e l e m e n t by
btstack linked list remove
∗ @param i t i t e r a t o r c o n t e x t
∗ @param l i s t
∗/
void b t s t a c k l i n k e d l i s t i t e r a t o r i n i t (
b t s t a c k l i n k e d l i s t i t e r a t o r t ∗ it , b t s t a c k l i n k e d l i s t t ∗
list );

/∗ ∗
∗ @ b r i e f Has n e x t e l e m e n t
∗ @param i t i t e r a t o r c o n t e x t
∗ @return t r u e i f n e x t e l e m e n t i s a v a i l a b l e
∗/
bool b t s t a c k l i n k e d l i s t i t e r a t o r h a s n e x t (
btstack linked list iterator t ∗ it ) ;

/∗ ∗
∗ @ b r i e f Get n e x t l i s t e l e e m n t
∗ @param i t i t e r a t o r c o n t e x t
∗ @return l i s t e l e m e n t
∗/
btstack linked item t ∗ btstack linked list iterator next (
btstack linked list iterator t ∗ it ) ;
356

/∗ ∗
∗ @ b r i e f Remove c u r r e n t l i s t e l e m e n t from l i s t
∗ @param i t i t e r a t o r c o n t e x t
∗/
void b t s t a c k l i n k e d l i s t i t e r a t o r r e m o v e (
btstack linked list iterator t ∗ it ) ;

1.40. Linked Queue API. btstack linked queue.h

typedef struct {
b t s t a c k l i n k e d i t e m t ∗ head ;
btstack linked item t ∗ tail ;
} btstack linked queue t ;

/∗ ∗
∗ @ b r i e f T e s t s i f queue i s empty
∗ @return t r u e i f emtpy
∗/
b o o l b t s t a c k l i n k e d q u e u e e m p t y ( b t s t a c k l i n k e d q u e u e t ∗ queue ) ;

/∗ ∗
∗ @ b r i e f Append item t o queue
∗ @param queue
∗ @param item
∗/
void b t s t a c k l i n k e d q u e u e e n q u e u e ( b t s t a c k l i n k e d q u e u e t ∗ queue ,
b t s t a c k l i n k e d i t e m t ∗ item ) ;

/∗ ∗
∗ @ b r i e f Pop n e x t item from queue
∗ @param queue
∗ @return item or NULL i f queue empty
∗/
btstack linked item t ∗ btstack linked queue dequeue (
btstack linked queue t ∗ queue ) ;

/∗ ∗
∗ @ b r i e f Get f i r s t item from queue
∗ @param queue
∗ @return item or NULL i f queue empty
∗/
btstack linked item t ∗ btstack linked queue first (
b t s t a c k l i n k e d q u e u e t ∗ queue ) ;

1.41. Network Interface API. btstack network.h

/∗ ∗
∗ @ b r i e f I n i t i a l i z e network i n t e r f a c e
∗ @param s e n d p a c k e t c a l l b a c k
357

∗/
void b t s t a c k n e t w o r k i n i t ( void ( ∗ s e n d p a c k e t c a l l b a c k ) ( const uint8 t
∗ packet , uint16 t s i z e ) ) ;

/∗ ∗
∗ @ b r i e f Bring up network i n t e r f a c d
∗ @param n e t w o r k a d d r e s s
∗ @return 0 i f ok
∗/
int b t s t a c k n e t w o r k u p ( bd addr t n e t w o r k a d d r e s s ) ;

/∗ ∗
∗ @ b r i e f Shut down network i n t e r f a c d
∗ @param n e t w o r k a d d r e s s
∗ @return 0 i f ok
∗/
int b t s t a c k n e t w o r k d o w n ( void ) ;

/∗ ∗
∗ @ b r i e f R e c e i v e p a c k e t on network i n t e r f a c e , e . g . , f o r w a r d p a c k e t
t o TCP/IP s t a c k
∗ @param p a c k e t
∗ @param s i z e
∗/
void b t s t a c k n e t w o r k p r o c e s s p a c k e t ( const uint8 t ∗ packet , uint16 t
size ) ;

/∗ ∗
∗ @ b r i e f N o t i f y network i n t e r f a c e t h a t p a c k e t from
s e n d p a c k e t c a l l b a c k was s e n t and t h e n e x t p a c k e t can be
delivered .
∗/
void b t s t a c k n e t w o r k p a c k e t s e n t ( void ) ;

/∗ ∗
∗ @ b r i e f Get network name a f t e r network was a c t i v a t e d
∗ @note e . g . tapX on Linux , might not be u s e f u l on a l l p l a t f o r m s
∗ @return network name
∗/
const char ∗ b t s t a c k n e t w o r k g e t n a m e ( void ) ;

1.42. Lienar Resampling API. btstack resample.h : Linear resampling for


16-bit audio code samples using 16 bit/16 bit fixed point math.

/∗ ∗
∗ @brief I n i t resample context
∗ @param num channels
∗ @return b t s t a c k a u d i o i m p l e m e n t a t i o n
∗/
void b t s t a c k r e s a m p l e i n i t ( b t s t a c k r e s a m p l e t ∗ c o n t e x t , int
num channels ) ;
358

/∗ ∗
∗ @brief Set resampling f a c t o r
∗ @param f a c t o r as f i x e d p o i n t v a l u e , i d e n t i t y i s 0 x10000
∗/
void b t s t a c k r e s a m p l e s e t f a c t o r ( b t s t a c k r e s a m p l e t ∗ c o n t e x t ,
uint32 t f a c t o r ) ;

/∗ ∗
∗ @brief Process b l o c k of input samples
∗ @note s i z e o f o u t p u t b u f f e r i s not c h e c k e d
∗ @param i n p u t b u f f e r
∗ @param num frames
∗ @param o u t p u t b u f f e r
∗ @return number d e s t i n a t i o n frames
∗/
uint16 t b t s t a c k r e s a m p l e b l o c k ( b t s t a c k r e s a m p l e t ∗ c o n t e x t , const
i n t 1 6 t ∗ i n p u t b u f f e r , uint32 t num frames , i n t 1 6 t ∗
output buffer ) ;

1.43. Ring Buffer API. btstack ring buffer.h

/∗ ∗
∗ Init ring buffer
∗ @param r i n g b u f f e r o b j e c t
∗ @param s t o r a g e
∗ @param s t o r a g e s i z e i n b y t e s
∗/
void b t s t a c k r i n g b u f f e r i n i t ( b t s t a c k r i n g b u f f e r t ∗ r i n g b u f f e r ,
uint8 t ∗ s t o r a g e , uint32 t s t o r a g e s i z e ) ;

/∗ ∗
∗ R e s e t r i n g b u f f e r t o i n i t i a l s t a t e ( empty )
∗ @param r i n g b u f f e r o b j e c t
∗/
void b t s t a c k r i n g b u f f e r r e s e t ( b t s t a c k r i n g b u f f e r t ∗ r i n g b u f f e r ) ;

/∗ ∗
∗ Check i f r i n g b u f f e r i s empty
∗ @param r i n g b u f f e r o b j e c t
∗ @return TRUE i f empty
∗/
int b t s t a c k r i n g b u f f e r e m p t y ( b t s t a c k r i n g b u f f e r t ∗ r i n g b u f f e r ) ;

/∗ ∗
∗ Get number o f b y t e s a v a i l a b l e f o r read
∗ @param r i n g b u f f e r o b j e c t
∗ @return number o f b y t e s a v a i l a b l e f o r r ead
∗/
uint32 t b t s t a c k r i n g b u f f e r b y t e s a v a i l a b l e ( b t s t a c k r i n g b u f f e r t ∗
ring buffer ) ;

/∗ ∗
359

∗ Get f r e e s p a c e a v a i l a b l e f o r w r i t e
∗ @param r i n g b u f f e r o b j e c t
∗ @return number o f b y t e s a v a i l a b l e f o r w r i t e
∗/
uint32 t b t s t a c k r i n g b u f f e r b y t e s f r e e ( b t s t a c k r i n g b u f f e r t ∗
ring buffer ) ;

/∗ ∗
∗ Write b y t e s i n t o r i n g b u f f e r
∗ @param r i n g b u f f e r o b j e c t
∗ @param d a t a t o s t o r e
∗ @param d a t a l e n g t h
∗ @return 0 i f ok , ERROR CODE MEMORY CAPACITY EXCEEDED i f not
enough s p a c e i n b u f f e r
∗/
int b t s t a c k r i n g b u f f e r w r i t e ( b t s t a c k r i n g b u f f e r t ∗ r i n g b u f f e r ,
uint8 t ∗ data , uint32 t d a t a l e n g t h ) ;

/∗ ∗
∗ Read from r i n g b u f f e r
∗ @param r i n g b u f f e r o b j e c t
∗ @param b u f f e r t o s t o r e re ad d a t a
∗ @param l e n g t h t o rea d
∗ @param n u m b e r o f b y t e s r e a d
∗/
void b t s t a c k r i n g b u f f e r r e a d ( b t s t a c k r i n g b u f f e r t ∗ r i n g b u f f e r ,
uint8 t ∗ b u f f e r , uint32 t l e n g t h , uint32 t ∗
number of bytes read ) ;

1.44. Sample rate compensation API. btstack sample rate compensation.h


: Prevents buffer over/under-run at the audio receiver by compensating for vary-
ing/different playback/receiving sample rates.
Intended to measure the L2CAP packet sample rate and with the provided
playback sample rate calculates a compensation ratio which compensates for
drift between playback and reception.
Requires the audio interface to provide the current playback sample rate.

#define FLOAT TO Q15( a ) ( ( signed ) ( ( a ) ∗ ( UINT16 C ( 1 ) <<15)+0.5 f ) )


#define FLOAT TO Q8( a ) ( ( signed ) ( ( a ) ∗ ( UINT16 C ( 1 ) <<8)+0.5 f ) )
#define FLOAT TO Q7( a ) ( ( signed ) ( ( a ) ∗ ( UINT16 C ( 1 ) <<7)+0.5 f ) )

#define Q16 TO FLOAT( a ) ( ( f l o a t ) ( a ) / ( UINT32 C ( 1 ) <<16) )


#define Q15 TO FLOAT( a ) ( ( f l o a t ) ( a ) / ( UINT32 C ( 1 ) <<15) )
#define Q8 TO FLOAT( a ) ( ( f l o a t ) ( a ) / ( UINT32 C ( 1 ) <<8))
#define Q7 TO FLOAT( a ) ( ( f l o a t ) ( a ) / ( UINT32 C ( 1 ) <<7))

//#d e f i n e DEBUG RATIO CALCULATION

typedef struct {
uint32 t count ; // 17 b i t a r e u s a b l e t o co u nt samples ,
recommended f o r max 96 kHz
360

uint32 t l a s t ; // time stamp o f l a s t measurement


uint32 t r a t e s t a t e ; // u n s i g n e d Q17 . 8
uint32 t r a t i o s t a t e ; // u n s i g n e d Q16 . 1 6
uint32 t c o n s t a n t p l a y b a c k s a m p l e r a t e ; // p l a y b a c k sample r a t e
i f no r e a l one i s a v a i l a b l e
#i f d e f DEBUG RATIO CALCULATION
double s a m p l e r a t e ;
double r a t i o ;
#endif
} btstack sample rate compensation t ;

/∗ ∗
∗ @ b r i e f I n i t i a l i z e sample r a t e compensation
∗ @param s e l f p o i n t e r t o c u r r e n t i n s t a n c e
∗ @param time stamp a t which t o s t a r t sample r a t e measurement
∗/
void b t s t a c k s a m p l e r a t e c o m p e n s a t i o n i n i t (
b t s t a c k s a m p l e r a t e c o m p e n s a t i o n t ∗ s e l f , uint32 t timestamp ms ,
uint32 t s a m p l e r a t e , uint32 t r a t i o Q 1 5 ) ;

/∗ ∗
∗ @ b r i e f r e s e t sample r a t e compensation
∗ @param s e l f p o i n t e r t o c u r r e n t i n s t a n c e
∗ @param time stamp a t which t o s t a r t sample r a t e measurement
∗/
void b t s t a c k s a m p l e r a t e c o m p e n s a t i o n r e s e t (
b t s t a c k s a m p l e r a t e c o m p e n s a t i o n t ∗ s e l f , uint32 t timestamp ms
);

/∗ ∗
∗ @ b r i e f u p d a t e sample r a t e compensation w i t h t h e c u r r e n t p l a y b a c k
sample r a t e decoded s a m p l e s
∗ @param s e l f p o i n t e r t o c u r r e n t i n s t a n c e
∗ @param time stamp f o r c u r r e n t s a m p l e s
∗ @param s a m p l e s f o r c u r r e n t time stamp
∗ @param p l a y b a c k sample r a t e
∗/
uint32 t b t s t a c k s a m p l e r a t e c o m p e n s a t i o n u p d a t e (
b t s t a c k s a m p l e r a t e c o m p e n s a t i o n t ∗ s e l f , uint32 t timestamp ms ,
uint32 t samples , uint32 t p l a y b a c k s a m p l e r a t e ) ;

1.45. SCO Transport API. btstack sco transport.h : Hardware abstrac-


tion for PCM/I2S Inteface used for HSP/HFP profiles.

typedef struct {

/∗ ∗
∗ r e g i s t e r p a c k e t h a n d l e r f o r SCO HCI p a c k e t s
∗/
void ( ∗ r e g i s t e r p a c k e t h a n d l e r ) ( void ( ∗ h a n d l e r ) ( uint8 t
p a c k e t t y p e , uint8 t ∗ packet , uint16 t s i z e ) ) ;
361

/∗ ∗
∗ open t r a n s p o r t
∗ @param c o n h a n d l e o f SCO c o n n e c t i o n
∗ @param s c o f o r m a t
∗/
void ( ∗ open ) ( h c i c o n h a n d l e t c o n h a n d l e , s c o f o r m a t t
sco format ) ;

/∗ ∗
∗ send SCO p a c k e t
∗/
void ( ∗ s e n d p a c k e t ) ( const uint8 t ∗ b u f f e r , uint16 t l e n g t h ) ;

/∗ ∗
∗ close transport
∗ @param c o n h a n d l e o f SCO c o n n e c t i o n
∗/
void ( ∗ c l o s e ) ( h c i c o n h a n d l e t c o n h a n d l e ) ;

} btstack sco transport t ;

1.46. SLIP encoder/decoder API. btstack slip.h

// ENCODER

/∗ ∗
∗ @ b r i e f I n i t i a l i s e SLIP e n c o d e r w i t h d a t a
∗ @param d a t a
∗ @param l e n
∗/
void b t s t a c k s l i p e n c o d e r s t a r t ( const uint8 t ∗ data , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f Check i f e n c o d e r has d a t a r e a d y
∗ @return True i f d a t a r e a d y
∗/
int b t s t a c k s l i p e n c o d e r h a s d a t a ( void ) ;

/∗ ∗
∗ @ b r i e f Get n e x t b y t e from e n c o d e r
∗ @return Next b y t e s from e n c o d e r
∗/
uint8 t b t s t a c k s l i p e n c o d e r g e t b y t e ( void ) ;

// DECODER

/∗ ∗
∗ @ b r i e f I n i t i a l i s e SLIP d e c o d e r w i t h b u f f e r
∗ @param b u f f e r t o s t o r e r e c e i v e d d a t a
∗ @param m a x s i z e o f b u f f e r
∗/
void b t s t a c k s l i p d e c o d e r i n i t ( uint8 t ∗ b u f f e r , uint16 t m a x s i z e ) ;
362

/∗ ∗
∗ @brief Process r e c e i v e d byte
∗ @param i n p u t
∗/

void b t s t a c k s l i p d e c o d e r p r o c e s s ( uint8 t i n p u t ) ;

/∗ ∗
∗ @ b r i e f Get s i z e o f decoded frame
∗ @return s i z e o f frame . S i z e = 0 => frame not c o m p l e t e
∗/

uint16 t b t s t a c k s l i p d e c o d e r f r a m e s i z e ( void ) ;

1.47. Tag-Value-Length Persistent Storage (TLV) API. btstack tlv.h


: Inteface for BTstack’s Tag Value Length Persistent Storage implementations
used to store pairing/bonding data.

typedef struct {

/∗ ∗
∗ Get Value f o r Tag
∗ @param c o n t e x t
∗ @param t a g
∗ @param b u f f e r
∗ @param b u f f e r s i z e
∗ @return s i z e o f v a l u e
∗/
int ( ∗ g e t t a g ) ( void ∗ c o n t e x t , uint32 t tag , uint8 t ∗ b u f f e r ,
uint32 t b u f f e r s i z e ) ;

/∗ ∗
∗ S t o r e Tag
∗ @param c o n t e x t
∗ @param t a g
∗ @param d a t a
∗ @param d a t a s i z e
∗ @return 0 on s u c c e s s
∗/
int ( ∗ s t o r e t a g ) ( void ∗ c o n t e x t , uint32 t tag , const uint8 t ∗
data , uint32 t d a t a s i z e ) ;

/∗ ∗
∗ D e l e t e Tag
∗ @note i t i s not e x p e c t e d t h a t d e l e t e o p e r a t i o n f a i l s , p l e a s e
use a t l e a s t l o g e r r o r i n c a s e o f e r r o r s
∗ @param c o n t e x t
∗ @param t a g
∗/
void ( ∗ d e l e t e t a g ) ( void ∗ c o n t e x t , uint32 t t a g ) ;
363

} btstack tlv t ;

/∗ ∗
∗ @ b r i e f Make TLV i m p l e m e n t a t i o n a v a i l a b l e t o BTstack components
via Singleton
∗ @note U s u a l l y c a l l e d by p o r t a f t e r BD ADDR was r e t r i e v e d from
Bluetooth Controller
∗ @param t l v i m p l
∗ @param t l v c o n t e x t
∗/
void b t s t a c k t l v s e t i n s t a n c e ( const b t s t a c k t l v t ∗ t l v i m p l , void ∗
tlv context ) ;

/∗ ∗
∗ @ b r i e f Get c u r r e n t TLV i m p l e m e n t a t i o n . Used f o r b o n d i n g
i n f o r m a t i o n , b u t can be used by a p p l i c a t i o n , t o o .
∗ @param t l v i m p l
∗ @param t l v c o n t e x t
∗/
void b t s t a c k t l v g e t i n s t a n c e ( const b t s t a c k t l v t ∗∗ t l v i m p l , void
∗∗ t l v c o n t e x t ) ;

1.48. Empty TLV Instance API. btstack tlv none.h : Empty implemen-
tation for BTstack’s Tag Value Length Persistent Storage implementations No
keys are stored. Can be used as placeholder during porting to new platform.

/∗ ∗
∗ I n i t Tag Length Value S t o r e
∗ @param c o n t e x t b t s t a c k t l v n o n e t
∗ @param h a l f l a s h b a n k i m p l of hal flash bank interface
∗ @Param h a l f l a s h b a n k c o n t e x t o f h a l f l a s h b a n k i n t e r f a c e
∗/
const b t s t a c k t l v t ∗ b t s t a c k t l v n o n e i n i t i n s t a n c e ( void ) ;

1.49. UART API. btstack uart.h : Common types for UART transports

typedef struct {
/∗ ∗
∗ init transport
∗ @param u a r t c o n f i g
∗/
int ( ∗ i n i t ) ( const b t s t a c k u a r t c o n f i g t ∗ u a r t c o n f i g ) ;

/∗ ∗
∗ open t r a n s p o r t c o n n e c t i o n
∗/
int ( ∗ open ) ( void ) ;

/∗ ∗
364

∗ c l o s e transport connection
∗/
int ( ∗ c l o s e ) ( void ) ;

/∗ ∗
∗ s e t c a l l b a c k f o r b l o c k r e c e i v e d . NULL d i s a b l e s c a l l b a c k
∗/
void ( ∗ s e t b l o c k r e c e i v e d ) ( void ( ∗ b l o c k h a n d l e r ) ( void ) ) ;

/∗ ∗
∗ s e t c a l l b a c k f o r s e n t . NULL d i s a b l e s c a l l b a c k
∗/
void ( ∗ s e t b l o c k s e n t ) ( void ( ∗ b l o c k h a n d l e r ) ( void ) ) ;

/∗ ∗
∗ set baudrate
∗/
int ( ∗ s e t b a u d r a t e ) ( uint32 t b a u d r a t e ) ;

/∗ ∗
∗ set parity
∗/
int ( ∗ s e t p a r i t y ) ( int p a r i t y ) ;

/∗ ∗
∗ set flowcontrol
∗/
int ( ∗ s e t f l o w c o n t r o l ) ( int f l o w c o n t r o l ) ;

/∗ ∗
∗ receive block
∗/
void ( ∗ r e c e i v e b l o c k ) ( uint8 t ∗ b u f f e r , uint16 t l e n ) ;

/∗ ∗
∗ send b l o c k
∗/
void ( ∗ s e n d b l o c k ) ( const uint8 t ∗ b u f f e r , uint16 t l e n g t h ) ;

/∗ ∗ S u p p o r t f o r d i f f e r e n t S l e e p Modes i n TI ’ s H4 eHCILL and i n


H5 − can be s e t t o NULL i f not used ∗/

/∗ ∗
∗ q u e r y s u p p o r t e d wakeup mechanisms
∗ @return s u p p o r t e d s l e e p m o d e s mask
∗/
int ( ∗ g e t s u p p o r t e d s l e e p m o d e s ) ( void ) ;

/∗ ∗
∗ s e t UART s l e e p mode − a l l o w s t o t u r n o f f UART and i t ’ s c l o c k s
to save energy
∗ S u p p o r t e d s l e e p modes :
365

∗ − o f f : UART a c t i v e , RTS low i f r e c e i v e b l o c k was c a l l e d and


b l o c k not rea d y e t
∗ − RTS h i g h , wake on CTS: RTS s h o u l d be h i g h . On CTS p u l s e ,
UART g e t s e n a b l e d a g a i n and RTS g o e s t o low
∗ − RTS low , wake on RX: d a t a on RX w i l l t r i g g e r UART e n a b l e ,
b y t e s might g e t l o s t
∗/
void ( ∗ s e t s l e e p ) ( b t s t a c k u a r t s l e e p m o d e t s l e e p m o d e ) ;

/∗ ∗
∗ s e t wakeup h a n d l e r − needed t o n o t i f y h c i t r a n s p o r t o f wakeup
r e q u e s t s by B l u e t o o t h c o n t r o l l e r
∗ C a l l e d upon CTS p u l s e or RX d a t a . See s l e e p modes .
∗/
void ( ∗ s e t w a k e u p h a n d l e r ) ( void ( ∗ wakeup handler ) ( void ) ) ;

/∗ ∗ S u p p o r t f o r HCI H5 T r a n s p o r t Mode − can be s e t t o NULL f o r


H4 ∗/

/∗ ∗
∗ H5/SLIP o n l y : s e t c a l l b a c k f o r frame r e c e i v e d . NULL d i s a b l e s
callback
∗/
void ( ∗ s e t f r a m e r e c e i v e d ) ( void ( ∗ f r a m e h a n d l e r ) ( uint16 t
frame size ) ) ;

/∗ ∗
∗ H5/SLIP o n l y : s e t c a l l b a c k f o r frame s e n t . NULL d i s a b l e s
callback
∗/
void ( ∗ s e t f r a m e s e n t ) ( void ( ∗ b l o c k h a n d l e r ) ( void ) ) ;

/∗ ∗
∗ H5/SLIP o n l y : r e c e i v e SLIP frame
∗/
void ( ∗ r e c e i v e f r a m e ) ( uint8 t ∗ b u f f e r , uint16 t l e n ) ;

/∗ ∗
∗ H5/SLIP o n l y : send SLIP frame
∗/
void ( ∗ s e n d f r a m e ) ( const uint8 t ∗ b u f f e r , uint16 t l e n g t h ) ;

} btstack uart t ;

1.50. UART Block API. btstack uart block.h : Compatibility layer for
ports that use btstack uart block t

typedef b t s t a c k u a r t t b t s t a c k u a r t b l o c k t ;

// e x i s t i n g b l o c k −o n l y i m p l e m e n t a t i o n s
366

const b t s t a c k u a r t b l o c k t ∗ b t s t a c k u a r t b l o c k w i n d o w s i n s t a n c e (
void ) ;
const b t s t a c k u a r t b l o c k t ∗ b t s t a c k u a r t b l o c k e m b e d d e d i n s t a n c e (
void ) ;
const b t s t a c k u a r t b l o c k t ∗ b t s t a c k u a r t b l o c k f r e e r t o s i n s t a n c e (
void ) ;

// mapper f o r e x t e n d e d i m p l e m e n t a t i o n
s t a t i c i n l i n e const b t s t a c k u a r t b l o c k t ∗
b t s t a c k u a r t b l o c k p o s i x i n s t a n c e ( void ) {
return ( const b t s t a c k u a r t b l o c k t ∗ )
btstack uart posix instance () ;
}
/∗ API STOP ∗/

#i f d e f i n e d cplusplus
}
#endif

#endif

1.51. UART SLIP Wrapper API. btstack uart slip wrapper.h : Com-
patibility layer to use new H5 implementation with btstack uart.h implemen-
tations without SLIP support. Using this compatibility layer caused increased
processing as it uses single byte UART reads.
If you’re using H5, please consider implement the H5/SLIP functions in your
btstack uart.h or hal uart dma.h implementation.

/∗ ∗
∗ @ b r i e f I n i t i a l i z e SLIP wrapper f o r e x i s t i n g b t s t a c k u a r t b l o c k t
i n s t a n c e w i t h o u t SLIP s u p p o r t
∗ @param u a r t b l o c k w i t h o u t s l i p
∗ @return b t s t a c k u a r t t i n s t a n c e w i t h SLIP s u p p o r t f o r use w i t h
hci trasnport h5
∗/
const b t s t a c k u a r t t ∗ b t s t a c k u a r t s l i p w r a p p e r i n s t a n c e ( const
btstack uart t ∗ uart without slip ) ;

1.52. General Utility Functions API. btstack util.h

/∗ ∗
∗ @ b r i e f Minimum f u n c t i o n f o r u i n t 3 2 t
∗ @param a
∗ @param b
∗ @return v a l u e
∗/
uint32 t b t s t a c k m i n ( uint32 t a , uint32 t b ) ;

/∗ ∗
367

∗ @ b r i e f Maximum f u n c t i o n f o r u i n t 3 2 t
∗ @param a
∗ @param b
∗ @return v a l u e
∗/
uint32 t btstack max ( uint32 t a , uint32 t b ) ;

/∗ ∗
∗ @ b r i e f C a l c u l a t e d e l t a b e t w e e n two u i n t 3 2 t p o i n t s i n time
∗ @return t i m e a − t i m e b − r e s u l t > 0 i f t i m e a i s newer than
time b
∗/
i n t 3 2 t b t s t a c k t i m e d e l t a ( uint32 t ti me a , uint32 t t i m e b ) ;

/∗ ∗
∗ @ b r i e f C a l c u l a t e d e l t a b e t w e e n two u i n t 1 6 t p o i n t s i n time
∗ @return t i m e a − t i m e b − r e s u l t > 0 i f t i m e a i s newer than
time b
∗/
i n t 1 6 t b t s t a c k t i m e 1 6 d e l t a ( uint16 t ti me a , uint16 t t i m e b ) ;

/∗ ∗
∗ @ b r i e f Read 16/24/32 b i t l i t t l e endian v a l u e from buffer
∗ @param b u f f e r
∗ @param p o s i t i o n i n b u f f e r
∗ @return v a l u e
∗/
uint16 t l i t t l e e n d i a n r e a d 1 6 ( const uint8 t ∗ b u f f e r , int p o s i t i o n )
;
uint32 t l i t t l e e n d i a n r e a d 2 4 ( const uint8 t ∗ b u f f e r , int p o s i t i o n )
;
uint32 t l i t t l e e n d i a n r e a d 3 2 ( const uint8 t ∗ b u f f e r , int p o s i t i o n )
;

/∗ ∗
∗ @ b r i e f Write 16/32 b i t l i t t l e endian v a l u e into buffer
∗ @param b u f f e r
∗ @param p o s i t i o n i n b u f f e r
∗ @param v a l u e
∗/
void l i t t l e e n d i a n s t o r e 1 6 ( uint8 t ∗ b u f f e r , uint16 t p o s i t i o n ,
uint16 t v a l u e ) ;
void l i t t l e e n d i a n s t o r e 2 4 ( uint8 t ∗ b u f f e r , uint16 t p o s i t i o n ,
uint32 t v a l u e ) ;
void l i t t l e e n d i a n s t o r e 3 2 ( uint8 t ∗ b u f f e r , uint16 t p o s i t i o n ,
uint32 t v a l u e ) ;

/∗ ∗
∗ @ b r i e f Read 16/24/32 b i t b i g endian v a l u e from b u f f e r
∗ @param b u f f e r
∗ @param p o s i t i o n i n b u f f e r
∗ @return v a l u e
∗/
uint32 t b i g e n d i a n r e a d 1 6 ( const uint8 t ∗ b u f f e r , int p o s i t i o n ) ;
368

uint32 t b i g e n d i a n r e a d 2 4 ( const uint8 t ∗ b u f f e r , int p o s i t i o n ) ;


uint32 t b i g e n d i a n r e a d 3 2 ( const uint8 t ∗ b u f f e r , int p o s i t i o n ) ;

/∗ ∗
∗ @ b r i e f Write 16/32 b i t b i g endian v a l u e i n t o b u f f e r
∗ @param b u f f e r
∗ @param p o s i t i o n i n buffer
∗ @param v a l u e
∗/
void b i g e n d i a n s t o r e 1 6 ( uint8 t ∗ b u f f e r , uint16 t p o s i t i o n ,
uint16 t v a l u e ) ;
void b i g e n d i a n s t o r e 2 4 ( uint8 t ∗ b u f f e r , uint16 t p o s i t i o n ,
uint32 t v a l u e ) ;
void b i g e n d i a n s t o r e 3 2 ( uint8 t ∗ b u f f e r , uint16 t p o s i t i o n ,
uint32 t v a l u e ) ;

/∗ ∗
∗ @ b r i e f Swap b y t e s i n 16 b i t i n t e g e r
∗/
s t a t i c i n l i n e uint16 t b t s t a c k f l i p 1 6 ( uint16 t v a l u e ) {
return ( uint16 t ) ( ( v a l u e & 0 x f f u ) << 8 ) | ( v a l u e >> 8 ) ;
}

/∗ ∗
∗ @ b r i e f Check f o r b i g endian system
∗ @return 1 i f on b i g endian
∗/
s t a t i c i n l i n e int b t s t a c k i s b i g e n d i a n ( void ) {
uint16 t sample = 0 x0100 ;
return ( int ) ∗ ( uint8 t ∗ ) &sample ;
}

/∗ ∗
∗ @ b r i e f Check f o r l i t t l e endian system
∗ @return 1 i f on l i t t l e endian
∗/
s t a t i c i n l i n e int b t s t a c k i s l i t t l e e n d i a n ( void ) {
uint16 t sample = 0 x0001 ;
return ( int ) ∗ ( uint8 t ∗ ) &sample ;
}

/∗ ∗
∗ @ b r i e f Copy from s o u r c e t o d e s t i n a t i o n and r e v e r s e b y t e o r d e r
∗ @param s r c
∗ @param d e s t
∗ @param l e n
∗/
void r e v e r s e b y t e s ( const uint8 t ∗ s r c , uint8 t ∗ d e s t , int l e n ) ;

/∗ ∗
∗ @ b r i e f Wrapper around r e v e r s e b y t e s f o r common b u f f e r s i z e s
∗ @param s r c
∗ @param d e s t
369

∗/
void reverse 2 4 ( const uint8 t ∗ src , uint8 t ∗ dest ) ;
void reverse 4 8 ( const uint8 t ∗ src , uint8 t ∗ dest ) ;
void reverse 5 6 ( const uint8 t ∗ src , uint8 t ∗ dest ) ;
void reverse 6 4 ( const uint8 t ∗ src , uint8 t ∗ dest ) ;
void reverse 1 2 8 ( const uint8 t ∗ src , uint8 t ∗ dest ) ;
void reverse 2 5 6 ( const uint8 t ∗ src , uint8 t ∗ dest ) ;

void r e v e r s e b d a d d r ( const bd addr t s r c , bd addr t d e s t ) ;

/∗ ∗
∗ @ b r i e f Check i f a l l b y t e s i n b u f f e r a r e z e r o
∗ @param b u f f e r
∗ @param s i z e
∗ @return t r u e i f a l l b y t e s i s b u f f e r a r e z e r o
∗/
b o o l b t s t a c k i s n u l l ( const uint8 t ∗ b u f f e r , uint16 t s i z e ) ;

/∗ ∗
∗ @ b r i e f Check i f a l l b y t e s i n a b d a d d r t a r e z e r o
∗ @param addr
∗ @return t r u e i f a l l b y t e s i n addr a r e z e r o
∗/
b o o l b t s t a c k i s n u l l b d a d d r ( const bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f ASCII c h a r a c t e r f o r 4− b i t n i b b l e
∗ @return c h a r a c t e r
∗/
char c h a r f o r n i b b l e ( uint8 t n i b b l e ) ;

/∗ ∗
∗ @ b r i f 4− b i t n i b b l e from ASCII c h a r a c t e r
∗ @return v a l u e
∗/
int n i b b l e f o r c h a r ( char c ) ;

/∗ ∗
∗ @ b r i e f Compare two B l u e t o o t h a d d r e s s e s
∗ @param a
∗ @param b
∗ @return 0 i f e q u a l
∗/
int bd addr cmp ( const bd addr t a , const bd addr t b ) ;

/∗ ∗
∗ @ b r i e f Copy B l u e t o o t h a d d r e s s
∗ @param d e s t
∗ @param s r c
∗/
void b d a d d r c o p y ( bd addr t d e s t , const bd addr t s r c ) ;

/∗ ∗
∗ @ b r i e f Use p r i n t f t o w r i t e hexdump as s i n g l e l i n e o f d a t a
370

∗/
void p r i n t f h e x d u m p ( const void ∗ data , int s i z e ) ;

/∗ ∗
∗ @ b r i e f C r ea t e human r e a d a b l e r e p r e s e n t a t i o n f o r UUID128
∗ @note u s e s f i x e d g l o b a l b u f f e r
∗ @return p o i n t e r t o UUID128 s t r i n g
∗/
char ∗ u u i d 1 2 8 t o s t r ( const uint8 t ∗ uuid ) ;

/∗ ∗
∗ @ b r i e f C r ea t e human r e a d a b l e r e p r e s e n a t i o n t o f B l u e t o o t h a d d r e s s
∗ @note u s e s f i x e d g l o b a l b u f f e r
∗ @param d e l i m i t e r
∗ @return p o i n t e r t o B l u e t o o t h a d d r e s s s t r i n g
∗/
char ∗ b d a d d r t o s t r w i t h d e l i m i t e r ( const bd addr t addr , char
delimiter ) ;

/∗ ∗
∗ @ b r i e f C r ea t e human r e a d a b l e r e p r e s e n a t i o n t o f B l u e t o o t h a d d r e s s
∗ @note u s e s f i x e d g l o b a l b u f f e r
∗ @return p o i n t e r t o B l u e t o o t h a d d r e s s s t r i n g
∗/
char ∗ b d a d d r t o s t r ( const bd addr t addr ) ;

/∗ ∗
∗ @brief Replace address p l a c e h o l d e r ’ 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ’ with
Bluetooth address
∗ @param b u f f e r
∗ @param s i z e
∗ @param a d d r e s s
∗/
void b t s t a c k r e p l a c e b d a d d r p l a c e h o l d e r ( uint8 t ∗ b u f f e r , uint16 t
s i z e , const bd addr t a d d r e s s ) ;

/∗ ∗
∗ @ b r i e f Parse B l u e t o o t h a d d r e s s
∗ @param a d d r e s s s t r i n g
∗ @param b u f f e r f o r p a r s e d a d d r e s s
∗ @return 1 i f s t r i n g was p a r s e d s u c c e s s f u l l y
∗/
int s s c a n f b d a d d r ( const char ∗ a d d r s t r i n g , bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f C o n s t r u c t s UUID128 from 16 or 32 b i t UUID u s i n g B l u e t o o t h
b a s e UUID
∗ @param uuid128 o u t p u t b u f f e r
∗ @param s h o r t u u i d
∗/
void u u i d a d d b l u e t o o t h p r e f i x ( uint8 t ∗ uuid128 , uint32 t
short uuid ) ;

/∗ ∗
371

∗ @ b r i e f Checks i f UUID128 has B l u e t o o t h b a s e UUID p r e f i x


∗ @param uui128 t o t e s t
∗ @return t r u e i f i t can be e x p r e s s e d as UUID32
∗/
b o o l u u i d h a s b l u e t o o t h p r e f i x ( const uint8 t ∗ uuid128 ) ;

/∗ ∗
∗ @ b r i e f Parse u n s i g n e d number
∗ @param s t r t o p a r s e
∗ @return v a l u e
∗/
uint32 t b t s t a c k a t o i ( const char ∗ s t r ) ;

/∗ ∗
∗ @ b r i e f Return number o f d i g i t s o f a u i n t 3 2 number
∗ @param u i n t 3 2 n u m b e r
∗ @return n u m d i g i t s
∗/
int s t r i n g l e n f o r u i n t 3 2 ( uint32 t i ) ;

/∗ ∗
∗ @ b r i e f Return number o f s e t b i t s i n a u i n t 3 2 number
∗ @param u i n t 3 2 n u m b e r
∗ @return n u m s e t b i t s
∗/
int c o u n t s e t b i t s u i n t 3 2 ( uint32 t x ) ;

/∗ ∗
∗ @ b r i e f Check CRC8 u s i n g ETSI TS 101 369 V6 . 3 . 0 .
∗ @note Only used by RFCOMM
∗ @param d a t a
∗ @param l e n
∗ @param check sum
∗/
uint8 t b t s t a c k c r c 8 c h e c k ( uint8 t ∗ data , uint16 t l e n , uint8 t
check sum ) ;

/∗ ∗
∗ @ b r i e f C a l c u l a t e CRC8 u s i n g ETSI TS 101 369 V6 . 3 . 0 .
∗ @note Only used by RFCOMM
∗ @param d a t a
∗ @param l e n
∗/
uint8 t b t s t a c k c r c 8 c a l c ( uint8 t ∗ data , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f C a l c u l a t e t h e i n i t i a l CRC32 v a l u e u s i n g ISO 3309 (HDLC) ,
p o l y n o m i a l ( normal ) 0 x04c11db7
∗ @note Used by OTS S e r v i c e .

∗ @return The i n i t i a l c r c v a l u e .
∗/
uint32 t b t s t a c k c r c 3 2 i n i t ( void ) ;
372

/∗ ∗
∗ @ b r i e f Update t h e CRC32 v a l u e w i t h new d a t a .

∗ @param c r c The c u r r e n t c r c v a l u e .
∗ @param d a t a P o i n t e r t o a b u f f e r o f \a d a t a l e n b y t e s .
∗ @param d a t a l e n Number o f b y t e s i n t h e \a d a t a b u f f e r .
∗ @return The u p d a t e d c r c v a l u e .
∗/
uint32 t b t s t a c k c r c 3 2 u p d a t e ( uint32 t c r c , const uint8 t ∗ data ,
uint32 t d a t a l e n ) ;

/∗ ∗
∗ @ b r i e f C a l c u l a t e t h e f i n a l CRC32 v a l u e .

∗ @param c r c The c u r r e n t c r c v a l u e .
∗ @return The f i n a l c r c v a l u e .
∗/
uint32 t b t s t a c k c r c 3 2 f i n a l i z e ( uint32 t c r c ) ;

/∗ ∗
∗ @ b r i e f Get n e x t c i d
∗ @param c u r r e n t c i d
∗ @return n e x t c i d s k i p i n g 0
∗/
uint16 t b t s t a c k n e x t c i d i g n o r i n g z e r o ( uint16 t c u r r e n t c i d ) ;

/∗ ∗
∗ @ b r i e f Copy s t r i n g ( up t o d s t s i z e −1 c h a r a c t e r s ) from s r c i n t o
dst b u f f e r with terminating ’\0 ’
∗ @note r e p l a c e s s t r n c p y + d s t [ d s t s i z e −1] = ’ \ 0 ’
∗ @param d s t
∗ @param d s t s i z e
∗ @param s r c
∗ @retun b y t e s c o p i e d i n c l u d i n g t r a i l i n g 0
∗/
uint16 t b t s t a c k s t r c p y ( char ∗ dst , uint16 t d s t s i z e , const char ∗
src ) ;

/∗ ∗
∗ @ b r i e f Append s r c s t r i n g t o s t r i n g i n d s t b u f f e r w i t h t e r m i n a t i n g
’\0 ’
∗ @note max t o t a l s t r i n g l e n g t h w i l l be d s t s i z e −1 c h a r a c t e r s
∗ @param d s t
∗ @param d s t s i z e
∗ @param s r c
∗/
void b t s t a c k s t r c a t ( char ∗ dst , uint16 t d s t s i z e , const char ∗ s r c )
;

/∗ ∗
∗ Returns t h e number o f l e a d i n g 0− b i t s i n x , s t a r t i n g a t t h e most
significant bit position .
∗ I f x i s 0 , the r e s u l t i s undefined .
373

∗ @note maps t o b u i l t i n c l z f o r g c c and c l a n g


∗ @param v a l u e
∗ @return number o f l e a d i n g 0− b i t s
∗/
uint8 t b t s t a c k c l z ( uint32 t v a l u e ) ;

/∗ ∗
∗ @ b r i e f Copy chunk o f d a t a i n t o a v i r t u a l b u f f e r b a c k e d by a
physical buffer .
∗ Used t o p r o v i d e chunk o f d a t a o f l a r g e r b u f f e r t h a t i s
c o n s t r u c t e d on t h e f l y , e . g . s e r i a l i z i n g d a t a s t r u c t

∗ For example , copy f i e l d 2 t o b u f f e r , w i t h b u f f e r o f f s e t = 11

∗ field1 field2 field3 field4 field5 filed6
∗ struct :
−−−−−−−|−−−−−−−|−−−−−−−−−−|−−−−−−−−−−−−−|−−−−−−−|−−−−−−−−−−−−−−
∗ buffer : −−−−−−−−−−−−−−−−−−
∗ result : −−−−|

∗ When a l s o c o p y i n g f i e l d 3 and f i e l d 4 t o b u f f e r , w i t h b u f f e r o f f s e t
= 11

∗ field1 field2 field3 field4 field5 filed6
∗ struct :
−−−−−−−|−−−−−−−|−−−−−−−−−−|−−−−−−−−−−−−−|−−−−−−−|−−−−−−−−−−−−−−
∗ buffer : −−−−−−−−−−−−−−−−−−
∗ result : −−−−|−−−−−−−−−−|−−

∗ @param f i e l d d a t a
∗ @param f i e l d l e n
∗ @param f i e l d o f f s e t p o s i t i o n of f i e l d in complete data b l o c k
∗ @param b u f f e r d a t a
∗ @param b u f f e r l e n
∗ @param b u f f e r o f f s e t p o s i t i o n o f b u f f e r i n c o m p l e t e d a t a b l o c k
∗ @return b y t e s c o p i e d number o f b y t e s a c t u a l l y s t o r e d i n b u f f e r
∗/
uint16 t b t s t a c k v i r t u a l m e m c p y (
const uint8 t ∗ f i e l d d a t a , uint16 t f i e l d l e n , uint16 t
field offset ,
uint8 t ∗ b u f f e r , uint16 t b u f f e r s i z e , uint16 t b u f f e r o f f s e t ) ;

1.53. A2DP Sink API. a2dp sink.h : Audio/Video Distribution Transport


Protocol A2DP Sink is a device that accepts streamed media data.

/∗ ∗
∗ @ b r i e f C r ea t e A2DP S i n k s e r v i c e r e c o r d .
∗ @param s e r v i c e
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param s u p p o r t e d f e a t u r e s 16− b i t bitmap , s e e AVDTP SINK SF ∗
values in avdtp . h
374

∗ @param s e r v i c e n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty


s t r i n g ) to skip a t t r i b u t e
∗ @param s e r v i c e p r o v i d e r n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e
”” ( empty s t r i n g ) t o s k i p a t t r i b u t e
∗/
void a 2 d p s i n k c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t s u p p o r t e d f e a t u r e s , const char ∗
s e r v i c e n a m e , const char ∗ s e r v i c e p r o v i d e r n a m e ) ;

/∗ ∗
∗ @ b r i e f I n i t i a l i z e up A2DP S i n k d e v i c e .
∗/
void a 2 d p s i n k i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f C r ea t e a stream e n d p o i n t o f t y p e SINK , and r e g i s t e r media
c od e c by s p e c i f y i n g i t s c a p a b i l i t i e s and t h e d e f a u l t
configuration .
∗ @param m e d i a t y p e see avdtp media type t values in
a v d t p . h ( audio , v i d e o or m u l t i m e d i a )
∗ @param m e d i a c o d e c t y p e see avdtp media codec type t
values in avdtp . h
∗ @param c o d e c c a p a b i l i t i e s media c od e c c a p a b i l i t i e s as
d e f i n e d i n A2DP spec , s e c t i o n 4 − Audio Codec I n t e r o p e r a b i l i t y
Requirements .
∗ @param c o d e c c a p a b i l i t i e s l e n media co d ec c a p a b i l i t i e s l e n g t h
∗ @param c o d e c c o n f i g u r a t i o n d e f a u l t media co d ec
configuration
∗ @param c o d e c c o n f i g u r a t i o n l e n media co de c c o n f i g u r a t i o n l e n g t h

∗ @return l o c a l s t r e a m e n d p o i n t
∗/
avdtp stream endpoint t ∗ a2dp sink create stream endpoint (
a v d t p m e d i a t y p e t media type , a v d t p m e d i a c o d e c t y p e t
media codec type ,
const
uint8 t

codec capabilities
,
uint16 t

codec capabilities len


,
uint8 t

codec configuration
,
uint16 t

codec configuration l
);

/∗ ∗
375

∗ @ b r i e f U n r e g i s t e r stream e n d p o i n t and f r e e i t ’ s memory


∗ @param s t r e a m e n d p o i n t c r e a t e d by
a2dp sink create stream endpoint
∗/
void a 2 d p s i n k f i n a l i z e s t r e a m e n d p o i n t ( a v d t p s t r e a m e n d p o i n t t ∗
stream endpoint ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e A2DP S i n k c l i e n t . I t w i l l
r e c e i v e f o l l o w i n g s u b e v e n t s o f HCI EVENT A2DP META HCI e v e n t
type :
∗ − A2DP SUBEVENT SIGNALING MEDIA CODEC SBC CONFIGURATION :
i n d i c a t e s from remote chosen SBC media c od e c c o n f i g u r a t i o n
∗ − A2DP SUBEVENT SIGNALING MEDIA CODEC OTHER CONFIGURATION:
i n d i c a t e s from remote chosen o t h e r t h e n SBC media co d ec
configuration
∗ − A2DP SUBEVENT STREAM ESTABLISHED:
r e c e i v e d when stream t o a remote d e v i c e i s e s t a b l i s h e d
∗ − A2DP SUBEVENT STREAM STARTED:
r e c e i v e d when stream i s s t a r t e d
∗ − A2DP SUBEVENT STREAM SUSPENDED:
r e c e i v e d when stream i s paused
∗ − A2DP SUBEVENT STREAM STOPED:
r e c e i v e d when stream i s a b o r t e d or s t o p p e d
∗ − A2DP SUBEVENT STREAM RELEASED:
r e c e i v e d when stream i s r e l e a s e d
∗ − A2DP SUBEVENT SIGNALING CONNECTION RELEASED :
r e c e i v e d when s i g n a l i n g c h a n n e l i s d i s c o n n e c t e d

∗ @param c a l l b a c k
∗/
void a 2 d p s i n k r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r media h a n d l e r f o r t h e A2DP S i n k c l i e n t .
∗ @param c a l l b a c k
∗ @param p a c k e t
∗ @param s i z e
∗/
void a 2 d p s i n k r e g i s t e r m e d i a h a n d l e r ( void ( ∗ c a l l b a c k ) ( uint8 t
l o c a l s e i d , uint8 t ∗ packet , uint16 t s i z e ) ) ;

/∗ ∗
∗ @ b r i e f E s t a b l i s h stream .
∗ @param remote
∗ @param o u t a 2 d p c i d A s s i g n e d A2DP c h a n n e l i d e n t i f i e r used
f o r f u r h t e r A2DP commands .
∗/
uint8 t a 2 d p s i n k e s t a b l i s h s t r e a m ( bd addr t remote , uint16 t ∗
out a2dp cid ) ;

#i f d e f ENABLE AVDTP ACCEPTOR EXPLICIT START STREAM CONFIRMATION


/∗ ∗
376

∗ @ b r i e f Accept s t a r t i n g t h e stream on
A2DP SUBEVENT START STREAM REQUESTED e v e n t .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
uint8 t a 2 d p s i n k s t a r t s t r e a m a c c e p t ( uint16 t a 2 d p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f R e j e c t s t a r t i n g t h e stream on
A2DP SUBEVENT START STREAM REQUESTED e v e n t .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
uint8 t a 2 d p s i n k s t a r t s t r e a m r e j e c t ( uint16 t a 2 d p c i d , uint8 t
local seid ) ;
#endif

/∗ ∗
∗ @ b r i e f R e l e a s e stream and d i s c o n n e c t from remote .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗/
void a 2 d p s i n k d i s c o n n e c t ( uint16 t a 2 d p c i d ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e SBC e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n SBC C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s i n k s e t c o n f i g s b c ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const a v d t p c o n f i g u r a t i o n s b c t
∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e MPEG AUDIO e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n MPEG AUDIO C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s i n k s e t c o n f i g m p e g a u d i o ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const
avdtp configuration mpeg audio t ∗ configuration ) ;

/∗ ∗
∗ @brief S e l e c t and c o n f i g u r e MPEG AAC e n d p o i n t
∗ @param a2dp cid A2DP c h a n n e l i d e n t i f i e r .
∗ @param local seid ID o f a l o c a l stream e n d p o i n t .
∗ @param remote seid ID o f a remote stream e n d p o i n t .
∗ @param configuration MPEG AAC C o n f i g u r a t i o n
377

∗ @return s t a t u s
∗/
uint8 t a 2 d p s i n k s e t c o n f i g m p e g a a c ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const
avdtp configuration mpeg aac t ∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e ATRAC e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n ATRAC C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s i n k s e t c o n f i g a t r a c ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const
avdtp configuration atrac t ∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e Non−A2DP e n d p o i n t . B y t e s 0−3 o f c od ec
i n f o r m a t i o n c o n t a i n Vendor ID , b y t e s 4−5 c o n t a i n Vendor
S p e c i f i c Codec ID ( l i t t l e endian )
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param m e d i a c o d e c i n f o r m a t i o n
∗ @param m e d i a c o d e c i n f o r m a t i o n l e n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s i n k s e t c o n f i g o t h e r ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const uint8 t ∗
m e d i a c o d e c i n f o r m a t i o n , uint8 t m e d i a c o d e c i n f o r m a t i o n l e n ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r media c o n f i g u r a t i o n v a l i d a t o r . Can r e j e c t
i n s u i t a b l e c o n f i g u r a t i o n or r e p o r t stream e n d p o i n t as c u r r e n t l y
busy
∗ @note v a l i d a t o r has t o r e t u r n AVDTP e r r o r c o d e s l i k e :
AVDTP ERROR CODE SEP IN USE or
AVDTP ERROR CODE UNSUPPORTED CONFIGURATION
∗ t h e c a l l b a c k r e c e i v e s t h e media c o n f i g u r a t i o n i n t h e same
f o r m a t as t h e e x i s t i n g
A2dP SUBEVENT SIGNALING MEDIA CODEC SBC CONFIGURATION
∗ and s i m i l a r
∗ @param c a l l b a c k
∗/
void a 2 d p s i n k r e g i s t e r m e d i a c o n f i g v a l i d a t o r ( uint8 t ( ∗ c a l l b a c k ) (
const a v d t p s t r e a m e n d p o i n t t ∗ s t r e a m e n d p o i n t , const uint8 t ∗
event , uint16 t s i z e ) ) ;

/∗ ∗
∗ @ b r i e f De−I n i t A2DP S i n k d e v i c e .
∗/
void a 2 d p s i n k d e i n i t ( void ) ;
378

1.54. A2DP Source API. a2dp source.h : Audio/Video Distribution Trans-


port Protocol A2DP Source is a device that streames media data.

/∗ ∗
∗ @ b r i e f C r ea t e A2DP Source s e r v i c e r e c o r d .
∗ @param s e r v i c e
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param s u p p o r t e d f e a t u r e s 16− b i t bitmap , s e e AVDTP SOURCE SF ∗
values in avdtp . h
∗ @param s e r v i c e n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty
s t r i n g ) to skip a t t r i b u t e
∗ @param s e r v i c e p r o v i d e r n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e
”” ( empty s t r i n g ) t o s k i p a t t r i b u t e
∗/
void a 2 d p s o u r c e c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t s u p p o r t e d f e a t u r e s , const char ∗
s e r v i c e n a m e , const char ∗ s e r v i c e p r o v i d e r n a m e ) ;

/∗ ∗
∗ @ b r i e f I n i t i a l i z e up A2DP Source d e v i c e .
∗/
void a 2 d p s o u r c e i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f C r ea t e a stream e n d p o i n t o f t y p e SOURCE, and r e g i s t e r
media c o de c by s p e c i f y i n g i t s c a p a b i l i t i e s and t h e d e f a u l t
configuration .
∗ @param m e d i a t y p e See a v d t p m e d i a t y p e t v a l u e s i n
a v d t p . h ( audio , v i d e o or m u l t i m e d i a ) .
∗ @param m e d i a c o d e c t y p e See a v d t p m e d i a c o d e c t y p e t
values in avdtp . h
∗ @param c o d e c c a p a b i l i t i e s Media c od e c c a p a b i l i t i e s as
d e f i n e d i n A2DP spec , s e c t i o n 4 − Audio Codec I n t e r o p e r a b i l i t y
Requirements .
∗ @param c o d e c c a p a b i l i t i e s l e n Media co d ec c a p a b i l i t i e s l e n g t h .
∗ @param c o d e c c o n f i g u r a t i o n D e f a u l t media co d ec
configuration .
∗ @param c o d e c c o n f i g u r a t i o n l e n Media co d ec c o n f i g u r a t i o n l e n g t h
.

∗ @return l o c a l s t r e a m e n d p o i n t
∗/
avdtp stream endpoint t ∗ a2dp source create stream endpoint (
a v d t p m e d i a t y p e t media type , a v d t p m e d i a c o d e c t y p e t
media codec type ,
379

const
uint8 t

codec capabilities
,
uint16 t

codec capabilities le
,
uint8 t

codec configuration
,
uint16 t

codec configuration
);

/∗ ∗
∗ @ b r i e f U n r e g i s t e r stream e n d p o i n t and f r e e i t ’ s memory
∗ @param s t r e a m e n d p o i n t c r e a t e d by
a2dp source create stream endpoint
∗/
void a 2 d p s o u r c e f i n a l i z e s t r e a m e n d p o i n t ( a v d t p s t r e a m e n d p o i n t t ∗
stream endpoint ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e A2DP Source c l i e n t . I t w i l l
r e c e i v e f o l l o w i n g s u b e v e n t s o f HCI EVENT A2DP META HCI e v e n t
type :
∗ − A2DP SUBEVENT STREAMING CAN SEND MEDIA PACKET NOW:
I n d i c a t e s t h a t t h e n e x t media p a c k e t can be s e n t .

∗ − A2DP SUBEVENT SIGNALING CONNECTION ESTABLISHED
R e c e i v e d when s i g n a l i n g c o n n e c t i o n w i t h a remote i s e s t a b l i s h e d
.
∗ − A2DP SUBEVENT SIGNALING CONNECTION RELEASED
R e c e i v e d when s i g n a l i n g c o n n e c t i o n w i t h a remote i s r e l e a s e d
∗ − A2DP SUBEVENT STREAM ESTABLISHED
R e c e i v e d when stream t o a remote d e v i c e i s e s t a b l i s h e d .
∗ − A2DP SUBEVENT STREAM STARTED
R e c e i v e d when stream i s s t a r t e d .
∗ − A2DP SUBEVENT STREAM SUSPENDED
R e c e i v e d when stream i s paused .
∗ − A2DP SUBEVENT STREAM STOPED
r e c e i v e d when stream i s a b o r t e d or s t o p p e d .
∗ − A2DP SUBEVENT STREAM RELEASED
R e c e i v e d when stream i s r e l e a s e d .
∗ − A2DP SUBEVENT SIGNALING DELAY REPORTING CAPABILITY
Currently the only c a p a b i l i t y that i s passed to c l i e n t
∗ − A2DP SUBEVENT SIGNALING CAPABILITIES DONE
S i g n a l s t h a t a l l c a p a b i l i t i e s are reported
∗ − A2DP SUBEVENT SIGNALING DELAY REPORT
Delay r e p o r t
380

∗ − A2DP SUBEVENT SIGNALING MEDIA CODEC SBC CONFIGURATION SBC


configuration
∗ − A2DP SUBEVENT STREAMING CAN SEND MEDIA PACKET NOW
S i g n a l s t h a t a media p a c k e t can be s e n t
∗ − A2DP SUBEVENT COMMAND REJECTED
Command r e j e c t
∗ @param c a l l b a c k
∗/
void a 2 d p s o u r c e r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f Open stream .
∗ @param r e m o t e a d d r
∗ @param a v d t p c i d A s s i g n e d A2DP c h a n n e l i d e n t i f i e r used
f o r f u r t h e r A2DP commands .
∗/
uint8 t a 2 d p s o u r c e e s t a b l i s h s t r e a m ( bd addr t remote addr , uint16 t
∗ avdtp cid ) ;

/∗ ∗
∗ @ b r i e f R e c o n f i g u r e stream .
∗ @param l o c a l s e i d ID a s s i g n e d t o a l o c a l stream
endpoint
∗ @param s a m p l i n g f r e q u e n c y New s a m p l i n g f r e q u e n c y t o use .
Cannot be c a l l e d w h i l e stream i s a c t i v e
∗/
uint8 t a 2 d p s o u r c e r e c o n f i g u r e s t r e a m s a m p l i n g f r e q u e n c y ( uint16 t
a 2 d p c i d , uint32 t s a m p l i n g f r e q u e n c y ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
uint8 t a 2 d p s o u r c e s t a r t s t r e a m ( uint16 t a 2 d p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f Pause stream .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
uint8 t a 2 d p s o u r c e p a u s e s t r e a m ( uint16 t a 2 d p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f R e l e a s e stream and d i s c o n n e c t from remote .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗/
uint8 t a 2 d p s o u r c e d i s c o n n e c t ( uint16 t a 2 d p c i d ) ;

/∗ ∗
381

∗ @ b r i e f R e q u e s t t o send a media p a c k e t . P a c ke t can be t h e n s e n t on


r e c e p t i o n o f A2DP SUBEVENT STREAMING CAN SEND MEDIA PACKET NOW
event .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
void a 2 d p s o u r c e s t r e a m e n d p o i n t r e q u e s t c a n s e n d n o w ( uint16 t
a 2 d p c i d , uint8 t l o c a l s e i d ) ;

/∗ ∗
∗ @ b r i e f Return maximal media p a y l o a d s i z e , d o e s not i n c l u d e media
header .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @return m a x m e d i a p a y l o a d s i z e w i t h o u t m e d i a h e a d e r
∗/
int a 2 d p m a x m e d i a p a y l o a d s i z e ( uint16 t a 2 d p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f Send media p a y l o a d .
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param marker
∗ @param timestamp i n sample r a t e u n i t s
∗ @param p a y l o a d
∗ @param p a y l o a d s i z e
∗ @param marker
∗ @return s t a t u s
∗/
uint8 t a 2 d p s o u r c e s t r e a m s e n d m e d i a p a y l o a d r t p ( uint16 t a 2 d p c i d ,
uint8 t l o c a l s e i d , uint8 t marker , uint32 t timestamp ,
uint8 t ∗ payload , uint16 t
payload size ) ;

/∗ ∗
∗ @ b r i e f Send media p a c k e t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param p a c k e t
∗ @param s i z e
∗ @return s t a t u s
∗/
uint8 t a 2 d p s o u r c e s t r e a m s e n d m e d i a p a c k e t ( uint16 t a 2 d p c i d ,
uint8 t l o c a l s e i d , const uint8 t ∗ packet , uint16 t s i z e ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e SBC e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n SBC C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
382

uint8 t a 2 d p s o u r c e s e t c o n f i g s b c ( uint16 t a 2 d p c i d , uint8 t


l o c a l s e i d , uint8 t r e m o t e s e i d , const a v d t p c o n f i g u r a t i o n s b c t
∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e MPEG AUDIO e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n MPEG AUDIO C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s o u r c e s e t c o n f i g m p e g a u d i o ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const
avdtp configuration mpeg audio t ∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e MPEG AAC e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n MPEG AAC C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s o u r c e s e t c o n f i g m p e g a a c ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const
avdtp configuration mpeg aac t ∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e ATRAC e n d p o i n t
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param c o n f i g u r a t i o n ATRAC C o n f i g u r a t i o n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s o u r c e s e t c o n f i g a t r a c ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const
avdtp configuration atrac t ∗ configuration ) ;

/∗ ∗
∗ @ b r i e f S e l e c t and c o n f i g u r e Non−A2DP e n d p o i n t . B y t e s 0−3 o f c od ec
i n f o r m a t i o n c o n t a i n Vendor ID , b y t e s 4−5 c o n t a i n Vendor
S p e c i f i c Codec ID ( l i t t l e endian )
∗ @param a 2 d p c i d A2DP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param r e m o t e s e i d ID o f a remote stream e n d p o i n t .
∗ @param m e d i a c o d e c i n f o r m a t i o n
∗ @param m e d i a c o d e c i n f o r m a t i o n l e n
∗ @return s t a t u s
∗/
uint8 t a 2 d p s o u r c e s e t c o n f i g o t h e r ( uint16 t a 2 d p c i d , uint8 t
l o c a l s e i d , uint8 t r e m o t e s e i d , const uint8 t ∗
m e d i a c o d e c i n f o r m a t i o n , uint8 t m e d i a c o d e c i n f o r m a t i o n l e n ) ;
383

/∗ ∗
∗ @ b r i e f R e g i s t e r media c o n f i g u r a t i o n v a l i d a t o r . Can r e j e c t
i n s u i t a b l e c o n f i g u r a t i o n or r e p o r t stream e n d p o i n t as c u r r e n t l y
busy
∗ @note v a l i d a t o r has t o r e t u r n AVDTP e r r o r c o d e s l i k e :
AVDTP ERROR CODE SEP IN USE or
AVDTP ERROR CODE UNSUPPORTED CONFIGURATION
∗ t h e c a l l b a c k r e c e i v e s t h e media c o n f i g u r a t i o n i n t h e same
f o r m a t as t h e e x i s t i n g
A2dP SUBEVENT SIGNALING MEDIA CODEC SBC CONFIGURATION
∗ and s i m i l a r
∗ @param c a l l b a c k
∗/
void a 2 d p s o u r c e r e g i s t e r m e d i a c o n f i g v a l i d a t o r ( uint8 t ( ∗ c a l l b a c k )
( const a v d t p s t r e a m e n d p o i n t t ∗ s t r e a m e n d p o i n t , const uint8 t
∗ event , uint16 t s i z e ) ) ;

/∗ ∗
∗ @ b r i e f De−I n i t A2DP Source d e v i c e .
∗/
void a 2 d p s o u r c e d e i n i t ( void ) ;

1.55. AVDTP Sink API. avdtp sink.h : Audio/Video Distribution Trans-


port Protocol (AVDTP) Sink is a device that accepts streamed media data.

/∗ ∗
∗ @ b r i e f S e t up AVDTP S i n k d e v i c e .
∗/
void a v d t p s i n k i n i t ( void ) ;

// r e t u r n s a v d t p s t r e a m e n d p o i n t t ∗
avdtp stream endpoint t ∗ avdtp sink create stream endpoint (
a v d t p s e p t y p e t sep type , avdtp media type t media type ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r stream e n d p o i n t and f r e e i t ’ s memory
∗ @param s t r e a m e n d p o i n t c r e a t e d by
avdtp sink create stream endpoint
∗/
void a v d t p s i n k f i n a l i z e s t r e a m e n d p o i n t ( a v d t p s t r e a m e n d p o i n t t ∗
stream endpoint ) ;

void a v d t p s i n k r e g i s t e r m e d i a t r a n s p o r t c a t e g o r y ( uint8 t s e i d ) ;
void a v d t p s i n k r e g i s t e r r e p o r t i n g c a t e g o r y ( uint8 t s e i d ) ;
void a v d t p s i n k r e g i s t e r d e l a y r e p o r t i n g c a t e g o r y ( uint8 t s e i d ) ;
void a v d t p s i n k r e g i s t e r r e c o v e r y c a t e g o r y ( uint8 t s e i d , uint8 t
maximum recovery window size , uint8 t
maximum number media packets ) ;
void a v d t p s i n k r e g i s t e r h e a d e r c o m p r e s s i o n c a t e g o r y ( uint8 t s e i d ,
uint8 t back ch , uint8 t media , uint8 t r e c o v e r y ) ;
384

void a v d t p s i n k r e g i s t e r m u l t i p l e x i n g c a t e g o r y ( uint8 t s e i d , uint8 t


fragmentation ) ;

void a v d t p s i n k r e g i s t e r m e d i a c o d e c c a t e g o r y ( uint8 t s e i d ,
a v d t p m e d i a t y p e t media type , a v d t p m e d i a c o d e c t y p e t
m e d i a c o d e c t y p e , const uint8 t ∗ m e d i a c o d e c i n f o , uint16 t
media codec info len ) ;
void a v d t p s i n k r e g i s t e r c o n t e n t p r o t e c t i o n c a t e g o r y ( uint8 t s e i d ,
uint16 t c p t y p e , const uint8 t ∗ c p t y p e v a l u e , uint8 t
cp type value len ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVDTP S i n k c l i e n t .
∗ @param c a l l b a c k
∗/
void a v d t p s i n k r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f Connect t o d e v i c e w i t h a b l u e t o o t h a d d r e s s . ( and perform
c o n f i g u r a t i o n ?)
∗ @param b d a d d r
∗ @param a v d t p c i d A s s i g n e d a v d t p c i d
∗/
uint8 t a v d t p s i n k c o n n e c t ( bd addr t bd addr , uint16 t ∗ a v d t p c i d ) ;

void a v d t p s i n k r e g i s t e r m e d i a h a n d l e r ( void ( ∗ c a l l b a c k ) ( uint8 t


l o c a l s e i d , uint8 t ∗ packet , uint16 t s i z e ) ) ;
/∗ ∗
∗ @ b r i e f D i s c o n n e c t from d e v i c e w i t h c o n n e c t i o n h a n d l e .
∗ @param a v d t p c i d
∗/
uint8 t a v d t p s i n k d i s c o n n e c t ( uint16 t a v d t p c i d ) ;

/∗ ∗
∗ @ b r i e f D i s c o v e r stream e n d p o i n t s
∗ @param a v d t p c i d
∗/
uint8 t a v d t p s i n k d i s c o v e r s t r e a m e n d p o i n t s ( uint16 t a v d t p c i d ) ;

/∗ ∗
∗ @ b r i e f Get c a p a b i l i t i e s
∗ @param a v d t p c i d
∗/
uint8 t a v d t p s i n k g e t c a p a b i l i t i e s ( uint16 t a v d t p c i d , uint8 t
acp seid ) ;

/∗ ∗
∗ @ b r i e f Get a l l c a p a b i l i t i e s
∗ @param a v d t p c i d
∗/
uint8 t a v d t p s i n k g e t a l l c a p a b i l i t i e s ( uint16 t a v d t p c i d , uint8 t
acp seid ) ;
385

/∗ ∗
∗ @brief Set configuration
∗ @param a v d t p c i d
∗/
uint8 t a v d t p s i n k s e t c o n f i g u r a t i o n ( uint16 t a v d t p c i d , uint8 t
i n t s e i d , uint8 t a c p s e i d , uint16 t c o n f i g u r e d s e r v i c e s b i t m a p ,
avdtp capabilities t configuration ) ;

/∗ ∗
∗ @ b r i e f R e c o n f i g u r e stream
∗ @param a v d t p c i d
∗ @param s e i d
∗/
uint8 t a v d t p s i n k r e c o n f i g u r e ( uint16 t a v d t p c i d , uint8 t i n t s e i d ,
uint8 t a c p s e i d , uint16 t c o n f i g u r e d s e r v i c e s b i t m a p ,
avdtp capabilities t configuration ) ;

/∗ ∗
∗ @ b r i e f Get c o n f i g u r a t i o n
∗ @param a v d t p c i d
∗/
uint8 t a v d t p s i n k g e t c o n f i g u r a t i o n ( uint16 t a v d t p c i d , uint8 t
acp seid ) ;

/∗ ∗
∗ @ b r i e f Open stream
∗ @param a v d t p c i d
∗ @param s e i d
∗/
uint8 t a v d t p s i n k o p e n s t r e a m ( uint16 t a v d t p c i d , uint8 t i n t s e i d ,
uint8 t a c p s e i d ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream
∗ @param l o c a l s e i d
∗/
uint8 t a v d t p s i n k s t a r t s t r e a m ( uint16 t a v d t p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f Abort stream
∗ @param l o c a l s e i d
∗/
uint8 t a v d t p s i n k a b o r t s t r e a m ( uint16 t a v d t p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream
∗ @param l o c a l s e i d
∗/
uint8 t a v d t p s i n k s t o p s t r e a m ( uint16 t a v d t p c i d , uint8 t
local seid ) ;
386

/∗ ∗
∗ @ b r i e f Suspend stream
∗ @param l o c a l s e i d
∗/
uint8 t a v d t p s i n k s u s p e n d ( uint16 t a v d t p c i d , uint8 t l o c a l s e i d ) ;

/∗ ∗
∗ @ b r i e f Report d e l a y
∗ @param l o c a l s e i d
∗ @param d e l a y 1 0 0 u s
∗/
uint8 t a v d t p s i n k d e l a y r e p o r t ( uint16 t a v d t p c i d , uint8 t
l o c a l s e i d , uint16 t d e l a y 1 0 0 u s ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r media c o n f i g u r a t i o n v a l i d a t o r . Can r e j e c t
i n s u i t a b l e c o n f i g u r a t i o n or r e p o r t stream e n d p o i n t as c u r r e n t l y
busy
∗ @note v a l i d a t o r has t o r e t u r n AVDTP e r r o r c o d e s l i k e :
AVDTP ERROR CODE SEP IN USE or
AVDTP ERROR CODE UNSUPPORTED CONFIGURATION
∗ t h e c a l l b a c k r e c e i v e s t h e media c o n f i g u r a t i o n i n t h e same
f o r m a t as t h e e x i s t i n g
AVDTP SUBEVENT SIGNALING MEDIA CODEC SBC CONFIGURATION
∗ and s i m i l a r
∗ @param c a l l b a c k
∗/
void a v d t p s i n k r e g i s t e r m e d i a c o n f i g v a l i d a t o r ( uint8 t ( ∗ c a l l b a c k ) (
const a v d t p s t r e a m e n d p o i n t t ∗ s t r e a m e n d p o i n t , const uint8 t ∗
event , uint16 t s i z e ) ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVDTP S i n k .
∗/
void a v d t p s i n k d e i n i t ( void ) ;

// AVDTP SI DELAYREPORT

1.56. AVDTP Source API. avdtp source.h : Audio/Video Distribution Trans-


port Protocol (AVDTP) Source is a device that streames media data.

/∗ ∗
∗ @ b r i e f R e g i s t e r media t r a n s p o r t c a t e g o r y w i t h l o c a l stream
e n d p o i n t i d e n t i f i e d by s e i d
∗ @param s e i d
∗/
void a v d t p s o u r c e r e g i s t e r m e d i a t r a n s p o r t c a t e g o r y ( uint8 t s e i d ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r r e p o r t i n g c a t e g o r y w i t h l o c a l stream e n d p o i n t
i d e n t i f i e d by s e i d
387

∗ @param s e i d
∗/
void a v d t p s o u r c e r e g i s t e r r e p o r t i n g c a t e g o r y ( uint8 t s e i d ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r d e l a y r e p o r t i n g c a t e g o r y w i t h l o c a l stream
e n d p o i n t i d e n t i f i e d by s e i d
∗ @param s e i d
∗/
void a v d t p s o u r c e r e g i s t e r d e l a y r e p o r t i n g c a t e g o r y ( uint8 t s e i d ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r r e c o v e r y c a t e g o r y w i t h l o c a l stream e n d p o i n t
i d e n t i f i e d by s e i d
∗ @param s e i d
∗ @param m a x i m u m r e c o v e r y w i n d o w s i z e
∗ @param maximum number media packets
∗/
void a v d t p s o u r c e r e g i s t e r r e c o v e r y c a t e g o r y ( uint8 t s e i d , uint8 t
maximum recovery window size , uint8 t
maximum number media packets ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c o n t e n t p r o t e c t i o n c a t e g o r y w i t h l o c a l stream
e n d p o i n t i d e n t i f i e d by s e i d
∗ @param s e i d
∗ @param c p t y p e
∗ @param c p t y p e v a l u e
∗ @param c p t y p e v a l u e l e n
∗/
void a v d t p s o u r c e r e g i s t e r c o n t e n t p r o t e c t i o n c a t e g o r y ( uint8 t s e i d ,
uint16 t c p t y p e , const uint8 t ∗ c p t y p e v a l u e , uint8 t
cp type value len ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r h e a d e r c o m p r e s s i o n c a t e g o r y w i t h l o c a l stream
e n d p o i n t i d e n t i f i e d by s e i d
∗ @param s e i d
∗ @param b a c k c h
∗ @param media
∗ @param r e c o v e r y
∗/
void a v d t p s o u r c e r e g i s t e r h e a d e r c o m p r e s s i o n c a t e g o r y ( uint8 t s e i d ,
uint8 t back ch , uint8 t media , uint8 t r e c o v e r y ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r media c od e c c a t e g o r y w i t h l o c a l stream e n d p o i n t
i d e n t i f i e d by s e i d
∗ @param s e i d
∗ @param m e d i a t y p e
∗ @param m e d i a c o d e c t y p e
∗ @param m e d i a c o d e c i n f o
∗ @param m e d i a c o d e c i n f o l e n
∗/
388

void a v d t p s o u r c e r e g i s t e r m e d i a c o d e c c a t e g o r y ( uint8 t s e i d ,
a v d t p m e d i a t y p e t media type , a v d t p m e d i a c o d e c t y p e t
m e d i a c o d e c t y p e , const uint8 t ∗ m e d i a c o d e c i n f o , uint16 t
media codec info len ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r m u l t i p l e x i n g c a t e g o r y w i t h l o c a l stream e n d p o i n t
i d e n t i f i e d by s e i d
∗ @param s e i d
∗ @param f r a g m e n t a t i o n
∗/
void a v d t p s o u r c e r e g i s t e r m u l t i p l e x i n g c a t e g o r y ( uint8 t s e i d ,
uint8 t f r a g m e n t a t i o n ) ;

/∗ ∗
∗ @ b r i e f I n i t i a l i z e up AVDTP Source d e v i c e .
∗/
void a v d t p s o u r c e i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVDTP Source c l i e n t . See
b t s t a c k d e f i n e s . h f o r AVDTP SUBEVENT ∗ e v e n t s

∗ @param c a l l b a c k
∗/
void a v d t p s o u r c e r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f Connect t o d e v i c e w i t h a b l u e t o o t h a d d r e s s . ( and perform
c o n f i g u r a t i o n ?)
∗ @param b d a d d r
∗ @param a v d t p c i d A s s i g n e d a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
BTSTACK MEMORY ALLOC FAILED, SDP QUERY BUSY
∗/
uint8 t a v d t p s o u r c e c o n n e c t ( bd addr t bd addr , uint16 t ∗ a v d t p c i d
);

/∗ ∗
∗ @ b r i e f D i s c o n n e c t from d e v i c e w i t h c o n n e c t i o n h a n d l e .
∗ @param a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER
∗/
uint8 t a v d t p s o u r c e d i s c o n n e c t ( uint16 t a v d t p c i d ) ;

/∗ ∗
∗ @ b r i e f D i s c o v e r stream e n d p o i n t s
∗ @param a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
389

uint8 t a v d t p s o u r c e d i s c o v e r s t r e a m e n d p o i n t s ( uint16 t a v d t p c i d ) ;

/∗ ∗
∗ @ b r i e f Get c a p a b i l i t i e s
∗ @param a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e g e t c a p a b i l i t i e s ( uint16 t a v d t p c i d , uint8 t
acp seid ) ;

/∗ ∗
∗ @ b r i e f Get a l l c a p a b i l i t i e s
∗ @param a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e g e t a l l c a p a b i l i t i e s ( uint16 t a v d t p c i d ,
uint8 t a c p s e i d ) ;

/∗ ∗
∗ @brief Set configuration
∗ @param a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e s e t c o n f i g u r a t i o n ( uint16 t a v d t p c i d , uint8 t
i n t s e i d , uint8 t a c p s e i d , uint16 t c o n f i g u r e d s e r v i c e s b i t m a p ,
avdtp capabilities t configuration ) ;

/∗ ∗
∗ @ b r i e f R e c o n f i g u r e stream
∗ @param a v d t p c i d
∗ @param s e i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e r e c o n f i g u r e ( uint16 t a v d t p c i d , uint8 t
i n t s e i d , uint8 t a c p s e i d , uint16 t c o n f i g u r e d s e r v i c e s b i t m a p ,
avdtp capabilities t configuration ) ;

/∗ ∗
∗ @ b r i e f Get c o n f i g u r a t i o n
∗ @param a v d t p c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e g e t c o n f i g u r a t i o n ( uint16 t a v d t p c i d , uint8 t
acp seid ) ;
390

/∗ ∗
∗ @ b r i e f Open stream
∗ @param a v d t p c i d
∗ @param s e i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e o p e n s t r e a m ( uint16 t a v d t p c i d , uint8 t
i n t s e i d , uint8 t a c p s e i d ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream
∗ @param l o c a l s e i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e s t a r t s t r e a m ( uint16 t a v d t p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f Abort stream
∗ @param l o c a l s e i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e a b o r t s t r e a m ( uint16 t a v d t p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f S t a r t stream
∗ @param l o c a l s e i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e s t o p s t r e a m ( uint16 t a v d t p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f Suspend stream
∗ @param l o c a l s e i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t a v d t p s o u r c e s u s p e n d ( uint16 t a v d t p c i d , uint8 t l o c a l s e i d )
;

/∗ ∗
391

∗ @ b r i e f C r ea t e stream e n d p o i n t
∗ @param s e p t y p e AVDTP SOURCE or AVDTP SINK, s e e a v d t p . h
∗ @param m e d i a t y p e AVDTP AUDIO, AVDTP VIDEO or
AVDTP MULTIMEDIA, s e e a v d t p . h
∗ @return p o i n t e r t o newly c r e a t e d stream e n d p o i n t , or NULL i f
allocation failed
∗/
avdtp stream endpoint t ∗ avdtp source create stream endpoint (
a v d t p s e p t y p e t sep type , avdtp media type t media type ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r stream e n d p o i n t and f r e e i t ’ s memory
∗ @param s t r e a m e n d p o i n t c r e a t e d by
avdtp sink create stream endpoint
∗/
void a v d t p s o u r c e f i n a l i z e s t r e a m e n d p o i n t ( a v d t p s t r e a m e n d p o i n t t ∗
stream endpoint ) ;

/∗ ∗
∗ @ b r i e f Send media p a c k e t
∗ @param a v d t p c i d AVDTP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param p a c k e t
∗ @param s i z e
∗ @return s t a t u s
∗/
uint8 t a v d t p s o u r c e s t r e a m s e n d m e d i a p a c k e t ( uint16 t a v d t p c i d ,
uint8 t l o c a l s e i d , const uint8 t ∗ packet , uint16 t s i z e ) ;

/∗ ∗
∗ @ b r i e f Send media p a y l o a d i n c l u d i n g RTP h e a d e r
∗ @param a v d t p c i d AVDTP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗ @param marker
∗ @param timestamp i n sample r a t e u n i t s
∗ @param p a y l o a d
∗ @param s i z e
∗ @return s t a t u s
∗/
uint8 t a v d t p s o u r c e s t r e a m s e n d m e d i a p a y l o a d r t p ( uint16 t
a v d t p c i d , uint8 t l o c a l s e i d , uint8 t marker , uint32 t
timestamp ,
const uint8 t ∗ payload ,
uint16 t s i z e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t t o send a media p a c k e t . P a c ke t can be t h e n s e n t on
reception of
AVDTP SUBEVENT STREAMING CAN SEND MEDIA PACKET NOW e v e n t .
∗ @param a v d t p c i d AVDTP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
void a v d t p s o u r c e s t r e a m e n d p o i n t r e q u e s t c a n s e n d n o w ( uint16 t
avddp cid , uint8 t l o c a l s e i d ) ;
392

/∗ ∗
∗ @ b r i e f Return maximal media p a y l o a d s i z e , d o e s not i n c l u d e media
header .
∗ @param a v d t p c i d AVDTP c h a n n e l i d e n t i f i e r .
∗ @param l o c a l s e i d ID o f a l o c a l stream e n d p o i n t .
∗/
int a v d t p m a x m e d i a p a y l o a d s i z e ( uint16 t a v d t p c i d , uint8 t
local seid ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r media c o n f i g u r a t i o n v a l i d a t o r . Can r e j e c t
i n s u i t a b l e c o n f i g u r a t i o n or r e p o r t stream e n d p o i n t as c u r r e n t l y
busy
∗ @note v a l i d a t o r has t o r e t u r n AVDTP e r r o r c o d e s l i k e :
AVDTP ERROR CODE SEP IN USE or
AVDTP ERROR CODE UNSUPPORTED CONFIGURATION
∗ t h e c a l l b a c k r e c e i v e s t h e media c o n f i g u r a t i o n i n t h e same
f o r m a t as t h e e x i s t i n g
AVDTP SUBEVENT SIGNALING MEDIA CODEC SBC CONFIGURATION
∗ and s i m i l a r
∗ @param c a l l b a c k
∗/
void a v d t p s o u r c e r e g i s t e r m e d i a c o n f i g v a l i d a t o r ( uint8 t ( ∗ c a l l b a c k
) ( const a v d t p s t r e a m e n d p o i n t t ∗ s t r e a m e n d p o i n t , const uint8 t
∗ event , uint16 t s i z e ) ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVDTP Source .
∗/
void a v d t p s o u r c e d e i n i t ( void ) ;

1.57. AVRCP Browsing API. avrcp browsing.h

/∗ ∗
∗ @ b r i e f S e t up AVRCP Browsing s e r v i c e
∗/
void a v r c p b r o w s i n g i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVRCP Browsing C o n t r o l l e r c l i e n t
.
∗ @param c a l l b a c k
∗/
void a v r c p b r o w s i n g r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @brief Connect t o AVRCP Browsing s e r v i c e on a remote d e v i c e ,
e m i t s AVRCP SUBEVENT BROWSING CONNECTION ESTABLISHED w i t h
status
∗ @param remote addr
393

∗ @param ertm buffer


∗ @param ertm buffer size
∗ @param ertm config
∗ @param a v r c p b r o w s i n g c i d o u t g o i n g parameter , v a l i d i f s t a t u s
== ERROR CODE SUCCESS
∗ @return s t a t u s
∗/
uint8 t a v r c p b r o w s i n g c o n n e c t ( bd addr t remote addr , uint8 t ∗
e r t m b u f f e r , uint32 t e r t m b u f f e r s i z e , l 2 c a p e r t m c o n f i g t ∗
e r t m c o n f i g , uint16 t ∗ a v r c p b r o w s i n g c i d ) ;

/∗ ∗
∗ @ b r i e f C o n f i g u r e incoming c o n n e c t i o n f o r Browsing S e r v i c e .
∗ @param a v r c p b r o w s i n g c i d
∗ @param e r t m b u f f e r
∗ @param e r t m b u f f e r s i z e
∗ @param e r t m c o n f i g
∗ @return s t a t u s
∗/
uint8 t a v r c p b r o w s i n g c o n f i g u r e i n c o m i n g c o n n e c t i o n ( uint16 t
a v r c p b r o w s i n g c i d , uint8 t ∗ e r t m b u f f e r , uint32 t
ertm buffer size , l2cap ertm config t ∗ ertm config ) ;

/∗ ∗
∗ @ b r i e f D e c l i n e incoming c o n n e c t i o n Browsing S e r v i c e .
∗ @param a v r c p b r o w s i n g c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p b r o w s i n g d e c l i n e i n c o m i n g c o n n e c t i o n ( uint16 t
avrcp browsing cid ) ;

/∗ ∗
∗ @brief D i s c o n n e c t from AVRCP Browsing s e r v i c e
∗ @param avrcp browsing cid
∗ @return s t a t u s
∗/
uint8 t a v r c p b r o w s i n g d i s c o n n e c t ( uint16 t a v r c p b r o w s i n g c i d ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVRCP Browsing
∗/
void a v r c p b r o w s i n g d e i n i t ( void ) ;

1.58. AVRCP Browsing Controller API. avrcp browsing controller.h

typedef enum {
AVRCP BROWSING MEDIA PLAYER ITEM = 0 x01 ,
AVRCP BROWSING FOLDER ITEM,
AVRCP BROWSING MEDIA ELEMENT ITEM,
AVRCP BROWSING MEDIA ROOT FOLDER,
AVRCP BROWSING MEDIA ELEMENT ITEM ATTRIBUTE
} avrcp browsing item type t ;
394

typedef enum {
AVRCP BROWSING MEDIA PLAYER MAJOR TYPE AUDIO = 1 ,
AVRCP BROWSING MEDIA PLAYER MAJOR TYPE VIDEO = 2 ,
AVRCP BROWSING MEDIA PLAYER MAJOR TYPE BROADCASTING AUDIO = 4 ,
AVRCP BROWSING MEDIA PLAYER MAJOR TYPE BROADCASTING VIDEO = 8
} avrcp browsing media player major type t ;

typedef enum {
AVRCP BROWSING MEDIA PLAYER SUBTYPE AUDIO BOOK = 1 ,
AVRCP BROWSING MEDIA PLAYER SUBTYPE POADCAST = 2
} avrcp browsing media player subtype t ;

typedef enum {
AVRCP BROWSING MEDIA PLAYER STATUS STOPPED = 0 ,
AVRCP BROWSING MEDIA PLAYER STATUS PLAYING,
AVRCP BROWSING MEDIA PLAYER STATUS PAUSED,
AVRCP BROWSING MEDIA PLAYER STATUS FWD SEEK,
AVRCP BROWSING MEDIA PLAYER STATUS REV SEEK,
AVRCP BROWSING MEDIA PLAYER STATUS ERROR = 0xFF
} avrcp browsing media player status t ;

typedef enum {
AVRCP BROWSING FOLDER TYPE MIXED = 0 x00 ,
AVRCP BROWSING FOLDER TYPE TITLES,
AVRCP BROWSING FOLDER TYPE ALBUMS,
AVRCP BROWSING FOLDER TYPE ARTISTS,
AVRCP BROWSING FOLDER TYPE GENRES,
AVRCP BROWSING FOLDER TYPE PLAYLISTS,
AVRCP BROWSING FOLDER TYPE YEARS
} avrcp browsing folder type t ;

typedef enum {
AVRCP BROWSING MEDIA TYPE AUDIO = 0 x00 ,
AVRCP BROWSING MEDIA TYPE VIDEO
} avrcp browsing media type t ;

/∗ ∗
∗ @ b r i e f S e t up AVRCP Browsing C o n t r o l l e r d e v i c e .
∗/
void a v r c p b r o w s i n g c o n t r o l l e r i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVRCP Browsing C o n t r o l l e r c l i e n t
.
∗ @param c a l l b a c k
∗/
void a v r c p b r o w s i n g c o n t r o l l e r r e g i s t e r p a c k e t h a n d l e r (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f R e t r i e v e a l i s t o f media p l a y e r s .
∗ @param a v r c p b r o w s i n g c i d
∗ @param s t a r t i t e m
395

∗ @param e n d i t e m
∗ @param a t t r b i t m a p Use AVRCP MEDIA ATTR ALL f o r a l l , and
AVRCP MEDIA ATTR NONE f o r none . Otherwise , s e e
a v r c p m e d i a a t t r i b u t e i d t f o r t h e bitmap p o s i t i o n o f a t t r s .
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r g e t m e d i a p l a y e r s ( uint16 t
a v r c p b r o w s i n g c i d , uint32 t s t a r t i t e m , uint32 t end item ,
uint32 t a t t r b i t m a p ) ;

/∗ ∗
∗ @ b r i e f R e t r i e v e a l i s t o f f o l d e r s and media i t e m s o f t h e browsed
player .
∗ @param a v r c p b r o w s i n g c i d
∗ @param s t a r t i t e m
∗ @param e n d i t e m
∗ @param a t t r b i t m a p Use AVRCP MEDIA ATTR ALL f o r a l l , and
AVRCP MEDIA ATTR NONE f o r none . Otherwise , s e e
a v r c p m e d i a a t t r i b u t e i d t f o r t h e bitmap p o s i t i o n o f a t t r s .
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r b r o w s e f i l e s y s t e m ( uint16 t
a v r c p b r o w s i n g c i d , uint32 t s t a r t i t e m , uint32 t end item ,
uint32 t a t t r b i t m a p ) ;

/∗ ∗
∗ @ b r i e f R e t r i e v e a l i s t o f media i t e m s o f t h e browsed p l a y e r .
∗ @param a v r c p b r o w s i n g c i d
∗ @param s t a r t i t e m
∗ @param e n d i t e m
∗ @param a t t r b i t m a p Use AVRCP MEDIA ATTR ALL f o r a l l , and
AVRCP MEDIA ATTR NONE f o r none . Otherwise , s e e
a v r c p m e d i a a t t r i b u t e i d t f o r t h e bitmap p o s i t i o n o f a t t r s .
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r b r o w s e m e d i a ( uint16 t
a v r c p b r o w s i n g c i d , uint32 t s t a r t i t e m , uint32 t end item ,
uint32 t a t t r b i t m a p ) ;

/∗ ∗
∗ @ b r i e f R e t r i e v e a l i s t o f f o l d e r s and media i t e m s o f t h e
addressed player .
∗ @param a v r c p b r o w s i n g c i d
∗ @param s t a r t i t e m
∗ @param e n d i t e m
∗ @param a t t r b i t m a p Use AVRCP MEDIA ATTR ALL f o r a l l , and
AVRCP MEDIA ATTR NONE f o r none . Otherwise , s e e
a v r c p m e d i a a t t r i b u t e i d t f o r t h e bitmap p o s i t i o n o f a t t r s .
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r b r o w s e n o w p l a y i n g l i s t ( uint16 t
a v r c p b r o w s i n g c i d , uint32 t s t a r t i t e m , uint32 t end item ,
uint32 t a t t r b i t m a p ) ;

/∗ ∗
∗ @ b r i e f S e t browsed p l a y e r . C a l l i n g t h i s command i s r e q u i r e d p r i o r
t o b r o w s i n g t h e p l a y e r ’ s f i l e system . Some p l a y e r s may s u p p o r t
b r o w s i n g o n l y when s e t as t h e Addressed P l a y e r .
396

∗ @param a v r c p b r o w s i n g c i d
∗ @param b r o w s e d p l a y e r i d
∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r s e t b r o w s e d p l a y e r ( uint16 t
a v r c p b r o w s i n g c i d , uint16 t b r o w s e d p l a y e r i d ) ;

/∗ ∗
∗ @ b r i e f Get t o t a l num a t t r i b u t e s
∗ @param a v r c p b r o w s i n g c i d
∗ @param s c o p e
∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r g e t t o t a l n r i t e m s f o r s c o p e (
uint16 t a v r c p b r o w s i n g c i d , a v r c p b r o w s i n g s c o p e t s c o p e ) ;

/∗ ∗
∗ @ b r i e f N a v i g a t e one l e v e l up or down i n t h h e v i r t u a l f i l e s y s t e m .
R e q u i r e s t h a t s browsed p l a y e r i s s e t .
∗ @param a v r c p b r o w s i n g c i d
∗ @param d i r e c t i o n 0− f o l d e r up , 1− f o l d e r down
∗ @param f o l d e r u i d 8 bytes long
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r c h a n g e p a t h ( uint16 t
a v r c p b r o w s i n g c i d , uint8 t d i r e c t i o n , uint8 t ∗ f o l d e r u i d ) ;
uint8 t a v r c p b r o w s i n g c o n t r o l l e r g o u p o n e l e v e l ( uint16 t
avrcp browsing cid ) ;
uint8 t a v r c p b r o w s i n g c o n t r o l l e r g o d o w n o n e l e v e l ( uint16 t
a v r c p b r o w s i n g c i d , uint8 t ∗ f o l d e r u i d ) ;

/∗ ∗
∗ @ b r i e f R e t r i v e s metadata i n f o r m a t i o n ( t i t l e , a r t i s t , album , . . . )
a b o u t a media e l e m e n t w i t h g i v e n u i d .
∗ @param a v r c p b r o w s i n g c i d
∗ @param u i d media e l e m e n t u i d
∗ @param u i d c o u n t e r Used t o d e t e c t change t o t h e media d a t a b a s e
on t a r g e t d e v i c e . A TG d e v i c e t h a t s u p p o r t s t h e UID Counter
s h a l l u p d a t e t h e v a l u e o f t h e c o u n t e r on each change t o t h e
media d a t a b a s e .
∗ @param a t t r b i t m a p 0 x00000000 − r e t r i e v e a l l , c h e k
a v r c p m e d i a a t t r i b u t e i d t in avrcp . h f o r d e t a i l e d b i t p o s i t i o n
description .
∗ @param s c o p e check a v r c p b r o w s i n g s c o p e t in avrcp . h
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r g e t i t e m a t t r i b u t e s f o r s c o p e (
uint16 t a v r c p b r o w s i n g c i d , uint8 t ∗ uid , uint16 t u i d c o u n t e r
, uint32 t a t t r b i t m a p , a v r c p b r o w s i n g s c o p e t s c o p e ) ;

/∗ ∗
∗ @ b r i e f S e a r c h e s a r e performed from t h e c u r r e n t f o l d e r i n t h e
Browsed P l a y e r s v i r t u a l f i l e s y s t e m . The s e a r c h a p p l i e s t o t h e
c u r r e n t f o l d e r and a l l f o l d e r s b e l o w t h a t .
∗ @param a v r c p b r o w s i n g c i d
∗ @param s e a r c h s t r l e n
∗ @param s e a r c h s t r
397

∗ @return s t a t u s
∗ ∗/
uint8 t a v r c p b r o w s i n g c o n t r o l l e r s e a r c h ( uint16 t a v r c p b r o w s i n g c i d
, uint16 t s e a r c h s t r l e n , char ∗ s e a r c h s t r ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVRCP Browsing C o n t r o l l e r
∗/
void a v r c p b r o w s i n g c o n t r o l l e r d e i n i t ( void ) ;

1.59. AVRCP Browsing Target API. avrcp browsing target.h

/∗ ∗
∗ @ b r i e f S e t up AVRCP Browsing C o n t r o l l e r d e v i c e .
∗/
void a v r c p b r o w s i n g t a r g e t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVRCP Browsing C o n t r o l l e r c l i e n t
.
∗ @param c a l l b a c k
∗/
void a v r c p b r o w s i n g t a r g e t r e g i s t e r p a c k e t h a n d l e r (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f Accept s e t browsed p l a y e r
∗ @param b r o w s i n g c i d
∗ @param u i d c o u n t e r
∗ @param b r o w s e d p l a y e r i d
∗ @param r e s p o n s e
∗ @param r e s p o n s e s i z e
∗/
uint8 t a v r c p b r o w s i n g t a r g e t s e n d a c c e p t s e t b r o w s e d p l a y e r (
uint16 t b r o w s i n g c i d , uint16 t u i d c o u n t e r , uint16 t
b r o w s e d p l a y e r i d , uint8 t ∗ r e s p o n s e , uint16 t r e s p o n s e l e n ) ;

/∗ ∗
∗ @ b r i e f R e j e c t s e t browsed p l a y e r
∗ @param b r o w s i n g c i d
∗ @param s t a t u s
∗/
uint8 t a v r c p b r o w s i n g t a r g e t s e n d r e j e c t s e t b r o w s e d p l a y e r (
uint16 t b r o w s i n g c i d , a v r c p s t a t u s c o d e t s t a t u s ) ;

/∗ ∗
∗ @ b r i e f Send answer t o g e t f o l d e r i t e m s q u e r y on e v e n t
AVRCP SUBEVENT BROWSING GET FOLDER ITEMS. The f i r s t b y t e o f
t h i s e v e n t d e f i n e s t h e s c o p e o f t h e query , s e e
avrcp browsing scope t .
∗ @param b r o w s i n g c i d
∗ @param u i d c o u n t e r
398

∗ @param a t t r l i s t
∗ @param a t t r l i s t s i z e
∗/
uint8 t a v r c p b r o w s i n g t a r g e t s e n d g e t f o l d e r i t e m s r e s p o n s e (
uint16 t b r o w s i n g c i d , uint16 t u i d c o u n t e r , uint8 t ∗ a t t r l i s t
, uint16 t a t t r l i s t s i z e ) ;

/∗ ∗
∗ @ b r i e f Send answer t o g e t t o t a l number o f i t e m s q u e r y on e v e n t
AVRCP SUBEVENT BROWSING GET TOTAL NUM ITEMS. The f i r s t b y t e o f
t h i s e v e n t d e f i n e s t h e s c o p e o f t h e query , s e e
avrcp browsing scope t .
∗ @param b r o w s i n g c i d
∗ @param u i d c o u n t e r
∗ @param t o t a l n u m i t e m s
∗/
uint8 t a v r c p b r o w s i n g t a r g e t s e n d g e t t o t a l n u m i t e m s r e s p o n s e (
uint16 t b r o w s i n g c i d , uint16 t u i d c o u n t e r , uint32 t
total num items ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVRCP Browsing C o n t r o l l e r
∗/
void a v r c p b r o w s i n g t a r g e t d e i n i t ( void ) ;

1.60. AVRCP Controller API. avrcp controller.h

typedef enum {
AVRCP CONTROLLER SUPPORTED FEATURE CATEGORY PLAYER OR RECORDER =
0,
AVRCP CONTROLLER SUPPORTED FEATURE CATEGORY MONITOR OR AMPLIFIER
,
AVRCP CONTROLLER SUPPORTED FEATURE CATEGORY TUNER,
AVRCP CONTROLLER SUPPORTED FEATURE CATEGORY MENU,
AVRCP CONTROLLER SUPPORTED FEATURE RESERVED 4,
AVRCP CONTROLLER SUPPORTED FEATURE RESERVED 5,
AVRCP CONTROLLER SUPPORTED FEATURE BROWSING,
AVRCP CONTROLLER SUPPORTED FEATURE COVER ART GET IMAGE PROPERTIES
,
AVRCP CONTROLLER SUPPORTED FEATURE COVER ART GET IMAGE,
AVRCP CONTROLLER SUPPORTED FEATURE COVER ART GET LINKED THUMBNAIL

} avrcp controller supported feature t ;

/∗ ∗
∗ @ b r i e f AVRCP C o n t r o l l e r s e r v i c e r e c o r d .
∗ @param s e r v i c e
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param s u p p o r t e d f e a t u r e s 16− b i t bitmap , s e e AVRCP FEATURE MASK ∗
in avrcp . h
∗ @param s e r v i c e n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty
s t r i n g ) to skip a t t r i b u t e
399

∗ @param s e r v i c e p r o v i d e r n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e
”” ( empty s t r i n g ) t o s k i p a t t r i b u t e
∗/
void a v r c p c o n t r o l l e r c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t s u p p o r t e d f e a t u r e s , const char ∗
s e r v i c e n a m e , const char ∗ s e r v i c e p r o v i d e r n a m e ) ;

/∗ ∗
∗ @ b r i e f S e t up AVRCP C o n t r o l l e r s e r v i c e .
∗/
void a v r c p c o n t r o l l e r i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVRCP C o n t r o l l e r c l i e n t .
∗ @param c a l l b a c k
∗/
void a v r c p c o n t r o l l e r r e g i s t e r p a c k e t h a n d l e r (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f S e t max num f r a g m e n t s i n whuch message can be t r a n s m i t e d .
∗ @param a v r c p c i d
∗ @param max num fragments
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s e t m a x n u m f r a g m e n t s ( uint16 t a v r c p c i d ,
uint8 t max num fragments ) ;

/∗ ∗
∗ @ b r i e f Unit i n f o .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r u n i t i n f o ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @brief Subunit info .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s u b u n i t i n f o ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Get c a p a b i l i t i e s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r g e t s u p p o r t e d c o m p a n y i d s ( uint16 t
avrcp cid ) ;

/∗ ∗
∗ @ b r i e f Get s u p p o r t e d E v en t s .
∗ @param a v r c p c i d
400

∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r g e t s u p p o r t e d e v e n t s ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f S t a r t c o n t i n u o u s cmd ( p l a y , pause , volume up , . . . ) . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s t a r t p r e s s a n d h o l d c m d ( uint16 t a v r c p c i d
, avrcp operation id t operation id ) ;

/∗ ∗
∗ @ b r i e f S t o p s c o n t i n u o u s cmd ( p l a y , pause , volume up , . . . ) . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r r e l e a s e p r e s s a n d h o l d c m d ( uint16 t
avrcp cid ) ;

/∗ ∗
∗ @ b r i e f Play . Event AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s
o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r p l a y ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d p l a y ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Stop . Event AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s
o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s t o p ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d s t o p ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Pause . Event AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s
o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r p a u s e ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d p a u s e ( uint16 t a v r c p c i d ) ;

/∗ ∗
401

∗ @ b r i e f S i n g l e s t e p − f a s t f o r w a r d . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r f a s t f o r w a r d ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d f a s t f o r w a r d ( uint16 t
avrcp cid ) ;

/∗ ∗
∗ @ b r i e f S i n g l e s t e p rewind . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r r e w i n d ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d r e w i n d ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Forward . Event AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s
o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r f o r w a r d ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d f o r w a r d ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Backward . Event AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s
o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r b a c k w a r d ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d b a c k w a r d ( uint16 t a v r c p c i d )
;

/∗ ∗
∗ @ b r i e f Turns t h e volume t o h i g h . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r v o l u m e u p ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d v o l u m e u p ( uint16 t a v r c p c i d
);
/∗ ∗
∗ @ b r i e f Turns t h e volume t o low . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
402

∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r v o l u m e d o w n ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d v o l u m e d o w n ( uint16 t
avrcp cid ) ;

/∗ ∗
∗ @ b r i e f Puts t h e sound o u t . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r m u t e ( uint16 t a v r c p c i d ) ;
uint8 t a v r c p c o n t r o l l e r p r e s s a n d h o l d m u t e ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Get p l a y s t a t u s . Returns e v e n t o f t y p e
AVRCP SUBEVENT PLAY STATUS ( l e n g t h , p o s i t i o n , p l a y s t a t u s ) .
∗ I f TG d o e s not s u p p o r t SongLength And S o n g P o s i t i o n on TG, t h e n TG
s h a l l r e t u r n 0xFFFFFFFF .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r g e t p l a y s t a t u s ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Enable n o t i f i c a t i o n . Response v i a
AVRCP SUBEVENT NOTIFICATION STATE.
∗ @param a v r c p c i d
∗ @param e v e n t i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r e n a b l e n o t i f i c a t i o n ( uint16 t a v r c p c i d ,
avrcp notification event id t event id ) ;

/∗ ∗
∗ @ b r i e f D i s a b l e n o t i f i c a t i o n . Response v i a
AVRCP SUBEVENT NOTIFICATION STATE.
∗ @param a v r c p c i d
∗ @param e v e n t i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r d i s a b l e n o t i f i c a t i o n ( uint16 t a v r c p c i d ,
avrcp notification event id t event id ) ;

/∗ ∗
∗ @ b r i e f Get i n f o on now p l a y i n g media u s i n g s u b s e t o f a t t r i b u t e
IDs
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
403

uint8 t a v r c p c o n t r o l l e r g e t e l e m e n t a t t r i b u t e s ( uint16 t a v r c p c i d ,
uint8 t n u m a t t r i b u t e s , a v r c p m e d i a a t t r i b u t e i d t ∗ a t t r i b u t e s )
;

/∗ ∗
∗ @ b r i e f Get i n f o on now p l a y i n g media u s i n g a l l IDs .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r g e t n o w p l a y i n g i n f o ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Get i n f o on now p l a y i n g media u s i n g s p e c i f i c media
a t t r i b u t e ID .
∗ @param m e d i a a t t r i b u t e i d
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r g e t n o w p l a y i n g i n f o f o r m e d i a a t t r i b u t e i d
( uint16 t a v r c p c i d , a v r c p m e d i a a t t r i b u t e i d t
media attribute id ) ;

/∗ ∗
∗ @ b r i e f S e t a b s o l u t e volume 0−127 ( c o r r e s p o n d s t o 0−100%) .
Response v i a AVRCP SUBEVENT SET ABSOLUTE VOLUME RESPONSE
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s e t a b s o l u t e v o l u m e ( uint16 t a v r c p c i d ,
uint8 t volume ) ;

/∗ ∗
∗ @ b r i e f S k i p t o n e x t p l a y i n g media . Event
AVRCP SUBEVENT OPERATION COMPLETE r e t u r n s o p e r a t i o n i d and
status .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s k i p ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Query r e p e a t and s h u f f l e mode . Response v i a
AVRCP SUBEVENT SHUFFLE AND REPEAT MODE.
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r q u e r y s h u f f l e a n d r e p e a t m o d e s ( uint16 t
avrcp cid ) ;

/∗ ∗
∗ @ b r i e f S e t s h u f f l e mode . Event AVRCP SUBEVENT OPERATION COMPLETE
r e t u r n s o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
404

∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s e t s h u f f l e m o d e ( uint16 t a v r c p c i d ,
a v r c p s h u f f l e m o d e t mode ) ;

/∗ ∗
∗ @ b r i e f S e t r e p e a t mode . Event AVRCP SUBEVENT OPERATION COMPLETE
r e t u r n s o p e r a t i o n i d and s t a t u s .
∗ @param a v r c p c i d
∗ @return s t a t u s
∗/
uint8 t a v r c p c o n t r o l l e r s e t r e p e a t m o d e ( uint16 t a v r c p c i d ,
a v r c p r e p e a t m o d e t mode ) ;

/∗ ∗
∗ @ b r i e f The PlayItem command s t a r t s p l a y i n g an item i n d i c a t e d by
t h e UID . I t i s r o u t e d t o t h e Addressed P l a y e r .
∗ @param a v r c p c i d
∗ @param u i d
∗ @param u i d c o u n t e r
∗ @param s c o p e
∗ ∗/
uint8 t a v r c p c o n t r o l l e r p l a y i t e m f o r s c o p e ( uint16 t a v r c p c i d ,
uint8 t ∗ uid , uint16 t u i d c o u n t e r , a v r c p b r o w s i n g s c o p e t
scope ) ;

/∗ ∗
∗ @ b r i e f Adds an item i n d i c a t e d by t h e UID t o t h e Now P l a y i n g queue
.
∗ @param a v r c p c i d
∗ @param u i d
∗ @param u i d c o u n t e r
∗ @param s c o p e
∗ ∗/
uint8 t a v r c p c o n t r o l l e r a d d i t e m f r o m s c o p e t o n o w p l a y i n g l i s t (
uint16 t a v r c p c i d , uint8 t ∗ uid , uint16 t u i d c o u n t e r ,
avrcp browsing scope t scope ) ;

/∗ ∗
∗ @brief Set addressed player .
∗ @param a v r c p c i d
∗ @param a d d r e s s e d p l a y e r i d
∗/
uint8 t a v r c p c o n t r o l l e r s e t a d d r e s s e d p l a y e r ( uint16 t a v r c p c i d ,
uint16 t a d d r e s s e d p l a y e r i d ) ;

/∗ ∗
∗ @brief Send custom command
∗ @param avrcp cid
∗ @param command type
∗ @param subunit type
∗ @param subunit id
∗ @param pdu id
∗ @param company id
405

∗ @param d a t a
∗ @param d a t a l e n
∗/
uint8 t a v r c p c o n t r o l l e r s e n d c u s t o m c o m m a n d ( uint16 t a v r c p c i d ,
avrcp command type t command type ,
avrcp subunit type t subunit type , avrcp subunit id t subunit id
,
a v r c p p d u i d t pdu id , uint32 t company id ,
const uint8 t ∗ data , uint16 t d a t a l e n ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVRCP C o n t r o l l e r
∗/
void a v r c p c o n t r o l l e r d e i n i t ( void ) ;

1.61. AVRCP Cover Art Client API. avrcp cover art client.h

/∗ ∗
∗ @ b r i e f S e t up AVRCP Cover Art c l i e n t
∗/
void a v r c p c o v e r a r t c l i e n t i n i t ( void ) ;

/∗ ∗
∗ @brief Connect t o AVRCP Cover Art s e r v i c e on a remote d e v i c e ,
e m i t s AVRCP SUBEVENT COVER ART CONNECTION ESTABLISHED w i t h
status
∗ @param packet handler
∗ @param remote addr
∗ @param ertm buffer
∗ @param ertm buffer size
∗ @param ertm config
∗ @param a v r c p c o v e r a r t c i d o u t g o i n g parameter , v a l i d i f s t a t u s
== ERROR CODE SUCCESS
∗ @return s t a t u s
∗/
uint8 t
avrcp cover art client connect ( avrcp cover art client t ∗
c o v e r a r t c l i e n t , btstack packet handler t p a c k e t h a n d l e r ,
bd addr t remote addr , uint8 t ∗
e r t m b u f f e r , uint32 t
ertm buffer size ,
const l 2 c a p e r t m c o n f i g t ∗
e r t m c o n f i g , uint16 t ∗
avrcp cover art cid ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c o v e r a r t t h u m b n a i l f o r c o v e r w i t h a g i v e n image
handle r e t r i e v e d via
∗ − a v r c p c o n t r o l l e r g e t n o w p l a y i n g i n f o or
∗ − avrcp controller get element attributes (...
AVRCP MEDIA ATTR DEFAULT COVER ART . . . )
∗ @param a v r c p c o v e r a r t c i d
406

∗ @param i m a g e h a n d l e
∗ @return s t a t u s
∗/
uint8 t a v r c p c o v e r a r t c l i e n t g e t l i n k e d t h u m b n a i l ( uint16 t
a v r c p c o v e r a r t c i d , const char ∗ i m a g e h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t c o v e r a r t image f o r g i v e n image h a n d l e r e t r i e v e d
via
∗ − a v r c p c o n t r o l l e r g e t n o w p l a y i n g i n f o or
∗ − avrcp controller get element attributes (...
AVRCP MEDIA ATTR DEFAULT COVER ART . . . )
∗ and g i v e n image d e s c r i p t o r
∗ @param a v r c p c o v e r a r t c i d
∗ @param i m a g e h a n d l e
∗ @param i m a g e d e s c r i p t o r
∗ @return s t a t u s
∗/
uint8 t a v r c p c o v e r a r t c l i e n t g e t i m a g e ( uint16 t
a v r c p c o v e r a r t c i d , const char ∗ i ma g e h an d le , const char ∗
image descriptor ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t image p r o p e r t i e s f o r g i v e n image h a n d l e r e t r i e v e d
via
∗ − a v r c p c o n t r o l l e r g e t n o w p l a y i n g i n f o or
∗ − avrcp controller get element attributes (...
AVRCP MEDIA ATTR DEFAULT COVER ART . . . )
∗ @param a v r c p c o v e r a r t c i d
∗ @param i m a g e h a n d l e
∗ @return s t a t u s
∗/
uint8 t a v r c p c o v e r a r t c l i e n t g e t i m a g e p r o p e r t i e s ( uint16 t
a v r c p c o v e r a r t c i d , const char ∗ i m a g e h a n d l e ) ;

/∗ ∗
∗ @brief D i s c o n n e c t from AVRCP Cover Art s e r v i c e
∗ @param avrcp cover art cid
∗ @return s t a t u s
∗/
uint8 t a v r c p c o v e r a r t c l i e n t d i s c o n n e c t ( uint16 t
avrcp cover art cid ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVRCP Cover Art C l i e n t
∗/
void a v r c p c o v e r a r t c l i e n t d e i n i t ( void ) ;

1.62. AVRCP Media Item Iterator API. avrcp media item iterator.h

typedef struct a v r c p m e d i a i t e m c o n t e x t {
const uint8 t ∗ data ;
407

uint16 t offset ;
uint16 t length ;
} avrcp media item context t ;

// Media item d a t a i t e r a t o r
void a v r c p m e d i a i t e m i t e r a t o r i n i t ( a v r c p m e d i a i t e m c o n t e x t t ∗
c o n t e x t , uint16 t a v r c p m e d i a i t e m l e n , const uint8 t ∗
avrcp media item data ) ;
int a v r c p m e d i a i t e m i t e r a t o r h a s m o r e ( const
avrcp media item context t ∗ context ) ;
void a v r c p m e d i a i t e m i t e r a t o r n e x t ( a v r c p m e d i a i t e m c o n t e x t t ∗
context ) ;

// Access f u n c t i o n s
uint32 t a v r c p m e d i a i t e m i t e r a t o r g e t a t t r i d ( const
avrcp media item context t ∗ context ) ;
uint16 t a v r c p m e d i a i t e m i t e r a t o r g e t a t t r c h a r s e t ( const
avrcp media item context t ∗ context ) ;
uint16 t a v r c p m e d i a i t e m i t e r a t o r g e t a t t r v a l u e l e n ( const
avrcp media item context t ∗ context ) ;
const uint8 t ∗ a v r c p m e d i a i t e m i t e r a t o r g e t a t t r v a l u e ( const
avrcp media item context t ∗ context ) ;

1.63. AVRCP Target API. avrcp target.h

typedef enum {
AVRCP TARGET SUPPORTED FEATURE CATEGORY PLAYER OR RECORDER = 0 ,
AVRCP TARGET SUPPORTED FEATURE CATEGORY MONITOR OR AMPLIFIER,
AVRCP TARGET SUPPORTED FEATURE CATEGORY TUNER,
AVRCP TARGET SUPPORTED FEATURE CATEGORY MENU,
AVRCP TARGET SUPPORTED FEATURE PLAYER APPLICATION SETTINGS, //
AVRCP TARGET SUPPORTED FEATURE CATEGORY PLAYER OR RECORDER
must be 1 f o r t h i s f e a t u r e t o be s e t
AVRCP TARGET SUPPORTED FEATURE GROUP NAVIGATION, //
AVRCP TARGET SUPPORTED FEATURE CATEGORY PLAYER OR RECORDER
must be 1 f o r t h i s f e a t u r e t o be s e t
AVRCP TARGET SUPPORTED FEATURE BROWSING,
AVRCP TARGET SUPPORTED FEATURE MULTIPLE MEDIA PLAYER APPLICATIONS
,
AVRCP TARGET SUPPORTED FEATURE COVER ART,
} avrcp target supported feature t ;

/∗ ∗
∗ @ b r i e f AVRCP T a r g et s e r v i c e r e c o r d .
∗ @param s e r v i c e
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param s u p p o r t e d f e a t u r e s 16− b i t bitmap , s e e AVRCP FEATURE MASK ∗
in avrcp . h
∗ @param s e r v i c e n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty
s t r i n g ) to skip a t t r i b u t e
∗ @param s e r v i c e p r o v i d e r n a m e or NULL f o r d e f a u l t v a l u e . P r o v i d e
”” ( empty s t r i n g ) t o s k i p a t t r i b u t e
408

∗/
void a v r c p t a r g e t c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t s u p p o r t e d f e a t u r e s , const char ∗
s e r v i c e n a m e , const char ∗ s e r v i c e p r o v i d e r n a m e ) ;

/∗ ∗
∗ @ b r i e f S e t up AVRCP T a rg e t s e r v i c e .
∗/
void a v r c p t a r g e t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e AVRCP T a r g e t c l i e n t .
∗ @param c a l l b a c k
∗/
void avrcp target register packet handler (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f S e l e c t P l a y e r t h a t i s c o n t r o l l e d by C o n t r o l l e r
∗ @param c a l l b a c k
∗ @note C a l l b a c k s h o u l d r e t u r n i f s e l e c t e d p l a y e r i s v a l i d
∗/
void a v r c p t a r g e t r e g i s t e r s e t a d d r e s s e d p l a y e r h a n d l e r ( b o o l ( ∗
c a l l b a c k ) ( uint16 t p l a y e r i d ) ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r a l i s t o f Company IDs s u p p o r t e d by t a r g e t .
∗ @param a v r c p c i d
∗ @param num companies
∗ @param companies
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t s u p p o r t c o m p a n i e s ( uint16 t a v r c p c i d , uint8 t
num companies , const uint32 t ∗ companies ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r e v e n t ID s u p p o r t e d by t a r g e t .
∗ @param a v r c p c i d
∗ @param e v e n t i d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found ,
ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE f o r
u n s u p p o r t e d e v e n t id , o t h e r w i s e ERROR CODE SUCCESS,
∗/
uint8 t a v r c p t a r g e t s u p p o r t e v e n t ( uint16 t a v r c p c i d ,
avrcp notification event id t event id ) ;

/∗ ∗
∗ @ b r i e f Send a p l a y s t a t u s .
∗ @note The a v r c p t a r g e t p a c k e t h a n d l e r w i l l r e c e i v e
AVRCP SUBEVENT PLAY STATUS QUERY e v e n t . Use t h i s f u n c t i o n t o
respond .
∗ @param a v r c p c i d
409

∗ @param s o n g l e n g t h m s
∗ @param s o n g p o s i t i o n m s
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t p l a y s t a t u s ( uint16 t a v r c p c i d , uint32 t
s o n g l e n g t h m s , uint32 t s o n g p o s i t i o n m s ,
avrcp playback status t status ) ;

/∗ ∗
∗ @ b r i e f S e t Now P l a y i n g I n f o t h a t i s send t o C o n t r o l l e r i f
n o t i f i c a t i o n s are enabled
∗ @param a v r c p c i d
∗ @param c u r r e n t t r a c k
∗ @param t o t a l t r a c k s
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , ERROR CODE COMMAND DISALLOWED i f no
t r a c k i s p r o v i d e d , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t s e t n o w p l a y i n g i n f o ( uint16 t a v r c p c i d , const
a v r c p t r a c k t ∗ c u r r e n t t r a c k , uint16 t t o t a l t r a c k s ) ;

/∗ ∗
∗ @ b r i e f S e t P l a y i n g s t a t u s and send t o C o n t r o l l e r
∗ @param a v r c p c i d
∗ @param p l a y b a c k s t a t u s
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t s e t p l a y b a c k s t a t u s ( uint16 t a v r c p c i d ,
avrcp playback status t playback status ) ;

/∗ ∗
∗ @ b r i e f S e t Unit I n f o
∗ @param a v r c p c i d
∗ @param u n i t t y p e
∗ @param company id
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t s e t u n i t i n f o ( uint16 t a v r c p c i d ,
a v r c p s u b u n i t t y p e t u n i t t y p e , uint32 t company id ) ;

/∗ ∗
∗ @brief Set Subunit Info
∗ @param a v r c p c i d
∗ @param s u b u n i t t y p e
∗ @param s u b u n i t i n f o d a t a
∗ @param s u b u n i t i n f o d a t a s i z e
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
410

uint8 t a v r c p t a r g e t s e t s u b u n i t i n f o ( uint16 t a v r c p c i d ,
a v r c p s u b u n i t t y p e t s u b u n i t t y p e , const uint8 t ∗
s u b u n i t i n f o d a t a , uint16 t s u b u n i t i n f o d a t a s i z e ) ;

/∗ ∗
∗ @ b r i e f Send P l a y i n g Content Changed N o t i f i c a t i o n i f e n a b l e d
∗ @param a v r c p c i d
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t p l a y i n g c o n t e n t c h a n g e d ( uint16 t a v r c p c i d ) ;

/∗ ∗
∗ @ b r i e f Send Addressed P l a y e r Changed N o t i f i c a t i o n i f e n a b l e d
∗ @param a v r c p c i d
∗ @param p l a y e r i d
∗ @param u i d c o u n t e r
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t a d d r e s s e d p l a y e r c h a n g e d ( uint16 t a v r c p c i d ,
uint16 t p l a y e r i d , uint16 t u i d c o u n t e r ) ;

/∗ ∗
∗ @ b r i e f S e t B a t t e r y S t a t u s Changed and send n o t i f i c a t i o n i f
enabled
∗ @param a v r c p c i d
∗ @param b a t t e r y s t a t u s
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t b a t t e r y s t a t u s c h a n g e d ( uint16 t a v r c p c i d ,
avrcp battery status t battery status ) ;

/∗ ∗
∗ @ b r i e f O v e r w r i t e t h e a b s o l u t e volume r e q u e s t e d by c o n t r o l l e r w i t h
t h e a c t u a l a b s o l u t e volume .
∗ This f u n c t i o n can o n l y be c a l l e d on
AVRCP SUBEVENT NOTIFICATION VOLUME CHANGED e v e n t , which
i n d i c a t e s a s e t a b s o l u t e volume r e q u e s t by c o n t r o l l e r .
∗ I f t h e a b s o l u t e volume r e q u e s t e d by c o n t r o l l e r d o e s not match t h e
g r a n u l a r i t y o f volume c o n t r o l t h e TG p r o v i d e s , you can use
t h i s function to adjust the actual value .

∗ @param a v r c p c i d
∗ @param a b s o l u t e v o l u m e
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t a d j u s t a b s o l u t e v o l u m e ( uint16 t a v r c p c i d ,
uint8 t a b s o l u t e v o l u m e ) ;

/∗ ∗
411

∗ @ b r i e f S e t A b s o l u t e Volume and send n o t i f i c a t i o n i f e n a b l e d


∗ @param a v r c p c i d
∗ @param a b s o l u t e v o l u m e
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t v o l u m e c h a n g e d ( uint16 t a v r c p c i d , uint8 t
absolute volume ) ;

/∗ ∗
∗ @ b r i e f S e t Track and send n o t i f i c a t i o n i f e n a b l e d
∗ @param a v r c p c i d
∗ @param t r a c k I D
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t t r a c k c h a n g e d ( uint16 t a v r c p c i d , uint8 t ∗
trackID ) ;

/∗ ∗
∗ @ b r i e f Send O p e r a t i o n R e j e c t e d message
∗ @param a v r c p c i d
∗ @param o p i d
∗ @param o p e r a n d s l e n g t h
∗ @param operand
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t o p e r a t i o n r e j e c t e d ( uint16 t a v r c p c i d ,
a v r c p o p e r a t i o n i d t opid , uint8 t o p e r a n d s l e n g t h , uint8 t
operand ) ;

/∗ ∗
∗ @ b r i e f Send O p e r a t i o n Accepted message
∗ @param a v r c p c i d
∗ @param o p i d
∗ @param o p e r a n d s l e n g t h
∗ @param operand
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
uint8 t a v r c p t a r g e t o p e r a t i o n a c c e p t e d ( uint16 t a v r c p c i d ,
a v r c p o p e r a t i o n i d t opid , uint8 t o p e r a n d s l e n g t h , uint8 t
operand ) ;

/∗ ∗
∗ @ b r i e f Send O p e r a t i o n Not Implemented message
∗ @param a v r c p c i d
∗ @param o p i d
∗ @param o p e r a n d s l e n g t h
∗ @param operand
∗ @return s t a t u s ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n i s not found , o t h e r w i s e ERROR CODE SUCCESS
∗/
412

uint8 t a v r c p t a r g e t o p e r a t i o n n o t i m p l e m e n t e d ( uint16 t a v r c p c i d ,
a v r c p o p e r a t i o n i d t opid , uint8 t o p e r a n d s l e n g t h , uint8 t
operand ) ;

/∗ ∗
∗ @ b r i e f De−I n i t AVRCP Browsing T a r g e t
∗/
void a v r c p t a r g e t d e i n i t ( void ) ;

1.64. BNEP API. bnep.h

/∗ ∗
∗ @ b r i e f S e t up BNEP.
∗/
void b n e p i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Check i f a d a t a p a c k e t can be send o u t .
∗/
int b n e p c a n s e n d p a c k e t n o w ( uint16 t b n e p c i d ) ;

/∗ ∗
∗ @brief Request emission o f BNEP CAN SEND NOW as soon as p o s s i b l e
∗ @note BNEP CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o t h i s
function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗ @param b n e p c i d
∗/
void b n e p r e q u e s t c a n s e n d n o w e v e n t ( uint16 t b n e p c i d ) ;

/∗ ∗
∗ @ b r i e f Send a d a t a p a c k e t .
∗/
int bnep send ( uint16 t b n e p c i d , uint8 t ∗ packet , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f S e t t h e network p r o t o c o l f i l t e r .
∗/
int b n e p s e t n e t t y p e f i l t e r ( uint16 t b n e p c i d , b n e p n e t f i l t e r t ∗
f i l t e r , uint16 t l e n ) ;

/∗ ∗
∗ @brief Set the multicast address f i l t e r .
∗/
int b n e p s e t m u l t i c a s t f i l t e r ( uint16 t b n e p c i d , b n e p m u l t i f i l t e r t
∗ f i l t e r , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f S e t s e c u r i t y l e v e l r e q u i r e d f o r incoming c o n n e c t i o n s , need
t o be c a l l e d b e f o r e r e g i s t e r i n g s e r v i c e s .
∗ @ de pr e ca te d use g a p s e t s e c u r i t y l e v e l i n s t e a d
∗/
413

void b n e p s e t r e q u i r e d s e c u r i t y l e v e l ( g a p s e c u r i t y l e v e l t
security level ) ;

/∗ ∗
∗ @ b r i e f C r e a t e s BNEP c o n n e c t i o n ( c h a n n e l ) t o a g i v e n s e r v e r on a
remote d e v i c e w i t h b a s e b a n d a d d r e s s . A new b a s e b a n d c o n n e c t i o n
w i l l be i n i t i a t e d i f n e c e s s a r y .
∗/
int b n e p c o n n e c t ( btstack packet handler t p a c k e t h a n d l e r , bd addr t
addr , uint16 t l2cap psm , uint16 t u u i d s r c , uint16 t u u i d d e s t )
;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t s BNEP c h a n n e l w i t h g i v e n i d e n t i f i e r .
∗/
void b n e p d i s c o n n e c t ( bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s BNEP s e r v i c e , s e t a maximum frame s i z e and
a s s i g n s a p a c k e t h a n d l e r . On embedded systems , use NULL f o r
c o n n e c t i o n parameter .
∗/
uint8 t b n e p r e g i s t e r s e r v i c e ( btstack packet handler t
p a c k e t h a n d l e r , uint16 t s e r v i c e u u i d , uint16 t m a x f r a m e s i z e ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r BNEP s e r v i c e .
∗/
void b n e p u n r e g i s t e r s e r v i c e ( uint16 t s e r v i c e u u i d ) ;

/∗ ∗
∗ @ b r i e f De−I n i t BNEP
∗/
void b n e p d e i n i t ( void ) ;

1.65. Link Key DB API. btstack link key db.h : Interface to provide link
key storage.

typedef struct {

// management

/∗ ∗
∗ @ b r i e f Open t h e Link Key DB
∗/
void ( ∗ open ) ( void ) ;

/∗ ∗
∗ @ b r i e f S e t s BD Addr o f l o c a l B l u e t o o t h C o n t r o l l e r .
∗ @note Only needed i f B l u e t o o t h C o n t r o l l e r can be swapped , e . g
. USB Dongles on d e s k t o p s y s t e m s
∗/
414

void ( ∗ s e t l o c a l b d a d d r ) ( bd addr t bd addr ) ;

/∗ ∗
∗ @ b r i e f C l o s e t h e Link Key DB
∗/
void ( ∗ c l o s e ) ( void ) ;

// g e t / s e t / d e l e t e l i n k key

/∗ ∗
∗ @ b r i e f Get Link Key f o r g i v e n a d d r e s s
∗ @param addr t o l o o k u p
∗ @param l i n k k e y ( o u t )
∗ @param t y p e ( o u t )
∗ @return 1 on s u c c e s s
∗/
int ( ∗ g e t l i n k k e y ) ( bd addr t bd addr , l i n k k e y t l i n k k e y ,
l i n k k e y t y p e t ∗ type ) ;

/∗ ∗
∗ @ b r i e f Update / S t o r e Link key
∗ @ b r i e f addr
∗ @brief link key
∗ @ b r i e f t y p e o f l i n k key
∗/
void ( ∗ p u t l i n k k e y ) ( bd addr t bd addr , l i n k k e y t l i n k k e y ,
l i n k k e y t y p e t type ) ;

/∗ ∗
∗ @ b r i e f D e l e t e Link Keys
∗ @ b r i e f addr
∗/
void ( ∗ d e l e t e l i n k k e y ) ( bd addr t bd addr ) ;

// i t e r a t o r : i t ’ s a l l o w e d t o d e l e t e

/∗ ∗
∗ @ b r i e f S e tu p i t e r a t o r
∗ @param i t
∗ @return 1 on s u c c e s s
∗/
int ( ∗ i t e r a t o r i n i t ) ( b t s t a c k l i n k k e y i t e r a t o r t ∗ i t ) ;

/∗ ∗
∗ @ b r i e f Get n e x t Link Key
∗ @param i t
∗ @ b r i e f addr
∗ @brief link key
∗ @ b r i e f t y p e o f l i n k key
∗ @return 1 , i f v a l i d l i n k key found
∗/
int ( ∗ i t e r a t o r g e t n e x t ) ( b t s t a c k l i n k k e y i t e r a t o r t ∗ i t ,
bd addr t bd addr , l i n k k e y t l i n k k e y , l i n k k e y t y p e t ∗
type ) ;
415

/∗ ∗
∗ @ b r i e f F re es r e s o u r c e s a l l o c a t e d by i t e r a t o r i n i t
∗ @note Must be c a l l e d a f t e r i t e r a t i o n t o f r e e r e s o u r c e s
∗ @param i t
∗/
void ( ∗ i t e r a t o r d o n e ) ( b t s t a c k l i n k k e y i t e r a t o r t ∗ i t ) ;

} btstack link key db t ;

1.66. In-Memory Link Key Storage API. btstack link key db memory.h

/∗
∗ @brief
∗/
const btstack link key db t ∗ b t s t a c k l i n k k e y d b m e m o r y i n s t a n c e (
void ) ;

typedef struct {
b t s t a c k l i n k e d i t e m t item ;
bd addr t bd addr ;
link key t l i n k k e y ;
link key type t link key type ;
} btstack link key db memory entry t ;

1.67. Static Link Key Storage API. btstack link key db static.h : Static
Link Key Storage implementation to use during development/porting: - Link
keys have to be manually added to this file to make them usable + Link keys are
preserved on reflash in constrast to the program flash based link key store

/∗
∗ @brief
∗/
const btstack link key db t ∗ b t s t a c k l i n k k e y d b s t a t i c i n s t a n c e (
void ) ;

1.68. Link Key TLV Storage API. btstack link key db tlv.h : Interface
to provide link key storage via BTstack’s TLV storage.

/∗ ∗
∗ I n i t Link Key DB u s i n g TLV
∗ @param b t s t a c k t l v i m p l o f b t s t a c k t l v i n t e r f a c e
∗ @Param b t s t a c k t l v c o n t e x t o f b t s t a c k t l v i n t e r f a c e
∗/
416

const btstack link key db t ∗ b t s t a c k l i n k k e y d b t l v g e t i n s t a n c e (


const b t s t a c k t l v t ∗ b t s t a c k t l v i m p l , void ∗
btstack tlv context ) ;

1.69. Device ID Server API. device id server.h : Create Device ID SDP


Records.

/∗ ∗
∗ @ b r i e f C r ea t e SDP r e c o r d f o r De v i ce ID s e r v i c e
∗ @param s e r v i c e b u f f e r − n ee d s t o l a r g e enough
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param v e n d o r i d s o u r c e u s u a l l y
DEVICE ID VENDOR ID SOURCE BLUETOOTH or
DEVICE ID VENDOR ID SOURCE USB
∗ @param v e n d o r i d
∗ @param p r o d u c t i t
∗ @param v e r s i o n
∗/
void d e v i c e i d c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t v e n d o r i d s o u r c e , uint16 t
v e n d o r i d , uint16 t p r o d u c t i d , uint16 t v e r s i o n ) ;

1.70. GATT SDP API. gatt sdp.h

/∗ ∗
∗ @ b r i e f C r e a t e s SDP r e c o r d forG ATT s e r v i c e i n p r o v i d e d empty
buffer .
∗ @note Make s u r e t h e b u f f e r i s b i g enough .

∗ @param s e r v i c e i s an empty b u f f e r t o s t o r e s e r v i c e r e c o r d
∗ @param s e r v i c e r e c o r d h a n d l e f o r new s e r v i c e
∗ @param g a t t s t a r t h a n d l e
∗ @param g a t t e n d h a n d l e
∗/
void g a t t c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t g a t t s t a r t h a n d l e , uint16 t
gatt end handle ) ;

1.71. GOEP Client API. goep client.h : Communicate with remote OBEX
server - General Object Exchange

typedef struct {
b t s t a c k l i n k e d i t e m t item ;

uint16 t cid ;

goep client state t state ;


417

bd addr t bd addr ;
uint16 t uuid ;
hci con handle t con handle ;
uint8 t incoming ;

btstack packet handler t c l i e n t h a n d l e r ;


btstack context callback registration t sdp query request ;

uint8 t rfcomm port ;


uint16 t l2cap psm ;
uint16 t bearer cid ;
uint16 t bearer mtu ;

uint16 t record index ;

// cached h i g h e r l a y e r i n f o r m a t i o n PBAP + MAP


uint32 t profile supported features ;
uint8 t map mas instance id ;
uint8 t map supported message types ;

// needed t o s e l e c t one o f m u l t i p l e MAS I n s t a n c e s


struct {
uint32 t s u p p o r t e d f e a t u r e s ;
uint8 t i n s t a n c e i d ;
uint8 t s u p p o r t e d m e s s a g e t y p e s ;
uint8 t rfcomm port ;
#i f d e f ENABLE GOEP L2CAP
uint16 t l2cap psm ;
#endif
} mas info ;

uint8 t obex opcode ;


uint32 t obex connection id ;
int obex connection id set ;

#i f d e f ENABLE GOEP L2CAP


l2cap ertm config t ertm config ;
uint16 t ertm buffer size ;
uint8 t ∗ ertm buffer ;
#endif
} goep client t ;

// remote d o e s not e x p o s e PBAP f e a t u r e s i n SDP r e c o r d


#define PBAP FEATURES NOT PRESENT ( ( uint32 t ) −1)
#define MAP FEATURES NOT PRESENT ( ( uint32 t ) −1)
#define PROFILE FEATURES NOT PRESENT ( ( uint32 t ) −1)

/∗ ∗
∗ S et u p GOEP C l i e n t
∗/
void g o e p c l i e n t i n i t ( void ) ;

/∗ ∗
418

∗ @ b r i e f Connect t o a GEOP s e r v e r w i t h s p e c i f i e d UUID on a remote


device .
∗ @param g o e p c l i e n t
∗ @param l 2 c a p e r t m c o n f i g
∗ @param l 2 c a p e r t m b u f f e r s i z e
∗ @param l 2 c a p e r t m b u f f e r
∗ @param h a n d l e r
∗ @param addr
∗ @param u u i d
∗ @param i n s t a n c e i d e . g . used t o c o n n e c t t o d i f f e r e n t MAP Access
Servers , d e f a u l t : 0
∗ @param o u t c i d
∗ @return
∗/
uint8 t
goep client connect ( goep client t ∗ goep client , l2cap ertm config t
∗ l 2 c a p e r t m c o n f i g , uint8 t ∗ l 2 c a p e r t m b u f f e r ,
uint16 t l 2 c a p e r t m b u f f e r s i z e ,
btstack packet handler t h a n d l e r , bd addr t
addr , uint16 t uuid ,
uint8 t i n s t a n c e i d , uint16 t ∗ o u t c i d ) ;

/∗ ∗
∗ @ b r i e f Connect t o a GEOP s e r v e r o v e r L2CAP w i t h s p e c i f i e d PSM on
a remote d e v i c e .
∗ @note In c o n t r a s t t o g o e p c l i e n t c o n n e c t which s e a r c h e s f o r a
OBEX s e r v i c e w i t h a g i v e n UUID, t h i s
∗ f u n c t i o n o n l y s u p p o r t s GOEP v2 . 0 (L2CAP) t o a s p e c i f i e d
L2CAP PSM
∗ @param g o e p c l i e n t
∗ @param l 2 c a p e r t m c o n f i g
∗ @param l 2 c a p e r t m b u f f e r s i z e
∗ @param l 2 c a p e r t m b u f f e r
∗ @param h a n d l e r
∗ @param addr
∗ @param l 2 c a p p s m
∗ @param o u t c i d
∗ @return
∗/
uint8 t
goep client connect l2cap ( goep client t ∗ goep client ,
l 2 c a p e r t m c o n f i g t ∗ l 2 c a p e r t m c o n f i g , uint8 t ∗
l2cap ertm buffer ,
uint16 t l 2 c a p e r t m b u f f e r s i z e ,
btstack packet handler t h a n d l e r , bd addr t
addr , uint16 t l2cap psm ,
uint16 t ∗ o u t c i d ) ;

/∗
∗ @ b r i e f Connect t o a GEOP s e r v e r w i t h s p e c i f i e d UUID on a remote
device .
∗ @note This f u n c t i o n s u s e s a s i n g l e g o e p c l i e n t t i n s t a n c e and
o n l y a l l o w s f o r a s i n g l e goep c o n n e c t i o n
∗ P l e a s e use g o e p c l i e n t c o n n e c t i n s t e a d
419

∗ @param h a n d l e r
∗ @param addr
∗ @param u u i d
∗ @param o u t c i d t o use f o r f u r t h e r commands
∗ @result status
∗/
uint8 t g o e p c l i e n t c r e a t e c o n n e c t i o n ( btstack packet handler t
h a n d l e r , bd addr t addr , uint16 t uuid , uint16 t ∗ o u t c i d ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t s GOEP c o n n e c t i o n w i t h g i v e n i d e n t i f i e r .
∗ @param g o e p c i d
∗ @return s t a t u s
∗/
uint8 t g o e p c l i e n t d i s c o n n e c t ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f GOEP SUBEVENT CAN SEND NOW as soon as
possible
∗ @note GOEP SUBEVENT CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o
this function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗ @param g o e p c i d
∗/
void g o e p c l i e n t r e q u e s t c a n s e n d n o w ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Get Opcode from l a s t c r e a t e d r e q u e s t , needed f o r p a r s i n g
o f OBEX r e s p o n s e p a c k e t
∗ @param g o e p c i d
∗ @return opcode
∗/
uint8 t g o e p c l i e n t g e t r e q u e s t o p c o d e ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Get PBAP S u p p o r t e d F e a t u r e s found i n SDP r e c o r d d u r i n g
connect
∗/
uint32 t g o e p c l i e n t g e t p b a p s u p p o r t e d f e a t u r e s ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Get MAP S u p p o r t e d F e a t u r e s found i n SDP r e c o r d d u r i n g
connect
∗/
uint32 t g o e p c l i e n t g e t m a p s u p p o r t e d f e a t u r e s ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Get MAP MAS I n s t a n c e ID found i n SDP r e c o r d d u r i n g c o n n e c t
∗/
uint8 t g o e p c l i e n t g e t m a p m a s i n s t a n c e i d ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Get MAP MAS S u p p o r t e d Message Types found i n SDP r e c o r d
during connect
420

∗/
uint8 t g o e p c l i e n t g e t m a p s u p p o r t e d m e s s a g e t y p e s ( uint16 t
goep cid ) ;

/∗ ∗
∗ @ b r i e f Check i f GOEP 2 . 0 or h i g h e r f e a t u r e s can be used
∗ @return t r u e i f GOEP Version 2 . 0 or h i g h e r
∗/
b o o l g o e p c l i e n t v e r s i o n 2 0 o r h i g h e r ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f S e t Connection ID used f o r newly c r e a t e d r e q u e s t s
∗ @param g o e p c i d
∗/
void g o e p c l i e n t s e t c o n n e c t i o n i d ( uint16 t g o e p c i d , uint32 t
connection id ) ;

/∗ ∗
∗ @ b r i e f S t a r t Connect r e q u e s t
∗ @param g o e p c i d
∗ @param o b e x v e r s i o n n u m b e r
∗ @param f l a g s
∗ @param m a x i m u m o b e x p a c k e t l e n g t h
∗/
void g o e p c l i e n t r e q u e s t c r e a t e c o n n e c t ( uint16 t g o e p c i d , uint8 t
o b e x v e r s i o n n u m b e r , uint8 t f l a g s , uint16 t
maximum obex packet length ) ;

/∗ ∗
∗ @brief S t a r t Disconnect r e q u e s t
∗ @param g o e p c i d
∗/
void g o e p c l i e n t r e q u e s t c r e a t e d i s c o n n e c t ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f C r ea t e Get r e q u e s t
∗ @param g o e p c i d
∗/
void g o e p c l i e n t r e q u e s t c r e a t e g e t ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f C r ea t e Abort r e q u e s t
∗ @param g o e p c i d
∗/
void g o e p c l i e n t r e q u e s t c r e a t e a b o r t ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f S t a r t S e t Path r e q u e s t
∗ @param g o e p c i d
∗/
void g o e p c l i e n t r e q u e s t c r e a t e s e t p a t h ( uint16 t g o e p c i d , uint8 t
flags ) ;

/∗ ∗
421

∗ @ b r i e f C r ea t e Put r e q u e s t
∗ @param g o e p c i d
∗/
void g o e p c l i e n t r e q u e s t c r e a t e p u t ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Get max s i z e o f body d a t a t h a t can be added t o c u r r e n t
response with g o e p c l i e n t b o d y a d d s t a t i c
∗ @param g o e p c i d
∗ @param d a t a
∗ @param l e n g t h
∗ @return s i z e i n b y t e s or 0
∗/
uint16 t g o e p c l i e n t r e q u e s t g e t m a x b o d y s i z e ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @ b r i e f Add SRM Enable
∗ @param g o e p c i d
∗/
void g o e p c l i e n t h e a d e r a d d s r m e n a b l e ( uint16 t g o e p c i d ) ;

/∗ ∗
∗ @brief Add h e a d e r w i t h s i n g l e b y t e v a l u e (8 b i t )
∗ @param goep cid
∗ @param header type
∗ @param value
∗/
void g o e p c l i e n t h e a d e r a d d b y t e ( uint16 t g o e p c i d , uint8 t
header t y p e , uint8 t v a l u e ) ;

/∗ ∗
∗ @brief Add h e a d e r w i t h word v a l u e (32 b i t )
∗ @param goep cid
∗ @param header type
∗ @param value
∗/
void g o e p c l i e n t h e a d e r a d d w o r d ( uint16 t g o e p c i d , uint8 t
header t y p e , uint32 t v a l u e ) ;

/∗ ∗
∗ @brief Add h e a d e r w i t h v a r i a b l e s i z e
∗ @param goep cid
∗ @param header type
∗ @param header data
∗ @param header data length
∗/
void g o e p c l i e n t h e a d e r a d d v a r i a b l e ( uint16 t g o e p c i d , uint8 t
header t y p e , const uint8 t ∗ h e a d e r d a t a , uint16 t
header data length ) ;

/∗ ∗
∗ @ b r i e f Add name h e a d e r t o c u r r e n t r e q u e s t
∗ @param g o e p c i d
∗ @param name
422

∗/
void g o e p c l i e n t h e a d e r a d d n a m e ( uint16 t g o e p c i d , const char ∗
name ) ;

/∗ ∗
∗ @brief Add name h e a d e r t o c u r r e n t r e q u e s t
∗ @param goep cid
∗ @param name
∗ @param name len
∗/
void g o e p c l i e n t h e a d e r a d d n a m e p r e f i x ( uint16 t g o e p c i d , const
char ∗ name , uint16 t name len ) ;

/∗ ∗
∗ @ b r i e f Add s t r i n g encoded as u n i c o d e t o c u r r e n t r e q u e s t
∗ @param g o e p c i d
∗ @param name
∗ @param name len
∗/
void g o e p c l i e n t h e a d e r a d d u n i c o d e p r e f i x ( uint16 t g o e p c i d ,
uint8 t h e a d e r i d , const char ∗ name , uint16 t name len ) ;

/∗ ∗
∗ @ b r i e f Add t a r g e t h e a d e r t o c u r r e n t r e q u e s t
∗ @param g o e p c i d
∗ @param t a r g e t
∗ @param l e n g t h o f t a r g e t
∗/
void g o e p c l i e n t h e a d e r a d d t a r g e t ( uint16 t g o e p c i d , const uint8 t
∗ t a r g e t , uint16 t l e n g t h ) ;

/∗ ∗
∗ @brief Add t y p e h e a d e r t o c u r r e n t r e q u e s t
∗ @param goep cid
∗ @param type
∗/
void g o e p c l i e n t h e a d e r a d d t y p e ( uint16 t g o e p c i d , const char ∗
type ) ;

/∗ ∗
∗ @brief Add c ou n t h e a d e r t o c u r r e n t r e q u e s t
∗ @param goep cid
∗ @param co un t
∗/
void g o e p c l i e n t h e a d e r a d d c o u n t ( uint16 t g o e p c i d , uint32 t count )
;

/∗ ∗
∗ @ b r i e f Add l e n g t h h e a d e r t o c u r r e n t r e q u e s t
∗ @param g o e p c i d
∗ @param l e n g t h
∗/
void g o e p c l i e n t h e a d e r a d d l e n g t h ( uint16 t g o e p c i d , uint32 t
length ) ;
423

/∗ ∗
∗ @ b r i e f Add a p p l i c a t i o n p a r a m e t e r s h e a d e r t o c u r r e n t r e q u e s t
∗ @param g o e p c i d
∗ @param d a t a
∗ @param l e n g h t o f a p p l i c a t i o n p a r a m e t e r s
∗/
void g o e p c l i e n t h e a d e r a d d a p p l i c a t i o n p a r a m e t e r s ( uint16 t g o e p c i d
, const uint8 t ∗ data , uint16 t l e n g t h ) ;

/∗ ∗
∗ @ b r i e f Add a p p l i c a t i o n p a r a m e t e r s h e a d e r t o c u r r e n t r e q u e s t
∗ @param g o e p c i d
∗ @param d a t a
∗ @param l e n g h t o f c h a l l e n g e r e s p o n s e
∗/
void g o e p c l i e n t h e a d e r a d d c h a l l e n g e r e s p o n s e ( uint16 t g o e p c i d ,
const uint8 t ∗ data , uint16 t l e n g t h ) ;

/∗ ∗
∗ @ b r i e f Add body
∗ @param g o e p c i d
∗ @param d a t a
∗ @param l e n g h t
∗/
void g o e p c l i e n t b o d y a d d s t a t i c ( uint16 t g o e p c i d , const uint8 t ∗
data , uint32 t l e n g t h ) ;

/∗ ∗
∗ @ b r i e f Query re mainin g b u f f e r s i z e
∗ @param g o e p c i d
∗ @return s i z e
∗/
uint16 t g o e p c l i e n t b o d y g e t o u t g o i n g b u f f e r l e n ( uint16 t g o e p c i d )
;

/∗ ∗
∗ @ b r i e f Add body
∗ @param g o e p c i d
∗ @param d a t a
∗ @param l e n g t h
∗ @param r e t l e n g t h
∗/
void g o e p c l i e n t b o d y f i l l u p s t a t i c ( uint16 t g o e p c i d , const uint8 t
∗ data , uint32 t l e n g t h , uint32 t ∗ r e t l e n g t h ) ;

/∗ ∗
∗ @brief Execute prepared r e q u e s t
∗ @param g o e p c i d
∗ @param daa
∗/
int g o e p c l i e n t e x e c u t e ( uint16 t g o e p c i d ) ;

/∗ ∗
424

∗ @brief Execute prepared r e q u e s t with f i n a l b i t


∗ @param goep cid
∗ @param final
∗/
int g o e p c l i e n t e x e c u t e w i t h f i n a l b i t ( uint16 t g o e p c i d , b o o l f i n a l
);

/∗ ∗
∗ @ b r i e f De−I n i t GOEP C l i e n t
∗/
void g o e p c l i e n t d e i n i t ( void ) ;

1.72. HFP Audio Gateway (AG) API. hfp ag.h

typedef struct {
uint8 t type ;
const char ∗ number ;
} hfp phone number t ;

/∗ ∗
∗ @ b r i e f C r ea t e HFP Audio Gateway (AG) SDP s e r v i c e r e c o r d .
∗ @param s e r v i c e
∗ @param r f c o m m c h a n n e l n r
∗ @param name or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty s t r i n g )
to skip a t t r i b u t e
∗ @param a b i l i t y t o r e j e c t c a l l
∗ @param s u p p o r t e d f e a t u r e s 32− b i t bitmap , s e e HFP AGSF ∗ v a l u e s i n
hfp . h
∗ @param c o d e c s n r
∗ @param c o d e c s
∗/
void h f p a g c r e a t e s d p r e c o r d w i t h c o d e c s ( uint8 t ∗ s e r v i c e ,
uint32 t s e r v i c e r e c o r d h a n d l e , int r fc om m c ha nn el nr ,
const char ∗ name , uint8 t

ability to reject call


, uint16 t
supported features ,
uint8 t c o d e c s n r , const
uint8 t ∗ c o d e c s ) ;

/∗ ∗
∗ @ b r i e f S e t up HFP Audio Gateway (AG) d e v i c e w i t h o u t a d d i t i o n a l
supported features .
∗ @param r f c o m m c h a n n e l n r
∗/
void h f p a g i n i t ( uint8 t r f c o m m c h a n n e l n r ) ;

/∗ ∗
∗ @brief Set codecs .
∗ @param c o d e c s n r
∗ @param c o d e c s
425

∗/
void h f p a g i n i t c o d e c s ( uint8 t c o d e c s n r , const uint8 t ∗ c o d e c s ) ;

/∗ ∗
∗ @brief Set supported f e a t u r e s .
∗ @param s u p p o r t e d f e a t u r e s 32− b i t bitmap , s e e HFP AGSF ∗ v a l u e s i n
hfp . h
∗/
void h f p a g i n i t s u p p o r t e d f e a t u r e s ( uint32 t s u p p o r t e d f e a t u r e s ) ;

/∗ ∗
∗ @ b r i e f S e t AG i n d i c a t o r s .
∗ @param i n d i c a t o r s n r
∗ @param i n d i c a t o r s
∗/
void h f p a g i n i t a g i n d i c a t o r s ( int a g i n d i c a t o r s n r , const
hfp ag indicator t ∗ ag indicators ) ;

/∗ ∗
∗ @ b r i e f S e t HF i n d i c a t o r s .
∗ @param i n d i c a t o r s n r
∗ @param i n d i c a t o r s
∗/
void h f p a g i n i t h f i n d i c a t o r s ( int h f i n d i c a t o r s n r , const
hfp generic status indicator t ∗ hf indicators ) ;

/∗ ∗
∗ @ b r i e f S e t C a l l Hold s e r v i c e s .
∗ @param i n d i c a t o r s n r
∗ @param i n d i c a t o r s
∗/
void h f p a g i n i t c a l l h o l d s e r v i c e s ( int c a l l h o l d s e r v i c e s n r , const
char ∗ c a l l h o l d s e r v i c e s [ ] ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e HFP Audio Gateway (AG) c l i e n t .
∗ @param c a l l b a c k
∗/
void h f p a g r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r custom AT command .
∗ @param hfp custom at command ( w i t h ’AT+’ p r e f i x )
∗/
void h f p a g r e g i s t e r c u s t o m a t c o m m a n d ( hfp custom at command t ∗
custom at command ) ;

/∗ ∗
∗ @ b r i e f Enable / D i s a b l e in−band r i n g t o n e .

∗ @param u s e i n b a n d r i n g t o n e
∗/
426

void h f p a g s e t u s e i n b a n d r i n g t o n e ( int u s e i n b a n d r i n g t o n e ) ;

// a c t i o n s used by l o c a l d e v i c e / u s e r

/∗ ∗
∗ @ b r i e f E s t a b l i s h RFCOMM c o n n e c t i o n , and perform s e r v i c e l e v e l
c o n n e c t i o n agreement :
∗ − exchange of supported f e a t u r e s
∗ − r e p o r t Audio Gateway (AG) i n d i c a t o r s and t h e i r s t a t u s
∗ − e n a b l e i n d i c a t o r s t a t u s u p d a t e i n t h e AG
∗ − a c c e p t t h e i n f o r m a t i o n a b o u t a v a i l a b l e c o d e c s i n t h e Hands−Free
(HF) , i f s e n t
∗ − r e p o r t own i n f o r m a t i o n d e s c r i b i n g t h e c a l l h o l d and m u l t i p a r t y
services , i f possible
∗ − r e p o r t which HF i n d i c a t o r s a r e e n a b l e d on t h e AG, i f p o s s i b l e
∗ The s t a t u s o f SLC c o n n e c t i o n e s t a b l i s h m e n t i s r e p o r t e d v i a
∗ HFP SUBEVENT SERVICE LEVEL CONNECTION ESTABLISHED .

∗ @param b d a d d r o f HF
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE COMMAND DISALLOWED i f c o n n e c t i o n
a l r e a d y e x i s t s or c o n n e c t i o n i n wrong s t a t e , or
∗ − BTSTACK MEMORY ALLOC FAILED

∗/
uint8 t h f p a g e s t a b l i s h s e r v i c e l e v e l c o n n e c t i o n ( bd addr t bd addr )
;

/∗ ∗
∗ @ b r i e f R e l e a s e t h e RFCOMM c h a n n e l and t h e a u d i o c o n n e c t i o n
b e t w e e n t h e HF and t h e AG.
∗ I f t h e a u d i o c o n n e c t i o n e x i s t s , i t w i l l be r e l e a s e d .
∗ The s t a t u s o f r e l e a s i n g t h e SLC c o n n e c t i o n i s r e p o r t e d v i a
∗ HFP SUBEVENT SERVICE LEVEL CONNECTION RELEASED .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p a g r e l e a s e s e r v i c e l e v e l c o n n e c t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @brief E s t a b l i s h audio connection .
∗ The s t a t u s o f Audio c o n n e c t i o n e s t a b l i s h m e n t i s r e p o r t e d v i a
HSP SUBEVENT AUDIO CONNECTION COMPLETE.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
427

uint8 t h f p a g e s t a b l i s h a u d i o c o n n e c t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @brief Release audio connection .
∗ The s t a t u s o f r e l e a s i n g t h e Audio c o n n e c t i o n i s r e p o r t e d v i a
HSP SUBEVENT AUDIO DISCONNECTION COMPLETE.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p a g r e l e a s e a u d i o c o n n e c t i o n ( h c i c o n h a n d l e t a c l h a n d l e )
;

/∗ ∗
∗ @ b r i e f Put t h e c u r r e n t c a l l on h o l d , i f i t e x i s t s , and a c c e p t
incoming c a l l .
∗/
void h f p a g a n s w e r i n c o m i n g c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f Join h e l d c a l l w i t h a c t i v e c a l l .
∗/
void h f p a g j o i n h e l d c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f R e j e c t incoming c a l l , i f e x i s t s , or t e r m i n a t e a c t i v e c a l l .
∗/
void h f p a g t e r m i n a t e c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f Put incoming c a l l on h o l d .
∗/
void h f p a g h o l d i n c o m i n g c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f Accept t h e h e l d incoming c a l l .
∗/
void h f p a g a c c e p t h e l d i n c o m i n g c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f R e j e c t t h e h e l d incoming c a l l .
∗/
void h f p a g r e j e c t h e l d i n c o m i n g c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f S e t microphone g a i n .

∗ @param a c l h a n d l e
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
428

∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f


c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d g a i n
range
∗/
uint8 t h f p a g s e t m i c r o p h o n e g a i n ( h c i c o n h a n d l e t a c l h a n d l e , int
gain ) ;

/∗ ∗
∗ @brief Set speaker gain .

∗ @param a c l h a n d l e
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d g a i n
range
∗/
uint8 t h f p a g s e t s p e a k e r g a i n ( h c i c o n h a n d l e t a c l h a n d l e , int
gain ) ;

/∗ ∗
∗ @brief Set b a t t e r y l e v e l .

∗ @param b a t t e r y l e v e l V a l i d range : [ 0 , 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d b a t t e r y
l e v e l range
∗/
uint8 t h f p a g s e t b a t t e r y l e v e l ( int b a t t e r y l e v e l ) ;

/∗ ∗
∗ @ b r i e f C l e a r l a s t d i a l e d number .
∗/
void h f p a g c l e a r l a s t d i a l e d n u m b e r ( void ) ;

/∗ ∗
∗ @ b r i e f S e t l a s t d i a l e d number .
∗/
void h f p a g s e t l a s t d i a l e d n u m b e r ( const char ∗ number ) ;

/∗ ∗
∗ @ b r i e f N o t i f y t h e HF t h a t an incoming c a l l i s w a i t i n g
∗ d u r i n g an o n g o i n g c a l l . The n o t i f i c a t i o n w i l l be s e n t o n l y i f t h e
HF has
∗ has p r e v i o u s l y e n a b l e d t h e ” C a l l Waiting n o t i f i c a t i o n ” i n t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
429

∗ − ERROR CODE COMMAND DISALLOWED i f c a l l w a i t i n g


n o t i f i c a t i o n i s not e n a b l e d
∗/
uint8 t h f p a g n o t i f y i n c o m i n g c a l l w a i t i n g ( h c i c o n h a n d l e t
acl handle ) ;

// Voice R e c o g n i t i o n

/∗ ∗
∗ @ b r i e f A c t i v a t e v o i c e r e c o g n i t i o n and emit
HFP SUBEVENT VOICE RECOGNITION ACTIVATED e v e n t w i t h s t a t u s
ERROR CODE SUCCESS
∗ i f s u c c e s s f u l . P r e r e q u i s i t e i s e s t a b l i s h e d SLC .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/
AG)SF VOICE RECOGNITION FUNCTION i s not s u p p o r t e d by HF and AG,
or a l r e a d y a c t i v a t e d
∗/
uint8 t h f p a g a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f D e a c t i v a t e v o i c e r e c o g n i t i o n and emit
HFP SUBEVENT VOICE RECOGNITION DEACTIVATED e v e n t w i t h s t a t u s
ERROR CODE SUCCESS
∗ i f s u c c e s s f u l . P r e r e q u i s i t e i s e s t a b l i s h e d SLC .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/
AG)SF VOICE RECOGNITION FUNCTION i s not s u p p o r t e d by HF and AG,
or a l r e a d y d e a c t i v a t e d
∗/
uint8 t h f p a g d e a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f N o t i f y HF t h a t sound w i l l be p l a y e d and
HFP SUBEVENT ENHANCED VOICE RECOGNITION AG IS STARTING SOUND
e v e n t w i t h s t a t u s ERROR CODE SUCCESS
∗ i f s u c c e s s f u l , o t h e r w i s e ERROR CODE COMMAND DISALLOWED.

∗ @param a c l h a n d l e
∗ @param a c t i v a t e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
430

∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/


AG)SF ENHANCED VOICE RECOGNITION STATUS i s not s u p p o r t e d by HF
and AG
∗/
uint8 t h f p a g e n h a n c e d v o i c e r e c o g n i t i o n r e p o r t s e n d i n g a u d i o (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f N o t i f y HF t h a t AG i s r e a d y f o r i n p u t and emit
HFP SUBEVENT ENHANCED VOICE RECOGNITION AG READY TO ACCEPT AUDIO INPUT
e v e n t w i t h s t a t u s ERROR CODE SUCCESS
∗ i f s u c c e s s f u l , o t h e r w i s e ERROR CODE COMMAND DISALLOWED.

∗ @param a c l h a n d l e
∗ @param a c t i v a t e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/
AG)SF ENHANCED VOICE RECOGNITION STATUS i s not s u p p o r t e d by HF
and AG
∗/
uint8 t h f p a g e n h a n c e d v o i c e r e c o g n i t i o n r e p o r t r e a d y f o r a u d i o (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f N o t i f y t h a t AG i s p r o c e s s i n g i n p u t and emit
HFP SUBEVENT ENHANCED VOICE RECOGNITION AG IS PROCESSING AUDIO INPUT
e v e n t w i t h s t a t u s ERROR CODE SUCCESS
∗ i f s u c c e s s f u l , o t h e r w i s e ERROR CODE COMMAND DISALLOWED.

∗ @param a c l h a n d l e
∗ @param a c t i v a t e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/
AG)SF ENHANCED VOICE RECOGNITION STATUS i s not s u p p o r t e d by HF
and AG
∗/
uint8 t h f p a g e n h a n c e d v o i c e r e c o g n i t i o n r e p o r t p r o c e s s i n g i n p u t (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f Send enhanced a u d i o r e c o g n i t i o n message and
HFP SUBEVENT ENHANCED VOICE RECOGNITION AG MESSAGE SENT e v e n t
w i t h s t a t u s ERROR CODE SUCCESS
∗ i f s u c c e s s f u l , o t h e r w i s e ERROR CODE COMMAND DISALLOWED.

∗ @param a c l h a n d l e
∗ @param a c t i v a t e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t ,
431

− ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE


i f t h e message s i z e e x c e e d s t h e
HFP MAX VR TEXT SIZE , or t h e command d o e s not
f i t i n t o a s i n g l e p a c k e t frame ,
∗ − ERROR CODE COMMAND DISALLOWED i f HF and AG do not
s u p p o r t f e a t u r e s : HFP (HF/AG)
SF ENHANCED VOICE RECOGNITION STATUS and HFP (HF/AG)
SF VOICE RECOGNITION TEXT
∗/
uint8 t h f p a g e n h a n c e d v o i c e r e c o g n i t i o n s e n d m e s s a g e (
hci con handle t acl handle , h f p v o i c e r e c o g n i t i o n s t a t e t state
, h f p v o i c e r e c o g n i t i o n m e s s a g e t msg ) ;

/∗ ∗
∗ @ b r i e f Send a phone number b a c k t o t h e HF.

∗ @param a c l h a n d l e
∗ @param phone number
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p a g s e n d p h o n e n u m b e r f o r v o i c e t a g ( h c i c o n h a n d l e t
a c l h a n d l e , const char ∗ phone number ) ;

/∗ ∗
∗ @ b r i e f R e j e c t s e n d i n g a phone number t o t h e HF.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p a g r e j e c t p h o n e n u m b e r f o r v o i c e t a g ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f S t o r e phone number w i t h i n i t i a t e d c a l l .
∗ @param t y p e
∗ @param number
∗/
void h f p a g s e t c l i p ( uint8 t type , const char ∗ number ) ;

// C e l l u l a r A c t i o n s

/∗ ∗
∗ @ b r i e f Pass t h e a c c e p t incoming c a l l e v e n t t o t h e AG.
∗/
void h f p a g i n c o m i n g c a l l ( void ) ;

/∗ ∗
∗ @ b r i e f Outgoing c a l l i n i t i a t e d
∗/
432

void h f p a g o u t g o i n g c a l l i n i t i a t e d ( void ) ;

/∗ ∗
∗ @ b r i e f Pass t h e r e j e c t o u t g o i n g c a l l e v e n t t o t h e AG.
∗/
void h f p a g o u t g o i n g c a l l r e j e c t e d ( void ) ;

/∗ ∗
∗ @ b r i e f Pass t h e a c c e p t o u t g o i n g c a l l e v e n t t o t h e AG.
∗/
void h f p a g o u t g o i n g c a l l a c c e p t e d ( void ) ;

/∗ ∗
∗ @ b r i e f Pass t h e o u t g o i n g c a l l r i n g i n g e v e n t t o t h e AG.
∗/
void h f p a g o u t g o i n g c a l l r i n g i n g ( void ) ;

/∗ ∗
∗ @ b r i e f Pass t h e o u t g o i n g c a l l e s t a b l i s h e d e v e n t t o t h e AG.
∗/
void h f p a g o u t g o i n g c a l l e s t a b l i s h e d ( void ) ;

/∗ ∗
∗ @ b r i e f Pass t h e c a l l dropped e v e n t t o t h e AG.
∗/
void h f p a g c a l l d r o p p e d ( void ) ;

/∗ ∗
∗ @ b r i e f S e t network r e g i s t r a t i o n s t a t u s .
∗ @param s t a t u s 0 − not r e g i s t e r e d , 1 − r e g i s t e r e d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d
registration status
∗/
uint8 t h f p a g s e t r e g i s t r a t i o n s t a t u s ( int r e g i s t r a t i o n s t a t u s ) ;

/∗ ∗
∗ @ b r i e f S e t network s i g n a l s t r e n g t h .

∗ @param s i g n a l s t r e n g t h [0 −5]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d s i g n a l
s t r e n g t h range
∗/
uint8 t h f p a g s e t s i g n a l s t r e n g t h ( int s i g n a l s t r e n g t h ) ;

/∗ ∗
∗ @ b r i e f S e t roaming s t a t u s .

∗ @param r o a m i n g s t a t u s 0 − no roaming , 1 − roaming a c t i v e
433

∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :


∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d roaming
status
∗/
uint8 t h f p a g s e t r o a m i n g s t a t u s ( int r o a m i n g s t a t u s ) ;

/∗ ∗
∗ @ b r i e f S e t s u b c r i b e r number i n f o r m a t i o n , e . g . t h e phone number
∗ @param numbers
∗ @param numbers count
∗/
void h f p a g s e t s u b c r i b e r n u m b e r i n f o r m a t i o n ( h f p p h o n e n u m b e r t ∗
numbers , int numbers count ) ;

/∗ ∗
∗ @ b r i e f C a l l e d by c e l l u l a r u n i t a f t e r a DTMF code was t r a n s m i t t e d ,
so t h a t t h e n e x t one can be e m i t t e d .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p a g s e n d d t m f c o d e d o n e ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Report Extended Audio Gateway Error r e s u l t c o d e s i n t h e AG
.
∗ Whenever t h e r e i s an e r r o r r e l a t i n g t o t h e f u n c t i o n a l i t y o f t h e
AG as a
∗ r e s u l t o f AT command , t h e AG s h a l l send +CME ERROR:
∗ − +CME ERROR: 0 − AG f a i l u r e
∗ − +CME ERROR: 1 − no c o n n e c t i o n t o phone
∗ − +CME ERROR: 3 − o p e r a t i o n not a l l o w e d
∗ − +CME ERROR: 4 − o p e r a t i o n not s u p p o r t e d
∗ − +CME ERROR: 5 − PH−SIM PIN r e q u i r e d
∗ − +CME ERROR: 10 − SIM not i n s e r t e d
∗ − +CME ERROR: 11 − SIM PIN r e q u i r e d
∗ − +CME ERROR: 12 − SIM PUK r e q u i r e d
∗ − +CME ERROR: 13 − SIM f a i l u r e
∗ − +CME ERROR: 14 − SIM b u s y
∗ − +CME ERROR: 16 − i n c o r r e c t password
∗ − +CME ERROR: 17 − SIM PIN2 r e q u i r e d
∗ − +CME ERROR: 18 − SIM PUK2 r e q u i r e d
∗ − +CME ERROR: 20 − memory f u l l
∗ − +CME ERROR: 21 − i n v a l i d i n d e x
∗ − +CME ERROR: 23 − memory f a i l u r e
∗ − +CME ERROR: 24 − t e x t s t r i n g t o o l o n g
∗ − +CME ERROR: 25 − i n v a l i d c h a r a c t e r s i n t e x t s t r i n g
∗ − +CME ERROR: 26 − d i a l s t r i n g t o o l o n g
∗ − +CME ERROR: 27 − i n v a l i d c h a r a c t e r s i n d i a l s t r i n g
∗ − +CME ERROR: 30 − no network s e r v i c e
434

∗ − +CME ERROR: 31 − network Timeout .


∗ − +CME ERROR: 32 − network not a l l o w e d Emergency c a l l s o n l y

∗ @param a c l h a n d l e
∗ @param e r r o r
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f e x t e n d e d a u d i o
gateway e r r o r r e p o r t i s d i s a b l e d
∗/
uint8 t h f p a g r e p o r t e x t e n d e d a u d i o g a t e w a y e r r o r r e s u l t c o d e (
hci con handle t acl handle , hfp cme error t error ) ;

/∗ ∗
∗ @ b r i e f Send u n s o l i c i t e d r e s u l t code ( most l i k e l y a r e s p o n s e t o a
vendor−s p e c i f i c command not p a r t o f s t a n d a r d HFP) .
∗ @note Emits HFP SUBEVENT CUSTOM AT MESSAGE SENT when r e s u l t code
was s e n t

∗ @param u n s o l i c i t e d r e s u l t c o d e t o send
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f e x t e n d e d a u d i o
gateway e r r o r r e p o r t i s d i s a b l e d
∗/
uint8 t h f p a g s e n d u n s o l i c i t e d r e s u l t c o d e ( h c i c o n h a n d l e t
a c l h a n d l e , const char ∗ u n s o l i c i t e d r e s u l t c o d e ) ;

/∗ ∗
∗ @ b r i e f Send r e s u l t code f o r AT command r e c e i v e d v i a
HFP SUBEVENT CUSTOM AT COMMAND
∗ @note Emits HFP SUBEVENT COMPLETE when r e s u l t code was s e n t

∗ @param ok f o r OK, or ERROR
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f e x t e n d e d a u d i o
gateway e r r o r r e p o r t i s d i s a b l e d
∗/
uint8 t h f p a g s e n d c o m m a n d r e s u l t c o d e ( h c i c o n h a n d l e t a c l h a n d l e ,
b o o l ok ) ;

/∗ ∗
∗ @ b r i e f De−I n i t HFP AG
∗/
void h f p a g d e i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f C r ea t e HFP Audio Gateway (AG) SDP s e r v i c e r e c o r d .
∗ @ de pr e ca te d Use h f p a g c r e a t e s d p r e c o r d w i t h c o d e c s i n s t e a d
∗ @param s e r v i c e
435

∗ @param r f c o m m c h a n n e l n r
∗ @param name
∗ @param a b i l i t y t o r e j e c t c a l l
∗ @param s u p o r t e d f e a t u r e s 32− b i t bitmap , s e e HFP AGSF ∗ v a l u e s i n
hfp . h
∗ @param w i d e b a n d s p e e c h s u p p o r t e d
∗/
void h f p a g c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , int rf c om m c ha nn el n r , const char ∗ name ,
uint8 t a b i l i t y t o r e j e c t c a l l , uint16 t s u p p o r t e d f e a t u r e s ,
int w i d e b a n d s p e e c h ) ;

1.73. HFP Audio Encoder API. hfp codec.h : @brief Create SCO packet
with H2 Synchronization Header and encoded audio samples

typedef struct h f p c o d e c h f p c o d e c t ;

#i f d e f ENABLE HFP WIDE BAND SPEECH


/∗ ∗
∗ @ b r i e f I n i t i a l i z e HFP Audio Codec f o r mSBC
∗ @param h f p c o d e c
∗ @param m s b c e n c o d e r c o n t e x t f o r msbc e n c o d e r
∗ @return s t a t u s
∗/
void h f p c o d e c i n i t m s b c w i t h c o d e c ( h f p c o d e c t ∗ h f p c o d e c , const
b t s t a c k s b c e n c o d e r t ∗ s b c e n c o d e r , void ∗ s b c e n c o d e r c o n t e x t )
;

/∗ ∗
∗ @ b r i e f I n i t i a l i z e HFP Audio Codec f o r mSBC
∗ @ de pr e ca te d P l e a s e use h f p c o d e c i n i t m s b c w i t h c o d e c
∗ @param h f p c o d e c
∗ @param m s b c e n c o d e r c o n t e x t f o r msbc e n c o d e r
∗ @return s t a t u s
∗/
void h f p c o d e c i n i t m s b c ( h f p c o d e c t ∗ h f p c o d e c ,
b t s t a c k s b c e n c o d e r s t a t e t ∗ msbc encoder context ) ;
#endif

#i f d e f ENABLE HFP SUPER WIDE BAND SPEECH


/∗ ∗
∗ @ b r i e f I n i t i a l i z e HFP Audio Codec f o r LC3−SWB
∗ @param h f p c o d e c
∗ @param l c 3 e n c o d e r
∗ @param l c 3 e n c o d e r c o n t e x t f o r l c 3 e n c o d e r
∗ @return s t a t u s
∗/
void h f p c o d e c i n i t l c 3 s w b ( h f p c o d e c t ∗ h f p c o d e c , const
b t s t a c k l c 3 e n c o d e r t ∗ l c 3 e n c o d e r , void ∗ l c 3 e n c o d e r c o n t e x t )
;
#endif
436

/∗ ∗
∗ @ b r i e f Get number o f a u d i o s a m p l e s p e r HFP SCO frame
∗ @param h f p c o d e c
∗ @return num a u d i o s a m p l e s p e r 7 . 5 ms SCO p a c k e t
∗/
uint16 t h f p c o d e c n u m a u d i o s a m p l e s p e r f r a m e ( const h f p c o d e c t ∗
hfp codec ) ;

/∗ ∗
∗ @ b r i e f Checks i f n e x t frame can be encoded
∗ @param h f p c o d e c
∗/
b o o l h f p c o d e c c a n e n c o d e a u d i o f r a m e n o w ( const h f p c o d e c t ∗
hfp codec ) ;

/∗ ∗
∗ Get number o f b y t e s r e a d y f o r s e n d i n g
∗ @param h f p c o d e c
∗ @return num b y t e s r e a d y f o r c u r r e n t p a c k e t
∗/
uint16 t h f p c o d e c n u m b y t e s a v a i l a b l e ( const h f p c o d e c t ∗ h f p c o d e c
);

/∗ ∗
∗ Encode a u d i o s a m p l e s f o r HFP SCO p a c k e t
∗ @param h f p c o d e c
∗ @param pcm samples − c o m p l e t e a u d i o frame o f
hfp msbc num audio samples per frame int16 samples
∗/
void h f p c o d e c e n c o d e a u d i o f r a m e ( h f p c o d e c t ∗ h f p c o d e c , i n t 1 6 t ∗
pcm samples ) ;

/∗ ∗
∗ Read from stream i n t o SCO p a c k e t b u f f e r
∗ @param h f p c o d e c
∗ @param b u f f e r t o s t o r e stream
∗ @param s i z e num b y t e s t o re ad from stream
∗/
void h f p c o d e c r e a d f r o m s t r e a m ( h f p c o d e c t ∗ h f p c o d e c , uint8 t ∗
b u f f e r , uint16 t s i z e ) ;

/∗ ∗
∗ @param h f p c o d e c
∗/
void h f p c o d e c d e i n i t ( h f p c o d e c t ∗ h f p c o d e c ) ;

1.74. HFP GSM Model API. hfp gsm model.h

typedef struct {
bool u s e d s l o t ;
hfp enhanced call status t enhanced status ;
hfp enhanced call dir t direction ;
437

h f p e n h a n c e d c a l l m o d e t mode ;
h f p e n h a n c e d c a l l m p t y t mpty ;
// TODO: s o r t on drop c a l l , so t h a t i n d e x c o r r e s p o n d s t o t a b l e
index
int i n d e x ;
uint8 t c l i p t y p e ;
char clip number [ 2 5 ] ;
} hfp gsm call t ;

h f p c a l l h e l d s t a t u s t h f p g s m c a l l h e l d s t a t u s ( void ) ;
h f p c a l l s t a t u s t h f p g s m c a l l s t a t u s ( void ) ;
h f p c a l l s e t u p s t a t u s t h f p g s m c a l l s e t u p s t a t u s ( void ) ;

int h f p g s m g e t n u m b e r o f c a l l s ( void ) ;
char ∗ h f p g s m l a s t d i a l e d n u m b e r ( void ) ;
void h f p g s m c l e a r l a s t d i a l e d n u m b e r ( void ) ;
void h f p g s m s e t l a s t d i a l e d n u m b e r ( const char∗ number ) ;

h f p g s m c a l l t ∗ h f p g s m c a l l ( int i n d e x ) ;

int h f p g s m c a l l p o s s i b l e ( void ) ;

uint8 t h f p g s m c l i p t y p e ( void ) ;
char ∗ h f p g s m c l i p n u m b e r ( void ) ;

void h f p g s m i n i t ( void ) ;
void h f p g s m d e i n i t ( void ) ;

void h f p g s m h a n d l e r ( h f p a g c a l l e v e n t t event , uint8 t index ,


uint8 t type , const char ∗ number ) ;

1.75. HFP Hands-Free (HF) API. hfp hf.h

/∗ ∗
∗ @ b r i e f C r ea t e HFP Hands−Free (HF) SDP s e r v i c e r e c o r d .
∗ @param s e r v i c e
∗ @param r f c o m m c h a n n e l n r
∗ @param name or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty s t r i n g )
to skip a t t r i b u t e
∗ @param s u p p o r t e d f e a t u r e s 32− b i t bitmap , s e e HFP HFSF ∗ v a l u e s i n
hfp . h
∗ @param c o d e c s n r number o f c o d e c s i n c o d e c s argument
∗ @param c o d e c s
∗/
void h f p h f c r e a t e s d p r e c o r d w i t h c o d e c s ( uint8 t ∗ s e r v i c e ,
uint32 t s e r v i c e r e c o r d h a n d l e , int r fc om m c ha nn el nr ,
const char ∗ name ,
uint16 t
supported features ,
uint8 t c o d e c s n r ,
const uint8 t ∗
codecs ) ;
438

/∗ ∗
∗ @ b r i e f S e t up HFP Hands−Free (HF) d e v i c e w i t h o u t a d d i t i o n a l
supported features .
∗ @param r f c o m m c h a n n e l n r
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − L2CAP SERVICE ALREADY REGISTERED,
∗ − RFCOMM SERVICE ALREADY REGISTERED or
∗ − BTSTACK MEMORY ALLOC FAILED i f a l l o c a t i o n o f
any o f RFCOMM or L2CAP s e r v i c e s f a i l e d
∗/
uint8 t h f p h f i n i t ( uint8 t r f c o m m c h a n n e l n r ) ;

/∗ ∗
∗ @brief Set codecs .
∗ @param c o d e c s n r number o f c o d e c s i n c o d e c s argument
∗ @param c o d e c s
∗/
void h f p h f i n i t c o d e c s ( uint8 t c o d e c s n r , const uint8 t ∗ c o d e c s ) ;

/∗ ∗
∗ @brief Set supported f e a t u r e s .
∗ @param s u p p o r t e d f e a t u r e s 32− b i t bitmap , s e e HFP HFSF ∗ v a l u e s i n
hfp . h
∗/
void h f p h f i n i t s u p p o r t e d f e a t u r e s ( uint32 t s u p p o r t e d f e a t u r e s ) ;

/∗ ∗
∗ @ b r i e f S e t HF i n d i c a t o r s .
∗ @param i n d i c a t o r s n r
∗ @param i n d i c a t o r s
∗/
void h f p h f i n i t h f i n d i c a t o r s ( int i n d i c a t o r s n r , const uint16 t ∗
indicators ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e HFP Hands−Free (HF) c l i e n t .
∗ @param c a l l b a c k
∗/
void h f p h f r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f S e t microphone g a i n used d u r i n g SLC f o r Volume
Synchronization .

∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE INVALID HCI COMMAND PARAMETERS i f
i n v a l i d g a i n range
∗/
uint8 t h f p h f s e t d e f a u l t m i c r o p h o n e g a i n ( uint8 t g a i n ) ;
439

/∗ ∗
∗ @ b r i e f S e t s p e a k e r g a i n used d u r i n g SLC f o r Volume
Synchronization .

∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE INVALID HCI COMMAND PARAMETERS i f
i n v a l i d g a i n range
∗/
uint8 t h f p h f s e t d e f a u l t s p e a k e r g a i n ( uint8 t g a i n ) ;

/∗ ∗
∗ @ b r i e f E s t a b l i s h RFCOMM c o n n e c t i o n w i t h t h e AG w i t h g i v e n
Bluetooth address ,
∗ and perform s e r v i c e l e v e l c o n n e c t i o n (SLC) agreement :
∗ − exchange supported f e a t u r e s
∗ − r e t r i e v e Audio Gateway (AG) i n d i c a t o r s and t h e i r s t a t u s
∗ − e n a b l e i n d i c a t o r s t a t u s u p d a t e i n t h e AG
∗ − n o t i f y t h e AG a b o u t i t s own a v a i l a b l e codecs , i f p o s s i b l e
∗ − r e t r i e v e t h e AG i n f o r m a t i o n d e s c r i b i n g t h e c a l l h o l d and
multiparty services , i f possible
∗ − r e t r i e v e which HF i n d i c a t o r s a r e e n a b l e d on t h e AG, i f p o s s i b l e
∗ The s t a t u s o f SLC c o n n e c t i o n e s t a b l i s h m e n t i s r e p o r t e d v i a
∗ HFP SUBEVENT SERVICE LEVEL CONNECTION ESTABLISHED .

∗ @param b d a d d r B l u e t o o t h a d d r e s s o f t h e AG
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE COMMAND DISALLOWED i f c o n n e c t i o n
a l r e a d y e x i s t s , or
∗ − BTSTACK MEMORY ALLOC FAILED
∗/
uint8 t h f p h f e s t a b l i s h s e r v i c e l e v e l c o n n e c t i o n ( bd addr t bd addr )
;

/∗ ∗
∗ @ b r i e f R e l e a s e t h e RFCOMM c h a n n e l and t h e a u d i o c o n n e c t i o n
b e t w e e n t h e HF and t h e AG.
∗ The s t a t u s o f r e l e a s i n g t h e SLC c o n n e c t i o n i s r e p o r t e d v i a
∗ HFP SUBEVENT SERVICE LEVEL CONNECTION RELEASED .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r e l e a s e s e r v i c e l e v e l c o n n e c t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f Enable s t a t u s u p d a t e f o r a l l i n d i c a t o r s i n t h e AG.
∗ The s t a t u s f i e l d o f t h e HFP SUBEVENT COMPLETE r e p o r t s i f t h e
command was a c c e p t e d .
∗ The s t a t u s o f an AG i n d i c a t o r i s r e p o r t e d v i a
HFP SUBEVENT AG INDICATOR STATUS CHANGED.
440


∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f e n a b l e s t a t u s u p d a t e f o r a l l a g i n d i c a t o r s (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f D i s a b l e s t a t u s u p d a t e f o r a l l i n d i c a t o r s i n t h e AG.
∗ The s t a t u s f i e l d o f t h e HFP SUBEVENT COMPLETE r e p o r t s i f t h e
command was a c c e p t e d .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f d i s a b l e s t a t u s u p d a t e f o r a l l a g i n d i c a t o r s (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f Enable or d i s a b l e s t a t u s u p d a t e f o r t h e i n d i v i d u a l
i n d i c a t o r s i n t h e AG u s i n g bitmap .
∗ The s t a t u s f i e l d o f t h e HFP SUBEVENT COMPLETE r e p o r t s i f t h e
command was a c c e p t e d .
∗ The s t a t u s o f an AG i n d i c a t o r i s r e p o r t e d v i a
HFP SUBEVENT AG INDICATOR STATUS CHANGED.

∗ @param a c l h a n d l e
∗ @param i n d i c a t o r s s t a t u s b i t m a p 32− b i t bitmap , 0 − i n d i c a t o r i s
disabled , 1 − indicator i s enabled
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f s e t s t a t u s u p d a t e f o r i n d i v i d u a l a g i n d i c a t o r s (
h c i c o n h a n d l e t a c l h a n d l e , uint32 t i n d i c a t o r s s t a t u s b i t m a p ) ;

/∗ ∗
∗ @ b r i e f Query t h e name o f t h e c u r r e n t l y s e l e c t e d Network o p e r a t o r
by AG.

∗ The name i s r e s t r i c t e d t o max 16 c h a r a c t e r s . The r e s u l t i s
reported via
∗ HFP SUBEVENT NETWORK OPERATOR CHANGED s u b t y p e
∗ c o n t a i n i n g network o p e r a t o r mode , f o r m at and name .
∗ I f no o p e r a t o r i s s e l e c t e d , f o r m a t and o p e r a t o r a r e o m i t t e d .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
441

∗ − ERROR CODE COMMAND DISALLOWED i f c o n n e c t i o n i n


wrong s t a t e
∗/
uint8 t h f p h f q u e r y o p e r a t o r s e l e c t i o n ( h c i c o n h a n d l e t a c l h a n d l e )
;

/∗ ∗
∗ @ b r i e f Enable Extended Audio Gateway Error r e s u l t c o d e s i n t h e AG
.
∗ Whenever t h e r e i s an e r r o r r e l a t i n g t o t h e f u n c t i o n a l i t y o f t h e
AG as a
∗ r e s u l t o f AT command , t h e AG s h a l l send +CME ERROR. This e r r o r i s
reported via
∗ HFP SUBEVENT EXTENDED AUDIO GATEWAY ERROR, s e e h f p c m e e r r o r t i n
hfp . h

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t
hfp hf enable report extended audio gateway error result code (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f D i s a b l e Extended Audio Gateway Error r e s u l t c o d e s i n t h e
AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t
hfp hf disable report extended audio gateway error result code (
hci con handle t acl handle ) ;

/∗ ∗
∗ @brief E s t a b l i s h audio connection .
∗ The s t a t u s o f a u d i o c o n n e c t i o n e s t a b l i s h m e n t i s r e p o r t e d v i a
HFP SUBEVENT AUDIO CONNECTION ESTABLISHED.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f c o n n e c t i o n i n
wrong s t a t e
∗/
uint8 t h f p h f e s t a b l i s h a u d i o c o n n e c t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
442

∗ @brief Release audio connection .


∗ The s t a t u s o f r e l e a s i n g o f t h e a u d i o c o n n e c t i o n i s r e p o r t e d v i a
∗ HFP SUBEVENT AUDIO CONNECTION RELEASED.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r e l e a s e a u d i o c o n n e c t i o n ( h c i c o n h a n d l e t a c l h a n d l e )
;

/∗ ∗
∗ @ b r i e f Answer incoming c a l l .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f a n s w e r i n g
incoming c a l l w i t h wrong c a l l s e t u p s t a t u s
∗/
uint8 t h f p h f a n s w e r i n c o m i n g c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e j e c t incoming c a l l .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r e j e c t i n c o m i n g c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e l e a s e a l l h e l d c a l l s or s e t s User Determined User Busy (
UDUB) f o r a w a i t i n g c a l l .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f u s e r b u s y ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e l e a s e a l l a c t i v e c a l l s ( i f any e x i s t ) and a c c e p t s t h e
o t h e r ( h e l d or w a i t i n g ) c a l l .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
443

uint8 t h f p h f e n d a c t i v e a n d a c c e p t o t h e r ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f P l a c e a l l a c t i v e c a l l s ( i f any e x i s t ) on h o l d and a c c e p t s
t h e o t h e r ( h e l d or w a i t i n g ) c a l l .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f s w a p c a l l s ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Add a h e l d c a l l t o t h e c o n v e r s a t i o n .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f j o i n h e l d c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Connect t h e two c a l l s and d i s c o n n e c t s t h e s u b s c r i b e r from
both c a l l s ( E x p l i c i t Call Transfer ) .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f c o n n e c t c a l l s ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Terminate an incoming or an o u t g o i n g c a l l .
HFP SUBEVENT CALL TERMINATED i s s e n t upon c a l l t e r m i n a t i o n .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f t e r m i n a t e c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Terminate a l l h e l d c a l l s .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
444

uint8 t h f p h f t e r m i n a t e h e l d c a l l s ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f I n i t i a t e o u t g o i n g v o i c e c a l l by p r o v i d i n g t h e d e s t i n a t i o n
phone number t o t h e AG.

∗ @param a c l h a n d l e
∗ @param number
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f d i a l n u m b e r ( h c i c o n h a n d l e t a c l h a n d l e , char ∗
number ) ;

/∗ ∗
∗ @ b r i e f I n i t i a t e o u t g o i n g v o i c e c a l l u s i n g t h e memory d i a l i n g
f e a t u r e o f t h e AG.

∗ @param a c l h a n d l e
∗ @param memory id
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f d i a l m e m o r y ( h c i c o n h a n d l e t a c l h a n d l e , int
memory id ) ;

/∗ ∗
∗ @ b r i e f I n i t i a t e o u t g o i n g v o i c e c a l l by r e c a l l i n g t h e l a s t number
d i a l e d by t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r e d i a l l a s t n u m b e r ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Enable t h e C a l l Waiting n o t i f i c a t i o n function in the
AG.
∗ The AG s h a l l send t h e c o r r e s p o n d i n g r e s u l t code t o t h e HF
whenever
∗ an incoming c a l l i s w a i t i n g d u r i n g an o n g o i n g c a l l . In t h a t e v e n t
,
∗ t h e HFP SUBEVENT CALL WAITING NOTIFICATION i s e m i t t e d .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
445

uint8 t h f p h f a c t i v a t e c a l l w a i t i n g n o t i f i c a t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @brief Disable the C a l l Waiting n o t i f i c a t i o n function in
t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f d e a c t i v a t e c a l l w a i t i n g n o t i f i c a t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f Enable t h e C a l l i n g Line I d e n t i f i c a t i o n n o t i f i c a t i o n
f u n c t i o n i n t h e AG.
∗ The AG s h a l l i s s u e t h e c o r r e s p o n d i n g r e s u l t code j u s t a f t e r e v e r y
RING i n d i c a t i o n ,
∗ when t h e HF i s a l e r t e d i n an incoming c a l l . In t h a t e v e n t ,
∗ t h e HFP SUBEVENT CALLING LINE INDETIFICATION NOTIFICATION i s
emitted .
∗ @param a c l h a n d l e
∗/
uint8 t h f p h f a c t i v a t e c a l l i n g l i n e n o t i f i c a t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @brief Disable the C a l l i n g Line I d e n t i f i c a t i o n n o t i f i c a t i o n
f u n c t i o n i n t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f d e a c t i v a t e c a l l i n g l i n e n o t i f i c a t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f D e a c t i v a t e echo c a n c e l i n g (EC) and n o i s e r e d u c t i o n (NR) i n
t h e AG and emit
∗ HFP SUBEVENT ECHO CANCELING NOISE REDUCTION DEACTIVATE w i t h
s t a t u s ERROR CODE SUCCESS i f AG s u p p o r t s EC and AG.
∗ I f t h e AG s u p p o r t s i t s own embedded echo c a n c e l i n g and/ or n o i s e
reduction function ,
∗ i t s h a l l have EC and NR a c t i v a t e d u n t i l t h i s f u n c t i o n i s c a l l e d .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
446

∗ − ERROR CODE COMMAND DISALLOWED i f HFP (HF/AG)


SF EC NR FUNCTION f e a t u r e i s not s u p p o r t e d by AG and HF
∗/
uint8 t h f p h f d e a c t i v a t e e c h o c a n c e l i n g a n d n o i s e r e d u c t i o n (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f A c t i v a t e v o i c e r e c o g n i t i o n and emit
HFP SUBEVENT VOICE RECOGNITION ACTIVATED e v e n t w i t h s t a t u s
ERROR CODE SUCCESS
∗ i f s u c c e s s f u l , o t h e r w i s e ERROR CODE COMMAND DISALLOWED.
P r e r e q u i s i t e i s e s t a b l i s h e d SLC .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/
AG)SF VOICE RECOGNITION FUNCTION i s not s u p p o r t e d by HF and AG,
or a l r e a d y a c t i v a t e d
∗/
uint8 t h f p h f a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f D e c t i v a t e v o i c e r e c o g n i t i o n and emit
HFP SUBEVENT VOICE RECOGNITION DEACTIVATED e v e n t w i t h s t a t u s
ERROR CODE SUCCESS
∗ i f s u c c e s s f u l , o t h e r w i s e ERROR CODE COMMAND DISALLOWED.
P r e r e q u i s i t e i s e s t a b l i s h e d SLC .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/
AG)SF VOICE RECOGNITION FUNCTION i s not s u p p o r t e d by HF and AG,
or a l r e a d y a c t i v a t e d
∗/
uint8 t h f p h f d e a c t i v a t e v o i c e r e c o g n i t i o n ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f I n d i c a t e t h a t t h e HF i s r e a d y t o a c c e p t a u d i o .
Prerequisite is established voice recognition session .
∗ The HF may c a l l t h i s f u n c t i o n d u r i n g an o n g o i n g AVR ( Audio Voice
R e c o g n i t i o n ) s e s s i o n t o t e r m i n a t e a u d i o o u t p u t from
∗ t h e AG ( i f t h e r e i s any ) and p r e p a r e t h e AG f o r new a u d i o i n p u t .

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
447

∗ − ERROR CODE COMMAND DISALLOWED i f f e a t u r e HFP (HF/


AG)SF ENHANCED VOICE RECOGNITION STATUS i s not s u p p o r t e d by HF
and AG, or wrong VRA s t a t u s
∗/
uint8 t h f p h f e n h a n c e d v o i c e r e c o g n i t i o n r e p o r t r e a d y f o r a u d i o (
hci con handle t acl handle ) ;

/∗ ∗
∗ @ b r i e f S e t microphone g a i n .

∗ @param a c l h a n d l e
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d g a i n
range
∗/
uint8 t h f p h f s e t m i c r o p h o n e g a i n ( h c i c o n h a n d l e t a c l h a n d l e , int
gain ) ;

/∗ ∗
∗ @brief Set speaker gain .

∗ @param a c l h a n d l e
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f i n v a l i d g a i n
range
∗/
uint8 t h f p h f s e t s p e a k e r g a i n ( h c i c o n h a n d l e t a c l h a n d l e , int
gain ) ;

/∗ ∗
∗ @ b r i e f I n s t r u c t t h e AG t o t r a n s m i t a DTMF code .

∗ @param a c l h a n d l e
∗ @param d t m f c o d e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f s e n d d t m f c o d e ( h c i c o n h a n d l e t a c l h a n d l e , char code
);

/∗ ∗
∗ @ b r i e f Read numbers from t h e AG f o r t h e p u r p o s e o f c r e a t i n g
∗ a u n i q u e v o i c e t a g and s t o r i n g t h e number and i t s l i n k e d v o i c e
∗ t a g i n t h e H F s memory .
∗ The number i s r e p o r t e d v i a HFP SUBEVENT NUMBER FOR VOICE TAG.

448

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r e q u e s t p h o n e n u m b e r f o r v o i c e t a g ( h c i c o n h a n d l e t
acl handle ) ;

/∗ ∗
∗ @ b r i e f Query t h e l i s t o f c u r r e n t c a l l s i n AG.
∗ The r e s u l t i s r e c e i v e d v i a HFP SUBEVENT ENHANCED CALL STATUS.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f q u e r y c u r r e n t c a l l s t a t u s ( h c i c o n h a n d l e t a c l h a n d l e
);

/∗ ∗
∗ @ b r i e f R e l e a s e a c a l l w i t h i n d e x i n t h e AG.

∗ @param a c l h a n d l e
∗ @param i n d e x
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r e l e a s e c a l l w i t h i n d e x ( h c i c o n h a n d l e t a c l h a n d l e ,
int i n d e x ) ;

/∗ ∗
∗ @ b r i e f P l a c e a l l p a r t i e s o f a m u l t i p a r t y c a l l on h o l d w i t h t h e
∗ exception of the s p e c i f i e d c a l l .

∗ @param a c l h a n d l e
∗ @param i n d e x
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f p r i v a t e c o n s u l t a t i o n w i t h c a l l ( h c i c o n h a n d l e t
a c l h a n d l e , int i n d e x ) ;

/∗ ∗
∗ @ b r i e f Query t h e s t a t u s o f t h e R e s p o n s e and H o l d state of
t h e AG.
∗ The r e s u l t i s r e p o r t e d v i a HFP SUBEVENT RESPONSE AND HOLD STATUS.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
449

∗/
uint8 t h f p h f r r h q u e r y s t a t u s ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Put an incoming c a l l on h o l d i n t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r r h h o l d c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Accept h e l d incoming c a l l i n t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r r h a c c e p t h e l d c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e j e c t h e l d incoming c a l l i n t h e AG.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f r r h r e j e c t h e l d c a l l ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Query t h e AG s u b s c r i b e r number . The r e s u l t i s r e p o r t e d v i a
HFP SUBEVENT SUBSCRIBER NUMBER INFORMATION.

∗ @param a c l h a n d l e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
uint8 t h f p h f q u e r y s u b s c r i b e r n u m b e r ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f S e t HF i n d i c a t o r .

∗ @param a c l h a n d l e
∗ @param a s s i g n e d n u m b e r
∗ @param v a l u e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f c o n n e c t i o n d o e s not
exist
∗/
450

uint8 t h f p h f s e t h f i n d i c a t o r ( h c i c o n h a n d l e t a c l h a n d l e , int
assigned number , int v a l u e ) ;

/∗ ∗
∗ @ b r i e f T e s t s i f in−band r i n g t o n e i s a c t i v e on AG ( r e q u i r e s SLC)

∗ @param a c l h a n d l e r
∗ @return 0 i f unknown a c l h a n d l e or in−band r i n g −t o n e d i s a b l e d ,
otherwise 1
∗/
int h f p h f i n b a n d r i n g t o n e a c t i v e ( h c i c o n h a n d l e t a c l h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Send AT command ( most l i k e l y a vendor−s p e c i f i c command not
p a r t o f s t a n d a r d HFP) .
∗ @note R e s u l t (OK/ERROR) i s r e p o r t e d v i a
HFP SUBEVENT CUSTOM AT MESSAGE SENT
∗ To r e c e i v e p o t e n t i a l u n s o l i c i t e d r e s u l t code , add
ENABLE HFP AT MESSAGES t o g e t a l l message v i a
HFP SUBEVENT AT MESSAGE RECEIVED

∗ @param a c l h a n d l e
∗ @param at command t o send
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e :
∗ − ERROR CODE UNKNOWN CONNECTION IDENTIFIER i f
c o n n e c t i o n d o e s not e x i s t , or
∗ − ERROR CODE COMMAND DISALLOWED i f e x t e n d e d a u d i o
gateway e r r o r r e p o r t i s d i s a b l e d
∗/
uint8 t h f p h f s e n d a t c o m m a n d ( h c i c o n h a n d l e t a c l h a n d l e , const
char ∗ at command ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r custom AT command .
∗ @param hfp custom at command ( w i t h ’+ ’ p r e f i x )
∗/
void h f p h f r e g i s t e r c u s t o m a t c o m m a n d ( hfp custom at command t ∗
custom at command ) ;

/∗ ∗
∗ @ b r i e f De−I n i t HFP HF
∗/
void h f p h f d e i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f C r ea t e HFP Hands−Free (HF) SDP s e r v i c e r e c o r d .
∗ @ de pr e ca te d Use h f p h f c r e a t e s d p r e c o r d w i t h c o d e c s i n s t e a d
∗ @param s e r v i c e
∗ @param r f c o m m c h a n n e l n r
∗ @param name
∗ @param s u p o r t e d f e a t u r e s 32− b i t bitmap , s e e HFP HFSF ∗ v a l u e s i n
hfp . h
∗ @param w i d e b a n d s p e e c h s u p p o r t e d
∗/
451

void h f p h f c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t


s e r v i c e r e c o r d h a n d l e , int rf c om m c ha nn el n r , const char ∗ name ,
uint16 t s u p p o r t e d f e a t u r e s , int w i d e b a n d s p e e c h ) ;

1.76. HFP mSBC Encoder API. hfp msbc.h

/∗ ∗

∗/
void h f p m s b c i n i t ( void ) ;

/∗ ∗

∗/
int h f p m s b c n u m a u d i o s a m p l e s p e r f r a m e ( void ) ;

/∗ ∗

∗/
int h f p m s b c c a n e n c o d e a u d i o f r a m e n o w ( void ) ;

/∗ ∗
∗ @param pcm samples − c o m p l e t e a u d i o frame o f
hfp msbc num audio samples per frame int16 samples
∗/
void h f p m s b c e n c o d e a u d i o f r a m e ( i n t 1 6 t ∗ pcm samples ) ;

/∗ ∗

∗/
int h f p m s b c n u m b y t e s i n s t r e a m ( void ) ;

/∗ ∗

∗ @param b u f f e r t o s t o r e stream
∗ @param s i z e num b y t e s t o re ad from stream
∗/
void h f p m s b c r e a d f r o m s t r e a m ( uint8 t ∗ b u f f e r , int s i z e ) ;

/∗ ∗
∗ @ b r i e f De−I n i t HFP mSBC Codec
∗/
void h f p m s b c d e i n i t ( void ) ;

1.77. HID Device API. hid device.h

typedef struct {
uint16 t hid device subclass ;
uint8 t hid country code ;
uint8 t hid virtual cable ;
452

uint8 t hid remote wake ;


uint8 t hid reconnect initiate ;
bool hid normally connectable ;
bool hid boot device ;
uint16 t hid ssr host max latency ;
uint16 t hid ssr host min timeout ;
uint16 t hid supervision timeout ;
const uint8 t ∗ hid descriptor ;
uint16 t hid descriptor size ;
const char ∗ device name ;
} hid sdp record t ;

/∗ ∗
∗ @ b r i e f C r ea t e HID D e vi c e SDP s e r v i c e r e c o r d .
∗ @param s e r v i c e Empty b u f f e r i n which a new s e r v i c e r e c o r d w i l l be
stored .
∗ @param h a v e r e m o t e a u d i o c o n t r o l
∗ @param s e r v i c e
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param params
∗/
void h i d c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , const h i d s d p r e c o r d t ∗ params ) ;

/∗ ∗
∗ @ b r i e f S e t up HID De v i ce
∗ @param b o o t p r o t o c o l m o d e s u p p o r t e d
∗ @param h i d d e s c r i p t o r l e n
∗ @param h i d d e s c r i p t o r
∗/
void h i d d e v i c e i n i t ( b o o l b o o t p r o t o c o l m o d e s u p p o r t e d , uint16 t
h i d d e s c r i p t o r l e n , const uint8 t ∗ h i d d e s c r i p t o r ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e HID D ev i c e c l i e n t .
∗ @param c a l l b a c k
∗/
void h i d d e v i c e r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r g e t r e p o r t c a l l b a c k f o r t h e HID D ev i c e c l i e n t .
∗ @param c a l l b a c k
∗/
void h i d d e v i c e r e g i s t e r r e p o r t r e q u e s t c a l l b a c k ( int ( ∗ c a l l b a c k ) (
uint16 t h i d c i d , h i d r e p o r t t y p e t r e p o r t t y p e , uint16 t
r e p o r t i d , int ∗ o u t r e p o r t s i z e , uint8 t ∗ o u t r e p o r t ) ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s e t r e p o r t c a l l b a c k f o r t h e HID D e vi c e c l i e n t .
∗ @param c a l l b a c k
∗/
453

void h i d d e v i c e r e g i s t e r s e t r e p o r t c a l l b a c k ( void ( ∗ c a l l b a c k ) (
uint16 t h i d c i d , h i d r e p o r t t y p e t r e p o r t t y p e , int r e p o r t s i z e
, uint8 t ∗ r e p o r t ) ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k t o r e c e i v e r e p o r t d a t a f o r t h e HID
D e vi c e c l i e n t .
∗ @param c a l l b a c k
∗/
void h i d d e v i c e r e g i s t e r r e p o r t d a t a c a l l b a c k ( void ( ∗ c a l l b a c k ) (
uint16 t c i d , h i d r e p o r t t y p e t r e p o r t t y p e , uint16 t r e p o r t i d ,
int r e p o r t s i z e , uint8 t ∗ r e p o r t ) ) ;

/∗
∗ @ b r i e f C r ea t e HID c o n n e c t i o n t o HID Host
∗ @param addr
∗ @param h i d c i d t o use f o r o t h e r commands
∗ @result status
∗/
uint8 t h i d d e v i c e c o n n e c t ( bd addr t addr , uint16 t ∗ h i d c i d ) ;

/∗
∗ @ b r i e f D i s c o n n e c t from HID Host
∗ @param h i d c i d
∗/
void h i d d e v i c e d i s c o n n e c t ( uint16 t h i d c i d ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t can send now e v e n t t o send HID Report
∗ G e n e r a t e s an HID SUBEVENT CAN SEND NOW s u b e v e n t
∗ @param h i d c i d
∗/
void h i d d e v i c e r e q u e s t c a n s e n d n o w e v e n t ( uint16 t h i d c i d ) ;

/∗ ∗
∗ @ b r i e f Send HID message on i n t e r r u p t c h a n n e l
∗ @param h i d c i d
∗/
void h i d d e v i c e s e n d i n t e r r u p t m e s s a g e ( uint16 t h i d c i d , const
uint8 t ∗ message , uint16 t m e s s a g e l e n ) ;

/∗ ∗
∗ @ b r i e f Send HID message on c o n t r o l c h a n n e l
∗ @param h i d c i d
∗/
void h i d d e v i c e s e n d c o n t r o l m e s s a g e ( uint16 t h i d c i d , const uint8 t
∗ message , uint16 t m e s s a g e l e n ) ;

/∗ ∗
∗ @ b r i e f Retutn 1 i f b o o t p r o t o c o l mode a c t i v e
∗ @param h i d c i d
∗/
int h i d d e v i c e i n b o o t p r o t o c o l m o d e ( uint16 t h i d c i d ) ;
454

/∗ ∗
∗ @ b r i e f De−I n i t HID De v i ce
∗/
void h i d d e v i c e d e i n i t ( void ) ;

1.78. HID Host API. hid host.h

/∗ ∗
∗ @ b r i e f S e t up HID Host
∗ @param h i d d e s c r i p t o r s t o r a g e
∗ @param h i d d e s c r i p t o r s t o r a g e l e n
∗/
void h i d h o s t i n i t ( uint8 t ∗ h i d d e s c r i p t o r s t o r a g e , uint16 t
hid descriptor storage len ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e HID Host .
∗ @param c a l l b a c k
∗/
void h i d h o s t r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗
∗ @ b r i e f C r ea t e HID c o n n e c t i o n t o HID D e v ic e and emit
HID SUBEVENT CONNECTION OPENED e v e n t w i t h s t a t u s code ,
∗ f o l l o w e d by HID SUBEVENT DESCRIPTOR AVAILABLE t h a t i n f o r m s i f t h e
HID D e s c r i p t o r was found . In t h e c a s e o f incoming
∗ c o n n e c t i o n , i . e . HID De v i ce i n i t i a t i n g t h e c o n n e c t i o n , t h e
HID SUBEVENT DESCRIPTOR AVAILABLE i s d e l a y e d , and t h e r e p o r t s
∗ may a l r e a d y come v i a HID SUBEVENT REPORT e v e n t . I t i s up t o t h e
a p p l i c a t i o n code i f
∗ t h e s e r e p o r t s s h o u l d be b u f f e r e d or i g n o r e d u n t i l t h e d e s c r i p t o r
is available .
∗ @note HID PROTOCOL MODE REPORT WITH FALLBACK TO BOOT w i l l t r y t i
s e t up REPORT mode , b u t f a l l b a c k t o BOOT mode i f n e c e s s a r y .
∗ @note HID SUBEVENT DESCRIPTOR AVAILABLE p o s s i b l e s t a t u s v a l u e s
are :
∗ − ERROR CODE SUCCESS i f d e s c r i p t o r a v a i l a b l e ,
∗ − ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE i f not , and
∗ − ERROR CODE MEMORY CAPACITY EXCEEDED i f d e s c r i p t o r i s l a r g e r
then the a v a i l a b l e space
∗ @param r e m o t e a d d r
∗ @param p r o t o c o l m o d e s e e h i d p r o t o c o l m o d e t i n b t s t a c k h i d . h
∗ @param h i d c i d t o use f o r o t h e r commands
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE COMMAND DISALLOWED, BTSTACK MEMORY ALLOC FAILED
∗/
uint8 t h i d h o s t c o n n e c t ( bd addr t remote addr , h i d p r o t o c o l m o d e t
p r o t o c o l m o d e , uint16 t ∗ h i d c i d ) ;

/∗
455

∗ @ b r i e f Accept incoming HID c o n n e c t i o n , t h i s s h o u l d be c a l l e d upon


r e c e i v i n g HID SUBEVENT INCOMING CONNECTION e v e n t .
∗ @param h i d c i d
∗ @param p r o t o c o l m o d e s e e h i d p r o t o c o l m o d e t i n b t s t a c k h i d . h
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t a c c e p t c o n n e c t i o n ( uint16 t h i d c i d ,
hid protocol mode t protocol mode ) ;

/∗
∗ @ b r i e f D e c l i n e incoming HID c o n n e c t i o n , t h i s s h o u l d be c a l l e d
upon r e c e i v i n g HID SUBEVENT INCOMING CONNECTION e v e n t .
∗ @param h i d c i d
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t d e c l i n e c o n n e c t i o n ( uint16 t h i d c i d ) ;

/∗
∗ @ b r i e f D i s c o n n e c t from HID D e v ic e and emit
HID SUBEVENT CONNECTION CLOSED e v e n t .
∗ @param h i d c i d
∗/
void h i d h o s t d i s c o n n e c t ( uint16 t h i d c i d ) ;

// C o n t r o l messages :

/∗
∗ @ b r i e f Send SUSPEND c o n t r o l s i g n a l t o c o n n e c t e d HID D e v ic e . A
B l u e t o o t h HID D e v ic e which r e c e i v e s a SUSPEND c o n t r o l s i g n a l
∗ may o p t i o n a l l y d i s c o n n e c t from t h e B l u e t o o t h HID Host .
∗ @param h i d c i d
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d s u s p e n d ( uint16 t h i d c i d ) ;

/∗
∗ @ b r i e f Order c o n n e c t e d HID D ev i c e t o e x i t s u s p e n d mode .
∗ The B l u e t o o t h HID D e vi c e s h a l l send a r e p o r t t o t h e B l u e t o o t h HID
Host .
∗ @param h i d c i d
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d e x i t s u s p e n d ( uint16 t h i d c i d ) ;

/∗
∗ @ b r i e f Unplug c o n n e c t e d HID D e vi c e .
456

∗ @note This i s t h e o n l y command t h a t can be a l s o r e c e i v e d from HID


D e vi c e . I t w i l l be i n d i c a t e d by r e c e i v i n g
∗ HID SUBEVENT VIRTUAL CABLE UNPLUG e v e n t , as w e l l as d i s c o n n e c t i n g
HID Host from d e v i c e .
∗ @param h i d c i d
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d v i r t u a l c a b l e u n p l u g ( uint16 t h i d c i d ) ;

/∗
∗ @ b r i e f S e t P r o t o c o l Mode on t h e B l u e t o o t h HID D e vi c e and emit
HID SUBEVENT SET PROTOCOL RESPONSE e v e n t w i t h h a n d s h a k e s t a t u s ,
see hid handshake param type t
∗ @param h i d c i d
∗ @param p r o t o c o l m o d e s e e h i d p r o t o c o l m o d e t i n b t s t a c k h i d . h
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d s e t p r o t o c o l m o d e ( uint16 t h i d c i d ,
hid protocol mode t protocol mode ) ;

/∗
∗ @ b r i e f R e t r i e v e t h e P r o t o c o l Mode o f t h e B l u e t o o t h HID D ev i c e and
emit HID SUBEVENT GET PROTOCOL RESPONSE w i t h h a n d s h a k e s t a t u s ,
see hid handshake param type t
∗ @param h i d c i d
∗ @param p r o t o c o l m o d e s e e h i d p r o t o c o l m o d e t i n b t s t a c k h i d . h
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d g e t p r o t o c o l ( uint16 t h i d c i d ) ;

/∗

∗ @ b r i e f Send r e p o r t t o a B l u e t o o t h HID D e v ic e and emit


HID SUBEVENT SET REPORT RESPONSE w i t h h a n d s h a k e s t a t u s , s e e
h i d h a n d s h a k e p a r a m t y p e t . The B l u e t o o t h HID Host s h a l l send
complete reports .
∗ @param h i d c i d
∗ @param r e p o r t t y p e s e e h i d r e p o r t t y p e t i n b t s t a c k h i d . h
∗ @param r e p o r t i d
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d s e t r e p o r t ( uint16 t h i d c i d , h i d r e p o r t t y p e t
r e p o r t t y p e , uint8 t r e p o r t i d , const uint8 t ∗ r e p o r t , uint8 t
report len ) ;
457

/∗
∗ @ b r i e f R e q u e s t a HID r e p o r t from t h e B l u e t o o t h HID De v i ce and
emit HID SUBEVENT GET REPORT RESPONSE e v e n t w i t h w i t h
handshake status , see hid handshake param type t .
∗ P o l l i n g B l u e t o o t h HID D e v i c e s u s i n g t h e GET REPORT t r a n s f e r i s
c o s t l y i n terms o f time and overhead ,
∗ and s h o u l d be a v o i d e d whenever p o s s i b l e . The GET REPORT t r a n s f e r
i s t y p i c a l l y o n l y used by a p p l i c a t i o n s
∗ t o d e t e r m i n e t h e i n i t i a l s t a t e o f a B l u e t o o t h HID De v i ce . I f t h e
s t a t e of a r e p o r t changes f r e q u e n t l y ,
∗ t h e n t h e r e p o r t s h o u l d be r e p o r t e d o v e r t h e more e f f i c i e n t
I n t e r r u p t channel , s e e h i d h o s t s e n d r e p o r t .
∗ @param h i d c i d
∗ @param r e p o r t t y p e s e e h i d r e p o r t t y p e t i n b t s t a c k h i d . h
∗ @param r e p o r t i d
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d g e t r e p o r t ( uint16 t h i d c i d , h i d r e p o r t t y p e t
r e p o r t t y p e , uint8 t r e p o r t i d ) ;

/∗ ∗
∗ @ b r i e f Send HID o u t p u t r e p o r t on i n t e r r u p t c h a n n e l .
∗ @param h i d c i d
∗ @param r e p o r t i d
∗ @param r e p o r t
∗ @param r e p o r t l e n
∗ @ r e s u l t s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
ERROR CODE UNKNOWN CONNECTION IDENTIFIER,
ERROR CODE COMMAND DISALLOWED
∗/
uint8 t h i d h o s t s e n d r e p o r t ( uint16 t h i d c i d , uint8 t r e p o r t i d ,
const uint8 t ∗ r e p o r t , uint8 t r e p o r t l e n ) ;

/∗
∗ @ b r i e f Get d e s c r i p t o r d a t a
∗ @param h i d c i d
∗ @result data
∗/
const uint8 t ∗ h i d d e s c r i p t o r s t o r a g e g e t d e s c r i p t o r d a t a ( uint16 t
hid cid ) ;

/∗
∗ @ b r i e f Get d e s c r i p t o r l e n g t h
∗ @param h i d c i d
∗ @result length
∗/
uint16 t h i d d e s c r i p t o r s t o r a g e g e t d e s c r i p t o r l e n ( uint16 t h i d c i d )
;

/∗ ∗
∗ @ b r i e f De−I n i t HID De v i ce
458

∗/
void h i d h o s t d e i n i t ( void ) ;

1.79. HSP Audio Gateway API. hsp ag.h

/∗ ∗
∗ @ b r i e f S e t up HSP AG.
∗ @param r f c o m m c h a n n e l n r
∗/
void h s p a g i n i t ( uint8 t r f c o m m c h a n n e l n r ) ;

/∗ ∗
∗ @ b r i e f C r ea t e HSP Audio Gateway (AG) SDP s e r v i c e r e c o r d .
∗ @param s e r v i c e Empty b u f f e r i n which a new s e r v i c e r e c o r d w i l l be
stored .
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param r f c o m m c h a n n e l n r
∗ @param name
∗/
void h s p a g c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , int rf c om m c ha nn el n r , const char ∗ name )
;

/∗ ∗
∗ @ b r i e f R e g i s t e r p a c k e t h a n d l e r t o r e c e i v e HSP AG e v e n t s .

∗ The HSP AG e v e n t has t y p e HCI EVENT HSP META w i t h f o l l o w i n g


subtypes :
∗ − HSP SUBEVENT RFCOMM CONNECTION COMPLETE
∗ − HSP SUBEVENT RFCOMM DISCONNECTION COMPLETE
∗ − HSP SUBEVENT AUDIO CONNECTION COMPLETE
∗ − HSP SUBEVENT AUDIO DISCONNECTION COMPLETE
∗ − HSP SUBEVENT MICROPHONE GAIN CHANGED
∗ − HSP SUBEVENT SPEAKER GAIN CHANGED
∗ − HSP SUBEVENT HS COMMAND

∗ @param c a l l b a c k
∗/
void h s p a g r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f Connect t o HSP Headset .

∗ Perform SDP q u e r y f o r an RFCOMM s e r v i c e on a remote d e v i c e ,
∗ and e s t a b l i s h an RFCOMM c o n n e c t i o n i f such s e r v i c e i s found .
Reception of the
∗ HSP SUBEVENT RFCOMM CONNECTION COMPLETE w i t h s t a t u s 0
∗ i n d i c a t e s i f the connection i s s u c c e s s f u l l y e s t a b l i s h e d .

∗ @param b d a d d r
∗/
459

void h s p a g c o n n e c t ( bd addr t bd addr ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t from HSP Headset

∗ R e c e p t i o n o f t h e HSP SUBEVENT RFCOMM DISCONNECTION COMPLETE w i t h
status 0
∗ i n d i c a t e s i f the connection i s s u c c e s s f u l l y released .
∗ @param b d a d d r
∗/
void h s p a g d i s c o n n e c t ( void ) ;

/∗ ∗
∗ @brief E s t a b l i s h audio connection .

∗ R e c e p t i o n o f t h e HSP SUBEVENT AUDIO CONNECTION COMPLETE w i t h
status 0
∗ i n d i c a t e s i f the audio connection i s s u c c e s s f u l l y e s t a b l i s h e d .
∗ @param b d a d d r
∗/
void h s p a g e s t a b l i s h a u d i o c o n n e c t i o n ( void ) ;

/∗ ∗
∗ @brief Release audio connection .

∗ R e c e p t i o n o f t h e HSP SUBEVENT AUDIO DISCONNECTION COMPLETE w i t h
status 0
∗ i n d i c a t e s i f the connection i s s u c c e s s f u l l y released .
∗ @param b d a d d r
∗/
void h s p a g r e l e a s e a u d i o c o n n e c t i o n ( void ) ;

/∗ ∗
∗ @ b r i e f S e t microphone g a i n .
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗/
void h s p a g s e t m i c r o p h o n e g a i n ( uint8 t g a i n ) ;

/∗ ∗
∗ @brief Set speaker gain .
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗/
void h s p a g s e t s p e a k e r g a i n ( uint8 t g a i n ) ;

/∗ ∗
∗ @ b r i e f S t a r t r i n g i n g b e c a u s e o f incoming c a l l .
∗/
void h s p a g s t a r t r i n g i n g ( void ) ;

/∗ ∗
∗ @ b r i e f Stop r i n g i n g ( e . g . c a l l was t e r m i n a t e d ) .
∗/
void h s p a g s t o p r i n g i n g ( void ) ;
460

/∗ ∗
∗ @ b r i e f Enable custom AT commands .

∗ Custom commands a r e d i s a b l e d by d e f a u l t .
∗ When e n a b l e d , custom AT commands a r e r e c e i v e d v i a t h e
HSP SUBEVENT HS COMMAND.
∗ @param e n a b l e
∗/
void hsp ag enable custom commands ( int e n a b l e ) ;

/∗ ∗
∗ @ b r i e f Send a custom AT command t o HSP Headset .

∗ On HSP SUBEVENT AG INDICATION, t h e c l i e n t n e ed s t o r e s p o n d
∗ w i t h t h i s f u n c t i o n w i t h t h e r e s u l t t o t h e custom command .
∗ @param r e s u l t
∗/
int h s p a g s e n d r e s u l t ( char ∗ r e s u l t ) ;

/∗ ∗
∗ @ b r i e f S e t p a c k e t t y p e s used f o r o u t g o i n g SCO c o n n e c t i o n r e q u e s t s
∗ @param common s i n g l e p a c k e t t y p e s : SCO PACKET TYPES ∗
∗/
void h s p a g s e t s c o p a c k e t t y p e s ( uint16 t p a c k e t t y p e s ) ;

/∗ ∗
∗ @ b r i e f De−I n i t HSP AG
∗/
void h s p a g d e i n i t ( void ) ;

1.80. HSP Headset API. hsp hs.h

/∗ ∗
∗ @ b r i e f S e t up HSP HS .
∗ @param r f c o m m c h a n n e l n r
∗/
void h s p h s i n i t ( uint8 t r f c o m m c h a n n e l n r ) ;

/∗ ∗
∗ @ b r i e f C r ea t e HSP Headset (HS) SDP s e r v i c e r e c o r d .
∗ @param s e r v i c e Empty b u f f e r i n which a new s e r v i c e r e c o r d w i l l be
stored .
∗ @param r f c o m m c h a n n e l n r
∗ @param name
∗ @param h a v e r e m o t e a u d i o c o n t r o l
∗/
void h s p h s c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , int rf c om m c ha nn el n r , const char ∗ name ,
uint8 t h a v e r e m o t e a u d i o c o n t r o l ) ;

/∗ ∗
461

∗ @ b r i e f R e g i s t e r p a c k e t h a n d l e r t o r e c e i v e HSP HS e v e n t s .

∗ The HSP HS e v e n t has t y p e HCI EVENT HSP META w i t h f o l l o w i n g
subtypes :
∗ − HSP SUBEVENT RFCOMM CONNECTION COMPLETE
∗ − HSP SUBEVENT RFCOMM DISCONNECTION COMPLETE
∗ − HSP SUBEVENT AUDIO CONNECTION COMPLETE
∗ − HSP SUBEVENT AUDIO DISCONNECTION COMPLETE
∗ − HSP SUBEVENT RING
∗ − HSP SUBEVENT MICROPHONE GAIN CHANGED
∗ − HSP SUBEVENT SPEAKER GAIN CHANGED
∗ − HSP SUBEVENT AG INDICATION

∗ @param c a l l b a c k
∗/
void h s p h s r e g i s t e r p a c k e t h a n d l e r ( btstack packet handler t
callback ) ;

/∗ ∗
∗ @ b r i e f Connect t o HSP Audio Gateway .

∗ Perform SDP q u e r y f o r an RFCOMM s e r v i c e on a remote d e v i c e ,
∗ and e s t a b l i s h an RFCOMM c o n n e c t i o n i f such s e r v i c e i s found .
Reception of the
∗ HSP SUBEVENT RFCOMM CONNECTION COMPLETE w i t h s t a t u s 0
∗ i n d i c a t e s i f the connection i s s u c c e s s f u l l y e s t a b l i s h e d .

∗ @param b d a d d r
∗/
void h s p h s c o n n e c t ( bd addr t bd addr ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t from HSP Audio Gateway

∗ R e l e a s e s t h e RFCOMM c h a n n e l . R e c e p t i o n o f t h e
∗ HSP SUBEVENT RFCOMM DISCONNECTION COMPLETE w i t h s t a t u s 0
∗ i n d i c a t e s i f the connection i s s u c c e s s f u l l y released .
∗ @param b d a d d r
∗/
void h s p h s d i s c o n n e c t ( void ) ;

/∗ ∗
∗ @ b r i e f Send b u t t o n p r e s s a c t i o n . T o g g l e e s t a b l i s h / r e l e a s e o f
audio connection .
∗/
void h s p h s s e n d b u t t o n p r e s s ( void ) ;

/∗ ∗
∗ @brief Triger e s t a b l i s h i n g audio connection .

∗ R e c e p t i o n o f t h e HSP SUBEVENT AUDIO CONNECTION COMPLETE w i t h
status 0
∗ i n d i c a t e s i f the audio connection i s s u c c e s s f u l l y e s t a b l i s h e d .
462

∗ @param b d a d d r
∗/
void h s p h s e s t a b l i s h a u d i o c o n n e c t i o n ( void ) ;

/∗ ∗
∗ @brief Trigger r e l e a s i n g audio connection .

∗ R e c e p t i o n o f t h e HSP SUBEVENT AUDIO DISCONNECTION COMPLETE w i t h
status 0
∗ i n d i c a t e s i f the connection i s s u c c e s s f u l l y released .
∗ @param b d a d d r
∗/
void h s p h s r e l e a s e a u d i o c o n n e c t i o n ( void ) ;

/∗ ∗
∗ @ b r i e f S e t microphone g a i n .

∗ The new g a i n v a l u e w i l l be c o n f i r m e d by t h e HSP Audio Gateway .
∗ A HSP SUBEVENT MICROPHONE GAIN CHANGED e v e n t w i l l be r e c e i v e d .
∗ @param g a i n V a l i d range : [ 0 , 1 5 ]
∗/
void h s p h s s e t m i c r o p h o n e g a i n ( uint8 t g a i n ) ;

/∗ ∗
∗ @brief Set speaker gain .

∗ The new g a i n v a l u e w i l l be c o n f i r m e d by t h e HSP Audio Gateway .
∗ A HSP SUBEVENT SPEAKER GAIN CHANGED e v e n t w i l l be r e c e i v e d .
∗ @param g a i n − v a l i d range : [ 0 , 1 5 ]
∗/
void h s p h s s e t s p e a k e r g a i n ( uint8 t g a i n ) ;

/∗ ∗
∗ @ b r i e f Enable custom i n d i c a t i o n s .

∗ Custom i n d i c a t i o n s a r e d i s a b l e d by d e f a u l t .
∗ When e n a b l e d , custom i n d i c a t i o n s a r e r e c e i v e d v i a t h e
HSP SUBEVENT AG INDICATION .
∗ @param e n a b l e
∗/
void h s p h s e n a b l e c u s t o m i n d i c a t i o n s ( int e n a b l e ) ;

/∗ ∗
∗ @ b r i e f Send answer t o custom i n d i c a t i o n .

∗ On HSP SUBEVENT AG INDICATION, t h e c l i e n t n e ed s t o r e s p o n d
∗ w i t h t h i s f u n c t i o n w i t h t h e r e s u l t t o t h e custom i n d i c a t i o n
∗ @param r e s u l t
∗/
int h s p h s s e n d r e s u l t ( const char ∗ r e s u l t ) ;

/∗ ∗
463

∗ @ b r i e f S e t p a c k e t t y p e s used f o r incoming SCO c o n n e c t i o n r e q u e s t s


∗ @param common s i n g l e p a c k e t t y p e s : SCO PACKET TYPES ∗
∗/
void h s p h s s e t s c o p a c k e t t y p e s ( uint16 t p a c k e t t y p e s ) ;

/∗ ∗
∗ @ b r i e f De−I n i t HSP AG
∗/
void h s p h s d e i n i t ( void ) ;

1.81. Personal Area Network (PAN) API. pan.h

/∗ ∗
∗ @ b r i e f C r e a t e s SDP r e c o r d f o r PANU BNEP s e r v i c e i n p r o v i d e d empty
buffer .
∗ @note Make s u r e t h e b u f f e r i s b i g enough .

∗ @param s e r v i c e i s an empty b u f f e r t o s t o r e s e r v i c e r e c o r d
∗ @param s e r v i c e r e c o r d h a n d l e f o r new s e r v i c e
∗ @param n e t w o r k p a c k e t t y p e s a r r a y o f t y p e s t e r m i n a t e d by a 0 x0000
entry
∗ @param name i f NULL, t h e d e f a u l t s e r v i c e name w i l l be a s s i g n e d
∗ @param d e s c r i p t i o n i f NULL, t h e d e f a u l t s e r v i c e d e s c r i p t i o n w i l l
be a s s i g n e d
∗ @param s e c u r i t y d e s c
∗/
void p a n c r e a t e p a n u s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t ∗ n e t w o r k p a c k e t t y p e s , const
char ∗name ,
const char ∗ d e s c r i p t i o n , s e c u r i t y d e s c r i p t i o n t s e c u r i t y d e s c ) ;

/∗ ∗
∗ @ b r i e f C r e a t e s SDP r e c o r d f o r GN BNEP s e r v i c e i n p r o v i d e d empty
buffer .
∗ @note Make s u r e t h e b u f f e r i s b i g enough .

∗ @param s e r v i c e i s an empty b u f f e r t o s t o r e s e r v i c e r e c o r d
∗ @param s e r v i c e r e c o r d h a n d l e f o r new s e r v i c e
∗ @param n e t w o r k p a c k e t t y p e s a r r a y o f t y p e s t e r m i n a t e d by a 0 x0000
entry
∗ @param name i f NULL, t h e d e f a u l t s e r v i c e name w i l l be a s s i g n e d
∗ @param d e s c r i p t i o n i f NULL, t h e d e f a u l t s e r v i c e d e s c r i p t i o n w i l l
be a s s i g n e d
∗ @param s e c u r i t y d e s c
∗ @param IPv4Subnet i s o p t i o n a l s u b n e t d e f i n i t i o n , e . g .
”10.0.0.0/8”
∗ @param IPv6Subnet i s o p t i o n a l s u b n e t d e f i n i t i o n g i v e n i n t h e
s t a n d a r d IETF f o r ma t w i t h t h e a b s o l u t e a t t r i b u t e IDs
∗/
void p a n c r e a t e g n s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t ∗ n e t w o r k p a c k e t t y p e s , const
char ∗name ,
464

const char ∗ d e s c r i p t i o n , s e c u r i t y d e s c r i p t i o n t s e c u r i t y d e s c ,
const char ∗ IPv4Subnet ,
const char ∗ IPv6Subnet ) ;

/∗ ∗
∗ @ b r i e f C r e a t e s SDP r e c o r d f o r NAP BNEP s e r v i c e i n p r o v i d e d empty
buffer .
∗ @note Make s u r e t h e b u f f e r i s b i g enough .

∗ @param s e r v i c e i s an empty b u f f e r t o s t o r e s e r v i c e r e c o r d
∗ @param s e r v i c e r e c o r d h a n d l e f o r new s e r v i c e
∗ @param name i f NULL, t h e d e f a u l t s e r v i c e name w i l l be a s s i g n e d
∗ @param n e t w o r k p a c k e t t y p e s a r r a y o f t y p e s t e r m i n a t e d by a 0 x0000
entry
∗ @param d e s c r i p t i o n i f NULL, t h e d e f a u l t s e r v i c e d e s c r i p t i o n w i l l
be a s s i g n e d
∗ @param s e c u r i t y d e s c
∗ @param n e t a c c e s s t y p e t y p e o f a v a i l a b l e network a c c e s s
∗ @param m a x n e t a c c e s s r a t e b a s e d on n e t a c c e s s t y p e measured i n
byte /s
∗ @param IPv4Subnet i s o p t i o n a l s u b n e t d e f i n i t i o n , e . g .
”10.0.0.0/8”
∗ @param IPv6Subnet i s o p t i o n a l s u b n e t d e f i n i t i o n g i v e n i n t h e
s t a n d a r d IETF f o r ma t w i t h t h e a b s o l u t e a t t r i b u t e IDs
∗/
void p a n c r e a t e n a p s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , uint16 t ∗ n e t w o r k p a c k e t t y p e s , const
char ∗name ,
const char ∗ d e s c r i p t i o n , s e c u r i t y d e s c r i p t i o n t s e c u r i t y d e s c ,
net access type t net access type ,
uint32 t m a x n e t a c c e s s r a t e , const char ∗ IPv4Subnet , const char
∗ IPv6Subnet ) ;

1.82. PBAP Client API. pbap.h

// PBAP S u p p o r t e d F e a t u r e s

#define PBAP SUPPORTED FEATURES DOWNLOAD


(1<<0)
#define PBAP SUPPORTED FEATURES BROWSING
(1<<1)
#define PBAP SUPPORTED FEATURES DATABASE IDENTIFIER
(1<<2)
#define PBAP SUPPORTED FEATURES FOLDER VERSION COUNTERS
(1<<3)
#define PBAP SUPPORTED FEATURES VCARD SELECTING
(1<<4)
#define PBAP SUPPORTED FEATURES ENHANCED MISSED CALLS
(1<<5)
#define PBAP SUPPORTED FEATURES X BT UCI VCARD PROPERTY
(1<<6)
465

#define PBAP SUPPORTED FEATURES X BT UID VCARD PROPERTY


(1<<7)
#define PBAP SUPPORTED FEATURES CONTACT REFERENCING
(1<<8)
#define PBAP SUPPORTED FEATURES DEFAULT CONTACT IMAGE FORMAT
(1<<9)

// PBAP P r o p e r t y Mask − a l s o used f o r v C a r d S e l e c t o r


#define PBAP PROPERTY MASK VERSION (1<< 0 ) // vCard
Version
#define PBAP PROPERTY MASK FN (1<< 1 ) // Formatted
Name
#define PBAP PROPERTY MASK N (1<< 2 ) //
S t r u c t u r e d P r e s e n t a t i o n o f Name
#define PBAP PROPERTY MASK PHOTO (1<< 3 ) //
A s s o c i a t e d Image or Photo
#define PBAP PROPERTY MASK BDAY (1<< 4 ) // B i r t h d a y
#define PBAP PROPERTY MASK ADR (1<< 5 ) // D e l i v e r y
Address
#define PBAP PROPERTY MASK LABEL (1<< 6 ) // D e l i v e r y
#define PBAP PROPERTY MASK TEL (1<< 7 ) // Telephone
Number
#define PBAP PROPERTY MASK EMAIL (1<< 8 ) //
E l e c t r o n i c Mail Address
#define PBAP PROPERTY MASK MAILER (1<< 9 ) //
E l e c t r o n i c Mail
#define PBAP PROPERTY MASK TZ (1<<10) // Time Zone
#define PBAP PROPERTY MASK GEO (1<<11) //
Geographic P o s i t i o n
#define PBAP PROPERTY MASK TITLE (1<<12) // Job
#define PBAP PROPERTY MASK ROLE (1<<13) // Role
within the Organization
#define PBAP PROPERTY MASK LOGO (1<<14) //
O r g a n i z a t i o n Logo
#define PBAP PROPERTY MASK AGENT (1<<15) // vCard o f
Person R e p r e s e n t i n g
#define PBAP PROPERTY MASK ORG (1<<16) // Name o f
Organization
#define PBAP PROPERTY MASK NOTE (1<<17) // Comments
#define PBAP PROPERTY MASK REV (1<<18) // R e v i s i o n
#define PBAP PROPERTY MASK SOUND (1<<19) //
P r o n u n c i a t i o n o f Name
#define PBAP PROPERTY MASK URL (1<<20) // Uniform
Resource L o c a t o r
#define PBAP PROPERTY MASK UID (1<<21) // Unique ID
#define PBAP PROPERTY MASK KEY (1<<22) // P u b l i c
E n c r y p t i o n Key
#define PBAP PROPERTY MASK NICKNAME (1<<23) // Nickname
#define PBAP PROPERTY MASK CATEGORIES (1<<24) //
Categories
#define PBAP PROPERTY MASK PROID (1<<25) // Product
ID
#define PBAP PROPERTY MASK CLASS (1<<26) // C l a s s
information
466

#define PBAP PROPERTY MASK SORT STRING (1<<27) // S t r i n g


used f o r s o r t i n g o p e r a t i o n s
#define PBAP PROPERTY MASK X IRMC CALL DATETIME (1<<28) // Time
stamp
#define PBAP PROPERTY MASK X BT SPEEDDIALKEY (1<<29) // Speed−
dial shortcut
#define PBAP PROPERTY MASK X BT UCI (1<<30) // Uniform
Caller Identifier
#define PBAP PROPERTY MASK X BT UID (1<<31) // B l u e t o o t h
Contact Unique I d e n t i f i e r

// PBAP v C a r d S e l e c t o r O p e r a t o r
#define PBAP VCARD SELECTOR OPERATOR OR 0
#define PBAP VCARD SELECTOR OPERATOR AND 1

// PBAP Format
typedef enum {
PBAP FORMAT VCARD 21 = 0 ,
PBAP FORMAT VCRAD 30
} pbap format vcard t ;

// PBAP O b j e c t Types
typedef enum {
PBAP OBJECT TYPE INVALID = 0 ,
PBAP OBJECT TYPE PHONEBOOOK,
PBAP OBJECT TYPE VCARD LISTING,
PBAP OBJECT TYPE VCARD,
} pbap object type t ;

// PBAP Phonebooks
typedef enum {
PBAP PHONEBOOK INVALID = 0 ,
PBAP PHONEBOOK TELECOM CCH,
PBAP PHONEBOOK TELECOM FAV,
PBAP PHONEBOOK TELECOM ICH,
PBAP PHONEBOOK TELECOM MCH,
PBAP PHONEBOOK TELECOM OCH,
PBAP PHONEBOOK TELECOM PB,
PBAP PHONEBOOK TELECOM SPD,
PBAP PHONEBOOK SIM TELECOM CCH,
PBAP PHONEBOOK SIM TELECOM ICH,
PBAP PHONEBOOK SIM TELECOM MCH,
PBAP PHONEBOOK SIM TELECOM OCH,
PBAP PHONEBOOK SIM TELECOM PB
} pbap phonebook t ;

// l e n g t h s
#define PBAP DATABASE IDENTIFIER LEN 16
#define PBAP FOLDER VERSION LEN 16

1.83. PBAP Client API. pbap client.h


467

/∗ ∗
∗ S et u p PhoneBook Access C l i e n t
∗/
void p b a p c l i e n t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f C r ea t e PBAP c o n n e c t i o n t o a Phone Book S e r v e r (PSE) s e r v e r
on a remote d e v i c e .
∗ I f the server requires authentication , a
PBAP SUBEVENT AUTHENTICATION REQUEST i s e m i t t e d , which
∗ can be answered w i t h p b a p a u t h e n t i c a t i o n p a s s w o r d ( . . ) .
∗ The s t a t u s o f PBAP c o n n e c t i o n e s t a b l i s h m e n t i s r e p o r t e d v i a
PBAP SUBEVENT CONNECTION OPENED e v e n t ,
∗ i . e . on s u c c e s s s t a t u s f i e l d i s s e t t o ERROR CODE SUCCESS.

∗ @param h a n d l e r
∗ @param addr
∗ @param o u t c i d t o use f o r f u r t h e r commands
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK MEMORY ALLOC FAILED i f PBAP or GOEP c o n n e c t i o n a l r e a d y
exists .
∗/
uint8 t p b a p c o n n e c t ( btstack packet handler t h a n d l e r , bd addr t
addr , uint16 t ∗ o u t c i d ) ;

/∗ ∗
∗ @ b r i e f P r o v i d e password f o r OBEX A u t h e n t i c a t i o n a f t e r r e c e i v i n g
PBAP SUBEVENT AUTHENTICATION REQUEST.
∗ The s t a t u s o f PBAP c o n n e c t i o n e s t a b l i s h m e n t i s r e p o r t e d v i a
PBAP SUBEVENT CONNECTION OPENED e v e n t ,
∗ i . e . on s u c c e s s s t a t u s f i e l d i s s e t t o ERROR CODE SUCCESS.

∗ @param p b a p c i d
∗ @param password ( n u l l t e r m i n a t e d s t r i n g ) − not c o p i e d , n ee d s t o
stay v a l i d u n t i l connection completed
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p a u t h e n t i c a t i o n p a s s w o r d ( uint16 t pb a p c id , const char ∗
password ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t s PBAP c o n n e c t i o n w i t h g i v e n i d e n t i f i e r .
∗ Event PBAP SUBEVENT CONNECTION CLOSED i n d i c a t e s t h a t PBAP
connection i s closed .

∗ @param p b a p c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p d i s c o n n e c t ( uint16 t p b a p c i d ) ;

/∗ ∗
468

∗ @ b r i e f S e t c u r r e n t f o l d e r on PSE . The s t a t u s i s r e p o r t e d v i a
PBAP SUBEVENT OPERATION COMPLETED e v e n t .

∗ @param p b a p c i d
∗ @param p a t h − n o t e : p a t h i s not c o p i e d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p s e t p h o n e b o o k ( uint16 t p ba p c id , const char ∗ path ) ;

/∗ ∗
∗ @ b r i e f S e t vCard S e l e c t o r f o r g e t / p u l l phonebook . No e v e n t i s
emitted .

∗ @param p b a p c i d
∗ @param v c a r d s e l e c t o r − c o m b i n a t i o n o f PBAP PROPERTY MASK ∗
properties
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p s e t v c a r d s e l e c t o r ( uint16 t pb a p c id , uint32 t
vcard selector ) ;

/∗ ∗
∗ @ b r i e f S e t vCard S e l e c t o r f o r g e t / p u l l phonebook . No e v e n t i s
emitted .

∗ @param p b a p c i d
∗ @param v c a r d s e l e c t o r o p e r a t o r − PBAP VCARD SELECTOR OPERATOR OR
( d e f a u l t ) or PBAP VCARD SELECTOR OPERATOR AND
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p s e t v c a r d s e l e c t o r o p e r a t o r ( uint16 t p ba p c id , int
vcard selector operator ) ;

/∗ ∗
∗ @ b r i e f S e t P r o p e r t y S e l e c t o r . No e v e n t i s e m i t t e d .
∗ @param p b a p c i d
∗ @param p r o p e r t y s e l e c t o r − c o m b i n a t i o n o f PBAP PROPERTY MASK ∗
properties
∗ @return
∗/
uint8 t p b a p s e t p r o p e r t y s e l e c t o r ( uint16 t p ba p c id , uint32 t
property selector ) ;

/∗ ∗
∗ @ b r i e f Get s i z e o f phone book from PSE . The r e s u l t i s r e p o r t e d
v i a PBAP SUBEVENT PHONEBOOK SIZE e v e n t .

∗ @param p b a p c i d
∗ @param p a t h − n o t e : p a t h i s not c o p i e d , common p a t h ’ t e l e c o m / pb .
vcf ’
469

∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e


BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p g e t p h o n e b o o k s i z e ( uint16 t pb a p c id , const char ∗ path
);

/∗ ∗
∗ @ b r i e f P u l l phone book from PSE . The r e s u l t i s r e p o r t e d v i a
r e g i s t e r e d packet handler ( see pbap connect function ) ,
∗ w i t h p a c k e t t y p e s e t t o PBAP DATA PACKET. Event
PBAP SUBEVENT OPERATION COMPLETED marks t h e end o f t h e phone
book .

∗ @param p b a p c i d
∗ @param p a t h − n o t e : p a t h i s not c o p i e d , common p a t h ’ t e l e c o m / pb .
vcf ’
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p p u l l p h o n e b o o k ( uint16 t p ba p c id , const char ∗ path ) ;

/∗ ∗
∗ @ b r i e f P u l l vCard l i s t i n g . vCard d a t a i s e m i t t e d v i a
PBAP SUBEVENT CARD RESULT e v e n t .
∗ Event PBAP SUBEVENT OPERATION COMPLETED marks t h e end o f vCard
listing .

∗ @param p b a p c i d
∗ @param p a t h
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p p u l l v c a r d l i s t i n g ( uint16 t pb a p c id , const char ∗ path
);

/∗ ∗
∗ @ b r i e f P u l l vCard e n t r y . The r e s u l t i s r e p o r t e d v i a c a l l b a c k ( s e e
pbap connect function ) ,
∗ w i t h p a c k e t t y p e s e t t o PBAP DATA PACKET.
∗ Event PBAP SUBEVENT OPERATION COMPLETED marks t h e end o f t h e
vCard e n t r y .

∗ @param p b a p c i d
∗ @param p a t h
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p p u l l v c a r d e n t r y ( uint16 t p ba p c id , const char ∗ path ) ;

/∗ ∗
∗ @ b r i e f Lookup c o n t a c t ( s ) by phone number . vCard d a t a i s e m i t t e d
v i a PBAP SUBEVENT CARD RESULT e v e n t .
∗ Event PBAP SUBEVENT OPERATION COMPLETED marks t h e end o f t h e
lookup .
470


∗ @param p b a p c i d
∗ @param phone number
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t pbap lookup by number ( uint16 t p ba p c id , const char ∗
phone number ) ;

/∗ ∗
∗ @ b r i e f Abort c u r r e n t o p e r a t i o n . No e v e n t i s e m i t t e d .

∗ @param p b a p c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p a b o r t ( uint16 t p b a p c i d ) ;

/∗ ∗
∗ @ b r i e f S e t f l o w c o n t r o l mode − d e f a u l t i s o f f . No e v e n t i s
emitted .
∗ @note When e n a b l e d , p b a p n e x t p a c k e t ne e ds t o be c a l l e d a f t e r a
p a c k e t was p r o c e s s e d t o r e c e i v e t h e n e x t one

∗ @param p b a p c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p s e t f l o w c o n t r o l m o d e ( uint16 t p ba p c id , int e n a b l e ) ;

/∗ ∗
∗ @ b r i e f T r i g g e r n e x t p a c k e t from PSE when Flow C o n t r o l Mode i s
enabled .
∗ @param p b a p c i d
∗ @return s t a t u s ERROR CODE SUCCESS on s u c c e s s , o t h e r w i s e
BTSTACK BUSY i f i n a wrong s t a t e .
∗/
uint8 t p b a p n e x t p a c k e t ( uint16 t p b a p c i d ) ;

/∗ ∗
∗ @ b r i e f De−I n i t PBAP C l i e n t
∗/
void p b a p c l i e n t d e i n i t ( void ) ;

1.84. RFCOMM API. rfcomm.h

/∗ ∗
∗ @ b r i e f S e t up RFCOMM.
∗/
void r f c o m m i n i t ( void ) ;
471

/∗ ∗
∗ @ b r i e f S e t s e c u r i t y l e v e l r e q u i r e d f o r incoming c o n n e c t i o n s , need
t o be c a l l e d b e f o r e r e g i s t e r i n g s e r v i c e s .
∗ @ de pr e ca te d use g a p s e t s e c u r i t y l e v e l i n s t e a d
∗/
void r f c o m m s e t r e q u i r e d s e c u r i t y l e v e l ( g a p s e c u r i t y l e v e l t
security level ) ;

/∗
∗ @ b r i e f C r ea t e RFCOMM c o n n e c t i o n t o a g i v e n s e r v e r c h a n n e l on a
remote d e i v c e .
∗ This c h a n n e l w i l l a u t o m a t i c a l l y p r o v i d e enough c r e d i t s t o t h e
remote s i d e .
∗ @param addr
∗ @param s e r v e r c h a n n e l
∗ @param o u t c i d
∗ @result status
∗/
uint8 t r f c o m m c r e a t e c h a n n e l ( btstack packet handler t
p a c k e t h a n d l e r , bd addr t addr , uint8 t s e r v e r c h a n n e l , uint16 t
∗ out cid ) ;

/∗
∗ @ b r i e f C r ea t e RFCOMM c o n n e c t i o n t o a g i v e n s e r v e r c h a n n e l on a
remote d e i v c e .
∗ This c h a n n e l w i l l use e x p l i c i t c r e d i t management . During c h a n n e l
e s t a b l i s h m e n t , an i n i t i a l amount o f c r e d i t s i s provided .
∗ @param addr
∗ @param s e r v e r c h a n n e l
∗ @param i n i t i a l c r e d i t s
∗ @param o u t c i d
∗ @result status
∗/
uint8 t r f c o m m c r e a t e c h a n n e l w i t h i n i t i a l c r e d i t s (
btstack packet handler t p a c k e t h a n d l e r , bd addr t addr , uint8 t
s e r v e r c h a n n e l , uint8 t i n i t i a l c r e d i t s , uint16 t ∗ out cid ) ;

/∗ ∗
∗ @ b r i e f D i s c o n n e c t s RFCOMM c h a n n e l w i t h g i v e n i d e n t i f i e r .
∗ @return s t a t u s
∗/
uint8 t r f c o m m d i s c o n n e c t ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s RFCOMM s e r v i c e f o r a s e r v e r c h a n n e l and a
maximum frame s i z e , and a s s i g n s a p a c k e t h a n d l e r .
∗ This c h a n n e l p r o v i d e s c r e d i t s a u t o m a t i c a l l y t o t h e remote s i d e −>
no f l o w c o n t r o l
∗ @param p a c k e t h a n d l e r f o r a l l c h a n n e l s o f t h i s s e r v i c e
∗ @param c h a n n e l
∗ @param m a x f r a m e s i z e
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
L2CAP SERVICE ALREADY REGISTERED or BTSTACK MEMORY ALLOC FAILED
∗/
472

uint8 t r f c o m m r e g i s t e r s e r v i c e ( btstack packet handler t


p a c k e t h a n d l e r , uint8 t channel , uint16 t m a x f r a m e s i z e ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s RFCOMM s e r v i c e f o r a s e r v e r c h a n n e l and a
maximum frame s i z e , and a s s i g n s a p a c k e t h a n d l e r .
∗ This c h a n n e l w i l l use e x p l i c i t c r e d i t management . During c h a n n e l
e s t a b l i s h m e n t , an i n i t i a l amount o f c r e d i t s i s p r o v i d e d .
∗ @param p a c k e t h a n d l e r f o r a l l c h a n n e l s o f t h i s s e r v i c e
∗ @param c h a n n e l
∗ @param m a x f r a m e s i z e
∗ @param i n i t i a l c r e d i t s
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
L2CAP SERVICE ALREADY REGISTERED or BTSTACK MEMORY ALLOC FAILED
∗/
uint8 t r f c o m m r e g i s t e r s e r v i c e w i t h i n i t i a l c r e d i t s (
btstack packet handler t p a c k e t h a n d l e r , uint8 t channel ,
uint16 t m a x f r a m e s i z e , uint8 t i n i t i a l c r e d i t s ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r RFCOMM s e r v i c e .
∗/
void r f c o m m u n r e g i s t e r s e r v i c e ( uint8 t s e r v i c e c h a n n e l ) ;

/∗ ∗
∗ @ b r i e f A c c e p t s incoming RFCOMM c o n n e c t i o n .
∗ @return s t a t u s
∗/
uint8 t r f c o m m a c c e p t c o n n e c t i o n ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f Deny incoming RFCOMM c o n n e c t i o n .
∗ @return s t a t u s
∗/
uint8 t r f c o m m d e c l i n e c o n n e c t i o n ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f Grant more incoming c r e d i t s t o t h e remote s i d e f o r t h e
g i v e n RFCOMM c h a n n e l i d e n t i f i e r .
∗ @return s t a t u s
∗/
uint8 t r f c o m m g r a n t c r e d i t s ( uint16 t rfcomm cid , uint8 t c r e d i t s ) ;

/∗ ∗
∗ @ b r i e f Checks i f RFCOMM can send p a c k e t .
∗ @param rfcomm cid
∗ @ r e s u l t t r u e i f can send now
∗/
b o o l r f c o m m c a n s e n d p a c k e t n o w ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f RFCOMM EVENT CAN SEND NOW as soon as
possible
473

∗ @note RFCOMM EVENT CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o


this function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗ @param rfcomm cid
∗ @prarm s t a t u s
∗/
uint8 t r f c o m m r e q u e s t c a n s e n d n o w e v e n t ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f Sends RFCOMM d a t a p a c k e t t o t h e RFCOMM c h a n n e l w i t h g i v e n
identifier .
∗ @param rfcomm cid
∗ @return s t a t u s
∗/
uint8 t rfcomm send ( uint16 t rfcomm cid , uint8 t ∗ data , uint16 t l e n
);

/∗ ∗
∗ @ b r i e f Sends L o c a l Line S t a t u s , s e e LINE STATUS . .
∗ @param rfcomm cid
∗ @param l i n e s t a t u s
∗ @return s t a t u s
∗/
uint8 t r f c o m m s e n d l o c a l l i n e s t a t u s ( uint16 t rfcomm cid , uint8 t
line status ) ;

/∗ ∗
∗ @ b r i e f Send l o c a l modem s t a t u s . s e e MODEM STAUS . .
∗ @param rfcomm cid
∗ @param modem status
∗ @return s t a t u s
∗/
uint8 t rfcomm send modem status ( uint16 t rfcomm cid , uint8 t
modem status ) ;

/∗ ∗
∗ @ b r i e f C o n f i g u r e remote p o r t
∗ @param rfcomm cid
∗ @param b a u d r a t e
∗ @param d a t a b i t s
∗ @param s t o p b i t s
∗ @param p a r i t y
∗ @param f l o w c o n t r o l
∗ @return s t a t u s
∗/
uint8 t r f c o m m s e n d p o r t c o n f i g u r a t i o n ( uint16 t rfcomm cid ,
rpn baud t baud rate , r p n d a t a b i t s t data bits , r p n s t o p b i t s t
s t o p b i t s , r p n p a r i t y t p a r i t y , uint8 t f l o w c o n t r o l ) ;

/∗ ∗
∗ @ b r i e f Query remote p o r t
∗ @param rfcomm cid
∗ @return s t a t u s
∗/
474

uint8 t r f c o m m q u e r y p o r t c o n f i g u r a t i o n ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f Query max frame s i z e
∗ @param rfcomm cid
∗ @return max frame s i z e
∗/
uint16 t r f c o m m g e t m a x f r a m e s i z e ( uint16 t rfcomm cid ) ;

/∗ ∗
∗ @ b r i e f R e s e r v e p a c k e t b u f f e r t o a l l o w t o c r e a t e RFCOMM p a c k e t i n
place
∗ @note Must o n l y be c a l l e d a f t e r a ’ can send now ’ c h e c k or e v e n t
∗ @note A s s e r t s i f p a c k e t b u f f e r i s a l r e a d y r e s e r v e d

∗ i f ( rfcomm can send packet now ( cid ) ) {
∗ rfcomm reserve packet buffer () ;
∗ uint8 t ∗ buffer = rfcomm get outgoing buffer () ;
∗ uint16 t b u f f e r s i z e = rfcomm get max frame size ( cid ) ;
∗ . . setup data in b u f f e r with len . .
∗ rfcomm send prepared ( cid , len )
∗ }
∗/
void r f c o m m r e s e r v e p a c k e t b u f f e r ( void ) ;

/∗ ∗
∗ @ b r i e f Get o u t g o i n g b u f f e r
∗ @return p o i n t e r t o o u t g o i n g rfcomm b u f f e r
∗/
uint8 t ∗ r f c o m m g e t o u t g o i n g b u f f e r ( void ) ;

/∗ ∗
∗ @ b r i e f Send p a c k e t p r e p a r e d i n o u t g o i n g b u f f e r
∗ @note This r e l e a s e s t h e o u t g o i n g rfcomm b u f f e r
∗ @param rfcomm cid
∗ @param l e n
∗ @return s t a t u s
∗/
uint8 t r f c o m m s e n d p r e p a r e d ( uint16 t rfcomm cid , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f R e l e a s e o u t g o i n g b u f f e r i n c a s e r f c o m m s e n d p r e p a r e d was
not c a l l e d
∗/
void r f c o m m r e l e a s e p a c k e t b u f f e r ( void ) ;

/∗ ∗
∗ @ b r i e f Enable L2CAP ERTM mode f o r RFCOMM. r e q u e s t c a l l b a c k i s
used t o p r o v i d e ERTM b u f f e r . r e l e a s e d c a l l b a c k r e t u r n s b u f f e r

∗ @note on r e q u e s t c a l l b a c k , t h e app must s e t t h e e r t m c o n f i g ,
b u f f e r , s i z e f i e l d s t o e n a b l e ERTM f o r t h e c u r r e n t c o n n e c t i o n
∗ @note i f b u f f e r i s not s e t , BASIC mode w i l l be used i n s t e a d

475

∗ @note r e l e a s e d c a l l b a c k p r o v i d e s e r t m i d from e a r l i e r r e q u e s t t o
match r e q u e s t and r e l e a s e

∗ @param r e q u e s t c a l l b a c k
∗ @param r e l e a s e d c a l l b a c k
∗/
void r f c o m m e n a b l e l 2 c a p e r t m ( void r e q u e s t c a l l b a c k (
r f c o m m e r t m r e q u e s t t ∗ r e q u e s t ) , void r e l e a s e d c a l l b a c k (
uint16 t e r t m i d ) ) ;

// Event g e t t e r s f o r RFCOMM EVENT PORT CONFIGURATION

/∗ ∗
∗ @ b r i e f Get f i e l d rfcomm cid from e v e n t
RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return rfcomm cid
∗/
s t a t i c i n l i n e uint16 t
r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t r f c o m m c i d ( const uint8 t ∗
event ) {
return l i t t l e e n d i a n r e a d 1 6 ( event , 2 ) ;
}

/∗ ∗
∗ @ b r i e f Get f i e l d l o c a l from e v e n t RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return remote − f a l s e f o r l o c a l p o r t , t r u e f o r remote p o r t
∗/
s t a t i c i n l i n e b o o l r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t r e m o t e ( const
uint8 t ∗ e v e n t ) {
return e v e n t [ 4 ] != 0 ;
}

/∗ ∗
∗ @ b r i e f Get f i e l d b a u d r a t e from e v e n t
RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return b a u d r a t e
∗/

static i n l i n e rpn baud t


r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t b a u d r a t e ( const uint8 t ∗
event ) {
return ( r p n b a u d t ) e v e n t [ 5 ] ;
}

/∗ ∗
∗ @ b r i e f Get f i e l d d a t a b i t s from e v e n t
RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return d a t a b i t s
∗/
476

static i n l i n e rpn data bits t


r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t d a t a b i t s ( const uint8 t ∗
event ) {
return ( r p n d a t a b i t s t ) ( e v e n t [ 6 ] & 3 ) ;
}
/∗ ∗
∗ @ b r i e f Get f i e l d s t o p b i t s from e v e n t
RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return s t o p b i t s
∗/
static i n l i n e r p n s t o p b i t s t
r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t s t o p b i t s ( const uint8 t ∗
event ) {
return ( r p n s t o p b i t s t ) ( ( e v e n t [ 6 ] >> 2 ) & 1 ) ;
}

/∗ ∗
∗ @ b r i e f Get f i e l d p a r i t y from e v e n t
RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return p a r i t y
∗/
static i n l i n e rpn parity t
r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t p a r i t y ( const uint8 t ∗ e v e n t
){
return ( r p n p a r i t y t ) ( ( e v e n t [ 6 ] >> 3 ) & 7 ) ;
}

/∗ ∗
∗ @ b r i e f Get f i e l d f l o w c o n t r o l from e v e n t
RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return f l o w c o n t r o l
∗/

s t a t i c i n l i n e uint8 t
r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t f l o w c o n t r o l ( const uint8 t ∗
event ) {
return e v e n t [ 7 ] & 0 x 3 f ;
}

/∗ ∗
∗ @ b r i e f Get f i e l d xon from e v e n t RFCOMM EVENT PORT CONFIGURATION
∗ @param e v e n t p a c k e t
∗ @return xon
∗/
s t a t i c i n l i n e uint8 t r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t x o n ( const
uint8 t ∗ e v e n t ) {
return e v e n t [ 8 ] ;
}

/∗ ∗
477

∗ @ b r i e f Get f i e l d x o f f from e v e n t RFCOMM EVENT PORT CONFIGURATION


∗ @param e v e n t p a c k e t
∗ @return x o f f
∗/
s t a t i c i n l i n e uint8 t r f c o m m e v e n t p o r t c o n f i g u r a t i o n g e t x o f f ( const
uint8 t ∗ e v e n t ) {
return e v e n t [ 9 ] ;
}

/∗ ∗
∗ @ b r i e f De−I n i t RFCOMM
∗/
void r f c o m m d e i n i t ( void ) ;

1.85. SDP Client API. sdp client.h

typedef struct d e s t a t e {
uint8 t in state GET DE HEADER LENGTH ;
uint32 t a d d o n h e a d e r b y t e s ;
uint32 t d e s i z e ;
uint32 t d e o f f s e t ;
} de state t ;

void d e s t a t e i n i t ( d e s t a t e t ∗ s t a t e ) ;
int d e s t a t e s i z e ( uint8 t eventByte , d e s t a t e t ∗ d e s t a t e ) ;

/∗ ∗
∗ @ b r i e f SDP C l i e n t I n i t
∗/
void s d p c l i e n t i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Checks i f t h e SDP C l i e n t i s r e a d y
∗ @ de pr e ca te d P l e a s e use s d p c l i e n t r e g i s t e r q u e r y c a l l b a c k i n s t e a d
∗ @return t r u e when no q u e r y i s a c t i v e
∗/
b o o l s d p c l i e n t r e a d y ( void ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t s a c a l l b a c k , when t h e SDP C l i e n t i s r e a d y and can
be used
∗ @note The c a l l b a c k might happens b e f o r e
s d p c l i e n t r e g i s t e r q u e r y c a l l b a c k has r e t u r n e d
∗ @param c a l l b a c k r e g i s t r a t i o n
∗/
uint8 t s d p c l i e n t r e g i s t e r q u e r y c a l l b a c k (
btstack context callback registration t ∗ callback registration )
;

/∗ ∗
∗ @ b r i e f Q u e r i e s t h e SDP s e r v i c e o f t h e remote d e v i c e g i v e n a
s e r v i c e s e a r c h p a t t e r n and a l i s t o f a t t r i b u t e IDs .
478

∗ The remote d a t a i s h a n d l e d by t h e SDP p a r s e r . The SDP p a r s e r


d e l i v e r s a t t r i b u t e v a l u e s and done e v e n t v i a t h e c a l l b a c k .
∗ @param c a l l b a c k f o r a t t r i b u t e s v a l u e s and done e v e n t
∗ @param remote a d d r e s s
∗ @param d e s s e r v i c e s e a r c h p a t t e r n
∗ @param d e s a t t r i b u t e i d l i s t
∗/
uint8 t s d p c l i e n t q u e r y ( btstack packet handler t c a l l b a c k ,
bd addr t remote , const uint8 t ∗ d e s s e r v i c e s e a r c h p a t t e r n ,
const uint8 t ∗ d e s a t t r i b u t e i d l i s t ) ;

/∗
∗ @ b r i e f S e a r c h e s SDP r e c o r d s on a remote d e v i c e f o r a l l s e r v i c e s
w i t h a g i v e n UUID .
∗ @note c a l l s s d p c l i e n t q u e r y w i t h s e r v i c e s e a r c h p a t t e r n b a s e d on
uuid16
∗/
uint8 t s d p c l i e n t q u e r y u u i d 1 6 ( btstack packet handler t c a l l b a c k ,
bd addr t remote , uint16 t uuid16 ) ;

/∗
∗ @ b r i e f S e a r c h e s SDP r e c o r d s on a remote d e v i c e f o r a l l s e r v i c e s
w i t h a g i v e n UUID .
∗ @note c a l l s s d p c l i e n t q u e r y w i t h s e r v i c e s e a r c h p a t t e r n b a s e d on
uuid128
∗/
uint8 t s d p c l i e n t q u e r y u u i d 1 2 8 ( btstack packet handler t c a l l b a c k ,
bd addr t remote , const uint8 t ∗ uuid128 ) ;

/∗ ∗
∗ @ b r i e f R e t r i e v e s a l l a t t r i b u t e IDs o f a SDP r e c o r d s p e c i f i e d by
i t s s e r v i c e r e c o r d h a n d l e and a l i s t o f a t t r i b u t e IDs .
∗ The remote d a t a i s h a n d l e d by t h e SDP p a r s e r . The SDP p a r s e r
d e l i v e r s a t t r i b u t e v a l u e s and done e v e n t v i a t h e c a l l b a c k .
∗ @note o n l y p r o v i d e d i f ENABLE SDP EXTRA QUERIES i s d e f i n e d
∗ @param c a l l b a c k f o r a t t r i b u t e s v a l u e s and done e v e n t
∗ @param remote a d d r e s s
∗ @param s e a r c h s e r v i c e r e c o r d h a n d l e
∗ @param d e s a t t r i b u t e I D L i s t
∗/
uint8 t s d p c l i e n t s e r v i c e a t t r i b u t e s e a r c h ( btstack packet handler t
c a l l b a c k , bd addr t remote , uint32 t
s e a r c h s e r v i c e r e c o r d h a n d l e , const uint8 t ∗
des attributeIDList ) ;

/∗ ∗
∗ @ b r i e f Query t h e l i s t o f SDP r e c o r d s t h a t match a g i v e n s e r v i c e
search pattern .
∗ The remote d a t a i s h a n d l e d by t h e SDP p a r s e r . The SDP p a r s e r
d e l i v e r s a t t r i b u t e v a l u e s and done e v e n t v i a t h e c a l l b a c k .
∗ @note o n l y p r o v i d e d i f ENABLE SDP EXTRA QUERIES i s d e f i n e d
∗ @param c a l l b a c k f o r a t t r i b u t e s v a l u e s and done e v e n t
∗ @param remote a d d r e s s
479

∗ @param d e s s e r v i c e s e a r c h p a t t e r n
∗/
uint8 t s d p c l i e n t s e r v i c e s e a r c h ( btstack packet handler t c a l l b a c k ,
bd addr t remote , const uint8 t ∗ d e s s e r v i c e s e a r c h p a t t e r n ) ;

#i f d e f ENABLE SDP EXTRA QUERIES


void s d p c l i e n t p a r s e s e r v i c e r e c o r d h a n d l e l i s t ( uint8 t ∗ packet ,
uint16 t t o t a l c o u n t , uint16 t c u r r e n t c o u n t ) ;
#endif

/∗ ∗
∗ @ b r i e f De−I n i t SDP C l i e n t
∗/
void s d p c l i e n t d e i n i t ( void ) ;

1.86. SDP Client RFCOMM API. sdp client rfcomm.h

/∗ ∗
∗ @ b r i e f S e a r c h e s SDP r e c o r d s on a remote d e v i c e f o r RFCOMM
s e r v i c e s w i t h a g i v e n 16− b i t UUID anywhere .
∗ @note c a l l s s d p s e r v i c e s e a r c h p a t t e r n f o r u u i d 1 6 t h a t u s e s
global buffer
∗ @param c a l l b a c k h a n d l e r
∗ @param remote BD ADDR
∗ @param uuid16
∗/
uint8 t s d p c l i e n t q u e r y r f c o m m c h a n n e l a n d n a m e f o r u u i d (
btstack packet handler t c a l l b a c k , bd addr t remote , uint16 t
uuid16 ) ;

/∗ ∗
∗ @ b r i e f S e a r c h e s SDP r e c o r d s on a remote d e v i c e f o r RFCOMM
s e r v i c e s w i t h a g i v e n 16− b i t UUID i n i t s S e r v i c e C l a s s I D L i s t
∗ @note c a l l s s d p s e r v i c e s e a r c h p a t t e r n f o r u u i d 1 6 t h a t u s e s
global buffer
∗ @param c a l l b a c k h a n d l e r
∗ @param remote BD ADDR
∗ @param uuid16
∗/
uint8 t
sdp client query rfcomm channel and name for service class uuid (
btstack packet handler t c a l l b a c k , bd addr t remote , uint16 t
uuid16 ) ;

/∗ ∗
∗ @ b r i e f S e a r c h e s SDP r e c o r d s on a remote d e v i c e f o r RFCOMM
s e r v i c e s w i t h a g i v e n 128− b i t UUID anywhere
∗ @note c a l l s s d p s e r v i c e s e a r c h p a t t e r n f o r u u i d 1 2 8 t h a t u s e s
global buffer
∗ @param c a l l b a c k h a n d l e r
∗ @param remote BD ADDR
∗ @param uuid128
480

∗/
uint8 t s d p c l i e n t q u e r y r f c o m m c h a n n e l a n d n a m e f o r u u i d 1 2 8 (
btstack packet handler t c a l l b a c k , bd addr t remote , const
uint8 t ∗ uuid128 ) ;

/∗ ∗
∗ @ b r i e f S e a r c h e s SDP r e c o r d s on a remote d e v i c e f o r RFCOMM
s e r v i c e s with a given s e r v i ce search pattern .
∗/
uint8 t s d p c l i e n t q u e r y r f c o m m c h a n n e l a n d n a m e f o r s e a r c h p a t t e r n (
btstack packet handler t c a l l b a c k , bd addr t remote , const
uint8 t ∗ d e s s e r v i c e S e a r c h P a t t e r n ) ;

1.87. SDP Server API. sdp server.h

/∗ ∗
∗ @ b r i e f S e t up SDP S e r v e r .
∗/
void s d p i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r S e r v i c e Record w i t h d a t a b a s e u s i n g
ServiceRecordHandle stored in record
∗ @pre A t t r i b u t e I D s a r e i n a s c e n d i n g o r d e r
∗ @pre S e r v i c e R e c o r d H a n d l e i s f i r s t a t t r i b u t e and v a l i d
∗ @param r e c o r d i s not c o p i e d !
∗ @result status
∗/
uint8 t s d p r e g i s t e r s e r v i c e ( const uint8 t ∗ r e c o r d ) ;

/∗ ∗
∗ @brief Unregister s e r v i c e record i n t e r n a l l y .
∗/
void s d p u n r e g i s t e r s e r v i c e ( uint32 t s e r v i c e r e c o r d h a n d l e ) ;

/∗ ∗
∗ @ b r i e f g e t s s e r v i c e r e c o r d h a n d l e from r e c o r d
∗ @ r e s u t l s e r v i c e r e c o r d h a n d l e or 0
∗/
uint32 t s d p g e t s e r v i c e r e c o r d h a n d l e ( const uint8 t ∗ r e c o r d ) ;

/∗ ∗
∗ @ b r i e f Finds an unused v a l i d s e r v i c e r e c o r d h a n d l e
∗ @result handle
∗/
uint32 t s d p c r e a t e s e r v i c e r e c o r d h a n d l e ( void ) ;

/∗ ∗
∗ @brief g e t s record for handle
∗ @result record
∗/
481

uint8 t ∗ s d p g e t r e c o r d f o r h a n d l e ( uint32 t h a n d l e ) ;

/∗ ∗
∗ @ b r i e f De−I n i t SDP S e r v e r
∗/
void s d p d e i n i t ( void ) ;

1.88. SDP Utils API. sdp util.h

// OFFSETS FOR LOCALIZED ATTRIBUTES −


BLUETOOTH ATTRIBUTE LANGUAGE BASE ATTRIBUTE ID LIST
#define SDP Offset ServiceName 0 x0000
#define S D P O f f s e t S e r v i c e D e s c r i p t i o n 0 x0001
#define SDP Offset ProviderName 0 x0002

typedef enum {
DE NIL = 0 ,
DE UINT ,
DE INT ,
DE UUID ,
DE STRING ,
DE BOOL,
DE DES ,
DE DEA,
DE URL
} de type t ;

typedef enum {
DE SIZE 8 = 0 ,
DE SIZE 16 ,
DE SIZE 32 ,
DE SIZE 64 ,
DE SIZE 128 ,
DE SIZE VAR 8 ,
DE SIZE VAR 16 ,
DE SIZE VAR 32
} de size t ;

// MARK: DateElement
void de du mp da ta el em ent ( const uint8 t ∗ r e c o r d ) ;
uint32 t d e g e t l e n ( const uint8 t ∗ h e a d e r ) ;

// @note r e t u r n e d ” s t r i n g ” i s not NULL t e r m i n a t e d


const uint8 t ∗ d e g e t s t r i n g ( const uint8 t ∗ e l e m e n t ) ;

d e s i z e t d e g e t s i z e t y p e ( const uint8 t ∗ h e a d e r ) ;
d e t y p e t d e g e t e l e m e n t t y p e ( const uint8 t ∗ h e a d e r ) ;
uint32 t d e g e t h e a d e r s i z e ( const uint8 t ∗ h e a d e r ) ;
// r e t u r n s t r u e i f u i n t 1 6 was re ad
bool d e e l e m e n t g e t u i n t 1 6 ( const uint8 t ∗ element , uint16 t ∗
value ) ;
482

uint32 t d e g e t d a t a s i z e ( const uint8 t ∗ h e a d e r ) ;


uint32 t d e g e t u u i d 3 2 ( const uint8 t ∗ e l e m e n t ) ;
// r e t u r n s t r u e i f u i n t 1 6 was re ad
bool d e g e t n o r m a l i z e d u u i d ( uint8 t ∗ uuid128 , const uint8 t ∗
element ) ;

void d e c r e a t e s e q u e n c e ( uint8 t ∗ h e a d e r ) ;
void d e s t o r e d e s c r i p t o r w i t h l e n ( uint8 t ∗ header , d e t y p e t
type , d e s i z e t s i z e , uint32 t l e n ) ;
uint8 t ∗ d e p u s h s e q u e n c e ( uint8 t ∗ s e q u e n c e ) ;
void d e p o p s e q u e n c e ( uint8 t ∗ parent , uint8 t ∗ c h i l d ) ;
void de add number ( uint8 t ∗ sequence , d e t y p e t type , d e s i z e t
s i z e , uint32 t v a l u e ) ;
void d e a d d d a t a ( uint8 t ∗ sequence , d e t y p e t type , uint16 t
s i z e , uint8 t ∗ data ) ;
void d e a d d u u i d 1 2 8 ( uint8 t ∗ sequence , uint8 t ∗ uuid ) ;

// r e t u r n s d a t a e l e m e n t l e n i f d a t e e l e m e n t i s s m a l l e r than s i z e
uint32 t d e g e t l e n s a f e ( const uint8 t ∗ header , uint32 t s i z e ) ;

// MARK: DES i t e r a t o r
typedef struct {
uint8 t ∗ e l e m e n t ;
uint16 t pos ;
uint16 t l e n g t h ;
} des iterator t ;

bool des i t e r a t o r i n i t ( d e s i t e r a t o r t ∗ i t , uint8 t ∗ e l e m e n t ) ;


bool des iterator has more ( des iterator t ∗ it ) ;
de type t des iterator get type ( des iterator t ∗ it ) ;
uint16 t des iterator get size ( des iterator t ∗ it ) ;
uint8 t ∗ des iterator get element ( des iterator t ∗ it ) ;
void des iterator next ( des iterator t ∗ it ) ;

// MARK: SDP
uint16 t s d p a p p e n d a t t r i b u t e s i n a t t r i b u t e I D L i s t ( uint8 t ∗ r e c o r d ,
uint8 t ∗ a t t r i b u t e I D L i s t , uint16 t s t a r t O f f s e t , uint16 t
maxBytes , uint8 t ∗ b u f f e r ) ;
uint8 t ∗ s d p g e t a t t r i b u t e v a l u e f o r a t t r i b u t e i d ( uint8 t ∗ r e c o r d ,
uint16 t a t t r i b u t e I D ) ;
bool s d p s e t a t t r i b u t e v a l u e f o r a t t r i b u t e i d ( uint8 t ∗ r e c o r d ,
uint16 t a t t r i b u t e I D , uint32 t v a l u e ) ;
bool s d p r e c o r d m a t c h e s s e r v i c e s e a r c h p a t t e r n ( uint8 t ∗ r e c o r d ,
uint8 t ∗ s e r v i c e S e a r c h P a t t e r n ) ;
uint16 t s d p g e t f i l t e r e d s i z e ( uint8 t ∗ r e c o r d , uint8 t ∗
attributeIDList ) ;
bool s d p f i l t e r a t t r i b u t e s i n a t t r i b u t e I D L i s t ( uint8 t ∗ r e c o r d ,
uint8 t ∗ a t t r i b u t e I D L i s t , uint16 t s t a r t O f f s e t , uint16 t
maxBytes , uint16 t ∗ usedBytes , uint8 t ∗ b u f f e r ) ;
bool s d p a t t r i b u t e l i s t c o n t a i n s i d ( uint8 t ∗ a t t r i b u t e I D L i s t ,
uint16 t a t t r i b u t e I D ) ;

/∗
∗ @ b r i e f Returns s e r v i c e s e a r c h p a t t e r n f o r g i v e n UUID−16
483

∗ @note Uses f i x e d b u f f e r
∗/
uint8 t ∗ s d p s e r v i c e s e a r c h p a t t e r n f o r u u i d 1 6 ( uint16 t uuid16 ) ;

/∗
∗ @ b r i e f Returns s e r v i c e s e a r c h p a t t e r n f o r g i v e n UUID−128
∗ @note Uses f i x e d b u f f e r
∗/
uint8 t ∗ s d p s e r v i c e s e a r c h p a t t e r n f o r u u i d 1 2 8 ( const uint8 t ∗
uuid128 ) ;

1.89. SPP Server API. spp server.h : Create SPP SDP Records.

/∗ ∗
∗ @ b r i e f C r ea t e SDP r e c o r d f o r SPP s e r v i c e w i t h o f f i c i a l SPP
Service Class
∗ @param s e r v i c e b u f f e r − n ee d s t o l a r g e enough
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param rfcomm channel
∗ @param name or NULL f o r d e f a u l t v a l u e . P r o v i d e ”” ( empty s t r i n g )
to skip a t t r i b u t e
∗/
void s p p c r e a t e s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , int rfcomm channel , const char ∗name ) ;

/∗ ∗
∗ @ b r i e f C r ea t e SDP r e c o r d f o r SPP s e r v i c e w i t h custom s e r v i c e UUID
( e . g . f o r use w i t h Android )
∗ @param s e r v i c e b u f f e r − n ee d s t o l a r g e enough
∗ @param s e r v i c e r e c o r d h a n d l e
∗ @param s e r v i c e u u i d 1 2 8 b u f f e r
∗ @param rfcomm channel
∗ @param name
∗/
void s p p c r e a t e c u s t o m s d p r e c o r d ( uint8 t ∗ s e r v i c e , uint32 t
s e r v i c e r e c o r d h a n d l e , const uint8 t ∗ s e r v i c e u u i d 1 2 8 , int
rfcomm channel , const char ∗name ) ;

1.90. Genral Access Profile (GAP) API. gap.h

// C l a s s i c + LE

/∗ ∗
∗ @ b r i e f Read RSSI
∗ @param c o n h a n d l e
∗ @events : GAP EVENT RSSI MEASUREMENT
∗/
int g a p r e a d r s s i ( h c i c o n h a n d l e t c o n h a n d l e ) ;
484

/∗ ∗
∗ @ b r i e f Gets l o c a l a d d r e s s .
∗/
void g a p l o c a l b d a d d r ( bd addr t a d d r e s s b u f f e r ) ;

/∗ ∗
∗ @brief Disconnect connection with handle
∗ @param h a n d l e
∗ @return s t a t u s
∗/
uint8 t g a p d i s c o n n e c t ( h c i c o n h a n d l e t h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Get c o n n e c t i o n t y p e
∗ @param c o n h a n d l e
∗ @result connection type
∗/
gap connection type t gap get connection type ( hci con handle t
connection handle ) ;

/∗ ∗
∗ @ b r i e f Get HCI c o n n e c t i o n r o l e
∗ @param c o n h a n d l e
∗ @ r e s u l t h c i r o l e t HCI ROLE MASTER / HCI ROLE SLAVE /
HCI ROLE INVALID ( i f c o n n e c t i o n d o e s not e x i s t )
∗/
h c i r o l e t gap get role ( hci con handle t connection handle ) ;

// C l a s s i c

/∗ ∗
∗ @brief Request r o l e switch
∗ @note t h i s o n l y r e q u e s t s t h e r o l e s w i t c h . A HCI EVENT ROLE CHANGE
i s e m i t t e d and i t s s t a t u s f i e l d w i l l i n d i c a t e i f t h e s w i t c h
was s u c c e s f u l
∗ @param addr
∗ @param h c i r o l e t HCI ROLE MASTER / HCI ROLE SLAVE
∗ @result status
∗/
uint8 t g a p r e q u e s t r o l e ( const bd addr t addr , h c i r o l e t r o l e ) ;

/∗ ∗
∗ @ b r i e f S e t s l o c a l name .
∗ @note D e f a u l t name i s ’ BTstack 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ’
∗ @note ’ 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ’ i n l o c a l n a m e w i l l be r e p l a c e d w i t h
a c t u a l bd addr
∗ @param name i s not c o p i e d , make s u r e memory s t a y s v a l i d
∗/
void g a p s e t l o c a l n a m e ( const char ∗ l o c a l n a m e ) ;

/∗ ∗
∗ @ b r i e f S e t Extended I n q u i r y Response d a t a
∗ @note I f not s e t , l o c a l name w i l l be used f o r EIR d a t a ( s e e
gap set local name )
485

∗ @note ’ 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ’ i n l o c a l n a m e w i l l be r e p l a c e d w i t h
a c t u a l bd addr
∗ @param e i r d a t a s i z e HCI EXTENDED INQUIRY RESPONSE DATA LEN ( 2 4 0 )
b y t e s , i s not c o p i e d make s u r e memory s t a y s v a l i d
∗/
void g a p s e t e x t e n d e d i n q u i r y r e s p o n s e ( const uint8 t ∗ data ) ;

/∗ ∗
∗ @brief Set c l a s s of device
∗/
void g a p s e t c l a s s o f d e v i c e ( uint32 t c l a s s o f d e v i c e ) ;

/∗ ∗
∗ @ b r i e f S e t d e f a u l t l i n k p o l i c y s e t t i n g s f o r a l l c l a s s i c ACL l i n k s
∗ @param d e f a u l t l i n k p o l i c y s e t t i n g s − s e e LM LINK POLICY ∗ i n
bluetooth .h
∗ @note common v a l u e : LM LINK POLICY ENABLE ROLE SWITCH |
LM LINK POLICY ENABLE SNIFF MODE t o e n a b l e r o l e s w i t c h and
s n i f f mode
∗/
void g a p s e t d e f a u l t l i n k p o l i c y s e t t i n g s ( uint16 t
default link policy settings ) ;

/∗ ∗
∗ @brief S e t Allow Role S w i t c h param f o r o u t g o i n g c l a s s i c ACL l i n k s
∗ @param a l l o w r o l e s w i t c h − t r u e : a l l o w remote d e v i c e t o r e q u e s t
role s w i t c h , f a l s e : s t a y master
∗/
void g a p s e t a l l o w r o l e s w i t c h ( bool a l l o w r o l e s w i t c h ) ;

/∗ ∗
∗ @ b r i e f S e t l i n k s u p e r v i s i o n t i m e o u t f o r o u t g o i n g c l a s s i c ACL
links
∗ @param d e f a u l t l i n k s u p e r v i s i o n t i m e o u t ∗ 0 . 6 2 5 ms , d e f a u l t 0
x7d00 = 20 seconds , 0 = no l i n k s u p e r v i s i o n t i m e o u t
∗/
void g a p s e t l i n k s u p e r v i s i o n t i m e o u t ( uint16 t
link supervision timeout ) ;

/∗ ∗
∗ @ b r i e f Enable l i n k watchdog . I f no ACL p a c k e t i s s e n t w i t h i n
timeout ms , t h e l i n k w i l l g e t d i s c o n n e c t e d
∗ note : current implementation uses the automatic f l u s h timeout
c o n t r o l l e r f e a t u r e w i t h a max t i m e o u t o f 1 . 2 8 s
∗ @param t i m e o u t m s
∗/
void g a p e n a b l e l i n k w a t c h d o g ( uint16 t timeout ms ) ;

/∗ ∗
∗ @ b r i e f Enable / d i s a b l e b o n d i n g . D e f a u l t i s e n a b l e d .
∗ @param e n a b l e d
∗/
void g a p s e t b o n d a b l e m o d e ( int e n a b l e d ) ;
486

/∗ ∗
∗ @ b r i e f Get b o n d a b l e mode .
∗ @return 1 i f b o n d a b l e
∗/
int g a p g e t b o n d a b l e m o d e ( void ) ;

/∗ ∗
∗ @ b r i e f S e t s e c u r i t y mode f o r a l l o u t g o i n g and incoming
c o n n e c t i o n s . D e f a u l t : GAP SECURITY MODE 4
∗ @param s e c u r i t y m o d e i s GAP SECURITY MODE 2 or
GAP SECURITY MODE 4
∗ @return s t a t u s ERROR CODE SUCCESS or
ERROR CODE UNSUPPORTED FEATURE OR PARAMETER VALUE
∗/
uint8 t g a p s e t s e c u r i t y m o d e ( g a p s e c u r i t y m o d e t s e c u r i t y m o d e ) ;

/∗ ∗
∗ @ b r i e f Get s e c u r i t y mode
∗ @return s e c u r i t y m o d e
∗/
g a p s e c u r i t y m o d e t g a p g e t s e c u r i t y m o d e ( void ) ;

/∗ ∗
∗ @brief Set s e c u r i t y l e v e l for a l l o u t g o i n g and incoming
c o n n e c t i o n s . D e f a u l t : LEVEL 2
∗ @param s e c u r i t y l e v e l
∗ @note has t o be c a l l e d b e f o r e s e r v i c e s or p r o f i l e s a r e
initialized
∗/
void g a p s e t s e c u r i t y l e v e l ( g a p security level t security level ) ;

/∗ ∗
∗ @ b r i e f Get s e c u r i t y l e v e l
∗ @return s e c u r i t y l e v e l
∗/
g a p s e c u r i t y l e v e l t g a p g e t s e c u r i t y l e v e l ( void ) ;

/∗ ∗
∗ @ b r i e f S e t S e c u r e C o n n e c t i o n s Only Mode f o r BR/EDR ( C l a s s i c )
Default : f a l s e
∗ @param e n a b l e
∗/
void g a p s e t s e c u r e c o n n e c t i o n s o n l y m o d e ( b o o l e n a b l e ) ;

/∗ ∗
∗ @ b r e i f Get S e c u r e C o n n e c t i o n s Only Mode
∗ @param e n a b l e d
∗/
b o o l g a p g e t s e c u r e c o n n e c t i o n s o n l y m o d e ( void ) ;

/∗ ∗
∗ @ b r i e f S e t minimal s e c u r i t y l e v e l f o r r e g i s t e r e d s e r v i c e s
∗ @param s e c u r i t y l e v e l
∗ @note C a l l e d by L2CAP b a s e d on r e g i s t e r e d s e r v i c e s
487

∗/
void g a p s e t m i n i m a l s e r v i c e s e c u r i t y l e v e l ( g a p s e c u r i t y l e v e l t
security level ) ;

/∗ ∗
∗ @brief Register f i l t e r for r e j e c t i n g c l a s s i c connections .
C a l l b a c k w i l l r e t u r n 1 a c c e p t c o n n e c t i o n , 0 on r e j e c t .
∗/
void g a p r e g i s t e r c l a s s i c c o n n e c t i o n f i l t e r ( int ( ∗ a c c e p t c a l l b a c k ) (
bd addr t addr , h c i l i n k t y p e t l i n k t y p e ) ) ;

/∗ C o n f i g u r e S e c u r e Simple P a i r i n g ∗/

/∗ ∗
∗ @ b r i e f Enable w i l l e n a b l e SSP d u r i n g i n i t . D e f a u l t : t r u e
∗/
void g a p s s p s e t e n a b l e ( int e n a b l e ) ;

/∗ ∗
∗ @ b r i e f S e t IO C a p a b i l i t y . BTstack w i l l r e t u r n c a p a b i l i t y t o SSP
requests
∗/
void g a p s s p s e t i o c a p a b i l i t y ( int s s p i o c a p a b i l i t y ) ;

/∗ ∗
∗ @ b r i e f S e t A u t h e n t i c a t i o n Requirements u s i n g d u r i n g SSP
∗/
void g a p s s p s e t a u t h e n t i c a t i o n r e q u i r e m e n t ( int
authentication requirement ) ;

/∗ ∗
∗ @ b r i e f Enable / d i s a b l e S e c u r e C o n n e c t i o n s . D e f a u l t : t r u e i f
s u p p o r t e d by C o n t r o l l e r
∗/
void g a p s e c u r e c o n n e c t i o n s e n a b l e ( b o o l e n a b l e ) ;

/∗ ∗
∗ @ b r i e f Query i f S e c ur e C o n n e c t i o n s can be used f o r C l a s s i c
connections .
∗ @note R e q u i r e s g a p s e c u r e c o n n e c t i o n s e n a b l e == t r u e and
Controller to support i t
∗/
b o o l g a p s e c u r e c o n n e c t i o n s a c t i v e ( void ) ;

/∗ ∗
∗ @ b r i e f I f s e t , BTstack w i l l c o n f i r m a numeric comparison and
enter ’000000 ’ i f r e q u e s t e d .
∗/
void g a p s s p s e t a u t o a c c e p t ( int a u t o a c c e p t ) ;

/∗ ∗
∗ @ b r i e f S e t r e q u i r e d e n c r y p t i o n key s i z e f o r GAP L e v e l s 1−3 on
c l a s s i c connections .
488

∗ @note I f you need t o r e d u c e t h e r e q u i r e d e n c r y p t i o n key s i z e ,


please consider enabling
∗ ENABLE MUTUAL AUTHENTICATION FOR LEGACY SECURE CONNECTIONS
t o p r e v e n t BIAS a t t a c k s .
∗ However , t h e re−a u t h e n t i c a t i o n f o r Legacy S e c u r e
C o n n e c t i o n s can c a u s e a l i n k l o s s
∗ i n some C o n t r o l l e r c o m b i n a t i o n s .
∗ @param e n c r y p t i o n k e y s i z e i n b y t e s . V a l i d 7 . . 1 6 , d e f a u l t : 16
∗/
void g a p s e t r e q u i r e d e n c r y p t i o n k e y s i z e ( uint8 t
encryption key size ) ;

/∗ ∗
∗ @brief S t a r t d ed i ca t e d bonding with d e v i c e . Disconnect a f t e r
bonding .
∗ @param d e v i c e
∗ @param r e q u e s t MITM p r o t e c t i o n
∗ @return e r r o r , i f max num a c l c o n n e c t i o n s a c t i v e
∗ @ r e s u l t GAP DEDICATED BONDING COMPLETE
∗/
int g a p d e d i c a t e d b o n d i n g ( bd addr t d e v i c e , int
mitm protection required ) ;

gap security level t gap security level for link key type (
link key type t link key type ) ;

/∗ ∗
∗ @ b r i e f map l i n k k e y s t o s e c u r e c o n n e c t i o n y e s /no
∗/
bool g a p s e c u r e c o n n e c t i o n f o r l i n k k e y t y p e ( l i n k k e y t y p e t
link key type ) ;

/∗ ∗
∗ @ b r i e f map l i n k k e y s t o a u t h e n t i c a t e d
∗/
bool g a p a u t h e n t i c a t e d f o r l i n k k e y t y p e ( l i n k k e y t y p e t
link key type ) ;

g a p s e c u r i t y l e v e l t g a p s e c u r i t y l e v e l ( hci con handle t con handle )


;

void g a p r e q u e s t s e c u r i t y l e v e l ( h c i c o n h a n d l e t c o n h a n d l e ,
gap security level t level ) ;

bool g a p m i t m p r o t e c t i o n r e q u i r e d f o r s e c u r i t y l e v e l (
gap security level t level ) ;

/∗ ∗
∗ @ b r i e f S e t Page Scan Type
∗ @param p a g e s c a n i n t e r v a l ∗ 0 . 6 2 5 ms , range : 0 x0012 . . 0 x1000 ,
d e f a u l t : 0 x0800
∗ @param p a g e s c a n w i n d o w s ∗ 0 . 6 2 5 ms , range : 0 x0011 . .
p a g e s c a n i n t e r v a l , d e f a u l t : 0 x0012
∗/
489

void g a p s e t p a g e s c a n a c t i v i t y ( uint16 t p a g e s c a n i n t e r v a l ,
uint16 t page scan window ) ;

/∗ ∗
∗ @ b r i e f S e t Page Scan Type
∗ @param page scan mode
∗/
void g a p s e t p a g e s c a n t y p e ( p a g e s c a n t y p e t p a g e s c a n t y p e ) ;

/∗ ∗
∗ @ b r i e f S e t Page Timeout
∗ @param p a g e t i m e o u t ∗ 0 . 6 2 5 ms , range : 0 x0001 . . 0 x f f f f , d e f a u l t : 0
x6000 ( ca 15 s e c o n d s )
∗/
void g a p s e t p a g e t i m e o u t ( uint16 t p a g e t i m e o u t ) ;

// LE

/∗ ∗
∗ @ b r i e f S e t p a r a m e t e r s f o r LE Scan
∗ @param s c a n t y p e 0 = p a s s i v e , 1 = a c t i v e
∗ @param s c a n i n t e r v a l range 0 x0004 . . 0 x4000 , u n i t 0 . 6 2 5 ms
∗ @param scan window range 0 x0004 . . 0 x4000 , u n i t 0 . 6 2 5 ms
∗ @param s c a n n i n g f i l t e r p o l i c y 0 = a l l d e v i c e s , 1 = a l l from
whitelist
∗/
void g a p s e t s c a n p a r a m s ( uint8 t s c a n t y p e , uint16 t s c a n i n t e r v a l ,
uint16 t scan window , uint8 t s c a n n i n g f i l t e r p o l i c y ) ;

/∗ ∗
∗ @ b r i e f S e t p a r a m e t e r s f o r LE Scan
∗ @ de pr e ca te d Use g a p s e t s c a n p a r a m s i n s t e a d
∗/
void g a p s e t s c a n p a r a m e t e r s ( uint8 t s c a n t y p e , uint16 t
s c a n i n t e r v a l , uint16 t scan window ) ;

/∗ ∗
∗ @ b r i e f S e t d u p l i c a t e f i l t e r f o r LE Scan
∗ @param e n a b l e d i f e n a b l e d , o n l y one a d v e r t i s e m e n t s p e r BD ADDR i s
reported , d e f a u l t : f a l s e
∗/
void g a p s e t s c a n d u p l i c a t e f i l t e r ( b o o l e n a b l e d ) ;

/∗ ∗
∗ @ b r i e f S e t PHYs f o r LE Scan
∗ @param phy b i t m a s k : 1 = LE 1M PHY, 4 = LE Coded PHY
∗/
void g a p s e t s c a n p h y s ( uint8 t phys ) ;

/∗ ∗
∗ @ b r i e f S t a r t LE Scan
∗/
void g a p s t a r t s c a n ( void ) ;
490

/∗ ∗
∗ @ b r i e f Stop LE Scan
∗/
void g a p s t o p s c a n ( void ) ;

/∗ ∗
∗ @ b r i e f Enable p r i v a c y by u s i n g random a d d r e s s e s
∗ @param r a n d o m a d d r e s s t y p e t o use ( i n c l . OFF)
∗/
void g a p r a n d o m a d d r e s s s e t m o d e ( g a p r a n d o m a d d r e s s t y p e t
random address type ) ;

/∗ ∗
∗ @ b r i e f Get p r i v a c y mode
∗/
g a p r a n d o m a d d r e s s t y p e t g a p r a n d o m a d d r e s s g e t m o d e ( void ) ;

/∗ ∗
∗ @ b r i e f S e t s u p d a t e p e r i o d f o r random a d d r e s s
∗ @param p e r i o d m s i n ms
∗/
void g a p r a n d o m a d d r e s s s e t u p d a t e p e r i o d ( int p e r i o d m s ) ;

/∗ ∗
∗ @ b r i e f S e t s a f i x e d random a d d r e s s f o r a d v e r t i s i n g
∗ @param addr
∗ @note S e t s random a d d r e s s mode t o t y p e s t a t i c
∗/
void g a p r a n d o m a d d r e s s s e t ( const bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f S e t A d v e r t i s e m e n t Data
∗ @param a d v e r t i s i n g d a t a l e n g t h
∗ @param a d v e r t i s i n g d a t a (max 31 o c t e t s )
∗ @note d a t a i s not c o p i e d , p o i n t e r has t o s t a y v a l i d
∗ @note ’ 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ’ i n a d v e r t i s i n g d a t a w i l l be r e p l a c e d
w i t h a c t u a l bd addr
∗/
void g a p a d v e r t i s e m e n t s s e t d a t a ( uint8 t a d v e r t i s i n g d a t a l e n g t h ,
uint8 t ∗ a d v e r t i s i n g d a t a ) ;

/∗ ∗
∗ @ b r i e f S e t A d v e r t i s e m e n t Parameters
∗ @param a d v i n t m i n
∗ @param a d v i n t m a x
∗ @param a d v t y p e
∗ @param d i r e c t a d d r e s s t y p e
∗ @param d i r e c t a d d r e s s
∗ @param channel map
∗ @param f i l t e r p o l i c y
∗ @note o w n a d d r e s s t y p e i s used from g a p r a n d o m a d d r e s s s e t m o d e
∗/
void g a p a d v e r t i s e m e n t s s e t p a r a m s ( uint16 t a d v i n t m i n , uint16 t
adv int max , uint8 t adv type ,
491

uint8 t d i r e c t a d d r e s s t y p , bd addr t d i r e c t a d d r e s s , uint8 t


channel map , uint8 t f i l t e r p o l i c y ) ;

/∗ ∗
∗ @ b r i e f Enable / D i s a b l e A d v e r t i s e m e n t s . OFF by d e f a u l t .
∗ @param e n a b l e d
∗/
void g a p a d v e r t i s e m e n t s e n a b l e ( int e n a b l e d ) ;

/∗ ∗
∗ @ b r i e f S e t Scan Response Data

∗ @note For scan r e s p o n s e data , s c a n n a b l e u n d i r e c t e d a d v e r t i s i n g (
ADV SCAN IND) need t o be used

∗ @param a d v e r t i s i n g d a t a l e n g t h
∗ @param a d v e r t i s i n g d a t a (max 31 o c t e t s )
∗ @note d a t a i s not c o p i e d , p o i n t e r has t o s t a y v a l i d
∗ @note ’ 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ’ i n s c a n r e s p o n s e d a t a w i l l be r e p l a c e d
w i t h a c t u a l bd addr
∗/
void g a p s c a n r e s p o n s e s e t d a t a ( uint8 t s c a n r e s p o n s e d a t a l e n g t h ,
uint8 t ∗ s c a n r e s p o n s e d a t a ) ;

/∗ ∗
∗ @brief Set update i n t e r v a l f o r r e s o l v a b l e p r i v a t e addresses
g e n e r a t e d by t h e C o n t r o l l e r
∗ @param u p d a t e s t i m e o u t f o r u p d a t e s i n s e c o n d s
∗ @return s t a t u s
∗/
uint8 t
gap extended advertising set resolvable private address update (
uint16 t u p d a t e s ) ;

/∗ ∗
∗ @ b r i e f P r o v i d e s t o r a g e f o r new a d v e r t i s i n g s e t and s e t u p on
Controller
∗ @note Using RPA as o w n a d d r e s s t y p e r e q u i r e s
ENABLE LE ENHANCED CONNECTION COMPLETE EVENT i s r e q u i r e d f o r
pairing
∗ @param s t o r a g e t o use by s t a c k , n e ed s t o s t a y v a l i d u n t i l adv s e t
i s removed w i t h g a p e x t e n d e d a d v e r t i s i n g r e m o v e
∗ @param a d v e r t i s i n g p a r a m e t e r s
∗ @param o u t a d v e r t i s i n g h a n d l e t o use w i t h o t h e r adv c o n f i g
commands
∗ @return s t a t u s
∗ @events : GAP SUBEVENT ADVERTISING SET INSTALLED
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s e t u p ( l e a d v e r t i s i n g s e t t ∗
s t o r a g e , const l e e x t e n d e d a d v e r t i s i n g p a r a m e t e r s t ∗
a d v e r t i s i n g p a r a m e t e r s , uint8 t ∗ o u t a d v e r t i s i n g h a n d l e ) ;

/∗ ∗
492

∗ @param S e t a d v e r t i s i n g params f o r a d v e r t i s i n g s e t
∗ @note Using RPA as o w n a d d r e s s t y p e r e q u i r e s
ENABLE LE ENHANCED CONNECTION COMPLETE EVENT i s r e q u i r e d f o r
pairing
∗ @param a d v e r t i s i n g h a n d l e
∗ @param a d v e r t i s i n g p a r a m e t e r s
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s e t p a r a m s ( uint8 t
a d v e r t i s i n g h a n d l e , const l e e x t e n d e d a d v e r t i s i n g p a r a m e t e r s t ∗
advertising parameters ) ;

/∗ ∗
∗ @param Get a d v e r t i s i n g params f o r a d v e r t i s i n g s e t , e . g . t o u p d a t e
params
∗ @param a d v e r t i s i n g h a n d l e
∗ @param a d v e r t i s i n g p a r a m e t e r s
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g g e t p a r a m s ( uint8 t
advertising handle , le extended advertising parameters t ∗
advertising parameters ) ;

/∗ ∗
∗ @param S e t p e r i o d i c a d v e r t i s i n g params f o r a d v e r t i s i n g s e t
∗ @param a d v e r t i s i n g h a n d l e
∗ @param a d v e r t i s i n g p a r a m e t e r s
∗ @return s t a t u s
∗/
uint8 t g a p p e r i o d i c a d v e r t i s i n g s e t p a r a m s ( uint8 t
a d v e r t i s i n g h a n d l e , const l e p e r i o d i c a d v e r t i s i n g p a r a m e t e r s t ∗
advertising parameters ) ;

/∗ ∗
∗ @param Get params f o r p e r i o d i c a d v e r t i s i n g s e t , e . g . t o u p d a t e
params
∗ @param a d v e r t i s i n g h a n d l e
∗ @param a d v e r t i s i n g p a r a m e t e r s
∗ @return s t a t u s
∗/
uint8 t g a p p e r i o d i c a d v e r t i s i n g g e t p a r a m s ( uint8 t
advertising handle , le periodic advertising parameters t ∗
advertising parameters ) ;

/∗ ∗
∗ @param S e t random a d d r r e s s f o r a d v e r t i s i n g s e t
∗ @param a d v e r t i s i n g h a n d l e
∗ @param random address
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s e t r a n d o m a d d r e s s ( uint8 t
a d v e r t i s i n g h a n d l e , bd addr t random address ) ;

/∗ ∗
493

∗ @ b r i e f S e t A d v e r t i s i n g Data f o r a a d v e r t i s e m e n t s e t
∗ @param a d v e r t i s i n g h a n d l e
∗ @param a d v e r t i s i n g d a t a l e n g t h
∗ @param a d v e r t i s i n g d a t a
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s e t a d v d a t a ( uint8 t
a d v e r t i s i n g h a n d l e , uint16 t a d v e r t i s i n g d a t a l e n g t h , const
uint8 t ∗ a d v e r t i s i n g d a t a ) ;

/∗ ∗
∗ @ b r i e f S e t Scan Response Data f o r a a d v e r t i s e m e n t s e t
∗ @param a d v e r t i s i n g h a n d l e
∗ @param s c a n r e s p o n s e d a t a l e n g t h
∗ @param s c a n r e s p o n s e d a t a
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s e t s c a n r e s p o n s e d a t a ( uint8 t
a d v e r t i s i n g h a n d l e , uint16 t s c a n r e s p o n s e d a t a l e n g t h , const
uint8 t ∗ s c a n r e s p o n s e d a t a ) ;

/∗ ∗
∗ @brief Set data f o r p e r i o d i c advertisement s e t
∗ @param a d v e r t i s i n g h a n d l e
∗ @param p e r i o d i c d a t a l e n g t h
∗ @param p e r i o d i c d a t a
∗ @return s t a t u s
∗/
uint8 t g a p p e r i o d i c a d v e r t i s i n g s e t d a t a ( uint8 t a d v e r t i s i n g h a n d l e
, uint16 t p e r i o d i c d a t a l e n g t h , const uint8 t ∗ p e r i o d i c d a t a ) ;

/∗ ∗
∗ @brief Start advertising advertising set
∗ @param a d v e r t i s i n g h a n d l e
∗ @param t i m e o u t i n 10ms , or 0 == no t i m e o u t
∗ @param n u m e x t e n d e d a d v e r t i s i n g e v e n t s C o n t r o l l e r s h a l l send , or
0 == no max number
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s t a r t ( uint8 t a d v e r t i s i n g h a n d l e ,
uint16 t timeout , uint8 t n u m e x t e n d e d a d v e r t i s i n g e v e n t s ) ;

/∗ ∗
∗ @ b r i e f Stop a d v e r t i s i n g
∗ @param a d v e r t i s i n g h a n d l e
∗ @return s t a t u s
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g s t o p ( uint8 t a d v e r t i s i n g h a n d l e ) ;

/∗ ∗
∗ @brief Start periodic advertising for given advertising set
∗ @param a d v e r t i s i n g h a n d l e
∗ @param i n c l u d e a d i
∗ @return s t a t u s
494

∗/
uint8 t g a p p e r i o d i c a d v e r t i s i n g s t a r t ( uint8 t a d v e r t i s i n g h a n d l e ,
bool i n c l u d e a d i ) ;

/∗ ∗
∗ @ b r i e f Stop p e r i o d i c a d v e r t i s i n g f o r g i v e n a d v e r t i s i n g s e t
∗ @param a d v e r t i s i n g h a n d l e
∗ @return s t a t u s
∗/
uint8 t g a p p e r i o d i c a d v e r t i s i n g s t o p ( uint8 t a d v e r t i s i n g h a n d l e ) ;

/∗ ∗
∗ @ b r i e f S e t D e f a u l t P e r i o d i c A d v e r t i s i n g Sync T r a n s f e r Parameters
∗ @note The p a r a m e t e r s a r e used f o r a l l s u b s e q u e n t c o n n e c t i o n s o v e r
t h e LE t r a n s p o r t .
∗ I f mode != 0 , an
HCI LE Periodic Advertising Sync Transfer Received event w i l l
be e m i t t e d by t h e C o n t r o l l e r
∗ @param mode 0 = i g n o r e ( d e f a u l t ) , 1 = p e r i o d i c a d v e r t i s i n g e v e n t s
disabled
∗ 2 = periodic a d v e r t i s i n g events enabled with
duplicate f i l t e r i n g
∗ 3 = periodic a d v e r t i s i n g events enabled with
duplicate f i l t e r i n g
∗ @param s k i p The number o f p e r i o d i c a d v e r t i s i n g p a c k e t s t h a t can
be s k i p p e d a f t e r a s u c c e s s f u l r e c e i v e
∗ @param s y n c t i m e o u t Range : 0x000A t o 0 x4000 , Time = N∗10 ms , Time
Range : 100 ms t o 1 6 3 . 8 4 s
∗ @param c t e t y p e b i t 0 = Do not sync t o p a c k e t s w i t h an AoA
Constant Tone E x t e n s i o n
∗ b i t 1 = Do not sync t o p a c k e t s w i t h an AoD
Constant Tone E x t e n s i o n w i t h 1 s slots
∗ b i t 2 = Do not sync t o p a c k e t s w i t h an AoD
Constant Tone E x t e n s i o n w i t h 2 s slots
∗ b i t 3 = Do not sync t o p a c k e t s w i t h o u t a
Constant Tone E x t e n s i o n
∗ @return s t a t u s
∗/
uint8 t
gap periodic advertising sync transfer set default parameters (
uint8 t mode , uint16 t s k i p , uint16 t s y n c t i m e o u t , uint8 t
cte type ) ;

/∗ ∗
∗ @ b r i e f Send P e r i o d i c A d v e r t i s i n g Sync T r a n s f e r t o c o n n e c t e d
device
∗ @param c o n h a n d l e o f c o n n e c t e d d e v i c e
∗ @param s e r v i c e d a t a 16− b i t d a t a t o t r a n s f e r t o remote h o s t
∗ @param s y n c h a n d l e o f s y n c h r o n i z e d p e r i o d i c a d v e r t i s i n g t r a i n t o
transfer
∗ @return s t a t u s
∗/
495

uint8 t g a p p e r i o d i c a d v e r t i s i n g s y n c t r a n s f e r s e n d ( h c i c o n h a n d l e t
c o n h a n d l e , uint16 t s e r v i c e d a t a , h c i c o n h a n d l e t s y n c h a n d l e
);

/∗ ∗
∗ @ b r i e f Send P e r i o d i c A d v e r t i s i n g S e t I n f o T r a n s f e r t o c o n n e c t e d
device
∗ @param c o n h a n d l e o f c o n n e c t e d d e v i c e
∗ @param s e r v i c e d a t a 16− b i t d a t a t o t r a n s f e r t o remote h o s t
∗ @param a d v e r t i s i n g h a n d l e o f l o c a l p e r i o d i c a d v e r t i s i n g t r a i n t o
transfer
∗ @return s t a t u s
∗/
uint8 t g a p p e r i o d i c a d v e r t i s i n g s e t i n f o t r a n s f e r s e n d (
h c i c o n h a n d l e t c o n h a n d l e , uint16 t s e r v i c e d a t a , uint8 t
advertising handle ) ;

/∗ ∗
∗ @ b r i e f Remove a d v e r t i s i n g s e t from C o n t r o l l e r
∗ @param a d v e r t i s i n g h a n d l e
∗ @return s t a t u s
∗ @events GAP SUBEVENT ADVERTISING SET REMOVED
∗/
uint8 t g a p e x t e n d e d a d v e r t i s i n g r e m o v e ( uint8 t a d v e r t i s i n g h a n d l e ) ;

/∗ ∗
∗ @ b r i e f C r ea t e B r o a d c a s t I s o c h r o n o u s Group (BIG)
∗ @param s t o r a g e t o use by s t a c k , n e ed s t o s t a y v a l i d u n t i l adv s e t
i s removed w i t h g a p b i g t e r m i n a t e
∗ @param b i g p a r a m s
∗ @return s t a t u s
∗ @events GAP SUBEVENT BIG CREATED u n l e s s i n t e r r u p t e d by c a l l t o
gap big terminate
∗/
uint8 t g a p b i g c r e a t e ( l e a u d i o b i g t ∗ s t o r a g e ,
l e a u d i o b i g p a r a m s t ∗ big params ) ;

/∗ ∗
∗ @ b r i e f Terminate B r o a d c a s t I s o c h r o n o u s Group (BIG)
∗ @param b i g h a n d l e
∗ @return s t a t u s
∗ @events GAP SUBEVENT BIG TERMINATED
∗/
uint8 t g a p b i g t e r m i n a t e ( uint8 t b i g h a n d l e ) ;

/∗ ∗
∗ @ b r i e f S y n c h r o n i z e t o B r o a d c a s t I s o c h r o n o u s Group (BIG)
∗ @param s t o r a g e t o use by s t a c k , n e ed s t o s t a y v a l i d u n t i l adv s e t
i s removed w i t h g a p b i g t e r m i n a t e
∗ @param b i g s y n c p a r a m s
∗ @return s t a t u s
∗ @events GAP SUBEVENT BIG SYNC CREATED u n l e s s i n t e r r u p t e d by c a l l
to gap big sync terminate
∗/
496

uint8 t g a p b i g s y n c c r e a t e ( l e a u d i o b i g s y n c t ∗ s t o r a g e ,
le audio big sync params t ∗ big sync params ) ;

/∗ ∗
∗ @ b r i e f Stop s y n c h r o n i z i n g t o B r o a d c a s t I s o c h r o n o u s Group (BIG) .
T r i g g e r s GAP SUBEVENT BIG SYNC STOPPED
∗ @note Also used t o s t o p s y n c h r o n i z i n g b e f o r e BIG Sync was
established
∗ @param b i g h a n d l e
∗ @return s t a t u s
∗ @events GAP SUBEVENT BIG SYNC STOPPED
∗/
uint8 t g a p b i g s y n c t e r m i n a t e ( uint8 t b i g h a n d l e ) ;

/∗ ∗
∗ @ b r i e f C r ea t e Connected I s o c h r o n o u s Group (CIG)
∗ @param s t o r a g e t o use by s t a c k , n e ed s t o s t a y v a l i d u n t i l CIG
removed w i t h g a p c i g r e m o v e
∗ @param c i g p a r a m s
∗ @return s t a t u s
∗ @events GAP SUBEVENT CIG CREATED u n l e s s i n t e r r u p t e d by c a l l t o
gap cig remove
∗/
uint8 t g a p c i g c r e a t e ( l e a u d i o c i g t ∗ s t o r a g e ,
l e a u d i o c i g p a r a m s t ∗ cig params ) ;

/∗ ∗
∗ @ b r i e f Remove Connected I s o c h r o n o u s Group (CIG)
∗ @param c i g i d
∗ @return s t a t u s
∗ @events GAP SUBEVENT CIG TERMINATED
∗/
uint8 t g a p c i g r e m o v e ( uint8 t c i g i d ) ;

/∗ ∗
∗ @ b r i e f C r ea t e Connected I s o c h r o n o u s Streams ( CIS )
∗ @note number o f CIS from c i g p a r a m s i n g a p c i g c r e a t e i s used
∗ @param c i g i d
∗ @param c i s c o n h a n d l e s a r r a y o f CIS Connection Handles
∗ @param a c l c o n h a n d l e s a r r a y o f ACL Connection Handles
∗ @return s t a t u s
∗ @events GAP SUBEVENT CIS CREATED u n l e s s i n t e r r u p t e d by c a l l t o
gap cig remove
∗/
uint8 t g a p c i s c r e a t e ( uint8 t c i g i d , h c i c o n h a n d l e t
cis con handles [ ] , hci con handle t acl con handles [ ] ) ;

/∗ ∗
∗ @ b r i e f Accept Connected I s o c h r o n o u s Stream ( CIS )
∗ @param c i s c o n h a n d l e
∗ @return s t a t u s
∗ @events GAP SUBEVENT CIS CREATED
∗/
uint8 t g a p c i s a c c e p t ( h c i c o n h a n d l e t c i s c o n h a n d l e ) ;
497

/∗ ∗
∗ @ b r i e f R e j e c t Connected I s o c h r o n o u s Stream ( CIS )
∗ @param c i s c o n h a n d l e
∗ @return s t a t u s
∗ @events GAP SUBEVENT CIS CREATED
∗/
uint8 t g a p c i s r e j e c t ( h c i c o n h a n d l e t c i s c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f S e t c o n n e c t i o n p a r a m e t e r s f o r o u t g o i n g c o n n e c t i o n s and
c o n n e c t i o n parameter u p d a t e s
∗ @param c o n n s c a n i n t e r v a l ( u n i t : 0 . 6 2 5 msec ) , d e f a u l t : 60 ms
∗ @param conn scan window ( u n i t : 0 . 6 2 5 msec ) , d e f a u l t : 30 ms
∗ @param c o n n i n t e r v a l m i n ( u n i t : 1 . 2 5 ms) , d e f a u l t : 10 ms
∗ @param c o n n i n t e r v a l m a x ( u n i t : 1 . 2 5 ms) , d e f a u l t : 30 ms
∗ @param c o n n l a t e n c y , d e f a u l t : 4
∗ @param s u p e r v i s i o n t i m e o u t ( u n i t : 10ms) , d e f a u l t : 720 ms
∗ @param m i n c e l e n g t h ( u n i t : 0 . 6 2 5ms) , d e f a u l t : 10 ms
∗ @param m a x c e l e n g t h ( u n i t : 0 . 6 2 5ms) , d e f a u l t : 30 ms
∗/
void g a p s e t c o n n e c t i o n p a r a m e t e r s ( uint16 t c o n n s c a n i n t e r v a l ,
uint16 t conn scan window ,
uint16 t c o n n i n t e r v a l m i n , uint16 t c o n n i n t e r v a l m a x , uint16 t
conn latency ,
uint16 t s u p e r v i s i o n t i m e o u t , uint16 t m i n c e l e n g t h , uint16 t
max ce length ) ;

/∗ ∗
∗ @ b r i e f S e t i n i t i a t i n g PHYs f o r o u t g o i n g c o n n e c t i o n s
∗ @param phy b i t m a s k : 1 = LE 1M PHY, 2 = LE 2M PHY, 4 = LE Coded
PHY
∗/
void g a p s e t c o n n e c t i o n p h y s ( uint8 t phys ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t an u p d a t e o f t h e c o n n e c t i o n parameter f o r a g i v e n
LE c o n n e c t i o n
∗ @param h a n d l e
∗ @param c o n n i n t e r v a l m i n ( u n i t : 1 . 2 5 ms)
∗ @param c o n n i n t e r v a l m a x ( u n i t : 1 . 2 5 ms)
∗ @param c o n n l a t e n c y
∗ @param s u p e r v i s i o n t i m e o u t ( u n i t : 10ms)
∗ @return 0 i f ok
∗/
int g a p r e q u e s t c o n n e c t i o n p a r a m e t e r u p d a t e ( h c i c o n h a n d l e t
c o n h a n d l e , uint16 t c o n n i n t e r v a l m i n ,
uint16 t c o n n i n t e r v a l m a x , uint16 t c o n n l a t e n c y , uint16 t
supervision timeout ) ;

/∗ ∗
∗ @ b r i e f Updates t h e c o n n e c t i o n p a r a m e t e r s f o r a g i v e n LE
connection
∗ @param h a n d l e
498

∗ @param c o n n i n t e r v a l m i n ( u n i t : 1 . 2 5 ms)
∗ @param c o n n i n t e r v a l m a x ( u n i t : 1 . 2 5 ms)
∗ @param c o n n l a t e n c y
∗ @param s u p e r v i s i o n t i m e o u t ( u n i t : 10ms)
∗ @return 0 i f ok
∗/
int g a p u p d a t e c o n n e c t i o n p a r a m e t e r s ( h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t c o n n i n t e r v a l m i n ,
uint16 t c o n n i n t e r v a l m a x , uint16 t c o n n l a t e n c y , uint16 t
supervision timeout ) ;

/∗ ∗
∗ @ b r i e f S e t a c c e p t e d c o n n e c t i o n parameter range
∗ @param range
∗/
void g a p g e t c o n n e c t i o n p a r a m e t e r r a n g e (
l e c o n n e c t i o n p a r a m e t e r r a n g e t ∗ range ) ;

/∗ ∗
∗ @ b r i e f Get a c c e p t e d c o n n e c t i o n parameter range
∗ @param range
∗/
void g a p s e t c o n n e c t i o n p a r a m e t e r r a n g e (
l e c o n n e c t i o n p a r a m e t e r r a n g e t ∗ range ) ;

/∗ ∗
∗ @ b r i e f Test i f c o n n e c t i o n p a r a m e t e r s a r e i n s i d e i n e x i s t i n g r a g e
∗ @param c o n n i n t e r v a l m i n ( u n i t : 1 . 2 5 ms)
∗ @param c o n n i n t e r v a l m a x ( u n i t : 1 . 2 5 ms)
∗ @param c o n n l a t e n c y
∗ @param s u p e r v i s i o n t i m e o u t ( u n i t : 10ms)
∗ @return 1 i f i n c l u d e d
∗/
int g a p c o n n e c t i o n p a r a m e t e r r a n g e i n c l u d e d (
l e c o n n e c t i o n p a r a m e t e r r a n g e t ∗ e x i s t i n g r a n g e , uint16 t
l e c o n n i n t e r v a l m i n , uint16 t l e c o n n i n t e r v a l m a x , uint16 t
l e c o n n l a t e n c y , uint16 t l e s u p e r v i s i o n t i m e o u t ) ;

/∗ ∗
∗ @ b r i e f S e t max number o f c o n n e c t i o n s i n LE P e r i p h e r a l r o l e ( i f
Bluetooth Controller supports i t )
∗ @note : d e f a u l t : 1
∗ @param m a x p e r i p h e r a l c o n n e c t i o n s
∗/
void g a p s e t m a x n u m b e r p e r i p h e r a l c o n n e c t i o n s ( int
max peripheral connections ) ;

/∗ ∗
∗ @ b r i e f Add D e vi c e t o W h i t e l i s t
∗ @param a d d r e s s t y p
∗ @param a d d r e s s
∗ @return s t a t u s
∗/
499

uint8 t g a p w h i t e l i s t a d d ( b d a d d r t y p e t a d d r e s s t y p e , const
bd addr t a d d r e s s ) ;

/∗ ∗
∗ @ b r i e f Remove D e v ic e from W h i t e l i s t
∗ @param a d d r e s s t y p
∗ @param a d d r e s s
∗ @return s t a t u s
∗/
uint8 t g a p w h i t e l i s t r e m o v e ( b d a d d r t y p e t a d d r e s s t y p e , const
bd addr t a d d r e s s ) ;

/∗ ∗
∗ @brief Clear W h i t e l i s t
∗ @return s t a t u s
∗/
uint8 t g a p w h i t e l i s t c l e a r ( void ) ;

/∗ ∗
∗ @ b r i e f Connect t o remote LE d e v i c e
∗ @return s t a t u s
∗/
uint8 t g a p c o n n e c t ( const bd addr t addr , b d a d d r t y p e t a d d r t y p e ) ;

/∗ ∗
∗ @ b r i e f Connect w i t h W h i t e l i s t
∗ @note E x p l i c i t w h i t e l i s t management and t h i s c o n n e c t w i t h
w h i t e l i s t replace deprecated gap auto connection ∗ functions
∗ @return s t a t u s
∗/
uint8 t g a p c o n n e c t w i t h w h i t e l i s t ( void ) ;

/∗ ∗
∗ @ b r i e f Cancel c o n n e c t i o n p r o c e s s i n i t i a t e d by g a p c o n n e c t
∗ @return s t a t u s
∗/
uint8 t g a p c o n n e c t c a n c e l ( void ) ;

/∗ ∗
∗ @ b r i e f Auto Connection E s t a b l i s h m e n t − S t a r t Connecting t o d e v i c e
∗ @ de pr e ca te d P l e a s e s e t u p W h i t e l i s t w i t h g a p w h i t e l i s t ∗ and s t a r t
connecting with g a p c o n n e c t w i t h w h i t e l i s t
∗ @param a d d r e s s t y p e
∗ @param a d d r e s s
∗ @return s t a t u s
∗/
uint8 t g a p a u t o c o n n e c t i o n s t a r t ( b d a d d r t y p e t a d d r e s s t y p e , const
bd addr t a d d r e s s ) ;

/∗ ∗
∗ @ b r i e f Auto Connection E s t a b l i s h m e n t − Stop Connecting t o d e v i c e
∗ @ de pr e ca te d P l e a s e s e t u p W h i t e l i s t w i t h g a p w h i t e l i s t ∗ and s t a r t
connecting with g a p c o n n e c t w i t h w h i t e l i s t
∗ @param a d d r e s s t y p e
500

∗ @param a d d r e s s
∗ @return s t a t u s
∗/
uint8 t g a p a u t o c o n n e c t i o n s t o p ( b d a d d r t y p e t a d d r e s s t y p e , const
bd addr t a d d r e s s ) ;

/∗ ∗
∗ @ b r i e f Auto Connection E s t a b l i s h m e n t − Stop e v e r y t h i n g
∗ @ de pr e ca te d P l e a s e s e t u p W h i t e l i s t w i t h g a p w h i t e l i s t ∗ and s t a r t
connecting with g a p c o n n e c t w i t h w h i t e l i s t
∗ @note Convenience f u n c t i o n t o s t o p a l l a c t i v e a u t o c o n n e c t i o n
attempts
∗ @return s t a t u s
∗/
uint8 t g a p a u t o c o n n e c t i o n s t o p a l l ( void ) ;

/∗ ∗
∗ @ b r i e f S e t LE PHY
∗ @param c o n h a n d l e
∗ @param a l l p h y s 0 = s e t r x / t x , 1 = s e t o n l y rx , 2 = s e t o n l y t x
∗ @param t x p h y s 1 = 1M, 2 = 2M, 4 = Coded
∗ @param r x p h y s 1 = 1M, 2 = 2M, 4 = Coded
∗ @param p h y o p t i o n s 0 = no p r e f e r r e d c o d i n g f o r Coded , 1 = S=2
c o d i n g (500 k b i t ) , 2 = S=8 c o d i n g (125 k b i t )
∗ @return s t a t u s
∗/
uint8 t g a p l e s e t p h y ( h c i c o n h a n d l e t c o n h a n d l e , uint8 t a l l p h y s
, uint8 t tx phys , uint8 t rx phys , uint16 t p h y o p t i o n s ) ;

/∗ ∗
∗ @ b r i e f Get c o n n e c t i o n i n t e r v a l
∗ @param c o n h a n d l e
∗ @return c o n n e c t i o n i n t e r v a l , o t h e r w i s e 0 i f e r r o r
∗/
uint16 t g a p l e c o n n e c t i o n i n t e r v a l ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗

∗ @ b r i e f Get e n c r y p t i o n key s i z e .
∗ @param c o n h a n d l e
∗ @return 0 i f not e n c r y p t e d , 7−16 o t h e r w i s e
∗/
uint8 t g a p e n c r y p t i o n k e y s i z e ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Get a u t h e n t i c a t i o n p r o p e r t y .
∗ @param c o n h a n d l e
∗ @return t r u e i f bonded w i t h OOB/ Passkey (AND MITM p r o t e c t i o n )
∗/
bool gap authenticated ( hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f Get s e c u r e c o n n e c t i o n p r o p e r t y
∗ @param c o n h a n d l e
501

∗ @return t r u e i f bonded u s i u n g LE S e c u r e C o n n e c t i o n s
∗/
bool gap secure connection ( hci con handle t con handle ) ;

/∗ ∗
∗ @brief Queries a u t h o r i z a t i o n s t a t e .
∗ @param c o n h a n d l e
∗ @return a u t h o r i z a t i o n s t a t e f o r t h e c u r r e n t s e s s i o n
∗/
authorization state t gap authorization state ( hci con handle t
con handle ) ;

/∗ ∗
∗ @ b r i e f Get bonded p r o p e r t y (BR/EDR/LE)
∗ @note LE : has t o be c a l l e d a f t e r i d e n t i t y r e s o l v i n g i s c o m p l e t e
∗ @param c o n h a n d l e
∗ @return t r u e i f bonded
∗/
b o o l gap bonded ( h c i c o n h a n d l e t c o n h a n d l e ) ;

// C l a s s i c
#i f d e f ENABLE CLASSIC

/∗ ∗
∗ @ b r i e f O v e r r i d e page scan mode . Page scan mode e n a b l e d by l 2 c a p
when s e r v i c e s a r e r e g i s t e r e d
∗ @note Might be used t o r e d u c e power consumption w h i l e B l u e t o o t h
module s t a y s powered b u t no ( new )
∗ connections are expected
∗/
void g a p c o n n e c t a b l e c o n t r o l ( uint8 t e n a b l e ) ;

/∗ ∗
∗ @ b r i e f A l l o w s t o c o n t r o l i f d e v i c e i s d i s c o v e r a b l e . OFF by
default .
∗/
void g a p d i s c o v e r a b l e c o n t r o l ( uint8 t e n a b l e ) ;

/∗ ∗
∗ @ b r i e f D e l e t e s l i n k key f o r remote d e v i c e w i t h b a s e b a n d a d d r e s s .
∗ @param addr
∗ @note On most d e s k t o p p o r t s , t h e Link Key DB u s e s a TLV and t h e r e
i s one TLV s t o r a g e p e r
∗ C o n t r o l l e r r e s p . i t s B l u e t o o t h Address . As t h e B l u e t o o t h
Address i s r e t r i e v e d d u r i n g
∗ power up , t h i s f u n c t i o n o n l y works , when t h e s t a c k i s i n
working s t a t e f o r t h e s e p o r t s .
∗/
void g a p d r o p l i n k k e y f o r b d a d d r ( bd addr t addr ) ;

/∗ ∗
∗ @brief Delete a l l stored l i n k keys
∗ @note On most d e s k t o p p o r t s , t h e Link Key DB u s e s a TLV and t h e r e
i s one TLV s t o r a g e p e r
502

∗ C o n t r o l l e r r e s p . i t s B l u e t o o t h Address . As t h e B l u e t o o t h
Address i s r e t r i e v e d d u r i n g
∗ power up , t h i s f u n c t i o n o n l y works , when t h e s t a c k i s i n
working s t a t e f o r t h e s e p o r t s .
∗/
void g a p d e l e t e a l l l i n k k e y s ( void ) ;

/∗ ∗
∗ @ b r i e f S t o r e l i n k key f o r remote d e v i c e w i t h b a s e b a n d a d d r e s s
∗ @param addr
∗ @param l i n k k e y
∗ @param l i n k k e y t y p e
∗ @note On most d e s k t o p p o r t s , t h e Link Key DB u s e s a TLV and t h e r e
i s one TLV s t o r a g e p e r
∗ C o n t r o l l e r r e s p . i t s B l u e t o o t h Address . As t h e B l u e t o o t h
Address i s r e t r i e v e d d u r i n g
∗ power up , t h i s f u n c t i o n o n l y works , when t h e s t a c k i s i n
working s t a t e f o r t h e s e p o r t s .
∗/
void g a p s t o r e l i n k k e y f o r b d a d d r ( bd addr t addr , l i n k k e y t
l i n k k e y , l i n k k e y t y p e t type ) ;

/∗ ∗
∗ @ b r i e f Get l i n k f o r remote d e v i c e w i t h basband a d d r e s s
∗ @param addr
∗ @param l i n k k e y ( o u t ) i s s t o r e d h e r e
∗ @param l i n k k e y t y p e ( o u t ) i s s t o r e d h e r e
∗ @note On most d e s k t o p p o r t s , t h e Link Key DB u s e s a TLV and t h e r e
i s one TLV s t o r a g e p e r
∗ C o n t r o l l e r r e s p . i t s B l u e t o o t h Address . As t h e B l u e t o o t h
Address i s r e t r i e v e d d u r i n g
∗ power up , t h i s f u n c t i o n o n l y works , when t h e s t a c k i s i n
working s t a t e f o r t h e s e p o r t s .
∗/
b o o l g a p g e t l i n k k e y f o r b d a d d r ( bd addr t addr , l i n k k e y t
l i n k k e y , l i n k k e y t y p e t ∗ type ) ;

/∗ ∗
∗ @ b r i e f S e tu p Link Key i t e r a t o r
∗ @param i t
∗ @return 1 on s u c c e s s
∗ @note On most d e s k t o p p o r t s , t h e Link Key DB u s e s a TLV and t h e r e
i s one TLV s t o r a g e p e r
∗ C o n t r o l l e r r e s p . i t s B l u e t o o t h Address . As t h e B l u e t o o t h
Address i s r e t r i e v e d d u r i n g
∗ power up , t h i s f u n c t i o n o n l y works , when t h e s t a c k i s i n
working s t a t e f o r t h e s e p o r t s .
∗/
int g a p l i n k k e y i t e r a t o r i n i t ( b t s t a c k l i n k k e y i t e r a t o r t ∗ i t ) ;

/∗ ∗
∗ @ b r i e f Get n e x t Link Key
∗ @param i t
∗ @ b r i e f addr
503

∗ @brief link key


∗ @ b r i e f t y p e o f l i n k key
∗ @return 1 , i f v a l i d l i n k key found
∗ @see n o t e on g a p l i n k k e y i t e r a t o r i n i t
∗/
int g a p l i n k k e y i t e r a t o r g e t n e x t ( b t s t a c k l i n k k e y i t e r a t o r t ∗ i t ,
bd addr t bd addr , l i n k k e y t l i n k k e y , l i n k k e y t y p e t ∗ type )
;

/∗ ∗
∗ @ b r i e f F re es r e s o u r c e s a l l o c a t e d by i t e r a t o r i n i t
∗ @note Must be c a l l e d a f t e r i t e r a t i o n t o f r e e r e s o u r c e s
∗ @param i t
∗ @see n o t e on g a p l i n k k e y i t e r a t o r i n i t
∗/
void g a p l i n k k e y i t e r a t o r d o n e ( b t s t a c k l i n k k e y i t e r a t o r t ∗ i t ) ;

/∗ ∗
∗ @ b r i e f S t a r t GAP C l a s s i c I n q u i r y
∗ @param d u r a t i o n i n 1 . 2 8 s u n i t s
∗ @return s t a t u s
∗ @events : GAP EVENT INQUIRY RESULT, GAP EVENT INQUIRY COMPLETE
∗/
int g a p i n q u i r y s t a r t ( uint8 t d u r a t i o n i n 1 2 8 0 m s u n i t s ) ;

/∗ ∗
∗ @ b r i e f S t a r t GAP C l a s s i c P e r i o d i c I n q u i r y
∗ @param d u r a t i o n i n 1 . 2 8 s u n i t s
∗ @param m a x p e r i o d l e n g t h b e t w e e n c o n s e c u t i v e i n q u i r i e s i n 1 . 2 8 s
units
∗ @param m i n p e r i o d l e n g t h b e t w e e n c o n s e c u t i v e i n q u i r i e s i n 1 . 2 8 s
units
∗ @return s t a t u s
∗ @events : GAP EVENT INQUIRY RESULT, GAP EVENT INQUIRY COMPLETE
∗/
uint8 t g a p i n q u i r y p e r i o d i c s t a r t ( uint8 t d u r a t i o n , uint16 t
m a x p e r i o d l e n g t h , uint16 t m i n p e r i o d l e n g t h ) ;

/∗ ∗
∗ @ b r i e f Stop GAP C l a s s i c I n q u i r y ( r e g u l a r or p e r i o d i c )
∗ @return 0 i f ok
∗ @events GAP EVENT INQUIRY COMPLETE
∗/
int g a p i n q u i r y s t o p ( void ) ;

/∗ ∗
∗ @ b r i e f S e t LAP f o r GAP C l a s s i c I n q u i r y
∗ @param l a p GAP IAC GENERAL INQUIRY ( d e f a u l t ) ,
GAP IAC LIMITED INQUIRY
∗/
void g a p i n q u i r y s e t l a p ( uint32 t l a p ) ;

/∗ ∗
∗ @ b r i e f S e t I n q u i r y Scan A c t i v i t y
504

∗ @param i n q u i r y s c a n i n t e r v a l range : 0 x0012 t o 0 x1000 ; o n l y even


v a l u e s a r e v a l i d , Time = N ∗ 0 . 6 2 5 ms
∗ @param i n q u i r y s c a n w i n d o w range : 0 x0011 t o 0 x1000 ; Time = N ∗
0 . 6 2 5 ms
∗/
void g a p i n q u i r y s e t s c a n a c t i v i t y ( uint16 t i n q u i r y s c a n i n t e r v a l ,
uint16 t i n q u i r y s c a n w i n d o w ) ;

/∗ ∗
∗ @ b r i e f S e t I n q u i r y Transmit Power L e v e l
∗ @param t x p o w e r range : −70 t o 20 dBm
∗/
void g a p i n q u i r y s e t t r a n s m i t p o w e r l e v e l ( i n t 8 t t x p o w e r ) ;

/∗ ∗
∗ @ b r i e f Remote Name R e q u e s t
∗ @param addr
∗ @param p a g e s c a n r e p e t i t i o n m o d e
∗ @param c l o c k o f f s e t o n l y used when b i t 15 i s s e t − p a s s 0 i f not
known
∗ @events HCI EVENT REMOTE NAME REQUEST COMPLETE
∗/
int g a p r e m o t e n a m e r e q u e s t ( const bd addr t addr , uint8 t
p a g e s c a n r e p e t i t i o n m o d e , uint16 t c l o c k o f f s e t ) ;

/∗ ∗
∗ @ b r i e f Legacy P a i r i n g Pin Code Response
∗ @note d a t a i s not c o p i e d , p o i n t e r has t o s t a y v a l i d
∗ @param addr
∗ @param p i n
∗ @return 0 i f ok
∗/
int g a p p i n c o d e r e s p o n s e ( const bd addr t addr , const char ∗ p i n ) ;

/∗ ∗
∗ @ b r i e f Legacy P a i r i n g Pin Code Response f o r b i n a r y d a t a / non−
strings
∗ @note d a t a i s not c o p i e d , p o i n t e r has t o s t a y v a l i d
∗ @param addr
∗ @param p i n d a t a
∗ @param p i n l e n
∗ @return 0 i f ok
∗/
int g a p p i n c o d e r e s p o n s e b i n a r y ( const bd addr t addr , const uint8 t
∗ p i n d a t a , uint8 t p i n l e n ) ;

/∗ ∗
∗ @ b r i e f Abort Legacy P a i r i n g
∗ @param addr
∗ @param p i n
∗ @return 0 i f ok
∗/
int g a p p i n c o d e n e g a t i v e ( bd addr t addr ) ;
505

/∗ ∗
∗ @ b r i e f SSP Passkey Response
∗ @param addr
∗ @param p a s s k e y [ 0 . . 9 9 9 9 9 9 ]
∗ @return 0 i f ok
∗/
int g a p s s p p a s s k e y r e s p o n s e ( const bd addr t addr , uint32 t p a s s k e y )
;

/∗ ∗
∗ @ b r i e f Abort SSP Passkey Entry / P a i r i n g
∗ @param addr
∗ @param p i n
∗ @return 0 i f ok
∗/
int g a p s s p p a s s k e y n e g a t i v e ( const bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f Accept SSP Numeric Comparison
∗ @param addr
∗ @param p a s s k e y
∗ @return 0 i f ok
∗/
int g a p s s p c o n f i r m a t i o n r e s p o n s e ( const bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f Abort SSP Numeric Comparison / P a i r i n g
∗ @param addr
∗ @param p i n
∗ @return 0 i f ok
∗/
int g a p s s p c o n f i r m a t i o n n e g a t i v e ( const bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f Generate new OOB d a t a
∗ @note OOB d a t a w i l l be p r o v i d e d i n GAP EVENT LOCAL OOB DATA and
be used i n f u t u r e p a i r i n g p r o c e d u r e s
∗/
void g a p s s p g e n e r a t e o o b d a t a ( void ) ;

/∗ ∗
∗ @ b r i e f Report Remote OOB Data
∗ @note P a i r i n g Hash and Randomizer a r e e x p e c t e d i n b i g −endian b y t e
format
∗ @param b d a d d r
∗ @param c 1 9 2 Simple P a i r i n g Hash C d e r i v e d from P−192 p u b l i c key
∗ @param r 1 9 2 Simple P a i r i n g Randomizer d e r i v e d from P−192 p u b l i c
key
∗ @param c 2 5 6 Simple P a i r i n g Hash C d e r i v e d from P−256 p u b l i c key
∗ @param r 2 5 6 Simple P a i r i n g Randomizer d e r i v e d from P−256 p u b l i c
key
∗ @return s t a t u s
∗/
506

uint8 t g a p s s p r e m o t e o o b d a t a ( const bd addr t addr , const uint8 t


∗ c 19 2 , const uint8 t ∗ r 1 9 2 , const uint8 t ∗ c 25 6 , const
uint8 t ∗ r 2 5 6 ) ;

/∗ ∗
∗ Send SSP IO C a p a b i l i t i e s Reply
∗ @note IO C a p a b i l i t i e s ( N e g a t i v e ) Reply i s s e n t a u t o m a t i c a l l y
u n l e s s ENABLE EXPLICIT IO CAPABILITIES REPLY
∗ @param addr
∗ @return s t a t u s
∗/
uint8 t g a p s s p i o c a p a b i l i t i e s r e s p o n s e ( const bd addr t addr ) ;

/∗ ∗
∗ Send SSP IO C a p a b i l i t i e s N e g a t i v e Reply
∗ @note IO C a p a b i l i t i e s ( N e g a t i v e ) Reply i s s e n t a u t o m a t i c a l l y
u n l e s s ENABLE EXPLICIT IO CAPABILITIES REPLY
∗ @param addr
∗ @return s t a t u s
∗/
uint8 t g a p s s p i o c a p a b i l i t i e s n e g a t i v e ( const bd addr t addr ) ;

/∗ ∗
∗ Send Link Key Reponse
∗ @note Link Key ( N e g a t i v e ) Reply i s s e n t a u t o m a t i c a l l y u n l e s s
ENABLE EXPLICIT LINK KEY RESPONSE
∗ @param addr
∗ @param l i n k k e y
∗ @param t y p e or INVALID LINK KEY i f l i n k key not a v a i l a b l e
∗ @return s t a t u s
∗/
uint8 t g a p s e n d l i n k k e y r e s p o n s e ( const bd addr t addr , l i n k k e y t
l i n k k e y , l i n k k e y t y p e t type ) ;

/∗ ∗
∗ @ b r i e f Enter S n i f f mode
∗ @param c o n h a n d l e
∗ @param s n i f f m i n i n t e r v a l range : 0 x0002 t o 0xFFFE ; o n l y even
v a l u e s a r e v a l i d , Time = N ∗ 0 . 6 2 5 ms
∗ @param s n i f f m a x i n t e r v a l range : 0 x0002 t o 0xFFFE ; o n l y even
v a l u e s a r e v a l i d , Time = N ∗ 0 . 6 2 5 ms
∗ @param s n i f f a t t e m p t Number o f Baseband r e c e i v e s l o t s f o r s n i f f
attempt .
∗ @param s n i f f t i m e o u t Number o f Baseband r e c e i v e s l o t s f o r s n i f f
timeout .
∗ @return s t a t u s
∗/
uint8 t g a p s n i f f m o d e e n t e r ( h c i c o n h a n d l e t c o n h a n d l e , uint16 t
s n i f f m i n i n t e r v a l , uint16 t s n i f f m a x i n t e r v a l , uint16 t
s n i f f a t t e m p t , uint16 t s n i f f t i m e o u t ) ;

/∗ ∗
∗ @ b r i e f E x i t S n i f f mode
∗ @param c o n h a n d l e
507

∗ @return s t a t u s
∗/
uint8 t g a p s n i f f m o d e e x i t ( h c i c o n h a n d l e t c o n h a n d l e ) ;

/∗ ∗
∗ @brief Configure S n i f f Subrating
∗ @param c o n h a n d l e
∗ @param m a x l a t e n c y range : 0 x0002 t o 0xFFFE ; Time = N ∗ 0 . 6 2 5 ms
∗ @param m i n r e m o t e t i m e o u t range : 0 x0002 t o 0xFFFE ; Time = N ∗
0 . 6 2 5 ms
∗ @param m i n l o c a l t i m e o u t range : 0 x0002 t o 0xFFFE ; Time = N ∗
0 . 6 2 5 ms
∗ @return s t a t u s
∗/
uint8 t g a p s n i f f s u b r a t i n g c o n f i g u r e ( h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t max latency , uint16 t m i n r e m o t e t i m e o u t , uint16 t
min local timeout ) ;

/∗ ∗
∗ @Brief S e t QoS
∗ @param c o n h a n d l e
∗ @param s e r v i c e t y p e
∗ @param t o k e n r a t e
∗ @param p e a k b a n d w i d t h
∗ @param l a t e n c y
∗ @param d e l a y v a r i a t i o n
∗ @return s t a t u s
∗/
uint8 t g a p q o s s e t ( h c i c o n h a n d l e t c o n h a n d l e , h c i s e r v i c e t y p e t
s e r v i c e t y p e , uint32 t t o k e n r a t e , uint32 t peak bandwidth ,
uint32 t l a t e n c y , uint32 t d e l a y v a r i a t i o n ) ;

#endif

// LE

/∗ ∗
∗ @ b r i e f Get own addr t y p e and a d d r e s s used f o r LE f o r n e x t scan /
advertisement / connect operation
∗/
void g a p l e g e t o w n a d d r e s s ( uint8 t ∗ a d d r t y p e , bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f Get own addr t y p e and a d d r e s s used f o r LE a d v e r t i s e m e n t s (
Peripheral )
∗/
void g a p l e g e t o w n a d v e r t i s e m e n t s a d d r e s s ( uint8 t ∗ a d d r t y p e ,
bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f Get own addr t y p e and a d d r e s s used f o r LE Extended
Advertisiing ( Peripheral )
∗/
508

void g a p l e g e t o w n a d v e r t i s i n g s e t a d d r e s s ( uint8 t ∗ a d d r t y p e ,
bd addr t addr , uint8 t a d v e r t i s i n g h a n d l e ) ;

/∗ ∗
∗ @ b r i e f Get own addr t y p e and a d d r e s s used f o r LE c o n n e c t i o n s (
Central )
∗/
void g a p l e g e t o w n c o n n e c t i o n a d d r e s s ( uint8 t ∗ a d d r t y p e ,
bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f Get s t a t e o f c o n n e c t i o n re−e n c r y p t i o n f o r bonded d e v i c e s
when i n c e n t r a l r o l e
∗ @note used by g a t t c l i e n t and a t t s e r v e r t o w a i t f o r re−
encryption
∗ @param c o n h a n d l e
∗ @return 1 i f s e c u r i t y s e t u p i s a c t i v e
∗/
bool g a p r e c o n n e c t s e c u r i t y s e t u p a c t i v e ( hci con handle t con handle
);

/∗ ∗
∗ @ b r i e f D e l e t e b o n d i n g i n f o r m a t i o n f o r remote d e v i c e
∗ @note On most d e s k t o p p o r t s , t h e LE D ev i c e DB u s e s a TLV and
t h e r e i s one TLV s t o r a g e p e r
∗ C o n t r o l l e r r e s p . i t s B l u e t o o t h Address . As t h e B l u e t o o t h
Address i s r e t r i e v e d d u r i n g
∗ power up , t h i s f u n c t i o n o n l y works , when t h e s t a c k i s i n
working s t a t e f o r t h e s e p o r t s .
∗ @param a d d r e s s t y p e
∗ @param a d d r e s s
∗/
void g a p d e l e t e b o n d i n g ( b d a d d r t y p e t a d d r e s s t y p e , bd addr t
address ) ;

/∗ ∗
∗ LE P r i v a c y 1 . 2 − r e q u i r e s s u p p o r t by C o n t r o l l e r and
ENABLE LE RESOLVING LIST t o be d e f i n e d
∗/

/∗ ∗
∗ S e t P r i v a c y Mode f o r use i n R e s o l v i n g L i s t . D e f a u l t :
LE PRIVACY MODE DEVICE
∗ @note Only a p p l i e s f o r new d e v i c e s added t o r e s o l v i n g l i s t ,
please c a l l before startup
∗ @param p r i v a c y m o d e
∗/
void g a p s e t p e e r p r i v a c y m o d e ( l e p r i v a c y m o d e t privacy mode ) ;

/∗ ∗
∗ @ b r i e f Load LE De v i ce DB e n t r i e s i n t o C o n t r o l l e r R e s o l v i n g L i s t
t o a l l o w f i l t e r i n g on
∗ bonded d e v i e s w i t h r e s o l v a b l e p r i v a t e a d d r e s s e s
∗ @return EROOR CODE SUCCESS i f s u p p o r t e d by C o n t r o l l e r
509

∗/
uint8 t g a p l o a d r e s o l v i n g l i s t f r o m l e d e v i c e d b ( void ) ;

typedef enum {
GAP PRIVACY CLIENT STATE IDLE ,
GAP PRIVACY CLIENT STATE PENDING,
GAP PRIVACY CLIENT STATE READY
} gap privacy client state t ;

struct g a p p r i v a c y c l i e n t {
b t s t a c k l i n k e d i t e m t ∗ next ;
void ( ∗ c a l l b a c k ) ( struct g a p p r i v a c y c l i e n t ∗ c l i e n t , bd addr t
random addr ) ;
gap privacy client state t state ;
};
typedef struct g a p p r i v a c y c l i e n t g a p p r i v a c y c l i e n t t ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k t h a t g e t s e x e c u t e d d u r i n g random a d d r e s s
update
∗ @note g a p p r i v a c y c l i e n t r e a d y n ee d s t o be c a l l e d a f t e r c a l l b a c k
is received
∗ @param c l i e n t
∗ @return s t a t u s
∗/
void g a p p r i v a c y c l i e n t r e g i s t e r ( g a p p r i v a c y c l i e n t t ∗ c l i e n t ) ;

/∗ ∗
∗ @ b r i e f Acknowledge upcoming random a d d r e s s change
∗ @param c l i e n t
∗ @return s t a t u s
∗/
void g a p p r i v a c y c l i e n t r e a d y ( g a p p r i v a c y c l i e n t t ∗ c l i e n t ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r c a l l b a c k from random a d d r e s s u p d a t e s
∗ @param c l i e n t
∗ @return s t a t u s
∗/
void g a p p r i v a c y c l i e n t u n r e g i s t e r ( g a p p r i v a c y c l i e n t t ∗ c l i e n t ) ;

/∗ ∗
∗ @ b r i e f Get l o c a l p e r s i s t e n t IRK
∗/
const uint8 t ∗ g a p g e t p e r s i s t e n t i r k ( void ) ;

1.91. Host Controler Interface (HCI) API. hci.h

// HCI i n i t and c o n f i g u r a t i o n

/∗ ∗
510

∗ @ b r i e f S e t up HCI . Needs t o be c a l l e d b e f o r e any o t h e r f u n c t i o n .


∗/
void h c i i n i t ( const hci transport t ∗ t r a n s p o r t , const void ∗ c o n f i g ) ;

/∗ ∗
∗ @ b r i e f C o n f i g u r e B l u e t o o t h c h i p s e t d r i v e r . Has t o be c a l l e d
b e f o r e power on , or r i g h t a f t e r r e c e i v i n g t h e l o c a l v e r s i o n
information .
∗/
void h c i s e t c h i p s e t ( const b t s t a c k c h i p s e t t ∗ c h i p s e t d r i v e r ) ;

/∗ ∗
∗ @ b r i e f Enable custom i n i t f o r c h i p s e t d r i v e r t o send HCI commands
b e f o r e HCI R e s e t
∗/
void h c i e n a b l e c u s t o m p r e i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f C o n f i g u r e B l u e t o o t h hardware c o n t r o l . Has t o be c a l l e d
b e f o r e power on .
∗ @[ aram h a r d w a r e c o n t r o l i m p l e m e n t a t i o n
∗/
void h c i s e t c o n t r o l ( const btstack control t ∗ h a r d w a r e c o n t r o l ) ;

#i f d e f HAVE SCO TRANSPORT


/∗ ∗
∗ @ b r i e f S e t SCO T r a n s p o r t i m p l e m e n t a t i o n f o r SCO o v e r PCM mode
∗ @param s c o t r a n s p o r t t h a t s e n d s SCO o v e r I2S or PCM i n t e r f a c e
∗/
void h c i s e t s c o t r a n s p o r t ( const b t s t a c k s c o t r a n s p o r t t ∗
sco transport ) ;
#endif

#i f d e f ENABLE CLASSIC
/∗ ∗
∗ @ b r i e f C o n f i g u r e B l u e t o o t h hardware c o n t r o l . Has t o be c a l l e d
b e f o r e power on .
∗/
void h c i s e t l i n k k e y d b ( btstack link key db t const ∗ l i n k k e y d b ) ;
#endif

/∗ ∗
∗ @ b r i e f S e t c a l l b a c k f o r B l u e t o o t h Hardware Error
∗/
void h c i s e t h a r d w a r e e r r o r c a l l b a c k ( void ( ∗ f n ) ( uint8 t e r r o r ) ) ;

/∗ ∗
∗ @ b r i e f S e t P u b l i c BD ADDR − p a s s e d on t o B l u e t o o t h c h i p s e t d u r i n g
i n i t i f supported in b t c o n t r o l h
∗/
void h c i s e t b d a d d r ( bd addr t addr ) ;

/∗ ∗
∗ @ b r i e f C o n f i g u r e Voice S e t t i n g f o r use w i t h SCO d a t a i n HSP/HFP
511

∗/
void h c i s e t s c o v o i c e s e t t i n g ( uint16 t v o i c e s e t t i n g ) ;

/∗ ∗
∗ @ b r i e f Get SCO Voice S e t t i n g
∗ @return c u r r e n t v o i c e s e t t i n g
∗/
uint16 t h c i g e t s c o v o i c e s e t t i n g ( void ) ;

/∗ ∗
∗ @ b r i e f S e t number o f ISO p a c k e t s t o b u f f e r f o r BIS/CIS
∗ @param num packets ( d e f a u l t = 1)
∗/
void h c i s e t n u m i s o p a c k e t s t o q u e u e ( uint8 t num packets ) ;

/∗ ∗
∗ @ b r i e f S e t i n q u i r y mode : s t a n d a r d , w i t h RSSI , w i t h RSSI +
Extended I n q u i r y R e s u l t s . Has t o be c a l l e d b e f o r e power on .
∗ @param i n q u r i y m o d e s e e b l u e t o o t h d e f i n e s . h
∗/
void h c i s e t i n q u i r y m o d e ( i n q u i r y m o d e t i n q u r i y m o d e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t s t h e change o f BTstack power mode .
∗ @param power mode
∗ @return 0 i f s u c c e s s , o t h e r w i s e e r r o r
∗/
int h c i p o w e r c o n t r o l (HCI POWER MODE power mode ) ;

/∗ ∗
∗ @ b r i e f Shutdown HCI
∗/
void h c i c l o s e ( void ) ;

// C a l l b a c k r e g i s t r a t i o n

/∗ ∗
∗ @ b r i e f Add e v e n t p a c k e t h a n d l e r .
∗/
void h c i a d d e v e n t h a n d l e r ( b t s t a c k p a c k e t c a l l b a c k r e g i s t r a t i o n t ∗
callback handler ) ;

/∗ ∗
∗ @ b r i e f Remove e v e n t p a c k e t h a n d l e r .
∗/
void h c i r e m o v e e v e n t h a n d l e r ( b t s t a c k p a c k e t c a l l b a c k r e g i s t r a t i o n t
∗ callback handler ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s a p a c k e t h a n d l e r f o r ACL d a t a . Used by L2CAP
∗/
512

void h c i r e g i s t e r a c l p a c k e t h a n d l e r ( btstack packet handler t


handler ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s a p a c k e t h a n d l e r f o r SCO d a t a . Used f o r HSP and
HFP p r o f i l e s .
∗/
void h c i r e g i s t e r s c o p a c k e t h a n d l e r ( btstack packet handler t
handler ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s a p a c k e t h a n d l e r f o r ISO d a t a . Used f o r LE Audio
profiles
∗/
void h c i r e g i s t e r i s o p a c k e t h a n d l e r ( btstack packet handler t
handler ) ;

// Sending HCI Commands

/∗ ∗
∗ @ b r i e f Check i f CMD p a c k e t can be s e n t t o c o n t r o l l e r
∗ @return t r u e i f command can be s e n t
∗/
b o o l h c i c a n s e n d c o m m a n d p a c k e t n o w ( void ) ;

/∗ ∗
∗ @ b r i e f C r e a t e s and s e n d s HCI command p a c k e t s b a s e d on a t e m p l a t e
and a l i s t o f p a r a m e t e r s . W i l l r e t u r n e r r o r i f o u t g o i n g d a t a
b u f f e r i s occupied .
∗ @return s t a t u s
∗/
uint8 t h c i s e n d c m d ( const hci cmd t ∗ cmd , . . . ) ;

// Sending SCO P a c k e t s

/∗ ∗ @ b r i e f Get SCO p a y l o a d l e n g t h f o r e x i s t i n g SCO c o n n e c t i o n and


c u r r e n t SCO Voice s e t t i n g
∗ @note Using SCO p a c k e t s o f t h e e x a c t l e n g t h i s r e q u i r e d f o r USB
t r a n s f e r i n g e n e r a l and some H4 c o n t r o l l e r s as w e l l
∗ @param s c o c o n h a n d l e
∗ @return Length o f SCO p a y l o a d i n b y t e s ( not a u d i o frames ) i n c l .
3 byte header
∗/
uint16 t h c i g e t s c o p a c k e t l e n g t h f o r c o n n e c t i o n ( h c i c o n h a n d l e t
sco con handle ) ;

/∗ ∗ @ b r i e f Get SCO p a c k e t l e n g t h f o r one o f t h e e x i s t i n g SCO


c o n n e c t i o n s and c u r r e n t SCO Voice s e t t i n g
∗ @ de pr e ca te d P l e a s e use h c i g e t s c o p a c k e t l e n g t h f o r c o n n e c t i o n
instead
∗ @note Using SCO p a c k e t s o f t h e e x a c t l e n g t h i s r e q u i r e d f o r USB
transfer
513

∗ @return Length o f SCO p a c k e t s i n b y t e s ( not a u d i o frames ) i n c l .


3 byte header
∗/
uint16 t h c i g e t s c o p a c k e t l e n g t h ( void ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f HCI EVENT SCO CAN SEND NOW as soon as
possible
∗ @note HCI EVENT SCO CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o
this function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗/
void h c i r e q u e s t s c o c a n s e n d n o w e v e n t ( void ) ;

/∗ ∗
∗ @ b r i e f Check HCI p a c k e t b u f f e r and i f SCO p a c k e t can be s e n t t o
controller
∗ @return t r u e i f s c o p a c k e t can be s e n t
∗/
b o o l h c i c a n s e n d s c o p a c k e t n o w ( void ) ;

/∗ ∗
∗ @ b r i e f Check i f SCO p a c k e t can be s e n t t o c o n t r o l l e r
∗ @return t r u e i f s c o p a c k e t can be s e n t
∗/
b o o l h c i c a n s e n d p r e p a r e d s c o p a c k e t n o w ( void ) ;

/∗ ∗
∗ @ b r i e f Send SCO p a c k e t p r e p a r e d i n HCI p a c k e t b u f f e r
∗/
uint8 t h c i s e n d s c o p a c k e t b u f f e r ( int s i z e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f HCI EVENT BIS CAN SEND NOW f o r a l l BIS
as soon as p o s s i b l e
∗ @param b i g h a n d l e
∗ @note HCI EVENT ISO CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o
this function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗/
uint8 t h c i r e q u e s t b i s c a n s e n d n o w e v e n t s ( uint8 t b i g h a n d l e ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f HCI EVENT CIS CAN SEND NOW f o r CIS as
soon as p o s s i b l e
∗ @param c i s c o n h a n d l e
∗ @note HCI EVENT CIS CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o
this function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗/
uint8 t h c i r e q u e s t c i s c a n s e n d n o w e v e n t s ( h c i c o n h a n d l e t
cis con handle ) ;

/∗ ∗
514

∗ @ b r i e f Send ISO p a c k e t p r e p a r e d i n HCI p a c k e t b u f f e r


∗/
uint8 t h c i s e n d i s o p a c k e t b u f f e r ( uint16 t s i z e ) ;

/∗ ∗
∗ Reserves outgoing packet b u f f e r .
∗ @note Must o n l y be c a l l e d a f t e r a ’ can send now ’ c h e c k or e v e n t
∗ @note A s s e r t s i f p a c k e t b u f f e r i s a l r e a d y r e s e r v e d
∗/
void h c i r e s e r v e p a c k e t b u f f e r ( void ) ;

/∗ ∗
∗ Get p o i n t e r f o r o u t g o i n g p a c k e t b u f f e r
∗/
uint8 t ∗ h c i g e t o u t g o i n g p a c k e t b u f f e r ( void ) ;

/∗ ∗
∗ Release outgoing packet b u f f e r \
∗ @note o n l y c a l l e d i n s t e a d o f h c i s e n d p r e p a r e d
∗/
void h c i r e l e a s e p a c k e t b u f f e r ( void ) ;

/∗ ∗
∗ @ b r i e f S e t s t h e master / s l a v e p o l i c y
∗ @param p o l i c y ( 0 : a t t e m p t t o become master , 1 : l e t c o n n e c t i n g
device decide )
∗/
void h c i s e t m a s t e r s l a v e p o l i c y ( uint8 t p o l i c y ) ;

/∗ ∗
∗ @ b r i e f Check i f C o n t r o l l e r s u p p o r t s BR/EDR ( B l u e t o o t h C l a s s i c )
∗ @return t r u e i f s u p p o r t e d
∗ @note o n l y v a l i d i n w o r k i n g s t a t e
∗/
b o o l h c i c l a s s i c s u p p o r t e d ( void ) ;

/∗ ∗
∗ @ b r i e f Check i f C o n t r o l l e r s u p p o r t s LE ( B l u e t o o t h Low Energy )
∗ @return t r u e i f s u p p o r t e d
∗ @note o n l y v a l i d i n w o r k i n g s t a t e
∗/
b o o l h c i l e s u p p o r t e d ( void ) ;

/∗ ∗
∗ @ b r i e f Check i f LE Extended A d v e r t i s i n g i s s u p p o r t e d
∗ @return t r u e i f s u p p o r t e d
∗/
b o o l h c i l e e x t e n d e d a d v e r t i s i n g s u p p o r t e d ( void ) ;

/∗ ∗ @ b r i e f Check i f a d d r e s s t y p e c o r r e s p o n d s t o LE c o n n e c t i o n
∗ @bparam a d d r e s s t y p e
∗ @erturn t r u e i f LE c o n n e c t i o n
∗/
bool h c i i s l e c o n n e c t i o n t y p e ( bd addr type t address type ) ;
515

/∗ ∗ @ b r i e f Check i f a d d r e s s t y p e c o r r e s p o n d s t o I d e n t i t y Address
∗ @bparam a d d r e s s t y p e
∗ @erturn t r u e i f LE c o n n e c t i o n
∗/
bool h c i i s l e i d e n t i t y a d d r e s s t y p e ( bd addr type t address type ) ;

1.92. HCI Logging API. hci dump.h : Dump HCI trace as BlueZ’s hcidump
format, Apple’s PacketLogger, or stdout.

typedef enum {
HCI DUMP INVALID = 0 ,
HCI DUMP BLUEZ,
HCI DUMP PACKETLOGGER,
HCI DUMP BTSNOOP,
} hci dump format t ;

typedef struct {
// r e s e t o u t p u t , c a l l e d i f max p a c k e t s i s reached , t o l i m i t f i l e
size
void ( ∗ r e s e t ) ( void ) ;
// l o g p a c k e t
void ( ∗ l o g p a c k e t ) ( uint8 t p a c k e t t y p e , uint8 t in , uint8 t ∗
packet , uint16 t l e n ) ;
// l o g message
void ( ∗ l o g m e s s a g e ) ( int l o g l e v e l , const char ∗ format , v a l i s t
argptr ) ;
#i f d e f AVR \
// l o g message − AVR
void ( ∗ l o g m e s s a g e P ) ( int l o g l e v e l , PGM P ∗ format , v a l i s t
argptr ) ;
#endif
} hci dump t ;

/∗ ∗
∗ @ b r i e f I n i t HCI Dump
∗ @param h c i d u m p i m p l − p l a t f o r m −s p e c i f i c i m p l e m e n t a t i o n
∗/
void h c i d u m p i n i t ( const h c i d u m p t ∗ hci dump impl ) ;

/∗ ∗
∗ @ b r i e f Enable p a c k e t l o g g i n g
∗ @param e n a b l e d d e f a u l t : t r u e
∗/
void h c i d u m p e n a b l e p a c k e t l o g ( b o o l e n a b l e d ) ;

/∗ ∗
∗ @brief
∗/
void h c i d u m p e n a b l e l o g l e v e l ( int l o g l e v e l , int e n a b l e ) ;

/∗
516

∗ @ b r i e f S e t max number o f p a c k e t s − o u t p u t f i l e might be t r u n c a t e d


∗/
void h c i d u m p s e t m a x p a c k e t s ( int p a c k e t s ) ; // −1 f o r u n l i m i t e d

/∗ ∗
∗ @ b r i e f Dump P a ck e t
∗ @param p a c k e t t y p e
∗ @param i n i s 1 f o r incoming , 0 f o r o u t o i n g
∗ @param p a c k e t
∗ @param l e n
∗/
void h c i d u m p p a c k e t ( uint8 t p a c k e t t y p e , uint8 t in , uint8 t ∗
packet , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f Dump Message
∗ @param l o g l e v e l
∗ @param f o r m at
∗/
void h c i d u m p l o g ( int l o g l e v e l , const char ∗ format , . . . )
#i f d e f GNUC
attribute ( ( format ( p r i n t f , 2 , 3) ) )
#endif
;

#i f d e f AVR
/∗
∗ @ b r i e f Dump Message u s i n g f o r m a t s t r i n g s t o r e d i n PGM memory (
a l l o w s t o s a v e RAM)
∗ @param l o g l e v e l
∗ @param f o r m at
∗/
void h c i d u m p l o g P ( int l o g l e v e l , PGM P format , . . . )
#i f d e f GNUC
attribute ( ( format ( p r i n t f , 2 , 3) ) )
#endif
;
#endif

/∗ ∗
∗ @ b r i e f Dump i n t e r n a l BTstack e v e n t
∗ @note o n l y l o g g e d i f ENABLE LOG BTSTACK EVENTS i s d e f i n e d
∗ @param p a c k e t
∗ @param l e n
∗/
void h c i d u m p b t s t a c k e v e n t ( const uint8 t ∗ packet , uint16 t l e n ) ;

/∗ ∗
∗ @brief S e tu p h e a d e r f o r P a c k e t L o g g e r f o rm a t
∗ @param buffer
∗ @param tv sec
∗ @param tv us
∗ @param packet type
∗ @param in
517

∗ @param l e n
∗/
void h c i d u m p s e t u p h e a d e r p a c k e t l o g g e r ( uint8 t ∗ b u f f e r , uint32 t
t v s e c , uint32 t t v u s , uint8 t p a c k e t t y p e , uint8 t in ,
uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f S e tu p h e a d e r f o r BLUEZ ( hcidump ) f o r m a t
∗ @param b u f f e r
∗ @param t v s e c
∗ @param t v u s
∗ @param p a c k e t t y p e
∗ @param i n
∗ @param l e n
∗/
void h c i d u m p s e t u p h e a d e r b l u e z ( uint8 t ∗ b u f f e r , uint32 t t v s e c ,
uint32 t t v u s , uint8 t p a c k e t t y p e , uint8 t in , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f S e tu p h e a d e r f o r BT Snoop f o r m a t
∗ @param b u f f e r
∗ @param t s u s e c h i g h upper 32− b i t o f 64− b i t microsecond timestamp
∗ @param t s u s e c l o w l o w e r 2− b i t o f 64− b i t microsecond timestamp
∗ @param c u m u l a t i v e d r o p s s i n c e l a s t p a c k e t was r e c o r d e d
∗ @param p a c k e t t y p e
∗ @param i n
∗ @param l e n
∗/
void h c i d u m p s e t u p h e a d e r b t s n o o p ( uint8 t ∗ b u f f e r , uint32 t
t s u s e c h i g h , uint32 t t s u s e c l o w , uint32 t c u m u l a t i v e d r o p s ,
uint8 t p a c k e t t y p e , uint8 t in , uint16 t l e n ) ;

1.93. HCI Transport API. hci transport.h : The API allows BTstack to
use different transport interfaces.

/∗ HCI p a c k e t t y p e s ∗/
typedef struct {
/∗ ∗
∗ t r a n s p o r t name
∗/
const char ∗ name ;

/∗ ∗
∗ init transport
∗ @param t r a n s p o r t c o n f i g
∗/
void ( ∗ i n i t ) ( const void ∗ t r a n s p o r t c o n f i g ) ;

/∗ ∗
∗ open t r a n s p o r t c o n n e c t i o n
∗/
int ( ∗ open ) ( void ) ;
518

/∗ ∗
∗ c l o s e transport connection
∗/
int ( ∗ c l o s e ) ( void ) ;

/∗ ∗
∗ r e g i s t e r p a c k e t h a n d l e r f o r HCI p a c k e t s : ACL, SCO, and Ev e n ts
∗/
void ( ∗ r e g i s t e r p a c k e t h a n d l e r ) ( void ( ∗ h a n d l e r ) ( uint8 t
p a c k e t t y p e , uint8 t ∗ packet , uint16 t s i z e ) ) ;

/∗ ∗
∗ s u p p o r t async t r a n s p o r t l a y e r s , e . g . IRQ d r i v e n w i t h o u t
buffers
∗/
int ( ∗ c a n s e n d p a c k e t n o w ) ( uint8 t p a c k e t t y p e ) ;

/∗ ∗
∗ send p a c k e t
∗/
int ( ∗ s e n d p a c k e t ) ( uint8 t p a c k e t t y p e , uint8 t ∗ packet , int
size ) ;

/∗ ∗
∗ e x t e n s i o n f o r UART t r a n s p o r t i m p l e m e n t a t i o n s
∗/
int ( ∗ s e t b a u d r a t e ) ( uint32 t b a u d r a t e ) ;

/∗ ∗
∗ e x t e n s i o n f o r UART H5 on CSR: r e s e t BCSP/H5 Link
∗/
void ( ∗ r e s e t l i n k ) ( void ) ;

/∗ ∗
∗ e x t e n s i o n f o r USB t r a n s p o r t i m p l e m e n t a t i o n s : c o n f i g SCO
connections
∗/
void ( ∗ s e t s c o c o n f i g ) ( uint16 t v o i c e s e t t i n g , int
num connections ) ;

} hci transport t ;

typedef enum {
HCI TRANSPORT CONFIG UART,
HCI TRANSPORT CONFIG USB
} hci transport config type t ;

typedef struct {
h c i t r a n s p o r t c o n f i g t y p e t type ;
} hci transport config t ;

typedef struct {
519

h c i t r a n s p o r t c o n f i g t y p e t type ; // ==
HCI TRANSPORT CONFIG UART
uint32 t b a u d r a t e i n i t ; // i n i t i a l baud r a t e
uint32 t baudrate main ; // = 0 : same as i n i t i a l b a u d r a t e
int flowcontrol ; //
const char ∗ d e v i c e n a m e ;
int parity ; // s e e b t s t a c k u a r t . h
BTSTACK UART PARITY
} hci transport config uart t ;

1.94. HCI Transport EM9304 API API. hci transport em9304 spi.h :
The EM9304 uses an extended SPI interface and this HCI Transport is based on
the the btstack em9304.h interface.

/∗
∗ @ b r i e f S e tu p H4 o v e r SPI i n s t a n c e f o r EM9304 w i t h
em9304 spi driver
∗ @param e m 9 3 0 4 s p i d r i v e r t o use
∗/
const hci transport t ∗ h c i t r a n s p o r t e m 9 3 0 4 s p i i n s t a n c e ( const
btstack em9304 spi t ∗ em9304 spi driver ) ;

1.95. HCI Transport H4 API. hci transport h4.h

/∗
∗ @ b r i e f S e tu p H4 i n s t a n c e w i t h b t s t a c k u a r t i m p l e m e n t a t i o n
∗ @param b t s t a c k u a r t b l o c k d r i v e r t o use
∗/
const hci transport t ∗ h c i t r a n s p o r t h 4 i n s t a n c e f o r u a r t ( const
btstack uart t ∗ uart driver ) ;

/∗
∗ @ b r i e f S e tu p H4 i n s t a n c e w i t h b t s t a c k u a r t b l o c k i m p l e m e n t a t i o n
∗ @param b t s t a c k u a r t b l o c k d r i v e r t o use
∗ @ de pr e ca te d use h c i t r a n s p o r t h 4 i n s t a n c e f o r u a r t i n s t e a d
∗/
const hci transport t ∗ h c i t r a n s p o r t h 4 i n s t a n c e ( const
btstack uart block t ∗ uart driver ) ;

1.96. HCI Transport H5 API. hci transport h5.h

/∗
∗ @ b r i e f S e tu p H5 i n s t a n c e w i t h b t s t a c k u a r t i m p l e m e n t a t i o n t h a t
s u p p o r t s SLIP frames
∗ @param u a r t d r i v e r t o use
∗/
520

const hci transport t ∗ h c i t r a n s p o r t h 5 i n s t a n c e ( const


btstack uart t ∗ uart driver ) ;

/∗
∗ @ b r i e f Enable H5 Low Power Mode : e n t e r s l e e p mode a f t e r x ms o f
inactivity
∗ @param i n a c t i v i t y t i m e o u t m s or 0 f o r o f f
∗/
void h c i t r a n s p o r t h 5 s e t a u t o s l e e p ( uint16 t i n a c t i v i t y t i m e o u t m s )
;

/∗
∗ @ b r i e f Enable BSCP mode H5 , by e n a b l i n g e v e n t p a r i t y
∗ @ de pr e ca te d P a r i t y can be e n a b l e d i n UART d r i v e r c o n f i g u r a t i o n
∗/
void h c i t r a n s p o r t h 5 e n a b l e b c s p m o d e ( void ) ;

1.97. HCI Transport USB API. hci transport usb.h

/∗
∗ @brief
∗/
const hci transport t ∗ h c i t r a n s p o r t u s b i n s t a n c e ( void ) ;

/∗ ∗
∗ @ b r i e f S p e c i f y USB B l u e t o o t h d e v i c e v i a p o r t numbers from r o o t t o
device
∗/
void h c i t r a n s p o r t u s b s e t p a t h ( int l e n , uint8 t ∗ port numbers ) ;

/∗ ∗
∗ @ b r i e f Add d e v i c e t o l i s t o f known B l u e t o o t h USB C o n t r o l l e r
∗ @param v e n d o r i d
∗ @param p r o d u c t i d
∗/
void h c i t r a n s p o r t u s b a d d d e v i c e ( uint16 t v e n d o r i d , uint16 t
product id ) ;

1.98. L2CAP API. l2cap.h : Logical Link Control and Adaption Protocol

//
// PSM numbers from h t t p s : / /www. b l u e t o o t h . com/ s p e c i f i c a t i o n s /
a s s i g n e d −numbers / l o g i c a l −l i n k −c o n t r o l
//
#define PSM SDP BLUETOOTH PROTOCOL SDP
#define PSM RFCOMM BLUETOOTH PROTOCOL RFCOMM
#define PSM BNEP BLUETOOTH PROTOCOL BNEP
// @TODO: s c r a p e PSMs B l u e t o o t h SIG s i t e and p u t i n b l u e t o o t h p s m . h
or b l u e t o o t h l 2 c a p . h
#define PSM HID CONTROL 0 x11
521

#define PSM HID INTERRUPT 0 x13


#define PSM ATT 0 x1f
#define PSM IPSP 0 x23

/∗ ∗
∗ @ b r i e f S e t up L2CAP and r e g i s t e r L2CAP w i t h HCI l a y e r .
∗/
void l 2 c a p i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Add e v e n t p a c k e t h a n d l e r f o r LE Connection Parameter
Update e v e n t s
∗/
void l 2 c a p a d d e v e n t h a n d l e r ( b t s t a c k p a c k e t c a l l b a c k r e g i s t r a t i o n t
∗ callback handler ) ;

/∗ ∗
∗ @ b r i e f Remove e v e n t p a c k e t h a n d l e r .
∗/
void l 2 c a p r e m o v e e v e n t h a n d l e r (
btstack packet callback registration t ∗ callback handler ) ;

/∗ ∗
∗ @ b r i e f Get max MTU f o r C l a s s i c c o n n e c t i o n s b a s e d on b t s t a c k
configuration
∗/
uint16 t l2cap max mtu ( void ) ;

/∗ ∗
∗ @ b r i e f Get max MTU f o r LE c o n n e c t i o n s b a s e d on b t s t a c k
configuration
∗/
uint16 t l 2 c a p m a x l e m t u ( void ) ;

/∗ ∗
∗ @ b r i e f S e t t h e max MTU f o r LE c o n n e c t i o n s , i f not s e t
l2cap max mtu ( ) w i l l be used .
∗/
void l 2 c a p s e t m a x l e m t u ( uint16 t max mtu ) ;

/∗ ∗
∗ @ b r i e f C r e a t e s L2CAP c h a n n e l t o t h e PSM o f a remote d e v i c e w i t h
b a s e b a n d a d d r e s s . A new b a s e b a n d c o n n e c t i o n w i l l be i n i t i a t e d
i f necessary .
∗ @param p a c k e t h a n d l e r
∗ @param a d d r e s s
∗ @param psm
∗ @param mtu
∗ @param l o c a l c i d
∗ @return s t a t u s
∗/
uint8 t l 2 c a p c r e a t e c h a n n e l ( btstack packet handler t p a c k e t h a n d l e r
, bd addr t a d d r e s s , uint16 t psm , uint16 t mtu , uint16 t ∗
out local cid ) ;
522

/∗ ∗
∗ @ b r i e f D i s c o n n e c t s L2CAP c h a n n e l w i t h g i v e n i d e n t i f i e r .
∗ @param l o c a l c i d
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l or
L2CAP LOCAL CID DOES NOT EXIST
∗/
uint8 t l 2 c a p d i s c o n n e c t ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f Q u e r i e s t h e maximal t r a n s f e r u n i t (MTU) f o r L2CAP c h a n n e l
with given i d e n t i f i e r .
∗/
uint16 t l 2 c a p g e t r e m o t e m t u f o r l o c a l c i d ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f Sends L2CAP d a t a p a c k e t t o t h e c h a n n e l w i t h g i v e n
identifier .
∗ @note For c h a n n e l i n c r e d i t −b a s e d f l o w c o n t r o l mode , d a t a ne e ds
to stay v a l i d u n t i l . . event
∗ @param l o c a l c i d
∗ @param d a t a t o send
∗ @param l e n o f d a t a
∗ @return s t a t u s
∗/
uint8 t l 2 c a p s e n d ( uint16 t l o c a l c i d , const uint8 t ∗ data , uint16 t
len ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r s L2CAP s e r v i c e w i t h g i v e n PSM and MTU, and
assigns a packet handler .
∗ @param p a c k e t h a n d l e r
∗ @param psm
∗ @param mtu
∗ @param s e c u r i t y l e v e l
∗ @return s t a t u s ERROR CODE SUCCESS i f s u c c e s s f u l , o t h e r w i s e
L2CAP SERVICE ALREADY REGISTERED or BTSTACK MEMORY ALLOC FAILED
∗/
uint8 t l 2 c a p r e g i s t e r s e r v i c e ( btstack packet handler t
p a c k e t h a n d l e r , uint16 t psm , uint16 t mtu , g a p s e c u r i t y l e v e l t
security level ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r s L2CAP s e r v i c e w i t h g i v e n PSM.
∗/
uint8 t l 2 c a p u n r e g i s t e r s e r v i c e ( uint16 t psm ) ;

/∗ ∗
∗ @ b r i e f A c c e p t s incoming L2CAP c o n n e c t i o n .
∗/
void l 2 c a p a c c e p t c o n n e c t i o n ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f Deny incoming L2CAP c o n n e c t i o n .
523

∗/
void l 2 c a p d e c l i n e c o n n e c t i o n ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f Check i f o u t g o i n g b u f f e r i s a v a i l a b l e and t h a t t h e r e ’ s
s p a c e on t h e B l u e t o o t h module
∗ @return t r u e i f p a c k e t can be s e n t
∗/
b o o l l 2 c a p c a n s e n d p a c k e t n o w ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f L2CAP EVENT CAN SEND NOW as soon as
possible
∗ @note L2CAP EVENT CAN SEND NOW might be e m i t t e d d u r i n g c a l l t o
this function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗ @param l o c a l c i d
∗ @return s t a t u s
∗/
uint8 t l 2 c a p r e q u e s t c a n s e n d n o w e v e n t ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @brief Reserve outgoing b u f f e r
∗ @note Only f o r L2CAP B a s i c Mode Channels
∗ @note Must o n l y be c a l l e d a f t e r a ’ can send now ’ c h e c k or e v e n t
∗ @note A s s e r t s i f p a c k e t b u f f e r i s a l r e a d y r e s e r v e d
∗/
void l 2 c a p r e s e r v e p a c k e t b u f f e r ( void ) ;

/∗ ∗
∗ @ b r i e f Get o u t g o i n g b u f f e r and p r e p a r e d a t a .
∗ @note Only f o r L2CAP B a s i c Mode Channels
∗/
uint8 t ∗ l 2 c a p g e t o u t g o i n g b u f f e r ( void ) ;

/∗ ∗
∗ @ b r i e f Send L2CAP p a c k e t p r e p a r e d i n o u t g o i n g b u f f e r t o c h a n n e l
∗ @note Only f o r L2CAP B a s i c Mode Channels
∗/
uint8 t l 2 c a p s e n d p r e p a r e d ( uint16 t l o c a l c i d , uint16 t l e n ) ;

/∗ ∗
∗ @ b r i e f R e l e a s e o u t g o i n g b u f f e r ( o n l y needed i f
l 2 c a p s e n d p r e p a r e d i s not c a l l e d )
∗ @note Only f o r L2CAP B a s i c Mode Channels
∗/
void l 2 c a p r e l e a s e p a c k e t b u f f e r ( void ) ;

//
// Connection−O r i e n t e d Channels i n Enhanced R e t r a n s m i s s i o n Mode −
ERTM
//

/∗ ∗
524

∗ @ b r i e f C r e a t e s L2CAP c h a n n e l t o t h e PSM o f a remote d e v i c e w i t h


b a s e b a n d a d d r e s s u s i n g Enhanced R e t r a n s m i s s i o n Mode .
∗ A new b a s e b a n d c o n n e c t i o n w i l l be i n i t i a t e d i f n e c e s s a r y .
∗ @param p a c k e t h a n d l e r
∗ @param a d d r e s s
∗ @param psm
∗ @param e r t m c o n f i g
∗ @param b u f f e r t o s t o r e r e a s s e m b l e d r x p a c k e t , out−of −o r d e r
p a c k e t s and unacknowledged o u t g o i n g p a c k e t s w i t h t h e i r
tretransmission timers
∗ @param s i z e o f b u f f e r
∗ @param l o c a l c i d
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e r t m c r e a t e c h a n n e l ( btstack packet handler t
p a c k e t h a n d l e r , bd addr t a d d r e s s , uint16 t psm ,
l 2c ap e rt m c on fi g t ∗ ertm contig ,
uint8 t ∗ b u f f e r , uint32 t
s i z e , uint16 t ∗ o u t l o c a l c i d
);

/∗ ∗
∗ @ b r i e f A c c e p t s incoming L2CAP c o n n e c t i o n f o r Enhanced
R e t r a n s m i s s i o n Mode
∗ @param l o c a l c i d
∗ @param e r t m c o n f i g
∗ @param b u f f e r t o s t o r e r e a s s e m b l e d r x p a c k e t , out−of −o r d e r
p a c k e t s and unacknowledged o u t g o i n g p a c k e t s w i t h t h e i r
tretransmission timers
∗ @param s i z e o f b u f f e r
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e r t m a c c e p t c o n n e c t i o n ( uint16 t l o c a l c i d ,
l 2 c a p e r t m c o n f i g t ∗ e r t m c o n t i g , uint8 t ∗ b u f f e r , uint32 t
size ) ;

/∗ ∗
∗ @ b r i e f Deny incoming incoming L2CAP c o n n e c t i o n f o r Enhanced
R e t r a n s m i s s i o n Mode
∗ @param l o c a l c i d
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e r t m d e c l i n e c o n n e c t i o n ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f ERTM S e t c h a n n e l as b u s y .
∗ @note Can be c l e a r e d by l 2 c a p e r t m s e t r e a d y
∗ @param l o c a l c i d
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e r t m s e t b u s y ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f ERTM S e t c h a n n e l as r e a d y
525

∗ @note Used a f t e r l 2 c a p e r t m s e t b u s y
∗ @param l o c a l c i d
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e r t m s e t r e a d y ( uint16 t l o c a l c i d ) ;

//
// L2CAP Connection−O r i e n t e d Channels i n LE C r e d i t −Based Flow−
C o n t r o l Mode − CBM
//

/∗ ∗
∗ @ b r i e f R e g i s t e r L2CAP s e r v i c e i n LE C r e d i t −Based Flow−C o n t r o l
Mode
∗ @note MTU and i n i t i a l c r e d i t s a r e s p e c i f i e d i n
l2cap cbm accept connection ( . . ) c a l l
∗ @param p a c k e t h a n d l e r
∗ @param psm
∗ @param s e c u r i t y l e v e l
∗/
uint8 t l 2 c a p c b m r e g i s t e r s e r v i c e ( btstack packet handler t
p a c k e t h a n d l e r , uint16 t psm , g a p s e c u r i t y l e v e l t
security level ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r L2CAP s e r v i c e i n LE C r e d i t −Based Flow−C o n t r o l
Mode
∗ @param psm
∗/

uint8 t l 2 c a p c b m u n r e g i s t e r s e r v i c e ( uint16 t psm ) ;

/∗
∗ @ b r i e f Accept incoming c o n n e c t i o n LE C r e d i t −Based Flow−C o n t r o l
Mode
∗ @param l o c a l c i d L2CAP Channel I d e n t i f i e r
∗ @param r e c e i v e b u f f e r b u f f e r used f o r r e a s s e m b l y o f L2CAP
LE I n f o r m a t i o n Frames i n t o s e r v i c e d a t a u n i t (SDU) w i t h g i v e n
MTU
∗ @param r e c e i v e b u f f e r s i z e b u f f e r s i z e e q u a l s MTU
∗ @param i n i t i a l c r e d i t s Number o f i n i t i a l c r e d i t s p r o v i d e d
t o p e e r or L2CAP LE AUTOMATIC CREDITS t o e n a b l e a u t o m a t i c
credits
∗/

uint8 t l 2 c a p c b m a c c e p t c o n n e c t i o n ( uint16 t l o c a l c i d , uint8 t ∗


r e c e i v e s d u b u f f e r , uint16 t mtu , uint16 t i n i t i a l c r e d i t s ) ;

/∗ ∗
∗ @ b r i e f D e e c l i n e c o n n e c t i o n i n LE C r e d i t −Based Flow−C o n t r o l Mode
∗ @param l o c a l c i d L2CAP Channel I d e n t i f i e r
∗ @param r e s u l t result , see
L2CAP CBM CONNECTION RESULT SUCCESS i n b l u e t o o t h . h
526

∗/

uint8 t l 2 c a p c b m d e c l i n e c o n n e c t i o n ( uint16 t l o c a l c i d , uint16 t


result ) ;

/∗ ∗
∗ @ b r i e f C r ea t e o u t g o i n g c h a n n e l i n LE C r e d i t −Based Flow−C o n t r o l
Mode
∗ @param p a c k e t h a n d l e r P a c k et h a n d l e r f o r t h i s c o n n e c t i o n
∗ @param c o n h a n d l e HCI Connection Handle , LE t r a n s p o r t
∗ @param psm S e r v i c e PSM t o c o n n e c t t o
∗ @param r e c e i v e b u f f e r b u f f e r used f o r r e a s s e m b l y o f L2CAP
LE I n f o r m a t i o n Frames i n t o s e r v i c e d a t a u n i t (SDU) w i t h g i v e n
MTU
∗ @param r e c e i v e b u f f e r s i z e b u f f e r s i z e e q u a l s MTU
∗ @param i n i t i a l c r e d i t s Number o f i n i t i a l c r e d i t s p r o v i d e d
t o p e e r or L2CAP LE AUTOMATIC CREDITS t o e n a b l e a u t o m a t i c
credits
∗ @param s e c u r i t y l e v e l Minimum r e q u i r e d s e c u r i t y l e v e l
∗ @param o u t l o c a l c i d L2CAP LE Channel I d e n t i f i e r i s
stored here
∗/
uint8 t l 2 c a p c b m c r e a t e c h a n n e l ( btstack packet handler t
packet handler , h c i c o n h a n d l e t con handle ,
uint16 t psm , uint8 t ∗ r e c e i v e s d u b u f f e r , uint16 t mtu ,
uint16 t i n i t i a l c r e d i t s , g a p s e c u r i t y l e v e l t
security level ,
uint16 t ∗ o u t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f P r o v i d e c r e d i t s f o r c h a n n e l i n LE C r e d i t −Based Flow−
C o n t r o l Mode
∗ @param l o c a l c i d L2CAP Channel I d e n t i f i e r
∗ @param c r e d i t s Number a d d i t i o n a l c r e d i t s f o r p e e r
∗/
uint8 t l 2 c a p c b m p r o v i d e c r e d i t s ( uint16 t l o c a l c i d , uint16 t
credits ) ;

//
// L2CAP Connection−O r i e n t e d Channels i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode − ECBM
//

/∗ ∗
∗ @ b r i e f R e g i s t e r L2CAP s e r v i c e i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @note MTU and i n i t i a l c r e d i t s a r e s p e c i f i e d i n
l2cap enhanced accept connection ( . . ) c a l l
∗ @param p a c k e t h a n d l e r
∗ @param psm
∗ @param min remote mtu
∗ @param s e c u r i t y l e v e l
∗ @oaram a u t h o r i z a t i o n r e q u i r e d
∗ @return s t a t u s
527

∗/
uint8 t l 2 c a p e c b m r e g i s t e r s e r v i c e ( btstack packet handler t
p a c k e t h a n d l e r , uint16 t psm , uint16 t min remote mtu ,
gap security level t
s e c u r i t y l e v e l , bool
authorization required ) ;

/∗ ∗
∗ @ b r i e f U n r e g i s t e r L2CAP s e r v i c e i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @param psm
∗ @return s t a t u s
∗/

uint8 t l 2 c a p e c b m u n r e g i s t e r s e r v i c e ( uint16 t psm ) ;

/∗ ∗
∗ @ b r i e f S e t Minimal MPS f o r c h a n n e l i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @param mps min
∗/
void l 2 c a p e c b m m p s s e t m i n ( uint16 t mps min ) ;

/∗ ∗
∗ @ b r i e f S e t Minimal MPS f o r c h a n n e l i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @param mps max
∗/
void l 2 c a p e c b m m p s s e t m a x ( uint16 t mps max ) ;

/∗ ∗
∗ @ b r i e f C r ea t e o u t g o i n g c h a n n e l i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @note r e c e i v e b u f f e r p o i n t s t o an a r r a y o f r e c e i v e b u f f e r s w i t h
num channels e l e m e n t s
∗ @note o u t l o c a l c i d p o i n t s t o an a r r a y where CID i s s t o r e d w i t h
num channel e l e m e n t s
∗ @param p a c k e t h a n d l e r P a c k et h a n d l e r f o r t h i s c o n n e c t i o n
∗ @param c o n h a n d l e HCI Connection Handle
∗ @param s e c u r i t y l e v e l Minimum r e q u i r e d s e c u r i t y l e v e l
∗ @param psm S e r v i c e PSM t o c o n n e c t t o
∗ @param num channels number o f c h a n n e l s t o c r e a t e
∗ @param i n i t i a l c r e d i t s Number o f i n i t i a l c r e d i t s p r o v i d e d
t o p e e r p e r c h a n n e l or L2CAP LE AUTOMATIC CREDITS t o e n a b l e
automatic c r e d i t s
∗ @param r e c e i v e b u f f e r s i z e b u f f e r s i z e e q u a l s MTU
∗ @param r e c e i v e b u f f e r s Array o f b u f f e r s used f o r r e a s s e m b l y
o f L2CAP I n f o r m a t i o n Frames i n t o s e r v i c e d a t a u n i t (SDU) w i t h
g i v e n MTU
∗ @param o u t l o c a l c i d s Array o f L2CAP Channel I d e n t i f i e r s
i s s t o r e d h e r e on s u c c e s s
∗ @return s t a t u s
∗/
528

uint8 t l 2 c a p e c b m c r e a t e c h a n n e l s ( btstack packet handler t


packet handler , h c i c o n h a n d l e t con handle ,
gap security level t
security level ,
uint16 t psm , uint8 t
num channels , uint16 t
i n i t i a l c r e d i t s , uint16 t
receive buffer size ,
uint8 t ∗∗ r e c e i v e b u f f e r s ,
uint16 t ∗ o u t l o c a l c i d s
);

/∗ ∗
∗ @ b r i e f Accept incoming c o n n e c t i o n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @param l o c a l c i d from
L2CAP EVENT INCOMING DATA CONNECTION
∗ @param num channels
∗ @param i n i t i a l c r e d i t s Number o f i n i t i a l c r e d i t s p r o v i d e d t o
p e e r p e r c h a n n e l or L2CAP LE AUTOMATIC CREDITS t o e n a b l e
automatic c r e d i t s
∗ @param r e c e i v e b u f f e r s i z e
∗ @param r e c e i v e b u f f e r s Array o f b u f f e r s used f o r r e a s s e m b l y
o f L2CAP I n f o r m a t i o n Frames i n t o s e r v i c e d a t a u n i t (SDU) w i t h
g i v e n MTU
∗ @param o u t l o c a l c i d s Array o f L2CAP Channel I d e n t i f i e r s i s
s t o r e d h e r e on s u c c e s s
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e c b m a c c e p t c h a n n e l s ( uint16 t l o c a l c i d , uint8 t
num channels , uint16 t i n i t i a l c r e d i t s ,
uint16 t
receive buffer size ,
uint8 t ∗∗
receive buffers ,
uint16 t ∗
out local cids ) ;
/∗ ∗
∗ @ b r i e f D e c l i n e c o n n e c t i o n i n Enhanced C r e d i t −Based Flow−C o n t r o l
Mode
∗ @param l o c a l c i d from
L2CAP EVENT INCOMING DATA CONNECTION
∗ @param r e s u l t See
L2CAP ECBM CONNECTION RESULT ALL SUCCESS i n b l u e t o o t h . h
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e c b m d e c l i n e c h a n n e l s ( uint16 t l o c a l c i d , uint16 t
result ) ;

/∗ ∗
∗ @ b r i e f P r o v i d e c r e d i t s f o r c h a n n e l i n Enhanced C r e d i t −Based Flow−
C o n t r o l Mode
∗ @param l o c a l c i d L2CAP Channel I d e n t i f i e r
∗ @param c r e d i t s Number a d d i t i o n a l c r e d i t s f o r p e e r
529

∗ @return s t a t u s
∗/
uint8 t l 2 c a p e c b m p r o v i d e c r e d i t s ( uint16 t l o c a l c i d , uint16 t
credits ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t e m i s s i o n o f L2CAP EVENT ECBM CAN SEND NOW as soon
as p o s s i b l e
∗ @note L2CAP EVENT ECBM CAN SEND NOW might be e m i t t e d d u r i n g c a l l
to t h i s function
∗ so p a c k e t h a n d l e r s h o u l d be r e a d y t o h a n d l e i t
∗ @param l o c a l c i d L2CAP Channel I d e n t i f i e r
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e c b m r e q u e s t c a n s e n d n o w e v e n t ( uint16 t l o c a l c i d ) ;

/∗ ∗
∗ @ b r i e f R e c o n f i g u r e MPS/MTU o f l o c a l c h a n n e l s
∗ @param num cids
∗ @param l o c a l c i d s array of l o c a l c i d s to r e c o n f i g u r e
∗ @param r e c e i v e b u f f e r s i z e b u f f e r s i z e e q u a l s MTU
∗ @param r e c e i v e b u f f e r s Array o f b u f f e r s used f o r r e a s s e m b l y
o f L2CAP I n f o r m a t i o n Frames i n t o s e r v i c e d a t a u n i t (SDU) w i t h
g i v e n MTU
∗ @return s t a t u s
∗/
uint8 t l 2 c a p e c b m r e c o n f i g u r e c h a n n e l s ( uint8 t num cids , uint16 t ∗
l o c a l c i d s , i n t 1 6 t r e c e i v e b u f f e r s i z e , uint8 t ∗∗
receive buffers ) ;

/∗ ∗
∗ @brief Trigger pending connection responses a f t e r p a i r i n g
completed
∗ @note Must be c a l l e d a f t e r r e c e i v i n g an SM PAIRING COMPLETE e v e n t
, w i l l be removed e v e n t u a l l y
∗ @param c o n h a n d l e
∗/
void l 2 c a p e c b m t r i g g e r p e n d i n g c o n n e c t i o n r e s p o n s e s (
hci con handle t con handle ) ;

/∗ ∗
∗ @ b r i e f De−I n i t L2CAP
∗/
void l 2 c a p d e i n i t ( void ) ;

1.99. Audio Stream Control Service Client API. broadcast audio scan service client.h

typedef enum {
BROADCAST AUDIO SCAN SERVICE CLIENT STATE IDLE ,
BROADCAST AUDIO SCAN SERVICE CLIENT STATE W2 QUERY SERVICE,
BROADCAST AUDIO SCAN SERVICE CLIENT STATE W4 SERVICE RESULT,
530

BROADCAST AUDIO SCAN SERVICE CLIENT STATE W2 QUERY CHARACTERISTICS


,
BROADCAST AUDIO SCAN SERVICE CLIENT STATE W4 CHARACTERISTIC RESULT
,

BROADCAST AUDIO SCAN SERVICE CLIENT STATE W2 QUERY CHARACTERISTIC DESCRIPTORS


,
BROADCAST AUDIO SCAN SERVICE CLIENT STATE W4 CHARACTERISTIC DESCRIPTORS RESULT
,

BROADCAST AUDIO SCAN SERVICE CLIENT STATE W2 REGISTER NOTIFICATION


,
BROADCAST AUDIO SCAN SERVICE CLIENT STATE W4 NOTIFICATION REGISTERED
,
BROADCAST AUDIO SCAN SERVICE CLIENT STATE CONNECTED,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 READ CHARACTERISTIC CONFIGURATION


,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 CHARACTERISTIC CONFIGURATION RESULT
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 WRITE CONTROL POINT START SCAN
,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 WRITE CONTROL POINT START SCAN
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 WRITE CONTROL POINT STOP SCAN
,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 WRITE CONTROL POINT STOP SCAN
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 WRITE CONTROL POINT ADD SOURCE
,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 WRITE CONTROL POINT ADD SOURCE
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 WRITE CONTROL POINT MODIFY SOURCE
,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 WRITE CONTROL POINT MODIFY SOURCE
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 WRITE CONTROL POINT SET BROADCAST CODE
,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 WRITE CONTROL POINT SET BROADCAST CODE
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 WRITE CONTROL POINT REMOVE SOURCE
,
BROADCAST AUDIO SCAN SERVICE CLIENT W4 WRITE CONTROL POINT REMOVE SOURCE
,

BROADCAST AUDIO SCAN SERVICE CLIENT W2 READE RECEIVE STATE,


BROADCAST AUDIO SCAN SERVICE CLIENT W4 READE RECEIVE STATE,
531

} broadcast audio scan service client state t ;

typedef struct {
// used f o r add s o u r c e command
b a s s s o u r c e d a t a t data ;

// r e c e i v e d v i a n o t i f i c a t i o n
bool in use ;
uint8 t s o u r c e i d ;
le audio big encryption t big encryption ;
uint8 t bad code [ 1 6 ] ;

// c h a r a c t e r i s t i c
uint16 t r e c e i v e s t a t e value handle ;
uint16 t r e c e i v e s t a t e ccc handle ;
uint16 t r e c e i v e s t a t e properties ;
uint16 t r e c e i v e s t a t e end handle ;
} bass client source t ;

typedef struct {
b t s t a c k l i n k e d i t e m t item ;

hci con handle t con handle ;


uint16 t cid ;
uint16 t mtu ;
broadcast audio scan service client state t state ;

// s e r v i c e
uint16 t s t a r t h a n d l e ;
uint16 t e n d h a n d l e ;
uint16 t c o n t r o l p o i n t v a l u e h a n d l e ;

// used f o r memory c a p a c i t y c h e c k i n g
uint8 t s e r v i c e i n s t a n c e s n u m ;
uint8 t r e c e i v e s t a t e s i n s t a n c e s n u m ;
// used f o r n o t i f i c a t i o n r e g i s t r a t i o n
uint8 t r e c e i v e s t a t e s i n d e x ;

uint8 t m a x r e c e i v e s t a t e s n u m ;
bass client source t ∗ receive states ;

// used f o r w r i t e s e g m e n t a t i o n
uint8 t b u f f e r [ BASS CLIENT MAX ATT BUFFER SIZE ] ;
uint16 t b u f f e r o f f s e t ;
uint16 t d a t a s i z e ;

gatt client notification t notification listener ;

// used f o r a d d i n g and m o d i f y i n g s o u r c e
const b a s s s o u r c e d a t a t ∗ c o n t r o l p o i n t o p e r a t i o n d a t a ;
uint8 t c o n t r o l p o i n t o p e r a t i o n s o u r c e i d ;
// used f o r s e t t i n g t h e b r o a d c a s t code
const uint8 t ∗ b r o a d c a s t c o d e ;
} bass client connection t ;
532

/∗ ∗
∗ @ b r i e f I n i t B r o a d c a s t Audio Scan S e r v i c e C l i e n t . R e g i s t e r p a c k e t
handler to receive events :
∗ − GATTSERVICE SUBEVENT BASS CLIENT CONNECTED
∗ − GATTSERVICE SUBEVENT BASS CLIENT DISCONNECTED
∗ − GATTSERVICE SUBEVENT BASS CLIENT SCAN OPERATION COMPLETE
∗ − GATTSERVICE SUBEVENT BASS CLIENT SOURCE OPERATION COMPLETE
∗ − GATTSERVICE SUBEVENT BASS CLIENT NOTIFICATION COMPLETE
∗ @param p a c k e t h a n d l e r f o r e v e n t s
∗/
void b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t i n i t (
btstack packet handler t p a c k e t h a n d l e r ) ;

/∗ ∗
∗ @ b r i e f Connect t o BASS S e r v i c e on remote d e v i c e
∗ @note GATTSERVICE SUBEVENT BASS CLIENT CONNECTED w i l l be e m i t t e d
∗ @param c o n n e c t i o n s t r u c t p r o v i d e d by user , n ee d s t o s t a y v a l i d
u n t i l disconnect event i s received
∗ @param s o u r c e s b u f f e r t o s t o r e i n f o r m a t i o n on B r o a d c a s t S o u r c e s
on t h e s e r v i c e
∗ @param num sources
∗ @param c o n h a n d l e t o c o n n e c t t o
∗ @param b a s s c i d c o n n e c t i o n i d f o r t h i s c o n n e c t i o n f o r o t h e r
functions
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t c o n n e c t (
b a s s c l i e n t c o n n e c t i o n t ∗ connection , b a s s c l i e n t s o u r c e t ∗
s o u r c e s , uint8 t num sources , h c i c o n h a n d l e t c o n h a n d l e ,
uint16 t ∗ b a s s c i d ) ;

/∗ ∗
∗ @ b r i e f N o t i f y BASS S e r v i c e t h a t s c a n n i n g has s t a r t e d
∗ @param b a s s c i d
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t s c a n n i n g s t a r t e d (
uint16 t b a s s c i d ) ;

/∗ ∗
∗ @ b r i e f N o t i f y BASS S e r v i c e t h a t s c a n n i n g has s t o p p e d
∗ @note e m i t s
GATTSERVICE SUBEVENT BASS CLIENT SOURCE OPERATION COMPLETE
∗ @param b a s s c i d
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t s c a n n i n g s t o p p e d (
uint16 t b a s s c i d ) ;

/∗ ∗
∗ @ b r i e f Add B r o a d c a s t Source on s e r v i c e
∗ @note GATTSERVICE SUBEVENT BASS NOTIFICATION COMPLETE w i l l
contain source id for other functions
533

∗ @param b a s s c i d
∗ @param a d d s o u r c e d a t a d a t a t o add , ne e ds t o s t a y v a l i d u n t i l
GATTSERVICE SUBEVENT BASS CLIENT SOURCE OPERATION COMPLETE
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t a d d s o u r c e ( uint16 t
b a s s c i d , const b a s s s o u r c e d a t a t ∗ a d d s o u r c e d a t a ) ;

/∗ ∗
∗ @ b r i e f Modify i n f o r m a t i o n a b o u t B r o a d c a s t Source on s e r v i c e
∗ @param b a s s c i d
∗ @param s o u r c e i d
∗ @param m o d i f y s o u r c e d a t a d a t a t o modify , ne ed s t o s t a y v a l i d
until
GATTSERVICE SUBEVENT BASS CLIENT SOURCE OPERATION COMPLETE
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t m o d i f y s o u r c e ( uint16 t
b a s s c i d , uint8 t s o u r c e i d , const b a s s s o u r c e d a t a t ∗
modify source data ) ;

/∗ ∗
∗ @ b r i e f S e t B r o a d c a s t Code f o r a B r o a d c a s t Source t o a l l o w remote
do d e c r y p t a u d i o stream
∗ @param b a s s c i d
∗ @param s o u r c e i d
∗ @param b r o a d c a s t c o d e
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t s e t b r o a d c a s t c o d e (
uint16 t b a s s c i d , uint8 t s o u r c e i d , const uint8 t ∗
broadcast code ) ;

/∗ ∗
∗ @ b r i e f Remove i n f o r m a t i o n a b o u t B r o a d c a s t Source
∗ @param b a s s c i d
∗ @param s o u r c e i d
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t r e m o v e s o u r c e ( uint16 t
b a s s c i d , uint8 t s o u r c e i d ) ;

/∗ ∗
∗ @param P r o v i d e read−o n l y a c c e s s t o B r o a d c a s t R e c e i v e S t a t e o f
g i v e n B r o a d c a s t Source on s e r v i c e
∗ @param b a s s c i d
∗ @param s o u r c e i d
∗ @return p o i n t e r t o s o u r c e d a t a or NULL, i f s o u r c e i d not found
∗/
const b a s s s o u r c e d a t a t ∗
b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t g e t s o u r c e d a t a ( uint16 t
b a s s c i d , uint8 t s o u r c e i d ) ;

/∗ ∗
534

∗ @param Get BIG E n c r y p t i o n and Bad Code from B r o a d c a s t R e c e i v e


S t a t e o f g i v e n B r o a d c a s t Source on s e r v i c e
∗ @param b a s s c i d
∗ @param s o u r c e i d
∗ @param o u t b i g e n c r y p t i o n
∗ @param o u t b a d c o d e 16− b y t e b u f f e r
∗ @return s t a t u s
∗/
uint8 t b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t g e t e n c r y p t i o n s t a t e (
uint16 t b a s s c i d , uint8 t s o u r c e i d ,
le audio big encryp

out big encryptio


,

uint8 t

out bad code


)
;

/∗ ∗
∗ @ b r i e f D e i n i t B r o a d c a s t Audio Scan S e r v i c e C l i e n t
∗/
void b r o a d c a s t a u d i o s c a n s e r v i c e c l i e n t d e i n i t ( uint16 t b a s s c i d ) ;

1.100. Broadcast Audio Scan Service Server (BASS) API. broadcast audio scan service
: @text The Broadcast Audio Scan Service is used by servers to expose their sta-
tus with respect to synchronization to broadcast Audio Streams and associated
data, including Broadcast Codes used to decrypt encrypted broadcast Audio
Streams. Clients can use the attributes exposed by servers to observe and/or
request changes in server behavior.
To use with your application, add #import <broadcast audio scan service.gatt> to
your .gatt file.

// memory f o r l i s t o f t h e s e s t r u c t s i s a l l o c a t e d by t h e a p p l i c a t i o n
typedef struct {
// a s s i g n e d by c l i e n t v i a c o n t r o l p o i n t
b a s s s o u r c e d a t a t data ;

uint8 t update counter ;


uint8 t source id ;
bool in use ;

le audio big encryption t big encryption ;


uint8 t bad code [ 1 6 ] ;
535

uint16 t b a s s r e c e i v e s t a t e h a n d l e ;
uint16 t b a s s r e c e i v e s t a t e c l i e n t c o n f i g u r a t i o n h a n d l e ;
uint16 t b a s s r e c e i v e s t a t e c l i e n t c o n f i g u r a t i o n ;
} bass server source t ;

typedef struct {
hci con handle t con handle ;
uint16 t s o u r c e s t o n o t i f y ;

// used f o r c a c h i n g l o n g w r i t e
uint8 t l o n g w r i t e b u f f e r [ 5 1 2 ] ;
uint16 t l o n g w r i t e v a l u e s i z e ;
uint16 t l o n g w r i t e a t t r i b u t e h a n d l e ;
} bass server connection t ;

/∗ ∗
∗ @ b r i e f I n i t B r o a d c a s t Audio Scan S e r v i c e S e r v e r w i t h ATT DB
∗ @param sources num
∗ @param s o u r c e s
∗ @param c l i e n t s n u m
∗ @param c l i e n t s
∗/
void b r o a d c a s t a u d i o s c a n s e r v i c e s e r v e r i n i t ( uint8 t const
sources num , b a s s s e r v e r s o u r c e t ∗ s o u r c e s , uint8 t const
clients num , b a s s s e r v e r c o n n e c t i o n t ∗ c l i e n t s ) ;

/∗ ∗
∗ @brief Register packet handler to receive events :
∗ − GATTSERVICE SUBEVENT BASS SERVER SCAN STOPPED
∗ − GATTSERVICE SUBEVENT BASS SERVER SCAN STARTED
∗ − GATTSERVICE SUBEVENT BASS SERVER BROADCAST CODE
∗ − GATTSERVICE SUBEVENT BASS SERVER SOURCE ADDED
∗ − GATTSERVICE SUBEVENT BASS SERVER SOURCE MODIFIED
∗ − GATTSERVICE SUBEVENT BASS SERVER SOURCE DELETED
∗ @param p a c k e t h a n d l e r
∗/
void b r o a d c a s t a u d i o s c a n s e r v i c e s e r v e r r e g i s t e r p a c k e t h a n d l e r (
btstack packet handler t p a c k e t h a n d l e r ) ;

/∗ ∗
∗ @ b r i e f S e t PA s t a t e o f s o u r c e .
∗ @param s o u r c e i n d e x
∗ @param s y n c s t a t e
∗/
void b r o a d c a s t a u d i o s c a n s e r v i c e s e r v e r s e t p a s y n c s t a t e ( uint8 t
source index , le audio pa sync state t sync state ) ;

/∗ ∗
∗ @ b r i e f Add s o u r c e .
∗ @param s o u r c e d a t a
∗ @param s o u r c e i n d e x
∗/
536

void b r o a d c a s t a u d i o s c a n s e r v i c e s e r v e r a d d s o u r c e ( const
b a s s s o u r c e d a t a t ∗ s o u r c e d a t a , uint8 t ∗ s o u r c e i n d e x ) ;

/∗ ∗
∗ @ b r i e f D e i n i t B r o a d c a s t Audio Scan S e r v i c e S e r v e r
∗/
void b r o a d c a s t a u d i o s c a n s e r v i c e s e r v e r d e i n i t ( void ) ;

1.101. Volume Offset Control Service Server API. le audio.h

1.102. Broadcast Audio Source Endpoint AD Builder API. le audio base builder.h

1.103. Broadcast Audio Source Endpoint AD Parser API. le audio base parser.h

1.104. LE Audio Util API. le audio util.h

1.105. Mesh Provisioning Service Server API. mesh provisioning service server.h

/∗ ∗
∗ @ b r i e f I n i t Mesh P r o v i s i o n i n g S e r v i c e S e r v e r w i t h ATT DB
∗/
void m e s h p r o v i s i o n i n g s e r v i c e s e r v e r i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Send a Proxy PDU message c o n t a i n i n g P r o v i s i o n i n g PDU from
a Provisioning Server to a Provisioning Client .
∗ @param c o n h a n d l e
∗ @param p r o x y p d u
∗ @param p r o x y p d u s i z e max l e n g h t MESH PROV MAX PROXY PDU
∗/
void m e s h p r o v i s i o n i n g s e r v i c e s e r v e r s e n d p r o x y p d u ( uint16 t
c o n h a n d l e , const uint8 t ∗ proxy pdu , uint16 t p r o x y p d u s i z e ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e PB−GATT.
∗ @param c a l l b a c k
∗/
void m e s h p r o v i s i o n i n g s e r v i c e s e r v e r r e g i s t e r p a c k e t h a n d l e r (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t can send now e v e n t t o send PDU
∗ G e n e r a t e s an MESH SUBEVENT CAN SEND NOW s u b e v e n t
∗ @param c o n h a n d l e
∗/
void m e s h p r o v i s i o n i n g s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w (
hci con handle t con handle ) ;
537

1.106. Mesh Proxy Service Server API. mesh proxy service server.h

/∗ ∗
∗ @ b r i e f I n i t Mesh Proxy S e r v i c e S e r v e r w i t h ATT DB
∗/
void m e s h p r o x y s e r v i c e s e r v e r i n i t ( void ) ;

/∗ ∗
∗ @ b r i e f Send a Proxy PDU message c o n t a i n i n g p r o x y PDU from a p r o x y
Server to a proxy C l i e n t .
∗ @param c o n h a n d l e
∗ @param p r o x y p d u
∗ @param p r o x y p d u s i z e max l e n g h t MESH PROV MAX PROXY PDU
∗/
void m e s h p r o x y s e r v i c e s e r v e r s e n d p r o x y p d u ( uint16 t c o n h a n d l e ,
const uint8 t ∗ proxy pdu , uint16 t p r o x y p d u s i z e ) ;

/∗ ∗
∗ @ b r i e f R e g i s t e r c a l l b a c k f o r t h e PB−GATT.
∗ @param c a l l b a c k
∗/
void m e s h p r o x y s e r v i c e s e r v e r r e g i s t e r p a c k e t h a n d l e r (
btstack packet handler t c a l l b a c k ) ;

/∗ ∗
∗ @ b r i e f R e q u e s t can send now e v e n t t o send PDU
∗ G e n e r a t e s an MESH SUBEVENT CAN SEND NOW s u b e v e n t
∗ @param c o n h a n d l e
∗/
void m e s h p r o x y s e r v i c e s e r v e r r e q u e s t c a n s e n d n o w ( h c i c o n h a n d l e t
con handle ) ;

#Events and Errors

1.107. L2CAP Events. L2CAP events and data packets are delivered to the
packet handler specified by l2cap register service resp. l2cap create channel. Data
packets have the L2CAP DATA PACKET packet type. L2CAP provides the fol-
lowing events:
• L2CAP EVENT CHANNEL OPENED - sent if channel establishment is
done. Status not equal zero indicates an error. Possible errors: out of
memory; connection terminated by local host, when the connection to
remote device fails.
• L2CAP EVENT CHANNEL CLOSED - emitted when channel is closed.
No status information is provided.
• L2CAP EVENT INCOMING CONNECTION - received when the con-
nection is requested by remote. Connection accept and decline are per-
formed with l2cap accept connection and l2cap decline connecti-on re-
spectively.
• L2CAP EVENT CAN SEND NOW - Indicates that an L2CAP data packet
could be sent on the reported l2cap cid. It is emitted after a call to
538

l2cap request can send now. See Sending L2CAP Data Please note that
the guarantee that a packet can be sent is only valid when the event is
received. After returning from the packet handler, BTstack might need
to send itself.

Event Event Code


L2CAP EVENT CHANNEL OPENED 0x70
L2CAP EVENT CHANNEL CLOSED 0x71
L2CAP EVENT INCOMING CONNECTION 0x72
L2CAP EVENT CAN SEND NOW 0x78

Table: L2CAP Events.


L2CAP event paramaters, with size in bits:
• L2CAP EVENT CHANNEL OPENED:
– event(8), len(8), status(8), address(48), handle(16), psm(16), lo-
cal cid(16), remote cid(16), local mtu(16), remote mtu(16)

• L2CAP EVENT CHANNEL CLOSED:


– event (8), len(8), channel(16)
• L2CAP EVENT INCOMING CONNECTION:
– event(8), len(8), address(48), handle(16), psm (16), local cid(16),
remote cid (16)
• L2CAP EVENT CAN SEND NOW:
– *event(8), len(8), local cid(16)
1.108. RFCOMM Events. All RFCOMM events and data packets are cur-
rently delivered to the packet handler specified by rfcomm register packet handler.
Data packets have the DATA PACKET packet type. Here is the list of events
provided by RFCOMM:
• RFCOMM EVENT INCOMING CONNECTION - received when the con-
nection is requested by remote. Connection accept and decline are per-
formed with rfcomm accept connection and rfcomm decline connection
respectively.
• RFCOMM EVENT CHANNEL CLOSED - emitted when channel is closed.
No status information is provided.
• RFCOMM EVENT CHANNEL OPENED - sent if channel establishment
is done. Status not equal zero indicates an error. Possible errors: an
L2CAP error, out of memory.
• RFCOMM EVENT CAN SEND NOW - Indicates that an RFCOMM
data packet could be sent on the reported rfcomm cid. It is emitted af-
ter a call to rfcomm request can send now. See Sending RFCOMM Data
Please note that the guarantee that a packet can be sent is only valid
when the event is received. After returning from the packet handler,
BTstack might need to send itself.
539

Event Event Code


RFCOMM EVENT CHANNEL OPENED 0x80
RFCOMM EVENT CHANNEL CLOSED 0x81
RFCOMM EVENT INCOMING CONNECTION 0x82
RFCOMM EVENT CAN SEND NOW 0x89

Table: RFCOMM Events.


RFCOMM event paramaters, with size in bits:
• RFCOMM EVENT CHANNEL OPENED:
– event(8), len(8), status(8), address(48), handle(16), server channel(8),
rfcomm cid(16), max frame size(16)
• RFCOMM EVENT CHANNEL CLOSED:
– event(8), len(8), rfcomm cid(16)
• RFCOMM EVENT INCOMING CONNECTION:
– event(8), len(8), address(48), channel (8), rfcomm cid(16)
• RFCOMM EVENT CAN SEND NOW:
– *event(8), len(8), rfcomm cid(16)

Error Error Code


BTSTACK MEMORY ALLOC FAILED 0x56
BTSTACK ACL BUFFERS FULL 0x57
L2CAP COMMAND REJECT REASON COMMAND NOT UNDERSTOOD 0x60
L2CAP COMMAND REJECT REASON SIGNALING MTU EXCEEDED 0x61
L2CAP COMMAND REJECT REASON INVALID CID IN REQUEST 0x62
L2CAP CONNECTION RESPONSE RESULT SUCCESSFUL 0x63
L2CAP CONNECTION RESPONSE RESULT PENDING 0x64
L2CAP CONNECTION RESPONSE RESULT REFUSED PSM 0x65
L2CAP CONNECTION RESPONSE RESULT REFUSED SECURITY 0x66
L2CAP CONNECTION RESPONSE RESULT REFUSED RESOURCES 0x65
L2CAP CONFIG RESPONSE RESULT SUCCESSFUL 0x66
L2CAP CONFIG RESPONSE RESULT UNACCEPTABLE PARAMS 0x67
L2CAP CONFIG RESPONSE RESULT REJECTED 0x68
L2CAP CONFIG RESPONSE RESULT UNKNOWN OPTIONS 0x69
L2CAP SERVICE ALREADY REGISTERED 0x6a
RFCOMM MULTIPLEXER STOPPED 0x70
RFCOMM NO OUTGOING CREDITS 0x72
SDP HANDLE ALREADY REGISTERED 0x80

1.109. Errors. Table: Errors.


We already had two listings with the Bluetooth SIG, but no official BTstack
v1.0 release. After the second listing, we decided that it’s time for a major
overhaul of the API - making it easier for new users.
In the following, we provide an overview of the changes and guidelines for
updating an existing code base. At the end, we present a command line tool and
540

as an alternative a Web service, that can simplify the migration to the new v1.0
API.

2. Changes
2.1. Repository structure.
2.1.1. include/btstack folder. The header files had been split between src/ and
include/btstack /. Now, the include/ folder is gone and the headers are pro-
vided in src/, src/classic/, src/ble/ or by the platform/ folders. There’s a new
src/btstack.h header that includes all BTstack headers.
2.1.2. Plural folder names. Folder with plural names have been renamed to the
singular form, examples: doc, chipset, platform, tool.
2.1.3. ble and src folders. The ble folder has been renamed into src/ble. Files
that are relevant for using BTstack in Classic mode, have been moved to src/-
classic. Files in src that are specific to individual platforms have been moved to
platform or port.
2.1.4. platform and port folders. The platforms folder has been split into plat-
form and “port” folders. The port folder contains a complete BTstack port of
for a specific setup consisting of an MCU and a Bluetooth chipset. Code that
didn’t belong to the BTstack core in src have been moved to platform or port as
well, e.g. hci transport h4 dma.c.
2.1.5. Common file names. Types with generic names like linked list have been
prefixed with btstack (e.g. btstack linked list.h) to avoid problems when inte-
grating with other environments like vendor SDKs.
2.2. Defines and event names. All defines that originate from the Blue-
tooth Specification are now in src/bluetooth.h. Addition defines by BTstack
are collected in src/btstack defines.h. All events names have the form MOD-
ULE EVENT NAME now.
2.3. Function names.
• The internal suffix has been an artifact from the iOS port. All public
functions with the internal suffix have been stripped of this suffix.
• Types with generic names like linked list have been prefixed with btstack
(e.g. btstack linked list) to avoid problems when integrating with other
environments like vendor SDKs.
2.4. Packet Handlers. We streamlined the use of packet handlers and their
types. Most callbacks are now of type btstack packet handler t and receive a
pointer to an HCI Event packet. Often a void * connection was the first argument
- this has been removed.
To facilitate working with HCI Events and get rid of manually calculating
offsets into packets, we’re providing auto-generated getters for all fields of all
events in src/hci event.h. All functions are defined as static inline, so they are
not wasting any program memory if not used. If used, the memory footprint
541

should be identical to accessing the field directly via offsets into the packet. Feel
free to start using these getters as needed.
2.5. Event Forwarding. In the past, events have been forwarded up the stack
from layer to layer, with the undesired effect that an app that used both att server
and security manager would get each HCI event twice. To fix this and other
potential issues, this has been cleaned up by providing a way to register multiple
listeners for HCI events. If you need to receive HCI or GAP events, you can now
directly register your callback with hci add event handler.
2.6. util folder. The utils folder has been renamed into btstack util to avoid
compile issues with other frameworks.
• The functions to read/store values in little/bit endian have been renamed
into big/little endian read/write 16/24/32.
• The functions to reverse bytes swap16/24/32/48/64/128/X habe been
renamed to reverse 16/24/32/48/64/128/X.
2.7. btstack config.h.
• btstack-config.h is now btstack config.h
• Defines have been sorted: HAVE specify features that are particular to
your port. ENABLE features can be added as needed.
• NO has been replaced with NR for the BTstack static memory allocation,
e.g., MAX NO HCI CONNECTIONS8 -> MAX NR HCI CONNECTIONS
• The #define EMBEDDED is dropped, i.e. the distinction if the API is
for embedded or not has been removed.
2.8. Linked List.
• The file has been renamed to btstack linked list.
• All functions are prefixed with btstack .
• The user data field has been removed as well.
2.9. Run Loop.
• The files have been renamed to btstack run loop
• To allow for simpler integration of custom run loop implementations,
run loop init(. . . ) is now called with a pointer to a run loop t function
table instead of using an enum that needs to be defined inside the BTstack
sources.
• Timers now have a new context field that can be used by the user.
2.10. HCI Setup. In the past, hci init(. . . ) was called with an hci transport t,
the transport configuration, remote device t and a bt control t objects. Besides
cleaning up the types (see remote device db and bt control below), hci init only
requires the hci transport t and it’s configuration.
The used btstack chipset t, bt control t, or link key db t can now be set with
hci set chipset, hci set control, and hci set link key db respectively.
2.10.1. remote device db. Has been split into src/classic/btstack link key db, plat-
form/daemon/btstack device name db, and platform/daemon/rfcomm service db.
2.10.2. bt control. Has been split into src/btstack chipset.h and src/bstack control.h
542

2.11. HCI / GAP. HCI functions that are commonly placed in GAP have been
moved from src/hci.h to src/gap.h

2.12. RFCOMM. In contrast to L2CAP, RFCOMM did not allow to regis-


ter individual packet handlers for each service and outgoing connection. This
has been fixed and the general rfcomm register packet handler(. . . ) has been
removed.

2.13. SPP Server. The function to create an SPP SDP record has been moved
into spp server.h

2.14. SDP Client.


• SDP Query structs have been replaced by HCI events. You can use
btstack event.h to access the fields.

2.15. SDP Server.


• Has been renamed to src/classic/sdp server.h.
• The distinction if the API is for embedded or not has been removed.

2.16. Security Manager.


• In all Security Manager calls that refer to an active connection, pass in
the current handle instead of addr + addr type.
• All Security Manager events are now regular HCI Events instead of sm *
structs
• Multiple packet handler can be registered with sm add event handler(. . . )
similar to HCI.

2.17. GATT Client.


• All GATT Client events are now regular HCI Events instead of gatt *
structs.
• The subclient id has been replaced by a complete handler for GATT
Client requests

2.18. ANCS Client. Renamed to src/ble/ancs client

2.19. Flow control / DAEMON EVENT HCI PACKET SENT. In BT-


stack, you can only send a packet with most protocols (L2CAP, RFCOMM, ATT)
if the outgoing buffer is free and also per-protocol constraints are satisfied, e.g.,
there are outgoing credits for RFCOMM.
Before v1.0, we suggested to check with l2cap can send packet now(..) or rf-
comm can send packet(..) whenever an HCI event was received. This has been
cleaned up and streamlined in v1.0.
Now, when there is a need to send a packet, you can call rcomm request can send now(..)
/ l2cap request can send now(..) to let BTstack know that you want to send a
packet. As soon as it becomes possible to send a RFCOMM EVENT CAN SEND NOW/L2CAP EV
will be emitted and you can directly react on that and send a packet. After that,
you can request another “can send event” if needed.
543

2.20. Daemon.
• Not tested since API migration!
• Moved into platform/daemon/
• Header for clients: platform/daemon/btstack client.h
• Java bindings are now at platform/daemon/bindings
2.21. Migration to v1.0 with a script. To simplify the migration to the new
v1.0 API, we’ve provided a tool in tool/migration to v1.0 that fixes include path
changes, handles all function renames and also updates the packet handlers to
the btstack packet handler t type. It also has a few rules that try to rename file
names in Makefile as good as possible.
It’s possible to migrate most of the provided embedded examples to v1.0. The
one change that it cannot handle is the switch from structs to HCI Events for the
SDP, GATT, and ANCS clients. The migration tool updates the packet handler
signature to btstack packet handler t, but it does not convert the field accesses to
sue the appropriate getters in btstack event.h. This has to be done manually, but
it is straight forward. E.g., to read the field status of the GATT EVENT QUERY COMPLETE,
you call call gatt event query complete get status(packet).
2.21.1. Requirements.
• bash
• sed
• Coccinelle. On Debian-based distributions, it’s available via apt. On OS
X, it can be installed via Homebrew.
2.21.2. Usage.

t o o l / m i g r a t i o n t o v 1 . 0 / m i g r a t i o n . sh PATH TO ORIGINAL PROJECT


PATH TO MIGRATED PROJECT

The tool first creates a copy of the original project and then uses sed and
coccinelle to update the source files.
2.22. Migration to v1.0 with a Web Service. BlueKitchen GmbH is pro-
viding a web service to help migrate your sources if you don’t want or cannot
install Coccinelle yourself.

You might also like