From 992e18df97db2a2976108feaecda9ddfbbaee79d Mon Sep 17 00:00:00 2001 From: Arkadiusz Lichwa Date: Mon, 10 Aug 2015 22:23:05 +0200 Subject: [PATCH] Bluetooth: Handle LE Remote Connection Parameters Request Event Adds Remote Connection Parameter Request Event handler and command response handlers to support LL Connection Parameter Update procedure (BT 4.1). < HCI Command: LE Connection Update (0x08|0x0013) plen 14 [hci1] 86319.053586 Handle: 42 Min connection interval: 38.75 msec (0x001f) Max connection interval: 58.75 msec (0x002f) 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] 86319.053597 LE Connection Update (0x08|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 11 [hci0] 86319.053600 LE Remote Connection Parameter Request (0x06) Handle: 42 Min connection interval: 38.75 msec (0x001f) Max connection interval: 58.75 msec (0x002f) Connection latency: 0x0000 Supervision timeout: 32000 msec (0x0c80) ... < HCI Command: LE Remote Connection Parameter Request Reply (0x08|0x0020) plen 14 [hci0] 86319.055663 Handle: 42 Min connection interval: 38.75 msec (0x001f) Max connection interval: 58.75 msec (0x002f) Connection latency: 0x0000 Supervision timeout: 32000 msec (0x0c80) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Complete (0x0e) plen 6 [hci0] 86319.055687 LE Remote Connection Parameter Request Reply (0x08|0x0020) ncmd 1 Status: Success (0x00) Handle: 42 > HCI Event: LE Meta Event (0x3e) plen 10 [hci1] 86319.055694 LE Connection Update Complete (0x03) Status: Success (0x00) Handle: 42 Connection interval: 38.75 msec (0x001f) Connection latency: 0.00 msec (0x0000) Supervision timeout: 32000 msec (0x0c80) > HCI Event: LE Meta Event (0x3e) plen 10 [hci0] 86319.055692 LE Connection Update Complete (0x03) Status: Success (0x00) Handle: 42 Connection interval: 38.75 msec (0x001f) Connection latency: 0.00 msec (0x0000) Supervision timeout: 32000 msec (0x0c80) Change-Id: Ief5d7bd404ce476e48a4d66983a03928d9db11d0 Signed-off-by: Arkadiusz Lichwa Signed-off-by: Mariusz Skamra --- net/bluetooth/hci_core.c | 73 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e76fb0b2ba0..b022ff515e0 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -862,6 +862,76 @@ static void le_remote_feat_complete(struct bt_buf *buf) bt_conn_put(conn); } +static int le_conn_param_neg_reply(uint16_t handle, uint8_t reason) +{ + struct bt_hci_cp_le_conn_param_req_neg_reply *cp; + struct bt_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, + sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = bt_buf_add(buf, sizeof(*cp)); + cp->handle = sys_cpu_to_le16(handle); + cp->reason = sys_cpu_to_le16(reason); + + return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, buf); +} + +static int le_conn_param_req_reply(uint16_t handle, uint16_t min, uint16_t max, + uint16_t latency, uint16_t timeout) +{ + struct bt_hci_cp_le_conn_param_req_reply *cp; + struct bt_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = bt_buf_add(buf, sizeof(*cp)); + memset(cp, 0x0, sizeof(*cp)); + + cp->handle = sys_cpu_to_le16(handle); + cp->interval_min = sys_cpu_to_le16(min); + cp->interval_max = sys_cpu_to_le16(max); + cp->latency = sys_cpu_to_le16(latency); + cp->timeout = sys_cpu_to_le16(timeout); + + return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, buf); +} + +static int le_conn_param_req(struct bt_buf *buf) +{ + struct bt_hci_evt_le_conn_param_req *evt = (void *)buf->data; + struct bt_conn *conn; + uint16_t handle, min, max, latency, timeout; + + handle = sys_le16_to_cpu(evt->handle); + min = sys_le16_to_cpu(evt->interval_min); + max = sys_le16_to_cpu(evt->interval_max); + latency = sys_le16_to_cpu(evt->latency); + timeout = sys_le16_to_cpu(evt->timeout); + + conn = bt_conn_lookup_handle(handle); + if (!conn) { + BT_ERR("Unable to lookup conn for handle %u\n", handle); + return le_conn_param_neg_reply(handle, + BT_HCI_ERR_UNKNOWN_CONN_ID); + } + + bt_conn_put(conn); + + if (!bt_le_conn_params_valid(min, max, latency, timeout)) { + return le_conn_param_neg_reply(handle, + BT_HCI_ERR_INVALID_LL_PARAMS); + } + + return le_conn_param_req_reply(handle, min, max, latency, timeout); +} + static void check_pending_conn(const bt_addr_le_t *addr, uint8_t evtype, struct bt_keys *keys) { @@ -1015,6 +1085,9 @@ static void hci_le_meta_event(struct bt_buf *buf) case BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE: le_remote_feat_complete(buf); break; + case BT_HCI_EVT_LE_CONN_PARAM_REQ: + le_conn_param_req(buf); + break; default: BT_DBG("Unhandled LE event %x\n", evt->subevent); break;