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