Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH v4] Bluetooth: Add hci_h4p driver
From: Pavel Machek @ 2014-01-10 14:49 UTC (permalink / raw)
  To: Marcel Holtmann, Pali Rohár,
	Ивайло Димитров,
	Gustavo F. Padovan, Johan Hedberg, linux-kernel,
	linux-bluetooth@vger.kernel.org development, Ville Tervo
In-Reply-To: <20140110134426.GA7235@earth.universe>

Hi!

> You have missed some things. See inline comments below.

Ok, I've done this, it should fix the rest.

diff --git a/drivers/bluetooth/nokia_core.c b/drivers/bluetooth/nokia_core.c
index d6e9b3911..6615939 100644
--- a/drivers/bluetooth/nokia_core.c
+++ b/drivers/bluetooth/nokia_core.c
@@ -1138,8 +1138,8 @@ static int hci_h4p_probe(struct platform_device *pdev)
 	info->uart_iclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_iclk);
 	info->uart_fclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_fclk);
 
-	err = request_irq(info->irq, hci_h4p_interrupt, IRQF_DISABLED, "hci_h4p",
-			  info);
+	err = devm_request_irq(&pdev->dev, info->irq, hci_h4p_interrupt, IRQF_DISABLED,
+			       "hci_h4p", info);
 	if (err < 0) {
 		dev_err(info->dev, "hci_h4p: unable to get IRQ %d\n", info->irq);
 		return err;
@@ -1192,9 +1192,6 @@ static int hci_h4p_remove(struct platform_device *pdev)
 	hci_h4p_hci_close(info->hdev);
 	hci_unregister_dev(info->hdev);
 	hci_free_dev(info->hdev);
-	gpio_free(info->bt_wakeup_gpio);
-	gpio_free(info->host_wakeup_gpio);
-	free_irq(info->irq, (void *) info);
 
 	return 0;
 }



-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply related

* [PATCH v3] android/tester: Multi property check for test case
From: Grzegorz Kolodziejczyk @ 2014-01-10 14:21 UTC (permalink / raw)
  To: linux-bluetooth

This patch allows to check multiple properties for test case. Properties
can be prioritized to allow check if they'll come in right order. Now
properties aren't treated as a "single" callback. In future in one
callback multiple properties can come.
---
 android/android-tester.c | 536 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 392 insertions(+), 144 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 0185f99..6f18e5c 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -43,13 +43,19 @@
 
 #include "utils.h"
 
+struct priority_property {
+	bt_property_t prop;
+	int prio;
+};
+
 struct generic_data {
 	int expected_adapter_status;
 	uint32_t expect_settings_set;
 	int expected_cb_count;
 	bt_property_t set_property;
-	bt_property_t expected_property;
 	bt_callbacks_t expected_hal_cb;
+	struct priority_property *expected_properties;
+	uint8_t expected_properties_num;
 };
 
 struct socket_data {
@@ -91,6 +97,7 @@ struct test_data {
 	bool test_init_done;
 
 	int cb_count;
+	GSList *expected_properties_list;
 };
 
 static char exec_dir[PATH_MAX + 1];
@@ -185,9 +192,18 @@ static void expected_status_init(struct test_data *data)
 static void test_property_init(struct test_data *data)
 {
 	const struct generic_data *test_data = data->test_data;
+	GSList *l = data->expected_properties_list;
+	int i;
 
-	if (!test_data->expected_property.type)
+	if (!test_data->expected_hal_cb.adapter_properties_cb) {
 		data->property_checked = true;
+		return;
+	}
+
+	for (i = 0; i < test_data->expected_properties_num; i++)
+		l = g_slist_prepend(l, &(test_data->expected_properties[i]));
+
+	data->expected_properties_list = l;
 }
 
 static void init_test_conditions(struct test_data *data)
@@ -212,6 +228,75 @@ static void check_expected_status(uint8_t status)
 		tester_test_failed();
 }
 
+static int locate_property(gconstpointer expected_data,
+						gconstpointer received_prop)
+{
+	bt_property_t rec_prop = *((bt_property_t *)received_prop);
+	bt_property_t exp_prop =
+			((struct priority_property *)expected_data)->prop;
+
+	if (exp_prop.type && (exp_prop.type != rec_prop.type))
+		return 1;
+	if (exp_prop.len && (exp_prop.len != rec_prop.len))
+		return 1;
+	if (exp_prop.val && memcmp(exp_prop.val, rec_prop.val, exp_prop.len))
+		return 1;
+
+	return 0;
+}
+
+static int compare_priorities(gconstpointer prop_list, gconstpointer priority)
+{
+	int prio = GPOINTER_TO_INT(priority);
+	int comp_prio = ((struct priority_property *)prop_list)->prio;
+
+	if (prio > comp_prio)
+		return 0;
+
+	return 1;
+}
+
+static bool check_prop_priority(int rec_prop_prio)
+{
+	struct test_data *data = tester_get_data();
+	GSList *l = data->expected_properties_list;
+
+	if (!rec_prop_prio || !g_slist_length(l))
+		return true;
+
+	if (g_slist_find_custom(l, GINT_TO_POINTER(rec_prop_prio),
+							&compare_priorities))
+		return false;
+
+	return true;
+}
+
+static void check_expected_property(bt_property_t received_prop)
+{
+	struct test_data *data = tester_get_data();
+	int rec_prio;
+	GSList *l = data->expected_properties_list;
+	GSList *found_exp_prop;
+
+	found_exp_prop = g_slist_find_custom(l, &received_prop,
+							&locate_property);
+
+	if (found_exp_prop) {
+		rec_prio = ((struct priority_property *)
+						(found_exp_prop->data))->prio;
+		if (check_prop_priority(rec_prio))
+			l = g_slist_remove(l, found_exp_prop->data);
+	}
+
+	data->expected_properties_list = l;
+
+	if (g_slist_length(l))
+		return;
+
+	data->property_checked = true;
+	test_update_state();
+}
+
 static bool check_test_property(bt_property_t received_prop,
 						bt_property_t expected_prop)
 {
@@ -625,27 +710,18 @@ static void device_found_cb(int num_properties, bt_property_t *properties)
 	if (data->test_init_done && test->expected_hal_cb.device_found_cb) {
 		test->expected_hal_cb.device_found_cb(num_properties,
 								properties);
-		check_cb_count();
 	}
 }
 
 static void check_count_properties_cb(bt_status_t status, int num_properties,
 						bt_property_t *properties)
 {
-	struct test_data *data = tester_get_data();
+	int i;
 
-	data->cb_count--;
+	for (i = 0; i < num_properties; i++)
+		check_expected_property(properties[i]);
 }
 
-static void getprop_success_cb(bt_status_t status, int num_properties,
-						bt_property_t *properties)
-{
-	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-
-	if (check_test_property(properties[0], test->expected_property))
-		data->cb_count--;
-}
 
 static void adapter_properties_cb(bt_status_t status, int num_properties,
 						bt_property_t *properties)
@@ -658,21 +734,84 @@ static void adapter_properties_cb(bt_status_t status, int num_properties,
 		test->expected_hal_cb.adapter_properties_cb(
 							status, num_properties,
 							properties);
-		check_cb_count();
 	}
 }
 
+static bt_bdaddr_t enable_done_bdaddr_val = { {0x00} };
+static const char enable_done_bdname_val[] = "BlueZ for Android";
+static bt_uuid_t enable_done_uuids_val = {
+	.uu = { 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
+					0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb},
+};
+static bt_device_type_t enable_done_tod_val = BT_DEVICE_DEVTYPE_BREDR;
+static bt_scan_mode_t enable_done_scanmode_val = BT_SCAN_MODE_NONE;
+static uint32_t enable_done_disctimeout_val = 120;
+
+static struct priority_property enable_done_props[] = {
+	{
+	.prop.type = BT_PROPERTY_BDADDR,
+	.prop.len = sizeof(enable_done_bdaddr_val),
+	.prop.val = &enable_done_bdaddr_val,
+	.prio = 1,
+	},
+	{
+	.prop.type = BT_PROPERTY_BDNAME,
+	.prop.len = sizeof(enable_done_bdname_val) - 1,
+	.prop.val = &enable_done_bdname_val,
+	.prio = 2,
+	},
+	{
+	.prop.type = BT_PROPERTY_UUIDS,
+	.prop.len = sizeof(enable_done_uuids_val),
+	.prop.val = &enable_done_uuids_val,
+	.prio = 3,
+	},
+	{
+	.prop.type = BT_PROPERTY_CLASS_OF_DEVICE,
+	.prop.len = sizeof(uint32_t),
+	.prop.val = NULL,
+	.prio = 4,
+	},
+	{
+	.prop.type = BT_PROPERTY_TYPE_OF_DEVICE,
+	.prop.len = sizeof(enable_done_tod_val),
+	.prop.val = &enable_done_tod_val,
+	.prio = 5,
+	},
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
+	.prop.len = sizeof(enable_done_scanmode_val),
+	.prop.val = &enable_done_scanmode_val,
+	.prio = 6,
+	},
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+	.prop.len = 0,
+	.prop.val = NULL,
+	.prio = 7,
+	},
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+	.prop.len = sizeof(enable_done_disctimeout_val),
+	.prop.val = &enable_done_disctimeout_val,
+	.prio = 8,
+	},
+};
+
 static const struct generic_data bluetooth_enable_success_test = {
 	.expected_hal_cb.adapter_state_changed_cb = enable_success_cb,
 	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
-	.expected_cb_count = 9,
+	.expected_cb_count = 1,
+	.expected_properties_num = 8,
+	.expected_properties = enable_done_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
 };
 
 static const struct generic_data bluetooth_enable_done_test = {
 	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
-	.expected_cb_count = 8,
 	.expected_adapter_status = BT_STATUS_DONE,
+	.expected_properties_num = 8,
+	.expected_properties = enable_done_props,
 };
 
 static const struct generic_data bluetooth_disable_success_test = {
@@ -683,94 +822,146 @@ static const struct generic_data bluetooth_disable_success_test = {
 
 static char test_set_bdname[] = "test_bdname_set";
 
+static struct priority_property setprop_bdname_props[] = {
+	{
+	.prop.type = BT_PROPERTY_BDNAME,
+	.prop.val = test_set_bdname,
+	.prop.len = sizeof(test_set_bdname) - 1,
+	.prio = 0,
+	},
+};
+
 static const struct generic_data bluetooth_setprop_bdname_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
-	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_BDNAME,
-	.expected_property.val = test_set_bdname,
-	.expected_property.len = sizeof(test_set_bdname) - 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = setprop_bdname_props,
 };
 
 static bt_scan_mode_t test_setprop_scanmode_val =
 					BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
 
+static struct priority_property setprop_scanmode_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
+	.prop.val = &test_setprop_scanmode_val,
+	.prop.len = sizeof(bt_scan_mode_t),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_scanmode_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = setprop_scanmode_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
-	.expected_property.val = &test_setprop_scanmode_val,
-	.expected_property.len = sizeof(bt_scan_mode_t),
 };
 
 static uint32_t test_setprop_disctimeout_val = 120;
 
+static struct priority_property setprop_disctimeout_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+	.prop.val = &test_setprop_disctimeout_val,
+	.prop.len = sizeof(test_setprop_disctimeout_val),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_disctimeout_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = setprop_disctimeout_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
-	.expected_property.val = &test_setprop_disctimeout_val,
-	.expected_property.len = sizeof(test_setprop_disctimeout_val),
+};
+
+static bt_bdaddr_t test_getprop_bdaddr_val = { {0x00} };
+
+static struct priority_property getprop_bdaddr_props[] = {
+	{
+	.prop.type = BT_PROPERTY_BDADDR,
+	.prop.val = &test_getprop_bdaddr_val,
+	.prop.len = sizeof(test_getprop_bdaddr_val),
+	},
 };
 
 static const struct generic_data bluetooth_getprop_bdaddr_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_bdaddr_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_BDADDR,
-	.expected_property.val = NULL,
-	.expected_property.len = sizeof(bt_bdaddr_t),
 };
 
 static char test_bdname[] = "test_bdname_setget";
 
+static struct priority_property getprop_bdname_props[] = {
+	{
+	.prop.type = BT_PROPERTY_BDNAME,
+	.prop.val = &test_bdname,
+	.prop.len = sizeof(test_bdname) - 1,
+	},
+};
+
 static const struct generic_data bluetooth_getprop_bdname_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_bdname_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_BDNAME,
-	.expected_property.val = test_bdname,
-	.expected_property.len = sizeof(test_bdname) - 1,
 };
 
 static unsigned char setprop_uuids[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00,
 			0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
 			0x00, 0x00 };
 
+static struct priority_property setprop_uuid_prop[] = {
+	{
+	.prop.type = BT_PROPERTY_UUIDS,
+	.prop.val = &setprop_uuids,
+	.prop.len = sizeof(setprop_uuids),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_uuid_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_UUIDS,
-	.set_property.val = &setprop_uuids,
-	.set_property.len = sizeof(setprop_uuids),
 };
 
 static uint32_t setprop_class_of_device = 0;
 
+static struct priority_property setprop_cod_props[] = {
+	{
+	.prop.type = BT_PROPERTY_CLASS_OF_DEVICE,
+	.prop.val = &setprop_class_of_device,
+	.prop.len = sizeof(setprop_class_of_device),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_cod_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_CLASS_OF_DEVICE,
-	.set_property.val = &setprop_class_of_device,
-	.set_property.len = sizeof(setprop_class_of_device),
 };
 
 static bt_device_type_t setprop_type_of_device = BT_DEVICE_DEVTYPE_BREDR;
 
+static struct priority_property setprop_tod_props[] = {
+	{
+	.prop.type = BT_PROPERTY_TYPE_OF_DEVICE,
+	.prop.val = &setprop_type_of_device,
+	.prop.len = sizeof(setprop_type_of_device),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_tod_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_TYPE_OF_DEVICE,
-	.set_property.val = &setprop_type_of_device,
-	.set_property.len = sizeof(setprop_type_of_device),
 };
 
 static int32_t setprop_remote_rssi = 0;
 
+static struct priority_property setprop_remote_rssi_props[] = {
+	{
+	.prop.type = BT_PROPERTY_REMOTE_RSSI,
+	.prop.val = &setprop_remote_rssi,
+	.prop.len = sizeof(setprop_remote_rssi),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_remote_rssi_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_REMOTE_RSSI,
-	.set_property.val = &setprop_remote_rssi,
-	.set_property.len = sizeof(setprop_remote_rssi),
 };
 
 static bt_service_record_t setprop_remote_service = {
@@ -779,91 +970,136 @@ static bt_service_record_t setprop_remote_service = {
 	.name = "bt_name",
 };
 
+static struct priority_property setprop_service_record_props[] = {
+	{
+	.prop.type = BT_PROPERTY_SERVICE_RECORD,
+	.prop.val = &setprop_remote_service,
+	.prop.len = sizeof(setprop_remote_service),
+	},
+};
+
 static const struct generic_data
 			bluetooth_setprop_service_record_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_SERVICE_RECORD,
-	.set_property.val = &setprop_remote_service,
-	.set_property.len = sizeof(setprop_remote_service),
 };
 
 static bt_bdaddr_t setprop_bdaddr = {
 	.address = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 };
 
+static struct priority_property setprop_bdaddr_props[] = {
+	{
+	.prop.type = BT_PROPERTY_BDADDR,
+	.prop.val = &setprop_bdaddr,
+	.prop.len = sizeof(setprop_bdaddr),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_bdaddr_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_BDADDR,
-	.set_property.val = &setprop_bdaddr,
-	.set_property.len = sizeof(setprop_bdaddr),
 };
 
 static bt_scan_mode_t setprop_scanmode_connectable = BT_SCAN_MODE_CONNECTABLE;
 
+static struct priority_property setprop_scanmode_connectable_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
+	.prop.val = &setprop_scanmode_connectable,
+	.prop.len = sizeof(setprop_scanmode_connectable),
+	},
+};
+
 static const struct generic_data
 			bluetooth_setprop_scanmode_connectable_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = setprop_scanmode_connectable_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
-	.expected_property.val = &setprop_scanmode_connectable,
-	.expected_property.len = sizeof(setprop_scanmode_connectable),
 };
 
 static bt_bdaddr_t setprop_bonded_devices = {
 	.address = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 },
 };
 
+static struct priority_property setprop_bonded_devices_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+	.prop.val = &setprop_bonded_devices,
+	.prop.len = sizeof(setprop_bonded_devices),
+	},
+};
+
 static const struct generic_data
 			bluetooth_setprop_bonded_devices_invalid_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
-	.set_property.type = BT_PROPERTY_ADAPTER_BONDED_DEVICES,
-	.set_property.val = &setprop_bonded_devices,
-	.set_property.len = sizeof(setprop_bonded_devices),
 };
 
 static uint32_t getprop_cod = 0x00020c;
 
+static struct priority_property getprop_cod_props[] = {
+	{
+	.prop.type = BT_PROPERTY_CLASS_OF_DEVICE,
+	.prop.val = &getprop_cod,
+	.prop.len = sizeof(getprop_cod),
+	},
+};
+
 static const struct generic_data bluetooth_getprop_cod_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_cod_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_CLASS_OF_DEVICE,
-	.expected_property.val = &getprop_cod,
-	.expected_property.len = sizeof(getprop_cod),
 };
 
 static bt_device_type_t getprop_tod = BT_DEVICE_DEVTYPE_BREDR;
 
+static struct priority_property getprop_tod_props[] = {
+	{
+	.prop.type = BT_PROPERTY_TYPE_OF_DEVICE,
+	.prop.val = &getprop_tod,
+	.prop.len = sizeof(getprop_tod),
+	},
+};
+
 static const struct generic_data bluetooth_getprop_tod_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_tod_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_TYPE_OF_DEVICE,
-	.expected_property.val = &getprop_tod,
-	.expected_property.len = sizeof(getprop_tod),
 };
 
 static bt_scan_mode_t getprop_scanmode = BT_SCAN_MODE_NONE;
 
+static struct priority_property getprop_scanmode_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
+	.prop.val = &getprop_scanmode,
+	.prop.len = sizeof(getprop_scanmode),
+	},
+};
+
 static const struct generic_data bluetooth_getprop_scanmode_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_scanmode_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
-	.expected_property.val = &getprop_scanmode,
-	.expected_property.len = sizeof(getprop_scanmode),
 };
 
 static uint32_t getprop_disctimeout_val = 120;
 
+static struct priority_property getprop_disctimeout_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+	.prop.val = &getprop_disctimeout_val,
+	.prop.len = sizeof(getprop_disctimeout_val),
+	},
+};
+
 static const struct generic_data bluetooth_getprop_disctimeout_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_disctimeout_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
-	.expected_property.val = &getprop_disctimeout_val,
-	.expected_property.len = sizeof(getprop_disctimeout_val),
 };
 
 static bt_uuid_t getprop_uuids = {
@@ -871,33 +1107,51 @@ static bt_uuid_t getprop_uuids = {
 					0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB },
 };
 
+static struct priority_property getprop_uuids_props[] = {
+	{
+	.prop.type = BT_PROPERTY_UUIDS,
+	.prop.val = &getprop_uuids,
+	.prop.len = sizeof(getprop_uuids),
+	},
+};
+
 static const struct generic_data bluetooth_getprop_uuids_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_uuids_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_UUIDS,
-	.expected_property.val = &getprop_uuids,
-	.expected_property.len = sizeof(getprop_uuids),
+};
+
+static struct priority_property getprop_bondeddev_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+	.prop.val = NULL,
+	.prop.len = 0,
+	},
 };
 
 static const struct generic_data bluetooth_getprop_bondeddev_success_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = getprop_bondeddev_props,
 	.expected_adapter_status = BT_STATUS_SUCCESS,
-	.expected_property.type = BT_PROPERTY_ADAPTER_BONDED_DEVICES,
-	.expected_property.val = NULL,
-	.expected_property.len = 0,
 };
 
 static bt_scan_mode_t setprop_scanmode_none = BT_SCAN_MODE_NONE;
 
+static struct priority_property setprop_scanmode_none_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
+	.prop.val = &setprop_scanmode_none,
+	.prop.len = sizeof(setprop_scanmode_none),
+	},
+};
+
 static const struct generic_data bluetooth_setprop_scanmode_none_done_test = {
-	.expected_hal_cb.adapter_properties_cb = getprop_success_cb,
-	.expected_cb_count = 1,
+	.expected_hal_cb.adapter_properties_cb = check_count_properties_cb,
+	.expected_properties_num = 1,
+	.expected_properties = setprop_scanmode_none_props,
 	.expected_adapter_status = BT_STATUS_DONE,
-	.expected_property.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
-	.expected_property.val = &setprop_scanmode_none,
-	.expected_property.len = sizeof(setprop_scanmode_none),
 };
 
 static const struct generic_data bluetooth_discovery_start_success_test = {
@@ -1073,6 +1327,9 @@ static void teardown(const void *test_data)
 		data->if_bluetooth = NULL;
 	}
 
+	if (data->expected_properties_list)
+		g_slist_free(data->expected_properties_list);
+
 	data->device->close(data->device);
 
 	if (data->bluetoothd_pid)
@@ -1091,8 +1348,12 @@ static void test_enable(const void *test_data)
 	struct test_data *data = tester_get_data();
 	bt_status_t adapter_status;
 
+	uint8_t *bdaddr = (uint8_t *)hciemu_get_master_bdaddr(data->hciemu);
+
 	init_test_conditions(data);
 
+	bdaddr2android((const bdaddr_t *)bdaddr, &enable_done_bdaddr_val.address);
+
 	adapter_status = data->if_bluetooth->enable();
 	check_expected_status(adapter_status);
 }
@@ -1102,8 +1363,12 @@ static void test_enable_done(const void *test_data)
 	struct test_data *data = tester_get_data();
 	bt_status_t adapter_status;
 
+	uint8_t *bdaddr = (uint8_t *)hciemu_get_master_bdaddr(data->hciemu);
+
 	init_test_conditions(data);
 
+	bdaddr2android((const bdaddr_t *)bdaddr, &enable_done_bdaddr_val.address);
+
 	adapter_status = data->if_bluetooth->enable();
 	check_expected_status(adapter_status);
 }
@@ -1122,22 +1387,19 @@ static void test_disable(const void *test_data)
 static void test_setprop_bdname_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_bdname_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
 
 	adapter_status = data->if_bluetooth->set_adapter_property(prop);
-
 	check_expected_status(adapter_status);
 }
 
 static void test_setprop_scanmode_succes(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_scanmode_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1149,8 +1411,7 @@ static void test_setprop_scanmode_succes(const void *test_data)
 static void test_setprop_disctimeout_succes(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_disctimeout_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1162,12 +1423,14 @@ static void test_setprop_disctimeout_succes(const void *test_data)
 static void test_getprop_bdaddr_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = setprop_bdaddr_props[0].prop;
 	bt_status_t adapter_status;
+	uint8_t *bdaddr = (uint8_t *)hciemu_get_master_bdaddr(data->hciemu);
 
 	init_test_conditions(data);
 
+	bdaddr2android((const bdaddr_t *)bdaddr, &test_getprop_bdaddr_val.address);
+
 	adapter_status = data->if_bluetooth->get_adapter_property(prop.type);
 	check_expected_status(adapter_status);
 }
@@ -1175,8 +1438,7 @@ static void test_getprop_bdaddr_success(const void *test_data)
 static void test_getprop_bdname_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(getprop_bdname_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1187,12 +1449,10 @@ static void test_getprop_bdname_success(const void *test_data)
 	adapter_status = data->if_bluetooth->get_adapter_property((*prop).type);
 	check_expected_status(adapter_status);
 }
-
 static void test_setprop_uuid_invalid(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_uuid_prop[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1204,8 +1464,7 @@ static void test_setprop_uuid_invalid(const void *test_data)
 static void test_setprop_cod_invalid(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_cod_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1230,8 +1489,7 @@ static void test_setprop_tod_invalid(const void *test_data)
 static void test_setprop_rssi_invalid(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_remote_rssi_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1243,8 +1501,7 @@ static void test_setprop_rssi_invalid(const void *test_data)
 static void test_setprop_service_record_invalid(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_service_record_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1256,8 +1513,7 @@ static void test_setprop_service_record_invalid(const void *test_data)
 static void test_setprop_bdaddr_invalid(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_bdaddr_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1269,8 +1525,8 @@ static void test_setprop_bdaddr_invalid(const void *test_data)
 static void test_setprop_scanmode_connectable_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop =
+				&(setprop_scanmode_connectable_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1282,8 +1538,7 @@ static void test_setprop_scanmode_connectable_success(const void *test_data)
 static void test_setprop_bonded_devices_invalid(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_bonded_devices_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1295,8 +1550,7 @@ static void test_setprop_bonded_devices_invalid(const void *test_data)
 static void test_getprop_cod_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = setprop_cod_props[0].prop;
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1308,8 +1562,7 @@ static void test_getprop_cod_success(const void *test_data)
 static void test_getprop_tod_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = setprop_tod_props[0].prop;
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1321,8 +1574,7 @@ static void test_getprop_tod_success(const void *test_data)
 static void test_getprop_scanmode_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = setprop_scanmode_props[0].prop;
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1334,8 +1586,7 @@ static void test_getprop_scanmode_success(const void *test_data)
 static void test_getprop_disctimeout_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = setprop_disctimeout_props[0].prop;
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1347,8 +1598,7 @@ static void test_getprop_disctimeout_success(const void *test_data)
 static void test_getprop_uuids_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = getprop_uuids_props[0].prop;
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1360,8 +1610,7 @@ static void test_getprop_uuids_success(const void *test_data)
 static void test_getprop_bondeddev_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t prop = test->expected_property;
+	const bt_property_t prop = getprop_bondeddev_props[0].prop;
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
@@ -1373,8 +1622,7 @@ static void test_getprop_bondeddev_success(const void *test_data)
 static void test_setprop_scanmode_none_done(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	const struct generic_data *test = data->test_data;
-	const bt_property_t *prop = &test->expected_property;
+	const bt_property_t *prop = &(setprop_scanmode_none_props[0].prop);
 	bt_status_t adapter_status;
 
 	init_test_conditions(data);
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH_v7 4/4] android/pan: Remove connected PAN devices on profile unregister call
From: Ravi kumar Veeramally @ 2014-01-10 14:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389363109-6312-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/android/pan.c b/android/pan.c
index 9f99ed9..205da71 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -752,10 +752,20 @@ bool bt_pan_register(const bdaddr_t *addr)
 	return true;
 }
 
+static void pan_device_disconnected(gpointer data, gpointer user_data)
+{
+	struct pan_device *dev = data;
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
 void bt_pan_unregister(void)
 {
 	DBG("");
 
+	g_slist_foreach(devices, pan_device_disconnected, NULL);
+	devices = NULL;
+
 	bnep_cleanup();
 
 	ipc_unregister(HAL_SERVICE_ID_PAN);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v7 3/4] android/pan: Implement PAN enable HAL api at daemon side
From: Ravi kumar Veeramally @ 2014-01-10 14:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389363109-6312-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 21a46b4..9f99ed9 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -576,18 +576,40 @@ static void bt_pan_enable(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_enable *cmd = buf;
 	uint8_t status;
+	int err;
+
+	DBG("");
+
+	if (local_role == cmd->local_role) {
+		status = HAL_STATUS_SUCCESS;
+		goto reply;
+	}
+
+	/* destroy existing server */
+	destroy_nap_device();
 
 	switch (cmd->local_role) {
-	case HAL_PAN_ROLE_PANU:
 	case HAL_PAN_ROLE_NAP:
-		DBG("Not Implemented");
-		status  = HAL_STATUS_FAILED;
 		break;
+	case HAL_PAN_ROLE_NONE:
+		status = HAL_STATUS_SUCCESS;
+		goto reply;
 	default:
 		status = HAL_STATUS_UNSUPPORTED;
-		break;
+		goto reply;
 	}
 
+	local_role = cmd->local_role;
+	err = register_nap_server();
+	if (err < 0) {
+		status = HAL_STATUS_FAILED;
+		destroy_nap_device();
+		goto reply;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+reply:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v7 2/4] android/pan: Listen for incoming connections and accept in NAP role
From: Ravi kumar Veeramally @ 2014-01-10 14:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389363109-6312-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Listen for incoming connections and accept it. Create bnep interface
add it to bridge and notify control and connection state information
through HAL. Remove the device on disconnect request. If android
settings UI does not have bluetooth tethering enabled it immediately
sends disconnect signal.
---
 android/pan.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 182 insertions(+), 3 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index bb009f3..21a46b4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -65,12 +65,15 @@ struct pan_device {
 	uint8_t		role;
 	GIOChannel	*io;
 	struct bnep	*session;
+	guint		watch;
 };
 
 static struct {
 	uint32_t	record_id;
+	GIOChannel	*io;
 } nap_dev = {
 	.record_id = 0,
+	.io = NULL,
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -83,13 +86,19 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 
 static void pan_device_free(struct pan_device *dev)
 {
+	if (dev->watch > 0) {
+		bnep_server_delete(BNEP_BRIDGE, dev->iface, &dev->dst);
+		g_source_remove(dev->watch);
+	}
+
 	if (dev->io) {
 		g_io_channel_shutdown(dev->io, FALSE, NULL);
 		g_io_channel_unref(dev->io);
-		dev->io = NULL;
 	}
 
-	bnep_free(dev->session);
+	if (dev->session)
+		bnep_free(dev->session);
+
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
 
@@ -300,7 +309,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 
 	dev = l->data;
 
-	if (dev->conn_state == HAL_PAN_STATE_CONNECTED)
+	if (dev->conn_state == HAL_PAN_STATE_CONNECTED && dev->session)
 		bnep_disconnect(dev->session);
 
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
@@ -310,6 +319,154 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
 }
 
+static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+
+	DBG("disconnected");
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+
+	return FALSE;
+}
+static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+	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 sk, n;
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		error("Hangup or error or inval on BNEP socket");
+		return FALSE;
+	}
+
+	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);
+		goto failed;
+	}
+
+	/* Highest known control command id BNEP_FILTER_MULT_ADDR_RSP 0x06 */
+	if (req->type == BNEP_CONTROL &&
+			req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+		error("cmd not understood");
+		bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_CMD_NOT_UNDERSTOOD,
+								req->ctrl);
+		goto failed;
+	}
+
+	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ) {
+		error("cmd is not BNEP_SETUP_CONN_REQ %02X %02X", req->type,
+								req->ctrl);
+		goto failed;
+	}
+
+	rsp = bnep_setup_decode(req, &dst_role, &src_role);
+	if (rsp) {
+		error("bnep_setup_decode failed");
+		goto failed;
+	}
+
+	rsp = bnep_setup_chk(dst_role, src_role);
+	if (rsp) {
+		error("benp_setup_chk failed");
+		goto failed;
+	}
+
+	if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
+							&dev->dst) < 0) {
+		error("server_connadd failed");
+		rsp = BNEP_CONN_NOT_ALLOWED;
+		goto failed;
+	}
+
+	rsp = BNEP_SUCCESS;
+	bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+
+	dev->watch = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+							nap_watchdog_cb, dev);
+	g_io_channel_unref(dev->io);
+	dev->io = NULL;
+
+	bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
+
+	return FALSE;
+
+failed:
+	bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+	pan_device_free(dev);
+
+	return FALSE;
+}
+
+static void nap_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+
+	DBG("");
+
+	if (err) {
+		error("%s", err->message);
+		bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+		return;
+	}
+
+	g_io_channel_set_close_on_unref(chan, TRUE);
+	dev->watch = g_io_add_watch(chan,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				nap_setup_cb, dev);
+}
+
+static void nap_confirm_cb(GIOChannel *chan, gpointer data)
+{
+	struct pan_device *dev = NULL;
+	bdaddr_t dst;
+	char address[18];
+	GError *err = NULL;
+
+	DBG("");
+
+	bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	DBG("incoming connect request from %s", address);
+	dev = g_new0(struct pan_device, 1);
+	bacpy(&dev->dst, &dst);
+	local_role = HAL_PAN_ROLE_NAP;
+	dev->role = HAL_PAN_ROLE_PANU;
+
+	dev->io = g_io_channel_ref(chan);
+	g_io_channel_set_close_on_unref(dev->io, TRUE);
+
+	if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) {
+		error("bt_io_accept: %s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	devices = g_slist_append(devices, dev);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
+
+	return;
+
+failed:
+	g_free(dev);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
 static int set_forward_delay(void)
 {
 	int fd, ret;
@@ -378,10 +535,17 @@ static void destroy_nap_device(void)
 	DBG("");
 
 	nap_remove_bridge();
+
+	if (nap_dev.io) {
+		g_io_channel_shutdown(nap_dev.io, FALSE, NULL);
+		g_io_channel_unref(nap_dev.io);
+		nap_dev.io = NULL;
+	}
 }
 
 static int register_nap_server(void)
 {
+	GError *gerr;
 	int err;
 
 	DBG("");
@@ -390,6 +554,21 @@ static int register_nap_server(void)
 	if (err < 0)
 		return err;
 
+	nap_dev.io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
+					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+					BT_IO_OPT_PSM, BNEP_PSM,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_OMTU, BNEP_MTU,
+					BT_IO_OPT_IMTU, BNEP_MTU,
+					BT_IO_OPT_INVALID);
+
+	if (!nap_dev.io) {
+		destroy_nap_device();
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v7 1/4] android/pan: Register Network Access Point
From: Ravi kumar Veeramally @ 2014-01-10 14:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389363109-6312-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Register NAP server and adds bnep bridge. Removes bridge
on destroy call. Bridge mechanism is needed when device acting
as a server and listen for incoming connections.
---
 android/pan.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 109 insertions(+), 5 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 38e353d..bb009f3 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -28,6 +28,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <glib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <linux/sockios.h>
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
@@ -45,11 +50,13 @@
 #include "bluetooth.h"
 
 #define SVC_HINT_NETWORKING 0x02
+#define BNEP_BRIDGE	"bnep"
+#define FORWARD_DELAY_PATH	"/sys/class/net/%s/bridge/forward_delay"
+#define DELAY_PATH_MAX	41
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
 uint8_t local_role = HAL_PAN_ROLE_NONE;
-static uint32_t record_id = 0;
 
 struct pan_device {
 	char		iface[16];
@@ -60,6 +67,12 @@ struct pan_device {
 	struct bnep	*session;
 };
 
+static struct {
+	uint32_t	record_id;
+} nap_dev = {
+	.record_id = 0,
+};
+
 static int device_cmp(gconstpointer s, gconstpointer user_data)
 {
 	const struct pan_device *dev = s;
@@ -297,6 +310,89 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
 }
 
+static int set_forward_delay(void)
+{
+	int fd, ret;
+	char path[DELAY_PATH_MAX];
+
+	snprintf(path, sizeof(path), FORWARD_DELAY_PATH, BNEP_BRIDGE);
+
+	fd = open(path, O_RDWR);
+	if (fd < 0)
+		return -errno;
+
+	ret = write(fd, "0", sizeof("0"));
+	close(fd);
+
+	return ret;
+}
+
+static int nap_create_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
+		err = -errno;
+		if (err != -EEXIST) {
+			close(sk);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	err = set_forward_delay();
+	if (err < 0)
+		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+
+	close(sk);
+
+	return err;
+}
+
+static int nap_remove_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+	close(sk);
+
+	if (err < 0)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static void destroy_nap_device(void)
+{
+	DBG("");
+
+	nap_remove_bridge();
+}
+
+static int register_nap_server(void)
+{
+	int err;
+
+	DBG("");
+
+	err = nap_create_bridge();
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static void bt_pan_enable(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_enable *cmd = buf;
@@ -437,11 +533,18 @@ bool bt_pan_register(const bdaddr_t *addr)
 	err = bnep_init();
 	if (err) {
 		error("bnep init failed");
-		sdp_record_free(rec);
+		bt_adapter_remove_record(rec->handle);
+		return false;
+	}
+
+	err = register_nap_server();
+	if (err < 0) {
+		bt_adapter_remove_record(rec->handle);
+		bnep_cleanup();
 		return false;
 	}
 
-	record_id = rec->handle;
+	nap_dev.record_id = rec->handle;
 	ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
 
@@ -455,6 +558,7 @@ void bt_pan_unregister(void)
 	bnep_cleanup();
 
 	ipc_unregister(HAL_SERVICE_ID_PAN);
-	bt_adapter_remove_record(record_id);
-	record_id = 0;
+	bt_adapter_remove_record(nap_dev.record_id);
+	nap_dev.record_id = 0;
+	destroy_nap_device();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v7 0/4] Add support for NAP role
From: Ravi kumar Veeramally @ 2014-01-10 14:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

v7: Rebase issue with _v6.

v6: Fixed Szymon's comments (use snprintf and defines).

v5: Fixed Szymon's comments and added his fix (crash when bridge create
    fails).

v4: Fixed Szymon's and Luiz's comments.

v3: Fixed Johan's comments (removed fopen, fprintf and used open and write).

v2: Fixed Johan's comments.

v1: This patch set add support for NAP role. It register NAP server and create
  bnep bridge and listen for incoming connections from client devices.
  On incoming connection request it accepts connection, creates bnep interface
  and notifies control state and connection state infromation. Removes device
  on disconnect request. Android related changes are required to enable this
  role. Patches sent to respective ML.

Ravi kumar Veeramally (4):
  android/pan: Register Network Access Point
  android/pan: Listen for incoming connections and accept in NAP role
  android/pan: Implement PAN enable HAL api at daemon side
  android/pan: Remove connected PAN devices on profile unregister call

 android/pan.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 327 insertions(+), 12 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* [PATCH_v6 4/4] android/pan: Remove connected PAN devices on profile unregister call
From: Ravi kumar Veeramally @ 2014-01-10 13:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389361840-5021-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/android/pan.c b/android/pan.c
index a733d22..8ea07a4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -750,10 +750,20 @@ bool bt_pan_register(const bdaddr_t *addr)
 	return true;
 }
 
+static void pan_device_disconnected(gpointer data, gpointer user_data)
+{
+	struct pan_device *dev = data;
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
 void bt_pan_unregister(void)
 {
 	DBG("");
 
+	g_slist_foreach(devices, pan_device_disconnected, NULL);
+	devices = NULL;
+
 	bnep_cleanup();
 
 	ipc_unregister(HAL_SERVICE_ID_PAN);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v6 3/4] android/pan: Implement PAN enable HAL api at daemon side
From: Ravi kumar Veeramally @ 2014-01-10 13:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389361840-5021-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index d683945..a733d22 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -574,18 +574,40 @@ static void bt_pan_enable(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_enable *cmd = buf;
 	uint8_t status;
+	int err;
+
+	DBG("");
+
+	if (local_role == cmd->local_role) {
+		status = HAL_STATUS_SUCCESS;
+		goto reply;
+	}
+
+	/* destroy existing server */
+	destroy_nap_device();
 
 	switch (cmd->local_role) {
-	case HAL_PAN_ROLE_PANU:
 	case HAL_PAN_ROLE_NAP:
-		DBG("Not Implemented");
-		status  = HAL_STATUS_FAILED;
 		break;
+	case HAL_PAN_ROLE_NONE:
+		status = HAL_STATUS_SUCCESS;
+		goto reply;
 	default:
 		status = HAL_STATUS_UNSUPPORTED;
-		break;
+		goto reply;
 	}
 
+	local_role = cmd->local_role;
+	err = register_nap_server();
+	if (err < 0) {
+		status = HAL_STATUS_FAILED;
+		destroy_nap_device();
+		goto reply;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+reply:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v6 2/4] android/pan: Listen for incoming connections and accept in NAP role
From: Ravi kumar Veeramally @ 2014-01-10 13:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389361840-5021-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Listen for incoming connections and accept it. Create bnep interface
add it to bridge and notify control and connection state information
through HAL. Remove the device on disconnect request. If android
settings UI does not have bluetooth tethering enabled it immediately
sends disconnect signal.
---
 android/pan.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 182 insertions(+), 3 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index ea0e34e..d683945 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -63,12 +63,15 @@ struct pan_device {
 	uint8_t		role;
 	GIOChannel	*io;
 	struct bnep	*session;
+	guint		watch;
 };
 
 static struct {
 	uint32_t	record_id;
+	GIOChannel	*io;
 } nap_dev = {
 	.record_id = 0,
+	.io = NULL,
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -81,13 +84,19 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 
 static void pan_device_free(struct pan_device *dev)
 {
+	if (dev->watch > 0) {
+		bnep_server_delete(BNEP_BRIDGE, dev->iface, &dev->dst);
+		g_source_remove(dev->watch);
+	}
+
 	if (dev->io) {
 		g_io_channel_shutdown(dev->io, FALSE, NULL);
 		g_io_channel_unref(dev->io);
-		dev->io = NULL;
 	}
 
-	bnep_free(dev->session);
+	if (dev->session)
+		bnep_free(dev->session);
+
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
 
@@ -298,7 +307,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 
 	dev = l->data;
 
-	if (dev->conn_state == HAL_PAN_STATE_CONNECTED)
+	if (dev->conn_state == HAL_PAN_STATE_CONNECTED && dev->session)
 		bnep_disconnect(dev->session);
 
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
@@ -308,6 +317,154 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
 }
 
+static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+
+	DBG("disconnected");
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+
+	return FALSE;
+}
+static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+	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 sk, n;
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		error("Hangup or error or inval on BNEP socket");
+		return FALSE;
+	}
+
+	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);
+		goto failed;
+	}
+
+	/* Highest known control command id BNEP_FILTER_MULT_ADDR_RSP 0x06 */
+	if (req->type == BNEP_CONTROL &&
+			req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+		error("cmd not understood");
+		bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_CMD_NOT_UNDERSTOOD,
+								req->ctrl);
+		goto failed;
+	}
+
+	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ) {
+		error("cmd is not BNEP_SETUP_CONN_REQ %02X %02X", req->type,
+								req->ctrl);
+		goto failed;
+	}
+
+	rsp = bnep_setup_decode(req, &dst_role, &src_role);
+	if (rsp) {
+		error("bnep_setup_decode failed");
+		goto failed;
+	}
+
+	rsp = bnep_setup_chk(dst_role, src_role);
+	if (rsp) {
+		error("benp_setup_chk failed");
+		goto failed;
+	}
+
+	if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
+							&dev->dst) < 0) {
+		error("server_connadd failed");
+		rsp = BNEP_CONN_NOT_ALLOWED;
+		goto failed;
+	}
+
+	rsp = BNEP_SUCCESS;
+	bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+
+	dev->watch = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+							nap_watchdog_cb, dev);
+	g_io_channel_unref(dev->io);
+	dev->io = NULL;
+
+	bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
+
+	return FALSE;
+
+failed:
+	bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+	pan_device_free(dev);
+
+	return FALSE;
+}
+
+static void nap_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+
+	DBG("");
+
+	if (err) {
+		error("%s", err->message);
+		bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+		return;
+	}
+
+	g_io_channel_set_close_on_unref(chan, TRUE);
+	dev->watch = g_io_add_watch(chan,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				nap_setup_cb, dev);
+}
+
+static void nap_confirm_cb(GIOChannel *chan, gpointer data)
+{
+	struct pan_device *dev = NULL;
+	bdaddr_t dst;
+	char address[18];
+	GError *err = NULL;
+
+	DBG("");
+
+	bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	DBG("incoming connect request from %s", address);
+	dev = g_new0(struct pan_device, 1);
+	bacpy(&dev->dst, &dst);
+	local_role = HAL_PAN_ROLE_NAP;
+	dev->role = HAL_PAN_ROLE_PANU;
+
+	dev->io = g_io_channel_ref(chan);
+	g_io_channel_set_close_on_unref(dev->io, TRUE);
+
+	if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) {
+		error("bt_io_accept: %s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	devices = g_slist_append(devices, dev);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
+
+	return;
+
+failed:
+	g_free(dev);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
 static int set_forward_delay(void)
 {
 	int fd, ret;
@@ -376,10 +533,17 @@ static void destroy_nap_device(void)
 	DBG("");
 
 	nap_remove_bridge();
+
+	if (nap_dev.io) {
+		g_io_channel_shutdown(nap_dev.io, FALSE, NULL);
+		g_io_channel_unref(nap_dev.io);
+		nap_dev.io = NULL;
+	}
 }
 
 static int register_nap_server(void)
 {
+	GError *gerr;
 	int err;
 
 	DBG("");
@@ -388,6 +552,21 @@ static int register_nap_server(void)
 	if (err < 0)
 		return err;
 
+	nap_dev.io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
+					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+					BT_IO_OPT_PSM, BNEP_PSM,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_OMTU, BNEP_MTU,
+					BT_IO_OPT_IMTU, BNEP_MTU,
+					BT_IO_OPT_INVALID);
+
+	if (!nap_dev.io) {
+		destroy_nap_device();
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v6 1/4] android/pan: Register Network Access Point
From: Ravi kumar Veeramally @ 2014-01-10 13:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389361840-5021-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Register NAP server and adds bnep bridge. Removes bridge
on destroy call. Bridge mechanism is needed when device acting
as a server and listen for incoming connections.
---
 android/pan.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 107 insertions(+), 5 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 38e353d..ea0e34e 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -28,6 +28,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <glib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <linux/sockios.h>
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
@@ -45,11 +50,11 @@
 #include "bluetooth.h"
 
 #define SVC_HINT_NETWORKING 0x02
+#define BNEP_BRIDGE	"bnep"
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
 uint8_t local_role = HAL_PAN_ROLE_NONE;
-static uint32_t record_id = 0;
 
 struct pan_device {
 	char		iface[16];
@@ -60,6 +65,12 @@ struct pan_device {
 	struct bnep	*session;
 };
 
+static struct {
+	uint32_t	record_id;
+} nap_dev = {
+	.record_id = 0,
+};
+
 static int device_cmp(gconstpointer s, gconstpointer user_data)
 {
 	const struct pan_device *dev = s;
@@ -297,6 +308,89 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
 }
 
+static int set_forward_delay(void)
+{
+	int fd, ret;
+	char path[41];
+
+	sprintf(path, "/sys/class/net/%s/bridge/forward_delay", BNEP_BRIDGE);
+
+	fd = open(path, O_RDWR);
+	if (fd < 0)
+		return -errno;
+
+	ret = write(fd, "0", sizeof("0"));
+	close(fd);
+
+	return ret;
+}
+
+static int nap_create_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
+		err = -errno;
+		if (err != -EEXIST) {
+			close(sk);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	err = set_forward_delay();
+	if (err < 0)
+		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+
+	close(sk);
+
+	return err;
+}
+
+static int nap_remove_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+	close(sk);
+
+	if (err < 0)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static void destroy_nap_device(void)
+{
+	DBG("");
+
+	nap_remove_bridge();
+}
+
+static int register_nap_server(void)
+{
+	int err;
+
+	DBG("");
+
+	err = nap_create_bridge();
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static void bt_pan_enable(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_enable *cmd = buf;
@@ -437,11 +531,18 @@ bool bt_pan_register(const bdaddr_t *addr)
 	err = bnep_init();
 	if (err) {
 		error("bnep init failed");
-		sdp_record_free(rec);
+		bt_adapter_remove_record(rec->handle);
+		return false;
+	}
+
+	err = register_nap_server();
+	if (err < 0) {
+		bt_adapter_remove_record(rec->handle);
+		bnep_cleanup();
 		return false;
 	}
 
-	record_id = rec->handle;
+	nap_dev.record_id = rec->handle;
 	ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
 
@@ -455,6 +556,7 @@ void bt_pan_unregister(void)
 	bnep_cleanup();
 
 	ipc_unregister(HAL_SERVICE_ID_PAN);
-	bt_adapter_remove_record(record_id);
-	record_id = 0;
+	bt_adapter_remove_record(nap_dev.record_id);
+	nap_dev.record_id = 0;
+	destroy_nap_device();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v6 0/4] Add support for NAP role
From: Ravi kumar Veeramally @ 2014-01-10 13:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

v6: Fixed Szymon's comments (use snprintf and defines).

v5: Fixed Szymon's comments and added his fix (crash when bridge create
    fails).

v4: Fixed Szymon's and Luiz's comments.

v3: Fixed Johan's comments (removed fopen, fprintf and used open and write).

v2: Fixed Johan's comments.

v1: This patch set add support for NAP role. It register NAP server and create
  bnep bridge and listen for incoming connections from client devices.
  On incoming connection request it accepts connection, creates bnep interface
  and notifies control state and connection state infromation. Removes device
  on disconnect request. Android related changes are required to enable this
  role. Patches sent to respective ML.

Ravi kumar Veeramally (4):
  android/pan: Register Network Access Point
  android/pan: Listen for incoming connections and accept in NAP role
  android/pan: Implement PAN enable HAL api at daemon side
  android/pan: Remove connected PAN devices on profile unregister call

 android/pan.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 325 insertions(+), 12 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* Re: [PATCH v4] Bluetooth: Add hci_h4p driver
From: Sebastian Reichel @ 2014-01-10 13:44 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Marcel Holtmann, Pali Rohár,
	Ивайло Димитров,
	Gustavo F. Padovan, Johan Hedberg, linux-kernel,
	linux-bluetooth@vger.kernel.org development, Ville Tervo
In-Reply-To: <20140110121805.GA21117@amd.pavel.ucw.cz>

[-- Attachment #1: Type: text/plain, Size: 6143 bytes --]

Hi Pavel,

You have missed some things. See inline comments below.

On Fri, Jan 10, 2014 at 01:18:05PM +0100, Pavel Machek wrote:
> diff --git a/drivers/bluetooth/nokia_core.c b/drivers/bluetooth/nokia_core.c
> index 5c7acad..d6b0701 100644
> --- a/drivers/bluetooth/nokia_core.c
> v+++ b/drivers/bluetooth/nokia_core.c
> @@ -39,6 +39,7 @@
>  #include <linux/gpio.h>
>  #include <linux/timer.h>
>  #include <linux/kthread.h>
> +#include <linux/io.h>
>  
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
> @@ -1079,7 +1080,7 @@ static int hci_h4p_probe(struct platform_device *pdev)
>  	int err;
>  
>  	dev_info(&pdev->dev, "Registering HCI H4P device\n");
> -	info = kzalloc(sizeof(struct hci_h4p_info), GFP_KERNEL);
> +	info = devm_kzalloc(&pdev->dev, sizeof(struct hci_h4p_info), GFP_KERNEL);
>  	if (!info)
>  		return -ENOMEM;
>  
> @@ -1092,7 +1093,6 @@ static int hci_h4p_probe(struct platform_device *pdev)
>  
>  	if (pdev->dev.platform_data == NULL) {
>  		dev_err(&pdev->dev, "Could not get Bluetooth config data\n");
> -		kfree(info);
>  		return -ENODATA;
>  	}
>  
> @@ -1113,67 +1113,59 @@ static int hci_h4p_probe(struct platform_device *pdev)
>  	complete_all(&info->test_completion);
>  
>  	if (!info->reset_gpio_shared) {
> -		err = gpio_request(info->reset_gpio, "bt_reset");
> +		err = devm_gpio_request_one(&pdev->dev, info->reset_gpio,
> +					    GPIOF_OUT_INIT_LOW, "bt_reset");
>  		if (err < 0) {
>  			dev_err(&pdev->dev, "Cannot get GPIO line %d\n",
>  				info->reset_gpio);
> -			goto cleanup_setup;
> +			return err;
>  		}
>  	}
>  
> -	err = gpio_request(info->bt_wakeup_gpio, "bt_wakeup");
> +	err = devm_gpio_request_one(&pdev->dev, info->bt_wakeup_gpio,
> +				    GPIOF_OUT_INIT_LOW, "bt_wakeup");
> +
>  	if (err < 0) {
>  		dev_err(info->dev, "Cannot get GPIO line 0x%d",
>  			info->bt_wakeup_gpio);
> -		if (!info->reset_gpio_shared)
> -			gpio_free(info->reset_gpio);
> -		goto cleanup_setup;
> +		return err;
>  	}
>  
> -	err = gpio_request(info->host_wakeup_gpio, "host_wakeup");
> +	err = devm_gpio_request_one(&pdev->dev, info->host_wakeup_gpio,
> +				    GPIOF_DIR_IN, "host_wakeup");
>  	if (err < 0) {
>  		dev_err(info->dev, "Cannot get GPIO line %d",
>  		       info->host_wakeup_gpio);
> -		if (!info->reset_gpio_shared)
> -			gpio_free(info->reset_gpio);
> -		gpio_free(info->bt_wakeup_gpio);
> -		goto cleanup_setup;
> +		return err;
>  	}
>  
> -	gpio_direction_output(info->reset_gpio, 0);
> -	gpio_direction_output(info->bt_wakeup_gpio, 0);
> -	gpio_direction_input(info->host_wakeup_gpio);
> -
>  	info->irq = bt_plat_data->uart_irq;
> -	info->uart_base = ioremap(bt_plat_data->uart_base, SZ_2K);
> -	info->uart_iclk = clk_get(NULL, bt_plat_data->uart_iclk);
> -	info->uart_fclk = clk_get(NULL, bt_plat_data->uart_fclk);
> +	info->uart_base = devm_ioremap(&pdev->dev, bt_plat_data->uart_base, SZ_2K);
> +	info->uart_iclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_iclk);
> +	info->uart_fclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_fclk);
>  
>  	err = request_irq(info->irq, hci_h4p_interrupt, IRQF_DISABLED, "hci_h4p",
>  			  info);

This one should also use devm_request_irq(). Especially since you
removed the cleanup in the probe function already ;)

>  	if (err < 0) {
>  		dev_err(info->dev, "hci_h4p: unable to get IRQ %d\n", info->irq);
> -		goto cleanup;
> +		return err;
>  	}
>  
> -	err = request_irq(gpio_to_irq(info->host_wakeup_gpio),
> +	err = devm_request_irq(&pdev->dev, gpio_to_irq(info->host_wakeup_gpio),
>  			  hci_h4p_wakeup_interrupt,  IRQF_TRIGGER_FALLING |
>  			  IRQF_TRIGGER_RISING | IRQF_DISABLED,
>  			  "hci_h4p_wkup", info);
>  	if (err < 0) {
>  		dev_err(info->dev, "hci_h4p: unable to get wakeup IRQ %d\n",
>  			  gpio_to_irq(info->host_wakeup_gpio));
> -		free_irq(info->irq, info);
> -		goto cleanup;
> +		return err;
>  	}
>  
>  	err = irq_set_irq_wake(gpio_to_irq(info->host_wakeup_gpio), 1);
>  	if (err < 0) {
>  		dev_err(info->dev, "hci_h4p: unable to set wakeup for IRQ %d\n",
>  				gpio_to_irq(info->host_wakeup_gpio));
> -		free_irq(info->irq, info);
> -		free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
> -		goto cleanup;
> +		return err;
>  	}
>  
>  	init_timer_deferrable(&info->lazy_release);
> @@ -1182,7 +1174,7 @@ static int hci_h4p_probe(struct platform_device *pdev)
>  	hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
>  	err = hci_h4p_reset_uart(info);
>  	if (err < 0)
> -		goto cleanup_irq;
> +		return err;
>  	gpio_set_value(info->reset_gpio, 0);
>  	hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
>  
> @@ -1190,23 +1182,10 @@ static int hci_h4p_probe(struct platform_device *pdev)
>  
>  	if (hci_h4p_register_hdev(info) < 0) {
>  		dev_err(info->dev, "failed to register hci_h4p hci device\n");
> -		goto cleanup_irq;
> +		return -EINVAL;
>  	}
>  
>  	return 0;
> -
> -cleanup_irq:
> -	free_irq(info->irq, (void *)info);
> -	free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
> -cleanup:
> -	gpio_set_value(info->reset_gpio, 0);
> -	if (!info->reset_gpio_shared)
> -		gpio_free(info->reset_gpio);
> -	gpio_free(info->bt_wakeup_gpio);
> -	gpio_free(info->host_wakeup_gpio);
> -cleanup_setup:
> -	kfree(info);
> -	return err;
>  }
>  
>  static int hci_h4p_remove(struct platform_device *pdev)
> @@ -1217,15 +1196,11 @@ static int hci_h4p_remove(struct platform_device *pdev)
>  
>  	hci_h4p_sysfs_remove_files(info->dev);
>  	hci_h4p_hci_close(info->hdev);
> -	free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
>  	hci_unregister_dev(info->hdev);
>  	hci_free_dev(info->hdev);
> -	if (!info->reset_gpio_shared)
> -		gpio_free(info->reset_gpio);
>  	gpio_free(info->bt_wakeup_gpio);
>  	gpio_free(info->host_wakeup_gpio);

those two gpios are also managed. No need to free them manually.

>  	free_irq(info->irq, (void *) info);

Once this irq is also requested using managed resources you can also
drop this line.

> -	kfree(info);
>  
>  	return 0;
>  }
> [...]

-- Sebastian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH BlueZ 1/3] android: Convert libaudio-internal to a plugin
From: Luiz Augusto von Dentz @ 2014-01-10 13:39 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org
In-Reply-To: <1389356048-4333-1-git-send-email-luiz.dentz@gmail.com>

Hi,

On Fri, Jan 10, 2014 at 2:14 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This convert the static library libaudio-internal.la to
> audio.a2dp.default.so when building with autotools.
> ---
>  android/Makefile.am | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/android/Makefile.am b/android/Makefile.am
> index 0a32a95..97173db 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -114,18 +114,19 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la \
>
>  android_android_tester_LDFLAGS = -pthread
>
> -noinst_LTLIBRARIES += android/libaudio-internal.la
> +plugin_LTLIBRARIES += android/audio.a2dp.default.la
>
> -android_libaudio_internal_la_SOURCES = android/audio-msg.h \
> +android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
>                                         android/hal-audio.c \
>                                         android/hardware/audio.h \
>                                         android/hardware/audio_effect.h \
>                                         android/hardware/hardware.h \
>                                         android/system/audio.h
>
> -android_libaudio_internal_la_CFLAGS = -I$(srcdir)/android
> +android_audio_a2dp_default_la_CFLAGS = -I$(srcdir)/android
>
> -android_libaudio_internal_la_LDFLAGS = -pthread
> +android_audio_a2dp_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
> +                                       -no-undefined -pthread
>
>  endif
>
> --
> 1.8.4.2

This now pushed.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH] android-tester: Add possibility to debug mgmt
From: Marcin Kraglak @ 2014-01-10 13:23 UTC (permalink / raw)
  To: linux-bluetooth

Print mgmt debug info if debug flag is set in android-tester.
---
 android/android-tester.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 0185f99..ce1cedf 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -95,6 +95,13 @@ struct test_data {
 
 static char exec_dir[PATH_MAX + 1];
 
+static void mgmt_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	tester_print("%s%s", prefix, str);
+}
+
 static void test_update_state(void)
 {
 	struct test_data *data = tester_get_data();
@@ -334,9 +341,6 @@ static void test_pre_setup(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	if (!tester_use_debug())
-		fclose(stderr);
-
 	data->mgmt = mgmt_new_default();
 	if (!data->mgmt) {
 		tester_warn("Failed to setup management interface");
@@ -344,6 +348,11 @@ static void test_pre_setup(const void *test_data)
 		return;
 	}
 
+	if (!tester_use_debug())
+		fclose(stderr);
+	else
+		mgmt_set_debug(data->mgmt, mgmt_debug, "mgmt: ", NULL);
+
 	mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
 				NULL, read_index_list_callback, NULL, NULL);
 }
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH v4] Bluetooth: Add hci_h4p driver
From: Pavel Machek @ 2014-01-10 12:18 UTC (permalink / raw)
  To: Marcel Holtmann, Pali Rohár,
	Ивайло Димитров,
	Gustavo F. Padovan, Johan Hedberg, linux-kernel,
	linux-bluetooth@vger.kernel.org development, Ville Tervo
In-Reply-To: <20140110003231.GA14141@earth.universe>

On Fri 2014-01-10 01:32:31, Sebastian Reichel wrote:
> Hi Pavel,
> 
> On Fri, Jan 10, 2014 at 12:38:43AM +0100, Pavel Machek wrote:
> > > Here are some cleanup suggestions for probe, removal & module
> > > initialization functions.
> > 
> > ...and here's the patch implementing those suggestions. Thanks!
> 
> That looks right, but you forgot to cleanup hci_h4p_remove. Also I
> suggest to simply merge this as v5.

Here it goes, now with hci_h4p_remove fixed. v5 will follow.

commit b77cc9dd6f6897183d97717cec63aaa248317f95
Author: Pavel <pavel@ucw.cz>
Date:   Fri Jan 10 13:14:45 2014 +0100

    Switch to devm_ functions to make code cleaner.
    
    Reported-by: Sebastian Reichel <sre@ring0.de>
    Signed-off-by: Pavel Machek <pavel@ucw.cz>

diff --git a/drivers/bluetooth/nokia_core.c b/drivers/bluetooth/nokia_core.c
index 5c7acad..d6b0701 100644
--- a/drivers/bluetooth/nokia_core.c
v+++ b/drivers/bluetooth/nokia_core.c
@@ -39,6 +39,7 @@
 #include <linux/gpio.h>
 #include <linux/timer.h>
 #include <linux/kthread.h>
+#include <linux/io.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -1079,7 +1080,7 @@ static int hci_h4p_probe(struct platform_device *pdev)
 	int err;
 
 	dev_info(&pdev->dev, "Registering HCI H4P device\n");
-	info = kzalloc(sizeof(struct hci_h4p_info), GFP_KERNEL);
+	info = devm_kzalloc(&pdev->dev, sizeof(struct hci_h4p_info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -1092,7 +1093,6 @@ static int hci_h4p_probe(struct platform_device *pdev)
 
 	if (pdev->dev.platform_data == NULL) {
 		dev_err(&pdev->dev, "Could not get Bluetooth config data\n");
-		kfree(info);
 		return -ENODATA;
 	}
 
@@ -1113,67 +1113,59 @@ static int hci_h4p_probe(struct platform_device *pdev)
 	complete_all(&info->test_completion);
 
 	if (!info->reset_gpio_shared) {
-		err = gpio_request(info->reset_gpio, "bt_reset");
+		err = devm_gpio_request_one(&pdev->dev, info->reset_gpio,
+					    GPIOF_OUT_INIT_LOW, "bt_reset");
 		if (err < 0) {
 			dev_err(&pdev->dev, "Cannot get GPIO line %d\n",
 				info->reset_gpio);
-			goto cleanup_setup;
+			return err;
 		}
 	}
 
-	err = gpio_request(info->bt_wakeup_gpio, "bt_wakeup");
+	err = devm_gpio_request_one(&pdev->dev, info->bt_wakeup_gpio,
+				    GPIOF_OUT_INIT_LOW, "bt_wakeup");
+
 	if (err < 0) {
 		dev_err(info->dev, "Cannot get GPIO line 0x%d",
 			info->bt_wakeup_gpio);
-		if (!info->reset_gpio_shared)
-			gpio_free(info->reset_gpio);
-		goto cleanup_setup;
+		return err;
 	}
 
-	err = gpio_request(info->host_wakeup_gpio, "host_wakeup");
+	err = devm_gpio_request_one(&pdev->dev, info->host_wakeup_gpio,
+				    GPIOF_DIR_IN, "host_wakeup");
 	if (err < 0) {
 		dev_err(info->dev, "Cannot get GPIO line %d",
 		       info->host_wakeup_gpio);
-		if (!info->reset_gpio_shared)
-			gpio_free(info->reset_gpio);
-		gpio_free(info->bt_wakeup_gpio);
-		goto cleanup_setup;
+		return err;
 	}
 
-	gpio_direction_output(info->reset_gpio, 0);
-	gpio_direction_output(info->bt_wakeup_gpio, 0);
-	gpio_direction_input(info->host_wakeup_gpio);
-
 	info->irq = bt_plat_data->uart_irq;
-	info->uart_base = ioremap(bt_plat_data->uart_base, SZ_2K);
-	info->uart_iclk = clk_get(NULL, bt_plat_data->uart_iclk);
-	info->uart_fclk = clk_get(NULL, bt_plat_data->uart_fclk);
+	info->uart_base = devm_ioremap(&pdev->dev, bt_plat_data->uart_base, SZ_2K);
+	info->uart_iclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_iclk);
+	info->uart_fclk = devm_clk_get(&pdev->dev, bt_plat_data->uart_fclk);
 
 	err = request_irq(info->irq, hci_h4p_interrupt, IRQF_DISABLED, "hci_h4p",
 			  info);
 	if (err < 0) {
 		dev_err(info->dev, "hci_h4p: unable to get IRQ %d\n", info->irq);
-		goto cleanup;
+		return err;
 	}
 
-	err = request_irq(gpio_to_irq(info->host_wakeup_gpio),
+	err = devm_request_irq(&pdev->dev, gpio_to_irq(info->host_wakeup_gpio),
 			  hci_h4p_wakeup_interrupt,  IRQF_TRIGGER_FALLING |
 			  IRQF_TRIGGER_RISING | IRQF_DISABLED,
 			  "hci_h4p_wkup", info);
 	if (err < 0) {
 		dev_err(info->dev, "hci_h4p: unable to get wakeup IRQ %d\n",
 			  gpio_to_irq(info->host_wakeup_gpio));
-		free_irq(info->irq, info);
-		goto cleanup;
+		return err;
 	}
 
 	err = irq_set_irq_wake(gpio_to_irq(info->host_wakeup_gpio), 1);
 	if (err < 0) {
 		dev_err(info->dev, "hci_h4p: unable to set wakeup for IRQ %d\n",
 				gpio_to_irq(info->host_wakeup_gpio));
-		free_irq(info->irq, info);
-		free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
-		goto cleanup;
+		return err;
 	}
 
 	init_timer_deferrable(&info->lazy_release);
@@ -1182,7 +1174,7 @@ static int hci_h4p_probe(struct platform_device *pdev)
 	hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
 	err = hci_h4p_reset_uart(info);
 	if (err < 0)
-		goto cleanup_irq;
+		return err;
 	gpio_set_value(info->reset_gpio, 0);
 	hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
 
@@ -1190,23 +1182,10 @@ static int hci_h4p_probe(struct platform_device *pdev)
 
 	if (hci_h4p_register_hdev(info) < 0) {
 		dev_err(info->dev, "failed to register hci_h4p hci device\n");
-		goto cleanup_irq;
+		return -EINVAL;
 	}
 
 	return 0;
-
-cleanup_irq:
-	free_irq(info->irq, (void *)info);
-	free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
-cleanup:
-	gpio_set_value(info->reset_gpio, 0);
-	if (!info->reset_gpio_shared)
-		gpio_free(info->reset_gpio);
-	gpio_free(info->bt_wakeup_gpio);
-	gpio_free(info->host_wakeup_gpio);
-cleanup_setup:
-	kfree(info);
-	return err;
 }
 
 static int hci_h4p_remove(struct platform_device *pdev)
@@ -1217,15 +1196,11 @@ static int hci_h4p_remove(struct platform_device *pdev)
 
 	hci_h4p_sysfs_remove_files(info->dev);
 	hci_h4p_hci_close(info->hdev);
-	free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
 	hci_unregister_dev(info->hdev);
 	hci_free_dev(info->hdev);
-	if (!info->reset_gpio_shared)
-		gpio_free(info->reset_gpio);
 	gpio_free(info->bt_wakeup_gpio);
 	gpio_free(info->host_wakeup_gpio);
 	free_irq(info->irq, (void *) info);
-	kfree(info);
 
 	return 0;
 }
@@ -1238,25 +1213,7 @@ static struct platform_driver hci_h4p_driver = {
 	},
 };
 
-static int __init hci_h4p_init(void)
-{
-	int err = 0;
-
-	/* Register the driver with LDM */
-	err = platform_driver_register(&hci_h4p_driver);
-	if (err < 0)
-		printk(KERN_WARNING "failed to register hci_h4p driver\n");
-
-	return err;
-}
-
-static void __exit hci_h4p_exit(void)
-{
-	platform_driver_unregister(&hci_h4p_driver);
-}
-
-module_init(hci_h4p_init);
-module_exit(hci_h4p_exit);
+module_platform_driver(hci_h4p_driver);
 
 MODULE_ALIAS("platform:hci_h4p");
 MODULE_DESCRIPTION("Bluetooth h4 driver with nokia extensions");





-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* [PATCH BlueZ 3/3] android: Load bluetooth.default.so as a module
From: Luiz Augusto von Dentz @ 2014-01-10 12:14 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389356048-4333-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This makes haltest and android-tester to load bluetooth.default.so
instead of linking directly to it.
---
 android/Makefile.am         |  26 +++++-----
 android/hardware/hardware.c | 124 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+), 12 deletions(-)
 create mode 100644 android/hardware/hardware.c

diff --git a/android/Makefile.am b/android/Makefile.am
index 4b843b2..f5e8c99 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -1,4 +1,6 @@
 if ANDROID
+android_plugindir = $(abs_top_srcdir)/android/.libs
+
 noinst_PROGRAMS += android/system-emulator
 
 android_system_emulator_SOURCES = android/system-emulator.c \
@@ -61,7 +63,8 @@ android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
 					android/hardware/hardware.h \
 					android/cutils/properties.h \
 					android/hal-log.h \
-					android/hal-ipc.h android/hal-ipc.c
+					android/hal-ipc.h android/hal-ipc.c \
+					android/hal-utils.h android/hal-utils.c
 
 android_bluetooth_default_la_CPPFLAGS = -I$(srcdir)/android \
 					-DPLATFORM_SDK_VERSION=19
@@ -86,15 +89,14 @@ android_haltest_SOURCES = android/client/haltest.c \
 				android/client/if-hh.c \
 				android/client/if-pan.c \
 				android/client/if-sock.c \
-				android/client/hwmodule.c \
+				android/hardware/hardware.c \
 				android/hal-utils.h android/hal-utils.c
 
-android_haltest_LDADD = android/bluetooth.default.la
-
 android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android \
-				-DPLATFORM_SDK_VERSION=19
+				-DPLATFORM_SDK_VERSION=19 \
+				-DPLUGINDIR=\""$(android_plugindir)"\"
 
-android_haltest_LDFLAGS = -pthread
+android_haltest_LDFLAGS = -pthread -ldl
 
 noinst_PROGRAMS += android/android-tester
 
@@ -106,15 +108,15 @@ android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
 				src/shared/mgmt.h src/shared/mgmt.c \
 				src/shared/hciemu.h src/shared/hciemu.c \
 				src/shared/tester.h src/shared/tester.c \
-				android/hal-utils.h android/hal-utils.c \
-				android/client/hwmodule.c android/android-tester.c
+				android/hardware/hardware.c \
+				android/android-tester.c
 
-android_android_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+android_android_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android \
+				-DPLUGINDIR=\""$(android_plugindir)"\"
 
-android_android_tester_LDADD = lib/libbluetooth-internal.la \
-				android/bluetooth.default.la @GLIB_LIBS@
+android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
-android_android_tester_LDFLAGS = -pthread
+android_android_tester_LDFLAGS = -pthread -ldl
 
 plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
diff --git a/android/hardware/hardware.c b/android/hardware/hardware.c
new file mode 100644
index 0000000..4bd5eba
--- /dev/null
+++ b/android/hardware/hardware.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hardware/hardware.h>
+
+#include <dlfcn.h>
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+
+#define LOG_TAG "HAL"
+
+#define LOG_INFO " I"
+#define LOG_WARN " W"
+#define LOG_ERROR " E"
+#define LOG_DEBUG " D"
+#define ALOG(pri, tag, fmt, arg...) fprintf(stderr, tag pri": " fmt"\n", ##arg)
+
+#define info(fmt, arg...) ALOG(LOG_INFO, LOG_TAG, fmt, ##arg)
+#define warn(fmt, arg...) ALOG(LOG_WARN, LOG_TAG, fmt, ##arg)
+#define error(fmt, arg...) ALOG(LOG_ERROR, LOG_TAG, fmt, ##arg)
+
+/**
+ * Load the file defined by the variant and if successful
+ * return the dlopen handle and the hmi.
+ * @return 0 = success, !0 = failure.
+ */
+static int load(const char *id,
+        const char *path,
+        const struct hw_module_t **pHmi)
+{
+    int status;
+    void *handle;
+    struct hw_module_t *hmi;
+    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
+
+    /*
+     * load the symbols resolving undefined symbols before
+     * dlopen returns. Since RTLD_GLOBAL is not or'd in with
+     * RTLD_NOW the external symbols will not be global
+     */
+    handle = dlopen(path, RTLD_NOW);
+    if (handle == NULL) {
+        char const *err_str = dlerror();
+        error("load: module=%s\n%s", path, err_str?err_str:"unknown");
+        status = -EINVAL;
+        goto done;
+    }
+
+    /* Get the address of the struct hal_module_info. */
+    hmi = (struct hw_module_t *)dlsym(handle, sym);
+    if (hmi == NULL) {
+        error("load: couldn't find symbol %s", sym);
+        status = -EINVAL;
+        goto done;
+    }
+
+    /* Check that the id matches */
+    if (strcmp(id, hmi->id) != 0) {
+        error("load: id=%s != hmi->id=%s", id, hmi->id);
+        status = -EINVAL;
+        goto done;
+    }
+
+    hmi->dso = handle;
+
+    *pHmi = hmi;
+
+    info("loaded HAL id=%s path=%s hmi=%p handle=%p",
+                id, path, *pHmi, handle);
+
+    return 0;
+
+done:
+    hmi = NULL;
+    if (handle != NULL) {
+        dlclose(handle);
+        handle = NULL;
+    }
+
+    return status;
+}
+
+int hw_get_module_by_class(const char *class_id, const char *inst,
+                           const struct hw_module_t **module)
+{
+    char path[PATH_MAX];
+    char name[PATH_MAX];
+
+    if (inst)
+        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
+    else
+        snprintf(name, PATH_MAX, "%s", class_id);
+
+    /*
+     * Here we rely on the fact that calling dlopen multiple times on
+     * the same .so will simply increment a refcount (and not load
+     * a new copy of the library).
+     * We also assume that dlopen() is thread-safe.
+     */
+    snprintf(path, sizeof(path), "%s/%s.default.so", PLUGINDIR, name);
+
+    return load(class_id, path, module);
+}
+
+int hw_get_module(const char *id, const struct hw_module_t **module)
+{
+    return hw_get_module_by_class(id, NULL, module);
+}
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH BlueZ 2/3] android: Convert libhal-internal to a plugin
From: Luiz Augusto von Dentz @ 2014-01-10 12:14 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389356048-4333-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This convert the static library libhal-internal.la to
bluetooth.default.la when building with autotools.
---
 android/Makefile.am | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/android/Makefile.am b/android/Makefile.am
index 97173db..4b843b2 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -39,9 +39,9 @@ android_bluetoothd_SOURCES = android/main.c \
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
-noinst_LTLIBRARIES += android/libhal-internal.la
+plugin_LTLIBRARIES += android/bluetooth.default.la
 
-android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
+android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
 					android/hal-sock.c \
 					android/hal-hidhost.c \
 					android/hal-pan.c \
@@ -63,8 +63,10 @@ android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
 					android/hal-log.h \
 					android/hal-ipc.h android/hal-ipc.c
 
-android_libhal_internal_la_CPPFLAGS = -I$(srcdir)/android \
+android_bluetooth_default_la_CPPFLAGS = -I$(srcdir)/android \
 					-DPLATFORM_SDK_VERSION=19
+android_bluetooth_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
+					-no-undefined
 
 noinst_PROGRAMS += android/haltest
 
@@ -87,7 +89,7 @@ android_haltest_SOURCES = android/client/haltest.c \
 				android/client/hwmodule.c \
 				android/hal-utils.h android/hal-utils.c
 
-android_haltest_LDADD = android/libhal-internal.la
+android_haltest_LDADD = android/bluetooth.default.la
 
 android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android \
 				-DPLATFORM_SDK_VERSION=19
@@ -110,7 +112,7 @@ android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
 android_android_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
 
 android_android_tester_LDADD = lib/libbluetooth-internal.la \
-				android/libhal-internal.la @GLIB_LIBS@
+				android/bluetooth.default.la @GLIB_LIBS@
 
 android_android_tester_LDFLAGS = -pthread
 
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH BlueZ 1/3] android: Convert libaudio-internal to a plugin
From: Luiz Augusto von Dentz @ 2014-01-10 12:14 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This convert the static library libaudio-internal.la to
audio.a2dp.default.so when building with autotools.
---
 android/Makefile.am | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/android/Makefile.am b/android/Makefile.am
index 0a32a95..97173db 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -114,18 +114,19 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la \
 
 android_android_tester_LDFLAGS = -pthread
 
-noinst_LTLIBRARIES += android/libaudio-internal.la
+plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
-android_libaudio_internal_la_SOURCES = android/audio-msg.h \
+android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
 					android/hal-audio.c \
 					android/hardware/audio.h \
 					android/hardware/audio_effect.h \
 					android/hardware/hardware.h \
 					android/system/audio.h
 
-android_libaudio_internal_la_CFLAGS = -I$(srcdir)/android
+android_audio_a2dp_default_la_CFLAGS = -I$(srcdir)/android
 
-android_libaudio_internal_la_LDFLAGS = -pthread
+android_audio_a2dp_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
+					-no-undefined -pthread
 
 endif
 
-- 
1.8.4.2


^ permalink raw reply related

* Re: [PATCH] android/pts: Add PTS test results for L2CAP
From: Szymon Janc @ 2014-01-10 12:02 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1389354460-7297-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Friday 10 of January 2014 13:47:40 Sebastian Chlad wrote:
> ---
>  android/pts-l2cap.txt | 128 +++++++++++++++++++++++++-------------------------
>  1 file changed, 64 insertions(+), 64 deletions(-)
> 
> diff --git a/android/pts-l2cap.txt b/android/pts-l2cap.txt
> index d293046..51eedf5 100644
> --- a/android/pts-l2cap.txt
> +++ b/android/pts-l2cap.txt
> @@ -1,7 +1,7 @@
>  PTS test results for L2CAP
>  
>  PTS version: 5.0
> -Tested: 18.12.2013
> +Tested: 10.01.2014
>  
>  Results:
>  PASS   test passed
> @@ -12,21 +12,21 @@ N/A    test is disabled due to PICS setup
>  -------------------------------------------------------------------------------
>  Test Name              Result  Notes
>  -------------------------------------------------------------------------------
> -TC_COS_CED_BV_01_C     PASS
> +TC_COS_CED_BV_01_C     PASS    l2test -n -P 33 <bdaddr>
>  TC_COS_CED_BV_03_C     PASS
>  TC_COS_CED_BV_04_C     N/A
>  TC_COS_CED_BV_05_C     PASS
>  TC_COS_CED_BV_07_C     PASS
>  TC_COS_CED_BV_08_C     PASS
> -TC_COS_CED_BV_09_C     INC
> +TC_COS_CED_BV_09_C     PASS
>  TC_COS_CED_BV_10_C     N/A
>  TC_COS_CED_BV_11_C     PASS
>  TC_COS_CED_BI_01_C     PASS
>  TC_COS_CFD_BV_01_C     PASS
>  TC_COS_CFD_BV_02_C     PASS
>  TC_COS_CFD_BV_03_C     PASS
> -TC_COS_CFD_BV_08_C     INC
> -TC_COS_CFD_BV_09_C     INC
> +TC_COS_CFD_BV_08_C     PASS
> +TC_COS_CFD_BV_09_C     PASS
>  TC_COS_CFD_BV_10_C     N/A
>  TC_COS_CFD_BI_11_C     PASS
>  TC_COS_CFD_BV_12_C     PASS
> @@ -34,7 +34,7 @@ TC_COS_CFD_BV_13_C     N/A
>  TC_COS_IEX_BV_01_C     PASS
>  TC_COS_IEX_BV_02_C     PASS
>  TC_COS_ECH_BV_01_C     PASS
> -TC_COS_ECH_BV_02_C     INC
> +TC_COS_ECH_BV_02_C     PASS
>  TC_CLS_CLR_BV_01_C     N/A
>  TC_CLS_UCD_BV_01_C     N/A
>  TC_CLS_UCD_BV_02_C     N/A
> @@ -45,75 +45,75 @@ TC_EXF_BV_03_C         PASS
>  TC_EXF_BV_04_C         N/A
>  TC_EXF_BV_05_C         PASS
>  TC_EXF_BV_06_C         N/A
> -TC_CMC_BV_01_C         INC
> -TC_CMC_BV_02_C         INC
> -TC_CMC_BV_03_C         INC
> -TC_CMC_BV_04_C         INC
> -TC_CMC_BV_05_C         INC
> -TC_CMC_BV_06_C         INC
> -TC_CMC_BV_07_C         INC
> -TC_CMC_BV_08_C         INC
> -TC_CMC_BV_09_C         INC
> -TC_CMC_BV_10_C         INC
> -TC_CMC_BV_11_C         INC
> -TC_CMC_BV_12_C         INC
> -TC_CMC_BV_13_C         INC
> -TC_CMC_BV_14_C         INC
> -TC_CMC_BV_15_C         INC
> -TC_CMC_BI_01_C         INC
> -TC_CMC_BI_02_C         INC
> -TC_CMC_BI_03_C         INC
> -TC_CMC_BI_04_C         INC
> -TC_CMC_BI_05_C         INC
> -TC_CMC_BI_06_C         INC
> -TC_FOC_BV_01_C         INC
> -TC_FOC_BV_02_C         INC
> -TC_FOC_BV_03_C         INC
> -TC_FOC_BV_04_C         INC
> -TC_OFS_BV_01_C         INC
> -TC_OFS_BV_02_C         INC
> -TC_OFS_BV_03_C         INC
> -TC_OFS_BV_04_C         INC
> -TC_OFS_BV_05_C         INC
> -TC_OFS_BV_06_C         INC
> -TC_OFS_BV_07_C         INC
> -TC_OFS_BV_08_C         INC
> -TC_ERM_BV_01_C         INC
> -TC_ERM_BV_02_C         INC
> -TC_ERM_BV_03_C         INC
> -TC_ERM_BV_04_C         INC
> -TC_ERM_BV_05_C         INC
> -TC_ERM_BV_06_C         INC
> -TC_ERM_BV_07_C         INC
> -TC_ERM_BV_08_C         INC
> -TC_ERM_BV_09_C         INC
> +TC_CMC_BV_01_C         PASS    l2test -X ertm -P 33 <bdaddr>
> +TC_CMC_BV_02_C         PASS    l2test -X ertm -P 33 <bdaddr>
> +TC_CMC_BV_03_C         PASS    l2test -X ertm -P 33 <bdaddr>
> +TC_CMC_BV_04_C         PASS    l2test -X streaming -P 33 <bdaddr>
> +TC_CMC_BV_05_C         PASS    l2test -X streaming -P 33 <bdaddr>
> +TC_CMC_BV_06_C         PASS    l2test -X streaming -P 33 <bdaddr>
> +TC_CMC_BV_07_C         PASS    l2test -X basic -P 33 <bdaddr>
> +TC_CMC_BV_08_C         PASS    l2test -X basic -P 33 <bdaddr>
> +TC_CMC_BV_09_C         PASS    l2test -X streaming -P 33 <bdaddr>
> +TC_CMC_BV_10_C         PASS    l2test -n <bdaddr>
> +TC_CMC_BV_11_C         PASS    l2test -n <bdaddr>
> +TC_CMC_BV_12_C         PASS    l2test -n -X ertm -P 33 <bdaddr>
> +TC_CMC_BV_13_C         PASS    l2test -s -X streaming -P 33 <bdaddr>
> +TC_CMC_BV_14_C         PASS    l2test -X streaming -P 33 <bdaddr>
> +TC_CMC_BV_15_C         PASS    l2test -X streaming -P 33 <bdaddr>
> +TC_CMC_BI_01_C         PASS
> +TC_CMC_BI_02_C         PASS
> +TC_CMC_BI_03_C         PASS
> +TC_CMC_BI_04_C         PASS
> +TC_CMC_BI_05_C         PASS
> +TC_CMC_BI_06_C         PASS
> +TC_FOC_BV_01_C         PASS    l2test -X ertm -P 33 -F 0 &
> +TC_FOC_BV_02_C         PASS    l2test -X ertm -P 33 -F 0 &
> +TC_FOC_BV_03_C         PASS    l2test -X ertm -P 33 -F 0 &
> +TC_FOC_BV_04_C         PASS    l2test -n -X ertm -P <bdaddr> &
> +TC_OFS_BV_01_C         PASS
> +TC_OFS_BV_02_C         PASS    l2test -X ertm -P 33 -F 0 &
> +TC_OFS_BV_03_C         PASS
> +TC_OFS_BV_04_C         PASS
> +TC_OFS_BV_05_C         PASS    l2test -X ertm -P 33 -F 0 &
> +TC_OFS_BV_06_C         PASS    l2test -X ertm -P 33 -F 0 &
> +TC_OFS_BV_07_C         PASS
> +TC_OFS_BV_08_C         PASS
> +TC_ERM_BV_01_C         PASS    l2test -X ertm -P 33 -B -Y 3 &
> +TC_ERM_BV_02_C         PASS    l2test -X ertm -P 33 &
> +TC_ERM_BV_03_C         PASS    l2test -X ertm -P 33 &
> +TC_ERM_BV_04_C         PASS    l2test -X ertm -P 33 -B &
> +TC_ERM_BV_05_C         PASS
> +TC_ERM_BV_06_C         PASS
> +TC_ERM_BV_07_C         PASS    l2test -X ertm -P 33 &
> +TC_ERM_BV_08_C         PASS
> +TC_ERM_BV_09_C         PASS    l2test -X ertm -P 33 &
>  TC_ERM_BV_10_C         INC
>  TC_ERM_BV_11_C         INC
>  TC_ERM_BV_12_C         INC
> -TC_ERM_BV_13_C         INC
> -TC_ERM_BV_14_C         INC
> -TC_ERM_BV_15_C         INC
> -TC_ERM_BV_16_C         INC
> -TC_ERM_BV_17_C         INC
> +TC_ERM_BV_13_C         PASS
> +TC_ERM_BV_14_C         PASS
> +TC_ERM_BV_15_C         PASS
> +TC_ERM_BV_16_C         PASS
> +TC_ERM_BV_17_C         PASS
>  TC_ERM_BV_18_C         INC
>  TC_ERM_BV_19_C         INC
> -TC_ERM_BV_20_C         INC
> -TC_ERM_BV_21_C         INC
> -TC_ERM_BV_22_C         INC
> -TC_ERM_BV_23_C         INC
> -TC_ERM_BI_01_C         INC
> -TC_ERM_BI_02_C         INC
> -TC_ERM_BI_03_C         INC
> -TC_ERM_BI_04_C         INC
> -TC_ERM_BI_05_C         INC
> +TC_ERM_BV_20_C         PASS
> +TC_ERM_BV_21_C         PASS
> +TC_ERM_BV_22_C         PASS
> +TC_ERM_BV_23_C         PASS
> +TC_ERM_BI_01_C         PASS
> +TC_ERM_BI_02_C         PASS
> +TC_ERM_BI_03_C         PASS
> +TC_ERM_BI_04_C         PASS
> +TC_ERM_BI_05_C         PASS
>  TC_STM_BV_01_C         INC
>  TC_STM_BV_02_C         INC
>  TC_STM_BV_03_C         INC
>  TC_STM_BV_11_C         N/A
>  TC_STM_BV_12_C         N/A
>  TC_STM_BV_13_C         N/A
> -TC_FIX_BV_01_C         PASS
> -TC_FIX_BV_02_C         PASS
> +TC_FIX_BV_01_C         PASS    l2test -n -P 33 <bdaddr>
> +TC_FIX_BV_02_C         N/A
>  TC_EWC_BV_01_C         N/A
>  TC_EWC_BV_02_C         N/A
>  TC_EWC_BV_03_C         N/A
> 

Applied, thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* [PATCH_v5 4/4] android/pan: Remove connected PAN devices on profile unregister call
From: Ravi kumar Veeramally @ 2014-01-10 11:52 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389354776-18098-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/android/pan.c b/android/pan.c
index a733d22..8ea07a4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -750,10 +750,20 @@ bool bt_pan_register(const bdaddr_t *addr)
 	return true;
 }
 
+static void pan_device_disconnected(gpointer data, gpointer user_data)
+{
+	struct pan_device *dev = data;
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
 void bt_pan_unregister(void)
 {
 	DBG("");
 
+	g_slist_foreach(devices, pan_device_disconnected, NULL);
+	devices = NULL;
+
 	bnep_cleanup();
 
 	ipc_unregister(HAL_SERVICE_ID_PAN);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v5 3/4] android/pan: Implement PAN enable HAL api at daemon side
From: Ravi kumar Veeramally @ 2014-01-10 11:52 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389354776-18098-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/pan.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index d683945..a733d22 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -574,18 +574,40 @@ static void bt_pan_enable(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_enable *cmd = buf;
 	uint8_t status;
+	int err;
+
+	DBG("");
+
+	if (local_role == cmd->local_role) {
+		status = HAL_STATUS_SUCCESS;
+		goto reply;
+	}
+
+	/* destroy existing server */
+	destroy_nap_device();
 
 	switch (cmd->local_role) {
-	case HAL_PAN_ROLE_PANU:
 	case HAL_PAN_ROLE_NAP:
-		DBG("Not Implemented");
-		status  = HAL_STATUS_FAILED;
 		break;
+	case HAL_PAN_ROLE_NONE:
+		status = HAL_STATUS_SUCCESS;
+		goto reply;
 	default:
 		status = HAL_STATUS_UNSUPPORTED;
-		break;
+		goto reply;
 	}
 
+	local_role = cmd->local_role;
+	err = register_nap_server();
+	if (err < 0) {
+		status = HAL_STATUS_FAILED;
+		destroy_nap_device();
+		goto reply;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+reply:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v5 2/4] android/pan: Listen for incoming connections and accept in NAP role
From: Ravi kumar Veeramally @ 2014-01-10 11:52 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389354776-18098-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Listen for incoming connections and accept it. Create bnep interface
add it to bridge and notify control and connection state information
through HAL. Remove the device on disconnect request. If android
settings UI does not have bluetooth tethering enabled it immediately
sends disconnect signal.
---
 android/pan.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 182 insertions(+), 3 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index ea0e34e..d683945 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -63,12 +63,15 @@ struct pan_device {
 	uint8_t		role;
 	GIOChannel	*io;
 	struct bnep	*session;
+	guint		watch;
 };
 
 static struct {
 	uint32_t	record_id;
+	GIOChannel	*io;
 } nap_dev = {
 	.record_id = 0,
+	.io = NULL,
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -81,13 +84,19 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 
 static void pan_device_free(struct pan_device *dev)
 {
+	if (dev->watch > 0) {
+		bnep_server_delete(BNEP_BRIDGE, dev->iface, &dev->dst);
+		g_source_remove(dev->watch);
+	}
+
 	if (dev->io) {
 		g_io_channel_shutdown(dev->io, FALSE, NULL);
 		g_io_channel_unref(dev->io);
-		dev->io = NULL;
 	}
 
-	bnep_free(dev->session);
+	if (dev->session)
+		bnep_free(dev->session);
+
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
 
@@ -298,7 +307,7 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
 
 	dev = l->data;
 
-	if (dev->conn_state == HAL_PAN_STATE_CONNECTED)
+	if (dev->conn_state == HAL_PAN_STATE_CONNECTED && dev->session)
 		bnep_disconnect(dev->session);
 
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
@@ -308,6 +317,154 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
 }
 
+static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+
+	DBG("disconnected");
+
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+
+	return FALSE;
+}
+static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+	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 sk, n;
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		error("Hangup or error or inval on BNEP socket");
+		return FALSE;
+	}
+
+	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);
+		goto failed;
+	}
+
+	/* Highest known control command id BNEP_FILTER_MULT_ADDR_RSP 0x06 */
+	if (req->type == BNEP_CONTROL &&
+			req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+		error("cmd not understood");
+		bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_CMD_NOT_UNDERSTOOD,
+								req->ctrl);
+		goto failed;
+	}
+
+	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ) {
+		error("cmd is not BNEP_SETUP_CONN_REQ %02X %02X", req->type,
+								req->ctrl);
+		goto failed;
+	}
+
+	rsp = bnep_setup_decode(req, &dst_role, &src_role);
+	if (rsp) {
+		error("bnep_setup_decode failed");
+		goto failed;
+	}
+
+	rsp = bnep_setup_chk(dst_role, src_role);
+	if (rsp) {
+		error("benp_setup_chk failed");
+		goto failed;
+	}
+
+	if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
+							&dev->dst) < 0) {
+		error("server_connadd failed");
+		rsp = BNEP_CONN_NOT_ALLOWED;
+		goto failed;
+	}
+
+	rsp = BNEP_SUCCESS;
+	bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+
+	dev->watch = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+							nap_watchdog_cb, dev);
+	g_io_channel_unref(dev->io);
+	dev->io = NULL;
+
+	bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
+
+	return FALSE;
+
+failed:
+	bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+	pan_device_free(dev);
+
+	return FALSE;
+}
+
+static void nap_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+	struct pan_device *dev = user_data;
+
+	DBG("");
+
+	if (err) {
+		error("%s", err->message);
+		bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+		return;
+	}
+
+	g_io_channel_set_close_on_unref(chan, TRUE);
+	dev->watch = g_io_add_watch(chan,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				nap_setup_cb, dev);
+}
+
+static void nap_confirm_cb(GIOChannel *chan, gpointer data)
+{
+	struct pan_device *dev = NULL;
+	bdaddr_t dst;
+	char address[18];
+	GError *err = NULL;
+
+	DBG("");
+
+	bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	DBG("incoming connect request from %s", address);
+	dev = g_new0(struct pan_device, 1);
+	bacpy(&dev->dst, &dst);
+	local_role = HAL_PAN_ROLE_NAP;
+	dev->role = HAL_PAN_ROLE_PANU;
+
+	dev->io = g_io_channel_ref(chan);
+	g_io_channel_set_close_on_unref(dev->io, TRUE);
+
+	if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) {
+		error("bt_io_accept: %s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	devices = g_slist_append(devices, dev);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
+
+	return;
+
+failed:
+	g_free(dev);
+	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+}
+
 static int set_forward_delay(void)
 {
 	int fd, ret;
@@ -376,10 +533,17 @@ static void destroy_nap_device(void)
 	DBG("");
 
 	nap_remove_bridge();
+
+	if (nap_dev.io) {
+		g_io_channel_shutdown(nap_dev.io, FALSE, NULL);
+		g_io_channel_unref(nap_dev.io);
+		nap_dev.io = NULL;
+	}
 }
 
 static int register_nap_server(void)
 {
+	GError *gerr;
 	int err;
 
 	DBG("");
@@ -388,6 +552,21 @@ static int register_nap_server(void)
 	if (err < 0)
 		return err;
 
+	nap_dev.io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
+					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+					BT_IO_OPT_PSM, BNEP_PSM,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_OMTU, BNEP_MTU,
+					BT_IO_OPT_IMTU, BNEP_MTU,
+					BT_IO_OPT_INVALID);
+
+	if (!nap_dev.io) {
+		destroy_nap_device();
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v5 1/4] android/pan: Register Network Access Point
From: Ravi kumar Veeramally @ 2014-01-10 11:52 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1389354776-18098-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Register NAP server and adds bnep bridge. Removes bridge
on destroy call. Bridge mechanism is needed when device acting
as a server and listen for incoming connections.
---
 android/pan.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 107 insertions(+), 5 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 38e353d..ea0e34e 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -28,6 +28,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <glib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <linux/sockios.h>
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
@@ -45,11 +50,11 @@
 #include "bluetooth.h"
 
 #define SVC_HINT_NETWORKING 0x02
+#define BNEP_BRIDGE	"bnep"
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
 uint8_t local_role = HAL_PAN_ROLE_NONE;
-static uint32_t record_id = 0;
 
 struct pan_device {
 	char		iface[16];
@@ -60,6 +65,12 @@ struct pan_device {
 	struct bnep	*session;
 };
 
+static struct {
+	uint32_t	record_id;
+} nap_dev = {
+	.record_id = 0,
+};
+
 static int device_cmp(gconstpointer s, gconstpointer user_data)
 {
 	const struct pan_device *dev = s;
@@ -297,6 +308,89 @@ failed:
 	ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
 }
 
+static int set_forward_delay(void)
+{
+	int fd, ret;
+	char path[41];
+
+	sprintf(path, "/sys/class/net/%s/bridge/forward_delay", BNEP_BRIDGE);
+
+	fd = open(path, O_RDWR);
+	if (fd < 0)
+		return -errno;
+
+	ret = write(fd, "0", sizeof("0"));
+	close(fd);
+
+	return ret;
+}
+
+static int nap_create_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
+		err = -errno;
+		if (err != -EEXIST) {
+			close(sk);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	err = set_forward_delay();
+	if (err < 0)
+		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+
+	close(sk);
+
+	return err;
+}
+
+static int nap_remove_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+	close(sk);
+
+	if (err < 0)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static void destroy_nap_device(void)
+{
+	DBG("");
+
+	nap_remove_bridge();
+}
+
+static int register_nap_server(void)
+{
+	int err;
+
+	DBG("");
+
+	err = nap_create_bridge();
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static void bt_pan_enable(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_pan_enable *cmd = buf;
@@ -437,11 +531,18 @@ bool bt_pan_register(const bdaddr_t *addr)
 	err = bnep_init();
 	if (err) {
 		error("bnep init failed");
-		sdp_record_free(rec);
+		bt_adapter_remove_record(rec->handle);
+		return false;
+	}
+
+	err = register_nap_server();
+	if (err < 0) {
+		bt_adapter_remove_record(rec->handle);
+		bnep_cleanup();
 		return false;
 	}
 
-	record_id = rec->handle;
+	nap_dev.record_id = rec->handle;
 	ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
 
@@ -455,6 +556,7 @@ void bt_pan_unregister(void)
 	bnep_cleanup();
 
 	ipc_unregister(HAL_SERVICE_ID_PAN);
-	bt_adapter_remove_record(record_id);
-	record_id = 0;
+	bt_adapter_remove_record(nap_dev.record_id);
+	nap_dev.record_id = 0;
+	destroy_nap_device();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v5 0/4] Add support for NAP role
From: Ravi kumar Veeramally @ 2014-01-10 11:52 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

v5: Fixed Szymon's comments and added his fix (crash when bridge create
    fails).

v4: Fixed Szymon's and Luiz's comments.

v3: Fixed Johan's comments (removed fopen, fprintf and used open and write).

v2: Fixed Johan's comments.

v1: This patch set add support for NAP role. It register NAP server and create
  bnep bridge and listen for incoming connections from client devices.
  On incoming connection request it accepts connection, creates bnep interface
  and notifies control state and connection state infromation. Removes device
  on disconnect request. Android related changes are required to enable this
  role. Patches sent to respective ML.

Ravi kumar Veeramally (4):
  android/pan: Register Network Access Point
  android/pan: Listen for incoming connections and accept in NAP role
  android/pan: Implement PAN enable HAL api at daemon side
  android/pan: Remove connected PAN devices on profile unregister call

 android/pan.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 325 insertions(+), 12 deletions(-)

-- 
1.8.3.2


^ permalink raw reply


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