From: Hasso Tepper Date: Tue, 14 Aug 2007 08:53:59 +0000 (+0000) Subject: Add uslcom(4) driver which provides support for USB devices based on X-Git-Tag: v2.0.1~2388 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/2fe7d695bf67df1dde39a4743f7e09a221d560f3 Add uslcom(4) driver which provides support for USB devices based on Silicon Laboratories CP120x USB-UART bridges. Obtained-from: OpenBSD --- diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 7e81dbdaad..fadb749bc0 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,6 +1,6 @@ # @(#)Makefile 8.1 (Berkeley) 6/18/93 # $FreeBSD: src/share/man/man4/Makefile,v 1.83.2.66 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/share/man/man4/Makefile,v 1.58 2007/06/24 10:47:48 swildner Exp $ +# $DragonFly: src/share/man/man4/Makefile,v 1.59 2007/08/14 08:53:58 hasso Exp $ MAN= aac.4 \ acpi.4 \ @@ -282,6 +282,7 @@ MAN= aac.4 \ urio.4 \ usb.4 \ uscanner.4 \ + uslcom.4 \ uvisor.4 \ uvscom.4 \ vga.4 \ diff --git a/share/man/man4/uslcom.4 b/share/man/man4/uslcom.4 new file mode 100644 index 0000000000..78402de2fe --- /dev/null +++ b/share/man/man4/uslcom.4 @@ -0,0 +1,82 @@ +.\" $DragonFly: src/share/man/man4/uslcom.4,v 1.1 2007/08/14 08:53:58 hasso Exp $ +.\" $OpenBSD: uslcom.4,v 1.4 2007/02/17 01:47:47 jsg Exp $ +.\" +.\" Copyright (c) 2006 Jonathan Gray +.\" +.\" 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$ +.Dt USLCOM 4 +.Os +.Sh NAME +.Nm uslcom +.Nd Silicon Laboratories CP2101/CP2102 based USB serial adapter +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device uslcom" +.Cd "device ucom" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +uslcom_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver supports Silicon Laboratories CP2101/CP2102 based serial adapters. +.Pp +The following devices should work with the +.Nm +driver: +.Bd -literal -offset indent +Argussoft ISP +Baltech card reader +Burnside Telecom Desktop Mobile +chip45.com Crumb128 module +Jablotron PC-60B +Lipowsky Baby-JTAG +Lipowsky Baby-LIN +Lipowsky HARP-1 +Pololu USB to Serial +Silicon Laboratories CP2101 +Silicon Laboratories CP2102 +.Ed +.Sh SEE ALSO +.Xr tty 4 , +.Xr ucom 4 , +.Xr usb 4 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Ox 4.0 +and was imported into +.Dx 1.11 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Jonathan Gray +.Aq jsg@openbsd.org . +.Sh CAVEATS +Setting hardware flow control is not currently supported. +.Pp +Silicon Laboratories don't release any programming information +on their products. diff --git a/sys/bus/usb/usbdevs.h b/sys/bus/usb/usbdevs.h index 3c43590116..e495d988b9 100644 --- a/sys/bus/usb/usbdevs.h +++ b/sys/bus/usb/usbdevs.h @@ -1,10 +1,10 @@ -/* $DragonFly: src/sys/bus/usb/Attic/usbdevs.h,v 1.19 2007/08/02 11:53:30 hasso Exp $ */ +/* $DragonFly: src/sys/bus/usb/Attic/usbdevs.h,v 1.20 2007/08/14 08:53:58 hasso Exp $ */ /* * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * DragonFly: src/sys/bus/usb/usbdevs,v 1.24 2007/08/02 11:37:24 hasso Exp + * DragonFly: src/sys/bus/usb/usbdevs,v 1.25 2007/08/14 08:42:34 hasso Exp */ /* $FreeBSD: src/sys/dev/usb/usbdevs,v 1.203 2004/09/20 04:56:13 sanpei Exp $ */ /* $NetBSD: usbdevs,v 1.387 2004/10/27 07:02:47 augustss Exp $ */ @@ -916,6 +916,9 @@ /* Avision products */ #define USB_PRODUCT_AVISION_1200U 0x0268 /* 1200U scanner */ +/* Baltech products */ +#define USB_PRODUCT_BALTECH_CARDREADER 0x9999 /* Card reader */ + /* B&B Electronics products */ #define USB_PRODUCT_BBELECTRONICS_USOTL4 0xAC01 /* uLinks Isolated RS-422/485 to USB adapter */ @@ -1167,6 +1170,9 @@ #define USB_PRODUCT_DLINK2_DWLG122C1 0x3c03 /* DWL-G122 rev C1 */ #define USB_PRODUCT_DLINK2_WUA1340 0x3c04 /* WUA-1340 */ +/* Dynastream Innovations */ +#define USB_PRODUCT_DYNASTREAM_ANTDEVBOARD 0x1003 /* ANT dev board */ + /* eGalax Products */ #define USB_PRODUCT_EGALAX_TPANEL 0x0001 /* Touch Panel */ #define USB_PRODUCT_EGALAX_TPANEL2 0x0002 /* Touch Panel */ @@ -1540,6 +1546,9 @@ /* Ituner networks products */ #define USB_PRODUCT_ITUNERNET_USBLCD2X20 0x0002 /* USB-LCD 2x20 */ +/* Jablotron products */ +#define USB_PRODUCT_JABLOTRON_PC60B 0x0001 /* PC-60B */ + /* Jaton products */ #define USB_PRODUCT_JATON_EDA 0x5704 /* Ethernet Device Adapter */ @@ -2305,6 +2314,22 @@ #define USB_PRODUCT_SIIG2_USBTOETHER 0x0109 /* USB TO Ethernet */ #define USB_PRODUCT_SIIG2_US2308 0x0421 /* Serial */ +/* Silicon Labs products */ +#define USB_PRODUCT_SILABS_POLOLU 0x803b /* Pololu Serial */ +#define USB_PRODUCT_SILABS_ARGUSISP 0x8066 /* Argussoft ISP */ +#define USB_PRODUCT_SILABS_CRUMB128 0x807a /* Crumb128 */ +#define USB_PRODUCT_SILABS_DEGREECONT 0x80ca /* Degree Controls */ +#define USB_PRODUCT_SILABS_SUNNTO 0x80f6 /* Suunto sports */ +#define USB_PRODUCT_SILABS_DESKTOPMOBILE 0x813d /* Burnside Desktop mobile */ +#define USB_PRODUCT_SILABS_IPLINK1220 0x815e /* IP-Link 1220 */ +#define USB_PRODUCT_SILABS_LIPOWSKY_JTAG 0x81c8 /* Lipowsky Baby-JTAG */ +#define USB_PRODUCT_SILABS_LIPOWSKY_LIN 0x81e2 /* Lipowsky Baby-LIN */ +#define USB_PRODUCT_SILABS_LIPOWSKY_HARP 0x8218 /* Lipowsky HARP-1 */ +#define USB_PRODUCT_SILABS_CP210X_1 0xea60 /* CP210x Serial */ +#define USB_PRODUCT_SILABS_CP210X_2 0xea61 /* CP210x Serial */ + +#define USB_PRODUCT_SILABS2_DCU11CLONE 0xaa26 /* DCU-11 clone */ + /* Silicom products */ #define USB_PRODUCT_SILICOM_U2E 0x0001 /* U2E */ #define USB_PRODUCT_SILICOM_GPE 0x0002 /* Psion Gold Port Ethernet */ @@ -2521,6 +2546,9 @@ /* Universal Access products */ #define USB_PRODUCT_UNIACCESS_PANACHE 0x0101 /* Panache Surf USB ISDN Adapter */ +/* USI products */ +#define USB_PRODUCT_USI_MC60 0x10c5 /* MC60 Serial */ + /* U.S. Robotics products */ #define USB_PRODUCT_USR_USR1120 0x00eb /* USR1120 WLAN */ diff --git a/sys/bus/usb/usbdevs_data.h b/sys/bus/usb/usbdevs_data.h index e0bdff4fce..c42b5e4347 100644 --- a/sys/bus/usb/usbdevs_data.h +++ b/sys/bus/usb/usbdevs_data.h @@ -1,10 +1,10 @@ -/* $DragonFly: src/sys/bus/usb/Attic/usbdevs_data.h,v 1.19 2007/08/02 11:53:30 hasso Exp $ */ +/* $DragonFly: src/sys/bus/usb/Attic/usbdevs_data.h,v 1.20 2007/08/14 08:53:58 hasso Exp $ */ /* * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * DragonFly: src/sys/bus/usb/usbdevs,v 1.24 2007/08/02 11:37:24 hasso Exp + * DragonFly: src/sys/bus/usb/usbdevs,v 1.25 2007/08/14 08:42:34 hasso Exp */ /* $FreeBSD: src/sys/dev/usb/usbdevs,v 1.203 2004/09/20 04:56:13 sanpei Exp $ */ /* $NetBSD: usbdevs,v 1.387 2004/10/27 07:02:47 augustss Exp $ */ @@ -1007,6 +1007,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Avision", "1200U scanner", }, + { + USB_VENDOR_BALTECH, USB_PRODUCT_BALTECH_CARDREADER, + 0, + "Baltech", + "Card reader", + }, { USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USOTL4, 0, @@ -2015,6 +2021,12 @@ const struct usb_knowndev usb_knowndevs[] = { "D-Link", "WUA-1340", }, + { + USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD, + 0, + "Dynastream Innovations", + "ANT dev board", + }, { USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL, 0, @@ -3545,6 +3557,12 @@ const struct usb_knowndev usb_knowndevs[] = { "I-Tuner Networks", "USB-LCD 2x20", }, + { + USB_VENDOR_JABLOTRON, USB_PRODUCT_JABLOTRON_PC60B, + 0, + "Jablotron", + "PC-60B", + }, { USB_VENDOR_JATON, USB_PRODUCT_JATON_EDA, 0, @@ -6605,6 +6623,84 @@ const struct usb_knowndev usb_knowndevs[] = { "SIIG", "Serial", }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU, + 0, + "Silicon Labs", + "Pololu Serial", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARGUSISP, + 0, + "Silicon Labs", + "Argussoft ISP", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CRUMB128, + 0, + "Silicon Labs", + "Crumb128", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREECONT, + 0, + "Silicon Labs", + "Degree Controls", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SUNNTO, + 0, + "Silicon Labs", + "Suunto sports", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DESKTOPMOBILE, + 0, + "Silicon Labs", + "Burnside Desktop mobile", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_IPLINK1220, + 0, + "Silicon Labs", + "IP-Link 1220", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_JTAG, + 0, + "Silicon Labs", + "Lipowsky Baby-JTAG", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_LIN, + 0, + "Silicon Labs", + "Lipowsky Baby-LIN", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_HARP, + 0, + "Silicon Labs", + "Lipowsky HARP-1", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_1, + 0, + "Silicon Labs", + "CP210x Serial", + }, + { + USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_2, + 0, + "Silicon Labs", + "CP210x Serial", + }, + { + USB_VENDOR_SILABS2, USB_PRODUCT_SILABS2_DCU11CLONE, + 0, + "SILABS2", + "DCU-11 clone", + }, { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_U2E, 0, @@ -7313,6 +7409,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Universal Access", "Panache Surf USB ISDN Adapter", }, + { + USB_VENDOR_USI, USB_PRODUCT_USI_MC60, + 0, + "USI", + "MC60 Serial", + }, { USB_VENDOR_USR, USB_PRODUCT_USR_USR1120, 0, diff --git a/sys/conf/files b/sys/conf/files index bd33243a77..d126b84d16 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.169 2007/08/13 17:49:14 dillon Exp $ +# $DragonFly: src/sys/conf/files,v 1.170 2007/08/14 08:53:58 hasso Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -1192,6 +1192,7 @@ dev/usbmisc/umct/umct.c optional umct ucom dev/usbmisc/ums/ums.c optional ums dev/usbmisc/uplcom/uplcom.c optional uplcom ucom dev/usbmisc/urio/urio.c optional urio +dev/usbmisc/uplcom/uslcom.c optional uslcom ucom dev/usbmisc/ulpt/ulpt.c optional ulpt dev/usbmisc/ukbd/ukbd.c optional ukbd dev/usbmisc/umass/umass.c optional umass diff --git a/sys/dev/usbmisc/Makefile b/sys/dev/usbmisc/Makefile index a4386a1947..811ab31372 100644 --- a/sys/dev/usbmisc/Makefile +++ b/sys/dev/usbmisc/Makefile @@ -1,7 +1,7 @@ -# $DragonFly: src/sys/dev/usbmisc/Makefile,v 1.2 2006/12/13 20:19:04 dillon Exp $ +# $DragonFly: src/sys/dev/usbmisc/Makefile,v 1.3 2007/08/14 08:53:58 hasso Exp $ # SUBDIR= ubsa ucom ufm uftdi ugen uhid ukbd ulpt umass umodem ums \ - uplcom uscanner uvisor uvscom umct + uplcom uscanner uslcom uvisor uvscom umct .include diff --git a/sys/dev/usbmisc/uslcom/Makefile b/sys/dev/usbmisc/uslcom/Makefile new file mode 100644 index 0000000000..550e98979d --- /dev/null +++ b/sys/dev/usbmisc/uslcom/Makefile @@ -0,0 +1,10 @@ +# $DragonFly: src/sys/dev/usbmisc/uslcom/Makefile,v 1.1 2007/08/14 08:53:59 hasso Exp $ + +.PATH: ${.CURDIR}/../ucom + +KMOD= uslcom +SRCS= uslcom.c +NOMAN= +KMODDEPS= ucom + +.include diff --git a/sys/dev/usbmisc/uslcom/uslcom.c b/sys/dev/usbmisc/uslcom/uslcom.c new file mode 100644 index 0000000000..4be9fc7e7c --- /dev/null +++ b/sys/dev/usbmisc/uslcom/uslcom.c @@ -0,0 +1,464 @@ +/* $DragonFly: src/sys/dev/usbmisc/uslcom/uslcom.c,v 1.1 2007/08/14 08:53:59 hasso Exp $ */ +/* $OpenBSD: uslcom.c,v 1.12 2007/06/13 06:25:03 mbalmer Exp $ */ + +/* + * Copyright (c) 2006 Jonathan Gray + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#ifdef USLCOM_DEBUG +#define DPRINTFN(n, x) do { if (uslcomdebug > (n)) kprintf x; } while (0) +int uslcomdebug = 0; +#else +#define DPRINTFN(n, x) +#endif +#define DPRINTF(x) DPRINTFN(0, x) + +#define USLCOMBUFSZ 256 +#define USLCOM_CONFIG_NO 0 +#define USLCOM_IFACE_NO 0 + +#define USLCOM_SET_DATA_BITS(x) (x << 8) + +#define USLCOM_WRITE 0x41 +#define USLCOM_READ 0xc1 + +#define USLCOM_UART 0x00 +#define USLCOM_BAUD_RATE 0x01 +#define USLCOM_DATA 0x03 +#define USLCOM_BREAK 0x05 +#define USLCOM_CTRL 0x07 + +#define USLCOM_UART_DISABLE 0x00 +#define USLCOM_UART_ENABLE 0x01 + +#define USLCOM_CTRL_DTR_ON 0x0001 +#define USLCOM_CTRL_DTR_SET 0x0100 +#define USLCOM_CTRL_RTS_ON 0x0002 +#define USLCOM_CTRL_RTS_SET 0x0200 +#define USLCOM_CTRL_CTS 0x0010 +#define USLCOM_CTRL_DSR 0x0020 +#define USLCOM_CTRL_DCD 0x0080 + + +#define USLCOM_BAUD_REF 0x384000 + +#define USLCOM_STOP_BITS_1 0x00 +#define USLCOM_STOP_BITS_2 0x02 + +#define USLCOM_PARITY_NONE 0x00 +#define USLCOM_PARITY_ODD 0x10 +#define USLCOM_PARITY_EVEN 0x20 + +#define USLCOM_BREAK_OFF 0x00 +#define USLCOM_BREAK_ON 0x01 + + +struct uslcom_softc { + struct ucom_softc sc_ucom; + u_char sc_msr; + u_char sc_lsr; +}; + +void uslcom_get_status(void *, int portno, u_char *lsr, u_char *msr); +void uslcom_set(void *, int, int, int); +int uslcom_param(void *, int, struct termios *); +int uslcom_open(void *sc, int portno); +void uslcom_close(void *, int); +void uslcom_break(void *sc, int portno, int onoff); + +struct ucom_callback uslcom_callback = { + uslcom_get_status, + uslcom_set, + uslcom_param, + NULL, + uslcom_open, + uslcom_close, + NULL, + NULL, +}; + +static const struct usb_devno uslcom_devs[] = { + { USB_VENDOR_BALTECH, USB_PRODUCT_BALTECH_CARDREADER }, + { USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD }, + { USB_VENDOR_JABLOTRON, USB_PRODUCT_JABLOTRON_PC60B }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARGUSISP }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CRUMB128 }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREECONT }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DESKTOPMOBILE }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_IPLINK1220 }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_HARP }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_JTAG }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_LIN }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_1 }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_2 }, + { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SUNNTO }, + { USB_VENDOR_SILABS2, USB_PRODUCT_SILABS2_DCU11CLONE }, + { USB_VENDOR_USI, USB_PRODUCT_USI_MC60 } +}; + +static device_probe_t uslcom_match; +static device_attach_t uslcom_attach; +static device_detach_t uslcom_detach; + +static device_method_t uslcom_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uslcom_match), + DEVMETHOD(device_attach, uslcom_attach), + DEVMETHOD(device_detach, uslcom_detach), + { 0, 0 } +}; + +static driver_t uslcom_driver = { + "ucom", + uslcom_methods, + sizeof (struct uslcom_softc) +}; + +DRIVER_MODULE(uslcom, uhub, uslcom_driver, ucom_devclass, usbd_driver_load, 0); +MODULE_DEPEND(uslcom, usb, 1, 1, 1); +MODULE_DEPEND(uslcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); +MODULE_VERSION(uslcom, 1); + +static int +uslcom_match(device_t self) +{ + struct usb_attach_arg *uaa = device_get_ivars(self); + + if (uaa->iface != NULL) + return UMATCH_NONE; + + return (usb_lookup(uslcom_devs, uaa->vendor, uaa->product) != NULL) ? + UMATCH_VENDOR_PRODUCT : UMATCH_NONE; +} + +static int +uslcom_attach(device_t self) +{ + struct uslcom_softc *sc = device_get_softc(self); + struct usb_attach_arg *uaa = device_get_ivars(self); + struct ucom_softc *ucom; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + usbd_status error; + char *devinfo; + const char *devname; + int i; + + devinfo = kmalloc(1024, M_USBDEV, M_INTWAIT); + ucom = &sc->sc_ucom; + + bzero(sc, sizeof (struct uslcom_softc)); + + usbd_devinfo(uaa->device, 0, devinfo); + ucom->sc_dev = self; + device_set_desc_copy(self, devinfo); + + ucom->sc_udev = uaa->device; + ucom->sc_iface = uaa->iface; + + devname = device_get_nameunit(ucom->sc_dev); + kprintf("%s: %s\n", devname, devinfo); + kfree(devinfo, M_USBDEV); + + if (usbd_set_config_index(ucom->sc_udev, USLCOM_CONFIG_NO, 1) != 0) { + kprintf("%s: could not set configuration no\n", devname); + goto error; + } + + /* get the first interface handle */ + error = usbd_device2interface_handle(ucom->sc_udev, USLCOM_IFACE_NO, + &ucom->sc_iface); + if (error != 0) { + kprintf("%s: could not get interface handle\n", devname); + goto error; + } + + id = usbd_get_interface_descriptor(ucom->sc_iface); + + ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; + for (i = 0; i < id->bNumEndpoints; i++) { + ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); + if (ed == NULL) { + kprintf("%s: no endpoint descriptor found for %d\n", + devname, i); + goto error; + } + + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) + ucom->sc_bulkin_no = ed->bEndpointAddress; + else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && + UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) + ucom->sc_bulkout_no = ed->bEndpointAddress; + } + + if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { + kprintf("%s: missing endpoint\n", devname); + goto error; + } + + ucom->sc_parent = sc; + ucom->sc_portno = UCOM_UNK_PORTNO; + ucom->sc_ibufsize = USLCOMBUFSZ; + ucom->sc_obufsize = USLCOMBUFSZ; + ucom->sc_ibufsizepad = USLCOMBUFSZ; + ucom->sc_opkthdrlen = 0; + ucom->sc_callback = &uslcom_callback; + + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, + ucom->sc_dev); + + DPRINTF(("uslcom: in = 0x%x, out = 0x%x, intr = 0x%x\n", + ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); + + ucom_attach(&sc->sc_ucom); + return 0; + +error: + ucom->sc_dying = 1; + return ENXIO; +} + +static int +uslcom_detach(device_t self) +{ + struct uslcom_softc *sc = device_get_softc(self); + int rv = 0; + + DPRINTF(("uslcom_detach: sc=%p\n", sc)); + sc->sc_ucom.sc_dying = 1; + rv = ucom_detach(&sc->sc_ucom); + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, + sc->sc_ucom.sc_dev); + + return (rv); +} + +#if 0 /* not yet */ +int +uslcom_activate(struct device *self, enum devact act) +{ + struct uslcom_softc *sc = (struct uslcom_softc *)self; + int rv = 0; + + switch (act) { + case DVACT_ACTIVATE: + break; + + case DVACT_DEACTIVATE: + if (sc->sc_subdev != NULL) + rv = config_deactivate(sc->sc_subdev); + sc->sc_dying = 1; + break; + } + return (rv); +} +#endif + +int +uslcom_open(void *vsc, int portno) +{ + struct uslcom_softc *sc = vsc; + usb_device_request_t req; + usbd_status err; + + if (sc->sc_ucom.sc_dying) + return (EIO); + + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_UART; + USETW(req.wValue, USLCOM_UART_ENABLE); + USETW(req.wIndex, portno); + USETW(req.wLength, 0); + err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); + if (err) + return (EIO); + + return (0); +} + +void +uslcom_close(void *vsc, int portno) +{ + struct uslcom_softc *sc = vsc; + usb_device_request_t req; + + if (sc->sc_ucom.sc_dying) + return; + + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_UART; + USETW(req.wValue, USLCOM_UART_DISABLE); + USETW(req.wIndex, portno); + USETW(req.wLength, 0); + usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); +} + +void +uslcom_set(void *vsc, int portno, int reg, int onoff) +{ + struct uslcom_softc *sc = vsc; + usb_device_request_t req; + int ctl; + + switch (reg) { + case UCOM_SET_DTR: + ctl = onoff ? USLCOM_CTRL_DTR_ON : 0; + ctl |= USLCOM_CTRL_DTR_SET; + break; + case UCOM_SET_RTS: + ctl = onoff ? USLCOM_CTRL_RTS_ON : 0; + ctl |= USLCOM_CTRL_RTS_SET; + break; + case UCOM_SET_BREAK: + uslcom_break(sc, portno, onoff); + return; + default: + return; + } + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_CTRL; + USETW(req.wValue, ctl); + USETW(req.wIndex, portno); + USETW(req.wLength, 0); + usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); +} + +int +uslcom_param(void *vsc, int portno, struct termios *t) +{ + struct uslcom_softc *sc = (struct uslcom_softc *)vsc; + usbd_status err; + usb_device_request_t req; + int data; + + switch (t->c_ospeed) { + case 600: + case 1200: + case 1800: + case 2400: + case 4800: + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + case 460800: + case 921600: + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_BAUD_RATE; + USETW(req.wValue, USLCOM_BAUD_REF / t->c_ospeed); + USETW(req.wIndex, portno); + USETW(req.wLength, 0); + err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); + if (err) + return (EIO); + break; + default: + return (EINVAL); + } + + if (ISSET(t->c_cflag, CSTOPB)) + data = USLCOM_STOP_BITS_2; + else + data = USLCOM_STOP_BITS_1; + if (ISSET(t->c_cflag, PARENB)) { + if (ISSET(t->c_cflag, PARODD)) + data |= USLCOM_PARITY_ODD; + else + data |= USLCOM_PARITY_EVEN; + } else + data |= USLCOM_PARITY_NONE; + switch (ISSET(t->c_cflag, CSIZE)) { + case CS5: + data |= USLCOM_SET_DATA_BITS(5); + break; + case CS6: + data |= USLCOM_SET_DATA_BITS(6); + break; + case CS7: + data |= USLCOM_SET_DATA_BITS(7); + break; + case CS8: + data |= USLCOM_SET_DATA_BITS(8); + break; + } + + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_DATA; + USETW(req.wValue, data); + USETW(req.wIndex, portno); + USETW(req.wLength, 0); + err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); + if (err) + return (EIO); + +#if 0 + /* XXX flow control */ + if (ISSET(t->c_cflag, CRTSCTS)) + /* rts/cts flow ctl */ + } else if (ISSET(t->c_iflag, IXON|IXOFF)) { + /* xon/xoff flow ctl */ + } else { + /* disable flow ctl */ + } +#endif + + return (0); +} + +void +uslcom_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) +{ + struct uslcom_softc *sc = vsc; + + if (msr != NULL) + *msr = sc->sc_msr; + if (lsr != NULL) + *lsr = sc->sc_lsr; +} + +void +uslcom_break(void *vsc, int portno, int onoff) +{ + struct uslcom_softc *sc = vsc; + usb_device_request_t req; + int brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF; + + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_BREAK; + USETW(req.wValue, brk); + USETW(req.wIndex, portno); + USETW(req.wLength, 0); + usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); +}