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