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/uplcom.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: uplcom.c,v 1.34.2.3 2004/07/28 10:40:40 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  * General information: http://www.prolific.com.tw/fr_pl2303.htm
   40  * http://www.hitachi-hitec.com/jyouhou/prolific/2303.pdf
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __KERNEL_RCSID(0, "$NetBSD: uplcom.c,v 1.34.2.3 2004/07/28 10:40:40 tron Exp $");
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/malloc.h>
   50 #include <sys/ioctl.h>
   51 #include <sys/conf.h>
   52 #include <sys/tty.h>
   53 #include <sys/file.h>
   54 #include <sys/select.h>
   55 #include <sys/proc.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 #ifdef UPLCOM_DEBUG
   71 #define DPRINTFN(n, x)  if (uplcomdebug > (n)) logprintf x
   72 int     uplcomdebug = 0;
   73 #else
   74 #define DPRINTFN(n, x)
   75 #endif
   76 #define DPRINTF(x) DPRINTFN(0, x)
   77 
   78 #define UPLCOM_CONFIG_INDEX     0
   79 #define UPLCOM_IFACE_INDEX      0
   80 #define UPLCOM_SECOND_IFACE_INDEX       1
   81 
   82 #define UPLCOM_SET_REQUEST      0x01
   83 #define UPLCOM_SET_CRTSCTS      0x41
   84 #define RSAQ_STATUS_DSR         0x02
   85 #define RSAQ_STATUS_DCD         0x01
   86 
   87 #define UPLCOM_FLOW_OUT_CTS     0x0001
   88 #define UPLCOM_FLOW_OUT_DSR     0x0002
   89 #define UPLCOM_FLOW_IN_DSR      0x0004
   90 #define UPLCOM_FLOW_IN_DTR      0x0008
   91 #define UPLCOM_FLOW_IN_RTS      0x0010
   92 #define UPLCOM_FLOW_OUT_RTS     0x0020
   93 #define UPLCOM_FLOW_OUT_XON     0x0080
   94 #define UPLCOM_FLOW_IN_XON      0x0100
   95 
   96 struct  uplcom_softc {
   97         USBBASEDEVICE           sc_dev;         /* base device */
   98         usbd_device_handle      sc_udev;        /* USB device */
   99         usbd_interface_handle   sc_iface;       /* interface */
  100         int                     sc_iface_number;        /* interface number */
  101 
  102         usbd_interface_handle   sc_intr_iface;  /* interrupt interface */
  103         int                     sc_intr_number; /* interrupt number */
  104         usbd_pipe_handle        sc_intr_pipe;   /* interrupt pipe */
  105         u_char                  *sc_intr_buf;   /* interrupt buffer */
  106         int                     sc_isize;
  107 
  108         usb_cdc_line_state_t    sc_line_state;  /* current line state */
  109         int                     sc_dtr;         /* current DTR state */
  110         int                     sc_rts;         /* current RTS state */
  111 
  112         device_ptr_t            sc_subdev;      /* ucom device */
  113 
  114         u_char                  sc_dying;       /* disconnecting */
  115 
  116         u_char                  sc_lsr;         /* Local status register */
  117         u_char                  sc_msr;         /* uplcom status register */
  118 };
  119 
  120 /*
  121  * These are the maximum number of bytes transferred per frame.
  122  * The output buffer size cannot be increased due to the size encoding.
  123  */
  124 #define UPLCOMIBUFSIZE 256
  125 #define UPLCOMOBUFSIZE 256
  126 
  127 Static  usbd_status uplcom_reset(struct uplcom_softc *);
  128 Static  usbd_status uplcom_set_line_coding(struct uplcom_softc *sc,
  129                                            usb_cdc_line_state_t *state);
  130 Static  usbd_status uplcom_set_crtscts(struct uplcom_softc *);
  131 Static  void uplcom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
  132 
  133 Static  void uplcom_set(void *, int, int, int);
  134 Static  void uplcom_dtr(struct uplcom_softc *, int);
  135 Static  void uplcom_rts(struct uplcom_softc *, int);
  136 Static  void uplcom_break(struct uplcom_softc *, int);
  137 Static  void uplcom_set_line_state(struct uplcom_softc *);
  138 Static  void uplcom_get_status(void *, int portno, u_char *lsr, u_char *msr);
  139 #if TODO
  140 Static  int  uplcom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr );
  141 #endif
  142 Static  int  uplcom_param(void *, int, struct termios *);
  143 Static  int  uplcom_open(void *, int);
  144 Static  void uplcom_close(void *, int);
  145 
  146 struct  ucom_methods uplcom_methods = {
  147         uplcom_get_status,
  148         uplcom_set,
  149         uplcom_param,
  150         NULL, /* uplcom_ioctl, TODO */
  151         uplcom_open,
  152         uplcom_close,
  153         NULL,
  154         NULL,
  155 };
  156 
  157 static const struct usb_devno uplcom_devs[] = {
  158         /* I/O DATA USB-RSAQ2 */
  159         { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2 },
  160         /* I/O DATA USB-RSAQ */
  161         { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ },
  162         /* PLANEX USB-RS232 URS-03 */
  163         { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A },
  164         /* IOGEAR/ATEN UC-232A */
  165         { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303 },
  166         /* IOGEAR/ATENTRIPPLITE */
  167         { USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209 },
  168         /* ELECOM UC-SGT */
  169         { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT },
  170         /* RATOC REX-USB60 */
  171         { USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60 },
  172         /* TDK USB-PHS Adapter UHA6400 */
  173         { USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400 },
  174         /* TDK USB-PDC Adapter UPA9664 */
  175         { USB_VENDOR_TDK, USB_PRODUCT_TDK_UPA9664 },
  176         /* Sony Ericsson USB Cable */
  177         { USB_VENDOR_SONYERICSSON, USB_PRODUCT_SONYERICSSON_DCU10 },
  178         /* SOURCENEXT KeikaiDenwa 8 */
  179         { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8 },
  180         /* SOURCENEXT KeikaiDenwa 8 with charger */
  181         { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG },
  182         /* HAL Corporation Crossam2+USB */
  183         { USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001 },
  184         /* Sitecom USB to serial cable */
  185         { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_SERIAL },
  186 };
  187 #define uplcom_lookup(v, p) usb_lookup(uplcom_devs, v, p)
  188 
  189 
  190 USB_DECLARE_DRIVER(uplcom);
  191 
  192 USB_MATCH(uplcom)
  193 {
  194         USB_MATCH_START(uplcom, uaa);
  195 
  196         if (uaa->iface != NULL)
  197                 return (UMATCH_NONE);
  198 
  199         return (uplcom_lookup(uaa->vendor, uaa->product) != NULL ?
  200                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  201 }
  202 
  203 USB_ATTACH(uplcom)
  204 {
  205         USB_ATTACH_START(uplcom, sc, uaa);
  206         usbd_device_handle dev = uaa->device;
  207         usb_config_descriptor_t *cdesc;
  208         usb_interface_descriptor_t *id;
  209         usb_endpoint_descriptor_t *ed;
  210 
  211         char devinfo[1024];
  212         char *devname = USBDEVNAME(sc->sc_dev);
  213         usbd_status err;
  214         int i;
  215         struct ucom_attach_args uca;
  216 
  217         usbd_devinfo(dev, 0, devinfo);
  218         USB_ATTACH_SETUP;
  219         printf("%s: %s\n", devname, devinfo);
  220 
  221         sc->sc_udev = dev;
  222 
  223         DPRINTF(("\n\nuplcom attach: sc=%p\n", sc));
  224 
  225         /* initialize endpoints */
  226         uca.bulkin = uca.bulkout = -1;
  227         sc->sc_intr_number = -1;
  228         sc->sc_intr_pipe = NULL;
  229 
  230         /* Move the device into the configured state. */
  231         err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1);
  232         if (err) {
  233                 printf("\n%s: failed to set configuration, err=%s\n",
  234                         devname, usbd_errstr(err));
  235                 sc->sc_dying = 1;
  236                 USB_ATTACH_ERROR_RETURN;
  237         }
  238 
  239         /* get the config descriptor */
  240         cdesc = usbd_get_config_descriptor(sc->sc_udev);
  241 
  242         if (cdesc == NULL) {
  243                 printf("%s: failed to get configuration descriptor\n",
  244                         USBDEVNAME(sc->sc_dev));
  245                 sc->sc_dying = 1;
  246                 USB_ATTACH_ERROR_RETURN;
  247         }
  248 
  249         /* get the (first/common) interface */
  250         err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX,
  251                                                         &sc->sc_iface);
  252         if (err) {
  253                 printf("\n%s: failed to get interface, err=%s\n",
  254                         devname, usbd_errstr(err));
  255                 sc->sc_dying = 1;
  256                 USB_ATTACH_ERROR_RETURN;
  257         }
  258 
  259         /* Find the interrupt endpoints */
  260 
  261         id = usbd_get_interface_descriptor(sc->sc_iface);
  262         sc->sc_iface_number = id->bInterfaceNumber;
  263 
  264         for (i = 0; i < id->bNumEndpoints; i++) {
  265                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  266                 if (ed == NULL) {
  267                         printf("%s: no endpoint descriptor for %d\n",
  268                                 USBDEVNAME(sc->sc_dev), i);
  269                         sc->sc_dying = 1;
  270                         USB_ATTACH_ERROR_RETURN;
  271                 }
  272 
  273                 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 (sc->sc_intr_number== -1) {
  281                 printf("%s: Could not find interrupt in\n",
  282                         USBDEVNAME(sc->sc_dev));
  283                 sc->sc_dying = 1;
  284                 USB_ATTACH_ERROR_RETURN;
  285         }
  286 
  287         /* keep interface for interrupt */
  288         sc->sc_intr_iface = sc->sc_iface;
  289 
  290         /*
  291          * USB-RSAQ1 has two interface
  292          *
  293          *  USB-RSAQ1       | USB-RSAQ2
  294          * -----------------+-----------------
  295          * Interface 0      |Interface 0
  296          *  Interrupt(0x81) | Interrupt(0x81)
  297          * -----------------+ BulkIN(0x02)
  298          * Interface 1      | BulkOUT(0x83)
  299          *   BulkIN(0x02)   |
  300          *   BulkOUT(0x83)  |
  301          */
  302         if (cdesc->bNumInterface == 2) {
  303                 err = usbd_device2interface_handle(dev,
  304                                 UPLCOM_SECOND_IFACE_INDEX, &sc->sc_iface);
  305                 if (err) {
  306                         printf("\n%s: failed to get second interface, err=%s\n",
  307                                                         devname, usbd_errstr(err));
  308                         sc->sc_dying = 1;
  309                         USB_ATTACH_ERROR_RETURN;
  310                 }
  311         }
  312 
  313         /* Find the bulk{in,out} endpoints */
  314 
  315         id = usbd_get_interface_descriptor(sc->sc_iface);
  316         sc->sc_iface_number = id->bInterfaceNumber;
  317 
  318         for (i = 0; i < id->bNumEndpoints; i++) {
  319                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  320                 if (ed == NULL) {
  321                         printf("%s: no endpoint descriptor for %d\n",
  322                                 USBDEVNAME(sc->sc_dev), i);
  323                         sc->sc_dying = 1;
  324                         USB_ATTACH_ERROR_RETURN;
  325                 }
  326 
  327                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  328                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  329                         uca.bulkin = ed->bEndpointAddress;
  330                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  331                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  332                         uca.bulkout = ed->bEndpointAddress;
  333                 }
  334         }
  335 
  336         if (uca.bulkin == -1) {
  337                 printf("%s: Could not find data bulk in\n",
  338                         USBDEVNAME(sc->sc_dev));
  339                 sc->sc_dying = 1;
  340                 USB_ATTACH_ERROR_RETURN;
  341         }
  342 
  343         if (uca.bulkout == -1) {
  344                 printf("%s: Could not find data bulk out\n",
  345                         USBDEVNAME(sc->sc_dev));
  346                 sc->sc_dying = 1;
  347                 USB_ATTACH_ERROR_RETURN;
  348         }
  349 
  350         sc->sc_dtr = sc->sc_rts = -1;
  351         uca.portno = UCOM_UNK_PORTNO;
  352         /* bulkin, bulkout set above */
  353         uca.ibufsize = UPLCOMIBUFSIZE;
  354         uca.obufsize = UPLCOMOBUFSIZE;
  355         uca.ibufsizepad = UPLCOMIBUFSIZE;
  356         uca.opkthdrlen = 0;
  357         uca.device = dev;
  358         uca.iface = sc->sc_iface;
  359         uca.methods = &uplcom_methods;
  360         uca.arg = sc;
  361         uca.info = NULL;
  362 
  363         err = uplcom_reset(sc);
  364 
  365         if (err) {
  366                 printf("%s: reset failed, %s\n", USBDEVNAME(sc->sc_dev),
  367                         usbd_errstr(err));
  368                 sc->sc_dying = 1;
  369                 USB_ATTACH_ERROR_RETURN;
  370         }
  371 
  372         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  373                            USBDEV(sc->sc_dev));
  374 
  375         DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
  376                         uca.bulkin, uca.bulkout, sc->sc_intr_number ));
  377         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
  378 
  379         USB_ATTACH_SUCCESS_RETURN;
  380 }
  381 
  382 USB_DETACH(uplcom)
  383 {
  384         USB_DETACH_START(uplcom, sc);
  385         int rv = 0;
  386 
  387         DPRINTF(("uplcom_detach: sc=%p flags=%d\n", sc, flags));
  388 
  389         if (sc->sc_intr_pipe != NULL) {
  390                 usbd_abort_pipe(sc->sc_intr_pipe);
  391                 usbd_close_pipe(sc->sc_intr_pipe);
  392                 free(sc->sc_intr_buf, M_USBDEV);
  393                 sc->sc_intr_pipe = NULL;
  394         }
  395 
  396         sc->sc_dying = 1;
  397         if (sc->sc_subdev != NULL) {
  398                 rv = config_detach(sc->sc_subdev, flags);
  399                 sc->sc_subdev = NULL;
  400         }
  401 
  402         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  403                            USBDEV(sc->sc_dev));
  404 
  405         return (rv);
  406 }
  407 
  408 int
  409 uplcom_activate(device_ptr_t self, enum devact act)
  410 {
  411         struct uplcom_softc *sc = (struct uplcom_softc *)self;
  412         int rv = 0;
  413 
  414         switch (act) {
  415         case DVACT_ACTIVATE:
  416                 return (EOPNOTSUPP);
  417 
  418         case DVACT_DEACTIVATE:
  419                 if (sc->sc_subdev != NULL)
  420                         rv = config_deactivate(sc->sc_subdev);
  421                 sc->sc_dying = 1;
  422                 break;
  423         }
  424         return (rv);
  425 }
  426 
  427 usbd_status
  428 uplcom_reset(struct uplcom_softc *sc)
  429 {
  430         usb_device_request_t req;
  431         usbd_status err;
  432 
  433         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  434         req.bRequest = UPLCOM_SET_REQUEST;
  435         USETW(req.wValue, 0);
  436         USETW(req.wIndex, sc->sc_iface_number);
  437         USETW(req.wLength, 0);
  438 
  439         err = usbd_do_request(sc->sc_udev, &req, 0);
  440         if (err)
  441                 return (EIO);
  442 
  443         return (0);
  444 }
  445 
  446 void
  447 uplcom_set_line_state(struct uplcom_softc *sc)
  448 {
  449         usb_device_request_t req;
  450         int ls;
  451 
  452         /* make sure we have initialized state for sc_dtr and sc_rts */
  453         if (sc->sc_dtr == -1)
  454                 sc->sc_dtr = 0;
  455         if (sc->sc_rts == -1)
  456                 sc->sc_rts = 0;
  457 
  458         ls = (sc->sc_dtr ? UPLCOM_FLOW_OUT_DSR : 0) |
  459                 (sc->sc_rts ? UPLCOM_FLOW_OUT_CTS : 0);
  460 
  461         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  462         req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
  463         USETW(req.wValue, ls);
  464         USETW(req.wIndex, sc->sc_iface_number);
  465         USETW(req.wLength, 0);
  466 
  467         (void)usbd_do_request(sc->sc_udev, &req, 0);
  468 
  469 }
  470 
  471 void
  472 uplcom_set(void *addr, int portno, int reg, int onoff)
  473 {
  474         struct uplcom_softc *sc = addr;
  475 
  476         switch (reg) {
  477         case UCOM_SET_DTR:
  478                 uplcom_dtr(sc, onoff);
  479                 break;
  480         case UCOM_SET_RTS:
  481                 uplcom_rts(sc, onoff);
  482                 break;
  483         case UCOM_SET_BREAK:
  484                 uplcom_break(sc, onoff);
  485                 break;
  486         default:
  487                 break;
  488         }
  489 }
  490 
  491 void
  492 uplcom_dtr(struct uplcom_softc *sc, int onoff)
  493 {
  494 
  495         DPRINTF(("uplcom_dtr: onoff=%d\n", onoff));
  496 
  497         if (sc->sc_dtr != -1 && !sc->sc_dtr == !onoff)
  498                 return;
  499 
  500         sc->sc_dtr = !!onoff;
  501 
  502         uplcom_set_line_state(sc);
  503 }
  504 
  505 void
  506 uplcom_rts(struct uplcom_softc *sc, int onoff)
  507 {
  508         DPRINTF(("uplcom_rts: onoff=%d\n", onoff));
  509 
  510         if (sc->sc_rts != -1 && !sc->sc_rts == !onoff)
  511                 return;
  512 
  513         sc->sc_rts = !!onoff;
  514 
  515         uplcom_set_line_state(sc);
  516 }
  517 
  518 void
  519 uplcom_break(struct uplcom_softc *sc, int onoff)
  520 {
  521         usb_device_request_t req;
  522 
  523         DPRINTF(("uplcom_break: onoff=%d\n", onoff));
  524 
  525         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  526         req.bRequest = UCDC_SEND_BREAK;
  527         USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF);
  528         USETW(req.wIndex, sc->sc_iface_number);
  529         USETW(req.wLength, 0);
  530 
  531         (void)usbd_do_request(sc->sc_udev, &req, 0);
  532 }
  533 
  534 usbd_status
  535 uplcom_set_crtscts(struct uplcom_softc *sc)
  536 {
  537         usb_device_request_t req;
  538         usbd_status err;
  539 
  540         DPRINTF(("uplcom_set_crtscts: on\n"));
  541 
  542         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  543         req.bRequest = UPLCOM_SET_REQUEST;
  544         USETW(req.wValue, 0);
  545         USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
  546         USETW(req.wLength, 0);
  547 
  548         err = usbd_do_request(sc->sc_udev, &req, 0);
  549         if (err) {
  550                 DPRINTF(("uplcom_set_crtscts: failed, err=%s\n",
  551                         usbd_errstr(err)));
  552                 return (err);
  553         }
  554 
  555         return (USBD_NORMAL_COMPLETION);
  556 }
  557 
  558 usbd_status
  559 uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state)
  560 {
  561         usb_device_request_t req;
  562         usbd_status err;
  563 
  564         DPRINTF(("uplcom_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n",
  565                 UGETDW(state->dwDTERate), state->bCharFormat,
  566                 state->bParityType, state->bDataBits));
  567 
  568         if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
  569                 DPRINTF(("uplcom_set_line_coding: already set\n"));
  570                 return (USBD_NORMAL_COMPLETION);
  571         }
  572 
  573         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  574         req.bRequest = UCDC_SET_LINE_CODING;
  575         USETW(req.wValue, 0);
  576         USETW(req.wIndex, sc->sc_iface_number);
  577         USETW(req.wLength, UCDC_LINE_STATE_LENGTH);
  578 
  579         err = usbd_do_request(sc->sc_udev, &req, state);
  580         if (err) {
  581                 DPRINTF(("uplcom_set_line_coding: failed, err=%s\n",
  582                         usbd_errstr(err)));
  583                 return (err);
  584         }
  585 
  586         sc->sc_line_state = *state;
  587 
  588         return (USBD_NORMAL_COMPLETION);
  589 }
  590 
  591 int
  592 uplcom_param(void *addr, int portno, struct termios *t)
  593 {
  594         struct uplcom_softc *sc = addr;
  595         usbd_status err;
  596         usb_cdc_line_state_t ls;
  597 
  598         DPRINTF(("uplcom_param: sc=%p\n", sc));
  599 
  600         USETDW(ls.dwDTERate, t->c_ospeed);
  601         if (ISSET(t->c_cflag, CSTOPB))
  602                 ls.bCharFormat = UCDC_STOP_BIT_2;
  603         else
  604                 ls.bCharFormat = UCDC_STOP_BIT_1;
  605         if (ISSET(t->c_cflag, PARENB)) {
  606                 if (ISSET(t->c_cflag, PARODD))
  607                         ls.bParityType = UCDC_PARITY_ODD;
  608                 else
  609                         ls.bParityType = UCDC_PARITY_EVEN;
  610         } else
  611                 ls.bParityType = UCDC_PARITY_NONE;
  612         switch (ISSET(t->c_cflag, CSIZE)) {
  613         case CS5:
  614                 ls.bDataBits = 5;
  615                 break;
  616         case CS6:
  617                 ls.bDataBits = 6;
  618                 break;
  619         case CS7:
  620                 ls.bDataBits = 7;
  621                 break;
  622         case CS8:
  623                 ls.bDataBits = 8;
  624                 break;
  625         }
  626 
  627         err = uplcom_set_line_coding(sc, &ls);
  628         if (err) {
  629                 DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err)));
  630                 return (EIO);
  631         }
  632 
  633         if (ISSET(t->c_cflag, CRTSCTS))
  634                 uplcom_set_crtscts(sc);
  635 
  636         if (sc->sc_rts == -1 || sc->sc_dtr == -1)
  637                 uplcom_set_line_state(sc);
  638 
  639         if (err) {
  640                 DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err)));
  641                 return (EIO);
  642         }
  643 
  644         return (0);
  645 }
  646 
  647 int
  648 uplcom_open(void *addr, int portno)
  649 {
  650         struct uplcom_softc *sc = addr;
  651         int err;
  652 
  653         if (sc->sc_dying)
  654                 return (EIO);
  655 
  656         DPRINTF(("uplcom_open: sc=%p\n", sc));
  657 
  658         if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
  659                 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
  660                 err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number,
  661                         USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc,
  662                         sc->sc_intr_buf, sc->sc_isize,
  663                         uplcom_intr, USBD_DEFAULT_INTERVAL);
  664                 if (err) {
  665                         DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n",
  666                                 USBDEVNAME(sc->sc_dev), sc->sc_intr_number));
  667                                         return (EIO);
  668                 }
  669         }
  670 
  671         return (0);
  672 }
  673 
  674 void
  675 uplcom_close(void *addr, int portno)
  676 {
  677         struct uplcom_softc *sc = addr;
  678         int err;
  679 
  680         if (sc->sc_dying)
  681                 return;
  682 
  683         DPRINTF(("uplcom_close: close\n"));
  684 
  685         if (sc->sc_intr_pipe != NULL) {
  686                 err = usbd_abort_pipe(sc->sc_intr_pipe);
  687                 if (err)
  688                         printf("%s: abort interrupt pipe failed: %s\n",
  689                                 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
  690                 err = usbd_close_pipe(sc->sc_intr_pipe);
  691                 if (err)
  692                         printf("%s: close interrupt pipe failed: %s\n",
  693                                 USBDEVNAME(sc->sc_dev), usbd_errstr(err));
  694                 free(sc->sc_intr_buf, M_USBDEV);
  695                 sc->sc_intr_pipe = NULL;
  696         }
  697 }
  698 
  699 void
  700 uplcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  701 {
  702         struct uplcom_softc *sc = priv;
  703         u_char *buf = sc->sc_intr_buf;
  704         u_char pstatus;
  705 
  706         if (sc->sc_dying)
  707                 return;
  708 
  709         if (status != USBD_NORMAL_COMPLETION) {
  710                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  711                         return;
  712 
  713                 DPRINTF(("%s: abnormal status: %s\n", USBDEVNAME(sc->sc_dev),
  714                         usbd_errstr(status)));
  715                 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
  716                 return;
  717         }
  718 
  719         DPRINTF(("%s: uplcom status = %02x\n", USBDEVNAME(sc->sc_dev), buf[8]));
  720 
  721         sc->sc_lsr = sc->sc_msr = 0;
  722         pstatus = buf[8];
  723         if (ISSET(pstatus, RSAQ_STATUS_DSR))
  724                 sc->sc_msr |= UMSR_DSR;
  725         if (ISSET(pstatus, RSAQ_STATUS_DCD))
  726                 sc->sc_msr |= UMSR_DCD;
  727         ucom_status_change((struct ucom_softc *) sc->sc_subdev);
  728 }
  729 
  730 void
  731 uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  732 {
  733         struct uplcom_softc *sc = addr;
  734 
  735         DPRINTF(("uplcom_get_status:\n"));
  736 
  737         if (lsr != NULL)
  738                 *lsr = sc->sc_lsr;
  739         if (msr != NULL)
  740                 *msr = sc->sc_msr;
  741 }
  742 
  743 #if TODO
  744 int
  745 uplcom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag,
  746              usb_proc_ptr p)
  747 {
  748         struct uplcom_softc *sc = addr;
  749         int error = 0;
  750 
  751         if (sc->sc_dying)
  752                 return (EIO);
  753 
  754         DPRINTF(("uplcom_ioctl: cmd=0x%08lx\n", cmd));
  755 
  756         switch (cmd) {
  757         case TIOCNOTTY:
  758         case TIOCMGET:
  759         case TIOCMSET:
  760         case USB_GET_CM_OVER_DATA:
  761         case USB_SET_CM_OVER_DATA:
  762                 break;
  763 
  764         default:
  765                 DPRINTF(("uplcom_ioctl: unknown\n"));
  766                 error = ENOTTY;
  767                 break;
  768         }
  769 
  770         return (error);
  771 }
  772 #endif

Cache object: e41b3ddbbfa1db53d2f006a9474c9465


[ 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.