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