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

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

CVSweb <webmaster@jp.NetBSD.org>