diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-21 13:47:02 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:41 +0200 |
commit | bcdce02d9bc8150e1d191ed5ca9da45b7604964a (patch) | |
tree | 3b2faf509db7672ee1fc98857736470be97e7ed8 /freebsd/sys/dev/usb | |
parent | Update to FreeBSD head 2018-04-01 (diff) | |
download | rtems-libbsd-bcdce02d9bc8150e1d191ed5ca9da45b7604964a.tar.bz2 |
Update to FreeBSD head 2018-06-01
Git mirror commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9.
Update #3472.
Diffstat (limited to 'freebsd/sys/dev/usb')
24 files changed, 260 insertions, 101 deletions
diff --git a/freebsd/sys/dev/usb/input/ukbd.c b/freebsd/sys/dev/usb/input/ukbd.c index 5cb2636c..76fe76b6 100644 --- a/freebsd/sys/dev/usb/input/ukbd.c +++ b/freebsd/sys/dev/usb/input/ukbd.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf */ -#include <rtems/bsd/local/opt_compat.h> #include <rtems/bsd/local/opt_kbd.h> #include <rtems/bsd/local/opt_ukbd.h> #include <rtems/bsd/local/opt_evdev.h> diff --git a/freebsd/sys/dev/usb/input/usb_rdesc.h b/freebsd/sys/dev/usb/input/usb_rdesc.h index 00eea122..889381e8 100644 --- a/freebsd/sys/dev/usb/input/usb_rdesc.h +++ b/freebsd/sys/dev/usb/input/usb_rdesc.h @@ -276,3 +276,31 @@ 0x81, 0x01, /* INPUT (Constant) */\ 0xc0 /* END COLLECTION */\ +/* Fixed report descriptor for Super Nintendo gamepads */ +#define UHID_SNES_REPORT_DESCR(...) \ + 0x05, 0x01, /* Usage Page (Desktop), */\ + 0x09, 0x04, /* Usage (Joystik), */\ + 0xA1, 0x01, /* Collection (Application), */\ + 0xA1, 0x02, /* Collection (Logical), */\ + 0x14, /* Logical Minimum (0), */\ + 0x75, 0x08, /* Report Size (8), */\ + 0x95, 0x03, /* Report Count (3), */\ + 0x81, 0x01, /* Input (Constant), */\ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */\ + 0x95, 0x02, /* Report Count (2), */\ + 0x09, 0x30, /* Usage (X), */\ + 0x09, 0x31, /* Usage (Y), */\ + 0x81, 0x02, /* Input (Variable), */\ + 0x75, 0x01, /* Report Size (1), */\ + 0x95, 0x04, /* Report Count (4), */\ + 0x81, 0x01, /* Input (Constant), */\ + 0x25, 0x01, /* Logical Maximum (1), */\ + 0x95, 0x0A, /* Report Count (10), */\ + 0x05, 0x09, /* Usage Page (Button), */\ + 0x19, 0x01, /* Usage Minimum (01h), */\ + 0x29, 0x0A, /* Usage Maximum (0Ah), */\ + 0x81, 0x02, /* Input (Variable), */\ + 0x95, 0x0A, /* Report Count (10), */\ + 0x81, 0x01, /* Input (Constant), */\ + 0xC0, /* End Collection, */\ + 0xC0 /* End Collection */ diff --git a/freebsd/sys/dev/usb/net/if_aue.c b/freebsd/sys/dev/usb/net/if_aue.c index 69951b70..5454e2aa 100644 --- a/freebsd/sys/dev/usb/net/if_aue.c +++ b/freebsd/sys/dev/usb/net/if_aue.c @@ -557,7 +557,7 @@ aue_setmulti(struct usb_ether *ue) /* now program new ones */ if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; h = ether_crc32_le(LLADDR((struct sockaddr_dl *) diff --git a/freebsd/sys/dev/usb/net/if_axe.c b/freebsd/sys/dev/usb/net/if_axe.c index b77292ba..cf54e96e 100644 --- a/freebsd/sys/dev/usb/net/if_axe.c +++ b/freebsd/sys/dev/usb/net/if_axe.c @@ -504,7 +504,7 @@ axe_setmulti(struct usb_ether *ue) rxmode &= ~AXE_RXCMD_ALLMULTI; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; diff --git a/freebsd/sys/dev/usb/net/if_axge.c b/freebsd/sys/dev/usb/net/if_axge.c index 575571e4..f8ed34ae 100644 --- a/freebsd/sys/dev/usb/net/if_axge.c +++ b/freebsd/sys/dev/usb/net/if_axge.c @@ -788,7 +788,7 @@ axge_rxfilter(struct usb_ether *ue) rxmode |= RCR_ACPT_MCAST; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; h = ether_crc32_be(LLADDR((struct sockaddr_dl *) diff --git a/freebsd/sys/dev/usb/net/if_cue.c b/freebsd/sys/dev/usb/net/if_cue.c index 63846a01..f184fa24 100644 --- a/freebsd/sys/dev/usb/net/if_cue.c +++ b/freebsd/sys/dev/usb/net/if_cue.c @@ -330,7 +330,7 @@ cue_setmulti(struct usb_ether *ue) /* now program new ones */ if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; diff --git a/freebsd/sys/dev/usb/net/if_kue.c b/freebsd/sys/dev/usb/net/if_kue.c index 255a83bb..35fd3fcf 100644 --- a/freebsd/sys/dev/usb/net/if_kue.c +++ b/freebsd/sys/dev/usb/net/if_kue.c @@ -379,7 +379,7 @@ kue_setmulti(struct usb_ether *ue) sc->sc_rxfilt &= ~KUE_RXFILT_ALLMULTI; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; diff --git a/freebsd/sys/dev/usb/net/if_mos.c b/freebsd/sys/dev/usb/net/if_mos.c index ad7bfcce..3dd0e5ef 100644 --- a/freebsd/sys/dev/usb/net/if_mos.c +++ b/freebsd/sys/dev/usb/net/if_mos.c @@ -608,7 +608,7 @@ mos_setmulti(struct usb_ether *ue) /* get all new ones */ if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) { allmulti = 1; continue; diff --git a/freebsd/sys/dev/usb/net/if_rue.c b/freebsd/sys/dev/usb/net/if_rue.c index 7b062755..810a98c8 100644 --- a/freebsd/sys/dev/usb/net/if_rue.c +++ b/freebsd/sys/dev/usb/net/if_rue.c @@ -502,7 +502,7 @@ rue_setmulti(struct usb_ether *ue) /* now program new ones */ if_maddr_rlock(ifp); - TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) + CK_STAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; diff --git a/freebsd/sys/dev/usb/net/if_smsc.c b/freebsd/sys/dev/usb/net/if_smsc.c index 88ecb618..87e181d8 100644 --- a/freebsd/sys/dev/usb/net/if_smsc.c +++ b/freebsd/sys/dev/usb/net/if_smsc.c @@ -454,7 +454,7 @@ smsc_miibus_readreg(device_t dev, int phy, int reg) goto done; } - addr = (phy << 11) | (reg << 6) | SMSC_MII_READ; + addr = (phy << 11) | (reg << 6) | SMSC_MII_READ | SMSC_MII_BUSY; smsc_write_reg(sc, SMSC_MII_ADDR, addr); if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) @@ -507,7 +507,7 @@ smsc_miibus_writereg(device_t dev, int phy, int reg, int val) val = htole32(val); smsc_write_reg(sc, SMSC_MII_DATA, val); - addr = (phy << 11) | (reg << 6) | SMSC_MII_WRITE; + addr = (phy << 11) | (reg << 6) | SMSC_MII_WRITE | SMSC_MII_BUSY; smsc_write_reg(sc, SMSC_MII_ADDR, addr); if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) @@ -716,14 +716,14 @@ smsc_setmulti(struct usb_ether *ue) /* Take the lock of the mac address list before hashing each of them */ if_maddr_rlock(ifp); - if (!TAILQ_EMPTY(&ifp->if_multiaddrs)) { + if (!CK_STAILQ_EMPTY(&ifp->if_multiaddrs)) { /* We are filtering on a set of address so calculate hashes of each * of the address and set the corresponding bits in the register. */ sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT; sc->sc_mac_csr &= ~(SMSC_MAC_CSR_PRMS | SMSC_MAC_CSR_MCPAS); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1308,7 +1308,7 @@ smsc_phy_init(struct smsc_softc *sc) do { uether_pause(&sc->sc_ue, hz / 100); bmcr = smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR); - } while ((bmcr & MII_BMCR) && ((ticks - start_ticks) < max_ticks)); + } while ((bmcr & BMCR_RESET) && ((ticks - start_ticks) < max_ticks)); if (((usb_ticks_t)(ticks - start_ticks)) >= max_ticks) { smsc_err_printf(sc, "PHY reset timed-out"); diff --git a/freebsd/sys/dev/usb/net/if_udav.c b/freebsd/sys/dev/usb/net/if_udav.c index 21019265..a4e683ac 100644 --- a/freebsd/sys/dev/usb/net/if_udav.c +++ b/freebsd/sys/dev/usb/net/if_udav.c @@ -524,7 +524,7 @@ udav_setmulti(struct usb_ether *ue) /* now program new ones */ if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c index 0e45a6c9..8a88feae 100644 --- a/freebsd/sys/dev/usb/net/if_ure.c +++ b/freebsd/sys/dev/usb/net/if_ure.c @@ -797,7 +797,7 @@ ure_rxfilter(struct usb_ether *ue) rxmode |= URE_RCR_AM; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; h = ether_crc32_be(LLADDR((struct sockaddr_dl *) diff --git a/freebsd/sys/dev/usb/net/usb_ethernet.c b/freebsd/sys/dev/usb/net/usb_ethernet.c index 842e7987..9ce60eff 100644 --- a/freebsd/sys/dev/usb/net/usb_ethernet.c +++ b/freebsd/sys/dev/usb/net/usb_ethernet.c @@ -192,6 +192,17 @@ error: return (error); } +void +uether_ifattach_wait(struct usb_ether *ue) +{ + + UE_LOCK(ue); + usb_proc_mwait(&ue->ue_tq, + &ue->ue_sync_task[0].hdr, + &ue->ue_sync_task[1].hdr); + UE_UNLOCK(ue); +} + static void ue_attach_post_task(struct usb_proc_msg *_task) { diff --git a/freebsd/sys/dev/usb/net/usb_ethernet.h b/freebsd/sys/dev/usb/net/usb_ethernet.h index c7afc650..9839db16 100644 --- a/freebsd/sys/dev/usb/net/usb_ethernet.h +++ b/freebsd/sys/dev/usb/net/usb_ethernet.h @@ -113,6 +113,7 @@ struct ifnet *uether_getifp(struct usb_ether *); struct mii_data *uether_getmii(struct usb_ether *); void *uether_getsc(struct usb_ether *); int uether_ifattach(struct usb_ether *); +void uether_ifattach_wait(struct usb_ether *); void uether_ifdetach(struct usb_ether *); int uether_ifmedia_upd(struct ifnet *); void uether_init(void *); diff --git a/freebsd/sys/dev/usb/serial/uchcom.c b/freebsd/sys/dev/usb/serial/uchcom.c index 1e741ccd..24cb8433 100644 --- a/freebsd/sys/dev/usb/serial/uchcom.c +++ b/freebsd/sys/dev/usb/serial/uchcom.c @@ -124,11 +124,11 @@ SYSCTL_INT(_hw_usb_uchcom, OID_AUTO, debug, CTLFLAG_RWTUN, #define UCHCOM_REG_BPS_MOD 0x14 #define UCHCOM_REG_BPS_PAD 0x0F #define UCHCOM_REG_BREAK1 0x05 -#define UCHCOM_REG_BREAK2 0x18 #define UCHCOM_REG_LCR1 0x18 #define UCHCOM_REG_LCR2 0x25 #define UCHCOM_VER_20 0x20 +#define UCHCOM_VER_30 0x30 #define UCHCOM_BASE_UNKNOWN 0 #define UCHCOM_BPS_MOD_BASE 20000000 @@ -137,12 +137,14 @@ SYSCTL_INT(_hw_usb_uchcom, OID_AUTO, debug, CTLFLAG_RWTUN, #define UCHCOM_DTR_MASK 0x20 #define UCHCOM_RTS_MASK 0x40 -#define UCHCOM_BRK1_MASK 0x01 -#define UCHCOM_BRK2_MASK 0x40 +#define UCHCOM_BRK_MASK 0x01 #define UCHCOM_LCR1_MASK 0xAF #define UCHCOM_LCR2_MASK 0x07 -#define UCHCOM_LCR1_PARENB 0x80 +#define UCHCOM_LCR1_RX 0x80 +#define UCHCOM_LCR1_TX 0x40 +#define UCHCOM_LCR1_PARENB 0x08 +#define UCHCOM_LCR1_CS8 0x03 #define UCHCOM_LCR2_PAREVEN 0x07 #define UCHCOM_LCR2_PARODD 0x06 #define UCHCOM_LCR2_PARMARK 0x05 @@ -324,13 +326,17 @@ uchcom_attach(device_t dev) sc->sc_udev = uaa->device; - switch (uaa->info.bcdDevice) { - case UCHCOM_REV_CH340: + switch (uaa->info.idProduct) { + case USB_PRODUCT_WCH2_CH341SER: device_printf(dev, "CH340 detected\n"); break; - default: + case USB_PRODUCT_WCH2_CH341SER_2: device_printf(dev, "CH341 detected\n"); break; + default: + device_printf(dev, "New CH340/CH341 product 0x%04x detected\n", + uaa->info.idProduct); + break; } iface_index = UCHCOM_IFACE_INDEX; @@ -414,6 +420,8 @@ uchcom_ctrl_write(struct uchcom_softc *sc, uint8_t reqno, USETW(req.wIndex, index); USETW(req.wLength, 0); + DPRINTF("WR REQ 0x%02X VAL 0x%04X IDX 0x%04X\n", + reqno, value, index); ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000); } @@ -430,6 +438,8 @@ uchcom_ctrl_read(struct uchcom_softc *sc, uint8_t reqno, USETW(req.wIndex, index); USETW(req.wLength, buflen); + DPRINTF("RD REQ 0x%02X VAL 0x%04X IDX 0x%04X LEN %d\n", + reqno, value, index, buflen); ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, buf, USB_SHORT_XFER_OK, 1000); } @@ -504,6 +514,7 @@ static void uchcom_update_version(struct uchcom_softc *sc) { uchcom_get_version(sc, &sc->sc_version); + DPRINTF("Chip version: 0x%02x\n", sc->sc_version); } static void @@ -549,17 +560,17 @@ uchcom_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff) uint8_t brk1; uint8_t brk2; - uchcom_read_reg(sc, UCHCOM_REG_BREAK1, &brk1, UCHCOM_REG_BREAK2, &brk2); + uchcom_read_reg(sc, UCHCOM_REG_BREAK1, &brk1, UCHCOM_REG_LCR1, &brk2); if (onoff) { /* on - clear bits */ - brk1 &= ~UCHCOM_BRK1_MASK; - brk2 &= ~UCHCOM_BRK2_MASK; + brk1 &= ~UCHCOM_BRK_MASK; + brk2 &= ~UCHCOM_LCR1_TX; } else { /* off - set bits */ - brk1 |= UCHCOM_BRK1_MASK; - brk2 |= UCHCOM_BRK2_MASK; + brk1 |= UCHCOM_BRK_MASK; + brk2 |= UCHCOM_LCR1_TX; } - uchcom_write_reg(sc, UCHCOM_REG_BREAK1, brk1, UCHCOM_REG_BREAK2, brk2); + uchcom_write_reg(sc, UCHCOM_REG_BREAK1, brk1, UCHCOM_REG_LCR1, brk2); } static int @@ -611,8 +622,12 @@ uchcom_set_baudrate(struct uchcom_softc *sc, uint32_t rate) if (uchcom_calc_divider_settings(&dv, rate)) return; + /* + * According to linux code we need to set bit 7 of UCHCOM_REG_BPS_PRE, + * otherwise the chip will buffer data. + */ uchcom_write_reg(sc, - UCHCOM_REG_BPS_PRE, dv.dv_prescaler, + UCHCOM_REG_BPS_PRE, dv.dv_prescaler | 0x80, UCHCOM_REG_BPS_DIV, dv.dv_div); uchcom_write_reg(sc, UCHCOM_REG_BPS_MOD, dv.dv_mod, @@ -678,6 +693,10 @@ uchcom_pre_param(struct ucom_softc *ucom, struct termios *t) default: return (EIO); } + if ((t->c_cflag & CSTOPB) != 0) + return (EIO); + if ((t->c_cflag & PARENB) != 0) + return (EIO); if (uchcom_calc_divider_settings(&dv, t->c_ospeed)) { return (EIO); @@ -690,11 +709,26 @@ uchcom_cfg_param(struct ucom_softc *ucom, struct termios *t) { struct uchcom_softc *sc = ucom->sc_parent; - uchcom_get_version(sc, 0); + uchcom_get_version(sc, NULL); uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0, 0); uchcom_set_baudrate(sc, t->c_ospeed); - uchcom_read_reg(sc, 0x18, 0, 0x25, 0); - uchcom_write_reg(sc, 0x18, 0x50, 0x25, 0x00); + if (sc->sc_version < UCHCOM_VER_30) { + uchcom_read_reg(sc, UCHCOM_REG_LCR1, NULL, + UCHCOM_REG_LCR2, NULL); + uchcom_write_reg(sc, UCHCOM_REG_LCR1, 0x50, + UCHCOM_REG_LCR2, 0x00); + } else { + /* + * Set up line control: + * - enable transmit and receive + * - set 8n1 mode + * To do: support other sizes, parity, stop bits. + */ + uchcom_write_reg(sc, + UCHCOM_REG_LCR1, + UCHCOM_LCR1_RX | UCHCOM_LCR1_TX | UCHCOM_LCR1_CS8, + UCHCOM_REG_LCR2, 0x00); + } uchcom_update_status(sc); uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0x501f, 0xd90a); uchcom_set_baudrate(sc, t->c_ospeed); diff --git a/freebsd/sys/dev/usb/serial/umodem.c b/freebsd/sys/dev/usb/serial/umodem.c index ac1e35c8..76c7dfe2 100644 --- a/freebsd/sys/dev/usb/serial/umodem.c +++ b/freebsd/sys/dev/usb/serial/umodem.c @@ -459,6 +459,8 @@ umodem_attach(device_t dev) mtx_unlock(&sc->sc_mtx); } + ucom_set_usb_mode(&sc->sc_super_ucom, uaa->usb_mode); + error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, &umodem_callback, &sc->sc_mtx); if (error) { diff --git a/freebsd/sys/dev/usb/serial/usb_serial.c b/freebsd/sys/dev/usb/serial/usb_serial.c index 46a18d63..a3f9b5de 100644 --- a/freebsd/sys/dev/usb/serial/usb_serial.c +++ b/freebsd/sys/dev/usb/serial/usb_serial.c @@ -109,6 +109,12 @@ static int ucom_pps_mode; SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RWTUN, &ucom_pps_mode, 0, "pulse capture mode: 0/1/2=disabled/CTS/DCD; add 0x10 to invert"); + +static int ucom_device_mode_console = 1; + +SYSCTL_INT(_hw_usb_ucom, OID_AUTO, device_mode_console, CTLFLAG_RW, + &ucom_device_mode_console, 0, + "set to 1 to mark terminals as consoles when in device mode"); #endif /* __rtems__ */ #ifdef USB_DEBUG @@ -203,6 +209,7 @@ ucom_init(void *arg) } SYSINIT(ucom_init, SI_SUB_KLD - 1, SI_ORDER_ANY, ucom_init, NULL); +#ifndef __rtems__ static void ucom_uninit(void *arg) { @@ -218,6 +225,7 @@ ucom_uninit(void *arg) mtx_destroy(&ucom_mtx); } SYSUNINIT(ucom_uninit, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_uninit, NULL); +#endif /* __rtems__ */ /* * Mark a unit number (the X in cuaUX) as in use. @@ -294,7 +302,7 @@ ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, } ssc->sc_subunits = subunits; ssc->sc_flag = UCOM_FLAG_ATTACHED | - UCOM_FLAG_FREE_UNIT; + UCOM_FLAG_FREE_UNIT | (ssc->sc_flag & UCOM_FLAG_DEVICE_MODE); if (callback->ucom_free == NULL) ssc->sc_flag |= UCOM_FLAG_WAIT_REFS; @@ -394,6 +402,24 @@ ucom_drain_all(void *arg) mtx_unlock(&ucom_mtx); } +static cn_probe_t ucom_cnprobe; +static cn_init_t ucom_cninit; +static cn_term_t ucom_cnterm; +static cn_getc_t ucom_cngetc; +static cn_putc_t ucom_cnputc; +static cn_grab_t ucom_cngrab; +static cn_ungrab_t ucom_cnungrab; + +const struct consdev_ops ucom_cnops = { + .cn_probe = ucom_cnprobe, + .cn_init = ucom_cninit, + .cn_term = ucom_cnterm, + .cn_getc = ucom_cngetc, + .cn_putc = ucom_cnputc, + .cn_grab = ucom_cngrab, + .cn_ungrab = ucom_cnungrab, +}; + static int ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) { @@ -458,6 +484,26 @@ ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) UCOM_MTX_UNLOCK(ucom_cons_softc); } +#ifndef __rtems__ + if ((ssc->sc_flag & UCOM_FLAG_DEVICE_MODE) != 0 && + ucom_device_mode_console > 0 && + ucom_cons_softc == NULL) { + struct consdev *cp; + + cp = malloc(sizeof(struct consdev), M_USBDEV, + M_WAITOK|M_ZERO); + cp->cn_ops = &ucom_cnops; + cp->cn_arg = NULL; + cp->cn_pri = CN_NORMAL; + strlcpy(cp->cn_name, "tty", sizeof(cp->cn_name)); + strlcat(cp->cn_name, buf, sizeof(cp->cn_name)); + + sc->sc_consdev = cp; + + cnadd(cp); + } +#endif /* __rtems__ */ + return (0); } @@ -468,6 +514,14 @@ ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty); +#ifndef __rtems__ + if (sc->sc_consdev != NULL) { + cnremove(sc->sc_consdev); + free(sc->sc_consdev, M_USBDEV); + sc->sc_consdev = NULL; + } +#endif /* __rtems__ */ + if (sc->sc_flag & UCOM_FLAG_CONSOLE) { UCOM_MTX_LOCK(ucom_cons_softc); ucom_close(ucom_cons_softc->sc_tty); @@ -541,6 +595,20 @@ ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev) } } +void +ucom_set_usb_mode(struct ucom_super_softc *ssc, enum usb_hc_mode usb_mode) +{ + + switch (usb_mode) { + case USB_MODE_DEVICE: + ssc->sc_flag |= UCOM_FLAG_DEVICE_MODE; + break; + default: + ssc->sc_flag &= ~UCOM_FLAG_DEVICE_MODE; + break; + } +} + static void ucom_queue_command(struct ucom_softc *sc, usb_proc_callback_t *fn, struct termios *pt, @@ -1547,14 +1615,6 @@ ucom_free(void *xsc) mtx_unlock(&ucom_mtx); } -static cn_probe_t ucom_cnprobe; -static cn_init_t ucom_cninit; -static cn_term_t ucom_cnterm; -static cn_getc_t ucom_cngetc; -static cn_putc_t ucom_cnputc; -static cn_grab_t ucom_cngrab; -static cn_ungrab_t ucom_cnungrab; - CONSOLE_DRIVER(ucom); static void diff --git a/freebsd/sys/dev/usb/serial/usb_serial.h b/freebsd/sys/dev/usb/serial/usb_serial.h index 9a5e043e..2bcc388d 100644 --- a/freebsd/sys/dev/usb/serial/usb_serial.h +++ b/freebsd/sys/dev/usb/serial/usb_serial.h @@ -165,6 +165,9 @@ struct ucom_softc { const struct ucom_callback *sc_callback; struct ucom_super_softc *sc_super; struct tty *sc_tty; +#ifndef __rtems__ + struct consdev *sc_consdev; +#endif /* __rtems__ */ struct mtx *sc_mtx; void *sc_parent; int sc_subunit; @@ -183,6 +186,7 @@ struct ucom_softc { #define UCOM_FLAG_FREE_UNIT 0x0200 /* set if we must free the unit */ #define UCOM_FLAG_INWAKEUP 0x0400 /* set if we are in the tsw_inwakeup callback */ #define UCOM_FLAG_LSRTXIDLE 0x0800 /* set if sc_lsr bits ULSR_TSRE+TXRDY work */ +#define UCOM_FLAG_DEVICE_MODE 0x1000 /* set if we're an USB device, not a host */ uint8_t sc_lsr; uint8_t sc_msr; uint8_t sc_mcr; @@ -211,6 +215,7 @@ int ucom_attach(struct ucom_super_softc *, const struct ucom_callback *callback, struct mtx *); void ucom_detach(struct ucom_super_softc *, struct ucom_softc *); void ucom_set_pnpinfo_usb(struct ucom_super_softc *, device_t); +void ucom_set_usb_mode(struct ucom_super_softc *, enum usb_hc_mode); void ucom_status_change(struct ucom_softc *); uint8_t ucom_get_data(struct ucom_softc *, struct usb_page_cache *, uint32_t, uint32_t, uint32_t *); diff --git a/freebsd/sys/dev/usb/serial/uslcom.c b/freebsd/sys/dev/usb/serial/uslcom.c index 45835b82..4128802d 100644 --- a/freebsd/sys/dev/usb/serial/uslcom.c +++ b/freebsd/sys/dev/usb/serial/uslcom.c @@ -66,7 +66,7 @@ SYSCTL_INT(_hw_usb_uslcom, OID_AUTO, debug, CTLFLAG_RWTUN, &uslcom_debug, 0, "Debug level"); #endif -#define USLCOM_BULK_BUF_SIZE 1024 +#define USLCOM_BULK_BUF_SIZE 1024 #define USLCOM_CONFIG_INDEX 0 /* Request types */ @@ -75,13 +75,13 @@ SYSCTL_INT(_hw_usb_uslcom, OID_AUTO, debug, CTLFLAG_RWTUN, /* Request codes */ #define USLCOM_IFC_ENABLE 0x00 -#define USLCOM_SET_BAUDDIV 0x01 +#define USLCOM_SET_BAUDDIV 0x01 #define USLCOM_SET_LINE_CTL 0x03 #define USLCOM_SET_BREAK 0x05 #define USLCOM_SET_MHS 0x07 #define USLCOM_GET_MDMSTS 0x08 #define USLCOM_SET_FLOW 0x13 -#define USLCOM_SET_BAUDRATE 0x1e +#define USLCOM_SET_BAUDRATE 0x1e #define USLCOM_VENDOR_SPECIFIC 0xff /* USLCOM_IFC_ENABLE values */ @@ -89,7 +89,7 @@ SYSCTL_INT(_hw_usb_uslcom, OID_AUTO, debug, CTLFLAG_RWTUN, #define USLCOM_IFC_ENABLE_EN 0x01 /* USLCOM_SET_MHS/USLCOM_GET_MDMSTS values */ -#define USLCOM_MHS_DTR_ON 0x0001 +#define USLCOM_MHS_DTR_ON 0x0001 #define USLCOM_MHS_DTR_SET 0x0100 #define USLCOM_MHS_RTS_ON 0x0002 #define USLCOM_MHS_RTS_SET 0x0200 @@ -114,11 +114,11 @@ SYSCTL_INT(_hw_usb_uslcom, OID_AUTO, debug, CTLFLAG_RWTUN, #define USLCOM_SET_BREAK_ON 0x01 /* USLCOM_SET_FLOW values - 1st word */ -#define USLCOM_FLOW_DTR_ON 0x00000001 /* DTR static active */ -#define USLCOM_FLOW_CTS_HS 0x00000008 /* CTS handshake */ +#define USLCOM_FLOW_DTR_ON 0x00000001 /* DTR static active */ +#define USLCOM_FLOW_CTS_HS 0x00000008 /* CTS handshake */ /* USLCOM_SET_FLOW values - 2nd word */ -#define USLCOM_FLOW_RTS_ON 0x00000040 /* RTS static active */ -#define USLCOM_FLOW_RTS_HS 0x00000080 /* RTS handshake */ +#define USLCOM_FLOW_RTS_ON 0x00000040 /* RTS static active */ +#define USLCOM_FLOW_RTS_HS 0x00000080 /* RTS handshake */ /* USLCOM_VENDOR_SPECIFIC values */ #define USLCOM_GET_PARTNUM 0x370B @@ -148,10 +148,10 @@ struct uslcom_softc { struct usb_device *sc_udev; struct mtx sc_mtx; - uint8_t sc_msr; - uint8_t sc_lsr; - uint8_t sc_iface_no; - uint8_t sc_partnum; + uint8_t sc_msr; + uint8_t sc_lsr; + uint8_t sc_iface_no; + uint8_t sc_partnum; }; static device_probe_t uslcom_probe; @@ -163,18 +163,18 @@ static usb_callback_t uslcom_write_callback; static usb_callback_t uslcom_read_callback; static usb_callback_t uslcom_control_callback; -static void uslcom_free(struct ucom_softc *); -static void uslcom_open(struct ucom_softc *); -static void uslcom_close(struct ucom_softc *); +static void uslcom_free(struct ucom_softc *); static uint8_t uslcom_get_partnum(struct uslcom_softc *); -static void uslcom_set_dtr(struct ucom_softc *, uint8_t); -static void uslcom_set_rts(struct ucom_softc *, uint8_t); -static void uslcom_set_break(struct ucom_softc *, uint8_t); +static void uslcom_cfg_open(struct ucom_softc *); +static void uslcom_cfg_close(struct ucom_softc *); +static void uslcom_cfg_set_dtr(struct ucom_softc *, uint8_t); +static void uslcom_cfg_set_rts(struct ucom_softc *, uint8_t); +static void uslcom_cfg_set_break(struct ucom_softc *, uint8_t); +static void uslcom_cfg_param(struct ucom_softc *, struct termios *); +static void uslcom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); static int uslcom_ioctl(struct ucom_softc *, uint32_t, caddr_t, int, - struct thread *); + struct thread *); static int uslcom_pre_param(struct ucom_softc *, struct termios *); -static void uslcom_param(struct ucom_softc *, struct termios *); -static void uslcom_get_status(struct ucom_softc *, uint8_t *, uint8_t *); static void uslcom_start_read(struct ucom_softc *); static void uslcom_stop_read(struct ucom_softc *); static void uslcom_start_write(struct ucom_softc *); @@ -182,7 +182,6 @@ static void uslcom_stop_write(struct ucom_softc *); static void uslcom_poll(struct ucom_softc *ucom); static const struct usb_config uslcom_config[USLCOM_N_TRANSFER] = { - [USLCOM_BULK_DT_WR] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, @@ -212,15 +211,15 @@ static const struct usb_config uslcom_config[USLCOM_N_TRANSFER] = { }; static struct ucom_callback uslcom_callback = { - .ucom_cfg_open = &uslcom_open, - .ucom_cfg_close = &uslcom_close, - .ucom_cfg_get_status = &uslcom_get_status, - .ucom_cfg_set_dtr = &uslcom_set_dtr, - .ucom_cfg_set_rts = &uslcom_set_rts, - .ucom_cfg_set_break = &uslcom_set_break, - .ucom_ioctl = &uslcom_ioctl, - .ucom_cfg_param = &uslcom_param, + .ucom_cfg_get_status = &uslcom_cfg_get_status, + .ucom_cfg_set_dtr = &uslcom_cfg_set_dtr, + .ucom_cfg_set_rts = &uslcom_cfg_set_rts, + .ucom_cfg_set_break = &uslcom_cfg_set_break, + .ucom_cfg_open = &uslcom_cfg_open, + .ucom_cfg_close = &uslcom_cfg_close, + .ucom_cfg_param = &uslcom_cfg_param, .ucom_pre_param = &uslcom_pre_param, + .ucom_ioctl = &uslcom_ioctl, .ucom_start_read = &uslcom_start_read, .ucom_stop_read = &uslcom_stop_read, .ucom_start_write = &uslcom_start_write, @@ -501,7 +500,7 @@ uslcom_free(struct ucom_softc *ucom) } static void -uslcom_open(struct ucom_softc *ucom) +uslcom_cfg_open(struct ucom_softc *ucom) { struct uslcom_softc *sc = ucom->sc_parent; struct usb_device_request req; @@ -512,7 +511,7 @@ uslcom_open(struct ucom_softc *ucom) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("UART enable failed (ignored)\n"); } @@ -522,7 +521,7 @@ uslcom_open(struct ucom_softc *ucom) } static void -uslcom_close(struct ucom_softc *ucom) +uslcom_cfg_close(struct ucom_softc *ucom) { struct uslcom_softc *sc = ucom->sc_parent; struct usb_device_request req; @@ -536,7 +535,7 @@ uslcom_close(struct ucom_softc *ucom) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("UART disable failed (ignored)\n"); } @@ -565,13 +564,13 @@ uslcom_get_partnum(struct uslcom_softc *sc) } static void -uslcom_set_dtr(struct ucom_softc *ucom, uint8_t onoff) +uslcom_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff) { - struct uslcom_softc *sc = ucom->sc_parent; + struct uslcom_softc *sc = ucom->sc_parent; struct usb_device_request req; uint16_t ctl; - DPRINTF("onoff = %d\n", onoff); + DPRINTF("onoff = %d\n", onoff); ctl = onoff ? USLCOM_MHS_DTR_ON : 0; ctl |= USLCOM_MHS_DTR_SET; @@ -582,20 +581,20 @@ uslcom_set_dtr(struct ucom_softc *ucom, uint8_t onoff) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("Setting DTR failed (ignored)\n"); } } static void -uslcom_set_rts(struct ucom_softc *ucom, uint8_t onoff) +uslcom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff) { - struct uslcom_softc *sc = ucom->sc_parent; + struct uslcom_softc *sc = ucom->sc_parent; struct usb_device_request req; uint16_t ctl; - DPRINTF("onoff = %d\n", onoff); + DPRINTF("onoff = %d\n", onoff); ctl = onoff ? USLCOM_MHS_RTS_ON : 0; ctl |= USLCOM_MHS_RTS_SET; @@ -606,7 +605,7 @@ uslcom_set_rts(struct ucom_softc *ucom, uint8_t onoff) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("Setting DTR failed (ignored)\n"); } @@ -615,13 +614,28 @@ uslcom_set_rts(struct ucom_softc *ucom, uint8_t onoff) static int uslcom_pre_param(struct ucom_softc *ucom, struct termios *t) { - if (t->c_ospeed <= 0 || t->c_ospeed > 921600) + struct uslcom_softc *sc = ucom->sc_parent; + uint32_t maxspeed; + + switch (sc->sc_partnum) { + case USLCOM_PARTNUM_CP2104: + case USLCOM_PARTNUM_CP2105: + maxspeed = 2000000; + break; + case USLCOM_PARTNUM_CP2101: + case USLCOM_PARTNUM_CP2102: + case USLCOM_PARTNUM_CP2103: + default: + maxspeed = 921600; + break; + } + if (t->c_ospeed <= 0 || t->c_ospeed > maxspeed) return (EINVAL); return (0); } static void -uslcom_param(struct ucom_softc *ucom, struct termios *t) +uslcom_cfg_param(struct ucom_softc *ucom, struct termios *t) { struct uslcom_softc *sc = ucom->sc_parent; struct usb_device_request req; @@ -637,9 +651,9 @@ uslcom_param(struct ucom_softc *ucom, struct termios *t) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, sizeof(baudrate)); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, &baudrate, 0, 1000)) { - DPRINTF("Set baudrate failed (ignored)\n"); + printf("Set baudrate failed (ignored)\n"); } if (t->c_cflag & CSTOPB) @@ -674,11 +688,11 @@ uslcom_param(struct ucom_softc *ucom, struct termios *t) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("Set format failed (ignored)\n"); } - + if (t->c_cflag & CRTSCTS) { flowctrl[0] = htole32(USLCOM_FLOW_DTR_ON | USLCOM_FLOW_CTS_HS); flowctrl[1] = htole32(USLCOM_FLOW_RTS_HS); @@ -694,14 +708,14 @@ uslcom_param(struct ucom_softc *ucom, struct termios *t) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, sizeof(flowctrl)); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, flowctrl, 0, 1000)) { DPRINTF("Set flowcontrol failed (ignored)\n"); } } static void -uslcom_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) +uslcom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) { struct uslcom_softc *sc = ucom->sc_parent; @@ -713,9 +727,9 @@ uslcom_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) } static void -uslcom_set_break(struct ucom_softc *ucom, uint8_t onoff) +uslcom_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff) { - struct uslcom_softc *sc = ucom->sc_parent; + struct uslcom_softc *sc = ucom->sc_parent; struct usb_device_request req; uint16_t brk = onoff ? USLCOM_SET_BREAK_ON : USLCOM_SET_BREAK_OFF; @@ -725,7 +739,7 @@ uslcom_set_break(struct ucom_softc *ucom, uint8_t onoff) USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("Set BREAK failed (ignored)\n"); } @@ -754,7 +768,7 @@ uslcom_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data, USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, sizeof(latch)); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, &latch, 0, 1000)) { DPRINTF("Get LATCH failed\n"); error = EIO; @@ -773,7 +787,7 @@ uslcom_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data, USETW(req.wIndex, (*(int *)data)); USETW(req.wLength, 0); - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, &req, NULL, 0, 1000)) { DPRINTF("Set LATCH failed\n"); error = EIO; @@ -888,7 +902,7 @@ uslcom_control_callback(struct usb_xfer *xfer, usb_error_t error) USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, sizeof(buf)); - + usbd_xfer_set_frames(xfer, 2); usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); usbd_xfer_set_frame_len(xfer, 1, sizeof(buf)); diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index 5f1cf409..5d6b9d0f 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -120,7 +120,7 @@ static void usb_cdev_free(struct usb_device *); #ifdef USB_TEMPLATE int usb_template = USB_TEMPLATE; #else -int usb_template; +int usb_template = -1; #endif #ifndef __rtems__ diff --git a/freebsd/sys/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h index 7cf90649..fcd31e31 100644 --- a/freebsd/sys/dev/usb/usb_ioctl.h +++ b/freebsd/sys/dev/usb/usb_ioctl.h @@ -69,6 +69,7 @@ enum { USB_TEMP_PHONE, /* USB Phone */ USB_TEMP_SERIALNET, /* USB CDC Ethernet and Modem */ USB_TEMP_MIDI, /* USB MIDI */ + USB_TEMP_MULTI, /* USB Ethernet, serial, and storage */ USB_TEMP_MAX, }; diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c index 6be241c2..cb69ce0e 100644 --- a/freebsd/sys/dev/usb/usb_request.c +++ b/freebsd/sys/dev/usb/usb_request.c @@ -1157,7 +1157,11 @@ usbd_req_get_string_any(struct usb_device *udev, struct mtx *mtx, char *buf, *s == '+' || *s == ' ' || *s == '.' || - *s == ',') { + *s == ',' || + *s == ':' || + *s == '/' || + *s == '(' || + *s == ')') { /* allowed */ s++; } diff --git a/freebsd/sys/dev/usb/wlan/if_rsu.c b/freebsd/sys/dev/usb/wlan/if_rsu.c index 179de4e5..1cb504cc 100644 --- a/freebsd/sys/dev/usb/wlan/if_rsu.c +++ b/freebsd/sys/dev/usb/wlan/if_rsu.c @@ -890,7 +890,7 @@ rsu_set_multi(struct rsu_softc *sc) TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { ifp = vap->iv_ifp; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { caddr_t dl; uint8_t pos; diff --git a/freebsd/sys/dev/usb/wlan/if_zyd.c b/freebsd/sys/dev/usb/wlan/if_zyd.c index dee03bdd..1835b58b 100644 --- a/freebsd/sys/dev/usb/wlan/if_zyd.c +++ b/freebsd/sys/dev/usb/wlan/if_zyd.c @@ -2002,7 +2002,7 @@ zyd_set_multi(struct zyd_softc *sc) TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { ifp = vap->iv_ifp; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; v = ((uint8_t *)LLADDR((struct sockaddr_dl *) |