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