Commit 69ab39ea5da03e632a51b31534da713aff8d1e3b
Committed by
Gustavo F. Padovan
1 parent
590051de5c
Exists in
master
and in
6 other branches
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>
Showing 3 changed files with 113 additions and 63 deletions Side-by-side Diff
include/net/bluetooth/hci.h
include/net/bluetooth/mgmt.h
... | ... | @@ -61,22 +61,29 @@ |
61 | 61 | /* Reserve one extra byte for names in management messages so that they |
62 | 62 | * are always guaranteed to be nul-terminated */ |
63 | 63 | #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) |
64 | +#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) | |
64 | 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 | |
76 | + | |
65 | 77 | #define MGMT_OP_READ_INFO 0x0004 |
66 | 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 | 79 | bdaddr_t bdaddr; |
80 | + __u8 version; | |
81 | + __le16 manufacturer; | |
82 | + __le32 supported_settings; | |
83 | + __le32 current_settings; | |
74 | 84 | __u8 dev_class[3]; |
75 | - __u8 features[8]; | |
76 | - __u16 manufacturer; | |
77 | - __u8 hci_ver; | |
78 | - __u16 hci_rev; | |
79 | 85 | __u8 name[MGMT_MAX_NAME_LENGTH]; |
86 | + __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; | |
80 | 87 | } __packed; |
81 | 88 | |
82 | 89 | struct mgmt_mode { |
... | ... | @@ -285,7 +292,7 @@ |
285 | 292 | |
286 | 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 | 297 | #define MGMT_EV_DISCOVERABLE 0x0007 |
291 | 298 |
net/bluetooth/mgmt.c
... | ... | @@ -242,6 +242,63 @@ |
242 | 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 | 302 | static int read_controller_info(struct sock *sk, u16 index) |
246 | 303 | { |
247 | 304 | struct mgmt_rp_read_info rp; |
248 | 305 | |
249 | 306 | |
250 | 307 | |
251 | 308 | |
... | ... | @@ -263,26 +320,16 @@ |
263 | 320 | |
264 | 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); | |
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); | |
325 | + rp.version = hdev->hci_ver; | |
272 | 326 | |
273 | - if (test_bit(HCI_AUTH, &hdev->flags)) | |
274 | - rp.sec_mode = 3; | |
275 | - else if (hdev->ssp_mode > 0) | |
276 | - rp.sec_mode = 4; | |
277 | - else | |
278 | - rp.sec_mode = 2; | |
327 | + put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); | |
279 | 328 | |
280 | - bacpy(&rp.bdaddr, &hdev->bdaddr); | |
281 | - memcpy(rp.features, hdev->features, 8); | |
329 | + rp.supported_settings = cpu_to_le32(get_supported_settings(hdev)); | |
330 | + rp.current_settings = cpu_to_le32(get_current_settings(hdev)); | |
331 | + | |
282 | 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 | 334 | memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); |
288 | 335 | |
289 | 336 | |
290 | 337 | |
... | ... | @@ -365,13 +412,11 @@ |
365 | 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; | |
373 | - | |
374 | - return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); | |
419 | + return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings)); | |
375 | 420 | } |
376 | 421 | |
377 | 422 | static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) |
... | ... | @@ -398,7 +443,7 @@ |
398 | 443 | |
399 | 444 | up = test_bit(HCI_UP, &hdev->flags); |
400 | 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 | 447 | goto failed; |
403 | 448 | } |
404 | 449 | |
... | ... | @@ -466,8 +511,7 @@ |
466 | 511 | |
467 | 512 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && |
468 | 513 | test_bit(HCI_PSCAN, &hdev->flags)) { |
469 | - err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, | |
470 | - cp->val); | |
514 | + err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); | |
471 | 515 | goto failed; |
472 | 516 | } |
473 | 517 | |
... | ... | @@ -536,8 +580,7 @@ |
536 | 580 | } |
537 | 581 | |
538 | 582 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { |
539 | - err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, | |
540 | - cp->val); | |
583 | + err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); | |
541 | 584 | goto failed; |
542 | 585 | } |
543 | 586 | |
544 | 587 | |
... | ... | @@ -595,8 +638,9 @@ |
595 | 638 | static int set_pairable(struct sock *sk, u16 index, unsigned char *data, |
596 | 639 | u16 len) |
597 | 640 | { |
598 | - struct mgmt_mode *cp, ev; | |
641 | + struct mgmt_mode *cp; | |
599 | 642 | struct hci_dev *hdev; |
643 | + __le32 ev; | |
600 | 644 | int err; |
601 | 645 | |
602 | 646 | cp = (void *) data; |
603 | 647 | |
604 | 648 | |
... | ... | @@ -619,13 +663,13 @@ |
619 | 663 | else |
620 | 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 | 667 | if (err < 0) |
624 | 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 | 674 | failed: |
631 | 675 | hci_dev_unlock(hdev); |
632 | 676 | |
633 | 677 | |
634 | 678 | |
635 | 679 | |
... | ... | @@ -2234,18 +2278,15 @@ |
2234 | 2278 | struct cmd_lookup { |
2235 | 2279 | u8 val; |
2236 | 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 | 2286 | struct cmd_lookup *match = data; |
2243 | 2287 | |
2244 | - if (cp->val != match->val) | |
2245 | - return; | |
2288 | + send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); | |
2246 | 2289 | |
2247 | - send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val); | |
2248 | - | |
2249 | 2290 | list_del(&cmd->list); |
2250 | 2291 | |
2251 | 2292 | if (match->sk == NULL) { |
2252 | 2293 | |
2253 | 2294 | |
2254 | 2295 | |
... | ... | @@ -2258,20 +2299,21 @@ |
2258 | 2299 | |
2259 | 2300 | int mgmt_powered(struct hci_dev *hdev, u8 powered) |
2260 | 2301 | { |
2261 | - struct mgmt_mode ev; | |
2262 | - struct cmd_lookup match = { powered, NULL }; | |
2302 | + struct cmd_lookup match = { powered, NULL, hdev }; | |
2303 | + __le32 ev; | |
2263 | 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 | 2308 | if (!powered) { |
2268 | 2309 | u8 status = ENETDOWN; |
2269 | 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 | 2318 | if (match.sk) |
2277 | 2319 | sock_put(match.sk); |
2278 | 2320 | |
2279 | 2321 | |
2280 | 2322 | |
2281 | 2323 | |
... | ... | @@ -2281,17 +2323,16 @@ |
2281 | 2323 | |
2282 | 2324 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) |
2283 | 2325 | { |
2284 | - struct mgmt_mode ev; | |
2285 | - struct cmd_lookup match = { discoverable, NULL }; | |
2326 | + struct cmd_lookup match = { discoverable, NULL, hdev }; | |
2327 | + __le32 ev; | |
2286 | 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 | 2335 | match.sk); |
2294 | - | |
2295 | 2336 | if (match.sk) |
2296 | 2337 | sock_put(match.sk); |
2297 | 2338 | |
2298 | 2339 | |
2299 | 2340 | |
2300 | 2341 | |
... | ... | @@ -2300,15 +2341,16 @@ |
2300 | 2341 | |
2301 | 2342 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
2302 | 2343 | { |
2303 | - struct mgmt_mode ev; | |
2304 | - struct cmd_lookup match = { connectable, NULL }; | |
2344 | + __le32 ev; | |
2345 | + struct cmd_lookup match = { connectable, NULL, hdev }; | |
2305 | 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 | 2355 | if (match.sk) |
2314 | 2356 | sock_put(match.sk); |