diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2011-12-14 17:47:35 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-18 14:34:04 -0500 |
commit | 69ab39ea5da03e632a51b31534da713aff8d1e3b (patch) | |
tree | 3f10083b2ed1bd186f0f38b513453c68954dac45 | |
parent | 590051de5ce54f7ae02997ed0a2532f08c7b7866 (diff) |
Bluetooth: Update mgmt_read_info and related mgmt messages
This patch updates the mgmt_read_info and related messages to the latest
management API which uses a bitfield of settings instead of individual
boolean values.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/hci.h | 1 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 29 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 146 |
3 files changed, 113 insertions, 63 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 67ad98430348..c9ad56fe58f4 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -210,6 +210,7 @@ enum { | |||
210 | 210 | ||
211 | #define LMP_EV4 0x01 | 211 | #define LMP_EV4 0x01 |
212 | #define LMP_EV5 0x02 | 212 | #define LMP_EV5 0x02 |
213 | #define LMP_NO_BREDR 0x20 | ||
213 | #define LMP_LE 0x40 | 214 | #define LMP_LE 0x40 |
214 | 215 | ||
215 | #define LMP_SNIFF_SUBR 0x02 | 216 | #define LMP_SNIFF_SUBR 0x02 |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 3b6880690a78..85e9c6e9d221 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list { | |||
61 | /* Reserve one extra byte for names in management messages so that they | 61 | /* Reserve one extra byte for names in management messages so that they |
62 | * are always guaranteed to be nul-terminated */ | 62 | * are always guaranteed to be nul-terminated */ |
63 | #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) | 63 | #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) |
64 | #define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) | ||
65 | |||
66 | #define MGMT_SETTING_POWERED 0x00000001 | ||
67 | #define MGMT_SETTING_CONNECTABLE 0x00000002 | ||
68 | #define MGMT_SETTING_FAST_CONNECTABLE 0x00000004 | ||
69 | #define MGMT_SETTING_DISCOVERABLE 0x00000008 | ||
70 | #define MGMT_SETTING_PAIRABLE 0x00000010 | ||
71 | #define MGMT_SETTING_LINK_SECURITY 0x00000020 | ||
72 | #define MGMT_SETTING_SSP 0x00000040 | ||
73 | #define MGMT_SETTING_BREDR 0x00000080 | ||
74 | #define MGMT_SETTING_HS 0x00000100 | ||
75 | #define MGMT_SETTING_LE 0x00000200 | ||
64 | 76 | ||
65 | #define MGMT_OP_READ_INFO 0x0004 | 77 | #define MGMT_OP_READ_INFO 0x0004 |
66 | struct mgmt_rp_read_info { | 78 | struct mgmt_rp_read_info { |
67 | __u8 type; | ||
68 | __u8 powered; | ||
69 | __u8 connectable; | ||
70 | __u8 discoverable; | ||
71 | __u8 pairable; | ||
72 | __u8 sec_mode; | ||
73 | bdaddr_t bdaddr; | 79 | bdaddr_t bdaddr; |
80 | __u8 version; | ||
81 | __le16 manufacturer; | ||
82 | __le32 supported_settings; | ||
83 | __le32 current_settings; | ||
74 | __u8 dev_class[3]; | 84 | __u8 dev_class[3]; |
75 | __u8 features[8]; | ||
76 | __u16 manufacturer; | ||
77 | __u8 hci_ver; | ||
78 | __u16 hci_rev; | ||
79 | __u8 name[MGMT_MAX_NAME_LENGTH]; | 85 | __u8 name[MGMT_MAX_NAME_LENGTH]; |
86 | __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; | ||
80 | } __packed; | 87 | } __packed; |
81 | 88 | ||
82 | struct mgmt_mode { | 89 | struct mgmt_mode { |
@@ -285,7 +292,7 @@ struct mgmt_ev_controller_error { | |||
285 | 292 | ||
286 | #define MGMT_EV_INDEX_REMOVED 0x0005 | 293 | #define MGMT_EV_INDEX_REMOVED 0x0005 |
287 | 294 | ||
288 | #define MGMT_EV_POWERED 0x0006 | 295 | #define MGMT_EV_NEW_SETTINGS 0x0006 |
289 | 296 | ||
290 | #define MGMT_EV_DISCOVERABLE 0x0007 | 297 | #define MGMT_EV_DISCOVERABLE 0x0007 |
291 | 298 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ffd1c01c7d0e..087cf00a443d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -242,6 +242,63 @@ static int read_index_list(struct sock *sk) | |||
242 | return err; | 242 | return err; |
243 | } | 243 | } |
244 | 244 | ||
245 | static u32 get_supported_settings(struct hci_dev *hdev) | ||
246 | { | ||
247 | u32 settings = 0; | ||
248 | |||
249 | settings |= MGMT_SETTING_POWERED; | ||
250 | settings |= MGMT_SETTING_CONNECTABLE; | ||
251 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
252 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
253 | settings |= MGMT_SETTING_PAIRABLE; | ||
254 | |||
255 | if (hdev->features[6] & LMP_SIMPLE_PAIR) | ||
256 | settings |= MGMT_SETTING_SSP; | ||
257 | |||
258 | if (!(hdev->features[4] & LMP_NO_BREDR)) { | ||
259 | settings |= MGMT_SETTING_BREDR; | ||
260 | settings |= MGMT_SETTING_LINK_SECURITY; | ||
261 | } | ||
262 | |||
263 | if (hdev->features[4] & LMP_LE) | ||
264 | settings |= MGMT_SETTING_LE; | ||
265 | |||
266 | return settings; | ||
267 | } | ||
268 | |||
269 | static u32 get_current_settings(struct hci_dev *hdev) | ||
270 | { | ||
271 | u32 settings = 0; | ||
272 | |||
273 | if (test_bit(HCI_UP, &hdev->flags)) | ||
274 | settings |= MGMT_SETTING_POWERED; | ||
275 | else | ||
276 | return settings; | ||
277 | |||
278 | if (test_bit(HCI_PSCAN, &hdev->flags)) | ||
279 | settings |= MGMT_SETTING_CONNECTABLE; | ||
280 | |||
281 | if (test_bit(HCI_ISCAN, &hdev->flags)) | ||
282 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
283 | |||
284 | if (test_bit(HCI_PAIRABLE, &hdev->flags)) | ||
285 | settings |= MGMT_SETTING_PAIRABLE; | ||
286 | |||
287 | if (!(hdev->features[4] & LMP_NO_BREDR)) | ||
288 | settings |= MGMT_SETTING_BREDR; | ||
289 | |||
290 | if (hdev->extfeatures[0] & LMP_HOST_LE) | ||
291 | settings |= MGMT_SETTING_LE; | ||
292 | |||
293 | if (test_bit(HCI_AUTH, &hdev->flags)) | ||
294 | settings |= MGMT_SETTING_LINK_SECURITY; | ||
295 | |||
296 | if (hdev->ssp_mode > 0) | ||
297 | settings |= MGMT_SETTING_SSP; | ||
298 | |||
299 | return settings; | ||
300 | } | ||
301 | |||
245 | static int read_controller_info(struct sock *sk, u16 index) | 302 | static int read_controller_info(struct sock *sk, u16 index) |
246 | { | 303 | { |
247 | struct mgmt_rp_read_info rp; | 304 | struct mgmt_rp_read_info rp; |
@@ -263,26 +320,16 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
263 | 320 | ||
264 | memset(&rp, 0, sizeof(rp)); | 321 | memset(&rp, 0, sizeof(rp)); |
265 | 322 | ||
266 | rp.type = hdev->dev_type; | 323 | bacpy(&rp.bdaddr, &hdev->bdaddr); |
267 | 324 | ||
268 | rp.powered = test_bit(HCI_UP, &hdev->flags); | 325 | rp.version = hdev->hci_ver; |
269 | rp.connectable = test_bit(HCI_PSCAN, &hdev->flags); | ||
270 | rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags); | ||
271 | rp.pairable = test_bit(HCI_PSCAN, &hdev->flags); | ||
272 | 326 | ||
273 | if (test_bit(HCI_AUTH, &hdev->flags)) | 327 | put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); |
274 | rp.sec_mode = 3; | 328 | |
275 | else if (hdev->ssp_mode > 0) | 329 | rp.supported_settings = cpu_to_le32(get_supported_settings(hdev)); |
276 | rp.sec_mode = 4; | 330 | rp.current_settings = cpu_to_le32(get_current_settings(hdev)); |
277 | else | ||
278 | rp.sec_mode = 2; | ||
279 | 331 | ||
280 | bacpy(&rp.bdaddr, &hdev->bdaddr); | ||
281 | memcpy(rp.features, hdev->features, 8); | ||
282 | memcpy(rp.dev_class, hdev->dev_class, 3); | 332 | memcpy(rp.dev_class, hdev->dev_class, 3); |
283 | put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); | ||
284 | rp.hci_ver = hdev->hci_ver; | ||
285 | put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); | ||
286 | 333 | ||
287 | memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); | 334 | memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); |
288 | 335 | ||
@@ -365,13 +412,11 @@ static void mgmt_pending_remove(struct pending_cmd *cmd) | |||
365 | mgmt_pending_free(cmd); | 412 | mgmt_pending_free(cmd); |
366 | } | 413 | } |
367 | 414 | ||
368 | static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) | 415 | static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) |
369 | { | 416 | { |
370 | struct mgmt_mode rp; | 417 | __le32 settings = cpu_to_le32(get_current_settings(hdev)); |
371 | 418 | ||
372 | rp.val = val; | 419 | return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings)); |
373 | |||
374 | return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); | ||
375 | } | 420 | } |
376 | 421 | ||
377 | static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | 422 | static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) |
@@ -398,7 +443,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
398 | 443 | ||
399 | up = test_bit(HCI_UP, &hdev->flags); | 444 | up = test_bit(HCI_UP, &hdev->flags); |
400 | if ((cp->val && up) || (!cp->val && !up)) { | 445 | if ((cp->val && up) || (!cp->val && !up)) { |
401 | err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val); | 446 | err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); |
402 | goto failed; | 447 | goto failed; |
403 | } | 448 | } |
404 | 449 | ||
@@ -466,8 +511,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
466 | 511 | ||
467 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && | 512 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && |
468 | test_bit(HCI_PSCAN, &hdev->flags)) { | 513 | test_bit(HCI_PSCAN, &hdev->flags)) { |
469 | err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, | 514 | err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); |
470 | cp->val); | ||
471 | goto failed; | 515 | goto failed; |
472 | } | 516 | } |
473 | 517 | ||
@@ -536,8 +580,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, | |||
536 | } | 580 | } |
537 | 581 | ||
538 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { | 582 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { |
539 | err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, | 583 | err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); |
540 | cp->val); | ||
541 | goto failed; | 584 | goto failed; |
542 | } | 585 | } |
543 | 586 | ||
@@ -595,8 +638,9 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, | |||
595 | static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | 638 | static int set_pairable(struct sock *sk, u16 index, unsigned char *data, |
596 | u16 len) | 639 | u16 len) |
597 | { | 640 | { |
598 | struct mgmt_mode *cp, ev; | 641 | struct mgmt_mode *cp; |
599 | struct hci_dev *hdev; | 642 | struct hci_dev *hdev; |
643 | __le32 ev; | ||
600 | int err; | 644 | int err; |
601 | 645 | ||
602 | cp = (void *) data; | 646 | cp = (void *) data; |
@@ -619,13 +663,13 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | |||
619 | else | 663 | else |
620 | clear_bit(HCI_PAIRABLE, &hdev->flags); | 664 | clear_bit(HCI_PAIRABLE, &hdev->flags); |
621 | 665 | ||
622 | err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val); | 666 | err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); |
623 | if (err < 0) | 667 | if (err < 0) |
624 | goto failed; | 668 | goto failed; |
625 | 669 | ||
626 | ev.val = cp->val; | 670 | ev = cpu_to_le32(get_current_settings(hdev)); |
627 | 671 | ||
628 | err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk); | 672 | err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk); |
629 | 673 | ||
630 | failed: | 674 | failed: |
631 | hci_dev_unlock(hdev); | 675 | hci_dev_unlock(hdev); |
@@ -2234,17 +2278,14 @@ int mgmt_index_removed(struct hci_dev *hdev) | |||
2234 | struct cmd_lookup { | 2278 | struct cmd_lookup { |
2235 | u8 val; | 2279 | u8 val; |
2236 | struct sock *sk; | 2280 | struct sock *sk; |
2281 | struct hci_dev *hdev; | ||
2237 | }; | 2282 | }; |
2238 | 2283 | ||
2239 | static void mode_rsp(struct pending_cmd *cmd, void *data) | 2284 | static void settings_rsp(struct pending_cmd *cmd, void *data) |
2240 | { | 2285 | { |
2241 | struct mgmt_mode *cp = cmd->param; | ||
2242 | struct cmd_lookup *match = data; | 2286 | struct cmd_lookup *match = data; |
2243 | 2287 | ||
2244 | if (cp->val != match->val) | 2288 | send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); |
2245 | return; | ||
2246 | |||
2247 | send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val); | ||
2248 | 2289 | ||
2249 | list_del(&cmd->list); | 2290 | list_del(&cmd->list); |
2250 | 2291 | ||
@@ -2258,20 +2299,21 @@ static void mode_rsp(struct pending_cmd *cmd, void *data) | |||
2258 | 2299 | ||
2259 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 2300 | int mgmt_powered(struct hci_dev *hdev, u8 powered) |
2260 | { | 2301 | { |
2261 | struct mgmt_mode ev; | 2302 | struct cmd_lookup match = { powered, NULL, hdev }; |
2262 | struct cmd_lookup match = { powered, NULL }; | 2303 | __le32 ev; |
2263 | int ret; | 2304 | int ret; |
2264 | 2305 | ||
2265 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, mode_rsp, &match); | 2306 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
2266 | 2307 | ||
2267 | if (!powered) { | 2308 | if (!powered) { |
2268 | u8 status = ENETDOWN; | 2309 | u8 status = ENETDOWN; |
2269 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 2310 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
2270 | } | 2311 | } |
2271 | 2312 | ||
2272 | ev.val = powered; | 2313 | ev = cpu_to_le32(get_current_settings(hdev)); |
2273 | 2314 | ||
2274 | ret = mgmt_event(MGMT_EV_POWERED, hdev, &ev, sizeof(ev), match.sk); | 2315 | ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), |
2316 | match.sk); | ||
2275 | 2317 | ||
2276 | if (match.sk) | 2318 | if (match.sk) |
2277 | sock_put(match.sk); | 2319 | sock_put(match.sk); |
@@ -2281,17 +2323,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2281 | 2323 | ||
2282 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | 2324 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) |
2283 | { | 2325 | { |
2284 | struct mgmt_mode ev; | 2326 | struct cmd_lookup match = { discoverable, NULL, hdev }; |
2285 | struct cmd_lookup match = { discoverable, NULL }; | 2327 | __le32 ev; |
2286 | int ret; | 2328 | int ret; |
2287 | 2329 | ||
2288 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mode_rsp, &match); | 2330 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match); |
2289 | 2331 | ||
2290 | ev.val = discoverable; | 2332 | ev = cpu_to_le32(get_current_settings(hdev)); |
2291 | 2333 | ||
2292 | ret = mgmt_event(MGMT_EV_DISCOVERABLE, hdev, &ev, sizeof(ev), | 2334 | ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), |
2293 | match.sk); | 2335 | match.sk); |
2294 | |||
2295 | if (match.sk) | 2336 | if (match.sk) |
2296 | sock_put(match.sk); | 2337 | sock_put(match.sk); |
2297 | 2338 | ||
@@ -2300,15 +2341,16 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | |||
2300 | 2341 | ||
2301 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | 2342 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
2302 | { | 2343 | { |
2303 | struct mgmt_mode ev; | 2344 | __le32 ev; |
2304 | struct cmd_lookup match = { connectable, NULL }; | 2345 | struct cmd_lookup match = { connectable, NULL, hdev }; |
2305 | int ret; | 2346 | int ret; |
2306 | 2347 | ||
2307 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, mode_rsp, &match); | 2348 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp, |
2349 | &match); | ||
2308 | 2350 | ||
2309 | ev.val = connectable; | 2351 | ev = cpu_to_le32(get_current_settings(hdev)); |
2310 | 2352 | ||
2311 | ret = mgmt_event(MGMT_EV_CONNECTABLE, hdev, &ev, sizeof(ev), match.sk); | 2353 | ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk); |
2312 | 2354 | ||
2313 | if (match.sk) | 2355 | if (match.sk) |
2314 | sock_put(match.sk); | 2356 | sock_put(match.sk); |