* [PATCH v3 10/15] Bluetooth: Limit acceptable link key types to only supported ones
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
The link keys that are loaded by userspace during controller setup
should be limited to actual valid and supported types. With the
support for Secure Connections, it is limited to types 0x00 - 0x08
at the moment. Reject any other link key types.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/mgmt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 68a3c998d19c..9b162038acb7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2241,7 +2241,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
for (i = 0; i < key_count; i++) {
struct mgmt_link_key_info *key = &cp->keys[i];
- if (key->addr.type != BDADDR_BREDR)
+ if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 09/15] Bluetooth: Enable Secure Connection during power on if configured
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
If support for Secure Connection has been configured, then make sure
to send the appropiate HCI command to enable it when powering on the
controller.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_core.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 52e398f37129..b3b619a448b5 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1363,6 +1363,14 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
/* Check for Synchronization Train support */
if (lmp_sync_train_capable(hdev))
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
+
+ /* Enable Secure Connections if supported and configured */
+ if (lmp_sc_capable(hdev) &&
+ test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+ u8 support = 0x01;
+ hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
+ sizeof(support), &support);
+ }
}
static int __hci_init(struct hci_dev *hdev)
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 08/15] Bluetooth: Add management command for enabling Secure Connections
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
The support for Secure Connections need to be explicitly enabled by
userspace. This is required since only userspace that can handle the
new link key types should enable support for Secure Connections.
This command handling is similar to how Secure Simple Pairing enabling
is done. It also tracks the case when Secure Connections support is
enabled via raw HCI commands. This makes sure that the host features
page is updated as well.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci_core.h | 1 +
include/net/bluetooth/mgmt.h | 2 +
net/bluetooth/hci_event.c | 32 ++++++++++++
net/bluetooth/mgmt.c | 106 +++++++++++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bb984d0626b7..1eb55ec40ac0 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1125,6 +1125,7 @@ void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status);
void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
+void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
u8 status);
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4ec17dec62e0..8a2c78175997 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -370,6 +370,8 @@ struct mgmt_cp_set_scan_params {
} __packed;
#define MGMT_SET_SCAN_PARAMS_SIZE 4
+#define MGMT_OP_SET_SECURE_CONN 0x002D
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b3c5396e0c1b..820a01965ce3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -461,6 +461,34 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
}
}
+static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ struct hci_cp_write_sc_support *sent;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
+ if (!sent)
+ return;
+
+ if (!status) {
+ if (sent->support)
+ hdev->features[1][0] |= LMP_HOST_SC;
+ else
+ hdev->features[1][0] &= ~LMP_HOST_SC;
+ }
+
+ if (test_bit(HCI_MGMT, &hdev->dev_flags))
+ mgmt_sc_enable_complete(hdev, sent->support, status);
+ else if (!status) {
+ if (sent->support)
+ set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
+ else
+ clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
+ }
+}
+
static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_read_local_version *rp = (void *) skb->data;
@@ -2147,6 +2175,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_write_ssp_mode(hdev, skb);
break;
+ case HCI_OP_WRITE_SC_SUPPORT:
+ hci_cc_write_sc_support(hdev, skb);
+ break;
+
case HCI_OP_READ_LOCAL_VERSION:
hci_cc_read_local_version(hdev, skb);
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b00fa0253cba..68a3c998d19c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4006,6 +4006,79 @@ unlock:
return err;
}
+static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_mode *cp = data;
+ struct pending_cmd *cmd;
+ u8 status;
+ int err;
+
+ BT_DBG("request for %s", hdev->name);
+
+ status = mgmt_bredr_support(hdev);
+ if (status)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
+ status);
+
+ if (!lmp_sc_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
+ MGMT_STATUS_NOT_SUPPORTED);
+
+ if (cp->val != 0x00 && cp->val != 0x01)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ hci_dev_lock(hdev);
+
+ if (!hdev_is_powered(hdev)) {
+ bool changed;
+
+ if (cp->val)
+ changed = !test_and_set_bit(HCI_SC_ENABLED,
+ &hdev->dev_flags);
+ else
+ changed = test_and_clear_bit(HCI_SC_ENABLED,
+ &hdev->dev_flags);
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
+ if (err < 0)
+ goto failed;
+
+ if (changed)
+ err = new_settings(hdev, sk);
+
+ goto failed;
+ }
+
+ if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
+ MGMT_STATUS_BUSY);
+ goto failed;
+ }
+
+ if (!!cp->val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+ err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
+ goto failed;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &cp->val);
+ if (err < 0) {
+ mgmt_pending_remove(cmd);
+ goto failed;
+ }
+
+failed:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static bool ltk_is_valid(struct mgmt_ltk_info *key)
{
if (key->authenticated != 0x00 && key->authenticated != 0x01)
@@ -4134,6 +4207,7 @@ static const struct mgmt_handler {
{ set_bredr, false, MGMT_SETTING_SIZE },
{ set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
{ set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
+ { set_secure_conn, false, MGMT_SETTING_SIZE },
};
@@ -4917,6 +4991,38 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
hci_req_run(&req, NULL);
}
+void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
+{
+ struct cmd_lookup match = { NULL, hdev };
+ bool changed = false;
+
+ if (status) {
+ u8 mgmt_err = mgmt_status(status);
+
+ if (enable && test_and_clear_bit(HCI_SC_ENABLED,
+ &hdev->dev_flags))
+ new_settings(hdev, NULL);
+
+ mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
+ cmd_status_rsp, &mgmt_err);
+ return;
+ }
+
+ if (enable)
+ changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
+ else
+ changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
+
+ mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
+ settings_rsp, &match);
+
+ if (changed)
+ new_settings(hdev, match.sk);
+
+ if (match.sk)
+ sock_put(match.sk);
+}
+
static void sk_lookup(struct pending_cmd *cmd, void *data)
{
struct cmd_lookup *match = data;
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 07/15] Bluetooth: Add flags and setting for Secure Connections support
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
The MGMT_SETTING_SECURE_CONN setting is used to track the support and
status for Secure Connections from the management interface. For HCI
based tracking HCI_SC_ENABLED flag is used.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/mgmt.h | 1 +
net/bluetooth/mgmt.c | 7 +++++++
3 files changed, 9 insertions(+)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 8d888bc432c6..0253276e88e4 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -122,6 +122,7 @@ enum {
HCI_LE_SCAN,
HCI_SSP_ENABLED,
+ HCI_SC_ENABLED,
HCI_HS_ENABLED,
HCI_LE_ENABLED,
HCI_ADVERTISING,
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 518c5c84e39a..4ec17dec62e0 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -94,6 +94,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_ADVERTISING 0x00000400
+#define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a03ca3ca91bf..b00fa0253cba 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -79,6 +79,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_SET_BREDR,
MGMT_OP_SET_STATIC_ADDRESS,
MGMT_OP_SET_SCAN_PARAMS,
+ MGMT_OP_SET_SECURE_CONN,
};
static const u16 mgmt_events[] = {
@@ -376,6 +377,9 @@ static u32 get_supported_settings(struct hci_dev *hdev)
settings |= MGMT_SETTING_SSP;
settings |= MGMT_SETTING_HS;
}
+
+ if (lmp_sc_capable(hdev))
+ settings |= MGMT_SETTING_SECURE_CONN;
}
if (lmp_le_capable(hdev)) {
@@ -423,6 +427,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
settings |= MGMT_SETTING_ADVERTISING;
+ if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
+ settings |= MGMT_SETTING_SECURE_CONN;
+
return settings;
}
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 06/15] Bluetooth: Enable Authenticated Payload Timeout Expired event
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
With Secure Connections capable controllers, the authenticated payload
timeout can trigger. Enable the event so the controller informs the
host when this happens.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5e8663c194c1..52e398f37129 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1288,6 +1288,10 @@ static void hci_set_event_mask_page_2(struct hci_request *req)
events[2] |= 0x08; /* Truncated Page Complete */
}
+ /* Enable Authenticated Payload Timeout Expired event if supported */
+ if (lmp_ping_capable(hdev))
+ events[2] |= 0x80;
+
hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events);
}
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 05/15] Bluetooth: Add support for handling P-256 derived link keys
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
Before being able to enable Secure Connections support, the core needs
to know on how to handle P-256 derived link keys. The difference between
authenticated and unauthenticated P-256 derived link keys is the same as
its P-192 counter parts.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_conn.c | 6 ++++--
net/bluetooth/hci_event.c | 3 ++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 251f22e32fbf..cf96b3438a91 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -802,12 +802,14 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
/* An authenticated combination key has sufficient security for any
security level. */
- if (conn->key_type == HCI_LK_AUTH_COMBINATION_P192)
+ if (conn->key_type == HCI_LK_AUTH_COMBINATION_P192 ||
+ conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
goto encrypt;
/* An unauthenticated combination key has sufficient security for
security level 1 and 2. */
- if (conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 &&
+ if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 ||
+ conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) &&
(sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
goto encrypt;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index defa1252b534..b3c5396e0c1b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2633,7 +2633,8 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
- if (key->type == HCI_LK_UNAUTH_COMBINATION_P192 &&
+ if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
+ key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
BT_DBG("%s ignoring unauthenticated key", hdev->name);
goto not_found;
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 04/15] Bluetooth: Add definitions for new link key types
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
With the introduction of Secure Connections, the list of link key types
got extended by P-256 versions of authenticated and unauthenticated
link keys.
To avoid any confusion the previous authenticated and unauthenticated
link key types got ammended with a P912 postfix. And the two new keys
have a P256 postfix now. Existing code using the previous definitions
has been adjusted.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci.h | 6 ++++--
net/bluetooth/hci_conn.c | 4 ++--
net/bluetooth/hci_event.c | 2 +-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e4e94bfc5232..8d888bc432c6 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -331,9 +331,11 @@ enum {
#define HCI_LK_LOCAL_UNIT 0x01
#define HCI_LK_REMOTE_UNIT 0x02
#define HCI_LK_DEBUG_COMBINATION 0x03
-#define HCI_LK_UNAUTH_COMBINATION 0x04
-#define HCI_LK_AUTH_COMBINATION 0x05
+#define HCI_LK_UNAUTH_COMBINATION_P192 0x04
+#define HCI_LK_AUTH_COMBINATION_P192 0x05
#define HCI_LK_CHANGED_COMBINATION 0x06
+#define HCI_LK_UNAUTH_COMBINATION_P256 0x07
+#define HCI_LK_AUTH_COMBINATION_P256 0x08
/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
#define HCI_SMP_STK 0x80
#define HCI_SMP_STK_SLAVE 0x81
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ba5366c320da..251f22e32fbf 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -802,12 +802,12 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
/* An authenticated combination key has sufficient security for any
security level. */
- if (conn->key_type == HCI_LK_AUTH_COMBINATION)
+ if (conn->key_type == HCI_LK_AUTH_COMBINATION_P192)
goto encrypt;
/* An unauthenticated combination key has sufficient security for
security level 1 and 2. */
- if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
+ if (conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 &&
(sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
goto encrypt;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index cfcce448957b..defa1252b534 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2633,7 +2633,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
- if (key->type == HCI_LK_UNAUTH_COMBINATION &&
+ if (key->type == HCI_LK_UNAUTH_COMBINATION_P192 &&
conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
BT_DBG("%s ignoring unauthenticated key", hdev->name);
goto not_found;
--
1.8.4.2
^ permalink raw reply related
* [PATCH v3 03/15] Bluetooth: Add HCI command definition for extended OOB data
From: Marcel Holtmann @ 2014-01-10 9:29 UTC (permalink / raw)
To: linux-bluetooth
The Secure Connections feature introduces the support for P-256 strength
pairings (compared to P-192 with Secure Simple Pairing). This however
means that for out-of-band pairing the hash and randomizer needs to be
differentiated. Two new commands are introduced to handle the possible
combinations of P-192 and P-256. This add the HCI command definition
for both.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 2a35d273de2c..e4e94bfc5232 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -664,6 +664,15 @@ struct hci_rp_set_csb {
#define HCI_OP_START_SYNC_TRAIN 0x0443
+#define HCI_OP_REMOTE_OOB_EXT_DATA_REPLY 0x0445
+struct hci_cp_remote_oob_ext_data_reply {
+ bdaddr_t bdaddr;
+ __u8 hash192[16];
+ __u8 randomizer192[16];
+ __u8 hash256[16];
+ __u8 randomizer256[16];
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
@@ -948,6 +957,15 @@ struct hci_cp_write_sc_support {
__u8 support;
} __packed;
+#define HCI_OP_READ_LOCAL_OOB_EXT_DATA 0x0c7d
+struct hci_rp_read_local_oob_ext_data {
+ __u8 status;
+ __u8 hash192[16];
+ __u8 randomizer192[16];
+ __u8 hash256[16];
+ __u8 randomizer256[16];
+} __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 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox