The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/umct.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: fe16210147dac9d40c0a87b974e1e398


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.