Home | History | Annotate | Line # | Download | only in usb
uvscom.c revision 1.21.8.1
      1  1.21.8.1      yamt /*	$NetBSD: uvscom.c,v 1.21.8.1 2008/06/04 02:05:21 yamt Exp $	*/
      2       1.1  augustss /*-
      3       1.1  augustss  * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama (at) jp.FreeBSD.org>.
      4       1.1  augustss  * All rights reserved.
      5       1.1  augustss  *
      6       1.1  augustss  * Redistribution and use in source and binary forms, with or without
      7       1.1  augustss  * modification, are permitted provided that the following conditions
      8       1.1  augustss  * are met:
      9       1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     10       1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     11       1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     13       1.1  augustss  *    documentation and/or other materials provided with the distribution.
     14       1.1  augustss  *
     15       1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16       1.1  augustss  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17       1.1  augustss  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18       1.1  augustss  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19       1.1  augustss  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20       1.1  augustss  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21       1.1  augustss  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22       1.1  augustss  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23       1.1  augustss  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24       1.1  augustss  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25       1.1  augustss  * SUCH DAMAGE.
     26       1.1  augustss  *
     27       1.1  augustss  * $FreeBSD: src/sys/dev/usb/uvscom.c,v 1.1 2002/03/18 18:23:39 joe Exp $
     28       1.1  augustss  */
     29       1.1  augustss 
     30       1.1  augustss /*
     31       1.1  augustss  * uvscom: SUNTAC Slipper U VS-10U driver.
     32       1.1  augustss  * Slipper U is a PC card to USB converter for data communication card
     33       1.1  augustss  * adapter.  It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in,
     34       1.1  augustss  * P-in m@ater and various data communication card adapters.
     35       1.1  augustss  */
     36      1.10     lukem 
     37      1.10     lukem #include <sys/cdefs.h>
     38  1.21.8.1      yamt __KERNEL_RCSID(0, "$NetBSD: uvscom.c,v 1.21.8.1 2008/06/04 02:05:21 yamt Exp $");
     39       1.1  augustss 
     40       1.1  augustss #include <sys/param.h>
     41       1.1  augustss #include <sys/systm.h>
     42       1.1  augustss #include <sys/kernel.h>
     43       1.1  augustss #include <sys/malloc.h>
     44       1.1  augustss #include <sys/fcntl.h>
     45       1.1  augustss #include <sys/conf.h>
     46       1.1  augustss #include <sys/tty.h>
     47       1.1  augustss #include <sys/file.h>
     48       1.1  augustss #if defined(__FreeBSD__)
     49       1.1  augustss #include <sys/bus.h>
     50       1.1  augustss #include <sys/ioccom.h>
     51       1.1  augustss #if __FreeBSD_version >= 500014
     52       1.1  augustss #include <sys/selinfo.h>
     53       1.1  augustss #else
     54       1.1  augustss #include <sys/select.h>
     55       1.1  augustss #endif
     56       1.1  augustss #else
     57       1.1  augustss #include <sys/ioctl.h>
     58       1.1  augustss #include <sys/device.h>
     59       1.1  augustss #endif
     60       1.1  augustss #include <sys/proc.h>
     61       1.1  augustss #include <sys/poll.h>
     62       1.1  augustss 
     63       1.1  augustss #include <dev/usb/usb.h>
     64       1.1  augustss #include <dev/usb/usbcdc.h>
     65       1.1  augustss 
     66       1.1  augustss #include <dev/usb/usbdi.h>
     67       1.1  augustss #include <dev/usb/usbdi_util.h>
     68       1.1  augustss #include <dev/usb/usbdevs.h>
     69       1.1  augustss #include <dev/usb/usb_quirks.h>
     70       1.1  augustss 
     71       1.1  augustss #include <dev/usb/ucomvar.h>
     72       1.1  augustss 
     73       1.1  augustss #ifdef UVSCOM_DEBUG
     74       1.1  augustss static int	uvscomdebug = 1;
     75       1.1  augustss 
     76       1.1  augustss #if defined(__FreeBSD__)
     77       1.1  augustss #include <sys/sysctl.h>
     78       1.1  augustss 
     79       1.1  augustss SYSCTL_DECL(_debug_usb);
     80       1.1  augustss SYSCTL_INT(_debug_usb, OID_AUTO, uvscom, CTLFLAG_RW,
     81       1.1  augustss 	   &uvscomdebug, 0, "uvscom debug level");
     82       1.1  augustss 
     83       1.1  augustss #endif
     84       1.1  augustss 
     85       1.1  augustss #define DPRINTFN(n, x)  do { \
     86       1.1  augustss 				if (uvscomdebug > (n)) \
     87       1.1  augustss 					logprintf x; \
     88       1.1  augustss 			} while (0)
     89       1.1  augustss #else
     90       1.1  augustss #define DPRINTFN(n, x)
     91       1.1  augustss #endif
     92       1.1  augustss #define DPRINTF(x) DPRINTFN(0, x)
     93       1.5  augustss 
     94       1.5  augustss #if defined(__FreeBSD__)
     95       1.5  augustss #define UVSCOM_MODVER		1	/* module version */
     96       1.5  augustss #endif
     97       1.1  augustss 
     98       1.1  augustss #define	UVSCOM_CONFIG_INDEX	0
     99       1.1  augustss #define	UVSCOM_IFACE_INDEX	0
    100       1.1  augustss 
    101       1.1  augustss #define UVSCOM_INTR_INTERVAL	100	/* mS */
    102       1.1  augustss 
    103       1.1  augustss #define UVSCOM_UNIT_WAIT	5
    104       1.1  augustss 
    105       1.1  augustss /* Request */
    106       1.1  augustss #define UVSCOM_SET_SPEED	0x10
    107       1.1  augustss #define UVSCOM_LINE_CTL		0x11
    108       1.1  augustss #define UVSCOM_SET_PARAM	0x12
    109       1.1  augustss #define UVSCOM_READ_STATUS	0xd0
    110       1.1  augustss #define UVSCOM_SHUTDOWN		0xe0
    111       1.1  augustss 
    112       1.1  augustss /* UVSCOM_SET_SPEED parameters */
    113       1.1  augustss #define UVSCOM_SPEED_150BPS	0x00
    114       1.1  augustss #define UVSCOM_SPEED_300BPS	0x01
    115       1.1  augustss #define UVSCOM_SPEED_600BPS	0x02
    116       1.1  augustss #define UVSCOM_SPEED_1200BPS	0x03
    117       1.1  augustss #define UVSCOM_SPEED_2400BPS	0x04
    118       1.1  augustss #define UVSCOM_SPEED_4800BPS	0x05
    119       1.1  augustss #define UVSCOM_SPEED_9600BPS	0x06
    120       1.1  augustss #define UVSCOM_SPEED_19200BPS	0x07
    121       1.1  augustss #define UVSCOM_SPEED_38400BPS	0x08
    122       1.1  augustss #define UVSCOM_SPEED_57600BPS	0x09
    123       1.1  augustss #define UVSCOM_SPEED_115200BPS	0x0a
    124       1.1  augustss 
    125       1.1  augustss /* UVSCOM_LINE_CTL parameters */
    126       1.1  augustss #define UVSCOM_BREAK		0x40
    127       1.1  augustss #define UVSCOM_RTS		0x02
    128       1.1  augustss #define UVSCOM_DTR		0x01
    129       1.1  augustss #define UVSCOM_LINE_INIT	0x08
    130       1.1  augustss 
    131       1.1  augustss /* UVSCOM_SET_PARAM parameters */
    132       1.1  augustss #define UVSCOM_DATA_MASK	0x03
    133       1.1  augustss #define UVSCOM_DATA_BIT_8	0x03
    134       1.1  augustss #define UVSCOM_DATA_BIT_7	0x02
    135       1.1  augustss #define UVSCOM_DATA_BIT_6	0x01
    136       1.1  augustss #define UVSCOM_DATA_BIT_5	0x00
    137       1.1  augustss 
    138       1.1  augustss #define UVSCOM_STOP_MASK	0x04
    139       1.1  augustss #define UVSCOM_STOP_BIT_2	0x04
    140       1.1  augustss #define UVSCOM_STOP_BIT_1	0x00
    141       1.1  augustss 
    142       1.1  augustss #define UVSCOM_PARITY_MASK	0x18
    143       1.1  augustss #define UVSCOM_PARITY_EVEN	0x18
    144       1.1  augustss #if 0
    145       1.1  augustss #define UVSCOM_PARITY_UNK	0x10
    146       1.1  augustss #endif
    147       1.1  augustss #define UVSCOM_PARITY_ODD	0x08
    148       1.1  augustss #define UVSCOM_PARITY_NONE	0x00
    149       1.1  augustss 
    150       1.1  augustss /* Status bits */
    151       1.1  augustss #define UVSCOM_TXRDY		0x04
    152       1.1  augustss #define UVSCOM_RXRDY		0x01
    153       1.1  augustss 
    154       1.1  augustss #define UVSCOM_DCD		0x08
    155       1.1  augustss #define UVSCOM_NOCARD		0x04
    156       1.1  augustss #define UVSCOM_DSR		0x02
    157       1.1  augustss #define UVSCOM_CTS		0x01
    158       1.1  augustss #define UVSCOM_USTAT_MASK	(UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
    159       1.1  augustss 
    160       1.1  augustss struct	uvscom_softc {
    161       1.1  augustss 	USBBASEDEVICE		sc_dev;		/* base device */
    162       1.1  augustss 	usbd_device_handle	sc_udev;	/* USB device */
    163       1.1  augustss 	usbd_interface_handle	sc_iface;	/* interface */
    164       1.1  augustss 	int			sc_iface_number;/* interface number */
    165       1.1  augustss 
    166       1.1  augustss 	usbd_interface_handle	sc_intr_iface;	/* interrupt interface */
    167       1.1  augustss 	int			sc_intr_number;	/* interrupt number */
    168       1.1  augustss 	usbd_pipe_handle	sc_intr_pipe;	/* interrupt pipe */
    169       1.1  augustss 	u_char			*sc_intr_buf;	/* interrupt buffer */
    170       1.1  augustss 	int			sc_isize;
    171       1.1  augustss 
    172       1.1  augustss 	u_char			sc_dtr;		/* current DTR state */
    173       1.1  augustss 	u_char			sc_rts;		/* current RTS state */
    174       1.1  augustss 
    175       1.1  augustss 	u_char			sc_lsr;		/* Local status register */
    176       1.1  augustss 	u_char			sc_msr;		/* uvscom status register */
    177       1.1  augustss 
    178       1.1  augustss 	uint16_t		sc_lcr;		/* Line control */
    179       1.1  augustss 	u_char			sc_usr;		/* unit status */
    180       1.1  augustss 
    181       1.1  augustss 	device_ptr_t		sc_subdev;	/* ucom device */
    182       1.1  augustss 	u_char			sc_dying;	/* disconnecting */
    183       1.1  augustss };
    184       1.1  augustss 
    185       1.1  augustss /*
    186       1.1  augustss  * These are the maximum number of bytes transferred per frame.
    187       1.1  augustss  * The output buffer size cannot be increased due to the size encoding.
    188       1.1  augustss  */
    189       1.1  augustss #define UVSCOMIBUFSIZE 512
    190       1.1  augustss #define UVSCOMOBUFSIZE 64
    191       1.1  augustss 
    192       1.1  augustss Static	usbd_status uvscom_readstat(struct uvscom_softc *);
    193       1.1  augustss Static	usbd_status uvscom_shutdown(struct uvscom_softc *);
    194       1.1  augustss Static	usbd_status uvscom_reset(struct uvscom_softc *);
    195       1.1  augustss Static	usbd_status uvscom_set_line_coding(struct uvscom_softc *,
    196       1.1  augustss 					   uint16_t, uint16_t);
    197       1.1  augustss Static	usbd_status uvscom_set_line(struct uvscom_softc *, uint16_t);
    198       1.1  augustss Static	usbd_status uvscom_set_crtscts(struct uvscom_softc *);
    199       1.1  augustss Static	void uvscom_get_status(void *, int, u_char *, u_char *);
    200       1.1  augustss Static	void uvscom_dtr(struct uvscom_softc *, int);
    201       1.1  augustss Static	void uvscom_rts(struct uvscom_softc *, int);
    202       1.1  augustss Static	void uvscom_break(struct uvscom_softc *, int);
    203       1.1  augustss 
    204       1.1  augustss Static	void uvscom_set(void *, int, int, int);
    205       1.1  augustss Static	void uvscom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
    206       1.1  augustss Static	int  uvscom_param(void *, int, struct termios *);
    207       1.1  augustss Static	int  uvscom_open(void *, int);
    208       1.1  augustss Static	void uvscom_close(void *, int);
    209       1.1  augustss 
    210       1.1  augustss struct ucom_methods uvscom_methods = {
    211       1.1  augustss 	uvscom_get_status,
    212       1.1  augustss 	uvscom_set,
    213       1.1  augustss 	uvscom_param,
    214       1.1  augustss 	NULL, /* uvscom_ioctl, TODO */
    215       1.1  augustss 	uvscom_open,
    216       1.1  augustss 	uvscom_close,
    217       1.1  augustss 	NULL,
    218       1.1  augustss 	NULL
    219       1.1  augustss };
    220       1.1  augustss 
    221       1.1  augustss static const struct usb_devno uvscom_devs [] = {
    222      1.14    martin 	/* SUNTAC U-Cable type A4 */
    223      1.14    martin 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 },
    224       1.8    ichiro 	/* SUNTAC U-Cable type D2 */
    225       1.8    ichiro 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L },
    226       1.1  augustss 	/* SUNTAC U-Cable type P1 */
    227       1.1  augustss 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 },
    228       1.1  augustss 	/* SUNTAC Slipper U  */
    229       1.1  augustss 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U },
    230       1.9    ichiro 	/* SUNTAC Ir-Trinity */
    231       1.9    ichiro 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U },
    232       1.1  augustss };
    233       1.1  augustss #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
    234       1.1  augustss 
    235  1.21.8.1      yamt int uvscom_match(device_t, cfdata_t, void *);
    236      1.21    dyoung void uvscom_attach(device_t, device_t, void *);
    237      1.21    dyoung void uvscom_childdet(device_t, device_t);
    238      1.21    dyoung int uvscom_detach(device_t, int);
    239      1.21    dyoung int uvscom_activate(device_t, enum devact);
    240      1.21    dyoung extern struct cfdriver uvscom_cd;
    241  1.21.8.1      yamt CFATTACH_DECL2_NEW(uvscom, sizeof(struct uvscom_softc), uvscom_match,
    242      1.21    dyoung     uvscom_attach, uvscom_detach, uvscom_activate, NULL, uvscom_childdet);
    243       1.1  augustss 
    244       1.1  augustss USB_MATCH(uvscom)
    245       1.1  augustss {
    246       1.1  augustss 	USB_MATCH_START(uvscom, uaa);
    247       1.1  augustss 
    248       1.1  augustss 	return (uvscom_lookup(uaa->vendor, uaa->product) != NULL ?
    249       1.1  augustss 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
    250       1.1  augustss }
    251       1.1  augustss 
    252       1.1  augustss USB_ATTACH(uvscom)
    253       1.1  augustss {
    254       1.1  augustss 	USB_ATTACH_START(uvscom, sc, uaa);
    255       1.1  augustss 	usbd_device_handle dev = uaa->device;
    256       1.1  augustss 	usb_config_descriptor_t *cdesc;
    257       1.1  augustss 	usb_interface_descriptor_t *id;
    258       1.1  augustss 	usb_endpoint_descriptor_t *ed;
    259      1.15  augustss 	char *devinfop;
    260       1.1  augustss 	usbd_status err;
    261       1.1  augustss 	int i;
    262       1.1  augustss 	struct ucom_attach_args uca;
    263       1.1  augustss 
    264      1.15  augustss 	devinfop = usbd_devinfo_alloc(dev, 0);
    265       1.1  augustss         USB_ATTACH_SETUP;
    266  1.21.8.1      yamt         aprint_normal_dev(self, "%s\n", devinfop);
    267      1.15  augustss 	usbd_devinfo_free(devinfop);
    268       1.1  augustss 
    269  1.21.8.1      yamt 	sc->sc_dev = self;
    270       1.1  augustss         sc->sc_udev = dev;
    271       1.1  augustss 
    272       1.1  augustss 	DPRINTF(("uvscom attach: sc = %p\n", sc));
    273       1.1  augustss 
    274       1.6  augustss 	/* initialize endpoints */
    275       1.1  augustss 	uca.bulkin = uca.bulkout = -1;
    276       1.1  augustss 	sc->sc_intr_number = -1;
    277       1.1  augustss 	sc->sc_intr_pipe = NULL;
    278       1.1  augustss 
    279       1.1  augustss 	/* Move the device into the configured state. */
    280       1.1  augustss 	err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1);
    281       1.1  augustss 	if (err) {
    282  1.21.8.1      yamt 		aprint_error_dev(self, "failed to set configuration, err=%s\n",
    283  1.21.8.1      yamt 		    usbd_errstr(err));
    284       1.1  augustss 		sc->sc_dying = 1;
    285       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    286       1.1  augustss 	}
    287       1.1  augustss 
    288       1.1  augustss 	/* get the config descriptor */
    289       1.1  augustss 	cdesc = usbd_get_config_descriptor(sc->sc_udev);
    290       1.1  augustss 
    291       1.1  augustss 	if (cdesc == NULL) {
    292  1.21.8.1      yamt 		aprint_error_dev(self,
    293  1.21.8.1      yamt 		    "failed to get configuration descriptor\n");
    294       1.1  augustss 		sc->sc_dying = 1;
    295       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    296       1.1  augustss 	}
    297       1.1  augustss 
    298       1.1  augustss 	/* get the common interface */
    299       1.6  augustss 	err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX,
    300       1.1  augustss 					   &sc->sc_iface);
    301       1.1  augustss 	if (err) {
    302  1.21.8.1      yamt 		aprint_error_dev(self, "failed to get interface, err=%s\n",
    303  1.21.8.1      yamt 		    usbd_errstr(err));
    304       1.1  augustss 		sc->sc_dying = 1;
    305       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    306       1.1  augustss 	}
    307       1.1  augustss 
    308       1.1  augustss 	id = usbd_get_interface_descriptor(sc->sc_iface);
    309       1.1  augustss 	sc->sc_iface_number = id->bInterfaceNumber;
    310       1.1  augustss 
    311       1.1  augustss 	/* Find endpoints */
    312       1.1  augustss 	for (i = 0; i < id->bNumEndpoints; i++) {
    313       1.1  augustss 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
    314       1.1  augustss 		if (ed == NULL) {
    315  1.21.8.1      yamt 			aprint_error_dev(self,
    316  1.21.8.1      yamt 			    "no endpoint descriptor for %d\n", i);
    317       1.1  augustss 			sc->sc_dying = 1;
    318       1.1  augustss 			USB_ATTACH_ERROR_RETURN;
    319       1.1  augustss 		}
    320       1.1  augustss 
    321       1.1  augustss 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    322       1.1  augustss 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    323       1.1  augustss 			uca.bulkin = ed->bEndpointAddress;
    324       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    325       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    326       1.1  augustss 			uca.bulkout = ed->bEndpointAddress;
    327       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    328       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    329       1.1  augustss 			sc->sc_intr_number = ed->bEndpointAddress;
    330       1.1  augustss 			sc->sc_isize = UGETW(ed->wMaxPacketSize);
    331       1.6  augustss 		}
    332       1.1  augustss 	}
    333       1.1  augustss 
    334       1.1  augustss 	if (uca.bulkin == -1) {
    335  1.21.8.1      yamt 		aprint_error_dev(self, "Could not find data bulk in\n");
    336       1.1  augustss 		sc->sc_dying = 1;
    337       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    338       1.1  augustss 	}
    339       1.1  augustss 	if (uca.bulkout == -1) {
    340  1.21.8.1      yamt 		aprint_error_dev(self, "Could not find data bulk out\n");
    341       1.1  augustss 		sc->sc_dying = 1;
    342       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    343       1.1  augustss 	}
    344       1.1  augustss 	if (sc->sc_intr_number == -1) {
    345  1.21.8.1      yamt 		aprint_error_dev(self, "Could not find interrupt in\n");
    346       1.1  augustss 		sc->sc_dying = 1;
    347       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    348       1.1  augustss 	}
    349       1.1  augustss 
    350       1.1  augustss 	sc->sc_dtr = sc->sc_rts = 0;
    351       1.1  augustss 	sc->sc_lcr = UVSCOM_LINE_INIT;
    352       1.1  augustss 
    353       1.1  augustss 	uca.portno = UCOM_UNK_PORTNO;
    354       1.1  augustss 	/* bulkin, bulkout set above */
    355       1.1  augustss 	uca.ibufsize = UVSCOMIBUFSIZE;
    356       1.1  augustss 	uca.obufsize = UVSCOMOBUFSIZE;
    357       1.1  augustss 	uca.ibufsizepad = UVSCOMIBUFSIZE;
    358       1.1  augustss 	uca.opkthdrlen = 0;
    359       1.1  augustss 	uca.device = dev;
    360       1.1  augustss 	uca.iface = sc->sc_iface;
    361       1.1  augustss 	uca.methods = &uvscom_methods;
    362       1.1  augustss 	uca.arg = sc;
    363       1.1  augustss 	uca.info = NULL;
    364       1.1  augustss 
    365       1.1  augustss 	err = uvscom_reset(sc);
    366       1.1  augustss 
    367       1.1  augustss 	if (err) {
    368  1.21.8.1      yamt 		aprint_error_dev(self, "reset failed, %s\n", usbd_errstr(err));
    369       1.1  augustss 		sc->sc_dying = 1;
    370       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    371       1.1  augustss 	}
    372       1.1  augustss 
    373       1.1  augustss 	DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
    374      1.17  christos 		 uca.bulkin, uca.bulkout, sc->sc_intr_number));
    375       1.1  augustss 
    376       1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    377       1.1  augustss 			   USBDEV(sc->sc_dev));
    378       1.1  augustss 
    379       1.1  augustss 	DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
    380       1.1  augustss 			uca.bulkin, uca.bulkout, sc->sc_intr_number ));
    381      1.13  drochner 	sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca,
    382      1.13  drochner 					    ucomprint, ucomsubmatch);
    383       1.1  augustss 
    384       1.1  augustss 	USB_ATTACH_SUCCESS_RETURN;
    385       1.1  augustss }
    386       1.1  augustss 
    387      1.21    dyoung void
    388      1.21    dyoung uvscom_childdet(device_t self, device_t child)
    389      1.21    dyoung {
    390      1.21    dyoung 	struct uvscom_softc *sc = device_private(self);
    391      1.21    dyoung 
    392      1.21    dyoung 	KASSERT(sc->sc_subdev == child);
    393      1.21    dyoung 	sc->sc_subdev = NULL;
    394      1.21    dyoung }
    395      1.21    dyoung 
    396       1.1  augustss USB_DETACH(uvscom)
    397       1.1  augustss {
    398       1.1  augustss 	USB_DETACH_START(uvscom, sc);
    399       1.1  augustss 	int rv = 0;
    400       1.1  augustss 
    401       1.1  augustss 	DPRINTF(("uvscom_detach: sc = %p\n", sc));
    402       1.1  augustss 
    403       1.1  augustss 	sc->sc_dying = 1;
    404       1.1  augustss 
    405       1.1  augustss 	if (sc->sc_intr_pipe != NULL) {
    406       1.1  augustss 		usbd_abort_pipe(sc->sc_intr_pipe);
    407       1.1  augustss 		usbd_close_pipe(sc->sc_intr_pipe);
    408       1.1  augustss 		free(sc->sc_intr_buf, M_USBDEV);
    409       1.1  augustss 		sc->sc_intr_pipe = NULL;
    410       1.1  augustss 	}
    411       1.1  augustss 
    412       1.1  augustss 	sc->sc_dying = 1;
    413      1.21    dyoung 	if (sc->sc_subdev != NULL)
    414       1.1  augustss 		rv = config_detach(sc->sc_subdev, flags);
    415       1.1  augustss 
    416       1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    417       1.1  augustss 			   USBDEV(sc->sc_dev));
    418       1.1  augustss 
    419       1.1  augustss 	return (rv);
    420       1.1  augustss }
    421       1.1  augustss 
    422       1.3  augustss int
    423      1.21    dyoung uvscom_activate(device_t self, enum devact act)
    424       1.1  augustss {
    425      1.21    dyoung 	struct uvscom_softc *sc = device_private(self);
    426       1.1  augustss 	int rv = 0;
    427       1.1  augustss 
    428       1.1  augustss 	switch (act) {
    429       1.1  augustss 	case DVACT_ACTIVATE:
    430       1.1  augustss 		return (EOPNOTSUPP);
    431       1.1  augustss 
    432       1.1  augustss 	case DVACT_DEACTIVATE:
    433       1.1  augustss 		if (sc->sc_subdev != NULL)
    434       1.1  augustss 			rv = config_deactivate(sc->sc_subdev);
    435       1.1  augustss 		sc->sc_dying = 1;
    436       1.1  augustss 		break;
    437       1.1  augustss 	}
    438       1.1  augustss 	return (rv);
    439       1.1  augustss }
    440       1.1  augustss 
    441       1.1  augustss Static usbd_status
    442       1.1  augustss uvscom_readstat(struct uvscom_softc *sc)
    443       1.1  augustss {
    444       1.1  augustss 	usb_device_request_t req;
    445       1.1  augustss 	usbd_status err;
    446       1.1  augustss 	uint16_t r;
    447       1.1  augustss 
    448       1.1  augustss 	DPRINTF(("%s: send readstat\n", USBDEVNAME(sc->sc_dev)));
    449       1.1  augustss 
    450       1.1  augustss 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    451       1.1  augustss 	req.bRequest = UVSCOM_READ_STATUS;
    452       1.1  augustss 	USETW(req.wValue, 0);
    453       1.1  augustss 	USETW(req.wIndex, 0);
    454       1.6  augustss 	USETW(req.wLength, 2);
    455       1.1  augustss 
    456       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, &r);
    457       1.1  augustss 	if (err) {
    458  1.21.8.1      yamt 		aprint_error_dev(sc->sc_dev, "uvscom_readstat: %s\n",
    459  1.21.8.1      yamt 		    usbd_errstr(err));
    460       1.1  augustss 		return (err);
    461       1.1  augustss 	}
    462       1.1  augustss 
    463       1.1  augustss 	DPRINTF(("%s: uvscom_readstat: r = %d\n",
    464       1.1  augustss 		 USBDEVNAME(sc->sc_dev), r));
    465       1.1  augustss 
    466       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    467       1.1  augustss }
    468       1.1  augustss 
    469       1.1  augustss Static usbd_status
    470       1.1  augustss uvscom_shutdown(struct uvscom_softc *sc)
    471       1.1  augustss {
    472       1.1  augustss 	usb_device_request_t req;
    473       1.1  augustss 	usbd_status err;
    474       1.1  augustss 
    475       1.1  augustss 	DPRINTF(("%s: send shutdown\n", USBDEVNAME(sc->sc_dev)));
    476       1.1  augustss 
    477       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    478       1.1  augustss 	req.bRequest = UVSCOM_SHUTDOWN;
    479       1.1  augustss 	USETW(req.wValue, 0);
    480       1.1  augustss 	USETW(req.wIndex, 0);
    481       1.6  augustss 	USETW(req.wLength, 0);
    482       1.1  augustss 
    483       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    484       1.1  augustss 	if (err) {
    485  1.21.8.1      yamt 		aprint_error_dev(sc->sc_dev, "uvscom_shutdown: %s\n",
    486  1.21.8.1      yamt 		   usbd_errstr(err));
    487       1.1  augustss 		return (err);
    488       1.1  augustss 	}
    489       1.1  augustss 
    490       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    491       1.1  augustss }
    492       1.1  augustss 
    493       1.1  augustss Static usbd_status
    494      1.19  christos uvscom_reset(struct uvscom_softc *sc)
    495       1.1  augustss {
    496       1.1  augustss 	DPRINTF(("%s: uvscom_reset\n", USBDEVNAME(sc->sc_dev)));
    497       1.1  augustss 
    498       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    499       1.1  augustss }
    500       1.1  augustss 
    501       1.1  augustss Static usbd_status
    502      1.19  christos uvscom_set_crtscts(struct uvscom_softc *sc)
    503       1.1  augustss {
    504       1.1  augustss 	DPRINTF(("%s: uvscom_set_crtscts\n", USBDEVNAME(sc->sc_dev)));
    505       1.1  augustss 
    506       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    507       1.1  augustss }
    508       1.1  augustss 
    509       1.1  augustss Static usbd_status
    510       1.1  augustss uvscom_set_line(struct uvscom_softc *sc, uint16_t line)
    511       1.1  augustss {
    512       1.1  augustss 	usb_device_request_t req;
    513       1.1  augustss 	usbd_status err;
    514       1.1  augustss 
    515       1.1  augustss 	DPRINTF(("%s: uvscom_set_line: %04x\n",
    516       1.1  augustss 		 USBDEVNAME(sc->sc_dev), line));
    517       1.1  augustss 
    518       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    519       1.1  augustss 	req.bRequest = UVSCOM_LINE_CTL;
    520       1.1  augustss 	USETW(req.wValue, line);
    521       1.1  augustss 	USETW(req.wIndex, 0);
    522       1.6  augustss 	USETW(req.wLength, 0);
    523       1.1  augustss 
    524       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    525       1.1  augustss 	if (err) {
    526  1.21.8.1      yamt 		aprint_error_dev(sc->sc_dev, "uvscom_set_line: %s\n",
    527  1.21.8.1      yamt 		    usbd_errstr(err));
    528       1.1  augustss 		return (err);
    529       1.1  augustss 	}
    530       1.1  augustss 
    531       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    532       1.1  augustss }
    533       1.1  augustss 
    534       1.1  augustss Static usbd_status
    535       1.1  augustss uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls)
    536       1.1  augustss {
    537       1.1  augustss 	usb_device_request_t req;
    538       1.1  augustss 	usbd_status err;
    539       1.1  augustss 
    540       1.1  augustss 	DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
    541       1.1  augustss 		 USBDEVNAME(sc->sc_dev), lsp, ls));
    542       1.1  augustss 
    543       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    544       1.1  augustss 	req.bRequest = UVSCOM_SET_SPEED;
    545       1.1  augustss 	USETW(req.wValue, lsp);
    546       1.1  augustss 	USETW(req.wIndex, 0);
    547       1.1  augustss 	USETW(req.wLength, 0);
    548       1.1  augustss 
    549       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    550       1.1  augustss 	if (err) {
    551  1.21.8.1      yamt 		aprint_error_dev(sc->sc_dev, "uvscom_set_line_coding: %s\n",
    552  1.21.8.1      yamt 		   usbd_errstr(err));
    553       1.1  augustss 		return (err);
    554       1.1  augustss 	}
    555       1.1  augustss 
    556       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    557       1.1  augustss 	req.bRequest = UVSCOM_SET_PARAM;
    558       1.1  augustss 	USETW(req.wValue, ls);
    559       1.1  augustss 	USETW(req.wIndex, 0);
    560       1.1  augustss 	USETW(req.wLength, 0);
    561       1.1  augustss 
    562       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    563       1.1  augustss 	if (err) {
    564  1.21.8.1      yamt 		aprint_error_dev(sc->sc_dev, "uvscom_set_line_coding: %s\n",
    565  1.21.8.1      yamt 		   usbd_errstr(err));
    566       1.1  augustss 		return (err);
    567       1.1  augustss 	}
    568       1.1  augustss 
    569       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    570       1.1  augustss }
    571       1.1  augustss 
    572       1.1  augustss Static void
    573       1.1  augustss uvscom_dtr(struct uvscom_softc *sc, int onoff)
    574       1.1  augustss {
    575       1.1  augustss 	DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
    576       1.1  augustss 		 USBDEVNAME(sc->sc_dev), onoff));
    577       1.1  augustss 
    578       1.1  augustss 	if (sc->sc_dtr == onoff)
    579       1.1  augustss 		return;			/* no change */
    580       1.1  augustss 
    581       1.1  augustss 	sc->sc_dtr = onoff;
    582       1.1  augustss 
    583       1.1  augustss 	if (onoff)
    584       1.1  augustss 		SET(sc->sc_lcr, UVSCOM_DTR);
    585       1.1  augustss 	else
    586       1.1  augustss 		CLR(sc->sc_lcr, UVSCOM_DTR);
    587       1.1  augustss 
    588       1.1  augustss 	uvscom_set_line(sc, sc->sc_lcr);
    589       1.1  augustss }
    590       1.1  augustss 
    591       1.1  augustss Static void
    592       1.1  augustss uvscom_rts(struct uvscom_softc *sc, int onoff)
    593       1.1  augustss {
    594       1.1  augustss 	DPRINTF(("%s: uvscom_rts: onoff = %d\n",
    595       1.1  augustss 		 USBDEVNAME(sc->sc_dev), onoff));
    596       1.1  augustss 
    597       1.1  augustss 	if (sc->sc_rts == onoff)
    598       1.1  augustss 		return;			/* no change */
    599       1.1  augustss 
    600       1.1  augustss 	sc->sc_rts = onoff;
    601       1.1  augustss 
    602       1.1  augustss 	if (onoff)
    603       1.1  augustss 		SET(sc->sc_lcr, UVSCOM_RTS);
    604       1.1  augustss 	else
    605       1.1  augustss 		CLR(sc->sc_lcr, UVSCOM_RTS);
    606       1.1  augustss 
    607       1.1  augustss 	uvscom_set_line(sc, sc->sc_lcr);
    608       1.1  augustss }
    609       1.1  augustss 
    610       1.1  augustss Static void
    611       1.1  augustss uvscom_break(struct uvscom_softc *sc, int onoff)
    612       1.1  augustss {
    613       1.1  augustss 	DPRINTF(("%s: uvscom_break: onoff = %d\n",
    614       1.1  augustss 		 USBDEVNAME(sc->sc_dev), onoff));
    615       1.1  augustss 
    616       1.1  augustss 	if (onoff)
    617       1.1  augustss 		uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK));
    618       1.1  augustss }
    619       1.1  augustss 
    620       1.1  augustss Static void
    621      1.19  christos uvscom_set(void *addr, int portno, int reg, int onoff)
    622       1.1  augustss {
    623       1.1  augustss 	struct uvscom_softc *sc = addr;
    624       1.1  augustss 
    625       1.1  augustss 	switch (reg) {
    626       1.1  augustss 	case UCOM_SET_DTR:
    627       1.1  augustss 		uvscom_dtr(sc, onoff);
    628       1.1  augustss 		break;
    629       1.1  augustss 	case UCOM_SET_RTS:
    630       1.1  augustss 		uvscom_rts(sc, onoff);
    631       1.1  augustss 		break;
    632       1.1  augustss 	case UCOM_SET_BREAK:
    633       1.1  augustss 		uvscom_break(sc, onoff);
    634       1.1  augustss 		break;
    635       1.1  augustss 	default:
    636       1.1  augustss 		break;
    637       1.1  augustss 	}
    638       1.1  augustss }
    639       1.1  augustss 
    640       1.1  augustss Static int
    641      1.19  christos uvscom_param(void *addr, int portno, struct termios *t)
    642       1.1  augustss {
    643       1.1  augustss 	struct uvscom_softc *sc = addr;
    644       1.1  augustss 	usbd_status err;
    645       1.1  augustss 	uint16_t lsp;
    646       1.1  augustss 	uint16_t ls;
    647       1.1  augustss 
    648       1.1  augustss 	DPRINTF(("%s: uvscom_param: sc = %p\n",
    649       1.1  augustss 		 USBDEVNAME(sc->sc_dev), sc));
    650       1.1  augustss 
    651       1.1  augustss 	ls = 0;
    652       1.1  augustss 
    653       1.1  augustss 	switch (t->c_ospeed) {
    654       1.1  augustss 	case B150:
    655       1.1  augustss 		lsp = UVSCOM_SPEED_150BPS;
    656       1.1  augustss 		break;
    657       1.1  augustss 	case B300:
    658       1.1  augustss 		lsp = UVSCOM_SPEED_300BPS;
    659       1.1  augustss 		break;
    660       1.1  augustss 	case B600:
    661       1.1  augustss 		lsp = UVSCOM_SPEED_600BPS;
    662       1.1  augustss 		break;
    663       1.1  augustss 	case B1200:
    664       1.1  augustss 		lsp = UVSCOM_SPEED_1200BPS;
    665       1.1  augustss 		break;
    666       1.1  augustss 	case B2400:
    667       1.1  augustss 		lsp = UVSCOM_SPEED_2400BPS;
    668       1.1  augustss 		break;
    669       1.1  augustss 	case B4800:
    670       1.1  augustss 		lsp = UVSCOM_SPEED_4800BPS;
    671       1.1  augustss 		break;
    672       1.1  augustss 	case B9600:
    673       1.1  augustss 		lsp = UVSCOM_SPEED_9600BPS;
    674       1.1  augustss 		break;
    675       1.1  augustss 	case B19200:
    676       1.1  augustss 		lsp = UVSCOM_SPEED_19200BPS;
    677       1.1  augustss 		break;
    678       1.1  augustss 	case B38400:
    679       1.1  augustss 		lsp = UVSCOM_SPEED_38400BPS;
    680       1.1  augustss 		break;
    681       1.1  augustss 	case B57600:
    682       1.1  augustss 		lsp = UVSCOM_SPEED_57600BPS;
    683       1.1  augustss 		break;
    684       1.1  augustss 	case B115200:
    685       1.1  augustss 		lsp = UVSCOM_SPEED_115200BPS;
    686       1.1  augustss 		break;
    687       1.1  augustss 	default:
    688       1.1  augustss 		return (EIO);
    689       1.1  augustss 	}
    690       1.6  augustss 
    691       1.1  augustss 	if (ISSET(t->c_cflag, CSTOPB))
    692       1.1  augustss 		SET(ls, UVSCOM_STOP_BIT_2);
    693       1.1  augustss 	else
    694       1.1  augustss 		SET(ls, UVSCOM_STOP_BIT_1);
    695       1.1  augustss 
    696       1.1  augustss 	if (ISSET(t->c_cflag, PARENB)) {
    697       1.1  augustss 		if (ISSET(t->c_cflag, PARODD))
    698       1.1  augustss 			SET(ls, UVSCOM_PARITY_ODD);
    699       1.1  augustss 		else
    700       1.1  augustss 			SET(ls, UVSCOM_PARITY_EVEN);
    701       1.1  augustss 	} else
    702       1.1  augustss 		SET(ls, UVSCOM_PARITY_NONE);
    703       1.1  augustss 
    704       1.1  augustss 	switch (ISSET(t->c_cflag, CSIZE)) {
    705       1.1  augustss 	case CS5:
    706       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_5);
    707       1.1  augustss 		break;
    708       1.1  augustss 	case CS6:
    709       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_6);
    710       1.1  augustss 		break;
    711       1.1  augustss 	case CS7:
    712       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_7);
    713       1.1  augustss 		break;
    714       1.1  augustss 	case CS8:
    715       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_8);
    716       1.1  augustss 		break;
    717       1.1  augustss 	default:
    718       1.1  augustss 		return (EIO);
    719       1.1  augustss 	}
    720       1.1  augustss 
    721       1.1  augustss 	err = uvscom_set_line_coding(sc, lsp, ls);
    722       1.1  augustss 	if (err)
    723       1.1  augustss 		return (EIO);
    724       1.1  augustss 
    725       1.1  augustss 	if (ISSET(t->c_cflag, CRTSCTS)) {
    726       1.1  augustss 		err = uvscom_set_crtscts(sc);
    727       1.1  augustss 		if (err)
    728       1.1  augustss 			return (EIO);
    729       1.1  augustss 	}
    730       1.1  augustss 
    731       1.1  augustss 	return (0);
    732       1.1  augustss }
    733       1.1  augustss 
    734       1.1  augustss Static int
    735      1.19  christos uvscom_open(void *addr, int portno)
    736       1.1  augustss {
    737       1.1  augustss 	struct uvscom_softc *sc = addr;
    738       1.1  augustss 	int err;
    739       1.1  augustss 	int i;
    740       1.6  augustss 
    741       1.1  augustss 	if (sc->sc_dying)
    742       1.1  augustss 		return (EIO);
    743       1.1  augustss 
    744       1.1  augustss 	DPRINTF(("uvscom_open: sc = %p\n", sc));
    745       1.1  augustss 
    746       1.1  augustss 	if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
    747       1.1  augustss 		DPRINTF(("uvscom_open: open interrupt pipe.\n"));
    748       1.1  augustss 
    749       1.1  augustss 		sc->sc_usr = 0;		/* clear unit status */
    750       1.1  augustss 
    751       1.1  augustss 		err = uvscom_readstat(sc);
    752       1.1  augustss 		if (err) {
    753       1.1  augustss 			DPRINTF(("%s: uvscom_open: readstat faild\n",
    754       1.1  augustss 				 USBDEVNAME(sc->sc_dev)));
    755       1.1  augustss 			return (EIO);
    756       1.1  augustss 		}
    757       1.1  augustss 
    758       1.1  augustss 		sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
    759       1.1  augustss 		err = usbd_open_pipe_intr(sc->sc_iface,
    760       1.1  augustss 					  sc->sc_intr_number,
    761       1.1  augustss 					  USBD_SHORT_XFER_OK,
    762       1.1  augustss 					  &sc->sc_intr_pipe,
    763       1.1  augustss 					  sc,
    764       1.1  augustss 					  sc->sc_intr_buf,
    765       1.1  augustss 					  sc->sc_isize,
    766       1.1  augustss 					  uvscom_intr,
    767       1.1  augustss 					  UVSCOM_INTR_INTERVAL);
    768       1.1  augustss 		if (err) {
    769  1.21.8.1      yamt 			aprint_error_dev(sc->sc_dev,
    770  1.21.8.1      yamt 			    "cannot open interrupt pipe (addr %d)\n",
    771       1.1  augustss 				 sc->sc_intr_number);
    772       1.1  augustss 			return (EIO);
    773       1.1  augustss 		}
    774       1.1  augustss 	} else {
    775       1.1  augustss 		DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
    776       1.1  augustss 	}
    777       1.1  augustss 
    778       1.1  augustss 	if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) {
    779       1.1  augustss 		/* unit is not ready */
    780       1.1  augustss 
    781       1.1  augustss 		for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
    782       1.1  augustss 			tsleep(&err, TTIPRI, "uvsop", hz);	/* XXX */
    783       1.1  augustss 			if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK))
    784       1.1  augustss 				break;
    785       1.1  augustss 		}
    786       1.1  augustss 		if (i == 0) {
    787       1.1  augustss 			DPRINTF(("%s: unit is not ready\n",
    788       1.1  augustss 				 USBDEVNAME(sc->sc_dev)));
    789       1.1  augustss 			return (EIO);
    790       1.1  augustss 		}
    791       1.1  augustss 
    792       1.1  augustss 		/* check PC card was inserted */
    793       1.1  augustss 		if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) {
    794       1.1  augustss 			DPRINTF(("%s: no card\n",
    795       1.1  augustss 				 USBDEVNAME(sc->sc_dev)));
    796       1.1  augustss 			return (EIO);
    797       1.1  augustss 		}
    798       1.1  augustss 	}
    799       1.1  augustss 
    800       1.1  augustss 	return (0);
    801       1.1  augustss }
    802       1.1  augustss 
    803       1.1  augustss Static void
    804      1.19  christos uvscom_close(void *addr, int portno)
    805       1.1  augustss {
    806       1.1  augustss 	struct uvscom_softc *sc = addr;
    807       1.1  augustss 	int err;
    808       1.1  augustss 
    809       1.1  augustss 	if (sc->sc_dying)
    810       1.1  augustss 		return;
    811       1.1  augustss 
    812       1.1  augustss 	DPRINTF(("uvscom_close: close\n"));
    813       1.1  augustss 
    814       1.1  augustss 	uvscom_shutdown(sc);
    815       1.1  augustss 
    816       1.1  augustss 	if (sc->sc_intr_pipe != NULL) {
    817       1.1  augustss 		err = usbd_abort_pipe(sc->sc_intr_pipe);
    818       1.1  augustss 		if (err)
    819  1.21.8.1      yamt 			aprint_error_dev(sc->sc_dev,
    820  1.21.8.1      yamt 			    "abort interrupt pipe failed: %s\n",
    821  1.21.8.1      yamt 			    usbd_errstr(err));
    822       1.1  augustss 		err = usbd_close_pipe(sc->sc_intr_pipe);
    823       1.1  augustss 		if (err)
    824  1.21.8.1      yamt 			aprint_error_dev(sc->sc_dev,
    825  1.21.8.1      yamt 			    "lose interrupt pipe failed: %s\n",
    826  1.21.8.1      yamt 			    usbd_errstr(err));
    827       1.1  augustss 		free(sc->sc_intr_buf, M_USBDEV);
    828       1.1  augustss 		sc->sc_intr_pipe = NULL;
    829       1.1  augustss 	}
    830       1.1  augustss }
    831       1.1  augustss 
    832       1.1  augustss Static void
    833      1.19  christos uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv,
    834      1.18  christos     usbd_status status)
    835       1.1  augustss {
    836       1.1  augustss 	struct uvscom_softc *sc = priv;
    837       1.1  augustss 	u_char *buf = sc->sc_intr_buf;
    838       1.1  augustss 	u_char pstatus;
    839       1.1  augustss 
    840       1.1  augustss 	if (sc->sc_dying)
    841       1.1  augustss 		return;
    842       1.1  augustss 
    843       1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    844       1.1  augustss 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    845       1.1  augustss 			return;
    846       1.1  augustss 
    847  1.21.8.1      yamt 		aprint_error_dev(sc->sc_dev,
    848  1.21.8.1      yamt 		    "uvscom_intr: abnormal status: %s\n",
    849  1.21.8.1      yamt 		    usbd_errstr(status));
    850       1.1  augustss 		usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
    851       1.1  augustss 		return;
    852       1.1  augustss 	}
    853       1.1  augustss 
    854       1.1  augustss 	DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
    855       1.1  augustss 		 USBDEVNAME(sc->sc_dev), buf[0], buf[1]));
    856       1.1  augustss 
    857       1.1  augustss 	sc->sc_lsr = sc->sc_msr = 0;
    858       1.1  augustss 	sc->sc_usr = buf[1];
    859       1.1  augustss 
    860       1.1  augustss 	pstatus = buf[0];
    861       1.1  augustss 	if (ISSET(pstatus, UVSCOM_TXRDY))
    862       1.1  augustss 		SET(sc->sc_lsr, ULSR_TXRDY);
    863       1.1  augustss 	if (ISSET(pstatus, UVSCOM_RXRDY))
    864       1.1  augustss 		SET(sc->sc_lsr, ULSR_RXRDY);
    865       1.1  augustss 
    866       1.1  augustss 	pstatus = buf[1];
    867       1.1  augustss 	if (ISSET(pstatus, UVSCOM_CTS))
    868       1.1  augustss 		SET(sc->sc_msr, UMSR_CTS);
    869       1.1  augustss 	if (ISSET(pstatus, UVSCOM_DSR))
    870       1.1  augustss 		SET(sc->sc_msr, UMSR_DSR);
    871       1.1  augustss 	if (ISSET(pstatus, UVSCOM_DCD))
    872       1.1  augustss 		SET(sc->sc_msr, UMSR_DCD);
    873       1.1  augustss 
    874  1.21.8.1      yamt 	ucom_status_change(device_private(sc->sc_subdev));
    875       1.1  augustss }
    876       1.1  augustss 
    877       1.1  augustss Static void
    878      1.19  christos uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
    879       1.1  augustss {
    880       1.1  augustss 	struct uvscom_softc *sc = addr;
    881       1.1  augustss 
    882       1.1  augustss 	if (lsr != NULL)
    883       1.1  augustss 		*lsr = sc->sc_lsr;
    884       1.1  augustss 	if (msr != NULL)
    885       1.1  augustss 		*msr = sc->sc_msr;
    886       1.1  augustss }
    887       1.1  augustss 
    888