diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 1 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 10 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 9 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 75 |
4 files changed, 92 insertions, 3 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9aabb14982dd..3912c7ab717c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -767,6 +767,7 @@ int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); | |||
767 | int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, | 767 | 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 | 771 | ||
771 | /* HCI info for socket */ | 772 | /* HCI info for socket */ |
772 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | 773 | #define hci_pi(sk) ((struct hci_pinfo *) sk) |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 7d0749bed090..89e7c82c4784 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -172,6 +172,11 @@ struct mgmt_rp_user_confirm_reply { | |||
172 | 172 | ||
173 | #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 | 173 | #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 |
174 | 174 | ||
175 | #define MGMT_OP_SET_LOCAL_NAME 0x0017 | ||
176 | struct mgmt_cp_set_local_name { | ||
177 | __u8 name[MGMT_MAX_NAME_LENGTH]; | ||
178 | } __packed; | ||
179 | |||
175 | #define MGMT_EV_CMD_COMPLETE 0x0001 | 180 | #define MGMT_EV_CMD_COMPLETE 0x0001 |
176 | struct mgmt_ev_cmd_complete { | 181 | struct mgmt_ev_cmd_complete { |
177 | __le16 opcode; | 182 | __le16 opcode; |
@@ -239,3 +244,8 @@ struct mgmt_ev_auth_failed { | |||
239 | bdaddr_t bdaddr; | 244 | bdaddr_t bdaddr; |
240 | __u8 status; | 245 | __u8 status; |
241 | } __packed; | 246 | } __packed; |
247 | |||
248 | #define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 | ||
249 | struct mgmt_ev_local_name_changed { | ||
250 | __u8 name[MGMT_MAX_NAME_LENGTH]; | ||
251 | } __packed; | ||
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 | } | ||