1 /* $NetBSD: utoppy.c,v 1.26 2016/07/07 06:55:42 msaitoh 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.26 2016/07/07 06:55:42 msaitoh 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, 203 utoppy_attach, utoppy_detach, utoppy_activate); 204 205 int 206 utoppy_match(device_t parent, cfdata_t match, void *aux) 207 { 208 struct usb_attach_arg *uaa = aux; 209 210 if (uaa->uaa_vendor == USB_VENDOR_TOPFIELD && 211 uaa->uaa_product == USB_PRODUCT_TOPFIELD_TF5000PVR) 212 return UMATCH_VENDOR_PRODUCT; 213 214 return UMATCH_NONE; 215 } 216 217 void 218 utoppy_attach(device_t parent, device_t self, void *aux) 219 { 220 struct utoppy_softc *sc = device_private(self); 221 struct usb_attach_arg *uaa = aux; 222 struct usbd_device *dev = uaa->uaa_device; 223 struct usbd_interface *iface; 224 usb_endpoint_descriptor_t *ed; 225 char *devinfop; 226 uint8_t epcount; 227 int i; 228 229 sc->sc_dev = self; 230 231 aprint_naive("\n"); 232 aprint_normal("\n"); 233 234 devinfop = usbd_devinfo_alloc(dev, 0); 235 aprint_normal_dev(self, "%s\n", devinfop); 236 usbd_devinfo_free(devinfop); 237 238 sc->sc_dying = 0; 239 sc->sc_refcnt = 0; 240 sc->sc_udev = dev; 241 242 if (usbd_set_config_index(dev, 0, 1) 243 || usbd_device2interface_handle(dev, 0, &iface)) { 244 aprint_error_dev(self, "Configuration failed\n"); 245 return; 246 } 247 248 epcount = 0; 249 (void) usbd_endpoint_count(iface, &epcount); 250 if (epcount != UTOPPY_NUMENDPOINTS) { 251 aprint_error_dev(self, "Expected %d endpoints, got %d\n", 252 UTOPPY_NUMENDPOINTS, epcount); 253 return; 254 } 255 256 sc->sc_in = -1; 257 sc->sc_out = -1; 258 259 for (i = 0; i < epcount; i++) { 260 ed = usbd_interface2endpoint_descriptor(iface, i); 261 if (ed == NULL) { 262 aprint_error_dev(self, "couldn't get ep %d\n", i); 263 return; 264 } 265 266 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 267 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 268 sc->sc_in = ed->bEndpointAddress; 269 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 270 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 271 sc->sc_out = ed->bEndpointAddress; 272 } 273 } 274 275 if (sc->sc_out == -1 || sc->sc_in == -1) { 276 aprint_error_dev(self, 277 "could not find bulk in/out endpoints\n"); 278 sc->sc_dying = 1; 279 return; 280 } 281 282 sc->sc_iface = iface; 283 sc->sc_udev = dev; 284 285 sc->sc_out_pipe = NULL; 286 sc->sc_in_pipe = NULL; 287 288 if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) { 289 DPRINTF(UTOPPY_DBG_OPEN, ("%s: usbd_open_pipe(OUT) failed\n", 290 device_xname(sc->sc_dev))); 291 aprint_error_dev(self, "could not open OUT pipe\n"); 292 sc->sc_dying = 1; 293 return; 294 } 295 296 if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) { 297 DPRINTF(UTOPPY_DBG_OPEN, ("%s: usbd_open_pipe(IN) failed\n", 298 device_xname(sc->sc_dev))); 299 aprint_error_dev(self, "could not open IN pipe\n"); 300 301 usbd_close_pipe(sc->sc_out_pipe); 302 sc->sc_out_pipe = NULL; 303 sc->sc_dying = 1; 304 return; 305 } 306 307 int error; 308 error = usbd_create_xfer(sc->sc_out_pipe, UTOPPY_FRAG_SIZE, 0, 0, 309 &sc->sc_out_xfer); 310 if (error) { 311 aprint_error_dev(self, "could not allocate bulk out xfer\n"); 312 goto fail0; 313 } 314 315 error = usbd_create_xfer(sc->sc_in_pipe, UTOPPY_FRAG_SIZE, 316 USBD_SHORT_XFER_OK, 0, &sc->sc_in_xfer); 317 if (error) { 318 aprint_error_dev(self, "could not allocate bulk in xfer\n"); 319 goto fail1; 320 } 321 322 sc->sc_out_buf = usbd_get_buffer(sc->sc_out_xfer); 323 sc->sc_in_buf = usbd_get_buffer(sc->sc_in_xfer); 324 325 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 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, sc->sc_dev); 386 387 return 0; 388 } 389 390 static const uint16_t utoppy_crc16_lookup[] = { 391 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 392 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 393 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 394 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 395 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 396 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 397 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 398 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 399 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 400 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 401 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 402 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 403 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 404 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 405 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 406 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 407 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 408 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 409 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 410 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 411 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 412 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 413 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 414 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 415 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 416 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 417 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 418 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 419 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 420 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 421 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 422 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 423 }; 424 425 #define UTOPPY_CRC16(ccrc,b) \ 426 (utoppy_crc16_lookup[((ccrc) ^ (b)) & 0xffu] ^ ((ccrc) >> 8)) 427 428 static const int utoppy_usbdstatus_lookup[] = { 429 0, /* USBD_NORMAL_COMPLETION */ 430 EINPROGRESS, /* USBD_IN_PROGRESS */ 431 EALREADY, /* USBD_PENDING_REQUESTS */ 432 EAGAIN, /* USBD_NOT_STARTED */ 433 EINVAL, /* USBD_INVAL */ 434 ENOMEM, /* USBD_NOMEM */ 435 ECONNRESET, /* USBD_CANCELLED */ 436 EFAULT, /* USBD_BAD_ADDRESS */ 437 EBUSY, /* USBD_IN_USE */ 438 EADDRNOTAVAIL, /* USBD_NO_ADDR */ 439 ENETDOWN, /* USBD_SET_ADDR_FAILED */ 440 EIO, /* USBD_NO_POWER */ 441 EMLINK, /* USBD_TOO_DEEP */ 442 EIO, /* USBD_IOERROR */ 443 ENXIO, /* USBD_NOT_CONFIGURED */ 444 ETIMEDOUT, /* USBD_TIMEOUT */ 445 EBADMSG, /* USBD_SHORT_XFER */ 446 EHOSTDOWN, /* USBD_STALLED */ 447 EINTR /* USBD_INTERRUPTED */ 448 }; 449 450 static __inline int 451 utoppy_usbd_status2errno(usbd_status err) 452 { 453 454 if (err >= USBD_ERROR_MAX) 455 return EFAULT; 456 return utoppy_usbdstatus_lookup[err]; 457 } 458 459 #ifdef UTOPPY_DEBUG 460 static const char * 461 utoppy_state_string(enum utoppy_state state) 462 { 463 const char *str; 464 465 switch (state) { 466 case UTOPPY_STATE_CLOSED: 467 str = "CLOSED"; 468 break; 469 case UTOPPY_STATE_OPENING: 470 str = "OPENING"; 471 break; 472 case UTOPPY_STATE_IDLE: 473 str = "IDLE"; 474 break; 475 case UTOPPY_STATE_READDIR: 476 str = "READ DIRECTORY"; 477 break; 478 case UTOPPY_STATE_READFILE: 479 str = "READ FILE"; 480 break; 481 case UTOPPY_STATE_WRITEFILE: 482 str = "WRITE FILE"; 483 break; 484 default: 485 str = "INVALID!"; 486 break; 487 } 488 489 return str; 490 } 491 492 static void 493 utoppy_dump_packet(const void *b, size_t len) 494 { 495 const uint8_t *buf = b, *l; 496 uint8_t c; 497 size_t i, j; 498 499 if (len == 0) 500 return; 501 502 len = min(len, 256); 503 504 printf("00: "); 505 506 for (i = 0, l = buf; i < len; i++) { 507 printf("%02x ", *buf++); 508 509 if ((i % 16) == 15) { 510 for (j = 0; j < 16; j++) { 511 c = *l++; 512 if (c < ' ' || c > 0x7e) 513 c = '.'; 514 printf("%c", c); 515 } 516 517 printf("\n"); 518 l = buf; 519 520 if ((i + 1) < len) 521 printf("%02x: ", (u_int)i + 1); 522 } 523 } 524 525 while ((i++ % 16) != 0) 526 printf(" "); 527 528 if (l < buf) { 529 while (l < buf) { 530 c = *l++; 531 if (c < ' ' || c > 0x7e) 532 c = '.'; 533 printf("%c", c); 534 } 535 536 printf("\n"); 537 } 538 } 539 #endif 540 541 static usbd_status 542 utoppy_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 543 uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 544 { 545 usbd_status err; 546 547 usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 548 549 err = usbd_sync_transfer_sig(xfer); 550 551 usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 552 return err; 553 } 554 555 static int 556 utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout) 557 { 558 struct utoppy_header *h; 559 usbd_status err; 560 uint32_t len; 561 uint16_t dlen, crc; 562 uint8_t *data, *e, t1, t2; 563 564 h = sc->sc_out_data; 565 566 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, " 567 "len %d\n", device_xname(sc->sc_dev), (u_int)cmd, h->h_len)); 568 569 dlen = h->h_len; 570 len = dlen + UTOPPY_HEADER_SIZE; 571 572 if (len & 1) 573 len++; 574 if ((len % 64) == 0) 575 len += 2; 576 577 if (len >= UTOPPY_BSIZE) { 578 DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: " 579 "packet too big (%d)\n", device_xname(sc->sc_dev), 580 (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", 649 device_xname(sc->sc_dev),err)); 650 651 return err ? utoppy_usbd_status2errno(err) : 0; 652 } 653 654 static int 655 utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout) 656 { 657 struct utoppy_header *h; 658 usbd_status err; 659 uint32_t len, thislen, requested, bytesleft; 660 uint16_t crc; 661 uint8_t *data, *e, t1, t2; 662 663 data = sc->sc_in_data; 664 len = 0; 665 bytesleft = UTOPPY_BSIZE; 666 667 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n", 668 device_xname(sc->sc_dev))); 669 670 do { 671 requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE); 672 673 err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe, 674 USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf, 675 &thislen); 676 677 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: " 678 "usbd_bulk_transfer() returned %d, thislen %d, data %p\n", 679 device_xname(sc->sc_dev), err, (u_int)thislen, data)); 680 681 if (err == 0) { 682 memcpy(data, sc->sc_in_buf, thislen); 683 DDUMP_PACKET(data, thislen); 684 len += thislen; 685 bytesleft -= thislen; 686 data += thislen; 687 } 688 } while (err == 0 && bytesleft && thislen == requested); 689 690 if (err) 691 return utoppy_usbd_status2errno(err); 692 693 h = sc->sc_in_data; 694 695 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d " 696 "bytes in total to %p\n", device_xname(sc->sc_dev), (u_int)len, h)); 697 DDUMP_PACKET(h, len); 698 699 if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) { 700 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad " 701 " length (len %d, h_len %d)\n", device_xname(sc->sc_dev), 702 (int)len, le16toh(h->h_len))); 703 return EIO; 704 } 705 706 len = h->h_len = le16toh(h->h_len); 707 h->h_crc = le16toh(h->h_crc); 708 *respp = h->h_cmd = le16toh(h->h_cmd); 709 h->h_cmd2 = le16toh(h->h_cmd2); 710 711 /* 712 * To maximise data throughput when transferring files, acknowledge 713 * data blocks as soon as we receive them. If we detect an error 714 * later on, we can always cancel. 715 */ 716 if (*respp == UTOPPY_RESP_FILE_DATA) { 717 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: " 718 "ACKing file data\n", device_xname(sc->sc_dev))); 719 720 UTOPPY_OUT_INIT(sc); 721 err = utoppy_send_packet(sc, UTOPPY_CMD_ACK, 722 UTOPPY_SHORT_TIMEOUT); 723 if (err) { 724 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: " 725 "utoppy_recv_packet: failed to ACK file data: %d\n", 726 device_xname(sc->sc_dev), err)); 727 return err; 728 } 729 } 730 731 /* The command word is part of the CRC */ 732 crc = UTOPPY_CRC16(0, h->h_cmd2 >> 8); 733 crc = UTOPPY_CRC16(crc, h->h_cmd2); 734 crc = UTOPPY_CRC16(crc, h->h_cmd >> 8); 735 crc = UTOPPY_CRC16(crc, h->h_cmd); 736 737 /* 738 * Extract any payload, byte-swapping and calculating the CRC16 739 * as we go. 740 */ 741 if (len > UTOPPY_HEADER_SIZE) { 742 data = h->h_data; 743 e = data + ((len & ~1) - UTOPPY_HEADER_SIZE); 744 745 while (data < e) { 746 t1 = data[0]; 747 t2 = data[1]; 748 crc = UTOPPY_CRC16(crc, t2); 749 crc = UTOPPY_CRC16(crc, t1); 750 *data++ = t2; 751 *data++ = t1; 752 } 753 754 if (len & 1) { 755 t1 = data[1]; 756 crc = UTOPPY_CRC16(crc, t1); 757 *data = t1; 758 } 759 } 760 761 sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE; 762 sc->sc_in_offset = 0; 763 764 DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, " 765 "crc 0x%04x, hdrcrc 0x%04x\n", device_xname(sc->sc_dev), 766 (int)len, crc, h->h_crc)); 767 DDUMP_PACKET(h, len); 768 769 return (crc == h->h_crc) ? 0 : EBADMSG; 770 } 771 772 static __inline void * 773 utoppy_current_ptr(void *b) 774 { 775 struct utoppy_header *h = b; 776 777 return &h->h_data[h->h_len]; 778 } 779 780 static __inline void 781 utoppy_advance_ptr(void *b, size_t len) 782 { 783 struct utoppy_header *h = b; 784 785 h->h_len += len; 786 } 787 788 static __inline void 789 utoppy_add_8(struct utoppy_softc *sc, uint8_t v) 790 { 791 struct utoppy_header *h = sc->sc_out_data; 792 uint8_t *p; 793 794 p = utoppy_current_ptr(h); 795 *p = v; 796 utoppy_advance_ptr(h, sizeof(v)); 797 } 798 799 static __inline void 800 utoppy_add_16(struct utoppy_softc *sc, uint16_t v) 801 { 802 struct utoppy_header *h = sc->sc_out_data; 803 uint8_t *p; 804 805 p = utoppy_current_ptr(h); 806 *p++ = (uint8_t)(v >> 8); 807 *p = (uint8_t)v; 808 utoppy_advance_ptr(h, sizeof(v)); 809 } 810 811 static __inline void 812 utoppy_add_32(struct utoppy_softc *sc, uint32_t v) 813 { 814 struct utoppy_header *h = sc->sc_out_data; 815 uint8_t *p; 816 817 p = utoppy_current_ptr(h); 818 *p++ = (uint8_t)(v >> 24); 819 *p++ = (uint8_t)(v >> 16); 820 *p++ = (uint8_t)(v >> 8); 821 *p = (uint8_t)v; 822 utoppy_advance_ptr(h, sizeof(v)); 823 } 824 825 static __inline void 826 utoppy_add_64(struct utoppy_softc *sc, uint64_t v) 827 { 828 struct utoppy_header *h = sc->sc_out_data; 829 uint8_t *p; 830 831 p = utoppy_current_ptr(h); 832 *p++ = (uint8_t)(v >> 56); 833 *p++ = (uint8_t)(v >> 48); 834 *p++ = (uint8_t)(v >> 40); 835 *p++ = (uint8_t)(v >> 32); 836 *p++ = (uint8_t)(v >> 24); 837 *p++ = (uint8_t)(v >> 16); 838 *p++ = (uint8_t)(v >> 8); 839 *p = (uint8_t)v; 840 utoppy_advance_ptr(h, sizeof(v)); 841 } 842 843 static __inline void 844 utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len) 845 { 846 struct utoppy_header *h = sc->sc_out_data; 847 char *p; 848 849 p = utoppy_current_ptr(h); 850 memset(p, 0, len); 851 strncpy(p, str, len); 852 utoppy_advance_ptr(h, len); 853 } 854 855 static int 856 utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen) 857 { 858 struct utoppy_header *h = sc->sc_out_data; 859 uint8_t *p, *str, *s; 860 size_t len; 861 int err; 862 863 p = utoppy_current_ptr(h); 864 865 str = putlen ? (p + sizeof(uint16_t)) : p; 866 867 err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len); 868 869 DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n", 870 err, (int)len)); 871 872 if (err) 873 return err; 874 875 if (len < 2) 876 return EINVAL; 877 878 /* 879 * copyinstr(9) has already copied the terminating NUL character, 880 * but we append another one in case we have to pad the length 881 * later on. 882 */ 883 str[len] = '\0'; 884 885 /* 886 * The Toppy uses backslash as the directory separator, so convert 887 * all forward slashes. 888 */ 889 for (s = &str[len - 2]; s >= str; s--) 890 if (*s == '/') 891 *s = '\\'; 892 893 if ((len + h->h_len) & 1) 894 len++; 895 896 if (putlen) 897 utoppy_add_16(sc, len); 898 899 utoppy_advance_ptr(h, len); 900 901 DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n", 902 (u_int)len)); 903 904 return 0; 905 } 906 907 static __inline int 908 utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp) 909 { 910 uint8_t *p; 911 912 if (sc->sc_in_len < sizeof(*vp)) 913 return 1; 914 915 p = UTOPPY_IN_DATA(sc); 916 *vp = *p; 917 sc->sc_in_offset += sizeof(*vp); 918 sc->sc_in_len -= sizeof(*vp); 919 return 0; 920 } 921 922 static __inline int 923 utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp) 924 { 925 uint16_t v; 926 uint8_t *p; 927 928 if (sc->sc_in_len < sizeof(v)) 929 return 1; 930 931 p = UTOPPY_IN_DATA(sc); 932 v = *p++; 933 v = (v << 8) | *p; 934 *vp = v; 935 sc->sc_in_offset += sizeof(v); 936 sc->sc_in_len -= sizeof(v); 937 return 0; 938 } 939 940 static __inline int 941 utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp) 942 { 943 uint32_t v; 944 uint8_t *p; 945 946 if (sc->sc_in_len < sizeof(v)) 947 return 1; 948 949 p = UTOPPY_IN_DATA(sc); 950 v = *p++; 951 v = (v << 8) | *p++; 952 v = (v << 8) | *p++; 953 v = (v << 8) | *p; 954 *vp = v; 955 sc->sc_in_offset += sizeof(v); 956 sc->sc_in_len -= sizeof(v); 957 return 0; 958 } 959 960 static __inline int 961 utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp) 962 { 963 uint64_t v; 964 uint8_t *p; 965 966 if (sc->sc_in_len < sizeof(v)) 967 return 1; 968 969 p = UTOPPY_IN_DATA(sc); 970 v = *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 v = (v << 8) | *p; 978 *vp = v; 979 sc->sc_in_offset += sizeof(v); 980 sc->sc_in_len -= sizeof(v); 981 return 0; 982 } 983 984 static __inline int 985 utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len) 986 { 987 char *p; 988 989 if (sc->sc_in_len < len) 990 return 1; 991 992 memset(str, 0, len); 993 p = UTOPPY_IN_DATA(sc); 994 strncpy(str, p, len); 995 sc->sc_in_offset += len; 996 sc->sc_in_len -= len; 997 return 0; 998 } 999 1000 static int 1001 utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout, 1002 uint16_t *presp) 1003 { 1004 int err; 1005 1006 err = utoppy_send_packet(sc, cmd, timeout); 1007 if (err) 1008 return err; 1009 1010 err = utoppy_recv_packet(sc, presp, timeout); 1011 if (err == EBADMSG) { 1012 UTOPPY_OUT_INIT(sc); 1013 utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout); 1014 } 1015 1016 return err; 1017 } 1018 1019 static int 1020 utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp) 1021 { 1022 uint16_t mjd; 1023 uint8_t hour, minute, sec; 1024 uint32_t rv; 1025 1026 if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) || 1027 utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec)) 1028 return 1; 1029 1030 if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){ 1031 *tp = 0; 1032 return 0; 1033 } 1034 1035 rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd; 1036 1037 /* Calculate seconds since 1970 */ 1038 rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24; 1039 1040 /* Add in the hours, minutes, and seconds */ 1041 rv += (uint32_t)hour * 60 * 60; 1042 rv += (uint32_t)minute * 60; 1043 rv += sec; 1044 *tp = (time_t)rv; 1045 1046 return 0; 1047 } 1048 1049 static void 1050 utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t) 1051 { 1052 u_int mjd, hour, minute; 1053 1054 mjd = t / (60 * 60 * 24); 1055 t -= mjd * 60 * 60 * 24; 1056 1057 hour = t / (60 * 60); 1058 t -= hour * 60 * 60; 1059 1060 minute = t / 60; 1061 t -= minute * 60; 1062 1063 utoppy_add_16(sc, mjd + UTOPPY_MJD_1970); 1064 utoppy_add_8(sc, hour); 1065 utoppy_add_8(sc, minute); 1066 utoppy_add_8(sc, t); 1067 } 1068 1069 static int 1070 utoppy_turbo_mode(struct utoppy_softc *sc, int state) 1071 { 1072 uint16_t r; 1073 int err; 1074 1075 UTOPPY_OUT_INIT(sc); 1076 utoppy_add_32(sc, state); 1077 1078 err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r); 1079 if (err) 1080 return err; 1081 1082 return (r == UTOPPY_RESP_SUCCESS) ? 0 : EIO; 1083 } 1084 1085 static int 1086 utoppy_check_ready(struct utoppy_softc *sc) 1087 { 1088 uint16_t r; 1089 int err; 1090 1091 UTOPPY_OUT_INIT(sc); 1092 1093 err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r); 1094 if (err) 1095 return err; 1096 1097 return (r == UTOPPY_RESP_SUCCESS) ? 0 : EIO; 1098 } 1099 1100 static int 1101 utoppy_cancel(struct utoppy_softc *sc) 1102 { 1103 uint16_t r; 1104 int err, i; 1105 1106 /* 1107 * Issue the cancel command serveral times. the Toppy doesn't 1108 * always respond to the first. 1109 */ 1110 for (i = 0; i < 3; i++) { 1111 UTOPPY_OUT_INIT(sc); 1112 err = utoppy_command(sc, UTOPPY_CMD_CANCEL, 1113 UTOPPY_SHORT_TIMEOUT, &r); 1114 if (err == 0 && r == UTOPPY_RESP_SUCCESS) 1115 break; 1116 err = ETIMEDOUT; 1117 } 1118 1119 if (err) 1120 return err; 1121 1122 /* 1123 * Make sure turbo mode is off, otherwise the Toppy will not 1124 * respond to remote control input. 1125 */ 1126 (void) utoppy_turbo_mode(sc, 0); 1127 1128 sc->sc_state = UTOPPY_STATE_IDLE; 1129 return 0; 1130 } 1131 1132 static int 1133 utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us) 1134 { 1135 uint32_t hsize, hfree; 1136 uint16_t r; 1137 int err; 1138 1139 UTOPPY_OUT_INIT(sc); 1140 err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r); 1141 if (err) 1142 return err; 1143 1144 if (r != UTOPPY_RESP_STATS_DATA) 1145 return EIO; 1146 1147 if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree)) 1148 return EIO; 1149 1150 us->us_hdd_size = hsize; 1151 us->us_hdd_size *= 1024; 1152 us->us_hdd_free = hfree; 1153 us->us_hdd_free *= 1024; 1154 1155 return 0; 1156 } 1157 1158 static int 1159 utoppy_readdir_next(struct utoppy_softc *sc) 1160 { 1161 uint16_t resp; 1162 int err; 1163 1164 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n", 1165 device_xname(sc->sc_dev))); 1166 1167 /* 1168 * Fetch the next READDIR response 1169 */ 1170 err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT); 1171 if (err) { 1172 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1173 "utoppy_recv_packet() returned %d\n", 1174 device_xname(sc->sc_dev), err)); 1175 if (err == EBADMSG) { 1176 UTOPPY_OUT_INIT(sc); 1177 utoppy_send_packet(sc, UTOPPY_RESP_ERROR, 1178 UTOPPY_LONG_TIMEOUT); 1179 } 1180 utoppy_cancel(sc); 1181 return err; 1182 } 1183 1184 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1185 "utoppy_recv_packet() returned %d, len %ld\n", 1186 device_xname(sc->sc_dev), err, (u_long)sc->sc_in_len)); 1187 1188 switch (resp) { 1189 case UTOPPY_RESP_READDIR_DATA: 1190 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1191 "UTOPPY_RESP_READDIR_DATA\n", device_xname(sc->sc_dev))); 1192 1193 UTOPPY_OUT_INIT(sc); 1194 err = utoppy_send_packet(sc, UTOPPY_CMD_ACK, 1195 UTOPPY_LONG_TIMEOUT); 1196 if (err) { 1197 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1198 "utoppy_send_packet(ACK) returned %d\n", 1199 device_xname(sc->sc_dev), err)); 1200 utoppy_cancel(sc); 1201 return err; 1202 } 1203 sc->sc_state = UTOPPY_STATE_READDIR; 1204 sc->sc_in_offset = 0; 1205 break; 1206 1207 case UTOPPY_RESP_READDIR_END: 1208 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1209 "UTOPPY_RESP_READDIR_END\n", device_xname(sc->sc_dev))); 1210 1211 UTOPPY_OUT_INIT(sc); 1212 utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT); 1213 sc->sc_state = UTOPPY_STATE_IDLE; 1214 sc->sc_in_len = 0; 1215 break; 1216 1217 default: 1218 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: " 1219 "bad response: 0x%x\n", device_xname(sc->sc_dev), resp)); 1220 sc->sc_state = UTOPPY_STATE_IDLE; 1221 sc->sc_in_len = 0; 1222 return EIO; 1223 } 1224 1225 return 0; 1226 } 1227 1228 static size_t 1229 utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud) 1230 { 1231 uint8_t ftype; 1232 1233 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left" 1234 " %d\n", device_xname(sc->sc_dev), (int)sc->sc_in_len)); 1235 1236 if (utoppy_timestamp_decode(sc, &ud->ud_mtime) || 1237 utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) || 1238 utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) || 1239 utoppy_get_32(sc, &ud->ud_attributes)) { 1240 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no " 1241 "more to decode\n", device_xname(sc->sc_dev))); 1242 return 0; 1243 } 1244 1245 switch (ftype) { 1246 case UTOPPY_FTYPE_DIR: 1247 ud->ud_type = UTOPPY_DIRENT_DIRECTORY; 1248 break; 1249 case UTOPPY_FTYPE_FILE: 1250 ud->ud_type = UTOPPY_DIRENT_FILE; 1251 break; 1252 default: 1253 ud->ud_type = UTOPPY_DIRENT_UNKNOWN; 1254 break; 1255 } 1256 1257 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', " 1258 "size %lld, time 0x%08lx, attr 0x%08x\n", device_xname(sc->sc_dev), 1259 (ftype == UTOPPY_FTYPE_DIR) ? "DIR" : 1260 ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path, 1261 ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes)); 1262 1263 return 1; 1264 } 1265 1266 static int 1267 utoppy_readfile_next(struct utoppy_softc *sc) 1268 { 1269 uint64_t off; 1270 uint16_t resp; 1271 int err; 1272 1273 err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT); 1274 if (err) { 1275 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1276 "utoppy_recv_packet() returned %d\n", 1277 device_xname(sc->sc_dev), err)); 1278 utoppy_cancel(sc); 1279 return err; 1280 } 1281 1282 switch (resp) { 1283 case UTOPPY_RESP_FILE_HEADER: 1284 /* ACK it */ 1285 UTOPPY_OUT_INIT(sc); 1286 err = utoppy_send_packet(sc, UTOPPY_CMD_ACK, 1287 UTOPPY_LONG_TIMEOUT); 1288 if (err) { 1289 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1290 "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n", 1291 device_xname(sc->sc_dev), err)); 1292 utoppy_cancel(sc); 1293 return err; 1294 } 1295 1296 sc->sc_in_len = 0; 1297 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1298 "FILE_HEADER done\n", device_xname(sc->sc_dev))); 1299 break; 1300 1301 case UTOPPY_RESP_FILE_DATA: 1302 /* Already ACK'd */ 1303 if (utoppy_get_64(sc, &off)) { 1304 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1305 "UTOPPY_RESP_FILE_DATA did not provide offset\n", 1306 device_xname(sc->sc_dev))); 1307 utoppy_cancel(sc); 1308 return EBADMSG; 1309 } 1310 1311 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1312 "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n", 1313 device_xname(sc->sc_dev), off, (u_long)sc->sc_in_len)); 1314 break; 1315 1316 case UTOPPY_RESP_FILE_END: 1317 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: " 1318 "UTOPPY_RESP_FILE_END: sending ACK\n", 1319 device_xname(sc->sc_dev))); 1320 UTOPPY_OUT_INIT(sc); 1321 utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT); 1322 /*FALLTHROUGH*/ 1323 1324 case UTOPPY_RESP_SUCCESS: 1325 sc->sc_state = UTOPPY_STATE_IDLE; 1326 (void) utoppy_turbo_mode(sc, 0); 1327 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all " 1328 "done\n", device_xname(sc->sc_dev))); 1329 break; 1330 1331 case UTOPPY_RESP_ERROR: 1332 default: 1333 DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad " 1334 "response code 0x%0x\n", device_xname(sc->sc_dev), resp)); 1335 utoppy_cancel(sc); 1336 return EIO; 1337 } 1338 1339 return 0; 1340 } 1341 1342 int 1343 utoppyopen(dev_t dev, int flag, int mode, 1344 struct lwp *l) 1345 { 1346 struct utoppy_softc *sc; 1347 int error = 0; 1348 1349 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1350 if (sc == NULL) 1351 return ENXIO; 1352 1353 if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) 1354 return ENXIO; 1355 1356 if (sc->sc_state != UTOPPY_STATE_CLOSED) { 1357 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n", 1358 device_xname(sc->sc_dev))); 1359 return EBUSY; 1360 } 1361 1362 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n", 1363 device_xname(sc->sc_dev))); 1364 1365 sc->sc_refcnt++; 1366 sc->sc_state = UTOPPY_STATE_OPENING; 1367 sc->sc_turbo_mode = 0; 1368 sc->sc_out_data = kmem_alloc(UTOPPY_BSIZE + 1, KM_SLEEP); 1369 if (sc->sc_out_data == NULL) { 1370 error = ENOMEM; 1371 goto error; 1372 } 1373 1374 sc->sc_in_data = kmem_alloc(UTOPPY_BSIZE + 1, KM_SLEEP); 1375 if (sc->sc_in_data == NULL) { 1376 kmem_free(sc->sc_out_data, UTOPPY_BSIZE + 1); 1377 sc->sc_out_data = NULL; 1378 error = ENOMEM; 1379 goto error; 1380 } 1381 1382 if ((error = utoppy_cancel(sc)) != 0) 1383 goto error; 1384 1385 if ((error = utoppy_check_ready(sc)) != 0) { 1386 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()" 1387 " returned %d\n", device_xname(sc->sc_dev), error)); 1388 } 1389 1390 error: 1391 sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE; 1392 1393 DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state " 1394 "'%s'\n", device_xname(sc->sc_dev), error, 1395 utoppy_state_string(sc->sc_state))); 1396 1397 if (--sc->sc_refcnt < 0) 1398 usb_detach_wakeupold(sc->sc_dev); 1399 1400 return error; 1401 } 1402 1403 int 1404 utoppyclose(dev_t dev, int flag, int mode, 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 " 1417 "open: %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 " 1564 "%ld, 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 " 1611 "%ld, wr_size %lld, wr_offset %lld, err %d\n", 1612 device_xname(sc->sc_dev), (u_long)uio->uio_resid, sc->sc_wr_size, 1613 sc->sc_wr_offset, err)); 1614 1615 if (err == 0 && sc->sc_wr_size == 0) { 1616 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending " 1617 "FILE_END...\n", device_xname(sc->sc_dev))); 1618 UTOPPY_OUT_INIT(sc); 1619 err = utoppy_command(sc, UTOPPY_RESP_FILE_END, 1620 UTOPPY_LONG_TIMEOUT, &resp); 1621 if (err) { 1622 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: " 1623 "utoppy_command(UTOPPY_RESP_FILE_END) returned " 1624 "%d\n", device_xname(sc->sc_dev), err)); 1625 1626 utoppy_cancel(sc); 1627 } 1628 1629 sc->sc_state = UTOPPY_STATE_IDLE; 1630 DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n", 1631 device_xname(sc->sc_dev), 1632 utoppy_state_string(sc->sc_state))); 1633 } 1634 1635 if (--sc->sc_refcnt < 0) 1636 usb_detach_wakeupold(sc->sc_dev); 1637 1638 return err; 1639 } 1640 1641 int 1642 utoppyioctl(dev_t dev, u_long cmd, void *data, int flag, 1643 struct lwp *l) 1644 { 1645 struct utoppy_softc *sc; 1646 struct utoppy_rename *ur; 1647 struct utoppy_readfile *urf; 1648 struct utoppy_writefile *uw; 1649 char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp; 1650 uint16_t resp; 1651 int err; 1652 1653 sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev)); 1654 1655 if (sc->sc_dying) 1656 return EIO; 1657 1658 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n", 1659 device_xname(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state))); 1660 1661 if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) { 1662 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n", 1663 device_xname(sc->sc_dev))); 1664 return EBUSY; 1665 } 1666 1667 sc->sc_refcnt++; 1668 1669 switch (cmd) { 1670 case UTOPPYIOTURBO: 1671 err = 0; 1672 sc->sc_turbo_mode = *((int *)data) ? 1 : 0; 1673 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: " 1674 "%s\n", device_xname(sc->sc_dev), 1675 sc->sc_turbo_mode ? "On" : "Off")); 1676 break; 1677 1678 case UTOPPYIOCANCEL: 1679 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n", 1680 device_xname(sc->sc_dev))); 1681 err = utoppy_cancel(sc); 1682 break; 1683 1684 case UTOPPYIOREBOOT: 1685 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n", 1686 device_xname(sc->sc_dev))); 1687 UTOPPY_OUT_INIT(sc); 1688 err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT, 1689 &resp); 1690 if (err) 1691 break; 1692 1693 if (resp != UTOPPY_RESP_SUCCESS) 1694 err = EIO; 1695 break; 1696 1697 case UTOPPYIOSTATS: 1698 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n", 1699 device_xname(sc->sc_dev))); 1700 err = utoppy_stats(sc, (struct utoppy_stats *)data); 1701 break; 1702 1703 case UTOPPYIORENAME: 1704 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n", 1705 device_xname(sc->sc_dev))); 1706 ur = (struct utoppy_rename *)data; 1707 UTOPPY_OUT_INIT(sc); 1708 1709 if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0) 1710 break; 1711 if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0) 1712 break; 1713 1714 err = utoppy_command(sc, UTOPPY_CMD_RENAME, 1715 UTOPPY_LONG_TIMEOUT, &resp); 1716 if (err) 1717 break; 1718 1719 if (resp != UTOPPY_RESP_SUCCESS) 1720 err = EIO; 1721 break; 1722 1723 case UTOPPYIOMKDIR: 1724 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n", 1725 device_xname(sc->sc_dev))); 1726 UTOPPY_OUT_INIT(sc); 1727 err = utoppy_add_path(sc, *((const char **)data), 1); 1728 if (err) 1729 break; 1730 1731 err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT, 1732 &resp); 1733 if (err) 1734 break; 1735 1736 if (resp != UTOPPY_RESP_SUCCESS) 1737 err = EIO; 1738 break; 1739 1740 case UTOPPYIODELETE: 1741 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n", 1742 device_xname(sc->sc_dev))); 1743 UTOPPY_OUT_INIT(sc); 1744 err = utoppy_add_path(sc, *((const char **)data), 0); 1745 if (err) 1746 break; 1747 1748 err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT, 1749 &resp); 1750 if (err) 1751 break; 1752 1753 if (resp != UTOPPY_RESP_SUCCESS) 1754 err = EIO; 1755 break; 1756 1757 case UTOPPYIOREADDIR: 1758 DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n", 1759 device_xname(sc->sc_dev))); 1760 UTOPPY_OUT_INIT(sc); 1761 err = utoppy_add_path(sc, *((const char **)data), 0); 1762 if (err) { 1763 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1764 "utoppy_add_path() returned %d\n", 1765 device_xname(sc->sc_dev), err)); 1766 break; 1767 } 1768 1769 err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR, 1770 UTOPPY_LONG_TIMEOUT); 1771 if (err != 0) { 1772 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1773 "UTOPPY_CMD_READDIR returned %d\n", 1774 device_xname(sc->sc_dev), err)); 1775 break; 1776 } 1777 1778 err = utoppy_readdir_next(sc); 1779 if (err) { 1780 DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: " 1781 "utoppy_readdir_next() returned %d\n", 1782 device_xname(sc->sc_dev), err)); 1783 } 1784 break; 1785 1786 case UTOPPYIOREADFILE: 1787 urf = (struct utoppy_readfile *)data; 1788 1789 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE " 1790 "%s, offset %lld\n", device_xname(sc->sc_dev), 1791 urf->ur_path, urf->ur_offset)); 1792 1793 if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0) 1794 break; 1795 1796 UTOPPY_OUT_INIT(sc); 1797 utoppy_add_8(sc, UTOPPY_FILE_READ); 1798 1799 if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0) 1800 break; 1801 1802 utoppy_add_64(sc, urf->ur_offset); 1803 1804 sc->sc_state = UTOPPY_STATE_READFILE; 1805 sc->sc_in_offset = 0; 1806 1807 err = utoppy_send_packet(sc, UTOPPY_CMD_FILE, 1808 UTOPPY_LONG_TIMEOUT); 1809 if (err == 0) 1810 err = utoppy_readfile_next(sc); 1811 break; 1812 1813 case UTOPPYIOWRITEFILE: 1814 uw = (struct utoppy_writefile *)data; 1815 1816 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE " 1817 "%s, size %lld, offset %lld\n", device_xname(sc->sc_dev), 1818 uw->uw_path, uw->uw_size, uw->uw_offset)); 1819 1820 if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0) 1821 break; 1822 1823 UTOPPY_OUT_INIT(sc); 1824 utoppy_add_8(sc, UTOPPY_FILE_WRITE); 1825 uwfp = utoppy_current_ptr(sc->sc_out_data); 1826 1827 if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) { 1828 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path()" 1829 " returned %d\n", device_xname(sc->sc_dev), err)); 1830 break; 1831 } 1832 1833 strncpy(uwf, &uwfp[2], sizeof(uwf)); 1834 utoppy_add_64(sc, uw->uw_offset); 1835 1836 err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT, 1837 &resp); 1838 if (err) { 1839 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1840 "utoppy_command(UTOPPY_CMD_FILE) returned " 1841 "%d\n", device_xname(sc->sc_dev), err)); 1842 break; 1843 } 1844 if (resp != UTOPPY_RESP_SUCCESS) { 1845 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1846 "utoppy_command(UTOPPY_CMD_FILE) returned " 1847 "bad response 0x%x\n", device_xname(sc->sc_dev), 1848 resp)); 1849 err = EIO; 1850 break; 1851 } 1852 1853 UTOPPY_OUT_INIT(sc); 1854 utoppy_timestamp_encode(sc, uw->uw_mtime); 1855 utoppy_add_8(sc, UTOPPY_FTYPE_FILE); 1856 utoppy_add_64(sc, uw->uw_size); 1857 utoppy_add_string(sc, uwf, sizeof(uwf)); 1858 utoppy_add_32(sc, 0); 1859 1860 err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER, 1861 UTOPPY_LONG_TIMEOUT, &resp); 1862 if (err) { 1863 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1864 "utoppy_command(UTOPPY_RESP_FILE_HEADER) " 1865 "returned %d\n", device_xname(sc->sc_dev), err)); 1866 break; 1867 } 1868 if (resp != UTOPPY_RESP_SUCCESS) { 1869 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: " 1870 "utoppy_command(UTOPPY_RESP_FILE_HEADER) " 1871 "returned bad response 0x%x\n", 1872 device_xname(sc->sc_dev), resp)); 1873 err = EIO; 1874 break; 1875 } 1876 1877 sc->sc_wr_offset = uw->uw_offset; 1878 sc->sc_wr_size = uw->uw_size; 1879 sc->sc_state = UTOPPY_STATE_WRITEFILE; 1880 1881 DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to " 1882 "%s. wr_offset %lld, wr_size %lld\n", 1883 device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state), 1884 sc->sc_wr_offset, sc->sc_wr_size)); 1885 break; 1886 1887 default: 1888 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n", 1889 device_xname(sc->sc_dev))); 1890 err = ENODEV; 1891 break; 1892 } 1893 1894 DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n", 1895 device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state))); 1896 1897 if (err) 1898 utoppy_cancel(sc); 1899 1900 if (--sc->sc_refcnt < 0) 1901 usb_detach_wakeupold(sc->sc_dev); 1902 1903 return err; 1904 } 1905