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/types.h> 22 23 #define BT_TBS_MAX_UCI_SIZE 6 24 #define BT_TBS_MIN_URI_LEN 3 /* a:b */ 25 #define BT_TBS_FREE_CALL_INDEX 0 26 27 /* Call Control Point Opcodes */ 28 #define BT_TBS_CALL_OPCODE_ACCEPT 0x00 29 #define BT_TBS_CALL_OPCODE_TERMINATE 0x01 30 #define BT_TBS_CALL_OPCODE_HOLD 0x02 31 #define BT_TBS_CALL_OPCODE_RETRIEVE 0x03 32 #define BT_TBS_CALL_OPCODE_ORIGINATE 0x04 33 #define BT_TBS_CALL_OPCODE_JOIN 0x05 34 35 /* Local Control Points - Used to do local control operations but still being 36 * able to determine if it is a local or remote operation 37 */ 38 #define BT_TBS_LOCAL_OPCODE_ANSWER 0x80 39 #define BT_TBS_LOCAL_OPCODE_HOLD 0x81 40 #define BT_TBS_LOCAL_OPCODE_RETRIEVE 0x82 41 #define BT_TBS_LOCAL_OPCODE_TERMINATE 0x83 42 #define BT_TBS_LOCAL_OPCODE_INCOMING 0x84 43 #define BT_TBS_LOCAL_OPCODE_SERVER_TERMINATE 0x85 44 45 #define FIRST_PRINTABLE_ASCII_CHAR ' ' /* space */ 46 47 #define BT_TBS_CALL_FLAG_SET_INCOMING(flag) (flag &= ~BT_TBS_CALL_FLAG_OUTGOING) 48 #define BT_TBS_CALL_FLAG_SET_OUTGOING(flag) (flag |= BT_TBS_CALL_FLAG_OUTGOING) 49 50 const char *parse_string_value(const void *data, uint16_t length, 51 uint16_t max_len); 52 bt_tbs_state_str(uint8_t state)53static inline const char *bt_tbs_state_str(uint8_t state) 54 { 55 switch (state) { 56 case BT_TBS_CALL_STATE_INCOMING: 57 return "incoming"; 58 case BT_TBS_CALL_STATE_DIALING: 59 return "dialing"; 60 case BT_TBS_CALL_STATE_ALERTING: 61 return "alerting"; 62 case BT_TBS_CALL_STATE_ACTIVE: 63 return "active"; 64 case BT_TBS_CALL_STATE_LOCALLY_HELD: 65 return "locally held"; 66 case BT_TBS_CALL_STATE_REMOTELY_HELD: 67 return "remote held"; 68 case BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD: 69 return "locally and remotely held"; 70 default: 71 return "unknown"; 72 } 73 } 74 bt_tbs_opcode_str(uint8_t opcode)75static inline const char *bt_tbs_opcode_str(uint8_t opcode) 76 { 77 switch (opcode) { 78 case BT_TBS_CALL_OPCODE_ACCEPT: 79 return "accept"; 80 case BT_TBS_CALL_OPCODE_TERMINATE: 81 return "terminate"; 82 case BT_TBS_CALL_OPCODE_HOLD: 83 return "hold"; 84 case BT_TBS_CALL_OPCODE_RETRIEVE: 85 return "retrieve"; 86 case BT_TBS_CALL_OPCODE_ORIGINATE: 87 return "originate"; 88 case BT_TBS_CALL_OPCODE_JOIN: 89 return "join"; 90 case BT_TBS_LOCAL_OPCODE_ANSWER: 91 return "remote answer"; 92 case BT_TBS_LOCAL_OPCODE_HOLD: 93 return "remote hold"; 94 case BT_TBS_LOCAL_OPCODE_RETRIEVE: 95 return "remote retrieve"; 96 case BT_TBS_LOCAL_OPCODE_TERMINATE: 97 return "remote terminate"; 98 case BT_TBS_LOCAL_OPCODE_INCOMING: 99 return "remote incoming"; 100 case BT_TBS_LOCAL_OPCODE_SERVER_TERMINATE: 101 return "server terminate"; 102 default: 103 return "unknown"; 104 } 105 } 106 bt_tbs_status_str(uint8_t status)107static inline const char *bt_tbs_status_str(uint8_t status) 108 { 109 switch (status) { 110 case BT_TBS_RESULT_CODE_SUCCESS: 111 return "success"; 112 case BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED: 113 return "opcode not supported"; 114 case BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE: 115 return "operation not possible"; 116 case BT_TBS_RESULT_CODE_INVALID_CALL_INDEX: 117 return "invalid call index"; 118 case BT_TBS_RESULT_CODE_STATE_MISMATCH: 119 return "state mismatch"; 120 case BT_TBS_RESULT_CODE_OUT_OF_RESOURCES: 121 return "out of resources"; 122 case BT_TBS_RESULT_CODE_INVALID_URI: 123 return "invalid URI"; 124 default: 125 return "ATT err"; 126 } 127 } 128 bt_tbs_technology_str(uint8_t status)129static inline const char *bt_tbs_technology_str(uint8_t status) 130 { 131 switch (status) { 132 case BT_TBS_TECHNOLOGY_3G: 133 return "3G"; 134 case BT_TBS_TECHNOLOGY_4G: 135 return "4G"; 136 case BT_TBS_TECHNOLOGY_LTE: 137 return "LTE"; 138 case BT_TBS_TECHNOLOGY_WIFI: 139 return "WIFI"; 140 case BT_TBS_TECHNOLOGY_5G: 141 return "5G"; 142 case BT_TBS_TECHNOLOGY_GSM: 143 return "GSM"; 144 case BT_TBS_TECHNOLOGY_CDMA: 145 return "CDMA"; 146 case BT_TBS_TECHNOLOGY_2G: 147 return "2G"; 148 case BT_TBS_TECHNOLOGY_WCDMA: 149 return "WCDMA"; 150 default: 151 return "unknown technology"; 152 } 153 } 154 bt_tbs_term_reason_str(uint8_t reason)155static inline const char *bt_tbs_term_reason_str(uint8_t reason) 156 { 157 switch (reason) { 158 case BT_TBS_REASON_BAD_REMOTE_URI: 159 return "bad remote URI"; 160 case BT_TBS_REASON_CALL_FAILED: 161 return "call failed"; 162 case BT_TBS_REASON_REMOTE_ENDED_CALL: 163 return "remote ended call"; 164 case BT_TBS_REASON_SERVER_ENDED_CALL: 165 return "server ended call"; 166 case BT_TBS_REASON_LINE_BUSY: 167 return "line busy"; 168 case BT_TBS_REASON_NETWORK_CONGESTED: 169 return "network congested"; 170 case BT_TBS_REASON_CLIENT_TERMINATED: 171 return "client terminated"; 172 case BT_TBS_REASON_UNSPECIFIED: 173 return "unspecified"; 174 default: 175 return "unknown reason"; 176 } 177 } 178 179 /** 180 * @brief Checks if a string contains a colon (':') followed by a printable 181 * character. Minimal uri is "a:b". 182 * 183 * @param uri The uri "scheme:id" 184 * @param len The length of uri 185 * @return true If the above is true 186 * @return false If the above is not true 187 */ bt_tbs_valid_uri(const char * uri,size_t len)188static inline bool bt_tbs_valid_uri(const char *uri, size_t len) 189 { 190 if (!uri) { 191 return false; 192 } 193 194 if (len > CONFIG_BT_TBS_MAX_URI_LENGTH || 195 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 (int i = 1; i < 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) 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 struct bt_tbs_instance { 317 struct bt_tbs_client_call_state calls[CONFIG_BT_TBS_CLIENT_MAX_CALLS]; 318 319 uint16_t start_handle; 320 uint16_t end_handle; 321 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) 322 uint16_t bearer_uci_handle; 323 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */ 324 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) 325 uint16_t uri_list_handle; 326 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */ 327 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) \ 328 || defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) 329 uint16_t signal_interval_handle; 330 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */ 331 /* || defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */ 332 #if defined(CONFIG_BT_TBS_CLIENT_CCID) 333 uint16_t ccid_handle; 334 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */ 335 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) 336 uint16_t optional_opcodes_handle; 337 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */ 338 uint16_t termination_reason_handle; 339 340 bool busy; 341 #if defined(CONFIG_BT_TBS_CLIENT_CCID) 342 uint8_t ccid; 343 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */ 344 345 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) 346 struct bt_gatt_subscribe_params name_sub_params; 347 struct bt_gatt_discover_params name_sub_disc_params; 348 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */ 349 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) 350 struct bt_gatt_subscribe_params technology_sub_params; 351 struct bt_gatt_discover_params technology_sub_disc_params; 352 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */ 353 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) 354 struct bt_gatt_subscribe_params signal_strength_sub_params; 355 struct bt_gatt_discover_params signal_strength_sub_disc_params; 356 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */ 357 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) 358 struct bt_gatt_subscribe_params current_calls_sub_params; 359 struct bt_gatt_discover_params current_calls_sub_disc_params; 360 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */ 361 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) 362 struct bt_gatt_subscribe_params status_flags_sub_params; 363 struct bt_gatt_discover_params status_sub_disc_params; 364 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */ 365 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) 366 struct bt_gatt_subscribe_params in_target_uri_sub_params; 367 struct bt_gatt_discover_params in_target_uri_sub_disc_params; 368 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */ 369 #if defined(CONFIG_BT_TBS_CLIENT_CP_PROCEDURES) 370 struct bt_gatt_subscribe_params call_cp_sub_params; 371 struct bt_gatt_discover_params call_cp_sub_disc_params; 372 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */ 373 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) 374 struct bt_gatt_subscribe_params friendly_name_sub_params; 375 struct bt_gatt_discover_params friendly_name_sub_disc_params; 376 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */ 377 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) 378 struct bt_gatt_subscribe_params incoming_call_sub_params; 379 struct bt_gatt_discover_params incoming_call_sub_disc_params; 380 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */ 381 struct bt_gatt_subscribe_params call_state_sub_params; 382 struct bt_gatt_discover_params call_state_sub_disc_params; 383 struct bt_gatt_subscribe_params termination_sub_params; 384 struct bt_gatt_discover_params termination_sub_disc_params; 385 struct bt_gatt_read_params read_params; 386 uint8_t read_buf[BT_TBS_CLIENT_INST_READ_BUF_SIZE]; 387 struct net_buf_simple net_buf; 388 }; 389 #endif /* CONFIG_BT_TBS_CLIENT */ 390