Module Name:    src
Committed By:   simonb
Date:           Sun Apr 12 01:10:54 UTC 2020

Modified Files:
        src/distrib/sets/lists/man: mi
        src/share/man/man4: Makefile ucom.4
        src/sys/dev/usb: files.usb ukyopon.c umodem.c umodem_common.c
            usbdevices.config usbdevs
Added Files:
        src/share/man/man4: uxrcom.4
        src/sys/dev/usb: uxrcom.c

Log Message:
Add uxrcom driver for Exar XR21V141x USB serial adapters.  Based in part
on the OpenBSD single-port XR21V1410 uxrcom driver, but adds support
for multi-port chipsets and uses the common umodem framework instead of
being a standalone driver.

Thanks to skrll@ for much USB clue and mrg@ for financing the
development of this driver.


To generate a diff of this commit:
cvs rdiff -u -r1.1686 -r1.1687 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.703 -r1.704 src/share/man/man4/Makefile
cvs rdiff -u -r1.27 -r1.28 src/share/man/man4/ucom.4
cvs rdiff -u -r0 -r1.1 src/share/man/man4/uxrcom.4
cvs rdiff -u -r1.172 -r1.173 src/sys/dev/usb/files.usb
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/usb/ukyopon.c
cvs rdiff -u -r1.73 -r1.74 src/sys/dev/usb/umodem.c
cvs rdiff -u -r1.32 -r1.33 src/sys/dev/usb/umodem_common.c
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/usb/usbdevices.config
cvs rdiff -u -r1.780 -r1.781 src/sys/dev/usb/usbdevs
cvs rdiff -u -r0 -r1.1 src/sys/dev/usb/uxrcom.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1686 src/distrib/sets/lists/man/mi:1.1687
--- src/distrib/sets/lists/man/mi:1.1686	Sat Apr  4 15:39:16 2020
+++ src/distrib/sets/lists/man/mi	Sun Apr 12 01:10:53 2020
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1686 2020/04/04 15:39:16 jdolecek Exp $
+# $NetBSD: mi,v 1.1687 2020/04/12 01:10:53 simonb Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -1957,6 +1957,7 @@
 ./usr/share/man/cat4/uvideo.0			man-sys-catman		.cat
 ./usr/share/man/cat4/uvisor.0			man-sys-catman		.cat
 ./usr/share/man/cat4/uvscom.0			man-sys-catman		.cat
+./usr/share/man/cat4/uxrcom.0			man-sys-catman		.cat
 ./usr/share/man/cat4/uyap.0			man-sys-catman		.cat
 ./usr/share/man/cat4/uyurex.0			man-obsolete		obsolete
 ./usr/share/man/cat4/vald.0			man-sys-catman		.cat
@@ -5101,6 +5102,7 @@
 ./usr/share/man/html4/uvideo.html		man-sys-htmlman		html
 ./usr/share/man/html4/uvisor.html		man-sys-htmlman		html
 ./usr/share/man/html4/uvscom.html		man-sys-htmlman		html
+./usr/share/man/html4/uxrcom.html		man-sys-htmlman		html
 ./usr/share/man/html4/uyap.html			man-sys-htmlman		html
 ./usr/share/man/html4/uyurex.html		man-obsolete		obsolete
 ./usr/share/man/html4/vald.html			man-sys-htmlman		html
@@ -8169,6 +8171,7 @@
 ./usr/share/man/man4/uvideo.4			man-sys-man		.man
 ./usr/share/man/man4/uvisor.4			man-sys-man		.man
 ./usr/share/man/man4/uvscom.4			man-sys-man		.man
+./usr/share/man/man4/uxrcom.4			man-sys-man		.man
 ./usr/share/man/man4/uyap.4			man-sys-man		.man
 ./usr/share/man/man4/uyurex.4			man-obsolete		obsolete
 ./usr/share/man/man4/vald.4			man-sys-man		.man

Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.703 src/share/man/man4/Makefile:1.704
--- src/share/man/man4/Makefile:1.703	Sat Apr  4 15:39:13 2020
+++ src/share/man/man4/Makefile	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.703 2020/04/04 15:39:13 jdolecek Exp $
+#	$NetBSD: Makefile,v 1.704 2020/04/12 01:10:54 simonb Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/18/93
 
 MAN=	aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@@ -87,8 +87,8 @@ MAN+=	atu.4 aubtfwl.4 aue.4 axe.4 axen.4
 	ulpt.4 umass.4 umcs.4 umct.4 umidi.4 umodem.4 ums.4 upgt.4 upl.4 \
 	uplcom.4 ure.4 url.4 urndis.4 urtw.4 urtwn.4 \
 	usb.4 usbnet.4 uscanner.4 uslsa.4 usmsc.4 usscanner.4 \
-	ustir.4 uthum.4 utoppy.4 uts.4 uvideo.4 uvisor.4 uvscom.4 uyap.4 \
-	xhci.4 \
+	ustir.4 uthum.4 utoppy.4 uts.4 uvideo.4 uvisor.4 uvscom.4 uxrcom.4 \
+	uyap.4 xhci.4 \
 
 # Ir devices
 MAN+=	irframe.4 cir.4 irframetty.4 oboe.4

Index: src/share/man/man4/ucom.4
diff -u src/share/man/man4/ucom.4:1.27 src/share/man/man4/ucom.4:1.28
--- src/share/man/man4/ucom.4:1.27	Sun May  5 00:12:34 2019
+++ src/share/man/man4/ucom.4	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-.\" $NetBSD: ucom.4,v 1.27 2019/05/05 00:12:34 pgoyette Exp $
+.\" $NetBSD: ucom.4,v 1.28 2020/04/12 01:10:54 simonb Exp $
 .\"
 .\" Copyright (c) 1999 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -50,6 +50,7 @@
 .Cd "ucom* at uslsa?"
 .Cd "ucom* at uvisor? portno ?"
 .Cd "ucom* at uvscom?"
+.Cd "ucom* at uxrcom?"
 .Sh DESCRIPTION
 The
 .Nm
@@ -103,7 +104,8 @@ are used for dial-out.
 .Xr usb 4 ,
 .Xr uslsa 4 ,
 .Xr uvisor 4 ,
-.Xr uvscom 4
+.Xr uvscom 4 ,
+.Xr uxrcom 4
 .Sh HISTORY
 The
 .Nm

Index: src/sys/dev/usb/files.usb
diff -u src/sys/dev/usb/files.usb:1.172 src/sys/dev/usb/files.usb:1.173
--- src/sys/dev/usb/files.usb:1.172	Sun Feb  9 15:46:15 2020
+++ src/sys/dev/usb/files.usb	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: files.usb,v 1.172 2020/02/09 15:46:15 maya Exp $
+#	$NetBSD: files.usb,v 1.173 2020/04/12 01:10:54 simonb Exp $
 #
 # Config file and device description for machine-independent USB code.
 # Included by ports that need it.  Ports that use it must provide
@@ -429,6 +429,11 @@ device	uvscom: ucombus
 attach	uvscom at usbdevif
 file	dev/usb/uvscom.c		uvscom
 
+# Exar XR21V141x serial driver (mostly CDC)
+device	uxrcom: ucombus, umodem_common
+attach	uxrcom at usbifif
+file	dev/usb/uxrcom.c		uxrcom
+
 # Belkin & other serial driver
 define	ubsa_common
 file	dev/usb/ubsa_common.c		ubsa_common

Index: src/sys/dev/usb/ukyopon.c
diff -u src/sys/dev/usb/ukyopon.c:1.25 src/sys/dev/usb/ukyopon.c:1.26
--- src/sys/dev/usb/ukyopon.c:1.25	Tue Jan  7 06:42:26 2020
+++ src/sys/dev/usb/ukyopon.c	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: ukyopon.c,v 1.25 2020/01/07 06:42:26 maxv Exp $	*/
+/*	$NetBSD: ukyopon.c,v 1.26 2020/04/12 01:10:54 simonb Exp $	*/
 
 /*
  * Copyright (c) 1998, 2005 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ukyopon.c,v 1.25 2020/01/07 06:42:26 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ukyopon.c,v 1.26 2020/04/12 01:10:54 simonb Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -130,6 +130,8 @@ ukyopon_attach(device_t parent, device_t
 	struct usbif_attach_arg *uiaa = aux;
 	struct ucom_attach_args ucaa;
 
+	memset(&ucaa, 0, sizeof(ucaa));
+
 	ucaa.ucaa_portno = (uiaa->uiaa_ifaceno == UKYOPON_MODEM_IFACE_INDEX) ?
 		UKYOPON_PORT_MODEM : UKYOPON_PORT_DATA;
 	ucaa.ucaa_methods = &ukyopon_methods;

Index: src/sys/dev/usb/umodem.c
diff -u src/sys/dev/usb/umodem.c:1.73 src/sys/dev/usb/umodem.c:1.74
--- src/sys/dev/usb/umodem.c:1.73	Tue Jan  7 06:42:26 2020
+++ src/sys/dev/usb/umodem.c	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: umodem.c,v 1.73 2020/01/07 06:42:26 maxv Exp $	*/
+/*	$NetBSD: umodem.c,v 1.74 2020/04/12 01:10:54 simonb Exp $	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umodem.c,v 1.73 2020/01/07 06:42:26 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umodem.c,v 1.74 2020/04/12 01:10:54 simonb Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -114,6 +114,8 @@ umodem_attach(device_t parent, device_t 
 	struct usbif_attach_arg *uiaa = aux;
 	struct ucom_attach_args ucaa;
 
+	memset(&ucaa, 0, sizeof(ucaa));
+
 	ucaa.ucaa_portno = UCOM_UNK_PORTNO;
 	ucaa.ucaa_methods = &umodem_methods;
 	ucaa.ucaa_info = NULL;

Index: src/sys/dev/usb/umodem_common.c
diff -u src/sys/dev/usb/umodem_common.c:1.32 src/sys/dev/usb/umodem_common.c:1.33
--- src/sys/dev/usb/umodem_common.c:1.32	Sat Mar 14 02:35:33 2020
+++ src/sys/dev/usb/umodem_common.c	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: umodem_common.c,v 1.32 2020/03/14 02:35:33 christos Exp $	*/
+/*	$NetBSD: umodem_common.c,v 1.33 2020/04/12 01:10:54 simonb Exp $	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umodem_common.c,v 1.32 2020/03/14 02:35:33 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umodem_common.c,v 1.33 2020/04/12 01:10:54 simonb Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -105,6 +105,12 @@ static void	umodem_break(struct umodem_s
 static void	umodem_set_line_state(struct umodem_softc *);
 static void	umodem_intr(struct usbd_xfer *, void *, usbd_status);
 
+/*
+ * NOTE: Callers of umodem_common_attach() should initialise their ucaa
+ * to 0 before assigning any fields.  ucaa_ibufsize, ucaa_ibufsize and
+ * ucaa_obufsize may be set by the caller, but if 0 are set to default
+ * umodem values.
+ */
 int
 umodem_common_attach(device_t self, struct umodem_softc *sc,
     struct usbif_attach_arg *uiaa, struct ucom_attach_args *ucaa)
@@ -239,10 +245,16 @@ umodem_common_attach(device_t self, stru
 
 	sc->sc_dtr = -1;
 
-	/* ucaa_bulkin, ucaa_bulkout set above */
-	ucaa->ucaa_ibufsize = UMODEMIBUFSIZE;
-	ucaa->ucaa_obufsize = UMODEMOBUFSIZE;
-	ucaa->ucaa_ibufsizepad = UMODEMIBUFSIZE;
+	/*
+	 * ucaa_bulkin, ucaa_bulkout set above.  ucaa_ibufsize,
+	 * ucaa_ibufsize, ucaa_obufsize may be initialised by caller
+	 */
+	if (ucaa->ucaa_ibufsize == 0)
+		ucaa->ucaa_ibufsize = UMODEMIBUFSIZE;
+	if (ucaa->ucaa_obufsize == 0)
+		ucaa->ucaa_obufsize = UMODEMOBUFSIZE;
+	if (ucaa->ucaa_ibufsizepad == 0)
+		ucaa->ucaa_ibufsizepad = UMODEMIBUFSIZE;
 	ucaa->ucaa_opkthdrlen = 0;
 	ucaa->ucaa_device = sc->sc_udev;
 	ucaa->ucaa_iface = sc->sc_data_iface;
@@ -356,7 +368,7 @@ umodem_intr(struct usbd_xfer *xfer, void
 			 sc->sc_notify_buf.data[0],
 			 sc->sc_notify_buf.data[1]));
 		/* Currently, lsr is always zero. */
-		sc->sc_lsr = sc->sc_msr = 0;
+	 	sc->sc_lsr = sc->sc_msr = 0;
 		mstatus = sc->sc_notify_buf.data[0];
 
 		if (ISSET(mstatus, UCDC_N_SERIAL_RI))

Index: src/sys/dev/usb/usbdevices.config
diff -u src/sys/dev/usb/usbdevices.config:1.37 src/sys/dev/usb/usbdevices.config:1.38
--- src/sys/dev/usb/usbdevices.config:1.37	Wed Jan 29 18:39:04 2020
+++ src/sys/dev/usb/usbdevices.config	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: usbdevices.config,v 1.37 2020/01/29 18:39:04 maya Exp $
+#	$NetBSD: usbdevices.config,v 1.38 2020/04/12 01:10:54 simonb Exp $
 #
 # This file contains all USB related configuration.
 # It is suitable for inclusion in a kernel config(5) file.
@@ -189,6 +189,9 @@ ucom*	at uvscom? portno ?
 umcs* at uhub? port ?	 	# Moschip MCS7xxx serial adapter
 ucom*	at umcs? portno ?
 
+uxrcom*	at uhub? port ?		# Exar XR21V141x serial adapter
+ucom*	at uxrcom? portno ?
+
 # RIM BlackBerry
 uberry* at uhub? port ?
 

Index: src/sys/dev/usb/usbdevs
diff -u src/sys/dev/usb/usbdevs:1.780 src/sys/dev/usb/usbdevs:1.781
--- src/sys/dev/usb/usbdevs:1.780	Sat Apr 11 06:54:59 2020
+++ src/sys/dev/usb/usbdevs	Sun Apr 12 01:10:54 2020
@@ -1,4 +1,4 @@
-$NetBSD: usbdevs,v 1.780 2020/04/11 06:54:59 jdolecek Exp $
+$NetBSD: usbdevs,v 1.781 2020/04/12 01:10:54 simonb Exp $
 
 /*-
  * Copyright (c) 1998-2004 The NetBSD Foundation, Inc.
@@ -153,6 +153,7 @@ vendor PANASONIC	0x04da	Panasonic (Matsu
 vendor HUANHSIN		0x04dc	Huan Hsin
 vendor SHARP		0x04dd	Sharp
 vendor IIYAMA		0x04e1	Iiyama
+vendor EXAR		0x04e2	Exar
 vendor SHUTTLE		0x04e6	Shuttle Technology
 vendor SAMSUNG		0x04e8	Samsung Electronics
 vendor ANNABOOKS	0x04ed	Annabooks
@@ -1583,6 +1584,11 @@ product EPSON 1670		0x011f	Perfection 16
 /* e-TEK Labs products */
 product ETEK 1COM		0x8007	Serial port
 
+/* Exar products */
+product EXAR XR21V1410		0x1410	XR21V1410 1 channel UART
+product EXAR XR21V1412		0x1412	XR21V1412 2 channel UART
+product EXAR XR21V1414		0x1414	XR21V1414 4 channel UART
+
 /* Extended Systems products */
 product EXTENDED XTNDACCESS	0x0100	XTNDAccess IrDA
 

Added files:

Index: src/share/man/man4/uxrcom.4
diff -u /dev/null src/share/man/man4/uxrcom.4:1.1
--- /dev/null	Sun Apr 12 01:10:54 2020
+++ src/share/man/man4/uxrcom.4	Sun Apr 12 01:10:54 2020
@@ -0,0 +1,79 @@
+.\"	$OpenBSD: uxrcom.4,v 1.1 2019/03/27 22:11:21 kettenis Exp $
+.\"
+.\" Copyright (c) 2019 Mark Kettenis <kette...@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and 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.
+.\"
+.Dd $Mdocdate: March 27 2019 $
+.Dt UXRCOM 4
+.Os
+.Sh NAME
+.Nm uxrcom
+.Nd Exar XR21V141x USB serial adapter
+.Sh SYNOPSIS
+.Cd "uxrcom* at uhub?"
+.Cd "ucom* at uxrcom?"
+.Sh HARDWARE
+The
+.Nm
+driver supports serial adapters based on the
+XR21V1410, XR21V1412 and XR21V1414 chipsets.
+Devices range from single port to eight port (implemented as a
+USB hub and two
+.Nm
+four port instances behind it).
+Examples of hardware known to work with this driver are:
+.Pp
+.Bl -tag -width Dv -offset indent -compact
+.It Gearmo GM-U28RS232 8 Port USB to Serial DB9 RS232 Adapter
+.El
+.Sh DESCRIPTION
+The
+.Nm
+driver attaches the Exar XR21V141x multiport chipset with individual
+port drivers via
+.Xr ucom 4 ,
+which makes it behave like a
+.Xr tty 4 .
+.Sh SEE ALSO
+.Xr tty 4 ,
+.Xr ucom 4 ,
+.Xr uhub 4 ,
+.Xr modem 4 ,
+.Xr usb 4
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Ox 6.5
+and in
+.Nx 9.1 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver for the single port XR21V1410 was written by
+.An Mark Kettenis Aq Mt kette...@openbsd.org .
+The multi-port
+.Nx
+driver is based on the
+.Ox
+driver but uses the common
+.Xr umodem 4
+framework.
+The
+.Nx
+driver was written by
+by
+.An Simon Burge
+.Aq sim...@netbsd.org .

Index: src/sys/dev/usb/uxrcom.c
diff -u /dev/null src/sys/dev/usb/uxrcom.c:1.1
--- /dev/null	Sun Apr 12 01:10:54 2020
+++ src/sys/dev/usb/uxrcom.c	Sun Apr 12 01:10:54 2020
@@ -0,0 +1,323 @@
+/*	$NetBSD: uxrcom.c,v 1.1 2020/04/12 01:10:54 simonb Exp $	*/
+/*	$OpenBSD: uxrcom.c,v 1.1 2019/03/27 22:08:51 kettenis Exp $	*/
+
+/*
+ * Copyright (c) 1998, 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lenn...@augustsson.net) at
+ * Carlstedt Research & Technology and Simon Burge.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2006 Jonathan Gray <j...@openbsd.org>
+ *
+ * Permission to use, copy, modify, and 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 <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: uxrcom.c,v 1.1 2020/04/12 01:10:54 simonb Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/tty.h>
+#include <sys/device.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbcdc.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdevs.h>
+#include <dev/usb/usbhist.h>
+
+#include <dev/usb/usbdevs.h>
+#include <dev/usb/ucomvar.h>
+#include <dev/usb/umodemvar.h>
+
+
+#define UXRCOMBUFSZ		64
+
+/* XXX uxrcomreg.h */
+#define XR_SET_REG		0
+#define XR_GET_REGN		1
+
+#define XR_FLOW_CONTROL		0x000c
+#define  XR_FLOW_CONTROL_ON	1
+#define  XR_FLOW_CONTROL_OFF	0
+#define XR_TX_BREAK		0x0014
+#define  XR_TX_BREAK_ON		1
+#define  XR_TX_BREAK_OFF	0
+#define XR_GPIO_SET		0x001d
+#define XR_GPIO_CLEAR		0x001e
+#define  XR_GPIO3		(1 << 3)
+#define  XR_GPIO5		(1 << 5)
+
+/* for XR_SET_REG/XR_GET_REGN specify which uart block to use */
+#define	XR_UART_BLOCK(sc)	(((sc)->sc_ctl_iface_no / 2) << NBBY)
+
+#ifdef UXRCOM_DEBUG
+#define	DPRINTF(x)	if (uxrcomdebug) printf x
+int uxrcomdebug = 0;
+#else
+#define	DPRINTF(x)
+#endif
+
+
+static void	uxrcom_set(void *, int, int, int);
+static int	uxrcom_param(void *, int, struct termios *);
+static void	uxrcom_break(void *, int, int);
+
+static const struct	ucom_methods uxrcom_methods = {
+	.ucom_get_status = umodem_get_status,
+	.ucom_set = uxrcom_set,
+	.ucom_param = uxrcom_param,
+	.ucom_ioctl = NULL,	/* TODO */
+	.ucom_open = umodem_open,
+	.ucom_close = umodem_close,
+};
+
+static const struct usb_devno uxrcom_devs[] = {
+	{ USB_VENDOR_EXAR,	USB_PRODUCT_EXAR_XR21V1410 },
+	{ USB_VENDOR_EXAR,	USB_PRODUCT_EXAR_XR21V1412 },
+	{ USB_VENDOR_EXAR,	USB_PRODUCT_EXAR_XR21V1414 },
+};
+#define uxrcom_lookup(v, p) usb_lookup(uxrcom_devs, v, p)
+
+static int uxrcom_match(device_t, cfdata_t, void *);
+static void uxrcom_attach(device_t, device_t, void *);
+static int uxrcom_detach(device_t, int);
+
+CFATTACH_DECL_NEW(uxrcom, sizeof(struct umodem_softc), uxrcom_match,
+    uxrcom_attach, uxrcom_detach, NULL);
+
+static int
+uxrcom_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct usbif_attach_arg *uiaa = aux;
+
+	if (uiaa->uiaa_class != UICLASS_CDC ||
+	    uiaa->uiaa_subclass != UISUBCLASS_ABSTRACT_CONTROL_MODEL ||
+	    !(uiaa->uiaa_proto == UIPROTO_CDC_NOCLASS ||
+	      uiaa->uiaa_proto == UIPROTO_CDC_AT))
+		return UMATCH_NONE;
+
+	return uxrcom_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ?
+		UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
+}
+
+static void
+uxrcom_attach(device_t parent, device_t self, void *aux)
+{
+	struct umodem_softc *sc = device_private(self);
+	struct usbif_attach_arg *uiaa = aux;
+	struct ucom_attach_args ucaa;
+
+	memset(&ucaa, 0, sizeof(ucaa));
+
+	ucaa.ucaa_portno = UCOM_UNK_PORTNO;
+	ucaa.ucaa_methods = &uxrcom_methods;
+	ucaa.ucaa_info = NULL;
+
+	ucaa.ucaa_ibufsize = UXRCOMBUFSZ;
+	ucaa.ucaa_obufsize = UXRCOMBUFSZ;
+	ucaa.ucaa_ibufsizepad = UXRCOMBUFSZ;
+
+	if (!pmf_device_register(self, NULL, NULL))
+		aprint_error_dev(self, "couldn't establish power handler");
+
+	if (umodem_common_attach(self, sc, uiaa, &ucaa))
+		return;
+	return;
+}
+
+static int
+uxrcom_detach(device_t self, int flags)
+{
+	struct umodem_softc *sc = device_private(self);
+
+	pmf_device_deregister(self);
+
+	return umodem_common_detach(sc, flags);
+}
+
+static void
+uxrcom_set(void *addr, int portno, int reg, int onoff)
+{
+	struct umodem_softc *sc = addr;
+	usb_device_request_t req;
+	uint16_t index;
+	uint8_t value;
+
+	if (sc->sc_dying)
+		return;
+
+	index = onoff ? XR_GPIO_SET : XR_GPIO_CLEAR;
+
+	switch (reg) {
+	case UCOM_SET_DTR:
+		value = XR_GPIO3;
+		break;
+	case UCOM_SET_RTS:
+		value = XR_GPIO5;
+		break;
+	case UCOM_SET_BREAK:
+		uxrcom_break(sc, portno, onoff);
+		return;
+	default:
+		return;
+	}
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = XR_SET_REG;
+	USETW(req.wValue, value);
+	USETW(req.wIndex, index | XR_UART_BLOCK(sc));
+	USETW(req.wLength, 0);
+	usbd_do_request(sc->sc_udev, &req, NULL);
+}
+
+static usbd_status
+uxrcom_set_line_coding(struct umodem_softc *sc, usb_cdc_line_state_t *state)
+{
+	usb_device_request_t req;
+	usbd_status err;
+
+	DPRINTF(("%s: rate=%d fmt=%d parity=%d bits=%d\n", __func__,
+		UGETDW(state->dwDTERate), state->bCharFormat,
+		state->bParityType, state->bDataBits));
+
+	if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
+		DPRINTF(("%s: already set\n", __func__));
+		return USBD_NORMAL_COMPLETION;
+	}
+
+	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+	req.bRequest = UCDC_SET_LINE_CODING;
+	USETW(req.wValue, 0);
+	USETW(req.wIndex, sc->sc_ctl_iface_no);
+	USETW(req.wLength, UCDC_LINE_STATE_LENGTH);
+
+	err = usbd_do_request(sc->sc_udev, &req, state);
+	if (err) {
+		DPRINTF(("%s: failed, err=%u\n", __func__, err));
+		return err;
+	}
+
+	sc->sc_line_state = *state;
+
+	return USBD_NORMAL_COMPLETION;
+}
+
+static int
+uxrcom_param(void *addr, int portno, struct termios *t)
+{
+	struct umodem_softc *sc = addr;
+	usb_device_request_t req;
+	usbd_status err;
+	usb_cdc_line_state_t ls;
+	uint8_t flowctrl;
+
+	if (sc->sc_dying)
+		return EIO;
+
+	/* slowest supported baud rate is 1200 bps, max is 12 Mbps */
+	if (t->c_ospeed < 1200 || t->c_ospeed > 12000000)
+		return (EINVAL);
+
+	USETDW(ls.dwDTERate, t->c_ospeed);
+	if (ISSET(t->c_cflag, CSTOPB))
+		ls.bCharFormat = UCDC_STOP_BIT_2;
+	else
+		ls.bCharFormat = UCDC_STOP_BIT_1;
+	if (ISSET(t->c_cflag, PARENB)) {
+		if (ISSET(t->c_cflag, PARODD))
+			ls.bParityType = UCDC_PARITY_ODD;
+		else
+			ls.bParityType = UCDC_PARITY_EVEN;
+	} else
+		ls.bParityType = UCDC_PARITY_NONE;
+	switch (ISSET(t->c_cflag, CSIZE)) {
+	case CS5:
+		ls.bDataBits = 5;
+		break;
+	case CS6:
+		ls.bDataBits = 6;
+		break;
+	case CS7:
+		ls.bDataBits = 7;
+		break;
+	case CS8:
+		ls.bDataBits = 8;
+		break;
+	}
+
+	err = uxrcom_set_line_coding(sc, &ls);
+	if (err) {
+		DPRINTF(("%s: err=%u\n", __func__, err));
+		return EIO;
+	}
+
+	if (ISSET(t->c_cflag, CRTSCTS)) {
+		/*  rts/cts flow ctl */
+		flowctrl = XR_FLOW_CONTROL_ON;
+	} else {
+		/* disable flow ctl */
+		flowctrl = XR_FLOW_CONTROL_OFF;
+	}
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = XR_SET_REG;
+	USETW(req.wValue, flowctrl);
+	USETW(req.wIndex, XR_FLOW_CONTROL | XR_UART_BLOCK(sc));
+	USETW(req.wLength, 0);
+	usbd_do_request(sc->sc_udev, &req, NULL);
+
+	return (0);
+}
+
+static void
+uxrcom_break(void *addr, int portno, int onoff)
+{
+	struct umodem_softc *sc = addr;
+	usb_device_request_t req;
+	uint8_t brk = onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF;
+
+	DPRINTF(("%s: port=%d onoff=%d\n", __func__, portno, onoff));
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = XR_SET_REG;
+	USETW(req.wValue, brk);
+	USETW(req.wIndex, XR_TX_BREAK | XR_UART_BLOCK(sc));
+	USETW(req.wLength, 0);
+
+	(void)usbd_do_request(sc->sc_udev, &req, 0);
+}

Reply via email to