]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/ath3kfw/ath3k_hw.c
zfs: merge openzfs/zfs@a382e2119
[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
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 }