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