xref: /freebsd/usr.sbin/bluetooth/ath3kfw/ath3k_hw.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
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
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
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
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
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
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
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
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