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