xref: /btstack/src/classic/hfp_hf.c (revision 3deb3ec68039c68a16974dffc53343233662f909)
1*3deb3ec6SMatthias Ringwald /*
2*3deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*3deb3ec6SMatthias Ringwald  *
4*3deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*3deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*3deb3ec6SMatthias Ringwald  * are met:
7*3deb3ec6SMatthias Ringwald  *
8*3deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*3deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*3deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*3deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*3deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*3deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
16*3deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*3deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*3deb3ec6SMatthias Ringwald  *    monetary gain.
19*3deb3ec6SMatthias Ringwald  *
20*3deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*3deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*3deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*3deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*3deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*3deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*3deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*3deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*3deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*3deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*3deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*3deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
32*3deb3ec6SMatthias Ringwald  *
33*3deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
34*3deb3ec6SMatthias Ringwald  * [email protected]
35*3deb3ec6SMatthias Ringwald  *
36*3deb3ec6SMatthias Ringwald  */
37*3deb3ec6SMatthias Ringwald 
38*3deb3ec6SMatthias Ringwald // *****************************************************************************
39*3deb3ec6SMatthias Ringwald //
40*3deb3ec6SMatthias Ringwald // Minimal setup for HFP Hands-Free (HF) unit (!! UNDER DEVELOPMENT !!)
41*3deb3ec6SMatthias Ringwald //
42*3deb3ec6SMatthias Ringwald // *****************************************************************************
43*3deb3ec6SMatthias Ringwald 
44*3deb3ec6SMatthias Ringwald #include "btstack-config.h"
45*3deb3ec6SMatthias Ringwald 
46*3deb3ec6SMatthias Ringwald #include <stdint.h>
47*3deb3ec6SMatthias Ringwald #include <stdio.h>
48*3deb3ec6SMatthias Ringwald #include <stdlib.h>
49*3deb3ec6SMatthias Ringwald #include <string.h>
50*3deb3ec6SMatthias Ringwald 
51*3deb3ec6SMatthias Ringwald #include "hci_cmds.h"
52*3deb3ec6SMatthias Ringwald #include "run_loop.h"
53*3deb3ec6SMatthias Ringwald 
54*3deb3ec6SMatthias Ringwald #include "hci.h"
55*3deb3ec6SMatthias Ringwald #include "btstack_memory.h"
56*3deb3ec6SMatthias Ringwald #include "hci_dump.h"
57*3deb3ec6SMatthias Ringwald #include "l2cap.h"
58*3deb3ec6SMatthias Ringwald #include "sdp_query_rfcomm.h"
59*3deb3ec6SMatthias Ringwald #include "sdp.h"
60*3deb3ec6SMatthias Ringwald #include "debug.h"
61*3deb3ec6SMatthias Ringwald #include "hfp.h"
62*3deb3ec6SMatthias Ringwald #include "hfp_hf.h"
63*3deb3ec6SMatthias Ringwald 
64*3deb3ec6SMatthias Ringwald 
65*3deb3ec6SMatthias Ringwald static const char default_hfp_hf_service_name[] = "Hands-Free unit";
66*3deb3ec6SMatthias Ringwald static uint16_t hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES;
67*3deb3ec6SMatthias Ringwald static uint8_t hfp_codecs_nr = 0;
68*3deb3ec6SMatthias Ringwald static uint8_t hfp_codecs[HFP_MAX_NUM_CODECS];
69*3deb3ec6SMatthias Ringwald 
70*3deb3ec6SMatthias Ringwald static uint8_t hfp_indicators_nr = 0;
71*3deb3ec6SMatthias Ringwald static uint8_t hfp_indicators[HFP_MAX_NUM_HF_INDICATORS];
72*3deb3ec6SMatthias Ringwald static uint8_t hfp_indicators_status;
73*3deb3ec6SMatthias Ringwald 
74*3deb3ec6SMatthias Ringwald static hfp_callback_t hfp_callback;
75*3deb3ec6SMatthias Ringwald 
76*3deb3ec6SMatthias Ringwald void hfp_hf_register_packet_handler(hfp_callback_t callback){
77*3deb3ec6SMatthias Ringwald     hfp_callback = callback;
78*3deb3ec6SMatthias Ringwald     if (callback == NULL){
79*3deb3ec6SMatthias Ringwald         log_error("hfp_hf_register_packet_handler called with NULL callback");
80*3deb3ec6SMatthias Ringwald         return;
81*3deb3ec6SMatthias Ringwald     }
82*3deb3ec6SMatthias Ringwald     hfp_callback = callback;
83*3deb3ec6SMatthias Ringwald }
84*3deb3ec6SMatthias Ringwald 
85*3deb3ec6SMatthias Ringwald static int hfp_hf_supports_codec(uint8_t codec){
86*3deb3ec6SMatthias Ringwald     int i;
87*3deb3ec6SMatthias Ringwald     for (i = 0; i < hfp_codecs_nr; i++){
88*3deb3ec6SMatthias Ringwald         if (hfp_codecs[i] == codec) return 1;
89*3deb3ec6SMatthias Ringwald     }
90*3deb3ec6SMatthias Ringwald     return 0;
91*3deb3ec6SMatthias Ringwald }
92*3deb3ec6SMatthias Ringwald static int has_codec_negotiation_feature(hfp_connection_t * connection){
93*3deb3ec6SMatthias Ringwald     int hf = get_bit(hfp_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
94*3deb3ec6SMatthias Ringwald     int ag = get_bit(connection->remote_supported_features, HFP_AGSF_CODEC_NEGOTIATION);
95*3deb3ec6SMatthias Ringwald     return hf && ag;
96*3deb3ec6SMatthias Ringwald }
97*3deb3ec6SMatthias Ringwald 
98*3deb3ec6SMatthias Ringwald static int has_call_waiting_and_3way_calling_feature(hfp_connection_t * connection){
99*3deb3ec6SMatthias Ringwald     int hf = get_bit(hfp_supported_features, HFP_HFSF_THREE_WAY_CALLING);
100*3deb3ec6SMatthias Ringwald     int ag = get_bit(connection->remote_supported_features, HFP_AGSF_THREE_WAY_CALLING);
101*3deb3ec6SMatthias Ringwald     return hf && ag;
102*3deb3ec6SMatthias Ringwald }
103*3deb3ec6SMatthias Ringwald 
104*3deb3ec6SMatthias Ringwald 
105*3deb3ec6SMatthias Ringwald static int has_hf_indicators_feature(hfp_connection_t * connection){
106*3deb3ec6SMatthias Ringwald     int hf = get_bit(hfp_supported_features, HFP_HFSF_HF_INDICATORS);
107*3deb3ec6SMatthias Ringwald     int ag = get_bit(connection->remote_supported_features, HFP_AGSF_HF_INDICATORS);
108*3deb3ec6SMatthias Ringwald     return hf && ag;
109*3deb3ec6SMatthias Ringwald }
110*3deb3ec6SMatthias Ringwald 
111*3deb3ec6SMatthias Ringwald static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
112*3deb3ec6SMatthias Ringwald 
113*3deb3ec6SMatthias Ringwald void hfp_hf_create_sdp_record(uint8_t * service, int rfcomm_channel_nr, const char * name, uint16_t supported_features){
114*3deb3ec6SMatthias Ringwald     if (!name){
115*3deb3ec6SMatthias Ringwald         name = default_hfp_hf_service_name;
116*3deb3ec6SMatthias Ringwald     }
117*3deb3ec6SMatthias Ringwald     hfp_create_sdp_record(service, SDP_Handsfree, rfcomm_channel_nr, name, supported_features);
118*3deb3ec6SMatthias Ringwald }
119*3deb3ec6SMatthias Ringwald 
120*3deb3ec6SMatthias Ringwald 
121*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_exchange_supported_features(uint16_t cid){
122*3deb3ec6SMatthias Ringwald     char buffer[20];
123*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_SUPPORTED_FEATURES, hfp_supported_features);
124*3deb3ec6SMatthias Ringwald     // printf("exchange_supported_features %s\n", buffer);
125*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
126*3deb3ec6SMatthias Ringwald }
127*3deb3ec6SMatthias Ringwald 
128*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_notify_on_codecs(uint16_t cid){
129*3deb3ec6SMatthias Ringwald     char buffer[30];
130*3deb3ec6SMatthias Ringwald     int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_AVAILABLE_CODECS);
131*3deb3ec6SMatthias Ringwald     offset += join(buffer+offset, sizeof(buffer)-offset, hfp_codecs, hfp_codecs_nr);
132*3deb3ec6SMatthias Ringwald     offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
133*3deb3ec6SMatthias Ringwald     buffer[offset] = 0;
134*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
135*3deb3ec6SMatthias Ringwald }
136*3deb3ec6SMatthias Ringwald 
137*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_indicators(uint16_t cid){
138*3deb3ec6SMatthias Ringwald     char buffer[20];
139*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=?\r\n", HFP_INDICATOR);
140*3deb3ec6SMatthias Ringwald     // printf("retrieve_indicators %s\n", buffer);
141*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
142*3deb3ec6SMatthias Ringwald }
143*3deb3ec6SMatthias Ringwald 
144*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_indicators_status(uint16_t cid){
145*3deb3ec6SMatthias Ringwald     char buffer[20];
146*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s?\r\n", HFP_INDICATOR);
147*3deb3ec6SMatthias Ringwald     // printf("retrieve_indicators_status %s\n", buffer);
148*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
149*3deb3ec6SMatthias Ringwald }
150*3deb3ec6SMatthias Ringwald 
151*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_activate_status_update_for_all_ag_indicators(uint16_t cid, uint8_t activate){
152*3deb3ec6SMatthias Ringwald     char buffer[20];
153*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=3,0,0,%d\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS, activate);
154*3deb3ec6SMatthias Ringwald     // printf("toggle_indicator_status_update %s\n", buffer);
155*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
156*3deb3ec6SMatthias Ringwald }
157*3deb3ec6SMatthias Ringwald 
158*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_activate_status_update_for_ag_indicator(uint16_t cid, uint32_t indicators_status, int indicators_nr){
159*3deb3ec6SMatthias Ringwald     char buffer[50];
160*3deb3ec6SMatthias Ringwald     int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS);
161*3deb3ec6SMatthias Ringwald     offset += join_bitmap(buffer+offset, sizeof(buffer)-offset, indicators_status, indicators_nr);
162*3deb3ec6SMatthias Ringwald     offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
163*3deb3ec6SMatthias Ringwald     buffer[offset] = 0;
164*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
165*3deb3ec6SMatthias Ringwald }
166*3deb3ec6SMatthias Ringwald 
167*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_can_hold_call(uint16_t cid){
168*3deb3ec6SMatthias Ringwald     char buffer[20];
169*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=?\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES);
170*3deb3ec6SMatthias Ringwald     // printf("retrieve_can_hold_call %s\n", buffer);
171*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
172*3deb3ec6SMatthias Ringwald }
173*3deb3ec6SMatthias Ringwald 
174*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_list_supported_generic_status_indicators(uint16_t cid){
175*3deb3ec6SMatthias Ringwald     char buffer[30];
176*3deb3ec6SMatthias Ringwald     int offset = snprintf(buffer, sizeof(buffer), "AT%s=", HFP_GENERIC_STATUS_INDICATOR);
177*3deb3ec6SMatthias Ringwald     offset += join(buffer+offset, sizeof(buffer)-offset, hfp_indicators, hfp_indicators_nr);
178*3deb3ec6SMatthias Ringwald     offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
179*3deb3ec6SMatthias Ringwald     buffer[offset] = 0;
180*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
181*3deb3ec6SMatthias Ringwald }
182*3deb3ec6SMatthias Ringwald 
183*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_retrieve_supported_generic_status_indicators(uint16_t cid){
184*3deb3ec6SMatthias Ringwald     char buffer[20];
185*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=?\r\n", HFP_GENERIC_STATUS_INDICATOR);
186*3deb3ec6SMatthias Ringwald     // printf("retrieve_supported_generic_status_indicators %s\n", buffer);
187*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
188*3deb3ec6SMatthias Ringwald }
189*3deb3ec6SMatthias Ringwald 
190*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_list_initital_supported_generic_status_indicators(uint16_t cid){
191*3deb3ec6SMatthias Ringwald     char buffer[20];
192*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s?\r\n", HFP_GENERIC_STATUS_INDICATOR);
193*3deb3ec6SMatthias Ringwald     // printf("list_initital_supported_generic_status_indicators %s\n", buffer);
194*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
195*3deb3ec6SMatthias Ringwald }
196*3deb3ec6SMatthias Ringwald 
197*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_query_operator_name_format(uint16_t cid){
198*3deb3ec6SMatthias Ringwald     char buffer[20];
199*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION);
200*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
201*3deb3ec6SMatthias Ringwald }
202*3deb3ec6SMatthias Ringwald 
203*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_query_operator_name(uint16_t cid){
204*3deb3ec6SMatthias Ringwald     char buffer[20];
205*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION);
206*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
207*3deb3ec6SMatthias Ringwald }
208*3deb3ec6SMatthias Ringwald 
209*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_enable_extended_audio_gateway_error_report(uint16_t cid, uint8_t enable){
210*3deb3ec6SMatthias Ringwald     char buffer[20];
211*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, enable);
212*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
213*3deb3ec6SMatthias Ringwald }
214*3deb3ec6SMatthias Ringwald 
215*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_trigger_codec_connection_setup(uint16_t cid){
216*3deb3ec6SMatthias Ringwald     char buffer[20];
217*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s\r\n", HFP_TRIGGER_CODEC_CONNECTION_SETUP);
218*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
219*3deb3ec6SMatthias Ringwald }
220*3deb3ec6SMatthias Ringwald 
221*3deb3ec6SMatthias Ringwald static int hfp_hf_cmd_confirm_codec(uint16_t cid, uint8_t codec){
222*3deb3ec6SMatthias Ringwald     char buffer[20];
223*3deb3ec6SMatthias Ringwald     sprintf(buffer, "AT%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec);
224*3deb3ec6SMatthias Ringwald     return send_str_over_rfcomm(cid, buffer);
225*3deb3ec6SMatthias Ringwald }
226*3deb3ec6SMatthias Ringwald 
227*3deb3ec6SMatthias Ringwald static void hfp_emit_ag_indicator_event(hfp_callback_t callback, int status, hfp_ag_indicator_t indicator){
228*3deb3ec6SMatthias Ringwald     if (!callback) return;
229*3deb3ec6SMatthias Ringwald     uint8_t event[6];
230*3deb3ec6SMatthias Ringwald     event[0] = HCI_EVENT_HFP_META;
231*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
232*3deb3ec6SMatthias Ringwald     event[2] = HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED;
233*3deb3ec6SMatthias Ringwald     event[3] = status;
234*3deb3ec6SMatthias Ringwald     event[4] = indicator.index;
235*3deb3ec6SMatthias Ringwald     event[5] = indicator.status;
236*3deb3ec6SMatthias Ringwald     (*callback)(event, sizeof(event));
237*3deb3ec6SMatthias Ringwald }
238*3deb3ec6SMatthias Ringwald 
239*3deb3ec6SMatthias Ringwald static void hfp_emit_network_operator_event(hfp_callback_t callback, int status, hfp_network_opearator_t network_operator){
240*3deb3ec6SMatthias Ringwald     if (!callback) return;
241*3deb3ec6SMatthias Ringwald     uint8_t event[24];
242*3deb3ec6SMatthias Ringwald     event[0] = HCI_EVENT_HFP_META;
243*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
244*3deb3ec6SMatthias Ringwald     event[2] = HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED;
245*3deb3ec6SMatthias Ringwald     event[3] = status;
246*3deb3ec6SMatthias Ringwald     event[4] = network_operator.mode;
247*3deb3ec6SMatthias Ringwald     event[5] = network_operator.format;
248*3deb3ec6SMatthias Ringwald     strcpy((char*)&event[6], network_operator.name);
249*3deb3ec6SMatthias Ringwald     (*callback)(event, sizeof(event));
250*3deb3ec6SMatthias Ringwald }
251*3deb3ec6SMatthias Ringwald 
252*3deb3ec6SMatthias Ringwald static int hfp_hf_run_for_context_service_level_connection(hfp_connection_t * context){
253*3deb3ec6SMatthias Ringwald     if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
254*3deb3ec6SMatthias Ringwald     int done = 0;
255*3deb3ec6SMatthias Ringwald     if (context->wait_ok) return done;
256*3deb3ec6SMatthias Ringwald 
257*3deb3ec6SMatthias Ringwald     switch (context->state){
258*3deb3ec6SMatthias Ringwald         case HFP_EXCHANGE_SUPPORTED_FEATURES:
259*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_exchange_supported_features(context->rfcomm_cid);
260*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
261*3deb3ec6SMatthias Ringwald             break;
262*3deb3ec6SMatthias Ringwald         case HFP_NOTIFY_ON_CODECS:
263*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
264*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_NOTIFY_ON_CODECS;
265*3deb3ec6SMatthias Ringwald             break;
266*3deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_INDICATORS:
267*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_retrieve_indicators(context->rfcomm_cid);
268*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_INDICATORS;
269*3deb3ec6SMatthias Ringwald             context->retrieve_ag_indicators = 1;
270*3deb3ec6SMatthias Ringwald             context->retrieve_ag_indicators_status = 0;
271*3deb3ec6SMatthias Ringwald             break;
272*3deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_INDICATORS_STATUS:
273*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_retrieve_indicators_status(context->rfcomm_cid);
274*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
275*3deb3ec6SMatthias Ringwald             context->retrieve_ag_indicators_status = 1;
276*3deb3ec6SMatthias Ringwald             context->retrieve_ag_indicators = 0;
277*3deb3ec6SMatthias Ringwald             break;
278*3deb3ec6SMatthias Ringwald         case HFP_ENABLE_INDICATORS_STATUS_UPDATE:
279*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_activate_status_update_for_all_ag_indicators(context->rfcomm_cid, 1);
280*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
281*3deb3ec6SMatthias Ringwald             break;
282*3deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_CAN_HOLD_CALL:
283*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_retrieve_can_hold_call(context->rfcomm_cid);
284*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
285*3deb3ec6SMatthias Ringwald             break;
286*3deb3ec6SMatthias Ringwald         case HFP_LIST_GENERIC_STATUS_INDICATORS:
287*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_list_supported_generic_status_indicators(context->rfcomm_cid);
288*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
289*3deb3ec6SMatthias Ringwald             context->list_generic_status_indicators = 1;
290*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators = 0;
291*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators_state = 0;
292*3deb3ec6SMatthias Ringwald             break;
293*3deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS:
294*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_retrieve_supported_generic_status_indicators(context->rfcomm_cid);
295*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
296*3deb3ec6SMatthias Ringwald             context->list_generic_status_indicators = 0;
297*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators = 1;
298*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators_state = 0;
299*3deb3ec6SMatthias Ringwald             break;
300*3deb3ec6SMatthias Ringwald         case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
301*3deb3ec6SMatthias Ringwald             hfp_hf_cmd_list_initital_supported_generic_status_indicators(context->rfcomm_cid);
302*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
303*3deb3ec6SMatthias Ringwald             context->list_generic_status_indicators = 0;
304*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators = 0;
305*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators_state = 1;
306*3deb3ec6SMatthias Ringwald             break;
307*3deb3ec6SMatthias Ringwald         default:
308*3deb3ec6SMatthias Ringwald             break;
309*3deb3ec6SMatthias Ringwald     }
310*3deb3ec6SMatthias Ringwald     return done;
311*3deb3ec6SMatthias Ringwald }
312*3deb3ec6SMatthias Ringwald 
313*3deb3ec6SMatthias Ringwald static void hfp_hf_handle_ok_service_level_connection_establishment(hfp_connection_t *context){
314*3deb3ec6SMatthias Ringwald     if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return;
315*3deb3ec6SMatthias Ringwald     switch (context->state){
316*3deb3ec6SMatthias Ringwald         case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
317*3deb3ec6SMatthias Ringwald             if (has_codec_negotiation_feature(context)){
318*3deb3ec6SMatthias Ringwald                 context->state = HFP_NOTIFY_ON_CODECS;
319*3deb3ec6SMatthias Ringwald                 break;
320*3deb3ec6SMatthias Ringwald             }
321*3deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INDICATORS;
322*3deb3ec6SMatthias Ringwald             break;
323*3deb3ec6SMatthias Ringwald 
324*3deb3ec6SMatthias Ringwald         case HFP_W4_NOTIFY_ON_CODECS:
325*3deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INDICATORS;
326*3deb3ec6SMatthias Ringwald             break;
327*3deb3ec6SMatthias Ringwald 
328*3deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_INDICATORS:
329*3deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INDICATORS_STATUS;
330*3deb3ec6SMatthias Ringwald             context->retrieve_ag_indicators = 0;
331*3deb3ec6SMatthias Ringwald             break;
332*3deb3ec6SMatthias Ringwald 
333*3deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_INDICATORS_STATUS:
334*3deb3ec6SMatthias Ringwald             context->state = HFP_ENABLE_INDICATORS_STATUS_UPDATE;
335*3deb3ec6SMatthias Ringwald             context->retrieve_ag_indicators_status = 0;
336*3deb3ec6SMatthias Ringwald             break;
337*3deb3ec6SMatthias Ringwald 
338*3deb3ec6SMatthias Ringwald         case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
339*3deb3ec6SMatthias Ringwald             if (has_call_waiting_and_3way_calling_feature(context)){
340*3deb3ec6SMatthias Ringwald                 context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
341*3deb3ec6SMatthias Ringwald                 break;
342*3deb3ec6SMatthias Ringwald             }
343*3deb3ec6SMatthias Ringwald             if (has_hf_indicators_feature(context)){
344*3deb3ec6SMatthias Ringwald                 context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
345*3deb3ec6SMatthias Ringwald                 break;
346*3deb3ec6SMatthias Ringwald             }
347*3deb3ec6SMatthias Ringwald             context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
348*3deb3ec6SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
349*3deb3ec6SMatthias Ringwald             break;
350*3deb3ec6SMatthias Ringwald 
351*3deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_CAN_HOLD_CALL:
352*3deb3ec6SMatthias Ringwald             if (has_hf_indicators_feature(context)){
353*3deb3ec6SMatthias Ringwald                 context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
354*3deb3ec6SMatthias Ringwald                 break;
355*3deb3ec6SMatthias Ringwald             }
356*3deb3ec6SMatthias Ringwald             context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
357*3deb3ec6SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
358*3deb3ec6SMatthias Ringwald            break;
359*3deb3ec6SMatthias Ringwald 
360*3deb3ec6SMatthias Ringwald         case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
361*3deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS;
362*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators = 0;
363*3deb3ec6SMatthias Ringwald             break;
364*3deb3ec6SMatthias Ringwald 
365*3deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
366*3deb3ec6SMatthias Ringwald             context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
367*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators = 0;
368*3deb3ec6SMatthias Ringwald             break;
369*3deb3ec6SMatthias Ringwald 
370*3deb3ec6SMatthias Ringwald         case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
371*3deb3ec6SMatthias Ringwald             context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
372*3deb3ec6SMatthias Ringwald             context->retrieve_generic_status_indicators_state = 0;
373*3deb3ec6SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
374*3deb3ec6SMatthias Ringwald             break;
375*3deb3ec6SMatthias Ringwald         default:
376*3deb3ec6SMatthias Ringwald             break;
377*3deb3ec6SMatthias Ringwald     }
378*3deb3ec6SMatthias Ringwald }
379*3deb3ec6SMatthias Ringwald 
380*3deb3ec6SMatthias Ringwald static void hfp_hf_run_for_context_service_level_connection_queries(hfp_connection_t * context){
381*3deb3ec6SMatthias Ringwald     if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return;
382*3deb3ec6SMatthias Ringwald     if (context->wait_ok) return;
383*3deb3ec6SMatthias Ringwald 
384*3deb3ec6SMatthias Ringwald     if (context->enable_status_update_for_ag_indicators != 0xFF){
385*3deb3ec6SMatthias Ringwald         hfp_hf_cmd_activate_status_update_for_all_ag_indicators(context->rfcomm_cid, context->enable_status_update_for_ag_indicators);
386*3deb3ec6SMatthias Ringwald         context->wait_ok = 1;
387*3deb3ec6SMatthias Ringwald         return;
388*3deb3ec6SMatthias Ringwald     };
389*3deb3ec6SMatthias Ringwald     if (context->change_status_update_for_individual_ag_indicators){
390*3deb3ec6SMatthias Ringwald         hfp_hf_cmd_activate_status_update_for_ag_indicator(context->rfcomm_cid,
391*3deb3ec6SMatthias Ringwald                 context->ag_indicators_status_update_bitmap,
392*3deb3ec6SMatthias Ringwald                 context->ag_indicators_nr);
393*3deb3ec6SMatthias Ringwald         context->wait_ok = 1;
394*3deb3ec6SMatthias Ringwald         return;
395*3deb3ec6SMatthias Ringwald     }
396*3deb3ec6SMatthias Ringwald 
397*3deb3ec6SMatthias Ringwald     if (context->operator_name_format){
398*3deb3ec6SMatthias Ringwald         hfp_hf_cmd_query_operator_name_format(context->rfcomm_cid);
399*3deb3ec6SMatthias Ringwald         context->wait_ok = 1;
400*3deb3ec6SMatthias Ringwald         return;
401*3deb3ec6SMatthias Ringwald     }
402*3deb3ec6SMatthias Ringwald     if (context->operator_name){
403*3deb3ec6SMatthias Ringwald         hfp_hf_cmd_query_operator_name(context->rfcomm_cid);
404*3deb3ec6SMatthias Ringwald         context->wait_ok = 1;
405*3deb3ec6SMatthias Ringwald         return;
406*3deb3ec6SMatthias Ringwald     }
407*3deb3ec6SMatthias Ringwald 
408*3deb3ec6SMatthias Ringwald     if (context->enable_extended_audio_gateway_error_report){
409*3deb3ec6SMatthias Ringwald         hfp_hf_cmd_enable_extended_audio_gateway_error_report(context->rfcomm_cid, context->enable_extended_audio_gateway_error_report);
410*3deb3ec6SMatthias Ringwald         context->wait_ok = 1;
411*3deb3ec6SMatthias Ringwald         return;
412*3deb3ec6SMatthias Ringwald     }
413*3deb3ec6SMatthias Ringwald }
414*3deb3ec6SMatthias Ringwald 
415*3deb3ec6SMatthias Ringwald static void hfp_hf_handle_ok_service_level_connection_queries(hfp_connection_t * context){
416*3deb3ec6SMatthias Ringwald     if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return;
417*3deb3ec6SMatthias Ringwald 
418*3deb3ec6SMatthias Ringwald     if (context->enable_status_update_for_ag_indicators != 0xFF){
419*3deb3ec6SMatthias Ringwald         context->enable_status_update_for_ag_indicators = 0xFF;
420*3deb3ec6SMatthias Ringwald         hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0);
421*3deb3ec6SMatthias Ringwald         return;
422*3deb3ec6SMatthias Ringwald     };
423*3deb3ec6SMatthias Ringwald 
424*3deb3ec6SMatthias Ringwald     if (context->change_status_update_for_individual_ag_indicators == 1){
425*3deb3ec6SMatthias Ringwald         context->change_status_update_for_individual_ag_indicators = 0;
426*3deb3ec6SMatthias Ringwald         hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0);
427*3deb3ec6SMatthias Ringwald         return;
428*3deb3ec6SMatthias Ringwald     }
429*3deb3ec6SMatthias Ringwald 
430*3deb3ec6SMatthias Ringwald     if (context->operator_name_format){
431*3deb3ec6SMatthias Ringwald         context->operator_name_format = 0;
432*3deb3ec6SMatthias Ringwald         context->operator_name = 1;
433*3deb3ec6SMatthias Ringwald         return;
434*3deb3ec6SMatthias Ringwald     }
435*3deb3ec6SMatthias Ringwald 
436*3deb3ec6SMatthias Ringwald     if (context->operator_name){
437*3deb3ec6SMatthias Ringwald         context->operator_name = 0;
438*3deb3ec6SMatthias Ringwald         hfp_emit_network_operator_event(hfp_callback, 0, context->network_operator);
439*3deb3ec6SMatthias Ringwald         return;
440*3deb3ec6SMatthias Ringwald     }
441*3deb3ec6SMatthias Ringwald     if (context->enable_extended_audio_gateway_error_report){
442*3deb3ec6SMatthias Ringwald         context->enable_extended_audio_gateway_error_report = 0;
443*3deb3ec6SMatthias Ringwald         return;
444*3deb3ec6SMatthias Ringwald     }
445*3deb3ec6SMatthias Ringwald }
446*3deb3ec6SMatthias Ringwald 
447*3deb3ec6SMatthias Ringwald 
448*3deb3ec6SMatthias Ringwald static void hfp_hf_run_for_context_codecs_connection(hfp_connection_t * context){
449*3deb3ec6SMatthias Ringwald     // if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED && context->state <= HFP_AUDIO_CONNECTION_ESTABLISHED){
450*3deb3ec6SMatthias Ringwald 
451*3deb3ec6SMatthias Ringwald     // handle audio connection setup
452*3deb3ec6SMatthias Ringwald     // printf("hfp_run_for_context state %d \n", context->state);
453*3deb3ec6SMatthias Ringwald     if (context->wait_ok) return;
454*3deb3ec6SMatthias Ringwald 
455*3deb3ec6SMatthias Ringwald     switch (context->state){
456*3deb3ec6SMatthias Ringwald         case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
457*3deb3ec6SMatthias Ringwald             if (context->notify_ag_on_new_codecs){
458*3deb3ec6SMatthias Ringwald                 context->wait_ok = 1;
459*3deb3ec6SMatthias Ringwald                 hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
460*3deb3ec6SMatthias Ringwald                 break;
461*3deb3ec6SMatthias Ringwald             }
462*3deb3ec6SMatthias Ringwald 
463*3deb3ec6SMatthias Ringwald             if (context->hf_trigger_codec_connection_setup){
464*3deb3ec6SMatthias Ringwald                 context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
465*3deb3ec6SMatthias Ringwald                 context->wait_ok = 1;
466*3deb3ec6SMatthias Ringwald                 hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
467*3deb3ec6SMatthias Ringwald                 break;
468*3deb3ec6SMatthias Ringwald             }
469*3deb3ec6SMatthias Ringwald 
470*3deb3ec6SMatthias Ringwald             if (context->suggested_codec){
471*3deb3ec6SMatthias Ringwald                 context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
472*3deb3ec6SMatthias Ringwald                 context->codec_confirmed = 1;
473*3deb3ec6SMatthias Ringwald                 context->wait_ok = 1;
474*3deb3ec6SMatthias Ringwald                 hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
475*3deb3ec6SMatthias Ringwald                 break;
476*3deb3ec6SMatthias Ringwald             }
477*3deb3ec6SMatthias Ringwald             break;
478*3deb3ec6SMatthias Ringwald 
479*3deb3ec6SMatthias Ringwald         case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
480*3deb3ec6SMatthias Ringwald             if (context->notify_ag_on_new_codecs){
481*3deb3ec6SMatthias Ringwald                 context->wait_ok = 1;
482*3deb3ec6SMatthias Ringwald                 context->codec_confirmed = 0;
483*3deb3ec6SMatthias Ringwald                 context->suggested_codec = 0;
484*3deb3ec6SMatthias Ringwald                 context->negotiated_codec = 0;
485*3deb3ec6SMatthias Ringwald                 hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
486*3deb3ec6SMatthias Ringwald                 break;
487*3deb3ec6SMatthias Ringwald             }
488*3deb3ec6SMatthias Ringwald             if (context->suggested_codec){
489*3deb3ec6SMatthias Ringwald                 if (hfp_hf_supports_codec(context->suggested_codec)){
490*3deb3ec6SMatthias Ringwald                     context->codec_confirmed = context->suggested_codec;
491*3deb3ec6SMatthias Ringwald                     context->wait_ok = 1;
492*3deb3ec6SMatthias Ringwald                     hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
493*3deb3ec6SMatthias Ringwald                 } else {
494*3deb3ec6SMatthias Ringwald                     context->notify_ag_on_new_codecs = 1;
495*3deb3ec6SMatthias Ringwald                     context->wait_ok = 1;
496*3deb3ec6SMatthias Ringwald                     context->codec_confirmed = 0;
497*3deb3ec6SMatthias Ringwald                     context->suggested_codec = 0;
498*3deb3ec6SMatthias Ringwald                     context->negotiated_codec = 0;
499*3deb3ec6SMatthias Ringwald                     hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
500*3deb3ec6SMatthias Ringwald                 }
501*3deb3ec6SMatthias Ringwald 
502*3deb3ec6SMatthias Ringwald                 break;
503*3deb3ec6SMatthias Ringwald             }
504*3deb3ec6SMatthias Ringwald 
505*3deb3ec6SMatthias Ringwald             break;
506*3deb3ec6SMatthias Ringwald 
507*3deb3ec6SMatthias Ringwald         case HFP_CODECS_CONNECTION_ESTABLISHED:
508*3deb3ec6SMatthias Ringwald             if (context->notify_ag_on_new_codecs){
509*3deb3ec6SMatthias Ringwald                 context->negotiated_codec = 0;
510*3deb3ec6SMatthias Ringwald                 context->wait_ok = 1;
511*3deb3ec6SMatthias Ringwald                 context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
512*3deb3ec6SMatthias Ringwald                 hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
513*3deb3ec6SMatthias Ringwald                 break;
514*3deb3ec6SMatthias Ringwald             }
515*3deb3ec6SMatthias Ringwald 
516*3deb3ec6SMatthias Ringwald             if (context->hf_trigger_codec_connection_setup){
517*3deb3ec6SMatthias Ringwald                 context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
518*3deb3ec6SMatthias Ringwald                 context->wait_ok = 1;
519*3deb3ec6SMatthias Ringwald                 hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
520*3deb3ec6SMatthias Ringwald                 break;
521*3deb3ec6SMatthias Ringwald             }
522*3deb3ec6SMatthias Ringwald 
523*3deb3ec6SMatthias Ringwald             if (context->establish_audio_connection){
524*3deb3ec6SMatthias Ringwald                 // TODO AUDIO CONNECTION
525*3deb3ec6SMatthias Ringwald             }
526*3deb3ec6SMatthias Ringwald             break;
527*3deb3ec6SMatthias Ringwald        default:
528*3deb3ec6SMatthias Ringwald             break;
529*3deb3ec6SMatthias Ringwald     }
530*3deb3ec6SMatthias Ringwald }
531*3deb3ec6SMatthias Ringwald 
532*3deb3ec6SMatthias Ringwald static void hfp_hf_handle_ok_codecs_connection(hfp_connection_t * context){
533*3deb3ec6SMatthias Ringwald         // handle audio connection setup
534*3deb3ec6SMatthias Ringwald     switch (context->state){
535*3deb3ec6SMatthias Ringwald         case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
536*3deb3ec6SMatthias Ringwald             if (context->notify_ag_on_new_codecs){
537*3deb3ec6SMatthias Ringwald                 context->notify_ag_on_new_codecs = 0;
538*3deb3ec6SMatthias Ringwald                 break;
539*3deb3ec6SMatthias Ringwald             }
540*3deb3ec6SMatthias Ringwald         case HFP_SLE_W2_EXCHANGE_COMMON_CODEC:
541*3deb3ec6SMatthias Ringwald             if (context->hf_trigger_codec_connection_setup){
542*3deb3ec6SMatthias Ringwald                 context->hf_trigger_codec_connection_setup = 0;
543*3deb3ec6SMatthias Ringwald                 context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
544*3deb3ec6SMatthias Ringwald                 break;
545*3deb3ec6SMatthias Ringwald             }
546*3deb3ec6SMatthias Ringwald             break;
547*3deb3ec6SMatthias Ringwald         case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
548*3deb3ec6SMatthias Ringwald             if (context->notify_ag_on_new_codecs){
549*3deb3ec6SMatthias Ringwald                 context->codec_confirmed = 0;
550*3deb3ec6SMatthias Ringwald                 context->suggested_codec = 0;
551*3deb3ec6SMatthias Ringwald                 context->notify_ag_on_new_codecs = 0;
552*3deb3ec6SMatthias Ringwald                 break;
553*3deb3ec6SMatthias Ringwald             }
554*3deb3ec6SMatthias Ringwald             if (context->codec_confirmed && context->suggested_codec){
555*3deb3ec6SMatthias Ringwald                 context->negotiated_codec = context->suggested_codec;
556*3deb3ec6SMatthias Ringwald                 context->codec_confirmed = 0;
557*3deb3ec6SMatthias Ringwald                 context->suggested_codec = 0;
558*3deb3ec6SMatthias Ringwald                 context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
559*3deb3ec6SMatthias Ringwald                 hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
560*3deb3ec6SMatthias Ringwald                 break;
561*3deb3ec6SMatthias Ringwald             }
562*3deb3ec6SMatthias Ringwald             break;
563*3deb3ec6SMatthias Ringwald 
564*3deb3ec6SMatthias Ringwald         case HFP_AUDIO_CONNECTION_ESTABLISHED:
565*3deb3ec6SMatthias Ringwald             printf("HFP_AUDIO_CONNECTION_ESTABLISHED \n");
566*3deb3ec6SMatthias Ringwald             break;
567*3deb3ec6SMatthias Ringwald 
568*3deb3ec6SMatthias Ringwald         default:
569*3deb3ec6SMatthias Ringwald             break;
570*3deb3ec6SMatthias Ringwald     }
571*3deb3ec6SMatthias Ringwald }
572*3deb3ec6SMatthias Ringwald 
573*3deb3ec6SMatthias Ringwald static void hfp_run_for_context(hfp_connection_t * context){
574*3deb3ec6SMatthias Ringwald 
575*3deb3ec6SMatthias Ringwald     if (!context) return;
576*3deb3ec6SMatthias Ringwald     if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
577*3deb3ec6SMatthias Ringwald 
578*3deb3ec6SMatthias Ringwald     hfp_hf_run_for_context_service_level_connection(context);
579*3deb3ec6SMatthias Ringwald     hfp_hf_run_for_context_service_level_connection_queries(context);
580*3deb3ec6SMatthias Ringwald     hfp_hf_run_for_context_codecs_connection(context);
581*3deb3ec6SMatthias Ringwald 
582*3deb3ec6SMatthias Ringwald     // deal with disconnect
583*3deb3ec6SMatthias Ringwald     switch (context->state){
584*3deb3ec6SMatthias Ringwald         case HFP_W2_DISCONNECT_RFCOMM:
585*3deb3ec6SMatthias Ringwald             context->state = HFP_W4_RFCOMM_DISCONNECTED;
586*3deb3ec6SMatthias Ringwald             rfcomm_disconnect_internal(context->rfcomm_cid);
587*3deb3ec6SMatthias Ringwald             break;
588*3deb3ec6SMatthias Ringwald 
589*3deb3ec6SMatthias Ringwald         default:
590*3deb3ec6SMatthias Ringwald             break;
591*3deb3ec6SMatthias Ringwald     }
592*3deb3ec6SMatthias Ringwald }
593*3deb3ec6SMatthias Ringwald 
594*3deb3ec6SMatthias Ringwald static void hfp_hf_switch_on_ok(hfp_connection_t *context){
595*3deb3ec6SMatthias Ringwald     // printf("switch on ok\n");
596*3deb3ec6SMatthias Ringwald     context->wait_ok = 0;
597*3deb3ec6SMatthias Ringwald 
598*3deb3ec6SMatthias Ringwald     hfp_hf_handle_ok_service_level_connection_establishment(context);
599*3deb3ec6SMatthias Ringwald     hfp_hf_handle_ok_service_level_connection_queries(context);
600*3deb3ec6SMatthias Ringwald     hfp_hf_handle_ok_codecs_connection(context);
601*3deb3ec6SMatthias Ringwald 
602*3deb3ec6SMatthias Ringwald     // done
603*3deb3ec6SMatthias Ringwald     context->command = HFP_CMD_NONE;
604*3deb3ec6SMatthias Ringwald }
605*3deb3ec6SMatthias Ringwald 
606*3deb3ec6SMatthias Ringwald 
607*3deb3ec6SMatthias Ringwald static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
608*3deb3ec6SMatthias Ringwald     hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
609*3deb3ec6SMatthias Ringwald     if (!context) return;
610*3deb3ec6SMatthias Ringwald 
611*3deb3ec6SMatthias Ringwald     packet[size] = 0;
612*3deb3ec6SMatthias Ringwald     int pos, i;
613*3deb3ec6SMatthias Ringwald     //printf("\nHF received: %s", packet+2);
614*3deb3ec6SMatthias Ringwald     for (pos = 0; pos < size ; pos++){
615*3deb3ec6SMatthias Ringwald         hfp_parse(context, packet[pos]);
616*3deb3ec6SMatthias Ringwald 
617*3deb3ec6SMatthias Ringwald         // emit indicators status changed
618*3deb3ec6SMatthias Ringwald         for (i = 0; i < context->ag_indicators_nr; i++){
619*3deb3ec6SMatthias Ringwald             if (context->ag_indicators[i].status_changed) {
620*3deb3ec6SMatthias Ringwald                 hfp_emit_ag_indicator_event(hfp_callback, 0, context->ag_indicators[i]);
621*3deb3ec6SMatthias Ringwald                 context->ag_indicators[i].status_changed = 0;
622*3deb3ec6SMatthias Ringwald                 break;
623*3deb3ec6SMatthias Ringwald             }
624*3deb3ec6SMatthias Ringwald         }
625*3deb3ec6SMatthias Ringwald 
626*3deb3ec6SMatthias Ringwald         if (context->command == HFP_CMD_ERROR){
627*3deb3ec6SMatthias Ringwald             context->wait_ok = 0;
628*3deb3ec6SMatthias Ringwald             hfp_reset_context_flags(context);
629*3deb3ec6SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 1);
630*3deb3ec6SMatthias Ringwald             return;
631*3deb3ec6SMatthias Ringwald         }
632*3deb3ec6SMatthias Ringwald         if (context->command == HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR){
633*3deb3ec6SMatthias Ringwald             context->wait_ok = 0;
634*3deb3ec6SMatthias Ringwald             hfp_emit_event(hfp_callback, HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR, context->extended_audio_gateway_error);
635*3deb3ec6SMatthias Ringwald             context->extended_audio_gateway_error = 0;
636*3deb3ec6SMatthias Ringwald             return;
637*3deb3ec6SMatthias Ringwald         }
638*3deb3ec6SMatthias Ringwald 
639*3deb3ec6SMatthias Ringwald         if (context->command != HFP_CMD_OK) continue;
640*3deb3ec6SMatthias Ringwald         hfp_hf_switch_on_ok(context);
641*3deb3ec6SMatthias Ringwald     }
642*3deb3ec6SMatthias Ringwald }
643*3deb3ec6SMatthias Ringwald 
644*3deb3ec6SMatthias Ringwald static void hfp_run(){
645*3deb3ec6SMatthias Ringwald     linked_list_iterator_t it;
646*3deb3ec6SMatthias Ringwald     linked_list_iterator_init(&it, hfp_get_connections());
647*3deb3ec6SMatthias Ringwald     while (linked_list_iterator_has_next(&it)){
648*3deb3ec6SMatthias Ringwald         hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it);
649*3deb3ec6SMatthias Ringwald         hfp_run_for_context(connection);
650*3deb3ec6SMatthias Ringwald     }
651*3deb3ec6SMatthias Ringwald }
652*3deb3ec6SMatthias Ringwald 
653*3deb3ec6SMatthias Ringwald static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
654*3deb3ec6SMatthias Ringwald     switch (packet_type){
655*3deb3ec6SMatthias Ringwald         case RFCOMM_DATA_PACKET:
656*3deb3ec6SMatthias Ringwald             hfp_handle_rfcomm_event(packet_type, channel, packet, size);
657*3deb3ec6SMatthias Ringwald             break;
658*3deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
659*3deb3ec6SMatthias Ringwald             hfp_handle_hci_event(hfp_callback, packet_type, packet, size);
660*3deb3ec6SMatthias Ringwald         default:
661*3deb3ec6SMatthias Ringwald             break;
662*3deb3ec6SMatthias Ringwald     }
663*3deb3ec6SMatthias Ringwald     hfp_run();
664*3deb3ec6SMatthias Ringwald }
665*3deb3ec6SMatthias Ringwald 
666*3deb3ec6SMatthias Ringwald void hfp_hf_set_codecs(uint8_t * codecs, int codecs_nr){
667*3deb3ec6SMatthias Ringwald     if (codecs_nr > HFP_MAX_NUM_CODECS){
668*3deb3ec6SMatthias Ringwald         log_error("hfp_hf_set_codecs: codecs_nr (%d) > HFP_MAX_NUM_CODECS (%d)", codecs_nr, HFP_MAX_NUM_CODECS);
669*3deb3ec6SMatthias Ringwald         return;
670*3deb3ec6SMatthias Ringwald     }
671*3deb3ec6SMatthias Ringwald 
672*3deb3ec6SMatthias Ringwald     hfp_codecs_nr = codecs_nr;
673*3deb3ec6SMatthias Ringwald     int i;
674*3deb3ec6SMatthias Ringwald     for (i=0; i<codecs_nr; i++){
675*3deb3ec6SMatthias Ringwald         hfp_codecs[i] = codecs[i];
676*3deb3ec6SMatthias Ringwald     }
677*3deb3ec6SMatthias Ringwald 
678*3deb3ec6SMatthias Ringwald     char buffer[30];
679*3deb3ec6SMatthias Ringwald     int offset = join(buffer, sizeof(buffer), hfp_codecs, hfp_codecs_nr);
680*3deb3ec6SMatthias Ringwald     buffer[offset] = 0;
681*3deb3ec6SMatthias Ringwald     printf("set codecs %s\n", buffer);
682*3deb3ec6SMatthias Ringwald 
683*3deb3ec6SMatthias Ringwald     linked_list_iterator_t it;
684*3deb3ec6SMatthias Ringwald     linked_list_iterator_init(&it, hfp_get_connections());
685*3deb3ec6SMatthias Ringwald     while (linked_list_iterator_has_next(&it)){
686*3deb3ec6SMatthias Ringwald         hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it);
687*3deb3ec6SMatthias Ringwald         if (!connection) continue;
688*3deb3ec6SMatthias Ringwald         connection->notify_ag_on_new_codecs = 1;
689*3deb3ec6SMatthias Ringwald         hfp_run_for_context(connection);
690*3deb3ec6SMatthias Ringwald     }
691*3deb3ec6SMatthias Ringwald }
692*3deb3ec6SMatthias Ringwald 
693*3deb3ec6SMatthias Ringwald void hfp_hf_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, uint16_t * indicators, int indicators_nr, uint32_t indicators_status){
694*3deb3ec6SMatthias Ringwald     rfcomm_register_packet_handler(packet_handler);
695*3deb3ec6SMatthias Ringwald     hfp_init(rfcomm_channel_nr);
696*3deb3ec6SMatthias Ringwald 
697*3deb3ec6SMatthias Ringwald     hfp_supported_features = supported_features;
698*3deb3ec6SMatthias Ringwald 
699*3deb3ec6SMatthias Ringwald     hfp_indicators_nr = indicators_nr;
700*3deb3ec6SMatthias Ringwald     hfp_indicators_status = indicators_status;
701*3deb3ec6SMatthias Ringwald     int i;
702*3deb3ec6SMatthias Ringwald     for (i=0; i<indicators_nr; i++){
703*3deb3ec6SMatthias Ringwald         hfp_indicators[i] = indicators[i];
704*3deb3ec6SMatthias Ringwald     }
705*3deb3ec6SMatthias Ringwald }
706*3deb3ec6SMatthias Ringwald 
707*3deb3ec6SMatthias Ringwald void hfp_hf_establish_service_level_connection(bd_addr_t bd_addr){
708*3deb3ec6SMatthias Ringwald     hfp_establish_service_level_connection(bd_addr, SDP_HandsfreeAudioGateway);
709*3deb3ec6SMatthias Ringwald }
710*3deb3ec6SMatthias Ringwald 
711*3deb3ec6SMatthias Ringwald void hfp_hf_release_service_level_connection(bd_addr_t bd_addr){
712*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
713*3deb3ec6SMatthias Ringwald     hfp_release_service_level_connection(connection);
714*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
715*3deb3ec6SMatthias Ringwald }
716*3deb3ec6SMatthias Ringwald 
717*3deb3ec6SMatthias Ringwald void hfp_hf_enable_status_update_for_all_ag_indicators(bd_addr_t bd_addr, uint8_t enable){
718*3deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
719*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
720*3deb3ec6SMatthias Ringwald     if (!connection){
721*3deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
722*3deb3ec6SMatthias Ringwald         return;
723*3deb3ec6SMatthias Ringwald     }
724*3deb3ec6SMatthias Ringwald     connection->enable_status_update_for_ag_indicators = enable;
725*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
726*3deb3ec6SMatthias Ringwald }
727*3deb3ec6SMatthias Ringwald 
728*3deb3ec6SMatthias Ringwald // TODO: returned ERROR - wrong format
729*3deb3ec6SMatthias Ringwald void hfp_hf_enable_status_update_for_individual_ag_indicators(bd_addr_t bd_addr, uint32_t indicators_status_bitmap){
730*3deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
731*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
732*3deb3ec6SMatthias Ringwald     if (!connection){
733*3deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
734*3deb3ec6SMatthias Ringwald         return;
735*3deb3ec6SMatthias Ringwald     }
736*3deb3ec6SMatthias Ringwald     connection->change_status_update_for_individual_ag_indicators = 1;
737*3deb3ec6SMatthias Ringwald     connection->ag_indicators_status_update_bitmap = indicators_status_bitmap;
738*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
739*3deb3ec6SMatthias Ringwald }
740*3deb3ec6SMatthias Ringwald 
741*3deb3ec6SMatthias Ringwald void hfp_hf_query_operator_selection(bd_addr_t bd_addr){
742*3deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
743*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
744*3deb3ec6SMatthias Ringwald     if (!connection){
745*3deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
746*3deb3ec6SMatthias Ringwald         return;
747*3deb3ec6SMatthias Ringwald     }
748*3deb3ec6SMatthias Ringwald     connection->operator_name_format = 1;
749*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
750*3deb3ec6SMatthias Ringwald }
751*3deb3ec6SMatthias Ringwald 
752*3deb3ec6SMatthias Ringwald void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, uint8_t enable){
753*3deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
754*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
755*3deb3ec6SMatthias Ringwald     if (!connection){
756*3deb3ec6SMatthias Ringwald         log_error("HFP HF: connection doesn't exist.");
757*3deb3ec6SMatthias Ringwald         return;
758*3deb3ec6SMatthias Ringwald     }
759*3deb3ec6SMatthias Ringwald     connection->enable_extended_audio_gateway_error_report = enable;
760*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
761*3deb3ec6SMatthias Ringwald }
762*3deb3ec6SMatthias Ringwald 
763*3deb3ec6SMatthias Ringwald void hfp_hf_negotiate_codecs(bd_addr_t bd_addr){
764*3deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
765*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
766*3deb3ec6SMatthias Ringwald     if (!has_codec_negotiation_feature(connection)) return;
767*3deb3ec6SMatthias Ringwald     if (connection->remote_codecs_nr == 0) return;
768*3deb3ec6SMatthias Ringwald 
769*3deb3ec6SMatthias Ringwald     if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
770*3deb3ec6SMatthias Ringwald 
771*3deb3ec6SMatthias Ringwald     if (connection->state != HFP_SLE_W2_EXCHANGE_COMMON_CODEC &&
772*3deb3ec6SMatthias Ringwald         connection->state != HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
773*3deb3ec6SMatthias Ringwald         connection->hf_trigger_codec_connection_setup = 1;
774*3deb3ec6SMatthias Ringwald     }
775*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
776*3deb3ec6SMatthias Ringwald }
777*3deb3ec6SMatthias Ringwald 
778*3deb3ec6SMatthias Ringwald 
779*3deb3ec6SMatthias Ringwald void hfp_hf_establish_audio_connection(bd_addr_t bd_addr){
780*3deb3ec6SMatthias Ringwald     hfp_hf_establish_service_level_connection(bd_addr);
781*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
782*3deb3ec6SMatthias Ringwald     if (!has_codec_negotiation_feature(connection)) return;
783*3deb3ec6SMatthias Ringwald         connection->establish_audio_connection = 0;
784*3deb3ec6SMatthias Ringwald     if (connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return;
785*3deb3ec6SMatthias Ringwald     if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
786*3deb3ec6SMatthias Ringwald 
787*3deb3ec6SMatthias Ringwald     connection->establish_audio_connection = 1;
788*3deb3ec6SMatthias Ringwald     if (connection->state < HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
789*3deb3ec6SMatthias Ringwald         connection->hf_trigger_codec_connection_setup = 1;
790*3deb3ec6SMatthias Ringwald     }
791*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
792*3deb3ec6SMatthias Ringwald }
793*3deb3ec6SMatthias Ringwald 
794*3deb3ec6SMatthias Ringwald void hfp_hf_release_audio_connection(bd_addr_t bd_addr){
795*3deb3ec6SMatthias Ringwald     hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
796*3deb3ec6SMatthias Ringwald     hfp_release_audio_connection(connection);
797*3deb3ec6SMatthias Ringwald     hfp_run_for_context(connection);
798*3deb3ec6SMatthias Ringwald }
799*3deb3ec6SMatthias Ringwald 
800*3deb3ec6SMatthias Ringwald 
801