mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-10 15:40:11 +00:00
Merge branch 'master' of https://github.com/bluekitchen/btstack
This commit is contained in:
commit
e4389f7451
@ -68,6 +68,8 @@ int send_str_over_rfcomm(uint16_t cid, char * command){
|
|||||||
int err = rfcomm_send_internal(cid, (uint8_t*) command, strlen(command));
|
int err = rfcomm_send_internal(cid, (uint8_t*) command, strlen(command));
|
||||||
if (err){
|
if (err){
|
||||||
printf("rfcomm_send_internal -> error 0X%02x", err);
|
printf("rfcomm_send_internal -> error 0X%02x", err);
|
||||||
|
} else {
|
||||||
|
printf("Sent %s", command);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -135,6 +137,8 @@ static hfp_connection_t * create_hfp_connection_context(){
|
|||||||
if (!context) return NULL;
|
if (!context) return NULL;
|
||||||
// init state
|
// init state
|
||||||
context->state = HFP_IDLE;
|
context->state = HFP_IDLE;
|
||||||
|
context->line_size = 0;
|
||||||
|
|
||||||
context->negotiated_codec = HFP_Codec_CSVD;
|
context->negotiated_codec = HFP_Codec_CSVD;
|
||||||
context->remote_supported_features = 0;
|
context->remote_supported_features = 0;
|
||||||
context->remote_indicators_update_enabled = 0;
|
context->remote_indicators_update_enabled = 0;
|
||||||
@ -396,5 +400,3 @@ void hfp_set_codec(hfp_connection_t * context, uint8_t *packet, uint16_t size){
|
|||||||
}
|
}
|
||||||
printf("Negotiated Codec 0x%02x\n", context->negotiated_codec);
|
printf("Negotiated Codec 0x%02x\n", context->negotiated_codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
50
src/hfp.h
50
src/hfp.h
@ -88,7 +88,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define HFP_Supported_Features "+BRSF"
|
#define HFP_Supported_Features "+BRSF"
|
||||||
#define HFP_Available_Codecs "+BAC"
|
#define HFP_Available_Codecs "+BAC"
|
||||||
#define HFP_Codec_Indicator "+CIND"
|
#define HFP_Indicator "+CIND"
|
||||||
#define HFP_Enable_Indicator_Status_Update "+CMER"
|
#define HFP_Enable_Indicator_Status_Update "+CMER"
|
||||||
#define HFP_Support_Call_Hold_And_Multiparty_Services "+CHLD"
|
#define HFP_Support_Call_Hold_And_Multiparty_Services "+CHLD"
|
||||||
#define HFP_Generic_Status_Indicator "+BIND"
|
#define HFP_Generic_Status_Indicator "+BIND"
|
||||||
@ -103,16 +103,33 @@ typedef enum {
|
|||||||
HFP_SDP_QUERY_RFCOMM_CHANNEL,
|
HFP_SDP_QUERY_RFCOMM_CHANNEL,
|
||||||
HFP_W4_SDP_QUERY_COMPLETE,
|
HFP_W4_SDP_QUERY_COMPLETE,
|
||||||
HFP_W4_RFCOMM_CONNECTED,
|
HFP_W4_RFCOMM_CONNECTED,
|
||||||
|
|
||||||
HFP_EXCHANGE_SUPPORTED_FEATURES,
|
HFP_EXCHANGE_SUPPORTED_FEATURES,
|
||||||
|
HFP_W4_EXCHANGE_SUPPORTED_FEATURES,
|
||||||
|
|
||||||
HFP_NOTIFY_ON_CODECS,
|
HFP_NOTIFY_ON_CODECS,
|
||||||
|
HFP_W4_NOTIFY_ON_CODECS,
|
||||||
|
|
||||||
HFP_RETRIEVE_INDICATORS,
|
HFP_RETRIEVE_INDICATORS,
|
||||||
|
HFP_W4_RETRIEVE_INDICATORS,
|
||||||
|
|
||||||
HFP_RETRIEVE_INDICATORS_STATUS,
|
HFP_RETRIEVE_INDICATORS_STATUS,
|
||||||
|
HFP_W4_RETRIEVE_INDICATORS_STATUS,
|
||||||
|
|
||||||
HFP_ENABLE_INDICATORS_STATUS_UPDATE,
|
HFP_ENABLE_INDICATORS_STATUS_UPDATE,
|
||||||
|
HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE,
|
||||||
|
|
||||||
HFP_RETRIEVE_CAN_HOLD_CALL,
|
HFP_RETRIEVE_CAN_HOLD_CALL,
|
||||||
|
HFP_W4_RETRIEVE_CAN_HOLD_CALL,
|
||||||
|
|
||||||
HFP_LIST_GENERIC_STATUS_INDICATORS,
|
HFP_LIST_GENERIC_STATUS_INDICATORS,
|
||||||
|
HFP_W4_LIST_GENERIC_STATUS_INDICATORS,
|
||||||
|
|
||||||
HFP_RETRIEVE_GENERIC_STATUS_INDICATORS,
|
HFP_RETRIEVE_GENERIC_STATUS_INDICATORS,
|
||||||
|
HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS,
|
||||||
|
|
||||||
HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS,
|
HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS,
|
||||||
|
HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS,
|
||||||
|
|
||||||
HFP_ACTIVE,
|
HFP_ACTIVE,
|
||||||
HFP_W2_DISCONNECT_RFCOMM,
|
HFP_W2_DISCONNECT_RFCOMM,
|
||||||
@ -120,12 +137,43 @@ typedef enum {
|
|||||||
HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
|
HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
|
||||||
} hfp_state_t;
|
} hfp_state_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HFP_AG_SERVICE, /* <value>=0 implies no service. No Home/Roam network available.
|
||||||
|
<value>=1 implies presence of service. Home/Roam network available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
HFP_AG_CALL, /* <value>=0 means there are no calls in progress
|
||||||
|
<value>=1 means at least one call is in progress
|
||||||
|
*/
|
||||||
|
|
||||||
|
HFP_AG_CALLSETUP, /* <value>=0 means not currently in call set up.
|
||||||
|
<value>=1 means an incoming call process ongoing.
|
||||||
|
<value>=2 means an outgoing call set up is ongoing.
|
||||||
|
<value>=3 means remote party being alerted in an outgoing call.
|
||||||
|
*/
|
||||||
|
HFP_AG_CALLHELD, /* 0 = No calls held
|
||||||
|
1 = Call is placed on hold or active/held calls swapped
|
||||||
|
(The AG has both an active AND a held call)
|
||||||
|
2 = Call on hold, no active call
|
||||||
|
*/
|
||||||
|
HFP_AG_SIGNAL, /* ranges from 0 to 5, Signal Strength indicator */
|
||||||
|
HFP_AG_ROAM, /* <value>=0 means roaming is not active
|
||||||
|
<value>=1 means a roaming is active
|
||||||
|
*/
|
||||||
|
HFP_AG_BATTCHG /* ranges from 0 to 5, Battery Charge */
|
||||||
|
|
||||||
|
} hfp_ag_indicators_t;
|
||||||
|
|
||||||
typedef void (*hfp_callback_t)(uint8_t * event, uint16_t event_size);
|
typedef void (*hfp_callback_t)(uint8_t * event, uint16_t event_size);
|
||||||
|
|
||||||
|
|
||||||
typedef struct hfp_connection {
|
typedef struct hfp_connection {
|
||||||
linked_item_t item;
|
linked_item_t item;
|
||||||
hfp_state_t state;
|
hfp_state_t state;
|
||||||
|
|
||||||
|
uint32_t line_size;
|
||||||
|
uint8_t line_buffer[20];
|
||||||
|
|
||||||
bd_addr_t remote_addr;
|
bd_addr_t remote_addr;
|
||||||
uint16_t con_handle;
|
uint16_t con_handle;
|
||||||
uint16_t rfcomm_channel_nr;
|
uint16_t rfcomm_channel_nr;
|
||||||
|
@ -95,7 +95,7 @@ static void hfp_run(hfp_connection_t * connection){
|
|||||||
}
|
}
|
||||||
|
|
||||||
hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
|
hfp_connection_t * context = provide_hfp_connection_context_for_rfcomm_cid(channel);
|
||||||
if (!context) return NULL;
|
if (!context) return NULL;
|
||||||
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
|
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
|
||||||
size--;
|
size--;
|
||||||
|
164
src/hfp_hf.c
164
src/hfp_hf.c
@ -98,6 +98,7 @@ static int store_bit(uint32_t bitmap, int position, uint8_t value){
|
|||||||
int hfp_hs_exchange_supported_features_cmd(uint16_t cid){
|
int hfp_hs_exchange_supported_features_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s=%d\r\n", HFP_Supported_Features, hfp_supported_features);
|
sprintf(buffer, "AT%s=%d\r\n", HFP_Supported_Features, hfp_supported_features);
|
||||||
|
// printf("exchange_supported_features %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,31 +106,36 @@ int hfp_hs_retrieve_codec_cmd(uint16_t cid){
|
|||||||
char buffer[30];
|
char buffer[30];
|
||||||
int buffer_offset = sprintf(buffer, "AT%s=", HFP_Available_Codecs);
|
int buffer_offset = sprintf(buffer, "AT%s=", HFP_Available_Codecs);
|
||||||
join(buffer, sizeof(buffer), buffer_offset, hfp_codecs, hfp_codecs_nr, 1);
|
join(buffer, sizeof(buffer), buffer_offset, hfp_codecs, hfp_codecs_nr, 1);
|
||||||
|
// printf("retrieve_codec %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hfp_hs_retrieve_indicators_cmd(uint16_t cid){
|
int hfp_hs_retrieve_indicators_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s=?\r\n", HFP_Codec_Indicator);
|
sprintf(buffer, "AT%s=?\r\n", HFP_Indicator);
|
||||||
|
// printf("retrieve_indicators %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hfp_hs_retrieve_indicators_status_cmd(uint16_t cid){
|
int hfp_hs_retrieve_indicators_status_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s?\r\n", HFP_Codec_Indicator);
|
sprintf(buffer, "AT%s?\r\n", HFP_Indicator);
|
||||||
|
// printf("retrieve_indicators_status %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hfp_hs_toggle_indicator_status_update_cmd(uint16_t cid){
|
int hfp_hs_toggle_indicator_status_update_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s\r\n", HFP_Enable_Indicator_Status_Update);
|
sprintf(buffer, "AT%s\r\n", HFP_Enable_Indicator_Status_Update);
|
||||||
|
// printf("toggle_indicator_status_update %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hfp_hs_retrieve_can_hold_call_cmd(uint16_t cid){
|
int hfp_hs_retrieve_can_hold_call_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s\r\n", HFP_Support_Call_Hold_And_Multiparty_Services);
|
sprintf(buffer, "AT%s\r\n", HFP_Support_Call_Hold_And_Multiparty_Services);
|
||||||
|
// printf("retrieve_can_hold_call %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,18 +144,21 @@ int hfp_hs_list_supported_generic_status_indicators_cmd(uint16_t cid){
|
|||||||
char buffer[30];
|
char buffer[30];
|
||||||
int buffer_offset = sprintf(buffer, "AT%s=", HFP_Generic_Status_Indicator);
|
int buffer_offset = sprintf(buffer, "AT%s=", HFP_Generic_Status_Indicator);
|
||||||
join(buffer, sizeof(buffer), buffer_offset, hfp_indicators, hfp_indicators_nr, 2);
|
join(buffer, sizeof(buffer), buffer_offset, hfp_indicators, hfp_indicators_nr, 2);
|
||||||
|
// printf("list_supported_generic_status_indicators %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hfp_hs_retrieve_supported_generic_status_indicators_cmd(uint16_t cid){
|
int hfp_hs_retrieve_supported_generic_status_indicators_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s=?\r\rn", HFP_Generic_Status_Indicator);
|
sprintf(buffer, "AT%s=?\r\rn", HFP_Generic_Status_Indicator);
|
||||||
|
// printf("retrieve_supported_generic_status_indicators %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hfp_hs_list_initital_supported_generic_status_indicators_cmd(uint16_t cid){
|
int hfp_hs_list_initital_supported_generic_status_indicators_cmd(uint16_t cid){
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "AT%s?\r\n", HFP_Generic_Status_Indicator);
|
sprintf(buffer, "AT%s?\r\n", HFP_Generic_Status_Indicator);
|
||||||
|
// printf("list_initital_supported_generic_status_indicators %s\n", buffer);
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +177,6 @@ int has_hf_indicators_feature(hfp_connection_t * connection){
|
|||||||
return get_bit(hfp_supported_features,8) && get_bit(connection->remote_supported_features,10);
|
return get_bit(hfp_supported_features,8) && get_bit(connection->remote_supported_features,10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hfp_run_for_context(hfp_connection_t * connection){
|
static void hfp_run_for_context(hfp_connection_t * connection){
|
||||||
if (!connection) return;
|
if (!connection) return;
|
||||||
if (!rfcomm_can_send_packet_now(connection->rfcomm_cid)) return;
|
if (!rfcomm_can_send_packet_now(connection->rfcomm_cid)) return;
|
||||||
@ -176,66 +184,120 @@ static void hfp_run_for_context(hfp_connection_t * connection){
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
switch (connection->state){
|
switch (connection->state){
|
||||||
case HFP_EXCHANGE_SUPPORTED_FEATURES:
|
case HFP_EXCHANGE_SUPPORTED_FEATURES:
|
||||||
log_info("HFP_EXCHANGE_SUPPORTED_FEATURES 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_exchange_supported_features_cmd(connection->rfcomm_cid);
|
err = hfp_hs_exchange_supported_features_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
|
||||||
break;
|
break;
|
||||||
case HFP_NOTIFY_ON_CODECS:
|
case HFP_NOTIFY_ON_CODECS:
|
||||||
log_info("HFP_NOTIFY_ON_CODECS 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_retrieve_codec_cmd(connection->rfcomm_cid);
|
err = hfp_hs_retrieve_codec_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_NOTIFY_ON_CODECS;
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_INDICATORS:
|
case HFP_RETRIEVE_INDICATORS:
|
||||||
log_info("HFP_RETRIEVE_INDICATORS 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_retrieve_indicators_cmd(connection->rfcomm_cid);
|
err = hfp_hs_retrieve_indicators_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_RETRIEVE_INDICATORS;
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_INDICATORS_STATUS:
|
case HFP_RETRIEVE_INDICATORS_STATUS:
|
||||||
log_info("HFP_RETRIEVE_INDICATORS_STATUS 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_retrieve_indicators_cmd(connection->rfcomm_cid);
|
err = hfp_hs_retrieve_indicators_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_EXCHANGE_SUPPORTED_FEATURES;
|
||||||
break;
|
break;
|
||||||
case HFP_ENABLE_INDICATORS_STATUS_UPDATE:
|
case HFP_ENABLE_INDICATORS_STATUS_UPDATE:
|
||||||
err = 0;
|
|
||||||
if (connection->remote_indicators_update_enabled == 0){
|
if (connection->remote_indicators_update_enabled == 0){
|
||||||
log_info("HFP_ENABLE_INDICATORS_STATUS_UPDATE 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_toggle_indicator_status_update_cmd(connection->rfcomm_cid);
|
err = hfp_hs_toggle_indicator_status_update_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_CAN_HOLD_CALL:
|
case HFP_RETRIEVE_CAN_HOLD_CALL:
|
||||||
log_info("HFP_RETRIEVE_CAN_HOLD_CALL 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_retrieve_can_hold_call_cmd(connection->rfcomm_cid);
|
err = hfp_hs_retrieve_can_hold_call_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
|
||||||
break;
|
break;
|
||||||
case HFP_LIST_GENERIC_STATUS_INDICATORS:
|
case HFP_LIST_GENERIC_STATUS_INDICATORS:
|
||||||
log_info("HFP_LIST_GENERIC_STATUS_INDICATORS 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_list_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
|
err = hfp_hs_list_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
||||||
log_info("HFP_RETRIEVE_GENERIC_STATUS_INDICATORS 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_retrieve_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
|
err = hfp_hs_retrieve_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
||||||
log_info("HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS 0x%02x", connection->rfcomm_cid);
|
|
||||||
err = hfp_hs_list_initital_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
|
err = hfp_hs_list_initital_supported_generic_status_indicators_cmd(connection->rfcomm_cid);
|
||||||
|
if (!err) connection->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
void hfp_parse_indicators(hfp_connection_t * context, uint8_t *packet, uint16_t size){
|
||||||
hfp_connection_t * context = provide_hfp_connection_context_for_rfcomm_cid(channel);
|
uint8_t parse_indicator = 0;
|
||||||
int offset = 0;
|
uint8_t parse_range = 0;
|
||||||
|
uint8_t parse_max_range = 0;
|
||||||
|
uint8_t byte;
|
||||||
|
char indicator[10];
|
||||||
|
char min_range[3];
|
||||||
|
char max_range[3];
|
||||||
|
|
||||||
if (!context) return NULL;
|
int i;
|
||||||
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
|
int pos = 0;
|
||||||
size--;
|
|
||||||
packet++;
|
while ( pos < size ){
|
||||||
|
while (!parse_indicator && pos < size){
|
||||||
|
byte = packet[pos++];
|
||||||
|
if (byte == '"'){
|
||||||
|
parse_indicator = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
while (parse_indicator && pos < size){
|
||||||
|
byte = packet[pos++];
|
||||||
|
if (byte == '"'){
|
||||||
|
parse_indicator = 0;
|
||||||
|
indicator[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
indicator[i++] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!parse_range && pos < size){
|
||||||
|
byte = packet[pos++];
|
||||||
|
if (byte == '('){
|
||||||
|
parse_range = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
while (parse_range && pos < size){
|
||||||
|
byte = packet[pos++];
|
||||||
|
if (byte == ')'){
|
||||||
|
parse_range = 0;
|
||||||
|
parse_max_range = 0;
|
||||||
|
max_range[i] = 0;
|
||||||
|
printf("Indicator %s, min %d, max %d\n", indicator, atoi(min_range), atoi(max_range));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (byte == ','){
|
||||||
|
parse_max_range = 1;
|
||||||
|
min_range[i] = 0;
|
||||||
|
i = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parse_max_range){
|
||||||
|
max_range[i++] = byte;
|
||||||
|
} else {
|
||||||
|
min_range[i++] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hfp_connection_t * handle_message(hfp_connection_t * context, uint8_t *packet, uint16_t size){
|
||||||
|
int offset = 0;
|
||||||
if (context->wait_ok){
|
if (context->wait_ok){
|
||||||
if (strncmp((char *)packet, HFP_OK, strlen(HFP_OK)) == 0){
|
if (strncmp((char *)packet, HFP_OK, strlen(HFP_OK)) == 0){
|
||||||
|
printf("Parsed %s\n", HFP_OK);
|
||||||
switch (context->state){
|
switch (context->state){
|
||||||
case HFP_NOTIFY_ON_CODECS:
|
case HFP_W4_NOTIFY_ON_CODECS:
|
||||||
context->state = HFP_RETRIEVE_INDICATORS;
|
context->state = HFP_RETRIEVE_INDICATORS;
|
||||||
break;
|
break;
|
||||||
case HFP_ENABLE_INDICATORS_STATUS_UPDATE:
|
case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
|
||||||
if (has_call_waiting_and_3way_calling_feature(context)){
|
if (has_call_waiting_and_3way_calling_feature(context)){
|
||||||
context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
|
context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
|
||||||
break;
|
break;
|
||||||
@ -247,11 +309,11 @@ hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HFP_LIST_GENERIC_STATUS_INDICATORS:
|
case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
|
||||||
context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS;
|
context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
||||||
context->state = HFP_ACTIVE;
|
context->state = HFP_ACTIVE;
|
||||||
printf(" state Active! \n");
|
printf(" state Active! \n");
|
||||||
break;
|
break;
|
||||||
@ -266,7 +328,7 @@ hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel
|
|||||||
if (strncmp((char *)packet, HFP_Supported_Features, strlen(HFP_Supported_Features)) == 0){
|
if (strncmp((char *)packet, HFP_Supported_Features, strlen(HFP_Supported_Features)) == 0){
|
||||||
offset = strlen(HFP_Supported_Features) + 1; // +1 for =
|
offset = strlen(HFP_Supported_Features) + 1; // +1 for =
|
||||||
context->remote_supported_features = atoi((char*)&packet[offset]);
|
context->remote_supported_features = atoi((char*)&packet[offset]);
|
||||||
|
printf("Parsed %s: %d (expected 224)\n", HFP_Supported_Features, context->remote_supported_features);
|
||||||
if (has_codec_negotiation_feature(context)){
|
if (has_codec_negotiation_feature(context)){
|
||||||
context->state = HFP_NOTIFY_ON_CODECS;
|
context->state = HFP_NOTIFY_ON_CODECS;
|
||||||
} else {
|
} else {
|
||||||
@ -276,28 +338,24 @@ hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp((char *)packet, HFP_Codec_Indicator, strlen(HFP_Codec_Indicator)) == 0){
|
if (strncmp((char *)packet, HFP_Indicator, strlen(HFP_Indicator)) == 0){
|
||||||
// https://www.bluetooth.org/en-us/specification/assigned-numbers/hands-free-profile
|
// https://www.bluetooth.org/en-us/specification/assigned-numbers/hands-free-profile
|
||||||
/*
|
/*
|
||||||
* 0x01 Enhanced Safety, on/off
|
* 0x01 Enhanced Safety, on/off
|
||||||
* 0x02 Battery Level, 0-100
|
* 0x02 Battery Level, 0-100
|
||||||
*/
|
*/
|
||||||
offset = strlen(HFP_Codec_Indicator) + 1;
|
// printf("Parsed %s, expected ("service",(0,1)),("call",(0,1)),("callsetup",(0,3)),("callheld",(0,2)),("signal",(0,5)),("roam",(0,1)),("battchg",(0,5))\n", HFP_Indicator);
|
||||||
|
|
||||||
|
offset = strlen(HFP_Indicator) + 1;
|
||||||
char * token = strtok((char*)&packet[offset], ",");
|
char * token = strtok((char*)&packet[offset], ",");
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
switch (context->state){
|
switch (context->state){
|
||||||
case HFP_RETRIEVE_INDICATORS:
|
case HFP_W4_RETRIEVE_INDICATORS:
|
||||||
while (token){
|
hfp_parse_indicators(context, &packet[offset], size-offset);
|
||||||
printf("%s\n", token);
|
|
||||||
context->remote_indicators[pos++] = atoi(token);
|
|
||||||
token = strtok(NULL, ",");
|
|
||||||
}
|
|
||||||
context->remote_indicators_nr = pos;
|
|
||||||
context->remote_indicators_status = 0;
|
context->remote_indicators_status = 0;
|
||||||
context->state = HFP_RETRIEVE_INDICATORS_STATUS;
|
context->state = HFP_RETRIEVE_INDICATORS_STATUS;
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_INDICATORS_STATUS:
|
case HFP_W4_RETRIEVE_INDICATORS_STATUS:
|
||||||
while (token){
|
while (token){
|
||||||
printf("%s\n", token);
|
printf("%s\n", token);
|
||||||
store_bit(context->remote_indicators_status, pos, atoi(token));
|
store_bit(context->remote_indicators_status, pos, atoi(token));
|
||||||
@ -327,7 +385,7 @@ hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel
|
|||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
switch (context->state){
|
switch (context->state){
|
||||||
case HFP_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
||||||
while (token){
|
while (token){
|
||||||
printf("%s\n", token);
|
printf("%s\n", token);
|
||||||
context->remote_hf_indicators[pos++] = atoi(token);
|
context->remote_hf_indicators[pos++] = atoi(token);
|
||||||
@ -337,7 +395,7 @@ hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel
|
|||||||
context->remote_hf_indicators_status = 0;
|
context->remote_hf_indicators_status = 0;
|
||||||
context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
|
context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
|
||||||
break;
|
break;
|
||||||
case HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:{
|
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:{
|
||||||
uint16_t indicator = atoi(token);
|
uint16_t indicator = atoi(token);
|
||||||
int status = atoi(strtok(NULL, ","));
|
int status = atoi(strtok(NULL, ","));
|
||||||
if (!status) break;
|
if (!status) break;
|
||||||
@ -360,6 +418,34 @@ hfp_connection_t * hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hfp_parse(hfp_connection_t * context, uint8_t byte){
|
||||||
|
if (byte != '\n' && byte != '\r'){
|
||||||
|
context->line_buffer[context->line_size] = byte;
|
||||||
|
context->line_size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->line_buffer[context->line_size] = '\0';
|
||||||
|
if (context->line_size > 0){
|
||||||
|
handle_message(context, context->line_buffer, context->line_size);
|
||||||
|
}
|
||||||
|
context->line_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!context) return;
|
||||||
|
|
||||||
|
packet[size] = 0;
|
||||||
|
printf("Received %s\n", packet);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i=0;i<size;i++){
|
||||||
|
hfp_parse(context, packet[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void hfp_run(){
|
static void hfp_run(){
|
||||||
linked_item_t *it;
|
linked_item_t *it;
|
||||||
for (it = hfp_get_connections(); it ; it = it->next){
|
for (it = hfp_get_connections(); it ; it = it->next){
|
||||||
|
@ -133,6 +133,7 @@ int btstack_main(int argc, const char * argv[]){
|
|||||||
rfcomm_init();
|
rfcomm_init();
|
||||||
|
|
||||||
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, HFP_Default_HF_Supported_Features, codecs, sizeof(codecs), indicators, sizeof(indicators)/sizeof(uint16_t), 1);
|
||||||
|
// hfp_hf_init(rfcomm_channel_nr, 0x0009, codecs, sizeof(codecs), indicators, sizeof(indicators)/sizeof(uint16_t), 1);
|
||||||
|
|
||||||
hfp_register_packet_handler(packet_handler);
|
hfp_register_packet_handler(packet_handler);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user