]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/bluetooth/btintel.c
Merge tag 'dm-4.3-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
[karo-tx-linux.git] / drivers / bluetooth / btintel.c
1 /*
2  *
3  *  Bluetooth support for Intel devices
4  *
5  *  Copyright (C) 2015  Intel Corporation
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <linux/module.h>
25
26 #include <net/bluetooth/bluetooth.h>
27 #include <net/bluetooth/hci_core.h>
28
29 #include "btintel.h"
30
31 #define VERSION "0.1"
32
33 #define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
34
35 int btintel_check_bdaddr(struct hci_dev *hdev)
36 {
37         struct hci_rp_read_bd_addr *bda;
38         struct sk_buff *skb;
39
40         skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
41                              HCI_INIT_TIMEOUT);
42         if (IS_ERR(skb)) {
43                 int err = PTR_ERR(skb);
44                 BT_ERR("%s: Reading Intel device address failed (%d)",
45                        hdev->name, err);
46                 return err;
47         }
48
49         if (skb->len != sizeof(*bda)) {
50                 BT_ERR("%s: Intel device address length mismatch", hdev->name);
51                 kfree_skb(skb);
52                 return -EIO;
53         }
54
55         bda = (struct hci_rp_read_bd_addr *)skb->data;
56
57         /* For some Intel based controllers, the default Bluetooth device
58          * address 00:03:19:9E:8B:00 can be found. These controllers are
59          * fully operational, but have the danger of duplicate addresses
60          * and that in turn can cause problems with Bluetooth operation.
61          */
62         if (!bacmp(&bda->bdaddr, BDADDR_INTEL)) {
63                 BT_ERR("%s: Found Intel default device address (%pMR)",
64                        hdev->name, &bda->bdaddr);
65                 set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
66         }
67
68         kfree_skb(skb);
69
70         return 0;
71 }
72 EXPORT_SYMBOL_GPL(btintel_check_bdaddr);
73
74 int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
75 {
76         struct sk_buff *skb;
77         int err;
78
79         skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
80         if (IS_ERR(skb)) {
81                 err = PTR_ERR(skb);
82                 BT_ERR("%s: Changing Intel device address failed (%d)",
83                        hdev->name, err);
84                 return err;
85         }
86         kfree_skb(skb);
87
88         return 0;
89 }
90 EXPORT_SYMBOL_GPL(btintel_set_bdaddr);
91
92 void btintel_hw_error(struct hci_dev *hdev, u8 code)
93 {
94         struct sk_buff *skb;
95         u8 type = 0x00;
96
97         BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code);
98
99         skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
100         if (IS_ERR(skb)) {
101                 BT_ERR("%s: Reset after hardware error failed (%ld)",
102                        hdev->name, PTR_ERR(skb));
103                 return;
104         }
105         kfree_skb(skb);
106
107         skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT);
108         if (IS_ERR(skb)) {
109                 BT_ERR("%s: Retrieving Intel exception info failed (%ld)",
110                        hdev->name, PTR_ERR(skb));
111                 return;
112         }
113
114         if (skb->len != 13) {
115                 BT_ERR("%s: Exception info size mismatch", hdev->name);
116                 kfree_skb(skb);
117                 return;
118         }
119
120         BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1));
121
122         kfree_skb(skb);
123 }
124 EXPORT_SYMBOL_GPL(btintel_hw_error);
125
126 void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
127 {
128         const char *variant;
129
130         switch (ver->fw_variant) {
131         case 0x06:
132                 variant = "Bootloader";
133                 break;
134         case 0x23:
135                 variant = "Firmware";
136                 break;
137         default:
138                 return;
139         }
140
141         BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name,
142                 variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
143                 ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy);
144 }
145 EXPORT_SYMBOL_GPL(btintel_version_info);
146
147 int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
148                         const void *param)
149 {
150         while (plen > 0) {
151                 struct sk_buff *skb;
152                 u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen;
153
154                 cmd_param[0] = fragment_type;
155                 memcpy(cmd_param + 1, param, fragment_len);
156
157                 skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1,
158                                      cmd_param, HCI_INIT_TIMEOUT);
159                 if (IS_ERR(skb))
160                         return PTR_ERR(skb);
161
162                 kfree_skb(skb);
163
164                 plen -= fragment_len;
165                 param += fragment_len;
166         }
167
168         return 0;
169 }
170 EXPORT_SYMBOL_GPL(btintel_secure_send);
171
172 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
173 MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
174 MODULE_VERSION(VERSION);
175 MODULE_LICENSE("GPL");
176 MODULE_FIRMWARE("intel/ibt-11-5.sfi");
177 MODULE_FIRMWARE("intel/ibt-11-5.ddc");