Merge "[OTP] Fix PTS fail cases" into tizen
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-headset-connection.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <glib.h>
19 #include <string.h>
20 #include <dlog.h>
21 #include <vconf.h>
22 #include <vconf-internal-bt-keys.h>
23
24 #include "bluetooth-api.h"
25 #include "bt-internal-types.h"
26
27 #include "bt-service-common.h"
28 #include "bt-service-event.h"
29 #include "bt-service-main.h"
30 #include "bt-service-adapter.h"
31 #include "bt-service-device.h"
32 #include "bt-service-audio.h"
33 #include "bt-service-headset-connection.h"
34
35 #include "bt-service-opp-client.h"
36 #include "bt-service-map-client.h"
37
38
39
40 static GList *p_connection_list = NULL;
41 typedef enum {
42         BLUETOOTH_NONE_CONNECTED = 0x00,
43         BLUETOOTH_HFP_CONNECTED ,
44         BLUETOOTH_A2DP_CONNECTED,
45         BLUETOOTH_ALL_CONNECTED,
46 } bluetooth_state_type_t;
47
48 typedef struct {
49         bluetooth_state_type_t state;
50         bluetooth_device_info_t dev_info;
51         int connection_type;
52 } bt_connection_node_info_t;
53
54 gboolean connection_local = FALSE;
55
56
57 void _bt_headset_set_local_connection(gboolean value)
58 {
59         BT_INFO("setting connection_local to %d", value);
60         connection_local = value;
61 }
62
63 gboolean _bt_headset_get_local_connection()
64 {
65         return connection_local;
66 }
67
68 //gint compare_state(GList *data, bluetooth_state_type_t state)
69 gint compare_state(gconstpointer list_data, gconstpointer conn_state)
70 {
71         GList *data = (GList *) list_data;
72         bluetooth_state_type_t *state = (bluetooth_state_type_t *)conn_state;
73         bt_connection_node_info_t *p_data = (bt_connection_node_info_t *) data;
74         if (p_data->state == *state) {
75                 BT_INFO("State Already Added");
76                 return 0;
77         }
78         return 1;
79 }
80
81 gboolean connect_remote_media_audio(gpointer user_data)
82 {
83         bt_connection_node_info_t *conn_info =
84                         (bt_connection_node_info_t *) user_data;
85         GList *list = NULL;
86         bluetooth_state_type_t state;
87
88         char remote_address[BT_ADDRESS_STRING_SIZE] = { 0 };
89         _bt_convert_addr_type_to_string(remote_address, conn_info->dev_info.device_address.addr);
90         if (p_connection_list == NULL) {
91                 BT_INFO("None of device connected and this hasbeen triggered");
92                 g_free(conn_info);
93                 return FALSE;
94         }
95         if (conn_info->connection_type == BT_AUDIO_A2DP) {
96                 state = BLUETOOTH_A2DP_CONNECTED;
97                 list = g_list_find_custom(p_connection_list,
98                                 &state, compare_state);
99                 if (list == NULL) {
100                         BT_INFO("Head Set didn't initiated a2dp connection");
101                         BT_INFO("local device initiating A2DP connection");
102
103                         _bt_audio_connect(0, BT_AUDIO_A2DP,
104                                         &conn_info->dev_info.device_address, NULL);
105                 } else {
106                         BT_INFO("A2DP Connection Already exists");
107                 }
108                 g_free(conn_info);
109         } else {
110                 state = BLUETOOTH_HFP_CONNECTED;
111                 list = g_list_find_custom(p_connection_list,
112                                 &state, compare_state);
113                 if (list == NULL) {
114                         BT_INFO("Headset didn't initiated HFP connection");
115                         BT_INFO("local device intiating HFP Connection");
116
117                         _bt_audio_connect(0, BT_AUDIO_HSP,
118                                         &conn_info->dev_info.device_address, NULL);
119                 } else {
120                         BT_INFO("HFP Connection Already exists");
121                 }
122                 g_free(conn_info);
123         }
124         return FALSE;
125 }
126
127 void _bt_get_bluetooth_device_info(char *remote_address, bluetooth_device_info_t *device)
128 {
129         GArray *dev_list = NULL;
130         int size = 0;
131         int i = 0;
132         bluetooth_device_info_t info;
133         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
134
135         if (device == NULL)
136                 return;
137
138         dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
139
140         _bt_get_bonded_devices(&dev_list);
141         size = (dev_list->len) / sizeof(bluetooth_device_info_t);
142         for (i = 0; i < size; i++) {
143                 info = g_array_index(dev_list, bluetooth_device_info_t, i);
144                 _bt_convert_addr_type_to_string(bond_address, info.device_address.addr);
145                 if (strcmp(bond_address, remote_address) == 0) {
146                         BT_INFO("Match found");
147                         memcpy(device, &info, sizeof(bluetooth_device_info_t));
148                         g_array_free(dev_list, TRUE);
149                         return;
150                 }
151         }
152         g_array_free(dev_list, TRUE);
153         return;
154 }
155
156 void _bt_headset_add_timer_function(int connection_type, bluetooth_device_info_t *info)
157 {
158         bt_connection_node_info_t *pass_conn_info = NULL;
159
160         if (info == NULL)
161                 return;
162
163         pass_conn_info = g_new0(bt_connection_node_info_t, 1);
164         pass_conn_info->connection_type = connection_type;
165         memcpy(&pass_conn_info->dev_info, info, sizeof(bluetooth_device_info_t));
166         /* This need to be freed in timer function */
167         g_timeout_add(CONNECT_TIMEOUT, connect_remote_media_audio,
168                 pass_conn_info);
169         return;
170 }
171
172 void _bt_start_timer_for_connection(char *remote_address, int connection_type)
173 {
174         GArray *dev_list = NULL;
175         int size;
176         int i;
177         int j;
178         bluetooth_device_info_t info;
179         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
180         dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
181         _bt_get_bonded_devices(&dev_list);
182         size = (dev_list->len) / sizeof(bluetooth_device_info_t);
183
184         for (i = 0; i < size; i++) {
185                 info = g_array_index(dev_list, bluetooth_device_info_t, i);
186                 j = 0;
187                 _bt_convert_addr_type_to_string(bond_address,
188                                 info.device_address.addr);
189                 if (strcmp(bond_address, remote_address) != 0)
190                         continue;
191                 BT_INFO("Device address Matched");
192
193                 while (j != info.service_index) {
194                         BT_INFO("UUID %s", info.uuids[j]);
195                         if (connection_type == BT_AUDIO_A2DP) {
196                                 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
197                                         BT_INFO("Remote Device has A2DP Sink Support start timer");
198                                         _bt_headset_add_timer_function(BT_AUDIO_A2DP, &info);
199                                         goto end;
200                                 }
201                         } else {
202                                 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
203                                         BT_INFO("Remote Device has HFP Sink Support start timer");
204                                         _bt_headset_add_timer_function(BT_AUDIO_HSP, &info);
205                                         goto end;
206                                 }
207                         }
208                         j++;
209                 }
210         }
211 end:
212         g_array_free(dev_list, TRUE);
213 }
214
215 void __bt_connection_manager_set_state(char *remote_address, int event)
216 {
217         bt_connection_node_info_t *info;
218
219         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
220         if (event == BLUETOOTH_EVENT_AG_CONNECTED) {
221                 info = g_new0(bt_connection_node_info_t, 1);
222                 info->state = BLUETOOTH_HFP_CONNECTED;
223                 _bt_get_bluetooth_device_info(remote_address, &info->dev_info);
224                 _bt_convert_addr_type_to_string(bond_address,
225                                 info->dev_info.device_address.addr);
226                 BT_INFO("Adding HFP Connected device to list");
227                 p_connection_list = g_list_append(p_connection_list, info);
228         } else if (event == BLUETOOTH_EVENT_AG_DISCONNECTED) {
229                 /* Delete coresponding node */
230                 BT_INFO("Deleting HFP Connected device from list");
231                 GList *list = NULL;
232                 bluetooth_state_type_t state;
233                 bt_connection_node_info_t *h_conn;
234                 state = BLUETOOTH_HFP_CONNECTED;
235                 list = g_list_find_custom(p_connection_list,
236                                 &state, compare_state);
237                 if (list == NULL) {
238                         BT_INFO("Didn't found any device with HFP State");
239                         return;
240                 }
241                 h_conn = list->data;
242                 p_connection_list = g_list_remove(p_connection_list, h_conn);
243                 g_free(h_conn);
244         } else if (event == BLUETOOTH_EVENT_AV_CONNECTED) {
245                 info = g_new0(bt_connection_node_info_t, 1);
246                 info->state = BLUETOOTH_A2DP_CONNECTED;
247                 _bt_get_bluetooth_device_info(remote_address, &info->dev_info);
248                 _bt_convert_addr_type_to_string(bond_address,
249                                 info->dev_info.device_address.addr);
250                 BT_INFO("Adding A2DP Connected device to list");
251                 p_connection_list = g_list_append(p_connection_list, info);
252         } else if (event == BLUETOOTH_EVENT_AV_DISCONNECTED) {
253                 BT_INFO("Deleting A2DP Connected device from list");
254                 bt_connection_node_info_t *a_conn;
255                 GList *list = NULL;
256                 bluetooth_state_type_t state;
257                 state = BLUETOOTH_A2DP_CONNECTED;
258                 list = g_list_find_custom(p_connection_list,
259                                 &state, compare_state);
260                 if (list == NULL) {
261                         BT_INFO("Didn't found any device with A2DP State");
262                         return;
263                 }
264                 a_conn = list->data;
265                 p_connection_list = g_list_remove(p_connection_list, a_conn);
266                 g_free(a_conn);
267         }
268 }
269