xref: /btstack/test/hfp/hfp_at_parser_test.cpp (revision 63a4cec072210152724610b97cfc41046ea1aab9)
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 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "CppUTest/TestHarness.h"
45 #include "CppUTest/CommandLineTestRunner.h"
46 
47 #include "btstack_event.h"
48 #include "classic/hfp.h"
49 #include "classic/hfp_hf.h"
50 #include "classic/hfp_ag.h"
51 
52 void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree);
53 
54 static  hfp_connection_t context;
55 static int hfp_ag_indicators_nr = 7;
56 static hfp_ag_indicator_t hfp_ag_indicators[] = {
57     // index, name, min range, max range, status, mandatory, enabled, status changed
58     {1, "service",   0, 1, 1, 0, 0, 0},
59     {2, "call",      0, 1, 0, 1, 1, 0},
60     {3, "callsetup", 0, 3, 0, 1, 1, 0},
61     {4, "battchg",   0, 5, 3, 0, 0, 0},
62     {5, "signal",    0, 5, 5, 0, 0, 0},
63     {6, "roam",      0, 1, 0, 0, 0, 0},
64     {7, "callheld",  0, 2, 0, 1, 1, 0}
65 };
66 static uint8_t call_status_index = 2;
67 static uint8_t callsetup_status_index = 3;
68 static uint8_t callheld_status_index = 7;
69 
70 // #define LOG_LINE_BUFFER
71 static void hfp_at_parser_test_dump_line_buffer(void){
72 #ifdef LOG_LINE_BUFFER
73     uint16_t line_len = strlen(reinterpret_cast<const char *>(context.line_buffer));
74     printf("\nLine buffer: %s\n", context.line_buffer);
75     printf_hexdump(context.line_buffer, line_len);
76 #endif
77 }
78 
79 static void parse_ag(const char * packet){
80     for (uint16_t pos = 0; pos < strlen(packet); pos++){
81         hfp_parse(&context, packet[pos], 0);
82     }
83 }
84 
85 static void parse_hf(const char * packet){
86     for (uint16_t pos = 0; pos < strlen(packet); pos++){
87         hfp_parse(&context, packet[pos], 1);
88     }
89 }
90 
91 TEST_GROUP(HFPParser){
92     char packet[200];
93     int pos;
94     int offset;
95 
96     void setup(void){
97         hfp_init();
98         memset(&context, 0, sizeof(hfp_connection_t));
99         context.parser_state = HFP_PARSER_CMD_HEADER;
100         context.parser_item_index = 0;
101         context.line_size = 0;
102         context.ag_indicators_nr = 0;
103         context.remote_codecs_nr = 0;
104         context.bnip_number[0] = 0;
105         context.bnip_type = 0;
106         memset(packet,0, sizeof(packet));
107     }
108 
109     void teardown(void){
110         hfp_deinit();
111     }
112 };
113 
114 TEST(HFPParser, HFP_HF_OK){
115     snprintf(packet, sizeof(packet), "\r\n%s\r\n", HFP_OK);
116     parse_hf(packet);
117     CHECK_EQUAL(HFP_CMD_OK, context.command);
118 }
119 
120 TEST(HFPParser, HFP_HF_SUPPORTED_FEATURES){
121     snprintf(packet, sizeof(packet), "\r\n%s:1007\r\n\r\nOK\r\n", HFP_SUPPORTED_FEATURES);
122     parse_hf(packet);
123     CHECK_EQUAL(HFP_CMD_OK, context.command);
124     CHECK_EQUAL(1007, context.remote_supported_features);
125 }
126 
127 TEST(HFPParser, HFP_CMD_INDICATORS_QUERY){
128     snprintf(packet, sizeof(packet), "\r\nAT%s?\r\n", HFP_INDICATOR);
129     parse_ag(packet);
130     CHECK_EQUAL(HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS, context.command);
131 }
132 
133 TEST(HFPParser, HFP_CMD_INDICATORS_RETRIEVE){
134     snprintf(packet, sizeof(packet), "\r\nAT%s=?\r\n", HFP_INDICATOR);
135     parse_ag(packet);
136     CHECK_EQUAL(HFP_CMD_RETRIEVE_AG_INDICATORS, context.command);
137 }
138 
139 TEST(HFPParser, HFP_HF_INDICATORS){
140     offset = 0;
141     offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR);
142     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
143     	if (pos != 0) {
144 			packet[offset++] = ',';
145 		}
146     	offset += snprintf(packet+offset, sizeof(packet)-offset, "(\"%s\", (%d, %d)),", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range);
147     }
148     offset += snprintf(packet+offset, sizeof(packet)-offset, "\r\n\r\nOK\r\n");
149     context.state = HFP_W4_RETRIEVE_INDICATORS;
150 
151     parse_hf(packet);
152     CHECK_EQUAL(HFP_CMD_OK, context.command);
153     CHECK_EQUAL(hfp_ag_indicators_nr, context.ag_indicators_nr);
154     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
155         CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index);
156         STRCMP_EQUAL(hfp_ag_indicators[pos].name, context.ag_indicators[pos].name);
157         CHECK_EQUAL(hfp_ag_indicators[pos].min_range, context.ag_indicators[pos].min_range);
158         CHECK_EQUAL(hfp_ag_indicators[pos].max_range, context.ag_indicators[pos].max_range);
159     }
160 }
161 
162 TEST(HFPParser, HFP_HF_INDICATORS_RANGE){
163 	offset = 0;
164 	offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR);
165 	for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
166 		if (pos != 0) {
167 			packet[offset++] = ',';
168 		}
169 		offset += snprintf(packet+offset, sizeof(packet)-offset, "(\"%s\", (%d-%d)),", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range);
170 	}
171 	offset += snprintf(packet+offset, sizeof(packet)-offset, "\r\n\r\nOK\r\n");
172 	context.state = HFP_W4_RETRIEVE_INDICATORS;
173 
174 	parse_hf(packet);
175 	CHECK_EQUAL(HFP_CMD_OK, context.command);
176 	CHECK_EQUAL(hfp_ag_indicators_nr, context.ag_indicators_nr);
177 	for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
178 		CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index);
179 		STRCMP_EQUAL(hfp_ag_indicators[pos].name, context.ag_indicators[pos].name);
180 		CHECK_EQUAL(hfp_ag_indicators[pos].min_range, context.ag_indicators[pos].min_range);
181 		CHECK_EQUAL(hfp_ag_indicators[pos].max_range, context.ag_indicators[pos].max_range);
182 	}
183 }
184 
185 TEST(HFPParser, HFP_HF_INDICATOR_STATUS){
186     // send status
187     offset = 0;
188     offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR);
189     for (pos = 0; pos < hfp_ag_indicators_nr - 1; pos++){
190         offset += snprintf(packet+offset, sizeof(packet)-offset, "%d,", hfp_ag_indicators[pos].status);
191     }
192     offset += snprintf(packet+offset, sizeof(packet)-offset, "%d\r\n\r\nOK\r\n", hfp_ag_indicators[pos].status);
193 
194     //context.command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS;
195     context.state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
196 
197     parse_hf(packet);
198     CHECK_EQUAL(HFP_CMD_OK, context.command);
199     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
200         CHECK_EQUAL(hfp_ag_indicators[pos].status, context.ag_indicators[pos].status);
201     }
202 }
203 
204 TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES_TEST){
205     snprintf(packet, sizeof(packet), "\r\nAT%s=?\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES);
206     parse_ag(packet);
207     CHECK_EQUAL(HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, context.command);
208 }
209 
210 TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES_SET){
211     int action = 1;
212     int call_index = 2;
213     snprintf(packet, sizeof(packet), "\r\nAT%s=%u%u\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, action, call_index);
214     parse_ag(packet);
215     CHECK_EQUAL(HFP_CMD_CALL_HOLD, context.command);
216     CHECK_EQUAL(action, context.ag_call_hold_action);
217     CHECK_EQUAL(call_index, context.call_index);
218 }
219 
220 TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES){
221     snprintf(packet, sizeof(packet), "\r\n%s:(1,1x,2,2x,3)\r\n\r\nOK\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES);
222     parse_hf(packet);
223     CHECK_EQUAL(HFP_CMD_OK, context.command);
224     CHECK_EQUAL(5, context.remote_call_services_index);
225 
226     STRCMP_EQUAL("1", (char*)context.remote_call_services[0].name);
227     STRCMP_EQUAL("1x", (char*)context.remote_call_services[1].name);
228     STRCMP_EQUAL("2", (char*)context.remote_call_services[2].name);
229     STRCMP_EQUAL("2x", (char*)context.remote_call_services[3].name);
230     STRCMP_EQUAL("3", (char*)context.remote_call_services[4].name);
231 }
232 
233 TEST(HFPParser, HFP_GENERIC_STATUS_INDICATOR_TEST){
234     snprintf(packet, sizeof(packet), "\r\nAT%s=?\r\n", HFP_GENERIC_STATUS_INDICATOR);
235     parse_ag(packet);
236     CHECK_EQUAL(HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS, context.command);
237 }
238 
239 TEST(HFPParser, HFP_GENERIC_STATUS_INDICATOR_SET){
240     int param1 = 1;
241     int param2 = 2;
242     int param3 = 3;
243     snprintf(packet, sizeof(packet), "\r\nAT%s= %u,%u,%u\r\n", HFP_GENERIC_STATUS_INDICATOR, param1, param2, param3);
244     parse_ag(packet);
245     CHECK_EQUAL(HFP_CMD_LIST_GENERIC_STATUS_INDICATORS, context.command);
246 }
247 
248 TEST(HFPParser, HFP_GENERIC_STATUS_INDICATOR_READ){
249     snprintf(packet, sizeof(packet), "\r\nAT%s?\r\n", HFP_GENERIC_STATUS_INDICATOR);
250     parse_ag(packet);
251     CHECK_EQUAL(HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE, context.command);
252 }
253 
254 TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR_STATE){
255     snprintf(packet, sizeof(packet), "\r\n%s:0,1\r\n\r\nOK\r\n", HFP_GENERIC_STATUS_INDICATOR);
256     // context.command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE;
257     context.state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
258 
259     parse_hf(packet);
260     CHECK_EQUAL(HFP_CMD_OK, context.command);
261     CHECK_EQUAL(1, context.generic_status_indicators[0].state);
262 }
263 
264 TEST(HFPParser, HFP_HF_AG_INDICATOR_STATUS_UPDATE){
265     context.ag_indicators_nr = hfp_ag_indicators_nr;
266     memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
267 
268     uint8_t index = 4;
269     uint8_t status = 5;
270 
271     snprintf(packet, sizeof(packet), "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
272 
273     parse_hf(packet);
274     CHECK_EQUAL(HFP_CMD_OK, context.command);
275     CHECK_EQUAL(status, context.ag_indicators[index - 1].status);
276 }
277 
278 TEST(HFPParser, HFP_HF_AG_QUERY_OPERATOR_SELECTION){
279     snprintf(packet, sizeof(packet), "\r\n%s:1,0,\"sunrise\"\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION);
280 
281     context.command = HFP_CMD_QUERY_OPERATOR_SELECTION_NAME;
282 
283     parse_hf(packet);
284     CHECK_EQUAL(HFP_CMD_OK, context.command);
285     CHECK_EQUAL(0, context.operator_name_changed);
286     STRCMP_EQUAL( "sunrise", context.network_operator.name);
287 }
288 
289 TEST(HFPParser, HFP_HF_ERROR){
290     snprintf(packet, sizeof(packet), "\r\n%s\r\n", HFP_ERROR);
291 
292     parse_hf(packet);
293     CHECK_EQUAL(HFP_CMD_ERROR, context.command);
294 }
295 
296 TEST(HFPParser, HFP_HF_EXTENDED_AUDIO_GATEWAY_ERROR){
297     snprintf(packet, sizeof(packet), "\r\n%s:%d\r\n", HFP_EXTENDED_AUDIO_GATEWAY_ERROR, HFP_CME_ERROR_NO_NETWORK_SERVICE);
298 
299     parse_hf(packet);
300     CHECK_EQUAL(HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR, context.command);
301     CHECK_EQUAL(HFP_CME_ERROR_NO_NETWORK_SERVICE, context.extended_audio_gateway_error_value);
302 }
303 
304 TEST(HFPParser, HFP_HF_AG_INDICATOR_CALLS_STATUS_UPDATE){
305     context.ag_indicators_nr = hfp_ag_indicators_nr;
306     memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
307     uint8_t status = 1;
308 
309     // call status
310     uint8_t index = call_status_index;
311     snprintf(packet, sizeof(packet), "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
312     parse_hf(packet);
313     CHECK_EQUAL(HFP_CMD_OK, context.command);
314     CHECK_EQUAL(status, context.ag_indicators[index - 1].status);
315 
316     // callsetup status
317     index = callsetup_status_index;
318     snprintf(packet, sizeof(packet), "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
319     parse_hf(packet);
320     CHECK_EQUAL(HFP_CMD_OK, context.command);
321     CHECK_EQUAL(status, context.ag_indicators[index - 1].status);
322 
323     // callheld status
324     index = callheld_status_index;
325     snprintf(packet, sizeof(packet), "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
326     parse_hf(packet);
327     CHECK_EQUAL(HFP_CMD_OK, context.command);
328     CHECK_EQUAL(status, context.ag_indicators[index - 1].status);
329 }
330 
331 TEST(HFPParser, HFP_LIST_CURRENT_CALLS_1){
332     strcpy(packet, "\r\n+CLCC: 1,2,3,4,5,,129\r\n");
333     parse_hf(packet);
334     CHECK_EQUAL(HFP_CMD_LIST_CURRENT_CALLS, context.command);
335     CHECK_EQUAL(1, context.clcc_idx);
336     CHECK_EQUAL(2, context.clcc_dir);
337     CHECK_EQUAL(3, context.clcc_status);
338     CHECK_EQUAL(4, context.clcc_mode);
339     CHECK_EQUAL(5, context.clcc_mpty);
340     STRCMP_EQUAL("", context.bnip_number);
341     CHECK_EQUAL(129, context.bnip_type);
342 }
343 
344 TEST(HFPParser, HFP_LIST_CURRENT_CALLS_2){
345     strcpy(packet, "\r\n+CLCC: 1,2,3,4,5,"",129\r\n");
346     parse_hf(packet);
347     CHECK_EQUAL(HFP_CMD_LIST_CURRENT_CALLS, context.command);
348     CHECK_EQUAL(1, context.clcc_idx);
349     CHECK_EQUAL(2, context.clcc_dir);
350     CHECK_EQUAL(3, context.clcc_status);
351     CHECK_EQUAL(4, context.clcc_mode);
352     CHECK_EQUAL(5, context.clcc_mpty);
353     STRCMP_EQUAL("", context.bnip_number);
354     CHECK_EQUAL(129, context.bnip_type);
355 }
356 
357 TEST(HFPParser, HFP_AG_SUPPORTED_FEATURES){
358     snprintf(packet, sizeof(packet), "\r\nAT%s=159\r\n", HFP_SUPPORTED_FEATURES);
359     //context.keep_separator = 0;
360     parse_ag(packet);
361     CHECK_EQUAL(HFP_CMD_SUPPORTED_FEATURES, context.command);
362     CHECK_EQUAL(159, context.remote_supported_features);
363 }
364 
365 TEST(HFPParser, HFP_AG_AVAILABLE_CODECS){
366     snprintf(packet, sizeof(packet), "\r\nAT%s=0,1,2\r\n", HFP_AVAILABLE_CODECS);
367     parse_ag(packet);
368     CHECK_EQUAL(HFP_CMD_AVAILABLE_CODECS, context.command);
369     CHECK_EQUAL(3, context.remote_codecs_nr);
370     for (pos = 0; pos < 3; pos++){
371         CHECK_EQUAL(pos, context.remote_codecs[pos]);
372     }
373 }
374 
375 TEST(HFPParser, HFP_AG_GENERIC_STATUS_INDICATOR){
376     snprintf(packet, sizeof(packet), "\r\nAT%s=0,1,2,3,4\r\n", HFP_GENERIC_STATUS_INDICATOR);
377     parse_ag(packet);
378     CHECK_EQUAL(context.command, HFP_CMD_LIST_GENERIC_STATUS_INDICATORS);
379     CHECK_EQUAL(5, context.generic_status_indicators_nr);
380 
381     for (pos = 0; pos < context.generic_status_indicators_nr; pos++){
382         CHECK_EQUAL(pos, context.generic_status_indicators[pos].uuid);
383     }
384 }
385 
386 TEST(HFPParser, HFP_AG_ENABLE_INDICATOR_STATUS_UPDATE){
387     snprintf(packet, sizeof(packet), "\r\nAT%s=3,0,0,1\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS);
388     parse_ag(packet);
389     CHECK_EQUAL(HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE, context.command);
390     CHECK_EQUAL(1, context.enable_status_update_for_ag_indicators);
391 }
392 
393 TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){
394     hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators);
395     context.ag_indicators_nr = hfp_ag_indicators_nr;
396     memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
397 
398     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
399         CHECK_EQUAL(hfp_ag_indicators[pos].index,   hfp_ag_get_ag_indicators(&context)[pos].index );
400         CHECK_EQUAL(hfp_ag_indicators[pos].enabled, hfp_ag_get_ag_indicators(&context)[pos].enabled);
401         CHECK_EQUAL(hfp_ag_indicators[pos].index,   context.ag_indicators[pos].index);
402         CHECK_EQUAL(hfp_ag_indicators[pos].enabled, context.ag_indicators[pos].enabled);
403     }
404     snprintf(packet, sizeof(packet), "\r\nAT%s=0,0,0,0,0,0,0\r\n",
405         HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS);
406     parse_ag(packet);
407     CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command);
408 
409     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
410         if (hfp_ag_get_ag_indicators(&context)[pos].mandatory){
411             CHECK_EQUAL(1, hfp_ag_get_ag_indicators(&context)[pos].enabled);
412             CHECK_EQUAL(1, context.ag_indicators[pos].enabled);
413         } else {
414             CHECK_EQUAL(0, hfp_ag_get_ag_indicators(&context)[pos].enabled);
415             CHECK_EQUAL(0, context.ag_indicators[pos].enabled);
416         }
417     }
418 }
419 
420 TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES3){
421     hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators);
422     context.ag_indicators_nr = hfp_ag_indicators_nr;
423     memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
424 
425     snprintf(packet, sizeof(packet), "\r\nAT%s=,1,,,,,1\r\n",
426         HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS);
427     parse_ag(packet);
428 
429     CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command);
430 
431     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
432         CHECK_EQUAL(hfp_ag_indicators[pos].index, hfp_ag_get_ag_indicators(&context)[pos].index );
433         CHECK_EQUAL(hfp_ag_indicators[pos].enabled, hfp_ag_get_ag_indicators(&context)[pos].enabled);
434         CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index );
435         CHECK_EQUAL(hfp_ag_indicators[pos].enabled, context.ag_indicators[pos].enabled);
436     }
437 }
438 
439 TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES2){
440     hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators);
441     context.ag_indicators_nr = hfp_ag_indicators_nr;
442     memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
443 
444     snprintf(packet, sizeof(packet), "\r\nAT%s=1,,,1,1,1,\r\n",
445         HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS);
446     parse_ag(packet);
447 
448     CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command);
449 
450     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
451         CHECK_EQUAL(1,hfp_ag_get_ag_indicators(&context)[pos].enabled);
452         CHECK_EQUAL(1, context.ag_indicators[pos].enabled);
453     }
454 }
455 
456 TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES1){
457     hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators);
458     context.ag_indicators_nr = hfp_ag_indicators_nr;
459     memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
460 
461     snprintf(packet, sizeof(packet), "\r\nAT%s=1,,,1,1,1,\r\n",
462         HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS);
463     parse_ag(packet);
464 
465     CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command);
466 
467     for (pos = 0; pos < hfp_ag_indicators_nr; pos++){
468         CHECK_EQUAL(1, hfp_ag_get_ag_indicators(&context)[pos].enabled);
469         CHECK_EQUAL(1, context.ag_indicators[pos].enabled);
470     }
471 }
472 
473 TEST(HFPParser, HFP_AG_HF_QUERY_OPERATOR_SELECTION){
474     context.network_operator.format = 0xff;
475     snprintf(packet, sizeof(packet), "\r\nAT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION);
476 
477     parse_ag(packet);
478     CHECK_EQUAL(0, context.operator_name_changed);
479     CHECK_EQUAL(HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT, context.command);
480 
481     snprintf(packet, sizeof(packet), "\r\nAT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION);
482 
483     parse_ag(packet);
484     CHECK_EQUAL(HFP_CMD_QUERY_OPERATOR_SELECTION_NAME, context.command);
485     CHECK_EQUAL(0, context.operator_name_changed);
486 }
487 
488 TEST(HFPParser, HFP_AG_EXTENDED_AUDIO_GATEWAY_ERROR){
489     snprintf(packet, sizeof(packet), "\r\nAT%s=1\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR);
490 
491     parse_ag(packet);
492     CHECK_EQUAL(HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, context.command );
493     CHECK_EQUAL(1, context.enable_extended_audio_gateway_error_report);
494 }
495 
496 TEST(HFPParser, HFP_AG_TRIGGER_CODEC_CONNECTION_SETUP){
497     snprintf(packet, sizeof(packet), "\r\nAT%s\r\n", HFP_TRIGGER_CODEC_CONNECTION_SETUP);
498     parse_ag(packet);
499     CHECK_EQUAL(HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP, context.command);
500 }
501 
502 TEST(HFPParser, HFP_AG_CONFIRM_COMMON_CODEC){
503     int codec = 2;
504     snprintf(packet, sizeof(packet), "\r\nAT%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec);
505 
506     parse_ag(packet);
507     CHECK_EQUAL(HFP_CMD_HF_CONFIRMED_CODEC, context.command );
508     CHECK_EQUAL(codec, context.codec_confirmed);
509 }
510 
511 TEST(HFPParser, HFP_AG_DIAL){
512     strcpy(packet, "\r\nATD00123456789;\r\n");
513 
514     parse_ag(packet);
515     CHECK_EQUAL(HFP_CMD_CALL_PHONE_NUMBER, context.command);
516     STRCMP_EQUAL("00123456789", (const char *) &context.line_buffer[3]);
517 }
518 
519 TEST(HFPParser, HFP_ANSWER_CALL){
520     snprintf(packet, sizeof(packet), "\r\n%s\r\n", HFP_ANSWER_CALL);
521     parse_ag(packet);
522     CHECK_EQUAL(HFP_CMD_CALL_ANSWERED, context.command);
523 }
524 
525 TEST(HFPParser, HFP_CMD_RESPONSE_AND_HOLD_QUERY){
526     snprintf(packet, sizeof(packet), "\r\nAT%s?\r\n", HFP_RESPONSE_AND_HOLD);
527     parse_ag(packet);
528     CHECK_EQUAL(HFP_CMD_RESPONSE_AND_HOLD_QUERY, context.command);
529 }
530 
531 TEST(HFPParser, HFP_CMD_RESPONSE_AND_HOLD_COMMAND){
532     int param = 1;
533     snprintf(packet, sizeof(packet), "\r\nAT%s=%u\r\n", HFP_RESPONSE_AND_HOLD, param);
534     parse_ag(packet);
535     CHECK_EQUAL(HFP_CMD_RESPONSE_AND_HOLD_COMMAND, context.command);
536     CHECK_EQUAL(param, context.ag_response_and_hold_action);
537 }
538 
539 TEST(HFPParser, HFP_CMD_RESPONSE_AND_HOLD_STATUS){
540     int status = 1;
541     snprintf(packet, sizeof(packet), "\r\n%s:%u\r\n", HFP_RESPONSE_AND_HOLD, status);
542     parse_hf(packet);
543     CHECK_EQUAL(HFP_CMD_RESPONSE_AND_HOLD_STATUS, context.command);
544 }
545 
546 TEST(HFPParser, HFP_CMD_ENABLE_CLIP){
547     int param = 1;
548     snprintf(packet, sizeof(packet), "\r\nAT%s=%u\r\n", HFP_ENABLE_CLIP, param);
549     parse_ag(packet);
550     CHECK_EQUAL(HFP_CMD_ENABLE_CLIP, context.command);
551     CHECK_EQUAL(param, context.clip_enabled);
552 }
553 
554 TEST(HFPParser, HFP_CMD_AG_SENT_CLIP_INFORMATION_a){
555     // default/minimal
556     parse_hf("\r\n+CLIP: \"+123456789\",145\r\n");
557     CHECK_EQUAL(HFP_CMD_AG_SENT_CLIP_INFORMATION, context.command);
558     STRCMP_EQUAL("+123456789", context.bnip_number);
559     CHECK_EQUAL(145, context.bnip_type);
560     CHECK_EQUAL(false, context.clip_have_alpha);
561 }
562 
563 TEST(HFPParser, HFP_CMD_AG_SENT_CLIP_INFORMATION_b){
564     // iOS
565     parse_hf("\r\n+CLIP: \"+123456789\",145,,,\"BlueKitchen GmbH\"\r\n");
566     CHECK_EQUAL(HFP_CMD_AG_SENT_CLIP_INFORMATION, context.command);
567     STRCMP_EQUAL("+123456789", context.bnip_number);
568     CHECK_EQUAL(145, context.bnip_type);
569     CHECK_EQUAL(true, context.clip_have_alpha);
570     STRCMP_EQUAL("BlueKitchen GmbH", (const char *)context.line_buffer);
571 }
572 
573 TEST(HFPParser, HFP_CMD_AG_SENT_CLIP_INFORMATION_c){
574     // older iOS with additional ','
575     parse_hf("\r\n+CLIP: \"+123456789\",145,,,,\"BlueKitchen GmbH\"\r\n");
576     CHECK_EQUAL(HFP_CMD_AG_SENT_CLIP_INFORMATION, context.command);
577     STRCMP_EQUAL("+123456789", context.bnip_number);
578     CHECK_EQUAL(145, context.bnip_type);
579     CHECK_EQUAL(true, context.clip_have_alpha);
580     STRCMP_EQUAL("BlueKitchen GmbH", (const char *)context.line_buffer);
581 }
582 
583 TEST(HFPParser, HFP_CMD_AG_SENT_CLIP_INFORMATION_d){
584     // BlackBerry, additional quotes
585     parse_hf("\r\n+CLIP: \"+123456789\",145,\"\",,\"BlueKitchen GmbH\"\r\n");
586     CHECK_EQUAL(HFP_CMD_AG_SENT_CLIP_INFORMATION, context.command);
587     STRCMP_EQUAL("+123456789", context.bnip_number);
588     CHECK_EQUAL(145, context.bnip_type);
589     CHECK_EQUAL(true, context.clip_have_alpha);
590     STRCMP_EQUAL("BlueKitchen GmbH", (const char *)context.line_buffer);
591 }
592 
593 TEST(HFPParser, HFP_CMD_AG_SENT_CALL_WAITING_INFORMATION){
594     parse_hf("\r\n+CCWA: \"+123456789\",145,\"\",1,\"BlueKitchen GmbH\"\r\n");
595     CHECK_EQUAL(HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE, context.command);
596     STRCMP_EQUAL("+123456789", context.bnip_number);
597     CHECK_EQUAL(145, context.bnip_type);
598     CHECK_EQUAL(true, context.clip_have_alpha);
599     STRCMP_EQUAL("BlueKitchen GmbH", (const char *)context.line_buffer);
600 }
601 
602 TEST(HFPParser, custom_command_hf){
603     hfp_custom_at_command_t custom_hf_command = {
604             .command = "+FOO:",
605             .command_id = 1
606     };
607     const char * custom_hf_command_string = "\r\n+FOO:1,2,3\r\n";
608     hfp_register_custom_hf_command(&custom_hf_command);
609     parse_hf(custom_hf_command_string);
610     CHECK_EQUAL(1, context.custom_at_command_id);
611     STRCMP_EQUAL("+FOO:1,2,3", (const char *)context.line_buffer);
612     hfp_at_parser_test_dump_line_buffer();
613 }
614 
615 TEST(HFPParser, custom_command_ag_with_colon){
616     hfp_custom_at_command_t custom_ag_command = {
617             .command = "AT+FOO:",
618             .command_id = 2
619     };
620     const char * custom_hf_command_string = "\r\nAT+FOO:1,2,3\r\n";
621     hfp_register_custom_ag_command(&custom_ag_command);
622     parse_ag(custom_hf_command_string);
623     CHECK_EQUAL(2, context.custom_at_command_id);
624     STRCMP_EQUAL("AT+FOO:1,2,3", (const char *)context.line_buffer);
625     hfp_at_parser_test_dump_line_buffer();
626 }
627 
628 TEST(HFPParser, custom_command_ag_with_question){
629     hfp_custom_at_command_t custom_ag_command = {
630             .command = "AT+FOO?",
631             .command_id = 3
632     };
633     const char * custom_hf_command_string = "\r\nAT+FOO?\r\n";
634     hfp_register_custom_ag_command(&custom_ag_command);
635     parse_ag(custom_hf_command_string);
636     CHECK_EQUAL(3, context.custom_at_command_id);
637     STRCMP_EQUAL("AT+FOO?", (const char *)context.line_buffer);
638     hfp_at_parser_test_dump_line_buffer();
639 }
640 
641 TEST(HFPParser, custom_command_hf_with_assignment){
642     hfp_custom_at_command_t custom_ag_command = {
643             .command = "AT+TEST=",
644             .command_id = 3
645     };
646     const char * custom_hf_command_string = "\r\nAT+TEST=ABCDE\r\n";
647     hfp_register_custom_ag_command(&custom_ag_command);
648     parse_ag(custom_hf_command_string);
649     CHECK_EQUAL(3, context.custom_at_command_id);
650     STRCMP_EQUAL("AT+TEST=ABCDE", (const char *)context.line_buffer);
651     hfp_at_parser_test_dump_line_buffer();
652 }
653 
654 TEST(HFPParser, HFP_GABRBAGE_AND_ANSWER_CALL){
655     parse_ag("\r\nAT+ABCDEF\r\n");
656     CHECK_EQUAL(HFP_CMD_UNKNOWN, context.command);
657     snprintf(packet, sizeof(packet), "\r\n%s\r\n", HFP_ANSWER_CALL);
658     parse_ag(packet);
659     CHECK_EQUAL(HFP_CMD_CALL_ANSWERED, context.command);
660 }
661 
662 TEST(HFPParser, AG_SENDS_RANDOM){
663     parse_hf("\r\n+$PATH:511\r\n");
664     CHECK_EQUAL(HFP_CMD_UNKNOWN, context.command);
665 }
666 
667 TEST(HFPParser, long_command){
668     char command[300];
669     uint16_t offset = 0;
670     const char * header = "+CIEV";
671     uint16_t header_len = strlen(header);
672     memcpy(&command[offset], header, header_len);
673     offset += header_len;
674     command[offset++] = 0x02;
675     command[offset++] = 0x32;
676     uint16_t num_2c = 250;
677     memset(&command[offset], 0x2c, num_2c);
678     offset += num_2c;
679     command[offset++] = 0x31;
680     command[offset++] = '\r';
681     command[offset++] = '\n';
682     command[offset++] = 0x00;
683     parse_hf(command);
684 }
685 
686 TEST(HFPParser, apple_accessory_information){
687     parse_ag("\n\rAT+XAPL=ABCD-1234-0100,10\r\n");
688     CHECK_EQUAL(HFP_CMD_APPLE_ACCESSORY_INFORMATION, context.command);
689     CHECK_EQUAL(0xABCD, context.apple_accessory_vendor_id);
690     CHECK_EQUAL(0x1234, context.apple_accessory_product_id);
691     STRCMP_EQUAL("0100",context.apple_accessory_version);
692     CHECK_EQUAL(10, context.apple_accessory_features);
693 }
694 
695 TEST(HFPParser, apple_accessory_state_battery){
696     context.apple_accessory_battery_level = -1;
697     context.apple_accessory_docked = -1;
698     parse_ag("\n\rAT+IPHONEACCEV=1,1,3\r\n");
699     CHECK_EQUAL(HFP_CMD_APPLE_ACCESSORY_STATE, context.command);
700     CHECK_EQUAL(3, context.apple_accessory_battery_level);
701     CHECK_EQUAL(-1, context.apple_accessory_docked);
702 }
703 
704 TEST(HFPParser, apple_accessory_state_docked){
705     context.apple_accessory_battery_level = -1;
706     context.apple_accessory_docked = -1;
707     parse_ag("\n\rAT+IPHONEACCEV=1,2,1\r\n");
708     CHECK_EQUAL(HFP_CMD_APPLE_ACCESSORY_STATE, context.command);
709     CHECK_EQUAL(-1, context.apple_accessory_battery_level);
710     CHECK_EQUAL(1, context.apple_accessory_docked);
711 }
712 
713 TEST(HFPParser, apple_accessory_state_both){
714     context.apple_accessory_battery_level = -1;
715     context.apple_accessory_docked = -1;
716     parse_ag("\n\rAT+IPHONEACCEV=1,1,3,2,1\r\n");
717     CHECK_EQUAL(HFP_CMD_APPLE_ACCESSORY_STATE, context.command);
718     CHECK_EQUAL(3, context.apple_accessory_battery_level);
719     CHECK_EQUAL(1, context.apple_accessory_docked);
720 }
721 
722 TEST(HFPParser,dummy){
723     unsigned char data[] = {
724         0x99, 0x08, 0x0a
725     };
726     unsigned int data_len = sizeof(data);
727     int is_handsfree = data[0] & 1;
728     hfp_connection_t hfp_connection;
729     memset(&hfp_connection, 0, sizeof(hfp_connection_t));
730     uint32_t i;
731     for (i = 1; i < data_len; i++){
732         hfp_parse(&hfp_connection, data[i], is_handsfree);
733     }
734 
735 }
736 
737 int main (int argc, const char * argv[]){
738     return CommandLineTestRunner::RunAllTests(argc, argv);
739 }
740