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