diff options
| -rw-r--r-- | drivers/bluetooth/btusb.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3d684d20b584..7a7e5f8ecadc 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/usb.h> | 25 | #include <linux/usb.h> |
| 26 | #include <linux/firmware.h> | ||
| 26 | 27 | ||
| 27 | #include <net/bluetooth/bluetooth.h> | 28 | #include <net/bluetooth/bluetooth.h> |
| 28 | #include <net/bluetooth/hci_core.h> | 29 | #include <net/bluetooth/hci_core.h> |
| @@ -47,6 +48,7 @@ static struct usb_driver btusb_driver; | |||
| 47 | #define BTUSB_BROKEN_ISOC 0x20 | 48 | #define BTUSB_BROKEN_ISOC 0x20 |
| 48 | #define BTUSB_WRONG_SCO_MTU 0x40 | 49 | #define BTUSB_WRONG_SCO_MTU 0x40 |
| 49 | #define BTUSB_ATH3012 0x80 | 50 | #define BTUSB_ATH3012 0x80 |
| 51 | #define BTUSB_INTEL 0x100 | ||
| 50 | 52 | ||
| 51 | static struct usb_device_id btusb_table[] = { | 53 | static struct usb_device_id btusb_table[] = { |
| 52 | /* Generic Bluetooth USB device */ | 54 | /* Generic Bluetooth USB device */ |
| @@ -207,6 +209,9 @@ static struct usb_device_id blacklist_table[] = { | |||
| 207 | /* Frontline ComProbe Bluetooth Sniffer */ | 209 | /* Frontline ComProbe Bluetooth Sniffer */ |
| 208 | { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER }, | 210 | { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER }, |
| 209 | 211 | ||
| 212 | /* Intel Bluetooth device */ | ||
| 213 | { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, | ||
| 214 | |||
| 210 | { } /* Terminating entry */ | 215 | { } /* Terminating entry */ |
| 211 | }; | 216 | }; |
| 212 | 217 | ||
| @@ -943,6 +948,375 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev) | |||
| 943 | return 0; | 948 | return 0; |
| 944 | } | 949 | } |
| 945 | 950 | ||
| 951 | struct intel_version { | ||
| 952 | u8 status; | ||
| 953 | u8 hw_platform; | ||
| 954 | u8 hw_variant; | ||
| 955 | u8 hw_revision; | ||
| 956 | u8 fw_variant; | ||
| 957 | u8 fw_revision; | ||
| 958 | u8 fw_build_num; | ||
| 959 | u8 fw_build_ww; | ||
| 960 | u8 fw_build_yy; | ||
| 961 | u8 fw_patch_num; | ||
| 962 | } __packed; | ||
| 963 | |||
| 964 | static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, | ||
| 965 | struct intel_version *ver) | ||
| 966 | { | ||
| 967 | const struct firmware *fw; | ||
| 968 | char fwname[64]; | ||
| 969 | int ret; | ||
| 970 | |||
| 971 | snprintf(fwname, sizeof(fwname), | ||
| 972 | "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq", | ||
| 973 | ver->hw_platform, ver->hw_variant, ver->hw_revision, | ||
| 974 | ver->fw_variant, ver->fw_revision, ver->fw_build_num, | ||
| 975 | ver->fw_build_ww, ver->fw_build_yy); | ||
| 976 | |||
| 977 | ret = request_firmware(&fw, fwname, &hdev->dev); | ||
| 978 | if (ret < 0) { | ||
| 979 | if (ret == -EINVAL) { | ||
| 980 | BT_ERR("%s Intel firmware file request failed (%d)", | ||
| 981 | hdev->name, ret); | ||
| 982 | return NULL; | ||
| 983 | } | ||
| 984 | |||
| 985 | BT_ERR("%s failed to open Intel firmware file: %s(%d)", | ||
| 986 | hdev->name, fwname, ret); | ||
| 987 | |||
| 988 | /* If the correct firmware patch file is not found, use the | ||
| 989 | * default firmware patch file instead | ||
| 990 | */ | ||
| 991 | snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", | ||
| 992 | ver->hw_platform, ver->hw_variant); | ||
| 993 | if (request_firmware(&fw, fwname, &hdev->dev) < 0) { | ||
| 994 | BT_ERR("%s failed to open default Intel fw file: %s", | ||
| 995 | hdev->name, fwname); | ||
| 996 | return NULL; | ||
| 997 | } | ||
| 998 | } | ||
| 999 | |||
| 1000 | BT_INFO("%s: Intel Bluetooth firmware file: %s", hdev->name, fwname); | ||
| 1001 | |||
| 1002 | return fw; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static int btusb_setup_intel_patching(struct hci_dev *hdev, | ||
| 1006 | const struct firmware *fw, | ||
| 1007 | const u8 **fw_ptr, int *disable_patch) | ||
| 1008 | { | ||
| 1009 | struct sk_buff *skb; | ||
| 1010 | struct hci_command_hdr *cmd; | ||
| 1011 | const u8 *cmd_param; | ||
| 1012 | struct hci_event_hdr *evt = NULL; | ||
| 1013 | const u8 *evt_param = NULL; | ||
| 1014 | int remain = fw->size - (*fw_ptr - fw->data); | ||
| 1015 | |||
| 1016 | /* The first byte indicates the types of the patch command or event. | ||
| 1017 | * 0x01 means HCI command and 0x02 is HCI event. If the first bytes | ||
| 1018 | * in the current firmware buffer doesn't start with 0x01 or | ||
| 1019 | * the size of remain buffer is smaller than HCI command header, | ||
| 1020 | * the firmware file is corrupted and it should stop the patching | ||
| 1021 | * process. | ||
| 1022 | */ | ||
| 1023 | if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { | ||
| 1024 | BT_ERR("%s Intel fw corrupted: invalid cmd read", hdev->name); | ||
| 1025 | return -EINVAL; | ||
| 1026 | } | ||
| 1027 | (*fw_ptr)++; | ||
| 1028 | remain--; | ||
| 1029 | |||
| 1030 | cmd = (struct hci_command_hdr *)(*fw_ptr); | ||
| 1031 | *fw_ptr += sizeof(*cmd); | ||
| 1032 | remain -= sizeof(*cmd); | ||
| 1033 | |||
| 1034 | /* Ensure that the remain firmware data is long enough than the length | ||
| 1035 | * of command parameter. If not, the firmware file is corrupted. | ||
| 1036 | */ | ||
| 1037 | if (remain < cmd->plen) { | ||
| 1038 | BT_ERR("%s Intel fw corrupted: invalid cmd len", hdev->name); | ||
| 1039 | return -EFAULT; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /* If there is a command that loads a patch in the firmware | ||
| 1043 | * file, then enable the patch upon success, otherwise just | ||
| 1044 | * disable the manufacturer mode, for example patch activation | ||
| 1045 | * is not required when the default firmware patch file is used | ||
| 1046 | * because there are no patch data to load. | ||
| 1047 | */ | ||
| 1048 | if (*disable_patch && le16_to_cpu(cmd->opcode) == 0xfc8e) | ||
| 1049 | *disable_patch = 0; | ||
| 1050 | |||
| 1051 | cmd_param = *fw_ptr; | ||
| 1052 | *fw_ptr += cmd->plen; | ||
| 1053 | remain -= cmd->plen; | ||
| 1054 | |||
| 1055 | /* This reads the expected events when the above command is sent to the | ||
| 1056 | * device. Some vendor commands expects more than one events, for | ||
| 1057 | * example command status event followed by vendor specific event. | ||
| 1058 | * For this case, it only keeps the last expected event. so the command | ||
| 1059 | * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of | ||
| 1060 | * last expected event. | ||
| 1061 | */ | ||
| 1062 | while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) { | ||
| 1063 | (*fw_ptr)++; | ||
| 1064 | remain--; | ||
| 1065 | |||
| 1066 | evt = (struct hci_event_hdr *)(*fw_ptr); | ||
| 1067 | *fw_ptr += sizeof(*evt); | ||
| 1068 | remain -= sizeof(*evt); | ||
| 1069 | |||
| 1070 | if (remain < evt->plen) { | ||
| 1071 | BT_ERR("%s Intel fw corrupted: invalid evt len", | ||
| 1072 | hdev->name); | ||
| 1073 | return -EFAULT; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | evt_param = *fw_ptr; | ||
| 1077 | *fw_ptr += evt->plen; | ||
| 1078 | remain -= evt->plen; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | /* Every HCI commands in the firmware file has its correspond event. | ||
| 1082 | * If event is not found or remain is smaller than zero, the firmware | ||
| 1083 | * file is corrupted. | ||
| 1084 | */ | ||
| 1085 | if (!evt || !evt_param || remain < 0) { | ||
| 1086 | BT_ERR("%s Intel fw corrupted: invalid evt read", hdev->name); | ||
| 1087 | return -EFAULT; | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, | ||
| 1091 | cmd_param, evt->evt, HCI_INIT_TIMEOUT); | ||
| 1092 | if (IS_ERR(skb)) { | ||
| 1093 | BT_ERR("%s sending Intel patch command (0x%4.4x) failed (%ld)", | ||
| 1094 | hdev->name, cmd->opcode, PTR_ERR(skb)); | ||
| 1095 | return -PTR_ERR(skb); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | /* It ensures that the returned event matches the event data read from | ||
| 1099 | * the firmware file. At fist, it checks the length and then | ||
| 1100 | * the contents of the event. | ||
| 1101 | */ | ||
| 1102 | if (skb->len != evt->plen) { | ||
| 1103 | BT_ERR("%s mismatch event length (opcode 0x%4.4x)", hdev->name, | ||
| 1104 | le16_to_cpu(cmd->opcode)); | ||
| 1105 | kfree_skb(skb); | ||
| 1106 | return -EFAULT; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | if (memcmp(skb->data, evt_param, evt->plen)) { | ||
| 1110 | BT_ERR("%s mismatch event parameter (opcode 0x%4.4x)", | ||
| 1111 | hdev->name, le16_to_cpu(cmd->opcode)); | ||
