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); +}