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