summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-09 13:04:41 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commite4a8065910cd6b2e7e0448cc6431ca2906322389 (patch)
tree73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/dev/usb
parentUpdate to FreeBSD head 2017-08-01 (diff)
downloadrtems-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.c1
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c5
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.h1
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c74
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c4
-rw-r--r--freebsd/sys/dev/usb/usbhid.h23
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uath.c122
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;