* [PATCHv5 1/3] android: Create debug hal-utils helpers
From: Andrei Emeltchenko @ 2013-11-08 13:15 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Create hal-utils helpers which helps to decode packets Android
sends through HAL interface.
---
android/Android.mk | 2 ++
android/Makefile.am | 3 ++-
android/client/if-gatt.c | 1 +
android/client/textconv.c | 42 ++------------------------------
android/client/textconv.h | 2 --
android/hal-utils.c | 58 +++++++++++++++++++++++++++++++++++++++++++++
android/hal-utils.h | 26 ++++++++++++++++++++
7 files changed, 91 insertions(+), 43 deletions(-)
create mode 100644 android/hal-utils.c
create mode 100644 android/hal-utils.h
diff --git a/android/Android.mk b/android/Android.mk
index 51037a7..0bc0e82 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -88,6 +88,7 @@ LOCAL_SRC_FILES := \
hal-pan.c \
hal-a2dp.c \
client/textconv.c \
+ hal-utils.c \
LOCAL_C_INCLUDES += \
$(call include-path-for, system-core) \
@@ -125,6 +126,7 @@ LOCAL_SRC_FILES := \
client/if-hh.c \
client/if-pan.c \
client/if-sock.c \
+ hal-utils.c \
ANDROID_4_3_OR_ABOVE := $(shell echo 0 | awk -v v=$(PLATFORM_SDK_VERSION) 'END {print (v > 17) ? 1 : 0}')
diff --git a/android/Makefile.am b/android/Makefile.am
index 073edc8..debe7c1 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -68,7 +68,8 @@ android_haltest_SOURCES = android/client/haltest.c \
android/client/if-hh.c \
android/client/if-pan.c \
android/client/if-sock.c \
- android/client/hwmodule.c
+ android/client/hwmodule.c \
+ android/hal-utils.h android/hal-utils.c
android_haltest_LDADD = android/libhal-internal.la
diff --git a/android/client/if-gatt.c b/android/client/if-gatt.c
index b2b20cb..bb53952 100644
--- a/android/client/if-gatt.c
+++ b/android/client/if-gatt.c
@@ -17,6 +17,7 @@
#include <hardware/bluetooth.h>
+#include "../hal-utils.h"
#include "if-main.h"
const btgatt_interface_t *if_gatt = NULL;
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 4def3da..469b2c3 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
#include <stdio.h>
#include <hardware/bluetooth.h>
+#include "../hal-utils.h"
+
#include "textconv.h"
/*
@@ -154,39 +156,6 @@ void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
&p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
}
-static const char BT_BASE_UUID[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
-};
-
-/*
- * converts uuid to string
- * buf should be at least 39 bytes
- *
- * returns string representation of uuid
- */
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
-{
- int shift = 0;
- int i;
- int is_bt;
-
- is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
-
- for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
- if (i == 4 && is_bt)
- break;
-
- if (i == 4 || i == 6 || i == 8 || i == 10) {
- buf[i * 2 + shift] = '-';
- shift++;
- }
- sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
- }
-
- return buf;
-}
-
/* converts string to uuid */
void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
{
@@ -234,13 +203,6 @@ char *bdaddr2str(const bt_bdaddr_t *bd_addr)
return bt_bdaddr_t2str(bd_addr, buf);
}
-static char *btuuid2str(const bt_uuid_t *uuid)
-{
- static char buf[MAX_UUID_STR_LEN];
-
- return bt_uuid_t2str(uuid, buf);
-}
-
char *btproperty2str(const bt_property_t *property)
{
static char buf[4096];
diff --git a/android/client/textconv.h b/android/client/textconv.h
index 1c848ef..837eb4e 100644
--- a/android/client/textconv.h
+++ b/android/client/textconv.h
@@ -103,8 +103,6 @@ static struct int2str __##type##2str[] = {
char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
-#define MAX_UUID_STR_LEN 37
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
char *btproperty2str(const bt_property_t *property);
diff --git a/android/hal-utils.c b/android/hal-utils.c
new file mode 100644
index 0000000..84cfad1
--- /dev/null
+++ b/android/hal-utils.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <hardware/bluetooth.h>
+
+#include "hal-utils.h"
+
+/*
+ * converts uuid to string
+ * buf should be at least 39 bytes
+ *
+ * returns string representation of uuid
+ */
+char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+{
+ int shift = 0;
+ int i;
+ int is_bt;
+
+ is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+
+ for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
+ if (i == 4 && is_bt)
+ break;
+
+ if (i == 4 || i == 6 || i == 8 || i == 10) {
+ buf[i * 2 + shift] = '-';
+ shift++;
+ }
+ sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+ }
+
+ return buf;
+}
+
+char *btuuid2str(const bt_uuid_t *uuid)
+{
+ static char buf[MAX_UUID_STR_LEN];
+
+ return bt_uuid_t2str(uuid, buf);
+}
diff --git a/android/hal-utils.h b/android/hal-utils.h
new file mode 100644
index 0000000..d40b430
--- /dev/null
+++ b/android/hal-utils.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ */
+
+#define MAX_UUID_STR_LEN 37
+
+static const char BT_BASE_UUID[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
+};
+
+char *btuuid2str(const bt_uuid_t *uuid);
+char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 2/3] android/debug: Convert uuid helper to use uint8_t buffer
From: Andrei Emeltchenko @ 2013-11-08 13:16 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383916561-9719-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
At this moment Android uses uint8_t * and bt_uuid_t for representing
UUID for different HALs. Convert debug helper to use uint8_t * string.
---
android/client/textconv.c | 7 +++++--
android/hal-utils.c | 15 +++++++--------
android/hal-utils.h | 7 ++++---
3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 469b2c3..ebf6316 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -272,7 +272,9 @@ char *btproperty2str(const bt_property_t *property)
strcat(p, "{");
while (count--) {
- strcat(p, btuuid2str((bt_uuid_t *) ptr));
+ bt_uuid_t *uuid = (bt_uuid_t *) ptr;
+
+ strcat(p, btuuid2str(uuid->uu));
if (count)
strcat(p, ", ");
ptr += sizeof(bt_uuid_t);
@@ -286,8 +288,9 @@ char *btproperty2str(const bt_property_t *property)
case BT_PROPERTY_SERVICE_RECORD:
{
bt_service_record_t *rec = property->val;
+ bt_uuid_t *uuid = &rec->uuid;
- sprintf(p, "{%s, %d, %s}", btuuid2str(&rec->uuid),
+ sprintf(p, "{%s, %d, %s}", btuuid2str(uuid->uu),
rec->channel, rec->name);
}
break;
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 84cfad1..96dc234 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -17,8 +17,7 @@
#include <stdio.h>
#include <string.h>
-
-#include <hardware/bluetooth.h>
+#include <stdint.h>
#include "hal-utils.h"
@@ -28,15 +27,15 @@
*
* returns string representation of uuid
*/
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
{
int shift = 0;
- int i;
+ unsigned int i;
int is_bt;
- is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+ is_bt = !memcmp(&uuid[4], &BT_BASE_UUID[4], HAL_UUID_LEN - 4);
- for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
+ for (i = 0; i < HAL_UUID_LEN; i++) {
if (i == 4 && is_bt)
break;
@@ -44,13 +43,13 @@ char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
buf[i * 2 + shift] = '-';
shift++;
}
- sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+ sprintf(buf + i * 2 + shift, "%02x", uuid[i]);
}
return buf;
}
-char *btuuid2str(const bt_uuid_t *uuid)
+char *btuuid2str(const uint8_t *uuid)
{
static char buf[MAX_UUID_STR_LEN];
diff --git a/android/hal-utils.h b/android/hal-utils.h
index d40b430..5287180 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -15,12 +15,13 @@
*
*/
-#define MAX_UUID_STR_LEN 37
+#define MAX_UUID_STR_LEN 37
+#define HAL_UUID_LEN 16
static const char BT_BASE_UUID[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
};
-char *btuuid2str(const bt_uuid_t *uuid);
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
+char *btuuid2str(const uint8_t *uuid);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 3/3] android/hal-sock: Add UUID debug print in socket HAL
From: Andrei Emeltchenko @ 2013-11-08 13:16 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383916561-9719-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Socket HAL uses uint8_t * strings which are of size bt_uuid_t.
---
android/hal-sock.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/android/hal-sock.c b/android/hal-sock.c
index 32c7939..d24276e 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -25,6 +25,8 @@
#include "hal-msg.h"
#include "hal.h"
+#include "hal-utils.h"
+
static bt_status_t sock_listen_rfcomm(const char *service_name,
const uint8_t *uuid, int chan,
int *sock, int flags)
@@ -49,13 +51,13 @@ static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
int *sock, int flags)
{
if ((!uuid && chan <= 0) || !sock) {
- error("%s: invalid params: uuid %p, chan %d, sock %p",
- __func__, uuid, chan, sock);
+ error("Invalid params: uuid %s, chan %d, sock %p",
+ btuuid2str(uuid), chan, sock);
return BT_STATUS_PARM_INVALID;
}
- DBG("uuid %p chan %d sock %p type %d service_name %s",
- uuid, chan, sock, type, service_name);
+ DBG("uuid %s chan %d sock %p type %d service_name %s",
+ btuuid2str(uuid), chan, sock, type, service_name);
switch (type) {
case BTSOCK_RFCOMM:
@@ -76,12 +78,13 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
struct hal_cmd_sock_connect cmd;
if ((!uuid && chan <= 0) || !bdaddr || !sock) {
- error("invalid params: bd_addr %p, uuid %p, chan %d, sock %p",
- bdaddr, uuid, chan, sock);
+ error("Invalid params: bd_addr %p, uuid %s, chan %d, sock %p",
+ bdaddr, btuuid2str(uuid), chan, sock);
return BT_STATUS_PARM_INVALID;
}
- DBG("uuid %p chan %d sock %p type %d", uuid, chan, sock, type);
+ DBG("uuid %s chan %d sock %p type %d", btuuid2str(uuid), chan, sock,
+ type);
if (type != BTSOCK_RFCOMM) {
error("Socket type %u not supported", type);
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 0/8] Improve user experience
From: Johan Hedberg @ 2013-11-08 13:16 UTC (permalink / raw)
To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <1383914910-2304-1-git-send-email-jerzy.kasenberg@tieto.com>
Hi Jerzy,
On Fri, Nov 08, 2013, Jerzy Kasenberg wrote:
> This patchset works towards improving user interface.
> - Command line parsing (--help, --version, --no-init)
> - All interfaces are now initialized at start by default
> - --no-init allows to disable this initialization
> - pin_request_cb will now present prompt and send reply
> - ssp_request_cb will now present prompt and sent reply
>
> As part of adding those features terminal.c was restructured.
> Big switch inside terminal_process_char was distributed between
> number of small functions. This work was necessary due to input
> handling of prompted data.
>
> Version print may need to be changed according to bluez culture.
>
> Jerzy Kasenberg (8):
> android/client: Export get_interface_method
> android/client: Add NELEM macro for count elements
> android/client: Initialize all interfaces at start
> android/client: Add command line arguments
> android/client: Split terminal_process_char
> android/client: Add prompting for answer
> android/client: Add pin handling for bind
> android/client: Add ssp key confirmation helper
>
> android/client/haltest.c | 102 ++++++-
> android/client/if-bt.c | 46 +++
> android/client/if-main.h | 4 +
> android/client/tabcompletion.c | 2 +-
> android/client/terminal.c | 605 +++++++++++++++++++++++++++-------------
> android/client/terminal.h | 5 +-
> 6 files changed, 567 insertions(+), 197 deletions(-)
All eight patches have been applied. Thanks.
Johan
^ permalink raw reply
* [PATCH_v6 1/5] android/hid: Fill send data command struct in hal-hidhost
From: Ravi kumar Veeramally @ 2013-11-08 13:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
---
android/hal-hidhost.c | 18 ++++++++++--------
android/hal-msg.h | 2 +-
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 94f7e01..e8570bc 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -18,6 +18,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+#include <stdlib.h>
#include "hal-log.h"
#include "hal.h"
@@ -298,7 +299,8 @@ static bt_status_t set_report(bt_bdaddr_t *bd_addr,
bthh_report_type_t report_type,
char *report)
{
- struct hal_cmd_hidhost_set_report cmd;
+ uint8_t buf[BLUEZ_HAL_MTU];
+ struct hal_cmd_hidhost_set_report *cmd = (void *) buf;
DBG("");
@@ -308,26 +310,26 @@ static bt_status_t set_report(bt_bdaddr_t *bd_addr,
if (!bd_addr || !report)
return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- cmd.len = strlen(report);
- memcpy(cmd.data, report, cmd.len);
+ memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
+ cmd->len = strlen(report);
+ memcpy(cmd->data, report, cmd->len);
switch (report_type) {
case BTHH_INPUT_REPORT:
- cmd.type = HAL_HIDHOST_INPUT_REPORT;
+ cmd->type = HAL_HIDHOST_INPUT_REPORT;
break;
case BTHH_OUTPUT_REPORT:
- cmd.type = HAL_HIDHOST_OUTPUT_REPORT;
+ cmd->type = HAL_HIDHOST_OUTPUT_REPORT;
break;
case BTHH_FEATURE_REPORT:
- cmd.type = HAL_HIDHOST_FEATURE_REPORT;
+ cmd->type = HAL_HIDHOST_FEATURE_REPORT;
break;
default:
return BT_STATUS_PARM_INVALID;
}
return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT,
- sizeof(cmd), &cmd, 0, NULL, NULL);
+ sizeof(*cmd) + cmd->len, buf, 0, NULL, NULL);
}
static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 4af86de..4c7d344 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -293,7 +293,7 @@ struct hal_cmd_hidhost_set_report {
uint8_t bdaddr[6];
uint8_t type;
uint16_t len;
- uint8_t data[670];
+ uint8_t data[0];
} __attribute__((packed));
#define HAL_OP_HIDHOST_SEND_DATA 0x09
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v6 3/5] android/hid: Fill send data command struct in hal-hidhost
From: Ravi kumar Veeramally @ 2013-11-08 13:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1383916984-11010-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-hidhost.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index e8570bc..97a1aa0 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -334,7 +334,8 @@ static bt_status_t set_report(bt_bdaddr_t *bd_addr,
static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
{
- struct hal_cmd_hidhost_send_data cmd;
+ uint8_t buf[BLUEZ_HAL_MTU];
+ struct hal_cmd_hidhost_send_data *cmd = (void *) buf;
DBG("");
@@ -344,10 +345,12 @@ static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
if (!bd_addr || !data)
return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+ memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
+ cmd->len = strlen(data);
+ memcpy(cmd->data, data, cmd->len);
return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA,
- sizeof(cmd), &cmd, 0, NULL, NULL);
+ sizeof(*cmd) + cmd->len, buf, 0, NULL, NULL);
}
static bt_status_t init(bthh_callbacks_t *callbacks)
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH_v6 1/5] android/hid: Fill send data command struct in hal-hidhost
From: Johan Hedberg @ 2013-11-08 13:32 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1383916984-11010-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Fri, Nov 08, 2013, Ravi kumar Veeramally wrote:
> ---
> android/hal-hidhost.c | 18 ++++++++++--------
> android/hal-msg.h | 2 +-
> 2 files changed, 11 insertions(+), 9 deletions(-)
All patches in this set have now been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCHv5 1/3] android: Create debug hal-utils helpers
From: Johan Hedberg @ 2013-11-08 13:48 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1383916561-9719-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Fri, Nov 08, 2013, Andrei Emeltchenko wrote:
> Create hal-utils helpers which helps to decode packets Android
> sends through HAL interface.
> ---
> android/Android.mk | 2 ++
> android/Makefile.am | 3 ++-
> android/client/if-gatt.c | 1 +
> android/client/textconv.c | 42 ++------------------------------
> android/client/textconv.h | 2 --
> android/hal-utils.c | 58 +++++++++++++++++++++++++++++++++++++++++++++
> android/hal-utils.h | 26 ++++++++++++++++++++
> 7 files changed, 91 insertions(+), 43 deletions(-)
> create mode 100644 android/hal-utils.c
> create mode 100644 android/hal-utils.h
This first patch has been applied, however I'm waiting for v6 of the
other two as we discussed offline.
Johan
^ permalink raw reply
* [PATCHv5 [2/3]] android/debug: Convert uuid helper to use uint8_t buffer
From: Andrei Emeltchenko @ 2013-11-08 13:48 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383916561-9719-2-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
At this moment Android uses uint8_t * and bt_uuid_t for representing
UUID for different HALs. Convert debug helper to use uint8_t * string.
---
android/client/textconv.c | 6 +++---
android/hal-utils.c | 15 +++++++--------
android/hal-utils.h | 7 ++++---
3 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 469b2c3..60ac08a 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -267,12 +267,12 @@ char *btproperty2str(const bt_property_t *property)
case BT_PROPERTY_UUIDS:
{
int count = property->len / sizeof(bt_uuid_t);
- char *ptr = property->val;
+ uint8_t *ptr = property->val;
strcat(p, "{");
while (count--) {
- strcat(p, btuuid2str((bt_uuid_t *) ptr));
+ strcat(p, btuuid2str(ptr));
if (count)
strcat(p, ", ");
ptr += sizeof(bt_uuid_t);
@@ -287,7 +287,7 @@ char *btproperty2str(const bt_property_t *property)
{
bt_service_record_t *rec = property->val;
- sprintf(p, "{%s, %d, %s}", btuuid2str(&rec->uuid),
+ sprintf(p, "{%s, %d, %s}", btuuid2str(rec->uuid.uu),
rec->channel, rec->name);
}
break;
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 84cfad1..96dc234 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -17,8 +17,7 @@
#include <stdio.h>
#include <string.h>
-
-#include <hardware/bluetooth.h>
+#include <stdint.h>
#include "hal-utils.h"
@@ -28,15 +27,15 @@
*
* returns string representation of uuid
*/
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
{
int shift = 0;
- int i;
+ unsigned int i;
int is_bt;
- is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+ is_bt = !memcmp(&uuid[4], &BT_BASE_UUID[4], HAL_UUID_LEN - 4);
- for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
+ for (i = 0; i < HAL_UUID_LEN; i++) {
if (i == 4 && is_bt)
break;
@@ -44,13 +43,13 @@ char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
buf[i * 2 + shift] = '-';
shift++;
}
- sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+ sprintf(buf + i * 2 + shift, "%02x", uuid[i]);
}
return buf;
}
-char *btuuid2str(const bt_uuid_t *uuid)
+char *btuuid2str(const uint8_t *uuid)
{
static char buf[MAX_UUID_STR_LEN];
diff --git a/android/hal-utils.h b/android/hal-utils.h
index d40b430..5287180 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -15,12 +15,13 @@
*
*/
-#define MAX_UUID_STR_LEN 37
+#define MAX_UUID_STR_LEN 37
+#define HAL_UUID_LEN 16
static const char BT_BASE_UUID[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
};
-char *btuuid2str(const bt_uuid_t *uuid);
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
+char *btuuid2str(const uint8_t *uuid);
--
1.7.10.4
^ permalink raw reply related
* [PATCH] android: Fix error handling in adapter_ready
From: Szymon Janc @ 2013-11-08 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
On error negative value is passed to adapter_ready callback. This fix
passing negative error code to strerror.
---
android/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/android/main.c b/android/main.c
index 93870d0..36cc8aa 100644
--- a/android/main.c
+++ b/android/main.c
@@ -465,8 +465,8 @@ static GOptionEntry options[] = {
static void adapter_ready(int err)
{
- if (err) {
- error("Adapter initialization failed: %s", strerror(err));
+ if (err < 0) {
+ error("Adapter initialization failed: %s", strerror(-err));
exit(EXIT_FAILURE);
}
--
1.8.4.2
^ permalink raw reply related
* [PATCH 1/2] androi/haltest: Make debug functions return const string
From: Andrei Emeltchenko @ 2013-11-08 14:08 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/client/textconv.c | 6 +++---
android/client/textconv.h | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 60ac08a..dcbe53e 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -137,7 +137,7 @@ int int2str_findstr(const char *str, const struct int2str m[])
*
* returns buf
*/
-char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
{
const uint8_t *p = bd_addr->address;
@@ -196,14 +196,14 @@ const char *enum_one_string(void *v, int i)
return (i == 0) && (m[0] != 0) ? m : NULL;
}
-char *bdaddr2str(const bt_bdaddr_t *bd_addr)
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr)
{
static char buf[MAX_ADDR_STR_LEN];
return bt_bdaddr_t2str(bd_addr, buf);
}
-char *btproperty2str(const bt_property_t *property)
+const char *btproperty2str(const bt_property_t *property)
{
static char buf[4096];
char *p;
diff --git a/android/client/textconv.h b/android/client/textconv.h
index 837eb4e..0a72805 100644
--- a/android/client/textconv.h
+++ b/android/client/textconv.h
@@ -100,13 +100,13 @@ static struct int2str __##type##2str[] = {
/* End of mapping section */
#define MAX_ADDR_STR_LEN 18
-char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
-char *btproperty2str(const bt_property_t *property);
-char *bdaddr2str(const bt_bdaddr_t *bd_addr);
+const char *btproperty2str(const bt_property_t *property);
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr);
DECINTMAP(bt_status_t);
DECINTMAP(bt_state_t);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/2] android/hal-utils: Make hal-utils functions return const string
From: Andrei Emeltchenko @ 2013-11-08 14:08 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383919730-13597-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/hal-utils.c | 4 ++--
android/hal-utils.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 96dc234..7ac5047 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -27,7 +27,7 @@
*
* returns string representation of uuid
*/
-char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
+const char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
{
int shift = 0;
unsigned int i;
@@ -49,7 +49,7 @@ char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
return buf;
}
-char *btuuid2str(const uint8_t *uuid)
+const char *btuuid2str(const uint8_t *uuid)
{
static char buf[MAX_UUID_STR_LEN];
diff --git a/android/hal-utils.h b/android/hal-utils.h
index 5287180..8c74653 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -23,5 +23,5 @@ static const char BT_BASE_UUID[] = {
0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
};
-char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
-char *btuuid2str(const uint8_t *uuid);
+const char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
+const char *btuuid2str(const uint8_t *uuid);
--
1.7.10.4
^ permalink raw reply related
* [RFC] android/hid: Handle virtual unplug event from hid device
From: Ravi kumar Veeramally @ 2013-11-08 14:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
If hid host receives the virtual unplug event from hid device
recipient shall destroy or invalidate all bluetooth bonding and
virtual cable information
---
android/hal-msg.h | 1 +
android/hidhost.c | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 4c7d344..569c8ea 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -449,6 +449,7 @@ struct hal_ev_hidhost_conn_state {
} __attribute__((packed));
#define HAL_HIDHOST_STATUS_OK 0x00
+#define HAL_HIDHOST_GENERAL_ERROR 0x06
#define HAL_EV_HIDHOST_INFO 0x82
struct hal_ev_hidhost_info {
diff --git a/android/hidhost.c b/android/hidhost.c
index d36cb82..683938f 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -379,6 +379,31 @@ send:
g_free(ev);
}
+static void bt_hid_notify_virtual_unplug(struct hid_device *dev,
+ uint8_t *buf, int len)
+{
+ struct hal_ev_hidhost_virtual_unplug ev;
+ char address[18];
+
+ ba2str(&dev->dst, address);
+ DBG("device %s", address);
+ bdaddr2android(&dev->dst, ev.bdaddr);
+
+ ev.status = HAL_HIDHOST_GENERAL_ERROR;
+
+ /* Wait either channels to HUP */
+ if (dev->intr_io && dev->ctrl_io) {
+ g_io_channel_shutdown(dev->intr_io, TRUE, NULL);
+ g_io_channel_shutdown(dev->ctrl_io, TRUE, NULL);
+ bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING);
+ ev.status = HAL_HIDHOST_STATUS_OK;
+ }
+
+ ipc_send(notification_sk, HAL_SERVICE_ID_HIDHOST,
+ HAL_EV_HIDHOST_VIRTUAL_UNPLUG, sizeof(ev), &ev, -1);
+
+}
+
static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
{
struct hid_device *dev = data;
@@ -404,6 +429,9 @@ static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
break;
}
+ if (buf[0] == (HID_MSG_CONTROL | HID_VIRTUAL_CABLE_UNPLUG))
+ bt_hid_notify_virtual_unplug(dev, buf, bread);
+
/* reset msg type request */
dev->last_hid_msg = 0;
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH] android: Fix error handling in adapter_ready
From: Johan Hedberg @ 2013-11-08 14:15 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1383919259-11782-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Fri, Nov 08, 2013, Szymon Janc wrote:
> On error negative value is passed to adapter_ready callback. This fix
> passing negative error code to strerror.
> ---
> android/main.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 1/2] androi/haltest: Make debug functions return const string
From: Johan Hedberg @ 2013-11-08 14:22 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1383919730-13597-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Fri, Nov 08, 2013, Andrei Emeltchenko wrote:
> ---
> android/client/textconv.c | 6 +++---
> android/client/textconv.h | 6 +++---
> 2 files changed, 6 insertions(+), 6 deletions(-)
Both patches have been applied. Thanks.
Johan
^ permalink raw reply
* [PATCH] android: Avoid unneeded includes
From: Andrei Emeltchenko @ 2013-11-08 14:26 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Declare struct mgmt in adapter.h. This avoids including mgmt.h in
every file using adapter functions like socket and hid.
---
android/adapter.h | 2 ++
android/hidhost.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/android/adapter.h b/android/adapter.h
index c62b859..3bda9d9 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -23,6 +23,8 @@
typedef void (*bt_adapter_ready)(int err);
+struct mgmt;
+
void bt_adapter_init(uint16_t index, struct mgmt *mgmt_if,
bt_adapter_ready cb);
diff --git a/android/hidhost.c b/android/hidhost.c
index d36cb82..6054c1c 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -38,7 +38,6 @@
#include "lib/sdp.h"
#include "lib/sdp_lib.h"
#include "lib/uuid.h"
-#include "src/shared/mgmt.h"
#include "src/sdp-client.h"
#include "src/glib-helper.h"
#include "profiles/input/uhid_copy.h"
--
1.7.10.4
^ permalink raw reply related
* [RFC] android/debug: Move debug functions to hal-utils.c
From: Andrei Emeltchenko @ 2013-11-08 15:05 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Debug functions will be used by HALs and haltest.
---
android/Android.mk | 2 -
android/Makefile.am | 3 -
android/client/if-av.c | 1 +
android/client/if-bt.c | 1 +
android/client/if-hf.c | 1 +
android/client/if-hh.c | 1 +
android/client/if-main.h | 2 -
android/client/if-pan.c | 1 +
android/client/if-sock.c | 1 +
android/client/textconv.c | 300 ---------------------------------------------
android/client/textconv.h | 120 ------------------
android/hal-bluetooth.c | 3 +-
android/hal-utils.c | 269 ++++++++++++++++++++++++++++++++++++++++
android/hal-utils.h | 103 ++++++++++++++++
14 files changed, 379 insertions(+), 429 deletions(-)
delete mode 100644 android/client/textconv.c
delete mode 100644 android/client/textconv.h
diff --git a/android/Android.mk b/android/Android.mk
index 0bc0e82..53c766b 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -87,7 +87,6 @@ LOCAL_SRC_FILES := \
hal-hidhost.c \
hal-pan.c \
hal-a2dp.c \
- client/textconv.c \
hal-utils.c \
LOCAL_C_INCLUDES += \
@@ -118,7 +117,6 @@ LOCAL_SRC_FILES := \
client/pollhandler.c \
client/terminal.c \
client/history.c \
- client/textconv.c \
client/tabcompletion.c \
client/if-av.c \
client/if-bt.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index debe7c1..e81d1a5 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -59,7 +59,6 @@ android_haltest_SOURCES = android/client/haltest.c \
android/client/pollhandler.c \
android/client/terminal.c \
android/client/history.c \
- android/client/textconv.c \
android/client/tabcompletion.c \
android/client/if-av.c \
android/client/if-bt.c \
@@ -102,9 +101,7 @@ EXTRA_DIST += android/client/terminal.c \
android/client/if-hh.c \
android/client/if-pan.c \
android/client/if-sock.c \
- android/client/textconv.c \
android/client/tabcompletion.c \
- android/client/textconv.h \
android/client/if-main.h \
android/client/pollhandler.h \
android/client/history.h \
diff --git a/android/client/if-av.c b/android/client/if-av.c
index 3f133eb..0470e0d 100644
--- a/android/client/if-av.c
+++ b/android/client/if-av.c
@@ -16,6 +16,7 @@
*/
#include "if-main.h"
+#include "../hal-utils.h"
const btav_interface_t *if_av = NULL;
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 10ae125..0cd43db 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -17,6 +17,7 @@
#include "if-main.h"
#include "terminal.h"
+#include "../hal-utils.h"
const bt_interface_t *if_bluetooth;
diff --git a/android/client/if-hf.c b/android/client/if-hf.c
index c23fb13..d0e7a66 100644
--- a/android/client/if-hf.c
+++ b/android/client/if-hf.c
@@ -16,6 +16,7 @@
*/
#include "if-main.h"
+#include "../hal-utils.h"
const bthf_interface_t *if_hf = NULL;
diff --git a/android/client/if-hh.c b/android/client/if-hh.c
index 005b13a..b8ebc8e 100644
--- a/android/client/if-hh.c
+++ b/android/client/if-hh.c
@@ -23,6 +23,7 @@
#include "if-main.h"
#include "pollhandler.h"
+#include "../hal-utils.h"
const bthh_interface_t *if_hh = NULL;
diff --git a/android/client/if-main.h b/android/client/if-main.h
index dea7237..a83f48b 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -44,8 +44,6 @@
#include <hardware/bt_gatt_server.h>
#endif
-#include "textconv.h"
-
/* Interfaces from hal that can be populated during application lifetime */
extern const bt_interface_t *if_bluetooth;
extern const btav_interface_t *if_av;
diff --git a/android/client/if-pan.c b/android/client/if-pan.c
index dcc7e80..a11f2a3 100644
--- a/android/client/if-pan.c
+++ b/android/client/if-pan.c
@@ -18,6 +18,7 @@
#include <hardware/bluetooth.h>
#include "if-main.h"
+#include "../hal-utils.h"
const btpan_interface_t *if_pan = NULL;
diff --git a/android/client/if-sock.c b/android/client/if-sock.c
index dcaf048..2cd06e8 100644
--- a/android/client/if-sock.c
+++ b/android/client/if-sock.c
@@ -21,6 +21,7 @@
#include "if-main.h"
#include "pollhandler.h"
+#include "../hal-utils.h"
const btsock_interface_t *if_sock = NULL;
diff --git a/android/client/textconv.c b/android/client/textconv.c
deleted file mode 100644
index dcbe53e..0000000
--- a/android/client/textconv.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2013 Intel Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <hardware/bluetooth.h>
-
-#include "../hal-utils.h"
-
-#include "textconv.h"
-
-/*
- * Following are maps of defines found in bluetooth header files to strings
- *
- * Those mappings are used to accurately use defines as input parameters in
- * command line as well as for printing of statuses
- */
-
-INTMAP(bt_status_t, -1, "(unknown)")
- DELEMENT(BT_STATUS_SUCCESS),
- DELEMENT(BT_STATUS_FAIL),
- DELEMENT(BT_STATUS_NOT_READY),
- DELEMENT(BT_STATUS_NOMEM),
- DELEMENT(BT_STATUS_BUSY),
- DELEMENT(BT_STATUS_DONE),
- DELEMENT(BT_STATUS_UNSUPPORTED),
- DELEMENT(BT_STATUS_PARM_INVALID),
- DELEMENT(BT_STATUS_UNHANDLED),
- DELEMENT(BT_STATUS_AUTH_FAILURE),
- DELEMENT(BT_STATUS_RMT_DEV_DOWN),
-ENDMAP
-
-INTMAP(bt_state_t, -1, "(unknown)")
- DELEMENT(BT_STATE_OFF),
- DELEMENT(BT_STATE_ON),
-ENDMAP
-
-INTMAP(bt_device_type_t, -1, "(unknown)")
- DELEMENT(BT_DEVICE_DEVTYPE_BREDR),
- DELEMENT(BT_DEVICE_DEVTYPE_BLE),
- DELEMENT(BT_DEVICE_DEVTYPE_DUAL),
-ENDMAP
-
-INTMAP(bt_scan_mode_t, -1, "(unknown)")
- DELEMENT(BT_SCAN_MODE_NONE),
- DELEMENT(BT_SCAN_MODE_CONNECTABLE),
- DELEMENT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE),
-ENDMAP
-
-INTMAP(bt_discovery_state_t, -1, "(unknown)")
- DELEMENT(BT_DISCOVERY_STOPPED),
- DELEMENT(BT_DISCOVERY_STARTED),
-ENDMAP
-
-INTMAP(bt_acl_state_t, -1, "(unknown)")
- DELEMENT(BT_ACL_STATE_CONNECTED),
- DELEMENT(BT_ACL_STATE_DISCONNECTED),
-ENDMAP
-
-INTMAP(bt_bond_state_t, -1, "(unknown)")
- DELEMENT(BT_BOND_STATE_NONE),
- DELEMENT(BT_BOND_STATE_BONDING),
- DELEMENT(BT_BOND_STATE_BONDED),
-ENDMAP
-
-INTMAP(bt_ssp_variant_t, -1, "(unknown)")
- DELEMENT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
- DELEMENT(BT_SSP_VARIANT_PASSKEY_ENTRY),
- DELEMENT(BT_SSP_VARIANT_CONSENT),
- DELEMENT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION),
-ENDMAP
-
-INTMAP(bt_property_type_t, -1, "(unknown)")
- DELEMENT(BT_PROPERTY_BDNAME),
- DELEMENT(BT_PROPERTY_BDADDR),
- DELEMENT(BT_PROPERTY_UUIDS),
- DELEMENT(BT_PROPERTY_CLASS_OF_DEVICE),
- DELEMENT(BT_PROPERTY_TYPE_OF_DEVICE),
- DELEMENT(BT_PROPERTY_SERVICE_RECORD),
- DELEMENT(BT_PROPERTY_ADAPTER_SCAN_MODE),
- DELEMENT(BT_PROPERTY_ADAPTER_BONDED_DEVICES),
- DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
- DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
- DELEMENT(BT_PROPERTY_REMOTE_RSSI),
-#if PLATFORM_SDK_VERSION > 17
- DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
-#endif
- DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
-ENDMAP
-
-INTMAP(bt_cb_thread_evt, -1, "(unknown)")
- DELEMENT(ASSOCIATE_JVM),
- DELEMENT(DISASSOCIATE_JVM),
-ENDMAP
-
-/* Find first index of given value in table m */
-int int2str_findint(int v, const struct int2str m[])
-{
- int i;
-
- for (i = 0; m[i].str; ++i) {
- if (m[i].val == v)
- return i;
- }
- return -1;
-}
-
-/* Find first index of given string in table m */
-int int2str_findstr(const char *str, const struct int2str m[])
-{
- int i;
-
- for (i = 0; m[i].str; ++i) {
- if (strcmp(m[i].str, str) == 0)
- return i;
- }
- return -1;
-}
-
-/*
- * convert bd_addr to string
- * buf must be at least 18 char long
- *
- * returns buf
- */
-const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
-{
- const uint8_t *p = bd_addr->address;
-
- snprintf(buf, MAX_ADDR_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
- p[0], p[1], p[2], p[3], p[4], p[5]);
-
- return buf;
-}
-
-/* converts string to bt_bdaddr_t */
-void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
-{
- uint8_t *p = bd_addr->address;
-
- sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
- &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
-}
-
-/* converts string to uuid */
-void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
-{
- int i = 0;
-
- memcpy(uuid, BT_BASE_UUID, sizeof(bt_uuid_t));
-
- while (*str && i < (int) sizeof(bt_uuid_t)) {
- while (*str == '-')
- str++;
-
- if (sscanf(str, "%02hhx", &uuid->uu[i]) != 1)
- break;
-
- i++;
- str += 2;
- }
-}
-
-const char *enum_defines(void *v, int i)
-{
- const struct int2str *m = v;
-
- return m[i].str != NULL ? m[i].str : NULL;
-}
-
-const char *enum_strings(void *v, int i)
-{
- const char **m = v;
-
- return m[i] != NULL ? m[i] : NULL;
-}
-
-const char *enum_one_string(void *v, int i)
-{
- const char *m = v;
-
- return (i == 0) && (m[0] != 0) ? m : NULL;
-}
-
-const char *bdaddr2str(const bt_bdaddr_t *bd_addr)
-{
- static char buf[MAX_ADDR_STR_LEN];
-
- return bt_bdaddr_t2str(bd_addr, buf);
-}
-
-const char *btproperty2str(const bt_property_t *property)
-{
- static char buf[4096];
- char *p;
-
- p = buf + sprintf(buf, "type=%s len=%d val=",
- bt_property_type_t2str(property->type),
- property->len);
-
- switch (property->type) {
- case BT_PROPERTY_BDNAME:
- case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
- snprintf(p, property->len + 1, "%s",
- ((bt_bdname_t *) property->val)->name);
- break;
-
- case BT_PROPERTY_BDADDR:
- sprintf(p, "%s", bdaddr2str((bt_bdaddr_t *) property->val));
- break;
-
- case BT_PROPERTY_CLASS_OF_DEVICE:
- sprintf(p, "%06x", *((int *) property->val));
- break;
-
- case BT_PROPERTY_TYPE_OF_DEVICE:
- sprintf(p, "%s", bt_device_type_t2str(
- *((bt_device_type_t *) property->val)));
- break;
-
- case BT_PROPERTY_REMOTE_RSSI:
- sprintf(p, "%d", *((char *) property->val));
- break;
-
- case BT_PROPERTY_ADAPTER_SCAN_MODE:
- sprintf(p, "%s",
- bt_scan_mode_t2str(*((bt_scan_mode_t *) property->val)));
- break;
-
- case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
- sprintf(p, "%d", *((int *) property->val));
- break;
-
- case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
- {
- int count = property->len / sizeof(bt_bdaddr_t);
- char *ptr = property->val;
-
- strcat(p, "{");
-
- while (count--) {
- strcat(p, bdaddr2str((bt_bdaddr_t *) ptr));
- if (count)
- strcat(p, ", ");
- ptr += sizeof(bt_bdaddr_t);
- }
-
- strcat(p, "}");
-
- }
- break;
-
- case BT_PROPERTY_UUIDS:
- {
- int count = property->len / sizeof(bt_uuid_t);
- uint8_t *ptr = property->val;
-
- strcat(p, "{");
-
- while (count--) {
- strcat(p, btuuid2str(ptr));
- if (count)
- strcat(p, ", ");
- ptr += sizeof(bt_uuid_t);
- }
-
- strcat(p, "}");
-
- }
- break;
-
- case BT_PROPERTY_SERVICE_RECORD:
- {
- bt_service_record_t *rec = property->val;
-
- sprintf(p, "{%s, %d, %s}", btuuid2str(rec->uuid.uu),
- rec->channel, rec->name);
- }
- break;
-
- default:
- sprintf(p, "%p", property->val);
- }
-
- return buf;
-}
diff --git a/android/client/textconv.h b/android/client/textconv.h
deleted file mode 100644
index 0a72805..0000000
--- a/android/client/textconv.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.
- *
- */
-
-/**
- * Begin mapping section
- *
- * There are some mappings between integer values (enums) and strings
- * to be presented to user. To make it easier to convert between those two
- * set of macros is given. It is specially useful when we want to have
- * strings that match constants from header files like:
- * BT_STATUS_SUCCESS (0) and corresponding "BT_STATUS_SUCCESS"
- * Example of usage:
- *
- * INTMAP(int, -1, "invalid")
- * DELEMENT(BT_STATUS_SUCCESS)
- * DELEMENT(BT_STATUS_FAIL)
- * MELEMENT(123, "Some strange value")
- * ENDMAP
- *
- * Just by doing this we have mapping table plus two functions:
- * int str2int(const char *str);
- * const char *int2str(int v);
- *
- * second argument to INTMAP specifies value to be returned from
- * str2int function when there is not mapping for such number
- * third argument specifies default value to be returned from int2str
- *
- * If same mapping is to be used in several source files put
- * INTMAP in c file and DECINTMAP in h file.
- *
- * For mappings that are to be used in single file only
- * use SINTMAP which will create the same but everything will be marked
- * as static.
- */
-
-struct int2str {
- int val; /* int value */
- const char *str; /* corresponding string */
-};
-
-int int2str_findint(int v, const struct int2str m[]);
-int int2str_findstr(const char *str, const struct int2str m[]);
-const char *enum_defines(void *v, int i);
-const char *enum_strings(void *v, int i);
-const char *enum_one_string(void *v, int i);
-
-#define TYPE_ENUM(type) ((void *) &__##type##2str[0])
-#define DECINTMAP(type) \
-extern struct int2str __##type##2str[]; \
-const char *type##2##str(type v); \
-type str##2##type(const char *str); \
-
-#define INTMAP(type, deft, defs) \
-const char *type##2##str(type v) \
-{ \
- int i = int2str_findint((int) v, __##type##2str); \
- return (i < 0) ? defs : __##type##2str[i].str; \
-} \
-type str##2##type(const char *str) \
-{ \
- int i = int2str_findstr(str, __##type##2str); \
- return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
-} \
-struct int2str __##type##2str[] = {
-
-#define SINTMAP(type, deft, defs) \
-static struct int2str __##type##2str[]; \
-static inline const char *type##2##str(type v) \
-{ \
- int i = int2str_findint((int) v, __##type##2str); \
- return (i < 0) ? defs : __##type##2str[i].str; \
-} \
-static inline type str##2##type(const char *str) \
-{ \
- int i = int2str_findstr(str, __##type##2str); \
- return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
-} \
-static struct int2str __##type##2str[] = {
-
-#define ENDMAP {0, NULL} };
-
-/* use this to generate string from header file constant */
-#define MELEMENT(v, s) {v, s}
-/* use this to have arbitrary mapping from int to string */
-#define DELEMENT(s) {s, #s}
-/* End of mapping section */
-
-#define MAX_ADDR_STR_LEN 18
-const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
-void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
-
-void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
-
-const char *btproperty2str(const bt_property_t *property);
-const char *bdaddr2str(const bt_bdaddr_t *bd_addr);
-
-DECINTMAP(bt_status_t);
-DECINTMAP(bt_state_t);
-DECINTMAP(bt_device_type_t);
-DECINTMAP(bt_scan_mode_t);
-DECINTMAP(bt_discovery_state_t);
-DECINTMAP(bt_acl_state_t);
-DECINTMAP(bt_bond_state_t);
-DECINTMAP(bt_ssp_variant_t);
-DECINTMAP(bt_property_type_t);
-DECINTMAP(bt_cb_thread_evt);
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 3e5d41f..5c14649 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -24,8 +24,7 @@
#include "hal.h"
#include "hal-msg.h"
#include "hal-ipc.h"
-
-#include "client/textconv.h"
+#include "hal-utils.h"
static const bt_callbacks_t *bt_hal_cbacks = NULL;
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 7ac5047..4f44d98 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -55,3 +55,272 @@ const char *btuuid2str(const uint8_t *uuid)
return bt_uuid_t2str(uuid, buf);
}
+
+INTMAP(bt_status_t, -1, "(unknown)")
+ DELEMENT(BT_STATUS_SUCCESS),
+ DELEMENT(BT_STATUS_FAIL),
+ DELEMENT(BT_STATUS_NOT_READY),
+ DELEMENT(BT_STATUS_NOMEM),
+ DELEMENT(BT_STATUS_BUSY),
+ DELEMENT(BT_STATUS_DONE),
+ DELEMENT(BT_STATUS_UNSUPPORTED),
+ DELEMENT(BT_STATUS_PARM_INVALID),
+ DELEMENT(BT_STATUS_UNHANDLED),
+ DELEMENT(BT_STATUS_AUTH_FAILURE),
+ DELEMENT(BT_STATUS_RMT_DEV_DOWN),
+ENDMAP
+
+INTMAP(bt_state_t, -1, "(unknown)")
+ DELEMENT(BT_STATE_OFF),
+ DELEMENT(BT_STATE_ON),
+ENDMAP
+
+INTMAP(bt_device_type_t, -1, "(unknown)")
+ DELEMENT(BT_DEVICE_DEVTYPE_BREDR),
+ DELEMENT(BT_DEVICE_DEVTYPE_BLE),
+ DELEMENT(BT_DEVICE_DEVTYPE_DUAL),
+ENDMAP
+
+INTMAP(bt_scan_mode_t, -1, "(unknown)")
+ DELEMENT(BT_SCAN_MODE_NONE),
+ DELEMENT(BT_SCAN_MODE_CONNECTABLE),
+ DELEMENT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE),
+ENDMAP
+
+INTMAP(bt_discovery_state_t, -1, "(unknown)")
+ DELEMENT(BT_DISCOVERY_STOPPED),
+ DELEMENT(BT_DISCOVERY_STARTED),
+ENDMAP
+
+INTMAP(bt_acl_state_t, -1, "(unknown)")
+ DELEMENT(BT_ACL_STATE_CONNECTED),
+ DELEMENT(BT_ACL_STATE_DISCONNECTED),
+ENDMAP
+
+INTMAP(bt_bond_state_t, -1, "(unknown)")
+ DELEMENT(BT_BOND_STATE_NONE),
+ DELEMENT(BT_BOND_STATE_BONDING),
+ DELEMENT(BT_BOND_STATE_BONDED),
+ENDMAP
+
+INTMAP(bt_ssp_variant_t, -1, "(unknown)")
+ DELEMENT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
+ DELEMENT(BT_SSP_VARIANT_PASSKEY_ENTRY),
+ DELEMENT(BT_SSP_VARIANT_CONSENT),
+ DELEMENT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION),
+ENDMAP
+
+INTMAP(bt_property_type_t, -1, "(unknown)")
+ DELEMENT(BT_PROPERTY_BDNAME),
+ DELEMENT(BT_PROPERTY_BDADDR),
+ DELEMENT(BT_PROPERTY_UUIDS),
+ DELEMENT(BT_PROPERTY_CLASS_OF_DEVICE),
+ DELEMENT(BT_PROPERTY_TYPE_OF_DEVICE),
+ DELEMENT(BT_PROPERTY_SERVICE_RECORD),
+ DELEMENT(BT_PROPERTY_ADAPTER_SCAN_MODE),
+ DELEMENT(BT_PROPERTY_ADAPTER_BONDED_DEVICES),
+ DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
+ DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
+ DELEMENT(BT_PROPERTY_REMOTE_RSSI),
+#if PLATFORM_SDK_VERSION > 17
+ DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
+#endif
+ DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
+ENDMAP
+
+INTMAP(bt_cb_thread_evt, -1, "(unknown)")
+ DELEMENT(ASSOCIATE_JVM),
+ DELEMENT(DISASSOCIATE_JVM),
+ENDMAP
+
+/* Find first index of given value in table m */
+int int2str_findint(int v, const struct int2str m[])
+{
+ int i;
+
+ for (i = 0; m[i].str; ++i) {
+ if (m[i].val == v)
+ return i;
+ }
+ return -1;
+}
+
+/* Find first index of given string in table m */
+int int2str_findstr(const char *str, const struct int2str m[])
+{
+ int i;
+
+ for (i = 0; m[i].str; ++i) {
+ if (strcmp(m[i].str, str) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * convert bd_addr to string
+ * buf must be at least 18 char long
+ *
+ * returns buf
+ */
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
+{
+ const uint8_t *p = bd_addr->address;
+
+ snprintf(buf, MAX_ADDR_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
+ p[0], p[1], p[2], p[3], p[4], p[5]);
+
+ return buf;
+}
+
+/* converts string to bt_bdaddr_t */
+void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
+{
+ uint8_t *p = bd_addr->address;
+
+ sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
+}
+
+/* converts string to uuid */
+void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
+{
+ int i = 0;
+
+ memcpy(uuid, BT_BASE_UUID, sizeof(bt_uuid_t));
+
+ while (*str && i < (int) sizeof(bt_uuid_t)) {
+ while (*str == '-')
+ str++;
+
+ if (sscanf(str, "%02hhx", &uuid->uu[i]) != 1)
+ break;
+
+ i++;
+ str += 2;
+ }
+}
+
+const char *enum_defines(void *v, int i)
+{
+ const struct int2str *m = v;
+
+ return m[i].str != NULL ? m[i].str : NULL;
+}
+
+const char *enum_strings(void *v, int i)
+{
+ const char **m = v;
+
+ return m[i] != NULL ? m[i] : NULL;
+}
+
+const char *enum_one_string(void *v, int i)
+{
+ const char *m = v;
+
+ return (i == 0) && (m[0] != 0) ? m : NULL;
+}
+
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr)
+{
+ static char buf[MAX_ADDR_STR_LEN];
+
+ return bt_bdaddr_t2str(bd_addr, buf);
+}
+
+const char *btproperty2str(const bt_property_t *property)
+{
+ static char buf[4096];
+ char *p;
+
+ p = buf + sprintf(buf, "type=%s len=%d val=",
+ bt_property_type_t2str(property->type),
+ property->len);
+
+ switch (property->type) {
+ case BT_PROPERTY_BDNAME:
+ case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
+ snprintf(p, property->len + 1, "%s",
+ ((bt_bdname_t *) property->val)->name);
+ break;
+
+ case BT_PROPERTY_BDADDR:
+ sprintf(p, "%s", bdaddr2str((bt_bdaddr_t *) property->val));
+ break;
+
+ case BT_PROPERTY_CLASS_OF_DEVICE:
+ sprintf(p, "%06x", *((int *) property->val));
+ break;
+
+ case BT_PROPERTY_TYPE_OF_DEVICE:
+ sprintf(p, "%s", bt_device_type_t2str(
+ *((bt_device_type_t *) property->val)));
+ break;
+
+ case BT_PROPERTY_REMOTE_RSSI:
+ sprintf(p, "%d", *((char *) property->val));
+ break;
+
+ case BT_PROPERTY_ADAPTER_SCAN_MODE:
+ sprintf(p, "%s",
+ bt_scan_mode_t2str(*((bt_scan_mode_t *) property->val)));
+ break;
+
+ case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ sprintf(p, "%d", *((int *) property->val));
+ break;
+
+ case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
+ {
+ int count = property->len / sizeof(bt_bdaddr_t);
+ char *ptr = property->val;
+
+ strcat(p, "{");
+
+ while (count--) {
+ strcat(p, bdaddr2str((bt_bdaddr_t *) ptr));
+ if (count)
+ strcat(p, ", ");
+ ptr += sizeof(bt_bdaddr_t);
+ }
+
+ strcat(p, "}");
+
+ }
+ break;
+
+ case BT_PROPERTY_UUIDS:
+ {
+ int count = property->len / sizeof(bt_uuid_t);
+ uint8_t *ptr = property->val;
+
+ strcat(p, "{");
+
+ while (count--) {
+ strcat(p, btuuid2str(ptr));
+ if (count)
+ strcat(p, ", ");
+ ptr += sizeof(bt_uuid_t);
+ }
+
+ strcat(p, "}");
+
+ }
+ break;
+
+ case BT_PROPERTY_SERVICE_RECORD:
+ {
+ bt_service_record_t *rec = property->val;
+
+ sprintf(p, "{%s, %d, %s}", btuuid2str(rec->uuid.uu),
+ rec->channel, rec->name);
+ }
+ break;
+
+ default:
+ sprintf(p, "%p", property->val);
+ }
+
+ return buf;
+}
diff --git a/android/hal-utils.h b/android/hal-utils.h
index 8c74653..75de7e9 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -15,8 +15,11 @@
*
*/
+#include <hardware/bluetooth.h>
+
#define MAX_UUID_STR_LEN 37
#define HAL_UUID_LEN 16
+#define MAX_ADDR_STR_LEN 18
static const char BT_BASE_UUID[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
@@ -25,3 +28,103 @@ static const char BT_BASE_UUID[] = {
const char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
const char *btuuid2str(const uint8_t *uuid);
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
+void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
+void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
+const char *btproperty2str(const bt_property_t *property);
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr);
+
+/**
+ * Begin mapping section
+ *
+ * There are some mappings between integer values (enums) and strings
+ * to be presented to user. To make it easier to convert between those two
+ * set of macros is given. It is specially useful when we want to have
+ * strings that match constants from header files like:
+ * BT_STATUS_SUCCESS (0) and corresponding "BT_STATUS_SUCCESS"
+ * Example of usage:
+ *
+ * INTMAP(int, -1, "invalid")
+ * DELEMENT(BT_STATUS_SUCCESS)
+ * DELEMENT(BT_STATUS_FAIL)
+ * MELEMENT(123, "Some strange value")
+ * ENDMAP
+ *
+ * Just by doing this we have mapping table plus two functions:
+ * int str2int(const char *str);
+ * const char *int2str(int v);
+ *
+ * second argument to INTMAP specifies value to be returned from
+ * str2int function when there is not mapping for such number
+ * third argument specifies default value to be returned from int2str
+ *
+ * If same mapping is to be used in several source files put
+ * INTMAP in c file and DECINTMAP in h file.
+ *
+ * For mappings that are to be used in single file only
+ * use SINTMAP which will create the same but everything will be marked
+ * as static.
+ */
+
+struct int2str {
+ int val; /* int value */
+ const char *str; /* corresponding string */
+};
+
+int int2str_findint(int v, const struct int2str m[]);
+int int2str_findstr(const char *str, const struct int2str m[]);
+const char *enum_defines(void *v, int i);
+const char *enum_strings(void *v, int i);
+const char *enum_one_string(void *v, int i);
+
+#define TYPE_ENUM(type) ((void *) &__##type##2str[0])
+#define DECINTMAP(type) \
+extern struct int2str __##type##2str[]; \
+const char *type##2##str(type v); \
+type str##2##type(const char *str); \
+
+#define INTMAP(type, deft, defs) \
+const char *type##2##str(type v) \
+{ \
+ int i = int2str_findint((int) v, __##type##2str); \
+ return (i < 0) ? defs : __##type##2str[i].str; \
+} \
+type str##2##type(const char *str) \
+{ \
+ int i = int2str_findstr(str, __##type##2str); \
+ return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
+} \
+struct int2str __##type##2str[] = {
+
+#define SINTMAP(type, deft, defs) \
+static struct int2str __##type##2str[]; \
+static inline const char *type##2##str(type v) \
+{ \
+ int i = int2str_findint((int) v, __##type##2str); \
+ return (i < 0) ? defs : __##type##2str[i].str; \
+} \
+static inline type str##2##type(const char *str) \
+{ \
+ int i = int2str_findstr(str, __##type##2str); \
+ return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
+} \
+static struct int2str __##type##2str[] = {
+
+#define ENDMAP {0, NULL} };
+
+/* use this to generate string from header file constant */
+#define MELEMENT(v, s) {v, s}
+/* use this to have arbitrary mapping from int to string */
+#define DELEMENT(s) {s, #s}
+/* End of mapping section */
+
+DECINTMAP(bt_status_t);
+DECINTMAP(bt_state_t);
+DECINTMAP(bt_device_type_t);
+DECINTMAP(bt_scan_mode_t);
+DECINTMAP(bt_discovery_state_t);
+DECINTMAP(bt_acl_state_t);
+DECINTMAP(bt_bond_state_t);
+DECINTMAP(bt_ssp_variant_t);
+DECINTMAP(bt_property_type_t);
+DECINTMAP(bt_cb_thread_evt);
--
1.7.10.4
^ permalink raw reply related
* [RFC v3 0/8] Bluetooth LE 6LoWPAN
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
Hi,
this is 6LoWPAN code for BT LE as described in
http://tools.ietf.org/html/draft-ietf-6lowpan-btle-12
v3:
- misc changes according to Marcel's comments
- supports multiple connections / interface
- removed unused fragmentation code
- setup 6lowpan connection automatically if enabled via debugfs
The automatic 6lowpan enabling is done by setting
echo 1 > /sys/kernel/debug/bluetooth/hci0/6lowpan
before devices are connected.
v2:
- Change ARPHRD_IEEE802154 to ARPHRD_RAWIP. The generic code
in patches 1 and 2 is also sent to netdev mailing list.
- Sending route exporting patch 5 to netdev ml
- Check private/public BT address and toggle universal/local bit
accordingly in patch 3.
- The virtual interface template name is now shorter (bt%d)
- Various function name renames
- devtype of the interface set to "bluetooth"
v1:
- initial release
TODO:
- Discovery of 6LoWPAN service needs be automatic.
- Refactor compression and uncompression code after these are fixed
in net/ieee802154/6lowpan.c. Bluetooth 6LoWPAN should be able to share
that part of the code.
Known issues:
- route to peer is not removed when connection is dropped
- no UUID handling yet
Cheers,
Jukka
Jukka Rissanen (8):
net: if_arp: add ARPHRD_RAWIP type
ipv6: Add checks for RAWIP ARP type
Bluetooth: Initial skeleton code for BT 6LoWPAN
Bluetooth: Enable 6LoWPAN support for BT LE devices
Bluetooth: Enable 6LoWPAN if device supports it
route: Exporting ip6_route_add() so that Bluetooth 6LoWPAN can use it
Bluetooth: Set route to peer for 6LoWPAN
Bluetooth: Manually enable or disable 6LoWPAN between devices
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 1 +
include/net/bluetooth/l2cap.h | 1 +
include/uapi/linux/if_arp.h | 1 +
net/bluetooth/6lowpan.c | 1723 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/6lowpan.h | 27 +
net/bluetooth/Makefile | 2 +-
net/bluetooth/hci_core.c | 4 +
net/bluetooth/hci_event.c | 3 +
net/bluetooth/l2cap_core.c | 25 +-
net/ipv6/addrconf.c | 4 +-
net/ipv6/route.c | 1 +
12 files changed, 1790 insertions(+), 3 deletions(-)
create mode 100644 net/bluetooth/6lowpan.c
create mode 100644 net/bluetooth/6lowpan.h
--
1.8.3.1
^ permalink raw reply
* [RFC v3 1/8] net: if_arp: add ARPHRD_RAWIP type
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
This is used when there is no L2 header before IP header.
Example of this is Bluetooth 6LoWPAN network.
The RAWIP header type value is already used in some Android kernels
so same value is used here in order not to break userspace.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
include/uapi/linux/if_arp.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h
index d7fea34..06fc69f 100644
--- a/include/uapi/linux/if_arp.h
+++ b/include/uapi/linux/if_arp.h
@@ -59,6 +59,7 @@
#define ARPHRD_LAPB 516 /* LAPB */
#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */
#define ARPHRD_RAWHDLC 518 /* Raw HDLC */
+#define ARPHRD_RAWIP 530 /* Raw IP */
#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */
--
1.8.3.1
^ permalink raw reply related
* [RFC v3 2/8] ipv6: Add checks for RAWIP ARP type
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
net/ipv6/addrconf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d6ff126..cde1061 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1797,6 +1797,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
return addrconf_ifid_sit(eui, dev);
case ARPHRD_IPGRE:
return addrconf_ifid_gre(eui, dev);
+ case ARPHRD_RAWIP:
case ARPHRD_IEEE802154:
return addrconf_ifid_eui64(eui, dev);
case ARPHRD_IEEE1394:
@@ -2681,7 +2682,8 @@ static void addrconf_dev_config(struct net_device *dev)
(dev->type != ARPHRD_INFINIBAND) &&
(dev->type != ARPHRD_IEEE802154) &&
(dev->type != ARPHRD_IEEE1394) &&
- (dev->type != ARPHRD_TUNNEL6)) {
+ (dev->type != ARPHRD_TUNNEL6) &&
+ (dev->type != ARPHRD_RAWIP)) {
/* Alas, we support only Ethernet autoconfiguration. */
return;
}
--
1.8.3.1
^ permalink raw reply related
* [RFC v3 3/8] Bluetooth: Initial skeleton code for BT 6LoWPAN
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/6lowpan.c | 546 ++++++++++++++++++++++++++++++++++++++++++
net/bluetooth/6lowpan.h | 26 ++
net/bluetooth/Makefile | 2 +-
net/bluetooth/l2cap_core.c | 22 +-
5 files changed, 595 insertions(+), 2 deletions(-)
create mode 100644 net/bluetooth/6lowpan.c
create mode 100644 net/bluetooth/6lowpan.h
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 5132990..c28ac0d 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -133,6 +133,7 @@ struct l2cap_conninfo {
#define L2CAP_FC_L2CAP 0x02
#define L2CAP_FC_CONNLESS 0x04
#define L2CAP_FC_A2MP 0x08
+#define L2CAP_FC_6LOWPAN 0x3e
/* 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..2982a4e
--- /dev/null
+++ b/net/bluetooth/6lowpan.c
@@ -0,0 +1,546 @@
+/*
+ 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/bitops.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>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+
+#include "../ieee802154/6lowpan.h" /* for the compression defines */
+
+#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 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;
+ int peer_count;
+};
+
+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 peer *peer)
+{
+ list_add(&peer->list, &info->peers);
+ info->peer_count++;
+}
+
+static inline void peer_del(struct lowpan_info *info, struct peer *peer)
+{
+ list_del(&peer->list);
+ info->peer_count--;
+ if (info->peer_count < 0) {
+ BT_ERR("peer count underflow");
+ info->peer_count = 0;
+ }
+}
+
+static inline struct peer *peer_lookup_ba(struct lowpan_info *info,
+ __u8 type, bdaddr_t *ba)
+{
+ struct peer *peer, *tmp;
+
+ BT_DBG("peers %d addr %pMR type %d", 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 peer *peer_lookup_conn(struct lowpan_info *info,
+ struct l2cap_conn *conn)
+{
+ struct peer *peer, *tmp;
+
+ list_for_each_entry_safe(peer, tmp, &info->peers, list) {
+ if (peer->conn == conn)
+ return peer;
+ }
+
+ return NULL;
+}
+
+static struct peer *lookup_peer(struct l2cap_conn *conn,
+ struct lowpan_info **dev)
+{
+ struct lowpan_dev *entry, *tmp;
+ struct peer *peer = NULL;
+
+ write_lock(&devices_lock);
+
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+ struct lowpan_info *info = lowpan_info(entry->dev);
+
+ if (dev)
+ *dev = info;
+
+ peer = peer_lookup_conn(info, conn);
+ if (peer)
+ break;
+ }
+
+ write_unlock(&devices_lock);
+
+ return peer;
+}
+
+/* print data in line */
+static inline void raw_dump_inline(const char *caller, char *msg,
+ unsigned char *buf, int len)
+{
+#ifdef DEBUG
+ if (msg)
+ pr_debug("%s():%s: ", caller, msg);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE,
+ 16, 1, buf, len, false);
+#endif /* DEBUG */
+}
+
+/*
+ * 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)
+{
+#ifdef DEBUG
+ if (msg)
+ pr_debug("%s():%s:\n", caller, msg);
+ print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET,
+ 16, 1, buf, len, false);
+#endif /* DEBUG */
+}
+
+static int recv_pkt(struct sk_buff *skb, struct net_device *dev)
+{
+ 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 peer *peer;
+ int err = -ENOENT;
+
+ peer = lookup_peer(conn, &info);
+ if (!peer)
+ return -ENOENT;
+
+ if (info && info->net) {
+ err = recv_pkt(skb, info->net, conn);
+ BT_DBG("recv pkt %d", err);
+ }
+
+ 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);
+
+ return;
+}
+
+static int conn_send(struct l2cap_conn *conn,
+ void *msg, size_t len, u32 priority,
+ struct net_device *dev)
+{
+ struct sk_buff *skb = {0};
+
+ do_send(conn, skb);
+ return 0;
+}
+
+/* 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;
+
+ write_lock(&devices_lock);
+
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+ struct 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);
+ }
+ }
+
+ write_unlock(&devices_lock);
+
+ return err;
+}
+
+static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int err = -ENOENT;
+ unsigned char *eui64_addr;
+ struct lowpan_info *info;
+ struct 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 {
+ get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
+ eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
+ info = lowpan_info(dev);
+
+ write_lock(&devices_lock);
+ peer = peer_lookup_ba(info, addr_type, &addr);
+ write_unlock(&devices_lock);
+
+ 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 = xmit,
+};
+
+static void netdev_setup(struct net_device *dev)
+{
+ dev->addr_len = EUI64_ADDR_LEN;
+ dev->type = ARPHRD_RAWIP;
+
+ 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->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
+ */
+ 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;
+}
+
+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();
+}
+
+/*
+ * 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 peer *peer = NULL;
+ struct net_device *net;
+ struct lowpan_dev *entry;
+ struct inet6_dev *idev;
+ int err;
+
+ peer = lookup_peer(conn, &dev);
+ if (peer)
+ return -EEXIST;
+
+ /*
+ * If net device exists already, just add route.
+ */
+ 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);
+
+ idev = in6_dev_get(net);
+ if (idev) {
+ idev->cnf.autoconf = 1;
+ idev->cnf.forwarding = 1;
+ idev->cnf.accept_ra = 2;
+
+ in6_dev_put(idev);
+ }
+
+ entry = kzalloc(sizeof(struct lowpan_dev), GFP_KERNEL);
+ if (!entry) {
+ unregister_netdev(net);
+ return -ENOMEM;
+ }
+
+ entry->dev = net;
+
+ write_lock(&devices_lock);
+ INIT_LIST_HEAD(&entry->list);
+ list_add(&entry->list, &bt_6lowpan_devices);
+ write_unlock(&devices_lock);
+
+ ifup(net);
+
+add_peer:
+ peer = kzalloc(sizeof(struct peer), GFP_KERNEL);
+ if (!peer)
+ return -ENOMEM;
+
+ peer->conn = conn;
+
+ write_lock(&devices_lock);
+ INIT_LIST_HEAD(&peer->list);
+ peer_add(dev, peer);
+ write_unlock(&devices_lock);
+
+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 peer *peer;
+ int err = -ENOENT;
+
+ write_lock(&devices_lock);
+
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+ info = lowpan_info(entry->dev);
+ peer = peer_lookup_conn(info, conn);
+ if (peer) {
+ peer_del(info, peer);
+ err = 0;
+ break;
+ }
+ }
+
+ write_unlock(&devices_lock);
+
+ if (!err && info && info->peer_count == 0) {
+ /*
+ * This function 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);
+ }
+
+ 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;
+
+ if (dev->type != ARPHRD_RAWIP)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ write_lock(&devices_lock);
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
+ list) {
+ if (entry->dev == dev) {
+ list_del(&entry->list);
+ kfree(entry);
+ break;
+ }
+ }
+ write_unlock(&devices_lock);
+ 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..80cb215 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -10,6 +10,6 @@ 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
subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4af3821..155485f 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;
@@ -6473,6 +6474,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;
@@ -6510,6 +6515,11 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
return exact ? lm1 : lm2;
}
+static bool is_bt_6lowpan(struct hci_conn *hcon)
+{
+ return false;
+}
+
void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn;
@@ -6518,8 +6528,12 @@ 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);
+
+ if (is_bt_6lowpan(hcon))
+ bt_6lowpan_add_conn(conn);
+ }
} else {
l2cap_conn_del(hcon, bt_to_errno(status));
}
@@ -6540,6 +6554,9 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
BT_DBG("hcon %p reason %d", hcon, reason);
+ if (is_bt_6lowpan(hcon))
+ bt_6lowpan_del_conn(hcon->l2cap_data);
+
l2cap_conn_del(hcon, bt_to_errno(reason));
}
@@ -6817,11 +6834,14 @@ int __init l2cap_init(void)
l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
NULL, &l2cap_debugfs_fops);
+ bt_6lowpan_init();
+
return 0;
}
void l2cap_exit(void)
{
+ bt_6lowpan_cleanup();
debugfs_remove(l2cap_debugfs);
l2cap_cleanup_sockets();
}
--
1.8.3.1
^ permalink raw reply related
* [RFC v3 4/8] Bluetooth: Enable 6LoWPAN support for BT LE devices
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
net/bluetooth/6lowpan.c | 1039 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 1037 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 2982a4e..d33a32e 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -11,6 +11,20 @@
GNU General Public License for more details.
*/
+/*
+ * The compression, uncompression and IPv6 packet code
+ * is from net/ieee802154/6lowpan.c with these copyrights
+ *
+ * Copyright 2011, Siemens AG
+ * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ *
+ * Based on patches from Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * Jon's code is based on 6lowpan implementation for Contiki which is:
+ * Copyright (c) 2008, Swedish Institute of Computer Science.
+ */
+
#include <linux/version.h>
#include <linux/bitops.h>
#include <linux/if_arp.h>
@@ -176,8 +190,578 @@ static inline void raw_dump_table(const char *caller, char *msg,
#endif /* DEBUG */
}
-static int recv_pkt(struct sk_buff *skb, struct net_device *dev)
+static inline bool fetch_skb(struct sk_buff *skb,
+ void *data, const unsigned int len)
+{
+ if (unlikely(!pskb_may_pull(skb, len)))
+ return true;
+
+ skb_copy_from_linear_data(skb, data, len);
+ skb_pull(skb, len);
+
+ return false;
+}
+
+/*
+ * Uncompress address function for source and
+ * destination address(non-multicast).
+ *
+ * address_mode is sam value or dam value.
+ */
+static int uncompress_addr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 address_mode,
+ const u8 *lladdr)
+{
+ bool fail;
+
+ switch (address_mode) {
+ case LOWPAN_IPHC_ADDR_00:
+ /* for global link addresses */
+ fail = fetch_skb(skb, ipaddr->s6_addr, 16);
+ break;
+ case LOWPAN_IPHC_ADDR_01:
+ /* fe:80::XXXX:XXXX:XXXX:XXXX */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ fail = fetch_skb(skb, &ipaddr->s6_addr[8], 8);
+ break;
+ case LOWPAN_IPHC_ADDR_02:
+ /* fe:80::ff:fe00:XXXX */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ ipaddr->s6_addr[11] = 0xFF;
+ ipaddr->s6_addr[12] = 0xFE;
+ fail = fetch_skb(skb, &ipaddr->s6_addr[14], 2);
+ break;
+ case LOWPAN_IPHC_ADDR_03:
+ fail = false;
+ /* XXX: support only normal addr (IEEE802154_ADDR_LONG) atm */
+
+ /* fe:80::XXXX:XXXX:XXXX:XXXX
+ * \_________________/
+ * hwaddr
+ */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ memcpy(&ipaddr->s6_addr[8], lladdr, EUI64_ADDR_LEN);
+ break;
+ default:
+ pr_debug("Invalid address mode value: 0x%x\n", address_mode);
+ return -EINVAL;
+ }
+
+ if (fail) {
+ pr_debug("Failed to fetch skb data\n");
+ return -EIO;
+ }
+
+ raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
+ ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
+/*
+ * Uncompress address function for source context
+ * based address(non-multicast).
+ */
+static int uncompress_context_based_src_addr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 sam)
+{
+ switch (sam) {
+ case LOWPAN_IPHC_ADDR_00:
+ /* unspec address ::
+ * Do nothing, address is already ::
+ */
+ break;
+ case LOWPAN_IPHC_ADDR_01:
+ /* TODO */
+ case LOWPAN_IPHC_ADDR_02:
+ /* TODO */
+ case LOWPAN_IPHC_ADDR_03:
+ /* TODO */
+ netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
+ return -EINVAL;
+ default:
+ pr_debug("Invalid sam value: 0x%x\n", sam);
+ return -EINVAL;
+ }
+
+ raw_dump_inline(NULL,
+ "Reconstructed context based ipv6 src addr is",
+ ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
+/*
+ * This func is called when the packet from BT LE device
+ * needs to be sent upper layers.
+ */
+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;
+ } else {
+ ret = netif_rx(skb_cp);
+
+ BT_DBG("receive skb %d", ret);
+ if (ret < 0)
+ ret = NET_RX_DROP;
+ }
+
+ return ret;
+}
+
+static inline int fetch_skb_u8(struct sk_buff *skb, u8 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 1)))
+ return -EINVAL;
+
+ *val = skb->data[0];
+ skb_pull(skb, 1);
+
+ return 0;
+}
+
+static inline int fetch_skb_u16(struct sk_buff *skb, u16 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 2)))
+ return -EINVAL;
+
+ *val = (skb->data[0] << 8) | skb->data[1];
+ skb_pull(skb, 2);
+
+ return 0;
+}
+
+static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
+ struct net_device *dev)
+{
+ struct sk_buff *new;
+ int stat;
+
+ new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
+ GFP_ATOMIC);
+ kfree_skb(skb);
+
+ if (!new)
+ return -ENOMEM;
+
+ skb_push(new, sizeof(struct ipv6hdr));
+ skb_reset_network_header(new);
+ skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
+
+ new->protocol = htons(ETH_P_IPV6);
+ new->pkt_type = PACKET_HOST;
+ new->dev = dev;
+
+ raw_dump_table(__func__,
+ "raw skb data dump before receiving",
+ new->data, new->len);
+
+ stat = give_skb_to_upper(new, dev);
+
+ kfree_skb(new);
+
+ return stat;
+}
+
+/* Uncompress function for multicast destination address,
+ * when M bit is set.
+ */
+static int
+lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 dam)
+{
+ bool fail;
+
+ switch (dam) {
+ case LOWPAN_IPHC_DAM_00:
+ /* 00: 128 bits. The full address
+ * is carried in-line.
+ */
+ fail = fetch_skb(skb, ipaddr->s6_addr, 16);
+ break;
+ case LOWPAN_IPHC_DAM_01:
+ /* 01: 48 bits. The address takes
+ * the form ffXX::00XX:XXXX:XXXX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ fail = fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+ fail |= fetch_skb(skb, &ipaddr->s6_addr[11], 5);
+ break;
+ case LOWPAN_IPHC_DAM_10:
+ /* 10: 32 bits. The address takes
+ * the form ffXX::00XX:XXXX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ fail = fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+ fail |= fetch_skb(skb, &ipaddr->s6_addr[13], 3);
+ break;
+ case LOWPAN_IPHC_DAM_11:
+ /* 11: 8 bits. The address takes
+ * the form ff02::00XX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ ipaddr->s6_addr[1] = 0x02;
+ fail = fetch_skb(skb, &ipaddr->s6_addr[15], 1);
+ break;
+ default:
+ pr_debug("DAM value has a wrong value: 0x%x\n", dam);
+ return -EINVAL;
+ }
+
+ if (fail) {
+ pr_debug("Failed to fetch skb data\n");
+ return -EIO;
+ }
+
+ raw_dump_inline(NULL,
+ "Reconstructed ipv6 multicast addr is",
+ ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
+static int
+uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
+{
+ u8 tmp;
+
+ if (!uh)
+ goto err;
+
+ if (fetch_skb_u8(skb, &tmp))
+ goto err;
+
+ if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
+ pr_debug("UDP header uncompression\n");
+ switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
+ case LOWPAN_NHC_UDP_CS_P_00:
+ memcpy(&uh->source, &skb->data[0], 2);
+ memcpy(&uh->dest, &skb->data[2], 2);
+ skb_pull(skb, 4);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_01:
+ memcpy(&uh->source, &skb->data[0], 2);
+ uh->dest =
+ skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT;
+ skb_pull(skb, 3);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_10:
+ uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT;
+ memcpy(&uh->dest, &skb->data[1], 2);
+ skb_pull(skb, 3);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_11:
+ uh->source =
+ LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4);
+ uh->dest =
+ LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f);
+ skb_pull(skb, 1);
+ break;
+ default:
+ pr_debug("ERROR: unknown UDP format\n");
+ goto err;
+ break;
+ }
+
+ pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
+ uh->source, uh->dest);
+
+ /* copy checksum */
+ memcpy(&uh->check, &skb->data[0], 2);
+ skb_pull(skb, 2);
+
+ /*
+ * UDP lenght needs to be infered from the lower layers
+ * here, we obtain the hint from the remaining size of the
+ * frame
+ */
+ uh->len = htons(skb->len + sizeof(struct udphdr));
+ pr_debug("uncompressed UDP length: src = %d", uh->len);
+ } else {
+ pr_debug("ERROR: unsupported NH format\n");
+ goto err;
+ }
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+/* TTL uncompression values */
+static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
+
+static int process_data(struct sk_buff *skb, struct net_device *dev,
+ struct l2cap_conn *conn)
+{
+ struct ipv6hdr hdr = {};
+ u8 tmp, iphc0, iphc1, num_context = 0;
+ const u8 *_saddr = NULL, *_daddr = NULL;
+ struct lowpan_info *info;
+ struct peer *peer;
+ int err;
+
+ raw_dump_table(__func__, "raw skb data dump uncompressed",
+ skb->data, skb->len);
+
+ /* at least two bytes will be used for the encoding */
+ if (skb->len < 2)
+ goto drop;
+
+ if (fetch_skb_u8(skb, &iphc0))
+ goto drop;
+
+ info = lowpan_info(dev);
+
+ if (fetch_skb_u8(skb, &iphc1))
+ goto drop;
+
+ write_lock(&devices_lock);
+ peer = peer_lookup_conn(info, conn);
+ write_unlock(&devices_lock);
+ if (!peer)
+ goto drop;
+
+ _saddr = peer->eui64_addr;
+ _daddr = info->net->dev_addr;
+
+ /* another if the CID flag is set */
+ if (iphc1 & LOWPAN_IPHC_CID) {
+ pr_debug("CID flag is set, increase header with one\n");
+ if (fetch_skb_u8(skb, &num_context))
+ goto drop;
+ }
+
+ hdr.version = 6;
+
+ /* Traffic Class and Flow Label */
+ switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
+ /*
+ * Traffic Class and FLow Label carried in-line
+ * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+ */
+ case 0: /* 00b */
+ if (fetch_skb_u8(skb, &tmp))
+ goto drop;
+
+ memcpy(&hdr.flow_lbl, &skb->data[0], 3);
+ skb_pull(skb, 3);
+ hdr.priority = ((tmp >> 2) & 0x0f);
+ hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
+ (hdr.flow_lbl[0] & 0x0f);
+ break;
+ /*
+ * Traffic class carried in-line
+ * ECN + DSCP (1 byte), Flow Label is elided
+ */
+ case 1: /* 10b */
+ if (fetch_skb_u8(skb, &tmp))
+ goto drop;
+
+ hdr.priority = ((tmp >> 2) & 0x0f);
+ hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
+ break;
+ /*
+ * Flow Label carried in-line
+ * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
+ */
+ case 2: /* 01b */
+ if (fetch_skb_u8(skb, &tmp))
+ goto drop;
+
+ hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
+ memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
+ skb_pull(skb, 2);
+ break;
+ /* Traffic Class and Flow Label are elided */
+ case 3: /* 11b */
+ break;
+ default:
+ break;
+ }
+
+ /* Next Header */
+ if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+ /* Next header is carried inline */
+ if (fetch_skb_u8(skb, &(hdr.nexthdr)))
+ goto drop;
+
+ pr_debug("NH flag is set, next header carried inline: %02x\n",
+ hdr.nexthdr);
+ }
+
+ /* Hop Limit */
+ if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
+ hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
+ else {
+ if (fetch_skb_u8(skb, &(hdr.hop_limit)))
+ goto drop;
+ }
+
+ /* Extract SAM to the tmp variable */
+ tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
+
+ if (iphc1 & LOWPAN_IPHC_SAC) {
+ /* Source address context based uncompression */
+ pr_debug("SAC bit is set. Handle context based source address.\n");
+ err = uncompress_context_based_src_addr(
+ skb, &hdr.saddr, tmp);
+ } else {
+ /* Source address uncompression */
+ pr_debug("source address stateless compression\n");
+ err = uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
+ }
+
+ /* Check on error of previous branch */
+ if (err)
+ goto drop;
+
+ /* Extract DAM to the tmp variable */
+ tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
+
+ /* check for Multicast Compression */
+ if (iphc1 & LOWPAN_IPHC_M) {
+ if (iphc1 & LOWPAN_IPHC_DAC) {
+ pr_debug("dest: context-based mcast compression\n");
+ /* TODO: implement this */
+ } else {
+ err = lowpan_uncompress_multicast_daddr(
+ skb, &hdr.daddr, tmp);
+ if (err)
+ goto drop;
+ }
+ } else {
+ pr_debug("dest: stateless compression\n");
+ err = uncompress_addr(skb, &hdr.daddr, tmp, _daddr);
+ if (err)
+ goto drop;
+ }
+
+ /* UDP data uncompression */
+ if (iphc0 & LOWPAN_IPHC_NH_C) {
+ struct udphdr uh;
+ struct sk_buff *new;
+ if (uncompress_udp_header(skb, &uh))
+ goto drop;
+
+ /*
+ * replace the compressed UDP head by the uncompressed UDP
+ * header
+ */
+ new = skb_copy_expand(skb, sizeof(struct udphdr),
+ skb_tailroom(skb), GFP_ATOMIC);
+ kfree_skb(skb);
+
+ if (!new)
+ return -ENOMEM;
+
+ skb = new;
+
+ skb_push(skb, sizeof(struct udphdr));
+ skb_reset_transport_header(skb);
+ skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+ raw_dump_table(__func__, "raw UDP header dump",
+ (u8 *)&uh, sizeof(uh));
+
+ hdr.nexthdr = UIP_PROTO_UDP;
+ }
+
+ hdr.payload_len = htons(skb->len);
+
+ pr_debug("skb headroom size = %d, data length = %d\n",
+ skb_headroom(skb), skb->len);
+
+ pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
+ "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
+ hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
+ hdr.hop_limit, &hdr.daddr);
+
+ raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
+ sizeof(hdr));
+
+ return skb_deliver(skb, &hdr, dev);
+
+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_RAWIP)
+ goto drop;
+
+ raw_dump_table(__func__, "raw recv dump", skb->head,
+ skb->len);
+
+ /* 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;
}
@@ -206,19 +790,465 @@ 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);
return;
}
+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_KERNEL);
+ 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;
+
+ 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_KERNEL);
+ 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 = {0};
+ 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 u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
+ const struct in6_addr *ipaddr,
+ const unsigned char *lladdr)
+{
+ u8 val = 0;
+
+ if (is_addr_mac_addr_based(ipaddr, lladdr))
+ val = 3; /* 0-bits */
+ else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
+ /* compress IID to 16 bits xxxx::XXXX */
+ memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
+ *hc06_ptr += 2;
+ val = 2; /* 16-bits */
+ } else {
+ /* do not compress IID => xxxx::IID */
+ memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
+ *hc06_ptr += 8;
+ val = 1; /* 64-bits */
+ }
+
+ return rol8(val, shift);
+}
+
+static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
+{
+ struct udphdr *uh = udp_hdr(skb);
+
+ if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
+ LOWPAN_NHC_UDP_4BIT_PORT) &&
+ ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
+ LOWPAN_NHC_UDP_4BIT_PORT)) {
+ pr_debug("UDP header: both ports compression to 4 bits\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
+ **(hc06_ptr + 1) = /* subtraction is faster */
+ (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
+ ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
+ *hc06_ptr += 2;
+ } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
+ LOWPAN_NHC_UDP_8BIT_PORT) {
+ pr_debug("UDP header: remove 8 bits of dest\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
+ memcpy(*hc06_ptr + 1, &uh->source, 2);
+ **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
+ *hc06_ptr += 4;
+ } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
+ LOWPAN_NHC_UDP_8BIT_PORT) {
+ pr_debug("UDP header: remove 8 bits of source\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
+ memcpy(*hc06_ptr + 1, &uh->dest, 2);
+ **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
+ *hc06_ptr += 4;
+ } else {
+ pr_debug("UDP header: can't compress\n");
+ **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
+ memcpy(*hc06_ptr + 1, &uh->source, 2);
+ memcpy(*hc06_ptr + 3, &uh->dest, 2);
+ *hc06_ptr += 5;
+ }
+
+ /* checksum is always inline */
+ memcpy(*hc06_ptr, &uh->check, 2);
+ *hc06_ptr += 2;
+
+ /* skip the UDP header */
+ skb_pull(skb, sizeof(struct udphdr));
+}
+
+static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 1)))
+ return -EINVAL;
+
+ *val = skb->data[0];
+ skb_pull(skb, 1);
+
+ return 0;
+}
+
+static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 2)))
+ return -EINVAL;
+
+ *val = (skb->data[0] << 8) | skb->data[1];
+ skb_pull(skb, 2);
+
+ 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)
+{
+ u8 tmp, iphc0, iphc1, *hc06_ptr;
+ struct lowpan_info *info;
+ struct peer *peer;
+ struct ipv6hdr *hdr;
+ bdaddr_t addr, *any = BDADDR_ANY;
+ u8 *saddr, *daddr = any->b;
+ u8 addr_type;
+ u8 head[100];
+
+ if (type != ETH_P_IPV6)
+ return -EINVAL;
+
+ hdr = ipv6_hdr(skb);
+ hc06_ptr = head + 2;
+
+ pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
+ "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
+ hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
+ hdr->hop_limit, &hdr->daddr);
+
+ raw_dump_table(__func__, "raw skb network header dump",
+ skb_network_header(skb), sizeof(struct ipv6hdr));
+
+ 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 {
+ /*
+ * 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);
+
+ write_lock(&devices_lock);
+ peer = peer_lookup_ba(info, addr_type, &addr);
+ write_unlock(&devices_lock);
+
+ 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;
+
+ raw_dump_inline(__func__, "saddr",
+ (unsigned char *)saddr, 8);
+
+ /*
+ * As we copy some bit-length fields, in the IPHC encoding bytes,
+ * we sometimes use |=
+ * If the field is 0, and the current bit value in memory is 1,
+ * this does not work. We therefore reset the IPHC encoding here
+ */
+ iphc0 = LOWPAN_DISPATCH_IPHC;
+ iphc1 = 0;
+
+ /* TODO: context lookup */
+
+ raw_dump_inline(__func__, "daddr",
+ (unsigned char *)daddr, 8);
+
+ raw_dump_table(__func__,
+ "sending raw skb network uncompressed packet",
+ skb->data, skb->len);
+
+ /*
+ * Traffic class, flow label
+ * If flow label is 0, compress it. If traffic class is 0, compress it
+ * We have to process both in the same time as the offset of traffic
+ * class depends on the presence of version and flow label
+ */
+
+ /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
+ tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
+ tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
+
+ if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
+ (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
+ /* flow label can be compressed */
+ iphc0 |= LOWPAN_IPHC_FL_C;
+ if ((hdr->priority == 0) &&
+ ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+ /* compress (elide) all */
+ iphc0 |= LOWPAN_IPHC_TC_C;
+ } else {
+ /* compress only the flow label */
+ *hc06_ptr = tmp;
+ hc06_ptr += 1;
+ }
+ } else {
+ /* Flow label cannot be compressed */
+ if ((hdr->priority == 0) &&
+ ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+ /* compress only traffic class */
+ iphc0 |= LOWPAN_IPHC_TC_C;
+ *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
+ memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
+ hc06_ptr += 3;
+ } else {
+ /* compress nothing */
+ memcpy(hc06_ptr, &hdr, 4);
+ /* replace the top byte with new ECN | DSCP format */
+ *hc06_ptr = tmp;
+ hc06_ptr += 4;
+ }
+ }
+
+ /* NOTE: payload length is always compressed */
+
+ /* Next Header is compress if UDP */
+ if (hdr->nexthdr == UIP_PROTO_UDP)
+ iphc0 |= LOWPAN_IPHC_NH_C;
+
+ if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+ *hc06_ptr = hdr->nexthdr;
+ hc06_ptr += 1;
+ }
+
+ /*
+ * Hop limit
+ * if 1: compress, encoding is 01
+ * if 64: compress, encoding is 10
+ * if 255: compress, encoding is 11
+ * else do not compress
+ */
+ switch (hdr->hop_limit) {
+ case 1:
+ iphc0 |= LOWPAN_IPHC_TTL_1;
+ break;
+ case 64:
+ iphc0 |= LOWPAN_IPHC_TTL_64;
+ break;
+ case 255:
+ iphc0 |= LOWPAN_IPHC_TTL_255;
+ break;
+ default:
+ *hc06_ptr = hdr->hop_limit;
+ hc06_ptr += 1;
+ break;
+ }
+
+ /* source address compression */
+ if (is_addr_unspecified(&hdr->saddr)) {
+ pr_debug("source address is unspecified, setting SAC\n");
+ iphc1 |= LOWPAN_IPHC_SAC;
+ /* TODO: context lookup */
+ } else if (is_addr_link_local(&hdr->saddr)) {
+ pr_debug("source address is link-local\n");
+ iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+ LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr);
+ } else {
+ pr_debug("send the full source address\n");
+ memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
+ hc06_ptr += 16;
+ }
+
+ /* destination address compression */
+ if (is_addr_mcast(&hdr->daddr)) {
+ pr_debug("destination address is multicast: ");
+ iphc1 |= LOWPAN_IPHC_M;
+ if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
+ pr_debug("compressed to 1 octet\n");
+ iphc1 |= LOWPAN_IPHC_DAM_11;
+ /* use last byte */
+ *hc06_ptr = hdr->daddr.s6_addr[15];
+ hc06_ptr += 1;
+ } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
+ pr_debug("compressed to 4 octets\n");
+ iphc1 |= LOWPAN_IPHC_DAM_10;
+ /* second byte + the last three */
+ *hc06_ptr = hdr->daddr.s6_addr[1];
+ memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
+ hc06_ptr += 4;
+ } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
+ pr_debug("compressed to 6 octets\n");
+ iphc1 |= LOWPAN_IPHC_DAM_01;
+ /* second byte + the last five */
+ *hc06_ptr = hdr->daddr.s6_addr[1];
+ memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
+ hc06_ptr += 6;
+ } else {
+ pr_debug("using full address\n");
+ iphc1 |= LOWPAN_IPHC_DAM_00;
+ memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
+ hc06_ptr += 16;
+ }
+ } else {
+ /* TODO: context lookup */
+ if (is_addr_link_local(&hdr->daddr)) {
+ pr_debug("dest address is unicast and link-local\n");
+ iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+ LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr);
+ } else {
+ pr_debug("dest address is unicast: using full one\n");
+ memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
+ hc06_ptr += 16;
+ }
+ }
+
+ /* UDP header compression */
+ if (hdr->nexthdr == UIP_PROTO_UDP)
+ compress_udp_header(&hc06_ptr, skb);
+
+ head[0] = iphc0;
+ head[1] = iphc1;
+
+ skb_pull(skb, sizeof(struct ipv6hdr));
+
+ memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+
+ BT_DBG("header len %d skb %u", (int)(hc06_ptr - head), skb->len);
+
+ skb_reset_network_header(skb);
+
+ raw_dump_table(__func__, "raw skb data dump compressed",
+ skb->data, skb->len);
+ return 0;
+}
+
/* Packet to BT LE device */
static int send_pkt(struct l2cap_conn *conn, const void *saddr,
const void *daddr, struct sk_buff *skb,
@@ -309,6 +1339,10 @@ static const struct net_device_ops netdev_ops = {
.ndo_start_xmit = xmit,
};
+static struct header_ops header_ops = {
+ .create = header_create,
+};
+
static void netdev_setup(struct net_device *dev)
{
dev->addr_len = EUI64_ADDR_LEN;
@@ -322,6 +1356,7 @@ static void netdev_setup(struct net_device *dev)
dev->watchdog_timeo = 0;
dev->netdev_ops = &netdev_ops;
+ dev->header_ops = &header_ops;
dev->destructor = free_netdev;
}
--
1.8.3.1
^ permalink raw reply related
* [RFC v3 5/8] Bluetooth: Enable 6LoWPAN if device supports it
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_event.c | 3 +++
net/bluetooth/l2cap_core.c | 3 +++
4 files changed, 8 insertions(+)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 1784c48..f8f8447 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 8c0ab3d..e689052 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -449,6 +449,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/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 155485f..df475c7 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6517,6 +6517,9 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
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;
}
--
1.8.3.1
^ permalink raw reply related
* [RFC v3 6/8] route: Exporting ip6_route_add() so that Bluetooth 6LoWPAN can use it
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
net/ipv6/route.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c979dd9..d7c200f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1662,6 +1662,7 @@ out:
dst_free(&rt->dst);
return err;
}
+EXPORT_SYMBOL_GPL(ip6_route_add);
static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
{
--
1.8.3.1
^ permalink raw reply related
* [RFC v3 7/8] Bluetooth: Set route to peer for 6LoWPAN
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
net/bluetooth/6lowpan.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index d33a32e..e70302a 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -1395,6 +1395,38 @@ static void set_dev_addr(struct net_device *net, bdaddr_t *addr,
net->dev_addr[0] ^= 2;
}
+static int add_peer_route(struct peer *dev, struct net_device *net,
+ bdaddr_t *addr, u8 addr_type)
+{
+ struct in6_addr peer_addr;
+ struct fib6_config cfg = {
+ .fc_table = RT6_TABLE_MAIN,
+ .fc_metric = IP6_RT_PRIO_ADDRCONF,
+ .fc_ifindex = net->ifindex,
+ .fc_dst_len = 128,
+ .fc_flags = RTF_ADDRCONF | RTF_UP |
+ RTF_PREF(ICMPV6_ROUTER_PREF_MEDIUM),
+ .fc_nlinfo.portid = 0,
+ .fc_nlinfo.nlh = NULL,
+ .fc_nlinfo.nl_net = dev_net(net),
+ };
+
+ memset(&peer_addr, 0, sizeof(struct in6_addr));
+
+ /* RFC 2464 ch. 5 */
+ peer_addr.s6_addr[0] = 0xFE;
+ peer_addr.s6_addr[1] = 0x80;
+ set_addr((u8 *)&peer_addr.s6_addr + 8, addr->b, addr_type);
+
+ memcpy(&dev->eui64_addr, (u8 *)&peer_addr.s6_addr + 8, EUI64_ADDR_LEN);
+
+ BT_DBG("peer address %pI6c", (u8 *)&peer_addr.s6_addr);
+
+ cfg.fc_dst = dev->peer_addr = peer_addr;
+
+ return ip6_route_add(&cfg);
+}
+
static void ifup(struct net_device *net)
{
int err;
@@ -1492,6 +1524,11 @@ add_peer:
peer_add(dev, peer);
write_unlock(&devices_lock);
+ err = add_peer_route(peer, dev->net, &conn->hcon->dst,
+ conn->hcon->dst_type);
+ if (err < 0)
+ BT_INFO("Setting route failed %d", err);
+
out:
return err;
}
--
1.8.3.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox