avrcp browsing: register l2cap service only once, move connection establishment to avrcp.c

This commit is contained in:
Milanka Ringwald 2020-05-18 11:45:39 +02:00 committed by Matthias Ringwald
parent 12c4a6eeaf
commit 0eebc13233
5 changed files with 196 additions and 116 deletions

View File

@ -80,8 +80,10 @@
// iPhone 5S: static const char * device_addr_string = "54:E4:3A:26:A2:39"; // iPhone 5S: static const char * device_addr_string = "54:E4:3A:26:A2:39";
// phone 2013: // phone 2013:
// static const char * device_addr_string = "B0:34:95:CB:97:C4"; // static const char * device_addr_string = "B0:34:95:CB:97:C4";
// iPod // iPod
static const char * device_addr_string = "B0:34:95:CB:97:C4"; // static const char * device_addr_string = "B0:34:95:CB:97:C4";
// iPhone
static const char * device_addr_string = "6C:72:E7:10:22:EE";
static bd_addr_t device_addr; static bd_addr_t device_addr;
#endif #endif
@ -157,12 +159,12 @@ static int next_player_index(void){
* SDP record and register it with the SDP service. * SDP record and register it with the SDP service.
* You'll also need to register several packet handlers: * You'll also need to register several packet handlers:
* - stdin_process callback - used to trigger AVRCP commands, such are get media players, playlists, albums, etc. Requires HAVE_BTSTACK_STDIN. * - stdin_process callback - used to trigger AVRCP commands, such are get media players, playlists, albums, etc. Requires HAVE_BTSTACK_STDIN.
* - avrcp_browsing_controller_packet_handler - used to receive answers for AVRCP commands. * - avrcp_browsing_packet_handler - used to receive answers for AVRCP commands.
* *
*/ */
/* LISTING_START(MainConfiguration): Setup Audio Sink and AVRCP Controller services */ /* LISTING_START(MainConfiguration): Setup Audio Sink and AVRCP Controller services */
static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_browsing_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
#ifdef HAVE_BTSTACK_STDIN #ifdef HAVE_BTSTACK_STDIN
@ -188,10 +190,15 @@ int btstack_main(int argc, const char * argv[]){
avrcp_controller_register_packet_handler(&avrcp_packet_handler); avrcp_controller_register_packet_handler(&avrcp_packet_handler);
avrcp_target_register_packet_handler(&avrcp_packet_handler); avrcp_target_register_packet_handler(&avrcp_packet_handler);
// Initialize AVRCP Browsing Controller, HCI events will be sent to the AVRCP Controller callback. // Initialize AVRCP Browsing Service.
avrcp_browsing_init();
avrcp_browsing_controller_init(); avrcp_browsing_controller_init();
// // Register AVRCP for HCI events. avrcp_browsing_target_init();
avrcp_browsing_controller_register_packet_handler(&avrcp_browsing_controller_packet_handler);
// Register for HCI events.
avrcp_browsing_controller_register_packet_handler(&avrcp_browsing_packet_handler);
avrcp_browsing_target_register_packet_handler(&avrcp_browsing_packet_handler);
avrcp_browsing_register_packet_handler(&avrcp_browsing_packet_handler);
// Initialize SDP. // Initialize SDP.
sdp_init(); sdp_init();
@ -214,12 +221,9 @@ int btstack_main(int argc, const char * argv[]){
gap_set_class_of_device(0x200408); gap_set_class_of_device(0x200408);
// Register for HCI events. // Register for HCI events.
hci_event_callback_registration.callback = &avrcp_browsing_controller_packet_handler; hci_event_callback_registration.callback = &avrcp_browsing_packet_handler;
hci_add_event_handler(&hci_event_callback_registration); hci_add_event_handler(&hci_event_callback_registration);
// Register for AVRCP events.
avrcp_controller_register_packet_handler(&avrcp_browsing_controller_packet_handler);
#ifdef HAVE_BTSTACK_STDIN #ifdef HAVE_BTSTACK_STDIN
// Parse human readable Bluetooth address. // Parse human readable Bluetooth address.
@ -267,7 +271,7 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
break; break;
} }
} }
static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void avrcp_browsing_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel); UNUSED(channel);
int pos; int pos;

View File

@ -50,7 +50,10 @@
#include "classic/avrcp.h" #include "classic/avrcp.h"
#include "classic/avrcp_controller.h" #include "classic/avrcp_controller.h"
#define PSM_AVCTP_BROWSING 0x001b
static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void avrcp_browsing_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static const char * default_avrcp_controller_service_name = "BTstack AVRCP Controller Service"; 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"; static const char * default_avrcp_controller_service_provider_name = "BTstack AVRCP Controller Service Provider";
@ -63,6 +66,7 @@ static avrcp_context_t * sdp_query_context;
static avrcp_context_t avrcp_context; static avrcp_context_t avrcp_context;
static btstack_packet_handler_t avrcp_callback; static btstack_packet_handler_t avrcp_callback;
static btstack_packet_handler_t avrcp_browsing_callback;
static uint8_t attribute_value[45]; static uint8_t attribute_value[45];
static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); static const unsigned int attribute_value_buffer_size = sizeof(attribute_value);
@ -70,7 +74,11 @@ static const unsigned int attribute_value_buffer_size = sizeof(attribute_value);
static btstack_linked_list_t connections; static btstack_linked_list_t connections;
static btstack_packet_handler_t avrcp_controller_packet_handler; static btstack_packet_handler_t avrcp_controller_packet_handler;
static btstack_packet_handler_t avrcp_target_packet_handler; static btstack_packet_handler_t avrcp_target_packet_handler;
static int l2cap_service_registered = 0; static bool l2cap_service_registered = false;
static bool l2cap_browsing_service_registered = false;
static btstack_packet_handler_t avrcp_browsing_controller_packet_handler;
static btstack_packet_handler_t avrcp_browsing_target_packet_handler;
static const char * avrcp_subunit_type_name[] = { static const char * avrcp_subunit_type_name[] = {
"MONITOR", "AUDIO", "PRINTER", "DISC", "TAPE_RECORDER_PLAYER", "TUNER", "MONITOR", "AUDIO", "PRINTER", "DISC", "TAPE_RECORDER_PLAYER", "TUNER",
@ -376,6 +384,11 @@ void avrcp_request_can_send_now(avrcp_connection_t * connection, uint16_t l2cap_
l2cap_request_can_send_now_event(l2cap_cid); l2cap_request_can_send_now_event(l2cap_cid);
} }
void avrcp_browsing_request_can_send_now(avrcp_browsing_connection_t * connection, uint16_t l2cap_cid){
// printf("AVRCP: avrcp_request_can_send_now, role %d\n", connection->role);
connection->wait_to_send = 1;
l2cap_request_can_send_now_event(l2cap_cid);
}
uint16_t avrcp_get_next_cid(avrcp_role_t role){ uint16_t avrcp_get_next_cid(avrcp_role_t role){
do { do {
@ -695,8 +708,6 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
btstack_assert(avrcp_controller_packet_handler != NULL); btstack_assert(avrcp_controller_packet_handler != NULL);
btstack_assert(avrcp_target_packet_handler != NULL); btstack_assert(avrcp_target_packet_handler != NULL);
log_info("incoming connection");
l2cap_event_incoming_connection_get_address(packet, event_addr); l2cap_event_incoming_connection_get_address(packet, event_addr);
local_cid = l2cap_event_incoming_connection_get_local_cid(packet); local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
outoing_active = false; outoing_active = false;
@ -916,7 +927,7 @@ void avrcp_init(void){
int status = l2cap_register_service(&avrcp_packet_handler, BLUETOOTH_PSM_AVCTP, 0xffff, gap_get_security_level()); int status = l2cap_register_service(&avrcp_packet_handler, BLUETOOTH_PSM_AVCTP, 0xffff, gap_get_security_level());
if (status != ERROR_CODE_SUCCESS) return; if (status != ERROR_CODE_SUCCESS) return;
l2cap_service_registered = 1; l2cap_service_registered = true;
} }
void avrcp_register_controller_packet_handler(btstack_packet_handler_t callback){ void avrcp_register_controller_packet_handler(btstack_packet_handler_t callback){
@ -933,6 +944,7 @@ void avrcp_register_packet_handler(btstack_packet_handler_t callback){
} }
// AVRCP Browsing Service functions // AVRCP Browsing Service functions
avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection){ avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection){
avrcp_browsing_connection_t * connection = btstack_memory_avrcp_browsing_connection_get(); avrcp_browsing_connection_t * connection = btstack_memory_avrcp_browsing_connection_get();
connection->state = AVCTP_CONNECTION_IDLE; connection->state = AVCTP_CONNECTION_IDLE;
@ -942,8 +954,8 @@ avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_
return connection; return connection;
} }
void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status){ static void avrcp_emit_browsing_connection_established(uint16_t browsing_cid, bd_addr_t addr, uint8_t status){
btstack_assert(callback != NULL); btstack_assert(avrcp_browsing_callback != NULL);
uint8_t event[12]; uint8_t event[12];
int pos = 0; int pos = 0;
@ -955,11 +967,11 @@ void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callbac
pos += 6; pos += 6;
little_endian_store_16(event, pos, browsing_cid); little_endian_store_16(event, pos, browsing_cid);
pos += 2; pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); (*avrcp_browsing_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
} }
void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){ static void avrcp_emit_incoming_browsing_connection(uint16_t browsing_cid, bd_addr_t addr){
btstack_assert(callback != NULL); btstack_assert(avrcp_browsing_callback != NULL);
uint8_t event[11]; uint8_t event[11];
int pos = 0; int pos = 0;
@ -970,11 +982,11 @@ void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback,
pos += 6; pos += 6;
little_endian_store_16(event, pos, browsing_cid); little_endian_store_16(event, pos, browsing_cid);
pos += 2; pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); (*avrcp_browsing_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
} }
void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid){ static void avrcp_emit_browsing_connection_closed(uint16_t browsing_cid){
btstack_assert(callback != NULL); btstack_assert(avrcp_browsing_callback != NULL);
uint8_t event[5]; uint8_t event[5];
int pos = 0; int pos = 0;
@ -983,10 +995,11 @@ void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, ui
event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED; event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED;
little_endian_store_16(event, pos, browsing_cid); little_endian_store_16(event, pos, browsing_cid);
pos += 2; pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); (*avrcp_browsing_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
} }
void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){
static void avrcp_browsing_packet_handler_with_role(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_role_t avrcp_role){
UNUSED(channel); UNUSED(channel);
UNUSED(size); UNUSED(size);
bd_addr_t event_addr; bd_addr_t event_addr;
@ -995,76 +1008,128 @@ void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
avrcp_browsing_connection_t * browsing_connection = NULL; avrcp_browsing_connection_t * browsing_connection = NULL;
avrcp_connection_t * avrcp_connection = NULL; avrcp_connection_t * avrcp_connection = NULL;
if (packet_type != HCI_EVENT_PACKET) return; btstack_packet_handler_t browsing_callback;
switch (hci_event_packet_get_type(packet)) { switch (avrcp_role){
case HCI_EVENT_DISCONNECTION_COMPLETE: case AVRCP_CONTROLLER:
avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0); browsing_callback = avrcp_browsing_controller_packet_handler;
break; break;
case L2CAP_EVENT_INCOMING_CONNECTION: case AVRCP_TARGET:
l2cap_event_incoming_connection_get_address(packet, event_addr); browsing_callback = avrcp_browsing_target_packet_handler;
local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(context->role, event_addr);
if (!avrcp_connection) {
log_error("No previously created AVRCP controller connections");
l2cap_decline_connection(local_cid);
break;
}
browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
browsing_connection->l2cap_browsing_cid = local_cid;
browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
log_info("Emit AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION browsing_cid 0x%02x, l2cap_signaling_cid 0x%02x\n", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr);
break; break;
default:
case L2CAP_EVENT_CHANNEL_OPENED: break;
l2cap_event_channel_opened_get_address(packet, event_addr); }
status = l2cap_event_channel_opened_get_status(packet); btstack_assert(browsing_callback != NULL);
local_cid = l2cap_event_channel_opened_get_local_cid(packet);
avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(context->role, event_addr);
if (!avrcp_connection){
log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
l2cap_disconnect(local_cid, 0); // reason isn't used
break;
}
browsing_connection = avrcp_connection->browsing_connection; switch (packet_type){
if (status != ERROR_CODE_SUCCESS){ case L2CAP_DATA_PACKET:
log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); (*browsing_callback)(packet_type, channel, packet, size);
avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status); // frame_type = (avrcp_frame_type_t)((packet[0] & 0x02) >> 1);
btstack_memory_avrcp_browsing_connection_free(browsing_connection);
avrcp_connection->browsing_connection = NULL;
break;
}
if (browsing_connection->state != AVCTP_CONNECTION_W4_L2CAP_CONNECTED) break;
browsing_connection->l2cap_browsing_cid = local_cid;
log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid); // switch (frame_type){
browsing_connection->state = AVCTP_CONNECTION_OPENED; // case AVRCP_RESPONSE_FRAME:
avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS); // (*avrcp_controller_packet_handler)(packet_type, channel, packet, size);
// break;
// case AVRCP_COMMAND_FRAME:
// default: // make compiler happy
// (*avrcp_target_packet_handler)(packet_type, channel, packet, size);
// break;
// }
break; break;
case HCI_EVENT_PACKET:
case L2CAP_EVENT_CHANNEL_CLOSED:
local_cid = l2cap_event_channel_closed_get_local_cid(packet); switch (hci_event_packet_get_type(packet)) {
avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid_for_role(context->role, local_cid); case L2CAP_EVENT_CAN_SEND_NOW:
(*browsing_callback)(packet_type, channel, packet, size);
if (avrcp_connection && avrcp_connection->browsing_connection){ break;
avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid);
// free connection case HCI_EVENT_DISCONNECTION_COMPLETE:
btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection); avrcp_emit_browsing_connection_closed(ERROR_CODE_SUCCESS);
avrcp_connection->browsing_connection = NULL; break;
break; case L2CAP_EVENT_INCOMING_CONNECTION:
l2cap_event_incoming_connection_get_address(packet, event_addr);
local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(avrcp_role, event_addr);
if (!avrcp_connection) {
log_error("No previously created AVRCP controller connections");
l2cap_decline_connection(local_cid);
break;
}
browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
browsing_connection->l2cap_browsing_cid = local_cid;
browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
log_info("Emit AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION browsing_cid 0x%02x, l2cap_signaling_cid 0x%02x\n", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
avrcp_emit_incoming_browsing_connection(avrcp_connection->avrcp_browsing_cid, event_addr);
break;
case L2CAP_EVENT_CHANNEL_OPENED:
l2cap_event_channel_opened_get_address(packet, event_addr);
status = l2cap_event_channel_opened_get_status(packet);
local_cid = l2cap_event_channel_opened_get_local_cid(packet);
log_info("received L2CAP_EVENT_CHANNEL_OPENED, cid 0x%02x", local_cid);
avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(avrcp_role, event_addr);
if (!avrcp_connection){
log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
avrcp_emit_browsing_connection_established(local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
l2cap_disconnect(local_cid, 0); // reason isn't used
break;
}
browsing_connection = avrcp_connection->browsing_connection;
if (status != ERROR_CODE_SUCCESS){
log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
avrcp_emit_browsing_connection_established(avrcp_connection->avrcp_browsing_cid, event_addr, status);
btstack_memory_avrcp_browsing_connection_free(browsing_connection);
avrcp_connection->browsing_connection = NULL;
break;
}
if (browsing_connection->state != AVCTP_CONNECTION_W4_L2CAP_CONNECTED) break;
browsing_connection->l2cap_browsing_cid = local_cid;
log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
browsing_connection->state = AVCTP_CONNECTION_OPENED;
avrcp_emit_browsing_connection_established(avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS);
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid_for_role(avrcp_role, local_cid);
if (avrcp_connection && avrcp_connection->browsing_connection){
avrcp_emit_browsing_connection_closed(avrcp_connection->avrcp_browsing_cid);
// free connection
btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
avrcp_connection->browsing_connection = NULL;
break;
}
break;
default:
break;
} }
break; break;
default: default:
break; break;
} }
} }
uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_role_t avrcp_role, btstack_packet_handler_t avrcp_browsing_packet_handler, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){ static void avrcp_browsing_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
avrcp_browsing_packet_handler_with_role(packet_type, channel, packet, size, AVRCP_CONTROLLER);
// avrcp_browsing_packet_handler_with_role(packet_type, channel, packet, size, AVRCP_TARGET);
}
void avrcp_browsing_init(void){
if (l2cap_browsing_service_registered) return;
int status = l2cap_register_service(&avrcp_browsing_packet_handler, PSM_AVCTP_BROWSING, 0xffff, LEVEL_2);
if (status != ERROR_CODE_SUCCESS) return;
l2cap_browsing_service_registered = true;
}
uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_role_t avrcp_role, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){
avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(avrcp_role, remote_addr); avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(avrcp_role, remote_addr);
if (!avrcp_connection){ if (!avrcp_connection){
@ -1087,7 +1152,6 @@ uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_role_t avrcp_role, b
if (avrcp_browsing_cid){ if (avrcp_browsing_cid){
*avrcp_browsing_cid = avrcp_connection->avrcp_browsing_cid; *avrcp_browsing_cid = avrcp_connection->avrcp_browsing_cid;
} }
connection->ertm_buffer = ertm_buffer; connection->ertm_buffer = ertm_buffer;
connection->ertm_buffer_size = ertm_buffer_size; connection->ertm_buffer_size = ertm_buffer_size;
avrcp_connection->browsing_connection = connection; avrcp_connection->browsing_connection = connection;
@ -1111,3 +1175,16 @@ uint8_t avrcp_browsing_disconnect(uint16_t avrcp_browsing_cid, avrcp_role_t avrc
l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0); l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
void avrcp_browsing_register_controller_packet_handler(btstack_packet_handler_t callback){
avrcp_browsing_controller_packet_handler = callback;
}
void avrcp_browsing_register_target_packet_handler(btstack_packet_handler_t callback){
avrcp_browsing_target_packet_handler = callback;
}
void avrcp_browsing_register_packet_handler(btstack_packet_handler_t callback){
btstack_assert(callback != NULL);
avrcp_browsing_callback = callback;
}

View File

@ -597,19 +597,28 @@ uint8_t avrcp_connect(bd_addr_t remote_addr, uint16_t * avrcp_cid);
*/ */
uint8_t avrcp_disconnect(uint16_t avrcp_cid); uint8_t avrcp_disconnect(uint16_t avrcp_cid);
/**
* @brief Set up AVRCP Browsing service
*/
void avrcp_browsing_init(void);
/**
* @brief Register callback for the AVRCP Browsing Controller client.
* @param callback
*/
void avrcp_browsing_register_packet_handler(btstack_packet_handler_t callback);
/** /**
* @brief Connect to AVRCP Browsing service on a remote device, emits AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED with status * @brief Connect to AVRCP Browsing service on a remote device, emits AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED with status
* @param remote_addr * @param remote_addr
* @param avrcp_role * @param avrcp_role
* @param avrcp_browsing_packet_handler
* @param ertm_buffer * @param ertm_buffer
* @param ertm_buffer_size * @param ertm_buffer_size
* @param ertm_config * @param ertm_config
* @param avrcp_browsing_cid outgoing parameter, valid if status == ERROR_CODE_SUCCESS * @param avrcp_browsing_cid outgoing parameter, valid if status == ERROR_CODE_SUCCESS
* @returns status * @returns status
*/ */
uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_role_t avrcp_role, btstack_packet_handler_t avrcp_browsing_packet_handler, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid); uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_role_t avrcp_role, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid);
/** /**
* @brief Disconnect from AVRCP Browsing service * @brief Disconnect from AVRCP Browsing service
@ -621,11 +630,11 @@ uint8_t avrcp_browsing_disconnect(uint16_t avrcp_browsing_cid, avrcp_role_t avrc
/* API_END */ /* API_END */
void avrcp_browsing_register_controller_packet_handler(btstack_packet_handler_t callback);
void avrcp_browsing_register_target_packet_handler(btstack_packet_handler_t callback);
void avrcp_browsing_request_can_send_now(avrcp_browsing_connection_t * connection, uint16_t l2cap_cid);
avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection); avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection);
void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status);
void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr);
void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid);
void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context);
#if defined __cplusplus #if defined __cplusplus
} }

View File

@ -46,7 +46,6 @@
#include "classic/avrcp.h" #include "classic/avrcp.h"
#include "classic/avrcp_browsing_controller.h" #include "classic/avrcp_browsing_controller.h"
#define PSM_AVCTP_BROWSING 0x001b
static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@ -377,9 +376,8 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16
avrcp_browsing_connection_t * browsing_connection; avrcp_browsing_connection_t * browsing_connection;
uint8_t transport_header; uint8_t transport_header;
int pos; int pos;
switch (packet_type) { switch (packet_type) {
case L2CAP_DATA_PACKET: case L2CAP_DATA_PACKET:
browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER, channel); browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER, channel);
if (!browsing_connection) break; if (!browsing_connection) break;
pos = 0; pos = 0;
@ -499,7 +497,6 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16
avrcp_browsing_controller_handle_can_send_now(browsing_connection); avrcp_browsing_controller_handle_can_send_now(browsing_connection);
break; break;
default: default:
avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context);
break; break;
} }
break; break;
@ -511,7 +508,7 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16
void avrcp_browsing_controller_init(void){ void avrcp_browsing_controller_init(void){
avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler; avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler;
l2cap_register_service(&avrcp_browsing_controller_packet_handler, PSM_AVCTP_BROWSING, 0xffff, gap_get_security_level()); avrcp_browsing_register_controller_packet_handler(avrcp_browsing_controller_packet_handler);
} }
void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){ void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){
@ -520,7 +517,7 @@ void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t
} }
uint8_t avrcp_browsing_controller_connect(bd_addr_t bd_addr, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){ uint8_t avrcp_browsing_controller_connect(bd_addr_t bd_addr, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){
return avrcp_browsing_connect(bd_addr, AVRCP_CONTROLLER, avrcp_browsing_controller_packet_handler, ertm_buffer, size, ertm_config, avrcp_browsing_cid); return avrcp_browsing_connect(bd_addr, AVRCP_CONTROLLER, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
} }
uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){ uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){
@ -586,7 +583,7 @@ uint8_t avrcp_browsing_controller_get_item_attributes_for_scope(uint16_t avrcp_b
connection->uid_counter = uid_counter; connection->uid_counter = uid_counter;
connection->attr_bitmap = attr_bitmap; connection->attr_bitmap = attr_bitmap;
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -616,7 +613,7 @@ static uint8_t avrcp_browsing_controller_get_folder_items(uint16_t avrcp_browsin
connection->end_item = end_item; connection->end_item = end_item;
connection->attr_bitmap = attr_bitmap; connection->attr_bitmap = attr_bitmap;
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -654,7 +651,7 @@ uint8_t avrcp_browsing_controller_set_browsed_player(uint16_t avrcp_browsing_cid
connection->set_browsed_player_id = 1; connection->set_browsed_player_id = 1;
connection->browsed_player_id = browsed_player_id; connection->browsed_player_id = browsed_player_id;
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -688,7 +685,7 @@ uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8
(void)memcpy(connection->folder_uid, folder_uid, 8); (void)memcpy(connection->folder_uid, folder_uid, 8);
} }
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -728,7 +725,7 @@ uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t s
memset(connection->search_str, 0, sizeof(connection->search_str)); memset(connection->search_str, 0, sizeof(connection->search_str));
(void)memcpy(connection->search_str, search_str, (void)memcpy(connection->search_str, search_str,
connection->search_str_len); connection->search_str_len);
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -752,6 +749,6 @@ uint8_t avrcp_browsing_controller_get_total_nr_items_for_scope(uint16_t avrcp_br
} }
connection->get_total_nr_items = 1; connection->get_total_nr_items = 1;
connection->get_total_nr_items_scope = scope; connection->get_total_nr_items_scope = scope;
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }

View File

@ -46,15 +46,8 @@
#include "classic/avrcp.h" #include "classic/avrcp.h"
#include "classic/avrcp_browsing_target.h" #include "classic/avrcp_browsing_target.h"
#define PSM_AVCTP_BROWSING 0x001b
static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void avrcp_browsing_target_request_can_send_now(avrcp_browsing_connection_t * connection, uint16_t l2cap_cid){
connection->wait_to_send = 1;
l2cap_request_can_send_now_event(l2cap_cid);
}
static int avrcp_browsing_target_handle_can_send_now(avrcp_browsing_connection_t * connection){ static int avrcp_browsing_target_handle_can_send_now(avrcp_browsing_connection_t * connection){
int pos = 0; int pos = 0;
// printf("avrcp_browsing_target_handle_can_send_now, cmd_operands_length %d\n", connection->cmd_operands_length); // printf("avrcp_browsing_target_handle_can_send_now, cmd_operands_length %d\n", connection->cmd_operands_length);
@ -90,7 +83,7 @@ static uint8_t avrcp_browsing_target_response_general_reject(avrcp_browsing_conn
connection->cmd_operands[pos++] = status; connection->cmd_operands[pos++] = status;
connection->cmd_operands_length = 4; connection->cmd_operands_length = 4;
connection->state = AVCTP_W2_SEND_RESPONSE; connection->state = AVCTP_W2_SEND_RESPONSE;
avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -126,6 +119,7 @@ static void avrcp_browsing_target_emit_get_total_num_items(btstack_packet_handle
static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(size);
avrcp_browsing_connection_t * browsing_connection; avrcp_browsing_connection_t * browsing_connection;
switch (packet_type) { switch (packet_type) {
@ -202,7 +196,6 @@ static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t c
avrcp_browsing_target_handle_can_send_now(browsing_connection); avrcp_browsing_target_handle_can_send_now(browsing_connection);
break; break;
default: default:
avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_target_context);
break; break;
} }
break; break;
@ -214,7 +207,7 @@ static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t c
void avrcp_browsing_target_init(void){ void avrcp_browsing_target_init(void){
avrcp_target_context.browsing_packet_handler = avrcp_browsing_target_packet_handler; avrcp_target_context.browsing_packet_handler = avrcp_browsing_target_packet_handler;
l2cap_register_service(&avrcp_browsing_target_packet_handler, PSM_AVCTP_BROWSING, 0xffff, gap_get_security_level()); avrcp_browsing_register_target_packet_handler(avrcp_browsing_target_packet_handler);
} }
void avrcp_browsing_target_register_packet_handler(btstack_packet_handler_t callback){ void avrcp_browsing_target_register_packet_handler(btstack_packet_handler_t callback){
@ -223,7 +216,7 @@ void avrcp_browsing_target_register_packet_handler(btstack_packet_handler_t call
} }
uint8_t avrcp_browsing_target_connect(bd_addr_t bd_addr, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){ uint8_t avrcp_browsing_target_connect(bd_addr_t bd_addr, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){
return avrcp_browsing_connect(bd_addr, AVRCP_TARGET, avrcp_browsing_target_packet_handler, ertm_buffer, size, ertm_config, avrcp_browsing_cid); return avrcp_browsing_connect(bd_addr, AVRCP_TARGET, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
} }
uint8_t avrcp_browsing_target_disconnect(uint16_t avrcp_browsing_cid){ uint8_t avrcp_browsing_target_disconnect(uint16_t avrcp_browsing_cid){
@ -312,7 +305,7 @@ uint8_t avrcp_subevent_browsing_get_folder_items_response(uint16_t avrcp_browsin
// printf_hexdump(connection->cmd_operands, connection->cmd_operands_length); // printf_hexdump(connection->cmd_operands, connection->cmd_operands_length);
connection->state = AVCTP_W2_SEND_RESPONSE; connection->state = AVCTP_W2_SEND_RESPONSE;
avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
@ -348,7 +341,7 @@ uint8_t avrcp_subevent_browsing_get_total_num_items_response(uint16_t avrcp_brow
connection->cmd_operands_length = pos; connection->cmd_operands_length = pos;
connection->state = AVCTP_W2_SEND_RESPONSE; connection->state = AVCTP_W2_SEND_RESPONSE;
avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid); avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }