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