mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-15 04:21:01 +00:00
avrcp: unit info cmd
This commit is contained in:
parent
decc740c46
commit
4217b63bd9
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user