diff options
Diffstat (limited to 'net/bluetooth_mgmt')
-rw-r--r-- | net/bluetooth_mgmt/l2cap_core.c | 50 | ||||
-rw-r--r-- | net/bluetooth_mgmt/mgmt.c | 19 | ||||
-rw-r--r-- | net/bluetooth_mgmt/smp.c | 13 |
3 files changed, 71 insertions, 11 deletions
diff --git a/net/bluetooth_mgmt/l2cap_core.c b/net/bluetooth_mgmt/l2cap_core.c index 884f61c..ab3369f 100644 --- a/net/bluetooth_mgmt/l2cap_core.c +++ b/net/bluetooth_mgmt/l2cap_core.c @@ -393,6 +393,13 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) BT_DBG("chan %p, conn %p, err %d", chan, conn, err); + if (chan->mode == L2CAP_MODE_ERTM) { + BT_DBG("L2CAP_MODE_ERTM __clear_ack_timer"); + __clear_ack_timer(chan); + __clear_retrans_timer(chan); + __clear_monitor_timer(chan); + } + if (conn) { /* Delete from channel list */ write_lock_bh(&conn->chan_lock); @@ -448,9 +455,11 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) if (chan->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; + /* __clear_retrans_timer(chan); __clear_monitor_timer(chan); __clear_ack_timer(chan); + */ skb_queue_purge(&chan->srej_q); @@ -1465,7 +1474,7 @@ static int l2cap_retransmit_frames(struct l2cap_chan *chan) ret = l2cap_ertm_send(chan); return ret; } - +/* static void l2cap_send_ack(struct l2cap_chan *chan) { u16 control = 0; @@ -1485,6 +1494,34 @@ static void l2cap_send_ack(struct l2cap_chan *chan) control |= L2CAP_SUPER_RCV_READY; l2cap_send_sframe(chan, control); } +*/ + +static void __l2cap_send_ack(struct l2cap_chan *chan) +{ + u16 control = 0; + + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + + if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { + control |= L2CAP_SUPER_RCV_NOT_READY; + set_bit(CONN_RNR_SENT, &chan->conn_state); + l2cap_send_sframe(chan, control); + return; + } + + if (l2cap_ertm_send(chan) > 0) + return; + + control |= L2CAP_SUPER_RCV_READY; + l2cap_send_sframe(chan, control); +} + +static void l2cap_send_ack(struct l2cap_chan *chan) +{ + BT_DBG("l2cap_send_ack"); + __clear_ack_timer(chan); + __l2cap_send_ack(chan); +} static void l2cap_send_srejtail(struct l2cap_chan *chan) { @@ -1920,7 +1957,8 @@ static void l2cap_ack_timeout(unsigned long arg) struct l2cap_chan *chan = (void *) arg; spin_lock_bh(&((chan->sk)->sk_lock.slock)); - l2cap_send_ack(chan); + /* l2cap_send_ack(chan);*/ + __l2cap_send_ack(chan); spin_unlock_bh(&((chan->sk)->sk_lock.slock)); } @@ -3652,11 +3690,13 @@ expected: l2cap_retransmit_frames(chan); } - __set_ack_timer(chan); - chan->num_acked = (chan->num_acked + 1) % num_to_ack; - if (chan->num_acked == num_to_ack - 1) + if (chan->num_acked == num_to_ack - 1) { l2cap_send_ack(chan); + } else { + BT_DBG("__set_ack_timer"); + __set_ack_timer(chan); + } return 0; diff --git a/net/bluetooth_mgmt/mgmt.c b/net/bluetooth_mgmt/mgmt.c index dd23eb7..04eaf75 100644 --- a/net/bluetooth_mgmt/mgmt.c +++ b/net/bluetooth_mgmt/mgmt.c @@ -1627,6 +1627,22 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status) pairing_complete(cmd, status); } +static void le_connect_complete_cb(struct hci_conn *conn, u8 status) +{ + struct pending_cmd *cmd; + + BT_DBG("status %u", status); + + if (!status) + return; + + cmd = find_pairing(conn); + if (!cmd) + BT_DBG("Unable to find a pending command"); + else + pairing_complete(cmd, mgmt_status(status)); +} + static int pair_device(struct sock *sk, u16 index, void *data, u16 len) { struct hci_dev *hdev; @@ -1687,9 +1703,10 @@ static int pair_device(struct sock *sk, u16 index, void *data, u16 len) goto unlock; } - /* For LE, just connecting isn't a proof that the pairing finished */ if (cp->addr.type == MGMT_ADDR_BREDR) conn->connect_cfm_cb = pairing_complete_cb; + else + conn->connect_cfm_cb = le_connect_complete_cb; conn->security_cfm_cb = pairing_complete_cb; conn->disconn_cfm_cb = pairing_complete_cb; diff --git a/net/bluetooth_mgmt/smp.c b/net/bluetooth_mgmt/smp.c index a40db2d..0786fde 100644 --- a/net/bluetooth_mgmt/smp.c +++ b/net/bluetooth_mgmt/smp.c @@ -294,11 +294,16 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) * 3 - NoInputNoOutput * 4 - KeyboardDisplay */ + +/* gen_method[3][4] is changed to JUST_WORKS. + *Although JUST_CFM works with pin 0000, when interacting with NoInputNoOutput, + * such a gesture might be confusing to user. Hence its changed to JUST_WORKS + */ static const u8 gen_method[5][5] = { { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, - { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, + { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_WORKS }, { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, }; @@ -325,7 +330,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, remote_io > SMP_IO_KEYBOARD_DISPLAY) method = JUST_WORKS; else - method = gen_method[local_io][remote_io]; + method = gen_method[remote_io][local_io]; /* If not bonding, don't ask user to confirm a Zero TK */ if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) @@ -629,8 +634,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); /* Request setup of TK */ - /* SSBT :: KJH * loc, rem */ - ret = tk_request(conn, 0, auth, req->io_capability, rsp.io_capability); + ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); if (ret) return SMP_UNSPECIFIED; @@ -671,7 +675,6 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; - /* SSBT :: KJH * loc, rem */ ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); if (ret) return SMP_UNSPECIFIED; |