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