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