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