* [PATCH v2 8/8] android/bluetooth: Add send_adapter_property helper function
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
Adapter property notification are send from multiple places so it make
sense to have helper for that. This is especially usefull for 'simple'
properties.
---
android/bluetooth.c | 88 +++++++++++++++--------------------------------------
1 file changed, 25 insertions(+), 63 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index b1d2c71..e456f3c 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -164,24 +164,26 @@ static struct device *get_device(const bdaddr_t *bdaddr)
return create_device(bdaddr);
}
-static void adapter_name_changed(const uint8_t *name)
+static void send_adapter_property(uint8_t type, uint16_t len, const void *val)
{
- struct hal_ev_adapter_props_changed *ev;
- size_t len = strlen((const char *) name);
uint8_t buf[BASELEN_PROP_CHANGED + len];
+ struct hal_ev_adapter_props_changed *ev = (void *) buf;
- memset(buf, 0, sizeof(buf));
- ev = (void *) buf;
-
- ev->num_props = 1;
ev->status = HAL_STATUS_SUCCESS;
- ev->props[0].type = HAL_PROP_ADAPTER_NAME;
- /* Android expects value without NULL terminator */
+ ev->num_props = 1;
+ ev->props[0].type = type;
ev->props[0].len = len;
- memcpy(ev->props->val, name, len);
+ memcpy(ev->props[0].val, val, len);
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), ev);
+ sizeof(buf), buf);
+}
+
+static void adapter_name_changed(const uint8_t *name)
+{
+ /* Android expects string value without NULL terminator */
+ send_adapter_property(HAL_PROP_ADAPTER_NAME,
+ strlen((const char *) name), name);
}
static void adapter_set_name(const uint8_t *name)
@@ -243,39 +245,19 @@ static uint8_t settings2scan_mode(void)
static void scan_mode_changed(void)
{
- uint8_t buf[BASELEN_PROP_CHANGED + 1];
- struct hal_ev_adapter_props_changed *ev = (void *) buf;
- uint8_t *mode;
-
- ev->num_props = 1;
- ev->status = HAL_STATUS_SUCCESS;
-
- ev->props[0].type = HAL_PROP_ADAPTER_SCAN_MODE;
- ev->props[0].len = 1;
+ uint8_t mode;
- mode = ev->props[0].val;
- *mode = settings2scan_mode();
+ mode = settings2scan_mode();
- DBG("mode %u", *mode);
+ DBG("mode %u", mode);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), buf);
+ send_adapter_property(HAL_PROP_ADAPTER_SCAN_MODE, sizeof(mode), &mode);
}
static void adapter_class_changed(void)
{
- uint8_t buf[BASELEN_PROP_CHANGED + sizeof(uint32_t)];
- struct hal_ev_adapter_props_changed *ev = (void *) buf;
-
- ev->num_props = 1;
- ev->status = HAL_STATUS_SUCCESS;
-
- ev->props[0].type = HAL_PROP_ADAPTER_CLASS;
- ev->props[0].len = sizeof(uint32_t);
- memcpy(ev->props->val, &adapter.dev_class, sizeof(uint32_t));
-
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), buf);
+ send_adapter_property(HAL_PROP_ADAPTER_CLASS, sizeof(adapter.dev_class),
+ &adapter.dev_class);
}
static void settings_changed(uint32_t settings)
@@ -1663,18 +1645,11 @@ static bool set_discoverable(uint8_t mode, uint16_t timeout)
static uint8_t get_adapter_address(void)
{
- uint8_t buf[BASELEN_PROP_CHANGED + sizeof(bdaddr_t)];
- struct hal_ev_adapter_props_changed *ev = (void *) buf;
-
- ev->num_props = 1;
- ev->status = HAL_STATUS_SUCCESS;
+ uint8_t buf[6];
- ev->props[0].type = HAL_PROP_ADAPTER_ADDR;
- ev->props[0].len = sizeof(bdaddr_t);
- bdaddr2android(&adapter.bdaddr, ev->props[0].val);
+ bdaddr2android(&adapter.bdaddr, buf);
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), buf);
+ send_adapter_property(HAL_PROP_ADAPTER_ADDR, sizeof(buf), buf);
return HAL_STATUS_SUCCESS;
}
@@ -1737,22 +1712,9 @@ static uint8_t get_adapter_bonded_devices(void)
static uint8_t get_adapter_discoverable_timeout(void)
{
- struct hal_ev_adapter_props_changed *ev;
- uint8_t buf[BASELEN_PROP_CHANGED + sizeof(uint32_t)];
-
- memset(buf, 0, sizeof(buf));
- ev = (void *) buf;
-
- ev->num_props = 1;
- ev->status = HAL_STATUS_SUCCESS;
-
- ev->props[0].type = HAL_PROP_ADAPTER_DISC_TIMEOUT;
- ev->props[0].len = sizeof(uint32_t);
- memcpy(&ev->props[0].val, &adapter.discoverable_timeout,
- sizeof(uint32_t));
-
- ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
- sizeof(buf), ev);
+ send_adapter_property(HAL_PROP_ADAPTER_DISC_TIMEOUT,
+ sizeof(adapter.discoverable_timeout),
+ &adapter.discoverable_timeout);
return HAL_STATUS_SUCCESS;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 7/8] android/bluetooth: Add send_device_property helper function
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
Remote device property notification will be send from multiple places
so it make sense to have helper for that. This will be especially
usefull for 'simple' properties.
---
android/bluetooth.c | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 483396c..b1d2c71 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -574,26 +574,27 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
browse_remote_sdp(&addr->bdaddr);
}
-
-static uint8_t get_device_name(struct device *dev)
+static void send_device_property(const bdaddr_t *bdaddr, uint8_t type,
+ uint16_t len, const void *val)
{
- struct hal_ev_remote_device_props *ev;
- size_t ev_len;
-
- ev_len = BASELEN_REMOTE_DEV_PROP + strlen(dev->name);
- ev = g_malloc0(ev_len);
+ uint8_t buf[BASELEN_REMOTE_DEV_PROP + len];
+ struct hal_ev_remote_device_props *ev = (void *) buf;
ev->status = HAL_STATUS_SUCCESS;
- bdaddr2android(&dev->bdaddr, ev->bdaddr);
+ bdaddr2android(bdaddr, ev->bdaddr);
ev->num_props = 1;
- ev->props[0].type = HAL_PROP_DEVICE_NAME;
- ev->props[0].len = strlen(dev->name);
- memcpy(&ev->props[0].val, dev->name, strlen(dev->name));
+ ev->props[0].type = type;
+ ev->props[0].len = len;
+ memcpy(ev->props[0].val, val, len);
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_REMOTE_DEVICE_PROPS,
- ev_len, ev);
+ sizeof(buf), buf);
+}
- g_free(ev);
+static uint8_t get_device_name(struct device *dev)
+{
+ send_device_property(&dev->bdaddr, HAL_PROP_DEVICE_NAME,
+ strlen(dev->name), dev->name);
return HAL_STATUS_SUCCESS;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 6/8] android/bluetooth: Add stubs for set device property command
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
This adds per property stubs.
---
android/bluetooth.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index f46238a..483396c 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -2373,10 +2373,30 @@ failed:
status);
}
+static uint8_t set_device_friendly_name(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t set_device_version_info(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return 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;
+ bdaddr_t addr;
+ GSList *l;
if (len != sizeof(*cmd) + cmd->len) {
error("Invalid set remote device prop cmd (0x%x), terminating",
@@ -2385,15 +2405,27 @@ static void handle_set_remote_device_prop_cmd(const void *buf, uint16_t len)
return;
}
- /* TODO */
+ android2bdaddr(cmd->bdaddr, &addr);
+
+ l = g_slist_find_custom(devices, &addr, bdaddr_cmp);
+ if (!l) {
+ status = HAL_STATUS_INVALID;
+ goto failed;
+ }
switch (cmd->type) {
+ case HAL_PROP_DEVICE_FRIENDLY_NAME:
+ status = set_device_friendly_name(l->data);
+ break;
+ case HAL_PROP_DEVICE_VERSION_INFO:
+ status = set_device_version_info(l->data);
+ break;
default:
- DBG("Unhandled property type 0x%x", cmd->type);
status = HAL_STATUS_FAILED;
break;
}
+failed:
ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_REMOTE_DEVICE_PROP,
status);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 5/8] android/bluetooth: Add stubs for get device properties command
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
This adds per property stubs.
---
android/bluetooth.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 119 insertions(+), 2 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 326f6d2..f46238a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -2240,6 +2240,78 @@ static void handle_get_adapter_props_cmd(const void *buf, uint16_t len)
HAL_STATUS_SUCCESS);
}
+static uint8_t get_device_uuids(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_class(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_type(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_service_rec(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_friendly_name(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_rssi(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_version_info(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
+static uint8_t get_device_timestamp(struct device *dev)
+{
+ DBG("Not implemented");
+
+ /* TODO */
+
+ return HAL_STATUS_FAILED;
+}
+
static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
{
/* TODO */
@@ -2250,10 +2322,55 @@ static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
static void handle_get_remote_device_prop_cmd(const void *buf, uint16_t len)
{
- /* TODO */
+ const struct hal_cmd_get_remote_device_prop *cmd = buf;
+ uint8_t status;
+ bdaddr_t addr;
+ GSList *l;
+ android2bdaddr(cmd->bdaddr, &addr);
+
+ l = g_slist_find_custom(devices, &addr, bdaddr_cmp);
+ if (!l) {
+ status = HAL_STATUS_INVALID;
+ goto failed;
+ }
+
+ switch (cmd->type) {
+ case HAL_PROP_DEVICE_NAME:
+ status = get_device_name(l->data);
+ break;
+ case HAL_PROP_DEVICE_UUIDS:
+ status = get_device_uuids(l->data);
+ break;
+ case HAL_PROP_DEVICE_CLASS:
+ status = get_device_class(l->data);
+ break;
+ case HAL_PROP_DEVICE_TYPE:
+ status = get_device_type(l->data);
+ break;
+ case HAL_PROP_DEVICE_SERVICE_REC:
+ status = get_device_service_rec(l->data);
+ break;
+ case HAL_PROP_DEVICE_FRIENDLY_NAME:
+ status = get_device_friendly_name(l->data);
+ break;
+ case HAL_PROP_DEVICE_RSSI:
+ status = get_device_rssi(l->data);
+ break;
+ case HAL_PROP_DEVICE_VERSION_INFO:
+ status = get_device_version_info(l->data);
+ break;
+ case HAL_PROP_DEVICE_TIMESTAMP:
+ status = get_device_timestamp(l->data);
+ break;
+ default:
+ status = HAL_STATUS_FAILED;
+ break;
+ }
+
+failed:
ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROP,
- HAL_STATUS_FAILED);
+ status);
}
static void handle_set_remote_device_prop_cmd(const void *buf, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 4/8] android/bluetooth: Refactor send_remote_device_name_prop
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
Rename send_remote_device_name_prop to get_device_name and make it
accept struct device as parameter. Also return HAL status code.
This will allow to use this function also in get device property
command handler.
---
android/bluetooth.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 5494dcb..326f6d2 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -575,19 +575,16 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
browse_remote_sdp(&addr->bdaddr);
}
-static void send_remote_device_name_prop(const bdaddr_t *bdaddr)
+static uint8_t get_device_name(struct device *dev)
{
struct hal_ev_remote_device_props *ev;
- struct device *dev;
size_t ev_len;
- dev = get_device(bdaddr);
-
ev_len = BASELEN_REMOTE_DEV_PROP + strlen(dev->name);
ev = g_malloc0(ev_len);
ev->status = HAL_STATUS_SUCCESS;
- bdaddr2android(bdaddr, ev->bdaddr);
+ bdaddr2android(&dev->bdaddr, ev->bdaddr);
ev->num_props = 1;
ev->props[0].type = HAL_PROP_DEVICE_NAME;
ev->props[0].len = strlen(dev->name);
@@ -597,6 +594,8 @@ static void send_remote_device_name_prop(const bdaddr_t *bdaddr)
ev_len, ev);
g_free(ev);
+
+ return HAL_STATUS_SUCCESS;
}
static void pin_code_request_callback(uint16_t index, uint16_t length,
@@ -615,7 +614,7 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
/* Workaround for Android Bluetooth.apk issue: send remote
* device property */
- send_remote_device_name_prop(&ev->addr.bdaddr);
+ get_device_name(get_device(&ev->addr.bdaddr));
set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDING);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 3/8] android/bluetooth: Fix coding style issue in set_device_bond_state
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
---
android/bluetooth.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 17c8e7a..5494dcb 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -372,7 +372,8 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
}
static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
- int state) {
+ int state)
+{
struct device *dev;
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 2/8] android/bluetooth: Use single list for device caching
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386687982-1799-1-git-send-email-szymon.janc@tieto.com>
This makes code much simpler and easier to follow. It is also
a preparation for supporting remote device properties getting, setting
and storing.
---
android/bluetooth.c | 160 ++++++++++++++++++++++------------------------------
1 file changed, 67 insertions(+), 93 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index f8df473..17c8e7a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -111,9 +111,59 @@ static const uint16_t uuid_list[] = {
0
};
-static GSList *found_devices = NULL;
static GSList *devices = NULL;
+static int bdaddr_cmp(gconstpointer a, gconstpointer b)
+{
+ const bdaddr_t *bda = a;
+ const bdaddr_t *bdb = b;
+
+ return bacmp(bdb, bda);
+}
+
+static struct device *find_device(const bdaddr_t *bdaddr)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(devices, bdaddr, bdaddr_cmp);
+ if (l)
+ return l->data;
+
+ return NULL;
+}
+
+static struct device *create_device(const bdaddr_t *bdaddr)
+{
+ struct device *dev;
+ char addr[18];
+
+ ba2str(bdaddr, addr);
+ DBG("%s", addr);
+
+ dev = g_new0(struct device, 1);
+
+ bacpy(&dev->bdaddr, bdaddr);
+ dev->bond_state = HAL_BOND_STATE_NONE;
+
+ /* use address for name, will be change if one is present
+ * eg. in EIR or set by set_property. */
+ dev->name = g_strdup(addr);
+ devices = g_slist_prepend(devices, dev);
+
+ return dev;
+}
+
+static struct device *get_device(const bdaddr_t *bdaddr)
+{
+ struct device *dev;
+
+ dev = find_device(bdaddr);
+ if (dev)
+ return dev;
+
+ return create_device(bdaddr);
+}
+
static void adapter_name_changed(const uint8_t *name)
{
struct hal_ev_adapter_props_changed *ev;
@@ -308,14 +358,6 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
}
-static int bdaddr_cmp(gconstpointer a, gconstpointer b)
-{
- const bdaddr_t *bda = a;
- const bdaddr_t *bdb = b;
-
- return bacmp(bdb, bda);
-}
-
static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
uint8_t state)
{
@@ -329,46 +371,12 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
sizeof(ev), &ev);
}
-static void cache_device_name(const bdaddr_t *addr, const char *name)
-{
- struct device *dev = NULL;
- GSList *l;
-
- l = g_slist_find_custom(devices, addr, bdaddr_cmp);
- if (l)
- dev = l->data;
-
- if (!dev) {
- dev = g_new0(struct device, 1);
- bacpy(&dev->bdaddr, addr);
- dev->bond_state = HAL_BOND_STATE_NONE;
- devices = g_slist_prepend(devices, dev);
- }
-
- if (!g_strcmp0(dev->name, name))
- return;
-
- g_free(dev->name);
- dev->name = g_strdup(name);
- /*TODO: Do some real caching here */
-}
-
static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
int state) {
- struct device *dev = NULL;
- GSList *l;
-
- l = g_slist_find_custom(devices, addr, bdaddr_cmp);
- if (l)
- dev = l->data;
+ struct device *dev;
- if (!dev) {
- dev = g_new0(struct device, 1);
- bacpy(&dev->bdaddr, addr);
- dev->bond_state = HAL_BOND_STATE_NONE;
- devices = g_slist_prepend(devices, dev);
- }
+ dev = get_device(addr);
if (dev->bond_state != state) {
dev->bond_state = state;
@@ -566,42 +574,23 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
browse_remote_sdp(&addr->bdaddr);
}
-static const char *get_device_name(const bdaddr_t *addr)
-{
- GSList *l;
-
- l = g_slist_find_custom(devices, addr, bdaddr_cmp);
- if (l) {
- struct device *dev = l->data;
- return dev->name;
- }
-
- return NULL;
-}
-
static void send_remote_device_name_prop(const bdaddr_t *bdaddr)
{
struct hal_ev_remote_device_props *ev;
- const char *name;
+ struct device *dev;
size_t ev_len;
- char dst[18];
- /* Use cached name or bdaddr string */
- name = get_device_name(bdaddr);
- if (!name) {
- ba2str(bdaddr, dst);
- name = dst;
- }
+ dev = get_device(bdaddr);
- ev_len = BASELEN_REMOTE_DEV_PROP + strlen(name);
+ ev_len = BASELEN_REMOTE_DEV_PROP + strlen(dev->name);
ev = g_malloc0(ev_len);
ev->status = HAL_STATUS_SUCCESS;
bdaddr2android(bdaddr, ev->bdaddr);
ev->num_props = 1;
ev->props[0].type = HAL_PROP_DEVICE_NAME;
- ev->props[0].len = strlen(name);
- memcpy(&ev->props[0].val, name, strlen(name));
+ ev->props[0].len = strlen(dev->name);
+ memcpy(&ev->props[0].val, dev->name, strlen(dev->name));
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_REMOTE_DEVICE_PROPS,
ev_len, ev);
@@ -749,14 +738,10 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
DBG("new discovering state %u", ev->discovering);
- if (adapter.discovering) {
+ if (adapter.discovering)
cp.state = HAL_DISCOVERY_STATE_STARTED;
- } else {
- g_slist_free_full(found_devices, g_free);
- found_devices = NULL;
-
+ else
cp.state = HAL_DISCOVERY_STATE_STOPPED;
- }
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_DISCOVERY_STATE_CHANGED, sizeof(cp), &cp);
@@ -793,8 +778,8 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
const uint8_t *data, uint8_t data_len)
{
uint8_t buf[BLUEZ_HAL_MTU];
- bool new_dev = false;
struct eir_data eir;
+ struct device *dev;
uint8_t *num_prop;
uint8_t opcode;
int size = 0;
@@ -804,25 +789,13 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
eir_parse(&eir, data, data_len);
- if (!g_slist_find_custom(found_devices, bdaddr, bdaddr_cmp)) {
- bdaddr_t *new_bdaddr;
- char addr[18];
-
- new_bdaddr = g_new0(bdaddr_t, 1);
- bacpy(new_bdaddr, bdaddr);
-
- found_devices = g_slist_prepend(found_devices, new_bdaddr);
-
- ba2str(new_bdaddr, addr);
- DBG("New device found: %s", addr);
-
- new_dev = true;
- }
-
- if (new_dev) {
+ dev = find_device(bdaddr);
+ if (!dev) {
struct hal_ev_device_found *ev = (void *) buf;
bdaddr_t android_bdaddr;
+ dev = create_device(bdaddr);
+
size += sizeof(*ev);
num_prop = &ev->num_props;
@@ -858,7 +831,8 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
}
if (eir.name) {
- cache_device_name(bdaddr, eir.name);
+ g_free(dev->name);
+ dev->name = g_strdup(eir.name);
size += fill_hal_prop(buf + size, HAL_PROP_DEVICE_NAME,
strlen(eir.name), eir.name);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 1/8] android/bluetooth: Rename functions to match adapter properties names
From: Szymon Janc @ 2013-12-10 15:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This match adapter properties handling functions with properties names.
Will make code easier to understand and avoid clashes with remote
device properties functions.
---
android/bluetooth.c | 72 ++++++++++++++++++++++++++---------------------------
1 file changed, 36 insertions(+), 36 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index a3145cb..f8df473 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1128,7 +1128,7 @@ static void uuid16_to_uint128(uint16_t uuid, uint128_t *u128)
ntoh128(&uuid128.value.uuid128, u128);
}
-static uint8_t get_uuids(void)
+static uint8_t get_adapter_uuids(void)
{
struct hal_ev_adapter_props_changed *ev;
GSList *list = adapter.uuids;
@@ -1178,7 +1178,7 @@ static void remove_uuid_complete(uint8_t status, uint16_t length,
mgmt_dev_class_changed_event(adapter.index, length, param, NULL);
- get_uuids();
+ get_adapter_uuids();
}
static void remove_uuid(uint16_t uuid)
@@ -1204,7 +1204,7 @@ static void add_uuid_complete(uint8_t status, uint16_t length,
mgmt_dev_class_changed_event(adapter.index, length, param, NULL);
- get_uuids();
+ get_adapter_uuids();
}
static void add_uuid(uint8_t svc_hint, uint16_t uuid)
@@ -1373,7 +1373,7 @@ static uint8_t set_adapter_name(const uint8_t *name, uint16_t len)
return HAL_STATUS_FAILED;
}
-static uint8_t set_discoverable_timeout(const void *buf, uint16_t len)
+static uint8_t set_adapter_discoverable_timeout(const void *buf, uint16_t len)
{
const uint32_t *timeout = buf;
@@ -1686,7 +1686,7 @@ static bool set_discoverable(uint8_t mode, uint16_t timeout)
return false;
}
-static uint8_t get_address(void)
+static uint8_t get_adapter_address(void)
{
uint8_t buf[BASELEN_PROP_CHANGED + sizeof(bdaddr_t)];
struct hal_ev_adapter_props_changed *ev = (void *) buf;
@@ -1704,7 +1704,7 @@ static uint8_t get_address(void)
return HAL_STATUS_SUCCESS;
}
-static uint8_t get_name(void)
+static uint8_t get_adapter_name(void)
{
if (!adapter.name)
return HAL_STATUS_FAILED;
@@ -1715,7 +1715,7 @@ static uint8_t get_name(void)
}
-static uint8_t get_class(void)
+static uint8_t get_adapter_class(void)
{
DBG("");
@@ -1724,7 +1724,7 @@ static uint8_t get_class(void)
return HAL_STATUS_SUCCESS;
}
-static uint8_t get_type(void)
+static uint8_t get_adapter_type(void)
{
DBG("Not implemented");
@@ -1733,7 +1733,7 @@ static uint8_t get_type(void)
return HAL_STATUS_FAILED;
}
-static uint8_t get_service(void)
+static uint8_t get_adapter_service_rec(void)
{
DBG("Not implemented");
@@ -1742,7 +1742,7 @@ static uint8_t get_service(void)
return HAL_STATUS_FAILED;
}
-static uint8_t get_scan_mode(void)
+static uint8_t get_adapter_scan_mode(void)
{
DBG("");
@@ -1751,7 +1751,7 @@ static uint8_t get_scan_mode(void)
return HAL_STATUS_SUCCESS;
}
-static uint8_t get_devices(void)
+static uint8_t get_adapter_bonded_devices(void)
{
DBG("Not implemented");
@@ -1760,7 +1760,7 @@ static uint8_t get_devices(void)
return HAL_STATUS_FAILED;
}
-static uint8_t get_discoverable_timeout(void)
+static uint8_t get_adapter_discoverable_timeout(void)
{
struct hal_ev_adapter_props_changed *ev;
uint8_t buf[BASELEN_PROP_CHANGED + sizeof(uint32_t)];
@@ -1789,31 +1789,31 @@ static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
switch (cmd->type) {
case HAL_PROP_ADAPTER_ADDR:
- status = get_address();
+ status = get_adapter_address();
break;
case HAL_PROP_ADAPTER_NAME:
- status = get_name();
+ status = get_adapter_name();
break;
case HAL_PROP_ADAPTER_UUIDS:
- status = get_uuids();
+ status = get_adapter_uuids();
break;
case HAL_PROP_ADAPTER_CLASS:
- status = get_class();
+ status = get_adapter_class();
break;
case HAL_PROP_ADAPTER_TYPE:
- status = get_type();
+ status = get_adapter_type();
break;
case HAL_PROP_ADAPTER_SERVICE_REC:
- status = get_service();
+ status = get_adapter_service_rec();
break;
case HAL_PROP_ADAPTER_SCAN_MODE:
- status = get_scan_mode();
+ status = get_adapter_scan_mode();
break;
case HAL_PROP_ADAPTER_BONDED_DEVICES:
- status = get_devices();
+ status = get_adapter_bonded_devices();
break;
case HAL_PROP_ADAPTER_DISC_TIMEOUT:
- status = get_discoverable_timeout();
+ status = get_adapter_discoverable_timeout();
break;
default:
status = HAL_STATUS_FAILED;
@@ -1823,17 +1823,17 @@ static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP, status);
}
-static void get_properties(void)
+static void get_adapter_properties(void)
{
- get_address();
- get_name();
- get_uuids();
- get_class();
- get_type();
- get_service();
- get_scan_mode();
- get_devices();
- get_discoverable_timeout();
+ get_adapter_address();
+ get_adapter_name();
+ get_adapter_uuids();
+ get_adapter_class();
+ get_adapter_type();
+ get_adapter_service_rec();
+ get_adapter_scan_mode();
+ get_adapter_bonded_devices();
+ get_adapter_discoverable_timeout();
}
static bool start_discovery(void)
@@ -1876,7 +1876,7 @@ static bool stop_discovery(void)
return false;
}
-static uint8_t set_scan_mode(const void *buf, uint16_t len)
+static uint8_t set_adapter_scan_mode(const void *buf, uint16_t len)
{
const uint8_t *mode = buf;
bool conn, disc, cur_conn, cur_disc;
@@ -1953,13 +1953,13 @@ static void handle_set_adapter_prop_cmd(const void *buf, uint16_t len)
switch (cmd->type) {
case HAL_PROP_ADAPTER_SCAN_MODE:
- status = set_scan_mode(cmd->val, cmd->len);
+ status = set_adapter_scan_mode(cmd->val, cmd->len);
break;
case HAL_PROP_ADAPTER_NAME:
status = set_adapter_name(cmd->val, cmd->len);
break;
case HAL_PROP_ADAPTER_DISC_TIMEOUT:
- status = set_discoverable_timeout(cmd->val, cmd->len);
+ status = set_adapter_discoverable_timeout(cmd->val, cmd->len);
break;
default:
DBG("Unhandled property type 0x%x", cmd->type);
@@ -2222,7 +2222,7 @@ static void handle_enable_cmd(const void *buf, uint16_t len)
/* Framework expects all properties to be emitted while
* enabling adapter */
- get_properties();
+ get_adapter_properties();
if (adapter.current_settings & MGMT_SETTING_POWERED) {
status = HAL_STATUS_DONE;
@@ -2260,7 +2260,7 @@ failed:
static void handle_get_adapter_props_cmd(const void *buf, uint16_t len)
{
- get_properties();
+ get_adapter_properties();
ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROPS,
HAL_STATUS_SUCCESS);
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH 2/8] android/bluetooth: Use single list for device caching
From: Luiz Augusto von Dentz @ 2013-12-10 14:13 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1386602049-5533-2-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
> @@ -809,20 +778,8 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
> return;
> }
>
> - if (!g_slist_find_custom(found_devices, bdaddr, bdaddr_cmp)) {
> - bdaddr_t *new_bdaddr;
> - char addr[18];
> -
> - new_bdaddr = g_new0(bdaddr_t, 1);
> - bacpy(new_bdaddr, bdaddr);
> -
> - found_devices = g_slist_prepend(found_devices, new_bdaddr);
> -
> - ba2str(new_bdaddr, addr);
> - DBG("New device found: %s", addr);
> -
> - new_dev = true;
> - }
> + new_dev = !g_slist_find_custom(devices, bdaddr, bdaddr_cmp);
> + dev = get_device(bdaddr);
This is not very efficient since get_device does the lookup again you
might want to use what g_slist_find_custom return or split get_device
internally in 2 e.g. find_device and create_device which can be used
by get_device or separately.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH v3 7/7] android/tester: Add status check and adapter enable, disable test cases
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Grzegorz Kolodziejczyk
In-Reply-To: <1386684051-31748-1-git-send-email-marcin.kraglak@tieto.com>
From: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>
This adds handling of status check, enabled adapter setup method,
disable and enable fail test case.
---
android/android-tester.c | 108 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 103 insertions(+), 5 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 1cba50a..061d94c 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -48,6 +48,7 @@
enum hal_bluetooth_callbacks_id {
adapter_test_end,
+ adapter_test_setup_mode,
adapter_state_changed_on,
adapter_state_changed_off,
adapter_prop_bdaddr,
@@ -61,6 +62,7 @@ enum hal_bluetooth_callbacks_id {
};
struct generic_data {
+ uint8_t expected_adapter_status;
uint32_t expect_settings_set;
uint8_t expected_hal_callbacks[];
};
@@ -80,6 +82,7 @@ struct test_data {
bool mgmt_settings_set;
bool hal_cb_called;
+ bool status_checked;
GSList *expected_callbacks;
};
@@ -88,8 +91,13 @@ static void test_update_state(void)
{
struct test_data *data = tester_get_data();
- if (data->mgmt_settings_set && data->hal_cb_called)
- tester_test_passed();
+ if (!(data->mgmt_settings_set))
+ return;
+ if (!(data->hal_cb_called))
+ return;
+ if (!(data->status_checked))
+ return;
+ tester_test_passed();
}
static void test_mgmt_settings_set(struct test_data *data)
@@ -143,10 +151,38 @@ static void mgmt_cb_init(struct test_data *data)
command_generic_new_settings, NULL, NULL);
}
+static void expected_status_init(struct test_data *data)
+{
+ if (!(data->test_data->expected_adapter_status))
+ data->status_checked = true;
+}
+
+static void init_test_conditions(struct test_data *data)
+{
+ hal_cb_init(data);
+ mgmt_cb_init(data);
+ expected_status_init(data);
+}
+
+static void check_expected_status(uint8_t status)
+{
+ struct test_data *data = tester_get_data();
+
+ if (data->test_data->expected_adapter_status == status)
+ data->status_checked = true;
+ else
+ tester_test_failed();
+
+ test_update_state();
+}
+
static int get_expected_hal_cb(void)
{
struct test_data *data = tester_get_data();
+ if (!(g_slist_length(data->expected_callbacks)))
+ return adapter_test_setup_mode;
+
return GPOINTER_TO_INT(data->expected_callbacks->data);
}
@@ -359,13 +395,28 @@ failed:
static void adapter_state_changed_cb(bt_state_t state)
{
- switch (get_expected_hal_cb()) {
+ enum hal_bluetooth_callbacks_id hal_cb;
+
+ hal_cb = get_expected_hal_cb();
+
+ switch (hal_cb) {
case adapter_state_changed_on:
if (state == BT_STATE_ON)
remove_expected_hal_cb();
else
tester_test_failed();
break;
+ case adapter_state_changed_off:
+ if (state == BT_STATE_OFF)
+ remove_expected_hal_cb();
+ else
+ tester_test_failed();
+ break;
+ case adapter_test_setup_mode:
+ if (state == BT_STATE_ON)
+ tester_setup_complete();
+ else
+ tester_setup_failed();
default:
break;
}
@@ -379,6 +430,10 @@ static void adapter_properties_cb(bt_status_t status, int num_properties,
for (i = 0; i < num_properties; i++) {
hal_cb = get_expected_hal_cb();
+
+ if (hal_cb == adapter_test_setup_mode)
+ break;
+
switch (properties[i].type) {
case BT_PROPERTY_BDADDR:
if (hal_cb != adapter_prop_bdaddr) {
@@ -454,6 +509,15 @@ static const struct generic_data bluetooth_enable_success_test = {
adapter_test_end}
};
+static const struct generic_data bluetooth_enable_done_test = {
+ .expected_hal_callbacks = {adapter_props, adapter_test_end},
+ .expected_adapter_status = BT_STATUS_DONE
+};
+
+static const struct generic_data bluetooth_disable_success_test = {
+ .expected_hal_callbacks = {adapter_state_changed_off, adapter_test_end}
+};
+
static bt_callbacks_t bt_callbacks = {
.size = sizeof(bt_callbacks),
.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -551,6 +615,15 @@ static void setup_base(const void *test_data)
tester_setup_complete();
}
+static void setup_enabled_adapter(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ setup(data);
+
+ data->if_bluetooth->enable();
+}
+
static void teardown(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -573,12 +646,31 @@ static void test_enable(const void *test_data)
{
struct test_data *data = tester_get_data();
- hal_cb_init(data);
- mgmt_cb_init(data);
+ init_test_conditions(data);
data->if_bluetooth->enable();
}
+static void test_enable_done(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ bt_status_t adapter_status;
+
+ init_test_conditions(data);
+
+ adapter_status = data->if_bluetooth->enable();
+ check_expected_status(adapter_status);
+}
+
+static void test_disable(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ init_test_conditions(data);
+
+ data->if_bluetooth->disable();
+}
+
static void controller_setup(const void *test_data)
{
tester_test_passed();
@@ -606,5 +698,11 @@ int main(int argc, char *argv[])
test_bredrle("Test Enable - Success", &bluetooth_enable_success_test,
setup_base, test_enable, teardown);
+ test_bredrle("Test Enable - Done", &bluetooth_enable_done_test,
+ setup_enabled_adapter, test_enable_done, teardown);
+
+ test_bredrle("Test Disable - Success", &bluetooth_disable_success_test,
+ setup_enabled_adapter, test_disable, teardown);
+
return tester_run();
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 6/7] android/tester: Add basic enable test
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Grzegorz Kolodziejczyk
In-Reply-To: <1386684051-31748-1-git-send-email-marcin.kraglak@tieto.com>
From: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>
---
android/android-tester.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 225 insertions(+), 2 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index ace7427..1cba50a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -37,7 +37,32 @@
#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
#define EMULATOR_SIGNAL "emulator_started"
+#define adapter_props adapter_prop_bdaddr, adapter_prop_bdname, \
+ adapter_prop_uuids, adapter_prop_cod, \
+ adapter_prop_scan_mode, adapter_prop_disc_timeout
+
+/*
+ * those are assigned to HAL methods and callbacks, we use ID later
+ * on mapped in switch-case due to different functions prototypes.
+ */
+
+enum hal_bluetooth_callbacks_id {
+ adapter_test_end,
+ adapter_state_changed_on,
+ adapter_state_changed_off,
+ adapter_prop_bdaddr,
+ adapter_prop_bdname,
+ adapter_prop_uuids,
+ adapter_prop_cod,
+ adapter_prop_scan_mode,
+ adapter_prop_disc_timeout,
+ adapter_prop_service_record,
+ adapter_prop_bonded_devices
+};
+
struct generic_data {
+ uint32_t expect_settings_set;
+ uint8_t expected_hal_callbacks[];
};
#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
@@ -46,13 +71,98 @@ struct generic_data {
struct test_data {
struct mgmt *mgmt;
uint16_t mgmt_index;
+ unsigned int mgmt_settings_id;
struct hciemu *hciemu;
enum hciemu_type hciemu_type;
const struct generic_data *test_data;
pid_t bluetoothd_pid;
const bt_interface_t *if_bluetooth;
+
+ bool mgmt_settings_set;
+ bool hal_cb_called;
+
+ GSList *expected_callbacks;
};
+static void test_update_state(void)
+{
+ struct test_data *data = tester_get_data();
+
+ if (data->mgmt_settings_set && data->hal_cb_called)
+ tester_test_passed();
+}
+
+static void test_mgmt_settings_set(struct test_data *data)
+{
+ data->mgmt_settings_set = true;
+
+ test_update_state();
+}
+
+static void command_generic_new_settings(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ uint32_t settings;
+
+ if (length != 4) {
+ tester_warn("Invalid parameter size for new settings event");
+ tester_test_failed();
+ return;
+ }
+
+ settings = bt_get_le32(param);
+
+ if ((settings & data->test_data->expect_settings_set) !=
+ data->test_data->expect_settings_set)
+ return;
+
+ test_mgmt_settings_set(data);
+ mgmt_unregister(data->mgmt, data->mgmt_settings_id);
+}
+
+static void hal_cb_init(struct test_data *data)
+{
+ unsigned int i = 0;
+
+ while (data->test_data->expected_hal_callbacks[i]) {
+ data->expected_callbacks =
+ g_slist_append(data->expected_callbacks,
+ GINT_TO_POINTER(data->test_data->expected_hal_callbacks[i]));
+ i++;
+ }
+}
+
+static void mgmt_cb_init(struct test_data *data)
+{
+ if (!data->test_data->expect_settings_set)
+ test_mgmt_settings_set(data);
+ else
+ data->mgmt_settings_id = mgmt_register(data->mgmt,
+ MGMT_EV_NEW_SETTINGS, data->mgmt_index,
+ command_generic_new_settings, NULL, NULL);
+}
+
+static int get_expected_hal_cb(void)
+{
+ struct test_data *data = tester_get_data();
+
+ return GPOINTER_TO_INT(data->expected_callbacks->data);
+}
+
+static void remove_expected_hal_cb(void)
+{
+ struct test_data *data = tester_get_data();
+
+ data->expected_callbacks = g_slist_remove(data->expected_callbacks,
+ data->expected_callbacks->data);
+
+ if (!data->expected_callbacks)
+ data->hal_cb_called = true;
+
+ test_update_state();
+}
+
static void read_info_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -247,10 +357,107 @@ failed:
close(fd);
}
+static void adapter_state_changed_cb(bt_state_t state)
+{
+ switch (get_expected_hal_cb()) {
+ case adapter_state_changed_on:
+ if (state == BT_STATE_ON)
+ remove_expected_hal_cb();
+ else
+ tester_test_failed();
+ break;
+ default:
+ break;
+ }
+}
+
+static void adapter_properties_cb(bt_status_t status, int num_properties,
+ bt_property_t *properties)
+{
+ enum hal_bluetooth_callbacks_id hal_cb;
+ int i;
+
+ for (i = 0; i < num_properties; i++) {
+ hal_cb = get_expected_hal_cb();
+ switch (properties[i].type) {
+ case BT_PROPERTY_BDADDR:
+ if (hal_cb != adapter_prop_bdaddr) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_BDNAME:
+ if (hal_cb != adapter_prop_bdname) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_UUIDS:
+ if (hal_cb != adapter_prop_uuids) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_CLASS_OF_DEVICE:
+ if (hal_cb != adapter_prop_cod) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_TYPE_OF_DEVICE:
+ if (hal_cb != adapter_prop_bdaddr) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_SERVICE_RECORD:
+ if (hal_cb != adapter_prop_service_record) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_ADAPTER_SCAN_MODE:
+ if (hal_cb != adapter_prop_scan_mode) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
+ if (hal_cb != adapter_prop_bonded_devices) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ if (hal_cb != adapter_prop_disc_timeout) {
+ tester_test_failed();
+ return;
+ }
+ remove_expected_hal_cb();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static const struct generic_data bluetooth_enable_success_test = {
+ .expected_hal_callbacks = {adapter_props, adapter_state_changed_on,
+ adapter_test_end}
+};
+
static bt_callbacks_t bt_callbacks = {
.size = sizeof(bt_callbacks),
- .adapter_state_changed_cb = NULL,
- .adapter_properties_cb = NULL,
+ .adapter_state_changed_cb = adapter_state_changed_cb,
+ .adapter_properties_cb = adapter_properties_cb,
.remote_device_properties_cb = NULL,
.device_found_cb = NULL,
.discovery_state_changed_cb = NULL,
@@ -356,9 +563,22 @@ static void teardown(const void *test_data)
if (data->bluetoothd_pid)
waitpid(data->bluetoothd_pid, NULL, 0);
+ if (data->expected_callbacks)
+ g_slist_free(data->expected_callbacks);
+
tester_teardown_complete();
}
+static void test_enable(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ hal_cb_init(data);
+ mgmt_cb_init(data);
+
+ data->if_bluetooth->enable();
+}
+
static void controller_setup(const void *test_data)
{
tester_test_passed();
@@ -383,5 +603,8 @@ int main(int argc, char *argv[])
test_bredrle("Test Init", NULL, setup_base, controller_setup, teardown);
+ test_bredrle("Test Enable - Success", &bluetooth_enable_success_test,
+ setup_base, test_enable, teardown);
+
return tester_run();
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 5/7] android/tester: Make HAL logging wrapper print to stderr instead of stdout
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1386684051-31748-1-git-send-email-marcin.kraglak@tieto.com>
From: Szymon Janc <szymon.janc@tieto.com>
This is used for testing and for user it makes no difference. This
will allow to switch on/off verbose logging from automated android
tester.
---
android/hal-log.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/android/hal-log.h b/android/hal-log.h
index 9bd024d..63ff61b 100644
--- a/android/hal-log.h
+++ b/android/hal-log.h
@@ -25,7 +25,7 @@
#define LOG_WARN " W"
#define LOG_ERROR " E"
#define LOG_DEBUG " D"
-#define ALOG(pri, tag, fmt, arg...) printf(tag pri": " fmt"\n", ##arg)
+#define ALOG(pri, tag, fmt, arg...) fprintf(stderr, tag pri": " fmt"\n", ##arg)
#endif
#define info(fmt, arg...) ALOG(LOG_INFO, LOG_TAG, fmt, ##arg)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 4/7] android/tester: Add stack initialization of stack in setup
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386684051-31748-1-git-send-email-marcin.kraglak@tieto.com>
This add stack initialization and cleanup in setup/teardown.
---
android/Makefile.am | 10 ++++++--
android/android-tester.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/android/Makefile.am b/android/Makefile.am
index 5364c2e..f3e77c3 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -91,9 +91,15 @@ android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
src/shared/tester.h src/shared/tester.c \
- android/android-tester.c
+ android/hal-utils.h android/hal-utils.c \
+ android/client/hwmodule.c android/android-tester.c
-android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+android_android_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_android_tester_LDADD = lib/libbluetooth-internal.la \
+ android/libhal-internal.la @GLIB_LIBS@
+
+android_android_tester_LDFLAGS = -pthread
endif
diff --git a/android/android-tester.c b/android/android-tester.c
index 301b96a..ace7427 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -31,6 +31,12 @@
#include "src/shared/mgmt.h"
#include "src/shared/hciemu.h"
+#include <hardware/hardware.h>
+#include <hardware/bluetooth.h>
+
+#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
+#define EMULATOR_SIGNAL "emulator_started"
+
struct generic_data {
};
@@ -44,6 +50,7 @@ struct test_data {
enum hciemu_type hciemu_type;
const struct generic_data *test_data;
pid_t bluetoothd_pid;
+ const bt_interface_t *if_bluetooth;
};
static void read_info_callback(uint8_t status, uint16_t length,
@@ -240,12 +247,32 @@ failed:
close(fd);
}
+static bt_callbacks_t bt_callbacks = {
+ .size = sizeof(bt_callbacks),
+ .adapter_state_changed_cb = NULL,
+ .adapter_properties_cb = NULL,
+ .remote_device_properties_cb = NULL,
+ .device_found_cb = NULL,
+ .discovery_state_changed_cb = NULL,
+ .pin_request_cb = NULL,
+ .ssp_request_cb = NULL,
+ .bond_state_changed_cb = NULL,
+ .acl_state_changed_cb = NULL,
+ .thread_evt_cb = NULL,
+ .dut_mode_recv_cb = NULL,
+ .le_test_mode_cb = NULL
+};
+
static void setup(struct test_data *data)
{
+ const hw_module_t *module;
+ hw_device_t *device;
+ bt_status_t status;
int signal_fd[2];
char buf[1024];
pid_t pid;
int len;
+ int err;
if (pipe(signal_fd)) {
tester_setup_failed();
@@ -279,6 +306,33 @@ static void setup(struct test_data *data)
tester_setup_failed();
return;
}
+
+ close(signal_fd[0]);
+
+ err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+ if (err) {
+ tester_setup_failed();
+ return;
+ }
+
+ err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+ if (err) {
+ tester_setup_failed();
+ return;
+ }
+
+ data->if_bluetooth = ((bluetooth_device_t *)
+ device)->get_bluetooth_interface();
+ if (!data->if_bluetooth) {
+ tester_setup_failed();
+ return;
+ }
+
+ status = data->if_bluetooth->init(&bt_callbacks);
+ if (status != BT_STATUS_SUCCESS) {
+ data->if_bluetooth = NULL;
+ tester_setup_failed();
+ }
}
static void setup_base(const void *test_data)
@@ -294,6 +348,11 @@ static void teardown(const void *test_data)
{
struct test_data *data = tester_get_data();
+ if (data->if_bluetooth) {
+ data->if_bluetooth->cleanup();
+ data->if_bluetooth = NULL;
+ }
+
if (data->bluetoothd_pid)
waitpid(data->bluetoothd_pid, NULL, 0);
@@ -302,6 +361,7 @@ static void teardown(const void *test_data)
static void controller_setup(const void *test_data)
{
+ tester_test_passed();
}
#define test_bredrle(name, data, test_setup, test, test_teardown) \
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 3/7] android/tester: Start emulator in new process
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386684051-31748-1-git-send-email-marcin.kraglak@tieto.com>
This is needed because bluetooth->init call is blocking,
and we have to emulate normal behaviour of android environment.
That process will exit if it won't receive any message in 2 sec
or when bluetoothd will exit. Main tester thread will wait for
this process in teardown method.
---
android/android-tester.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 126 insertions(+), 1 deletion(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 498da22..301b96a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -15,9 +15,14 @@
*
*/
+#include <stdlib.h>
#include <unistd.h>
#include <glib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
#include "lib/bluetooth.h"
#include "lib/mgmt.h"
@@ -29,12 +34,16 @@
struct generic_data {
};
+#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
+#define EMULATOR_SIGNAL "emulator_started"
+
struct test_data {
struct mgmt *mgmt;
uint16_t mgmt_index;
struct hciemu *hciemu;
enum hciemu_type hciemu_type;
const struct generic_data *test_data;
+ pid_t bluetoothd_pid;
};
static void read_info_callback(uint8_t status, uint16_t length,
@@ -165,13 +174,129 @@ static void test_post_teardown(const void *test_data)
data->hciemu = NULL;
}
+static void bluetoothd_start(int hci_index)
+{
+ char prg_name[PATH_MAX + 1];
+ char index[8];
+ char *prg_argv[4];
+
+ snprintf(prg_name, sizeof(prg_name), "%s/%s", "android", "bluetoothd");
+ snprintf(index, sizeof(index), "%d", hci_index);
+
+ prg_argv[0] = prg_name;
+ prg_argv[1] = "-i";
+ prg_argv[2] = index;
+ prg_argv[3] = NULL;
+
+ if (!tester_use_debug())
+ fclose(stderr);
+
+ execve(prg_argv[0], prg_argv, NULL);
+}
+
+static void emulator(int pipe, int hci_index)
+{
+ static const char SYSTEM_SOCKET_PATH[] = "\0android_system";
+ char buf[1024];
+ struct sockaddr_un addr;
+ struct timeval tv;
+ int fd;
+ ssize_t len;
+
+ fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ goto failed;
+
+ tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
+ tv.tv_usec = 0;
+ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH));
+
+ if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("Failed to bind system socket");
+ goto failed;
+ }
+
+ len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
+
+ if (len != sizeof(EMULATOR_SIGNAL))
+ goto failed;
+
+ memset(buf, 0, sizeof(buf));
+
+ len = read(fd, buf, sizeof(buf));
+ if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd")))
+ goto failed;
+
+ close(pipe);
+ close(fd);
+ bluetoothd_start(hci_index);
+
+failed:
+ close(pipe);
+ close(fd);
+}
+
+static void setup(struct test_data *data)
+{
+ int signal_fd[2];
+ char buf[1024];
+ pid_t pid;
+ int len;
+
+ if (pipe(signal_fd)) {
+ tester_setup_failed();
+ return;
+ }
+
+ pid = fork();
+
+ if (pid < 0) {
+ close(signal_fd[0]);
+ close(signal_fd[1]);
+ tester_setup_failed();
+ return;
+ }
+
+ if (pid == 0) {
+ if (!tester_use_debug())
+ fclose(stderr);
+
+ close(signal_fd[0]);
+ emulator(signal_fd[1], data->mgmt_index);
+ exit(0);
+ }
+
+ close(signal_fd[1]);
+ data->bluetoothd_pid = pid;
+
+ len = read(signal_fd[0], buf, sizeof(buf));
+ if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
+ close(signal_fd[0]);
+ tester_setup_failed();
+ return;
+ }
+}
+
static void setup_base(const void *test_data)
{
- tester_setup_failed();
+ struct test_data *data = tester_get_data();
+
+ setup(data);
+
+ tester_setup_complete();
}
static void teardown(const void *test_data)
{
+ struct test_data *data = tester_get_data();
+
+ if (data->bluetoothd_pid)
+ waitpid(data->bluetoothd_pid, NULL, 0);
+
tester_teardown_complete();
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 2/7] android/tester: Add pre-setup and post-teardown routines
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1386684051-31748-1-git-send-email-marcin.kraglak@tieto.com>
This will add hciemu initialization and cleanup. These functions
will be called to create hci emulator and cleanup it.
---
android/Makefile.am | 10 ++-
android/android-tester.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 191 insertions(+), 2 deletions(-)
diff --git a/android/Makefile.am b/android/Makefile.am
index 0768985..5364c2e 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -85,7 +85,15 @@ android_haltest_LDFLAGS = -pthread
noinst_PROGRAMS += android/android-tester
-android_android_tester_SOURCES = android/android-tester.c
+android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
+ emulator/bthost.h emulator/bthost.c \
+ src/shared/util.h src/shared/util.c \
+ src/shared/mgmt.h src/shared/mgmt.c \
+ src/shared/hciemu.h src/shared/hciemu.c \
+ src/shared/tester.h src/shared/tester.c \
+ android/android-tester.c
+
+android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
endif
diff --git a/android/android-tester.c b/android/android-tester.c
index f5c42b0..498da22 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -15,7 +15,188 @@
*
*/
+#include <unistd.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "src/shared/tester.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/hciemu.h"
+
+struct generic_data {
+};
+
+struct test_data {
+ struct mgmt *mgmt;
+ uint16_t mgmt_index;
+ struct hciemu *hciemu;
+ enum hciemu_type hciemu_type;
+ const struct generic_data *test_data;
+};
+
+static void read_info_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct mgmt_rp_read_info *rp = param;
+ char addr[18];
+ uint16_t manufacturer;
+ uint32_t supported_settings, current_settings;
+
+ tester_print("Read Info callback");
+ tester_print(" Status: 0x%02x", status);
+
+ if (status || !param) {
+ tester_pre_setup_failed();
+ return;
+ }
+
+ ba2str(&rp->bdaddr, addr);
+ manufacturer = btohs(rp->manufacturer);
+ supported_settings = btohl(rp->supported_settings);
+ current_settings = btohl(rp->current_settings);
+
+ tester_print(" Address: %s", addr);
+ tester_print(" Version: 0x%02x", rp->version);
+ tester_print(" Manufacturer: 0x%04x", manufacturer);
+ tester_print(" Supported settings: 0x%08x", supported_settings);
+ tester_print(" Current settings: 0x%08x", current_settings);
+ tester_print(" Class: 0x%02x%02x%02x",
+ rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+ tester_print(" Name: %s", rp->name);
+ tester_print(" Short name: %s", rp->short_name);
+
+ if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+ tester_pre_setup_failed();
+ return;
+ }
+
+ tester_pre_setup_complete();
+}
+
+static void index_added_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Index Added callback");
+ tester_print(" Index: 0x%04x", index);
+
+ data->mgmt_index = index;
+
+ mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
+ read_info_callback, NULL, NULL);
+}
+
+static void index_removed_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Index Removed callback");
+ tester_print(" Index: 0x%04x", index);
+
+ if (index != data->mgmt_index)
+ return;
+
+ mgmt_unregister_index(data->mgmt, data->mgmt_index);
+
+ mgmt_unref(data->mgmt);
+ data->mgmt = NULL;
+
+ tester_post_teardown_complete();
+}
+
+static void read_index_list_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Read Index List callback");
+ tester_print(" Status: 0x%02x", status);
+
+ if (status || !param) {
+ tester_pre_setup_failed();
+ return;
+ }
+
+ mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+ index_added_callback, NULL, NULL);
+
+ mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+ index_removed_callback, NULL, NULL);
+
+ data->hciemu = hciemu_new(data->hciemu_type);
+ if (!data->hciemu) {
+ tester_warn("Failed to setup HCI emulation");
+ tester_pre_setup_failed();
+ return;
+ }
+
+ tester_print("New hciemu instance created");
+}
+
+static void test_pre_setup(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ if (!tester_use_debug())
+ fclose(stderr);
+
+ data->mgmt = mgmt_new_default();
+ if (!data->mgmt) {
+ tester_warn("Failed to setup management interface");
+ tester_pre_setup_failed();
+ return;
+ }
+
+ mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+ NULL, read_index_list_callback, NULL, NULL);
+}
+
+static void test_post_teardown(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ hciemu_unref(data->hciemu);
+ data->hciemu = NULL;
+}
+
+static void setup_base(const void *test_data)
+{
+ tester_setup_failed();
+}
+
+static void teardown(const void *test_data)
+{
+ tester_teardown_complete();
+}
+
+static void controller_setup(const void *test_data)
+{
+}
+
+#define test_bredrle(name, data, test_setup, test, test_teardown) \
+ do { \
+ struct test_data *user; \
+ user = g_malloc0(sizeof(struct test_data)); \
+ if (!user) \
+ break; \
+ user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
+ user->test_data = data; \
+ tester_add_full(name, data, test_pre_setup, test_setup, \
+ test, test_teardown, test_post_teardown, \
+ 3, user, g_free); \
+ } while (0)
+
int main(int argc, char *argv[])
{
- return 0;
+ tester_init(&argc, &argv);
+
+ test_bredrle("Test Init", NULL, setup_base, controller_setup, teardown);
+
+ return tester_run();
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 1/7] android/tester: Add android-tester
From: Marcin Kraglak @ 2013-12-10 14:00 UTC (permalink / raw)
To: linux-bluetooth
This commit add android-tester.c to tree and Makefile.am.
This will contain set of unit tests for testing android daemon.
---
.gitignore | 1 +
android/Makefile.am | 4 ++++
android/android-tester.c | 21 +++++++++++++++++++++
3 files changed, 26 insertions(+)
create mode 100644 android/android-tester.c
diff --git a/.gitignore b/.gitignore
index 2d3435a..c570728 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,3 +107,4 @@ unit/test-*.trs
android/system-emulator
android/bluetoothd
android/haltest
+android/android-tester
diff --git a/android/Makefile.am b/android/Makefile.am
index df04762..0768985 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -83,6 +83,10 @@ android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android \
android_haltest_LDFLAGS = -pthread
+noinst_PROGRAMS += android/android-tester
+
+android_android_tester_SOURCES = android/android-tester.c
+
endif
EXTRA_DIST += android/Android.mk android/hal-ipc-api.txt android/README \
diff --git a/android/android-tester.c b/android/android-tester.c
new file mode 100644
index 0000000..f5c42b0
--- /dev/null
+++ b/android/android-tester.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+int main(int argc, char *argv[])
+{
+ return 0;
+}
--
1.8.3.1
^ permalink raw reply related
* Re: [RFC v4 05/12] Bluetooth: Stop scanning on LE connection
From: Johan Hedberg @ 2013-12-10 13:21 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1386367549-29136-6-git-send-email-andre.guedes@openbossa.org>
Hi Andre,
On Fri, Dec 06, 2013, Andre Guedes wrote:
> Some LE controllers don't support scanning and creating a connection
> at the same time. So we should always stop scanning in order to
> establish the connection.
>
> Since we may prematurely stop the discovery procedure in favor of
> the connection establishment, we should also cancel hdev->le_scan_
> disable delayed work and set the discovery state to DISCOVERY_STOPPED.
>
> This change does a small improvement since it is not mandatory the
> user stops scanning before connecting anymore. Moreover, this change
> is required by upcoming LE auto connection mechanism in order to work
> properly with controllers that don't support background scanning and
> connection establishment at the same time.
>
> In future, we might want to do a small optimization by checking if
> controller is able to scan and connect at the same time. For now,
> we want the simplest approach so we always stop scanning (even if
> the controller is able to carry out both operations).
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/hci_conn.c | 23 ++++++++++++++++++++++-
> 1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index b5c3ebff..750a39d 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -518,8 +518,17 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
> {
> struct hci_conn *conn;
>
> - if (status == 0)
> + if (status == 0) {
> + /* If the discovery procedure was running, we prematurely
> + * stopped it. So we have to change the discovery state.
> + */
> + if (hdev->discovery.state == DISCOVERY_FINDING) {
> + cancel_delayed_work(&hdev->le_scan_disable);
> + hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> + }
> +
> return;
> + }
>
> BT_ERR("HCI request failed to create LE connection: status 0x%2.2x",
> status);
> @@ -552,6 +561,18 @@ static int hci_create_le_conn(struct hci_conn *conn)
>
> hci_req_init(&req, hdev);
>
> + /* If controller is scanning, we stop it since some controllers are
> + * not able to scan and connect at the same time.
> + */
> + if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
> + struct hci_cp_le_set_scan_enable enable_cp;
> +
> + memset(&enable_cp, 0, sizeof(enable_cp));
> + enable_cp.enable = LE_SCAN_DISABLE;
> + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
> + &enable_cp);
> + }
> +
> memset(&cp, 0, sizeof(cp));
> cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
> cp.scan_window = cpu_to_le16(hdev->le_scan_window);
The way this all hangs together with a discovery process started through
mgmt_start_discovery feels a bit flimsy to me. Particularly, have you
ensured that everything is fine if you've got inquiry ongoing when you
do hci_discovery_set_state(hdev, DISCOVERY_STOPPED). Also, are there any
risks of race conditions here, e.g. is it fine to let the
cancel_delayed_work() call be in create_le_conn_complete() instead of
doing it in hci_create_le_conn()?
What also makes this hard to track is that the condition you're testing
for first is the HCI_LE_SCAN bit, but then later you look at
discovery.state == DISCOVERY_FINDING. For the casual reader there's no
direct indication of how these two are releated for the various types of
discovery that are possible (LE-only, BR/EDR-only and interleaved).
I don't mean to say that this is a nack for the patch, but I'd like to
know that you've considered and tested this kind of cases. I had to
spend quite some time looking through the existing code and this patch
and still couldn't arrive at absolute confidence of its correctness,
meaning there should hopefully be some room for simplification.
Johan
^ permalink raw reply
* Re: [PATCH v7 4/5] Bluetooth: Enable 6LoWPAN support for BT LE devices
From: Jukka Rissanen @ 2013-12-10 13:15 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <072BE4A2-71E0-48B1-9C5A-0DF09F732BEC@holtmann.org>
Hi Marcel,
On ti, 2013-12-10 at 13:06 +0100, Marcel Holtmann wrote:
> Hi Jukka,
>
> you might want to add a bit of commit message here.
>
> > ---
> > +
> > +#include <net/af_ieee802154.h> /* to get the address type */
>
> Is this still needed? What address type is it that we need?
We need to access IEEE802154_ADDR_LONG as that symbol is needed by the
common compression code. We can figure out how to get rid of it later.
Cheers,
Jukka
^ permalink raw reply
* mouse not found with bluez5 but was fine with bluez4
From: Brian J. Murrell @ 2013-12-10 13:08 UTC (permalink / raw)
To: linux-bluetooth
[-- Attachment #1: Type: text/plain, Size: 547 bytes --]
So, in chasing an issue with mouse pairing in another thread I was asked
to upgrade to Fedora 20 to see if my mouse pairing issue was
reproducible on bluez5 given that bluez4 is pretty dead now.
But the same mouse that could be found and paired on bluez4 (Fedora 19)
is not even being found during the search on bluez5 (Fedora 20) on the
exact same hardware (same machine in fact). Bluez5 did manage to see
and pair a headset though, just not this mouse.
What information/tests can I provide to help figure this out?
Cheers,
b.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* Re: [PATCH v2 6/7] android/tester: Add basic tests
From: Luiz Augusto von Dentz @ 2013-12-10 12:17 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth@vger.kernel.org, Grzegorz Kolodziejczyk
In-Reply-To: <1386672344-13438-6-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin, Grzegorz,
On Tue, Dec 10, 2013 at 12:45 PM, Marcin Kraglak
<marcin.kraglak@tieto.com> wrote:
> From: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>
>
> This adds basic tests for bluetooth hal interface, enable and controller
> setup.
>
> ---
> android/android-tester.c | 247 +++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 240 insertions(+), 7 deletions(-)
>
> diff --git a/android/android-tester.c b/android/android-tester.c
> index 2df5bdb..6cde3cf 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -37,16 +37,129 @@
> #define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
> #define EMULATOR_SIGNAL "emulator_started"
>
> +#define adapter_props adapter_prop_bdaddr, adapter_prop_bdname, \
> + adapter_prop_uuids, adapter_prop_cod, \
> + adapter_prop_scan_mode, adapter_prop_disc_timeout
> +
> +/*
> + * those are assigned to HAL methods and callbacks, we use ID later
> + * on mapped in switch-case due to different functions prototypes.
> + */
> +
> +enum hal_bluetooth_callbacks_id {
> + adapter_test_end,
> + adapter_state_changed_on,
> + adapter_state_changed_off,
> + adapter_prop_bdaddr,
> + adapter_prop_bdname,
> + adapter_prop_uuids,
> + adapter_prop_cod,
> + adapter_prop_scan_mode,
> + adapter_prop_disc_timeout,
> + adapter_prop_service_record,
> + adapter_prop_bonded_devices
> +};
> +
> +struct generic_data {
> + uint32_t expect_settings_set;
> + uint8_t expected_hal_callbacks[];
> +};
> +
> struct test_data {
> struct mgmt *mgmt;
> uint16_t mgmt_index;
> + unsigned int mgmt_settings_id;
> struct hciemu *hciemu;
> enum hciemu_type hciemu_type;
> - void *test_data;
> + const struct generic_data *test_data;
> pid_t bluetoothd_pid;
> const bt_interface_t *if_bluetooth;
> +
> + bool mgmt_settings_set;
> + bool hal_cb_called;
> +
> + GSList *expected_callbacks;
> };
>
> +static void test_update_state(void)
> +{
> + struct test_data *data = tester_get_data();
> +
> + if (data->mgmt_settings_set && data->hal_cb_called)
> + tester_test_passed();
> +}
> +
> +static void test_mgmt_settings_set(struct test_data *data)
> +{
> + data->mgmt_settings_set = true;
> +
> + test_update_state();
> +}
> +
> +static void command_generic_new_settings(uint16_t index, uint16_t length,
> + const void *param, void *user_data)
> +{
> + struct test_data *data = tester_get_data();
> + uint32_t settings;
> +
> + if (length != 4) {
> + tester_warn("Invalid parameter size for new settings event");
> + tester_test_failed();
> + return;
> + }
> +
> + settings = bt_get_le32(param);
> +
> + if ((settings & data->test_data->expect_settings_set) !=
> + data->test_data->expect_settings_set)
> + return;
> +
> + test_mgmt_settings_set(data);
> + mgmt_unregister(data->mgmt, data->mgmt_settings_id);
> +}
> +
> +static void hal_cb_init(struct test_data *data)
> +{
> + unsigned int i = 0;
> +
> + while (data->test_data->expected_hal_callbacks[i]) {
> + data->expected_callbacks =
> + g_slist_append(data->expected_callbacks,
> + GINT_TO_POINTER(data->test_data->expected_hal_callbacks[i]));
> + i++;
> + }
> +}
> +
> +static void mgmt_cb_init(struct test_data *data)
> +{
> + if (!data->test_data->expect_settings_set)
> + test_mgmt_settings_set(data);
> + else
> + data->mgmt_settings_id = mgmt_register(data->mgmt,
> + MGMT_EV_NEW_SETTINGS, data->mgmt_index,
> + command_generic_new_settings, NULL, NULL);
> +}
> +
> +static int get_expected_hal_cb(void)
> +{
> + struct test_data *data = tester_get_data();
> +
> + return GPOINTER_TO_INT(data->expected_callbacks->data);
> +}
> +
> +static void remove_expected_hal_cb(void)
> +{
> + struct test_data *data = tester_get_data();
> +
> + data->expected_callbacks = g_slist_remove(data->expected_callbacks,
> + data->expected_callbacks->data);
> +
> + if (!data->expected_callbacks)
> + data->hal_cb_called = true;
> +
> + test_update_state();
> +}
> +
> static void read_info_callback(uint8_t status, uint16_t length,
> const void *param, void *user_data)
> {
> @@ -241,10 +354,107 @@ failed:
> close(fd);
> }
>
> +static void adapter_state_changed_cb(bt_state_t state)
> +{
> + switch (get_expected_hal_cb()) {
> + case adapter_state_changed_on:
> + if (state == BT_STATE_ON)
> + remove_expected_hal_cb();
> + else
> + tester_test_failed();
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static void adapter_properties_cb(bt_status_t status, int num_properties,
> + bt_property_t *properties)
> +{
> + enum hal_bluetooth_callbacks_id hal_cb;
> + int i;
> +
> + for (i = 0; i < num_properties; i++) {
> + hal_cb = get_expected_hal_cb();
> + switch (properties[i].type) {
> + case BT_PROPERTY_BDADDR:
> + if (hal_cb != adapter_prop_bdaddr) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_BDNAME:
> + if (hal_cb != adapter_prop_bdname) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_UUIDS:
> + if (hal_cb != adapter_prop_uuids) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_CLASS_OF_DEVICE:
> + if (hal_cb != adapter_prop_cod) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_TYPE_OF_DEVICE:
> + if (hal_cb != adapter_prop_bdaddr) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_SERVICE_RECORD:
> + if (hal_cb != adapter_prop_service_record) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_ADAPTER_SCAN_MODE:
> + if (hal_cb != adapter_prop_scan_mode) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
> + if (hal_cb != adapter_prop_bonded_devices) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
> + if (hal_cb != adapter_prop_disc_timeout) {
> + tester_test_failed();
> + return;
> + }
> + remove_expected_hal_cb();
> + break;
> + default:
> + break;
> + }
> + }
> +}
> +
> +static const struct generic_data bluetooth_enable_success_test = {
> + .expected_hal_callbacks = {adapter_props, adapter_state_changed_on,
> + adapter_test_end}
> +};
> +
> static bt_callbacks_t bt_callbacks = {
> .size = sizeof(bt_callbacks),
> - .adapter_state_changed_cb = NULL,
> - .adapter_properties_cb = NULL,
> + .adapter_state_changed_cb = adapter_state_changed_cb,
> + .adapter_properties_cb = adapter_properties_cb,
> .remote_device_properties_cb = NULL,
> .device_found_cb = NULL,
> .discovery_state_changed_cb = NULL,
> @@ -257,9 +467,8 @@ static bt_callbacks_t bt_callbacks = {
> .le_test_mode_cb = NULL
> };
>
> -static void setup(const void *test_data)
> +static void setup(struct test_data *data)
> {
> - struct test_data *data = tester_get_data();
> const hw_module_t *module;
> hw_device_t *device;
> bt_status_t status;
> @@ -328,6 +537,13 @@ static void setup(const void *test_data)
> data->if_bluetooth = NULL;
> tester_setup_failed();
> }
> +}
> +
> +static void setup_base(const void *test_data)
> +{
> + struct test_data *data = tester_get_data();
> +
> + setup(data);
>
> tester_setup_complete();
> }
> @@ -344,10 +560,23 @@ static void teardown(const void *test_data)
> if (data->bluetoothd_pid)
> waitpid(data->bluetoothd_pid, NULL, 0);
>
> + if (data->expected_callbacks)
> + g_slist_free(data->expected_callbacks);
> +
> tester_teardown_complete();
> }
>
> -static void pass_test(const void *test_data)
> +static void test_enable(const void *test_data)
> +{
> + struct test_data *data = tester_get_data();
> +
> + hal_cb_init(data);
> + mgmt_cb_init(data);
> +
> + data->if_bluetooth->enable();
> +}
> +
> +static void controller_setup(const void *test_data)
> {
> tester_test_passed();
> }
> @@ -369,7 +598,11 @@ int main(int argc, char *argv[])
> {
> tester_init(&argc, &argv);
>
> - test_bredrle("test", NULL, setup, pass_test, teardown);
> + test_bredrle("Controller setup", NULL, setup_base, controller_setup,
> + teardown);
> +
> + test_bredrle("Test Enable - Success", &bluetooth_enable_success_test,
> + setup_base, test_enable, teardown);
Could you please split this in 2, one for each test, also I don't like
that we are adding a generic test then replacing it, make sure each
patch introduces code that are actually used by the test to make it
easier to review without having to look in other patches.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH v7 1/5] 6lowpan: Moving generic compression code into 6lowpan_iphc.c
From: Marcel Holtmann @ 2013-12-10 12:08 UTC (permalink / raw)
To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1386675457-26024-2-git-send-email-jukka.rissanen@linux.intel.com>
Hi Jukka,
> Because the IEEE 802154 and Bluetooth share the IP header compression
> and uncompression code, the common code is moved to 6lowpan_iphc.c
> file.
>
> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> net/ieee802154/6lowpan.c | 753 ++-------------------------------------
> net/ieee802154/6lowpan.h | 32 ++
> net/ieee802154/6lowpan_iphc.c | 807 ++++++++++++++++++++++++++++++++++++++++++
> net/ieee802154/Makefile | 2 +-
> 4 files changed, 875 insertions(+), 719 deletions(-)
> create mode 100644 net/ieee802154/6lowpan_iphc.c
what are we doing with this patch. Are we taking this through the bluetooth-next tree as well?
Regards
Marcel
^ permalink raw reply
* Re: [PATCH v7 4/5] Bluetooth: Enable 6LoWPAN support for BT LE devices
From: Marcel Holtmann @ 2013-12-10 12:06 UTC (permalink / raw)
To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1386675457-26024-5-git-send-email-jukka.rissanen@linux.intel.com>
Hi Jukka,
you might want to add a bit of commit message here.
> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> include/net/bluetooth/hci.h | 1 +
> include/net/bluetooth/hci_core.h | 1 +
> include/net/bluetooth/l2cap.h | 1 +
> net/bluetooth/6lowpan.c | 881 +++++++++++++++++++++++++++++++++++++++
> net/bluetooth/6lowpan.h | 26 ++
> net/bluetooth/Makefile | 6 +-
> net/bluetooth/hci_event.c | 3 +
> net/bluetooth/l2cap_core.c | 14 +-
> 8 files changed, 931 insertions(+), 2 deletions(-)
> create mode 100644 net/bluetooth/6lowpan.c
> create mode 100644 net/bluetooth/6lowpan.h
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index cc2da73..5dc3d90 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -131,6 +131,7 @@ enum {
> HCI_PERIODIC_INQ,
> HCI_FAST_CONNECTABLE,
> HCI_BREDR_ENABLED,
> + HCI_6LOWPAN_ENABLED,
> };
>
> /* A mask for the flags that are supposed to remain when a reset happens
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index b796161..f2f0cf5 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -448,6 +448,7 @@ enum {
> HCI_CONN_SSP_ENABLED,
> HCI_CONN_POWER_SAVE,
> HCI_CONN_REMOTE_OOB,
> + HCI_CONN_6LOWPAN,
> };
>
> static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index e149e99..dbc4a89 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -136,6 +136,7 @@ struct l2cap_conninfo {
> #define L2CAP_FC_L2CAP 0x02
> #define L2CAP_FC_CONNLESS 0x04
> #define L2CAP_FC_A2MP 0x08
> +#define L2CAP_FC_6LOWPAN 0x3e /* reserved and temporary value */
>
> /* L2CAP Control Field bit masks */
> #define L2CAP_CTRL_SAR 0xC000
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> new file mode 100644
> index 0000000..5b6966a
> --- /dev/null
> +++ b/net/bluetooth/6lowpan.c
> @@ -0,0 +1,881 @@
> +/*
> + Copyright (c) 2013 Intel Corp.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License version 2 and
> + only version 2 as published by the Free Software Foundation.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +*/
> +
> +#include <linux/version.h>
> +#include <linux/if_arp.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +
> +#include <net/ipv6.h>
> +#include <net/ip6_route.h>
> +#include <net/addrconf.h>
> +
> +#include <net/af_ieee802154.h> /* to get the address type */
Is this still needed? What address type is it that we need?
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +#include <net/bluetooth/l2cap.h>
> +
> +#include "../ieee802154/6lowpan.h" /* for the compression support */
> +
> +#define IFACE_NAME_TEMPLATE "bt%d"
> +#define EUI64_ADDR_LEN 8
> +
> +struct skb_cb {
> + struct in6_addr addr;
> + struct l2cap_conn *conn;
> +};
> +#define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
> +
> +/*
> + * The devices list contains those devices that we are acting
> + * as a proxy. The BT 6LoWPAN device is a virtual device that
> + * connects to the Bluetooth LE device. The real connection to
> + * BT device is done via l2cap layer. There exists one
> + * virtual device / one BT 6LoWPAN network (=hciX device).
> + * The list contains struct lowpan_dev elements.
> + */
> +static LIST_HEAD(bt_6lowpan_devices);
> +static DEFINE_RWLOCK(devices_lock);
> +
> +struct lowpan_dev {
> + struct net_device *dev;
> + struct work_struct delete_netdev;
> + struct list_head list;
> +};
> +
> +struct lowpan_peer {
> + struct list_head list;
> + struct l2cap_conn *conn;
> +
> + /* peer addresses in various formats */
> + unsigned char eui64_addr[EUI64_ADDR_LEN];
> + struct in6_addr peer_addr;
> +};
> +
> +struct lowpan_info {
> + struct net_device *net;
> + struct list_head peers;
> + atomic_t peer_count; /* number of items in peers list */
> +
> + struct delayed_work notify_peers;
> +};
> +
> +static inline struct lowpan_info *lowpan_info(const struct net_device *dev)
> +{
> + return netdev_priv(dev);
> +}
> +
> +static inline void peer_add(struct lowpan_info *info, struct lowpan_peer *peer)
> +{
> + list_add(&peer->list, &info->peers);
> + atomic_inc(&info->peer_count);
> +}
> +
> +static inline bool peer_del(struct lowpan_info *info, struct lowpan_peer *peer)
> +{
> + list_del(&peer->list);
I would add an extra empty line here.
> + if (atomic_dec_and_test(&info->peer_count)) {
> + BT_DBG("last peer");
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_info *info,
> + bdaddr_t *ba, __u8 type)
> +{
> + struct lowpan_peer *peer, *tmp;
> +
> + BT_DBG("peers %d addr %pMR type %d", atomic_read(&info->peer_count),
> + ba, type);
> +
> + list_for_each_entry_safe(peer, tmp, &info->peers, list) {
> + BT_DBG("addr %pMR type %d",
> + &peer->conn->hcon->dst, peer->conn->hcon->dst_type);
> +
> + if (!bacmp(&peer->conn->hcon->dst, ba))
> + return peer;
> + }
> +
> + return NULL;
> +}
> +
> +static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_info *info,
> + struct l2cap_conn *conn)
> +{
> + struct lowpan_peer *peer, *tmp;
> +
> + list_for_each_entry_safe(peer, tmp, &info->peers, list) {
> + if (peer->conn == conn)
> + return peer;
> + }
> +
> + return NULL;
> +}
> +
> +static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn,
> + struct lowpan_info **dev)
> +{
> + struct lowpan_dev *entry, *tmp;
> + struct lowpan_peer *peer = NULL;
> + unsigned long flags;
> +
> + read_lock_irqsave(&devices_lock, flags);
> +
> + list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
> + struct lowpan_info *info = lowpan_info(entry->dev);
> +
> + peer = peer_lookup_conn(info, conn);
> + if (peer) {
> + if (dev)
> + *dev = info;
> + break;
> + }
> + }
> +
> + read_unlock_irqrestore(&devices_lock, flags);
> +
> + return peer;
> +}
> +
> +/* print data in line */
> +static inline void raw_dump_inline(const char *caller, char *msg,
> + unsigned char *buf, int len)
> +{
> + if (msg)
> + pr_debug("%s():%s: ", caller, msg);
> + print_hex_dump_debug("", DUMP_PREFIX_NONE,
> + 16, 1, buf, len, false);
> +}
> +
> +/*
> + * print data in a table format:
> + *
> + * addr: xx xx xx xx xx xx
> + * addr: xx xx xx xx xx xx
> + * ...
> + */
> +static inline void raw_dump_table(const char *caller, char *msg,
> + unsigned char *buf, int len)
> +{
> + if (msg)
> + pr_debug("%s():%s:\n", caller, msg);
> + print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET,
> + 16, 1, buf, len, false);
> +}
> +
> +static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct sk_buff *skb_cp;
> + int ret = NET_RX_SUCCESS;
> +
> + skb_cp = skb_copy(skb, GFP_ATOMIC);
> + if (!skb_cp) {
> + ret = -ENOMEM;
And reason we are not just doing this:
return -ENOMEM;
> + } else {
> + ret = netif_rx(skb_cp);
> +
> + BT_DBG("receive skb %d", ret);
> + if (ret < 0)
> + ret = NET_RX_DROP;
> + }
> +
> + return ret;
> +}
> +
> +static int process_data(struct sk_buff *skb, struct net_device *dev,
> + struct l2cap_conn *conn)
> +{
> + const u8 *saddr, *daddr;
> + u8 iphc0, iphc1;
> + struct lowpan_info *info;
> + struct lowpan_peer *peer;
> + unsigned long flags;
> +
> + info = lowpan_info(dev);
> +
> + read_lock_irqsave(&devices_lock, flags);
> + peer = peer_lookup_conn(info, conn);
> + read_unlock_irqrestore(&devices_lock, flags);
> + if (!peer)
> + return -EINVAL;
> +
> + saddr = peer->eui64_addr;
> + daddr = info->net->dev_addr;
> +
> + /* at least two bytes will be used for the encoding */
> + if (skb->len < 2)
> + goto drop;
> +
> + if (lowpan_fetch_skb_u8(skb, &iphc0))
> + goto drop;
> +
> + if (lowpan_fetch_skb_u8(skb, &iphc1))
> + goto drop;
> +
> + return lowpan_process_data(skb, dev,
> + saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
> + daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
> + iphc0, iphc1, give_skb_to_upper);
> +
> +drop:
> + kfree_skb(skb);
> + return -EINVAL;
> +}
> +
> +static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
> + struct l2cap_conn *conn)
> +{
> + struct sk_buff *local_skb;
> +
> + if (!netif_running(dev))
> + goto drop;
> +
> + if (dev->type != ARPHRD_6LOWPAN)
> + goto drop;
> +
> + /* check that it's our buffer */
> + if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
> + /* Copy the packet so that the IPv6 header is
> + * properly aligned.
> + */
> + local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1,
> + skb_tailroom(skb), GFP_ATOMIC);
> + if (!local_skb)
> + goto drop;
> +
> + local_skb->protocol = htons(ETH_P_IPV6);
> + local_skb->pkt_type = PACKET_HOST;
> +
> + skb_reset_network_header(local_skb);
> + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
> +
> + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) {
> + kfree_skb(local_skb);
> + goto drop;
> + }
> +
> + dev->stats.rx_bytes += skb->len;
> + dev->stats.rx_packets++;
> +
> + kfree_skb(local_skb);
> + kfree_skb(skb);
> + } else {
> + switch (skb->data[0] & 0xe0) {
> + case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
> + local_skb = skb_clone(skb, GFP_ATOMIC);
> + if (!local_skb)
> + goto drop;
> + if (process_data(local_skb, dev, conn)
> + != NET_RX_SUCCESS)
> + goto drop;
> +
> + dev->stats.rx_bytes += skb->len;
> + dev->stats.rx_packets++;
> +
> + kfree_skb(skb);
> + break;
> + default:
> + break;
> + }
> + }
> +
> + return NET_RX_SUCCESS;
> +
> +drop:
> + kfree_skb(skb);
> + return NET_RX_DROP;
> +}
> +
> +/* Packet from BT LE device */
> +int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
> +{
> + struct lowpan_info *info = NULL;
> + struct lowpan_peer *peer;
> + int err;
> +
> + peer = lookup_peer(conn, &info);
> + if (!peer)
> + return -ENOENT;
> +
> + if (info->net) {
> + err = recv_pkt(skb, info->net, conn);
> + BT_DBG("recv pkt %d", err);
> + } else {
> + err = -ENOENT;
> + }
I would just do this:
if (!info->net)
return -ENOENT;
> +
> + return err;
> +}
> +
> +static void do_send(struct l2cap_conn *conn, struct sk_buff *skb)
> +{
> + BT_DBG("conn %p, skb %p len %d priority %u", conn, skb, skb->len,
> + skb->priority);
> +
> + hci_send_acl(conn->hchan, skb, ACL_START);
> +}
> +
> +static inline int skbuff_copy(void *msg, int len, int count, int mtu,
> + struct sk_buff *skb, struct net_device *dev)
> +{
> + struct sk_buff **frag;
> + int sent = 0;
> +
> + memcpy(skb_put(skb, count), msg, count);
> +
> + sent += count;
> + msg += count;
> + len -= count;
> +
> + dev->stats.tx_bytes += count;
> + dev->stats.tx_packets++;
> +
> + raw_dump_table(__func__, "Sending", skb->data, skb->len);
> +
> + /* Continuation fragments (no L2CAP header) */
> + frag = &skb_shinfo(skb)->frag_list;
> + while (len > 0) {
> + struct sk_buff *tmp;
> +
> + count = min_t(unsigned int, mtu, len);
> +
> + tmp = bt_skb_alloc(count, GFP_ATOMIC);
> + if (IS_ERR(tmp))
> + return PTR_ERR(tmp);
> +
> + *frag = tmp;
> +
> + memcpy(skb_put(*frag, count), msg, count);
> +
> + raw_dump_table(__func__, "Sending fragment",
> + (*frag)->data, count);
> +
> + (*frag)->priority = skb->priority;
> +
> + sent += count;
> + msg += count;
> + len -= count;
> +
> + skb->len += (*frag)->len;
> + skb->data_len += (*frag)->len;
> +
> + frag = &(*frag)->next;
> +
> + dev->stats.tx_bytes += count;
> + dev->stats.tx_packets++;
> + }
> +
> + return sent;
> +}
> +
> +static struct sk_buff *create_pdu(struct l2cap_conn *conn, void *msg,
> + size_t len, u32 priority,
> + struct net_device *dev)
> +{
> + struct sk_buff *skb;
> + int err, count;
> + struct l2cap_hdr *lh;
> +
> + if (conn->mtu > (L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE))
> + /* XXX: This should be not needed and atm is only used for
> + * testing purposes */
> + conn->mtu = L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE;
The comment should go above the if itself.
> +
> + count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
> +
> + BT_DBG("conn %p len %zu mtu %d count %d", conn, len, conn->mtu, count);
> +
> + skb = bt_skb_alloc(count + L2CAP_HDR_SIZE, GFP_ATOMIC);
> + if (IS_ERR(skb))
> + return skb;
> +
> + skb->priority = priority;
> +
> + lh = (struct l2cap_hdr *)skb_put(skb, L2CAP_HDR_SIZE);
> + lh->cid = cpu_to_le16(L2CAP_FC_6LOWPAN);
> + lh->len = cpu_to_le16(len);
> +
> + err = skbuff_copy(msg, len, count, conn->mtu, skb, dev);
> + if (unlikely(err < 0)) {
> + kfree_skb(skb);
> + BT_DBG("skbuff copy %d failed", err);
> + return ERR_PTR(err);
> + }
> +
> + return skb;
> +}
> +
> +static int conn_send(struct l2cap_conn *conn,
> + void *msg, size_t len, u32 priority,
> + struct net_device *dev)
> +{
> + struct sk_buff *skb;
> +
> + skb = create_pdu(conn, msg, len, priority, dev);
> + if (IS_ERR(skb))
> + return -EINVAL;
> +
> + do_send(conn, skb);
> + return 0;
> +}
> +
> +static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
> + bdaddr_t *addr, u8 *addr_type)
> +{
> + u8 *eui64;
> +
> + eui64 = ip6_daddr->s6_addr + 8;
> +
> + addr->b[0] = eui64[7];
> + addr->b[1] = eui64[6];
> + addr->b[2] = eui64[5];
> + addr->b[3] = eui64[2];
> + addr->b[4] = eui64[1];
> + addr->b[5] = eui64[0];
> +
> + addr->b[5] ^= 2;
> +
> + /* Set universal/local bit to 0 */
> + if (addr->b[5] & 1) {
> + addr->b[5] &= ~1;
> + *addr_type = BDADDR_LE_PUBLIC;
> + } else
> + *addr_type = BDADDR_LE_RANDOM;
> +}
> +
> +static int header_create(struct sk_buff *skb, struct net_device *dev,
> + unsigned short type, const void *_daddr,
> + const void *_saddr, unsigned int len)
> +{
> + struct ipv6hdr *hdr;
> + struct lowpan_info *info;
> + struct lowpan_peer *peer;
> + bdaddr_t addr, *any = BDADDR_ANY;
> + u8 *saddr, *daddr = any->b;
> + u8 addr_type;
> +
> + if (type != ETH_P_IPV6)
> + return -EINVAL;
> +
> + hdr = ipv6_hdr(skb);
> +
> + info = lowpan_info(dev);
> +
> + if (ipv6_addr_is_multicast(&hdr->daddr)) {
> + memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
> + sizeof(struct in6_addr));
> + lowpan_cb(skb)->conn = NULL;
> + } else {
> + unsigned long flags;
> +
> + /*
> + * Get destination BT device from skb.
> + * If there is no such peer then discard the packet.
> + */
> + get_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
> +
> + BT_DBG("dest addr %pMR type %d", &addr, addr_type);
> +
> + read_lock_irqsave(&devices_lock, flags);
> + peer = peer_lookup_ba(info, &addr, addr_type);
> + read_unlock_irqrestore(&devices_lock, flags);
> +
> + if (!peer) {
> + BT_DBG("no such peer %pMR found", &addr);
> + return -ENOENT;
> + }
> +
> + daddr = peer->eui64_addr;
> +
> + memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
> + sizeof(struct in6_addr));
> + lowpan_cb(skb)->conn = peer->conn;
> + }
> +
> + saddr = info->net->dev_addr;
> +
> + return lowpan_header_compress(skb, dev, type, daddr, saddr, len);
> +}
> +
> +/* Packet to BT LE device */
> +static int send_pkt(struct l2cap_conn *conn, const void *saddr,
> + const void *daddr, struct sk_buff *skb,
> + struct net_device *dev)
> +{
> + raw_dump_table(__func__, "raw skb data dump before fragmentation",
> + skb->data, skb->len);
> +
> + return conn_send(conn, skb->data, skb->len, 0, dev);
> +}
> +
> +static int send_mcast_pkt(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct sk_buff *local_skb;
> + struct lowpan_dev *entry, *tmp;
> + int err = 0;
> + unsigned long flags;
> +
> + read_lock_irqsave(&devices_lock, flags);
> +
> + list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
> + struct lowpan_peer *pentry, *ptmp;
> + struct lowpan_info *info;
> +
> + if (entry->dev != dev)
> + continue;
> +
> + info = lowpan_info(entry->dev);
> +
> + list_for_each_entry_safe(pentry, ptmp, &info->peers, list) {
> + local_skb = skb_clone(skb, GFP_ATOMIC);
> +
> + err = send_pkt(pentry->conn, dev->dev_addr,
> + pentry->eui64_addr,
> + local_skb, dev);
> +
> + kfree_skb(local_skb);
> + }
> + }
> +
> + read_unlock_irqrestore(&devices_lock, flags);
> +
> + return err;
> +}
> +
> +static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + int err = -ENOENT;
> + unsigned char *eui64_addr;
> + struct lowpan_info *info;
> + struct lowpan_peer *peer;
> + bdaddr_t addr;
> + u8 addr_type;
> +
> + if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) {
> + /*
> + * We need to send the packet to every device
> + * behind this interface.
> + */
> + err = send_mcast_pkt(skb, dev);
> + } else {
> + unsigned long flags;
> +
> + get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
> + eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
> + info = lowpan_info(dev);
> +
> + read_lock_irqsave(&devices_lock, flags);
> + peer = peer_lookup_ba(info, &addr, addr_type);
> + read_unlock_irqrestore(&devices_lock, flags);
> +
> + BT_DBG("xmit from %s to %pMR (%pI6c), peer %p", dev->name,
> + &addr, &lowpan_cb(skb)->addr, peer);
> +
> + if (peer && peer->conn)
> + err = send_pkt(peer->conn, dev->dev_addr, eui64_addr,
> + skb, dev);
> + }
> + dev_kfree_skb(skb);
> +
> + if (err)
> + BT_DBG("ERROR: xmit failed (%d)", err);
> +
> + return (err < 0) ? NET_XMIT_DROP : err;
> +}
> +
> +static const struct net_device_ops netdev_ops = {
> + .ndo_start_xmit = bt_xmit,
> +};
> +
> +static struct header_ops header_ops = {
> + .create = header_create,
> +};
> +
> +static void netdev_setup(struct net_device *dev)
> +{
> + dev->addr_len = EUI64_ADDR_LEN;
> + dev->type = ARPHRD_6LOWPAN;
> +
> + dev->hard_header_len = 0;
> + dev->needed_tailroom = 0;
> + dev->mtu = IPV6_MIN_MTU;
> + dev->tx_queue_len = 0;
> + dev->flags = IFF_RUNNING | IFF_POINTOPOINT;
> + dev->watchdog_timeo = 0;
> +
> + dev->netdev_ops = &netdev_ops;
> + dev->header_ops = &header_ops;
> + dev->destructor = free_netdev;
> +}
> +
> +static struct device_type bt_type = {
> + .name = "bluetooth",
> +};
> +
> +static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
> +{
> + /* addr is the BT address in little-endian format */
> + eui[0] = addr[5];
> + eui[1] = addr[4];
> + eui[2] = addr[3];
> + eui[3] = 0xFF;
> + eui[4] = 0xFE;
> + eui[5] = addr[2];
> + eui[6] = addr[1];
> + eui[7] = addr[0];
> +
> + eui[0] ^= 2;
> +
> + /*
> + * Universal/local bit set, RFC 4291
> + */
Single line comment here.
> + if (addr_type == BDADDR_LE_PUBLIC)
> + eui[0] |= 1;
> + else
> + eui[0] &= ~1;
> +}
> +
> +static void set_dev_addr(struct net_device *net, bdaddr_t *addr,
> + u8 addr_type)
> +{
> + net->addr_assign_type = NET_ADDR_PERM;
> + set_addr(net->dev_addr, addr->b, addr_type);
> + net->dev_addr[0] ^= 2;
> +}
If you use set_addr only here, consider putting it directly into set_dev_addr.
> +
> +static void ifup(struct net_device *net)
> +{
> + int err;
> +
> + rtnl_lock();
> + err = dev_open(net);
> + if (err < 0)
> + BT_INFO("iface %s cannot be opened (%d)", net->name, err);
> + rtnl_unlock();
> +}
> +
> +static void do_notify_peers(struct work_struct *work)
> +{
> + struct lowpan_info *info = container_of(work, struct lowpan_info,
> + notify_peers.work);
> +
> + netdev_notify_peers(info->net); /* send neighbour adv at startup */
> +}
> +
> +static bool is_bt_6lowpan(struct hci_conn *hcon)
> +{
> + if (hcon->type == LE_LINK && test_bit(HCI_CONN_6LOWPAN, &hcon->flags))
> + return true;
> +
> + return false;
if (hcon->type != LE_LINK)
return false;
return test_bit(HCI_CONN_6LOWPAN, &hcon->flags);
> +}
> +
> +/*
> + * This gets called when BT LE 6LoWPAN device is connected. We then
> + * create network device that acts as a proxy between BT LE device
> + * and kernel network stack.
> + */
> +int bt_6lowpan_add_conn(struct l2cap_conn *conn)
> +{
> + struct lowpan_info *dev = NULL;
> + struct lowpan_peer *peer = NULL;
> + struct net_device *net;
> + struct lowpan_dev *entry;
> + int err = 0;
> + unsigned long flags;
> +
> + if (!is_bt_6lowpan(conn->hcon))
> + return 0;
> +
> + peer = lookup_peer(conn, &dev);
> + if (peer)
> + return -EEXIST;
> +
> + if (dev && !peer)
> + goto add_peer;
> +
> + net = alloc_netdev(sizeof(struct lowpan_info), IFACE_NAME_TEMPLATE,
> + netdev_setup);
> + if (!net)
> + return -ENOMEM;
> +
> + dev = netdev_priv(net);
> + dev->net = net;
> + INIT_LIST_HEAD(&dev->peers);
> +
> + set_dev_addr(net, &conn->hcon->src, conn->hcon->src_type);
> +
> + net->netdev_ops = &netdev_ops;
> + SET_NETDEV_DEV(net, &conn->hcon->dev);
> + SET_NETDEV_DEVTYPE(net, &bt_type);
> +
> + err = register_netdev(net);
> + if (err < 0) {
> + BT_INFO("register_netdev failed %d", err);
> + free_netdev(net);
> + goto out;
> + }
> +
> + BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR",
> + net->ifindex, &conn->hcon->dst, &conn->hcon->src);
> + set_bit(__LINK_STATE_PRESENT, &net->state);
> +
> + entry = kzalloc(sizeof(struct lowpan_dev), GFP_ATOMIC);
> + if (!entry) {
> + unregister_netdev(net);
> + return -ENOMEM;
> + }
> +
> + entry->dev = net;
> +
> + write_lock_irqsave(&devices_lock, flags);
> + INIT_LIST_HEAD(&entry->list);
> + list_add(&entry->list, &bt_6lowpan_devices);
> + write_unlock_irqrestore(&devices_lock, flags);
> +
> + ifup(net);
> +
> +add_peer:
> + peer = kzalloc(sizeof(struct lowpan_peer), GFP_ATOMIC);
> + if (!peer)
> + return -ENOMEM;
> +
> + peer->conn = conn;
> + memset(&peer->peer_addr, 0, sizeof(struct in6_addr));
> +
> + /* RFC 2464 ch. 5 */
> + peer->peer_addr.s6_addr[0] = 0xFE;
> + peer->peer_addr.s6_addr[1] = 0x80;
> + set_addr((u8 *)&peer->peer_addr.s6_addr + 8, conn->hcon->dst.b,
> + conn->hcon->dst_type);
> +
> + memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8,
> + EUI64_ADDR_LEN);
> + peer->eui64_addr[0] ^= 2; /* second bit-flip (Universe/Local)
> + * is done according RFC2464
> + */
> +
> + raw_dump_inline(__func__, "peer IPv6 address",
> + (unsigned char *)&peer->peer_addr, 16);
> + raw_dump_inline(__func__, "peer EUI64 address", peer->eui64_addr, 8);
> +
> + write_lock_irqsave(&devices_lock, flags);
> + INIT_LIST_HEAD(&peer->list);
> + peer_add(dev, peer);
> + write_unlock_irqrestore(&devices_lock, flags);
> +
> + /*
> + * Notifying peers about us needs to be done without locks held
> + */
> + INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers);
> + schedule_delayed_work(&dev->notify_peers, msecs_to_jiffies(100));
> +
> +out:
> + return err;
> +}
> +
> +static void delete_netdev(struct work_struct *work)
> +{
> + struct lowpan_dev *entry = container_of(work, struct lowpan_dev,
> + delete_netdev);
> +
> + unregister_netdev(entry->dev);
> +
> + /* The entry pointer is deleted in device_event() */
> +}
> +
> +int bt_6lowpan_del_conn(struct l2cap_conn *conn)
> +{
> + struct lowpan_dev *entry, *tmp;
> + struct lowpan_info *info = NULL;
> + struct lowpan_peer *peer;
> + int err = -ENOENT;
> + unsigned long flags;
> + bool last = false;
> +
> + if (!is_bt_6lowpan(conn->hcon))
> + return 0;
> +
> + write_lock_irqsave(&devices_lock, flags);
> +
> + list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
> + info = lowpan_info(entry->dev);
> + peer = peer_lookup_conn(info, conn);
> + if (peer) {
> + last = peer_del(info, peer);
> + err = 0;
> + break;
> + }
> + }
> +
> + if (!err && last && info && !atomic_read(&info->peer_count)) {
> + write_unlock_irqrestore(&devices_lock, flags);
> +
> + cancel_delayed_work_sync(&info->notify_peers);
> +
> + /*
> + * bt_6lowpan_del_conn() is called with hci dev lock held which
> + * means that we must delete the netdevice in worker thread.
> + */
> + INIT_WORK(&entry->delete_netdev, delete_netdev);
> + schedule_work(&entry->delete_netdev);
> + } else
> + write_unlock_irqrestore(&devices_lock, flags);
> +
> + return err;
> +}
> +
> +static int device_event(struct notifier_block *unused,
> + unsigned long event, void *ptr)
> +{
> + struct net_device *dev = netdev_notifier_info_to_dev(ptr);
> + struct lowpan_dev *entry, *tmp;
> + unsigned long flags;
> +
> + if (dev->type != ARPHRD_6LOWPAN)
> + return NOTIFY_DONE;
> +
> + switch (event) {
> + case NETDEV_UNREGISTER:
> + write_lock_irqsave(&devices_lock, flags);
> + list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
> + list) {
> + if (entry->dev == dev) {
> + list_del(&entry->list);
> + kfree(entry);
> + break;
> + }
> + }
> + write_unlock_irqrestore(&devices_lock, flags);
> + break;
> + }
> +
> + return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block bt_6lowpan_dev_notifier = {
> + .notifier_call = device_event,
> +};
> +
> +int bt_6lowpan_init(void)
> +{
> + return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
> +}
> +
> +void bt_6lowpan_cleanup(void)
> +{
> + unregister_netdevice_notifier(&bt_6lowpan_dev_notifier);
> +}
> diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
> new file mode 100644
> index 0000000..680eac8
> --- /dev/null
> +++ b/net/bluetooth/6lowpan.h
> @@ -0,0 +1,26 @@
> +/*
> + Copyright (c) 2013 Intel Corp.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License version 2 and
> + only version 2 as published by the Free Software Foundation.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +*/
> +
> +#ifndef __6LOWPAN_H
> +#define __6LOWPAN_H
> +
> +#include <linux/skbuff.h>
> +#include <net/bluetooth/l2cap.h>
> +
> +int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
> +int bt_6lowpan_add_conn(struct l2cap_conn *conn);
> +int bt_6lowpan_del_conn(struct l2cap_conn *conn);
> +int bt_6lowpan_init(void);
> +void bt_6lowpan_cleanup(void);
> +
> +#endif /* __6LOWPAN_H */
> diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
> index 6a791e7..cc6827e 100644
> --- a/net/bluetooth/Makefile
> +++ b/net/bluetooth/Makefile
> @@ -10,6 +10,10 @@ obj-$(CONFIG_BT_HIDP) += hidp/
>
> bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
> hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
> - a2mp.o amp.o
> + a2mp.o amp.o 6lowpan.o
> +
> +ifeq ($(CONFIG_IEEE802154_6LOWPAN),)
> + bluetooth-y += ../ieee802154/6lowpan_iphc.o
> +endif
>
> subdir-ccflags-y += -D__CHECK_ENDIAN__
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 5fb3df6..5f81245 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -3533,6 +3533,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
> conn->handle = __le16_to_cpu(ev->handle);
> conn->state = BT_CONNECTED;
>
> + if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
> + set_bit(HCI_CONN_6LOWPAN, &conn->flags);
> +
> hci_conn_add_sysfs(conn);
>
> hci_proto_connect_cfm(conn, ev->status);
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index ae0054c..9d6e952 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -40,6 +40,7 @@
> #include "smp.h"
> #include "a2mp.h"
> #include "amp.h"
> +#include "6lowpan.h"
>
> bool disable_ertm;
>
> @@ -7093,6 +7094,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
> l2cap_conn_del(conn->hcon, EACCES);
> break;
>
> + case L2CAP_FC_6LOWPAN:
> + bt_6lowpan_recv(conn, skb);
> + break;
> +
> default:
> l2cap_data_channel(conn, cid, skb);
> break;
> @@ -7138,8 +7143,10 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
>
> if (!status) {
> conn = l2cap_conn_add(hcon);
> - if (conn)
> + if (conn) {
> l2cap_conn_ready(conn);
> + bt_6lowpan_add_conn(conn);
> + }
Didn’t Johan add an l2cap_le_conn_ready for the LE CoC support.
> } else {
> l2cap_conn_del(hcon, bt_to_errno(status));
> }
> @@ -7160,6 +7167,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
> {
> BT_DBG("hcon %p reason %d", hcon, reason);
>
> + bt_6lowpan_del_conn(hcon->l2cap_data);
> +
> l2cap_conn_del(hcon, bt_to_errno(reason));
> }
>
> @@ -7441,11 +7450,14 @@ int __init l2cap_init(void)
> debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
> &le_default_mps);
>
> + bt_6lowpan_init();
> +
> return 0;
> }
>
> void l2cap_exit(void)
> {
> + bt_6lowpan_cleanup();
> debugfs_remove(l2cap_debugfs);
> l2cap_cleanup_sockets();
> }
Regards
Marcel
^ permalink raw reply
* [PATCH] hciemu: Make code consistent
From: Andrei Emeltchenko @ 2013-12-10 12:01 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
It is enough to check for zero in __sync_sub_and_fetch(). This makes
code consistent like shown below:
./src/shared/mgmt.c: if (__sync_sub_and_fetch(&mgmt->ref_count, 1))
./src/shared/pcap.c: if (__sync_sub_and_fetch(&pcap->ref_count, 1))
./src/shared/btsnoop.c: if (__sync_sub_and_fetch(&btsnoop->ref_count, 1))
./src/shared/hciemu.c: if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
---
src/shared/hciemu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/hciemu.c b/src/shared/hciemu.c
index 0ea191f..c2b4748 100644
--- a/src/shared/hciemu.c
+++ b/src/shared/hciemu.c
@@ -341,7 +341,7 @@ void hciemu_unref(struct hciemu *hciemu)
if (!hciemu)
return;
- if (__sync_sub_and_fetch(&hciemu->ref_count, 1) > 0)
+ if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
return;
g_list_foreach(hciemu->post_command_hooks, destroy_command_hook, NULL);
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH v7 5/5] Bluetooth: Manually enable or disable 6LoWPAN between devices
From: Marcel Holtmann @ 2013-12-10 11:55 UTC (permalink / raw)
To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1386675457-26024-6-git-send-email-jukka.rissanen@linux.intel.com>
Hi Jukka,
> This is a temporary patch where user can manually enable or
> disable BT 6LoWPAN functionality between devices.
> Eventually the connection is established automatically if
> the devices are advertising suitable capability and this patch
> can be removed.
>
> Before connecting the devices do this
>
> echo 1 > /sys/kernel/debug/bluetooth/hci0/6lowpan
>
> This enables 6LoWPAN support and creates the bt0 interface
> automatically when devices are finally connected.
>
> Rebooting or unloading the bluetooth kernel module will also clear the
> settings from the kernel.
>
> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> net/bluetooth/hci_core.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 93 insertions(+)
>
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 8b8b5f8..e289072 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -636,6 +636,97 @@ static int conn_max_interval_get(void *data, u64 *val)
> DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
> conn_max_interval_set, "%llu\n");
>
> +static LIST_HEAD(lowpan_user_enabled);
> +static DEFINE_RWLOCK(lowpan_enabled_lock);
> +
> +struct lowpan_enabled {
> + __u8 dev_name[HCI_MAX_NAME_LENGTH];
> + bool enabled;
> + struct list_head list;
> +};
> +
> +static int lowpan_debugfs_show(struct seq_file *f, void *p)
> +{
> + struct hci_dev *hdev = f->private;
> +
> + if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
> + seq_printf(f, "1\n");
> + else
> + seq_printf(f, "0\n");
> +
> + return 0;
> +}
I think we should do Y and N here. Check how I implemented dut_mode. No need to use seq_printf here.
> +
> +static int lowpan_debugfs_open(struct inode *inode, struct file *file)
> +{
> + return single_open(file, lowpan_debugfs_show, inode->i_private);
> +}
> +
> +static ssize_t lowpan_writer(struct file *fp, const char __user *user_buffer,
> + size_t count, loff_t *position)
> +{
> + struct hci_dev *hdev = fp->f_inode->i_private;
> + struct lowpan_enabled *entry = NULL, *tmp;
> + bool new_value, old_value;
> + char buf[3] = { 0 };
> + ssize_t ret;
> +
> + BT_DBG("dev %s count %zd", hdev->dev_name, count);
> +
> + ret = simple_write_to_buffer(buf, 2, position, user_buffer, count);
Spaces?
> + if (ret <= 0)
> + return ret;
> +
> + if (strtobool(buf, &new_value) < 0)
> + return -EINVAL;
> +
> + ret = -ENOENT;
> +
> + write_lock(&lowpan_enabled_lock);
> + list_for_each_entry_safe(entry, tmp, &lowpan_user_enabled, list) {
> + if (!strncmp(entry->dev_name, hdev->dev_name,
> + HCI_MAX_NAME_LENGTH)) {
> + old_value = entry->enabled;
> + entry->enabled = new_value;
> + ret = 0;
> + break;
> + }
> + }
> + write_unlock(&lowpan_enabled_lock);
Why are we testing the dev_name here and not dev_id?
> +
> + if (ret == 0 && old_value == new_value)
> + return count;
> +
> + if (ret < 0) {
> + entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> + if (!entry)
> + return -ENOMEM;
> +
> + strncpy(entry->dev_name, hdev->dev_name, HCI_MAX_NAME_LENGTH);
> + entry->enabled = new_value;
> +
> + write_lock(&lowpan_enabled_lock);
> + INIT_LIST_HEAD(&entry->list);
> + list_add(&entry->list, &lowpan_user_enabled);
> + write_unlock(&lowpan_enabled_lock);
> + }
> +
> + if (new_value == true)
> + set_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
> + else
> + clear_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
I might be just missing something here, but do we need to track the list of enabled HCI controllers twice. The core tracks the controller list. We can just enumerate over it and flip the bit, right?
> +
> + return count;
> +}
> +
> +static const struct file_operations lowpan_debugfs_fops = {
> + .open = lowpan_debugfs_open,
> + .read = seq_read,
> + .write = lowpan_writer,
> + .llseek = seq_lseek,
> + .release = single_release,
> +};
> +
> /* ---- HCI requests ---- */
>
> static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
> @@ -1406,6 +1497,8 @@ static int __hci_init(struct hci_dev *hdev)
> hdev, &conn_min_interval_fops);
> debugfs_create_file("conn_max_interval", 0644, hdev->debugfs,
> hdev, &conn_max_interval_fops);
> + debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
> + &lowpan_debugfs_fops);
> }
Regards
Marcel
^ permalink raw reply
* Re: [PATCH] bnep: Remove unneeded assignment
From: Luiz Augusto von Dentz @ 2013-12-10 11:40 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1386598648-31619-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Mon, Dec 9, 2013 at 4:17 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> ---
> profiles/network/bnep.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
> index 0a719a2..912c0c2 100644
> --- a/profiles/network/bnep.c
> +++ b/profiles/network/bnep.c
> @@ -88,7 +88,6 @@ static void free_bnep_connect(struct bnep_conn *bc)
> }
>
> g_free(bc);
> - bc = NULL;
> }
>
> uint16_t bnep_service_id(const char *svc)
> --
> 1.8.3.2
Pushed, thanks.
--
Luiz Augusto von Dentz
^ 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