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