2015-08-27 15:54:49

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCH 1/5] emulator: Fix LE Connection Complete Event data

This sets LE Connection Complete Event paramaters based on parameters
from LE Create Connection command.
Event parameters like Conn_Interval and Supervision_Timeout
shouldn't be set to 0.
---
emulator/btdev.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index e4c85f8..319d434 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -1085,20 +1085,22 @@ static void sco_conn_complete(struct btdev *btdev, uint8_t status)
send_event(btdev, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc));
}

-static void le_conn_complete(struct btdev *btdev,
- const uint8_t *bdaddr, uint8_t bdaddr_type,
- uint8_t status)
+static void le_conn_complete(struct btdev *btdev, const void *cmd,
+ uint8_t status)
{
char buf[1 + sizeof(struct bt_hci_evt_le_conn_complete)];
struct bt_hci_evt_le_conn_complete *cc = (void *) &buf[1];
+ const struct bt_hci_cmd_le_create_conn *lecc = cmd;

memset(buf, 0, sizeof(buf));

buf[0] = BT_HCI_EVT_LE_CONN_COMPLETE;

if (!status) {
- struct btdev *remote = find_btdev_by_bdaddr_type(bdaddr,
- bdaddr_type);
+ struct btdev *remote;
+
+ remote = find_btdev_by_bdaddr_type(lecc->peer_addr,
+ lecc->peer_addr_type);

btdev->conn = remote;
btdev->le_adv_enable = 0;
@@ -1114,6 +1116,9 @@ static void le_conn_complete(struct btdev *btdev,

cc->role = 0x01;
cc->handle = cpu_to_le16(42);
+ cc->interval = lecc->max_interval;
+ cc->latency = lecc->latency;
+ cc->supv_timeout = lecc->supv_timeout;

send_event(remote, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));

@@ -1121,8 +1126,8 @@ static void le_conn_complete(struct btdev *btdev,
}

cc->status = status;
- cc->peer_addr_type = bdaddr_type;
- memcpy(cc->peer_addr, bdaddr, 6);
+ cc->peer_addr_type = lecc->peer_addr_type;
+ memcpy(cc->peer_addr, lecc->peer_addr, 6);
cc->role = 0x00;

send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
@@ -1164,16 +1169,17 @@ static bool adv_connectable(struct btdev *btdev)
return btdev->le_adv_type != 0x03;
}

-static void le_conn_request(struct btdev *btdev, const uint8_t *bdaddr,
- uint8_t bdaddr_type)
+static void le_conn_request(struct btdev *btdev, const void *cmd)
{
- struct btdev *remote = find_btdev_by_bdaddr_type(bdaddr, bdaddr_type);
+ const struct bt_hci_cmd_le_create_conn *lecc = cmd;
+ struct btdev *remote = find_btdev_by_bdaddr_type(lecc->peer_addr,
+ lecc->peer_addr_type);

if (remote && adv_connectable(remote) && adv_match(btdev, remote) &&
- remote->le_adv_own_addr == bdaddr_type)
- le_conn_complete(btdev, bdaddr, bdaddr_type, 0);
+ remote->le_adv_own_addr == lecc->peer_addr_type)
+ le_conn_complete(btdev, lecc, 0);
else
- le_conn_complete(btdev, bdaddr, bdaddr_type,
+ le_conn_complete(btdev, lecc,
BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
}

@@ -3314,7 +3320,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
return;
lecc = data;
btdev->le_scan_own_addr_type = lecc->own_addr_type;
- le_conn_request(btdev, lecc->peer_addr, lecc->peer_addr_type);
+ le_conn_request(btdev, lecc);
break;

case BT_HCI_CMD_LE_CONN_UPDATE:
--
2.4.3



2015-08-31 10:18:08

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCHv2 6/6] emulator: Refactor le set scan enable command handler

le_set_scan_enable_complete should be called as post hook action.
---
emulator/btdev.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 7ff750d..e8cead8 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -3005,8 +3005,6 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
status = BT_HCI_ERR_SUCCESS;
}
cmd_complete(btdev, opcode, &status, sizeof(status));
- if (status == BT_HCI_ERR_SUCCESS && btdev->le_scan_enable)
- le_set_scan_enable_complete(btdev);
break;

case BT_HCI_CMD_LE_CREATE_CONN:
@@ -3254,6 +3252,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_conn_update *lecu;
const struct bt_hci_cmd_le_conn_param_req_reply *lcprr;
const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr;
+ const struct bt_hci_cmd_le_set_scan_enable *lsse;

switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3441,6 +3440,14 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
rej_le_conn_update(btdev, le16_to_cpu(lcprnr->handle),
le16_to_cpu(lcprnr->reason));
break;
+ break;
+ case BT_HCI_CMD_LE_SET_SCAN_ENABLE:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ return;
+ lsse = data;
+ if (btdev->le_scan_enable && lsse->enable)
+ le_set_scan_enable_complete(btdev);
+
}
}

--
2.4.3


2015-08-31 10:18:06

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCHv2 4/6] emulator: Add support for LE Remote Connection Parameter Request Negative Reply

< HCI Command: LE Connection Update (0x08|0x0013) plen 14
[hci1] 915.472416
Handle: 42
Min connection interval: 0.00 msec (0x0000)
Max connection interval: 18.75 msec (0x000f)
Connection latency: 0x0000
Supervision timeout: 32000 msec (0x0c80)
Min connection length: 0.625 msec (0x0001)
Max connection length: 0.625 msec (0x0001)
> HCI Event: Command Status (0x0f) plen 4 [hci1] 915.472432
LE Connection Update (0x08|0x0013) ncmd 1
Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 11 [hci0] 915.472443
LE Remote Connection Parameter Request (0x06)
Handle: 42
Min connection interval: 0.00 msec (0x0000)
Max connection interval: 18.75 msec (0x000f)
Connection latency: 0x0000
Supervision timeout: 32000 msec (0x0c80)
< HCI Command: LE Remote Connection Parameter Request Negative Reply
(0x08|0x0021) plen 3 [hci0] 915.474095
Handle: 42
Reason: Invalid LMP Parameters / Invalid LL Parameters (0x1e)
> HCI Event: Command Complete (0x0e) plen 6 [hci0] 915.474119
LE Remote Connection Parameter Request Negative Reply
(0x08|0x0021) ncmd 1
Status: Success (0x00)
Handle: 42
> HCI Event: LE Meta Event (0x3e) plen 10 [hci1] 915.474124
LE Connection Update Complete (0x03)
Status: Invalid LMP Parameters / Invalid LL Parameters (0x1e)
Handle: 42
Connection interval: 4800.00 msec (0x0f00)
Connection latency: 0.00 msec (0x0000)
Supervision timeout: 327680 msec (0x8000)

LE Connection Update rejected due to invalid parameter:
Min connection interval: 0.00 msec (0x0000)
---
emulator/btdev.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 1395ec8..a3c73d9 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -445,6 +445,7 @@ static void set_le_commands(struct btdev *btdev)

/* Extra LE commands for >= 4.1 adapters */
btdev->commands[33] |= 0x10; /* LE Remote Conn Param Req Reply */
+ btdev->commands[33] |= 0x20; /* LE Remote Conn Param Req Neg Reply */

/* Extra LE commands for >= 4.2 adapters */
btdev->commands[34] |= 0x02; /* LE Read Local P-256 Public Key */
@@ -1211,6 +1212,25 @@ static void conn_request(struct btdev *btdev, const uint8_t *bdaddr)
}
}

+static void rej_le_conn_update(struct btdev *btdev, uint16_t handle,
+ uint8_t reason)
+{
+ struct btdev *remote = btdev->conn;
+ struct __packed {
+ uint8_t subevent;
+ struct bt_hci_evt_le_conn_update_complete ev;
+ } ev;
+
+ if (!remote)
+ return;
+
+ ev.subevent = BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE;
+ ev.ev.handle = cpu_to_le16(handle);
+ ev.ev.status = cpu_to_le16(reason);
+
+ send_event(remote, BT_HCI_EVT_LE_META_EVENT, &ev, sizeof(ev));
+}
+
static void le_conn_update(struct btdev *btdev, uint16_t handle,
uint16_t min_interval, uint16_t max_interval,
uint16_t latency, uint16_t supv_timeout,
@@ -2033,6 +2053,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_encrypt *lenc_cmd;
const struct bt_hci_cmd_le_generate_dhkey *dh;
const struct bt_hci_cmd_le_conn_param_req_reply *lcprr_cmd;
+ const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr_cmd;
const struct bt_hci_cmd_read_local_amp_assoc *rlaa_cmd;
const struct bt_hci_cmd_read_rssi *rrssi;
const struct bt_hci_cmd_read_tx_power *rtxp;
@@ -2075,6 +2096,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
struct bt_hci_rsp_read_local_amp_assoc rlaa_rsp;
struct bt_hci_rsp_get_mws_transport_config *gmtc;
struct bt_hci_rsp_le_conn_param_req_reply lcprr_rsp;
+ struct bt_hci_rsp_le_conn_param_req_neg_reply lcprnr_rsp;
struct bt_hci_rsp_le_read_buffer_size lrbs;
struct bt_hci_rsp_le_read_local_features lrlf;
struct bt_hci_rsp_le_read_adv_tx_power lratp;
@@ -3187,6 +3209,14 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
lcprr_rsp.status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &lcprr_rsp, sizeof(lcprr_rsp));
break;
+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_NEG_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ goto unsupported;
+ lcprnr_cmd = data;
+ lcprnr_rsp.handle = lcprnr_cmd->handle;
+ lcprnr_rsp.status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &lcprnr_rsp, sizeof(lcprnr_rsp));
+ break;
default:
goto unsupported;
}
@@ -3222,6 +3252,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_create_conn *lecc;
const struct bt_hci_cmd_le_conn_update *lecu;
const struct bt_hci_cmd_le_conn_param_req_reply *lcprr;
+ const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr;

switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3402,6 +3433,13 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
le16_to_cpu(lcprr->min_length),
le16_to_cpu(lcprr->max_length));
break;
+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_NEG_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ return;
+ lcprnr = data;
+ rej_le_conn_update(btdev, le16_to_cpu(lcprnr->handle),
+ le16_to_cpu(lcprnr->reason));
+ break;
}
}

--
2.4.3


2015-08-31 10:18:07

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCHv2 5/6] emulator: Enable Slave-initiated Features Exchange feature

---
emulator/btdev.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index a3c73d9..7ff750d 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -567,6 +567,7 @@ static void set_le_features(struct btdev *btdev)

btdev->le_features[0] |= 0x01; /* LE Encryption */
btdev->le_features[0] |= 0x02; /* Connection Parameters Request */
+ btdev->le_features[0] |= 0x08; /* Slave-initiated Features Exchange */
}

static void set_amp_features(struct btdev *btdev)
--
2.4.3


2015-08-31 10:18:05

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCHv2 3/6] emulator: Add support for LE Remote Connection Parameter Request Reply

< HCI Command: LE Connection Update (0x08|0x0013) plen 14
[hci0] 92750.079447
Handle: 42
Min connection interval: 50.00 msec (0x0028)
Max connection interval: 70.00 msec (0x0038)
Connection latency: 0x0000
Supervision timeout: 420 msec (0x002a)
Min connection length: 0.000 msec (0x0000)
Max connection length: 0.000 msec (0x0000)
> HCI Event: Command Status (0x0f) plen 4
[hci0] 92750.079459
LE Connection Update (0x08|0x0013) ncmd 1
Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 11
[hci1] 92750.079462
LE Remote Connection Parameter Request (0x06)
Handle: 42
Min connection interval: 50.00 msec (0x0028)
Max connection interval: 70.00 msec (0x0038)
Connection latency: 0x0000
Supervision timeout: 420 msec (0x002a)
< HCI Command: LE Remote Connection Parameter Request Reply
(0x08|0x0020) plen 14 [hci1] 92750.079476
Handle: 42
Min connection interval: 50.00 msec (0x0028)
Max connection interval: 70.00 msec (0x0038)
Connection latency: 0x0000
Supervision timeout: 420 msec (0x002a)
Min connection length: 0.000 msec (0x0000)
Max connection length: 0.000 msec (0x0000)
> HCI Event: Command Complete (0x0e) plen 6
[hci1] 92750.079507
LE Remote Connection Parameter Request Reply (0x08|0x0020)
ncmd 1
Status: Success (0x00)
Handle: 42
> HCI Event: LE Meta Event (0x3e) plen 10
[hci0] 92750.079510
LE Connection Update Complete (0x03)
Status: Success (0x00)
Handle: 42
Connection interval: 50.00 msec (0x0028)
Connection latency: 0.00 msec (0x0000)
Supervision timeout: 420 msec (0x002a)
> HCI Event: LE Meta Event (0x3e) plen 10
[hci1] 92750.079509
LE Connection Update Complete (0x03)
Status: Success (0x00)
Handle: 42
Connection interval: 50.00 msec (0x0028)
Connection latency: 0.00 msec (0x0000)
Supervision timeout: 420 msec (0x002a)
@ New Conn Param: 00:AA:01:00:00:23 (1) hint 0 min 0x0028 max 0x0038
latency 0x0000 timeout 0x002a
---
emulator/btdev.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 67 insertions(+), 7 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 77a83ef..1395ec8 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -443,6 +443,9 @@ static void set_le_commands(struct btdev *btdev)
btdev->commands[28] |= 0x20; /* LE Transmitter Test */
btdev->commands[28] |= 0x40; /* LE Test End */

+ /* Extra LE commands for >= 4.1 adapters */
+ btdev->commands[33] |= 0x10; /* LE Remote Conn Param Req Reply */
+
/* Extra LE commands for >= 4.2 adapters */
btdev->commands[34] |= 0x02; /* LE Read Local P-256 Public Key */
btdev->commands[34] |= 0x04; /* LE Generate DHKey */
@@ -562,6 +565,7 @@ static void set_le_features(struct btdev *btdev)
btdev->max_page = 1;

btdev->le_features[0] |= 0x01; /* LE Encryption */
+ btdev->le_features[0] |= 0x02; /* Connection Parameters Request */
}

static void set_amp_features(struct btdev *btdev)
@@ -1235,6 +1239,30 @@ static void le_conn_update(struct btdev *btdev, uint16_t handle,
send_event(remote, BT_HCI_EVT_LE_META_EVENT, &ev, sizeof(ev));
}

+static void le_conn_param_req(struct btdev *btdev, uint16_t handle,
+ uint16_t min_interval, uint16_t max_interval,
+ uint16_t latency, uint16_t supv_timeout,
+ uint16_t min_length, uint16_t max_length)
+{
+ struct btdev *remote = btdev->conn;
+ struct __packed {
+ uint8_t subevent;
+ struct bt_hci_evt_le_conn_param_request ev;
+ } ev;
+
+ if (!remote)
+ return;
+
+ ev.subevent = BT_HCI_EVT_LE_CONN_PARAM_REQUEST;
+ ev.ev.handle = cpu_to_le16(handle);
+ ev.ev.min_interval = cpu_to_le16(min_interval);
+ ev.ev.max_interval = cpu_to_le16(max_interval);
+ ev.ev.latency = cpu_to_le16(latency);
+ ev.ev.supv_timeout = cpu_to_le16(supv_timeout);
+
+ send_event(remote, BT_HCI_EVT_LE_META_EVENT, &ev, sizeof(ev));
+}
+
static void disconnect_complete(struct btdev *btdev, uint16_t handle,
uint8_t reason)
{
@@ -2004,6 +2032,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_ltk_req_reply *llrr;
const struct bt_hci_cmd_le_encrypt *lenc_cmd;
const struct bt_hci_cmd_le_generate_dhkey *dh;
+ const struct bt_hci_cmd_le_conn_param_req_reply *lcprr_cmd;
const struct bt_hci_cmd_read_local_amp_assoc *rlaa_cmd;
const struct bt_hci_cmd_read_rssi *rrssi;
const struct bt_hci_cmd_read_tx_power *rtxp;
@@ -2045,6 +2074,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
struct bt_hci_rsp_read_local_amp_info rlai;
struct bt_hci_rsp_read_local_amp_assoc rlaa_rsp;
struct bt_hci_rsp_get_mws_transport_config *gmtc;
+ struct bt_hci_rsp_le_conn_param_req_reply lcprr_rsp;
struct bt_hci_rsp_le_read_buffer_size lrbs;
struct bt_hci_rsp_le_read_local_features lrlf;
struct bt_hci_rsp_le_read_adv_tx_power lratp;
@@ -3149,6 +3179,14 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &lte, sizeof(lte));
break;

+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ goto unsupported;
+ lcprr_cmd = data;
+ lcprr_rsp.handle = lcprr_cmd->handle;
+ lcprr_rsp.status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &lcprr_rsp, sizeof(lcprr_rsp));
+ break;
default:
goto unsupported;
}
@@ -3183,6 +3221,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_read_clock_offset *rco;
const struct bt_hci_cmd_le_create_conn *lecc;
const struct bt_hci_cmd_le_conn_update *lecu;
+ const struct bt_hci_cmd_le_conn_param_req_reply *lcprr;

switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3334,13 +3373,34 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
if (btdev->type == BTDEV_TYPE_BREDR)
return;
lecu = data;
- le_conn_update(btdev, le16_to_cpu(lecu->handle),
- le16_to_cpu(lecu->min_interval),
- le16_to_cpu(lecu->max_interval),
- le16_to_cpu(lecu->latency),
- le16_to_cpu(lecu->supv_timeout),
- le16_to_cpu(lecu->min_length),
- le16_to_cpu(lecu->max_length));
+ if (btdev->le_features[0] & 0x02)
+ le_conn_param_req(btdev, le16_to_cpu(lecu->handle),
+ le16_to_cpu(lecu->min_interval),
+ le16_to_cpu(lecu->max_interval),
+ le16_to_cpu(lecu->latency),
+ le16_to_cpu(lecu->supv_timeout),
+ le16_to_cpu(lecu->min_length),
+ le16_to_cpu(lecu->max_length));
+ else
+ le_conn_update(btdev, le16_to_cpu(lecu->handle),
+ le16_to_cpu(lecu->min_interval),
+ le16_to_cpu(lecu->max_interval),
+ le16_to_cpu(lecu->latency),
+ le16_to_cpu(lecu->supv_timeout),
+ le16_to_cpu(lecu->min_length),
+ le16_to_cpu(lecu->max_length));
+ break;
+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ return;
+ lcprr = data;
+ le_conn_update(btdev, le16_to_cpu(lcprr->handle),
+ le16_to_cpu(lcprr->min_interval),
+ le16_to_cpu(lcprr->max_interval),
+ le16_to_cpu(lcprr->latency),
+ le16_to_cpu(lcprr->supv_timeout),
+ le16_to_cpu(lcprr->min_length),
+ le16_to_cpu(lcprr->max_length));
break;
}
}
--
2.4.3


2015-08-31 10:18:04

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCHv2 2/6] emulator: Remove duplicated assignment

Connection handle has been already assigned few lines earlier.
---
emulator/btdev.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index f3ef1ca..77a83ef 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -1130,8 +1130,6 @@ static void le_conn_complete(struct btdev *btdev,
cc->supv_timeout = lecc->supv_timeout;

send_event(remote, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
-
- cc->handle = cpu_to_le16(42);
}

cc->status = status;
--
2.4.3


2015-08-31 10:18:03

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCHv2 1/6] emulator: Fix LE Connection Complete Event data

This sets LE Connection Complete Event paramaters based on parameters
from LE Create Connection command.
Event parameters like Conn_Interval and Supervision_Timeout
shouldn't be set to 0.
---
emulator/btdev.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index ceefd56..f3ef1ca 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -1095,8 +1095,8 @@ static void sco_conn_complete(struct btdev *btdev, uint8_t status)
}

static void le_conn_complete(struct btdev *btdev,
- const uint8_t *bdaddr, uint8_t bdaddr_type,
- uint8_t status)
+ const struct bt_hci_cmd_le_create_conn *lecc,
+ uint8_t status)
{
char buf[1 + sizeof(struct bt_hci_evt_le_conn_complete)];
struct bt_hci_evt_le_conn_complete *cc = (void *) &buf[1];
@@ -1106,8 +1106,10 @@ static void le_conn_complete(struct btdev *btdev,
buf[0] = BT_HCI_EVT_LE_CONN_COMPLETE;

if (!status) {
- struct btdev *remote = find_btdev_by_bdaddr_type(bdaddr,
- bdaddr_type);
+ struct btdev *remote;
+
+ remote = find_btdev_by_bdaddr_type(lecc->peer_addr,
+ lecc->peer_addr_type);

btdev->conn = remote;
btdev->le_adv_enable = 0;
@@ -1123,6 +1125,9 @@ static void le_conn_complete(struct btdev *btdev,

cc->role = 0x01;
cc->handle = cpu_to_le16(42);
+ cc->interval = lecc->max_interval;
+ cc->latency = lecc->latency;
+ cc->supv_timeout = lecc->supv_timeout;

send_event(remote, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));

@@ -1130,8 +1135,8 @@ static void le_conn_complete(struct btdev *btdev,
}

cc->status = status;
- cc->peer_addr_type = bdaddr_type;
- memcpy(cc->peer_addr, bdaddr, 6);
+ cc->peer_addr_type = lecc->peer_addr_type;
+ memcpy(cc->peer_addr, lecc->peer_addr, 6);
cc->role = 0x00;

send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
@@ -1173,16 +1178,17 @@ static bool adv_connectable(struct btdev *btdev)
return btdev->le_adv_type != 0x03;
}

-static void le_conn_request(struct btdev *btdev, const uint8_t *bdaddr,
- uint8_t bdaddr_type)
+static void le_conn_request(struct btdev *btdev,
+ const struct bt_hci_cmd_le_create_conn *lecc)
{
- struct btdev *remote = find_btdev_by_bdaddr_type(bdaddr, bdaddr_type);
+ struct btdev *remote = find_btdev_by_bdaddr_type(lecc->peer_addr,
+ lecc->peer_addr_type);

if (remote && adv_connectable(remote) && adv_match(btdev, remote) &&
- remote->le_adv_own_addr == bdaddr_type)
- le_conn_complete(btdev, bdaddr, bdaddr_type, 0);
+ remote->le_adv_own_addr == lecc->peer_addr_type)
+ le_conn_complete(btdev, lecc, 0);
else
- le_conn_complete(btdev, bdaddr, bdaddr_type,
+ le_conn_complete(btdev, lecc,
BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
}

@@ -3323,7 +3329,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
return;
lecc = data;
btdev->le_scan_own_addr_type = lecc->own_addr_type;
- le_conn_request(btdev, lecc->peer_addr, lecc->peer_addr_type);
+ le_conn_request(btdev, lecc);
break;

case BT_HCI_CMD_LE_CONN_UPDATE:
--
2.4.3


2015-08-29 03:25:22

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 2/5] emulator: Update LE supported commands

Hi Mariusz,

On Thu, Aug 27, 2015, Mariusz Skamra wrote:
> ---
> emulator/btdev.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/emulator/btdev.c b/emulator/btdev.c
> index 319d434..b285b2a 100644
> --- a/emulator/btdev.c
> +++ b/emulator/btdev.c
> @@ -420,15 +420,24 @@ static void set_le_commands(struct btdev *btdev)
> btdev->commands[25] |= 0x01; /* LE Set Event Mask */
> btdev->commands[25] |= 0x02; /* LE Read Buffer Size */
> btdev->commands[25] |= 0x04; /* LE Read Local Features */
> + btdev->commands[25] |= 0x10; /* LE Set Random Address */
> btdev->commands[25] |= 0x20; /* LE Set Adv Parameters */
> btdev->commands[25] |= 0x40; /* LE Read Adv TX Power */
> btdev->commands[25] |= 0x80; /* LE Set Adv Data */
> + btdev->commands[26] |= 0x01; /* LE Set Scan Response Data */
> btdev->commands[26] |= 0x02; /* LE Set Adv Enable */
> btdev->commands[26] |= 0x04; /* LE Set Scan Parameters */
> btdev->commands[26] |= 0x08; /* LE Set Scan Enable */
> + btdev->commands[26] |= 0x10; /* LE Create Connection */
> btdev->commands[26] |= 0x40; /* LE Read White List Size */
> + btdev->commands[26] |= 0x80; /* LE Clear White List */
> + btdev->commands[27] |= 0x04; /* LE Connection Update */
> + btdev->commands[27] |= 0x20; /* LE Read Remote Used Features */
> btdev->commands[27] |= 0x40; /* LE Encrypt */
> btdev->commands[27] |= 0x80; /* LE Rand */
> + btdev->commands[28] |= 0x01; /* LE Start Encryption */
> + btdev->commands[28] |= 0x02; /* LE Long Term Key Request Reply */
> + btdev->commands[28] |= 0x04; /* LE Long Term Key Request Neg Reply */
> btdev->commands[28] |= 0x08; /* LE Read Supported States */
> btdev->commands[28] |= 0x10; /* LE Receiver Test */
> btdev->commands[28] |= 0x20; /* LE Transmitter Test */

I'm surprised these were missing. Good catch! I've applied this patch,
so no need to resend it for your future revisions of this set.

Johan

2015-08-29 03:20:25

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 1/5] emulator: Fix LE Connection Complete Event data

Hi Mariusz,

On Thu, Aug 27, 2015, Mariusz Skamra wrote:
> +static void le_conn_complete(struct btdev *btdev, const void *cmd,
> + uint8_t status)
> {
> char buf[1 + sizeof(struct bt_hci_evt_le_conn_complete)];
> struct bt_hci_evt_le_conn_complete *cc = (void *) &buf[1];
> + const struct bt_hci_cmd_le_create_conn *lecc = cmd;

Why the void pointer in the function parameters and then casting it to
the actual one? It'd be simpler and safer if you just passed this as the
right type from the start.

Johan

2015-08-27 15:54:52

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCH 4/5] emulator: Add support for LE Remote Connection Parameter Request Reply

< HCI Command: LE Connection Update (0x08|0x0013) plen 14
[hci0] 92750.079447
Handle: 42
Min connection interval: 50.00 msec (0x0028)
Max connection interval: 70.00 msec (0x0038)
Connection latency: 0x0000
Supervision timeout: 420 msec (0x002a)
Min connection length: 0.000 msec (0x0000)
Max connection length: 0.000 msec (0x0000)
> HCI Event: Command Status (0x0f) plen 4
[hci0] 92750.079459
LE Connection Update (0x08|0x0013) ncmd 1
Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 11
[hci1] 92750.079462
LE Remote Connection Parameter Request (0x06)
Handle: 42
Min connection interval: 50.00 msec (0x0028)
Max connection interval: 70.00 msec (0x0038)
Connection latency: 0x0000
Supervision timeout: 420 msec (0x002a)
< HCI Command: LE Remote Connection Parameter Request Reply
(0x08|0x0020) plen 14 [hci1] 92750.079476
Handle: 42
Min connection interval: 50.00 msec (0x0028)
Max connection interval: 70.00 msec (0x0038)
Connection latency: 0x0000
Supervision timeout: 420 msec (0x002a)
Min connection length: 0.000 msec (0x0000)
Max connection length: 0.000 msec (0x0000)
> HCI Event: Command Complete (0x0e) plen 6
[hci1] 92750.079507
LE Remote Connection Parameter Request Reply (0x08|0x0020)
ncmd 1
Status: Success (0x00)
Handle: 42
> HCI Event: LE Meta Event (0x3e) plen 10
[hci0] 92750.079510
LE Connection Update Complete (0x03)
Status: Success (0x00)
Handle: 42
Connection interval: 50.00 msec (0x0028)
Connection latency: 0.00 msec (0x0000)
Supervision timeout: 420 msec (0x002a)
> HCI Event: LE Meta Event (0x3e) plen 10
[hci1] 92750.079509
LE Connection Update Complete (0x03)
Status: Success (0x00)
Handle: 42
Connection interval: 50.00 msec (0x0028)
Connection latency: 0.00 msec (0x0000)
Supervision timeout: 420 msec (0x002a)
@ New Conn Param: 00:AA:01:00:00:23 (1) hint 0 min 0x0028 max 0x0038
latency 0x0000 timeout 0x002a
---
emulator/btdev.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 95 insertions(+), 7 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 1f8aa44..1de0956 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -443,6 +443,10 @@ static void set_le_commands(struct btdev *btdev)
btdev->commands[28] |= 0x20; /* LE Transmitter Test */
btdev->commands[28] |= 0x40; /* LE Test End */

+ /* Extra LE commands for >= 4.1 adapters */
+ btdev->commands[33] |= 0x10; /* LE Remote Conn Param Req Reply */
+ btdev->commands[33] |= 0x20; /* LE Remote Conn Param Req Neg Reply */
+
/* Extra LE commands for >= 4.2 adapters */
btdev->commands[34] |= 0x02; /* LE Read Local P-256 Public Key */
btdev->commands[34] |= 0x04; /* LE Generate DHKey */
@@ -562,6 +566,7 @@ static void set_le_features(struct btdev *btdev)
btdev->max_page = 1;

btdev->le_features[0] |= 0x01; /* LE Encryption */
+ btdev->le_features[0] |= 0x02; /* Connection Parameters Request */
}

static void set_amp_features(struct btdev *btdev)
@@ -1235,6 +1240,49 @@ static void le_conn_update(struct btdev *btdev, uint16_t handle,
send_event(remote, BT_HCI_EVT_LE_META_EVENT, &ev, sizeof(ev));
}

+static void rej_le_conn_update(struct btdev *btdev, uint16_t handle,
+ uint8_t reason)
+{
+ struct btdev *remote = btdev->conn;
+ struct __packed {
+ uint8_t subevent;
+ struct bt_hci_evt_le_conn_update_complete ev;
+ } ev;
+
+ if (!remote)
+ return;
+
+ ev.subevent = BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE;
+ ev.ev.handle = cpu_to_le16(handle);
+ ev.ev.status = cpu_to_le16(reason);
+
+ send_event(remote, BT_HCI_EVT_LE_META_EVENT, &ev, sizeof(ev));
+}
+
+static void le_conn_param_req(struct btdev *btdev, uint16_t handle,
+ uint16_t min_interval, uint16_t max_interval,
+ uint16_t latency, uint16_t supv_timeout,
+ uint16_t min_length, uint16_t max_length)
+{
+ struct btdev *remote = btdev->conn;
+ struct __packed {
+ uint8_t subevent;
+ struct bt_hci_evt_le_conn_param_request ev;
+ } ev;
+
+ if (!remote)
+ return;
+
+ ev.subevent = BT_HCI_EVT_LE_CONN_PARAM_REQUEST;
+ ev.ev.handle = cpu_to_le16(handle);
+ ev.ev.min_interval = cpu_to_le16(min_interval);
+ ev.ev.max_interval = cpu_to_le16(max_interval);
+ ev.ev.latency = cpu_to_le16(latency);
+ ev.ev.supv_timeout = cpu_to_le16(supv_timeout);
+
+ send_event(remote, BT_HCI_EVT_LE_META_EVENT, &ev, sizeof(ev));
+}
+
static void disconnect_complete(struct btdev *btdev, uint16_t handle,
uint8_t reason)
{
@@ -2004,6 +2052,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_ltk_req_reply *llrr;
const struct bt_hci_cmd_le_encrypt *lenc_cmd;
const struct bt_hci_cmd_le_generate_dhkey *dh;
+ const struct bt_hci_cmd_le_conn_param_req_reply *lcprr_cmd;
const struct bt_hci_cmd_read_local_amp_assoc *rlaa_cmd;
const struct bt_hci_cmd_read_rssi *rrssi;
const struct bt_hci_cmd_read_tx_power *rtxp;
@@ -2045,6 +2094,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
struct bt_hci_rsp_read_local_amp_info rlai;
struct bt_hci_rsp_read_local_amp_assoc rlaa_rsp;
struct bt_hci_rsp_get_mws_transport_config *gmtc;
+ struct bt_hci_rsp_le_conn_param_req_reply lcprr_rsp;
struct bt_hci_rsp_le_read_buffer_size lrbs;
struct bt_hci_rsp_le_read_local_features lrlf;
struct bt_hci_rsp_le_read_adv_tx_power lratp;
@@ -3149,6 +3199,14 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &lte, sizeof(lte));
break;

+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ goto unsupported;
+ lcprr_cmd = data;
+ lcprr_rsp.handle = lcprr_cmd->handle;
+ lcprr_rsp.status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &lcprr_rsp, sizeof(lcprr_rsp));
+ break;
default:
goto unsupported;
}
@@ -3183,6 +3241,8 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_read_clock_offset *rco;
const struct bt_hci_cmd_le_create_conn *lecc;
const struct bt_hci_cmd_le_conn_update *lecu;
+ const struct bt_hci_cmd_le_conn_param_req_reply *lcprr;
+ const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr;

switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3334,13 +3394,41 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
if (btdev->type == BTDEV_TYPE_BREDR)
return;
lecu = data;
- le_conn_update(btdev, le16_to_cpu(lecu->handle),
- le16_to_cpu(lecu->min_interval),
- le16_to_cpu(lecu->max_interval),
- le16_to_cpu(lecu->latency),
- le16_to_cpu(lecu->supv_timeout),
- le16_to_cpu(lecu->min_length),
- le16_to_cpu(lecu->max_length));
+ if (btdev->le_features[0] & 0x02)
+ le_conn_param_req(btdev, le16_to_cpu(lecu->handle),
+ le16_to_cpu(lecu->min_interval),
+ le16_to_cpu(lecu->max_interval),
+ le16_to_cpu(lecu->latency),
+ le16_to_cpu(lecu->supv_timeout),
+ le16_to_cpu(lecu->min_length),
+ le16_to_cpu(lecu->max_length));
+ else
+ le_conn_update(btdev, le16_to_cpu(lecu->handle),
+ le16_to_cpu(lecu->min_interval),
+ le16_to_cpu(lecu->max_interval),
+ le16_to_cpu(lecu->latency),
+ le16_to_cpu(lecu->supv_timeout),
+ le16_to_cpu(lecu->min_length),
+ le16_to_cpu(lecu->max_length));
+ break;
+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ return;
+ lcprr = data;
+ le_conn_update(btdev, le16_to_cpu(lcprr->handle),
+ le16_to_cpu(lcprr->min_interval),
+ le16_to_cpu(lcprr->max_interval),
+ le16_to_cpu(lcprr->latency),
+ le16_to_cpu(lcprr->supv_timeout),
+ le16_to_cpu(lcprr->min_length),
+ le16_to_cpu(lcprr->max_length));
+ break;
+ case BT_HCI_CMD_LE_CONN_PARAM_REQ_NEG_REPLY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ return;
+ lcprnr = data;
+ rej_le_conn_update(btdev, le16_to_cpu(lcprnr->handle),
+ le16_to_cpu(lcprnr->reason));
break;
}
}
--
2.4.3


2015-08-27 15:54:53

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCH 5/5] emulator: Enable Slave-initiated Features Exchange feature

---
emulator/btdev.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 1de0956..c00d71a 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -567,6 +567,7 @@ static void set_le_features(struct btdev *btdev)

btdev->le_features[0] |= 0x01; /* LE Encryption */
btdev->le_features[0] |= 0x02; /* Connection Parameters Request */
+ btdev->le_features[0] |= 0x08; /* Slave-initiated Features Exchange */
}

static void set_amp_features(struct btdev *btdev)
--
2.4.3


2015-08-27 15:54:51

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCH 3/5] emulator: Remove duplicated assignment

Connection handle has been already assigned few lines earlier.
---
emulator/btdev.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index b285b2a..1f8aa44 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -1130,8 +1130,6 @@ static void le_conn_complete(struct btdev *btdev, const void *cmd,
cc->supv_timeout = lecc->supv_timeout;

send_event(remote, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
-
- cc->handle = cpu_to_le16(42);
}

cc->status = status;
--
2.4.3


2015-08-27 15:54:50

by Mariusz Skamra

[permalink] [raw]
Subject: [PATCH 2/5] emulator: Update LE supported commands

---
emulator/btdev.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 319d434..b285b2a 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -420,15 +420,24 @@ static void set_le_commands(struct btdev *btdev)
btdev->commands[25] |= 0x01; /* LE Set Event Mask */
btdev->commands[25] |= 0x02; /* LE Read Buffer Size */
btdev->commands[25] |= 0x04; /* LE Read Local Features */
+ btdev->commands[25] |= 0x10; /* LE Set Random Address */
btdev->commands[25] |= 0x20; /* LE Set Adv Parameters */
btdev->commands[25] |= 0x40; /* LE Read Adv TX Power */
btdev->commands[25] |= 0x80; /* LE Set Adv Data */
+ btdev->commands[26] |= 0x01; /* LE Set Scan Response Data */
btdev->commands[26] |= 0x02; /* LE Set Adv Enable */
btdev->commands[26] |= 0x04; /* LE Set Scan Parameters */
btdev->commands[26] |= 0x08; /* LE Set Scan Enable */
+ btdev->commands[26] |= 0x10; /* LE Create Connection */
btdev->commands[26] |= 0x40; /* LE Read White List Size */
+ btdev->commands[26] |= 0x80; /* LE Clear White List */
+ btdev->commands[27] |= 0x04; /* LE Connection Update */
+ btdev->commands[27] |= 0x20; /* LE Read Remote Used Features */
btdev->commands[27] |= 0x40; /* LE Encrypt */
btdev->commands[27] |= 0x80; /* LE Rand */
+ btdev->commands[28] |= 0x01; /* LE Start Encryption */
+ btdev->commands[28] |= 0x02; /* LE Long Term Key Request Reply */
+ btdev->commands[28] |= 0x04; /* LE Long Term Key Request Neg Reply */
btdev->commands[28] |= 0x08; /* LE Read Supported States */
btdev->commands[28] |= 0x10; /* LE Receiver Test */
btdev->commands[28] |= 0x20; /* LE Transmitter Test */
--
2.4.3