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