Bug Summary

File:dev/usb/if_bwfm_usb.c
Warning:line 728, column 2
Value stored to 'rdlbytes' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_bwfm_usb.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/if_bwfm_usb.c
1/* $OpenBSD: if_bwfm_usb.c,v 1.20 2021/11/05 11:38:51 mpi Exp $ */
2/*
3 * Copyright (c) 2010-2016 Broadcom Corporation
4 * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include "bpfilter.h"
20
21#include <sys/param.h>
22#include <sys/systm.h>
23#include <sys/buf.h>
24#include <sys/kernel.h>
25#include <sys/malloc.h>
26#include <sys/device.h>
27#include <sys/queue.h>
28#include <sys/socket.h>
29
30#if NBPFILTER1 > 0
31#include <net/bpf.h>
32#endif
33#include <net/if.h>
34#include <net/if_dl.h>
35#include <net/if_media.h>
36
37#include <netinet/in.h>
38#include <netinet/if_ether.h>
39
40#include <net80211/ieee80211_var.h>
41
42#include <machine/bus.h>
43
44#include <dev/usb/usb.h>
45#include <dev/usb/usbdi.h>
46#include <dev/usb/usbdi_util.h>
47#include <dev/usb/usbdivar.h>
48#include <dev/usb/usb_mem.h>
49#include <dev/usb/usbdevs.h>
50
51#include <dev/ic/bwfmvar.h>
52#include <dev/ic/bwfmreg.h>
53
54/*
55 * Various supported device vendors/products.
56 */
57static const struct usb_devno bwfm_usbdevs[] = {
58 { USB_VENDOR_BROADCOM0x0a5c, USB_PRODUCT_BROADCOM_BCM431430xbd1e },
59 { USB_VENDOR_BROADCOM0x0a5c, USB_PRODUCT_BROADCOM_BCM432360xbd17 },
60 { USB_VENDOR_BROADCOM0x0a5c, USB_PRODUCT_BROADCOM_BCM432420xbd1f },
61 { USB_VENDOR_BROADCOM0x0a5c, USB_PRODUCT_BROADCOM_BCM435690xbd27 },
62 { USB_VENDOR_BROADCOM0x0a5c, USB_PRODUCT_BROADCOM_BCMFW0x0bdc },
63};
64
65#ifdef BWFM_DEBUG
66#define DPRINTF(x)do { ; } while (0) do { if (bwfm_debug > 0) printf x; } while (0)
67#define DPRINTFN(n, x)do { ; } while (0) do { if (bwfm_debug >= (n)) printf x; } while (0)
68static int bwfm_debug = 2;
69#else
70#define DPRINTF(x)do { ; } while (0) do { ; } while (0)
71#define DPRINTFN(n, x)do { ; } while (0) do { ; } while (0)
72#endif
73
74#define DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname) ((sc)->sc_sc.sc_dev.dv_xname)
75
76#define BRCMF_POSTBOOT_ID0xA123 0xA123 /* ID to detect if dongle
77 * has boot up
78 */
79
80#define TRX_MAGIC0x30524448 0x30524448 /* "HDR0" */
81#define TRX_MAX_OFFSET3 3 /* Max number of file offsets */
82#define TRX_UNCOMP_IMAGE0x20 0x20 /* Trx holds uncompressed img */
83#define TRX_RDL_CHUNK1500 1500 /* size of each dl transfer */
84#define TRX_OFFSETS_DLFWLEN_IDX0 0
85
86/* Control messages: bRequest values */
87#define DL_GETSTATE0 0 /* returns the rdl_state_t struct */
88#define DL_CHECK_CRC1 1 /* currently unused */
89#define DL_GO2 2 /* execute downloaded image */
90#define DL_START3 3 /* initialize dl state */
91#define DL_REBOOT4 4 /* reboot the device in 2 seconds */
92#define DL_GETVER5 5 /* returns the bootrom_id_t struct */
93#define DL_GO_PROTECTED6 6 /* execute the downloaded code and set reset
94 * event to occur in 2 seconds. It is the
95 * responsibility of the downloaded code to
96 * clear this event
97 */
98#define DL_EXEC7 7 /* jump to a supplied address */
99#define DL_RESETCFG8 8 /* To support single enum on dongle
100 * - Not used by bootloader
101 */
102#define DL_DEFER_RESP_OK9 9 /* Potentially defer the response to setup
103 * if resp unavailable
104 */
105
106/* states */
107#define DL_WAITING0 0 /* waiting to rx first pkt */
108#define DL_READY1 1 /* hdr was good, waiting for more of the
109 * compressed image
110 */
111#define DL_BAD_HDR2 2 /* hdr was corrupted */
112#define DL_BAD_CRC3 3 /* compressed image was corrupted */
113#define DL_RUNNABLE4 4 /* download was successful,waiting for go cmd */
114#define DL_START_FAIL5 5 /* failed to initialize correctly */
115#define DL_NVRAM_TOOBIG6 6 /* host specified nvram data exceeds DL_NVRAM
116 * value
117 */
118#define DL_IMAGE_TOOBIG7 7 /* firmware image too big */
119
120
121struct trx_header {
122 uint32_t magic; /* "HDR0" */
123 uint32_t len; /* Length of file including header */
124 uint32_t crc32; /* CRC from flag_version to end of file */
125 uint32_t flag_version; /* 0:15 flags, 16:31 version */
126 uint32_t offsets[TRX_MAX_OFFSET3];/* Offsets of partitions from start of
127 * header
128 */
129};
130
131struct rdl_state {
132 uint32_t state;
133 uint32_t bytes;
134};
135
136struct bootrom_id {
137 uint32_t chip; /* Chip id */
138 uint32_t chiprev; /* Chip rev */
139 uint32_t ramsize; /* Size of RAM */
140 uint32_t remapbase; /* Current remap base address */
141 uint32_t boardtype; /* Type of board */
142 uint32_t boardrev; /* Board revision */
143};
144
145struct bwfm_usb_rx_data {
146 struct bwfm_usb_softc *sc;
147 struct usbd_xfer *xfer;
148 uint8_t *buf;
149};
150
151struct bwfm_usb_tx_data {
152 struct bwfm_usb_softc *sc;
153 struct usbd_xfer *xfer;
154 uint8_t *buf;
155 struct mbuf *mbuf;
156 TAILQ_ENTRY(bwfm_usb_tx_data)struct { struct bwfm_usb_tx_data *tqe_next; struct bwfm_usb_tx_data
**tqe_prev; }
next;
157};
158
159#define BWFM_RX_LIST_COUNT50 50
160#define BWFM_TX_LIST_COUNT50 50
161#define BWFM_RXBUFSZ1600 1600
162#define BWFM_TXBUFSZ1600 1600
163struct bwfm_usb_softc {
164 struct bwfm_softc sc_sc;
165 struct usbd_device *sc_udev;
166 struct usbd_interface *sc_iface;
167 uint8_t sc_ifaceno;
168
169 int sc_initialized;
170
171 uint16_t sc_vendor;
172 uint16_t sc_product;
173
174 uint32_t sc_chip;
175 uint32_t sc_chiprev;
176
177 int sc_rx_no;
178 int sc_tx_no;
179
180 struct usbd_pipe *sc_rx_pipeh;
181 struct usbd_pipe *sc_tx_pipeh;
182
183 struct bwfm_usb_rx_data sc_rx_data[BWFM_RX_LIST_COUNT50];
184 struct bwfm_usb_tx_data sc_tx_data[BWFM_TX_LIST_COUNT50];
185 TAILQ_HEAD(, bwfm_usb_tx_data)struct { struct bwfm_usb_tx_data *tqh_first; struct bwfm_usb_tx_data
**tqh_last; }
sc_tx_free_list;
186};
187
188int bwfm_usb_match(struct device *, void *, void *);
189void bwfm_usb_attach(struct device *, struct device *, void *);
190int bwfm_usb_detach(struct device *, int);
191
192int bwfm_usb_dl_cmd(struct bwfm_usb_softc *, uint8_t, void *, int);
193int bwfm_usb_load_microcode(struct bwfm_usb_softc *, const u_char *,
194 size_t);
195
196int bwfm_usb_alloc_rx_list(struct bwfm_usb_softc *);
197void bwfm_usb_free_rx_list(struct bwfm_usb_softc *);
198int bwfm_usb_alloc_tx_list(struct bwfm_usb_softc *);
199void bwfm_usb_free_tx_list(struct bwfm_usb_softc *);
200
201int bwfm_usb_preinit(struct bwfm_softc *);
202int bwfm_usb_txcheck(struct bwfm_softc *);
203int bwfm_usb_txdata(struct bwfm_softc *, struct mbuf *);
204int bwfm_usb_txctl(struct bwfm_softc *, void *);
205void bwfm_usb_txctl_cb(struct usbd_xfer *, void *, usbd_status);
206
207struct mbuf * bwfm_usb_newbuf(void);
208void bwfm_usb_rxeof(struct usbd_xfer *, void *, usbd_status);
209void bwfm_usb_txeof(struct usbd_xfer *, void *, usbd_status);
210
211struct bwfm_bus_ops bwfm_usb_bus_ops = {
212 .bs_preinit = bwfm_usb_preinit,
213 .bs_stop = NULL((void *)0),
214 .bs_txcheck = bwfm_usb_txcheck,
215 .bs_txdata = bwfm_usb_txdata,
216 .bs_txctl = bwfm_usb_txctl,
217};
218
219const struct cfattach bwfm_usb_ca = {
220 sizeof(struct bwfm_usb_softc),
221 bwfm_usb_match,
222 bwfm_usb_attach,
223 bwfm_usb_detach,
224};
225
226int
227bwfm_usb_match(struct device *parent, void *match, void *aux)
228{
229 struct usb_attach_arg *uaa = aux;
230
231 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
232 return UMATCH_NONE0;
233
234 return (usb_lookup(bwfm_usbdevs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(bwfm_usbdevs), sizeof
(bwfm_usbdevs) / sizeof ((bwfm_usbdevs)[0]), sizeof ((bwfm_usbdevs
)[0]), (uaa->vendor), (uaa->product))
!= NULL((void *)0)) ?
235 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0;
236}
237
238void
239bwfm_usb_attach(struct device *parent, struct device *self, void *aux)
240{
241 struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self;
242 struct usb_attach_arg *uaa = aux;
243 usb_device_descriptor_t *dd;
244 usb_interface_descriptor_t *id;
245 usb_endpoint_descriptor_t *ed;
246 int i;
247
248 sc->sc_udev = uaa->device;
249 sc->sc_iface = uaa->iface;
250 sc->sc_ifaceno = uaa->ifaceno;
251 sc->sc_vendor = uaa->vendor;
252 sc->sc_product = uaa->product;
253 sc->sc_sc.sc_bus_ops = &bwfm_usb_bus_ops;
254 sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops;
255
256 /* Check number of configurations. */
257 dd = usbd_get_device_descriptor(sc->sc_udev);
258 if (dd->bNumConfigurations != 1) {
259 printf("%s: number of configurations not supported\n",
260 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
261 return;
262 }
263
264 /* Get endpoints. */
265 id = usbd_get_interface_descriptor(sc->sc_iface);
266
267 sc->sc_rx_no = sc->sc_tx_no = -1;
268 for (i = 0; i < id->bNumEndpoints; i++) {
269 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
270 if (ed == NULL((void *)0)) {
271 printf("%s: no endpoint descriptor for iface %d\n",
272 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), i);
273 return;
274 }
275
276 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
277 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02 &&
278 sc->sc_rx_no == -1)
279 sc->sc_rx_no = ed->bEndpointAddress;
280 else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00 &&
281 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02 &&
282 sc->sc_tx_no == -1)
283 sc->sc_tx_no = ed->bEndpointAddress;
284 }
285 if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) {
286 printf("%s: missing endpoint\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
287 return;
288 }
289
290 bwfm_attach(&sc->sc_sc);
291 config_mountroot(self, bwfm_attachhook);
292}
293
294int
295bwfm_usb_preinit(struct bwfm_softc *bwfm)
296{
297 struct bwfm_usb_softc *sc = (void *)bwfm;
298 struct bwfm_usb_rx_data *data;
299 const char *name = NULL((void *)0);
300 struct bootrom_id brom;
301 usbd_status error;
302 u_char *ucode;
303 size_t size;
304 int i;
305
306 if (sc->sc_initialized)
307 return 0;
308
309 /* Read chip id and chip rev to check the firmware. */
310 memset(&brom, 0, sizeof(brom))__builtin_memset((&brom), (0), (sizeof(brom)));
311 bwfm_usb_dl_cmd(sc, DL_GETVER5, &brom, sizeof(brom));
312 sc->sc_chip = letoh32(brom.chip)((__uint32_t)(brom.chip));
313 sc->sc_chiprev = letoh32(brom.chiprev)((__uint32_t)(brom.chiprev));
314
315 /* Setup data pipes */
316 error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE0x01,
317 &sc->sc_rx_pipeh);
318 if (error != 0) {
319 printf("%s: could not open rx pipe: %s\n",
320 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
321 return 1;
322 }
323 error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE0x01,
324 &sc->sc_tx_pipeh);
325 if (error != 0) {
326 printf("%s: could not open tx pipe: %s\n",
327 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
328 goto cleanup;
329 }
330
331 /* Firmware not yet loaded? */
332 if (sc->sc_chip != BRCMF_POSTBOOT_ID0xA123) {
333 switch (sc->sc_chip)
334 {
335 case BRCM_CC_43143_CHIP_ID43143:
336 name = "brcmfmac43143.bin";
337 break;
338 case BRCM_CC_43235_CHIP_ID43235:
339 case BRCM_CC_43236_CHIP_ID43236:
340 case BRCM_CC_43238_CHIP_ID43238:
341 if (sc->sc_chiprev == 3)
342 name = "brcmfmac43236b.bin";
343 break;
344 case BRCM_CC_43242_CHIP_ID43242:
345 name = "brcmfmac43242a.bin";
346 break;
347 case BRCM_CC_43566_CHIP_ID43566:
348 case BRCM_CC_43569_CHIP_ID43569:
349 name = "brcmfmac43569.bin";
350 break;
351 default:
352 break;
353 }
354
355 if (name == NULL((void *)0)) {
356 printf("%s: unknown firmware\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
357 goto cleanup;
358 }
359
360 if (loadfirmware(name, &ucode, &size) != 0) {
361 printf("%s: failed loadfirmware of file %s\n",
362 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), name);
363 goto cleanup;
364 }
365
366 if (bwfm_usb_load_microcode(sc, ucode, size) != 0) {
367 printf("%s: could not load microcode\n",
368 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
369 free(ucode, M_DEVBUF2, size);
370 goto cleanup;
371 }
372
373 free(ucode, M_DEVBUF2, size);
374
375 for (i = 0; i < 10; i++) {
376 delay(100 * 1000)(*delay_func)(100 * 1000);
377 memset(&brom, 0, sizeof(brom))__builtin_memset((&brom), (0), (sizeof(brom)));
378 bwfm_usb_dl_cmd(sc, DL_GETVER5, &brom, sizeof(brom));
379 if (letoh32(brom.chip)((__uint32_t)(brom.chip)) == BRCMF_POSTBOOT_ID0xA123)
380 break;
381 }
382
383 if (letoh32(brom.chip)((__uint32_t)(brom.chip)) != BRCMF_POSTBOOT_ID0xA123) {
384 printf("%s: firmware did not start up\n",
385 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
386 goto cleanup;
387 }
388
389 sc->sc_chip = letoh32(brom.chip)((__uint32_t)(brom.chip));
390 sc->sc_chiprev = letoh32(brom.chiprev)((__uint32_t)(brom.chiprev));
391 }
392
393 bwfm_usb_dl_cmd(sc, DL_RESETCFG8, &brom, sizeof(brom));
394
395 if (bwfm_usb_alloc_rx_list(sc) || bwfm_usb_alloc_tx_list(sc)) {
396 printf("%s: cannot allocate rx/tx lists\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
397 goto cleanup;
398 }
399
400 for (i = 0; i < BWFM_RX_LIST_COUNT50; i++) {
401 data = &sc->sc_rx_data[i];
402
403 usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf,
404 BWFM_RXBUFSZ1600, USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0,
405 bwfm_usb_rxeof);
406 error = usbd_transfer(data->xfer);
407 if (error != 0 && error != USBD_IN_PROGRESS)
408 printf("%s: could not set up new transfer: %s\n",
409 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
410 }
411
412 sc->sc_initialized = 1;
413 return 0;
414
415cleanup:
416 if (sc->sc_rx_pipeh) {
417 usbd_close_pipe(sc->sc_rx_pipeh);
418 sc->sc_rx_pipeh = NULL((void *)0);
419 }
420 if (sc->sc_tx_pipeh) {
421 usbd_close_pipe(sc->sc_tx_pipeh);
422 sc->sc_tx_pipeh = NULL((void *)0);
423 }
424 bwfm_usb_free_rx_list(sc);
425 bwfm_usb_free_tx_list(sc);
426 return 1;
427}
428
429struct mbuf *
430bwfm_usb_newbuf(void)
431{
432 struct mbuf *m;
433
434 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
435 if (m == NULL((void *)0))
436 return (NULL((void *)0));
437
438 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
439 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
440 m_freem(m);
441 return (NULL((void *)0));
442 }
443
444 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11);
445
446 return (m);
447}
448
449void
450bwfm_usb_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
451{
452 struct bwfm_usb_rx_data *data = priv;
453 struct bwfm_usb_softc *sc = data->sc;
454 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
455 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_ific_ac.ac_if;
456 usbd_status error;
457 struct mbuf *m;
458 uint32_t len;
459
460 DPRINTFN(2, ("%s: %s status %s\n", DEVNAME(sc), __func__,do { ; } while (0)
461 usbd_errstr(status)))do { ; } while (0);
462
463 if (usbd_is_dying(sc->sc_udev))
464 return;
465
466 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
467 usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh);
468 if (status != USBD_CANCELLED)
469 goto resubmit;
470 return;
471 }
472 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
473
474 m = bwfm_usb_newbuf();
475 if (m == NULL((void *)0))
476 goto resubmit;
477
478 memcpy(mtod(m, char *), data->buf, len)__builtin_memcpy((((char *)((m)->m_hdr.mh_data))), (data->
buf), (len))
;
479 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = len;
480 sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, &ml);
481 if_input(ifp, &ml);
482
483resubmit:
484 usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf,
485 BWFM_RXBUFSZ1600, USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0,
486 bwfm_usb_rxeof);
487 error = usbd_transfer(data->xfer);
488 if (error != 0 && error != USBD_IN_PROGRESS)
489 printf("%s: could not set up new transfer: %s\n",
490 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
491}
492
493int
494bwfm_usb_alloc_rx_list(struct bwfm_usb_softc *sc)
495{
496 struct bwfm_usb_rx_data *data;
497 int i, error = 0;
498
499 for (i = 0; i < BWFM_RX_LIST_COUNT50; i++) {
500 data = &sc->sc_rx_data[i];
501
502 data->sc = sc; /* Backpointer for callbacks. */
503
504 data->xfer = usbd_alloc_xfer(sc->sc_udev);
505 if (data->xfer == NULL((void *)0)) {
506 printf("%s: could not allocate xfer\n",
507 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
508 error = ENOMEM12;
509 break;
510 }
511 data->buf = usbd_alloc_buffer(data->xfer, BWFM_RXBUFSZ1600);
512 if (data->buf == NULL((void *)0)) {
513 printf("%s: could not allocate xfer buffer\n",
514 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
515 error = ENOMEM12;
516 break;
517 }
518 }
519 if (error != 0)
520 bwfm_usb_free_rx_list(sc);
521 return (error);
522}
523
524void
525bwfm_usb_free_rx_list(struct bwfm_usb_softc *sc)
526{
527 int i;
528
529 /* NB: Caller must abort pipe first. */
530 for (i = 0; i < BWFM_RX_LIST_COUNT50; i++) {
531 if (sc->sc_rx_data[i].xfer != NULL((void *)0))
532 usbd_free_xfer(sc->sc_rx_data[i].xfer);
533 sc->sc_rx_data[i].xfer = NULL((void *)0);
534 }
535}
536
537int
538bwfm_usb_alloc_tx_list(struct bwfm_usb_softc *sc)
539{
540 struct bwfm_usb_tx_data *data;
541 int i, error = 0;
542
543 TAILQ_INIT(&sc->sc_tx_free_list)do { (&sc->sc_tx_free_list)->tqh_first = ((void *)0
); (&sc->sc_tx_free_list)->tqh_last = &(&sc
->sc_tx_free_list)->tqh_first; } while (0)
;
544 for (i = 0; i < BWFM_TX_LIST_COUNT50; i++) {
545 data = &sc->sc_tx_data[i];
546
547 data->sc = sc; /* Backpointer for callbacks. */
548
549 data->xfer = usbd_alloc_xfer(sc->sc_udev);
550 if (data->xfer == NULL((void *)0)) {
551 printf("%s: could not allocate xfer\n",
552 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
553 error = ENOMEM12;
554 break;
555 }
556 data->buf = usbd_alloc_buffer(data->xfer, BWFM_TXBUFSZ1600);
557 if (data->buf == NULL((void *)0)) {
558 printf("%s: could not allocate xfer buffer\n",
559 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
560 error = ENOMEM12;
561 break;
562 }
563 /* Append this Tx buffer to our free list. */
564 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&sc->sc_tx_free_list)->tqh_last; *(&
sc->sc_tx_free_list)->tqh_last = (data); (&sc->sc_tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
565 }
566 if (error != 0)
567 bwfm_usb_free_tx_list(sc);
568 return (error);
569}
570
571void
572bwfm_usb_free_tx_list(struct bwfm_usb_softc *sc)
573{
574 int i;
575
576 /* NB: Caller must abort pipe first. */
577 for (i = 0; i < BWFM_TX_LIST_COUNT50; i++) {
578 if (sc->sc_tx_data[i].xfer != NULL((void *)0))
579 usbd_free_xfer(sc->sc_tx_data[i].xfer);
580 sc->sc_tx_data[i].xfer = NULL((void *)0);
581 }
582}
583
584void
585bwfm_usb_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
586{
587 struct bwfm_usb_tx_data *data = priv;
588 struct bwfm_usb_softc *sc = data->sc;
589 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_ific_ac.ac_if;
590 int s;
591
592 DPRINTFN(2, ("%s: %s status %s\n", DEVNAME(sc), __func__,do { ; } while (0)
593 usbd_errstr(status)))do { ; } while (0);
594
595 if (usbd_is_dying(sc->sc_udev))
596 return;
597
598 s = splnet()splraise(0x7);
599 /* Put this Tx buffer back to our free list. */
600 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&sc->sc_tx_free_list)->tqh_last; *(&
sc->sc_tx_free_list)->tqh_last = (data); (&sc->sc_tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
601
602 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
603 if (status == USBD_CANCELLED)
604 usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh);
605 ifp->if_oerrorsif_data.ifi_oerrors++;
606 splx(s)spllower(s);
607 return;
608 }
609
610 m_freem(data->mbuf);
611 data->mbuf = NULL((void *)0);
612
613 /* We just released a Tx buffer, notify Tx. */
614 if (ifq_is_oactive(&ifp->if_snd)) {
615 ifq_restart(&ifp->if_snd);
616 }
617 splx(s)spllower(s);
618}
619
620int
621bwfm_usb_detach(struct device *self, int flags)
622{
623 struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self;
624
625 bwfm_detach(&sc->sc_sc, flags);
626
627 if (sc->sc_rx_pipeh != NULL((void *)0))
628 usbd_close_pipe(sc->sc_rx_pipeh);
629 if (sc->sc_tx_pipeh != NULL((void *)0))
630 usbd_close_pipe(sc->sc_tx_pipeh);
631
632 bwfm_usb_free_rx_list(sc);
633 bwfm_usb_free_tx_list(sc);
634
635 return 0;
636}
637
638int
639bwfm_usb_dl_cmd(struct bwfm_usb_softc *sc, uByte cmd, void *buf, int len)
640{
641 usb_device_request_t req;
642 usbd_status error;
643
644 req.bmRequestType = UT_READ_VENDOR_INTERFACE(0x80 | 0x40 | 0x01);
645 req.bRequest = cmd;
646
647 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
648 USETW(req.wIndex, sc->sc_ifaceno)(*(u_int16_t *)(req.wIndex) = (sc->sc_ifaceno));
649 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
650
651 error = usbd_do_request(sc->sc_udev, &req, buf);
652 if (error != 0) {
653 printf("%s: could not read register: %s\n",
654 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
655 }
656 return error;
657}
658
659int
660bwfm_usb_load_microcode(struct bwfm_usb_softc *sc, const u_char *ucode, size_t size)
661{
662 struct trx_header *trx = (struct trx_header *)ucode;
663 struct rdl_state state;
664 uint32_t rdlstate, rdlbytes, sent = 0, sendlen = 0;
665 struct usbd_xfer *xfer;
666 usbd_status error;
667 char *buf;
668
669 if (letoh32(trx->magic)((__uint32_t)(trx->magic)) != TRX_MAGIC0x30524448 ||
670 (letoh32(trx->flag_version)((__uint32_t)(trx->flag_version)) & TRX_UNCOMP_IMAGE0x20) == 0) {
671 printf("%s: invalid firmware\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
672 return 1;
673 }
674
675 bwfm_usb_dl_cmd(sc, DL_START3, &state, sizeof(state));
676 rdlstate = letoh32(state.state)((__uint32_t)(state.state));
677 rdlbytes = letoh32(state.bytes)((__uint32_t)(state.bytes));
678
679 if (rdlstate != DL_WAITING0) {
680 printf("%s: cannot start fw download\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
681 return 1;
682 }
683
684 xfer = usbd_alloc_xfer(sc->sc_udev);
685 if (xfer == NULL((void *)0)) {
686 printf("%s: cannot alloc xfer\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
687 goto err;
688 }
689
690 buf = usbd_alloc_buffer(xfer, TRX_RDL_CHUNK1500);
691 if (buf == NULL((void *)0)) {
692 printf("%s: cannot alloc buf\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
693 goto err;
694 }
695
696 while (rdlbytes != size) {
697 sendlen = MIN(size - sent, TRX_RDL_CHUNK)(((size - sent)<(1500))?(size - sent):(1500));
698 memcpy(buf, ucode + sent, sendlen)__builtin_memcpy((buf), (ucode + sent), (sendlen));
699
700 usbd_setup_xfer(xfer, sc->sc_tx_pipeh, NULL((void *)0), buf, sendlen,
701 USBD_SYNCHRONOUS0x02 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0, NULL((void *)0));
702 error = usbd_transfer(xfer);
703 if (error != 0 && error != USBD_IN_PROGRESS) {
704 printf("%s: transfer error\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
705 goto err;
706 }
707 sent += sendlen;
708
709 bwfm_usb_dl_cmd(sc, DL_GETSTATE0, &state, sizeof(state));
710 rdlstate = letoh32(state.state)((__uint32_t)(state.state));
711 rdlbytes = letoh32(state.bytes)((__uint32_t)(state.bytes));
712
713 if (rdlbytes != sent) {
714 printf("%s: device reported different size\n",
715 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
716 goto err;
717 }
718
719 if (rdlstate == DL_BAD_HDR2 || rdlstate == DL_BAD_CRC3) {
720 printf("%s: device reported bad hdr/crc\n",
721 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
722 goto err;
723 }
724 }
725
726 bwfm_usb_dl_cmd(sc, DL_GETSTATE0, &state, sizeof(state));
727 rdlstate = letoh32(state.state)((__uint32_t)(state.state));
728 rdlbytes = letoh32(state.bytes)((__uint32_t)(state.bytes));
Value stored to 'rdlbytes' is never read
729
730 if (rdlstate != DL_RUNNABLE4) {
731 printf("%s: dongle not runnable\n", DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname));
732 goto err;
733 }
734
735 bwfm_usb_dl_cmd(sc, DL_GO2, &state, sizeof(state));
736
737 return 0;
738err:
739 if (sc->sc_tx_pipeh != NULL((void *)0)) {
740 usbd_close_pipe(sc->sc_tx_pipeh);
741 sc->sc_tx_pipeh = NULL((void *)0);
742 }
743 if (xfer != NULL((void *)0))
744 usbd_free_xfer(xfer);
745 return 1;
746}
747
748int
749bwfm_usb_txcheck(struct bwfm_softc *bwfm)
750{
751 struct bwfm_usb_softc *sc = (void *)bwfm;
752
753 if (TAILQ_EMPTY(&sc->sc_tx_free_list)(((&sc->sc_tx_free_list)->tqh_first) == ((void *)0)
)
)
754 return ENOBUFS55;
755
756 return 0;
757}
758
759int
760bwfm_usb_txdata(struct bwfm_softc *bwfm, struct mbuf *m)
761{
762 struct bwfm_usb_softc *sc = (void *)bwfm;
763 struct bwfm_proto_bcdc_hdr *hdr;
764 struct bwfm_usb_tx_data *data;
765 uint32_t len = 0;
766 int error;
767
768 DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__))do { ; } while (0);
769
770 if (TAILQ_EMPTY(&sc->sc_tx_free_list)(((&sc->sc_tx_free_list)->tqh_first) == ((void *)0)
)
)
771 return ENOBUFS55;
772
773 /* Grab a Tx buffer from our free list. */
774 data = TAILQ_FIRST(&sc->sc_tx_free_list)((&sc->sc_tx_free_list)->tqh_first);
775 TAILQ_REMOVE(&sc->sc_tx_free_list, data, next)do { if (((data)->next.tqe_next) != ((void *)0)) (data)->
next.tqe_next->next.tqe_prev = (data)->next.tqe_prev; else
(&sc->sc_tx_free_list)->tqh_last = (data)->next
.tqe_prev; *(data)->next.tqe_prev = (data)->next.tqe_next
; ((data)->next.tqe_prev) = ((void *)-1); ((data)->next
.tqe_next) = ((void *)-1); } while (0)
;
776
777 hdr = (void *)&data->buf[len];
778 hdr->data_offset = 0;
779 hdr->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m);
780 hdr->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER)(((2) & 0xf) << 4);
781 hdr->flags2 = 0;
782 len += sizeof(*hdr);
783
784 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, (caddr_t)&data->buf[len]);
785 len += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
786
787 data->mbuf = m;
788
789 usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf,
790 len, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0,
791 bwfm_usb_txeof);
792 error = usbd_transfer(data->xfer);
793 if (error != 0 && error != USBD_IN_PROGRESS)
794 printf("%s: could not set up new transfer: %s\n",
795 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
796 return 0;
797}
798
799int
800bwfm_usb_txctl(struct bwfm_softc *bwfm, void *arg)
801{
802 struct bwfm_usb_softc *sc = (void *)bwfm;
803 struct bwfm_proto_bcdc_ctl *ctl = arg;
804 usb_device_request_t req;
805 struct usbd_xfer *xfer;
806 usbd_status error;
807 char *buf;
808
809 DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__))do { ; } while (0);
810
811 /* Send out control packet. */
812 req.bmRequestType = UT_WRITE_CLASS_INTERFACE(0x00 | 0x20 | 0x01);
813 req.bRequest = 0;
814 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
815 USETW(req.wIndex, sc->sc_ifaceno)(*(u_int16_t *)(req.wIndex) = (sc->sc_ifaceno));
816 USETW(req.wLength, ctl->len)(*(u_int16_t *)(req.wLength) = (ctl->len));
817
818 error = usbd_do_request(sc->sc_udev, &req, ctl->buf);
819 if (error != 0) {
820 printf("%s: could not write ctl packet: %s\n",
821 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
822 free(ctl->buf, M_TEMP127, ctl->len);
823 free(ctl, M_TEMP127, sizeof(*ctl));
824 return 1;
825 }
826
827 /* Setup asynchronous receive. */
828 if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
829 free(ctl->buf, M_TEMP127, ctl->len);
830 free(ctl, M_TEMP127, sizeof(*ctl));
831 return 1;
832 }
833 if ((buf = usbd_alloc_buffer(xfer, ctl->len)) == NULL((void *)0)) {
834 free(ctl->buf, M_TEMP127, ctl->len);
835 free(ctl, M_TEMP127, sizeof(*ctl));
836 usbd_free_xfer(xfer);
837 return 1;
838 }
839
840 memset(buf, 0, ctl->len)__builtin_memset((buf), (0), (ctl->len));
841 req.bmRequestType = UT_READ_CLASS_INTERFACE(0x80 | 0x20 | 0x01);
842 req.bRequest = 1;
843 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
844 USETW(req.wIndex, sc->sc_ifaceno)(*(u_int16_t *)(req.wIndex) = (sc->sc_ifaceno));
845 USETW(req.wLength, ctl->len)(*(u_int16_t *)(req.wLength) = (ctl->len));
846
847 error = usbd_request_async(xfer, &req, sc, bwfm_usb_txctl_cb);
848 if (error != 0) {
849 printf("%s: could not read ctl packet: %s\n",
850 DEVNAME(sc)((sc)->sc_sc.sc_dev.dv_xname), usbd_errstr(error));
851 free(ctl->buf, M_TEMP127, ctl->len);
852 free(ctl, M_TEMP127, sizeof(*ctl));
853 return 1;
854 }
855
856 TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next)do { (ctl)->next.tqe_next = ((void *)0); (ctl)->next.tqe_prev
= (&sc->sc_sc.sc_bcdc_rxctlq)->tqh_last; *(&sc
->sc_sc.sc_bcdc_rxctlq)->tqh_last = (ctl); (&sc->
sc_sc.sc_bcdc_rxctlq)->tqh_last = &(ctl)->next.tqe_next
; } while (0)
;
857
858 return 0;
859}
860
861void
862bwfm_usb_txctl_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
863{
864 struct bwfm_usb_softc *sc = priv;
865
866 if (usbd_is_dying(xfer->pipe->device))
867 goto err;
868
869 if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
870 sc->sc_sc.sc_proto_ops->proto_rxctl(&sc->sc_sc,
871 KERNADDR(&xfer->dmabuf, 0)((void *)((char *)((&xfer->dmabuf)->block->kaddr
+ (&xfer->dmabuf)->offs) + (0)))
, xfer->actlen);
872 }
873
874err:
875 usbd_free_xfer(xfer);
876}