From 33337dcb891e54d63433101af21fbff0b3f87bfa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 23 Oct 2013 08:28:01 -0700 Subject: [PATCH 01/19] Bluetooth: Fix limited discoverable mode for Zeevo modules There is an old Panasonic module with a Zeevo chip in there that is not really operating according to Bluetooth core specification when it comes to setting the IAC LAP for limited discoverable mode. For reference, this is the vendor information about this module: < HCI Command: Read Local Version Information (0x04|0x0001) plen 0 > HCI Event: Command Complete (0x0e) plen 12 Read Local Version Information (0x04|0x0001) ncmd 1 Status: Success (0x00) HCI version: Bluetooth 1.2 (0x02) - Revision 196 (0x00c4) LMP version: Bluetooth 1.2 (0x02) - Subversion 61 (0x003d) Manufacturer: Zeevo, Inc. (18) The module reports only the support for one IAC at a time. And that is totally acceptable according to the Bluetooth core specification since the minimum supported IAC is only one. < HCI Command: Read Number of Supported IAC (0x03|0x0038) plen 0 > HCI Event: Command Complete (0x0e) plen 5 Read Number of Supported IAC (0x03|0x0038) ncmd 1 Status: Success (0x00) Number of IAC: 1 The problem arises when trying to program two IAC into the module on a controller that only supports one. < HCI Command: Write Current IAC LAP (0x03|0x003a) plen 7 Number of IAC: 2 Access code: 0x9e8b00 (Limited Inquiry) Access code: 0x9e8b33 (General Inquiry) > HCI Event: Command Status (0x0f) plen 4 Write Current IAC LAP (0x03|0x003a) ncmd 1 Status: Unknown HCI Command (0x01) While this looks strange, but according to the Bluetooth core specification it is a legal operation. The controller has to ignore the other values and only program as many as it supports. This command shall clear any existing IACs and stores Num_Current_IAC and the IAC_LAPs in to the controller. If Num_Current_IAC is greater than Num_Support_IAC then only the first Num_Support_IAC shall be stored in the controller, and a Command Complete event with error code Success (0x00) shall be generated. This specific controller has a bug here and just returns an error. So in case the number of supported IAC is less than two and the limited discoverable mode is requested, now only the LIAC is written to the controller. < HCI Command: Write Current IAC LAP (0x03|0x003a) plen 4 Number of IAC: 1 Access code: 0x9e8b00 (Limited Inquiry) > HCI Event: Command Complete (0x0e) plen 4 Write Current IAC LAP (0x03|0x003a) ncmd 1 Status: Success (0x00) All other controllers that only support one IAC seem to handle this perfectly fine, but this fix will only write the LIAC for these controllers as well. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 074d83690a41..22cf54710744 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1264,7 +1264,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, if (cp->val == 0x02) { /* Limited discoverable mode */ - hci_cp.num_iac = 2; + hci_cp.num_iac = min_t(u8, hdev->num_iac, 2); hci_cp.iac_lap[0] = 0x00; /* LIAC */ hci_cp.iac_lap[1] = 0x8b; hci_cp.iac_lap[2] = 0x9e; From bef34c0aa1bdd5bc106697bd7340eb212dcf3c85 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 29 Oct 2013 12:26:51 -0700 Subject: [PATCH 02/19] Bluetooth: Set default own address type only during controller setup The default own address type is currently set at every power on of a controller. This overwrites the value set via debugfs. To avoid this issue, set the default own address type only during controller setup. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 6ccc4eb9e55e..03e83558a411 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1275,15 +1275,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) hci_setup_link_policy(req); if (lmp_le_capable(hdev)) { - /* If the controller has a public BD_ADDR, then by - * default use that one. If this is a LE only - * controller without one, default to the random - * address. - */ - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) - hdev->own_addr_type = ADDR_LE_DEV_PUBLIC; - else - hdev->own_addr_type = ADDR_LE_DEV_RANDOM; + if (test_bit(HCI_SETUP, &hdev->dev_flags)) { + /* If the controller has a public BD_ADDR, then + * by default use that one. If this is a LE only + * controller without a public address, default + * to the random address. + */ + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + hdev->own_addr_type = ADDR_LE_DEV_PUBLIC; + else + hdev->own_addr_type = ADDR_LE_DEV_RANDOM; + } hci_set_le_support(req); } From d3d5dd3eb45c37141096c65a3742f4cf38f785ea Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 31 Oct 2013 04:54:32 -0700 Subject: [PATCH 03/19] Bluetooth: Remove debug statement for features complete event The complete list of local features are available through debugfs and so there is no need to add a debug print here. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5935f748c0f9..d75d51ff4fdd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -538,12 +538,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, if (hdev->features[0][5] & LMP_EDR_3S_ESCO) hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); - - BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, - hdev->features[0][0], hdev->features[0][1], - hdev->features[0][2], hdev->features[0][3], - hdev->features[0][4], hdev->features[0][5], - hdev->features[0][6], hdev->features[0][7]); } static void hci_cc_read_local_ext_features(struct hci_dev *hdev, From 6a070e6e81adfaed060c5696ef3388126d2165b1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 31 Oct 2013 04:54:33 -0700 Subject: [PATCH 04/19] Bluetooth: Store supported commands only during setup procedure The list of supported commands of a controller can not change during its lifetime. So store the list just once during the setup procedure and not every time the HCI command is executed. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d75d51ff4fdd..4d0f4018df18 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -486,7 +486,10 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); - if (!rp->status) + if (rp->status) + return; + + if (test_bit(HCI_SETUP, &hdev->dev_flags)) memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); } From 3e4543abf9deea8733341d235719e7e02b4068ed Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 31 Oct 2013 15:08:31 -0700 Subject: [PATCH 05/19] Bluetooth: btmrvl: operate on 16-bit opcodes instead of ogf/ocf Replace ogf/ocf and its packing with 16-bit opcodes. Signed-off-by: Bing Zhao Signed-off-by: Amitkumar Karwar Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 19 +++++++++++-------- drivers/bluetooth/btmrvl_main.c | 21 +++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index f9d183387f45..e3b49c68ea71 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -90,12 +90,12 @@ struct btmrvl_private { #define MRVL_VENDOR_PKT 0xFE -/* Bluetooth commands */ -#define BT_CMD_AUTO_SLEEP_MODE 0x23 -#define BT_CMD_HOST_SLEEP_CONFIG 0x59 -#define BT_CMD_HOST_SLEEP_ENABLE 0x5A -#define BT_CMD_MODULE_CFG_REQ 0x5B -#define BT_CMD_LOAD_CONFIG_DATA 0x61 +/* Vendor specific Bluetooth commands */ +#define BT_CMD_AUTO_SLEEP_MODE 0xFC23 +#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 +#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A +#define BT_CMD_MODULE_CFG_REQ 0xFC5B +#define BT_CMD_LOAD_CONFIG_DATA 0xFC61 /* Sub-commands: Module Bringup/Shutdown Request/Response */ #define MODULE_BRINGUP_REQ 0xF1 @@ -104,6 +104,11 @@ struct btmrvl_private { #define MODULE_SHUTDOWN_REQ 0xF2 +/* Vendor specific Bluetooth events */ +#define BT_EVENT_AUTO_SLEEP_MODE 0x23 +#define BT_EVENT_HOST_SLEEP_CONFIG 0x59 +#define BT_EVENT_HOST_SLEEP_ENABLE 0x5A +#define BT_EVENT_MODULE_CFG_REQ 0x5B #define BT_EVENT_POWER_STATE 0x20 /* Bluetooth Power States */ @@ -111,8 +116,6 @@ struct btmrvl_private { #define BT_PS_DISABLE 0x03 #define BT_PS_SLEEP 0x01 -#define OGF 0x3F - /* Host Sleep states */ #define HS_ACTIVATED 0x01 #define HS_DEACTIVATED 0x00 diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 5cf31c4fe6d1..477b658316b4 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -50,12 +50,10 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) if (hdr->evt == HCI_EV_CMD_COMPLETE) { struct hci_ev_cmd_complete *ec; - u16 opcode, ocf, ogf; + u16 opcode; ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE); opcode = __le16_to_cpu(ec->opcode); - ocf = hci_opcode_ocf(opcode); - ogf = hci_opcode_ogf(opcode); if (priv->btmrvl_dev.sendcmdflag) { priv->btmrvl_dev.sendcmdflag = false; @@ -63,9 +61,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) wake_up_interruptible(&priv->adapter->cmd_wait_q); } - if (ogf == OGF) { - BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x", - ogf, ocf); + if (hci_opcode_ogf(opcode) == 0x3F) { + BT_DBG("vendor event skipped: opcode=%#4.4x", opcode); kfree_skb(skb); return false; } @@ -89,7 +86,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) } switch (event->data[0]) { - case BT_CMD_AUTO_SLEEP_MODE: + case BT_EVENT_AUTO_SLEEP_MODE: if (!event->data[2]) { if (event->data[1] == BT_PS_ENABLE) adapter->psmode = 1; @@ -102,7 +99,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) } break; - case BT_CMD_HOST_SLEEP_CONFIG: + case BT_EVENT_HOST_SLEEP_CONFIG: if (!event->data[3]) BT_DBG("gpio=%x, gap=%x", event->data[1], event->data[2]); @@ -110,7 +107,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) BT_DBG("HSCFG command failed"); break; - case BT_CMD_HOST_SLEEP_ENABLE: + case BT_EVENT_HOST_SLEEP_ENABLE: if (!event->data[1]) { adapter->hs_state = HS_ACTIVATED; if (adapter->psmode) @@ -121,7 +118,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) } break; - case BT_CMD_MODULE_CFG_REQ: + case BT_EVENT_MODULE_CFG_REQ: if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_BRINGUP_REQ) { BT_DBG("EVENT:%s", @@ -166,7 +163,7 @@ exit: } EXPORT_SYMBOL_GPL(btmrvl_process_event); -static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, +static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, const void *param, u8 len) { struct sk_buff *skb; @@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, } hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE); - hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no)); + hdr->opcode = cpu_to_le16(opcode); hdr->plen = len; if (len) From 433a9389a11778f1bc342789abccac9ce46eee82 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 1 Nov 2013 15:28:24 -0700 Subject: [PATCH 06/19] Bluetooth: btmrvl: use cal-data from device-tree instead of conf file Some ARM versions of Chromebook need to download a new calibration data from host driver to firmware. They do have EEPROM but still need a piece of new calibration data in test mode. The cal-data is platform dependent. It's simpler and more feasible to use device tree based cal-data instead of configuration file based cal-data. This patch remove configuration file based cal-data downloading and replace it using cal-data from device tree. When CONFIG_OF is not selected, or the specific property is not present in the device tree, the calibration downloading will not happen. Cc: Mike Frysinger Cc: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Hyuckjoo Lee Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 4 -- drivers/bluetooth/btmrvl_main.c | 92 ++++++--------------------------- drivers/bluetooth/btmrvl_sdio.c | 9 +--- drivers/bluetooth/btmrvl_sdio.h | 2 - 4 files changed, 18 insertions(+), 89 deletions(-) diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index e3b49c68ea71..98187f09393d 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -23,8 +23,6 @@ #include #include #include -#include -#include #define BTM_HEADER_LEN 4 #define BTM_UPLD_SIZE 2312 @@ -43,8 +41,6 @@ struct btmrvl_thread { struct btmrvl_device { void *card; struct hci_dev *hcidev; - struct device *dev; - const char *cal_data; u8 dev_type; diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 477b658316b4..6441f724aeb0 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -19,7 +19,7 @@ **/ #include - +#include #include #include @@ -414,52 +414,8 @@ static int btmrvl_open(struct hci_dev *hdev) return 0; } -/* - * This function parses provided calibration data input. It should contain - * hex bytes separated by space or new line character. Here is an example. - * 00 1C 01 37 FF FF FF FF 02 04 7F 01 - * CE BA 00 00 00 2D C6 C0 00 00 00 00 - * 00 F0 00 00 - */ -static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size) -{ - const u8 *s = src; - u8 *d = dst; - int ret; - u8 tmp[3]; - - tmp[2] = '\0'; - while ((s - src) <= len - 2) { - if (isspace(*s)) { - s++; - continue; - } - - if (isxdigit(*s)) { - if ((d - dst) >= dst_size) { - BT_ERR("calibration data file too big!!!"); - return -EINVAL; - } - - memcpy(tmp, s, 2); - - ret = kstrtou8(tmp, 16, d++); - if (ret < 0) - return ret; - - s += 2; - } else { - return -EINVAL; - } - } - if (d == dst) - return -EINVAL; - - return 0; -} - -static int btmrvl_load_cal_data(struct btmrvl_private *priv, - u8 *config_data) +static int btmrvl_download_cal_data(struct btmrvl_private *priv, + u8 *config_data) { int i, ret; u8 data[BT_CMD_DATA_SIZE]; @@ -487,54 +443,40 @@ static int btmrvl_load_cal_data(struct btmrvl_private *priv, return 0; } -static int -btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size) +static int btmrvl_cal_data_dt(struct btmrvl_private *priv) { + struct device_node *dt_node; u8 cal_data[BT_CAL_DATA_SIZE]; + const char name[] = "btmrvl_caldata"; + const char property[] = "btmrvl,caldata"; int ret; - ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data)); + dt_node = of_find_node_by_name(NULL, name); + if (!dt_node) + return -ENODEV; + + ret = of_property_read_u8_array(dt_node, property, cal_data, + sizeof(cal_data)); if (ret) return ret; - ret = btmrvl_load_cal_data(priv, cal_data); + BT_DBG("Use cal data from device tree"); + ret = btmrvl_download_cal_data(priv, cal_data); if (ret) { - BT_ERR("Fail to load calibrate data"); + BT_ERR("Fail to download calibrate data"); return ret; } return 0; } -static int btmrvl_cal_data_config(struct btmrvl_private *priv) -{ - const struct firmware *cfg; - int ret; - const char *cal_data = priv->btmrvl_dev.cal_data; - - if (!cal_data) - return 0; - - ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev); - if (ret < 0) { - BT_DBG("Failed to get %s file, skipping cal data download", - cal_data); - return 0; - } - - ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size); - release_firmware(cfg); - return ret; -} - static int btmrvl_setup(struct hci_dev *hdev) { struct btmrvl_private *priv = hci_get_drvdata(hdev); btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); - if (btmrvl_cal_data_config(priv)) - BT_ERR("Set cal data failed"); + btmrvl_cal_data_dt(priv); priv->btmrvl_dev.psmode = 1; btmrvl_enable_ps(priv); diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index fabcf5bb48af..1b52c9f5230d 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -18,6 +18,7 @@ * this warranty disclaimer. **/ +#include #include #include @@ -101,7 +102,6 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { .helper = "mrvl/sd8688_helper.bin", .firmware = "mrvl/sd8688.bin", - .cal_data = NULL, .reg = &btmrvl_reg_8688, .sd_blksz_fw_dl = 64, }; @@ -109,7 +109,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { .helper = NULL, .firmware = "mrvl/sd8787_uapsta.bin", - .cal_data = NULL, .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -117,7 +116,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { .helper = NULL, .firmware = "mrvl/sd8797_uapsta.bin", - .cal_data = "mrvl/sd8797_caldata.conf", .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -125,7 +123,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { .helper = NULL, .firmware = "mrvl/sd8897_uapsta.bin", - .cal_data = NULL, .reg = &btmrvl_reg_88xx, .sd_blksz_fw_dl = 256, }; @@ -1007,7 +1004,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func, struct btmrvl_sdio_device *data = (void *) id->driver_data; card->helper = data->helper; card->firmware = data->firmware; - card->cal_data = data->cal_data; card->reg = data->reg; card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; } @@ -1036,8 +1032,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func, } card->priv = priv; - priv->btmrvl_dev.dev = &card->func->dev; - priv->btmrvl_dev.cal_data = card->cal_data; /* Initialize the interface specific function pointers */ priv->hw_host_to_card = btmrvl_sdio_host_to_card; @@ -1220,5 +1214,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); MODULE_FIRMWARE("mrvl/sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); -MODULE_FIRMWARE("mrvl/sd8797_caldata.conf"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 6872d9ecac07..43d35a609ca9 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -85,7 +85,6 @@ struct btmrvl_sdio_card { u32 ioport; const char *helper; const char *firmware; - const char *cal_data; const struct btmrvl_sdio_card_reg *reg; u16 sd_blksz_fw_dl; u8 rx_unit; @@ -95,7 +94,6 @@ struct btmrvl_sdio_card { struct btmrvl_sdio_device { const char *helper; const char *firmware; - const char *cal_data; const struct btmrvl_sdio_card_reg *reg; u16 sd_blksz_fw_dl; }; From 8a4934f1d62b8be7a00cdb4e65124f4d02d412f3 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 1 Nov 2013 15:28:25 -0700 Subject: [PATCH 07/19] Bluetooth: btmrvl: remove cal-data byte swapping and redundant mem copy The device tree property can define the cal-data in proper order. There is no need to swap the bytes in driver. Also remove the redundant cal-data memory copy after removing the byte swapping. Cc: Mike Frysinger Cc: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Hyuckjoo Lee Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 2 +- drivers/bluetooth/btmrvl_main.c | 27 ++++++++++----------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 98187f09393d..7399303d7d99 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -120,7 +120,7 @@ struct btmrvl_private { #define PS_SLEEP 0x01 #define PS_AWAKE 0x00 -#define BT_CMD_DATA_SIZE 32 +#define BT_CAL_HDR_LEN 4 #define BT_CAL_DATA_SIZE 28 struct btmrvl_event { diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 6441f724aeb0..1e0320af00c6 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -415,28 +415,20 @@ static int btmrvl_open(struct hci_dev *hdev) } static int btmrvl_download_cal_data(struct btmrvl_private *priv, - u8 *config_data) + u8 *data, int len) { - int i, ret; - u8 data[BT_CMD_DATA_SIZE]; + int ret; data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; - data[3] = BT_CMD_DATA_SIZE - 4; - - /* Swap cal-data bytes. Each four bytes are swapped. Considering 4 - * byte SDIO header offset, mapping of input and output bytes will be - * {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4}, - * {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */ - for (i = 4; i < BT_CMD_DATA_SIZE; i++) - data[i] = config_data[(i / 4) * 8 - 1 - i]; + data[3] = len; print_hex_dump_bytes("Calibration data: ", - DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE); + DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len); ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data, - BT_CMD_DATA_SIZE); + BT_CAL_HDR_LEN + len); if (ret) BT_ERR("Failed to download caibration data\n"); @@ -446,7 +438,7 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv, static int btmrvl_cal_data_dt(struct btmrvl_private *priv) { struct device_node *dt_node; - u8 cal_data[BT_CAL_DATA_SIZE]; + u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE]; const char name[] = "btmrvl_caldata"; const char property[] = "btmrvl,caldata"; int ret; @@ -455,13 +447,14 @@ static int btmrvl_cal_data_dt(struct btmrvl_private *priv) if (!dt_node) return -ENODEV; - ret = of_property_read_u8_array(dt_node, property, cal_data, - sizeof(cal_data)); + ret = of_property_read_u8_array(dt_node, property, + cal_data + BT_CAL_HDR_LEN, + BT_CAL_DATA_SIZE); if (ret) return ret; BT_DBG("Use cal data from device tree"); - ret = btmrvl_download_cal_data(priv, cal_data); + ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE); if (ret) { BT_ERR("Fail to download calibrate data"); return ret; From 3655bba8fe693e31c44c43cd30a9aaeee8bd45df Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Wed, 30 Oct 2013 19:01:40 -0300 Subject: [PATCH 08/19] Bluetooth: Check address in mgmt_disconnect_failed() Check the address and address type in mgmt_disconnect_failed() otherwise we may wrongly fail the MGMT_OP_DISCONNECT command. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 22cf54710744..6a74aa776541 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4613,6 +4613,8 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status) { + u8 bdaddr_type = link_to_bdaddr(link_type, addr_type); + struct mgmt_cp_disconnect *cp; struct mgmt_rp_disconnect rp; struct pending_cmd *cmd; @@ -4623,8 +4625,16 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, if (!cmd) return; + cp = cmd->param; + + if (bacmp(bdaddr, &cp->addr.bdaddr)) + return; + + if (cp->addr.type != bdaddr_type) + return; + bacpy(&rp.addr.bdaddr, bdaddr); - rp.addr.type = link_to_bdaddr(link_type, addr_type); + rp.addr.type = bdaddr_type; cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, mgmt_status(status), &rp, sizeof(rp)); From 57eb776feac497c8e5b561c0a24156245f0c08db Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Wed, 30 Oct 2013 19:01:41 -0300 Subject: [PATCH 09/19] Bluetooth: Add an extra check in mgmt_device_disconnected() This patch adds an extra check in mgmt_device_disconnected() so we only send the "Device Disconnected" event if it is ACL_LINK or LE_LINK link type. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 6a74aa776541..a03ca3ca91bf 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4595,6 +4595,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, struct mgmt_ev_device_disconnected ev; struct sock *sk = NULL; + if (link_type != ACL_LINK && link_type != LE_LINK) + return; + mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); bacpy(&ev.addr.bdaddr, bdaddr); From 4ebbd5357531694b9243b176674ae27edf5bd8e1 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Wed, 30 Oct 2013 19:01:42 -0300 Subject: [PATCH 10/19] Bluetooth: Remove link type check in hci_disconn_complete_evt() We can safely remove the link type check from hci_disconn_complete_ evt() since this check in not required for mgmt_disconnect_failed() and mgmt_device_disconnected() does it internally. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4d0f4018df18..142aa61f9c3f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1792,8 +1792,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ev->status == 0) conn->state = BT_CLOSED; - if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && - (conn->type == ACL_LINK || conn->type == LE_LINK)) { + if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { if (ev->status) { mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); From 84794e119a22f67f2cac3f0ae958f2d69c46fa1e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 6 Nov 2013 11:24:57 +0200 Subject: [PATCH 11/19] Bluetooth: Remove unnecessary 'send' parameter from smp_failure() The send parameter has only been used for determining whether to send a Pairing Failed PDU or not. However, the function can equally well use the already existing reason parameter to make this choice and send the PDU whenever a non-zero value was passed. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/smp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 4b07acb8293c..f99352d1aa43 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -257,11 +257,11 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) return 0; } -static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) +static void smp_failure(struct l2cap_conn *conn, u8 reason) { struct hci_conn *hcon = conn->hcon; - if (send) + if (reason) smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); @@ -406,7 +406,7 @@ static void confirm_work(struct work_struct *work) return; error: - smp_failure(conn, reason, 1); + smp_failure(conn, reason); } static void random_work(struct work_struct *work) @@ -490,7 +490,7 @@ static void random_work(struct work_struct *work) return; error: - smp_failure(conn, reason, 1); + smp_failure(conn, reason); } static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) @@ -555,10 +555,10 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) break; case MGMT_OP_USER_PASSKEY_NEG_REPLY: case MGMT_OP_USER_CONFIRM_NEG_REPLY: - smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); + smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); return 0; default: - smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1); + smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); return -EOPNOTSUPP; } @@ -895,7 +895,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) break; case SMP_CMD_PAIRING_FAIL: - smp_failure(conn, skb->data[0], 0); + smp_failure(conn, 0); reason = 0; err = -EPERM; break; @@ -941,7 +941,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) done: if (reason) - smp_failure(conn, reason, 1); + smp_failure(conn, reason); kfree_skb(skb); return err; From bd0fca1b2be8c96dfc391a2bc2ee4ce6970ae6af Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 6 Nov 2013 10:56:00 +0530 Subject: [PATCH 12/19] Bluetooth: ath3k: Add support for another AR3012 card T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=04ca ProdID=300b Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01 I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Reported-by: Face Signed-off-by: Sujith Manoharan Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 6bfc1bb318f6..cb5ef5ba9650 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -83,6 +83,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3006) }, { USB_DEVICE(0x04CA, 0x3008) }, + { USB_DEVICE(0x04CA, 0x300b) }, { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0CF3, 0xE005) }, @@ -125,6 +126,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c0ff34f2d2df..67790b78a974 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -150,6 +150,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, From 35580d223b6b04d9a570e4fe377c46a102413fe8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 4 Nov 2013 21:38:23 +0530 Subject: [PATCH 13/19] Bluetooth: ath3k: Add support for a new AR3012 device T: Bus=02 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 9 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e05f Rev= 0.02 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01 I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Reported-by: Joshua Richenhagen Signed-off-by: Sujith Manoharan Signed-off-by: Johan Hedberg --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index cb5ef5ba9650..d3fdc32b579d 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -97,6 +97,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x0cf3, 0x3121) }, { USB_DEVICE(0x0cf3, 0xe003) }, + { USB_DEVICE(0x0489, 0xe05f) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -140,6 +141,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 67790b78a974..3d04bce0d12f 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -164,6 +164,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, From abf54a506d06e0b3ba2c408040e647791af37937 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 7 Nov 2013 17:36:09 -0300 Subject: [PATCH 14/19] Bluetooth: Remove unneeded check in hci_disconn_complete_evt() According to b644ba336 (patch that introduced HCI_CONN_MGMT_CONNECTED flag), the HCI_CONN_MGMT_CONNECTED flag tracks when mgmt has been notified about the connection. That being said, there is no point in calling mgmt_disconnect_failed() conditionally based on this flag. mgmt_disconnect_failed() removes pending MGMT_OP_DISCONNECT commands, it doesn't matter if that connection was notified or not. Moreover, if the Disconnection Complete event has status then we have nothing else to do but call mgmt_disconnect_failed() and return. Signed-off-by: Andre Guedes Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 142aa61f9c3f..eb99a12948c5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1779,6 +1779,7 @@ static u8 hci_to_mgmt_reason(u8 err) static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_disconn_complete *ev = (void *) skb->data; + u8 reason = hci_to_mgmt_reason(ev->reason); struct hci_conn *conn; BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); @@ -1792,18 +1793,16 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ev->status == 0) conn->state = BT_CLOSED; - if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { - if (ev->status) { - mgmt_disconnect_failed(hdev, &conn->dst, conn->type, - conn->dst_type, ev->status); - } else { - u8 reason = hci_to_mgmt_reason(ev->reason); - - mgmt_device_disconnected(hdev, &conn->dst, conn->type, - conn->dst_type, reason); - } + if (ev->status) { + mgmt_disconnect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, ev->status); + goto unlock; } + if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) + mgmt_device_disconnected(hdev, &conn->dst, conn->type, + conn->dst_type, reason); + if (ev->status == 0) { u8 type = conn->type; From 3846220b0df414816d00365cec559ff3c8b7c4bf Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 7 Nov 2013 17:36:10 -0300 Subject: [PATCH 15/19] Bluetooth: Refactor hci_disconn_complete_evt hci_disconn_complete_evt() logic is more complicated than what it should be, making it hard to follow and add new features. So this patch does some code refactoring by handling the error cases in the beginning of the function and by moving the main flow into the first level of function scope. No change is done in the event handling logic itself. Besides organizing this messy code, this patch makes easier to add code for handling LE auto connection (which will be added in a further patch). Signed-off-by: Andre Guedes Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 43 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index eb99a12948c5..5fb3df66c2cd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1781,6 +1781,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) struct hci_ev_disconn_complete *ev = (void *) skb->data; u8 reason = hci_to_mgmt_reason(ev->reason); struct hci_conn *conn; + u8 type; BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); @@ -1790,40 +1791,38 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (!conn) goto unlock; - if (ev->status == 0) - conn->state = BT_CLOSED; - if (ev->status) { mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); goto unlock; } + conn->state = BT_CLOSED; + if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, reason); - if (ev->status == 0) { - u8 type = conn->type; + if (conn->type == ACL_LINK && conn->flush_key) + hci_remove_link_key(hdev, &conn->dst); - if (type == ACL_LINK && conn->flush_key) - hci_remove_link_key(hdev, &conn->dst); - hci_proto_disconn_cfm(conn, ev->reason); - hci_conn_del(conn); + type = conn->type; - /* Re-enable advertising if necessary, since it might - * have been disabled by the connection. From the - * HCI_LE_Set_Advertise_Enable command description in - * the core specification (v4.0): - * "The Controller shall continue advertising until the Host - * issues an LE_Set_Advertise_Enable command with - * Advertising_Enable set to 0x00 (Advertising is disabled) - * or until a connection is created or until the Advertising - * is timed out due to Directed Advertising." - */ - if (type == LE_LINK) - mgmt_reenable_advertising(hdev); - } + hci_proto_disconn_cfm(conn, ev->reason); + hci_conn_del(conn); + + /* Re-enable advertising if necessary, since it might + * have been disabled by the connection. From the + * HCI_LE_Set_Advertise_Enable command description in + * the core specification (v4.0): + * "The Controller shall continue advertising until the Host + * issues an LE_Set_Advertise_Enable command with + * Advertising_Enable set to 0x00 (Advertising is disabled) + * or until a connection is created or until the Advertising + * is timed out due to Directed Advertising." + */ + if (type == LE_LINK) + mgmt_reenable_advertising(hdev); unlock: hci_dev_unlock(hdev); From ef4e5e4a756ff077dbdbdb8481d0e3788a07c005 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Tue, 12 Nov 2013 13:10:58 -0800 Subject: [PATCH 16/19] Bluetooth: Add support for Intel Bluetooth device [8087:0a2a] This patch adds support for new Intel Bluetooth device. T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=8087 ProdID=0a2a Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3d04bce0d12f..b73ae34cdbe0 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -225,6 +225,7 @@ static const struct usb_device_id blacklist_table[] = { /* Intel Bluetooth device */ { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, + { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, { } /* Terminating entry */ }; From d2bee8fb6e18f6116aada39851918473761f7ab1 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Tue, 12 Nov 2013 13:16:41 -0800 Subject: [PATCH 17/19] Bluetooth: Enable autosuspend for Intel Bluetooth device This patch enables autosuspend for Intel Bluetooth device. After btusb is loaded for Intel Bluetooth device, the power/control attribute contains "on" value by default which disables the autosuspend. Based on the USB PM document(Documentation/usb/power-management.txt), kernel disabled the autosuspend for all devices other than hub by default. "The USB specification states that all USB devices must support power management. Nevertheless, the sad fact is that many devices do not support it very well. You can suspend them all right, but when you try to resume them they disconnect themselves from the USB bus or they stop working entirely. This seems to be especially prevalent among printers and scanners, but plenty of other types of device have the same deficiency. For this reason, by default the kernel disables autosuspend (the power/control attribute is initialized to "on") for all devices other than hubs. Hubs, at least, appear to be reasonably well-behaved in this regard." This document also described how the driver can enables the autosuspend by using an USB api. "Drivers can enable autosuspend for their devices by calling usb_enable_autosuspend(struct usb_device *udev); in their probe() routine, if they know that the device is capable of suspending and resuming correctly. This is exactly equivalent to writing "auto" to the device's power/control attribute." For Intel Bluetooth device, the autosuspend needs to be enabled so the device can transit to LPM(Low Power Mode) and ULPM(Ultra LPM) states after receiving suspend message from the host. Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b73ae34cdbe0..bfbcc5a772a6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1438,8 +1438,10 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_BCM92035) hdev->setup = btusb_setup_bcm92035; - if (id->driver_info & BTUSB_INTEL) + if (id->driver_info & BTUSB_INTEL) { + usb_enable_autosuspend(data->udev); hdev->setup = btusb_setup_intel; + } /* Interface numbers are hardcoded in the specification */ data->isoc = usb_ifnum_to_if(data->udev, 1); From e84a6b139bdd3af2914f194ff840b1a36fa55598 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 2 Dec 2013 10:49:03 +0200 Subject: [PATCH 18/19] Bluetooth: Remove useless smp_rand function This function was always just making a single get_random_bytes() call and always returning the value 0. It's simpler to just call get_random_bytes() directly where needed. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/smp.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index f99352d1aa43..3bcb765b6a92 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -143,13 +143,6 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], return err; } -static int smp_rand(u8 *buf) -{ - get_random_bytes(buf, 16); - - return 0; -} - static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, u16 dlen, void *data) { @@ -606,9 +599,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) if (check_enc_key_size(conn, key_size)) return SMP_ENC_KEY_SIZE; - ret = smp_rand(smp->prnd); - if (ret) - return SMP_UNSPECIFIED; + get_random_bytes(smp->prnd, sizeof(smp->prnd)); smp->prsp[0] = SMP_CMD_PAIRING_RSP; memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); @@ -644,9 +635,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) if (check_enc_key_size(conn, key_size)) return SMP_ENC_KEY_SIZE; - ret = smp_rand(smp->prnd); - if (ret) - return SMP_UNSPECIFIED; + get_random_bytes(smp->prnd, sizeof(smp->prnd)); smp->prsp[0] = SMP_CMD_PAIRING_RSP; memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); From 201a5929c8c788f9ef53b010065c9ce70c9c06f0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 2 Dec 2013 10:49:04 +0200 Subject: [PATCH 19/19] Bluetooth: Remove dead code from SMP encryption function The AES cipher is used in ECB mode by SMP and therefore doesn't use an IV (crypto_blkcipher_ivsize returns 0) so the code trying to set the IV was never getting called. Simply remove this code to avoid anyone from thinking it actually makes some difference. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/smp.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3bcb765b6a92..e61e74a1aabb 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -53,8 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) { struct blkcipher_desc desc; struct scatterlist sg; - int err, iv_len; - unsigned char iv[128]; + int err; if (tfm == NULL) { BT_ERR("tfm %p", tfm); @@ -72,12 +71,6 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) sg_init_one(&sg, r, 16); - iv_len = crypto_blkcipher_ivsize(tfm); - if (iv_len) { - memset(&iv, 0xff, iv_len); - crypto_blkcipher_set_iv(tfm, iv, iv_len); - } - err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); if (err) BT_ERR("Encrypt data error %d", err);