2013-10-28 11:38:59

by Jerzy Kasenberg

[permalink] [raw]
Subject: [PATCH 0/4] Add handsfree interface methods to haltest

With this patchset handsfree interface is available in haltest.

Jerzy Kasenberg (4):
android/client: Add skeleton for handsfree calls
android/client: Add code for handsfree callbacks
android/client: Add code for handsfree methods
android/client: Add completion for hf methods

Makefile.android | 2 +
android/Android.mk | 1 +
android/client/haltest.c | 1 +
android/client/if-bt.c | 2 +-
android/client/if-hf.c | 784 ++++++++++++++++++++++++++++++++++++++++++++++
android/client/if-main.h | 2 +
6 files changed, 791 insertions(+), 1 deletion(-)
create mode 100644 android/client/if-hf.c

--
1.7.9.5



2013-10-28 12:42:16

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 0/4] Add handsfree interface methods to haltest

Hi Jerzy,

On Mon, Oct 28, 2013, Jerzy Kasenberg wrote:
> With this patchset handsfree interface is available in haltest.
>
> Jerzy Kasenberg (4):
> android/client: Add skeleton for handsfree calls
> android/client: Add code for handsfree callbacks
> android/client: Add code for handsfree methods
> android/client: Add completion for hf methods
>
> Makefile.android | 2 +
> android/Android.mk | 1 +
> android/client/haltest.c | 1 +
> android/client/if-bt.c | 2 +-
> android/client/if-hf.c | 784 ++++++++++++++++++++++++++++++++++++++++++++++
> android/client/if-main.h | 2 +
> 6 files changed, 791 insertions(+), 1 deletion(-)
> create mode 100644 android/client/if-hf.c

All patches have been applied. Thanks.

Johan

2013-10-28 11:39:00

by Jerzy Kasenberg

[permalink] [raw]
Subject: [PATCH 1/4] android/client: Add skeleton for handsfree calls

This patch adds skeleton for all methods of handsfree along with
all callbacks.
---
Makefile.android | 2 +
android/Android.mk | 1 +
android/client/haltest.c | 1 +
android/client/if-bt.c | 2 +-
android/client/if-hf.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++
android/client/if-main.h | 2 +
6 files changed, 375 insertions(+), 1 deletion(-)
create mode 100644 android/client/if-hf.c

diff --git a/Makefile.android b/Makefile.android
index 01b3cea..fd8043c 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -51,6 +51,7 @@ android_haltest_SOURCES = android/client/haltest.c \
android/client/tabcompletion.c \
android/client/if-av.c \
android/client/if-bt.c \
+ android/client/if-hf.c \
android/client/if-hh.c \
android/client/if-pan.c \
android/client/if-sock.c \
@@ -81,6 +82,7 @@ EXTRA_DIST += android/client/terminal.c \
android/client/history.c \
android/client/if-av.c \
android/client/if-bt.c \
+ android/client/if-hf.c \
android/client/if-hh.c \
android/client/if-pan.c \
android/client/if-sock.c \
diff --git a/android/Android.mk b/android/Android.mk
index 56c43cb..22208e0 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -104,6 +104,7 @@ LOCAL_SRC_FILES := \
client/tabcompletion.c \
client/if-av.c \
client/if-bt.c \
+ client/if-hf.c \
client/if-hh.c \
client/if-pan.c \
client/if-sock.c \
diff --git a/android/client/haltest.c b/android/client/haltest.c
index 6b4030b..7fe0436 100644
--- a/android/client/haltest.c
+++ b/android/client/haltest.c
@@ -32,6 +32,7 @@
const struct interface *interfaces[] = {
&bluetooth_if,
&av_if,
+ &hf_if,
&hh_if,
&pan_if,
&sock_if,
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index dd5d12e..a20a7c6 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -811,7 +811,7 @@ static void get_profile_interface_p(int argc, const char **argv)
RETURN_IF_NULL(if_bluetooth);

if (strcmp(BT_PROFILE_HANDSFREE_ID, id) == 0)
- pif = &dummy; /* TODO: change when if_hf is there */
+ pif = (const void **) &if_hf;
else if (strcmp(BT_PROFILE_ADVANCED_AUDIO_ID, id) == 0)
pif = (const void **) &if_av;
else if (strcmp(BT_PROFILE_HEALTH_ID, id) == 0)
diff --git a/android/client/if-hf.c b/android/client/if-hf.c
new file mode 100644
index 0000000..e4065df
--- /dev/null
+++ b/android/client/if-hf.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "if-main.h"
+
+const bthf_interface_t *if_hf = NULL;
+
+SINTMAP(bthf_at_response_t, -1, "(unknown)")
+ DELEMENT(BTHF_AT_RESPONSE_ERROR),
+ DELEMENT(BTHF_AT_RESPONSE_OK),
+ENDMAP
+
+SINTMAP(bthf_connection_state_t, -1, "(unknown)")
+ DELEMENT(BTHF_CONNECTION_STATE_DISCONNECTED),
+ DELEMENT(BTHF_CONNECTION_STATE_CONNECTING),
+ DELEMENT(BTHF_CONNECTION_STATE_CONNECTED),
+ DELEMENT(BTHF_CONNECTION_STATE_SLC_CONNECTED),
+ DELEMENT(BTHF_CONNECTION_STATE_DISCONNECTING),
+ENDMAP
+
+SINTMAP(bthf_audio_state_t, -1, "(unknown)")
+ DELEMENT(BTHF_AUDIO_STATE_DISCONNECTED),
+ DELEMENT(BTHF_AUDIO_STATE_CONNECTING),
+ DELEMENT(BTHF_AUDIO_STATE_CONNECTED),
+ DELEMENT(BTHF_AUDIO_STATE_DISCONNECTING),
+ENDMAP
+
+SINTMAP(bthf_vr_state_t, -1, "(unknown)")
+ DELEMENT(BTHF_VR_STATE_STOPPED),
+ DELEMENT(BTHF_VR_STATE_STARTED),
+ENDMAP
+
+SINTMAP(bthf_volume_type_t, -1, "(unknown)")
+ DELEMENT(BTHF_VOLUME_TYPE_SPK),
+ DELEMENT(BTHF_VOLUME_TYPE_MIC),
+ENDMAP
+
+SINTMAP(bthf_nrec_t, -1, "(unknown)")
+ DELEMENT(BTHF_NREC_STOP),
+ DELEMENT(BTHF_NREC_START),
+ENDMAP
+
+SINTMAP(bthf_chld_type_t, -1, "(unknown)")
+ DELEMENT(BTHF_CHLD_TYPE_RELEASEHELD),
+ DELEMENT(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD),
+ DELEMENT(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD),
+ DELEMENT(BTHF_CHLD_TYPE_ADDHELDTOCONF),
+ENDMAP
+
+/* Network Status */
+SINTMAP(bthf_network_state_t, -1, "(unknown)")
+ DELEMENT(BTHF_NETWORK_STATE_NOT_AVAILABLE),
+ DELEMENT(BTHF_NETWORK_STATE_AVAILABLE),
+ENDMAP
+
+/* Service type */
+SINTMAP(bthf_service_type_t, -1, "(unknown)")
+ DELEMENT(BTHF_SERVICE_TYPE_HOME),
+ DELEMENT(BTHF_SERVICE_TYPE_ROAMING),
+ENDMAP
+
+SINTMAP(bthf_call_state_t, -1, "(unknown)")
+ DELEMENT(BTHF_CALL_STATE_ACTIVE),
+ DELEMENT(BTHF_CALL_STATE_HELD),
+ DELEMENT(BTHF_CALL_STATE_DIALING),
+ DELEMENT(BTHF_CALL_STATE_ALERTING),
+ DELEMENT(BTHF_CALL_STATE_INCOMING),
+ DELEMENT(BTHF_CALL_STATE_WAITING),
+ DELEMENT(BTHF_CALL_STATE_IDLE),
+ENDMAP
+
+SINTMAP(bthf_call_direction_t, -1, "(unknown)")
+ DELEMENT(BTHF_CALL_DIRECTION_OUTGOING),
+ DELEMENT(BTHF_CALL_DIRECTION_INCOMING),
+ENDMAP
+
+SINTMAP(bthf_call_mode_t, -1, "(unknown)")
+ DELEMENT(BTHF_CALL_TYPE_VOICE),
+ DELEMENT(BTHF_CALL_TYPE_DATA),
+ DELEMENT(BTHF_CALL_TYPE_FAX),
+ENDMAP
+
+SINTMAP(bthf_call_mpty_type_t, -1, "(unknown)")
+ DELEMENT(BTHF_CALL_MPTY_TYPE_SINGLE),
+ DELEMENT(BTHF_CALL_MPTY_TYPE_MULTI),
+ENDMAP
+
+SINTMAP(bthf_call_addrtype_t, -1, "(unknown)")
+ DELEMENT(BTHF_CALL_ADDRTYPE_UNKNOWN),
+ DELEMENT(BTHF_CALL_ADDRTYPE_INTERNATIONAL),
+ENDMAP
+
+/* Callbacks */
+
+/*
+ * Callback for connection state change.
+ * state will have one of the values from BtHfConnectionState
+ */
+static void connection_state_cb(bthf_connection_state_t state,
+ bt_bdaddr_t *bd_addr)
+{
+}
+
+/*
+ * Callback for audio connection state change.
+ * state will have one of the values from BtHfAudioState
+ */
+static void audio_state_cb(bthf_audio_state_t state, bt_bdaddr_t *bd_addr)
+{
+}
+
+/*
+ * Callback for VR connection state change.
+ * state will have one of the values from BtHfVRState
+ */
+static void vr_cmd_cb(bthf_vr_state_t state)
+{
+}
+
+/* Callback for answer incoming call (ATA) */
+static void answer_call_cmd_cb(void)
+{
+}
+
+/* Callback for disconnect call (AT+CHUP) */
+static void hangup_call_cmd_cb(void)
+{
+}
+
+/*
+ * Callback for disconnect call (AT+CHUP)
+ * type will denote Speaker/Mic gain (BtHfVolumeControl).
+ */
+static void volume_cmd_cb(bthf_volume_type_t type, int volume)
+{
+}
+
+/*
+ * Callback for dialing an outgoing call
+ * If number is NULL, redial
+ */
+static void dial_call_cmd_cb(char *number)
+{
+}
+
+/*
+ * Callback for sending DTMF tones
+ * tone contains the dtmf character to be sent
+ */
+static void dtmf_cmd_cb(char tone)
+{
+}
+
+/*
+ * Callback for enabling/disabling noise reduction/echo cancellation
+ * value will be 1 to enable, 0 to disable
+ */
+static void nrec_cmd_cb(bthf_nrec_t nrec)
+{
+}
+
+/*
+ * Callback for call hold handling (AT+CHLD)
+ * value will contain the call hold command (0, 1, 2, 3)
+ */
+static void chld_cmd_cb(bthf_chld_type_t chld)
+{
+}
+
+/* Callback for CNUM (subscriber number) */
+static void cnum_cmd_cb(void)
+{
+}
+
+/* Callback for indicators (CIND) */
+static void cind_cmd_cb(void)
+{
+}
+
+/* Callback for operator selection (COPS) */
+static void cops_cmd_cb(void)
+{
+}
+
+/* Callback for call list (AT+CLCC) */
+static void clcc_cmd_cb(void)
+{
+}
+
+/*
+ * Callback for unknown AT command recd from HF
+ * at_string will contain the unparsed AT string
+ */
+static void unknown_at_cmd_cb(char *at_string)
+{
+}
+
+/* Callback for keypressed (HSP) event. */
+static void key_pressed_cmd_cb(void)
+{
+}
+
+static bthf_callbacks_t hf_cbacks = {
+
+ .size = sizeof(hf_cbacks),
+ .connection_state_cb = connection_state_cb,
+ .audio_state_cb = audio_state_cb,
+ .vr_cmd_cb = vr_cmd_cb,
+ .answer_call_cmd_cb = answer_call_cmd_cb,
+ .hangup_call_cmd_cb = hangup_call_cmd_cb,
+ .volume_cmd_cb = volume_cmd_cb,
+ .dial_call_cmd_cb = dial_call_cmd_cb,
+ .dtmf_cmd_cb = dtmf_cmd_cb,
+ .nrec_cmd_cb = nrec_cmd_cb,
+ .chld_cmd_cb = chld_cmd_cb,
+ .cnum_cmd_cb = cnum_cmd_cb,
+ .cind_cmd_cb = cind_cmd_cb,
+ .cops_cmd_cb = cops_cmd_cb,
+ .clcc_cmd_cb = clcc_cmd_cb,
+ .unknown_at_cmd_cb = unknown_at_cmd_cb,
+ .key_pressed_cmd_cb = key_pressed_cmd_cb,
+};
+
+/* init */
+
+static void init_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_hf);
+
+ EXEC(if_hf->init, &hf_cbacks);
+}
+
+/* connect */
+
+
+static void connect_p(int argc, const char **argv)
+{
+}
+
+/* disconnect */
+
+static void disconnect_p(int argc, const char **argv)
+{
+}
+
+/* create an audio connection */
+
+static void connect_audio_p(int argc, const char **argv)
+{
+}
+
+/* close the audio connection */
+
+static void disconnect_audio_p(int argc, const char **argv)
+{
+}
+
+/* start voice recognition */
+
+static void start_voice_recognition_p(int argc, const char **argv)
+{
+}
+
+/* stop voice recognition */
+
+static void stop_voice_recognition_p(int argc, const char **argv)
+{
+}
+
+/* volume control */
+
+static void volume_control_p(int argc, const char **argv)
+{
+}
+
+/* Combined device status change notification */
+
+static void device_status_notification_p(int argc, const char **argv)
+{
+}
+
+/* Response for COPS command */
+
+static void cops_response_p(int argc, const char **argv)
+{
+}
+
+/* Response for CIND command */
+
+static void cind_response_p(int argc, const char **argv)
+{
+}
+
+/* Pre-formatted AT response, typically in response to unknown AT cmd */
+
+static void formatted_at_response_p(int argc, const char **argv)
+{
+}
+
+/* at_response */
+
+static void at_response_p(int argc, const char **argv)
+{
+}
+
+/* response for CLCC command */
+
+static void clcc_response_p(int argc, const char **argv)
+{
+}
+
+/* phone state change */
+static void phone_state_change_p(int argc, const char **argv)
+{
+}
+
+/* cleanup */
+
+static void cleanup_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_hf);
+
+ EXECV(if_hf->cleanup);
+ if_hf = NULL;
+}
+
+static struct method methods[] = {
+ STD_METHOD(init),
+ STD_METHODH(connect, "<addr>"),
+ STD_METHODH(disconnect, "<addr>"),
+ STD_METHODH(connect_audio, "<addr>"),
+ STD_METHODH(disconnect_audio, "<addr>"),
+ STD_METHOD(start_voice_recognition),
+ STD_METHOD(stop_voice_recognition),
+ STD_METHODH(volume_control, "<vol_type> <volume>"),
+ STD_METHODH(device_status_notification,
+ "<ntk_state> <svt_type> <signal> <batt_chg>"),
+ STD_METHODH(cops_response, "<cops string>"),
+ STD_METHODH(cind_response,
+ "<svc> <num_active> <num_held> <setup_state> <signal> <roam> <batt_chg>"),
+ STD_METHODH(formatted_at_response, "<at_response>"),
+ STD_METHODH(at_response, "<response_code> [<error_code>]"),
+ STD_METHODH(clcc_response,
+ "<index> <direction> <state> <mode> <mpty> <number> <type>"),
+ STD_METHODH(phone_state_change,
+ "<num_active> <num_held> <setup_state> <number> <type>"),
+ STD_METHOD(cleanup),
+ END_METHOD
+};
+
+const struct interface hf_if = {
+ .name = "handsfree",
+ .methods = methods
+};
diff --git a/android/client/if-main.h b/android/client/if-main.h
index eaee914..37086dd 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -45,6 +45,7 @@
/* Interfaces from hal that can be populated during application lifetime */
extern const bt_interface_t *if_bluetooth;
extern const btav_interface_t *if_av;
+extern const bthf_interface_t *if_hf;
extern const bthh_interface_t *if_hh;
extern const btpan_interface_t *if_pan;
extern const btsock_interface_t *if_sock;
@@ -62,6 +63,7 @@ extern const struct interface bluetooth_if;
extern const struct interface av_if;
extern const struct interface pan_if;
extern const struct interface sock_if;
+extern const struct interface hf_if;
extern const struct interface hh_if;

/* Interfaces that will show up in tool (first part of command line) */
--
1.7.9.5


2013-10-28 11:39:03

by Jerzy Kasenberg

[permalink] [raw]
Subject: [PATCH 4/4] android/client: Add completion for hf methods

This patch adds completion functions to handsfree methods.
---
android/client/if-hf.c | 124 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 114 insertions(+), 10 deletions(-)

diff --git a/android/client/if-hf.c b/android/client/if-hf.c
index 585a569..c23fb13 100644
--- a/android/client/if-hf.c
+++ b/android/client/if-hf.c
@@ -269,6 +269,14 @@ static void init_p(int argc, const char **argv)

/* connect */

+static void connect_c(int argc, const char **argv, enum_func *enum_func,
+ void **user)
+{
+ if (argc == 3) {
+ *user = NULL;
+ *enum_func = enum_devices;
+ }
+}

static void connect_p(int argc, const char **argv)
{
@@ -282,6 +290,22 @@ static void connect_p(int argc, const char **argv)

/* disconnect */

+/*
+ * 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
+
static void disconnect_p(int argc, const char **argv)
{
bt_bdaddr_t addr;
@@ -294,6 +318,9 @@ static void disconnect_p(int argc, const char **argv)

/* create an audio connection */

+/* Map completion to connected_addr_c */
+#define connect_audio_c connected_addr_c
+
static void connect_audio_p(int argc, const char **argv)
{
bt_bdaddr_t addr;
@@ -306,6 +333,9 @@ static void connect_audio_p(int argc, const char **argv)

/* close the audio connection */

+/* Map completion to connected_addr_c */
+#define disconnect_audio_c connected_addr_c
+
static void disconnect_audio_p(int argc, const char **argv)
{
bt_bdaddr_t addr;
@@ -336,6 +366,15 @@ static void stop_voice_recognition_p(int argc, const char **argv)

/* volume control */

+static void volume_control_c(int argc, const char **argv, enum_func *enum_func,
+ void **user)
+{
+ if (argc == 3) {
+ *user = TYPE_ENUM(bthf_volume_type_t);
+ *enum_func = enum_defines;
+ }
+}
+
static void volume_control_p(int argc, const char **argv)
{
bthf_volume_type_t type;
@@ -362,6 +401,19 @@ static void volume_control_p(int argc, const char **argv)

/* Combined device status change notification */

+static void device_status_notification_c(int argc, const char **argv,
+ enum_func *enum_func,
+ void **user)
+{
+ if (argc == 3) {
+ *user = TYPE_ENUM(bthf_network_state_t);
+ *enum_func = enum_defines;
+ } else if (argc == 4) {
+ *user = TYPE_ENUM(bthf_service_type_t);
+ *enum_func = enum_defines;
+ }
+}
+
static void device_status_notification_p(int argc, const char **argv)
{
bthf_network_state_t ntk_state;
@@ -420,6 +472,15 @@ static void cops_response_p(int argc, const char **argv)

/* Response for CIND command */

+static void cind_response_c(int argc, const char **argv, enum_func *enum_func,
+ void **user)
+{
+ if (argc == 6) {
+ *user = TYPE_ENUM(bthf_call_state_t);
+ *enum_func = enum_defines;
+ }
+}
+
static void cind_response_p(int argc, const char **argv)
{
int svc;
@@ -502,6 +563,15 @@ static void formatted_at_response_p(int argc, const char **argv)

/* at_response */

+static void at_response_c(int argc, const char **argv, enum_func *enum_func,
+ void **user)
+{
+ if (argc == 3) {
+ *user = TYPE_ENUM(bthf_at_response_t);
+ *enum_func = enum_defines;
+ }
+}
+
static void at_response_p(int argc, const char **argv)
{
bthf_at_response_t response_code;
@@ -525,6 +595,27 @@ static void at_response_p(int argc, const char **argv)

/* response for CLCC command */

+static void clcc_response_c(int argc, const char **argv, enum_func *enum_func,
+ void **user)
+{
+ if (argc == 4) {
+ *user = TYPE_ENUM(bthf_call_direction_t);
+ *enum_func = enum_defines;
+ } else if (argc == 5) {
+ *user = TYPE_ENUM(bthf_call_state_t);
+ *enum_func = enum_defines;
+ } else if (argc == 6) {
+ *user = TYPE_ENUM(bthf_call_mode_t);
+ *enum_func = enum_defines;
+ } else if (argc == 7) {
+ *user = TYPE_ENUM(bthf_call_mpty_type_t);
+ *enum_func = enum_defines;
+ } else if (argc == 9) {
+ *user = TYPE_ENUM(bthf_call_addrtype_t);
+ *enum_func = enum_defines;
+ }
+}
+
static void clcc_response_p(int argc, const char **argv)
{
int index;
@@ -591,6 +682,19 @@ static void clcc_response_p(int argc, const char **argv)
}

/* phone state change */
+
+static void phone_state_change_c(int argc, const char **argv,
+ enum_func *enum_func, void **user)
+{
+ if (argc == 5) {
+ *user = TYPE_ENUM(bthf_call_state_t);
+ *enum_func = enum_defines;
+ } else if (argc == 7) {
+ *user = TYPE_ENUM(bthf_call_addrtype_t);
+ *enum_func = enum_defines;
+ }
+}
+
static void phone_state_change_p(int argc, const char **argv)
{
int num_active;
@@ -652,23 +756,23 @@ static void cleanup_p(int argc, const char **argv)

static struct method methods[] = {
STD_METHOD(init),
- STD_METHODH(connect, "<addr>"),
- STD_METHODH(disconnect, "<addr>"),
- STD_METHODH(connect_audio, "<addr>"),
- STD_METHODH(disconnect_audio, "<addr>"),
+ 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_METHODH(volume_control, "<vol_type> <volume>"),
- STD_METHODH(device_status_notification,
+ STD_METHODCH(volume_control, "<vol_type> <volume>"),
+ STD_METHODCH(device_status_notification,
"<ntk_state> <svt_type> <signal> <batt_chg>"),
STD_METHODH(cops_response, "<cops string>"),
- STD_METHODH(cind_response,
+ STD_METHODCH(cind_response,
"<svc> <num_active> <num_held> <setup_state> <signal> <roam> <batt_chg>"),
STD_METHODH(formatted_at_response, "<at_response>"),
- STD_METHODH(at_response, "<response_code> [<error_code>]"),
- STD_METHODH(clcc_response,
+ STD_METHODCH(at_response, "<response_code> [<error_code>]"),
+ STD_METHODCH(clcc_response,
"<index> <direction> <state> <mode> <mpty> <number> <type>"),
- STD_METHODH(phone_state_change,
+ STD_METHODCH(phone_state_change,
"<num_active> <num_held> <setup_state> <number> <type>"),
STD_METHOD(cleanup),
END_METHOD
--
1.7.9.5


2013-10-28 11:39:02

by Jerzy Kasenberg

[permalink] [raw]
Subject: [PATCH 3/4] android/client: Add code for handsfree methods

This patch adds implementation of handsfree methods to haltest.
---
android/client/if-hf.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 289 insertions(+)

diff --git a/android/client/if-hf.c b/android/client/if-hf.c
index 43c7f47..585a569 100644
--- a/android/client/if-hf.c
+++ b/android/client/if-hf.c
@@ -272,83 +272,372 @@ static void init_p(int argc, const char **argv)

static void connect_p(int argc, const char **argv)
{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_hf);
+ VERIFY_ADDR_ARG(2, &addr);
+
+ EXEC(if_hf->connect, &addr);
}

/* disconnect */

static void disconnect_p(int argc, const char **argv)
{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_hf);
+ VERIFY_ADDR_ARG(2, &addr);
+
+ EXEC(if_hf->disconnect, &addr);
}

/* create an audio connection */

static void connect_audio_p(int argc, const char **argv)
{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_hf);
+ VERIFY_ADDR_ARG(2, &addr);
+
+ EXEC(if_hf->connect_audio, &addr);
}

/* close the audio connection */

static void disconnect_audio_p(int argc, const char **argv)
{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_hf);
+ VERIFY_ADDR_ARG(2, &addr);
+
+ EXEC(if_hf->disconnect_audio, &addr);
}

/* start voice recognition */

static void start_voice_recognition_p(int argc, const char **argv)
{
+ RETURN_IF_NULL(if_hf);
+
+ EXEC(if_hf->start_voice_recognition);
}

/* stop voice recognition */

static void stop_voice_recognition_p(int argc, const char **argv)
{
+ RETURN_IF_NULL(if_hf);
+
+ EXEC(if_hf->stop_voice_recognition);
}

/* volume control */

static void volume_control_p(int argc, const char **argv)
{
+ bthf_volume_type_t type;
+ int volume;
+
+ RETURN_IF_NULL(if_hf);
+
+ /* volume type */
+ if (argc <= 2) {
+ haltest_error("No volume type specified\n");
+ return;
+ }
+ type = str2bthf_volume_type_t(argv[2]);
+
+ /* volume */
+ if (argc <= 3) {
+ haltest_error("No volume specified\n");
+ return;
+ }
+ volume = atoi(argv[3]);
+
+ EXEC(if_hf->volume_control, type, volume);
}

/* Combined device status change notification */

static void device_status_notification_p(int argc, const char **argv)
{
+ bthf_network_state_t ntk_state;
+ bthf_service_type_t svc_type;
+ int signal;
+ int batt_chg;
+
+ RETURN_IF_NULL(if_hf);
+
+ /* network state */
+ if (argc <= 2) {
+ haltest_error("No network state specified\n");
+ return;
+ }
+ ntk_state = str2bthf_network_state_t(argv[2]);
+
+ /* service type */
+ if (argc <= 3) {
+ haltest_error("No service type specified\n");
+ return;
+ }
+ svc_type = str2bthf_service_type_t(argv[3]);
+
+ /* signal */
+ if (argc <= 4) {
+ haltest_error("No signal specified\n");
+ return;
+ }
+ signal = atoi(argv[4]);
+
+ /* batt_chg */
+ if (argc <= 5) {
+ haltest_error("No batt_chg specified\n");
+ return;
+ }
+ batt_chg = atoi(argv[5]);
+
+ EXEC(if_hf->device_status_notification, ntk_state, svc_type, signal,
+ batt_chg);
}

/* Response for COPS command */

static void cops_response_p(int argc, const char **argv)
{
+ RETURN_IF_NULL(if_hf);
+
+ /* response */
+ if (argc <= 2) {
+ haltest_error("No cops specified\n");
+ return;
+ }
+
+ EXEC(if_hf->cops_response, argv[2]);
}

/* Response for CIND command */

static void cind_response_p(int argc, const char **argv)
{
+ int svc;
+ int num_active;
+ int num_held;
+ bthf_call_state_t call_setup_state;
+ int signal;
+ int roam;
+ int batt_chg;
+
+ RETURN_IF_NULL(if_hf);
+
+ /* svc */
+ if (argc <= 2) {
+ haltest_error("No service specified\n");
+ return;
+ }
+ svc = atoi(argv[2]);
+
+ /* num active */
+ if (argc <= 3) {
+ haltest_error("No num active specified\n");
+ return;
+ }
+ num_active = atoi(argv[3]);
+
+ /* num held */
+ if (argc <= 4) {
+ haltest_error("No num held specified\n");
+ return;
+ }
+ num_held = atoi(argv[4]);
+
+ /* call setup state */
+ if (argc <= 5) {
+ haltest_error("No call setup state specified\n");
+ return;
+ }
+ call_setup_state = str2bthf_call_state_t(argv[5]);
+
+ /* signal */
+ if (argc <= 6) {
+ haltest_error("No signal specified\n");
+ return;
+ }
+ signal = atoi(argv[6]);
+
+ /* roam */
+ if (argc <= 7) {
+ haltest_error("No roam specified\n");
+ return;
+ }
+ roam = atoi(argv[7]);
+
+ /* batt_chg */
+ if (argc <= 8) {
+ haltest_error("No batt_chg specified\n");
+ return;
+ }
+ batt_chg = atoi(argv[8]);
+
+ EXEC(if_hf->cind_response, svc, num_active, num_held, call_setup_state,
+ signal, roam, batt_chg);
}

/* Pre-formatted AT response, typically in response to unknown AT cmd */

static void formatted_at_response_p(int argc, const char **argv)
{
+ RETURN_IF_NULL(if_hf);
+
+ /* response */
+ if (argc <= 2) {
+ haltest_error("No response specified\n");
+ return;
+ }
+
+ EXEC(if_hf->formatted_at_response, argv[2]);
}

/* at_response */

static void at_response_p(int argc, const char **argv)
{
+ bthf_at_response_t response_code;
+ int error_code = 0;
+
+ RETURN_IF_NULL(if_hf);
+
+ /* response type */
+ if (argc <= 2) {
+ haltest_error("No response specified\n");
+ return;
+ }
+ response_code = str2bthf_at_response_t(argv[2]);
+
+ /* error code */
+ if (argc >= 3)
+ error_code = atoi(argv[3]);
+
+ EXEC(if_hf->at_response, response_code, error_code);
}

/* response for CLCC command */

static void clcc_response_p(int argc, const char **argv)
{
+ 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;
+
+ RETURN_IF_NULL(if_hf);
+
+ /* index */
+ if (argc <= 2) {
+ haltest_error("No index specified\n");
+ return;
+ }
+ index = atoi(argv[2]);
+
+ /* direction */
+ if (argc <= 3) {
+ haltest_error("No direction specified\n");
+ return;
+ }
+ dir = str2bthf_call_direction_t(argv[3]);
+
+ /* call state */
+ if (argc <= 4) {
+ haltest_error("No call state specified\n");
+ return;
+ }
+ state = str2bthf_call_state_t(argv[4]);
+
+ /* call mode */
+ if (argc <= 5) {
+ haltest_error("No mode specified\n");
+ return;
+ }
+ mode = str2bthf_call_mode_t(argv[5]);
+
+ /* call mpty type */
+ if (argc <= 6) {
+ haltest_error("No mpty type specified\n");
+ return;
+ }
+ mpty = str2bthf_call_mpty_type_t(argv[6]);
+
+ /* number */
+ if (argc <= 7) {
+ haltest_error("No number specified\n");
+ return;
+ }
+ number = argv[7];
+
+ /* call mpty type */
+ if (argc <= 8) {
+ haltest_error("No address type specified\n");
+ return;
+ }
+ type = str2bthf_call_addrtype_t(argv[8]);
+
+ EXEC(if_hf->clcc_response, index, dir, state, mode, mpty, number,
+ type);
}

/* phone state change */
static void phone_state_change_p(int argc, const char **argv)
{
+ int num_active;
+ int num_held;
+ bthf_call_state_t call_setup_state;
+ const char *number;
+ bthf_call_addrtype_t type;
+
+ RETURN_IF_NULL(if_hf);
+
+ /* num_active */
+ if (argc <= 2) {
+ haltest_error("No num_active specified\n");
+ return;
+ }
+ num_active = atoi(argv[2]);
+
+ /* num_held */
+ if (argc <= 3) {
+ haltest_error("No num_held specified\n");
+ return;
+ }
+ num_held = atoi(argv[3]);
+
+ /* setup state */
+ if (argc <= 4) {
+ haltest_error("No call setup state specified\n");
+ return;
+ }
+ call_setup_state = str2bthf_call_state_t(argv[4]);
+
+ /* number */
+ if (argc <= 5) {
+ haltest_error("No number specified\n");
+ return;
+ }
+ number = argv[5];
+
+ /* call mpty type */
+ if (argc <= 6) {
+ haltest_error("No address type specified\n");
+ return;
+ }
+ type = str2bthf_call_addrtype_t(argv[6]);
+
+ EXEC(if_hf->phone_state_change, num_active, num_held, call_setup_state,
+ number, type);
}

/* cleanup */
--
1.7.9.5


2013-10-28 11:39:01

by Jerzy Kasenberg

[permalink] [raw]
Subject: [PATCH 2/4] android/client: Add code for handsfree callbacks

This adds implementation for handsfree callbacks.
---
android/client/if-hf.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/android/client/if-hf.c b/android/client/if-hf.c
index e4065df..43c7f47 100644
--- a/android/client/if-hf.c
+++ b/android/client/if-hf.c
@@ -106,6 +106,8 @@ ENDMAP

/* Callbacks */

+static char last_addr[MAX_ADDR_STR_LEN];
+
/*
* Callback for connection state change.
* state will have one of the values from BtHfConnectionState
@@ -113,6 +115,9 @@ ENDMAP
static void connection_state_cb(bthf_connection_state_t state,
bt_bdaddr_t *bd_addr)
{
+ haltest_info("%s: state=%s bd_addr=%s\n", __func__,
+ bthf_connection_state_t2str(state),
+ bt_bdaddr_t2str(bd_addr, last_addr));
}

/*
@@ -121,6 +126,9 @@ static void connection_state_cb(bthf_connection_state_t state,
*/
static void audio_state_cb(bthf_audio_state_t state, bt_bdaddr_t *bd_addr)
{
+ haltest_info("%s: state=%s bd_addr=%s\n", __func__,
+ bthf_audio_state_t2str(state),
+ bt_bdaddr_t2str(bd_addr, last_addr));
}

/*
@@ -129,16 +137,19 @@ static void audio_state_cb(bthf_audio_state_t state, bt_bdaddr_t *bd_addr)
*/
static void vr_cmd_cb(bthf_vr_state_t state)
{
+ haltest_info("%s: state=%s\n", __func__, bthf_vr_state_t2str(state));
}

/* Callback for answer incoming call (ATA) */
static void answer_call_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

/* Callback for disconnect call (AT+CHUP) */
static void hangup_call_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

/*
@@ -147,6 +158,8 @@ static void hangup_call_cmd_cb(void)
*/
static void volume_cmd_cb(bthf_volume_type_t type, int volume)
{
+ haltest_info("%s: type=%s volume=%d\n", __func__,
+ bthf_volume_type_t2str(type), volume);
}

/*
@@ -155,6 +168,7 @@ static void volume_cmd_cb(bthf_volume_type_t type, int volume)
*/
static void dial_call_cmd_cb(char *number)
{
+ haltest_info("%s: number=%s\n", __func__, number);
}

/*
@@ -163,6 +177,7 @@ static void dial_call_cmd_cb(char *number)
*/
static void dtmf_cmd_cb(char tone)
{
+ haltest_info("%s: tone=%d\n", __func__, tone);
}

/*
@@ -171,6 +186,7 @@ static void dtmf_cmd_cb(char tone)
*/
static void nrec_cmd_cb(bthf_nrec_t nrec)
{
+ haltest_info("%s: nrec=%s\n", __func__, bthf_nrec_t2str(nrec));
}

/*
@@ -179,26 +195,31 @@ static void nrec_cmd_cb(bthf_nrec_t nrec)
*/
static void chld_cmd_cb(bthf_chld_type_t chld)
{
+ haltest_info("%s: chld=%s\n", __func__, bthf_chld_type_t2str(chld));
}

/* Callback for CNUM (subscriber number) */
static void cnum_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

/* Callback for indicators (CIND) */
static void cind_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

/* Callback for operator selection (COPS) */
static void cops_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

/* Callback for call list (AT+CLCC) */
static void clcc_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

/*
@@ -207,11 +228,13 @@ static void clcc_cmd_cb(void)
*/
static void unknown_at_cmd_cb(char *at_string)
{
+ haltest_info("%s: at_string=%s\n", __func__, at_string);
}

/* Callback for keypressed (HSP) event. */
static void key_pressed_cmd_cb(void)
{
+ haltest_info("%s\n", __func__);
}

static bthf_callbacks_t hf_cbacks = {
--
1.7.9.5