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
49int
50ath3k_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
111int
112ath3k_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
136int
137ath3k_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
164int
165ath3k_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
235int
236ath3k_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
294int
295ath3k_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
335int
336ath3k_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