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/uark.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 /*      $OpenBSD: uark.c,v 1.1 2006/08/14 08:30:22 jsg Exp $    */
    2 
    3 /*
    4  * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  *
   18  * $FreeBSD: releng/7.3/sys/dev/usb/uark.c 171099 2007-06-30 02:42:36Z imp $
   19  */
   20 
   21 #include <sys/param.h>
   22 #include <sys/systm.h>
   23 #include <sys/kernel.h>
   24 #include <sys/malloc.h>
   25 #include <sys/module.h>
   26 #include <sys/bus.h>
   27 #include <sys/ioccom.h>
   28 #include <sys/fcntl.h>
   29 #include <sys/conf.h>
   30 #include <sys/tty.h>
   31 #include <sys/file.h>
   32 #include <sys/selinfo.h>
   33 #include <sys/sysctl.h>
   34 
   35 #include <dev/usb/usb.h>
   36 #include <dev/usb/usbdi.h>
   37 #include <dev/usb/usbdi_util.h>
   38 #include "usbdevs.h"
   39 
   40 #include <dev/usb/ucomvar.h>
   41 
   42 #ifdef UARK_DEBUG
   43 #define DPRINTFN(n, x)  do {    \
   44         if (uarkdebug > (n))    \
   45                 printf x;       \
   46 } while (0)
   47 int     uarkebug = 0;
   48 #else
   49 #define DPRINTFN(n, x)
   50 #endif
   51 #define DPRINTF(x) DPRINTFN(0, x)
   52 
   53 #define UARKBUFSZ               256
   54 #define UARK_CONFIG_NO          0
   55 #define UARK_IFACE_NO           0
   56 
   57 #define UARK_SET_DATA_BITS(x)   (x - 5)
   58 
   59 #define UARK_PARITY_NONE        0x00
   60 #define UARK_PARITY_ODD         0x08
   61 #define UARK_PARITY_EVEN        0x18
   62 
   63 #define UARK_STOP_BITS_1        0x00
   64 #define UARK_STOP_BITS_2        0x04
   65 
   66 #define UARK_BAUD_REF           3000000
   67 
   68 #define UARK_WRITE              0x40
   69 #define UARK_READ               0xc0
   70 
   71 #define UARK_REQUEST            0xfe
   72 
   73 #define UARK_CONFIG_INDEX       0
   74 #define UARK_IFACE_INDEX        0
   75 
   76 struct uark_softc {
   77         struct ucom_softc       sc_ucom;
   78         usbd_interface_handle   sc_iface;
   79 
   80         u_char                  sc_msr;
   81         u_char                  sc_lsr;
   82 };
   83 
   84 static void     uark_get_status(void *, int portno, u_char *lsr, u_char *msr);
   85 static void     uark_set(void *, int, int, int);
   86 static int      uark_param(void *, int, struct termios *);
   87 static void     uark_break(void *, int, int);
   88 static int      uark_cmd(struct uark_softc *, uint16_t, uint16_t);
   89 
   90 struct ucom_callback uark_callback = {
   91         uark_get_status,
   92         uark_set,
   93         uark_param,
   94         NULL,
   95         NULL,
   96         NULL,
   97         NULL,
   98         NULL,
   99 };
  100 
  101 static const struct usb_devno uark_devs[] = {
  102         { USB_VENDOR_ARKMICRO,          USB_PRODUCT_ARKMICRO_ARK3116 }
  103 };
  104 
  105 static int
  106 uark_match(device_t self)
  107 {
  108         struct usb_attach_arg *uaa = device_get_ivars(self);
  109 
  110         if (uaa->iface != NULL)
  111                 return (UMATCH_NONE);
  112 
  113         return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ?
  114             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
  115 }
  116 
  117 static int
  118 uark_attach(device_t self)
  119 {
  120         struct uark_softc *sc = device_get_softc(self);
  121         struct usb_attach_arg *uaa = device_get_ivars(self);
  122         usbd_device_handle dev = uaa->device;
  123         usbd_interface_handle iface;
  124         usb_interface_descriptor_t *id;
  125         usb_endpoint_descriptor_t *ed;
  126         usbd_status error;
  127         int i;
  128         struct ucom_softc *ucom = &sc->sc_ucom;
  129 
  130         ucom->sc_dev = self;
  131         ucom->sc_udev = dev;
  132 
  133         if (uaa->iface == NULL) {
  134                 /* Move the device into the configured state. */
  135                 error = usbd_set_config_index(dev, UARK_CONFIG_INDEX, 1);
  136                 if (error) {
  137                         device_printf(ucom->sc_dev,
  138                             "failed to set configuration, err=%s\n",
  139                             usbd_errstr(error));
  140                         goto bad;
  141                 }
  142                 error =
  143                     usbd_device2interface_handle(dev, UARK_IFACE_INDEX, &iface);
  144                 if (error) {
  145                         device_printf(ucom->sc_dev,
  146                             "failed to get interface, err=%s\n",
  147                             usbd_errstr(error));
  148                         goto bad;
  149                 }
  150         } else
  151                 iface = uaa->iface;
  152 
  153         id = usbd_get_interface_descriptor(iface);
  154         ucom->sc_iface = iface;
  155 
  156         ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
  157         for (i = 0; i < id->bNumEndpoints; i++) {
  158                 ed = usbd_interface2endpoint_descriptor(iface, i);
  159                 if (ed == NULL) {
  160                         device_printf(ucom->sc_dev,
  161                             "could not read endpoint descriptor\n");
  162                         goto bad;
  163                 }
  164                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  165                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  166                         ucom->sc_bulkin_no = ed->bEndpointAddress;
  167                 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  168                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  169                         ucom->sc_bulkout_no = ed->bEndpointAddress;
  170         }
  171         if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
  172                 device_printf(ucom->sc_dev, "missing endpoint\n");
  173                 goto bad;
  174         }
  175         ucom->sc_parent = sc;
  176         ucom->sc_ibufsize = UARKBUFSZ;
  177         ucom->sc_obufsize = UARKBUFSZ;
  178         ucom->sc_ibufsizepad = UARKBUFSZ;
  179         ucom->sc_opkthdrlen = 0;
  180 
  181         ucom->sc_callback = &uark_callback;
  182 
  183         DPRINTF(("uark: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no));
  184         ucom_attach(&sc->sc_ucom);
  185         return 0;
  186 
  187 bad:
  188         DPRINTF(("uftdi_attach: ATTACH ERROR\n"));
  189         ucom->sc_dying = 1;
  190         return ENXIO;
  191 }
  192 
  193 static int
  194 uark_detach(device_t self)
  195 {
  196         struct uark_softc *sc = device_get_softc(self);
  197         int rv = 0;
  198 
  199         DPRINTF(("uark_detach: sc=%p\n", sc));
  200         sc->sc_ucom.sc_dying = 1;
  201         rv = ucom_detach(&sc->sc_ucom);
  202 
  203         return (rv);
  204 }
  205 
  206 static void
  207 uark_set(void *vsc, int portno, int reg, int onoff)
  208 {
  209         struct uark_softc *sc = vsc;
  210 
  211         switch (reg) {
  212         case UCOM_SET_BREAK:
  213                 uark_break(sc, portno, onoff);
  214                 return;
  215                 /* NOTREACHED */
  216         case UCOM_SET_DTR:
  217         case UCOM_SET_RTS:
  218         default:
  219                 return;
  220                 /* NOTREACHED */
  221         }
  222 }
  223 
  224 static int
  225 uark_param(void *vsc, int portno, struct termios *t)
  226 {
  227         struct uark_softc *sc = (struct uark_softc *)vsc;
  228         int data;
  229 
  230         switch (t->c_ospeed) {
  231         case 300:
  232         case 600:
  233         case 1200:
  234         case 1800:
  235         case 2400:
  236         case 4800:
  237         case 9600:
  238         case 19200:
  239         case 38400:
  240         case 57600:
  241         case 115200:
  242                 uark_cmd(sc, 3, 0x83);
  243                 uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF);
  244                 uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8);
  245                 uark_cmd(sc, 3, 0x03);
  246                 break;
  247         default:
  248                 return (EINVAL);
  249                 /* NOTREACHED */
  250         }
  251         if (ISSET(t->c_cflag, CSTOPB))
  252                 data = UARK_STOP_BITS_2;
  253         else
  254                 data = UARK_STOP_BITS_1;
  255 
  256         if (ISSET(t->c_cflag, PARENB)) {
  257                 if (ISSET(t->c_cflag, PARODD))
  258                         data |= UARK_PARITY_ODD;
  259                 else
  260                         data |= UARK_PARITY_EVEN;
  261         } else
  262                 data |= UARK_PARITY_NONE;
  263 
  264         switch (ISSET(t->c_cflag, CSIZE)) {
  265         case CS5:
  266                 data |= UARK_SET_DATA_BITS(5);
  267                 break;
  268         case CS6:
  269                 data |= UARK_SET_DATA_BITS(6);
  270                 break;
  271         case CS7:
  272                 data |= UARK_SET_DATA_BITS(7);
  273                 break;
  274         case CS8:
  275                 data |= UARK_SET_DATA_BITS(8);
  276                 break;
  277         }
  278         uark_cmd(sc, 3, 0x00);
  279         uark_cmd(sc, 3, data);
  280 
  281         return (0);
  282 }
  283 
  284 void
  285 uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
  286 {
  287         struct uark_softc *sc = vsc;
  288 
  289         if (msr != NULL)
  290                 *msr = sc->sc_msr;
  291         if (lsr != NULL)
  292                 *lsr = sc->sc_lsr;
  293 }
  294 
  295 void
  296 uark_break(void *vsc, int portno, int onoff)
  297 {
  298 #ifdef UARK_DEBUG
  299         struct uark_softc *sc = vsc;
  300 
  301         device_printf(sc->sc_dev, "%s: break %s!\n", onoff ? "on" : "off");
  302         if (onoff)
  303                 /* break on */
  304                 uark_cmd(sc, 4, 0x01);
  305         else
  306                 uark_cmd(sc, 4, 0x00);
  307 #endif
  308 }
  309 
  310 int
  311 uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value)
  312 {
  313         usb_device_request_t req;
  314         usbd_status err;
  315         struct ucom_softc *ucom = &sc->sc_ucom;
  316 
  317         req.bmRequestType = UARK_WRITE;
  318         req.bRequest = UARK_REQUEST;
  319         USETW(req.wValue, value);
  320         USETW(req.wIndex, index);
  321         USETW(req.wLength, 0);
  322         err = usbd_do_request(ucom->sc_udev, &req, NULL);
  323 
  324         if (err)
  325                 return (EIO);
  326 
  327         return (0);
  328 }
  329 
  330 static device_method_t uark_methods[] = {
  331         /* Device interface */
  332         DEVMETHOD(device_probe, uark_match),
  333         DEVMETHOD(device_attach, uark_attach),
  334         DEVMETHOD(device_detach, uark_detach),
  335 
  336         { 0, 0 }
  337 };
  338 
  339 static driver_t uark_driver = {
  340         "ucom",
  341         uark_methods,
  342         sizeof (struct uark_softc)
  343 };
  344 
  345 DRIVER_MODULE(uark, uhub, uark_driver, ucom_devclass, usbd_driver_load, 0);
  346 MODULE_DEPEND(uark, usb, 1, 1, 1);
  347 MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);

Cache object: d9d65961093f12600a09717349d7342e


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