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