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