1*aebdb1e2SAdrian Chadd /*-
2*aebdb1e2SAdrian Chadd * Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org>
3*aebdb1e2SAdrian Chadd * All rights reserved.
4*aebdb1e2SAdrian Chadd *
5*aebdb1e2SAdrian Chadd * Redistribution and use in source and binary forms, with or without
6*aebdb1e2SAdrian Chadd * modification, are permitted provided that the following conditions
7*aebdb1e2SAdrian Chadd * are met:
8*aebdb1e2SAdrian Chadd * 1. Redistributions of source code must retain the above copyright
9*aebdb1e2SAdrian Chadd * notice, this list of conditions and the following disclaimer,
10*aebdb1e2SAdrian Chadd * without modification.
11*aebdb1e2SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12*aebdb1e2SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13*aebdb1e2SAdrian Chadd * redistribution must be conditioned upon including a substantially
14*aebdb1e2SAdrian Chadd * similar Disclaimer requirement for further binary redistribution.
15*aebdb1e2SAdrian Chadd *
16*aebdb1e2SAdrian Chadd * NO WARRANTY
17*aebdb1e2SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*aebdb1e2SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*aebdb1e2SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20*aebdb1e2SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21*aebdb1e2SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22*aebdb1e2SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*aebdb1e2SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*aebdb1e2SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*aebdb1e2SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*aebdb1e2SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27*aebdb1e2SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES.
28*aebdb1e2SAdrian Chadd */
29*aebdb1e2SAdrian Chadd
30*aebdb1e2SAdrian Chadd #include <stdio.h>
31*aebdb1e2SAdrian Chadd #include <stdlib.h>
32*aebdb1e2SAdrian Chadd #include <unistd.h>
33*aebdb1e2SAdrian Chadd #include <errno.h>
34*aebdb1e2SAdrian Chadd #include <string.h>
35*aebdb1e2SAdrian Chadd #include <err.h>
36*aebdb1e2SAdrian Chadd #include <fcntl.h>
37*aebdb1e2SAdrian Chadd #include <sys/endian.h>
38*aebdb1e2SAdrian Chadd #include <sys/types.h>
39*aebdb1e2SAdrian Chadd #include <sys/stat.h>
40*aebdb1e2SAdrian Chadd
41*aebdb1e2SAdrian Chadd #include <libusb.h>
42*aebdb1e2SAdrian Chadd
43*aebdb1e2SAdrian Chadd #include "ath3k_fw.h"
44*aebdb1e2SAdrian Chadd #include "ath3k_hw.h"
45*aebdb1e2SAdrian Chadd #include "ath3k_dbg.h"
46*aebdb1e2SAdrian Chadd
47*aebdb1e2SAdrian Chadd #define XMIN(x, y) ((x) < (y) ? (x) : (y))
48*aebdb1e2SAdrian Chadd
49*aebdb1e2SAdrian Chadd int
ath3k_load_fwfile(struct libusb_device_handle * hdl,const struct ath3k_firmware * fw)50*aebdb1e2SAdrian Chadd ath3k_load_fwfile(struct libusb_device_handle *hdl,
51*aebdb1e2SAdrian Chadd const struct ath3k_firmware *fw)
52*aebdb1e2SAdrian Chadd {
53*aebdb1e2SAdrian Chadd int size, count, sent = 0;
54*aebdb1e2SAdrian Chadd int ret, r;
55*aebdb1e2SAdrian Chadd
56*aebdb1e2SAdrian Chadd count = fw->len;
57*aebdb1e2SAdrian Chadd
58*aebdb1e2SAdrian Chadd size = XMIN(count, FW_HDR_SIZE);
59*aebdb1e2SAdrian Chadd
60*aebdb1e2SAdrian Chadd ath3k_debug("%s: file=%s, size=%d\n",
61*aebdb1e2SAdrian Chadd __func__, fw->fwname, count);
62*aebdb1e2SAdrian Chadd
63*aebdb1e2SAdrian Chadd /*
64*aebdb1e2SAdrian Chadd * Flip the device over to configuration mode.
65*aebdb1e2SAdrian Chadd */
66*aebdb1e2SAdrian Chadd ret = libusb_control_transfer(hdl,
67*aebdb1e2SAdrian Chadd LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
68*aebdb1e2SAdrian Chadd ATH3K_DNLOAD,
69*aebdb1e2SAdrian Chadd 0,
70*aebdb1e2SAdrian Chadd 0,
71*aebdb1e2SAdrian Chadd fw->buf + sent,
72*aebdb1e2SAdrian Chadd size,
73*aebdb1e2SAdrian Chadd 1000); /* XXX timeout */
74*aebdb1e2SAdrian Chadd
75*aebdb1e2SAdrian Chadd if (ret != size) {
76*aebdb1e2SAdrian Chadd fprintf(stderr, "Can't switch to config mode; ret=%d\n",
77*aebdb1e2SAdrian Chadd ret);
78*aebdb1e2SAdrian Chadd return (-1);
79*aebdb1e2SAdrian Chadd }
80*aebdb1e2SAdrian Chadd
81*aebdb1e2SAdrian Chadd sent += size;
82*aebdb1e2SAdrian Chadd count -= size;
83*aebdb1e2SAdrian Chadd
84*aebdb1e2SAdrian Chadd /* Load in the rest of the data */
85*aebdb1e2SAdrian Chadd while (count) {
86*aebdb1e2SAdrian Chadd size = XMIN(count, BULK_SIZE);
87*aebdb1e2SAdrian Chadd ath3k_debug("%s: transferring %d bytes, offset %d\n",
88*aebdb1e2SAdrian Chadd __func__,
89*aebdb1e2SAdrian Chadd sent,
90*aebdb1e2SAdrian Chadd size);
91*aebdb1e2SAdrian Chadd
92*aebdb1e2SAdrian Chadd ret = libusb_bulk_transfer(hdl,
93*aebdb1e2SAdrian Chadd 0x2,
94*aebdb1e2SAdrian Chadd fw->buf + sent,
95*aebdb1e2SAdrian Chadd size,
96*aebdb1e2SAdrian Chadd &r,
97*aebdb1e2SAdrian Chadd 1000);
98*aebdb1e2SAdrian Chadd
99*aebdb1e2SAdrian Chadd if (ret < 0 || r != size) {
100*aebdb1e2SAdrian Chadd fprintf(stderr, "Can't load firmware: err=%s, size=%d\n",
101*aebdb1e2SAdrian Chadd libusb_strerror(ret),
102*aebdb1e2SAdrian Chadd size);
103*aebdb1e2SAdrian Chadd return (-1);
104*aebdb1e2SAdrian Chadd }
105*aebdb1e2SAdrian Chadd sent += size;
106*aebdb1e2SAdrian Chadd count -= size;
107*aebdb1e2SAdrian Chadd }
108*aebdb1e2SAdrian Chadd return (0);
109*aebdb1e2SAdrian Chadd }
110*aebdb1e2SAdrian Chadd
111*aebdb1e2SAdrian Chadd int
ath3k_get_state(struct libusb_device_handle * hdl,unsigned char * state)112*aebdb1e2SAdrian Chadd ath3k_get_state(struct libusb_device_handle *hdl, unsigned char *state)
113*aebdb1e2SAdrian Chadd {
114*aebdb1e2SAdrian Chadd int ret;
115*aebdb1e2SAdrian Chadd
116*aebdb1e2SAdrian Chadd ret = libusb_control_transfer(hdl,
117*aebdb1e2SAdrian Chadd LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
118*aebdb1e2SAdrian Chadd ATH3K_GETSTATE,
119*aebdb1e2SAdrian Chadd 0,
120*aebdb1e2SAdrian Chadd 0,
121*aebdb1e2SAdrian Chadd state,
122*aebdb1e2SAdrian Chadd 1,
123*aebdb1e2SAdrian Chadd 1000); /* XXX timeout */
124*aebdb1e2SAdrian Chadd
125*aebdb1e2SAdrian Chadd if (ret < 0) {
126*aebdb1e2SAdrian Chadd fprintf(stderr,
127*aebdb1e2SAdrian Chadd "%s: libusb_control_transfer() failed: code=%d\n",
128*aebdb1e2SAdrian Chadd __func__,
129*aebdb1e2SAdrian Chadd ret);
130*aebdb1e2SAdrian Chadd return (0);
131*aebdb1e2SAdrian Chadd }
132*aebdb1e2SAdrian Chadd
133*aebdb1e2SAdrian Chadd return (ret == 1);
134*aebdb1e2SAdrian Chadd }
135*aebdb1e2SAdrian Chadd
136*aebdb1e2SAdrian Chadd int
ath3k_get_version(struct libusb_device_handle * hdl,struct ath3k_version * version)137*aebdb1e2SAdrian Chadd ath3k_get_version(struct libusb_device_handle *hdl,
138*aebdb1e2SAdrian Chadd struct ath3k_version *version)
139*aebdb1e2SAdrian Chadd {
140*aebdb1e2SAdrian Chadd int ret;
141*aebdb1e2SAdrian Chadd
142*aebdb1e2SAdrian Chadd ret = libusb_control_transfer(hdl,
143*aebdb1e2SAdrian Chadd LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
144*aebdb1e2SAdrian Chadd ATH3K_GETVERSION,
145*aebdb1e2SAdrian Chadd 0,
146*aebdb1e2SAdrian Chadd 0,
147*aebdb1e2SAdrian Chadd (unsigned char *) version,
148*aebdb1e2SAdrian Chadd sizeof(struct ath3k_version),
149*aebdb1e2SAdrian Chadd 1000); /* XXX timeout */
150*aebdb1e2SAdrian Chadd
151*aebdb1e2SAdrian Chadd if (ret < 0) {
152*aebdb1e2SAdrian Chadd fprintf(stderr,
153*aebdb1e2SAdrian Chadd "%s: libusb_control_transfer() failed: code=%d\n",
154*aebdb1e2SAdrian Chadd __func__,
155*aebdb1e2SAdrian Chadd ret);
156*aebdb1e2SAdrian Chadd return (0);
157*aebdb1e2SAdrian Chadd }
158*aebdb1e2SAdrian Chadd
159*aebdb1e2SAdrian Chadd /* XXX endian fix! */
160*aebdb1e2SAdrian Chadd
161*aebdb1e2SAdrian Chadd return (ret == sizeof(struct ath3k_version));
162*aebdb1e2SAdrian Chadd }
163*aebdb1e2SAdrian Chadd
164*aebdb1e2SAdrian Chadd int
ath3k_load_patch(libusb_device_handle * hdl,const char * fw_path)165*aebdb1e2SAdrian Chadd ath3k_load_patch(libusb_device_handle *hdl, const char *fw_path)
166*aebdb1e2SAdrian Chadd {
167*aebdb1e2SAdrian Chadd int ret;
168*aebdb1e2SAdrian Chadd unsigned char fw_state;
169*aebdb1e2SAdrian Chadd struct ath3k_version fw_ver, pt_ver;
170*aebdb1e2SAdrian Chadd char fwname[FILENAME_MAX];
171*aebdb1e2SAdrian Chadd struct ath3k_firmware fw;
172*aebdb1e2SAdrian Chadd uint32_t tmp;
173*aebdb1e2SAdrian Chadd
174*aebdb1e2SAdrian Chadd ret = ath3k_get_state(hdl, &fw_state);
175*aebdb1e2SAdrian Chadd if (ret < 0) {
176*aebdb1e2SAdrian Chadd ath3k_err("%s: Can't get state\n", __func__);
177*aebdb1e2SAdrian Chadd return (ret);
178*aebdb1e2SAdrian Chadd }
179*aebdb1e2SAdrian Chadd
180*aebdb1e2SAdrian Chadd if (fw_state & ATH3K_PATCH_UPDATE) {
181*aebdb1e2SAdrian Chadd ath3k_info("%s: Patch already downloaded\n",
182*aebdb1e2SAdrian Chadd __func__);
183*aebdb1e2SAdrian Chadd return (0);
184*aebdb1e2SAdrian Chadd }
185*aebdb1e2SAdrian Chadd
186*aebdb1e2SAdrian Chadd ret = ath3k_get_version(hdl, &fw_ver);
187*aebdb1e2SAdrian Chadd if (ret < 0) {
188*aebdb1e2SAdrian Chadd ath3k_debug("%s: Can't get version\n", __func__);
189*aebdb1e2SAdrian Chadd return (ret);
190*aebdb1e2SAdrian Chadd }
191*aebdb1e2SAdrian Chadd
192*aebdb1e2SAdrian Chadd /* XXX path info? */
193*aebdb1e2SAdrian Chadd snprintf(fwname, FILENAME_MAX, "%s/ar3k/AthrBT_0x%08x.dfu",
194*aebdb1e2SAdrian Chadd fw_path,
195*aebdb1e2SAdrian Chadd fw_ver.rom_version);
196*aebdb1e2SAdrian Chadd
197*aebdb1e2SAdrian Chadd /* Read in the firmware */
198*aebdb1e2SAdrian Chadd if (ath3k_fw_read(&fw, fwname) <= 0) {
199*aebdb1e2SAdrian Chadd ath3k_debug("%s: ath3k_fw_read() failed\n",
200*aebdb1e2SAdrian Chadd __func__);
201*aebdb1e2SAdrian Chadd return (-1);
202*aebdb1e2SAdrian Chadd }
203*aebdb1e2SAdrian Chadd
204*aebdb1e2SAdrian Chadd /*
205*aebdb1e2SAdrian Chadd * Extract the ROM/build version from the patch file.
206*aebdb1e2SAdrian Chadd */
207*aebdb1e2SAdrian Chadd memcpy(&tmp, fw.buf + fw.len - 8, sizeof(tmp));
208*aebdb1e2SAdrian Chadd pt_ver.rom_version = le32toh(tmp);
209*aebdb1e2SAdrian Chadd memcpy(&tmp, fw.buf + fw.len - 4, sizeof(tmp));
210*aebdb1e2SAdrian Chadd pt_ver.build_version = le32toh(tmp);
211*aebdb1e2SAdrian Chadd
212*aebdb1e2SAdrian Chadd ath3k_info("%s: file %s: rom_ver=%d, build_ver=%d\n",
213*aebdb1e2SAdrian Chadd __func__,
214*aebdb1e2SAdrian Chadd fwname,
215*aebdb1e2SAdrian Chadd (int) pt_ver.rom_version,
216*aebdb1e2SAdrian Chadd (int) pt_ver.build_version);
217*aebdb1e2SAdrian Chadd
218*aebdb1e2SAdrian Chadd /* Check the ROM/build version against the firmware */
219*aebdb1e2SAdrian Chadd if ((pt_ver.rom_version != fw_ver.rom_version) ||
220*aebdb1e2SAdrian Chadd (pt_ver.build_version <= fw_ver.build_version)) {
221*aebdb1e2SAdrian Chadd ath3k_debug("Patch file version mismatch!\n");
222*aebdb1e2SAdrian Chadd ath3k_fw_free(&fw);
223*aebdb1e2SAdrian Chadd return (-1);
224*aebdb1e2SAdrian Chadd }
225*aebdb1e2SAdrian Chadd
226*aebdb1e2SAdrian Chadd /* Load in the firmware */
227*aebdb1e2SAdrian Chadd ret = ath3k_load_fwfile(hdl, &fw);
228*aebdb1e2SAdrian Chadd
229*aebdb1e2SAdrian Chadd /* free it */
230*aebdb1e2SAdrian Chadd ath3k_fw_free(&fw);
231*aebdb1e2SAdrian Chadd
232*aebdb1e2SAdrian Chadd return (ret);
233*aebdb1e2SAdrian Chadd }
234*aebdb1e2SAdrian Chadd
235*aebdb1e2SAdrian Chadd int
ath3k_load_syscfg(libusb_device_handle * hdl,const char * fw_path)236*aebdb1e2SAdrian Chadd ath3k_load_syscfg(libusb_device_handle *hdl, const char *fw_path)
237*aebdb1e2SAdrian Chadd {
238*aebdb1e2SAdrian Chadd unsigned char fw_state;
239*aebdb1e2SAdrian Chadd char filename[FILENAME_MAX];
240*aebdb1e2SAdrian Chadd struct ath3k_firmware fw;
241*aebdb1e2SAdrian Chadd struct ath3k_version fw_ver;
242*aebdb1e2SAdrian Chadd int clk_value, ret;
243*aebdb1e2SAdrian Chadd
244*aebdb1e2SAdrian Chadd ret = ath3k_get_state(hdl, &fw_state);
245*aebdb1e2SAdrian Chadd if (ret < 0) {
246*aebdb1e2SAdrian Chadd ath3k_err("Can't get state to change to load configuration err");
247*aebdb1e2SAdrian Chadd return (-EBUSY);
248*aebdb1e2SAdrian Chadd }
249*aebdb1e2SAdrian Chadd
250*aebdb1e2SAdrian Chadd ret = ath3k_get_version(hdl, &fw_ver);
251*aebdb1e2SAdrian Chadd if (ret < 0) {
252*aebdb1e2SAdrian Chadd ath3k_err("Can't get version to change to load ram patch err");
253*aebdb1e2SAdrian Chadd return (ret);
254*aebdb1e2SAdrian Chadd }
255*aebdb1e2SAdrian Chadd
256*aebdb1e2SAdrian Chadd switch (fw_ver.ref_clock) {
257*aebdb1e2SAdrian Chadd case ATH3K_XTAL_FREQ_26M:
258*aebdb1e2SAdrian Chadd clk_value = 26;
259*aebdb1e2SAdrian Chadd break;
260*aebdb1e2SAdrian Chadd case ATH3K_XTAL_FREQ_40M:
261*aebdb1e2SAdrian Chadd clk_value = 40;
262*aebdb1e2SAdrian Chadd break;
263*aebdb1e2SAdrian Chadd case ATH3K_XTAL_FREQ_19P2:
264*aebdb1e2SAdrian Chadd clk_value = 19;
265*aebdb1e2SAdrian Chadd break;
266*aebdb1e2SAdrian Chadd default:
267*aebdb1e2SAdrian Chadd clk_value = 0;
268*aebdb1e2SAdrian Chadd break;
269*aebdb1e2SAdrian Chadd }
270*aebdb1e2SAdrian Chadd
271*aebdb1e2SAdrian Chadd snprintf(filename, FILENAME_MAX, "%s/ar3k/ramps_0x%08x_%d%s",
272*aebdb1e2SAdrian Chadd fw_path,
273*aebdb1e2SAdrian Chadd fw_ver.rom_version,
274*aebdb1e2SAdrian Chadd clk_value,
275*aebdb1e2SAdrian Chadd ".dfu");
276*aebdb1e2SAdrian Chadd
277*aebdb1e2SAdrian Chadd ath3k_info("%s: syscfg file = %s\n",
278*aebdb1e2SAdrian Chadd __func__,
279*aebdb1e2SAdrian Chadd filename);
280*aebdb1e2SAdrian Chadd
281*aebdb1e2SAdrian Chadd /* Read in the firmware */
282*aebdb1e2SAdrian Chadd if (ath3k_fw_read(&fw, filename) <= 0) {
283*aebdb1e2SAdrian Chadd ath3k_err("%s: ath3k_fw_read() failed\n",
284*aebdb1e2SAdrian Chadd __func__);
285*aebdb1e2SAdrian Chadd return (-1);
286*aebdb1e2SAdrian Chadd }
287*aebdb1e2SAdrian Chadd
288*aebdb1e2SAdrian Chadd ret = ath3k_load_fwfile(hdl, &fw);
289*aebdb1e2SAdrian Chadd
290*aebdb1e2SAdrian Chadd ath3k_fw_free(&fw);
291*aebdb1e2SAdrian Chadd return (ret);
292*aebdb1e2SAdrian Chadd }
293*aebdb1e2SAdrian Chadd
294*aebdb1e2SAdrian Chadd int
ath3k_set_normal_mode(libusb_device_handle * hdl)295*aebdb1e2SAdrian Chadd ath3k_set_normal_mode(libusb_device_handle *hdl)
296*aebdb1e2SAdrian Chadd {
297*aebdb1e2SAdrian Chadd int ret;
298*aebdb1e2SAdrian Chadd unsigned char fw_state;
299*aebdb1e2SAdrian Chadd
300*aebdb1e2SAdrian Chadd ret = ath3k_get_state(hdl, &fw_state);
301*aebdb1e2SAdrian Chadd if (ret < 0) {
302*aebdb1e2SAdrian Chadd ath3k_err("%s: can't get state\n", __func__);
303*aebdb1e2SAdrian Chadd return (ret);
304*aebdb1e2SAdrian Chadd }
305*aebdb1e2SAdrian Chadd
306*aebdb1e2SAdrian Chadd /*
307*aebdb1e2SAdrian Chadd * This isn't a fatal error - the device may have detached
308*aebdb1e2SAdrian Chadd * already.
309*aebdb1e2SAdrian Chadd */
310*aebdb1e2SAdrian Chadd if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
311*aebdb1e2SAdrian Chadd ath3k_debug("%s: firmware is already in normal mode\n",
312*aebdb1e2SAdrian Chadd __func__);
313*aebdb1e2SAdrian Chadd return (0);
314*aebdb1e2SAdrian Chadd }
315*aebdb1e2SAdrian Chadd
316*aebdb1e2SAdrian Chadd ret = libusb_control_transfer(hdl,
317*aebdb1e2SAdrian Chadd LIBUSB_REQUEST_TYPE_VENDOR, /* XXX out direction? */
318*aebdb1e2SAdrian Chadd ATH3K_SET_NORMAL_MODE,
319*aebdb1e2SAdrian Chadd 0,
320*aebdb1e2SAdrian Chadd 0,
321*aebdb1e2SAdrian Chadd NULL,
322*aebdb1e2SAdrian Chadd 0,
323*aebdb1e2SAdrian Chadd 1000); /* XXX timeout */
324*aebdb1e2SAdrian Chadd
325*aebdb1e2SAdrian Chadd if (ret < 0) {
326*aebdb1e2SAdrian Chadd ath3k_err("%s: libusb_control_transfer() failed: code=%d\n",
327*aebdb1e2SAdrian Chadd __func__,
328*aebdb1e2SAdrian Chadd ret);
329*aebdb1e2SAdrian Chadd return (0);
330*aebdb1e2SAdrian Chadd }
331*aebdb1e2SAdrian Chadd
332*aebdb1e2SAdrian Chadd return (ret == 0);
333*aebdb1e2SAdrian Chadd }
334*aebdb1e2SAdrian Chadd
335*aebdb1e2SAdrian Chadd int
ath3k_switch_pid(libusb_device_handle * hdl)336*aebdb1e2SAdrian Chadd ath3k_switch_pid(libusb_device_handle *hdl)
337*aebdb1e2SAdrian Chadd {
338*aebdb1e2SAdrian Chadd int ret;
339*aebdb1e2SAdrian Chadd ret = libusb_control_transfer(hdl,
340*aebdb1e2SAdrian Chadd LIBUSB_REQUEST_TYPE_VENDOR, /* XXX set an out flag? */
341*aebdb1e2SAdrian Chadd USB_REG_SWITCH_VID_PID,
342*aebdb1e2SAdrian Chadd 0,
343*aebdb1e2SAdrian Chadd 0,
344*aebdb1e2SAdrian Chadd NULL,
345*aebdb1e2SAdrian Chadd 0,
346*aebdb1e2SAdrian Chadd 1000); /* XXX timeout */
347*aebdb1e2SAdrian Chadd
348*aebdb1e2SAdrian Chadd if (ret < 0) {
349*aebdb1e2SAdrian Chadd ath3k_debug("%s: libusb_control_transfer() failed: code=%d\n",
350*aebdb1e2SAdrian Chadd __func__,
351*aebdb1e2SAdrian Chadd ret);
352*aebdb1e2SAdrian Chadd return (0);
353*aebdb1e2SAdrian Chadd }
354*aebdb1e2SAdrian Chadd
355*aebdb1e2SAdrian Chadd return (ret == 0);
356*aebdb1e2SAdrian Chadd }
357