From: Andrei Emeltchenko <[email protected]>
This is my set of patches rebased against very recent bluez.git
(most probably there might be some issues related to style used).
These patches add some missing capability to the process, add basic IPC server
and client. Daemon listens for incoming connections from HALs so it acts
as a server, while HALs connect and act as client. Please advise what
are better names for hal-msg and hal-msg-client, should some code be moved
to adapter.c?
Andrei Emeltchenko (6):
android: Add capabilities and set userid
android: Handle mgmt changed events
android: Implement basic HAL server
android: Add HAL message helpers
android: Add helper to send fd using SCM_RIGHTS
android: Add Android HAL callback task
Makefile.android | 2 +-
android/Android.mk | 9 ++
android/adapter.c | 129 ++++++++++++++++++++++
android/bt-sock.c | 64 +++++++++++
android/hal-cb-thread.c | 86 +++++++++++++++
android/hal-msg-client.c | 123 +++++++++++++++++++++
android/hal-msg-client.h | 25 +++++
android/hal-msg.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++
android/hal-msg.h | 5 +
android/main.c | 69 ++++++++++++
configure.ac | 4 +
11 files changed, 782 insertions(+), 1 deletion(-)
create mode 100644 android/bt-sock.c
create mode 100644 android/hal-cb-thread.c
create mode 100644 android/hal-msg-client.c
create mode 100644 android/hal-msg-client.h
create mode 100644 android/hal-msg.c
--
1.7.10.4
From: Andrei Emeltchenko <[email protected]>
Add basic HAL server on BlueZ daemon side. It will listen for messages
from Android HAL threads.
---
Makefile.android | 2 +-
android/Android.mk | 1 +
android/hal-msg.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++
android/hal-msg.h | 5 +
android/main.c | 11 +++
5 files changed, 285 insertions(+), 1 deletion(-)
create mode 100644 android/hal-msg.c
diff --git a/Makefile.android b/Makefile.android
index 8196583..96f3f22 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -3,7 +3,7 @@ noinst_PROGRAMS += android/bluetoothd
android_bluetoothd_SOURCES = android/main.c \
src/log.c \
- android/hal-msg.h \
+ android/hal-msg.h android/hal-msg.c \
src/sdpd-database.c src/sdpd-server.c \
src/sdpd-service.c src/sdpd-request.c \
src/shared/util.h src/shared/util.c \
diff --git a/android/Android.mk b/android/Android.mk
index 30b2169..d5dfde7 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -16,6 +16,7 @@ LOCAL_SRC_FILES := \
main.c \
log.c \
adapter.c \
+ hal-msg.c \
../src/shared/mgmt.c \
../src/shared/util.c \
../src/sdpd-database.c \
diff --git a/android/hal-msg.c b/android/hal-msg.c
new file mode 100644
index 0000000..aa02236
--- /dev/null
+++ b/android/hal-msg.c
@@ -0,0 +1,267 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+
+#include "log.h"
+#include "hal-msg.h"
+
+static guint watch_id = 0;
+
+static uint8_t hal_register_module(struct hal_msg_hdr *msg)
+{
+ DBG("");
+
+ return 0;
+}
+
+static uint8_t hal_unregister_module(struct hal_msg_hdr *msg)
+{
+ DBG("");
+
+ return 0;
+}
+
+static uint8_t process_hal_service_chan(struct hal_msg_hdr *msg)
+{
+ uint8_t status = -1;
+
+ DBG("");
+
+ switch (msg->opcode) {
+ case HAL_MSG_OP_REGISTER_MODULE:
+ status = hal_register_module(msg);
+ break;
+ case HAL_MSG_OP_UNREGISTER_MODULE:
+ status = hal_unregister_module(msg);
+ break;
+ default:
+ error("%s: unrecognized command on service channel", __func__);
+ break;
+ }
+
+ return status;
+}
+
+static uint8_t sanity_check(struct hal_msg_hdr *msg)
+{
+ /* TODO: Add sanity check here */
+
+ return 0;
+}
+
+static uint8_t process_hal_msg(uint8_t *buf, int len)
+{
+ struct hal_msg_hdr *msg = (struct hal_msg_hdr *) buf;
+ uint8_t status;
+
+ DBG("");
+
+ status = sanity_check(msg);
+ if (status != 0)
+ return status;
+
+ if (msg->service_id == 0)
+ status = process_hal_service_chan(msg);
+
+ return status;
+}
+
+static gboolean io_session_event(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct hal_msg_hdr *hdr;
+ uint8_t buf[MAX_HAL_BUF_SIZE];
+ int sock, len;
+ uint8_t status;
+
+ if (cond & G_IO_NVAL)
+ return FALSE;
+
+ sock = g_io_channel_unix_get_fd(chan);
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ error("%s: error condition %d", __func__, cond);
+ /* TODO: handle */
+ return FALSE;
+ }
+
+ len = recv(sock, buf, sizeof(buf), 0);
+ if (len <= 0) {
+ error("%s: recv(): %s", __func__, strerror(errno));
+ /* TODO: handle */
+ return FALSE;
+ }
+
+ if (len < (int) sizeof(struct hal_msg_hdr))
+ return FALSE;
+
+ status = process_hal_msg(buf, len);
+
+ hdr = (struct hal_msg_hdr *) buf;
+
+ if (status == 0) {
+ /* Success reply */
+ len = send(sock, hdr, sizeof(*hdr), 0);
+ if (len != sizeof(hdr)) {
+ error("%s: send() rsp: %s", __func__, strerror(errno));
+ /* TODO: handle */
+ return FALSE;
+ }
+ } else {
+ struct hal_msg_rsp {
+ struct hal_msg_hdr hdr;
+ uint8_t status;
+ } rsp;
+
+ rsp.hdr.service_id = hdr->service_id;
+ rsp.hdr.opcode = HAL_MSG_OP_ERROR;
+ rsp.hdr.len = sizeof(rsp.status);
+ rsp.status = status;
+
+ len = send(sock, &rsp, sizeof(rsp), 0);
+ if (len != sizeof(rsp)) {
+ error("%s: send() rsp: %s", __func__, strerror(errno));
+ /* TODO: handle */
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean io_accept_event(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ GIOChannel *io;
+ int sock, nsk;
+ struct sockaddr_un addr;
+ socklen_t len = sizeof(addr);
+
+ DBG("");
+
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
+ return FALSE;
+
+ sock = g_io_channel_unix_get_fd(chan);
+
+ nsk = accept(sock, (struct sockaddr *) &addr, &len);
+ if (nsk < 0) {
+ error("%s: accept(): %s", __func__, strerror(errno));
+ return TRUE;
+ }
+
+ io = g_io_channel_unix_new(nsk);
+ g_io_channel_set_close_on_unref(io, TRUE);
+
+ g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ io_session_event, data);
+
+ g_io_channel_unref(io);
+
+ return TRUE;
+}
+
+static int init_hal_socket(const char *sock_path)
+{
+ struct sockaddr_un addr;
+ int sock;
+ size_t len;
+
+ DBG("");
+
+ sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ if (sock < 0) {
+ error("%s: socket(): %s", __func__, strerror(errno));
+ return sock;
+ }
+
+ len = strlen(sock_path);
+ if (len > sizeof(addr.sun_path) - 1) {
+ error("%s: too big socket name", __func__);
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, sock_path);
+
+ /* let fail for android */
+ if (unlink(addr.sun_path) < 0)
+ warn("%s: unlink() %s failed: %s", __func__, sock_path,
+ strerror(errno));
+
+ if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ error("%s: bind(): %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ if (listen(sock, 5) < 0) {
+ error("%s: listen(): %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ chmod(sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+ return sock;
+}
+
+void start_hal_srv(const char *sock_path)
+{
+ GIOChannel *io;
+ int sock;
+
+ DBG("");
+
+ sock = init_hal_socket(sock_path);
+ if (sock < 0)
+ return;
+
+ io = g_io_channel_unix_new(sock);
+ g_io_channel_set_close_on_unref(io, TRUE);
+
+ watch_id = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ io_accept_event, &sock);
+}
+
+void stop_hal_srv(void)
+{
+ DBG("");
+
+ if (watch_id > 0)
+ g_source_remove(watch_id);
+
+ watch_id = 0;
+}
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 4440fc8..f27662a 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -23,6 +23,9 @@
static const char BLUEZ_HAL_SK_PATH[] = "\0bluez_hal_socket";
+void start_hal_srv(const char *sock_path);
+void stop_hal_srv(void);
+
struct hal_msg_hdr {
uint8_t service_id;
uint8_t opcode;
@@ -40,6 +43,8 @@ struct hal_msg_hdr {
#define HAL_SERVICE_ID_AVRCP 8
#define HAL_SERVICE_ID_GATT 9
+#define MAX_HAL_BUF_SIZE 1024
+
/* Core Service */
#define HAL_MSG_OP_ERROR 0x00
diff --git a/android/main.c b/android/main.c
index 4a716be..99db09b 100644
--- a/android/main.c
+++ b/android/main.c
@@ -56,6 +56,14 @@
#include "adapter.h"
#include "hal-msg.h"
+#if defined(ANDROID)
+#define BT_HAL_SOCKET "/tmp/bt_hal"
+#else
+#define BT_HAL_SOCKET "/var/run/bt_hal"
+#endif
+
+#define SHUTDOWN_GRACE_SECONDS 10
+
static GMainLoop *event_loop;
static struct mgmt *mgmt_if = NULL;
@@ -505,6 +513,7 @@ int main(int argc, char *argv[])
/* Use params: mtu = 0, flags = 0 */
start_sdp_server(0, 0);
+ start_hal_srv(BT_HAL_SOCKET);
DBG("Entering main loop");
@@ -513,6 +522,8 @@ int main(int argc, char *argv[])
g_source_remove(signal);
cleanup_hal_connection();
+
+ stop_hal_srv();
stop_sdp_server();
cleanup_mgmt_interface();
g_main_loop_unref(event_loop);
--
1.7.10.4
From: Andrei Emeltchenko <[email protected]>
Add code handling changing adapter settings.
---
android/adapter.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 129 insertions(+)
diff --git a/android/adapter.c b/android/adapter.c
index 4009f4d..cae3187 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -69,6 +69,134 @@ failed:
adapter->ready(NULL, err);
}
+static void mgmt_local_name_changed_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct bt_adapter *adapter = user_data;
+ const struct mgmt_cp_set_local_name *rp = param;
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size of local name changed parameters");
+ return;
+ }
+
+ if (!g_strcmp0(adapter->name, (const char *) rp->name))
+ return;
+
+ DBG("name: %s", rp->name);
+
+ g_free(adapter->name);
+ adapter->name = g_strdup((const char *) rp->name);
+
+ /* TODO Update services if needed */
+}
+
+static void settings_changed_connectable(struct bt_adapter *adapter)
+{
+ /* TODO */
+}
+
+static void settings_changed_discoverable(struct bt_adapter *adapter)
+{
+ /* TODO */
+}
+
+static void settings_changed(struct bt_adapter *adapter, uint32_t settings)
+{
+ uint32_t changed_mask;
+
+ changed_mask = adapter->current_settings ^ settings;
+
+ adapter->current_settings = settings;
+
+ DBG("0x%08x", changed_mask);
+
+ if (changed_mask & MGMT_SETTING_POWERED) {
+ info("Powered");
+
+ /*
+ if (adapter->current_settings & MGMT_SETTING_POWERED)
+ start_adapter()
+ else
+ stop_adapter()
+ */
+ }
+
+ if (changed_mask & MGMT_SETTING_CONNECTABLE) {
+ DBG("Connectable");
+
+ settings_changed_connectable(adapter);
+ }
+
+ if (changed_mask & MGMT_SETTING_DISCOVERABLE) {
+ DBG("Discoverable");
+
+ settings_changed_discoverable(adapter);
+ }
+}
+
+static void new_settings_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct bt_adapter *adapter = user_data;
+ uint32_t settings;
+
+ if (length < sizeof(settings)) {
+ error("Wrong size of new settings parameters");
+ return;
+ }
+
+ settings = bt_get_le32(param);
+
+ DBG("settings: 0x%8.8x -> 0x%8.8x", adapter->current_settings,
+ settings);
+
+ if (settings == adapter->current_settings)
+ return;
+
+ settings_changed(adapter, settings);
+}
+
+static void mgmt_dev_class_changed_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct bt_adapter *adapter = user_data;
+ const struct mgmt_cod *rp = param;
+ uint32_t dev_class;
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size of class of device changed parameters");
+ return;
+ }
+
+ dev_class = rp->val[0] | (rp->val[1] << 8) | (rp->val[2] << 16);
+
+ if (dev_class == adapter->dev_class)
+ return;
+
+ DBG("Class: 0x%06x", dev_class);
+
+ adapter->dev_class = dev_class;
+
+ /* TODO: Inform prop change: Class */
+
+ /* TODO: Gatt attrib set*/
+}
+
+static void register_mgmt_handlers(struct bt_adapter *adapter)
+{
+ mgmt_register(adapter->mgmt, MGMT_EV_NEW_SETTINGS, 0,
+ new_settings_callback, adapter, NULL);
+
+ mgmt_register(adapter->mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED,
+ 0, mgmt_dev_class_changed_event,
+ adapter, NULL);
+
+ mgmt_register(adapter->mgmt, MGMT_EV_LOCAL_NAME_CHANGED,
+ 0, mgmt_local_name_changed_event,
+ adapter, NULL);
+}
+
static void load_link_keys(struct bt_adapter *adapter, GSList *keys)
{
struct mgmt_cp_load_link_keys *cp;
@@ -128,6 +256,7 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
adapter->current_settings = btohs(rp->current_settings);
/* TODO: Register all event notification handlers */
+ register_mgmt_handlers(adapter);
load_link_keys(adapter, NULL);
--
1.7.10.4
From: Andrei Emeltchenko <[email protected]>
This is used in accept message to Android framework.
---
android/Android.mk | 1 +
android/bt-sock.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)
create mode 100644 android/bt-sock.c
diff --git a/android/Android.mk b/android/Android.mk
index 4bd4116..786c9fb 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -57,6 +57,7 @@ LOCAL_SRC_FILES := \
hal-hidhost.c \
hal-pan.c \
hal-msg-client.c \
+ bt-sock.c \
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/android/bt-sock.c b/android/bt-sock.c
new file mode 100644
index 0000000..68dbe32
--- /dev/null
+++ b/android/bt-sock.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+
+int bt_sock_send_acc_fd(int sock_fd, const unsigned char *buf, int len,
+ int send_fd)
+{
+ ssize_t ret;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iv;
+ char msgbuf[CMSG_SPACE(1)];
+
+ ALOGD("%s: len %d sock_fd %d send_fd %d", __func__, len, sock_fd,
+ send_fd);
+
+ if (sock_fd == -1 || send_fd == -1)
+ return -1;
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = msgbuf;
+ msg.msg_controllen = sizeof(msgbuf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
+ memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(send_fd));
+
+ iv.iov_base = (unsigned char *) buf;
+ iv.iov_len = len;
+
+ msg.msg_iov = &iv;
+ msg.msg_iovlen = 1;
+
+ ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL);
+ if (ret < 0) {
+ ALOGE("%s: sock_fd %d send_fd %d sendmsg ret %d errno %d %s",
+ __func__, sock_fd, send_fd, (int)ret, errno,
+ strerror(errno));
+ return ret;
+ }
+
+ return ret;
+}
--
1.7.10.4
From: Andrei Emeltchenko <[email protected]>
Android HAL callback task listens for messages from BlueZ GPL daemon.
---
android/Android.mk | 6 ++++
android/hal-cb-thread.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+)
create mode 100644 android/hal-cb-thread.c
diff --git a/android/Android.mk b/android/Android.mk
index 786c9fb..c5c6e7b 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -58,9 +58,15 @@ LOCAL_SRC_FILES := \
hal-pan.c \
hal-msg-client.c \
bt-sock.c \
+ hal-cb-thread.c \
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ libglib \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
LOCAL_MODULE := bluetooth.default
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
diff --git a/android/hal-cb-thread.c b/android/hal-cb-thread.c
new file mode 100644
index 0000000..1b1e228
--- /dev/null
+++ b/android/hal-cb-thread.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <sys/epoll.h>
+#include <hardware/bluetooth.h>
+#include <fcntl.h>
+
+#define LOG_TAG "BlueZ"
+#include <cutils/log.h>
+
+#include "hal-msg.h"
+
+#define HAL_CBACK(base, cb_function, ...) \
+ do { \
+ if (base && base->cb_function) { \
+ ALOGI("CB %s->%s", #base, #cb_function); \
+ base->cb_function(__VA_ARGS__); \
+ } else { \
+ ALOGE("%s: Callback is NULL", __func__); \
+ } \
+ } while (0)
+
+extern bt_callbacks_t *bt_hal_cbacks;
+
+static int epfd;
+
+static void bthal_thread_associate(void)
+{
+ ALOGI(__func__);
+
+ HAL_CBACK(bt_hal_cbacks, thread_evt_cb, ASSOCIATE_JVM);
+}
+
+static void bthal_thread_disassociate(void)
+{
+ ALOGI(__func__);
+
+ HAL_CBACK(bt_hal_cbacks, thread_evt_cb, DISASSOCIATE_JVM);
+
+ bt_hal_cbacks = NULL;
+}
+
+void process_msg(struct hal_msg_hdr *msg)
+{
+ ALOGI(__func__);
+
+ /* TODO: Process messages from daemon */
+}
+
+int mainloop(void)
+{
+ return EXIT_SUCCESS;
+}
+
+void *hal_cb_task(void *arg)
+{
+ int sock;
+
+ sock = open_hal_chan();
+
+ bthal_thread_associate();
+
+ bthal_thread_disassociate();
+
+ return NULL;
+}
--
1.7.10.4
From: Andrei Emeltchenko <[email protected]>
Add helper to ease opening channel and sending commands.
---
android/Android.mk | 1 +
android/hal-msg-client.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
android/hal-msg-client.h | 25 ++++++++++
3 files changed, 149 insertions(+)
create mode 100644 android/hal-msg-client.c
create mode 100644 android/hal-msg-client.h
diff --git a/android/Android.mk b/android/Android.mk
index d5dfde7..4bd4116 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -56,6 +56,7 @@ LOCAL_SRC_FILES := \
hal-sock.c \
hal-hidhost.c \
hal-pan.c \
+ hal-msg-client.c \
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/android/hal-msg-client.c b/android/hal-msg-client.c
new file mode 100644
index 0000000..43af9a1
--- /dev/null
+++ b/android/hal-msg-client.c
@@ -0,0 +1,123 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <hardware/bluetooth.h>
+#include <cutils/sockets.h>
+#include <cutils/properties.h>
+
+#define LOG_TAG "BlueZ"
+#include <cutils/log.h>
+
+#include "hal-msg.h"
+#include "hal-msg-client.h"
+
+#define BLUEZ_SOCKET "/tmp/bt_hal"
+
+int open_hal_chan(void)
+{
+ int tries = 10;
+ int sock;
+
+ while (tries-- > 0) {
+ sock = socket_local_client(BLUEZ_SOCKET,
+ ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
+ SOCK_SEQPACKET);
+ if (sock < 0)
+ ALOGE("%s: Cannot open chan: %s", __func__,
+ strerror(errno));
+ else
+ return sock;
+
+ usleep(100000);
+ }
+
+ return sock;
+}
+
+static int hal_send(int sock, struct hal_msg_hdr *msg)
+{
+ int len, size;
+ uint8_t buf[MAX_HAL_BUF_SIZE];
+ struct hal_msg_rsp {
+ struct hal_msg_hdr hdr;
+ uint8_t status;
+ } *rsp;
+
+ if (sock < 0) {
+ ALOGE("%s: socket not ready", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ size = sizeof(*msg) + msg->len;
+ len = send(sock, msg, size, 0);
+ if (len != size) {
+ ALOGE("%s: send(): %s", __func__, strerror(errno));
+ close(sock);
+ return BT_STATUS_FAIL;
+ }
+
+ ALOGD("%s: Sent %d bytes", __func__, len);
+
+ len = recv(sock, &buf, sizeof(buf), 0);
+ if (len <= 0) {
+ ALOGE("%s: recv(): %s", __func__, strerror(errno));
+ return BT_STATUS_FAIL;
+ }
+
+ if (len == sizeof(struct hal_msg_hdr))
+ return BT_STATUS_SUCCESS;
+
+ rsp = (struct hal_msg_rsp *) buf;
+
+ ALOGE("%s: error returned: %u", __func__, rsp->status);
+
+ return rsp->status;
+}
+
+int hal_register_module(int sock, uint8_t service_id)
+{
+ struct hal_msg_hdr *hdr;
+ struct hal_msg_cmd_register_module *msg;
+ int err;
+
+ hdr = malloc(sizeof(*hdr) + sizeof(*msg));
+ if (hdr == NULL)
+ return BT_STATUS_NOMEM;
+
+ hdr->service_id = 0;
+ hdr->opcode = HAL_MSG_OP_REGISTER_MODULE;
+ hdr->len = sizeof(*msg);
+
+ msg = (struct hal_msg_cmd_register_module *) hdr + sizeof(*hdr);
+ msg->service_id = service_id;
+
+ err = hal_send(sock, hdr);
+
+ free(hdr);
+ return err;
+}
diff --git a/android/hal-msg-client.h b/android/hal-msg-client.h
new file mode 100644
index 0000000..c620dea
--- /dev/null
+++ b/android/hal-msg-client.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 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
+ *
+ */
+
+int hal_register_module(int sock, uint8_t service_id);
+int open_hal_chan(void);
--
1.7.10.4
From: Andrei Emeltchenko <[email protected]>
The patch set UID as standard Bluetooth user for Android (AID_BLUETOOTH).
For SDP server we need to bind to lower port, acquire this capability.
Other capabilities are required to access management interface.
---
android/main.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 4 ++++
2 files changed, 62 insertions(+)
diff --git a/android/main.c b/android/main.c
index fac1003..4a716be 100644
--- a/android/main.c
+++ b/android/main.c
@@ -33,10 +33,17 @@
#include <stdbool.h>
#include <string.h>
#include <errno.h>
+#include <unistd.h>
+
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/un.h>
+#if defined(ANDROID)
+#include <sys/prctl.h>
+#include <private/android_filesystem_config.h>
+#endif
+
#include <glib.h>
#include "log.h"
@@ -409,6 +416,54 @@ static void cleanup_hal_connection(void)
}
}
+static bool set_capabilities(void)
+{
+#if defined(ANDROID)
+ struct __user_cap_header_struct header;
+ struct __user_cap_data_struct cap;
+ gid_t groups[] = {AID_NET_BT, AID_NET_BT_ADMIN, AID_NET_ADMIN};
+
+ DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+
+ header.version = _LINUX_CAPABILITY_VERSION;
+
+ prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+ if (setgid(AID_BLUETOOTH) < 0)
+ warn("%s: setgid(): %s", __func__, strerror(errno));
+
+ if (setuid(AID_BLUETOOTH) < 0)
+ warn("%s: setuid(): %s", __func__, strerror(errno));
+
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = 0;
+
+ cap.effective = cap.permitted =
+ CAP_TO_MASK(CAP_SETGID) |
+ CAP_TO_MASK(CAP_NET_RAW) |
+ CAP_TO_MASK(CAP_NET_ADMIN) |
+ CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+ cap.inheritable = 0;
+
+ if (capset(&header, &cap) < 0) {
+ error("%s: capset(): %s", __func__, strerror(errno));
+ return false;
+ }
+
+ if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) < 0)
+ warn("%s: setgroups: %s", __func__, strerror(errno));
+
+ if (capget(&header, &cap) < 0)
+ error("%s: capget(): %s", __func__, strerror(errno));
+ else
+ DBG("Caps: eff: 0x%x, perm: 0x%x, inh: 0x%x", cap.effective,
+ cap.permitted, cap.inheritable);
+
+ DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+#endif
+ return true;
+}
+
int main(int argc, char *argv[])
{
GOptionContext *context;
@@ -442,6 +497,9 @@ int main(int argc, char *argv[])
__btd_log_init("*", 0);
+ if (!set_capabilities())
+ return EXIT_FAILURE;
+
if (!init_mgmt_interface())
return EXIT_FAILURE;
diff --git a/configure.ac b/configure.ac
index b4d3998..e3b5220 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,4 +247,8 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
[enable_android=${enableval}])
AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
+if (test "${enable_android}" = "yes"); then
+ AC_CHECK_LIB(cap, capget, dummy=yes, AC_MSG_ERROR(libcap is required))
+fi
+
AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
--
1.7.10.4