* [PATCH 01/13] android/handsfree: Add initial files
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 02/13] android/handsfree: Add commands and events definition to IPC header Szymon Janc
` (12 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This adds initial HAL and daemon code for Handsfree profile.
---
android/Android.mk | 2 ++
android/Makefile.am | 2 ++
android/hal-bluetooth.c | 3 ++
android/hal-handsfree.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++
android/hal.h | 2 ++
android/handsfree.c | 41 +++++++++++++++++++++
android/handsfree.h | 25 +++++++++++++
android/main.c | 14 ++++++++
8 files changed, 185 insertions(+)
create mode 100644 android/hal-handsfree.c
create mode 100644 android/handsfree.c
create mode 100644 android/handsfree.h
diff --git a/android/Android.mk b/android/Android.mk
index 03f2d8b..c16f29a 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -32,6 +32,7 @@ LOCAL_SRC_FILES := \
bluez/android/avctp.c \
bluez/android/avrcp.c \
bluez/android/pan.c \
+ bluez/android/handsfree.c \
bluez/src/log.c \
bluez/src/shared/mgmt.c \
bluez/src/shared/util.c \
@@ -108,6 +109,7 @@ LOCAL_SRC_FILES := \
bluez/android/hal-pan.c \
bluez/android/hal-a2dp.c \
bluez/android/hal-avrcp.c \
+ bluez/android/hal-handsfree.c \
bluez/android/hal-utils.c \
LOCAL_C_INCLUDES += \
diff --git a/android/Makefile.am b/android/Makefile.am
index e065c0c..23e30c9 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -37,6 +37,7 @@ android_bluetoothd_SOURCES = android/main.c \
android/avrcp.h android/avrcp.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
+ android/handsfree.h android/handsfree.c \
btio/btio.h btio/btio.c \
src/sdp-client.h src/sdp-client.c \
profiles/network/bnep.h profiles/network/bnep.c
@@ -51,6 +52,7 @@ android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
android/hal-pan.c \
android/hal-a2dp.c \
android/hal-avrcp.c \
+ android/hal-handsfree.c \
android/hardware/bluetooth.h \
android/hardware/bt_av.h \
android/hardware/bt_gatt.h \
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 0dac158..67c91e4 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -765,6 +765,9 @@ static const void *get_profile_interface(const char *profile_id)
if (!strcmp(profile_id, BT_PROFILE_AV_RC_ID))
return bt_get_avrcp_interface();
+ if (!strcmp(profile_id, BT_PROFILE_HANDSFREE_ID))
+ return bt_get_handsfree_interface();
+
return NULL;
}
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
new file mode 100644
index 0000000..181e05f
--- /dev/null
+++ b/android/hal-handsfree.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 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 <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "hal-log.h"
+#include "hal.h"
+#include "hal-msg.h"
+#include "hal-ipc.h"
+
+static const bthf_callbacks_t *cbs = NULL;
+
+static bool interface_ready(void)
+{
+ return cbs != NULL;
+}
+
+/* handlers will be called from notification thread context,
+ * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
+static const struct hal_ipc_handler ev_handlers[] = {
+
+};
+
+static bt_status_t init(bthf_callbacks_t *callbacks)
+{
+ struct hal_cmd_register_module cmd;
+ int ret;
+
+ DBG("");
+
+ if (interface_ready())
+ return BT_STATUS_DONE;
+
+ cbs = callbacks;
+
+ hal_ipc_register(HAL_SERVICE_ID_HANDSFREE, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]));
+
+ cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+
+ ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ if (ret != BT_STATUS_SUCCESS) {
+ cbs = NULL;
+ hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+ }
+
+ return ret;
+}
+
+static void cleanup(void)
+{
+ struct hal_cmd_unregister_module cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return;
+
+ cbs = NULL;
+
+ cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+
+ hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+}
+
+static bthf_interface_t iface = {
+ .size = sizeof(iface),
+ .init = init,
+ .cleanup = cleanup
+};
+
+bthf_interface_t *bt_get_handsfree_interface(void)
+{
+ return &iface;
+}
diff --git a/android/hal.h b/android/hal.h
index 1ff4fbd..5005b49 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -21,12 +21,14 @@
#include <hardware/bt_pan.h>
#include <hardware/bt_av.h>
#include <hardware/bt_rc.h>
+#include <hardware/bt_hf.h>
btsock_interface_t *bt_get_sock_interface(void);
bthh_interface_t *bt_get_hidhost_interface(void);
btpan_interface_t *bt_get_pan_interface(void);
btav_interface_t *bt_get_a2dp_interface(void);
btrc_interface_t *bt_get_avrcp_interface(void);
+bthf_interface_t *bt_get_handsfree_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
diff --git a/android/handsfree.c b/android/handsfree.c
new file mode 100644
index 0000000..fb48ff1
--- /dev/null
+++ b/android/handsfree.c
@@ -0,0 +1,41 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+
+#include "lib/bluetooth.h"
+#include "handsfree.h"
+
+bool bt_handsfree_register(const bdaddr_t *addr)
+{
+ return false;
+}
+
+void bt_handsfree_unregister(void)
+{
+
+}
diff --git a/android/handsfree.h b/android/handsfree.h
new file mode 100644
index 0000000..799fcb6
--- /dev/null
+++ b/android/handsfree.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+bool bt_handsfree_register(const bdaddr_t *addr);
+void bt_handsfree_unregister(void);
diff --git a/android/main.c b/android/main.c
index 417dbc3..d9d0572 100644
--- a/android/main.c
+++ b/android/main.c
@@ -56,6 +56,7 @@
#include "a2dp.h"
#include "pan.h"
#include "avrcp.h"
+#include "handsfree.h"
#define STARTUP_GRACE_SECONDS 5
#define SHUTDOWN_GRACE_SECONDS 10
@@ -115,6 +116,13 @@ static void service_register(const void *buf, uint16_t len)
}
break;
+ case HAL_SERVICE_ID_HANDSFREE:
+ if (!bt_handsfree_register(&adapter_bdaddr)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ break;
default:
DBG("service %u not supported", m->service_id);
status = HAL_STATUS_FAILED;
@@ -160,6 +168,9 @@ static void service_unregister(const void *buf, uint16_t len)
case HAL_SERVICE_ID_AVRCP:
bt_avrcp_unregister();
break;
+ case HAL_SERVICE_ID_HANDSFREE:
+ bt_handsfree_unregister();
+ break;
default:
/* This would indicate bug in HAL, as unregister should not be
* called in init failed */
@@ -338,6 +349,9 @@ static void cleanup_services(void)
case HAL_SERVICE_ID_PAN:
bt_pan_unregister();
break;
+ case HAL_SERVICE_ID_HANDSFREE:
+ bt_handsfree_unregister();
+ break;
}
services[i] = false;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 02/13] android/handsfree: Add commands and events definition to IPC header
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
2014-02-02 21:09 ` [PATCH 01/13] android/handsfree: Add initial files Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 03/13] android/handsfree: Add stubs for commands handlers Szymon Janc
` (11 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/hal-msg.h | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 208 insertions(+)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index d46b428..56e1116 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -389,6 +389,130 @@ struct hal_cmd_pan_disconnect {
uint8_t bdaddr[6];
} __attribute__((packed));
+/* Handsfree HAL API */
+
+#define HAL_OP_HANDSFREE_CONNECT 0x01
+struct hal_cmd_handsfree_connect {
+ uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_DISCONNECT 0x02
+struct hal_cmd_handsfree_disconnect {
+ uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_CONNECT_AUDIO 0x03
+struct hal_cmd_handsfree_connect_audio {
+ uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_DISCONNECT_AUDIO 0x04
+struct hal_cmd_handsfree_disconnect_audio {
+ uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_START_VR 0x05
+
+#define HAL_OP_HANDSFREE_STOP_VR 0x06
+
+#define HAL_HANDSFREE_VOLUME_TYPE_SPEAKER 0x00
+#define HAL_HANDSFREE_VOLUME_TYPE_MIC 0x01
+
+#define HAL_OP_HANDSFREE_VOLUME_CONTROL 0x07
+struct hal_cmd_handsfree_volume_control {
+ uint8_t type;
+ uint32_t volume;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_NETWORK_STATE_NOT_AVAILABLE 0x00
+#define HAL_HANDSFREE_NETWORK_STATE_AVAILABLE 0x01
+
+#define HAL_HANDSFREE_SERVICE_TYPE_HOME 0x00
+#define HAL_HANDSFREE_SERVICE_TYPE_ROAMING 0x01
+
+#define HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF 0x08
+struct hal_cmd_handsfree_device_status_notif {
+ uint8_t state;
+ uint8_t type;
+ uint32_t signal;
+ uint32_t battery;
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_COPS_RESPONSE 0x09
+struct hal_cmd_handsfree_cops_response {
+ uint32_t len;
+ uint8_t buf[0];
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_CALL_STATE_ACTIVE 0x00
+#define HAL_HANDSFREE_CALL_STATE_HELD 0x01
+#define HAL_HANDSFREE_CALL_STATE_DIALING 0x02
+#define HAL_HANDSFREE_CALL_STATE_ALERTING 0x03
+#define HAL_HANDSFREE_CALL_STATE_INCOMING 0x04
+#define HAL_HANDSFREE_CALL_STATE_WAITING 0x05
+#define HAL_HANDSFREE_CALL_STATE_IDLE 0x06
+
+#define HAL_OP_HANDSFREE_CIND_RESPONSE 0x0A
+struct hal_cmd_handsfree_cind_response {
+ uint32_t svc;
+ uint32_t num_active;
+ uint32_t num_held;
+ uint8_t state;
+ uint32_t signal;
+ uint32_t roam;
+ uint32_t batt_chg;
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE 0x0B
+struct hal_cmd_handsfree_formatted_at_response {
+ uint32_t len;
+ uint8_t buf[0];
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_AT_RESPONSE_ERROR 0x00
+#define HAL_HANDSFREE_AT_RESPONSE_OK 0x01
+
+#define HAL_OP_HANDSFREE_AT_RESPONSE 0x0C
+struct hal_cmd_handsfree_at_response {
+ uint8_t response;
+ uint32_t error;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_CALL_DIRECTION_OUTGOING 0x00
+#define HAL_HANDSFREE_CALL_DIRECTION_INCOMING 0x01
+
+#define HAL_HANDSFREE_CALL_TYPE_VOICE 0x00
+#define HAL_HANDSFREE_CALL_TYPE_DATA 0x01
+#define HAL_HANDSFREE_CALL_TYPE_FAX 0x02
+
+#define HAL_HANDSFREE_CALL_MPTY_TYPE_SINGLE 0x00
+#define HAL_HANDSFREE_CALL_MPTY_TYPE_MULTI 0x01
+
+#define HAL_HANDSFREE_CALL_ADDRTYPE_UNKNOWN 0x81
+#define HAL_HANDSFREE_CALL_ADDRTYPE_INTERNATIONAL 0x91
+
+#define HAL_OP_HANDSFREE_CLCC_RESPONSE 0x0D
+struct hal_cmd_handsfree_clcc_response {
+ uint32_t index;
+ uint8_t dir;
+ uint8_t state;
+ uint8_t mode;
+ uint8_t mpty;
+ uint8_t type;
+ uint32_t number_len;
+ uint8_t number[0];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_PHONE_STATE_CHANGE 0x0E
+struct hal_cmd_handsfree_phone_state_change {
+ uint32_t num_active;
+ uint32_t num_held;
+ uint8_t state;
+ uint8_t type;
+ uint32_t number_len;
+ uint8_t number[0];
+} __attribute__((packed));
+
/* Notifications and confirmations */
#define HAL_POWER_OFF 0x00
@@ -572,3 +696,87 @@ struct hal_ev_a2dp_audio_state {
uint8_t state;
uint8_t bdaddr[6];
} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED 0x00
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTING 0x01
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTED 0x02
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED 0x03
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING 0x04
+
+#define HAL_EV_HANDSFREE_CONN_STATE 0x81
+struct hal_ev_handsfree_conn_state {
+ uint8_t state;
+ uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED 0x00
+#define HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTING 0x01
+#define HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED 0x02
+#define HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTING 0x03
+
+#define HAL_EV_HANDSFREE_AUDIO_STATE 0x82
+struct hal_ev_handsfree_audio_state {
+ uint8_t state;
+ uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_VR 0x83
+struct hal_ev_handsfree_vr_state {
+ uint8_t state;
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_ANSWER 0x84
+
+#define HAL_EV_HANDSFREE_HANGUP 0x85
+
+#define HAL_EV_HANDSFREE_VOLUME 0x86
+struct hal_ev_handsfree_volume {
+ uint8_t type;
+ uint32_t volume;
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_DIAL 0x87
+struct hal_ev_handsfree_dial {
+ uint32_t number_len;
+ uint8_t number[0];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_DTMF 0x88
+struct hal_ev_handsfree_dtmf {
+ uint8_t tone;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_NREC_STOP 0x00
+#define HAL_HANDSFREE_NREC_STart 0x01
+
+#define HAL_EV_HANDSFREE_NREC 0x89
+struct hal_ev_handsfree_nrec {
+ uint8_t nrec;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_CHLD_TYPE_RELEASEHELD 0x00
+#define HAL_HANDSFREE_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD 0x01
+#define HAL_HANDSFREE_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD 0x02
+#define HAL_HANDSFREE_CHLD_TYPE_ADDHELDTOCONF 0x03
+
+#define HAL_EV_HANDSFREE_CHLD 0x8A
+struct hal_ev_handsfree_chld {
+ uint8_t chld;
+} __attribute__((packed));
+
+
+#define HAL_EV_HANDSFREE_CNUM 0x8B
+
+#define HAL_EV_HANDSFREE_CIND 0x8C
+
+#define HAL_EV_HANDSFREE_COPS 0x8D
+
+#define HAL_EV_HANDSFREE_CLCC 0x8E
+
+#define HAL_EV_HANDSFREE_UNKNOWN_AT 0x8F
+struct hal_ev_handsfree_unknown_at {
+ uint32_t len;
+ uint8_t buf[0];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_HSP_KEY_PRESS 0x90
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 03/13] android/handsfree: Add stubs for commands handlers
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
2014-02-02 21:09 ` [PATCH 01/13] android/handsfree: Add initial files Szymon Janc
2014-02-02 21:09 ` [PATCH 02/13] android/handsfree: Add commands and events definition to IPC header Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 04/13] android/hal-handsfree: Implement notifications handling Szymon Janc
` (10 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Add empty handlers for all IPC commands.
---
android/handsfree.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 169 insertions(+), 1 deletion(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index fb48ff1..3c0d52b 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -26,16 +26,184 @@
#endif
#include <stdbool.h>
+#include <glib.h>
#include "lib/bluetooth.h"
#include "handsfree.h"
+#include "src/log.h"
+#include "hal-msg.h"
+#include "ipc.h"
+
+static bdaddr_t adapter_addr;
+
+static void handle_connect(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_disconnect(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_connect_audio(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT_AUDIO,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_disconnect_audio(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_DISCONNECT_AUDIO, HAL_STATUS_FAILED);
+}
+
+static void handle_start_vr(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_START_VR,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_stop_vr(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_STOP_VR,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_volume_control(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_VOLUME_CONTROL,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_device_status_notif(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_cops(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_COPS_RESPONSE,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_cind(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CIND_RESPONSE,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_formatted_at_resp(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_at_resp(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_AT_RESPONSE,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_clcc_resp(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CLCC_RESPONSE,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_phone_state_change(const void *buf, uint16_t len)
+{
+ DBG("");
+
+ ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
+ HAL_STATUS_FAILED);
+}
+
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_HANDSFREE_CONNECT */
+ { handle_connect, false, sizeof(struct hal_cmd_handsfree_connect)},
+ /* HAL_OP_HANDSFREE_DISCONNECT */
+ {handle_disconnect, false, sizeof(struct hal_cmd_handsfree_disconnect)},
+ /*HAL_OP_HANDSFREE_CONNECT_AUDIO*/
+ {handle_connect_audio, false,
+ sizeof(struct hal_cmd_handsfree_connect_audio)},
+ /*HAL_OP_HANDSFREE_DISCONNECT_AUDIO*/
+ {handle_disconnect_audio, false,
+ sizeof(struct hal_cmd_handsfree_disconnect_audio)},
+ /* define HAL_OP_HANDSFREE_START_VR */
+ {handle_start_vr, false, 0 },
+ /* define HAL_OP_HANDSFREE_STOP_VR */
+ {handle_stop_vr, false, 0 },
+ /* HAL_OP_HANDSFREE_VOLUME_CONTROL */
+ {handle_volume_control, false,
+ sizeof(struct hal_cmd_handsfree_volume_control)},
+ /* HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF */
+ {handle_device_status_notif, false,
+ sizeof(struct hal_cmd_handsfree_device_status_notif)},
+ /* HAL_OP_HANDSFREE_COPS_RESPONSE */
+ {handle_cops, true, sizeof(struct hal_cmd_handsfree_cops_response)},
+ /* HAL_OP_HANDSFREE_CIND_RESPONSE */
+ { handle_cind, false, sizeof(struct hal_cmd_handsfree_cind_response)},
+ /* HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE */
+ {handle_formatted_at_resp, true,
+ sizeof(struct hal_cmd_handsfree_formatted_at_response)},
+ /* HAL_OP_HANDSFREE_AT_RESPONSE */
+ {handle_at_resp, false, sizeof(struct hal_cmd_handsfree_at_response)},
+ /* HAL_OP_HANDSFREE_CLCC_RESPONSE */
+ {handle_clcc_resp, true,
+ sizeof(struct hal_cmd_handsfree_clcc_response)},
+ /* HAL_OP_HANDSFREE_PHONE_STATE_CHANGE */
+ {handle_phone_state_change, true,
+ sizeof(struct hal_cmd_handsfree_phone_state_change)},
+};
bool bt_handsfree_register(const bdaddr_t *addr)
{
- return false;
+ DBG("");
+
+ bacpy(&adapter_addr, addr);
+
+ ipc_register(HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
+ G_N_ELEMENTS(cmd_handlers));
+
+ return true;
}
void bt_handsfree_unregister(void)
{
+ DBG("");
+ ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 04/13] android/hal-handsfree: Implement notifications handling
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (2 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 03/13] android/handsfree: Add stubs for commands handlers Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 05/13] android/hal-handsfree: Implement sending commands Szymon Janc
` (9 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This implements all notifications handlers and call proper HAL
callbacks.
---
android/hal-handsfree.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 159 insertions(+), 1 deletion(-)
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 181e05f..6e11367 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -18,6 +18,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+#include <stdlib.h>
#include "hal-log.h"
#include "hal.h"
@@ -31,10 +32,167 @@ static bool interface_ready(void)
return cbs != NULL;
}
+static void handle_conn_state(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_conn_state *ev = buf;
+
+ if (cbs->connection_state_cb)
+ cbs->connection_state_cb(ev->state,
+ (bt_bdaddr_t *) (ev->bdaddr));
+}
+
+static void handle_audio_state(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_audio_state *ev = buf;
+
+ if (cbs->audio_state_cb)
+ cbs->audio_state_cb(ev->state, (bt_bdaddr_t *) (ev->bdaddr));
+}
+
+static void handle_vr_state(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_vr_state *ev = buf;
+
+ if (cbs->vr_cmd_cb)
+ cbs->vr_cmd_cb(ev->state);
+}
+
+static void handle_answer(void *buf, uint16_t len)
+{
+ if (cbs->answer_call_cmd_cb)
+ cbs->answer_call_cmd_cb();
+}
+
+static void handle_hangup(void *buf, uint16_t len)
+{
+ if (cbs->hangup_call_cmd_cb)
+ cbs->hangup_call_cmd_cb();
+}
+
+static void handle_volume(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_volume *ev = buf;
+
+ if (cbs->volume_cmd_cb)
+ cbs->volume_cmd_cb(ev->type, ev->volume);
+}
+
+static void handle_dial(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_dial *ev = buf;
+
+ if (len != sizeof(*ev) + ev->number_len) {
+ error("invalid dial event, aborting");
+ exit(EXIT_FAILURE);
+ }
+
+ if (cbs->dial_call_cmd_cb)
+ cbs->dial_call_cmd_cb((char *) ev->number);
+}
+
+static void handle_dtmf(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_dtmf *ev = buf;
+
+ if (cbs->dtmf_cmd_cb)
+ cbs->dtmf_cmd_cb(ev->tone);
+}
+
+static void handle_nrec(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_nrec *ev = buf;
+
+ if (cbs->nrec_cmd_cb)
+ cbs->nrec_cmd_cb(ev->nrec);
+}
+
+static void handle_chld(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_chld *ev = buf;
+
+ if (cbs->chld_cmd_cb)
+ cbs->chld_cmd_cb(ev->chld);
+}
+
+static void handle_cnum(void *buf, uint16_t len)
+{
+ if (cbs->cnum_cmd_cb)
+ cbs->cnum_cmd_cb();
+}
+
+static void handle_cind(void *buf, uint16_t len)
+{
+ if (cbs->cind_cmd_cb)
+ cbs->cind_cmd_cb();
+}
+
+static void handle_cops(void *buf, uint16_t len)
+{
+ if (cbs->cops_cmd_cb)
+ cbs->cops_cmd_cb();
+}
+
+static void handle_clcc(void *buf, uint16_t len)
+{
+ if (cbs->clcc_cmd_cb)
+ cbs->clcc_cmd_cb();
+}
+
+static void handle_unknown_at(void *buf, uint16_t len)
+{
+ struct hal_ev_handsfree_unknown_at *ev = buf;
+
+ if (len != sizeof(*ev) + ev->len) {
+ error("invalid dial event, aborting");
+ exit(EXIT_FAILURE);
+ }
+
+ if (cbs->unknown_at_cmd_cb)
+ cbs->unknown_at_cmd_cb((char *) ev->buf);
+}
+
+static void handle_hsp_key_press(void *buf, uint16_t len)
+{
+ if (cbs->key_pressed_cmd_cb)
+ cbs->key_pressed_cmd_cb();
+}
+
/* handlers will be called from notification thread context,
* index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
static const struct hal_ipc_handler ev_handlers[] = {
-
+ /* HAL_EV_HANDSFREE_CONN_STATE */
+ {handle_conn_state, false, sizeof(struct hal_ev_handsfree_conn_state)},
+ /* HAL_EV_HANDSFREE_AUDIO_STATE */
+ {handle_audio_state, false,
+ sizeof(struct hal_ev_handsfree_audio_state)},
+ /* HAL_EV_HANDSFREE_VR */
+ {handle_vr_state, false, sizeof(struct hal_ev_handsfree_vr_state)},
+ /*HAL_EV_HANDSFREE_ANSWER */
+ {handle_answer, false, 0},
+ /*HAL_EV_HANDSFREE_HANGUP */
+ {handle_hangup, false, 0},
+ /* HAL_EV_HANDSFREE_VOLUME */
+ {handle_volume, false, sizeof(struct hal_ev_handsfree_volume)},
+ /* HAL_EV_HANDSFREE_DIAL */
+ {handle_dial, true, sizeof(struct hal_ev_handsfree_dial)},
+ /* HAL_EV_HANDSFREE_DTMF */
+ {handle_dtmf, false, sizeof(struct hal_ev_handsfree_dtmf)},
+ /* HAL_EV_HANDSFREE_NREC */
+ {handle_nrec, false, sizeof(struct hal_ev_handsfree_nrec)},
+ /* HAL_EV_HANDSFREE_CHLD */
+ {handle_chld, false, sizeof(struct hal_ev_handsfree_chld)},
+ /* HAL_EV_HANDSFREE_CNUM */
+ {handle_cnum, false, 0},
+ /* HAL_EV_HANDSFREE_CIND */
+ {handle_cind, false, 0},
+ /* HAL_EV_HANDSFREE_COPS */
+ {handle_cops, false, 0},
+ /* HAL_EV_HANDSFREE_CLCC */
+ {handle_clcc, false, 0},
+ /* HAL_EV_HANDSFREE_UNKNOWN_AT */
+ {handle_unknown_at, true, sizeof(struct hal_ev_handsfree_unknown_at)},
+ /* HAL_EV_HANDSFREE_HSP_KEY_PRESS */
+ {handle_hsp_key_press, false, 0},
};
static bt_status_t init(bthf_callbacks_t *callbacks)
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 05/13] android/hal-handsfree: Implement sending commands
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (3 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 04/13] android/hal-handsfree: Implement notifications handling Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 06/13] android/handsfree: Add SDP record for AG Szymon Janc
` (8 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This implements HAL interface methods and pass commands over IPC.
---
android/hal-handsfree.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 344 insertions(+)
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
@@ -223,6 +223,336 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
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;
@@ -245,6 +575,20 @@ static void cleanup(void)
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
};
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 06/13] android/handsfree: Add SDP record for AG
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (4 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 05/13] android/hal-handsfree: Implement sending commands Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-03 7:56 ` Andrei Emeltchenko
2014-02-02 21:09 ` [PATCH 07/13] android/handsfree: Add support for RFCOMM connection handling Szymon Janc
` (7 subsequent siblings)
13 siblings, 1 reply; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Service Name: Hands-Free Audio GatewayService RecHandle: 0x10001
Service Class ID List:
"Handsfree Audio Gateway" (0x111f)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 13
Profile Descriptor List:
"Handsfree" (0x111e)
Version: 0x0106
---
android/handsfree.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/android/handsfree.c b/android/handsfree.c
index 3c0d52b..d2dc543 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -29,12 +29,19 @@
#include <glib.h>
#include "lib/bluetooth.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
#include "handsfree.h"
+#include "bluetooth.h"
#include "src/log.h"
#include "hal-msg.h"
#include "ipc.h"
+#define HFP_AG_CHANNEL 13
+#define HFP_AG_FEATURES 0
+
static bdaddr_t adapter_addr;
+static uint32_t record_id = 0;
static void handle_connect(const void *buf, uint16_t len)
{
@@ -189,12 +196,99 @@ static const struct ipc_handler cmd_handlers[] = {
sizeof(struct hal_cmd_handsfree_phone_state_change)},
};
+static sdp_record_t *handsfree_ag_record(void)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
+ uuid_t l2cap_uuid, rfcomm_uuid;
+ sdp_profile_desc_t profile;
+ sdp_list_t *aproto, *proto[2];
+ sdp_record_t *record;
+ sdp_data_t *channel, *features;
+ uint8_t netid = 0x01;
+ uint16_t sdpfeat;
+ sdp_data_t *network;
+ uint8_t ch = HFP_AG_CHANNEL;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ network = sdp_data_alloc(SDP_UINT8, &netid);
+ if (!network) {
+ sdp_record_free(record);
+ return NULL;
+ }
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(0, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
+ svclass_id = sdp_list_append(0, &svclass_uuid);
+ sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
+ svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
+ profile.version = 0x0106;
+ pfseq = sdp_list_append(0, &profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto[0] = sdp_list_append(0, &l2cap_uuid);
+ apseq = sdp_list_append(0, proto[0]);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[1] = sdp_list_append(0, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &ch);
+ proto[1] = sdp_list_append(proto[1], channel);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ sdpfeat = HFP_AG_FEATURES;
+ features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
+ sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+ aproto = sdp_list_append(0, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0);
+
+ sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], 0);
+ sdp_list_free(proto[1], 0);
+ sdp_list_free(apseq, 0);
+ sdp_list_free(pfseq, 0);
+ sdp_list_free(aproto, 0);
+ sdp_list_free(root, 0);
+ sdp_list_free(svclass_id, 0);
+
+ return record;
+}
+
bool bt_handsfree_register(const bdaddr_t *addr)
{
+ sdp_record_t *rec;
+
DBG("");
bacpy(&adapter_addr, addr);
+ rec = handsfree_ag_record();
+ if (!rec) {
+ error("Failed to allocate Handsfree record");
+ return false;
+ }
+
+ if (bt_adapter_add_record(rec, 0) < 0) {
+ error("Failed to register Handsfree record");
+ sdp_record_free(rec);
+ return false;
+ }
+ record_id = rec->handle;
+
ipc_register(HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
@@ -206,4 +300,7 @@ void bt_handsfree_unregister(void)
DBG("");
ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+
+ bt_adapter_remove_record(record_id);
+ record_id = 0;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH 06/13] android/handsfree: Add SDP record for AG
2014-02-02 21:09 ` [PATCH 06/13] android/handsfree: Add SDP record for AG Szymon Janc
@ 2014-02-03 7:56 ` Andrei Emeltchenko
2014-02-05 9:10 ` Szymon Janc
0 siblings, 1 reply; 17+ messages in thread
From: Andrei Emeltchenko @ 2014-02-03 7:56 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
Hi Szymon,
On Sun, Feb 02, 2014 at 10:09:17PM +0100, Szymon Janc wrote:
> Service Name: Hands-Free Audio GatewayService RecHandle: 0x10001
> Service Class ID List:
> "Handsfree Audio Gateway" (0x111f)
> "Generic Audio" (0x1203)
> Protocol Descriptor List:
> "L2CAP" (0x0100)
> "RFCOMM" (0x0003)
> Channel: 13
> Profile Descriptor List:
> "Handsfree" (0x111e)
> Version: 0x0106
> ---
> android/handsfree.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/android/handsfree.c b/android/handsfree.c
> index 3c0d52b..d2dc543 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -29,12 +29,19 @@
> #include <glib.h>
>
> #include "lib/bluetooth.h"
> +#include "lib/sdp.h"
> +#include "lib/sdp_lib.h"
> #include "handsfree.h"
> +#include "bluetooth.h"
> #include "src/log.h"
> #include "hal-msg.h"
> #include "ipc.h"
>
> +#define HFP_AG_CHANNEL 13
> +#define HFP_AG_FEATURES 0
> +
> static bdaddr_t adapter_addr;
> +static uint32_t record_id = 0;
>
> static void handle_connect(const void *buf, uint16_t len)
> {
> @@ -189,12 +196,99 @@ static const struct ipc_handler cmd_handlers[] = {
> sizeof(struct hal_cmd_handsfree_phone_state_change)},
> };
>
> +static sdp_record_t *handsfree_ag_record(void)
> +{
> + sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
> + uuid_t l2cap_uuid, rfcomm_uuid;
> + sdp_profile_desc_t profile;
> + sdp_list_t *aproto, *proto[2];
> + sdp_record_t *record;
> + sdp_data_t *channel, *features;
> + uint8_t netid = 0x01;
> + uint16_t sdpfeat;
> + sdp_data_t *network;
> + uint8_t ch = HFP_AG_CHANNEL;
> +
> + record = sdp_record_alloc();
> + if (!record)
> + return NULL;
> +
> + network = sdp_data_alloc(SDP_UINT8, &netid);
> + if (!network) {
> + sdp_record_free(record);
> + return NULL;
> + }
> +
> + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> + root = sdp_list_append(0, &root_uuid);
> + sdp_set_browse_groups(record, root);
> +
> + sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
> + svclass_id = sdp_list_append(0, &svclass_uuid);
> + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> + sdp_set_service_classes(record, svclass_id);
> +
> + sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
> + profile.version = 0x0106;
> + pfseq = sdp_list_append(0, &profile);
> + sdp_set_profile_descs(record, pfseq);
> +
> + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> + proto[0] = sdp_list_append(0, &l2cap_uuid);
> + apseq = sdp_list_append(0, proto[0]);
> +
> + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> + proto[1] = sdp_list_append(0, &rfcomm_uuid);
> + channel = sdp_data_alloc(SDP_UINT8, &ch);
> + proto[1] = sdp_list_append(proto[1], channel);
> + apseq = sdp_list_append(apseq, proto[1]);
> +
> + sdpfeat = HFP_AG_FEATURES;
> + features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
> + sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
> +
> + aproto = sdp_list_append(0, apseq);
> + sdp_set_access_protos(record, aproto);
> +
> + sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0);
> +
> + sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
> +
> + sdp_data_free(channel);
> + sdp_list_free(proto[0], 0);
We have agreed to use NULL for zero pointers.
Best regards
Andrei Emeltchenko
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH 06/13] android/handsfree: Add SDP record for AG
2014-02-03 7:56 ` Andrei Emeltchenko
@ 2014-02-05 9:10 ` Szymon Janc
0 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-05 9:10 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
Hi Andrei,
On Monday 03 of February 2014 09:56:18 Andrei Emeltchenko wrote:
> Hi Szymon,
>
> On Sun, Feb 02, 2014 at 10:09:17PM +0100, Szymon Janc wrote:
> > Service Name: Hands-Free Audio GatewayService RecHandle: 0x10001
> > Service Class ID List:
> > "Handsfree Audio Gateway" (0x111f)
> > "Generic Audio" (0x1203)
> > Protocol Descriptor List:
> > "L2CAP" (0x0100)
> > "RFCOMM" (0x0003)
> > Channel: 13
> > Profile Descriptor List:
> > "Handsfree" (0x111e)
> > Version: 0x0106
> > ---
> > android/handsfree.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 97 insertions(+)
> >
> > diff --git a/android/handsfree.c b/android/handsfree.c
> > index 3c0d52b..d2dc543 100644
> > --- a/android/handsfree.c
> > +++ b/android/handsfree.c
> > @@ -29,12 +29,19 @@
> > #include <glib.h>
> >
> > #include "lib/bluetooth.h"
> > +#include "lib/sdp.h"
> > +#include "lib/sdp_lib.h"
> > #include "handsfree.h"
> > +#include "bluetooth.h"
> > #include "src/log.h"
> > #include "hal-msg.h"
> > #include "ipc.h"
> >
> > +#define HFP_AG_CHANNEL 13
> > +#define HFP_AG_FEATURES 0
> > +
> > static bdaddr_t adapter_addr;
> > +static uint32_t record_id = 0;
> >
> > static void handle_connect(const void *buf, uint16_t len)
> > {
> > @@ -189,12 +196,99 @@ static const struct ipc_handler cmd_handlers[] = {
> > sizeof(struct hal_cmd_handsfree_phone_state_change)},
> > };
> >
> > +static sdp_record_t *handsfree_ag_record(void)
> > +{
> > + sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> > + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
> > + uuid_t l2cap_uuid, rfcomm_uuid;
> > + sdp_profile_desc_t profile;
> > + sdp_list_t *aproto, *proto[2];
> > + sdp_record_t *record;
> > + sdp_data_t *channel, *features;
> > + uint8_t netid = 0x01;
> > + uint16_t sdpfeat;
> > + sdp_data_t *network;
> > + uint8_t ch = HFP_AG_CHANNEL;
> > +
> > + record = sdp_record_alloc();
> > + if (!record)
> > + return NULL;
> > +
> > + network = sdp_data_alloc(SDP_UINT8, &netid);
> > + if (!network) {
> > + sdp_record_free(record);
> > + return NULL;
> > + }
> > +
> > + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> > + root = sdp_list_append(0, &root_uuid);
> > + sdp_set_browse_groups(record, root);
> > +
> > + sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
> > + svclass_id = sdp_list_append(0, &svclass_uuid);
> > + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> > + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> > + sdp_set_service_classes(record, svclass_id);
> > +
> > + sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
> > + profile.version = 0x0106;
> > + pfseq = sdp_list_append(0, &profile);
> > + sdp_set_profile_descs(record, pfseq);
> > +
> > + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> > + proto[0] = sdp_list_append(0, &l2cap_uuid);
> > + apseq = sdp_list_append(0, proto[0]);
> > +
> > + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> > + proto[1] = sdp_list_append(0, &rfcomm_uuid);
> > + channel = sdp_data_alloc(SDP_UINT8, &ch);
> > + proto[1] = sdp_list_append(proto[1], channel);
> > + apseq = sdp_list_append(apseq, proto[1]);
> > +
> > + sdpfeat = HFP_AG_FEATURES;
> > + features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
> > + sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
> > +
> > + aproto = sdp_list_append(0, apseq);
> > + sdp_set_access_protos(record, aproto);
> > +
> > + sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0);
> > +
> > + sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
> > +
> > + sdp_data_free(channel);
> > + sdp_list_free(proto[0], 0);
>
> We have agreed to use NULL for zero pointers.
I've miss that comment, but this is now fixed by follow-up patch.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 07/13] android/handsfree: Add support for RFCOMM connection handling
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (5 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 06/13] android/handsfree: Add SDP record for AG Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 08/13] android/handsfree: Add initial code for AT commands processing Szymon Janc
` (6 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This adds incoming connection handling and initial connection state
tracking. Only one device is allowed to be connected at the same time.
---
android/handsfree.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 165 insertions(+), 2 deletions(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index d2dc543..ad4c0ff 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -25,24 +25,162 @@
#include <config.h>
#endif
+#include <stdlib.h>
#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
#include <glib.h>
#include "lib/bluetooth.h"
#include "lib/sdp.h"
#include "lib/sdp_lib.h"
+#include "lib/uuid.h"
+#include "src/sdp-client.h"
+#include "src/uuid-helper.h"
+#include "btio/btio.h"
#include "handsfree.h"
#include "bluetooth.h"
#include "src/log.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "utils.h"
#define HFP_AG_CHANNEL 13
#define HFP_AG_FEATURES 0
+static struct {
+ bdaddr_t bdaddr;
+ uint8_t state;
+ GIOChannel *io;
+ guint watch;
+} device;
+
static bdaddr_t adapter_addr;
static uint32_t record_id = 0;
+static GIOChannel *server = NULL;
+
+static void device_set_state(uint8_t state)
+{
+ struct hal_ev_handsfree_conn_state ev;
+ char address[18];
+
+ if (device.state == state)
+ return;
+
+ device.state = state;
+
+ ba2str(&device.bdaddr, address);
+ DBG("device %s state %u", address, state);
+
+ bdaddr2android(&device.bdaddr, ev.bdaddr);
+ ev.state = state;
+
+ ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CONN_STATE,
+ sizeof(ev), &ev);
+}
+
+static void device_init(const bdaddr_t *bdaddr)
+{
+ bacpy(&device.bdaddr, bdaddr);
+
+ device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTING);
+}
+
+static void device_cleanup(void)
+{
+ if (device.watch) {
+ g_source_remove(device.watch);
+ device.watch = 0;
+ }
+
+ if (device.io) {
+ g_io_channel_unref(device.io);
+ device.io = NULL;
+ }
+
+ device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED);
+
+ memset(&device, 0, sizeof(device));
+}
+
+static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ DBG("");
+
+ device.watch = 0;
+
+ device_cleanup();
+
+ return FALSE;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ DBG("");
+
+ if (err) {
+ error("handsfree: connect failed (%s)", err->message);
+ goto failed;
+ }
+
+ g_io_channel_set_close_on_unref(chan, TRUE);
+
+ device.watch = g_io_add_watch(chan,
+ G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ watch_cb, NULL);
+ if (device.watch == 0)
+ goto failed;
+
+ device.io = g_io_channel_ref(chan);
+
+ device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTED);
+
+ return;
+
+failed:
+ g_io_channel_shutdown(chan, TRUE, NULL);
+ device_cleanup();
+}
+
+static void confirm_cb(GIOChannel *chan, gpointer data)
+{
+ char address[18];
+ bdaddr_t bdaddr;
+ GError *err = NULL;
+
+ bt_io_get(chan, &err,
+ BT_IO_OPT_DEST, address,
+ BT_IO_OPT_DEST_BDADDR, &bdaddr,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("handsfree: confirm failed (%s)", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ DBG("incoming connect from %s", address);
+
+ if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED) {
+ info("handsfree: refusing connection from %s", address);
+ goto drop;
+ }
+
+ device_init(&bdaddr);
+
+ if (!bt_io_accept(chan, connect_cb, NULL, NULL, NULL)) {
+ error("handsfree: failed to accept connection");
+ device_cleanup();
+ goto drop;
+ }
+
+ return;
+
+drop:
+ g_io_channel_shutdown(chan, TRUE, NULL);
+}
+
static void handle_connect(const void *buf, uint16_t len)
{
DBG("");
@@ -271,21 +409,33 @@ static sdp_record_t *handsfree_ag_record(void)
bool bt_handsfree_register(const bdaddr_t *addr)
{
sdp_record_t *rec;
+ GError *err = NULL;
DBG("");
bacpy(&adapter_addr, addr);
+ server = bt_io_listen( NULL, confirm_cb, NULL, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_CHANNEL, HFP_AG_CHANNEL,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_INVALID);
+ if (!server) {
+ error("Failed to listen on Handsfree rfcomm: %s", err->message);
+ g_error_free(err);
+ return false;
+ }
+
rec = handsfree_ag_record();
if (!rec) {
error("Failed to allocate Handsfree record");
- return false;
+ goto failed;
}
if (bt_adapter_add_record(rec, 0) < 0) {
error("Failed to register Handsfree record");
sdp_record_free(rec);
- return false;
+ goto failed;
}
record_id = rec->handle;
@@ -293,6 +443,13 @@ bool bt_handsfree_register(const bdaddr_t *addr)
G_N_ELEMENTS(cmd_handlers));
return true;
+
+failed:
+ g_io_channel_shutdown(server, TRUE, NULL);
+ g_io_channel_unref(server);
+ server = NULL;
+
+ return false;
}
void bt_handsfree_unregister(void)
@@ -301,6 +458,12 @@ void bt_handsfree_unregister(void)
ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+ if (server) {
+ g_io_channel_shutdown(server, TRUE, NULL);
+ g_io_channel_unref(server);
+ server = NULL;
+ }
+
bt_adapter_remove_record(record_id);
record_id = 0;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 08/13] android/handsfree: Add initial code for AT commands processing
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (6 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 07/13] android/handsfree: Add support for RFCOMM connection handling Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 09/13] android/handsfree: Add connect command handling Szymon Janc
` (5 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Currently always reply with error and disconnect connection.
---
android/Makefile.am | 2 ++
android/handsfree.c | 21 +++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/android/Makefile.am b/android/Makefile.am
index 23e30c9..41bbbcb 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -27,6 +27,8 @@ android_bluetoothd_SOURCES = android/main.c \
src/shared/queue.h src/shared/queue.c \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
+ src/shared/ringbuf.h src/shared/ringbuf.c \
+ src/shared/hfp.h src/shared/hfp.c \
android/bluetooth.h android/bluetooth.c \
android/hidhost.h android/hidhost.c \
android/ipc.h android/ipc.c \
diff --git a/android/handsfree.c b/android/handsfree.c
index ad4c0ff..a4ce398 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -37,6 +37,7 @@
#include "lib/uuid.h"
#include "src/sdp-client.h"
#include "src/uuid-helper.h"
+#include "src/shared/hfp.h"
#include "btio/btio.h"
#include "handsfree.h"
#include "bluetooth.h"
@@ -53,6 +54,7 @@ static struct {
uint8_t state;
GIOChannel *io;
guint watch;
+ struct hfp_gw *gw;
} device;
static bdaddr_t adapter_addr;
@@ -89,6 +91,11 @@ static void device_init(const bdaddr_t *bdaddr)
static void device_cleanup(void)
{
+ if (device.gw) {
+ hfp_gw_unref(device.gw);
+ device.gw = NULL;
+ }
+
if (device.watch) {
g_source_remove(device.watch);
device.watch = 0;
@@ -116,6 +123,13 @@ static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
}
+static void at_command_handler(const char *command, void *user_data)
+{
+ hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+ g_io_channel_shutdown(device.io, TRUE, NULL);
+}
+
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
DBG("");
@@ -127,6 +141,13 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
g_io_channel_set_close_on_unref(chan, TRUE);
+ device.gw = hfp_gw_new(g_io_channel_unix_get_fd(chan));
+ if (!device.gw)
+ goto failed;
+
+ hfp_gw_set_close_on_unref(device.gw, true);
+ hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
+
device.watch = g_io_add_watch(chan,
G_IO_HUP | G_IO_ERR | G_IO_NVAL,
watch_cb, NULL);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 09/13] android/handsfree: Add connect command handling
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (7 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 08/13] android/handsfree: Add initial code for AT commands processing Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 10/13] android/handsfree: Add disconnect " Szymon Janc
` (4 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This allows to query SDP for RFCOMM channel and connect.
---
android/handsfree.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 100 insertions(+), 1 deletion(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index a4ce398..79e61b4 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -202,12 +202,111 @@ drop:
g_io_channel_shutdown(chan, TRUE, NULL);
}
+static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+{
+ sdp_list_t *protos, *classes;
+ GError *gerr = NULL;
+ GIOChannel *io;
+ uuid_t uuid;
+ int channel;
+
+ DBG("");
+
+ if (err < 0) {
+ error("handsfree: unable to get SDP record: %s", strerror(-err));
+ goto fail;
+ }
+
+ if (!recs || !recs->data) {
+ error("handsfree: no SDP records found");
+ goto fail;
+ }
+
+ if (sdp_get_service_classes(recs->data, &classes) < 0) {
+ error("handsfree: unable to get service classes from record");
+ goto fail;
+ }
+
+ if (sdp_get_access_protos(recs->data, &protos) < 0) {
+ error("handsfree: unable to get access protocols from record");
+ goto fail;
+ }
+
+ /* TODO read remote version? */
+
+ memcpy(&uuid, classes->data, sizeof(uuid));
+ sdp_list_free(classes, free);
+
+ if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
+ uuid.value.uuid16 != HANDSFREE_SVCLASS_ID) {
+ sdp_list_free(protos, NULL);
+ error("handsfree: invalid service record or not HFP");
+ goto fail;
+ }
+
+ channel = sdp_get_proto_port(protos, RFCOMM_UUID);
+ sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(protos, NULL);
+ if (channel <= 0) {
+ error("handsfree: unable to get RFCOMM channel from record");
+ goto fail;
+ }
+
+ io = bt_io_connect(connect_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &device.bdaddr,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_CHANNEL, channel,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("handsfree: unable to connect: %s", gerr->message);
+ g_error_free(gerr);
+ goto fail;
+ }
+
+ g_io_channel_unref(io);
+ return;
+
+fail:
+ device_cleanup();
+}
+
static void handle_connect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_handsfree_connect *cmd = buf;
+ char addr[18];
+ uint8_t status;
+ uuid_t uuid;
+ bdaddr_t bdaddr;
+
DBG("");
+ if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ android2bdaddr(&cmd->bdaddr, &bdaddr);
+
+ ba2str(&device.bdaddr, addr);
+ DBG("connecting to %s", addr);
+
+ device_init(&bdaddr);
+
+ bt_string2uuid(&uuid, HFP_HS_UUID);
+ if (bt_search_service(&adapter_addr, &device.bdaddr, &uuid,
+ sdp_search_cb, NULL, NULL, 0) < 0) {
+ error("handsfree: SDP search failed");
+ device_cleanup();
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
- HAL_STATUS_FAILED);
+ status);
}
static void handle_disconnect(const void *buf, uint16_t len)
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 10/13] android/handsfree: Add disconnect command handling
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (8 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 09/13] android/handsfree: Add connect command handling Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 11/13] android/handsfree: Add AT+BRSF command support Szymon Janc
` (3 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/handsfree.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 79e61b4..5fe7638 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -311,10 +311,38 @@ failed:
static void handle_disconnect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_handsfree_disconnect *cmd = buf;
+ bdaddr_t bdaddr;
+ uint8_t status;
+
DBG("");
+ android2bdaddr(cmd->bdaddr, &bdaddr);
+
+ if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED ||
+ bacmp(&device.bdaddr, &bdaddr)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+
+ }
+
+ if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING) {
+ status = HAL_STATUS_SUCCESS;
+ goto failed;
+ }
+
+ if (device.io) {
+ device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING);
+ g_io_channel_shutdown(device.io, TRUE, NULL);
+ } else {
+ device_cleanup();
+ }
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
- HAL_STATUS_FAILED);
+ status);
}
static void handle_connect_audio(const void *buf, uint16_t len)
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 11/13] android/handsfree: Add AT+BRSF command support
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (9 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 10/13] android/handsfree: Add disconnect " Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 12/13] android/handsfree: Add support for AT+CIND command Szymon Janc
` (2 subsequent siblings)
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/handsfree.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 5fe7638..990ba2f 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -49,12 +49,16 @@
#define HFP_AG_CHANNEL 13
#define HFP_AG_FEATURES 0
+#define AG_FEATURES 0
+
static struct {
bdaddr_t bdaddr;
uint8_t state;
GIOChannel *io;
guint watch;
struct hfp_gw *gw;
+
+ uint32_t features;
} device;
static bdaddr_t adapter_addr;
@@ -123,11 +127,69 @@ static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
}
+static bool at_brsf(const char *at)
+{
+ uint32_t feat;
+
+ if (sscanf(at, " = %u", &feat) != 1) {
+ hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+ return false;
+ }
+
+ /* TODO verify features */
+ device.features = feat;
+
+ hfp_gw_send_info(device.gw, "+BRSF=%u", AG_FEATURES);
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+ return true;
+}
+
+static const struct {
+ const char *prefix;
+ int prefix_len;
+ bool (*func)(const char *at_cmds);
+} at_cmds[] = {
+ { "+BRSF", sizeof("+BRSF") - 1, at_brsf },
+};
+
static void at_command_handler(const char *command, void *user_data)
{
+ unsigned int i;
+
+ if (strlen(command) < 3)
+ goto error;
+
+ if (strncmp(command, "AT", sizeof("AT") - 1))
+ goto error;
+
+ command += sizeof("AT") - 1;
+
+ for (i = 0; i < G_N_ELEMENTS(at_cmds); i++) {
+ if (strncmp(command, at_cmds[i].prefix, at_cmds[i].prefix_len))
+ continue;
+
+ command += at_cmds[i].prefix_len;
+
+ if (at_cmds[i].func(command))
+ return;
+
+ goto check_slc;
+ }
+
+error:
hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
- g_io_channel_shutdown(device.io, TRUE, NULL);
+check_slc:
+ /* Error while establishing SLC */
+ if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED)
+ g_io_channel_shutdown(device.io, TRUE, NULL);
+}
+
+static void hfp_gw_debug(const char *str, void *user_data)
+{
+ DBG("%s", str);
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -148,6 +210,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
hfp_gw_set_close_on_unref(device.gw, true);
hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
+ hfp_gw_set_debug(device.gw, hfp_gw_debug, NULL, NULL);
+
device.watch = g_io_add_watch(chan,
G_IO_HUP | G_IO_ERR | G_IO_NVAL,
watch_cb, NULL);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 12/13] android/handsfree: Add support for AT+CIND command
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (10 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 11/13] android/handsfree: Add AT+BRSF command support Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-02 21:09 ` [PATCH 13/13] android/handsfree: Add support for AT+CMER command Szymon Janc
2014-02-05 9:10 ` [PATCH 00/13] Initial code for handsfree support Szymon Janc
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Android supports only fixed number of indicators so this is all static
for now.
---
android/handsfree.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 990ba2f..02135cb 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -51,6 +51,10 @@
#define AG_FEATURES 0
+#define CIND_SUPPORT_STR "+CIND: (\"service\",(0,1)),(\"call\",(0,1)),\
+ (\"callsetup\",(0-3)),(\"callheld\",(0-2)),\
+ (\"signal\",(0-5)),(\"roam\",(0,1)),(\"battchg\",(0,1))"
+
static struct {
bdaddr_t bdaddr;
uint8_t state;
@@ -146,12 +150,35 @@ static bool at_brsf(const char *at)
return true;
}
+static bool at_cind(const char *at)
+{
+ if (strcmp(at, "?")) {
+ ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CIND,
+ 0, NULL);
+
+ return true;
+ }
+
+ if (strcmp(at, "=?")) {
+ hfp_gw_send_info(device.gw, "%s", CIND_SUPPORT_STR);
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+ return true;
+ }
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+ return false;
+}
+
static const struct {
const char *prefix;
int prefix_len;
bool (*func)(const char *at_cmds);
} at_cmds[] = {
{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
+ { "+CIND", sizeof("+CIND") - 1, at_cind },
};
static void at_command_handler(const char *command, void *user_data)
@@ -466,12 +493,41 @@ static void handle_cops(const void *buf, uint16_t len)
HAL_STATUS_FAILED);
}
+static unsigned int get_callsetup(uint8_t state)
+{
+ switch (state) {
+ case HAL_HANDSFREE_CALL_STATE_INCOMING:
+ return 1;
+ case HAL_HANDSFREE_CALL_STATE_DIALING:
+ return 2;
+ case HAL_HANDSFREE_CALL_STATE_ALERTING:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
static void handle_cind(const void *buf, uint16_t len)
{
+ const struct hal_cmd_handsfree_cind_response *cmd = buf;
+
DBG("");
+ /* HAL doesn't provide CIND values directly so need to convert here */
+
+ hfp_gw_send_info(device.gw, "+CIND: %u,%u,%u,%u,%u,%u,%u",
+ cmd->svc,
+ !!(cmd->num_active + cmd->num_held),
+ get_callsetup(cmd->state),
+ cmd->num_held ? (cmd->num_active ? 1 : 2) : 0,
+ cmd->signal,
+ cmd->roam,
+ cmd->batt_chg);
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CIND_RESPONSE,
- HAL_STATUS_FAILED);
+ HAL_STATUS_SUCCESS);
}
static void handle_formatted_at_resp(const void *buf, uint16_t len)
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 13/13] android/handsfree: Add support for AT+CMER command
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (11 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 12/13] android/handsfree: Add support for AT+CIND command Szymon Janc
@ 2014-02-02 21:09 ` Szymon Janc
2014-02-05 9:10 ` [PATCH 00/13] Initial code for handsfree support Szymon Janc
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/handsfree.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/android/handsfree.c b/android/handsfree.c
index 02135cb..bf6a575 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -63,6 +63,7 @@ static struct {
struct hfp_gw *gw;
uint32_t features;
+ bool ind_notif_active;
} device;
static bdaddr_t adapter_addr;
@@ -172,6 +173,30 @@ static bool at_cind(const char *at)
return false;
}
+static bool at_cmer(const char *at)
+{
+ unsigned int mode, ind;
+ int ret;
+
+ DBG("");
+
+ ret = sscanf(at, " = %u, %*u, %*u, %u", &mode, &ind);
+ if (ret != 2 || mode != 3 || ind > 1) {
+ hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+ return false;
+ }
+
+ device.ind_notif_active = ind;
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+ /* TODO Check for 3-way calling support */
+ device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED);
+
+ return true;
+}
+
static const struct {
const char *prefix;
int prefix_len;
@@ -179,6 +204,7 @@ static const struct {
} at_cmds[] = {
{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
{ "+CIND", sizeof("+CIND") - 1, at_cind },
+ { "+CMER", sizeof("+CMER") - 1, at_cmer },
};
static void at_command_handler(const char *command, void *user_data)
--
1.8.5.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH 00/13] Initial code for handsfree support
2014-02-02 21:09 [PATCH 00/13] Initial code for handsfree support Szymon Janc
` (12 preceding siblings ...)
2014-02-02 21:09 ` [PATCH 13/13] android/handsfree: Add support for AT+CMER command Szymon Janc
@ 2014-02-05 9:10 ` Szymon Janc
13 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-02-05 9:10 UTC (permalink / raw)
To: linux-bluetooth
On Sunday 02 of February 2014 22:09:11 Szymon Janc wrote:
> Hi,
>
> This adds initial support for HFP. HAL library is complete, for daemon
> only support for RFCOMM connection handling.
>
> There is also minimal set of AT handling needed for SLC establishment
> (proper AT parsing code is still missing).
>
> Comments are welcome.
>
> BR
> Szymon Janc
>
> Szymon Janc (13):
> android/handsfree: Add initial files
> android/handsfree: Add commands and events definition to IPC header
> android/handsfree: Add stubs for commands handlers
> android/hal-handsfree: Implement notifications handling
> android/hal-handsfree: Implement sending commands
> android/handsfree: Add SDP record for AG
> android/handsfree: Add support for RFCOMM connection handling
> android/handsfree: Add initial code for AT commands processing
> android/handsfree: Add connect command handling
> android/handsfree: Add disconnect command handling
> android/handsfree: Add AT+BRSF command support
> android/handsfree: Add support for AT+CIND command
> android/handsfree: Add support for AT+CMER command
>
> android/Android.mk | 2 +
> android/Makefile.am | 4 +
> android/hal-bluetooth.c | 3 +
> android/hal-handsfree.c | 598 +++++++++++++++++++++++++++++++++++++
> android/hal-msg.h | 208 +++++++++++++
> android/hal.h | 2 +
> android/handsfree.c | 763 ++++++++++++++++++++++++++++++++++++++++++++++++
> android/handsfree.h | 25 ++
> android/main.c | 14 +
> 9 files changed, 1619 insertions(+)
> create mode 100644 android/hal-handsfree.c
> create mode 100644 android/handsfree.c
> create mode 100644 android/handsfree.h
>
>
Patches 1-10 are now pushed.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 17+ messages in thread