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 /net/bluetooth/mgmt.c | |
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>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 83 |
1 files changed, 83 insertions, 0 deletions
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 | } | ||