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

1.36    ! skrll       1: /*     $NetBSD: ustir.c,v 1.35 2016/07/07 06:55:42 msaitoh 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.36    ! skrll      33: __KERNEL_RCSID(0, "$NetBSD: ustir.c,v 1.35 2016/07/07 06:55:42 msaitoh Exp $");
        !            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:        if (sc->sc_ur_buf == NULL) {
                    728:                error = ENOMEM;
                    729:                goto bad5;
                    730:        }
                    731:
                    732:        sc->sc_rd_index = sc->sc_rd_count = 0;
                    733:        sc->sc_closing = 0;
                    734:        sc->sc_rd_readinprogress = 0;
                    735:        sc->sc_rd_expectdataticks = 0;
                    736:        sc->sc_ur_framelen = 0;
                    737:        sc->sc_rd_err = 0;
1.10      dsainty   738:        sc->sc_wr_stalewrite = 0;
1.1       augustss  739:        sc->sc_speedrec = NULL;
                    740:        sc->sc_direction = udir_idle;
                    741:        sc->sc_params.speed = 0;
                    742:        sc->sc_params.ebofs = 0;
                    743:        sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE;
                    744:
1.33      kiyohara  745:        deframe_init(&sc->sc_framestate, sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
1.1       augustss  746:
                    747:        /* Increment reference for thread */
                    748:        sc->sc_refcnt++;
                    749:
1.20      ad        750:        error = kthread_create(PRI_NONE, 0, NULL, ustir_thread, sc,
1.26      cube      751:            &sc->sc_thread, "%s", device_xname(sc->sc_dev));
1.20      ad        752:        if (error) {
                    753:                sc->sc_refcnt--;
                    754:                goto bad5;
                    755:        }
                    756:
1.1       augustss  757:        return 0;
                    758:
                    759:  bad5:
1.34      skrll     760:        usbd_destroy_xfer(sc->sc_wr_xfer);
1.1       augustss  761:        sc->sc_wr_xfer = NULL;
                    762:  bad4:
1.34      skrll     763:        usbd_destroy_xfer(sc->sc_rd_xfer);
1.1       augustss  764:        sc->sc_rd_xfer = NULL;
                    765:  bad3:
                    766:        usbd_close_pipe(sc->sc_wr_pipe);
                    767:        sc->sc_wr_pipe = NULL;
                    768:  bad2:
                    769:        usbd_close_pipe(sc->sc_rd_pipe);
                    770:        sc->sc_rd_pipe = NULL;
                    771:  bad1:
                    772:        return error;
                    773: }
                    774:
1.5       dsainty   775: /* ARGSUSED */
1.1       augustss  776: Static int
1.17      christos  777: ustir_close(void *h, int flag, int mode,
                    778:     struct lwp *l)
1.1       augustss  779: {
                    780:        struct ustir_softc *sc = h;
                    781:
1.3       augustss  782:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss  783:
                    784:        sc->sc_refcnt++;
                    785:
                    786:        sc->sc_rd_readinprogress = 1;
                    787:        sc->sc_closing = 1;
                    788:
                    789:        wakeup(&sc->sc_thread);
                    790:
                    791:        while (sc->sc_thread != NULL)
                    792:                tsleep(&sc->sc_closing, PWAIT, "usircl", 0);
                    793:
                    794:        if (sc->sc_rd_pipe != NULL) {
                    795:                usbd_abort_pipe(sc->sc_rd_pipe);
                    796:                sc->sc_rd_pipe = NULL;
                    797:        }
                    798:        if (sc->sc_wr_pipe != NULL) {
                    799:                usbd_abort_pipe(sc->sc_wr_pipe);
                    800:                sc->sc_wr_pipe = NULL;
                    801:        }
                    802:        if (sc->sc_rd_xfer != NULL) {
1.34      skrll     803:                usbd_destroy_xfer(sc->sc_rd_xfer);
1.1       augustss  804:                sc->sc_rd_xfer = NULL;
                    805:                sc->sc_rd_buf = NULL;
                    806:        }
                    807:        if (sc->sc_wr_xfer != NULL) {
1.34      skrll     808:                usbd_destroy_xfer(sc->sc_wr_xfer);
1.1       augustss  809:                sc->sc_wr_xfer = NULL;
                    810:                sc->sc_wr_buf = NULL;
                    811:        }
                    812:        if (sc->sc_ur_buf != NULL) {
1.34      skrll     813:                kmem_free(sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
1.1       augustss  814:                sc->sc_ur_buf = NULL;
                    815:        }
1.34      skrll     816:        if (sc->sc_rd_pipe != NULL) {
                    817:                usbd_close_pipe(sc->sc_rd_pipe);
                    818:                sc->sc_rd_pipe = NULL;
                    819:        }
                    820:        if (sc->sc_wr_pipe != NULL) {
                    821:                usbd_close_pipe(sc->sc_wr_pipe);
                    822:                sc->sc_wr_pipe = NULL;
                    823:        }
1.1       augustss  824:
                    825:        if (--sc->sc_refcnt < 0)
1.32      mrg       826:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss  827:
                    828:        return 0;
                    829: }
                    830:
1.7       dsainty   831: /* ARGSUSED */
1.1       augustss  832: Static int
1.17      christos  833: ustir_read(void *h, struct uio *uio, int flag)
1.1       augustss  834: {
                    835:        struct ustir_softc *sc = h;
                    836:        int s;
                    837:        int error;
                    838:        u_int uframelen;
                    839:
1.3       augustss  840:        DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1       augustss  841:
                    842:        if (sc->sc_dying)
                    843:                return EIO;
                    844:
                    845: #ifdef DIAGNOSTIC
                    846:        if (sc->sc_rd_buf == NULL)
                    847:                return EINVAL;
                    848: #endif
                    849:
                    850:        sc->sc_refcnt++;
                    851:
                    852:        if (!sc->sc_rd_readinprogress && !USTIR_BLOCK_RX_DATA(sc))
                    853:                /* Possibly wake up polling thread */
                    854:                wakeup(&sc->sc_thread);
                    855:
                    856:        do {
                    857:                s = splusb();
                    858:                while (sc->sc_ur_framelen == 0) {
1.3       augustss  859:                        DPRINTFN(5,("%s: calling tsleep()\n", __func__));
1.1       augustss  860:                        error = tsleep(&sc->sc_ur_framelen, PZERO | PCATCH,
                    861:                                       "usirrd", 0);
                    862:                        if (sc->sc_dying)
                    863:                                error = EIO;
                    864:                        if (error) {
                    865:                                splx(s);
                    866:                                DPRINTFN(0, ("%s: tsleep() = %d\n",
1.3       augustss  867:                                             __func__, error));
1.1       augustss  868:                                goto ret;
                    869:                        }
                    870:                }
                    871:                splx(s);
                    872:
                    873:                uframelen = sc->sc_ur_framelen;
                    874:                DPRINTFN(1,("%s: sc=%p framelen=%u, hdr=0x%02x\n",
1.3       augustss  875:                            __func__, sc, uframelen, sc->sc_ur_buf[0]));
1.1       augustss  876:                if (uframelen > uio->uio_resid)
                    877:                        error = EINVAL;
                    878:                else
                    879:                        error = uiomove(sc->sc_ur_buf, uframelen, uio);
                    880:                sc->sc_ur_framelen = 0;
                    881:
                    882:                if (!deframe_rd_ur(sc) && uframelen > 0) {
                    883:                        /*
                    884:                         * Need to wait for another read to obtain a
                    885:                         * complete frame...  If we also obtained
                    886:                         * actual data, wake up the possibly sleeping
                    887:                         * thread immediately...
                    888:                         */
                    889:                        wakeup(&sc->sc_thread);
                    890:                }
                    891:        } while (uframelen == 0);
                    892:
1.3       augustss  893:        DPRINTFN(1,("%s: return %d\n", __func__, error));
1.1       augustss  894:
                    895:  ret:
                    896:        if (--sc->sc_refcnt < 0)
1.32      mrg       897:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss  898:        return error;
                    899: }
                    900:
1.7       dsainty   901: /* ARGSUSED */
1.1       augustss  902: Static int
1.17      christos  903: ustir_write(void *h, struct uio *uio, int flag)
1.1       augustss  904: {
                    905:        struct ustir_softc *sc = h;
                    906:        usbd_status err;
1.34      skrll     907:        uint32_t wrlen;
1.1       augustss  908:        int error, sirlength;
1.34      skrll     909:        uint8_t *wrbuf;
1.1       augustss  910:        int s;
                    911:
1.3       augustss  912:        DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1       augustss  913:
                    914:        if (sc->sc_dying)
                    915:                return EIO;
                    916:
                    917: #ifdef DIAGNOSTIC
                    918:        if (sc->sc_wr_buf == NULL)
                    919:                return EINVAL;
                    920: #endif
                    921:
                    922:        wrlen = uio->uio_resid;
                    923:        if (wrlen > sc->sc_params.maxsize)
                    924:                return EINVAL;
                    925:
                    926:        sc->sc_refcnt++;
                    927:
1.10      dsainty   928:        if (!USTIR_BLOCK_RX_DATA(sc)) {
                    929:                /*
                    930:                 * If reads are not blocked, determine what action we
                    931:                 * should potentially take...
                    932:                 */
                    933:                if (sc->sc_direction == udir_output) {
                    934:                        /*
                    935:                         * If the last operation was an output, wait for the
                    936:                         * polling thread to check for incoming data.
                    937:                         */
                    938:                        sc->sc_wr_stalewrite = 1;
                    939:                        wakeup(&sc->sc_thread);
                    940:                } else if (!sc->sc_rd_readinprogress &&
                    941:                           (sc->sc_direction == udir_idle ||
                    942:                            sc->sc_direction == udir_input)) {
                    943:                        /* If idle, check for input before outputting */
                    944:                        ustir_start_read(sc);
                    945:                }
                    946:        }
1.1       augustss  947:
                    948:        s = splusb();
1.10      dsainty   949:        while (sc->sc_wr_stalewrite ||
                    950:               (sc->sc_direction != udir_output &&
                    951:                sc->sc_direction != udir_idle)) {
                    952:                DPRINTFN(5, ("%s: sc=%p stalewrite=%d direction=%d, "
                    953:                             "calling tsleep()\n", __func__,
                    954:                             sc, sc->sc_wr_stalewrite, sc->sc_direction));
1.1       augustss  955:                error = tsleep(&sc->sc_wr_buf, PZERO | PCATCH,
                    956:                               "usirwr", 0);
                    957:                if (sc->sc_dying)
                    958:                        error = EIO;
                    959:                if (error) {
                    960:                        splx(s);
1.3       augustss  961:                        DPRINTFN(0, ("%s: tsleep() = %d\n", __func__,
1.1       augustss  962:                                     error));
                    963:                        goto ret;
                    964:                }
                    965:        }
                    966:        splx(s);
                    967:
                    968:        wrbuf = sc->sc_wr_buf;
                    969:
                    970:        /* Build header */
                    971:        wrbuf[0] = STIR_OUTPUT_HEADER_BYTE0;
                    972:        wrbuf[1] = STIR_OUTPUT_HEADER_BYTE1;
                    973:
                    974:        sirlength = irda_sir_frame(&wrbuf[STIR_OUTPUT_HEADER_SIZE],
                    975:                                   MAX_USTIR_OUTPUT_FRAME -
                    976:                                   STIR_OUTPUT_HEADER_SIZE,
                    977:                                   uio, sc->sc_params.ebofs);
                    978:        if (sirlength < 0) {
                    979:                error = -sirlength;
                    980:        } else {
1.34      skrll     981:                uint32_t btlen;
1.1       augustss  982:
1.3       augustss  983:                DPRINTFN(1, ("%s: transfer %u bytes\n", __func__,
1.1       augustss  984:                             (unsigned int)wrlen));
                    985:
                    986:                wrbuf[2] = sirlength & 0xff;
                    987:                wrbuf[3] = (sirlength >> 8) & 0xff;
                    988:
                    989:                btlen = STIR_OUTPUT_HEADER_SIZE + sirlength;
                    990:
                    991:                sc->sc_direction = udir_output;
                    992:
                    993: #ifdef USTIR_DEBUG
                    994:                if (ustirdebug >= 20)
1.3       augustss  995:                        ustir_dumpdata(wrbuf, btlen, __func__);
1.1       augustss  996: #endif
                    997:
                    998:                err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
1.34      skrll     999:                    USBD_FORCE_SHORT_XFER, USTIR_WR_TIMEOUT, wrbuf, &btlen);
1.3       augustss 1000:                DPRINTFN(2, ("%s: err=%d\n", __func__, err));
1.8       dsainty  1001:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1002:                        if (err == USBD_INTERRUPTED)
                   1003:                                error = EINTR;
                   1004:                        else if (err == USBD_TIMEOUT)
                   1005:                                error = ETIMEDOUT;
                   1006:                        else
                   1007:                                error = EIO;
                   1008:                } else {
                   1009:                        error = 0;
                   1010:                }
                   1011:        }
                   1012:
                   1013:  ret:
                   1014:        if (--sc->sc_refcnt < 0)
1.32      mrg      1015:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss 1016:
1.3       augustss 1017:        DPRINTFN(1,("%s: sc=%p done\n", __func__, sc));
1.1       augustss 1018:        return error;
                   1019: }
                   1020:
                   1021: Static int
1.15      christos 1022: ustir_poll(void *h, int events, struct lwp *l)
1.1       augustss 1023: {
                   1024:        struct ustir_softc *sc = h;
                   1025:        int revents = 0;
                   1026:
1.3       augustss 1027:        DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
1.1       augustss 1028:
                   1029:        if (events & (POLLOUT | POLLWRNORM)) {
                   1030:                if (sc->sc_direction != udir_input) {
                   1031:                        revents |= events & (POLLOUT | POLLWRNORM);
                   1032:                } else {
                   1033:                        DPRINTFN(2,("%s: recording write select\n",
1.3       augustss 1034:                                    __func__));
1.15      christos 1035:                        selrecord(l, &sc->sc_wr_sel);
1.1       augustss 1036:                }
                   1037:        }
                   1038:
                   1039:        if (events & (POLLIN | POLLRDNORM)) {
                   1040:                if (sc->sc_ur_framelen != 0) {
1.3       augustss 1041:                        DPRINTFN(2,("%s: have data\n", __func__));
1.1       augustss 1042:                        revents |= events & (POLLIN | POLLRDNORM);
                   1043:                } else {
                   1044:                        DPRINTFN(2,("%s: recording read select\n",
1.3       augustss 1045:                                    __func__));
1.15      christos 1046:                        selrecord(l, &sc->sc_rd_sel);
1.1       augustss 1047:                }
                   1048:        }
                   1049:
                   1050:        return revents;
1.4       jdolecek 1051: }
                   1052:
                   1053: static void
                   1054: filt_ustirrdetach(struct knote *kn)
                   1055: {
                   1056:        struct ustir_softc *sc = kn->kn_hook;
                   1057:        int s;
                   1058:
                   1059:        s = splusb();
1.6       christos 1060:        SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext);
1.4       jdolecek 1061:        splx(s);
                   1062: }
                   1063:
1.7       dsainty  1064: /* ARGSUSED */
1.4       jdolecek 1065: static int
1.17      christos 1066: filt_ustirread(struct knote *kn, long hint)
1.4       jdolecek 1067: {
                   1068:        struct ustir_softc *sc = kn->kn_hook;
                   1069:
                   1070:        kn->kn_data = sc->sc_ur_framelen;
1.34      skrll    1071:        return kn->kn_data > 0;
1.4       jdolecek 1072: }
                   1073:
                   1074: static void
                   1075: filt_ustirwdetach(struct knote *kn)
                   1076: {
                   1077:        struct ustir_softc *sc = kn->kn_hook;
                   1078:        int s;
                   1079:
                   1080:        s = splusb();
1.6       christos 1081:        SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext);
1.4       jdolecek 1082:        splx(s);
                   1083: }
                   1084:
1.7       dsainty  1085: /* ARGSUSED */
1.4       jdolecek 1086: static int
1.17      christos 1087: filt_ustirwrite(struct knote *kn, long hint)
1.4       jdolecek 1088: {
                   1089:        struct ustir_softc *sc = kn->kn_hook;
                   1090:
                   1091:        kn->kn_data = 0;
1.34      skrll    1092:        return sc->sc_direction != udir_input;
1.4       jdolecek 1093: }
                   1094:
                   1095: static const struct filterops ustirread_filtops =
                   1096:        { 1, NULL, filt_ustirrdetach, filt_ustirread };
                   1097: static const struct filterops ustirwrite_filtops =
                   1098:        { 1, NULL, filt_ustirwdetach, filt_ustirwrite };
                   1099:
                   1100: Static int
                   1101: ustir_kqfilter(void *h, struct knote *kn)
                   1102: {
                   1103:        struct ustir_softc *sc = h;
                   1104:        struct klist *klist;
                   1105:        int s;
                   1106:
                   1107:        switch (kn->kn_filter) {
                   1108:        case EVFILT_READ:
1.6       christos 1109:                klist = &sc->sc_rd_sel.sel_klist;
1.4       jdolecek 1110:                kn->kn_fop = &ustirread_filtops;
                   1111:                break;
                   1112:        case EVFILT_WRITE:
1.6       christos 1113:                klist = &sc->sc_wr_sel.sel_klist;
1.4       jdolecek 1114:                kn->kn_fop = &ustirwrite_filtops;
                   1115:                break;
                   1116:        default:
1.34      skrll    1117:                return EINVAL;
1.4       jdolecek 1118:        }
                   1119:
                   1120:        kn->kn_hook = sc;
                   1121:
                   1122:        s = splusb();
                   1123:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
                   1124:        splx(s);
                   1125:
1.34      skrll    1126:        return 0;
1.1       augustss 1127: }
                   1128:
                   1129: #ifdef USTIR_DEBUG_IOCTLS
1.18      christos 1130: Static int ustir_ioctl(void *h, u_long cmd, void *addr, int flag, struct lwp *l)
1.1       augustss 1131: {
                   1132:        struct ustir_softc *sc = h;
                   1133:        int error;
                   1134:        unsigned int regnum;
                   1135:        usbd_status err;
1.34      skrll    1136:        uint8_t regdata;
1.1       augustss 1137:
                   1138:        if (sc->sc_dying)
                   1139:                return EIO;
                   1140:
                   1141:        sc->sc_refcnt++;
                   1142:
                   1143:        error = 0;
                   1144:        switch (cmd) {
                   1145:        case USTIR_READ_REGISTER:
1.2       augustss 1146:                regnum = *(unsigned int *)addr;
1.1       augustss 1147:
                   1148:                if (regnum > STIR_MAX_REG) {
                   1149:                        error = EINVAL;
                   1150:                        break;
                   1151:                }
                   1152:
                   1153:                err = ustir_read_reg(sc, regnum, &regdata);
                   1154:
1.3       augustss 1155:                DPRINTFN(10, ("%s: regget(%u) = 0x%x\n", __func__,
1.1       augustss 1156:                              regnum, (unsigned int)regdata));
                   1157:
1.2       augustss 1158:                *(unsigned int *)addr = regdata;
1.8       dsainty  1159:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1160:                        printf("%s: register read failed: %s\n",
1.29      dyoung   1161:                               device_xname(sc->sc_dev),
1.1       augustss 1162:                               usbd_errstr(err));
                   1163:                        error = EIO;
                   1164:                }
                   1165:                break;
                   1166:
                   1167:        case USTIR_WRITE_REGISTER:
1.2       augustss 1168:                regnum = *(unsigned int *)addr;
1.1       augustss 1169:                regdata = (regnum >> 8) & 0xff;
                   1170:                regnum = regnum & 0xff;
                   1171:
                   1172:                if (regnum > STIR_MAX_REG) {
                   1173:                        error = EINVAL;
                   1174:                        break;
                   1175:                }
                   1176:
1.3       augustss 1177:                DPRINTFN(10, ("%s: regset(%u, 0x%x)\n", __func__,
1.1       augustss 1178:                              regnum, (unsigned int)regdata));
                   1179:
                   1180:                err = ustir_write_reg(sc, regnum, regdata);
1.8       dsainty  1181:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1182:                        printf("%s: register write failed: %s\n",
1.29      dyoung   1183:                               device_xname(sc->sc_dev),
1.1       augustss 1184:                               usbd_errstr(err));
                   1185:                        error = EIO;
                   1186:                }
                   1187:                break;
                   1188:
                   1189:        case USTIR_DEBUG_LEVEL:
                   1190: #ifdef USTIR_DEBUG
1.2       augustss 1191:                ustirdebug = *(int *)addr;
1.1       augustss 1192: #endif
                   1193:                break;
                   1194:
                   1195:        case USTIR_DEBUG_OPERATION:
                   1196:                break;
                   1197:
                   1198:        default:
                   1199:                error = EINVAL;
                   1200:                break;
                   1201:        }
                   1202:
                   1203:        if (--sc->sc_refcnt < 0)
1.32      mrg      1204:                usb_detach_wakeupold(sc->sc_dev);
1.1       augustss 1205:
                   1206:        return error;
                   1207: }
                   1208: #endif
                   1209:
                   1210: Static int
                   1211: ustir_set_params(void *h, struct irda_params *p)
                   1212: {
                   1213:        struct ustir_softc *sc = h;
                   1214:        struct ustir_speedrec const *speedblk;
                   1215:        int i;
                   1216:
1.3       augustss 1217:        DPRINTFN(0, ("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__,
1.1       augustss 1218:                     sc, p->speed, p->ebofs, p->maxsize));
                   1219:
                   1220:        if (sc->sc_dying)
                   1221:                return EIO;
                   1222:
                   1223:        speedblk = NULL;
                   1224:
                   1225:        if (sc->sc_speedrec == NULL || p->speed != sc->sc_speedrec->speed) {
                   1226:                /* find speed */
                   1227:                for (i = 0; i < USTIR_NSPEEDS; i++) {
                   1228:                        if (ustir_speeds[i].speed == p->speed) {
                   1229:                                speedblk = &ustir_speeds[i];
                   1230:                                goto found2;
                   1231:                        }
                   1232:                }
                   1233:                /* no good value found */
                   1234:                return EINVAL;
                   1235:        found2:
                   1236:                ;
                   1237:        }
                   1238:        if (p->maxsize != sc->sc_params.maxsize) {
                   1239:                if (p->maxsize > IRDA_MAX_FRAME_SIZE)
                   1240:                        return EINVAL;
                   1241:                sc->sc_params.maxsize = p->maxsize;
                   1242:        }
                   1243:
                   1244:        sc->sc_params = *p;
                   1245:
                   1246:        if (speedblk != NULL) {
                   1247:                usbd_status err;
1.34      skrll    1248:                uint8_t regmode;
                   1249:                uint8_t regbrate;
1.1       augustss 1250:
                   1251:                sc->sc_speedrec = speedblk;
                   1252:
                   1253:                regmode = STIR_BRMODE_MODEREG(speedblk->config);
                   1254:                regbrate = STIR_BRMODE_BRATEREG(speedblk->config);
                   1255:
                   1256:                /*
                   1257:                 * FFSPRST must be set to enable the FIFO.
                   1258:                 */
                   1259:                regmode |= STIR_RMODE_FFSPRST;
                   1260:
1.3       augustss 1261:                DPRINTFN(10, ("%s: setting BRATE = %x\n", __func__,
1.1       augustss 1262:                              (unsigned int)regbrate));
                   1263:                err = ustir_write_reg(sc, STIR_REG_BRATE, regbrate);
1.8       dsainty  1264:                if (err == USBD_NORMAL_COMPLETION) {
1.3       augustss 1265:                        DPRINTFN(10, ("%s: setting MODE = %x\n", __func__,
1.1       augustss 1266:                                      (unsigned int)regmode));
                   1267:                        err = ustir_write_reg(sc, STIR_REG_MODE, regmode);
                   1268:                }
1.8       dsainty  1269:                if (err != USBD_NORMAL_COMPLETION) {
1.1       augustss 1270:                        DPRINTFN(10, ("%s: error setting register: %s\n",
1.3       augustss 1271:                                      __func__, usbd_errstr(err)));
1.1       augustss 1272:                        return EIO;
                   1273:                }
                   1274:        }
                   1275:
                   1276:        return 0;
                   1277: }
                   1278:
                   1279: Static int
                   1280: ustir_get_speeds(void *h, int *speeds)
                   1281: {
                   1282:        struct ustir_softc *sc = h;
                   1283:
1.3       augustss 1284:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss 1285:
                   1286:        if (sc->sc_dying)
                   1287:                return EIO;
                   1288:
                   1289:        /* All these speeds are supported */
                   1290:        *speeds = IRDA_SPEED_4000000 |
                   1291:                IRDA_SPEED_1152000 |
                   1292:                IRDA_SPEED_576000 |
                   1293:                IRDA_SPEED_115200 |
                   1294:                IRDA_SPEED_57600 |
                   1295:                IRDA_SPEED_38400 |
                   1296:                IRDA_SPEED_19200 |
                   1297:                IRDA_SPEED_9600 |
                   1298:                IRDA_SPEED_2400;
                   1299:
                   1300:        return 0;
                   1301: }
                   1302:
                   1303: Static int
                   1304: ustir_get_turnarounds(void *h, int *turnarounds)
                   1305: {
                   1306:        struct ustir_softc *sc = h;
                   1307:
1.3       augustss 1308:        DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
1.1       augustss 1309:
                   1310:        if (sc->sc_dying)
                   1311:                return EIO;
                   1312:
                   1313:        /*
                   1314:         * Documentation is on the light side with respect to
                   1315:         * turnaround time for this device.
                   1316:         */
                   1317:        *turnarounds = IRDA_TURNT_10000;
                   1318:
                   1319:        return 0;
                   1320: }

CVSweb <webmaster@jp.NetBSD.org>