root/dev/usb/uplcom.c

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

DEFINITIONS

This source file includes following definitions.
  1. uplcom_match
  2. uplcom_attach
  3. uplcom_detach
  4. uplcom_activate
  5. uplcom_reset
  6. uplcom_set_line_state
  7. uplcom_set
  8. uplcom_dtr
  9. uplcom_rts
  10. uplcom_break
  11. uplcom_set_crtscts
  12. uplcom_set_line_coding
  13. uplcom_param
  14. uplcom_open
  15. uplcom_close
  16. uplcom_intr
  17. uplcom_get_status
  18. uplcom_ioctl

    1 /*      $OpenBSD: uplcom.c,v 1.43 2007/06/14 10:11:16 mbalmer Exp $     */
    2 /*      $NetBSD: uplcom.c,v 1.29 2002/09/23 05:51:23 simonb Exp $       */
    3 /*
    4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Ichiro FUKUHARA (ichiro@ichiro.org).
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Simple datasheet
   41  * http://www.prolific.com.tw/PDF/PL-2303%20Market%20Spec.pdf
   42  * http://www.hitachi-hitec.com/jyouhou/prolific/2303.pdf
   43  *      (english)
   44  *
   45  */
   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/selinfo.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 #ifdef UPLCOM_DEBUG
   73 #define DPRINTFN(n, x)  do { if (uplcomdebug > (n)) printf x; } while (0)
   74 int     uplcomdebug = 0;
   75 #else
   76 #define DPRINTFN(n, x)
   77 #endif
   78 #define DPRINTF(x) DPRINTFN(0, x)
   79 
   80 #define UPLCOM_CONFIG_INDEX     0
   81 #define UPLCOM_IFACE_INDEX      0
   82 #define UPLCOM_SECOND_IFACE_INDEX       1
   83 
   84 #define UPLCOM_SET_REQUEST      0x01
   85 #define UPLCOM_SET_CRTSCTS      0x41
   86 #define UPLCOM_HX_SET_CRTSCTS   0x61
   87 #define RSAQ_STATUS_CTS         0x80
   88 #define RSAQ_STATUS_DSR         0x02
   89 #define RSAQ_STATUS_DCD         0x01
   90 
   91 struct  uplcom_softc {
   92         struct device            sc_dev;        /* base device */
   93         usbd_device_handle       sc_udev;       /* USB device */
   94         usbd_interface_handle    sc_iface;      /* interface */
   95         int                      sc_iface_number;       /* interface number */
   96 
   97         usbd_interface_handle    sc_intr_iface; /* interrupt interface */
   98         int                      sc_intr_number;        /* interrupt number */
   99         usbd_pipe_handle         sc_intr_pipe;  /* interrupt pipe */
  100         u_char                  *sc_intr_buf;   /* interrupt buffer */
  101         int                      sc_isize;
  102 
  103         usb_cdc_line_state_t     sc_line_state; /* current line state */
  104         int                      sc_dtr;        /* current DTR state */
  105         int                      sc_rts;        /* current RTS state */
  106 
  107         struct device           *sc_subdev;     /* ucom device */
  108 
  109         u_char                   sc_dying;      /* disconnecting */
  110 
  111         u_char                   sc_lsr;        /* Local status register */
  112         u_char                   sc_msr;        /* uplcom status register */
  113         int                      sc_type_hx;    /* HX variant */
  114 };
  115 
  116 /*
  117  * These are the maximum number of bytes transferred per frame.
  118  * The output buffer size cannot be increased due to the size encoding.
  119  */
  120 #define UPLCOMIBUFSIZE 256
  121 #define UPLCOMOBUFSIZE 256
  122 
  123 usbd_status uplcom_reset(struct uplcom_softc *);
  124 usbd_status uplcom_set_line_coding(struct uplcom_softc *sc,
  125                                            usb_cdc_line_state_t *state);
  126 usbd_status uplcom_set_crtscts(struct uplcom_softc *);
  127 void uplcom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
  128 
  129 void uplcom_set(void *, int, int, int);
  130 void uplcom_dtr(struct uplcom_softc *, int);
  131 void uplcom_rts(struct uplcom_softc *, int);
  132 void uplcom_break(struct uplcom_softc *, int);
  133 void uplcom_set_line_state(struct uplcom_softc *);
  134 void uplcom_get_status(void *, int portno, u_char *lsr, u_char *msr);
  135 #if TODO
  136 int  uplcom_ioctl(void *, int, u_long, caddr_t, int, struct proc *);
  137 #endif
  138 int  uplcom_param(void *, int, struct termios *);
  139 int  uplcom_open(void *, int);
  140 void uplcom_close(void *, int);
  141 
  142 struct  ucom_methods uplcom_methods = {
  143         uplcom_get_status,
  144         uplcom_set,
  145         uplcom_param,
  146         NULL, /* uplcom_ioctl, TODO */
  147         uplcom_open,
  148         uplcom_close,
  149         NULL,
  150         NULL,
  151 };
  152 
  153 static const struct usb_devno uplcom_devs[] = {
  154         { USB_VENDOR_ALCATEL, USB_PRODUCT_ALCATEL_OT535 },
  155         { USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_SERIAL },
  156         { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A },
  157         { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U257 },
  158         { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT },
  159         { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT0 },
  160         { USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001 },
  161         { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ },
  162         { USB_VENDOR_LEADTEK, USB_PRODUCT_LEADTEK_9531 },
  163         { USB_VENDOR_MOBILEACTION, USB_PRODUCT_MOBILEACTION_MA620 },
  164         { USB_VENDOR_NOKIA, USB_PRODUCT_NOKIA_CA42 },
  165         { USB_VENDOR_OTI, USB_PRODUCT_OTI_DKU5 },
  166         { USB_VENDOR_PLX, USB_PRODUCT_PLX_CA42 },
  167         { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_TYTP50P6S },
  168         { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303 },
  169         { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303X },
  170         { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303X2 },
  171         { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2 },
  172         { USB_VENDOR_PROLIFIC2, USB_PRODUCT_PROLIFIC2_PL2303 },
  173         { USB_VENDOR_RADIOSHACK, USB_PRODUCT_RADIOSHACK_PL2303 },
  174         { USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60 },
  175         { USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_SERIAL },
  176         { USB_VENDOR_SAMSUNG2, USB_PRODUCT_SAMSUNG2_I330 },
  177         { USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_SX1 },
  178         { USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_X65 },
  179         { USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_X75 },
  180         { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_CN104 },
  181         { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8 },
  182         { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG },
  183         { USB_VENDOR_SPEEDDRAGON, USB_PRODUCT_SPEEDDRAGON_MS3303H },
  184         { USB_VENDOR_SUSTEEN, USB_PRODUCT_SUSTEEN_DCU11 },
  185         { USB_VENDOR_SYNTECH, USB_PRODUCT_SYNTECH_SERIAL },
  186         { USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400 },
  187         { USB_VENDOR_TDK, USB_PRODUCT_TDK_UPA9664 },
  188         { USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209 }
  189 };
  190 #define uplcom_lookup(v, p) usb_lookup(uplcom_devs, v, p)
  191 
  192 int uplcom_match(struct device *, void *, void *); 
  193 void uplcom_attach(struct device *, struct device *, void *); 
  194 int uplcom_detach(struct device *, int); 
  195 int uplcom_activate(struct device *, enum devact); 
  196 
  197 struct cfdriver uplcom_cd = { 
  198         NULL, "uplcom", DV_DULL 
  199 }; 
  200 
  201 const struct cfattach uplcom_ca = { 
  202         sizeof(struct uplcom_softc), 
  203         uplcom_match, 
  204         uplcom_attach, 
  205         uplcom_detach, 
  206         uplcom_activate, 
  207 };
  208 
  209 int
  210 uplcom_match(struct device *parent, void *match, void *aux)
  211 {
  212         struct usb_attach_arg *uaa = aux;
  213 
  214         if (uaa->iface != NULL)
  215                 return (UMATCH_NONE);
  216 
  217         return (uplcom_lookup(uaa->vendor, uaa->product) != NULL ?
  218                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  219 }
  220 
  221 void
  222 uplcom_attach(struct device *parent, struct device *self, void *aux)
  223 {
  224         struct uplcom_softc *sc = (struct uplcom_softc *)self;
  225         struct usb_attach_arg *uaa = aux;
  226         usbd_device_handle dev = uaa->device;
  227         usb_config_descriptor_t *cdesc;
  228         usb_device_descriptor_t *ddesc;
  229         usb_interface_descriptor_t *id;
  230         usb_endpoint_descriptor_t *ed;
  231 
  232         char *devinfop;
  233         char *devname = sc->sc_dev.dv_xname;
  234         usbd_status err;
  235         int i;
  236         struct ucom_attach_args uca;
  237 
  238         devinfop = usbd_devinfo_alloc(dev, 0);
  239         printf("\n%s: %s\n", devname, devinfop);
  240         usbd_devinfo_free(devinfop);
  241 
  242         sc->sc_udev = dev;
  243 
  244         DPRINTF(("\n\nuplcom attach: sc=%p\n", sc));
  245 
  246         /* initialize endpoints */
  247         uca.bulkin = uca.bulkout = -1;
  248         sc->sc_intr_number = -1;
  249         sc->sc_intr_pipe = NULL;
  250 
  251         /* Move the device into the configured state. */
  252         err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1);
  253         if (err) {
  254                 printf("\n%s: failed to set configuration, err=%s\n",
  255                         devname, usbd_errstr(err));
  256                 sc->sc_dying = 1;
  257                 return;
  258         }
  259 
  260         /* get the config descriptor */
  261         cdesc = usbd_get_config_descriptor(sc->sc_udev);
  262 
  263         if (cdesc == NULL) {
  264                 printf("%s: failed to get configuration descriptor\n",
  265                         sc->sc_dev.dv_xname);
  266                 sc->sc_dying = 1;
  267                 return;
  268         }
  269 
  270         /* get the device descriptor */
  271         ddesc = usbd_get_device_descriptor(sc->sc_udev);
  272         if (ddesc == NULL) {
  273                 printf("%s: failed to get device descriptor\n",
  274                     sc->sc_dev.dv_xname);
  275                 sc->sc_dying = 1;
  276                 return;
  277         }
  278 
  279         /*
  280          * The Linux driver suggest this will only be true for the HX
  281          * variants. The datasheets disagree.
  282          */
  283         if (ddesc->bMaxPacketSize == 0x40) {
  284                 DPRINTF(("%s: Assuming HX variant\n", sc->sc_dev.dv_xname));
  285                 sc->sc_type_hx = 1;
  286         } else
  287                 sc->sc_type_hx = 0;
  288 
  289         /* get the (first/common) interface */
  290         err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX,
  291                                                         &sc->sc_iface);
  292         if (err) {
  293                 printf("\n%s: failed to get interface, err=%s\n",
  294                         devname, usbd_errstr(err));
  295                 sc->sc_dying = 1;
  296                 return;
  297         }
  298 
  299         /* Find the interrupt endpoints */
  300 
  301         id = usbd_get_interface_descriptor(sc->sc_iface);
  302         sc->sc_iface_number = id->bInterfaceNumber;
  303 
  304         for (i = 0; i < id->bNumEndpoints; i++) {
  305                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  306                 if (ed == NULL) {
  307                         printf("%s: no endpoint descriptor for %d\n",
  308                                 sc->sc_dev.dv_xname, i);
  309                         sc->sc_dying = 1;
  310                         return;
  311                 }
  312 
  313                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  314                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  315                         sc->sc_intr_number = ed->bEndpointAddress;
  316                         sc->sc_isize = UGETW(ed->wMaxPacketSize);
  317                 }
  318         }
  319 
  320         if (sc->sc_intr_number== -1) {
  321                 printf("%s: Could not find interrupt in\n",
  322                         sc->sc_dev.dv_xname);
  323                 sc->sc_dying = 1;
  324                 return;
  325         }
  326 
  327         /* keep interface for interrupt */
  328         sc->sc_intr_iface = sc->sc_iface;
  329 
  330         /*
  331          * USB-RSAQ1 has two interface
  332          *
  333          *  USB-RSAQ1       | USB-RSAQ2
  334          * -----------------+-----------------
  335          * Interface 0      |Interface 0
  336          *  Interrupt(0x81) | Interrupt(0x81)
  337          * -----------------+ BulkIN(0x02)
  338          * Interface 1      | BulkOUT(0x83)
  339          *   BulkIN(0x02)   |
  340          *   BulkOUT(0x83)  |
  341          */
  342         if (cdesc->bNumInterface == 2) {
  343                 err = usbd_device2interface_handle(dev,
  344                                 UPLCOM_SECOND_IFACE_INDEX, &sc->sc_iface);
  345                 if (err) {
  346                         printf("\n%s: failed to get second interface, err=%s\n",
  347                                                         devname, usbd_errstr(err));
  348                         sc->sc_dying = 1;
  349                         return;
  350                 }
  351         }
  352 
  353         /* Find the bulk{in,out} endpoints */
  354 
  355         id = usbd_get_interface_descriptor(sc->sc_iface);
  356         sc->sc_iface_number = id->bInterfaceNumber;
  357 
  358         for (i = 0; i < id->bNumEndpoints; i++) {
  359                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  360                 if (ed == NULL) {
  361                         printf("%s: no endpoint descriptor for %d\n",
  362                                 sc->sc_dev.dv_xname, i);
  363                         sc->sc_dying = 1;
  364                         return;
  365                 }
  366 
  367                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  368                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  369                         uca.bulkin = ed->bEndpointAddress;
  370                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  371                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  372                         uca.bulkout = ed->bEndpointAddress;
  373                 }
  374         }
  375 
  376         if (uca.bulkin == -1) {
  377                 printf("%s: Could not find data bulk in\n",
  378                         sc->sc_dev.dv_xname);
  379                 sc->sc_dying = 1;
  380                 return;
  381         }
  382 
  383         if (uca.bulkout == -1) {
  384                 printf("%s: Could not find data bulk out\n",
  385                         sc->sc_dev.dv_xname);
  386                 sc->sc_dying = 1;
  387                 return;
  388         }
  389 
  390         sc->sc_dtr = sc->sc_rts = -1;
  391         uca.portno = UCOM_UNK_PORTNO;
  392         /* bulkin, bulkout set above */
  393         uca.ibufsize = UPLCOMIBUFSIZE;
  394         uca.obufsize = UPLCOMOBUFSIZE;
  395         uca.ibufsizepad = UPLCOMIBUFSIZE;
  396         uca.opkthdrlen = 0;
  397         uca.device = dev;
  398         uca.iface = sc->sc_iface;
  399         uca.methods = &uplcom_methods;
  400         uca.arg = sc;
  401         uca.info = NULL;
  402 
  403         err = uplcom_reset(sc);
  404 
  405         if (err) {
  406                 printf("%s: reset failed, %s\n", sc->sc_dev.dv_xname,
  407                         usbd_errstr(err));
  408                 sc->sc_dying = 1;
  409                 return;
  410         }
  411 
  412         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  413                            &sc->sc_dev);
  414 
  415         DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
  416                         uca.bulkin, uca.bulkout, sc->sc_intr_number ));
  417         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
  418 }
  419 
  420 int
  421 uplcom_detach(struct device *self, int flags)
  422 {
  423         struct uplcom_softc *sc = (struct uplcom_softc *)self;
  424         int rv = 0;
  425 
  426         DPRINTF(("uplcom_detach: sc=%p flags=%d\n", sc, flags));
  427 
  428         if (sc->sc_intr_pipe != NULL) {
  429                 usbd_abort_pipe(sc->sc_intr_pipe);
  430                 usbd_close_pipe(sc->sc_intr_pipe);
  431                 free(sc->sc_intr_buf, M_USBDEV);
  432                 sc->sc_intr_pipe = NULL;
  433         }
  434 
  435         sc->sc_dying = 1;
  436         if (sc->sc_subdev != NULL) {
  437                 rv = config_detach(sc->sc_subdev, flags);
  438                 sc->sc_subdev = NULL;
  439         }
  440 
  441         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  442                            &sc->sc_dev);
  443 
  444         return (rv);
  445 }
  446 
  447 int
  448 uplcom_activate(struct device *self, enum devact act)
  449 {
  450         struct uplcom_softc *sc = (struct uplcom_softc *)self;
  451         int rv = 0;
  452 
  453         switch (act) {
  454         case DVACT_ACTIVATE:
  455                 break;
  456 
  457         case DVACT_DEACTIVATE:
  458                 if (sc->sc_subdev != NULL)
  459                         rv = config_deactivate(sc->sc_subdev);
  460                 sc->sc_dying = 1;
  461                 break;
  462         }
  463         return (rv);
  464 }
  465 
  466 usbd_status
  467 uplcom_reset(struct uplcom_softc *sc)
  468 {
  469         usb_device_request_t req;
  470         usbd_status err;
  471 
  472         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  473         req.bRequest = UPLCOM_SET_REQUEST;
  474         USETW(req.wValue, 0);
  475         USETW(req.wIndex, sc->sc_iface_number);
  476         USETW(req.wLength, 0);
  477 
  478         err = usbd_do_request(sc->sc_udev, &req, 0);
  479         if (err)
  480                 return (EIO);
  481 
  482         return (0);
  483 }
  484 
  485 void
  486 uplcom_set_line_state(struct uplcom_softc *sc)
  487 {
  488         usb_device_request_t req;
  489         int ls;
  490 
  491         /* Make sure we have initialized state for sc_dtr and sc_rts */
  492         if (sc->sc_dtr == -1)
  493                 sc->sc_dtr = 0;
  494         if (sc->sc_rts == -1)
  495                 sc->sc_rts = 0;
  496 
  497         ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
  498             (sc->sc_rts ? UCDC_LINE_RTS : 0);
  499 
  500         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  501         req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
  502         USETW(req.wValue, ls);
  503         USETW(req.wIndex, sc->sc_iface_number);
  504         USETW(req.wLength, 0);
  505 
  506         (void)usbd_do_request(sc->sc_udev, &req, 0);
  507 
  508 }
  509 
  510 void
  511 uplcom_set(void *addr, int portno, int reg, int onoff)
  512 {
  513         struct uplcom_softc *sc = addr;
  514 
  515         switch (reg) {
  516         case UCOM_SET_DTR:
  517                 uplcom_dtr(sc, onoff);
  518                 break;
  519         case UCOM_SET_RTS:
  520                 uplcom_rts(sc, onoff);
  521                 break;
  522         case UCOM_SET_BREAK:
  523                 uplcom_break(sc, onoff);
  524                 break;
  525         default:
  526                 break;
  527         }
  528 }
  529 
  530 void
  531 uplcom_dtr(struct uplcom_softc *sc, int onoff)
  532 {
  533 
  534         DPRINTF(("uplcom_dtr: onoff=%d\n", onoff));
  535 
  536         if (sc->sc_dtr != -1 && !sc->sc_dtr == !onoff)
  537                 return;
  538 
  539         sc->sc_dtr = !!onoff;
  540 
  541         uplcom_set_line_state(sc);
  542 }
  543 
  544 void
  545 uplcom_rts(struct uplcom_softc *sc, int onoff)
  546 {
  547         DPRINTF(("uplcom_rts: onoff=%d\n", onoff));
  548 
  549         if (sc->sc_rts == -1 && !sc->sc_rts == !onoff)
  550                 return;
  551 
  552         sc->sc_rts = !!onoff;
  553 
  554         uplcom_set_line_state(sc);
  555 }
  556 
  557 void
  558 uplcom_break(struct uplcom_softc *sc, int onoff)
  559 {
  560         usb_device_request_t req;
  561 
  562         DPRINTF(("uplcom_break: onoff=%d\n", onoff));
  563 
  564         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  565         req.bRequest = UCDC_SEND_BREAK;
  566         USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF);
  567         USETW(req.wIndex, sc->sc_iface_number);
  568         USETW(req.wLength, 0);
  569 
  570         (void)usbd_do_request(sc->sc_udev, &req, 0);
  571 }
  572 
  573 usbd_status
  574 uplcom_set_crtscts(struct uplcom_softc *sc)
  575 {
  576         usb_device_request_t req;
  577         usbd_status err;
  578 
  579         DPRINTF(("uplcom_set_crtscts: on\n"));
  580 
  581         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  582         req.bRequest = UPLCOM_SET_REQUEST;
  583         USETW(req.wValue, 0);
  584         USETW(req.wIndex,
  585             (sc->sc_type_hx ? UPLCOM_HX_SET_CRTSCTS : UPLCOM_SET_CRTSCTS));
  586         USETW(req.wLength, 0);
  587 
  588         err = usbd_do_request(sc->sc_udev, &req, 0);
  589         if (err) {
  590                 DPRINTF(("uplcom_set_crtscts: failed, err=%s\n",
  591                         usbd_errstr(err)));
  592                 return (err);
  593         }
  594 
  595         return (USBD_NORMAL_COMPLETION);
  596 }
  597 
  598 usbd_status
  599 uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state)
  600 {
  601         usb_device_request_t req;
  602         usbd_status err;
  603 
  604         DPRINTF(("uplcom_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n",
  605                 UGETDW(state->dwDTERate), state->bCharFormat,
  606                 state->bParityType, state->bDataBits));
  607 
  608         if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
  609                 DPRINTF(("uplcom_set_line_coding: already set\n"));
  610                 return (USBD_NORMAL_COMPLETION);
  611         }
  612 
  613         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  614         req.bRequest = UCDC_SET_LINE_CODING;
  615         USETW(req.wValue, 0);
  616         USETW(req.wIndex, sc->sc_iface_number);
  617         USETW(req.wLength, UCDC_LINE_STATE_LENGTH);
  618 
  619         err = usbd_do_request(sc->sc_udev, &req, state);
  620         if (err) {
  621                 DPRINTF(("uplcom_set_line_coding: failed, err=%s\n",
  622                         usbd_errstr(err)));
  623                 return (err);
  624         }
  625 
  626         sc->sc_line_state = *state;
  627 
  628         return (USBD_NORMAL_COMPLETION);
  629 }
  630 
  631 int
  632 uplcom_param(void *addr, int portno, struct termios *t)
  633 {
  634         struct uplcom_softc *sc = addr;
  635         usbd_status err;
  636         usb_cdc_line_state_t ls;
  637 
  638         DPRINTF(("uplcom_param: sc=%p\n", sc));
  639 
  640         USETDW(ls.dwDTERate, t->c_ospeed);
  641         if (ISSET(t->c_cflag, CSTOPB))
  642                 ls.bCharFormat = UCDC_STOP_BIT_2;
  643         else
  644                 ls.bCharFormat = UCDC_STOP_BIT_1;
  645         if (ISSET(t->c_cflag, PARENB)) {
  646                 if (ISSET(t->c_cflag, PARODD))
  647                         ls.bParityType = UCDC_PARITY_ODD;
  648                 else
  649                         ls.bParityType = UCDC_PARITY_EVEN;
  650         } else
  651                 ls.bParityType = UCDC_PARITY_NONE;
  652         switch (ISSET(t->c_cflag, CSIZE)) {
  653         case CS5:
  654                 ls.bDataBits = 5;
  655                 break;
  656         case CS6:
  657                 ls.bDataBits = 6;
  658                 break;
  659         case CS7:
  660                 ls.bDataBits = 7;
  661                 break;
  662         case CS8:
  663                 ls.bDataBits = 8;
  664                 break;
  665         }
  666 
  667         err = uplcom_set_line_coding(sc, &ls);
  668         if (err) {
  669                 DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err)));
  670                 return (EIO);
  671         }
  672 
  673         if (ISSET(t->c_cflag, CRTSCTS))
  674                 uplcom_set_crtscts(sc);
  675 
  676         if (sc->sc_rts == -1 || sc->sc_dtr == -1)
  677                 uplcom_set_line_state(sc);
  678 
  679         if (err) {
  680                 DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err)));
  681                 return (EIO);
  682         }
  683 
  684         return (0);
  685 }
  686 
  687 int
  688 uplcom_open(void *addr, int portno)
  689 {
  690         struct uplcom_softc *sc = addr;
  691         usb_device_request_t req;
  692         usbd_status uerr;
  693         int err;
  694 
  695         if (sc->sc_dying)
  696                 return (EIO);
  697 
  698         DPRINTF(("uplcom_open: sc=%p\n", sc));
  699 
  700         if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
  701                 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
  702                 err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number,
  703                         USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc,
  704                         sc->sc_intr_buf, sc->sc_isize,
  705                         uplcom_intr, USBD_DEFAULT_INTERVAL);
  706                 if (err) {
  707                         DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n",
  708                                 sc->sc_dev.dv_xname, sc->sc_intr_number));
  709                                         return (EIO);
  710                 }
  711         }
  712 
  713         if (sc->sc_type_hx == 1) {
  714                 /*
  715                  * Undocumented (vendor unresponsive) - possibly changes
  716                  * flow control semantics. It is needed for HX variant devices.
  717                  */
  718                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  719                 req.bRequest = UPLCOM_SET_REQUEST;
  720                 USETW(req.wValue, 2);
  721                 USETW(req.wIndex, 0x44);
  722                 USETW(req.wLength, 0);
  723 
  724                 uerr = usbd_do_request(sc->sc_udev, &req, 0);
  725                 if (uerr)
  726                         return (EIO);
  727 
  728                 /* Reset upstream data pipes */
  729                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  730                 req.bRequest = UPLCOM_SET_REQUEST;
  731                 USETW(req.wValue, 8);
  732                 USETW(req.wIndex, 0);
  733                 USETW(req.wLength, 0);
  734 
  735                 uerr = usbd_do_request(sc->sc_udev, &req, 0);
  736                 if (uerr)
  737                         return (EIO);
  738 
  739                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  740                 req.bRequest = UPLCOM_SET_REQUEST;
  741                 USETW(req.wValue, 9);
  742                 USETW(req.wIndex, 0);
  743                 USETW(req.wLength, 0);
  744 
  745                 uerr = usbd_do_request(sc->sc_udev, &req, 0);
  746                 if (uerr)
  747                         return (EIO);
  748         }
  749 
  750         return (0);
  751 }
  752 
  753 void
  754 uplcom_close(void *addr, int portno)
  755 {
  756         struct uplcom_softc *sc = addr;
  757         int err;
  758 
  759         if (sc->sc_dying)
  760                 return;
  761 
  762         DPRINTF(("uplcom_close: close\n"));
  763 
  764         if (sc->sc_intr_pipe != NULL) {
  765                 err = usbd_abort_pipe(sc->sc_intr_pipe);
  766                 if (err)
  767                         printf("%s: abort interrupt pipe failed: %s\n",
  768                                 sc->sc_dev.dv_xname, usbd_errstr(err));
  769                 err = usbd_close_pipe(sc->sc_intr_pipe);
  770                 if (err)
  771                         printf("%s: close interrupt pipe failed: %s\n",
  772                                 sc->sc_dev.dv_xname, usbd_errstr(err));
  773                 free(sc->sc_intr_buf, M_USBDEV);
  774                 sc->sc_intr_pipe = NULL;
  775         }
  776 }
  777 
  778 void
  779 uplcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  780 {
  781         struct uplcom_softc *sc = priv;
  782         u_char *buf = sc->sc_intr_buf;
  783         u_char pstatus;
  784 
  785         if (sc->sc_dying)
  786                 return;
  787 
  788         if (status != USBD_NORMAL_COMPLETION) {
  789                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  790                         return;
  791 
  792                 DPRINTF(("%s: abnormal status: %s\n", sc->sc_dev.dv_xname,
  793                         usbd_errstr(status)));
  794                 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
  795                 return;
  796         }
  797 
  798         DPRINTF(("%s: uplcom status = %02x\n", sc->sc_dev.dv_xname, buf[8]));
  799 
  800         sc->sc_lsr = sc->sc_msr = 0;
  801         pstatus = buf[8];
  802         if (ISSET(pstatus, RSAQ_STATUS_CTS))
  803                 sc->sc_msr |= UMSR_CTS;
  804         else
  805                 sc->sc_msr &= ~UMSR_CTS;
  806         if (ISSET(pstatus, RSAQ_STATUS_DSR))
  807                 sc->sc_msr |= UMSR_DSR;
  808         else
  809                 sc->sc_msr &= ~UMSR_DSR;
  810         if (ISSET(pstatus, RSAQ_STATUS_DCD))
  811                 sc->sc_msr |= UMSR_DCD;
  812         else
  813                 sc->sc_msr &= ~UMSR_DCD;
  814         ucom_status_change((struct ucom_softc *) sc->sc_subdev);
  815 }
  816 
  817 void
  818 uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  819 {
  820         struct uplcom_softc *sc = addr;
  821 
  822         DPRINTF(("uplcom_get_status:\n"));
  823 
  824         if (lsr != NULL)
  825                 *lsr = sc->sc_lsr;
  826         if (msr != NULL)
  827                 *msr = sc->sc_msr;
  828 }
  829 
  830 #if TODO
  831 int
  832 uplcom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag,
  833              struct proc *p)
  834 {
  835         struct uplcom_softc *sc = addr;
  836         int error = 0;
  837 
  838         if (sc->sc_dying)
  839                 return (EIO);
  840 
  841         DPRINTF(("uplcom_ioctl: cmd=0x%08lx\n", cmd));
  842 
  843         switch (cmd) {
  844         case TIOCNOTTY:
  845         case TIOCMGET:
  846         case TIOCMSET:
  847         case USB_GET_CM_OVER_DATA:
  848         case USB_SET_CM_OVER_DATA:
  849                 break;
  850 
  851         default:
  852                 DPRINTF(("uplcom_ioctl: unknown\n"));
  853                 error = ENOTTY;
  854                 break;
  855         }
  856 
  857         return (error);
  858 }
  859 #endif

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