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