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

Annotation of src/sys/dev/usb/utoppy.c, Revision 1.8.10.3

1.8.10.3! itohy       1: /*     $NetBSD: utoppy.c,v 1.9 2007/03/04 06:02:50 christos Exp $      */
1.1       scw         2:
                      3: /*-
                      4:  * Copyright (c) 2006 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Steve C. Woodford.
                      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.8.10.3! itohy      40: __KERNEL_RCSID(0, "$NetBSD: utoppy.c,v 1.9 2007/03/04 06:02:50 christos Exp $");
1.1       scw        41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/proc.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/fcntl.h>
                     47: #include <sys/device.h>
                     48: #include <sys/malloc.h>
                     49: #include <sys/ioctl.h>
                     50: #include <sys/uio.h>
                     51: #include <sys/conf.h>
                     52: #include <sys/vnode.h>
                     53:
                     54: #include <dev/usb/usb.h>
                     55: #include <dev/usb/usbdi.h>
                     56: #include <dev/usb/usbdi_util.h>
                     57: #include <dev/usb/usbdevs.h>
                     58: #include <dev/usb/usb_quirks.h>
                     59: #include <dev/usb/utoppy.h>
                     60:
                     61: #undef UTOPPY_DEBUG
                     62: #ifdef UTOPPY_DEBUG
                     63: #define        UTOPPY_DBG_OPEN         0x0001
                     64: #define        UTOPPY_DBG_CLOSE        0x0002
                     65: #define        UTOPPY_DBG_READ         0x0004
                     66: #define        UTOPPY_DBG_WRITE        0x0008
                     67: #define        UTOPPY_DBG_IOCTL        0x0010
                     68: #define        UTOPPY_DBG_SEND_PACKET  0x0020
                     69: #define        UTOPPY_DBG_RECV_PACKET  0x0040
                     70: #define        UTOPPY_DBG_ADDPATH      0x0080
                     71: #define        UTOPPY_DBG_READDIR      0x0100
                     72: #define        UTOPPY_DBG_DUMP         0x0200
                     73: #define        DPRINTF(l, m)                           \
                     74:                do {                            \
                     75:                        if (utoppy_debug & l)   \
                     76:                                printf m;       \
                     77:                } while (/*CONSTCOND*/0)
                     78: static int utoppy_debug = 0;
                     79: static void utoppy_dump_packet(const void *, size_t);
                     80: #define        DDUMP_PACKET(p, l)                                      \
                     81:                do {                                            \
                     82:                        if (utoppy_debug & UTOPPY_DBG_DUMP)     \
                     83:                                utoppy_dump_packet((p), (l));   \
                     84:                } while (/*CONSTCOND*/0)
                     85: #else
                     86: #define        DPRINTF(l, m)           /* nothing */
                     87: #define        DDUMP_PACKET(p, l)      /* nothing */
                     88: #endif
                     89:
                     90:
                     91: #define        UTOPPY_CONFIG_NO        1
                     92: #define        UTOPPY_NUMENDPOINTS     2
                     93:
                     94: #define        UTOPPY_BSIZE            0xffff
                     95: #define        UTOPPY_FRAG_SIZE        0x1000
                     96: #define        UTOPPY_HEADER_SIZE      8
                     97: #define        UTOPPY_SHORT_TIMEOUT    (500)           /* 0.5 seconds */
                     98: #define        UTOPPY_LONG_TIMEOUT     (10 * 1000)     /* 10 seconds */
                     99:
                    100: /* Protocol Commands and Responses */
                    101: #define        UTOPPY_RESP_ERROR               0x0001
                    102: #define        UTOPPY_CMD_ACK                  0x0002
                    103: #define         UTOPPY_RESP_SUCCESS            UTOPPY_CMD_ACK
                    104: #define        UTOPPY_CMD_CANCEL               0x0003
                    105: #define        UTOPPY_CMD_READY                0x0100
                    106: #define        UTOPPY_CMD_RESET                0x0101
                    107: #define        UTOPPY_CMD_TURBO                0x0102
                    108: #define        UTOPPY_CMD_STATS                0x1000
                    109: #define  UTOPPY_RESP_STATS_DATA                0x1001
                    110: #define        UTOPPY_CMD_READDIR              0x1002
                    111: #define         UTOPPY_RESP_READDIR_DATA       0x1003
                    112: #define         UTOPPY_RESP_READDIR_END        0x1004
                    113: #define        UTOPPY_CMD_DELETE               0x1005
                    114: #define        UTOPPY_CMD_RENAME               0x1006
                    115: #define        UTOPPY_CMD_MKDIR                0x1007
                    116: #define        UTOPPY_CMD_FILE                 0x1008
                    117: #define  UTOPPY_FILE_WRITE             0
                    118: #define  UTOPPY_FILE_READ              1
                    119: #define         UTOPPY_RESP_FILE_HEADER        0x1009
                    120: #define         UTOPPY_RESP_FILE_DATA          0x100a
                    121: #define         UTOPPY_RESP_FILE_END           0x100b
                    122:
                    123: enum utoppy_state {
                    124:        UTOPPY_STATE_CLOSED,
                    125:        UTOPPY_STATE_OPENING,
                    126:        UTOPPY_STATE_IDLE,
                    127:        UTOPPY_STATE_READDIR,
                    128:        UTOPPY_STATE_READFILE,
                    129:        UTOPPY_STATE_WRITEFILE
                    130: };
                    131:
                    132: struct utoppy_softc {
                    133:        USBBASEDEVICE sc_dev;
                    134:        usbd_device_handle sc_udev;     /* device */
                    135:        usbd_interface_handle sc_iface; /* interface */
                    136:        int sc_dying;
                    137:        int sc_refcnt;
                    138:
                    139:        enum utoppy_state sc_state;
                    140:        u_int sc_turbo_mode;
                    141:
                    142:        int sc_out;
                    143:        usbd_pipe_handle sc_out_pipe;   /* bulk out pipe */
                    144:        usbd_xfer_handle sc_out_xfer;
                    145:        void *sc_out_buf;
                    146:        void *sc_out_data;
                    147:        uint64_t sc_wr_offset;
                    148:        uint64_t sc_wr_size;
                    149:
                    150:        int sc_in;
                    151:        usbd_pipe_handle sc_in_pipe;    /* bulk in pipe */
                    152:        usbd_xfer_handle sc_in_xfer;
                    153:        void *sc_in_buf;
                    154:        void *sc_in_data;
                    155:        size_t sc_in_len;
                    156:        u_int sc_in_offset;
                    157: };
                    158:
                    159: struct utoppy_header {
                    160:        uint16_t h_len;
                    161:        uint16_t h_crc;
                    162:        uint16_t h_cmd2;
                    163:        uint16_t h_cmd;
                    164:        uint8_t h_data[0];
                    165: };
                    166: #define        UTOPPY_OUT_INIT(sc)                                     \
                    167:        do {                                                    \
                    168:                struct utoppy_header *_h = sc->sc_out_data;     \
                    169:                _h->h_len = 0;                                  \
                    170:        } while (/*CONSTCOND*/0)
                    171:
                    172: #define        UTOPPY_MJD_1970 40587u  /* MJD value for Jan 1 00:00:00 1970 */
                    173:
                    174: #define        UTOPPY_FTYPE_DIR        1
                    175: #define        UTOPPY_FTYPE_FILE       2
                    176:
                    177: #define        UTOPPY_IN_DATA(sc)      \
                    178:  ((void*)&(((uint8_t*)(sc)->sc_in_data)[(sc)->sc_in_offset+UTOPPY_HEADER_SIZE]))
                    179:
                    180: dev_type_open(utoppyopen);
                    181: dev_type_close(utoppyclose);
                    182: dev_type_read(utoppyread);
                    183: dev_type_write(utoppywrite);
                    184: dev_type_ioctl(utoppyioctl);
                    185:
                    186: const struct cdevsw utoppy_cdevsw = {
                    187:        utoppyopen, utoppyclose, utoppyread, utoppywrite, utoppyioctl,
1.6       christos  188:        nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
1.1       scw       189: };
                    190:
                    191: #define        UTOPPYUNIT(n)   (minor(n))
                    192:
                    193: USB_DECLARE_DRIVER(utoppy);
                    194:
                    195: USB_MATCH(utoppy)
                    196: {
                    197:        USB_MATCH_START(utoppy, uaa);
                    198:
                    199:        if (uaa->iface == NULL)
                    200:                return (UMATCH_NONE);
                    201:
                    202:        if (uaa->vendor == USB_VENDOR_TOPFIELD &&
                    203:            uaa->product == USB_PRODUCT_TOPFIELD_TF5000PVR)
                    204:                return (UMATCH_VENDOR_PRODUCT);
                    205:
                    206:        return (UMATCH_NONE);
                    207: }
                    208:
                    209: USB_ATTACH(utoppy)
                    210: {
                    211:        USB_ATTACH_START(utoppy, sc, uaa);
                    212:        usbd_device_handle dev = uaa->device;
                    213:        usb_endpoint_descriptor_t *ed;
                    214:        char *devinfop;
                    215:        u_int8_t epcount;
                    216:        int i;
                    217:
                    218:        devinfop = usbd_devinfo_alloc(dev, 0);
                    219:        USB_ATTACH_SETUP;
                    220:        printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop);
                    221:        usbd_devinfo_free(devinfop);
                    222:
                    223:        sc->sc_dying = 0;
                    224:        sc->sc_refcnt = 0;
                    225:        sc->sc_udev = dev;
                    226:
                    227:        epcount = 0;
                    228:        (void) usbd_endpoint_count(uaa->iface, &epcount);
                    229:        if (epcount != UTOPPY_NUMENDPOINTS) {
                    230:                printf("%s: Expected %d endpoints, got %d\n",
                    231:                    USBDEVNAME(sc->sc_dev), UTOPPY_NUMENDPOINTS, epcount);
                    232:                USB_ATTACH_ERROR_RETURN;
                    233:        }
                    234:
                    235:        sc->sc_in = -1;
                    236:        sc->sc_out = -1;
                    237:
                    238:        for (i = 0; i < epcount; i++) {
                    239:                ed = usbd_interface2endpoint_descriptor(uaa->iface, i);
                    240:                if (ed == NULL) {
                    241:                        printf("%s: couldn't get ep %d\n",
                    242:                            USBDEVNAME(sc->sc_dev), i);
                    243:                        USB_ATTACH_ERROR_RETURN;
                    244:                }
                    245:
                    246:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    247:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    248:                        sc->sc_in = ed->bEndpointAddress;
                    249:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                    250:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    251:                        sc->sc_out = ed->bEndpointAddress;
                    252:                }
                    253:        }
                    254:
                    255:        if (sc->sc_out == -1 || sc->sc_in == -1) {
                    256:                printf("%s: could not find bulk in/out endpoints\n",
                    257:                    USBDEVNAME(sc->sc_dev));
                    258:                sc->sc_dying = 1;
                    259:                USB_ATTACH_ERROR_RETURN;
                    260:        }
                    261:
                    262:        sc->sc_iface = uaa->iface;
                    263:        sc->sc_udev = dev;
                    264:
                    265:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    266:                           USBDEV(sc->sc_dev));
                    267:
                    268:        USB_ATTACH_SUCCESS_RETURN;
                    269: }
                    270:
                    271: int
                    272: utoppy_activate(device_ptr_t self, enum devact act)
                    273: {
                    274:        struct utoppy_softc *sc = (struct utoppy_softc *)self;
                    275:
                    276:        switch (act) {
                    277:        case DVACT_ACTIVATE:
                    278:                return (EOPNOTSUPP);
                    279:
                    280:        case DVACT_DEACTIVATE:
                    281:                sc->sc_dying = 1;
                    282:                break;
                    283:        }
                    284:        return (0);
                    285: }
                    286:
                    287: USB_DETACH(utoppy)
                    288: {
                    289:        USB_DETACH_START(utoppy, sc);
                    290:        int maj, mn;
                    291:        int s;
                    292:
                    293:        sc->sc_dying = 1;
                    294:        if (sc->sc_out_pipe != NULL)
                    295:                usbd_abort_pipe(sc->sc_out_pipe);
                    296:        if (sc->sc_in_pipe != NULL)
                    297:                usbd_abort_pipe(sc->sc_in_pipe);
                    298:
                    299:        if (sc->sc_in_xfer != NULL)
                    300:                usbd_free_xfer(sc->sc_in_xfer);
                    301:        if (sc->sc_out_xfer != NULL)
                    302:                usbd_free_xfer(sc->sc_out_xfer);
                    303:
1.8.10.2  itohy     304:        if (sc->sc_out_pipe != NULL)
                    305:                usbd_close_pipe(sc->sc_out_pipe);
                    306:        if (sc->sc_in_pipe != NULL)
                    307:                usbd_close_pipe(sc->sc_in_pipe);
                    308:
1.1       scw       309:        s = splusb();
                    310:        if (--sc->sc_refcnt >= 0)
                    311:                usb_detach_wait(USBDEV(sc->sc_dev));
                    312:        splx(s);
                    313:
                    314:        /* locate the major number */
                    315:        maj = cdevsw_lookup_major(&utoppy_cdevsw);
                    316:
                    317:        /* Nuke the vnodes for any open instances (calls close). */
                    318:        mn = self->dv_unit;
                    319:        vdevgone(maj, mn, mn, VCHR);
                    320:
                    321:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    322:                           USBDEV(sc->sc_dev));
                    323:
                    324:        return (0);
                    325: }
                    326:
                    327: static const uint16_t utoppy_crc16_lookup[] = {
                    328:        0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
                    329:        0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
                    330:        0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
                    331:        0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
                    332:        0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
                    333:        0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
                    334:        0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
                    335:        0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
                    336:        0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
                    337:        0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
                    338:        0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
                    339:        0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
                    340:        0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
                    341:        0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
                    342:        0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
                    343:        0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
                    344:        0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
                    345:        0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
                    346:        0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
                    347:        0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
                    348:        0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
                    349:        0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
                    350:        0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
                    351:        0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
                    352:        0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
                    353:        0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
                    354:        0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
                    355:        0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
                    356:        0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
                    357:        0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
                    358:        0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
                    359:        0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
                    360: };
                    361:
                    362: #define        UTOPPY_CRC16(ccrc,b)    \
                    363:        (utoppy_crc16_lookup[((ccrc) ^ (b)) & 0xffu] ^ ((ccrc) >> 8))
                    364:
                    365: static const int utoppy_usbdstatus_lookup[] = {
                    366:        0,              /* USBD_NORMAL_COMPLETION */
                    367:        EINPROGRESS,    /* USBD_IN_PROGRESS */
                    368:        EALREADY,       /* USBD_PENDING_REQUESTS */
                    369:        EAGAIN,         /* USBD_NOT_STARTED */
                    370:        EINVAL,         /* USBD_INVAL */
                    371:        ENOMEM,         /* USBD_NOMEM */
                    372:        ECONNRESET,     /* USBD_CANCELLED */
                    373:        EFAULT,         /* USBD_BAD_ADDRESS */
                    374:        EBUSY,          /* USBD_IN_USE */
                    375:        EADDRNOTAVAIL,  /* USBD_NO_ADDR */
                    376:        ENETDOWN,       /* USBD_SET_ADDR_FAILED */
                    377:        EIO,            /* USBD_NO_POWER */
                    378:        EMLINK,         /* USBD_TOO_DEEP */
                    379:        EIO,            /* USBD_IOERROR */
                    380:        ENXIO,          /* USBD_NOT_CONFIGURED */
                    381:        ETIMEDOUT,      /* USBD_TIMEOUT */
                    382:        EBADMSG,        /* USBD_SHORT_XFER */
                    383:        EHOSTDOWN,      /* USBD_STALLED */
                    384:        EINTR           /* USBD_INTERRUPTED */
                    385: };
                    386:
                    387: static __inline int
                    388: utoppy_usbd_status2errno(usbd_status err)
                    389: {
                    390:
                    391:        if (err >= USBD_ERROR_MAX)
                    392:                return (EFAULT);
                    393:        return (utoppy_usbdstatus_lookup[err]);
                    394: }
                    395:
                    396: #ifdef UTOPPY_DEBUG
                    397: static const char *
                    398: utoppy_state_string(enum utoppy_state state)
                    399: {
                    400:        const char *str;
                    401:
                    402:        switch (state) {
                    403:        case UTOPPY_STATE_CLOSED:
                    404:                str = "CLOSED";
                    405:                break;
                    406:        case UTOPPY_STATE_OPENING:
                    407:                str = "OPENING";
                    408:                break;
                    409:        case UTOPPY_STATE_IDLE:
                    410:                str = "IDLE";
                    411:                break;
                    412:        case UTOPPY_STATE_READDIR:
                    413:                str = "READ DIRECTORY";
                    414:                break;
                    415:        case UTOPPY_STATE_READFILE:
                    416:                str = "READ FILE";
                    417:                break;
                    418:        case UTOPPY_STATE_WRITEFILE:
                    419:                str = "WRITE FILE";
                    420:                break;
                    421:        default:
                    422:                str = "INVALID!";
                    423:                break;
                    424:        }
                    425:
                    426:        return (str);
                    427: }
                    428:
                    429: static void
                    430: utoppy_dump_packet(const void *b, size_t len)
                    431: {
                    432:        const uint8_t *buf = b, *l;
                    433:        uint8_t c;
                    434:        size_t i, j;
                    435:
                    436:        if (len == 0)
                    437:                return;
                    438:
                    439:        len = min(len, 256);
                    440:
                    441:        printf("00: ");
                    442:
                    443:        for (i = 0, l = buf; i < len; i++) {
                    444:                printf("%02x ", *buf++);
                    445:
                    446:                if ((i % 16) == 15) {
                    447:                        for (j = 0; j < 16; j++) {
                    448:                                c = *l++;
                    449:                                if (c < ' ' || c > 0x7e)
                    450:                                        c = '.';
                    451:                                printf("%c", c);
                    452:                        }
                    453:
                    454:                        printf("\n");
                    455:                        l = buf;
                    456:
                    457:                        if ((i + 1) < len)
                    458:                                printf("%02x: ", (u_int)i + 1);
                    459:                }
                    460:        }
                    461:
                    462:        while ((i++ % 16) != 0)
                    463:                printf("   ");
                    464:
                    465:        if (l < buf) {
                    466:                while (l < buf) {
                    467:                        c = *l++;
                    468:                        if (c < ' ' || c > 0x7e)
                    469:                                c = '.';
                    470:                        printf("%c", c);
                    471:                }
                    472:
                    473:                printf("\n");
                    474:        }
                    475: }
                    476: #endif
                    477:
                    478: /*
                    479:  * Very much like usbd_bulk_transfer(), except don't catch signals
                    480:  */
                    481: static void
1.7       christos  482: utoppy_bulk_transfer_cb(usbd_xfer_handle xfer,
1.8       christos  483:     usbd_private_handle priv,
                    484:     usbd_status status)
1.1       scw       485: {
                    486:
                    487:        wakeup(xfer);
                    488: }
                    489:
                    490: static usbd_status
                    491: utoppy_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
                    492:     u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size,
                    493:     const char *lbl)
                    494: {
                    495:        usbd_status err;
                    496:        int s, error;
                    497:
                    498:        usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
                    499:            utoppy_bulk_transfer_cb);
                    500:        s = splusb();
                    501:        err = usbd_transfer(xfer);
                    502:        if (err != USBD_IN_PROGRESS) {
                    503:                splx(s);
                    504:                return (err);
                    505:        }
1.8.10.3! itohy     506:        error = tsleep(xfer, PZERO, lbl, 0);
1.1       scw       507:        splx(s);
                    508:        if (error) {
                    509:                usbd_abort_pipe(pipe);
                    510:                return (USBD_INTERRUPTED);
                    511:        }
                    512:        usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
                    513:        return (err);
                    514: }
                    515:
                    516: static int
                    517: utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout)
                    518: {
                    519:        struct utoppy_header *h;
                    520:        usbd_status err;
                    521:        uint32_t len;
                    522:        uint16_t dlen, crc;
                    523:        uint8_t *data, *e, t1, t2;
                    524:
                    525:        h = sc->sc_out_data;
                    526:
                    527:        DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, "
                    528:            "len %d\n", USBDEVNAME(sc->sc_dev), (u_int)cmd, h->h_len));
                    529:
                    530:        dlen = h->h_len;
                    531:        len = dlen + UTOPPY_HEADER_SIZE;
                    532:
                    533:        if (len & 1)
                    534:                len++;
                    535:        if ((len % 64) == 0)
                    536:                len += 2;
                    537:
                    538:        if (len >= UTOPPY_BSIZE) {
                    539:                DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
                    540:                    "packet too big (%d)\n", USBDEVNAME(sc->sc_dev), (int)len));
                    541:                return (EINVAL);
                    542:        }
                    543:
                    544:        h->h_len = htole16(dlen + UTOPPY_HEADER_SIZE);
                    545:        h->h_cmd2 = 0;
                    546:        h->h_cmd = htole16(cmd);
                    547:
                    548:        /* The command word is part of the CRC */
                    549:        crc = UTOPPY_CRC16(0,   0);
                    550:        crc = UTOPPY_CRC16(crc, 0);
                    551:        crc = UTOPPY_CRC16(crc, cmd >> 8);
                    552:        crc = UTOPPY_CRC16(crc, cmd);
                    553:
                    554:        /*
                    555:         * If there is data following the header, calculate the CRC and
                    556:         * byte-swap as we go.
                    557:         */
                    558:        if (dlen) {
                    559:                data = h->h_data;
                    560:                e = data + (dlen & ~1);
                    561:
                    562:                do {
                    563:                        t1 = data[0];
                    564:                        t2 = data[1];
                    565:                        crc = UTOPPY_CRC16(crc, t1);
                    566:                        crc = UTOPPY_CRC16(crc, t2);
                    567:                        *data++ = t2;
                    568:                        *data++ = t1;
                    569:                } while (data < e);
                    570:
                    571:                if (dlen & 1) {
                    572:                        t1 = data[0];
                    573:                        crc = UTOPPY_CRC16(crc, t1);
                    574:                        data[1] = t1;
                    575:                }
                    576:        }
                    577:
                    578:        h->h_crc = htole16(crc);
                    579:        data = sc->sc_out_data;
                    580:
                    581:        DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: total len "
                    582:            "%d...\n", USBDEVNAME(sc->sc_dev), (int)len));
                    583:        DDUMP_PACKET(data, len);
                    584:
                    585:        do {
                    586:                uint32_t thislen;
                    587:
                    588:                thislen = min(len, UTOPPY_FRAG_SIZE);
                    589:
                    590:                memcpy(sc->sc_out_buf, data, thislen);
                    591:
                    592:                err = utoppy_bulk_transfer(sc->sc_out_xfer, sc->sc_out_pipe,
                    593:                    USBD_NO_COPY, timeout, sc->sc_out_buf, &thislen,
                    594:                    "utoppytx");
                    595:
                    596:                if (thislen != min(len, UTOPPY_FRAG_SIZE)) {
                    597:                        DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: "
                    598:                            "utoppy_send_packet: sent %ld, err %d\n",
                    599:                            USBDEVNAME(sc->sc_dev), (u_long)thislen, err));
                    600:                }
                    601:
                    602:                if (err == 0) {
                    603:                        len -= thislen;
                    604:                        data += thislen;
                    605:                }
                    606:        } while (err == 0 && len);
                    607:
                    608:        DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
                    609:            "usbd_bulk_transfer() returned %d.\n", USBDEVNAME(sc->sc_dev),err));
                    610:
                    611:        return (err ? utoppy_usbd_status2errno(err) : 0);
                    612: }
                    613:
                    614: static int
                    615: utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout)
                    616: {
                    617:        struct utoppy_header *h;
                    618:        usbd_status err;
                    619:        uint32_t len, thislen, requested, bytesleft;
1.4       scw       620:        uint16_t crc;
1.1       scw       621:        uint8_t *data, *e, t1, t2;
                    622:
                    623:        data = sc->sc_in_data;
                    624:        len = 0;
                    625:        bytesleft = UTOPPY_BSIZE;
                    626:
                    627:        DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n",
                    628:            USBDEVNAME(sc->sc_dev)));
                    629:
                    630:        do {
                    631:                requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE);
                    632:
                    633:                err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe,
                    634:                    USBD_NO_COPY | USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf,
                    635:                    &thislen, "utoppyrx");
                    636:
                    637:                DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
                    638:                    "usbd_bulk_transfer() returned %d, thislen %d, data %p\n",
                    639:                    USBDEVNAME(sc->sc_dev), err, (u_int)thislen, data));
                    640:
                    641:                if (err == 0) {
                    642:                        memcpy(data, sc->sc_in_buf, thislen);
                    643:                        DDUMP_PACKET(data, thislen);
                    644:                        len += thislen;
                    645:                        bytesleft -= thislen;
                    646:                        data += thislen;
                    647:                }
                    648:        } while (err == 0 && bytesleft && thislen == requested);
                    649:
                    650:        if (err)
                    651:                return (utoppy_usbd_status2errno(err));
                    652:
                    653:        h = sc->sc_in_data;
                    654:
                    655:        DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d "
                    656:            "bytes in total to %p\n", USBDEVNAME(sc->sc_dev), (u_int)len, h));
                    657:        DDUMP_PACKET(h, len);
                    658:
                    659:        if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) {
                    660:                DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad "
                    661:                    " length (len %d, h_len %d)\n", USBDEVNAME(sc->sc_dev),
                    662:                    (int)len, le16toh(h->h_len)));
                    663:                return (EIO);
                    664:        }
                    665:
                    666:        len = h->h_len = le16toh(h->h_len);
                    667:        h->h_crc = le16toh(h->h_crc);
                    668:        *respp = h->h_cmd = le16toh(h->h_cmd);
                    669:        h->h_cmd2 = le16toh(h->h_cmd2);
                    670:
                    671:        /*
                    672:         * To maximise data throughput when transferring files, acknowledge
                    673:         * data blocks as soon as we receive them. If we detect an error
                    674:         * later on, we can always cancel.
                    675:         */
                    676:        if (*respp == UTOPPY_RESP_FILE_DATA) {
                    677:                DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
                    678:                    "ACKing file data\n", USBDEVNAME(sc->sc_dev)));
                    679:
                    680:                UTOPPY_OUT_INIT(sc);
                    681:                err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
                    682:                    UTOPPY_SHORT_TIMEOUT);
                    683:                if (err) {
                    684:                        DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: "
                    685:                            "utoppy_recv_packet: failed to ACK file data: %d\n",
                    686:                            USBDEVNAME(sc->sc_dev), err));
                    687:                        return (err);
                    688:                }
                    689:        }
                    690:
                    691:        /* The command word is part of the CRC */
1.4       scw       692:        crc = UTOPPY_CRC16(0,   h->h_cmd2 >> 8);
                    693:        crc = UTOPPY_CRC16(crc, h->h_cmd2);
1.1       scw       694:        crc = UTOPPY_CRC16(crc, h->h_cmd >> 8);
                    695:        crc = UTOPPY_CRC16(crc, h->h_cmd);
                    696:
                    697:        /*
                    698:         * Extract any payload, byte-swapping and calculating the CRC16
                    699:         * as we go.
                    700:         */
                    701:        if (len > UTOPPY_HEADER_SIZE) {
                    702:                data = h->h_data;
                    703:                e = data + ((len & ~1) - UTOPPY_HEADER_SIZE);
                    704:
                    705:                while (data < e) {
                    706:                        t1 = data[0];
                    707:                        t2 = data[1];
                    708:                        crc = UTOPPY_CRC16(crc, t2);
                    709:                        crc = UTOPPY_CRC16(crc, t1);
                    710:                        *data++ = t2;
                    711:                        *data++ = t1;
                    712:                }
                    713:
                    714:                if (len & 1) {
                    715:                        t1 = data[1];
                    716:                        crc = UTOPPY_CRC16(crc, t1);
                    717:                        *data = t1;
                    718:                }
                    719:        }
                    720:
                    721:        sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE;
                    722:        sc->sc_in_offset = 0;
                    723:
                    724:        DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, "
                    725:            "crc 0x%04x, hdrcrc 0x%04x\n", USBDEVNAME(sc->sc_dev),
                    726:            (int)len, crc, h->h_crc));
                    727:        DDUMP_PACKET(h, len);
                    728:
                    729:        return ((crc == h->h_crc) ? 0 : EBADMSG);
                    730: }
                    731:
                    732: static __inline void *
                    733: utoppy_current_ptr(void *b)
                    734: {
                    735:        struct utoppy_header *h = b;
                    736:
                    737:        return (&h->h_data[h->h_len]);
                    738: }
                    739:
                    740: static __inline void
                    741: utoppy_advance_ptr(void *b, size_t len)
                    742: {
                    743:        struct utoppy_header *h = b;
                    744:
                    745:        h->h_len += len;
                    746: }
                    747:
                    748: static __inline void
                    749: utoppy_add_8(struct utoppy_softc *sc, uint8_t v)
                    750: {
                    751:        struct utoppy_header *h = sc->sc_out_data;
                    752:        uint8_t *p;
                    753:
                    754:        p = utoppy_current_ptr(h);
                    755:        *p = v;
                    756:        utoppy_advance_ptr(h, sizeof(v));
                    757: }
                    758:
                    759: static __inline void
                    760: utoppy_add_16(struct utoppy_softc *sc, uint16_t v)
                    761: {
                    762:        struct utoppy_header *h = sc->sc_out_data;
                    763:        uint8_t *p;
                    764:
                    765:        p = utoppy_current_ptr(h);
                    766:        *p++ = (uint8_t)(v >> 8);
                    767:        *p = (uint8_t)v;
                    768:        utoppy_advance_ptr(h, sizeof(v));
                    769: }
                    770:
                    771: static __inline void
                    772: utoppy_add_32(struct utoppy_softc *sc, uint32_t v)
                    773: {
                    774:        struct utoppy_header *h = sc->sc_out_data;
                    775:        uint8_t *p;
                    776:
                    777:        p = utoppy_current_ptr(h);
                    778:        *p++ = (uint8_t)(v >> 24);
                    779:        *p++ = (uint8_t)(v >> 16);
                    780:        *p++ = (uint8_t)(v >> 8);
                    781:        *p = (uint8_t)v;
                    782:        utoppy_advance_ptr(h, sizeof(v));
                    783: }
                    784:
                    785: static __inline void
                    786: utoppy_add_64(struct utoppy_softc *sc, uint64_t v)
                    787: {
                    788:        struct utoppy_header *h = sc->sc_out_data;
                    789:        uint8_t *p;
                    790:
                    791:        p = utoppy_current_ptr(h);
                    792:        *p++ = (uint8_t)(v >> 56);
                    793:        *p++ = (uint8_t)(v >> 48);
                    794:        *p++ = (uint8_t)(v >> 40);
                    795:        *p++ = (uint8_t)(v >> 32);
                    796:        *p++ = (uint8_t)(v >> 24);
                    797:        *p++ = (uint8_t)(v >> 16);
                    798:        *p++ = (uint8_t)(v >> 8);
                    799:        *p = (uint8_t)v;
                    800:        utoppy_advance_ptr(h, sizeof(v));
                    801: }
                    802:
                    803: static __inline void
                    804: utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len)
                    805: {
                    806:        struct utoppy_header *h = sc->sc_out_data;
                    807:        char *p;
                    808:
                    809:        p = utoppy_current_ptr(h);
                    810:        memset(p, 0, len);
                    811:        strncpy(p, str, len);
                    812:        utoppy_advance_ptr(h, len);
                    813: }
                    814:
                    815: static int
                    816: utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen)
                    817: {
                    818:        struct utoppy_header *h = sc->sc_out_data;
                    819:        uint8_t *p, *str, *s;
                    820:        size_t len;
                    821:        int err;
                    822:
                    823:        p = utoppy_current_ptr(h);
                    824:
                    825:        str = putlen ? (p + sizeof(uint16_t)) : p;
                    826:
                    827:        err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len);
                    828:
                    829:        DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n",
                    830:            err, (int)len));
                    831:
                    832:        if (err)
                    833:                return (err);
                    834:
                    835:        if (len < 2)
                    836:                return (EINVAL);
                    837:
                    838:        /*
                    839:         * copyinstr(9) has already copied the terminating NUL character,
                    840:         * but we append another one in case we have to pad the length
                    841:         * later on.
                    842:         */
                    843:        str[len] = '\0';
                    844:
                    845:        /*
                    846:         * The Toppy uses backslash as the directory separator, so convert
                    847:         * all forward slashes.
                    848:         */
                    849:        for (s = &str[len - 2]; s >= str; s--)
                    850:                if (*s == '/')
                    851:                        *s = '\\';
                    852:
                    853:        if ((len + h->h_len) & 1)
                    854:                len++;
                    855:
                    856:        if (putlen)
                    857:                utoppy_add_16(sc, len);
                    858:
                    859:        utoppy_advance_ptr(h, len);
                    860:
                    861:        DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n",
                    862:            (u_int)len));
                    863:
                    864:        return (0);
                    865: }
                    866:
                    867: static __inline int
                    868: utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp)
                    869: {
                    870:        uint8_t *p;
                    871:
                    872:        if (sc->sc_in_len < sizeof(*vp))
                    873:                return (1);
                    874:
                    875:        p = UTOPPY_IN_DATA(sc);
                    876:        *vp = *p;
                    877:        sc->sc_in_offset += sizeof(*vp);
                    878:        sc->sc_in_len -= sizeof(*vp);
                    879:        return (0);
                    880: }
                    881:
                    882: static __inline int
                    883: utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp)
                    884: {
                    885:        uint16_t v;
                    886:        uint8_t *p;
                    887:
                    888:        if (sc->sc_in_len < sizeof(v))
                    889:                return (1);
                    890:
                    891:        p = UTOPPY_IN_DATA(sc);
                    892:        v = *p++;
                    893:        v = (v << 8) | *p;
                    894:        *vp = v;
                    895:        sc->sc_in_offset += sizeof(v);
                    896:        sc->sc_in_len -= sizeof(v);
                    897:        return (0);
                    898: }
                    899:
                    900: static __inline int
                    901: utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp)
                    902: {
                    903:        uint32_t v;
                    904:        uint8_t *p;
                    905:
                    906:        if (sc->sc_in_len < sizeof(v))
                    907:                return (1);
                    908:
                    909:        p = UTOPPY_IN_DATA(sc);
                    910:        v = *p++;
                    911:        v = (v << 8) | *p++;
                    912:        v = (v << 8) | *p++;
                    913:        v = (v << 8) | *p;
                    914:        *vp = v;
                    915:        sc->sc_in_offset += sizeof(v);
                    916:        sc->sc_in_len -= sizeof(v);
                    917:        return (0);
                    918: }
                    919:
                    920: static __inline int
                    921: utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp)
                    922: {
                    923:        uint64_t v;
                    924:        uint8_t *p;
                    925:
                    926:        if (sc->sc_in_len < sizeof(v))
                    927:                return (1);
                    928:
                    929:        p = UTOPPY_IN_DATA(sc);
                    930:        v = *p++;
                    931:        v = (v << 8) | *p++;
                    932:        v = (v << 8) | *p++;
                    933:        v = (v << 8) | *p++;
                    934:        v = (v << 8) | *p++;
                    935:        v = (v << 8) | *p++;
                    936:        v = (v << 8) | *p++;
                    937:        v = (v << 8) | *p;
                    938:        *vp = v;
                    939:        sc->sc_in_offset += sizeof(v);
                    940:        sc->sc_in_len -= sizeof(v);
                    941:        return (0);
                    942: }
                    943:
                    944: static __inline int
                    945: utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len)
                    946: {
                    947:        char *p;
                    948:
                    949:        if (sc->sc_in_len < len)
                    950:                return (1);
                    951:
                    952:        memset(str, 0, len);
                    953:        p = UTOPPY_IN_DATA(sc);
                    954:        strncpy(str, p, len);
                    955:        sc->sc_in_offset += len;
                    956:        sc->sc_in_len -= len;
                    957:        return (0);
                    958: }
                    959:
                    960: static int
                    961: utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout,
                    962:     uint16_t *presp)
                    963: {
                    964:        int err;
                    965:
                    966:        err = utoppy_send_packet(sc, cmd, timeout);
                    967:        if (err)
                    968:                return (err);
                    969:
                    970:        err = utoppy_recv_packet(sc, presp, timeout);
                    971:        if (err == EBADMSG) {
                    972:                UTOPPY_OUT_INIT(sc);
                    973:                utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout);
                    974:        }
                    975:
                    976:        return (err);
                    977: }
                    978:
                    979: static int
                    980: utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp)
                    981: {
                    982:        uint16_t mjd;
                    983:        uint8_t hour, minute, sec;
                    984:        uint32_t rv;
                    985:
                    986:        if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) ||
                    987:            utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec))
                    988:                return (1);
                    989:
                    990:        if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){
                    991:                *tp = 0;
                    992:                return (0);
                    993:        }
                    994:
                    995:        rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd;
                    996:
                    997:        /* Calculate seconds since 1970 */
                    998:        rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24;
                    999:
                   1000:        /* Add in the hours, minutes, and seconds */
                   1001:        rv += (uint32_t)hour * 60 * 60;
                   1002:        rv += (uint32_t)minute * 60;
                   1003:        rv += sec;
                   1004:        *tp = (time_t)rv;
                   1005:
                   1006:        return (0);
                   1007: }
                   1008:
                   1009: static void
                   1010: utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t)
                   1011: {
                   1012:        u_int mjd, hour, minute;
                   1013:
                   1014:        mjd = t / (60 * 60 * 24);
                   1015:        t -= mjd * 60 * 60 * 24;
                   1016:
                   1017:        hour = t / (60 * 60);
                   1018:        t -= hour * 60 * 60;
                   1019:
                   1020:        minute = t / 60;
                   1021:        t -= minute * 60;
                   1022:
                   1023:        utoppy_add_16(sc, mjd + UTOPPY_MJD_1970);
                   1024:        utoppy_add_8(sc, hour);
                   1025:        utoppy_add_8(sc, minute);
                   1026:        utoppy_add_8(sc, t);
                   1027: }
                   1028:
                   1029: static int
                   1030: utoppy_turbo_mode(struct utoppy_softc *sc, int state)
                   1031: {
                   1032:        uint16_t r;
                   1033:        int err;
                   1034:
                   1035:        UTOPPY_OUT_INIT(sc);
                   1036:        utoppy_add_32(sc, state);
                   1037:
                   1038:        err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r);
                   1039:        if (err)
                   1040:                return (err);
                   1041:
                   1042:        return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO);
                   1043: }
                   1044:
                   1045: static int
                   1046: utoppy_check_ready(struct utoppy_softc *sc)
                   1047: {
                   1048:        uint16_t r;
                   1049:        int err;
                   1050:
                   1051:        UTOPPY_OUT_INIT(sc);
                   1052:
                   1053:        err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r);
                   1054:        if (err)
                   1055:                return (err);
                   1056:
                   1057:        return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO);
                   1058: }
                   1059:
                   1060: static int
                   1061: utoppy_cancel(struct utoppy_softc *sc)
                   1062: {
                   1063:        uint16_t r;
                   1064:        int err, i;
                   1065:
                   1066:        /*
                   1067:         * Issue the cancel command serveral times. the Toppy doesn't
                   1068:         * always respond to the first.
                   1069:         */
                   1070:        for (i = 0; i < 3; i++) {
                   1071:                UTOPPY_OUT_INIT(sc);
                   1072:                err = utoppy_command(sc, UTOPPY_CMD_CANCEL,
                   1073:                    UTOPPY_SHORT_TIMEOUT, &r);
                   1074:                if (err == 0 && r == UTOPPY_RESP_SUCCESS)
                   1075:                        break;
                   1076:                err = ETIMEDOUT;
                   1077:        }
                   1078:
                   1079:        if (err)
                   1080:                return (err);
                   1081:
                   1082:        /*
                   1083:         * Make sure turbo mode is off, otherwise the Toppy will not
                   1084:         * respond to remote control input.
                   1085:         */
                   1086:        (void) utoppy_turbo_mode(sc, 0);
                   1087:
                   1088:        sc->sc_state = UTOPPY_STATE_IDLE;
                   1089:        return (0);
                   1090: }
                   1091:
                   1092: static int
                   1093: utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us)
                   1094: {
                   1095:        uint32_t hsize, hfree;
                   1096:        uint16_t r;
                   1097:        int err;
                   1098:
                   1099:        UTOPPY_OUT_INIT(sc);
                   1100:        err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r);
                   1101:        if (err)
                   1102:                return (err);
                   1103:
                   1104:        if (r != UTOPPY_RESP_STATS_DATA)
                   1105:                return (EIO);
                   1106:
                   1107:        if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree))
                   1108:                return (EIO);
                   1109:
                   1110:        us->us_hdd_size = hsize;
                   1111:        us->us_hdd_size *= 1024;
                   1112:        us->us_hdd_free = hfree;
                   1113:        us->us_hdd_free *= 1024;
                   1114:
                   1115:        return (0);
                   1116: }
                   1117:
                   1118: static int
                   1119: utoppy_readdir_next(struct utoppy_softc *sc)
                   1120: {
                   1121:        uint16_t resp;
                   1122:        int err;
                   1123:
                   1124:        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n",
                   1125:            USBDEVNAME(sc->sc_dev)));
                   1126:
                   1127:        /*
                   1128:         * Fetch the next READDIR response
                   1129:         */
                   1130:        err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
                   1131:        if (err) {
                   1132:                DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
                   1133:                    "utoppy_recv_packet() returned %d\n",
                   1134:                    USBDEVNAME(sc->sc_dev), err));
                   1135:                if (err == EBADMSG) {
                   1136:                        UTOPPY_OUT_INIT(sc);
                   1137:                        utoppy_send_packet(sc, UTOPPY_RESP_ERROR,
                   1138:                            UTOPPY_LONG_TIMEOUT);
                   1139:                }
                   1140:                utoppy_cancel(sc);
                   1141:                return (err);
                   1142:        }
                   1143:
                   1144:        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
                   1145:            "utoppy_recv_packet() returned %d, len %ld\n",
                   1146:            USBDEVNAME(sc->sc_dev), err, (u_long)sc->sc_in_len));
                   1147:
                   1148:        switch (resp) {
                   1149:        case UTOPPY_RESP_READDIR_DATA:
                   1150:                DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
                   1151:                    "UTOPPY_RESP_READDIR_DATA\n", USBDEVNAME(sc->sc_dev)));
                   1152:
                   1153:                UTOPPY_OUT_INIT(sc);
                   1154:                err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
                   1155:                    UTOPPY_LONG_TIMEOUT);
                   1156:                if (err) {
                   1157:                        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
                   1158:                            "utoppy_send_packet(ACK) returned %d\n",
                   1159:                            USBDEVNAME(sc->sc_dev), err));
                   1160:                        utoppy_cancel(sc);
                   1161:                        return (err);
                   1162:                }
                   1163:                sc->sc_state = UTOPPY_STATE_READDIR;
                   1164:                sc->sc_in_offset = 0;
                   1165:                break;
                   1166:
                   1167:        case UTOPPY_RESP_READDIR_END:
                   1168:                DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
                   1169:                    "UTOPPY_RESP_READDIR_END\n", USBDEVNAME(sc->sc_dev)));
                   1170:
                   1171:                UTOPPY_OUT_INIT(sc);
                   1172:                utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
                   1173:                sc->sc_state = UTOPPY_STATE_IDLE;
                   1174:                sc->sc_in_len = 0;
                   1175:                break;
                   1176:
                   1177:        default:
                   1178:                DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
                   1179:                    "bad response: 0x%x\n", USBDEVNAME(sc->sc_dev), resp));
                   1180:                sc->sc_state = UTOPPY_STATE_IDLE;
                   1181:                sc->sc_in_len = 0;
                   1182:                return (EIO);
                   1183:        }
                   1184:
                   1185:        return (0);
                   1186: }
                   1187:
                   1188: static size_t
                   1189: utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud)
                   1190: {
                   1191:        uint8_t ftype;
                   1192:
                   1193:        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left"
                   1194:            " %d\n", USBDEVNAME(sc->sc_dev), (int)sc->sc_in_len));
                   1195:
                   1196:        if (utoppy_timestamp_decode(sc, &ud->ud_mtime) ||
                   1197:            utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) ||
                   1198:            utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) ||
                   1199:            utoppy_get_32(sc, &ud->ud_attributes)) {
                   1200:                DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no "
                   1201:                    "more to decode\n", USBDEVNAME(sc->sc_dev)));
                   1202:                return (0);
                   1203:        }
                   1204:
                   1205:        switch (ftype) {
                   1206:        case UTOPPY_FTYPE_DIR:
                   1207:                ud->ud_type = UTOPPY_DIRENT_DIRECTORY;
                   1208:                break;
                   1209:        case UTOPPY_FTYPE_FILE:
                   1210:                ud->ud_type = UTOPPY_DIRENT_FILE;
                   1211:                break;
                   1212:        default:
                   1213:                ud->ud_type = UTOPPY_DIRENT_UNKNOWN;
                   1214:                break;
                   1215:        }
                   1216:
                   1217:        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', "
                   1218:            "size %lld, time 0x%08lx, attr 0x%08x\n", USBDEVNAME(sc->sc_dev),
                   1219:            (ftype == UTOPPY_FTYPE_DIR) ? "DIR" :
                   1220:            ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path,
                   1221:            ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes));
                   1222:
                   1223:        return (1);
                   1224: }
                   1225:
                   1226: static int
                   1227: utoppy_readfile_next(struct utoppy_softc *sc)
                   1228: {
                   1229:        uint64_t off;
                   1230:        uint16_t resp;
                   1231:        int err;
                   1232:
                   1233:        err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
                   1234:        if (err) {
                   1235:                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
                   1236:                    "utoppy_recv_packet() returned %d\n",
                   1237:                    USBDEVNAME(sc->sc_dev), err));
                   1238:                utoppy_cancel(sc);
                   1239:                return (err);
                   1240:        }
                   1241:
                   1242:        switch (resp) {
                   1243:        case UTOPPY_RESP_FILE_HEADER:
                   1244:                /* ACK it */
                   1245:                UTOPPY_OUT_INIT(sc);
                   1246:                err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
                   1247:                    UTOPPY_LONG_TIMEOUT);
                   1248:                if (err) {
                   1249:                        DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
                   1250:                            "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n",
                   1251:                            USBDEVNAME(sc->sc_dev), err));
                   1252:                        utoppy_cancel(sc);
                   1253:                        return (err);
                   1254:                }
                   1255:
                   1256:                sc->sc_in_len = 0;
                   1257:                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
                   1258:                    "FILE_HEADER done\n", USBDEVNAME(sc->sc_dev)));
                   1259:                break;
                   1260:
                   1261:        case UTOPPY_RESP_FILE_DATA:
                   1262:                /* Already ACK'd */
                   1263:                if (utoppy_get_64(sc, &off)) {
                   1264:                        DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
                   1265:                            "UTOPPY_RESP_FILE_DATA did not provide offset\n",
                   1266:                            USBDEVNAME(sc->sc_dev)));
                   1267:                        utoppy_cancel(sc);
                   1268:                        return (EBADMSG);
                   1269:                }
                   1270:
                   1271:                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
                   1272:                    "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n",
                   1273:                    USBDEVNAME(sc->sc_dev), off, (u_long)sc->sc_in_len));
                   1274:                break;
                   1275:
                   1276:        case UTOPPY_RESP_FILE_END:
                   1277:                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
                   1278:                    "UTOPPY_RESP_FILE_END: sending ACK\n",
                   1279:                    USBDEVNAME(sc->sc_dev)));
                   1280:                UTOPPY_OUT_INIT(sc);
                   1281:                utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
                   1282:                /*FALLTHROUGH*/
                   1283:
                   1284:        case UTOPPY_RESP_SUCCESS:
                   1285:                sc->sc_state = UTOPPY_STATE_IDLE;
                   1286:                (void) utoppy_turbo_mode(sc, 0);
                   1287:                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all "
                   1288:                    "done\n", USBDEVNAME(sc->sc_dev)));
                   1289:                break;
                   1290:
                   1291:        case UTOPPY_RESP_ERROR:
                   1292:        default:
                   1293:                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad "
                   1294:                    "response code 0x%0x\n", USBDEVNAME(sc->sc_dev), resp));
                   1295:                utoppy_cancel(sc);
                   1296:                return (EIO);
                   1297:        }
                   1298:
                   1299:        return (0);
                   1300: }
                   1301:
                   1302: int
1.8       christos 1303: utoppyopen(dev_t dev, int flag, int mode,
1.8.10.3! itohy    1304:     usb_proc_ptr p)
1.1       scw      1305: {
                   1306:        struct utoppy_softc *sc;
                   1307:        int error = 0;
                   1308:
                   1309:        USB_GET_SC_OPEN(utoppy, UTOPPYUNIT(dev), sc);
                   1310:
                   1311:        if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying)
                   1312:                return (ENXIO);
                   1313:
                   1314:        if (sc->sc_state != UTOPPY_STATE_CLOSED) {
                   1315:                DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n",
                   1316:                    USBDEVNAME(sc->sc_dev)));
                   1317:                return (EBUSY);
                   1318:        }
                   1319:
                   1320:        DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n",
                   1321:            USBDEVNAME(sc->sc_dev)));
                   1322:
                   1323:        sc->sc_refcnt++;
                   1324:        sc->sc_state = UTOPPY_STATE_OPENING;
                   1325:        sc->sc_turbo_mode = 0;
                   1326:        sc->sc_out_pipe = NULL;
                   1327:        sc->sc_in_pipe = NULL;
                   1328:
                   1329:        if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) {
                   1330:                DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(OUT) "
                   1331:                    "failed\n", USBDEVNAME(sc->sc_dev)));
                   1332:                error = EIO;
                   1333:                goto done;
                   1334:        }
                   1335:
                   1336:        if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) {
                   1337:                DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(IN) "
                   1338:                    "failed\n", USBDEVNAME(sc->sc_dev)));
                   1339:                error = EIO;
                   1340:                usbd_close_pipe(sc->sc_out_pipe);
                   1341:                sc->sc_out_pipe = NULL;
1.5       scw      1342:                goto done;
1.1       scw      1343:        }
                   1344:
1.8.10.2  itohy    1345:        sc->sc_out_xfer = usbd_alloc_xfer(sc->sc_udev, sc->sc_out_pipe);
                   1346:        if (sc->sc_out_xfer == NULL) {
                   1347:                error = ENOMEM;
                   1348:                goto error;
                   1349:        }
                   1350:
                   1351:        sc->sc_out_buf = usbd_alloc_buffer(sc->sc_out_xfer, UTOPPY_FRAG_SIZE);
                   1352:        if (sc->sc_out_buf == NULL) {
                   1353:                error = ENOMEM;
                   1354:                goto error;
                   1355:        }
                   1356:
                   1357:        sc->sc_in_xfer = usbd_alloc_xfer(sc->sc_udev, sc->sc_in_pipe);
                   1358:        if (sc->sc_in_xfer == NULL) {
                   1359:                error = ENOMEM;
                   1360:                goto error;
                   1361:        }
                   1362:
                   1363:        sc->sc_in_buf = usbd_alloc_buffer(sc->sc_in_xfer, UTOPPY_FRAG_SIZE);
                   1364:        if (sc->sc_in_buf == NULL) {
                   1365:                error = ENOMEM;
                   1366:                goto error;
                   1367:        }
                   1368:
1.1       scw      1369:        sc->sc_out_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK);
                   1370:        if (sc->sc_out_data == NULL) {
                   1371:                error = ENOMEM;
                   1372:                goto error;
                   1373:        }
                   1374:
                   1375:        sc->sc_in_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK);
                   1376:        if (sc->sc_in_data == NULL) {
                   1377:                free(sc->sc_out_data, M_DEVBUF);
                   1378:                sc->sc_out_data = NULL;
                   1379:                error = ENOMEM;
                   1380:                goto error;
                   1381:        }
                   1382:
                   1383:        if ((error = utoppy_cancel(sc)) != 0)
                   1384:                goto error;
                   1385:
                   1386:        if ((error = utoppy_check_ready(sc)) != 0) {
                   1387:                DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()"
                   1388:                    " returned %d\n", USBDEVNAME(sc->sc_dev), error));
                   1389:  error:
                   1390:                usbd_abort_pipe(sc->sc_out_pipe);
1.8.10.2  itohy    1391:                if (sc->sc_out_xfer)
                   1392:                        usbd_free_xfer(sc->sc_out_xfer);
1.1       scw      1393:                usbd_close_pipe(sc->sc_out_pipe);
                   1394:                sc->sc_out_pipe = NULL;
1.8.10.2  itohy    1395:                sc->sc_out_xfer = NULL;
1.1       scw      1396:                usbd_abort_pipe(sc->sc_in_pipe);
1.8.10.2  itohy    1397:                if (sc->sc_in_xfer)
                   1398:                        usbd_free_xfer(sc->sc_in_xfer);
1.1       scw      1399:                usbd_close_pipe(sc->sc_in_pipe);
                   1400:                sc->sc_in_pipe = NULL;
1.8.10.2  itohy    1401:                sc->sc_in_xfer = NULL;
1.1       scw      1402:        }
                   1403:
                   1404:  done:
                   1405:        sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE;
                   1406:
                   1407:        DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state "
                   1408:            "'%s'\n", USBDEVNAME(sc->sc_dev), error,
                   1409:            utoppy_state_string(sc->sc_state)));
                   1410:
                   1411:        if (--sc->sc_refcnt < 0)
                   1412:                usb_detach_wakeup(USBDEV(sc->sc_dev));
                   1413:
                   1414:        return (error);
                   1415: }
                   1416:
                   1417: int
1.8       christos 1418: utoppyclose(dev_t dev, int flag, int mode,
1.8.10.3! itohy    1419:     usb_proc_ptr p)
1.1       scw      1420: {
                   1421:        struct utoppy_softc *sc;
                   1422:        usbd_status err;
                   1423:
                   1424:        USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
                   1425:
                   1426:        DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n",
                   1427:            USBDEVNAME(sc->sc_dev)));
                   1428:
                   1429:        if (sc->sc_state < UTOPPY_STATE_IDLE) {
                   1430:                /* We are being forced to close before the open completed. */
                   1431:                DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:"
                   1432:                    " %s\n", USBDEVNAME(sc->sc_dev),
                   1433:                    utoppy_state_string(sc->sc_state)));
                   1434:                return (0);
                   1435:        }
                   1436:
1.3       christos 1437:        if (sc->sc_out_data)
                   1438:                (void) utoppy_cancel(sc);
1.1       scw      1439:
                   1440:        if (sc->sc_out_pipe != NULL) {
                   1441:                if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0)
                   1442:                        printf("usbd_abort_pipe(OUT) returned %d\n", err);
1.8.10.2  itohy    1443:                if (sc->sc_out_xfer)
                   1444:                        usbd_free_xfer(sc->sc_out_xfer);
1.1       scw      1445:                if ((err = usbd_close_pipe(sc->sc_out_pipe)) != 0)
                   1446:                        printf("usbd_close_pipe(OUT) returned %d\n", err);
                   1447:                sc->sc_out_pipe = NULL;
1.8.10.2  itohy    1448:                sc->sc_out_xfer = NULL;
1.1       scw      1449:        }
                   1450:
                   1451:        if (sc->sc_in_pipe != NULL) {
                   1452:                if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0)
                   1453:                        printf("usbd_abort_pipe(IN) returned %d\n", err);
1.8.10.2  itohy    1454:                if (sc->sc_in_xfer)
                   1455:                        usbd_free_xfer(sc->sc_in_xfer);
1.1       scw      1456:                if ((err = usbd_close_pipe(sc->sc_in_pipe)) != 0)
                   1457:                        printf("usbd_close_pipe(IN) returned %d\n", err);
                   1458:                sc->sc_in_pipe = NULL;
1.8.10.2  itohy    1459:                sc->sc_in_xfer = NULL;
1.1       scw      1460:        }
                   1461:
                   1462:        if (sc->sc_out_data) {
                   1463:                free(sc->sc_out_data, M_DEVBUF);
                   1464:                sc->sc_out_data = NULL;
                   1465:        }
                   1466:
                   1467:        if (sc->sc_in_data) {
                   1468:                free(sc->sc_in_data, M_DEVBUF);
                   1469:                sc->sc_in_data = NULL;
                   1470:        }
                   1471:
                   1472:        sc->sc_state = UTOPPY_STATE_CLOSED;
                   1473:
                   1474:        DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n",
                   1475:            USBDEVNAME(sc->sc_dev)));
                   1476:
                   1477:        return (0);
                   1478: }
                   1479:
                   1480: int
1.8       christos 1481: utoppyread(dev_t dev, struct uio *uio, int flags)
1.1       scw      1482: {
                   1483:        struct utoppy_softc *sc;
                   1484:        struct utoppy_dirent ud;
                   1485:        size_t len;
                   1486:        int err;
                   1487:
                   1488:        USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
                   1489:
                   1490:        if (sc->sc_dying)
                   1491:                return (EIO);
                   1492:
                   1493:        sc->sc_refcnt++;
                   1494:
                   1495:        DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n",
                   1496:            USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state)));
                   1497:
                   1498:        switch (sc->sc_state) {
                   1499:        case UTOPPY_STATE_READDIR:
                   1500:                err = 0;
                   1501:                while (err == 0 && uio->uio_resid >= sizeof(ud) &&
                   1502:                    sc->sc_state != UTOPPY_STATE_IDLE) {
                   1503:                        if (utoppy_readdir_decode(sc, &ud) == 0)
                   1504:                                err = utoppy_readdir_next(sc);
                   1505:                        else
                   1506:                        if ((err = uiomove(&ud, sizeof(ud), uio)) != 0)
                   1507:                                utoppy_cancel(sc);
                   1508:                }
                   1509:                break;
                   1510:
                   1511:        case UTOPPY_STATE_READFILE:
                   1512:                err = 0;
                   1513:                while (err == 0 && uio->uio_resid > 0 &&
                   1514:                    sc->sc_state != UTOPPY_STATE_IDLE) {
                   1515:                        DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: "
                   1516:                            "resid %ld, bytes_left %ld\n",
                   1517:                            USBDEVNAME(sc->sc_dev), (u_long)uio->uio_resid,
                   1518:                            (u_long)sc->sc_in_len));
                   1519:
                   1520:                        if (sc->sc_in_len == 0 &&
                   1521:                            (err = utoppy_readfile_next(sc)) != 0) {
                   1522:                                DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: "
                   1523:                                    "READFILE: utoppy_readfile_next returned "
                   1524:                                    "%d\n", USBDEVNAME(sc->sc_dev), err));
                   1525:                                break;
                   1526:                        }
                   1527:
                   1528:                        len = min(uio->uio_resid, sc->sc_in_len);
                   1529:                        if (len) {
                   1530:                                err = uiomove(UTOPPY_IN_DATA(sc), len, uio);
                   1531:                                if (err == 0) {
                   1532:                                        sc->sc_in_offset += len;
                   1533:                                        sc->sc_in_len -= len;
                   1534:                                }
                   1535:                        }
                   1536:                }
                   1537:                break;
                   1538:
                   1539:        case UTOPPY_STATE_IDLE:
                   1540:                err = 0;
                   1541:                break;
                   1542:
                   1543:        case UTOPPY_STATE_WRITEFILE:
                   1544:                err = EBUSY;
                   1545:                break;
                   1546:
                   1547:        default:
                   1548:                err = EIO;
                   1549:                break;
                   1550:        }
                   1551:
                   1552:        DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n",
                   1553:            USBDEVNAME(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
                   1554:
                   1555:        if (--sc->sc_refcnt < 0)
                   1556:                usb_detach_wakeup(USBDEV(sc->sc_dev));
                   1557:
                   1558:        return (err);
                   1559: }
                   1560:
                   1561: int
1.8       christos 1562: utoppywrite(dev_t dev, struct uio *uio, int flags)
1.1       scw      1563: {
                   1564:        struct utoppy_softc *sc;
                   1565:        uint16_t resp;
                   1566:        size_t len;
                   1567:        int err;
                   1568:
                   1569:        USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
                   1570:
                   1571:        if (sc->sc_dying)
                   1572:                return (EIO);
                   1573:
                   1574:        switch(sc->sc_state) {
                   1575:        case UTOPPY_STATE_WRITEFILE:
                   1576:                break;
                   1577:
                   1578:        case UTOPPY_STATE_IDLE:
                   1579:                return (0);
                   1580:
                   1581:        default:
                   1582:                return (EIO);
                   1583:        }
                   1584:
                   1585:        sc->sc_refcnt++;
                   1586:        err = 0;
                   1587:
                   1588:        DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid %ld, "
                   1589:            "wr_size %lld, wr_offset %lld\n", USBDEVNAME(sc->sc_dev),
                   1590:            (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset));
                   1591:
                   1592:        while (sc->sc_state == UTOPPY_STATE_WRITEFILE &&
                   1593:            (len = min(uio->uio_resid, sc->sc_wr_size)) != 0) {
                   1594:
                   1595:                len = min(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE +
                   1596:                    sizeof(uint64_t) + 3));
                   1597:
                   1598:                DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n",
                   1599:                    USBDEVNAME(sc->sc_dev), (u_long)len));
                   1600:
                   1601:                UTOPPY_OUT_INIT(sc);
                   1602:                utoppy_add_64(sc, sc->sc_wr_offset);
                   1603:
                   1604:                err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio);
                   1605:                if (err) {
                   1606:                        DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove() "
                   1607:                            "returned %d\n", USBDEVNAME(sc->sc_dev), err));
                   1608:                        break;
                   1609:                }
                   1610:
                   1611:                utoppy_advance_ptr(sc->sc_out_data, len);
                   1612:
                   1613:                err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA,
                   1614:                    UTOPPY_LONG_TIMEOUT, &resp);
                   1615:                if (err) {
                   1616:                        DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
                   1617:                            "utoppy_command(UTOPPY_RESP_FILE_DATA) "
                   1618:                            "returned %d\n", USBDEVNAME(sc->sc_dev), err));
                   1619:                        break;
                   1620:                }
                   1621:                if (resp != UTOPPY_RESP_SUCCESS) {
                   1622:                        DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
                   1623:                            "utoppy_command(UTOPPY_RESP_FILE_DATA) returned "
                   1624:                            "bad response 0x%x\n", USBDEVNAME(sc->sc_dev),
                   1625:                            resp));
                   1626:                        utoppy_cancel(sc);
                   1627:                        err = EIO;
                   1628:                        break;
                   1629:                }
                   1630:
                   1631:                sc->sc_wr_offset += len;
                   1632:                sc->sc_wr_size -= len;
                   1633:        }
                   1634:
                   1635:        DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid %ld,"
                   1636:            " wr_size %lld, wr_offset %lld, err %d\n", USBDEVNAME(sc->sc_dev),
                   1637:            (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset, err));
                   1638:
                   1639:        if (err == 0 && sc->sc_wr_size == 0) {
                   1640:                DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending "
                   1641:                    "FILE_END...\n", USBDEVNAME(sc->sc_dev)));
                   1642:                UTOPPY_OUT_INIT(sc);
                   1643:                err = utoppy_command(sc, UTOPPY_RESP_FILE_END,
                   1644:                    UTOPPY_LONG_TIMEOUT, &resp);
                   1645:                if (err) {
                   1646:                        DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
                   1647:                            "utoppy_command(UTOPPY_RESP_FILE_END) returned "
                   1648:                            "%d\n", USBDEVNAME(sc->sc_dev), err));
                   1649:
                   1650:                        utoppy_cancel(sc);
                   1651:                }
                   1652:
                   1653:                sc->sc_state = UTOPPY_STATE_IDLE;
                   1654:                DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n",
                   1655:                    USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state)));
                   1656:        }
                   1657:
                   1658:        if (--sc->sc_refcnt < 0)
                   1659:                usb_detach_wakeup(USBDEV(sc->sc_dev));
                   1660:
                   1661:        return (err);
                   1662: }
                   1663:
                   1664: int
1.8.10.3! itohy    1665: utoppyioctl(dev_t dev, u_long cmd, usb_ioctlarg_t data, int flag,
        !          1666:     usb_proc_ptr p)
1.1       scw      1667: {
                   1668:        struct utoppy_softc *sc;
                   1669:        struct utoppy_rename *ur;
                   1670:        struct utoppy_readfile *urf;
                   1671:        struct utoppy_writefile *uw;
                   1672:        char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp;
                   1673:        uint16_t resp;
                   1674:        int err;
                   1675:
                   1676:        USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
                   1677:
                   1678:        if (sc->sc_dying)
                   1679:                return (EIO);
                   1680:
                   1681:        DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n",
                   1682:            USBDEVNAME(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state)));
                   1683:
                   1684:        if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) {
                   1685:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n",
                   1686:                    USBDEVNAME(sc->sc_dev)));
                   1687:                return (EBUSY);
                   1688:        }
                   1689:
                   1690:        sc->sc_refcnt++;
                   1691:
                   1692:        switch (cmd) {
                   1693:        case UTOPPYIOTURBO:
                   1694:                err = 0;
                   1695:                sc->sc_turbo_mode = *((int *)data) ? 1 : 0;
                   1696:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: "
                   1697:                    "%s\n", USBDEVNAME(sc->sc_dev), sc->sc_turbo_mode ? "On" :
                   1698:                    "Off"));
                   1699:                break;
                   1700:
                   1701:        case UTOPPYIOCANCEL:
                   1702:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n",
                   1703:                    USBDEVNAME(sc->sc_dev)));
                   1704:                err = utoppy_cancel(sc);
                   1705:                break;
                   1706:
                   1707:        case UTOPPYIOREBOOT:
                   1708:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n",
                   1709:                    USBDEVNAME(sc->sc_dev)));
                   1710:                UTOPPY_OUT_INIT(sc);
                   1711:                err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT,
                   1712:                    &resp);
                   1713:                if (err)
                   1714:                        break;
                   1715:
                   1716:                if (resp != UTOPPY_RESP_SUCCESS)
                   1717:                        err = EIO;
                   1718:                break;
                   1719:
                   1720:        case UTOPPYIOSTATS:
                   1721:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n",
                   1722:                    USBDEVNAME(sc->sc_dev)));
                   1723:                err = utoppy_stats(sc, (struct utoppy_stats *)data);
                   1724:                break;
                   1725:
                   1726:        case UTOPPYIORENAME:
                   1727:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n",
                   1728:                    USBDEVNAME(sc->sc_dev)));
                   1729:                ur = (struct utoppy_rename *)data;
                   1730:                UTOPPY_OUT_INIT(sc);
                   1731:
                   1732:                if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0)
                   1733:                        break;
                   1734:                if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0)
                   1735:                        break;
                   1736:
                   1737:                err = utoppy_command(sc, UTOPPY_CMD_RENAME, UTOPPY_LONG_TIMEOUT,
                   1738:                    &resp);
                   1739:                if (err)
                   1740:                        break;
                   1741:
                   1742:                if (resp != UTOPPY_RESP_SUCCESS)
                   1743:                        err = EIO;
                   1744:                break;
                   1745:
                   1746:        case UTOPPYIOMKDIR:
                   1747:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n",
                   1748:                    USBDEVNAME(sc->sc_dev)));
                   1749:                UTOPPY_OUT_INIT(sc);
                   1750:                err = utoppy_add_path(sc, *((const char **)data), 1);
                   1751:                if (err)
                   1752:                        break;
                   1753:
                   1754:                err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT,
                   1755:                    &resp);
                   1756:                if (err)
                   1757:                        break;
                   1758:
                   1759:                if (resp != UTOPPY_RESP_SUCCESS)
                   1760:                        err = EIO;
                   1761:                break;
                   1762:
                   1763:        case UTOPPYIODELETE:
                   1764:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n",
                   1765:                    USBDEVNAME(sc->sc_dev)));
                   1766:                UTOPPY_OUT_INIT(sc);
                   1767:                err = utoppy_add_path(sc, *((const char **)data), 0);
                   1768:                if (err)
                   1769:                        break;
                   1770:
                   1771:                err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT,
                   1772:                    &resp);
                   1773:                if (err)
                   1774:                        break;
                   1775:
                   1776:                if (resp != UTOPPY_RESP_SUCCESS)
                   1777:                        err = EIO;
                   1778:                break;
                   1779:
                   1780:        case UTOPPYIOREADDIR:
                   1781:                DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n",
                   1782:                    USBDEVNAME(sc->sc_dev)));
                   1783:                UTOPPY_OUT_INIT(sc);
                   1784:                err = utoppy_add_path(sc, *((const char **)data), 0);
                   1785:                if (err) {
                   1786:                        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
                   1787:                            "utoppy_add_path() returned %d\n",
                   1788:                            USBDEVNAME(sc->sc_dev), err));
                   1789:                        break;
                   1790:                }
                   1791:
                   1792:                err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR,
                   1793:                    UTOPPY_LONG_TIMEOUT);
                   1794:                if (err != 0) {
                   1795:                        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
                   1796:                            "UTOPPY_CMD_READDIR returned %d\n",
                   1797:                            USBDEVNAME(sc->sc_dev), err));
                   1798:                        break;
                   1799:                }
                   1800:
                   1801:                err = utoppy_readdir_next(sc);
                   1802:                if (err) {
                   1803:                        DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
                   1804:                            "utoppy_readdir_next() returned %d\n",
                   1805:                            USBDEVNAME(sc->sc_dev), err));
                   1806:                }
                   1807:                break;
                   1808:
                   1809:        case UTOPPYIOREADFILE:
                   1810:                urf = (struct utoppy_readfile *)data;
                   1811:
                   1812:                DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE "
                   1813:                    "%s, offset %lld\n", USBDEVNAME(sc->sc_dev), urf->ur_path,
                   1814:                    urf->ur_offset));
                   1815:
                   1816:                if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
                   1817:                        break;
                   1818:
                   1819:                UTOPPY_OUT_INIT(sc);
                   1820:                utoppy_add_8(sc, UTOPPY_FILE_READ);
                   1821:
                   1822:                if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0)
                   1823:                        break;
                   1824:
                   1825:                utoppy_add_64(sc, urf->ur_offset);
                   1826:
                   1827:                sc->sc_state = UTOPPY_STATE_READFILE;
                   1828:                sc->sc_in_offset = 0;
                   1829:
                   1830:                err = utoppy_send_packet(sc, UTOPPY_CMD_FILE,
                   1831:                    UTOPPY_LONG_TIMEOUT);
                   1832:                if (err == 0)
                   1833:                        err = utoppy_readfile_next(sc);
                   1834:                break;
                   1835:
                   1836:        case UTOPPYIOWRITEFILE:
                   1837:                uw = (struct utoppy_writefile *)data;
                   1838:
                   1839:                DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE "
                   1840:                    "%s, size %lld, offset %lld\n", USBDEVNAME(sc->sc_dev),
                   1841:                    uw->uw_path, uw->uw_size, uw->uw_offset));
                   1842:
                   1843:                if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
                   1844:                        break;
                   1845:
                   1846:                UTOPPY_OUT_INIT(sc);
                   1847:                utoppy_add_8(sc, UTOPPY_FILE_WRITE);
                   1848:                uwfp = utoppy_current_ptr(sc->sc_out_data);
                   1849:
                   1850:                if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) {
                   1851:                        DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path() "
                   1852:                            "returned %d\n", USBDEVNAME(sc->sc_dev), err));
                   1853:                        break;
                   1854:                }
                   1855:
                   1856:                strncpy(uwf, &uwfp[2], sizeof(uwf));
                   1857:                utoppy_add_64(sc, uw->uw_offset);
                   1858:
                   1859:                err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT,
                   1860:                    &resp);
                   1861:                if (err) {
                   1862:                        DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
                   1863:                            "utoppy_command(UTOPPY_CMD_FILE) returned "
                   1864:                            "%d\n", USBDEVNAME(sc->sc_dev), err));
                   1865:                        break;
                   1866:                }
                   1867:                if (resp != UTOPPY_RESP_SUCCESS) {
                   1868:                        DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
                   1869:                            "utoppy_command(UTOPPY_CMD_FILE) returned "
                   1870:                            "bad response 0x%x\n", USBDEVNAME(sc->sc_dev),
                   1871:                            resp));
                   1872:                        err = EIO;
                   1873:                        break;
                   1874:                }
                   1875:
                   1876:                UTOPPY_OUT_INIT(sc);
                   1877:                utoppy_timestamp_encode(sc, uw->uw_mtime);
                   1878:                utoppy_add_8(sc, UTOPPY_FTYPE_FILE);
                   1879:                utoppy_add_64(sc, uw->uw_size);
                   1880:                utoppy_add_string(sc, uwf, sizeof(uwf));
                   1881:                utoppy_add_32(sc, 0);
                   1882:
                   1883:                err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER,
                   1884:                    UTOPPY_LONG_TIMEOUT, &resp);
                   1885:                if (err) {
                   1886:                        DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
                   1887:                            "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
                   1888:                            "returned %d\n", USBDEVNAME(sc->sc_dev), err));
                   1889:                        break;
                   1890:                }
                   1891:                if (resp != UTOPPY_RESP_SUCCESS) {
                   1892:                        DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
                   1893:                            "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
                   1894:                            "returned bad response 0x%x\n",
                   1895:                            USBDEVNAME(sc->sc_dev), resp));
                   1896:                        err = EIO;
                   1897:                        break;
                   1898:                }
                   1899:
                   1900:                sc->sc_wr_offset = uw->uw_offset;
                   1901:                sc->sc_wr_size = uw->uw_size;
                   1902:                sc->sc_state = UTOPPY_STATE_WRITEFILE;
                   1903:
                   1904:                DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to "
                   1905:                    "%s. wr_offset %lld, wr_size %lld\n",
                   1906:                    USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state),
                   1907:                    sc->sc_wr_offset, sc->sc_wr_size));
                   1908:                break;
                   1909:
                   1910:        default:
                   1911:                DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n",
                   1912:                    USBDEVNAME(sc->sc_dev)));
                   1913:                err = ENODEV;
                   1914:                break;
                   1915:        }
                   1916:
                   1917:        DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n",
                   1918:            USBDEVNAME(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
                   1919:
                   1920:        if (err)
                   1921:                utoppy_cancel(sc);
                   1922:
                   1923:        if (--sc->sc_refcnt < 0)
                   1924:                usb_detach_wakeup(USBDEV(sc->sc_dev));
                   1925:
                   1926:        return (err);
                   1927: }

CVSweb <webmaster@jp.NetBSD.org>