* [PATCH 01/13] android/handsfree: Add initial files
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 02/13] android/handsfree: Add commands and events definition to IPC header
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
---
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
* [PATCH 03/13] android/handsfree: Add stubs for commands handlers
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 04/13] android/hal-handsfree: Implement notifications handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 05/13] android/hal-handsfree: Implement sending commands
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 06/13] android/handsfree: Add SDP record for AG
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 07/13] android/handsfree: Add support for RFCOMM connection handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 08/13] android/handsfree: Add initial code for AT commands processing
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 09/13] android/handsfree: Add connect command handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 10/13] android/handsfree: Add disconnect command handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
---
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
* [PATCH 11/13] android/handsfree: Add AT+BRSF command support
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
---
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
* [PATCH 12/13] android/handsfree: Add support for AT+CIND command
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 13/13] android/handsfree: Add support for AT+CMER command
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>
---
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
* AVRCP profile/plugin in bluez 5
From: Serkan Kaba @ 2014-02-03 6:52 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
Hi,
I was trying to get my GTK-N1BT hi-fi system. It was constantly bailing "UUIDs has unsupported type" errors and disconnecting after the pairing. All the online examples were referring to bluez 4 config (audio.conf) which even in 4 it was hard to get it working. I added the following in "General" section of audio.conf
<code>
Enable=Media,Sink,Source
</code>
and got it working
I couldn't figure out enabling avrcp profile with bluez 5. Please help
^ permalink raw reply
* [PATCH] pbap: Fix PhonebookSize endianness
From: Hannu Mallat @ 2014-02-03 7:47 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Hannu Mallat
As g_obex_apparam_set_uint16() converts data to big-endian format
internally, do not call htons() prior to it.
---
obexd/plugins/pbap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c
index 4740188..acac3aa 100644
--- a/obexd/plugins/pbap.c
+++ b/obexd/plugins/pbap.c
@@ -188,7 +188,7 @@ static void phonebook_size_result(const char *buffer, size_t bufsize,
DBG("vcards %d", vcards);
- phonebooksize = htons(vcards);
+ phonebooksize = vcards;
pbap->obj->apparam = g_obex_apparam_set_uint16(NULL, PHONEBOOKSIZE_TAG,
phonebooksize);
@@ -365,7 +365,7 @@ static int generate_response(void *user_data)
if (max == 0) {
/* Ignore all other parameter and return PhoneBookSize */
- uint16_t size = htons(g_slist_length(pbap->cache.entries));
+ uint16_t size = g_slist_length(pbap->cache.entries);
pbap->obj->apparam = g_obex_apparam_set_uint16(
pbap->obj->apparam,
--
1.8.5.3
^ permalink raw reply related
* Re: [PATCH] avrcp: Fix wrong pointer check
From: Andrei Emeltchenko @ 2014-02-03 7:51 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZ+-mc_u+ihj_FB5e89TNmBgZvyWxW4vwMCuFDh1_TjCJg@mail.gmail.com>
Hi Luiz,
On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
> Hi Andrei,
>
> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >
> > There is wrong assumption that handler might be NULL while it is a
> > pointer to a struct table so check instead for struct members. This
> > fixes accessing wrong memory.
> > ---
> > profiles/audio/avrcp.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> > index df88138..5030ce1 100644
> > --- a/profiles/audio/avrcp.c
> > +++ b/profiles/audio/avrcp.c
> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
> > break;
> > }
> >
> > - if (!handler || handler->code != *code) {
> > + if (!handler->code || handler->code != *code) {
>
> The code checks if session->control_handlers is initialized and Im
> not sure what is the invalid memory access you are talking about since
> handle->code is no a pointer, I do agree that we should probably drop
> the second check for the handler in the lines bellow.
handler is a pointer, and it points to
static const struct control_pdu_handler control_handlers[]
table with the last element:
...
{ },
};
...
So checking for !handler is pointless.
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH 06/13] android/handsfree: Add SDP record for AG
From: Andrei Emeltchenko @ 2014-02-03 7:56 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1391375364-27106-7-git-send-email-szymon.janc@tieto.com>
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
* Re: [PATCH] android/avrcp: Decouple AVRCP logic from btio
From: Andrei Emeltchenko @ 2014-02-03 9:01 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391092704-24806-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
On Thu, Jan 30, 2014 at 04:38:24PM +0200, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> The patch makes AVRCP to be channel-agnostic so that it might be used in
> unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
> channel stuff got to avrcp.
> ---
> android/Android.mk | 1 +
> android/Makefile.am | 1 +
> android/avrcp-lib.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> android/avrcp-lib.h | 32 ++++++++++++++++++++
> android/avrcp.c | 46 ++--------------------------
> 5 files changed, 124 insertions(+), 43 deletions(-)
> create mode 100644 android/avrcp-lib.c
> create mode 100644 android/avrcp-lib.h
>
> diff --git a/android/Android.mk b/android/Android.mk
> index 1d12da5..09b54d6 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
> bluez/android/avdtp.c \
> bluez/android/a2dp.c \
> bluez/android/avctp.c \
> + bluez/android/avrcp-lib.c \
> bluez/android/avrcp.c \
> bluez/android/pan.c \
> bluez/src/log.c \
> diff --git a/android/Makefile.am b/android/Makefile.am
> index e065c0c..29cbf79 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -34,6 +34,7 @@ android_bluetoothd_SOURCES = android/main.c \
> android/avdtp.h android/avdtp.c \
> android/a2dp.h android/a2dp.c \
> android/avctp.h android/avctp.c \
> + android/avrcp-lib.h android/avrcp-lib.c \
> android/avrcp.h android/avrcp.c \
> android/socket.h android/socket.c \
> android/pan.h android/pan.c \
> diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
> new file mode 100644
> index 0000000..33d03d9
> --- /dev/null
> +++ b/android/avrcp-lib.c
> @@ -0,0 +1,87 @@
> +/*
> + *
> + * 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 <glib.h>
> +
> +#include "lib/bluetooth.h"
> +
> +#include "src/log.h"
> +
> +#include "avctp.h"
> +#include "avrcp-lib.h"
> +
> +static GSList *devices = NULL;
> +
> +void avrcp_device_free(void *data)
> +{
> + struct avrcp_device *dev = data;
> +
> + if (dev->session)
> + avctp_shutdown(dev->session);
> +
> + devices = g_slist_remove(devices, dev);
> + g_free(dev);
> +}
> +
> +void avrcp_free_all(void)
> +{
> + g_slist_free_full(devices, avrcp_device_free);
> + devices = NULL;
> +}
> +
> +struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
> +{
> + struct avrcp_device *dev;
> +
> + dev = g_new0(struct avrcp_device, 1);
> + bacpy(&dev->dst, dst);
> + devices = g_slist_prepend(devices, dev);
> +
> + return dev;
> +}
> +
> +static int device_cmp(gconstpointer s, gconstpointer user_data)
> +{
> + const struct avrcp_device *dev = s;
> + const bdaddr_t *dst = user_data;
> +
> + return bacmp(&dev->dst, dst);
> +}
> +
> +struct avrcp_device *avrcp_find(bdaddr_t *dst)
> +{
> + GSList *l;
> +
> + l = g_slist_find_custom(devices, dst, device_cmp);
> + if (l) {
will fix this to !l
Best regards
Andrei Emeltchenko
^ permalink raw reply
* [PATCHv2] android/avrcp: Decouple AVRCP logic from btio
From: Andrei Emeltchenko @ 2014-02-03 9:16 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391092704-24806-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
The patch makes AVRCP to be channel-agnostic so that it might be used in
unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
channel stuff got to avrcp.
---
android/Android.mk | 1 +
android/Makefile.am | 1 +
android/avrcp-lib.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++
android/avrcp-lib.h | 32 ++++++++++++++++++++
android/avrcp.c | 44 ++-------------------------
5 files changed, 122 insertions(+), 41 deletions(-)
create mode 100644 android/avrcp-lib.c
create mode 100644 android/avrcp-lib.h
diff --git a/android/Android.mk b/android/Android.mk
index 09ed32d..2772b58 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
bluez/android/avdtp.c \
bluez/android/a2dp.c \
bluez/android/avctp.c \
+ bluez/android/avrcp-lib.c \
bluez/android/avrcp.c \
bluez/android/pan.c \
bluez/src/log.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index e065c0c..29cbf79 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -34,6 +34,7 @@ android_bluetoothd_SOURCES = android/main.c \
android/avdtp.h android/avdtp.c \
android/a2dp.h android/a2dp.c \
android/avctp.h android/avctp.c \
+ android/avrcp-lib.h android/avrcp-lib.c \
android/avrcp.h android/avrcp.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
new file mode 100644
index 0000000..a4bfe6d
--- /dev/null
+++ b/android/avrcp-lib.c
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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 <glib.h>
+
+#include "lib/bluetooth.h"
+
+#include "src/log.h"
+
+#include "avctp.h"
+#include "avrcp-lib.h"
+
+static GSList *devices = NULL;
+
+void avrcp_device_free(void *data)
+{
+ struct avrcp_device *dev = data;
+
+ if (dev->session)
+ avctp_shutdown(dev->session);
+
+ devices = g_slist_remove(devices, dev);
+ g_free(dev);
+}
+
+void avrcp_free_all(void)
+{
+ g_slist_free_full(devices, avrcp_device_free);
+ devices = NULL;
+}
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
+{
+ struct avrcp_device *dev;
+
+ dev = g_new0(struct avrcp_device, 1);
+ bacpy(&dev->dst, dst);
+ devices = g_slist_prepend(devices, dev);
+
+ return dev;
+}
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+ const struct avrcp_device *dev = s;
+ const bdaddr_t *dst = user_data;
+
+ return bacmp(&dev->dst, dst);
+}
+
+struct avrcp_device *avrcp_find(bdaddr_t *dst)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(devices, dst, device_cmp);
+ if (!l)
+ return NULL;
+
+ return l->data;
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
new file mode 100644
index 0000000..a7213fb
--- /dev/null
+++ b/android/avrcp-lib.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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
+ *
+ */
+
+struct avrcp_device {
+ bdaddr_t dst;
+ struct avctp *session;
+};
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst);
+void avrcp_device_free(void *data);
+void avrcp_free_all(void);
+struct avrcp_device *avrcp_find(bdaddr_t *dst);
diff --git a/android/avrcp.c b/android/avrcp.c
index ef833df..ff923cb 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -38,6 +38,7 @@
#include "hal-msg.h"
#include "ipc.h"
#include "avctp.h"
+#include "avrcp-lib.h"
#define L2CAP_PSM_AVCTP 0x17
@@ -48,14 +49,8 @@
static bdaddr_t adapter_addr;
static uint32_t record_id = 0;
-static GSList *devices = NULL;
static GIOChannel *server = NULL;
-struct avrcp_device {
- bdaddr_t dst;
- struct avctp *session;
-};
-
static const struct ipc_handler cmd_handlers[] = {
};
@@ -127,36 +122,6 @@ static sdp_record_t *avrcp_record(void)
return record;
}
-static void avrcp_device_free(void *data)
-{
- struct avrcp_device *dev = data;
-
- if (dev->session)
- avctp_shutdown(dev->session);
-
- devices = g_slist_remove(devices, dev);
- g_free(dev);
-}
-
-static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
-{
- struct avrcp_device *dev;
-
- dev = g_new0(struct avrcp_device, 1);
- bacpy(&dev->dst, dst);
- devices = g_slist_prepend(devices, dev);
-
- return dev;
-}
-
-static int device_cmp(gconstpointer s, gconstpointer user_data)
-{
- const struct avrcp_device *dev = s;
- const bdaddr_t *dst = user_data;
-
- return bacmp(&dev->dst, dst);
-}
-
static void disconnect_cb(void *data)
{
struct avrcp_device *dev = data;
@@ -175,7 +140,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
char address[18];
uint16_t imtu, omtu;
GError *gerr = NULL;
- GSList *l;
int fd;
if (err) {
@@ -199,8 +163,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
ba2str(&dst, address);
DBG("Incoming connection from %s", address);
- l = g_slist_find_custom(devices, &dst, device_cmp);
- if (l) {
+ if (avrcp_find(&dst)) {
error("Unexpected connection");
return;
}
@@ -274,8 +237,7 @@ void bt_avrcp_unregister(void)
{
DBG("");
- g_slist_free_full(devices, avrcp_device_free);
- devices = NULL;
+ avrcp_free_all();
ipc_unregister(HAL_SERVICE_ID_AVRCP);
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH] avrcp: Fix wrong pointer check
From: Luiz Augusto von Dentz @ 2014-02-03 9:20 UTC (permalink / raw)
To: Andrei Emeltchenko, Luiz Augusto von Dentz,
linux-bluetooth@vger.kernel.org
In-Reply-To: <20140203074920.GA2930@aemeltch-MOBL1>
Hi Andrei,
On Sun, Feb 2, 2014 at 11:51 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> Hi Luiz,
>
> On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
>> Hi Andrei,
>>
>> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
>> <Andrei.Emeltchenko.news@gmail.com> wrote:
>> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>> >
>> > There is wrong assumption that handler might be NULL while it is a
>> > pointer to a struct table so check instead for struct members. This
>> > fixes accessing wrong memory.
>> > ---
>> > profiles/audio/avrcp.c | 4 ++--
>> > 1 file changed, 2 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
>> > index df88138..5030ce1 100644
>> > --- a/profiles/audio/avrcp.c
>> > +++ b/profiles/audio/avrcp.c
>> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
>> > break;
>> > }
>> >
>> > - if (!handler || handler->code != *code) {
>> > + if (!handler->code || handler->code != *code) {
>>
>> The code checks if session->control_handlers is initialized and Im
>> not sure what is the invalid memory access you are talking about since
>> handle->code is no a pointer, I do agree that we should probably drop
>> the second check for the handler in the lines bellow.
>
> handler is a pointer, and it points to
>
> static const struct control_pdu_handler control_handlers[]
> table with the last element:
>
> ...
> { },
> };
> ...
>
> So checking for !handler is pointless.
Right, because checking for pointer is pointless, yes Im being
sarcastic here... Now lets be clear, you are changing a check of a
pointer to a value and claiming it fixes invalid accesses which does
not make any sense, what could make sense is to check if
handler->pdu_id == pdu->pdu_id since that what we check when we lookup
for a handle.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH] avrcp: Fix wrong pointer check
From: Andrei Emeltchenko @ 2014-02-03 9:36 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZ+VPAkfgUNRu6GC9DhkP=KXpTzBC03OVW8nNC_55uaMfg@mail.gmail.com>
On Mon, Feb 03, 2014 at 01:20:11AM -0800, Luiz Augusto von Dentz wrote:
> Hi Andrei,
>
> On Sun, Feb 2, 2014 at 11:51 PM, Andrei Emeltchenko
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > Hi Luiz,
> >
> > On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
> >> Hi Andrei,
> >>
> >> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
> >> <Andrei.Emeltchenko.news@gmail.com> wrote:
> >> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >> >
> >> > There is wrong assumption that handler might be NULL while it is a
> >> > pointer to a struct table so check instead for struct members. This
> >> > fixes accessing wrong memory.
> >> > ---
> >> > profiles/audio/avrcp.c | 4 ++--
> >> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >> >
> >> > diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> >> > index df88138..5030ce1 100644
> >> > --- a/profiles/audio/avrcp.c
> >> > +++ b/profiles/audio/avrcp.c
> >> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
> >> > break;
> >> > }
> >> >
> >> > - if (!handler || handler->code != *code) {
> >> > + if (!handler->code || handler->code != *code) {
> >>
> >> The code checks if session->control_handlers is initialized and Im
> >> not sure what is the invalid memory access you are talking about since
> >> handle->code is no a pointer, I do agree that we should probably drop
> >> the second check for the handler in the lines bellow.
> >
> > handler is a pointer, and it points to
> >
> > static const struct control_pdu_handler control_handlers[]
> > table with the last element:
> >
> > ...
> > { },
> > };
> > ...
> >
> > So checking for !handler is pointless.
>
> Right, because checking for pointer is pointless, yes Im being
> sarcastic here... Now lets be clear, you are changing a check of a
> pointer to a value and claiming it fixes invalid accesses which does
> not make any sense, what could make sense is to check if
> handler->pdu_id == pdu->pdu_id since that what we check when we lookup
> for a handle.
No, we break if handler->pdu_id == pdu->pdu_id one line above ;)
Best regards
Andrei Emeltchenko
>
>
>
> --
> Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH BlueZ] audio/AVRCP: Fix checking for handler pointer instead of pdu_id
From: Luiz Augusto von Dentz @ 2014-02-03 9:40 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
The code may not find a valid handler for the pdu_id, in that case the
handler would not be NULL because the handlers table is not NULL
terminated, instead the code should check if pdu_id really matches.
---
profiles/audio/avrcp.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 12f7faa..4532d85 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
break;
}
- if (!handler || handler->code != *code) {
+ if (handler->pdu_id != pdu->pdu_id || handler->code != *code) {
pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
goto err_metadata;
}
@@ -1734,12 +1734,12 @@ static size_t handle_browsing_pdu(struct avctp *conn,
for (handler = browsing_handlers; handler->pdu_id; handler++) {
if (handler->pdu_id == pdu->pdu_id)
- break;
+ goto done;
}
- if (handler == NULL || handler->func == NULL)
- return avrcp_browsing_general_reject(operands);
+ return avrcp_browsing_general_reject(operands);
+done:
session->transaction = transaction;
handler->func(session, pdu, transaction);
return AVRCP_BROWSING_HEADER_LENGTH + ntohs(pdu->param_len);
--
1.8.4.2
^ permalink raw reply related
* Re: [PATCH] avrcp: Fix wrong pointer check
From: Andrei Emeltchenko @ 2014-02-03 9:42 UTC (permalink / raw)
To: Luiz Augusto von Dentz, linux-bluetooth@vger.kernel.org
In-Reply-To: <20140203093651.GE2930@aemeltch-MOBL1>
On Mon, Feb 03, 2014 at 11:36:52AM +0200, Andrei Emeltchenko wrote:
> On Mon, Feb 03, 2014 at 01:20:11AM -0800, Luiz Augusto von Dentz wrote:
> > Hi Andrei,
> >
> > On Sun, Feb 2, 2014 at 11:51 PM, Andrei Emeltchenko
> > <Andrei.Emeltchenko.news@gmail.com> wrote:
> > > Hi Luiz,
> > >
> > > On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
> > >> Hi Andrei,
> > >>
> > >> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
> > >> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > >> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > >> >
> > >> > There is wrong assumption that handler might be NULL while it is a
> > >> > pointer to a struct table so check instead for struct members. This
> > >> > fixes accessing wrong memory.
> > >> > ---
> > >> > profiles/audio/avrcp.c | 4 ++--
> > >> > 1 file changed, 2 insertions(+), 2 deletions(-)
> > >> >
> > >> > diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> > >> > index df88138..5030ce1 100644
> > >> > --- a/profiles/audio/avrcp.c
> > >> > +++ b/profiles/audio/avrcp.c
> > >> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
> > >> > break;
> > >> > }
> > >> >
> > >> > - if (!handler || handler->code != *code) {
> > >> > + if (!handler->code || handler->code != *code) {
> > >>
> > >> The code checks if session->control_handlers is initialized and Im
> > >> not sure what is the invalid memory access you are talking about since
> > >> handle->code is no a pointer, I do agree that we should probably drop
> > >> the second check for the handler in the lines bellow.
> > >
> > > handler is a pointer, and it points to
> > >
> > > static const struct control_pdu_handler control_handlers[]
> > > table with the last element:
> > >
> > > ...
> > > { },
> > > };
> > > ...
> > >
> > > So checking for !handler is pointless.
> >
> > Right, because checking for pointer is pointless, yes Im being
> > sarcastic here... Now lets be clear, you are changing a check of a
> > pointer to a value and claiming it fixes invalid accesses which does
> > not make any sense, what could make sense is to check if
> > handler->pdu_id == pdu->pdu_id since that what we check when we lookup
> > for a handle.
>
> No, we break if handler->pdu_id == pdu->pdu_id one line above ;)
Sorry this was wrong. So my idea is to check that we are not at the end of
the table. In this case every element of a struct is zero, so it does not
matter which one to check.
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH] Bluetooth: hidp: make sure input buffers are big enough
From: Jiri Kosina @ 2014-02-03 10:08 UTC (permalink / raw)
To: David Herrmann
Cc: Marcel Holtmann, open list:HID CORE LAYER,
linux-bluetooth@vger.kernel.org development, Gustavo F. Padovan
In-Reply-To: <CANq1E4TW+GU=oaW0tXb=Tun9HMtr26u-PC3H6BsLot560ANgog@mail.gmail.com>
On Wed, 29 Jan 2014, David Herrmann wrote:
> >> Due to various reasons I will not have access to any testing HW for the
> >> upcoming 2-3 days, so if you can cook something up in that timeframe, it'd
> >> be appreciated.
> >>
> >> Otherwise I'll be working on it by the end of this week.
> >
> > David,
> >
> > just got back to this, finally ... did you have time to work on this at
> > all, or should I just start from scratch?
>
> Sorry, no. Fosdem is this weekend and I needed to get my code ready
> for that. But I'll finally have time again next week.
Okay, thanks. I then guess we should proceed with this bandaid (double
allocation) for 3.14
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH] Bluetooth: hidp: make sure input buffers are big enough
From: David Herrmann @ 2014-02-03 11:27 UTC (permalink / raw)
To: Jiri Kosina
Cc: Marcel Holtmann, open list:HID CORE LAYER,
linux-bluetooth@vger.kernel.org development, Gustavo F. Padovan
In-Reply-To: <alpine.LNX.2.00.1402031107310.14066@pobox.suse.cz>
Hi Jiri
On Mon, Feb 3, 2014 at 11:08 AM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Wed, 29 Jan 2014, David Herrmann wrote:
>
>> >> Due to various reasons I will not have access to any testing HW for the
>> >> upcoming 2-3 days, so if you can cook something up in that timeframe, it'd
>> >> be appreciated.
>> >>
>> >> Otherwise I'll be working on it by the end of this week.
>> >
>> > David,
>> >
>> > just got back to this, finally ... did you have time to work on this at
>> > all, or should I just start from scratch?
>>
>> Sorry, no. Fosdem is this weekend and I needed to get my code ready
>> for that. But I'll finally have time again next week.
>
> Okay, thanks. I then guess we should proceed with this bandaid (double
> allocation) for 3.14
It would be really nice if we could get the HIDP patch into 3.14-rc2
and backported to stable. There have been quite a bunch of reports now
and I dislike adding a GFP_ATOMIC allocation in HID core. I am back
home now and will try to make HID core honor the length, but that's
quite invasive and shouldn't be used for stable.
Sorry for the delay,
David
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox