Loading drivers/bluetooth/ath3k.c +154 −28 Original line number Diff line number Diff line /* * Copyright (c) 2008-2009 Atheros Communications Inc. * Copyright (c) 2014 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -33,6 +34,19 @@ #define VERSION "1.0" #define ATH3K_FIRMWARE "ath3k-1.fw" #define ROME2_1_USB_RAMPATCH_FILE "ar3k/rampatch_2.1.tlv" #define ROME2_1_USB_NVM_FILE "ar3k/nvm_tlv_usb_2.1.bin" #define ROME1_1_USB_RAMPATCH_FILE "ar3k/rampatch_1.1.img" #define ROME1_1_USB_NVM_FILE "ar3k/nvm_tlv_usb_1.1.bin" #define ROME2_1_USB_RAMPATCH_HEADER sizeof(struct rome2_1_version) #define ROME1_1_USB_RAMPATCH_HEADER sizeof(struct rome1_1_version) #define ROME1_1_USB_NVM_HEADER 0x04 #define ROME2_1_USB_NVM_HEADER 0x04 #define ROME2_1_USB_CHIP_VERSION 0x200 #define ROME1_1_USB_CHIP_VERSION 0x101 #define ATH3K_DNLOAD 0x01 #define ATH3K_GETSTATE 0x05 #define ATH3K_SET_NORMAL_MODE 0x07 Loading @@ -51,14 +65,42 @@ #define ATH3K_NAME_LEN 0xFF struct ath3k_version { __le32 rom_version; __le32 build_version; __le32 ram_version; __u8 ref_clock; __u8 reserved[7]; } __packed; static const struct usb_device_id ath3k_table[] = { unsigned int rom_version; unsigned int build_version; unsigned int ram_version; unsigned char ref_clock; unsigned char reserved[0x07]; }; struct __packed rome1_1_version { u8 type; u8 length[3]; u8 sign_ver; u8 sign_algo; u8 resv1[2]; u16 product_id; u16 build_ver; u16 patch_ver; u8 resv2[2]; u32 entry_addr; }; struct __packed rome2_1_version { u8 type; u8 length[3]; u32 total_len; u32 patch_len; u8 sign_ver; u8 sign_algo; u8 resv1[2]; u16 product_id; u16 build_ver; u16 patch_ver; u8 resv2[2]; u32 entry_addr; }; static struct usb_device_id ath3k_table[] = { /* Atheros AR3011 */ { USB_DEVICE(0x0CF3, 0x3000) }, Loading Loading @@ -284,8 +326,27 @@ static int ath3k_get_version(struct usb_device *udev, return ret; } int get_rome_version(struct usb_device *udev) { struct ath3k_version fw_version; int ret = 0; ret = ath3k_get_version(udev, &fw_version); if (ret < 0) { BT_ERR("Failed to get Rome Firmware version"); return ret; } if ((fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) || (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION)) ret = fw_version.rom_version; else ret = 0; return ret; } EXPORT_SYMBOL(get_rome_version); static int ath3k_load_fwfile(struct usb_device *udev, const struct firmware *firmware) const struct firmware *firmware, int header_h) { u8 *send_buf; int err, pipe, len, size, count, sent = 0; Loading @@ -299,7 +360,7 @@ static int ath3k_load_fwfile(struct usb_device *udev, return -ENOMEM; } size = min_t(uint, count, FW_HDR_SIZE); size = min_t(uint, count, header_h); memcpy(send_buf, firmware->data, size); pipe = usb_sndctrlpipe(udev, 0); Loading Loading @@ -377,8 +438,9 @@ static int ath3k_load_patch(struct usb_device *udev) unsigned char fw_state; char filename[ATH3K_NAME_LEN] = {0}; const struct firmware *firmware; struct ath3k_version fw_version; __u32 pt_rom_version, pt_build_version; struct ath3k_version fw_version, pt_version; struct rome2_1_version *rome2_1_version; struct rome1_1_version *rome1_1_version; int ret; ret = ath3k_get_state(udev, &fw_state); Loading @@ -397,29 +459,61 @@ static int ath3k_load_patch(struct usb_device *udev) BT_ERR("Can't get version to change to load ram patch err"); return ret; } if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) { BT_DBG("Chip Detected as ROME1.1"); snprintf(filename, ATH3K_NAME_LEN, ROME1_1_USB_RAMPATCH_FILE); } else if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) { BT_DBG("Chip Detected as ROME2.1"); snprintf(filename, ATH3K_NAME_LEN, ROME2_1_USB_RAMPATCH_FILE); } else { BT_DBG("Chip Detected as Ath3k"); snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", le32_to_cpu(fw_version.rom_version)); fw_version.rom_version); } ret = request_firmware(&firmware, filename, &udev->dev); if (ret < 0) { BT_ERR("Patch file not found %s", filename); return ret; } pt_rom_version = get_unaligned_le32(firmware->data + if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) { rome2_1_version = (struct rome2_1_version *) firmware->data; pt_version.rom_version = rome2_1_version->build_ver; pt_version.build_version = rome2_1_version->patch_ver; BT_DBG("pt_ver.rom2.1_ver : 0x%x", pt_version.rom_version); BT_DBG("pt_ver.build2.1_ver: 0x%x", pt_version.build_version); BT_DBG("fw_ver.rom2.1_ver: 0x%x", fw_version.rom_version); BT_DBG("fw_ver.build2.1_ver: 0x%x", fw_version.build_version); } else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) { rome1_1_version = (struct rome1_1_version *) firmware->data; pt_version.build_version = rome1_1_version->build_ver; pt_version.rom_version = rome1_1_version->patch_ver; BT_DBG("pt_ver.rom1.1_ver : 0x%x", pt_version.rom_version); BT_DBG("pt_ver.build1.1_ver: 0x%x", pt_version.build_version); BT_DBG("fw_ver.rom1.1_ver: 0x%x", fw_version.rom_version); BT_DBG("fw_ver.build1.1_ver: 0x%x", fw_version.build_version); } else { pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); pt_build_version = get_unaligned_le32(firmware->data + firmware->size - 4); if (pt_rom_version != le32_to_cpu(fw_version.rom_version) || pt_build_version <= le32_to_cpu(fw_version.build_version)) { pt_version.build_version = *(int *) (firmware->data + firmware->size - 4); } if ((pt_version.rom_version != fw_version.rom_version) || (pt_version.build_version <= fw_version.build_version)) { BT_ERR("Patch file version did not match with firmware"); release_firmware(firmware); return -EINVAL; } ret = ath3k_load_fwfile(udev, firmware); if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME2_1_USB_RAMPATCH_HEADER); else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME1_1_USB_RAMPATCH_HEADER); else ret = ath3k_load_fwfile(udev, firmware, FW_HDR_SIZE); release_firmware(firmware); return ret; Loading Loading @@ -461,8 +555,13 @@ static int ath3k_load_syscfg(struct usb_device *udev) break; } if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) snprintf(filename, ATH3K_NAME_LEN, ROME2_1_USB_NVM_FILE); else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) snprintf(filename, ATH3K_NAME_LEN, ROME1_1_USB_NVM_FILE); else snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", le32_to_cpu(fw_version.rom_version), clk_value, ".dfu"); fw_version.rom_version, clk_value, ".dfu"); ret = request_firmware(&firmware, filename, &udev->dev); if (ret < 0) { Loading @@ -470,12 +569,36 @@ static int ath3k_load_syscfg(struct usb_device *udev) return ret; } ret = ath3k_load_fwfile(udev, firmware); if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME2_1_USB_NVM_HEADER); else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME1_1_USB_NVM_HEADER); else ret = ath3k_load_fwfile(udev, firmware, FW_HDR_SIZE); release_firmware(firmware); return ret; } int rome_download(struct usb_device *udev) { int ret; ret = ath3k_load_patch(udev); if (ret < 0) { BT_ERR("Loading patch file failed"); return ret; } ret = ath3k_load_syscfg(udev); if (ret < 0) { BT_ERR("Loading sysconfig file failed"); return ret; } return ret; } EXPORT_SYMBOL(rome_download); static int ath3k_probe(struct usb_interface *intf, const struct usb_device_id *id) { Loading @@ -487,7 +610,10 @@ static int ath3k_probe(struct usb_interface *intf, if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; if (get_rome_version(udev)) { BT_INFO("Rome detected, fw dnld will be triggered from btusb"); return -ENODEV; } /* match device ID in ath3k blacklist table */ if (!id->driver_info) { const struct usb_device_id *match; Loading drivers/bluetooth/btusb.c +8 −4 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ * * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or Loading Loading @@ -1963,7 +1962,7 @@ static int btusb_probe(struct usb_interface *intf, struct usb_endpoint_descriptor *ep_desc; struct btusb_data *data; struct hci_dev *hdev; int i, err; int i, version, err; BT_DBG("intf %p id %p", intf, id); Loading @@ -1985,12 +1984,17 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_ATH3012) { struct usb_device *udev = interface_to_usbdev(intf); version = get_rome_version(udev); BT_INFO("Rome Version: 0x%x", version); /* Old firmware would otherwise let ath3k driver load * patch and sysconfig files */ if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) if (version) rome_download(udev); else if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) { BT_INFO("FW for ar3k is yet to be downloaded"); return -ENODEV; } } data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; Loading include/net/bluetooth/bluetooth.h +5 −0 Original line number Diff line number Diff line /* BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2000-2001 Qualcomm Incorporated Copyright (C) 2014 The Linux Foundation. All rights reserved. Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> Loading Loading @@ -28,6 +29,7 @@ #include <linux/poll.h> #include <net/sock.h> #include <linux/seq_file.h> #include <linux/usb.h> #ifndef AF_BLUETOOTH #define AF_BLUETOOTH 31 Loading Loading @@ -360,4 +362,7 @@ void sco_exit(void); void bt_sock_reclassify_lock(struct sock *sk, int proto); int get_rome_version(struct usb_device *udev); int rome_download(struct usb_device *udev); #endif /* __BLUETOOTH_H */ Loading
drivers/bluetooth/ath3k.c +154 −28 Original line number Diff line number Diff line /* * Copyright (c) 2008-2009 Atheros Communications Inc. * Copyright (c) 2014 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -33,6 +34,19 @@ #define VERSION "1.0" #define ATH3K_FIRMWARE "ath3k-1.fw" #define ROME2_1_USB_RAMPATCH_FILE "ar3k/rampatch_2.1.tlv" #define ROME2_1_USB_NVM_FILE "ar3k/nvm_tlv_usb_2.1.bin" #define ROME1_1_USB_RAMPATCH_FILE "ar3k/rampatch_1.1.img" #define ROME1_1_USB_NVM_FILE "ar3k/nvm_tlv_usb_1.1.bin" #define ROME2_1_USB_RAMPATCH_HEADER sizeof(struct rome2_1_version) #define ROME1_1_USB_RAMPATCH_HEADER sizeof(struct rome1_1_version) #define ROME1_1_USB_NVM_HEADER 0x04 #define ROME2_1_USB_NVM_HEADER 0x04 #define ROME2_1_USB_CHIP_VERSION 0x200 #define ROME1_1_USB_CHIP_VERSION 0x101 #define ATH3K_DNLOAD 0x01 #define ATH3K_GETSTATE 0x05 #define ATH3K_SET_NORMAL_MODE 0x07 Loading @@ -51,14 +65,42 @@ #define ATH3K_NAME_LEN 0xFF struct ath3k_version { __le32 rom_version; __le32 build_version; __le32 ram_version; __u8 ref_clock; __u8 reserved[7]; } __packed; static const struct usb_device_id ath3k_table[] = { unsigned int rom_version; unsigned int build_version; unsigned int ram_version; unsigned char ref_clock; unsigned char reserved[0x07]; }; struct __packed rome1_1_version { u8 type; u8 length[3]; u8 sign_ver; u8 sign_algo; u8 resv1[2]; u16 product_id; u16 build_ver; u16 patch_ver; u8 resv2[2]; u32 entry_addr; }; struct __packed rome2_1_version { u8 type; u8 length[3]; u32 total_len; u32 patch_len; u8 sign_ver; u8 sign_algo; u8 resv1[2]; u16 product_id; u16 build_ver; u16 patch_ver; u8 resv2[2]; u32 entry_addr; }; static struct usb_device_id ath3k_table[] = { /* Atheros AR3011 */ { USB_DEVICE(0x0CF3, 0x3000) }, Loading Loading @@ -284,8 +326,27 @@ static int ath3k_get_version(struct usb_device *udev, return ret; } int get_rome_version(struct usb_device *udev) { struct ath3k_version fw_version; int ret = 0; ret = ath3k_get_version(udev, &fw_version); if (ret < 0) { BT_ERR("Failed to get Rome Firmware version"); return ret; } if ((fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) || (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION)) ret = fw_version.rom_version; else ret = 0; return ret; } EXPORT_SYMBOL(get_rome_version); static int ath3k_load_fwfile(struct usb_device *udev, const struct firmware *firmware) const struct firmware *firmware, int header_h) { u8 *send_buf; int err, pipe, len, size, count, sent = 0; Loading @@ -299,7 +360,7 @@ static int ath3k_load_fwfile(struct usb_device *udev, return -ENOMEM; } size = min_t(uint, count, FW_HDR_SIZE); size = min_t(uint, count, header_h); memcpy(send_buf, firmware->data, size); pipe = usb_sndctrlpipe(udev, 0); Loading Loading @@ -377,8 +438,9 @@ static int ath3k_load_patch(struct usb_device *udev) unsigned char fw_state; char filename[ATH3K_NAME_LEN] = {0}; const struct firmware *firmware; struct ath3k_version fw_version; __u32 pt_rom_version, pt_build_version; struct ath3k_version fw_version, pt_version; struct rome2_1_version *rome2_1_version; struct rome1_1_version *rome1_1_version; int ret; ret = ath3k_get_state(udev, &fw_state); Loading @@ -397,29 +459,61 @@ static int ath3k_load_patch(struct usb_device *udev) BT_ERR("Can't get version to change to load ram patch err"); return ret; } if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) { BT_DBG("Chip Detected as ROME1.1"); snprintf(filename, ATH3K_NAME_LEN, ROME1_1_USB_RAMPATCH_FILE); } else if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) { BT_DBG("Chip Detected as ROME2.1"); snprintf(filename, ATH3K_NAME_LEN, ROME2_1_USB_RAMPATCH_FILE); } else { BT_DBG("Chip Detected as Ath3k"); snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", le32_to_cpu(fw_version.rom_version)); fw_version.rom_version); } ret = request_firmware(&firmware, filename, &udev->dev); if (ret < 0) { BT_ERR("Patch file not found %s", filename); return ret; } pt_rom_version = get_unaligned_le32(firmware->data + if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) { rome2_1_version = (struct rome2_1_version *) firmware->data; pt_version.rom_version = rome2_1_version->build_ver; pt_version.build_version = rome2_1_version->patch_ver; BT_DBG("pt_ver.rom2.1_ver : 0x%x", pt_version.rom_version); BT_DBG("pt_ver.build2.1_ver: 0x%x", pt_version.build_version); BT_DBG("fw_ver.rom2.1_ver: 0x%x", fw_version.rom_version); BT_DBG("fw_ver.build2.1_ver: 0x%x", fw_version.build_version); } else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) { rome1_1_version = (struct rome1_1_version *) firmware->data; pt_version.build_version = rome1_1_version->build_ver; pt_version.rom_version = rome1_1_version->patch_ver; BT_DBG("pt_ver.rom1.1_ver : 0x%x", pt_version.rom_version); BT_DBG("pt_ver.build1.1_ver: 0x%x", pt_version.build_version); BT_DBG("fw_ver.rom1.1_ver: 0x%x", fw_version.rom_version); BT_DBG("fw_ver.build1.1_ver: 0x%x", fw_version.build_version); } else { pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); pt_build_version = get_unaligned_le32(firmware->data + firmware->size - 4); if (pt_rom_version != le32_to_cpu(fw_version.rom_version) || pt_build_version <= le32_to_cpu(fw_version.build_version)) { pt_version.build_version = *(int *) (firmware->data + firmware->size - 4); } if ((pt_version.rom_version != fw_version.rom_version) || (pt_version.build_version <= fw_version.build_version)) { BT_ERR("Patch file version did not match with firmware"); release_firmware(firmware); return -EINVAL; } ret = ath3k_load_fwfile(udev, firmware); if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME2_1_USB_RAMPATCH_HEADER); else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME1_1_USB_RAMPATCH_HEADER); else ret = ath3k_load_fwfile(udev, firmware, FW_HDR_SIZE); release_firmware(firmware); return ret; Loading Loading @@ -461,8 +555,13 @@ static int ath3k_load_syscfg(struct usb_device *udev) break; } if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) snprintf(filename, ATH3K_NAME_LEN, ROME2_1_USB_NVM_FILE); else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) snprintf(filename, ATH3K_NAME_LEN, ROME1_1_USB_NVM_FILE); else snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", le32_to_cpu(fw_version.rom_version), clk_value, ".dfu"); fw_version.rom_version, clk_value, ".dfu"); ret = request_firmware(&firmware, filename, &udev->dev); if (ret < 0) { Loading @@ -470,12 +569,36 @@ static int ath3k_load_syscfg(struct usb_device *udev) return ret; } ret = ath3k_load_fwfile(udev, firmware); if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME2_1_USB_NVM_HEADER); else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) ret = ath3k_load_fwfile(udev, firmware, ROME1_1_USB_NVM_HEADER); else ret = ath3k_load_fwfile(udev, firmware, FW_HDR_SIZE); release_firmware(firmware); return ret; } int rome_download(struct usb_device *udev) { int ret; ret = ath3k_load_patch(udev); if (ret < 0) { BT_ERR("Loading patch file failed"); return ret; } ret = ath3k_load_syscfg(udev); if (ret < 0) { BT_ERR("Loading sysconfig file failed"); return ret; } return ret; } EXPORT_SYMBOL(rome_download); static int ath3k_probe(struct usb_interface *intf, const struct usb_device_id *id) { Loading @@ -487,7 +610,10 @@ static int ath3k_probe(struct usb_interface *intf, if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; if (get_rome_version(udev)) { BT_INFO("Rome detected, fw dnld will be triggered from btusb"); return -ENODEV; } /* match device ID in ath3k blacklist table */ if (!id->driver_info) { const struct usb_device_id *match; Loading
drivers/bluetooth/btusb.c +8 −4 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ * * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or Loading Loading @@ -1963,7 +1962,7 @@ static int btusb_probe(struct usb_interface *intf, struct usb_endpoint_descriptor *ep_desc; struct btusb_data *data; struct hci_dev *hdev; int i, err; int i, version, err; BT_DBG("intf %p id %p", intf, id); Loading @@ -1985,12 +1984,17 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_ATH3012) { struct usb_device *udev = interface_to_usbdev(intf); version = get_rome_version(udev); BT_INFO("Rome Version: 0x%x", version); /* Old firmware would otherwise let ath3k driver load * patch and sysconfig files */ if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) if (version) rome_download(udev); else if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) { BT_INFO("FW for ar3k is yet to be downloaded"); return -ENODEV; } } data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; Loading
include/net/bluetooth/bluetooth.h +5 −0 Original line number Diff line number Diff line /* BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2000-2001 Qualcomm Incorporated Copyright (C) 2014 The Linux Foundation. All rights reserved. Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> Loading Loading @@ -28,6 +29,7 @@ #include <linux/poll.h> #include <net/sock.h> #include <linux/seq_file.h> #include <linux/usb.h> #ifndef AF_BLUETOOTH #define AF_BLUETOOTH 31 Loading Loading @@ -360,4 +362,7 @@ void sco_exit(void); void bt_sock_reclassify_lock(struct sock *sk, int proto); int get_rome_version(struct usb_device *udev); int rome_download(struct usb_device *udev); #endif /* __BLUETOOTH_H */