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