Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH 2/4] emulator: Add data handler for l2cap connections
From: Marcin Kraglak @ 2013-12-18  8:56 UTC (permalink / raw)
  To: Marcin, linux-bluetooth@vger.kernel.org development
In-Reply-To: <20131218084056.GH12649@x220.p-661hnu-f1>

Hi Johan,

On 18 December 2013 09:40, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Marcin,
>
> On Tue, Dec 17, 2013, Marcin wrote:
>> +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;
>> +}
>
> The function is called just "data handler" but it applies to a more
> specific read_data_psm. Should this perhaps be simply called data_psm?
>
>
>> +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);
>> +
>
> The problem with your approach is that it will not be usable for
> protocols that have multiple channels to the same PSM such as AVDTP.
> To cover this I'd suggest you to consider having something like the
> following:
>
> typedef void (*bthost_l2cap_connect_cb) (uint16_t handle, uint16_t cid);
>
> void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
>                                         bthost_l2cap_connect_cb func);
> /* the above could replace the existing bthost_set_server_psm */
>
> void bthost_connect_l2cap(struct bthost *bthost, uint16_t handle, uint16_t psm,
>                                                 bthost_l2cap_connect_cb func);
>
> For sending and receiving data you wouldn't then need any new functions
> but you could use the already existing bthost_add_cid_hook (for
> receiving data) and bthost_send_cid (for sending data).
>
> Thoughts?
>
> Johan

So first is to extend existing method bthost_add_l2cap_server and call
back after connect, and create method bthost_connect_l2cap (instead of
calling bthost_l2cap_req())?

BR
Marcin

^ permalink raw reply

* [PATCH 3/3] android/tester: Enable bthost after device is enabled
From: Andrei Emeltchenko @ 2013-12-18  8:55 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1387356913-32666-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

This puts bthost to connectible mode allowing us to use powered setup
for connect to emulated device.
---
 android/android-tester.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 423dd6a..736cd70 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -33,10 +33,15 @@
 #include "src/shared/mgmt.h"
 #include "src/shared/hciemu.h"
 
+#include "emulator/bthost.h"
+#include "monitor/bt.h"
+
 #include <hardware/hardware.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
 
+#include "utils.h"
+
 #define ADAPTER_PROPS ADAPTER_PROP_BDADDR, ADAPTER_PROP_BDNAME, \
 			ADAPTER_PROP_UUIDS, ADAPTER_PROP_COD, \
 			ADAPTER_PROP_TYPE, ADAPTER_PROP_SCAN_MODE, \
@@ -466,12 +471,48 @@ failed:
 		close(fd);
 }
 
+static void emu_connectable_complete(uint16_t opcode, uint8_t status,
+					const void *param, uint8_t len,
+					void *user_data)
+{
+	switch (opcode) {
+	case BT_HCI_CMD_WRITE_SCAN_ENABLE:
+	case BT_HCI_CMD_LE_SET_ADV_ENABLE:
+		break;
+	default:
+		return;
+	}
+
+	tester_print("Emulated remote set connectable status 0x%02x", status);
+
+	if (status)
+		tester_setup_failed();
+	else
+		tester_setup_complete();
+}
+
+static void setup_powered_emulated_remote(void)
+{
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost;
+
+	tester_print("Controller powered on");
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_set_cmd_complete_cb(bthost, emu_connectable_complete, data);
+
+	if (data->hciemu_type == HCIEMU_TYPE_LE)
+		bthost_set_adv_enable(bthost, 0x01);
+	else
+		bthost_write_scan_enable(bthost, 0x03);
+}
+
 static void adapter_state_changed_cb(bt_state_t state)
 {
 	switch (state) {
 	case BT_STATE_ON:
 		if (is_empty_halcb_list())
-			tester_setup_complete();
+			setup_powered_emulated_remote();
 		update_hal_cb_list(ADAPTER_STATE_CHANGED_ON);
 		break;
 	case BT_STATE_OFF:
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/3] android/tester: Check return status for enable()
From: Andrei Emeltchenko @ 2013-12-18  8:55 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1387356913-32666-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Use check_expected_status helper for test for returned status in
enable() HAL call.
---
 android/android-tester.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 4a75704..423dd6a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -542,7 +542,8 @@ fail:
 
 static const struct generic_data bluetooth_enable_success_test = {
 	.expected_hal_callbacks = {ADAPTER_PROPS, ADAPTER_STATE_CHANGED_ON,
-							ADAPTER_TEST_END}
+							ADAPTER_TEST_END},
+	.expected_adapter_status = BT_STATUS_SUCCESS
 };
 
 static const struct generic_data bluetooth_enable_done_test = {
@@ -726,10 +727,12 @@ static void teardown(const void *test_data)
 static void test_enable(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	bt_status_t adapter_status;
 
 	init_test_conditions(data);
 
-	data->if_bluetooth->enable();
+	adapter_status = data->if_bluetooth->enable();
+	check_expected_status(adapter_status);
 }
 
 static void test_enable_done(const void *test_data)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 1/3] android/tester: Check status returned from HAL calls
From: Andrei Emeltchenko @ 2013-12-18  8:55 UTC (permalink / raw)
  To: linux-bluetooth

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

In test setup phase check status returned from  enable() call.
---
 android/android-tester.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index bd6fa02..4a75704 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -696,10 +696,13 @@ static void setup_base(const void *test_data)
 static void setup_enabled_adapter(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
+	bt_status_t status;
 
 	setup(data);
 
-	data->if_bluetooth->enable();
+	status = data->if_bluetooth->enable();
+	if (status != BT_STATUS_SUCCESS)
+		tester_setup_failed();
 }
 
 static void teardown(const void *test_data)
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH 6/7] android/tester: Add RSSI set prop fail test case
From: Andrei Emeltchenko @ 2013-12-18  8:46 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk, linux-bluetooth
In-Reply-To: <20131218080034.GD12649@x220.p-661hnu-f1>

On Wed, Dec 18, 2013 at 10:00:34AM +0200, Johan Hedberg wrote:
> 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},

btw: do we need to have space after "{" ?

Best regards 
Andrei Emeltchenko 

> > +	.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
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] android/tester: Fix not returning in failure
From: Johan Hedberg @ 2013-12-18  8:42 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1387289853-8942-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Tue, Dec 17, 2013, Andrei Emeltchenko wrote:
> ---
>  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;

Applied. Thanks.

Johan

^ permalink raw reply

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

Hi Marcin,

On Tue, Dec 17, 2013, Marcin wrote:
> +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;
> +}

The function is called just "data handler" but it applies to a more
specific read_data_psm. Should this perhaps be simply called data_psm?


> +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);
> +

The problem with your approach is that it will not be usable for
protocols that have multiple channels to the same PSM such as AVDTP.
To cover this I'd suggest you to consider having something like the
following:

typedef void (*bthost_l2cap_connect_cb) (uint16_t handle, uint16_t cid);

void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
					bthost_l2cap_connect_cb func);
/* the above could replace the existing bthost_set_server_psm */

void bthost_connect_l2cap(struct bthost *bthost, uint16_t handle, uint16_t psm,
						bthost_l2cap_connect_cb func);

For sending and receiving data you wouldn't then need any new functions
but you could use the already existing bthost_add_cid_hook (for
receiving data) and bthost_send_cid (for sending data).

Thoughts?

Johan

^ permalink raw reply

* 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


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