[BACK]Return to ustir.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/ustir.c, Revision 1.33.14.1

1.33.14.1! skrll       1: /*     $NetBSD: ustir.c,v 1.33 2013/05/27 16:23:20 kiyohara Exp $      */
1.1       augustss    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 David Sainty <David.Sainty@dtsp.co.nz>
                      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:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
1.33.14.1! skrll      33: __KERNEL_RCSID(0, "$NetBSD: ustir.c,v 1.33 2013/05/27 16:23:20 kiyohara Exp $");
1.1       augustss   34:
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/kernel.h>
                     38: #include <sys/device.h>
1.33.14.1! skrll      39: #include <sys/kmem.h>
1.1       augustss   40: #include <sys/conf.h>
                     41: #include <sys/file.h>
                     42: #include <sys/poll.h>
                     43: #include <sys/select.h>
                     44: #include <sys/proc.h>
                     45: #include <sys/kthread.h>
                     46:
                     47: #ifdef USTIR_DEBUG_IOCTLS
                     48: #include <sys/ioctl.h>
                     49: #include <dev/usb/ustir.h>
                     50: #endif
                     51:
                     52: #include <dev/usb/usb.h>
                     53: #include <dev/usb/usbdevs.h>
                     54: #include <dev/usb/usbdi.h>
                     55: #include <dev/usb/usbdi_util.h>
                     56: #include <dev/usb/ustirreg.h>
                     57:
                     58: #include <dev/ir/ir.h>
                     59: #include <dev/ir/irdaio.h>
                     60: #include <dev/ir/irframevar.h>
                     61: #include <dev/ir/sir.h>
                     62:
                     63: #ifdef USTIR_DEBUG
1.29      dyoung     64: #define DPRINTFN(n,x)  if (ustirdebug>(n)) printf x
1.1       augustss   65: int    ustirdebug = 0;
                     66: #else
                     67: #define DPRINTFN(n,x)
                     68: #endif
                     69:
                     70: /* Max size with framing. */
                     71: #define MAX_USTIR_OUTPUT_FRAME (2*IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + STIR_OUTPUT_HEADER_SIZE + 4)
                     72:
                     73: #define USTIR_NSPEEDS 9
                     74: struct ustir_speedrec {
                     75:        unsigned int speed;
                     76:        unsigned int config;
                     77: };
                     78:
                     79: Static struct ustir_speedrec const ustir_speeds[USTIR_NSPEEDS] = {
                     80:        { 4000000, STIR_BRMODE_4000000 },
                     81:        { 1152000, STIR_BRMODE_1152000 },
                     82:        { 576000, STIR_BRMODE_576000 },
                     83:        { 115200, STIR_BRMODE_115200 },
                     84:        { 57600, STIR_BRMODE_57600 },
                     85:        { 38400, STIR_BRMODE_38400 },
                     86:        { 19200, STIR_BRMODE_19200 },
                     87:        { 9600, STIR_BRMODE_9600 },
                     88:        { 2400, STIR_BRMODE_2400 }
                     89: };
                     90:
                     91: struct ustir_softc {
1.29      dyoung     92:        device_t                sc_dev;
1.33.14.1! skrll      93:        struct usbd_device      *sc_udev;
        !            94:        struct usbd_interface   *sc_iface;
1.1       augustss   95:
1.33.14.1! skrll      96:        uint8_t                 *sc_ur_buf; /* Unencapsulated frame */
1.1       augustss   97:        u_int                   sc_ur_framelen;
                     98:
1.33.14.1! skrll      99:        uint8_t                 *sc_rd_buf; /* Raw incoming data stream */
1.1       augustss  100:        size_t                  sc_rd_index;
                    101:        int                     sc_rd_addr;
1.33.14.1! skrll     102:        struct usbd_pipe        *sc_rd_pipe;
        !           103:        struct usbd_xfer        *sc_rd_xfer;
1.1       augustss  104:        u_int                   sc_rd_count;
                    105:        int                     sc_rd_readinprogress;
                    106:        u_int                   sc_rd_expectdataticks;
                    107:        u_char                  sc_rd_err;
                    108:        struct framestate       sc_framestate;
1.20      ad        109:        struct lwp              *sc_thread;
1.1       augustss  110:        struct selinfo          sc_rd_sel;
                    111:
1.33.14.1! skrll     112:        uint8_t                 *sc_wr_buf;
1.1       augustss  113:        int                     sc_wr_addr;
1.10      dsainty   114:        int                     sc_wr_stalewrite;
1.33.14.1! skrll     115:        struct usbd_xfer        *sc_wr_xfer;
        !           116:        struct usbd_pipe        *sc_wr_pipe;
1.1       augustss  117:        struct selinfo          sc_wr_sel;
                    118:
                    119:        enum {
                    120:                udir_input, /* Receiving data */
                    121:                udir_output, /* Transmitting data */
                    122:                udir_stalled, /* Error preventing data flow */
                    123:                udir_idle /* Neither receiving nor transmitting */
                    124:        } sc_direction;
                    125:
                    126:        struct ustir_speedrec const *sc_speedrec;
                    127:
1.26      cube      128:        device_t                sc_child;
1.1       augustss  129:        struct irda_params      sc_params;
                    130:
                    131:        int                     sc_refcnt;
                    132:        char                    sc_closing;
                    133:        char                    sc_dying;
                    134: };
                    135:
                    136: /* True if we cannot safely read data from the device */
                    137: #define USTIR_BLOCK_RX_DATA(sc) ((sc)->sc_ur_framelen != 0)
                    138:
                    139: #define USTIR_WR_TIMEOUT 200
                    140:
1.33.14.1! skrll     141: Static int ustir_activate(device_t, enum devact);
        !           142: Static int ustir_open(void *, int, int, struct lwp *);
        !           143: Static int ustir_close(void *, int, int, struct lwp *);
        !           144: Static int ustir_read(void *, struct uio *, int);
        !           145: Static int ustir_write(void *, struct uio *, int);
        !           146: Static int ustir_set_params(void *, struct irda_params *);
        !           147: Static int ustir_get_speeds(void *, int *);
        !           148: Static int ustir_get_turnarounds(void *, int *);
        !           149: Static int ustir_poll(void *, int, struct lwp *);
        !           150: Static int ustir_kqfilter(void *, struct knote *);
1.1       augustss  151:
                    152: #ifdef USTIR_DEBUG_IOCTLS
1.33.14.1! skrll     153: Static int ustir_ioctl(void *, u_long, void *, int, struct lwp *);
1.1       augustss  154: #endif
                    155:
                    156: Static struct irframe_methods const ustir_methods = {
                    157:        ustir_open, ustir_close, ustir_read, ustir_write, ustir_poll,
1.4       jdolecek  158:        ustir_kqfilter, ustir_set_params, ustir_get_speeds,
                    159:        ustir_get_turnarounds,
1.1       augustss  160: #ifdef USTIR_DEBUG_IOCTLS
                    161:        ustir_ioctl
                    162: #endif
                    163: };
                    164:
1.33.14.1! skrll     165: Static void ustir_rd_cb(struct usbd_xfer *, void *, usbd_status);
1.2       augustss  166: Static usbd_status ustir_start_read(struct ustir_softc *);
                    167: Static void ustir_periodic(struct ustir_softc *);
                    168: Static void ustir_thread(void *);
1.1       augustss  169:
                    170: static usbd_status
1.33.14.1! skrll     171: ustir_read_reg(struct ustir_softc *sc, unsigned int reg, uint8_t *data)
1.1       augustss  172: {
                    173:        usb_device_request_t req;
                    174:
                    175:        req.bmRequestType = UT_READ_VENDOR_DEVICE;
                    176:        req.bRequest = STIR_CMD_READMULTIREG;
                    177:        USETW(req.wValue, 0);
                    178:        USETW(req.wIndex, reg);
                    179:        USETW(req.wLength, 1);
                    180:
                    181:        return usbd_do_request(sc->sc_udev, &req, data);
                    182: }
                    183:
                    184: static usbd_status
1.33.14.1! skrll     185: ustir_write_reg(struct ustir_softc *sc, unsigned int reg, uint8_t data)
1.1       augustss  186: {
                    187:        usb_device_request_t req;
                    188:
                    189:        req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
                    190:        req.bRequest = STIR_CMD_WRITESINGLEREG;
                    191:        USETW(req.wValue, data);
                    192:        USETW(req.wIndex, reg);
                    193:        USETW(req.wLength, 0);
                    194:
                    195:        return usbd_do_request(sc->sc_udev, &req, NULL);
                    196: }
                    197:
                    198: #ifdef USTIR_DEBUG
                    199: static void
1.33.14.1! skrll     200: ustir_dumpdata(uint8_t const *data, size_t dlen, char const *desc)
1.1       augustss  201: {
                    202:        size_t bdindex;
                    203:        printf("%s: (%lx)", desc, (unsigned long)dlen);
                    204:        for (bdindex = 0; bdindex < dlen; bdindex++)
1.9       dsainty   205:                printf(" %02x", (unsigned int)data[bdindex]);
1.1       augustss  206:        printf("\n");
                    207: }
                    208: #endif
                    209:
1.26      cube      210: int ustir_match(device_t, cfdata_t, void *);
1.22      dyoung    211: void ustir_attach(device_t, device_t, void *);
                    212: void ustir_childdet(device_t, device_t);
                    213: int ustir_detach(device_t, int);
                    214: int ustir_activate(device_t, enum devact);
                    215: extern struct cfdriver ustir_cd;
1.26      cube      216: CFATTACH_DECL2_NEW(ustir, sizeof(struct ustir_softc), ustir_match,
1.22      dyoung    217:     ustir_attach, ustir_detach, ustir_activate, NULL, ustir_childdet);
1.1       augustss  218:
1.33.14.1! skrll     219: int
1.29      dyoung    220: ustir_match(device_t parent, cfdata_t match, void *aux)
1.1       augustss  221: {
1.29      dyoung    222:        struct usb_attach_arg *uaa = aux;
1.1       augustss  223:
                    224:        DPRINTFN(50,("ustir_match\n"));
                    225:
1.33.14.1! skrll     226:        if (uaa->uaa_vendor == USB_VENDOR_SIGMATEL &&
        !           227:            uaa->uaa_product == USB_PRODUCT_SIGMATEL_IRDA)
1.1       augustss  228:                return UMATCH_VENDOR_PRODUCT;
                    229:
                    230:        return UMATCH_NONE;
                    231: }
                    232:
1.33.14.1! skrll     233: void
1.29      dyoung    234: ustir_attach(device_t parent, device_t self, void *aux)
1.1       augustss  235: {
1.29      dyoung    236:        struct ustir_softc *sc = device_private(self);
                    237:        struct usb_attach_arg *uaa = aux;
1.33.14.1! skrll     238:        struct usbd_device *dev = uaa->uaa_device;
        !           239:        struct usbd_interface *iface;
1.14      augustss  240:        char *devinfop;
1.1       augustss  241:        usb_endpoint_descriptor_t *ed;
1.33.14.1! skrll     242:        uint8_t epcount;
1.1       augustss  243:        int i;
                    244:        struct ir_attach_args ia;
                    245:
                    246:        DPRINTFN(10,("ustir_attach: sc=%p\n", sc));
                    247:
1.26      cube      248:        sc->sc_dev = self;
                    249:
1.27      plunky    250:        aprint_naive("\n");
                    251:        aprint_normal("\n");
                    252:
1.14      augustss  253:        devinfop = usbd_devinfo_alloc(dev, 0);
1.26      cube      254:        aprint_normal_dev(self, "%s\n", devinfop);
1.14      augustss  255:        usbd_devinfo_free(devinfop);
1.1       augustss  256:
1.19      drochner  257:        if (usbd_set_config_index(dev, 0, 1)
                    258:            || usbd_device2interface_handle(dev, 0, &iface)) {
1.26      cube      259:                aprint_error_dev(self, "Configuration failed\n");
1.29      dyoung    260:                return;
1.19      drochner  261:        }
                    262:
1.1       augustss  263:        sc->sc_udev = dev;
                    264:        sc->sc_iface = iface;
                    265:
                    266:        epcount = 0;
                    267:        (void)usbd_endpoint_count(iface, &epcount);
                    268:
                    269:        sc->sc_rd_addr = -1;
                    270:        sc->sc_wr_addr = -1;
                    271:        for (i = 0; i < epcount; i++) {
                    272:                ed = usbd_interface2endpoint_descriptor(iface, i);
                    273:                if (ed == NULL) {
1.26      cube      274:                        aprint_error_dev(self, "couldn't get ep %d\n", i);
1.29      dyoung    275:                        return;
1.1       augustss  276:                }
                    277:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    278:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    279:                        sc->sc_rd_addr = ed->bEndpointAddress;
                    280:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                    281:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    282:                        sc->sc_wr_addr = ed->bEndpointAddress;
                    283:                }
                    284:        }
                    285:        if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) {
1.26      cube      286:                aprint_error_dev(self, "missing endpoint\n");
1.29      dyoung    287:                return;
1.1       augustss  288:        }
                    289:
                    290:        DPRINTFN(10, ("ustir_attach: %p\n", sc->sc_udev));
                    291:
1.33.14.1! skrll     292:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
1.1       augustss  293:
                    294:        ia.ia_type = IR_TYPE_IRFRAME;
                    295:        ia.ia_methods = &ustir_methods;
                    296:        ia.ia_handle = sc;
                    297:
                    298:        sc->sc_child = config_found(self, &ia, ir_print);
1.23      rmind     299:        selinit(&sc->sc_rd_sel);
                    300:        selinit(&sc->sc_wr_sel);
1.1       augustss  301:
1.29      dyoung    302:        return;
1.1       augustss  303: }
                    304:
1.22      dyoung    305: void
                    306: ustir_childdet(device_t self, device_t child)
                    307: {
                    308:        struct ustir_softc *sc = device_private(self);
                    309:
                    310:        KASSERT(sc->sc_child == child);
                    311:        sc->sc_child = NULL;
                    312: }
                    313:
1.33.14.1! skrll     314: int
1.29      dyoung    315: ustir_detach(device_t self, int flags)
1.1       augustss  316: {
1.29      dyoung    317:        struct ustir_softc *sc = device_private(self);
1.1       augustss  318:        int s;
                    319:        int rv = 0;
                    320:
                    321:        DPRINTFN(0, ("ustir_detach: sc=%p flags=%d\n", sc, flags));
                    322:
                    323:        sc->sc_closing = sc->sc_dying = 1;
                    324:
                    325:        wakeup(&sc->sc_thread);
                    326:
                    327:        while (sc->sc_thread != NULL)
                    328:                tsleep(&sc->sc_closing, PWAIT, "usircl", 0);
                    329:
                    330:        /* Abort all pipes.  Causes processes waiting for transfer to wake. */
                    331:        if (sc->sc_rd_pipe != NULL) {
                    332:                usbd_abort_pipe(sc->sc_rd_pipe);
1.33.14.1! skrll     333:        }
        !           334:        if (sc->sc_wr_pipe != NULL) {
        !           335:                usbd_abort_pipe(sc->sc_wr_pipe);
        !           336:        }
        !           337:        if (sc->sc_rd_xfer != NULL) {
        !           338:                usbd_destroy_xfer(sc->sc_rd_xfer);
        !           339:                sc->sc_rd_xfer = NULL;
        !           340:                sc->sc_rd_buf = NULL;
        !           341:        }
        !           342:        if (sc->sc_wr_xfer != NULL) {
        !           343:                usbd_destroy_xfer(sc->sc_wr_xfer);
        !           344:                sc->sc_wr_xfer = NULL;
        !           345:                sc->sc_wr_buf = NULL;
        !           346:        }
        !           347:        if (sc->sc_rd_pipe != NULL) {
1.1       augustss  348:                usbd_close_pipe(sc->sc_rd_pipe);
                    349:                sc->sc_rd_pipe = NULL;
                    350:        }
                    351:        if (sc->sc_wr_pipe != NULL) {
                    352:                usbd_close_pipe(sc->sc_wr_pipe);
                    353:                sc->sc_wr_pipe = NULL;
                    354:        }
                    355:        wakeup(&sc->sc_ur_framelen);
                    356:        wakeup(&sc->sc_wr_buf);
                    357:
                    358:        s = splusb();
                    359:        if (--sc->sc_refcnt >= 0) {
                    360:                /* Wait for processes to go away. */
1.32      mrg       361:                usb_detach_waitold(sc->sc_dev);
1.1       augustss  362:        }
                    363:        splx(s);
                    364:
1.22      dyoung    365:        if (sc->sc_child != NULL)
1.1       augustss  366:                rv = config_detach(sc->sc_child, flags);
                    367:
1.33.14.1! skrll     368:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
1.1       augustss  369:
1.23      rmind     370:        seldestroy(&sc->sc_rd_sel);
                    371:        seldestroy(&sc->sc_wr_sel);
                    372:
1.1       augustss  373:        return rv;
                    374: }
                    375:
                    376: /* Returns 0 if more data required, 1 if a complete frame was extracted */
                    377: static int
                    378: deframe_rd_ur(struct ustir_softc *sc)
                    379: {
                    380:        while (sc->sc_rd_index < sc->sc_rd_count) {
1.33.14.1! skrll     381:                uint8_t const *buf;
1.1       augustss  382:                size_t buflen;
                    383:                enum frameresult fresult;
                    384:
                    385:                buf = &sc->sc_rd_buf[sc->sc_rd_index];
                    386:                buflen = sc->sc_rd_count - sc->sc_rd_index;
                    387:
                    388:                fresult = deframe_process(&sc->sc_framestate, &buf, &buflen);
                    389:
                    390:                sc->sc_rd_index = sc->sc_rd_count - buflen;
                    391:
1.3       augustss  392:                DPRINTFN(1,("%s: result=%d\n", __func__, (int)fresult));
1.1       augustss  393:
                    394:                switch (fresult) {
                    395:                case FR_IDLE:
                    396:                case FR_INPROGRESS:
                    397:                case FR_FRAMEBADFCS:
                    398:                case FR_FRAMEMALFORMED:
                    399:                case FR_BUFFEROVERRUN:
                    400:                        break;
                    401:                case FR_FRAMEOK:
                    402:                        sc->sc_ur_framelen = sc->sc_framestate.bufindex;
                    403:                        wakeup(&sc->sc_ur_framelen); /* XXX should use flag */
1.23      rmind     404:                        selnotify(&sc->sc_rd_sel, 0, 0);
1.1       augustss  405:                        return 1;
                    406:                }
                    407:        }
                    408:
                    409:        /* Reset indices into USB-side buffer */
                    410:        sc->sc_rd_index = sc->sc_rd_count = 0;
                    411:
                    412:        return 0;
                    413: }
                    414:
                    415: /*
                    416:  * Direction transitions:
                    417:  *
                    418:  * ustir_periodic() can switch the direction from:
                    419:  *
                    420:  *     output -> idle
                    421:  *     output -> stalled
                    422:  *     stalled -> idle
                    423:  *     idle -> input
                    424:  *
                    425:  * ustir_rd_cb() can switch the direction from:
                    426:  *
                    427:  *     input -> stalled
                    428:  *     input -> idle
                    429:  *
                    430:  * ustir_write() can switch the direction from:
                    431:  *
                    432:  *     idle -> output
                    433:  */
                    434: Static void
                    435: ustir_periodic(struct ustir_softc *sc)
                    436: {
                    437:        DPRINTFN(60, ("%s: direction = %d\n",
1.3       augustss  438:                      __func__, sc->sc_direction));
1.1       augustss  439:
                    440:        if (sc->sc_direction == udir_output ||
                    441:            sc->sc_direction == udir_stalled) {
                    442:                usbd_status err;
1.33.14.1! skrll     443:                uint8_t regval;
1.1       augustss  444:
                    445:                DPRINTFN(60, ("%s: reading status register\n",
1.3       augustss  446:                              __func__));
1.1       augustss  447:
                    448:                err = ustir_read_reg(sc, STIR_REG_STATUS,
                    449:                                     &regval);
1.8       dsainty   450:                if (err != USBD_NORMAL_COMPLETION) {
1.26      cube      451:                        aprint_error_dev(sc->sc_dev,
                    452:                            "status register read failed: %s\n",
                    453:                             usbd_errstr(err));
1.1       augustss  454:                } else {
                    455:                        DPRINTFN(10, ("%s: status register = 0x%x\n",
1.3       augustss  456:                                      __func__,
1.1       augustss  457:                                      (unsigned int)regval));
                    458:                        if (sc->sc_direction == udir_output &&
                    459:                            !(regval & STIR_RSTATUS_FFDIR))
                    460:                                /* Output has completed */
                    461:                                sc->sc_direction = udir_idle;
                    462:                        if (regval & STIR_RSTATUS_FFOVER) {
                    463:                                /*
                    464:                                 * On an overrun the FIFO hangs, and
                    465:                                 * any data bulk transfers will stall.
                    466:                                 * Reset the FIFO.
                    467:                                 */
                    468:                                sc->sc_direction = udir_stalled;
                    469:
                    470:                                DPRINTFN(10, ("%s: clearing FIFO error\n",
1.3       augustss  471:                                              __func__));
1.1       augustss  472:
                    473:                                err = ustir_write_reg(sc, STIR_REG_STATUS,
                    474:                                                      STIR_RSTATUS_FFCLR);
                    475:                                /* XXX if we fail partway through
                    476:                                 * this, we may not recover? */
1.8       dsainty   477:                                if (err == USBD_NORMAL_COMPLETION)
1.1       augustss  478:                                        err = ustir_write_reg(sc,
                    479:                                                              STIR_REG_STATUS,
                    480:                                                              0);
1.8       dsainty   481:                                if (err != USBD_NORMAL_COMPLETION) {
1.26      cube      482:                                        aprint_error_dev(sc->sc_dev,
                    483:                                            "FIFO reset failed: %s\n",
                    484:                                            usbd_errstr(err));
1.1       augustss  485:                                } else {
                    486:                                        /* FIFO reset */
                    487:                                        sc->sc_direction = udir_idle;
                    488:                                }
                    489:                        }
                    490:                }
                    491:        }
                    492:
1.10      dsainty   493:        if (sc->sc_wr_stalewrite && sc->sc_direction == udir_idle) {
                    494:                /*
                    495:                 * In a stale write case, we need to check if the
                    496:                 * write has completed.  Once that has happened, the
                    497:                 * write is no longer stale.
                    498:                 *
                    499:                 * But note that we may immediately start a read poll...
                    500:                 */
                    501:                sc->sc_wr_stalewrite = 0;
                    502:                wakeup(&sc->sc_wr_buf);
                    503:        }
                    504:
1.1       augustss  505:        if (!sc->sc_rd_readinprogress &&
                    506:            (sc->sc_direction == udir_idle ||
                    507:             sc->sc_direction == udir_input))
                    508:                /* Do a read poll if appropriate... */
                    509:                ustir_start_read(sc);
                    510: }
                    511:
                    512: Static void
                    513: ustir_thread(void *arg)
                    514: {
                    515:        struct ustir_softc *sc = arg;
                    516:
1.3       augustss  517:        DPRINTFN(20, ("%s: starting polling thread\n", __func__));
1.1       augustss  518:
                    519:        while (!sc->sc_closing) {
                    520:                if (!sc->sc_rd_readinprogress && !USTIR_BLOCK_RX_DATA(sc))
                    521:                        ustir_periodic(sc);
                    522:
                    523:                if (!sc->sc_closing) {
                    524:                        int error;
                    525:                        error = tsleep(&sc->sc_thread, PWAIT,
                    526:                                       "ustir", hz / 10);
                    527:                        if (error == EWOULDBLOCK &&
                    528:                            sc->sc_rd_expectdataticks > 0)
                    529:                                /*
                    530:                                 * After a timeout decrement the tick
                    531:                                 * counter within which time we expect
                    532:                                 * data to arrive if we are receiving
                    533:                                 * data...
                    534:                                 */
                    535:                                sc->sc_rd_expectdataticks--;
                    536:                }
                    537:        }
                    538:
1.3       augustss  539:        DPRINTFN(20, ("%s: exiting polling thread\n", __func__));
1.1       augustss  540:
                    541:        sc->sc_thread = NULL;
                    542:
                    543:        wakeup(&sc->sc_closing);
                    544:
                    545:        if (--sc->sc_refcnt < 0)
1.32      mrg       546:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss  547:
                    548:        kthread_exit(0);
                    549: }
                    550:
                    551: Static void
1.33.14.1! skrll     552: ustir_rd_cb(struct usbd_xfer *xfer, void *priv,
1.1       augustss  553:            usbd_status status)
                    554: {
                    555:        struct ustir_softc *sc = priv;
1.33.14.1! skrll     556:        uint32_t size;
1.1       augustss  557:
1.3       augustss  558:        DPRINTFN(60, ("%s: sc=%p\n", __func__, sc));
1.1       augustss  559:
                    560:        /* Read is no longer in progress */
                    561:        sc->sc_rd_readinprogress = 0;
                    562:
                    563:        if (status == USBD_CANCELLED || sc->sc_closing) /* this is normal */
                    564:                return;
                    565:        if (status) {
                    566:                size = 0;
                    567:                sc->sc_rd_err = 1;
                    568:
                    569:                if (sc->sc_direction == udir_input ||
                    570:                    sc->sc_direction == udir_idle) {
                    571:                        /*
                    572:                         * Receive error, probably need to clear error
                    573:                         * condition.
                    574:                         */
                    575:                        sc->sc_direction = udir_stalled;
                    576:                }
                    577:        } else {
                    578:                usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL);
                    579:        }
                    580:
                    581:        sc->sc_rd_index = 0;
                    582:        sc->sc_rd_count = size;
                    583:
                    584:        DPRINTFN(((size > 0 || sc->sc_rd_err != 0) ? 20 : 60),
1.3       augustss  585:                 ("%s: sc=%p size=%u, err=%d\n", __func__,
1.1       augustss  586:                  sc, size, sc->sc_rd_err));
                    587:
                    588: #ifdef USTIR_DEBUG
                    589:        if (ustirdebug >= 20 && size > 0)
1.3       augustss  590:                ustir_dumpdata(sc->sc_rd_buf, size, __func__);
1.1       augustss  591: #endif
                    592:
                    593:        if (!deframe_rd_ur(sc)) {
                    594:                if (!deframe_isclear(&sc->sc_framestate) && size == 0 &&
                    595:                    sc->sc_rd_expectdataticks == 0) {
                    596:                        /*
                    597:                         * Expected data, but didn't get it
                    598:                         * within expected time...
                    599:                         */
                    600:                        DPRINTFN(5,("%s: incoming packet timeout\n",
1.3       augustss  601:                                    __func__));
1.1       augustss  602:                        deframe_clear(&sc->sc_framestate);
                    603:                } else if (size > 0) {
                    604:                        /*
                    605:                         * If we also received actual data, reset the
                    606:                         * data read timeout and wake up the possibly
                    607:                         * sleeping thread...
                    608:                         */
                    609:                        sc->sc_rd_expectdataticks = 2;
                    610:                        wakeup(&sc->sc_thread);
                    611:                }
                    612:        }
                    613:
                    614:        /*
                    615:         * Check if incoming data has stopped, or that we cannot
                    616:         * safely read any more data.  In the case of the latter we
                    617:         * must switch to idle so that a write will not block...
                    618:         */
                    619:        if (sc->sc_direction == udir_input &&
                    620:            ((size == 0 && sc->sc_rd_expectdataticks == 0) ||
                    621:             USTIR_BLOCK_RX_DATA(sc))) {
1.10      dsainty   622:                DPRINTFN(8,("%s: idling on packet timeout, "
                    623:                            "complete frame, or no data\n", __func__));
1.1       augustss  624:                sc->sc_direction = udir_idle;
                    625:
                    626:                /* Wake up for possible output */
                    627:                wakeup(&sc->sc_wr_buf);
1.23      rmind     628:                selnotify(&sc->sc_wr_sel, 0, 0);
1.1       augustss  629:        }
                    630: }
                    631:
                    632: Static usbd_status
                    633: ustir_start_read(struct ustir_softc *sc)
                    634: {
                    635:        usbd_status err;
                    636:
1.3       augustss  637:        DPRINTFN(60,("%s: sc=%p, size=%d\n", __func__, sc,
1.1       augustss  638:                     sc->sc_params.maxsize));
                    639:
                    640:        if (sc->sc_dying)
                    641:                return USBD_IOERROR;
                    642:
                    643:        if (USTIR_BLOCK_RX_DATA(sc) || deframe_rd_ur(sc)) {
                    644:                /*
                    645:                 * Can't start reading just yet.  Since we aren't
                    646:                 * going to start a read, have to switch direction to
                    647:                 * idle.
                    648:                 */
                    649:                sc->sc_direction = udir_idle;
                    650:                return USBD_NORMAL_COMPLETION;
                    651:        }
                    652:
                    653:        /* Starting a read... */
                    654:        sc->sc_rd_readinprogress = 1;
                    655:        sc->sc_direction = udir_input;
                    656:
                    657:        if (sc->sc_rd_err) {
                    658:                sc->sc_rd_err = 0;
1.3       augustss  659:                DPRINTFN(0, ("%s: clear stall\n", __func__));
1.1       augustss  660:                usbd_clear_endpoint_stall(sc->sc_rd_pipe);
                    661:        }
                    662:
1.33.14.1! skrll     663:        usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf,
        !           664:            sc->sc_params.maxsize, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
        !           665:            ustir_rd_cb);
1.1       augustss  666:        err = usbd_transfer(sc->sc_rd_xfer);
                    667:        if (err != USBD_IN_PROGRESS) {
1.8       dsainty   668:                DPRINTFN(0, ("%s: err=%d\n", __func__, (int)err));
1.1       augustss  669:                return err;
                    670:        }
                    671:        return USBD_NORMAL_COMPLETION;
                    672: }
                    673:
                    674: Static int
1.22      dyoung    675: ustir_activate(device_t self, enum devact act)
1.1       augustss  676: {
1.22      dyoung    677:        struct ustir_softc *sc = device_private(self);
1.1       augustss  678:
                    679:        switch (act) {
                    680:        case DVACT_DEACTIVATE:
                    681:                sc->sc_dying = 1;
1.28      dyoung    682:                return 0;
                    683:        default:
                    684:                return EOPNOTSUPP;
1.1       augustss  685:        }
                    686: }
                    687:
1.5       dsainty   688: /* ARGSUSED */
1.1       augustss  689: Static int
1.17      christos  690: ustir_open(void *h, int flag, int mode,
                    691:     struct lwp *l)
1.1       augustss  692: {
                    693:        struct ustir_softc *sc = h;
                    694:        int error;
                    695:        usbd_status err;
                    696:
1.3       augustss  697:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss  698:
                    699:        err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe);
1.8       dsainty   700:        if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss  701:                error = EIO;
                    702:                goto bad1;
                    703:        }
                    704:        err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe);
1.8       dsainty   705:        if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss  706:                error = EIO;
                    707:                goto bad2;
                    708:        }
1.33.14.1! skrll     709:        error = usbd_create_xfer(sc->sc_rd_pipe, IRDA_MAX_FRAME_SIZE,
        !           710:            USBD_SHORT_XFER_OK, 0, &sc->sc_rd_xfer);
        !           711:        if (error)
1.1       augustss  712:                goto bad3;
1.33.14.1! skrll     713:        sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer);
        !           714:
        !           715:        error = usbd_create_xfer(sc->sc_wr_pipe,
        !           716:            IRDA_MAX_FRAME_SIZE + STIR_OUTPUT_HEADER_SIZE,
        !           717:            USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer);
        !           718:        if (error)
1.1       augustss  719:                goto bad4;
1.33.14.1! skrll     720:        sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer);
        !           721:
        !           722:        sc->sc_ur_buf = kmem_alloc(IRDA_MAX_FRAME_SIZE, KM_SLEEP);
1.1       augustss  723:        if (sc->sc_ur_buf == NULL) {
                    724:                error = ENOMEM;
                    725:                goto bad5;
                    726:        }
                    727:
                    728:        sc->sc_rd_index = sc->sc_rd_count = 0;
                    729:        sc->sc_closing = 0;
                    730:        sc->sc_rd_readinprogress = 0;
                    731:        sc->sc_rd_expectdataticks = 0;
                    732:        sc->sc_ur_framelen = 0;
                    733:        sc->sc_rd_err = 0;
1.10      dsainty   734:        sc->sc_wr_stalewrite = 0;
1.1       augustss  735:        sc->sc_speedrec = NULL;
                    736:        sc->sc_direction = udir_idle;
                    737:        sc->sc_params.speed = 0;
                    738:        sc->sc_params.ebofs = 0;
                    739:        sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE;
                    740:
1.33      kiyohara  741:        deframe_init(&sc->sc_framestate, sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
1.1       augustss  742:
                    743:        /* Increment reference for thread */
                    744:        sc->sc_refcnt++;
                    745:
1.20      ad        746:        error = kthread_create(PRI_NONE, 0, NULL, ustir_thread, sc,
1.26      cube      747:            &sc->sc_thread, "%s", device_xname(sc->sc_dev));
1.20      ad        748:        if (error) {
                    749:                sc->sc_refcnt--;
                    750:                goto bad5;
                    751:        }
                    752:
1.1       augustss  753:        return 0;
                    754:
                    755:  bad5:
1.33.14.1! skrll     756:        usbd_destroy_xfer(sc->sc_wr_xfer);
1.1       augustss  757:        sc->sc_wr_xfer = NULL;
                    758:  bad4:
1.33.14.1! skrll     759:        usbd_destroy_xfer(sc->sc_rd_xfer);
1.1       augustss  760:        sc->sc_rd_xfer = NULL;
                    761:  bad3:
                    762:        usbd_close_pipe(sc->sc_wr_pipe);
                    763:        sc->sc_wr_pipe = NULL;
                    764:  bad2:
                    765:        usbd_close_pipe(sc->sc_rd_pipe);
                    766:        sc->sc_rd_pipe = NULL;
                    767:  bad1:
                    768:        return error;
                    769: }
                    770:
1.5       dsainty   771: /* ARGSUSED */
1.1       augustss  772: Static int
1.17      christos  773: ustir_close(void *h, int flag, int mode,
                    774:     struct lwp *l)
1.1       augustss  775: {
                    776:        struct ustir_softc *sc = h;
                    777:
1.3       augustss  778:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss  779:
                    780:        sc->sc_refcnt++;
                    781:
                    782:        sc->sc_rd_readinprogress = 1;
                    783:        sc->sc_closing = 1;
                    784:
                    785:        wakeup(&sc->sc_thread);
                    786:
                    787:        while (sc->sc_thread != NULL)
                    788:                tsleep(&sc->sc_closing, PWAIT, "usircl", 0);
                    789:
                    790:        if (sc->sc_rd_pipe != NULL) {
                    791:                usbd_abort_pipe(sc->sc_rd_pipe);
                    792:                sc->sc_rd_pipe = NULL;
                    793:        }
                    794:        if (sc->sc_wr_pipe != NULL) {
                    795:                usbd_abort_pipe(sc->sc_wr_pipe);
                    796:                sc->sc_wr_pipe = NULL;
                    797:        }
                    798:        if (sc->sc_rd_xfer != NULL) {
1.33.14.1! skrll     799:                usbd_destroy_xfer(sc->sc_rd_xfer);
1.1       augustss  800:                sc->sc_rd_xfer = NULL;
                    801:                sc->sc_rd_buf = NULL;
                    802:        }
                    803:        if (sc->sc_wr_xfer != NULL) {
1.33.14.1! skrll     804:                usbd_destroy_xfer(sc->sc_wr_xfer);
1.1       augustss  805:                sc->sc_wr_xfer = NULL;
                    806:                sc->sc_wr_buf = NULL;
                    807:        }
                    808:        if (sc->sc_ur_buf != NULL) {
1.33.14.1! skrll     809:                kmem_free(sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
1.1       augustss  810:                sc->sc_ur_buf = NULL;
                    811:        }
1.33.14.1! skrll     812:        if (sc->sc_rd_pipe != NULL) {
        !           813:                usbd_close_pipe(sc->sc_rd_pipe);
        !           814:                sc->sc_rd_pipe = NULL;
        !           815:        }
        !           816:        if (sc->sc_wr_pipe != NULL) {
        !           817:                usbd_close_pipe(sc->sc_wr_pipe);
        !           818:                sc->sc_wr_pipe = NULL;
        !           819:        }
1.1       augustss  820:
                    821:        if (--sc->sc_refcnt < 0)
1.32      mrg       822:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss  823:
                    824:        return 0;
                    825: }
                    826:
1.7       dsainty   827: /* ARGSUSED */
1.1       augustss  828: Static int
1.17      christos  829: ustir_read(void *h, struct uio *uio, int flag)
1.1       augustss  830: {
                    831:        struct ustir_softc *sc = h;
                    832:        int s;
                    833:        int error;
                    834:        u_int uframelen;
                    835:
1.3       augustss  836:        DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1       augustss  837:
                    838:        if (sc->sc_dying)
                    839:                return EIO;
                    840:
                    841: #ifdef DIAGNOSTIC
                    842:        if (sc->sc_rd_buf == NULL)
                    843:                return EINVAL;
                    844: #endif
                    845:
                    846:        sc->sc_refcnt++;
                    847:
                    848:        if (!sc->sc_rd_readinprogress && !USTIR_BLOCK_RX_DATA(sc))
                    849:                /* Possibly wake up polling thread */
                    850:                wakeup(&sc->sc_thread);
                    851:
                    852:        do {
                    853:                s = splusb();
                    854:                while (sc->sc_ur_framelen == 0) {
1.3       augustss  855:                        DPRINTFN(5,("%s: calling tsleep()\n", __func__));
1.1       augustss  856:                        error = tsleep(&sc->sc_ur_framelen, PZERO | PCATCH,
                    857:                                       "usirrd", 0);
                    858:                        if (sc->sc_dying)
                    859:                                error = EIO;
                    860:                        if (error) {
                    861:                                splx(s);
                    862:                                DPRINTFN(0, ("%s: tsleep() = %d\n",
1.3       augustss  863:                                             __func__, error));
1.1       augustss  864:                                goto ret;
                    865:                        }
                    866:                }
                    867:                splx(s);
                    868:
                    869:                uframelen = sc->sc_ur_framelen;
                    870:                DPRINTFN(1,("%s: sc=%p framelen=%u, hdr=0x%02x\n",
1.3       augustss  871:                            __func__, sc, uframelen, sc->sc_ur_buf[0]));
1.1       augustss  872:                if (uframelen > uio->uio_resid)
                    873:                        error = EINVAL;
                    874:                else
                    875:                        error = uiomove(sc->sc_ur_buf, uframelen, uio);
                    876:                sc->sc_ur_framelen = 0;
                    877:
                    878:                if (!deframe_rd_ur(sc) && uframelen > 0) {
                    879:                        /*
                    880:                         * Need to wait for another read to obtain a
                    881:                         * complete frame...  If we also obtained
                    882:                         * actual data, wake up the possibly sleeping
                    883:                         * thread immediately...
                    884:                         */
                    885:                        wakeup(&sc->sc_thread);
                    886:                }
                    887:        } while (uframelen == 0);
                    888:
1.3       augustss  889:        DPRINTFN(1,("%s: return %d\n", __func__, error));
1.1       augustss  890:
                    891:  ret:
                    892:        if (--sc->sc_refcnt < 0)
1.32      mrg       893:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss  894:        return error;
                    895: }
                    896:
1.7       dsainty   897: /* ARGSUSED */
1.1       augustss  898: Static int
1.17      christos  899: ustir_write(void *h, struct uio *uio, int flag)
1.1       augustss  900: {
                    901:        struct ustir_softc *sc = h;
                    902:        usbd_status err;
1.33.14.1! skrll     903:        uint32_t wrlen;
1.1       augustss  904:        int error, sirlength;
1.33.14.1! skrll     905:        uint8_t *wrbuf;
1.1       augustss  906:        int s;
                    907:
1.3       augustss  908:        DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1       augustss  909:
                    910:        if (sc->sc_dying)
                    911:                return EIO;
                    912:
                    913: #ifdef DIAGNOSTIC
                    914:        if (sc->sc_wr_buf == NULL)
                    915:                return EINVAL;
                    916: #endif
                    917:
                    918:        wrlen = uio->uio_resid;
                    919:        if (wrlen > sc->sc_params.maxsize)
                    920:                return EINVAL;
                    921:
                    922:        sc->sc_refcnt++;
                    923:
1.10      dsainty   924:        if (!USTIR_BLOCK_RX_DATA(sc)) {
                    925:                /*
                    926:                 * If reads are not blocked, determine what action we
                    927:                 * should potentially take...
                    928:                 */
                    929:                if (sc->sc_direction == udir_output) {
                    930:                        /*
                    931:                         * If the last operation was an output, wait for the
                    932:                         * polling thread to check for incoming data.
                    933:                         */
                    934:                        sc->sc_wr_stalewrite = 1;
                    935:                        wakeup(&sc->sc_thread);
                    936:                } else if (!sc->sc_rd_readinprogress &&
                    937:                           (sc->sc_direction == udir_idle ||
                    938:                            sc->sc_direction == udir_input)) {
                    939:                        /* If idle, check for input before outputting */
                    940:                        ustir_start_read(sc);
                    941:                }
                    942:        }
1.1       augustss  943:
                    944:        s = splusb();
1.10      dsainty   945:        while (sc->sc_wr_stalewrite ||
                    946:               (sc->sc_direction != udir_output &&
                    947:                sc->sc_direction != udir_idle)) {
                    948:                DPRINTFN(5, ("%s: sc=%p stalewrite=%d direction=%d, "
                    949:                             "calling tsleep()\n", __func__,
                    950:                             sc, sc->sc_wr_stalewrite, sc->sc_direction));
1.1       augustss  951:                error = tsleep(&sc->sc_wr_buf, PZERO | PCATCH,
                    952:                               "usirwr", 0);
                    953:                if (sc->sc_dying)
                    954:                        error = EIO;
                    955:                if (error) {
                    956:                        splx(s);
1.3       augustss  957:                        DPRINTFN(0, ("%s: tsleep() = %d\n", __func__,
1.1       augustss  958:                                     error));
                    959:                        goto ret;
                    960:                }
                    961:        }
                    962:        splx(s);
                    963:
                    964:        wrbuf = sc->sc_wr_buf;
                    965:
                    966:        /* Build header */
                    967:        wrbuf[0] = STIR_OUTPUT_HEADER_BYTE0;
                    968:        wrbuf[1] = STIR_OUTPUT_HEADER_BYTE1;
                    969:
                    970:        sirlength = irda_sir_frame(&wrbuf[STIR_OUTPUT_HEADER_SIZE],
                    971:                                   MAX_USTIR_OUTPUT_FRAME -
                    972:                                   STIR_OUTPUT_HEADER_SIZE,
                    973:                                   uio, sc->sc_params.ebofs);
                    974:        if (sirlength < 0) {
                    975:                error = -sirlength;
                    976:        } else {
1.33.14.1! skrll     977:                uint32_t btlen;
1.1       augustss  978:
1.3       augustss  979:                DPRINTFN(1, ("%s: transfer %u bytes\n", __func__,
1.1       augustss  980:                             (unsigned int)wrlen));
                    981:
                    982:                wrbuf[2] = sirlength & 0xff;
                    983:                wrbuf[3] = (sirlength >> 8) & 0xff;
                    984:
                    985:                btlen = STIR_OUTPUT_HEADER_SIZE + sirlength;
                    986:
                    987:                sc->sc_direction = udir_output;
                    988:
                    989: #ifdef USTIR_DEBUG
                    990:                if (ustirdebug >= 20)
1.3       augustss  991:                        ustir_dumpdata(wrbuf, btlen, __func__);
1.1       augustss  992: #endif
                    993:
                    994:                err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
1.33.14.1! skrll     995:                    USBD_FORCE_SHORT_XFER, USTIR_WR_TIMEOUT, wrbuf, &btlen);
1.3       augustss  996:                DPRINTFN(2, ("%s: err=%d\n", __func__, err));
1.8       dsainty   997:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss  998:                        if (err == USBD_INTERRUPTED)
                    999:                                error = EINTR;
                   1000:                        else if (err == USBD_TIMEOUT)
                   1001:                                error = ETIMEDOUT;
                   1002:                        else
                   1003:                                error = EIO;
                   1004:                } else {
                   1005:                        error = 0;
                   1006:                }
                   1007:        }
                   1008:
                   1009:  ret:
                   1010:        if (--sc->sc_refcnt < 0)
1.32      mrg      1011:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss 1012:
1.3       augustss 1013:        DPRINTFN(1,("%s: sc=%p done\n", __func__, sc));
1.1       augustss 1014:        return error;
                   1015: }
                   1016:
                   1017: Static int
1.15      christos 1018: ustir_poll(void *h, int events, struct lwp *l)
1.1       augustss 1019: {
                   1020:        struct ustir_softc *sc = h;
                   1021:        int revents = 0;
                   1022:
1.3       augustss 1023:        DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1       augustss 1024:
                   1025:        if (events & (POLLOUT | POLLWRNORM)) {
                   1026:                if (sc->sc_direction != udir_input) {
                   1027:                        revents |= events & (POLLOUT | POLLWRNORM);
                   1028:                } else {
                   1029:                        DPRINTFN(2,("%s: recording write select\n",
1.3       augustss 1030:                                    __func__));
1.15      christos 1031:                        selrecord(l, &sc->sc_wr_sel);
1.1       augustss 1032:                }
                   1033:        }
                   1034:
                   1035:        if (events & (POLLIN | POLLRDNORM)) {
                   1036:                if (sc->sc_ur_framelen != 0) {
1.3       augustss 1037:                        DPRINTFN(2,("%s: have data\n", __func__));
1.1       augustss 1038:                        revents |= events & (POLLIN | POLLRDNORM);
                   1039:                } else {
                   1040:                        DPRINTFN(2,("%s: recording read select\n",
1.3       augustss 1041:                                    __func__));
1.15      christos 1042:                        selrecord(l, &sc->sc_rd_sel);
1.1       augustss 1043:                }
                   1044:        }
                   1045:
                   1046:        return revents;
1.4       jdolecek 1047: }
                   1048:
                   1049: static void
                   1050: filt_ustirrdetach(struct knote *kn)
                   1051: {
                   1052:        struct ustir_softc *sc = kn->kn_hook;
                   1053:        int s;
                   1054:
                   1055:        s = splusb();
1.6       christos 1056:        SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext);
1.4       jdolecek 1057:        splx(s);
                   1058: }
                   1059:
1.7       dsainty  1060: /* ARGSUSED */
1.4       jdolecek 1061: static int
1.17      christos 1062: filt_ustirread(struct knote *kn, long hint)
1.4       jdolecek 1063: {
                   1064:        struct ustir_softc *sc = kn->kn_hook;
                   1065:
                   1066:        kn->kn_data = sc->sc_ur_framelen;
1.33.14.1! skrll    1067:        return kn->kn_data > 0;
1.4       jdolecek 1068: }
                   1069:
                   1070: static void
                   1071: filt_ustirwdetach(struct knote *kn)
                   1072: {
                   1073:        struct ustir_softc *sc = kn->kn_hook;
                   1074:        int s;
                   1075:
                   1076:        s = splusb();
1.6       christos 1077:        SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext);
1.4       jdolecek 1078:        splx(s);
                   1079: }
                   1080:
1.7       dsainty  1081: /* ARGSUSED */
1.4       jdolecek 1082: static int
1.17      christos 1083: filt_ustirwrite(struct knote *kn, long hint)
1.4       jdolecek 1084: {
                   1085:        struct ustir_softc *sc = kn->kn_hook;
                   1086:
                   1087:        kn->kn_data = 0;
1.33.14.1! skrll    1088:        return sc->sc_direction != udir_input;
1.4       jdolecek 1089: }
                   1090:
                   1091: static const struct filterops ustirread_filtops =
                   1092:        { 1, NULL, filt_ustirrdetach, filt_ustirread };
                   1093: static const struct filterops ustirwrite_filtops =
                   1094:        { 1, NULL, filt_ustirwdetach, filt_ustirwrite };
                   1095:
                   1096: Static int
                   1097: ustir_kqfilter(void *h, struct knote *kn)
                   1098: {
                   1099:        struct ustir_softc *sc = h;
                   1100:        struct klist *klist;
                   1101:        int s;
                   1102:
                   1103:        switch (kn->kn_filter) {
                   1104:        case EVFILT_READ:
1.6       christos 1105:                klist = &sc->sc_rd_sel.sel_klist;
1.4       jdolecek 1106:                kn->kn_fop = &ustirread_filtops;
                   1107:                break;
                   1108:        case EVFILT_WRITE:
1.6       christos 1109:                klist = &sc->sc_wr_sel.sel_klist;
1.4       jdolecek 1110:                kn->kn_fop = &ustirwrite_filtops;
                   1111:                break;
                   1112:        default:
1.33.14.1! skrll    1113:                return EINVAL;
1.4       jdolecek 1114:        }
                   1115:
                   1116:        kn->kn_hook = sc;
                   1117:
                   1118:        s = splusb();
                   1119:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
                   1120:        splx(s);
                   1121:
1.33.14.1! skrll    1122:        return 0;
1.1       augustss 1123: }
                   1124:
                   1125: #ifdef USTIR_DEBUG_IOCTLS
1.18      christos 1126: Static int ustir_ioctl(void *h, u_long cmd, void *addr, int flag, struct lwp *l)
1.1       augustss 1127: {
                   1128:        struct ustir_softc *sc = h;
                   1129:        int error;
                   1130:        unsigned int regnum;
                   1131:        usbd_status err;
1.33.14.1! skrll    1132:        uint8_t regdata;
1.1       augustss 1133:
                   1134:        if (sc->sc_dying)
                   1135:                return EIO;
                   1136:
                   1137:        sc->sc_refcnt++;
                   1138:
                   1139:        error = 0;
                   1140:        switch (cmd) {
                   1141:        case USTIR_READ_REGISTER:
1.2       augustss 1142:                regnum = *(unsigned int *)addr;
1.1       augustss 1143:
                   1144:                if (regnum > STIR_MAX_REG) {
                   1145:                        error = EINVAL;
                   1146:                        break;
                   1147:                }
                   1148:
                   1149:                err = ustir_read_reg(sc, regnum, &regdata);
                   1150:
1.3       augustss 1151:                DPRINTFN(10, ("%s: regget(%u) = 0x%x\n", __func__,
1.1       augustss 1152:                              regnum, (unsigned int)regdata));
                   1153:
1.2       augustss 1154:                *(unsigned int *)addr = regdata;
1.8       dsainty  1155:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1156:                        printf("%s: register read failed: %s\n",
1.29      dyoung   1157:                               device_xname(sc->sc_dev),
1.1       augustss 1158:                               usbd_errstr(err));
                   1159:                        error = EIO;
                   1160:                }
                   1161:                break;
                   1162:
                   1163:        case USTIR_WRITE_REGISTER:
1.2       augustss 1164:                regnum = *(unsigned int *)addr;
1.1       augustss 1165:                regdata = (regnum >> 8) & 0xff;
                   1166:                regnum = regnum & 0xff;
                   1167:
                   1168:                if (regnum > STIR_MAX_REG) {
                   1169:                        error = EINVAL;
                   1170:                        break;
                   1171:                }
                   1172:
1.3       augustss 1173:                DPRINTFN(10, ("%s: regset(%u, 0x%x)\n", __func__,
1.1       augustss 1174:                              regnum, (unsigned int)regdata));
                   1175:
                   1176:                err = ustir_write_reg(sc, regnum, regdata);
1.8       dsainty  1177:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1178:                        printf("%s: register write failed: %s\n",
1.29      dyoung   1179:                               device_xname(sc->sc_dev),
1.1       augustss 1180:                               usbd_errstr(err));
                   1181:                        error = EIO;
                   1182:                }
                   1183:                break;
                   1184:
                   1185:        case USTIR_DEBUG_LEVEL:
                   1186: #ifdef USTIR_DEBUG
1.2       augustss 1187:                ustirdebug = *(int *)addr;
1.1       augustss 1188: #endif
                   1189:                break;
                   1190:
                   1191:        case USTIR_DEBUG_OPERATION:
                   1192:                break;
                   1193:
                   1194:        default:
                   1195:                error = EINVAL;
                   1196:                break;
                   1197:        }
                   1198:
                   1199:        if (--sc->sc_refcnt < 0)
1.32      mrg      1200:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss 1201:
                   1202:        return error;
                   1203: }
                   1204: #endif
                   1205:
                   1206: Static int
                   1207: ustir_set_params(void *h, struct irda_params *p)
                   1208: {
                   1209:        struct ustir_softc *sc = h;
                   1210:        struct ustir_speedrec const *speedblk;
                   1211:        int i;
                   1212:
1.3       augustss 1213:        DPRINTFN(0, ("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__,
1.1       augustss 1214:                     sc, p->speed, p->ebofs, p->maxsize));
                   1215:
                   1216:        if (sc->sc_dying)
                   1217:                return EIO;
                   1218:
                   1219:        speedblk = NULL;
                   1220:
                   1221:        if (sc->sc_speedrec == NULL || p->speed != sc->sc_speedrec->speed) {
                   1222:                /* find speed */
                   1223:                for (i = 0; i < USTIR_NSPEEDS; i++) {
                   1224:                        if (ustir_speeds[i].speed == p->speed) {
                   1225:                                speedblk = &ustir_speeds[i];
                   1226:                                goto found2;
                   1227:                        }
                   1228:                }
                   1229:                /* no good value found */
                   1230:                return EINVAL;
                   1231:        found2:
                   1232:                ;
                   1233:        }
                   1234:        if (p->maxsize != sc->sc_params.maxsize) {
                   1235:                if (p->maxsize > IRDA_MAX_FRAME_SIZE)
                   1236:                        return EINVAL;
                   1237:                sc->sc_params.maxsize = p->maxsize;
                   1238:        }
                   1239:
                   1240:        sc->sc_params = *p;
                   1241:
                   1242:        if (speedblk != NULL) {
                   1243:                usbd_status err;
1.33.14.1! skrll    1244:                uint8_t regmode;
        !          1245:                uint8_t regbrate;
1.1       augustss 1246:
                   1247:                sc->sc_speedrec = speedblk;
                   1248:
                   1249:                regmode = STIR_BRMODE_MODEREG(speedblk->config);
                   1250:                regbrate = STIR_BRMODE_BRATEREG(speedblk->config);
                   1251:
                   1252:                /*
                   1253:                 * FFSPRST must be set to enable the FIFO.
                   1254:                 */
                   1255:                regmode |= STIR_RMODE_FFSPRST;
                   1256:
1.3       augustss 1257:                DPRINTFN(10, ("%s: setting BRATE = %x\n", __func__,
1.1       augustss 1258:                              (unsigned int)regbrate));
                   1259:                err = ustir_write_reg(sc, STIR_REG_BRATE, regbrate);
1.8       dsainty  1260:                if (err == USBD_NORMAL_COMPLETION) {
1.3       augustss 1261:                        DPRINTFN(10, ("%s: setting MODE = %x\n", __func__,
1.1       augustss 1262:                                      (unsigned int)regmode));
                   1263:                        err = ustir_write_reg(sc, STIR_REG_MODE, regmode);
                   1264:                }
1.8       dsainty  1265:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1266:                        DPRINTFN(10, ("%s: error setting register: %s\n",
1.3       augustss 1267:                                      __func__, usbd_errstr(err)));
1.1       augustss 1268:                        return EIO;
                   1269:                }
                   1270:        }
                   1271:
                   1272:        return 0;
                   1273: }
                   1274:
                   1275: Static int
                   1276: ustir_get_speeds(void *h, int *speeds)
                   1277: {
                   1278:        struct ustir_softc *sc = h;
                   1279:
1.3       augustss 1280:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss 1281:
                   1282:        if (sc->sc_dying)
                   1283:                return EIO;
                   1284:
                   1285:        /* All these speeds are supported */
                   1286:        *speeds = IRDA_SPEED_4000000 |
                   1287:                IRDA_SPEED_1152000 |
                   1288:                IRDA_SPEED_576000 |
                   1289:                IRDA_SPEED_115200 |
                   1290:                IRDA_SPEED_57600 |
                   1291:                IRDA_SPEED_38400 |
                   1292:                IRDA_SPEED_19200 |
                   1293:                IRDA_SPEED_9600 |
                   1294:                IRDA_SPEED_2400;
                   1295:
                   1296:        return 0;
                   1297: }
                   1298:
                   1299: Static int
                   1300: ustir_get_turnarounds(void *h, int *turnarounds)
                   1301: {
                   1302:        struct ustir_softc *sc = h;
                   1303:
1.3       augustss 1304:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss 1305:
                   1306:        if (sc->sc_dying)
                   1307:                return EIO;
                   1308:
                   1309:        /*
                   1310:         * Documentation is on the light side with respect to
                   1311:         * turnaround time for this device.
                   1312:         */
                   1313:        *turnarounds = IRDA_TURNT_10000;
                   1314:
                   1315:        return 0;
                   1316: }

CVSweb <webmaster@jp.NetBSD.org>