1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 // ***************************************************************************** 39 // 40 // HFG HF state machine tests 41 // 42 // ***************************************************************************** 43 44 #include "btstack_config.h" 45 46 #include <stdint.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 51 #include "CppUTest/TestHarness.h" 52 #include "CppUTest/CommandLineTestRunner.h" 53 54 #include "hci_cmd.h" 55 #include "btstack_run_loop.h" 56 #include "classic/sdp_util.h" 57 58 #include "hci.h" 59 #include "l2cap.h" 60 #include "classic/rfcomm.h" 61 #include "classic/sdp_server.h" 62 #include "btstack_debug.h" 63 #include "classic/hfp_hf.h" 64 65 #include "mock.h" 66 #include "test_sequences.h" 67 #include "btstack.h" 68 69 const uint8_t rfcomm_channel_nr = 1; 70 71 static bd_addr_t device_addr = {0xD8,0xBb,0x2C,0xDf,0xF1,0x08}; 72 73 static uint8_t codecs[2] = {1,2}; 74 static uint16_t indicators[1] = {0x01}; 75 76 static uint8_t service_level_connection_established = 0; 77 static uint8_t audio_connection_established = 0; 78 static uint8_t start_ringing = 0; 79 static uint8_t stop_ringing = 0; 80 static uint8_t call_termiated = 0; 81 82 static int supported_features_with_codec_negotiation = 438; 83 84 static uint16_t acl_handle = -1; 85 86 static char * get_next_hfp_hf_command(void){ 87 return get_next_hfp_command(0,2); 88 } 89 90 static int has_more_hfp_hf_commands(void){ 91 return has_more_hfp_commands(0,2); 92 } 93 94 static void user_command(char cmd){ 95 switch (cmd){ 96 case '#': 97 case '-': 98 case '+': 99 case '*': 100 printf("DTMF Code: %c\n", cmd); 101 hfp_hf_send_dtmf_code(acl_handle, cmd); 102 break; 103 case 'a': 104 printf("Establish Service level connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr)); 105 hfp_hf_establish_service_level_connection(device_addr); 106 break; 107 case 'A': 108 printf("Release Service level connection.\n"); 109 hfp_hf_release_service_level_connection(acl_handle); 110 break; 111 case 'b': 112 printf("Establish Audio connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr)); 113 hfp_hf_establish_audio_connection(acl_handle); 114 break; 115 case 'B': 116 printf("Release Audio service level connection.\n"); 117 hfp_hf_release_audio_connection(acl_handle); 118 break; 119 case 'C': 120 printf("Enable registration status update for all AG indicators.\n"); 121 hfp_hf_enable_status_update_for_all_ag_indicators(acl_handle); 122 case 'c': 123 printf("Disable registration status update for all AG indicators.\n"); 124 hfp_hf_disable_status_update_for_all_ag_indicators(acl_handle); 125 break; 126 case 'D': 127 printf("Set HFP AG registration status update for individual indicators (0111111).\n"); 128 hfp_hf_set_status_update_for_individual_ag_indicators(acl_handle, 63); 129 break; 130 case 'd': 131 printf("Query network operator.\n"); 132 hfp_hf_query_operator_selection(acl_handle); 133 break; 134 case 'E': 135 printf("Enable reporting of the extended AG error result code.\n"); 136 hfp_hf_enable_report_extended_audio_gateway_error_result_code(acl_handle); 137 break; 138 case 'e': 139 printf("Disable reporting of the extended AG error result code.\n"); 140 hfp_hf_disable_report_extended_audio_gateway_error_result_code(acl_handle); 141 break; 142 case 'f': 143 printf("Answer incoming call.\n"); 144 hfp_hf_answer_incoming_call(acl_handle); 145 break; 146 case 'F': 147 printf("Hangup call.\n"); 148 hfp_hf_terminate_call(acl_handle); 149 break; 150 case 'G': 151 printf("Reject incoming call.\n"); 152 hfp_hf_reject_incoming_call(acl_handle); 153 break; 154 case 'g': 155 printf("Query operator.\n"); 156 hfp_hf_query_operator_selection(acl_handle); 157 break; 158 case 't': 159 printf("Terminate HCI connection.\n"); 160 gap_disconnect(acl_handle); 161 break; 162 case 'i': 163 printf("Dial 1234567\n"); 164 hfp_hf_dial_number(acl_handle, (char *)"1234567"); 165 break; 166 case 'I': 167 printf("Dial 7654321\n"); 168 hfp_hf_dial_number(acl_handle, (char *)"7654321"); 169 break; 170 case 'j': 171 printf("Dial #1\n"); 172 hfp_hf_dial_memory(acl_handle, 1); 173 break; 174 case 'J': 175 printf("Dial #99\n"); 176 hfp_hf_dial_memory(acl_handle, 99); 177 break; 178 case 'k': 179 printf("Deactivate call waiting notification\n"); 180 hfp_hf_deactivate_call_waiting_notification(acl_handle); 181 break; 182 case 'K': 183 printf("Activate call waiting notification\n"); 184 hfp_hf_activate_call_waiting_notification(acl_handle); 185 break; 186 case 'l': 187 printf("Deactivate calling line notification\n"); 188 hfp_hf_deactivate_calling_line_notification(acl_handle); 189 break; 190 case 'L': 191 printf("Activate calling line notification\n"); 192 hfp_hf_activate_calling_line_notification(acl_handle); 193 break; 194 case 'm': 195 printf("Deactivate echo canceling and noise reduction\n"); 196 hfp_hf_deactivate_echo_canceling_and_noise_reduction(acl_handle); 197 break; 198 case 'n': 199 printf("Deactivate voice recognition\n"); 200 hfp_hf_deactivate_voice_recognition(acl_handle); 201 break; 202 case 'N': 203 printf("Activate voice recognition\n"); 204 hfp_hf_activate_voice_recognition(acl_handle); 205 break; 206 case 'o': 207 printf("Set speaker gain to 0 (minimum)\n"); 208 hfp_hf_set_speaker_gain(acl_handle, 0); 209 break; 210 case 'O': 211 printf("Set speaker gain to 9 (default)\n"); 212 hfp_hf_set_speaker_gain(acl_handle, 9); 213 break; 214 case 'p': 215 printf("Set speaker gain to 12 (higher)\n"); 216 hfp_hf_set_speaker_gain(acl_handle, 12); 217 break; 218 case 'P': 219 printf("Set speaker gain to 15 (maximum)\n"); 220 hfp_hf_set_speaker_gain(acl_handle, 15); 221 break; 222 case 'q': 223 printf("Set microphone gain to 0\n"); 224 hfp_hf_set_microphone_gain(acl_handle, 0); 225 break; 226 case 'Q': 227 printf("Set microphone gain to 9\n"); 228 hfp_hf_set_microphone_gain(acl_handle, 9); 229 break; 230 case 's': 231 printf("Set microphone gain to 12\n"); 232 hfp_hf_set_microphone_gain(acl_handle, 12); 233 break; 234 case 'S': 235 printf("Set microphone gain to 15\n"); 236 hfp_hf_set_microphone_gain(acl_handle, 15); 237 break; 238 case 'u': 239 printf("Send 'user busy' (Three-Way Call 0)\n"); 240 hfp_hf_user_busy(acl_handle); 241 break; 242 case 'U': 243 printf("End active call and accept waiting/held call (Three-Way Call 1)\n"); 244 hfp_hf_end_active_and_accept_other(acl_handle); 245 break; 246 case 'v': 247 printf("Swap active call and hold/waiting call (Three-Way Call 2)\n"); 248 hfp_hf_swap_calls(acl_handle); 249 break; 250 case 'V': 251 printf("Join hold call (Three-Way Call 3)\n"); 252 hfp_hf_join_held_call(acl_handle); 253 break; 254 case 'w': 255 printf("Connect calls (Three-Way Call 4)\n"); 256 hfp_hf_connect_calls(acl_handle); 257 break; 258 case 'W': 259 printf("Redial\n"); 260 hfp_hf_redial_last_number(acl_handle); 261 break; 262 case 'x': 263 printf("Request phone number for voice tag\n"); 264 hfp_hf_request_phone_number_for_voice_tag(acl_handle); 265 break; 266 case 'X': 267 printf("Query current call status\n"); 268 hfp_hf_query_current_call_status(acl_handle); 269 break; 270 case 'y': 271 printf("Release call with index 2\n"); 272 hfp_hf_release_call_with_index(acl_handle, 2); 273 break; 274 case 'Y': 275 printf("Private consulation with call 2\n"); 276 hfp_hf_private_consultation_with_call(acl_handle, 2); 277 break; 278 case '[': 279 printf("Query Response and Hold status (RHH ?)\n"); 280 hfp_hf_rrh_query_status(acl_handle); 281 break; 282 case ']': 283 printf("Place call in a response and held state (RHH 0)\n"); 284 hfp_hf_rrh_hold_call(acl_handle); 285 break; 286 case '{': 287 printf("Accept held call (RHH 1)\n"); 288 hfp_hf_rrh_accept_held_call(acl_handle); 289 break; 290 case '}': 291 printf("Reject held call (RHH 2)\n"); 292 hfp_hf_rrh_reject_held_call(acl_handle); 293 break; 294 case '?': 295 printf("Query Subscriber Number\n"); 296 hfp_hf_query_subscriber_number(acl_handle); 297 break; 298 case '!': 299 printf("Update HF indicator with assigned number 1 (HFI)\n"); 300 hfp_hf_set_hf_indicator(acl_handle, 1, 1); 301 break; 302 default: 303 printf("HF: undefined user command\n"); 304 break; 305 } 306 } 307 308 static void simulate_test_sequence(hfp_test_item_t * test_item){ 309 char ** test_steps = test_item->test; 310 printf("\nSimulate test sequence: \"%s\" [%d steps]\n", test_item->name, test_item->len); 311 312 int i = 0; 313 int previous_step = -1; 314 while ( i < test_item->len){ 315 previous_step++; 316 CHECK_EQUAL(i >= previous_step, 1); 317 318 char * expected_cmd = test_steps[i]; 319 int expected_cmd_len = strlen(expected_cmd); 320 printf("\nStep %d, %s \n", i, expected_cmd); 321 322 if (strncmp(expected_cmd, "USER:", 5) == 0){ 323 user_command(expected_cmd[5]); 324 while (has_more_hfp_hf_commands()){ 325 // empty rfcomm payload buffer 326 get_next_hfp_hf_command(); 327 } 328 i++; 329 330 } else if (strncmp(expected_cmd, "AT+BAC=", 7) == 0){ 331 int parsed_codecs[2]; 332 uint8_t new_codecs[2]; 333 sscanf(&expected_cmd[7],"%d,%d", &parsed_codecs[0], &parsed_codecs[1]); 334 new_codecs[0] = parsed_codecs[0]; 335 new_codecs[1] = parsed_codecs[1]; 336 hfp_hf_init_codecs(2, (uint8_t*)new_codecs); 337 while (has_more_hfp_hf_commands()){ 338 // empty rfcomm payload buffer 339 get_next_hfp_hf_command(); 340 } 341 i++; 342 } else if (strncmp(expected_cmd, "AT+BRSF=", 8) == 0 ){ 343 int supported_features = 0; 344 sscanf(&expected_cmd[8],"%d", &supported_features); 345 printf("Call hfp_hf_init with SF %d\n", supported_features); 346 hfp_hf_release_service_level_connection(acl_handle); 347 348 hfp_hf_init_supported_features(supported_features); 349 350 user_command('a'); 351 while (has_more_hfp_hf_commands()){ 352 // empty rfcomm payload buffer 353 get_next_hfp_hf_command(); 354 } 355 i++; 356 } else if (strncmp(expected_cmd, "AT+BCC", 6) == 0){ 357 user_command('b'); 358 while (has_more_hfp_hf_commands()){ 359 // empty rfcomm payload buffer 360 get_next_hfp_hf_command(); 361 } 362 i++; 363 } else if (strncmp(expected_cmd, "AT", 2) == 0){ 364 printf("\n---> NEXT STEP expect from HF: %s\n", expected_cmd); 365 while (has_more_hfp_hf_commands()){ 366 char * ag_cmd = get_next_hfp_hf_command(); 367 printf("HF response verify %s == %s[%d]\n", expected_cmd, ag_cmd, expected_cmd_len); 368 369 int equal_cmds = strncmp(ag_cmd, expected_cmd, expected_cmd_len) == 0; 370 if (!equal_cmds){ 371 printf("\nError: Expected:'%s', but got:'%s'\n", expected_cmd, ag_cmd); 372 CHECK_EQUAL(equal_cmds,1); 373 return; 374 } 375 printf("Verified: '%s'\n", expected_cmd); 376 i++; 377 if (i < test_item->len){ 378 expected_cmd = test_steps[i]; 379 expected_cmd_len = strlen(expected_cmd); 380 } 381 } 382 } else { 383 //printf("\n---> NEXT STEP receive from AG: '%s'\n", expected_cmd); 384 inject_hfp_command_to_hf((uint8_t*)expected_cmd, strlen(expected_cmd)); 385 i++; 386 } 387 } 388 } 389 390 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ 391 if (event[0] != HCI_EVENT_HFP_META) return; 392 393 switch (event[2]) { 394 case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED: 395 printf("\n** SLC established **\n\n"); 396 acl_handle = hfp_subevent_service_level_connection_established_get_acl_handle(event); 397 service_level_connection_established = 1; 398 audio_connection_established = 0; 399 break; 400 case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED: 401 printf("\n** SLC released **\n\n"); 402 service_level_connection_established = 0; 403 break; 404 case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED: 405 printf("\n** AC established **\n\n"); 406 audio_connection_established = 1; 407 break; 408 case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED: 409 printf("\n** AC released **\n\n"); 410 audio_connection_established = 0; 411 break; 412 case HFP_SUBEVENT_START_RINGING: 413 printf("\n** Start ringing **\n\n"); 414 start_ringing = 1; 415 break; 416 case HFP_SUBEVENT_STOP_RINGING: 417 printf("\n** Stop ringing **\n\n"); 418 stop_ringing = 1; 419 start_ringing = 0; 420 break; 421 case HFP_SUBEVENT_CALL_TERMINATED: 422 call_termiated = 1; 423 break; 424 case HFP_SUBEVENT_COMPLETE: 425 printf("HFP AG HFP_SUBEVENT_COMPLETE.\n"); 426 break; 427 case HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED: 428 printf("AG_INDICATOR_STATUS_CHANGED, AG indicator (index: %d) to: %d of range [%d, %d], name '%s'\n", 429 hfp_subevent_ag_indicator_status_changed_get_indicator_index(event), 430 hfp_subevent_ag_indicator_status_changed_get_indicator_status(event), 431 hfp_subevent_ag_indicator_status_changed_get_indicator_min_range(event), 432 hfp_subevent_ag_indicator_status_changed_get_indicator_max_range(event), 433 (const char*) hfp_subevent_ag_indicator_status_changed_get_indicator_name(event)); 434 break; 435 case HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED: 436 printf("NETWORK_OPERATOR_CHANGED, operator mode: %d, format: %d, name: %s\n", 437 hfp_subevent_network_operator_changed_get_network_operator_mode(event), 438 hfp_subevent_network_operator_changed_get_network_operator_format(event), 439 (char *) hfp_subevent_network_operator_changed_get_network_operator_name(event)); 440 break; 441 case HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR: 442 printf("EXTENDED_AUDIO_GATEWAY_ERROR_REPORT, status : %d\n", 443 hfp_subevent_extended_audio_gateway_error_get_error(event)); 444 break; 445 case HFP_SUBEVENT_RING: 446 printf("** Ring **\n"); 447 break; 448 case HFP_SUBEVENT_NUMBER_FOR_VOICE_TAG: 449 printf("Phone number for voice tag: %s\n", 450 (const char *) hfp_subevent_number_for_voice_tag_get_number(event)); 451 break; 452 case HFP_SUBEVENT_SPEAKER_VOLUME: 453 printf("Speaker volume: gain %u\n", 454 hfp_subevent_speaker_volume_get_gain(event)); 455 break; 456 case HFP_SUBEVENT_MICROPHONE_VOLUME: 457 printf("Microphone volume: gain %u\n", 458 hfp_subevent_microphone_volume_get_gain(event)); 459 break; 460 case HFP_SUBEVENT_CALLING_LINE_IDENTIFICATION_NOTIFICATION: 461 printf("Caller ID, number %s\n", hfp_subevent_calling_line_identification_notification_get_number(event)); 462 break; 463 default: 464 printf("event not handled %u\n", event[2]); 465 break; 466 } 467 } 468 469 470 TEST_GROUP(HFPClient){ 471 472 void setup(void){ 473 service_level_connection_established = 0; 474 audio_connection_established = 0; 475 start_ringing = 0; 476 stop_ringing = 0; 477 call_termiated = 0; 478 479 hfp_hf_init(rfcomm_channel_nr); 480 hfp_hf_init_supported_features(supported_features_with_codec_negotiation); 481 hfp_hf_init_hf_indicators(sizeof(indicators)/sizeof(uint16_t), indicators); 482 483 hfp_hf_init_codecs(sizeof(codecs), codecs); 484 } 485 486 void teardown(void){ 487 hfp_hf_release_audio_connection(acl_handle); 488 hfp_hf_release_service_level_connection(acl_handle); 489 490 service_level_connection_established = 0; 491 audio_connection_established = 0; 492 } 493 }; 494 495 496 TEST(HFPClient, PTSRHHTests){ 497 for (int i = 0; i < hfp_pts_hf_rhh_tests_size(); i++){ 498 setup(); 499 simulate_test_sequence(&hfp_pts_hf_rhh_tests()[i]); 500 teardown(); 501 } 502 } 503 504 TEST(HFPClient, PTSECCTests){ 505 for (int i = 0; i < hfp_pts_hf_ecc_tests_size(); i++){ 506 setup(); 507 simulate_test_sequence(&hfp_pts_hf_ecc_tests()[i]); 508 teardown(); 509 } 510 } 511 512 TEST(HFPClient, PTSECSTests){ 513 for (int i = 0; i < hfp_pts_hf_ecs_tests_size(); i++){ 514 setup(); 515 simulate_test_sequence(&hfp_pts_hf_ecs_tests()[i]); 516 teardown(); 517 } 518 } 519 520 TEST(HFPClient, PTSTWCTests){ 521 for (int i = 0; i < hfp_pts_hf_twc_tests_size(); i++){ 522 setup(); 523 simulate_test_sequence(&hfp_pts_hf_twc_tests()[i]); 524 teardown(); 525 } 526 } 527 528 TEST(HFPClient, PTSATATests){ 529 for (int i = 0; i < hfp_pts_hf_ata_tests_size(); i++){ 530 setup(); 531 simulate_test_sequence(&hfp_pts_hf_ata_tests()[i]); 532 teardown(); 533 } 534 } 535 536 TEST(HFPClient, PTSSLCTests){ 537 for (int i = 0; i < hfp_pts_hf_slc_tests_size(); i++){ 538 setup(); 539 simulate_test_sequence(&hfp_pts_hf_slc_tests()[i]); 540 teardown(); 541 } 542 } 543 544 int main (int argc, const char * argv[]){ 545 hfp_hf_register_packet_handler(packet_handler); 546 return CommandLineTestRunner::RunAllTests(argc, argv); 547 } 548