diff options
author | Szymon Janc <szymon.janc@tieto.com> | 2011-03-22 08:12:21 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-03-31 13:22:57 -0400 |
commit | c35938b2f56547ee77b5a038fe0db394aeac59bb (patch) | |
tree | 8bb0975ce5b48bd01ca04432e3fa13ae605b60b9 | |
parent | 8fce6357a9e72c4c9c846f9951895954bfb34ad1 (diff) |
Bluetooth: Add read_local_oob_data management command
This patch adds a command to read local OOB data to the managment interface.
The command maps directly to the Read Local OOB Data HCI command.
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/hci.h | 7 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 6 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 15 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 83 |
5 files changed, 113 insertions, 0 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 1cd031cd1c4d..ac4de1afe046 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -613,6 +613,13 @@ struct hci_cp_write_ssp_mode { | |||
613 | __u8 mode; | 613 | __u8 mode; |
614 | } __packed; | 614 | } __packed; |
615 | 615 | ||
616 | #define HCI_OP_READ_LOCAL_OOB_DATA 0x0c57 | ||
617 | struct hci_rp_read_local_oob_data { | ||
618 | __u8 status; | ||
619 | __u8 hash[16]; | ||
620 | __u8 randomizer[16]; | ||
621 | } __packed; | ||
622 | |||
616 | #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 | 623 | #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 |
617 | 624 | ||
618 | #define HCI_OP_READ_LOCAL_VERSION 0x1001 | 625 | #define HCI_OP_READ_LOCAL_VERSION 0x1001 |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3912c7ab717c..fd9b8a31e5b0 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -768,6 +768,8 @@ int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, | |||
768 | u8 status); | 768 | u8 status); |
769 | int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); | 769 | int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); |
770 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); | 770 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); |
771 | int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | ||
772 | u8 status); | ||
771 | 773 | ||
772 | /* HCI info for socket */ | 774 | /* HCI info for socket */ |
773 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | 775 | #define hci_pi(sk) ((struct hci_pinfo *) sk) |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 89e7c82c4784..6ebb1265c36e 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -177,6 +177,12 @@ struct mgmt_cp_set_local_name { | |||
177 | __u8 name[MGMT_MAX_NAME_LENGTH]; | 177 | __u8 name[MGMT_MAX_NAME_LENGTH]; |
178 | } __packed; | 178 | } __packed; |
179 | 179 | ||
180 | #define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 | ||
181 | struct mgmt_rp_read_local_oob_data { | ||
182 | __u8 hash[16]; | ||
183 | __u8 randomizer[16]; | ||
184 | } __packed; | ||
185 | |||
180 | #define MGMT_EV_CMD_COMPLETE 0x0001 | 186 | #define MGMT_EV_CMD_COMPLETE 0x0001 |
181 | struct mgmt_ev_cmd_complete { | 187 | struct mgmt_ev_cmd_complete { |
182 | __le16 opcode; | 188 | __le16 opcode; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0def3e1fe5ef..582ef60a8bc0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -822,6 +822,17 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, | |||
822 | rp->status); | 822 | rp->status); |
823 | } | 823 | } |
824 | 824 | ||
825 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | ||
826 | struct sk_buff *skb) | ||
827 | { | ||
828 | struct hci_rp_read_local_oob_data *rp = (void *) skb->data; | ||
829 | |||
830 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
831 | |||
832 | mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, | ||
833 | rp->randomizer, rp->status); | ||
834 | } | ||
835 | |||
825 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | 836 | static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
826 | { | 837 | { |
827 | BT_DBG("%s status 0x%x", hdev->name, status); | 838 | BT_DBG("%s status 0x%x", hdev->name, status); |
@@ -1752,6 +1763,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1752 | hci_cc_pin_code_neg_reply(hdev, skb); | 1763 | hci_cc_pin_code_neg_reply(hdev, skb); |
1753 | break; | 1764 | break; |
1754 | 1765 | ||
1766 | case HCI_OP_READ_LOCAL_OOB_DATA: | ||
1767 | hci_cc_read_local_oob_data_reply(hdev, skb); | ||
1768 | break; | ||
1769 | |||
1755 | case HCI_OP_LE_READ_BUFFER_SIZE: | 1770 | case HCI_OP_LE_READ_BUFFER_SIZE: |
1756 | hci_cc_le_read_buffer_size(hdev, skb); | 1771 | hci_cc_le_read_buffer_size(hdev, skb); |
1757 | break; | 1772 | break; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 93f0f04c8bcd..33b1f7400dab 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1296,6 +1296,55 @@ failed: | |||
1296 | return err; | 1296 | return err; |
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | static int read_local_oob_data(struct sock *sk, u16 index) | ||
1300 | { | ||
1301 | struct hci_dev *hdev; | ||
1302 | struct pending_cmd *cmd; | ||
1303 | int err; | ||
1304 | |||
1305 | BT_DBG("hci%u", index); | ||
1306 | |||
1307 | hdev = hci_dev_get(index); | ||
1308 | if (!hdev) | ||
1309 | return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1310 | ENODEV); | ||
1311 | |||
1312 | hci_dev_lock_bh(hdev); | ||
1313 | |||
1314 | if (!test_bit(HCI_UP, &hdev->flags)) { | ||
1315 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1316 | ENETDOWN); | ||
1317 | goto unlock; | ||
1318 | } | ||
1319 | |||
1320 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | ||
1321 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1322 | EOPNOTSUPP); | ||
1323 | goto unlock; | ||
1324 | } | ||
1325 | |||
1326 | if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { | ||
1327 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); | ||
1328 | goto unlock; | ||
1329 | } | ||
1330 | |||
1331 | cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); | ||
1332 | if (!cmd) { | ||
1333 | err = -ENOMEM; | ||
1334 | goto unlock; | ||
1335 | } | ||
1336 | |||
1337 | err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); | ||
1338 | if (err < 0) | ||
1339 | mgmt_pending_remove(cmd); | ||
1340 | |||
1341 | unlock: | ||
1342 | hci_dev_unlock_bh(hdev); | ||
1343 | hci_dev_put(hdev); | ||
1344 | |||
1345 | return err; | ||
1346 | } | ||
1347 | |||
1299 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 1348 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
1300 | { | 1349 | { |
1301 | unsigned char *buf; | 1350 | unsigned char *buf; |
@@ -1394,6 +1443,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1394 | case MGMT_OP_SET_LOCAL_NAME: | 1443 | case MGMT_OP_SET_LOCAL_NAME: |
1395 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); | 1444 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); |
1396 | break; | 1445 | break; |
1446 | case MGMT_OP_READ_LOCAL_OOB_DATA: | ||
1447 | err = read_local_oob_data(sk, index); | ||
1448 | break; | ||
1449 | |||
1397 | default: | 1450 | default: |
1398 | BT_DBG("Unknown op %u", opcode); | 1451 | BT_DBG("Unknown op %u", opcode); |
1399 | err = cmd_status(sk, index, opcode, 0x01); | 1452 | err = cmd_status(sk, index, opcode, 0x01); |
@@ -1723,3 +1776,33 @@ failed: | |||
1723 | mgmt_pending_remove(cmd); | 1776 | mgmt_pending_remove(cmd); |
1724 | return err; | 1777 | return err; |
1725 | } | 1778 | } |
1779 | |||
1780 | int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | ||
1781 | u8 status) | ||
1782 | { | ||
1783 | struct pending_cmd *cmd; | ||
1784 | int err; | ||
1785 | |||
1786 | BT_DBG("hci%u status %u", index, status); | ||
1787 | |||
1788 | cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index); | ||
1789 | if (!cmd) | ||
1790 | return -ENOENT; | ||
1791 | |||
1792 | if (status) { | ||
1793 | err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1794 | EIO); | ||
1795 | } else { | ||
1796 | struct mgmt_rp_read_local_oob_data rp; | ||
1797 | |||
1798 | memcpy(rp.hash, hash, sizeof(rp.hash)); | ||
1799 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); | ||
1800 | |||
1801 | err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | ||
1802 | &rp, sizeof(rp)); | ||
1803 | } | ||
1804 | |||
1805 | mgmt_pending_remove(cmd); | ||
1806 | |||
1807 | return err; | ||
1808 | } | ||