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