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$
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
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
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
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
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
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
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
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