9bc19d1992e306a5c7e261c336a1f55f4a79534f
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-avrcp-ctrl-dbus-handler.c
1 /*
2  *
3  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
4  *
5  * Contact: Nilesh Trimbake <t.shripati@samsung.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *              http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include <string.h>
25
26 #include <glib.h>
27 #include <gio/gio.h>
28 #include <dlog.h>
29 #include <vconf.h>
30
31 #include "bt-hal-avrcp-ctrl-dbus-handler.h"
32 #include "bt-hal-dbus-common-utils.h"
33 #include "bt-hal-internal.h"
34
35 static bt_player_settinngs_t repeat_status[] = {
36         { REPEAT_MODE_OFF, "off" },
37         { REPEAT_SINGLE_TRACK, "singletrack" },
38         { REPEAT_ALL_TRACK, "alltracks" },
39         { REPEAT_GROUP, "group" },
40         { REPEAT_INVALID, "" }
41 };
42
43 static bt_player_settinngs_t equalizer_status[] = {
44         { EQUALIZER_OFF, "off" },
45         { EQUALIZER_ON, "on" },
46         { EQUALIZER_INVALID, "" },
47 };
48
49 static bt_player_settinngs_t scan_status[] = {
50         { SCAN_MODE_OFF, "off" },
51         { SCAN_ALL_TRACK, "alltracks" },
52         { SCAN_GROUP, "group" },
53         { SCAN_INVALID, "" },
54 };
55
56 static bt_player_settinngs_t shuffle_settings[] = {
57         { SHUFFLE_MODE_OFF, "off" },
58         { SHUFFLE_ALL_TRACK, "alltracks" },
59         { SHUFFLE_GROUP, "group" },
60         { SHUFFLE_INVALID, "" }
61 };
62
63 static handle_stack_msg event_cb = NULL;
64
65 /* To send stack event to hal-avrcp-ctrl handler */
66 void _bt_hal_register_avrcp_ctrl_dbus_handler_cb(handle_stack_msg cb)
67 {
68         event_cb = cb;
69 }
70
71 /* To send stack event to hal-avrcp-ctrl handler */
72 void _bt_hal_unregister_avrcp_ctrl_dbus_handler_cb()
73 {
74         event_cb = NULL;
75 }
76
77 static void __bt_avrcp_target_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
78                 gpointer user_data)
79 {
80         struct hal_ev_avrcp_ctrl_conn_state ev;
81         char *address = user_data;
82         int result = BT_STATUS_SUCCESS;
83         GVariant *reply = NULL;
84         GError *g_error = NULL;
85
86         DBG("+");
87
88         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
89         g_object_unref(proxy);
90         if (reply == NULL) {
91                 ERR("AVRCP Target Connect Dbus Call Error");
92                 if (g_error) {
93                         ERR("Error: %s\n", g_error->message);
94                         g_clear_error(&g_error);
95                 }
96                 result = BT_STATUS_FAIL;
97         }
98         g_variant_unref(reply);
99
100         DBG("Address: %s", address);
101         /*
102          * If result is success, Remote device connected event will be triggered
103          * automatically from stack, so return from here.
104          */
105         if (result == BT_STATUS_SUCCESS)
106                 goto done;
107
108         /* Prepare to send AVRCP Target connection state event */
109         memset(&ev, 0, sizeof(ev));
110         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
111         ev.state = HAL_AVRCP_CTRL_STATE_DISCONNECTED;
112         if (!event_cb)
113                 ERR("AVRCP CTRL DBUS handler callback not registered");
114         else
115                 event_cb(HAL_EV_AVRCP_CTRL_CONN_STATE, (void *)&ev, sizeof(ev));
116
117 done:
118         g_free(address);
119 }
120
121 bt_status_t _bt_hal_dbus_handler_avrcp_ctrl_connect(bt_bdaddr_t *bd_addr)
122 {
123         char *address;
124         int ret;
125         GDBusConnection *conn;
126
127         if (!bd_addr) {
128                 ERR("bd_addr is NULL, return");
129                 return BT_STATUS_PARM_INVALID;
130         }
131
132         conn = _bt_hal_get_system_gconn();
133         if (!conn) {
134                 ERR("_bt_hal_get_system_gconn returned NULL, return");
135                 return BT_STATUS_FAIL;
136         }
137
138         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
139         if (!address) {
140                 ERR("Memory allocation failed");
141                 return BT_STATUS_NOMEM;
142         }
143         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
144
145         ret = _bt_hal_connect_profile(address, AVRCP_TARGET_UUID,
146                         __bt_avrcp_target_connect_cb, address);
147
148         if (ret != BT_HAL_ERROR_NONE) {
149                 ERR("_bt_hal_connect_profile(AVRCP Target) Error");
150                 g_free(address);
151                 return BT_STATUS_FAIL;
152         }
153
154         return BT_STATUS_SUCCESS;
155 }
156
157 static void __bt_avrcp_target_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
158                 gpointer user_data)
159 {
160         struct hal_ev_avrcp_ctrl_conn_state ev;
161         char *address = user_data;
162         int result = BT_STATUS_SUCCESS;
163         GError *g_error = NULL;
164         GVariant *reply = NULL;
165
166         DBG("+");
167
168         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
169         g_object_unref(proxy);
170         if (reply == NULL) {
171                 ERR("AVRCP Target Disconnect Dbus Call Error");
172                 if (g_error) {
173                         ERR("Error: %s\n", g_error->message);
174                         g_clear_error(&g_error);
175                 }
176                 result = BT_STATUS_FAIL;
177         }
178         g_variant_unref(reply);
179
180         if (result != BT_STATUS_FAIL) {
181                 DBG("AVRCP Target Disconnect successful for Device: %s", address);
182                 g_free(address);
183                 return;
184         } else {
185                 DBG("AVRCP Target Disconnect un-successful for Device: %s", address);
186         }
187
188         /*
189          * Prepare to send AVRCP Target connection state event indicating
190          * disconnection failed.
191          */
192         memset(&ev, 0, sizeof(ev));
193         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
194         ev.state = HAL_AVRCP_CTRL_STATE_CONNECTED;
195         if (!event_cb)
196                 ERR("AVRCP Target DBUS handler callback not registered");
197         else
198                 event_cb(HAL_EV_AVRCP_CTRL_CONN_STATE, (void *)&ev, sizeof(ev));
199         g_free(address);
200         DBG("-");
201 }
202
203 bt_status_t _bt_hal_dbus_handler_avrcp_ctrl_disconnect(bt_bdaddr_t *bd_addr)
204 {
205         char *address;
206         int ret;
207         GDBusConnection *conn;
208
209         if (!bd_addr) {
210                 ERR("bd_addr is NULL, return");
211                 return BT_STATUS_PARM_INVALID;
212         }
213
214         conn = _bt_hal_get_system_gconn();
215         if (!conn) {
216                 ERR("_bt_hal_get_system_gconn returned NULL, return");
217                 return BT_STATUS_FAIL;
218         }
219
220         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
221         if (!address) {
222                 ERR("Memory allocation failed");
223                 return BT_STATUS_NOMEM;
224         }
225         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
226
227         ret = _bt_hal_disconnect_profile(address, AVRCP_TARGET_UUID,
228                         __bt_avrcp_target_disconnect_cb, address);
229
230         if (ret != BT_HAL_ERROR_NONE) {
231                 ERR("_bt_hal_connect_profile(AVRCP Target) Error");
232                 g_free(address);
233                 return BT_STATUS_FAIL;
234         }
235
236         return BT_STATUS_SUCCESS;
237 }
238
239 static int __bt_media_send_control_msg(bt_bdaddr_t *bd_addr, const char *name)
240 {
241         GVariant *reply = NULL;
242         GError *err = NULL;
243         GDBusProxy *proxy = NULL;
244
245         if (name == NULL) {
246                 ERR("Command is NULL");
247                 return BT_STATUS_FAIL;
248         }
249         DBG("Command [%s]", name);
250         proxy = _bt_hal_get_avrcp_ctrl_proxy(bd_addr);
251         if (proxy == NULL) {
252                 ERR("Unable to allocate new proxy \n");
253                 if (err) {
254                         ERR("%s", err->message);
255                         g_clear_error(&err);
256                 }
257                 return BT_STATUS_FAIL;
258         }
259         reply = g_dbus_proxy_call_sync(proxy, name, NULL,
260                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
261
262         if (!reply) {
263                 ERR("Error returned in method call");
264                 if (err) {
265                         ERR("%s", err->message);
266                         g_clear_error(&err);
267                 }
268                 return BT_STATUS_FAIL;
269         }
270         g_variant_unref(reply);
271         DBG("-");
272         return BT_STATUS_SUCCESS;
273 }
274
275 bt_status_t _bt_hal_dbus_handler_avrcp_ctrl_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
276 {       int ret;
277         DBG("+");
278
279         switch (key_code) {
280                 case PLAY: {
281                         ret = __bt_media_send_control_msg(bd_addr, "Play");
282                         break;
283                 }
284                 case PAUSE: {
285                         ret = __bt_media_send_control_msg(bd_addr, "Pause");
286                         break;
287                 }
288                 case STOP: {
289                         ret = __bt_media_send_control_msg(bd_addr, "Stop");
290                         break;
291                 }
292                 case NEXT: {
293                         ret = __bt_media_send_control_msg(bd_addr, "Next");
294                         break;
295                 }
296                 case PREVIOUS: {
297                         ret = __bt_media_send_control_msg(bd_addr, "Previous");
298                         break;
299                 }
300                 case PRESS_FAST_FORWARD: {
301                         ret = __bt_media_send_control_msg(bd_addr, "PressFastForward");
302                         break;
303                 }
304                 case RELEASE_FAST_FORWARD: {
305                         ret = __bt_media_send_control_msg(bd_addr, "ReleaseFastForward");
306                         break;
307                 }
308                 case PRESS_REWIND: {
309                         ret = __bt_media_send_control_msg(bd_addr, "PressRewind");
310                         break;
311                 }
312                 case RELEASE_REWIND: {
313                         ret = __bt_media_send_control_msg(bd_addr, "ReleaseRewind");
314                         break;
315                 }
316                 default: {
317                         DBG("Invalid Type\n");
318                         return BT_STATUS_FAIL;
319                 }
320         }
321         DBG("-");
322         return ret;
323 }
324 static const char *__bt_media_type_to_str(int type)
325 {
326         switch (type) {
327         case BTRC_PLAYER_ATTR_EQUALIZER:
328                 return "Equalizer";
329         case BTRC_PLAYER_ATTR_REPEAT:
330                 return "Repeat";
331         case BTRC_PLAYER_ATTR_SHUFFLE:
332                 return "Shuffle";
333         case BTRC_PLAYER_ATTR_SCAN:
334                 return "Scan";
335         default:
336                 return NULL;
337         }
338
339         return NULL;
340 }
341
342 static const char *__bt_transport_type_to_str(int type)
343 {
344         switch (type) {
345         case BTRC_TRANSPORT_ATTR_DELAY:
346                 return "Delay";
347         case BTRC_TRANSPORT_ATTR_VOLUME:
348                 return "Volume";
349         default:
350                 return NULL;
351         }
352
353         return NULL;
354 }
355
356 bt_status_t _bt_hal_dbus_handler_avrcp_ctrl_set_property(bt_bdaddr_t *bd_addr, uint8_t type, uint8_t value)
357 {
358         GVariant *reply, *param = NULL;
359         GError *err = NULL;
360         GDBusProxy *proxy = NULL;
361
362         DBG("+");
363         switch (type) {
364         case BTRC_PLAYER_ATTR_EQUALIZER:
365                 param = g_variant_new("s", equalizer_status[value].property);
366                 INFO("equalizer_status %s", equalizer_status[value].property);
367                 break;
368         case BTRC_PLAYER_ATTR_REPEAT:
369                 param = g_variant_new("s", repeat_status[value].property);
370                 INFO("repeat_status %s", repeat_status[value].property);
371                 break;
372         case BTRC_PLAYER_ATTR_SHUFFLE:
373                 param = g_variant_new("s", shuffle_settings[value].property);
374                 INFO("shuffle_settings %s", shuffle_settings[value].property);
375                 break;
376         case BTRC_PLAYER_ATTR_SCAN:
377                 param = g_variant_new("s", scan_status[value].property);
378                 INFO("scan_status %s", scan_status[value].property);
379                 break;
380         default:
381                 ERR("Invalid property type: %d", type);
382                 return BT_STATUS_FAIL;
383         }
384
385         proxy = _bt_hal_get_avrcp_ctrl_properties_proxy(bd_addr);
386         if (proxy == NULL) {
387                 ERR("Unable to allocate new proxy \n");
388                 if (err) {
389                         ERR("%s", err->message);
390                         g_clear_error(&err);
391                 }
392                 return BT_STATUS_FAIL;
393         }
394
395         reply = g_dbus_proxy_call_sync(proxy,
396                         "Set", g_variant_new("(ssv)",
397                                 BT_HAL_PLAYER_CONTROL_INTERFACE,
398                                 __bt_media_type_to_str(type), param),
399                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
400         g_object_unref(proxy);
401         if (!reply) {
402                 ERR("Can't get managed objects");
403                 if (err) {
404                         ERR("SetProperty Fail: %s", err->message);
405                         g_clear_error(&err);
406                         return BT_STATUS_FAIL;
407                 }
408         }
409
410         g_variant_unref(reply);
411         DBG("-");
412         return BT_STATUS_SUCCESS;
413 }
414
415 bt_status_t _bt_hal_dbus_handler_avrcp_transport_set_property(bt_bdaddr_t *bd_addr, int type, unsigned int value)
416 {
417         GVariant *reply, *param = NULL;
418         GError *err = NULL;
419         GDBusProxy *proxy = NULL;
420         uint16_t property_level = (uint16_t)value;
421
422         DBG("+");
423         switch (type) {
424         case BTRC_TRANSPORT_ATTR_DELAY:
425                 param = g_variant_new("q", property_level);
426                 INFO("delay level %d", property_level);
427                 break;
428         case BTRC_TRANSPORT_ATTR_VOLUME:
429                 param = g_variant_new("q", property_level);
430                 INFO("volume level %d", property_level);
431                 break;
432         default:
433                 ERR("Invalid property type: %d", type);
434                 return BT_STATUS_FAIL;
435         }
436
437         proxy = _bt_hal_get_avrcp_transport_properties_proxy(bd_addr);
438         if (proxy == NULL) {
439                 ERR("Unable to allocate new proxy \n");
440                 if (err) {
441                         ERR("%s", err->message);
442                         g_clear_error(&err);
443                 }
444                 return BT_STATUS_FAIL;
445         }
446
447         reply = g_dbus_proxy_call_sync(proxy,
448                         "Set", g_variant_new("(ssv)",
449                                 BT_HAL_MEDIATRANSPORT_INTERFACE,
450                                 __bt_media_type_to_str(type), param),
451                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
452         g_object_unref(proxy);
453         if (!reply) {
454                 ERR("Can't get managed objects");
455                 if (err) {
456                         ERR("SetProperty Fail: %s", err->message);
457                         g_clear_error(&err);
458                         return BT_STATUS_FAIL;
459                 }
460         }
461
462         g_variant_unref(reply);
463         DBG("-");
464         return BT_STATUS_SUCCESS;
465 }