root/dev/usb/uvscom.c

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

DEFINITIONS

This source file includes following definitions.
  1. uvscom_match
  2. uvscom_attach
  3. uvscom_detach
  4. uvscom_activate
  5. uvscom_readstat
  6. uvscom_shutdown
  7. uvscom_reset
  8. uvscom_set_crtscts
  9. uvscom_set_line
  10. uvscom_set_line_coding
  11. uvscom_dtr
  12. uvscom_rts
  13. uvscom_break
  14. uvscom_set
  15. uvscom_param
  16. uvscom_open
  17. uvscom_close
  18. uvscom_intr
  19. uvscom_get_status

    1 /*      $OpenBSD: uvscom.c,v 1.18 2007/06/14 10:11:16 mbalmer 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/file.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/device.h>
   48 #include <sys/proc.h>
   49 #include <sys/vnode.h>
   50 #include <sys/poll.h>
   51 
   52 #include <dev/usb/usb.h>
   53 #include <dev/usb/usbcdc.h>
   54 
   55 #include <dev/usb/usbdi.h>
   56 #include <dev/usb/usbdi_util.h>
   57 #include <dev/usb/usbdevs.h>
   58 #include <dev/usb/usb_quirks.h>
   59 
   60 #include <dev/usb/ucomvar.h>
   61 
   62 #ifdef UVSCOM_DEBUG
   63 static int      uvscomdebug = 1;
   64 
   65 #define DPRINTFN(n, x)  do { if (uvscomdebug > (n)) printf x; } while (0)
   66 #else
   67 #define DPRINTFN(n, x)
   68 #endif
   69 #define DPRINTF(x) DPRINTFN(0, x)
   70 
   71 #define UVSCOM_CONFIG_INDEX     0
   72 #define UVSCOM_IFACE_INDEX      0
   73 
   74 #define UVSCOM_INTR_INTERVAL    100     /* mS */
   75 
   76 #define UVSCOM_UNIT_WAIT        5
   77 
   78 /* Request */
   79 #define UVSCOM_SET_SPEED        0x10
   80 #define UVSCOM_LINE_CTL         0x11
   81 #define UVSCOM_SET_PARAM        0x12
   82 #define UVSCOM_READ_STATUS      0xd0
   83 #define UVSCOM_SHUTDOWN         0xe0
   84 
   85 /* UVSCOM_SET_SPEED parameters */
   86 #define UVSCOM_SPEED_150BPS     0x00
   87 #define UVSCOM_SPEED_300BPS     0x01
   88 #define UVSCOM_SPEED_600BPS     0x02
   89 #define UVSCOM_SPEED_1200BPS    0x03
   90 #define UVSCOM_SPEED_2400BPS    0x04
   91 #define UVSCOM_SPEED_4800BPS    0x05
   92 #define UVSCOM_SPEED_9600BPS    0x06
   93 #define UVSCOM_SPEED_19200BPS   0x07
   94 #define UVSCOM_SPEED_38400BPS   0x08
   95 #define UVSCOM_SPEED_57600BPS   0x09
   96 #define UVSCOM_SPEED_115200BPS  0x0a
   97 
   98 /* UVSCOM_LINE_CTL parameters */
   99 #define UVSCOM_BREAK            0x40
  100 #define UVSCOM_RTS              0x02
  101 #define UVSCOM_DTR              0x01
  102 #define UVSCOM_LINE_INIT        0x08
  103 
  104 /* UVSCOM_SET_PARAM parameters */
  105 #define UVSCOM_DATA_MASK        0x03
  106 #define UVSCOM_DATA_BIT_8       0x03
  107 #define UVSCOM_DATA_BIT_7       0x02
  108 #define UVSCOM_DATA_BIT_6       0x01
  109 #define UVSCOM_DATA_BIT_5       0x00
  110 
  111 #define UVSCOM_STOP_MASK        0x04
  112 #define UVSCOM_STOP_BIT_2       0x04
  113 #define UVSCOM_STOP_BIT_1       0x00
  114 
  115 #define UVSCOM_PARITY_MASK      0x18
  116 #define UVSCOM_PARITY_EVEN      0x18
  117 #if 0
  118 #define UVSCOM_PARITY_UNK       0x10
  119 #endif
  120 #define UVSCOM_PARITY_ODD       0x08
  121 #define UVSCOM_PARITY_NONE      0x00
  122 
  123 /* Status bits */
  124 #define UVSCOM_TXRDY            0x04
  125 #define UVSCOM_RXRDY            0x01
  126 
  127 #define UVSCOM_DCD              0x08
  128 #define UVSCOM_NOCARD           0x04
  129 #define UVSCOM_DSR              0x02
  130 #define UVSCOM_CTS              0x01
  131 #define UVSCOM_USTAT_MASK       (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
  132 
  133 struct  uvscom_softc {
  134         struct device           sc_dev;         /* base device */
  135         usbd_device_handle      sc_udev;        /* USB device */
  136         usbd_interface_handle   sc_iface;       /* interface */
  137         int                     sc_iface_number;/* interface number */
  138 
  139         usbd_interface_handle   sc_intr_iface;  /* interrupt interface */
  140         int                     sc_intr_number; /* interrupt number */
  141         usbd_pipe_handle        sc_intr_pipe;   /* interrupt pipe */
  142         u_char                  *sc_intr_buf;   /* interrupt buffer */
  143         int                     sc_isize;
  144 
  145         u_char                  sc_dtr;         /* current DTR state */
  146         u_char                  sc_rts;         /* current RTS state */
  147 
  148         u_char                  sc_lsr;         /* Local status register */
  149         u_char                  sc_msr;         /* uvscom status register */
  150 
  151         uint16_t                sc_lcr;         /* Line control */
  152         u_char                  sc_usr;         /* unit status */
  153 
  154         struct device           *sc_subdev;     /* ucom device */
  155         u_char                  sc_dying;       /* disconnecting */
  156 };
  157 
  158 /*
  159  * These are the maximum number of bytes transferred per frame.
  160  * The output buffer size cannot be increased due to the size encoding.
  161  */
  162 #define UVSCOMIBUFSIZE 512
  163 #define UVSCOMOBUFSIZE 64
  164 
  165 usbd_status uvscom_readstat(struct uvscom_softc *);
  166 usbd_status uvscom_shutdown(struct uvscom_softc *);
  167 usbd_status uvscom_reset(struct uvscom_softc *);
  168 usbd_status uvscom_set_line_coding(struct uvscom_softc *,
  169                                            uint16_t, uint16_t);
  170 usbd_status uvscom_set_line(struct uvscom_softc *, uint16_t);
  171 usbd_status uvscom_set_crtscts(struct uvscom_softc *);
  172 void uvscom_get_status(void *, int, u_char *, u_char *);
  173 void uvscom_dtr(struct uvscom_softc *, int);
  174 void uvscom_rts(struct uvscom_softc *, int);
  175 void uvscom_break(struct uvscom_softc *, int);
  176 
  177 void uvscom_set(void *, int, int, int);
  178 void uvscom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
  179 int  uvscom_param(void *, int, struct termios *);
  180 int  uvscom_open(void *, int);
  181 void uvscom_close(void *, int);
  182 
  183 struct ucom_methods uvscom_methods = {
  184         uvscom_get_status,
  185         uvscom_set,
  186         uvscom_param,
  187         NULL, /* uvscom_ioctl, TODO */
  188         uvscom_open,
  189         uvscom_close,
  190         NULL,
  191         NULL
  192 };
  193 
  194 static const struct usb_devno uvscom_devs [] = {
  195         /* SUNTAC U-Cable type A3 */
  196         { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS64LX },
  197         /* SUNTAC U-Cable type A4 */
  198         { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 },
  199         /* SUNTAC U-Cable type D2 */
  200         { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L },
  201         /* SUNTAC U-Cable type P1 */
  202         { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 },
  203         /* SUNTAC Slipper U  */
  204         { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U },
  205         /* SUNTAC Ir-Trinity */
  206         { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U },
  207 };
  208 #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
  209 
  210 int uvscom_match(struct device *, void *, void *); 
  211 void uvscom_attach(struct device *, struct device *, void *); 
  212 int uvscom_detach(struct device *, int); 
  213 int uvscom_activate(struct device *, enum devact); 
  214 
  215 struct cfdriver uvscom_cd = { 
  216         NULL, "uvscom", DV_DULL 
  217 }; 
  218 
  219 const struct cfattach uvscom_ca = { 
  220         sizeof(struct uvscom_softc), 
  221         uvscom_match, 
  222         uvscom_attach, 
  223         uvscom_detach, 
  224         uvscom_activate, 
  225 };
  226 
  227 int
  228 uvscom_match(struct device *parent, void *match, void *aux)
  229 {
  230         struct usb_attach_arg *uaa = aux;
  231 
  232         if (uaa->iface != NULL)
  233                 return (UMATCH_NONE);
  234 
  235         return (uvscom_lookup(uaa->vendor, uaa->product) != NULL ?
  236                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  237 }
  238 
  239 void
  240 uvscom_attach(struct device *parent, struct device *self, void *aux)
  241 {
  242         struct uvscom_softc *sc = (struct uvscom_softc *)self;
  243         struct usb_attach_arg *uaa = aux;
  244         usbd_device_handle dev = uaa->device;
  245         usb_config_descriptor_t *cdesc;
  246         usb_interface_descriptor_t *id;
  247         usb_endpoint_descriptor_t *ed;
  248         char *devinfop;
  249         const char *devname = sc->sc_dev.dv_xname;
  250         usbd_status err;
  251         int i;
  252         struct ucom_attach_args uca;
  253 
  254         devinfop = usbd_devinfo_alloc(dev, 0);
  255         printf("\n%s: %s\n", devname, devinfop);
  256         usbd_devinfo_free(devinfop);
  257 
  258         sc->sc_udev = dev;
  259 
  260         DPRINTF(("uvscom attach: sc = %p\n", sc));
  261 
  262         /* initialize endpoints */
  263         uca.bulkin = uca.bulkout = -1;
  264         sc->sc_intr_number = -1;
  265         sc->sc_intr_pipe = NULL;
  266 
  267         /* Move the device into the configured state. */
  268         err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1);
  269         if (err) {
  270                 printf("%s: failed to set configuration, err=%s\n",
  271                         devname, usbd_errstr(err));
  272                 sc->sc_dying = 1;
  273                 return;
  274         }
  275 
  276         /* get the config descriptor */
  277         cdesc = usbd_get_config_descriptor(sc->sc_udev);
  278 
  279         if (cdesc == NULL) {
  280                 printf("%s: failed to get configuration descriptor\n",
  281                         sc->sc_dev.dv_xname);
  282                 sc->sc_dying = 1;
  283                 return;
  284         }
  285 
  286         /* get the common interface */
  287         err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX,
  288                                            &sc->sc_iface);
  289         if (err) {
  290                 printf("%s: failed to get interface, err=%s\n",
  291                         devname, usbd_errstr(err));
  292                 sc->sc_dying = 1;
  293                 return;
  294         }
  295 
  296         id = usbd_get_interface_descriptor(sc->sc_iface);
  297         sc->sc_iface_number = id->bInterfaceNumber;
  298 
  299         /* Find endpoints */
  300         for (i = 0; i < id->bNumEndpoints; i++) {
  301                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  302                 if (ed == NULL) {
  303                         printf("%s: no endpoint descriptor for %d\n",
  304                                 sc->sc_dev.dv_xname, i);
  305                         sc->sc_dying = 1;
  306                         return;
  307                 }
  308 
  309                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  310                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  311                         uca.bulkin = ed->bEndpointAddress;
  312                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  313                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  314                         uca.bulkout = ed->bEndpointAddress;
  315                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  316                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  317                         sc->sc_intr_number = ed->bEndpointAddress;
  318                         sc->sc_isize = UGETW(ed->wMaxPacketSize);
  319                 }
  320         }
  321 
  322         if (uca.bulkin == -1) {
  323                 printf("%s: Could not find data bulk in\n",
  324                         sc->sc_dev.dv_xname);
  325                 sc->sc_dying = 1;
  326                 return;
  327         }
  328         if (uca.bulkout == -1) {
  329                 printf("%s: Could not find data bulk out\n",
  330                         sc->sc_dev.dv_xname);
  331                 sc->sc_dying = 1;
  332                 return;
  333         }
  334         if (sc->sc_intr_number == -1) {
  335                 printf("%s: Could not find interrupt in\n",
  336                         sc->sc_dev.dv_xname);
  337                 sc->sc_dying = 1;
  338                 return;
  339         }
  340 
  341         sc->sc_dtr = sc->sc_rts = 0;
  342         sc->sc_lcr = UVSCOM_LINE_INIT;
  343 
  344         uca.portno = UCOM_UNK_PORTNO;
  345         /* bulkin, bulkout set above */
  346         uca.ibufsize = UVSCOMIBUFSIZE;
  347         uca.obufsize = UVSCOMOBUFSIZE;
  348         uca.ibufsizepad = UVSCOMIBUFSIZE;
  349         uca.opkthdrlen = 0;
  350         uca.device = dev;
  351         uca.iface = sc->sc_iface;
  352         uca.methods = &uvscom_methods;
  353         uca.arg = sc;
  354         uca.info = NULL;
  355 
  356         err = uvscom_reset(sc);
  357 
  358         if (err) {
  359                 printf("%s: reset failed, %s\n", sc->sc_dev.dv_xname,
  360                         usbd_errstr(err));
  361                 sc->sc_dying = 1;
  362                 return;
  363         }
  364 
  365         DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
  366                  ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number));
  367 
  368         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  369                            &sc->sc_dev);
  370 
  371         DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
  372                         uca.bulkin, uca.bulkout, sc->sc_intr_number ));
  373         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
  374 }
  375 
  376 int
  377 uvscom_detach(struct device *self, int flags)
  378 {
  379         struct uvscom_softc *sc = (struct uvscom_softc *)self;
  380         int rv = 0;
  381 
  382         DPRINTF(("uvscom_detach: sc = %p\n", sc));
  383 
  384         sc->sc_dying = 1;
  385 
  386         if (sc->sc_intr_pipe != NULL) {
  387                 usbd_abort_pipe(sc->sc_intr_pipe);
  388                 usbd_close_pipe(sc->sc_intr_pipe);
  389                 free(sc->sc_intr_buf, M_USBDEV);
  390                 sc->sc_intr_pipe = NULL;
  391         }
  392 
  393         sc->sc_dying = 1;
  394         if (sc->sc_subdev != NULL) {
  395                 rv = config_detach(sc->sc_subdev, flags);
  396                 sc->sc_subdev = NULL;
  397         }
  398 
  399         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  400                            &sc->sc_dev);
  401 
  402         return (rv);
  403 }
  404 
  405 int
  406 uvscom_activate(struct device *self, enum devact act)
  407 {
  408         struct uvscom_softc *sc = (struct uvscom_softc *)self;
  409         int rv = 0;
  410 
  411         switch (act) {
  412         case DVACT_ACTIVATE:
  413                 break;
  414 
  415         case DVACT_DEACTIVATE:
  416                 if (sc->sc_subdev != NULL)
  417                         rv = config_deactivate(sc->sc_subdev);
  418                 sc->sc_dying = 1;
  419                 break;
  420         }
  421         return (rv);
  422 }
  423 
  424 usbd_status
  425 uvscom_readstat(struct uvscom_softc *sc)
  426 {
  427         usb_device_request_t req;
  428         usbd_status err;
  429         uint16_t r;
  430 
  431         DPRINTF(("%s: send readstat\n", sc->sc_dev.dv_xname));
  432 
  433         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  434         req.bRequest = UVSCOM_READ_STATUS;
  435         USETW(req.wValue, 0);
  436         USETW(req.wIndex, 0);
  437         USETW(req.wLength, 2);
  438 
  439         err = usbd_do_request(sc->sc_udev, &req, &r);
  440         if (err) {
  441                 printf("%s: uvscom_readstat: %s\n",
  442                        sc->sc_dev.dv_xname, usbd_errstr(err));
  443                 return (err);
  444         }
  445 
  446         DPRINTF(("%s: uvscom_readstat: r = %d\n",
  447                  sc->sc_dev.dv_xname, r));
  448 
  449         return (USBD_NORMAL_COMPLETION);
  450 }
  451 
  452 usbd_status
  453 uvscom_shutdown(struct uvscom_softc *sc)
  454 {
  455         usb_device_request_t req;
  456         usbd_status err;
  457 
  458         DPRINTF(("%s: send shutdown\n", sc->sc_dev.dv_xname));
  459 
  460         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  461         req.bRequest = UVSCOM_SHUTDOWN;
  462         USETW(req.wValue, 0);
  463         USETW(req.wIndex, 0);
  464         USETW(req.wLength, 0);
  465 
  466         err = usbd_do_request(sc->sc_udev, &req, NULL);
  467         if (err) {
  468                 printf("%s: uvscom_shutdown: %s\n",
  469                        sc->sc_dev.dv_xname, usbd_errstr(err));
  470                 return (err);
  471         }
  472 
  473         return (USBD_NORMAL_COMPLETION);
  474 }
  475 
  476 usbd_status
  477 uvscom_reset(struct uvscom_softc *sc)
  478 {
  479         DPRINTF(("%s: uvscom_reset\n", sc->sc_dev.dv_xname));
  480 
  481         return (USBD_NORMAL_COMPLETION);
  482 }
  483 
  484 usbd_status
  485 uvscom_set_crtscts(struct uvscom_softc *sc)
  486 {
  487         DPRINTF(("%s: uvscom_set_crtscts\n", sc->sc_dev.dv_xname));
  488 
  489         return (USBD_NORMAL_COMPLETION);
  490 }
  491 
  492 usbd_status
  493 uvscom_set_line(struct uvscom_softc *sc, uint16_t line)
  494 {
  495         usb_device_request_t req;
  496         usbd_status err;
  497 
  498         DPRINTF(("%s: uvscom_set_line: %04x\n",
  499                  sc->sc_dev.dv_xname, line));
  500 
  501         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  502         req.bRequest = UVSCOM_LINE_CTL;
  503         USETW(req.wValue, line);
  504         USETW(req.wIndex, 0);
  505         USETW(req.wLength, 0);
  506 
  507         err = usbd_do_request(sc->sc_udev, &req, NULL);
  508         if (err) {
  509                 printf("%s: uvscom_set_line: %s\n",
  510                        sc->sc_dev.dv_xname, usbd_errstr(err));
  511                 return (err);
  512         }
  513 
  514         return (USBD_NORMAL_COMPLETION);
  515 }
  516 
  517 usbd_status
  518 uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls)
  519 {
  520         usb_device_request_t req;
  521         usbd_status err;
  522 
  523         DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
  524                  sc->sc_dev.dv_xname, lsp, ls));
  525 
  526         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  527         req.bRequest = UVSCOM_SET_SPEED;
  528         USETW(req.wValue, lsp);
  529         USETW(req.wIndex, 0);
  530         USETW(req.wLength, 0);
  531 
  532         err = usbd_do_request(sc->sc_udev, &req, NULL);
  533         if (err) {
  534                 printf("%s: uvscom_set_line_coding: %s\n",
  535                        sc->sc_dev.dv_xname, usbd_errstr(err));
  536                 return (err);
  537         }
  538 
  539         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  540         req.bRequest = UVSCOM_SET_PARAM;
  541         USETW(req.wValue, ls);
  542         USETW(req.wIndex, 0);
  543         USETW(req.wLength, 0);
  544 
  545         err = usbd_do_request(sc->sc_udev, &req, NULL);
  546         if (err) {
  547                 printf("%s: uvscom_set_line_coding: %s\n",
  548                        sc->sc_dev.dv_xname, usbd_errstr(err));
  549                 return (err);
  550         }
  551 
  552         return (USBD_NORMAL_COMPLETION);
  553 }
  554 
  555 void
  556 uvscom_dtr(struct uvscom_softc *sc, int onoff)
  557 {
  558         DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
  559                  sc->sc_dev.dv_xname, onoff));
  560 
  561         if (sc->sc_dtr == onoff)
  562                 return;                 /* no change */
  563 
  564         sc->sc_dtr = onoff;
  565 
  566         if (onoff)
  567                 SET(sc->sc_lcr, UVSCOM_DTR);
  568         else
  569                 CLR(sc->sc_lcr, UVSCOM_DTR);
  570 
  571         uvscom_set_line(sc, sc->sc_lcr);
  572 }
  573 
  574 void
  575 uvscom_rts(struct uvscom_softc *sc, int onoff)
  576 {
  577         DPRINTF(("%s: uvscom_rts: onoff = %d\n",
  578                  sc->sc_dev.dv_xname, onoff));
  579 
  580         if (sc->sc_rts == onoff)
  581                 return;                 /* no change */
  582 
  583         sc->sc_rts = onoff;
  584 
  585         if (onoff)
  586                 SET(sc->sc_lcr, UVSCOM_RTS);
  587         else
  588                 CLR(sc->sc_lcr, UVSCOM_RTS);
  589 
  590         uvscom_set_line(sc, sc->sc_lcr);
  591 }
  592 
  593 void
  594 uvscom_break(struct uvscom_softc *sc, int onoff)
  595 {
  596         DPRINTF(("%s: uvscom_break: onoff = %d\n",
  597                  sc->sc_dev.dv_xname, onoff));
  598 
  599         if (onoff)
  600                 uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK));
  601 }
  602 
  603 void
  604 uvscom_set(void *addr, int portno, int reg, int onoff)
  605 {
  606         struct uvscom_softc *sc = addr;
  607 
  608         switch (reg) {
  609         case UCOM_SET_DTR:
  610                 uvscom_dtr(sc, onoff);
  611                 break;
  612         case UCOM_SET_RTS:
  613                 uvscom_rts(sc, onoff);
  614                 break;
  615         case UCOM_SET_BREAK:
  616                 uvscom_break(sc, onoff);
  617                 break;
  618         default:
  619                 break;
  620         }
  621 }
  622 
  623 int
  624 uvscom_param(void *addr, int portno, struct termios *t)
  625 {
  626         struct uvscom_softc *sc = addr;
  627         usbd_status err;
  628         uint16_t lsp;
  629         uint16_t ls;
  630 
  631         DPRINTF(("%s: uvscom_param: sc = %p\n",
  632                  sc->sc_dev.dv_xname, sc));
  633 
  634         ls = 0;
  635 
  636         switch (t->c_ospeed) {
  637         case B150:
  638                 lsp = UVSCOM_SPEED_150BPS;
  639                 break;
  640         case B300:
  641                 lsp = UVSCOM_SPEED_300BPS;
  642                 break;
  643         case B600:
  644                 lsp = UVSCOM_SPEED_600BPS;
  645                 break;
  646         case B1200:
  647                 lsp = UVSCOM_SPEED_1200BPS;
  648                 break;
  649         case B2400:
  650                 lsp = UVSCOM_SPEED_2400BPS;
  651                 break;
  652         case B4800:
  653                 lsp = UVSCOM_SPEED_4800BPS;
  654                 break;
  655         case B9600:
  656                 lsp = UVSCOM_SPEED_9600BPS;
  657                 break;
  658         case B19200:
  659                 lsp = UVSCOM_SPEED_19200BPS;
  660                 break;
  661         case B38400:
  662                 lsp = UVSCOM_SPEED_38400BPS;
  663                 break;
  664         case B57600:
  665                 lsp = UVSCOM_SPEED_57600BPS;
  666                 break;
  667         case B115200:
  668                 lsp = UVSCOM_SPEED_115200BPS;
  669                 break;
  670         default:
  671                 return (EIO);
  672         }
  673 
  674         if (ISSET(t->c_cflag, CSTOPB))
  675                 SET(ls, UVSCOM_STOP_BIT_2);
  676         else
  677                 SET(ls, UVSCOM_STOP_BIT_1);
  678 
  679         if (ISSET(t->c_cflag, PARENB)) {
  680                 if (ISSET(t->c_cflag, PARODD))
  681                         SET(ls, UVSCOM_PARITY_ODD);
  682                 else
  683                         SET(ls, UVSCOM_PARITY_EVEN);
  684         } else
  685                 SET(ls, UVSCOM_PARITY_NONE);
  686 
  687         switch (ISSET(t->c_cflag, CSIZE)) {
  688         case CS5:
  689                 SET(ls, UVSCOM_DATA_BIT_5);
  690                 break;
  691         case CS6:
  692                 SET(ls, UVSCOM_DATA_BIT_6);
  693                 break;
  694         case CS7:
  695                 SET(ls, UVSCOM_DATA_BIT_7);
  696                 break;
  697         case CS8:
  698                 SET(ls, UVSCOM_DATA_BIT_8);
  699                 break;
  700         default:
  701                 return (EIO);
  702         }
  703 
  704         err = uvscom_set_line_coding(sc, lsp, ls);
  705         if (err)
  706                 return (EIO);
  707 
  708         if (ISSET(t->c_cflag, CRTSCTS)) {
  709                 err = uvscom_set_crtscts(sc);
  710                 if (err)
  711                         return (EIO);
  712         }
  713 
  714         return (0);
  715 }
  716 
  717 int
  718 uvscom_open(void *addr, int portno)
  719 {
  720         struct uvscom_softc *sc = addr;
  721         int err;
  722         int i;
  723 
  724         if (sc->sc_dying)
  725                 return (EIO);
  726 
  727         DPRINTF(("uvscom_open: sc = %p\n", sc));
  728 
  729         if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
  730                 DPRINTF(("uvscom_open: open interrupt pipe.\n"));
  731 
  732                 sc->sc_usr = 0;         /* clear unit status */
  733 
  734                 err = uvscom_readstat(sc);
  735                 if (err) {
  736                         DPRINTF(("%s: uvscom_open: readstat faild\n",
  737                                  sc->sc_dev.dv_xname));
  738                         return (EIO);
  739                 }
  740 
  741                 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
  742                 err = usbd_open_pipe_intr(sc->sc_iface,
  743                                           sc->sc_intr_number,
  744                                           USBD_SHORT_XFER_OK,
  745                                           &sc->sc_intr_pipe,
  746                                           sc,
  747                                           sc->sc_intr_buf,
  748                                           sc->sc_isize,
  749                                           uvscom_intr,
  750                                           UVSCOM_INTR_INTERVAL);
  751                 if (err) {
  752                         printf("%s: cannot open interrupt pipe (addr %d)\n",
  753                                  sc->sc_dev.dv_xname,
  754                                  sc->sc_intr_number);
  755                         return (EIO);
  756                 }
  757         } else {
  758                 DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
  759         }
  760 
  761         if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) {
  762                 /* unit is not ready */
  763 
  764                 for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
  765                         tsleep(&err, TTIPRI, "uvsop", hz);      /* XXX */
  766                         if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK))
  767                                 break;
  768                 }
  769                 if (i == 0) {
  770                         DPRINTF(("%s: unit is not ready\n",
  771                                  sc->sc_dev.dv_xname));
  772                         return (EIO);
  773                 }
  774 
  775                 /* check PC card was inserted */
  776                 if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) {
  777                         DPRINTF(("%s: no card\n",
  778                                  sc->sc_dev.dv_xname));
  779                         return (EIO);
  780                 }
  781         }
  782 
  783         return (0);
  784 }
  785 
  786 void
  787 uvscom_close(void *addr, int portno)
  788 {
  789         struct uvscom_softc *sc = addr;
  790         int err;
  791 
  792         if (sc->sc_dying)
  793                 return;
  794 
  795         DPRINTF(("uvscom_close: close\n"));
  796 
  797         uvscom_shutdown(sc);
  798 
  799         if (sc->sc_intr_pipe != NULL) {
  800                 err = usbd_abort_pipe(sc->sc_intr_pipe);
  801                 if (err)
  802                         printf("%s: abort interrupt pipe failed: %s\n",
  803                                 sc->sc_dev.dv_xname,
  804                                            usbd_errstr(err));
  805                 err = usbd_close_pipe(sc->sc_intr_pipe);
  806                 if (err)
  807                         printf("%s: close interrupt pipe failed: %s\n",
  808                                 sc->sc_dev.dv_xname,
  809                                            usbd_errstr(err));
  810                 free(sc->sc_intr_buf, M_USBDEV);
  811                 sc->sc_intr_pipe = NULL;
  812         }
  813 }
  814 
  815 void
  816 uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  817 {
  818         struct uvscom_softc *sc = priv;
  819         u_char *buf = sc->sc_intr_buf;
  820         u_char pstatus;
  821 
  822         if (sc->sc_dying)
  823                 return;
  824 
  825         if (status != USBD_NORMAL_COMPLETION) {
  826                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  827                         return;
  828 
  829                 printf("%s: uvscom_intr: abnormal status: %s\n",
  830                         sc->sc_dev.dv_xname,
  831                         usbd_errstr(status));
  832                 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
  833                 return;
  834         }
  835 
  836         DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
  837                  sc->sc_dev.dv_xname, buf[0], buf[1]));
  838 
  839         sc->sc_lsr = sc->sc_msr = 0;
  840         sc->sc_usr = buf[1];
  841 
  842         pstatus = buf[0];
  843         if (ISSET(pstatus, UVSCOM_TXRDY))
  844                 SET(sc->sc_lsr, ULSR_TXRDY);
  845         if (ISSET(pstatus, UVSCOM_RXRDY))
  846                 SET(sc->sc_lsr, ULSR_RXRDY);
  847 
  848         pstatus = buf[1];
  849         if (ISSET(pstatus, UVSCOM_CTS))
  850                 SET(sc->sc_msr, UMSR_CTS);
  851         if (ISSET(pstatus, UVSCOM_DSR))
  852                 SET(sc->sc_msr, UMSR_DSR);
  853         if (ISSET(pstatus, UVSCOM_DCD))
  854                 SET(sc->sc_msr, UMSR_DCD);
  855 
  856         ucom_status_change((struct ucom_softc *) sc->sc_subdev);
  857 }
  858 
  859 void
  860 uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  861 {
  862         struct uvscom_softc *sc = addr;
  863 
  864         if (lsr != NULL)
  865                 *lsr = sc->sc_lsr;
  866         if (msr != NULL)
  867                 *msr = sc->sc_msr;
  868 }

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