aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/mgmt.c76
1 files changed, 47 insertions, 29 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1ae14c91bb0..394222ef67a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1567,29 +1567,14 @@ unlock:
1567 return err; 1567 return err;
1568} 1568}
1569 1569
1570static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, 1570static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
1571 u16 len, int success) 1571 u16 mgmt_op, u16 hci_op, __le32 passkey)
1572{ 1572{
1573 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1574 u16 mgmt_op, hci_op;
1575 struct pending_cmd *cmd; 1573 struct pending_cmd *cmd;
1576 struct hci_dev *hdev; 1574 struct hci_dev *hdev;
1575 struct hci_conn *conn;
1577 int err; 1576 int err;
1578 1577
1579 BT_DBG("");
1580
1581 if (success) {
1582 mgmt_op = MGMT_OP_USER_CONFIRM_REPLY;
1583 hci_op = HCI_OP_USER_CONFIRM_REPLY;
1584 } else {
1585 mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY;
1586 hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
1587 }
1588
1589 if (len != sizeof(*cp))
1590 return cmd_status(sk, index, mgmt_op,
1591 MGMT_STATUS_INVALID_PARAMS);
1592
1593 hdev = hci_dev_get(index); 1578 hdev = hci_dev_get(index);
1594 if (!hdev) 1579 if (!hdev)
1595 return cmd_status(sk, index, mgmt_op, 1580 return cmd_status(sk, index, mgmt_op,
@@ -1598,27 +1583,59 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
1598 hci_dev_lock_bh(hdev); 1583 hci_dev_lock_bh(hdev);
1599 1584
1600 if (!test_bit(HCI_UP, &hdev->flags)) { 1585 if (!test_bit(HCI_UP, &hdev->flags)) {
1601 err = cmd_status(sk, index, mgmt_op, ENETDOWN); 1586 err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED);
1602 goto failed; 1587 goto done;
1603 } 1588 }
1604 1589
1605 cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len); 1590 cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
1606 if (!cmd) { 1591 if (!cmd) {
1607 err = -ENOMEM; 1592 err = -ENOMEM;
1608 goto failed; 1593 goto done;
1609 } 1594 }
1610 1595
1611 err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr); 1596 /* Continue with pairing via HCI */
1597 err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
1612 if (err < 0) 1598 if (err < 0)
1613 mgmt_pending_remove(cmd); 1599 mgmt_pending_remove(cmd);
1614 1600
1615failed: 1601done:
1616 hci_dev_unlock_bh(hdev); 1602 hci_dev_unlock_bh(hdev);
1617 hci_dev_put(hdev); 1603 hci_dev_put(hdev);
1618 1604
1619 return err; 1605 return err;
1620} 1606}
1621 1607
1608static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
1609{
1610 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1611
1612 BT_DBG("");
1613
1614 if (len != sizeof(*cp))
1615 return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY,
1616 MGMT_STATUS_INVALID_PARAMS);
1617
1618 return user_pairing_resp(sk, index, &cp->bdaddr,
1619 MGMT_OP_USER_CONFIRM_REPLY,
1620 HCI_OP_USER_CONFIRM_REPLY, 0);
1621}
1622
1623static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
1624 u16 len)
1625{
1626 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
1627
1628 BT_DBG("");
1629
1630 if (len != sizeof(*cp))
1631 return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY,
1632 MGMT_STATUS_INVALID_PARAMS);
1633
1634 return user_pairing_resp(sk, index, &cp->bdaddr,
1635 MGMT_OP_USER_CONFIRM_NEG_REPLY,
1636 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
1637}
1638
1622static int set_local_name(struct sock *sk, u16 index, unsigned char *data, 1639static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1623 u16 len) 1640 u16 len)
1624{ 1641{
@@ -2070,10 +2087,11 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2070 err = pair_device(sk, index, buf + sizeof(*hdr), len); 2087 err = pair_device(sk, index, buf + sizeof(*hdr), len);
2071 break; 2088 break;
2072 case MGMT_OP_USER_CONFIRM_REPLY: 2089 case MGMT_OP_USER_CONFIRM_REPLY:
2073 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1); 2090 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len);
2074 break; 2091 break;
2075 case MGMT_OP_USER_CONFIRM_NEG_REPLY: 2092 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
2076 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); 2093 err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr),
2094 len);
2077 break; 2095 break;
2078 case MGMT_OP_SET_LOCAL_NAME: 2096 case MGMT_OP_SET_LOCAL_NAME:
2079 err = set_local_name(sk, index, buf + sizeof(*hdr), len); 2097 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
@@ -2435,7 +2453,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
2435 NULL); 2453 NULL);
2436} 2454}
2437 2455
2438static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, 2456static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2439 u8 status, u8 opcode) 2457 u8 status, u8 opcode)
2440{ 2458{
2441 struct pending_cmd *cmd; 2459 struct pending_cmd *cmd;
@@ -2458,14 +2476,14 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2458int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, 2476int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2459 u8 status) 2477 u8 status)
2460{ 2478{
2461 return confirm_reply_complete(hdev, bdaddr, mgmt_status(status), 2479 return user_pairing_resp_complete(hdev, bdaddr, status,
2462 MGMT_OP_USER_CONFIRM_REPLY); 2480 MGMT_OP_USER_CONFIRM_REPLY);
2463} 2481}
2464 2482
2465int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, 2483int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
2466 bdaddr_t *bdaddr, u8 status) 2484 bdaddr_t *bdaddr, u8 status)
2467{ 2485{
2468 return confirm_reply_complete(hdev, bdaddr, mgmt_status(status), 2486 return user_pairing_resp_complete(hdev, bdaddr, status,
2469 MGMT_OP_USER_CONFIRM_NEG_REPLY); 2487 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2470} 2488}
2471 2489