1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6 #include <sys/socket.h> 7 #include <syslog.h> 8 9 #include "cras_bt_device.h" 10 #include "cras_telephony.h" 11 #include "cras_hfp_ag_profile.h" 12 #include "cras_hfp_slc.h" 13 #include "cras_system_state.h" 14 15 #define SLC_BUF_SIZE_BYTES 256 16 17 /* Indicator update command response and indicator indices. 18 * Note that indicator index starts from '1'. 19 */ 20 #define BATTERY_IND_INDEX 1 21 #define SIGNAL_IND_INDEX 2 22 #define SERVICE_IND_INDEX 3 23 #define CALL_IND_INDEX 4 24 #define CALLSETUP_IND_INDEX 5 25 #define CALLHELD_IND_INDEX 6 26 #define INDICATOR_UPDATE_RSP \ 27 "+CIND: " \ 28 "(\"battchg\",(0-5))," \ 29 "(\"signal\",(0-5))," \ 30 "(\"service\",(0,1))," \ 31 "(\"call\",(0,1))," \ 32 "(\"callsetup\",(0-3))," \ 33 "(\"callheld\",(0-2))," \ 34 "(\"roam\",(0,1))" \ 35 "" 36 /* Mode values for standard event reporting activation/deactivation AT 37 * command AT+CMER. Used for indicator events reporting in HFP. */ 38 #define FORWARD_UNSOLICIT_RESULT_CODE 3 39 40 /* Handle object to hold required info to initialize and maintain 41 * an HFP service level connection. 42 * Args: 43 * buf - Buffer hold received commands. 44 * buf_read_idx - Read index for buf. 45 * buf_write_idx - Write index for buf. 46 * rfcomm_fd - File descriptor for the established RFCOMM connection. 47 * init_cb - Callback to be triggered when an SLC is initialized. 48 * initialized - The service level connection is fully initilized of not. 49 * cli_active - Calling line identification notification is enabled or not. 50 * battery - Current battery level of AG stored in SLC. 51 * signal - Current signal strength of AG stored in SLC. 52 * service - Current service availability of AG stored in SLC. 53 * callheld - Current callheld status of AG stored in SLC. 54 * ind_event_report - Activate status of indicator events reporting. 55 * telephony - A reference of current telephony handle. 56 * device - The associated bt device. 57 */ 58 struct hfp_slc_handle { 59 char buf[SLC_BUF_SIZE_BYTES]; 60 int buf_read_idx; 61 int buf_write_idx; 62 63 int is_hsp; 64 int rfcomm_fd; 65 hfp_slc_init_cb init_cb; 66 hfp_slc_disconnect_cb disconnect_cb; 67 int initialized; 68 int cli_active; 69 int battery; 70 int signal; 71 int service; 72 int callheld; 73 int ind_event_report; 74 struct cras_bt_device *device; 75 76 struct cras_telephony_handle *telephony; 77 }; 78 79 /* AT command exchanges between AG(Audio gateway) and HF(Hands-free device) */ 80 struct at_command { 81 const char *cmd; 82 int (*callback) (struct hfp_slc_handle *handle, const char *cmd); 83 }; 84 85 /* Sends a response or command to HF */ 86 static int hfp_send(struct hfp_slc_handle *handle, const char *buf) 87 { 88 int written, err, len; 89 90 if (handle->rfcomm_fd < 0) 91 return -EIO; 92 93 /* Message start and end with "\r\n". refer to spec 4.33. */ 94 err = write(handle->rfcomm_fd, "\r\n", 2); 95 if (err < 0) 96 return -errno; 97 98 len = strlen(buf); 99 written = 0; 100 while (written < len) { 101 err = write(handle->rfcomm_fd, 102 buf + written, len - written); 103 if (err < 0) 104 return -errno; 105 written += err; 106 } 107 108 err = write(handle->rfcomm_fd, "\r\n", 2); 109 if (err < 0) 110 return -errno; 111 112 return 0; 113 } 114 115 /* Sends a response for indicator event reporting. */ 116 static int hfp_send_ind_event_report(struct hfp_slc_handle *handle, 117 int ind_index, 118 int value) 119 { 120 char cmd[64]; 121 122 if (handle->is_hsp || !handle->ind_event_report) 123 return 0; 124 125 snprintf(cmd, 64, "+CIEV: %d,%d", ind_index, value); 126 return hfp_send(handle, cmd); 127 } 128 129 /* Sends calling line identification unsolicited result code and 130 * standard call waiting notification. */ 131 static int hfp_send_calling_line_identification(struct hfp_slc_handle *handle, 132 const char *number, 133 int type) 134 { 135 char cmd[64]; 136 137 if (handle->is_hsp) 138 return 0; 139 140 if (handle->telephony->call) { 141 snprintf(cmd, 64, "+CCWA: \"%s\",%d", number, type); 142 } else { 143 snprintf(cmd, 64, "+CLIP: \"%s\",%d", number, type); 144 } 145 return hfp_send(handle, cmd); 146 } 147 148 /* ATA command to accept an incoming call. Mandatory support per spec 4.13. */ 149 static int answer_call(struct hfp_slc_handle *handle, const char *cmd) 150 { 151 int rc; 152 rc = hfp_send(handle, "OK"); 153 if (rc) 154 return rc; 155 156 return cras_telephony_event_answer_call(); 157 } 158 159 /* AT+CCWA command to enable the "Call Waiting notification" function. 160 * Mandatory support per spec 4.21. */ 161 static int call_waiting_notify(struct hfp_slc_handle *handle, const char *buf) 162 { 163 return hfp_send(handle, "OK"); 164 } 165 166 /* AT+CLIP command to enable the "Calling Line Identification notification" 167 * function. Mandatory per spec 4.23. 168 */ 169 static int cli_notification(struct hfp_slc_handle *handle, const char *cmd) 170 { 171 handle->cli_active = (cmd[8] == '1'); 172 return hfp_send(handle, "OK"); 173 } 174 175 /* ATDdd...dd command to place call with supplied number, or ATD>nnn... 176 * command to dial the number stored at memory location. Mandatory per 177 * spec 4.18 and 4.19. 178 */ 179 static int dial_number(struct hfp_slc_handle *handle, const char *cmd) 180 { 181 int rc, cmd_len; 182 183 cmd_len = strlen(cmd); 184 185 if (cmd[3] == '>') { 186 /* Handle memory dial. Extract memory location from command 187 * ATD>nnn...; and lookup. */ 188 int memory_location; 189 memory_location = strtol(cmd + 4, NULL, 0); 190 if (handle->telephony->dial_number == NULL || memory_location != 1) 191 return hfp_send(handle, "ERROR"); 192 } 193 else { 194 /* ATDddddd; Store dial number to the only memory slot. */ 195 cras_telephony_store_dial_number(cmd_len - 3 - 1, cmd + 3); 196 } 197 198 rc = hfp_send(handle, "OK"); 199 if (rc) 200 return rc; 201 202 handle->telephony->callsetup = 2; 203 return hfp_send_ind_event_report(handle, CALLSETUP_IND_INDEX, 2); 204 } 205 206 /* AT+VTS command to generate a DTMF code. Mandatory per spec 4.27. */ 207 static int dtmf_tone(struct hfp_slc_handle *handle, const char *buf) 208 { 209 return hfp_send(handle, "OK"); 210 } 211 212 /* AT+CMER command enables the registration status update function in AG. 213 * The service level connection is consider initialized when successfully 214 * responded OK to the AT+CMER command. Mandatory support per spec 4.4. 215 */ 216 static int event_reporting(struct hfp_slc_handle *handle, const char *cmd) 217 { 218 char *tokens, *mode, *tmp; 219 int err = 0; 220 221 /* AT+CMER=[<mode>[,<keyp>[,<disp>[,<ind> [,<bfr>]]]]] 222 * Parse <ind>, the only token we care about. 223 */ 224 tokens = strdup(cmd); 225 strtok(tokens, "="); 226 227 mode = strtok(NULL, ","); 228 tmp = strtok(NULL, ","); 229 tmp = strtok(NULL, ","); 230 tmp = strtok(NULL, ","); 231 232 /* mode = 3 for forward unsolicited result codes. 233 * AT+CMER=3,0,0,1 activates “indicator events reporting”. 234 * The service level connection is considered established after 235 * successfully responded with OK, regardless of the indicator 236 * events reporting status. 237 */ 238 if (!mode || !tmp) { 239 syslog(LOG_ERR, "Invalid event reporting” cmd %s", cmd); 240 err = -EINVAL; 241 goto event_reporting_err; 242 } 243 if (atoi(mode) == FORWARD_UNSOLICIT_RESULT_CODE) 244 handle->ind_event_report = atoi(tmp); 245 246 err = hfp_send(handle, "OK"); 247 if (err) { 248 syslog(LOG_ERR, "Error sending response for command %s", cmd); 249 goto event_reporting_err; 250 } 251 252 /* Consider the Service Level Connection to be fully initialized, 253 * and thereby established, after successfully responded with OK. 254 */ 255 if (!handle->initialized) { 256 handle->initialized = 1; 257 if (handle->init_cb) 258 handle->init_cb(handle); 259 } 260 261 event_reporting_err: 262 free(tokens); 263 return err; 264 } 265 266 /* AT+CMEE command to set the "Extended Audio Gateway Error Result Code". 267 * Mandatory per spec 4.9. 268 */ 269 static int extended_errors(struct hfp_slc_handle *handle, const char *buf) 270 { 271 return hfp_send(handle, "OK"); 272 } 273 274 /* AT+CKPD command to handle the user initiated action from headset profile 275 * device. 276 */ 277 static int key_press(struct hfp_slc_handle *handle, const char *buf) 278 { 279 hfp_send(handle, "OK"); 280 281 /* Release the call and connection. */ 282 if (handle->telephony->call || handle->telephony->callsetup) { 283 cras_telephony_event_terminate_call(); 284 handle->disconnect_cb(handle); 285 return -EIO; 286 } 287 return 0; 288 } 289 290 /* AT+BLDN command to re-dial the last number. Mandatory support 291 * per spec 4.20. 292 */ 293 static int last_dialed_number(struct hfp_slc_handle *handle, const char *buf) 294 { 295 int rc; 296 297 if (!handle->telephony->dial_number) 298 return hfp_send(handle, "ERROR"); 299 300 rc = hfp_send(handle, "OK"); 301 if (rc) 302 return rc; 303 304 handle->telephony->callsetup = 2; 305 return hfp_send_ind_event_report(handle, CALLSETUP_IND_INDEX, 2); 306 } 307 308 /* AT+CLCC command to query list of current calls. Mandatory support 309 * per spec 4.31. 310 * 311 * +CLCC: <idx>,<direction>,<status>,<mode>,<multiparty> 312 */ 313 static int list_current_calls(struct hfp_slc_handle *handle, const char *cmd) 314 { 315 char buf[64]; 316 317 int idx = 1; 318 int rc; 319 /* Fake the call list base on callheld and call status 320 * since we have no API exposed to manage call list. 321 * This is a hack to pass qualification test which ask us to 322 * handle the basic case that one call is active and 323 * the other is on hold. */ 324 if (handle->telephony->callheld) 325 { 326 snprintf(buf, 64, "+CLCC: %d,1,1,0,0", idx++); 327 rc = hfp_send(handle, buf); 328 if (rc) 329 return rc; 330 } 331 332 if (handle->telephony->call) 333 { 334 snprintf(buf, 64, "+CLCC: %d,1,0,0,0", idx++); 335 rc = hfp_send(handle, buf); 336 if (rc) 337 return rc; 338 } 339 340 return hfp_send(handle, "OK"); 341 } 342 343 /* AT+COPS command to query currently selected operator or set name format. 344 * Mandatory support per spec 4.8. 345 */ 346 static int operator_selection(struct hfp_slc_handle *handle, const char *buf) 347 { 348 int rc; 349 if (buf[7] == '?') 350 { 351 /* HF sends AT+COPS? command to find current network operator. 352 * AG responds with +COPS:<mode>,<format>,<operator>, where 353 * the mode=0 means automatic for network selection. If no 354 * operator is selected, <format> and <operator> are omitted. 355 */ 356 rc = hfp_send(handle, "+COPS: 0"); 357 if (rc) 358 return rc; 359 } 360 return hfp_send(handle, "OK"); 361 } 362 363 /* AT+CIND command retrieves the supported indicator and its corresponding 364 * range and order index or read current status of indicators. Mandatory 365 * support per spec 4.2. 366 */ 367 static int report_indicators(struct hfp_slc_handle *handle, const char *cmd) 368 { 369 int err; 370 char buf[64]; 371 372 if (cmd[7] == '=') { 373 /* Indicator update test command "AT+CIND=?" */ 374 err = hfp_send(handle, INDICATOR_UPDATE_RSP); 375 } else { 376 /* Indicator update read command "AT+CIND?". 377 * Respond with current status of AG indicators, 378 * the values must be listed in the indicator order declared 379 * in INDICATOR_UPDATE_RSP. 380 * +CIND: <signal>,<service>,<call>, 381 * <callsetup>,<callheld>,<roam> 382 */ 383 snprintf(buf, 64, "+CIND: %d,%d,%d,%d,%d,%d,0", 384 handle->battery, 385 handle->signal, 386 handle->service, 387 handle->telephony->call, 388 handle->telephony->callsetup, 389 handle->telephony->callheld 390 ); 391 err = hfp_send(handle, buf); 392 } 393 394 if (err < 0) 395 return err; 396 397 return hfp_send(handle, "OK"); 398 } 399 400 /* AT+BIA command to change the subset of indicators that shall be 401 * sent by the AG. It is okay to ignore this command here since we 402 * don't do event reporting(CMER). 403 */ 404 static int indicator_activation(struct hfp_slc_handle *handle, const char *cmd) 405 { 406 /* AT+BIA=[[<indrep 1>][,[<indrep 2>][,...[,[<indrep n>]]]]] */ 407 syslog(LOG_ERR, "Bluetooth indicator activation command %s", cmd); 408 return hfp_send(handle, "OK"); 409 } 410 411 /* AT+VGM and AT+VGS command reports the current mic and speaker gain 412 * level respectively. Optional support per spec 4.28. 413 */ 414 static int signal_gain_setting(struct hfp_slc_handle *handle, 415 const char *cmd) 416 { 417 int gain; 418 419 if (strlen(cmd) < 8) { 420 syslog(LOG_ERR, "Invalid gain setting command %s", cmd); 421 return -EINVAL; 422 } 423 424 /* Map 0 to the smallest non-zero scale 6/100, and 15 to 425 * 100/100 full. */ 426 if (cmd[5] == 'S') { 427 gain = atoi(&cmd[7]); 428 cras_bt_device_update_hardware_volume(handle->device, 429 (gain + 1) * 100 / 16); 430 } 431 432 return hfp_send(handle, "OK"); 433 } 434 435 /* AT+CNUM command to query the subscriber number. Mandatory support 436 * per spec 4.30. 437 */ 438 static int subscriber_number(struct hfp_slc_handle *handle, const char *buf) 439 { 440 return hfp_send(handle, "OK"); 441 } 442 443 /* AT+BRSF command notifies the HF(Hands-free device) supported features 444 * and retrieves the AG(Audio gateway) supported features. Mandatory 445 * support per spec 4.2. 446 */ 447 static int supported_features(struct hfp_slc_handle *handle, const char *cmd) 448 { 449 int err; 450 char response[128]; 451 if (strlen(cmd) < 9) 452 return -EINVAL; 453 454 /* AT+BRSF=<feature> command received, ignore the HF supported feature 455 * for now. Respond with +BRSF:<feature> to notify mandatory supported 456 * features in AG(audio gateway). 457 */ 458 snprintf(response, 128, "+BRSF: %u", HFP_SUPPORTED_FEATURE); 459 err = hfp_send(handle, response); 460 if (err < 0) 461 return err; 462 463 return hfp_send(handle, "OK"); 464 } 465 466 int hfp_event_speaker_gain(struct hfp_slc_handle *handle, int gain) 467 { 468 char command[128]; 469 470 /* Normailize gain value to 0-15 */ 471 gain = gain * 15 / 100; 472 snprintf(command, 128, "+VGS=%d", gain); 473 474 return hfp_send(handle, command); 475 } 476 477 /* AT+CHUP command to terminate current call. Mandatory support 478 * per spec 4.15. 479 */ 480 static int terminate_call(struct hfp_slc_handle *handle, const char *cmd) 481 { 482 int rc; 483 rc = hfp_send(handle, "OK"); 484 if (rc) 485 return rc; 486 487 return cras_telephony_event_terminate_call(); 488 } 489 490 /* AT commands to support in order to conform HFP specification. 491 * 492 * An initialized service level connection is the pre-condition for all 493 * call related procedures. Note that for the call related commands, 494 * we are good to just respond with a dummy "OK". 495 * 496 * The procedure to establish a service level connection is described below: 497 * 498 * 1. HF notifies AG about its own supported features and AG responds 499 * with its supported feature. 500 * 501 * HF(hands-free) AG(audio gateway) 502 * AT+BRSF=<HF supported feature> --> 503 * <-- +BRSF:<AG supported feature> 504 * <-- OK 505 * 506 * 2. HF retrieves the information about the indicators supported in AG. 507 * 508 * HF(hands-free) AG(audio gateway) 509 * AT+CIND=? --> 510 * <-- +CIND:... 511 * <-- OK 512 * 513 * 3. The HF requests the current status of the indicators in AG. 514 * 515 * HF(hands-free) AG(audio gateway) 516 * AT+CIND --> 517 * <-- +CIND:... 518 * <-- OK 519 * 520 * 4. HF requests enabling indicator status update in the AG. 521 * 522 * HF(hands-free) AG(audio gateway) 523 * AT+CMER= --> 524 * <-- OK 525 */ 526 static struct at_command at_commands[] = { 527 { "ATA", answer_call }, 528 { "ATD", dial_number }, 529 { "AT+BIA", indicator_activation }, 530 { "AT+BLDN", last_dialed_number }, 531 { "AT+BRSF", supported_features }, 532 { "AT+CCWA", call_waiting_notify }, 533 { "AT+CHUP", terminate_call }, 534 { "AT+CIND", report_indicators }, 535 { "AT+CKPD", key_press }, 536 { "AT+CLCC", list_current_calls }, 537 { "AT+CLIP", cli_notification }, 538 { "AT+CMEE", extended_errors }, 539 { "AT+CMER", event_reporting }, 540 { "AT+CNUM", subscriber_number }, 541 { "AT+COPS", operator_selection }, 542 { "AT+VG", signal_gain_setting }, 543 { "AT+VTS", dtmf_tone }, 544 { 0 } 545 }; 546 547 static int handle_at_command(struct hfp_slc_handle *slc_handle, 548 const char *cmd) { 549 struct at_command *atc; 550 551 for (atc = at_commands; atc->cmd; atc++) 552 if (!strncmp(cmd, atc->cmd, strlen(atc->cmd))) 553 return atc->callback(slc_handle, cmd); 554 555 syslog(LOG_ERR, "AT command %s not supported", cmd); 556 return hfp_send(slc_handle, "ERROR"); 557 } 558 559 static void slc_watch_callback(void *arg) 560 { 561 struct hfp_slc_handle *handle = (struct hfp_slc_handle *)arg; 562 ssize_t bytes_read; 563 int err; 564 565 bytes_read = read(handle->rfcomm_fd, 566 &handle->buf[handle->buf_write_idx], 567 SLC_BUF_SIZE_BYTES - handle->buf_write_idx - 1); 568 if (bytes_read < 0) { 569 syslog(LOG_ERR, "Error reading slc command %s", 570 strerror(errno)); 571 handle->disconnect_cb(handle); 572 return; 573 } 574 handle->buf_write_idx += bytes_read; 575 handle->buf[handle->buf_write_idx] = '\0'; 576 577 while (handle->buf_read_idx != handle->buf_write_idx) { 578 char *end_char; 579 end_char = strchr(&handle->buf[handle->buf_read_idx], '\r'); 580 if (end_char == NULL) 581 break; 582 583 *end_char = '\0'; 584 err = handle_at_command(handle, 585 &handle->buf[handle->buf_read_idx]); 586 if (err < 0) 587 return; 588 589 /* Shift the read index */ 590 handle->buf_read_idx = 1 + end_char - handle->buf; 591 if (handle->buf_read_idx == handle->buf_write_idx) { 592 handle->buf_read_idx = 0; 593 handle->buf_write_idx = 0; 594 } 595 } 596 597 /* Handle the case when buffer is full and no command found. */ 598 if (handle->buf_write_idx == SLC_BUF_SIZE_BYTES - 1) { 599 if (handle->buf_read_idx) { 600 memmove(handle->buf, 601 &handle->buf[handle->buf_read_idx], 602 handle->buf_write_idx - handle->buf_read_idx); 603 handle->buf_write_idx -= handle->buf_read_idx; 604 handle->buf_read_idx = 0; 605 } else { 606 syslog(LOG_ERR, 607 "Parse SLC command error, clean up buffer"); 608 handle->buf_write_idx = 0; 609 } 610 } 611 612 return; 613 } 614 615 /* Exported interfaces */ 616 617 struct hfp_slc_handle *hfp_slc_create(int fd, 618 int is_hsp, 619 struct cras_bt_device *device, 620 hfp_slc_init_cb init_cb, 621 hfp_slc_disconnect_cb disconnect_cb) 622 { 623 struct hfp_slc_handle *handle; 624 625 handle = (struct hfp_slc_handle*) calloc(1, sizeof(*handle)); 626 if (!handle) 627 return NULL; 628 629 handle->rfcomm_fd = fd; 630 handle->is_hsp = is_hsp; 631 handle->device = device; 632 handle->init_cb = init_cb; 633 handle->disconnect_cb = disconnect_cb; 634 handle->cli_active = 0; 635 handle->battery = 5; 636 handle->signal = 5; 637 handle->service = 1; 638 handle->ind_event_report = 0; 639 handle->telephony = cras_telephony_get(); 640 641 cras_system_add_select_fd(handle->rfcomm_fd, 642 slc_watch_callback, handle); 643 644 return handle; 645 } 646 647 void hfp_slc_destroy(struct hfp_slc_handle *slc_handle) 648 { 649 cras_system_rm_select_fd(slc_handle->rfcomm_fd); 650 close(slc_handle->rfcomm_fd); 651 free(slc_handle); 652 } 653 654 int hfp_set_call_status(struct hfp_slc_handle *handle, int call) 655 { 656 int old_call = handle->telephony->call; 657 658 if (old_call == call) 659 return 0; 660 661 handle->telephony->call = call; 662 return hfp_event_update_call(handle); 663 } 664 665 /* Procedure to setup a call when AG sees incoming call. 666 * 667 * HF(hands-free) AG(audio gateway) 668 * <-- Incoming call 669 * <-- +CIEV: (callsetup = 1) 670 * <-- RING (ALERT) 671 */ 672 int hfp_event_incoming_call(struct hfp_slc_handle *handle, 673 const char *number, 674 int type) 675 { 676 int rc; 677 678 if (handle->is_hsp) 679 return 0; 680 681 if (handle->cli_active) { 682 rc = hfp_send_calling_line_identification(handle, number, type); 683 if (rc) 684 return rc; 685 } 686 687 if (handle->telephony->call) 688 return 0; 689 else 690 return hfp_send(handle, "RING"); 691 } 692 693 int hfp_event_update_call(struct hfp_slc_handle *handle) 694 { 695 return hfp_send_ind_event_report(handle, CALL_IND_INDEX, 696 handle->telephony->call); 697 } 698 699 int hfp_event_update_callsetup(struct hfp_slc_handle *handle) 700 { 701 return hfp_send_ind_event_report(handle, CALLSETUP_IND_INDEX, 702 handle->telephony->callsetup); 703 } 704 705 int hfp_event_update_callheld(struct hfp_slc_handle *handle) 706 { 707 return hfp_send_ind_event_report(handle, CALLHELD_IND_INDEX, 708 handle->telephony->callheld); 709 } 710 711 int hfp_event_set_battery(struct hfp_slc_handle *handle, int level) 712 { 713 handle->battery = level; 714 return hfp_send_ind_event_report(handle, BATTERY_IND_INDEX, level); 715 } 716 717 int hfp_event_set_signal(struct hfp_slc_handle *handle, int level) 718 { 719 handle->signal = level; 720 return hfp_send_ind_event_report(handle, SIGNAL_IND_INDEX, level); 721 } 722 723 int hfp_event_set_service(struct hfp_slc_handle *handle, int avail) 724 { 725 /* Convert to 0 or 1. 726 * Since the value must be either 1 or 0. (service presence or not) */ 727 handle->service = !!avail; 728 return hfp_send_ind_event_report(handle, SERVICE_IND_INDEX, avail); 729 } 730