diff options
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/files.usb | 5 | ||||
-rw-r--r-- | sys/dev/usb/if_bwfm_usb.c | 698 | ||||
-rw-r--r-- | sys/dev/usb/usbdevs | 7 |
3 files changed, 708 insertions, 2 deletions
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 34cd81b8c4c..551fd9dd356 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,4 +1,4 @@ -# $OpenBSD: files.usb,v 1.133 2017/08/29 03:35:11 deraadt Exp $ +# $OpenBSD: files.usb,v 1.134 2017/10/11 17:19:50 patrick Exp $ # $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. @@ -440,3 +440,6 @@ file dev/usb/upd.c upd device uwacom: hid, hidms, wsmousedev attach uwacom at uhidbus file dev/usb/uwacom.c uwacom + +attach bwfm at uhub with bwfm_usb: firmload +file dev/usb/if_bwfm_usb.c bwfm_usb diff --git a/sys/dev/usb/if_bwfm_usb.c b/sys/dev/usb/if_bwfm_usb.c new file mode 100644 index 00000000000..a90f9634f6d --- /dev/null +++ b/sys/dev/usb/if_bwfm_usb.c @@ -0,0 +1,698 @@ +/* $OpenBSD: if_bwfm_usb.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */ +/* + * Copyright (c) 2010-2016 Broadcom Corporation + * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/device.h> +#include <sys/queue.h> +#include <sys/socket.h> + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#include <net80211/ieee80211_var.h> + +#include <machine/bus.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> +#include <dev/usb/usbdivar.h> +#include <dev/usb/usbdevs.h> + +#include <dev/ic/bwfmvar.h> +#include <dev/ic/bwfmreg.h> + +/* + * Various supported device vendors/products. + */ +static const struct usb_devno bwfm_usbdevs[] = { + { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43143 }, + { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43236 }, + { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43242 }, + { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43569 }, + { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCMFW }, +}; + +#ifdef BWFM_DEBUG +#define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) +#define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) +static int bwfm_debug = 2; +#else +#define DPRINTF(x) do { ; } while (0) +#define DPRINTFN(n, x) do { ; } while (0) +#endif + +#define DEVNAME(sc) ((sc)->sc_sc.sc_dev.dv_xname) + +#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle + * has boot up + */ + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_MAX_OFFSET 3 /* Max number of file offsets */ +#define TRX_UNCOMP_IMAGE 0x20 /* Trx holds uncompressed img */ +#define TRX_RDL_CHUNK 1500 /* size of each dl transfer */ +#define TRX_OFFSETS_DLFWLEN_IDX 0 + +/* Control messages: bRequest values */ +#define DL_GETSTATE 0 /* returns the rdl_state_t struct */ +#define DL_CHECK_CRC 1 /* currently unused */ +#define DL_GO 2 /* execute downloaded image */ +#define DL_START 3 /* initialize dl state */ +#define DL_REBOOT 4 /* reboot the device in 2 seconds */ +#define DL_GETVER 5 /* returns the bootrom_id_t struct */ +#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset + * event to occur in 2 seconds. It is the + * responsibility of the downloaded code to + * clear this event + */ +#define DL_EXEC 7 /* jump to a supplied address */ +#define DL_RESETCFG 8 /* To support single enum on dongle + * - Not used by bootloader + */ +#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup + * if resp unavailable + */ + +/* states */ +#define DL_WAITING 0 /* waiting to rx first pkt */ +#define DL_READY 1 /* hdr was good, waiting for more of the + * compressed image + */ +#define DL_BAD_HDR 2 /* hdr was corrupted */ +#define DL_BAD_CRC 3 /* compressed image was corrupted */ +#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ +#define DL_START_FAIL 5 /* failed to initialize correctly */ +#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM + * value + */ +#define DL_IMAGE_TOOBIG 7 /* firmware image too big */ + + +struct trx_header { + uint32_t magic; /* "HDR0" */ + uint32_t len; /* Length of file including header */ + uint32_t crc32; /* CRC from flag_version to end of file */ + uint32_t flag_version; /* 0:15 flags, 16:31 version */ + uint32_t offsets[TRX_MAX_OFFSET];/* Offsets of partitions from start of + * header + */ +}; + +struct rdl_state { + uint32_t state; + uint32_t bytes; +}; + +struct bootrom_id { + uint32_t chip; /* Chip id */ + uint32_t chiprev; /* Chip rev */ + uint32_t ramsize; /* Size of RAM */ + uint32_t remapbase; /* Current remap base address */ + uint32_t boardtype; /* Type of board */ + uint32_t boardrev; /* Board revision */ +}; + +#define BWFM_RXBUFSZ 1600 +#define BWFM_TXBUFSZ 1600 +struct bwfm_usb_softc { + struct bwfm_softc sc_sc; + struct usbd_device *sc_udev; + struct usbd_interface *sc_iface; + uint8_t sc_ifaceno; + + uint16_t sc_vendor; + uint16_t sc_product; + + uint32_t sc_chip; + uint32_t sc_chiprev; + + int sc_rx_no; + int sc_tx_no; + + struct usbd_pipe *sc_rx_pipeh; + struct usbd_pipe *sc_tx_pipeh; + + struct usbd_xfer *sc_rx_xfer; + char *sc_rx_buf; + + struct usbd_xfer *sc_tx_xfer; + char *sc_tx_buf; +}; + +int bwfm_usb_match(struct device *, void *, void *); +void bwfm_usb_attachhook(struct device *); +void bwfm_usb_attach(struct device *, struct device *, void *); +int bwfm_usb_detach(struct device *, int); + +int bwfm_usb_dl_cmd(struct bwfm_usb_softc *, uint8_t, void *, int); +int bwfm_usb_load_microcode(struct bwfm_usb_softc *, const u_char *, + size_t); + +int bwfm_usb_txdata(struct bwfm_softc *, struct mbuf *); +int bwfm_usb_txctl(struct bwfm_softc *, char *, size_t); +int bwfm_usb_rxctl(struct bwfm_softc *, char *, size_t *); + +void bwfm_usb_rxeof(struct usbd_xfer *, void *, usbd_status); +void bwfm_usb_txeof(struct usbd_xfer *, void *, usbd_status); + +struct bwfm_bus_ops bwfm_usb_bus_ops = { + .bs_init = NULL, + .bs_stop = NULL, + .bs_txdata = bwfm_usb_txdata, + .bs_txctl = bwfm_usb_txctl, + .bs_rxctl = bwfm_usb_rxctl, +}; + +struct cfattach bwfm_usb_ca = { + sizeof(struct bwfm_usb_softc), + bwfm_usb_match, + bwfm_usb_attach, + bwfm_usb_detach, +}; + +int +bwfm_usb_match(struct device *parent, void *match, void *aux) +{ + struct usb_attach_arg *uaa = aux; + + if (uaa->iface == NULL || uaa->configno != 1) + return UMATCH_NONE; + + return (usb_lookup(bwfm_usbdevs, uaa->vendor, uaa->product) != NULL) ? + UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE; +} + +void +bwfm_usb_attach(struct device *parent, struct device *self, void *aux) +{ + struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self; + struct usb_attach_arg *uaa = aux; + usb_device_descriptor_t *dd; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + int i; + + sc->sc_udev = uaa->device; + sc->sc_iface = uaa->iface; + sc->sc_ifaceno = uaa->ifaceno; + sc->sc_vendor = uaa->vendor; + sc->sc_product = uaa->product; + sc->sc_sc.sc_bus_ops = &bwfm_usb_bus_ops; + sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; + + /* Check number of configurations. */ + dd = usbd_get_device_descriptor(sc->sc_udev); + if (dd->bNumConfigurations != 1) { + printf("%s: number of configurations not supported\n", + DEVNAME(sc)); + return; + } + + /* Get endpoints. */ + id = usbd_get_interface_descriptor(sc->sc_iface); + + sc->sc_rx_no = sc->sc_tx_no = -1; + for (i = 0; i < id->bNumEndpoints; i++) { + ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); + if (ed == NULL) { + printf("%s: no endpoint descriptor for iface %d\n", + DEVNAME(sc), i); + return; + } + + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && + sc->sc_rx_no == -1) + sc->sc_rx_no = ed->bEndpointAddress; + else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && + sc->sc_tx_no == -1) + sc->sc_tx_no = ed->bEndpointAddress; + } + if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) { + printf("%s: missing endpoint\n", DEVNAME(sc)); + return; + } + + config_mountroot(self, bwfm_usb_attachhook); +} + +void +bwfm_usb_attachhook(struct device *self) +{ + struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self; + const char *name = NULL; + struct bootrom_id brom; + usbd_status error; + u_char *ucode; + size_t size; + int i; + + /* Read chip id and chip rev to check the firmware. */ + memset(&brom, 0, sizeof(brom)); + bwfm_usb_dl_cmd(sc, DL_GETVER, &brom, sizeof(brom)); + sc->sc_chip = letoh32(brom.chip); + sc->sc_chiprev = letoh32(brom.chiprev); + + /* Setup data pipes */ + error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, + &sc->sc_rx_pipeh); + if (error != 0) { + printf("%s: could not open rx pipe: %s\n", + DEVNAME(sc), usbd_errstr(error)); + return; + } + error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, + &sc->sc_tx_pipeh); + if (error != 0) { + printf("%s: could not open tx pipe: %s\n", + DEVNAME(sc), usbd_errstr(error)); + return; + } + + /* Firmware not yet loaded? */ + if (sc->sc_chip != BRCMF_POSTBOOT_ID) { + switch (sc->sc_chip) + { + case BRCM_CC_43143_CHIP_ID: + name = "brcmfmac43143.bin"; + break; + case BRCM_CC_43235_CHIP_ID: + case BRCM_CC_43236_CHIP_ID: + case BRCM_CC_43238_CHIP_ID: + if (sc->sc_chiprev == 3) + name = "brcmfmac43236b.bin"; + break; + case BRCM_CC_43242_CHIP_ID: + name = "brcmfmac43242a.bin"; + break; + case BRCM_CC_43566_CHIP_ID: + case BRCM_CC_43569_CHIP_ID: + name = "brcmfmac43569.bin"; + break; + default: + break; + } + + if (name == NULL) { + printf("%s: unknown firmware\n", DEVNAME(sc)); + return; + } + + if (loadfirmware(name, &ucode, &size) != 0) { + printf("%s: failed loadfirmware of file %s\n", + DEVNAME(sc), name); + return; + } + + if (bwfm_usb_load_microcode(sc, ucode, size) != 0) { + printf("%s: could not load microcode\n", + DEVNAME(sc)); + return; + } + + free(ucode, M_DEVBUF, 0); + + for (i = 0; i < 10; i++) { + delay(100 * 1000); + memset(&brom, 0, sizeof(brom)); + bwfm_usb_dl_cmd(sc, DL_GETVER, &brom, sizeof(brom)); + if (letoh32(brom.chip) == BRCMF_POSTBOOT_ID) + break; + } + + if (letoh32(brom.chip) != BRCMF_POSTBOOT_ID) { + printf("%s: firmware did not start up\n", + DEVNAME(sc)); + return; + } + + sc->sc_chip = letoh32(brom.chip); + sc->sc_chiprev = letoh32(brom.chiprev); + printf("%s: firmware loaded\n", DEVNAME(sc)); + } + + bwfm_usb_dl_cmd(sc, DL_RESETCFG, &brom, sizeof(brom)); + + sc->sc_rx_xfer = usbd_alloc_xfer(sc->sc_udev); + if (sc->sc_rx_xfer == NULL) { + printf("%s: cannot alloc xfer\n", DEVNAME(sc)); + return; + } + + sc->sc_rx_buf = usbd_alloc_buffer(sc->sc_rx_xfer, BWFM_RXBUFSZ); + if (sc->sc_rx_buf == NULL) { + printf("%s: cannot alloc buf\n", DEVNAME(sc)); + return; + } + usbd_setup_xfer(sc->sc_rx_xfer, sc->sc_rx_pipeh, sc, sc->sc_rx_buf, + BWFM_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, + bwfm_usb_rxeof); + error = usbd_transfer(sc->sc_rx_xfer); + if (error != 0 && error != USBD_IN_PROGRESS) + printf("%s: could not set up new transfer: %s\n", + DEVNAME(sc), usbd_errstr(error)); + + sc->sc_tx_xfer = usbd_alloc_xfer(sc->sc_udev); + if (sc->sc_tx_xfer == NULL) { + printf("%s: cannot alloc xfer\n", DEVNAME(sc)); + return; + } + + sc->sc_tx_buf = usbd_alloc_buffer(sc->sc_tx_xfer, BWFM_TXBUFSZ); + if (sc->sc_tx_buf == NULL) { + printf("%s: cannot alloc buf\n", DEVNAME(sc)); + return; + } + + bwfm_attach(&sc->sc_sc); +} + +void +bwfm_usb_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) +{ + struct bwfm_usb_softc *sc = priv; + struct bwfm_proto_bcdc_hdr *hdr; + usbd_status error; + uint32_t len, off; + + DPRINTFN(2, ("%s: %s status %s\n", DEVNAME(sc), __func__, + usbd_errstr(status))); + + if (usbd_is_dying(sc->sc_udev)) + return; + + if (__predict_false(status != USBD_NORMAL_COMPLETION)) { + usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); + if (status != USBD_CANCELLED) + goto resubmit; + return; + } + usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); + + hdr = (void *)sc->sc_rx_buf; + if (len < sizeof(*hdr)) + return; + len -= sizeof(*hdr); + off += sizeof(*hdr); + if (len < hdr->data_offset << 2) + return; + len -= hdr->data_offset << 2; + off += hdr->data_offset << 2; + + bwfm_rx(&sc->sc_sc, &sc->sc_rx_buf[off], len); + + usbd_setup_xfer(sc->sc_rx_xfer, sc->sc_rx_pipeh, sc, sc->sc_rx_buf, + BWFM_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, + bwfm_usb_rxeof); + +resubmit: + error = usbd_transfer(sc->sc_rx_xfer); + if (error != 0 && error != USBD_IN_PROGRESS) + printf("%s: could not set up new transfer: %s\n", + DEVNAME(sc), usbd_errstr(error)); +} + +void +bwfm_usb_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) +{ + struct bwfm_usb_softc *sc = priv; + usbd_status error; + + DPRINTFN(2, ("%s: %s status %s\n", DEVNAME(sc), __func__, + usbd_errstr(status))); + + if (usbd_is_dying(sc->sc_udev)) + return; + + if (__predict_false(status != USBD_NORMAL_COMPLETION)) { + usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh); + if (status != USBD_CANCELLED) + goto resubmit; + return; + } + + // FIXME: leak + //m_freem(m); + return; + +resubmit: + error = usbd_transfer(sc->sc_tx_xfer); + if (error != 0 && error != USBD_IN_PROGRESS) + printf("%s: could not set up new transfer: %s\n", + DEVNAME(sc), usbd_errstr(error)); +} + +int +bwfm_usb_detach(struct device *self, int flags) +{ + struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self; + + bwfm_detach(&sc->sc_sc, flags); + + if (sc->sc_rx_pipeh != NULL) { + usbd_abort_pipe(sc->sc_rx_pipeh); + usbd_close_pipe(sc->sc_rx_pipeh); + } + if (sc->sc_tx_pipeh != NULL) { + usbd_abort_pipe(sc->sc_tx_pipeh); + usbd_close_pipe(sc->sc_tx_pipeh); + } + + return 0; +} + +int +bwfm_usb_dl_cmd(struct bwfm_usb_softc *sc, uByte cmd, void *buf, int len) +{ + usb_device_request_t req; + usbd_status error; + + req.bmRequestType = UT_READ_VENDOR_INTERFACE; + req.bRequest = cmd; + + USETW(req.wValue, 0); + USETW(req.wIndex, sc->sc_ifaceno); + USETW(req.wLength, len); + + error = usbd_do_request(sc->sc_udev, &req, buf); + if (error != 0) { + printf("%s: could not read register: %s\n", + DEVNAME(sc), usbd_errstr(error)); + } + return error; +} + +int +bwfm_usb_load_microcode(struct bwfm_usb_softc *sc, const u_char *ucode, size_t size) +{ + struct trx_header *trx = (struct trx_header *)ucode; + struct rdl_state state; + uint32_t rdlstate, rdlbytes, sent = 0, sendlen = 0; + struct usbd_xfer *xfer; + usbd_status error; + char *buf; + + if (letoh32(trx->magic) != TRX_MAGIC || + (letoh32(trx->flag_version) & TRX_UNCOMP_IMAGE) == 0) { + printf("%s: invalid firmware\n", DEVNAME(sc)); + return 1; + } + + bwfm_usb_dl_cmd(sc, DL_START, &state, sizeof(state)); + rdlstate = letoh32(state.state); + rdlbytes = letoh32(state.bytes); + + if (rdlstate != DL_WAITING) { + printf("%s: cannot start fw download\n", DEVNAME(sc)); + return 1; + } + + xfer = usbd_alloc_xfer(sc->sc_udev); + if (xfer == NULL) { + printf("%s: cannot alloc xfer\n", DEVNAME(sc)); + goto err; + } + + buf = usbd_alloc_buffer(xfer, TRX_RDL_CHUNK); + if (buf == NULL) { + printf("%s: cannot alloc buf\n", DEVNAME(sc)); + goto err; + } + + while (rdlbytes != size) { + sendlen = MIN(size - sent, TRX_RDL_CHUNK); + memcpy(buf, ucode + sent, sendlen); + + usbd_setup_xfer(xfer, sc->sc_tx_pipeh, NULL, buf, sendlen, + USBD_SYNCHRONOUS | USBD_NO_COPY, USBD_NO_TIMEOUT, NULL); + error = usbd_transfer(xfer); + if (error != 0 && error != USBD_IN_PROGRESS) { + printf("%s: transfer error\n", DEVNAME(sc)); + goto err; + } + sent += sendlen; + + bwfm_usb_dl_cmd(sc, DL_GETSTATE, &state, sizeof(state)); + rdlstate = letoh32(state.state); + rdlbytes = letoh32(state.bytes); + + if (rdlbytes != sent) { + printf("%s: device reported different size\n", + DEVNAME(sc)); + goto err; + } + + if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) { + printf("%s: device reported bad hdr/crc\n", + DEVNAME(sc)); + goto err; + } + } + + bwfm_usb_dl_cmd(sc, DL_GETSTATE, &state, sizeof(state)); + rdlstate = letoh32(state.state); + rdlbytes = letoh32(state.bytes); + + if (rdlstate != DL_RUNNABLE) { + printf("%s: dongle not runnable\n", DEVNAME(sc)); + goto err; + } + + bwfm_usb_dl_cmd(sc, DL_GO, &state, sizeof(state)); + + return 0; +err: + if (sc->sc_tx_pipeh != NULL) { + usbd_abort_pipe(sc->sc_tx_pipeh); + usbd_close_pipe(sc->sc_tx_pipeh); + sc->sc_tx_pipeh = NULL; + } + if (xfer != NULL) + usbd_free_xfer(xfer); + return 1; +} + +int +bwfm_usb_txdata(struct bwfm_softc *bwfm, struct mbuf *m) +{ + struct bwfm_usb_softc *sc = (void *)bwfm; + struct bwfm_proto_bcdc_hdr *hdr; + uint32_t len = 0; + int error; + + DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__)); + + hdr = (void *)&sc->sc_tx_buf[len]; + hdr->data_offset = 0; + hdr->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER); + len += sizeof(*hdr); + + m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&sc->sc_tx_buf[len]); + len += m->m_pkthdr.len; + //m_freem(m); + + usbd_setup_xfer(sc->sc_tx_xfer, sc->sc_tx_pipeh, sc, sc->sc_tx_buf, + len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, USBD_NO_TIMEOUT, + bwfm_usb_txeof); + error = usbd_transfer(sc->sc_tx_xfer); + if (error != 0 && error != USBD_IN_PROGRESS) + printf("%s: could not set up new transfer: %s\n", + DEVNAME(sc), usbd_errstr(error)); + return 0; +} + +int +bwfm_usb_txctl(struct bwfm_softc *bwfm, char *buf, size_t len) +{ + struct bwfm_usb_softc *sc = (void *)bwfm; + usb_device_request_t req; + usbd_status error; + int ret = 1; + + DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__)); + + req.bmRequestType = UT_WRITE_CLASS_INTERFACE; + req.bRequest = 0; + + USETW(req.wValue, 0); + USETW(req.wIndex, sc->sc_ifaceno); + USETW(req.wLength, len); + + error = usbd_do_request(sc->sc_udev, &req, buf); + if (error != 0) { + printf("%s: could not read ctl packet: %s\n", + DEVNAME(sc), usbd_errstr(error)); + goto err; + } + + ret = 0; +err: + return ret; +} + +int +bwfm_usb_rxctl(struct bwfm_softc *bwfm, char *buf, size_t *len) +{ + struct bwfm_usb_softc *sc = (void *)bwfm; + usb_device_request_t req; + usbd_status error; + uint32_t len32; + int ret = 1; + + DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__)); + + req.bmRequestType = UT_READ_CLASS_INTERFACE; + req.bRequest = 1; + + USETW(req.wValue, 0); + USETW(req.wIndex, sc->sc_ifaceno); + USETW(req.wLength, *len); + + error = usbd_do_request_flags(sc->sc_udev, &req, buf, 0, + &len32, USBD_DEFAULT_TIMEOUT); + if (error != 0) { + printf("%s: could not read ctl packet: %s\n", + DEVNAME(sc), usbd_errstr(error)); + goto err; + } + + if (len32 > *len) { + printf("%s: broken length\n", DEVNAME(sc)); + goto err; + } + + *len = len32; + ret = 0; +err: + return ret; +} diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 46811894b25..8a8a4706c4d 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1,4 +1,4 @@ -$OpenBSD: usbdevs,v 1.677 2017/08/26 12:45:16 abieber Exp $ +$OpenBSD: usbdevs,v 1.678 2017/10/11 17:19:50 patrick Exp $ /* $NetBSD: usbdevs,v 1.322 2003/05/10 17:47:14 hamajima Exp $ */ /* @@ -1239,8 +1239,13 @@ product BILLIONTON USBE100 0x8511 USBE100 product BILLIONTON USB2AR 0x90ff USB2AR Ethernet /* Broadcom products */ +product BROADCOM BCMFW 0x0bdc BCMFW product BROADCOM BCM2033 0x2000 BCM2033 product BROADCOM BCM2033NF 0x2033 BCM2033 (no fw) +product BROADCOM BCM43236 0xbd17 BCM43236 +product BROADCOM BCM43143 0xbd1e BCM43143 +product BROADCOM BCM43242 0xbd1f BCM43242 +product BROADCOM BCM43569 0xbd27 BCM43569 /* Brother Industries products */ product BROTHER HL1050 0x0002 HL-1050 laser printer |