1/* $FreeBSD: head/lib/libusb/libusb10.c 195560 2009-07-10 14:15:53Z thompsa $ */ |
2/*- 3 * Copyright (c) 2009 Sylvestre Gallon. 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. --- 60 unchanged lines hidden (view full) --- 70 if (debug != NULL) { 71 ctx->debug = atoi(debug); 72 if (ctx->debug != 0) 73 ctx->debug_fixed = 1; 74 } 75 76 pthread_mutex_init(&ctx->usb_devs_lock, NULL); 77 pthread_mutex_init(&ctx->open_devs_lock, NULL); |
78 TAILQ_INIT(&ctx->usb_devs); 79 TAILQ_INIT(&ctx->open_devs); |
80 81 pthread_mutex_init(&ctx->flying_transfers_lock, NULL); 82 pthread_mutex_init(&ctx->pollfds_lock, NULL); 83 pthread_mutex_init(&ctx->pollfd_modify_lock, NULL); 84 pthread_mutex_init(&ctx->events_lock, NULL); 85 pthread_mutex_init(&ctx->event_waiters_lock, NULL); 86 pthread_cond_init(&ctx->event_waiters_cond, NULL); 87 |
88 TAILQ_INIT(&ctx->flying_transfers); 89 TAILQ_INIT(&ctx->pollfds); |
90 91 ret = pipe(ctx->ctrl_pipe); 92 if (ret < 0) { 93 usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]); 94 close(ctx->ctrl_pipe[0]); 95 close(ctx->ctrl_pipe[1]); 96 free(ctx); 97 return (LIBUSB_ERROR_OTHER); --- 20 unchanged lines hidden (view full) --- 118 return (0); 119} 120 121void 122libusb_exit(libusb_context * ctx) 123{ 124 GET_CONTEXT(ctx); 125 |
126 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit enter"); |
127 usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]); 128 close(ctx->ctrl_pipe[0]); 129 close(ctx->ctrl_pipe[1]); 130 131 pthread_mutex_lock(&default_context_lock); 132 if (ctx == usbi_default_context) { 133 usbi_default_context = NULL; 134 } 135 pthread_mutex_unlock(&default_context_lock); 136 137 free(ctx); |
138 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit leave"); |
139} 140 141/* Device handling and initialisation. */ 142 143ssize_t 144libusb_get_device_list(libusb_context * ctx, libusb_device *** list) 145{ 146 struct libusb20_device *pdev; 147 struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; 148 struct libusb_device *dev; 149 struct libusb20_backend *usb_backend; 150 int i; 151 152 GET_CONTEXT(ctx); |
153 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list enter"); |
154 155 usb_backend = libusb20_be_alloc_default(); 156 if (usb_backend == NULL) 157 return (-1); 158 159 pdev = NULL; 160 i = 0; 161 while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) --- 11 unchanged lines hidden (view full) --- 173 i = 0; 174 while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 175 /* get device into libUSB v1.0 list */ 176 libusb20_be_dequeue_device(usb_backend, pdev); 177 178 ddesc = libusb20_dev_get_device_desc(pdev); 179 dev = malloc(sizeof(*dev)); 180 if (dev == NULL) { |
181 while (i != 0) { 182 libusb_unref_device((*list)[i - 1]); 183 i--; 184 } |
185 free(*list); 186 libusb20_be_free(usb_backend); 187 return (LIBUSB_ERROR_NO_MEM); 188 } 189 memset(dev, 0, sizeof(*dev)); 190 191 pthread_mutex_init(&dev->lock, NULL); 192 dev->ctx = ctx; 193 dev->bus_number = pdev->bus_number; 194 dev->device_address = pdev->device_address; 195 dev->num_configurations = ddesc->bNumConfigurations; 196 197 /* link together the two structures */ 198 dev->os_priv = pdev; 199 200 pthread_mutex_lock(&ctx->usb_devs_lock); |
201 TAILQ_INSERT_HEAD(&ctx->usb_devs, dev, list); |
202 pthread_mutex_unlock(&ctx->usb_devs_lock); 203 204 (*list)[i] = libusb_ref_device(dev); 205 i++; 206 } 207 (*list)[i] = NULL; 208 209 libusb20_be_free(usb_backend); |
210 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list leave"); |
211 return (i); 212} 213 214/* 215 * In this function we cant free all the device contained into list because 216 * open_with_pid_vid use some node of list after the free_device_list. 217 */ 218void 219libusb_free_device_list(libusb_device **list, int unref_devices) 220{ 221 int i; 222 libusb_context *ctx; 223 224 ctx = NULL; 225 GET_CONTEXT(ctx); |
226 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_device_list enter"); |
227 228 if (list == NULL) 229 return ; 230 231 if (unref_devices) { 232 for (i = 0; list[i] != NULL; i++) 233 libusb_unref_device(list[i]); 234 } 235 free(list); |
236 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_device_list leave"); |
237} 238 239uint8_t 240libusb_get_bus_number(libusb_device * dev) 241{ 242 libusb_context *ctx; 243 244 ctx = NULL; 245 GET_CONTEXT(ctx); |
246 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_bus_number enter"); |
247 248 if (dev == NULL) 249 return (LIBUSB_ERROR_NO_DEVICE); |
250 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_bus_number leave"); |
251 return (dev->bus_number); 252} 253 254uint8_t 255libusb_get_device_address(libusb_device * dev) 256{ 257 libusb_context *ctx; 258 259 ctx = NULL; 260 GET_CONTEXT(ctx); |
261 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_address enter"); |
262 263 if (dev == NULL) 264 return (LIBUSB_ERROR_NO_DEVICE); |
265 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_address leave"); |
266 return (dev->device_address); 267} 268 269int 270libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint) 271{ 272 struct libusb_config_descriptor *pdconf; 273 struct libusb_interface *pinf; 274 struct libusb_interface_descriptor *pdinf; 275 struct libusb_endpoint_descriptor *pdend; 276 libusb_context *ctx; 277 int i, j, k, ret; 278 279 ctx = NULL; 280 GET_CONTEXT(ctx); |
281 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size enter"); |
282 283 if (dev == NULL) 284 return (LIBUSB_ERROR_NO_DEVICE); 285 286 if (libusb_get_active_config_descriptor(dev, &pdconf) < 0) 287 return (LIBUSB_ERROR_OTHER); 288 289 ret = LIBUSB_ERROR_NOT_FOUND; --- 8 unchanged lines hidden (view full) --- 298 goto out; 299 } 300 } 301 } 302 } 303 304out: 305 libusb_free_config_descriptor(pdconf); |
306 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size leave"); |
307 return (ret); 308} 309 310libusb_device * 311libusb_ref_device(libusb_device * dev) 312{ 313 libusb_context *ctx; 314 315 ctx = NULL; 316 GET_CONTEXT(ctx); |
317 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_ref_device enter"); |
318 319 if (dev == NULL) 320 return (NULL); 321 322 pthread_mutex_lock(&dev->lock); 323 dev->refcnt++; 324 pthread_mutex_unlock(&dev->lock); 325 |
326 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_ref_device leave"); |
327 return (dev); 328} 329 330void 331libusb_unref_device(libusb_device * dev) 332{ 333 libusb_context *ctx; 334 335 ctx = NULL; 336 GET_CONTEXT(ctx); |
337 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unref_device enter"); |
338 339 if (dev == NULL) 340 return; 341 342 pthread_mutex_lock(&dev->lock); 343 dev->refcnt--; 344 pthread_mutex_unlock(&dev->lock); 345 346 if (dev->refcnt == 0) { 347 pthread_mutex_lock(&dev->ctx->usb_devs_lock); |
348 TAILQ_REMOVE(&ctx->usb_devs, dev, list); |
349 pthread_mutex_unlock(&dev->ctx->usb_devs_lock); 350 351 libusb20_dev_free(dev->os_priv); 352 free(dev); 353 } |
354 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unref_device leave"); |
355} 356 357int 358libusb_open(libusb_device * dev, libusb_device_handle **devh) 359{ 360 libusb_context *ctx = dev->ctx; 361 struct libusb20_device *pdev = dev->os_priv; 362 libusb_device_handle *hdl; 363 unsigned char dummy; 364 int err; 365 366 GET_CONTEXT(ctx); |
367 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open enter"); |
368 369 dummy = 1; 370 if (devh == NULL) 371 return (LIBUSB_ERROR_INVALID_PARAM); 372 373 hdl = malloc(sizeof(*hdl)); 374 if (hdl == NULL) 375 return (LIBUSB_ERROR_NO_MEM); 376 377 err = libusb20_dev_open(pdev, 16 * 4 /* number of endpoints */ ); 378 if (err) { 379 free(hdl); 380 return (LIBUSB_ERROR_NO_MEM); 381 } 382 memset(hdl, 0, sizeof(*hdl)); 383 pthread_mutex_init(&hdl->lock, NULL); 384 |
385 TAILQ_INIT(&hdl->ep_list); |
386 hdl->dev = libusb_ref_device(dev); 387 hdl->claimed_interfaces = 0; 388 hdl->os_priv = dev->os_priv; 389 err = usb_add_pollfd(ctx, libusb20_dev_get_fd(pdev), POLLIN | 390 POLLOUT | POLLRDNORM | POLLWRNORM); 391 if (err < 0) { 392 libusb_unref_device(dev); 393 free(hdl); 394 return (err); 395 } 396 397 pthread_mutex_lock(&ctx->open_devs_lock); |
398 TAILQ_INSERT_HEAD(&ctx->open_devs, hdl, list); |
399 pthread_mutex_unlock(&ctx->open_devs_lock); 400 401 *devh = hdl; 402 403 pthread_mutex_lock(&ctx->pollfd_modify_lock); 404 ctx->pollfd_modify++; 405 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 406 --- 7 unchanged lines hidden (view full) --- 414 415 libusb_lock_events(ctx); 416 read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); 417 pthread_mutex_lock(&ctx->pollfd_modify_lock); 418 ctx->pollfd_modify--; 419 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 420 libusb_unlock_events(ctx); 421 |
422 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open leave"); |
423 return (0); 424} 425 426libusb_device_handle * 427libusb_open_device_with_vid_pid(libusb_context * ctx, uint16_t vendor_id, 428 uint16_t product_id) 429{ 430 struct libusb_device **devs; 431 struct libusb_device_handle *devh; 432 struct libusb20_device *pdev; 433 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 434 int i, j; 435 436 GET_CONTEXT(ctx); |
437 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter"); |
438 439 devh = NULL; 440 441 if ((i = libusb_get_device_list(ctx, &devs)) < 0) 442 return (NULL); 443 444 for (j = 0; j < i; j++) { 445 pdev = (struct libusb20_device *)devs[j]->os_priv; 446 pdesc = libusb20_dev_get_device_desc(pdev); 447 if (pdesc->idVendor == vendor_id && |
448 pdesc->idProduct == product_id) { |
449 if (libusb_open(devs[j], &devh) < 0) 450 devh = NULL; |
451 break ; 452 } |
453 } 454 455 libusb_free_device_list(devs, 1); |
456 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave"); |
457 return (devh); 458} 459 460void 461libusb_close(libusb_device_handle * devh) 462{ 463 libusb_context *ctx; 464 struct libusb20_device *pdev; |
465 struct usb_ep_tr *eptr; |
466 unsigned char dummy = 1; 467 int err; 468 469 if (devh == NULL) 470 return ; 471 472 ctx = devh->dev->ctx; 473 pdev = devh->os_priv; 474 475 GET_CONTEXT(ctx); |
476 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close enter"); |
477 478 pthread_mutex_lock(&ctx->pollfd_modify_lock); 479 ctx->pollfd_modify++; 480 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 481 482 err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); 483 484 if (err <= 0) { 485 pthread_mutex_lock(&ctx->open_devs_lock); |
486 TAILQ_REMOVE(&ctx->open_devs, devh, list); |
487 pthread_mutex_unlock(&ctx->open_devs_lock); 488 489 usb_remove_pollfd(ctx, libusb20_dev_get_fd(pdev)); |
490 libusb20_dev_close(pdev); |
491 libusb_unref_device(devh->dev); 492 TAILQ_FOREACH(eptr, &devh->ep_list, list) { 493 TAILQ_REMOVE(&devh->ep_list, eptr, list); 494 libusb20_tr_close(((struct libusb20_transfer **) 495 eptr->os_priv)[0]); 496 if (eptr->flags) 497 libusb20_tr_close(((struct libusb20_transfer **) 498 eptr->os_priv)[1]); 499 free((struct libusb20_transfer **)eptr->os_priv); 500 } |
501 free(devh); 502 503 pthread_mutex_lock(&ctx->pollfd_modify_lock); 504 ctx->pollfd_modify--; 505 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 506 return ; 507 } 508 libusb_lock_events(ctx); 509 510 read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); 511 pthread_mutex_lock(&ctx->open_devs_lock); |
512 TAILQ_REMOVE(&ctx->open_devs, devh, list); |
513 pthread_mutex_unlock(&ctx->open_devs_lock); 514 515 usb_remove_pollfd(ctx, libusb20_dev_get_fd(pdev)); |
516 libusb20_dev_close(pdev); |
517 libusb_unref_device(devh->dev); 518 TAILQ_FOREACH(eptr, &devh->ep_list, list) { 519 TAILQ_REMOVE(&devh->ep_list, eptr, list); 520 libusb20_tr_close(((struct libusb20_transfer **) 521 eptr->os_priv)[0]); 522 if (eptr->flags) 523 libusb20_tr_close(((struct libusb20_transfer **) 524 eptr->os_priv)[1]); 525 free((struct libusb20_transfer **)eptr->os_priv); 526 } |
527 free(devh); 528 529 pthread_mutex_lock(&ctx->pollfd_modify_lock); 530 ctx->pollfd_modify--; 531 pthread_mutex_unlock(&ctx->pollfd_modify_lock); 532 533 libusb_unlock_events(ctx); |
534 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close leave"); |
535} 536 537libusb_device * 538libusb_get_device(libusb_device_handle * devh) 539{ 540 libusb_context *ctx; 541 542 ctx = NULL; 543 GET_CONTEXT(ctx); |
544 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device enter"); |
545 546 if (devh == NULL) 547 return (NULL); 548 |
549 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device leave"); |
550 return (devh->dev); 551} 552 553int 554libusb_get_configuration(libusb_device_handle * devh, int *config) 555{ 556 libusb_context *ctx; 557 558 ctx = NULL; 559 GET_CONTEXT(ctx); |
560 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration enter"); |
561 562 if (devh == NULL || config == NULL) 563 return (LIBUSB_ERROR_INVALID_PARAM); 564 565 *config = libusb20_dev_get_config_index((struct libusb20_device *) 566 devh->dev->os_priv); 567 |
568 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration leave"); |
569 return (0); 570} 571 |
572int 573libusb_set_configuration(libusb_device_handle * devh, int configuration) 574{ 575 struct libusb20_device *pdev; 576 libusb_context *ctx; 577 578 ctx = NULL; 579 GET_CONTEXT(ctx); |
580 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration enter"); |
581 582 if (devh == NULL) 583 return (LIBUSB_ERROR_INVALID_PARAM); 584 585 pdev = (struct libusb20_device *)devh->dev->os_priv; 586 |
587 libusb20_dev_set_config_index(pdev, configuration); 588 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration leave"); |
589 return (0); 590} 591 592int 593libusb_claim_interface(libusb_device_handle * dev, int interface_number) 594{ 595 libusb_context *ctx; 596 int ret = 0; 597 598 ctx = NULL; 599 GET_CONTEXT(ctx); |
600 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface enter"); |
601 602 if (dev == NULL) 603 return (LIBUSB_ERROR_INVALID_PARAM); 604 605 if (interface_number >= sizeof(dev->claimed_interfaces) * 8) 606 return (LIBUSB_ERROR_INVALID_PARAM); 607 608 pthread_mutex_lock(&(dev->lock)); 609 if (dev->claimed_interfaces & (1 << interface_number)) 610 ret = LIBUSB_ERROR_BUSY; 611 612 if (!ret) 613 dev->claimed_interfaces |= (1 << interface_number); 614 pthread_mutex_unlock(&(dev->lock)); 615 |
616 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface leave"); |
617 return (ret); 618} 619 620int 621libusb_release_interface(libusb_device_handle * dev, int interface_number) 622{ 623 libusb_context *ctx; 624 int ret; 625 626 ctx = NULL; 627 GET_CONTEXT(ctx); |
628 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_release_interface enter"); |
629 630 ret = 0; 631 if (dev == NULL) 632 return (LIBUSB_ERROR_INVALID_PARAM); 633 634 if (interface_number >= sizeof(dev->claimed_interfaces) * 8) 635 return (LIBUSB_ERROR_INVALID_PARAM); 636 637 pthread_mutex_lock(&(dev->lock)); 638 if (!(dev->claimed_interfaces & (1 << interface_number))) 639 ret = LIBUSB_ERROR_NOT_FOUND; 640 641 if (!ret) 642 dev->claimed_interfaces &= ~(1 << interface_number); 643 pthread_mutex_unlock(&(dev->lock)); 644 |
645 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_release_interface leave"); |
646 return (ret); 647} 648 649int 650libusb_set_interface_alt_setting(libusb_device_handle * dev, 651 int interface_number, int alternate_setting) 652{ 653 libusb_context *ctx; |
654 655 ctx = NULL; 656 GET_CONTEXT(ctx); |
657 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_interface_alt_setting enter"); |
658 659 if (dev == NULL) 660 return (LIBUSB_ERROR_INVALID_PARAM); 661 662 if (interface_number >= sizeof(dev->claimed_interfaces) *8) 663 return (LIBUSB_ERROR_INVALID_PARAM); 664 665 pthread_mutex_lock(&dev->lock); 666 if (!(dev->claimed_interfaces & (1 << interface_number))) { 667 pthread_mutex_unlock(&dev->lock); 668 return (LIBUSB_ERROR_NOT_FOUND); 669 } 670 pthread_mutex_unlock(&dev->lock); 671 672 if (libusb20_dev_set_alt_index(dev->os_priv, interface_number, 673 alternate_setting) != 0) 674 return (LIBUSB_ERROR_OTHER); 675 |
676 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_interface_alt_setting leave"); |
677 return (0); 678} 679 680int 681libusb_clear_halt(libusb_device_handle * devh, unsigned char endpoint) 682{ 683 struct libusb20_transfer *xfer; |
684 struct libusb20_device *pdev; |
685 libusb_context *ctx; 686 int ret; 687 688 ctx = NULL; 689 GET_CONTEXT(ctx); |
690 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_clear_halt enter"); 691 692 pdev = devh->os_priv; 693 xfer = libusb20_tr_get_pointer(pdev, 694 ((endpoint / 0x40) | (endpoint * 4)) % (16 * 4)); 695 if (xfer == NULL) 696 return (LIBUSB_ERROR_NO_MEM); |
697 |
698 pthread_mutex_lock(&libusb20_lock); 699 ret = libusb20_tr_open(xfer, 0, 0, endpoint); 700 if (ret != 0 && ret != LIBUSB20_ERROR_BUSY) { 701 pthread_mutex_unlock(&libusb20_lock); 702 return (LIBUSB_ERROR_OTHER); 703 } 704 705 libusb20_tr_clear_stall_sync(xfer); 706 if (ret == 0) /* check if we have open the device */ 707 libusb20_tr_close(xfer); 708 pthread_mutex_unlock(&libusb20_lock); 709 |
710 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_clear_halt leave"); |
711 return (0); 712} 713 714int 715libusb_reset_device(libusb_device_handle * dev) 716{ 717 libusb_context *ctx; 718 719 ctx = NULL; 720 GET_CONTEXT(ctx); |
721 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_reset_device enter"); |
722 723 if (dev == NULL) 724 return (LIBUSB20_ERROR_INVALID_PARAM); 725 726 libusb20_dev_reset(dev->os_priv); |
727 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_reset_device leave"); |
728 return (0); 729} 730 731int 732libusb_kernel_driver_active(libusb_device_handle * devh, int interface) 733{ 734 libusb_context *ctx; 735 736 ctx = NULL; 737 GET_CONTEXT(ctx); |
738 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_kernel_driver_active enter"); |
739 740 if (devh == NULL) 741 return (LIBUSB_ERROR_INVALID_PARAM); 742 |
743 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_kernel_driver_active leave"); |
744 return (libusb20_dev_kernel_driver_active(devh->os_priv, interface)); 745} 746 747int 748libusb_detach_kernel_driver(libusb_device_handle * devh, int interface) 749{ 750 struct libusb20_device *pdev; 751 libusb_context *ctx; 752 753 ctx = NULL; 754 GET_CONTEXT(ctx); |
755 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_detach_kernel_driver enter"); |
756 757 if (devh == NULL) 758 return (LIBUSB_ERROR_INVALID_PARAM); 759 760 pdev = (struct libusb20_device *)devh->dev->os_priv; 761 if (libusb20_dev_detach_kernel_driver(pdev, interface) == LIBUSB20_ERROR_OTHER) 762 return (LIBUSB_ERROR_OTHER); 763 |
764 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_detach_kernel_driver leave"); |
765 return (0); 766} 767 768/* 769 * stub function. 770 * libusb20 doesn't support this feature. 771 */ 772int 773libusb_attach_kernel_driver(libusb_device_handle * devh, int interface) 774{ 775 libusb_context *ctx; 776 777 ctx = NULL; 778 GET_CONTEXT(ctx); |
779 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_attach_kernel_driver enter"); |
780 781 if (devh == NULL) 782 return (LIBUSB_ERROR_INVALID_PARAM); 783 |
784 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_attach_kernel_driver leave"); |
785 return (0); 786} 787 788/* Asynchronous device I/O */ 789 790struct libusb_transfer * 791libusb_alloc_transfer(int iso_packets) 792{ 793 struct libusb_transfer *xfer; 794 struct usb_transfer *bxfer; 795 libusb_context *ctx; 796 int len; 797 798 ctx = NULL; 799 GET_CONTEXT(ctx); |
800 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_alloc_transfer enter"); |
801 802 len = sizeof(struct libusb_transfer) + 803 sizeof(struct usb_transfer) + 804 (iso_packets * sizeof(libusb_iso_packet_descriptor)); 805 806 bxfer = malloc(len); 807 if (bxfer == NULL) 808 return (NULL); 809 810 memset(bxfer, 0, len); 811 bxfer->num_iso_packets = iso_packets; 812 813 xfer = (struct libusb_transfer *) ((uint8_t *)bxfer + 814 sizeof(struct usb_transfer)); 815 |
816 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_alloc_transfer leave"); |
817 return (xfer); 818} 819 820void 821libusb_free_transfer(struct libusb_transfer *xfer) 822{ 823 struct usb_transfer *bxfer; 824 libusb_context *ctx; 825 826 ctx = NULL; 827 GET_CONTEXT(ctx); |
828 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_transfer enter"); |
829 830 if (xfer == NULL) 831 return ; 832 833 bxfer = (struct usb_transfer *) ((uint8_t *)xfer - 834 sizeof(struct usb_transfer)); 835 836 free(bxfer); |
837 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_transfer leave"); |
838 return; 839} 840 |
841static int 842libusb_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer) 843{ 844 int ret; 845 int usb_speed; 846 847 usb_speed = libusb20_dev_get_speed(pdev); 848 849 switch (xfer->type) { 850 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 851 switch (usb_speed) { 852 case LIBUSB20_SPEED_LOW: 853 case LIBUSB20_SPEED_FULL: 854 ret = 60 * 1; 855 break ; 856 default : 857 ret = 60 * 8; 858 break ; 859 } 860 break ; 861 case LIBUSB_TRANSFER_TYPE_CONTROL: 862 ret = 2; 863 break ; 864 default: 865 ret = 1; 866 break ; 867 } 868 869 return ret; 870} 871 872static int 873libusb_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) 874{ 875 int ret; 876 int usb_speed; 877 878 usb_speed = libusb20_dev_get_speed(pdev); 879 880 switch (xfer->type) { 881 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 882 ret = 0; 883 break ; 884 case LIBUSB_TRANSFER_TYPE_CONTROL: 885 switch (usb_speed) { 886 case LIBUSB20_SPEED_LOW: 887 ret = 8; 888 break ; 889 case LIBUSB20_SPEED_FULL: 890 ret = 64; 891 break ; 892 default: 893 ret = 64; 894 break ; 895 } 896 ret += 8; 897 break ; 898 default : 899 switch (usb_speed) { 900 case LIBUSB20_SPEED_LOW: 901 ret = 256; 902 break ; 903 case LIBUSB20_SPEED_FULL: 904 ret = 4096; 905 break ; 906 default: 907 ret = 16384; 908 break ; 909 } 910 break ; 911 } 912 913 return ret; 914} 915 |
916static void 917libusb10_proxy(struct libusb20_transfer *xfer) 918{ 919 struct usb_transfer *usb_backend; 920 struct libusb20_device *pdev; 921 libusb_transfer *usb_xfer; 922 libusb_context *ctx; |
923 uint32_t pos; 924 uint32_t max; 925 uint32_t size; |
926 uint8_t status; 927 uint32_t iso_packets; 928 int i; 929 930 status = libusb20_tr_get_status(xfer); 931 usb_xfer = libusb20_tr_get_priv_sc0(xfer); 932 usb_backend = (struct usb_transfer *) ((uint8_t *)usb_xfer - 933 sizeof(struct usb_transfer)); 934 pdev = usb_xfer->dev_handle->dev->os_priv; 935 ctx = usb_xfer->dev_handle->dev->ctx; 936 GET_CONTEXT(ctx); 937 938 switch (status) { 939 case LIBUSB20_TRANSFER_COMPLETED: |
940 usb_backend->transferred += libusb20_tr_get_actual_length(xfer); 941 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 TRANSFER %i bytes", 942 usb_backend->transferred); 943 if (usb_backend->transferred != usb_xfer->length) 944 goto tr_start; 945 946 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 TRANSFER COMPLETE"); 947 usb_handle_transfer_completion(usb_backend, LIBUSB_TRANSFER_COMPLETED); 948 |
949 break ; 950 case LIBUSB20_TRANSFER_START: |
951tr_start: 952 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 START"); 953 max = libusb_get_buffsize(pdev, usb_xfer); 954 pos = usb_backend->transferred; 955 size = (usb_xfer->length - pos); 956 size = (size > max) ? max : size; |
957 usb_xfer->actual_length = 0; 958 switch (usb_xfer->type) { 959 case LIBUSB_TRANSFER_TYPE_CONTROL: |
960 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE CTR"); |
961 libusb20_tr_setup_control(xfer, usb_xfer->buffer, |
962 (void *)(((uint8_t *) &usb_xfer->buffer[pos]) + |
963 sizeof(libusb_control_setup)), 964 usb_xfer->timeout); 965 break ; 966 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: |
967 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE ISO"); |
968 iso_packets = libusb20_tr_get_max_frames(xfer); 969 if (usb_xfer->num_iso_packets > iso_packets) 970 usb_xfer->num_iso_packets = iso_packets; 971 for (i = 0 ; i < usb_xfer->num_iso_packets ; i++) { 972 libusb20_tr_setup_isoc(xfer, |
973 &usb_xfer->buffer[pos], size, i); |
974 } 975 libusb20_tr_set_total_frames(xfer, i); 976 break ; 977 case LIBUSB_TRANSFER_TYPE_BULK: |
978 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE BULK"); 979 libusb20_tr_setup_bulk(xfer, &usb_xfer->buffer[pos], 980 size, usb_xfer->timeout); |
981 break ; 982 case LIBUSB_TRANSFER_TYPE_INTERRUPT: |
983 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE INTR"); 984 libusb20_tr_setup_intr(xfer, &usb_xfer->buffer[pos], 985 size, usb_xfer->timeout); |
986 break ; 987 } 988 libusb20_tr_submit(xfer); |
989 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 SUBMITED"); |
990 break ; 991 default: |
992 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "TRANSFER DEFAULT 0x%x\n", 993 status); 994 usb_backend->transferred = 0; 995 usb_handle_transfer_completion(usb_backend, LIBUSB_TRANSFER_CANCELLED); |
996 break ; 997 } 998 999 switch (status) { 1000 case LIBUSB20_TRANSFER_COMPLETED: |
1001 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS COMPLETED"); |
1002 usb_xfer->status = LIBUSB_TRANSFER_COMPLETED; 1003 break ; 1004 case LIBUSB20_TRANSFER_OVERFLOW: |
1005 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR OVERFLOW"); |
1006 usb_xfer->status = LIBUSB_TRANSFER_OVERFLOW; 1007 break ; 1008 case LIBUSB20_TRANSFER_NO_DEVICE: |
1009 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR NO DEVICE"); |
1010 usb_xfer->status = LIBUSB_TRANSFER_NO_DEVICE; 1011 break ; 1012 case LIBUSB20_TRANSFER_STALL: |
1013 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR STALL"); |
1014 usb_xfer->status = LIBUSB_TRANSFER_STALL; 1015 break ; 1016 case LIBUSB20_TRANSFER_CANCELLED: |
1017 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR CANCELLED"); |
1018 usb_xfer->status = LIBUSB_TRANSFER_CANCELLED; 1019 break ; 1020 case LIBUSB20_TRANSFER_TIMED_OUT: |
1021 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR TIMEOUT"); |
1022 usb_xfer->status = LIBUSB_TRANSFER_TIMED_OUT; 1023 break ; 1024 case LIBUSB20_TRANSFER_ERROR: |
1025 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "ERROR"); |
1026 usb_xfer->status = LIBUSB_TRANSFER_ERROR; 1027 break ; 1028 } 1029} 1030 |
1031int 1032libusb_submit_transfer(struct libusb_transfer *xfer) 1033{ 1034 struct libusb20_transfer **usb20_xfer; 1035 struct usb_transfer *usb_backend; 1036 struct usb_transfer *usb_node; 1037 struct libusb20_device *pdev; |
1038 struct usb_ep_tr *eptr; |
1039 struct timespec cur_ts; 1040 struct timeval *cur_tv; |
1041 libusb_device_handle *devh; 1042 libusb_context *ctx; |
1043 int maxframe; 1044 int buffsize; |
1045 int ep_idx; 1046 int ret; |
1047 1048 if (xfer == NULL) 1049 return (LIBUSB_ERROR_NO_MEM); 1050 1051 usb20_xfer = malloc(2 * sizeof(struct libusb20_transfer *)); 1052 if (usb20_xfer == NULL) 1053 return (LIBUSB_ERROR_NO_MEM); 1054 1055 ctx = xfer->dev_handle->dev->ctx; 1056 pdev = xfer->dev_handle->os_priv; |
1057 devh = xfer->dev_handle; |
1058 |
1059 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); |
1060 1061 usb_backend = (struct usb_transfer *) ((uint8_t *)xfer - 1062 sizeof(struct usb_transfer)); 1063 usb_backend->transferred = 0; 1064 usb_backend->flags = 0; 1065 1066 if (xfer->timeout != 0) { 1067 clock_gettime(CLOCK_MONOTONIC, &cur_ts); 1068 cur_ts.tv_sec += xfer->timeout / 1000; 1069 cur_ts.tv_nsec += (xfer->timeout % 1000) * 1000000; 1070 1071 if (cur_ts.tv_nsec > 1000000000) { 1072 cur_ts.tv_nsec -= 1000000000; 1073 cur_ts.tv_sec++; 1074 } 1075 1076 TIMESPEC_TO_TIMEVAL(&usb_backend->timeout, &cur_ts); |
1077 } |
1078 1079 /*Add to flying list*/ 1080 pthread_mutex_lock(&ctx->flying_transfers_lock); |
1081 if (TAILQ_EMPTY(&ctx->flying_transfers)) { 1082 TAILQ_INSERT_HEAD(&ctx->flying_transfers, usb_backend, list); |
1083 goto out; 1084 } 1085 if (timerisset(&usb_backend->timeout) == 0) { |
1086 TAILQ_INSERT_HEAD(&ctx->flying_transfers, usb_backend, list); |
1087 goto out; 1088 } |
1089 TAILQ_FOREACH(usb_node, &ctx->flying_transfers, list) { |
1090 cur_tv = &usb_node->timeout; 1091 if (timerisset(cur_tv) == 0 || 1092 (cur_tv->tv_sec > usb_backend->timeout.tv_sec) || 1093 (cur_tv->tv_sec == usb_backend->timeout.tv_sec && 1094 cur_tv->tv_usec > usb_backend->timeout.tv_usec)) { |
1095 TAILQ_INSERT_TAIL(&ctx->flying_transfers, usb_backend, list); |
1096 goto out; 1097 } 1098 } |
1099 TAILQ_INSERT_TAIL(&ctx->flying_transfers, usb_backend, list); |
1100 1101out: 1102 pthread_mutex_unlock(&ctx->flying_transfers_lock); 1103 |
1104 ep_idx = (xfer->endpoint / 0x40) | (xfer->endpoint * 4) % (16 * 4); 1105 usb20_xfer[0] = libusb20_tr_get_pointer(pdev, ep_idx); 1106 usb20_xfer[1] = libusb20_tr_get_pointer(pdev, ep_idx + 1); |
1107 1108 if (usb20_xfer[0] == NULL) 1109 return (LIBUSB_ERROR_OTHER); 1110 1111 xfer->os_priv = usb20_xfer; 1112 1113 pthread_mutex_lock(&libusb20_lock); 1114 1115 buffsize = libusb_get_buffsize(pdev, xfer); 1116 maxframe = libusb_get_maxframe(pdev, xfer); 1117 |
1118 ret = 0; 1119 TAILQ_FOREACH(eptr, &devh->ep_list, list) { 1120 if (xfer->endpoint == eptr->addr) 1121 ret++; 1122 } 1123 if (ret == 0) { 1124 eptr = malloc(sizeof(struct usb_ep_tr)); 1125 eptr->addr = xfer->endpoint; 1126 eptr->idx = ep_idx; 1127 eptr->os_priv = usb20_xfer; 1128 eptr->flags = (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)?1:0; 1129 TAILQ_INSERT_HEAD(&devh->ep_list, eptr, list); 1130 ret = libusb20_tr_open(usb20_xfer[0], buffsize, 1131 maxframe, xfer->endpoint); 1132 if (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) 1133 ret |= libusb20_tr_open(usb20_xfer[1], buffsize, 1134 maxframe, xfer->endpoint); |
1135 |
1136 if (ret != 0) { 1137 pthread_mutex_unlock(&libusb20_lock); 1138 pthread_mutex_lock(&ctx->flying_transfers_lock); 1139 TAILQ_REMOVE(&ctx->flying_transfers, usb_backend, list); 1140 pthread_mutex_unlock(&ctx->flying_transfers_lock); 1141 return (LIBUSB_ERROR_OTHER); 1142 } |
1143 } 1144 1145 libusb20_tr_set_priv_sc0(usb20_xfer[0], xfer); 1146 libusb20_tr_set_callback(usb20_xfer[0], libusb10_proxy); 1147 if (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { 1148 libusb20_tr_set_priv_sc0(usb20_xfer[1], xfer); 1149 libusb20_tr_set_callback(usb20_xfer[1], libusb10_proxy); 1150 } 1151 |
1152 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20_TR_START"); |
1153 libusb20_tr_start(usb20_xfer[0]); 1154 if (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) 1155 libusb20_tr_start(usb20_xfer[1]); 1156 1157 pthread_mutex_unlock(&libusb20_lock); 1158 |
1159 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave"); |
1160 return (0); 1161} 1162 1163int 1164libusb_cancel_transfer(struct libusb_transfer *xfer) 1165{ 1166 libusb_context *ctx; 1167 1168 ctx = NULL; 1169 GET_CONTEXT(ctx); |
1170 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); |
1171 1172 if (xfer == NULL) 1173 return (LIBUSB_ERROR_NO_MEM); 1174 1175 pthread_mutex_lock(&libusb20_lock); 1176 libusb20_tr_stop(xfer->os_priv); 1177 pthread_mutex_unlock(&libusb20_lock); 1178 |
1179 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); |
1180 return (0); 1181} 1182 |