Home | History | Annotate | Line # | Download | only in usb
utoppy.c revision 1.10
      1 /*	$NetBSD: utoppy.c,v 1.10 2007/03/13 13:51:57 drochner 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 2007/03/13 13:51:57 drochner 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;
    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 	USB_ATTACH_SUCCESS_RETURN;
    301 
    302  fail2:	usbd_free_xfer(sc->sc_in_xfer);
    303 	sc->sc_in_xfer = NULL;
    304 
    305  fail1:	usbd_free_xfer(sc->sc_out_xfer);
    306 	sc->sc_out_xfer = NULL;
    307 
    308  fail0:	sc->sc_dying = 1;
    309 	USB_ATTACH_ERROR_RETURN;
    310 }
    311 
    312 int
    313 utoppy_activate(device_ptr_t self, enum devact act)
    314 {
    315 	struct utoppy_softc *sc = (struct utoppy_softc *)self;
    316 
    317 	switch (act) {
    318 	case DVACT_ACTIVATE:
    319 		return (EOPNOTSUPP);
    320 
    321 	case DVACT_DEACTIVATE:
    322 		sc->sc_dying = 1;
    323 		break;
    324 	}
    325 	return (0);
    326 }
    327 
    328 USB_DETACH(utoppy)
    329 {
    330 	USB_DETACH_START(utoppy, sc);
    331 	int maj, mn;
    332 	int s;
    333 
    334 	sc->sc_dying = 1;
    335 	if (sc->sc_out_pipe != NULL)
    336 		usbd_abort_pipe(sc->sc_out_pipe);
    337 	if (sc->sc_in_pipe != NULL)
    338 		usbd_abort_pipe(sc->sc_in_pipe);
    339 
    340 	if (sc->sc_in_xfer != NULL)
    341 		usbd_free_xfer(sc->sc_in_xfer);
    342 	if (sc->sc_out_xfer != NULL)
    343 		usbd_free_xfer(sc->sc_out_xfer);
    344 
    345 	s = splusb();
    346 	if (--sc->sc_refcnt >= 0)
    347 		usb_detach_wait(USBDEV(sc->sc_dev));
    348 	splx(s);
    349 
    350 	/* locate the major number */
    351 	maj = cdevsw_lookup_major(&utoppy_cdevsw);
    352 
    353 	/* Nuke the vnodes for any open instances (calls close). */
    354 	mn = self->dv_unit;
    355 	vdevgone(maj, mn, mn, VCHR);
    356 
    357 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    358 			   USBDEV(sc->sc_dev));
    359 
    360 	return (0);
    361 }
    362 
    363 static const uint16_t utoppy_crc16_lookup[] = {
    364 	0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    365 	0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    366 	0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    367 	0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    368 	0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    369 	0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    370 	0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    371 	0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    372 	0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    373 	0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    374 	0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    375 	0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    376 	0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    377 	0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    378 	0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    379 	0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    380 	0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    381 	0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    382 	0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    383 	0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    384 	0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    385 	0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    386 	0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    387 	0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    388 	0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    389 	0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    390 	0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    391 	0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    392 	0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    393 	0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    394 	0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    395 	0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    396 };
    397 
    398 #define	UTOPPY_CRC16(ccrc,b)	\
    399 	(utoppy_crc16_lookup[((ccrc) ^ (b)) & 0xffu] ^ ((ccrc) >> 8))
    400 
    401 static const int utoppy_usbdstatus_lookup[] = {
    402 	0,		/* USBD_NORMAL_COMPLETION */
    403 	EINPROGRESS,	/* USBD_IN_PROGRESS */
    404 	EALREADY,	/* USBD_PENDING_REQUESTS */
    405 	EAGAIN,		/* USBD_NOT_STARTED */
    406 	EINVAL,		/* USBD_INVAL */
    407 	ENOMEM,		/* USBD_NOMEM */
    408 	ECONNRESET,	/* USBD_CANCELLED */
    409 	EFAULT,		/* USBD_BAD_ADDRESS */
    410 	EBUSY,		/* USBD_IN_USE */
    411 	EADDRNOTAVAIL,	/* USBD_NO_ADDR */
    412 	ENETDOWN,	/* USBD_SET_ADDR_FAILED */
    413 	EIO,		/* USBD_NO_POWER */
    414 	EMLINK,		/* USBD_TOO_DEEP */
    415 	EIO,		/* USBD_IOERROR */
    416 	ENXIO,		/* USBD_NOT_CONFIGURED */
    417 	ETIMEDOUT,	/* USBD_TIMEOUT */
    418 	EBADMSG,	/* USBD_SHORT_XFER */
    419 	EHOSTDOWN,	/* USBD_STALLED */
    420 	EINTR		/* USBD_INTERRUPTED */
    421 };
    422 
    423 static __inline int
    424 utoppy_usbd_status2errno(usbd_status err)
    425 {
    426 
    427 	if (err >= USBD_ERROR_MAX)
    428 		return (EFAULT);
    429 	return (utoppy_usbdstatus_lookup[err]);
    430 }
    431 
    432 #ifdef UTOPPY_DEBUG
    433 static const char *
    434 utoppy_state_string(enum utoppy_state state)
    435 {
    436 	const char *str;
    437 
    438 	switch (state) {
    439 	case UTOPPY_STATE_CLOSED:
    440 		str = "CLOSED";
    441 		break;
    442 	case UTOPPY_STATE_OPENING:
    443 		str = "OPENING";
    444 		break;
    445 	case UTOPPY_STATE_IDLE:
    446 		str = "IDLE";
    447 		break;
    448 	case UTOPPY_STATE_READDIR:
    449 		str = "READ DIRECTORY";
    450 		break;
    451 	case UTOPPY_STATE_READFILE:
    452 		str = "READ FILE";
    453 		break;
    454 	case UTOPPY_STATE_WRITEFILE:
    455 		str = "WRITE FILE";
    456 		break;
    457 	default:
    458 		str = "INVALID!";
    459 		break;
    460 	}
    461 
    462 	return (str);
    463 }
    464 
    465 static void
    466 utoppy_dump_packet(const void *b, size_t len)
    467 {
    468 	const uint8_t *buf = b, *l;
    469 	uint8_t c;
    470 	size_t i, j;
    471 
    472 	if (len == 0)
    473 		return;
    474 
    475 	len = min(len, 256);
    476 
    477 	printf("00: ");
    478 
    479 	for (i = 0, l = buf; i < len; i++) {
    480 		printf("%02x ", *buf++);
    481 
    482 		if ((i % 16) == 15) {
    483 			for (j = 0; j < 16; j++) {
    484 				c = *l++;
    485 				if (c < ' ' || c > 0x7e)
    486 					c = '.';
    487 				printf("%c", c);
    488 			}
    489 
    490 			printf("\n");
    491 			l = buf;
    492 
    493 			if ((i + 1) < len)
    494 				printf("%02x: ", (u_int)i + 1);
    495 		}
    496 	}
    497 
    498 	while ((i++ % 16) != 0)
    499 		printf("   ");
    500 
    501 	if (l < buf) {
    502 		while (l < buf) {
    503 			c = *l++;
    504 			if (c < ' ' || c > 0x7e)
    505 				c = '.';
    506 			printf("%c", c);
    507 		}
    508 
    509 		printf("\n");
    510 	}
    511 }
    512 #endif
    513 
    514 /*
    515  * Very much like usbd_bulk_transfer(), except don't catch signals
    516  */
    517 static void
    518 utoppy_bulk_transfer_cb(usbd_xfer_handle xfer,
    519     usbd_private_handle priv,
    520     usbd_status status)
    521 {
    522 
    523 	wakeup(xfer);
    524 }
    525 
    526 static usbd_status
    527 utoppy_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
    528     u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size,
    529     const char *lbl)
    530 {
    531 	usbd_status err;
    532 	int s, error;
    533 
    534 	usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
    535 	    utoppy_bulk_transfer_cb);
    536 	s = splusb();
    537 	err = usbd_transfer(xfer);
    538 	if (err != USBD_IN_PROGRESS) {
    539 		splx(s);
    540 		return (err);
    541 	}
    542 	error = tsleep((void *)xfer, PZERO, lbl, 0);
    543 	splx(s);
    544 	if (error) {
    545 		usbd_abort_pipe(pipe);
    546 		return (USBD_INTERRUPTED);
    547 	}
    548 	usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
    549 	return (err);
    550 }
    551 
    552 static int
    553 utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout)
    554 {
    555 	struct utoppy_header *h;
    556 	usbd_status err;
    557 	uint32_t len;
    558 	uint16_t dlen, crc;
    559 	uint8_t *data, *e, t1, t2;
    560 
    561 	h = sc->sc_out_data;
    562 
    563 	DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, "
    564 	    "len %d\n", USBDEVNAME(sc->sc_dev), (u_int)cmd, h->h_len));
    565 
    566 	dlen = h->h_len;
    567 	len = dlen + UTOPPY_HEADER_SIZE;
    568 
    569 	if (len & 1)
    570 		len++;
    571 	if ((len % 64) == 0)
    572 		len += 2;
    573 
    574 	if (len >= UTOPPY_BSIZE) {
    575 		DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
    576 		    "packet too big (%d)\n", USBDEVNAME(sc->sc_dev), (int)len));
    577 		return (EINVAL);
    578 	}
    579 
    580 	h->h_len = htole16(dlen + UTOPPY_HEADER_SIZE);
    581 	h->h_cmd2 = 0;
    582 	h->h_cmd = htole16(cmd);
    583 
    584 	/* The command word is part of the CRC */
    585 	crc = UTOPPY_CRC16(0,   0);
    586 	crc = UTOPPY_CRC16(crc, 0);
    587 	crc = UTOPPY_CRC16(crc, cmd >> 8);
    588 	crc = UTOPPY_CRC16(crc, cmd);
    589 
    590 	/*
    591 	 * If there is data following the header, calculate the CRC and
    592 	 * byte-swap as we go.
    593 	 */
    594 	if (dlen) {
    595 		data = h->h_data;
    596 		e = data + (dlen & ~1);
    597 
    598 		do {
    599 			t1 = data[0];
    600 			t2 = data[1];
    601 			crc = UTOPPY_CRC16(crc, t1);
    602 			crc = UTOPPY_CRC16(crc, t2);
    603 			*data++ = t2;
    604 			*data++ = t1;
    605 		} while (data < e);
    606 
    607 		if (dlen & 1) {
    608 			t1 = data[0];
    609 			crc = UTOPPY_CRC16(crc, t1);
    610 			data[1] = t1;
    611 		}
    612 	}
    613 
    614 	h->h_crc = htole16(crc);
    615 	data = sc->sc_out_data;
    616 
    617 	DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: total len "
    618 	    "%d...\n", USBDEVNAME(sc->sc_dev), (int)len));
    619 	DDUMP_PACKET(data, len);
    620 
    621 	do {
    622 		uint32_t thislen;
    623 
    624 		thislen = min(len, UTOPPY_FRAG_SIZE);
    625 
    626 		memcpy(sc->sc_out_buf, data, thislen);
    627 
    628 		err = utoppy_bulk_transfer(sc->sc_out_xfer, sc->sc_out_pipe,
    629 		    USBD_NO_COPY, timeout, sc->sc_out_buf, &thislen,
    630 		    "utoppytx");
    631 
    632 		if (thislen != min(len, UTOPPY_FRAG_SIZE)) {
    633 			DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: "
    634 			    "utoppy_send_packet: sent %ld, err %d\n",
    635 			    USBDEVNAME(sc->sc_dev), (u_long)thislen, err));
    636 		}
    637 
    638 		if (err == 0) {
    639 			len -= thislen;
    640 			data += thislen;
    641 		}
    642 	} while (err == 0 && len);
    643 
    644 	DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
    645 	    "usbd_bulk_transfer() returned %d.\n", USBDEVNAME(sc->sc_dev),err));
    646 
    647 	return (err ? utoppy_usbd_status2errno(err) : 0);
    648 }
    649 
    650 static int
    651 utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout)
    652 {
    653 	struct utoppy_header *h;
    654 	usbd_status err;
    655 	uint32_t len, thislen, requested, bytesleft;
    656 	uint16_t crc;
    657 	uint8_t *data, *e, t1, t2;
    658 
    659 	data = sc->sc_in_data;
    660 	len = 0;
    661 	bytesleft = UTOPPY_BSIZE;
    662 
    663 	DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n",
    664 	    USBDEVNAME(sc->sc_dev)));
    665 
    666 	do {
    667 		requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE);
    668 
    669 		err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe,
    670 		    USBD_NO_COPY | USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf,
    671 		    &thislen, "utoppyrx");
    672 
    673 		DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
    674 		    "usbd_bulk_transfer() returned %d, thislen %d, data %p\n",
    675 		    USBDEVNAME(sc->sc_dev), err, (u_int)thislen, data));
    676 
    677 		if (err == 0) {
    678 			memcpy(data, sc->sc_in_buf, thislen);
    679 			DDUMP_PACKET(data, thislen);
    680 			len += thislen;
    681 			bytesleft -= thislen;
    682 			data += thislen;
    683 		}
    684 	} while (err == 0 && bytesleft && thislen == requested);
    685 
    686 	if (err)
    687 		return (utoppy_usbd_status2errno(err));
    688 
    689 	h = sc->sc_in_data;
    690 
    691 	DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d "
    692 	    "bytes in total to %p\n", USBDEVNAME(sc->sc_dev), (u_int)len, h));
    693 	DDUMP_PACKET(h, len);
    694 
    695 	if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) {
    696 		DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad "
    697 		    " length (len %d, h_len %d)\n", USBDEVNAME(sc->sc_dev),
    698 		    (int)len, le16toh(h->h_len)));
    699 		return (EIO);
    700 	}
    701 
    702 	len = h->h_len = le16toh(h->h_len);
    703 	h->h_crc = le16toh(h->h_crc);
    704 	*respp = h->h_cmd = le16toh(h->h_cmd);
    705 	h->h_cmd2 = le16toh(h->h_cmd2);
    706 
    707 	/*
    708 	 * To maximise data throughput when transferring files, acknowledge
    709 	 * data blocks as soon as we receive them. If we detect an error
    710 	 * later on, we can always cancel.
    711 	 */
    712 	if (*respp == UTOPPY_RESP_FILE_DATA) {
    713 		DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
    714 		    "ACKing file data\n", USBDEVNAME(sc->sc_dev)));
    715 
    716 		UTOPPY_OUT_INIT(sc);
    717 		err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
    718 		    UTOPPY_SHORT_TIMEOUT);
    719 		if (err) {
    720 			DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: "
    721 			    "utoppy_recv_packet: failed to ACK file data: %d\n",
    722 			    USBDEVNAME(sc->sc_dev), err));
    723 			return (err);
    724 		}
    725 	}
    726 
    727 	/* The command word is part of the CRC */
    728 	crc = UTOPPY_CRC16(0,   h->h_cmd2 >> 8);
    729 	crc = UTOPPY_CRC16(crc, h->h_cmd2);
    730 	crc = UTOPPY_CRC16(crc, h->h_cmd >> 8);
    731 	crc = UTOPPY_CRC16(crc, h->h_cmd);
    732 
    733 	/*
    734 	 * Extract any payload, byte-swapping and calculating the CRC16
    735 	 * as we go.
    736 	 */
    737 	if (len > UTOPPY_HEADER_SIZE) {
    738 		data = h->h_data;
    739 		e = data + ((len & ~1) - UTOPPY_HEADER_SIZE);
    740 
    741 		while (data < e) {
    742 			t1 = data[0];
    743 			t2 = data[1];
    744 			crc = UTOPPY_CRC16(crc, t2);
    745 			crc = UTOPPY_CRC16(crc, t1);
    746 			*data++ = t2;
    747 			*data++ = t1;
    748 		}
    749 
    750 		if (len & 1) {
    751 			t1 = data[1];
    752 			crc = UTOPPY_CRC16(crc, t1);
    753 			*data = t1;
    754 		}
    755 	}
    756 
    757 	sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE;
    758 	sc->sc_in_offset = 0;
    759 
    760 	DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, "
    761 	    "crc 0x%04x, hdrcrc 0x%04x\n", USBDEVNAME(sc->sc_dev),
    762 	    (int)len, crc, h->h_crc));
    763 	DDUMP_PACKET(h, len);
    764 
    765 	return ((crc == h->h_crc) ? 0 : EBADMSG);
    766 }
    767 
    768 static __inline void *
    769 utoppy_current_ptr(void *b)
    770 {
    771 	struct utoppy_header *h = b;
    772 
    773 	return (&h->h_data[h->h_len]);
    774 }
    775 
    776 static __inline void
    777 utoppy_advance_ptr(void *b, size_t len)
    778 {
    779 	struct utoppy_header *h = b;
    780 
    781 	h->h_len += len;
    782 }
    783 
    784 static __inline void
    785 utoppy_add_8(struct utoppy_softc *sc, uint8_t v)
    786 {
    787 	struct utoppy_header *h = sc->sc_out_data;
    788 	uint8_t *p;
    789 
    790 	p = utoppy_current_ptr(h);
    791 	*p = v;
    792 	utoppy_advance_ptr(h, sizeof(v));
    793 }
    794 
    795 static __inline void
    796 utoppy_add_16(struct utoppy_softc *sc, uint16_t v)
    797 {
    798 	struct utoppy_header *h = sc->sc_out_data;
    799 	uint8_t *p;
    800 
    801 	p = utoppy_current_ptr(h);
    802 	*p++ = (uint8_t)(v >> 8);
    803 	*p = (uint8_t)v;
    804 	utoppy_advance_ptr(h, sizeof(v));
    805 }
    806 
    807 static __inline void
    808 utoppy_add_32(struct utoppy_softc *sc, uint32_t v)
    809 {
    810 	struct utoppy_header *h = sc->sc_out_data;
    811 	uint8_t *p;
    812 
    813 	p = utoppy_current_ptr(h);
    814 	*p++ = (uint8_t)(v >> 24);
    815 	*p++ = (uint8_t)(v >> 16);
    816 	*p++ = (uint8_t)(v >> 8);
    817 	*p = (uint8_t)v;
    818 	utoppy_advance_ptr(h, sizeof(v));
    819 }
    820 
    821 static __inline void
    822 utoppy_add_64(struct utoppy_softc *sc, uint64_t v)
    823 {
    824 	struct utoppy_header *h = sc->sc_out_data;
    825 	uint8_t *p;
    826 
    827 	p = utoppy_current_ptr(h);
    828 	*p++ = (uint8_t)(v >> 56);
    829 	*p++ = (uint8_t)(v >> 48);
    830 	*p++ = (uint8_t)(v >> 40);
    831 	*p++ = (uint8_t)(v >> 32);
    832 	*p++ = (uint8_t)(v >> 24);
    833 	*p++ = (uint8_t)(v >> 16);
    834 	*p++ = (uint8_t)(v >> 8);
    835 	*p = (uint8_t)v;
    836 	utoppy_advance_ptr(h, sizeof(v));
    837 }
    838 
    839 static __inline void
    840 utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len)
    841 {
    842 	struct utoppy_header *h = sc->sc_out_data;
    843 	char *p;
    844 
    845 	p = utoppy_current_ptr(h);
    846 	memset(p, 0, len);
    847 	strncpy(p, str, len);
    848 	utoppy_advance_ptr(h, len);
    849 }
    850 
    851 static int
    852 utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen)
    853 {
    854 	struct utoppy_header *h = sc->sc_out_data;
    855 	uint8_t *p, *str, *s;
    856 	size_t len;
    857 	int err;
    858 
    859 	p = utoppy_current_ptr(h);
    860 
    861 	str = putlen ? (p + sizeof(uint16_t)) : p;
    862 
    863 	err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len);
    864 
    865 	DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n",
    866 	    err, (int)len));
    867 
    868 	if (err)
    869 		return (err);
    870 
    871 	if (len < 2)
    872 		return (EINVAL);
    873 
    874 	/*
    875 	 * copyinstr(9) has already copied the terminating NUL character,
    876 	 * but we append another one in case we have to pad the length
    877 	 * later on.
    878 	 */
    879 	str[len] = '\0';
    880 
    881 	/*
    882 	 * The Toppy uses backslash as the directory separator, so convert
    883 	 * all forward slashes.
    884 	 */
    885 	for (s = &str[len - 2]; s >= str; s--)
    886 		if (*s == '/')
    887 			*s = '\\';
    888 
    889 	if ((len + h->h_len) & 1)
    890 		len++;
    891 
    892 	if (putlen)
    893 		utoppy_add_16(sc, len);
    894 
    895 	utoppy_advance_ptr(h, len);
    896 
    897 	DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n",
    898 	    (u_int)len));
    899 
    900 	return (0);
    901 }
    902 
    903 static __inline int
    904 utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp)
    905 {
    906 	uint8_t *p;
    907 
    908 	if (sc->sc_in_len < sizeof(*vp))
    909 		return (1);
    910 
    911 	p = UTOPPY_IN_DATA(sc);
    912 	*vp = *p;
    913 	sc->sc_in_offset += sizeof(*vp);
    914 	sc->sc_in_len -= sizeof(*vp);
    915 	return (0);
    916 }
    917 
    918 static __inline int
    919 utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp)
    920 {
    921 	uint16_t v;
    922 	uint8_t *p;
    923 
    924 	if (sc->sc_in_len < sizeof(v))
    925 		return (1);
    926 
    927 	p = UTOPPY_IN_DATA(sc);
    928 	v = *p++;
    929 	v = (v << 8) | *p;
    930 	*vp = v;
    931 	sc->sc_in_offset += sizeof(v);
    932 	sc->sc_in_len -= sizeof(v);
    933 	return (0);
    934 }
    935 
    936 static __inline int
    937 utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp)
    938 {
    939 	uint32_t v;
    940 	uint8_t *p;
    941 
    942 	if (sc->sc_in_len < sizeof(v))
    943 		return (1);
    944 
    945 	p = UTOPPY_IN_DATA(sc);
    946 	v = *p++;
    947 	v = (v << 8) | *p++;
    948 	v = (v << 8) | *p++;
    949 	v = (v << 8) | *p;
    950 	*vp = v;
    951 	sc->sc_in_offset += sizeof(v);
    952 	sc->sc_in_len -= sizeof(v);
    953 	return (0);
    954 }
    955 
    956 static __inline int
    957 utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp)
    958 {
    959 	uint64_t v;
    960 	uint8_t *p;
    961 
    962 	if (sc->sc_in_len < sizeof(v))
    963 		return (1);
    964 
    965 	p = UTOPPY_IN_DATA(sc);
    966 	v = *p++;
    967 	v = (v << 8) | *p++;
    968 	v = (v << 8) | *p++;
    969 	v = (v << 8) | *p++;
    970 	v = (v << 8) | *p++;
    971 	v = (v << 8) | *p++;
    972 	v = (v << 8) | *p++;
    973 	v = (v << 8) | *p;
    974 	*vp = v;
    975 	sc->sc_in_offset += sizeof(v);
    976 	sc->sc_in_len -= sizeof(v);
    977 	return (0);
    978 }
    979 
    980 static __inline int
    981 utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len)
    982 {
    983 	char *p;
    984 
    985 	if (sc->sc_in_len < len)
    986 		return (1);
    987 
    988 	memset(str, 0, len);
    989 	p = UTOPPY_IN_DATA(sc);
    990 	strncpy(str, p, len);
    991 	sc->sc_in_offset += len;
    992 	sc->sc_in_len -= len;
    993 	return (0);
    994 }
    995 
    996 static int
    997 utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout,
    998     uint16_t *presp)
    999 {
   1000 	int err;
   1001 
   1002 	err = utoppy_send_packet(sc, cmd, timeout);
   1003 	if (err)
   1004 		return (err);
   1005 
   1006 	err = utoppy_recv_packet(sc, presp, timeout);
   1007 	if (err == EBADMSG) {
   1008 		UTOPPY_OUT_INIT(sc);
   1009 		utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout);
   1010 	}
   1011 
   1012 	return (err);
   1013 }
   1014 
   1015 static int
   1016 utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp)
   1017 {
   1018 	uint16_t mjd;
   1019 	uint8_t hour, minute, sec;
   1020 	uint32_t rv;
   1021 
   1022 	if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) ||
   1023 	    utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec))
   1024 		return (1);
   1025 
   1026 	if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){
   1027 		*tp = 0;
   1028 		return (0);
   1029 	}
   1030 
   1031 	rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd;
   1032 
   1033 	/* Calculate seconds since 1970 */
   1034 	rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24;
   1035 
   1036 	/* Add in the hours, minutes, and seconds */
   1037 	rv += (uint32_t)hour * 60 * 60;
   1038 	rv += (uint32_t)minute * 60;
   1039 	rv += sec;
   1040 	*tp = (time_t)rv;
   1041 
   1042 	return (0);
   1043 }
   1044 
   1045 static void
   1046 utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t)
   1047 {
   1048 	u_int mjd, hour, minute;
   1049 
   1050 	mjd = t / (60 * 60 * 24);
   1051 	t -= mjd * 60 * 60 * 24;
   1052 
   1053 	hour = t / (60 * 60);
   1054 	t -= hour * 60 * 60;
   1055 
   1056 	minute = t / 60;
   1057 	t -= minute * 60;
   1058 
   1059 	utoppy_add_16(sc, mjd + UTOPPY_MJD_1970);
   1060 	utoppy_add_8(sc, hour);
   1061 	utoppy_add_8(sc, minute);
   1062 	utoppy_add_8(sc, t);
   1063 }
   1064 
   1065 static int
   1066 utoppy_turbo_mode(struct utoppy_softc *sc, int state)
   1067 {
   1068 	uint16_t r;
   1069 	int err;
   1070 
   1071 	UTOPPY_OUT_INIT(sc);
   1072 	utoppy_add_32(sc, state);
   1073 
   1074 	err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r);
   1075 	if (err)
   1076 		return (err);
   1077 
   1078 	return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO);
   1079 }
   1080 
   1081 static int
   1082 utoppy_check_ready(struct utoppy_softc *sc)
   1083 {
   1084 	uint16_t r;
   1085 	int err;
   1086 
   1087 	UTOPPY_OUT_INIT(sc);
   1088 
   1089 	err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r);
   1090 	if (err)
   1091 		return (err);
   1092 
   1093 	return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO);
   1094 }
   1095 
   1096 static int
   1097 utoppy_cancel(struct utoppy_softc *sc)
   1098 {
   1099 	uint16_t r;
   1100 	int err, i;
   1101 
   1102 	/*
   1103 	 * Issue the cancel command serveral times. the Toppy doesn't
   1104 	 * always respond to the first.
   1105 	 */
   1106 	for (i = 0; i < 3; i++) {
   1107 		UTOPPY_OUT_INIT(sc);
   1108 		err = utoppy_command(sc, UTOPPY_CMD_CANCEL,
   1109 		    UTOPPY_SHORT_TIMEOUT, &r);
   1110 		if (err == 0 && r == UTOPPY_RESP_SUCCESS)
   1111 			break;
   1112 		err = ETIMEDOUT;
   1113 	}
   1114 
   1115 	if (err)
   1116 		return (err);
   1117 
   1118 	/*
   1119 	 * Make sure turbo mode is off, otherwise the Toppy will not
   1120 	 * respond to remote control input.
   1121 	 */
   1122 	(void) utoppy_turbo_mode(sc, 0);
   1123 
   1124 	sc->sc_state = UTOPPY_STATE_IDLE;
   1125 	return (0);
   1126 }
   1127 
   1128 static int
   1129 utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us)
   1130 {
   1131 	uint32_t hsize, hfree;
   1132 	uint16_t r;
   1133 	int err;
   1134 
   1135 	UTOPPY_OUT_INIT(sc);
   1136 	err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r);
   1137 	if (err)
   1138 		return (err);
   1139 
   1140 	if (r != UTOPPY_RESP_STATS_DATA)
   1141 		return (EIO);
   1142 
   1143 	if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree))
   1144 		return (EIO);
   1145 
   1146 	us->us_hdd_size = hsize;
   1147 	us->us_hdd_size *= 1024;
   1148 	us->us_hdd_free = hfree;
   1149 	us->us_hdd_free *= 1024;
   1150 
   1151 	return (0);
   1152 }
   1153 
   1154 static int
   1155 utoppy_readdir_next(struct utoppy_softc *sc)
   1156 {
   1157 	uint16_t resp;
   1158 	int err;
   1159 
   1160 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n",
   1161 	    USBDEVNAME(sc->sc_dev)));
   1162 
   1163 	/*
   1164 	 * Fetch the next READDIR response
   1165 	 */
   1166 	err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
   1167 	if (err) {
   1168 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1169 		    "utoppy_recv_packet() returned %d\n",
   1170 		    USBDEVNAME(sc->sc_dev), err));
   1171 		if (err == EBADMSG) {
   1172 			UTOPPY_OUT_INIT(sc);
   1173 			utoppy_send_packet(sc, UTOPPY_RESP_ERROR,
   1174 			    UTOPPY_LONG_TIMEOUT);
   1175 		}
   1176 		utoppy_cancel(sc);
   1177 		return (err);
   1178 	}
   1179 
   1180 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1181 	    "utoppy_recv_packet() returned %d, len %ld\n",
   1182 	    USBDEVNAME(sc->sc_dev), err, (u_long)sc->sc_in_len));
   1183 
   1184 	switch (resp) {
   1185 	case UTOPPY_RESP_READDIR_DATA:
   1186 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1187 		    "UTOPPY_RESP_READDIR_DATA\n", USBDEVNAME(sc->sc_dev)));
   1188 
   1189 		UTOPPY_OUT_INIT(sc);
   1190 		err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
   1191 		    UTOPPY_LONG_TIMEOUT);
   1192 		if (err) {
   1193 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1194 			    "utoppy_send_packet(ACK) returned %d\n",
   1195 			    USBDEVNAME(sc->sc_dev), err));
   1196 			utoppy_cancel(sc);
   1197 			return (err);
   1198 		}
   1199 		sc->sc_state = UTOPPY_STATE_READDIR;
   1200 		sc->sc_in_offset = 0;
   1201 		break;
   1202 
   1203 	case UTOPPY_RESP_READDIR_END:
   1204 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1205 		    "UTOPPY_RESP_READDIR_END\n", USBDEVNAME(sc->sc_dev)));
   1206 
   1207 		UTOPPY_OUT_INIT(sc);
   1208 		utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
   1209 		sc->sc_state = UTOPPY_STATE_IDLE;
   1210 		sc->sc_in_len = 0;
   1211 		break;
   1212 
   1213 	default:
   1214 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1215 		    "bad response: 0x%x\n", USBDEVNAME(sc->sc_dev), resp));
   1216 		sc->sc_state = UTOPPY_STATE_IDLE;
   1217 		sc->sc_in_len = 0;
   1218 		return (EIO);
   1219 	}
   1220 
   1221 	return (0);
   1222 }
   1223 
   1224 static size_t
   1225 utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud)
   1226 {
   1227 	uint8_t ftype;
   1228 
   1229 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left"
   1230 	    " %d\n", USBDEVNAME(sc->sc_dev), (int)sc->sc_in_len));
   1231 
   1232 	if (utoppy_timestamp_decode(sc, &ud->ud_mtime) ||
   1233 	    utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) ||
   1234 	    utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) ||
   1235 	    utoppy_get_32(sc, &ud->ud_attributes)) {
   1236 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no "
   1237 		    "more to decode\n", USBDEVNAME(sc->sc_dev)));
   1238 		return (0);
   1239 	}
   1240 
   1241 	switch (ftype) {
   1242 	case UTOPPY_FTYPE_DIR:
   1243 		ud->ud_type = UTOPPY_DIRENT_DIRECTORY;
   1244 		break;
   1245 	case UTOPPY_FTYPE_FILE:
   1246 		ud->ud_type = UTOPPY_DIRENT_FILE;
   1247 		break;
   1248 	default:
   1249 		ud->ud_type = UTOPPY_DIRENT_UNKNOWN;
   1250 		break;
   1251 	}
   1252 
   1253 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', "
   1254 	    "size %lld, time 0x%08lx, attr 0x%08x\n", USBDEVNAME(sc->sc_dev),
   1255 	    (ftype == UTOPPY_FTYPE_DIR) ? "DIR" :
   1256 	    ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path,
   1257 	    ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes));
   1258 
   1259 	return (1);
   1260 }
   1261 
   1262 static int
   1263 utoppy_readfile_next(struct utoppy_softc *sc)
   1264 {
   1265 	uint64_t off;
   1266 	uint16_t resp;
   1267 	int err;
   1268 
   1269 	err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
   1270 	if (err) {
   1271 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1272 		    "utoppy_recv_packet() returned %d\n",
   1273 		    USBDEVNAME(sc->sc_dev), err));
   1274 		utoppy_cancel(sc);
   1275 		return (err);
   1276 	}
   1277 
   1278 	switch (resp) {
   1279 	case UTOPPY_RESP_FILE_HEADER:
   1280 		/* ACK it */
   1281 		UTOPPY_OUT_INIT(sc);
   1282 		err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
   1283 		    UTOPPY_LONG_TIMEOUT);
   1284 		if (err) {
   1285 			DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1286 			    "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n",
   1287 			    USBDEVNAME(sc->sc_dev), err));
   1288 			utoppy_cancel(sc);
   1289 			return (err);
   1290 		}
   1291 
   1292 		sc->sc_in_len = 0;
   1293 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1294 		    "FILE_HEADER done\n", USBDEVNAME(sc->sc_dev)));
   1295 		break;
   1296 
   1297 	case UTOPPY_RESP_FILE_DATA:
   1298 		/* Already ACK'd */
   1299 		if (utoppy_get_64(sc, &off)) {
   1300 			DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1301 			    "UTOPPY_RESP_FILE_DATA did not provide offset\n",
   1302 			    USBDEVNAME(sc->sc_dev)));
   1303 			utoppy_cancel(sc);
   1304 			return (EBADMSG);
   1305 		}
   1306 
   1307 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1308 		    "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n",
   1309 		    USBDEVNAME(sc->sc_dev), off, (u_long)sc->sc_in_len));
   1310 		break;
   1311 
   1312 	case UTOPPY_RESP_FILE_END:
   1313 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1314 		    "UTOPPY_RESP_FILE_END: sending ACK\n",
   1315 		    USBDEVNAME(sc->sc_dev)));
   1316 		UTOPPY_OUT_INIT(sc);
   1317 		utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
   1318 		/*FALLTHROUGH*/
   1319 
   1320 	case UTOPPY_RESP_SUCCESS:
   1321 		sc->sc_state = UTOPPY_STATE_IDLE;
   1322 		(void) utoppy_turbo_mode(sc, 0);
   1323 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all "
   1324 		    "done\n", USBDEVNAME(sc->sc_dev)));
   1325 		break;
   1326 
   1327 	case UTOPPY_RESP_ERROR:
   1328 	default:
   1329 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad "
   1330 		    "response code 0x%0x\n", USBDEVNAME(sc->sc_dev), resp));
   1331 		utoppy_cancel(sc);
   1332 		return (EIO);
   1333 	}
   1334 
   1335 	return (0);
   1336 }
   1337 
   1338 int
   1339 utoppyopen(dev_t dev, int flag, int mode,
   1340     struct lwp *l)
   1341 {
   1342 	struct utoppy_softc *sc;
   1343 	int error = 0;
   1344 
   1345 	USB_GET_SC_OPEN(utoppy, UTOPPYUNIT(dev), sc);
   1346 
   1347 	if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying)
   1348 		return (ENXIO);
   1349 
   1350 	if (sc->sc_state != UTOPPY_STATE_CLOSED) {
   1351 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n",
   1352 		    USBDEVNAME(sc->sc_dev)));
   1353 		return (EBUSY);
   1354 	}
   1355 
   1356 	DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n",
   1357 	    USBDEVNAME(sc->sc_dev)));
   1358 
   1359 	sc->sc_refcnt++;
   1360 	sc->sc_state = UTOPPY_STATE_OPENING;
   1361 	sc->sc_turbo_mode = 0;
   1362 	sc->sc_out_pipe = NULL;
   1363 	sc->sc_in_pipe = NULL;
   1364 
   1365 	if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) {
   1366 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(OUT) "
   1367 		    "failed\n", USBDEVNAME(sc->sc_dev)));
   1368 		error = EIO;
   1369 		goto done;
   1370 	}
   1371 
   1372 	if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) {
   1373 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(IN) "
   1374 		    "failed\n", USBDEVNAME(sc->sc_dev)));
   1375 		error = EIO;
   1376 		usbd_close_pipe(sc->sc_out_pipe);
   1377 		sc->sc_out_pipe = NULL;
   1378 		goto done;
   1379 	}
   1380 
   1381 	sc->sc_out_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK);
   1382 	if (sc->sc_out_data == NULL) {
   1383 		error = ENOMEM;
   1384 		goto error;
   1385 	}
   1386 
   1387 	sc->sc_in_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK);
   1388 	if (sc->sc_in_data == NULL) {
   1389 		free(sc->sc_out_data, M_DEVBUF);
   1390 		sc->sc_out_data = NULL;
   1391 		error = ENOMEM;
   1392 		goto error;
   1393 	}
   1394 
   1395 	if ((error = utoppy_cancel(sc)) != 0)
   1396 		goto error;
   1397 
   1398 	if ((error = utoppy_check_ready(sc)) != 0) {
   1399 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()"
   1400 		    " returned %d\n", USBDEVNAME(sc->sc_dev), error));
   1401  error:
   1402 		usbd_abort_pipe(sc->sc_out_pipe);
   1403 		usbd_close_pipe(sc->sc_out_pipe);
   1404 		sc->sc_out_pipe = NULL;
   1405 		usbd_abort_pipe(sc->sc_in_pipe);
   1406 		usbd_close_pipe(sc->sc_in_pipe);
   1407 		sc->sc_in_pipe = NULL;
   1408 	}
   1409 
   1410  done:
   1411 	sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE;
   1412 
   1413 	DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state "
   1414 	    "'%s'\n", USBDEVNAME(sc->sc_dev), error,
   1415 	    utoppy_state_string(sc->sc_state)));
   1416 
   1417 	if (--sc->sc_refcnt < 0)
   1418 		usb_detach_wakeup(USBDEV(sc->sc_dev));
   1419 
   1420 	return (error);
   1421 }
   1422 
   1423 int
   1424 utoppyclose(dev_t dev, int flag, int mode,
   1425     struct lwp *l)
   1426 {
   1427 	struct utoppy_softc *sc;
   1428 	usbd_status err;
   1429 
   1430 	USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
   1431 
   1432 	DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n",
   1433 	    USBDEVNAME(sc->sc_dev)));
   1434 
   1435 	if (sc->sc_state < UTOPPY_STATE_IDLE) {
   1436 		/* We are being forced to close before the open completed. */
   1437 		DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:"
   1438 		    " %s\n", USBDEVNAME(sc->sc_dev),
   1439 		    utoppy_state_string(sc->sc_state)));
   1440 		return (0);
   1441 	}
   1442 
   1443 	if (sc->sc_out_data)
   1444 		(void) utoppy_cancel(sc);
   1445 
   1446 	if (sc->sc_out_pipe != NULL) {
   1447 		if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0)
   1448 			printf("usbd_abort_pipe(OUT) returned %d\n", err);
   1449 		if ((err = usbd_close_pipe(sc->sc_out_pipe)) != 0)
   1450 			printf("usbd_close_pipe(OUT) returned %d\n", err);
   1451 		sc->sc_out_pipe = NULL;
   1452 	}
   1453 
   1454 	if (sc->sc_in_pipe != NULL) {
   1455 		if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0)
   1456 			printf("usbd_abort_pipe(IN) returned %d\n", err);
   1457 		if ((err = usbd_close_pipe(sc->sc_in_pipe)) != 0)
   1458 			printf("usbd_close_pipe(IN) returned %d\n", err);
   1459 		sc->sc_in_pipe = NULL;
   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
   1481 utoppyread(dev_t dev, struct uio *uio, int flags)
   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
   1562 utoppywrite(dev_t dev, struct uio *uio, int flags)
   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
   1665 utoppyioctl(dev_t dev, u_long cmd, void *data, int flag,
   1666     struct lwp *l)
   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 }
   1928