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