* [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
* [PATCH_v3 7/7] android: Add reasons for adding capabilites to process
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-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_v3 6/7] android/pan: Implement the get local role method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-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 cb22fea..87ae622 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -277,9 +277,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_v3 5/7] android/pan: Implement pan disconnect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-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 7fe40da..cb22fea 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -237,9 +237,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_v3 4/7] android/pan: Implement pan connect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-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 | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 215 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..7fe40da 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -29,35 +29,227 @@
#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;
+
+ 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;
+
+ perr = bnep_connect(np->io, 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 +283,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_v3 3/7] profiles/network: Rename common.c|h to bnep.c|h
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-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 fd25d96..03f9f57 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 5723afd..6ad0277 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_v3 2/7] profiles/network: Refactor bnep connection setup functionality
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-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 | 178 ++++++++++++++++++++++++++++++++++++++++++
profiles/network/common.h | 5 ++
profiles/network/connection.c | 167 +++------------------------------------
3 files changed, 194 insertions(+), 156 deletions(-)
diff --git a/profiles/network/common.c b/profiles/network/common.c
index c2da925..fd25d96 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,21 @@ 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;
+};
+
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -215,6 +233,166 @@ 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);
+ g_free(bc);
+
+ return FALSE;
+
+failed:
+ bc->conn_cb(NULL, NULL, -EIO, bc->data);
+ g_free(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);
+ g_free(bc);
+
+ return FALSE;
+}
+
+int bnep_connect(GIOChannel *io, uint16_t src, uint16_t dst,
+ bnep_connect_cb conn_cb, void *data)
+{
+ struct bnep_conn *bc;
+ int err;
+
+ if (!io || !conn_cb)
+ return -EINVAL;
+
+ bc = g_new0(struct bnep_conn, 1);
+ bc->io = io;
+ 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..11db828 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(GIOChannel *io, 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 301f66d..5723afd 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,88 +219,16 @@ 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)
@@ -386,7 +241,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
goto failed;
}
- perr = bnep_connect(nc);
+ perr = bnep_connect(nc->io, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v3 1/7] profiles/network: Remove redundant code for bnep interface name
From: Ravi kumar Veeramally @ 2013-11-29 9:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385718846-19070-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Remove redundant code for copying bnepX interface name from connection
and server files. It is better to place on actual function call.
---
profiles/network/common.c | 4 ++--
profiles/network/connection.c | 2 --
profiles/network/server.c | 3 ---
3 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/profiles/network/common.c b/profiles/network/common.c
index 0b291bd..c2da925 100644
--- a/profiles/network/common.c
+++ b/profiles/network/common.c
@@ -149,9 +149,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) {
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5966268..301f66d 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -692,8 +692,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_v3 0/7] Refactor bnep code and implement pan methods
From: Ravi kumar Veeramally @ 2013-11-29 9:53 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
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 (7):
profiles/network: Remove redundant code for bnep interface name
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 | 252 ++++++++++++++++++++++++++++++++--
profiles/network/{common.c => bnep.c} | 184 ++++++++++++++++++++++++-
profiles/network/{common.h => bnep.h} | 5 +
profiles/network/connection.c | 171 ++---------------------
profiles/network/manager.c | 2 +-
profiles/network/server.c | 5 +-
10 files changed, 452 insertions(+), 177 deletions(-)
rename profiles/network/{common.c => bnep.c} (59%)
rename profiles/network/{common.h => bnep.h} (87%)
--
1.8.3.2
^ permalink raw reply
* [PATCHv2] android/socket: Cleanup sockets on unregister
From: Andrei Emeltchenko @ 2013-11-29 9:33 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This cleans up rfsock structures closing all sockets and making general cleanup
for servers and for connections. This will be called form socket unregister.
---
android/socket.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/android/socket.c b/android/socket.c
index 4f47861..7d41756 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -93,8 +93,10 @@ static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
return rfsock;
}
-static void cleanup_rfsock(struct rfcomm_sock *rfsock)
+static void cleanup_rfsock(gpointer data)
{
+ struct rfcomm_sock *rfsock = data;
+
DBG("rfsock: %p fd %d real_sock %d chan %u",
rfsock, rfsock->fd, rfsock->real_sock, rfsock->channel);
@@ -941,4 +943,7 @@ void bt_socket_register(const bdaddr_t *addr)
void bt_socket_unregister(void)
{
DBG("");
+
+ g_list_free_full(connections, cleanup_rfsock);
+ g_list_free_full(servers, cleanup_rfsock);
}
--
1.8.3.2
^ permalink raw reply related
* Re: [RFC] Fix eir parsing function.
From: Szymon Janc @ 2013-11-29 9:03 UTC (permalink / raw)
To: Johan Hedberg; +Cc: Andrei Emeltchenko, linux-bluetooth
In-Reply-To: <20131129085407.GA10642@x220.p-661hnu-f1>
Hi Johan,
> Hi Szymon,
>
> On Fri, Nov 29, 2013, Szymon Janc wrote:
> > > Hi Andrei,
> > >
> > > On Fri, Nov 29, 2013, Andrei Emeltchenko wrote:
> > > > Currently eir_parse always return 0 but it is checked throughout the
> > > > code (in android/bluetooth code as well in src/adapteri, etc) for
> > > > return value (err < 0) which never happens. Return -1 if there is
> > > > nothing to parse. Send as RFC as I do not know how current code supposed
> > > > to be working.
> > > > ---
> > > > src/eir.c | 2 +-
> > > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/src/eir.c b/src/eir.c
> > > > index 084884e..f7450c9 100644
> > > > --- a/src/eir.c
> > > > +++ b/src/eir.c
> > > > @@ -138,7 +138,7 @@ int eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
> > > >
> > > > /* No EIR data to parse */
> > > > if (eir_data == NULL)
> > > > - return 0;
> > > > + return -1;
> > > >
> > > > while (len < eir_len - 1) {
> > > > uint8_t field_len = eir_data[0];
> > >
> > > I think the only concern here is "when is it safe to call
> > > eir_data_free()?". If it would not be safe to call that in case the
> > > eir_parse function "fails" then we'd need to be able to clearly
> > > distinguish failure though a -1 return value. However, as it now stands
> > > it is always safe to call eir_data_free() on a struct that was passed to
> > > eir_parse(), so I'd go for simply changing this function to return void
> > > instead of int.
> >
> > I think it should be possible to check if parsing failed due to invalid EIR
> > but I think parsing empty EIR should not result in error.
> >
> > Most callers do verify eir_len or buffer validity before calling eir_parse()
> > anyway so I would change this check to:
> > if (!eir_data || !eir_len) return 0;
> >
> > and simplify callers code.
>
> I'm fine with adding a check for !eir_len, but if you check the actual
> implementation of eir_parse you'll see that it has no places where it'd
> return an error in the case of invalid EIR. In such a case the function
> just stops parsing at that point and returns. I think from a
> interoperability/usability perspective this makes sense: we take the
> best effort to parse what we can and use the data that we were able to
> parse until the parsing error happened. If you'd return an error when
> parsing fails it'd make the calling code disregard any of the valid data
> that was parsed until the point where the invalid data began.
Right, then making this return void makes sense as currently it is confusing
that it might return an error (eg. as used in eir_parse_oob()).
--
BR
Szymon Janc
^ permalink raw reply
* Re: [RFC] Fix eir parsing function.
From: Johan Hedberg @ 2013-11-29 8:54 UTC (permalink / raw)
To: Szymon Janc; +Cc: Andrei Emeltchenko, linux-bluetooth
In-Reply-To: <1501205.ZvMV0NcIeM@uw000953>
Hi Szymon,
On Fri, Nov 29, 2013, Szymon Janc wrote:
> > Hi Andrei,
> >
> > On Fri, Nov 29, 2013, Andrei Emeltchenko wrote:
> > > Currently eir_parse always return 0 but it is checked throughout the
> > > code (in android/bluetooth code as well in src/adapteri, etc) for
> > > return value (err < 0) which never happens. Return -1 if there is
> > > nothing to parse. Send as RFC as I do not know how current code supposed
> > > to be working.
> > > ---
> > > src/eir.c | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/src/eir.c b/src/eir.c
> > > index 084884e..f7450c9 100644
> > > --- a/src/eir.c
> > > +++ b/src/eir.c
> > > @@ -138,7 +138,7 @@ int eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
> > >
> > > /* No EIR data to parse */
> > > if (eir_data == NULL)
> > > - return 0;
> > > + return -1;
> > >
> > > while (len < eir_len - 1) {
> > > uint8_t field_len = eir_data[0];
> >
> > I think the only concern here is "when is it safe to call
> > eir_data_free()?". If it would not be safe to call that in case the
> > eir_parse function "fails" then we'd need to be able to clearly
> > distinguish failure though a -1 return value. However, as it now stands
> > it is always safe to call eir_data_free() on a struct that was passed to
> > eir_parse(), so I'd go for simply changing this function to return void
> > instead of int.
>
> I think it should be possible to check if parsing failed due to invalid EIR
> but I think parsing empty EIR should not result in error.
>
> Most callers do verify eir_len or buffer validity before calling eir_parse()
> anyway so I would change this check to:
> if (!eir_data || !eir_len) return 0;
>
> and simplify callers code.
I'm fine with adding a check for !eir_len, but if you check the actual
implementation of eir_parse you'll see that it has no places where it'd
return an error in the case of invalid EIR. In such a case the function
just stops parsing at that point and returns. I think from a
interoperability/usability perspective this makes sense: we take the
best effort to parse what we can and use the data that we were able to
parse until the parsing error happened. If you'd return an error when
parsing fails it'd make the calling code disregard any of the valid data
that was parsed until the point where the invalid data began.
Johan
^ permalink raw reply
* Re: [RFC] Fix eir parsing function.
From: Szymon Janc @ 2013-11-29 8:39 UTC (permalink / raw)
To: Johan Hedberg; +Cc: Andrei Emeltchenko, linux-bluetooth
In-Reply-To: <20131129082247.GA6800@x220.p-661hnu-f1>
Hi,
> Hi Andrei,
>
> On Fri, Nov 29, 2013, Andrei Emeltchenko wrote:
> > Currently eir_parse always return 0 but it is checked throughout the
> > code (in android/bluetooth code as well in src/adapteri, etc) for
> > return value (err < 0) which never happens. Return -1 if there is
> > nothing to parse. Send as RFC as I do not know how current code supposed
> > to be working.
> > ---
> > src/eir.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/src/eir.c b/src/eir.c
> > index 084884e..f7450c9 100644
> > --- a/src/eir.c
> > +++ b/src/eir.c
> > @@ -138,7 +138,7 @@ int eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
> >
> > /* No EIR data to parse */
> > if (eir_data == NULL)
> > - return 0;
> > + return -1;
> >
> > while (len < eir_len - 1) {
> > uint8_t field_len = eir_data[0];
>
> I think the only concern here is "when is it safe to call
> eir_data_free()?". If it would not be safe to call that in case the
> eir_parse function "fails" then we'd need to be able to clearly
> distinguish failure though a -1 return value. However, as it now stands
> it is always safe to call eir_data_free() on a struct that was passed to
> eir_parse(), so I'd go for simply changing this function to return void
> instead of int.
I think it should be possible to check if parsing failed due to invalid EIR
but I think parsing empty EIR should not result in error.
Most callers do verify eir_len or buffer validity before calling eir_parse()
anyway so I would change this check to:
if (!eir_data || !eir_len) return 0;
and simplify callers code.
--
BR
Szymon Janc
^ permalink raw reply
* Re: [PATCH] android/main: Call unregister for all registered services on exit
From: Johan Hedberg @ 2013-11-29 8:34 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1385712529-24757-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Fri, Nov 29, 2013, Andrei Emeltchenko wrote:
> ---
> android/main.c | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/android/main.c b/android/main.c
> index 2879bbf..2a9348b 100644
> --- a/android/main.c
> +++ b/android/main.c
> @@ -493,6 +493,38 @@ static void cleanup_hal_connection(void)
> ipc_cleanup();
> }
>
> +static void cleanup_services(void)
> +{
> + int i;
> +
> + DBG("");
> +
> + for (i=HAL_SERVICE_ID_BLUETOOTH; i < HAL_SERVICE_ID_MAX; i++) {
You've got coding style issues here: there should be a space before and
after '='. Since this trivial thing was the only issue I saw with the
patch I fixed it up myself and applied it.
Johan
^ permalink raw reply
* Re: [PATCH 1/2] android/hal-bluetooth: Rename create_enum_prop to enum_prop_to_hal
From: Johan Hedberg @ 2013-11-29 8:32 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1385712358-8121-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Fri, Nov 29, 2013, Szymon Janc wrote:
> This better describes purpose of this macro.
> ---
> android/hal-bluetooth.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
Both patches have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 10/10] android/socket: Remove unneeded code
From: Johan Hedberg @ 2013-11-29 8:31 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1385649486-19978-10-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Thu, Nov 28, 2013, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> The flag is already set in bt_io_listen.
> ---
> android/socket.c | 2 --
> 1 file changed, 2 deletions(-)
Patches 6-10 have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 04/10] android/main: Free enabled string on exit
From: Johan Hedberg @ 2013-11-29 8:29 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1385649486-19978-4-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Thu, Nov 28, 2013, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> ---
> android/main.c | 3 +++
> 1 file changed, 3 insertions(+)
Patches 1-4 have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 05/10] android/socket: Cleanup sockets on unregister
From: Johan Hedberg @ 2013-11-29 8:26 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1385649486-19978-5-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Thu, Nov 28, 2013, Andrei Emeltchenko wrote:
> This cleans up rfsock structures closing all sockets and making general cleanup
> for servers and for connections. This will be called form socket unregister.
> ---
> android/socket.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/android/socket.c b/android/socket.c
> index 1fb154d..d55db54 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -943,7 +943,27 @@ bool bt_socket_register(int sk, const bdaddr_t *addr)
> return true;
> }
>
> +static void free_connection(gpointer data, gpointer user_data)
> +{
> + struct rfcomm_sock *rfsock = data;
> +
> + connections = g_list_remove(connections, rfsock);
> + cleanup_rfsock(rfsock);
> +}
> +
> +static void free_server(gpointer data, gpointer user_data)
> +{
> + struct rfcomm_sock *rfsock = data;
> +
> + servers = g_list_remove(servers, rfsock);
> + cleanup_rfsock(rfsock);
> +}
> +
> void bt_socket_unregister(void)
> {
> DBG("");
> +
> + g_list_foreach(connections, free_connection, NULL);
> +
> + g_list_foreach(servers, free_server, NULL);
> }
I think what you're looking for here is g_slist_free_full instead of
g_slist_foreach. That way you won't need to have any helper functions at
all but you can directly pass cleanup_rfsock to it.
Johan
^ 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