mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-16 08:42:28 +00:00
avrcp: get capabilities draft
This commit is contained in:
parent
7f535380ac
commit
49bbb6f27b
@ -290,8 +290,52 @@ 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;
|
||||
connection->state = AVCTP_CONNECTION_OPENED;
|
||||
avrcp_command_type_t ctype;
|
||||
avrcp_subunit_type_t subunit_type;
|
||||
avrcp_subunit_type_t subunit_id;
|
||||
|
||||
uint8_t operands[5];
|
||||
uint8_t opcode;
|
||||
uint8_t value;
|
||||
int pos = 0;
|
||||
|
||||
uint8_t transport_header = packet[pos++];
|
||||
uint8_t transaction_label = transport_header >> 4;
|
||||
uint8_t packet_type = (transport_header & 0x0F) >> 2;
|
||||
uint8_t frame_type = (transport_header & 0x03) >> 1;
|
||||
uint8_t ipid = transport_header & 0x01;
|
||||
value = packet[pos++];
|
||||
uint16_t pid = (value << 8) | packet[pos++];
|
||||
|
||||
printf("L2CAP DATA, response: ");
|
||||
printf_hexdump(packet, size);
|
||||
|
||||
printf(" Transport header 0x%02x (transaction_label %d, packet_type %d, frame_type %d, ipid %d), pid 0x%4x\n",
|
||||
transport_header, transaction_label, packet_type, frame_type, ipid, pid);
|
||||
switch (connection->cmd_to_send){
|
||||
case AVRCP_CMD_OPCODE_UNIT_INFO:{
|
||||
ctype = packet[pos++];
|
||||
value = packet[pos++];
|
||||
subunit_type = value >> 3;
|
||||
subunit_id = value & 0x07;
|
||||
opcode = packet[pos++];
|
||||
|
||||
// operands:
|
||||
memcpy(operands, packet+pos, 5);
|
||||
uint8_t unit_type = operands[1] >> 3;
|
||||
uint8_t unit = operands[1] & 0x07;
|
||||
uint32_t company_id = operands[2] << 16 | operands[3] << 8 | operands[4];
|
||||
printf(" UNIT INFO response: ctype 0x%02x (0C), subunit_type 0x%02x (1F), subunit_id 0x%02x (07), opcode 0x%02x (30), unit_type 0x%02x, unit %d, company_id 0x%06x\n",
|
||||
ctype, subunit_type, subunit_id, opcode, unit_type, unit, company_id );
|
||||
break;
|
||||
}
|
||||
case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int avrcp_send_cmd(uint16_t cid, avrcp_connection_t * connection){
|
||||
@ -316,20 +360,10 @@ static int avrcp_send_cmd(uint16_t cid, avrcp_connection_t * connection){
|
||||
return l2cap_send(cid, command, sizeof(command));
|
||||
}
|
||||
|
||||
static void avrcp_handle_can_send_now(avrcp_connection_t * connection, uint16_t l2cap_cid){
|
||||
if (!connection->wait_to_send) return;
|
||||
static void avrcp_handle_can_send_now(avrcp_connection_t * connection){
|
||||
if (connection->state != AVCTP_W2_SEND_COMMAND) return;
|
||||
|
||||
if (connection->cmd_to_send){
|
||||
connection->wait_to_send = 0;
|
||||
connection->state = AVCTP_W2_RECEIVE_RESPONSE;
|
||||
avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
|
||||
}
|
||||
|
||||
int more_to_send = connection->wait_to_send;
|
||||
if (more_to_send){
|
||||
l2cap_request_can_send_now_event(l2cap_cid);
|
||||
}
|
||||
connection->state = AVCTP_W2_RECEIVE_RESPONSE;
|
||||
avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
|
||||
}
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
@ -387,7 +421,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
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);
|
||||
avrcp_handle_can_send_now(connection);
|
||||
break;
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_CLOSED:
|
||||
@ -464,12 +498,35 @@ void avrcp_unit_info(uint16_t con_handle){
|
||||
if (connection->state != AVCTP_CONNECTION_OPENED) return;
|
||||
connection->state = AVCTP_W2_SEND_COMMAND;
|
||||
|
||||
connection->cmd_to_send = AVRCP_UNIT_INFO;
|
||||
connection->cmd_to_send = AVRCP_CMD_OPCODE_UNIT_INFO;
|
||||
connection->cmd_operands_lenght = 5;
|
||||
connection->subunit_type = 0x1F;
|
||||
connection->subunit_id = 7;
|
||||
connection->command_type = AVRCP_STATUS_COMMAND;
|
||||
connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT;
|
||||
connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE;
|
||||
connection->command_type = AVRCP_CTYPE_STATUS;
|
||||
connection->transaction_label++;
|
||||
memset(connection->cmd_operands, 0xFF, connection->cmd_operands_lenght);
|
||||
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avrcp_get_capabilities(uint16_t con_handle){
|
||||
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle);
|
||||
if (!connection){
|
||||
log_error("avrcp_unit_info: coud not find a connection.");
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVCTP_CONNECTION_OPENED) return;
|
||||
connection->state = AVCTP_W2_SEND_COMMAND;
|
||||
|
||||
connection->cmd_to_send = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
|
||||
connection->command_type = AVRCP_CTYPE_STATUS;
|
||||
connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
|
||||
connection->subunit_id = 0;
|
||||
connection->transaction_label++;
|
||||
big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID);
|
||||
connection->cmd_operands[3] = 0x10;
|
||||
connection->cmd_operands[4] = 0;
|
||||
big_endian_store_16(connection->cmd_operands, 5, 1);
|
||||
connection->cmd_operands[7] = 0x02;
|
||||
connection->cmd_operands_lenght = 8;
|
||||
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
|
||||
}
|
@ -51,38 +51,58 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BT_SIG_COMPANY_ID 0x001958
|
||||
/* 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_CTYPE_CONTROL = 0,
|
||||
AVRCP_CTYPE_STATUS,
|
||||
AVRCP_CTYPE_SPECIFIC_INQUIRY,
|
||||
AVRCP_CTYPE_NOTIFY,
|
||||
AVRCP_CTYPE_GENERAL_INQUIRY,
|
||||
AVRCP_CTYPE_RESERVED5,
|
||||
AVRCP_CTYPE_RESERVED6,
|
||||
AVRCP_CTYPE_RESERVED7,
|
||||
AVRCP_CTYPE_RESPONSE_NOT_IMPLEMENTED = 8,
|
||||
AVRCP_CTYPE_RESPONSE_ACCEPTED,
|
||||
AVRCP_CTYPE_RESPONSE_REJECTED,
|
||||
AVRCP_CTYPE_RESPONSE_IN_TRANSITION,
|
||||
AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE,
|
||||
AVRCP_CTYPE_RESPONSE_CHANGED_STABLE,
|
||||
AVRCP_CTYPE_RESPONSE_RESERVED,
|
||||
AVRCP_CTYPE_RESPONSE_INTERIM
|
||||
} 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_MONITOR = 0,
|
||||
AVRCP_SUBUNIT_TYPE_AUDIO = 1,
|
||||
AVRCP_SUBUNIT_TYPE_PRINTER,
|
||||
AVRCP_SUBUNIT_TYPE_DISC,
|
||||
AVRCP_SUBUNIT_TYPE_TAPE_RECORDER_PLAYER,
|
||||
AVRCP_SUBUNIT_TYPE_TUNER,
|
||||
AVRCP_SUBUNIT_TYPE_CA,
|
||||
AVRCP_SUBUNIT_TYPE_CAMERA,
|
||||
AVRCP_SUBUNIT_TYPE_RESERVED,
|
||||
AVRCP_SUBUNIT_TYPE_PANEL = 9,
|
||||
AVRCP_SUBUNIT_TYPE_BULLETIN_BOARD,
|
||||
AVRCP_SUBUNIT_TYPE_CAMERA_STORAGE,
|
||||
AVRCP_SUBUNIT_TYPE_VENDOR_UNIQUE = 0x1C,
|
||||
AVRCP_SUBUNIT_TYPE_RESERVED_FOR_ALL_SUBUNIT_TYPES,
|
||||
AVRCP_SUBUNIT_TYPE_EXTENDED_TO_NEXT_BYTE,
|
||||
AVRCP_SUBUNIT_TYPE_UNIT = 0x1F
|
||||
} avrcp_subunit_type_t;
|
||||
|
||||
typedef enum {
|
||||
AVRCP_SUBUNIT_ID = 0,
|
||||
AVRCP_SUBUNIT_ID_IGNORE = 7
|
||||
} avrcp_subunit_id_t;
|
||||
|
||||
typedef enum{
|
||||
AVRCP_CMD_NONE = 0,
|
||||
AVRCP_UNIT_INFO = 0x30
|
||||
AVRCP_CMD_OPCODE_VENDOR_DEPENDENT = 0x00,
|
||||
AVRCP_CMD_OPCODE_RESERVE = 0x01,
|
||||
AVRCP_CMD_OPCODE_UNIT_INFO = 0x30,
|
||||
AVRCP_CMD_OPCODE_SUBUNIT_INFO = 0x31,
|
||||
AVRCP_CMD_OPCODE_VERSION = 0xB0,
|
||||
AVRCP_CMD_OPCODE_POWER = 0xB2
|
||||
} avrcp_command_opcode_t;
|
||||
|
||||
typedef enum {
|
||||
@ -108,8 +128,8 @@ typedef struct {
|
||||
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];
|
||||
avrcp_subunit_id_t subunit_id;
|
||||
uint8_t cmd_operands[20];
|
||||
uint8_t cmd_operands_lenght;
|
||||
} avrcp_connection_t;
|
||||
|
||||
@ -154,11 +174,17 @@ void avrcp_register_packet_handler(btstack_packet_handler_t callback);
|
||||
void avrcp_connect(bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Pause.
|
||||
* @brief Unit info.
|
||||
* @param con_handle
|
||||
*/
|
||||
void avrcp_unit_info(uint16_t con_handle);
|
||||
|
||||
/**
|
||||
* @brief Unit info.
|
||||
* @param con_handle
|
||||
*/
|
||||
void avrcp_get_capabilities(uint16_t con_handle);
|
||||
|
||||
|
||||
/* API_END */
|
||||
#if defined __cplusplus
|
||||
|
@ -114,6 +114,8 @@ static void show_usage(void){
|
||||
printf("c - create connection to addr %s\n", bd_addr_to_str(remote));
|
||||
printf("C - disconnect\n");
|
||||
printf("u - get unit info\n");
|
||||
printf("p - get capabilities\n");
|
||||
|
||||
printf("Ctrl-c - exit\n");
|
||||
printf("---\n");
|
||||
}
|
||||
@ -133,6 +135,10 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
printf("u - get unit info\n");
|
||||
avrcp_unit_info(con_handle);
|
||||
break;
|
||||
case 'p':
|
||||
printf("p - get capabilities\n");
|
||||
avrcp_get_capabilities(con_handle);
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user