libusb20_ugen20.c revision 185087
1/* $FreeBSD: head/lib/libusb20/libusb20_ugen20.c 185087 2008-11-19 08:56:35Z alfred $ */ 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 <stdio.h> 31#include <stdlib.h> 32#include <unistd.h> 33#include <string.h> 34#include <poll.h> 35#include <fcntl.h> 36#include <errno.h> 37 38#include "libusb20.h" 39#include "libusb20_desc.h" 40#include "libusb20_int.h" 41 42#include <dev/usb2/include/usb2_standard.h> 43#include <dev/usb2/include/usb2_ioctl.h> 44#include <dev/usb2/include/usb2_mfunc.h> 45#include <dev/usb2/include/usb2_error.h> 46#include <dev/usb2/include/usb2_revision.h> 47 48static libusb20_init_backend_t ugen20_init_backend; 49static libusb20_open_device_t ugen20_open_device; 50static libusb20_close_device_t ugen20_close_device; 51static libusb20_get_backend_name_t ugen20_get_backend_name; 52static libusb20_exit_backend_t ugen20_exit_backend; 53static libusb20_bus_set_owner_t ugen20_bus_set_owner; 54static libusb20_bus_get_owner_t ugen20_bus_get_owner; 55static libusb20_bus_set_perm_t ugen20_bus_set_perm; 56static libusb20_bus_get_perm_t ugen20_bus_get_perm; 57static libusb20_dev_get_iface_owner_t ugen20_dev_get_iface_owner; 58static libusb20_dev_get_iface_perm_t ugen20_dev_get_iface_perm; 59static libusb20_dev_get_owner_t ugen20_dev_get_owner; 60static libusb20_dev_get_perm_t ugen20_dev_get_perm; 61static libusb20_dev_set_iface_owner_t ugen20_dev_set_iface_owner; 62static libusb20_dev_set_iface_perm_t ugen20_dev_set_iface_perm; 63static libusb20_dev_set_owner_t ugen20_dev_set_owner; 64static libusb20_dev_set_perm_t ugen20_dev_set_perm; 65static libusb20_root_get_dev_quirk_t ugen20_root_get_dev_quirk; 66static libusb20_root_get_quirk_name_t ugen20_root_get_quirk_name; 67static libusb20_root_add_dev_quirk_t ugen20_root_add_dev_quirk; 68static libusb20_root_remove_dev_quirk_t ugen20_root_remove_dev_quirk; 69static libusb20_root_set_owner_t ugen20_root_set_owner; 70static libusb20_root_get_owner_t ugen20_root_get_owner; 71static libusb20_root_set_perm_t ugen20_root_set_perm; 72static libusb20_root_get_perm_t ugen20_root_get_perm; 73 74const struct libusb20_backend_methods libusb20_ugen20_backend = { 75 LIBUSB20_BACKEND(LIBUSB20_DECLARE, ugen20) 76}; 77 78/* USB device specific */ 79static libusb20_get_config_desc_full_t ugen20_get_config_desc_full; 80static libusb20_get_config_index_t ugen20_get_config_index; 81static libusb20_set_config_index_t ugen20_set_config_index; 82static libusb20_claim_interface_t ugen20_claim_interface; 83static libusb20_release_interface_t ugen20_release_interface; 84static libusb20_set_alt_index_t ugen20_set_alt_index; 85static libusb20_reset_device_t ugen20_reset_device; 86static libusb20_set_power_mode_t ugen20_set_power_mode; 87static libusb20_get_power_mode_t ugen20_get_power_mode; 88static libusb20_kernel_driver_active_t ugen20_kernel_driver_active; 89static libusb20_detach_kernel_driver_t ugen20_detach_kernel_driver; 90static libusb20_do_request_sync_t ugen20_do_request_sync; 91static libusb20_process_t ugen20_process; 92 93/* USB transfer specific */ 94static libusb20_tr_open_t ugen20_tr_open; 95static libusb20_tr_close_t ugen20_tr_close; 96static libusb20_tr_clear_stall_sync_t ugen20_tr_clear_stall_sync; 97static libusb20_tr_submit_t ugen20_tr_submit; 98static libusb20_tr_cancel_async_t ugen20_tr_cancel_async; 99 100static const struct libusb20_device_methods libusb20_ugen20_device_methods = { 101 LIBUSB20_DEVICE(LIBUSB20_DECLARE, ugen20) 102}; 103 104static const char * 105ugen20_get_backend_name(void) 106{ 107 return ("FreeBSD UGEN 2.0"); 108} 109 110static uint32_t 111ugen20_path_convert_one(const char **pp) 112{ 113 const char *ptr; 114 uint32_t temp = 0; 115 116 ptr = *pp; 117 118 while ((*ptr >= '0') && (*ptr <= '9')) { 119 temp *= 10; 120 temp += (*ptr - '0'); 121 if (temp >= 1000000) { 122 /* catch overflow early */ 123 return (0 - 1); 124 } 125 ptr++; 126 } 127 128 if (*ptr == '.') { 129 /* skip dot */ 130 ptr++; 131 } 132 *pp = ptr; 133 134 return (temp); 135} 136 137static int 138ugen20_enumerate(struct libusb20_device *pdev, const char *id) 139{ 140 const char *tmp = id; 141 struct usb2_device_descriptor ddesc; 142 struct usb2_device_info devinfo; 143 uint32_t plugtime; 144 char buf[64]; 145 int f; 146 int error; 147 148 pdev->bus_number = ugen20_path_convert_one(&tmp); 149 pdev->device_address = ugen20_path_convert_one(&tmp); 150 151 snprintf(buf, sizeof(buf), "/dev/ugen%u.%u", 152 pdev->bus_number, pdev->device_address); 153 154 f = open(buf, O_RDWR); 155 if (f < 0) { 156 return (LIBUSB20_ERROR_OTHER); 157 } 158 if (ioctl(f, USB_GET_PLUGTIME, &plugtime)) { 159 error = LIBUSB20_ERROR_OTHER; 160 goto done; 161 } 162 /* store when the device was plugged */ 163 pdev->session_data.plugtime = plugtime; 164 165 if (ioctl(f, USB_GET_DEVICE_DESC, &ddesc)) { 166 error = LIBUSB20_ERROR_OTHER; 167 goto done; 168 } 169 LIBUSB20_INIT(LIBUSB20_DEVICE_DESC, &(pdev->ddesc)); 170 171 libusb20_me_decode(&ddesc, sizeof(ddesc), &(pdev->ddesc)); 172 173 if (pdev->ddesc.bNumConfigurations == 0) { 174 error = LIBUSB20_ERROR_OTHER; 175 goto done; 176 } else if (pdev->ddesc.bNumConfigurations >= 8) { 177 error = LIBUSB20_ERROR_OTHER; 178 goto done; 179 } 180 if (ioctl(f, USB_GET_DEVICEINFO, &devinfo)) { 181 error = LIBUSB20_ERROR_OTHER; 182 goto done; 183 } 184 switch (devinfo.udi_mode) { 185 case USB_MODE_DEVICE: 186 pdev->usb_mode = LIBUSB20_MODE_DEVICE; 187 break; 188 default: 189 pdev->usb_mode = LIBUSB20_MODE_HOST; 190 break; 191 } 192 193 switch (devinfo.udi_speed) { 194 case USB_SPEED_LOW: 195 pdev->usb_speed = LIBUSB20_SPEED_LOW; 196 break; 197 case USB_SPEED_FULL: 198 pdev->usb_speed = LIBUSB20_SPEED_FULL; 199 break; 200 case USB_SPEED_HIGH: 201 pdev->usb_speed = LIBUSB20_SPEED_HIGH; 202 break; 203 case USB_SPEED_VARIABLE: 204 pdev->usb_speed = LIBUSB20_SPEED_VARIABLE; 205 break; 206 case USB_SPEED_SUPER: 207 pdev->usb_speed = LIBUSB20_SPEED_SUPER; 208 break; 209 default: 210 pdev->usb_speed = LIBUSB20_SPEED_UNKNOWN; 211 break; 212 } 213 214 /* generate a nice description for printout */ 215 216 snprintf(pdev->usb_desc, sizeof(pdev->usb_desc), 217 "ugen%u.%u: <%s %s> at usbus%u", pdev->bus_number, 218 pdev->device_address, devinfo.udi_product, 219 devinfo.udi_vendor, pdev->bus_number); 220 221 error = 0; 222done: 223 close(f); 224 return (error); 225} 226 227struct ugen20_urd_state { 228 struct usb2_read_dir urd; 229 uint32_t nparsed; 230 int f; 231 uint8_t *ptr; 232 const char *src; 233 const char *dst; 234 uint8_t buf[256]; 235 uint8_t dummy_zero[1]; 236}; 237 238static int 239ugen20_readdir(struct ugen20_urd_state *st) 240{ 241 ; /* style fix */ 242repeat: 243 if (st->ptr == NULL) { 244 st->urd.urd_startentry += st->nparsed; 245 st->urd.urd_data = st->buf; 246 st->urd.urd_maxlen = sizeof(st->buf); 247 st->nparsed = 0; 248 249 if (ioctl(st->f, USB_READ_DIR, &st->urd)) { 250 return (EINVAL); 251 } 252 st->ptr = st->buf; 253 } 254 if (st->ptr[0] == 0) { 255 if (st->nparsed) { 256 st->ptr = NULL; 257 goto repeat; 258 } else { 259 return (ENXIO); 260 } 261 } 262 st->src = (void *)(st->ptr + 1); 263 st->dst = st->src + strlen(st->src) + 1; 264 st->ptr = st->ptr + st->ptr[0]; 265 st->nparsed++; 266 267 if ((st->ptr < st->buf) || 268 (st->ptr > st->dummy_zero)) { 269 /* invalid entry */ 270 return (EINVAL); 271 } 272 return (0); 273} 274 275static int 276ugen20_init_backend(struct libusb20_backend *pbe) 277{ 278 struct ugen20_urd_state state; 279 struct libusb20_device *pdev; 280 281 memset(&state, 0, sizeof(state)); 282 283 state.f = open("/dev/usb", O_RDONLY); 284 if (state.f < 0) 285 return (LIBUSB20_ERROR_OTHER); 286 287 while (ugen20_readdir(&state) == 0) { 288 289 if ((state.src[0] != 'u') || 290 (state.src[1] != 'g') || 291 (state.src[2] != 'e') || 292 (state.src[3] != 'n')) { 293 continue; 294 } 295 pdev = libusb20_dev_alloc(); 296 if (pdev == NULL) { 297 continue; 298 } 299 if (ugen20_enumerate(pdev, state.src + 4)) { 300 libusb20_dev_free(pdev); 301 continue; 302 } 303 /* put the device on the backend list */ 304 libusb20_be_enqueue_device(pbe, pdev); 305 } 306 close(state.f); 307 return (0); /* success */ 308} 309 310static int 311ugen20_tr_renew(struct libusb20_device *pdev) 312{ 313 struct usb2_fs_uninit fs_uninit; 314 struct usb2_fs_init fs_init; 315 struct usb2_fs_endpoint *pfse; 316 int error; 317 uint32_t size; 318 uint16_t nMaxTransfer; 319 320 nMaxTransfer = pdev->nTransfer; 321 error = 0; 322 323 if (nMaxTransfer == 0) { 324 goto done; 325 } 326 size = nMaxTransfer * sizeof(*pfse); 327 328 if (pdev->privBeData != NULL) { 329 memset(&fs_uninit, 0, sizeof(fs_uninit)); 330 if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { 331 /* ignore any errors of this kind */ 332 } 333 } else { 334 pfse = malloc(size); 335 if (pfse == NULL) { 336 error = LIBUSB20_ERROR_NO_MEM; 337 goto done; 338 } 339 pdev->privBeData = pfse; 340 } 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 = 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 } 354done: 355 return (error); 356} 357 358static int 359ugen20_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/ugen%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 405done: 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 420static int 421ugen20_close_device(struct libusb20_device *pdev) 422{ 423 struct usb2_fs_uninit fs_uninit; 424 int error = 0; 425 426 if (pdev->privBeData) { 427 memset(&fs_uninit, 0, sizeof(fs_uninit)); 428 if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { 429 error = LIBUSB20_ERROR_OTHER; 430 } 431 free(pdev->privBeData); 432 } 433 pdev->nTransfer = 0; 434 pdev->privBeData = NULL; 435 close(pdev->file); 436 close(pdev->file_ctrl); 437 pdev->file = -1; 438 pdev->file_ctrl = -1; 439 return (error); 440} 441 442static void 443ugen20_exit_backend(struct libusb20_backend *pbe) 444{ 445 return; /* nothing to do */ 446} 447 448static int 449ugen20_get_config_desc_full(struct libusb20_device *pdev, 450 uint8_t **ppbuf, uint16_t *plen, uint8_t cfg_index) 451{ 452 struct usb2_gen_descriptor gen_desc; 453 struct usb2_config_descriptor cdesc; 454 uint8_t *ptr; 455 uint16_t len; 456 int error; 457 458 memset(&gen_desc, 0, sizeof(gen_desc)); 459 460 gen_desc.ugd_data = &cdesc; 461 gen_desc.ugd_maxlen = sizeof(cdesc); 462 gen_desc.ugd_config_index = cfg_index; 463 464 error = ioctl(pdev->file_ctrl, USB_GET_FULL_DESC, &gen_desc); 465 if (error) { 466 return (LIBUSB20_ERROR_OTHER); 467 } 468 len = UGETW(cdesc.wTotalLength); 469 if (len < sizeof(cdesc)) { 470 /* corrupt descriptor */ 471 return (LIBUSB20_ERROR_OTHER); 472 } 473 ptr = malloc(len); 474 if (!ptr) { 475 return (LIBUSB20_ERROR_NO_MEM); 476 } 477 gen_desc.ugd_data = ptr; 478 gen_desc.ugd_maxlen = len; 479 480 error = ioctl(pdev->file_ctrl, USB_GET_FULL_DESC, &gen_desc); 481 if (error) { 482 free(ptr); 483 return (LIBUSB20_ERROR_OTHER); 484 } 485 /* make sure that the device doesn't fool us */ 486 memcpy(ptr, &cdesc, sizeof(cdesc)); 487 488 *ppbuf = ptr; 489 *plen = len; 490 491 return (0); /* success */ 492} 493 494static int 495ugen20_get_config_index(struct libusb20_device *pdev, uint8_t *pindex) 496{ 497 int temp; 498 499 if (ioctl(pdev->file_ctrl, USB_GET_CONFIG, &temp)) { 500 return (LIBUSB20_ERROR_OTHER); 501 } 502 *pindex = temp; 503 504 return (0); 505} 506 507static int 508ugen20_set_config_index(struct libusb20_device *pdev, uint8_t cfg_index) 509{ 510 int temp = cfg_index; 511 512 if (ioctl(pdev->file_ctrl, USB_SET_CONFIG, &temp)) { 513 return (LIBUSB20_ERROR_OTHER); 514 } 515 return (ugen20_tr_renew(pdev)); 516} 517 518static int 519ugen20_claim_interface(struct libusb20_device *pdev, uint8_t iface_index) 520{ 521 int temp = iface_index; 522 523 if (ioctl(pdev->file_ctrl, USB_CLAIM_INTERFACE, &temp)) { 524 return (LIBUSB20_ERROR_OTHER); 525 } 526 return (0); 527} 528 529static int 530ugen20_release_interface(struct libusb20_device *pdev, uint8_t iface_index) 531{ 532 int temp = iface_index; 533 534 if (ioctl(pdev->file_ctrl, USB_RELEASE_INTERFACE, &temp)) { 535 return (LIBUSB20_ERROR_OTHER); 536 } 537 return (0); 538} 539 540static int 541ugen20_set_alt_index(struct libusb20_device *pdev, 542 uint8_t iface_index, uint8_t alt_index) 543{ 544 struct usb2_alt_interface alt_iface; 545 546 memset(&alt_iface, 0, sizeof(alt_iface)); 547 548 alt_iface.uai_interface_index = iface_index; 549 alt_iface.uai_alt_index = alt_index; 550 551 if (ioctl(pdev->file_ctrl, USB_SET_ALTINTERFACE, &alt_iface)) { 552 return (LIBUSB20_ERROR_OTHER); 553 } 554 return (ugen20_tr_renew(pdev)); 555} 556 557static int 558ugen20_reset_device(struct libusb20_device *pdev) 559{ 560 int temp = 0; 561 562 if (ioctl(pdev->file_ctrl, USB_DEVICEENUMERATE, &temp)) { 563 return (LIBUSB20_ERROR_OTHER); 564 } 565 return (ugen20_tr_renew(pdev)); 566} 567 568static int 569ugen20_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 570{ 571 int temp; 572 573 switch (power_mode) { 574 case LIBUSB20_POWER_OFF: 575 temp = USB_POWER_MODE_OFF; 576 break; 577 case LIBUSB20_POWER_ON: 578 temp = USB_POWER_MODE_ON; 579 break; 580 case LIBUSB20_POWER_SAVE: 581 temp = USB_POWER_MODE_SAVE; 582 break; 583 case LIBUSB20_POWER_SUSPEND: 584 temp = USB_POWER_MODE_SUSPEND; 585 break; 586 case LIBUSB20_POWER_RESUME: 587 temp = USB_POWER_MODE_RESUME; 588 break; 589 default: 590 return (LIBUSB20_ERROR_INVALID_PARAM); 591 } 592 if (ioctl(pdev->file_ctrl, USB_SET_POWER_MODE, &temp)) { 593 return (LIBUSB20_ERROR_OTHER); 594 } 595 return (0); 596} 597 598static int 599ugen20_get_power_mode(struct libusb20_device *pdev, uint8_t *power_mode) 600{ 601 int temp; 602 603 if (ioctl(pdev->file_ctrl, USB_GET_POWER_MODE, &temp)) { 604 return (LIBUSB20_ERROR_OTHER); 605 } 606 switch (temp) { 607 case USB_POWER_MODE_OFF: 608 temp = LIBUSB20_POWER_OFF; 609 break; 610 case USB_POWER_MODE_ON: 611 temp = LIBUSB20_POWER_ON; 612 break; 613 case USB_POWER_MODE_SAVE: 614 temp = LIBUSB20_POWER_SAVE; 615 break; 616 case USB_POWER_MODE_SUSPEND: 617 temp = LIBUSB20_POWER_SUSPEND; 618 break; 619 case USB_POWER_MODE_RESUME: 620 temp = LIBUSB20_POWER_RESUME; 621 break; 622 default: 623 temp = LIBUSB20_POWER_ON; 624 break; 625 } 626 *power_mode = temp; 627 return (0); /* success */ 628} 629 630static int 631ugen20_kernel_driver_active(struct libusb20_device *pdev, 632 uint8_t iface_index) 633{ 634 int temp = iface_index; 635 636 if (ioctl(pdev->file_ctrl, USB_IFACE_DRIVER_ACTIVE, &temp)) { 637 return (LIBUSB20_ERROR_OTHER); 638 } 639 return (0); /* kernel driver is active */ 640} 641 642static int 643ugen20_detach_kernel_driver(struct libusb20_device *pdev, 644 uint8_t iface_index) 645{ 646 int temp = iface_index; 647 648 if (ioctl(pdev->file_ctrl, USB_IFACE_DRIVER_DETACH, &temp)) { 649 return (LIBUSB20_ERROR_OTHER); 650 } 651 return (0); /* kernel driver is active */ 652} 653 654static int 655ugen20_do_request_sync(struct libusb20_device *pdev, 656 struct LIBUSB20_CONTROL_SETUP_DECODED *setup, 657 void *data, uint16_t *pactlen, uint32_t timeout, uint8_t flags) 658{ 659 struct usb2_ctl_request req; 660 661 memset(&req, 0, sizeof(req)); 662 663 req.ucr_data = data; 664 if (!(flags & LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK)) { 665 req.ucr_flags |= USB_SHORT_XFER_OK; 666 } 667 if (libusb20_me_encode(&req.ucr_request, 668 sizeof(req.ucr_request), setup)) { 669 /* ignore */ 670 } 671 if (ioctl(pdev->file_ctrl, USB_DO_REQUEST, &req)) { 672 return (LIBUSB20_ERROR_OTHER); 673 } 674 if (pactlen) { 675 /* get actual length */ 676 *pactlen = req.ucr_actlen; 677 } 678 return (0); /* kernel driver is active */ 679} 680 681static int 682ugen20_process(struct libusb20_device *pdev) 683{ 684 struct usb2_fs_complete temp; 685 struct usb2_fs_endpoint *fsep; 686 struct libusb20_transfer *xfer; 687 688 while (1) { 689 690 if (ioctl(pdev->file, USB_FS_COMPLETE, &temp)) { 691 if (errno == EBUSY) { 692 break; 693 } else { 694 /* device detached */ 695 return (LIBUSB20_ERROR_OTHER); 696 } 697 } 698 fsep = pdev->privBeData; 699 xfer = pdev->pTransfer; 700 fsep += temp.ep_index; 701 xfer += temp.ep_index; 702 703 /* update transfer status */ 704 705 if (fsep->status == 0) { 706 xfer->aFrames = fsep->aFrames; 707 xfer->timeComplete = fsep->isoc_time_complete; 708 xfer->status = LIBUSB20_TRANSFER_COMPLETED; 709 } else if (fsep->status == USB_ERR_CANCELLED) { 710 xfer->aFrames = 0; 711 xfer->timeComplete = 0; 712 xfer->status = LIBUSB20_TRANSFER_CANCELLED; 713 } else if (fsep->status == USB_ERR_STALLED) { 714 xfer->aFrames = 0; 715 xfer->timeComplete = 0; 716 xfer->status = LIBUSB20_TRANSFER_STALL; 717 } else if (fsep->status == USB_ERR_TIMEOUT) { 718 xfer->aFrames = 0; 719 xfer->timeComplete = 0; 720 xfer->status = LIBUSB20_TRANSFER_TIMED_OUT; 721 } else { 722 xfer->aFrames = 0; 723 xfer->timeComplete = 0; 724 xfer->status = LIBUSB20_TRANSFER_ERROR; 725 } 726 libusb20_tr_callback_wrapper(xfer); 727 } 728 return (0); /* done */ 729} 730 731static int 732ugen20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 733 uint32_t MaxFrameCount, uint8_t ep_no) 734{ 735 struct usb2_fs_open temp; 736 struct usb2_fs_endpoint *fsep; 737 738 memset(&temp, 0, sizeof(temp)); 739 740 fsep = xfer->pdev->privBeData; 741 fsep += xfer->trIndex; 742 743 temp.max_bufsize = MaxBufSize; 744 temp.max_frames = MaxFrameCount; 745 temp.ep_index = xfer->trIndex; 746 temp.ep_no = ep_no; 747 748 if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp)) { 749 return (LIBUSB20_ERROR_INVALID_PARAM); 750 } 751 /* maximums might have changed - update */ 752 xfer->maxFrames = temp.max_frames; 753 754 /* "max_bufsize" should be multiple of "max_packet_length" */ 755 xfer->maxTotalLength = temp.max_bufsize; 756 xfer->maxPacketLen = temp.max_packet_length; 757 758 /* setup buffer and length lists */ 759 fsep->ppBuffer = xfer->ppBuffer;/* zero copy */ 760 fsep->pLength = xfer->pLength; /* zero copy */ 761 762 return (0); /* success */ 763} 764 765static int 766ugen20_tr_close(struct libusb20_transfer *xfer) 767{ 768 struct usb2_fs_close temp; 769 770 memset(&temp, 0, sizeof(temp)); 771 772 temp.ep_index = xfer->trIndex; 773 774 if (ioctl(xfer->pdev->file, USB_FS_CLOSE, &temp)) { 775 return (LIBUSB20_ERROR_INVALID_PARAM); 776 } 777 return (0); /* success */ 778} 779 780static int 781ugen20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 782{ 783 struct usb2_fs_clear_stall_sync temp; 784 785 memset(&temp, 0, sizeof(temp)); 786 787 /* if the transfer is active, an error will be returned */ 788 789 temp.ep_index = xfer->trIndex; 790 791 if (ioctl(xfer->pdev->file, USB_FS_CLEAR_STALL_SYNC, &temp)) { 792 return (LIBUSB20_ERROR_INVALID_PARAM); 793 } 794 return (0); /* success */ 795} 796 797static void 798ugen20_tr_submit(struct libusb20_transfer *xfer) 799{ 800 struct usb2_fs_start temp; 801 struct usb2_fs_endpoint *fsep; 802 803 memset(&temp, 0, sizeof(temp)); 804 805 fsep = xfer->pdev->privBeData; 806 fsep += xfer->trIndex; 807 808 fsep->nFrames = xfer->nFrames; 809 fsep->flags = 0; 810 if (!(xfer->flags & LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK)) { 811 fsep->flags |= USB_FS_FLAG_SINGLE_SHORT_OK; 812 } 813 if (!(xfer->flags & LIBUSB20_TRANSFER_MULTI_SHORT_NOT_OK)) { 814 fsep->flags |= USB_FS_FLAG_MULTI_SHORT_OK; 815 } 816 if (xfer->flags & LIBUSB20_TRANSFER_FORCE_SHORT) { 817 fsep->flags |= USB_FS_FLAG_FORCE_SHORT; 818 } 819 if (xfer->flags & LIBUSB20_TRANSFER_DO_CLEAR_STALL) { 820 fsep->flags |= USB_FS_FLAG_CLEAR_STALL; 821 } 822 fsep->timeout = xfer->timeout; 823 824 temp.ep_index = xfer->trIndex; 825 826 if (ioctl(xfer->pdev->file, USB_FS_START, &temp)) { 827 /* ignore any errors - should never happen */ 828 } 829 return; /* success */ 830} 831 832static void 833ugen20_tr_cancel_async(struct libusb20_transfer *xfer) 834{ 835 struct usb2_fs_stop temp; 836 837 memset(&temp, 0, sizeof(temp)); 838 839 temp.ep_index = xfer->trIndex; 840 841 if (ioctl(xfer->pdev->file, USB_FS_STOP, &temp)) { 842 /* ignore any errors - should never happen */ 843 } 844 return; 845} 846 847static int 848ugen20_be_ioctl(uint32_t cmd, void *data) 849{ 850 int f; 851 int error; 852 853 f = open("/dev/usb", O_RDONLY); 854 if (f < 0) 855 return (LIBUSB20_ERROR_OTHER); 856 error = ioctl(f, cmd, data); 857 if (error == -1) { 858 if (errno == EPERM) { 859 error = LIBUSB20_ERROR_ACCESS; 860 } else { 861 error = LIBUSB20_ERROR_OTHER; 862 } 863 } 864 close(f); 865 return (error); 866} 867 868static int 869ugen20_be_do_perm(uint32_t get_cmd, uint32_t set_cmd, uint8_t bus, 870 uint8_t dev, uint8_t iface, uid_t *uid, 871 gid_t *gid, mode_t *mode) 872{ 873 struct usb2_dev_perm perm; 874 int error; 875 876 memset(&perm, 0, sizeof(perm)); 877 878 perm.bus_index = bus; 879 perm.dev_index = dev; 880 perm.iface_index = iface; 881 882 error = ugen20_be_ioctl(get_cmd, &perm); 883 if (error) 884 return (error); 885 886 if (set_cmd == 0) { 887 if (uid) 888 *uid = perm.user_id; 889 if (gid) 890 *gid = perm.group_id; 891 if (mode) 892 *mode = perm.mode; 893 return (0); 894 } 895 if (uid) 896 perm.user_id = *uid; 897 if (gid) 898 perm.group_id = *gid; 899 if (mode) 900 perm.mode = *mode; 901 902 return (ugen20_be_ioctl(set_cmd, &perm)); 903} 904 905static int 906ugen20_bus_set_owner(struct libusb20_backend *pbe, 907 uint8_t bus, uid_t user, gid_t group) 908{ 909 return (ugen20_be_do_perm(USB_GET_BUS_PERM, USB_SET_BUS_PERM, 910 bus, 0, 0, &user, &group, NULL)); 911} 912 913static int 914ugen20_bus_get_owner(struct libusb20_backend *pbe, uint8_t bus, 915 uid_t *user, gid_t *group) 916{ 917 return (ugen20_be_do_perm(USB_GET_BUS_PERM, 0, 918 bus, 0, 0, user, group, NULL)); 919} 920 921static int 922ugen20_bus_set_perm(struct libusb20_backend *pbe, 923 uint8_t bus, mode_t mode) 924{ 925 return (ugen20_be_do_perm(USB_GET_BUS_PERM, USB_SET_BUS_PERM, 926 bus, 0, 0, NULL, NULL, &mode)); 927} 928 929static int 930ugen20_bus_get_perm(struct libusb20_backend *pbe, 931 uint8_t bus, mode_t *mode) 932{ 933 return (ugen20_be_do_perm(USB_GET_BUS_PERM, 0, 934 bus, 0, 0, NULL, NULL, mode)); 935} 936 937static int 938ugen20_dev_get_iface_owner(struct libusb20_device *pdev, 939 uint8_t iface_index, uid_t *user, gid_t *group) 940{ 941 return (ugen20_be_do_perm(USB_GET_IFACE_PERM, 0, 942 pdev->bus_number, pdev->device_address, iface_index, 943 user, group, NULL)); 944} 945 946static int 947ugen20_dev_get_iface_perm(struct libusb20_device *pdev, 948 uint8_t iface_index, mode_t *mode) 949{ 950 return (ugen20_be_do_perm(USB_GET_IFACE_PERM, 0, 951 pdev->bus_number, pdev->device_address, iface_index, 952 NULL, NULL, mode)); 953} 954 955static int 956ugen20_dev_get_owner(struct libusb20_device *pdev, 957 uid_t *user, gid_t *group) 958{ 959 return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, 0, 960 pdev->bus_number, pdev->device_address, 0, 961 user, group, NULL)); 962} 963 964static int 965ugen20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode) 966{ 967 return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, 0, 968 pdev->bus_number, pdev->device_address, 0, 969 NULL, NULL, mode)); 970} 971 972static int 973ugen20_dev_set_iface_owner(struct libusb20_device *pdev, 974 uint8_t iface_index, uid_t user, gid_t group) 975{ 976 return (ugen20_be_do_perm(USB_GET_IFACE_PERM, USB_SET_IFACE_PERM, 977 pdev->bus_number, pdev->device_address, iface_index, 978 &user, &group, NULL)); 979} 980 981static int 982ugen20_dev_set_iface_perm(struct libusb20_device *pdev, 983 uint8_t iface_index, mode_t mode) 984{ 985 return (ugen20_be_do_perm(USB_GET_IFACE_PERM, USB_SET_IFACE_PERM, 986 pdev->bus_number, pdev->device_address, iface_index, 987 NULL, NULL, &mode)); 988} 989 990static int 991ugen20_root_get_dev_quirk(struct libusb20_backend *pbe, 992 uint16_t quirk_index, struct libusb20_quirk *pq) 993{ 994 struct usb2_gen_quirk q; 995 int error; 996 997 memset(&q, 0, sizeof(q)); 998 999 q.index = quirk_index; 1000 1001 error = ugen20_be_ioctl(USB_DEV_QUIRK_GET, &q); 1002 1003 if (error) { 1004 if (errno == EINVAL) { 1005 return (LIBUSB20_ERROR_NOT_FOUND); 1006 } 1007 } else { 1008 pq->vid = q.vid; 1009 pq->pid = q.pid; 1010 pq->bcdDeviceLow = q.bcdDeviceLow; 1011 pq->bcdDeviceHigh = q.bcdDeviceHigh; 1012 strlcpy(pq->quirkname, q.quirkname, sizeof(pq->quirkname)); 1013 } 1014 return (error); 1015} 1016 1017static int 1018ugen20_root_get_quirk_name(struct libusb20_backend *pbe, uint16_t quirk_index, 1019 struct libusb20_quirk *pq) 1020{ 1021 struct usb2_gen_quirk q; 1022 int error; 1023 1024 memset(&q, 0, sizeof(q)); 1025 1026 q.index = quirk_index; 1027 1028 error = ugen20_be_ioctl(USB_QUIRK_NAME_GET, &q); 1029 1030 if (error) { 1031 if (errno == EINVAL) { 1032 return (LIBUSB20_ERROR_NOT_FOUND); 1033 } 1034 } else { 1035 strlcpy(pq->quirkname, q.quirkname, sizeof(pq->quirkname)); 1036 } 1037 return (error); 1038} 1039 1040static int 1041ugen20_root_add_dev_quirk(struct libusb20_backend *pbe, 1042 struct libusb20_quirk *pq) 1043{ 1044 struct usb2_gen_quirk q; 1045 int error; 1046 1047 memset(&q, 0, sizeof(q)); 1048 1049 q.vid = pq->vid; 1050 q.pid = pq->pid; 1051 q.bcdDeviceLow = pq->bcdDeviceLow; 1052 q.bcdDeviceHigh = pq->bcdDeviceHigh; 1053 strlcpy(q.quirkname, pq->quirkname, sizeof(q.quirkname)); 1054 1055 error = ugen20_be_ioctl(USB_DEV_QUIRK_ADD, &q); 1056 if (error) { 1057 if (errno == ENOMEM) { 1058 return (LIBUSB20_ERROR_NO_MEM); 1059 } 1060 } 1061 return (error); 1062} 1063 1064static int 1065ugen20_root_remove_dev_quirk(struct libusb20_backend *pbe, 1066 struct libusb20_quirk *pq) 1067{ 1068 struct usb2_gen_quirk q; 1069 int error; 1070 1071 memset(&q, 0, sizeof(q)); 1072 1073 q.vid = pq->vid; 1074 q.pid = pq->pid; 1075 q.bcdDeviceLow = pq->bcdDeviceLow; 1076 q.bcdDeviceHigh = pq->bcdDeviceHigh; 1077 strlcpy(q.quirkname, pq->quirkname, sizeof(q.quirkname)); 1078 1079 error = ugen20_be_ioctl(USB_DEV_QUIRK_REMOVE, &q); 1080 if (error) { 1081 if (errno == EINVAL) { 1082 return (LIBUSB20_ERROR_NOT_FOUND); 1083 } 1084 } 1085 return (error); 1086} 1087 1088static int 1089ugen20_dev_set_owner(struct libusb20_device *pdev, 1090 uid_t user, gid_t group) 1091{ 1092 return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, USB_SET_DEVICE_PERM, 1093 pdev->bus_number, pdev->device_address, 0, 1094 &user, &group, NULL)); 1095} 1096 1097static int 1098ugen20_dev_set_perm(struct libusb20_device *pdev, mode_t mode) 1099{ 1100 return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, USB_SET_DEVICE_PERM, 1101 pdev->bus_number, pdev->device_address, 0, 1102 NULL, NULL, &mode)); 1103} 1104 1105static int 1106ugen20_root_set_owner(struct libusb20_backend *pbe, 1107 uid_t user, gid_t group) 1108{ 1109 return (ugen20_be_do_perm(USB_GET_ROOT_PERM, USB_SET_ROOT_PERM, 0, 0, 0, 1110 &user, &group, NULL)); 1111} 1112 1113static int 1114ugen20_root_get_owner(struct libusb20_backend *pbe, uid_t *user, gid_t *group) 1115{ 1116 return (ugen20_be_do_perm(USB_GET_ROOT_PERM, 0, 0, 0, 0, 1117 user, group, NULL)); 1118} 1119 1120static int 1121ugen20_root_set_perm(struct libusb20_backend *pbe, mode_t mode) 1122{ 1123 return (ugen20_be_do_perm(USB_GET_ROOT_PERM, USB_SET_ROOT_PERM, 0, 0, 0, 1124 NULL, NULL, &mode)); 1125} 1126 1127static int 1128ugen20_root_get_perm(struct libusb20_backend *pbe, mode_t *mode) 1129{ 1130 return (ugen20_be_do_perm(USB_GET_ROOT_PERM, 0, 0, 0, 0, 1131 NULL, NULL, mode)); 1132} 1133