ce46fb4787f7b8b6281d0b454a81d59e2ef6f374
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-avrcp-tg.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Atul Kumar Rai <a.rai@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 <stdbool.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <dlog.h>
27
28 #include "bt-hal.h"
29 #include "bt-hal-log.h"
30 #include "bt-hal-msg.h"
31 #include "bt-hal-utils.h"
32
33 #include "bt-hal-event-receiver.h"
34 #include "bt-hal-avrcp-tg-dbus-handler.h"
35 #include "bt-hal-avrcp-transport-dbus-handler.h"
36
37 static const btrc_callbacks_t *bt_hal_avrcp_tg_cbacks;
38
39 static bool interface_ready(void)
40 {
41         return bt_hal_avrcp_tg_cbacks != NULL;
42 }
43
44 bt_status_t get_play_status_rsp(bt_bdaddr_t *bd_addr, btrc_play_status_t play_status,
45                         uint32_t song_len, uint32_t song_pos)
46 {
47         return BT_STATUS_UNSUPPORTED;
48 }
49
50 bt_status_t list_player_app_attr_rsp(bt_bdaddr_t *bd_addr, int num_attr,
51                         btrc_player_attr_t *p_attrs)
52 {
53         return BT_STATUS_UNSUPPORTED;
54 }
55
56 bt_status_t list_player_app_value_rsp(bt_bdaddr_t *bd_addr, int num_val, uint8_t *p_vals)
57 {
58         return BT_STATUS_UNSUPPORTED;
59 }
60
61 bt_status_t get_player_app_value_rsp(bt_bdaddr_t *bd_addr, btrc_player_settings_t *p_vals)
62 {
63         return BT_STATUS_UNSUPPORTED;
64 }
65
66 bt_status_t get_player_app_attr_text_rsp(bt_bdaddr_t *bd_addr, int num_attr,
67                 btrc_player_setting_text_t *p_attrs)
68 {
69         return BT_STATUS_UNSUPPORTED;
70 }
71
72 bt_status_t get_player_app_value_text_rsp(bt_bdaddr_t *bd_addr, int num_val,
73                 btrc_player_setting_text_t *p_vals)
74 {
75         return BT_STATUS_UNSUPPORTED;
76 }
77
78 bt_status_t get_element_attr_rsp(bt_bdaddr_t *bd_addr, uint8_t num_attr,
79                 btrc_element_attr_val_t *p_attrs)
80 {
81         if (num_attr > 0 && !p_attrs)
82                 return BT_STATUS_PARM_INVALID;
83
84         return _bt_hal_dbus_handler_avrcp_tg_set_track_info(num_attr, p_attrs);
85 }
86
87 bt_status_t set_player_app_value_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
88 {
89         return BT_STATUS_UNSUPPORTED;
90 }
91
92 gboolean __fetch_track_info(gpointer data)
93 {
94         if (bt_hal_avrcp_tg_cbacks->get_element_attr_cb) {
95                 uint8_t num_attr;
96                 btrc_media_attr_t attrs[] = {
97                         BTRC_MEDIA_ATTR_TITLE, BTRC_MEDIA_ATTR_ARTIST,
98                         BTRC_MEDIA_ATTR_ALBUM, BTRC_MEDIA_ATTR_TRACK_NUM,
99                         BTRC_MEDIA_ATTR_NUM_TRACKS, BTRC_MEDIA_ATTR_GENRE,
100                         BTRC_MEDIA_ATTR_PLAYING_TIME};
101
102                 num_attr = sizeof(attrs) / sizeof(btrc_media_attr_t);
103
104                 bt_hal_avrcp_tg_cbacks->get_element_attr_cb(num_attr, attrs, NULL);
105         }
106
107         return FALSE;
108 }
109
110 bt_status_t register_notification_rsp(btrc_event_id_t event_id,
111                 btrc_notification_type_t type,
112                 btrc_register_notification_t *p_param)
113 {
114         if (BTRC_NOTIFICATION_TYPE_INTERIM == type)
115                 return BT_STATUS_SUCCESS;
116
117         switch (event_id) {
118         case BTRC_EVT_PLAY_STATUS_CHANGED:
119                 _bt_hal_dbus_handler_avrcp_tg_play_status_changed(p_param->play_status);
120                 break;
121         case BTRC_EVT_TRACK_CHANGE:
122                 g_idle_add(__fetch_track_info, NULL);
123                 break;
124         case BTRC_EVT_PLAY_POS_CHANGED:
125                 _bt_hal_dbus_handler_avrcp_tg_play_pos_changed(p_param->song_pos);
126                 break;
127         case BTRC_EVT_APP_SETTINGS_CHANGED:
128                 _bt_hal_dbus_handler_avrcp_tg_app_setting_changed(&(p_param->player_setting));
129                 break;
130         default:
131                 ERR("Unknown event Id: %d", event_id);
132         }
133
134         return BT_STATUS_SUCCESS;
135 }
136
137 bt_status_t set_volume(bt_bdaddr_t *bd_addr, uint32_t volume)
138 {
139         int ret = BT_STATUS_SUCCESS;
140
141         ret = _bt_hal_dbus_handler_avrcp_transport_set_property(bd_addr, BTRC_TRANSPORT_ATTR_VOLUME, volume);
142
143         return ret;
144 }
145
146 bt_status_t get_volume(bt_bdaddr_t *bd_addr, uint32_t *volume)
147 {
148         int ret = BT_STATUS_SUCCESS;
149
150         ret = _bt_hal_dbus_handler_avrcp_transport_get_property(bd_addr, BTRC_TRANSPORT_ATTR_VOLUME, volume);
151
152         return ret;
153 }
154
155 bt_status_t set_addressed_player_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
156 {
157         return BT_STATUS_UNSUPPORTED;
158 }
159
160 bt_status_t set_browsed_player_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
161                 uint32_t num_items, uint16_t charset_id, uint8_t folder_depth,
162                 btrc_br_folder_name_t *p_folders)
163 {
164         return BT_STATUS_UNSUPPORTED;
165 }
166
167 bt_status_t get_folder_items_list_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
168                 uint16_t uid_counter, uint8_t num_items, btrc_folder_items_t *p_items)
169 {
170         return BT_STATUS_UNSUPPORTED;
171 }
172
173 bt_status_t change_path_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
174                 uint32_t num_items)
175 {
176         return BT_STATUS_UNSUPPORTED;
177 }
178
179 bt_status_t get_item_attr_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
180                 uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
181 {
182         return BT_STATUS_UNSUPPORTED;
183 }
184
185 bt_status_t play_item_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
186 {
187         return BT_STATUS_UNSUPPORTED;
188 }
189
190 bt_status_t get_total_num_of_items_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status,
191                 uint32_t uid_counter, uint32_t num_items)
192 {
193         return BT_STATUS_UNSUPPORTED;
194 }
195
196 bt_status_t search_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, uint32_t uid_counter,
197                 uint32_t num_items)
198 {
199         return BT_STATUS_UNSUPPORTED;
200 }
201
202 bt_status_t add_to_now_playing_rsp(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status)
203 {
204         return BT_STATUS_UNSUPPORTED;
205 }
206
207 static gboolean __bt_avrcp_register_notifications(gpointer user_data)
208 {
209         bt_bdaddr_t *bdaddr = user_data;
210
211         if (!bt_hal_avrcp_tg_cbacks->register_notification_cb)
212                 return FALSE;
213
214         bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_PLAY_STATUS_CHANGED, 0, bdaddr);
215         bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_TRACK_CHANGE, 0, bdaddr);
216         bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_PLAY_POS_CHANGED, 1, bdaddr);
217         bt_hal_avrcp_tg_cbacks->register_notification_cb(BTRC_EVT_APP_SETTINGS_CHANGED, 0, bdaddr);
218
219         return FALSE;
220 }
221
222 static void __handle_player_property(void *buf, uint16_t len)
223 {
224         btrc_player_settings_t player_setting;
225         struct hal_ev_avrcp_tg_player_property *ev = buf;
226
227         if (!bt_hal_avrcp_tg_cbacks->set_player_app_value_cb)
228                 return;
229
230         memset(&player_setting, 0, sizeof(btrc_player_settings_t));
231         player_setting.num_attr = 1;
232
233         switch (ev->prop_type) {
234         case HAL_AVRCP_TG_PLAYER_PROP_REPEAT:
235                 player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_REPEAT;
236                 player_setting.attr_values[0] = ev->value;
237                 break;
238         case HAL_AVRCP_TG_PLAYER_PROP_SHUFFLE:
239                 player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_SHUFFLE;
240                 player_setting.attr_values[0] = ev->value;
241                 break;
242         case HAL_AVRCP_TG_PLAYER_PROP_SCAN:
243                 player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_SCAN;
244                 player_setting.attr_values[0] = ev->value;
245                 break;
246         case HAL_AVRCP_TG_PLAYER_PROP_EQUALIZER:
247                 player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_EQUALIZER;
248                 player_setting.attr_values[0] = ev->value;
249                 break;
250         default:
251                 INFO("Player property not handled: %d", ev->prop_type);
252                 return;
253         }
254
255         bt_hal_avrcp_tg_cbacks->set_player_app_value_cb(&player_setting, NULL);
256 }
257
258 static void __bt_hal_handle_avrcp_tg_events(int message, void *buf, uint16_t len)
259 {
260         DBG("+");
261
262         switch (message) {
263 #ifdef TIZEN_BT_HAL
264         case HAL_EV_AVRCP_TG_CONN_STATE:
265         {
266                 struct hal_ev_avrcp_tg_conn_state *ev = buf;
267
268                 if (!bt_hal_avrcp_tg_cbacks->connection_state_cb)
269                         break;
270
271                 bt_hal_avrcp_tg_cbacks->connection_state_cb(
272                                 (bt_bdaddr_t *)ev->bdaddr, ev->state);
273                 /*
274                  * To retrieve various player properties, callbacks are invoked from bluedroid to
275                  * upper layers (in our case OAL). But in case of BlueZ, these properties are
276                  * cached in stack and replied from within. For this, BlueZ relies on property
277                  * changed signals from upper layer, to keep its cache updated. To handle the above
278                  * case in BlueZ HAL, we register notifications (internal to HAL) and send property
279                  * changed signals to bluez on receiving notifications from upper layer (OAL).
280                  */
281                 if (HAL_AVRCP_TG_STATE_CONNECTED == ev->state)
282                         g_idle_add(__bt_avrcp_register_notifications, ev->bdaddr);
283                 break;
284         }
285         case HAL_EV_AVRCP_TG_DELAY_CHANGE:
286         {
287                 DBG("avrcp tg delay change");
288                 struct hal_ev_avrcp_tg_delay_changed *ev = buf;
289                 bt_hal_avrcp_tg_cbacks->delay_change_cb(
290                                 ev->value, (bt_bdaddr_t *)ev->bdaddr);
291                 break;
292         }
293         case HAL_EV_AVRCP_TG_VOLUME_CHANGE:
294         {
295                 DBG("avrcp tg volume change");
296                 struct hal_ev_avrcp_tg_volume_changed *ev = buf;
297                 bt_hal_avrcp_tg_cbacks->volume_change_cb(
298                                 ev->volume, 0, (bt_bdaddr_t *)ev->bdaddr);
299                 break;
300         }
301 #endif
302         case HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY:
303                 __handle_player_property(buf, len);
304                 break;
305         default:
306                 ERR("Unknown event: 0x%.2X", message);
307         }
308
309         DBG("-");
310 }
311
312 #ifdef TIZEN_BT_HAL
313 bt_status_t hal_avrcp_tg_connect(bt_bdaddr_t *rem_addr)
314 {
315         return _bt_hal_dbus_handler_avrcp_tg_connect(rem_addr);
316 }
317
318 bt_status_t hal_avrcp_tg_disconnect(bt_bdaddr_t *rem_addr)
319 {
320         return _bt_hal_dbus_handler_avrcp_tg_disconnect(rem_addr);
321 }
322 #endif
323
324 static bt_status_t init(btrc_callbacks_t *callbacks)
325 {
326         int ret;
327
328         DBG("");
329
330         if (interface_ready())
331                 return BT_STATUS_DONE;
332
333         if (!callbacks)
334                 return BT_STATUS_PARM_INVALID;
335
336         /* Register AVRCP Media player */
337         ret = _bt_hal_dbus_handler_register_media_player();
338         if (BT_STATUS_SUCCESS != ret)
339                 ERR("_bt_hal_dbus_handler_register_media_player failed");
340
341         /* Register AVRCP event callback */
342         _bt_hal_register_avrcp_tg_dbus_handler_cb(
343                         __bt_hal_handle_avrcp_tg_events);
344         _bt_hal_register_event_handler_cb(HAL_AVRCP_TG,
345                         __bt_hal_handle_avrcp_tg_events);
346
347         bt_hal_avrcp_tg_cbacks = callbacks;
348
349         return BT_STATUS_SUCCESS;
350 }
351
352 static void cleanup(void)
353 {
354         DBG("");
355
356         if (!interface_ready())
357                 return;
358
359         /* Un-register AVRCP Media player */
360         _bt_hal_dbus_handler_unregister_media_player();
361
362         /* Un-register AVRCP event callback */
363         _bt_hal_unregister_avrcp_tg_dbus_handler_cb();
364         _bt_hal_unregister_event_handler_cb(HAL_AVRCP_TG);
365
366         bt_hal_avrcp_tg_cbacks = NULL;
367 }
368
369 static btrc_interface_t avrcp_tg_if = {
370         .size = sizeof(avrcp_tg_if),
371         .init = init,
372 #ifdef TIZEN_BT_HAL
373         .connect = hal_avrcp_tg_connect,
374         .disconnect = hal_avrcp_tg_disconnect,
375 #endif
376         .get_play_status_rsp = get_play_status_rsp,
377         .list_player_app_attr_rsp = list_player_app_attr_rsp,
378         .list_player_app_value_rsp = list_player_app_value_rsp,
379         .get_player_app_attr_text_rsp = get_player_app_attr_text_rsp,
380         .get_player_app_value_text_rsp = get_player_app_value_text_rsp,
381         .get_element_attr_rsp = get_element_attr_rsp,
382         .set_player_app_value_rsp = set_player_app_value_rsp,
383         .register_notification_rsp = register_notification_rsp,
384         .set_volume = set_volume,
385         .get_volume = get_volume,
386         .set_addressed_player_rsp = set_addressed_player_rsp,
387         .set_browsed_player_rsp = set_browsed_player_rsp,
388         .get_folder_items_list_rsp = get_folder_items_list_rsp,
389         .change_path_rsp = change_path_rsp,
390         .get_item_attr_rsp = get_item_attr_rsp,
391         .play_item_rsp = play_item_rsp,
392         .get_total_num_of_items_rsp = get_total_num_of_items_rsp,
393         .search_rsp = search_rsp,
394         .add_to_now_playing_rsp = add_to_now_playing_rsp,
395         .cleanup = cleanup
396 };
397
398 btrc_interface_t *bt_get_avrcp_tg_interface(void)
399 {
400         return &avrcp_tg_if;
401 }