diff options
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 95 |
1 files changed, 89 insertions, 6 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c304688252b8..2481d257ed98 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
945 | for (i = 0; i < key_count; i++) { | 945 | for (i = 0; i < key_count; i++) { |
946 | struct mgmt_key_info *key = &cp->keys[i]; | 946 | struct mgmt_key_info *key = &cp->keys[i]; |
947 | 947 | ||
948 | hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type, | 948 | hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, |
949 | key->pin_len); | 949 | key->pin_len); |
950 | } | 950 | } |
951 | 951 | ||
@@ -1569,6 +1569,75 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, | |||
1569 | return err; | 1569 | return err; |
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | static int start_discovery(struct sock *sk, u16 index) | ||
1573 | { | ||
1574 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | ||
1575 | struct hci_cp_inquiry cp; | ||
1576 | struct pending_cmd *cmd; | ||
1577 | struct hci_dev *hdev; | ||
1578 | int err; | ||
1579 | |||
1580 | BT_DBG("hci%u", index); | ||
1581 | |||
1582 | hdev = hci_dev_get(index); | ||
1583 | if (!hdev) | ||
1584 | return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV); | ||
1585 | |||
1586 | hci_dev_lock_bh(hdev); | ||
1587 | |||
1588 | cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0); | ||
1589 | if (!cmd) { | ||
1590 | err = -ENOMEM; | ||
1591 | goto failed; | ||
1592 | } | ||
1593 | |||
1594 | memset(&cp, 0, sizeof(cp)); | ||
1595 | memcpy(&cp.lap, lap, 3); | ||
1596 | cp.length = 0x08; | ||
1597 | cp.num_rsp = 0x00; | ||
1598 | |||
1599 | err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
1600 | if (err < 0) | ||
1601 | mgmt_pending_remove(cmd); | ||
1602 | |||
1603 | failed: | ||
1604 | hci_dev_unlock_bh(hdev); | ||
1605 | hci_dev_put(hdev); | ||
1606 | |||
1607 | return err; | ||
1608 | } | ||
1609 | |||
1610 | static int stop_discovery(struct sock *sk, u16 index) | ||
1611 | { | ||
1612 | struct hci_dev *hdev; | ||
1613 | struct pending_cmd *cmd; | ||
1614 | int err; | ||
1615 | |||
1616 | BT_DBG("hci%u", index); | ||
1617 | |||
1618 | hdev = hci_dev_get(index); | ||
1619 | if (!hdev) | ||
1620 | return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV); | ||
1621 | |||
1622 | hci_dev_lock_bh(hdev); | ||
1623 | |||
1624 | cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0); | ||
1625 | if (!cmd) { | ||
1626 | err = -ENOMEM; | ||
1627 | goto failed; | ||
1628 | } | ||
1629 | |||
1630 | err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); | ||
1631 | if (err < 0) | ||
1632 | mgmt_pending_remove(cmd); | ||
1633 | |||
1634 | failed: | ||
1635 | hci_dev_unlock_bh(hdev); | ||
1636 | hci_dev_put(hdev); | ||
1637 | |||
1638 | return err; | ||
1639 | } | ||
1640 | |||
1572 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 1641 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
1573 | { | 1642 | { |
1574 | unsigned char *buf; | 1643 | unsigned char *buf; |
@@ -1677,7 +1746,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1677 | err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), | 1746 | err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), |
1678 | len); | 1747 | len); |
1679 | break; | 1748 | break; |
1680 | 1749 | case MGMT_OP_START_DISCOVERY: | |
1750 | err = start_discovery(sk, index); | ||
1751 | break; | ||
1752 | case MGMT_OP_STOP_DISCOVERY: | ||
1753 | err = stop_discovery(sk, index); | ||
1754 | break; | ||
1681 | default: | 1755 | default: |
1682 | BT_DBG("Unknown op %u", opcode); | 1756 | BT_DBG("Unknown op %u", opcode); |
1683 | err = cmd_status(sk, index, opcode, 0x01); | 1757 | err = cmd_status(sk, index, opcode, 0x01); |
@@ -1784,17 +1858,17 @@ int mgmt_connectable(u16 index, u8 connectable) | |||
1784 | return ret; | 1858 | return ret; |
1785 | } | 1859 | } |
1786 | 1860 | ||
1787 | int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type) | 1861 | int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) |
1788 | { | 1862 | { |
1789 | struct mgmt_ev_new_key ev; | 1863 | struct mgmt_ev_new_key ev; |
1790 | 1864 | ||
1791 | memset(&ev, 0, sizeof(ev)); | 1865 | memset(&ev, 0, sizeof(ev)); |
1792 | 1866 | ||
1867 | ev.store_hint = persistent; | ||
1793 | bacpy(&ev.key.bdaddr, &key->bdaddr); | 1868 | bacpy(&ev.key.bdaddr, &key->bdaddr); |
1794 | ev.key.type = key->type; | 1869 | ev.key.type = key->type; |
1795 | memcpy(ev.key.val, key->val, 16); | 1870 | memcpy(ev.key.val, key->val, 16); |
1796 | ev.key.pin_len = key->pin_len; | 1871 | ev.key.pin_len = key->pin_len; |
1797 | ev.old_key_type = old_key_type; | ||
1798 | 1872 | ||
1799 | return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); | 1873 | return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); |
1800 | } | 1874 | } |
@@ -1868,11 +1942,12 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status) | |||
1868 | return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); | 1942 | return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); |
1869 | } | 1943 | } |
1870 | 1944 | ||
1871 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr) | 1945 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure) |
1872 | { | 1946 | { |
1873 | struct mgmt_ev_pin_code_request ev; | 1947 | struct mgmt_ev_pin_code_request ev; |
1874 | 1948 | ||
1875 | bacpy(&ev.bdaddr, bdaddr); | 1949 | bacpy(&ev.bdaddr, bdaddr); |
1950 | ev.secure = secure; | ||
1876 | 1951 | ||
1877 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev), | 1952 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev), |
1878 | NULL); | 1953 | NULL); |
@@ -1920,13 +1995,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status) | |||
1920 | return err; | 1995 | return err; |
1921 | } | 1996 | } |
1922 | 1997 | ||
1923 | int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value) | 1998 | int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, |
1999 | u8 confirm_hint) | ||
1924 | { | 2000 | { |
1925 | struct mgmt_ev_user_confirm_request ev; | 2001 | struct mgmt_ev_user_confirm_request ev; |
1926 | 2002 | ||
1927 | BT_DBG("hci%u", index); | 2003 | BT_DBG("hci%u", index); |
1928 | 2004 | ||
1929 | bacpy(&ev.bdaddr, bdaddr); | 2005 | bacpy(&ev.bdaddr, bdaddr); |
2006 | ev.confirm_hint = confirm_hint; | ||
1930 | put_unaligned_le32(value, &ev.value); | 2007 | put_unaligned_le32(value, &ev.value); |
1931 | 2008 | ||
1932 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev), | 2009 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev), |
@@ -2075,3 +2152,9 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) | |||
2075 | 2152 | ||
2076 | return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); | 2153 | return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); |
2077 | } | 2154 | } |
2155 | |||
2156 | int mgmt_discovering(u16 index, u8 discovering) | ||
2157 | { | ||
2158 | return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, | ||
2159 | sizeof(discovering), NULL); | ||
2160 | } | ||