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