| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678 |
- // SPDX-License-Identifier: Apache-2.0
- /*
- * Copyright (C) 2014 Intel Corporation
- *
- */
- #define _GNU_SOURCE
- #include <stdbool.h>
- #include <stddef.h>
- #include <string.h>
- #include <stdlib.h>
- #include "hal-utils.h"
- #include "hal-log.h"
- #include "hal.h"
- #include "hal-msg.h"
- #include "ipc-common.h"
- #include "hal-ipc.h"
- static const btrc_callbacks_t *cbs = NULL;
- static bool interface_ready(void)
- {
- return cbs != NULL;
- }
- static void handle_remote_features(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_remote_features *ev = buf;
- if (cbs->remote_features_cb)
- cbs->remote_features_cb((bt_bdaddr_t *) (ev->bdaddr),
- ev->features);
- }
- static void handle_get_play_status(void *buf, uint16_t len, int fd)
- {
- if (cbs->get_play_status_cb)
- cbs->get_play_status_cb();
- }
- static void handle_list_player_attrs(void *buf, uint16_t len, int fd)
- {
- if (cbs->list_player_app_attr_cb)
- cbs->list_player_app_attr_cb();
- }
- static void handle_list_player_values(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_list_player_values *ev = buf;
- if (cbs->list_player_app_values_cb)
- cbs->list_player_app_values_cb(ev->attr);
- }
- static void handle_get_player_values(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_get_player_values *ev = buf;
- btrc_player_attr_t attrs[4];
- int i;
- if (!cbs->get_player_app_value_cb)
- return;
- /* Convert uint8_t array to btrc_player_attr_t array */
- for (i = 0; i < ev->number; i++)
- attrs[i] = ev->attrs[i];
- cbs->get_player_app_value_cb(ev->number, attrs);
- }
- static void handle_get_player_attrs_text(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_get_player_attrs_text *ev = buf;
- btrc_player_attr_t attrs[4];
- int i;
- if (!cbs->get_player_app_attrs_text_cb)
- return;
- /* Convert uint8_t array to btrc_player_attr_t array */
- for (i = 0; i < ev->number; i++)
- attrs[i] = ev->attrs[i];
- cbs->get_player_app_attrs_text_cb(ev->number, attrs);
- }
- static void handle_get_player_values_text(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_get_player_values_text *ev = buf;
- if (cbs->get_player_app_values_text_cb)
- cbs->get_player_app_values_text_cb(ev->attr, ev->number,
- ev->values);
- }
- static void handle_set_player_value(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_set_player_values *ev = buf;
- struct hal_avrcp_player_attr_value *attrs;
- btrc_player_settings_t values;
- int i;
- if (!cbs->set_player_app_value_cb)
- return;
- attrs = (struct hal_avrcp_player_attr_value *) ev->attrs;
- /* Convert to btrc_player_settings_t */
- values.num_attr = ev->number;
- for (i = 0; i < ev->number; i++) {
- values.attr_ids[i] = attrs[i].attr;
- values.attr_values[i] = attrs[i].value;
- }
- cbs->set_player_app_value_cb(&values);
- }
- static void handle_get_element_attrs(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_get_element_attrs *ev = buf;
- btrc_media_attr_t attrs[BTRC_MAX_APP_SETTINGS];
- int i;
- if (!cbs->get_element_attr_cb)
- return;
- /* Convert uint8_t array to btrc_media_attr_t array */
- for (i = 0; i < ev->number; i++)
- attrs[i] = ev->attrs[i];
- cbs->get_element_attr_cb(ev->number, attrs);
- }
- static void handle_register_notification(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_register_notification *ev = buf;
- if (cbs->register_notification_cb)
- cbs->register_notification_cb(ev->event, ev->param);
- }
- static void handle_volume_changed(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_volume_changed *ev = buf;
- if (cbs->volume_change_cb)
- cbs->volume_change_cb(ev->volume, ev->type);
- }
- static void handle_passthrough_cmd(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_avrcp_passthrough_cmd *ev = buf;
- if (cbs->passthrough_cmd_cb)
- cbs->passthrough_cmd_cb(ev->id, ev->state);
- }
- /*
- * handlers will be called from notification thread context,
- * index in table equals to 'opcode - HAL_MINIMUM_EVENT'
- */
- static const struct hal_ipc_handler ev_handlers[] = {
- /* HAL_EV_AVRCP_REMOTE_FEATURES */
- { handle_remote_features, false,
- sizeof(struct hal_ev_avrcp_remote_features) },
- /* HAL_EV_AVRCP_GET_PLAY_STATUS */
- { handle_get_play_status, false, 0 },
- /* HAL_EV_AVRCP_LIST_PLAYER_ATTRS */
- { handle_list_player_attrs, false, 0 },
- /* HAL_EV_AVRCP_LIST_PLAYER_VALUES */
- { handle_list_player_values, false,
- sizeof(struct hal_ev_avrcp_list_player_values) },
- /* HAL_EV_AVRCP_GET_PLAYER_VALUES */
- { handle_get_player_values, true,
- sizeof(struct hal_ev_avrcp_get_player_values) },
- /* HAL_EV_AVRCP_GET_PLAYER_ATTRS_TEXT */
- { handle_get_player_attrs_text, true,
- sizeof(struct hal_ev_avrcp_get_player_attrs_text) },
- /* HAL_EV_AVRCP_GET_PLAYER_VALUES_TEXT */
- { handle_get_player_values_text, true,
- sizeof(struct hal_ev_avrcp_get_player_values_text) },
- /* HAL_EV_AVRCP_SET_PLAYER_VALUES */
- { handle_set_player_value, true,
- sizeof(struct hal_ev_avrcp_set_player_values) },
- /* HAL_EV_AVRCP_GET_ELEMENT_ATTRS */
- { handle_get_element_attrs, true,
- sizeof(struct hal_ev_avrcp_get_element_attrs) },
- /* HAL_EV_AVRCP_REGISTER_NOTIFICATION */
- { handle_register_notification, false,
- sizeof(struct hal_ev_avrcp_register_notification) },
- /* HAL_EV_AVRCP_VOLUME_CHANGED */
- { handle_volume_changed, false,
- sizeof(struct hal_ev_avrcp_volume_changed) },
- /* HAL_EV_AVRCP_PASSTHROUGH_CMD */
- { handle_passthrough_cmd, false,
- sizeof(struct hal_ev_avrcp_passthrough_cmd) },
- };
- static bt_status_t init(btrc_callbacks_t *callbacks)
- {
- struct hal_cmd_register_module cmd;
- int ret;
- DBG("");
- if (interface_ready())
- return BT_STATUS_DONE;
- cbs = callbacks;
- hal_ipc_register(HAL_SERVICE_ID_AVRCP, ev_handlers,
- sizeof(ev_handlers) / sizeof(ev_handlers[0]));
- cmd.service_id = HAL_SERVICE_ID_AVRCP;
- cmd.mode = HAL_MODE_DEFAULT;
- cmd.max_clients = 1;
- ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- if (ret != BT_STATUS_SUCCESS) {
- cbs = NULL;
- hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
- }
- return ret;
- }
- static bt_status_t get_play_status_rsp(btrc_play_status_t status,
- uint32_t song_len, uint32_t song_pos)
- {
- struct hal_cmd_avrcp_get_play_status cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- cmd.status = status;
- cmd.duration = song_len;
- cmd.position = song_pos;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAY_STATUS,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t list_player_app_attr_rsp(int num_attr,
- btrc_player_attr_t *p_attrs)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_list_player_attrs *cmd = (void *) buf;
- size_t len;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (num_attr < 0)
- return BT_STATUS_PARM_INVALID;
- len = sizeof(*cmd) + num_attr;
- if (len > IPC_MTU)
- return BT_STATUS_PARM_INVALID;
- cmd->number = num_attr;
- memcpy(cmd->attrs, p_attrs, num_attr);
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_LIST_PLAYER_ATTRS,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t list_player_app_value_rsp(int num_val, uint8_t *p_vals)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_list_player_values *cmd = (void *) buf;
- size_t len;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (num_val < 0)
- return BT_STATUS_PARM_INVALID;
- len = sizeof(*cmd) + num_val;
- if (len > IPC_MTU)
- return BT_STATUS_PARM_INVALID;
- cmd->number = num_val;
- memcpy(cmd->values, p_vals, num_val);
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_LIST_PLAYER_VALUES,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_get_player_attrs *cmd = (void *) buf;
- size_t len, attrs_len;
- int i;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!p_vals)
- return BT_STATUS_PARM_INVALID;
- attrs_len = p_vals->num_attr *
- sizeof(struct hal_avrcp_player_attr_value);
- len = sizeof(*cmd) + attrs_len;
- if (len > IPC_MTU)
- return BT_STATUS_PARM_INVALID;
- cmd->number = p_vals->num_attr;
- for (i = 0; i < p_vals->num_attr; i++) {
- cmd->attrs[i].attr = p_vals->attr_ids[i];
- cmd->attrs[i].value = p_vals->attr_values[i];
- }
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_GET_PLAYER_ATTRS,
- len, cmd, NULL, NULL, NULL);
- }
- static int write_text(uint8_t *ptr, uint8_t id, uint8_t *text, size_t *len)
- {
- struct hal_avrcp_player_setting_text *value = (void *) ptr;
- size_t attr_len = sizeof(*value);
- if (attr_len + *len > IPC_MTU)
- return 0;
- value->id = id;
- value->len = strnlen((const char *) text, BTRC_MAX_ATTR_STR_LEN);
- *len += attr_len;
- if (value->len + *len > IPC_MTU)
- value->len = IPC_MTU - *len;
- memcpy(value->text, text, value->len);
- *len += value->len;
- return attr_len + value->len;
- }
- static uint8_t write_player_setting_text(uint8_t *ptr, uint8_t num_attr,
- btrc_player_setting_text_t *p_attrs,
- size_t *len)
- {
- int i;
- for (i = 0; i < num_attr && *len < IPC_MTU; i++) {
- int ret;
- ret = write_text(ptr, p_attrs[i].id, p_attrs[i].text, len);
- if (ret == 0)
- break;
- ptr += ret;
- }
- return i;
- }
- static bt_status_t get_player_app_attr_text_rsp(int num_attr,
- btrc_player_setting_text_t *p_attrs)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_get_player_attrs_text *cmd = (void *) buf;
- uint8_t *ptr;
- size_t len;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (num_attr < 0 || num_attr > BTRC_MAX_APP_SETTINGS)
- return BT_STATUS_PARM_INVALID;
- len = sizeof(*cmd);
- ptr = (uint8_t *) &cmd->attrs[0];
- cmd->number = write_player_setting_text(ptr, num_attr, p_attrs, &len);
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t get_player_app_value_text_rsp(int num_val,
- btrc_player_setting_text_t *p_vals)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_get_player_values_text *cmd = (void *) buf;
- uint8_t *ptr;
- size_t len;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (num_val < 0)
- return BT_STATUS_PARM_INVALID;
- len = sizeof(*cmd);
- ptr = (uint8_t *) &cmd->values[0];
- cmd->number = write_player_setting_text(ptr, num_val, p_vals, &len);
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT,
- len, cmd, NULL, NULL, NULL);
- }
- static uint8_t write_element_attr_text(uint8_t *ptr, uint8_t num_attr,
- btrc_element_attr_val_t *p_attrs,
- size_t *len)
- {
- int i;
- for (i = 0; i < num_attr && *len < IPC_MTU; i++) {
- int ret;
- ret = write_text(ptr, p_attrs[i].attr_id, p_attrs[i].text, len);
- if (ret == 0)
- break;
- ptr += ret;
- }
- return i;
- }
- static bt_status_t get_element_attr_rsp(uint8_t num_attr,
- btrc_element_attr_val_t *p_attrs)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_get_element_attrs_text *cmd = (void *) buf;
- size_t len;
- uint8_t *ptr;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- len = sizeof(*cmd);
- ptr = (uint8_t *) &cmd->values[0];
- cmd->number = write_element_attr_text(ptr, num_attr, p_attrs, &len);
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t set_player_app_value_rsp(btrc_status_t rsp_status)
- {
- struct hal_cmd_avrcp_set_player_attrs_value cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- cmd.status = rsp_status;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t play_status_changed_rsp(btrc_notification_type_t type,
- btrc_play_status_t *play_status)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
- size_t len;
- cmd->event = BTRC_EVT_PLAY_STATUS_CHANGED;
- cmd->type = type;
- cmd->len = 1;
- memcpy(cmd->data, play_status, cmd->len);
- len = sizeof(*cmd) + cmd->len;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t track_change_rsp(btrc_notification_type_t type,
- btrc_uid_t *track)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
- size_t len;
- cmd->event = BTRC_EVT_TRACK_CHANGE;
- cmd->type = type;
- cmd->len = sizeof(*track);
- memcpy(cmd->data, track, cmd->len);
- len = sizeof(*cmd) + cmd->len;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t track_reached_end_rsp(btrc_notification_type_t type)
- {
- struct hal_cmd_avrcp_register_notification cmd;
- cmd.event = BTRC_EVT_TRACK_REACHED_END;
- cmd.type = type;
- cmd.len = 0;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t track_reached_start_rsp(btrc_notification_type_t type)
- {
- struct hal_cmd_avrcp_register_notification cmd;
- cmd.event = BTRC_EVT_TRACK_REACHED_START;
- cmd.type = type;
- cmd.len = 0;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t play_pos_changed_rsp(btrc_notification_type_t type,
- uint32_t *song_pos)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
- size_t len;
- cmd->event = BTRC_EVT_PLAY_POS_CHANGED;
- cmd->type = type;
- cmd->len = sizeof(*song_pos);
- memcpy(cmd->data, song_pos, cmd->len);
- len = sizeof(*cmd) + cmd->len;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t settings_changed_rsp(btrc_notification_type_t type,
- btrc_player_settings_t *player_setting)
- {
- char buf[IPC_MTU];
- struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
- struct hal_avrcp_player_attr_value *attrs;
- size_t len, param_len;
- int i;
- param_len = player_setting->num_attr * sizeof(*attrs);
- len = sizeof(*cmd) + param_len;
- if (len > IPC_MTU)
- return BT_STATUS_PARM_INVALID;
- cmd->event = BTRC_EVT_APP_SETTINGS_CHANGED;
- cmd->type = type;
- cmd->len = param_len;
- attrs = (struct hal_avrcp_player_attr_value *) &cmd->data[0];
- for (i = 0; i < player_setting->num_attr; i++) {
- attrs[i].attr = player_setting->attr_ids[i];
- attrs[i].value = player_setting->attr_values[i];
- }
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
- HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- len, cmd, NULL, NULL, NULL);
- }
- static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
- btrc_notification_type_t type,
- btrc_register_notification_t *p_param)
- {
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- switch (event_id) {
- case BTRC_EVT_PLAY_STATUS_CHANGED:
- return play_status_changed_rsp(type, &p_param->play_status);
- case BTRC_EVT_TRACK_CHANGE:
- return track_change_rsp(type, &p_param->track);
- case BTRC_EVT_TRACK_REACHED_END:
- return track_reached_end_rsp(type);
- case BTRC_EVT_TRACK_REACHED_START:
- return track_reached_start_rsp(type);
- case BTRC_EVT_PLAY_POS_CHANGED:
- return play_pos_changed_rsp(type, &p_param->song_pos);
- case BTRC_EVT_APP_SETTINGS_CHANGED:
- return settings_changed_rsp(type, &p_param->player_setting);
- default:
- return BT_STATUS_PARM_INVALID;
- }
- }
- static bt_status_t set_volume(uint8_t volume)
- {
- struct hal_cmd_avrcp_set_volume cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- cmd.value = volume;
- return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static void cleanup(void)
- {
- struct hal_cmd_unregister_module cmd;
- DBG("");
- if (!interface_ready())
- return;
- cmd.service_id = HAL_SERVICE_ID_AVRCP;
- hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
- cbs = NULL;
- }
- static btrc_interface_t iface = {
- .size = sizeof(iface),
- .init = init,
- .get_play_status_rsp = get_play_status_rsp,
- .list_player_app_attr_rsp = list_player_app_attr_rsp,
- .list_player_app_value_rsp = list_player_app_value_rsp,
- .get_player_app_value_rsp = get_player_app_value_rsp,
- .get_player_app_attr_text_rsp = get_player_app_attr_text_rsp,
- .get_player_app_value_text_rsp = get_player_app_value_text_rsp,
- .get_element_attr_rsp = get_element_attr_rsp,
- .set_player_app_value_rsp = set_player_app_value_rsp,
- .register_notification_rsp = register_notification_rsp,
- .set_volume = set_volume,
- .cleanup = cleanup
- };
- btrc_interface_t *bt_get_avrcp_interface(void)
- {
- return &iface;
- }
|