e9e35fab7ae4a3dd48558687e0a681c96e485681
[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         BT_DBG("-\n");
296 }
297
298 static void __bt_hdp_internal_event_filter(GDBusConnection *connection,
299                                         const gchar *sender_name,
300                                         const gchar *object_path,
301                                         const gchar *interface_name,
302                                         const gchar *signal_name,
303                                         GVariant *parameters,
304                                         gpointer user_data)
305 {
306         BT_DBG("Path = %s\n", object_path);
307         if (object_path == NULL || g_strcmp0(object_path, "/") == 0)
308                 return;
309
310         if (signal_name == NULL)
311                 return;
312
313         if (strcasecmp(signal_name, "ChannelConnected") == 0) 
314                 __bt_hdp_internal_handle_connect(parameters);
315
316         else if (strcasecmp(signal_name, "ChannelDeleted") == 0)
317                 __bt_hdp_internal_handle_disconnect(parameters, object_path);
318
319         else if (strcasecmp(signal_name, "PropertyChanged") == 0)
320                 __bt_hdp_internal_handle_property_changed(parameters);
321
322         return;
323 }
324
325 static void __bt_hdp_internal_handle_connect(GVariant *parameters)
326 {
327         BT_DBG("+");
328         const char *obj_channel_path;
329         bt_user_info_t *user_info;
330         int ret;
331
332         BT_INFO("*********Signal - ChannelConnected******\n\n");
333         g_variant_get(parameters, "(&o)", &obj_channel_path);
334
335         BT_INFO("Channel connected, Path = %s", obj_channel_path);
336
337         user_info = _bt_get_user_data(BT_COMMON);
338         if (user_info == NULL || user_info->cb == NULL)
339                 return;
340
341         ret = __bt_hdp_internal_acquire_fd(obj_channel_path);
342         if (ret != BLUETOOTH_ERROR_NONE) {
343                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
344                                 BLUETOOTH_ERROR_CONNECTION_ERROR, NULL,
345                                 user_info->cb, user_info->user_data);
346         }
347         BT_DBG("-");
348 }
349
350 static void __bt_hdp_internal_handle_disconnect(GVariant *parameters,
351                                         const gchar *object_path)
352 {
353         const char *obj_channel_path;
354         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
355         bluetooth_device_address_t device_addr = { {0} };
356         bt_hdp_disconnected_t dis_ind;
357         hdp_obj_info_t *info;
358         bt_user_info_t *user_info;
359
360         BT_INFO("+********Signal - ChannelDeleted ******\n\n");
361         BT_DBG("Path = %s", object_path);
362
363         g_variant_get(parameters, "(&o)", &obj_channel_path);
364
365         BT_INFO("Channel Deleted, Path = %s", obj_channel_path);
366
367         info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path);
368         if (!info) {
369                 BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path);
370                 return;
371         }
372
373         /*Since bluetoothd is not sending the ChannelDeleted signal */
374         _bt_convert_device_path_to_address(object_path, address);
375
376         _bt_convert_addr_string_to_type(device_addr.addr, address);
377
378         dis_ind.channel_id = info->fd;
379         dis_ind.device_address = device_addr;
380
381         user_info = _bt_get_user_data(BT_COMMON);
382
383         if (user_info->cb) {
384                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
385                                 BLUETOOTH_ERROR_NONE, &dis_ind,
386                                 user_info->cb, user_info->user_data);
387         }
388
389         BT_DBG(" Removed connection from list\n");
390
391         __bt_hdp_obj_info_free(info);
392
393 }
394
395 static void __bt_hdp_internal_handle_property_changed(GVariant *parameters)
396 {
397         char *property = NULL;
398         GVariant *value = NULL;
399         gsize len;
400         char *obj_main_channel_path = NULL;
401         GVariantIter *property_iter;
402
403         BT_DBG("+*******Signal - PropertyChanged*******\n");
404
405         g_variant_get(parameters, "(a{sv})", &property_iter);
406
407         while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
408                 if (g_strcmp0("MainChannel", property) == 0) {
409                         BT_INFO("Property MainChannel received");
410                         obj_main_channel_path = g_variant_dup_string(value, &len);
411                         BT_DBG("Main Channel  Path = %s", obj_main_channel_path);
412                         break;
413                 }
414         }
415         g_variant_iter_free(property_iter);
416
417         g_free(property);
418         g_variant_unref(value);
419         g_free(obj_main_channel_path);
420         BT_DBG("-*************\n");
421 }
422
423 static int __bt_hdp_internal_acquire_fd(const char *path)
424 {
425         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
426         bluetooth_device_address_t device_addr = { {0} };
427         const char *property;
428         GVariant *value = NULL;
429         char *type_qos = NULL;
430         char *device = NULL;
431         char *app_handle = NULL;
432         hdp_app_list_t *list = NULL;
433         GDBusProxy *proxy = NULL;
434         GVariant *reply = NULL;
435         GDBusConnection *conn;
436         bt_hdp_connected_t conn_ind;
437         GError *err = NULL;
438         int fd;
439         bt_user_info_t *user_info;
440         char *dev_path;
441         GUnixFDList *out_fd_list;
442         int index;
443         GVariantIter *property_iter;
444         gsize len;
445
446         BT_DBG("+");
447
448         conn = _bt_gdbus_get_system_gconn();
449         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
450
451         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
452                                         NULL,
453                                         BT_BLUEZ_NAME,
454                                         path,
455                                         BLUEZ_HDP_CHANNEL_INTERFACE,
456                                         NULL, &err);
457
458         if (!proxy) {
459                 BT_ERR("Unable to create proxy: %s", err->message);
460                 g_clear_error(&err);
461                 return BLUETOOTH_ERROR_INTERNAL;
462         }
463
464         reply = g_dbus_proxy_call_with_unix_fd_list_sync(proxy,
465                                                    "Acquire",
466                                                    NULL,
467                                                    G_DBUS_CALL_FLAGS_NONE,
468                                                    -1,
469                                                    NULL,
470                                                    &out_fd_list,
471                                                    NULL,
472                                                   &err);
473
474         g_object_unref(proxy);
475
476         if (!reply) {
477                 BT_ERR(" HDP:****** dbus Can't create application ****");
478
479                 if (err) {
480                         BT_ERR("%s", err->message);;
481                         g_clear_error(&err);
482                 }
483
484                 return BLUETOOTH_ERROR_INTERNAL;
485         }
486
487         g_variant_get(reply, "(h)", &index);
488         fd = g_unix_fd_list_get(out_fd_list, index, NULL);
489
490         g_variant_unref(reply);
491
492         BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path);
493
494         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
495                                         NULL,
496                                         BT_BLUEZ_NAME,
497                                         path,
498                                         BT_PROPERTIES_INTERFACE,
499                                         NULL, &err);
500
501         if (!proxy) {
502                 BT_ERR("Unable to create proxy: %s", err->message);
503                 g_clear_error(&err);
504                 return BLUETOOTH_ERROR_INTERNAL;
505         }
506
507         dev_path = g_strdup(BLUEZ_HDP_CHANNEL_INTERFACE);
508
509         reply = g_dbus_proxy_call_sync(proxy, "GetAll",
510                                 g_variant_new("(s)", dev_path),
511                                 G_DBUS_CALL_FLAGS_NONE,
512                                 -1,
513                                 NULL,
514                                 &err);
515
516         g_free(dev_path);
517         g_object_unref(proxy);
518
519         if (!reply) {
520                 BT_ERR(" HDP:dbus Can't get the reply");
521
522                 if (err) {
523                         BT_ERR("%s", err->message);;
524                         g_clear_error(&err);
525                 }
526
527                 return BLUETOOTH_ERROR_INTERNAL;
528         }
529
530         g_variant_get(reply, "(a{sv})", &property_iter);
531
532         while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
533                 BT_DBG("String received = %s\n", property);
534
535                 if (g_strcmp0("Type", property) == 0) {
536                         type_qos = g_variant_dup_string(value, &len);
537                 } else if (g_strcmp0("Device", property) == 0) {
538                         device = g_variant_dup_string(value, &len);
539                 } else if (g_strcmp0("Application", property) == 0) {
540                         app_handle = g_variant_dup_string(value, &len);
541                 }
542         }
543         g_variant_iter_free(property_iter);
544
545         g_variant_unref(reply);
546         BT_DBG("QOS = %s, Device = %s, Apphandler = %s",
547                         type_qos, device, app_handle);
548
549         if (NULL == type_qos || NULL == app_handle) {
550                 BT_ERR("Pasing failed\n");
551                 goto error;
552         }
553
554         list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
555
556         /*Only process register with app handle receive the Connected event */
557         if (NULL == list) {
558                 BT_ERR("**** Could not locate the list for %s*****\n", app_handle);
559                 goto error;
560         }
561
562         hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1);
563         info->fd = fd;
564         info->obj_channel_path = g_strdup(path);
565         info->watch_id = __bt_hdp_internal_watch_fd(fd, info->obj_channel_path);
566         list->obj_info = g_slist_append(list->obj_info, info);
567
568         _bt_convert_device_path_to_address(path, address);
569
570         _bt_convert_addr_string_to_type(device_addr.addr, address);
571
572         conn_ind.app_handle = app_handle;
573         conn_ind.channel_id = fd;
574         conn_ind.device_address = device_addr;
575         conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ?
576                         HDP_QOS_RELIABLE : HDP_QOS_STREAMING;
577
578         BT_DBG("Going to give callback\n");
579
580         user_info = _bt_get_user_data(BT_COMMON);
581
582         if (user_info->cb) {
583                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
584                                 BLUETOOTH_ERROR_NONE, &conn_ind,
585                                 user_info->cb, user_info->user_data);
586         }
587
588         BT_DBG("Updated fd in the list*\n");
589         BT_DBG("-\n");
590
591         g_free(type_qos);
592         g_free(device);
593         g_free(app_handle);
594         return BLUETOOTH_ERROR_NONE;
595 error:
596         g_free(type_qos);
597         g_free(device);
598         g_free(app_handle);
599         return BLUETOOTH_ERROR_INTERNAL;
600 }
601
602 static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path)
603 {
604         GIOChannel *gio;
605         guint id;
606
607         BT_DBG("+");
608
609         gio = g_io_channel_unix_new(file_desc);
610
611         g_io_channel_set_close_on_unref(gio, TRUE);
612
613         id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
614                         __bt_hdp_internal_data_received, (void *)path);
615         BT_DBG("-");
616         return id;
617 }
618
619
620 static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path)
621 {
622         char address[BT_ADDRESS_STRING_SIZE] = { 0, };
623         bluetooth_device_address_t device_addr = { {0} };
624         bt_hdp_disconnected_t dis_ind;
625         hdp_obj_info_t *info;
626         bt_user_info_t *user_info;
627
628         BT_INFO("******** Socket Error  ******\n");
629
630         info = __bt_hdp_internal_gslist_obj_find_using_path(path);
631         ret_if(info == NULL);
632
633         /*Since bluetoothd is not sending the ChannelDeleted signal */
634         _bt_convert_device_path_to_address(path, address);
635
636         _bt_convert_addr_string_to_type(device_addr.addr, address);
637
638         dis_ind.channel_id = sk;
639         dis_ind.device_address = device_addr;
640
641         user_info = _bt_get_user_data(BT_COMMON);
642
643         if (user_info->cb) {
644                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
645                                 BLUETOOTH_ERROR_NONE, &dis_ind,
646                                 user_info->cb, user_info->user_data);
647         }
648
649         BT_DBG(" Removed connection from list\n");
650
651         __bt_hdp_obj_info_free(info);
652 }
653
654 static gboolean __bt_hdp_internal_data_received(GIOChannel *gio,
655                                         GIOCondition cond, gpointer data)
656 {
657         char buff[HDP_BUFFER_SIZE] = { 0, };
658         int sk;
659         int act_read;
660         bt_hdp_data_ind_t data_ind = { 0, };
661         const char *path = (const char *)data;
662         bt_user_info_t *user_info;
663
664         BT_DBG("+");
665
666         sk = g_io_channel_unix_get_fd(gio);
667
668         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
669                 BT_DBG("GIOCondition %d.............path = %s\n", cond, path);
670                 g_io_channel_shutdown(gio, TRUE, NULL);
671                 g_io_channel_unref(gio);
672                  __bt_hdp_internal_handle_disconnect_cb(sk, path);
673                 return FALSE;
674         }
675
676         act_read = recv(sk, (void *)buff, sizeof(buff), 0);
677
678         if (act_read > 0) {
679                 BT_DBG("Received data of %d\n", act_read);
680         } else {
681                 BT_ERR("Read failed.....\n");
682                 return FALSE;
683         }
684
685         data_ind.channel_id = sk;
686         data_ind.buffer = buff;
687         data_ind.size = act_read;
688
689         user_info = _bt_get_user_data(BT_COMMON);
690
691         if (user_info->cb) {
692                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED,
693                                 BLUETOOTH_ERROR_NONE, &data_ind,
694                                 user_info->cb, user_info->user_data);
695         }
696
697         BT_DBG("-\n");
698
699         return TRUE;
700 }
701
702 BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle)
703 {
704         BT_DBG("+");
705
706         BT_CHECK_ENABLED(return);
707         BT_CHECK_PARAMETER(app_handle, return);
708
709         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_UNREGISTER_SINK_APP)
710              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
711                 BT_ERR("Don't have a privilege to use this API");
712                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
713         }
714
715         return __bt_hdp_internal_destroy_application(app_handle);
716 }
717
718 static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle)
719 {
720         GSList *l;
721
722         retv_if(g_app_list == NULL, NULL);
723
724         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
725
726         for (l = g_app_list; l != NULL; l = l->next) {
727                 hdp_app_list_t *list = l->data;
728
729                 if (list) {
730                         if (0 == g_strcmp0((char *)list->app_handle,
731                                                 (char *)app_handle))
732                                 return list;
733                 }
734         }
735         return NULL;
736 }
737
738 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd)
739 {
740         GSList *l;
741         GSList *iter;
742
743         retv_if(g_app_list == NULL, NULL);
744
745         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
746
747         for (l = g_app_list; l != NULL; l = l->next) {
748                 hdp_app_list_t *list = l->data;
749                 if (!list)
750                         return NULL;
751
752                 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
753                         hdp_obj_info_t *info = iter->data;
754                         if (!info)
755                                 return NULL;
756
757                         if (fd == info->fd)
758                                 return info;
759                 }
760         }
761         return NULL;
762 }
763
764 static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path)
765 {
766         GSList *l;
767         GSList *iter;
768         hdp_obj_info_t *info = NULL;
769
770         retv_if(g_app_list == NULL, NULL);
771
772         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
773         for (l = g_app_list; l != NULL; l = l->next) {
774                 hdp_app_list_t *list = l->data;
775                 if (!list)
776                         return NULL;
777
778                 for (iter = list->obj_info; iter != NULL; iter = iter->next) {
779                          info = iter->data;
780                         if (!info)
781                                 return NULL;
782
783                         if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) {
784                                 list->obj_info = g_slist_remove(list->obj_info, info);
785                                 return info;
786                         }
787                 }
788         }
789         return NULL;
790 }
791
792 static gboolean  __bt_hdp_internal_destroy_application_cb(gpointer data)
793 {
794         const char *app_handle;
795         hdp_app_list_t *list = NULL;
796         app_handle = (const char *)data;
797
798         BT_DBG("+");
799
800         list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle);
801         if (NULL == list) {
802                 BT_ERR("**** list not found for %s ******\n", app_handle);
803                 return FALSE;
804         }
805
806         g_app_list = g_slist_remove(g_app_list, list);
807
808         g_free(list->app_handle);
809         g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL);
810         g_free(list);
811
812         BT_DBG("List length = %d\n", g_slist_length(g_app_list));
813
814         if (0 == g_slist_length(g_app_list))
815                 __bt_hdp_internal_remove_filter();
816         BT_DBG("-");
817         return FALSE;
818 }
819
820 static int __bt_hdp_internal_destroy_application(const char *app_handle)
821 {
822         GDBusProxy *proxy = NULL;
823         GVariant *reply = NULL;
824         GError *err = NULL;
825         GDBusConnection *conn;
826         int result = BLUETOOTH_ERROR_NONE;
827
828         conn = _bt_gdbus_get_system_gconn();
829         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
830
831         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
832                                         NULL,
833                                         BT_BLUEZ_NAME,
834                                         "/org/bluez",
835                                         BLUEZ_HDP_MANAGER_INTERFACE,
836                                         NULL, &err);
837
838         if (!proxy) {
839                 BT_ERR("Unable to create proxy: %s", err->message);
840                 g_clear_error(&err);
841                 return BLUETOOTH_ERROR_INTERNAL;
842         }
843
844         reply = g_dbus_proxy_call_sync(proxy, "DestroyApplication",
845                                 g_variant_new("o", app_handle),
846                                 G_DBUS_CALL_FLAGS_NONE,
847                                 -1,
848                                 NULL,
849                                 &err);
850
851         g_object_unref(proxy);
852         if (!reply) {
853                 BT_ERR(" HDP:dbus Can't Destroy application");
854
855                 if (err) {
856                         BT_ERR("%s", err->message);
857                         if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
858                                 result  = BLUETOOTH_ERROR_ACCESS_DENIED;
859                         else
860                                 result  = BLUETOOTH_ERROR_INTERNAL;
861                         g_clear_error(&err);
862                 }
863                 return result ;
864         }
865
866         g_variant_unref(reply);
867
868         BT_DBG("Destroyed health application: %s", (char *)app_handle);
869
870         g_idle_add(__bt_hdp_internal_destroy_application_cb,
871                         (gpointer)app_handle);
872
873         return BLUETOOTH_ERROR_NONE;
874 }
875
876 static void __bt_hdp_internal_remove_filter(void)
877 {
878         BT_DBG("+");
879
880         ret_if(g_hdp_dus_conn == NULL);
881
882         __bt_hdp_add_filter_subscribe_signal(g_hdp_dus_conn, FALSE);
883
884         g_hdp_dus_conn = NULL;  /*should not unref here, bcz no ++reff */
885
886         BT_DBG("-");
887 }
888
889 BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id,
890                                             const char *buffer,
891                                             unsigned int size)
892 {
893         int wbytes = 0;
894         int written = 0;
895         int result;
896
897         BT_DBG("+");
898
899         BT_CHECK_ENABLED(return);
900
901         if ((channel_id == 0) || (NULL == buffer) || (size == 0)) {
902                 BT_ERR("Invalid arguments..\n");
903                 return BLUETOOTH_ERROR_INVALID_PARAM;
904         }
905
906         switch (privilege_token) {
907         case 0:
908                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA);
909
910                 if (result == BLUETOOTH_ERROR_NONE) {
911                         privilege_token = 1; /* Have a permission */
912                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
913                         BT_ERR("Don't have a privilege to use this API");
914                         privilege_token = -1; /* Don't have a permission */
915                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
916                 } else {
917                         /* Just break - It is not related with permission error */
918                 }
919                 break;
920         case 1:
921                 /* Already have a privilege */
922                 break;
923         case -1:
924                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
925         default:
926                 /* Invalid privilge token value */
927                 return BLUETOOTH_ERROR_INTERNAL;
928         }
929
930         while (wbytes < size) {
931                 written = write(channel_id, buffer + wbytes, size - wbytes);
932                 if (written <= 0) {
933                         BT_ERR("write failed..\n");
934                         return BLUETOOTH_ERROR_NOT_IN_OPERATION;
935                 }
936                 wbytes += written;
937         }
938
939         return BLUETOOTH_ERROR_NONE;
940 }
941
942 static void __bt_hdp_connect_request_cb(GDBusProxy *hdp_proxy,
943                                 GAsyncResult *res, gpointer user_data)
944 {
945         GError *err = NULL;
946         char *obj_connect_path = NULL;
947         bt_hdp_connected_t *conn_ind = user_data;
948         bt_user_info_t *user_info;
949         GVariant *reply = NULL;
950
951         reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
952
953         g_object_unref(hdp_proxy);
954
955         if (!reply) {
956                 if (err) {
957                         BT_ERR("HDP connection  Dbus Call Error: %s\n", err->message);
958                         g_clear_error(&err);
959                 }
960
961                 user_info = _bt_get_user_data(BT_COMMON);
962
963                 if (user_info->cb) {
964                         _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED,
965                                         BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind,
966                                         user_info->cb, user_info->user_data);
967                 }
968         } else {
969                 g_variant_get(reply, "(&o)", &obj_connect_path);
970                 BT_DBG("Obj Path returned = %s\n", obj_connect_path);
971         }
972         g_free((void *)conn_ind->app_handle);
973         g_free(conn_ind);
974 }
975
976
977 BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle,
978                         bt_hdp_qos_type_t channel_type,
979                         const bluetooth_device_address_t *device_address)
980 {
981         GError *err = NULL;
982         GDBusConnection *conn = NULL;
983         GDBusProxy *hdp_proxy = NULL;
984         bt_hdp_connected_t *param;
985         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
986         char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
987         char *dev_path = NULL;
988         char *role;
989
990         BT_DBG("+");
991
992         BT_CHECK_ENABLED(return);
993         BT_CHECK_PARAMETER(app_handle, return);
994         BT_CHECK_PARAMETER(device_address, return);
995
996         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_CONNECT)
997              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
998                 BT_ERR("Don't have a privilege to use this API");
999                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1000         }
1001
1002         if (channel_type == HDP_QOS_RELIABLE) {
1003                 role = "Reliable";
1004         } else if (channel_type == HDP_QOS_STREAMING) {
1005                 role = "Streaming";
1006         } else if (channel_type == HDP_QOS_ANY) {
1007                 role = "Any";
1008         } else {
1009                 BT_ERR("Invalid channel_type %d", channel_type);
1010                 return BLUETOOTH_ERROR_ACCESS_DENIED;
1011         }
1012
1013         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1014
1015         if (err) {
1016                 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1017                 g_clear_error(&err);
1018                 return BLUETOOTH_ERROR_INTERNAL;
1019         }
1020
1021         /* If the adapter path is wrong, we can think the BT is not enabled. */
1022         if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1023                                         default_adapter_path) < 0) {
1024                 BT_ERR("Could not get adapter path\n");
1025                 g_object_unref(conn);
1026                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1027         }
1028
1029         _bt_convert_addr_type_to_string(address,
1030                                 (unsigned char *)device_address->addr);
1031
1032         BT_DBG("create conection to %s", address);
1033
1034         dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1035
1036         if (dev_path == NULL) {
1037                 g_object_unref(conn);
1038                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1039         }
1040
1041         g_strdelimit(dev_path, ":", '_');
1042
1043         BT_DBG("path: %s", dev_path);
1044
1045         hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1046                                                 NULL, BT_BLUEZ_NAME,
1047                                                 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1048                                                 NULL, NULL);
1049         g_object_unref(conn);
1050
1051         if (hdp_proxy == NULL) {
1052                 BT_ERR("Failed to get the HDP server proxy\n");
1053                 g_free(dev_path);
1054                 return BLUETOOTH_ERROR_NOT_PAIRED;
1055         }
1056
1057         BT_DBG("app path %s\n", app_handle);
1058
1059         param = g_new0(bt_hdp_connected_t, 1);
1060         param->app_handle = g_strdup(app_handle);
1061         memcpy(&param->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1062         param->type = channel_type;
1063
1064         g_dbus_proxy_call(hdp_proxy, "CreateChannel",
1065                                 g_variant_new("(os)", app_handle, role),
1066                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1067                                 (GAsyncReadyCallback)__bt_hdp_connect_request_cb,
1068                                 param);
1069
1070         g_free(dev_path);
1071
1072         return BLUETOOTH_ERROR_NONE;
1073 }
1074
1075 static void __bt_hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
1076                         GAsyncResult *res, gpointer user_data)
1077 {
1078         GError *err = NULL;
1079         bt_hdp_disconnected_t *disconn_ind = user_data;
1080         bt_user_info_t *user_info;
1081         GVariant *reply = NULL;
1082
1083         reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
1084         g_object_unref(hdp_proxy);
1085
1086         user_info = _bt_get_user_data(BT_COMMON);
1087         if (user_info == NULL || user_info->cb == NULL) {
1088                 g_free(disconn_ind);
1089                 if (err) {
1090                                 g_clear_error(&err);
1091                         return;
1092                 }
1093                 g_variant_unref(reply);
1094                 return;
1095         }
1096
1097         if (!reply) {
1098                 if (err) {
1099                         BT_ERR("HDP disconnection Dbus Call Error: %s\n",
1100                                                         err->message);
1101                         g_clear_error(&err);
1102                 }
1103
1104                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1105                                 BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind,
1106                                 user_info->cb, user_info->user_data);
1107         } else {
1108                 _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED,
1109                                 BLUETOOTH_ERROR_NONE, disconn_ind,
1110                                 user_info->cb, user_info->user_data);
1111                 BT_INFO("HDP disconnection Dbus Call is done\n");
1112                 g_variant_unref(reply);
1113         }
1114
1115         g_free(disconn_ind);
1116 }
1117
1118 BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id,
1119                         const bluetooth_device_address_t *device_address)
1120 {
1121         GError *err = NULL;
1122         GDBusConnection *conn = NULL;
1123         GDBusProxy *hdp_proxy = NULL;
1124         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1125         char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 };
1126         char *dev_path = NULL;
1127         bt_hdp_disconnected_t *param;
1128
1129         BT_DBG("+\n");
1130
1131         BT_CHECK_ENABLED(return);
1132         BT_CHECK_PARAMETER(device_address, return);
1133
1134         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_DISCONNECT)
1135              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1136                 BT_ERR("Don't have a privilege to use this API");
1137                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1138         }
1139
1140         hdp_obj_info_t *info =
1141                 __bt_hdp_internal_gslist_obj_find_using_fd(channel_id);
1142         if (NULL == info) {
1143                 BT_ERR("*** Could not locate the list for %d*****\n",
1144                                                         channel_id);
1145                 return BLUETOOTH_ERROR_INVALID_PARAM;
1146         }
1147
1148         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1149
1150         if (err) {
1151                 BT_ERR("ERROR: Can't get on system bus [%s]", err->message);
1152                 g_clear_error(&err);
1153                 return BLUETOOTH_ERROR_INTERNAL;
1154         }
1155
1156         /* If the adapter path is wrong, we can think the BT is not enabled. */
1157         if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(),
1158                                         default_adapter_path) < 0) {
1159                 BT_ERR("Could not get adapter path\n");
1160                 g_object_unref(conn);
1161                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1162         }
1163
1164         _bt_convert_addr_type_to_string(address,
1165                                 (unsigned char *)device_address->addr);
1166
1167         BT_DBG("create conection to  %s\n", address);
1168
1169         dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address);
1170
1171         if (dev_path == NULL) {
1172                 g_object_unref(conn);
1173                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1174         }
1175
1176         g_strdelimit(dev_path, ":", '_');
1177
1178         BT_DBG("path  %s\n", dev_path);
1179
1180         hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1181                                                 NULL, BT_BLUEZ_NAME,
1182                                                 dev_path, BLUEZ_HDP_DEVICE_INTERFACE,
1183                                                 NULL, NULL);
1184
1185         g_object_unref(conn);
1186
1187         if (hdp_proxy == NULL) {
1188                 BT_ERR("Failed to get the HDP proxy\n");
1189                 g_free(dev_path);
1190                 return BLUETOOTH_ERROR_NOT_PAIRED;
1191         }
1192
1193         param = g_new0(bt_hdp_disconnected_t, 1);
1194         param->channel_id = channel_id;
1195         memcpy(&param->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH);
1196
1197         g_dbus_proxy_call(hdp_proxy, "DestroyChannel",
1198                                 g_variant_new("o", info->obj_channel_path),
1199                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1200                                 (GAsyncReadyCallback)__bt_hdp_disconnect_request_cb,
1201                                 param);
1202
1203         g_free(dev_path);
1204         g_free(param);
1205         g_object_unref(hdp_proxy);
1206
1207         return BLUETOOTH_ERROR_NONE;
1208
1209 }