Home | History | Annotate | Line # | Download | only in usb
utoppy.c revision 1.1
      1 /*	$NetBSD: utoppy.c,v 1.1 2006/04/03 08:15:48 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.1 2006/04/03 08:15:48 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(crc, h->h_cmd2 >> 8);
    724 	crc = UTOPPY_CRC16(0,   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 	}
   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, struct lwp *l)
   1418 {
   1419 	struct utoppy_softc *sc;
   1420 	usbd_status err;
   1421 
   1422 	USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
   1423 
   1424 	DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n",
   1425 	    USBDEVNAME(sc->sc_dev)));
   1426 
   1427 	if (sc->sc_state < UTOPPY_STATE_IDLE) {
   1428 		/* We are being forced to close before the open completed. */
   1429 		DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:"
   1430 		    " %s\n", USBDEVNAME(sc->sc_dev),
   1431 		    utoppy_state_string(sc->sc_state)));
   1432 		return (0);
   1433 	}
   1434 
   1435 	(void) utoppy_cancel(sc);
   1436 
   1437 	if (sc->sc_out_pipe != NULL) {
   1438 		if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0)
   1439 			printf("usbd_abort_pipe(OUT) returned %d\n", err);
   1440 		if ((err = usbd_close_pipe(sc->sc_out_pipe)) != 0)
   1441 			printf("usbd_close_pipe(OUT) returned %d\n", err);
   1442 		sc->sc_out_pipe = NULL;
   1443 	}
   1444 
   1445 	if (sc->sc_in_pipe != NULL) {
   1446 		if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0)
   1447 			printf("usbd_abort_pipe(IN) returned %d\n", err);
   1448 		if ((err = usbd_close_pipe(sc->sc_in_pipe)) != 0)
   1449 			printf("usbd_close_pipe(IN) returned %d\n", err);
   1450 		sc->sc_in_pipe = NULL;
   1451 	}
   1452 
   1453 	if (sc->sc_out_data) {
   1454 		free(sc->sc_out_data, M_DEVBUF);
   1455 		sc->sc_out_data = NULL;
   1456 	}
   1457 
   1458 	if (sc->sc_in_data) {
   1459 		free(sc->sc_in_data, M_DEVBUF);
   1460 		sc->sc_in_data = NULL;
   1461 	}
   1462 
   1463 	sc->sc_state = UTOPPY_STATE_CLOSED;
   1464 
   1465 	DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n",
   1466 	    USBDEVNAME(sc->sc_dev)));
   1467 
   1468 	return (0);
   1469 }
   1470 
   1471 int
   1472 utoppyread(dev_t dev, struct uio *uio, int flags)
   1473 {
   1474 	struct utoppy_softc *sc;
   1475 	struct utoppy_dirent ud;
   1476 	size_t len;
   1477 	int err;
   1478 
   1479 	USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
   1480 
   1481 	if (sc->sc_dying)
   1482 		return (EIO);
   1483 
   1484 	sc->sc_refcnt++;
   1485 
   1486 	DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n",
   1487 	    USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state)));
   1488 
   1489 	switch (sc->sc_state) {
   1490 	case UTOPPY_STATE_READDIR:
   1491 		err = 0;
   1492 		while (err == 0 && uio->uio_resid >= sizeof(ud) &&
   1493 		    sc->sc_state != UTOPPY_STATE_IDLE) {
   1494 			if (utoppy_readdir_decode(sc, &ud) == 0)
   1495 				err = utoppy_readdir_next(sc);
   1496 			else
   1497 			if ((err = uiomove(&ud, sizeof(ud), uio)) != 0)
   1498 				utoppy_cancel(sc);
   1499 		}
   1500 		break;
   1501 
   1502 	case UTOPPY_STATE_READFILE:
   1503 		err = 0;
   1504 		while (err == 0 && uio->uio_resid > 0 &&
   1505 		    sc->sc_state != UTOPPY_STATE_IDLE) {
   1506 			DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: "
   1507 			    "resid %ld, bytes_left %ld\n",
   1508 			    USBDEVNAME(sc->sc_dev), (u_long)uio->uio_resid,
   1509 			    (u_long)sc->sc_in_len));
   1510 
   1511 			if (sc->sc_in_len == 0 &&
   1512 			    (err = utoppy_readfile_next(sc)) != 0) {
   1513 				DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: "
   1514 				    "READFILE: utoppy_readfile_next returned "
   1515 				    "%d\n", USBDEVNAME(sc->sc_dev), err));
   1516 				break;
   1517 			}
   1518 
   1519 			len = min(uio->uio_resid, sc->sc_in_len);
   1520 			if (len) {
   1521 				err = uiomove(UTOPPY_IN_DATA(sc), len, uio);
   1522 				if (err == 0) {
   1523 					sc->sc_in_offset += len;
   1524 					sc->sc_in_len -= len;
   1525 				}
   1526 			}
   1527 		}
   1528 		break;
   1529 
   1530 	case UTOPPY_STATE_IDLE:
   1531 		err = 0;
   1532 		break;
   1533 
   1534 	case UTOPPY_STATE_WRITEFILE:
   1535 		err = EBUSY;
   1536 		break;
   1537 
   1538 	default:
   1539 		err = EIO;
   1540 		break;
   1541 	}
   1542 
   1543 	DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n",
   1544 	    USBDEVNAME(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
   1545 
   1546 	if (--sc->sc_refcnt < 0)
   1547 		usb_detach_wakeup(USBDEV(sc->sc_dev));
   1548 
   1549 	return (err);
   1550 }
   1551 
   1552 int
   1553 utoppywrite(dev_t dev, struct uio *uio, int flags)
   1554 {
   1555 	struct utoppy_softc *sc;
   1556 	uint16_t resp;
   1557 	size_t len;
   1558 	int err;
   1559 
   1560 	USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
   1561 
   1562 	if (sc->sc_dying)
   1563 		return (EIO);
   1564 
   1565 	switch(sc->sc_state) {
   1566 	case UTOPPY_STATE_WRITEFILE:
   1567 		break;
   1568 
   1569 	case UTOPPY_STATE_IDLE:
   1570 		return (0);
   1571 
   1572 	default:
   1573 		return (EIO);
   1574 	}
   1575 
   1576 	sc->sc_refcnt++;
   1577 	err = 0;
   1578 
   1579 	DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid %ld, "
   1580 	    "wr_size %lld, wr_offset %lld\n", USBDEVNAME(sc->sc_dev),
   1581 	    (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset));
   1582 
   1583 	while (sc->sc_state == UTOPPY_STATE_WRITEFILE &&
   1584 	    (len = min(uio->uio_resid, sc->sc_wr_size)) != 0) {
   1585 
   1586 		len = min(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE +
   1587 		    sizeof(uint64_t) + 3));
   1588 
   1589 		DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n",
   1590 		    USBDEVNAME(sc->sc_dev), (u_long)len));
   1591 
   1592 		UTOPPY_OUT_INIT(sc);
   1593 		utoppy_add_64(sc, sc->sc_wr_offset);
   1594 
   1595 		err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio);
   1596 		if (err) {
   1597 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove() "
   1598 			    "returned %d\n", USBDEVNAME(sc->sc_dev), err));
   1599 			break;
   1600 		}
   1601 
   1602 		utoppy_advance_ptr(sc->sc_out_data, len);
   1603 
   1604 		err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA,
   1605 		    UTOPPY_LONG_TIMEOUT, &resp);
   1606 		if (err) {
   1607 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
   1608 			    "utoppy_command(UTOPPY_RESP_FILE_DATA) "
   1609 			    "returned %d\n", USBDEVNAME(sc->sc_dev), err));
   1610 			break;
   1611 		}
   1612 		if (resp != UTOPPY_RESP_SUCCESS) {
   1613 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
   1614 			    "utoppy_command(UTOPPY_RESP_FILE_DATA) returned "
   1615 			    "bad response 0x%x\n", USBDEVNAME(sc->sc_dev),
   1616 			    resp));
   1617 			utoppy_cancel(sc);
   1618 			err = EIO;
   1619 			break;
   1620 		}
   1621 
   1622 		sc->sc_wr_offset += len;
   1623 		sc->sc_wr_size -= len;
   1624 	}
   1625 
   1626 	DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid %ld,"
   1627 	    " wr_size %lld, wr_offset %lld, err %d\n", USBDEVNAME(sc->sc_dev),
   1628 	    (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset, err));
   1629 
   1630 	if (err == 0 && sc->sc_wr_size == 0) {
   1631 		DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending "
   1632 		    "FILE_END...\n", USBDEVNAME(sc->sc_dev)));
   1633 		UTOPPY_OUT_INIT(sc);
   1634 		err = utoppy_command(sc, UTOPPY_RESP_FILE_END,
   1635 		    UTOPPY_LONG_TIMEOUT, &resp);
   1636 		if (err) {
   1637 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
   1638 			    "utoppy_command(UTOPPY_RESP_FILE_END) returned "
   1639 			    "%d\n", USBDEVNAME(sc->sc_dev), err));
   1640 
   1641 			utoppy_cancel(sc);
   1642 		}
   1643 
   1644 		sc->sc_state = UTOPPY_STATE_IDLE;
   1645 		DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n",
   1646 		    USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state)));
   1647 	}
   1648 
   1649 	if (--sc->sc_refcnt < 0)
   1650 		usb_detach_wakeup(USBDEV(sc->sc_dev));
   1651 
   1652 	return (err);
   1653 }
   1654 
   1655 int
   1656 utoppyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
   1657 {
   1658 	struct utoppy_softc *sc;
   1659 	struct utoppy_rename *ur;
   1660 	struct utoppy_readfile *urf;
   1661 	struct utoppy_writefile *uw;
   1662 	char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp;
   1663 	uint16_t resp;
   1664 	int err;
   1665 
   1666 	USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
   1667 
   1668 	if (sc->sc_dying)
   1669 		return (EIO);
   1670 
   1671 	DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n",
   1672 	    USBDEVNAME(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state)));
   1673 
   1674 	if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) {
   1675 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n",
   1676 		    USBDEVNAME(sc->sc_dev)));
   1677 		return (EBUSY);
   1678 	}
   1679 
   1680 	sc->sc_refcnt++;
   1681 
   1682 	switch (cmd) {
   1683 	case UTOPPYIOTURBO:
   1684 		err = 0;
   1685 		sc->sc_turbo_mode = *((int *)data) ? 1 : 0;
   1686 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: "
   1687 		    "%s\n", USBDEVNAME(sc->sc_dev), sc->sc_turbo_mode ? "On" :
   1688 		    "Off"));
   1689 		break;
   1690 
   1691 	case UTOPPYIOCANCEL:
   1692 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n",
   1693 		    USBDEVNAME(sc->sc_dev)));
   1694 		err = utoppy_cancel(sc);
   1695 		break;
   1696 
   1697 	case UTOPPYIOREBOOT:
   1698 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n",
   1699 		    USBDEVNAME(sc->sc_dev)));
   1700 		UTOPPY_OUT_INIT(sc);
   1701 		err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT,
   1702 		    &resp);
   1703 		if (err)
   1704 			break;
   1705 
   1706 		if (resp != UTOPPY_RESP_SUCCESS)
   1707 			err = EIO;
   1708 		break;
   1709 
   1710 	case UTOPPYIOSTATS:
   1711 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n",
   1712 		    USBDEVNAME(sc->sc_dev)));
   1713 		err = utoppy_stats(sc, (struct utoppy_stats *)data);
   1714 		break;
   1715 
   1716 	case UTOPPYIORENAME:
   1717 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n",
   1718 		    USBDEVNAME(sc->sc_dev)));
   1719 		ur = (struct utoppy_rename *)data;
   1720 		UTOPPY_OUT_INIT(sc);
   1721 
   1722 		if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0)
   1723 			break;
   1724 		if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0)
   1725 			break;
   1726 
   1727 		err = utoppy_command(sc, UTOPPY_CMD_RENAME, UTOPPY_LONG_TIMEOUT,
   1728 		    &resp);
   1729 		if (err)
   1730 			break;
   1731 
   1732 		if (resp != UTOPPY_RESP_SUCCESS)
   1733 			err = EIO;
   1734 		break;
   1735 
   1736 	case UTOPPYIOMKDIR:
   1737 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n",
   1738 		    USBDEVNAME(sc->sc_dev)));
   1739 		UTOPPY_OUT_INIT(sc);
   1740 		err = utoppy_add_path(sc, *((const char **)data), 1);
   1741 		if (err)
   1742 			break;
   1743 
   1744 		err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT,
   1745 		    &resp);
   1746 		if (err)
   1747 			break;
   1748 
   1749 		if (resp != UTOPPY_RESP_SUCCESS)
   1750 			err = EIO;
   1751 		break;
   1752 
   1753 	case UTOPPYIODELETE:
   1754 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n",
   1755 		    USBDEVNAME(sc->sc_dev)));
   1756 		UTOPPY_OUT_INIT(sc);
   1757 		err = utoppy_add_path(sc, *((const char **)data), 0);
   1758 		if (err)
   1759 			break;
   1760 
   1761 		err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT,
   1762 		    &resp);
   1763 		if (err)
   1764 			break;
   1765 
   1766 		if (resp != UTOPPY_RESP_SUCCESS)
   1767 			err = EIO;
   1768 		break;
   1769 
   1770 	case UTOPPYIOREADDIR:
   1771 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n",
   1772 		    USBDEVNAME(sc->sc_dev)));
   1773 		UTOPPY_OUT_INIT(sc);
   1774 		err = utoppy_add_path(sc, *((const char **)data), 0);
   1775 		if (err) {
   1776 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
   1777 			    "utoppy_add_path() returned %d\n",
   1778 			    USBDEVNAME(sc->sc_dev), err));
   1779 			break;
   1780 		}
   1781 
   1782 		err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR,
   1783 		    UTOPPY_LONG_TIMEOUT);
   1784 		if (err != 0) {
   1785 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
   1786 			    "UTOPPY_CMD_READDIR returned %d\n",
   1787 			    USBDEVNAME(sc->sc_dev), err));
   1788 			break;
   1789 		}
   1790 
   1791 		err = utoppy_readdir_next(sc);
   1792 		if (err) {
   1793 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
   1794 			    "utoppy_readdir_next() returned %d\n",
   1795 			    USBDEVNAME(sc->sc_dev), err));
   1796 		}
   1797 		break;
   1798 
   1799 	case UTOPPYIOREADFILE:
   1800 		urf = (struct utoppy_readfile *)data;
   1801 
   1802 		DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE "
   1803 		    "%s, offset %lld\n", USBDEVNAME(sc->sc_dev), urf->ur_path,
   1804 		    urf->ur_offset));
   1805 
   1806 		if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
   1807 			break;
   1808 
   1809 		UTOPPY_OUT_INIT(sc);
   1810 		utoppy_add_8(sc, UTOPPY_FILE_READ);
   1811 
   1812 		if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0)
   1813 			break;
   1814 
   1815 		utoppy_add_64(sc, urf->ur_offset);
   1816 
   1817 		sc->sc_state = UTOPPY_STATE_READFILE;
   1818 		sc->sc_in_offset = 0;
   1819 
   1820 		err = utoppy_send_packet(sc, UTOPPY_CMD_FILE,
   1821 		    UTOPPY_LONG_TIMEOUT);
   1822 		if (err == 0)
   1823 			err = utoppy_readfile_next(sc);
   1824 		break;
   1825 
   1826 	case UTOPPYIOWRITEFILE:
   1827 		uw = (struct utoppy_writefile *)data;
   1828 
   1829 		DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE "
   1830 		    "%s, size %lld, offset %lld\n", USBDEVNAME(sc->sc_dev),
   1831 		    uw->uw_path, uw->uw_size, uw->uw_offset));
   1832 
   1833 		if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
   1834 			break;
   1835 
   1836 		UTOPPY_OUT_INIT(sc);
   1837 		utoppy_add_8(sc, UTOPPY_FILE_WRITE);
   1838 		uwfp = utoppy_current_ptr(sc->sc_out_data);
   1839 
   1840 		if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) {
   1841 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path() "
   1842 			    "returned %d\n", USBDEVNAME(sc->sc_dev), err));
   1843 			break;
   1844 		}
   1845 
   1846 		strncpy(uwf, &uwfp[2], sizeof(uwf));
   1847 		utoppy_add_64(sc, uw->uw_offset);
   1848 
   1849 		err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT,
   1850 		    &resp);
   1851 		if (err) {
   1852 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1853 			    "utoppy_command(UTOPPY_CMD_FILE) returned "
   1854 			    "%d\n", USBDEVNAME(sc->sc_dev), err));
   1855 			break;
   1856 		}
   1857 		if (resp != UTOPPY_RESP_SUCCESS) {
   1858 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1859 			    "utoppy_command(UTOPPY_CMD_FILE) returned "
   1860 			    "bad response 0x%x\n", USBDEVNAME(sc->sc_dev),
   1861 			    resp));
   1862 			err = EIO;
   1863 			break;
   1864 		}
   1865 
   1866 		UTOPPY_OUT_INIT(sc);
   1867 		utoppy_timestamp_encode(sc, uw->uw_mtime);
   1868 		utoppy_add_8(sc, UTOPPY_FTYPE_FILE);
   1869 		utoppy_add_64(sc, uw->uw_size);
   1870 		utoppy_add_string(sc, uwf, sizeof(uwf));
   1871 		utoppy_add_32(sc, 0);
   1872 
   1873 		err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER,
   1874 		    UTOPPY_LONG_TIMEOUT, &resp);
   1875 		if (err) {
   1876 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1877 			    "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
   1878 			    "returned %d\n", USBDEVNAME(sc->sc_dev), err));
   1879 			break;
   1880 		}
   1881 		if (resp != UTOPPY_RESP_SUCCESS) {
   1882 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1883 			    "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
   1884 			    "returned bad response 0x%x\n",
   1885 			    USBDEVNAME(sc->sc_dev), resp));
   1886 			err = EIO;
   1887 			break;
   1888 		}
   1889 
   1890 		sc->sc_wr_offset = uw->uw_offset;
   1891 		sc->sc_wr_size = uw->uw_size;
   1892 		sc->sc_state = UTOPPY_STATE_WRITEFILE;
   1893 
   1894 		DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to "
   1895 		    "%s. wr_offset %lld, wr_size %lld\n",
   1896 		    USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state),
   1897 		    sc->sc_wr_offset, sc->sc_wr_size));
   1898 		break;
   1899 
   1900 	default:
   1901 		DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n",
   1902 		    USBDEVNAME(sc->sc_dev)));
   1903 		err = ENODEV;
   1904 		break;
   1905 	}
   1906 
   1907 	DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n",
   1908 	    USBDEVNAME(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
   1909 
   1910 	if (err)
   1911 		utoppy_cancel(sc);
   1912 
   1913 	if (--sc->sc_refcnt < 0)
   1914 		usb_detach_wakeup(USBDEV(sc->sc_dev));
   1915 
   1916 	return (err);
   1917 }
   1918