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