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