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