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/misc/uled.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 /*-
    2  * Copyright (c) 2014, 2017 Kevin Lo
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions, and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/stdint.h>
   32 #include <sys/stddef.h>
   33 #include <sys/param.h>
   34 #include <sys/queue.h>
   35 #include <sys/types.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/bus.h>
   39 #include <sys/module.h>
   40 #include <sys/lock.h>
   41 #include <sys/mutex.h>
   42 #include <sys/condvar.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/sx.h>
   45 #include <sys/unistd.h>
   46 #include <sys/callout.h>
   47 #include <sys/malloc.h>
   48 #include <sys/priv.h>
   49 #include <sys/conf.h>
   50 #include <sys/fcntl.h>
   51 
   52 #include <dev/usb/usb.h>
   53 #include <dev/usb/usbdi.h>
   54 #include <dev/usb/usbhid.h>
   55 #include "usbdevs.h"
   56 
   57 #define USB_DEBUG_VAR usb_debug
   58 #include <dev/usb/usb_debug.h>
   59 
   60 #include <dev/usb/uled_ioctl.h>
   61 
   62 struct uled_softc {
   63         struct usb_fifo_sc      sc_fifo;
   64         struct mtx              sc_mtx;
   65 
   66         struct usb_device       *sc_udev;
   67         struct uled_color       sc_color;
   68 
   69         uint8_t                 sc_state;
   70 #define ULED_ENABLED    0x01
   71 
   72         int                     sc_flags;
   73 #define ULED_FLAG_BLINK1        0x0001
   74 };
   75 
   76 /* Initial commands. */
   77 static uint8_t blink1[] = { 0x1, 'v', 0, 0, 0, 0, 0, 0 };
   78 static uint8_t dl100b[] = { 0x1f, 0x2, 0, 0x5f, 0, 0, 0x1a, 0x3 };
   79 
   80 /* Prototypes. */
   81 static device_probe_t   uled_probe;
   82 static device_attach_t  uled_attach;
   83 static device_detach_t  uled_detach;
   84 
   85 static usb_fifo_open_t  uled_open;
   86 static usb_fifo_close_t uled_close;
   87 static usb_fifo_ioctl_t uled_ioctl;
   88 
   89 static struct usb_fifo_methods uled_fifo_methods = {
   90         .f_open = &uled_open,
   91         .f_close = &uled_close,
   92         .f_ioctl = &uled_ioctl,
   93         .basename[0] = "uled",
   94 };
   95 
   96 static usb_error_t      uled_ctrl_msg(struct uled_softc *, uint8_t, uint8_t,
   97                             uint16_t, uint16_t, void *, uint16_t);
   98 static int              uled_enable(struct uled_softc *);
   99 
  100 static device_method_t uled_methods[] = {
  101         DEVMETHOD(device_probe,         uled_probe),
  102         DEVMETHOD(device_attach,        uled_attach),
  103         DEVMETHOD(device_detach,        uled_detach),
  104 
  105         DEVMETHOD_END
  106 };
  107 
  108 static driver_t uled_driver = {
  109         .name = "uled",
  110         .methods = uled_methods,
  111         .size = sizeof(struct uled_softc),
  112 };
  113 
  114 static const STRUCT_USB_HOST_ID uled_devs[] = {
  115 #define ULED_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
  116         ULED_DEV(DREAMLINK, DL100B, 0),
  117         ULED_DEV(THINGM, BLINK1, ULED_FLAG_BLINK1),
  118 #undef ULED_DEV
  119 };
  120 
  121 DRIVER_MODULE(uled, uhub, uled_driver, NULL, NULL);
  122 MODULE_DEPEND(uled, usb, 1, 1, 1);
  123 MODULE_VERSION(uled, 1);
  124 USB_PNP_HOST_INFO(uled_devs);
  125 
  126 static int
  127 uled_probe(device_t dev)
  128 {
  129         struct usb_attach_arg *uaa;
  130 
  131         uaa = device_get_ivars(dev);
  132         if (uaa->usb_mode != USB_MODE_HOST)
  133                 return (ENXIO);
  134         if (uaa->info.bInterfaceClass != UICLASS_HID)
  135                 return (ENXIO);
  136 
  137         return (usbd_lookup_id_by_uaa(uled_devs, sizeof(uled_devs), uaa));
  138 }
  139 
  140 static int
  141 uled_attach(device_t dev)
  142 {
  143         struct usb_attach_arg *uaa;
  144         struct uled_softc *sc;
  145         int unit;
  146         usb_error_t error;
  147 
  148         uaa = device_get_ivars(dev);
  149         sc = device_get_softc(dev);
  150         unit = device_get_unit(dev);
  151         sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
  152 
  153         device_set_usb_desc(dev);
  154         mtx_init(&sc->sc_mtx, "uled lock", NULL, MTX_DEF | MTX_RECURSE);
  155 
  156         sc->sc_udev = uaa->device;
  157 
  158         error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
  159             &uled_fifo_methods, &sc->sc_fifo, unit, -1,
  160             uaa->info.bIfaceIndex, UID_ROOT, GID_OPERATOR, 0644);
  161         if (error != 0)
  162                 goto detach;
  163 
  164         sc->sc_color.red = 0;
  165         sc->sc_color.green = 0;
  166         sc->sc_color.blue = 0;
  167 
  168         return (0);
  169 
  170 detach:
  171         uled_detach(dev);
  172         return (ENOMEM);
  173 }
  174 
  175 static int
  176 uled_detach(device_t dev)
  177 {
  178         struct uled_softc *sc;
  179 
  180         sc = device_get_softc(dev);
  181         usb_fifo_detach(&sc->sc_fifo);
  182         mtx_destroy(&sc->sc_mtx);
  183         return (0);
  184 }
  185 
  186 static usb_error_t
  187 uled_ctrl_msg(struct uled_softc *sc, uint8_t rt, uint8_t reqno,
  188     uint16_t value, uint16_t index, void *buf, uint16_t buflen)
  189 {
  190         struct usb_device_request req;
  191 
  192         req.bmRequestType = rt;
  193         req.bRequest = reqno;
  194         USETW(req.wValue, value);
  195         USETW(req.wIndex, index);
  196         USETW(req.wLength, buflen);
  197 
  198         return (usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, buf,
  199             0, NULL, 2000));
  200 }
  201 
  202 static int
  203 uled_enable(struct uled_softc *sc)
  204 {
  205         uint8_t *cmdbuf;
  206         int error;
  207 
  208         cmdbuf = (sc->sc_flags & ULED_FLAG_BLINK1) ? blink1 : dl100b;
  209 
  210         sc->sc_state |= ULED_ENABLED;
  211         mtx_lock(&sc->sc_mtx);
  212         error = uled_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_SET_REPORT,
  213             0x200, 0, cmdbuf, sizeof(cmdbuf));
  214         mtx_unlock(&sc->sc_mtx);
  215         return (error);
  216 }
  217 
  218 static int
  219 uled_open(struct usb_fifo *fifo, int fflags)
  220 {
  221         if (fflags & FREAD) {
  222                 struct uled_softc *sc;
  223                 int rc;
  224 
  225                 sc = usb_fifo_softc(fifo);
  226                 if (sc->sc_state & ULED_ENABLED)
  227                         return (EBUSY);
  228                 if ((rc = uled_enable(sc)) != 0)
  229                         return (rc);
  230         }
  231         return (0);
  232 }
  233 
  234 static void
  235 uled_close(struct usb_fifo *fifo, int fflags)
  236 {
  237         if (fflags & FREAD) {
  238                 struct uled_softc *sc;
  239 
  240                 sc = usb_fifo_softc(fifo);
  241                 sc->sc_state &= ~ULED_ENABLED;
  242         }
  243 }
  244 
  245 static int
  246 uled_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
  247 {
  248         struct uled_softc *sc;
  249         struct uled_color color;
  250         int error;
  251 
  252         sc = usb_fifo_softc(fifo);
  253         error = 0;
  254 
  255         mtx_lock(&sc->sc_mtx);
  256 
  257         switch(cmd) {
  258         case ULED_GET_COLOR:
  259                 *(struct uled_color *)addr = sc->sc_color;
  260                 break;
  261         case ULED_SET_COLOR:
  262                 color = *(struct uled_color *)addr;
  263                 uint8_t buf[8];
  264 
  265                 sc->sc_color.red = color.red;
  266                 sc->sc_color.green = color.green;
  267                 sc->sc_color.blue = color.blue;
  268 
  269                 if (sc->sc_flags & ULED_FLAG_BLINK1) {
  270                         buf[0] = 0x1;
  271                         buf[1] = 'n';
  272                         buf[2] = color.red;
  273                         buf[3] = color.green;
  274                         buf[4] = color.blue;
  275                         buf[5] = buf[6] = buf[7] = 0;
  276                 } else {
  277                         buf[0] = color.red;
  278                         buf[1] = color.green;
  279                         buf[2] = color.blue;
  280                         buf[3] = buf[4] = buf[5] = 0;
  281                         buf[6] = 0x1a;
  282                         buf[7] = 0x05;
  283                 }
  284                 error = uled_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE,
  285                     UR_SET_REPORT, 0x200, 0, buf, sizeof(buf));
  286                 break;
  287         default:
  288                 error = ENOTTY;
  289                 break;
  290         }
  291 
  292         mtx_unlock(&sc->sc_mtx);
  293         return (error);
  294 }

Cache object: 68d6be3aa4dcfd168a131fd4661e3499


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