diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 6e11367..601c14f 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
return ret;
}
+static bt_status_t handsfree_connect(bt_bdaddr_t *bd_addr)
+{
+ struct hal_cmd_handsfree_connect cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ if (!bd_addr)
+ return BT_STATUS_PARM_INVALID;
+
+ memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
+{
+ struct hal_cmd_handsfree_disconnect cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ if (!bd_addr)
+ return BT_STATUS_PARM_INVALID;
+
+ memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_DISCONNECT, sizeof(cmd), &cmd,
+ 0, NULL, NULL);
+}
+
+static bt_status_t connect_audio(bt_bdaddr_t *bd_addr)
+{
+ struct hal_cmd_handsfree_connect_audio cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ if (!bd_addr)
+ return BT_STATUS_PARM_INVALID;
+
+ memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_CONNECT_AUDIO, sizeof(cmd),
+ &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t disconnect_audio(bt_bdaddr_t *bd_addr)
+{
+ struct hal_cmd_handsfree_disconnect_audio cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ if (!bd_addr)
+ return BT_STATUS_PARM_INVALID;
+
+ memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_DISCONNECT_AUDIO, sizeof(cmd),
+ &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t start_voice_recognition(void)
+{
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_START_VR,
+ 0, NULL, 0, NULL, NULL);
+}
+
+static bt_status_t stop_voice_recognition(void)
+{
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_STOP_VR,
+ 0, NULL, 0, NULL, NULL);
+}
+
+static bt_status_t volume_control(bthf_volume_type_t type, int volume)
+{
+ struct hal_cmd_handsfree_volume_control cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ cmd.type = type;
+ cmd.volume = volume;
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_VOLUME_CONTROL, sizeof(cmd),
+ &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t device_status_notification(bthf_network_state_t state,
+ bthf_service_type_t type,
+ int signal, int battery)
+{
+ struct hal_cmd_handsfree_device_status_notif cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ cmd.state = state;
+ cmd.type = type;
+ cmd.signal = signal;
+ cmd.battery = battery;
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t cops_response(const char *cops)
+{
+ struct hal_cmd_handsfree_cops_response *cmd;
+ bt_status_t status;
+ int len;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ if (!cops)
+ return BT_STATUS_PARM_INVALID;
+
+ len = sizeof(*cmd) + strlen(cops);
+
+ cmd = malloc(len);
+ if (!cmd)
+ return BT_STATUS_NOMEM;
+
+ cmd->len = strlen(cops);
+ memcpy(cmd->buf, cops, cmd->len);
+
+ status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_COPS_RESPONSE, len, cmd, 0,
+ NULL, NULL);
+
+ free(cmd);
+
+ return status;
+}
+
+static bt_status_t cind_response(int svc, int num_active, int num_held,
+ bthf_call_state_t state, int signal,
+ int roam, int batt_chg)
+{
+ struct hal_cmd_handsfree_cind_response cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ cmd.svc = svc;
+ cmd.num_active = num_active;
+ cmd.num_held = num_held;
+ cmd.state = state;
+ cmd.signal = signal;
+ cmd.roam = roam;
+ cmd.batt_chg = batt_chg;
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_CIND_RESPONSE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t formatted_at_response(const char *rsp)
+{
+ struct hal_cmd_handsfree_formatted_at_response *cmd;
+ bt_status_t status;
+ int len;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ if (!rsp)
+ return BT_STATUS_PARM_INVALID;
+
+ len = sizeof(*cmd) + strlen(rsp);
+
+ cmd = malloc(len);
+ if (!cmd)
+ return BT_STATUS_NOMEM;
+
+ cmd->len = strlen(rsp);
+ memcpy(cmd->buf, rsp, cmd->len);
+
+ status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE, len,
+ cmd, 0, NULL, NULL);
+
+ free(cmd);
+
+ return status;
+}
+
+static bt_status_t at_response(bthf_at_response_t response, int error)
+{
+ struct hal_cmd_handsfree_at_response cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ cmd.response = response;
+ cmd.error = error;
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_AT_RESPONSE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
+ bthf_call_state_t state,
+ bthf_call_mode_t mode,
+ bthf_call_mpty_type_t mpty,
+ const char *number,
+ bthf_call_addrtype_t type)
+{
+ struct hal_cmd_handsfree_clcc_response *cmd;
+ bt_status_t status;
+ int len;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ len = sizeof(*cmd);
+ if (number)
+ len += strlen(number);
+
+ cmd = malloc(len);
+ if (!cmd)
+ return BT_STATUS_NOMEM;
+
+ cmd->index = index;
+ cmd->dir = dir;
+ cmd->state = state;
+ cmd->mode = mode;
+ cmd->mpty = mpty;
+ cmd->type = type;
+
+ if (number) {
+ cmd->number_len = strlen(number);
+ memcpy(cmd->number, number, cmd->number_len);
+ } else {
+ cmd->number_len = 0;
+ }
+
+ status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_CLCC_RESPONSE, len,
+ cmd, 0, NULL, NULL);
+
+ free(cmd);
+
+ return status;
+}
+
+static bt_status_t phone_state_change(int num_active, int num_held,
+ bthf_call_state_t state,
+ const char *number,
+ bthf_call_addrtype_t type)
+{
+ struct hal_cmd_handsfree_phone_state_change *cmd;
+ bt_status_t status;
+ int len;
+
+ DBG("");
+
+ if (!interface_ready())
+ return BT_STATUS_NOT_READY;
+
+ len = sizeof(*cmd);
+ if (number)
+ len += strlen(number);
+
+ cmd = malloc(len);
+ if (!cmd)
+ return BT_STATUS_NOMEM;
+
+ cmd->num_active = num_active;
+ cmd->num_held = num_held;
+ cmd->state = state;
+ cmd->type = type;
+
+ if (number) {
+ cmd->number_len = strlen(number);
+ memcpy(cmd->number, number, cmd->number_len);
+ } else {
+ cmd->number_len = 0;
+ }
+
+ status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
+ len, cmd, 0, NULL, NULL);
+
+ free(cmd);
+
+ return status;
+}
+
static void cleanup(void)
{
struct hal_cmd_unregister_module cmd;
static bthf_interface_t iface = {
.size = sizeof(iface),
.init = init,
+ .connect = handsfree_connect,
+ .disconnect = disconnect,
+ .connect_audio = connect_audio,
+ .disconnect_audio = disconnect_audio,
+ .start_voice_recognition = start_voice_recognition,
+ .stop_voice_recognition = stop_voice_recognition,
+ .volume_control = volume_control,
+ .device_status_notification = device_status_notification,
+ .cops_response = cops_response,
+ .cind_response = cind_response,
+ .formatted_at_response = formatted_at_response,
+ .at_response = at_response,
+ .clcc_response = clcc_response,
+ .phone_state_change = phone_state_change,
.cleanup = cleanup
};