From 4a67e5d4adbf3b419f17924322f468ac5cb8c14f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 25 Feb 2019 13:11:37 -0600 Subject: Bluetooth: mgmt: Use struct_size() helper Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes, in particular in the context in which this code is being used. So, change the following form: sizeof(*rp) + (sizeof(rp->entry[0]) * count); to : struct_size(rp, entry, count) Notice that, in this case, variable rp_len is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ccce954f8146..1e2acaddcdfd 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -474,7 +474,6 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev, { struct mgmt_rp_read_ext_index_list *rp; struct hci_dev *d; - size_t rp_len; u16 count; int err; @@ -488,8 +487,7 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev, count++; } - rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count); - rp = kmalloc(rp_len, GFP_ATOMIC); + rp = kmalloc(struct_size(rp, entry, count), GFP_ATOMIC); if (!rp) { read_unlock(&hci_dev_list_lock); return -ENOMEM; @@ -525,7 +523,6 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev, } rp->num_controllers = cpu_to_le16(count); - rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count); read_unlock(&hci_dev_list_lock); @@ -538,7 +535,8 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev, hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, - MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len); + MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, + struct_size(rp, entry, count)); kfree(rp); -- cgit v1.2.3 From 7a0e5b15ca458dd47e4c60b7fa9f22b84c7068c7 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 19 Feb 2019 12:05:57 -0800 Subject: Bluetooth: Add quirk for reading BD_ADDR from fwnode property Add HCI_QUIRK_USE_BDADDR_PROPERTY to allow controllers to retrieve the public Bluetooth address from the firmware node property 'local-bd-address'. If quirk is set and the property does not exist or is invalid the controller is marked as unconfigured. Signed-off-by: Matthias Kaehlcke Reviewed-by: Balakrishna Godavarthi Tested-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/mgmt.c | 6 ++++-- 2 files changed, 47 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 26e3d36aee29..d6b2540ba7f8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1355,6 +1356,32 @@ done: return err; } +/** + * hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address + * (BD_ADDR) for a HCI device from + * a firmware node property. + * @hdev: The HCI device + * + * Search the firmware node for 'local-bd-address'. + * + * All-zero BD addresses are rejected, because those could be properties + * that exist in the firmware tables, but were not updated by the firmware. For + * example, the DTS could define 'local-bd-address', with zero BD addresses. + */ +static void hci_dev_get_bd_addr_from_property(struct hci_dev *hdev) +{ + struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent); + bdaddr_t ba; + int ret; + + ret = fwnode_property_read_u8_array(fwnode, "local-bd-address", + (u8 *)&ba, sizeof(ba)); + if (ret < 0 || !bacmp(&ba, BDADDR_ANY)) + return; + + bacpy(&hdev->public_addr, &ba); +} + static int hci_dev_do_open(struct hci_dev *hdev) { int ret = 0; @@ -1422,6 +1449,22 @@ static int hci_dev_do_open(struct hci_dev *hdev) if (hdev->setup) ret = hdev->setup(hdev); + if (ret) + goto setup_failed; + + if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) { + if (!bacmp(&hdev->public_addr, BDADDR_ANY)) + hci_dev_get_bd_addr_from_property(hdev); + + if (bacmp(&hdev->public_addr, BDADDR_ANY) && + hdev->set_bdaddr) + ret = hdev->set_bdaddr(hdev, + &hdev->public_addr); + else + ret = -EADDRNOTAVAIL; + } + +setup_failed: /* The transport driver can set these quirks before * creating the HCI device or in its setup callback. * diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 1e2acaddcdfd..2457f408d17d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -549,7 +549,8 @@ static bool is_configured(struct hci_dev *hdev) !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED)) return false; - if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && + if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) || + test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) && !bacmp(&hdev->public_addr, BDADDR_ANY)) return false; @@ -564,7 +565,8 @@ static __le32 get_missing_options(struct hci_dev *hdev) !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED)) options |= MGMT_OPTION_EXTERNAL_CONFIG; - if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && + if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) || + test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) && !bacmp(&hdev->public_addr, BDADDR_ANY)) options |= MGMT_OPTION_PUBLIC_ADDRESS; -- cgit v1.2.3