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/serial/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$
   19  */
   20 
   21 /*
   22  * NOTE: all function names beginning like "uark_cfg_" can only
   23  * be called from within the config thread function !
   24  */
   25 
   26 #include <sys/stdint.h>
   27 #include <sys/stddef.h>
   28 #include <sys/param.h>
   29 #include <sys/queue.h>
   30 #include <sys/types.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bus.h>
   34 #include <sys/module.h>
   35 #include <sys/lock.h>
   36 #include <sys/mutex.h>
   37 #include <sys/condvar.h>
   38 #include <sys/sysctl.h>
   39 #include <sys/sx.h>
   40 #include <sys/unistd.h>
   41 #include <sys/callout.h>
   42 #include <sys/malloc.h>
   43 #include <sys/priv.h>
   44 
   45 #include <dev/usb/usb.h>
   46 #include <dev/usb/usbdi.h>
   47 #include <dev/usb/usbdi_util.h>
   48 #include <dev/usb/usbhid.h>
   49 #include "usbdevs.h"
   50 
   51 #define USB_DEBUG_VAR usb_debug
   52 #include <dev/usb/usb_debug.h>
   53 #include <dev/usb/usb_process.h>
   54 
   55 #include <dev/usb/serial/usb_serial.h>
   56 
   57 #define UARK_BUF_SIZE           1024    /* bytes */
   58 
   59 #define UARK_SET_DATA_BITS(x)   ((x) - 5)
   60 
   61 #define UARK_PARITY_NONE        0x00
   62 #define UARK_PARITY_ODD         0x08
   63 #define UARK_PARITY_EVEN        0x18
   64 
   65 #define UARK_STOP_BITS_1        0x00
   66 #define UARK_STOP_BITS_2        0x04
   67 
   68 #define UARK_BAUD_REF           3000000
   69 
   70 #define UARK_WRITE              0x40
   71 #define UARK_READ               0xc0
   72 
   73 #define UARK_REQUEST            0xfe
   74 
   75 #define UARK_CONFIG_INDEX       0
   76 #define UARK_IFACE_INDEX        0
   77 
   78 enum {
   79         UARK_BULK_DT_WR,
   80         UARK_BULK_DT_RD,
   81         UARK_N_TRANSFER,
   82 };
   83 
   84 struct uark_softc {
   85         struct ucom_super_softc sc_super_ucom;
   86         struct ucom_softc sc_ucom;
   87 
   88         struct usb_xfer *sc_xfer[UARK_N_TRANSFER];
   89         struct usb_device *sc_udev;
   90         struct mtx sc_mtx;
   91 
   92         uint8_t sc_msr;
   93         uint8_t sc_lsr;
   94 };
   95 
   96 /* prototypes */
   97 
   98 static device_probe_t uark_probe;
   99 static device_attach_t uark_attach;
  100 static device_detach_t uark_detach;
  101 static void uark_free_softc(struct uark_softc *);
  102 
  103 static usb_callback_t uark_bulk_write_callback;
  104 static usb_callback_t uark_bulk_read_callback;
  105 
  106 static void     uark_free(struct ucom_softc *);
  107 static void     uark_start_read(struct ucom_softc *);
  108 static void     uark_stop_read(struct ucom_softc *);
  109 static void     uark_start_write(struct ucom_softc *);
  110 static void     uark_stop_write(struct ucom_softc *);
  111 static int      uark_pre_param(struct ucom_softc *, struct termios *);
  112 static void     uark_cfg_param(struct ucom_softc *, struct termios *);
  113 static void     uark_cfg_get_status(struct ucom_softc *, uint8_t *,
  114                     uint8_t *);
  115 static void     uark_cfg_set_break(struct ucom_softc *, uint8_t);
  116 static void     uark_cfg_write(struct uark_softc *, uint16_t, uint16_t);
  117 static void     uark_poll(struct ucom_softc *ucom);
  118 
  119 static const struct usb_config
  120         uark_xfer_config[UARK_N_TRANSFER] = {
  121         [UARK_BULK_DT_WR] = {
  122                 .type = UE_BULK,
  123                 .endpoint = UE_ADDR_ANY,
  124                 .direction = UE_DIR_OUT,
  125                 .bufsize = UARK_BUF_SIZE,
  126                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
  127                 .callback = &uark_bulk_write_callback,
  128         },
  129 
  130         [UARK_BULK_DT_RD] = {
  131                 .type = UE_BULK,
  132                 .endpoint = UE_ADDR_ANY,
  133                 .direction = UE_DIR_IN,
  134                 .bufsize = UARK_BUF_SIZE,
  135                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
  136                 .callback = &uark_bulk_read_callback,
  137         },
  138 };
  139 
  140 static const struct ucom_callback uark_callback = {
  141         .ucom_cfg_get_status = &uark_cfg_get_status,
  142         .ucom_cfg_set_break = &uark_cfg_set_break,
  143         .ucom_cfg_param = &uark_cfg_param,
  144         .ucom_pre_param = &uark_pre_param,
  145         .ucom_start_read = &uark_start_read,
  146         .ucom_stop_read = &uark_stop_read,
  147         .ucom_start_write = &uark_start_write,
  148         .ucom_stop_write = &uark_stop_write,
  149         .ucom_poll = &uark_poll,
  150         .ucom_free = &uark_free,
  151 };
  152 
  153 static device_method_t uark_methods[] = {
  154         /* Device methods */
  155         DEVMETHOD(device_probe, uark_probe),
  156         DEVMETHOD(device_attach, uark_attach),
  157         DEVMETHOD(device_detach, uark_detach),
  158         DEVMETHOD_END
  159 };
  160 
  161 static driver_t uark_driver = {
  162         .name = "uark",
  163         .methods = uark_methods,
  164         .size = sizeof(struct uark_softc),
  165 };
  166 
  167 static const STRUCT_USB_HOST_ID uark_devs[] = {
  168         {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)},
  169 };
  170 
  171 DRIVER_MODULE(uark, uhub, uark_driver, NULL, NULL);
  172 MODULE_DEPEND(uark, ucom, 1, 1, 1);
  173 MODULE_DEPEND(uark, usb, 1, 1, 1);
  174 MODULE_VERSION(uark, 1);
  175 USB_PNP_HOST_INFO(uark_devs);
  176 
  177 static int
  178 uark_probe(device_t dev)
  179 {
  180         struct usb_attach_arg *uaa = device_get_ivars(dev);
  181 
  182         if (uaa->usb_mode != USB_MODE_HOST) {
  183                 return (ENXIO);
  184         }
  185         if (uaa->info.bConfigIndex != 0) {
  186                 return (ENXIO);
  187         }
  188         if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) {
  189                 return (ENXIO);
  190         }
  191         return (usbd_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa));
  192 }
  193 
  194 static int
  195 uark_attach(device_t dev)
  196 {
  197         struct usb_attach_arg *uaa = device_get_ivars(dev);
  198         struct uark_softc *sc = device_get_softc(dev);
  199         int32_t error;
  200         uint8_t iface_index;
  201 
  202         device_set_usb_desc(dev);
  203         mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF);
  204         ucom_ref(&sc->sc_super_ucom);
  205 
  206         sc->sc_udev = uaa->device;
  207 
  208         iface_index = UARK_IFACE_INDEX;
  209         error = usbd_transfer_setup
  210             (uaa->device, &iface_index, sc->sc_xfer,
  211             uark_xfer_config, UARK_N_TRANSFER, sc, &sc->sc_mtx);
  212 
  213         if (error) {
  214                 device_printf(dev, "allocating control USB "
  215                     "transfers failed\n");
  216                 goto detach;
  217         }
  218         /* clear stall at first run */
  219         mtx_lock(&sc->sc_mtx);
  220         usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]);
  221         usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]);
  222         mtx_unlock(&sc->sc_mtx);
  223 
  224         error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
  225             &uark_callback, &sc->sc_mtx);
  226         if (error) {
  227                 DPRINTF("ucom_attach failed\n");
  228                 goto detach;
  229         }
  230         ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
  231 
  232         return (0);                     /* success */
  233 
  234 detach:
  235         uark_detach(dev);
  236         return (ENXIO);                 /* failure */
  237 }
  238 
  239 static int
  240 uark_detach(device_t dev)
  241 {
  242         struct uark_softc *sc = device_get_softc(dev);
  243 
  244         ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
  245         usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
  246 
  247         device_claim_softc(dev);
  248 
  249         uark_free_softc(sc);
  250 
  251         return (0);
  252 }
  253 
  254 UCOM_UNLOAD_DRAIN(uark);
  255 
  256 static void
  257 uark_free_softc(struct uark_softc *sc)
  258 {
  259         if (ucom_unref(&sc->sc_super_ucom)) {
  260                 mtx_destroy(&sc->sc_mtx);
  261                 device_free_softc(sc);
  262         }
  263 }
  264 
  265 static void
  266 uark_free(struct ucom_softc *ucom)
  267 {
  268         uark_free_softc(ucom->sc_parent);
  269 }
  270 
  271 static void
  272 uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
  273 {
  274         struct uark_softc *sc = usbd_xfer_softc(xfer);
  275         struct usb_page_cache *pc;
  276         uint32_t actlen;
  277 
  278         switch (USB_GET_STATE(xfer)) {
  279         case USB_ST_SETUP:
  280         case USB_ST_TRANSFERRED:
  281 tr_setup:
  282                 pc = usbd_xfer_get_frame(xfer, 0);
  283                 if (ucom_get_data(&sc->sc_ucom, pc, 0,
  284                     UARK_BUF_SIZE, &actlen)) {
  285                         usbd_xfer_set_frame_len(xfer, 0, actlen);
  286                         usbd_transfer_submit(xfer);
  287                 }
  288                 return;
  289 
  290         default:                        /* Error */
  291                 if (error != USB_ERR_CANCELLED) {
  292                         /* try to clear stall first */
  293                         usbd_xfer_set_stall(xfer);
  294                         goto tr_setup;
  295                 }
  296                 return;
  297         }
  298 }
  299 
  300 static void
  301 uark_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
  302 {
  303         struct uark_softc *sc = usbd_xfer_softc(xfer);
  304         struct usb_page_cache *pc;
  305         int actlen;
  306 
  307         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
  308 
  309         switch (USB_GET_STATE(xfer)) {
  310         case USB_ST_TRANSFERRED:
  311                 pc = usbd_xfer_get_frame(xfer, 0);
  312                 ucom_put_data(&sc->sc_ucom, pc, 0, actlen);
  313 
  314         case USB_ST_SETUP:
  315 tr_setup:
  316                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
  317                 usbd_transfer_submit(xfer);
  318                 return;
  319 
  320         default:                        /* Error */
  321                 if (error != USB_ERR_CANCELLED) {
  322                         /* try to clear stall first */
  323                         usbd_xfer_set_stall(xfer);
  324                         goto tr_setup;
  325                 }
  326                 return;
  327         }
  328 }
  329 
  330 static void
  331 uark_start_read(struct ucom_softc *ucom)
  332 {
  333         struct uark_softc *sc = ucom->sc_parent;
  334 
  335         usbd_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]);
  336 }
  337 
  338 static void
  339 uark_stop_read(struct ucom_softc *ucom)
  340 {
  341         struct uark_softc *sc = ucom->sc_parent;
  342 
  343         usbd_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]);
  344 }
  345 
  346 static void
  347 uark_start_write(struct ucom_softc *ucom)
  348 {
  349         struct uark_softc *sc = ucom->sc_parent;
  350 
  351         usbd_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]);
  352 }
  353 
  354 static void
  355 uark_stop_write(struct ucom_softc *ucom)
  356 {
  357         struct uark_softc *sc = ucom->sc_parent;
  358 
  359         usbd_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]);
  360 }
  361 
  362 static int
  363 uark_pre_param(struct ucom_softc *ucom, struct termios *t)
  364 {
  365         if ((t->c_ospeed < 300) || (t->c_ospeed > 115200))
  366                 return (EINVAL);
  367         return (0);
  368 }
  369 
  370 static void
  371 uark_cfg_param(struct ucom_softc *ucom, struct termios *t)
  372 {
  373         struct uark_softc *sc = ucom->sc_parent;
  374         uint32_t speed = t->c_ospeed;
  375         uint16_t data;
  376 
  377         /*
  378          * NOTE: When reverse computing the baud rate from the "data" all
  379          * allowed baud rates are within 3% of the initial baud rate.
  380          */
  381         data = (UARK_BAUD_REF + (speed / 2)) / speed;
  382 
  383         uark_cfg_write(sc, 3, 0x83);
  384         uark_cfg_write(sc, 0, data & 0xFF);
  385         uark_cfg_write(sc, 1, data >> 8);
  386         uark_cfg_write(sc, 3, 0x03);
  387 
  388         if (t->c_cflag & CSTOPB)
  389                 data = UARK_STOP_BITS_2;
  390         else
  391                 data = UARK_STOP_BITS_1;
  392 
  393         if (t->c_cflag & PARENB) {
  394                 if (t->c_cflag & PARODD)
  395                         data |= UARK_PARITY_ODD;
  396                 else
  397                         data |= UARK_PARITY_EVEN;
  398         } else
  399                 data |= UARK_PARITY_NONE;
  400 
  401         switch (t->c_cflag & CSIZE) {
  402         case CS5:
  403                 data |= UARK_SET_DATA_BITS(5);
  404                 break;
  405         case CS6:
  406                 data |= UARK_SET_DATA_BITS(6);
  407                 break;
  408         case CS7:
  409                 data |= UARK_SET_DATA_BITS(7);
  410                 break;
  411         default:
  412         case CS8:
  413                 data |= UARK_SET_DATA_BITS(8);
  414                 break;
  415         }
  416         uark_cfg_write(sc, 3, 0x00);
  417         uark_cfg_write(sc, 3, data);
  418 }
  419 
  420 static void
  421 uark_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
  422 {
  423         struct uark_softc *sc = ucom->sc_parent;
  424 
  425         /* XXX Note: sc_lsr is always zero */
  426         *lsr = sc->sc_lsr;
  427         *msr = sc->sc_msr;
  428 }
  429 
  430 static void
  431 uark_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
  432 {
  433         struct uark_softc *sc = ucom->sc_parent;
  434 
  435         DPRINTF("onoff=%d\n", onoff);
  436 
  437         uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
  438 }
  439 
  440 static void
  441 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
  442 {
  443         struct usb_device_request req;
  444         usb_error_t err;
  445 
  446         req.bmRequestType = UARK_WRITE;
  447         req.bRequest = UARK_REQUEST;
  448         USETW(req.wValue, value);
  449         USETW(req.wIndex, index);
  450         USETW(req.wLength, 0);
  451 
  452         err = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
  453             &req, NULL, 0, 1000);
  454         if (err) {
  455                 DPRINTFN(0, "device request failed, err=%s "
  456                     "(ignored)\n", usbd_errstr(err));
  457         }
  458 }
  459 
  460 static void
  461 uark_poll(struct ucom_softc *ucom)
  462 {
  463         struct uark_softc *sc = ucom->sc_parent;
  464         usbd_transfer_poll(sc->sc_xfer, UARK_N_TRANSFER);
  465 }

Cache object: 40d092e03e3c593ab3ce722011ce74dc


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