aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-03-16 08:29:37 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-03-31 13:22:54 -0400
commitb312b161ecb833b1bce5c4a97853f4a4f40c7901 (patch)
tree7700417fc16114030316a3a2ba2fcd58ea37a25d /net
parentdc4fe30b8675033e538e2dea50be8af9c75f1b6a (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.c9
-rw-r--r--net/bluetooth/mgmt.c75
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
1259static 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
1291failed:
1292 hci_dev_unlock_bh(hdev);
1293 hci_dev_put(hdev);
1294
1295 return err;
1296}
1297
1259int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 1298int 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
1693int 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
1716send_event:
1717 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
1718 cmd ? cmd->sk : NULL);
1719
1720failed:
1721 if (cmd)
1722 mgmt_pending_remove(cmd);
1723 return err;
1724}