Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH 1/7] android/tester: Fix enum and define coding style
From: Johan Hedberg @ 2013-12-18  8:05 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: Grzegorz Kolodziejczyk, linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZLCgpqR+hsR7vcadV52Y+x2jdRSWGQWfsSr3PhyPKCNTQ@mail.gmail.com>

Hi Luiz,

On Tue, Dec 17, 2013, Luiz Augusto von Dentz wrote:
> On Tue, Dec 17, 2013 at 2:37 PM, Grzegorz Kolodziejczyk
> <grzegorz.kolodziejczyk@tieto.com> wrote:
> > This changes all enums values and defines to uppercase instead of
> > lowercase according to coding style.
> > ---
> >  android/android-tester.c | 86 ++++++++++++++++++++++++------------------------
> >  1 file changed, 43 insertions(+), 43 deletions(-)
> >
> > diff --git a/android/android-tester.c b/android/android-tester.c
> > index eb938d0..4eb265b 100644
> > --- a/android/android-tester.c
> > +++ b/android/android-tester.c
> > @@ -37,10 +37,10 @@
> >  #include <hardware/bluetooth.h>
> >  #include <hardware/bt_sock.h>
> >
> > -#define adapter_props adapter_prop_bdaddr, adapter_prop_bdname, \
> > -                       adapter_prop_uuids, adapter_prop_cod, \
> > -                       adapter_prop_type, adapter_prop_scan_mode, \
> > -                       adapter_prop_bonded_devices, adapter_prop_disc_timeout
> > +#define ADAPTER_PROPS ADAPTER_PROP_BDADDR, ADAPTER_PROP_BDNAME, \
> > +                       ADAPTER_PROP_UUIDS, ADAPTER_PROP_COD, \
> > +                       ADAPTER_PROP_TYPE, ADAPTER_PROP_SCAN_MODE, \
> > +                       ADAPTER_PROP_BONDED_DEVICES, ADAPTER_PROP_DISC_TIMEOUT
> >
> >  static bt_scan_mode_t test_setprop_scanmode_val =
> >                                         BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
> > @@ -52,19 +52,19 @@ static uint32_t test_setprop_disctimeout_val = 120;
> >   */
> >
> >  enum hal_bluetooth_callbacks_id {
> > -       adapter_test_end,
> > -       adapter_test_setup_mode,
> > -       adapter_state_changed_on,
> > -       adapter_state_changed_off,
> > -       adapter_prop_bdaddr,
> > -       adapter_prop_bdname,
> > -       adapter_prop_uuids,
> > -       adapter_prop_cod,
> > -       adapter_prop_type,
> > -       adapter_prop_scan_mode,
> > -       adapter_prop_disc_timeout,
> > -       adapter_prop_service_record,
> > -       adapter_prop_bonded_devices
> > +       ADAPTER_TEST_END,
> > +       ADAPTER_TEST_SETUP_MODE,
> > +       ADAPTER_STATE_CHANGED_ON,
> > +       ADAPTER_STATE_CHANGED_OFF,
> > +       ADAPTER_PROP_BDADDR,
> > +       ADAPTER_PROP_BDNAME,
> > +       ADAPTER_PROP_UUIDS,
> > +       ADAPTER_PROP_COD,
> > +       ADAPTER_PROP_TYPE,
> > +       ADAPTER_PROP_SCAN_MODE,
> > +       ADAPTER_PROP_DISC_TIMEOUT,
> > +       ADAPTER_PROP_SERVICE_RECORD,
> > +       ADAPTER_PROP_BONDED_DEVICES
> >  };
> 
> This is something I dislike right now, why are defining these and not
> using directly the values defined in hal-msg.h? We should probably
> have a struct with expected opcode and value e.g:
> .{HAL_EV_ADAPTER_PROPS_CHANGED, BT_STATE_ON} and don't try to invent
> another ID for each of those.

I missed this email from you and already applied the patch. You're right
that if these are already defined elsewhere they should not be
redefined. What bugged me most about this was the lower-case so whatever
fix is done will have to be on top of this patch.

Johan

^ permalink raw reply

* Re: [PATCH 2/2] android/hidhost: Simplify handle_uhid_output
From: Johan Hedberg @ 2013-12-18  8:03 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Szymon Janc, linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZLu11494VB7WKMj-nxaXr1GfzNt_unYezPcU==e_7HweQ@mail.gmail.com>

Hi Luiz & Szymon,

On Mon, Dec 16, 2013, Luiz Augusto von Dentz wrote:
> On Mon, Dec 16, 2013 at 4:37 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
> > Make it use VLA for req buffer. This makes function simpler and also
> > fix cutting req to 255 bytes (req_len was uint8_t)
> > ---
> >  android/hidhost.c | 17 +++++------------
> >  1 file changed, 5 insertions(+), 12 deletions(-)
> >
> > diff --git a/android/hidhost.c b/android/hidhost.c
> > index 0e0391a..76322af 100644
> > --- a/android/hidhost.c
> > +++ b/android/hidhost.c
> > @@ -156,29 +156,22 @@ static void hid_device_free(struct hid_device *dev)
> >  static void handle_uhid_output(struct hid_device *dev,
> >                                                 struct uhid_output_req *output)
> >  {
> > -       int fd, i;
> > -       uint8_t *req = NULL;
> > -       uint8_t req_size = 0;
> > +       int fd;
> > +       unsigned int i;
> > +       uint8_t req[1 + (output->size / 2)];
> 
> Im not a fan of VLA and Ive seem even some static analyzer that would
> warn about its use without first checking > 0 and have a check of
> upper bond limit, so perhaps just having it set to UHID_DATA_MAX or
> dynamically allocate a buffer to match the output MTU size of the
> control channel would better imo.

I've applied the first patch in this set, but was there some conclusion
on how to proceed here?

If output->size was an uint8_t this would be a non-issue, but as it's
uint16_t I'm a bit uncomfortable with the idea of potentially having a
huge variable on the stack.

Johan

^ permalink raw reply

* Re: [PATCH 7/7] android/tester: Add SERVICE_RECORD set prop fail test case
From: Johan Hedberg @ 2013-12-18  8:00 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1387283874-29721-7-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Tue, Dec 17, 2013, Grzegorz Kolodziejczyk wrote:
> +static bt_service_record_t setprop_remote_service = {
> +	.uuid = { {0x00} },
> +	.channel = 12,
> +	.name = "bt_name"
> +};
> +
> +static const struct generic_data
> +			bluetooth_setprop_service_record_invalid_test = {
> +	.expected_hal_callbacks = {ADAPTER_TEST_END},
> +	.expected_adapter_status = BT_STATUS_FAIL,
> +	.expected_property.type = BT_PROPERTY_SERVICE_RECORD,
> +	.expected_property.val = &setprop_remote_service,
> +	.expected_property.len = sizeof(bt_service_record_t)

sizeof(setprop_remote_service);


Johan

^ permalink raw reply

* Re: [PATCH 6/7] android/tester: Add RSSI set prop fail test case
From: Johan Hedberg @ 2013-12-18  8:00 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1387283874-29721-6-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Tue, Dec 17, 2013, Grzegorz Kolodziejczyk wrote:
> +static int32_t setprop_remote_rssi = 0;
> +
> +static const struct generic_data bluetooth_setprop_remote_rssi_invalid_test = {
> +	.expected_hal_callbacks = {ADAPTER_TEST_END},
> +	.expected_adapter_status = BT_STATUS_FAIL,
> +	.expected_property.type = BT_PROPERTY_REMOTE_RSSI,
> +	.expected_property.val = &setprop_remote_rssi,
> +	.expected_property.len = sizeof(int32_t)

sizeof(setprop_remote_rssi);

Johan

^ permalink raw reply

* Re: [PATCH 5/7] android/tester: Add TOD set prop fail test case
From: Johan Hedberg @ 2013-12-18  8:00 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1387283874-29721-5-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Tue, Dec 17, 2013, Grzegorz Kolodziejczyk wrote:
> This adds TYPE_OF_DEVICE set property fail test case due to only
> get possibility.
> ---
>  android/android-tester.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/android/android-tester.c b/android/android-tester.c
> index a6f66c2..4923a6c 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -618,6 +618,16 @@ static const struct generic_data bluetooth_setprop_cod_invalid_test = {
>  	.expected_property.len = sizeof(uint32_t)
>  };
>  
> +static bt_device_type_t setprop_type_of_device = BT_DEVICE_DEVTYPE_BREDR;
> +
> +static const struct generic_data bluetooth_setprop_tod_invalid_test = {
> +	.expected_hal_callbacks = {ADAPTER_TEST_END},
> +	.expected_adapter_status = BT_STATUS_FAIL,
> +	.expected_property.type = BT_PROPERTY_TYPE_OF_DEVICE,
> +	.expected_property.val = &setprop_type_of_device,
> +	.expected_property.len = sizeof(bt_device_type_t)

sizeof(setprop_type_of_device)

Johan

^ permalink raw reply

* Re: [PATCH 4/7] android/tester: Add COD set prop fail test case
From: Johan Hedberg @ 2013-12-18  7:59 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1387283874-29721-4-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Tue, Dec 17, 2013, Grzegorz Kolodziejczyk wrote:
> This adds CLASS_OF_DEVICE set property fail test case due to only
> get possibility.
> ---
>  android/android-tester.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/android/android-tester.c b/android/android-tester.c
> index 4fe0033..a6f66c2 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -608,6 +608,16 @@ static const struct generic_data bluetooth_setprop_uuid_invalid_test = {
>  	.expected_property.len = 17
>  };
>  
> +static uint32_t setprop_class_of_device = 0;
> +
> +static const struct generic_data bluetooth_setprop_cod_invalid_test = {
> +	.expected_hal_callbacks = {ADAPTER_TEST_END},
> +	.expected_adapter_status = BT_STATUS_FAIL,
> +	.expected_property.type = BT_PROPERTY_CLASS_OF_DEVICE,
> +	.expected_property.val = &setprop_class_of_device,
> +	.expected_property.len = sizeof(uint32_t)

sizeof(setprop_class_of_device) makes more sense than uint32_t.

Johan

^ permalink raw reply

* Re: [PATCH 3/7] android/tester: Add UUIDS set prop fail test case
From: Johan Hedberg @ 2013-12-18  7:58 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1387283874-29721-3-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Tue, Dec 17, 2013, Grzegorz Kolodziejczyk wrote:
> This adds UUIDS set property fail test case due to only get
> possibility.
> ---
>  android/android-tester.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)

The first two patches have been applied, but a minor thing with this
one:

> +static unsigned char setprop_uuids[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00,
> +			0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
> +			0x00, 0x00 };
> +
> +static const struct generic_data bluetooth_setprop_uuid_invalid_test = {
> +	.expected_hal_callbacks = {ADAPTER_TEST_END},
> +	.expected_adapter_status = BT_STATUS_FAIL,
> +	.expected_property.type = BT_PROPERTY_UUIDS,
> +	.expected_property.val = &setprop_uuids,
> +	.expected_property.len = 17

How about sizeof(setprop_uuids) here instead of 17?

Johan

^ permalink raw reply

* [PATCH 4/4] tools/l2cap-tester: Add server write test case
From: Marcin @ 2013-12-17 14:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcin Kraglak
In-Reply-To: <1387291779-14960-1-git-send-email-marcin.kraglak@tieto.com>

From: Marcin Kraglak <marcin.kraglak@tieto.com>

This test case checks if data was received on client side.
---
 tools/l2cap-tester.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index cbea26e..35d4634 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -68,6 +68,8 @@ struct l2cap_server_data {
 	uint8_t expect_rsp_code;
 	const void *expect_rsp;
 	uint16_t expect_rsp_len;
+	const void *write_data;
+	uint16_t write_data_len;
 };
 
 static void mgmt_debug(const char *str, void *user_data)
@@ -273,6 +275,16 @@ static const struct l2cap_server_data l2cap_server_success_test = {
 	.expect_rsp_code = BT_L2CAP_PDU_CONN_RSP,
 };
 
+static const struct l2cap_server_data l2cap_server_success_write_test = {
+	.server_psm = 0x1001,
+	.send_req_code = BT_L2CAP_PDU_CONN_REQ,
+	.send_req = l2cap_connect_req,
+	.send_req_len = sizeof(l2cap_connect_req),
+	.expect_rsp_code = BT_L2CAP_PDU_CONN_RSP,
+	.write_data = l2cap_write_data,
+	.write_data_len = sizeof(l2cap_write_data),
+};
+
 static const uint8_t l2cap_nval_psm_rsp[] = {	0x00, 0x00,	/* dcid */
 						0x41, 0x00,	/* scid */
 						0x02, 0x00,	/* nval PSM */
@@ -482,6 +494,22 @@ static void l2cap_client_data(const void *data, uint16_t len)
 		tester_test_passed();
 }
 
+static void l2cap_server_data(const void *data, uint16_t len)
+{
+	struct test_data *test_data = tester_get_data();
+	const struct l2cap_server_data *l2data = test_data->test_data;
+
+	if (len != l2data->write_data_len) {
+		tester_test_failed();
+		return;
+	}
+
+	if (memcmp(data, l2data->write_data, len))
+		tester_test_failed();
+	else
+		tester_test_passed();
+}
+
 static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -637,6 +665,7 @@ static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct l2cap_server_data *l2data = data->test_data;
 	int sk, new_sk;
 
 	data->io_id = 0;
@@ -652,6 +681,22 @@ static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
 
 	tester_print("Successfully connected");
 
+	if (l2data->write_data) {
+		struct bthost *temp;
+		int len;
+
+		temp = hciemu_client_get_host(data->hciemu);
+		bthost_l2cap_set_data_handler(temp, l2cap_server_data,
+						l2data->server_psm);
+
+		len = write(new_sk, l2data->write_data,
+						l2data->write_data_len);
+		if (len != l2data->write_data_len)
+			tester_test_failed();
+
+		return FALSE;
+	}
+
 	close(new_sk);
 
 	tester_test_passed();
@@ -794,6 +839,9 @@ int main(int argc, char *argv[])
 	test_l2cap_bredr("L2CAP BR/EDR Server - Success",
 					&l2cap_server_success_test,
 					setup_powered_server, test_server);
+	test_l2cap_bredr("L2CAP BR/EDR Server - Write Success",
+					&l2cap_server_success_write_test,
+					setup_powered_server, test_server);
 	test_l2cap_bredr("L2CAP BR/EDR Server - Invalid PSM",
 					&l2cap_server_nval_psm_test,
 					setup_powered_server, test_server);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 3/4] tools/l2cap-tester: Add client test with write data
From: Marcin @ 2013-12-17 14:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcin Kraglak
In-Reply-To: <1387291779-14960-1-git-send-email-marcin.kraglak@tieto.com>

From: Marcin Kraglak <marcin.kraglak@tieto.com>

This test checks if data is received on server side.
---
 tools/l2cap-tester.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index e4dade2..cbea26e 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -56,6 +56,8 @@ struct l2cap_client_data {
 	uint16_t client_psm;
 	uint16_t server_psm;
 	int expect_err;
+	const void *write_data;
+	uint16_t write_data_len;
 };
 
 struct l2cap_server_data {
@@ -247,6 +249,15 @@ static const struct l2cap_client_data client_connect_success_test = {
 	.server_psm = 0x1001,
 };
 
+static const uint8_t l2cap_write_data[] = { 0x01, 0x02, 0x03, 0x04 };
+
+static const struct l2cap_client_data client_connect_success_write_test = {
+	.client_psm = 0x1001,
+	.server_psm = 0x1001,
+	.write_data = l2cap_write_data,
+	.write_data_len = sizeof(l2cap_write_data),
+};
+
 static const struct l2cap_client_data client_connect_nval_psm_test = {
 	.client_psm = 0x1001,
 	.expect_err = ECONNREFUSED,
@@ -455,6 +466,22 @@ static void test_basic(const void *test_data)
 	tester_test_passed();
 }
 
+static void l2cap_client_data(const void *data, uint16_t len)
+{
+	struct test_data *test_data = tester_get_data();
+	const struct l2cap_client_data *l2data = test_data->test_data;
+
+	if (len != l2data->write_data_len) {
+		tester_test_failed();
+		return;
+	}
+
+	if (memcmp(data, l2data->write_data, len))
+		tester_test_failed();
+	else
+		tester_test_passed();
+}
+
 static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -477,10 +504,23 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 	else
 		tester_print("Successfully connected");
 
-	if (-err != l2data->expect_err)
-		tester_test_failed();
-	else
-		tester_test_passed();
+	if (l2data->write_data) {
+		struct bthost *temp;
+		int len;
+
+		temp = hciemu_client_get_host(data->hciemu);
+		bthost_l2cap_set_data_handler(temp, l2cap_client_data,
+							l2data->client_psm);
+
+		len = write(sk, l2data->write_data, l2data->write_data_len);
+		if (len != l2data->write_data_len)
+			tester_test_failed();
+	} else {
+		if (-err != l2data->expect_err)
+			tester_test_failed();
+		else
+			tester_test_passed();
+	}
 
 	return FALSE;
 }
@@ -744,6 +784,9 @@ int main(int argc, char *argv[])
 	test_l2cap_bredr("L2CAP BR/EDR Client - Success",
 					&client_connect_success_test,
 					setup_powered_client, test_connect);
+	test_l2cap_bredr("L2CAP BR/EDR Client - Write Success",
+					&client_connect_success_write_test,
+					setup_powered_client, test_connect);
 	test_l2cap_bredr("L2CAP BR/EDR Client - Invalid PSM",
 					&client_connect_nval_psm_test,
 					setup_powered_client, test_connect);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 2/4] emulator: Add data handler for l2cap connections
From: Marcin @ 2013-12-17 14:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcin Kraglak
In-Reply-To: <1387291779-14960-1-git-send-email-marcin.kraglak@tieto.com>

From: Marcin Kraglak <marcin.kraglak@tieto.com>

Add possibility to handle data received on specified psm.
---
 emulator/bthost.c | 19 ++++++++++++++++++-
 emulator/bthost.h |  6 ++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 32d46b0..bd8bd00 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -103,6 +103,8 @@ struct bthost {
 	void *new_conn_data;
 	uint16_t server_psm;
 	struct l2cap_pending_req *l2reqs;
+	uint16_t read_data_psm;
+	bthost_l2cap_data_cb l2cap_data_cb;
 };
 
 struct bthost *bthost_create(void)
@@ -1119,6 +1121,7 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 	uint16_t handle, cid, acl_len, l2_len;
 	struct cid_hook *hook;
 	struct btconn *conn;
+	struct l2conn *l2conn;
 	const void *l2_data;
 
 	if (len < sizeof(*acl_hdr) + sizeof(*l2_hdr))
@@ -1157,7 +1160,13 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 		l2cap_le_sig(bthost, conn, l2_data, l2_len);
 		break;
 	default:
-		printf("Packet for unknown CID 0x%04x (%u)\n", cid, cid);
+		l2conn = btconn_find_l2cap_conn_by_scid(conn, cid);
+		if (l2conn && l2conn->psm &&
+				l2conn->psm == bthost->read_data_psm)
+			bthost->l2cap_data_cb(l2_data, l2_len);
+		else
+			printf("Packet for unknown CID 0x%04x (%u)\n", cid,
+									cid);
 		break;
 	}
 }
@@ -1254,6 +1263,14 @@ void bthost_set_server_psm(struct bthost *bthost, uint16_t psm)
 	bthost->server_psm = psm;
 }
 
+void bthost_l2cap_set_data_handler(struct bthost *bthost,
+					bthost_l2cap_data_cb handler,
+					uint16_t psm)
+{
+	bthost->read_data_psm = psm;
+	bthost->l2cap_data_cb = handler;
+}
+
 void bthost_start(struct bthost *bthost)
 {
 	if (!bthost)
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 474ada9..5703262 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -68,6 +68,12 @@ bool bthost_l2cap_req(struct bthost *bthost, uint16_t handle, uint8_t req,
 				const void *data, uint16_t len,
 				bthost_l2cap_rsp_cb cb, void *user_data);
 
+typedef void (*bthost_l2cap_data_cb) (const void *data, uint16_t len);
+
+void bthost_l2cap_set_data_handler(struct bthost *bthost,
+					bthost_l2cap_data_cb handler,
+					uint16_t psm);
+
 void bthost_write_scan_enable(struct bthost *bthost, uint8_t scan);
 
 void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 1/4] emulator: Add psm handling to bthost
From: Marcin @ 2013-12-17 14:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcin Kraglak

From: Marcin Kraglak <marcin.kraglak@tieto.com>

Store psm of l2cap connections. We retrieve psm from
connection request frame.
---
 emulator/bthost.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index b05072a..32d46b0 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -79,6 +79,7 @@ struct btconn {
 struct l2conn {
 	uint16_t scid;
 	uint16_t dcid;
+	uint16_t psm;
 	struct l2conn *next;
 };
 
@@ -154,7 +155,8 @@ static struct btconn *bthost_find_conn(struct bthost *bthost, uint16_t handle)
 }
 
 static void bthost_add_l2cap_conn(struct bthost *bthost, struct btconn *conn,
-						uint16_t scid, uint16_t dcid)
+						uint16_t scid, uint16_t dcid,
+						uint16_t psm)
 {
 	struct l2conn *l2conn;
 
@@ -164,6 +166,7 @@ static void bthost_add_l2cap_conn(struct bthost *bthost, struct btconn *conn,
 
 	memset(l2conn, 0, sizeof(*l2conn));
 
+	l2conn->psm = psm;
 	l2conn->scid = scid;
 	l2conn->dcid = dcid;
 
@@ -376,6 +379,15 @@ bool bthost_l2cap_req(struct bthost *bthost, uint16_t handle, uint8_t code,
 	if (!conn)
 		return false;
 
+	if (code == BT_L2CAP_PDU_CONN_REQ &&
+			len == sizeof(struct bt_l2cap_pdu_conn_req)) {
+		const struct bt_l2cap_pdu_conn_req *req = data;
+
+		bthost_add_l2cap_conn(bthost, conn, le16_to_cpu(req->scid),
+							le16_to_cpu(req->scid),
+							le16_to_cpu(req->psm));
+	}
+
 	ident = l2cap_sig_send(bthost, conn, code, 0, data, len);
 	if (!ident)
 		return false;
@@ -737,7 +749,8 @@ static bool l2cap_conn_req(struct bthost *bthost, struct btconn *conn,
 		struct bt_l2cap_pdu_config_req conf_req;
 
 		bthost_add_l2cap_conn(bthost, conn, le16_to_cpu(rsp.dcid),
-							le16_to_cpu(rsp.scid));
+							le16_to_cpu(rsp.scid),
+							le16_to_cpu(psm));
 
 		memset(&conf_req, 0, sizeof(conf_req));
 		conf_req.dcid = rsp.dcid;
@@ -753,12 +766,16 @@ static bool l2cap_conn_rsp(struct bthost *bthost, struct btconn *conn,
 				uint8_t ident, const void *data, uint16_t len)
 {
 	const struct bt_l2cap_pdu_conn_rsp *rsp = data;
+	struct l2conn *l2conn;
 
 	if (len < sizeof(*rsp))
 		return false;
 
-	bthost_add_l2cap_conn(bthost, conn, le16_to_cpu(rsp->scid),
-						le16_to_cpu(rsp->dcid));
+	l2conn = btconn_find_l2cap_conn_by_scid(conn, le16_to_cpu(rsp->scid));
+	if (l2conn)
+		l2conn->dcid = le16_to_cpu(rsp->dcid);
+	else
+		return false;
 
 	if (le16_to_cpu(rsp->result) == 0x0001) {
 		struct bt_l2cap_pdu_config_req req;
@@ -1013,8 +1030,8 @@ static bool l2cap_le_conn_rsp(struct bthost *bthost, struct btconn *conn,
 
 	if (len < sizeof(*rsp))
 		return false;
-
-	bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->dcid));
+	/* TODO add l2cap connection with proper psm when sending conn req*/
+	bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->dcid), 0);
 
 	return true;
 }
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH v3 bluetooth-next 0/8] 6lowpan: udp compression/uncompression fix
From: Marcel Holtmann @ 2013-12-17 14:18 UTC (permalink / raw)
  To: Alexander Aring
  Cc: linux-zigbee-devel, werner,
	linux-bluetooth@vger.kernel.org development
In-Reply-To: <1387286488-29382-1-git-send-email-alex.aring@gmail.com>

Hi Alex,

> The current 6LoWPAN udp compression/uncompression is completely broken.
> This patch series fix a lot of udp compression/uncompression issues and
> add support parsing with lowpan_fetch_skb/lowpan_push_hc_data functions.
> 
> I tested it in all cases of compressions in wireshark and a contiki
> sensornode.
> 
> Changes since v3:
> - add patch to introduce lowpan_push_hc_data helper function.
> - remove patch to fix nullpointer dereferencing and replace it with
>   a patch which use the lowpan_push_hc_data function in compress_udp_header
>   function. This fixes the nullpointer dereferencing problem also and is more
>   readable.
> - add missing newline in pr_debug_ratelimited.
> 
> Changes since v2:
> - remove unnecessary casts and brackes, suggested by Werner Almesberger.
> - use pr_debug_ratelimited instead of pr_debug on patch 4/7.
> 
> Alexander Aring (8):
>  6lowpan: introduce lowpan_push_hc_data function
>  6lowpan: udp use lowpan_push_hc_data function
>  6lowpan: fix udp compress ordering
>  6lowpan: fix udp byte ordering
>  6lowpan: add udp warning for elided checksum
>  6lowpan: udp use lowpan_fetch_skb function
>  6lowpan: udp use subtraction on both conditions
>  6lowpan: cleanup udp compress function
> 
> net/ieee802154/6lowpan.h      |   8 +++
> net/ieee802154/6lowpan_iphc.c | 114 ++++++++++++++++++++++++------------------
> 2 files changed, 74 insertions(+), 48 deletions(-)

all 8 patches have been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* [PATCH_v3 5/5] bnep: Refactor bnep setup response validation functionality
From: Ravi kumar Veeramally @ 2013-12-17 14:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387289872-23408-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Providing single api to validate bnep setup resp and hide
other functions.
---
 profiles/network/bnep.c   | 49 ++++++++++++++++++++++++++++++++++++++++++-----
 profiles/network/bnep.h   |  4 +---
 profiles/network/server.c | 45 +++++++++----------------------------------
 3 files changed, 54 insertions(+), 44 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index dd69851..1fd20f7 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -567,19 +567,19 @@ ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp)
 	return send(sk, &rsp, sizeof(rsp), 0);
 }
 
-uint16_t bnep_setup_chk(uint16_t dst, uint16_t src)
+static uint16_t bnep_setup_chk(uint16_t dst, uint16_t src)
 {
 	/* Allowed PAN Profile scenarios */
 	switch (dst) {
 	case BNEP_SVC_NAP:
 	case BNEP_SVC_GN:
 		if (src == BNEP_SVC_PANU)
-			return 0;
+			return BNEP_SUCCESS;
 		return BNEP_CONN_INVALID_SRC;
 	case BNEP_SVC_PANU:
 		if (src == BNEP_SVC_PANU ||  src == BNEP_SVC_GN ||
 							src == BNEP_SVC_NAP)
-			return 0;
+			return BNEP_SUCCESS;
 
 		return BNEP_CONN_INVALID_SRC;
 	}
@@ -587,8 +587,8 @@ uint16_t bnep_setup_chk(uint16_t dst, uint16_t src)
 	return BNEP_CONN_INVALID_DST;
 }
 
-uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
-								uint16_t *src)
+static uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req,
+						uint16_t *dst, uint16_t *src)
 {
 	const uint8_t bt_base[] = { 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
 					0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
@@ -633,3 +633,42 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
 
 	return BNEP_SUCCESS;
 }
+
+int bnep_validate_setup_rsp(int sk, uint16_t *dst)
+{
+	uint8_t packet[BNEP_MTU];
+	struct bnep_setup_conn_req *req = (void *) packet;
+	uint16_t src;
+	uint8_t pkt[3];
+	int n, rsp = BNEP_CONN_NOT_ALLOWED;
+
+	/* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
+	n = read(sk, packet, sizeof(packet));
+	if (n < 0) {
+		error("read(): %s(%d)", strerror(errno), errno);
+		return n;
+	}
+
+	/* Highest known Control command ID
+	 * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
+	if (req->type == BNEP_CONTROL &&
+				req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+		pkt[0] = BNEP_CONTROL;
+		pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
+		pkt[2] = req->ctrl;
+
+		send(sk, pkt, sizeof(pkt), 0);
+		return -EINVAL;
+	}
+
+	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
+		return -EINVAL;
+
+	rsp = bnep_setup_decode(req, dst, &src);
+	if (rsp)
+		return rsp;
+
+	rsp = bnep_setup_chk(*dst, src);
+
+	return rsp;
+}
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index d177ea0..97e19f6 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -42,7 +42,5 @@ int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
 							const bdaddr_t *addr);
 void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr);
 
+int bnep_validate_setup_rsp(int sk, uint16_t *dst);
 ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp);
-uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role);
-uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
-								uint16_t *src);
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 7cb5a1e..ac0c653 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -282,10 +282,8 @@ static gboolean bnep_setup(GIOChannel *chan,
 {
 	struct network_adapter *na = user_data;
 	struct network_server *ns;
-	uint8_t packet[BNEP_MTU];
-	struct bnep_setup_conn_req *req = (void *) packet;
-	uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
-	int n, sk;
+	uint16_t dst;
+	int sk, rsp = BNEP_CONN_NOT_ALLOWED;
 
 	if (cond & G_IO_NVAL)
 		return FALSE;
@@ -297,44 +295,18 @@ static gboolean bnep_setup(GIOChannel *chan,
 
 	sk = g_io_channel_unix_get_fd(chan);
 
-	/* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
-	n = read(sk, packet, sizeof(packet));
-	if (n < 0) {
-		error("read(): %s(%d)", strerror(errno), errno);
+	rsp = bnep_validate_setup_rsp(sk, &dst);
+	if (rsp < 0)
 		return FALSE;
-	}
-
-	/* Highest known Control command ID
-	 * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
-	if (req->type == BNEP_CONTROL &&
-				req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
-		uint8_t pkt[3];
-
-		pkt[0] = BNEP_CONTROL;
-		pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
-		pkt[2] = req->ctrl;
-
-		send(sk, pkt, sizeof(pkt), 0);
-
-		return FALSE;
-	}
-
-	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
-		return FALSE;
-
-	rsp = bnep_setup_decode(req, &dst_role, &src_role);
-	if (rsp)
-		goto reply;
 
-	rsp = bnep_setup_chk(dst_role, src_role);
-	if (rsp)
+	if (rsp > 0)
 		goto reply;
 
 	rsp = BNEP_CONN_NOT_ALLOWED;
 
-	ns = find_server(na->servers, dst_role);
+	ns = find_server(na->servers, dst);
 	if (!ns) {
-		error("Server unavailable: (0x%x)", dst_role);
+		error("Server unavailable: (0x%x)", dst);
 		goto reply;
 	}
 
@@ -348,10 +320,11 @@ static gboolean bnep_setup(GIOChannel *chan,
 		goto reply;
 	}
 
-	if (bnep_server_add(sk, dst_role, ns->bridge, na->setup->dev,
+	if (bnep_server_add(sk, dst, ns->bridge, na->setup->dev,
 							&na->setup->dst) < 0)
 		goto reply;
 
+	ns->sessions = g_slist_append(ns->sessions, na->setup);
 	na->setup = NULL;
 
 	rsp = BNEP_SUCCESS;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v3 4/5] bnep: Refactored bnep server apis for bridge addition and deletion
From: Ravi kumar Veeramally @ 2013-12-17 14:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387289872-23408-1-git-send-email-ravikumar.veeramally@linux.intel.com>

To simplify bnep server realted bridge creation and deletion calls
provided extra apis and moved related apis to static.
---
 profiles/network/bnep.c   | 50 +++++++++++++++++++++++++++++++++++++++++------
 profiles/network/bnep.h   | 10 ++++------
 profiles/network/server.c | 37 +++--------------------------------
 3 files changed, 51 insertions(+), 46 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 6416535..dd69851 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -152,7 +152,7 @@ int bnep_cleanup(void)
 	return 0;
 }
 
-int bnep_conndel(const bdaddr_t *dst)
+static int bnep_conndel(const bdaddr_t *dst)
 {
 	struct bnep_conndel_req req;
 
@@ -168,7 +168,7 @@ int bnep_conndel(const bdaddr_t *dst)
 	return 0;
 }
 
-int bnep_connadd(int sk, uint16_t role, char *dev)
+static int bnep_connadd(int sk, uint16_t role, char *dev)
 {
 	struct bnep_connadd_req req;
 
@@ -188,7 +188,7 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
 	return 0;
 }
 
-int bnep_if_up(const char *devname)
+static int bnep_if_up(const char *devname)
 {
 	struct ifreq ifr;
 	int sk, err;
@@ -213,7 +213,7 @@ int bnep_if_up(const char *devname)
 	return 0;
 }
 
-int bnep_if_down(const char *devname)
+static int bnep_if_down(const char *devname)
 {
 	struct ifreq ifr;
 	int sk, err;
@@ -458,7 +458,7 @@ void bnep_disconnect(struct bnep_conn *bc)
 	bnep_conndel(&bc->dst_addr);
 }
 
-int bnep_add_to_bridge(const char *devname, const char *bridge)
+static int bnep_add_to_bridge(const char *devname, const char *bridge)
 {
 	int ifindex;
 	struct ifreq ifr;
@@ -489,7 +489,7 @@ int bnep_add_to_bridge(const char *devname, const char *bridge)
 	return 0;
 }
 
-int bnep_del_from_bridge(const char *devname, const char *bridge)
+static int bnep_del_from_bridge(const char *devname, const char *bridge)
 {
 	int ifindex = if_nametoindex(devname);
 	struct ifreq ifr;
@@ -518,6 +518,44 @@ int bnep_del_from_bridge(const char *devname, const char *bridge)
 	return 0;
 }
 
+int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
+						const bdaddr_t *addr)
+{
+	if (!bridge || !bridge || !iface || !addr)
+		return -EINVAL;
+
+	if (bnep_connadd(sk, dst, iface) < 0) {
+		error("Can't add connection to the bridge %s: %s(%d)",
+						bridge, strerror(errno), errno);
+		return -errno;
+	}
+
+	if (bnep_add_to_bridge(iface, bridge) < 0) {
+		error("Can't add %s to the bridge %s: %s(%d)",
+					iface, bridge, strerror(errno), errno);
+		bnep_conndel(addr);
+		return -errno;
+	}
+
+	if (bnep_if_up(iface) < 0) {
+		error("Can't up the interface %s: %s(%d)",
+						iface, strerror(errno), errno);
+		return -errno;
+	}
+
+	return 0;
+}
+
+void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
+{
+	if (!bridge || !iface || !addr)
+		return;
+
+	bnep_del_from_bridge(iface, bridge);
+	bnep_if_down(iface);
+	bnep_conndel(addr);
+}
+
 ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp)
 {
 	struct bnep_control_rsp rsp;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 6e385e4..d177ea0 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -37,12 +37,10 @@ typedef void (*bnep_disconnect_cb) (void *data);
 int bnep_connect(struct bnep_conn *bnep, int sk, bnep_connect_cb conn_cb,
 				bnep_disconnect_cb disconn_cb, void *data);
 void bnep_disconnect(struct bnep_conn *bnep);
-int bnep_connadd(int sk, uint16_t role, char *dev);
-int bnep_conndel(const bdaddr_t *dst);
-int bnep_if_up(const char *devname);
-int bnep_if_down(const char *devname);
-int bnep_add_to_bridge(const char *devname, const char *bridge);
-int bnep_del_from_bridge(const char *devname, const char *bridge);
+
+int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
+							const bdaddr_t *addr);
+void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr);
 
 ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp);
 uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role);
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 73741ec..7cb5a1e 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -251,35 +251,6 @@ static sdp_record_t *server_record_new(const char *name, uint16_t id)
 	return record;
 }
 
-static int server_connadd(struct network_server *ns,
-				struct network_session *session,
-				uint16_t dst_role)
-{
-	char devname[16];
-	int err, nsk;
-
-	nsk = g_io_channel_unix_get_fd(session->io);
-	err = bnep_connadd(nsk, dst_role, devname);
-	if (err < 0)
-		return err;
-
-	info("Added new connection: %s", devname);
-
-	if (bnep_add_to_bridge(devname, ns->bridge) < 0) {
-		error("Can't add %s to the bridge %s: %s(%d)",
-				devname, ns->bridge, strerror(errno), errno);
-		return -EPERM;
-	}
-
-	bnep_if_up(devname);
-
-	strncpy(session->dev, devname, sizeof(devname));
-
-	ns->sessions = g_slist_append(ns->sessions, session);
-
-	return 0;
-}
-
 static void session_free(void *data)
 {
 	struct network_session *session = data;
@@ -377,7 +348,8 @@ static gboolean bnep_setup(GIOChannel *chan,
 		goto reply;
 	}
 
-	if (server_connadd(ns, na->setup, dst_role) < 0)
+	if (bnep_server_add(sk, dst_role, ns->bridge, na->setup->dev,
+							&na->setup->dst) < 0)
 		goto reply;
 
 	na->setup = NULL;
@@ -524,10 +496,7 @@ static void server_remove_sessions(struct network_server *ns)
 		if (*session->dev == '\0')
 			continue;
 
-		bnep_del_from_bridge(session->dev, ns->bridge);
-		bnep_if_down(session->dev);
-
-		bnep_conndel(&session->dst);
+		bnep_server_delete(ns->bridge, session->dev, &session->dst);
 	}
 
 	g_slist_free_full(ns->sessions, session_free);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v3 3/5] bnep: Refactored bnep connect and disconnect calls
From: Ravi kumar Veeramally @ 2013-12-17 14:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387289872-23408-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Refactored bnep connect and disconnect calls to simply and
keeping bnep related functionality behind curtains.
Provided bnep_conn struct globally. bnep_connect calls takes
care of bnep_setup until interface up then connect callback
will be called, disconnect_cb is registered as watchdog and it
will triggered by remote device on disconnect or any other
I/O error. bnep_disconnect should be called only when iface is
up/connected.
---
 android/pan.c                 | 51 ++++++----------------
 profiles/network/bnep.c       | 99 ++++++++++++++++++++++++++++---------------
 profiles/network/bnep.h       | 10 ++---
 profiles/network/connection.c | 43 +++++++++++--------
 4 files changed, 108 insertions(+), 95 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index ec589cf..a647d95 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -54,7 +54,7 @@ struct pan_device {
 	uint8_t		conn_state;
 	uint8_t		role;
 	GIOChannel	*io;
-	guint		watch;
+	struct bnep_conn *bnep;
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -105,38 +105,31 @@ static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
 
 static void destroy_pan_device(struct pan_device *dev)
 {
-	local_role = HAL_PAN_ROLE_NONE;
-
-	if (dev->watch > 0) {
-		g_source_remove(dev->watch);
-		dev->watch = 0;
-	}
-
 	if (dev->io) {
+		g_io_channel_shutdown(dev->io, TRUE, NULL);
 		g_io_channel_unref(dev->io);
 		dev->io = NULL;
 	}
 
+	if (dev->conn_state == HAL_PAN_STATE_CONNECTED)
+		bnep_disconnect(dev->bnep);
+
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+	bnep_free(dev->bnep);
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
 }
 
-static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
-								gpointer data)
+static void bnep_disconn_cb(void *data)
 {
 	struct pan_device *dev = data;
 
 	DBG("%s disconnected", dev->iface);
 
-	bnep_if_down(dev->iface);
-	bnep_conndel(&dev->dst);
 	destroy_pan_device(dev);
-
-	return FALSE;
 }
 
-static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+static void bnep_conn_cb(char *iface, int err, void *data)
 {
 	struct pan_device *dev = data;
 
@@ -144,22 +137,15 @@ static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
 
 	if (err < 0) {
 		error("bnep connect req failed: %s", strerror(-err));
-		bnep_conndel(&dev->dst);
 		destroy_pan_device(dev);
 		return;
 	}
 
-	memcpy(dev->iface, iface, sizeof(dev->iface));
-
-	DBG("%s connected", dev->iface);
+	DBG("%s connected", iface);
 
+	memcpy(dev->iface, iface, sizeof(dev->iface));
 	bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
-
-	dev->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-							bnep_watchdog_cb, dev);
-	g_io_channel_unref(dev->io);
-	dev->io = NULL;
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
@@ -179,7 +165,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 	dst = (dev->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
 	sk = g_io_channel_unix_get_fd(dev->io);
 
-	perr = bnep_connect(sk, src, dst, bnep_conn_cb, dev);
+	dev->bnep = bnep_new(src, dst);
+	perr = bnep_connect(dev->bnep, sk, bnep_conn_cb, bnep_disconn_cb, dev);
 	if (perr < 0) {
 		error("bnep connect req failed: %s", strerror(-perr));
 		goto fail;
@@ -267,7 +254,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_disconnect *cmd = buf;
 	struct pan_device *dev;
-	uint8_t status;
+	uint8_t status = HAL_STATUS_FAILED;
 	GSList *l;
 	bdaddr_t dst;
 
@@ -276,20 +263,10 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 	android2bdaddr(&cmd->bdaddr, &dst);
 
 	l = g_slist_find_custom(devices, &dst, device_cmp);
-	if (!l) {
-		status = HAL_STATUS_FAILED;
+	if (!l)
 		goto failed;
-	}
 
 	dev = l->data;
-
-	if (dev->watch) {
-		g_source_remove(dev->watch);
-		dev->watch = 0;
-	}
-
-	bnep_if_down(dev->iface);
-	bnep_conndel(&dst);
 	destroy_pan_device(dev);
 	status = HAL_STATUS_SUCCESS;
 
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 4c2fb1a..6416535 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -39,6 +39,7 @@
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/bnep.h>
+#include <btio/btio.h>
 
 #include <glib.h>
 
@@ -71,25 +72,16 @@ struct bnep_conn {
 	GIOChannel	*io;
 	uint16_t	src;
 	uint16_t	dst;
+	bdaddr_t	dst_addr;
+	char	iface[16];
 	guint	attempts;
 	guint	setup_to;
 	void	*data;
 	bnep_connect_cb	conn_cb;
+	bnep_disconnect_cb disconn_cb;
+	int watch;
 };
 
-static void free_bnep_connect(struct bnep_conn *bc)
-{
-	if (!bc)
-		return;
-
-	if (bc->io) {
-		g_io_channel_unref(bc->io);
-		bc->io = NULL;
-	}
-
-	g_free(bc);
-}
-
 uint16_t bnep_service_id(const char *svc)
 {
 	int i;
@@ -270,6 +262,16 @@ void bnep_free(struct bnep_conn *bc)
 	g_free(bc);
 }
 
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct bnep_conn *bc = data;
+
+	bc->disconn_cb(bc->data);
+
+	return FALSE;
+}
+
 static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 								gpointer data)
 {
@@ -277,12 +279,11 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 	struct bnep_control_rsp *rsp;
 	struct timeval timeo;
 	char pkt[BNEP_MTU];
-	char iface[16];
 	ssize_t r;
 	int sk;
 
 	if (cond & G_IO_NVAL)
-		goto failed;
+		return FALSE;
 
 	if (bc->setup_to > 0) {
 		g_source_remove(bc->setup_to);
@@ -334,24 +335,28 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
 
 	sk = g_io_channel_unix_get_fd(bc->io);
-	if (bnep_connadd(sk, bc->src, iface)) {
+	if (bnep_connadd(sk, bc->src, bc->iface)) {
 		error("bnep conn could not be added");
 		goto failed;
 	}
 
-	if (bnep_if_up(iface)) {
-		error("could not up %s", iface);
+	if (bnep_if_up(bc->iface)) {
+		bnep_conndel(&bc->dst_addr);
+		error("could not up %s", bc->iface);
 		goto failed;
 	}
 
-	bc->conn_cb(chan, iface, 0, bc->data);
-	free_bnep_connect(bc);
+	bc->watch = g_io_add_watch(bc->io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+							bnep_watchdog_cb, bc);
+	g_io_channel_unref(bc->io);
+	bc->io = NULL;
+
+	bc->conn_cb(bc->iface, 0, bc->data);
 
 	return FALSE;
 
 failed:
-	bc->conn_cb(NULL, NULL, -EIO, bc->data);
-	free_bnep_connect(bc);
+	bc->conn_cb(NULL, -EIO, bc->data);
 
 	return FALSE;
 }
@@ -395,40 +400,64 @@ static gboolean bnep_conn_req_to(gpointer user_data)
 			return TRUE;
 	}
 
-	bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
-	free_bnep_connect(bc);
+	bc->conn_cb(NULL, -ETIMEDOUT, bc->data);
 
 	return FALSE;
 }
 
-int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
-								void *data)
+int bnep_connect(struct bnep_conn *bc, int sk, bnep_connect_cb conn_cb,
+				bnep_disconnect_cb disconn_cb, void *data)
 {
-	struct bnep_conn *bc;
+	GError *gerr = NULL;
 	int err;
 
-	if (!conn_cb)
+	if (!bc || !conn_cb || !disconn_cb)
 		return -EINVAL;
 
-	bc = g_new0(struct bnep_conn, 1);
 	bc->io = g_io_channel_unix_new(sk);
-	bc->attempts = 0;
-	bc->src = src;
-	bc->dst = dst;
-	bc->conn_cb = conn_cb;
 	bc->data = data;
+	bc->conn_cb = conn_cb;
+	bc->disconn_cb = disconn_cb;
+
+	bt_io_get(bc->io, &gerr, BT_IO_OPT_DEST_BDADDR, &bc->dst_addr,
+							BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return -EINVAL;
+	}
 
 	err = bnep_setup_conn_req(bc);
 	if (err < 0)
 		return err;
 
 	bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
-							bnep_conn_req_to, bc);
-	g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+						bnep_conn_req_to, bc);
+	bc->watch = g_io_add_watch(bc->io,
+				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 							bnep_setup_cb, bc);
 	return 0;
 }
 
+void bnep_disconnect(struct bnep_conn *bc)
+{
+	if (!bc)
+		return;
+
+	if (bc->io) {
+		g_io_channel_unref(bc->io);
+		bc->io = NULL;
+	}
+
+	if (bc->watch) {
+		g_source_remove(bc->watch);
+		bc->watch = 0;
+	}
+
+	bnep_if_down(bc->iface);
+	bnep_conndel(&bc->dst_addr);
+}
+
 int bnep_add_to_bridge(const char *devname, const char *bridge)
 {
 	int ifindex;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index a42309c..6e385e4 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -32,6 +32,11 @@ const char *bnep_name(uint16_t id);
 
 struct bnep_conn *bnep_new(uint16_t src, uint16_t dst);
 void bnep_free(struct bnep_conn *bnep);
+typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
+typedef void (*bnep_disconnect_cb) (void *data);
+int bnep_connect(struct bnep_conn *bnep, int sk, bnep_connect_cb conn_cb,
+				bnep_disconnect_cb disconn_cb, void *data);
+void bnep_disconnect(struct bnep_conn *bnep);
 int bnep_connadd(int sk, uint16_t role, char *dev);
 int bnep_conndel(const bdaddr_t *dst);
 int bnep_if_up(const char *devname);
@@ -39,11 +44,6 @@ int bnep_if_down(const char *devname);
 int bnep_add_to_bridge(const char *devname, const char *bridge);
 int bnep_del_from_bridge(const char *devname, const char *bridge);
 
-typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
-								void *data);
-int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
-								void *data);
-
 ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp);
 uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role);
 uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index fb3e1ce..0fdac17 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -72,6 +72,7 @@ struct network_conn {
 	guint		dc_id;
 	struct network_peer *peer;
 	DBusMessage	*connect;
+	struct bnep_conn *bnep;
 };
 
 static GSList *peers = NULL;
@@ -106,8 +107,7 @@ static struct network_conn *find_connection_by_state(GSList *list,
 	return NULL;
 }
 
-static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
-				gpointer data)
+static void bnep_disconn_cb(void *data)
 {
 	struct network_conn *nc = data;
 	DBusConnection *conn = btd_get_dbus_connection();
@@ -126,12 +126,18 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
 
 	info("%s disconnected", nc->dev);
 
-	bnep_if_down(nc->dev);
 	nc->state = DISCONNECTED;
 	memset(nc->dev, 0, sizeof(nc->dev));
 	strcpy(nc->dev, "bnep%d");
 
-	return FALSE;
+	bnep_free(nc->bnep);
+	nc->bnep = NULL;
+
+	if (nc->io) {
+		g_io_channel_shutdown(nc->io, TRUE, NULL);
+		g_io_channel_unref(nc->io);
+		nc->io = NULL;
+	}
 }
 
 static void local_connect_cb(struct network_conn *nc, int err)
@@ -158,9 +164,17 @@ static void cancel_connection(struct network_conn *nc, int err)
 	if (nc->connect)
 		local_connect_cb(nc, err);
 
-	g_io_channel_shutdown(nc->io, TRUE, NULL);
-	g_io_channel_unref(nc->io);
-	nc->io = NULL;
+	if (nc->io) {
+		g_io_channel_shutdown(nc->io, TRUE, NULL);
+		g_io_channel_unref(nc->io);
+		nc->io = NULL;
+	}
+
+	if (nc->state == CONNECTED)
+		bnep_disconnect(nc->bnep);
+
+	bnep_free(nc->bnep);
+	nc->bnep = NULL;
 
 	nc->state = DISCONNECTED;
 }
@@ -169,11 +183,7 @@ static void connection_destroy(DBusConnection *conn, void *user_data)
 {
 	struct network_conn *nc = user_data;
 
-	if (nc->state == CONNECTED) {
-		bnep_if_down(nc->dev);
-		bnep_conndel(device_get_address(nc->peer->device));
-	} else if (nc->io)
-		cancel_connection(nc, -EIO);
+	cancel_connection(nc, -EIO);
 }
 
 static void disconnect_cb(struct btd_device *device, gboolean removal,
@@ -186,7 +196,7 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
 	connection_destroy(NULL, user_data);
 }
 
-static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+static void bnep_conn_cb(char *iface, int err, void *data)
 {
 	struct network_conn *nc = data;
 	const char *path;
@@ -220,10 +230,6 @@ static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
 	nc->state = CONNECTED;
 	nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
 								nc, NULL);
-	g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-							bnep_watchdog_cb, nc);
-	g_io_channel_unref(nc->io);
-	nc->io = NULL;
 
 	return;
 
@@ -242,7 +248,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 	}
 
 	sk = g_io_channel_unix_get_fd(nc->io);
-	perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
+	nc->bnep = bnep_new(BNEP_SVC_PANU, nc->id);
+	perr = bnep_connect(nc->bnep, sk, bnep_conn_cb, bnep_disconn_cb, nc);
 	if (perr < 0) {
 		error("bnep connect(): %s (%d)", strerror(-perr), -perr);
 		goto failed;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v3 2/5] bnep: Add bnep_new and bnep_free api's
From: Ravi kumar Veeramally @ 2013-12-17 14:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1387289872-23408-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Refacoring connect and disconnect mechanisms. It would be more
convinient for caller to maintain just bnep connection reference
and delete whenever it is not required.
---
 profiles/network/bnep.c | 24 ++++++++++++++++++++++++
 profiles/network/bnep.h |  4 ++++
 2 files changed, 28 insertions(+)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 08037e6..4c2fb1a 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -246,6 +246,30 @@ int bnep_if_down(const char *devname)
 	return 0;
 }
 
+struct bnep_conn *bnep_new(uint16_t src, uint16_t dst)
+{
+	struct bnep_conn *bc;
+
+	bc = g_new0(struct bnep_conn, 1);
+	bc->src = src;
+	bc->dst = dst;
+
+	return bc;
+}
+
+void bnep_free(struct bnep_conn *bc)
+{
+	if (!bc)
+		return;
+
+	if (bc->io) {
+		g_io_channel_unref(bc->io);
+		bc->io = NULL;
+	}
+
+	g_free(bc);
+}
+
 static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
 								gpointer data)
 {
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index dd22c40..a42309c 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -21,6 +21,8 @@
  *
  */
 
+struct bnep_conn;
+
 int bnep_init(void);
 int bnep_cleanup(void);
 
@@ -28,6 +30,8 @@ uint16_t bnep_service_id(const char *svc);
 const char *bnep_uuid(uint16_t id);
 const char *bnep_name(uint16_t id);
 
+struct bnep_conn *bnep_new(uint16_t src, uint16_t dst);
+void bnep_free(struct bnep_conn *bnep);
 int bnep_connadd(int sk, uint16_t role, char *dev);
 int bnep_conndel(const bdaddr_t *dst);
 int bnep_if_up(const char *devname);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v3 1/5] android/pan: Rename pan_device_free to destroy_pan_device
From: Ravi kumar Veeramally @ 2013-12-17 14:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Renaming function name because it does more than freeing memory.
Also moving disconnect notification call to destory_pan_device
reduce redundancy.
---
 android/pan.c | 51 +++++++++++++++++++++++----------------------------
 1 file changed, 23 insertions(+), 28 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index e410f54..ec589cf 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -65,24 +65,6 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 	return bacmp(&dev->dst, dst);
 }
 
-static void pan_device_free(struct pan_device *dev)
-{
-	local_role = HAL_PAN_ROLE_NONE;
-
-	if (dev->watch > 0) {
-		g_source_remove(dev->watch);
-		dev->watch = 0;
-	}
-
-	if (dev->io) {
-		g_io_channel_unref(dev->io);
-		dev->io = NULL;
-	}
-
-	devices = g_slist_remove(devices, dev);
-	g_free(dev);
-}
-
 static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
 {
 	struct hal_ev_pan_conn_state ev;
@@ -121,6 +103,25 @@ static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
 									&ev);
 }
 
+static void destroy_pan_device(struct pan_device *dev)
+{
+	local_role = HAL_PAN_ROLE_NONE;
+
+	if (dev->watch > 0) {
+		g_source_remove(dev->watch);
+		dev->watch = 0;
+	}
+
+	if (dev->io) {
+		g_io_channel_unref(dev->io);
+		dev->io = NULL;
+	}
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+	devices = g_slist_remove(devices, dev);
+	g_free(dev);
+}
+
 static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
 								gpointer data)
 {
@@ -130,8 +131,7 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
 
 	bnep_if_down(dev->iface);
 	bnep_conndel(&dev->dst);
-	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-	pan_device_free(dev);
+	destroy_pan_device(dev);
 
 	return FALSE;
 }
@@ -145,8 +145,7 @@ static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
 	if (err < 0) {
 		error("bnep connect req failed: %s", strerror(-err));
 		bnep_conndel(&dev->dst);
-		bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-		pan_device_free(dev);
+		destroy_pan_device(dev);
 		return;
 	}
 
@@ -189,8 +188,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 	return;
 
 fail:
-	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-	pan_device_free(dev);
+	destroy_pan_device(dev);
 }
 
 static void bt_pan_connect(const void *buf, uint16_t len)
@@ -292,10 +290,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 
 	bnep_if_down(dev->iface);
 	bnep_conndel(&dst);
-
-	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
-	pan_device_free(dev);
-
+	destroy_pan_device(dev);
 	status = HAL_STATUS_SUCCESS;
 
 failed:
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH] android/tester: Fix not returning in failure
From: Andrei Emeltchenko @ 2013-12-17 14:17 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/android-tester.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 2a8c8d0..c193921 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -851,8 +851,10 @@ static void setup_socket_interface(const void *test_data)
 	setup(data);
 
 	sock = data->if_bluetooth->get_profile_interface(BT_PROFILE_SOCKETS_ID);
-	if (!sock)
+	if (!sock) {
 		tester_setup_failed();
+		return;
+	}
 
 	data->if_sock = sock;
 
-- 
1.8.3.2


^ permalink raw reply related

* Re: [RFC v4 05/12] Bluetooth: Stop scanning on LE connection
From: Andre Guedes @ 2013-12-17 14:05 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <20131210132131.GA10392@x220.p-661hnu-f1>

Hi Johan,

Sorry the delay to reply, I was out of the office last week.

On Tue, 2013-12-10 at 15:21 +0200, Johan Hedberg wrote:
> Hi Andre,
> 
> On Fri, Dec 06, 2013, Andre Guedes wrote:
> > Some LE controllers don't support scanning and creating a connection
> > at the same time. So we should always stop scanning in order to
> > establish the connection.
> > 
> > Since we may prematurely stop the discovery procedure in favor of
> > the connection establishment, we should also cancel hdev->le_scan_
> > disable delayed work and set the discovery state to DISCOVERY_STOPPED.
> > 
> > This change does a small improvement since it is not mandatory the
> > user stops scanning before connecting anymore. Moreover, this change
> > is required by upcoming LE auto connection mechanism in order to work
> > properly with controllers that don't support background scanning and
> > connection establishment at the same time.
> > 
> > In future, we might want to do a small optimization by checking if
> > controller is able to scan and connect at the same time. For now,
> > we want the simplest approach so we always stop scanning (even if
> > the controller is able to carry out both operations).
> > 
> > Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> > ---
> >  net/bluetooth/hci_conn.c | 23 ++++++++++++++++++++++-
> >  1 file changed, 22 insertions(+), 1 deletion(-)
> > 
> > diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> > index b5c3ebff..750a39d 100644
> > --- a/net/bluetooth/hci_conn.c
> > +++ b/net/bluetooth/hci_conn.c
> > @@ -518,8 +518,17 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
> >  {
> >  	struct hci_conn *conn;
> >  
> > -	if (status == 0)
> > +	if (status == 0) {
> > +		/* If the discovery procedure was running, we prematurely
> > +		 * stopped it. So we have to change the discovery state.
> > +		 */
> > +		if (hdev->discovery.state == DISCOVERY_FINDING) {
> > +			cancel_delayed_work(&hdev->le_scan_disable);
> > +			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
> > +		}
> > +
> >  		return;
> > +	}
> >  
> >  	BT_ERR("HCI request failed to create LE connection: status 0x%2.2x",
> >  	       status);
> > @@ -552,6 +561,18 @@ static int hci_create_le_conn(struct hci_conn *conn)
> >  
> >  	hci_req_init(&req, hdev);
> >  
> > +	/* If controller is scanning, we stop it since some controllers are
> > +	 * not able to scan and connect at the same time.
> > +	 */
> > +	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
> > +		struct hci_cp_le_set_scan_enable enable_cp;
> > +
> > +		memset(&enable_cp, 0, sizeof(enable_cp));
> > +		enable_cp.enable = LE_SCAN_DISABLE;
> > +		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
> > +			    &enable_cp);
> > +	}
> > +
> >  	memset(&cp, 0, sizeof(cp));
> >  	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
> >  	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
> 
> The way this all hangs together with a discovery process started through
> mgmt_start_discovery feels a bit flimsy to me. Particularly, have you
> ensured that everything is fine if you've got inquiry ongoing when you
> do hci_discovery_set_state(hdev, DISCOVERY_STOPPED). Also, are there any
> risks of race conditions here, e.g. is it fine to let the
> cancel_delayed_work() call be in create_le_conn_complete() instead of
> doing it in hci_create_le_conn()?

Yes, I did lots of testing, including the inquiry test you mentioned,
and I didn't find any issues.

I failed to see any race conditons since cancel_delayed_work() does not
block. So it is fine to call cancel_delayed_work() in
create_le_conn_complete() as well as in hci_create_le_conn().

> What also makes this hard to track is that the condition you're testing
> for first is the HCI_LE_SCAN bit, but then later you look at
> discovery.state == DISCOVERY_FINDING. For the casual reader there's no
> direct indication of how these two are releated for the various types of
> discovery that are possible (LE-only, BR/EDR-only and interleaved).

Yes, I see your point. However, we can't check HCI_LE_SCAN in
create_le_conn_complete() because the flag was already cleared in
hci_cc_le_set_scan_enable().

> I don't mean to say that this is a nack for the patch, but I'd like to
> know that you've considered and tested this kind of cases. I had to
> spend quite some time looking through the existing code and this patch
> and still couldn't arrive at absolute confidence of its correctness,
> meaning there should hopefully be some room for simplification.

So I think we can do some simplification by moving this discovery
handling from create_le_conn_complete() to hci_create_le_conn(), at
least I think this code will become a bit easier to follow. What do you
think?

Regards,

Andre


^ permalink raw reply

* Re: [PATCH 1/7] android/tester: Fix enum and define coding style
From: Luiz Augusto von Dentz @ 2013-12-17 13:34 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1387283874-29721-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Tue, Dec 17, 2013 at 2:37 PM, Grzegorz Kolodziejczyk
<grzegorz.kolodziejczyk@tieto.com> wrote:
> This changes all enums values and defines to uppercase instead of
> lowercase according to coding style.
> ---
>  android/android-tester.c | 86 ++++++++++++++++++++++++------------------------
>  1 file changed, 43 insertions(+), 43 deletions(-)
>
> diff --git a/android/android-tester.c b/android/android-tester.c
> index eb938d0..4eb265b 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -37,10 +37,10 @@
>  #include <hardware/bluetooth.h>
>  #include <hardware/bt_sock.h>
>
> -#define adapter_props adapter_prop_bdaddr, adapter_prop_bdname, \
> -                       adapter_prop_uuids, adapter_prop_cod, \
> -                       adapter_prop_type, adapter_prop_scan_mode, \
> -                       adapter_prop_bonded_devices, adapter_prop_disc_timeout
> +#define ADAPTER_PROPS ADAPTER_PROP_BDADDR, ADAPTER_PROP_BDNAME, \
> +                       ADAPTER_PROP_UUIDS, ADAPTER_PROP_COD, \
> +                       ADAPTER_PROP_TYPE, ADAPTER_PROP_SCAN_MODE, \
> +                       ADAPTER_PROP_BONDED_DEVICES, ADAPTER_PROP_DISC_TIMEOUT
>
>  static bt_scan_mode_t test_setprop_scanmode_val =
>                                         BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
> @@ -52,19 +52,19 @@ static uint32_t test_setprop_disctimeout_val = 120;
>   */
>
>  enum hal_bluetooth_callbacks_id {
> -       adapter_test_end,
> -       adapter_test_setup_mode,
> -       adapter_state_changed_on,
> -       adapter_state_changed_off,
> -       adapter_prop_bdaddr,
> -       adapter_prop_bdname,
> -       adapter_prop_uuids,
> -       adapter_prop_cod,
> -       adapter_prop_type,
> -       adapter_prop_scan_mode,
> -       adapter_prop_disc_timeout,
> -       adapter_prop_service_record,
> -       adapter_prop_bonded_devices
> +       ADAPTER_TEST_END,
> +       ADAPTER_TEST_SETUP_MODE,
> +       ADAPTER_STATE_CHANGED_ON,
> +       ADAPTER_STATE_CHANGED_OFF,
> +       ADAPTER_PROP_BDADDR,
> +       ADAPTER_PROP_BDNAME,
> +       ADAPTER_PROP_UUIDS,
> +       ADAPTER_PROP_COD,
> +       ADAPTER_PROP_TYPE,
> +       ADAPTER_PROP_SCAN_MODE,
> +       ADAPTER_PROP_DISC_TIMEOUT,
> +       ADAPTER_PROP_SERVICE_RECORD,
> +       ADAPTER_PROP_BONDED_DEVICES
>  };

This is something I dislike right now, why are defining these and not
using directly the values defined in hal-msg.h? We should probably
have a struct with expected opcode and value e.g:
.{HAL_EV_ADAPTER_PROPS_CHANGED, BT_STATE_ON} and don't try to invent
another ID for each of those.

Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH v3 bluetooth-next 8/8] 6lowpan: cleanup udp compress function
From: Alexander Aring @ 2013-12-17 13:21 UTC (permalink / raw)
  To: linux-zigbee-devel; +Cc: werner, linux-bluetooth, Alexander Aring
In-Reply-To: <1387286488-29382-1-git-send-email-alex.aring@gmail.com>

This patch remove unnecessary casts and brackets in compress_udp_header
function.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan_iphc.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
index b298bfc..11840f9 100644
--- a/net/ieee802154/6lowpan_iphc.c
+++ b/net/ieee802154/6lowpan_iphc.c
@@ -553,33 +553,43 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
 	    ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
 	     LOWPAN_NHC_UDP_4BIT_PORT)) {
 		pr_debug("UDP header: both ports compression to 4 bits\n");
+		/* compression value */
 		tmp = LOWPAN_NHC_UDP_CS_P_11;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
-		tmp = /* subtraction is faster */
-		   (u8)((ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT) +
-		       ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4));
+		/* source and destination port */
+		tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
+		      ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 	} else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
 			LOWPAN_NHC_UDP_8BIT_PORT) {
 		pr_debug("UDP header: remove 8 bits of dest\n");
+		/* compression value */
 		tmp = LOWPAN_NHC_UDP_CS_P_01;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+		/* source port */
 		lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source));
-		tmp = (u8)(ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT);
+		/* destination port */
+		tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 	} else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
 			LOWPAN_NHC_UDP_8BIT_PORT) {
 		pr_debug("UDP header: remove 8 bits of source\n");
+		/* compression value */
 		tmp = LOWPAN_NHC_UDP_CS_P_10;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
-		tmp = (u8)(ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT);
+		/* source port */
+		tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+		/* destination port */
 		lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest));
 	} else {
 		pr_debug("UDP header: can't compress\n");
+		/* compression value */
 		tmp = LOWPAN_NHC_UDP_CS_P_00;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
+		/* source port */
 		lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source));
+		/* destination port */
 		lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest));
 	}
 
-- 
1.8.5.1


^ permalink raw reply related

* [PATCH v3 bluetooth-next 7/8] 6lowpan: udp use subtraction on both conditions
From: Alexander Aring @ 2013-12-17 13:21 UTC (permalink / raw)
  To: linux-zigbee-devel; +Cc: werner, linux-bluetooth, Alexander Aring
In-Reply-To: <1387286488-29382-1-git-send-email-alex.aring@gmail.com>

Cleanup code to handle both calculation in the same way.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan_iphc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
index 8857285..b298bfc 100644
--- a/net/ieee802154/6lowpan_iphc.c
+++ b/net/ieee802154/6lowpan_iphc.c
@@ -557,7 +557,7 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 		tmp = /* subtraction is faster */
 		   (u8)((ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT) +
-		       ((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
+		       ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4));
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 	} else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
 			LOWPAN_NHC_UDP_8BIT_PORT) {
-- 
1.8.5.1


^ permalink raw reply related

* [PATCH v3 bluetooth-next 6/8] 6lowpan: udp use lowpan_fetch_skb function
From: Alexander Aring @ 2013-12-17 13:21 UTC (permalink / raw)
  To: linux-zigbee-devel; +Cc: werner, linux-bluetooth, Alexander Aring
In-Reply-To: <1387286488-29382-1-git-send-email-alex.aring@gmail.com>

Cleanup the lowpan_uncompress_udp_header function to use the
lowpan_fetch_skb function.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan_iphc.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
index a70fa66..8857285 100644
--- a/net/ieee802154/6lowpan_iphc.c
+++ b/net/ieee802154/6lowpan_iphc.c
@@ -265,40 +265,37 @@ lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
 static int
 uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 {
-	u8 tmp;
+	bool fail;
+	u8 tmp = 0, val = 0;
 
 	if (!uh)
 		goto err;
 
-	if (lowpan_fetch_skb_u8(skb, &tmp))
-		goto err;
+	fail = lowpan_fetch_skb(skb, &tmp, 1);
 
 	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);
+			fail |= lowpan_fetch_skb(skb, &uh->source, 2);
+			fail |= lowpan_fetch_skb(skb, &uh->dest, 2);
 			break;
 		case LOWPAN_NHC_UDP_CS_P_01:
-			memcpy(&uh->source, &skb->data[0], 2);
-			uh->dest = htons(skb->data[2] +
-					 LOWPAN_NHC_UDP_8BIT_PORT);
-			skb_pull(skb, 3);
+			fail |= lowpan_fetch_skb(skb, &uh->source, 2);
+			fail |= lowpan_fetch_skb(skb, &val, 1);
+			uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
 			break;
 		case LOWPAN_NHC_UDP_CS_P_10:
-			uh->source = htons(skb->data[0] +
-					   LOWPAN_NHC_UDP_8BIT_PORT);
-			memcpy(&uh->dest, &skb->data[1], 2);
-			skb_pull(skb, 3);
+			fail |= lowpan_fetch_skb(skb, &val, 1);
+			uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
+			fail |= lowpan_fetch_skb(skb, &uh->dest, 2);
 			break;
 		case LOWPAN_NHC_UDP_CS_P_11:
+			fail |= lowpan_fetch_skb(skb, &val, 1);
 			uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
-					   (skb->data[0] >> 4));
+					   (val >> 4));
 			uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
-					 (skb->data[0] & 0x0f));
-			skb_pull(skb, 1);
+					 (val & 0x0f));
 			break;
 		default:
 			pr_debug("ERROR: unknown UDP format\n");
@@ -314,8 +311,7 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 			pr_debug_ratelimited("checksum elided currently not supported\n");
 			goto err;
 		} else {
-			memcpy(&uh->check, &skb->data[0], 2);
-			skb_pull(skb, 2);
+			fail |= lowpan_fetch_skb(skb, &uh->check, 2);
 		}
 
 		/*
@@ -330,6 +326,9 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 		goto err;
 	}
 
+	if (fail)
+		goto err;
+
 	return 0;
 err:
 	return -EINVAL;
-- 
1.8.5.1


^ permalink raw reply related

* [PATCH v3 bluetooth-next 5/8] 6lowpan: add udp warning for elided checksum
From: Alexander Aring @ 2013-12-17 13:21 UTC (permalink / raw)
  To: linux-zigbee-devel; +Cc: werner, linux-bluetooth, Alexander Aring
In-Reply-To: <1387286488-29382-1-git-send-email-alex.aring@gmail.com>

Bit 5 of "UDP LOWPAN_NHC Format" indicate that the checksum can be
elided.
The host need to calculate the udp checksum afterwards but this isn't
supported right now.

See:
http://tools.ietf.org/html/rfc6282#section-4.3.3
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan.h      |  1 +
 net/ieee802154/6lowpan_iphc.c | 11 ++++++++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index 4981bf8..2b835db 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -231,6 +231,7 @@
 #define LOWPAN_NHC_UDP_CS_P_10	0xF2 /* source = 0xF0 + 8bit inline,
 					dest = 16 bit inline */
 #define LOWPAN_NHC_UDP_CS_P_11	0xF3 /* source & dest = 0xF0B + 4bit inline */
+#define LOWPAN_NHC_UDP_CS_C	0x04 /* checksum elided */
 
 #ifdef DEBUG
 /* print data in line */
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
index 02bf74d..a70fa66 100644
--- a/net/ieee802154/6lowpan_iphc.c
+++ b/net/ieee802154/6lowpan_iphc.c
@@ -309,9 +309,14 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 		pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
 			 ntohs(uh->source), ntohs(uh->dest));
 
-		/* copy checksum */
-		memcpy(&uh->check, &skb->data[0], 2);
-		skb_pull(skb, 2);
+		/* checksum */
+		if (tmp & LOWPAN_NHC_UDP_CS_C) {
+			pr_debug_ratelimited("checksum elided currently not supported\n");
+			goto err;
+		} else {
+			memcpy(&uh->check, &skb->data[0], 2);
+			skb_pull(skb, 2);
+		}
 
 		/*
 		 * UDP lenght needs to be infered from the lower layers
-- 
1.8.5.1


^ permalink raw reply related

* [PATCH v3 bluetooth-next 4/8] 6lowpan: fix udp byte ordering
From: Alexander Aring @ 2013-12-17 13:21 UTC (permalink / raw)
  To: linux-zigbee-devel; +Cc: werner, linux-bluetooth, Alexander Aring
In-Reply-To: <1387286488-29382-1-git-send-email-alex.aring@gmail.com>

The incoming udp header in lowpan_compress_udp_header function is
already in network byte order.

Everytime we read this values for source and destination port we need
to convert this value to host byte order.

In the outcoming header we need to set this value in network byte order
which the upcoming process assumes.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 net/ieee802154/6lowpan_iphc.c | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
index 1933f5b..02bf74d 100644
--- a/net/ieee802154/6lowpan_iphc.c
+++ b/net/ieee802154/6lowpan_iphc.c
@@ -283,20 +283,21 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 			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;
+			uh->dest = htons(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;
+			uh->source = htons(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);
+			uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
+					   (skb->data[0] >> 4));
+			uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
+					 (skb->data[0] & 0x0f));
 			skb_pull(skb, 1);
 			break;
 		default:
@@ -306,7 +307,7 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 		}
 
 		pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
-			 uh->source, uh->dest);
+			 ntohs(uh->source), ntohs(uh->dest));
 
 		/* copy checksum */
 		memcpy(&uh->check, &skb->data[0], 2);
@@ -318,7 +319,7 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 		 * frame
 		 */
 		uh->len = htons(skb->len + sizeof(struct udphdr));
-		pr_debug("uncompressed UDP length: src = %d", uh->len);
+		pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len));
 	} else {
 		pr_debug("ERROR: unsupported NH format\n");
 		goto err;
@@ -543,31 +544,31 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
 	struct udphdr *uh = udp_hdr(skb);
 	u8 tmp;
 
-	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)) {
+	if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
+	     LOWPAN_NHC_UDP_4BIT_PORT) &&
+	    ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
+	     LOWPAN_NHC_UDP_4BIT_PORT)) {
 		pr_debug("UDP header: both ports compression to 4 bits\n");
 		tmp = LOWPAN_NHC_UDP_CS_P_11;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 		tmp = /* subtraction is faster */
-		   (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
-		       ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
+		   (u8)((ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT) +
+		       ((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
-	} else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
+	} else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
 			LOWPAN_NHC_UDP_8BIT_PORT) {
 		pr_debug("UDP header: remove 8 bits of dest\n");
 		tmp = LOWPAN_NHC_UDP_CS_P_01;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 		lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source));
-		tmp = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
+		tmp = (u8)(ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT);
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
-	} else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
+	} else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
 			LOWPAN_NHC_UDP_8BIT_PORT) {
 		pr_debug("UDP header: remove 8 bits of source\n");
 		tmp = LOWPAN_NHC_UDP_CS_P_10;
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
-		tmp = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
+		tmp = (u8)(ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT);
 		lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp));
 		lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest));
 	} else {
-- 
1.8.5.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox