hfp disconnect

This commit is contained in:
Milanka Ringwald 2015-08-05 17:05:16 +02:00
parent 2fc8e6351e
commit 4ec1791519
9 changed files with 219 additions and 106 deletions

View File

@ -616,8 +616,8 @@ extern "C" {
#define HCI_EVENT_HFP_META 0xE9
#define HFP_SUBEVENT_AUDIO_CONNECTION_COMPLETE 0x01
#define HFP_SUBEVENT_SUPPORTED_FEATURES_EXCHANGE 0x02
#define HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED 0x01
#define HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED 0x02
// ANCS Client

113
src/hfp.c
View File

@ -93,7 +93,7 @@ static const char * hfp_ag_features[] = {
"Reserved for future definition"
};
static hfp_callback_t hfp_callback;
static linked_list_t hfp_connections = NULL;
const char * hfp_hf_feature(int index){
@ -135,7 +135,7 @@ int join(char * buffer, int buffer_size, uint8_t * values, int values_nr){
}
static void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value){
void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value){
if (!callback) return;
uint8_t event[4];
event[0] = HCI_EVENT_HFP_META;
@ -178,6 +178,8 @@ static hfp_connection_t * create_hfp_connection_context(){
hfp_connection_t * context = btstack_memory_hfp_connection_get();
if (!context) return NULL;
// init state
memset(context,0, sizeof(hfp_connection_t));
context->state = HFP_IDLE;
context->line_size = 0;
context->parser_state = HFP_PARSER_CMD_HEADER;
@ -193,6 +195,9 @@ static hfp_connection_t * create_hfp_connection_context(){
return context;
}
static void remove_hfp_connection_context(hfp_connection_t * context){
linked_list_remove(&hfp_connections, (linked_item_t*)context);
}
hfp_connection_t * provide_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr){
hfp_connection_t * context = get_hfp_connection_context_for_bd_addr(bd_addr);
@ -202,23 +207,6 @@ hfp_connection_t * provide_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr)
return context;
}
hfp_connection_t * provide_hfp_connection_context_for_rfcomm_cid(uint16_t rfcomm_cid){
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid);
if (context) return context;
context = create_hfp_connection_context();
printf("Set RFCOMM cid %p %u\n", context, context->rfcomm_cid);
context->rfcomm_cid = rfcomm_cid;
return context;
}
void hfp_register_packet_handler(hfp_callback_t callback){
if (callback == NULL){
log_error("hfp_register_packet_handler called with NULL callback");
return;
}
hfp_callback = callback;
}
/* @param suported_features
* HF bit 0: EC and/or NR function (yes/no, 1 = yes, 0 = no)
@ -338,15 +326,9 @@ static void handle_query_rfcomm_event(sdp_query_event_t * event, void * context)
}
}
static void hfp_reset_state(hfp_connection_t * connection){
if (!connection) return;
connection->state = HFP_IDLE;
}
hfp_connection_t * hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
void hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
uint16_t rfcomm_cid = 0;
hfp_connection_t * context = NULL;
switch (packet[0]) {
@ -367,9 +349,9 @@ hfp_connection_t * hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, ui
case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
bt_flip_addr(event_addr, &packet[2]);
context = provide_hfp_connection_context_for_bd_addr(event_addr);
context = get_hfp_connection_context_for_bd_addr(event_addr);
if (!context || context->state != HFP_IDLE) return context;
if (!context || context->state != HFP_IDLE) return;
context->rfcomm_cid = READ_BT_16(packet, 9);
context->state = HFP_W4_RFCOMM_CONNECTED;
@ -381,34 +363,41 @@ hfp_connection_t * hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, ui
// data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16)
printf("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
bt_flip_addr(event_addr, &packet[3]);
context = provide_hfp_connection_context_for_bd_addr(event_addr);
if (!context || context->state != HFP_W4_RFCOMM_CONNECTED) return context;
context = get_hfp_connection_context_for_bd_addr(event_addr);
if (!context || context->state != HFP_W4_RFCOMM_CONNECTED) return;
if (packet[2]) {
hfp_reset_state(context);
// hfp_emit_event(context->callback, HFP_SUBEVENT_CONNECTION_COMPLETE, packet[2]);
remove_hfp_connection_context(context);
} else {
context->con_handle = READ_BT_16(packet, 9);
context->rfcomm_cid = READ_BT_16(packet, 12);
uint16_t mtu = READ_BT_16(packet, 14);
context->state = HFP_EXCHANGE_SUPPORTED_FEATURES;
printf("RFCOMM channel open succeeded. Context %p, RFCOMM Channel ID 0x%02x, max frame size %u\n", context, context->rfcomm_cid, mtu);
switch (context->state){
case HFP_W4_RFCOMM_CONNECTED:
context->state = HFP_EXCHANGE_SUPPORTED_FEATURES;
break;
case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN:
context->state = HFP_W2_DISCONNECT_RFCOMM;
printf("Shutting down RFCOMM.\n");
break;
default:
break;
}
}
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
printf("HCI_EVENT_DISCONNECTION_COMPLETE \n");
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
printf(" RFCOMM_EVENT_CHANNEL_CLOSED\n");
// hfp_emit_event(context->callback, HFP_SUBEVENT_DISCONNECTION_COMPLETE,0);
break;
case RFCOMM_EVENT_CREDITS:
context = provide_hfp_connection_context_for_rfcomm_cid(READ_BT_16(packet, 2));
rfcomm_cid = READ_BT_16(packet,2);
context = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid);
if (!context) break;
remove_hfp_connection_context(context);
break;
default:
break;
}
return context;
}
void update_command(hfp_connection_t * context);
@ -548,20 +537,40 @@ void hfp_init(uint16_t rfcomm_channel_nr){
}
void hfp_connect(bd_addr_t bd_addr, uint16_t service_uuid){
hfp_connection_t * connection = provide_hfp_connection_context_for_bd_addr(bd_addr);
log_info("hfp_connect %s, context %p", bd_addr_to_str(bd_addr), connection);
hfp_connection_t * context = provide_hfp_connection_context_for_bd_addr(bd_addr);
log_info("hfp_connect %s, context %p", bd_addr_to_str(bd_addr), context);
if (!connection) {
log_error("hfp_hf_connect for addr %s failed", bd_addr_to_str(bd_addr));
if (!context) {
log_error("hfp_connect for addr %s failed", bd_addr_to_str(bd_addr));
return;
}
if (connection->state != HFP_IDLE) return;
if (context->state != HFP_IDLE) return;
memcpy(connection->remote_addr, bd_addr, 6);
connection->state = HFP_W4_SDP_QUERY_COMPLETE;
memcpy(context->remote_addr, bd_addr, 6);
context->state = HFP_W4_SDP_QUERY_COMPLETE;
connection_doing_sdp_query = connection;
sdp_query_rfcomm_channel_and_name_for_uuid(connection->remote_addr, service_uuid);
connection_doing_sdp_query = context;
sdp_query_rfcomm_channel_and_name_for_uuid(context->remote_addr, service_uuid);
}
hfp_connection_t * hfp_disconnect(bd_addr_t bd_addr){
hfp_connection_t * context = get_hfp_connection_context_for_bd_addr(bd_addr);
if (!context) {
log_error("hfp_disconnect for addr %s failed", bd_addr_to_str(bd_addr));
return NULL;
}
switch (context->state){
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
context->state = HFP_W2_DISCONNECT_RFCOMM;
break;
case HFP_W4_RFCOMM_CONNECTED:
context->state = HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN;
break;
default:
break;
}
return context;
}
void hfp_set_codec(hfp_connection_t * context, uint8_t *packet, uint16_t size){

View File

@ -167,13 +167,13 @@ typedef enum {
HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS, // 20
HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS,
HFP_ACTIVE, // 22
HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED, // 22
HFP_W2_DISCONNECT_RFCOMM,
HFP_W4_RFCOMM_DISCONNECTED,
HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
} hfp_state_t;
typedef void (*hfp_callback_t)(uint8_t * event, uint16_t event_size);
typedef struct{
@ -193,7 +193,7 @@ typedef struct{
typedef struct hfp_connection {
linked_item_t item;
hfp_state_t state;
hfp_command_t command;
hfp_parser_state_t parser_state;
@ -215,17 +215,19 @@ typedef struct hfp_connection {
uint32_t remote_indicators_status;
hfp_callback_t callback;
} hfp_connection_t;
void hfp_create_service(uint8_t * service, uint16_t service_uuid, int rfcomm_channel_nr, const char * name, uint16_t supported_features);
void hfp_register_packet_handler(hfp_callback_t callback);
hfp_connection_t * hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, uint16_t size);
void hfp_init(uint16_t rfcomm_channel_nr);
void hfp_connect(bd_addr_t bd_addr, uint16_t service_uuid);
void hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, uint16_t size);
void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value);
hfp_connection_t * provide_hfp_connection_context_for_rfcomm_cid(uint16_t cid);
void hfp_init(uint16_t rfcomm_channel_nr);
void hfp_connect(bd_addr_t bd_addr, uint16_t service_uuid);
hfp_connection_t * hfp_disconnect(bd_addr_t bd_addr);
hfp_connection_t * get_hfp_connection_context_for_rfcomm_cid(uint16_t cid);
linked_list_t * hfp_get_connections();
void hfp_parse(hfp_connection_t * context, uint8_t byte);

View File

@ -74,9 +74,18 @@ static hfp_ag_indicator_t hfp_ag_indicators[HFP_MAX_NUM_AG_INDICATORS];
static int hfp_ag_call_hold_services_nr = 0;
static char *hfp_ag_call_hold_services[6];
static hfp_callback_t hfp_callback;
static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
void hfp_ag_register_packet_handler(hfp_callback_t callback){
if (callback == NULL){
log_error("hfp_ag_register_packet_handler called with NULL callback");
return;
}
hfp_callback = callback;
}
static int has_codec_negotiation_feature(hfp_connection_t * connection){
int hf = get_bit(connection->remote_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
@ -291,7 +300,7 @@ void update_command(hfp_connection_t * context){
void hfp_run_for_context(hfp_connection_t *context){
if (!context) return;
if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
printf("hfp_run_for_context: command %d, state %d\n", context->command, context->state);
switch(context->command){
case HFP_CMD_SUPPORTED_FEATURES:
switch(context->state){
@ -337,7 +346,8 @@ void hfp_run_for_context(hfp_connection_t *context){
context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
break;
}
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
break;
default:
break;
@ -355,7 +365,8 @@ void hfp_run_for_context(hfp_connection_t *context){
context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
break;
}
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
break;
default:
break;
@ -369,7 +380,8 @@ void hfp_run_for_context(hfp_connection_t *context){
context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
break;
}
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
break;
default:
break;
@ -387,7 +399,20 @@ void hfp_run_for_context(hfp_connection_t *context){
break;
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
hfp_ag_retrieve_initital_supported_generic_status_indicators_cmd(context->rfcomm_cid);
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
break;
default:
break;
}
break;
case HFP_CMD_NONE:
switch(context->state){
case HFP_W2_DISCONNECT_RFCOMM:
// printf("rfcomm_disconnect_internal cid 0x%02x\n", context->rfcomm_cid);
context->state = HFP_W4_RFCOMM_DISCONNECTED;
rfcomm_disconnect_internal(context->rfcomm_cid);
break;
default:
break;
@ -401,7 +426,7 @@ void hfp_run_for_context(hfp_connection_t *context){
}
static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
hfp_connection_t * context = provide_hfp_connection_context_for_rfcomm_cid(channel);
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
if (!context) return;
if (context->state == HFP_EXCHANGE_SUPPORTED_FEATURES){
context->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
@ -434,6 +459,18 @@ static void packet_handler(void * connection, uint8_t packet_type, uint16_t chan
break;
case HCI_EVENT_PACKET:
hfp_handle_hci_event(packet_type, packet, size);
switch(packet[0]){
case RFCOMM_EVENT_CHANNEL_CLOSED:
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
if (packet[2]){
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, packet[2]);
}
break;
default:
break;
}
break;
default:
break;
@ -476,6 +513,7 @@ void hfp_ag_connect(bd_addr_t bd_addr){
}
void hfp_ag_disconnect(bd_addr_t bd_addr){
hfp_connection_t * connection = hfp_disconnect(bd_addr);
hfp_run_for_context(connection);
}

View File

@ -59,6 +59,7 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features,
hfp_ag_indicator_t * ag_indicators, int ag_indicators_nr,
hfp_hf_indicator_t * hf_indicators, int hf_indicators_nr,
char *call_hold_services[], int call_hold_services_nr);
void hfp_ag_register_packet_handler(hfp_callback_t callback);
void hfp_ag_connect(bd_addr_t bd_addr);
void hfp_ag_disconnect(bd_addr_t bd_addr);

View File

@ -71,6 +71,17 @@ static uint8_t hfp_indicators_nr = 0;
static uint8_t hfp_indicators[HFP_MAX_NUM_HF_INDICATORS];
static uint8_t hfp_indicators_status;
static hfp_callback_t hfp_callback;
void hfp_hf_register_packet_handler(hfp_callback_t callback){
hfp_callback = callback;
if (callback == NULL){
log_error("hfp_hf_register_packet_handler called with NULL callback");
return;
}
hfp_callback = callback;
}
static int has_codec_negotiation_feature(hfp_connection_t * connection){
int hf = get_bit(hfp_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
@ -169,50 +180,54 @@ int hfp_hs_list_initital_supported_generic_status_indicators_cmd(uint16_t cid){
return send_str_over_rfcomm(cid, buffer);
}
static void hfp_run_for_context(hfp_connection_t * connection){
if (!connection) return;
// printf("hfp send cmd: context %p, RFCOMM cid %u \n", connection, connection->rfcomm_cid );
if (!rfcomm_can_send_packet_now(connection->rfcomm_cid)) return;
static void hfp_run_for_context(hfp_connection_t * context){
if (!context) return;
// printf("hfp send cmd: context %p, RFCOMM cid %u \n", context, context->rfcomm_cid );
if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
switch (connection->state){
switch (context->state){
case HFP_EXCHANGE_SUPPORTED_FEATURES:
hfp_hs_exchange_supported_features_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
hfp_hs_exchange_supported_features_cmd(context->rfcomm_cid);
context->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
break;
case HFP_NOTIFY_ON_CODECS:
hfp_hs_retrieve_codec_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_NOTIFY_ON_CODECS;
hfp_hs_retrieve_codec_cmd(context->rfcomm_cid);
context->state = HFP_W4_NOTIFY_ON_CODECS;
break;
case HFP_RETRIEVE_INDICATORS:
hfp_hs_retrieve_indicators_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_RETRIEVE_INDICATORS;
hfp_hs_retrieve_indicators_cmd(context->rfcomm_cid);
context->state = HFP_W4_RETRIEVE_INDICATORS;
break;
case HFP_RETRIEVE_INDICATORS_STATUS:
hfp_hs_retrieve_indicators_status_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
hfp_hs_retrieve_indicators_status_cmd(context->rfcomm_cid);
context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
break;
case HFP_ENABLE_INDICATORS_STATUS_UPDATE:
hfp_hs_toggle_indicator_status_update_cmd(connection->rfcomm_cid, 1);
connection->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
hfp_hs_toggle_indicator_status_update_cmd(context->rfcomm_cid, 1);
context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
break;
case HFP_RETRIEVE_CAN_HOLD_CALL:
hfp_hs_retrieve_can_hold_call_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
hfp_hs_retrieve_can_hold_call_cmd(context->rfcomm_cid);
context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
break;
case HFP_LIST_GENERIC_STATUS_INDICATORS:
hfp_hs_list_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
hfp_hs_list_supported_generic_status_indicators_cmd(context->rfcomm_cid);
context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
break;
case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS:
hfp_hs_retrieve_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
hfp_hs_retrieve_supported_generic_status_indicators_cmd(context->rfcomm_cid);
context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
break;
case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
hfp_hs_list_initital_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
connection->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
hfp_hs_list_initital_supported_generic_status_indicators_cmd(context->rfcomm_cid);
context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
break;
case HFP_ACTIVE:
printf("HFP_ACTIVE\n");
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
break;
case HFP_W2_DISCONNECT_RFCOMM:
context->state = HFP_W4_RFCOMM_DISCONNECTED;
rfcomm_disconnect_internal(context->rfcomm_cid);
break;
default:
break;
@ -297,7 +312,7 @@ void handle_switch_on_ok(hfp_connection_t *context){
context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
break;
}
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
break;
case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
@ -309,7 +324,7 @@ void handle_switch_on_ok(hfp_connection_t *context){
context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
break;
}
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
break;
case HFP_W4_RETRIEVE_CAN_HOLD_CALL:
@ -317,7 +332,7 @@ void handle_switch_on_ok(hfp_connection_t *context){
context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
break;
}
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
break;
case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
@ -330,7 +345,7 @@ void handle_switch_on_ok(hfp_connection_t *context){
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
printf("Supported initial state generic status indicators \n");
context->state = HFP_ACTIVE;
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
break;
default:
@ -342,7 +357,7 @@ void handle_switch_on_ok(hfp_connection_t *context){
}
static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
hfp_connection_t * context = provide_hfp_connection_context_for_rfcomm_cid(channel);
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
if (!context) return;
packet[size] = 0;
@ -372,8 +387,21 @@ static void packet_handler(void * connection, uint8_t packet_type, uint16_t chan
break;
case HCI_EVENT_PACKET:
hfp_handle_hci_event(packet_type, packet, size);
switch(packet[0]){
case RFCOMM_EVENT_CHANNEL_CLOSED:
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
if (packet[2]){
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, packet[2]);
}
break;
default:
break;
}
break;
default:
printf(" hf packet handler\n");
break;
}
hfp_run();
@ -407,5 +435,6 @@ void hfp_hf_connect(bd_addr_t bd_addr){
}
void hfp_hf_disconnect(bd_addr_t bd_addr){
hfp_connection_t * connection = hfp_disconnect(bd_addr);
hfp_run_for_context(connection);
}

View File

@ -53,9 +53,9 @@
extern "C" {
#endif
void hfp_hf_create_service(uint8_t * service, int rfcomm_channel_nr, const char * name, uint16_t supported_features);
void hfp_hf_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, uint8_t * codecs, int codecs_nr, uint16_t * indicators, int indicators_nr, uint32_t indicators_status);
void hfp_hf_register_packet_handler(hfp_callback_t callback);
void hfp_hf_connect(bd_addr_t bd_addr);
void hfp_hf_disconnect(bd_addr_t bd_addr);

View File

@ -125,7 +125,7 @@ static int stdin_process(struct data_source *ds){
break;
case 'd':
printf("Releasing HFP connection.\n");
hfp_ag_disconnect(pts_addr);
hfp_ag_disconnect(speaker);
break;
default:
show_usage();
@ -136,7 +136,23 @@ static int stdin_process(struct data_source *ds){
}
void packet_handler(uint8_t * event, uint16_t event_size){
if (event[0] != HCI_EVENT_HFP_META) return;
switch (event[2]) {
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
if (event[3] == 0){
printf("Service level connection established.\n\n");
} else {
printf("Service level connection establishment failed with status %u\n", event[3]);
}
break;
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
if (event[3] == 0){
printf("Service level connection released.\n\n");
} else {
printf("Service level connection releasing failed with status %u\n", event[3]);
}
break;
default:
printf("event not handled %u\n", event[2]);
break;
@ -154,7 +170,7 @@ int btstack_main(int argc, const char * argv[]){
hf_indicators, hf_indicators_nr,
call_hold_services, call_hold_services_nr);
hfp_register_packet_handler(packet_handler);
hfp_ag_register_packet_handler(packet_handler);
sdp_init();
// init SDP, create record for SPP and register with SDP

View File

@ -108,7 +108,7 @@ static int stdin_process(struct data_source *ds){
break;
case 'd':
printf("Releasing HFP connection.\n");
hfp_hf_disconnect(pts_addr);
hfp_hf_disconnect(phone);
break;
default:
show_usage();
@ -118,14 +118,32 @@ static int stdin_process(struct data_source *ds){
return 0;
}
void packet_handler(uint8_t * event, uint16_t event_size){
if (event[0] != HCI_EVENT_HFP_META) return;
switch (event[2]) {
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
if (event[3] == 0){
printf("Service level connection established.\n\n");
} else {
printf("Service level connection establishment failed with status %u\n", event[3]);
}
break;
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
if (event[3] == 0){
printf("Service level connection released.\n\n");
} else {
printf("Service level connection releasing failed with status %u\n", event[3]);
}
break;
default:
printf("event not handled %u\n", event[2]);
break;
}
}
int btstack_main(int argc, const char * argv[]){
// init L2CAP
l2cap_init();
@ -134,7 +152,7 @@ int btstack_main(int argc, const char * argv[]){
// hfp_hf_init(rfcomm_channel_nr, HFP_DEFAULT_HF_SUPPORTED_FEATURES, codecs, sizeof(codecs), indicators, sizeof(indicators)/sizeof(uint16_t), 1);
hfp_hf_init(rfcomm_channel_nr, 438, codecs, sizeof(codecs), indicators, sizeof(indicators)/sizeof(uint16_t), 1);
hfp_register_packet_handler(packet_handler);
hfp_hf_register_packet_handler(packet_handler);
sdp_init();
// init SDP, create record for SPP and register with SDP