hfp: extract hfp_handle_rfcomm_event from hfp_handle_hci_event, register hci handler in hf/ag

This commit is contained in:
Matthias Ringwald 2018-04-20 15:54:36 +02:00
parent 225dff0411
commit 279501658e
4 changed files with 107 additions and 85 deletions

View File

@ -109,8 +109,6 @@ static btstack_packet_handler_t hfp_ag_rfcomm_packet_handler;
static void (*hfp_hf_run_for_context)(hfp_connection_t * hfp_connection);
static btstack_packet_callback_registration_t hci_event_callback_registration;
static hfp_connection_t * sco_establishment_active;
const char * hfp_hf_feature(int index){
@ -564,15 +562,15 @@ static void hfp_handle_failed_sco_connection(uint8_t status){
}
void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){
void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel); // ok: no channel
bd_addr_t event_addr;
uint16_t rfcomm_cid, handle;
hci_con_handle_t handle;
hfp_connection_t * hfp_connection = NULL;
uint8_t status;
log_debug("HFP packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size);
log_debug("HFP HCI event handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size);
switch (hci_event_packet_get_type(packet)) {
@ -593,60 +591,6 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
break;
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr);
hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr, local_role);
if (!hfp_connection){
log_info("hfp: no memory to accept incoming connection - decline");
rfcomm_decline_connection(rfcomm_event_incoming_connection_get_rfcomm_cid(packet));
return;
}
if (hfp_connection->state != HFP_IDLE) {
log_error("hfp: incoming connection but state != HFP_IDLE");
return;
}
hfp_connection->rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet);
hfp_connection->state = HFP_W4_RFCOMM_CONNECTED;
// printf("RFCOMM channel %u requested for %s\n", hfp_connection->rfcomm_cid, bd_addr_to_str(hfp_connection->remote_addr));
rfcomm_accept_connection(hfp_connection->rfcomm_cid);
break;
case RFCOMM_EVENT_CHANNEL_OPENED:
// data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16)
rfcomm_event_channel_opened_get_bd_addr(packet, event_addr);
status = rfcomm_event_channel_opened_get_status(packet);
hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr);
if (!hfp_connection || hfp_connection->state != HFP_W4_RFCOMM_CONNECTED) return;
if (status) {
hfp_emit_slc_connection_event(hfp_connection, status, rfcomm_event_channel_opened_get_con_handle(packet), event_addr);
remove_hfp_connection_context(hfp_connection);
} else {
hfp_connection->acl_handle = rfcomm_event_channel_opened_get_con_handle(packet);
hfp_connection->rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet);
bd_addr_copy(hfp_connection->remote_addr, event_addr);
// uint16_t mtu = rfcomm_event_channel_opened_get_max_frame_size(packet);
// printf("RFCOMM channel open succeeded. hfp_connection %p, RFCOMM Channel ID 0x%02x, max frame size %u\n", hfp_connection, hfp_connection->rfcomm_cid, mtu);
switch (hfp_connection->state){
case HFP_W4_RFCOMM_CONNECTED:
hfp_connection->state = HFP_EXCHANGE_SUPPORTED_FEATURES;
break;
case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN:
hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM;
// printf("Shutting down RFCOMM.\n");
break;
default:
break;
}
rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid);
}
break;
case HCI_EVENT_COMMAND_STATUS:
if (hci_event_command_status_get_command_opcode(packet) == hci_setup_synchronous_connection.opcode) {
status = hci_event_command_status_get_status(packet);
@ -717,23 +661,6 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
break;
}
case RFCOMM_EVENT_CHANNEL_CLOSED:
if (local_role > 1){
log_error("hfp_handle_hci_event role %x", local_role);
}
rfcomm_cid = little_endian_read_16(packet,2);
hfp_connection = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid);
if (!hfp_connection) break;
if (hfp_connection->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){
hfp_connection->state = HFP_IDLE;
hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role);
break;
}
hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0);
remove_hfp_connection_context(hfp_connection);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
handle = little_endian_read_16(packet,3);
hfp_connection = get_hfp_connection_context_for_sco_handle(handle);
@ -760,6 +687,90 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
}
void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){
UNUSED(channel); // ok: no channel
bd_addr_t event_addr;
uint16_t rfcomm_cid;
hfp_connection_t * hfp_connection = NULL;
uint8_t status;
log_debug("HFP packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size);
switch (hci_event_packet_get_type(packet)) {
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr);
hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr, local_role);
if (!hfp_connection){
log_info("hfp: no memory to accept incoming connection - decline");
rfcomm_decline_connection(rfcomm_event_incoming_connection_get_rfcomm_cid(packet));
return;
}
if (hfp_connection->state != HFP_IDLE) {
log_error("hfp: incoming connection but state != HFP_IDLE");
return;
}
hfp_connection->rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet);
hfp_connection->state = HFP_W4_RFCOMM_CONNECTED;
// printf("RFCOMM channel %u requested for %s\n", hfp_connection->rfcomm_cid, bd_addr_to_str(hfp_connection->remote_addr));
rfcomm_accept_connection(hfp_connection->rfcomm_cid);
break;
case RFCOMM_EVENT_CHANNEL_OPENED:
// data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16)
rfcomm_event_channel_opened_get_bd_addr(packet, event_addr);
status = rfcomm_event_channel_opened_get_status(packet);
hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr);
if (!hfp_connection || hfp_connection->state != HFP_W4_RFCOMM_CONNECTED) return;
if (status) {
hfp_emit_slc_connection_event(hfp_connection, status, rfcomm_event_channel_opened_get_con_handle(packet), event_addr);
remove_hfp_connection_context(hfp_connection);
} else {
hfp_connection->acl_handle = rfcomm_event_channel_opened_get_con_handle(packet);
hfp_connection->rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet);
bd_addr_copy(hfp_connection->remote_addr, event_addr);
// uint16_t mtu = rfcomm_event_channel_opened_get_max_frame_size(packet);
// printf("RFCOMM channel open succeeded. hfp_connection %p, RFCOMM Channel ID 0x%02x, max frame size %u\n", hfp_connection, hfp_connection->rfcomm_cid, mtu);
switch (hfp_connection->state){
case HFP_W4_RFCOMM_CONNECTED:
hfp_connection->state = HFP_EXCHANGE_SUPPORTED_FEATURES;
break;
case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN:
hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM;
// printf("Shutting down RFCOMM.\n");
break;
default:
break;
}
rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid);
}
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
rfcomm_cid = little_endian_read_16(packet,2);
hfp_connection = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid);
if (!hfp_connection) break;
if (hfp_connection->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){
hfp_connection->state = HFP_IDLE;
hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role);
break;
}
hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0);
remove_hfp_connection_context(hfp_connection);
break;
default:
break;
}
}
// translates command string into hfp_command_t CMD
static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){
int offset = isHandsFree ? 0 : 2;
@ -1505,11 +1516,5 @@ void hfp_set_hf_run_for_context(void (*callback)(hfp_connection_t * hfp_connecti
hfp_hf_run_for_context = callback;
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_INVALID);
}
void hfp_init(void){
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
}

View File

@ -652,7 +652,8 @@ void hfp_set_hf_run_for_context(void (*callbcack)(hfp_connection_t * hfp_connect
void hfp_init(void);
void hfp_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t service_uuid, int rfcomm_channel_nr, const char * name);
void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role);
void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role);
void hfp_emit_event(hfp_connection_t * hfp_connection, uint8_t event_subtype, uint8_t value);
void hfp_emit_simple_event(hfp_connection_t * hfp_connection, uint8_t event_subtype);
void hfp_emit_string_event(hfp_connection_t * hfp_connection, uint8_t event_subtype, const char * value);

View File

@ -81,6 +81,8 @@ void set_hfp_ag_indicators(hfp_ag_indicator_t * indicators, int indicator_nr);
int get_hfp_ag_indicators_nr(hfp_connection_t * context);
hfp_ag_indicator_t * get_hfp_ag_indicators(hfp_connection_t * context);
static btstack_packet_callback_registration_t hci_event_callback_registration;
// gobals
static const char default_hfp_ag_service_name[] = "Voice gateway";
@ -2032,7 +2034,7 @@ static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
hfp_run_for_context(get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid));
return;
}
hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_AG);
hfp_handle_rfcomm_event(packet_type, channel, packet, size, HFP_ROLE_AG);
break;
default:
break;
@ -2075,9 +2077,15 @@ void hfp_ag_init_call_hold_services(int call_hold_services_nr, const char * call
void hfp_ag_init(uint16_t rfcomm_channel_nr){
hfp_init();
hci_event_callback_registration.callback = &hfp_handle_hci_event;
hci_add_event_handler(&hci_event_callback_registration);
rfcomm_register_service(&rfcomm_packet_handler, rfcomm_channel_nr, 0xffff);
// used to set packet handler for outgoing rfcomm connections - could be handled by emitting an event to us
hfp_set_ag_rfcomm_packet_handler(&rfcomm_packet_handler);
hfp_ag_response_and_hold_active = 0;

View File

@ -66,6 +66,8 @@
#include "hci_dump.h"
#include "l2cap.h"
static btstack_packet_callback_registration_t hci_event_callback_registration;
static const char default_hfp_hf_service_name[] = "Hands-Free unit";
static uint16_t hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES;
static uint8_t hfp_codecs_nr = 0;
@ -1099,7 +1101,7 @@ static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
hfp_run_for_context(get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid));
return;
}
hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_HF);
hfp_handle_rfcomm_event(packet_type, channel, packet, size, HFP_ROLE_HF);
break;
default:
break;
@ -1110,8 +1112,14 @@ static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
void hfp_hf_init(uint16_t rfcomm_channel_nr){
hfp_init();
hci_event_callback_registration.callback = &hfp_handle_hci_event;
hci_add_event_handler(&hci_event_callback_registration);
rfcomm_register_service(rfcomm_packet_handler, rfcomm_channel_nr, 0xffff);
// used to set packet handler for outgoing rfcomm connections - could be handled by emitting an event to us
hfp_set_hf_rfcomm_packet_handler(&rfcomm_packet_handler);
hfp_set_hf_run_for_context(hfp_run_for_context);
hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES;