mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-26 21:54:33 +08:00
7d95d027b1
This header contains IPC specific structures and code not related to BT and audio HAL protocols. This allows to fully decouple IPC from HAL messages. This is first step to make HAL part of IPC unit-testable and reusable between BT HAL and audio HAL.
685 lines
16 KiB
C
685 lines
16 KiB
C
/*
|
|
* Copyright (C) 2014 Intel Corporation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <stdlib.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)
|
|
{
|
|
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)
|
|
{
|
|
if (cbs->get_play_status_cb)
|
|
cbs->get_play_status_cb();
|
|
}
|
|
|
|
static void handle_list_player_attrs(void *buf, uint16_t len)
|
|
{
|
|
if (cbs->list_player_app_attr_cb)
|
|
cbs->list_player_app_attr_cb();
|
|
}
|
|
|
|
static void handle_list_player_values(void *buf, uint16_t len)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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;
|
|
|
|
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
|
|
sizeof(cmd), &cmd, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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;
|
|
ptr += 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, NULL, NULL);
|
|
}
|
|
|
|
static void cleanup()
|
|
{
|
|
struct hal_cmd_unregister_module cmd;
|
|
|
|
DBG("");
|
|
|
|
if (!interface_ready())
|
|
return;
|
|
|
|
cbs = NULL;
|
|
|
|
cmd.service_id = HAL_SERVICE_ID_AVRCP;
|
|
|
|
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
|
|
sizeof(cmd), &cmd, 0, NULL, NULL);
|
|
|
|
hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
|
|
}
|
|
|
|
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()
|
|
{
|
|
return &iface;
|
|
}
|