Coverity Fixes in BTAPI and BTHAL
[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                 g_free(address);
132                 return BT_STATUS_FAIL;
133         }
134         return BT_STATUS_SUCCESS;
135 }
136
137 static void __bt_av_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
138                 gpointer user_data)
139 {
140         GError *g_error = NULL;
141         struct hal_ev_a2dp_conn_state ev;
142         GVariant *reply = NULL;
143         char *address = user_data;
144         int result = BT_STATUS_SUCCESS;
145
146         DBG("+");
147
148         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
149         g_object_unref(proxy);
150         if (reply == NULL) {
151                 ERR("A2DP Disconnect Dbus Call Error");
152                 if (g_error) {
153                         ERR("Error: %s\n", g_error->message);
154                         g_clear_error(&g_error);
155                 }
156                 result = BT_STATUS_FAIL;
157         }
158         g_variant_unref(reply);
159
160         if (result != BT_STATUS_FAIL)
161                 DBG("A2DP Disconnect successful for Device: %s", address);
162         else
163                 DBG("A2DP Disconnect un-successful for Device: %s", address);
164
165         if (result == BT_STATUS_FAIL) {
166                 /* Prepare to send AV Disconnected event */
167                 memset(&ev, 0, sizeof(ev));
168                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
169                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
170                 if (!event_cb)
171                         ERR("HF DBUS handler callback not registered");
172                 else
173                         event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
174         } else {
175                 /* Prepare to send AV Disconnecting event */
176                 memset(&ev, 0, sizeof(ev));
177                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
178                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTING;
179                 if (!event_cb)
180                         ERR("HF DBUS handler callback not registered");
181                 else
182                         event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
183         }
184         g_free(address);
185         DBG("-");
186 }
187
188 bt_status_t _bt_hal_dbus_handler_av_disconnect(bt_bdaddr_t *bd_addr)
189 {
190         char *address;
191         GDBusConnection *conn;
192         int ret;
193
194         if (!bd_addr) {
195                 ERR("bd_addr is NULL, return");
196                 return BT_STATUS_PARM_INVALID;
197         }
198
199         conn = _bt_hal_get_system_gconn();
200         if (!conn) {
201                 ERR("_bt_hal_get_system_gconn returned NULL, return");
202                 return BT_STATUS_FAIL;
203         }
204
205         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
206         if (!address) {
207                 ERR("Memory allocation failed");
208                 return BT_STATUS_NOMEM;
209         }
210         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
211
212         ret = _bt_hal_disconnect_profile(address, A2DP_SINK_UUID,
213                         __bt_av_disconnect_cb, address);
214
215         if (ret != BT_HAL_ERROR_NONE) {
216                 ERR("_bt_hal_connect_profile(AV) Error");
217                 return BT_STATUS_FAIL;
218         }
219
220         return BT_STATUS_SUCCESS;
221 }
222
223 bt_status_t _bt_hal_dbus_handler_enable_a2dp_source(void)
224 {
225         GDBusProxy *proxy;
226         GVariant *ret;
227         GError *error = NULL;
228         gchar *adapter_path;
229         GDBusConnection *gconn;
230
231         DBG("+");
232
233         if (_bt_hal_is_service_enabled(A2DP_SOURCE_UUID)) {
234                 ERR("Audio sink role already enabled, return");
235                 return BT_STATUS_SUCCESS;
236         }
237
238         gconn = _bt_hal_get_system_gconn();
239         if (!gconn) {
240                 ERR("_bt_hal_get_system_gconn returned NULL, return");
241                 return BT_STATUS_FAIL;
242         }
243
244         adapter_path = _bt_hal_get_adapter_path();
245         if (!adapter_path) {
246                 ERR("adapter_path is NULL");
247                 return BT_STATUS_FAIL;
248         }
249
250         proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE, NULL,
251                         BT_HAL_BLUEZ_NAME, adapter_path, BT_HAL_MEDIA_INTERFACE, NULL, &error);
252         g_free(adapter_path);
253         if (proxy == NULL) {
254                 ERR("Unable to create proxy");
255
256                 if (error) {
257                         ERR("Error: %s", error->message);
258                         g_clear_error(&error);
259                 }
260                 return BT_STATUS_FAIL;
261         }
262
263         ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "source"),
264                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
265         g_object_unref(proxy);
266         if (ret == NULL) {
267                 ERR("Call SelectRole Failed");
268                 if (error) {
269                         ERR("errCode[%x], message[%s]", error->code, error->message);
270                         g_clear_error(&error);
271                 }
272                 return BT_STATUS_FAIL;
273         }
274
275         g_variant_unref(ret);
276         DBG("-");
277         return BT_STATUS_SUCCESS;
278 }