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