summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-10-23 08:22:44 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-10-25 08:38:45 +0200
commitb3169c2a6a01cc0555181f61b5254dd2c1f1c310 (patch)
treef84d67c9d17b2625481513fa6dc85929fdb08442 /freebsd/sys/dev/usb
parentUpdate rtems_waf (diff)
downloadrtems-libbsd-b3169c2a6a01cc0555181f61b5254dd2c1f1c310.tar.bz2
Update to FreeBSD head 2018-10-23
Git mirror commit 59f44d20be3f99d181ca742e636d45fc39ec982b. This commit updates OpenSSL to version 1.1.1. This required an update of racoon which uses some internal stuff from OpenSSL and seems to be mostly unmaintained, e.g. there is update in the FreeBSD ports to cope with OpenSSL 1.1.1. Update #3472.
Diffstat (limited to 'freebsd/sys/dev/usb')
-rw-r--r--freebsd/sys/dev/usb/controller/dwc_otg.c29
-rw-r--r--freebsd/sys/dev/usb/net/if_ure.c3
-rw-r--r--freebsd/sys/dev/usb/serial/uplcom.c218
-rw-r--r--freebsd/sys/dev/usb/usbdi.h6
4 files changed, 210 insertions, 46 deletions
diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.c b/freebsd/sys/dev/usb/controller/dwc_otg.c
index abc23ac6..1332b485 100644
--- a/freebsd/sys/dev/usb/controller/dwc_otg.c
+++ b/freebsd/sys/dev/usb/controller/dwc_otg.c
@@ -1460,6 +1460,8 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
/* check if we are complete */
if (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN) {
goto complete;
+ } else if (td->hcsplt != 0) {
+ goto receive_pkt;
} else {
/* get more packets */
goto busy;
@@ -1518,8 +1520,10 @@ receive_pkt:
if (td->hcsplt != 0) {
delta = td->tt_complete_slot - sc->sc_last_frame_num - 1;
if (td->tt_scheduled == 0 || delta < DWC_OTG_TT_SLOT_MAX) {
- td->state = DWC_CHAN_ST_WAIT_C_PKT;
- goto busy;
+ if (td->ep_type != UE_ISOCHRONOUS) {
+ td->state = DWC_CHAN_ST_WAIT_C_PKT;
+ goto busy;
+ }
}
delta = sc->sc_last_frame_num - td->tt_start_slot;
if (delta > DWC_OTG_TT_SLOT_MAX) {
@@ -1565,12 +1569,23 @@ receive_pkt:
hcchar = td->hcchar;
hcchar |= HCCHAR_EPDIR_IN;
- /* receive complete split ASAP */
- if ((sc->sc_last_frame_num & 1) != 0 &&
- td->ep_type == UE_ISOCHRONOUS)
- hcchar |= HCCHAR_ODDFRM;
- else
+ if (td->ep_type == UE_ISOCHRONOUS) {
+ if (td->hcsplt != 0) {
+ /* continously buffer */
+ if (sc->sc_last_frame_num & 1)
+ hcchar &= ~HCCHAR_ODDFRM;
+ else
+ hcchar |= HCCHAR_ODDFRM;
+ } else {
+ /* multi buffer, if any */
+ if (sc->sc_last_frame_num & 1)
+ hcchar |= HCCHAR_ODDFRM;
+ else
+ hcchar &= ~HCCHAR_ODDFRM;
+ }
+ } else {
hcchar &= ~HCCHAR_ODDFRM;
+ }
/* must enable channel before data can be received */
DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c
index bcae02cb..136b61f9 100644
--- a/freebsd/sys/dev/usb/net/if_ure.c
+++ b/freebsd/sys/dev/usb/net/if_ure.c
@@ -70,6 +70,8 @@ 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(LENOVO, TBT3LAN, 0),
+ URE_DEV(LENOVO, USBCLAN, 0),
URE_DEV(NVIDIA, RTL8153, 0),
URE_DEV(REALTEK, RTL8152, URE_FLAG_8152),
URE_DEV(REALTEK, RTL8153, 0),
@@ -171,6 +173,7 @@ MODULE_DEPEND(ure, usb, 1, 1, 1);
MODULE_DEPEND(ure, ether, 1, 1, 1);
MODULE_DEPEND(ure, miibus, 1, 1, 1);
MODULE_VERSION(ure, 1);
+USB_PNP_HOST_INFO(ure_devs);
static const struct usb_ether_methods ure_ue_methods = {
.ue_attach_post = ure_attach_post,
diff --git a/freebsd/sys/dev/usb/serial/uplcom.c b/freebsd/sys/dev/usb/serial/uplcom.c
index 2b90e4d6..a58ba3ce 100644
--- a/freebsd/sys/dev/usb/serial/uplcom.c
+++ b/freebsd/sys/dev/usb/serial/uplcom.c
@@ -136,11 +136,19 @@ SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RWTUN,
#define UPLCOM_SET_CRTSCTS 0x41
#define UPLCOM_SET_CRTSCTS_PL2303X 0x61
#define RSAQ_STATUS_CTS 0x80
+#define RSAQ_STATUS_OVERRUN_ERROR 0x40
+#define RSAQ_STATUS_PARITY_ERROR 0x20
+#define RSAQ_STATUS_FRAME_ERROR 0x10
+#define RSAQ_STATUS_RING 0x08
+#define RSAQ_STATUS_BREAK_ERROR 0x04
#define RSAQ_STATUS_DSR 0x02
#define RSAQ_STATUS_DCD 0x01
#define TYPE_PL2303 0
#define TYPE_PL2303HX 1
+#define TYPE_PL2303HXD 2
+
+#define UPLCOM_STATE_INDEX 8
enum {
UPLCOM_BULK_DT_WR,
@@ -371,18 +379,49 @@ uplcom_attach(device_t dev)
sc->sc_udev = uaa->device;
- /* Determine the chip type. This algorithm is taken from Linux. */
dd = usbd_get_device_descriptor(sc->sc_udev);
- if (dd->bDeviceClass == 0x02)
- sc->sc_chiptype = TYPE_PL2303;
- else if (dd->bMaxPacketSize == 0x40)
+
+ switch (UGETW(dd->bcdDevice)) {
+ case 0x0300:
sc->sc_chiptype = TYPE_PL2303HX;
- else
- sc->sc_chiptype = TYPE_PL2303;
+ /* or TA, that is HX with external crystal */
+ break;
+ case 0x0400:
+ sc->sc_chiptype = TYPE_PL2303HXD;
+ /* or EA, that is HXD with ESD protection */
+ /* or RA, that has internal voltage level converter that works only up to 1Mbaud (!) */
+ break;
+ case 0x0500:
+ sc->sc_chiptype = TYPE_PL2303HXD;
+ /* in fact it's TB, that is HXD with external crystal */
+ break;
+ default:
+ /* NOTE: I have no info about the bcdDevice for the base PL2303 (up to 1.2Mbaud,
+ only fixed rates) and for PL2303SA (8-pin chip, up to 115200 baud */
+ /* Determine the chip type. This algorithm is taken from Linux. */
+ if (dd->bDeviceClass == 0x02)
+ sc->sc_chiptype = TYPE_PL2303;
+ else if (dd->bMaxPacketSize == 0x40)
+ sc->sc_chiptype = TYPE_PL2303HX;
+ else
+ sc->sc_chiptype = TYPE_PL2303;
+ break;
+ }
- DPRINTF("chiptype: %s\n",
- (sc->sc_chiptype == TYPE_PL2303HX) ?
- "2303X" : "2303");
+ switch (sc->sc_chiptype) {
+ case TYPE_PL2303:
+ DPRINTF("chiptype: 2303\n");
+ break;
+ case TYPE_PL2303HX:
+ DPRINTF("chiptype: 2303HX/TA\n");
+ break;
+ case TYPE_PL2303HXD:
+ DPRINTF("chiptype: 2303HXD/TB/RA/EA\n");
+ break;
+ default:
+ DPRINTF("chiptype: unknown %d\n", sc->sc_chiptype);
+ break;
+ }
/*
* USB-RSAQ1 has two interface
@@ -431,13 +470,14 @@ uplcom_attach(device_t dev)
goto detach;
}
- if (sc->sc_chiptype != TYPE_PL2303HX) {
+ if (sc->sc_chiptype == TYPE_PL2303) {
/* HX variants seem to lock up after a clear stall request. */
mtx_lock(&sc->sc_mtx);
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]);
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]);
mtx_unlock(&sc->sc_mtx);
} else {
+ /* reset upstream data pipes */
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE,
UPLCOM_SET_REQUEST, 8, 0, 0) ||
uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE,
@@ -556,7 +596,7 @@ uplcom_pl2303_init(struct usb_device *udev, uint8_t chiptype)
|| uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0))
return (EIO);
- if (chiptype == TYPE_PL2303HX)
+ if (chiptype != TYPE_PL2303)
err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0);
else
err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x24, 0);
@@ -636,23 +676,52 @@ uplcom_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
&req, NULL, 0, 1000);
}
+/*
+ * NOTE: These baud rates are officially supported, they can be written
+ * directly into dwDTERate register.
+ *
+ * Free baudrate setting is not supported by the base PL2303, and on
+ * other models it requires writing a divisor value to dwDTERate instead
+ * of the raw baudrate. The formula for divisor calculation is not published
+ * by the vendor, so it is speculative, though the official product homepage
+ * refers to the Linux module source as a reference implementation.
+ */
static const uint32_t uplcom_rates[] = {
- 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400,
- 19200, 28800, 38400, 57600, 115200,
/*
- * Higher speeds are probably possible. PL2303X supports up to
- * 6Mb and can set any rate
+ * Basic 'standard' speed rates, supported by all models
+ * NOTE: 900 and 56000 actually works as well
*/
- 230400, 460800, 614400, 921600, 1228800
+ 75, 150, 300, 600, 900, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400,
+ 19200, 28800, 38400, 56000, 57600, 115200,
+ /*
+ * Advanced speed rates up to 6Mbs, supported by HX/TA and HXD/TB/EA/RA
+ * NOTE: regardless of the spec, 256000 does not work
+ */
+ 128000, 134400, 161280, 201600, 230400, 268800, 403200, 460800, 614400,
+ 806400, 921600, 1228800, 2457600, 3000000, 6000000,
+ /*
+ * Advanced speed rates up to 12, supported by HXD/TB/EA/RA
+ */
+ 12000000
};
#define N_UPLCOM_RATES nitems(uplcom_rates)
static int
+uplcom_baud_supported(unsigned int speed)
+{
+ int i;
+ for (i = 0; i < N_UPLCOM_RATES; i++) {
+ if (uplcom_rates[i] == speed)
+ return 1;
+ }
+ return 0;
+}
+
+static int
uplcom_pre_param(struct ucom_softc *ucom, struct termios *t)
{
struct uplcom_softc *sc = ucom->sc_parent;
- uint8_t i;
DPRINTF("\n");
@@ -660,26 +729,75 @@ uplcom_pre_param(struct ucom_softc *ucom, struct termios *t)
* Check requested baud rate.
*
* The PL2303 can only set specific baud rates, up to 1228800 baud.
- * The PL2303X can set any baud rate up to 6Mb.
+ * The PL2303HX can set any baud rate up to 6Mb.
* The PL2303HX rev. D can set any baud rate up to 12Mb.
*
- * XXX: We currently cannot identify the PL2303HX rev. D, so treat
- * it the same as the PL2303X.
*/
- if (sc->sc_chiptype != TYPE_PL2303HX) {
- for (i = 0; i < N_UPLCOM_RATES; i++) {
- if (uplcom_rates[i] == t->c_ospeed)
+
+ /* accept raw divisor data, if someone wants to do the math in user domain */
+ if (t->c_ospeed & 0x80000000)
+ return 0;
+ switch (sc->sc_chiptype) {
+ case TYPE_PL2303HXD:
+ if (t->c_ospeed <= 12000000)
return (0);
- }
- } else {
- if (t->c_ospeed <= 6000000)
- return (0);
+ break;
+ case TYPE_PL2303HX:
+ if (t->c_ospeed <= 6000000)
+ return (0);
+ break;
+ default:
+ if (uplcom_baud_supported(t->c_ospeed))
+ return (0);
+ break;
}
DPRINTF("uplcom_param: bad baud rate (%d)\n", t->c_ospeed);
return (EIO);
}
+static unsigned int
+uplcom_encode_baud_rate_divisor(uint8_t *buf, unsigned int baud)
+{
+ unsigned int baseline, mantissa, exponent;
+
+ /* Determine the baud rate divisor. This algorithm is taken from Linux. */
+ /*
+ * Apparently the formula is:
+ * baudrate = baseline / (mantissa * 4^exponent)
+ * where
+ * mantissa = buf[8:0]
+ * exponent = buf[11:9]
+ */
+ if (baud == 0)
+ baud = 1;
+ baseline = 383385600;
+ mantissa = baseline / baud;
+ if (mantissa == 0)
+ mantissa = 1;
+ exponent = 0;
+ while (mantissa >= 512) {
+ if (exponent < 7) {
+ mantissa >>= 2; /* divide by 4 */
+ exponent++;
+ } else {
+ /* Exponent is maxed. Trim mantissa and leave. This gives approx. 45.8 baud */
+ mantissa = 511;
+ break;
+ }
+ }
+
+ buf[3] = 0x80;
+ buf[2] = 0;
+ buf[1] = exponent << 1 | mantissa >> 8;
+ buf[0] = mantissa & 0xff;
+
+ /* Calculate and return the exact baud rate. */
+ baud = (baseline / mantissa) >> (exponent << 1);
+ DPRINTF("real baud rate will be %u\n", baud);
+
+ return baud;
+}
static void
uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
{
@@ -691,10 +809,24 @@ uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
memset(&ls, 0, sizeof(ls));
- USETDW(ls.dwDTERate, t->c_ospeed);
+ /*
+ * NOTE: If unsupported baud rates are set directly, the PL2303* uses 9600 baud.
+ */
+ if ((t->c_ospeed & 0x80000000) || uplcom_baud_supported(t->c_ospeed))
+ USETDW(ls.dwDTERate, t->c_ospeed);
+ else
+ t->c_ospeed = uplcom_encode_baud_rate_divisor((uint8_t*)&ls.dwDTERate, t->c_ospeed);
if (t->c_cflag & CSTOPB) {
- ls.bCharFormat = UCDC_STOP_BIT_2;
+ if ((t->c_cflag & CSIZE) == CS5) {
+ /*
+ * NOTE: Comply with "real" UARTs / RS232:
+ * use 1.5 instead of 2 stop bits with 5 data bits
+ */
+ ls.bCharFormat = UCDC_STOP_BIT_1_5;
+ } else {
+ ls.bCharFormat = UCDC_STOP_BIT_2;
+ }
} else {
ls.bCharFormat = UCDC_STOP_BIT_1;
}
@@ -724,7 +856,7 @@ uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
break;
}
- DPRINTF("rate=%d fmt=%d parity=%d bits=%d\n",
+ DPRINTF("rate=0x%08x fmt=%d parity=%d bits=%d\n",
UGETDW(ls.dwDTERate), ls.bCharFormat,
ls.bParityType, ls.bDataBits);
@@ -745,7 +877,7 @@ uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UPLCOM_SET_REQUEST;
USETW(req.wValue, 0);
- if (sc->sc_chiptype == TYPE_PL2303HX)
+ if (sc->sc_chiptype != TYPE_PL2303)
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X);
else
USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
@@ -811,7 +943,6 @@ uplcom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
DPRINTF("\n");
- /* XXX Note: sc_lsr is always zero */
*lsr = sc->sc_lsr;
*msr = sc->sc_msr;
}
@@ -836,18 +967,33 @@ uplcom_intr_callback(struct usb_xfer *xfer, usb_error_t error)
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, buf, sizeof(buf));
- DPRINTF("status = 0x%02x\n", buf[8]);
+ DPRINTF("status = 0x%02x\n", buf[UPLCOM_STATE_INDEX]);
sc->sc_lsr = 0;
sc->sc_msr = 0;
- if (buf[8] & RSAQ_STATUS_CTS) {
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_CTS) {
sc->sc_msr |= SER_CTS;
}
- if (buf[8] & RSAQ_STATUS_DSR) {
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_OVERRUN_ERROR) {
+ sc->sc_lsr |= ULSR_OE;
+ }
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_PARITY_ERROR) {
+ sc->sc_lsr |= ULSR_PE;
+ }
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_FRAME_ERROR) {
+ sc->sc_lsr |= ULSR_FE;
+ }
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_RING) {
+ sc->sc_msr |= SER_RI;
+ }
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_BREAK_ERROR) {
+ sc->sc_lsr |= ULSR_BI;
+ }
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_DSR) {
sc->sc_msr |= SER_DSR;
}
- if (buf[8] & RSAQ_STATUS_DCD) {
+ if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_DCD) {
sc->sc_msr |= SER_DCD;
}
ucom_status_change(&sc->sc_ucom);
diff --git a/freebsd/sys/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h
index 147b5d5e..d5648c03 100644
--- a/freebsd/sys/dev/usb/usbdi.h
+++ b/freebsd/sys/dev/usb/usbdi.h
@@ -342,13 +342,13 @@ struct usb_device_id {
#define USB_STD_PNP_HOST_INFO USB_STD_PNP_INFO "T:mode=host;"
#define USB_STD_PNP_DEVICE_INFO USB_STD_PNP_INFO "T:mode=device;"
#define USB_PNP_HOST_INFO(table) \
- MODULE_PNP_INFO(USB_STD_PNP_HOST_INFO, uhub, table, table, sizeof(table[0]), \
+ MODULE_PNP_INFO(USB_STD_PNP_HOST_INFO, uhub, table, table, \
sizeof(table) / sizeof(table[0]))
#define USB_PNP_DEVICE_INFO(table) \
- MODULE_PNP_INFO(USB_STD_PNP_DEVICE_INFO, uhub, table, table, sizeof(table[0]), \
+ MODULE_PNP_INFO(USB_STD_PNP_DEVICE_INFO, uhub, table, table, \
sizeof(table) / sizeof(table[0]))
#define USB_PNP_DUAL_INFO(table) \
- MODULE_PNP_INFO(USB_STD_PNP_INFO, uhub, table, table, sizeof(table[0]), \
+ MODULE_PNP_INFO(USB_STD_PNP_INFO, uhub, table, table, \
sizeof(table) / sizeof(table[0]))
/* check that the size of the structure above is correct */