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