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
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <err.h>
36 #include <fcntl.h>
37 #include <sys/endian.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40
41 #include <libusb.h>
42
43 #include "ath3k_fw.h"
44 #include "ath3k_hw.h"
45 #include "ath3k_dbg.h"
46
47 #define XMIN(x, y) ((x) < (y) ? (x) : (y))
48
49 int
ath3k_load_fwfile(struct libusb_device_handle * hdl,const struct ath3k_firmware * fw)50 ath3k_load_fwfile(struct libusb_device_handle *hdl,
51 const struct ath3k_firmware *fw)
52 {
53 int size, count, sent = 0;
54 int ret, r;
55
56 count = fw->len;
57
58 size = XMIN(count, FW_HDR_SIZE);
59
60 ath3k_debug("%s: file=%s, size=%d\n",
61 __func__, fw->fwname, count);
62
63 /*
64 * Flip the device over to configuration mode.
65 */
66 ret = libusb_control_transfer(hdl,
67 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
68 ATH3K_DNLOAD,
69 0,
70 0,
71 fw->buf + sent,
72 size,
73 1000); /* XXX timeout */
74
75 if (ret != size) {
76 fprintf(stderr, "Can't switch to config mode; ret=%d\n",
77 ret);
78 return (-1);
79 }
80
81 sent += size;
82 count -= size;
83
84 /* Load in the rest of the data */
85 while (count) {
86 size = XMIN(count, BULK_SIZE);
87 ath3k_debug("%s: transferring %d bytes, offset %d\n",
88 __func__,
89 sent,
90 size);
91
92 ret = libusb_bulk_transfer(hdl,
93 0x2,
94 fw->buf + sent,
95 size,
96 &r,
97 1000);
98
99 if (ret < 0 || r != size) {
100 fprintf(stderr, "Can't load firmware: err=%s, size=%d\n",
101 libusb_strerror(ret),
102 size);
103 return (-1);
104 }
105 sent += size;
106 count -= size;
107 }
108 return (0);
109 }
110
111 int
ath3k_get_state(struct libusb_device_handle * hdl,unsigned char * state)112 ath3k_get_state(struct libusb_device_handle *hdl, unsigned char *state)
113 {
114 int ret;
115
116 ret = libusb_control_transfer(hdl,
117 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
118 ATH3K_GETSTATE,
119 0,
120 0,
121 state,
122 1,
123 1000); /* XXX timeout */
124
125 if (ret < 0) {
126 fprintf(stderr,
127 "%s: libusb_control_transfer() failed: code=%d\n",
128 __func__,
129 ret);
130 return (0);
131 }
132
133 return (ret == 1);
134 }
135
136 int
ath3k_get_version(struct libusb_device_handle * hdl,struct ath3k_version * version)137 ath3k_get_version(struct libusb_device_handle *hdl,
138 struct ath3k_version *version)
139 {
140 int ret;
141
142 ret = libusb_control_transfer(hdl,
143 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
144 ATH3K_GETVERSION,
145 0,
146 0,
147 (unsigned char *) version,
148 sizeof(struct ath3k_version),
149 1000); /* XXX timeout */
150
151 if (ret < 0) {
152 fprintf(stderr,
153 "%s: libusb_control_transfer() failed: code=%d\n",
154 __func__,
155 ret);
156 return (0);
157 }
158
159 /* XXX endian fix! */
160
161 return (ret == sizeof(struct ath3k_version));
162 }
163
164 int
ath3k_load_patch(libusb_device_handle * hdl,const char * fw_path)165 ath3k_load_patch(libusb_device_handle *hdl, const char *fw_path)
166 {
167 int ret;
168 unsigned char fw_state;
169 struct ath3k_version fw_ver, pt_ver;
170 char fwname[FILENAME_MAX];
171 struct ath3k_firmware fw;
172 uint32_t tmp;
173
174 ret = ath3k_get_state(hdl, &fw_state);
175 if (ret < 0) {
176 ath3k_err("%s: Can't get state\n", __func__);
177 return (ret);
178 }
179
180 if (fw_state & ATH3K_PATCH_UPDATE) {
181 ath3k_info("%s: Patch already downloaded\n",
182 __func__);
183 return (0);
184 }
185
186 ret = ath3k_get_version(hdl, &fw_ver);
187 if (ret < 0) {
188 ath3k_debug("%s: Can't get version\n", __func__);
189 return (ret);
190 }
191
192 /* XXX path info? */
193 snprintf(fwname, FILENAME_MAX, "%s/ar3k/AthrBT_0x%08x.dfu",
194 fw_path,
195 fw_ver.rom_version);
196
197 /* Read in the firmware */
198 if (ath3k_fw_read(&fw, fwname) <= 0) {
199 ath3k_debug("%s: ath3k_fw_read() failed\n",
200 __func__);
201 return (-1);
202 }
203
204 /*
205 * Extract the ROM/build version from the patch file.
206 */
207 memcpy(&tmp, fw.buf + fw.len - 8, sizeof(tmp));
208 pt_ver.rom_version = le32toh(tmp);
209 memcpy(&tmp, fw.buf + fw.len - 4, sizeof(tmp));
210 pt_ver.build_version = le32toh(tmp);
211
212 ath3k_info("%s: file %s: rom_ver=%d, build_ver=%d\n",
213 __func__,
214 fwname,
215 (int) pt_ver.rom_version,
216 (int) pt_ver.build_version);
217
218 /* Check the ROM/build version against the firmware */
219 if ((pt_ver.rom_version != fw_ver.rom_version) ||
220 (pt_ver.build_version <= fw_ver.build_version)) {
221 ath3k_debug("Patch file version mismatch!\n");
222 ath3k_fw_free(&fw);
223 return (-1);
224 }
225
226 /* Load in the firmware */
227 ret = ath3k_load_fwfile(hdl, &fw);
228
229 /* free it */
230 ath3k_fw_free(&fw);
231
232 return (ret);
233 }
234
235 int
ath3k_load_syscfg(libusb_device_handle * hdl,const char * fw_path)236 ath3k_load_syscfg(libusb_device_handle *hdl, const char *fw_path)
237 {
238 unsigned char fw_state;
239 char filename[FILENAME_MAX];
240 struct ath3k_firmware fw;
241 struct ath3k_version fw_ver;
242 int clk_value, ret;
243
244 ret = ath3k_get_state(hdl, &fw_state);
245 if (ret < 0) {
246 ath3k_err("Can't get state to change to load configuration err");
247 return (-EBUSY);
248 }
249
250 ret = ath3k_get_version(hdl, &fw_ver);
251 if (ret < 0) {
252 ath3k_err("Can't get version to change to load ram patch err");
253 return (ret);
254 }
255
256 switch (fw_ver.ref_clock) {
257 case ATH3K_XTAL_FREQ_26M:
258 clk_value = 26;
259 break;
260 case ATH3K_XTAL_FREQ_40M:
261 clk_value = 40;
262 break;
263 case ATH3K_XTAL_FREQ_19P2:
264 clk_value = 19;
265 break;
266 default:
267 clk_value = 0;
268 break;
269 }
270
271 snprintf(filename, FILENAME_MAX, "%s/ar3k/ramps_0x%08x_%d%s",
272 fw_path,
273 fw_ver.rom_version,
274 clk_value,
275 ".dfu");
276
277 ath3k_info("%s: syscfg file = %s\n",
278 __func__,
279 filename);
280
281 /* Read in the firmware */
282 if (ath3k_fw_read(&fw, filename) <= 0) {
283 ath3k_err("%s: ath3k_fw_read() failed\n",
284 __func__);
285 return (-1);
286 }
287
288 ret = ath3k_load_fwfile(hdl, &fw);
289
290 ath3k_fw_free(&fw);
291 return (ret);
292 }
293
294 int
ath3k_set_normal_mode(libusb_device_handle * hdl)295 ath3k_set_normal_mode(libusb_device_handle *hdl)
296 {
297 int ret;
298 unsigned char fw_state;
299
300 ret = ath3k_get_state(hdl, &fw_state);
301 if (ret < 0) {
302 ath3k_err("%s: can't get state\n", __func__);
303 return (ret);
304 }
305
306 /*
307 * This isn't a fatal error - the device may have detached
308 * already.
309 */
310 if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
311 ath3k_debug("%s: firmware is already in normal mode\n",
312 __func__);
313 return (0);
314 }
315
316 ret = libusb_control_transfer(hdl,
317 LIBUSB_REQUEST_TYPE_VENDOR, /* XXX out direction? */
318 ATH3K_SET_NORMAL_MODE,
319 0,
320 0,
321 NULL,
322 0,
323 1000); /* XXX timeout */
324
325 if (ret < 0) {
326 ath3k_err("%s: libusb_control_transfer() failed: code=%d\n",
327 __func__,
328 ret);
329 return (0);
330 }
331
332 return (ret == 0);
333 }
334
335 int
ath3k_switch_pid(libusb_device_handle * hdl)336 ath3k_switch_pid(libusb_device_handle *hdl)
337 {
338 int ret;
339 ret = libusb_control_transfer(hdl,
340 LIBUSB_REQUEST_TYPE_VENDOR, /* XXX set an out flag? */
341 USB_REG_SWITCH_VID_PID,
342 0,
343 0,
344 NULL,
345 0,
346 1000); /* XXX timeout */
347
348 if (ret < 0) {
349 ath3k_debug("%s: libusb_control_transfer() failed: code=%d\n",
350 __func__,
351 ret);
352 return (0);
353 }
354
355 return (ret == 0);
356 }
357