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