diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index cd0a736..ad7742d 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
GDestroyNotify destroy;
};
-struct avrcp {
- struct avrcp_server *server;
- struct avctp *conn;
- struct btd_device *dev;
+struct avrcp_data {
struct avrcp_player *player;
- gboolean target;
uint16_t version;
int features;
GSList *players;
+};
- void (*init_control) (struct avrcp *session);
- void (*init_browsing) (struct avrcp *session);
- void (*destroy) (struct avrcp *sesion);
+struct avrcp {
+ struct avrcp_server *server;
+ struct avctp *conn;
+ struct btd_device *dev;
+ struct avrcp_data *target;
+ struct avrcp_data *controller;
const struct passthrough_handler *passthrough_handlers;
const struct control_pdu_handler *control_handlers;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
uint64_t identifier = bt_get_le64(&pdu->params[0]);
uint16_t pos;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
uint8_t *settings;
unsigned int i;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
uint8_t *param;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
uint32_t position;
uint32_t duration;
static bool avrcp_handle_play(struct avrcp *session)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
- if (session->player == NULL)
+ if (player == NULL)
return false;
return player->cb->play(player->user_data);
static bool avrcp_handle_stop(struct avrcp *session)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
- if (session->player == NULL)
+ if (player == NULL)
return false;
return player->cb->stop(player->user_data);
static bool avrcp_handle_pause(struct avrcp *session)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
- if (session->player == NULL)
+ if (player == NULL)
return false;
return player->cb->pause(player->user_data);
static bool avrcp_handle_next(struct avrcp *session)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
- if (session->player == NULL)
+ if (player == NULL)
return false;
return player->cb->next(player->user_data);
static bool avrcp_handle_previous(struct avrcp *session)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
- if (session->player == NULL)
+ if (player == NULL)
return false;
return player->cb->previous(player->user_data);
}
-static const struct passthrough_handler tg_passthrough_handlers[] = {
+static const struct passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, avrcp_handle_play },
{ AVC_STOP, avrcp_handle_stop },
{ AVC_PAUSE, avrcp_handle_pause },
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
struct btd_device *dev = session->dev;
uint16_t len = ntohs(pdu->params_len);
uint64_t uid;
break;
case AVRCP_EVENT_TRACK_CHANGED:
len = 9;
- uid = player_get_uid(player);
+ uid = player_get_uid(session->target->player);
memcpy(&pdu->params[1], &uid, sizeof(uint64_t));
break;
break;
case AVRCP_EVENT_VOLUME_CHANGED:
- if (session->version < 0x0104)
- goto err;
-
pdu->params[1] = media_transport_get_device_volume(dev);
if (pdu->params[1] > 127)
goto err;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint16_t len = ntohs(pdu->params_len);
struct pending_pdu *pending;
struct avrcp_header *pdu,
uint8_t transaction)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
uint16_t len = ntohs(pdu->params_len);
uint8_t volume;
return AVC_CTYPE_REJECTED;
}
-static const struct control_pdu_handler tg_control_handlers[] = {
+static const struct control_pdu_handler control_handlers[] = {
{ AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
avrcp_handle_get_capabilities },
{ AVRCP_LIST_PLAYER_ATTRIBUTES, AVC_CTYPE_STATUS,
avrcp_handle_get_play_status },
{ AVRCP_REGISTER_NOTIFICATION, AVC_CTYPE_NOTIFY,
avrcp_handle_register_notification },
+ { AVRCP_SET_ABSOLUTE_VOLUME, AVC_CTYPE_CONTROL,
+ avrcp_handle_set_absolute_volume },
{ AVRCP_REQUEST_CONTINUING, AVC_CTYPE_CONTROL,
avrcp_handle_request_continuing },
{ AVRCP_ABORT_CONTINUING, AVC_CTYPE_CONTROL,
{ },
};
-static const struct control_pdu_handler ct_control_handlers[] = {
- { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
- avrcp_handle_get_capabilities },
- { AVRCP_REGISTER_NOTIFICATION, AVC_CTYPE_NOTIFY,
- avrcp_handle_register_notification },
- { AVRCP_SET_ABSOLUTE_VOLUME, AVC_CTYPE_CONTROL,
- avrcp_handle_set_absolute_volume },
- { },
-};
-
/* handle vendordep pdu inside an avctp packet */
static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
uint8_t *code, uint8_t *subunit,
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
struct avrcp_header *pdu = (void *) operands;
uint32_t duration;
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
struct avrcp_header *pdu = (void *) operands;
uint8_t count;
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct avrcp_header *pdu = (void *) operands;
uint8_t count;
name[namelen] = '\0';
}
- player = session->player;
+ player = session->controller->player;
mp = player->user_data;
item = media_player_create_item(mp, name, PLAYER_ITEM_TYPE_AUDIO, uid);
static struct media_item *parse_media_folder(struct avrcp *session,
uint8_t *operands, uint16_t len)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
uint16_t namelen;
char name[255];
{
struct avrcp_browsing_header *pdu = (void *) operands;
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct pending_list_items *p = player->p;
uint16_t count;
uint32_t items, total;
{
uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 10 +
AVRCP_MEDIA_ATTRIBUTE_LAST * sizeof(uint32_t)];
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct avrcp_browsing_header *pdu = (void *) buf;
uint16_t length = AVRCP_BROWSING_HEADER_LENGTH + 10;
uint32_t attribute;
{
struct avrcp_browsing_header *pdu = (void *) operands;
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
int ret;
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
struct avrcp_browsing_header *pdu = (void *) operands;
uint32_t items;
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct avrcp_browsing_header *pdu = (void *) operands;
uint8_t count;
static void avrcp_get_item_attributes(struct avrcp *session, uint64_t uid)
{
+ struct avrcp_player *player = session->controller->player;
uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 12];
struct avrcp_browsing_header *pdu = (void *) buf;
pdu->pdu_id = AVRCP_GET_ITEM_ATTRIBUTES;
pdu->params[0] = 0x03;
bt_put_be64(uid, &pdu->params[1]);
- bt_put_be16(session->player->uid_counter, &pdu->params[9]);
+ bt_put_be16(player->uid_counter, &pdu->params[9]);
pdu->param_len = htons(12);
avctp_send_browsing_req(session->conn, buf, sizeof(buf),
if (session == NULL)
return false;
- if (session->version < 0x0103)
+ if (session->controller->version < 0x0103)
return false;
attr = attr_to_val(key);
static void avrcp_change_path(struct avrcp *session, uint8_t direction,
uint64_t uid)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 11];
struct avrcp_browsing_header *pdu = (void *) buf;
{
struct avrcp_browsing_header *pdu = (void *) operands;
struct avrcp *session = (void *) user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
int ret;
static void avrcp_play_item(struct avrcp *session, uint64_t uid)
{
uint8_t buf[AVRCP_HEADER_LENGTH + 11];
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct avrcp_header *pdu = (void *) buf;
uint16_t length;
static void avrcp_add_to_nowplaying(struct avrcp *session, uint64_t uid)
{
uint8_t buf[AVRCP_HEADER_LENGTH + 11];
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct avrcp_header *pdu = (void *) buf;
uint16_t length;
player->user_data = mp;
player->destroy = (GDestroyNotify) media_player_destroy;
- if (session->player == NULL)
- session->player = player;
+ if (session->controller->player == NULL)
+ session->controller->player = player;
- session->players = g_slist_prepend(session->players, player);
+ session->controller->players = g_slist_prepend(
+ session->controller->players,
+ player);
return player;
}
{
GSList *l;
- for (l = session->players; l; l = l->next) {
+ for (l = session->controller->players; l; l = l->next) {
struct avrcp_player *player = l->data;
if (player->id == 0) {
media_player_set_name(mp, name);
}
- if (session->player == player && !player->browsed)
+ if (session->controller->player == player && !player->browsed)
avrcp_set_browsed_player(session, player);
return player;
for (l = player->sessions; l; l = l->next) {
struct avrcp *session = l->data;
- session->players = g_slist_remove(session->players, player);
+ session->controller->players = g_slist_remove(
+ session->controller->players,
+ player);
}
player_destroy(player);
operand_count < 5)
return FALSE;
- removed = g_slist_copy(session->players);
+ removed = g_slist_copy(session->controller->players);
count = bt_get_be16(&operands[6]);
for (i = 8; count && i < operand_count; count--) {
i += len;
}
- if (g_slist_find(removed, session->player))
- session->player = NULL;
+ if (g_slist_find(removed, session->controller->player))
+ session->controller->player = NULL;
g_slist_free_full(removed, player_remove);
static void avrcp_volume_changed(struct avrcp *session,
struct avrcp_header *pdu)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
uint8_t volume;
if (player == NULL)
static void avrcp_status_changed(struct avrcp *session,
struct avrcp_header *pdu)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
uint8_t value;
const char *curval, *strval;
struct avrcp_header *pdu)
{
if (session->browsing_id) {
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
player->uid = bt_get_be64(&pdu->params[1]);
avrcp_get_item_attributes(session, player->uid);
} else
static void avrcp_setting_changed(struct avrcp *session,
struct avrcp_header *pdu)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
struct media_player *mp = player->user_data;
uint8_t count = pdu->params[1];
int i;
static void avrcp_addressed_player_changed(struct avrcp *session,
struct avrcp_header *pdu)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
uint16_t id = bt_get_be16(&pdu->params[1]);
if (player != NULL && player->id == id)
}
player->uid_counter = bt_get_be16(&pdu->params[3]);
- session->player = player;
+ session->controller->player = player;
if (player->features != NULL)
return;
static void avrcp_uids_changed(struct avrcp *session, struct avrcp_header *pdu)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->controller->player;
player->uid_counter = bt_get_be16(&pdu->params[1]);
}
session->browsing_id = 0;
}
-static void session_tg_init_browsing(struct avrcp *session)
+static void session_init_browsing(struct avrcp *session)
{
session->browsing_id = avctp_register_browsing_pdu_handler(
session->conn,
destroy_browsing);
}
-static void session_tg_init_control(struct avrcp *session)
+static struct avrcp_data *data_init(struct avrcp *session, const char *uuid)
+{
+ struct avrcp_data *data;
+ const sdp_record_t *rec;
+ sdp_list_t *list;
+ sdp_profile_desc_t *desc;
+
+ data = g_new0(struct avrcp_data, 1);
+
+ rec = btd_device_get_record(session->dev, uuid);
+ if (rec == NULL)
+ return data;
+
+ if (sdp_get_profile_descs(rec, &list) == 0) {
+ desc = list->data;
+ data->version = desc->version;
+ }
+
+ sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES, &data->features);
+ sdp_list_free(list, free);
+
+ return data;
+}
+
+static void target_init(struct avrcp *session)
{
struct avrcp_server *server = session->server;
+ struct avrcp_data *target;
struct avrcp_player *player;
struct btd_service *service;
+ btd_service_state_t old_state = BTD_SERVICE_STATE_UNAVAILABLE;
- if (session->version < 0x0103)
+ if (session->target != NULL)
return;
- DBG("%p version 0x%04x", session, session->version);
+ target = data_init(session, AVRCP_REMOTE_UUID);
+ session->target = target;
+
+ DBG("%p version 0x%04x", target, target->version);
+
+ service = btd_device_get_service(session->dev, AVRCP_REMOTE_UUID);
+ if (service != NULL) {
+ old_state = btd_service_get_state(service);
+ btd_service_connecting_complete(service, 0);
+ }
+
+ if (target->version < 0x0103)
+ return;
player = g_slist_nth_data(server->players, 0);
if (player != NULL) {
- session->player = player;
+ target->player = player;
player->sessions = g_slist_prepend(player->sessions, session);
}
- session->passthrough_id = avctp_register_passthrough_handler(
- session->conn,
- handle_passthrough,
- session);
- session->passthrough_handlers = tg_passthrough_handlers;
- session->control_id = avctp_register_pdu_handler(session->conn,
- AVC_OP_VENDORDEP,
- handle_vendordep_pdu,
- session);
- session->control_handlers = tg_control_handlers;
- session->supported_events = (1 << AVRCP_EVENT_STATUS_CHANGED) |
+ session->supported_events |= (1 << AVRCP_EVENT_STATUS_CHANGED) |
(1 << AVRCP_EVENT_TRACK_CHANGED) |
(1 << AVRCP_EVENT_TRACK_REACHED_START) |
(1 << AVRCP_EVENT_TRACK_REACHED_END) |
(1 << AVRCP_EVENT_SETTINGS_CHANGED);
- if (session->version >= 0x0104)
- avrcp_register_notification(session,
- AVRCP_EVENT_VOLUME_CHANGED);
+ if (target->version < 0x0104)
+ return;
- service = btd_device_get_service(session->dev, AVRCP_REMOTE_UUID);
- if (service != NULL)
- btd_service_connecting_complete(service, 0);
-}
+ avrcp_register_notification(session, AVRCP_EVENT_VOLUME_CHANGED);
-static void session_ct_init_browsing(struct avrcp *session)
-{
- session->browsing_id = avctp_register_browsing_pdu_handler(
- session->conn,
- handle_browsing_pdu,
- session,
- destroy_browsing);
+ /* Auto-connect browsing channel only if initiator */
+ if (old_state == BTD_SERVICE_STATE_CONNECTING &&
+ target->features & AVRCP_FEATURE_BROWSING)
+ avctp_connect_browsing(session->conn);
}
-static void session_ct_init_control(struct avrcp *session)
+static void controller_init(struct avrcp *session)
{
struct avrcp_player *player;
struct btd_service *service;
+ struct avrcp_data *controller;
+ btd_service_state_t old_state = BTD_SERVICE_STATE_UNAVAILABLE;
- DBG("%p version 0x%04x", session, session->version);
+ if (session->controller != NULL)
+ return;
- session->control_id = avctp_register_pdu_handler(session->conn,
- AVC_OP_VENDORDEP,
- handle_vendordep_pdu,
- session);
- session->control_handlers = ct_control_handlers;
- if (session->version >= 0x0104)
- session->supported_events = (1 << AVRCP_EVENT_VOLUME_CHANGED);
+ controller = data_init(session, AVRCP_TARGET_UUID);
+ session->controller = controller;
+
+ DBG("%p version 0x%04x", controller, controller->version);
+
+ if (controller->version >= 0x0104)
+ session->supported_events |= (1 << AVRCP_EVENT_VOLUME_CHANGED);
service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
- if (service != NULL)
+ if (service != NULL) {
+ old_state = btd_service_get_state(service);
btd_service_connecting_complete(service, 0);
+ }
+
+ /* Only create player if category 1 is supported */
+ if (!(controller->features & AVRCP_FEATURE_CATEGORY_1))
+ return;
player = create_ct_player(session, 0);
if (player == NULL)
return;
- if (session->version < 0x0103)
+ if (controller->version < 0x0103)
return;
avrcp_get_capabilities(session);
+
+ if (controller->version < 0x0104)
+ return;
+
+ /* Auto-connect browsing channel only if initiator */
+ if (old_state == BTD_SERVICE_STATE_CONNECTING &&
+ controller->features & AVRCP_FEATURE_BROWSING)
+ avctp_connect_browsing(session->conn);
}
-static void session_destroy(struct avrcp *session)
+static void session_init_control(struct avrcp *session)
{
- struct avrcp_server *server = session->server;
+ session->passthrough_id = avctp_register_passthrough_handler(
+ session->conn,
+ handle_passthrough,
+ session);
+ session->passthrough_handlers = passthrough_handlers;
+ session->control_id = avctp_register_pdu_handler(session->conn,
+ AVC_OP_VENDORDEP,
+ handle_vendordep_pdu,
+ session);
+ session->control_handlers = control_handlers;
- server->sessions = g_slist_remove(server->sessions, session);
+ if (btd_device_get_service(session->dev, AVRCP_TARGET_UUID) != NULL)
+ controller_init(session);
- if (session->passthrough_id > 0)
- avctp_unregister_passthrough_handler(session->passthrough_id);
+ if (btd_device_get_service(session->dev, AVRCP_REMOTE_UUID) != NULL)
+ target_init(session);
+}
- if (session->control_id > 0)
- avctp_unregister_pdu_handler(session->control_id);
+static void controller_destroy(struct avrcp *session)
+{
+ struct avrcp_data *controller = session->controller;
+ struct btd_service *service;
- if (session->browsing_id > 0)
- avctp_unregister_browsing_pdu_handler(session->browsing_id);
+ DBG("%p", controller);
- g_free(session);
+ g_slist_free_full(controller->players, player_destroy);
+
+ service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
+
+ if (session->control_id == 0)
+ btd_service_connecting_complete(service, -EIO);
+ else
+ btd_service_disconnecting_complete(service, 0);
+
+ g_free(controller);
}
-static void session_tg_destroy(struct avrcp *session)
+static void target_destroy(struct avrcp *session)
{
- struct avrcp_player *player = session->player;
+ struct avrcp_data *target = session->target;
+ struct avrcp_player *player = target->player;
struct btd_service *service;
- DBG("%p", session);
+ DBG("%p", target);
if (player != NULL)
player->sessions = g_slist_remove(player->sessions, session);
service = btd_device_get_service(session->dev, AVRCP_REMOTE_UUID);
- if (service == NULL)
- return session_destroy(session);
if (session->control_id == 0)
btd_service_connecting_complete(service, -EIO);
else
btd_service_disconnecting_complete(service, 0);
- session_destroy(session);
+ g_free(target);
}
-static void session_ct_destroy(struct avrcp *session)
+static void session_destroy(struct avrcp *session)
{
- struct btd_service *service;
+ struct avrcp_server *server = session->server;
- DBG("%p", session);
+ server->sessions = g_slist_remove(server->sessions, session);
- g_slist_free_full(session->players, player_destroy);
+ if (session->controller != NULL)
+ controller_destroy(session);
- service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
- if (service == NULL)
- return session_destroy(session);
+ if (session->target != NULL)
+ target_destroy(session);
- if (session->control_id == 0)
- btd_service_connecting_complete(service, -EIO);
- else
- btd_service_disconnecting_complete(service, 0);
+ if (session->passthrough_id > 0)
+ avctp_unregister_passthrough_handler(session->passthrough_id);
- session_destroy(session);
+ if (session->control_id > 0)
+ avctp_unregister_pdu_handler(session->control_id);
+
+ if (session->browsing_id > 0)
+ avctp_unregister_browsing_pdu_handler(session->browsing_id);
+
+ g_free(session);
}
static struct avrcp *session_create(struct avrcp_server *server,
struct btd_device *device)
{
struct avrcp *session;
- const sdp_record_t *rec;
- sdp_list_t *list;
- sdp_profile_desc_t *desc;
- struct btd_service *sink, *source;
session = g_new0(struct avrcp, 1);
session->server = server;
server->sessions = g_slist_append(server->sessions, session);
- sink = btd_device_get_service(device, A2DP_SINK_UUID);
- source = btd_device_get_service(device, A2DP_SOURCE_UUID);
-
- /* If sink and source are not supported assume the controller must
- * be the initiator
- */
- if (sink == NULL && source == NULL)
- session->target = !avctp_is_initiator(session->conn);
- else if (sink && !source)
- session->target = TRUE;
- else if (source && !sink)
- session->target = FALSE;
- else if (sink && sink_is_active(sink))
- session->target = TRUE;
- else
- session->target = FALSE;
-
- if (session->target) {
- session->init_control = session_tg_init_control;
- session->init_browsing = session_tg_init_browsing;
- session->destroy = session_tg_destroy;
-
- rec = btd_device_get_record(device, AVRCP_REMOTE_UUID);
- if (rec == NULL)
- btd_device_add_uuid(device, AVRCP_REMOTE_UUID);
- } else {
- session->init_control = session_ct_init_control;
- session->init_browsing = session_ct_init_browsing;
- session->destroy = session_ct_destroy;
- rec = btd_device_get_record(device, AVRCP_TARGET_UUID);
- if (rec == NULL)
- btd_device_add_uuid(device, AVRCP_TARGET_UUID);
- }
-
- if (rec == NULL)
- return session;
-
- if (sdp_get_profile_descs(rec, &list) < 0)
- return session;
-
- desc = list->data;
- session->version = desc->version;
- sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES, &session->features);
-
- sdp_list_free(list, free);
-
return session;
}
if (session == NULL)
break;
- session->destroy(session);
+ session_destroy(session);
break;
case AVCTP_STATE_CONNECTING:
if (session == NULL || session->control_id > 0)
break;
- session->init_control(session);
-
- if (session->version >= 0x0104 &&
- session->features & AVRCP_FEATURE_BROWSING)
- avctp_connect_browsing(session->conn);
+ session_init_control(session);
break;
case AVCTP_STATE_BROWSING_CONNECTED:
if (session == NULL || session->browsing_id > 0)
break;
- session->init_browsing(session);
+ session_init_browsing(session);
+
break;
default:
return;
/* Assign player to session without current player */
for (l = server->sessions; l; l = l->next) {
struct avrcp *session = l->data;
+ struct avrcp_data *target = session->target;
- if (session->player == NULL) {
- session->player = player;
+ if (target == NULL)
+ continue;
+
+ if (target->player == NULL) {
+ target->player = player;
player->sessions = g_slist_append(player->sessions,
session);
}
/* Remove player from sessions using it */
for (l = player->sessions; l; l = l->next) {
struct avrcp *session = l->data;
+ struct avrcp_data *target = session->target;
+
+ if (target == NULL)
+ continue;
- if (session->player == player)
- session->player = g_slist_nth_data(server->players, 0);
+ if (target->player == player)
+ target->player = g_slist_nth_data(server->players, 0);
}
player_destroy(player);
void *user_data)
{
struct avrcp *session = user_data;
- struct avrcp_player *player = session->player;
+ struct avrcp_player *player = session->target->player;
struct avrcp_header *pdu = (void *) operands;
uint8_t volume;
return -EINVAL;
session = find_session(server->sessions, dev);
- if (session == NULL)
+ if (session == NULL || session->target == NULL)
return -ENOTCONN;
- if (session->version < 0x0104)
+ if (session->target->version < 0x0104)
return -ENOTSUP;
memset(buf, 0, sizeof(buf));