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/uirda.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: uirda.c,v 1.16 2003/06/29 22:30:57 fvdl Exp $  */
    2 
    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 Lennart Augustsson (lennart@augustsson.net).
    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 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: uirda.c,v 1.16 2003/06/29 22:30:57 fvdl Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/device.h>
   46 #include <sys/lock.h>
   47 #include <sys/ioctl.h>
   48 #include <sys/conf.h>
   49 #include <sys/file.h>
   50 #include <sys/poll.h>
   51 #include <sys/select.h>
   52 #include <sys/proc.h>
   53 
   54 #include <dev/usb/usb.h>
   55 #include <dev/usb/usbdi.h>
   56 #include <dev/usb/usbdi_util.h>
   57 #include <dev/usb/usbdevs.h>
   58 
   59 #include <dev/ir/ir.h>
   60 #include <dev/ir/irdaio.h>
   61 #include <dev/ir/irframevar.h>
   62 
   63 #ifdef UIRDA_DEBUG
   64 #define DPRINTF(x)      if (uirdadebug) logprintf x
   65 #define DPRINTFN(n,x)   if (uirdadebug>(n)) logprintf x
   66 int     uirdadebug = 0;
   67 #else
   68 #define DPRINTF(x)
   69 #define DPRINTFN(n,x)
   70 #endif
   71 
   72 /*
   73  * Protocol related definitions
   74  */
   75 
   76 #define UIRDA_INPUT_HEADER_SIZE 1
   77 /* Inbound header byte */
   78 #define UIRDA_MEDIA_BUSY        0x80
   79 #define UIRDA_SPEED_MASK        0x0f
   80 #define UIRDA_NO_SPEED          0x00
   81 #define UIRDA_2400              0x01
   82 #define UIRDA_9600              0x02
   83 #define UIRDA_19200             0x03
   84 #define UIRDA_38400             0x04
   85 #define UIRDA_57600             0x05
   86 #define UIRDA_115200            0x06
   87 #define UIRDA_576000            0x07
   88 #define UIRDA_1152000           0x08
   89 #define UIRDA_4000000           0x09
   90 
   91 #define UIRDA_OUTPUT_HEADER_SIZE 1
   92 /* Outbound header byte */
   93 #define UIRDA_EB_NO_CHANGE      0x00
   94 #define UIRDA_EB_48             0x10
   95 #define UIRDA_EB_24             0x20
   96 #define UIRDA_EB_12             0x30
   97 #define UIRDA_EB_6              0x40
   98 #define UIRDA_EB_3              0x50
   99 #define UIRDA_EB_2              0x60
  100 #define UIRDA_EB_1              0x70
  101 #define UIRDA_EB_0              0x80
  102 /* Speeds as above */
  103 
  104 /* Class specific requests */
  105 #define UR_IRDA_RECEIVING               0x01    /* Receive in progress? */
  106 #define UR_IRDA_CHECK_MEDIA_BUSY        0x03
  107 #define UR_IRDA_SET_RATE_SNIFF          0x04    /* opt */
  108 #define UR_IRDA_SET_UNICAST_LIST        0x05    /* opt */
  109 #define UR_IRDA_GET_DESC                0x06
  110 
  111 typedef struct {
  112         uByte           bLength;
  113         uByte           bDescriptorType;
  114 #define UDESC_IRDA      0x21
  115         uWord           bcdSpecRevision;
  116         uByte           bmDataSize;
  117 #define UI_DS_2048      0x20
  118 #define UI_DS_1024      0x10
  119 #define UI_DS_512       0x08
  120 #define UI_DS_256       0x04
  121 #define UI_DS_128       0x02
  122 #define UI_DS_64        0x01
  123         uByte           bmWindowSize;
  124 #define UI_WS_7         0x40
  125 #define UI_WS_6         0x20
  126 #define UI_WS_5         0x10
  127 #define UI_WS_4         0x08
  128 #define UI_WS_3         0x04
  129 #define UI_WS_2         0x02
  130 #define UI_WS_1         0x01
  131         uByte           bmMinTurnaroundTime;
  132 #define UI_TA_0         0x80
  133 #define UI_TA_10        0x40
  134 #define UI_TA_50        0x20
  135 #define UI_TA_100       0x10
  136 #define UI_TA_500       0x08
  137 #define UI_TA_1000      0x04
  138 #define UI_TA_5000      0x02
  139 #define UI_TA_10000     0x01
  140         uWord           wBaudRate;
  141 #define UI_BR_4000000   0x0100
  142 #define UI_BR_1152000   0x0080
  143 #define UI_BR_576000    0x0040
  144 #define UI_BR_115200    0x0020
  145 #define UI_BR_57600     0x0010
  146 #define UI_BR_38400     0x0008
  147 #define UI_BR_19200     0x0004
  148 #define UI_BR_9600      0x0002
  149 #define UI_BR_2400      0x0001
  150         uByte           bmAdditionalBOFs;
  151 #define UI_EB_0         0x80
  152 #define UI_EB_1         0x40
  153 #define UI_EB_2         0x20
  154 #define UI_EB_3         0x10
  155 #define UI_EB_6         0x08
  156 #define UI_EB_12        0x04
  157 #define UI_EB_24        0x02
  158 #define UI_EB_48        0x01
  159         uByte           bIrdaSniff;
  160         uByte           bMaxUnicastList;
  161 } UPACKED usb_irda_descriptor_t;
  162 #define USB_IRDA_DESCRIPTOR_SIZE 12
  163 
  164 
  165 #define UIRDA_NEBOFS 8
  166 static struct {
  167         int count;
  168         int mask;
  169         int header;
  170 } uirda_ebofs[UIRDA_NEBOFS] = {
  171         { 0, UI_EB_0, UIRDA_EB_0 },
  172         { 1, UI_EB_1, UIRDA_EB_1 },
  173         { 2, UI_EB_2, UIRDA_EB_2 },
  174         { 3, UI_EB_3, UIRDA_EB_3 },
  175         { 6, UI_EB_6, UIRDA_EB_6 },
  176         { 12, UI_EB_12, UIRDA_EB_12 },
  177         { 24, UI_EB_24, UIRDA_EB_24 },
  178         { 48, UI_EB_48, UIRDA_EB_48 }
  179 };
  180 
  181 #define UIRDA_NSPEEDS 9
  182 static struct {
  183         int speed;
  184         int mask;
  185         int header;
  186 } uirda_speeds[UIRDA_NSPEEDS] = {
  187         { 4000000, UI_BR_4000000, UIRDA_4000000 },
  188         { 1152000, UI_BR_1152000, UIRDA_1152000 },
  189         { 576000, UI_BR_576000, UIRDA_576000 },
  190         { 115200, UI_BR_115200, UIRDA_115200 },
  191         { 57600, UI_BR_57600, UIRDA_57600 },
  192         { 38400, UI_BR_38400, UIRDA_38400 },
  193         { 19200, UI_BR_19200, UIRDA_19200 },
  194         { 9600, UI_BR_9600, UIRDA_9600 },
  195         { 2400, UI_BR_2400, UIRDA_2400 },
  196 };
  197 
  198 struct uirda_softc {
  199         USBBASEDEVICE           sc_dev;
  200         usbd_device_handle      sc_udev;
  201         usbd_interface_handle   sc_iface;
  202 
  203         struct lock             sc_rd_buf_lk;
  204         u_int8_t                *sc_rd_buf;
  205         int                     sc_rd_addr;
  206         usbd_pipe_handle        sc_rd_pipe;
  207         usbd_xfer_handle        sc_rd_xfer;
  208         struct selinfo          sc_rd_sel;
  209         u_int                   sc_rd_count;
  210         u_char                  sc_rd_err;
  211 
  212         struct lock             sc_wr_buf_lk;
  213         u_int8_t                *sc_wr_buf;
  214         int                     sc_wr_addr;
  215         usbd_xfer_handle        sc_wr_xfer;
  216         usbd_pipe_handle        sc_wr_pipe;
  217         int                     sc_wr_hdr;
  218         struct selinfo          sc_wr_sel;
  219 
  220         struct device           *sc_child;
  221         struct irda_params      sc_params;
  222         usb_irda_descriptor_t   sc_irdadesc;
  223 
  224         int                     sc_refcnt;
  225         char                    sc_dying;
  226 };
  227 
  228 #define UIRDA_WR_TIMEOUT 200
  229 
  230 int uirda_open(void *h, int flag, int mode, usb_proc_ptr p);
  231 int uirda_close(void *h, int flag, int mode, usb_proc_ptr p);
  232 int uirda_read(void *h, struct uio *uio, int flag);
  233 int uirda_write(void *h, struct uio *uio, int flag);
  234 int uirda_set_params(void *h, struct irda_params *params);
  235 int uirda_get_speeds(void *h, int *speeds);
  236 int uirda_get_turnarounds(void *h, int *times);
  237 int uirda_poll(void *h, int events, usb_proc_ptr p);
  238 int uirda_kqfilter(void *h, struct knote *kn);
  239 
  240 struct irframe_methods uirda_methods = {
  241         uirda_open, uirda_close, uirda_read, uirda_write, uirda_poll,
  242         uirda_kqfilter, uirda_set_params, uirda_get_speeds,
  243         uirda_get_turnarounds
  244 };
  245 
  246 void uirda_rd_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  247                  usbd_status status);
  248 usbd_status uirda_start_read(struct uirda_softc *sc);
  249 
  250 usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type);
  251 
  252 /*
  253  * These devices don't quite follow the spec.  Speed changing is broken
  254  * and they don't handle windows.
  255  * But we change speed in a safe way, and don't use windows now.
  256  * Some devices also seem to have an interrupt pipe that can be ignored.
  257  *
  258  * Table information taken from Linux driver.
  259  */
  260 Static const struct usb_devno uirda_devs[] = {
  261         { USB_VENDOR_ACTISYS, USB_PRODUCT_ACTISYS_IR2000U },
  262         { USB_VENDOR_EXTENDED, USB_PRODUCT_EXTENDED_XTNDACCESS },
  263         { USB_VENDOR_KAWATSU, USB_PRODUCT_KAWATSU_KC180 },
  264 };
  265 #define uirda_lookup(v, p) (usb_lookup(uirda_devs, v, p))
  266 
  267 USB_DECLARE_DRIVER(uirda);
  268 
  269 USB_MATCH(uirda)
  270 {
  271         USB_MATCH_START(uirda, uaa);
  272         usb_interface_descriptor_t *id;
  273 
  274         DPRINTFN(50,("uirda_match\n"));
  275 
  276         if (uaa->iface == NULL)
  277                 return (UMATCH_NONE);
  278 
  279         if (uirda_lookup(uaa->vendor, uaa->product) != NULL)
  280                 return (UMATCH_VENDOR_PRODUCT);
  281 
  282         id = usbd_get_interface_descriptor(uaa->iface);
  283         if (id != NULL &&
  284             id->bInterfaceClass == UICLASS_APPL_SPEC &&
  285             id->bInterfaceSubClass == UISUBCLASS_IRDA &&
  286             id->bInterfaceProtocol == UIPROTO_IRDA)
  287                 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
  288         return (UMATCH_NONE);
  289 }
  290 
  291 USB_ATTACH(uirda)
  292 {
  293         USB_ATTACH_START(uirda, sc, uaa);
  294         usbd_device_handle      dev = uaa->device;
  295         usbd_interface_handle   iface = uaa->iface;
  296         char                    devinfo[1024];
  297         usb_endpoint_descriptor_t *ed;
  298         usbd_status             err;
  299         u_int8_t                epcount;
  300         u_int                   specrev;
  301         int                     i;
  302         struct ir_attach_args   ia;
  303 
  304         DPRINTFN(10,("uirda_attach: sc=%p\n", sc));
  305 
  306         usbd_devinfo(dev, 0, devinfo);
  307         USB_ATTACH_SETUP;
  308         printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
  309 
  310         sc->sc_udev = dev;
  311         sc->sc_iface = iface;
  312 
  313         epcount = 0;
  314         (void)usbd_endpoint_count(iface, &epcount);
  315 
  316         sc->sc_rd_addr = -1;
  317         sc->sc_wr_addr = -1;
  318         for (i = 0; i < epcount; i++) {
  319                 ed = usbd_interface2endpoint_descriptor(iface, i);
  320                 if (ed == NULL) {
  321                         printf("%s: couldn't get ep %d\n",
  322                             USBDEVNAME(sc->sc_dev), i);
  323                         USB_ATTACH_ERROR_RETURN;
  324                 }
  325                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  326                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  327                         sc->sc_rd_addr = ed->bEndpointAddress;
  328                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  329                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  330                         sc->sc_wr_addr = ed->bEndpointAddress;
  331                 }
  332         }
  333         if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) {
  334                 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
  335                 USB_ATTACH_ERROR_RETURN;
  336         }
  337 
  338         /* Get the IrDA descriptor */
  339         err = usbd_get_desc(sc->sc_udev, UDESC_IRDA, 0,
  340                   USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc);
  341         if (err) {
  342                 /* maybe it's embedded in the config desc? */
  343                 void *d = usb_find_desc(sc->sc_udev, UDESC_IRDA);
  344                 if (d == NULL) {
  345                         printf("%s: Cannot get IrDA descriptor\n",
  346                                USBDEVNAME(sc->sc_dev));
  347                         USB_ATTACH_ERROR_RETURN;
  348                 }
  349                 memcpy(&sc->sc_irdadesc, d, USB_IRDA_DESCRIPTOR_SIZE);
  350         }
  351         DPRINTF(("uirda_attach: bmDataSize=0x%02x bmWindowSize=0x%02x "
  352                  "bmMinTurnaroundTime=0x%02x wBaudRate=0x%04x "
  353                  "bmAdditionalBOFs=0x%02x bIrdaSniff=%d bMaxUnicastList=%d\n",
  354                  sc->sc_irdadesc.bmDataSize,
  355                  sc->sc_irdadesc.bmWindowSize,
  356                  sc->sc_irdadesc.bmMinTurnaroundTime,
  357                  UGETW(sc->sc_irdadesc.wBaudRate),
  358                  sc->sc_irdadesc.bmAdditionalBOFs,
  359                  sc->sc_irdadesc.bIrdaSniff,
  360                  sc->sc_irdadesc.bMaxUnicastList));
  361 
  362         specrev = UGETW(sc->sc_irdadesc.bcdSpecRevision);
  363         printf("%s: USB-IrDA protocol version %x.%02x\n",
  364                USBDEVNAME(sc->sc_dev), specrev >> 8, specrev & 0xff);
  365 
  366         DPRINTFN(10, ("uirda_attach: %p\n", sc->sc_udev));
  367 
  368         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  369                            USBDEV(sc->sc_dev));
  370 
  371         lockinit(&sc->sc_wr_buf_lk, PZERO, "iirwrl", 0, 0);
  372         lockinit(&sc->sc_rd_buf_lk, PZERO, "uirrdl", 0, 0);
  373 
  374         ia.ia_type = IR_TYPE_IRFRAME;
  375         ia.ia_methods = &uirda_methods;
  376         ia.ia_handle = sc;
  377 
  378         sc->sc_child = config_found(self, &ia, ir_print);
  379 
  380         USB_ATTACH_SUCCESS_RETURN;
  381 }
  382 
  383 USB_DETACH(uirda)
  384 {
  385         USB_DETACH_START(uirda, sc);
  386         int s;
  387         int rv = 0;
  388 
  389         DPRINTF(("uirda_detach: sc=%p flags=%d\n", sc, flags));
  390 
  391         sc->sc_dying = 1;
  392         /* Abort all pipes.  Causes processes waiting for transfer to wake. */
  393         if (sc->sc_rd_pipe != NULL) {
  394                 usbd_abort_pipe(sc->sc_rd_pipe);
  395                 usbd_close_pipe(sc->sc_rd_pipe);
  396                 sc->sc_rd_pipe = NULL;
  397         }
  398         if (sc->sc_wr_pipe != NULL) {
  399                 usbd_abort_pipe(sc->sc_wr_pipe);
  400                 usbd_close_pipe(sc->sc_wr_pipe);
  401                 sc->sc_wr_pipe = NULL;
  402         }
  403         wakeup(&sc->sc_rd_count);
  404 
  405         s = splusb();
  406         if (--sc->sc_refcnt >= 0) {
  407                 /* Wait for processes to go away. */
  408                 usb_detach_wait(USBDEV(sc->sc_dev));
  409         }
  410         splx(s);
  411 
  412         if (sc->sc_child != NULL) {
  413                 rv = config_detach(sc->sc_child, flags);
  414                 sc->sc_child = NULL;
  415         }
  416 
  417         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  418                            USBDEV(sc->sc_dev));
  419 
  420         return (rv);
  421 }
  422 
  423 int
  424 uirda_activate(device_ptr_t self, enum devact act)
  425 {
  426         struct uirda_softc *sc = (struct uirda_softc *)self;
  427         int error = 0;
  428 
  429         switch (act) {
  430         case DVACT_ACTIVATE:
  431                 return (EOPNOTSUPP);
  432                 break;
  433 
  434         case DVACT_DEACTIVATE:
  435                 sc->sc_dying = 1;
  436                 if (sc->sc_child != NULL)
  437                         error = config_deactivate(sc->sc_child);
  438                 break;
  439         }
  440         return (error);
  441 }
  442 
  443 int
  444 uirda_open(void *h, int flag, int mode, usb_proc_ptr p)
  445 {
  446         struct uirda_softc *sc = h;
  447         int error;
  448         usbd_status err;
  449 
  450         DPRINTF(("%s: sc=%p\n", __func__, sc));
  451 
  452         err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe);
  453         if (err) {
  454                 error = EIO;
  455                 goto bad1;
  456         }
  457         err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe);
  458         if (err) {
  459                 error = EIO;
  460                 goto bad2;
  461         }
  462         sc->sc_rd_xfer = usbd_alloc_xfer(sc->sc_udev);
  463         if (sc->sc_rd_xfer == NULL) {
  464                 error = ENOMEM;
  465                 goto bad3;
  466         }
  467         sc->sc_wr_xfer = usbd_alloc_xfer(sc->sc_udev);
  468         if (sc->sc_wr_xfer == NULL) {
  469                 error = ENOMEM;
  470                 goto bad4;
  471         }
  472         sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer,
  473                             IRDA_MAX_FRAME_SIZE + UIRDA_INPUT_HEADER_SIZE);
  474         if (sc->sc_rd_buf == NULL) {
  475                 error = ENOMEM;
  476                 goto bad5;
  477         }
  478         sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer,
  479                             IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE);
  480         if (sc->sc_wr_buf == NULL) {
  481                 error = ENOMEM;
  482                 goto bad5;
  483         }
  484         sc->sc_rd_count = 0;
  485         sc->sc_rd_err = 0;
  486         sc->sc_params.speed = 0;
  487         sc->sc_params.ebofs = 0;
  488         sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE;
  489         sc->sc_wr_hdr = -1;
  490 
  491         err = uirda_start_read(sc);
  492         /* XXX check err */
  493 
  494         return (0);
  495 
  496 bad5:
  497         usbd_free_xfer(sc->sc_wr_xfer);
  498         sc->sc_wr_xfer = NULL;
  499 bad4:
  500         usbd_free_xfer(sc->sc_rd_xfer);
  501         sc->sc_rd_xfer = NULL;
  502 bad3:
  503         usbd_close_pipe(sc->sc_wr_pipe);
  504         sc->sc_wr_pipe = NULL;
  505 bad2:
  506         usbd_close_pipe(sc->sc_rd_pipe);
  507         sc->sc_rd_pipe = NULL;
  508 bad1:
  509         return (error);
  510 }
  511 
  512 int
  513 uirda_close(void *h, int flag, int mode, usb_proc_ptr p)
  514 {
  515         struct uirda_softc *sc = h;
  516 
  517         DPRINTF(("%s: sc=%p\n", __func__, sc));
  518 
  519         if (sc->sc_rd_pipe != NULL) {
  520                 usbd_abort_pipe(sc->sc_rd_pipe);
  521                 usbd_close_pipe(sc->sc_rd_pipe);
  522                 sc->sc_rd_pipe = NULL;
  523         }
  524         if (sc->sc_wr_pipe != NULL) {
  525                 usbd_abort_pipe(sc->sc_wr_pipe);
  526                 usbd_close_pipe(sc->sc_wr_pipe);
  527                 sc->sc_wr_pipe = NULL;
  528         }
  529         if (sc->sc_rd_xfer != NULL) {
  530                 usbd_free_xfer(sc->sc_rd_xfer);
  531                 sc->sc_rd_xfer = NULL;
  532                 sc->sc_rd_buf = NULL;
  533         }
  534         if (sc->sc_wr_xfer != NULL) {
  535                 usbd_free_xfer(sc->sc_wr_xfer);
  536                 sc->sc_wr_xfer = NULL;
  537                 sc->sc_wr_buf = NULL;
  538         }
  539 
  540         return (0);
  541 }
  542 
  543 int
  544 uirda_read(void *h, struct uio *uio, int flag)
  545 {
  546         struct uirda_softc *sc = h;
  547         usbd_status err;
  548         int s;
  549         int error;
  550         u_int n;
  551 
  552         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  553 
  554         if (sc->sc_dying)
  555                 return (EIO);
  556 
  557 #ifdef DIAGNOSTIC
  558         if (sc->sc_rd_buf == NULL)
  559                 return (EINVAL);
  560 #endif
  561 
  562         sc->sc_refcnt++;
  563 
  564         do {
  565                 s = splusb();
  566                 while (sc->sc_rd_count == 0) {
  567                         DPRINTFN(5,("uirda_read: calling tsleep()\n"));
  568                         error = tsleep(&sc->sc_rd_count, PZERO | PCATCH,
  569                                        "uirdrd", 0);
  570                         if (sc->sc_dying)
  571                                 error = EIO;
  572                         if (error) {
  573                                 splx(s);
  574                                 DPRINTF(("uirda_read: tsleep() = %d\n", error));
  575                                 goto ret;
  576                         }
  577                 }
  578                 splx(s);
  579 
  580                 lockmgr(&sc->sc_rd_buf_lk, LK_EXCLUSIVE, NULL);
  581                 n = sc->sc_rd_count - UIRDA_INPUT_HEADER_SIZE;
  582                 DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__,
  583                             sc, n, sc->sc_rd_buf[0]));
  584                 if (n > uio->uio_resid)
  585                         error = EINVAL;
  586                 else
  587                         error = uiomove(sc->sc_rd_buf+UIRDA_INPUT_HEADER_SIZE,
  588                                         n, uio);
  589                 sc->sc_rd_count = 0;
  590                 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL);
  591 
  592                 err = uirda_start_read(sc);
  593                 /* XXX check err */
  594 
  595         } while (n == 0);
  596 
  597         DPRINTFN(1,("uirda_read: return %d\n", error));
  598 
  599  ret:
  600         if (--sc->sc_refcnt < 0)
  601                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  602         return (error);
  603 }
  604 
  605 int
  606 uirda_write(void *h, struct uio *uio, int flag)
  607 {
  608         struct uirda_softc *sc = h;
  609         usbd_status err;
  610         u_int32_t n;
  611         int error = 0;
  612 
  613         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  614 
  615         if (sc->sc_dying)
  616                 return (EIO);
  617 
  618 #ifdef DIAGNOSTIC
  619         if (sc->sc_wr_buf == NULL)
  620                 return (EINVAL);
  621 #endif
  622 
  623         n = uio->uio_resid;
  624         if (n > sc->sc_params.maxsize)
  625                 return (EINVAL);
  626 
  627         sc->sc_refcnt++;
  628         lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL);
  629 
  630         sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED;
  631         error = uiomove(sc->sc_wr_buf + UIRDA_OUTPUT_HEADER_SIZE, n, uio);
  632         if (!error) {
  633                 DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n));
  634 
  635                 n++;
  636                 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
  637                           USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
  638                           UIRDA_WR_TIMEOUT,
  639                           sc->sc_wr_buf, &n, "uirdawr");
  640                 DPRINTFN(2, ("uirdawrite: err=%d\n", err));
  641                 if (err) {
  642                         if (err == USBD_INTERRUPTED)
  643                                 error = EINTR;
  644                         else if (err == USBD_TIMEOUT)
  645                                 error = ETIMEDOUT;
  646                         else
  647                                 error = EIO;
  648                 }
  649         }
  650 
  651         lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL);
  652         if (--sc->sc_refcnt < 0)
  653                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  654 
  655         DPRINTFN(1,("%s: sc=%p done\n", __func__, sc));
  656         return (error);
  657 }
  658 
  659 int
  660 uirda_poll(void *h, int events, usb_proc_ptr p)
  661 {
  662         struct uirda_softc *sc = h;
  663         int revents = 0;
  664         int s;
  665 
  666         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  667 
  668         s = splusb();
  669         if (events & (POLLOUT | POLLWRNORM))
  670                 revents |= events & (POLLOUT | POLLWRNORM);
  671         if (events & (POLLIN | POLLRDNORM)) {
  672                 if (sc->sc_rd_count != 0) {
  673                         DPRINTFN(2,("%s: have data\n", __func__));
  674                         revents |= events & (POLLIN | POLLRDNORM);
  675                 } else {
  676                         DPRINTFN(2,("%s: recording select\n", __func__));
  677                         selrecord(p, &sc->sc_rd_sel);
  678                 }
  679         }
  680         splx(s);
  681 
  682         return (revents);
  683 }
  684 
  685 static void
  686 filt_uirdardetach(struct knote *kn)
  687 {
  688         struct uirda_softc *sc = kn->kn_hook;
  689         int s;
  690 
  691         s = splusb();
  692         SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext);
  693         splx(s);
  694 }
  695 
  696 static int
  697 filt_uirdaread(struct knote *kn, long hint)
  698 {
  699         struct uirda_softc *sc = kn->kn_hook;
  700 
  701         kn->kn_data = sc->sc_rd_count;
  702         return (kn->kn_data > 0);
  703 }
  704 
  705 static void
  706 filt_uirdawdetach(struct knote *kn)
  707 {
  708         struct uirda_softc *sc = kn->kn_hook;
  709         int s;
  710 
  711         s = splusb();
  712         SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext);
  713         splx(s);
  714 }
  715 
  716 static const struct filterops uirdaread_filtops =
  717         { 1, NULL, filt_uirdardetach, filt_uirdaread };
  718 static const struct filterops uirdawrite_filtops =
  719         { 1, NULL, filt_uirdawdetach, filt_seltrue };
  720 
  721 int
  722 uirda_kqfilter(void *h, struct knote *kn)
  723 {
  724         struct uirda_softc *sc = kn->kn_hook;
  725         struct klist *klist;
  726         int s;
  727 
  728         switch (kn->kn_filter) {
  729         case EVFILT_READ:
  730                 klist = &sc->sc_rd_sel.sel_klist;
  731                 kn->kn_fop = &uirdaread_filtops;
  732                 break;
  733         case EVFILT_WRITE:
  734                 klist = &sc->sc_wr_sel.sel_klist;
  735                 kn->kn_fop = &uirdawrite_filtops;
  736                 break;
  737         default:
  738                 return (1);
  739         }
  740 
  741         kn->kn_hook = sc;
  742 
  743         s = splusb();
  744         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  745         splx(s);
  746 
  747         return (0);
  748 }
  749 
  750 int
  751 uirda_set_params(void *h, struct irda_params *p)
  752 {
  753         struct uirda_softc *sc = h;
  754         usbd_status err;
  755         int i;
  756         u_int8_t hdr;
  757         u_int32_t n;
  758         u_int mask;
  759 
  760         DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__,
  761                  sc, p->speed, p->ebofs, p->maxsize));
  762 
  763         if (sc->sc_dying)
  764                 return (EIO);
  765 
  766         hdr = 0;
  767         if (p->ebofs != sc->sc_params.ebofs) {
  768                 /* round up ebofs */
  769                 mask = sc->sc_irdadesc.bmAdditionalBOFs;
  770                 for (i = 0; i < UIRDA_NEBOFS; i++) {
  771                         if ((mask & uirda_ebofs[i].mask) &&
  772                             uirda_ebofs[i].count >= p->ebofs) {
  773                                 hdr = uirda_ebofs[i].header;
  774                                 goto found1;
  775                         }
  776                 }
  777                 /* no good value found */
  778                 return (EINVAL);
  779         found1:
  780                 DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr));
  781                 ;
  782 
  783         }
  784         if (hdr != 0 || p->speed != sc->sc_params.speed) {
  785                 /* find speed */
  786                 mask = UGETW(sc->sc_irdadesc.wBaudRate);
  787                 for (i = 0; i < UIRDA_NSPEEDS; i++) {
  788                         if ((mask & uirda_speeds[i].mask) &&
  789                             uirda_speeds[i].speed == p->speed) {
  790                                 hdr |= uirda_speeds[i].header;
  791                                 goto found2;
  792                         }
  793                 }
  794                 /* no good value found */
  795                 return (EINVAL);
  796         found2:
  797                 DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr));
  798                 ;
  799         }
  800         if (p->maxsize != sc->sc_params.maxsize) {
  801                 if (p->maxsize > IRDA_MAX_FRAME_SIZE)
  802                         return (EINVAL);
  803                 sc->sc_params.maxsize = p->maxsize;
  804 #if 0
  805                 DPRINTF(("%s: new buffers, old size=%d\n", __func__,
  806                          sc->sc_params.maxsize));
  807                 if (p->maxsize > 10000 || p < 0) /* XXX */
  808                         return (EINVAL);
  809 
  810                 /* Change the write buffer */
  811                 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL);
  812                 if (sc->sc_wr_buf != NULL)
  813                         usbd_free_buffer(sc->sc_wr_xfer);
  814                 sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, p->maxsize+1);
  815                 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL);
  816                 if (sc->sc_wr_buf == NULL)
  817                         return (ENOMEM);
  818 
  819                 /* Change the read buffer */
  820                 lockmgr(&sc->sc_rd_buf_lk, LK_EXCLUSIVE, NULL);
  821                 usbd_abort_pipe(sc->sc_rd_pipe);
  822                 if (sc->sc_rd_buf != NULL)
  823                         usbd_free_buffer(sc->sc_rd_xfer);
  824                 sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, p->maxsize+1);
  825                 sc->sc_rd_count = 0;
  826                 if (sc->sc_rd_buf == NULL) {
  827                         lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL);
  828                         return (ENOMEM);
  829                 }
  830                 sc->sc_params.maxsize = p->maxsize;
  831                 err = uirda_start_read(sc); /* XXX check */
  832                 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL);
  833 #endif
  834         }
  835         if (hdr != 0 && hdr != sc->sc_wr_hdr) {
  836                 /*
  837                  * A change has occurred, transmit a 0 length frame with
  838                  * the new settings.  The 0 length frame is not sent to the
  839                  * device.
  840                  */
  841                 DPRINTF(("%s: sc=%p setting header 0x%02x\n",
  842                          __func__, sc, hdr));
  843                 sc->sc_wr_hdr = hdr;
  844                 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL);
  845                 sc->sc_wr_buf[0] = hdr;
  846                 n = UIRDA_OUTPUT_HEADER_SIZE;
  847                 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
  848                           USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
  849                           UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n, "uirdast");
  850                 if (err) {
  851                         printf("%s: set failed, err=%d\n",
  852                             USBDEVNAME(sc->sc_dev), err);
  853                         usbd_clear_endpoint_stall(sc->sc_wr_pipe);
  854                 }
  855                 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL);
  856         }
  857 
  858         sc->sc_params = *p;
  859 
  860         return (0);
  861 }
  862 
  863 int
  864 uirda_get_speeds(void *h, int *speeds)
  865 {
  866         struct uirda_softc *sc = h;
  867         u_int isp;
  868         u_int usp;
  869 
  870         DPRINTF(("%s: sc=%p\n", __func__, sc));
  871 
  872         if (sc->sc_dying)
  873                 return (EIO);
  874 
  875         usp = UGETW(sc->sc_irdadesc.wBaudRate);
  876         isp = 0;
  877         if (usp & UI_BR_4000000) isp |= IRDA_SPEED_4000000;
  878         if (usp & UI_BR_1152000) isp |= IRDA_SPEED_1152000;
  879         if (usp & UI_BR_576000)  isp |= IRDA_SPEED_576000;
  880         if (usp & UI_BR_115200)  isp |= IRDA_SPEED_115200;
  881         if (usp & UI_BR_57600)   isp |= IRDA_SPEED_57600;
  882         if (usp & UI_BR_38400)   isp |= IRDA_SPEED_38400;
  883         if (usp & UI_BR_19200)   isp |= IRDA_SPEED_19200;
  884         if (usp & UI_BR_9600)    isp |= IRDA_SPEED_9600;
  885         if (usp & UI_BR_2400)    isp |= IRDA_SPEED_2400;
  886         *speeds = isp;
  887         return (0);
  888 }
  889 
  890 int
  891 uirda_get_turnarounds(void *h, int *turnarounds)
  892 {
  893         struct uirda_softc *sc = h;
  894         u_int ita;
  895         u_int uta;
  896 
  897         DPRINTF(("%s: sc=%p\n", __func__, sc));
  898 
  899         if (sc->sc_dying)
  900                 return (EIO);
  901 
  902         uta = sc->sc_irdadesc.bmMinTurnaroundTime;
  903         ita = 0;
  904         if (uta & UI_TA_0)     ita |= IRDA_TURNT_0;
  905         if (uta & UI_TA_10)    ita |= IRDA_TURNT_10;
  906         if (uta & UI_TA_50)    ita |= IRDA_TURNT_50;
  907         if (uta & UI_TA_100)   ita |= IRDA_TURNT_100;
  908         if (uta & UI_TA_500)   ita |= IRDA_TURNT_500;
  909         if (uta & UI_TA_1000)  ita |= IRDA_TURNT_1000;
  910         if (uta & UI_TA_5000)  ita |= IRDA_TURNT_5000;
  911         if (uta & UI_TA_10000) ita |= IRDA_TURNT_10000;
  912         *turnarounds = ita;
  913         return (0);
  914 }
  915 
  916 void
  917 uirda_rd_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  918             usbd_status status)
  919 {
  920         struct uirda_softc *sc = priv;
  921         u_int32_t size;
  922 
  923         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  924 
  925         if (status == USBD_CANCELLED) /* this is normal */
  926                 return;
  927         if (status) {
  928                 size = UIRDA_INPUT_HEADER_SIZE;
  929                 sc->sc_rd_err = 1;
  930         } else {
  931                 usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL);
  932         }
  933         DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__, sc, size,
  934                     sc->sc_rd_err));
  935         sc->sc_rd_count = size;
  936         wakeup(&sc->sc_rd_count); /* XXX should use flag */
  937         selnotify(&sc->sc_rd_sel, 0);
  938 }
  939 
  940 usbd_status
  941 uirda_start_read(struct uirda_softc *sc)
  942 {
  943         usbd_status err;
  944 
  945         DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__, sc,
  946                     sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE));
  947 
  948         if (sc->sc_dying)
  949                 return (USBD_IOERROR);
  950 
  951         if (sc->sc_rd_err) {
  952                 sc->sc_rd_err = 0;
  953                 DPRINTF(("uirda_start_read: clear stall\n"));
  954                 usbd_clear_endpoint_stall(sc->sc_rd_pipe);
  955         }
  956 
  957         usbd_setup_xfer(sc->sc_rd_xfer, sc->sc_rd_pipe, sc, sc->sc_rd_buf,
  958                         sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE,
  959                         USBD_SHORT_XFER_OK | USBD_NO_COPY,
  960                         USBD_NO_TIMEOUT, uirda_rd_cb);
  961         err = usbd_transfer(sc->sc_rd_xfer);
  962         if (err != USBD_IN_PROGRESS) {
  963                 DPRINTF(("uirda_start_read: err=%d\n", err));
  964                 return (err);
  965         }
  966         return (USBD_NORMAL_COMPLETION);
  967 }

Cache object: d87b8b19a528cc0608fe6fe55f7a1fa2


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