root/dev/usb/ubsa.c

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

DEFINITIONS

This source file includes following definitions.
  1. ubsa_match
  2. ubsa_attach
  3. ubsa_detach
  4. ubsa_activate
  5. ubsa_request
  6. ubsa_dtr
  7. ubsa_rts
  8. ubsa_break
  9. ubsa_set
  10. ubsa_baudrate
  11. ubsa_parity
  12. ubsa_databits
  13. ubsa_stopbits
  14. ubsa_flow
  15. ubsa_param
  16. ubsa_open
  17. ubsa_close
  18. ubsa_intr
  19. ubsa_get_status

    1 /*      $OpenBSD: ubsa.c,v 1.30 2007/06/14 10:11:15 mbalmer Exp $       */
    2 /*      $NetBSD: ubsa.c,v 1.5 2002/11/25 00:51:33 fvdl Exp $    */
    3 /*-
    4  * Copyright (c) 2002, Alexander Kabaev <kan.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 /*
   29  * Copyright (c) 2001 The NetBSD Foundation, Inc.
   30  * All rights reserved.
   31  *
   32  * This code is derived from software contributed to The NetBSD Foundation
   33  * by Ichiro FUKUHARA (ichiro@ichiro.org).
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgement:
   45  *        This product includes software developed by the NetBSD
   46  *        Foundation, Inc. and its contributors.
   47  * 4. Neither the name of The NetBSD Foundation nor the names of its
   48  *    contributors may be used to endorse or promote products derived
   49  *    from this software without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   52  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   53  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   54  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   55  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   56  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   57  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   58  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   59  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   60  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   61  * POSSIBILITY OF SUCH DAMAGE.
   62  */
   63 
   64 #include <sys/cdefs.h>
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 #include <sys/kernel.h>
   69 #include <sys/malloc.h>
   70 #include <sys/device.h>
   71 #include <sys/ioccom.h>
   72 #include <sys/fcntl.h>
   73 #include <sys/conf.h>
   74 #include <sys/tty.h>
   75 #include <sys/file.h>
   76 #include <sys/selinfo.h>
   77 #include <sys/proc.h>
   78 #include <sys/vnode.h>
   79 #include <sys/poll.h>
   80 #include <sys/sysctl.h>
   81 
   82 #include <dev/usb/usb.h>
   83 #include <dev/usb/usbcdc.h>
   84 
   85 #include <dev/usb/usbdi.h>
   86 #include <dev/usb/usbdi_util.h>
   87 #include <dev/usb/usbdevs.h>
   88 #include <dev/usb/usb_quirks.h>
   89 
   90 #include <dev/usb/ucomvar.h>
   91 
   92 #ifdef USB_DEBUG
   93 #define UBSA_DEBUG
   94 #endif
   95 
   96 #ifdef UBSA_DEBUG
   97 int     ubsadebug = 0;
   98 
   99 #define DPRINTFN(n, x)  do { if (ubsadebug > (n)) printf x; } while (0)
  100 #else
  101 #define DPRINTFN(n, x)
  102 #endif
  103 #define DPRINTF(x) DPRINTFN(0, x)
  104 
  105 #define UBSA_MODVER             1       /* module version */
  106 
  107 #define UBSA_CONFIG_INDEX       1
  108 #define UBSA_IFACE_INDEX        0
  109 
  110 #define UBSA_INTR_INTERVAL      100     /* ms */
  111 
  112 #define UBSA_SET_BAUDRATE       0x00
  113 #define UBSA_SET_STOP_BITS      0x01
  114 #define UBSA_SET_DATA_BITS      0x02
  115 #define UBSA_SET_PARITY         0x03
  116 #define UBSA_SET_DTR            0x0A
  117 #define UBSA_SET_RTS            0x0B
  118 #define UBSA_SET_BREAK          0x0C
  119 #define UBSA_SET_FLOW_CTRL      0x10
  120 
  121 #define UBSA_PARITY_NONE        0x00
  122 #define UBSA_PARITY_EVEN        0x01
  123 #define UBSA_PARITY_ODD         0x02
  124 #define UBSA_PARITY_MARK        0x03
  125 #define UBSA_PARITY_SPACE       0x04
  126 
  127 #define UBSA_FLOW_NONE          0x0000
  128 #define UBSA_FLOW_OCTS          0x0001
  129 #define UBSA_FLOW_ODSR          0x0002
  130 #define UBSA_FLOW_IDSR          0x0004
  131 #define UBSA_FLOW_IDTR          0x0008
  132 #define UBSA_FLOW_IRTS          0x0010
  133 #define UBSA_FLOW_ORTS          0x0020
  134 #define UBSA_FLOW_UNKNOWN       0x0040
  135 #define UBSA_FLOW_OXON          0x0080
  136 #define UBSA_FLOW_IXON          0x0100
  137 
  138 /* line status register */
  139 #define UBSA_LSR_TSRE           0x40    /* Transmitter empty: byte sent */
  140 #define UBSA_LSR_TXRDY          0x20    /* Transmitter buffer empty */
  141 #define UBSA_LSR_BI             0x10    /* Break detected */
  142 #define UBSA_LSR_FE             0x08    /* Framing error: bad stop bit */
  143 #define UBSA_LSR_PE             0x04    /* Parity error */
  144 #define UBSA_LSR_OE             0x02    /* Overrun, lost incoming byte */
  145 #define UBSA_LSR_RXRDY          0x01    /* Byte ready in Receive Buffer */
  146 #define UBSA_LSR_RCV_MASK       0x1f    /* Mask for incoming data or error */
  147 
  148 /* modem status register */
  149 /* All deltas are from the last read of the MSR. */
  150 #define UBSA_MSR_DCD            0x80    /* Current Data Carrier Detect */
  151 #define UBSA_MSR_RI             0x40    /* Current Ring Indicator */
  152 #define UBSA_MSR_DSR            0x20    /* Current Data Set Ready */
  153 #define UBSA_MSR_CTS            0x10    /* Current Clear to Send */
  154 #define UBSA_MSR_DDCD           0x08    /* DCD has changed state */
  155 #define UBSA_MSR_TERI           0x04    /* RI has toggled low to high */
  156 #define UBSA_MSR_DDSR           0x02    /* DSR has changed state */
  157 #define UBSA_MSR_DCTS           0x01    /* CTS has changed state */
  158 
  159 struct  ubsa_softc {
  160         struct device            sc_dev;        /* base device */
  161         usbd_device_handle       sc_udev;       /* USB device */
  162         usbd_interface_handle    sc_iface;      /* interface */
  163 
  164         int                      sc_iface_number;       /* interface number */
  165 
  166         int                      sc_intr_number;        /* interrupt number */
  167         usbd_pipe_handle         sc_intr_pipe;  /* interrupt pipe */
  168         u_char                  *sc_intr_buf;   /* interrupt buffer */
  169         int                      sc_isize;
  170 
  171         u_char                   sc_dtr;        /* current DTR state */
  172         u_char                   sc_rts;        /* current RTS state */
  173 
  174         u_char                   sc_lsr;        /* Local status register */
  175         u_char                   sc_msr;        /* ubsa status register */
  176 
  177         struct device           *sc_subdev;     /* ucom device */
  178 
  179         u_char                   sc_dying;      /* disconnecting */
  180 
  181 };
  182 
  183 void ubsa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
  184 
  185 void ubsa_get_status(void *, int, u_char *, u_char *);
  186 void ubsa_set(void *, int, int, int);
  187 int  ubsa_param(void *, int, struct termios *);
  188 int  ubsa_open(void *, int);
  189 void ubsa_close(void *, int);
  190 
  191 void ubsa_break(struct ubsa_softc *sc, int onoff);
  192 int  ubsa_request(struct ubsa_softc *, u_int8_t, u_int16_t);
  193 void ubsa_dtr(struct ubsa_softc *, int);
  194 void ubsa_rts(struct ubsa_softc *, int);
  195 void ubsa_baudrate(struct ubsa_softc *, speed_t);
  196 void ubsa_parity(struct ubsa_softc *, tcflag_t);
  197 void ubsa_databits(struct ubsa_softc *, tcflag_t);
  198 void ubsa_stopbits(struct ubsa_softc *, tcflag_t);
  199 void ubsa_flow(struct ubsa_softc *, tcflag_t, tcflag_t);
  200 
  201 struct  ucom_methods ubsa_methods = {
  202         ubsa_get_status,
  203         ubsa_set,
  204         ubsa_param,
  205         NULL,
  206         ubsa_open,
  207         ubsa_close,
  208         NULL,
  209         NULL
  210 };
  211 
  212 const struct usb_devno ubsa_devs[] = {
  213         /* AnyDATA ADU-E100H */
  214         { USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_E100H },
  215         /* BELKIN F5U103 */
  216         { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U103 },
  217         /* BELKIN F5U120 */
  218         { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U120 },
  219         /* GoHubs GO-COM232 , Belkin F5U003 */
  220         { USB_VENDOR_ETEK, USB_PRODUCT_ETEK_1COM },
  221         /* GoHubs GO-COM232 */
  222         { USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232 },
  223         /* HUAWEI Mobile */
  224         { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E618 },
  225         /* Novatel Wireless U740 */
  226         { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINU740 },
  227         /* Option Vodafone Mobile Connect 3G */
  228         { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G },
  229         /* Option GlobeTrotter 3G FUSION */
  230         { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GFUSION },
  231         /* Option GlobeTrotter 3G QUAD */
  232         { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD },
  233         /* Option GlobeTrotter 3G QUAD PLUS */
  234         { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUADPLUS },
  235         /* Peracom */
  236         { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1 },
  237 };
  238 #define ubsa_lookup(v, p) usb_lookup(ubsa_devs, v, p)
  239 
  240 int ubsa_match(struct device *, void *, void *); 
  241 void ubsa_attach(struct device *, struct device *, void *); 
  242 int ubsa_detach(struct device *, int); 
  243 int ubsa_activate(struct device *, enum devact); 
  244 
  245 struct cfdriver ubsa_cd = { 
  246         NULL, "ubsa", DV_DULL 
  247 }; 
  248 
  249 const struct cfattach ubsa_ca = { 
  250         sizeof(struct ubsa_softc), 
  251         ubsa_match, 
  252         ubsa_attach, 
  253         ubsa_detach, 
  254         ubsa_activate, 
  255 };
  256 
  257 int
  258 ubsa_match(struct device *parent, void *match, void *aux)
  259 {
  260         struct usb_attach_arg *uaa = aux;
  261 
  262         if (uaa->iface != NULL)
  263                 return (UMATCH_NONE);
  264 
  265         return (ubsa_lookup(uaa->vendor, uaa->product) != NULL ?
  266                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  267 }
  268 
  269 void
  270 ubsa_attach(struct device *parent, struct device *self, void *aux)
  271 {
  272         struct ubsa_softc *sc = (struct ubsa_softc *)self;
  273         struct usb_attach_arg *uaa = aux;
  274         usbd_device_handle dev = uaa->device;
  275         usb_config_descriptor_t *cdesc;
  276         usb_interface_descriptor_t *id;
  277         usb_endpoint_descriptor_t *ed;
  278         char *devinfop;
  279         const char *devname = sc->sc_dev.dv_xname;
  280         usbd_status err;
  281         struct ucom_attach_args uca;
  282         int i;
  283 
  284         devinfop = usbd_devinfo_alloc(dev, 0);
  285         printf("\n%s: %s\n", devname, devinfop);
  286         usbd_devinfo_free(devinfop);
  287 
  288         sc->sc_udev = dev;
  289 
  290         /*
  291          * initialize rts, dtr variables to something
  292          * different from boolean 0, 1
  293          */
  294         sc->sc_dtr = -1;
  295         sc->sc_rts = -1;
  296 
  297         DPRINTF(("ubsa attach: sc = %p\n", sc));
  298 
  299         /* initialize endpoints */
  300         uca.bulkin = uca.bulkout = -1;
  301         sc->sc_intr_number = -1;
  302         sc->sc_intr_pipe = NULL;
  303 
  304         /* Move the device into the configured state. */
  305         err = usbd_set_config_index(dev, UBSA_CONFIG_INDEX, 1);
  306         if (err) {
  307                 printf("%s: failed to set configuration: %s\n",
  308                     devname, usbd_errstr(err));
  309                 sc->sc_dying = 1;
  310                 goto error;
  311         }
  312 
  313         /* get the config descriptor */
  314         cdesc = usbd_get_config_descriptor(sc->sc_udev);
  315 
  316         if (cdesc == NULL) {
  317                 printf("%s: failed to get configuration descriptor\n",
  318                     devname);
  319                 sc->sc_dying = 1;
  320                 goto error;
  321         }
  322 
  323         /* get the first interface */
  324         err = usbd_device2interface_handle(dev, UBSA_IFACE_INDEX,
  325             &sc->sc_iface);
  326         if (err) {
  327                 printf("%s: failed to get interface: %s\n",
  328                         devname, usbd_errstr(err));
  329                 sc->sc_dying = 1;
  330                 goto error;
  331         }
  332 
  333         /* Find the endpoints */
  334 
  335         id = usbd_get_interface_descriptor(sc->sc_iface);
  336         sc->sc_iface_number = id->bInterfaceNumber;
  337 
  338         for (i = 0; i < id->bNumEndpoints; i++) {
  339                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  340                 if (ed == NULL) {
  341                         printf("%s: no endpoint descriptor for %d\n",
  342                             sc->sc_dev.dv_xname, i);
  343                         sc->sc_dying = 1;
  344                         goto error;
  345                 }
  346 
  347                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  348                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  349                         sc->sc_intr_number = ed->bEndpointAddress;
  350                         sc->sc_isize = UGETW(ed->wMaxPacketSize);
  351                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  352                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  353                         uca.bulkin = ed->bEndpointAddress;
  354                         uca.ibufsize = UGETW(ed->wMaxPacketSize);
  355                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  356                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  357                         uca.bulkout = ed->bEndpointAddress;
  358                         uca.obufsize = UGETW(ed->wMaxPacketSize);
  359                 }
  360         }
  361 
  362         if (sc->sc_intr_number == -1) {
  363                 printf("%s: Could not find interrupt in\n", devname);
  364                 sc->sc_dying = 1;
  365                 goto error;
  366         }
  367 
  368         if (uca.bulkin == -1) {
  369                 printf("%s: Could not find data bulk in\n", devname);
  370                 sc->sc_dying = 1;
  371                 goto error;
  372         }
  373 
  374         if (uca.bulkout == -1) {
  375                 printf("%s: Could not find data bulk out\n", devname);
  376                 sc->sc_dying = 1;
  377                 goto error;
  378         }
  379 
  380         uca.portno = UCOM_UNK_PORTNO;
  381         /* bulkin, bulkout set above */
  382         uca.ibufsizepad = uca.ibufsize;
  383         uca.opkthdrlen = 0;
  384         uca.device = dev;
  385         uca.iface = sc->sc_iface;
  386         uca.methods = &ubsa_methods;
  387         uca.arg = sc;
  388         uca.info = NULL;
  389 
  390         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  391                            &sc->sc_dev);
  392 
  393         DPRINTF(("ubsa: in = 0x%x, out = 0x%x, intr = 0x%x\n",
  394             uca.bulkin, uca.bulkout, sc->sc_intr_number));
  395 
  396         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
  397 
  398 error:
  399         return;
  400 }
  401 
  402 int
  403 ubsa_detach(struct device *self, int flags)
  404 {
  405         struct ubsa_softc *sc = (struct ubsa_softc *)self;
  406         int rv = 0;
  407 
  408 
  409         DPRINTF(("ubsa_detach: sc = %p\n", sc));
  410 
  411         if (sc->sc_intr_pipe != NULL) {
  412                 usbd_abort_pipe(sc->sc_intr_pipe);
  413                 usbd_close_pipe(sc->sc_intr_pipe);
  414                 free(sc->sc_intr_buf, M_USBDEV);
  415                 sc->sc_intr_pipe = NULL;
  416         }
  417 
  418         sc->sc_dying = 1;
  419         if (sc->sc_subdev != NULL) {
  420                 rv = config_detach(sc->sc_subdev, flags);
  421                 sc->sc_subdev = NULL;
  422         }
  423 
  424         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  425                            &sc->sc_dev);
  426 
  427         return (rv);
  428 }
  429 
  430 int
  431 ubsa_activate(struct device *self, enum devact act)
  432 {
  433         struct ubsa_softc *sc = (struct ubsa_softc *)self;
  434         int rv = 0;
  435 
  436         switch (act) {
  437         case DVACT_ACTIVATE:
  438                 break;
  439 
  440         case DVACT_DEACTIVATE:
  441                 if (sc->sc_subdev != NULL)
  442                         rv = config_deactivate(sc->sc_subdev);
  443                 sc->sc_dying = 1;
  444                 break;
  445         }
  446         return (rv);
  447 }
  448 
  449 int
  450 ubsa_request(struct ubsa_softc *sc, u_int8_t request, u_int16_t value)
  451 {
  452         usb_device_request_t req;
  453         usbd_status err;
  454 
  455         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  456         req.bRequest = request;
  457         USETW(req.wValue, value);
  458         USETW(req.wIndex, sc->sc_iface_number);
  459         USETW(req.wLength, 0);
  460 
  461         err = usbd_do_request(sc->sc_udev, &req, 0);
  462         if (err && err != USBD_STALLED)
  463                 printf("%s: ubsa_request: %s\n",
  464                     sc->sc_dev.dv_xname, usbd_errstr(err));
  465         return (err);
  466 }
  467 
  468 void
  469 ubsa_dtr(struct ubsa_softc *sc, int onoff)
  470 {
  471 
  472         DPRINTF(("ubsa_dtr: onoff = %d\n", onoff));
  473 
  474         if (sc->sc_dtr == onoff)
  475                 return;
  476         sc->sc_dtr = onoff;
  477 
  478         ubsa_request(sc, UBSA_SET_DTR, onoff ? 1 : 0);
  479 }
  480 
  481 void
  482 ubsa_rts(struct ubsa_softc *sc, int onoff)
  483 {
  484 
  485         DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
  486 
  487         if (sc->sc_rts == onoff)
  488                 return;
  489         sc->sc_rts = onoff;
  490 
  491         ubsa_request(sc, UBSA_SET_RTS, onoff ? 1 : 0);
  492 }
  493 
  494 void
  495 ubsa_break(struct ubsa_softc *sc, int onoff)
  496 {
  497 
  498         DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
  499 
  500         ubsa_request(sc, UBSA_SET_BREAK, onoff ? 1 : 0);
  501 }
  502 
  503 void
  504 ubsa_set(void *addr, int portno, int reg, int onoff)
  505 {
  506         struct ubsa_softc *sc;
  507 
  508         sc = addr;
  509         switch (reg) {
  510         case UCOM_SET_DTR:
  511                 ubsa_dtr(sc, onoff);
  512                 break;
  513         case UCOM_SET_RTS:
  514                 ubsa_rts(sc, onoff);
  515                 break;
  516         case UCOM_SET_BREAK:
  517                 ubsa_break(sc, onoff);
  518                 break;
  519         default:
  520                 break;
  521         }
  522 }
  523 
  524 void
  525 ubsa_baudrate(struct ubsa_softc *sc, speed_t speed)
  526 {
  527         u_int16_t value = 0;
  528 
  529         DPRINTF(("ubsa_baudrate: speed = %d\n", speed));
  530 
  531         switch(speed) {
  532         case B0:
  533                 break;
  534         case B300:
  535         case B600:
  536         case B1200:
  537         case B2400:
  538         case B4800:
  539         case B9600:
  540         case B19200:
  541         case B38400:
  542         case B57600:
  543         case B115200:
  544         case B230400:
  545                 value = B230400 / speed;
  546                 break;
  547         default:
  548                 DPRINTF(("%s: ubsa_param: unsupported baudrate, "
  549                     "forcing default of 9600\n",
  550                     sc->sc_dev.dv_xname));
  551                 value = B230400 / B9600;
  552                 break;
  553         };
  554 
  555         if (speed == B0) {
  556                 ubsa_flow(sc, 0, 0);
  557                 ubsa_dtr(sc, 0);
  558                 ubsa_rts(sc, 0);
  559         } else
  560                 ubsa_request(sc, UBSA_SET_BAUDRATE, value);
  561 }
  562 
  563 void
  564 ubsa_parity(struct ubsa_softc *sc, tcflag_t cflag)
  565 {
  566         int value;
  567 
  568         DPRINTF(("ubsa_parity: cflag = 0x%x\n", cflag));
  569 
  570         if (cflag & PARENB)
  571                 value = (cflag & PARODD) ? UBSA_PARITY_ODD : UBSA_PARITY_EVEN;
  572         else
  573                 value = UBSA_PARITY_NONE;
  574 
  575         ubsa_request(sc, UBSA_SET_PARITY, value);
  576 }
  577 
  578 void
  579 ubsa_databits(struct ubsa_softc *sc, tcflag_t cflag)
  580 {
  581         int value;
  582 
  583         DPRINTF(("ubsa_databits: cflag = 0x%x\n", cflag));
  584 
  585         switch (cflag & CSIZE) {
  586         case CS5: value = 0; break;
  587         case CS6: value = 1; break;
  588         case CS7: value = 2; break;
  589         case CS8: value = 3; break;
  590         default:
  591                 DPRINTF(("%s: ubsa_param: unsupported databits requested, "
  592                     "forcing default of 8\n",
  593                     sc->sc_dev.dv_xname));
  594                 value = 3;
  595         }
  596 
  597         ubsa_request(sc, UBSA_SET_DATA_BITS, value);
  598 }
  599 
  600 void
  601 ubsa_stopbits(struct ubsa_softc *sc, tcflag_t cflag)
  602 {
  603         int value;
  604 
  605         DPRINTF(("ubsa_stopbits: cflag = 0x%x\n", cflag));
  606 
  607         value = (cflag & CSTOPB) ? 1 : 0;
  608 
  609         ubsa_request(sc, UBSA_SET_STOP_BITS, value);
  610 }
  611 
  612 void
  613 ubsa_flow(struct ubsa_softc *sc, tcflag_t cflag, tcflag_t iflag)
  614 {
  615         int value;
  616 
  617         DPRINTF(("ubsa_flow: cflag = 0x%x, iflag = 0x%x\n", cflag, iflag));
  618 
  619         value = 0;
  620         if (cflag & CRTSCTS)
  621                 value |= UBSA_FLOW_OCTS | UBSA_FLOW_IRTS;
  622         if (iflag & (IXON|IXOFF))
  623                 value |= UBSA_FLOW_OXON | UBSA_FLOW_IXON;
  624 
  625         ubsa_request(sc, UBSA_SET_FLOW_CTRL, value);
  626 }
  627 
  628 int
  629 ubsa_param(void *addr, int portno, struct termios *ti)
  630 {
  631         struct ubsa_softc *sc = addr;
  632 
  633         DPRINTF(("ubsa_param: sc = %p\n", sc));
  634 
  635         ubsa_baudrate(sc, ti->c_ospeed);
  636         ubsa_parity(sc, ti->c_cflag);
  637         ubsa_databits(sc, ti->c_cflag);
  638         ubsa_stopbits(sc, ti->c_cflag);
  639         ubsa_flow(sc, ti->c_cflag, ti->c_iflag);
  640 
  641         return (0);
  642 }
  643 
  644 int
  645 ubsa_open(void *addr, int portno)
  646 {
  647         struct ubsa_softc *sc = addr;
  648         int err;
  649 
  650         if (sc->sc_dying)
  651                 return (ENXIO);
  652 
  653         DPRINTF(("ubsa_open: sc = %p\n", sc));
  654 
  655         if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
  656                 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
  657                 err = usbd_open_pipe_intr(sc->sc_iface,
  658                     sc->sc_intr_number,
  659                     USBD_SHORT_XFER_OK,
  660                     &sc->sc_intr_pipe,
  661                     sc,
  662                     sc->sc_intr_buf,
  663                     sc->sc_isize,
  664                     ubsa_intr,
  665                     UBSA_INTR_INTERVAL);
  666                 if (err) {
  667                         printf("%s: cannot open interrupt pipe (addr %d)\n",
  668                             sc->sc_dev.dv_xname,
  669                             sc->sc_intr_number);
  670                         return (EIO);
  671                 }
  672         }
  673 
  674         return (0);
  675 }
  676 
  677 void
  678 ubsa_close(void *addr, int portno)
  679 {
  680         struct ubsa_softc *sc = addr;
  681         int err;
  682 
  683         if (sc->sc_dying)
  684                 return;
  685 
  686         DPRINTF(("ubsa_close: close\n"));
  687 
  688         if (sc->sc_intr_pipe != NULL) {
  689                 err = usbd_abort_pipe(sc->sc_intr_pipe);
  690                 if (err)
  691                         printf("%s: abort interrupt pipe failed: %s\n",
  692                             sc->sc_dev.dv_xname,
  693                             usbd_errstr(err));
  694                 err = usbd_close_pipe(sc->sc_intr_pipe);
  695                 if (err)
  696                         printf("%s: close interrupt pipe failed: %s\n",
  697                             sc->sc_dev.dv_xname,
  698                             usbd_errstr(err));
  699                 free(sc->sc_intr_buf, M_USBDEV);
  700                 sc->sc_intr_pipe = NULL;
  701         }
  702 }
  703 
  704 void
  705 ubsa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  706 {
  707         struct ubsa_softc *sc = priv;
  708         u_char *buf;
  709 
  710         buf = sc->sc_intr_buf;
  711         if (sc->sc_dying)
  712                 return;
  713 
  714         if (status != USBD_NORMAL_COMPLETION) {
  715                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  716                         return;
  717 
  718                 DPRINTF(("%s: ubsa_intr: abnormal status: %s\n",
  719                     sc->sc_dev.dv_xname, usbd_errstr(status)));
  720                 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
  721                 return;
  722         }
  723 
  724         /* incidentally, Belkin adapter status bits match UART 16550 bits */
  725         sc->sc_lsr = buf[2];
  726         sc->sc_msr = buf[3];
  727 
  728         DPRINTF(("%s: ubsa lsr = 0x%02x, msr = 0x%02x\n",
  729             sc->sc_dev.dv_xname, sc->sc_lsr, sc->sc_msr));
  730 
  731         ucom_status_change((struct ucom_softc *)sc->sc_subdev);
  732 }
  733 
  734 void
  735 ubsa_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  736 {
  737         struct ubsa_softc *sc = addr;
  738 
  739         DPRINTF(("ubsa_get_status\n"));
  740 
  741         if (lsr != NULL)
  742                 *lsr = sc->sc_lsr;
  743         if (msr != NULL)
  744                 *msr = sc->sc_msr;
  745 }

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