Add SmackProcessLabel option in systemd service files
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-hdp.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 <sys/types.h>
19 #include <sys/socket.h>
20 #include <gio/gio.h>
21 #include <glib.h>
22 #include <string.h>
23 #include <gio/gunixfdlist.h>
24
25 #include "bluetooth-api.h"
26 #include "bt-common.h"
27 #include "bt-internal-types.h"
28
29 #define HDP_BUFFER_SIZE 1024
30 #define BLUEZ_HDP_MANAGER_INTERFACE  "org.bluez.HealthManager1"
31 #define BLUEZ_HDP_DEVICE_INTERFACE  "org.bluez.HealthDevice1"
32 #define BLUEZ_HDP_CHANNEL_INTERFACE  "org.bluez.HealthChannel1"
33
34 typedef struct {
35         char *obj_channel_path;
36         int fd;
37         guint watch_id;
38 } hdp_obj_info_t;
39
40 typedef struct {
41         void *app_handle;
42         GSList *obj_info;
43 } hdp_app_list_t;
44
45 /* Variable for privilege, only for write API,
46   before we should reduce time to bt-service dbus calling
47   -1 : Don't have a permission to access API
48   0 : Initial value, not yet check
49   1 : Have a permission to access API
50 */
51 static int privilege_token;
52
53
54 /**********************************************************************
55 *               Static Functions declaration                            *
56 ***********************************************************************/
57 static int __bt_hdp_internal_create_application(unsigned int data_type,
58                                                 int role,
59                                                 bt_hdp_qos_type_t channel_type,
60                                                 char **app_handle);
61
62 static void __bt_hdp_internal_event_filter(GDBusConnection *connection,
63                                         const gchar *sender_name,
64                                         const gchar *object_path,
65                                         const gchar *interface_name,
66                                         const gchar *signal_name,
67                                         GVariant *parameters,
68                                         gpointer user_data);
69
70 static void __bt_hdp_internal_handle_connect(GVariant *parameters);
71
72 static void __bt_hdp_internal_handle_disconnect(GVariant *parameters,
73                                 const gchar *object_path);
74
75 static void __bt_hdp_internal_handle_property_changed(GVariant *parameters);
76
77 static int __bt_hdp_internal_add_filter(void);
78
79 static int __bt_hdp_internal_acquire_fd(const char *path);
80
81 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path);
82
83 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
84                                                 GIOCondition cond,
85                                                 gpointer data);
86
87 static int __bt_hdp_internal_destroy_application(const char *app_handle);
88
89 static void __bt_hdp_internal_remove_filter(void);
90
91 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle);
92
93 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd);
94
95 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path);
96
97 /*Global Variables*/
98 static GDBusConnection *g_hdp_dus_conn;
99
100 static GSList *g_app_list = NULL;
101
102 /**********************************************************************
103 *                       Health device APIs (HDP)                        *
104 ***********************************************************************/
105
106 BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type,
107                                         bt_hdp_role_type_t role,
108                                         bt_hdp_qos_type_t channel_type,
109                                         char **app_handle)
110 {
111         int result = BLUETOOTH_ERROR_NONE;
112
113         BT_DBG("+");
114
115         BT_CHECK_ENABLED(return);
116
117         /*For source role is mandatory */
118         if (role == HDP_ROLE_SOURCE && channel_type == HDP_QOS_ANY) {
119                 BT_ERR("For source, type is mandatory - Reliable/Streaming");
120                 return BLUETOOTH_ERROR_INVALID_PARAM;
121         }
122
123         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_REGISTER_SINK_APP)
124              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
125                 BT_ERR("Don't have a privilege to use this API");
126                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
127         }
128
129         result = __bt_hdp_internal_create_application(data_type, role,
130                                                 channel_type, app_handle);
131
132         return result;
133 }
134
135 static void __bt_hdp_obj_info_free(hdp_obj_info_t *info)
136 {
137         if (info) {
138                 g_source_remove(info->watch_id);
139                 close(info->fd);
140                 g_free(info->obj_channel_path);
141                 g_free(info);
142         }
143 }
144
145 static int __bt_hdp_internal_create_application(unsigned int data_type,
146                                         int role,
147                                         bt_hdp_qos_type_t channel_type,
148                                         char **app_handle)
149 {
150         GDBusProxy *proxy = NULL;
151         GVariant *reply = NULL;
152         GVariantBuilder *builder;
153         const char *svalue;
154         const char *key_type;
155         char *app_path;
156         hdp_app_list_t *list;
157         GError *err = NULL;
158         guint16 value;
159         GDBusConnection *conn;
160         int ret = BLUETOOTH_ERROR_NONE;
161
162         BT_DBG("+");
163
164         conn = _bt_gdbus_get_system_gconn();
165         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
166
167         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
168                                         NULL,
169                                         BT_BLUEZ_NAME,
170                                         "/org/bluez",
171                                         BLUEZ_HDP_MANAGER_INTERFACE,
172                                         NULL, &err);
173
174         if (!proxy) {
175                 BT_ERR("Unable to create proxy: %s", err->message);
176                 g_clear_error(&err);
177                 return BLUETOOTH_ERROR_INTERNAL;
178         }
179
180         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
181
182         key_type = "DataType";
183         value = (guint16) data_type;
184         g_variant_builder_add(builder, "{sv}",
185                         key_type, g_variant_new("q",
186                                 value));
187
188         key_type = "Role";
189         /*0-Source,1-Sink*/
190         svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source";
191         g_variant_builder_add(builder, "{sv}",
192                         key_type, g_variant_new("s",
193                                 svalue));
194
195         key_type = "Description";
196         svalue = "Health Device";
197         g_variant_builder_add(builder, "{sv}",
198                         key_type, g_variant_new("s",
199                                 svalue));
200
201         if (role == HDP_ROLE_SOURCE) {
202                 key_type = "ChannelType";
203                 if (channel_type == HDP_QOS_RELIABLE)
204                         svalue = "reliable";
205                 else if (channel_type == HDP_QOS_STREAMING)
206                         svalue = "streaming";
207
208                 g_variant_builder_add(builder, "{sv}",
209                         key_type, g_variant_new("s",
210                                 svalue));
211         }
212
213         reply = g_dbus_proxy_call_sync(proxy, "CreateApplication",
214                                         g_variant_new("(a{sv})", builder),
215                                         G_DBUS_CALL_FLAGS_NONE, -1,
216                                         NULL, &err);
217
218         g_variant_builder_unref(builder);
219         g_object_unref(proxy);
220
221         if (!reply) {
222                 BT_ERR(" HDP:dbus Can't create application");
223                 if (err) {
224                         BT_ERR("%s", err->message);
225                         if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
226                                 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
227                         else
228                                 ret = BLUETOOTH_ERROR_INTERNAL;
229                         g_clear_error(&err);
230                 }
231                 return ret;
232         }
233
234         g_variant_get(reply, "(&o)", &app_path);
235         BT_DBG("Created health application: %s", (char *)app_path);
236
237         ret = __bt_hdp_internal_add_filter();
238
239         if (ret != BLUETOOTH_ERROR_NONE) {
240                 BT_ERR("Funtion failed");
241                 return ret;
242         }
243
244         list = g_new0(hdp_app_list_t, 1);
245         list->app_handle = (void *)g_strdup(app_path);
246         *app_handle = list->app_handle;
247
248         g_app_list = g_slist_append(g_app_list, list);
249
250         g_variant_unref(reply);
251         return BLUETOOTH_ERROR_NONE;
252 }
253
254 static int __bt_hdp_add_filter_subscribe_signal(GDBusConnection *conn,
255                 gboolean subscribe)
256 {
257         static guint subs_add_filter_id = 0;
258
259         if (conn == NULL)
260                 return BLUETOOTH_ERROR_INVALID_PARAM;
261
262         if (subscribe) {
263                 if (subs_add_filter_id == 0) {
264                         subs_add_filter_id = g_dbus_connection_signal_subscribe(
265                                 conn, NULL, BLUEZ_HDP_DEVICE_INTERFACE,
266                                 NULL, NULL, NULL, 0,
267                                 __bt_hdp_internal_event_filter, NULL, NULL);
268                 }
269         } else {
270                 if (subs_add_filter_id > 0) {
271                         g_dbus_connection_signal_unsubscribe(conn,
272                                         subs_add_filter_id);
273                         subs_add_filter_id = 0;
274                 }
275         }
276         return BLUETOOTH_ERROR_NONE;
277 }
278
279 static int __bt_hdp_internal_add_filter(void)
280 {
281         BT_DBG("+");
282
283         /*Single process only one signal registration is required */
284         if (g_hdp_dus_conn) {
285                 BT_ERR("g_hdp_dus_conn already exist");
286                 return BLUETOOTH_ERROR_NONE;
287         }
288
289         g_hdp_dus_conn = _bt_gdbus_get_system_gconn();
290         retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
291
292
293         return __bt_hdp_add_filter_subscribe_signal(g_hdp_dus_conn, TRUE);
294 }
295
296 static void __bt_hdp_internal_event_filter(GDBusConnection *connection,
297                                         const gchar *sender_name,
298                                         const gchar *object_path,
299                                         const gchar *interface_name,
300                                         const gchar *signal_name,
301                                         GVariant *parameters,
302                                         gpointer user_data)
303 {
304         BT_DBG("Path = %s\n", object_path);
305         if (object_path == NULL || g_strcmp0(object_path, "/") == 0)
306                 return;
307
308         if (signal_name == NULL)
309                 return;
310
311         if (strcasecmp(signal_name, "ChannelConnected") == 0)
312                 __bt_hdp_internal_handle_connect(parameters);
313
314         else if (strcasecmp(signal_name, "ChannelDeleted") == 0)
315                 __bt_hdp_internal_handle_disconnect(parameters, object_path);
316
317         else if (strcasecmp(signal_name, "PropertyChanged") == 0)
318                 __bt_hdp_internal_handle_property_changed(parameters);
319
320         return;
321 }
322
323 static void __bt_hdp_internal_handle_connect(GVariant *parameters)
324 {
325         BT_DBG("+");
326         const char *obj_channel_path;
327         bt_user_info_t *user_info;
328         int ret;
329
330         BT_INFO("*********Signal - ChannelConnected******\n\n");
331         g_variant_get(parameters, "(&o)", &obj_channel_path);
332
333         BT_INFO("Channel connected, Path = %s", obj_channel_path);
334
335         user_info = _bt_get_user_data(BT_COMMON);
336         if (user_info == NULL || user_info->cb == NULL)
337                 return;
338
339         ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
340         if (ret != BLUETOOTH_ERROR_NONE) {
341                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
342                                 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
343                                 user_info->cb, user_info->user_data);
344         }
345         BT_DBG("-");
346 }
347
348 static void __bt_hdp_internal_handle_disconnect(GVariant *parameters,
349                                         const gchar *object_path)
350 {
351         const char *obj_channel_path;
352         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
353         bluetooth_device_address_t device_addr = { {0} };
354         bt_hdp_disconnected_t dis_ind;
355         hdp_obj_info_t *info;
356         bt_user_info_t *user_info;
357
358         BT_INFO("+********Signal - ChannelDeleted ******\n\n");
359         BT_DBG("Path = %s", object_path);
360
361         g_variant_get(parameters, "(&o)", &obj_channel_path);
362
363         BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
364
365         info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
366         if (!info) {
367                 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
368                 return;
369         }
370
371         /*Since bluetoothd is not sending the ChannelDeleted signal */
372         _bt_convert_device_path_to_address(object_path, address);
373
374         _bt_convert_addr_string_to_type(device_addr.addr, address);
375
376         dis_ind.channel_id = info->fd;
377         dis_ind.device_address = device_addr;
378
379         user_info = _bt_get_user_data(BT_COMMON);
380
381         if (user_info->cb) {
382                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
383                                 BLUETOOTH_ERROR_NONE, &dis_ind,
384                                 user_info->cb, user_info->user_data);
385         }
386
387         BT_DBG(" Removed connection from list\n");
388
389         __bt_hdp_obj_info_free(info);
390
391 }
392
393 static void __bt_hdp_internal_handle_property_changed(GVariant *parameters)
394 {
395         char *property = NULL;
396         GVariant *value = NULL;
397         gsize len;
398         char *obj_main_channel_path = NULL;
399         GVariantIter *property_iter;
400
401         BT_DBG("+*******Signal - PropertyChanged*******\n");
402
403         g_variant_get(parameters, "(a{sv})", &property_iter);
404
405         while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
406                 if (g_strcmp0("MainChannel", property) == 0) {
407                         BT_INFO("Property MainChannel received");
408                         obj_main_channel_path = g_variant_dup_string(value, &len);
409                         BT_DBG("Main Channel  Path = %s", obj_main_channel_path);
410                         break;
411                 }
412         }
413         g_variant_iter_free(property_iter);
414
415         g_free(property);
416         g_variant_unref(value);
417         g_free(obj_main_channel_path);
418         BT_DBG("-*************\n");
419 }
420
421 static int __bt_hdp_internal_acquire_fd(const char *path)
422 {
423         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
424         bluetooth_device_address_t device_addr = { {0} };
425         const char *property;
426         GVariant *value = NULL;
427         char *type_qos = NULL;
428         char *device = NULL;
429         char *app_handle = NULL;
430         hdp_app_list_t *list = NULL;
431         GDBusProxy *proxy = NULL;
432         GVariant *reply = NULL;
433         GDBusConnection *conn;
434         bt_hdp_connected_t conn_ind;
435         GError *err = NULL;
436         int fd;
437         bt_user_info_t *user_info;
438         char *dev_path;
439         GUnixFDList *out_fd_list;
440         int index;
441         GVariantIter *property_iter;
442         gsize len;
443
444         BT_DBG("+");
445
446         conn = _bt_gdbus_get_system_gconn();
447         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
448
449         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
450                                         NULL,
451                                         BT_BLUEZ_NAME,
452                                         path,
453                                         BLUEZ_HDP_CHANNEL_INTERFACE,
454                                         NULL, &err);
455
456         if (!proxy) {
457                 BT_ERR("Unable to create proxy: %s", err->message);
458                 g_clear_error(&err);
459                 return BLUETOOTH_ERROR_INTERNAL;
460         }
461
462         reply = g_dbus_proxy_call_with_unix_fd_list_sync(proxy,
463                                 "Acquire", NULL,
464                                 G_DBUS_CALL_FLAGS_NONE,
465                                 -1, NULL, &out_fd_list,
466                                 NULL, &err);
467
468         g_object_unref(proxy);
469
470         if (!reply) {
471                 BT_ERR(" HDP:****** dbus Can't create application ****");
472
473                 if (err) {
474                         BT_ERR("%s", err->message);;
475                         g_clear_error(&err);
476                 }
477
478                 return BLUETOOTH_ERROR_INTERNAL;
479         }
480
481         g_variant_get(reply, "(h)", &index);
482         fd = g_unix_fd_list_get(out_fd_list, index, NULL);
483
484         g_variant_unref(reply);
485
486         BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
487
488         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
489                                         NULL,
490                                         BT_BLUEZ_NAME,
491                                         path,
492                                         BT_PROPERTIES_INTERFACE,
493                                         NULL, &err);
494
495         if (!proxy) {
496                 BT_ERR("Unable to create proxy: %s", err->message);
497                 g_clear_error(&err);
498                 return BLUETOOTH_ERROR_INTERNAL;
499         }
500
501         dev_path = g_strdup(BLUEZ_HDP_CHANNEL_INTERFACE);
502
503         reply = g_dbus_proxy_call_sync(proxy, "GetAll",
504                                 g_variant_new("(s)", dev_path),
505                                 G_DBUS_CALL_FLAGS_NONE,
506                                 -1,
507                                 NULL,
508                                 &err);
509
510         g_free(dev_path);
511         g_object_unref(proxy);
512
513         if (!reply) {
514                 BT_ERR(" HDP:dbus Can't get the reply");
515
516                 if (err) {
517                         BT_ERR("%s", err->message);;
518                         g_clear_error(&err);
519                 }
520
521                 return BLUETOOTH_ERROR_INTERNAL;
522         }
523
524         g_variant_get(reply, "(a{sv})", &property_iter);
525
526         while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
527                 BT_DBG("String received = %s\n", property);
528
529                 if (g_strcmp0("Type", property) == 0)
530                         type_qos = g_variant_dup_string(value, &len);
531                 else if (g_strcmp0("Device", property) == 0)
532                         device = g_variant_dup_string(value, &len);
533                 else if (g_strcmp0("Application", property) == 0)
534                         app_handle = g_variant_dup_string(value, &len);
535         }
536         g_variant_iter_free(property_iter);
537
538         g_variant_unref(reply);
539         BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
540                         type_qos, device, app_handle);
541
542         if (NULL == type_qos || NULL == app_handle) {
543                 BT_ERR("Pasing failed\n");
544                 goto error;
545         }
546
547         list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
548
549         /*Only process register with app handle receive the Connected event */
550         if (NULL == list) {
551                 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
552                 goto error;
553         }
554
555         hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
556         info->fd = fd;
557         info->obj_channel_path = g_strdup(path);
558         info->watch_id = __bt_hdp_internal_watch_fd(fd, info->obj_channel_path);
559         list->obj_info = g_slist_append(list->obj_info, info);
560
561         _bt_convert_device_path_to_address(path, address);
562
563         _bt_convert_addr_string_to_type(device_addr.addr, address);
564
565         conn_ind.app_handle = app_handle;
566         conn_ind.channel_id = fd;
567         conn_ind.device_address = device_addr;
568         conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ?
569                         HDP_QOS_RELIABLE : HDP_QOS_STREAMING;
570
571         BT_DBG("Going to give callback\n");
572
573         user_info = _bt_get_user_data(BT_COMMON);
574
575         if (user_info->cb) {
576                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
577                                 BLUETOOTH_ERROR_NONE, &conn_ind,
578                                 user_info->cb, user_info->user_data);
579         }
580
581         BT_DBG("Updated fd in the list*\n");
582         BT_DBG("-\n");
583
584         g_free(type_qos);
585         g_free(device);
586         g_free(app_handle);
587         return BLUETOOTH_ERROR_NONE;
588 error:
589         g_free(type_qos);
590         g_free(device);
591         g_free(app_handle);
592         return BLUETOOTH_ERROR_INTERNAL;
593 }
594
595 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
596 {
597         GIOChannel *gio;
598         guint id;
599
600         BT_DBG("+");
601
602         gio = g_io_channel_unix_new(file_desc);
603
604         g_io_channel_set_close_on_unref(gio, TRUE);
605
606         id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
607                         __bt_hdp_internal_data_received, (void *)path);
608         BT_DBG("-");
609         return id;
610 }
611
612
613 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
614 {
615         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
616         bluetooth_device_address_t device_addr = { {0} };
617         bt_hdp_disconnected_t dis_ind;
618         hdp_obj_info_t *info;
619         bt_user_info_t *user_info;
620
621         BT_INFO("******** Socket Error  ******\n");
622
623         info = __bt_hdp_internal_gslist_obj_find_using_path(path);
624         ret_if(info == NULL);
625
626         /*Since bluetoothd is not sending the ChannelDeleted signal */
627         _bt_convert_device_path_to_address(path, address);
628
629         _bt_convert_addr_string_to_type(device_addr.addr, address);
630
631         dis_ind.channel_id = sk;
632         dis_ind.device_address = device_addr;
633
634         user_info = _bt_get_user_data(BT_COMMON);
635
636         if (user_info->cb) {
637                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
638                                 BLUETOOTH_ERROR_NONE, &dis_ind,
639                                 user_info->cb, user_info->user_data);
640         }
641
642         BT_DBG(" Removed connection from list\n");
643
644         __bt_hdp_obj_info_free(info);
645 }
646
647 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
648                                         GIOCondition cond, gpointer data)
649 {
650         char buff[HDP_BUFFER_SIZE] = { 0, };
651         int sk;
652         int act_read;
653         bt_hdp_data_ind_t data_ind = { 0, };
654         const char *path = (const char *)data;
655         bt_user_info_t *user_info;
656
657         BT_DBG("+");
658
659         sk = g_io_channel_unix_get_fd(gio);
660
661         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
662                 BT_DBG("GIOCondition %d.............path = %s\n", cond, path);
663                 g_io_channel_shutdown(gio, TRUE, NULL);
664                 g_io_channel_unref(gio);
665                  __bt_hdp_internal_handle_disconnect_cb(sk, path);
666                 return FALSE;
667         }
668
669         act_read = recv(sk, (void *)buff, sizeof(buff), 0);
670
671         if (act_read > 0) {
672                 BT_DBG("Received data of %d\n", act_read);
673         } else {
674                 BT_ERR("Read failed.....\n");
675                 return FALSE;
676         }
677
678         data_ind.channel_id = sk;
679         data_ind.buffer = buff;
680         data_ind.size = act_read;
681
682         user_info = _bt_get_user_data(BT_COMMON);
683
684         if (user_info->cb) {
685                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
686                                 BLUETOOTH_ERROR_NONE, &data_ind,
687                                 user_info->cb, user_info->user_data);
688         }
689
690         BT_DBG("-\n");
691
692         return TRUE;
693 }
694
695 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
696 {
697         BT_DBG("+");
698
699         BT_CHECK_ENABLED(return);
700         BT_CHECK_PARAMETER(app_handle, return);
701
702         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_UNREGISTER_SINK_APP)
703              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
704                 BT_ERR("Don't have a privilege to use this API");
705                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
706         }
707
708         return __bt_hdp_internal_destroy_application(app_handle);
709 }
710
711 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
712 {
713         GSList *l;
714
715         retv_if(g_app_list == NULL, NULL);
716
717         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
718
719         for (l = g_app_list; l != NULL; l = l->next) {
720                 hdp_app_list_t *list = l->data;
721
722                 if (list) {
723                         if (0 == g_strcmp0((char *)list->app_handle,
724                                                 (char *)app_handle))
725                                 return list;
726                 }
727         }
728         return NULL;
729 }
730
731 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
732 {
733         GSList *l;
734         GSList *iter;
735
736         retv_if(g_app_list == NULL, NULL);
737
738         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
739
740         for (l = g_app_list; l != NULL; l = l->next) {
741                 hdp_app_list_t *list = l->data;
742                 if (!list)
743                         return NULL;
744
745                 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
746                         hdp_obj_info_t *info = iter->data;
747                         if (!info)
748                                 return NULL;
749
750                         if (fd == info->fd)
751                                 return info;
752                 }
753         }
754         return NULL;
755 }
756
757 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
758 {
759         GSList *l;
760         GSList *iter;
761         hdp_obj_info_t *info = NULL;
762
763         retv_if(g_app_list == NULL, NULL);
764
765         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
766         for (l = g_app_list; l != NULL; l = l->next) {
767                 hdp_app_list_t *list = l->data;
768                 if (!list)
769                         return NULL;
770
771                 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
772                          info = iter->data;
773                         if (!info)
774                                 return NULL;
775
776                         if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
777                                 list->obj_info = g_slist_remove(list->obj_info, info);
778                                 return info;
779                         }
780                 }
781         }
782         return NULL;
783 }
784
785 static gboolean  __bt_hdp_internal_destroy_application_cb(gpointer data)
786 {
787         const char *app_handle;
788         hdp_app_list_t *list = NULL;
789         app_handle = (const char *)data;
790
791         BT_DBG("+");
792
793         list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
794         if (NULL == list) {
795                 BT_ERR("**** list not found for %s ******\n", app_handle);
796                 return FALSE;
797         }
798
799         g_app_list = g_slist_remove(g_app_list, list);
800
801         g_free(list->app_handle);
802         g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
803         g_free(list);
804
805         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
806
807         if (0 == g_slist_length(g_app_list))
808                 __bt_hdp_internal_remove_filter();
809         BT_DBG("-");
810         return FALSE;
811 }
812
813 static int __bt_hdp_internal_destroy_application(const char *app_handle)
814 {
815         GDBusProxy *proxy = NULL;
816         GVariant *reply = NULL;
817         GError *err = NULL;
818         GDBusConnection *conn;
819         int result = BLUETOOTH_ERROR_NONE;
820
821         conn = _bt_gdbus_get_system_gconn();
822         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
823
824         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
825                                         NULL,
826                                         BT_BLUEZ_NAME,
827                                         "/org/bluez",
828                                         BLUEZ_HDP_MANAGER_INTERFACE,
829                                         NULL, &err);
830
831         if (!proxy) {
832                 BT_ERR("Unable to create proxy: %s", err->message);
833                 g_clear_error(&err);
834                 return BLUETOOTH_ERROR_INTERNAL;
835         }
836
837         reply = g_dbus_proxy_call_sync(proxy, "DestroyApplication",
838                                 g_variant_new("o", app_handle),
839                                 G_DBUS_CALL_FLAGS_NONE,
840                                 -1,
841                                 NULL,
842                                 &err);
843
844         g_object_unref(proxy);
845         if (!reply) {
846                 BT_ERR(" HDP:dbus Can't Destroy application");
847
848                 if (err) {
849                         BT_ERR("%s", err->message);
850                         if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
851                                 result  = BLUETOOTH_ERROR_ACCESS_DENIED;
852                         else
853                                 result  = BLUETOOTH_ERROR_INTERNAL;
854                         g_clear_error(&err);
855                 }
856                 return result ;
857         }
858
859         g_variant_unref(reply);
860
861         BT_DBG("Destroyed health application: %s", (char *)app_handle);
862
863         g_idle_add(__bt_hdp_internal_destroy_application_cb,
864                         (gpointer)app_handle);
865
866         return BLUETOOTH_ERROR_NONE;
867 }
868
869 static void __bt_hdp_internal_remove_filter(void)
870 {
871         BT_DBG("+");
872
873         ret_if(g_hdp_dus_conn == NULL);
874
875         __bt_hdp_add_filter_subscribe_signal(g_hdp_dus_conn, FALSE);
876
877         g_hdp_dus_conn = NULL;  /*should not unref here, bcz no ++reff */
878
879         BT_DBG("-");
880 }
881
882 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
883                                             const char *buffer,
884                                             unsigned int size)
885 {
886         int wbytes = 0;
887         int written = 0;
888         int result;
889
890         BT_DBG("+");
891
892         BT_CHECK_ENABLED(return);
893
894         if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
895                 BT_ERR("Invalid arguments..\n");
896                 return BLUETOOTH_ERROR_INVALID_PARAM;
897         }
898
899         switch (privilege_token) {
900         case 0:
901                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
902
903                 if (result == BLUETOOTH_ERROR_NONE) {
904                         privilege_token = 1; /* Have a permission */
905                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
906                         BT_ERR("Don't have a privilege to use this API");
907                         privilege_token = -1; /* Don't have a permission */
908                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
909                 } else {
910                         /* Just break - It is not related with permission error */
911                 }
912                 break;
913         case 1:
914                 /* Already have a privilege */
915                 break;
916         case -1:
917                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
918         default:
919                 /* Invalid privilge token value */
920                 return BLUETOOTH_ERROR_INTERNAL;
921         }
922
923         while (wbytes < size) {
924                 written = write(channel_id, buffer + wbytes, size - wbytes);
925                 if (written <= 0) {
926                         BT_ERR("write failed..\n");
927                         return BLUETOOTH_ERROR_NOT_IN_OPERATION;
928                 }
929                 wbytes += written;
930         }
931
932         return BLUETOOTH_ERROR_NONE;
933 }
934
935 static void __bt_hdp_connect_request_cb(GDBusProxy *hdp_proxy,
936                                 GAsyncResult *res, gpointer user_data)
937 {
938         GError *err = NULL;
939         char *obj_connect_path = NULL;
940         bt_hdp_connected_t *conn_ind = user_data;
941         bt_user_info_t *user_info;
942         GVariant *reply = NULL;
943
944         reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
945
946         g_object_unref(hdp_proxy);
947
948         if (!reply) {
949                 if (err) {
950                         BT_ERR("HDP connection  Dbus Call Error: %s\n", err->message);
951                         g_clear_error(&err);
952                 }
953
954                 user_info = _bt_get_user_data(BT_COMMON);
955
956                 if (user_info->cb) {
957                         _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
958                                         BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind,
959                                         user_info->cb, user_info->user_data);
960                 }
961         } else {
962                 g_variant_get(reply, "(&o)", &obj_connect_path);
963                 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
964         }
965         g_free((void *)conn_ind->app_handle);
966         g_free(conn_ind);
967 }
968
969
970 BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle,
971                         bt_hdp_qos_type_t channel_type,
972                         const bluetooth_device_address_t *device_address)
973 {
974         GError *err = NULL;
975         GDBusConnection *conn = NULL;
976         GDBusProxy *hdp_proxy = NULL;
977         bt_hdp_connected_t *param;
978         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
979         char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
980         char *dev_path = NULL;
981         char *role;
982
983         BT_DBG("+");
984
985         BT_CHECK_ENABLED(return);
986         BT_CHECK_PARAMETER(app_handle, return);
987         BT_CHECK_PARAMETER(device_address, return);
988
989         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_CONNECT)
990              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
991                 BT_ERR("Don't have a privilege to use this API");
992                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
993         }
994
995         if (channel_type == HDP_QOS_RELIABLE) {
996                 role = "Reliable";
997         } else if (channel_type == HDP_QOS_STREAMING) {
998                 role = "Streaming";
999         } else if (channel_type == HDP_QOS_ANY) {
1000                 role = "Any";
1001         } else {
1002                 BT_ERR("Invalid channel_type %d", channel_type);
1003                 return BLUETOOTH_ERROR_ACCESS_DENIED;
1004         }
1005
1006         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1007
1008         if (err) {
1009                 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1010                 g_clear_error(&err);
1011                 return BLUETOOTH_ERROR_INTERNAL;
1012         }
1013
1014         /* If the adapter path is wrong, we can think the BT is not enabled. */
1015         if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1016                                         default_adapter_path) < 0) {
1017                 BT_ERR("Could not get adapter path\n");
1018                 g_object_unref(conn);
1019                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1020         }
1021
1022         _bt_convert_addr_type_to_string(address,
1023                                 (unsigned char *)device_address->addr);
1024
1025         BT_DBG("create conection to %s", address);
1026
1027         dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1028
1029         if (dev_path == NULL) {
1030                 g_object_unref(conn);
1031                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1032         }
1033
1034         g_strdelimit(dev_path, ":", '_');
1035
1036         BT_DBG("path: %s", dev_path);
1037
1038         hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1039                                                 NULL, BT_BLUEZ_NAME,
1040                                                 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1041                                                 NULL, NULL);
1042         g_object_unref(conn);
1043
1044         if (hdp_proxy == NULL) {
1045                 BT_ERR("Failed to get the HDP server proxy\n");
1046                 g_free(dev_path);
1047                 return BLUETOOTH_ERROR_NOT_PAIRED;
1048         }
1049
1050         BT_DBG("app path %s\n", app_handle);
1051
1052         param = g_new0(bt_hdp_connected_t, 1);
1053         param->app_handle = g_strdup(app_handle);
1054         memcpy(&param->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1055         param->type = channel_type;
1056
1057         g_dbus_proxy_call(hdp_proxy, "CreateChannel",
1058                                 g_variant_new("(os)", app_handle, role),
1059                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1060                                 (GAsyncReadyCallback)__bt_hdp_connect_request_cb,
1061                                 param);
1062
1063         g_free(dev_path);
1064
1065         return BLUETOOTH_ERROR_NONE;
1066 }
1067
1068 static void __bt_hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
1069                         GAsyncResult *res, gpointer user_data)
1070 {
1071         GError *err = NULL;
1072         bt_hdp_disconnected_t *disconn_ind = user_data;
1073         bt_user_info_t *user_info;
1074         GVariant *reply = NULL;
1075
1076         reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1077         g_object_unref(hdp_proxy);
1078
1079         user_info = _bt_get_user_data(BT_COMMON);
1080         if (user_info == NULL || user_info->cb == NULL) {
1081                 g_free(disconn_ind);
1082                 if (err) {
1083                                 g_clear_error(&err);
1084                         return;
1085                 }
1086                 g_variant_unref(reply);
1087                 return;
1088         }
1089
1090         if (!reply) {
1091                 if (err) {
1092                         BT_ERR("HDP disconnection Dbus Call Error: %s\n",
1093                                                         err->message);
1094                         g_clear_error(&err);
1095                 }
1096
1097                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1098                                 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1099                                 user_info->cb, user_info->user_data);
1100         } else {
1101                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1102                                 BLUETOOTH_ERROR_NONE, disconn_ind,
1103                                 user_info->cb, user_info->user_data);
1104                 BT_INFO("HDP disconnection Dbus Call is done\n");
1105                 g_variant_unref(reply);
1106         }
1107
1108         g_free(disconn_ind);
1109 }
1110
1111 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1112                         const bluetooth_device_address_t *device_address)
1113 {
1114         GError *err = NULL;
1115         GDBusConnection *conn = NULL;
1116         GDBusProxy *hdp_proxy = NULL;
1117         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1118         char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1119         char *dev_path = NULL;
1120         bt_hdp_disconnected_t *param;
1121
1122         BT_DBG("+\n");
1123
1124         BT_CHECK_ENABLED(return);
1125         BT_CHECK_PARAMETER(device_address, return);
1126
1127         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_DISCONNECT)
1128              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1129                 BT_ERR("Don't have a privilege to use this API");
1130                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1131         }
1132
1133         hdp_obj_info_t *info =
1134                 __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1135         if (NULL == info) {
1136                 BT_ERR("*** Could not locate the list for %d*****\n",
1137                                                         channel_id);
1138                 return BLUETOOTH_ERROR_INVALID_PARAM;
1139         }
1140
1141         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1142
1143         if (err) {
1144                 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1145                 g_clear_error(&err);
1146                 return BLUETOOTH_ERROR_INTERNAL;
1147         }
1148
1149         /* If the adapter path is wrong, we can think the BT is not enabled. */
1150         if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1151                                         default_adapter_path) < 0) {
1152                 BT_ERR("Could not get adapter path\n");
1153                 g_object_unref(conn);
1154                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1155         }
1156
1157         _bt_convert_addr_type_to_string(address,
1158                                 (unsigned char *)device_address->addr);
1159
1160         BT_DBG("create conection to  %s\n", address);
1161
1162         dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1163
1164         if (dev_path == NULL) {
1165                 g_object_unref(conn);
1166                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1167         }
1168
1169         g_strdelimit(dev_path, ":", '_');
1170
1171         BT_DBG("path  %s\n", dev_path);
1172
1173         hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1174                                                 NULL, BT_BLUEZ_NAME,
1175                                                 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1176                                                 NULL, NULL);
1177
1178         g_object_unref(conn);
1179
1180         if (hdp_proxy == NULL) {
1181                 BT_ERR("Failed to get the HDP proxy\n");
1182                 g_free(dev_path);
1183                 return BLUETOOTH_ERROR_NOT_PAIRED;
1184         }
1185
1186         param = g_new0(bt_hdp_disconnected_t, 1);
1187         param->channel_id = channel_id;
1188         memcpy(&param->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1189
1190         g_dbus_proxy_call(hdp_proxy, "DestroyChannel",
1191                                 g_variant_new("o", info->obj_channel_path),
1192                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1193                                 (GAsyncReadyCallback)__bt_hdp_disconnect_request_cb,
1194                                 param);
1195
1196         g_free(dev_path);
1197         g_free(param);
1198         g_object_unref(hdp_proxy);
1199
1200         return BLUETOOTH_ERROR_NONE;
1201
1202 }