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