1 /** @file 2 * @brief Internal APIs for Bluetooth TBS. 3 */ 4 5 /* 6 * Copyright (c) 2019 Bose Corporation 7 * Copyright (c) 2021 Nordic Semiconductor ASA 8 * 9 * SPDX-License-Identifier: Apache-2.0 10 */ 11 12 #include <stdbool.h> 13 #include <stddef.h> 14 #include <stdint.h> 15 16 #include <zephyr/autoconf.h> 17 #include <zephyr/bluetooth/att.h> 18 #include <zephyr/bluetooth/audio/tbs.h> 19 #include <zephyr/bluetooth/gatt.h> 20 #include <zephyr/net_buf.h> 21 #include <zephyr/sys/atomic.h> 22 #include <zephyr/types.h> 23 24 #define BT_TBS_MAX_UCI_SIZE 6 25 #define BT_TBS_MIN_URI_LEN 3 /* a:b */ 26 #define BT_TBS_FREE_CALL_INDEX 0 27 28 /* Call Control Point Opcodes */ 29 #define BT_TBS_CALL_OPCODE_ACCEPT 0x00 30 #define BT_TBS_CALL_OPCODE_TERMINATE 0x01 31 #define BT_TBS_CALL_OPCODE_HOLD 0x02 32 #define BT_TBS_CALL_OPCODE_RETRIEVE 0x03 33 #define BT_TBS_CALL_OPCODE_ORIGINATE 0x04 34 #define BT_TBS_CALL_OPCODE_JOIN 0x05 35 36 /* Local Control Points - Used to do local control operations but still being 37 * able to determine if it is a local or remote operation 38 */ 39 #define BT_TBS_LOCAL_OPCODE_ANSWER 0x80 40 #define BT_TBS_LOCAL_OPCODE_HOLD 0x81 41 #define BT_TBS_LOCAL_OPCODE_RETRIEVE 0x82 42 #define BT_TBS_LOCAL_OPCODE_TERMINATE 0x83 43 #define BT_TBS_LOCAL_OPCODE_INCOMING 0x84 44 #define BT_TBS_LOCAL_OPCODE_SERVER_TERMINATE 0x85 45 46 #define FIRST_PRINTABLE_ASCII_CHAR ' ' /* space */ 47 48 #define BT_TBS_CALL_FLAG_SET_INCOMING(flag) (flag &= ~BT_TBS_CALL_FLAG_OUTGOING) 49 #define BT_TBS_CALL_FLAG_SET_OUTGOING(flag) (flag |= BT_TBS_CALL_FLAG_OUTGOING) 50 51 const char *parse_string_value(const void *data, uint16_t length, 52 uint16_t max_len); 53 bt_tbs_state_str(uint8_t state)54static inline const char *bt_tbs_state_str(uint8_t state) 55 { 56 switch (state) { 57 case BT_TBS_CALL_STATE_INCOMING: 58 return "incoming"; 59 case BT_TBS_CALL_STATE_DIALING: 60 return "dialing"; 61 case BT_TBS_CALL_STATE_ALERTING: 62 return "alerting"; 63 case BT_TBS_CALL_STATE_ACTIVE: 64 return "active"; 65 case BT_TBS_CALL_STATE_LOCALLY_HELD: 66 return "locally held"; 67 case BT_TBS_CALL_STATE_REMOTELY_HELD: 68 return "remote held"; 69 case BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD: 70 return "locally and remotely held"; 71 default: 72 return "unknown"; 73 } 74 } 75 bt_tbs_opcode_str(uint8_t opcode)76static inline const char *bt_tbs_opcode_str(uint8_t opcode) 77 { 78 switch (opcode) { 79 case BT_TBS_CALL_OPCODE_ACCEPT: 80 return "accept"; 81 case BT_TBS_CALL_OPCODE_TERMINATE: 82 return "terminate"; 83 case BT_TBS_CALL_OPCODE_HOLD: 84 return "hold"; 85 case BT_TBS_CALL_OPCODE_RETRIEVE: 86 return "retrieve"; 87 case BT_TBS_CALL_OPCODE_ORIGINATE: 88 return "originate"; 89 case BT_TBS_CALL_OPCODE_JOIN: 90 return "join"; 91 case BT_TBS_LOCAL_OPCODE_ANSWER: 92 return "remote answer"; 93 case BT_TBS_LOCAL_OPCODE_HOLD: 94 return "remote hold"; 95 case BT_TBS_LOCAL_OPCODE_RETRIEVE: 96 return "remote retrieve"; 97 case BT_TBS_LOCAL_OPCODE_TERMINATE: 98 return "remote terminate"; 99 case BT_TBS_LOCAL_OPCODE_INCOMING: 100 return "remote incoming"; 101 case BT_TBS_LOCAL_OPCODE_SERVER_TERMINATE: 102 return "server terminate"; 103 default: 104 return "unknown"; 105 } 106 } 107 bt_tbs_status_str(uint8_t status)108static inline const char *bt_tbs_status_str(uint8_t status) 109 { 110 switch (status) { 111 case BT_TBS_RESULT_CODE_SUCCESS: 112 return "success"; 113 case BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED: 114 return "opcode not supported"; 115 case BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE: 116 return "operation not possible"; 117 case BT_TBS_RESULT_CODE_INVALID_CALL_INDEX: 118 return "invalid call index"; 119 case BT_TBS_RESULT_CODE_STATE_MISMATCH: 120 return "state mismatch"; 121 case BT_TBS_RESULT_CODE_OUT_OF_RESOURCES: 122 return "out of resources"; 123 case BT_TBS_RESULT_CODE_INVALID_URI: 124 return "invalid URI"; 125 default: 126 return "ATT err"; 127 } 128 } 129 bt_tbs_technology_str(uint8_t status)130static inline const char *bt_tbs_technology_str(uint8_t status) 131 { 132 switch (status) { 133 case BT_TBS_TECHNOLOGY_3G: 134 return "3G"; 135 case BT_TBS_TECHNOLOGY_4G: 136 return "4G"; 137 case BT_TBS_TECHNOLOGY_LTE: 138 return "LTE"; 139 case BT_TBS_TECHNOLOGY_WIFI: 140 return "WIFI"; 141 case BT_TBS_TECHNOLOGY_5G: 142 return "5G"; 143 case BT_TBS_TECHNOLOGY_GSM: 144 return "GSM"; 145 case BT_TBS_TECHNOLOGY_CDMA: 146 return "CDMA"; 147 case BT_TBS_TECHNOLOGY_2G: 148 return "2G"; 149 case BT_TBS_TECHNOLOGY_WCDMA: 150 return "WCDMA"; 151 default: 152 return "unknown technology"; 153 } 154 } 155 bt_tbs_term_reason_str(uint8_t reason)156static inline const char *bt_tbs_term_reason_str(uint8_t reason) 157 { 158 switch (reason) { 159 case BT_TBS_REASON_BAD_REMOTE_URI: 160 return "bad remote URI"; 161 case BT_TBS_REASON_CALL_FAILED: 162 return "call failed"; 163 case BT_TBS_REASON_REMOTE_ENDED_CALL: 164 return "remote ended call"; 165 case BT_TBS_REASON_SERVER_ENDED_CALL: 166 return "server ended call"; 167 case BT_TBS_REASON_LINE_BUSY: 168 return "line busy"; 169 case BT_TBS_REASON_NETWORK_CONGESTED: 170 return "network congested"; 171 case BT_TBS_REASON_CLIENT_TERMINATED: 172 return "client terminated"; 173 case BT_TBS_REASON_UNSPECIFIED: 174 return "unspecified"; 175 default: 176 return "unknown reason"; 177 } 178 } 179 180 /** 181 * @brief Checks if @p uri contains a colon (':') followed by a printable 182 * character. Minimal uri is "a:b". 183 * 184 * @param uri The uri "scheme:id" 185 * @param len The length of uri 186 * @return true If the above is true 187 * @return false If the above is not true 188 */ bt_tbs_valid_uri(const uint8_t * uri,size_t uri_len)189static inline bool bt_tbs_valid_uri(const uint8_t *uri, size_t uri_len) 190 { 191 if (!uri) { 192 return false; 193 } 194 195 if (uri_len > CONFIG_BT_TBS_MAX_URI_LENGTH || uri_len < BT_TBS_MIN_URI_LEN) { 196 return false; 197 } else if (uri[0] < FIRST_PRINTABLE_ASCII_CHAR) { 198 /* Invalid first char */ 199 return false; 200 } 201 202 for (size_t i = 1; i < uri_len; i++) { 203 if (uri[i] == ':' && uri[i + 1] >= FIRST_PRINTABLE_ASCII_CHAR) { 204 return true; 205 } 206 } 207 208 return false; 209 } 210 211 /* TODO: The bt_tbs_call could use the bt_tbs_call_state struct for the first 212 * 3 fields 213 */ 214 struct bt_tbs_call { 215 uint8_t index; 216 uint8_t state; 217 uint8_t flags; 218 char remote_uri[CONFIG_BT_TBS_MAX_URI_LENGTH + 1]; 219 } __packed; 220 221 struct bt_tbs_call_state { 222 uint8_t index; 223 uint8_t state; 224 uint8_t flags; 225 } __packed; 226 227 struct bt_tbs_call_cp_acc { 228 uint8_t opcode; 229 uint8_t call_index; 230 } __packed; 231 232 struct bt_tbs_call_cp_term { 233 uint8_t opcode; 234 uint8_t call_index; 235 } __packed; 236 237 struct bt_tbs_call_cp_hold { 238 uint8_t opcode; 239 uint8_t call_index; 240 } __packed; 241 242 struct bt_tbs_call_cp_retrieve { 243 uint8_t opcode; 244 uint8_t call_index; 245 } __packed; 246 247 struct bt_tbs_call_cp_originate { 248 uint8_t opcode; 249 uint8_t uri[0]; 250 } __packed; 251 252 struct bt_tbs_call_cp_join { 253 uint8_t opcode; 254 uint8_t call_indexes[0]; 255 } __packed; 256 257 union bt_tbs_call_cp_t { 258 uint8_t opcode; 259 struct bt_tbs_call_cp_acc accept; 260 struct bt_tbs_call_cp_term terminate; 261 struct bt_tbs_call_cp_hold hold; 262 struct bt_tbs_call_cp_retrieve retrieve; 263 struct bt_tbs_call_cp_originate originate; 264 struct bt_tbs_call_cp_join join; 265 } __packed; 266 267 struct bt_tbs_call_cp_notify { 268 uint8_t opcode; 269 uint8_t call_index; 270 uint8_t status; 271 } __packed; 272 273 struct bt_tbs_call_state_notify { 274 uint8_t call_index; 275 uint8_t state; 276 } __packed; 277 278 struct bt_tbs_terminate_reason { 279 uint8_t call_index; 280 uint8_t reason; 281 } __packed; 282 283 struct bt_tbs_current_call_item { 284 uint8_t length; 285 uint8_t call_index; 286 uint8_t call_state; 287 uint8_t uri[CONFIG_BT_TBS_MAX_URI_LENGTH]; 288 } __packed; 289 290 struct bt_tbs_in_uri { 291 uint8_t call_index; 292 char uri[CONFIG_BT_TBS_MAX_URI_LENGTH + 1]; 293 } __packed; 294 295 #if defined(CONFIG_BT_TBS_CLIENT) 296 297 /* Features which may require long string reads */ 298 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) || \ 299 defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) || \ 300 defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) || \ 301 defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) || \ 302 defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) || \ 303 defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) || \ 304 defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) 305 #define BT_TBS_CLIENT_INST_READ_BUF_SIZE (BT_ATT_MAX_ATTRIBUTE_LEN + 1 /* NULL terminator*/) 306 #else 307 /* Need only be the size of call state reads which is the largest of the 308 * remaining characteristic values 309 */ 310 #define BT_TBS_CLIENT_INST_READ_BUF_SIZE \ 311 MIN(BT_ATT_MAX_ATTRIBUTE_LEN, \ 312 (CONFIG_BT_TBS_CLIENT_MAX_CALLS \ 313 * sizeof(struct bt_tbs_client_call_state))) 314 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */ 315 316 enum bt_tbs_client_flag { 317 BT_TBS_CLIENT_FLAG_BUSY, 318 319 BT_TBS_CLIENT_FLAG_NUM_FLAGS, /* keep as last */ 320 }; 321 322 struct bt_tbs_instance { 323 struct bt_tbs_client_call_state calls[CONFIG_BT_TBS_CLIENT_MAX_CALLS]; 324 325 uint16_t start_handle; 326 uint16_t end_handle; 327 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) 328 uint16_t bearer_uci_handle; 329 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */ 330 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) 331 uint16_t uri_list_handle; 332 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */ 333 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) \ 334 || defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) 335 uint16_t signal_interval_handle; 336 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */ 337 /* || defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */ 338 #if defined(CONFIG_BT_TBS_CLIENT_CCID) 339 uint16_t ccid_handle; 340 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */ 341 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) 342 uint16_t optional_opcodes_handle; 343 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */ 344 uint16_t termination_reason_handle; 345 346 #if defined(CONFIG_BT_TBS_CLIENT_CCID) 347 uint8_t ccid; 348 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */ 349 350 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) 351 struct bt_gatt_subscribe_params name_sub_params; 352 struct bt_gatt_discover_params name_sub_disc_params; 353 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */ 354 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) 355 struct bt_gatt_subscribe_params technology_sub_params; 356 struct bt_gatt_discover_params technology_sub_disc_params; 357 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */ 358 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) 359 struct bt_gatt_subscribe_params signal_strength_sub_params; 360 struct bt_gatt_discover_params signal_strength_sub_disc_params; 361 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */ 362 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) 363 struct bt_gatt_subscribe_params current_calls_sub_params; 364 struct bt_gatt_discover_params current_calls_sub_disc_params; 365 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */ 366 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) 367 struct bt_gatt_subscribe_params status_flags_sub_params; 368 struct bt_gatt_discover_params status_sub_disc_params; 369 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */ 370 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) 371 struct bt_gatt_subscribe_params in_target_uri_sub_params; 372 struct bt_gatt_discover_params in_target_uri_sub_disc_params; 373 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */ 374 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) 375 struct bt_gatt_subscribe_params call_cp_sub_params; 376 struct bt_gatt_discover_params call_cp_sub_disc_params; 377 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */ 378 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) 379 struct bt_gatt_subscribe_params friendly_name_sub_params; 380 struct bt_gatt_discover_params friendly_name_sub_disc_params; 381 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */ 382 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) 383 struct bt_gatt_subscribe_params incoming_call_sub_params; 384 struct bt_gatt_discover_params incoming_call_sub_disc_params; 385 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */ 386 struct bt_gatt_subscribe_params call_state_sub_params; 387 struct bt_gatt_discover_params call_state_sub_disc_params; 388 struct bt_gatt_subscribe_params termination_sub_params; 389 struct bt_gatt_discover_params termination_sub_disc_params; 390 struct bt_gatt_read_params read_params; 391 uint8_t read_buf[BT_TBS_CLIENT_INST_READ_BUF_SIZE]; 392 struct net_buf_simple net_buf; 393 394 ATOMIC_DEFINE(flags, BT_TBS_CLIENT_FLAG_NUM_FLAGS); 395 }; 396 #endif /* CONFIG_BT_TBS_CLIENT */ 397