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