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.
22 #include <sys/socket.h>
23 #include <sys/errno.h>
28 #include "oal-hardware.h"
29 #include "oal-device-mgr.h"
30 #include <oal-manager.h>
31 #include <oal-avrcp-ct.h>
33 #include <bt-service-avrcp-ctrl.h>
34 #include <bluetooth-media-control.h>
35 #include <bt-service-event.h>
37 static int __media_prop_to_oal_type(int type)
43 oal_type = OAL_EQUALIZER;
46 oal_type = OAL_SHUFFLE;
49 oal_type = OAL_REPEAT;
55 oal_type = OAL_PLAY_POSITION;
58 oal_type = OAL_PLAY_STATUS;
61 BT_ERR("Unknown type: %d", type);
68 static int __oal_type_to_media_prop(int oal_type)
85 case OAL_PLAY_POSITION:
92 BT_ERR("Unknown type: %d", oal_type);
99 int _bt_avrcp_connect_remote_target(bluetooth_device_address_t *device_address)
101 oal_status_t status = OAL_STATUS_SUCCESS;
102 int result = BLUETOOTH_ERROR_NONE;
105 status = avrcp_ct_connect((bt_address_t*)device_address);
106 if (status != OAL_STATUS_SUCCESS) {
107 BT_ERR("Connection could not be established, err: [%d]", status);
108 result = BLUETOOTH_ERROR_INTERNAL;
113 int _bt_avrcp_disconnect_remote_target(bluetooth_device_address_t *device_address)
115 oal_status_t status = OAL_STATUS_SUCCESS;
116 int result = BLUETOOTH_ERROR_NONE;
119 status = avrcp_ct_disconnect((bt_address_t*)device_address);
120 if (status != OAL_STATUS_SUCCESS) {
121 BT_ERR("DisConnection err: [%d]", status);
122 result = BLUETOOTH_ERROR_INTERNAL;
127 int _bt_avrcp_control_cmd(int type)
129 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
131 bluetooth_device_address_t device_address;
132 oal_status_t status = OAL_STATUS_SUCCESS;
133 int result = BLUETOOTH_ERROR_NONE;
136 connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
139 _bt_convert_addr_string_to_type(device_address.addr,
142 case RC_PASS_CMD_PLAY:
143 status = avrcp_ct_play((bt_address_t*)&device_address);
145 case RC_PASS_CMD_PAUSE:
146 status = avrcp_ct_pause((bt_address_t*)&device_address);
148 case RC_PASS_CMD_STOP:
149 status = avrcp_ct_stop((bt_address_t*)&device_address);
151 case RC_PASS_CMD_NEXT:
152 status = avrcp_ct_next_track((bt_address_t*)&device_address);
154 case RC_PASS_CMD_PREVIOUS:
155 status = avrcp_ct_prev_track((bt_address_t*)&device_address);
157 case RC_PASS_CMD_PRESS_FAST_FORWARD:
158 status = avrcp_ct_fforward((bt_address_t*)&device_address, PRESS_STATE);
160 case RC_PASS_CMD_RELEASE_FAST_FORWARD:
161 status = avrcp_ct_fforward((bt_address_t*)&device_address, RELEASE_STATE);
163 case RC_PASS_CMD_PRESS_REWIND:
164 status = avrcp_ct_rewind((bt_address_t*)&device_address, PRESS_STATE);
166 case RC_PASS_CMD_RELEASE_REWIND:
167 status = avrcp_ct_rewind((bt_address_t*)&device_address, RELEASE_STATE);
169 case RC_PASS_CMD_VOLUME_UP:
170 status = avrcp_ct_volume_up((bt_address_t*)&device_address);
172 case RC_PASS_CMD_VOLUME_DOWN:
173 status = avrcp_ct_volume_down((bt_address_t*)&device_address);
179 if (status != OAL_STATUS_SUCCESS) {
180 BT_ERR("Send pass through command err: [%d]", status);
181 result = BLUETOOTH_ERROR_INTERNAL;
184 BT_ERR("Device is not connected:");
185 return BLUETOOTH_ERROR_NOT_CONNECTED;
191 int _bt_avrcp_control_set_property(int type, unsigned int value)
193 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
195 bluetooth_device_address_t device_address;
196 oal_status_t status = OAL_STATUS_SUCCESS;
197 int result = BLUETOOTH_ERROR_NONE;
199 connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
204 oal_type = __media_prop_to_oal_type(type);
205 retv_if(0 > oal_type, BLUETOOTH_ERROR_INVALID_PARAM);
207 _bt_convert_addr_string_to_type(device_address.addr,
209 status = avrcp_ct_set_property((bt_address_t*)&device_address,
211 if (status != OAL_STATUS_SUCCESS) {
212 BT_ERR("Set peoperty err: [%d]", status);
213 result = BLUETOOTH_ERROR_INTERNAL;
216 BT_ERR("Device is not connected:");
217 return BLUETOOTH_ERROR_NOT_CONNECTED;
222 int _bt_avrcp_transport_set_property(int type, unsigned int value)
224 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
226 bluetooth_device_address_t device_address;
227 oal_status_t status = OAL_STATUS_SUCCESS;
228 int result = BLUETOOTH_ERROR_NONE;
230 connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
233 _bt_convert_addr_string_to_type(device_address.addr,
235 status = avrcp_transport_set_property((bt_address_t*)&device_address,
237 if (status != OAL_STATUS_SUCCESS) {
238 BT_ERR("Set peoperty err: [%d]", status);
239 result = BLUETOOTH_ERROR_INTERNAL;
242 BT_ERR("Device is not connected:");
243 return BLUETOOTH_ERROR_NOT_CONNECTED;
248 int _bt_avrcp_control_get_property(int type)
250 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
252 bt_address_t device_address;
253 oal_status_t status = OAL_STATUS_SUCCESS;
254 int result = BLUETOOTH_ERROR_NONE;
256 connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
259 avrcp_ct_player_property_type_t oal_type;
261 _bt_convert_addr_string_to_type(
264 if (type == STATUS) {
265 status = avrcp_ct_get_play_status(&device_address);
266 if (status != OAL_STATUS_SUCCESS) {
267 BT_ERR("Get play status err: [%d]", status);
268 result = BLUETOOTH_ERROR_INTERNAL;
271 oal_type = __media_prop_to_oal_type(type);
272 retv_if(0 > oal_type, BLUETOOTH_ERROR_INVALID_PARAM);
274 status = avrcp_ct_get_property(&device_address, oal_type);
275 if (status != OAL_STATUS_SUCCESS) {
276 BT_ERR("Get peoperty err: [%d]", status);
277 result = BLUETOOTH_ERROR_INTERNAL;
281 BT_ERR("Device is not connected:");
282 return BLUETOOTH_ERROR_NOT_CONNECTED;
287 int _bt_avrcp_control_get_track_info(void)
289 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
291 bluetooth_device_address_t device_address;
292 oal_status_t status = OAL_STATUS_SUCCESS;
293 int result = BLUETOOTH_ERROR_NONE;
295 connected = _bt_is_headset_type_connected(BT_AVRCP, connected_address);
298 _bt_convert_addr_string_to_type(
302 status = avrcp_ct_get_media_attribute((bt_address_t*)&device_address);
303 if (status != OAL_STATUS_SUCCESS) {
304 BT_ERR("Get track info err: [%d]", status);
305 result = BLUETOOTH_ERROR_INTERNAL;
308 BT_ERR("Device is not connected:");
309 return BLUETOOTH_ERROR_NOT_CONNECTED;
314 static void __bt_reply_avrcp_ct_connection_pending_request(bluetooth_device_address_t *address)
317 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
318 int result = BLUETOOTH_ERROR_NONE;
319 bluetooth_device_address_t device_address;
321 invocation_info_t *req_info;
322 memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH);
323 _bt_convert_addr_type_to_string(addr, address->addr);
325 req_info = _bt_get_request_info_data(BT_AVRCP_CONTROL_CONNECT, addr);
326 if (NULL == req_info) {
327 BT_INFO("AVRCP CT Connect request not found or possibly already replied");
330 BT_INFO("AVRCP CT Connect request found for [%s]", addr);
333 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
334 g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
335 _bt_service_method_return(req_info->context,
337 g_array_free(out_param, TRUE);
338 g_free(req_info->user_data);
339 _bt_free_info_from_invocation_list(req_info);
342 static void __bt_handle_avrcp_target_connected_state(bluetooth_device_address_t *address)
344 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
346 int result = BLUETOOTH_ERROR_NONE;
347 ret_if(NULL == address);
350 _bt_convert_addr_type_to_string(addr, address->addr);
351 BT_INFO("Address of connected device [%s]", addr);
353 /* Add data from the connected list */
354 _bt_add_headset_to_list(BT_AVRCP, BT_STATE_CONNECTED, addr);
356 /* Replay to avrcp cotroller connect */
357 __bt_reply_avrcp_ct_connection_pending_request(address);
359 /* Send AVRCP(TARGET Role) connected event to Application */
360 param = g_variant_new("(is)", result, addr);
361 _bt_send_event(BT_AVRCP_CONTROL_EVENT, BLUETOOTH_EVENT_AVRCP_CONNECTED, param);
366 static void __bt_reply_avrcp_ct_disconnection_pending_request(bluetooth_device_address_t *address)
368 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
369 int result = BLUETOOTH_ERROR_NONE;
371 invocation_info_t *req_info;
374 _bt_convert_addr_type_to_string(addr, address->addr);
376 req_info = _bt_get_request_info_data(BT_AVRCP_CONTROL_DISCONNECT, addr);
377 if (NULL == req_info) {
378 BT_INFO("AVRCP CT Disconnect request not found or possibly already replied");
381 BT_INFO("AVRCP CT Disconnect request found for [%s]", addr);
384 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
385 g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
386 _bt_service_method_return(req_info->context,
388 g_array_free(out_param, TRUE);
389 g_free(req_info->user_data);
390 _bt_free_info_from_invocation_list(req_info);
393 static void __bt_avrcp_ct_reply_pending_requests(void)
396 int result = BLUETOOTH_ERROR_INTERNAL;
398 invocation_info_t *req_info;
401 for (l = _bt_get_invocation_list(); l != NULL;) {
405 if (req_info == NULL)
408 /* Create out param */
409 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
411 BT_INFO("service_function: [0x%X]", req_info->service_function);
412 switch (req_info->service_function) {
413 case BT_AVRCP_GET_TRACK_INFO:
414 case BT_AVRCP_CONTROL_GET_PROPERTY: {
415 _bt_service_method_return(req_info->context, out_param, result);
421 _bt_free_info_from_invocation_list(req_info);
422 g_array_free(out_param, TRUE);
427 static void __bt_handle_avrcp_target_disconnected_state(bluetooth_device_address_t *address)
429 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
431 int result = BLUETOOTH_ERROR_NONE;
432 ret_if(NULL == address);
435 _bt_convert_addr_type_to_string(addr, address->addr);
436 BT_INFO("Address of disconnected device [%s]", addr);
438 /* Remove data from the connected list */
439 _bt_remove_headset_from_list(BT_AVRCP, addr);
441 /* Reply to avrcp cotroller connect */
442 __bt_reply_avrcp_ct_disconnection_pending_request(address);
444 /* Reply AVRCP CT pending requests */
445 __bt_avrcp_ct_reply_pending_requests();
447 /* Send AVRCP(TARGET Role) disconnected event to Application */
448 param = g_variant_new("(is)", result, addr);
449 _bt_send_event(BT_AVRCP_CONTROL_EVENT, BLUETOOTH_EVENT_AVRCP_DISCONNECTED, param);
454 static int __bt_oal_to_bt_event(int oal_event)
459 case OAL_EVENT_AVRCP_CT_EQUALIZER_STATUS:
460 ret = BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
462 case OAL_EVENT_AVRCP_CT_REPEAT_STATUS:
463 ret = BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
465 case OAL_EVENT_AVRCP_CT_SHUFFLE_STATUS:
466 ret = BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
468 case OAL_EVENT_AVRCP_CT_SCAN_STATUS:
469 ret = BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
471 case OAL_EVENT_AVRCP_CT_NOTIF_PLAY_POS_CHANGED:
472 ret = BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
474 case OAL_EVENT_AVRCP_CT_NOTIF_PLAY_STATUS_CHANGED:
475 ret = BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
483 static void __bt_handle_avrcp_target_player_property(unsigned int property_value, int oal_event)
487 /* Send AVRCP Target player property event to Application */
488 param = g_variant_new("(u)", property_value);
489 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
490 __bt_oal_to_bt_event(oal_event), param);
493 static void __bt_handle_avrcp_track_info_changed(event_avrcp_ct_media_info_t* metadata)
496 unsigned int total_track = 0;
497 unsigned int track_number = 0;
498 unsigned int playing_time = 0;
506 total_track = (unsigned int)(metadata->total_track);
507 track_number = (unsigned int)(metadata->track_number);
508 playing_time = (unsigned int)(metadata->playing_time);
510 title = g_variant_new_from_data((const GVariantType *)"ay",
511 metadata->title_info, MEDIA_ATTIRBUTE_STRING_LENGTH,
513 artist = g_variant_new_from_data((const GVariantType *)"ay",
514 metadata->artist_info, MEDIA_ATTIRBUTE_STRING_LENGTH,
516 album = g_variant_new_from_data((const GVariantType *)"ay",
517 metadata->album_info, MEDIA_ATTIRBUTE_STRING_LENGTH,
519 genre = g_variant_new_from_data((const GVariantType *)"ay",
520 metadata->genre_info, MEDIA_ATTIRBUTE_STRING_LENGTH,
523 /* Send AVRCP Target player track info changed event to application*/
524 param = g_variant_new("(@ay@ay@ay@ayuuu)",
525 title, artist, album, genre,
526 total_track, track_number, playing_time);
528 BT_INFO("Total_track: %u, track_number: %u, playing_time: %u",
529 total_track, track_number, playing_time);
530 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
531 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
534 static invocation_info_t* __bt_get_request_info(int service_function)
537 invocation_info_t *req_info = NULL;
540 /* Get method invocation context */
541 for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
543 if (req_info == NULL || req_info->service_function != service_function)
550 static void __bt_handle_avrcp_track_info(event_avrcp_ct_media_info_t* metadata)
552 media_metadata_t meta_data;
553 invocation_info_t *req_info = NULL;
554 GArray *out_param = NULL;
555 int result = BLUETOOTH_ERROR_NONE;
557 req_info = __bt_get_request_info(BT_AVRCP_GET_TRACK_INFO);
558 ret_if(NULL == req_info);
560 memset(&meta_data, 0x00, sizeof(media_metadata_t));
562 memcpy(&meta_data.title, &metadata->title_info,
563 strlen((char *)metadata->title_info));
564 meta_data.title[strlen((char *)metadata->title_info)] = '\0';
566 memcpy(&meta_data.artist, &metadata->artist_info,
567 strlen((char *)metadata->artist_info));
568 meta_data.artist[strlen((char *)metadata->artist_info)] = '\0';
570 memcpy(&meta_data.album, &metadata->album_info,
571 strlen((char *)metadata->album_info));
572 meta_data.album[strlen((char *)metadata->album_info)] = '\0';
574 memcpy(&meta_data.genre, &metadata->genre_info,
575 strlen((char *)metadata->genre_info));
576 meta_data.genre[strlen((char *)metadata->genre_info)] = '\0';
578 meta_data.total_tracks = metadata->total_track;
579 meta_data.number = metadata->track_number;
580 meta_data.duration = metadata->playing_time;
582 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
583 g_array_append_vals(out_param, &meta_data, sizeof(media_metadata_t));
585 _bt_service_method_return(req_info->context, out_param, result);
586 g_array_free(out_param, TRUE);
587 _bt_free_info_from_invocation_list(req_info);
590 static void __bt_handle_avrcp_pass_cmd_res(avrcp_ct_pass_cmd_t *pass_cmd)
592 BT_INFO(" Send Command Response [%d]", pass_cmd->key_code);
595 static void __bt_handle_avrcp_player_setting_res(avrcp_ct_playersetting_t *player_setting_res)
597 BT_INFO("Set Property Response [%d]", player_setting_res->accepted);
600 static void __bt_handle_avrcp_get_property_res_event(avrcp_ct_player_property_type_t oal_type, int value)
602 invocation_info_t *req_info = NULL;
603 GArray *out_param = NULL;
604 int result = BLUETOOTH_ERROR_NONE;
611 prop_type = __oal_type_to_media_prop(oal_type);
612 ret_if(0 > prop_type);
614 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
615 g_array_append_vals(out_param, &value, sizeof(value));
617 /* Find and reply to all get requests for prop_type */
618 for (l = _bt_get_invocation_list(); l != NULL;) {
622 if (req_info == NULL)
625 type = *((int *)req_info->user_data);
626 if (req_info->service_function != BT_AVRCP_CONTROL_GET_PROPERTY
627 || type != prop_type)
630 BT_INFO("Request found");
631 _bt_service_method_return(req_info->context, out_param, result);
632 g_free(req_info->user_data);
633 _bt_free_info_from_invocation_list(req_info);
636 g_array_free(out_param, TRUE);
640 void _bt_avrcp_ctrl_event_handler(int oal_event, gpointer event_data)
643 bluetooth_device_address_t* bd_addr;
646 case OAL_EVENT_AVRCP_CT_CONNECTED: {
647 BT_INFO("AVRCP Controller Profile connected..");
648 bd_addr = (bluetooth_device_address_t*)event_data;
649 __bt_handle_avrcp_target_connected_state(bd_addr);
652 case OAL_EVENT_AVRCP_CT_DISCONNECTED: {
653 BT_INFO("AVRCP Controller Profile dissconnected..");
654 bd_addr = (bluetooth_device_address_t*)event_data;
655 __bt_handle_avrcp_target_disconnected_state(bd_addr);
658 case OAL_EVENT_AVRCP_CT_EQUALIZER_STATUS:
659 case OAL_EVENT_AVRCP_CT_REPEAT_STATUS:
660 case OAL_EVENT_AVRCP_CT_SHUFFLE_STATUS:
661 case OAL_EVENT_AVRCP_CT_SCAN_STATUS: {
662 avrcp_ct_property_value_t* property_val;
663 property_val = (avrcp_ct_property_value_t*)event_data;
664 __bt_handle_avrcp_target_player_property(property_val->value, oal_event);
667 case OAL_EVENT_AVRCP_CT_NOTIF_PLAY_STATUS_CHANGED:{
668 event_notif_avrcp_ct_notif_info_t* play_status_val;
669 play_status_val = (event_notif_avrcp_ct_notif_info_t*)event_data;
670 __bt_handle_avrcp_target_player_property(play_status_val->play_status, oal_event);
673 case OAL_EVENT_AVRCP_CT_NOTIF_PLAY_POS_CHANGED: {
674 event_notif_avrcp_ct_notif_info_t* play_position;
675 play_position = (event_notif_avrcp_ct_notif_info_t*)event_data;
676 __bt_handle_avrcp_target_player_property(play_position->song_pos, oal_event);
679 case OAL_EVENT_AVRCP_CT_NOTIF_TRACK_CHANGE: {
680 BT_INFO("AVRCP Controller Track Changed event..");
681 event_avrcp_ct_media_info_t* metadata = event_data;
683 __bt_handle_avrcp_track_info_changed(metadata);
686 case OAL_EVENT_AVRCP_CT_MEDIA_INFO: {
687 BT_INFO("AVRCP Controller Track Info event..");
688 event_avrcp_ct_media_info_t* metadata;
690 metadata = (event_avrcp_ct_media_info_t*)event_data;
691 __bt_handle_avrcp_track_info(metadata);
694 case OAL_EVENT_AVRCP_CT_GET_PROPERTY_RES: {
695 BT_INFO("AVRCP Controller Get Property response event..");
696 avrcp_ct_property_value_t *property = (avrcp_ct_property_value_t *)event_data;
697 __bt_handle_avrcp_get_property_res_event(property->type, property->value);
700 case OAL_EVENT_AVRCP_CT_PLAY_STATUS: {
701 BT_INFO("AVRCP Controller Get Play status response event..");
702 event_avrcp_ct_play_status_t *play_status_info = (event_avrcp_ct_play_status_t *)event_data;
703 __bt_handle_avrcp_get_property_res_event(OAL_PLAY_STATUS, play_status_info->play_status);
706 case OAL_EVENT_AVRCP_CT_PASS_CMD_RES: {
707 BT_INFO("AVRCP Controller Pass Command Res");
708 avrcp_ct_pass_cmd_t *pass_cmd;
710 pass_cmd = (avrcp_ct_pass_cmd_t *)event_data;
711 __bt_handle_avrcp_pass_cmd_res(pass_cmd);
714 case OAL_EVENT_AVRCP_CT_PLAYER_SETTING_RES: {
715 BT_INFO("AVRCP Player setting response");
716 avrcp_ct_playersetting_t *player_setting_res;
718 player_setting_res = (avrcp_ct_playersetting_t *)event_data;
719 __bt_handle_avrcp_player_setting_res(player_setting_res);
723 BT_INFO("Invalid Event = %d", oal_event);