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