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