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