xref: /btstack/test/hfp/hfp_ag_client_test.cpp (revision 1d3bd1e51ca491d6783233c8d7431c44f06daa5a)
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 AG 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 
55 #include "btstack_debug.h"
56 #include "btstack_event.h"
57 #include "btstack_run_loop.h"
58 #include "classic/hfp_ag.h"
59 #include "classic/rfcomm.h"
60 #include "classic/sdp_server.h"
61 #include "classic/sdp_util.h"
62 #include "hci.h"
63 #include "hci_cmd.h"
64 #include "l2cap.h"
65 
66 #include "mock.h"
67 #include "test_sequences.h"
68 
69 static bd_addr_t pts_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46};
70 
71 const uint8_t    rfcomm_channel_nr = 1;
72 
73 static bd_addr_t device_addr = {0xD8,0xBb,0x2C,0xDf,0xF1,0x08};
74 
75 static uint8_t codecs[2] = {1, 3};
76 
77 static int ag_indicators_nr = 7;
78 static hfp_ag_indicator_t ag_indicators[] = {
79     // index, name, min range, max range, status, mandatory, enabled, status changed
80     {1, "service",   0, 1, 1, 0, 0, 0},
81     {2, "call",      0, 1, 0, 1, 1, 0},
82     {3, "callsetup", 0, 3, 0, 1, 1, 0},
83     {4, "battchg",   0, 5, 3, 0, 0, 0},
84     {5, "signal",    0, 5, 5, 0, 0, 0},
85     {6, "roam",      0, 1, 0, 0, 0, 0},
86     {7, "callheld",  0, 2, 0, 1, 1, 0}
87 };
88 
89 hfp_ag_indicator_t ag_indicators_temp[] = {
90     // index, name, min range, max range, status, mandatory, enabled, status changed
91     {1, "service",   0, 1, 1, 0, 0, 0},
92     {2, "call",      0, 1, 0, 1, 1, 0},
93     {3, "callsetup", 0, 3, 0, 1, 1, 0},
94     {4, "battchg",   0, 5, 3, 0, 0, 0},
95     {5, "signal",    0, 5, 5, 0, 0, 0},
96     {6, "roam",      0, 1, 0, 0, 0, 0},
97     {7, "callheld",  0, 2, 0, 1, 1, 0}
98 };
99 
100 static int supported_features_with_codec_negotiation = 4079;   // 0011 1110 1111
101 
102 static int call_hold_services_nr = 5;
103 static const char* call_hold_services[] = {"1", "1x", "2", "2x", "3"};
104 
105 static int hf_indicators_nr = 2;
106 static hfp_generic_status_indicator_t hf_indicators[] = {
107     {1, 1},
108     {2, 1},
109 };
110 
111 static hci_con_handle_t acl_handle = -1;
112 static int memory_1_enabled = 1;
113 
has_more_hfp_ag_commands(void)114 static int has_more_hfp_ag_commands(void){
115     return has_more_hfp_commands(2,2);
116 }
117 
get_next_hfp_ag_command(void)118 static char * get_next_hfp_ag_command(void){
119    return get_next_hfp_command(2,2);
120 }
121 
user_command(char cmd)122 static void user_command(char cmd){
123     switch (cmd){
124         case 'a':
125             memcpy(device_addr, pts_addr, 6);
126             printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
127             hfp_ag_establish_service_level_connection(device_addr);
128             break;
129         case 'A':
130             printf("Release HFP service level connection.\n");
131             hfp_ag_release_service_level_connection(acl_handle);
132             break;
133         case 'Z':
134             printf("Release HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
135             hfp_ag_release_service_level_connection(acl_handle);
136             break;
137         case 'b':
138             printf("Establish Audio connection %s...\n", bd_addr_to_str(device_addr));
139             hfp_ag_establish_audio_connection(acl_handle);
140             break;
141         case 'B':
142             printf("Release Audio connection.\n");
143             hfp_ag_release_audio_connection(acl_handle);
144             break;
145         case 'c':
146             printf("Simulate incoming call from 1234567\n");
147             hfp_ag_set_clip(129, "1234567");
148             hfp_ag_incoming_call();
149             break;
150         case 'm':
151             printf("Simulate incoming call from 7654321\n");
152             hfp_ag_set_clip(129, "7654321");
153             hfp_ag_incoming_call();
154             break;
155         case 'C':
156             printf("Simulate terminate call\n");
157             hfp_ag_call_dropped();
158             break;
159         case 'd':
160             printf("Report AG failure\n");
161             hfp_ag_report_extended_audio_gateway_error_result_code(acl_handle, HFP_CME_ERROR_AG_FAILURE);
162             break;
163         case 'e':
164             printf("Answer call on AG\n");
165             hfp_ag_answer_incoming_call();
166             break;
167         case 'E':
168             printf("Reject call on AG\n");
169             hfp_ag_terminate_call();
170             break;
171         case 'f':
172             printf("Disable cellular network\n");
173             hfp_ag_set_registration_status(0);
174             break;
175         case 'F':
176             printf("Enable cellular network\n");
177             hfp_ag_set_registration_status(1);
178             break;
179         case 'g':
180             printf("Set signal strength to 0\n");
181             hfp_ag_set_signal_strength(0);
182             break;
183         case 'G':
184             printf("Set signal strength to 5\n");
185             hfp_ag_set_signal_strength(5);
186             break;
187         case 'h':
188             printf("Disable roaming\n");
189             hfp_ag_set_roaming_status(0);
190             break;
191         case 'H':
192             printf("Enable roaming\n");
193             hfp_ag_set_roaming_status(1);
194             break;
195         case 'i':
196             printf("Set battery level to 3\n");
197             hfp_ag_set_battery_level(3);
198             break;
199         case 'I':
200             printf("Set battery level to 5\n");
201             hfp_ag_set_battery_level(5);
202             break;
203         case 'j':
204             printf("Answering call on remote side\n");
205             hfp_ag_outgoing_call_established();
206             break;
207         case 'r':
208             printf("Disable in-band ring tone\n");
209             hfp_ag_set_use_in_band_ring_tone(0);
210             break;
211         case 'k':
212             printf("Memory 1 cleared\n");
213             memory_1_enabled = 0;
214             break;
215         case 'K':
216             printf("Memory 1 set\n");
217             memory_1_enabled = 1;
218             break;
219         case 'l':
220             printf("Last dialed number cleared\n");
221             hfp_ag_clear_last_dialed_number();
222             break;
223         case 'L':
224             printf("Outgoing call connected, ringing\n");
225             hfp_ag_outgoing_call_ringing();
226             break;
227         case 'n':
228             printf("Disable Voice Recognition\n");
229             hfp_ag_deactivate_voice_recognition(acl_handle);
230             break;
231         case 'N':
232             printf("Enable Voice Recognition\n");
233             hfp_ag_activate_voice_recognition(acl_handle);
234             break;
235         case 'o':
236             printf("Set speaker gain to 0 (minimum)\n");
237             hfp_ag_set_speaker_gain(acl_handle, 0);
238             break;
239         case 'O':
240             printf("Set speaker gain to 9 (default)\n");
241             hfp_ag_set_speaker_gain(acl_handle, 9);
242             break;
243         case 'p':
244             printf("Set speaker gain to 12 (higher)\n");
245             hfp_ag_set_speaker_gain(acl_handle, 12);
246             break;
247         case 'P':
248             printf("Set speaker gain to 15 (maximum)\n");
249             hfp_ag_set_speaker_gain(acl_handle, 15);
250             break;
251         case 'q':
252             printf("Set microphone gain to 0\n");
253             hfp_ag_set_microphone_gain(acl_handle, 0);
254             break;
255         case 'Q':
256             printf("Set microphone gain to 9\n");
257             hfp_ag_set_microphone_gain(acl_handle, 9);
258             break;
259         case 's':
260             printf("Set microphone gain to 12\n");
261             hfp_ag_set_microphone_gain(acl_handle, 12);
262             break;
263         case 'S':
264             printf("Set microphone gain to 15\n");
265             hfp_ag_set_microphone_gain(acl_handle, 15);
266             break;
267         case 'R':
268             printf("Enable in-band ring tone\n");
269             hfp_ag_set_use_in_band_ring_tone(1);
270             break;
271         case 't':
272             printf("Terminate HCI connection.\n");
273             gap_disconnect(acl_handle);
274             break;
275         case 'u':
276             printf("Join held call\n");
277             hfp_ag_join_held_call();
278             break;
279         // case 'v':
280         //     printf("Starting inquiry scan..\n");
281         //     gap_inquiry_start(15);
282         //     break;
283         case 'w':
284             printf("AG: Put incoming call on hold (Response and Hold)\n");
285             hfp_ag_hold_incoming_call();
286             break;
287         case 'x':
288             printf("AG: Accept held incoming call (Response and Hold)\n");
289             hfp_ag_accept_held_incoming_call();
290             break;
291         case 'X':
292             printf("AG: Reject held incoming call (Response and Hold)\n");
293             hfp_ag_reject_held_incoming_call();
294             break;
295         default:
296             printf("unknow cmd %c\n", cmd);
297             break;
298     }
299 }
300 
simulate_test_sequence(hfp_test_item_t * test_item)301 static void simulate_test_sequence(hfp_test_item_t * test_item){
302     char ** test_steps = test_item->test;
303     printf("\nSimulate test sequence: \"%s\"\n", test_item->name);
304 
305     int i = 0;
306     int previous_step = -1;
307     while ( i < test_item->len){
308         previous_step++;
309         CHECK_EQUAL(i >= previous_step, 1);
310 
311         char * expected_cmd = test_steps[i];
312         int expected_cmd_len = strlen(expected_cmd);
313         printf("\nStep %d, %s \n", i, expected_cmd);
314 
315         if (strncmp(expected_cmd, "USER:", 5) == 0){
316             printf("\n---> USER: ");
317             user_command(expected_cmd[5]);
318             i++;
319         } else if (strncmp(expected_cmd, "AT", 2) == 0){
320             // printf("\n---> NEXT STEP receive from HF: '%s'\n", expected_cmd);
321             inject_hfp_command_to_ag((uint8_t*)expected_cmd, expected_cmd_len);
322             i++;
323 
324         } else {
325             while (has_more_hfp_ag_commands()){
326                 printf("\n---> NEXT STEP expect from AG: %s\n", expected_cmd);
327                 char * ag_cmd = get_next_hfp_ag_command();
328 
329                 int equal_cmds = strncmp(ag_cmd, expected_cmd, expected_cmd_len) == 0;
330                 // printf("CHECK: %s == %s -> %u", ag_cmd, expected_cmd, equal_cmds);
331                 if (!equal_cmds){
332                     printf("\nError: Expected:'%s', but got:'%s'\n", expected_cmd, ag_cmd);
333                     CHECK_EQUAL(equal_cmds,1);
334                     return;
335                 }
336                 printf("Verified: '%s'\n", expected_cmd);
337 
338                 i++;
339                 if (i < test_item->len){
340                     expected_cmd = test_steps[i];
341                     expected_cmd_len = strlen(expected_cmd);
342                 }
343             }
344             // printf("\n---> NEXT STEP trigger once more AG\n");
345             inject_hfp_command_to_ag((uint8_t*)"NOP",3);
346         }
347     }
348 }
349 
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * event,uint16_t event_size)350 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){
351 
352     if (event[0] != HCI_EVENT_HFP_META) return;
353     const char * dial_string;
354     const char * dtmf_string;
355 
356     switch (event[2]) {
357         case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
358             acl_handle = hfp_subevent_service_level_connection_established_get_acl_handle(event);
359             printf("Service level connection established.\n");
360             break;
361         case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
362             printf("Service level connection released.\n");
363             break;
364         case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED:
365             printf("\n** Audio connection established **\n");
366             break;
367         case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED:
368             printf("\n** Audio connection released **\n");
369             break;
370         case HFP_SUBEVENT_START_RINGING:
371             printf("\n** Start Ringing **\n");
372             break;
373         case HFP_SUBEVENT_STOP_RINGING:
374             printf("\n** Stop Ringing **\n");
375             break;
376         case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER:
377             dial_string = (const char *) hfp_subevent_place_call_with_number_get_number(event);
378             printf("\n** Outgoing call '%s' **\n", dial_string);
379             // validate number
380             if ( strcmp("1234567", dial_string) == 0
381               || strcmp("7654321", dial_string) == 0
382               || (memory_1_enabled && strcmp(">1", dial_string) == 0)){
383                 printf("Dialstring valid: accept call\n");
384                 hfp_ag_outgoing_call_accepted();
385             } else {
386                 printf("Dialstring invalid: reject call\n");
387                 hfp_ag_outgoing_call_rejected();
388             }
389             break;
390         case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG:
391             printf("\n** Attach number to voice tag. Sending '1234567\n");
392             hfp_ag_send_phone_number_for_voice_tag(acl_handle, "1234567");
393             break;
394         case HFP_SUBEVENT_TRANSMIT_DTMF_CODES:
395             dtmf_string = (const char *) hfp_subevent_transmit_dtmf_codes_get_dtmf(event);
396             printf("\n** Send DTMF Codes: '%s'\n",dtmf_string);
397             hfp_ag_send_dtmf_code_done(acl_handle);
398             break;
399         default:
400             break;
401     }
402 
403 }
404 
405 
TEST_GROUP(HFPClient)406 TEST_GROUP(HFPClient){
407     void setup(void){
408         hfp_ag_init(rfcomm_channel_nr);
409         hfp_ag_init_supported_features(supported_features_with_codec_negotiation);
410         hfp_ag_init_codecs(sizeof(codecs), codecs);
411         hfp_ag_init_ag_indicators(ag_indicators_nr, ag_indicators);
412         hfp_ag_init_hf_indicators(hf_indicators_nr, hf_indicators);
413         hfp_ag_init_call_hold_services(call_hold_services_nr, call_hold_services);
414     }
415 
416     void teardown(void){
417         hfp_ag_release_audio_connection(acl_handle);
418         hfp_ag_release_service_level_connection(acl_handle);
419     }
420 };
421 
422 
TEST(HFPClient,PTSRHHTests)423 TEST(HFPClient, PTSRHHTests){
424     for (int i = 0; i < hfp_pts_ag_rhh_tests_size(); i++){
425         setup();
426         simulate_test_sequence(&hfp_pts_ag_rhh_tests()[i]);
427         teardown();
428     }
429 }
430 
TEST(HFPClient,PTSECCTests)431 TEST(HFPClient, PTSECCTests){
432     for (int i = 0; i < hfp_pts_ag_ecc_tests_size(); i++){
433         setup();
434         simulate_test_sequence(&hfp_pts_ag_ecc_tests()[i]);
435         teardown();
436     }
437 }
438 
TEST(HFPClient,PTSECSTests)439 TEST(HFPClient, PTSECSTests){
440     for (int i = 0; i < hfp_pts_ag_ecs_tests_size(); i++){
441         setup();
442         simulate_test_sequence(&hfp_pts_ag_ecs_tests()[i]);
443         teardown();
444     }
445 }
446 
TEST(HFPClient,PTSTWCTests)447 TEST(HFPClient, PTSTWCTests){
448     for (int i = 0; i < hfp_pts_ag_twc_tests_size(); i++){
449         setup();
450         simulate_test_sequence(&hfp_pts_ag_twc_tests()[i]);
451         teardown();
452     }
453 }
454 
TEST(HFPClient,PTSATATests)455 TEST(HFPClient, PTSATATests){
456     for (int i = 0; i < hfp_pts_ag_ata_tests_size(); i++){
457         setup();
458         simulate_test_sequence(&hfp_pts_ag_ata_tests()[i]);
459         teardown();
460     }
461 }
462 
TEST(HFPClient,PTSSLCTests)463 TEST(HFPClient, PTSSLCTests){
464     for (int i = 0; i < hfp_pts_ag_slc_tests_size(); i++){
465         setup();
466         simulate_test_sequence(&hfp_pts_ag_slc_tests()[i]);
467         teardown();
468     }
469 }
470 
471 
main(int argc,const char * argv[])472 int main (int argc, const char * argv[]){
473     hfp_ag_register_packet_handler(packet_handler);
474 
475     return CommandLineTestRunner::RunAllTests(argc, argv);
476 }
477