* [PATCH_v5 6/6] android: Add reasons for adding capabilites to process
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
CAP_NET_ADMIN: Allow use of MGMT interface
CAP_NET_BIND_SERVICE: Allow use of privileged PSM
CAP_NET_RAW: Allow use of bnep ioctl calls
---
android/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/android/main.c b/android/main.c
index 3a14af5..eedca58 100644
--- a/android/main.c
+++ b/android/main.c
@@ -534,6 +534,9 @@ static bool set_capabilities(void)
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
+ /* CAP_NET_ADMIN: Allow use of MGMT interface
+ * CAP_NET_BIND_SERVICE: Allow use of privileged PSM
+ * CAP_NET_RAW: Allow use of bnep ioctl calls */
cap.effective = cap.permitted =
CAP_TO_MASK(CAP_NET_RAW) |
CAP_TO_MASK(CAP_NET_ADMIN) |
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 5/6] android/pan: Implement the get local role method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Returns local role of the device (NONE, PANU or NAP).
---
android/pan.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 7093e4c..9ff14f3 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -278,9 +278,15 @@ static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
- DBG("Not Implemented");
+ struct hal_rsp_pan_get_role rsp;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ rsp.local_role = local_role;
+ ipc_send_rsp_full(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, sizeof(rsp),
+ &rsp, -1);
+
+ return HAL_STATUS_SUCCESS;
}
void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 4/6] android/pan: Implement pan disconnect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Disconnect ongoing PANU role connection betweek devices, free
the device and notify the connection state.
---
android/pan.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 031dfff..7093e4c 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -238,9 +238,35 @@ static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct pan_device *dev;
+ GSList *l;
+ bdaddr_t dst;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ dev = l->data;
+
+ if (dev->watch) {
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
+
+ bnep_if_down(dev->dev);
+ bnep_kill_connection(&dst);
+
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+
+ return HAL_STATUS_SUCCESS;
}
static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 3/6] android/pan: Implement pan connect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Implements the PAN connect method in android daemon with PANU role
only. Setting up the bnep environment, adds connection and makes
bnep interface up are part of bnep_connect call. Notifies bnep
interface on control state call back and connection status on
connection state call back.
---
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/pan.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index c4d722d..549613c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
../lib/hci.c \
../btio/btio.c \
../src/sdp-client.c \
+ ../profiles/network/bnep.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
@@ -66,6 +67,7 @@ lib_headers := \
sdp.h \
rfcomm.h \
sco.h \
+ bnep.h \
$(shell mkdir -p $(LOCAL_PATH)/../lib/bluetooth)
diff --git a/android/Makefile.am b/android/Makefile.am
index 15ecf35..df04762 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -24,7 +24,8 @@ android_bluetoothd_SOURCES = android/main.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
btio/btio.h btio/btio.c \
- src/sdp-client.h src/sdp-client.c
+ src/sdp-client.h src/sdp-client.c \
+ profiles/network/bnep.h profiles/network/bnep.c
android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
diff --git a/android/pan.c b/android/pan.c
index ea15637..031dfff 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -29,35 +29,228 @@
#include <fcntl.h>
#include <glib.h>
+#include "btio/btio.h"
#include "lib/bluetooth.h"
+#include "lib/bnep.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "src/glib-helper.h"
+#include "profiles/network/bnep.h"
+
#include "log.h"
#include "pan.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "utils.h"
+#include "bluetooth.h"
-static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
+static bdaddr_t adapter_addr;
+GSList *peers = NULL;
+uint8_t local_role = HAL_PAN_ROLE_NONE;
+
+struct pan_device {
+ char dev[16];
+ bdaddr_t dst;
+ uint8_t conn_state;
+ uint8_t role;
+ GIOChannel *io;
+ guint watch;
+};
+
+static int peer_cmp(gconstpointer s, gconstpointer user_data)
{
- DBG("Not Implemented");
+ const struct pan_device *dev = s;
+ const bdaddr_t *dst = user_data;
- return HAL_STATUS_FAILED;
+ return bacmp(&dev->dst, dst);
}
-static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
+static void pan_device_free(struct pan_device *dev)
+{
+ local_role = HAL_PAN_ROLE_NONE;
+
+ if (dev->watch > 0) {
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
+
+ if (dev->io) {
+ g_io_channel_unref(dev->io);
+ dev->io = NULL;
+ }
+
+ peers = g_slist_remove(peers, dev);
+ g_free(dev);
+ dev = NULL;
+}
+
+static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
+{
+ struct hal_ev_pan_conn_state ev;
+ char addr[18];
+
+ if (dev->conn_state == state)
+ return;
+
+ dev->conn_state = state;
+ ba2str(&dev->dst, addr);
+ DBG("device %s state %u", addr, state);
+
+ bdaddr2android(&dev->dst, ev.bdaddr);
+ ev.state = state;
+ ev.local_role = local_role;
+ 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);
+}
+
+static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
+{
+ struct hal_ev_pan_ctrl_state ev;
+
+ DBG("");
+
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.status = HAL_STATUS_SUCCESS;
+ memcpy(ev.name, dev->dev, sizeof(dev->dev));
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
+ &ev);
+}
+
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct pan_device *dev = data;
+
+ DBG("%s disconnected", dev->dev);
+
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+
+ return FALSE;
+}
+
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+{
+ struct pan_device *dev = data;
+
+ DBG("");
+
+ if (err < 0) {
+ error("bnep connect req failed: %s", strerror(-err));
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+ return;
+ }
+
+ memcpy(dev->dev, iface, sizeof(dev->dev));
+
+ DBG("%s connected", dev->dev);
+
+ bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
+
+ dev->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_watchdog_cb, dev);
+ g_io_channel_unref(dev->io);
+ dev->io = NULL;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
+{
+ struct pan_device *dev = data;
+ uint16_t src, dst;
+ int perr, sk;
+
+ DBG("");
+
+ if (err) {
+ error("%s", err->message);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+ }
+
+ src = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ dst = (dev->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ sk = g_io_channel_unix_get_fd(dev->io);
+
+ perr = bnep_connect(sk, src, dst, bnep_conn_cb, dev);
+ if (perr < 0) {
+ error("bnep connect req failed: %s", strerror(-perr));
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+ return;
+ }
+}
+
+static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+{
+ struct pan_device *dev;
+ bdaddr_t dst;
+ char addr[18];
+ GSList *l;
+ GError *gerr = NULL;
+
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (l)
+ return HAL_STATUS_FAILED;
+
+ dev = g_new0(struct pan_device, 1);
+ bacpy(&dev->dst, &dst);
+ local_role = cmd->local_role;
+ dev->role = cmd->remote_role;
+
+ ba2str(&dev->dst, addr);
+ DBG("connecting to %s %s", addr, dev->dev);
+
+ dev->io = bt_io_connect(connect_cb, dev, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &dev->dst,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+ if (!dev->io) {
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ g_free(dev);
+ return HAL_STATUS_FAILED;
+ }
+
+ peers = g_slist_append(peers, dev);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
+
+ return HAL_STATUS_SUCCESS;
+}
+
+static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
+ uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
- uint16_t len)
+static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
DBG("Not Implemented");
@@ -91,12 +284,24 @@ void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
bool bt_pan_register(const bdaddr_t *addr)
{
+ int err;
+
DBG("");
+ bacpy(&adapter_addr, addr);
+
+ err = bnep_init();
+ if (err) {
+ error("bnep init failed");
+ return false;
+ }
+
return true;
}
void bt_pan_unregister(void)
{
DBG("");
+
+ bnep_cleanup();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 2/6] profiles/network: Rename common.c|h to bnep.c|h
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Files common.c|h contains only bnep related code, it makes
more sence with bnep.c|h.
---
Makefile.plugins | 2 +-
profiles/network/{common.c => bnep.c} | 2 +-
profiles/network/{common.h => bnep.h} | 0
profiles/network/connection.c | 2 +-
profiles/network/manager.c | 2 +-
profiles/network/server.c | 2 +-
6 files changed, 5 insertions(+), 5 deletions(-)
rename profiles/network/{common.c => bnep.c} (99%)
rename profiles/network/{common.h => bnep.h} (100%)
diff --git a/Makefile.plugins b/Makefile.plugins
index f5025e9..6a1ddbf 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -47,7 +47,7 @@ builtin_sources += profiles/audio/control.h profiles/audio/control.c \
builtin_modules += network
builtin_sources += profiles/network/manager.c \
- profiles/network/common.h profiles/network/common.c \
+ profiles/network/bnep.h profiles/network/bnep.c \
profiles/network/server.h profiles/network/server.c \
profiles/network/connection.h \
profiles/network/connection.c
diff --git a/profiles/network/common.c b/profiles/network/bnep.c
similarity index 99%
rename from profiles/network/common.c
rename to profiles/network/bnep.c
index 71154c8..0a719a2 100644
--- a/profiles/network/common.c
+++ b/profiles/network/bnep.c
@@ -43,7 +43,7 @@
#include <glib.h>
#include "log.h"
-#include "common.h"
+#include "bnep.h"
#include "lib/uuid.h"
#define CON_SETUP_RETRIES 3
diff --git a/profiles/network/common.h b/profiles/network/bnep.h
similarity index 100%
rename from profiles/network/common.h
rename to profiles/network/bnep.h
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index d100580..9aff319 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -47,7 +47,7 @@
#include "service.h"
#include "error.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index ab4224d..8ac2dec 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -43,7 +43,7 @@
#include "device.h"
#include "profile.h"
#include "service.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#include "server.h"
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 3a7e52a..b3aab11 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -48,7 +48,7 @@
#include "error.h"
#include "sdpd.h"
-#include "common.h"
+#include "bnep.h"
#include "server.h"
#define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 1/6] profiles/network: Refactor bnep connection setup functionality
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Moving bnep connection setup related functionality to common.c.
Provided bnep_connect call with bnep_connect_cb for status and
bnep interface name. It will be simple if someone want to utilize
this call otherwise they have to reimplement similar functionality
with minimal changes (e.g. android/pan).
---
profiles/network/common.c | 195 +++++++++++++++++++++++++++++++++++++++++-
profiles/network/common.h | 5 ++
profiles/network/connection.c | 172 +++----------------------------------
profiles/network/server.c | 3 -
4 files changed, 211 insertions(+), 164 deletions(-)
diff --git a/profiles/network/common.c b/profiles/network/common.c
index 0b291bd..71154c8 100644
--- a/profiles/network/common.c
+++ b/profiles/network/common.c
@@ -46,6 +46,9 @@
#include "common.h"
#include "lib/uuid.h"
+#define CON_SETUP_RETRIES 3
+#define CON_SETUP_TO 9
+
static int ctl;
static struct {
@@ -59,6 +62,35 @@ static struct {
{ NULL }
};
+struct __service_16 {
+ uint16_t dst;
+ uint16_t src;
+} __attribute__ ((packed));
+
+struct bnep_conn {
+ GIOChannel *io;
+ uint16_t src;
+ uint16_t dst;
+ guint attempts;
+ guint setup_to;
+ void *data;
+ bnep_connect_cb conn_cb;
+};
+
+static void free_bnep_connect(struct bnep_conn *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->io) {
+ g_io_channel_unref(bc->io);
+ bc->io = NULL;
+ }
+
+ g_free(bc);
+ bc = NULL;
+}
+
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -149,9 +181,9 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
{
struct bnep_connadd_req req;
+ memset(dev, 0, 16);
memset(&req, 0, sizeof(req));
- strncpy(req.device, dev, 16);
- req.device[15] = '\0';
+ strcpy(req.device, "bnep%d");
req.sock = sk;
req.role = role;
if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
@@ -215,6 +247,165 @@ int bnep_if_down(const char *devname)
return 0;
}
+static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct bnep_conn *bc = data;
+ struct bnep_control_rsp *rsp;
+ struct timeval timeo;
+ char pkt[BNEP_MTU];
+ char iface[16];
+ ssize_t r;
+ int sk;
+
+ if (cond & G_IO_NVAL)
+ goto failed;
+
+ if (bc->setup_to > 0) {
+ g_source_remove(bc->setup_to);
+ bc->setup_to = 0;
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ error("Hangup or error on l2cap server socket");
+ goto failed;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+ memset(pkt, 0, BNEP_MTU);
+ r = read(sk, pkt, sizeof(pkt) - 1);
+ if (r < 0) {
+ error("IO Channel read error");
+ goto failed;
+ }
+
+ if (r == 0) {
+ error("No packet received on l2cap socket");
+ goto failed;
+ }
+
+ errno = EPROTO;
+
+ if ((size_t) r < sizeof(*rsp)) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ rsp = (void *) pkt;
+ if (rsp->type != BNEP_CONTROL) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
+ return TRUE;
+
+ r = ntohs(rsp->resp);
+ if (r != BNEP_SUCCESS) {
+ error("bnep failed");
+ goto failed;
+ }
+
+ memset(&timeo, 0, sizeof(timeo));
+ timeo.tv_sec = 0;
+ setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+
+ sk = g_io_channel_unix_get_fd(bc->io);
+ if (bnep_connadd(sk, bc->src, iface)) {
+ error("bnep conn could not be added");
+ goto failed;
+ }
+
+ if (bnep_if_up(iface)) {
+ error("could not up %s", iface);
+ goto failed;
+ }
+
+ bc->conn_cb(chan, iface, 0, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+
+failed:
+ bc->conn_cb(NULL, NULL, -EIO, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+static int bnep_setup_conn_req(struct bnep_conn *bc)
+{
+ struct bnep_setup_conn_req *req;
+ struct __service_16 *s;
+ unsigned char pkt[BNEP_MTU];
+ int fd;
+
+ /* Send request */
+ req = (void *) pkt;
+ req->type = BNEP_CONTROL;
+ req->ctrl = BNEP_SETUP_CONN_REQ;
+ req->uuid_size = 2; /* 16bit UUID */
+ s = (void *) req->service;
+ s->src = htons(bc->src);
+ s->dst = htons(bc->dst);
+
+ fd = g_io_channel_unix_get_fd(bc->io);
+ if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
+ error("bnep connection req send failed: %s", strerror(errno));
+ return -errno;
+ }
+
+ bc->attempts++;
+
+ return 0;
+}
+
+static gboolean bnep_conn_req_to(gpointer user_data)
+{
+ struct bnep_conn *bc = user_data;
+
+ if (bc->attempts == CON_SETUP_RETRIES) {
+ error("Too many bnep connection attempts");
+ } else {
+ error("bnep connection setup TO, retrying...");
+ if (bnep_setup_conn_req(bc) == 0)
+ return TRUE;
+ }
+
+ bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data)
+{
+ struct bnep_conn *bc;
+ int err;
+
+ if (!conn_cb)
+ return -EINVAL;
+
+ bc = g_new0(struct bnep_conn, 1);
+ bc->io = g_io_channel_unix_new(sk);
+ bc->attempts = 0;
+ bc->src = src;
+ bc->dst = dst;
+ bc->conn_cb = conn_cb;
+ bc->data = data;
+
+ err = bnep_setup_conn_req(bc);
+ if (err < 0)
+ return err;
+
+ bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
+ bnep_conn_req_to, bc);
+ g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_setup_cb, bc);
+ return 0;
+}
+
int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/common.h b/profiles/network/common.h
index 9a8caac..9043e46 100644
--- a/profiles/network/common.h
+++ b/profiles/network/common.h
@@ -35,3 +35,8 @@ int bnep_if_up(const char *devname);
int bnep_if_down(const char *devname);
int bnep_add_to_bridge(const char *devname, const char *bridge);
int bnep_del_from_bridge(const char *devname, const char *bridge);
+
+typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
+ void *data);
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5966268..d100580 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -51,8 +51,6 @@
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
-#define CON_SETUP_RETRIES 3
-#define CON_SETUP_TO 9
typedef enum {
CONNECTED,
@@ -73,16 +71,9 @@ struct network_conn {
GIOChannel *io;
guint dc_id;
struct network_peer *peer;
- guint attempt_cnt;
- guint timeout_source;
DBusMessage *connect;
};
-struct __service_16 {
- uint16_t dst;
- uint16_t src;
-} __attribute__ ((packed));
-
static GSList *peers = NULL;
static uint16_t get_service_id(struct btd_service *service)
@@ -163,11 +154,6 @@ static void local_connect_cb(struct network_conn *nc, int err)
static void cancel_connection(struct network_conn *nc, int err)
{
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
btd_service_connecting_complete(nc->service, err);
if (nc->connect)
local_connect_cb(nc, err);
@@ -200,83 +186,24 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
connection_destroy(NULL, user_data);
}
-static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
- gpointer data)
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
{
struct network_conn *nc = data;
- struct bnep_control_rsp *rsp;
- struct timeval timeo;
- char pkt[BNEP_MTU];
- ssize_t r;
- int sk;
const char *path;
DBusConnection *conn;
- DBG("cond %u", cond);
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- error("Hangup or error on l2cap server socket");
- goto failed;
- }
-
- sk = g_io_channel_unix_get_fd(chan);
-
- memset(pkt, 0, BNEP_MTU);
- r = read(sk, pkt, sizeof(pkt) -1);
- if (r < 0) {
- error("IO Channel read error");
- goto failed;
- }
-
- if (r == 0) {
- error("No packet received on l2cap socket");
- goto failed;
- }
-
- errno = EPROTO;
-
- if ((size_t) r < sizeof(*rsp)) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- rsp = (void *) pkt;
- if (rsp->type != BNEP_CONTROL) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
- return TRUE;
-
- r = ntohs(rsp->resp);
-
- if (r != BNEP_SUCCESS) {
- error("bnep failed");
- goto failed;
- }
-
- memset(&timeo, 0, sizeof(timeo));
- timeo.tv_sec = 0;
-
- setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+ DBG("");
- if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
- error("%s could not be added", nc->dev);
+ if (err < 0) {
+ error("connect failed %s", strerror(-err));
goto failed;
}
- bnep_if_up(nc->dev);
+ info("%s connected", nc->dev);
+ memcpy(nc->dev, iface, sizeof(nc->dev));
btd_service_connecting_complete(nc->service, 0);
+
if (nc->connect)
local_connect_cb(nc, 0);
@@ -292,101 +219,30 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
nc->state = CONNECTED;
nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
- nc, NULL);
-
- info("%s connected", nc->dev);
- /* Start watchdog */
+ nc, NULL);
g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) bnep_watchdog_cb, nc);
+ bnep_watchdog_cb, nc);
g_io_channel_unref(nc->io);
nc->io = NULL;
- return FALSE;
+ return;
failed:
cancel_connection(nc, -EIO);
-
- return FALSE;
-}
-
-static int bnep_send_conn_req(struct network_conn *nc)
-{
- struct bnep_setup_conn_req *req;
- struct __service_16 *s;
- unsigned char pkt[BNEP_MTU];
- int fd;
-
- DBG("");
-
- /* Send request */
- req = (void *) pkt;
- req->type = BNEP_CONTROL;
- req->ctrl = BNEP_SETUP_CONN_REQ;
- req->uuid_size = 2; /* 16bit UUID */
- s = (void *) req->service;
- s->dst = htons(nc->id);
- s->src = htons(BNEP_SVC_PANU);
-
- fd = g_io_channel_unix_get_fd(nc->io);
- if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
- int err = -errno;
- error("bnep connection req send failed: %s", strerror(errno));
- return err;
- }
-
- nc->attempt_cnt++;
-
- return 0;
-}
-
-static gboolean bnep_conn_req_to(gpointer user_data)
-{
- struct network_conn *nc;
-
- nc = user_data;
- if (nc->attempt_cnt == CON_SETUP_RETRIES) {
- error("Too many bnep connection attempts");
- } else {
- error("bnep connection setup TO, retrying...");
- if (bnep_send_conn_req(nc) == 0)
- return TRUE;
- }
-
- cancel_connection(nc, -ETIMEDOUT);
-
- return FALSE;
-}
-
-static int bnep_connect(struct network_conn *nc)
-{
- int err;
-
- nc->attempt_cnt = 0;
-
- err = bnep_send_conn_req(nc);
- if (err < 0)
- return err;
-
- nc->timeout_source = g_timeout_add_seconds(CON_SETUP_TO,
- bnep_conn_req_to, nc);
-
- g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- bnep_setup_cb, nc);
-
- return 0;
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct network_conn *nc = data;
- int perr;
+ int sk, perr;
if (err) {
error("%s", err->message);
goto failed;
}
- perr = bnep_connect(nc);
+ sk = g_io_channel_unix_get_fd(nc->io);
+ perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
@@ -692,8 +548,6 @@ int connection_register(struct btd_service *service)
nc = g_new0(struct network_conn, 1);
nc->id = id;
- memset(nc->dev, 0, sizeof(nc->dev));
- strcpy(nc->dev, "bnep%d");
nc->service = btd_service_ref(service);
nc->state = DISCONNECTED;
nc->peer = peer;
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 0050b30..3a7e52a 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -269,9 +269,6 @@ static int server_connadd(struct network_server *ns,
char devname[16];
int err, nsk;
- memset(devname, 0, sizeof(devname));
- strcpy(devname, "bnep%d");
-
nsk = g_io_channel_unix_get_fd(session->io);
err = bnep_connadd(nsk, dst_role, devname);
if (err < 0)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 0/6] Refactor bnep code and implement pan methods
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
v5: Renamed strcut network_peer to pan_device as per Luiz comments.
v4: Fixed Luiz comments (discussed in irc). Merge patch 1 and 2.
Pass fd in bnep_connect instead of GIOChannel.
v3: Fixed Anderson and Luiz comments and solved rebased conflicts.
v2: Refactored profiles/network/common.* as per Johan's comments
(renaming common.c|h to bnep.c|h and moving bnep related code to
bnep.c ro reduce redundancy in profiles/netowrk/connection.c and
android/pan.c)
v1: This patch set supports PANU role with a minor fix in android. Added
CAP_NET_RAW capability for bnep services. Creates bnep connection and
up the inreface on connect call and free the device on disconnect call.
Interface name(bnepX) will be notified on control state cb. Android
environment will create IP address with dhcp calls.
Ravi kumar Veeramally (6):
profiles/network: Refactor bnep connection setup functionality
profiles/network: Rename common.c|h to bnep.c|h
android/pan: Implement pan connect method in daemon
android/pan: Implement pan disconnect method in daemon
android/pan: Implement the get local role method in daemon
android: Add reasons for adding capabilites to process
Makefile.plugins | 2 +-
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/main.c | 3 +
android/pan.c | 253 ++++++++++++++++++++++++++++++++--
profiles/network/{common.c => bnep.c} | 197 +++++++++++++++++++++++++-
profiles/network/{common.h => bnep.h} | 5 +
profiles/network/connection.c | 174 ++---------------------
profiles/network/manager.c | 2 +-
profiles/network/server.c | 5 +-
10 files changed, 468 insertions(+), 178 deletions(-)
rename profiles/network/{common.c => bnep.c} (58%)
rename profiles/network/{common.h => bnep.h} (87%)
--
1.8.3.2
^ permalink raw reply
* [RFC] android/doc: Add socket-api.txt document
From: Andrei Emeltchenko @ 2013-11-29 13:28 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Document describes how socket HAL is working.
---
android/socket-api.txt | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 android/socket-api.txt
diff --git a/android/socket-api.txt b/android/socket-api.txt
new file mode 100644
index 0000000..9f622f9
--- /dev/null
+++ b/android/socket-api.txt
@@ -0,0 +1,61 @@
+Android Socket protocol for Bluetooth
+=====================================
+
+Since Android switched from BlueZ (where sockets where nicely implemented) to
+Bluedroid user space stack there is a need to emulate bluetooth sockets.
+
+Android Bluetooth Socket Hardware Abstraction Layer (HAL) bt_sock.h has
+only 2 functions:
+
+static btsock_interface_t sock_if = {
+ sizeof(sock_if),
+ sock_listen,
+ sock_connect
+};
+
+with following parameters:
+
+sock_listen(btsock_type_t type, const char *service_name,
+ const uint8_t *uuid, int chan, int *sock_fd, int flags)
+sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
+ const uint8_t *uuid, int chan, int *sock_fd, int flags)
+
+socket type RFCOMM is only supported at the moment. uuid and channel used
+to decide where to connect.
+
+sockfd is used to return socket fd to Android framework. It is used to inform
+framework when remote device is connected.
+
+listen()
+========
+
+Listens on RFCOMM socket, socket channel is either found based on uuid or
+channel parameter used directly. Returns sock_fd to Android framework.
+
+Through this sock_fd channel number as (int) needs to be written right after
+listen() succeeds.
+
+When remote device is connected to this socket we shall send accept signal
+through sock_fd
+
+connect()
+=========
+
+Connects to remote device specified in bd_addr parameter. Socket channel is
+found by SDP search of remote device by supplied uuid. Returns sock_fd to
+Android framework.
+
+Through this sock_fd channel number as (int) needs to be written right after
+connects() succeeds.
+
+When remote device is connected to this socket we shall send connect signal
+through sock_fd
+
+The format of connect/accept signal is shown below:
+
+struct hal_sock_connect_signal {
+ short size;
+ uint8_t bdaddr[6];
+ int channel;
+ int status;
+} __attribute__((packed));
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 6/6] android: Add reasons for adding capabilites to process
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
CAP_NET_ADMIN: Allow use of MGMT interface
CAP_NET_BIND_SERVICE: Allow use of privileged PSM
CAP_NET_RAW: Allow use of bnep ioctl calls
---
android/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/android/main.c b/android/main.c
index 3a14af5..eedca58 100644
--- a/android/main.c
+++ b/android/main.c
@@ -534,6 +534,9 @@ static bool set_capabilities(void)
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
+ /* CAP_NET_ADMIN: Allow use of MGMT interface
+ * CAP_NET_BIND_SERVICE: Allow use of privileged PSM
+ * CAP_NET_RAW: Allow use of bnep ioctl calls */
cap.effective = cap.permitted =
CAP_TO_MASK(CAP_NET_RAW) |
CAP_TO_MASK(CAP_NET_ADMIN) |
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 5/6] android/pan: Implement the get local role method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Returns local role of the device (NONE, PANU or NAP).
---
android/pan.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 34bbbd0..88f96d4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -278,9 +278,15 @@ static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
- DBG("Not Implemented");
+ struct hal_rsp_pan_get_role rsp;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ rsp.local_role = local_role;
+ ipc_send_rsp_full(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, sizeof(rsp),
+ &rsp, -1);
+
+ return HAL_STATUS_SUCCESS;
}
void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 4/6] android/pan: Implement pan disconnect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Disconnect ongoing PANU role connection betweek devices, free
the device and notify the connection state.
---
android/pan.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 5bd1b0d..34bbbd0 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -238,9 +238,35 @@ static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct network_peer *np;
+ GSList *l;
+ bdaddr_t dst;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ np = l->data;
+
+ if (np->watch) {
+ g_source_remove(np->watch);
+ np->watch = 0;
+ }
+
+ bnep_if_down(np->dev);
+ bnep_kill_connection(&dst);
+
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+
+ return HAL_STATUS_SUCCESS;
}
static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 3/6] android/pan: Implement pan connect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Implements the PAN connect method in android daemon with PANU role
only. Setting up the bnep environment, adds connection and makes
bnep interface up are part of bnep_connect call. Notifies bnep
interface on control state call back and connection status on
connection state call back.
---
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/pan.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index c4d722d..549613c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
../lib/hci.c \
../btio/btio.c \
../src/sdp-client.c \
+ ../profiles/network/bnep.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
@@ -66,6 +67,7 @@ lib_headers := \
sdp.h \
rfcomm.h \
sco.h \
+ bnep.h \
$(shell mkdir -p $(LOCAL_PATH)/../lib/bluetooth)
diff --git a/android/Makefile.am b/android/Makefile.am
index 15ecf35..df04762 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -24,7 +24,8 @@ android_bluetoothd_SOURCES = android/main.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
btio/btio.h btio/btio.c \
- src/sdp-client.h src/sdp-client.c
+ src/sdp-client.h src/sdp-client.c \
+ profiles/network/bnep.h profiles/network/bnep.c
android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
diff --git a/android/pan.c b/android/pan.c
index ea15637..5bd1b0d 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -29,35 +29,228 @@
#include <fcntl.h>
#include <glib.h>
+#include "btio/btio.h"
#include "lib/bluetooth.h"
+#include "lib/bnep.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "src/glib-helper.h"
+#include "profiles/network/bnep.h"
+
#include "log.h"
#include "pan.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "utils.h"
+#include "bluetooth.h"
-static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
+static bdaddr_t adapter_addr;
+GSList *peers = NULL;
+uint8_t local_role = HAL_PAN_ROLE_NONE;
+
+struct network_peer {
+ char dev[16];
+ bdaddr_t dst;
+ uint8_t conn_state;
+ uint8_t role;
+ GIOChannel *io;
+ guint watch;
+};
+
+static int peer_cmp(gconstpointer s, gconstpointer user_data)
{
- DBG("Not Implemented");
+ const struct network_peer *np = s;
+ const bdaddr_t *dst = user_data;
- return HAL_STATUS_FAILED;
+ return bacmp(&np->dst, dst);
}
-static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
+static void network_peer_free(struct network_peer *np)
+{
+ local_role = HAL_PAN_ROLE_NONE;
+
+ if (np->watch > 0) {
+ g_source_remove(np->watch);
+ np->watch = 0;
+ }
+
+ if (np->io) {
+ g_io_channel_unref(np->io);
+ np->io = NULL;
+ }
+
+ peers = g_slist_remove(peers, np);
+ g_free(np);
+ np = NULL;
+}
+
+static void bt_pan_notify_conn_state(struct network_peer *np, uint8_t state)
+{
+ struct hal_ev_pan_conn_state ev;
+ char addr[18];
+
+ if (np->conn_state == state)
+ return;
+
+ np->conn_state = state;
+ ba2str(&np->dst, addr);
+ DBG("device %s state %u", addr, state);
+
+ bdaddr2android(&np->dst, ev.bdaddr);
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.remote_role = np->role;
+ ev.status = HAL_STATUS_SUCCESS;
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
+ &ev);
+}
+
+static void bt_pan_notify_ctrl_state(struct network_peer *np, uint8_t state)
+{
+ struct hal_ev_pan_ctrl_state ev;
+
+ DBG("");
+
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.status = HAL_STATUS_SUCCESS;
+ memcpy(ev.name, np->dev, sizeof(np->dev));
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
+ &ev);
+}
+
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct network_peer *np = data;
+
+ DBG("%s disconnected", np->dev);
+
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+
+ return FALSE;
+}
+
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+{
+ struct network_peer *np = data;
+
+ DBG("");
+
+ if (err < 0) {
+ error("bnep connect req failed: %s", strerror(-err));
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+ return;
+ }
+
+ memcpy(np->dev, iface, sizeof(np->dev));
+
+ DBG("%s connected", np->dev);
+
+ bt_pan_notify_ctrl_state(np, HAL_PAN_CTRL_ENABLED);
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_CONNECTED);
+
+ np->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_watchdog_cb, np);
+ g_io_channel_unref(np->io);
+ np->io = NULL;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
+{
+ struct network_peer *np = data;
+ uint16_t src, dst;
+ int perr, sk;
+
+ DBG("");
+
+ if (err) {
+ error("%s", err->message);
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+ }
+
+ src = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ dst = (np->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ sk = g_io_channel_unix_get_fd(np->io);
+
+ perr = bnep_connect(sk, src, dst, bnep_conn_cb, np);
+ if (perr < 0) {
+ error("bnep connect req failed: %s", strerror(-perr));
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+ return;
+ }
+}
+
+static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+{
+ struct network_peer *np;
+ bdaddr_t dst;
+ char addr[18];
+ GSList *l;
+ GError *gerr = NULL;
+
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (l)
+ return HAL_STATUS_FAILED;
+
+ np = g_new0(struct network_peer, 1);
+ bacpy(&np->dst, &dst);
+ local_role = cmd->local_role;
+ np->role = cmd->remote_role;
+
+ ba2str(&np->dst, addr);
+ DBG("connecting to %s %s", addr, np->dev);
+
+ np->io = bt_io_connect(connect_cb, np, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &np->dst,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+ if (!np->io) {
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ g_free(np);
+ return HAL_STATUS_FAILED;
+ }
+
+ peers = g_slist_append(peers, np);
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_CONNECTING);
+
+ return HAL_STATUS_SUCCESS;
+}
+
+static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
+ uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
- uint16_t len)
+static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
DBG("Not Implemented");
@@ -91,12 +284,24 @@ void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
bool bt_pan_register(const bdaddr_t *addr)
{
+ int err;
+
DBG("");
+ bacpy(&adapter_addr, addr);
+
+ err = bnep_init();
+ if (err) {
+ error("bnep init failed");
+ return false;
+ }
+
return true;
}
void bt_pan_unregister(void)
{
DBG("");
+
+ bnep_cleanup();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 2/6] profiles/network: Rename common.c|h to bnep.c|h
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Files common.c|h contains only bnep related code, it makes
more sence with bnep.c|h.
---
Makefile.plugins | 2 +-
profiles/network/{common.c => bnep.c} | 2 +-
profiles/network/{common.h => bnep.h} | 0
profiles/network/connection.c | 2 +-
profiles/network/manager.c | 2 +-
profiles/network/server.c | 2 +-
6 files changed, 5 insertions(+), 5 deletions(-)
rename profiles/network/{common.c => bnep.c} (99%)
rename profiles/network/{common.h => bnep.h} (100%)
diff --git a/Makefile.plugins b/Makefile.plugins
index f5025e9..6a1ddbf 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -47,7 +47,7 @@ builtin_sources += profiles/audio/control.h profiles/audio/control.c \
builtin_modules += network
builtin_sources += profiles/network/manager.c \
- profiles/network/common.h profiles/network/common.c \
+ profiles/network/bnep.h profiles/network/bnep.c \
profiles/network/server.h profiles/network/server.c \
profiles/network/connection.h \
profiles/network/connection.c
diff --git a/profiles/network/common.c b/profiles/network/bnep.c
similarity index 99%
rename from profiles/network/common.c
rename to profiles/network/bnep.c
index 71154c8..0a719a2 100644
--- a/profiles/network/common.c
+++ b/profiles/network/bnep.c
@@ -43,7 +43,7 @@
#include <glib.h>
#include "log.h"
-#include "common.h"
+#include "bnep.h"
#include "lib/uuid.h"
#define CON_SETUP_RETRIES 3
diff --git a/profiles/network/common.h b/profiles/network/bnep.h
similarity index 100%
rename from profiles/network/common.h
rename to profiles/network/bnep.h
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index d100580..9aff319 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -47,7 +47,7 @@
#include "service.h"
#include "error.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index ab4224d..8ac2dec 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -43,7 +43,7 @@
#include "device.h"
#include "profile.h"
#include "service.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#include "server.h"
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 3a7e52a..b3aab11 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -48,7 +48,7 @@
#include "error.h"
#include "sdpd.h"
-#include "common.h"
+#include "bnep.h"
#include "server.h"
#define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 1/6] profiles/network: Refactor bnep connection setup functionality
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Moving bnep connection setup related functionality to common.c.
Provided bnep_connect call with bnep_connect_cb for status and
bnep interface name. It will be simple if someone want to utilize
this call otherwise they have to reimplement similar functionality
with minimal changes (e.g. android/pan).
---
profiles/network/common.c | 195 +++++++++++++++++++++++++++++++++++++++++-
profiles/network/common.h | 5 ++
profiles/network/connection.c | 172 +++----------------------------------
profiles/network/server.c | 3 -
4 files changed, 211 insertions(+), 164 deletions(-)
diff --git a/profiles/network/common.c b/profiles/network/common.c
index 0b291bd..71154c8 100644
--- a/profiles/network/common.c
+++ b/profiles/network/common.c
@@ -46,6 +46,9 @@
#include "common.h"
#include "lib/uuid.h"
+#define CON_SETUP_RETRIES 3
+#define CON_SETUP_TO 9
+
static int ctl;
static struct {
@@ -59,6 +62,35 @@ static struct {
{ NULL }
};
+struct __service_16 {
+ uint16_t dst;
+ uint16_t src;
+} __attribute__ ((packed));
+
+struct bnep_conn {
+ GIOChannel *io;
+ uint16_t src;
+ uint16_t dst;
+ guint attempts;
+ guint setup_to;
+ void *data;
+ bnep_connect_cb conn_cb;
+};
+
+static void free_bnep_connect(struct bnep_conn *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->io) {
+ g_io_channel_unref(bc->io);
+ bc->io = NULL;
+ }
+
+ g_free(bc);
+ bc = NULL;
+}
+
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -149,9 +181,9 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
{
struct bnep_connadd_req req;
+ memset(dev, 0, 16);
memset(&req, 0, sizeof(req));
- strncpy(req.device, dev, 16);
- req.device[15] = '\0';
+ strcpy(req.device, "bnep%d");
req.sock = sk;
req.role = role;
if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
@@ -215,6 +247,165 @@ int bnep_if_down(const char *devname)
return 0;
}
+static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct bnep_conn *bc = data;
+ struct bnep_control_rsp *rsp;
+ struct timeval timeo;
+ char pkt[BNEP_MTU];
+ char iface[16];
+ ssize_t r;
+ int sk;
+
+ if (cond & G_IO_NVAL)
+ goto failed;
+
+ if (bc->setup_to > 0) {
+ g_source_remove(bc->setup_to);
+ bc->setup_to = 0;
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ error("Hangup or error on l2cap server socket");
+ goto failed;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+ memset(pkt, 0, BNEP_MTU);
+ r = read(sk, pkt, sizeof(pkt) - 1);
+ if (r < 0) {
+ error("IO Channel read error");
+ goto failed;
+ }
+
+ if (r == 0) {
+ error("No packet received on l2cap socket");
+ goto failed;
+ }
+
+ errno = EPROTO;
+
+ if ((size_t) r < sizeof(*rsp)) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ rsp = (void *) pkt;
+ if (rsp->type != BNEP_CONTROL) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
+ return TRUE;
+
+ r = ntohs(rsp->resp);
+ if (r != BNEP_SUCCESS) {
+ error("bnep failed");
+ goto failed;
+ }
+
+ memset(&timeo, 0, sizeof(timeo));
+ timeo.tv_sec = 0;
+ setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+
+ sk = g_io_channel_unix_get_fd(bc->io);
+ if (bnep_connadd(sk, bc->src, iface)) {
+ error("bnep conn could not be added");
+ goto failed;
+ }
+
+ if (bnep_if_up(iface)) {
+ error("could not up %s", iface);
+ goto failed;
+ }
+
+ bc->conn_cb(chan, iface, 0, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+
+failed:
+ bc->conn_cb(NULL, NULL, -EIO, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+static int bnep_setup_conn_req(struct bnep_conn *bc)
+{
+ struct bnep_setup_conn_req *req;
+ struct __service_16 *s;
+ unsigned char pkt[BNEP_MTU];
+ int fd;
+
+ /* Send request */
+ req = (void *) pkt;
+ req->type = BNEP_CONTROL;
+ req->ctrl = BNEP_SETUP_CONN_REQ;
+ req->uuid_size = 2; /* 16bit UUID */
+ s = (void *) req->service;
+ s->src = htons(bc->src);
+ s->dst = htons(bc->dst);
+
+ fd = g_io_channel_unix_get_fd(bc->io);
+ if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
+ error("bnep connection req send failed: %s", strerror(errno));
+ return -errno;
+ }
+
+ bc->attempts++;
+
+ return 0;
+}
+
+static gboolean bnep_conn_req_to(gpointer user_data)
+{
+ struct bnep_conn *bc = user_data;
+
+ if (bc->attempts == CON_SETUP_RETRIES) {
+ error("Too many bnep connection attempts");
+ } else {
+ error("bnep connection setup TO, retrying...");
+ if (bnep_setup_conn_req(bc) == 0)
+ return TRUE;
+ }
+
+ bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data)
+{
+ struct bnep_conn *bc;
+ int err;
+
+ if (!conn_cb)
+ return -EINVAL;
+
+ bc = g_new0(struct bnep_conn, 1);
+ bc->io = g_io_channel_unix_new(sk);
+ bc->attempts = 0;
+ bc->src = src;
+ bc->dst = dst;
+ bc->conn_cb = conn_cb;
+ bc->data = data;
+
+ err = bnep_setup_conn_req(bc);
+ if (err < 0)
+ return err;
+
+ bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
+ bnep_conn_req_to, bc);
+ g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_setup_cb, bc);
+ return 0;
+}
+
int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/common.h b/profiles/network/common.h
index 9a8caac..9043e46 100644
--- a/profiles/network/common.h
+++ b/profiles/network/common.h
@@ -35,3 +35,8 @@ int bnep_if_up(const char *devname);
int bnep_if_down(const char *devname);
int bnep_add_to_bridge(const char *devname, const char *bridge);
int bnep_del_from_bridge(const char *devname, const char *bridge);
+
+typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
+ void *data);
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5966268..d100580 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -51,8 +51,6 @@
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
-#define CON_SETUP_RETRIES 3
-#define CON_SETUP_TO 9
typedef enum {
CONNECTED,
@@ -73,16 +71,9 @@ struct network_conn {
GIOChannel *io;
guint dc_id;
struct network_peer *peer;
- guint attempt_cnt;
- guint timeout_source;
DBusMessage *connect;
};
-struct __service_16 {
- uint16_t dst;
- uint16_t src;
-} __attribute__ ((packed));
-
static GSList *peers = NULL;
static uint16_t get_service_id(struct btd_service *service)
@@ -163,11 +154,6 @@ static void local_connect_cb(struct network_conn *nc, int err)
static void cancel_connection(struct network_conn *nc, int err)
{
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
btd_service_connecting_complete(nc->service, err);
if (nc->connect)
local_connect_cb(nc, err);
@@ -200,83 +186,24 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
connection_destroy(NULL, user_data);
}
-static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
- gpointer data)
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
{
struct network_conn *nc = data;
- struct bnep_control_rsp *rsp;
- struct timeval timeo;
- char pkt[BNEP_MTU];
- ssize_t r;
- int sk;
const char *path;
DBusConnection *conn;
- DBG("cond %u", cond);
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- error("Hangup or error on l2cap server socket");
- goto failed;
- }
-
- sk = g_io_channel_unix_get_fd(chan);
-
- memset(pkt, 0, BNEP_MTU);
- r = read(sk, pkt, sizeof(pkt) -1);
- if (r < 0) {
- error("IO Channel read error");
- goto failed;
- }
-
- if (r == 0) {
- error("No packet received on l2cap socket");
- goto failed;
- }
-
- errno = EPROTO;
-
- if ((size_t) r < sizeof(*rsp)) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- rsp = (void *) pkt;
- if (rsp->type != BNEP_CONTROL) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
- return TRUE;
-
- r = ntohs(rsp->resp);
-
- if (r != BNEP_SUCCESS) {
- error("bnep failed");
- goto failed;
- }
-
- memset(&timeo, 0, sizeof(timeo));
- timeo.tv_sec = 0;
-
- setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+ DBG("");
- if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
- error("%s could not be added", nc->dev);
+ if (err < 0) {
+ error("connect failed %s", strerror(-err));
goto failed;
}
- bnep_if_up(nc->dev);
+ info("%s connected", nc->dev);
+ memcpy(nc->dev, iface, sizeof(nc->dev));
btd_service_connecting_complete(nc->service, 0);
+
if (nc->connect)
local_connect_cb(nc, 0);
@@ -292,101 +219,30 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
nc->state = CONNECTED;
nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
- nc, NULL);
-
- info("%s connected", nc->dev);
- /* Start watchdog */
+ nc, NULL);
g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) bnep_watchdog_cb, nc);
+ bnep_watchdog_cb, nc);
g_io_channel_unref(nc->io);
nc->io = NULL;
- return FALSE;
+ return;
failed:
cancel_connection(nc, -EIO);
-
- return FALSE;
-}
-
-static int bnep_send_conn_req(struct network_conn *nc)
-{
- struct bnep_setup_conn_req *req;
- struct __service_16 *s;
- unsigned char pkt[BNEP_MTU];
- int fd;
-
- DBG("");
-
- /* Send request */
- req = (void *) pkt;
- req->type = BNEP_CONTROL;
- req->ctrl = BNEP_SETUP_CONN_REQ;
- req->uuid_size = 2; /* 16bit UUID */
- s = (void *) req->service;
- s->dst = htons(nc->id);
- s->src = htons(BNEP_SVC_PANU);
-
- fd = g_io_channel_unix_get_fd(nc->io);
- if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
- int err = -errno;
- error("bnep connection req send failed: %s", strerror(errno));
- return err;
- }
-
- nc->attempt_cnt++;
-
- return 0;
-}
-
-static gboolean bnep_conn_req_to(gpointer user_data)
-{
- struct network_conn *nc;
-
- nc = user_data;
- if (nc->attempt_cnt == CON_SETUP_RETRIES) {
- error("Too many bnep connection attempts");
- } else {
- error("bnep connection setup TO, retrying...");
- if (bnep_send_conn_req(nc) == 0)
- return TRUE;
- }
-
- cancel_connection(nc, -ETIMEDOUT);
-
- return FALSE;
-}
-
-static int bnep_connect(struct network_conn *nc)
-{
- int err;
-
- nc->attempt_cnt = 0;
-
- err = bnep_send_conn_req(nc);
- if (err < 0)
- return err;
-
- nc->timeout_source = g_timeout_add_seconds(CON_SETUP_TO,
- bnep_conn_req_to, nc);
-
- g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- bnep_setup_cb, nc);
-
- return 0;
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct network_conn *nc = data;
- int perr;
+ int sk, perr;
if (err) {
error("%s", err->message);
goto failed;
}
- perr = bnep_connect(nc);
+ sk = g_io_channel_unix_get_fd(nc->io);
+ perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
@@ -692,8 +548,6 @@ int connection_register(struct btd_service *service)
nc = g_new0(struct network_conn, 1);
nc->id = id;
- memset(nc->dev, 0, sizeof(nc->dev));
- strcpy(nc->dev, "bnep%d");
nc->service = btd_service_ref(service);
nc->state = DISCONNECTED;
nc->peer = peer;
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 0050b30..3a7e52a 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -269,9 +269,6 @@ static int server_connadd(struct network_server *ns,
char devname[16];
int err, nsk;
- memset(devname, 0, sizeof(devname));
- strcpy(devname, "bnep%d");
-
nsk = g_io_channel_unix_get_fd(session->io);
err = bnep_connadd(nsk, dst_role, devname);
if (err < 0)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 0/6] Refactor bnep code and implement pan methods
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
v4: Fixed Luiz comments (discussed in irc). Merge patch 1 and 2.
Pass fd in bnep_connect instead of GIOChannel.
v3: Fixed Anderson and Luiz comments and solved rebased conflicts.
v2: Refactored profiles/network/common.* as per Johan's comments
(renaming common.c|h to bnep.c|h and moving bnep related code to
bnep.c ro reduce redundancy in profiles/netowrk/connection.c and
android/pan.c)
v1: This patch set supports PANU role with a minor fix in android. Added
CAP_NET_RAW capability for bnep services. Creates bnep connection and
up the inreface on connect call and free the device on disconnect call.
Interface name(bnepX) will be notified on control state cb. Android
environment will create IP address with dhcp calls.
Ravi kumar Veeramally (6):
profiles/network: Refactor bnep connection setup functionality
profiles/network: Rename common.c|h to bnep.c|h
android/pan: Implement pan connect method in daemon
android/pan: Implement pan disconnect method in daemon
android/pan: Implement the get local role method in daemon
android: Add reasons for adding capabilites to process
Makefile.plugins | 2 +-
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/main.c | 3 +
android/pan.c | 253 ++++++++++++++++++++++++++++++++--
profiles/network/{common.c => bnep.c} | 197 +++++++++++++++++++++++++-
profiles/network/{common.h => bnep.h} | 5 +
profiles/network/connection.c | 174 ++---------------------
profiles/network/manager.c | 2 +-
profiles/network/server.c | 5 +-
10 files changed, 468 insertions(+), 178 deletions(-)
rename profiles/network/{common.c => bnep.c} (58%)
rename profiles/network/{common.h => bnep.h} (87%)
--
1.8.3.2
^ permalink raw reply
* [PATCH v2 9/9] android/socket: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/socket.c | 102 ++++++++++++++++++++++++++-----------------------------
1 file changed, 49 insertions(+), 53 deletions(-)
diff --git a/android/socket.c b/android/socket.c
index 4f47861..76b40c8 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -650,15 +650,15 @@ static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
rfsock_acc->rfcomm_watch);
}
-static int handle_listen(void *buf)
+static void handle_listen(const void *buf, uint16_t len)
{
- struct hal_cmd_sock_listen *cmd = buf;
+ const struct hal_cmd_sock_listen *cmd = buf;
const struct profile_info *profile;
- struct rfcomm_sock *rfsock;
+ struct rfcomm_sock *rfsock = NULL;
BtIOSecLevel sec_level;
GIOChannel *io;
GError *err = NULL;
- int hal_fd;
+ int hal_fd = -1;
int chan;
DBG("");
@@ -666,11 +666,10 @@ static int handle_listen(void *buf)
profile = get_profile_by_uuid(cmd->uuid);
if (!profile) {
if (!cmd->channel)
- return -1;
- else {
- chan = cmd->channel;
- sec_level = BT_IO_SEC_MEDIUM;
- }
+ goto failed;
+
+ chan = cmd->channel;
+ sec_level = BT_IO_SEC_MEDIUM;
} else {
chan = profile->channel;
sec_level = profile->sec_level;
@@ -680,7 +679,7 @@ static int handle_listen(void *buf)
rfsock = create_rfsock(-1, &hal_fd);
if (!rfsock)
- return -1;
+ goto failed;
io = bt_io_listen(accept_cb, NULL, rfsock, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
@@ -690,8 +689,7 @@ static int handle_listen(void *buf)
if (!io) {
error("Failed listen: %s", err->message);
g_error_free(err);
- cleanup_rfsock(rfsock);
- return -1;
+ goto failed;
}
rfsock->real_sock = g_io_channel_unix_get_fd(io);
@@ -703,15 +701,27 @@ static int handle_listen(void *buf)
if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
error("Error sending RFCOMM channel");
- cleanup_rfsock(rfsock);
- return -1;
+ goto failed;
}
rfsock->service_handle = sdp_service_register(profile, cmd->name);
servers = g_list_append(servers, rfsock);
- return hal_fd;
+ ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN, 0, NULL,
+ hal_fd);
+ close(hal_fd);
+ return;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN,
+ HAL_STATUS_FAILED);
+
+ if (rfsock)
+ cleanup_rfsock(rfsock);
+
+ if (hal_fd >= 0)
+ close(hal_fd);
}
static bool sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
@@ -865,9 +875,9 @@ fail:
cleanup_rfsock(rfsock);
}
-static int handle_connect(void *buf)
+static void handle_connect(const void *buf, uint16_t len)
{
- struct hal_cmd_sock_connect *cmd = buf;
+ const struct hal_cmd_sock_connect *cmd = buf;
struct rfcomm_sock *rfsock;
uuid_t uuid;
int hal_fd = -1;
@@ -876,7 +886,7 @@ static int handle_connect(void *buf)
rfsock = create_rfsock(-1, &hal_fd);
if (!rfsock)
- return -1;
+ goto failed;
android2bdaddr(cmd->bdaddr, &rfsock->dst);
@@ -890,55 +900,41 @@ static int handle_connect(void *buf)
sdp_search_cb, rfsock, NULL) < 0) {
error("Failed to search SDP records");
cleanup_rfsock(rfsock);
- return -1;
+ goto failed;
}
- return hal_fd;
-}
-
-void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- int fd;
-
- switch (opcode) {
- case HAL_OP_SOCK_LISTEN:
- fd = handle_listen(buf);
- if (fd < 0)
- break;
-
- ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
-
- if (close(fd) < 0)
- error("close() fd %d failed: %s", fd, strerror(errno));
-
- return;
- case HAL_OP_SOCK_CONNECT:
- fd = handle_connect(buf);
- if (fd < 0)
- break;
-
- ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT, 0, NULL,
+ hal_fd);
+ close(hal_fd);
+ return;
- if (close(fd) < 0)
- error("close() fd %d failed: %s", fd, strerror(errno));
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT,
+ HAL_STATUS_FAILED);
- return;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
-
- ipc_send_rsp(HAL_SERVICE_ID_SOCK, opcode, HAL_STATUS_FAILED);
+ if (hal_fd >= 0)
+ close(hal_fd);
}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_SOCK_LISTEN */
+ { handle_listen, false, sizeof(struct hal_cmd_sock_listen) },
+ /* HAL_OP_SOCK_CONNECT */
+ { handle_connect, false, sizeof(struct hal_cmd_sock_connect) },
+};
+
void bt_socket_register(const bdaddr_t *addr)
{
DBG("");
bacpy(&adapter_addr, addr);
+ ipc_register(HAL_SERVICE_ID_SOCK, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
}
void bt_socket_unregister(void)
{
DBG("");
+
+ ipc_unregister(HAL_SERVICE_ID_SOCK);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 8/9] android/a2dp: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/a2dp.c | 69 +++++++++++++++++++++++++++++-----------------------------
android/a2dp.h | 2 --
2 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index 99aa14d..98c138e 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -164,9 +164,11 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
}
-static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
+static void bt_a2dp_connect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_a2dp_connect *cmd = buf;
struct a2dp_device *dev;
+ uint8_t status;
char addr[18];
bdaddr_t dst;
GSList *l;
@@ -174,14 +176,13 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (l)
- return HAL_STATUS_FAILED;
+ if (l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = a2dp_device_new(&dst);
dev->io = bt_io_connect(signaling_connect_cb, dev, NULL, &err,
@@ -194,7 +195,8 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
error("%s", err->message);
g_error_free(err);
a2dp_device_free(dev);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
ba2str(&dev->dst, addr);
@@ -202,26 +204,29 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTING);
- return HAL_STATUS_SUCCESS;
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_CONNECT, status);
}
-static uint8_t bt_a2dp_disconnect(struct hal_cmd_a2dp_connect *cmd,
- uint16_t len)
+static void bt_a2dp_disconnect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_a2dp_connect *cmd = buf;
+ uint8_t status;
struct a2dp_device *dev;
GSList *l;
bdaddr_t dst;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
@@ -231,28 +236,19 @@ static uint8_t bt_a2dp_disconnect(struct hal_cmd_a2dp_connect *cmd,
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTING);
- return HAL_STATUS_SUCCESS;
-}
-
-void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- uint8_t status = HAL_STATUS_FAILED;
-
- switch (opcode) {
- case HAL_OP_A2DP_CONNECT:
- status = bt_a2dp_connect(buf, len);
- break;
- case HAL_OP_A2DP_DISCONNECT:
- status = bt_a2dp_disconnect(buf, len);
- break;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
+ status = HAL_STATUS_SUCCESS;
- ipc_send_rsp(HAL_SERVICE_ID_A2DP, opcode, status);
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_DISCONNECT, status);
}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_A2DP_CONNECT */
+ { bt_a2dp_connect, false, sizeof(struct hal_cmd_a2dp_connect) },
+ /* HAL_OP_A2DP_DISCONNECT */
+ { bt_a2dp_disconnect, false, sizeof(struct hal_cmd_a2dp_disconnect) },
+};
+
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
struct a2dp_device *dev;
@@ -380,6 +376,9 @@ bool bt_a2dp_register(const bdaddr_t *addr)
}
record_id = rec->handle;
+ ipc_register(HAL_SERVICE_ID_A2DP, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
+
return true;
}
@@ -397,6 +396,8 @@ void bt_a2dp_unregister(void)
g_slist_foreach(devices, a2dp_device_disconnected, NULL);
devices = NULL;
+
+ ipc_unregister(HAL_SERVICE_ID_A2DP);
bt_adapter_remove_record(record_id);
record_id = 0;
diff --git a/android/a2dp.h b/android/a2dp.h
index 2a1eb3c..7e9b2f6 100644
--- a/android/a2dp.h
+++ b/android/a2dp.h
@@ -21,7 +21,5 @@
*
*/
-void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-
bool bt_a2dp_register(const bdaddr_t *addr);
void bt_a2dp_unregister(void);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 7/9] android/pan: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/pan.c | 57 ++++++++++++++++++++++++---------------------------------
android/pan.h | 2 --
2 files changed, 24 insertions(+), 35 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index ea15637..e15235d 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -35,68 +35,59 @@
#include "hal-msg.h"
#include "ipc.h"
-static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
+static void bt_pan_enable(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, HAL_STATUS_FAILED);
}
-static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
+static void bt_pan_get_role(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE,
+ HAL_STATUS_FAILED);
}
-static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+static void bt_pan_connect(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, HAL_STATUS_FAILED);
}
-static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
- uint16_t len)
+static void bt_pan_disconnect(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT,
+ HAL_STATUS_FAILED);
}
-void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- uint8_t status = HAL_STATUS_FAILED;
-
- switch (opcode) {
- case HAL_OP_PAN_ENABLE:
- status = bt_pan_enable(buf, len);
- break;
- case HAL_OP_PAN_GET_ROLE:
- status = bt_pan_get_role(buf, len);
- break;
- case HAL_OP_PAN_CONNECT:
- status = bt_pan_connect(buf, len);
- break;
- case HAL_OP_PAN_DISCONNECT:
- status = bt_pan_disconnect(buf, len);
- break;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
-
- ipc_send_rsp(HAL_SERVICE_ID_PAN, opcode, status);
-}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_PAN_ENABLE */
+ { bt_pan_enable, false, sizeof(struct hal_cmd_pan_enable) },
+ /* HAL_OP_PAN_GET_ROLE */
+ { bt_pan_get_role, false, 0 },
+ /* HAL_OP_PAN_CONNECT */
+ { bt_pan_connect, false, sizeof(struct hal_cmd_pan_connect) },
+ /* HAL_OP_PAN_DISCONNECT */
+ { bt_pan_disconnect, false, sizeof(struct hal_cmd_pan_disconnect) },
+};
bool bt_pan_register(const bdaddr_t *addr)
{
DBG("");
+ ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
return true;
}
void bt_pan_unregister(void)
{
DBG("");
+
+ ipc_unregister(HAL_SERVICE_ID_PAN);
}
diff --git a/android/pan.h b/android/pan.h
index dd18f68..3178d88 100644
--- a/android/pan.h
+++ b/android/pan.h
@@ -21,7 +21,5 @@
*
*/
-void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-
bool bt_pan_register(const bdaddr_t *addr);
void bt_pan_unregister(void);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 6/9] android/hidhost: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/hidhost.c | 309 ++++++++++++++++++++++++++++++++----------------------
android/hidhost.h | 2 -
2 files changed, 184 insertions(+), 127 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 44310ed..38194d0 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -720,10 +720,11 @@ fail:
hid_device_free(dev);
}
-static uint8_t bt_hid_connect(struct hal_cmd_hidhost_connect *cmd,
- uint16_t len)
+static void bt_hid_connect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_connect *cmd = buf;
struct hid_device *dev;
+ uint8_t status;
char addr[18];
bdaddr_t dst;
GSList *l;
@@ -731,14 +732,13 @@ static uint8_t bt_hid_connect(struct hal_cmd_hidhost_connect *cmd,
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (l)
- return HAL_STATUS_FAILED;
+ if (l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = g_new0(struct hid_device, 1);
bacpy(&dev->dst, &dst);
@@ -752,32 +752,36 @@ static uint8_t bt_hid_connect(struct hal_cmd_hidhost_connect *cmd,
hid_sdp_search_cb, dev, NULL) < 0) {
error("Failed to search sdp details");
hid_device_free(dev);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
devices = g_slist_append(devices, dev);
bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTING);
- return HAL_STATUS_SUCCESS;
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT, status);
}
-static uint8_t bt_hid_disconnect(struct hal_cmd_hidhost_disconnect *cmd,
- uint16_t len)
+static void bt_hid_disconnect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_disconnect *cmd = buf;
struct hid_device *dev;
+ uint8_t status;
GSList *l;
bdaddr_t dst;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
@@ -790,33 +794,38 @@ static uint8_t bt_hid_disconnect(struct hal_cmd_hidhost_disconnect *cmd,
bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING);
- return HAL_STATUS_SUCCESS;
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT, status);
}
-static uint8_t bt_hid_virtual_unplug(struct hal_cmd_hidhost_virtual_unplug *cmd,
- uint16_t len)
+static void bt_hid_virtual_unplug(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_virtual_unplug *cmd = buf;
struct hid_device *dev;
GSList *l;
+ uint8_t status;
bdaddr_t dst;
uint8_t hdr;
int fd;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
- if (!(dev->ctrl_io))
- return HAL_STATUS_FAILED;
+ if (!(dev->ctrl_io)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
hdr = HID_MSG_CONTROL | HID_VIRTUAL_CABLE_UNPLUG;
@@ -825,7 +834,8 @@ static uint8_t bt_hid_virtual_unplug(struct hal_cmd_hidhost_virtual_unplug *cmd,
if (write(fd, &hdr, sizeof(hdr)) < 0) {
error("error writing virtual unplug command: %s (%d)",
strerror(errno), errno);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
/* Wait either channels to HUP */
@@ -837,10 +847,14 @@ static uint8_t bt_hid_virtual_unplug(struct hal_cmd_hidhost_virtual_unplug *cmd,
bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING);
- return HAL_STATUS_SUCCESS;
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_VIRTUAL_UNPLUG,
+ status);
}
-static uint8_t bt_hid_info(struct hal_cmd_hidhost_set_info *cmd, uint16_t len)
+static void bt_hid_info(const void *buf, uint16_t len)
{
/* Data from hal_cmd_hidhost_set_info is usefull only when we create
* UHID device. Once device is created all the transactions will be
@@ -848,33 +862,36 @@ static uint8_t bt_hid_info(struct hal_cmd_hidhost_set_info *cmd, uint16_t len)
* once device is created with HID internals. */
DBG("Not supported");
- return HAL_STATUS_UNSUPPORTED;
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
+ HAL_STATUS_UNSUPPORTED);
}
-static uint8_t bt_hid_get_protocol(struct hal_cmd_hidhost_get_protocol *cmd,
- uint16_t len)
+static void bt_hid_get_protocol(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_get_protocol *cmd = buf;
struct hid_device *dev;
GSList *l;
bdaddr_t dst;
int fd;
uint8_t hdr;
+ uint8_t status;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
- if (dev->boot_dev)
- return HAL_STATUS_UNSUPPORTED;
+ if (dev->boot_dev) {
+ status = HAL_STATUS_UNSUPPORTED;
+ goto failed;
+ }
hdr = HID_MSG_GET_PROTOCOL | cmd->mode;
fd = g_io_channel_unix_get_fd(dev->ctrl_io);
@@ -882,37 +899,45 @@ static uint8_t bt_hid_get_protocol(struct hal_cmd_hidhost_get_protocol *cmd,
if (write(fd, &hdr, sizeof(hdr)) < 0) {
error("error writing device_get_protocol: %s (%d)",
strerror(errno), errno);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
dev->last_hid_msg = HID_MSG_GET_PROTOCOL;
- return HAL_STATUS_SUCCESS;
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_PROTOCOL,
+ status);
}
-static uint8_t bt_hid_set_protocol(struct hal_cmd_hidhost_set_protocol *cmd,
- uint16_t len)
+static void bt_hid_set_protocol(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_set_protocol *cmd = buf;
struct hid_device *dev;
GSList *l;
bdaddr_t dst;
int fd;
uint8_t hdr;
+ uint8_t status;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
- if (dev->boot_dev)
- return HAL_STATUS_UNSUPPORTED;
+ if (dev->boot_dev) {
+ status = HAL_STATUS_UNSUPPORTED;
+ goto failed;
+ }
hdr = HID_MSG_SET_PROTOCOL | cmd->mode;
fd = g_io_channel_unix_get_fd(dev->ctrl_io);
@@ -920,39 +945,47 @@ static uint8_t bt_hid_set_protocol(struct hal_cmd_hidhost_set_protocol *cmd,
if (write(fd, &hdr, sizeof(hdr)) < 0) {
error("error writing device_set_protocol: %s (%d)",
strerror(errno), errno);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
dev->last_hid_msg = HID_MSG_SET_PROTOCOL;
- return HAL_STATUS_SUCCESS;
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_PROTOCOL,
+ status);
}
-static uint8_t bt_hid_get_report(struct hal_cmd_hidhost_get_report *cmd,
- uint16_t len)
+static void bt_hid_get_report(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_get_report *cmd = buf;
struct hid_device *dev;
GSList *l;
bdaddr_t dst;
int fd;
uint8_t *req;
uint8_t req_size;
+ uint8_t status;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
req_size = (cmd->buf_size > 0) ? 4 : 2;
req = g_try_malloc0(req_size);
- if (!req)
- return HAL_STATUS_NOMEM;
+ if (!req) {
+ status = HAL_STATUS_NOMEM;
+ goto failed;
+ }
req[0] = HID_MSG_GET_REPORT | cmd->type;
req[1] = cmd->id;
@@ -968,44 +1001,60 @@ static uint8_t bt_hid_get_report(struct hal_cmd_hidhost_get_report *cmd,
error("error writing hid_get_report: %s (%d)",
strerror(errno), errno);
g_free(req);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
dev->last_hid_msg = HID_MSG_GET_REPORT;
g_free(req);
- return HAL_STATUS_SUCCESS;
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT, status);
}
-static uint8_t bt_hid_set_report(struct hal_cmd_hidhost_set_report *cmd,
- uint16_t len)
+static void bt_hid_set_report(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_set_report *cmd = buf;
struct hid_device *dev;
GSList *l;
bdaddr_t dst;
int i, fd;
uint8_t *req;
uint8_t req_size;
+ uint8_t status;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
+ if (len != sizeof(*cmd) + cmd->len) {
+ error("Invalid hid set report size (%u bytes), terminating",
+ len);
+ raise(SIGTERM);
+ return;
+ }
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
- if (!(dev->ctrl_io))
- return HAL_STATUS_FAILED;
+ if (!(dev->ctrl_io)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
req_size = 1 + (cmd->len / 2);
req = g_try_malloc0(req_size);
- if (!req)
- return HAL_STATUS_NOMEM;
+ if (!req) {
+ status = HAL_STATUS_NOMEM;
+ goto failed;
+ }
req[0] = HID_MSG_SET_REPORT | cmd->type;
/* Report data coming to HAL is in ascii format, HAL sends
@@ -1019,44 +1068,60 @@ static uint8_t bt_hid_set_report(struct hal_cmd_hidhost_set_report *cmd,
error("error writing hid_set_report: %s (%d)",
strerror(errno), errno);
g_free(req);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
dev->last_hid_msg = HID_MSG_SET_REPORT;
g_free(req);
- return HAL_STATUS_SUCCESS;
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT, status);
}
-static uint8_t bt_hid_send_data(struct hal_cmd_hidhost_send_data *cmd,
- uint16_t len)
+static void bt_hid_send_data(const void *buf, uint16_t len)
{
+ const struct hal_cmd_hidhost_send_data *cmd = buf;
struct hid_device *dev;
GSList *l;
bdaddr_t dst;
int i, fd;
uint8_t *req;
uint8_t req_size;
+ uint8_t status;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
+ if (len != sizeof(*cmd) + cmd->len) {
+ error("Invalid hid send data size (%u bytes), terminating",
+ len);
+ raise(SIGTERM);
+ return;
+ }
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
- if (!(dev->intr_io))
- return HAL_STATUS_FAILED;
+ if (!(dev->intr_io)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
req_size = 1 + (cmd->len / 2);
req = g_try_malloc0(req_size);
- if (!req)
- return HAL_STATUS_NOMEM;
+ if (!req) {
+ status = HAL_STATUS_NOMEM;
+ goto failed;
+ }
req[0] = HID_MSG_DATA | HID_DATA_TYPE_OUTPUT;
/* Report data coming to HAL is in ascii format, HAL sends
@@ -1070,53 +1135,42 @@ static uint8_t bt_hid_send_data(struct hal_cmd_hidhost_send_data *cmd,
error("error writing data to HID device: %s (%d)",
strerror(errno), errno);
g_free(req);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
g_free(req);
- return HAL_STATUS_SUCCESS;
-}
-void bt_hid_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- uint8_t status = HAL_STATUS_FAILED;
+ status = HAL_STATUS_SUCCESS;
- switch (opcode) {
- case HAL_OP_HIDHOST_CONNECT:
- status = bt_hid_connect(buf, len);
- break;
- case HAL_OP_HIDHOST_DISCONNECT:
- status = bt_hid_disconnect(buf, len);
- break;
- case HAL_OP_HIDHOST_VIRTUAL_UNPLUG:
- status = bt_hid_virtual_unplug(buf, len);
- break;
- case HAL_OP_HIDHOST_SET_INFO:
- status = bt_hid_info(buf, len);
- break;
- case HAL_OP_HIDHOST_GET_PROTOCOL:
- status = bt_hid_get_protocol(buf, len);
- break;
- case HAL_OP_HIDHOST_SET_PROTOCOL:
- status = bt_hid_set_protocol(buf, len);
- break;
- case HAL_OP_HIDHOST_GET_REPORT:
- status = bt_hid_get_report(buf, len);
- break;
- case HAL_OP_HIDHOST_SET_REPORT:
- status = bt_hid_set_report(buf, len);
- break;
- case HAL_OP_HIDHOST_SEND_DATA:
- status = bt_hid_send_data(buf, len);
- break;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
-
- ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, opcode, status);
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA, status);
}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_HIDHOST_CONNECT */
+ { bt_hid_connect, false, sizeof(struct hal_cmd_hidhost_connect) },
+ /* HAL_OP_HIDHOST_DISCONNECT */
+ { bt_hid_disconnect, false, sizeof(struct hal_cmd_hidhost_disconnect) },
+ /* HAL_OP_HIDHOST_VIRTUAL_UNPLUG */
+ { bt_hid_virtual_unplug, false,
+ sizeof(struct hal_cmd_hidhost_virtual_unplug) },
+ /* HAL_OP_HIDHOST_SET_INFO */
+ { bt_hid_info, true, sizeof(struct hal_cmd_hidhost_set_info) },
+ /* HAL_OP_HIDHOST_GET_PROTOCOL */
+ { bt_hid_get_protocol, false,
+ sizeof(struct hal_cmd_hidhost_get_protocol) },
+ /* HAL_OP_HIDHOST_SET_PROTOCOL */
+ { bt_hid_set_protocol, false,
+ sizeof(struct hal_cmd_hidhost_get_protocol) },
+ /* HAL_OP_HIDHOST_GET_REPORT */
+ { bt_hid_get_report, false, sizeof(struct hal_cmd_hidhost_get_report) },
+ /* HAL_OP_HIDHOST_SET_REPORT */
+ { bt_hid_set_report, true, sizeof(struct hal_cmd_hidhost_set_report) },
+ /* HAL_OP_HIDHOST_SEND_DATA */
+ { bt_hid_send_data, true, sizeof(struct hal_cmd_hidhost_send_data) },
+};
+
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
struct hid_device *dev;
@@ -1224,6 +1278,9 @@ bool bt_hid_register(const bdaddr_t *addr)
return false;
}
+ ipc_register(HAL_SERVICE_ID_HIDHOST, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
+
return true;
}
@@ -1253,4 +1310,6 @@ void bt_hid_unregister(void)
g_io_channel_unref(intr_io);
intr_io = NULL;
}
+
+ ipc_unregister(HAL_SERVICE_ID_HIDHOST);
}
diff --git a/android/hidhost.h b/android/hidhost.h
index b5545fb..ea14446 100644
--- a/android/hidhost.h
+++ b/android/hidhost.h
@@ -21,7 +21,5 @@
*
*/
-void bt_hid_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-
bool bt_hid_register(const bdaddr_t *addr);
void bt_hid_unregister(void);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 5/9] android/bluetooth: Make property handling function return HAL status
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
This makes funtions follow have similar style and makes properties
dispatch function much simpler.
---
android/bluetooth.c | 85 +++++++++++++++++++----------------------------------
1 file changed, 30 insertions(+), 55 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index eb8dbc5..a39e7bf 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1133,7 +1133,7 @@ static void uuid16_to_uint128(uint16_t uuid, uint128_t *u128)
ntoh128(&uuid128.value.uuid128, u128);
}
-static bool get_uuids(void)
+static uint8_t get_uuids(void)
{
struct hal_ev_adapter_props_changed *ev;
GSList *list = adapter.uuids;
@@ -1169,7 +1169,7 @@ static bool get_uuids(void)
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
sizeof(buf), ev);
- return true;
+ return HAL_STATUS_SUCCESS;
}
static void remove_uuid_complete(uint8_t status, uint16_t length,
@@ -1691,7 +1691,7 @@ static bool set_discoverable(uint8_t mode, uint16_t timeout)
return false;
}
-static void get_address(void)
+static uint8_t get_address(void)
{
uint8_t buf[BASELEN_PROP_CHANGED + sizeof(bdaddr_t)];
struct hal_ev_adapter_props_changed *ev = (void *) buf;
@@ -1705,65 +1705,67 @@ static void get_address(void)
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
sizeof(buf), buf);
+
+ return HAL_STATUS_SUCCESS;
}
-static bool get_name(void)
+static uint8_t get_name(void)
{
if (!adapter.name)
- return false;
+ return HAL_STATUS_FAILED;
adapter_name_changed((uint8_t *) adapter.name);
- return true;
+ return HAL_STATUS_SUCCESS;
}
-static bool get_class(void)
+static uint8_t get_class(void)
{
DBG("");
adapter_class_changed();
- return true;
+ return HAL_STATUS_SUCCESS;
}
-static bool get_type(void)
+static uint8_t get_type(void)
{
DBG("Not implemented");
/* TODO: Add implementation */
- return false;
+ return HAL_STATUS_FAILED;
}
-static bool get_service(void)
+static uint8_t get_service(void)
{
DBG("Not implemented");
/* TODO: Add implementation */
- return false;
+ return HAL_STATUS_FAILED;
}
-static bool get_scan_mode(void)
+static uint8_t get_scan_mode(void)
{
DBG("");
scan_mode_changed();
- return true;
+ return HAL_STATUS_SUCCESS;
}
-static bool get_devices(void)
+static uint8_t get_devices(void)
{
DBG("Not implemented");
/* TODO: Add implementation */
- return false;
+ return HAL_STATUS_FAILED;
}
-static bool get_discoverable_timeout(void)
+static uint8_t get_discoverable_timeout(void)
{
struct hal_ev_adapter_props_changed *ev;
uint8_t buf[BASELEN_PROP_CHANGED + sizeof(uint32_t)];
@@ -1782,7 +1784,7 @@ static bool get_discoverable_timeout(void)
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
sizeof(buf), ev);
- return true;
+ return HAL_STATUS_SUCCESS;
}
static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
@@ -1792,64 +1794,37 @@ static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
switch (cmd->type) {
case HAL_PROP_ADAPTER_ADDR:
- get_address();
+ status = get_address();
break;
case HAL_PROP_ADAPTER_NAME:
- if (!get_name()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_name();
break;
case HAL_PROP_ADAPTER_UUIDS:
- if (!get_uuids()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_uuids();
break;
case HAL_PROP_ADAPTER_CLASS:
- if (!get_class()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_class();
break;
case HAL_PROP_ADAPTER_TYPE:
- if (!get_type()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_type();
break;
case HAL_PROP_ADAPTER_SERVICE_REC:
- if (!get_service()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_service();
break;
case HAL_PROP_ADAPTER_SCAN_MODE:
- if (!get_scan_mode()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_scan_mode();
break;
case HAL_PROP_ADAPTER_BONDED_DEVICES:
- if (!get_devices()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_devices();
break;
case HAL_PROP_ADAPTER_DISC_TIMEOUT:
- if (!get_discoverable_timeout()) {
- status = HAL_STATUS_FAILED;
- goto failed;
- }
+ status = get_discoverable_timeout();
break;
default:
status = HAL_STATUS_FAILED;
- goto failed;
+ break;
}
- status = HAL_STATUS_SUCCESS;
-
-failed:
ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP, status);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 4/9] android/bluetooth: Use generic IPC msg handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/bluetooth.c | 464 ++++++++++++++++++++++++++++++++++++----------------
1 file changed, 321 insertions(+), 143 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 8a1d444..eb8dbc5 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1361,7 +1361,7 @@ static void set_adapter_name_complete(uint8_t status, uint16_t length,
adapter_set_name(rp->name);
}
-static uint8_t set_adapter_name(uint8_t *name, uint16_t len)
+static uint8_t set_adapter_name(const uint8_t *name, uint16_t len)
{
struct mgmt_cp_set_local_name cp;
@@ -1378,8 +1378,17 @@ static uint8_t set_adapter_name(uint8_t *name, uint16_t len)
return HAL_STATUS_FAILED;
}
-static uint8_t set_discoverable_timeout(uint8_t *timeout)
+static uint8_t set_discoverable_timeout(const void *buf, uint16_t len)
{
+ const uint32_t *timeout = buf;
+
+ if (len != sizeof(*timeout)) {
+ error("Invalid set disc timeout size (%u bytes), terminating",
+ len);
+ raise(SIGTERM);
+ return HAL_STATUS_FAILED;
+ }
+
/* Android handles discoverable timeout in Settings app.
* There is no need to use kernel feature for that.
* Just need to store this value here */
@@ -1776,33 +1785,72 @@ static bool get_discoverable_timeout(void)
return true;
}
-static bool get_property(void *buf, uint16_t len)
+static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_get_adapter_prop *cmd = buf;
+ const struct hal_cmd_get_adapter_prop *cmd = buf;
+ uint8_t status;
switch (cmd->type) {
case HAL_PROP_ADAPTER_ADDR:
get_address();
- return true;
+ break;
case HAL_PROP_ADAPTER_NAME:
- return get_name();
+ if (!get_name()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_UUIDS:
- return get_uuids();
+ if (!get_uuids()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_CLASS:
- return get_class();
+ if (!get_class()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_TYPE:
- return get_type();
+ if (!get_type()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_SERVICE_REC:
- return get_service();
+ if (!get_service()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_SCAN_MODE:
- return get_scan_mode();
+ if (!get_scan_mode()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_BONDED_DEVICES:
- return get_devices();
+ if (!get_devices()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
case HAL_PROP_ADAPTER_DISC_TIMEOUT:
- return get_discoverable_timeout();
+ if (!get_discoverable_timeout()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+ break;
default:
- return false;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP, status);
}
static void get_properties(void)
@@ -1858,11 +1906,18 @@ static bool stop_discovery(void)
return false;
}
-static uint8_t set_scan_mode(void *buf, uint16_t len)
+static uint8_t set_scan_mode(const void *buf, uint16_t len)
{
- uint8_t *mode = buf;
+ const uint8_t *mode = buf;
bool conn, disc, cur_conn, cur_disc;
+ if (len != sizeof(*mode)) {
+ error("Invalid set scan mode size (%u bytes), terminating",
+ len);
+ raise(SIGTERM);
+ return HAL_STATUS_FAILED;
+ }
+
cur_conn = adapter.current_settings & MGMT_SETTING_CONNECTABLE;
cur_disc = adapter.current_settings & MGMT_SETTING_DISCOVERABLE;
@@ -1914,21 +1969,35 @@ done:
return HAL_STATUS_DONE;
}
-static uint8_t set_property(void *buf, uint16_t len)
+static void handle_set_adapter_prop_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_set_adapter_prop *cmd = buf;
+ const struct hal_cmd_set_adapter_prop *cmd = buf;
+ uint8_t status;
+
+ if (len != sizeof(*cmd) + cmd->len) {
+ error("Invalid set adapter prop cmd (0x%x), terminating",
+ cmd->type);
+ raise(SIGTERM);
+ return;
+ }
switch (cmd->type) {
case HAL_PROP_ADAPTER_SCAN_MODE:
- return set_scan_mode(cmd->val, cmd->len);
+ status = set_scan_mode(cmd->val, cmd->len);
+ break;
case HAL_PROP_ADAPTER_NAME:
- return set_adapter_name(cmd->val, cmd->len);
+ status = set_adapter_name(cmd->val, cmd->len);
+ break;
case HAL_PROP_ADAPTER_DISC_TIMEOUT:
- return set_discoverable_timeout(cmd->val);
+ status = set_discoverable_timeout(cmd->val, cmd->len);
+ break;
default:
DBG("Unhandled property type 0x%x", cmd->type);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ break;
}
+
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_ADAPTER_PROP, status);
}
static void pair_device_complete(uint8_t status, uint16_t length,
@@ -1947,9 +2016,10 @@ static void pair_device_complete(uint8_t status, uint16_t length,
HAL_BOND_STATE_NONE);
}
-static bool create_bond(void *buf, uint16_t len)
+static void handle_create_bond_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_create_bond *cmd = buf;
+ const struct hal_cmd_create_bond *cmd = buf;
+ uint8_t status;
struct mgmt_cp_pair_device cp;
cp.io_cap = DEFAULT_IO_CAPABILITY;
@@ -1957,25 +2027,36 @@ static bool create_bond(void *buf, uint16_t len)
android2bdaddr(cmd->bdaddr, &cp.addr.bdaddr);
if (mgmt_send(mgmt_if, MGMT_OP_PAIR_DEVICE, adapter.index, sizeof(cp),
- &cp, pair_device_complete, NULL, NULL) == 0)
- return false;
+ &cp, pair_device_complete, NULL, NULL) == 0) {
+ status = HAL_STATUS_FAILED;
+ goto fail;
+ }
+
+ status = HAL_STATUS_SUCCESS;
set_device_bond_state(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDING);
- return true;
+fail:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CREATE_BOND, status);
}
-static bool cancel_bond(void *buf, uint16_t len)
+static void handle_cancel_bond_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_cancel_bond *cmd = buf;
+ const struct hal_cmd_cancel_bond *cmd = buf;
struct mgmt_addr_info cp;
+ uint8_t status;
cp.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.bdaddr);
- return mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
- sizeof(cp), &cp, NULL, NULL, NULL) > 0;
+ if (mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_BOND, status);
}
static void unpair_device_complete(uint8_t status, uint16_t length,
@@ -1992,23 +2073,30 @@ static void unpair_device_complete(uint8_t status, uint16_t length,
HAL_BOND_STATE_NONE);
}
-static bool remove_bond(void *buf, uint16_t len)
+static void handle_remove_bond_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_remove_bond *cmd = buf;
+ const struct hal_cmd_remove_bond *cmd = buf;
struct mgmt_cp_unpair_device cp;
+ uint8_t status;
cp.disconnect = 1;
cp.addr.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.addr.bdaddr);
- return mgmt_send(mgmt_if, MGMT_OP_UNPAIR_DEVICE, adapter.index,
+ if (mgmt_send(mgmt_if, MGMT_OP_UNPAIR_DEVICE, adapter.index,
sizeof(cp), &cp, unpair_device_complete,
- NULL, NULL) > 0;
+ NULL, NULL) > 0)
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_REMOVE_BOND, status);
}
-static uint8_t pin_reply(void *buf, uint16_t len)
+static void handle_pin_reply_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_pin_reply *cmd = buf;
+ const struct hal_cmd_pin_reply *cmd = buf;
+ uint8_t status;
bdaddr_t bdaddr;
char addr[18];
@@ -2017,8 +2105,10 @@ static uint8_t pin_reply(void *buf, uint16_t len)
DBG("%s accept %u pin_len %u", addr, cmd->accept, cmd->pin_len);
- if (!cmd->accept && cmd->pin_len)
- return HAL_STATUS_INVALID;
+ if (!cmd->accept && cmd->pin_len) {
+ status = HAL_STATUS_INVALID;
+ goto failed;
+ }
if (cmd->accept) {
struct mgmt_cp_pin_code_reply rp;
@@ -2031,8 +2121,10 @@ static uint8_t pin_reply(void *buf, uint16_t len)
memcpy(rp.pin_code, cmd->pin_code, rp.pin_len);
if (mgmt_reply(mgmt_if, MGMT_OP_PIN_CODE_REPLY, adapter.index,
- sizeof(rp), &rp, NULL, NULL, NULL) == 0)
- return HAL_STATUS_FAILED;
+ sizeof(rp), &rp, NULL, NULL, NULL) == 0) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
} else {
struct mgmt_cp_pin_code_neg_reply rp;
@@ -2041,11 +2133,15 @@ static uint8_t pin_reply(void *buf, uint16_t len)
if (mgmt_reply(mgmt_if, MGMT_OP_PIN_CODE_NEG_REPLY,
adapter.index, sizeof(rp), &rp,
- NULL, NULL, NULL) == 0)
- return HAL_STATUS_FAILED;
+ NULL, NULL, NULL) == 0) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
}
- return HAL_STATUS_SUCCESS;
+ status = HAL_STATUS_SUCCESS;
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_PIN_REPLY, status);
}
static uint8_t user_confirm_reply(const bdaddr_t *bdaddr, bool accept)
@@ -2102,11 +2198,11 @@ static uint8_t user_passkey_reply(const bdaddr_t *bdaddr, bool accept,
return HAL_STATUS_SUCCESS;
}
-static uint8_t ssp_reply(void *buf, uint16_t len)
+static void handle_ssp_reply_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_ssp_reply *cmd = buf;
- uint8_t status;
+ const struct hal_cmd_ssp_reply *cmd = buf;
bdaddr_t bdaddr;
+ uint8_t status;
char addr[18];
/* TODO should parameters sanity be verified here? */
@@ -2133,144 +2229,226 @@ static uint8_t ssp_reply(void *buf, uint16_t len)
break;
}
- return status;
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SSP_REPLY, status);
}
-static uint8_t get_remote_services(void *buf, uint16_t len)
+static void handle_get_remote_services_cmd(const void *buf, uint16_t len)
{
- struct hal_cmd_get_remote_services *cmd = buf;
+ const struct hal_cmd_get_remote_services *cmd = buf;
+ uint8_t status;
bdaddr_t addr;
android2bdaddr(&cmd->bdaddr, &addr);
- return browse_remote_sdp(&addr);
+ status = browse_remote_sdp(&addr);
+
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_SERVICES,
+ status);
}
-void bt_bluetooth_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
+static void handle_enable_cmd(const void *buf, uint16_t len)
{
- uint8_t status = HAL_STATUS_FAILED;
+ uint8_t status;
- switch (opcode) {
- case HAL_OP_ENABLE:
- /* Framework expects all properties to be emitted while
- * enabling adapter */
- get_properties();
+ /* Framework expects all properties to be emitted while
+ * enabling adapter */
+ get_properties();
- if (adapter.current_settings & MGMT_SETTING_POWERED) {
- status = HAL_STATUS_DONE;
- goto error;
- }
+ if (adapter.current_settings & MGMT_SETTING_POWERED) {
+ status = HAL_STATUS_DONE;
+ goto failed;
+ }
- if (!set_mode(MGMT_OP_SET_POWERED, 0x01))
- goto error;
+ if (!set_mode(MGMT_OP_SET_POWERED, 0x01)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
- break;
- case HAL_OP_DISABLE:
- if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
- status = HAL_STATUS_DONE;
- goto error;
- }
+ status = HAL_STATUS_SUCCESS;
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_ENABLE, status);
+}
- if (!set_mode(MGMT_OP_SET_POWERED, 0x00))
- goto error;
+static void handle_disable_cmd(const void *buf, uint16_t len)
+{
+ uint8_t status;
- break;
- case HAL_OP_GET_ADAPTER_PROPS:
- get_properties();
+ if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
+ status = HAL_STATUS_DONE;
+ goto failed;
+ }
- break;
- case HAL_OP_GET_ADAPTER_PROP:
- if (!get_property(buf, len))
- goto error;
+ if (!set_mode(MGMT_OP_SET_POWERED, 0x00)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
- break;
- case HAL_OP_SET_ADAPTER_PROP:
- status = set_property(buf, len);
- if (status != HAL_STATUS_SUCCESS && status != HAL_STATUS_DONE)
- goto error;
+ status = HAL_STATUS_SUCCESS;
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DISABLE, status);
+}
- break;
- case HAL_OP_CREATE_BOND:
- if (!create_bond(buf, len))
- goto error;
+static void handle_get_adapter_props_cmd(const void *buf, uint16_t len)
+{
+ get_properties();
- break;
- case HAL_OP_CANCEL_BOND:
- if (!cancel_bond(buf, len))
- goto error;
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROPS,
+ HAL_STATUS_SUCCESS);
+}
- break;
- case HAL_OP_REMOVE_BOND:
- if (!remove_bond(buf, len))
- goto error;
+static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
+{
+ /* TODO */
- break;
- case HAL_OP_PIN_REPLY:
- status = pin_reply(buf, len);
- if (status != HAL_STATUS_SUCCESS)
- goto error;
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROPS,
+ HAL_STATUS_FAILED);
+}
- break;
- case HAL_OP_SSP_REPLY:
- status = ssp_reply(buf, len);
- if (status != HAL_STATUS_SUCCESS)
- goto error;
- break;
- case HAL_OP_START_DISCOVERY:
- if (adapter.discovering) {
- status = HAL_STATUS_DONE;
- goto error;
- }
+static void handle_get_remote_device_prop_cmd(const void *buf, uint16_t len)
+{
+ /* TODO */
- if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
- status = HAL_STATUS_NOT_READY;
- goto error;
- }
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROP,
+ HAL_STATUS_FAILED);
+}
+
+static void handle_set_remote_device_prop_cmd(const void *buf, uint16_t len)
+{
+ const struct hal_cmd_set_remote_device_prop *cmd = buf;
+ uint8_t status;
- if (!start_discovery())
- goto error;
+ if (len != sizeof(*cmd) + cmd->len) {
+ error("Invalid set remote device prop cmd (0x%x), terminating",
+ cmd->type);
+ raise(SIGTERM);
+ return;
+ }
+ /* TODO */
+
+ switch (cmd->type) {
+ default:
+ DBG("Unhandled property type 0x%x", cmd->type);
+ status = HAL_STATUS_FAILED;
break;
- case HAL_OP_CANCEL_DISCOVERY:
- if (!adapter.discovering) {
- status = HAL_STATUS_DONE;
- goto error;
- }
+ }
- if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
- status = HAL_STATUS_NOT_READY;
- goto error;
- }
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_REMOTE_DEVICE_PROP,
+ status);
+}
- if (!stop_discovery())
- goto error;
+static void handle_get_remote_service_rec_cmd(const void *buf, uint16_t len)
+{
+ /* TODO */
- break;
- case HAL_OP_GET_REMOTE_SERVICES:
- status = get_remote_services(buf, len);
- if (status != HAL_STATUS_SUCCESS)
- goto error;
- break;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- goto error;
+ ipc_send_rsp(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)
+{
+ uint8_t status;
+
+ if (adapter.discovering) {
+ status = HAL_STATUS_DONE;
+ goto failed;
}
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, opcode, HAL_STATUS_SUCCESS);
- return;
+ if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
+ status = HAL_STATUS_NOT_READY;
+ goto failed;
+ }
-error:
- error("Error handling command 0x%02x status %u", opcode, status);
+ if (!start_discovery()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
- ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, opcode, status);
+ status = HAL_STATUS_SUCCESS;
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_START_DISCOVERY, status);
}
+static void handle_cancel_discovery_cmd(const void *buf, uint16_t len)
+{
+ uint8_t status;
+
+ if (!adapter.discovering) {
+ status = HAL_STATUS_DONE;
+ goto failed;
+ }
+
+ if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
+ status = HAL_STATUS_NOT_READY;
+ goto failed;
+ }
+
+ if (!stop_discovery()) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_DISCOVERY, status);
+}
+
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_ENABLE */
+ { handle_enable_cmd, false, 0 },
+ /* HAL_OP_DISABLE */
+ { handle_disable_cmd, false, 0 },
+ /* HAL_OP_GET_ADAPTER_PROPS */
+ { handle_get_adapter_props_cmd, false, 0 },
+ /* HAL_OP_GET_ADAPTER_PROP */
+ { handle_get_adapter_prop_cmd, false,
+ sizeof(struct hal_cmd_get_adapter_prop) },
+ /* HAL_OP_SET_ADAPTER_PROP */
+ { handle_set_adapter_prop_cmd, true,
+ sizeof(struct hal_cmd_set_adapter_prop) },
+ /* HAL_OP_GET_REMOTE_DEVICE_PROPS */
+ { handle_get_remote_device_props_cmd, false,
+ sizeof(struct hal_cmd_get_remote_device_props) },
+ /* HAL_OP_GET_REMOTE_DEVICE_PROP */
+ { handle_get_remote_device_prop_cmd, false,
+ sizeof(struct hal_cmd_get_remote_device_prop) },
+ /* HAL_OP_SET_REMOTE_DEVICE_PROP */
+ { handle_set_remote_device_prop_cmd, true,
+ sizeof(struct hal_cmd_set_remote_device_prop) },
+ /* HAL_OP_GET_REMOTE_SERVICE_REC */
+ { handle_get_remote_service_rec_cmd, false,
+ sizeof(struct hal_cmd_get_remote_service_rec) },
+ /* HAL_OP_GET_REMOTE_SERVICES */
+ { handle_get_remote_services_cmd, false,
+ sizeof(struct hal_cmd_get_remote_services) },
+ /* HAL_OP_START_DISCOVERY */
+ { handle_start_discovery_cmd, false, 0 },
+ /* HAL_OP_CANCEL_DISCOVERY */
+ { handle_cancel_discovery_cmd, false, 0 },
+ /* HAL_OP_CREATE_BOND */
+ { handle_create_bond_cmd, false, sizeof(struct hal_cmd_create_bond) },
+ /* HAL_OP_REMOVE_BOND */
+ { handle_remove_bond_cmd, false, sizeof(struct hal_cmd_remove_bond) },
+ /* HAL_OP_CANCEL_BOND */
+ {handle_cancel_bond_cmd, false, sizeof(struct hal_cmd_cancel_bond) },
+ /* HAL_OP_PIN_REPLY */
+ { handle_pin_reply_cmd, false, sizeof(struct hal_cmd_pin_reply) },
+ /* HAL_OP_SSP_REPLY */
+ { handle_ssp_reply_cmd, false, sizeof(struct hal_cmd_ssp_reply) },
+};
+
void bt_bluetooth_register(void)
{
DBG("");
+
+ ipc_register(HAL_SERVICE_ID_BLUETOOTH, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
}
void bt_bluetooth_unregister(void)
{
DBG("");
+
+ ipc_unregister(HAL_SERVICE_ID_CORE);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 3/9] android/main: Use common exit path in core service functions
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
This makes functions exit path simpler.
---
android/main.c | 40 +++++++++++++++++++++++++---------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/android/main.c b/android/main.c
index a08e281..91fa629 100644
--- a/android/main.c
+++ b/android/main.c
@@ -77,9 +77,12 @@ static bool services[HAL_SERVICE_ID_MAX + 1] = { false };
static void service_register(const void *buf, uint16_t len)
{
const struct hal_cmd_register_module *m = buf;
+ uint8_t status;
- if (m->service_id > HAL_SERVICE_ID_MAX || services[m->service_id])
+ if (m->service_id > HAL_SERVICE_ID_MAX || services[m->service_id]) {
+ status = HAL_STATUS_FAILED;
goto failed;
+ }
switch (m->service_id) {
case HAL_SERVICE_ID_BLUETOOTH:
@@ -91,43 +94,51 @@ static void service_register(const void *buf, uint16_t len)
break;
case HAL_SERVICE_ID_HIDHOST:
- if (!bt_hid_register(&adapter_bdaddr))
+ if (!bt_hid_register(&adapter_bdaddr)) {
+ status = HAL_STATUS_FAILED;
goto failed;
+ }
break;
case HAL_SERVICE_ID_A2DP:
- if (!bt_a2dp_register(&adapter_bdaddr))
+ if (!bt_a2dp_register(&adapter_bdaddr)) {
+ status = HAL_STATUS_FAILED;
goto failed;
+ }
break;
case HAL_SERVICE_ID_PAN:
- if (!bt_pan_register(&adapter_bdaddr))
+ if (!bt_pan_register(&adapter_bdaddr)) {
+ status = HAL_STATUS_FAILED;
goto failed;
+ }
break;
default:
DBG("service %u not supported", m->service_id);
+ status = HAL_STATUS_FAILED;
goto failed;
}
services[m->service_id] = true;
- ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
- HAL_STATUS_SUCCESS);
+ status = HAL_STATUS_SUCCESS;
info("Service ID=%u registered", m->service_id);
- return;
+
failed:
- ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE, status);
}
static void service_unregister(const void *buf, uint16_t len)
{
const struct hal_cmd_unregister_module *m = buf;
+ uint8_t status;
- if (m->service_id > HAL_SERVICE_ID_MAX || !services[m->service_id])
+ if (m->service_id > HAL_SERVICE_ID_MAX || !services[m->service_id]) {
+ status = HAL_STATUS_FAILED;
goto failed;
+ }
switch (m->service_id) {
case HAL_SERVICE_ID_BLUETOOTH:
@@ -149,19 +160,18 @@ static void service_unregister(const void *buf, uint16_t len)
/* This would indicate bug in HAL, as unregister should not be
* called in init failed */
DBG("service %u not supported", m->service_id);
+ status = HAL_STATUS_FAILED;
goto failed;
}
services[m->service_id] = false;
- ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
- HAL_STATUS_SUCCESS);
+ status = HAL_STATUS_SUCCESS;
info("Service ID=%u unregistered", m->service_id);
- return;
+
failed:
- ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
- HAL_STATUS_FAILED);
+ ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE, status);
}
static const struct ipc_handler cmd_handlers[] = {
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 2/9] android/main: Use generic IPC message handling for core service
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on daemon start and unregistered on shutdown.
---
android/main.c | 83 +++++++++++-----------------------------------------------
1 file changed, 16 insertions(+), 67 deletions(-)
diff --git a/android/main.c b/android/main.c
index 3a14af5..a08e281 100644
--- a/android/main.c
+++ b/android/main.c
@@ -74,9 +74,9 @@ static GIOChannel *hal_notif_io = NULL;
static bool services[HAL_SERVICE_ID_MAX + 1] = { false };
-static void service_register(void *buf, uint16_t len)
+static void service_register(const void *buf, uint16_t len)
{
- struct hal_cmd_register_module *m = buf;
+ const struct hal_cmd_register_module *m = buf;
if (m->service_id > HAL_SERVICE_ID_MAX || services[m->service_id])
goto failed;
@@ -122,9 +122,9 @@ failed:
HAL_STATUS_FAILED);
}
-static void service_unregister(void *buf, uint16_t len)
+static void service_unregister(const void *buf, uint16_t len)
{
- struct hal_cmd_unregister_module *m = buf;
+ const struct hal_cmd_unregister_module *m = buf;
if (m->service_id > HAL_SERVICE_ID_MAX || !services[m->service_id])
goto failed;
@@ -164,20 +164,12 @@ failed:
HAL_STATUS_FAILED);
}
-static void handle_service_core(uint8_t opcode, void *buf, uint16_t len)
-{
- switch (opcode) {
- case HAL_OP_REGISTER_MODULE:
- service_register(buf, len);
- break;
- case HAL_OP_UNREGISTER_MODULE:
- service_unregister(buf, len);
- break;
- default:
- ipc_send_rsp(HAL_SERVICE_ID_CORE, opcode, HAL_STATUS_FAILED);
- break;
- }
-}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_REGISTER_MODULE */
+ { service_register, false, sizeof(struct hal_cmd_register_module) },
+ /* HAL_OP_UNREGISTER_MODULE */
+ { service_unregister, false, sizeof(struct hal_cmd_unregister_module) },
+};
static void bluetooth_stopped(void)
{
@@ -211,7 +203,6 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
char buf[BLUEZ_HAL_MTU];
- struct hal_hdr *msg = (void *) buf;
ssize_t ret;
int fd;
@@ -229,51 +220,7 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
goto fail;
}
- if (ret < (ssize_t) sizeof(*msg)) {
- error("HAL command too small, terminating (%zd)", ret);
- goto fail;
- }
-
- if (ret != (ssize_t) (sizeof(*msg) + msg->len)) {
- error("Malformed HAL command (%zd bytes), terminating", ret);
- goto fail;
- }
-
- DBG("service_id %u opcode %u len %u", msg->service_id, msg->opcode,
- msg->len);
-
- if (msg->service_id > HAL_SERVICE_ID_MAX ||
- !services[msg->service_id]) {
- error("HAL command for unregistered service %u, terminating",
- msg->service_id);
- goto fail;
- }
-
- switch (msg->service_id) {
- case HAL_SERVICE_ID_CORE:
- handle_service_core(msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_BLUETOOTH:
- bt_bluetooth_handle_cmd(fd, msg->opcode, msg->payload,
- msg->len);
- break;
- case HAL_SERVICE_ID_HIDHOST:
- bt_hid_handle_cmd(fd, msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_SOCK:
- bt_sock_handle_cmd(fd, msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_A2DP:
- bt_a2dp_handle_cmd(fd, msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_PAN:
- bt_pan_handle_cmd(fd, msg->opcode, msg->payload, msg->len);
- break;
- default:
- ipc_send_rsp(msg->service_id, msg->opcode, HAL_STATUS_FAILED);
- break;
- }
-
+ ipc_handle_msg(buf, ret);
return TRUE;
fail:
@@ -565,9 +512,6 @@ int main(int argc, char *argv[])
GError *err = NULL;
guint signal;
- /* Core Service (ID=0) should always be considered registered */
- services[0] = true;
-
context = g_option_context_new(NULL);
g_option_context_add_main_entries(context, options, NULL);
@@ -619,6 +563,9 @@ 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,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
+
DBG("Entering main loop");
event_loop = g_main_loop_new(NULL, FALSE);
@@ -637,6 +584,8 @@ int main(int argc, char *argv[])
bt_bluetooth_cleanup();
g_main_loop_unref(event_loop);
+ ipc_unregister(HAL_SERVICE_ID_CORE);
+
info("Exit");
__btd_log_cleanup();
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 1/9] android: Add initial code for IPC message handlers
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
This will allow to register and unregister handlers for IPC messages
Basic sanity check will be done in common code. Commands with variable
length will be verified against minimum size only.
---
android/ipc.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
android/ipc.h | 10 ++++++++
2 files changed, 88 insertions(+)
diff --git a/android/ipc.c b/android/ipc.c
index 64b0db5..56f328b 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -30,12 +30,20 @@
#include <stdint.h>
#include <string.h>
#include <signal.h>
+#include <stdbool.h>
#include <sys/socket.h>
#include "hal-msg.h"
#include "ipc.h"
#include "log.h"
+struct service_handler {
+ const struct ipc_handler *handler;
+ uint8_t size;
+};
+
+static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
+
static int cmd_sk = -1;
static int notif_sk = -1;
@@ -124,3 +132,73 @@ void ipc_send_notif(uint8_t service_id, uint8_t opcode, uint16_t len,
ipc_send(notif_sk, service_id, opcode, len, param, -1);
}
+
+void ipc_register(uint8_t service, const struct ipc_handler *handlers,
+ uint8_t size)
+{
+ services[service].handler = handlers;
+ services[service].size = size;
+}
+
+void ipc_unregister(uint8_t service)
+{
+ services[service].handler = NULL;
+ services[service].size = 0;
+}
+
+void ipc_handle_msg(const void *buf, ssize_t len)
+{
+ const struct hal_hdr *msg = buf;
+ const struct ipc_handler *handler;
+
+ if (len < (ssize_t) sizeof(*msg)) {
+ error("IPC: message too small (%zd bytes), terminating", len);
+ raise(SIGTERM);
+ return;
+ }
+
+ if (len != (ssize_t) (sizeof(*msg) + msg->len)) {
+ error("IPC: message malformed (%zd bytes), terminating", len);
+ raise(SIGTERM);
+ return;
+ }
+
+ /* if service is valid */
+ if (msg->service_id > HAL_SERVICE_ID_MAX) {
+ error("IPC: unknown service (0x%x), terminating",
+ msg->service_id);
+ raise(SIGTERM);
+ return;
+ }
+
+ /* if service is registered */
+ if (!services[msg->service_id].handler) {
+ error("IPC: unregistered service (0x%x), terminating",
+ msg->service_id);
+ raise(SIGTERM);
+ return;
+ }
+
+ /* if opcode is valid */
+ if (msg->opcode == HAL_OP_STATUS ||
+ msg->opcode > services[msg->service_id].size) {
+ error("IPC: invalid opcode 0x%x for service 0x%x, terminating",
+ msg->opcode, msg->service_id);
+ raise(SIGTERM);
+ return;
+ }
+
+ /* opcode is table offset + 1 */
+ handler = &services[msg->service_id].handler[msg->opcode - 1];
+
+ /* if payload size is valid */
+ if ((handler->var_len && handler->data_len > msg->len) ||
+ (!handler->var_len && handler->data_len != msg->len)) {
+ error("IPC: size invalid opcode 0x%x service 0x%x, terminating",
+ msg->service_id, msg->opcode);
+ raise(SIGTERM);
+ return;
+ }
+
+ handler->handler(msg->payload, msg->len);
+}
diff --git a/android/ipc.h b/android/ipc.h
index f66c9e0..9d0c5e1 100644
--- a/android/ipc.h
+++ b/android/ipc.h
@@ -21,6 +21,11 @@
*
*/
+struct ipc_handler {
+ void (*handler) (const void *buf, uint16_t len);
+ bool var_len;
+ size_t data_len;
+};
void ipc_init(int command_sk, int notification_sk);
void ipc_cleanup(void);
@@ -29,3 +34,8 @@ 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_register(uint8_t service, const struct ipc_handler *handlers,
+ uint8_t size);
+void ipc_unregister(uint8_t service);
+
+void ipc_handle_msg(const void *buf, ssize_t len);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 0/9] android: IPC improvements - daemon part
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
v2:
- rebased against latest IPC helpers improvements
- more compact command handlers table format
- error handling path in command handlers improved according to Johan comments
- randmon small fixes
- patches not directly related to refactor removed from serie, will
be send after this is merged
v1:
This serie implements IPC message handling iprovments in daemon similar
to what is already done in HAL part.
--
BR
Szymon Janc
Szymon Janc (9):
android: Add initial code for IPC message handlers
android/main: Use generic IPC message handling for core service
android/main: Use common exit path in core service functions
android/bluetooth: Use generic IPC msg handling for commands
android/bluetooth: Make property handling function return HAL status
android/hidhost: Use generic IPC message handling for commands
android/pan: Use generic IPC message handling for commands
android/a2dp: Use generic IPC message handling for commands
android/socket: Use generic IPC message handling for commands
android/a2dp.c | 69 ++++----
android/a2dp.h | 2 -
android/bluetooth.c | 477 ++++++++++++++++++++++++++++++++++------------------
android/hidhost.c | 309 ++++++++++++++++++++--------------
android/hidhost.h | 2 -
android/ipc.c | 78 +++++++++
android/ipc.h | 10 ++
android/main.c | 123 +++++---------
android/pan.c | 57 +++----
android/pan.h | 2 -
android/socket.c | 102 ++++++-----
11 files changed, 736 insertions(+), 495 deletions(-)
--
1.8.3.2
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox