2015-09-23 11:36:54

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-09-23 11:36:59

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-09-23 11:36:58

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-09-23 11:36:57

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-09-23 11:36:56

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-09-23 11:36:55

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-10-05 08:03:33

by Johan Hedberg

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

Hi Mariusz,

On Wed, Sep 23, 2015, Mariusz Skamra wrote:
> 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(-)

All patches in this set have been applied. Thanks.

Johan