Remove unnecessary log
[platform/core/connectivity/bluetooth-frwk.git] / bt-core / bt-core-dbus-handler.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 <gio/gio.h>
19 #include <vconf.h>
20 #include <vconf-keys.h>
21
22 #include "bt-core-adapter.h"
23 #include "bt-core-common.h"
24 #include "bt-core-dbus-handler.h"
25 #include "bt-internal-types.h"
26 #include "bt-core-noti-handler.h"
27 #include "bt-core-main.h"
28
29 #define BT_SERVICE_NAME         "org.projectx.bt"
30 #define BT_SERVICE_PATH         "/org/projectx/bt_service"
31
32 #ifdef TIZEN_FEATURE_BT_HPS
33 #define BT_HPS_SERVICE_NAME "org.projectx.httpproxy"
34 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
35 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
36 #endif
37
38 static GDBusConnection *service_gconn;
39 static GDBusProxy *service_gproxy;
40 #ifdef TIZEN_FEATURE_BT_HPS
41 static GDBusProxy *hps_gproxy;
42 #endif
43 static gboolean factory_test_mode;
44
45 void _bt_core_fill_garray_from_variant(GVariant *var, GArray *param)
46 {
47         char *data;
48         int size;
49
50         size = g_variant_get_size(var);
51         if (size > 0) {
52                 data = (char *)g_variant_get_data(var);
53                 if (data)
54                         param = g_array_append_vals(param, data, size);
55
56         }
57 }
58
59 GDBusConnection * _bt_core_get_gdbus_connection(void)
60 {
61         GError *err = NULL;
62
63         if (service_gconn == NULL)
64                 service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
65
66         if (!service_gconn) {
67                 if (err) {
68                         BT_ERR("Unable to connect to dbus: %s", err->message);
69                         g_clear_error(&err);
70                 }
71                 return NULL;
72         }
73
74         return service_gconn;
75 }
76
77 static GDBusProxy *__bt_core_gdbus_init_service_proxy(void)
78 {
79         GDBusProxy *proxy;
80         GError *err = NULL;
81         GDBusConnection *conn;
82
83         conn = _bt_core_get_gdbus_connection();
84         if (!conn)
85                 return NULL;
86
87         proxy =  g_dbus_proxy_new_sync(conn,
88                         G_DBUS_PROXY_FLAGS_NONE, NULL,
89                         BT_SERVICE_NAME,
90                         BT_SERVICE_PATH,
91                         BT_SERVICE_NAME,
92                         NULL, &err);
93         if (!proxy) {
94                 if (err) {
95                          BT_ERR("Unable to create proxy: %s", err->message);
96                          g_clear_error(&err);
97                 }
98
99                 return NULL;
100         }
101
102         service_gproxy = proxy;
103
104         return proxy;
105 }
106
107 GDBusProxy *_bt_core_gdbus_get_service_proxy(void)
108 {
109         return (service_gproxy) ? service_gproxy : __bt_core_gdbus_init_service_proxy();
110 }
111
112 #ifdef TIZEN_FEATURE_BT_HPS
113 int _bt_core_start_httpproxy(void)
114 {
115         GVariant *variant = NULL;
116         unsigned char enabled;
117         GError *err = NULL;
118         BT_DBG(" ");
119
120         hps_gproxy = _bt_core_gdbus_get_hps_proxy();
121         if (!hps_gproxy) {
122                 BT_DBG("Couldn't get service proxy");
123                 return -1;
124         }
125
126         variant = g_dbus_proxy_call_sync(hps_gproxy, "enable",
127                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
128         if (err) {
129                 BT_ERR("Error : %s" , err->message);
130                 g_clear_error(&err);
131         }
132         if (variant) {
133                 g_variant_get(variant, "(y)", &enabled);
134                 BT_ERR("HPS enabled status 0x%x", enabled);
135         }
136         return 0;
137 }
138
139 int _bt_core_stop_httpproxy(void)
140 {
141         GVariant *variant = NULL;
142         unsigned char enabled;
143         GError *err = NULL;
144         BT_DBG(" ");
145
146         hps_gproxy = _bt_core_gdbus_get_hps_proxy();
147         if (!hps_gproxy) {
148                 BT_DBG("Couldn't get service proxy");
149                 return -1;
150         }
151
152         variant = g_dbus_proxy_call_sync(hps_gproxy, "disable",
153                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
154         if (err) {
155                 BT_ERR("Error : %s" , err->message);
156                 g_clear_error(&err);
157         }
158         if (variant) {
159                 g_variant_get(variant, "(y)", &enabled);
160                 BT_ERR("HPS disabled status 0x%x", enabled);
161         }
162         return 0;
163 }
164
165 static GDBusProxy *_bt_core_gdbus_init_hps_proxy(void)
166 {
167         GDBusProxy *proxy;
168         GError *err = NULL;
169         GDBusConnection *conn;
170
171         BT_DBG(" ");
172
173         conn = _bt_core_get_gdbus_connection();
174         if (!conn)
175                 return NULL;
176
177         proxy =  g_dbus_proxy_new_sync(conn,
178                         G_DBUS_PROXY_FLAGS_NONE, NULL,
179                         BT_HPS_SERVICE_NAME,
180                         BT_HPS_OBJECT_PATH,
181                         BT_HPS_INTERFACE_NAME,
182                         NULL, &err);
183         if (proxy == NULL) {
184                 if (err) {
185                          BT_ERR("Unable to create proxy: %s", err->message);
186                          g_clear_error(&err);
187                 }
188                 return NULL;
189         }
190
191         hps_gproxy = proxy;
192
193         return proxy;
194 }
195
196 GDBusProxy *_bt_core_gdbus_get_hps_proxy(void)
197 {
198         return (hps_gproxy) ? hps_gproxy : _bt_core_gdbus_init_hps_proxy();
199 }
200 #endif
201
202 void _bt_core_gdbus_deinit_proxys(void)
203 {
204         BT_DBG("");
205
206         if (service_gproxy) {
207                 g_object_unref(service_gproxy);
208                 service_gproxy = NULL;
209         }
210
211 #ifdef TIZEN_FEATURE_BT_HPS
212         if (hps_gproxy) {
213                 g_object_unref(hps_gproxy);
214                 hps_gproxy = NULL;
215         }
216 #endif
217
218         if (service_gconn) {
219                 g_object_unref(service_gconn);
220                 service_gconn = NULL;
221         }
222 }
223
224 int _bt_core_service_request(int service_type, int service_function,
225                         GArray *in_param1, GArray *in_param2,
226                         GArray *in_param3, GArray *in_param4,
227                         GArray **out_param1)
228 {
229         GDBusProxy  *proxy;
230         GVariant *ret = NULL;
231         GVariant *param1;
232         GVariant *param2;
233         GVariant *param3;
234         GVariant *param4;
235         GVariant *param5;
236
237         int result = BLUETOOTH_ERROR_NONE;
238         GError *error = NULL;
239         GArray *in_param5 = NULL;
240
241         int retry = 5;
242
243         proxy = _bt_core_gdbus_get_service_proxy();
244         if (!proxy)
245                 return BLUETOOTH_ERROR_INTERNAL;
246         in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
247
248         while (--retry >= 0) {
249                 param1 = g_variant_new_from_data((const GVariantType *)"ay",
250                                         in_param1->data, in_param1->len,
251                                         TRUE, NULL, NULL);
252                 param2 = g_variant_new_from_data((const GVariantType *)"ay",
253                                         in_param2->data, in_param2->len,
254                                         TRUE, NULL, NULL);
255                 param3 = g_variant_new_from_data((const GVariantType *)"ay",
256                                         in_param3->data, in_param3->len,
257                                         TRUE, NULL, NULL);
258                 param4 = g_variant_new_from_data((const GVariantType *)"ay",
259                                         in_param4->data, in_param4->len,
260                                         TRUE, NULL, NULL);
261                 param5 = g_variant_new_from_data((const GVariantType *)"ay",
262                                         in_param5->data, in_param5->len,
263                                         TRUE, NULL, NULL);
264
265                 ret = g_dbus_proxy_call_sync(proxy, "service_request",
266                                         g_variant_new("(iii@ay@ay@ay@ay@ay)",
267                                                 service_type, service_function,
268                                                 BT_SYNC_REQ, param1,
269                                                 param2, param3,
270                                                 param4, param5),
271                                         G_DBUS_CALL_FLAGS_NONE, 2000,
272                                         NULL, &error);
273                 if (ret == NULL && error != NULL) {
274                         if (error->code == G_IO_ERROR_TIMED_OUT) {
275                                 BT_ERR("D-Bus Timed out.");
276                                 g_clear_error(&error);
277                                 continue;
278                         }
279                 }
280
281                 break;
282         }
283
284         g_array_free(in_param5, TRUE);
285
286         if (ret == NULL) {
287                 /* dBUS-RPC is failed */
288                 BT_ERR("dBUS-RPC is failed");
289
290                 if (error != NULL) {
291                         /* dBUS gives error cause */
292                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
293                                error->code, error->message);
294
295                         g_clear_error(&error);
296                 } else {
297                         /* dBUS does not give error cause dBUS-RPC is failed */
298                         BT_ERR("error returned was NULL");
299                 }
300
301                 return BLUETOOTH_ERROR_INTERNAL;
302         }
303
304         param1 = NULL;
305
306         g_variant_get(ret, "(iv)", &result, &param1);
307
308         if (param1) {
309                 *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
310                 _bt_core_fill_garray_from_variant(param1, *out_param1);
311                 g_variant_unref(param1);
312         }
313
314         g_variant_unref(ret);
315
316         return result;
317 }
318
319 static const gchar bt_core_introspection_xml[] =
320 "<node name='/'>"
321 "  <interface name='org.projectx.btcore'>"
322 "     <method name='EnableAdapter'>"
323 "     </method>"
324 "     <method name='DisableAdapter'>"
325 "     </method>"
326 "     <method name='RecoverAdapter'>"
327 "     </method>"
328 "     <method name='ResetAdapter'>"
329 "     </method>"
330 "     <method name='EnableAdapterLe'>"
331 "     </method>"
332 "     <method name='DisableAdapterLe'>"
333 "     </method>"
334 "     <method name='EnableCore'>"
335 "     </method>"
336 "         <method name='SetTransferValue'>"
337 "          <arg type='b' name='value' direction='in'/>"
338 "         </method>"
339 "     <method name='FactoryTestMode'>"
340 "          <arg type='s' name='type' direction='in'/>"
341 "          <arg type='s' name='arg' direction='in'/>"
342 "          <arg type='i' name='ret' direction='out'/>"
343 "     </method>"
344 " </interface>"
345 "</node>";
346
347 static guint obj_id, sig_id1, sig_id2, sig_id3;
348
349 static void __bt_core_dbus_method(GDBusConnection *connection,
350                         const gchar *sender,
351                         const gchar *object_path,
352                         const gchar *interface_name,
353                         const gchar *method_name,
354                         GVariant *parameters,
355                         GDBusMethodInvocation *invocation,
356                         gpointer user_data)
357 {
358         gboolean ret;
359
360         BT_DBG("method %s", method_name);
361
362         if (g_strcmp0(method_name, "EnableAdapter") == 0) {
363                 ret = _bt_core_enable_adapter();
364         } else if (g_strcmp0(method_name, "DisableAdapter") == 0) {
365                 ret = _bt_core_disable_adapter();
366         } else if (g_strcmp0(method_name, "RecoverAdapter") == 0) {
367                 ret = _bt_core_recover_adapter();
368         } else if (g_strcmp0(method_name, "ResetAdapter") == 0) {
369                 ret = __bt_core_reset_adapter();
370         } else if (g_strcmp0(method_name, "EnableAdapterLe") == 0) {
371                 ret = _bt_core_enable_adapter_le();
372         } else if (g_strcmp0(method_name, "DisableAdapterLe") == 0) {
373                 ret = _bt_core_disable_adapter_le();
374         } else if (g_strcmp0(method_name, "EnableCore") == 0) {
375                 ret = _bt_core_enable_core();
376         } else if (g_strcmp0(method_name, "SetTransferValue") == 0) {
377                 gboolean value = FALSE;
378
379                 g_variant_get(parameters, "(b)", &value);
380                 BT_DBG("Transfer value: %d", value);
381
382                 ret = _bt_core_set_transfer_value(value);
383         } else if (g_strcmp0(method_name, "FactoryTestMode") == 0) {
384                 const char *type = NULL;
385                 const char *arg = NULL;
386
387                 g_variant_get(parameters, "(&s&s)", &type, &arg);
388                 ret = _bt_core_factory_test_mode(type, arg);
389                 factory_test_mode = TRUE;
390
391                 if (ret == TRUE)
392                         g_dbus_method_invocation_return_value(invocation,
393                                 g_variant_new("(i)", ret));
394                 else
395                         _bt_core_terminate();
396
397                  return;
398         } else {
399                 ret = FALSE;
400         }
401
402         if (!ret) {
403                 GQuark quark = g_quark_from_string("bt-core");
404                 GError *err = g_error_new(quark, 0, "Failed");
405                 g_dbus_method_invocation_return_gerror(invocation, err);
406                 g_error_free(err);
407         } else {
408                 g_dbus_method_invocation_return_value(invocation, NULL);
409         }
410
411         BT_DBG("-");
412 }
413
414 static const GDBusInterfaceVTable method_table = {
415         __bt_core_dbus_method,
416         NULL,
417         NULL,
418 };
419
420 static GDBusNodeInfo *__bt_core_create_node_info(
421                                         const gchar *introspection_data)
422 {
423         GError *err = NULL;
424         GDBusNodeInfo *node_info = NULL;
425
426         if (introspection_data == NULL)
427                 return NULL;
428
429         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
430
431         if (err) {
432                 BT_ERR("Unable to create node: %s", err->message);
433                 g_clear_error(&err);
434         }
435         return node_info;
436 }
437
438 gboolean __is_interface_and_signal_valid(const gchar *interface_name,
439                                                 const gchar *signal_name)
440 {
441         if (g_strcmp0(interface_name, "org.freedesktop.DBus") &&
442                 g_strcmp0(interface_name, "org.freedesktop.DBus.ObjectManager"))
443                 return FALSE;
444
445         if (g_strcmp0(signal_name, "NameOwnerChanged") &&
446                 g_strcmp0(signal_name, "InterfacesAdded") &&
447                 g_strcmp0(signal_name, "InterfacesRemoved"))
448                 return FALSE;
449
450         return TRUE;
451 }
452
453 static void __handle_name_owner_changed(const char *name)
454 {
455         gboolean flight_mode_status;
456
457         flight_mode_status = _bt_core_is_flight_mode_enabled();
458
459         if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
460                 BT_DBG("flightmode requested");
461                 return;
462         }
463
464         if ((g_strcmp0(name, "org.bluez") == 0) ||
465                 (g_strcmp0(name, "org.projectx.bt") == 0)) {
466                 BT_DBG("%s is terminated", name);
467                 if (_bt_check_terminating_condition() == TRUE && factory_test_mode == FALSE) {
468                         _bt_disable_adapter();
469                         _bt_disable_adapter_le();
470                         _bt_core_terminate();
471                 }
472         }
473 }
474
475 static void __bt_core_event_filter(GDBusConnection *connection,
476                                                  const gchar *sender_name,
477                                                  const gchar *object_path,
478                                                  const gchar *interface_name,
479                                                  const gchar *signal_name,
480                                                  GVariant *parameters,
481                                                  gpointer user_data)
482 {
483         if (!__is_interface_and_signal_valid(interface_name, signal_name))
484                 return;
485
486         if (!g_strcmp0(signal_name, "InterfacesAdded")) {
487                 char *obj_path = NULL;
488                 GVariant *optional_param;
489
490                 g_variant_get(parameters, "(&o@a{sa{sv}})",
491                                                 &obj_path, &optional_param);
492
493                 if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
494                         _bt_core_adapter_added_cb();
495
496         } else if (!g_strcmp0(signal_name, "InterfacesRemoved")) {
497                 char *obj_path = NULL;
498                 GVariant *optional_param;
499
500                 g_variant_get(parameters, "(&o@as)", &obj_path,
501                                                         &optional_param);
502
503                 if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
504                         _bt_core_adapter_removed_cb();
505
506         } else { /* NameOwnerChanged */
507                 const char *name = NULL;
508                 const char *old_owner = NULL;
509                 const char *new_owner = NULL;
510
511                 g_variant_get(parameters, "(&s&s&s)", &name, &old_owner,
512                                                                 &new_owner);
513
514                 if (new_owner != NULL && *new_owner == '\0')
515                         __handle_name_owner_changed(name);
516         }
517 }
518
519 gboolean _bt_core_register_dbus(void)
520 {
521         GError *error = NULL;
522         guint owner_id;
523         GDBusNodeInfo *node_info;
524         gchar *path;
525         GDBusConnection *conn;
526
527         conn = _bt_core_get_gdbus_connection();
528         if (!conn)
529                 return FALSE;
530
531         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
532                                 BT_CORE_NAME,
533                                 G_BUS_NAME_OWNER_FLAGS_NONE,
534                                 NULL, NULL, NULL,
535                                 NULL, NULL);
536
537         BT_DBG("owner_id is [%d]", owner_id);
538
539         node_info = __bt_core_create_node_info(bt_core_introspection_xml);
540         if (node_info == NULL)
541                 return FALSE;
542
543         path = g_strdup(BT_CORE_PATH);
544         BT_DBG("path is [%s]", path);
545
546         obj_id = g_dbus_connection_register_object(conn, path,
547                                         node_info->interfaces[0],
548                                         &method_table,
549                                         NULL, NULL, &error);
550         g_dbus_node_info_unref(node_info);
551         if (obj_id == 0) {
552                 BT_ERR("Failed to register: %s", error->message);
553                 g_error_free(error);
554                 g_free(path);
555                 return FALSE;
556         }
557
558         g_free(path);
559
560         sig_id1 = g_dbus_connection_signal_subscribe(conn,
561                                 NULL, "org.freedesktop.DBus",
562                                 "NameOwnerChanged", NULL, NULL, 0,
563                                 __bt_core_event_filter, NULL, NULL);
564         sig_id2 = g_dbus_connection_signal_subscribe(conn,
565                                 NULL, "org.freedesktop.DBus.ObjectManager",
566                                 "InterfacesAdded", NULL, NULL,
567                                 0, __bt_core_event_filter, NULL, NULL);
568         sig_id2 = g_dbus_connection_signal_subscribe(conn,
569                                 NULL, "org.freedesktop.DBus.ObjectManager",
570                                 "InterfacesRemoved", NULL,
571                                 NULL, 0, __bt_core_event_filter, NULL, NULL);
572
573         return TRUE;
574 }
575
576 void  _bt_core_unregister_dbus(void)
577 {
578         GDBusConnection *conn;
579
580         BT_DBG("");
581
582         conn = _bt_core_get_gdbus_connection();
583         if (!conn)
584                 return;
585
586         if (obj_id > 0) {
587                 g_dbus_connection_unregister_object(conn, obj_id);
588                 obj_id = 0;
589         }
590
591         if (sig_id1 > 0) {
592                 g_dbus_connection_signal_unsubscribe(conn, sig_id1);
593                 sig_id1 = 0;
594         }
595         if (sig_id2 > 0) {
596                 g_dbus_connection_signal_unsubscribe(conn, sig_id2);
597                 sig_id2 = 0;
598         }
599         if (sig_id3 > 0) {
600                 g_dbus_connection_signal_unsubscribe(conn, sig_id3);
601                 sig_id3 = 0;
602         }
603 }