/***************************************************************************** ** ** Name: wm_hfp_hsp_client.c ** ** Description: This file contains the sample functions for bluetooth hand-free/hand-set profile client application ** *****************************************************************************/ #include #include #include #include #include "wm_bt_config.h" #if (WM_BTA_HFP_HSP_INCLUDED == CFG_ON) #include "wm_bt_hf_client.h" #include "wm_hfp_hsp_client.h" #include "wm_bt_util.h" #if (WM_AUDIO_BOARD_INCLUDED == CFG_ON) #include "audio.h" #endif const char *dump_hf_client_call_state(tls_bthf_client_call_state_t event); const char *dump_hf_client_call(tls_bthf_client_call_t event); const char *dump_hf_client_callsetup(tls_bthf_client_callsetup_t event); const char *dump_hf_client_callheld(tls_bthf_client_callheld_t event); const char *dump_hf_client_resp_and_hold(tls_bthf_client_resp_and_hold_t event); const char *dump_hf_client_call_direction(uint16_t event); const char *dump_hf_client_conn_state(tls_bthf_client_connection_state_t event); const char *dump_hf_client_audio_state(tls_bthf_client_audio_state_t event); #if (WM_AUDIO_BOARD_INCLUDED == CFG_ON) static uint32_t Stereo2Mono(void *audio_buf, uint32_t len, int LR) { if (!audio_buf || !len || len % 4) { printf( "%s arg err\n", __func__); return 0; } int16_t *buf = audio_buf; uint32_t i = 0; LR = LR ? 1 : 0; for (i = 0; i < len / 4; i++) { buf[i] = buf[i * 2 + LR]; } return len / 2; } static void dump_sco_data(uint8_t *p_data,uint16_t length) { int i = 0; for(i=0; i<32; i++) { printf("%02x ", p_data[i]); } printf("\r\n"); } /*SCO data to application*/ int btif_co_sco_data_incoming(uint8_t type, uint8_t *p_data,uint16_t length) { dump_sco_data(p_data, length); FifoWrite(p_data, length); return length; } /*SCO data sent over HCI*/ int btif_co_sco_data_outgoing(uint8_t type, uint8_t *p_data,uint16_t length) { memset(p_data, 0, length); return length; } #else /*SCO data to application*/ int btif_co_sco_data_incoming(uint8_t type, uint8_t *p_data,uint16_t length) { return length; } /*SCO data sent over HCI*/ int btif_co_sco_data_outgoing(uint8_t type, uint8_t *p_data,uint16_t length) { memset(p_data, 0, length); return length; } #endif void hfp_client_connection_state_cb(tls_bthf_client_connection_state_t state, unsigned int peer_feat, unsigned int chld_feat, tls_bt_addr_t *bd_addr) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_connection_state_cb: state=%s\r\n", dump_hf_client_conn_state(state)); } void hfp_client_audio_state_cb(tls_bthf_client_audio_state_t state, tls_bt_addr_t *bd_addr) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_audio_state_cb: state=%s\r\n", dump_hf_client_audio_state(state)); switch(state) { case WM_BTHF_CLIENT_AUDIO_STATE_DISCONNECTED: #if (WM_AUDIO_BOARD_INCLUDED == CFG_ON) PlayStop(); #endif break; case WM_BTHF_CLIENT_AUDIO_STATE_CONNECTING: break; case WM_BTHF_CLIENT_AUDIO_STATE_CONNECTED: //break; case WM_BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC: #if (WM_AUDIO_BOARD_INCLUDED == CFG_ON) PlayStart(8000, 16, 2); #endif break; } } void hfp_client_vr_cmd_cb(tls_bthf_client_vr_state_t state) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_vr_cmd_cb: state=%d\r\n", state); } /** Callback for network state change */ void hfp_client_network_state_cb(tls_bthf_client_network_state_t state) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_network_state_cb: state=%d\r\n", state); } /** Callback for network roaming status change */ void hfp_client_network_roaming_cb(tls_bthf_client_service_type_t type) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_network_roaming_cb, type=%d\r\n", type); } /** Callback for signal strength indication */ void hfp_client_network_signal_cb(int signal_strength) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_network_signal_cb(%d)\r\n", signal_strength); } /** Callback for battery level indication */ void hfp_client_battery_level_cb(int battery_level) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_battery_level_cb, battery_level=%d\r\n", battery_level); } /** Callback for current operator name */ void hfp_client_current_operator_cb(const char *name) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_current_operator_cb, name=%s\r\n", name); } /** Callback for call indicator */ void hfp_client_call_cb(tls_bthf_client_call_t call) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_call_cb,call=%s\r\n", dump_hf_client_call(call)); } /** Callback for callsetup indicator */ void hfp_client_callsetup_cb(tls_bthf_client_callsetup_t callsetup) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_callsetup_cb, callsetup=%s\r\n", dump_hf_client_callsetup(callsetup)); ; } /** Callback for callheld indicator */ void hfp_client_callheld_cb(tls_bthf_client_callheld_t callheld) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_callheld_cb, callheld=%s\r\n", dump_hf_client_callheld(callheld)); } /** Callback for response and hold */ void hfp_client_resp_and_hold_cb(tls_bthf_client_resp_and_hold_t resp_and_hold) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_resp_and_hold_cb, resp_and_hold=%s\r\n", dump_hf_client_resp_and_hold(resp_and_hold)); } /** Callback for Calling Line Identification notification * Will be called only when there is an incoming call and number is provided. */ void hfp_client_clip_cb(const char *number) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_clip_cb, number=%s\r\n", number); } /** * Callback for Call Waiting notification */ void hfp_client_call_waiting_cb(const char *number) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_call_waiting_cb, number=%s\r\n", number); } /** * Callback for listing current calls. Can be called multiple time. * If number is unknown NULL is passed. */ void hfp_client_current_calls_cb(int index, tls_bthf_client_call_direction_t dir, tls_bthf_client_call_state_t state, tls_bthf_client_call_mpty_type_t mpty, const char *number) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_current_calls_cb, bthf_client_call_state_t=%s, number=%s\r\n", dump_hf_client_call_state(state), number); } /** Callback for audio volume change */ void hfp_client_volume_change_cb(tls_bthf_client_volume_type_t type, int volume) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_volume_change_cb, type=%d, volume=%d\r\n", type, volume); } /** Callback for command complete event * cme is valid only for BTHF_CLIENT_CMD_COMPLETE_ERROR_CME type */ void hfp_client_cmd_complete_cb(tls_bthf_client_cmd_complete_t type, int cme) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_cmd_complete_cb, type=%d\r\n", type); } /** Callback for subscriber information */ void hfp_client_subscriber_info_cb(const char *name, tls_bthf_client_subscriber_service_type_t type) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_subscriber_info_cb, name=%s, type=%d\r\n", name, type); } /** Callback for in-band ring tone settings */ void hfp_client_in_band_ring_tone_cb(tls_bthf_client_in_band_ring_state_t state) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_in_band_ring_tone_cb, in_band_ring_state=%d\r\n", state); } /** * Callback for requested number from AG */ void hfp_client_last_voice_tag_number_cb(const char *number) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_last_voice_tag_number_cb\r\n"); } /** * Callback for sending ring indication to app */ void hfp_client_ring_indication_cb(void) { TLS_BT_APPL_TRACE_DEBUG("hfp_client_ring_indication_cb\r\n"); } static void wm_bt_hfp_client_callback(tls_bthf_client_evt_t evt, tls_bthf_client_msg_t *msg) { switch(evt) { case WM_BTHF_CLIENT_CONNECTION_STATE_EVT: hfp_client_connection_state_cb(msg->connection_state_msg.state, msg->connection_state_msg.peer_feat, msg->connection_state_msg.chld_feat, msg->connection_state_msg.bd_addr); break; case WM_BTHF_CLIENT_AUDIO_STATE_EVT: hfp_client_audio_state_cb(msg->audio_state_msg.state, msg->audio_state_msg.bd_addr); break; case WM_BTHF_CLIENT_VR_CMD_EVT: hfp_client_vr_cmd_cb(msg->vr_cmd_msg.state); break; case WM_BTHF_CLIENT_NETWORK_STATE_EVT: hfp_client_network_state_cb(msg->network_state_msg.state); break; case WM_BTHF_CLIENT_NETWORK_ROAMING_EVT: hfp_client_network_roaming_cb(msg->network_roaming_msg.type); break; case WM_BTHF_CLIENT_NETWORK_SIGNAL_EVT: hfp_client_network_signal_cb(msg->network_signal_msg.signal_strength); break; case WM_BTHF_CLIENT_BATTERY_LEVEL_EVT: hfp_client_battery_level_cb(msg->battery_level_msg.battery_level); break; case WM_BTHF_CLIENT_CURRENT_OPERATOR_EVT: hfp_client_current_operator_cb(msg->current_operator_msg.name); break; case WM_BTHF_CLIENT_CALL_EVT: hfp_client_call_cb(msg->call_msg.call); break; case WM_BTHF_CLIENT_CALLSETUP_EVT: hfp_client_callsetup_cb(msg->callsetup_msg.callsetup); break; case WM_BTHF_CLIENT_CALLHELD_EVT: hfp_client_callheld_cb(msg->callheld_msg.callheld); break; case WM_BTHF_CLIENT_RESP_AND_HOLD_EVT: hfp_client_resp_and_hold_cb(msg->resp_and_hold_msg.resp_and_hold); break; case WM_BTHF_CLIENT_CLIP_EVT: hfp_client_clip_cb(msg->clip_msg.number); break; case WM_BTHF_CLIENT_CALL_WAITING_EVT: hfp_client_call_waiting_cb(msg->call_waiting_msg.number); break; case WM_BTHF_CLIENT_CURRENT_CALLS_EVT: hfp_client_current_calls_cb(msg->current_calls_msg.index, msg->current_calls_msg.dir, msg->current_calls_msg.state, msg->current_calls_msg.mpty, msg->current_calls_msg.number); break; case WM_BTHF_CLIENT_VOLUME_CHANGE_EVT: hfp_client_volume_change_cb(msg->volume_change_msg.type, msg->volume_change_msg.volume); break; case WM_BTHF_CLIENT_CMD_COMPLETE_EVT: hfp_client_cmd_complete_cb(msg->cmd_complete_msg.type, msg->cmd_complete_msg.cme); break; case WM_BTHF_CLIENT_SUBSCRIBER_INFO_EVT: hfp_client_subscriber_info_cb(msg->subscriber_info_msg.name, msg->subscriber_info_msg.type); break; case WM_BTHF_CLIENT_IN_BAND_RING_TONE_EVT: hfp_client_in_band_ring_tone_cb(msg->in_band_ring_tone_msg.state); break; case WM_BTHF_CLIENT_LAST_VOICE_TAG_NUMBER_EVT: hfp_client_last_voice_tag_number_cb(msg->last_voice_tag_number_msg.number); break; case WM_BTHF_CLIENT_RING_INDICATION_EVT: hfp_client_ring_indication_cb(); break; default: TLS_BT_APPL_TRACE_WARNING("Unknown hfp client callback evt:%d\r\n", evt); break; } } tls_bt_status_t tls_bt_enable_hfp_client() { tls_bt_status_t status; status = tls_bt_hf_client_init(wm_bt_hfp_client_callback); return status; } tls_bt_status_t tls_bt_disable_hfp_client() { tls_bt_status_t status; status = tls_bt_hf_client_deinit(); return status; } tls_bt_status_t tls_bt_dial_number(const char* number) { TLS_BT_APPL_TRACE_DEBUG("tls_bt_dial_number:%s\r\n", number); return tls_bt_hf_client_dial(number); } #ifndef CASE_RETURN_STR #define CASE_RETURN_STR(const) case const: return #const; #endif const char *dump_hf_client_call_state(tls_bthf_client_call_state_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_ACTIVE) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_HELD) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_DIALING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_ALERTING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_INCOMING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_WAITING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_STATE_HELD_BY_RESP_HOLD) default: return "UNKNOWN MSG ID(call_state)"; } } const char *dump_hf_client_call(tls_bthf_client_call_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_NO_CALLS_IN_PROGRESS) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_CALLS_IN_PROGRESS) default: return "UNKNOWN MSG ID(call)"; } } const char *dump_hf_client_callsetup(tls_bthf_client_callsetup_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_CALLSETUP_NONE) CASE_RETURN_STR(WM_BTHF_CLIENT_CALLSETUP_INCOMING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALLSETUP_OUTGOING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALLSETUP_ALERTING) default: return "UNKNOWN MSG ID(callheld)"; } } const char *dump_hf_client_callheld(tls_bthf_client_callheld_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_CALLHELD_NONE) CASE_RETURN_STR(WM_BTHF_CLIENT_CALLHELD_HOLD_AND_ACTIVE) CASE_RETURN_STR(WM_BTHF_CLIENT_CALLHELD_HOLD) default: return "UNKNOWN MSG ID(callheld)"; } } const char *dump_hf_client_resp_and_hold(tls_bthf_client_resp_and_hold_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_RESP_AND_HOLD_HELD) CASE_RETURN_STR(WM_BTRH_CLIENT_RESP_AND_HOLD_ACCEPT) CASE_RETURN_STR(WM_BTRH_CLIENT_RESP_AND_HOLD_REJECT) default: return "UNKNOWN MSG ID(hf_client_resp_and_hold)"; } } const char *dump_hf_client_call_direction(uint16_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_DIRECTION_OUTGOING) CASE_RETURN_STR(WM_BTHF_CLIENT_CALL_DIRECTION_INCOMING) default: return "UNKNOWN MSG ID(hf_client_call_direction)"; } } const char *dump_hf_client_conn_state(tls_bthf_client_connection_state_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED) CASE_RETURN_STR(WM_BTHF_CLIENT_CONNECTION_STATE_CONNECTING) CASE_RETURN_STR(WM_BTHF_CLIENT_CONNECTION_STATE_CONNECTED) CASE_RETURN_STR(WM_BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) CASE_RETURN_STR(WM_BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING) default: return "UNKNOWN MSG ID(hf_client_conn_state)"; } } const char *dump_hf_client_audio_state(tls_bthf_client_audio_state_t event) { switch(event) { CASE_RETURN_STR(WM_BTHF_CLIENT_AUDIO_STATE_DISCONNECTED) CASE_RETURN_STR(WM_BTHF_CLIENT_AUDIO_STATE_CONNECTING) CASE_RETURN_STR(WM_BTHF_CLIENT_AUDIO_STATE_CONNECTED) CASE_RETURN_STR(WM_BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC) default: return "UNKNOWN MSG ID(hf_client_audio_state)"; } } #endif