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