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