1 /*-
2 * Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 *
29 * $FreeBSD: stable/12/usr.sbin/bluetooth/ath3kfw/ath3k_hw.c 301537 2016-06-07 04:22:18Z adrian $
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <err.h>
38 #include <fcntl.h>
39 #include <sys/endian.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 #include <libusb.h>
44
45 #include "ath3k_fw.h"
46 #include "ath3k_hw.h"
47 #include "ath3k_dbg.h"
48
49 #define XMIN(x, y) ((x) < (y) ? (x) : (y))
50
51 int
ath3k_load_fwfile(struct libusb_device_handle * hdl,const struct ath3k_firmware * fw)52 ath3k_load_fwfile(struct libusb_device_handle *hdl,
53 const struct ath3k_firmware *fw)
54 {
55 int size, count, sent = 0;
56 int ret, r;
57
58 count = fw->len;
59
60 size = XMIN(count, FW_HDR_SIZE);
61
62 ath3k_debug("%s: file=%s, size=%d\n",
63 __func__, fw->fwname, count);
64
65 /*
66 * Flip the device over to configuration mode.
67 */
68 ret = libusb_control_transfer(hdl,
69 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
70 ATH3K_DNLOAD,
71 0,
72 0,
73 fw->buf + sent,
74 size,
75 1000); /* XXX timeout */
76
77 if (ret != size) {
78 fprintf(stderr, "Can't switch to config mode; ret=%d\n",
79 ret);
80 return (-1);
81 }
82
83 sent += size;
84 count -= size;
85
86 /* Load in the rest of the data */
87 while (count) {
88 size = XMIN(count, BULK_SIZE);
89 ath3k_debug("%s: transferring %d bytes, offset %d\n",
90 __func__,
91 sent,
92 size);
93
94 ret = libusb_bulk_transfer(hdl,
95 0x2,
96 fw->buf + sent,
97 size,
98 &r,
99 1000);
100
101 if (ret < 0 || r != size) {
102 fprintf(stderr, "Can't load firmware: err=%s, size=%d\n",
103 libusb_strerror(ret),
104 size);
105 return (-1);
106 }
107 sent += size;
108 count -= size;
109 }
110 return (0);
111 }
112
113 int
ath3k_get_state(struct libusb_device_handle * hdl,unsigned char * state)114 ath3k_get_state(struct libusb_device_handle *hdl, unsigned char *state)
115 {
116 int ret;
117
118 ret = libusb_control_transfer(hdl,
119 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
120 ATH3K_GETSTATE,
121 0,
122 0,
123 state,
124 1,
125 1000); /* XXX timeout */
126
127 if (ret < 0) {
128 fprintf(stderr,
129 "%s: libusb_control_transfer() failed: code=%d\n",
130 __func__,
131 ret);
132 return (0);
133 }
134
135 return (ret == 1);
136 }
137
138 int
ath3k_get_version(struct libusb_device_handle * hdl,struct ath3k_version * version)139 ath3k_get_version(struct libusb_device_handle *hdl,
140 struct ath3k_version *version)
141 {
142 int ret;
143
144 ret = libusb_control_transfer(hdl,
145 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
146 ATH3K_GETVERSION,
147 0,
148 0,
149 (unsigned char *) version,
150 sizeof(struct ath3k_version),
151 1000); /* XXX timeout */
152
153 if (ret < 0) {
154 fprintf(stderr,
155 "%s: libusb_control_transfer() failed: code=%d\n",
156 __func__,
157 ret);
158 return (0);
159 }
160
161 /* XXX endian fix! */
162
163 return (ret == sizeof(struct ath3k_version));
164 }
165
166 int
ath3k_load_patch(libusb_device_handle * hdl,const char * fw_path)167 ath3k_load_patch(libusb_device_handle *hdl, const char *fw_path)
168 {
169 int ret;
170 unsigned char fw_state;
171 struct ath3k_version fw_ver, pt_ver;
172 char fwname[FILENAME_MAX];
173 struct ath3k_firmware fw;
174 uint32_t tmp;
175
176 ret = ath3k_get_state(hdl, &fw_state);
177 if (ret < 0) {
178 ath3k_err("%s: Can't get state\n", __func__);
179 return (ret);
180 }
181
182 if (fw_state & ATH3K_PATCH_UPDATE) {
183 ath3k_info("%s: Patch already downloaded\n",
184 __func__);
185 return (0);
186 }
187
188 ret = ath3k_get_version(hdl, &fw_ver);
189 if (ret < 0) {
190 ath3k_debug("%s: Can't get version\n", __func__);
191 return (ret);
192 }
193
194 /* XXX path info? */
195 snprintf(fwname, FILENAME_MAX, "%s/ar3k/AthrBT_0x%08x.dfu",
196 fw_path,
197 fw_ver.rom_version);
198
199 /* Read in the firmware */
200 if (ath3k_fw_read(&fw, fwname) <= 0) {
201 ath3k_debug("%s: ath3k_fw_read() failed\n",
202 __func__);
203 return (-1);
204 }
205
206 /*
207 * Extract the ROM/build version from the patch file.
208 */
209 memcpy(&tmp, fw.buf + fw.len - 8, sizeof(tmp));
210 pt_ver.rom_version = le32toh(tmp);
211 memcpy(&tmp, fw.buf + fw.len - 4, sizeof(tmp));
212 pt_ver.build_version = le32toh(tmp);
213
214 ath3k_info("%s: file %s: rom_ver=%d, build_ver=%d\n",
215 __func__,
216 fwname,
217 (int) pt_ver.rom_version,
218 (int) pt_ver.build_version);
219
220 /* Check the ROM/build version against the firmware */
221 if ((pt_ver.rom_version != fw_ver.rom_version) ||
222 (pt_ver.build_version <= fw_ver.build_version)) {
223 ath3k_debug("Patch file version mismatch!\n");
224 ath3k_fw_free(&fw);
225 return (-1);
226 }
227
228 /* Load in the firmware */
229 ret = ath3k_load_fwfile(hdl, &fw);
230
231 /* free it */
232 ath3k_fw_free(&fw);
233
234 return (ret);
235 }
236
237 int
ath3k_load_syscfg(libusb_device_handle * hdl,const char * fw_path)238 ath3k_load_syscfg(libusb_device_handle *hdl, const char *fw_path)
239 {
240 unsigned char fw_state;
241 char filename[FILENAME_MAX];
242 struct ath3k_firmware fw;
243 struct ath3k_version fw_ver;
244 int clk_value, ret;
245
246 ret = ath3k_get_state(hdl, &fw_state);
247 if (ret < 0) {
248 ath3k_err("Can't get state to change to load configuration err");
249 return (-EBUSY);
250 }
251
252 ret = ath3k_get_version(hdl, &fw_ver);
253 if (ret < 0) {
254 ath3k_err("Can't get version to change to load ram patch err");
255 return (ret);
256 }
257
258 switch (fw_ver.ref_clock) {
259 case ATH3K_XTAL_FREQ_26M:
260 clk_value = 26;
261 break;
262 case ATH3K_XTAL_FREQ_40M:
263 clk_value = 40;
264 break;
265 case ATH3K_XTAL_FREQ_19P2:
266 clk_value = 19;
267 break;
268 default:
269 clk_value = 0;
270 break;
271 }
272
273 snprintf(filename, FILENAME_MAX, "%s/ar3k/ramps_0x%08x_%d%s",
274 fw_path,
275 fw_ver.rom_version,
276 clk_value,
277 ".dfu");
278
279 ath3k_info("%s: syscfg file = %s\n",
280 __func__,
281 filename);
282
283 /* Read in the firmware */
284 if (ath3k_fw_read(&fw, filename) <= 0) {
285 ath3k_err("%s: ath3k_fw_read() failed\n",
286 __func__);
287 return (-1);
288 }
289
290 ret = ath3k_load_fwfile(hdl, &fw);
291
292 ath3k_fw_free(&fw);
293 return (ret);
294 }
295
296 int
ath3k_set_normal_mode(libusb_device_handle * hdl)297 ath3k_set_normal_mode(libusb_device_handle *hdl)
298 {
299 int ret;
300 unsigned char fw_state;
301
302 ret = ath3k_get_state(hdl, &fw_state);
303 if (ret < 0) {
304 ath3k_err("%s: can't get state\n", __func__);
305 return (ret);
306 }
307
308 /*
309 * This isn't a fatal error - the device may have detached
310 * already.
311 */
312 if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
313 ath3k_debug("%s: firmware is already in normal mode\n",
314 __func__);
315 return (0);
316 }
317
318 ret = libusb_control_transfer(hdl,
319 LIBUSB_REQUEST_TYPE_VENDOR, /* XXX out direction? */
320 ATH3K_SET_NORMAL_MODE,
321 0,
322 0,
323 NULL,
324 0,
325 1000); /* XXX timeout */
326
327 if (ret < 0) {
328 ath3k_err("%s: libusb_control_transfer() failed: code=%d\n",
329 __func__,
330 ret);
331 return (0);
332 }
333
334 return (ret == 0);
335 }
336
337 int
ath3k_switch_pid(libusb_device_handle * hdl)338 ath3k_switch_pid(libusb_device_handle *hdl)
339 {
340 int ret;
341 ret = libusb_control_transfer(hdl,
342 LIBUSB_REQUEST_TYPE_VENDOR, /* XXX set an out flag? */
343 USB_REG_SWITCH_VID_PID,
344 0,
345 0,
346 NULL,
347 0,
348 1000); /* XXX timeout */
349
350 if (ret < 0) {
351 ath3k_debug("%s: libusb_control_transfer() failed: code=%d\n",
352 __func__,
353 ret);
354 return (0);
355 }
356
357 return (ret == 0);
358 }
359