4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Nilesh Trimbake <t.shripati@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
32 #include "bt-hal-a2dp-sink-dbus-handler.h"
33 #include "bt-hal-dbus-common-utils.h"
34 #include "bt-hal-internal.h"
37 static handle_stack_msg event_cb = NULL;
39 /* To send stack event to hal-a2dp-sink handler */
40 void _bt_hal_register_a2dp_sink_dbus_handler_cb(handle_stack_msg cb)
45 /* To send stack event to hal-a2dp-sink handler */
46 void _bt_hal_unregister_a2dp_sink_dbus_handler_cb()
51 static void __bt_a2dp_sink_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
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;
62 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
63 g_object_unref(proxy);
65 ERR("A2DP Source Connect Dbus Call Error");
67 ERR("Error: %s\n", g_error->message);
68 g_clear_error(&g_error);
70 result = BT_STATUS_FAIL;
72 g_variant_unref(reply);
74 DBG("Address: %s", address);
76 * If result is success, Send connecting event
78 if (result == BT_STATUS_SUCCESS) {
79 /* Prepare to send A2DP Source connecting event */
80 memset(&ev, 0, sizeof(ev));
81 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
82 ev.state = HAL_EV_A2DP_STATE_CONNECTING;
84 ERR("A2DP SINK DBUS handler callback not registered");
86 event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
88 /* Prepare to send A2DP Source disconnected event */
89 memset(&ev, 0, sizeof(ev));
90 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
91 ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
93 ERR("A2DP SINK DBUS handler callback not registered");
95 event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
100 bt_status_t _bt_hal_dbus_handler_a2dp_sink_connect(bt_bdaddr_t *bd_addr)
103 GDBusConnection *conn;
108 ERR("bd_addr is NULL, return");
109 return BT_STATUS_PARM_INVALID;
112 conn = _bt_hal_get_system_gconn();
114 ERR("_bt_hal_get_system_gconn returned NULL, return");
115 return BT_STATUS_FAIL;
118 address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
120 ERR("Memory allocation failed");
121 return BT_STATUS_NOMEM;
123 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
125 ret = _bt_hal_connect_profile(address, A2DP_SOURCE_UUID,
126 __bt_a2dp_sink_connect_cb, address);
128 if (ret != BT_HAL_ERROR_NONE) {
129 ERR("_bt_hal_connect_profile(A2DP source) Error");
131 return BT_STATUS_FAIL;
134 return BT_STATUS_SUCCESS;
137 static void __bt_a2dp_source_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
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;
148 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
149 g_object_unref(proxy);
151 ERR("A2DP Source Disconnect Dbus Call Error");
153 ERR("Error: %s\n", g_error->message);
154 g_clear_error(&g_error);
156 result = BT_STATUS_FAIL;
158 g_variant_unref(reply);
160 if (result != BT_STATUS_FAIL)
161 DBG("A2DP Source Disconnect successful for Device: %s", address);
163 DBG("A2DP Source Disconnect un-successful for Device: %s", address);
164 if (result == BT_STATUS_FAIL) {
165 /* Prepare to send AV source disconnected state 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;
170 ERR("A2DP SINK DBUS handler callback not registered");
172 event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
174 /* Prepare to send AV source disconnecting state 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;
179 ERR("A2DP SINK DBUS handler callback not registered");
181 event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
187 bt_status_t _bt_hal_dbus_handler_a2dp_sink_disconnect(bt_bdaddr_t *bd_addr)
190 GDBusConnection *conn;
195 ERR("bd_addr is NULL, return");
196 return BT_STATUS_PARM_INVALID;
199 conn = _bt_hal_get_system_gconn();
201 ERR("_bt_hal_get_system_gconn returned NULL, return");
202 return BT_STATUS_FAIL;
205 address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
207 ERR("Memory allocation failed");
208 return BT_STATUS_NOMEM;
210 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
212 ret = _bt_hal_disconnect_profile(address, A2DP_SOURCE_UUID,
213 __bt_a2dp_source_disconnect_cb, address);
215 if (ret != BT_HAL_ERROR_NONE) {
216 ERR("_bt_hal_connect_profile(AV) Error");
217 return BT_STATUS_FAIL;
220 return BT_STATUS_SUCCESS;
223 bt_status_t _bt_hal_dbus_handler_enable_a2dp_sink(void)
227 GError *error = NULL;
229 GDBusConnection *gconn;
233 if (_bt_hal_is_service_enabled(A2DP_SINK_UUID)) {
234 ERR("Audio sink role already enabled, return");
235 return BT_STATUS_SUCCESS;
238 gconn = _bt_hal_get_system_gconn();
240 ERR("_bt_hal_get_system_gconn returned NULL, return");
241 return BT_STATUS_FAIL;
244 adapter_path = _bt_hal_get_adapter_path();
246 ERR("adapter_path is NULL");
247 return BT_STATUS_FAIL;
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);
254 ERR("Unable to create proxy");
257 ERR("Error: %s", error->message);
258 g_clear_error(&error);
260 return BT_STATUS_FAIL;
263 ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "sink"),
264 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
265 g_object_unref(proxy);
267 ERR("Call SelectRole Failed");
269 g_dbus_error_strip_remote_error(error);
271 ERR("message[%s]", error->message);
273 /* Add the exception case for Already Exists */
274 if (g_strrstr(error->message, "Already Exists")) {
275 g_clear_error(&error);
276 return BT_STATUS_SUCCESS;
279 g_clear_error(&error);
281 return BT_STATUS_FAIL;
284 g_variant_unref(ret);
286 return BT_STATUS_SUCCESS;