mirror of
https://github.com/IllusionMan1212/ShockPair.git
synced 2026-10-24 10:12:26 +00:00
659 lines
18 KiB
C
659 lines
18 KiB
C
// SPDX-License-Identifier: Apache-2.0
|
|||
|
|
/*
|
||
|
|
* Copyright (C) 2014 Intel Corporation
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define _GNU_SOURCE
|
||
|
|
#include "if-main.h"
|
||
|
|
#include "../hal-utils.h"
|
||
|
|
|
||
|
|
const bthf_client_interface_t *if_hf_client = NULL;
|
||
|
|
|
||
|
|
static char last_addr[MAX_ADDR_STR_LEN];
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_connection_state_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED),
|
||
|
|
DELEMENT(BTHF_CLIENT_CONNECTION_STATE_CONNECTING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CONNECTION_STATE_CONNECTED),
|
||
|
|
DELEMENT(BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED),
|
||
|
|
DELEMENT(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_audio_state_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_AUDIO_STATE_DISCONNECTED),
|
||
|
|
DELEMENT(BTHF_CLIENT_AUDIO_STATE_CONNECTING),
|
||
|
|
DELEMENT(BTHF_CLIENT_AUDIO_STATE_CONNECTED),
|
||
|
|
DELEMENT(BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_vr_state_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_VR_STATE_STOPPED),
|
||
|
|
DELEMENT(BTHF_CLIENT_VR_STATE_STARTED),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_network_state_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_NETWORK_STATE_NOT_AVAILABLE),
|
||
|
|
DELEMENT(BTHF_CLIENT_NETWORK_STATE_AVAILABLE),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_service_type_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_SERVICE_TYPE_HOME),
|
||
|
|
DELEMENT(BTHF_CLIENT_SERVICE_TYPE_ROAMING),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_call_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_NO_CALLS_IN_PROGRESS),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_CALLS_IN_PROGRESS),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_callsetup_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLSETUP_NONE),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLSETUP_INCOMING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLSETUP_OUTGOING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLSETUP_ALERTING),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_callheld_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLHELD_NONE),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLHELD_HOLD_AND_ACTIVE),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALLHELD_HOLD),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_resp_and_hold_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_RESP_AND_HOLD_HELD),
|
||
|
|
DELEMENT(BTRH_CLIENT_RESP_AND_HOLD_ACCEPT),
|
||
|
|
DELEMENT(BTRH_CLIENT_RESP_AND_HOLD_REJECT),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_call_direction_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_DIRECTION_OUTGOING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_DIRECTION_INCOMING),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_call_state_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_ACTIVE),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_HELD),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_DIALING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_ALERTING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_INCOMING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_WAITING),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_STATE_HELD_BY_RESP_HOLD),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_call_mpty_type_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_MPTY_TYPE_MULTI),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_volume_type_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_VOLUME_TYPE_SPK),
|
||
|
|
DELEMENT(BTHF_CLIENT_VOLUME_TYPE_MIC),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_cmd_complete_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_OK),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_CARRIER),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR_BUSY),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_ANSWER),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR_DELAYED),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR_BLACKLISTED),
|
||
|
|
DELEMENT(BTHF_CLIENT_CMD_COMPLETE_ERROR_CME),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_subscriber_service_type_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_SERVICE_UNKNOWN),
|
||
|
|
DELEMENT(BTHF_CLIENT_SERVICE_VOICE),
|
||
|
|
DELEMENT(BTHF_CLIENT_SERVICE_FAX),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_in_band_ring_state_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED),
|
||
|
|
DELEMENT(BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
SINTMAP(bthf_client_call_action_t, -1, "(unknown)")
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_0),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_1),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_2),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_3),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_4),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_1x),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHLD_2x),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_ATA),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_CHUP),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_BTRH_0),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_BTRH_1),
|
||
|
|
DELEMENT(BTHF_CLIENT_CALL_ACTION_BTRH_2),
|
||
|
|
ENDMAP
|
||
|
|
|
||
|
|
/* Callbacks */
|
||
|
|
|
||
|
|
static char features_str[512];
|
||
|
|
|
||
|
|
static const char *pear_features_t2str(int feat)
|
||
|
|
{
|
||
|
|
memset(features_str, 0, sizeof(features_str));
|
||
|
|
|
||
|
|
sprintf(features_str, "BTHF_CLIENT_PEER_FEAT_3WAY: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_ECNR: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_VREC: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_INBAND: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_VTAG: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_REJECT: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_ECS: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_ECC: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_EXTERR: %s,\n"
|
||
|
|
"BTHF_CLIENT_PEER_FEAT_CODEC: %s,\n",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_3WAY ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_ECNR ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_VREC ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_INBAND ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_VTAG ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_REJECT ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_ECS ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_ECC ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_EXTERR ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_PEER_FEAT_CODEC ? "True" : "False");
|
||
|
|
|
||
|
|
return features_str;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const char *chld_features_t2str(int feat)
|
||
|
|
{
|
||
|
|
memset(features_str, 0, sizeof(features_str));
|
||
|
|
|
||
|
|
sprintf(features_str,
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_REL: %s,\n"
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_REL_ACC: %s,\n"
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_REL_X: %s,\n"
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_HOLD_ACC: %s,\n"
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_PRIV_X: %s,\n"
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_MERGE: %s,\n"
|
||
|
|
"BTHF_CLIENT_CHLD_FEAT_MERGE_DETACH: %s,\n",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_REL ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_REL_ACC ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_REL_X ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_HOLD_ACC ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_PRIV_X ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_MERGE ? "True" : "False",
|
||
|
|
feat & BTHF_CLIENT_CHLD_FEAT_MERGE_DETACH ? "True" : "False");
|
||
|
|
|
||
|
|
return features_str;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for connection state change. */
|
||
|
|
static void hf_client_connection_state_callback(
|
||
|
|
bthf_client_connection_state_t state,
|
||
|
|
unsigned int peer_feat,
|
||
|
|
unsigned int chld_feat,
|
||
|
|
bt_bdaddr_t *bd_addr)
|
||
|
|
{
|
||
|
|
haltest_info("%s: state=%s bd_addr=%s\n", __func__,
|
||
|
|
bthf_client_connection_state_t2str(state),
|
||
|
|
bt_bdaddr_t2str(bd_addr, last_addr));
|
||
|
|
|
||
|
|
if (state != BTHF_CLIENT_CONNECTION_STATE_CONNECTED)
|
||
|
|
return;
|
||
|
|
|
||
|
|
haltest_info("\tpeer_features%s\n", pear_features_t2str(peer_feat));
|
||
|
|
haltest_info("\tchld_feat=%s\n", chld_features_t2str(chld_feat));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for audio connection state change. */
|
||
|
|
static void hf_client_audio_state_callback(bthf_client_audio_state_t state,
|
||
|
|
bt_bdaddr_t *bd_addr)
|
||
|
|
{
|
||
|
|
haltest_info("%s: state=%s bd_addr=%s\n", __func__,
|
||
|
|
bthf_client_audio_state_t2str(state),
|
||
|
|
bt_bdaddr_t2str(bd_addr, last_addr));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for VR connection state change. */
|
||
|
|
static void hf_client_vr_cmd_callback(bthf_client_vr_state_t state)
|
||
|
|
{
|
||
|
|
haltest_info("%s: vr_state=%s\n", __func__,
|
||
|
|
bthf_client_vr_state_t2str(state));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for network state change */
|
||
|
|
static void hf_client_network_state_callback(bthf_client_network_state_t state)
|
||
|
|
{
|
||
|
|
haltest_info("%s: network_state=%s\n", __func__,
|
||
|
|
bthf_client_network_state_t2str(state));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for network roaming status change */
|
||
|
|
static void hf_client_network_roaming_callback(bthf_client_service_type_t type)
|
||
|
|
{
|
||
|
|
haltest_info("%s: service_type=%s\n", __func__,
|
||
|
|
bthf_client_service_type_t2str(type));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for signal strength indication */
|
||
|
|
static void hf_client_network_signal_callback(int signal_strength)
|
||
|
|
{
|
||
|
|
haltest_info("%s: signal strength=%d\n", __func__, signal_strength);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for battery level indication */
|
||
|
|
static void hf_client_battery_level_callback(int battery_level)
|
||
|
|
{
|
||
|
|
haltest_info("%s: battery_lvl=%d\n", __func__, battery_level);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for current operator name */
|
||
|
|
static void hf_client_current_operator_callback(const char *name)
|
||
|
|
{
|
||
|
|
haltest_info("%s: operator_name=%s\n", __func__, name);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for call indicator */
|
||
|
|
static void hf_client_call_callback(bthf_client_call_t call)
|
||
|
|
{
|
||
|
|
haltest_info("%s: call_state=%s\n", __func__,
|
||
|
|
bthf_client_call_t2str(call));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for callsetup indicator */
|
||
|
|
static void hf_client_callsetup_callback(bthf_client_callsetup_t callsetup)
|
||
|
|
{
|
||
|
|
haltest_info("%s: callsetup=%s\n", __func__,
|
||
|
|
bthf_client_callsetup_t2str(callsetup));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for callheld indicator */
|
||
|
|
static void hf_client_callheld_callback(bthf_client_callheld_t callheld)
|
||
|
|
{
|
||
|
|
haltest_info("%s: callheld=%s\n", __func__,
|
||
|
|
bthf_client_callheld_t2str(callheld));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for response and hold */
|
||
|
|
static void hf_client_resp_and_hold_callback(
|
||
|
|
bthf_client_resp_and_hold_t resp_and_hold)
|
||
|
|
{
|
||
|
|
haltest_info("%s: resp_and_hold=%s\n", __func__,
|
||
|
|
bthf_client_resp_and_hold_t2str(resp_and_hold));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for Calling Line Identification notification */
|
||
|
|
static void hf_client_clip_callback(const char *number)
|
||
|
|
{
|
||
|
|
haltest_info("%s: number=%s\n", __func__, number);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for Call Waiting notification */
|
||
|
|
static void hf_client_call_waiting_callback(const char *number)
|
||
|
|
{
|
||
|
|
haltest_info("%s: number=%s\n", __func__, number);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for listing current calls. Can be called multiple time. */
|
||
|
|
static void hf_client_current_calls_callback(int index,
|
||
|
|
bthf_client_call_direction_t dir,
|
||
|
|
bthf_client_call_state_t state,
|
||
|
|
bthf_client_call_mpty_type_t mpty,
|
||
|
|
const char *number)
|
||
|
|
{
|
||
|
|
haltest_info("%s: index=%d, direction=%s, state=%s, m_party=%s\n",
|
||
|
|
__func__, index,
|
||
|
|
bthf_client_call_direction_t2str(dir),
|
||
|
|
bthf_client_call_state_t2str(state),
|
||
|
|
bthf_client_call_mpty_type_t2str(mpty));
|
||
|
|
|
||
|
|
if (number)
|
||
|
|
haltest_info("%s: number=%s\n", __func__, number);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for audio volume change */
|
||
|
|
static void hf_client_volume_change_callback(bthf_client_volume_type_t type,
|
||
|
|
int volume)
|
||
|
|
{
|
||
|
|
haltest_info("%s: vol_type=%s, value=%d\n", __func__,
|
||
|
|
bthf_client_volume_type_t2str(type), volume);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for command complete event */
|
||
|
|
static void hf_client_cmd_complete_callback(bthf_client_cmd_complete_t type,
|
||
|
|
int cme)
|
||
|
|
{
|
||
|
|
haltest_info("%s: type=%s, cme=%d\n", __func__,
|
||
|
|
bthf_client_cmd_complete_t2str(type), cme);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for subscriber information */
|
||
|
|
static void hf_client_subscriber_info_callback(const char *name,
|
||
|
|
bthf_client_subscriber_service_type_t type)
|
||
|
|
{
|
||
|
|
haltest_info("%s: name=%s, type=%s\n", __func__, name,
|
||
|
|
bthf_client_subscriber_service_type_t2str(type));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for in-band ring tone settings */
|
||
|
|
static void hf_client_in_band_ring_tone_callback(
|
||
|
|
bthf_client_in_band_ring_state_t state)
|
||
|
|
{
|
||
|
|
haltest_info("%s: state=%s\n", __func__,
|
||
|
|
bthf_client_in_band_ring_state_t2str(state));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for requested number from AG */
|
||
|
|
static void hf_client_last_voice_tag_number_callback(const char *number)
|
||
|
|
{
|
||
|
|
haltest_info("%s: number=%s\n", __func__, number);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Callback for sending ring indication to app */
|
||
|
|
static void hf_client_ring_indication_callback(void)
|
||
|
|
{
|
||
|
|
haltest_info("%s\n", __func__);
|
||
|
|
}
|
||
|
|
|
||
|
|
static bthf_client_callbacks_t hf_client_cbacks = {
|
||
|
|
.size = sizeof(hf_client_cbacks),
|
||
|
|
.connection_state_cb = hf_client_connection_state_callback,
|
||
|
|
.audio_state_cb = hf_client_audio_state_callback,
|
||
|
|
.vr_cmd_cb = hf_client_vr_cmd_callback,
|
||
|
|
.network_state_cb = hf_client_network_state_callback,
|
||
|
|
.network_roaming_cb = hf_client_network_roaming_callback,
|
||
|
|
.network_signal_cb = hf_client_network_signal_callback,
|
||
|
|
.battery_level_cb = hf_client_battery_level_callback,
|
||
|
|
.current_operator_cb = hf_client_current_operator_callback,
|
||
|
|
.call_cb = hf_client_call_callback,
|
||
|
|
.callsetup_cb = hf_client_callsetup_callback,
|
||
|
|
.callheld_cb = hf_client_callheld_callback,
|
||
|
|
.resp_and_hold_cb = hf_client_resp_and_hold_callback,
|
||
|
|
.clip_cb = hf_client_clip_callback,
|
||
|
|
.call_waiting_cb = hf_client_call_waiting_callback,
|
||
|
|
.current_calls_cb = hf_client_current_calls_callback,
|
||
|
|
.volume_change_cb = hf_client_volume_change_callback,
|
||
|
|
.cmd_complete_cb = hf_client_cmd_complete_callback,
|
||
|
|
.subscriber_info_cb = hf_client_subscriber_info_callback,
|
||
|
|
.in_band_ring_tone_cb = hf_client_in_band_ring_tone_callback,
|
||
|
|
.last_voice_tag_number_callback =
|
||
|
|
hf_client_last_voice_tag_number_callback,
|
||
|
|
.ring_indication_cb = hf_client_ring_indication_callback,
|
||
|
|
};
|
||
|
|
|
||
|
|
/* init */
|
||
|
|
static void init_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->init, &hf_client_cbacks);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void connect_c(int argc, const char **argv, enum_func *enum_func,
|
||
|
|
void **user)
|
||
|
|
{
|
||
|
|
if (argc == 3) {
|
||
|
|
*user = NULL;
|
||
|
|
*enum_func = enum_devices;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* connect to audio gateway */
|
||
|
|
static void connect_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
bt_bdaddr_t addr;
|
||
|
|
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
VERIFY_ADDR_ARG(2, &addr);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->connect, &addr);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* This completion function will be used for several methods
|
||
|
|
* returning recently connected address
|
||
|
|
*/
|
||
|
|
static void connected_addr_c(int argc, const char **argv, enum_func *enum_func,
|
||
|
|
void **user)
|
||
|
|
{
|
||
|
|
if (argc == 3) {
|
||
|
|
*user = last_addr;
|
||
|
|
*enum_func = enum_one_string;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Map completion to connected_addr_c */
|
||
|
|
#define disconnect_c connected_addr_c
|
||
|
|
|
||
|
|
/* disconnect from audio gateway */
|
||
|
|
static void disconnect_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
bt_bdaddr_t addr;
|
||
|
|
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
VERIFY_ADDR_ARG(2, &addr);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->disconnect, &addr);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void connect_audio_c(int argc, const char **argv, enum_func *enum_func,
|
||
|
|
void **user)
|
||
|
|
{
|
||
|
|
if (argc == 3) {
|
||
|
|
*user = NULL;
|
||
|
|
*enum_func = enum_devices;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* create an audio connection */
|
||
|
|
static void connect_audio_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
bt_bdaddr_t addr;
|
||
|
|
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
VERIFY_ADDR_ARG(2, &addr);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->connect_audio, &addr);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Map completion to connected_addr_c */
|
||
|
|
#define disconnect_audio_c connected_addr_c
|
||
|
|
|
||
|
|
/* close the audio connection */
|
||
|
|
static void disconnect_audio_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
bt_bdaddr_t addr;
|
||
|
|
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
VERIFY_ADDR_ARG(2, &addr);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->disconnect_audio, &addr);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* start voice recognition */
|
||
|
|
static void start_voice_recognition_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->start_voice_recognition);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* stop voice recognition */
|
||
|
|
static void stop_voice_recognition_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->stop_voice_recognition);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void volume_control_c(int argc, const char **argv, enum_func *enum_func,
|
||
|
|
void **user)
|
||
|
|
{
|
||
|
|
if (argc == 3) {
|
||
|
|
*user = TYPE_ENUM(bthf_client_volume_type_t);
|
||
|
|
*enum_func = enum_defines;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* volume control */
|
||
|
|
static void volume_control_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
bthf_client_volume_type_t type;
|
||
|
|
int volume;
|
||
|
|
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
/* volume type */
|
||
|
|
if (argc <= 2) {
|
||
|
|
haltest_error("No volume type specified\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
type = str2bthf_client_volume_type_t(argv[2]);
|
||
|
|
|
||
|
|
/* volume */
|
||
|
|
if (argc <= 3) {
|
||
|
|
haltest_error("No volume specified\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
volume = atoi(argv[3]);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->volume_control, type, volume);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* place a call with number a number */
|
||
|
|
static void dial_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
/* number string */
|
||
|
|
if (argc <= 2) {
|
||
|
|
haltest_info("Number not specified. Redial\n");
|
||
|
|
EXEC(if_hf_client->dial, NULL);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
EXEC(if_hf_client->dial, argv[2]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* place a call with number specified by location (speed dial) */
|
||
|
|
static void dial_memory_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
/* memory index */
|
||
|
|
if (argc <= 2) {
|
||
|
|
haltest_error("No memory index specified\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
EXEC(if_hf_client->dial_memory, atoi(argv[2]));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void handle_call_action_c(int argc, const char **argv,
|
||
|
|
enum_func *enum_func, void **user)
|
||
|
|
{
|
||
|
|
if (argc == 3) {
|
||
|
|
*user = TYPE_ENUM(bthf_client_call_action_t);
|
||
|
|
*enum_func = enum_defines;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* perform specified call related action */
|
||
|
|
static void handle_call_action_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
bthf_client_call_action_t action;
|
||
|
|
int index = 0;
|
||
|
|
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
/* action */
|
||
|
|
if (argc <= 2) {
|
||
|
|
haltest_error("No action specified\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
action = str2bthf_client_call_action_t(argv[2]);
|
||
|
|
|
||
|
|
/* call index */
|
||
|
|
if (action == BTHF_CLIENT_CALL_ACTION_CHLD_1x ||
|
||
|
|
action == BTHF_CLIENT_CALL_ACTION_CHLD_2x) {
|
||
|
|
if (argc <= 3) {
|
||
|
|
haltest_error("No call index specified\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
index = atoi(argv[3]);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXEC(if_hf_client->handle_call_action, action, index);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* query list of current calls */
|
||
|
|
static void query_current_calls_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->query_current_calls);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* query name of current selected operator */
|
||
|
|
static void query_current_operator_name_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->query_current_operator_name);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Retrieve subscriber information */
|
||
|
|
static void retrieve_subscriber_info_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->retrieve_subscriber_info);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Send DTMF code*/
|
||
|
|
static void send_dtmf_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->send_dtmf, *argv[2]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Request a phone number from AG corresponding to last voice tag recorded */
|
||
|
|
static void request_last_voice_tag_number_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXEC(if_hf_client->request_last_voice_tag_number);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Closes the interface. */
|
||
|
|
static void cleanup_p(int argc, const char **argv)
|
||
|
|
{
|
||
|
|
RETURN_IF_NULL(if_hf_client);
|
||
|
|
|
||
|
|
EXECV(if_hf_client->cleanup);
|
||
|
|
if_hf_client = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
static struct method methods[] = {
|
||
|
|
STD_METHOD(init),
|
||
|
|
STD_METHODCH(connect, "<addr>"),
|
||
|
|
STD_METHODCH(disconnect, "<addr>"),
|
||
|
|
STD_METHODCH(connect_audio, "<addr>"),
|
||
|
|
STD_METHODCH(disconnect_audio, "<addr>"),
|
||
|
|
STD_METHOD(start_voice_recognition),
|
||
|
|
STD_METHOD(stop_voice_recognition),
|
||
|
|
STD_METHODCH(volume_control, "<volume_type> <value>"),
|
||
|
|
STD_METHODH(dial, "<destination_number>"),
|
||
|
|
STD_METHODH(dial_memory, "<memory_location>"),
|
||
|
|
STD_METHODCH(handle_call_action, "<call_action> <call_index>"),
|
||
|
|
STD_METHOD(query_current_calls),
|
||
|
|
STD_METHOD(query_current_operator_name),
|
||
|
|
STD_METHOD(retrieve_subscriber_info),
|
||
|
|
STD_METHODH(send_dtmf, "<code>"),
|
||
|
|
STD_METHOD(request_last_voice_tag_number),
|
||
|
|
STD_METHOD(cleanup),
|
||
|
|
END_METHOD
|
||
|
|
};
|
||
|
|
|
||
|
|
const struct interface hf_client_if = {
|
||
|
|
.name = "handsfree_client",
|
||
|
|
.methods = methods
|
||
|
|
};
|