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

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

CVSweb <webmaster@jp.NetBSD.org>