xref: /btstack/example/hfp_ag_demo.c (revision bdb44bd96ae543c7a3d46ba439628bc6db6be702)
1fffdd288SMatthias Ringwald /*
2fffdd288SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3fffdd288SMatthias Ringwald  *
4fffdd288SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5fffdd288SMatthias Ringwald  * modification, are permitted provided that the following conditions
6fffdd288SMatthias Ringwald  * are met:
7fffdd288SMatthias Ringwald  *
8fffdd288SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9fffdd288SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10fffdd288SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11fffdd288SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12fffdd288SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13fffdd288SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14fffdd288SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15fffdd288SMatthias Ringwald  *    from this software without specific prior written permission.
16fffdd288SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17fffdd288SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18fffdd288SMatthias Ringwald  *    monetary gain.
19fffdd288SMatthias Ringwald  *
20fffdd288SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21fffdd288SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22fffdd288SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23fffdd288SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24fffdd288SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25fffdd288SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26fffdd288SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27fffdd288SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28fffdd288SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29fffdd288SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30fffdd288SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31fffdd288SMatthias Ringwald  * SUCH DAMAGE.
32fffdd288SMatthias Ringwald  *
33fffdd288SMatthias Ringwald  * Please inquire about commercial licensing options at
34fffdd288SMatthias Ringwald  * [email protected]
35fffdd288SMatthias Ringwald  *
36fffdd288SMatthias Ringwald  */
37fffdd288SMatthias Ringwald 
38fffdd288SMatthias Ringwald /*
39fffdd288SMatthias Ringwald  * hfp_ag_demo.c
40fffdd288SMatthias Ringwald  */
41fffdd288SMatthias Ringwald 
42fffdd288SMatthias Ringwald // *****************************************************************************
43fffdd288SMatthias Ringwald /* EXAMPLE_START(hfp_ag_demo): HFP Audio Gateway (AG) Demo
44fffdd288SMatthias Ringwald  *
45fffdd288SMatthias Ringwald  * @text This HFP Audio Gateway example demonstrates how to receive
46fffdd288SMatthias Ringwald  * an output from a remote HFP Hands-Free (HF) unit, and,
47d0755cd6SMatthias Ringwald  * if HAVE_POSIX_STDIN is defined, how to control the HFP HF.
48fffdd288SMatthias Ringwald  */
49fffdd288SMatthias Ringwald // *****************************************************************************
50fffdd288SMatthias Ringwald 
51fffdd288SMatthias Ringwald 
52fffdd288SMatthias Ringwald #include <stdint.h>
53fffdd288SMatthias Ringwald #include <stdio.h>
54fffdd288SMatthias Ringwald #include <stdlib.h>
55fffdd288SMatthias Ringwald #include <string.h>
56fffdd288SMatthias Ringwald #include <unistd.h>
57fffdd288SMatthias Ringwald 
58fffdd288SMatthias Ringwald #include "btstack.h"
59d0755cd6SMatthias Ringwald #ifdef HAVE_POSIX_STDIN
60fffdd288SMatthias Ringwald #include "stdin_support.h"
614af4141bSMatthias Ringwald #endif
62fffdd288SMatthias Ringwald 
63fffdd288SMatthias Ringwald 
643cef842bSMatthias Ringwald static int phase = 0;
653cef842bSMatthias Ringwald 
663cef842bSMatthias Ringwald // input signal: pre-computed sine wave, 160 Hz
673cef842bSMatthias Ringwald static const uint8_t sine[] = {
683cef842bSMatthias Ringwald       0,  15,  31,  46,  61,  74,  86,  97, 107, 114,
693cef842bSMatthias Ringwald     120, 124, 126, 126, 124, 120, 114, 107,  97,  86,
703cef842bSMatthias Ringwald      74,  61,  46,  31,  15,   0, 241, 225, 210, 195,
713cef842bSMatthias Ringwald     182, 170, 159, 149, 142, 136, 132, 130, 130, 132,
723cef842bSMatthias Ringwald     136, 142, 149, 159, 170, 182, 195, 210, 225, 241,
733cef842bSMatthias Ringwald };
743cef842bSMatthias Ringwald 
75fffdd288SMatthias Ringwald uint8_t hfp_service_buffer[150];
76fffdd288SMatthias Ringwald const uint8_t    rfcomm_channel_nr = 1;
77fffdd288SMatthias Ringwald const char hfp_ag_service_name[] = "BTstack HFP AG Test";
78fffdd288SMatthias Ringwald 
79e64e0086SMatthias Ringwald // PTS
80e64e0086SMatthias Ringwald // static bd_addr_t device_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46};
81e64e0086SMatthias Ringwald // BT-201
82e64e0086SMatthias Ringwald static bd_addr_t device_addr = {0x00, 0x07, 0xB0, 0x83, 0x02, 0x5E};
83fffdd288SMatthias Ringwald 
84fffdd288SMatthias Ringwald static uint8_t codecs[1] = {HFP_CODEC_CVSD};
85fffdd288SMatthias Ringwald static uint16_t handle = -1;
863cef842bSMatthias Ringwald static hci_con_handle_t sco_handle;
87fffdd288SMatthias Ringwald static int memory_1_enabled = 1;
88fffdd288SMatthias Ringwald 
89fffdd288SMatthias Ringwald static int ag_indicators_nr = 7;
90fffdd288SMatthias Ringwald static hfp_ag_indicator_t ag_indicators[] = {
91fffdd288SMatthias Ringwald     // index, name, min range, max range, status, mandatory, enabled, status changed
92fffdd288SMatthias Ringwald     {1, "service",   0, 1, 1, 0, 0, 0},
93fffdd288SMatthias Ringwald     {2, "call",      0, 1, 0, 1, 1, 0},
94fffdd288SMatthias Ringwald     {3, "callsetup", 0, 3, 0, 1, 1, 0},
95fffdd288SMatthias Ringwald     {4, "battchg",   0, 5, 3, 0, 0, 0},
96fffdd288SMatthias Ringwald     {5, "signal",    0, 5, 5, 0, 1, 0},
97fffdd288SMatthias Ringwald     {6, "roam",      0, 1, 0, 0, 1, 0},
98fffdd288SMatthias Ringwald     {7, "callheld",  0, 2, 0, 1, 1, 0}
99fffdd288SMatthias Ringwald };
100fffdd288SMatthias Ringwald 
101fffdd288SMatthias Ringwald static int call_hold_services_nr = 5;
102fffdd288SMatthias Ringwald static const char* call_hold_services[] = {"1", "1x", "2", "2x", "3"};
103fffdd288SMatthias Ringwald 
104fffdd288SMatthias Ringwald static int hf_indicators_nr = 2;
105fffdd288SMatthias Ringwald static hfp_generic_status_indicator_t hf_indicators[] = {
106fffdd288SMatthias Ringwald     {1, 1},
107fffdd288SMatthias Ringwald     {2, 1},
108fffdd288SMatthias Ringwald };
109fffdd288SMatthias Ringwald 
110fffdd288SMatthias Ringwald char cmd;
111fffdd288SMatthias Ringwald 
112fffdd288SMatthias Ringwald // GAP INQUIRY
113fffdd288SMatthias Ringwald 
114fffdd288SMatthias Ringwald #define MAX_DEVICES 10
115fffdd288SMatthias Ringwald enum DEVICE_STATE { REMOTE_NAME_REQUEST, REMOTE_NAME_INQUIRED, REMOTE_NAME_FETCHED };
116fffdd288SMatthias Ringwald struct device {
117fffdd288SMatthias Ringwald     bd_addr_t  address;
118fffdd288SMatthias Ringwald     uint16_t   clockOffset;
119fffdd288SMatthias Ringwald     uint32_t   classOfDevice;
120fffdd288SMatthias Ringwald     uint8_t    pageScanRepetitionMode;
121fffdd288SMatthias Ringwald     uint8_t    rssi;
122fffdd288SMatthias Ringwald     enum DEVICE_STATE  state;
123fffdd288SMatthias Ringwald };
124fffdd288SMatthias Ringwald 
125fffdd288SMatthias Ringwald #define INQUIRY_INTERVAL 5
126fffdd288SMatthias Ringwald struct device devices[MAX_DEVICES];
127fffdd288SMatthias Ringwald int deviceCount = 0;
128fffdd288SMatthias Ringwald 
129fffdd288SMatthias Ringwald 
130fffdd288SMatthias Ringwald enum STATE {INIT, W4_INQUIRY_MODE_COMPLETE, ACTIVE} ;
131fffdd288SMatthias Ringwald enum STATE state = INIT;
132fffdd288SMatthias Ringwald 
133fffdd288SMatthias Ringwald 
134fffdd288SMatthias Ringwald static int getDeviceIndexForAddress( bd_addr_t addr){
135fffdd288SMatthias Ringwald     int j;
136fffdd288SMatthias Ringwald     for (j=0; j< deviceCount; j++){
137fffdd288SMatthias Ringwald         if (bd_addr_cmp(addr, devices[j].address) == 0){
138fffdd288SMatthias Ringwald             return j;
139fffdd288SMatthias Ringwald         }
140fffdd288SMatthias Ringwald     }
141fffdd288SMatthias Ringwald     return -1;
142fffdd288SMatthias Ringwald }
143fffdd288SMatthias Ringwald 
144d0755cd6SMatthias Ringwald #ifdef HAVE_POSIX_STDIN
145fffdd288SMatthias Ringwald static void start_scan(void){
146fffdd288SMatthias Ringwald     printf("Starting inquiry scan..\n");
147fffdd288SMatthias Ringwald     hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
148fffdd288SMatthias Ringwald }
149fffdd288SMatthias Ringwald #endif
150fffdd288SMatthias Ringwald 
151fffdd288SMatthias Ringwald static int has_more_remote_name_requests(void){
152fffdd288SMatthias Ringwald     int i;
153fffdd288SMatthias Ringwald     for (i=0;i<deviceCount;i++) {
154fffdd288SMatthias Ringwald         if (devices[i].state == REMOTE_NAME_REQUEST) return 1;
155fffdd288SMatthias Ringwald     }
156fffdd288SMatthias Ringwald     return 0;
157fffdd288SMatthias Ringwald }
158fffdd288SMatthias Ringwald 
159fffdd288SMatthias Ringwald static void do_next_remote_name_request(void){
160fffdd288SMatthias Ringwald     int i;
161fffdd288SMatthias Ringwald     for (i=0;i<deviceCount;i++) {
162fffdd288SMatthias Ringwald         // remote name request
163fffdd288SMatthias Ringwald         if (devices[i].state == REMOTE_NAME_REQUEST){
164fffdd288SMatthias Ringwald             devices[i].state = REMOTE_NAME_INQUIRED;
165fffdd288SMatthias Ringwald             printf("Get remote name of %s...\n", bd_addr_to_str(devices[i].address));
166fffdd288SMatthias Ringwald             hci_send_cmd(&hci_remote_name_request, devices[i].address,
167fffdd288SMatthias Ringwald                         devices[i].pageScanRepetitionMode, 0, devices[i].clockOffset | 0x8000);
168fffdd288SMatthias Ringwald             return;
169fffdd288SMatthias Ringwald         }
170fffdd288SMatthias Ringwald     }
171fffdd288SMatthias Ringwald }
172fffdd288SMatthias Ringwald 
173fffdd288SMatthias Ringwald static void continue_remote_names(void){
174fffdd288SMatthias Ringwald     // don't get remote names for testing
175fffdd288SMatthias Ringwald     if (has_more_remote_name_requests()){
176fffdd288SMatthias Ringwald         do_next_remote_name_request();
177fffdd288SMatthias Ringwald         return;
178fffdd288SMatthias Ringwald     }
179fffdd288SMatthias Ringwald     // try to find PTS
180fffdd288SMatthias Ringwald     int i;
181fffdd288SMatthias Ringwald     for (i=0;i<deviceCount;i++){
182fffdd288SMatthias Ringwald         if (memcmp(devices[i].address, device_addr, 6) == 0){
183fffdd288SMatthias Ringwald             printf("Inquiry scan over, successfully found PTS at index %u\nReady to connect to it.\n", i);
184fffdd288SMatthias Ringwald             return;
185fffdd288SMatthias Ringwald         }
186fffdd288SMatthias Ringwald     }
187fffdd288SMatthias Ringwald     printf("Inquiry scan over but PTS not found :(\n");
188fffdd288SMatthias Ringwald }
189fffdd288SMatthias Ringwald 
190fffdd288SMatthias Ringwald static void inquiry_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
191fffdd288SMatthias Ringwald     bd_addr_t addr;
192fffdd288SMatthias Ringwald     int i;
193fffdd288SMatthias Ringwald     int numResponses;
194fffdd288SMatthias Ringwald     int index;
195fffdd288SMatthias Ringwald 
196fffdd288SMatthias Ringwald     // printf("packet_handler: pt: 0x%02x, packet[0]: 0x%02x\n", packet_type, packet[0]);
197fffdd288SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
198fffdd288SMatthias Ringwald 
199fffdd288SMatthias Ringwald     uint8_t event = packet[0];
200fffdd288SMatthias Ringwald 
201fffdd288SMatthias Ringwald     switch(event){
202fffdd288SMatthias Ringwald         case HCI_EVENT_INQUIRY_RESULT:
203fffdd288SMatthias Ringwald         case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{
204f8744deaSMilanka Ringwald             numResponses = hci_event_inquiry_result_get_num_responses(packet);
205fffdd288SMatthias Ringwald             int offset = 3;
206fffdd288SMatthias Ringwald             for (i=0; i<numResponses && deviceCount < MAX_DEVICES;i++){
207e64e0086SMatthias Ringwald                 reverse_bd_addr(&packet[offset], addr);
208fffdd288SMatthias Ringwald                 offset += 6;
209fffdd288SMatthias Ringwald                 index = getDeviceIndexForAddress(addr);
210fffdd288SMatthias Ringwald                 if (index >= 0) continue;   // already in our list
211fffdd288SMatthias Ringwald                 memcpy(devices[deviceCount].address, addr, 6);
212fffdd288SMatthias Ringwald 
213fffdd288SMatthias Ringwald                 devices[deviceCount].pageScanRepetitionMode = packet[offset];
214fffdd288SMatthias Ringwald                 offset += 1;
215fffdd288SMatthias Ringwald 
216fffdd288SMatthias Ringwald                 if (event == HCI_EVENT_INQUIRY_RESULT){
217fffdd288SMatthias Ringwald                     offset += 2; // Reserved + Reserved
218fffdd288SMatthias Ringwald                     devices[deviceCount].classOfDevice = little_endian_read_24(packet, offset);
219fffdd288SMatthias Ringwald                     offset += 3;
220fffdd288SMatthias Ringwald                     devices[deviceCount].clockOffset =   little_endian_read_16(packet, offset) & 0x7fff;
221fffdd288SMatthias Ringwald                     offset += 2;
222fffdd288SMatthias Ringwald                     devices[deviceCount].rssi  = 0;
223fffdd288SMatthias Ringwald                 } else {
224fffdd288SMatthias Ringwald                     offset += 1; // Reserved
225fffdd288SMatthias Ringwald                     devices[deviceCount].classOfDevice = little_endian_read_24(packet, offset);
226fffdd288SMatthias Ringwald                     offset += 3;
227fffdd288SMatthias Ringwald                     devices[deviceCount].clockOffset =   little_endian_read_16(packet, offset) & 0x7fff;
228fffdd288SMatthias Ringwald                     offset += 2;
229fffdd288SMatthias Ringwald                     devices[deviceCount].rssi  = packet[offset];
230fffdd288SMatthias Ringwald                     offset += 1;
231fffdd288SMatthias Ringwald                 }
232fffdd288SMatthias Ringwald                 devices[deviceCount].state = REMOTE_NAME_REQUEST;
233fffdd288SMatthias Ringwald                 printf("Device #%u found: %s with COD: 0x%06x, pageScan %d, clock offset 0x%04x, rssi 0x%02x\n",
234fffdd288SMatthias Ringwald                     deviceCount, bd_addr_to_str(addr),
235fffdd288SMatthias Ringwald                     devices[deviceCount].classOfDevice, devices[deviceCount].pageScanRepetitionMode,
236fffdd288SMatthias Ringwald                     devices[deviceCount].clockOffset, devices[deviceCount].rssi);
237fffdd288SMatthias Ringwald                 deviceCount++;
238fffdd288SMatthias Ringwald             }
239fffdd288SMatthias Ringwald 
240fffdd288SMatthias Ringwald             break;
241fffdd288SMatthias Ringwald         }
242fffdd288SMatthias Ringwald         case HCI_EVENT_INQUIRY_COMPLETE:
243fffdd288SMatthias Ringwald             for (i=0;i<deviceCount;i++) {
244fffdd288SMatthias Ringwald                 // retry remote name request
245fffdd288SMatthias Ringwald                 if (devices[i].state == REMOTE_NAME_INQUIRED)
246fffdd288SMatthias Ringwald                     devices[i].state = REMOTE_NAME_REQUEST;
247fffdd288SMatthias Ringwald             }
248fffdd288SMatthias Ringwald             continue_remote_names();
249fffdd288SMatthias Ringwald             break;
250fffdd288SMatthias Ringwald 
251fffdd288SMatthias Ringwald         case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
252e64e0086SMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
253fffdd288SMatthias Ringwald             index = getDeviceIndexForAddress(addr);
254fffdd288SMatthias Ringwald             if (index >= 0) {
255fffdd288SMatthias Ringwald                 if (packet[2] == 0) {
256fffdd288SMatthias Ringwald                     printf("Name: '%s'\n", &packet[9]);
257fffdd288SMatthias Ringwald                     devices[index].state = REMOTE_NAME_FETCHED;
258fffdd288SMatthias Ringwald                 } else {
259fffdd288SMatthias Ringwald                     printf("Failed to get name: page timeout\n");
260fffdd288SMatthias Ringwald                 }
261fffdd288SMatthias Ringwald             }
262fffdd288SMatthias Ringwald             continue_remote_names();
263fffdd288SMatthias Ringwald             break;
264fffdd288SMatthias Ringwald 
265fffdd288SMatthias Ringwald         default:
266fffdd288SMatthias Ringwald             break;
267fffdd288SMatthias Ringwald     }
268fffdd288SMatthias Ringwald }
269fffdd288SMatthias Ringwald // GAP INQUIRY END
270d0755cd6SMatthias Ringwald #ifdef HAVE_POSIX_STDIN
271fffdd288SMatthias Ringwald 
272fffdd288SMatthias Ringwald // prototypes
27335833313SMatthias Ringwald static void show_usage(void);
274fffdd288SMatthias Ringwald 
275fffdd288SMatthias Ringwald // Testig User Interface
276fffdd288SMatthias Ringwald static void show_usage(void){
277e64e0086SMatthias Ringwald     bd_addr_t iut_address;
278e64e0086SMatthias Ringwald     gap_local_bd_addr(iut_address);
279e64e0086SMatthias Ringwald 
280e64e0086SMatthias Ringwald     printf("\n--- Bluetooth HFP Audiogateway (AG) unit Test Console %s ---\n", bd_addr_to_str(iut_address));
281fffdd288SMatthias Ringwald     printf("---\n");
282fffdd288SMatthias Ringwald 
283*bdb44bd9SMatthias Ringwald     printf("a - establish HFP connection to PTS module %s\n", bd_addr_to_str(device_addr));
284fffdd288SMatthias Ringwald     // printf("A - release HFP connection to PTS module\n");
285fffdd288SMatthias Ringwald 
286fffdd288SMatthias Ringwald     printf("b - establish AUDIO connection\n");
287fffdd288SMatthias Ringwald     printf("B - release AUDIO connection\n");
288fffdd288SMatthias Ringwald 
289fffdd288SMatthias Ringwald     printf("c - simulate incoming call from 1234567\n");
290fffdd288SMatthias Ringwald     printf("C - simulate call from 1234567 dropped\n");
291fffdd288SMatthias Ringwald 
292fffdd288SMatthias Ringwald     printf("d - report AG failure\n");
293fffdd288SMatthias Ringwald 
294fffdd288SMatthias Ringwald     printf("e - answer call on AG\n");
295fffdd288SMatthias Ringwald     printf("E - reject call on AG\n");
296fffdd288SMatthias Ringwald 
297fffdd288SMatthias Ringwald     printf("r - disable in-band ring tone\n");
298fffdd288SMatthias Ringwald     printf("R - enable in-band ring tone\n");
299fffdd288SMatthias Ringwald 
300fffdd288SMatthias Ringwald     printf("f - Disable cellular network\n");
301fffdd288SMatthias Ringwald     printf("F - Enable cellular network\n");
302fffdd288SMatthias Ringwald 
303fffdd288SMatthias Ringwald     printf("g - Set signal strength to 0\n");
304fffdd288SMatthias Ringwald     printf("G - Set signal strength to 5\n");
305fffdd288SMatthias Ringwald 
306fffdd288SMatthias Ringwald     printf("h - Disable roaming\n");
307fffdd288SMatthias Ringwald     printf("H - Enable roaming\n");
308fffdd288SMatthias Ringwald 
309fffdd288SMatthias Ringwald     printf("i - Set battery level to 3\n");
310fffdd288SMatthias Ringwald     printf("I - Set battery level to 5\n");
311fffdd288SMatthias Ringwald 
312fffdd288SMatthias Ringwald     printf("j - Answering call on remote side\n");
313fffdd288SMatthias Ringwald 
314fffdd288SMatthias Ringwald     printf("k - Clear memory #1\n");
315fffdd288SMatthias Ringwald     printf("K - Set memory #1\n");
316fffdd288SMatthias Ringwald 
317fffdd288SMatthias Ringwald     printf("l - Clear last number\n");
318fffdd288SMatthias Ringwald     printf("L - Set last number\n");
319fffdd288SMatthias Ringwald 
320fffdd288SMatthias Ringwald     printf("m - simulate incoming call from 7654321\n");
321fffdd288SMatthias Ringwald     // printf("M - simulate call from 7654321 dropped\n");
322fffdd288SMatthias Ringwald 
323fffdd288SMatthias Ringwald     printf("n - Disable Voice Regocnition\n");
324fffdd288SMatthias Ringwald     printf("N - Enable Voice Recognition\n");
325fffdd288SMatthias Ringwald 
326fffdd288SMatthias Ringwald     printf("o - Set speaker volume to 0  (minimum)\n");
327fffdd288SMatthias Ringwald     printf("O - Set speaker volume to 9  (default)\n");
328fffdd288SMatthias Ringwald     printf("p - Set speaker volume to 12 (higher)\n");
329fffdd288SMatthias Ringwald     printf("P - Set speaker volume to 15 (maximum)\n");
330fffdd288SMatthias Ringwald 
331fffdd288SMatthias Ringwald     printf("q - Set microphone gain to 0  (minimum)\n");
332fffdd288SMatthias Ringwald     printf("Q - Set microphone gain to 9  (default)\n");
333fffdd288SMatthias Ringwald     printf("s - Set microphone gain to 12 (higher)\n");
334fffdd288SMatthias Ringwald     printf("S - Set microphone gain to 15 (maximum)\n");
335fffdd288SMatthias Ringwald 
336fffdd288SMatthias Ringwald     printf("t - terminate connection\n");
337fffdd288SMatthias Ringwald     printf("u - join held call\n");
338fffdd288SMatthias Ringwald     printf("v - discover nearby HF units\n");
339fffdd288SMatthias Ringwald     printf("w - put incoming call on hold (Response and Hold)\n");
340fffdd288SMatthias Ringwald     printf("x - accept held incoming call (Response and Hold)\n");
341fffdd288SMatthias Ringwald     printf("X - reject held incoming call (Response and Hold)\n");
342fffdd288SMatthias Ringwald 
343fffdd288SMatthias Ringwald     printf("---\n");
344fffdd288SMatthias Ringwald     printf("Ctrl-c - exit\n");
345fffdd288SMatthias Ringwald     printf("---\n");
346fffdd288SMatthias Ringwald }
347fffdd288SMatthias Ringwald 
3484af4141bSMatthias Ringwald static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
349fffdd288SMatthias Ringwald     read(ds->fd, &cmd, 1);
350fffdd288SMatthias Ringwald     switch (cmd){
351fffdd288SMatthias Ringwald         case 'a':
352fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
353fffdd288SMatthias Ringwald             printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
354fffdd288SMatthias Ringwald             hfp_ag_establish_service_level_connection(device_addr);
355fffdd288SMatthias Ringwald             break;
356fffdd288SMatthias Ringwald         case 'A':
357fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
358fffdd288SMatthias Ringwald             printf("Release HFP service level connection.\n");
359fffdd288SMatthias Ringwald             hfp_ag_release_service_level_connection(device_addr);
360fffdd288SMatthias Ringwald             break;
361fffdd288SMatthias Ringwald         case 'Z':
362fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
363fffdd288SMatthias Ringwald             printf("Release HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
364fffdd288SMatthias Ringwald             hfp_ag_release_service_level_connection(device_addr);
365fffdd288SMatthias Ringwald             break;
366fffdd288SMatthias Ringwald         case 'b':
367fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
368fffdd288SMatthias Ringwald             printf("Establish Audio connection %s...\n", bd_addr_to_str(device_addr));
369fffdd288SMatthias Ringwald             hfp_ag_establish_audio_connection(device_addr);
370fffdd288SMatthias Ringwald             break;
371fffdd288SMatthias Ringwald         case 'B':
372fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
373fffdd288SMatthias Ringwald             printf("Release Audio connection.\n");
374fffdd288SMatthias Ringwald             hfp_ag_release_audio_connection(device_addr);
375fffdd288SMatthias Ringwald             break;
376fffdd288SMatthias Ringwald         case 'c':
377fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
378fffdd288SMatthias Ringwald             printf("Simulate incoming call from 1234567\n");
379fffdd288SMatthias Ringwald             hfp_ag_set_clip(129, "1234567");
380fffdd288SMatthias Ringwald             hfp_ag_incoming_call();
381fffdd288SMatthias Ringwald             break;
382fffdd288SMatthias Ringwald         case 'm':
383fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
384fffdd288SMatthias Ringwald             printf("Simulate incoming call from 7654321\n");
385fffdd288SMatthias Ringwald             hfp_ag_set_clip(129, "7654321");
386fffdd288SMatthias Ringwald             hfp_ag_incoming_call();
387fffdd288SMatthias Ringwald             break;
388fffdd288SMatthias Ringwald         case 'C':
389fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
390fffdd288SMatthias Ringwald             printf("Simulate terminate call\n");
391fffdd288SMatthias Ringwald             hfp_ag_call_dropped();
392fffdd288SMatthias Ringwald             break;
393fffdd288SMatthias Ringwald         case 'd':
394fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
395fffdd288SMatthias Ringwald             printf("Report AG failure\n");
396fffdd288SMatthias Ringwald             hfp_ag_report_extended_audio_gateway_error_result_code(device_addr, HFP_CME_ERROR_AG_FAILURE);
397fffdd288SMatthias Ringwald             break;
398fffdd288SMatthias Ringwald         case 'e':
399fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
400fffdd288SMatthias Ringwald             printf("Answer call on AG\n");
401fffdd288SMatthias Ringwald             hfp_ag_answer_incoming_call();
402fffdd288SMatthias Ringwald             break;
403fffdd288SMatthias Ringwald         case 'E':
404fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
405fffdd288SMatthias Ringwald             printf("Reject call on AG\n");
406fffdd288SMatthias Ringwald             hfp_ag_terminate_call();
407fffdd288SMatthias Ringwald             break;
408fffdd288SMatthias Ringwald         case 'f':
409fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
410fffdd288SMatthias Ringwald             printf("Disable cellular network\n");
411fffdd288SMatthias Ringwald             hfp_ag_set_registration_status(0);
412fffdd288SMatthias Ringwald             break;
413fffdd288SMatthias Ringwald         case 'F':
414fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
415fffdd288SMatthias Ringwald             printf("Enable cellular network\n");
416fffdd288SMatthias Ringwald             hfp_ag_set_registration_status(1);
417fffdd288SMatthias Ringwald             break;
418fffdd288SMatthias Ringwald         case 'g':
419fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
420fffdd288SMatthias Ringwald             printf("Set signal strength to 0\n");
421fffdd288SMatthias Ringwald             hfp_ag_set_signal_strength(0);
422fffdd288SMatthias Ringwald             break;
423fffdd288SMatthias Ringwald         case 'G':
424fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
425fffdd288SMatthias Ringwald             printf("Set signal strength to 5\n");
426fffdd288SMatthias Ringwald             hfp_ag_set_signal_strength(5);
427fffdd288SMatthias Ringwald             break;
428fffdd288SMatthias Ringwald         case 'h':
429fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
430fffdd288SMatthias Ringwald             printf("Disable roaming\n");
431fffdd288SMatthias Ringwald             hfp_ag_set_roaming_status(0);
432fffdd288SMatthias Ringwald             break;
433fffdd288SMatthias Ringwald         case 'H':
434fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
435fffdd288SMatthias Ringwald             printf("Enable roaming\n");
436fffdd288SMatthias Ringwald             hfp_ag_set_roaming_status(1);
437fffdd288SMatthias Ringwald             break;
438fffdd288SMatthias Ringwald         case 'i':
439fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
440fffdd288SMatthias Ringwald             printf("Set battery level to 3\n");
441fffdd288SMatthias Ringwald             hfp_ag_set_battery_level(3);
442fffdd288SMatthias Ringwald             break;
443fffdd288SMatthias Ringwald         case 'I':
444fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
445fffdd288SMatthias Ringwald             printf("Set battery level to 5\n");
446fffdd288SMatthias Ringwald             hfp_ag_set_battery_level(5);
447fffdd288SMatthias Ringwald             break;
448fffdd288SMatthias Ringwald         case 'j':
449fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
450fffdd288SMatthias Ringwald             printf("Answering call on remote side\n");
451fffdd288SMatthias Ringwald             hfp_ag_outgoing_call_established();
452fffdd288SMatthias Ringwald             break;
453fffdd288SMatthias Ringwald         case 'r':
454fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
455fffdd288SMatthias Ringwald             printf("Disable in-band ring tone\n");
456fffdd288SMatthias Ringwald             hfp_ag_set_use_in_band_ring_tone(0);
457fffdd288SMatthias Ringwald             break;
458fffdd288SMatthias Ringwald         case 'k':
459fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
460fffdd288SMatthias Ringwald             printf("Memory 1 cleared\n");
461fffdd288SMatthias Ringwald             memory_1_enabled = 0;
462fffdd288SMatthias Ringwald             break;
463fffdd288SMatthias Ringwald         case 'K':
464fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
465fffdd288SMatthias Ringwald             printf("Memory 1 set\n");
466fffdd288SMatthias Ringwald             memory_1_enabled = 1;
467fffdd288SMatthias Ringwald             break;
468fffdd288SMatthias Ringwald         case 'l':
469fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
470fffdd288SMatthias Ringwald             printf("Last dialed number cleared\n");
471fffdd288SMatthias Ringwald             hfp_ag_clear_last_dialed_number();
472fffdd288SMatthias Ringwald             break;
473fffdd288SMatthias Ringwald         case 'L':
474fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
475fffdd288SMatthias Ringwald             printf("Outgoing call connected, ringing\n");
476fffdd288SMatthias Ringwald             hfp_ag_outgoing_call_ringing();
477fffdd288SMatthias Ringwald             break;
478fffdd288SMatthias Ringwald         case 'n':
479fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
480fffdd288SMatthias Ringwald             printf("Disable Voice Recognition\n");
481fffdd288SMatthias Ringwald             hfp_ag_activate_voice_recognition(device_addr, 0);
482fffdd288SMatthias Ringwald             break;
483fffdd288SMatthias Ringwald         case 'N':
484fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
485fffdd288SMatthias Ringwald             printf("Enable Voice Recognition\n");
486fffdd288SMatthias Ringwald             hfp_ag_activate_voice_recognition(device_addr, 1);
487fffdd288SMatthias Ringwald             break;
488fffdd288SMatthias Ringwald         case 'o':
489fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
490fffdd288SMatthias Ringwald             printf("Set speaker gain to 0 (minimum)\n");
491fffdd288SMatthias Ringwald             hfp_ag_set_speaker_gain(device_addr, 0);
492fffdd288SMatthias Ringwald             break;
493fffdd288SMatthias Ringwald         case 'O':
494fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
495fffdd288SMatthias Ringwald             printf("Set speaker gain to 9 (default)\n");
496fffdd288SMatthias Ringwald             hfp_ag_set_speaker_gain(device_addr, 9);
497fffdd288SMatthias Ringwald             break;
498fffdd288SMatthias Ringwald         case 'p':
499fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
500fffdd288SMatthias Ringwald             printf("Set speaker gain to 12 (higher)\n");
501fffdd288SMatthias Ringwald             hfp_ag_set_speaker_gain(device_addr, 12);
502fffdd288SMatthias Ringwald             break;
503fffdd288SMatthias Ringwald         case 'P':
504fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
505fffdd288SMatthias Ringwald             printf("Set speaker gain to 15 (maximum)\n");
506fffdd288SMatthias Ringwald             hfp_ag_set_speaker_gain(device_addr, 15);
507fffdd288SMatthias Ringwald             break;
508fffdd288SMatthias Ringwald         case 'q':
509fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
510fffdd288SMatthias Ringwald             printf("Set microphone gain to 0\n");
511fffdd288SMatthias Ringwald             hfp_ag_set_microphone_gain(device_addr, 0);
512fffdd288SMatthias Ringwald             break;
513fffdd288SMatthias Ringwald         case 'Q':
514fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
515fffdd288SMatthias Ringwald             printf("Set microphone gain to 9\n");
516fffdd288SMatthias Ringwald             hfp_ag_set_microphone_gain(device_addr, 9);
517fffdd288SMatthias Ringwald             break;
518fffdd288SMatthias Ringwald         case 's':
519fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
520fffdd288SMatthias Ringwald             printf("Set microphone gain to 12\n");
521fffdd288SMatthias Ringwald             hfp_ag_set_microphone_gain(device_addr, 12);
522fffdd288SMatthias Ringwald             break;
523fffdd288SMatthias Ringwald         case 'S':
524fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
525fffdd288SMatthias Ringwald             printf("Set microphone gain to 15\n");
526fffdd288SMatthias Ringwald             hfp_ag_set_microphone_gain(device_addr, 15);
527fffdd288SMatthias Ringwald             break;
528fffdd288SMatthias Ringwald         case 'R':
529fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
530fffdd288SMatthias Ringwald             printf("Enable in-band ring tone\n");
531fffdd288SMatthias Ringwald             hfp_ag_set_use_in_band_ring_tone(1);
532fffdd288SMatthias Ringwald             break;
533fffdd288SMatthias Ringwald         case 't':
534fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
535e64e0086SMatthias Ringwald             printf("Terminate HCI connection. 0x%2x\n", handle);
536fffdd288SMatthias Ringwald             gap_disconnect(handle);
537fffdd288SMatthias Ringwald             break;
538fffdd288SMatthias Ringwald         case 'u':
539fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
540fffdd288SMatthias Ringwald             printf("Join held call\n");
541fffdd288SMatthias Ringwald             hfp_ag_join_held_call();
542fffdd288SMatthias Ringwald             break;
543fffdd288SMatthias Ringwald         case 'v':
544fffdd288SMatthias Ringwald             start_scan();
545fffdd288SMatthias Ringwald             break;
546fffdd288SMatthias Ringwald         case 'w':
547fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
548fffdd288SMatthias Ringwald             printf("AG: Put incoming call on hold (Response and Hold)\n");
549fffdd288SMatthias Ringwald             hfp_ag_hold_incoming_call();
550fffdd288SMatthias Ringwald             break;
551fffdd288SMatthias Ringwald         case 'x':
552fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
553fffdd288SMatthias Ringwald             printf("AG: Accept held incoming call (Response and Hold)\n");
554fffdd288SMatthias Ringwald             hfp_ag_accept_held_incoming_call();
555fffdd288SMatthias Ringwald             break;
556fffdd288SMatthias Ringwald         case 'X':
557fffdd288SMatthias Ringwald             log_info("USER:\'%c\'", cmd);
558fffdd288SMatthias Ringwald             printf("AG: Reject held incoming call (Response and Hold)\n");
559fffdd288SMatthias Ringwald             hfp_ag_reject_held_incoming_call();
560fffdd288SMatthias Ringwald             break;
561fffdd288SMatthias Ringwald         default:
562fffdd288SMatthias Ringwald             show_usage();
563fffdd288SMatthias Ringwald             break;
564fffdd288SMatthias Ringwald     }
565fffdd288SMatthias Ringwald }
566fffdd288SMatthias Ringwald #endif
567fffdd288SMatthias Ringwald 
5683cef842bSMatthias Ringwald #define SCO_REPORT_PERIOD 100
5693cef842bSMatthias Ringwald static void send_sco_data(void){
5703cef842bSMatthias Ringwald     if (!sco_handle) return;
5713cef842bSMatthias Ringwald 
5723cef842bSMatthias Ringwald     const int sco_packet_length = hci_get_sco_packet_length();
5733cef842bSMatthias Ringwald     const int sco_payload_length = sco_packet_length - 3;
5743cef842bSMatthias Ringwald     const int frames_per_packet = sco_payload_length;    // for 8-bit data. for 16-bit data it's /2
5753cef842bSMatthias Ringwald 
5763cef842bSMatthias Ringwald     hci_reserve_packet_buffer();
5773cef842bSMatthias Ringwald     uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
5783cef842bSMatthias Ringwald     // set handle + flags
5793cef842bSMatthias Ringwald     little_endian_store_16(sco_packet, 0, sco_handle);
5803cef842bSMatthias Ringwald     // set len
5813cef842bSMatthias Ringwald     sco_packet[2] = sco_payload_length;
5823cef842bSMatthias Ringwald     int i;
5833cef842bSMatthias Ringwald     for (i=0;i<frames_per_packet;i++){
5843cef842bSMatthias Ringwald         sco_packet[3+i] = sine[phase];
5853cef842bSMatthias Ringwald         phase++;
5863cef842bSMatthias Ringwald         if (phase >= sizeof(sine)) phase = 0;
5873cef842bSMatthias Ringwald     }
5883cef842bSMatthias Ringwald     hci_send_sco_packet_buffer(sco_packet_length);
5893cef842bSMatthias Ringwald 
5903cef842bSMatthias Ringwald     // request another send event
5913cef842bSMatthias Ringwald     hci_request_sco_can_send_now_event();
5923cef842bSMatthias Ringwald 
5933cef842bSMatthias Ringwald     static int count = 0;
5943cef842bSMatthias Ringwald     count++;
595*bdb44bd9SMatthias Ringwald     if ((count % SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count);
5963cef842bSMatthias Ringwald }
5973cef842bSMatthias Ringwald 
59813839019SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){
5993cef842bSMatthias Ringwald     switch (packet_type){
6003cef842bSMatthias Ringwald         case HCI_EVENT_PACKET:
601fffdd288SMatthias Ringwald             switch (event[0]){
602fffdd288SMatthias Ringwald                 case HCI_EVENT_INQUIRY_RESULT:
603fffdd288SMatthias Ringwald                 case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
604fffdd288SMatthias Ringwald                 case HCI_EVENT_INQUIRY_COMPLETE:
605fffdd288SMatthias Ringwald                 case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
606fffdd288SMatthias Ringwald                     inquiry_packet_handler(HCI_EVENT_PACKET, event, event_size);
607fffdd288SMatthias Ringwald                     break;
60813839019SMatthias Ringwald                 case HCI_EVENT_SCO_CAN_SEND_NOW:
60913839019SMatthias Ringwald                     send_sco_data();
61013839019SMatthias Ringwald                     break;
611fffdd288SMatthias Ringwald                 default:
612fffdd288SMatthias Ringwald                     break;
613fffdd288SMatthias Ringwald             }
614fffdd288SMatthias Ringwald 
615fffdd288SMatthias Ringwald             if (event[0] != HCI_EVENT_HFP_META) return;
616fffdd288SMatthias Ringwald 
617fffdd288SMatthias Ringwald             if (event[3]
618fffdd288SMatthias Ringwald                 && event[2] != HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER
619fffdd288SMatthias Ringwald                 && event[2] != HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG
620fffdd288SMatthias Ringwald                 && event[2] != HFP_SUBEVENT_TRANSMIT_DTMF_CODES){
621fffdd288SMatthias Ringwald                 printf("ERROR, status: %u\n", event[3]);
622fffdd288SMatthias Ringwald                 return;
623fffdd288SMatthias Ringwald             }
624fffdd288SMatthias Ringwald 
625fffdd288SMatthias Ringwald             switch (event[2]) {
626fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
627a0653c3bSMilanka Ringwald                     handle = hfp_subevent_service_level_connection_established_get_con_handle(event);
628fffdd288SMatthias Ringwald                     printf("Service level connection established.\n");
629fffdd288SMatthias Ringwald                     break;
630fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
631fffdd288SMatthias Ringwald                     printf("Service level connection released.\n");
6323cef842bSMatthias Ringwald                     sco_handle = 0;
633fffdd288SMatthias Ringwald                     break;
634fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED:
6353cef842bSMatthias Ringwald                     if (hfp_subevent_audio_connection_established_get_status(event)){
6363cef842bSMatthias Ringwald                         printf("Audio connection establishment failed with status %u\n", hfp_subevent_audio_connection_established_get_status(event));
6373cef842bSMatthias Ringwald                         sco_handle = 0;
6383cef842bSMatthias Ringwald                     } else {
6393cef842bSMatthias Ringwald                         sco_handle = hfp_subevent_audio_connection_established_get_handle(event);
6403cef842bSMatthias Ringwald                         printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
6413cef842bSMatthias Ringwald                         hci_request_sco_can_send_now_event();
6423cef842bSMatthias Ringwald                     }
643fffdd288SMatthias Ringwald                     break;
644fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED:
645fffdd288SMatthias Ringwald                     printf("\n** Audio connection released **\n");
6463cef842bSMatthias Ringwald                     sco_handle = 0;
647fffdd288SMatthias Ringwald                     break;
648fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_START_RINGINIG:
649fffdd288SMatthias Ringwald                     printf("\n** Start Ringing **\n");
650fffdd288SMatthias Ringwald                     break;
651fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_STOP_RINGINIG:
652fffdd288SMatthias Ringwald                     printf("\n** Stop Ringing **\n");
653fffdd288SMatthias Ringwald                     break;
654fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER:
6550696953aSMilanka Ringwald                     printf("\n** Outgoing call '%s' **\n", hfp_subevent_place_call_with_number_get_number(event));
656fffdd288SMatthias Ringwald                     // validate number
6570696953aSMilanka Ringwald                     if ( strcmp("1234567", hfp_subevent_place_call_with_number_get_number(event)) == 0
6580696953aSMilanka Ringwald                       || strcmp("7654321", hfp_subevent_place_call_with_number_get_number(event)) == 0
6590696953aSMilanka Ringwald                       || (memory_1_enabled && strcmp(">1", hfp_subevent_place_call_with_number_get_number(event)) == 0)){
660fffdd288SMatthias Ringwald                         printf("Dialstring valid: accept call\n");
661fffdd288SMatthias Ringwald                         hfp_ag_outgoing_call_accepted();
662fffdd288SMatthias Ringwald                     } else {
663fffdd288SMatthias Ringwald                         printf("Dialstring invalid: reject call\n");
664fffdd288SMatthias Ringwald                         hfp_ag_outgoing_call_rejected();
665fffdd288SMatthias Ringwald                     }
666fffdd288SMatthias Ringwald                     break;
667fffdd288SMatthias Ringwald 
668fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG:
669fffdd288SMatthias Ringwald                     printf("\n** Attach number to voice tag. Sending '1234567\n");
670fffdd288SMatthias Ringwald                     hfp_ag_send_phone_number_for_voice_tag(device_addr, "1234567");
671fffdd288SMatthias Ringwald                     break;
672fffdd288SMatthias Ringwald                 case HFP_SUBEVENT_TRANSMIT_DTMF_CODES:
6730696953aSMilanka Ringwald                     printf("\n** Send DTMF Codes: '%s'\n", hfp_subevent_transmit_dtmf_codes_get_dtmf(event));
674fffdd288SMatthias Ringwald                     hfp_ag_send_dtmf_code_done(device_addr);
675fffdd288SMatthias Ringwald                     break;
6760696953aSMilanka Ringwald                 case HFP_SUBEVENT_CALL_ANSWERED:
677fffdd288SMatthias Ringwald                     printf("Call answered by HF\n");
678fffdd288SMatthias Ringwald                     break;
679fffdd288SMatthias Ringwald                 default:
680fffdd288SMatthias Ringwald                     printf("Event not handled %u\n", event[2]);
681fffdd288SMatthias Ringwald                     break;
682fffdd288SMatthias Ringwald             }
68313839019SMatthias Ringwald         default:
68413839019SMatthias Ringwald             break;
68513839019SMatthias Ringwald     }
686fffdd288SMatthias Ringwald }
687fffdd288SMatthias Ringwald 
688fffdd288SMatthias Ringwald static hfp_phone_number_t subscriber_number = {
689fffdd288SMatthias Ringwald     129, "225577"
690fffdd288SMatthias Ringwald };
691fffdd288SMatthias Ringwald 
692fffdd288SMatthias Ringwald /* @section Main Application Setup
693fffdd288SMatthias Ringwald  *
694fffdd288SMatthias Ringwald  * @text Listing MainConfiguration shows main application code.
695fffdd288SMatthias Ringwald  * To run a HFP AG service you need to initialize the SDP, and to create and register HFP AG record with it.
696fffdd288SMatthias Ringwald  * The packet_handler is used for sending commands to the HFP HF. It also receives the HFP HF's answers.
697fffdd288SMatthias Ringwald  * The stdin_process callback allows for sending commands to the HFP HF.
698fffdd288SMatthias Ringwald  * At the end the Bluetooth stack is started.
699fffdd288SMatthias Ringwald  */
700fffdd288SMatthias Ringwald 
701fffdd288SMatthias Ringwald /* LISTING_START(MainConfiguration): Setup HFP Audio Gateway */
702fffdd288SMatthias Ringwald 
703fffdd288SMatthias Ringwald int btstack_main(int argc, const char * argv[]);
704fffdd288SMatthias Ringwald int btstack_main(int argc, const char * argv[]){
705fffdd288SMatthias Ringwald 
706e64e0086SMatthias Ringwald     gap_discoverable_control(1);
707e64e0086SMatthias Ringwald 
708e64e0086SMatthias Ringwald     // L2CAP
709e64e0086SMatthias Ringwald     l2cap_init();
710e64e0086SMatthias Ringwald 
711e64e0086SMatthias Ringwald     // HFP
712e64e0086SMatthias Ringwald     rfcomm_init();
713fffdd288SMatthias Ringwald     hfp_ag_init(rfcomm_channel_nr);
714fffdd288SMatthias Ringwald     hfp_ag_init_supported_features(0x3ef | (1<<HFP_AGSF_HF_INDICATORS) | (1<<HFP_AGSF_ESCO_S4));
715fffdd288SMatthias Ringwald     hfp_ag_init_codecs(sizeof(codecs), codecs);
716fffdd288SMatthias Ringwald     hfp_ag_init_ag_indicators(ag_indicators_nr, ag_indicators);
717fffdd288SMatthias Ringwald     hfp_ag_init_hf_indicators(hf_indicators_nr, hf_indicators);
718fffdd288SMatthias Ringwald     hfp_ag_init_call_hold_services(call_hold_services_nr, call_hold_services);
719fffdd288SMatthias Ringwald     hfp_ag_set_subcriber_number_information(&subscriber_number, 1);
7203cef842bSMatthias Ringwald     hfp_ag_register_packet_handler(&packet_handler);
72113839019SMatthias Ringwald     hci_register_sco_packet_handler(&packet_handler);
722fffdd288SMatthias Ringwald 
723e64e0086SMatthias Ringwald     // SDP Server
724e64e0086SMatthias Ringwald     sdp_init();
725fffdd288SMatthias Ringwald     memset(hfp_service_buffer, 0, sizeof(hfp_service_buffer));
726fffdd288SMatthias Ringwald     hfp_ag_create_sdp_record( hfp_service_buffer, 0x10001, rfcomm_channel_nr, hfp_ag_service_name, 0, 0);
727fffdd288SMatthias Ringwald     printf("SDP service record size: %u\n", de_get_len( hfp_service_buffer));
728fffdd288SMatthias Ringwald     sdp_register_service(hfp_service_buffer);
729fffdd288SMatthias Ringwald 
730d0755cd6SMatthias Ringwald #ifdef HAVE_POSIX_STDIN
731fffdd288SMatthias Ringwald     btstack_stdin_setup(stdin_process);
732fffdd288SMatthias Ringwald #endif
733fffdd288SMatthias Ringwald     // turn on!
734fffdd288SMatthias Ringwald     hci_power_control(HCI_POWER_ON);
735fffdd288SMatthias Ringwald     return 0;
736fffdd288SMatthias Ringwald }
737fffdd288SMatthias Ringwald /* LISTING_END */
7382b6b8c15SMilanka Ringwald /* EXAMPLE_END */
739