1 /* $NetBSD: utoppy.c,v 1.19 2012/03/11 01:06:07 mrg 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.19 2012/03/11 01:06:07 mrg 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 = self->dv_unit; 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 wakeup(xfer); 525 } 526 527 static usbd_status 528 utoppy_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, 529 u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, 530 const char *lbl) 531 { 532 usbd_status err; 533 int s, error; 534 535 usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout, 536 utoppy_bulk_transfer_cb); 537 s = splusb(); 538 err = usbd_transfer(xfer); 539 if (err != USBD_IN_PROGRESS) { 540 splx(s); 541 return (err); 542 } 543 error = tsleep((void *)xfer, PZERO, lbl, 0); 544 splx(s); 545 if (error) { 546 usbd_abort_pipe(pipe); 547 return (USBD_INTERRUPTED); 548 } 549 usbd_get_xfer_status(xfer, NULL, NULL, size, &err); 550 return (err); 551 } 552 553 static int 554 utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout) 555 { 556 struct utoppy_header *h; 557 usbd_status err; 558 uint32_t len; 559 uint16_t dlen, crc; 560 uint8_t *data, *e, t1, t2; 561 562 h = sc->sc_out_data; 563 564 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, " 565 "len %d\n", device_xname(sc->sc_dev), (u_int)cmd, h->h_len)); 566 567 dlen = h->h_len; 568 len = dlen + UTOPPY_HEADER_SIZE; 569 570 if (len & 1) 571 len++; 572 if ((len % 64) == 0) 573 len += 2; 574 575 if (len >= UTOPPY_BSIZE) { 576 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: " 577 "packet too big (%d)\n", device_xname(sc->sc_dev), (int)len)); 578 return (EINVAL); 579 } 580 581 h->h_len = htole16(dlen + UTOPPY_HEADER_SIZE); 582 h->h_cmd2 = 0; 583 h->h_cmd = htole16(cmd); 584 585 /* The command word is part of the CRC */ 586 crc = UTOPPY_CRC16(0, 0); 587 crc = UTOPPY_CRC16(crc, 0); 588 crc = UTOPPY_CRC16(crc, cmd >> 8); 589 crc = UTOPPY_CRC16(crc, cmd); 590 591 /* 592 * If there is data following the header, calculate the CRC and 593 * byte-swap as we go. 594 */ 595 if (dlen) { 596 data = h->h_data; 597 e = data + (dlen & ~1); 598 599 do { 600 t1 = data[0]; 601 t2 = data[1]; 602 crc = UTOPPY_CRC16(crc, t1); 603 crc = UTOPPY_CRC16(crc, t2); 604 *data++ = t2; 605 *data++ = t1; 606 } while (data < e); 607 608 if (dlen & 1) { 609 t1 = data[0]; 610 crc = UTOPPY_CRC16(crc, t1); 611 data[1] = t1; 612 } 613 } 614 615 h->h_crc = htole16(crc); 616 data = sc->sc_out_data; 617 618 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: total len " 619 "%d...\n", device_xname(sc->sc_dev), (int)len)); 620 DDUMP_PACKET(data, len); 621 622 do { 623 uint32_t thislen; 624 625 thislen = min(len, UTOPPY_FRAG_SIZE); 626 627 memcpy(sc->sc_out_buf, data, thislen); 628 629 err = utoppy_bulk_transfer(sc->sc_out_xfer, sc->sc_out_pipe, 630 USBD_NO_COPY, timeout, sc->sc_out_buf, &thislen, 631 "utoppytx"); 632 633 if (thislen != min(len, UTOPPY_FRAG_SIZE)) { 634 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: " 635 "utoppy_send_packet: sent %ld, err %d\n", 636 device_xname(sc->sc_dev), (u_long)thislen, err)); 637 } 638 639 if (err == 0) { 640 len -= thislen; 641 data += thislen; 642 } 643 } while (err == 0 && len); 644 645 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: " 646 "usbd_bulk_transfer() returned %d.\n", device_xname(sc->sc_dev),err)); 647 648 return (err ? utoppy_usbd_status2errno(err) : 0); 649 } 650 651 static int 652 utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout) 653 { 654 struct utoppy_header *h; 655 usbd_status err; 656 uint32_t len, thislen, requested, bytesleft; 657 uint16_t crc; 658 uint8_t *data, *e, t1, t2; 659 660 data = sc->sc_in_data; 661 len = 0; 662 bytesleft = UTOPPY_BSIZE; 663 664 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n", 665 device_xname(sc->sc_dev))); 666 667 do { 668 requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE); 669 670 err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe, 671 USBD_NO_COPY | USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf, 672 &thislen, "utoppyrx"); 673 674 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: " 675 "usbd_bulk_transfer() returned %d, thislen %d, data %p\n", 676 device_xname(sc->sc_dev), err, (u_int)thislen, data)); 677 678 if (err == 0) { 679 memcpy(data, sc->sc_in_buf, thislen); 680 DDUMP_PACKET(data, thislen); 681 len += thislen; 682 bytesleft -= thislen; 683 data += thislen; 684 } 685 } while (err == 0 && bytesleft && thislen == requested); 686 687 if (err) 688 return (utoppy_usbd_status2errno(err)); 689 690 h = sc->sc_in_data; 691 692 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d " 693 "bytes in total to %p\n", device_xname(sc->sc_dev), (u_int)len, h)); 694 DDUMP_PACKET(h, len); 695 696 if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) { 697 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad " 698 " length (len %d, h_len %d)\n", device_xname(sc->sc_dev), 699 (int)len, le16toh(h->h_len))); 700 return (EIO); 701 } 702 703 len = h->h_len = le16toh(h->h_len); 704 h->h_crc = le16toh(h->h_crc); 705 *respp = h->h_cmd = le16toh(h->h_cmd); 706 h->h_cmd2 = le16toh(h->h_cmd2); 707 708 /* 709 * To maximise data throughput when transferring files, acknowledge 710 * data blocks as soon as we receive them. If we detect an error 711 * later on, we can always cancel. 712 */ 713 if (*respp == UTOPPY_RESP_FILE_DATA) { 714 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: " 715 "ACKing file data\n", device_xname(sc->sc_dev))); 716 717 UTOPPY_OUT_INIT(sc); 718 err = utoppy_send_packet(sc, UTOPPY_CMD_ACK, 719 UTOPPY_SHORT_TIMEOUT); 720 if (err) { 721 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: " 722 "utoppy_recv_packet: failed to ACK file data: %d\n", 723 device_xname(sc->sc_dev), err)); 724 return (err); 725 } 726 } 727 728 /* The command word is part of the CRC */ 729 crc = UTOPPY_CRC16(0, h->h_cmd2 >> 8); 730 crc = UTOPPY_CRC16(crc, h->h_cmd2); 731 crc = UTOPPY_CRC16(crc, h->h_cmd >> 8); 732 crc = UTOPPY_CRC16(crc, h->h_cmd); 733 734 /* 735 * Extract any payload, byte-swapping and calculating the CRC16 736 * as we go. 737 */ 738 if (len > UTOPPY_HEADER_SIZE) { 739 data = h->h_data; 740 e = data + ((len & ~1) - UTOPPY_HEADER_SIZE); 741 742 while (data < e) { 743 t1 = data[0]; 744 t2 = data[1]; 745 crc = UTOPPY_CRC16(crc, t2); 746 crc = UTOPPY_CRC16(crc, t1); 747 *data++ = t2; 748 *data++ = t1; 749 } 750 751 if (len & 1) { 752 t1 = data[1]; 753 crc = UTOPPY_CRC16(crc, t1); 754 *data = t1; 755 } 756 } 757 758 sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE; 759 sc->sc_in_offset = 0; 760 761 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, " 762 "crc 0x%04x, hdrcrc 0x%04x\n", device_xname(sc->sc_dev), 763 (int)len, crc, h->h_crc)); 764 DDUMP_PACKET(h, len); 765 766 return ((crc == h->h_crc) ? 0 : EBADMSG); 767 } 768 769 static __inline void * 770 utoppy_current_ptr(void *b) 771 { 772 struct utoppy_header *h = b; 773 774 return (&h->h_data[h->h_len]); 775 } 776 777 static __inline void 778 utoppy_advance_ptr(void *b, size_t len) 779 { 780 struct utoppy_header *h = b; 781 782 h->h_len += len; 783 } 784 785 static __inline void 786 utoppy_add_8(struct utoppy_softc *sc, uint8_t v) 787 { 788 struct utoppy_header *h = sc->sc_out_data; 789 uint8_t *p; 790 791 p = utoppy_current_ptr(h); 792 *p = v; 793 utoppy_advance_ptr(h, sizeof(v)); 794 } 795 796 static __inline void 797 utoppy_add_16(struct utoppy_softc *sc, uint16_t v) 798 { 799 struct utoppy_header *h = sc->sc_out_data; 800 uint8_t *p; 801 802 p = utoppy_current_ptr(h); 803 *p++ = (uint8_t)(v >> 8); 804 *p = (uint8_t)v; 805 utoppy_advance_ptr(h, sizeof(v)); 806 } 807 808 static __inline void 809 utoppy_add_32(struct utoppy_softc *sc, uint32_t v) 810 { 811 struct utoppy_header *h = sc->sc_out_data; 812 uint8_t *p; 813 814 p = utoppy_current_ptr(h); 815 *p++ = (uint8_t)(v >> 24); 816 *p++ = (uint8_t)(v >> 16); 817 *p++ = (uint8_t)(v >> 8); 818 *p = (uint8_t)v; 819 utoppy_advance_ptr(h, sizeof(v)); 820 } 821 822 static __inline void 823 utoppy_add_64(struct utoppy_softc *sc, uint64_t v) 824 { 825 struct utoppy_header *h = sc->sc_out_data; 826 uint8_t *p; 827 828 p = utoppy_current_ptr(h); 829 *p++ = (uint8_t)(v >> 56); 830 *p++ = (uint8_t)(v >> 48); 831 *p++ = (uint8_t)(v >> 40); 832 *p++ = (uint8_t)(v >> 32); 833 *p++ = (uint8_t)(v >> 24); 834 *p++ = (uint8_t)(v >> 16); 835 *p++ = (uint8_t)(v >> 8); 836 *p = (uint8_t)v; 837 utoppy_advance_ptr(h, sizeof(v)); 838 } 839 840 static __inline void 841 utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len) 842 { 843 struct utoppy_header *h = sc->sc_out_data; 844 char *p; 845 846 p = utoppy_current_ptr(h); 847 memset(p, 0, len); 848 strncpy(p, str, len); 849 utoppy_advance_ptr(h, len); 850 } 851 852 static int 853 utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen) 854 { 855 struct utoppy_header *h = sc->sc_out_data; 856 uint8_t *p, *str, *s; 857 size_t len; 858 int err; 859 860 p = utoppy_current_ptr(h); 861 862 str = putlen ? (p + sizeof(uint16_t)) : p; 863 864 err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len); 865 866 DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n", 867 err, (int)len)); 868 869 if (err) 870 return (err); 871 872 if (len < 2) 873 return (EINVAL); 874 875 /* 876 * copyinstr(9) has already copied the terminating NUL character, 877 * but we append another one in case we have to pad the length 878 * later on. 879 */ 880 str[len] = '\0'; 881 882 /* 883 * The Toppy uses backslash as the directory separator, so convert 884 * all forward slashes. 885 */ 886 for (s = &str[len - 2]; s >= str; s--) 887 if (*s == '/') 888 *s = '\\'; 889 890 if ((len + h->h_len) & 1) 891 len++; 892 893 if (putlen) 894 utoppy_add_16(sc, len); 895 896 utoppy_advance_ptr(h, len); 897 898 DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n", 899 (u_int)len)); 900 901 return (0); 902 } 903 904 static __inline int 905 utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp) 906 { 907 uint8_t *p; 908 909 if (sc->sc_in_len < sizeof(*vp)) 910 return (1); 911 912 p = UTOPPY_IN_DATA(sc); 913 *vp = *p; 914 sc->sc_in_offset += sizeof(*vp); 915 sc->sc_in_len -= sizeof(*vp); 916 return (0); 917 } 918 919 static __inline int 920 utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp) 921 { 922 uint16_t v; 923 uint8_t *p; 924 925 if (sc->sc_in_len < sizeof(v)) 926 return (1); 927 928 p = UTOPPY_IN_DATA(sc); 929 v = *p++; 930 v = (v << 8) | *p; 931 *vp = v; 932 sc->sc_in_offset += sizeof(v); 933 sc->sc_in_len -= sizeof(v); 934 return (0); 935 } 936 937 static __inline int 938 utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp) 939 { 940 uint32_t v; 941 uint8_t *p; 942 943 if (sc->sc_in_len < sizeof(v)) 944 return (1); 945 946 p = UTOPPY_IN_DATA(sc); 947 v = *p++; 948 v = (v << 8) | *p++; 949 v = (v << 8) | *p++; 950 v = (v << 8) | *p; 951 *vp = v; 952 sc->sc_in_offset += sizeof(v); 953 sc->sc_in_len -= sizeof(v); 954 return (0); 955 } 956 957 static __inline int 958 utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp) 959 { 960 uint64_t v; 961 uint8_t *p; 962 963 if (sc->sc_in_len < sizeof(v)) 964 return (1); 965 966 p = UTOPPY_IN_DATA(sc); 967 v = *p++; 968 v = (v << 8) | *p++; 969 v = (v << 8) | *p++; 970 v = (v << 8) | *p++; 971 v = (v << 8) | *p++; 972 v = (v << 8) | *p++; 973 v = (v << 8) | *p++; 974 v = (v << 8) | *p; 975 *vp = v; 976 sc->sc_in_offset += sizeof(v); 977 sc->sc_in_len -= sizeof(v); 978 return (0); 979 } 980 981 static __inline int 982 utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len) 983 { 984 char *p; 985 986 if (sc->sc_in_len < len) 987 return (1); 988 989 memset(str, 0, len); 990 p = UTOPPY_IN_DATA(sc); 991 strncpy(str, p, len); 992 sc->sc_in_offset += len; 993 sc->sc_in_len -= len; 994 return (0); 995 } 996 997 static int 998 utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout, 999 uint16_t *presp) 1000 { 1001 int err; 1002 1003 err = utoppy_send_packet(sc, cmd, timeout); 1004 if (err) 1005 return (err); 1006 1007 err = utoppy_recv_packet(sc, presp, timeout); 1008 if (err == EBADMSG) { 1009 UTOPPY_OUT_INIT(sc); 1010 utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout); 1011 } 1012 1013 return (err); 1014 } 1015 1016 static int 1017 utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp) 1018 { 1019 uint16_t mjd; 1020 uint8_t hour, minute, sec; 1021 uint32_t rv; 1022 1023 if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) || 1024 utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec)) 1025 return (1); 1026 1027 if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){ 1028 *tp = 0; 1029 return (0); 1030 } 1031 1032 rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd; 1033 1034 /* Calculate seconds since 1970 */ 1035 rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24; 1036 1037 /* Add in the hours, minutes, and seconds */ 1038 rv += (uint32_t)hour * 60 * 60; 1039 rv += (uint32_t)minute * 60; 1040 rv += sec; 1041 *tp = (time_t)rv; 1042 1043 return (0); 1044 } 1045 1046 static void 1047 utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t) 1048 { 1049 u_int mjd, hour, minute; 1050 1051 mjd = t / (60 * 60 * 24); 1052 t -= mjd * 60 * 60 * 24; 1053 1054 hour = t / (60 * 60); 1055 t -= hour * 60 * 60; 1056 1057 minute = t / 60; 1058 t -= minute * 60; 1059 1060 utoppy_add_16(sc, mjd + UTOPPY_MJD_1970); 1061 utoppy_add_8(sc, hour); 1062 utoppy_add_8(sc, minute); 1063 utoppy_add_8(sc, t); 1064 } 1065 1066 static int 1067 utoppy_turbo_mode(struct utoppy_softc *sc, int state) 1068 { 1069 uint16_t r; 1070 int err; 1071 1072 UTOPPY_OUT_INIT(sc); 1073 utoppy_add_32(sc, state); 1074 1075 err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r); 1076 if (err) 1077 return (err); 1078 1079 return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO); 1080 } 1081 1082 static int 1083 utoppy_check_ready(struct utoppy_softc *sc) 1084 { 1085 uint16_t r; 1086 int err; 1087 1088 UTOPPY_OUT_INIT(sc); 1089 1090 err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r); 1091 if (err) 1092 return (err); 1093 1094 return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO); 1095 } 1096 1097 static int 1098 utoppy_cancel(struct utoppy_softc *sc) 1099 { 1100 uint16_t r; 1101 int err, i; 1102 1103 /* 1104 * Issue the cancel command serveral times. the Toppy doesn't 1105 * always respond to the first. 1106 */ 1107 for (i = 0; i < 3; i++) { 1108 UTOPPY_OUT_INIT(sc); 1109 err = utoppy_command(sc, UTOPPY_CMD_CANCEL, 1110 UTOPPY_SHORT_TIMEOUT, &r); 1111 if (err == 0 && r == UTOPPY_RESP_SUCCESS) 1112 break; 1113 err = ETIMEDOUT; 1114 } 1115 1116 if (err) 1117 return (err); 1118 1119 /* 1120 * Make sure turbo mode is off, otherwise the Toppy will not 1121 * respond to remote control input. 1122 */ 1123 (void) utoppy_turbo_mode(sc, 0); 1124 1125 sc->sc_state = UTOPPY_STATE_IDLE; 1126 return (0); 1127 } 1128 1129 static int 1130 utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us) 1131 { 1132 uint32_t hsize, hfree; 1133 uint16_t r; 1134 int err; 1135 1136 UTOPPY_OUT_INIT(sc); 1137 err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r); 1138 if (err) 1139 return (err); 1140 1141 if (r != UTOPPY_RESP_STATS_DATA) 1142 return (EIO); 1143 1144 if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree)) 1145 return (EIO); 1146 1147 us->us_hdd_size = hsize; 1148 us->us_hdd_size *= 1024; 1149 us->us_hdd_free = hfree; 1150 us->us_hdd_free *= 1024; 1151 1152 return (0); 1153 } 1154 1155 static int 1156 utoppy_readdir_next(struct utoppy_softc *sc) 1157 { 1158 uint16_t resp; 1159 int err; 1160 1161 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n", 1162 device_xname(sc->sc_dev))); 1163 1164 /* 1165 * Fetch the next READDIR response 1166 */ 1167 err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT); 1168 if (err) { 1169 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1170 "utoppy_recv_packet() returned %d\n", 1171 device_xname(sc->sc_dev), err)); 1172 if (err == EBADMSG) { 1173 UTOPPY_OUT_INIT(sc); 1174 utoppy_send_packet(sc, UTOPPY_RESP_ERROR, 1175 UTOPPY_LONG_TIMEOUT); 1176 } 1177 utoppy_cancel(sc); 1178 return (err); 1179 } 1180 1181 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1182 "utoppy_recv_packet() returned %d, len %ld\n", 1183 device_xname(sc->sc_dev), err, (u_long)sc->sc_in_len)); 1184 1185 switch (resp) { 1186 case UTOPPY_RESP_READDIR_DATA: 1187 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1188 "UTOPPY_RESP_READDIR_DATA\n", device_xname(sc->sc_dev))); 1189 1190 UTOPPY_OUT_INIT(sc); 1191 err = utoppy_send_packet(sc, UTOPPY_CMD_ACK, 1192 UTOPPY_LONG_TIMEOUT); 1193 if (err) { 1194 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1195 "utoppy_send_packet(ACK) returned %d\n", 1196 device_xname(sc->sc_dev), err)); 1197 utoppy_cancel(sc); 1198 return (err); 1199 } 1200 sc->sc_state = UTOPPY_STATE_READDIR; 1201 sc->sc_in_offset = 0; 1202 break; 1203 1204 case UTOPPY_RESP_READDIR_END: 1205 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1206 "UTOPPY_RESP_READDIR_END\n", device_xname(sc->sc_dev))); 1207 1208 UTOPPY_OUT_INIT(sc); 1209 utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT); 1210 sc->sc_state = UTOPPY_STATE_IDLE; 1211 sc->sc_in_len = 0; 1212 break; 1213 1214 default: 1215 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1216 "bad response: 0x%x\n", device_xname(sc->sc_dev), resp)); 1217 sc->sc_state = UTOPPY_STATE_IDLE; 1218 sc->sc_in_len = 0; 1219 return (EIO); 1220 } 1221 1222 return (0); 1223 } 1224 1225 static size_t 1226 utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud) 1227 { 1228 uint8_t ftype; 1229 1230 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left" 1231 " %d\n", device_xname(sc->sc_dev), (int)sc->sc_in_len)); 1232 1233 if (utoppy_timestamp_decode(sc, &ud->ud_mtime) || 1234 utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) || 1235 utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) || 1236 utoppy_get_32(sc, &ud->ud_attributes)) { 1237 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no " 1238 "more to decode\n", device_xname(sc->sc_dev))); 1239 return (0); 1240 } 1241 1242 switch (ftype) { 1243 case UTOPPY_FTYPE_DIR: 1244 ud->ud_type = UTOPPY_DIRENT_DIRECTORY; 1245 break; 1246 case UTOPPY_FTYPE_FILE: 1247 ud->ud_type = UTOPPY_DIRENT_FILE; 1248 break; 1249 default: 1250 ud->ud_type = UTOPPY_DIRENT_UNKNOWN; 1251 break; 1252 } 1253 1254 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', " 1255 "size %lld, time 0x%08lx, attr 0x%08x\n", device_xname(sc->sc_dev), 1256 (ftype == UTOPPY_FTYPE_DIR) ? "DIR" : 1257 ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path, 1258 ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes)); 1259 1260 return (1); 1261 } 1262 1263 static int 1264 utoppy_readfile_next(struct utoppy_softc *sc) 1265 { 1266 uint64_t off; 1267 uint16_t resp; 1268 int err; 1269 1270 err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT); 1271 if (err) { 1272 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1273 "utoppy_recv_packet() returned %d\n", 1274 device_xname(sc->sc_dev), err)); 1275 utoppy_cancel(sc); 1276 return (err); 1277 } 1278 1279 switch (resp) { 1280 case UTOPPY_RESP_FILE_HEADER: 1281 /* ACK it */ 1282 UTOPPY_OUT_INIT(sc); 1283 err = utoppy_send_packet(sc, UTOPPY_CMD_ACK, 1284 UTOPPY_LONG_TIMEOUT); 1285 if (err) { 1286 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1287 "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n", 1288 device_xname(sc->sc_dev), err)); 1289 utoppy_cancel(sc); 1290 return (err); 1291 } 1292 1293 sc->sc_in_len = 0; 1294 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1295 "FILE_HEADER done\n", device_xname(sc->sc_dev))); 1296 break; 1297 1298 case UTOPPY_RESP_FILE_DATA: 1299 /* Already ACK'd */ 1300 if (utoppy_get_64(sc, &off)) { 1301 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1302 "UTOPPY_RESP_FILE_DATA did not provide offset\n", 1303 device_xname(sc->sc_dev))); 1304 utoppy_cancel(sc); 1305 return (EBADMSG); 1306 } 1307 1308 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1309 "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n", 1310 device_xname(sc->sc_dev), off, (u_long)sc->sc_in_len)); 1311 break; 1312 1313 case UTOPPY_RESP_FILE_END: 1314 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1315 "UTOPPY_RESP_FILE_END: sending ACK\n", 1316 device_xname(sc->sc_dev))); 1317 UTOPPY_OUT_INIT(sc); 1318 utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT); 1319 /*FALLTHROUGH*/ 1320 1321 case UTOPPY_RESP_SUCCESS: 1322 sc->sc_state = UTOPPY_STATE_IDLE; 1323 (void) utoppy_turbo_mode(sc, 0); 1324 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all " 1325 "done\n", device_xname(sc->sc_dev))); 1326 break; 1327 1328 case UTOPPY_RESP_ERROR: 1329 default: 1330 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad " 1331 "response code 0x%0x\n", device_xname(sc->sc_dev), resp)); 1332 utoppy_cancel(sc); 1333 return (EIO); 1334 } 1335 1336 return (0); 1337 } 1338 1339 int 1340 utoppyopen(dev_t dev, int flag, int mode, 1341 struct lwp *l) 1342 { 1343 struct utoppy_softc *sc; 1344 int error = 0; 1345 1346 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1347 if (sc == NULL) 1348 return ENXIO; 1349 1350 if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) 1351 return (ENXIO); 1352 1353 if (sc->sc_state != UTOPPY_STATE_CLOSED) { 1354 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n", 1355 device_xname(sc->sc_dev))); 1356 return (EBUSY); 1357 } 1358 1359 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n", 1360 device_xname(sc->sc_dev))); 1361 1362 sc->sc_refcnt++; 1363 sc->sc_state = UTOPPY_STATE_OPENING; 1364 sc->sc_turbo_mode = 0; 1365 sc->sc_out_pipe = NULL; 1366 sc->sc_in_pipe = NULL; 1367 1368 if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) { 1369 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(OUT) " 1370 "failed\n", device_xname(sc->sc_dev))); 1371 error = EIO; 1372 goto done; 1373 } 1374 1375 if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) { 1376 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(IN) " 1377 "failed\n", device_xname(sc->sc_dev))); 1378 error = EIO; 1379 usbd_close_pipe(sc->sc_out_pipe); 1380 sc->sc_out_pipe = NULL; 1381 goto done; 1382 } 1383 1384 sc->sc_out_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK); 1385 if (sc->sc_out_data == NULL) { 1386 error = ENOMEM; 1387 goto error; 1388 } 1389 1390 sc->sc_in_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK); 1391 if (sc->sc_in_data == NULL) { 1392 free(sc->sc_out_data, M_DEVBUF); 1393 sc->sc_out_data = NULL; 1394 error = ENOMEM; 1395 goto error; 1396 } 1397 1398 if ((error = utoppy_cancel(sc)) != 0) 1399 goto error; 1400 1401 if ((error = utoppy_check_ready(sc)) != 0) { 1402 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()" 1403 " returned %d\n", device_xname(sc->sc_dev), error)); 1404 error: 1405 usbd_abort_pipe(sc->sc_out_pipe); 1406 usbd_close_pipe(sc->sc_out_pipe); 1407 sc->sc_out_pipe = NULL; 1408 usbd_abort_pipe(sc->sc_in_pipe); 1409 usbd_close_pipe(sc->sc_in_pipe); 1410 sc->sc_in_pipe = NULL; 1411 } 1412 1413 done: 1414 sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE; 1415 1416 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state " 1417 "'%s'\n", device_xname(sc->sc_dev), error, 1418 utoppy_state_string(sc->sc_state))); 1419 1420 if (--sc->sc_refcnt < 0) 1421 usb_detach_wakeupold(sc->sc_dev); 1422 1423 return (error); 1424 } 1425 1426 int 1427 utoppyclose(dev_t dev, int flag, int mode, 1428 struct lwp *l) 1429 { 1430 struct utoppy_softc *sc; 1431 usbd_status err; 1432 1433 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1434 1435 DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n", 1436 device_xname(sc->sc_dev))); 1437 1438 if (sc->sc_state < UTOPPY_STATE_IDLE) { 1439 /* We are being forced to close before the open completed. */ 1440 DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:" 1441 " %s\n", device_xname(sc->sc_dev), 1442 utoppy_state_string(sc->sc_state))); 1443 return (0); 1444 } 1445 1446 if (sc->sc_out_data) 1447 (void) utoppy_cancel(sc); 1448 1449 if (sc->sc_out_pipe != NULL) { 1450 if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0) 1451 printf("usbd_abort_pipe(OUT) returned %d\n", err); 1452 if ((err = usbd_close_pipe(sc->sc_out_pipe)) != 0) 1453 printf("usbd_close_pipe(OUT) returned %d\n", err); 1454 sc->sc_out_pipe = NULL; 1455 } 1456 1457 if (sc->sc_in_pipe != NULL) { 1458 if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0) 1459 printf("usbd_abort_pipe(IN) returned %d\n", err); 1460 if ((err = usbd_close_pipe(sc->sc_in_pipe)) != 0) 1461 printf("usbd_close_pipe(IN) returned %d\n", err); 1462 sc->sc_in_pipe = NULL; 1463 } 1464 1465 if (sc->sc_out_data) { 1466 free(sc->sc_out_data, M_DEVBUF); 1467 sc->sc_out_data = NULL; 1468 } 1469 1470 if (sc->sc_in_data) { 1471 free(sc->sc_in_data, M_DEVBUF); 1472 sc->sc_in_data = NULL; 1473 } 1474 1475 sc->sc_state = UTOPPY_STATE_CLOSED; 1476 1477 DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n", 1478 device_xname(sc->sc_dev))); 1479 1480 return (0); 1481 } 1482 1483 int 1484 utoppyread(dev_t dev, struct uio *uio, int flags) 1485 { 1486 struct utoppy_softc *sc; 1487 struct utoppy_dirent ud; 1488 size_t len; 1489 int err; 1490 1491 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1492 1493 if (sc->sc_dying) 1494 return (EIO); 1495 1496 sc->sc_refcnt++; 1497 1498 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n", 1499 device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state))); 1500 1501 switch (sc->sc_state) { 1502 case UTOPPY_STATE_READDIR: 1503 err = 0; 1504 while (err == 0 && uio->uio_resid >= sizeof(ud) && 1505 sc->sc_state != UTOPPY_STATE_IDLE) { 1506 if (utoppy_readdir_decode(sc, &ud) == 0) 1507 err = utoppy_readdir_next(sc); 1508 else 1509 if ((err = uiomove(&ud, sizeof(ud), uio)) != 0) 1510 utoppy_cancel(sc); 1511 } 1512 break; 1513 1514 case UTOPPY_STATE_READFILE: 1515 err = 0; 1516 while (err == 0 && uio->uio_resid > 0 && 1517 sc->sc_state != UTOPPY_STATE_IDLE) { 1518 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: " 1519 "resid %ld, bytes_left %ld\n", 1520 device_xname(sc->sc_dev), (u_long)uio->uio_resid, 1521 (u_long)sc->sc_in_len)); 1522 1523 if (sc->sc_in_len == 0 && 1524 (err = utoppy_readfile_next(sc)) != 0) { 1525 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: " 1526 "READFILE: utoppy_readfile_next returned " 1527 "%d\n", device_xname(sc->sc_dev), err)); 1528 break; 1529 } 1530 1531 len = min(uio->uio_resid, sc->sc_in_len); 1532 if (len) { 1533 err = uiomove(UTOPPY_IN_DATA(sc), len, uio); 1534 if (err == 0) { 1535 sc->sc_in_offset += len; 1536 sc->sc_in_len -= len; 1537 } 1538 } 1539 } 1540 break; 1541 1542 case UTOPPY_STATE_IDLE: 1543 err = 0; 1544 break; 1545 1546 case UTOPPY_STATE_WRITEFILE: 1547 err = EBUSY; 1548 break; 1549 1550 default: 1551 err = EIO; 1552 break; 1553 } 1554 1555 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n", 1556 device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state))); 1557 1558 if (--sc->sc_refcnt < 0) 1559 usb_detach_wakeupold(sc->sc_dev); 1560 1561 return (err); 1562 } 1563 1564 int 1565 utoppywrite(dev_t dev, struct uio *uio, int flags) 1566 { 1567 struct utoppy_softc *sc; 1568 uint16_t resp; 1569 size_t len; 1570 int err; 1571 1572 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1573 1574 if (sc->sc_dying) 1575 return (EIO); 1576 1577 switch(sc->sc_state) { 1578 case UTOPPY_STATE_WRITEFILE: 1579 break; 1580 1581 case UTOPPY_STATE_IDLE: 1582 return (0); 1583 1584 default: 1585 return (EIO); 1586 } 1587 1588 sc->sc_refcnt++; 1589 err = 0; 1590 1591 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid %ld, " 1592 "wr_size %lld, wr_offset %lld\n", device_xname(sc->sc_dev), 1593 (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset)); 1594 1595 while (sc->sc_state == UTOPPY_STATE_WRITEFILE && 1596 (len = min(uio->uio_resid, sc->sc_wr_size)) != 0) { 1597 1598 len = min(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE + 1599 sizeof(uint64_t) + 3)); 1600 1601 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n", 1602 device_xname(sc->sc_dev), (u_long)len)); 1603 1604 UTOPPY_OUT_INIT(sc); 1605 utoppy_add_64(sc, sc->sc_wr_offset); 1606 1607 err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio); 1608 if (err) { 1609 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove() " 1610 "returned %d\n", device_xname(sc->sc_dev), err)); 1611 break; 1612 } 1613 1614 utoppy_advance_ptr(sc->sc_out_data, len); 1615 1616 err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA, 1617 UTOPPY_LONG_TIMEOUT, &resp); 1618 if (err) { 1619 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1620 "utoppy_command(UTOPPY_RESP_FILE_DATA) " 1621 "returned %d\n", device_xname(sc->sc_dev), err)); 1622 break; 1623 } 1624 if (resp != UTOPPY_RESP_SUCCESS) { 1625 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1626 "utoppy_command(UTOPPY_RESP_FILE_DATA) returned " 1627 "bad response 0x%x\n", device_xname(sc->sc_dev), 1628 resp)); 1629 utoppy_cancel(sc); 1630 err = EIO; 1631 break; 1632 } 1633 1634 sc->sc_wr_offset += len; 1635 sc->sc_wr_size -= len; 1636 } 1637 1638 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid %ld," 1639 " wr_size %lld, wr_offset %lld, err %d\n", device_xname(sc->sc_dev), 1640 (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset, err)); 1641 1642 if (err == 0 && sc->sc_wr_size == 0) { 1643 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending " 1644 "FILE_END...\n", device_xname(sc->sc_dev))); 1645 UTOPPY_OUT_INIT(sc); 1646 err = utoppy_command(sc, UTOPPY_RESP_FILE_END, 1647 UTOPPY_LONG_TIMEOUT, &resp); 1648 if (err) { 1649 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1650 "utoppy_command(UTOPPY_RESP_FILE_END) returned " 1651 "%d\n", device_xname(sc->sc_dev), err)); 1652 1653 utoppy_cancel(sc); 1654 } 1655 1656 sc->sc_state = UTOPPY_STATE_IDLE; 1657 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n", 1658 device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state))); 1659 } 1660 1661 if (--sc->sc_refcnt < 0) 1662 usb_detach_wakeupold(sc->sc_dev); 1663 1664 return (err); 1665 } 1666 1667 int 1668 utoppyioctl(dev_t dev, u_long cmd, void *data, int flag, 1669 struct lwp *l) 1670 { 1671 struct utoppy_softc *sc; 1672 struct utoppy_rename *ur; 1673 struct utoppy_readfile *urf; 1674 struct utoppy_writefile *uw; 1675 char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp; 1676 uint16_t resp; 1677 int err; 1678 1679 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1680 1681 if (sc->sc_dying) 1682 return (EIO); 1683 1684 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n", 1685 device_xname(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state))); 1686 1687 if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) { 1688 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n", 1689 device_xname(sc->sc_dev))); 1690 return (EBUSY); 1691 } 1692 1693 sc->sc_refcnt++; 1694 1695 switch (cmd) { 1696 case UTOPPYIOTURBO: 1697 err = 0; 1698 sc->sc_turbo_mode = *((int *)data) ? 1 : 0; 1699 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: " 1700 "%s\n", device_xname(sc->sc_dev), sc->sc_turbo_mode ? "On" : 1701 "Off")); 1702 break; 1703 1704 case UTOPPYIOCANCEL: 1705 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n", 1706 device_xname(sc->sc_dev))); 1707 err = utoppy_cancel(sc); 1708 break; 1709 1710 case UTOPPYIOREBOOT: 1711 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n", 1712 device_xname(sc->sc_dev))); 1713 UTOPPY_OUT_INIT(sc); 1714 err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT, 1715 &resp); 1716 if (err) 1717 break; 1718 1719 if (resp != UTOPPY_RESP_SUCCESS) 1720 err = EIO; 1721 break; 1722 1723 case UTOPPYIOSTATS: 1724 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n", 1725 device_xname(sc->sc_dev))); 1726 err = utoppy_stats(sc, (struct utoppy_stats *)data); 1727 break; 1728 1729 case UTOPPYIORENAME: 1730 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n", 1731 device_xname(sc->sc_dev))); 1732 ur = (struct utoppy_rename *)data; 1733 UTOPPY_OUT_INIT(sc); 1734 1735 if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0) 1736 break; 1737 if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0) 1738 break; 1739 1740 err = utoppy_command(sc, UTOPPY_CMD_RENAME, UTOPPY_LONG_TIMEOUT, 1741 &resp); 1742 if (err) 1743 break; 1744 1745 if (resp != UTOPPY_RESP_SUCCESS) 1746 err = EIO; 1747 break; 1748 1749 case UTOPPYIOMKDIR: 1750 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n", 1751 device_xname(sc->sc_dev))); 1752 UTOPPY_OUT_INIT(sc); 1753 err = utoppy_add_path(sc, *((const char **)data), 1); 1754 if (err) 1755 break; 1756 1757 err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT, 1758 &resp); 1759 if (err) 1760 break; 1761 1762 if (resp != UTOPPY_RESP_SUCCESS) 1763 err = EIO; 1764 break; 1765 1766 case UTOPPYIODELETE: 1767 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n", 1768 device_xname(sc->sc_dev))); 1769 UTOPPY_OUT_INIT(sc); 1770 err = utoppy_add_path(sc, *((const char **)data), 0); 1771 if (err) 1772 break; 1773 1774 err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT, 1775 &resp); 1776 if (err) 1777 break; 1778 1779 if (resp != UTOPPY_RESP_SUCCESS) 1780 err = EIO; 1781 break; 1782 1783 case UTOPPYIOREADDIR: 1784 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n", 1785 device_xname(sc->sc_dev))); 1786 UTOPPY_OUT_INIT(sc); 1787 err = utoppy_add_path(sc, *((const char **)data), 0); 1788 if (err) { 1789 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1790 "utoppy_add_path() returned %d\n", 1791 device_xname(sc->sc_dev), err)); 1792 break; 1793 } 1794 1795 err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR, 1796 UTOPPY_LONG_TIMEOUT); 1797 if (err != 0) { 1798 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1799 "UTOPPY_CMD_READDIR returned %d\n", 1800 device_xname(sc->sc_dev), err)); 1801 break; 1802 } 1803 1804 err = utoppy_readdir_next(sc); 1805 if (err) { 1806 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1807 "utoppy_readdir_next() returned %d\n", 1808 device_xname(sc->sc_dev), err)); 1809 } 1810 break; 1811 1812 case UTOPPYIOREADFILE: 1813 urf = (struct utoppy_readfile *)data; 1814 1815 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE " 1816 "%s, offset %lld\n", device_xname(sc->sc_dev), urf->ur_path, 1817 urf->ur_offset)); 1818 1819 if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0) 1820 break; 1821 1822 UTOPPY_OUT_INIT(sc); 1823 utoppy_add_8(sc, UTOPPY_FILE_READ); 1824 1825 if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0) 1826 break; 1827 1828 utoppy_add_64(sc, urf->ur_offset); 1829 1830 sc->sc_state = UTOPPY_STATE_READFILE; 1831 sc->sc_in_offset = 0; 1832 1833 err = utoppy_send_packet(sc, UTOPPY_CMD_FILE, 1834 UTOPPY_LONG_TIMEOUT); 1835 if (err == 0) 1836 err = utoppy_readfile_next(sc); 1837 break; 1838 1839 case UTOPPYIOWRITEFILE: 1840 uw = (struct utoppy_writefile *)data; 1841 1842 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE " 1843 "%s, size %lld, offset %lld\n", device_xname(sc->sc_dev), 1844 uw->uw_path, uw->uw_size, uw->uw_offset)); 1845 1846 if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0) 1847 break; 1848 1849 UTOPPY_OUT_INIT(sc); 1850 utoppy_add_8(sc, UTOPPY_FILE_WRITE); 1851 uwfp = utoppy_current_ptr(sc->sc_out_data); 1852 1853 if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) { 1854 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path() " 1855 "returned %d\n", device_xname(sc->sc_dev), err)); 1856 break; 1857 } 1858 1859 strncpy(uwf, &uwfp[2], sizeof(uwf)); 1860 utoppy_add_64(sc, uw->uw_offset); 1861 1862 err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT, 1863 &resp); 1864 if (err) { 1865 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1866 "utoppy_command(UTOPPY_CMD_FILE) returned " 1867 "%d\n", device_xname(sc->sc_dev), err)); 1868 break; 1869 } 1870 if (resp != UTOPPY_RESP_SUCCESS) { 1871 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1872 "utoppy_command(UTOPPY_CMD_FILE) returned " 1873 "bad response 0x%x\n", device_xname(sc->sc_dev), 1874 resp)); 1875 err = EIO; 1876 break; 1877 } 1878 1879 UTOPPY_OUT_INIT(sc); 1880 utoppy_timestamp_encode(sc, uw->uw_mtime); 1881 utoppy_add_8(sc, UTOPPY_FTYPE_FILE); 1882 utoppy_add_64(sc, uw->uw_size); 1883 utoppy_add_string(sc, uwf, sizeof(uwf)); 1884 utoppy_add_32(sc, 0); 1885 1886 err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER, 1887 UTOPPY_LONG_TIMEOUT, &resp); 1888 if (err) { 1889 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1890 "utoppy_command(UTOPPY_RESP_FILE_HEADER) " 1891 "returned %d\n", device_xname(sc->sc_dev), err)); 1892 break; 1893 } 1894 if (resp != UTOPPY_RESP_SUCCESS) { 1895 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1896 "utoppy_command(UTOPPY_RESP_FILE_HEADER) " 1897 "returned bad response 0x%x\n", 1898 device_xname(sc->sc_dev), resp)); 1899 err = EIO; 1900 break; 1901 } 1902 1903 sc->sc_wr_offset = uw->uw_offset; 1904 sc->sc_wr_size = uw->uw_size; 1905 sc->sc_state = UTOPPY_STATE_WRITEFILE; 1906 1907 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to " 1908 "%s. wr_offset %lld, wr_size %lld\n", 1909 device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state), 1910 sc->sc_wr_offset, sc->sc_wr_size)); 1911 break; 1912 1913 default: 1914 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n", 1915 device_xname(sc->sc_dev))); 1916 err = ENODEV; 1917 break; 1918 } 1919 1920 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n", 1921 device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state))); 1922 1923 if (err) 1924 utoppy_cancel(sc); 1925 1926 if (--sc->sc_refcnt < 0) 1927 usb_detach_wakeupold(sc->sc_dev); 1928 1929 return (err); 1930 } 1931