91e41e5e5b4579eaf57a1d0c44a46bf6afc826fa
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-av-dbus-handler.c
1 /*
2  * BLUETOOTH HAL
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <dlog.h>
30 #include <vconf.h>
31
32 #include "bt-hal-av-dbus-handler.h"
33 #include "bt-hal-dbus-common-utils.h"
34 #include "bt-hal-internal.h"
35
36
37 static handle_stack_msg event_cb = NULL;
38
39 /* To send stack event to hal-av handler */
40 void _bt_hal_register_av_dbus_handler_cb(handle_stack_msg cb)
41 {
42         event_cb = cb;
43 }
44
45 /* To send stack event to hal-av handler */
46 void _bt_hal_unregister_av_dbus_handler_cb()
47 {
48         event_cb = NULL;
49 }
50
51 static void __bt_av_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
52                 gpointer user_data)
53 {
54         GError *g_error = NULL;
55         struct hal_ev_a2dp_conn_state ev;
56         GVariant *reply = NULL;
57         char *address = user_data;
58         int result = BT_STATUS_SUCCESS;
59
60         DBG("+");
61
62         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
63         g_object_unref(proxy);
64         if (reply == NULL) {
65                 ERR("A2DP Connect Dbus Call Error");
66                 if (g_error) {
67                         ERR("Error: %s\n", g_error->message);
68                         g_clear_error(&g_error);
69                 }
70                 result = BT_STATUS_FAIL;
71         }
72         g_variant_unref(reply);
73
74         DBG("Address: %s", address);
75         /*
76          * If result is success, AV Connecting event will be triggered
77          * from here.
78          */
79         if (result == BT_STATUS_SUCCESS) {
80                 /* Prepare to send AV connecting event */
81                 memset(&ev, 0, sizeof(ev));
82                 ev.state = HAL_EV_A2DP_STATE_CONNECTING;
83                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
84                 if (!event_cb)
85                         ERR("A2DP dbus handler callback not registered");
86                 else
87                         event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
88         } else {
89                 /* Prepare to send AV disconnected event */
90                 memset(&ev, 0, sizeof(ev));
91                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
92                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
93                 if (!event_cb)
94                         ERR("HF DBUS handler callback not registered");
95                 else
96                         event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
97         }
98
99         g_free(address);
100 }
101
102 bt_status_t _bt_hal_dbus_handler_av_connect(bt_bdaddr_t *bd_addr)
103 {
104         char *address;
105         GDBusConnection *conn;
106         int ret;
107
108         if (!bd_addr) {
109                 ERR("bd_addr is NULL, return");
110                 return BT_STATUS_PARM_INVALID;
111         }
112
113         conn = _bt_hal_get_system_gconn();
114         if (!conn) {
115                 ERR("_bt_hal_get_system_gconn returned NULL, return");
116                 return BT_STATUS_FAIL;
117         }
118
119         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
120         if (!address) {
121                 ERR("Memory allocation failed");
122                 return BT_STATUS_NOMEM;
123         }
124         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
125
126         ret = _bt_hal_connect_profile(address, A2DP_SINK_UUID,
127                         __bt_av_connect_cb, address);
128
129         if (ret != BT_HAL_ERROR_NONE) {
130                 ERR("_bt_hal_connect_profile(A2DP) Error");
131                 return BT_STATUS_FAIL;
132         }
133         return BT_STATUS_SUCCESS;
134 }
135
136 static void __bt_av_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
137                 gpointer user_data)
138 {
139         GError *g_error = NULL;
140         struct hal_ev_a2dp_conn_state ev;
141         GVariant *reply = NULL;
142         char *address = user_data;
143         int result = BT_STATUS_SUCCESS;
144
145         DBG("+");
146
147         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
148         g_object_unref(proxy);
149         if (reply == NULL) {
150                 ERR("A2DP Disconnect Dbus Call Error");
151                 if (g_error) {
152                         ERR("Error: %s\n", g_error->message);
153                         g_clear_error(&g_error);
154                 }
155                 result = BT_STATUS_FAIL;
156         }
157         g_variant_unref(reply);
158
159         if (result != BT_STATUS_FAIL)
160                 DBG("A2DP Disconnect successful for Device: %s", address);
161         else
162                 DBG("A2DP Disconnect un-successful for Device: %s", address);
163
164         if (result == BT_STATUS_FAIL) {
165                 /* Prepare to send AV Disconnected event */
166                 memset(&ev, 0, sizeof(ev));
167                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
168                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
169                 if (!event_cb)
170                         ERR("HF DBUS handler callback not registered");
171                 else
172                         event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
173         } else {
174                 /* Prepare to send AV Disconnecting event */
175                 memset(&ev, 0, sizeof(ev));
176                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
177                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTING;
178                 if (!event_cb)
179                         ERR("HF DBUS handler callback not registered");
180                 else
181                         event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
182         }
183         g_free(address);
184         DBG("-");
185 }
186
187 bt_status_t _bt_hal_dbus_handler_av_disconnect(bt_bdaddr_t *bd_addr)
188 {
189         char *address;
190         GDBusConnection *conn;
191         int ret;
192
193         if (!bd_addr) {
194                 ERR("bd_addr is NULL, return");
195                 return BT_STATUS_PARM_INVALID;
196         }
197
198         conn = _bt_hal_get_system_gconn();
199         if (!conn) {
200                 ERR("_bt_hal_get_system_gconn returned NULL, return");
201                 return BT_STATUS_FAIL;
202         }
203
204         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
205         if (!address) {
206                 ERR("Memory allocation failed");
207                 return BT_STATUS_NOMEM;
208         }
209         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
210
211         ret = _bt_hal_disconnect_profile(address, A2DP_SINK_UUID,
212                         __bt_av_disconnect_cb, address);
213
214         if (ret != BT_HAL_ERROR_NONE) {
215                 ERR("_bt_hal_connect_profile(AV) Error");
216                 return BT_STATUS_FAIL;
217         }
218
219         return BT_STATUS_SUCCESS;
220 }
221
222 bt_status_t _bt_hal_dbus_handler_enable_a2dp_source(void)
223 {
224         GDBusProxy *proxy;
225         GVariant *ret;
226         GError *error = NULL;
227         gchar *adapter_path;
228         GDBusConnection *gconn;
229
230         DBG("+");
231
232         if (_bt_hal_is_service_enabled(A2DP_SOURCE_UUID)) {
233                 ERR("Audio sink role already enabled, return");
234                 return BT_STATUS_SUCCESS;
235         }
236
237         gconn = _bt_hal_get_system_gconn();
238         if (!gconn) {
239                 ERR("_bt_hal_get_system_gconn returned NULL, return");
240                 return BT_STATUS_FAIL;
241         }
242
243         adapter_path = _bt_hal_get_adapter_path();
244         if (!adapter_path) {
245                 ERR("adapter_path is NULL");
246                 return BT_STATUS_FAIL;
247         }
248
249         proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE, NULL,
250                         BT_HAL_BLUEZ_NAME, adapter_path, BT_HAL_MEDIA_INTERFACE, NULL, &error);
251         g_free(adapter_path);
252         if (proxy == NULL) {
253                 ERR("Unable to create proxy");
254
255                 if (error) {
256                         ERR("Error: %s", error->message);
257                         g_clear_error(&error);
258                 }
259                 return BT_STATUS_FAIL;
260         }
261
262         ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "source"),
263                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
264         g_object_unref(proxy);
265         if (ret == NULL) {
266                 ERR("Call SelectRole Failed");
267                 if (error) {
268                         ERR("errCode[%x], message[%s]", error->code, error->message);
269                         g_clear_error(&error);
270                 }
271                 return BT_STATUS_FAIL;
272         }
273
274         g_variant_unref(ret);
275         DBG("-");
276         return BT_STATUS_SUCCESS;
277 }