aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-01-21 23:10:07 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-07 22:40:07 -0500
commit980e1a537fed7dfa53e9a4b6e586b43341f8c2d5 (patch)
tree36d7716d48a71e16f37afb5d8afdb527463826cd /net/bluetooth/mgmt.c
parenta38528f1117590169c0bf61cbf874e9fd2d5c5c9 (diff)
Bluetooth: Add support for PIN code handling in the management interface
This patch adds the necessary commands and events needed to communicate PIN code related actions between the kernel and userspace. This includes a pin_code_request event as well as pin_code_reply and pin_code_negative_reply commands. Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 005288b2a58e..3800aaf5792d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -933,6 +933,89 @@ unlock:
933 return err; 933 return err;
934} 934}
935 935
936static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len)
937{
938 struct hci_dev *hdev;
939 struct mgmt_cp_pin_code_reply *cp;
940 struct hci_cp_pin_code_reply reply;
941 u16 dev_id;
942 int err;
943
944 BT_DBG("");
945
946 cp = (void *) data;
947 dev_id = get_unaligned_le16(&cp->index);
948
949 hdev = hci_dev_get(dev_id);
950 if (!hdev)
951 return cmd_status(sk, MGMT_OP_DISCONNECT, ENODEV);
952
953 hci_dev_lock_bh(hdev);
954
955 if (!test_bit(HCI_UP, &hdev->flags)) {
956 err = cmd_status(sk, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
957 goto failed;
958 }
959
960 err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len);
961 if (err < 0)
962 goto failed;
963
964 bacpy(&reply.bdaddr, &cp->bdaddr);
965 reply.pin_len = cp->pin_len;
966 memcpy(reply.pin_code, cp->pin_code, 16);
967
968 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
969 if (err < 0)
970 mgmt_pending_remove(MGMT_OP_PIN_CODE_REPLY, dev_id);
971
972failed:
973 hci_dev_unlock_bh(hdev);
974 hci_dev_put(hdev);
975
976 return err;
977}
978
979static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len)
980{
981 struct hci_dev *hdev;
982 struct mgmt_cp_pin_code_neg_reply *cp;
983 u16 dev_id;
984 int err;
985
986 BT_DBG("");
987
988 cp = (void *) data;
989 dev_id = get_unaligned_le16(&cp->index);
990
991 hdev = hci_dev_get(dev_id);
992 if (!hdev)
993 return cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENODEV);
994
995 hci_dev_lock_bh(hdev);
996
997 if (!test_bit(HCI_UP, &hdev->flags)) {
998 err = cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENETDOWN);
999 goto failed;
1000 }
1001
1002 err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id,
1003 data, len);
1004 if (err < 0)
1005 goto failed;
1006
1007 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t),
1008 &cp->bdaddr);
1009 if (err < 0)
1010 mgmt_pending_remove(MGMT_OP_PIN_CODE_NEG_REPLY, dev_id);
1011
1012failed:
1013 hci_dev_unlock_bh(hdev);
1014 hci_dev_put(hdev);
1015
1016 return err;
1017}
1018
936int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 1019int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
937{ 1020{
938 unsigned char *buf; 1021 unsigned char *buf;
@@ -1009,6 +1092,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
1009 case MGMT_OP_GET_CONNECTIONS: 1092 case MGMT_OP_GET_CONNECTIONS:
1010 err = get_connections(sk, buf + sizeof(*hdr), len); 1093 err = get_connections(sk, buf + sizeof(*hdr), len);
1011 break; 1094 break;
1095 case MGMT_OP_PIN_CODE_REPLY:
1096 err = pin_code_reply(sk, buf + sizeof(*hdr), len);
1097 break;
1098 case MGMT_OP_PIN_CODE_NEG_REPLY:
1099 err = pin_code_neg_reply(sk, buf + sizeof(*hdr), len);
1100 break;
1012 default: 1101 default:
1013 BT_DBG("Unknown op %u", opcode); 1102 BT_DBG("Unknown op %u", opcode);
1014 err = cmd_status(sk, opcode, 0x01); 1103 err = cmd_status(sk, opcode, 0x01);
@@ -1217,3 +1306,55 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
1217 1306
1218 return mgmt_event(MGMT_EV_CONNECT_FAILED, &ev, sizeof(ev), NULL); 1307 return mgmt_event(MGMT_EV_CONNECT_FAILED, &ev, sizeof(ev), NULL);
1219} 1308}
1309
1310int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
1311{
1312 struct mgmt_ev_pin_code_request ev;
1313
1314 put_unaligned_le16(index, &ev.index);
1315 bacpy(&ev.bdaddr, bdaddr);
1316
1317 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, &ev, sizeof(ev), NULL);
1318}
1319
1320int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1321{
1322 struct pending_cmd *cmd;
1323 int err;
1324
1325 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
1326 if (!cmd)
1327 return -ENOENT;
1328
1329 if (status != 0)
1330 err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_REPLY, status);
1331 else
1332 err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_REPLY,
1333 bdaddr, sizeof(*bdaddr));
1334
1335 list_del(&cmd->list);
1336 mgmt_pending_free(cmd);
1337
1338 return err;
1339}
1340
1341int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1342{
1343 struct pending_cmd *cmd;
1344 int err;
1345
1346 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
1347 if (!cmd)
1348 return -ENOENT;
1349
1350 if (status != 0)
1351 err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY, status);
1352 else
1353 err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY,
1354 bdaddr, sizeof(*bdaddr));
1355
1356 list_del(&cmd->list);
1357 mgmt_pending_free(cmd);
1358
1359 return err;
1360}