1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/queue.h> 28 #include <sys/types.h> 29 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <unistd.h> 36 37 #include "libusb20.h" 38 #include "libusb20_desc.h" 39 #include "libusb20_int.h" 40 41 #include <dev/usb/usb.h> 42 #include <dev/usb/usbdi.h> 43 #include <dev/usb/usb_ioctl.h> 44 45 static libusb20_init_backend_t ugen20_init_backend; 46 static libusb20_open_device_t ugen20_open_device; 47 static libusb20_close_device_t ugen20_close_device; 48 static libusb20_get_backend_name_t ugen20_get_backend_name; 49 static libusb20_exit_backend_t ugen20_exit_backend; 50 static libusb20_dev_get_iface_desc_t ugen20_dev_get_iface_desc; 51 static libusb20_dev_get_info_t ugen20_dev_get_info; 52 static libusb20_root_get_dev_quirk_t ugen20_root_get_dev_quirk; 53 static libusb20_root_get_quirk_name_t ugen20_root_get_quirk_name; 54 static libusb20_root_add_dev_quirk_t ugen20_root_add_dev_quirk; 55 static libusb20_root_remove_dev_quirk_t ugen20_root_remove_dev_quirk; 56 static libusb20_root_set_template_t ugen20_root_set_template; 57 static libusb20_root_get_template_t ugen20_root_get_template; 58 59 const struct libusb20_backend_methods libusb20_ugen20_backend = { 60 LIBUSB20_BACKEND(LIBUSB20_DECLARE, ugen20) 61 }; 62 63 /* USB device specific */ 64 static libusb20_get_config_desc_full_t ugen20_get_config_desc_full; 65 static libusb20_get_config_index_t ugen20_get_config_index; 66 static libusb20_set_config_index_t ugen20_set_config_index; 67 static libusb20_set_alt_index_t ugen20_set_alt_index; 68 static libusb20_reset_device_t ugen20_reset_device; 69 static libusb20_check_connected_t ugen20_check_connected; 70 static libusb20_set_power_mode_t ugen20_set_power_mode; 71 static libusb20_get_power_mode_t ugen20_get_power_mode; 72 static libusb20_kernel_driver_active_t ugen20_kernel_driver_active; 73 static libusb20_detach_kernel_driver_t ugen20_detach_kernel_driver; 74 static libusb20_do_request_sync_t ugen20_do_request_sync; 75 static libusb20_process_t ugen20_process; 76 77 /* USB transfer specific */ 78 static libusb20_tr_open_t ugen20_tr_open; 79 static libusb20_tr_close_t ugen20_tr_close; 80 static libusb20_tr_clear_stall_sync_t ugen20_tr_clear_stall_sync; 81 static libusb20_tr_submit_t ugen20_tr_submit; 82 static libusb20_tr_cancel_async_t ugen20_tr_cancel_async; 83 84 static const struct libusb20_device_methods libusb20_ugen20_device_methods = { 85 LIBUSB20_DEVICE(LIBUSB20_DECLARE, ugen20) 86 }; 87 88 static const char * 89 ugen20_get_backend_name(void) 90 { 91 return ("FreeBSD UGEN 2.0"); 92 } 93 94 static uint32_t 95 ugen20_path_convert_one(const char **pp) 96 { 97 const char *ptr; 98 uint32_t temp = 0; 99 100 ptr = *pp; 101 102 while ((*ptr >= '0') && (*ptr <= '9')) { 103 temp *= 10; 104 temp += (*ptr - '0'); 105 if (temp >= 1000000) { 106 /* catch overflow early */ 107 return (0xFFFFFFFF); 108 } 109 ptr++; 110 } 111 112 if (*ptr == '.') { 113 /* skip dot */ 114 ptr++; 115 } 116 *pp = ptr; 117 118 return (temp); 119 } 120 121 static int 122 ugen20_enumerate(struct libusb20_device *pdev, const char *id) 123 { 124 const char *tmp = id; 125 struct usb_device_descriptor ddesc; 126 struct usb_device_info devinfo; 127 uint32_t plugtime; 128 char buf[64]; 129 int f; 130 int error; 131 132 pdev->bus_number = ugen20_path_convert_one(&tmp); 133 pdev->device_address = ugen20_path_convert_one(&tmp); 134 135 snprintf(buf, sizeof(buf), "/dev/" USB_GENERIC_NAME "%u.%u", 136 pdev->bus_number, pdev->device_address); 137 138 f = open(buf, O_RDWR); 139 if (f < 0) { 140 return (LIBUSB20_ERROR_OTHER); 141 } 142 if (ioctl(f, USB_GET_PLUGTIME, &plugtime)) { 143 error = LIBUSB20_ERROR_OTHER; 144 goto done; 145 } 146 /* store when the device was plugged */ 147 pdev->session_data.plugtime = plugtime; 148 149 if (ioctl(f, USB_GET_DEVICE_DESC, &ddesc)) { 150 error = LIBUSB20_ERROR_OTHER; 151 goto done; 152 } 153 LIBUSB20_INIT(LIBUSB20_DEVICE_DESC, &(pdev->ddesc)); 154 155 libusb20_me_decode(&ddesc, sizeof(ddesc), &(pdev->ddesc)); 156 157 if (pdev->ddesc.bNumConfigurations == 0) { 158 error = LIBUSB20_ERROR_OTHER; 159 goto done; 160 } else if (pdev->ddesc.bNumConfigurations >= 8) { 161 error = LIBUSB20_ERROR_OTHER; 162 goto done; 163 } 164 if (ioctl(f, USB_GET_DEVICEINFO, &devinfo)) { 165 error = LIBUSB20_ERROR_OTHER; 166 goto done; 167 } 168 switch (devinfo.udi_mode) { 169 case USB_MODE_DEVICE: 170 pdev->usb_mode = LIBUSB20_MODE_DEVICE; 171 break; 172 default: 173 pdev->usb_mode = LIBUSB20_MODE_HOST; 174 break; 175 } 176 177 switch (devinfo.udi_speed) { 178 case USB_SPEED_LOW: 179 pdev->usb_speed = LIBUSB20_SPEED_LOW; 180 break; 181 case USB_SPEED_FULL: 182 pdev->usb_speed = LIBUSB20_SPEED_FULL; 183 break; 184 case USB_SPEED_HIGH: 185 pdev->usb_speed = LIBUSB20_SPEED_HIGH; 186 break; 187 case USB_SPEED_VARIABLE: 188 pdev->usb_speed = LIBUSB20_SPEED_VARIABLE; 189 break; 190 case USB_SPEED_SUPER: 191 pdev->usb_speed = LIBUSB20_SPEED_SUPER; 192 break; 193 default: 194 pdev->usb_speed = LIBUSB20_SPEED_UNKNOWN; 195 break; 196 } 197 198 /* get parent HUB index and port */ 199 200 pdev->parent_address = devinfo.udi_hubindex; 201 pdev->parent_port = devinfo.udi_hubport; 202 203 /* generate a nice description for printout */ 204 205 snprintf(pdev->usb_desc, sizeof(pdev->usb_desc), 206 USB_GENERIC_NAME "%u.%u: <%s %s> at usbus%u", pdev->bus_number, 207 pdev->device_address, devinfo.udi_product, 208 devinfo.udi_vendor, pdev->bus_number); 209 210 error = 0; 211 done: 212 close(f); 213 return (error); 214 } 215 216 struct ugen20_urd_state { 217 struct usb_read_dir urd; 218 uint32_t nparsed; 219 int f; 220 uint8_t *ptr; 221 const char *src; 222 const char *dst; 223 uint8_t buf[256]; 224 uint8_t dummy_zero[1]; 225 }; 226 227 static int 228 ugen20_readdir(struct ugen20_urd_state *st) 229 { 230 ; /* style fix */ 231 repeat: 232 if (st->ptr == NULL) { 233 st->urd.urd_startentry += st->nparsed; 234 st->urd.urd_data = libusb20_pass_ptr(st->buf); 235 st->urd.urd_maxlen = sizeof(st->buf); 236 st->nparsed = 0; 237 238 if (ioctl(st->f, USB_READ_DIR, &st->urd)) { 239 return (EINVAL); 240 } 241 st->ptr = st->buf; 242 } 243 if (st->ptr[0] == 0) { 244 if (st->nparsed) { 245 st->ptr = NULL; 246 goto repeat; 247 } else { 248 return (ENXIO); 249 } 250 } 251 st->src = (void *)(st->ptr + 1); 252 st->dst = st->src + strlen(st->src) + 1; 253 st->ptr = st->ptr + st->ptr[0]; 254 st->nparsed++; 255 256 if ((st->ptr < st->buf) || 257 (st->ptr > st->dummy_zero)) { 258 /* invalid entry */ 259 return (EINVAL); 260 } 261 return (0); 262 } 263 264 static int 265 ugen20_init_backend(struct libusb20_backend *pbe) 266 { 267 struct ugen20_urd_state state; 268 struct libusb20_device *pdev; 269 270 memset(&state, 0, sizeof(state)); 271 272 state.f = open("/dev/" USB_DEVICE_NAME, O_RDONLY); 273 if (state.f < 0) 274 return (LIBUSB20_ERROR_OTHER); 275 276 while (ugen20_readdir(&state) == 0) { 277 278 if ((state.src[0] != 'u') || 279 (state.src[1] != 'g') || 280 (state.src[2] != 'e') || 281 (state.src[3] != 'n')) { 282 continue; 283 } 284 pdev = libusb20_dev_alloc(); 285 if (pdev == NULL) { 286 continue; 287 } 288 if (ugen20_enumerate(pdev, state.src + 4)) { 289 libusb20_dev_free(pdev); 290 continue; 291 } 292 /* put the device on the backend list */ 293 libusb20_be_enqueue_device(pbe, pdev); 294 } 295 close(state.f); 296 return (0); /* success */ 297 } 298 299 static void 300 ugen20_tr_release(struct libusb20_device *pdev) 301 { 302 struct usb_fs_uninit fs_uninit; 303 304 if (pdev->nTransfer == 0) { 305 return; 306 } 307 /* release all pending USB transfers */ 308 if (pdev->privBeData != NULL) { 309 memset(&fs_uninit, 0, sizeof(fs_uninit)); 310 if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { 311 /* ignore any errors of this kind */ 312 } 313 } 314 return; 315 } 316 317 static int 318 ugen20_tr_renew(struct libusb20_device *pdev) 319 { 320 struct usb_fs_init fs_init; 321 struct usb_fs_endpoint *pfse; 322 int error; 323 uint32_t size; 324 uint16_t nMaxTransfer; 325 326 nMaxTransfer = pdev->nTransfer; 327 error = 0; 328 329 if (nMaxTransfer == 0) { 330 goto done; 331 } 332 size = nMaxTransfer * sizeof(*pfse); 333 334 if (pdev->privBeData == NULL) { 335 pfse = malloc(size); 336 if (pfse == NULL) { 337 error = LIBUSB20_ERROR_NO_MEM; 338 goto done; 339 } 340 pdev->privBeData = pfse; 341 } 342 /* reset endpoint data */ 343 memset(pdev->privBeData, 0, size); 344 345 memset(&fs_init, 0, sizeof(fs_init)); 346 347 fs_init.pEndpoints = libusb20_pass_ptr(pdev->privBeData); 348 fs_init.ep_index_max = nMaxTransfer; 349 350 if (ioctl(pdev->file, USB_FS_INIT, &fs_init)) { 351 error = LIBUSB20_ERROR_OTHER; 352 goto done; 353 } 354 done: 355 return (error); 356 } 357 358 static int 359 ugen20_open_device(struct libusb20_device *pdev, uint16_t nMaxTransfer) 360 { 361 uint32_t plugtime; 362 char buf[64]; 363 int f; 364 int g; 365 int error; 366 367 snprintf(buf, sizeof(buf), "/dev/" USB_GENERIC_NAME "%u.%u", 368 pdev->bus_number, pdev->device_address); 369 370 /* 371 * We need two file handles, one for the control endpoint and one 372 * for BULK, INTERRUPT and ISOCHRONOUS transactions due to optimised 373 * kernel locking. 374 */ 375 g = open(buf, O_RDWR); 376 if (g < 0) { 377 return (LIBUSB20_ERROR_NO_DEVICE); 378 } 379 f = open(buf, O_RDWR); 380 if (f < 0) { 381 close(g); 382 return (LIBUSB20_ERROR_NO_DEVICE); 383 } 384 if (ioctl(f, USB_GET_PLUGTIME, &plugtime)) { 385 error = LIBUSB20_ERROR_OTHER; 386 goto done; 387 } 388 /* check that the correct device is still plugged */ 389 if (pdev->session_data.plugtime != plugtime) { 390 error = LIBUSB20_ERROR_NO_DEVICE; 391 goto done; 392 } 393 /* need to set this before "tr_renew()" */ 394 pdev->file = f; 395 pdev->file_ctrl = g; 396 397 /* renew all USB transfers */ 398 error = ugen20_tr_renew(pdev); 399 if (error) { 400 goto done; 401 } 402 /* set methods */ 403 pdev->methods = &libusb20_ugen20_device_methods; 404 405 done: 406 if (error) { 407 if (pdev->privBeData) { 408 /* cleanup after "tr_renew()" */ 409 free(pdev->privBeData); 410 pdev->privBeData = NULL; 411 } 412 pdev->file = -1; 413 pdev->file_ctrl = -1; 414 close(f); 415 close(g); 416 } 417 return (error); 418 } 419 420 static int 421 ugen20_close_device(struct libusb20_device *pdev) 422 { 423 struct usb_fs_uninit fs_uninit; 424 425 if (pdev->privBeData) { 426 memset(&fs_uninit, 0, sizeof(fs_uninit)); 427 if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { 428 /* ignore this error */ 429 } 430 free(pdev->privBeData); 431 } 432 pdev->nTransfer = 0; 433 pdev->privBeData = NULL; 434 close(pdev->file); 435 close(pdev->file_ctrl); 436 pdev->file = -1; 437 pdev->file_ctrl = -1; 438 return (0); /* success */ 439 } 440 441 static void 442 ugen20_exit_backend(struct libusb20_backend *pbe) 443 { 444 return; /* nothing to do */ 445 } 446 447 static int 448 ugen20_get_config_desc_full(struct libusb20_device *pdev, 449 uint8_t **ppbuf, uint16_t *plen, uint8_t cfg_index) 450 { 451 struct usb_gen_descriptor gen_desc; 452 struct usb_config_descriptor cdesc; 453 uint8_t *ptr; 454 uint16_t len; 455 int error; 456 457 /* make sure memory is initialised */ 458 memset(&cdesc, 0, sizeof(cdesc)); 459 memset(&gen_desc, 0, sizeof(gen_desc)); 460 461 gen_desc.ugd_data = libusb20_pass_ptr(&cdesc); 462 gen_desc.ugd_maxlen = sizeof(cdesc); 463 gen_desc.ugd_config_index = cfg_index; 464 465 error = ioctl(pdev->file_ctrl, USB_GET_FULL_DESC, &gen_desc); 466 if (error) { 467 return (LIBUSB20_ERROR_OTHER); 468 } 469 len = UGETW(cdesc.wTotalLength); 470 if (len < sizeof(cdesc)) { 471 /* corrupt descriptor */ 472 return (LIBUSB20_ERROR_OTHER); 473 } 474 ptr = malloc(len); 475 if (!ptr) { 476 return (LIBUSB20_ERROR_NO_MEM); 477 } 478 479 /* make sure memory is initialised */ 480 memset(ptr, 0, len); 481 482 gen_desc.ugd_data = libusb20_pass_ptr(ptr); 483 gen_desc.ugd_maxlen = len; 484 485 error = ioctl(pdev->file_ctrl, USB_GET_FULL_DESC, &gen_desc); 486 if (error) { 487 free(ptr); 488 return (LIBUSB20_ERROR_OTHER); 489 } 490 /* make sure that the device doesn't fool us */ 491 memcpy(ptr, &cdesc, sizeof(cdesc)); 492 493 *ppbuf = ptr; 494 *plen = len; 495 496 return (0); /* success */ 497 } 498 499 static int 500 ugen20_get_config_index(struct libusb20_device *pdev, uint8_t *pindex) 501 { 502 int temp; 503 504 if (ioctl(pdev->file_ctrl, USB_GET_CONFIG, &temp)) { 505 return (LIBUSB20_ERROR_OTHER); 506 } 507 *pindex = temp; 508 509 return (0); 510 } 511 512 static int 513 ugen20_set_config_index(struct libusb20_device *pdev, uint8_t cfg_index) 514 { 515 int temp = cfg_index; 516 517 /* release all active USB transfers */ 518 ugen20_tr_release(pdev); 519 520 if (ioctl(pdev->file_ctrl, USB_SET_CONFIG, &temp)) { 521 return (LIBUSB20_ERROR_OTHER); 522 } 523 return (ugen20_tr_renew(pdev)); 524 } 525 526 static int 527 ugen20_set_alt_index(struct libusb20_device *pdev, 528 uint8_t iface_index, uint8_t alt_index) 529 { 530 struct usb_alt_interface alt_iface; 531 532 memset(&alt_iface, 0, sizeof(alt_iface)); 533 534 alt_iface.uai_interface_index = iface_index; 535 alt_iface.uai_alt_index = alt_index; 536 537 /* release all active USB transfers */ 538 ugen20_tr_release(pdev); 539 540 if (ioctl(pdev->file_ctrl, USB_SET_ALTINTERFACE, &alt_iface)) { 541 return (LIBUSB20_ERROR_OTHER); 542 } 543 return (ugen20_tr_renew(pdev)); 544 } 545 546 static int 547 ugen20_reset_device(struct libusb20_device *pdev) 548 { 549 int temp = 0; 550 551 /* release all active USB transfers */ 552 ugen20_tr_release(pdev); 553 554 if (ioctl(pdev->file_ctrl, USB_DEVICEENUMERATE, &temp)) { 555 return (LIBUSB20_ERROR_OTHER); 556 } 557 return (ugen20_tr_renew(pdev)); 558 } 559 560 static int 561 ugen20_check_connected(struct libusb20_device *pdev) 562 { 563 uint32_t plugtime; 564 int error = 0; 565 566 if (ioctl(pdev->file_ctrl, USB_GET_PLUGTIME, &plugtime)) { 567 error = LIBUSB20_ERROR_NO_DEVICE; 568 goto done; 569 } 570 571 if (pdev->session_data.plugtime != plugtime) { 572 error = LIBUSB20_ERROR_NO_DEVICE; 573 goto done; 574 } 575 done: 576 return (error); 577 } 578 579 static int 580 ugen20_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 581 { 582 int temp; 583 584 switch (power_mode) { 585 case LIBUSB20_POWER_OFF: 586 temp = USB_POWER_MODE_OFF; 587 break; 588 case LIBUSB20_POWER_ON: 589 temp = USB_POWER_MODE_ON; 590 break; 591 case LIBUSB20_POWER_SAVE: 592 temp = USB_POWER_MODE_SAVE; 593 break; 594 case LIBUSB20_POWER_SUSPEND: 595 temp = USB_POWER_MODE_SUSPEND; 596 break; 597 case LIBUSB20_POWER_RESUME: 598 temp = USB_POWER_MODE_RESUME; 599 break; 600 default: 601 return (LIBUSB20_ERROR_INVALID_PARAM); 602 } 603 if (ioctl(pdev->file_ctrl, USB_SET_POWER_MODE, &temp)) { 604 return (LIBUSB20_ERROR_OTHER); 605 } 606 return (0); 607 } 608 609 static int 610 ugen20_get_power_mode(struct libusb20_device *pdev, uint8_t *power_mode) 611 { 612 int temp; 613 614 if (ioctl(pdev->file_ctrl, USB_GET_POWER_MODE, &temp)) { 615 return (LIBUSB20_ERROR_OTHER); 616 } 617 switch (temp) { 618 case USB_POWER_MODE_OFF: 619 temp = LIBUSB20_POWER_OFF; 620 break; 621 case USB_POWER_MODE_ON: 622 temp = LIBUSB20_POWER_ON; 623 break; 624 case USB_POWER_MODE_SAVE: 625 temp = LIBUSB20_POWER_SAVE; 626 break; 627 case USB_POWER_MODE_SUSPEND: 628 temp = LIBUSB20_POWER_SUSPEND; 629 break; 630 case USB_POWER_MODE_RESUME: 631 temp = LIBUSB20_POWER_RESUME; 632 break; 633 default: 634 temp = LIBUSB20_POWER_ON; 635 break; 636 } 637 *power_mode = temp; 638 return (0); /* success */ 639 } 640 641 static int 642 ugen20_kernel_driver_active(struct libusb20_device *pdev, 643 uint8_t iface_index) 644 { 645 int temp = iface_index; 646 647 if (ioctl(pdev->file_ctrl, USB_IFACE_DRIVER_ACTIVE, &temp)) { 648 return (LIBUSB20_ERROR_OTHER); 649 } 650 return (0); /* kernel driver is active */ 651 } 652 653 static int 654 ugen20_detach_kernel_driver(struct libusb20_device *pdev, 655 uint8_t iface_index) 656 { 657 int temp = iface_index; 658 659 if (ioctl(pdev->file_ctrl, USB_IFACE_DRIVER_DETACH, &temp)) { 660 return (LIBUSB20_ERROR_OTHER); 661 } 662 return (0); /* kernel driver is active */ 663 } 664 665 static int 666 ugen20_do_request_sync(struct libusb20_device *pdev, 667 struct LIBUSB20_CONTROL_SETUP_DECODED *setup, 668 void *data, uint16_t *pactlen, uint32_t timeout, uint8_t flags) 669 { 670 struct usb_ctl_request req; 671 672 memset(&req, 0, sizeof(req)); 673 674 req.ucr_data = libusb20_pass_ptr(data); 675 if (!(flags & LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK)) { 676 req.ucr_flags |= USB_SHORT_XFER_OK; 677 } 678 if (libusb20_me_encode(&req.ucr_request, 679 sizeof(req.ucr_request), setup)) { 680 /* ignore */ 681 } 682 if (ioctl(pdev->file_ctrl, USB_DO_REQUEST, &req)) { 683 return (LIBUSB20_ERROR_OTHER); 684 } 685 if (pactlen) { 686 /* get actual length */ 687 *pactlen = req.ucr_actlen; 688 } 689 return (0); /* kernel driver is active */ 690 } 691 692 static int 693 ugen20_process(struct libusb20_device *pdev) 694 { 695 struct usb_fs_complete temp; 696 struct usb_fs_endpoint *fsep; 697 struct libusb20_transfer *xfer; 698 699 while (1) { 700 701 if (ioctl(pdev->file, USB_FS_COMPLETE, &temp)) { 702 if (errno == EBUSY) { 703 break; 704 } else { 705 /* device detached */ 706 return (LIBUSB20_ERROR_OTHER); 707 } 708 } 709 fsep = pdev->privBeData; 710 xfer = pdev->pTransfer; 711 fsep += temp.ep_index; 712 xfer += temp.ep_index; 713 714 /* update transfer status */ 715 716 if (fsep->status == 0) { 717 xfer->aFrames = fsep->aFrames; 718 xfer->timeComplete = fsep->isoc_time_complete; 719 xfer->status = LIBUSB20_TRANSFER_COMPLETED; 720 } else if (fsep->status == USB_ERR_CANCELLED) { 721 xfer->aFrames = 0; 722 xfer->timeComplete = 0; 723 xfer->status = LIBUSB20_TRANSFER_CANCELLED; 724 } else if (fsep->status == USB_ERR_STALLED) { 725 xfer->aFrames = 0; 726 xfer->timeComplete = 0; 727 xfer->status = LIBUSB20_TRANSFER_STALL; 728 } else if (fsep->status == USB_ERR_TIMEOUT) { 729 xfer->aFrames = 0; 730 xfer->timeComplete = 0; 731 xfer->status = LIBUSB20_TRANSFER_TIMED_OUT; 732 } else { 733 xfer->aFrames = 0; 734 xfer->timeComplete = 0; 735 xfer->status = LIBUSB20_TRANSFER_ERROR; 736 } 737 libusb20_tr_callback_wrapper(xfer); 738 } 739 return (0); /* done */ 740 } 741 742 static int 743 ugen20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 744 uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id, 745 uint8_t pre_scale) 746 { 747 union { 748 struct usb_fs_open fs_open; 749 struct usb_fs_open_stream fs_open_stream; 750 } temp; 751 struct usb_fs_endpoint *fsep; 752 753 if (pre_scale) 754 MaxFrameCount |= USB_FS_MAX_FRAMES_PRE_SCALE; 755 756 memset(&temp, 0, sizeof(temp)); 757 758 fsep = xfer->pdev->privBeData; 759 fsep += xfer->trIndex; 760 761 temp.fs_open.max_bufsize = MaxBufSize; 762 temp.fs_open.max_frames = MaxFrameCount; 763 temp.fs_open.ep_index = xfer->trIndex; 764 temp.fs_open.ep_no = ep_no; 765 766 if (stream_id != 0) { 767 temp.fs_open_stream.stream_id = stream_id; 768 769 if (ioctl(xfer->pdev->file, USB_FS_OPEN_STREAM, &temp.fs_open_stream)) 770 return (LIBUSB20_ERROR_INVALID_PARAM); 771 } else { 772 if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp.fs_open)) 773 return (LIBUSB20_ERROR_INVALID_PARAM); 774 } 775 /* maximums might have changed - update */ 776 xfer->maxFrames = temp.fs_open.max_frames; 777 778 /* "max_bufsize" should be multiple of "max_packet_length" */ 779 xfer->maxTotalLength = temp.fs_open.max_bufsize; 780 xfer->maxPacketLen = temp.fs_open.max_packet_length; 781 782 /* setup buffer and length lists using zero copy */ 783 fsep->ppBuffer = libusb20_pass_ptr(xfer->ppBuffer); 784 fsep->pLength = libusb20_pass_ptr(xfer->pLength); 785 786 return (0); /* success */ 787 } 788 789 static int 790 ugen20_tr_close(struct libusb20_transfer *xfer) 791 { 792 struct usb_fs_close temp; 793 794 memset(&temp, 0, sizeof(temp)); 795 796 temp.ep_index = xfer->trIndex; 797 798 if (ioctl(xfer->pdev->file, USB_FS_CLOSE, &temp)) { 799 return (LIBUSB20_ERROR_INVALID_PARAM); 800 } 801 return (0); /* success */ 802 } 803 804 static int 805 ugen20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 806 { 807 struct usb_fs_clear_stall_sync temp; 808 809 memset(&temp, 0, sizeof(temp)); 810 811 /* if the transfer is active, an error will be returned */ 812 813 temp.ep_index = xfer->trIndex; 814 815 if (ioctl(xfer->pdev->file, USB_FS_CLEAR_STALL_SYNC, &temp)) { 816 return (LIBUSB20_ERROR_INVALID_PARAM); 817 } 818 return (0); /* success */ 819 } 820 821 static void 822 ugen20_tr_submit(struct libusb20_transfer *xfer) 823 { 824 struct usb_fs_start temp; 825 struct usb_fs_endpoint *fsep; 826 827 memset(&temp, 0, sizeof(temp)); 828 829 fsep = xfer->pdev->privBeData; 830 fsep += xfer->trIndex; 831 832 fsep->nFrames = xfer->nFrames; 833 fsep->flags = 0; 834 if (!(xfer->flags & LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK)) { 835 fsep->flags |= USB_FS_FLAG_SINGLE_SHORT_OK; 836 } 837 if (!(xfer->flags & LIBUSB20_TRANSFER_MULTI_SHORT_NOT_OK)) { 838 fsep->flags |= USB_FS_FLAG_MULTI_SHORT_OK; 839 } 840 if (xfer->flags & LIBUSB20_TRANSFER_FORCE_SHORT) { 841 fsep->flags |= USB_FS_FLAG_FORCE_SHORT; 842 } 843 if (xfer->flags & LIBUSB20_TRANSFER_DO_CLEAR_STALL) { 844 fsep->flags |= USB_FS_FLAG_CLEAR_STALL; 845 } 846 /* NOTE: The "fsep->timeout" variable is 16-bit. */ 847 if (xfer->timeout > 65535) 848 fsep->timeout = 65535; 849 else 850 fsep->timeout = xfer->timeout; 851 852 temp.ep_index = xfer->trIndex; 853 854 if (ioctl(xfer->pdev->file, USB_FS_START, &temp)) { 855 /* ignore any errors - should never happen */ 856 } 857 return; /* success */ 858 } 859 860 static void 861 ugen20_tr_cancel_async(struct libusb20_transfer *xfer) 862 { 863 struct usb_fs_stop temp; 864 865 memset(&temp, 0, sizeof(temp)); 866 867 temp.ep_index = xfer->trIndex; 868 869 if (ioctl(xfer->pdev->file, USB_FS_STOP, &temp)) { 870 /* ignore any errors - should never happen */ 871 } 872 return; 873 } 874 875 static int 876 ugen20_be_ioctl(uint32_t cmd, void *data) 877 { 878 int f; 879 int error; 880 881 f = open("/dev/" USB_DEVICE_NAME, O_RDONLY); 882 if (f < 0) 883 return (LIBUSB20_ERROR_OTHER); 884 error = ioctl(f, cmd, data); 885 if (error == -1) { 886 if (errno == EPERM) { 887 error = LIBUSB20_ERROR_ACCESS; 888 } else { 889 error = LIBUSB20_ERROR_OTHER; 890 } 891 } 892 close(f); 893 return (error); 894 } 895 896 static int 897 ugen20_dev_get_iface_desc(struct libusb20_device *pdev, 898 uint8_t iface_index, char *buf, uint8_t len) 899 { 900 struct usb_gen_descriptor ugd; 901 902 memset(&ugd, 0, sizeof(ugd)); 903 904 ugd.ugd_data = libusb20_pass_ptr(buf); 905 ugd.ugd_maxlen = len; 906 ugd.ugd_iface_index = iface_index; 907 908 if (ioctl(pdev->file, USB_GET_IFACE_DRIVER, &ugd)) { 909 return (LIBUSB20_ERROR_INVALID_PARAM); 910 } 911 return (0); 912 } 913 914 static int 915 ugen20_dev_get_info(struct libusb20_device *pdev, 916 struct usb_device_info *pinfo) 917 { 918 if (ioctl(pdev->file, USB_GET_DEVICEINFO, pinfo)) { 919 return (LIBUSB20_ERROR_INVALID_PARAM); 920 } 921 return (0); 922 } 923 924 static int 925 ugen20_root_get_dev_quirk(struct libusb20_backend *pbe, 926 uint16_t quirk_index, struct libusb20_quirk *pq) 927 { 928 struct usb_gen_quirk q; 929 int error; 930 931 memset(&q, 0, sizeof(q)); 932 933 q.index = quirk_index; 934 935 error = ugen20_be_ioctl(USB_DEV_QUIRK_GET, &q); 936 937 if (error) { 938 if (errno == EINVAL) { 939 return (LIBUSB20_ERROR_NOT_FOUND); 940 } 941 } else { 942 pq->vid = q.vid; 943 pq->pid = q.pid; 944 pq->bcdDeviceLow = q.bcdDeviceLow; 945 pq->bcdDeviceHigh = q.bcdDeviceHigh; 946 strlcpy(pq->quirkname, q.quirkname, sizeof(pq->quirkname)); 947 } 948 return (error); 949 } 950 951 static int 952 ugen20_root_get_quirk_name(struct libusb20_backend *pbe, uint16_t quirk_index, 953 struct libusb20_quirk *pq) 954 { 955 struct usb_gen_quirk q; 956 int error; 957 958 memset(&q, 0, sizeof(q)); 959 960 q.index = quirk_index; 961 962 error = ugen20_be_ioctl(USB_QUIRK_NAME_GET, &q); 963 964 if (error) { 965 if (errno == EINVAL) { 966 return (LIBUSB20_ERROR_NOT_FOUND); 967 } 968 } else { 969 strlcpy(pq->quirkname, q.quirkname, sizeof(pq->quirkname)); 970 } 971 return (error); 972 } 973 974 static int 975 ugen20_root_add_dev_quirk(struct libusb20_backend *pbe, 976 struct libusb20_quirk *pq) 977 { 978 struct usb_gen_quirk q; 979 int error; 980 981 memset(&q, 0, sizeof(q)); 982 983 q.vid = pq->vid; 984 q.pid = pq->pid; 985 q.bcdDeviceLow = pq->bcdDeviceLow; 986 q.bcdDeviceHigh = pq->bcdDeviceHigh; 987 strlcpy(q.quirkname, pq->quirkname, sizeof(q.quirkname)); 988 989 error = ugen20_be_ioctl(USB_DEV_QUIRK_ADD, &q); 990 if (error) { 991 if (errno == ENOMEM) { 992 return (LIBUSB20_ERROR_NO_MEM); 993 } 994 } 995 return (error); 996 } 997 998 static int 999 ugen20_root_remove_dev_quirk(struct libusb20_backend *pbe, 1000 struct libusb20_quirk *pq) 1001 { 1002 struct usb_gen_quirk q; 1003 int error; 1004 1005 memset(&q, 0, sizeof(q)); 1006 1007 q.vid = pq->vid; 1008 q.pid = pq->pid; 1009 q.bcdDeviceLow = pq->bcdDeviceLow; 1010 q.bcdDeviceHigh = pq->bcdDeviceHigh; 1011 strlcpy(q.quirkname, pq->quirkname, sizeof(q.quirkname)); 1012 1013 error = ugen20_be_ioctl(USB_DEV_QUIRK_REMOVE, &q); 1014 if (error) { 1015 if (errno == EINVAL) { 1016 return (LIBUSB20_ERROR_NOT_FOUND); 1017 } 1018 } 1019 return (error); 1020 } 1021 1022 static int 1023 ugen20_root_set_template(struct libusb20_backend *pbe, int temp) 1024 { 1025 return (ugen20_be_ioctl(USB_SET_TEMPLATE, &temp)); 1026 } 1027 1028 static int 1029 ugen20_root_get_template(struct libusb20_backend *pbe, int *ptemp) 1030 { 1031 return (ugen20_be_ioctl(USB_GET_TEMPLATE, ptemp)); 1032 } 1033