diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2011-03-16 08:29:37 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-03-31 13:22:54 -0400 |
commit | b312b161ecb833b1bce5c4a97853f4a4f40c7901 (patch) | |
tree | 7700417fc16114030316a3a2ba2fcd58ea37a25d /net | |
parent | dc4fe30b8675033e538e2dea50be8af9c75f1b6a (diff) |
Bluetooth: mgmt: Add support for setting the local name
This patch adds a new set_local_name management command as well as a
local_name_changed management event. With these user space can both
change the local name as well as monitor changes to it by others.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_event.c | 9 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 75 |
2 files changed, 81 insertions, 3 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 91ef52673ed3..0def3e1fe5ef 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -193,13 +193,16 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
193 | 193 | ||
194 | BT_DBG("%s status 0x%x", hdev->name, status); | 194 | BT_DBG("%s status 0x%x", hdev->name, status); |
195 | 195 | ||
196 | if (status) | ||
197 | return; | ||
198 | |||
199 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); | 196 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); |
200 | if (!sent) | 197 | if (!sent) |
201 | return; | 198 | return; |
202 | 199 | ||
200 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
201 | mgmt_set_local_name_complete(hdev->id, sent, status); | ||
202 | |||
203 | if (status) | ||
204 | return; | ||
205 | |||
203 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); | 206 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); |
204 | } | 207 | } |
205 | 208 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ffdb2f4e8635..f7ce78235590 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1256,6 +1256,45 @@ failed: | |||
1256 | return err; | 1256 | return err; |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | ||
1260 | u16 len) | ||
1261 | { | ||
1262 | struct mgmt_cp_set_local_name *mgmt_cp = (void *) data; | ||
1263 | struct hci_cp_write_local_name hci_cp; | ||
1264 | struct hci_dev *hdev; | ||
1265 | struct pending_cmd *cmd; | ||
1266 | int err; | ||
1267 | |||
1268 | BT_DBG(""); | ||
1269 | |||
1270 | if (len != sizeof(*mgmt_cp)) | ||
1271 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); | ||
1272 | |||
1273 | hdev = hci_dev_get(index); | ||
1274 | if (!hdev) | ||
1275 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); | ||
1276 | |||
1277 | hci_dev_lock_bh(hdev); | ||
1278 | |||
1279 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); | ||
1280 | if (!cmd) { | ||
1281 | err = -ENOMEM; | ||
1282 | goto failed; | ||
1283 | } | ||
1284 | |||
1285 | memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name)); | ||
1286 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp), | ||
1287 | &hci_cp); | ||
1288 | if (err < 0) | ||
1289 | mgmt_pending_remove(cmd); | ||
1290 | |||
1291 | failed: | ||
1292 | hci_dev_unlock_bh(hdev); | ||
1293 | hci_dev_put(hdev); | ||
1294 | |||
1295 | return err; | ||
1296 | } | ||
1297 | |||
1259 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 1298 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
1260 | { | 1299 | { |
1261 | unsigned char *buf; | 1300 | unsigned char *buf; |
@@ -1351,6 +1390,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1351 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: | 1390 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: |
1352 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); | 1391 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); |
1353 | break; | 1392 | break; |
1393 | case MGMT_OP_SET_LOCAL_NAME: | ||
1394 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); | ||
1395 | break; | ||
1354 | default: | 1396 | default: |
1355 | BT_DBG("Unknown op %u", opcode); | 1397 | BT_DBG("Unknown op %u", opcode); |
1356 | err = cmd_status(sk, index, opcode, 0x01); | 1398 | err = cmd_status(sk, index, opcode, 0x01); |
@@ -1647,3 +1689,36 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) | |||
1647 | 1689 | ||
1648 | return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); | 1690 | return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); |
1649 | } | 1691 | } |
1692 | |||
1693 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) | ||
1694 | { | ||
1695 | struct pending_cmd *cmd; | ||
1696 | struct mgmt_cp_set_local_name ev; | ||
1697 | int err; | ||
1698 | |||
1699 | memset(&ev, 0, sizeof(ev)); | ||
1700 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | ||
1701 | |||
1702 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index); | ||
1703 | if (!cmd) | ||
1704 | goto send_event; | ||
1705 | |||
1706 | if (status) { | ||
1707 | err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO); | ||
1708 | goto failed; | ||
1709 | } | ||
1710 | |||
1711 | err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, | ||
1712 | sizeof(ev)); | ||
1713 | if (err < 0) | ||
1714 | goto failed; | ||
1715 | |||
1716 | send_event: | ||
1717 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev), | ||
1718 | cmd ? cmd->sk : NULL); | ||
1719 | |||
1720 | failed: | ||
1721 | if (cmd) | ||
1722 | mgmt_pending_remove(cmd); | ||
1723 | return err; | ||
1724 | } | ||