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