diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2011-12-15 00:47:35 +0200 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-18 17:34:04 -0200 |
commit | 69ab39ea5da03e632a51b31534da713aff8d1e3b (patch) | |
tree | 3f10083b2ed1bd186f0f38b513453c68954dac45 /net | |
parent | 590051de5ce54f7ae02997ed0a2532f08c7b7866 (diff) | |
download | linux-69ab39ea5da03e632a51b31534da713aff8d1e3b.tar.gz linux-69ab39ea5da03e632a51b31534da713aff8d1e3b.tar.bz2 linux-69ab39ea5da03e632a51b31534da713aff8d1e3b.zip |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/mgmt.c | 146 |
1 files changed, 94 insertions, 52 deletions
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) return err; } +static u32 get_supported_settings(struct hci_dev *hdev) +{ + u32 settings = 0; + + settings |= MGMT_SETTING_POWERED; + settings |= MGMT_SETTING_CONNECTABLE; + settings |= MGMT_SETTING_FAST_CONNECTABLE; + settings |= MGMT_SETTING_DISCOVERABLE; + settings |= MGMT_SETTING_PAIRABLE; + + if (hdev->features[6] & LMP_SIMPLE_PAIR) + settings |= MGMT_SETTING_SSP; + + if (!(hdev->features[4] & LMP_NO_BREDR)) { + settings |= MGMT_SETTING_BREDR; + settings |= MGMT_SETTING_LINK_SECURITY; + } + + if (hdev->features[4] & LMP_LE) + settings |= MGMT_SETTING_LE; + + return settings; +} + +static u32 get_current_settings(struct hci_dev *hdev) +{ + u32 settings = 0; + + if (test_bit(HCI_UP, &hdev->flags)) + settings |= MGMT_SETTING_POWERED; + else + return settings; + + if (test_bit(HCI_PSCAN, &hdev->flags)) + settings |= MGMT_SETTING_CONNECTABLE; + + if (test_bit(HCI_ISCAN, &hdev->flags)) + settings |= MGMT_SETTING_DISCOVERABLE; + + if (test_bit(HCI_PAIRABLE, &hdev->flags)) + settings |= MGMT_SETTING_PAIRABLE; + + if (!(hdev->features[4] & LMP_NO_BREDR)) + settings |= MGMT_SETTING_BREDR; + + if (hdev->extfeatures[0] & LMP_HOST_LE) + settings |= MGMT_SETTING_LE; + + if (test_bit(HCI_AUTH, &hdev->flags)) + settings |= MGMT_SETTING_LINK_SECURITY; + + if (hdev->ssp_mode > 0) + settings |= MGMT_SETTING_SSP; + + return settings; +} + static int read_controller_info(struct sock *sk, u16 index) { struct mgmt_rp_read_info rp; @@ -263,26 +320,16 @@ static int read_controller_info(struct sock *sk, u16 index) memset(&rp, 0, sizeof(rp)); - rp.type = hdev->dev_type; + bacpy(&rp.bdaddr, &hdev->bdaddr); - rp.powered = test_bit(HCI_UP, &hdev->flags); - rp.connectable = test_bit(HCI_PSCAN, &hdev->flags); - rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags); - rp.pairable = test_bit(HCI_PSCAN, &hdev->flags); + rp.version = hdev->hci_ver; - if (test_bit(HCI_AUTH, &hdev->flags)) - rp.sec_mode = 3; - else if (hdev->ssp_mode > 0) - rp.sec_mode = 4; - else - rp.sec_mode = 2; + put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); + + rp.supported_settings = cpu_to_le32(get_supported_settings(hdev)); + rp.current_settings = cpu_to_le32(get_current_settings(hdev)); - bacpy(&rp.bdaddr, &hdev->bdaddr); - memcpy(rp.features, hdev->features, 8); memcpy(rp.dev_class, hdev->dev_class, 3); - put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); - rp.hci_ver = hdev->hci_ver; - put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); @@ -365,13 +412,11 @@ static void mgmt_pending_remove(struct pending_cmd *cmd) mgmt_pending_free(cmd); } -static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) +static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) { - struct mgmt_mode rp; + __le32 settings = cpu_to_le32(get_current_settings(hdev)); - rp.val = val; - - return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); + return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings)); } 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) up = test_bit(HCI_UP, &hdev->flags); if ((cp->val && up) || (!cp->val && !up)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); goto failed; } @@ -466,8 +511,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, - cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); goto failed; } @@ -536,8 +580,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, } if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, - cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); goto failed; } @@ -595,8 +638,9 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, static int set_pairable(struct sock *sk, u16 index, unsigned char *data, u16 len) { - struct mgmt_mode *cp, ev; + struct mgmt_mode *cp; struct hci_dev *hdev; + __le32 ev; int err; cp = (void *) data; @@ -619,13 +663,13 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, else clear_bit(HCI_PAIRABLE, &hdev->flags); - err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); if (err < 0) goto failed; - ev.val = cp->val; + ev = cpu_to_le32(get_current_settings(hdev)); - err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk); + err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk); failed: hci_dev_unlock(hdev); @@ -2234,17 +2278,14 @@ int mgmt_index_removed(struct hci_dev *hdev) struct cmd_lookup { u8 val; struct sock *sk; + struct hci_dev *hdev; }; -static void mode_rsp(struct pending_cmd *cmd, void *data) +static void settings_rsp(struct pending_cmd *cmd, void *data) { - struct mgmt_mode *cp = cmd->param; struct cmd_lookup *match = data; - if (cp->val != match->val) - return; - - send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val); + send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); list_del(&cmd->list); @@ -2258,20 +2299,21 @@ static void mode_rsp(struct pending_cmd *cmd, void *data) int mgmt_powered(struct hci_dev *hdev, u8 powered) { - struct mgmt_mode ev; - struct cmd_lookup match = { powered, NULL }; + struct cmd_lookup match = { powered, NULL, hdev }; + __le32 ev; int ret; - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, mode_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); if (!powered) { u8 status = ENETDOWN; mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); } - ev.val = powered; + ev = cpu_to_le32(get_current_settings(hdev)); - ret = mgmt_event(MGMT_EV_POWERED, hdev, &ev, sizeof(ev), match.sk); + ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), + match.sk); if (match.sk) sock_put(match.sk); @@ -2281,17 +2323,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) { - struct mgmt_mode ev; - struct cmd_lookup match = { discoverable, NULL }; + struct cmd_lookup match = { discoverable, NULL, hdev }; + __le32 ev; int ret; - mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mode_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match); - ev.val = discoverable; + ev = cpu_to_le32(get_current_settings(hdev)); - ret = mgmt_event(MGMT_EV_DISCOVERABLE, hdev, &ev, sizeof(ev), + ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk); - if (match.sk) sock_put(match.sk); @@ -2300,15 +2341,16 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) int mgmt_connectable(struct hci_dev *hdev, u8 connectable) { - struct mgmt_mode ev; - struct cmd_lookup match = { connectable, NULL }; + __le32 ev; + struct cmd_lookup match = { connectable, NULL, hdev }; int ret; - mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, mode_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp, + &match); - ev.val = connectable; + ev = cpu_to_le32(get_current_settings(hdev)); - ret = mgmt_event(MGMT_EV_CONNECTABLE, hdev, &ev, sizeof(ev), match.sk); + ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk); if (match.sk) sock_put(match.sk); |