Home | History | Annotate | Line # | Download | only in usb
uvscom.c revision 1.24.2.1
      1  1.24.2.1  uebayasi /*	$NetBSD: uvscom.c,v 1.24.2.1 2010/11/06 08:08:42 uebayasi 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.24.2.1  uebayasi __KERNEL_RCSID(0, "$NetBSD: uvscom.c,v 1.24.2.1 2010/11/06 08:08:42 uebayasi 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.24.2.1  uebayasi 					printf 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.24.2.1  uebayasi 	device_t		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.24.2.1  uebayasi 	device_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.22      cube 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.22      cube 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.24.2.1  uebayasi int
    245  1.24.2.1  uebayasi uvscom_match(device_t parent, cfdata_t match, void *aux)
    246       1.1  augustss {
    247  1.24.2.1  uebayasi 	struct usb_attach_arg *uaa = aux;
    248       1.1  augustss 
    249       1.1  augustss 	return (uvscom_lookup(uaa->vendor, uaa->product) != NULL ?
    250       1.1  augustss 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
    251       1.1  augustss }
    252       1.1  augustss 
    253  1.24.2.1  uebayasi void
    254  1.24.2.1  uebayasi uvscom_attach(device_t parent, device_t self, void *aux)
    255       1.1  augustss {
    256  1.24.2.1  uebayasi 	struct uvscom_softc *sc = device_private(self);
    257  1.24.2.1  uebayasi 	struct usb_attach_arg *uaa = aux;
    258       1.1  augustss 	usbd_device_handle dev = uaa->device;
    259       1.1  augustss 	usb_config_descriptor_t *cdesc;
    260       1.1  augustss 	usb_interface_descriptor_t *id;
    261       1.1  augustss 	usb_endpoint_descriptor_t *ed;
    262      1.15  augustss 	char *devinfop;
    263       1.1  augustss 	usbd_status err;
    264       1.1  augustss 	int i;
    265       1.1  augustss 	struct ucom_attach_args uca;
    266       1.1  augustss 
    267      1.23    plunky 	aprint_naive("\n");
    268      1.23    plunky 	aprint_normal("\n");
    269      1.23    plunky 
    270      1.15  augustss 	devinfop = usbd_devinfo_alloc(dev, 0);
    271      1.23    plunky 	aprint_normal_dev(self, "%s\n", devinfop);
    272      1.15  augustss 	usbd_devinfo_free(devinfop);
    273       1.1  augustss 
    274      1.22      cube 	sc->sc_dev = self;
    275       1.1  augustss         sc->sc_udev = dev;
    276       1.1  augustss 
    277       1.1  augustss 	DPRINTF(("uvscom attach: sc = %p\n", sc));
    278       1.1  augustss 
    279       1.6  augustss 	/* initialize endpoints */
    280       1.1  augustss 	uca.bulkin = uca.bulkout = -1;
    281       1.1  augustss 	sc->sc_intr_number = -1;
    282       1.1  augustss 	sc->sc_intr_pipe = NULL;
    283       1.1  augustss 
    284       1.1  augustss 	/* Move the device into the configured state. */
    285       1.1  augustss 	err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1);
    286       1.1  augustss 	if (err) {
    287      1.22      cube 		aprint_error_dev(self, "failed to set configuration, err=%s\n",
    288      1.22      cube 		    usbd_errstr(err));
    289       1.1  augustss 		sc->sc_dying = 1;
    290  1.24.2.1  uebayasi 		return;
    291       1.1  augustss 	}
    292       1.1  augustss 
    293       1.1  augustss 	/* get the config descriptor */
    294       1.1  augustss 	cdesc = usbd_get_config_descriptor(sc->sc_udev);
    295       1.1  augustss 
    296       1.1  augustss 	if (cdesc == NULL) {
    297      1.22      cube 		aprint_error_dev(self,
    298      1.22      cube 		    "failed to get configuration descriptor\n");
    299       1.1  augustss 		sc->sc_dying = 1;
    300  1.24.2.1  uebayasi 		return;
    301       1.1  augustss 	}
    302       1.1  augustss 
    303       1.1  augustss 	/* get the common interface */
    304       1.6  augustss 	err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX,
    305       1.1  augustss 					   &sc->sc_iface);
    306       1.1  augustss 	if (err) {
    307      1.22      cube 		aprint_error_dev(self, "failed to get interface, err=%s\n",
    308      1.22      cube 		    usbd_errstr(err));
    309       1.1  augustss 		sc->sc_dying = 1;
    310  1.24.2.1  uebayasi 		return;
    311       1.1  augustss 	}
    312       1.1  augustss 
    313       1.1  augustss 	id = usbd_get_interface_descriptor(sc->sc_iface);
    314       1.1  augustss 	sc->sc_iface_number = id->bInterfaceNumber;
    315       1.1  augustss 
    316       1.1  augustss 	/* Find endpoints */
    317       1.1  augustss 	for (i = 0; i < id->bNumEndpoints; i++) {
    318       1.1  augustss 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
    319       1.1  augustss 		if (ed == NULL) {
    320      1.22      cube 			aprint_error_dev(self,
    321      1.22      cube 			    "no endpoint descriptor for %d\n", i);
    322       1.1  augustss 			sc->sc_dying = 1;
    323  1.24.2.1  uebayasi 			return;
    324       1.1  augustss 		}
    325       1.1  augustss 
    326       1.1  augustss 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    327       1.1  augustss 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    328       1.1  augustss 			uca.bulkin = ed->bEndpointAddress;
    329       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    330       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    331       1.1  augustss 			uca.bulkout = ed->bEndpointAddress;
    332       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    333       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    334       1.1  augustss 			sc->sc_intr_number = ed->bEndpointAddress;
    335       1.1  augustss 			sc->sc_isize = UGETW(ed->wMaxPacketSize);
    336       1.6  augustss 		}
    337       1.1  augustss 	}
    338       1.1  augustss 
    339       1.1  augustss 	if (uca.bulkin == -1) {
    340      1.22      cube 		aprint_error_dev(self, "Could not find data bulk in\n");
    341       1.1  augustss 		sc->sc_dying = 1;
    342  1.24.2.1  uebayasi 		return;
    343       1.1  augustss 	}
    344       1.1  augustss 	if (uca.bulkout == -1) {
    345      1.22      cube 		aprint_error_dev(self, "Could not find data bulk out\n");
    346       1.1  augustss 		sc->sc_dying = 1;
    347  1.24.2.1  uebayasi 		return;
    348       1.1  augustss 	}
    349       1.1  augustss 	if (sc->sc_intr_number == -1) {
    350      1.22      cube 		aprint_error_dev(self, "Could not find interrupt in\n");
    351       1.1  augustss 		sc->sc_dying = 1;
    352  1.24.2.1  uebayasi 		return;
    353       1.1  augustss 	}
    354       1.1  augustss 
    355       1.1  augustss 	sc->sc_dtr = sc->sc_rts = 0;
    356       1.1  augustss 	sc->sc_lcr = UVSCOM_LINE_INIT;
    357       1.1  augustss 
    358       1.1  augustss 	uca.portno = UCOM_UNK_PORTNO;
    359       1.1  augustss 	/* bulkin, bulkout set above */
    360       1.1  augustss 	uca.ibufsize = UVSCOMIBUFSIZE;
    361       1.1  augustss 	uca.obufsize = UVSCOMOBUFSIZE;
    362       1.1  augustss 	uca.ibufsizepad = UVSCOMIBUFSIZE;
    363       1.1  augustss 	uca.opkthdrlen = 0;
    364       1.1  augustss 	uca.device = dev;
    365       1.1  augustss 	uca.iface = sc->sc_iface;
    366       1.1  augustss 	uca.methods = &uvscom_methods;
    367       1.1  augustss 	uca.arg = sc;
    368       1.1  augustss 	uca.info = NULL;
    369       1.1  augustss 
    370       1.1  augustss 	err = uvscom_reset(sc);
    371       1.1  augustss 
    372       1.1  augustss 	if (err) {
    373      1.22      cube 		aprint_error_dev(self, "reset failed, %s\n", usbd_errstr(err));
    374       1.1  augustss 		sc->sc_dying = 1;
    375  1.24.2.1  uebayasi 		return;
    376       1.1  augustss 	}
    377       1.1  augustss 
    378       1.1  augustss 	DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
    379      1.17  christos 		 uca.bulkin, uca.bulkout, sc->sc_intr_number));
    380       1.1  augustss 
    381       1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    382  1.24.2.1  uebayasi 			   sc->sc_dev);
    383       1.1  augustss 
    384       1.1  augustss 	DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
    385       1.1  augustss 			uca.bulkin, uca.bulkout, sc->sc_intr_number ));
    386      1.13  drochner 	sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca,
    387      1.13  drochner 					    ucomprint, ucomsubmatch);
    388       1.1  augustss 
    389  1.24.2.1  uebayasi 	return;
    390       1.1  augustss }
    391       1.1  augustss 
    392      1.21    dyoung void
    393      1.21    dyoung uvscom_childdet(device_t self, device_t child)
    394      1.21    dyoung {
    395      1.21    dyoung 	struct uvscom_softc *sc = device_private(self);
    396      1.21    dyoung 
    397      1.21    dyoung 	KASSERT(sc->sc_subdev == child);
    398      1.21    dyoung 	sc->sc_subdev = NULL;
    399      1.21    dyoung }
    400      1.21    dyoung 
    401  1.24.2.1  uebayasi int
    402  1.24.2.1  uebayasi uvscom_detach(device_t self, int flags)
    403       1.1  augustss {
    404  1.24.2.1  uebayasi 	struct uvscom_softc *sc = device_private(self);
    405       1.1  augustss 	int rv = 0;
    406       1.1  augustss 
    407       1.1  augustss 	DPRINTF(("uvscom_detach: sc = %p\n", sc));
    408       1.1  augustss 
    409       1.1  augustss 	sc->sc_dying = 1;
    410       1.1  augustss 
    411       1.1  augustss 	if (sc->sc_intr_pipe != NULL) {
    412       1.1  augustss 		usbd_abort_pipe(sc->sc_intr_pipe);
    413       1.1  augustss 		usbd_close_pipe(sc->sc_intr_pipe);
    414       1.1  augustss 		free(sc->sc_intr_buf, M_USBDEV);
    415       1.1  augustss 		sc->sc_intr_pipe = NULL;
    416       1.1  augustss 	}
    417       1.1  augustss 
    418       1.1  augustss 	sc->sc_dying = 1;
    419      1.21    dyoung 	if (sc->sc_subdev != NULL)
    420       1.1  augustss 		rv = config_detach(sc->sc_subdev, flags);
    421       1.1  augustss 
    422       1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    423  1.24.2.1  uebayasi 			   sc->sc_dev);
    424       1.1  augustss 
    425       1.1  augustss 	return (rv);
    426       1.1  augustss }
    427       1.1  augustss 
    428       1.3  augustss int
    429      1.21    dyoung uvscom_activate(device_t self, enum devact act)
    430       1.1  augustss {
    431      1.21    dyoung 	struct uvscom_softc *sc = device_private(self);
    432       1.1  augustss 
    433       1.1  augustss 	switch (act) {
    434       1.1  augustss 	case DVACT_DEACTIVATE:
    435       1.1  augustss 		sc->sc_dying = 1;
    436      1.24    dyoung 		return 0;
    437      1.24    dyoung 	default:
    438      1.24    dyoung 		return EOPNOTSUPP;
    439       1.1  augustss 	}
    440       1.1  augustss }
    441       1.1  augustss 
    442       1.1  augustss Static usbd_status
    443       1.1  augustss uvscom_readstat(struct uvscom_softc *sc)
    444       1.1  augustss {
    445       1.1  augustss 	usb_device_request_t req;
    446       1.1  augustss 	usbd_status err;
    447       1.1  augustss 	uint16_t r;
    448       1.1  augustss 
    449  1.24.2.1  uebayasi 	DPRINTF(("%s: send readstat\n", device_xname(sc->sc_dev)));
    450       1.1  augustss 
    451       1.1  augustss 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    452       1.1  augustss 	req.bRequest = UVSCOM_READ_STATUS;
    453       1.1  augustss 	USETW(req.wValue, 0);
    454       1.1  augustss 	USETW(req.wIndex, 0);
    455       1.6  augustss 	USETW(req.wLength, 2);
    456       1.1  augustss 
    457       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, &r);
    458       1.1  augustss 	if (err) {
    459      1.22      cube 		aprint_error_dev(sc->sc_dev, "uvscom_readstat: %s\n",
    460      1.22      cube 		    usbd_errstr(err));
    461       1.1  augustss 		return (err);
    462       1.1  augustss 	}
    463       1.1  augustss 
    464       1.1  augustss 	DPRINTF(("%s: uvscom_readstat: r = %d\n",
    465  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), r));
    466       1.1  augustss 
    467       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    468       1.1  augustss }
    469       1.1  augustss 
    470       1.1  augustss Static usbd_status
    471       1.1  augustss uvscom_shutdown(struct uvscom_softc *sc)
    472       1.1  augustss {
    473       1.1  augustss 	usb_device_request_t req;
    474       1.1  augustss 	usbd_status err;
    475       1.1  augustss 
    476  1.24.2.1  uebayasi 	DPRINTF(("%s: send shutdown\n", device_xname(sc->sc_dev)));
    477       1.1  augustss 
    478       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    479       1.1  augustss 	req.bRequest = UVSCOM_SHUTDOWN;
    480       1.1  augustss 	USETW(req.wValue, 0);
    481       1.1  augustss 	USETW(req.wIndex, 0);
    482       1.6  augustss 	USETW(req.wLength, 0);
    483       1.1  augustss 
    484       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    485       1.1  augustss 	if (err) {
    486      1.22      cube 		aprint_error_dev(sc->sc_dev, "uvscom_shutdown: %s\n",
    487      1.22      cube 		   usbd_errstr(err));
    488       1.1  augustss 		return (err);
    489       1.1  augustss 	}
    490       1.1  augustss 
    491       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    492       1.1  augustss }
    493       1.1  augustss 
    494       1.1  augustss Static usbd_status
    495      1.19  christos uvscom_reset(struct uvscom_softc *sc)
    496       1.1  augustss {
    497  1.24.2.1  uebayasi 	DPRINTF(("%s: uvscom_reset\n", device_xname(sc->sc_dev)));
    498       1.1  augustss 
    499       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    500       1.1  augustss }
    501       1.1  augustss 
    502       1.1  augustss Static usbd_status
    503      1.19  christos uvscom_set_crtscts(struct uvscom_softc *sc)
    504       1.1  augustss {
    505  1.24.2.1  uebayasi 	DPRINTF(("%s: uvscom_set_crtscts\n", device_xname(sc->sc_dev)));
    506       1.1  augustss 
    507       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    508       1.1  augustss }
    509       1.1  augustss 
    510       1.1  augustss Static usbd_status
    511       1.1  augustss uvscom_set_line(struct uvscom_softc *sc, uint16_t line)
    512       1.1  augustss {
    513       1.1  augustss 	usb_device_request_t req;
    514       1.1  augustss 	usbd_status err;
    515       1.1  augustss 
    516       1.1  augustss 	DPRINTF(("%s: uvscom_set_line: %04x\n",
    517  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), line));
    518       1.1  augustss 
    519       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    520       1.1  augustss 	req.bRequest = UVSCOM_LINE_CTL;
    521       1.1  augustss 	USETW(req.wValue, line);
    522       1.1  augustss 	USETW(req.wIndex, 0);
    523       1.6  augustss 	USETW(req.wLength, 0);
    524       1.1  augustss 
    525       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    526       1.1  augustss 	if (err) {
    527      1.22      cube 		aprint_error_dev(sc->sc_dev, "uvscom_set_line: %s\n",
    528      1.22      cube 		    usbd_errstr(err));
    529       1.1  augustss 		return (err);
    530       1.1  augustss 	}
    531       1.1  augustss 
    532       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    533       1.1  augustss }
    534       1.1  augustss 
    535       1.1  augustss Static usbd_status
    536       1.1  augustss uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls)
    537       1.1  augustss {
    538       1.1  augustss 	usb_device_request_t req;
    539       1.1  augustss 	usbd_status err;
    540       1.1  augustss 
    541       1.1  augustss 	DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
    542  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), lsp, ls));
    543       1.1  augustss 
    544       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    545       1.1  augustss 	req.bRequest = UVSCOM_SET_SPEED;
    546       1.1  augustss 	USETW(req.wValue, lsp);
    547       1.1  augustss 	USETW(req.wIndex, 0);
    548       1.1  augustss 	USETW(req.wLength, 0);
    549       1.1  augustss 
    550       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    551       1.1  augustss 	if (err) {
    552      1.22      cube 		aprint_error_dev(sc->sc_dev, "uvscom_set_line_coding: %s\n",
    553      1.22      cube 		   usbd_errstr(err));
    554       1.1  augustss 		return (err);
    555       1.1  augustss 	}
    556       1.1  augustss 
    557       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    558       1.1  augustss 	req.bRequest = UVSCOM_SET_PARAM;
    559       1.1  augustss 	USETW(req.wValue, ls);
    560       1.1  augustss 	USETW(req.wIndex, 0);
    561       1.1  augustss 	USETW(req.wLength, 0);
    562       1.1  augustss 
    563       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    564       1.1  augustss 	if (err) {
    565      1.22      cube 		aprint_error_dev(sc->sc_dev, "uvscom_set_line_coding: %s\n",
    566      1.22      cube 		   usbd_errstr(err));
    567       1.1  augustss 		return (err);
    568       1.1  augustss 	}
    569       1.1  augustss 
    570       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    571       1.1  augustss }
    572       1.1  augustss 
    573       1.1  augustss Static void
    574       1.1  augustss uvscom_dtr(struct uvscom_softc *sc, int onoff)
    575       1.1  augustss {
    576       1.1  augustss 	DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
    577  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), onoff));
    578       1.1  augustss 
    579       1.1  augustss 	if (sc->sc_dtr == onoff)
    580       1.1  augustss 		return;			/* no change */
    581       1.1  augustss 
    582       1.1  augustss 	sc->sc_dtr = onoff;
    583       1.1  augustss 
    584       1.1  augustss 	if (onoff)
    585       1.1  augustss 		SET(sc->sc_lcr, UVSCOM_DTR);
    586       1.1  augustss 	else
    587       1.1  augustss 		CLR(sc->sc_lcr, UVSCOM_DTR);
    588       1.1  augustss 
    589       1.1  augustss 	uvscom_set_line(sc, sc->sc_lcr);
    590       1.1  augustss }
    591       1.1  augustss 
    592       1.1  augustss Static void
    593       1.1  augustss uvscom_rts(struct uvscom_softc *sc, int onoff)
    594       1.1  augustss {
    595       1.1  augustss 	DPRINTF(("%s: uvscom_rts: onoff = %d\n",
    596  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), onoff));
    597       1.1  augustss 
    598       1.1  augustss 	if (sc->sc_rts == onoff)
    599       1.1  augustss 		return;			/* no change */
    600       1.1  augustss 
    601       1.1  augustss 	sc->sc_rts = onoff;
    602       1.1  augustss 
    603       1.1  augustss 	if (onoff)
    604       1.1  augustss 		SET(sc->sc_lcr, UVSCOM_RTS);
    605       1.1  augustss 	else
    606       1.1  augustss 		CLR(sc->sc_lcr, UVSCOM_RTS);
    607       1.1  augustss 
    608       1.1  augustss 	uvscom_set_line(sc, sc->sc_lcr);
    609       1.1  augustss }
    610       1.1  augustss 
    611       1.1  augustss Static void
    612       1.1  augustss uvscom_break(struct uvscom_softc *sc, int onoff)
    613       1.1  augustss {
    614       1.1  augustss 	DPRINTF(("%s: uvscom_break: onoff = %d\n",
    615  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), onoff));
    616       1.1  augustss 
    617       1.1  augustss 	if (onoff)
    618       1.1  augustss 		uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK));
    619       1.1  augustss }
    620       1.1  augustss 
    621       1.1  augustss Static void
    622      1.19  christos uvscom_set(void *addr, int portno, int reg, int onoff)
    623       1.1  augustss {
    624       1.1  augustss 	struct uvscom_softc *sc = addr;
    625       1.1  augustss 
    626       1.1  augustss 	switch (reg) {
    627       1.1  augustss 	case UCOM_SET_DTR:
    628       1.1  augustss 		uvscom_dtr(sc, onoff);
    629       1.1  augustss 		break;
    630       1.1  augustss 	case UCOM_SET_RTS:
    631       1.1  augustss 		uvscom_rts(sc, onoff);
    632       1.1  augustss 		break;
    633       1.1  augustss 	case UCOM_SET_BREAK:
    634       1.1  augustss 		uvscom_break(sc, onoff);
    635       1.1  augustss 		break;
    636       1.1  augustss 	default:
    637       1.1  augustss 		break;
    638       1.1  augustss 	}
    639       1.1  augustss }
    640       1.1  augustss 
    641       1.1  augustss Static int
    642      1.19  christos uvscom_param(void *addr, int portno, struct termios *t)
    643       1.1  augustss {
    644       1.1  augustss 	struct uvscom_softc *sc = addr;
    645       1.1  augustss 	usbd_status err;
    646       1.1  augustss 	uint16_t lsp;
    647       1.1  augustss 	uint16_t ls;
    648       1.1  augustss 
    649       1.1  augustss 	DPRINTF(("%s: uvscom_param: sc = %p\n",
    650  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), sc));
    651       1.1  augustss 
    652       1.1  augustss 	ls = 0;
    653       1.1  augustss 
    654       1.1  augustss 	switch (t->c_ospeed) {
    655       1.1  augustss 	case B150:
    656       1.1  augustss 		lsp = UVSCOM_SPEED_150BPS;
    657       1.1  augustss 		break;
    658       1.1  augustss 	case B300:
    659       1.1  augustss 		lsp = UVSCOM_SPEED_300BPS;
    660       1.1  augustss 		break;
    661       1.1  augustss 	case B600:
    662       1.1  augustss 		lsp = UVSCOM_SPEED_600BPS;
    663       1.1  augustss 		break;
    664       1.1  augustss 	case B1200:
    665       1.1  augustss 		lsp = UVSCOM_SPEED_1200BPS;
    666       1.1  augustss 		break;
    667       1.1  augustss 	case B2400:
    668       1.1  augustss 		lsp = UVSCOM_SPEED_2400BPS;
    669       1.1  augustss 		break;
    670       1.1  augustss 	case B4800:
    671       1.1  augustss 		lsp = UVSCOM_SPEED_4800BPS;
    672       1.1  augustss 		break;
    673       1.1  augustss 	case B9600:
    674       1.1  augustss 		lsp = UVSCOM_SPEED_9600BPS;
    675       1.1  augustss 		break;
    676       1.1  augustss 	case B19200:
    677       1.1  augustss 		lsp = UVSCOM_SPEED_19200BPS;
    678       1.1  augustss 		break;
    679       1.1  augustss 	case B38400:
    680       1.1  augustss 		lsp = UVSCOM_SPEED_38400BPS;
    681       1.1  augustss 		break;
    682       1.1  augustss 	case B57600:
    683       1.1  augustss 		lsp = UVSCOM_SPEED_57600BPS;
    684       1.1  augustss 		break;
    685       1.1  augustss 	case B115200:
    686       1.1  augustss 		lsp = UVSCOM_SPEED_115200BPS;
    687       1.1  augustss 		break;
    688       1.1  augustss 	default:
    689       1.1  augustss 		return (EIO);
    690       1.1  augustss 	}
    691       1.6  augustss 
    692       1.1  augustss 	if (ISSET(t->c_cflag, CSTOPB))
    693       1.1  augustss 		SET(ls, UVSCOM_STOP_BIT_2);
    694       1.1  augustss 	else
    695       1.1  augustss 		SET(ls, UVSCOM_STOP_BIT_1);
    696       1.1  augustss 
    697       1.1  augustss 	if (ISSET(t->c_cflag, PARENB)) {
    698       1.1  augustss 		if (ISSET(t->c_cflag, PARODD))
    699       1.1  augustss 			SET(ls, UVSCOM_PARITY_ODD);
    700       1.1  augustss 		else
    701       1.1  augustss 			SET(ls, UVSCOM_PARITY_EVEN);
    702       1.1  augustss 	} else
    703       1.1  augustss 		SET(ls, UVSCOM_PARITY_NONE);
    704       1.1  augustss 
    705       1.1  augustss 	switch (ISSET(t->c_cflag, CSIZE)) {
    706       1.1  augustss 	case CS5:
    707       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_5);
    708       1.1  augustss 		break;
    709       1.1  augustss 	case CS6:
    710       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_6);
    711       1.1  augustss 		break;
    712       1.1  augustss 	case CS7:
    713       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_7);
    714       1.1  augustss 		break;
    715       1.1  augustss 	case CS8:
    716       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_8);
    717       1.1  augustss 		break;
    718       1.1  augustss 	default:
    719       1.1  augustss 		return (EIO);
    720       1.1  augustss 	}
    721       1.1  augustss 
    722       1.1  augustss 	err = uvscom_set_line_coding(sc, lsp, ls);
    723       1.1  augustss 	if (err)
    724       1.1  augustss 		return (EIO);
    725       1.1  augustss 
    726       1.1  augustss 	if (ISSET(t->c_cflag, CRTSCTS)) {
    727       1.1  augustss 		err = uvscom_set_crtscts(sc);
    728       1.1  augustss 		if (err)
    729       1.1  augustss 			return (EIO);
    730       1.1  augustss 	}
    731       1.1  augustss 
    732       1.1  augustss 	return (0);
    733       1.1  augustss }
    734       1.1  augustss 
    735       1.1  augustss Static int
    736      1.19  christos uvscom_open(void *addr, int portno)
    737       1.1  augustss {
    738       1.1  augustss 	struct uvscom_softc *sc = addr;
    739       1.1  augustss 	int err;
    740       1.1  augustss 	int i;
    741       1.6  augustss 
    742       1.1  augustss 	if (sc->sc_dying)
    743       1.1  augustss 		return (EIO);
    744       1.1  augustss 
    745       1.1  augustss 	DPRINTF(("uvscom_open: sc = %p\n", sc));
    746       1.1  augustss 
    747       1.1  augustss 	if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
    748       1.1  augustss 		DPRINTF(("uvscom_open: open interrupt pipe.\n"));
    749       1.1  augustss 
    750       1.1  augustss 		sc->sc_usr = 0;		/* clear unit status */
    751       1.1  augustss 
    752       1.1  augustss 		err = uvscom_readstat(sc);
    753       1.1  augustss 		if (err) {
    754       1.1  augustss 			DPRINTF(("%s: uvscom_open: readstat faild\n",
    755  1.24.2.1  uebayasi 				 device_xname(sc->sc_dev)));
    756       1.1  augustss 			return (EIO);
    757       1.1  augustss 		}
    758       1.1  augustss 
    759       1.1  augustss 		sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
    760       1.1  augustss 		err = usbd_open_pipe_intr(sc->sc_iface,
    761       1.1  augustss 					  sc->sc_intr_number,
    762       1.1  augustss 					  USBD_SHORT_XFER_OK,
    763       1.1  augustss 					  &sc->sc_intr_pipe,
    764       1.1  augustss 					  sc,
    765       1.1  augustss 					  sc->sc_intr_buf,
    766       1.1  augustss 					  sc->sc_isize,
    767       1.1  augustss 					  uvscom_intr,
    768       1.1  augustss 					  UVSCOM_INTR_INTERVAL);
    769       1.1  augustss 		if (err) {
    770      1.22      cube 			aprint_error_dev(sc->sc_dev,
    771      1.22      cube 			    "cannot open interrupt pipe (addr %d)\n",
    772       1.1  augustss 				 sc->sc_intr_number);
    773       1.1  augustss 			return (EIO);
    774       1.1  augustss 		}
    775       1.1  augustss 	} else {
    776       1.1  augustss 		DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
    777       1.1  augustss 	}
    778       1.1  augustss 
    779       1.1  augustss 	if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) {
    780       1.1  augustss 		/* unit is not ready */
    781       1.1  augustss 
    782       1.1  augustss 		for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
    783       1.1  augustss 			tsleep(&err, TTIPRI, "uvsop", hz);	/* XXX */
    784       1.1  augustss 			if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK))
    785       1.1  augustss 				break;
    786       1.1  augustss 		}
    787       1.1  augustss 		if (i == 0) {
    788       1.1  augustss 			DPRINTF(("%s: unit is not ready\n",
    789  1.24.2.1  uebayasi 				 device_xname(sc->sc_dev)));
    790       1.1  augustss 			return (EIO);
    791       1.1  augustss 		}
    792       1.1  augustss 
    793       1.1  augustss 		/* check PC card was inserted */
    794       1.1  augustss 		if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) {
    795       1.1  augustss 			DPRINTF(("%s: no card\n",
    796  1.24.2.1  uebayasi 				 device_xname(sc->sc_dev)));
    797       1.1  augustss 			return (EIO);
    798       1.1  augustss 		}
    799       1.1  augustss 	}
    800       1.1  augustss 
    801       1.1  augustss 	return (0);
    802       1.1  augustss }
    803       1.1  augustss 
    804       1.1  augustss Static void
    805      1.19  christos uvscom_close(void *addr, int portno)
    806       1.1  augustss {
    807       1.1  augustss 	struct uvscom_softc *sc = addr;
    808       1.1  augustss 	int err;
    809       1.1  augustss 
    810       1.1  augustss 	if (sc->sc_dying)
    811       1.1  augustss 		return;
    812       1.1  augustss 
    813       1.1  augustss 	DPRINTF(("uvscom_close: close\n"));
    814       1.1  augustss 
    815       1.1  augustss 	uvscom_shutdown(sc);
    816       1.1  augustss 
    817       1.1  augustss 	if (sc->sc_intr_pipe != NULL) {
    818       1.1  augustss 		err = usbd_abort_pipe(sc->sc_intr_pipe);
    819       1.1  augustss 		if (err)
    820      1.22      cube 			aprint_error_dev(sc->sc_dev,
    821      1.22      cube 			    "abort interrupt pipe failed: %s\n",
    822      1.22      cube 			    usbd_errstr(err));
    823       1.1  augustss 		err = usbd_close_pipe(sc->sc_intr_pipe);
    824       1.1  augustss 		if (err)
    825      1.22      cube 			aprint_error_dev(sc->sc_dev,
    826      1.22      cube 			    "lose interrupt pipe failed: %s\n",
    827      1.22      cube 			    usbd_errstr(err));
    828       1.1  augustss 		free(sc->sc_intr_buf, M_USBDEV);
    829       1.1  augustss 		sc->sc_intr_pipe = NULL;
    830       1.1  augustss 	}
    831       1.1  augustss }
    832       1.1  augustss 
    833       1.1  augustss Static void
    834      1.19  christos uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv,
    835      1.18  christos     usbd_status status)
    836       1.1  augustss {
    837       1.1  augustss 	struct uvscom_softc *sc = priv;
    838       1.1  augustss 	u_char *buf = sc->sc_intr_buf;
    839       1.1  augustss 	u_char pstatus;
    840       1.1  augustss 
    841       1.1  augustss 	if (sc->sc_dying)
    842       1.1  augustss 		return;
    843       1.1  augustss 
    844       1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    845       1.1  augustss 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    846       1.1  augustss 			return;
    847       1.1  augustss 
    848      1.22      cube 		aprint_error_dev(sc->sc_dev,
    849      1.22      cube 		    "uvscom_intr: abnormal status: %s\n",
    850      1.22      cube 		    usbd_errstr(status));
    851       1.1  augustss 		usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
    852       1.1  augustss 		return;
    853       1.1  augustss 	}
    854       1.1  augustss 
    855       1.1  augustss 	DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
    856  1.24.2.1  uebayasi 		 device_xname(sc->sc_dev), buf[0], buf[1]));
    857       1.1  augustss 
    858       1.1  augustss 	sc->sc_lsr = sc->sc_msr = 0;
    859       1.1  augustss 	sc->sc_usr = buf[1];
    860       1.1  augustss 
    861       1.1  augustss 	pstatus = buf[0];
    862       1.1  augustss 	if (ISSET(pstatus, UVSCOM_TXRDY))
    863       1.1  augustss 		SET(sc->sc_lsr, ULSR_TXRDY);
    864       1.1  augustss 	if (ISSET(pstatus, UVSCOM_RXRDY))
    865       1.1  augustss 		SET(sc->sc_lsr, ULSR_RXRDY);
    866       1.1  augustss 
    867       1.1  augustss 	pstatus = buf[1];
    868       1.1  augustss 	if (ISSET(pstatus, UVSCOM_CTS))
    869       1.1  augustss 		SET(sc->sc_msr, UMSR_CTS);
    870       1.1  augustss 	if (ISSET(pstatus, UVSCOM_DSR))
    871       1.1  augustss 		SET(sc->sc_msr, UMSR_DSR);
    872       1.1  augustss 	if (ISSET(pstatus, UVSCOM_DCD))
    873       1.1  augustss 		SET(sc->sc_msr, UMSR_DCD);
    874       1.1  augustss 
    875      1.22      cube 	ucom_status_change(device_private(sc->sc_subdev));
    876       1.1  augustss }
    877       1.1  augustss 
    878       1.1  augustss Static void
    879      1.19  christos uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
    880       1.1  augustss {
    881       1.1  augustss 	struct uvscom_softc *sc = addr;
    882       1.1  augustss 
    883       1.1  augustss 	if (lsr != NULL)
    884       1.1  augustss 		*lsr = sc->sc_lsr;
    885       1.1  augustss 	if (msr != NULL)
    886       1.1  augustss 		*msr = sc->sc_msr;
    887       1.1  augustss }
    888       1.1  augustss 
    889