Initial code for libbt-oal
[platform/core/connectivity/bluetooth-frwk.git] / oal-avrcp-tg.c
1 /*
2  * Open Adaptation Layer (OAL)
3  *
4  * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <dlog.h>
21 #include <string.h>
22 #include <stdio.h>
23
24 #include "bluetooth.h"
25 #include "bt_rc.h"
26
27 #include "oal-event.h"
28 #include "oal-internal.h"
29 #include "oal-common.h"
30 #include "oal-manager.h"
31 #include "oal-avrcp-tg.h"
32
33 #define NUM_MEDIA_ATTR_MAX (BTRC_MEDIA_ATTR_PLAYING_TIME)
34
35 #define CHECK_OAL_AVRCP_ENABLED() \
36         do { \
37                 if (avrcp_api == NULL) { \
38                         BT_ERR("AVRCP Not Enabled"); \
39                         return OAL_STATUS_NOT_READY; \
40                 } \
41         } while (0)
42
43 static void remove_pos_timer();
44
45 #ifdef TIZEN_BT_HAL
46 static void cb_connection_state(bt_bdaddr_t* bd_addr, btrc_connection_state_t state);
47 #endif
48
49 static void cb_avrcp_remote_features(bt_bdaddr_t* bd_addr, btrc_remote_features_t features);
50
51 static void cb_avrcp_get_play_status();
52 static void cb_avrcp_set_player_app_value(btrc_player_settings_t *p_vals, bt_bdaddr_t *bd_addr);
53 static void cb_avrcp_get_element_attr(uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr);
54 static void cb_avrcp_register_notification(btrc_event_id_t event_id, uint32_t param, bt_bdaddr_t *bd_addr);
55 static void cb_avrcp_volume_change(uint8_t volume, uint8_t ctype, bt_bdaddr_t *bd_addr);
56 static void cb_avrcp_delay_change(uint16_t delay, bt_bdaddr_t *bd_addr);
57 static void cb_avrcp_passthrough_command(int id, int pressed, bt_bdaddr_t *bd_addr);
58
59 typedef struct {
60         int play_status:1;
61         int track_change:1;
62         int track_end:1;
63         int track_start:1;
64         int pos_change:1;
65         int setting_change:1;
66         int interval;
67 } notif_t;
68
69 typedef struct {
70         int equalizer;
71         btrc_player_repeat_val_t repeat;
72         btrc_player_shuffle_val_t shuffle;
73         int scan;
74         btrc_play_status_t status;
75         unsigned int volume;
76 } player_settings_t;
77
78 typedef struct {
79         uint32_t song_pos;
80         uint32_t playing_time;
81         uint8_t title[BTRC_MAX_ATTR_STR_LEN];
82         uint8_t artist[BTRC_MAX_ATTR_STR_LEN];
83         uint8_t album[BTRC_MAX_ATTR_STR_LEN];
84         uint8_t genre[BTRC_MAX_ATTR_STR_LEN];
85         unsigned int num_tracks;
86         uint32_t cur_track;
87 } track_info_t;
88
89 typedef enum {
90         STATUS_STOPPED = 0x00,
91         STATUS_PLAYING,
92         STATUS_PAUSED,
93         STATUS_FORWARD_SEEK,
94         STATUS_REVERSE_SEEK,
95         STATUS_ERROR,
96         STATUS_INVALID
97 } media_player_status;
98
99 static track_info_t track_info;
100 static player_settings_t player_setting;
101
102 static guint send_pos_timer = 0;
103
104 static notif_t registered_notifications;
105 static const btrc_interface_t *avrcp_api;
106
107 static btrc_callbacks_t sBluetoothAvrcpCallbacks = {
108         sizeof(sBluetoothAvrcpCallbacks),
109 #ifdef TIZEN_BT_HAL
110         cb_connection_state,
111 #endif
112         cb_avrcp_remote_features,
113         cb_avrcp_get_play_status,
114         NULL, /* cb_avrcp_list_player_app_attr, */
115         NULL, /* cb_avrcp_list_player_app_values, */
116         NULL, /* cb_avrcp_get_player_app_value, */
117         NULL, /* cb_avrcp_get_player_app_attrs_text, */
118         NULL, /* cb_avrcp_get_player_app_values_text, */
119         cb_avrcp_set_player_app_value,
120         cb_avrcp_get_element_attr,
121         cb_avrcp_register_notification,
122         cb_avrcp_volume_change,
123         cb_avrcp_delay_change,
124         cb_avrcp_passthrough_command,
125         NULL, /* cb_avrcp_set_addressed_player, */
126         NULL, /* cb_avrcp_set_browsed_player, */
127         NULL, /* cb_avrcp_get_folder_items, */
128         NULL, /* cb_avrcp_change_path, */
129         NULL, /* cb_avrcp_get_item_attr, */
130         NULL, /* cb_avrcp_play_item, */
131         NULL, /* cb_avrcp_get_total_num_of_items, */
132         NULL, /* cb_avrcp_search, */
133         NULL, /* cb_avrcp_add_to_now_playing, */
134 };
135
136 static void send_pos_changed(void)
137 {
138         BT_DBG("Pos changed");
139
140         if (avrcp_api == NULL) {
141                 BT_ERR("AVRCP Not Enabled");
142                 return ;
143         }
144
145         if (registered_notifications.pos_change) {
146                 int ret;
147                 btrc_register_notification_t response;
148
149                 BT_DBG("Song Pos: %d", track_info.song_pos);
150                 response.song_pos = track_info.song_pos;
151                 ret = avrcp_api->register_notification_rsp(
152                         BTRC_EVT_PLAY_POS_CHANGED, BTRC_NOTIFICATION_TYPE_CHANGED, &response);
153
154                 if (ret != BT_STATUS_SUCCESS)
155                         BT_ERR("Notif send failed: %s", status2string(ret));
156         }
157 }
158
159 static gboolean send_pos_timeout(gpointer  param)
160 {
161         BT_DBG("pos timeout");
162
163         if (!registered_notifications.pos_change)
164                 return FALSE;
165
166         send_pos_changed();
167
168         if (player_setting.status != BTRC_PLAYSTATE_PLAYING &&
169                 player_setting.status != BTRC_PLAYSTATE_FWD_SEEK &&
170                 player_setting.status != BTRC_PLAYSTATE_REV_SEEK)
171                 return FALSE;
172
173         return TRUE;
174 }
175
176 static void remove_pos_timer()
177 {
178
179         if (send_pos_timer > 0) {
180                 g_source_remove(send_pos_timer);
181                 send_pos_timer = 0;
182         }
183 }
184
185 static void send_track_boundary_reached(void)
186 {
187         int ret = BT_STATUS_SUCCESS;
188
189         if (avrcp_api == NULL) {
190                 BT_ERR("AVRCP Not Enabled");
191                 return;
192         }
193
194         if (track_info.song_pos == 0 &&
195                 registered_notifications.track_start)
196                 ret = avrcp_api->register_notification_rsp(
197                         BTRC_EVT_TRACK_REACHED_START, BTRC_NOTIFICATION_TYPE_CHANGED, NULL);
198         else if ((track_info.playing_time == track_info.song_pos) &&
199                         registered_notifications.track_end) {
200                 ret = avrcp_api->register_notification_rsp(
201                         BTRC_EVT_TRACK_REACHED_END, BTRC_NOTIFICATION_TYPE_CHANGED, NULL);
202         }
203
204         if (ret != BT_STATUS_SUCCESS)
205                 BT_ERR("Notif send failed: %s", status2string(ret));
206 }
207
208 gboolean avrcp_tg_enable_state(void)
209 {
210         if (avrcp_api == NULL)
211                 return FALSE;
212         else
213                 return TRUE;
214 }
215
216 oal_status_t avrcp_enable(void)
217 {
218         const bt_interface_t * blued_api = NULL;
219         int ret;
220
221         API_TRACE();
222
223         /*TODO: Need to check below logic */
224 #if 0
225         if (a2dp_sink_enable_state() == TRUE || avrcp_ct_enable_state() == TRUE) {
226                 BT_ERR("AVRCP_CT Role Enabled, cannot enable AVRCP_TG Role");
227                 return OAL_STATUS_BUSY;
228         }
229 #endif
230
231         blued_api = adapter_get_stack_interface();
232         if (blued_api == NULL) {
233                 BT_ERR("Stack is not initialized");
234                 return OAL_STATUS_NOT_READY;
235         }
236
237         if (avrcp_api) {
238                 BT_WARN("avrcp tg Interface is already initialized...");
239                 return OAL_STATUS_ALREADY_DONE;
240         }
241
242         avrcp_api = (const btrc_interface_t *)blued_api->get_profile_interface(BT_PROFILE_AV_RC_ID);
243         if (avrcp_api == NULL) {
244                 BT_ERR("AVRCP interface failed");
245                 return OAL_STATUS_INTERNAL_ERROR;
246         }
247
248         memset(&registered_notifications, 0x00, sizeof(registered_notifications));
249         memset(&track_info, 0x00, sizeof(track_info));
250         memset(&player_setting, 0, sizeof(player_settings_t));
251
252         /* Handle failure if return value is anything other than Success or Already done */
253         ret = avrcp_api->init(&sBluetoothAvrcpCallbacks);
254         if (ret != BT_STATUS_SUCCESS && ret != BT_STATUS_DONE) {
255                 BT_ERR("AVRCP Init failed %s", status2string(ret));
256                 avrcp_api->cleanup();
257                 avrcp_api = NULL;
258                 return convert_to_oal_status(ret);
259         }
260
261         return OAL_STATUS_SUCCESS;
262 }
263
264 oal_status_t avrcp_disable(void)
265 {
266
267         API_TRACE();
268
269         CHECK_OAL_AVRCP_ENABLED();
270
271         remove_pos_timer();
272         avrcp_api->cleanup();
273         avrcp_api = NULL;
274
275         return OAL_STATUS_SUCCESS;
276 }
277
278 void avrcp_tg_cleanup(void)
279 {
280
281         BT_DBG();
282
283         remove_pos_timer();
284         avrcp_api = NULL;
285 }
286
287 oal_status_t avrcp_tg_connect(bt_address_t *rem_addr)
288 {
289         int result = OAL_STATUS_SUCCESS;
290         bt_status_t status;
291         bdstr_t bdstr;
292
293         API_TRACE();
294
295         CHECK_OAL_AVRCP_ENABLED();
296         OAL_CHECK_PARAMETER(rem_addr, return);
297
298         BT_INFO("BT Audio Address: %s", bdt_bd2str(rem_addr, &bdstr));
299
300 #ifdef TIZEN_BT_HAL
301         status = avrcp_api->connect((bt_bdaddr_t *)rem_addr);
302         if ((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) {
303                 BT_ERR("Connection could not be established, err: %s", status2string(status));;
304                 result =  convert_to_oal_status(status);
305         }
306 #else
307         BT_INFO("Not Supported");
308         result = OAL_STATUS_NOT_SUPPORT;
309 #endif
310
311         return result;
312 }
313
314 oal_status_t avrcp_tg_disconnect(bt_address_t *rem_addr)
315 {
316         int result = OAL_STATUS_SUCCESS;
317         bdstr_t bdstr;
318         bt_status_t status;
319
320         API_TRACE();
321
322         CHECK_OAL_AVRCP_ENABLED();
323         OAL_CHECK_PARAMETER(rem_addr, return);
324
325         BT_INFO("BT Audio Address: %s", bdt_bd2str(rem_addr, &bdstr));
326
327 #ifdef TIZEN_BT_HAL
328         status = avrcp_api->disconnect((bt_bdaddr_t *)rem_addr);
329         if ((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) {
330                 BT_ERR("OAL, Disconnection failed err: %s", status2string(status));
331                 result =  convert_to_oal_status(status);
332         }
333 #else
334         BT_INFO("Not Supported");
335         result = OAL_STATUS_NOT_SUPPORT;
336 #endif
337
338         return result;
339 }
340
341 oal_status_t avrcp_set_track_info(oal_media_metadata_attributes_t *meta_data)
342 {
343         API_TRACE();
344
345         CHECK_OAL_AVRCP_ENABLED();
346
347         retv_if(meta_data == NULL, OAL_STATUS_INTERNAL_ERROR);
348
349         /********* Update media attribs **********/
350         g_strlcpy((char*)track_info.title, meta_data->title, BTRC_MAX_ATTR_STR_LEN);
351         g_strlcpy((char*)track_info.artist, meta_data->artist, BTRC_MAX_ATTR_STR_LEN);
352         g_strlcpy((char*)track_info.album, meta_data->album, BTRC_MAX_ATTR_STR_LEN);
353         g_strlcpy((char*)track_info.genre, meta_data->genre, BTRC_MAX_ATTR_STR_LEN);
354
355         track_info.num_tracks = meta_data->total_tracks;
356         track_info.playing_time = meta_data->duration;
357
358         if (registered_notifications.track_change &&
359                         track_info.cur_track != meta_data->number) {
360                 int ret;
361                 btrc_register_notification_t response;
362
363                 memset(&response, 0x00, sizeof(btrc_register_notification_t));
364
365                 track_info.cur_track = meta_data->number;
366
367                 /* Send Track Change notification */
368                 memcpy(&response.track, &track_info.cur_track, sizeof(uint32_t));
369                 ret = avrcp_api->register_notification_rsp(
370                         BTRC_EVT_TRACK_CHANGE, BTRC_NOTIFICATION_TYPE_CHANGED, &response);
371                 if (ret != BT_STATUS_SUCCESS)
372                         BT_ERR("Notif send failed: %s",  status2string(ret));
373
374                 send_pos_changed();
375         }
376
377         track_info.cur_track = meta_data->number;
378         return OAL_STATUS_SUCCESS;
379 }
380
381 oal_status_t avrcp_set_property(int type, unsigned int value)
382 {
383         btrc_register_notification_t response;
384         int ret;
385
386         API_TRACE("type: %d, value: %d", type, value);
387         CHECK_OAL_AVRCP_ENABLED();
388
389         switch (type) {
390         case AVRCP_EQUALIZER: {
391                 if (value == player_setting.equalizer &&
392                         !registered_notifications.setting_change)
393                         break;
394
395                 response.player_setting.num_attr = 1;
396                 response.player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_EQUALIZER;
397                 response.player_setting.attr_values[0] = value;
398                 ret = avrcp_api->register_notification_rsp(BTRC_EVT_APP_SETTINGS_CHANGED,
399                                 BTRC_NOTIFICATION_TYPE_CHANGED, &response);
400                 if (ret != BT_STATUS_SUCCESS)
401                         BT_ERR("Notif send failed: %s", status2string(ret));
402
403                 player_setting.equalizer = value;
404                 break;
405         }
406         case AVRCP_REPEAT: {
407                 if (value == player_setting.repeat &&
408                         !registered_notifications.setting_change)
409                         break;
410
411                 response.player_setting.num_attr = 1;
412                 response.player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_REPEAT;
413                 response.player_setting.attr_values[0] = value;
414                 ret = avrcp_api->register_notification_rsp(BTRC_EVT_APP_SETTINGS_CHANGED,
415                                 BTRC_NOTIFICATION_TYPE_CHANGED, &response);
416                 if (ret != BT_STATUS_SUCCESS)
417                         BT_ERR("Notif send failed: %s", status2string(ret));
418
419                 player_setting.repeat = value;
420                 break;
421         }
422         case AVRCP_SHUFFLE: {
423                 if (value == player_setting.shuffle &&
424                         !registered_notifications.setting_change)
425                         break;
426
427                 response.player_setting.num_attr = 1;
428                 response.player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_SHUFFLE;
429                 response.player_setting.attr_values[0] = value;
430                 ret = avrcp_api->register_notification_rsp(BTRC_EVT_APP_SETTINGS_CHANGED,
431                                 BTRC_NOTIFICATION_TYPE_CHANGED, &response);
432                 if (ret != BT_STATUS_SUCCESS)
433                         BT_ERR("Notif send failed: %s", status2string(ret));
434
435                 player_setting.shuffle = value;
436                 break;
437         }
438         case AVRCP_SCAN: {
439                 if (value == player_setting.scan &&
440                         !registered_notifications.setting_change)
441                         break;
442
443                 response.player_setting.num_attr = 1;
444                 response.player_setting.attr_ids[0] = BTRC_PLAYER_ATTR_SCAN;
445                 response.player_setting.attr_values[0] = value;
446                 ret = avrcp_api->register_notification_rsp(BTRC_EVT_APP_SETTINGS_CHANGED,
447                                 BTRC_NOTIFICATION_TYPE_CHANGED, &response);
448                 if (ret != BT_STATUS_SUCCESS)
449                         BT_ERR("Notif send failed: %s", status2string(ret));
450
451                 player_setting.scan = value;
452                 break;
453         }
454         case AVRCP_STATUS:
455                 if (value != player_setting.status) {
456                         btrc_play_status_t play_status = player_setting.status;
457
458                         player_setting.status = (value == STATUS_ERROR) ? BTRC_PLAYSTATE_ERROR : value;
459
460                         if (registered_notifications.play_status) {
461                                 gboolean is_timer = FALSE;
462
463                                 response.play_status = player_setting.status;
464                                 ret = avrcp_api->register_notification_rsp(BTRC_EVT_PLAY_STATUS_CHANGED,
465                                                 BTRC_NOTIFICATION_TYPE_CHANGED, &response);
466                                 if (ret != BT_STATUS_SUCCESS)
467                                         BT_ERR("Notif send failed: %s", status2string(ret));
468
469                                 /* Check if old and new status value are changed from NOT PLAYING to PLAYING */
470                                 switch (play_status) {
471                                 case BTRC_PLAYSTATE_ERROR:      /* Intentional fall-through */
472                                 case BTRC_PLAYSTATE_STOPPED:    /* Intentional fall-through */
473                                 case BTRC_PLAYSTATE_PAUSED:     /* Intentional fall-through */
474                                         if (STATUS_PLAYING == value ||
475                                                         STATUS_REVERSE_SEEK == value ||
476                                                         STATUS_FORWARD_SEEK == value) {
477                                                 BT_INFO("Play status changed from stopped to playing");
478                                                 is_timer = TRUE;
479                                         }
480                                         break;
481                                 default:
482                                         is_timer = FALSE;
483                                 }
484
485                                 if (is_timer) {
486                                         BT_DBG("Player is playing mode, start sending pos change notifications");
487                                         remove_pos_timer();
488                                         send_pos_timer = g_timeout_add(registered_notifications.interval * 1000,
489                                                         send_pos_timeout, NULL);
490                                 }
491                         }
492                 }
493                 break;
494         case AVRCP_POSITION:
495                 if (value != track_info.song_pos) {
496                         track_info.song_pos = value;
497                         send_pos_changed();
498                         send_track_boundary_reached();
499                 }
500                 break;
501         default:
502                 BT_ERR("Invalid Type\n");
503                 return OAL_STATUS_INTERNAL_ERROR;
504         }
505
506         return OAL_STATUS_SUCCESS;
507 }
508
509 #ifdef TIZEN_BT_HAL
510 static void cb_connection_state(bt_bdaddr_t* bd_addr, btrc_connection_state_t state)
511 {
512         bt_address_t * event_data = NULL;
513         int event;
514
515         BT_DBG("%d", state);
516
517         event_data = g_new0(bt_address_t, 1);
518         memcpy(event_data->addr, bd_addr->address, BT_ADDRESS_BYTES_NUM);
519
520         switch (state) {
521         case BTRC_CONNECTION_STATE_DISCONNECTED:
522                 event = OAL_EVENT_AVRCP_DISCONNECTED;
523                 break;
524         case BTRC_CONNECTION_STATE_CONNECTED:
525                 event = OAL_EVENT_AVRCP_CONNECTED;
526                 break;
527         default:
528                 BT_ERR("Unhandled Connection state %d", state);
529                 return;
530         }
531
532         send_event_bda_trace(event, event_data, sizeof(bt_address_t), (bt_address_t*)bd_addr);
533
534 }
535 #endif
536
537 static void cb_avrcp_remote_features(bt_bdaddr_t* bd_addr, btrc_remote_features_t features)
538 {
539         remote_feature *avrcp_rem_feature = g_new0(remote_feature, 1);
540
541         /* Reset variables */
542         memset(&registered_notifications, 0, sizeof(notif_t));
543         memset(&track_info, 0, sizeof(track_info_t));
544         memset(&player_setting, 0, sizeof(player_settings_t));
545         player_setting.volume =  0xFFFFFFFF/2;
546
547         /* TODO: need to check if this feature mask is useful */
548         BT_INFO("Remore features Mask: 0x%x", features);
549
550         avrcp_rem_feature->avrcp_feature = features;
551         memcpy(avrcp_rem_feature->address.addr, bd_addr->address, 6);
552
553         send_event_bda_trace(OAL_EVENT_AVRCP_REMOTE_FEATURES,
554                 avrcp_rem_feature, sizeof(remote_feature), (bt_address_t *)bd_addr);
555 }
556
557 static void cb_avrcp_get_play_status(bt_bdaddr_t *bd_addr)
558 {
559         int ret;
560
561         BT_DBG("");
562
563         if (avrcp_api == NULL) {
564                 BT_ERR("AVRCP Not Enabled");
565                 return ;
566         }
567
568         ret = avrcp_api->get_play_status_rsp(bd_addr, player_setting.status,
569                         track_info.playing_time, track_info.song_pos);
570         if (ret != BT_STATUS_SUCCESS)
571                 BT_ERR("Play Status send failed: %s", status2string(ret));
572 }
573
574 static void cb_avrcp_set_player_app_value(btrc_player_settings_t *p_vals, bt_bdaddr_t *bd_addr)
575 {
576         int i;
577         uint8_t *value ;
578         oal_event_t event;
579
580         BT_DBG("");
581
582         for (i = 0; i < p_vals->num_attr; i++) {
583                 event = 0xffff;
584
585                 switch (p_vals->attr_ids[i]) {
586                 case BTRC_PLAYER_ATTR_EQUALIZER:
587                         event = OAL_EVENT_AVRCP_SETTING_EQUALIZER_STATUS;
588                         break;
589                 case BTRC_PLAYER_ATTR_REPEAT:
590                         event = OAL_EVENT_AVRCP_SETTING_REPEAT_STATUS;
591                         break;
592                 case BTRC_PLAYER_ATTR_SHUFFLE:
593                         event = OAL_EVENT_AVRCP_SETTING_SHUFFLE_STATUS;
594                         break;
595                 case BTRC_PLAYER_ATTR_SCAN:
596                         event = OAL_EVENT_AVRCP_SETTING_SCAN_STATUS;
597                         break;
598                 default:
599                         BT_ERR("Inavlid attr id= %d", p_vals->attr_ids[i]);
600                 }
601
602                 if (event != 0xffff) {
603                         value = g_new0(uint8_t, 1);
604                         *value = p_vals->attr_values[i];
605                         send_event(event, value, sizeof(*value));
606                 }
607         }
608 }
609
610 static void cb_avrcp_get_element_attr(uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr)
611 {
612         btrc_element_attr_val_t *p_attrs_vals;
613         int ret;
614         int i;
615
616         if (avrcp_api == NULL) {
617                 BT_ERR("AVRCP Not Enabled");
618                 return;
619         }
620
621         if (p_attrs == NULL) {
622                 BT_ERR("p_attrs is NULL");
623                 return;
624         }
625
626         BT_DBG("num_attr: %d", num_attr);
627         p_attrs_vals = g_malloc0(num_attr * sizeof(btrc_element_attr_val_t));
628
629         for (i = 0; i < num_attr; i++) {
630                 p_attrs_vals[i].attr_id = p_attrs[i];
631
632                 switch (p_attrs[i]) {
633                 case BTRC_MEDIA_ATTR_TITLE:
634                         g_strlcpy((char*)p_attrs_vals[i].text,
635                                 (const char *)track_info.title, BTRC_MAX_ATTR_STR_LEN);
636                         break;
637                 case BTRC_MEDIA_ATTR_ARTIST:
638                         g_strlcpy((char*)p_attrs_vals[i].text,
639                                 (const char *)track_info.artist, BTRC_MAX_ATTR_STR_LEN);
640                         break;
641                 case BTRC_MEDIA_ATTR_ALBUM:
642                         g_strlcpy((char*)p_attrs_vals[i].text,
643                                 (const char *)track_info.album, BTRC_MAX_ATTR_STR_LEN);
644                         break;
645                 case BTRC_MEDIA_ATTR_TRACK_NUM:
646                         snprintf((char*)p_attrs_vals[i].text, BTRC_MAX_ATTR_STR_LEN, "%u", track_info.cur_track);
647                         break;
648                 case BTRC_MEDIA_ATTR_NUM_TRACKS:
649                         snprintf((char*)p_attrs_vals[i].text, BTRC_MAX_ATTR_STR_LEN, "%u", track_info.num_tracks);
650                         break;
651                 case BTRC_MEDIA_ATTR_GENRE:
652                         g_strlcpy((char*)p_attrs_vals[i].text,
653                                 (const char *)track_info.genre, BTRC_MAX_ATTR_STR_LEN);
654                         break;
655                 case BTRC_MEDIA_ATTR_PLAYING_TIME:
656                         snprintf((char*)p_attrs_vals[i].text, BTRC_MAX_ATTR_STR_LEN, "%u", track_info.playing_time);
657                         break;
658                 default:
659                         BT_ERR("Inavlid attr id= %d", p_attrs[i]);
660                 }
661         }
662
663         ret = avrcp_api->get_element_attr_rsp(bd_addr, num_attr, p_attrs_vals);
664         if (ret != BT_STATUS_SUCCESS)
665                 BT_ERR("Element attr send failed: %s", status2string(ret));
666
667         g_free(p_attrs_vals);
668 }
669
670 static void cb_avrcp_register_notification(btrc_event_id_t event_id, uint32_t param, bt_bdaddr_t *bd_addr)
671 {
672         btrc_register_notification_t response;
673         int ret;
674
675         BT_DBG("event_id: 0x%x", event_id);
676
677         if (avrcp_api == NULL) {
678                 BT_ERR("AVRCP Not Enabled");
679                 return ;
680         }
681         memset(&response, 0x00, sizeof(btrc_register_notification_t));
682
683         switch (event_id) {
684         case BTRC_EVT_PLAY_STATUS_CHANGED:
685                 registered_notifications.play_status = 1;
686                 response.play_status = player_setting.status;
687                 ret = avrcp_api->register_notification_rsp(
688                         BTRC_EVT_PLAY_STATUS_CHANGED, BTRC_NOTIFICATION_TYPE_INTERIM, &response);
689                 break;
690         case BTRC_EVT_TRACK_CHANGE:
691                 registered_notifications.track_change = 1;
692                 memcpy(response.track, &track_info.cur_track, sizeof(uint32_t));
693                 ret = avrcp_api->register_notification_rsp(
694                         BTRC_EVT_TRACK_CHANGE, BTRC_NOTIFICATION_TYPE_INTERIM, &response);
695                 break;
696         case BTRC_EVT_TRACK_REACHED_END:
697                 registered_notifications.track_end = 1;
698                 ret = avrcp_api->register_notification_rsp(
699                         BTRC_EVT_TRACK_REACHED_END, BTRC_NOTIFICATION_TYPE_INTERIM, NULL);
700                 break;
701         case BTRC_EVT_TRACK_REACHED_START:
702                 registered_notifications.track_start = 1;
703                 ret = avrcp_api->register_notification_rsp(
704                         BTRC_EVT_TRACK_REACHED_START, BTRC_NOTIFICATION_TYPE_INTERIM, NULL);
705                 break;
706         case BTRC_EVT_PLAY_POS_CHANGED:
707                 registered_notifications.pos_change = 1;
708                 registered_notifications.interval = param;
709                 BT_DBG("Pos will be notified every %d secs", param);
710                 /*
711                  * start a timer with value of interval and send rsp on each timer fire.
712                  * Other then this in below situations also send the response:
713                  *      - Change in Play status
714                  *      - Change in current track
715                  *      - Reach end or beginning of track
716                  */
717                 response.song_pos = track_info.song_pos;
718                 ret = avrcp_api->register_notification_rsp(
719                         BTRC_EVT_PLAY_POS_CHANGED, BTRC_NOTIFICATION_TYPE_INTERIM, &response);
720                 remove_pos_timer();
721                 send_pos_timer = g_timeout_add(param * 1000, send_pos_timeout, NULL);
722                 break;
723         case BTRC_EVT_APP_SETTINGS_CHANGED:
724                 registered_notifications.setting_change = 1;
725                 ret = avrcp_api->register_notification_rsp(
726                         BTRC_EVT_APP_SETTINGS_CHANGED, BTRC_NOTIFICATION_TYPE_INTERIM, &response);
727                 break;
728         default:
729                 BT_ERR("Invalid event id: 0x%x", event_id);
730                 ret = BT_STATUS_FAIL;
731         }
732
733         if (ret != BT_STATUS_SUCCESS)
734                 BT_ERR("Notif send failed: %s", status2string(ret));
735 }
736
737 static void cb_avrcp_volume_change(uint8_t volume, uint8_t ctype, bt_bdaddr_t *bd_addr)
738 {
739
740         oal_avrcp_volume_mute_t *avrcp_volume_mute = g_new0(oal_avrcp_volume_mute_t, 1);
741
742         BT_INFO("volume: %d, ctype: %d", volume, ctype);
743         player_setting.volume = volume;
744
745         avrcp_volume_mute->volume = volume;
746         if (0 == volume)
747                 avrcp_volume_mute->mute_status = TRUE;
748         else
749                 avrcp_volume_mute->mute_status = FALSE;
750
751         send_event(OAL_EVENT_AVRCP_VOLUME_MUTE_CHANGED,
752                         avrcp_volume_mute, sizeof(oal_avrcp_volume_mute_t));
753 }
754
755 static void cb_avrcp_delay_change(uint16_t delay, bt_bdaddr_t *bd_addr)
756 {
757         BT_INFO("Delay : %d", delay);
758         oal_avrcp_delay_t *avrcp_delay = g_new0(oal_avrcp_delay_t, 1);
759         avrcp_delay->delay = delay;
760
761         send_event(OAL_EVENT_AVRCP_DELAY_CHANGED,
762                         avrcp_delay, sizeof(oal_avrcp_delay_t));
763 }
764
765 static void cb_avrcp_passthrough_command(int id, int key_state, bt_bdaddr_t *bd_addr)
766 {
767         BT_DBG("id: %d, key_state: %d", id, key_state);
768         //TODO: need to check
769 }