diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-09 13:04:41 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:37 +0200 |
commit | e4a8065910cd6b2e7e0448cc6431ca2906322389 (patch) | |
tree | 73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/dev/usb | |
parent | Update to FreeBSD head 2017-08-01 (diff) | |
download | rtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2 |
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1.
Update #3472.
Diffstat (limited to 'freebsd/sys/dev/usb')
-rw-r--r-- | freebsd/sys/dev/usb/net/if_ure.c | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/quirk/usb_quirk.c | 5 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/quirk/usb_quirk.h | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_hid.c | 74 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_hub.c | 4 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usbhid.h | 23 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/wlan/if_uath.c | 122 |
7 files changed, 205 insertions, 25 deletions
diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c index 27e3ecca..89ce723b 100644 --- a/freebsd/sys/dev/usb/net/if_ure.c +++ b/freebsd/sys/dev/usb/net/if_ure.c @@ -69,6 +69,7 @@ SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0, */ static const STRUCT_USB_HOST_ID ure_devs[] = { #define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } + URE_DEV(LENOVO, RTL8153, 0), URE_DEV(REALTEK, RTL8152, URE_FLAG_8152), URE_DEV(REALTEK, RTL8153, 0), #undef URE_DEV diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index a5fac1b3..3ea3f3c6 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -236,6 +236,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_RBC), USB_QUIRK(INSYSTEM, STORAGE_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC), + USB_QUIRK(INTENSO, MEMORY_BOX, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), USB_QUIRK(IODATA, IU_CD2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI), USB_QUIRK(IODATA, DVR_UEH8, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, @@ -335,7 +336,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_START_STOP), USB_QUIRK(PROLIFIC, PL2506, 0x0000, 0xffff, - UQ_MSC_NO_SYNC_CACHE), + UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_PREVENT_ALLOW), USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY), @@ -509,6 +510,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), + USB_QUIRK(ROLAND, PCR300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY), @@ -608,6 +610,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = { [UQ_SINGLE_CMD_MIDI] = "UQ_SINGLE_CMD_MIDI", [UQ_MSC_DYMO_EJECT] = "UQ_MSC_DYMO_EJECT", [UQ_AU_SET_SPDIF_CM6206] = "UQ_AU_SET_SPDIF_CM6206", + [UQ_WMT_IGNORE] = "UQ_WMT_IGNORE", }; /*------------------------------------------------------------------------* diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h index f7e490ce..bb9fe190 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.h +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h @@ -110,6 +110,7 @@ enum { UQ_SINGLE_CMD_MIDI, /* at most one command per USB packet */ UQ_MSC_DYMO_EJECT, /* ejects Dymo MSC device */ UQ_AU_SET_SPDIF_CM6206, /* enable S/PDIF audio output */ + UQ_WMT_IGNORE, /* device should be ignored by wmt driver */ USB_QUIRK_MAX }; diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c index 56e31a6e..5019aa1a 100644 --- a/freebsd/sys/dev/usb/usb_hid.c +++ b/freebsd/sys/dev/usb/usb_hid.c @@ -851,6 +851,80 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, } /*------------------------------------------------------------------------* + * calculate HID item resolution. unit/mm for distances, unit/rad for angles + *------------------------------------------------------------------------*/ +int32_t +hid_item_resolution(struct hid_item *hi) +{ + /* + * hid unit scaling table according to HID Usage Table Review + * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf + */ + static const int64_t scale[0x10][2] = { + [0x00] = { 1, 1 }, + [0x01] = { 1, 10 }, + [0x02] = { 1, 100 }, + [0x03] = { 1, 1000 }, + [0x04] = { 1, 10000 }, + [0x05] = { 1, 100000 }, + [0x06] = { 1, 1000000 }, + [0x07] = { 1, 10000000 }, + [0x08] = { 100000000, 1 }, + [0x09] = { 10000000, 1 }, + [0x0A] = { 1000000, 1 }, + [0x0B] = { 100000, 1 }, + [0x0C] = { 10000, 1 }, + [0x0D] = { 1000, 1 }, + [0x0E] = { 100, 1 }, + [0x0F] = { 10, 1 }, + }; + int64_t logical_size; + int64_t physical_size; + int64_t multiplier; + int64_t divisor; + int64_t resolution; + + switch (hi->unit) { + case HUM_CENTIMETER: + multiplier = 1; + divisor = 10; + break; + case HUM_INCH: + multiplier = 10; + divisor = 254; + break; + case HUM_RADIAN: + multiplier = 1; + divisor = 1; + break; + case HUM_DEGREE: + multiplier = 573; + divisor = 10; + break; + default: + return (0); + } + + if ((hi->logical_maximum <= hi->logical_minimum) || + (hi->physical_maximum <= hi->physical_minimum) || + (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale))) + return (0); + + logical_size = (int64_t)hi->logical_maximum - + (int64_t)hi->logical_minimum; + physical_size = (int64_t)hi->physical_maximum - + (int64_t)hi->physical_minimum; + /* Round to ceiling */ + resolution = logical_size * multiplier * scale[hi->unit_exponent][0] / + (physical_size * divisor * scale[hi->unit_exponent][1]); + + if (resolution > INT32_MAX) + return (0); + + return (resolution); +} + +/*------------------------------------------------------------------------* * hid_is_mouse * * This function will decide if a USB descriptor belongs to a USB mouse. diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index e70be43b..0eaeeb60 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -102,7 +102,9 @@ SYSCTL_INT(_hw_usb, OID_AUTO, power_timeout, CTLFLAG_RWTUN, #if USB_HAVE_DISABLE_ENUM static int usb_disable_enumeration = 0; SYSCTL_INT(_hw_usb, OID_AUTO, disable_enumeration, CTLFLAG_RWTUN, - &usb_disable_enumeration, 0, "Set to disable all USB device enumeration."); + &usb_disable_enumeration, 0, "Set to disable all USB device enumeration. " + "This can secure against USB devices turning evil, " + "for example a USB memory stick becoming a USB keyboard."); static int usb_disable_port_power = 0; SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN, diff --git a/freebsd/sys/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h index 28dfede2..31aa7ea4 100644 --- a/freebsd/sys/dev/usb/usbhid.h +++ b/freebsd/sys/dev/usb/usbhid.h @@ -134,6 +134,12 @@ struct usb_hid_descriptor { /* Usages Digitizers */ #define HUD_UNDEFINED 0x0000 +#define HUD_DIGITIZER 0x0001 +#define HUD_PEN 0x0002 +#define HUD_TOUCHSCREEN 0x0004 +#define HUD_TOUCHPAD 0x0005 +#define HUD_CONFIG 0x000e +#define HUD_FINGER 0x0022 #define HUD_TIP_PRESSURE 0x0030 #define HUD_BARREL_PRESSURE 0x0031 #define HUD_IN_RANGE 0x0032 @@ -157,6 +163,16 @@ struct usb_hid_descriptor { #define HUD_BARREL_SWITCH 0x0044 #define HUD_ERASER 0x0045 #define HUD_TABLET_PICK 0x0046 +#define HUD_CONFIDENCE 0x0047 +#define HUD_WIDTH 0x0048 +#define HUD_HEIGHT 0x0049 +#define HUD_CONTACTID 0x0051 +#define HUD_INPUT_MODE 0x0052 +#define HUD_DEVICE_INDEX 0x0053 +#define HUD_CONTACTCOUNT 0x0054 +#define HUD_CONTACT_MAX 0x0055 +#define HUD_SCAN_TIME 0x0056 +#define HUD_BUTTON_TYPE 0x0059 /* Usages, Consumer */ #define HUC_AC_PAN 0x0238 @@ -178,6 +194,12 @@ struct usb_hid_descriptor { #define HIO_VOLATILE 0x080 #define HIO_BUFBYTES 0x100 +/* Units of Measure */ +#define HUM_CENTIMETER 0x11 +#define HUM_RADIAN 0x12 +#define HUM_INCH 0x13 +#define HUM_DEGREE 0x14 + #ifdef _KERNEL struct usb_config_descriptor; @@ -244,6 +266,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb( usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index); +int32_t hid_item_resolution(struct hid_item *hi); int hid_is_mouse(const void *d_ptr, uint16_t d_len); int hid_is_keyboard(const void *d_ptr, uint16_t d_len); #endif /* _KERNEL */ diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c index c3435d57..c4ebe5ed 100644 --- a/freebsd/sys/dev/usb/wlan/if_uath.c +++ b/freebsd/sys/dev/usb/wlan/if_uath.c @@ -2203,17 +2203,19 @@ uath_sysctl_node(struct uath_softc *sc) #undef UATH_SYSCTL_STAT_ADD32 +CTASSERT(sizeof(u_int) >= sizeof(uint32_t)); + static void uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) { struct uath_cmd_hdr *hdr; - int dlen; + uint32_t dlen; hdr = (struct uath_cmd_hdr *)cmd->buf; /* NB: msgid is passed thru w/o byte swapping */ #ifdef UATH_DEBUG if (sc->sc_debug & UATH_DEBUG_CMDS) { - int len = be32toh(hdr->len); + uint32_t len = be32toh(hdr->len); printf("%s: %s [ix %u] len %u status %u\n", __func__, uath_codename(be32toh(hdr->code)), hdr->msgid, len, be32toh(hdr->magic)); @@ -2229,15 +2231,9 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) switch (hdr->code & 0xff) { /* reply to a read command */ default: - dlen = hdr->len - sizeof(*hdr); - if (dlen < 0) { - device_printf(sc->sc_dev, - "Invalid header length %d\n", dlen); - return; - } DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, - "%s: code %d data len %u\n", - __func__, hdr->code & 0xff, dlen); + "%s: code %d hdr len %u\n", + __func__, hdr->code & 0xff, hdr->len); /* * The first response from the target after the * HOST_AVAILABLE has an invalid msgid so we must @@ -2247,8 +2243,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) uint32_t *rp = (uint32_t *)(hdr+1); u_int olen; - if (!(sizeof(*hdr) <= hdr->len && - hdr->len < UATH_MAX_CMDSZ)) { + if (sizeof(*hdr) > hdr->len || + hdr->len >= UATH_MAX_CMDSZ) { device_printf(sc->sc_dev, "%s: invalid WDC msg length %u; " "msg ignored\n", __func__, hdr->len); @@ -2260,7 +2256,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) * number of bytes--unless it's 0 in which * case a single 32-bit word should be present. */ - if (dlen >= (int)sizeof(uint32_t)) { + dlen = hdr->len - sizeof(*hdr); + if (dlen >= sizeof(uint32_t)) { olen = be32toh(rp[0]); dlen -= sizeof(uint32_t); if (olen == 0) { @@ -2280,7 +2277,7 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) cmd->olen); olen = cmd->olen; } - if (olen > (u_int)dlen) { + if (olen > dlen) { /* XXX complain, shouldn't happen */ device_printf(sc->sc_dev, "%s: cmd 0x%x olen %u dlen %u\n", @@ -2302,8 +2299,10 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) return; } dlen = hdr->len - sizeof(*hdr); - if (dlen != (int)sizeof(uint32_t)) { - /* XXX something wrong */ + if (dlen != sizeof(uint32_t)) { + device_printf(sc->sc_dev, + "%s: dlen (%u) != %zu!\n", + __func__, dlen, sizeof(uint32_t)); return; } /* XXX have submitter do this */ @@ -2332,6 +2331,7 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct uath_cmd *cmd; + struct uath_cmd_hdr *hdr; struct usb_page_cache *pc; int actlen; @@ -2349,10 +2349,25 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error) STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next); UATH_STAT_INC(sc, st_cmd_inactive); - KASSERT(actlen >= (int)sizeof(struct uath_cmd_hdr), - ("short xfer error")); + if (actlen < sizeof(struct uath_cmd_hdr)) { + device_printf(sc->sc_dev, + "%s: short xfer error (actlen %d)\n", + __func__, actlen); + goto setup; + } + pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_out(pc, 0, cmd->buf, actlen); + + hdr = (struct uath_cmd_hdr *)cmd->buf; + hdr->len = be32toh(hdr->len); + if (hdr->len > (uint32_t)actlen) { + device_printf(sc->sc_dev, + "%s: truncated xfer (len %u, actlen %d)\n", + __func__, hdr->len, actlen); + goto setup; + } + uath_cmdeof(sc, cmd); case USB_ST_SETUP: setup: @@ -2453,6 +2468,8 @@ uath_update_rxstat(struct uath_softc *sc, uint32_t status) } } +CTASSERT(UATH_MIN_RXBUFSZ >= sizeof(struct uath_chunk)); + static struct mbuf * uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, struct uath_rx_desc **pdesc) @@ -2475,13 +2492,24 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, } chunk = (struct uath_chunk *)data->buf; - if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) { + chunklen = be16toh(chunk->length); + if (chunk->seqnum == 0 && chunk->flags == 0 && chunklen == 0) { device_printf(sc->sc_dev, "%s: strange response\n", __func__); counter_u64_add(ic->ic_ierrors, 1); UATH_RESET_INTRX(sc); return (NULL); } + if (chunklen > actlen) { + device_printf(sc->sc_dev, + "%s: invalid chunk length (len %u > actlen %d)\n", + __func__, chunklen, actlen); + counter_u64_add(ic->ic_ierrors, 1); + /* XXX cleanup? */ + UATH_RESET_INTRX(sc); + return (NULL); + } + if (chunk->seqnum != sc->sc_intrx_nextnum) { DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n", chunk->seqnum, sc->sc_intrx_nextnum); @@ -2498,9 +2526,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, chunk->flags & UATH_CFLAGS_RXMSG) UATH_STAT_INC(sc, st_multichunk); - chunklen = be16toh(chunk->length); - if (chunk->flags & UATH_CFLAGS_FINAL) + if (chunk->flags & UATH_CFLAGS_FINAL) { + if (chunklen < sizeof(struct uath_rx_desc)) { + device_printf(sc->sc_dev, + "%s: invalid chunk length %d\n", + __func__, chunklen); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } chunklen -= sizeof(struct uath_rx_desc); + } if (chunklen > 0 && (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) { @@ -2561,6 +2599,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, (struct uath_rx_desc *)(((uint8_t *)chunk) + sizeof(struct uath_chunk) + be16toh(chunk->length) - sizeof(struct uath_rx_desc)); + if ((uint8_t *)chunk + actlen - sizeof(struct uath_rx_desc) < + (uint8_t *)desc) { + device_printf(sc->sc_dev, + "%s: wrong Rx descriptor pointer " + "(desc %p chunk %p actlen %d)\n", + __func__, desc, chunk, actlen); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } + *pdesc = desc; DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, @@ -2588,8 +2639,33 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, /* finalize mbuf */ if (sc->sc_intrx_head == NULL) { - m->m_pkthdr.len = m->m_len = - be32toh(desc->framelen) - UATH_RX_DUMMYSIZE; + uint32_t framelen; + + if (be32toh(desc->framelen) < UATH_RX_DUMMYSIZE) { + device_printf(sc->sc_dev, + "%s: framelen too small (%u)\n", + __func__, be32toh(desc->framelen)); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } + + framelen = be32toh(desc->framelen) - UATH_RX_DUMMYSIZE; + if (framelen > actlen - sizeof(struct uath_chunk) || + framelen < sizeof(struct ieee80211_frame_ack)) { + device_printf(sc->sc_dev, + "%s: wrong frame length (%u, actlen %d)!\n", + __func__, framelen, actlen); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } + + m->m_pkthdr.len = m->m_len = framelen; m->m_data += sizeof(struct uath_chunk); } else { mp = sc->sc_intrx_head; |