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