* [RFC 3/7] android/unit: Update test-ipc with failure handler support
From: Szymon Janc @ 2014-02-25 10:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393325419-16544-1-git-send-email-szymon.janc@tieto.com>
---
android/test-ipc.c | 117 +++++++++++++++++------------------------------------
1 file changed, 37 insertions(+), 80 deletions(-)
diff --git a/android/test-ipc.c b/android/test-ipc.c
index 054af84..84cb764 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -35,7 +35,6 @@
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/signalfd.h>
#include <glib.h>
#include "src/shared/util.h"
@@ -43,10 +42,8 @@
#include "android/hal-msg.h"
#include "android/ipc.h"
-static struct ipc *ipc = NULL;
-
struct test_data {
- uint32_t expected_signal;
+ bool disconnect;
const void *cmd;
uint16_t cmd_size;
uint8_t service;
@@ -65,13 +62,13 @@ struct context {
GIOChannel *cmd_io;
GIOChannel *notif_io;
- GIOChannel *signal_io;
-
- guint signal_source;
const struct test_data *data;
};
+
+static struct ipc *ipc = NULL;
+
static void context_quit(struct context *context)
{
g_main_loop_quit(context->main_loop);
@@ -92,13 +89,13 @@ static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
.len = 0,
};
- g_assert(test_data->expected_signal == 0);
-
if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
- g_assert(FALSE);
+ g_assert(test_data->disconnect);
return FALSE;
}
+ g_assert(!test_data->disconnect);
+
sk = g_io_channel_unix_get_fd(io);
g_assert(read(sk, buf, sizeof(buf)) == sizeof(struct hal_hdr));
@@ -112,11 +109,16 @@ static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
+ struct context *context = user_data;
+ const struct test_data *test_data = context->data;
+
if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
- g_assert(FALSE);
+ g_assert(test_data->disconnect);
return FALSE;
}
+ g_assert(!test_data->disconnect);
+
return TRUE;
}
@@ -162,62 +164,6 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
return TRUE;
}
-static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
- gpointer user_data)
-{
- struct context *context = user_data;
- const struct test_data *test_data = context->data;
- struct signalfd_siginfo si;
- ssize_t result;
- int fd;
-
- if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
- return FALSE;
-
- fd = g_io_channel_unix_get_fd(channel);
-
- result = read(fd, &si, sizeof(si));
- if (result != sizeof(si))
- return FALSE;
-
- g_assert(test_data->expected_signal == si.ssi_signo);
- context_quit(context);
- return TRUE;
-}
-
-static guint setup_signalfd(gpointer user_data)
-{
- GIOChannel *channel;
- guint source;
- sigset_t mask;
- int ret;
- int fd;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGTERM);
-
- ret = sigprocmask(SIG_BLOCK, &mask, NULL);
- g_assert(ret == 0);
-
- fd = signalfd(-1, &mask, 0);
- g_assert(fd >= 0);
-
- channel = g_io_channel_unix_new(fd);
-
- g_io_channel_set_close_on_unref(channel, TRUE);
- g_io_channel_set_encoding(channel, NULL, NULL);
- g_io_channel_set_buffered(channel, FALSE);
-
- source = g_io_add_watch(channel,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- signal_handler, user_data);
-
- g_io_channel_unref(channel);
-
- return source;
-}
-
static struct context *create_context(gconstpointer data)
{
struct context *context = g_new0(struct context, 1);
@@ -228,9 +174,6 @@ static struct context *create_context(gconstpointer data)
context->main_loop = g_main_loop_new(NULL, FALSE);
g_assert(context->main_loop);
- context->signal_source = setup_signalfd(context);
- g_assert(context->signal_source);
-
sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
g_assert(sk >= 0);
@@ -272,7 +215,6 @@ static void execute_context(struct context *context)
g_io_channel_unref(context->notif_io);
g_source_remove(context->notif_source);
- g_source_remove(context->signal_source);
g_source_remove(context->cmd_source);
g_source_remove(context->source);
@@ -281,6 +223,15 @@ static void execute_context(struct context *context)
g_free(context);
}
+static void disconnected(void *data)
+{
+ struct context *context = data;
+
+ g_assert(context->data->disconnect);
+
+ context_quit(context);
+}
+
static void test_init(gconstpointer data)
{
struct context *context = create_context(data);
@@ -341,6 +292,8 @@ static void test_cmd(gconstpointer data)
g_assert(ipc);
+ ipc_set_fail_handler(ipc, disconnected, context);
+
g_idle_add(send_cmd, context);
execute_context(context);
@@ -359,6 +312,8 @@ static void test_cmd_reg(gconstpointer data)
g_assert(ipc);
+ ipc_set_fail_handler(ipc, disconnected, context);
+
g_idle_add(register_service, context);
g_idle_add(send_cmd, context);
@@ -379,6 +334,8 @@ static void test_cmd_reg_1(gconstpointer data)
g_assert(ipc);
+ ipc_set_fail_handler(ipc, disconnected, context);
+
g_idle_add(register_service, context);
g_idle_add(unregister_service, context);
g_idle_add(send_cmd, context);
@@ -401,7 +358,7 @@ static void test_cmd_handler_2(const void *buf, uint16_t len)
static void test_cmd_handler_invalid(const void *buf, uint16_t len)
{
- raise(SIGTERM);
+ g_assert(false);
}
static const struct test_data test_init_1 = {};
@@ -421,7 +378,7 @@ static const struct hal_hdr test_cmd_2_hdr = {
static const struct test_data test_cmd_service_invalid_1 = {
.cmd = &test_cmd_1_hdr,
.cmd_size = sizeof(test_cmd_1_hdr),
- .expected_signal = SIGTERM
+ .disconnect = true,
};
static const struct ipc_handler cmd_handlers[] = {
@@ -442,7 +399,7 @@ static const struct test_data test_cmd_service_invalid_2 = {
.service = 0,
.handlers = cmd_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
static const struct ipc_handler cmd_handlers_invalid_2[] = {
@@ -477,7 +434,7 @@ static const struct test_data test_cmd_opcode_invalid_1 = {
.service = 0,
.handlers = cmd_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
static const struct test_data test_cmd_hdr_invalid = {
@@ -486,7 +443,7 @@ static const struct test_data test_cmd_hdr_invalid = {
.service = 0,
.handlers = cmd_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
#define VARDATA_EX1 "some data example"
@@ -533,7 +490,7 @@ static const struct test_data test_cmd_vardata_invalid_1 = {
.service = 0,
.handlers = cmd_vardata_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
static const struct hal_hdr test_cmd_service_offrange_hdr = {
@@ -548,7 +505,7 @@ static const struct test_data test_cmd_service_offrange = {
.service = 0,
.handlers = cmd_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
static const struct vardata test_cmd_invalid_data_1 = {
@@ -564,7 +521,7 @@ static const struct test_data test_cmd_msg_invalid_1 = {
.service = 0,
.handlers = cmd_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
static const struct vardata test_cmd_invalid_data_2 = {
@@ -580,7 +537,7 @@ static const struct test_data test_cmd_msg_invalid_2 = {
.service = 0,
.handlers = cmd_handlers,
.handlers_size = 1,
- .expected_signal = SIGTERM
+ .disconnect = true,
};
int main(int argc, char *argv[])
--
1.8.3.2
^ permalink raw reply related
* [RFC 2/7] android: Add support for registering failure callback in IPC
From: Szymon Janc @ 2014-02-25 10:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393325419-16544-1-git-send-email-szymon.janc@tieto.com>
Allow to register callback which is called in case of IPC failure
(eg malformed message) or disconnection. This makes caller responsible
for performing expected action in such case.
---
android/ipc.c | 103 +++++++++++++++++++++++++++++++++++++--------------------
android/ipc.h | 3 ++
android/main.c | 7 ++++
3 files changed, 77 insertions(+), 36 deletions(-)
diff --git a/android/ipc.c b/android/ipc.c
index 3d6e2a3..4bddb58 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -52,8 +52,39 @@ struct ipc {
GIOChannel *notif_io;
guint notif_watch;
+
+ ipc_failed_cb failed_cb;
+ void *failed_cb_data;
};
+static void ipc_disconnect(struct ipc *ipc, bool failed)
+{
+ if (ipc->cmd_watch) {
+ g_source_remove(ipc->cmd_watch);
+ ipc->cmd_watch = 0;
+ }
+
+ if (ipc->cmd_io) {
+ g_io_channel_shutdown(ipc->cmd_io, TRUE, NULL);
+ g_io_channel_unref(ipc->cmd_io);
+ ipc->cmd_io = NULL;
+ }
+
+ if (ipc->notif_watch) {
+ g_source_remove(ipc->notif_watch);
+ ipc->notif_watch = 0;
+ }
+
+ if (ipc->notif_io) {
+ g_io_channel_shutdown(ipc->notif_io, TRUE, NULL);
+ g_io_channel_unref(ipc->notif_io);
+ ipc->notif_io = NULL;
+ }
+
+ if (ipc->failed_cb && failed)
+ ipc->failed_cb(ipc->failed_cb_data);
+}
+
int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
const void *buf, ssize_t len)
{
@@ -116,7 +147,9 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
int fd, err;
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
- info("IPC: command socket closed, terminating");
+ info("IPC: command socket closed");
+
+ ipc->cmd_watch = 0;
goto fail;
}
@@ -124,30 +157,34 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
- error("IPC: command read failed, terminating (%s)",
- strerror(errno));
+ error("IPC: command read failed (%s)", strerror(errno));
goto fail;
}
err = ipc_handle_msg(ipc->services, ipc->service_max, buf, ret);
if (err < 0) {
- error("IPC: failed to handle message, terminating (%s)",
- strerror(-err));
+ error("IPC: failed to handle message (%s)", strerror(-err));
goto fail;
}
return TRUE;
fail:
- raise(SIGTERM);
+ ipc_disconnect(ipc, true);
+
return FALSE;
}
static gboolean notif_watch_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
- info("IPC: notification socket closed, terminating");
- raise(SIGTERM);
+ struct ipc *ipc = user_data;
+
+ info("IPC: notification socket closed");
+
+ ipc->notif_watch = 0;
+
+ ipc_disconnect(ipc, true);
return FALSE;
}
@@ -194,8 +231,10 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
DBG("");
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
- error("IPC: notification socket connect failed, terminating");
- raise(SIGTERM);
+ error("IPC: notification socket connect failed");
+
+ ipc_disconnect(ipc, true);
+
return FALSE;
}
@@ -220,15 +259,19 @@ static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
DBG("");
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
- error("IPC: command socket connect failed, terminating");
- raise(SIGTERM);
- return FALSE;
+ error("IPC: command socket connect failed");
+ goto failed;
}
ipc->notif_io = ipc_connect(ipc->path, ipc->size, notif_connect_cb,
ipc);
if (!ipc->notif_io)
- raise(SIGTERM);
+ goto failed;
+
+ return FALSE;
+
+failed:
+ ipc_disconnect(ipc, true);
return FALSE;
}
@@ -257,32 +300,18 @@ struct ipc *ipc_init(const char *path, size_t size, int max_service_id)
void ipc_cleanup(struct ipc *ipc)
{
- if (ipc->cmd_watch) {
- g_source_remove(ipc->cmd_watch);
- ipc->cmd_watch = 0;
- }
-
- if (ipc->cmd_io) {
- g_io_channel_shutdown(ipc->cmd_io, TRUE, NULL);
- g_io_channel_unref(ipc->cmd_io);
- ipc->cmd_io = NULL;
- }
-
- if (ipc->notif_watch) {
- g_source_remove(ipc->notif_watch);
- ipc->notif_watch = 0;
- }
-
- if (ipc->notif_io) {
- g_io_channel_shutdown(ipc->notif_io, TRUE, NULL);
- g_io_channel_unref(ipc->notif_io);
- ipc->notif_io = NULL;
- }
+ ipc_disconnect(ipc, false);
g_free(ipc->services);
g_free(ipc);
}
+void ipc_set_fail_handler(struct ipc *ipc, ipc_failed_cb cb, void *data)
+{
+ ipc->failed_cb = cb;
+ ipc->failed_cb_data = data;
+}
+
void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
void *param, int fd)
{
@@ -323,7 +352,9 @@ void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
}
if (sendmsg(sk, &msg, 0) < 0) {
- error("IPC send failed, terminating :%s", strerror(errno));
+ error("IPC send failed :%s", strerror(errno));
+
+ /* TODO disconnect IPC here when this function becomes static */
raise(SIGTERM);
}
}
diff --git a/android/ipc.h b/android/ipc.h
index 601301c..3a6adc8 100644
--- a/android/ipc.h
+++ b/android/ipc.h
@@ -37,6 +37,9 @@ struct ipc;
struct ipc *ipc_init(const char *path, size_t size, int max_service_id);
void ipc_cleanup(struct ipc *ipc);
+typedef void (*ipc_failed_cb) (void *data);
+void ipc_set_fail_handler(struct ipc *ipc, ipc_failed_cb cb, void *data);
+
GIOChannel *ipc_connect(const char *path, size_t size, GIOFunc connect_cb,
void *user_data);
int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
diff --git a/android/main.c b/android/main.c
index 9f22486..a821dfa 100644
--- a/android/main.c
+++ b/android/main.c
@@ -228,6 +228,11 @@ static void stop_bluetooth(void)
g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS, quit_eventloop, NULL);
}
+static void ipc_disconnected(void *data)
+{
+ stop_bluetooth();
+}
+
static void adapter_ready(int err, const bdaddr_t *addr)
{
if (err < 0) {
@@ -251,6 +256,8 @@ static void adapter_ready(int err, const bdaddr_t *addr)
exit(EXIT_FAILURE);
}
+ ipc_set_fail_handler(hal_ipc, ipc_disconnected, NULL);
+
ipc_register(hal_ipc, HAL_SERVICE_ID_CORE, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
}
--
1.8.3.2
^ permalink raw reply related
* [RFC 1/7] android: Refactor IPC init
From: Szymon Janc @ 2014-02-25 10:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This allows to pass socket path and max service ID while initializaing
IPC. This is first step to allow use it both for BT and Audio HALs.
---
android/a2dp.c | 27 +++++++----
android/a2dp.h | 2 +-
android/avrcp.c | 52 +++++++++++----------
android/avrcp.h | 2 +-
android/bluetooth.c | 113 +++++++++++++++++++++++++-------------------
android/bluetooth.h | 2 +-
android/handsfree.c | 65 ++++++++++++++------------
android/handsfree.h | 2 +-
android/hidhost.c | 61 +++++++++++++-----------
android/hidhost.h | 2 +-
android/ipc.c | 132 +++++++++++++++++++++++++++++++++-------------------
android/ipc.h | 24 ++++++----
android/main.c | 41 +++++++++-------
android/pan.c | 32 +++++++------
android/pan.h | 2 +-
android/socket.c | 26 +++++++----
android/socket.h | 2 +-
android/test-ipc.c | 44 ++++++++++++------
18 files changed, 374 insertions(+), 257 deletions(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index 5d7dc78..b05d4bd 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -39,9 +39,9 @@
#include "lib/sdp_lib.h"
#include "profiles/audio/a2dp-codecs.h"
#include "src/log.h"
-#include "a2dp.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "a2dp.h"
#include "utils.h"
#include "bluetooth.h"
#include "avdtp.h"
@@ -63,6 +63,8 @@ static uint32_t record_id = 0;
static guint audio_retry_id = 0;
static bool audio_retrying = false;
+static struct ipc *hal_ipc = NULL;
+
struct a2dp_preset {
void *data;
int8_t len;
@@ -226,8 +228,8 @@ static void bt_a2dp_notify_state(struct a2dp_device *dev, uint8_t state)
bdaddr2android(&dev->dst, ev.bdaddr);
ev.state = state;
- ipc_send_notif(HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_CONN_STATE, sizeof(ev),
- &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_CONN_STATE,
+ sizeof(ev), &ev);
if (state != HAL_A2DP_STATE_DISCONNECTED)
return;
@@ -253,8 +255,8 @@ static void bt_audio_notify_state(struct a2dp_setup *setup, uint8_t state)
bdaddr2android(&setup->dev->dst, ev.bdaddr);
ev.state = state;
- ipc_send_notif(HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_AUDIO_STATE, sizeof(ev),
- &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_AUDIO_STATE,
+ sizeof(ev), &ev);
}
static void disconnect_cb(void *user_data)
@@ -597,7 +599,7 @@ static void bt_a2dp_connect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_CONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_CONNECT, status);
}
static void bt_a2dp_disconnect(const void *buf, uint16_t len)
@@ -631,7 +633,8 @@ static void bt_a2dp_disconnect(const void *buf, uint16_t len)
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTING);
failed:
- ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_DISCONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_DISCONNECT,
+ status);
}
static const struct ipc_handler cmd_handlers[] = {
@@ -1540,7 +1543,7 @@ retry:
audio_disconnected);
}
-bool bt_a2dp_register(const bdaddr_t *addr)
+bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr)
{
GError *err = NULL;
sdp_record_t *rec;
@@ -1573,7 +1576,9 @@ bool bt_a2dp_register(const bdaddr_t *addr)
}
record_id = rec->handle;
- ipc_register(HAL_SERVICE_ID_A2DP, cmd_handlers,
+ hal_ipc = ipc;
+
+ ipc_register(hal_ipc, HAL_SERVICE_ID_A2DP, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
bt_audio_register(audio_disconnected);
@@ -1600,7 +1605,9 @@ void bt_a2dp_unregister(void)
g_slist_free_full(devices, a2dp_device_free);
devices = NULL;
- ipc_unregister(HAL_SERVICE_ID_A2DP);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_A2DP);
+ hal_ipc = NULL;
+
audio_ipc_unregister();
bt_adapter_remove_record(record_id);
diff --git a/android/a2dp.h b/android/a2dp.h
index e626e41..b41a178 100644
--- a/android/a2dp.h
+++ b/android/a2dp.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_a2dp_register(const bdaddr_t *addr);
+bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr);
void bt_a2dp_unregister(void);
diff --git a/android/avrcp.c b/android/avrcp.c
index acffd56..6caa7d2 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -33,11 +33,11 @@
#include "lib/sdp.h"
#include "lib/sdp_lib.h"
#include "src/log.h"
-#include "bluetooth.h"
-#include "avrcp.h"
#include "avrcp-lib.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "bluetooth.h"
+#include "avrcp.h"
#define L2CAP_PSM_AVCTP 0x17
@@ -50,6 +50,7 @@ static bdaddr_t adapter_addr;
static uint32_t record_id = 0;
static GSList *devices = NULL;
static GIOChannel *server = NULL;
+static struct ipc *hal_ipc = NULL;
struct avrcp_device {
bdaddr_t dst;
@@ -61,79 +62,79 @@ static void handle_get_play_status(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAY_STATUS,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_GET_PLAY_STATUS, HAL_STATUS_FAILED);
}
static void handle_list_player_attrs(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_LIST_PLAYER_ATTRS,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_LIST_PLAYER_ATTRS, HAL_STATUS_FAILED);
}
static void handle_list_player_values(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_LIST_PLAYER_VALUES,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_LIST_PLAYER_VALUES, HAL_STATUS_FAILED);
}
static void handle_get_player_attrs(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAYER_ATTRS,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_GET_PLAYER_ATTRS, HAL_STATUS_FAILED);
}
static void handle_get_player_attrs_text(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT, HAL_STATUS_FAILED);
}
static void handle_get_player_values_text(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT, HAL_STATUS_FAILED);
}
static void handle_get_element_attrs_text(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, HAL_STATUS_FAILED);
}
static void handle_set_player_attrs_value(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE, HAL_STATUS_FAILED);
}
static void handle_register_notification(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_REGISTER_NOTIFICATION,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
+ HAL_OP_AVRCP_REGISTER_NOTIFICATION, HAL_STATUS_FAILED);
}
static void handle_set_volume(const void *buf, uint16_t len)
{
DBG("");
- ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
HAL_STATUS_FAILED);
}
@@ -362,7 +363,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
DBG("%s connected", address);
}
-bool bt_avrcp_register(const bdaddr_t *addr)
+bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr)
{
GError *err = NULL;
sdp_record_t *rec;
@@ -395,7 +396,9 @@ bool bt_avrcp_register(const bdaddr_t *addr)
}
record_id = rec->handle;
- ipc_register(HAL_SERVICE_ID_AVRCP, cmd_handlers,
+ hal_ipc = ipc;
+
+ ipc_register(hal_ipc, HAL_SERVICE_ID_AVRCP, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
return true;
@@ -414,7 +417,8 @@ void bt_avrcp_unregister(void)
g_slist_free_full(devices, avrcp_device_free);
devices = NULL;
- ipc_unregister(HAL_SERVICE_ID_AVRCP);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_AVRCP);
+ hal_ipc = NULL;
bt_adapter_remove_record(record_id);
record_id = 0;
diff --git a/android/avrcp.h b/android/avrcp.h
index 1fcd953..3dcffeb 100644
--- a/android/avrcp.h
+++ b/android/avrcp.h
@@ -21,7 +21,7 @@
*
*/
-bool bt_avrcp_register(const bdaddr_t *addr);
+bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr);
void bt_avrcp_unregister(void);
void bt_avrcp_connect(const bdaddr_t *dst);
diff --git a/android/bluetooth.c b/android/bluetooth.c
index ac4c213..26493f7 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -145,6 +145,8 @@ static GSList *cached_devices = NULL;
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
+static struct ipc *hal_ipc = NULL;
+
static void store_adapter_config(void)
{
GKeyFile *key_file;
@@ -390,8 +392,8 @@ static void send_adapter_property(uint8_t type, uint16_t len, const void *val)
ev->props[0].len = len;
memcpy(ev->props[0].val, val, len);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), buf);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), buf);
}
static void adapter_name_changed(const uint8_t *name)
@@ -440,8 +442,8 @@ static void powered_changed(void)
DBG("%u", ev.state);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_STATE_CHANGED,
- sizeof(ev), &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_ADAPTER_STATE_CHANGED, sizeof(ev), &ev);
}
static uint8_t settings2scan_mode(void)
@@ -594,8 +596,8 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
ev.state = state;
bdaddr2android(addr, ev.bdaddr);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_BOND_STATE_CHANGED,
- sizeof(ev), &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_BOND_STATE_CHANGED, sizeof(ev), &ev);
}
static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
@@ -647,8 +649,8 @@ static void send_device_property(const bdaddr_t *bdaddr, uint8_t type,
ev->props[0].len = len;
memcpy(ev->props[0].val, val, len);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_REMOTE_DEVICE_PROPS,
- sizeof(buf), buf);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_REMOTE_DEVICE_PROPS, sizeof(buf), buf);
}
static void send_device_uuids_notif(struct device *dev)
@@ -883,7 +885,7 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
hal_ev.class_of_dev = dev->class;
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_PIN_REQUEST,
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_EV_PIN_REQUEST,
sizeof(hal_ev), &hal_ev);
}
@@ -901,7 +903,7 @@ static void send_ssp_request(const bdaddr_t *addr, uint8_t variant,
ev.pairing_variant = variant;
ev.passkey = passkey;
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_SSP_REQUEST,
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_EV_SSP_REQUEST,
sizeof(ev), &ev);
}
@@ -1010,7 +1012,7 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
cp.state = HAL_DISCOVERY_STATE_STOPPED;
}
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH,
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_DISCOVERY_STATE_CHANGED, sizeof(cp), &cp);
}
@@ -1106,8 +1108,8 @@ static void update_new_device(struct device *dev, int8_t rssi,
ev->num_props++;
}
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_DEVICE_FOUND, size,
- buf);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_EV_DEVICE_FOUND,
+ size, buf);
}
static void update_device(struct device *dev, int8_t rssi,
@@ -1147,7 +1149,7 @@ static void update_device(struct device *dev, int8_t rssi,
}
if (ev->num_props)
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH,
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_REMOTE_DEVICE_PROPS, size, buf);
}
@@ -1259,8 +1261,8 @@ static void mgmt_device_connected_event(uint16_t index, uint16_t length,
hal_ev.state = HAL_ACL_STATE_CONNECTED;
bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ACL_STATE_CHANGED,
- sizeof(hal_ev), &hal_ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_ACL_STATE_CHANGED, sizeof(hal_ev), &hal_ev);
}
static void mgmt_device_disconnected_event(uint16_t index, uint16_t length,
@@ -1279,8 +1281,8 @@ static void mgmt_device_disconnected_event(uint16_t index, uint16_t length,
hal_ev.state = HAL_ACL_STATE_DISCONNECTED;
bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ACL_STATE_CHANGED,
- sizeof(hal_ev), &hal_ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_ACL_STATE_CHANGED, sizeof(hal_ev), &hal_ev);
}
static uint8_t status_mgmt2hal(uint8_t mgmt)
@@ -1502,8 +1504,8 @@ static uint8_t get_adapter_uuids(void)
p += sizeof(uint128_t);
}
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), ev);
return HAL_STATUS_SUCCESS;
}
@@ -2387,7 +2389,8 @@ static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
error("Failed to get adapter property (type %u status %u)",
cmd->type, status);
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP,
+ status);
}
static void get_adapter_properties(void)
@@ -2538,7 +2541,8 @@ static void handle_set_adapter_prop_cmd(const void *buf, uint16_t len)
error("Failed to set adapter property (type %u status %u)",
cmd->type, status);
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_ADAPTER_PROP, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_ADAPTER_PROP,
+ status);
}
static void pair_device_complete(uint8_t status, uint16_t length,
@@ -2579,7 +2583,8 @@ static void handle_create_bond_cmd(const void *buf, uint16_t len)
HAL_BOND_STATE_BONDING);
fail:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CREATE_BOND, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CREATE_BOND,
+ status);
}
static void handle_cancel_bond_cmd(const void *buf, uint16_t len)
@@ -2597,7 +2602,8 @@ static void handle_cancel_bond_cmd(const void *buf, uint16_t len)
else
status = HAL_STATUS_FAILED;
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_BOND, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_BOND,
+ status);
}
static void unpair_device_complete(uint8_t status, uint16_t length,
@@ -2631,7 +2637,8 @@ static void handle_remove_bond_cmd(const void *buf, uint16_t len)
else
status = HAL_STATUS_FAILED;
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_REMOVE_BOND, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_REMOVE_BOND,
+ status);
}
static void handle_pin_reply_cmd(const void *buf, uint16_t len)
@@ -2682,7 +2689,8 @@ static void handle_pin_reply_cmd(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_PIN_REPLY, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_PIN_REPLY,
+ status);
}
static uint8_t user_confirm_reply(const bdaddr_t *bdaddr, bool accept)
@@ -2770,7 +2778,8 @@ static void handle_ssp_reply_cmd(const void *buf, uint16_t len)
break;
}
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SSP_REPLY, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SSP_REPLY,
+ status);
}
static void handle_get_remote_services_cmd(const void *buf, uint16_t len)
@@ -2783,8 +2792,8 @@ static void handle_get_remote_services_cmd(const void *buf, uint16_t len)
status = browse_remote_sdp(&addr);
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_SERVICES,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_OP_GET_REMOTE_SERVICES, status);
}
static uint8_t get_device_uuids(struct device *dev)
@@ -2907,7 +2916,7 @@ static void handle_enable_cmd(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
reply:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_ENABLE, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_ENABLE, status);
}
static void handle_disable_cmd(const void *buf, uint16_t len)
@@ -2929,15 +2938,15 @@ static void handle_disable_cmd(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
reply:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DISABLE, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DISABLE, status);
}
static void handle_get_adapter_props_cmd(const void *buf, uint16_t len)
{
get_adapter_properties();
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROPS,
- HAL_STATUS_SUCCESS);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_OP_GET_ADAPTER_PROPS, HAL_STATUS_SUCCESS);
}
static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
@@ -2960,8 +2969,8 @@ static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROPS,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_OP_GET_REMOTE_DEVICE_PROPS, status);
}
static void handle_get_remote_device_prop_cmd(const void *buf, uint16_t len)
@@ -3017,8 +3026,8 @@ static void handle_get_remote_device_prop_cmd(const void *buf, uint16_t len)
cmd->type, status);
failed:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROP,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_OP_GET_REMOTE_DEVICE_PROP, status);
}
static uint8_t set_device_friendly_name(struct device *dev, const uint8_t *val,
@@ -3088,8 +3097,8 @@ static void handle_set_remote_device_prop_cmd(const void *buf, uint16_t len)
cmd->type, status);
failed:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_REMOTE_DEVICE_PROP,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_OP_SET_REMOTE_DEVICE_PROP, status);
}
static void handle_get_remote_service_rec_cmd(const void *buf, uint16_t len)
@@ -3098,8 +3107,8 @@ static void handle_get_remote_service_rec_cmd(const void *buf, uint16_t len)
error("get_remote_service_record not supported");
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_SERVICE_REC,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_OP_GET_REMOTE_SERVICE_REC, HAL_STATUS_FAILED);
}
static void handle_start_discovery_cmd(const void *buf, uint16_t len)
@@ -3123,7 +3132,8 @@ static void handle_start_discovery_cmd(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
reply:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_START_DISCOVERY, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_START_DISCOVERY,
+ status);
}
static void handle_cancel_discovery_cmd(const void *buf, uint16_t len)
@@ -3148,7 +3158,8 @@ static void handle_cancel_discovery_cmd(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
reply:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_DISCOVERY, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_DISCOVERY,
+ status);
}
static void handle_dut_mode_conf_cmd(const void *buf, uint16_t len)
@@ -3181,7 +3192,8 @@ static void handle_dut_mode_conf_cmd(const void *buf, uint16_t len)
close(fd);
failed:
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_CONF, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_CONF,
+ status);
}
static void handle_dut_mode_send_cmd(const void *buf, uint16_t len)
@@ -3198,7 +3210,7 @@ static void handle_dut_mode_send_cmd(const void *buf, uint16_t len)
/* TODO */
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_SEND,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_SEND,
HAL_STATUS_FAILED);
}
@@ -3216,7 +3228,7 @@ static void handle_le_test_mode_cmd(const void *buf, uint16_t len)
/* TODO */
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_LE_TEST_MODE,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_LE_TEST_MODE,
HAL_STATUS_FAILED);
}
@@ -3272,11 +3284,13 @@ static const struct ipc_handler cmd_handlers[] = {
{ handle_le_test_mode_cmd, true, sizeof(struct hal_cmd_le_test_mode) },
};
-void bt_bluetooth_register(void)
+void bt_bluetooth_register(struct ipc *ipc)
{
DBG("");
- ipc_register(HAL_SERVICE_ID_BLUETOOTH, cmd_handlers,
+ hal_ipc = ipc;
+
+ ipc_register(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
}
@@ -3290,5 +3304,6 @@ void bt_bluetooth_unregister(void)
g_slist_free_full(cached_devices, (GDestroyNotify) free_device);
cached_devices = NULL;
- ipc_unregister(HAL_SERVICE_ID_CORE);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_CORE);
+ hal_ipc = NULL;
}
diff --git a/android/bluetooth.h b/android/bluetooth.h
index 8ab34f6..fbc850d 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -31,7 +31,7 @@ void bt_bluetooth_cleanup(void);
void bt_bluetooth_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-void bt_bluetooth_register(void);
+void bt_bluetooth_register(struct ipc *ipc);
void bt_bluetooth_unregister(void);
int bt_adapter_add_record(sdp_record_t *rec, uint8_t svc_hint);
diff --git a/android/handsfree.c b/android/handsfree.c
index 60bff91..ef8c776 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -38,11 +38,11 @@
#include "src/uuid-helper.h"
#include "src/shared/hfp.h"
#include "btio/btio.h"
+#include "hal-msg.h"
+#include "ipc.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
@@ -56,6 +56,7 @@ static struct {
static bdaddr_t adapter_addr;
static uint32_t record_id = 0;
+static struct ipc *hal_ipc = NULL;
static GIOChannel *server = NULL;
@@ -75,8 +76,8 @@ static void device_set_state(uint8_t state)
bdaddr2android(&device.bdaddr, ev.bdaddr);
ev.state = state;
- ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CONN_STATE,
- sizeof(ev), &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+ HAL_EV_HANDSFREE_CONN_STATE, sizeof(ev), &ev);
}
static void device_init(const bdaddr_t *bdaddr)
@@ -281,8 +282,8 @@ static void handle_connect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_CONNECT, status);
}
static void handle_disconnect(const void *buf, uint16_t len)
@@ -317,23 +318,23 @@ static void handle_disconnect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_DISCONNECT, status);
}
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);
+ ipc_send_rsp(hal_ipc, 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,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
HAL_OP_HANDSFREE_DISCONNECT_AUDIO, HAL_STATUS_FAILED);
}
@@ -341,31 +342,31 @@ 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);
+ ipc_send_rsp(hal_ipc, 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);
+ ipc_send_rsp(hal_ipc, 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);
+ ipc_send_rsp(hal_ipc, 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,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
HAL_STATUS_FAILED);
}
@@ -374,23 +375,23 @@ 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);
+ ipc_send_rsp(hal_ipc, 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);
+ ipc_send_rsp(hal_ipc, 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,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE,
HAL_STATUS_FAILED);
}
@@ -399,23 +400,23 @@ 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);
+ ipc_send_rsp(hal_ipc, 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);
+ ipc_send_rsp(hal_ipc, 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,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
HAL_STATUS_FAILED);
}
@@ -530,7 +531,7 @@ static sdp_record_t *handsfree_ag_record(void)
return record;
}
-bool bt_handsfree_register(const bdaddr_t *addr)
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr)
{
sdp_record_t *rec;
GError *err = NULL;
@@ -563,7 +564,8 @@ bool bt_handsfree_register(const bdaddr_t *addr)
}
record_id = rec->handle;
- ipc_register(HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
+ hal_ipc = ipc;
+ ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
return true;
@@ -580,7 +582,8 @@ void bt_handsfree_unregister(void)
{
DBG("");
- ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
+ hal_ipc = NULL;
if (server) {
g_io_channel_shutdown(server, TRUE, NULL);
diff --git a/android/handsfree.h b/android/handsfree.h
index e3fdd70..3ede819 100644
--- a/android/handsfree.h
+++ b/android/handsfree.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_handsfree_register(const bdaddr_t *addr);
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr);
void bt_handsfree_unregister(void);
diff --git a/android/hidhost.c b/android/hidhost.c
index fd5ea4d..0c6eb7d 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -81,6 +81,8 @@ static GIOChannel *ctrl_io = NULL;
static GIOChannel *intr_io = NULL;
static GSList *devices = NULL;
+static struct ipc *hal_ipc = NULL;
+
struct hid_device {
bdaddr_t dst;
uint8_t state;
@@ -303,8 +305,8 @@ static void bt_hid_notify_state(struct hid_device *dev, uint8_t state)
bdaddr2android(&dev->dst, ev.bdaddr);
ev.state = state;
- ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_CONN_STATE,
- sizeof(ev), &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_EV_HIDHOST_CONN_STATE, sizeof(ev), &ev);
}
static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
@@ -362,8 +364,8 @@ static void bt_hid_notify_proto_mode(struct hid_device *dev, uint8_t *buf,
ev.mode = HAL_HIDHOST_UNSUPPORTED_PROTOCOL;
}
- ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_PROTO_MODE,
- sizeof(ev), &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_EV_HIDHOST_PROTO_MODE, sizeof(ev), &ev);
}
static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
@@ -405,8 +407,8 @@ static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
}
send:
- ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_GET_REPORT,
- ev_len, ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_EV_HIDHOST_GET_REPORT, ev_len, ev);
g_free(ev);
}
@@ -430,9 +432,8 @@ static void bt_hid_notify_virtual_unplug(struct hid_device *dev,
ev.status = HAL_HIDHOST_STATUS_OK;
}
- ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_VIRTUAL_UNPLUG,
- sizeof(ev), &ev);
-
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_EV_HIDHOST_VIRTUAL_UNPLUG, sizeof(ev), &ev);
}
static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
@@ -515,8 +516,8 @@ static void bt_hid_set_info(struct hid_device *dev)
memset(ev.descr, 0, sizeof(ev.descr));
memcpy(ev.descr, dev->rd_data, ev.descr_len);
- ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_INFO, sizeof(ev),
- &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_INFO,
+ sizeof(ev), &ev);
}
static int uhid_create(struct hid_device *dev)
@@ -806,7 +807,8 @@ static void bt_hid_connect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT,
+ status);
}
static void bt_hid_disconnect(const void *buf, uint16_t len)
@@ -841,7 +843,8 @@ static void bt_hid_disconnect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT,
+ status);
}
static void bt_hid_virtual_unplug(const void *buf, uint16_t len)
@@ -894,8 +897,8 @@ static void bt_hid_virtual_unplug(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_VIRTUAL_UNPLUG,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_OP_HIDHOST_VIRTUAL_UNPLUG, status);
}
static void bt_hid_info(const void *buf, uint16_t len)
@@ -914,7 +917,7 @@ static void bt_hid_info(const void *buf, uint16_t len)
* once device is created with HID internals. */
DBG("Not supported");
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
HAL_STATUS_UNSUPPORTED);
}
@@ -964,8 +967,8 @@ static void bt_hid_get_protocol(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_PROTOCOL,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_OP_HIDHOST_GET_PROTOCOL, status);
}
static void bt_hid_set_protocol(const void *buf, uint16_t len)
@@ -1014,8 +1017,8 @@ static void bt_hid_set_protocol(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_PROTOCOL,
- status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST,
+ HAL_OP_HIDHOST_SET_PROTOCOL, status);
}
static void bt_hid_get_report(const void *buf, uint16_t len)
@@ -1081,7 +1084,8 @@ static void bt_hid_get_report(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT,
+ status);
}
static void bt_hid_set_report(const void *buf, uint16_t len)
@@ -1158,7 +1162,8 @@ static void bt_hid_set_report(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT,
+ status);
}
static void bt_hid_send_data(const void *buf, uint16_t len)
@@ -1224,7 +1229,8 @@ static void bt_hid_send_data(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA,
+ status);
}
static const struct ipc_handler cmd_handlers[] = {
@@ -1323,7 +1329,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
}
}
-bool bt_hid_register(const bdaddr_t *addr)
+bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr)
{
GError *err = NULL;
@@ -1358,7 +1364,9 @@ bool bt_hid_register(const bdaddr_t *addr)
return false;
}
- ipc_register(HAL_SERVICE_ID_HIDHOST, cmd_handlers,
+ hal_ipc = ipc;
+
+ ipc_register(hal_ipc, HAL_SERVICE_ID_HIDHOST, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
return true;
@@ -1383,5 +1391,6 @@ void bt_hid_unregister(void)
intr_io = NULL;
}
- ipc_unregister(HAL_SERVICE_ID_HIDHOST);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_HIDHOST);
+ hal_ipc = NULL;
}
diff --git a/android/hidhost.h b/android/hidhost.h
index 5c3c801..1017195 100644
--- a/android/hidhost.h
+++ b/android/hidhost.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_hid_register(const bdaddr_t *addr);
+bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr);
void bt_hid_unregister(void);
diff --git a/android/ipc.c b/android/ipc.c
index 4a3a60d..3d6e2a3 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -40,13 +40,19 @@
#include "ipc.h"
#include "src/log.h"
-static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
+struct ipc {
+ struct service_handler *services;
+ int service_max;
-static GIOChannel *cmd_io = NULL;
-static GIOChannel *notif_io = NULL;
+ const char *path;
+ size_t size;
-static guint cmd_watch = 0;
-static guint notif_watch = 0;
+ GIOChannel *cmd_io;
+ guint cmd_watch;
+
+ GIOChannel *notif_io;
+ guint notif_watch;
+};
int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
const void *buf, ssize_t len)
@@ -103,6 +109,8 @@ int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
+ struct ipc *ipc = user_data;
+
char buf[BLUEZ_HAL_MTU];
ssize_t ret;
int fd, err;
@@ -121,7 +129,7 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
goto fail;
}
- err = ipc_handle_msg(services, HAL_SERVICE_ID_MAX, buf, ret);
+ err = ipc_handle_msg(ipc->services, ipc->service_max, buf, ret);
if (err < 0) {
error("IPC: failed to handle message, terminating (%s)",
strerror(-err));
@@ -181,6 +189,8 @@ GIOChannel *ipc_connect(const char *path, size_t size, GIOFunc connect_cb,
static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
+ struct ipc *ipc = user_data;
+
DBG("");
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
@@ -191,11 +201,11 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- notif_watch = g_io_add_watch(io, cond, notif_watch_cb, NULL);
+ ipc->notif_watch = g_io_add_watch(io, cond, notif_watch_cb, ipc);
cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- cmd_watch = g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
+ ipc->cmd_watch = g_io_add_watch(ipc->cmd_io, cond, cmd_watch_cb, ipc);
info("IPC: successfully connected");
@@ -205,6 +215,8 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
+ struct ipc *ipc = user_data;
+
DBG("");
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
@@ -213,45 +225,62 @@ static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
return FALSE;
}
- notif_io = ipc_connect(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
- notif_connect_cb, NULL);
- if (!notif_io)
+ ipc->notif_io = ipc_connect(ipc->path, ipc->size, notif_connect_cb,
+ ipc);
+ if (!ipc->notif_io)
raise(SIGTERM);
return FALSE;
}
-void ipc_init(void)
+struct ipc *ipc_init(const char *path, size_t size, int max_service_id)
{
- cmd_io = ipc_connect(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
- cmd_connect_cb, NULL);
- if (!cmd_io)
- raise(SIGTERM);
+ struct ipc *ipc;
+
+ ipc = g_new0(struct ipc, 1);
+
+ ipc->services = g_new0(struct service_handler, max_service_id + 1);
+ ipc->service_max = max_service_id;
+
+ ipc->path = path;
+ ipc->size = size;
+
+ ipc->cmd_io = ipc_connect(path, size, cmd_connect_cb, ipc);
+ if (!ipc->cmd_io) {
+ g_free(ipc->services);
+ g_free(ipc);
+ return NULL;
+ }
+
+ return ipc;
}
-void ipc_cleanup(void)
+void ipc_cleanup(struct ipc *ipc)
{
- if (cmd_watch) {
- g_source_remove(cmd_watch);
- cmd_watch = 0;
+ if (ipc->cmd_watch) {
+ g_source_remove(ipc->cmd_watch);
+ ipc->cmd_watch = 0;
}
- if (cmd_io) {
- g_io_channel_shutdown(cmd_io, TRUE, NULL);
- g_io_channel_unref(cmd_io);
- cmd_io = NULL;
+ if (ipc->cmd_io) {
+ g_io_channel_shutdown(ipc->cmd_io, TRUE, NULL);
+ g_io_channel_unref(ipc->cmd_io);
+ ipc->cmd_io = NULL;
}
- if (notif_watch) {
- g_source_remove(notif_watch);
- notif_watch = 0;
+ if (ipc->notif_watch) {
+ g_source_remove(ipc->notif_watch);
+ ipc->notif_watch = 0;
}
- if (notif_io) {
- g_io_channel_shutdown(notif_io, TRUE, NULL);
- g_io_channel_unref(notif_io);
- notif_io = NULL;
+ if (ipc->notif_io) {
+ g_io_channel_shutdown(ipc->notif_io, TRUE, NULL);
+ g_io_channel_unref(ipc->notif_io);
+ ipc->notif_io = NULL;
}
+
+ g_free(ipc->services);
+ g_free(ipc);
}
void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
@@ -299,12 +328,13 @@ void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
}
}
-void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status)
+void ipc_send_rsp(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
+ uint8_t status)
{
struct hal_status s;
int sk;
- sk = g_io_channel_unix_get_fd(cmd_io);
+ sk = g_io_channel_unix_get_fd(ipc->cmd_io);
if (status == HAL_STATUS_SUCCESS) {
ipc_send(sk, service_id, opcode, 0, NULL, -1);
@@ -316,32 +346,38 @@ void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status)
ipc_send(sk, service_id, HAL_OP_STATUS, sizeof(s), &s, -1);
}
-void ipc_send_rsp_full(uint8_t service_id, uint8_t opcode, uint16_t len,
- void *param, int fd)
+void ipc_send_rsp_full(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
+ uint16_t len, void *param, int fd)
{
- ipc_send(g_io_channel_unix_get_fd(cmd_io), service_id, opcode, len,
+ ipc_send(g_io_channel_unix_get_fd(ipc->cmd_io), service_id, opcode, len,
param, fd);
}
-void ipc_send_notif(uint8_t service_id, uint8_t opcode, uint16_t len,
- void *param)
+void ipc_send_notif(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
+ uint16_t len, void *param)
{
- if (!notif_io)
+ if (!ipc || !ipc->notif_io)
return;
- ipc_send(g_io_channel_unix_get_fd(notif_io), service_id, opcode, len,
- param, -1);
+ ipc_send(g_io_channel_unix_get_fd(ipc->notif_io), service_id, opcode,
+ len, param, -1);
}
-void ipc_register(uint8_t service, const struct ipc_handler *handlers,
- uint8_t size)
+void ipc_register(struct ipc *ipc, uint8_t service,
+ const struct ipc_handler *handlers, uint8_t size)
{
- services[service].handler = handlers;
- services[service].size = size;
+ if (service > ipc->service_max)
+ return;
+
+ ipc->services[service].handler = handlers;
+ ipc->services[service].size = size;
}
-void ipc_unregister(uint8_t service)
+void ipc_unregister(struct ipc *ipc, uint8_t service)
{
- services[service].handler = NULL;
- services[service].size = 0;
+ if (service > ipc->service_max)
+ return;
+
+ ipc->services[service].handler = NULL;
+ ipc->services[service].size = 0;
}
diff --git a/android/ipc.h b/android/ipc.h
index cfa4018..601301c 100644
--- a/android/ipc.h
+++ b/android/ipc.h
@@ -32,20 +32,24 @@ struct service_handler {
uint8_t size;
};
-void ipc_init(void);
-void ipc_cleanup(void);
+struct ipc;
+
+struct ipc *ipc_init(const char *path, size_t size, int max_service_id);
+void ipc_cleanup(struct ipc *ipc);
+
GIOChannel *ipc_connect(const char *path, size_t size, GIOFunc connect_cb,
void *user_data);
int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
const void *buf, ssize_t len);
-void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status);
-void ipc_send_rsp_full(uint8_t service_id, uint8_t opcode, uint16_t len,
- void *param, int fd);
-void ipc_send_notif(uint8_t service_id, uint8_t opcode, uint16_t len,
- void *param);
+void ipc_send_rsp(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
+ uint8_t status);
+void ipc_send_rsp_full(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
+ uint16_t len, void *param, int fd);
+void ipc_send_notif(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
+ uint16_t len, void *param);
void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
void *param, int fd);
-void ipc_register(uint8_t service, const struct ipc_handler *handlers,
- uint8_t size);
-void ipc_unregister(uint8_t service);
+void ipc_register(struct ipc *ipc, uint8_t service,
+ const struct ipc_handler *handlers, uint8_t size);
+void ipc_unregister(struct ipc *ipc, uint8_t service);
diff --git a/android/main.c b/android/main.c
index aca6351..9f22486 100644
--- a/android/main.c
+++ b/android/main.c
@@ -48,11 +48,11 @@
#include "lib/bluetooth.h"
+#include "ipc.h"
#include "bluetooth.h"
#include "socket.h"
#include "hidhost.h"
#include "hal-msg.h"
-#include "ipc.h"
#include "a2dp.h"
#include "pan.h"
#include "avrcp.h"
@@ -67,6 +67,8 @@ static bdaddr_t adapter_bdaddr;
static GMainLoop *event_loop;
+static struct ipc *hal_ipc = NULL;
+
static bool services[HAL_SERVICE_ID_MAX + 1] = { false };
static void service_register(const void *buf, uint16_t len)
@@ -81,43 +83,43 @@ static void service_register(const void *buf, uint16_t len)
switch (m->service_id) {
case HAL_SERVICE_ID_BLUETOOTH:
- bt_bluetooth_register();
+ bt_bluetooth_register(hal_ipc);
break;
case HAL_SERVICE_ID_SOCKET:
- bt_socket_register(&adapter_bdaddr);
+ bt_socket_register(hal_ipc, &adapter_bdaddr);
break;
case HAL_SERVICE_ID_HIDHOST:
- if (!bt_hid_register(&adapter_bdaddr)) {
+ if (!bt_hid_register(hal_ipc, &adapter_bdaddr)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_A2DP:
- if (!bt_a2dp_register(&adapter_bdaddr)) {
+ if (!bt_a2dp_register(hal_ipc, &adapter_bdaddr)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_PAN:
- if (!bt_pan_register(&adapter_bdaddr)) {
+ if (!bt_pan_register(hal_ipc, &adapter_bdaddr)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_AVRCP:
- if (!bt_avrcp_register(&adapter_bdaddr)) {
+ if (!bt_avrcp_register(hal_ipc, &adapter_bdaddr)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_HANDSFREE:
- if (!bt_handsfree_register(&adapter_bdaddr)) {
+ if (!bt_handsfree_register(hal_ipc, &adapter_bdaddr)) {
status = HAL_STATUS_FAILED;
goto failed;
}
@@ -136,7 +138,8 @@ static void service_register(const void *buf, uint16_t len)
info("Service ID=%u registered", m->service_id);
failed:
- ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
+ status);
}
static void service_unregister(const void *buf, uint16_t len)
@@ -186,7 +189,8 @@ static void service_unregister(const void *buf, uint16_t len)
info("Service ID=%u unregistered", m->service_id);
failed:
- ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+ status);
}
static const struct ipc_handler cmd_handlers[] = {
@@ -240,7 +244,15 @@ static void adapter_ready(int err, const bdaddr_t *addr)
info("Adapter initialized");
- ipc_init();
+ hal_ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
+ HAL_SERVICE_ID_MAX);
+ if (!hal_ipc) {
+ error("Failed to initialize IPC");
+ exit(EXIT_FAILURE);
+ }
+
+ ipc_register(hal_ipc, HAL_SERVICE_ID_CORE, cmd_handlers,
+ G_N_ELEMENTS(cmd_handlers));
}
static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
@@ -464,9 +476,6 @@ int main(int argc, char *argv[])
/* Use params: mtu = 0, flags = 0 */
start_sdp_server(0, 0);
- ipc_register(HAL_SERVICE_ID_CORE, cmd_handlers,
- G_N_ELEMENTS(cmd_handlers));
-
DBG("Entering main loop");
event_loop = g_main_loop_new(NULL, FALSE);
@@ -480,12 +489,12 @@ int main(int argc, char *argv[])
cleanup_services();
- ipc_cleanup();
stop_sdp_server();
bt_bluetooth_cleanup();
g_main_loop_unref(event_loop);
- ipc_unregister(HAL_SERVICE_ID_CORE);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_CORE);
+ ipc_cleanup(hal_ipc);
info("Exit");
diff --git a/android/pan.c b/android/pan.c
index cfc03bc..b4a3494 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -49,11 +49,11 @@
#include "profiles/network/bnep.h"
#include "src/log.h"
-#include "pan.h"
#include "hal-msg.h"
#include "ipc.h"
#include "utils.h"
#include "bluetooth.h"
+#include "pan.h"
#define SVC_HINT_NETWORKING 0x02
@@ -64,6 +64,7 @@
static bdaddr_t adapter_addr;
GSList *devices = NULL;
uint8_t local_role = HAL_PAN_ROLE_NONE;
+static struct ipc *hal_ipc = NULL;
struct pan_device {
char iface[16];
@@ -247,8 +248,8 @@ static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
ev.remote_role = dev->role;
ev.status = HAL_STATUS_SUCCESS;
- ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
- &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE,
+ sizeof(ev), &ev);
if (dev->conn_state == HAL_PAN_STATE_DISCONNECTED)
pan_device_remove(dev);
}
@@ -270,8 +271,8 @@ static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
else
memcpy(ev.name, dev->iface, sizeof(dev->iface));
- ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
- &ev);
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE,
+ sizeof(ev), &ev);
}
static void bnep_disconn_cb(void *data)
@@ -414,7 +415,7 @@ static void bt_pan_connect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, status);
}
static void bt_pan_disconnect(const void *buf, uint16_t len)
@@ -444,7 +445,8 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT,
+ status);
}
static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
@@ -676,7 +678,7 @@ static void bt_pan_enable(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
reply:
- ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
}
static void bt_pan_get_role(const void *buf, uint16_t len)
@@ -686,8 +688,8 @@ static void bt_pan_get_role(const void *buf, uint16_t len)
DBG("");
rsp.local_role = local_role;
- ipc_send_rsp_full(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, sizeof(rsp),
- &rsp, -1);
+ ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE,
+ sizeof(rsp), &rsp, -1);
}
static const struct ipc_handler cmd_handlers[] = {
@@ -776,7 +778,7 @@ static sdp_record_t *pan_record(void)
return record;
}
-bool bt_pan_register(const bdaddr_t *addr)
+bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr)
{
sdp_record_t *rec;
int err;
@@ -813,7 +815,9 @@ bool bt_pan_register(const bdaddr_t *addr)
}
nap_dev.record_id = rec->handle;
- ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
+
+ hal_ipc = ipc;
+ ipc_register(hal_ipc, HAL_SERVICE_ID_PAN, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
return true;
@@ -829,7 +833,9 @@ void bt_pan_unregister(void)
bnep_cleanup();
- ipc_unregister(HAL_SERVICE_ID_PAN);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_PAN);
+ hal_ipc = NULL;
+
bt_adapter_remove_record(nap_dev.record_id);
nap_dev.record_id = 0;
destroy_nap_device();
diff --git a/android/pan.h b/android/pan.h
index 72a7eab..2045ac5 100644
--- a/android/pan.h
+++ b/android/pan.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_pan_register(const bdaddr_t *addr);
+bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr);
void bt_pan_unregister(void);
diff --git a/android/socket.c b/android/socket.c
index 655ee40..d463255 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -38,11 +38,11 @@
#include "src/sdpd.h"
#include "src/log.h"
-#include "bluetooth.h"
#include "hal-msg.h"
#include "hal-ipc.h"
#include "ipc.h"
#include "utils.h"
+#include "bluetooth.h"
#include "socket.h"
#define RFCOMM_CHANNEL_MAX 30
@@ -60,6 +60,7 @@
#define MAP_MSG_TYPE_SMS_CDMA 0x04
#define DEFAULT_MAS_MSG_TYPE (MAP_MSG_TYPE_SMS_GSM | MAP_MSG_TYPE_SMS_CDMA)
+static struct ipc *hal_ipc = NULL;
struct rfcomm_sock {
int channel; /* RFCOMM channel */
BtIOSecLevel sec_level;
@@ -862,13 +863,14 @@ static void handle_listen(const void *buf, uint16_t len)
if (status != HAL_STATUS_SUCCESS)
goto failed;
- ipc_send_rsp_full(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN, 0, NULL,
- hal_sock);
+ ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN,
+ 0, NULL, hal_sock);
close(hal_sock);
return ;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN,
+ status);
}
static bool sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
@@ -1106,13 +1108,14 @@ static void handle_connect(const void *buf, uint16_t len)
if (status != HAL_STATUS_SUCCESS)
goto failed;
- ipc_send_rsp_full(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT, 0,
- NULL, hal_sock);
+ ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT,
+ 0, NULL, hal_sock);
close(hal_sock);
return;
failed:
- ipc_send_rsp(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT, status);
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT,
+ status);
}
@@ -1123,7 +1126,7 @@ static const struct ipc_handler cmd_handlers[] = {
{ handle_connect, false, sizeof(struct hal_cmd_socket_connect) },
};
-void bt_socket_register(const bdaddr_t *addr)
+void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr)
{
size_t i;
@@ -1137,7 +1140,9 @@ void bt_socket_register(const bdaddr_t *addr)
servers[profiles[i].channel].reserved = true;
bacpy(&adapter_addr, addr);
- ipc_register(HAL_SERVICE_ID_SOCKET, cmd_handlers,
+
+ hal_ipc = ipc;
+ ipc_register(hal_ipc, HAL_SERVICE_ID_SOCKET, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
}
@@ -1155,5 +1160,6 @@ void bt_socket_unregister(void)
memset(servers, 0, sizeof(servers));
- ipc_unregister(HAL_SERVICE_ID_SOCKET);
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_SOCKET);
+ hal_ipc = NULL;
}
diff --git a/android/socket.h b/android/socket.h
index d41616f..d3ed9b4 100644
--- a/android/socket.h
+++ b/android/socket.h
@@ -30,5 +30,5 @@ struct hal_sock_connect_signal {
void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-void bt_socket_register(const bdaddr_t *addr);
+void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr);
void bt_socket_unregister(void);
diff --git a/android/test-ipc.c b/android/test-ipc.c
index 8dd53a1..054af84 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -43,6 +43,8 @@
#include "android/hal-msg.h"
#include "android/ipc.h"
+static struct ipc *ipc = NULL;
+
struct test_data {
uint32_t expected_signal;
const void *cmd;
@@ -283,11 +285,15 @@ static void test_init(gconstpointer data)
{
struct context *context = create_context(data);
- ipc_init();
+ ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
+ HAL_SERVICE_ID_MAX);
+
+ g_assert(ipc);
execute_context(context);
- ipc_cleanup();
+ ipc_cleanup(ipc);
+ ipc = NULL;
}
static gboolean send_cmd(gpointer user_data)
@@ -310,7 +316,7 @@ static gboolean register_service(gpointer user_data)
struct context *context = user_data;
const struct test_data *test_data = context->data;
- ipc_register(test_data->service, test_data->handlers,
+ ipc_register(ipc, test_data->service, test_data->handlers,
test_data->handlers_size);
return FALSE;
@@ -321,7 +327,7 @@ static gboolean unregister_service(gpointer user_data)
struct context *context = user_data;
const struct test_data *test_data = context->data;
- ipc_unregister(test_data->service);
+ ipc_unregister(ipc, test_data->service);
return FALSE;
}
@@ -330,13 +336,17 @@ static void test_cmd(gconstpointer data)
{
struct context *context = create_context(data);
- ipc_init();
+ ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
+ HAL_SERVICE_ID_MAX);
+
+ g_assert(ipc);
g_idle_add(send_cmd, context);
execute_context(context);
- ipc_cleanup();
+ ipc_cleanup(ipc);
+ ipc = NULL;
}
static void test_cmd_reg(gconstpointer data)
@@ -344,23 +354,30 @@ static void test_cmd_reg(gconstpointer data)
struct context *context = create_context(data);
const struct test_data *test_data = context->data;
- ipc_init();
+ ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
+ HAL_SERVICE_ID_MAX);
+
+ g_assert(ipc);
g_idle_add(register_service, context);
g_idle_add(send_cmd, context);
execute_context(context);
- ipc_unregister(test_data->service);
+ ipc_unregister(ipc, test_data->service);
- ipc_cleanup();
+ ipc_cleanup(ipc);
+ ipc = NULL;
}
static void test_cmd_reg_1(gconstpointer data)
{
struct context *context = create_context(data);
- ipc_init();
+ ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
+ HAL_SERVICE_ID_MAX);
+
+ g_assert(ipc);
g_idle_add(register_service, context);
g_idle_add(unregister_service, context);
@@ -368,17 +385,18 @@ static void test_cmd_reg_1(gconstpointer data)
execute_context(context);
- ipc_cleanup();
+ ipc_cleanup(ipc);
+ ipc = NULL;
}
static void test_cmd_handler_1(const void *buf, uint16_t len)
{
- ipc_send_rsp(0, 1, 0);
+ ipc_send_rsp(ipc, 0, 1, 0);
}
static void test_cmd_handler_2(const void *buf, uint16_t len)
{
- ipc_send_rsp(0, 2, 0);
+ ipc_send_rsp(ipc, 0, 2, 0);
}
static void test_cmd_handler_invalid(const void *buf, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH] tools: Fix using uninitialized value
From: Andrei Emeltchenko @ 2014-02-25 10:19 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Fixes warning:
tools/ibeacon.c:150:14: warning: The left expression of the compound
assignment is an uninitialized value. The computed value will also be
garbage
cmd.data[2] |= 0x02; /* LE General Discoverable Mode
*/
~~~~~~~~~~~ ^
1 warning generated.
---
tools/ibeacon.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/ibeacon.c b/tools/ibeacon.c
index 458f9e7..cd0ef65 100644
--- a/tools/ibeacon.c
+++ b/tools/ibeacon.c
@@ -145,6 +145,8 @@ static void adv_tx_power_callback(const void *data, uint8_t size,
return;
}
+ memset(&cmd, 0, sizeof(cmd));
+
cmd.data[0] = 0x02; /* Field length */
cmd.data[1] = 0x01; /* Flags */
cmd.data[2] |= 0x02; /* LE General Discoverable Mode */
--
1.8.3.2
^ permalink raw reply related
* [PATCH] Bluetooth: Fix NULL pointer dereference when sending data
From: Andrzej Kaczmarek @ 2014-02-25 10:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
When trying to allocate skb for new PDU, l2cap_chan is unlocked so we
can sleep waiting for memory as otherwise there's possible deadlock as
fixed in e454c84464. However, in a6a5568c03 lock was moved from socket
to channel level and it's no longer safe to just unlock and lock again
without checking l2cap_chan state since channel can be disconnected
when lock is not held.
This patch adds missing checks for l2cap_chan state when returning from
call which allocates skb.
Scenario is easily reproducible by running rfcomm-tester in a loop.
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<ffffffffa0442169>] l2cap_do_send+0x29/0x120 [bluetooth]
PGD 0
Oops: 0000 [#1] SMP
Modules linked in:
CPU: 7 PID: 4038 Comm: krfcommd Not tainted 3.14.0-rc2+ #15
Hardware name: Dell Inc. OptiPlex 790/0HY9JP, BIOS A10 11/24/2011
task: ffff8802bdd731c0 ti: ffff8801ec986000 task.ti: ffff8801ec986000
RIP: 0010:[<ffffffffa0442169>] [<ffffffffa0442169>] l2cap_do_send+0x29/0x120
RSP: 0018:ffff8801ec987ad8 EFLAGS: 00010202
RAX: 0000000000000000 RBX: ffff8800c5796800 RCX: 0000000000000000
RDX: ffff880410e7a800 RSI: ffff8802b6c1da00 RDI: ffff8800c5796800
RBP: ffff8801ec987af8 R08: 00000000000000c0 R09: 0000000000000300
R10: 000000000000573b R11: 000000000000573a R12: ffff8802b6c1da00
R13: 0000000000000000 R14: ffff8802b6c1da00 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff88042dce0000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000041257c000 CR4: 00000000000407e0
Stack:
ffff8801ec987d78 ffff8800c5796800 ffff8801ec987d78 0000000000000000
ffff8801ec987ba8 ffffffffa0449e37 0000000000000004 ffff8801ec987af0
ffff8801ec987d40 0000000000000282 0000000000000000 ffffffff00000004
Call Trace:
[<ffffffffa0449e37>] l2cap_chan_send+0xaa7/0x1120 [bluetooth]
[<ffffffff81770100>] ? _raw_spin_unlock_bh+0x20/0x40
[<ffffffffa045188b>] l2cap_sock_sendmsg+0xcb/0x110 [bluetooth]
[<ffffffff81652b0f>] sock_sendmsg+0xaf/0xc0
[<ffffffff810a8381>] ? update_curr+0x141/0x200
[<ffffffff810a8961>] ? dequeue_entity+0x181/0x520
[<ffffffff81652b60>] kernel_sendmsg+0x40/0x60
[<ffffffffa04a8505>] rfcomm_send_frame+0x45/0x70 [rfcomm]
[<ffffffff810766f0>] ? internal_add_timer+0x20/0x50
[<ffffffffa04a8564>] rfcomm_send_cmd+0x34/0x60 [rfcomm]
[<ffffffffa04a8605>] rfcomm_send_disc+0x75/0xa0 [rfcomm]
[<ffffffffa04aacec>] rfcomm_run+0x8cc/0x1a30 [rfcomm]
[<ffffffffa04aa420>] ? rfcomm_check_accept+0xc0/0xc0 [rfcomm]
[<ffffffff8108e3a9>] kthread+0xc9/0xe0
[<ffffffff8108e2e0>] ? flush_kthread_worker+0xb0/0xb0
[<ffffffff817795fc>] ret_from_fork+0x7c/0xb0
[<ffffffff8108e2e0>] ? flush_kthread_worker+0xb0/0xb0
Code: 00 00 66 66 66 66 90 55 48 89 e5 48 83 ec 20 f6 05 d6 a3 02 00 04
RIP [<ffffffffa0442169>] l2cap_do_send+0x29/0x120 [bluetooth]
RSP <ffff8801ec987ad8>
CR2: 0000000000000000
Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@tieto.com>
---
net/bluetooth/l2cap_core.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6ace116..cfc7c69 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2434,6 +2434,11 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
if (IS_ERR(skb))
return PTR_ERR(skb);
+ if (chan->state != BT_CONNECTED) {
+ kfree_skb(skb);
+ return -ENOTCONN;
+ }
+
l2cap_do_send(chan, skb);
return len;
}
@@ -2483,6 +2488,11 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
if (IS_ERR(skb))
return PTR_ERR(skb);
+ if (chan->state != BT_CONNECTED) {
+ kfree_skb(skb);
+ return -ENOTCONN;
+ }
+
l2cap_do_send(chan, skb);
err = len;
break;
--
1.8.5.4
^ permalink raw reply related
* [PATCH 4/4] unit/avrcp: Add /TP/PTT/BV-05-I test
From: Andrei Emeltchenko @ 2014-02-25 10:09 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393322970-27451-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Test verifies that the Target reacts to the PASS THROUGH command in
category 1 from the Controller. The command chosen is PLAY (0x44).
The PLAY button is being pressed and released.
---
unit/test-avrcp.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 66f0973..53e9237 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -354,5 +354,15 @@ int main(int argc, char *argv[])
raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
AVC_SELECT, 0x00));
+ define_test("/TP/PTT/BV-05-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
+ AVC_PLAY, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
+ AVC_PLAY, 0x00),
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
+ AVC_PLAY | 0x80, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
+ AVC_PLAY | 0x80, 0x00));
+
return g_test_run();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/4] unit/avrcp: Add /TP/PTT/BV-04-I test
From: Andrei Emeltchenko @ 2014-02-25 10:09 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393322970-27451-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Test verifies that the Target reacts to the PASS THROUGH command in
category 4 from the Controller. The command chosen is SELECT.
---
unit/test-avrcp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index d46f98c..66f0973 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -270,10 +270,18 @@ static bool handle_channel_up(struct avrcp *session)
return true;
}
+static bool handle_select(struct avrcp *session)
+{
+ DBG("");
+
+ return true;
+}
+
static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, handle_play },
{ AVC_VOLUME_UP, handle_volume_up },
{ AVC_CHANNEL_UP, handle_channel_up },
+ { AVC_SELECT, handle_select },
{ },
};
@@ -340,5 +348,11 @@ int main(int argc, char *argv[])
raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
AVC_CHANNEL_UP, 0x00));
+ define_test("/TP/PTT/BV-04-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
+ AVC_SELECT, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
+ AVC_SELECT, 0x00));
+
return g_test_run();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/4] unit/avrcp: Add /TP/PTT/BV-03-I test
From: Andrei Emeltchenko @ 2014-02-25 10:09 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393322970-27451-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Test verifies that the Target reacts to the PASS THROUGH command in
category 3 from the Controller. The command chosen is CHANNEL_UP.
---
unit/test-avrcp.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 7308443..d46f98c 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -263,9 +263,17 @@ static bool handle_volume_up(struct avrcp *session)
return true;
}
+static bool handle_channel_up(struct avrcp *session)
+{
+ DBG("");
+
+ return true;
+}
+
static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, handle_play },
{ AVC_VOLUME_UP, handle_volume_up },
+ { AVC_CHANNEL_UP, handle_channel_up },
{ },
};
@@ -326,5 +334,11 @@ int main(int argc, char *argv[])
raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
AVC_VOLUME_UP, 0x00));
+ define_test("/TP/PTT/BV-03-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
+ AVC_CHANNEL_UP, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
+ AVC_CHANNEL_UP, 0x00));
+
return g_test_run();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/4] unit/avrcp: Add /TP/PTT/BV-02-I test
From: Andrei Emeltchenko @ 2014-02-25 10:09 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Test verifies that the Target reacts to the PASS THROUGH command in
category 2 from the Controller. The command chosen is VOLUME_UP.
---
unit/test-avrcp.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 9bd27da..7308443 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -251,11 +251,21 @@ static void execute_context(struct context *context)
static bool handle_play(struct avrcp *session)
{
+ DBG("");
+
+ return true;
+}
+
+static bool handle_volume_up(struct avrcp *session)
+{
+ DBG("");
+
return true;
}
static const struct avrcp_passthrough_handler passthrough_handlers[] = {
{ AVC_PLAY, handle_play },
+ { AVC_VOLUME_UP, handle_volume_up },
{ },
};
@@ -310,5 +320,11 @@ int main(int argc, char *argv[])
raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
0x44, 0x00));
+ define_test("/TP/PTT/BV-02-I", test_server,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
+ AVC_VOLUME_UP, 0x00),
+ raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
+ AVC_VOLUME_UP, 0x00));
+
return g_test_run();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 9/9] shared/hfp_at: Add function to get unquoted string
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
---
src/shared/hfp_at.c | 27 +++++++++++++++++++++++++++
src/shared/hfp_at.h | 2 ++
2 files changed, 29 insertions(+)
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
index 750133f..50e8614 100644
--- a/src/shared/hfp_at.c
+++ b/src/shared/hfp_at.c
@@ -278,6 +278,33 @@ bool hfp_at_get_string(struct hfp_at *hfp_at, const char *data, char *buf,
return true;
}
+bool hfp_at_get_unquoted_string(struct hfp_at *hfp_at, const char *data,
+ char *buf, uint8_t len)
+{
+ int i = 0;
+ char c;
+
+ hfp_at_skip_whitespace(hfp_at, data);
+
+ c = data[hfp_at->offset];
+ if (c == '"' || c == ')' || c == '(')
+ return false;
+
+ while (data[hfp_at->offset] != '\0' && data[hfp_at->offset] != ','
+ && data[hfp_at->offset] != ')') {
+ if (i < len)
+ buf[i++] = data[hfp_at->offset];
+ hfp_at->offset++;
+ }
+
+ if (i < len)
+ buf[i++] = '\0';
+
+ hfp_at_next_field(hfp_at, data);
+
+ return true;
+}
+
bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data)
{
hfp_at_skip_whitespace(hfp_at, data);
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
index 4da381b..76bdb03 100644
--- a/src/shared/hfp_at.h
+++ b/src/shared/hfp_at.h
@@ -47,6 +47,8 @@ bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data);
bool hfp_at_close_container(struct hfp_at *hfp_at, const char *data);
bool hfp_at_get_string(struct hfp_at *hfp_at, const char *data, char *buf,
uint8_t len);
+bool hfp_at_get_unquoted_string(struct hfp_at *hfp_at, const char *data,
+ char *buf, uint8_t len);
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 8/9] shared/hfp_at: Add function to get string
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will look for quoted sting and write it to buffer.
---
src/shared/hfp_at.c | 32 ++++++++++++++++++++++++++++++++
src/shared/hfp_at.h | 2 ++
2 files changed, 34 insertions(+)
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
index 2db40b2..750133f 100644
--- a/src/shared/hfp_at.c
+++ b/src/shared/hfp_at.c
@@ -246,6 +246,38 @@ bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val)
return true;
}
+bool hfp_at_get_string(struct hfp_at *hfp_at, const char *data, char *buf,
+ uint8_t len)
+{
+ int i = 0;
+
+ hfp_at_skip_whitespace(hfp_at, data);
+
+ if (data[hfp_at->offset] != '"')
+ return false;
+
+ hfp_at->offset++;
+
+ while (data[hfp_at->offset] != '\0' && data[hfp_at->offset] != '"') {
+ if (i < len)
+ buf[i++] = data[hfp_at->offset];
+ hfp_at->offset++;
+ }
+
+ if (i < len)
+ buf[i++] = '\0';
+
+ if (data[hfp_at->offset] == '"')
+ hfp_at->offset++;
+ else
+ return false;
+
+ hfp_at_skip_whitespace(hfp_at, data);
+ hfp_at_next_field(hfp_at, data);
+
+ return true;
+}
+
bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data)
{
hfp_at_skip_whitespace(hfp_at, data);
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
index e709acb..4da381b 100644
--- a/src/shared/hfp_at.h
+++ b/src/shared/hfp_at.h
@@ -45,6 +45,8 @@ bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val);
bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data);
bool hfp_at_close_container(struct hfp_at *hfp_at, const char *data);
+bool hfp_at_get_string(struct hfp_at *hfp_at, const char *data, char *buf,
+ uint8_t len);
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 7/9] shared/hfp_at: Add function to close container
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will look for ")" parenthesis and skip it if found.
---
src/shared/hfp_at.c | 13 +++++++++++++
src/shared/hfp_at.h | 1 +
2 files changed, 14 insertions(+)
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
index 3bf1fd6..2db40b2 100644
--- a/src/shared/hfp_at.c
+++ b/src/shared/hfp_at.c
@@ -259,6 +259,19 @@ bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data)
return true;
}
+bool hfp_at_close_container(struct hfp_at *hfp_at, const char *data)
+{
+ hfp_at_skip_whitespace(hfp_at, data);
+
+ /* The list shall be followed by a right parenthesis (")" V250 5.7.3.1*/
+ if (data[hfp_at->offset] != ')')
+ return false;
+
+ hfp_at->offset++;
+
+ return true;
+}
+
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers)
{
struct hfp_at *hfp_at;
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
index d5dcf9d..e709acb 100644
--- a/src/shared/hfp_at.h
+++ b/src/shared/hfp_at.h
@@ -44,6 +44,7 @@ bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val);
bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data);
+bool hfp_at_close_container(struct hfp_at *hfp_at, const char *data);
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 6/9] shared/hfp_at: Add function to open container
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will look for "(" parenthesis and skip it if found.
---
src/shared/hfp_at.c | 13 +++++++++++++
src/shared/hfp_at.h | 1 +
2 files changed, 14 insertions(+)
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
index 623dab3..3bf1fd6 100644
--- a/src/shared/hfp_at.c
+++ b/src/shared/hfp_at.c
@@ -246,6 +246,19 @@ bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val)
return true;
}
+bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data)
+{
+ hfp_at_skip_whitespace(hfp_at, data);
+
+ /* The list shall be preceded by a left parenthesis "(") */
+ if (data[hfp_at->offset] != '(')
+ return false;
+
+ hfp_at->offset++;
+
+ return true;
+}
+
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers)
{
struct hfp_at *hfp_at;
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
index 2e2a757..d5dcf9d 100644
--- a/src/shared/hfp_at.h
+++ b/src/shared/hfp_at.h
@@ -43,6 +43,7 @@ bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
void *user_data);
bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val);
+bool hfp_at_open_container(struct hfp_at *hfp_at, const char *data);
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 5/9] shared/hfp_at: Add function for getting number
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will fetch decimal value from AT command.
---
src/shared/hfp_at.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/shared/hfp_at.h | 2 ++
2 files changed, 42 insertions(+)
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
index eff0a38..623dab3 100644
--- a/src/shared/hfp_at.c
+++ b/src/shared/hfp_at.c
@@ -206,6 +206,46 @@ bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
return hfp_at_process_basic(hfp_at, data, user_data);
}
+static void hfp_at_next_field(struct hfp_at *hfp_at, const char *data)
+{
+ if (data[hfp_at->offset] == ',')
+ hfp_at->offset++;
+}
+
+static void hfp_at_skip_whitespace(struct hfp_at *hfp_at, const char *data)
+{
+ while (data[hfp_at->offset] == ' ')
+ hfp_at->offset++;
+}
+
+bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val)
+{
+ int temp = 0;
+ int i;
+
+ hfp_at_skip_whitespace(hfp_at, data);
+
+ i = hfp_at->offset;
+
+ while (data[i] >= '0' && data[i] <= '9') {
+ temp *= 10;
+ temp += data[i++] - '0';
+ }
+
+ if (i == hfp_at->offset)
+ return false;
+
+ if (val)
+ *val = temp;
+
+ hfp_at->offset = i;
+
+ hfp_at_skip_whitespace(hfp_at, data);
+ hfp_at_next_field(hfp_at, data);
+
+ return true;
+}
+
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers)
{
struct hfp_at *hfp_at;
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
index 0b628b5..2e2a757 100644
--- a/src/shared/hfp_at.h
+++ b/src/shared/hfp_at.h
@@ -42,5 +42,7 @@ struct hfp_at_handler {
bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
void *user_data);
+bool hfp_at_get_number(struct hfp_at *hfp_at, const char *data, int *val);
+
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 4/9] unit/test_hfp_at: Add test cases for processing basic commands
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will test processing basic commands including S-parameter commands,
D-commands.
---
unit/test-hfp-at.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 252 insertions(+)
diff --git a/unit/test-hfp-at.c b/unit/test-hfp-at.c
index 4374a70..9cb716d 100644
--- a/unit/test-hfp-at.c
+++ b/unit/test-hfp-at.c
@@ -33,6 +33,9 @@
struct test_data {
const struct hfp_at_handler *handlers;
+ const char *process_data;
+ bool process_return_val;
+ enum hfp_cmd_type returned_type;
};
static void test_init(gconstpointer data)
@@ -46,9 +49,27 @@ static void test_init(gconstpointer data)
hfp_at_free(hfp_at);
}
+static void test_process_data(gconstpointer data)
+{
+ struct hfp_at *hfp_at;
+ const struct test_data *test_data = data;
+ bool ret;
+
+ hfp_at = hfp_at_new(test_data->handlers);
+ g_assert(hfp_at != NULL);
+
+ ret = hfp_at_process_data(hfp_at, test_data->process_data,
+ (void *)test_data);
+ g_assert(ret == test_data->process_return_val);
+
+ hfp_at_free(hfp_at);
+}
+
static void process_generic(struct hfp_at *hfp_at, enum hfp_cmd_type type,
const char *at, void *user_data)
{
+ struct test_data *test_data = user_data;
+ g_assert(type == test_data->returned_type);
}
const struct hfp_at_handler handlers_1[] = {};
@@ -62,8 +83,63 @@ const struct hfp_at_handler handlers_2[] = {
const struct hfp_at_handler handlers_3[] = {
{
+ .prefix = NULL,
+ .cb = process_generic
+ },
+ {
.prefix = "+BRSF",
.cb = process_generic
+ }
+};
+
+const struct hfp_at_handler handlers_4[] = {
+ {
+ .prefix = "S12",
+ .cb = process_generic
+ },
+ {
+ .prefix = NULL,
+ .cb = process_generic
+ }
+};
+
+const struct hfp_at_handler handlers_5[] = {
+ {
+ .prefix = "S12",
+ .cb = process_generic
+ },
+ {
+ .prefix = NULL,
+ .cb = process_generic
+ }
+};
+
+const struct hfp_at_handler handlers_6[] = {
+ {
+ .prefix = "D",
+ .cb = process_generic
+ },
+ {
+ .prefix = NULL,
+ .cb = process_generic
+ }
+};
+
+const struct hfp_at_handler handlers_7[] = {
+ {
+ .prefix = "&A",
+ .cb = process_generic
+ },
+ {
+ .prefix = NULL,
+ .cb = process_generic
+ }
+};
+
+const struct hfp_at_handler handlers_8[] = {
+ {
+ .prefix = "A",
+ .cb = process_generic
},
{
.prefix = NULL,
@@ -83,6 +159,136 @@ const struct test_data data_3 = {
.handlers = handlers_3,
};
+const struct test_data prefix_S_1_data = {
+ .handlers = handlers_4,
+ .process_data = "ATS12=12,6",
+ .process_return_val = true,
+ .returned_type = HFP_AT_SET
+};
+
+const struct test_data prefix_S_2_data = {
+ .handlers = handlers_4,
+ .process_data = "ATS12=?12,6",
+ .process_return_val = true,
+ .returned_type = HFP_AT_TEST
+};
+
+const struct test_data prefix_S_3_data = {
+ .handlers = handlers_4,
+ .process_data = "ATS12?",
+ .process_return_val = true,
+ .returned_type = HFP_AT_READ
+};
+
+const struct test_data prefix_S_4_data = {
+ .handlers = handlers_4,
+ .process_data = "ATS12",
+ .process_return_val = true,
+ .returned_type = HFP_AT_COMMAND
+};
+
+const struct test_data prefix_S_5_data = {
+ .handlers = handlers_5,
+ .process_data = "ATS1",
+ .process_return_val = true,
+ .returned_type = HFP_AT_UNKNOWN
+};
+
+const struct test_data prefix_D_1_data = {
+ .handlers = handlers_5,
+ .process_data = "ATD0046131415",
+ .process_return_val = true,
+ .returned_type = HFP_AT_UNKNOWN
+};
+
+const struct test_data prefix_D_2_data = {
+ .handlers = handlers_6,
+ .process_data = "ATD0046131415",
+ .process_return_val = true,
+ .returned_type = HFP_AT_SET
+};
+
+const struct test_data prefix_D_3_data = {
+ .handlers = handlers_2,
+ .process_data = "ATD0046131415",
+ .process_return_val = true,
+ .returned_type = HFP_AT_UNKNOWN
+};
+
+const struct test_data prefix_anda_1_data = {
+ .handlers = handlers_7,
+ .process_data = "AT&A=12",
+ .process_return_val = true,
+ .returned_type = HFP_AT_SET
+};
+
+const struct test_data prefix_anda_2_data = {
+ .handlers = handlers_7,
+ .process_data = "AT&A=?12",
+ .process_return_val = true,
+ .returned_type = HFP_AT_TEST
+};
+
+const struct test_data prefix_anda_3_data = {
+ .handlers = handlers_7,
+ .process_data = "AT&A?12",
+ .process_return_val = true,
+ .returned_type = HFP_AT_READ
+};
+
+const struct test_data prefix_anda_4_data = {
+ .handlers = handlers_7,
+ .process_data = "AT&A",
+ .process_return_val = true,
+ .returned_type = HFP_AT_COMMAND
+};
+
+const struct test_data prefix_a_1_data = {
+ .handlers = handlers_8,
+ .process_data = "ATA",
+ .process_return_val = true,
+ .returned_type = HFP_AT_COMMAND
+};
+
+const struct test_data prefix_a_2_data = {
+ .handlers = handlers_8,
+ .process_data = "ATA=12",
+ .process_return_val = true,
+ .returned_type = HFP_AT_SET
+};
+
+const struct test_data prefix_a_3_data = {
+ .handlers = handlers_8,
+ .process_data = "ATA=?12",
+ .process_return_val = true,
+ .returned_type = HFP_AT_TEST
+};
+
+const struct test_data prefix_a_4_data = {
+ .handlers = handlers_8,
+ .process_data = "ATA?",
+ .process_return_val = true,
+ .returned_type = HFP_AT_READ
+};
+
+const struct test_data invalid_command_1_data = {
+ .handlers = handlers_2,
+ .process_data = "AYA?",
+ .process_return_val = false,
+};
+
+const struct test_data invalid_command_2_data = {
+ .handlers = handlers_2,
+ .process_data = "AT?",
+ .process_return_val = false,
+};
+
+const struct test_data invalid_command_3_data = {
+ .handlers = handlers_2,
+ .process_data = "AT",
+ .process_return_val = false,
+};
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -90,6 +296,52 @@ int main(int argc, char *argv[])
g_test_add_data_func("/hfp_at/init_1", &data_1, test_init);
g_test_add_data_func("/hfp_at/init_2", &data_2, test_init);
g_test_add_data_func("/hfp_at/init_3", &data_3, test_init);
+ /* Basic commands tests */
+ g_test_add_data_func("/hfp_at/prefix_S_1", &prefix_S_1_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_S_2", &prefix_S_2_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_S_3", &prefix_S_3_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_S_4", &prefix_S_4_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_S_5", &prefix_S_5_data,
+ test_process_data);
+
+ g_test_add_data_func("/hfp_at/prefix_D_1", &prefix_D_1_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_D_2", &prefix_D_2_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_D_3", &prefix_D_3_data,
+ test_process_data);
+
+ g_test_add_data_func("/hfp_at/prefix_&A_1", &prefix_anda_1_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_&A_2", &prefix_anda_2_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_&A_3", &prefix_anda_3_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_&A_4", &prefix_anda_4_data,
+ test_process_data);
+
+ g_test_add_data_func("/hfp_at/prefix_A_1", &prefix_a_1_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_A_1", &prefix_a_2_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_A_1", &prefix_a_3_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/prefix_A_1", &prefix_a_4_data,
+ test_process_data);
+
+ g_test_add_data_func("/hfp_at/invalid_command_1",
+ &invalid_command_1_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/invalid_command_2",
+ &invalid_command_2_data,
+ test_process_data);
+ g_test_add_data_func("/hfp_at/invalid_command_3",
+ &invalid_command_3_data,
+ test_process_data);
return g_test_run();
}
--
1.8.5.3
^ permalink raw reply related
* [PATCH 3/9] shared/hfp_at: Add skeleton of hfp_at_process_data
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will handle AT frames and recognize their commands. It will also
call proper callback. If no callback was found, default handler
will be called.
---
src/shared/hfp_at.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/shared/hfp_at.h | 3 +
2 files changed, 178 insertions(+)
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
index bd1899b..eff0a38 100644
--- a/src/shared/hfp_at.c
+++ b/src/shared/hfp_at.c
@@ -29,8 +29,183 @@
struct hfp_at {
const struct hfp_at_handler *cmd_handlers;
+ int offset;
};
+/* Last cmd handler should have prefix NULL and will be returned if no other
+ * will be found
+ */
+static const struct hfp_at_handler *hfp_at_find_cb(struct hfp_at *hfp_at,
+ char *pref, uint8_t len)
+{
+ const struct hfp_at_handler *handler = hfp_at->cmd_handlers;
+
+ while (handler->prefix) {
+ if (strlen(handler->prefix) == len)
+ if (!memcmp(handler->prefix, pref, len))
+ break;
+
+ handler++;
+ }
+
+ return handler;
+}
+
+static void hfp_at_call_handler(struct hfp_at *hfp_at, char *prefix, int len,
+ const char *data, void *user_data,
+ enum hfp_cmd_type type)
+{
+ const struct hfp_at_handler *handler;
+
+ handler = hfp_at_find_cb(hfp_at, prefix, len);
+
+ if (handler->prefix) {
+ handler->cb(hfp_at, type, data, user_data);
+ return;
+ }
+
+ /* We set offset to 0 because it is unknown command */
+ hfp_at->offset = 0;
+ handler->cb(hfp_at, HFP_AT_UNKNOWN, data, user_data);
+}
+
+static bool hfp_at_process_basic(struct hfp_at *hfp_at, const char *data,
+ void *user_data)
+{
+ const char *prefix = data + hfp_at->offset;
+ enum hfp_cmd_type type;
+ char lookup_prefix[4];
+ uint8_t pref_len = 0;
+ bool equal = false;
+ int i;
+
+ /* Check if first sign is character */
+ if (isalpha(prefix[pref_len])) {
+ /* Handle S-parameter prefix */
+ if (toupper(prefix[pref_len]) == 'S') {
+ do {
+ pref_len++;
+ } while (isdigit(prefix[pref_len]));
+ /*S-parameter must be followed with number*/
+ if (pref_len == 1)
+ pref_len--;
+ } else {
+ /* It's just one-character prefix */
+ pref_len++;
+ }
+ } else if (prefix[pref_len] == '&' && isalpha(prefix[pref_len + 1])) {
+ /* Two-signed prefix starting with & */
+ pref_len = 2;
+ }
+
+ if (pref_len == 0 || pref_len > sizeof(lookup_prefix))
+ return false;
+
+ for (i = 0; i < pref_len; i++)
+ lookup_prefix[i] = toupper(prefix[i]);
+
+ hfp_at->offset += pref_len;
+
+ if (lookup_prefix[0] == 'D') {
+ type = HFP_AT_SET;
+
+ goto done;
+ }
+
+ if (data[hfp_at->offset] == '=') {
+ hfp_at->offset++;
+ equal = true;
+ }
+
+ if (data[hfp_at->offset] == '?') {
+ hfp_at->offset++;
+
+ if (equal)
+ type = HFP_AT_TEST;
+ else
+ type = HFP_AT_READ;
+ } else if (equal) {
+ type = HFP_AT_SET;
+ } else {
+ type = HFP_AT_COMMAND;
+ }
+
+done:
+ hfp_at_call_handler(hfp_at, lookup_prefix, pref_len, data, user_data,
+ type);
+
+ return true;
+}
+
+static bool hfp_at_process_extended(struct hfp_at *hfp_at, const char *data,
+ void *user_data)
+{
+ const char *prefix = data + hfp_at->offset;
+ const char *separators = ";?=";
+ enum hfp_cmd_type type;
+ char lookup_prefix[18];
+ bool equal = false;
+ uint8_t pref_len;
+ int i;
+
+ /* Lookup for first separator */
+ pref_len = strcspn(prefix, separators);
+
+ if (pref_len > 17 || pref_len < 2)
+ return false;
+
+ for (i = 0; i < pref_len; i++)
+ lookup_prefix[i] = toupper(prefix[i]);
+
+ hfp_at->offset += pref_len;
+
+ if (data[hfp_at->offset] == '=') {
+ hfp_at->offset++;
+ equal = true;
+ }
+
+ if (data[hfp_at->offset] == '?') {
+ hfp_at->offset++;
+
+ if (equal)
+ type = HFP_AT_TEST;
+ else
+ type = HFP_AT_READ;
+ } else if (equal) {
+ type = HFP_AT_SET;
+ } else {
+ type = HFP_AT_COMMAND;
+ }
+
+ hfp_at_call_handler(hfp_at, lookup_prefix, pref_len, data, user_data,
+ type);
+
+ return true;
+}
+
+static bool hfp_at_is_extended_cmd(struct hfp_at *hfp_at, const char *data)
+{
+ /* Extended commands names always begin with character "+" V250 5.4.1*/
+ return data[hfp_at->offset] == '+';
+}
+
+bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
+ void *user_data)
+{
+ if (strlen(data) < 3)
+ return false;
+
+ if (strncmp(data, "AT", 2))
+ return false;
+
+ hfp_at->offset = 2;
+
+ if (hfp_at_is_extended_cmd(hfp_at, data))
+ return hfp_at_process_extended(hfp_at, data, user_data);
+ else
+ return hfp_at_process_basic(hfp_at, data, user_data);
+}
+
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers)
{
struct hfp_at *hfp_at;
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
index fe074f2..0b628b5 100644
--- a/src/shared/hfp_at.h
+++ b/src/shared/hfp_at.h
@@ -39,5 +39,8 @@ struct hfp_at_handler {
hfp_at_cmd_cb cb;
};
+bool hfp_at_process_data(struct hfp_at *hfp_at, const char *data,
+ void *user_data);
+
struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 2/9] unit: Add hfp_at tester
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will test hfp_at parser. Initial versione performs three test cases
with hfp_at_new() calls.
---
.gitignore | 1 +
Makefile.am | 8 ++++-
unit/test-hfp-at.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 103 insertions(+), 1 deletion(-)
create mode 100644 unit/test-hfp-at.c
diff --git a/.gitignore b/.gitignore
index 94c0c78..fa34348 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,6 +84,7 @@ unit/test-gdbus-client
unit/test-sdp
unit/test-lib
unit/test-mgmt
+unit/test-hfp-at
tools/mgmt-tester
tools/smp-tester
tools/gap-tester
diff --git a/Makefile.am b/Makefile.am
index 0c79e58..c886ba8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -225,7 +225,8 @@ AM_CFLAGS += @DBUS_CFLAGS@ @GLIB_CFLAGS@
AM_CPPFLAGS = -I$(builddir)/lib -I$(srcdir)/gdbus
-unit_tests += unit/test-eir unit/test-uuid unit/test-textfile unit/test-crc
+unit_tests += unit/test-eir unit/test-uuid unit/test-textfile unit/test-crc \
+ unit/test-hfp-at
unit_test_eir_SOURCES = unit/test-eir.c src/eir.c src/uuid-helper.c
unit_test_eir_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
@@ -239,6 +240,11 @@ unit_test_textfile_LDADD = @GLIB_LIBS@
unit_test_crc_SOURCES = unit/test-crc.c monitor/crc.h monitor/crc.c
unit_test_crc_LDADD = @GLIB_LIBS@
+unit_test_hfp_at_SOURCES = unit/test-hfp-at.c \
+ src/shared/util.h src/shared/util.c \
+ src/shared/hfp_at.h src/shared/hfp_at.c
+unit_test_hfp_at_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
unit_tests += unit/test-ringbuf unit/test-queue
unit_test_ringbuf_SOURCES = unit/test-ringbuf.c \
diff --git a/unit/test-hfp-at.c b/unit/test-hfp-at.c
new file mode 100644
index 0000000..4374a70
--- /dev/null
+++ b/unit/test-hfp-at.c
@@ -0,0 +1,95 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ *
+ * 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 <stdio.h>
+#include <glib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "src/shared/hfp_at.h"
+
+struct test_data {
+ const struct hfp_at_handler *handlers;
+};
+
+static void test_init(gconstpointer data)
+{
+ struct hfp_at *hfp_at;
+ const struct test_data *test_data = data;
+
+ hfp_at = hfp_at_new(test_data->handlers);
+ g_assert(hfp_at != NULL);
+
+ hfp_at_free(hfp_at);
+}
+
+static void process_generic(struct hfp_at *hfp_at, enum hfp_cmd_type type,
+ const char *at, void *user_data)
+{
+}
+
+const struct hfp_at_handler handlers_1[] = {};
+
+const struct hfp_at_handler handlers_2[] = {
+ {
+ .prefix = NULL,
+ .cb = process_generic
+ }
+};
+
+const struct hfp_at_handler handlers_3[] = {
+ {
+ .prefix = "+BRSF",
+ .cb = process_generic
+ },
+ {
+ .prefix = NULL,
+ .cb = process_generic
+ }
+};
+
+const struct test_data data_1 = {
+ .handlers = handlers_1,
+};
+
+const struct test_data data_2 = {
+ .handlers = handlers_2,
+};
+
+const struct test_data data_3 = {
+ .handlers = handlers_3,
+};
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+ /* Tests for hfp_at_new() */
+ g_test_add_data_func("/hfp_at/init_1", &data_1, test_init);
+ g_test_add_data_func("/hfp_at/init_2", &data_2, test_init);
+ g_test_add_data_func("/hfp_at/init_3", &data_3, test_init);
+
+ return g_test_run();
+}
--
1.8.5.3
^ permalink raw reply related
* [PATCH 1/9] shared: Add skeleton of hfp_at parser
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393320227-10931-1-git-send-email-marcin.kraglak@tieto.com>
It will parse AT frames in HFP profile implementation. Use can register
handlers for specified prefixes. Callbacks will be called with one of
hfp_cmd_type. Default handler will have prefix NULL, and type passed
to callback will be always HFP_AT_UNKNOWN.
---
src/shared/hfp_at.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/shared/hfp_at.h | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+)
create mode 100644 src/shared/hfp_at.c
create mode 100644 src/shared/hfp_at.h
diff --git a/src/shared/hfp_at.c b/src/shared/hfp_at.c
new file mode 100644
index 0000000..bd1899b
--- /dev/null
+++ b/src/shared/hfp_at.c
@@ -0,0 +1,50 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "src/shared/util.h"
+#include "src/shared/hfp_at.h"
+
+struct hfp_at {
+ const struct hfp_at_handler *cmd_handlers;
+};
+
+struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers)
+{
+ struct hfp_at *hfp_at;
+
+ hfp_at = new0(struct hfp_at, 1);
+ if (!hfp_at)
+ return NULL;
+
+ hfp_at->cmd_handlers = handlers;
+
+ return hfp_at;
+}
+
+void hfp_at_free(struct hfp_at *hfp_at)
+{
+ free(hfp_at);
+}
diff --git a/src/shared/hfp_at.h b/src/shared/hfp_at.h
new file mode 100644
index 0000000..fe074f2
--- /dev/null
+++ b/src/shared/hfp_at.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+struct hfp_at;
+
+enum hfp_cmd_type {
+ HFP_AT_READ,
+ HFP_AT_SET,
+ HFP_AT_TEST,
+ HFP_AT_COMMAND,
+ HFP_AT_UNKNOWN
+};
+
+typedef void (*hfp_at_cmd_cb)(struct hfp_at *hfp_at, enum hfp_cmd_type type,
+ const char *at, void *user_data);
+
+struct hfp_at_handler {
+ const char *prefix;
+ hfp_at_cmd_cb cb;
+};
+
+struct hfp_at *hfp_at_new(const struct hfp_at_handler *handlers);
+void hfp_at_free(struct hfp_at *hfp_at);
--
1.8.5.3
^ permalink raw reply related
* [PATCH 0/9] HFP AT parser skeleton
From: Marcin Kraglak @ 2014-02-25 9:23 UTC (permalink / raw)
To: linux-bluetooth
Hi,
This set contains skeleton of hfp_at parser and some basic unit tests.
Unit tests check proper commands handling for now. If API will be acceptable
more test cases for fetching values will be added.
Comments are welcome
Marcin Kraglak (9):
shared: Add skeleton of hfp_at parser
unit: Add hfp_at tester
shared/hfp_at: Add skeleton of hfp_at_process_data
unit/test_hfp_at: Add test cases for processing basic commands
shared/hfp_at: Add function for getting number
shared/hfp_at: Add function to open container
shared/hfp_at: Add function to close container
shared/hfp_at: Add function to get string
shared/hfp_at: Add function to get unquoted string
.gitignore | 1 +
Makefile.am | 8 +-
src/shared/hfp_at.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/shared/hfp_at.h | 54 ++++++++
unit/test-hfp-at.c | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 759 insertions(+), 1 deletion(-)
create mode 100644 src/shared/hfp_at.c
create mode 100644 src/shared/hfp_at.h
create mode 100644 unit/test-hfp-at.c
--
1.8.5.3
^ permalink raw reply
* Re: [PATCH BlueZ v7 07/11] gatt: Add external services tracking
From: Johan Hedberg @ 2014-02-25 6:26 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: Claudio Takahasi, BlueZ development, Alvaro Silva
In-Reply-To: <CAJdJm_MhdZwHYuwNCJCvnfRN6DpivKLJi_hiV7icV69gFCne6Q@mail.gmail.com>
Hi Lizardo,
On Mon, Feb 24, 2014, Anderson Lizardo wrote:
> On Mon, Feb 24, 2014 at 8:49 AM, Anderson Lizardo
> <anderson.lizardo@openbossa.org> wrote:
> > Hi Johan,
> >
> > On Mon, Feb 24, 2014 at 4:33 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> >> This whole timer thing seems too hackish to me.
> >>
> >> A better way to fix this might be to have something like
> >> g_dbus_client_set_proxies_complete_watch (or some better name) to let
> >> the code wait until GetManagedObjects has returned and the initial
> >> proxies added. Do you agree?
> >
> > We came up with this workaround during development, but we forgot to
> > highlight on the cover letter. Indeed a function like the one you
> > propose should be enough.
> >
> > Regarding the name for the function, I was thinking as
> > "g_dbus_client_proxies_ready_watch()". What do you think?
>
> Or "g_dbus_client_set_proxies_ready_watch()" to be consistent.
That sounds good enough to me.
Johan
^ permalink raw reply
* Re: [RFC v11 01/15] Bluetooth: Create hci_req_add_le_scan_disable helper
From: Johan Hedberg @ 2014-02-25 5:57 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393281061-14320-2-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
On Mon, Feb 24, 2014, Andre Guedes wrote:
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1128,6 +1128,7 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
> void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
> const void *param, u8 event);
> void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
> +void hci_req_add_le_scan_disable(struct hci_request *req);
It doesn't feel right to put this straight next to the generic async
request API. I'd at least have an empty line between the generic API and
this new function.
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -3318,7 +3318,6 @@ static void le_scan_disable_work(struct work_struct *work)
> {
> struct hci_dev *hdev = container_of(work, struct hci_dev,
> le_scan_disable.work);
> - struct hci_cp_le_set_scan_enable cp;
> struct hci_request req;
> int err;
>
> @@ -3326,9 +3325,7 @@ static void le_scan_disable_work(struct work_struct *work)
>
> hci_req_init(&req, hdev);
>
> - memset(&cp, 0, sizeof(cp));
> - cp.enable = LE_SCAN_DISABLE;
> - hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> + hci_req_add_le_scan_disable(&req);
>
> err = hci_req_run(&req, le_scan_disable_work_complete);
> if (err)
> @@ -4872,3 +4869,12 @@ static void hci_cmd_work(struct work_struct *work)
> }
> }
> }
> +
> +void hci_req_add_le_scan_disable(struct hci_request *req)
> +{
> + struct hci_cp_le_set_scan_enable cp;
> +
> + memset(&cp, 0, sizeof(cp));
> + cp.enable = LE_SCAN_DISABLE;
> + hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> +}
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 25b8b27..c722914 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -3526,7 +3526,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
> struct hci_cp_remote_name_req_cancel cp;
> struct inquiry_entry *e;
> struct hci_request req;
> - struct hci_cp_le_set_scan_enable enable_cp;
> int err;
>
> BT_DBG("%s", hdev->name);
> @@ -3562,10 +3561,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
> } else {
> cancel_delayed_work(&hdev->le_scan_disable);
>
> - memset(&enable_cp, 0, sizeof(enable_cp));
> - enable_cp.enable = LE_SCAN_DISABLE;
> - hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
> - sizeof(enable_cp), &enable_cp);
> + hci_req_add_le_scan_disable(&req);
> }
>
> break;
You've missed one place in clean_up_hci_state() in mgmt.c (which was
added by the recent "graceful power down" patch set.
Johan
^ permalink raw reply
* Re: [RFC v11 06/15] Bluetooth: Introduce LE auto connection infrastructure
From: Johan Hedberg @ 2014-02-25 4:23 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393281061-14320-7-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
On Mon, Feb 24, 2014, Andre Guedes wrote:
> + if (hci_update_random_address(&req, false, &own_addr_type))
> + return;
Don't we want require_privacy = true here?
> + if (addr_type == ADDR_LE_DEV_PUBLIC)
> + bdaddr_type = BDADDR_LE_PUBLIC;
> + else
> + bdaddr_type = BDADDR_LE_RANDOM;
> +
> + conn = hci_connect(hdev, LE_LINK, addr, bdaddr_type, BT_SECURITY_LOW,
> + HCI_AT_NO_BONDING);
All hci_connect is is a very short wrapper to hci_connect_acl/le. The
hci_connect_le function in turn does the following:
/* Convert from L2CAP channel address type to HCI address type */
if (dst_type == BDADDR_LE_PUBLIC)
dst_type = ADDR_LE_DEV_PUBLIC;
else
dst_type = ADDR_LE_DEV_RANDOM;
So it seems a bit silly to do this kind of back and forth conversions.
Instead, I think the hci_connect API should take the address type that's
used for struct hci_conn, i.e. the HCI one (not the L2CAP/mgmt one).
Also, since pretty much all places that are calling hci_connect pass an
explicit value as the link type I think the most sensible thing to do
would be to completely remove this function and export hci_connect_le &
hci_connect_acl from hci_conn.c.
Johan
^ permalink raw reply
* [PATCH] tools/btmgmt: Add command to set scan parameters
From: Andre Guedes @ 2014-02-24 22:32 UTC (permalink / raw)
To: linux-bluetooth
---
tools/btmgmt.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 9a5e971..dd90f34 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -2073,6 +2073,47 @@ static void cmd_debug_keys(struct mgmt *mgmt, uint16_t index,
cmd_setting(mgmt, index, MGMT_OP_SET_DEBUG_KEYS, argc, argv);
}
+static void set_scan_params_usage(void)
+{
+ printf("Usage: btmgmt set-scan-params <window> <interval>");
+}
+
+static void set_scan_params_rsp(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ if (status != 0)
+ fprintf(stderr, "Set scan parameters failed "
+ "with status 0x%02x (%s)\n",
+ status, mgmt_errstr(status));
+ else
+ printf("Scan parameters successfully set\n");
+
+ mainloop_quit();
+}
+
+static void cmd_set_scan_params(struct mgmt *mgmt, uint16_t index, int argc,
+ char **argv)
+{
+ struct mgmt_cp_set_scan_params cp;
+
+ if (argc != 3) {
+ set_scan_params_usage();
+ exit(EXIT_FAILURE);
+ }
+
+ if (index == MGMT_INDEX_NONE)
+ index = 0;
+
+ cp.window = strtol(argv[1], NULL, 16);
+ cp.interval = strtol(argv[2], NULL, 16);
+
+ if (mgmt_send(mgmt, MGMT_OP_SET_SCAN_PARAMS, index, sizeof(cp), &cp,
+ set_scan_params_rsp, NULL, NULL) == 0) {
+ fprintf(stderr, "Unable to send set_scan_params cmd\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
static struct {
char *cmd;
void (*func)(struct mgmt *mgmt, uint16_t index, int argc, char **argv);
@@ -2115,6 +2156,7 @@ static struct {
{ "did", cmd_did, "Set Device ID" },
{ "static-addr",cmd_static_addr,"Set static address" },
{ "debug-keys", cmd_debug_keys, "Toogle debug keys" },
+ { "set-scan-params", cmd_set_scan_params, "Set scan parameters" },
{ }
};
--
1.8.5.4
^ permalink raw reply related
* [RFC v11 15/15] Bluetooth: Update background scan parameters
From: Andre Guedes @ 2014-02-24 22:31 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393281061-14320-1-git-send-email-andre.guedes@openbossa.org>
If new scanning parameters are set while background scan is running,
we should restart background scanning so these parameters are updated.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 26 ++++++++++++++++++++++++++
net/bluetooth/mgmt.c | 7 +++++++
3 files changed, 34 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c81847e..2c5289d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -812,6 +812,7 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conns_clear(struct hci_dev *hdev);
void hci_update_background_scan(struct hci_dev *hdev);
+void hci_restart_background_scan(struct hci_dev *hdev);
void hci_uuids_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e0ebbd9..55c01e9 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -5179,3 +5179,29 @@ void hci_update_background_scan(struct hci_dev *hdev)
if (err)
BT_ERR("Failed to run HCI request: err %d", err);
}
+
+static void restart_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+ if (status)
+ BT_DBG("HCI request failed to restart background scan: "
+ "status 0x%2.2x", status);
+}
+
+void hci_restart_background_scan(struct hci_dev *hdev)
+{
+ struct hci_request req;
+ int err;
+
+ hci_req_init(&req, hdev);
+
+ hci_req_add_le_scan_disable(&req);
+ hci_req_add_le_passive_scan(&req, hdev);
+
+ err = hci_req_run(&req, restart_background_scan_complete);
+ if (err) {
+ BT_ERR("Failed to run HCI request: err %d", err);
+ return;
+ }
+
+ BT_DBG("%s re-starting background scanning", hdev->name);
+}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4745fb5..679670d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3917,6 +3917,13 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
+ /* If background scan is running, restart it so new parameters are
+ * loaded.
+ */
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
+ hdev->discovery.state == DISCOVERY_STOPPED)
+ hci_restart_background_scan(hdev);
+
hci_dev_unlock(hdev);
return err;
--
1.8.5.4
^ permalink raw reply related
* [RFC v11 14/15] Bluetooth: Create hci_req_add_le_passive_scan helper
From: Andre Guedes @ 2014-02-24 22:31 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393281061-14320-1-git-send-email-andre.guedes@openbossa.org>
This patches creates the hci_req_add_le_passive_scan helper so it can
be re-used in the next patch.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_core.c | 46 ++++++++++++++++++++++++++--------------------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5d51086..e0ebbd9 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -5095,6 +5095,31 @@ void hci_req_add_le_scan_disable(struct hci_request *req)
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
+static void hci_req_add_le_passive_scan(struct hci_request *req,
+ struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_param param_cp;
+ struct hci_cp_le_set_scan_enable enable_cp;
+ u8 own_addr_type;
+
+ if (hci_update_random_address(req, true, &own_addr_type))
+ return;
+
+ memset(¶m_cp, 0, sizeof(param_cp));
+ param_cp.type = LE_SCAN_PASSIVE;
+ param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
+ param_cp.window = cpu_to_le16(hdev->le_scan_window);
+ param_cp.own_address_type = own_addr_type;
+ hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+ ¶m_cp);
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_ENABLE;
+ enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+ hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ &enable_cp);
+}
+
static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
{
if (status)
@@ -5110,8 +5135,6 @@ static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
*/
void hci_update_background_scan(struct hci_dev *hdev)
{
- struct hci_cp_le_set_scan_param param_cp;
- struct hci_cp_le_set_scan_enable enable_cp;
struct hci_request req;
struct hci_conn *conn;
int err;
@@ -5131,8 +5154,6 @@ void hci_update_background_scan(struct hci_dev *hdev)
BT_DBG("%s stopping background scanning", hdev->name);
} else {
- u8 own_addr_type;
-
/* If there is at least one pending LE connection, we should
* keep the background scan running.
*/
@@ -5149,22 +5170,7 @@ void hci_update_background_scan(struct hci_dev *hdev)
if (conn)
return;
- if (hci_update_random_address(&req, false, &own_addr_type))
- return;
-
- memset(¶m_cp, 0, sizeof(param_cp));
- param_cp.type = LE_SCAN_PASSIVE;
- param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
- param_cp.window = cpu_to_le16(hdev->le_scan_window);
- param_cp.own_address_type = own_addr_type;
- hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
- ¶m_cp);
-
- memset(&enable_cp, 0, sizeof(enable_cp));
- enable_cp.enable = LE_SCAN_ENABLE;
- enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
- hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
- &enable_cp);
+ hci_req_add_le_passive_scan(&req, hdev);
BT_DBG("%s starting background scanning", hdev->name);
}
--
1.8.5.4
^ permalink raw reply related
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