LCOV - code coverage report
Current view: top level - dev/usb - uvscom.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 313 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13