1 /* $NetBSD: utoppy.c,v 1.36 2022/03/03 06:05:38 riastradh 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.36 2022/03/03 06:05:38 riastradh 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 1369 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1370 1371 DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n", 1372 device_xname(sc->sc_dev))); 1373 1374 if (sc->sc_state < UTOPPY_STATE_IDLE) { 1375 /* We are being forced to close before the open completed. */ 1376 DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly " 1377 "open: %s\n", device_xname(sc->sc_dev), 1378 utoppy_state_string(sc->sc_state))); 1379 return 0; 1380 } 1381 1382 if (sc->sc_out_data) 1383 (void) utoppy_cancel(sc); 1384 1385 if (sc->sc_out_pipe != NULL) { 1386 usbd_abort_pipe(sc->sc_out_pipe); 1387 sc->sc_out_pipe = NULL; 1388 } 1389 1390 if (sc->sc_in_pipe != NULL) { 1391 usbd_abort_pipe(sc->sc_in_pipe); 1392 sc->sc_in_pipe = NULL; 1393 } 1394 1395 if (sc->sc_out_data) { 1396 kmem_free(sc->sc_out_data, UTOPPY_BSIZE + 1); 1397 sc->sc_out_data = NULL; 1398 } 1399 1400 if (sc->sc_in_data) { 1401 kmem_free(sc->sc_in_data, UTOPPY_BSIZE + 1); 1402 sc->sc_in_data = NULL; 1403 } 1404 1405 sc->sc_state = UTOPPY_STATE_CLOSED; 1406 1407 DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n", 1408 device_xname(sc->sc_dev))); 1409 1410 return 0; 1411 } 1412 1413 static int 1414 utoppyread(dev_t dev, struct uio *uio, int flags) 1415 { 1416 struct utoppy_softc *sc; 1417 struct utoppy_dirent ud; 1418 size_t len; 1419 int err; 1420 1421 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1422 1423 if (sc->sc_dying) 1424 return EIO; 1425 1426 sc->sc_refcnt++; 1427 1428 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n", 1429 device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state))); 1430 1431 switch (sc->sc_state) { 1432 case UTOPPY_STATE_READDIR: 1433 err = 0; 1434 while (err == 0 && uio->uio_resid >= sizeof(ud) && 1435 sc->sc_state != UTOPPY_STATE_IDLE) { 1436 if (utoppy_readdir_decode(sc, &ud) == 0) 1437 err = utoppy_readdir_next(sc); 1438 else 1439 if ((err = uiomove(&ud, sizeof(ud), uio)) != 0) 1440 utoppy_cancel(sc); 1441 } 1442 break; 1443 1444 case UTOPPY_STATE_READFILE: 1445 err = 0; 1446 while (err == 0 && uio->uio_resid > 0 && 1447 sc->sc_state != UTOPPY_STATE_IDLE) { 1448 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: " 1449 "resid %ld, bytes_left %ld\n", 1450 device_xname(sc->sc_dev), (u_long)uio->uio_resid, 1451 (u_long)sc->sc_in_len)); 1452 1453 if (sc->sc_in_len == 0 && 1454 (err = utoppy_readfile_next(sc)) != 0) { 1455 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: " 1456 "READFILE: utoppy_readfile_next returned " 1457 "%d\n", device_xname(sc->sc_dev), err)); 1458 break; 1459 } 1460 1461 len = uimin(uio->uio_resid, sc->sc_in_len); 1462 if (len) { 1463 err = uiomove(UTOPPY_IN_DATA(sc), len, uio); 1464 if (err == 0) { 1465 sc->sc_in_offset += len; 1466 sc->sc_in_len -= len; 1467 } 1468 } 1469 } 1470 break; 1471 1472 case UTOPPY_STATE_IDLE: 1473 err = 0; 1474 break; 1475 1476 case UTOPPY_STATE_WRITEFILE: 1477 err = EBUSY; 1478 break; 1479 1480 default: 1481 err = EIO; 1482 break; 1483 } 1484 1485 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n", 1486 device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state))); 1487 1488 if (--sc->sc_refcnt < 0) 1489 usb_detach_wakeupold(sc->sc_dev); 1490 1491 return err; 1492 } 1493 1494 static int 1495 utoppywrite(dev_t dev, struct uio *uio, int flags) 1496 { 1497 struct utoppy_softc *sc; 1498 uint16_t resp; 1499 size_t len; 1500 int err; 1501 1502 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1503 1504 if (sc->sc_dying) 1505 return EIO; 1506 1507 switch(sc->sc_state) { 1508 case UTOPPY_STATE_WRITEFILE: 1509 break; 1510 1511 case UTOPPY_STATE_IDLE: 1512 return 0; 1513 1514 default: 1515 return EIO; 1516 } 1517 1518 sc->sc_refcnt++; 1519 err = 0; 1520 1521 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid " 1522 "%ld, wr_size %lld, wr_offset %lld\n", device_xname(sc->sc_dev), 1523 (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset)); 1524 1525 while (sc->sc_state == UTOPPY_STATE_WRITEFILE && 1526 (len = uimin(uio->uio_resid, sc->sc_wr_size)) != 0) { 1527 1528 len = uimin(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE + 1529 sizeof(uint64_t) + 3)); 1530 1531 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n", 1532 device_xname(sc->sc_dev), (u_long)len)); 1533 1534 UTOPPY_OUT_INIT(sc); 1535 utoppy_add_64(sc, sc->sc_wr_offset); 1536 1537 err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio); 1538 if (err) { 1539 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove()" 1540 " returned %d\n", device_xname(sc->sc_dev), err)); 1541 break; 1542 } 1543 1544 utoppy_advance_ptr(sc->sc_out_data, len); 1545 1546 err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA, 1547 UTOPPY_LONG_TIMEOUT, &resp); 1548 if (err) { 1549 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1550 "utoppy_command(UTOPPY_RESP_FILE_DATA) " 1551 "returned %d\n", device_xname(sc->sc_dev), err)); 1552 break; 1553 } 1554 if (resp != UTOPPY_RESP_SUCCESS) { 1555 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1556 "utoppy_command(UTOPPY_RESP_FILE_DATA) returned " 1557 "bad response %#x\n", device_xname(sc->sc_dev), 1558 resp)); 1559 utoppy_cancel(sc); 1560 err = EIO; 1561 break; 1562 } 1563 1564 sc->sc_wr_offset += len; 1565 sc->sc_wr_size -= len; 1566 } 1567 1568 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid " 1569 "%ld, wr_size %lld, wr_offset %lld, err %d\n", 1570 device_xname(sc->sc_dev), (u_long)uio->uio_resid, sc->sc_wr_size, 1571 sc->sc_wr_offset, err)); 1572 1573 if (err == 0 && sc->sc_wr_size == 0) { 1574 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending " 1575 "FILE_END...\n", device_xname(sc->sc_dev))); 1576 UTOPPY_OUT_INIT(sc); 1577 err = utoppy_command(sc, UTOPPY_RESP_FILE_END, 1578 UTOPPY_LONG_TIMEOUT, &resp); 1579 if (err) { 1580 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1581 "utoppy_command(UTOPPY_RESP_FILE_END) returned " 1582 "%d\n", device_xname(sc->sc_dev), err)); 1583 1584 utoppy_cancel(sc); 1585 } 1586 1587 sc->sc_state = UTOPPY_STATE_IDLE; 1588 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n", 1589 device_xname(sc->sc_dev), 1590 utoppy_state_string(sc->sc_state))); 1591 } 1592 1593 if (--sc->sc_refcnt < 0) 1594 usb_detach_wakeupold(sc->sc_dev); 1595 1596 return err; 1597 } 1598 1599 static int 1600 utoppyioctl(dev_t dev, u_long cmd, void *data, int flag, 1601 struct lwp *l) 1602 { 1603 struct utoppy_softc *sc; 1604 struct utoppy_rename *ur; 1605 struct utoppy_readfile *urf; 1606 struct utoppy_writefile *uw; 1607 char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp; 1608 uint16_t resp; 1609 int err; 1610 1611 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1612 1613 if (sc->sc_dying) 1614 return EIO; 1615 1616 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n", 1617 device_xname(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state))); 1618 1619 if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) { 1620 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n", 1621 device_xname(sc->sc_dev))); 1622 return EBUSY; 1623 } 1624 1625 sc->sc_refcnt++; 1626 1627 switch (cmd) { 1628 case UTOPPYIOTURBO: 1629 err = 0; 1630 sc->sc_turbo_mode = *((int *)data) ? 1 : 0; 1631 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: " 1632 "%s\n", device_xname(sc->sc_dev), 1633 sc->sc_turbo_mode ? "On" : "Off")); 1634 break; 1635 1636 case UTOPPYIOCANCEL: 1637 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n", 1638 device_xname(sc->sc_dev))); 1639 err = utoppy_cancel(sc); 1640 break; 1641 1642 case UTOPPYIOREBOOT: 1643 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n", 1644 device_xname(sc->sc_dev))); 1645 UTOPPY_OUT_INIT(sc); 1646 err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT, 1647 &resp); 1648 if (err) 1649 break; 1650 1651 if (resp != UTOPPY_RESP_SUCCESS) 1652 err = EIO; 1653 break; 1654 1655 case UTOPPYIOSTATS: 1656 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n", 1657 device_xname(sc->sc_dev))); 1658 err = utoppy_stats(sc, (struct utoppy_stats *)data); 1659 break; 1660 1661 case UTOPPYIORENAME: 1662 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n", 1663 device_xname(sc->sc_dev))); 1664 ur = (struct utoppy_rename *)data; 1665 UTOPPY_OUT_INIT(sc); 1666 1667 if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0) 1668 break; 1669 if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0) 1670 break; 1671 1672 err = utoppy_command(sc, UTOPPY_CMD_RENAME, 1673 UTOPPY_LONG_TIMEOUT, &resp); 1674 if (err) 1675 break; 1676 1677 if (resp != UTOPPY_RESP_SUCCESS) 1678 err = EIO; 1679 break; 1680 1681 case UTOPPYIOMKDIR: 1682 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n", 1683 device_xname(sc->sc_dev))); 1684 UTOPPY_OUT_INIT(sc); 1685 err = utoppy_add_path(sc, *((const char **)data), 1); 1686 if (err) 1687 break; 1688 1689 err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT, 1690 &resp); 1691 if (err) 1692 break; 1693 1694 if (resp != UTOPPY_RESP_SUCCESS) 1695 err = EIO; 1696 break; 1697 1698 case UTOPPYIODELETE: 1699 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n", 1700 device_xname(sc->sc_dev))); 1701 UTOPPY_OUT_INIT(sc); 1702 err = utoppy_add_path(sc, *((const char **)data), 0); 1703 if (err) 1704 break; 1705 1706 err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT, 1707 &resp); 1708 if (err) 1709 break; 1710 1711 if (resp != UTOPPY_RESP_SUCCESS) 1712 err = EIO; 1713 break; 1714 1715 case UTOPPYIOREADDIR: 1716 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n", 1717 device_xname(sc->sc_dev))); 1718 UTOPPY_OUT_INIT(sc); 1719 err = utoppy_add_path(sc, *((const char **)data), 0); 1720 if (err) { 1721 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1722 "utoppy_add_path() returned %d\n", 1723 device_xname(sc->sc_dev), err)); 1724 break; 1725 } 1726 1727 err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR, 1728 UTOPPY_LONG_TIMEOUT); 1729 if (err != 0) { 1730 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1731 "UTOPPY_CMD_READDIR returned %d\n", 1732 device_xname(sc->sc_dev), err)); 1733 break; 1734 } 1735 1736 err = utoppy_readdir_next(sc); 1737 if (err) { 1738 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1739 "utoppy_readdir_next() returned %d\n", 1740 device_xname(sc->sc_dev), err)); 1741 } 1742 break; 1743 1744 case UTOPPYIOREADFILE: 1745 urf = (struct utoppy_readfile *)data; 1746 1747 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE " 1748 "%s, offset %lld\n", device_xname(sc->sc_dev), 1749 urf->ur_path, urf->ur_offset)); 1750 1751 if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0) 1752 break; 1753 1754 UTOPPY_OUT_INIT(sc); 1755 utoppy_add_8(sc, UTOPPY_FILE_READ); 1756 1757 if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0) 1758 break; 1759 1760 utoppy_add_64(sc, urf->ur_offset); 1761 1762 sc->sc_state = UTOPPY_STATE_READFILE; 1763 sc->sc_in_offset = 0; 1764 1765 err = utoppy_send_packet(sc, UTOPPY_CMD_FILE, 1766 UTOPPY_LONG_TIMEOUT); 1767 if (err == 0) 1768 err = utoppy_readfile_next(sc); 1769 break; 1770 1771 case UTOPPYIOWRITEFILE: 1772 uw = (struct utoppy_writefile *)data; 1773 1774 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE " 1775 "%s, size %lld, offset %lld\n", device_xname(sc->sc_dev), 1776 uw->uw_path, uw->uw_size, uw->uw_offset)); 1777 1778 if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0) 1779 break; 1780 1781 UTOPPY_OUT_INIT(sc); 1782 utoppy_add_8(sc, UTOPPY_FILE_WRITE); 1783 uwfp = utoppy_current_ptr(sc->sc_out_data); 1784 1785 if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) { 1786 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path()" 1787 " returned %d\n", device_xname(sc->sc_dev), err)); 1788 break; 1789 } 1790 1791 strncpy(uwf, &uwfp[2], sizeof(uwf)); 1792 utoppy_add_64(sc, uw->uw_offset); 1793 1794 err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT, 1795 &resp); 1796 if (err) { 1797 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1798 "utoppy_command(UTOPPY_CMD_FILE) returned " 1799 "%d\n", device_xname(sc->sc_dev), err)); 1800 break; 1801 } 1802 if (resp != UTOPPY_RESP_SUCCESS) { 1803 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1804 "utoppy_command(UTOPPY_CMD_FILE) returned " 1805 "bad response %#x\n", device_xname(sc->sc_dev), 1806 resp)); 1807 err = EIO; 1808 break; 1809 } 1810 1811 UTOPPY_OUT_INIT(sc); 1812 utoppy_timestamp_encode(sc, uw->uw_mtime); 1813 utoppy_add_8(sc, UTOPPY_FTYPE_FILE); 1814 utoppy_add_64(sc, uw->uw_size); 1815 utoppy_add_string(sc, uwf, sizeof(uwf)); 1816 utoppy_add_32(sc, 0); 1817 1818 err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER, 1819 UTOPPY_LONG_TIMEOUT, &resp); 1820 if (err) { 1821 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1822 "utoppy_command(UTOPPY_RESP_FILE_HEADER) " 1823 "returned %d\n", device_xname(sc->sc_dev), err)); 1824 break; 1825 } 1826 if (resp != UTOPPY_RESP_SUCCESS) { 1827 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1828 "utoppy_command(UTOPPY_RESP_FILE_HEADER) " 1829 "returned bad response %#x\n", 1830 device_xname(sc->sc_dev), resp)); 1831 err = EIO; 1832 break; 1833 } 1834 1835 sc->sc_wr_offset = uw->uw_offset; 1836 sc->sc_wr_size = uw->uw_size; 1837 sc->sc_state = UTOPPY_STATE_WRITEFILE; 1838 1839 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to " 1840 "%s. wr_offset %lld, wr_size %lld\n", 1841 device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state), 1842 sc->sc_wr_offset, sc->sc_wr_size)); 1843 break; 1844 1845 default: 1846 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n", 1847 device_xname(sc->sc_dev))); 1848 err = ENODEV; 1849 break; 1850 } 1851 1852 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n", 1853 device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state))); 1854 1855 if (err) 1856 utoppy_cancel(sc); 1857 1858 if (--sc->sc_refcnt < 0) 1859 usb_detach_wakeupold(sc->sc_dev); 1860 1861 return err; 1862 } 1863