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