]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/ath3kfw/ath3k_hw.c
Import libxo-0.7.2; add xo_options.7.
[FreeBSD/FreeBSD.git] / usr.sbin / bluetooth / ath3kfw / ath3k_hw.c
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 }