Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3 02/15] Bluetooth: Add HCI command definition for Secure Connections enabling
From: Marcel Holtmann @ 2014-01-10  9:29 UTC (permalink / raw)
  To: linux-bluetooth

The Secure Connections feature is optional and host stacks have to
manually enable it. This add the HCI command definiton for reading
and writing this setting.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index cd40219d32aa..2a35d273de2c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -937,6 +937,17 @@ struct hci_rp_write_sync_train_params {
 	__le16	sync_train_int;
 } __packed;
 
+#define HCI_OP_READ_SC_SUPPORT		0x0c79
+struct hci_rp_read_sc_support {
+	__u8	status;
+	__u8	support;
+} __packed;
+
+#define HCI_OP_WRITE_SC_SUPPORT		0x0c7a
+struct hci_cp_write_sc_support {
+	__u8	support;
+} __packed;
+
 #define HCI_OP_READ_LOCAL_VERSION	0x1001
 struct hci_rp_read_local_version {
 	__u8     status;
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH v3 01/15] Bluetooth: Add LMP feature definitions for Secure Connections support
From: Marcel Holtmann @ 2014-01-10  9:29 UTC (permalink / raw)
  To: linux-bluetooth

The support for Secure Connections introduces two new controller
features and one new host feature.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci.h      | 4 ++++
 include/net/bluetooth/hci_core.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 66c1cd87bfe7..cd40219d32aa 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -282,10 +282,14 @@ enum {
 #define LMP_SYNC_TRAIN	0x04
 #define LMP_SYNC_SCAN	0x08
 
+#define LMP_SC		0x01
+#define LMP_PING	0x02
+
 /* Host features */
 #define LMP_HOST_SSP		0x01
 #define LMP_HOST_LE		0x02
 #define LMP_HOST_LE_BREDR	0x04
+#define LMP_HOST_SC		0x08
 
 /* Connection modes */
 #define HCI_CM_ACTIVE	0x0000
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f2f0cf5865c4..bb984d0626b7 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -803,9 +803,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_csb_slave_capable(dev)  ((dev)->features[2][0] & LMP_CSB_SLAVE)
 #define lmp_sync_train_capable(dev) ((dev)->features[2][0] & LMP_SYNC_TRAIN)
 #define lmp_sync_scan_capable(dev)  ((dev)->features[2][0] & LMP_SYNC_SCAN)
+#define lmp_sc_capable(dev)         ((dev)->features[2][1] & LMP_SC)
+#define lmp_ping_capable(dev)       ((dev)->features[2][1] & LMP_PING)
 
 /* ----- Host capabilities ----- */
 #define lmp_host_ssp_capable(dev)  ((dev)->features[1][0] & LMP_HOST_SSP)
+#define lmp_host_sc_capable(dev)   ((dev)->features[1][0] & LMP_HOST_SC)
 #define lmp_host_le_capable(dev)   (!!((dev)->features[1][0] & LMP_HOST_LE))
 #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
 
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH v2] android/tester: Multi property check for test case
From: Grzegorz Kolodziejczyk @ 2014-01-10  9:22 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 | 530 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 386 insertions(+), 144 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index a29c982..a3c5f58 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,87 @@ 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 = {
+	.address = { 0x00, 0xaa, 0x01, 0x00, 0x00, 0x00 },
+};
+static const char enable_done_bdname_val[] = "";
+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 uint32_t enable_done_cod_val = 0;
+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(enable_done_cod_val),
+	.prop.val = &enable_done_cod_val,
+	.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 +825,148 @@ 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 = {
+	.address = { 0x00, 0xaa, 0x01, 0x00, 0x00, 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 +975,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 = 0;
 
+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 +1112,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 +1332,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)
@@ -1122,22 +1384,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 +1408,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,8 +1420,7 @@ 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;
 
 	init_test_conditions(data);
@@ -1175,8 +1432,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 +1443,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 +1458,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 +1483,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 +1495,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 +1507,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 +1519,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 +1532,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 +1544,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 +1556,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 +1568,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 +1580,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 +1592,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 +1604,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 +1616,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

* [PATCHv3 19/19] tools/rfcomm-tester: Add RFCOMM server negative test case
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This test case create RFCOMM server and reject incoming connection
from bthost.
---
 tools/rfcomm-tester.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index 72e765f..7997a4b 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -311,6 +311,12 @@ const struct rfcomm_server_data listen_success = {
 	.expected_status = true
 };
 
+const struct rfcomm_server_data listen_nval = {
+	.server_channel = 0x0c,
+	.client_channel = 0x0e,
+	.expected_status = false
+};
+
 static void test_basic(const void *test_data)
 {
 	int sk;
@@ -551,6 +557,8 @@ int main(int argc, char *argv[])
 			&connect_nval, setup_powered_client, test_connect);
 	test_rfcomm("Basic RFCOMM Socket Server - Success", &listen_success,
 					setup_powered_server, test_server);
+	test_rfcomm("Basic RFCOMM Socket Server - Conn Refused", &listen_nval,
+					setup_powered_server, test_server);
 
 	return tester_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 18/19] tools/rfcomm-tester: Add RFCOMM server test case
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This test case create RFCOMM server and accept incoming connection from
client bthost.
---
 tools/rfcomm-tester.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index f471c3b..72e765f 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -59,6 +59,12 @@ struct rfcomm_client_data {
 	int expected_connect_err;
 };
 
+struct rfcomm_server_data {
+	uint8_t server_channel;
+	uint8_t client_channel;
+	bool expected_status;
+};
+
 static void mgmt_debug(const char *str, void *user_data)
 {
 	const char *prefix = user_data;
@@ -257,6 +263,37 @@ static void setup_powered_client(const void *test_data)
 			NULL, NULL);
 }
 
+static void setup_powered_server_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	if (status != MGMT_STATUS_SUCCESS) {
+		tester_setup_failed();
+		return;
+	}
+
+	tester_print("Controller powered on");
+
+	tester_setup_complete();
+}
+
+static void setup_powered_server(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	unsigned char param[] = { 0x01 };
+
+	tester_print("Powering on controller");
+
+	mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index,
+				sizeof(param), param,
+				NULL, NULL, NULL);
+	mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index,
+				sizeof(param), param, NULL, NULL, NULL);
+
+	mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
+			sizeof(param), param, setup_powered_server_callback,
+			NULL, NULL);
+}
+
 const struct rfcomm_client_data connect_success = {
 	.server_channel = 0x0c,
 	.client_channel = 0x0c
@@ -268,6 +305,12 @@ const struct rfcomm_client_data connect_nval = {
 	.expected_connect_err = -ECONNREFUSED
 };
 
+const struct rfcomm_server_data listen_success = {
+	.server_channel = 0x0c,
+	.client_channel = 0x0c,
+	.expected_status = true
+};
+
 static void test_basic(const void *test_data)
 {
 	int sk;
@@ -383,6 +426,105 @@ static void test_connect(const void *test_data)
 	tester_print("Connect in progress %d", sk);
 }
 
+static gboolean rfcomm_listen_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	int sk, new_sk;
+
+	data->io_id = 0;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	new_sk = accept(sk, NULL, NULL);
+	if (new_sk < 0) {
+		tester_test_failed();
+		return false;
+	}
+
+	close(new_sk);
+
+	tester_test_passed();
+
+	return false;
+}
+
+static void connection_cb(uint16_t handle, uint16_t cid,
+					uint8_t channel, void *user_data,
+					bool status)
+{
+	struct test_data *data = tester_get_data();
+	const struct rfcomm_server_data *server_data = data->test_data;
+
+	if (server_data->expected_status == status)
+		tester_test_passed();
+	else
+		tester_test_failed();
+}
+
+static void client_new_conn(uint16_t handle, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct rfcomm_server_data *server_data = data->test_data;
+	struct bthost *bthost;
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_connect_rfcomm(bthost, handle, server_data->client_channel,
+						connection_cb, NULL);
+}
+
+static void test_server(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct rfcomm_server_data *server_data = data->test_data;
+	const uint8_t *master_bdaddr;
+	uint8_t addr_type;
+	struct bthost *bthost;
+	GIOChannel *io;
+	int sk;
+
+	sk = create_rfcomm_sock((bdaddr_t *)
+				hciemu_get_master_bdaddr(data->hciemu),
+				server_data->server_channel);
+	if (sk < 0) {
+		tester_test_failed();
+		return;
+	}
+
+	if (listen(sk, 5) < 0) {
+		tester_warn("listening on socket failed: %s (%u)",
+				strerror(errno), errno);
+		tester_test_failed();
+		close(sk);
+		return;
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	data->io_id = g_io_add_watch(io, G_IO_IN, rfcomm_listen_cb, NULL);
+	g_io_channel_unref(io);
+
+	tester_print("Listening for connections");
+
+	master_bdaddr = hciemu_get_master_bdaddr(data->hciemu);
+	if (!master_bdaddr) {
+		tester_warn("No master bdaddr");
+		tester_test_failed();
+		return;
+	}
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_set_connect_cb(bthost, client_new_conn, data);
+
+	if (data->hciemu_type == HCIEMU_TYPE_BREDR)
+		addr_type = BDADDR_BREDR;
+	else
+		addr_type = BDADDR_LE_PUBLIC;
+
+	bthost_hci_connect(bthost, master_bdaddr, addr_type);
+}
+
 #define test_rfcomm(name, data, setup, func) \
 	do { \
 		struct test_data *user; \
@@ -407,6 +549,8 @@ int main(int argc, char *argv[])
 					setup_powered_client, test_connect);
 	test_rfcomm("Basic RFCOMM Socket Client - Conn Refused",
 			&connect_nval, setup_powered_client, test_connect);
+	test_rfcomm("Basic RFCOMM Socket Server - Success", &listen_success,
+					setup_powered_server, test_server);
 
 	return tester_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 17/19] emulator/bthost: Call rfcomm_connect_cb when connected
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This will call connect callback when connected or failed to connect.
---
 emulator/bthost.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 96200a0..9b342ce 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1452,6 +1452,15 @@ static void rfcomm_ua_recv(struct bthost *bthost, struct btconn *conn,
 							rfcomm_fcs(buf);
 
 		send_acl(bthost, conn->handle, l2conn->dcid, buf, sizeof(buf));
+	} else if (bthost->rfcomm_conn_data &&
+				bthost->rfcomm_conn_data->channel == channel) {
+		if (bthost->rfcomm_conn_data->cb)
+			bthost->rfcomm_conn_data->cb(conn->handle,
+							l2conn->scid, channel,
+					bthost->rfcomm_conn_data->user_data,
+									true);
+		free(bthost->rfcomm_conn_data);
+		bthost->rfcomm_conn_data = NULL;
 	}
 }
 
@@ -1459,6 +1468,19 @@ static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
 				struct l2conn *l2conn, const void *data,
 				uint16_t len)
 {
+	const struct rfcomm_cmd *hdr = data;
+	uint8_t channel = RFCOMM_GET_CHANNEL(hdr->address);
+
+	if (bthost->rfcomm_conn_data &&
+				bthost->rfcomm_conn_data->channel == channel) {
+		if (bthost->rfcomm_conn_data->cb)
+			bthost->rfcomm_conn_data->cb(conn->handle,
+							l2conn->scid, channel,
+					bthost->rfcomm_conn_data->user_data,
+									false);
+		free(bthost->rfcomm_conn_data);
+		bthost->rfcomm_conn_data = NULL;
+	}
 }
 
 static void rfcomm_msc_recv(struct bthost *bthost, struct btconn *conn,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 16/19] emulator/bthost: Add implementation to PN RSP
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This will send sabm command if PN_RSP will be received.
---
 emulator/bthost.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index ebf8789..96200a0 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1516,6 +1516,9 @@ static void rfcomm_pn_recv(struct bthost *bthost, struct btconn *conn,
 							rfcomm_fcs(buf);
 
 		send_acl(bthost, conn->handle, l2conn->dcid, buf, sizeof(buf));
+	} else if (bthost->rfcomm_conn_data) {
+		rfcomm_sabm_send(bthost, conn, l2conn,
+				1, bthost->rfcomm_conn_data->channel * 2);
 	}
 }
 
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 15/19] emulator/bthost: Ad implementation of rfcomm_ua_recv
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This will handle ua responses in bthost.
---
 emulator/bthost.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 4006b71..ebf8789 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1418,6 +1418,41 @@ static void rfcomm_ua_recv(struct bthost *bthost, struct btconn *conn,
 				struct l2conn *l2conn, const void *data,
 				uint16_t len)
 {
+	const struct rfcomm_cmd *hdr = data;
+	uint8_t channel = RFCOMM_GET_CHANNEL(hdr->address);
+
+	if (!channel && RFCOMM_TEST_CR(RFCOMM_GET_TYPE(hdr->control)) &&
+						 bthost->rfcomm_conn_data) {
+		uint8_t buf[14];
+		struct rfcomm_hdr *hdr = (struct rfcomm_hdr *)buf;
+		struct rfcomm_mcc *mcc = (struct rfcomm_mcc *)
+							(buf + sizeof(*hdr));
+		struct rfcomm_pn *pn_cmd = (struct rfcomm_pn *)
+							(buf + sizeof(*hdr)
+							+ sizeof(*mcc));
+
+		memset(buf, 0, sizeof(buf));
+
+		hdr->address = RFCOMM_ADDR(1, 0);
+		hdr->control = RFCOMM_CTRL(RFCOMM_UIH, 0);
+		hdr->length  = RFCOMM_LEN8(sizeof(*mcc) +
+							sizeof(*pn_cmd));
+
+		mcc->type = RFCOMM_MCC_TYPE(1, RFCOMM_PN);
+		mcc->length = RFCOMM_LEN8(sizeof(*pn_cmd));
+
+		pn_cmd->dlci = bthost->rfcomm_conn_data->channel * 2;
+		pn_cmd->priority = 7;
+		pn_cmd->ack_timer = 0;
+		pn_cmd->max_retrans = 0;
+		pn_cmd->mtu = 667;
+		pn_cmd->credits = 7;
+
+		buf[sizeof(*hdr) + sizeof(*mcc) + sizeof(*pn_cmd)] =
+							rfcomm_fcs(buf);
+
+		send_acl(bthost, conn->handle, l2conn->dcid, buf, sizeof(buf));
+	}
 }
 
 static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 14/19] emulator/bthost: Implement bthost_connect_rfcomm
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This method will start L2CAP connection on RFCOMM PSM and continue
connecting to rfcomm server. User can specify callback to be called
after connection.
---
 emulator/bthost.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 emulator/bthost.h |  4 ++++
 2 files changed, 66 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 391d6cd..4006b71 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -168,6 +168,13 @@ struct rfcomm_conn_cb_data {
 	struct rfcomm_conn_cb_data *next;
 };
 
+struct rfcomm_connection_data {
+	uint8_t channel;
+	struct btconn *conn;
+	bthost_rfcomm_connect_cb cb;
+	void *user_data;
+};
+
 struct bthost {
 	uint8_t bdaddr[6];
 	bthost_send_func send_handler;
@@ -179,6 +186,7 @@ struct bthost {
 	void *cmd_complete_data;
 	bthost_new_conn_cb new_conn_cb;
 	void *new_conn_data;
+	struct rfcomm_connection_data *rfcomm_conn_data;
 	struct l2cap_conn_cb_data *new_l2cap_conn_data;
 	struct rfcomm_conn_cb_data *new_rfcomm_conn_data;
 	struct l2cap_pending_req *l2reqs;
@@ -338,6 +346,10 @@ void bthost_destroy(struct bthost *bthost)
 		free(cb);
 	}
 
+	if (bthost->rfcomm_conn_data)
+		free(bthost->rfcomm_conn_data);
+
+
 	free(bthost);
 }
 
@@ -977,6 +989,19 @@ static bool l2cap_conn_req(struct bthost *bthost, struct btconn *conn,
 	return true;
 }
 
+static void rfcomm_sabm_send(struct bthost *bthost, struct btconn *conn,
+			struct l2conn *l2conn, uint8_t cr, uint8_t dlci)
+{
+	struct rfcomm_cmd cmd;
+
+	cmd.address = RFCOMM_ADDR(cr, dlci);
+	cmd.control = RFCOMM_CTRL(RFCOMM_SABM, 1);
+	cmd.length = RFCOMM_LEN8(0);
+	cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd);
+
+	send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd));
+}
+
 static bool l2cap_conn_rsp(struct bthost *bthost, struct btconn *conn,
 				uint8_t ident, const void *data, uint16_t len)
 {
@@ -1000,6 +1025,10 @@ static bool l2cap_conn_rsp(struct bthost *bthost, struct btconn *conn,
 
 		l2cap_sig_send(bthost, conn, BT_L2CAP_PDU_CONFIG_REQ, 0,
 							&req, sizeof(req));
+	} else if (l2conn->psm == 0x0003 && le16_to_cpu(rsp->result) == 0 &&
+					le16_to_cpu(rsp->status) == 0 &&
+						bthost->rfcomm_conn_data) {
+		rfcomm_sabm_send(bthost, conn, l2conn, 1, 0);
 	}
 
 	return true;
@@ -1721,6 +1750,39 @@ void bthost_start(struct bthost *bthost)
 	send_command(bthost, BT_HCI_CMD_READ_BD_ADDR, NULL, 0);
 }
 
+bool bthost_connect_rfcomm(struct bthost *bthost, uint16_t handle,
+				uint8_t channel, bthost_rfcomm_connect_cb func,
+				void *user_data)
+{
+	struct rfcomm_connection_data *data;
+	struct bt_l2cap_pdu_conn_req req;
+	struct btconn *conn;
+
+	if (bthost->rfcomm_conn_data)
+		return false;
+
+	conn = bthost_find_conn(bthost, handle);
+	if (!conn)
+		return false;
+
+	data = malloc(sizeof(struct rfcomm_connection_data));
+	if (!data)
+		return false;
+
+	data->channel = channel;
+	data->conn = conn;
+	data->cb = func;
+	data->user_data = user_data;
+
+	bthost->rfcomm_conn_data = data;
+
+	req.psm = cpu_to_le16(0x0003);
+	req.scid = cpu_to_le16(conn->next_cid++);
+
+	return bthost_l2cap_req(bthost, handle, BT_L2CAP_PDU_CONN_REQ,
+					&req, sizeof(req), NULL, NULL);
+}
+
 void bthost_stop(struct bthost *bthost)
 {
 }
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 2fc21b5..2c9a125 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -90,5 +90,9 @@ typedef void (*bthost_rfcomm_connect_cb) (uint16_t handle, uint16_t cid,
 void bthost_add_rfcomm_server(struct bthost *bthost, uint8_t channel,
 			bthost_rfcomm_connect_cb func, void *user_data);
 
+bool bthost_connect_rfcomm(struct bthost *bthost, uint16_t handle,
+				uint8_t channel, bthost_rfcomm_connect_cb func,
+				void *user_data);
+
 void bthost_start(struct bthost *bthost);
 void bthost_stop(struct bthost *bthost);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 13/19] tools/rfcomm-tester: Add Connection refused client test case
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This will test RFCOMM client connection to wrong server channel.
---
 tools/rfcomm-tester.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index 271f554..f471c3b 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -262,6 +262,12 @@ const struct rfcomm_client_data connect_success = {
 	.client_channel = 0x0c
 };
 
+const struct rfcomm_client_data connect_nval = {
+	.server_channel = 0x0c,
+	.client_channel = 0x0e,
+	.expected_connect_err = -ECONNREFUSED
+};
+
 static void test_basic(const void *test_data)
 {
 	int sk;
@@ -399,6 +405,8 @@ int main(int argc, char *argv[])
 					setup_powered_client, test_basic);
 	test_rfcomm("Basic RFCOMM Socket Client - Success", &connect_success,
 					setup_powered_client, test_connect);
+	test_rfcomm("Basic RFCOMM Socket Client - Conn Refused",
+			&connect_nval, setup_powered_client, test_connect);
 
 	return tester_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 12/19] tools/rfcomm-tester: Implement client test case
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This will test RFCOMM client connection.
---
 tools/rfcomm-tester.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index a4f1c8e..271f554 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -35,6 +35,7 @@
 
 #include "lib/bluetooth.h"
 #include "lib/mgmt.h"
+#include "bluetooth/rfcomm.h"
 
 #include "monitor/bt.h"
 #include "emulator/bthost.h"
@@ -49,6 +50,13 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	const void *test_data;
+	unsigned int io_id;
+};
+
+struct rfcomm_client_data {
+	uint8_t server_channel;
+	uint8_t client_channel;
+	int expected_connect_err;
 };
 
 static void mgmt_debug(const char *str, void *user_data)
@@ -181,6 +189,11 @@ static void test_post_teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
+	if (data->io_id > 0) {
+		g_source_remove(data->io_id);
+		data->io_id = 0;
+	}
+
 	hciemu_unref(data->hciemu);
 	data->hciemu = NULL;
 }
@@ -244,6 +257,11 @@ static void setup_powered_client(const void *test_data)
 			NULL, NULL);
 }
 
+const struct rfcomm_client_data connect_success = {
+	.server_channel = 0x0c,
+	.client_channel = 0x0c
+};
+
 static void test_basic(const void *test_data)
 {
 	int sk;
@@ -261,6 +279,104 @@ static void test_basic(const void *test_data)
 	tester_test_passed();
 }
 
+static int create_rfcomm_sock(bdaddr_t *address, uint8_t channel)
+{
+	int sk;
+	struct sockaddr_rc addr;
+
+	sk = socket(PF_BLUETOOTH, SOCK_STREAM | SOCK_NONBLOCK, BTPROTO_RFCOMM);
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	addr.rc_channel = channel;
+	bacpy(&addr.rc_bdaddr, address);
+
+	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		close(sk);
+		return -1;
+	}
+
+	return sk;
+}
+
+static int connect_rfcomm_sock(int sk, bdaddr_t *address, uint8_t channel)
+{
+	struct sockaddr_rc addr;
+	int err;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, address);
+	addr.rc_channel = htobs(channel);
+
+	err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+static gboolean rc_connect_cb(GIOChannel *io, GIOCondition cond,
+		gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct rfcomm_client_data *client_data = data->test_data;
+	socklen_t len = sizeof(int);
+	int sk, err, sk_err;
+
+	data->io_id = 0;
+
+	sk = g_io_channel_unix_get_fd(io);
+
+	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
+		err = -errno;
+	else
+		err = -sk_err;
+
+	if (client_data->expected_connect_err &&
+				err == client_data->expected_connect_err) {
+		tester_test_passed();
+		return false;
+	}
+
+	if (err < 0)
+		tester_test_failed();
+	else
+		tester_test_passed();
+
+	return false;
+}
+
+static void test_connect(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+	const struct rfcomm_client_data *client_data = data->test_data;
+	GIOChannel *io;
+	int sk;
+
+	bthost_add_l2cap_server(bthost, 0x0003, NULL, NULL);
+	bthost_add_rfcomm_server(bthost, client_data->server_channel,
+								NULL, NULL);
+
+	sk = create_rfcomm_sock((bdaddr_t *)hciemu_get_master_bdaddr
+							(data->hciemu), 0);
+
+	if (connect_rfcomm_sock(sk, (bdaddr_t *)hciemu_get_client_bdaddr
+			(data->hciemu), client_data->client_channel) < 0) {
+		tester_test_failed();
+	}
+
+	io = g_io_channel_unix_new(sk);
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	data->io_id = g_io_add_watch(io, G_IO_OUT, rc_connect_cb, NULL);
+
+	g_io_channel_unref(io);
+
+	tester_print("Connect in progress %d", sk);
+}
+
 #define test_rfcomm(name, data, setup, func) \
 	do { \
 		struct test_data *user; \
@@ -269,6 +385,7 @@ static void test_basic(const void *test_data)
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDR; \
 		user->test_data = data; \
+		user->io_id = 0; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
 				test_post_teardown, 2, user, test_data_free); \
@@ -280,6 +397,8 @@ int main(int argc, char *argv[])
 
 	test_rfcomm("Basic RFCOMM Socket - Success", NULL,
 					setup_powered_client, test_basic);
+	test_rfcomm("Basic RFCOMM Socket Client - Success", &connect_success,
+					setup_powered_client, test_connect);
 
 	return tester_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 11/19] emulator/bthost: Implement recv_disc rfcomm frame in bthost
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

---
 emulator/bthost.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 1e2506e..391d6cd 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1379,6 +1379,10 @@ static void rfcomm_disc_recv(struct bthost *bthost, struct btconn *conn,
 				struct l2conn *l2conn, const void *data,
 				uint16_t len)
 {
+	const struct rfcomm_cmd *hdr = data;
+	uint8_t dlci = RFCOMM_GET_DLCI(hdr->address);
+
+	rfcomm_ua_send(bthost, conn, l2conn, 0, dlci);
 }
 
 static void rfcomm_ua_recv(struct bthost *bthost, struct btconn *conn,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 10/19] emulator/bthost: Service msc frames
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

---
 emulator/bthost.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 83f1e96..1e2506e 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1393,6 +1393,29 @@ static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
 {
 }
 
+static void rfcomm_msc_recv(struct bthost *bthost, struct btconn *conn,
+					struct l2conn *l2conn, uint8_t cr,
+					const struct rfcomm_msc *msc)
+{
+	uint8_t buf[8];
+	struct rfcomm_hdr *hdr = (struct rfcomm_hdr *)buf;
+	struct rfcomm_mcc *mcc = (struct rfcomm_mcc *)(buf + sizeof(*hdr));
+	struct rfcomm_msc *msc_cmd = (struct rfcomm_msc *)(buf + sizeof(*hdr)
+							+ sizeof(*mcc));
+
+	hdr->address = RFCOMM_ADDR(0, 0);
+	hdr->control = RFCOMM_CTRL(RFCOMM_UIH, 0);
+	hdr->length  = RFCOMM_LEN8(sizeof(*mcc) + sizeof(*msc));
+	mcc->type = RFCOMM_MCC_TYPE(cr, RFCOMM_MSC);
+	mcc->length = RFCOMM_LEN8(sizeof(*msc));
+
+	msc_cmd->dlci = msc->dlci;
+	msc_cmd->v24_sig = msc->v24_sig;
+	buf[sizeof(*hdr) + sizeof(*mcc) + sizeof(*msc_cmd)] = rfcomm_fcs(buf);
+
+	send_acl(bthost, conn->handle, l2conn->dcid, buf, sizeof(buf));
+}
+
 static void rfcomm_pn_recv(struct bthost *bthost, struct btconn *conn,
 					struct l2conn *l2conn, uint8_t cr,
 					const struct rfcomm_pn *pn)
@@ -1435,6 +1458,11 @@ static void rfcomm_mcc_recv(struct bthost *bthost, struct btconn *conn,
 	uint8_t type = RFCOMM_GET_MCC_TYPE(mcc->type);
 
 	switch (type) {
+	case RFCOMM_MSC:
+		rfcomm_msc_recv(bthost, conn, l2conn,
+						RFCOMM_TEST_CR(mcc->type) / 2,
+							data + sizeof(*mcc));
+		break;
 	case RFCOMM_PN:
 		rfcomm_pn_recv(bthost, conn, l2conn,
 					RFCOMM_TEST_CR(mcc->type) / 2,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 09/19] emulator/bthost: Add recv_pn implementation
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

---
 emulator/bthost.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 591aae9..83f1e96 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -54,6 +54,7 @@
 #define RFCOMM_CTRL(type, pf)	(((type & 0xef) | (pf << 4)))
 #define RFCOMM_LEN8(len)	(((len) << 1) | 1)
 #define RFCOMM_LEN16(len)	((len) << 1)
+#define RFCOMM_MCC_TYPE(cr, type)	(((type << 2) | (cr << 1) | 0x01))
 
 /* RFCOMM FCS calculation */
 #define CRC(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
@@ -105,6 +106,11 @@ static uint8_t rfcomm_fcs2(uint8_t *data)
 	return 0xff - rfcomm_crc_table[CRC(data) ^ data[2]];
 }
 
+static uint8_t rfcomm_fcs(uint8_t *data)
+{
+	return 0xff - CRC(data);
+}
+
 struct cmd {
 	struct cmd *next;
 	struct cmd *prev;
@@ -1387,9 +1393,56 @@ static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
 {
 }
 
+static void rfcomm_pn_recv(struct bthost *bthost, struct btconn *conn,
+					struct l2conn *l2conn, uint8_t cr,
+					const struct rfcomm_pn *pn)
+{
+	if (cr) {
+		uint8_t buf[14];
+		struct rfcomm_hdr *hdr = (struct rfcomm_hdr *)buf;
+		struct rfcomm_mcc *mcc = (struct rfcomm_mcc *)(buf +
+								sizeof(*hdr));
+		struct rfcomm_pn *pn_cmd = (struct rfcomm_pn *)
+					(buf + sizeof(*hdr) + sizeof(*mcc));
+
+		memset(buf, 0, sizeof(buf));
+
+		hdr->address = RFCOMM_ADDR(1, 0);
+		hdr->control = RFCOMM_CTRL(RFCOMM_UIH, 0);
+		hdr->length  = RFCOMM_LEN8(sizeof(*mcc) + sizeof(*pn_cmd));
+
+		mcc->type = RFCOMM_MCC_TYPE(0, RFCOMM_PN);
+		mcc->length = RFCOMM_LEN8(sizeof(*pn_cmd));
+
+		pn_cmd->dlci = pn->dlci;
+		pn_cmd->priority = pn->priority;
+		pn_cmd->ack_timer = pn->ack_timer;
+		pn_cmd->max_retrans = pn->max_retrans;
+		pn_cmd->mtu = pn->mtu;
+		pn_cmd->credits = pn->credits;
+
+		buf[sizeof(*hdr) + sizeof(*mcc) + sizeof(*pn_cmd)] =
+							rfcomm_fcs(buf);
+
+		send_acl(bthost, conn->handle, l2conn->dcid, buf, sizeof(buf));
+	}
+}
+
 static void rfcomm_mcc_recv(struct bthost *bthost, struct btconn *conn,
 			struct l2conn *l2conn, const void *data, uint16_t len)
 {
+	const struct rfcomm_mcc *mcc = data;
+	uint8_t type = RFCOMM_GET_MCC_TYPE(mcc->type);
+
+	switch (type) {
+	case RFCOMM_PN:
+		rfcomm_pn_recv(bthost, conn, l2conn,
+					RFCOMM_TEST_CR(mcc->type) / 2,
+					data + sizeof(*mcc));
+		break;
+	default:
+		break;
+	}
 }
 
 static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 08/19] emulator/bthost: Add rfcomm_mcc_recv stub
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

It will handle mcc frames in bthost.
---
 emulator/bthost.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 242ce19..591aae9 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1387,10 +1387,29 @@ static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
 {
 }
 
+static void rfcomm_mcc_recv(struct bthost *bthost, struct btconn *conn,
+			struct l2conn *l2conn, const void *data, uint16_t len)
+{
+}
+
 static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn,
 				struct l2conn *l2conn, const void *data,
 				uint16_t len)
 {
+	const struct rfcomm_cmd *hdr = data;
+	const void *p;
+	uint8_t ea;
+
+	ea = RFCOMM_TEST_EA(hdr->length) ? true : false;
+
+	if (!RFCOMM_GET_DLCI(hdr->address)) {
+		if (ea)
+			p = data + sizeof(struct rfcomm_hdr);
+		else
+			p = data + sizeof(struct rfcomm_hdr) + sizeof(uint8_t);
+
+		rfcomm_mcc_recv(bthost, conn, l2conn, p, p - data);
+	}
 }
 
 static void process_rfcomm(struct bthost *bthost, struct btconn *conn,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 07/19] monitor: Add mcc structs and types to rfcomm.h
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

---
 monitor/rfcomm.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/monitor/rfcomm.h b/monitor/rfcomm.h
index 8dcb9c1..4222624 100644
--- a/monitor/rfcomm.h
+++ b/monitor/rfcomm.h
@@ -45,3 +45,35 @@ struct rfcomm_cmd {
 	uint8_t length;
 	uint8_t fcs;
 } __attribute__((packed));
+
+#define RFCOMM_TEST    0x08
+#define RFCOMM_FCON    0x28
+#define RFCOMM_FCOFF   0x18
+#define RFCOMM_MSC     0x38
+#define RFCOMM_RPN     0x24
+#define RFCOMM_RLS     0x14
+#define RFCOMM_PN      0x20
+#define RFCOMM_NSC     0x04
+
+#define RFCOMM_TEST_CR(type)	((type & 0x02))
+#define RFCOMM_GET_MCC_TYPE(type)	((type & 0xfc) >> 2)
+
+struct rfcomm_mcc {
+	uint8_t type;
+	uint8_t length;
+} __attribute__((packed));
+
+struct rfcomm_msc {
+	uint8_t dlci;
+	uint8_t v24_sig;
+} __attribute__((packed));
+
+struct rfcomm_pn {
+	uint8_t dlci;
+	uint8_t flow_ctrl;
+	uint8_t priority;
+	uint8_t ack_timer;
+	uint16_t mtu;
+	uint8_t max_retrans;
+	uint8_t credits;
+} __attribute__((packed));
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 06/19] emulator/bthost: Add recv_sabm imnplementation
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This will handle sabm frames and send ua or dm frame.
---
 emulator/bthost.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 111 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index bf63b2f..242ce19 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -49,6 +49,62 @@
 #define cpu_to_le16(val) (val)
 #define cpu_to_le32(val) (val)
 
+/* RFCOMM setters */
+#define RFCOMM_ADDR(cr, dlci)	(((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
+#define RFCOMM_CTRL(type, pf)	(((type & 0xef) | (pf << 4)))
+#define RFCOMM_LEN8(len)	(((len) << 1) | 1)
+#define RFCOMM_LEN16(len)	((len) << 1)
+
+/* RFCOMM FCS calculation */
+#define CRC(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
+
+static unsigned char rfcomm_crc_table[256] = {
+	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
+	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
+	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
+	0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
+
+	0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
+	0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+	0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
+	0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
+
+	0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
+	0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
+	0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
+	0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+
+	0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
+	0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
+	0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
+	0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
+
+	0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
+	0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+	0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
+	0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
+
+	0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
+	0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
+	0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
+	0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+
+	0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
+	0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
+	0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
+	0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
+
+	0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
+	0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+	0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
+	0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
+};
+
+static uint8_t rfcomm_fcs2(uint8_t *data)
+{
+	return 0xff - rfcomm_crc_table[CRC(data) ^ data[2]];
+}
+
 struct cmd {
 	struct cmd *next;
 	struct cmd *prev;
@@ -222,6 +278,19 @@ static struct l2cap_conn_cb_data *bthost_find_l2cap_cb_by_psm(
 	return NULL;
 }
 
+static struct rfcomm_conn_cb_data *bthost_find_rfcomm_cb_by_channel(
+					struct bthost *bthost, uint8_t channel)
+{
+	struct rfcomm_conn_cb_data *cb;
+
+	for (cb = bthost->new_rfcomm_conn_data; cb != NULL; cb = cb->next) {
+		if (cb->channel == channel)
+			return cb;
+	}
+
+	return NULL;
+}
+
 void bthost_destroy(struct bthost *bthost)
 {
 	if (!bthost)
@@ -1252,10 +1321,52 @@ static struct cid_hook *find_cid_hook(struct btconn *conn, uint16_t cid)
 	return NULL;
 }
 
+static void rfcomm_ua_send(struct bthost *bthost, struct btconn *conn,
+			struct l2conn *l2conn, uint8_t cr, uint8_t dlci)
+{
+	struct rfcomm_cmd cmd;
+
+	cmd.address = RFCOMM_ADDR(cr, dlci);
+	cmd.control = RFCOMM_CTRL(RFCOMM_UA, 1);
+	cmd.length = RFCOMM_LEN8(0);
+	cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd);
+
+	send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd));
+}
+
+static void rfcomm_dm_send(struct bthost *bthost, struct btconn *conn,
+			struct l2conn *l2conn, uint8_t cr, uint8_t dlci)
+{
+	struct rfcomm_cmd cmd;
+
+	cmd.address = RFCOMM_ADDR(cr, dlci);
+	cmd.control = RFCOMM_CTRL(RFCOMM_DM, 1);
+	cmd.length = RFCOMM_LEN8(0);
+	cmd.fcs = rfcomm_fcs2((uint8_t *)&cmd);
+
+	send_acl(bthost, conn->handle, l2conn->dcid, &cmd, sizeof(cmd));
+}
+
 static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn,
 				struct l2conn *l2conn, const void *data,
 				uint16_t len)
 {
+	const struct rfcomm_cmd *hdr = data;
+	uint8_t dlci = RFCOMM_GET_DLCI(hdr->address);
+	struct rfcomm_conn_cb_data *cb;
+
+	cb = bthost_find_rfcomm_cb_by_channel(bthost,
+					RFCOMM_GET_CHANNEL(hdr->address));
+
+	if (!dlci || cb) {
+		rfcomm_ua_send(bthost, conn, l2conn, 1, dlci);
+		if (cb && cb->func)
+			cb->func(conn->handle, l2conn->scid,
+					RFCOMM_GET_CHANNEL(hdr->address),
+					cb->user_data, true);
+	} else {
+		rfcomm_dm_send(bthost, conn, l2conn, 1, dlci);
+	}
 }
 
 static void rfcomm_disc_recv(struct bthost *bthost, struct btconn *conn,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 05/19] emulator/bthost: Add method to create rfcomm server
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

It allows user to create rfcomm server on bthost.
---
 emulator/bthost.c | 32 ++++++++++++++++++++++++++++++++
 emulator/bthost.h |  7 +++++++
 2 files changed, 39 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index f896616..bf63b2f 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -99,6 +99,13 @@ struct l2cap_conn_cb_data {
 	struct l2cap_conn_cb_data *next;
 };
 
+struct rfcomm_conn_cb_data {
+	uint8_t channel;
+	bthost_rfcomm_connect_cb func;
+	void *user_data;
+	struct rfcomm_conn_cb_data *next;
+};
+
 struct bthost {
 	uint8_t bdaddr[6];
 	bthost_send_func send_handler;
@@ -111,6 +118,7 @@ struct bthost {
 	bthost_new_conn_cb new_conn_cb;
 	void *new_conn_data;
 	struct l2cap_conn_cb_data *new_l2cap_conn_data;
+	struct rfcomm_conn_cb_data *new_rfcomm_conn_data;
 	struct l2cap_pending_req *l2reqs;
 	uint8_t pin[16];
 	uint8_t pin_len;
@@ -248,6 +256,13 @@ void bthost_destroy(struct bthost *bthost)
 		free(cb);
 	}
 
+	while (bthost->new_rfcomm_conn_data) {
+		struct rfcomm_conn_cb_data *cb = bthost->new_rfcomm_conn_data;
+
+		bthost->new_rfcomm_conn_data = cb->next;
+		free(cb);
+	}
+
 	free(bthost);
 }
 
@@ -1462,6 +1477,23 @@ void bthost_set_pin_code(struct bthost *bthost, const uint8_t *pin,
 	bthost->pin_len = pin_len;
 }
 
+void bthost_add_rfcomm_server(struct bthost *bthost, uint8_t channel,
+				bthost_rfcomm_connect_cb func, void *user_data)
+{
+	struct rfcomm_conn_cb_data *data;
+
+	data = malloc(sizeof(struct rfcomm_conn_cb_data));
+	if (!data)
+		return;
+
+	data->channel = channel;
+	data->user_data = user_data;
+	data->func = func;
+	data->next = bthost->new_rfcomm_conn_data;
+
+	bthost->new_rfcomm_conn_data = data;
+}
+
 void bthost_start(struct bthost *bthost)
 {
 	if (!bthost)
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 7458d5e..2fc21b5 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -83,5 +83,12 @@ void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
 void bthost_set_pin_code(struct bthost *bthost, const uint8_t *pin,
 							uint8_t pin_len);
 
+typedef void (*bthost_rfcomm_connect_cb) (uint16_t handle, uint16_t cid,
+					uint8_t channel, void *user_data,
+					bool status);
+
+void bthost_add_rfcomm_server(struct bthost *bthost, uint8_t channel,
+			bthost_rfcomm_connect_cb func, void *user_data);
+
 void bthost_start(struct bthost *bthost);
 void bthost_stop(struct bthost *bthost);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 04/19] emulator/bthost: Add initial rfcomm handling
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This is initial rfcomm handling in bthost.
---
 emulator/bthost.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 4ce720e..f896616 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -36,6 +36,7 @@
 #include "bluetooth/bluetooth.h"
 
 #include "monitor/bt.h"
+#include "monitor/rfcomm.h"
 #include "bthost.h"
 
 /* ACL handle and flags pack/unpack */
@@ -1236,6 +1237,64 @@ static struct cid_hook *find_cid_hook(struct btconn *conn, uint16_t cid)
 	return NULL;
 }
 
+static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_disc_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_ua_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+}
+
+static void process_rfcomm(struct bthost *bthost, struct btconn *conn,
+				struct l2conn *l2conn, const void *data,
+				uint16_t len)
+{
+	const struct rfcomm_hdr *hdr = data;
+
+	switch (RFCOMM_GET_TYPE(hdr->control)) {
+	case RFCOMM_SABM:
+		rfcomm_sabm_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_DISC:
+		rfcomm_disc_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_UA:
+		rfcomm_ua_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_DM:
+		rfcomm_dm_recv(bthost, conn, l2conn, data, len);
+		break;
+	case RFCOMM_UIH:
+		rfcomm_uih_recv(bthost, conn, l2conn, data, len);
+		break;
+	default:
+		printf("Unknown frame type\n");
+		break;
+	}
+}
+
 static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 {
 	const struct bt_hci_acl_hdr *acl_hdr = data;
@@ -1243,6 +1302,7 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 	uint16_t handle, cid, acl_len, l2_len;
 	struct cid_hook *hook;
 	struct btconn *conn;
+	struct l2conn *l2conn;
 	const void *l2_data;
 
 	if (len < sizeof(*acl_hdr) + sizeof(*l2_hdr))
@@ -1281,7 +1341,12 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 		l2cap_le_sig(bthost, conn, l2_data, l2_len);
 		break;
 	default:
-		printf("Packet for unknown CID 0x%04x (%u)\n", cid, cid);
+		l2conn = btconn_find_l2cap_conn_by_scid(conn, cid);
+		if (l2conn && l2conn->psm == 0x0003)
+			process_rfcomm(bthost, conn, l2conn, l2_data, l2_len);
+		else
+			printf("Packet for unknown CID 0x%04x (%u)\n", cid,
+									cid);
 		break;
 	}
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 03/19] monitor: Add rfcomm.h to tree
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

Add initial rfcomm structs and defines to rfcomm.h.
---
 monitor/rfcomm.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 monitor/rfcomm.h

diff --git a/monitor/rfcomm.h b/monitor/rfcomm.h
new file mode 100644
index 0000000..8dcb9c1
--- /dev/null
+++ b/monitor/rfcomm.h
@@ -0,0 +1,47 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014 Intel Corporation
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define RFCOMM_SABM	0x2f
+#define RFCOMM_DISC	0x43
+#define RFCOMM_UA	0x63
+#define RFCOMM_DM	0x0f
+#define RFCOMM_UIH	0xef
+
+#define RFCOMM_GET_TYPE(control)	((control) & 0xef)
+#define RFCOMM_GET_DLCI(address)	((address & 0xfc) >> 2)
+#define RFCOMM_GET_CHANNEL(address)	((address & 0xf8) >> 3)
+#define RFCOMM_GET_DIR(address)	((address & 0x04) >> 2)
+#define RFCOMM_TEST_EA(length)	((length & 0x01))
+
+struct rfcomm_hdr {
+	uint8_t address;
+	uint8_t control;
+	uint8_t length;
+} __attribute__((packed));
+
+struct rfcomm_cmd {
+	uint8_t address;
+	uint8_t control;
+	uint8_t length;
+	uint8_t fcs;
+} __attribute__((packed));
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 02/19] tools/rfcomm-tester: Add basic rfcomm test case
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

This test case verifies creating rfcomm socket.
---
 Makefile.tools        |  11 ++-
 tools/rfcomm-tester.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+), 2 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 07fbd80..93ff354 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -80,8 +80,15 @@ tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
 				src/shared/tester.h src/shared/tester.c
 tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
-tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c src/shared/tester.h \
-				src/shared/tester.c
+tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
+				emulator/btdev.h emulator/btdev.c \
+				emulator/bthost.h emulator/bthost.c \
+				src/shared/io.h src/shared/io-glib.c \
+				src/shared/queue.h src/shared/queue.c \
+				src/shared/util.h src/shared/util.c \
+				src/shared/mgmt.h src/shared/mgmt.c \
+				src/shared/hciemu.h src/shared/hciemu.c \
+				src/shared/tester.h src/shared/tester.c
 tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index 200d953..a4f1c8e 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -25,12 +25,261 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+
 #include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "monitor/bt.h"
+#include "emulator/bthost.h"
+
 #include "src/shared/tester.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/hciemu.h"
+
+struct test_data {
+	struct mgmt *mgmt;
+	uint16_t mgmt_index;
+	struct hciemu *hciemu;
+	enum hciemu_type hciemu_type;
+	const void *test_data;
+};
+
+static void mgmt_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	tester_print("%s%s", prefix, str);
+}
+
+static void read_info_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct mgmt_rp_read_info *rp = param;
+	char addr[18];
+	uint16_t manufacturer;
+	uint32_t supported_settings, current_settings;
+
+	tester_print("Read Info callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	ba2str(&rp->bdaddr, addr);
+	manufacturer = btohs(rp->manufacturer);
+	supported_settings = btohl(rp->supported_settings);
+	current_settings = btohl(rp->current_settings);
+
+	tester_print("  Address: %s", addr);
+	tester_print("  Version: 0x%02x", rp->version);
+	tester_print("  Manufacturer: 0x%04x", manufacturer);
+	tester_print("  Supported settings: 0x%08x", supported_settings);
+	tester_print("  Current settings: 0x%08x", current_settings);
+	tester_print("  Class: 0x%02x%02x%02x",
+			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+	tester_print("  Name: %s", rp->name);
+	tester_print("  Short name: %s", rp->short_name);
+
+	if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	tester_pre_setup_complete();
+}
+
+static void index_added_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Added callback");
+	tester_print("  Index: 0x%04x", index);
+
+	data->mgmt_index = index;
+
+	mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
+					read_info_callback, NULL, NULL);
+}
+
+static void index_removed_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Removed callback");
+	tester_print("  Index: 0x%04x", index);
+
+	if (index != data->mgmt_index)
+		return;
+
+	mgmt_unregister_index(data->mgmt, data->mgmt_index);
+
+	mgmt_unref(data->mgmt);
+	data->mgmt = NULL;
+
+	tester_post_teardown_complete();
+}
+
+static void read_index_list_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Read Index List callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+					index_added_callback, NULL, NULL);
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+					index_removed_callback, NULL, NULL);
+
+	data->hciemu = hciemu_new(data->hciemu_type);
+	if (!data->hciemu) {
+		tester_warn("Failed to setup HCI emulation");
+		tester_pre_setup_failed();
+	}
+
+	tester_print("New hciemu instance created");
+}
+
+static void test_pre_setup(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	data->mgmt = mgmt_new_default();
+	if (!data->mgmt) {
+		tester_warn("Failed to setup management interface");
+		tester_pre_setup_failed();
+		return;
+	}
+
+	if (tester_use_debug())
+		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);
+}
+
+static void test_post_teardown(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	hciemu_unref(data->hciemu);
+	data->hciemu = NULL;
+}
+
+static void test_data_free(void *test_data)
+{
+	struct test_data *data = test_data;
+
+	free(data);
+}
+
+static void client_connectable_complete(uint16_t opcode, uint8_t status,
+					const void *param, uint8_t len,
+					void *user_data)
+{
+	switch (opcode) {
+	case BT_HCI_CMD_WRITE_SCAN_ENABLE:
+		break;
+	default:
+		return;
+	}
+
+	tester_print("Client set connectable status 0x%02x", status);
+
+	if (status)
+		tester_setup_failed();
+	else
+		tester_setup_complete();
+}
+
+static void setup_powered_client_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	struct bthost *bthost;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		tester_setup_failed();
+		return;
+	}
+
+	tester_print("Controller powered on");
+
+	bthost = hciemu_client_get_host(data->hciemu);
+	bthost_set_cmd_complete_cb(bthost, client_connectable_complete, data);
+	bthost_write_scan_enable(bthost, 0x03);
+}
+
+static void setup_powered_client(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	unsigned char param[] = { 0x01 };
+
+	tester_print("Powering on controller");
+
+	mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index,
+				sizeof(param), param, NULL, NULL, NULL);
+
+	mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
+			sizeof(param), param, setup_powered_client_callback,
+			NULL, NULL);
+}
+
+static void test_basic(const void *test_data)
+{
+	int sk;
+
+	sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (sk < 0) {
+		tester_warn("Can't create socket: %s (%d)", strerror(errno),
+									errno);
+		tester_test_failed();
+		return;
+	}
+
+	close(sk);
+
+	tester_test_passed();
+}
+
+#define test_rfcomm(name, data, setup, func) \
+	do { \
+		struct test_data *user; \
+		user = malloc(sizeof(struct test_data)); \
+		if (!user) \
+			break; \
+		user->hciemu_type = HCIEMU_TYPE_BREDR; \
+		user->test_data = data; \
+		tester_add_full(name, data, \
+				test_pre_setup, setup, func, NULL, \
+				test_post_teardown, 2, user, test_data_free); \
+	} while (0)
 
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
 
+	test_rfcomm("Basic RFCOMM Socket - Success", NULL,
+					setup_powered_client, test_basic);
+
 	return tester_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 01/19] tools/rfcomm-tester: Initial version of rfcomm-tester
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389345509-27206-1-git-send-email-marcin.kraglak@tieto.com>

Add rfcomm-tester to tree.
---
 .gitignore            |  1 +
 Makefile.tools        |  6 +++++-
 tools/rfcomm-tester.c | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 tools/rfcomm-tester.c

diff --git a/.gitignore b/.gitignore
index 3e0641d..4ac216d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,6 +81,7 @@ unit/test-mgmt
 tools/mgmt-tester
 tools/smp-tester
 tools/gap-tester
+tools/rfcomm-tester
 tools/btattach
 tools/btmgmt
 tools/btsnoop
diff --git a/Makefile.tools b/Makefile.tools
index ec1499a..07fbd80 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -39,7 +39,7 @@ if EXPERIMENTAL
 noinst_PROGRAMS += emulator/btvirt emulator/b1ee tools/3dsp \
 					tools/mgmt-tester tools/gap-tester \
 					tools/l2cap-tester tools/sco-tester \
-					tools/smp-tester
+					tools/smp-tester tools/rfcomm-tester
 
 emulator_btvirt_SOURCES = emulator/main.c monitor/bt.h \
 					monitor/mainloop.h monitor/mainloop.c \
@@ -80,6 +80,10 @@ tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
 				src/shared/tester.h src/shared/tester.c
 tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
+tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c src/shared/tester.h \
+				src/shared/tester.c
+tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
new file mode 100644
index 0000000..200d953
--- /dev/null
+++ b/tools/rfcomm-tester.c
@@ -0,0 +1,36 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include "src/shared/tester.h"
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	return tester_run();
+}
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 00/19] Initial RFCOMM support in bthost
From: Marcin Kraglak @ 2014-01-10  9:18 UTC (permalink / raw)
  To: linux-bluetooth

This adds initial support from rfcomm connection in bthost.
With these patches bthost can accept incoming RFCOMM connections
and create outgoing RFCOMM connections. Also rfcomm-tester is
introduced with few basic test cases. monitor/rfcomm.h is created
for proper handling rfcomm signaling.

Comments are welcome

Marcin Kraglak (19):
  tools/rfcomm-tester: Initial version of rfcomm-tester
  tools/rfcomm-tester: Add basic rfcomm test case
  monitor: Add rfcomm.h to tree
  emulator/bthost: Add initial rfcomm handling
  emulator/bthost: Add method to create rfcomm server
  emulator/bthost: Add recv_sabm imnplementation
  monitor: Add mcc structs and types to rfcomm.h
  emulator/bthost: Add rfcomm_mcc_recv stub
  emulator/bthost: Add recv_pn implementation
  emulator/bthost: Service msc frames
  emulator/bthost: Implement recv_disc rfcomm frame in bthost
  tools/rfcomm-tester: Implement client test case
  tools/rfcomm-tester: Add Connection refused client test case
  emulator/bthost: Implement bthost_connect_rfcomm
  emulator/bthost: Ad implementation of rfcomm_ua_recv
  emulator/bthost: Add implementation to PN RSP
  emulator/bthost: Call rfcomm_connect_cb when connected
  tools/rfcomm-tester: Add RFCOMM server test case
  tools/rfcomm-tester: Add RFCOMM server negative test case

 .gitignore            |   1 +
 Makefile.tools        |  13 +-
 emulator/bthost.c     | 436 +++++++++++++++++++++++++++++++++++++-
 emulator/bthost.h     |  11 +
 monitor/rfcomm.h      |  79 +++++++
 tools/rfcomm-tester.c | 564 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1102 insertions(+), 2 deletions(-)
 create mode 100644 monitor/rfcomm.h
 create mode 100644 tools/rfcomm-tester.c

-- 
1.8.3.1


^ permalink raw reply

* Re: [PATCH_v4 0/4] Add support for NAP role
From: Ravi kumar Veeramally @ 2014-01-10  8:38 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389181593-9683-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Ping.

On 01/08/2014 01:46 PM, Ravi kumar Veeramally wrote:
> 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 | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 334 insertions(+), 12 deletions(-)
>


^ permalink raw reply

* Re: Last depmod fails with 3.13-rc6
From: Paul Bolle @ 2014-01-10  8:11 UTC (permalink / raw)
  To: Marcel Holtmann, Gustavo Padovan, Johan Hedberg
  Cc: Sébastien Luttringer, linux-bluetooth, linux-kernel
In-Reply-To: <la50g5$n4j$1@ger.gmane.org>

Adding maintainers and linux-bluetooth.

On Fri, 2014-01-03 at 01:33 +0100, Sébastien Luttringer wrote:
> On 03/01/2014 01:11, Sébastien Luttringer wrote:
> > Hello,
> > 
> > Trying to run depmod (from kmod 16) on the 3.13-rc6, I got this error
> > message:
> > 
> > # depmod 3.13.0-rc6-seblu
> > depmod: ERROR: Module 'hci_vhci' has devname (vhci) but lacks major and
> > minor information. Ignoring.
> > 
> > The message and error code seem to be on purpose[2] but they break tools
> > which rely on depmod return 0 (like kernel-install).
> > 
> > 
> > [1] http://git.kernel.org/cgit/utils/kernel/kmod/kmod.git/commit/?id=6506ddf
> > 
> Forget about the return code and their consequences. I made a mistake.
> 
> The missing informations in hci_vhci is still relevant.
> 
> # depmod 3.13.0-rc6-seblu
> depmod: ERROR: Module 'hci_vhci' has devname (vhci) but lacks major and
> minor information. Ignoring.
> 
> Regards,
> 


Paul Bolle

^ 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