mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-20 18:40:31 +00:00
hfp disconnect
This commit is contained in:
parent
2fc8e6351e
commit
4ec1791519
@ -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
113
src/hfp.c
@ -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){
|
||||
|
20
src/hfp.h
20
src/hfp.h
@ -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);
|
||||
|
||||
|
52
src/hfp_ag.c
52
src/hfp_ag.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
91
src/hfp_hf.c
91
src/hfp_hf.c
@ -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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user