avrcp: unit info cmd

This commit is contained in:
Milanka Ringwald 2017-01-31 17:49:38 +01:00 committed by Matthias Ringwald
parent decc740c46
commit 4217b63bd9
3 changed files with 91 additions and 32 deletions

View File

@ -82,6 +82,18 @@ Bit 8-15 = RFA
The bits for supported categories are set to 1. Others are set to 0.
*/
// TODO: merge with avdtp_packet_type_t
typedef enum {
AVRCP_SINGLE_PACKET= 0,
AVRCP_START_PACKET ,
AVRCP_CONTINUE_PACKET ,
AVRCP_END_PACKET
} avrcp_packet_type_t;
typedef enum {
AVRCP_COMMAND_FRAME = 0,
AVRCP_RESPONSE_FRAME
} avrcp_frame_type_t;
static const char * default_avrcp_controller_service_name = "BTstack AVRCP Controller Service";
static const char * default_avrcp_controller_service_provider_name = "BTstack AVRCP Controller Service Provider";
@ -218,7 +230,7 @@ static void avrcp_emit_connection_established(btstack_packet_handler_t callback,
if (!callback) return;
uint8_t event[14];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_CONNECTION_ESTABLISHED;
little_endian_store_16(event, pos, con_handle);
@ -235,7 +247,7 @@ static void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint
if (!callback) return;
uint8_t event[5];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_CONNECTION_CLOSED;
little_endian_store_16(event, pos, con_handle);
@ -278,18 +290,29 @@ static avrcp_connection_t * get_avrcp_connection_for_l2cap_signaling_cid(uint16_
static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){
if (connection->state != AVCTP_W2_RECEIVE_RESPONSE) return;
printf("L2CAP DATA, response\n");
printf("L2CAP DATA, response: ");
printf_hexdump(packet, size);
}
static int avrcp_send_cmd(uint16_t cid, avrcp_command_t cmd_to_send, uint8_t * cmd_operands, uint8_t cmd_operands_lenght){
static int avrcp_send_cmd(uint16_t cid, avrcp_connection_t * connection){
uint8_t command[20];
int pos = 0;
command[pos++] = 1;
command[pos++] = (0x1F << 3) | 7;
command[pos++] = (uint8_t)cmd_to_send;
memcpy(command+pos, cmd_operands, cmd_operands_lenght);
pos += cmd_operands_lenght;
// transport header
// Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
// Profile IDentifier (PID)
command[pos++] = AV_REMOTE_CONTROL >> 8;
command[pos++] = AV_REMOTE_CONTROL & 0x00FF;
// command_type
command[pos++] = connection->command_type;
// subunit_type | subunit ID
command[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
// opcode
command[pos++] = (uint8_t)connection->cmd_to_send;
// operands
memcpy(command+pos, connection->cmd_operands, connection->cmd_operands_lenght);
pos += connection->cmd_operands_lenght;
return l2cap_send(cid, command, sizeof(command));
}
@ -300,7 +323,7 @@ static void avrcp_handle_can_send_now(avrcp_connection_t * connection, uint16_t
if (connection->cmd_to_send){
connection->wait_to_send = 0;
connection->state = AVCTP_W2_RECEIVE_RESPONSE;
avrcp_send_cmd(connection->l2cap_signaling_cid, connection->cmd_to_send, connection->cmd_operands, connection->cmd_operands_lenght);
avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
}
int more_to_send = connection->wait_to_send;
@ -322,17 +345,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
if (!connection) break;
avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);
break;
case L2CAP_EVENT_CAN_SEND_NOW:
connection = get_avrcp_connection_for_l2cap_signaling_cid(channel);
if (!connection) break;
avrcp_handle_can_send_now(connection, channel);
break;
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case L2CAP_EVENT_INCOMING_CONNECTION:
l2cap_event_incoming_connection_get_address(packet, event_addr);
local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
printf("avrcp: incoming connection with cid %02x\n", local_cid);
break;
case L2CAP_EVENT_CHANNEL_OPENED:
@ -345,7 +363,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
psm = l2cap_event_channel_opened_get_psm(packet);
if (psm != PSM_AVCTP){
log_error("unexpected PSM - Not implemented yet, avdtp sink: L2CAP_EVENT_CHANNEL_OPENED");
log_error("unexpected PSM - Not implemented yet: L2CAP_EVENT_CHANNEL_OPENED");
return;
}
@ -354,12 +372,10 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
con_handle = l2cap_event_channel_opened_get_handle(packet);
local_cid = l2cap_event_channel_opened_get_local_cid(packet);
printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet));
printf("channel %d, size %d\n", channel, size);
// printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
// bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet));
if (connection->l2cap_signaling_cid == 0) {
if (connection->state != AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) break;
connection->l2cap_signaling_cid = local_cid;
connection->con_handle = con_handle;
connection->state = AVCTP_CONNECTION_OPENED;
@ -368,6 +384,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
break;
case L2CAP_EVENT_CAN_SEND_NOW:
connection = get_avrcp_connection_for_l2cap_signaling_cid(channel);
if (!connection) break;
avrcp_handle_can_send_now(connection, channel);
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
// data: event (8), len(8), channel (16)
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
@ -407,7 +429,7 @@ static avrcp_connection_t * avrcp_create_connection(bd_addr_t remote_addr){
avrcp_connection_t * connection = btstack_memory_avrcp_connection_get();
memset(connection, 0, sizeof(avrcp_connection_t));
connection->state = AVCTP_CONNECTION_IDLE;
connection->transaction_label++;
connection->transaction_label = 0xFF;
memcpy(connection->remote_addr, remote_addr, 6);
btstack_linked_list_add(&avrcp_connections, (btstack_linked_item_t *) connection);
return connection;
@ -441,9 +463,13 @@ void avrcp_unit_info(uint16_t con_handle){
}
if (connection->state != AVCTP_CONNECTION_OPENED) return;
connection->state = AVCTP_W2_SEND_COMMAND;
// TODO: use bitmap
connection->cmd_to_send = AVRCP_UNIT_INFO;
connection->cmd_operands_lenght = 5;
connection->subunit_type = 0x1F;
connection->subunit_id = 7;
connection->command_type = AVRCP_STATUS_COMMAND;
connection->transaction_label++;
memset(connection->cmd_operands, 0xFF, connection->cmd_operands_lenght);
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
}

View File

@ -52,11 +52,38 @@ extern "C" {
#endif
/* API_START */
typedef enum {
AVRCP_CONTROL_COMMAND = 0,
AVRCP_STATUS_COMMAND,
AVRCP_INQUIRY_COMMAND,
AVRCP_NOTIFY_COMMAND,
AVRCP_NOTIFY_RESERVED4_COMMAND,
AVRCP_NOTIFY_RESERVED5_COMMAND,
AVRCP_NOTIFY_RESERVED6_COMMAND,
AVRCP_NOTIFY_RESERVED7_COMMAND,
AVRCP_NOT_IMPLEMENTED_RESPONSE = 8,
AVRCP_ACCEPTED_RESPONSE,
AVRCP_REJECTED_RESPONSE,
AVRCP_IN_TRANSITION_RESPONSE,
AVRCP_IMPLEMENTED_STABLE_RESPONSE,
AVRCP_CHANGED_STABLE_RESPONSE,
AVRCP_RESERVED_RESPONSE,
AVRCP_INTERIM_RESPONSE
} avrcp_command_type_t;
typedef enum {
AVRCP_SUBUNIT_TYPE_VIDEO_MONITOR = 0,
AVRCP_SUBUNIT_TYPE_AVIDEO_CASSETTE_RECORDER = 4,
AVRCP_SUBUNIT_TYPE_TV_TUNER = 5,
AVRCP_SUBUNIT_TYPE_VIDEO_CAMERA = 7,
AVRCP_SUBUNIT_TYPE_VENDOR_UNIQUE = 0x1C,
AVRCP_SUBUNIT_TYPE_UNIT = 0x1F
} avrcp_subunit_type_t;
typedef enum{
AVRCP_CMD_NONE = 0,
AVRCP_UNIT_INFO = 0x30
} avrcp_command_t;
} avrcp_command_opcode_t;
typedef enum {
AVCTP_CONNECTION_IDLE,
@ -72,12 +99,16 @@ typedef struct {
bd_addr_t remote_addr;
hci_con_handle_t con_handle;
uint16_t l2cap_signaling_cid;
uint16_t transaction_label;
avctp_connection_state_t state;
uint8_t wait_to_send;
avrcp_command_t cmd_to_send;
// command
uint8_t transaction_label;
avrcp_command_opcode_t cmd_to_send;
avrcp_command_type_t command_type;
avrcp_subunit_type_t subunit_type;
avrcp_subunit_type_t subunit_id;
uint8_t cmd_operands[5];
uint8_t cmd_operands_lenght;
} avrcp_connection_t;

View File

@ -59,10 +59,12 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
// mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3};
// pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
// mac 2013: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
// static uint16_t con_handle = 0;
// phone: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
static bd_addr_t remote = {0xD8, 0xBB, 0x2C, 0xDF, 0xF1, 0x08};
static uint16_t con_handle = 0;
static uint8_t sdp_avrcp_controller_service_buffer[150];
static uint16_t con_handle;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
@ -77,7 +79,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
// connection closed -> quit test app
printf("--- avrcp_test: HCI_EVENT_DISCONNECTION_COMPLETE\n");
break;
case HCI_EVENT_AVDTP_META:
case HCI_EVENT_AVRCP_META:
switch (packet[2]){
case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED:
con_handle = avrcp_subevent_connection_established_get_con_handle(packet);
@ -161,7 +163,7 @@ int btstack_main(int argc, const char * argv[]){
gap_set_local_name("BTstack AVRCP Test");
gap_discoverable_control(1);
gap_set_class_of_device(0x200408);
// gap_set_class_of_device(0x200408);
// turn on!
hci_power_control(HCI_POWER_ON);