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

          Line data    Source code
       1             : /*      $OpenBSD: umct.c,v 1.47 2017/12/30 20:47:00 guenther Exp $      */
       2             : /*      $NetBSD: umct.c,v 1.10 2003/02/23 04:20:07 simonb Exp $ */
       3             : /*
       4             :  * Copyright (c) 2001 The NetBSD Foundation, Inc.
       5             :  * All rights reserved.
       6             :  *
       7             :  * This code is derived from software contributed to The NetBSD Foundation
       8             :  * by Ichiro FUKUHARA (ichiro@ichiro.org).
       9             :  *
      10             :  * Redistribution and use in source and binary forms, with or without
      11             :  * modification, are permitted provided that the following conditions
      12             :  * are met:
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer.
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      20             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      21             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      22             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      23             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      24             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      25             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      26             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      27             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      28             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      29             :  * POSSIBILITY OF SUCH DAMAGE.
      30             :  */
      31             : 
      32             : /*
      33             :  * MCT USB-RS232 Interface Controller
      34             :  * http://www.mct.com.tw/prod/rs232.html
      35             :  * http://www.dlink.com/products/usb/dsbs25
      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/ioctl.h>
      43             : #include <sys/conf.h>
      44             : #include <sys/tty.h>
      45             : #include <sys/selinfo.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             : #include <dev/usb/umct.h>
      59             : 
      60             : #ifdef UMCT_DEBUG
      61             : #define DPRINTFN(n, x)  do { if (umctdebug > (n)) printf x; } while (0)
      62             : int     umctdebug = 0;
      63             : #else
      64             : #define DPRINTFN(n, x)
      65             : #endif
      66             : #define DPRINTF(x) DPRINTFN(0, x)
      67             : 
      68             : #define UMCT_IFACE_INDEX        0
      69             : 
      70             : struct  umct_softc {
      71             :         struct device            sc_dev;        /* base device */
      72             :         struct usbd_device      *sc_udev;       /* USB device */
      73             :         struct usbd_interface   *sc_iface;      /* interface */
      74             :         int                      sc_iface_number;       /* interface number */
      75             :         u_int16_t                sc_product;
      76             : 
      77             :         int                      sc_intr_number;        /* interrupt number */
      78             :         struct usbd_pipe        *sc_intr_pipe;  /* interrupt pipe */
      79             :         u_char                  *sc_intr_buf;   /* interrupt buffer */
      80             :         int                      sc_isize;
      81             : 
      82             :         struct usb_cdc_line_state sc_line_state;        /* current line state */
      83             :         u_char                   sc_dtr;        /* current DTR state */
      84             :         u_char                   sc_rts;        /* current RTS state */
      85             :         u_char                   sc_break;      /* set break */
      86             : 
      87             :         u_char                   sc_status;
      88             : 
      89             :         struct device           *sc_subdev;     /* ucom device */
      90             : 
      91             :         u_char                   sc_lsr;        /* Local status register */
      92             :         u_char                   sc_msr;        /* umct status register */
      93             : 
      94             :         u_int                    last_lcr;      /* keep lcr register */
      95             : };
      96             : 
      97             : /*
      98             :  * These are the maximum number of bytes transferred per frame.
      99             :  * The output buffer size cannot be increased due to the size encoding.
     100             :  */
     101             : #define UMCTIBUFSIZE 256
     102             : #define UMCTOBUFSIZE 256
     103             : 
     104             : void umct_init(struct umct_softc *);
     105             : void umct_set_baudrate(struct umct_softc *, u_int, int);
     106             : void umct_set_lcr(struct umct_softc *, u_int);
     107             : void umct_intr(struct usbd_xfer *, void *, usbd_status);
     108             : 
     109             : void umct_set(void *, int, int, int);
     110             : void umct_dtr(struct umct_softc *, int);
     111             : void umct_rts(struct umct_softc *, int);
     112             : void umct_break(struct umct_softc *, int);
     113             : void umct_set_line_state(struct umct_softc *);
     114             : void umct_get_status(void *, int portno, u_char *lsr, u_char *msr);
     115             : int  umct_param(void *, int, struct termios *);
     116             : int  umct_open(void *, int);
     117             : void umct_close(void *, int);
     118             : 
     119             : struct  ucom_methods umct_methods = {
     120             :         umct_get_status,
     121             :         umct_set,
     122             :         umct_param,
     123             :         NULL,
     124             :         umct_open,
     125             :         umct_close,
     126             :         NULL,
     127             :         NULL,
     128             : };
     129             : 
     130             : static const struct usb_devno umct_devs[] = {
     131             :         /* MCT USB-232 Interface Products */
     132             :         { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232 },
     133             :         /* Sitecom USB-232 Products */
     134             :         { USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232 },
     135             :         /* D-Link DU-H3SP USB BAY Hub Products */
     136             :         { USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232 },
     137             :         /* BELKIN F5U109 */
     138             :         { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U109 },
     139             :         /* BELKIN F5U409 */
     140             :         { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U409 },
     141             : };
     142             : 
     143             : int umct_match(struct device *, void *, void *);
     144             : void umct_attach(struct device *, struct device *, void *);
     145             : int umct_detach(struct device *, int);
     146             : 
     147             : struct cfdriver umct_cd = {
     148             :         NULL, "umct", DV_DULL
     149             : };
     150             : 
     151             : const struct cfattach umct_ca = {
     152             :         sizeof(struct umct_softc), umct_match, umct_attach, umct_detach
     153             : };
     154             : 
     155             : int
     156           0 : umct_match(struct device *parent, void *match, void *aux)
     157             : {
     158           0 :         struct usb_attach_arg *uaa = aux;
     159             : 
     160           0 :         if (uaa->iface == NULL)
     161           0 :                 return (UMATCH_NONE);
     162             : 
     163           0 :         return (usb_lookup(umct_devs, uaa->vendor, uaa->product) != NULL ?
     164             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
     165           0 : }
     166             : 
     167             : void
     168           0 : umct_attach(struct device *parent, struct device *self, void *aux)
     169             : {
     170           0 :         struct umct_softc *sc = (struct umct_softc *)self;
     171           0 :         struct usb_attach_arg *uaa = aux;
     172           0 :         struct usbd_device *dev = uaa->device;
     173             :         usb_config_descriptor_t *cdesc;
     174             :         usb_interface_descriptor_t *id;
     175             :         usb_endpoint_descriptor_t *ed;
     176             : 
     177           0 :         char *devname = sc->sc_dev.dv_xname;
     178             :         usbd_status err;
     179             :         int i;
     180           0 :         struct ucom_attach_args uca;
     181             : 
     182           0 :         sc->sc_udev = dev;
     183           0 :         sc->sc_product = uaa->product;
     184             : 
     185             :         DPRINTF(("\n\numct attach: sc=%p\n", sc));
     186             : 
     187             :         /* initialize endpoints */
     188           0 :         uca.bulkin = uca.bulkout = -1;
     189           0 :         sc->sc_intr_number = -1;
     190           0 :         sc->sc_intr_pipe = NULL;
     191             : 
     192             :         /* get the config descriptor */
     193           0 :         cdesc = usbd_get_config_descriptor(sc->sc_udev);
     194             : 
     195           0 :         if (cdesc == NULL) {
     196           0 :                 printf("%s: failed to get configuration descriptor\n",
     197             :                         sc->sc_dev.dv_xname);
     198           0 :                 usbd_deactivate(sc->sc_udev);
     199           0 :                 return;
     200             :         }
     201             : 
     202             :         /* get the interface */
     203           0 :         err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX,
     204           0 :                                                         &sc->sc_iface);
     205           0 :         if (err) {
     206           0 :                 printf("\n%s: failed to get interface, err=%s\n",
     207           0 :                         devname, usbd_errstr(err));
     208           0 :                 usbd_deactivate(sc->sc_udev);
     209           0 :                 return;
     210             :         }
     211             : 
     212             :         /* Find the bulk{in,out} and interrupt endpoints */
     213             : 
     214           0 :         id = usbd_get_interface_descriptor(sc->sc_iface);
     215           0 :         sc->sc_iface_number = id->bInterfaceNumber;
     216             : 
     217           0 :         for (i = 0; i < id->bNumEndpoints; i++) {
     218           0 :                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
     219           0 :                 if (ed == NULL) {
     220           0 :                         printf("%s: no endpoint descriptor for %d\n",
     221             :                                 sc->sc_dev.dv_xname, i);
     222           0 :                         usbd_deactivate(sc->sc_udev);
     223           0 :                         return;
     224             :                 }
     225             : 
     226             :                 /*
     227             :                  * The Bulkin endpoint is marked as an interrupt. Since
     228             :                  * we can't rely on the endpoint descriptor order, we'll
     229             :                  * check the wMaxPacketSize field to differentiate.
     230             :                  */
     231           0 :                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     232           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT &&
     233           0 :                     UGETW(ed->wMaxPacketSize) != 0x2) {
     234           0 :                         uca.bulkin = ed->bEndpointAddress;
     235           0 :                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
     236           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
     237           0 :                         uca.bulkout = ed->bEndpointAddress;
     238           0 :                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     239           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
     240           0 :                         sc->sc_intr_number = ed->bEndpointAddress;
     241           0 :                         sc->sc_isize = UGETW(ed->wMaxPacketSize);
     242           0 :                 }
     243             :         }
     244             : 
     245           0 :         if (uca.bulkin == -1) {
     246           0 :                 printf("%s: Could not find data bulk in\n",
     247             :                         sc->sc_dev.dv_xname);
     248           0 :                 usbd_deactivate(sc->sc_udev);
     249           0 :                 return;
     250             :         }
     251             : 
     252           0 :         if (uca.bulkout == -1) {
     253           0 :                 printf("%s: Could not find data bulk out\n",
     254             :                         sc->sc_dev.dv_xname);
     255           0 :                 usbd_deactivate(sc->sc_udev);
     256           0 :                 return;
     257             :         }
     258             : 
     259           0 :         if (sc->sc_intr_number== -1) {
     260           0 :                 printf("%s: Could not find interrupt in\n",
     261             :                         sc->sc_dev.dv_xname);
     262           0 :                 usbd_deactivate(sc->sc_udev);
     263           0 :                 return;
     264             :         }
     265             : 
     266           0 :         sc->sc_dtr = sc->sc_rts = 0;
     267           0 :         uca.portno = UCOM_UNK_PORTNO;
     268             :         /* bulkin, bulkout set above */
     269           0 :         uca.ibufsize = UMCTIBUFSIZE;
     270           0 :         if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232)
     271           0 :                 uca.obufsize = 16; /* device is broken */
     272             :         else
     273           0 :                 uca.obufsize = UMCTOBUFSIZE;
     274           0 :         uca.ibufsizepad = UMCTIBUFSIZE;
     275           0 :         uca.opkthdrlen = 0;
     276           0 :         uca.device = dev;
     277           0 :         uca.iface = sc->sc_iface;
     278           0 :         uca.methods = &umct_methods;
     279           0 :         uca.arg = sc;
     280           0 :         uca.info = NULL;
     281             : 
     282           0 :         umct_init(sc);
     283             : 
     284             :         DPRINTF(("umct: in=0x%x out=0x%x intr=0x%x\n",
     285             :                         uca.bulkin, uca.bulkout, sc->sc_intr_number ));
     286           0 :         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
     287           0 : }
     288             : 
     289             : int
     290           0 : umct_detach(struct device *self, int flags)
     291             : {
     292           0 :         struct umct_softc *sc = (struct umct_softc *)self;
     293             :         int rv = 0;
     294             : 
     295             :         DPRINTF(("umct_detach: sc=%p flags=%d\n", sc, flags));
     296             : 
     297           0 :         if (sc->sc_intr_pipe != NULL) {
     298           0 :                 usbd_abort_pipe(sc->sc_intr_pipe);
     299           0 :                 usbd_close_pipe(sc->sc_intr_pipe);
     300           0 :                 free(sc->sc_intr_buf, M_USBDEV, sc->sc_isize);
     301           0 :                 sc->sc_intr_pipe = NULL;
     302           0 :         }
     303             : 
     304           0 :         if (sc->sc_subdev != NULL) {
     305           0 :                 rv = config_detach(sc->sc_subdev, flags);
     306           0 :                 sc->sc_subdev = NULL;
     307           0 :         }
     308             : 
     309           0 :         return (rv);
     310             : }
     311             : 
     312             : void
     313           0 : umct_set_line_state(struct umct_softc *sc)
     314             : {
     315           0 :         usb_device_request_t req;
     316           0 :         uByte ls;
     317             : 
     318           0 :         ls = (sc->sc_dtr ? MCR_DTR : 0) |
     319           0 :              (sc->sc_rts ? MCR_RTS : 0);
     320             : 
     321             :         DPRINTF(("umct_set_line_state: DTR=%d,RTS=%d,ls=%02x\n",
     322             :                         sc->sc_dtr, sc->sc_rts, ls));
     323             : 
     324           0 :         req.bmRequestType = UMCT_SET_REQUEST;
     325           0 :         req.bRequest = REQ_SET_MCR;
     326           0 :         USETW(req.wValue, 0);
     327           0 :         USETW(req.wIndex, sc->sc_iface_number);
     328           0 :         USETW(req.wLength, LENGTH_SET_MCR);
     329             : 
     330           0 :         (void)usbd_do_request(sc->sc_udev, &req, &ls);
     331           0 : }
     332             : 
     333             : void
     334           0 : umct_set(void *addr, int portno, int reg, int onoff)
     335             : {
     336           0 :         struct umct_softc *sc = addr;
     337             : 
     338           0 :         switch (reg) {
     339             :         case UCOM_SET_DTR:
     340           0 :                 umct_dtr(sc, onoff);
     341           0 :                 break;
     342             :         case UCOM_SET_RTS:
     343           0 :                 umct_rts(sc, onoff);
     344           0 :                 break;
     345             :         case UCOM_SET_BREAK:
     346           0 :                 umct_break(sc, onoff);
     347           0 :                 break;
     348             :         default:
     349             :                 break;
     350             :         }
     351           0 : }
     352             : 
     353             : void
     354           0 : umct_dtr(struct umct_softc *sc, int onoff)
     355             : {
     356             : 
     357             :         DPRINTF(("umct_dtr: onoff=%d\n", onoff));
     358             : 
     359           0 :         if (sc->sc_dtr == onoff)
     360             :                 return;
     361           0 :         sc->sc_dtr = onoff;
     362             : 
     363           0 :         umct_set_line_state(sc);
     364           0 : }
     365             : 
     366             : void
     367           0 : umct_rts(struct umct_softc *sc, int onoff)
     368             : {
     369             :         DPRINTF(("umct_rts: onoff=%d\n", onoff));
     370             : 
     371           0 :         if (sc->sc_rts == onoff)
     372             :                 return;
     373           0 :         sc->sc_rts = onoff;
     374             : 
     375           0 :         umct_set_line_state(sc);
     376           0 : }
     377             : 
     378             : void
     379           0 : umct_break(struct umct_softc *sc, int onoff)
     380             : {
     381             :         DPRINTF(("umct_break: onoff=%d\n", onoff));
     382             : 
     383           0 :         umct_set_lcr(sc, onoff ? sc->last_lcr | LCR_SET_BREAK :
     384             :                      sc->last_lcr);
     385           0 : }
     386             : 
     387             : void
     388           0 : umct_set_lcr(struct umct_softc *sc, u_int data)
     389             : {
     390           0 :         usb_device_request_t req;
     391           0 :         uByte adata;
     392             : 
     393           0 :         adata = data;
     394           0 :         req.bmRequestType = UMCT_SET_REQUEST;
     395           0 :         req.bRequest = REQ_SET_LCR;
     396           0 :         USETW(req.wValue, 0);
     397           0 :         USETW(req.wIndex, sc->sc_iface_number);
     398           0 :         USETW(req.wLength, LENGTH_SET_LCR);
     399             : 
     400             :         /* XXX should check */
     401           0 :         (void)usbd_do_request(sc->sc_udev, &req, &adata);
     402           0 : }
     403             : 
     404             : void
     405           0 : umct_set_baudrate(struct umct_softc *sc, u_int rate, int cts)
     406             : {
     407           0 :         usb_device_request_t req;
     408           0 :         uDWord arate;
     409             :         u_int val;
     410             : 
     411           0 :         if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232 ||
     412           0 :             sc->sc_product == USB_PRODUCT_BELKIN_F5U109) {
     413           0 :                 switch (rate) {
     414           0 :                 case    300: val = 0x01; break;
     415           0 :                 case    600: val = 0x02; break;
     416           0 :                 case   1200: val = 0x03; break;
     417           0 :                 case   2400: val = 0x04; break;
     418           0 :                 case   4800: val = 0x06; break;
     419           0 :                 case   9600: val = 0x08; break;
     420           0 :                 case  19200: val = 0x09; break;
     421           0 :                 case  38400: val = 0x0a; break;
     422           0 :                 case  57600: val = 0x0b; break;
     423           0 :                 case 115200: val = 0x0c; break;
     424           0 :                 default:     val = -1; break;
     425             :                 }
     426             :         } else {
     427           0 :                 val = UMCT_BAUD_RATE(rate);
     428             :         }
     429           0 :         USETDW(arate, val);
     430             : 
     431           0 :         req.bmRequestType = UMCT_SET_REQUEST;
     432           0 :         req.bRequest = REQ_SET_BAUD_RATE;
     433           0 :         USETW(req.wValue, 0);
     434           0 :         USETW(req.wIndex, sc->sc_iface_number);
     435           0 :         USETW(req.wLength, LENGTH_BAUD_RATE);
     436             : 
     437             :         /* XXX should check */
     438           0 :         (void)usbd_do_request(sc->sc_udev, &req, arate);
     439             : 
     440             :         /* unknown request, required after setting baud rate */
     441           0 :         USETDW(arate, 0);
     442           0 :         req.bmRequestType = UMCT_SET_REQUEST;
     443           0 :         req.bRequest = REQ_UNKNOWN1;
     444           0 :         USETW(req.wValue, 0);
     445           0 :         USETW(req.wIndex, sc->sc_iface_number);
     446           0 :         USETW(req.wLength, LENGTH_UNKNOWN1);
     447           0 :         (void)usbd_do_request(sc->sc_udev, &req, arate);
     448             : 
     449             :         /* update CTS, also required after setting baud rate */
     450           0 :         USETDW(arate, cts);
     451           0 :         req.bmRequestType = UMCT_SET_REQUEST;
     452           0 :         req.bRequest = REQ_SET_CTS;
     453           0 :         USETW(req.wValue, 0);
     454           0 :         USETW(req.wIndex, sc->sc_iface_number);
     455           0 :         USETW(req.wLength, LENGTH_SET_CTS);
     456           0 :         (void)usbd_do_request(sc->sc_udev, &req, arate);
     457           0 : }
     458             : 
     459             : void
     460           0 : umct_init(struct umct_softc *sc)
     461             : {
     462           0 :         umct_set_baudrate(sc, 9600, 0);
     463           0 :         umct_set_lcr(sc, LCR_DATA_BITS_8 | LCR_PARITY_NONE | LCR_STOP_BITS_1);
     464           0 : }
     465             : 
     466             : int
     467           0 : umct_param(void *addr, int portno, struct termios *t)
     468             : {
     469           0 :         struct umct_softc *sc = addr;
     470             :         u_int data = 0;
     471             : 
     472             :         DPRINTF(("umct_param: sc=%p\n", sc));
     473             : 
     474             :         DPRINTF(("umct_param: BAUDRATE=%d\n", t->c_ospeed));
     475             : 
     476           0 :         if (ISSET(t->c_cflag, CSTOPB))
     477           0 :                 data |= LCR_STOP_BITS_2;
     478             :         else
     479             :                 data |= LCR_STOP_BITS_1;
     480           0 :         if (ISSET(t->c_cflag, PARENB)) {
     481           0 :                 if (ISSET(t->c_cflag, PARODD))
     482           0 :                         data |= LCR_PARITY_ODD;
     483             :                 else
     484           0 :                         data |= LCR_PARITY_EVEN;
     485             :         } else
     486             :                 data |= LCR_PARITY_NONE;
     487           0 :         switch (ISSET(t->c_cflag, CSIZE)) {
     488             :         case CS5:
     489             :                 data |= LCR_DATA_BITS_5;
     490           0 :                 break;
     491             :         case CS6:
     492           0 :                 data |= LCR_DATA_BITS_6;
     493           0 :                 break;
     494             :         case CS7:
     495           0 :                 data |= LCR_DATA_BITS_7;
     496           0 :                 break;
     497             :         case CS8:
     498           0 :                 data |= LCR_DATA_BITS_8;
     499           0 :                 break;
     500             :         }
     501             : 
     502           0 :         umct_set_baudrate(sc, t->c_ospeed, ISSET(t->c_cflag, CRTSCTS));
     503             : 
     504           0 :         sc->last_lcr = data;
     505           0 :         umct_set_lcr(sc, data);
     506             : 
     507           0 :         return (0);
     508             : }
     509             : 
     510             : int
     511           0 : umct_open(void *addr, int portno)
     512             : {
     513           0 :         struct umct_softc *sc = addr;
     514             :         int err, lcr_data;
     515             : 
     516           0 :         if (usbd_is_dying(sc->sc_udev))
     517           0 :                 return (EIO);
     518             : 
     519             :         DPRINTF(("umct_open: sc=%p\n", sc));
     520             : 
     521             :         /* initialize LCR */
     522             :         lcr_data = LCR_DATA_BITS_8 | LCR_PARITY_NONE |
     523             :             LCR_STOP_BITS_1;
     524           0 :         umct_set_lcr(sc, lcr_data);
     525             : 
     526           0 :         if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
     527           0 :                 sc->sc_status = 0; /* clear status bit */
     528           0 :                 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
     529           0 :                 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number,
     530             :                         USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc,
     531           0 :                         sc->sc_intr_buf, sc->sc_isize,
     532             :                         umct_intr, USBD_DEFAULT_INTERVAL);
     533           0 :                 if (err) {
     534             :                         DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n",
     535             :                                 sc->sc_dev.dv_xname, sc->sc_intr_number));
     536           0 :                                         return (EIO);
     537             :                 }
     538             :         }
     539             : 
     540           0 :         return (0);
     541           0 : }
     542             : 
     543             : void
     544           0 : umct_close(void *addr, int portno)
     545             : {
     546           0 :         struct umct_softc *sc = addr;
     547             :         int err;
     548             : 
     549           0 :         if (usbd_is_dying(sc->sc_udev))
     550           0 :                 return;
     551             : 
     552             :         DPRINTF(("umct_close: close\n"));
     553             : 
     554           0 :         if (sc->sc_intr_pipe != NULL) {
     555           0 :                 usbd_abort_pipe(sc->sc_intr_pipe);
     556           0 :                 err = usbd_close_pipe(sc->sc_intr_pipe);
     557           0 :                 if (err)
     558           0 :                         printf("%s: close interrupt pipe failed: %s\n",
     559           0 :                                 sc->sc_dev.dv_xname, usbd_errstr(err));
     560           0 :                 free(sc->sc_intr_buf, M_USBDEV, sc->sc_isize);
     561           0 :                 sc->sc_intr_pipe = NULL;
     562           0 :         }
     563           0 : }
     564             : 
     565             : void
     566           0 : umct_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
     567             : {
     568           0 :         struct umct_softc *sc = priv;
     569           0 :         u_char *buf = sc->sc_intr_buf;
     570             :         u_char mstatus;
     571             : 
     572           0 :         if (usbd_is_dying(sc->sc_udev))
     573           0 :                 return;
     574             : 
     575           0 :         if (status != USBD_NORMAL_COMPLETION) {
     576           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
     577           0 :                         return;
     578             : 
     579             :                 DPRINTF(("%s: abnormal status: %s\n", sc->sc_dev.dv_xname,
     580             :                         usbd_errstr(status)));
     581           0 :                 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
     582           0 :                 return;
     583             :         }
     584             : 
     585             :         DPRINTF(("%s: umct status = MSR:%02x, LSR:%02x\n",
     586             :                  sc->sc_dev.dv_xname, buf[0],buf[1]));
     587             : 
     588           0 :         sc->sc_lsr = sc->sc_msr = 0;
     589           0 :         mstatus = buf[0];
     590           0 :         if (ISSET(mstatus, MSR_DSR))
     591           0 :                 sc->sc_msr |= UMSR_DSR;
     592           0 :         if (ISSET(mstatus, MSR_DCD))
     593           0 :                 sc->sc_msr |= UMSR_DCD;
     594           0 :         ucom_status_change((struct ucom_softc *)sc->sc_subdev);
     595           0 : }
     596             : 
     597             : void
     598           0 : umct_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
     599             : {
     600           0 :         struct umct_softc *sc = addr;
     601             : 
     602             :         DPRINTF(("umct_get_status:\n"));
     603             : 
     604           0 :         if (lsr != NULL)
     605           0 :                 *lsr = sc->sc_lsr;
     606           0 :         if (msr != NULL)
     607           0 :                 *msr = sc->sc_msr;
     608           0 : }

Generated by: LCOV version 1.13