root/dev/usb/umct.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. umct_match
  2. umct_attach
  3. umct_detach
  4. umct_activate
  5. umct_set_line_state
  6. umct_set
  7. umct_dtr
  8. umct_rts
  9. umct_break
  10. umct_set_lcr
  11. umct_set_baudrate
  12. umct_init
  13. umct_param
  14. umct_open
  15. umct_close
  16. umct_intr
  17. umct_get_status

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

/* [<][>][^][v][top][bottom][index][help] */