Apply tizen 3.0 based product patchsets
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-network.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 <gio/gio.h>
20 #include <dlog.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <syspopup_caller.h>
24 #include <net_connection.h>
25
26 #include "bluetooth-api.h"
27 #include "bt-service-network.h"
28 #include "bt-service-common.h"
29 #include "bt-service-event.h"
30 #include "bt-service-util.h"
31 #include "bt-internal-types.h"
32
33 void _bt_util_addr_type_to_addr_net_string(char *address,
34                                         unsigned char *addr)
35 {
36         ret_if(address == NULL);
37         ret_if(addr == NULL);
38
39         snprintf(address, BT_ADDRESS_STR_LEN, "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", addr[0],
40                         addr[1], addr[2], addr[3], addr[4], addr[5]);
41 }
42
43 static connection_profile_h __bt_get_net_profile(void *connection,
44                                                 connection_iterator_type_e type,
45                                                 unsigned char *address)
46 {
47         int result;
48         gchar **split_string;
49         char net_address[BT_ADDRESS_STR_LEN + 1] = { 0 };
50         char *profile_name = NULL;
51         connection_profile_iterator_h profile_iter;
52         connection_profile_h profile_h;
53         connection_profile_type_e profile_type;
54
55         retv_if(connection == NULL, NULL);
56         retv_if(address == NULL, NULL);
57
58         BT_DBG("net_conn: %x", connection);
59
60         _bt_util_addr_type_to_addr_net_string(net_address, address);
61
62         result = connection_get_profile_iterator(connection,
63                                                         type,
64                                                         &profile_iter);
65         if (result != CONNECTION_ERROR_NONE) {
66                 BT_ERR("Fail to get profile iterator [%d]", result);
67                 return NULL;
68         }
69
70         while (connection_profile_iterator_has_next(profile_iter)) {
71                         profile_name = NULL;
72                         profile_h = NULL;
73                         split_string = NULL;
74
75                         if (connection_profile_iterator_next(profile_iter,
76                                                 &profile_h) != CONNECTION_ERROR_NONE) {
77                                 BT_ERR("Fail to get profile handle");
78                                 return NULL;
79                         }
80
81                         if (connection_profile_get_type(profile_h,
82                                                 &profile_type) != CONNECTION_ERROR_NONE) {
83                                 BT_ERR("Fail to get profile type");
84                                 continue;
85                         }
86
87                         if (profile_type != CONNECTION_PROFILE_TYPE_BT)
88                                 continue;
89
90                         if (connection_profile_get_name(profile_h,
91                                                 &profile_name) != CONNECTION_ERROR_NONE) {
92                                 BT_ERR("Fail to get profile name");
93                                 return NULL;
94                         }
95
96                         split_string = g_strsplit(profile_name, "_", 3);
97
98                         g_free(profile_name);
99
100                         if (g_strv_length(split_string) < 3)
101                                 continue;
102
103                         if (g_ascii_strcasecmp(split_string[2], net_address) == 0) {
104                                 BT_DBG("matched profile");
105                                 g_strfreev(split_string);
106                                 return profile_h;
107                         }
108
109                         g_strfreev(split_string);
110         }
111
112         return NULL;
113 }
114
115 int _bt_is_network_connected(void *connection, unsigned char *address,
116                                         gboolean *is_connected)
117 {
118         void *handle = NULL;
119         handle = __bt_get_net_profile(connection,
120                                 CONNECTION_ITERATOR_TYPE_CONNECTED,
121                                 address);
122         if (handle)
123                 *is_connected = TRUE;
124         else
125                 *is_connected = FALSE;
126
127         return BLUETOOTH_ERROR_NONE;
128 }
129
130 static void __bt_network_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
131                                         gpointer user_data)
132 {
133         GError *g_error = NULL;
134         GVariant *out_param1 = NULL;
135         GVariant *reply = NULL;
136         bluetooth_device_address_t device_addr = { {0} };
137         int result = BLUETOOTH_ERROR_NONE;
138         bt_function_data_t *func_data;
139         request_info_t *req_info;
140
141         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
142         g_object_unref(proxy);
143
144         if (reply == NULL) {
145                 BT_ERR("Network Connect Dbus Call Error");
146                 if (g_error) {
147                         BT_ERR("Error: %s\n", g_error->message);
148                         g_clear_error(&g_error);
149                 }
150                 result = BLUETOOTH_ERROR_INTERNAL;
151         } else {
152                 g_variant_unref(reply);
153         }
154
155         func_data = user_data;
156         if (func_data == NULL) {
157                 /* Send reply */
158                 BT_ERR("func_data == NULL");
159                 goto done;
160         }
161
162         BT_ERR("func_data->req_id: %d", func_data->req_id);
163         req_info = _bt_get_request_info(func_data->req_id);
164         if (req_info == NULL) {
165                 BT_ERR("req_info == NULL");
166                 goto done;
167         }
168
169         if (req_info->context == NULL)
170                 goto done;
171
172         _bt_convert_addr_string_to_type(device_addr.addr,
173                                         func_data->address);
174
175         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
176                                                         &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
177
178         g_dbus_method_invocation_return_value(req_info->context,
179                         g_variant_new("iv", result, out_param1));
180
181         _bt_delete_request_list(req_info->req_id);
182
183 done:
184         if (func_data) {
185                 g_free(func_data->address);
186                 g_free(func_data);
187         }
188 }
189
190 static void __bt_network_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
191                                         gpointer user_data)
192 {
193         GError *g_error = NULL;
194         GVariant *out_param1 = NULL;
195         GVariant *reply = NULL;
196         bluetooth_device_address_t device_addr = { {0} };
197         int result = BLUETOOTH_ERROR_NONE;
198         bt_function_data_t *func_data;
199         request_info_t *req_info;
200
201         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
202         g_object_unref(proxy);
203
204         if (reply == NULL) {
205                 BT_ERR("Network Disconnect Dbus Call Error");
206                 if (g_error) {
207                         BT_ERR("Error: %s\n", g_error->message);
208                         g_clear_error(&g_error);
209                 }
210                 result = BLUETOOTH_ERROR_INTERNAL;
211         } else {
212                 g_variant_unref(reply);
213         }
214
215         func_data = user_data;
216         if (func_data == NULL) {
217                 /* Send reply */
218                 BT_ERR("func_data == NULL");
219                 goto done;
220         }
221         BT_ERR("func_data->req_id: %d", func_data->req_id);
222         req_info = _bt_get_request_info(func_data->req_id);
223         if (req_info == NULL) {
224                 BT_ERR("req_info == NULL");
225                 goto done;
226         }
227
228         if (g_error != NULL) {
229                 BT_ERR("Network Connect Dbus Call Error: %s\n", g_error->message);
230                 result = BLUETOOTH_ERROR_INTERNAL;
231         }
232
233         if (req_info->context == NULL)
234                 goto done;
235
236         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
237                                                         &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
238
239         g_dbus_method_invocation_return_value(req_info->context,
240                         g_variant_new("iv", result, out_param1));
241
242         _bt_delete_request_list(req_info->req_id);
243
244 done:
245         if (func_data) {
246                 g_free(func_data->address);
247                 g_free(func_data);
248         }
249 }
250
251 int _bt_network_activate(void)
252 {
253         int ret = BLUETOOTH_ERROR_NONE;
254         char *adapter_path;
255         GVariant *result = NULL;
256         GError *err = NULL;
257         GDBusConnection *conn;
258         GDBusProxy *server_proxy;
259
260         conn = _bt_gdbus_get_system_gconn();
261         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
262
263         adapter_path = _bt_get_adapter_path();
264         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
265
266         server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
267                         NULL, BT_BLUEZ_NAME,
268                         adapter_path, BT_NETWORK_SERVER_INTERFACE,  NULL, NULL);
269         g_free(adapter_path);
270
271         if (server_proxy == NULL) {
272                 BT_ERR("Failed to get the network server proxy\n");
273                 return BLUETOOTH_ERROR_INTERNAL;
274         }
275
276         result = g_dbus_proxy_call_sync(server_proxy, "Register",
277                                  g_variant_new("(ss)", NAP_UUID_NAME, NET_BRIDGE_INTERFACE),
278                                  G_DBUS_CALL_FLAGS_NONE,
279                                  -1,
280                                  NULL,
281                                  &err);
282         if (result == NULL) {
283                 if (err != NULL) {
284                         g_dbus_error_strip_remote_error(err);
285                         BT_ERR("Network server register Error: %s\n", err->message);
286                         if (g_strcmp0(err->message, "Already Exists") == 0)
287                                 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
288                         else
289                                 ret = BLUETOOTH_ERROR_INTERNAL;
290
291                         g_error_free(err);
292                 }
293         } else {
294                 g_variant_unref(result);
295         }
296
297         g_object_unref(server_proxy);
298
299         return ret;
300 }
301
302 int _bt_network_deactivate(void)
303 {
304         char *adapter_path;
305         GVariant *result = NULL;
306         GError *err = NULL;
307         GDBusConnection *conn;
308         GDBusProxy *server_proxy;
309         int ret = BLUETOOTH_ERROR_NONE;
310
311         conn = _bt_gdbus_get_system_gconn();
312         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
313
314         adapter_path = _bt_get_adapter_path();
315         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
316
317         server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
318                                                                 NULL, BT_BLUEZ_NAME,
319                                                                 adapter_path, BT_NETWORK_SERVER_INTERFACE,  NULL, NULL);
320         g_free(adapter_path);
321
322         if (server_proxy == NULL) {
323                 BT_ERR("Failed to get the network server proxy\n");
324                 return BLUETOOTH_ERROR_INTERNAL;
325         }
326
327         result = g_dbus_proxy_call_sync(server_proxy, "Unregister",
328                                  g_variant_new("(s)", NAP_UUID_NAME),
329                                  G_DBUS_CALL_FLAGS_NONE,
330                                  -1,
331                                  NULL,
332                                  &err);
333         if (result == NULL) {
334                 if (err != NULL) {
335                         g_dbus_error_strip_remote_error(err);
336                         BT_ERR("Network server unregister Error: %s\n", err->message);
337                         if (g_strcmp0(err->message,
338                                         "Operation currently not available") == 0) {
339                                 ret = BLUETOOTH_ERROR_ALREADY_DEACTIVATED;
340                         } else {
341                                 ret = BLUETOOTH_ERROR_INTERNAL;
342                         }
343                         g_error_free(err);
344                 }
345         } else {
346                 g_variant_unref(result);
347         }
348
349         g_object_unref(server_proxy);
350
351         return ret;
352 }
353
354 int _bt_network_connect(int request_id, int role,
355                 bluetooth_device_address_t *device_address)
356 {
357         const gchar *device_path = NULL;
358         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
359         char remote_role[BLUETOOTH_UUID_STRING_MAX] = { 0 };
360         bt_function_data_t *func_data;
361         GDBusProxy *adapter_proxy;
362         GDBusProxy *profile_proxy;
363         GDBusConnection *conn;
364         GVariant *result = NULL;
365         GError*err = NULL;
366
367         BT_CHECK_PARAMETER(device_address, return);
368
369         switch (role) {
370         case BLUETOOTH_NETWORK_PANU_ROLE:
371                 g_strlcpy(remote_role, PANU_UUID_NAME, BLUETOOTH_UUID_STRING_MAX);
372                 break;
373
374         case BLUETOOTH_NETWORK_NAP_ROLE:
375                 g_strlcpy(remote_role, NAP_UUID_NAME, BLUETOOTH_UUID_STRING_MAX);
376                 break;
377
378         case BLUETOOTH_NETWORK_GN_ROLE:
379                 g_strlcpy(remote_role, GN_UUID_NAME, BLUETOOTH_UUID_STRING_MAX);
380                 break;
381         default:
382                 BT_ERR("Unknown role");
383                 return BLUETOOTH_ERROR_INTERNAL;
384         }
385
386         adapter_proxy = _bt_get_adapter_proxy();
387         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
388
389         conn = _bt_gdbus_get_system_gconn();
390         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
391
392         _bt_convert_addr_type_to_string(address, device_address->addr);
393
394         result = g_dbus_proxy_call_sync(adapter_proxy, "FindDevice",
395                         g_variant_new("(s)", address),
396                         G_DBUS_CALL_FLAGS_NONE,
397                         -1, NULL, &err);
398         if (result == NULL) {
399                 BT_ERR("Error occurred in call to FindDevice");
400                 if (err) {
401                         BT_ERR("Error: %s", err->message);
402                         g_clear_error(&err);
403                 }
404                 return BLUETOOTH_ERROR_INTERNAL;
405         }
406
407         device_path =  g_variant_get_string(result, NULL);
408         if (device_path == NULL) {
409                 BT_ERR("No paired device");
410                 g_variant_unref(result);
411                 return BLUETOOTH_ERROR_NOT_PAIRED;
412         }
413
414         profile_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
415                         NULL, BT_BLUEZ_NAME,
416                         device_path, BT_NETWORK_CLIENT_INTERFACE,  NULL, NULL);
417
418         g_variant_unref(result);
419         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
420         func_data = g_malloc0(sizeof(bt_function_data_t));
421         func_data->address = g_strdup(address);
422         func_data->req_id = request_id;
423
424         g_dbus_proxy_call(profile_proxy, "Connect",
425                                 g_variant_new("(s)", remote_role),
426                                 G_DBUS_CALL_FLAGS_NONE,
427                                 BT_MAX_DBUS_TIMEOUT,
428                                 NULL,
429                                 (GAsyncReadyCallback)__bt_network_connect_cb,
430                                 func_data);
431
432         return BLUETOOTH_ERROR_NONE;
433 }
434
435 int _bt_network_disconnect(int request_id,
436                 bluetooth_device_address_t *device_address)
437 {
438         const gchar *device_path = NULL;
439         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
440         bt_function_data_t *func_data;
441         GDBusProxy *adapter_proxy;
442         GDBusProxy *profile_proxy;
443         GDBusConnection *conn;
444         GVariant *result = NULL;
445         GError*err = NULL;
446
447         BT_CHECK_PARAMETER(device_address, return);
448
449         adapter_proxy = _bt_get_adapter_proxy();
450         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
451
452         conn = _bt_gdbus_get_system_gconn();
453         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
454
455         _bt_convert_addr_type_to_string(address, device_address->addr);
456
457         result = g_dbus_proxy_call_sync(adapter_proxy, "FindDevice",
458                                  g_variant_new("(s)", address),
459                                  G_DBUS_CALL_FLAGS_NONE,
460                                  -1, NULL, &err);
461         if (result == NULL) {
462                 BT_ERR("Error occurred in call to FindDevice");
463                 if (err) {
464                         BT_ERR("Error: %s", err->message);
465                         g_clear_error(&err);
466                 }
467                 return BLUETOOTH_ERROR_INTERNAL;
468         }
469
470         device_path =  g_variant_get_string(result, NULL);
471         if (device_path == NULL) {
472                 BT_ERR("No paired device");
473                 g_variant_unref(result);
474                 return BLUETOOTH_ERROR_NOT_PAIRED;
475         }
476
477         profile_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
478                         NULL, BT_BLUEZ_NAME,
479                         device_path, BT_NETWORK_CLIENT_INTERFACE,  NULL, NULL);
480
481         g_variant_unref(result);
482         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
483         func_data = g_malloc0(sizeof(bt_function_data_t));
484         func_data->address = g_strdup(address);
485         func_data->req_id = request_id;
486
487         g_dbus_proxy_call(profile_proxy, "Disconnect",
488                         NULL,
489                         G_DBUS_CALL_FLAGS_NONE,
490                         BT_MAX_DBUS_TIMEOUT,
491                         NULL,
492                         (GAsyncReadyCallback)__bt_network_disconnect_cb,
493                         func_data);
494
495         return BLUETOOTH_ERROR_NONE;
496 }
497
498 int _bt_network_server_disconnect(int request_id,
499                 bluetooth_device_address_t *device_address)
500 {
501         gchar *adapter_path = NULL;
502         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
503         bt_function_data_t *func_data;
504         GDBusProxy *profile_proxy;
505         GDBusConnection *conn;
506
507         BT_CHECK_PARAMETER(device_address, return);
508
509         conn = _bt_gdbus_get_system_gconn();
510         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
511
512         adapter_path = _bt_get_adapter_path();
513         if (adapter_path == NULL) {
514                 BT_ERR("No adapter found");
515                 return BLUETOOTH_ERROR_INTERNAL;
516         }
517
518         _bt_convert_addr_type_to_string(address, device_address->addr);
519
520         profile_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
521                         NULL, BT_BLUEZ_NAME,
522                         adapter_path, BT_NETWORK_SERVER_INTERFACE, NULL, NULL);
523         g_free(adapter_path);
524         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
525         func_data = g_malloc0(sizeof(bt_function_data_t));
526
527         func_data->address = g_strdup(address);
528         func_data->req_id = request_id;
529
530         g_dbus_proxy_call(profile_proxy, "Disconnect",
531                                  g_variant_new("(s)", address),
532                                 G_DBUS_CALL_FLAGS_NONE,
533                                 BT_MAX_DBUS_TIMEOUT,
534                                 NULL,
535                                 (GAsyncReadyCallback)__bt_network_disconnect_cb,
536                                 func_data);
537
538         return BLUETOOTH_ERROR_NONE;
539 }