- Timestamp:
- Jul 30, 2010 1:37:49 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 64261
- Location:
- trunk/src/VBox/RDP/client/vrdp
- Files:
-
- 1 added
- 4 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/RDP/client/vrdp/USBProxyDevice-linux.c
r28800 r31247 1 /* $Id$ */ 1 2 /** @file 2 * 3 * VUSB Device - USB Device Proxy, the Linux backend. 3 * USB device proxy - the Linux backend. 4 4 */ 5 5 … … 7 7 * Copyright (C) 2006-2007 Oracle Corporation 8 8 * 9 * This file is part of VirtualBox Open Source Edition (OSE), as 10 * available from http://www.virtualbox.org. This file is free software; 11 * you can redistribute it and/or modify it under the terms of the GNU 12 * General Public License (GPL) as published by the Free Software 13 * Foundation, in version 2 as it comes in the "COPYING" file of the 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 9 * Oracle Corporation confidential 10 * All rights reserved 16 11 */ 17 12 … … 31 26 *******************************************************************************/ 32 27 #define LOG_GROUP LOG_GROUP_DRV_USBPROXY 33 #if defined(VBOX) && !defined(RDESKTOP)28 #ifndef RDESKTOP 34 29 # include <iprt/stdint.h> 35 30 #endif … … 47 42 #include <fcntl.h> 48 43 #include <errno.h> 49 #include <ctype.h>50 44 #ifdef VBOX_WITH_LINUX_COMPILER_H 51 45 # include <linux/compiler.h> … … 71 65 #endif 72 66 73 #if defined(VBOX) && !defined(RDESKTOP)67 #ifndef RDESKTOP 74 68 # include <VBox/pdm.h> 75 69 # include <VBox/err.h> 76 70 # include <VBox/log.h> 71 # include <iprt/alloc.h> 77 72 # include <iprt/assert.h> 73 # include <iprt/asm.h> 74 # include <iprt/ctype.h> 75 # include <iprt/file.h> 76 # include <iprt/linux/sysfs.h> 78 77 # include <iprt/stream.h> 79 # include <iprt/ alloc.h>78 # include <iprt/string.h> 80 79 # include <iprt/thread.h> 81 80 # include <iprt/time.h> 82 # include <iprt/asm.h>83 # include <iprt/string.h>84 # include <iprt/file.h>85 81 # include "../USBProxyDevice.h" 86 82 #else 87 83 88 84 # include "../rdesktop.h" 89 # include "vrdpusb.h" 85 # include "runtime.h" 86 # include "USBProxyDevice.h" 87 # ifdef VBOX_USB_WITH_SYSFS 88 # include "sysfs.h" 89 # endif 90 90 #endif 91 91 … … 102 102 /** The kernel URB data */ 103 103 struct usbdevfs_urb KUrb; 104 /** Space filler for the isochronous packets. */ 105 struct usbdevfs_iso_packet_desc aIsocPktsDonUseTheseUseTheOnesInKUrb[8]; 104 106 /** The millisecond timestamp when this URB was submitted. */ 105 107 uint64_t u64SubmitTS; … … 120 122 /** This split element is reaped. */ 121 123 bool fSplitElementReaped; 124 /** Size to transfer in remaining fragments of a split URB */ 125 uint32_t cbSplitRemaining; 122 126 } USBPROXYURBLNX, *PUSBPROXYURBLNX; 123 127 … … 142 146 /** The tail of the landed linux URBs. */ 143 147 PUSBPROXYURBLNX pTaxingTail; 148 /** Are we using sysfs to find the active configuration? */ 149 bool fUsingSysfs; 150 /** The device node/sysfs path of the device. 151 * Used to figure out the configuration after a reset. */ 152 char szPath[1]; 144 153 } USBPROXYDEVLNX, *PUSBPROXYDEVLNX; 145 154 … … 148 157 * Internal Functions * 149 158 *******************************************************************************/ 150 static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, intiCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries);159 static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries); 151 160 static void usbProxLinuxUrbUnplugged(PUSBPROXYDEV pProxyDev); 152 161 static void usbProxyLinuxSetConnected(PUSBPROXYDEV pProyxDev, int iIf, bool fConnect, bool fQuiet); … … 154 163 static void usbProxyLinuxUrbFree(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx); 155 164 static void usbProxyLinuxUrbFreeSplitList(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx); 156 static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *psz Address, int *iFirstCfg);165 static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg); 157 166 158 167 … … 172 181 * @internal 173 182 */ 174 static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, intiCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries)183 static int usbProxyLinuxDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries) 175 184 { 176 185 int rc; … … 188 197 { 189 198 usbProxLinuxUrbUnplugged(pProxyDev); 190 Log(("usb-linux: ENODEV -> unplugged. pProxyDev=% p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));199 Log(("usb-linux: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev))); 191 200 errno = ENODEV; 192 201 break; … … 212 221 */ 213 222 RTCritSectEnter(&pDevLnx->CritSect); 223 pProxyDev->fDetached = true; 214 224 215 225 PUSBPROXYURBLNX pUrbTaxing = NULL; … … 250 260 251 261 RTCritSectLeave(&pDevLnx->CritSect); 252 253 vusbDevUnplugged(&pProxyDev->Dev);254 262 } 255 263 … … 261 269 static void usbProxyLinuxSetConnected(PUSBPROXYDEV pProxyDev, int iIf, bool fConnect, bool fQuiet) 262 270 { 263 struct usbdevfs_ioctl IoCtl; 264 if (!fQuiet) 265 LogFlow(("usbProxyLinuxSetConnected: pProxyDev=%p[%s] iIf=%#x fConnect=%d\n", 266 pProxyDev, pProxyDev->Dev.pszName, iIf, fConnect)); 267 268 IoCtl.ifno = iIf; 269 IoCtl.ioctl_code = fConnect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT; 270 IoCtl.data = NULL; 271 if ( usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_IOCTL, &IoCtl, true, UINT32_MAX) 272 && !fQuiet) 273 Log(("usbProxyLinuxSetConnected: failure, errno=%d. pProxyDev=%p[%s]\n", 274 errno, pProxyDev, pProxyDev->Dev.pszName)); 271 if ( iIf >= 32 272 || !(pProxyDev->fMaskedIfs & RT_BIT(iIf))) 273 { 274 struct usbdevfs_ioctl IoCtl; 275 if (!fQuiet) 276 LogFlow(("usbProxyLinuxSetConnected: pProxyDev=%s iIf=%#x fConnect=%RTbool\n", 277 usbProxyGetName(pProxyDev), iIf, fConnect)); 278 279 IoCtl.ifno = iIf; 280 IoCtl.ioctl_code = fConnect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT; 281 IoCtl.data = NULL; 282 if ( usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_IOCTL, &IoCtl, true, UINT32_MAX) 283 && !fQuiet) 284 Log(("usbProxyLinuxSetConnected: failure, errno=%d. pProxyDev=%s\n", 285 errno, usbProxyGetName(pProxyDev))); 286 } 275 287 } 276 288 … … 400 412 * @returns The Cfg#. 401 413 * @returns -1 if no active config. 402 * @param pszAddress The path to the device. We infere the location of the 403 * devices file, which bus and device number we're looking for. 414 * @param pszDevNode The path to the device. We infere the location of 415 * the devices file, which bus and device number we're 416 * looking for. 404 417 * @param iFirstCfg The first configuration. (optional) 405 418 * @internal 406 419 */ 407 static int usbProxyLinuxFindActiveConfig (PUSBPROXYDEV pProxyDev, const char *pszAddress, int *piFirstCfg)420 static int usbProxyLinuxFindActiveConfigUsbfs(PUSBPROXYDEV pProxyDev, const char *pszDevNode, int *piFirstCfg) 408 421 { 409 422 /* … … 415 428 416 429 /* 417 * Interpret the address and turn it into a path to the devices file. 418 */ 419 size_t cchAddress = strlen(pszAddress); 420 char *pszDevices = (char *)RTMemDupEx(pszAddress, cchAddress, sizeof("devices")); 430 * Parse the usbfs device node path and turn it into a path to the "devices" file, 431 * picking up the device number and bus along the way. 432 */ 433 size_t cchDevNode = strlen(pszDevNode); 434 char *pszDevices = (char *)RTMemDupEx(pszDevNode, cchDevNode, sizeof("devices")); 421 435 AssertReturn(pszDevices, iActiveCfg); 422 436 423 437 /* the device number */ 424 char *psz = pszDevices + cch Address;438 char *psz = pszDevices + cchDevNode; 425 439 while (*psz != '/') 426 440 psz--; … … 525 539 } 526 540 527 int dev2fd (PUSBPROXYDEV pProxyDev) 528 { 529 if (pProxyDev) 530 { 531 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 532 533 if (pDevLnx) 534 { 535 return pDevLnx->File; 536 } 537 } 541 542 /** 543 * This finds the active configuration from sysfs. 544 * 545 * @returns The Cfg#. 546 * @returns -1 if no active config. 547 * @param pszPath The sysfs path for the device. 548 * @param piFirstCfg The first configuration. (optional) 549 * @internal 550 */ 551 static int usbProxyLinuxFindActiveConfigSysfs(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg) 552 { 553 #ifdef VBOX_USB_WITH_SYSFS 554 if (piFirstCfg != NULL) 555 *piFirstCfg = pProxyDev->paCfgDescs != NULL 556 ? pProxyDev->paCfgDescs[0].Core.bConfigurationValue 557 : 1; 558 return RTLinuxSysFsReadIntFile(10, "%s/bConfigurationValue", pszPath); /* returns -1 on failure */ 559 #else /* !VBOX_USB_WITH_SYSFS */ 538 560 return -1; 539 } 540 541 /** 542 * Opens the /proc/bus/usb/bus/addr file. 561 #endif /* !VBOX_USB_WITH_SYSFS */ 562 } 563 564 565 /** 566 * This finds the active configuration. 567 * 568 * @returns The Cfg#. 569 * @returns -1 if no active config. 570 * @param pszPath The sysfs path for the device, or the usbfs device 571 * node path. 572 * @param iFirstCfg The first configuration. (optional) 573 * @internal 574 */ 575 static int usbProxyLinuxFindActiveConfig(PUSBPROXYDEV pProxyDev, const char *pszPath, int *piFirstCfg) 576 { 577 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 578 if (pDevLnx->fUsingSysfs) 579 return usbProxyLinuxFindActiveConfigSysfs(pProxyDev, pszPath, piFirstCfg); 580 return usbProxyLinuxFindActiveConfigUsbfs(pProxyDev, pszPath, piFirstCfg); 581 } 582 583 584 /** 585 * Extracts the Linux file descriptor associated with the kernel USB device. 586 * This is used by rdesktop-vrdp for polling for events. 587 * @returns the FD, or asserts and returns -1 on error 588 * @param pProxyDev The device instance 589 */ 590 RTDECL(int) USBProxyDeviceLinuxGetFD(PUSBPROXYDEV pProxyDev) 591 { 592 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 593 AssertReturn(pDevLnx->File != NIL_RTFILE, -1); 594 return pDevLnx->File; 595 } 596 597 598 /** 599 * Opens the device file. 543 600 * 544 601 * @returns VBox status code. 545 602 * @param pProxyDev The device instance. 546 * @param pszAddress The path to the device. 603 * @param pszAddress If we are using usbfs, this is the path to the 604 * device. If we are using sysfs, this is a string of 605 * the form "sysfs:<sysfs path>//device:<device node>". 606 * In the second case, the two paths are guaranteed 607 * not to contain the substring "//". 547 608 * @param pvBackend Backend specific pointer, unused for the linux backend. 548 609 */ … … 550 611 { 551 612 LogFlow(("usbProxyLinuxOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress)); 613 const char *pszDevNode; 614 const char *pszPath; 615 size_t cchPath; 616 bool fUsingSysfs; 617 618 /* 619 * Are we using sysfs or usbfs? 620 */ 621 #ifdef VBOX_USB_WITH_SYSFS 622 fUsingSysfs = strncmp(pszAddress, "sysfs:", sizeof("sysfs:") - 1) == 0; 623 if (fUsingSysfs) 624 { 625 pszDevNode = strstr(pszAddress, "//device:"); 626 if (!pszDevNode) 627 { 628 LogRel(("usbProxyLinuxOpen: Invalid device address: '%s'\n", pszAddress)); 629 pProxyDev->Backend.pv = NULL; 630 return VERR_INVALID_PARAMETER; 631 } 632 633 pszPath = pszAddress + sizeof("sysfs:") - 1; 634 cchPath = pszDevNode - pszPath; 635 pszDevNode += sizeof("//device:") - 1; 636 } 637 else 638 #endif /* VBOX_USB_WITH_SYSFS */ 639 { 640 #ifndef VBOX_USB_WITH_SYSFS 641 fUsingSysfs = false; 642 #endif 643 pszPath = pszDevNode = pszAddress; 644 cchPath = strlen(pszPath); 645 } 646 647 /* 648 * Try open the device node. 649 */ 552 650 RTFILE File; 553 int rc = RTFileOpen(&File, psz Address, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);651 int rc = RTFileOpen(&File, pszDevNode, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 554 652 if (RT_SUCCESS(rc)) 555 653 { … … 557 655 * Allocate and initialize the linux backend data. 558 656 */ 559 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)RTMemAllocZ (sizeof(*pDevLnx));657 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)RTMemAllocZVar(sizeof(*pDevLnx) + cchPath); 560 658 if (pDevLnx) 561 659 { 660 pDevLnx->fUsingSysfs = fUsingSysfs; 661 memcpy(&pDevLnx->szPath[0], pszPath, cchPath); 662 pDevLnx->szPath[cchPath] = '\0'; 562 663 pDevLnx->File = File; 563 664 rc = RTCritSectInit(&pDevLnx->CritSect); … … 566 667 pProxyDev->Backend.pv = pDevLnx; 567 668 568 /* brute force rulez */569 unsigned iIf;570 for (iIf = 0; iIf < 256; iIf++)571 usbProxyLinuxSetConnected(pProxyDev, iIf, false, true);572 573 /*574 * Determin the active configuration.575 *576 * If there isn't any active configuration, we will get EHOSTUNREACH (113) errors577 * when trying to read the device descriptors in usbProxyDevCreate. So, we'll make578 * the first one active (usually 1) then.579 */580 pProxyDev->cIgnoreSetConfigs = 1;581 int iFirstCfg;582 pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pszAddress, &iFirstCfg);583 if (pProxyDev->iActiveCfg == -1)584 {585 usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iFirstCfg, false, UINT32_MAX);586 pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pszAddress, NULL);587 Log(("usbProxyLinuxOpen: No active config! Tried to set %d: iActiveCfg=%d\n", iFirstCfg, pProxyDev->iActiveCfg));588 }589 590 669 LogFlow(("usbProxyLinuxOpen(%p, %s): returns successfully File=%d iActiveCfg=%d\n", 591 670 pProxyDev, pszAddress, pDevLnx->File, pProxyDev->iActiveCfg)); … … 603 682 rc = VERR_VUSB_USBFS_PERMISSION; 604 683 605 Log(("usbProxyLinuxOpen(%p, %s) failed, rc=% d!\n", pProxyDev, pszAddress, rc));684 Log(("usbProxyLinuxOpen(%p, %s) failed, rc=%Rrc!\n", pProxyDev, pszAddress, rc)); 606 685 pProxyDev->Backend.pv = NULL; 607 686 … … 612 691 613 692 /** 693 * Claims all the interfaces and figures out the 694 * current configuration. 695 * 696 * @returns VINF_SUCCESS. 697 * @param pProxyDev The proxy device. 698 */ 699 static int usbProxyLinuxInit(PUSBPROXYDEV pProxyDev) 700 { 701 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 702 703 /* 704 * Brute force rulez. 705 * usbProxyLinuxSetConnected check for masked interfaces. 706 */ 707 unsigned iIf; 708 for (iIf = 0; iIf < 256; iIf++) 709 usbProxyLinuxSetConnected(pProxyDev, iIf, false, true); 710 711 /* 712 * Determin the active configuration. 713 * 714 * If there isn't any active configuration, we will get EHOSTUNREACH (113) errors 715 * when trying to read the device descriptors in usbProxyDevCreate. So, we'll make 716 * the first one active (usually 1) then. 717 */ 718 pProxyDev->cIgnoreSetConfigs = 1; 719 int iFirstCfg; 720 pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, &iFirstCfg); 721 if (pProxyDev->iActiveCfg == -1) 722 { 723 usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iFirstCfg, false, UINT32_MAX); 724 pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, NULL); 725 Log(("usbProxyLinuxInit: No active config! Tried to set %d: iActiveCfg=%d\n", iFirstCfg, pProxyDev->iActiveCfg)); 726 } 727 else 728 Log(("usbProxyLinuxInit(%p): iActiveCfg=%d\n", pProxyDev, pProxyDev->iActiveCfg)); 729 return VINF_SUCCESS; 730 } 731 732 733 /** 614 734 * Closes the proxy device. 615 735 */ 616 736 static void usbProxyLinuxClose(PUSBPROXYDEV pProxyDev) 617 737 { 618 LogFlow(("usbProxyLinuxClose: pProxyDev=% p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));738 LogFlow(("usbProxyLinuxClose: pProxyDev=%s\n", usbProxyGetName(pProxyDev))); 619 739 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 620 740 Assert(pDevLnx); … … 626 746 * Resetting it would be a nice start, although we must remember 627 747 * that it might have been disconnected... 628 */ 629 /* ASSUMES: thread == EMT */ 630 if (!usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10)) 631 { 632 /* Connect drivers. */ 633 unsigned iIf; 634 for (iIf = 0; iIf < 256; iIf++) 635 usbProxyLinuxSetConnected(pProxyDev, iIf, true, true); 636 } 637 else 638 Log(("usbProxyLinuxClose: Reset failed, errno=%d.\n", errno)); 639 640 /* 641 * Now we can close it and free all the resources. 642 */ 643 RTFileClose(pDevLnx->File); 644 pDevLnx->File = NIL_RTFILE; 645 748 * 749 * Don't reset if we're masking interfaces or if construction failed. 750 */ 751 if (pProxyDev->fInited) 752 { 753 /* ASSUMES: thread == EMT */ 754 if ( pProxyDev->fMaskedIfs 755 || !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10)) 756 { 757 /* Connect drivers. */ 758 unsigned iIf; 759 for (iIf = 0; iIf < 256; iIf++) 760 usbProxyLinuxSetConnected(pProxyDev, iIf, true, true); 761 LogRel(("USB: Successfully reset device pProxyDev=%s\n", usbProxyGetName(pProxyDev))); 762 } 763 else if (errno != ENODEV) 764 LogRel(("USB: Reset failed, errno=%d, pProxyDev=%s.\n", errno, usbProxyGetName(pProxyDev))); 765 else 766 Log(("USB: Reset failed, errno=%d (ENODEV), pProxyDev=%s.\n", errno, usbProxyGetName(pProxyDev))); 767 } 768 769 /* 770 * Now we can free all the resources and close the device. 771 */ 646 772 RTCritSectDelete(&pDevLnx->CritSect); 647 773 … … 679 805 RTMemFree(pUrbLnx); 680 806 } 807 808 RTFileClose(pDevLnx->File); 809 pDevLnx->File = NIL_RTFILE; 681 810 682 811 RTMemFree(pDevLnx); … … 808 937 /* Skip past "S:" and then the whitespace */ 809 938 for(psz = buf + 2; *psz != '\0'; psz++) 810 if ( ! isspace(*psz) )939 if ( !RT_C_IS_SPACE(*psz) ) 811 940 break; 812 941 … … 878 1007 * @param pDev The device to reset. 879 1008 */ 880 static int usbProxyLinuxReset(PUSBPROXYDEV pProxyDev )1009 static int usbProxyLinuxReset(PUSBPROXYDEV pProxyDev, bool fResetOnLinux) 881 1010 { 882 1011 #ifdef NO_PORT_RESET 883 LogFlow(("usbProxyLinuxReset: pProxyDev=%p[%s] - NO_PORT_RESET\n", pProxyDev, pProxyDev->Dev.pszName)); 1012 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 1013 1014 /* 1015 * Specific device resets are NOPs. 1016 * Root hub resets that affects all devices are executed. 1017 * 1018 * The reasoning is that when a root hub reset is done, the guest shouldn't 1019 * will have to re enumerate the devices after doing this kind of reset. 1020 * So, it doesn't really matter if a device is 'logically disconnected'. 1021 */ 1022 if ( !fResetOnLinux 1023 || pProxyDev->fMaskedIfs) 1024 LogFlow(("usbProxyLinuxReset: pProxyDev=%s - NO_PORT_RESET\n", usbProxyGetName(pProxyDev))); 1025 else 1026 { 1027 LogFlow(("usbProxyLinuxReset: pProxyDev=%s - Real Reset!\n", usbProxyGetName(pProxyDev))); 1028 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RESET, NULL, false, 10)) 1029 { 1030 int rc = errno; 1031 Log(("usb-linux: Reset failed, rc=%Rrc errno=%d.\n", RTErrConvertFromErrno(rc), rc)); 1032 pProxyDev->iActiveCfg = -1; 1033 return RTErrConvertFromErrno(rc); 1034 } 1035 1036 /* find the active config - damn annoying. */ 1037 pProxyDev->iActiveCfg = usbProxyLinuxFindActiveConfig(pProxyDev, pDevLnx->szPath, NULL); 1038 LogFlow(("usbProxyLinuxReset: returns successfully iActiveCfg=%d\n", pProxyDev->iActiveCfg)); 1039 } 884 1040 pProxyDev->cIgnoreSetConfigs = 2; 885 1041 886 1042 #else /* !NO_PORT_RESET */ 887 LogFlow(("usbProxyLinuxReset: pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName)); 1043 1044 /* 1045 * This is the alternative, we will allways reset when asked to do so. 1046 * 1047 * The problem we're facing here is that on reset failure linux will do 1048 * a 'logical reconnect' on the device. This will invalidate the current 1049 * handle and we'll have to reopen the device. This is problematic to say 1050 * the least, especially since it happens pretty often. 1051 */ 1052 LogFlow(("usbProxyLinuxReset: pProxyDev=%s\n", usbProxyGetName(pProxyDev))); 888 1053 # ifndef NO_LOGICAL_RECONNECT 889 1054 ASMAtomicIncU32(&g_cResetActive); … … 941 1106 static int usbProxyLinuxSetConfig(PUSBPROXYDEV pProxyDev, int iCfg) 942 1107 { 943 LogFlow(("usbProxyLinuxSetConfig: pProxyDev=% p[%s]cfg=%#x\n",944 pProxyDev, pProxyDev->Dev.pszName, iCfg));1108 LogFlow(("usbProxyLinuxSetConfig: pProxyDev=%s cfg=%#x\n", 1109 usbProxyGetName(pProxyDev), iCfg)); 945 1110 946 1111 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETCONFIGURATION, &iCfg, true, UINT32_MAX)) … … 959 1124 static int usbProxyLinuxClaimInterface(PUSBPROXYDEV pProxyDev, int iIf) 960 1125 { 961 LogFlow(("usbProxyLinuxClaimInterface: pProxyDev=% p[%s] ifnum=%#x\n", pProxyDev, pProxyDev->Dev.pszName, iIf));1126 LogFlow(("usbProxyLinuxClaimInterface: pProxyDev=%s ifnum=%#x\n", usbProxyGetName(pProxyDev), iIf)); 962 1127 usbProxyLinuxSetConnected(pProxyDev, iIf, false, false); 963 1128 964 1129 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_CLAIMINTERFACE, &iIf, true, UINT32_MAX)) 965 1130 { 966 Log(("usb-linux: Claim interface. errno=%d pProxyDev=% p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));1131 Log(("usb-linux: Claim interface. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 967 1132 return false; 968 1133 } … … 977 1142 static int usbProxyLinuxReleaseInterface(PUSBPROXYDEV pProxyDev, int iIf) 978 1143 { 979 LogFlow(("usbProxyLinuxReleaseInterface: pProxyDev=% p[%s] ifnum=%#x\n", pProxyDev, pProxyDev->Dev.pszName, iIf));1144 LogFlow(("usbProxyLinuxReleaseInterface: pProxyDev=%s ifnum=%#x\n", usbProxyGetName(pProxyDev), iIf)); 980 1145 981 1146 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_RELEASEINTERFACE, &iIf, true, UINT32_MAX)) 982 1147 { 983 Log(("usb-linux: Release interface, errno=%d. pProxyDev=% p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));1148 Log(("usb-linux: Release interface, errno=%d. pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 984 1149 return false; 985 1150 } … … 1002 1167 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_SETINTERFACE, &SetIf, true, UINT32_MAX)) 1003 1168 { 1004 Log(("usb-linux: Set interface, errno=%d. pProxyDev=% p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));1169 Log(("usb-linux: Set interface, errno=%d. pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1005 1170 return false; 1006 1171 } … … 1014 1179 static bool usbProxyLinuxClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int EndPt) 1015 1180 { 1016 LogFlow(("usbProxyLinuxClearHaltedEp: pProxyDev=% p[%s] EndPt=%u\n", pProxyDev, pProxyDev->Dev.pszName, EndPt));1181 LogFlow(("usbProxyLinuxClearHaltedEp: pProxyDev=%s EndPt=%u\n", usbProxyGetName(pProxyDev), EndPt)); 1017 1182 1018 1183 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_CLEAR_HALT, &EndPt, true, UINT32_MAX)) … … 1025 1190 if (errno == ENOENT) 1026 1191 { 1027 Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=% p[%s]ep=%d - IGNORED\n",1028 errno, pProxyDev, pProxyDev->Dev.pszName, EndPt));1192 Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%s ep=%d - IGNORED\n", 1193 errno, usbProxyGetName(pProxyDev), EndPt)); 1029 1194 return true; 1030 1195 } 1031 Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=% p[%s]ep=%d\n",1032 errno, pProxyDev, pProxyDev->Dev.pszName, EndPt));1196 Log(("usb-linux: clear_halted_ep failed errno=%d. pProxyDev=%s ep=%d\n", 1197 errno, usbProxyGetName(pProxyDev), EndPt)); 1033 1198 return false; 1034 1199 } … … 1042 1207 static void usbProxyLinuxUrbSwapSetup(PVUSBSETUP pSetup) 1043 1208 { 1044 pSetup->wValue = RT_LE2H_U16(pSetup->wValue); 1045 pSetup->wIndex = RT_LE2H_U16(pSetup->wIndex); 1046 pSetup->wLength = RT_LE2H_U16(pSetup->wLength); 1047 } 1048 1049 1050 /** The split size. */ 1051 #define SPLIT_SIZE 0x2000 1052 1053 /** 1054 * Try split up a VUSB URB into smaller URBs which the 1055 * linux kernel can deal with. 1209 pSetup->wValue = RT_H2LE_U16(pSetup->wValue); 1210 pSetup->wIndex = RT_H2LE_U16(pSetup->wIndex); 1211 pSetup->wLength = RT_H2LE_U16(pSetup->wLength); 1212 } 1213 1214 1215 /** 1216 * Clean up after a failed URB submit. 1217 */ 1218 static void usbProxyLinuxCleanupFailedSubmit(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx, PUSBPROXYURBLNX pCur, PVUSBURB pUrb, bool *pfUnplugged) 1219 { 1220 if (pUrb->enmType == VUSBXFERTYPE_MSG) 1221 usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData); 1222 1223 /* discard and reap later (walking with pUrbLnx). */ 1224 if (pUrbLnx != pCur) 1225 { 1226 for (;;) 1227 { 1228 pUrbLnx->fCanceledBySubmit = true; 1229 pUrbLnx->KUrb.usercontext = NULL; 1230 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX)) 1231 { 1232 if (errno == ENODEV) 1233 *pfUnplugged = true; 1234 else if (errno == ENOENT) 1235 pUrbLnx->fSplitElementReaped = true; 1236 else 1237 LogRel(("USB: Failed to discard %p! errno=%d (pUrb=%p)\n", pUrbLnx->KUrb.usercontext, errno, pUrb)); /* serious! */ 1238 } 1239 if (pUrbLnx->pSplitNext == pCur) 1240 { 1241 pUrbLnx->pSplitNext = NULL; 1242 break; 1243 } 1244 pUrbLnx = pUrbLnx->pSplitNext; Assert(pUrbLnx); 1245 } 1246 } 1247 1248 /* free the unsubmitted ones. */ 1249 while (pCur) 1250 { 1251 PUSBPROXYURBLNX pFree = pCur; 1252 pCur = pCur->pSplitNext; 1253 usbProxyLinuxUrbFree(pProxyDev, pFree); 1254 } 1255 1256 /* send unplug event if we failed with ENODEV originally. */ 1257 if (*pfUnplugged) 1258 usbProxLinuxUrbUnplugged(pProxyDev); 1259 } 1260 1261 /** 1262 * Submit one URB through the usbfs IOCTL interface, with 1263 * retries 1264 * 1265 * @returns true / false. 1266 */ 1267 static bool usbProxyLinuxSubmitURB(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pCur, PVUSBURB pUrb, bool *pfUnplugged) 1268 { 1269 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 1270 unsigned cTries = 0; 1271 1272 while (ioctl(pDevLnx->File, USBDEVFS_SUBMITURB, &pCur->KUrb)) 1273 { 1274 if (errno == EINTR) 1275 continue; 1276 if (errno == ENODEV) 1277 { 1278 Log(("usbProxyLinuxSubmitURB: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev))); 1279 *pfUnplugged = true; 1280 return false; 1281 } 1282 1283 Log(("usb-linux: Submit URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n", 1284 pUrb, errno, pCur->KUrb.type, pCur->KUrb.endpoint, pCur->KUrb.buffer_length, cTries)); 1285 if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */ 1286 { 1287 pCur->u64SubmitTS = RTTimeMilliTS(); 1288 continue; 1289 } 1290 return false; 1291 } 1292 return true; 1293 } 1294 1295 /** The split size. 16K in known Linux kernel versions. */ 1296 #define SPLIT_SIZE 0x4000 1297 1298 /** 1299 * Create a URB fragment of up to SPLIT_SIZE size and hook it 1300 * into the list of fragments. 1301 * 1302 * @returns pointer to newly allocated URB fragment or NULL. 1303 */ 1304 static PUSBPROXYURBLNX usbProxyLinuxSplitURBFragment(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pHead, PUSBPROXYURBLNX pCur) 1305 { 1306 PUSBPROXYURBLNX pNew; 1307 uint32_t cbLeft = pCur->cbSplitRemaining; 1308 uint8_t *pb = (uint8_t *)pCur->KUrb.buffer; 1309 1310 Assert(cbLeft != 0); 1311 pNew = pCur->pSplitNext = usbProxyLinuxUrbAlloc(pProxyDev, pHead); 1312 if (!pNew) 1313 { 1314 usbProxyLinuxUrbFreeSplitList(pProxyDev, pHead); 1315 return NULL; 1316 } 1317 Assert(pHead->pNext != pNew); Assert(pHead->pPrev != pNew); Assert(pNew->pNext == pNew->pPrev); 1318 Assert(pNew->pSplitHead == pHead); 1319 Assert(pNew->pSplitNext == NULL); 1320 1321 pNew->KUrb = pHead->KUrb; 1322 pNew->KUrb.buffer = pb + pCur->KUrb.buffer_length; 1323 pNew->KUrb.buffer_length = RT_MIN(cbLeft, SPLIT_SIZE); 1324 pNew->KUrb.actual_length = 0; 1325 1326 cbLeft -= pNew->KUrb.buffer_length; 1327 Assert(cbLeft < INT32_MAX); 1328 pNew->cbSplitRemaining = cbLeft; 1329 return pNew; 1330 } 1331 1332 /** 1333 * Try splitting up a VUSB URB into smaller URBs which the 1334 * linux kernel (usbfs) can deal with. 1335 * 1336 * NB: For ShortOK reads things get a little tricky - we don't 1337 * know how much data is going to arrive and not all the 1338 * fragment URBs might be filled. We can only safely set up one 1339 * URB at a time -> worse performance but correct behaviour. 1056 1340 * 1057 1341 * @returns true / false. … … 1062 1346 static int usbProxyLinuxUrbQueueSplit(PUSBPROXYDEV pProxyDev, PUSBPROXYURBLNX pUrbLnx, PVUSBURB pUrb) 1063 1347 { 1064 unsigned cTries;1065 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv;1066 1067 1348 /* 1068 1349 * Split it up into SPLIT_SIZE sized blocks. … … 1080 1361 case VUSBXFERTYPE_BULK: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_BULK; break; 1081 1362 case VUSBXFERTYPE_INTR: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_INTERRUPT; break; 1082 case VUSBXFERTYPE_ISOC: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_ISO; break;1083 1363 case VUSBXFERTYPE_MSG: pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_CONTROL; break; 1364 case VUSBXFERTYPE_ISOC: 1365 AssertMsgFailed(("We can't split isochronous URBs!\n")); 1366 usbProxyLinuxUrbFree(pProxyDev, pUrbLnx); 1367 return false; 1084 1368 } 1085 1369 pUrbLnx->KUrb.endpoint = pUrb->EndPt; … … 1089 1373 pUrbLnx->KUrb.flags = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0; /* ISO_ASAP too? */ 1090 1374 pUrbLnx->KUrb.buffer = pb; 1091 pUrbLnx->KUrb.buffer_length = MIN(cbLeft, SPLIT_SIZE);1375 pUrbLnx->KUrb.buffer_length = RT_MIN(cbLeft, SPLIT_SIZE); 1092 1376 pUrbLnx->KUrb.actual_length = 0; 1093 1377 pUrbLnx->KUrb.start_frame = 0; … … 1099 1383 pUrbLnx->pSplitNext = NULL; 1100 1384 1101 pb += pUrbLnx->KUrb.buffer_length; 1385 PUSBPROXYURBLNX pCur = pUrbLnx; 1386 1102 1387 cbLeft -= pUrbLnx->KUrb.buffer_length; 1103 1104 /* the rest. */ 1105 unsigned i; 1106 PUSBPROXYURBLNX pCur = pUrbLnx; 1107 for (i = 1; i < cKUrbs; i++) 1108 { 1109 Assert(cbLeft != 0); 1110 pCur = pCur->pSplitNext = usbProxyLinuxUrbAlloc(pProxyDev, pUrbLnx); 1111 if (!pCur) 1112 { 1113 usbProxyLinuxUrbFreeSplitList(pProxyDev, pUrbLnx); 1114 return false; 1115 } 1116 Assert(pUrbLnx->pNext != pCur); Assert(pUrbLnx->pPrev != pCur); Assert(pCur->pNext == pCur->pPrev); 1117 Assert(pCur->pSplitHead == pUrbLnx); 1118 Assert(pCur->pSplitNext == NULL); 1119 1120 pCur->KUrb = pUrbLnx->KUrb; 1121 pCur->KUrb.buffer = pb; 1122 pCur->KUrb.buffer_length = MIN(cbLeft, SPLIT_SIZE); 1123 pCur->KUrb.actual_length = 0; 1124 1125 pb += pCur->KUrb.buffer_length; 1126 cbLeft -= pCur->KUrb.buffer_length; 1127 } 1128 Assert(cbLeft == 0); 1129 1130 /* 1131 * Submit them. 1132 */ 1388 pUrbLnx->cbSplitRemaining = cbLeft; 1389 1390 bool fSucceeded = false; 1133 1391 bool fUnplugged = false; 1134 bool fFailed = false; 1135 pCur = pUrbLnx; 1136 for (i = 0; i < cKUrbs; i++, pCur = pCur->pSplitNext) 1137 { 1138 cTries = 0; 1139 while (ioctl(pDevLnx->File, USBDEVFS_SUBMITURB, &pCur->KUrb)) 1140 { 1141 if (errno == EINTR) 1142 continue; 1143 if (errno == ENODEV) 1392 if (pUrb->enmDir == VUSBDIRECTION_IN && !pUrb->fShortNotOk) 1393 { 1394 /* Subsequent fragments will be queued only after the previous fragment is reaped 1395 * and only if necessary. 1396 */ 1397 fSucceeded = true; 1398 Log(("usb-linux: Large ShortOK read, only queuing first fragment.\n")); 1399 Assert(pUrbLnx->cbSplitRemaining > 0 && pUrbLnx->cbSplitRemaining < 256 * _1K); 1400 fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pUrbLnx, pUrb, &fUnplugged); 1401 } 1402 else 1403 { 1404 /* the rest. */ 1405 unsigned i; 1406 for (i = 1; i < cKUrbs; i++) 1407 { 1408 pCur = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx, pCur); 1409 if (!pCur) 1144 1410 { 1145 Log(("usbProxyLinuxUrbQueueSplit: ENODEV -> unplugged. pProxyDev=%p[%s]\n", pProxyDev, pProxyDev->Dev.pszName)); 1146 fFailed = fUnplugged = true; 1411 return false; 1412 } 1413 } 1414 Assert(pCur->cbSplitRemaining == 0); 1415 1416 /* Submit the blocks. */ 1417 pCur = pUrbLnx; 1418 for (i = 0; i < cKUrbs; i++, pCur = pCur->pSplitNext) 1419 { 1420 fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pCur, pUrb, &fUnplugged); 1421 if (!fSucceeded) 1147 1422 break; 1148 } 1149 1150 Log(("usb-linux: Queue URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n", 1151 pUrb, errno, pCur->KUrb.type, pCur->KUrb.endpoint, pCur->KUrb.buffer_length, cTries)); 1152 if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */ 1153 continue; 1154 fFailed = true; 1155 break; 1156 } 1157 if (fFailed) 1158 break; 1159 pCur->u64SubmitTS = RTTimeMilliTS(); 1160 } 1161 if (!fFailed) 1423 } 1424 } 1425 1426 if (fSucceeded) 1162 1427 { 1163 1428 pUrb->Dev.pvPrivate = pUrbLnx; … … 1166 1431 } 1167 1432 1168 /* 1169 * Clean up. 1170 */ 1171 if (pUrb->enmType == VUSBXFERTYPE_MSG) 1172 usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData); 1173 1174 /* discard and reap later (walking with pUrbLnx). */ 1175 if (pUrbLnx != pCur) 1176 { 1177 for (;;) 1178 { 1179 pUrbLnx->fCanceledBySubmit = true; 1180 pUrbLnx->KUrb.usercontext = NULL; 1181 if (usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX)) 1182 { 1183 if (errno == ENODEV) 1184 fUnplugged = true; 1185 else if (errno == ENOENT) 1186 pUrbLnx->fSplitElementReaped = true; 1187 else 1188 LogRel(("SUB: Failed to discard %p! errno=%d (pUrb=%p)\n", pUrbLnx->KUrb.usercontext, errno, pUrb)); /* serious! */ 1189 } 1190 if (pUrbLnx->pSplitNext == pCur) 1191 { 1192 pUrbLnx->pSplitNext = NULL; 1193 break; 1194 } 1195 pUrbLnx = pUrbLnx->pSplitNext; Assert(pUrbLnx); 1196 } 1197 } 1198 1199 /* free the unsubmitted ones. */ 1200 while (pCur) 1201 { 1202 PUSBPROXYURBLNX pFree = pCur; 1203 pCur = pCur->pSplitNext; 1204 usbProxyLinuxUrbFree(pProxyDev, pFree); 1205 } 1206 1207 /* send unplug event if we failed with ENODEV originally. */ 1208 if (fUnplugged) 1209 usbProxLinuxUrbUnplugged(pProxyDev); 1433 usbProxyLinuxCleanupFailedSubmit(pProxyDev, pUrbLnx, pCur, pUrb, &fUnplugged); 1210 1434 return false; 1211 1435 } … … 1213 1437 1214 1438 /** 1215 * @copydoc USBPROXYBACK::pf bUrbQueue1439 * @copydoc USBPROXYBACK::pfnUrbQueue 1216 1440 */ 1217 1441 static int usbProxyLinuxUrbQueue(PVUSBURB pUrb) 1218 1442 { 1219 1443 unsigned cTries; 1220 PUSBPROXYDEV pProxyDev = (PUSBPROXYDEV)pUrb->pDev; 1444 #ifndef RDESKTOP 1445 PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV); 1446 #else 1447 PUSBPROXYDEV pProxyDev = usbProxyFromVusbDev(pUrb->pDev); 1448 #endif 1221 1449 PUSBPROXYDEVLNX pDevLnx = (PUSBPROXYDEVLNX)pProxyDev->Backend.pv; 1222 LogFlow(("usbProxyLinuxUrbQueue: pProxyDev=% p[%s]pUrb=%p EndPt=%d cbData=%d\n",1223 pProxyDev, pProxyDev->Dev.pszName, pUrb, pUrb->EndPt, pUrb->cbData));1450 LogFlow(("usbProxyLinuxUrbQueue: pProxyDev=%s pUrb=%p EndPt=%d cbData=%d\n", 1451 usbProxyGetName(pProxyDev), pUrb, pUrb->EndPt, pUrb->cbData)); 1224 1452 1225 1453 /* … … 1229 1457 if (!pUrbLnx) 1230 1458 return false; 1459 1460 pUrbLnx->KUrb.endpoint = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0); 1461 pUrbLnx->KUrb.status = 0; 1462 pUrbLnx->KUrb.flags = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0; 1463 pUrbLnx->KUrb.buffer = pUrb->abData; 1464 pUrbLnx->KUrb.buffer_length = pUrb->cbData; 1465 pUrbLnx->KUrb.actual_length = 0; 1466 pUrbLnx->KUrb.start_frame = 0; 1467 pUrbLnx->KUrb.number_of_packets = 0; 1468 pUrbLnx->KUrb.error_count = 0; 1469 pUrbLnx->KUrb.signr = 0; 1470 pUrbLnx->KUrb.usercontext = pUrb; 1231 1471 1232 1472 switch (pUrb->enmType) … … 1247 1487 case VUSBXFERTYPE_ISOC: 1248 1488 pUrbLnx->KUrb.type = USBDEVFS_URB_TYPE_ISO; 1489 pUrbLnx->KUrb.flags |= USBDEVFS_URB_ISO_ASAP; 1490 pUrbLnx->KUrb.number_of_packets = pUrb->cIsocPkts; 1491 unsigned i; 1492 for (i = 0; i < pUrb->cIsocPkts; i++) 1493 { 1494 pUrbLnx->KUrb.iso_frame_desc[i].length = pUrb->aIsocPkts[i].cb; 1495 pUrbLnx->KUrb.iso_frame_desc[i].actual_length = 0; 1496 pUrbLnx->KUrb.iso_frame_desc[i].status = 0x7fff; 1497 } 1249 1498 break; 1250 1499 case VUSBXFERTYPE_INTR: … … 1254 1503 goto l_err; 1255 1504 } 1256 pUrbLnx->KUrb.endpoint = pUrb->EndPt;1257 pUrbLnx->KUrb.status = 0;1258 pUrbLnx->KUrb.flags = pUrb->fShortNotOk ? USBDEVFS_URB_SHORT_NOT_OK : 0; /* ISO_ASAP too? */1259 pUrbLnx->KUrb.buffer = pUrb->abData;1260 pUrbLnx->KUrb.buffer_length = pUrb->cbData;1261 pUrbLnx->KUrb.actual_length = 0;1262 pUrbLnx->KUrb.start_frame = 0;1263 pUrbLnx->KUrb.number_of_packets = 0;1264 pUrbLnx->KUrb.error_count = 0;1265 pUrbLnx->KUrb.signr = 0;1266 pUrbLnx->KUrb.usercontext = pUrb;1267 switch (pUrb->enmDir)1268 {1269 case VUSBDIRECTION_IN:1270 pUrbLnx->KUrb.endpoint |= 0x80;1271 break;1272 case VUSBDIRECTION_OUT:1273 break;1274 default:1275 AssertMsgFailed(("usbProxyLinuxUrbQueue: Invalid directorion %d\n", pUrb->enmDir));1276 goto l_err;1277 }1278 1505 1279 1506 /* … … 1287 1514 if (errno == ENODEV) 1288 1515 { 1289 Log(("usbProxyLinuxUrbQueue: ENODEV -> unplugged. pProxyDev=% p[%s]\n", pProxyDev, pProxyDev->Dev.pszName));1516 Log(("usbProxyLinuxUrbQueue: ENODEV -> unplugged. pProxyDev=%s\n", usbProxyGetName(pProxyDev))); 1290 1517 if (pUrb->enmType == VUSBXFERTYPE_MSG) 1291 1518 usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData); … … 1356 1583 Assert(pCur == pCur->pSplitHead); 1357 1584 unsigned cFailures = 0; 1358 1359 for ( 1585 PUSBPROXYURBLNX pCur2; 1586 for (pCur2 = pCur; pCur2; pCur2 = pCur2->pSplitNext) 1360 1587 { 1361 1588 if (pCur2->fSplitElementReaped) … … 1370 1597 goto l_leave; /* ENODEV means break and everything cancelled elsewhere. */ 1371 1598 } 1372 LogRel(("USB: Cancelled URB (%p) after %ll dms!! (cFailures=%d)\n",1373 pCur->KUrb.usercontext, u64MilliTS - pCur->u64SubmitTS, cFailures));1599 LogRel(("USB: Cancelled URB (%p) after %llums!! (cFailures=%d)\n", 1600 pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS, cFailures)); 1374 1601 } 1375 1602 else … … 1380 1607 { 1381 1608 pCur->fCanceledByTimedOut = true; 1382 LogRel(("USB: Cancelled URB (%p) after %ll dms!!\n", pCur->KUrb.usercontext,u64MilliTS - pCur->u64SubmitTS));1609 LogRel(("USB: Cancelled URB (%p) after %llums!!\n", pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS)); 1383 1610 } 1384 1611 else if (errno != ENODEV) … … 1388 1615 } 1389 1616 } 1617 #if 0 1618 /* Disabled for the time beeing as some USB devices have URBs pending for an unknown amount of time. 1619 * One example is the OmniKey CardMan 3821. */ 1390 1620 else if (u64MilliTS - pCur->u64SubmitTS >= 200*1000 /* 200 sec (180 sec has been observed with XP) */) 1391 1621 pCur->fTimedOut = true; 1622 #endif 1392 1623 } 1393 1624 … … 1398 1629 1399 1630 /** 1400 * Get and translates the linux status to a VUSB status. 1401 */ 1402 static VUSBSTATUS vusbProxyLinuxUrbGetStatus(PUSBPROXYURBLNX pUrbLnx) 1403 { 1404 switch (pUrbLnx->KUrb.status) 1405 { 1631 * Translate the linux status to a VUSB status. 1632 * 1633 * @remarks see cc_to_error in ohci.h, uhci_map_status in uhci-q.c, 1634 * sitd_complete+itd_complete in ehci-sched.c, and qtd_copy_status in 1635 * ehci-q.c. 1636 */ 1637 static VUSBSTATUS vusbProxyLinuxStatusToVUsbStatus(int iStatus) 1638 { 1639 switch (iStatus) 1640 { 1641 /** @todo VUSBSTATUS_NOT_ACCESSED */ 1642 case -EXDEV: /* iso transfer, partial result. */ 1406 1643 case 0: 1407 if (!pUrbLnx->fCanceledByTimedOut) 1408 return VUSBSTATUS_OK; 1409 /* fall thru */ 1644 return VUSBSTATUS_OK; 1410 1645 1411 1646 case -EILSEQ: … … 1413 1648 1414 1649 case -EREMOTEIO: /* ehci and ohci uses this for underflow error. */ 1415 return VUSBSTATUS_UNDERFLOW; 1416 1650 return VUSBSTATUS_DATA_UNDERRUN; 1651 case -EOVERFLOW: 1652 return VUSBSTATUS_DATA_OVERRUN; 1653 1654 case -ETIME: 1417 1655 case -ENODEV: 1418 1656 return VUSBSTATUS_DNR; … … 1426 1664 // return VUSBSTATUS_BIT_STUFFING; 1427 1665 1666 case -EPIPE: 1667 Log(("vusbProxyLinuxStatusToVUsbStatus: STALL/EPIPE!!\n")); 1668 return VUSBSTATUS_STALL; 1669 1670 case -ESHUTDOWN: 1671 Log(("vusbProxyLinuxStatusToVUsbStatus: SHUTDOWN!!\n")); 1672 return VUSBSTATUS_STALL; 1673 1428 1674 default: 1429 Log((" usbProxyLinuxUrbReap: pKUrb status %d!!\n", pUrbLnx->KUrb.status));1675 Log(("vusbProxyLinuxStatusToVUsbStatus: status %d!!\n", iStatus)); 1430 1676 return VUSBSTATUS_STALL; 1431 1677 } 1678 } 1679 1680 1681 /** 1682 * Get and translates the linux status to a VUSB status. 1683 */ 1684 static VUSBSTATUS vusbProxyLinuxUrbGetStatus(PUSBPROXYURBLNX pUrbLnx) 1685 { 1686 if ( pUrbLnx->fCanceledByTimedOut 1687 && pUrbLnx->KUrb.status == 0) 1688 return VUSBSTATUS_CRC; 1689 return vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.status); 1432 1690 } 1433 1691 … … 1441 1699 * @param cMillies Number of milliseconds to wait. Use 0 to not wait at all. 1442 1700 */ 1443 static PVUSBURB usbProxyLinuxUrbReap(PUSBPROXYDEV pProxyDev, unsignedcMillies)1701 static PVUSBURB usbProxyLinuxUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies) 1444 1702 { 1445 1703 PUSBPROXYURBLNX pUrbLnx = NULL; … … 1511 1769 if (errno != EAGAIN) 1512 1770 { 1513 Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=% p[%s]\n", rc, errno, pProxyDev, pProxyDev->Dev.pszName));1771 Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=%s\n", rc, errno, usbProxyGetName(pProxyDev))); 1514 1772 return NULL; 1515 1773 } … … 1532 1790 vusbProxyLinuxUrbDoTimeouts(pProxyDev, pDevLnx); 1533 1791 else 1534 Log(("usb-linux: Reap URB. errno=%d pProxyDev=% p[%s]\n", errno, pProxyDev, pProxyDev->Dev.pszName));1792 Log(("usb-linux: Reap URB. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1535 1793 return NULL; 1536 1794 } … … 1541 1799 { 1542 1800 pUrbLnx->fSplitElementReaped = true; 1543 PUSBPROXYURBLNX pCur; 1801 1802 /* for variable size URBs, we may need to queue more if the just-reaped URB was completely filled */ 1803 if (pUrbLnx->cbSplitRemaining && (pKUrb->actual_length == pKUrb->buffer_length) && !pUrbLnx->pSplitNext) 1804 { 1805 bool fUnplugged = false; 1806 bool fSucceeded; 1807 1808 Assert(pUrbLnx->pSplitHead); 1809 Assert((pKUrb->endpoint & 0x80) && (!pKUrb->flags & USBDEVFS_URB_SHORT_NOT_OK)); 1810 PUSBPROXYURBLNX pNew = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx->pSplitHead, pUrbLnx); 1811 if (!pNew) 1812 { 1813 Log(("usb-linux: Allocating URB fragment failed. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1814 return NULL; 1815 } 1816 PVUSBURB pUrb = (PVUSBURB)pUrbLnx->KUrb.usercontext; 1817 fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pNew, pUrb, &fUnplugged); 1818 if (fUnplugged) 1819 usbProxLinuxUrbUnplugged(pProxyDev); 1820 if (!fSucceeded) 1821 return NULL; 1822 continue; /* try reaping another URB */ 1823 } 1824 PUSBPROXYURBLNX pCur; 1544 1825 for (pCur = pUrbLnx->pSplitHead; pCur; pCur = pCur->pSplitNext) 1545 1826 if (!pCur->fSplitElementReaped) … … 1569 1850 uint8_t *pbEnd = &pUrb->abData[0]; 1570 1851 pUrb->enmStatus = VUSBSTATUS_OK; 1571 1852 PUSBPROXYURBLNX pCur; 1572 1853 for (pCur = pUrbLnx; pCur; pCur = pCur->pSplitNext) 1573 1854 { … … 1585 1866 pUrb->enmStatus = vusbProxyLinuxUrbGetStatus(pUrbLnx); 1586 1867 pUrb->cbData = pUrbLnx->KUrb.actual_length; 1868 if (pUrb->enmType == VUSBXFERTYPE_ISOC) 1869 { 1870 unsigned i, off; 1871 for (i = 0, off = 0; i < pUrb->cIsocPkts; i++) 1872 { 1873 pUrb->aIsocPkts[i].enmStatus = vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.iso_frame_desc[i].status); 1874 Assert(pUrb->aIsocPkts[i].off == off); 1875 pUrb->aIsocPkts[i].cb = pUrbLnx->KUrb.iso_frame_desc[i].actual_length; 1876 off += pUrbLnx->KUrb.iso_frame_desc[i].length; 1877 } 1878 } 1587 1879 usbProxyLinuxUrbFree(pProxyDev, pUrbLnx); 1588 1880 } … … 1602 1894 } 1603 1895 1604 LogFlow(("usbProxyLinuxUrbReap: dev=%p[%s] returns %p\n", pProxyDev, pProxyDev->Dev.pszName, pUrb));1896 LogFlow(("usbProxyLinuxUrbReap: pProxyDev=%s returns %p\n", usbProxyGetName(pProxyDev), pUrb)); 1605 1897 return pUrb; 1606 1898 } … … 1613 1905 static void usbProxyLinuxUrbCancel(PVUSBURB pUrb) 1614 1906 { 1615 PUSBPROXYDEV pProxyDev = (PUSBPROXYDEV)pUrb->pDev; 1907 #ifndef RDESKTOP 1908 PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV); 1909 #else 1910 PUSBPROXYDEV pProxyDev = usbProxyFromVusbDev(pUrb->pDev); 1911 #endif 1616 1912 PUSBPROXYURBLNX pUrbLnx = (PUSBPROXYURBLNX)pUrb->Dev.pvPrivate; 1617 1913 if (pUrbLnx->pSplitHead) … … 1619 1915 /* split */ 1620 1916 Assert(pUrbLnx == pUrbLnx->pSplitHead); 1621 1917 PUSBPROXYURBLNX pCur; 1622 1918 for (pCur = pUrbLnx; pCur; pCur = pCur->pSplitNext) 1623 1919 { … … 1629 1925 if (errno == ENODEV) 1630 1926 break; 1631 Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=% p[%s]!!! (split)\n",1632 pUrb, errno, pProxyDev, pProxyDev->Dev.pszName));1927 Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%s!!! (split)\n", 1928 pUrb, errno, usbProxyGetName(pProxyDev))); 1633 1929 } 1634 1930 } … … 1639 1935 && errno != ENODEV /* deal with elsewhere. */ 1640 1936 && errno != ENOENT) 1641 Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=% p[%s]!!!\n",1642 pUrb, errno, pProxyDev, pProxyDev->Dev.pszName));1937 Log(("usb-linux: Discard URB %p failed, errno=%d. pProxyDev=%s!!!\n", 1938 pUrb, errno, usbProxyGetName(pProxyDev))); 1643 1939 } 1644 1940 } … … 1648 1944 * The Linux USB Proxy Backend. 1649 1945 */ 1650 #ifdef __cplusplus1651 extern1652 #endif1653 1946 const USBPROXYBACK g_USBProxyDeviceHost = 1654 1947 { 1655 1948 "host", 1656 1949 usbProxyLinuxOpen, 1950 usbProxyLinuxInit, 1657 1951 usbProxyLinuxClose, 1658 1952 usbProxyLinuxReset, -
trunk/src/VBox/RDP/client/vrdp/rdpusb.c
r28800 r31247 24 24 #include <fcntl.h> 25 25 26 #include "runtime.h" 26 27 #include "vrdpusb.h" 28 #include "USBProxyDevice.h" 27 29 28 30 #define RDPUSB_REQ_OPEN (0) … … 64 66 #pragma pack () 65 67 68 static inline int op_usbproxy_back_open(PUSBPROXYDEV p, const char *pszAddress) 69 { 70 return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL); 71 } 72 73 static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev) 74 { 75 return g_USBProxyDeviceHost.pfnClose (pDev); 76 } 77 78 static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev) 79 { 80 return g_USBProxyDeviceHost.pfnReset (pDev, false); 81 } 82 83 static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg) 84 { 85 return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg); 86 } 87 88 static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum) 89 { 90 return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum); 91 } 92 93 static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum) 94 { 95 return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum); 96 } 97 98 static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting) 99 { 100 return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting); 101 } 102 103 static inline int op_usbproxy_back_queue_urb(PVUSBURB pUrb) 104 { 105 return g_USBProxyDeviceHost.pfnUrbQueue(pUrb); 106 } 107 108 static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies) 109 { 110 return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies); 111 } 112 113 static inline bool op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint) 114 { 115 return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint); 116 } 117 118 static inline void op_usbproxy_back_cancel_urb(PVUSBURB pUrb) 119 { 120 return g_USBProxyDeviceHost.pfnUrbCancel (pUrb); 121 } 122 66 123 static uint16 getBcd (const char *str, const char *prefix) 67 124 { … … 405 462 vrdp_usb_status (int rc, VUSBDEV *pdev) 406 463 { 407 if (!rc || pdev->request_detach)464 if (!rc || usbProxyFromVusbDev(pdev)->fDetached) 408 465 { 409 466 return VRDP_USB_STATUS_DEVICE_REMOVED; … … 413 470 } 414 471 415 static struct usb_proxy *g_proxies = NULL;416 417 static struct usb_proxy *472 static PUSBPROXYDEV g_proxies = NULL; 473 474 static PUSBPROXYDEV 418 475 devid2proxy (uint32_t devid) 419 476 { 420 struct usb_proxy *proxy = g_proxies;477 PUSBPROXYDEV proxy = g_proxies; 421 478 422 479 while (proxy && proxy->devid != devid) 423 480 { 424 proxy = proxy-> next;481 proxy = proxy->pNext; 425 482 } 426 483 … … 435 492 PVUSBURB pUrb = NULL; 436 493 437 struct usb_proxy *proxy = g_proxies;494 PUSBPROXYDEV proxy = g_proxies; 438 495 439 496 while (proxy) … … 467 524 rdpusb_send(s); 468 525 469 if (pUrb->p rev || pUrb->next || pUrb == proxy->urbs)526 if (pUrb->pPrev || pUrb->pNext || pUrb == proxy->pUrbs) 470 527 { 471 528 /* Remove the URB from list. */ 472 if (pUrb->p rev)473 { 474 pUrb->p rev->next = pUrb->next;529 if (pUrb->pPrev) 530 { 531 pUrb->pPrev->pNext = pUrb->pNext; 475 532 } 476 533 else 477 534 { 478 proxy-> urbs = pUrb->next;535 proxy->pUrbs = pUrb->pNext; 479 536 } 480 537 481 if (pUrb-> next)482 { 483 pUrb-> next->prev = pUrb->prev;538 if (pUrb->pNext) 539 { 540 pUrb->pNext->pPrev = pUrb->pPrev; 484 541 } 485 542 } … … 494 551 } 495 552 496 proxy = proxy-> next;553 proxy = proxy->pNext; 497 554 } 498 555 … … 509 566 uint32 devid; 510 567 511 struct usb_proxy *proxy = NULL;568 PUSBPROXYDEV proxy = NULL; 512 569 513 570 #ifdef RDPUSB_DEBUG … … 535 592 in_uint32_le(s, devid); 536 593 537 proxy = ( struct usb_proxy *)xmalloc (sizeof (struct usb_proxy));538 539 memset (proxy, 0, sizeof ( struct usb_proxy));594 proxy = (PUSBPROXYDEV )xmalloc (sizeof (USBPROXYDEV)); 595 596 memset (proxy, 0, sizeof (USBPROXYDEV)); 540 597 541 598 proxy->Dev.pszName = "Remote device"; … … 556 613 if (g_proxies) 557 614 { 558 g_proxies->p rev = proxy;615 g_proxies->pPrev = proxy; 559 616 } 560 617 561 proxy-> next = g_proxies;618 proxy->pNext = g_proxies; 562 619 g_proxies = proxy; 563 620 } … … 573 630 op_usbproxy_back_close(proxy); 574 631 575 if (proxy->p rev)576 { 577 proxy->p rev->next = proxy->next;632 if (proxy->pPrev) 633 { 634 proxy->pPrev->pNext = proxy->pNext; 578 635 } 579 636 else 580 637 { 581 g_proxies = proxy-> next;638 g_proxies = proxy->pNext; 582 639 } 583 640 584 if (proxy-> next)585 { 586 proxy-> next->prev = proxy->prev;641 if (proxy->pNext) 642 { 643 proxy->pNext->pPrev = proxy->pPrev; 587 644 } 588 645 … … 760 817 if (rc) 761 818 { 762 if (proxy-> urbs)763 { 764 proxy-> urbs->prev = pUrb;819 if (proxy->pUrbs) 820 { 821 proxy->pUrbs->pPrev = pUrb; 765 822 } 766 823 767 pUrb-> next = proxy->urbs;768 proxy-> urbs = pUrb;824 pUrb->pNext = proxy->pUrbs; 825 proxy->pUrbs = pUrb; 769 826 } 770 827 else … … 818 875 in_uint32_le(s, handle); 819 876 820 pUrb = proxy-> urbs;877 pUrb = proxy->pUrbs; 821 878 822 879 while (pUrb && pUrb->handle != handle) 823 880 { 824 pUrb = pUrb-> next;881 pUrb = pUrb->pNext; 825 882 } 826 883 … … 832 889 833 890 /* Remove URB from list. */ 834 if (pUrb->p rev)835 { 836 pUrb->p rev->next = pUrb->next;891 if (pUrb->pPrev) 892 { 893 pUrb->pPrev->pNext = pUrb->pNext; 837 894 } 838 895 else 839 896 { 840 proxy-> urbs = pUrb->next;897 proxy->pUrbs = pUrb->pNext; 841 898 } 842 899 843 if (pUrb-> next)844 { 845 pUrb-> next->prev = pUrb->prev;900 if (pUrb->pNext) 901 { 902 pUrb->pNext->pPrev = pUrb->pPrev; 846 903 } 847 904 848 pUrb-> next = pUrb->prev = NULL;905 pUrb->pNext = pUrb->pPrev = NULL; 849 906 850 907 Log(("Cancelled URB %p\n", pUrb)); … … 896 953 rdpusb_add_fds(int *n, fd_set * rfds, fd_set * wfds) 897 954 { 898 struct usb_proxy *proxy = g_proxies;955 PUSBPROXYDEV proxy = g_proxies; 899 956 900 957 // Log(("RDPUSB: rdpusb_add_fds: begin *n = %d\n", *n)); … … 902 959 while (proxy) 903 960 { 904 int fd = dev2fd(proxy);961 int fd = USBProxyDeviceLinuxGetFD(proxy); 905 962 906 963 if (fd != -1) … … 913 970 } 914 971 915 proxy = proxy-> next;972 proxy = proxy->pNext; 916 973 } 917 974 … … 924 981 rdpusb_check_fds(fd_set * rfds, fd_set * wfds) 925 982 { 926 (void)rfds; 927 (void)wfds; 983 PUSBPROXYDEV proxy = g_proxies; 984 unsigned found = 0; 985 986 while (proxy) 987 { 988 int fd = USBProxyDeviceLinuxGetFD(proxy); 989 990 if (fd != -1) 991 { 992 if (FD_ISSET(fd, rfds)) 993 found = 1; 994 if (FD_ISSET(fd, wfds)) 995 found = 1; 996 } 997 998 proxy = proxy->pNext; 999 } 928 1000 929 1001 // Log(("RDPUSB: rdpusb_check_fds: begin\n")); 930 1002 931 rdpusb_reap_urbs (); 1003 if (found) 1004 rdpusb_reap_urbs (); 932 1005 933 1006 // Log(("RDPUSB: rdpusb_check_fds: end\n")); … … 948 1021 rdpusb_close (void) 949 1022 { 950 struct usb_proxy *proxy = g_proxies;1023 PUSBPROXYDEV proxy = g_proxies; 951 1024 952 1025 while (proxy) 953 1026 { 954 struct usb_proxy *next = proxy->next;1027 PUSBPROXYDEV pNext = proxy->pNext; 955 1028 956 1029 Log(("RDPUSB: closing proxy %p\n", proxy)); … … 959 1032 xfree (proxy); 960 1033 961 proxy = next;1034 proxy = pNext; 962 1035 } 963 1036 -
trunk/src/VBox/RDP/client/vrdp/runtime.h
r30591 r31247 15 15 */ 16 16 17 #ifndef __ VRDPUSB__H18 #define __ VRDPUSB__H17 #ifndef __RUNTIME__H 18 #define __RUNTIME__H 19 19 20 20 #include <endian.h> 21 21 #include <byteswap.h> 22 #include <stdint.h> 23 #include <ctype.h> 24 #include <errno.h> 22 25 23 26 #ifndef cpu_to_le16 … … 34 37 //#define cpu_to_le16 __cpu_to_le16 35 38 39 #if 0 36 40 #define uint8_t uint8 37 41 #define uint16_t uint16 38 42 #define uint32_t uint32 39 43 #define uint64_t long long 44 #endif 40 45 #define bool int 41 46 #define false 0 … … 43 48 44 49 #define OPSTATIC 50 #define RDPUSB_DEBUG 45 51 #ifdef RDPUSB_DEBUG 46 #define LogFlow(a) printf a 47 #define Log(a) printf a 48 #define Log2(a) printf a 52 #define DoLog(a) do { \ 53 printf("Time %llu: ", RTTimeMilliTS()); \ 54 printf a; \ 55 } while(0) 56 57 #define LogFlow(a) DoLog(a) 58 #define Log(a) DoLog(a) 59 #define Log2(a) DoLog(a) 49 60 #else 50 61 #define LogFlow(a) do {} while (0) … … 62 73 #define _1K 1024 63 74 64 #define RT_LE2H_U16(_le16) (cpu_to_le16 (_le16)) 75 #ifdef RT_BIG_ENDIAN 76 # define RT_H2LE_U16(u16) RT_BSWAP_U16(u16) 77 # define RT_LE2H_U16(u16) RT_BSWAP_U16(u16) 78 #else 79 # define RT_H2LE_U16(u16) (u16) 80 # define RT_LE2H_U16(u16) (u16) 81 #endif 82 #define RT_BSWAP_U16(u16) RT_MAKE_U16(RT_HIBYTE(u16), RT_LOBYTE(u16)) 83 #define RT_MAKE_U16(Lo, Hi) \ 84 ((uint16_t)( (uint16_t)((uint8_t)(Hi)) << 8 \ 85 | (uint8_t)(Lo) )) 86 #define RT_LOBYTE(a) ( (a) & 0xff ) 87 #define RT_HIBYTE(a) ( (a) >> 8 ) 65 88 66 89 #define VINF_SUCCESS 0 67 #define VERR_NO_MEMORY (-8) 68 #define VERR_NOT_SUPPORTED (-37) 69 #define VERR_ACCESS_DENIED (-38) 90 #define VERR_NO_MEMORY (-8) 91 #define VERR_UNRESOLVED_ERROR (-35) 92 #define VERR_NOT_SUPPORTED (-37) 93 #define VERR_ACCESS_DENIED (-38) 70 94 #define VERR_VUSB_USBFS_PERMISSION (-2005) 95 96 static inline int RTErrConvertFromErrno(int iErrno) 97 { 98 return iErrno == 0 ? VINF_SUCCESS 99 : iErrno == ENOMEM ? VERR_NO_MEMORY 100 : iErrno == ENODEV ? VERR_NOT_SUPPORTED 101 : iErrno == ENOSYS ? VERR_NOT_SUPPORTED 102 : iErrno == EPERM ? VERR_ACCESS_DENIED 103 : iErrno == EACCES ? VERR_ACCESS_DENIED 104 : VERR_UNRESOLVED_ERROR; 105 } 71 106 72 107 #define RT_SUCCESS(_rc) ((_rc) >= 0) … … 101 136 #define NOREF(_a) ((void)_a) 102 137 103 static inline int RTCritSectInit (RTCRITSECT *pCritSect) 104 { 105 return VINF_SUCCESS; 106 } 107 108 static inline int RTCritSectDelete (RTCRITSECT *pCritSect) 109 { 110 return VINF_SUCCESS; 111 } 112 113 static inline int RTCritSectEnter (RTCRITSECT *pCritSect) 114 { 115 return VINF_SUCCESS; 116 } 117 118 static inline int RTCritSectLeave (RTCRITSECT *pCritSect) 119 { 120 return VINF_SUCCESS; 121 } 122 123 static inline void *RTMemDupEx (const void *pvSrc, size_t cbSrc, size_t cbExtra) 124 { 125 void *p = RTMemAlloc (cbSrc + cbExtra); 126 127 if (p) 128 { 129 memcpy (p, pvSrc, cbSrc); 130 memset ((char *)p + cbSrc, 0, cbExtra); 131 } 132 133 return p; 134 } 135 136 static inline void *RTMemAllocZ (size_t cb) 137 { 138 void *p = RTMemAlloc (cb); 139 140 if (p) 141 { 142 memset (p, 0, cb); 143 } 144 145 return p; 146 } 147 148 static inline int RTStrToUInt32Ex (const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32) 149 { 150 *pu32 = strtoul (pszValue, ppszNext, uBase); 151 return VINF_SUCCESS; 152 } 153 154 #define PRTSTREAM FILE * 155 156 static inline int RTStrmOpen (const char *pszFileName, const char *pszMode, PRTSTREAM *ppStream) 157 { 158 *ppStream = fopen (pszFileName, pszMode); 159 160 if (*ppStream) 161 { 162 return VINF_SUCCESS; 163 } 164 165 return VERR_NOT_SUPPORTED; 166 } 167 168 static inline int RTStrmClose (PRTSTREAM pStream) 169 { 170 fclose (pStream); 171 return VINF_SUCCESS; 172 } 173 174 static inline int RTStrmGetLine (PRTSTREAM pStream, char *pszString, size_t cchString) 175 { 176 if (fgets (pszString, cchString, pStream)) 177 { 178 return VINF_SUCCESS; 179 } 180 181 return VERR_NOT_SUPPORTED; 182 } 183 184 static inline char *RTStrStripL (const char *psz) 185 { 186 while (isspace (*psz)) 187 psz++; 188 return (char *)psz; 189 } 190 191 #define NIL_RTFILE -1 192 193 #define RTFILE_O_READWRITE 0x00000003 194 #define RTFILE_O_OPEN 0x00000000 195 #define RTFILE_O_DENY_NONE 0x00000000 196 197 static inline int RTFileOpen (RTFILE *pFile, const char *pszFileName, unsigned fOpen) 198 { 199 Assert (fOpen == RTFILE_O_READWRITE); 200 201 *pFile = open (pszFileName, O_RDWR, 00600); 202 203 if (*pFile != -1) 204 { 205 return VINF_SUCCESS; 206 } 207 208 return VERR_ACCESS_DENIED; 209 } 210 211 static inline int RTFileClose (RTFILE file) 212 { 213 close (file); 214 return VINF_SUCCESS; 215 } 138 #define RT_C_DECLS_BEGIN 139 #define RT_C_DECLS_END 140 141 #define RTCALL 142 #define DECLR3CALLBACKMEMBER(type, name, args) type (RTCALL * name) args 143 #define DECLINLINE(type) static __inline__ type 144 #define DECLCALLBACK(type) type RTCALL 145 #define DECLCALLBACKMEMBER(type, name) type (RTCALL * name) 146 #define RTDECL(type) RTCALL type 147 148 #define RT_BIT(bit) ( 1U << (bit) ) 149 #define RT_MAX(Value1, Value2) ( (Value1) >= (Value2) ? (Value1) : (Value2) ) 150 #define RT_MIN(Value1, Value2) ( (Value1) <= (Value2) ? (Value1) : (Value2) ) 151 typedef uint32_t RTGCPHYS32; 152 typedef uint32_t RTMSINTERVAL; 216 153 217 154 static inline uint64_t RTTimeMilliTS (void) … … 223 160 } 224 161 225 #define VRDP_USB_STATUS_SUCCESS 0 226 #define VRDP_USB_STATUS_ACCESS_DENIED 1 227 #define VRDP_USB_STATUS_DEVICE_REMOVED 2 228 229 #define VRDP_USB_REAP_FLAG_CONTINUED (0) 230 #define VRDP_USB_REAP_FLAG_LAST (1) 231 232 #define VRDP_USB_CAPS_FLAG_ASYNC (0) 233 #define VRDP_USB_CAPS_FLAG_POLL (1) 234 235 #pragma pack(1) 236 237 #include "vusb.h" 238 239 typedef struct VUSBDEV 240 { 241 char* pszName; 242 int request_detach; 243 } VUSBDEV, *PVUSBDEV; 244 245 typedef struct usb_proxy { 246 /* Note: the backend code assumes that the dev member is the first in the structure. */ 247 VUSBDEV Dev; 248 /* 'union' because backend accesses the file handle as priv.File. */ 249 union { 250 void *pv; 251 int File; 252 } Backend; 253 254 struct usb_proxy *next; 255 struct usb_proxy *prev; 256 257 uint32_t devid; 258 259 PVUSBURB urbs; 260 261 int iActiveCfg; 262 int cIgnoreSetConfigs; 263 } *PUSBPROXYDEV; 264 265 typedef struct vusb_setup { 266 uint8_t bmRequestType; 267 uint8_t bRequest; 268 uint16_t wValue; 269 uint16_t wIndex; 270 uint16_t wLength; 271 } VUSBSETUP, *PVUSBSETUP; 272 #pragma pack() 273 274 275 static inline void vusbDevUnplugged(PVUSBDEV dev) 276 { 277 dev->request_detach = 1; 278 } 279 280 int dev2fd (PUSBPROXYDEV pProxyDev); 281 282 283 typedef struct USBPROXYBACK 284 { 285 /** Name of the backend. */ 286 const char *pszName; 287 288 int (* pfnOpen)(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend); 289 void (* pfnClose)(PUSBPROXYDEV pProxyDev); 290 int (* pfnReset)(PUSBPROXYDEV pProxyDev); 291 int (* pfnSetConfig)(PUSBPROXYDEV pProxyDev, int iCfg); 292 int (* pfnClaimInterface)(PUSBPROXYDEV pProxyDev, int iIf); 293 int (* pfnReleaseInterface)(PUSBPROXYDEV pProxyDev, int iIf); 294 int (* pfnSetInterface)(PUSBPROXYDEV pProxyDev, int iIf, int setting); 295 bool (* pfnClearHaltedEndpoint)(PUSBPROXYDEV pDev, unsigned int iEp); 296 int (* pfnUrbQueue)(PVUSBURB urb); 297 void (* pfnUrbCancel)(PVUSBURB pUrb); 298 PVUSBURB (* pfnUrbReap)(PUSBPROXYDEV pProxyDev, unsigned cMillies); 299 uint32_t uDummy; 300 } USBPROXYBACK; 301 302 typedef USBPROXYBACK *PUSBPROXYBACK; 303 304 extern const USBPROXYBACK g_USBProxyDeviceHost; 305 306 static inline int op_usbproxy_back_open(struct usb_proxy *p, const char *pszAddress) 307 { 308 return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL); 309 } 310 311 static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev) 312 { 313 return g_USBProxyDeviceHost.pfnClose (pDev); 314 } 315 316 static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev) 317 { 318 return g_USBProxyDeviceHost.pfnReset (pDev); 319 } 320 321 static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg) 322 { 323 return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg); 324 } 325 326 static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum) 327 { 328 return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum); 329 } 330 331 static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum) 332 { 333 return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum); 334 } 335 336 static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting) 337 { 338 return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting); 339 } 340 341 static inline int op_usbproxy_back_queue_urb(PVUSBURB pUrb) 342 { 343 return g_USBProxyDeviceHost.pfnUrbQueue(pUrb); 344 } 345 346 static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies) 347 { 348 return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies); 349 } 350 351 static inline bool op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint) 352 { 353 return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint); 354 } 355 356 static inline void op_usbproxy_back_cancel_urb(PVUSBURB pUrb) 357 { 358 return g_USBProxyDeviceHost.pfnUrbCancel (pUrb); 359 } 360 361 #endif /* __VRDPUSB__H */ 162 static inline int RTCritSectInit (RTCRITSECT *pCritSect) 163 { 164 return VINF_SUCCESS; 165 } 166 167 static inline int RTCritSectDelete (RTCRITSECT *pCritSect) 168 { 169 return VINF_SUCCESS; 170 } 171 172 static inline int RTCritSectEnter (RTCRITSECT *pCritSect) 173 { 174 return VINF_SUCCESS; 175 } 176 177 static inline int RTCritSectLeave (RTCRITSECT *pCritSect) 178 { 179 return VINF_SUCCESS; 180 } 181 182 static inline void *RTMemDupEx (const void *pvSrc, size_t cbSrc, size_t cbExtra) 183 { 184 void *p = RTMemAlloc (cbSrc + cbExtra); 185 186 if (p) 187 { 188 memcpy (p, pvSrc, cbSrc); 189 memset ((char *)p + cbSrc, 0, cbExtra); 190 } 191 192 return p; 193 } 194 195 static inline void *RTMemAllocZ (size_t cb) 196 { 197 void *p = RTMemAlloc (cb); 198 199 if (p) 200 { 201 memset (p, 0, cb); 202 } 203 204 return p; 205 } 206 207 static inline void *RTMemAllocZVar (size_t cbUnaligned) 208 { 209 return RTMemAllocZ(cbUnaligned); 210 } 211 212 static inline int RTStrToUInt32Ex (const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32) 213 { 214 *pu32 = strtoul (pszValue, ppszNext, uBase); 215 return VINF_SUCCESS; 216 } 217 218 #define PRTSTREAM FILE * 219 220 static inline int RTStrmOpen (const char *pszFileName, const char *pszMode, PRTSTREAM *ppStream) 221 { 222 *ppStream = fopen (pszFileName, pszMode); 223 224 if (*ppStream) 225 { 226 return VINF_SUCCESS; 227 } 228 229 return VERR_NOT_SUPPORTED; 230 } 231 232 static inline int RTStrmClose (PRTSTREAM pStream) 233 { 234 fclose (pStream); 235 return VINF_SUCCESS; 236 } 237 238 static inline int RTStrmGetLine (PRTSTREAM pStream, char *pszString, size_t cchString) 239 { 240 if (fgets (pszString, cchString, pStream)) 241 { 242 return VINF_SUCCESS; 243 } 244 245 return VERR_NOT_SUPPORTED; 246 } 247 248 static inline char *RTStrStripL (const char *psz) 249 { 250 while (isspace (*psz)) 251 psz++; 252 return (char *)psz; 253 } 254 255 #define NIL_RTFILE -1 256 257 #define RTFILE_O_READWRITE 0x00000003 258 #define RTFILE_O_OPEN 0x00000000 259 #define RTFILE_O_DENY_NONE 0x00000000 260 261 static inline int RTFileOpen (RTFILE *pFile, const char *pszFileName, unsigned fOpen) 262 { 263 Assert (fOpen == RTFILE_O_READWRITE); 264 265 *pFile = open (pszFileName, O_RDWR, 00600); 266 267 if (*pFile != -1) 268 { 269 return VINF_SUCCESS; 270 } 271 272 return VERR_ACCESS_DENIED; 273 } 274 275 static inline int RTFileClose (RTFILE file) 276 { 277 close (file); 278 return VINF_SUCCESS; 279 } 280 #endif /* __RUNTIME__H */ -
trunk/src/VBox/RDP/client/vrdp/vrdpusb.h
r28800 r31247 18 18 #define __VRDPUSB__H 19 19 20 #include <endian.h>21 #include <byteswap.h>22 23 #ifndef cpu_to_le1624 #if __BYTE_ORDER == __LITTLE_ENDIAN25 #define cpu_to_le16(_le16) (_le16)26 #elif __BYTE_ORDER == __BIG_ENDIAN27 #define cpu_to_le16(_le16) bswap_16(_le16)28 #else29 #error Unsupported host byte order!30 #endif31 #endif /* cpu_to_le16 */32 33 //#include <asm/byteorder.h>34 //#define cpu_to_le16 __cpu_to_le1635 36 #define uint8_t uint837 #define uint16_t uint1638 #define uint32_t uint3239 #define uint64_t long long40 #define bool int41 #define false 042 #define true 143 44 #define OPSTATIC45 #ifdef RDPUSB_DEBUG46 #define LogFlow(a) printf a47 #define Log(a) printf a48 #define Log2(a) printf a49 #else50 #define LogFlow(a) do {} while (0)51 #define Log(a) do {} while (0)52 #define Log2(a) do {} while (0)53 #endif54 55 #define LogRel(a) printf a56 57 /* Runtime wrappers. */58 #define RTMemAlloc xmalloc59 #define RTMemRealloc xrealloc60 #define RTMemFree xfree61 62 #define _1K 102463 64 #define RT_LE2H_U16(_le16) (cpu_to_le16 (_le16))65 66 #define VINF_SUCCESS 067 #define VERR_NO_MEMORY (-8)68 #define VERR_NOT_SUPPORTED (-37)69 #define VERR_ACCESS_DENIED (-38)70 #define VERR_VUSB_USBFS_PERMISSION (-2005)71 72 #define RT_SUCCESS(_rc) ((_rc) >= 0)73 74 #define RTFILE int75 #define RTCRITSECT void *76 77 #define Assert(_expr) do { \78 if (!(_expr)) \79 { \80 Log(("Assertion failed: {%s}!!!\n", #_expr)); \81 } \82 } while (0)83 84 #define AssertMsgFailed(_msg) do { \85 Log(("Assertion failed msg:!!!\n")); \86 Log(_msg); \87 } while (0)88 89 #define AssertReturn(_expr, _retval) do { \90 if (!(_expr)) \91 { \92 Log(("Assertion failed: {%s}, returning 0x%08X!!!\n", #_expr, _retval)); \93 return (_retval); \94 } \95 } while (0)96 97 #define AssertRC(_rc) Assert(RT_SUCCESS(_rc))98 99 #define RT_FAILURE(_rc) (!RT_SUCCESS(_rc))100 101 #define NOREF(_a) ((void)_a)102 103 static inline int RTCritSectInit (RTCRITSECT *pCritSect)104 {105 return VINF_SUCCESS;106 }107 108 static inline int RTCritSectDelete (RTCRITSECT *pCritSect)109 {110 return VINF_SUCCESS;111 }112 113 static inline int RTCritSectEnter (RTCRITSECT *pCritSect)114 {115 return VINF_SUCCESS;116 }117 118 static inline int RTCritSectLeave (RTCRITSECT *pCritSect)119 {120 return VINF_SUCCESS;121 }122 123 static inline void *RTMemDupEx (const void *pvSrc, size_t cbSrc, size_t cbExtra)124 {125 void *p = RTMemAlloc (cbSrc + cbExtra);126 127 if (p)128 {129 memcpy (p, pvSrc, cbSrc);130 memset ((char *)p + cbSrc, 0, cbExtra);131 }132 133 return p;134 }135 136 static inline void *RTMemAllocZ (size_t cb)137 {138 void *p = RTMemAlloc (cb);139 140 if (p)141 {142 memset (p, 0, cb);143 }144 145 return p;146 }147 148 static inline int RTStrToUInt32Ex (const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)149 {150 *pu32 = strtoul (pszValue, ppszNext, uBase);151 return VINF_SUCCESS;152 }153 154 #define PRTSTREAM FILE *155 156 static inline int RTStrmOpen (const char *pszFileName, const char *pszMode, PRTSTREAM *ppStream)157 {158 *ppStream = fopen (pszFileName, pszMode);159 160 if (*ppStream)161 {162 return VINF_SUCCESS;163 }164 165 return VERR_NOT_SUPPORTED;166 }167 168 static inline int RTStrmClose (PRTSTREAM pStream)169 {170 fclose (pStream);171 return VINF_SUCCESS;172 }173 174 static inline int RTStrmGetLine (PRTSTREAM pStream, char *pszString, size_t cchString)175 {176 if (fgets (pszString, cchString, pStream))177 {178 return VINF_SUCCESS;179 }180 181 return VERR_NOT_SUPPORTED;182 }183 184 static inline char *RTStrStripL (const char *psz)185 {186 while (isspace (*psz))187 psz++;188 return (char *)psz;189 }190 191 #define NIL_RTFILE -1192 193 #define RTFILE_O_READWRITE 0x00000003194 #define RTFILE_O_OPEN 0x00000000195 #define RTFILE_O_DENY_NONE 0x00000000196 197 static inline int RTFileOpen (RTFILE *pFile, const char *pszFileName, unsigned fOpen)198 {199 Assert (fOpen == RTFILE_O_READWRITE);200 201 *pFile = open (pszFileName, O_RDWR, 00600);202 203 if (*pFile != -1)204 {205 return VINF_SUCCESS;206 }207 208 return VERR_ACCESS_DENIED;209 }210 211 static inline int RTFileClose (RTFILE file)212 {213 close (file);214 return VINF_SUCCESS;215 }216 217 static inline uint64_t RTTimeMilliTS (void)218 {219 struct timeval tv;220 gettimeofday (&tv, NULL);221 return (uint64_t)tv.tv_sec * (uint64_t)(1000)222 + (uint64_t)(tv.tv_usec / 1000);223 }224 225 20 #define VRDP_USB_STATUS_SUCCESS 0 226 21 #define VRDP_USB_STATUS_ACCESS_DENIED 1 … … 233 28 #define VRDP_USB_CAPS_FLAG_POLL (1) 234 29 235 #pragma pack(1)236 237 #include "vusb.h"238 239 typedef struct VUSBDEV240 {241 char* pszName;242 int request_detach;243 } VUSBDEV, *PVUSBDEV;244 245 typedef struct usb_proxy {246 /* Note: the backend code assumes that the dev member is the first in the structure. */247 VUSBDEV Dev;248 /* 'union' because backend accesses the file handle as priv.File. */249 union {250 void *pv;251 int File;252 } Backend;253 254 struct usb_proxy *next;255 struct usb_proxy *prev;256 257 uint32_t devid;258 259 PVUSBURB urbs;260 261 int iActiveCfg;262 int cIgnoreSetConfigs;263 } *PUSBPROXYDEV;264 265 typedef struct vusb_setup {266 uint8_t bmRequestType;267 uint8_t bRequest;268 uint16_t wValue;269 uint16_t wIndex;270 uint16_t wLength;271 } VUSBSETUP, *PVUSBSETUP;272 #pragma pack()273 274 275 static inline void vusbDevUnplugged(PVUSBDEV dev)276 {277 dev->request_detach = 1;278 }279 280 int dev2fd (PUSBPROXYDEV pProxyDev);281 282 283 typedef struct USBPROXYBACK284 {285 /** Name of the backend. */286 const char *pszName;287 288 int (* pfnOpen)(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend);289 void (* pfnClose)(PUSBPROXYDEV pProxyDev);290 int (* pfnReset)(PUSBPROXYDEV pProxyDev);291 int (* pfnSetConfig)(PUSBPROXYDEV pProxyDev, int iCfg);292 int (* pfnClaimInterface)(PUSBPROXYDEV pProxyDev, int iIf);293 int (* pfnReleaseInterface)(PUSBPROXYDEV pProxyDev, int iIf);294 int (* pfnSetInterface)(PUSBPROXYDEV pProxyDev, int iIf, int setting);295 bool (* pfnClearHaltedEndpoint)(PUSBPROXYDEV pDev, unsigned int iEp);296 int (* pfnUrbQueue)(PVUSBURB urb);297 void (* pfnUrbCancel)(PVUSBURB pUrb);298 PVUSBURB (* pfnUrbReap)(PUSBPROXYDEV pProxyDev, unsigned cMillies);299 uint32_t uDummy;300 } USBPROXYBACK;301 302 typedef USBPROXYBACK *PUSBPROXYBACK;303 304 extern const USBPROXYBACK g_USBProxyDeviceHost;305 306 static inline int op_usbproxy_back_open(struct usb_proxy *p, const char *pszAddress)307 {308 return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL);309 }310 311 static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev)312 {313 return g_USBProxyDeviceHost.pfnClose (pDev);314 }315 316 static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev)317 {318 return g_USBProxyDeviceHost.pfnReset (pDev);319 }320 321 static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg)322 {323 return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg);324 }325 326 static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum)327 {328 return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum);329 }330 331 static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum)332 {333 return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum);334 }335 336 static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting)337 {338 return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting);339 }340 341 static inline int op_usbproxy_back_queue_urb(PVUSBURB pUrb)342 {343 return g_USBProxyDeviceHost.pfnUrbQueue(pUrb);344 }345 346 static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies)347 {348 return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies);349 }350 351 static inline bool op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint)352 {353 return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint);354 }355 356 static inline void op_usbproxy_back_cancel_urb(PVUSBURB pUrb)357 {358 return g_USBProxyDeviceHost.pfnUrbCancel (pUrb);359 }360 361 30 #endif /* __VRDPUSB__H */ -
trunk/src/VBox/RDP/client/vrdp/vusb.h
r28800 r31247 1 1 /** @file 2 * 2 * VUSB - VirtualBox USB. (DEV,VMM) 3 3 */ 4 4 … … 13 13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 14 14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 */ 15 * 16 * The contents of this file may alternatively be used under the terms 17 * of the Common Development and Distribution License Version 1.0 18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 19 * VirtualBox OSE distribution, in which case the provisions of the 20 * CDDL are applicable instead of those of the GPL. 21 * 22 * You may elect to license modified versions of this file under the 23 * terms and conditions of either the GPL or the CDDL or both. 24 */ 25 26 #ifndef ___VBox_vusb_h 27 #define ___VBox_vusb_h 28 29 #ifndef RDESKTOP 30 # include <VBox/cdefs.h> 31 # include <VBox/types.h> 32 #else 33 # include "runtime.h" 34 #endif 35 36 RT_C_DECLS_BEGIN 37 38 /** @defgroup grp_vusb VBox USB API 39 * @{ 40 */ 41 42 /** @defgroup grp_vusb_std Standard Stuff 43 * @{ */ 44 45 /** Frequency of USB bus (from spec). */ 46 #define VUSB_BUS_HZ 12000000 47 48 49 /** @name USB Descriptor types (from spec) 50 * @{ */ 51 #define VUSB_DT_DEVICE 0x01 52 #define VUSB_DT_CONFIG 0x02 53 #define VUSB_DT_STRING 0x03 54 #define VUSB_DT_INTERFACE 0x04 55 #define VUSB_DT_ENDPOINT 0x05 56 #define VUSB_DT_DEVICE_QUALIFIER 0x06 57 #define VUSB_DT_OTHER_SPEED_CFG 0x07 58 #define VUSB_DT_INTERFACE_POWER 0x08 59 /** @} */ 60 61 /** @name USB Descriptor minimum sizes (from spec) 62 * @{ */ 63 #define VUSB_DT_DEVICE_MIN_LEN 18 64 #define VUSB_DT_CONFIG_MIN_LEN 9 65 #define VUSB_DT_CONFIG_STRING_MIN_LEN 2 66 #define VUSB_DT_INTERFACE_MIN_LEN 9 67 #define VUSB_DT_ENDPOINT_MIN_LEN 7 68 /** @} */ 69 70 71 #pragma pack(1) /* ensure byte packing of the descriptors. */ 72 73 /** 74 * USB language id descriptor (from specs). 75 */ 76 typedef struct VUSBDESCLANGID 77 { 78 uint8_t bLength; 79 uint8_t bDescriptorType; 80 } VUSBDESCLANGID; 81 /** Pointer to a USB language id descriptor. */ 82 typedef VUSBDESCLANGID *PVUSBDESCLANGID; 83 /** Pointer to a const USB language id descriptor. */ 84 typedef const VUSBDESCLANGID *PCVUSBDESCLANGID; 85 86 87 /** 88 * USB string descriptor (from specs). 89 */ 90 typedef struct VUSBDESCSTRING 91 { 92 uint8_t bLength; 93 uint8_t bDescriptorType; 94 } VUSBDESCSTRING; 95 /** Pointer to a USB string descriptor. */ 96 typedef VUSBDESCSTRING *PVUSBDESCSTRING; 97 /** Pointer to a const USB string descriptor. */ 98 typedef const VUSBDESCSTRING *PCVUSBDESCSTRING; 99 100 101 /** 102 * USB device descriptor (from spec) 103 */ 104 typedef struct VUSBDESCDEVICE 105 { 106 uint8_t bLength; 107 uint8_t bDescriptorType; 108 uint16_t bcdUSB; 109 uint8_t bDeviceClass; 110 uint8_t bDeviceSubClass; 111 uint8_t bDeviceProtocol; 112 uint8_t bMaxPacketSize0; 113 uint16_t idVendor; 114 uint16_t idProduct; 115 uint16_t bcdDevice; 116 uint8_t iManufacturer; 117 uint8_t iProduct; 118 uint8_t iSerialNumber; 119 uint8_t bNumConfigurations; 120 } VUSBDESCDEVICE; 121 /** Pointer to a USB device descriptor. */ 122 typedef VUSBDESCDEVICE *PVUSBDESCDEVICE; 123 /** Pointer to a const USB device descriptor. */ 124 typedef const VUSBDESCDEVICE *PCVUSBDESCDEVICE; 125 126 127 /** 128 * USB configuration descriptor (from spec). 129 */ 130 typedef struct VUSBDESCCONFIG 131 { 132 uint8_t bLength; 133 uint8_t bDescriptorType; 134 uint16_t wTotalLength; /**< recalculated by VUSB when involved in URB. */ 135 uint8_t bNumInterfaces; 136 uint8_t bConfigurationValue; 137 uint8_t iConfiguration; 138 uint8_t bmAttributes; 139 uint8_t MaxPower; 140 } VUSBDESCCONFIG; 141 /** Pointer to a USB configuration descriptor. */ 142 typedef VUSBDESCCONFIG *PVUSBDESCCONFIG; 143 /** Pointer to a readonly USB configuration descriptor. */ 144 typedef const VUSBDESCCONFIG *PCVUSBDESCCONFIG; 145 146 147 /** 148 * USB interface descriptor (from spec) 149 */ 150 typedef struct VUSBDESCINTERFACE 151 { 152 uint8_t bLength; 153 uint8_t bDescriptorType; 154 uint8_t bInterfaceNumber; 155 uint8_t bAlternateSetting; 156 uint8_t bNumEndpoints; 157 uint8_t bInterfaceClass; 158 uint8_t bInterfaceSubClass; 159 uint8_t bInterfaceProtocol; 160 uint8_t iInterface; 161 } VUSBDESCINTERFACE; 162 /** Pointer to an USB interface descriptor. */ 163 typedef VUSBDESCINTERFACE *PVUSBDESCINTERFACE; 164 /** Pointer to a const USB interface descriptor. */ 165 typedef const VUSBDESCINTERFACE *PCVUSBDESCINTERFACE; 166 167 168 /** 169 * USB endpoint descriptor (from spec) 170 */ 171 typedef struct VUSBDESCENDPOINT 172 { 173 uint8_t bLength; 174 uint8_t bDescriptorType; 175 uint8_t bEndpointAddress; 176 uint8_t bmAttributes; 177 uint16_t wMaxPacketSize; 178 uint8_t bInterval; 179 } VUSBDESCENDPOINT; 180 /** Pointer to an USB endpoint descriptor. */ 181 typedef VUSBDESCENDPOINT *PVUSBDESCENDPOINT; 182 /** Pointer to a const USB endpoint descriptor. */ 183 typedef const VUSBDESCENDPOINT *PCVUSBDESCENDPOINT; 184 185 #pragma pack() /* end of the byte packing. */ 186 187 188 /** 189 * USB configuration descriptor, the parsed variant used by VUSB. 190 */ 191 typedef struct VUSBDESCCONFIGEX 192 { 193 /** The USB descriptor data. 194 * @remark The wTotalLength member is recalculated before the data is passed to the guest. */ 195 VUSBDESCCONFIG Core; 196 /** Pointer to additional descriptor bytes following what's covered by VUSBDESCCONFIG. */ 197 void *pvMore; 198 /** Pointer to an array of the interfaces referenced in the configuration. 199 * Core.bNumInterfaces in size. */ 200 const struct VUSBINTERFACE *paIfs; 201 } VUSBDESCCONFIGEX; 202 /** Pointer to a parsed USB configuration descriptor. */ 203 typedef VUSBDESCCONFIGEX *PVUSBDESCCONFIGEX; 204 /** Pointer to a const parsed USB configuration descriptor. */ 205 typedef const VUSBDESCCONFIGEX *PCVUSBDESCCONFIGEX; 206 207 208 /** 209 * For tracking the alternate interface settings of a configuration. 210 */ 211 typedef struct VUSBINTERFACE 212 { 213 /** Pointer to an array of interfaces. */ 214 const struct VUSBDESCINTERFACEEX *paSettings; 215 /** The number of entries in the array. */ 216 uint32_t cSettings; 217 } VUSBINTERFACE; 218 /** Pointer to a VUSBINTERFACE. */ 219 typedef VUSBINTERFACE *PVUSBINTERFACE; 220 /** Pointer to a const VUSBINTERFACE. */ 221 typedef const VUSBINTERFACE *PCVUSBINTERFACE; 222 223 224 /** 225 * USB interface descriptor, the parsed variant used by VUSB. 226 */ 227 typedef struct VUSBDESCINTERFACEEX 228 { 229 /** The USB descriptor data. */ 230 VUSBDESCINTERFACE Core; 231 /** Pointer to additional descriptor bytes following what's covered by VUSBDESCINTERFACE. */ 232 const void *pvMore; 233 /** Pointer to additional class- or vendor-specific interface descriptors. */ 234 const void *pvClass; 235 /** Size of class- or vendor-specific descriptors. */ 236 uint16_t cbClass; 237 /** Pointer to an array of the endpoints referenced by the interface. 238 * Core.bNumEndpoints in size. */ 239 const struct VUSBDESCENDPOINTEX *paEndpoints; 240 } VUSBDESCINTERFACEEX; 241 /** Pointer to an prased USB interface descriptor. */ 242 typedef VUSBDESCINTERFACEEX *PVUSBDESCINTERFACEEX; 243 /** Pointer to a const parsed USB interface descriptor. */ 244 typedef const VUSBDESCINTERFACEEX *PCVUSBDESCINTERFACEEX; 245 246 247 /** 248 * USB endpoint descriptor, the parsed variant used by VUSB. 249 */ 250 typedef struct VUSBDESCENDPOINTEX 251 { 252 /** The USB descriptor data. 253 * @remark The wMaxPacketSize member is converted to native endian. */ 254 VUSBDESCENDPOINT Core; 255 /** Pointer to additional descriptor bytes following what's covered by VUSBDESCENDPOINT. */ 256 const void *pvMore; 257 /** Pointer to additional class- or vendor-specific interface descriptors. */ 258 const void *pvClass; 259 /** Size of class- or vendor-specific descriptors. */ 260 uint16_t cbClass; 261 } VUSBDESCENDPOINTEX; 262 /** Pointer to a parsed USB endpoint descriptor. */ 263 typedef VUSBDESCENDPOINTEX *PVUSBDESCENDPOINTEX; 264 /** Pointer to a const parsed USB endpoint descriptor. */ 265 typedef const VUSBDESCENDPOINTEX *PCVUSBDESCENDPOINTEX; 266 267 268 /** @name USB Control message recipient codes (from spec) 269 * @{ */ 270 #define VUSB_TO_DEVICE 0x0 271 #define VUSB_TO_INTERFACE 0x1 272 #define VUSB_TO_ENDPOINT 0x2 273 #define VUSB_TO_OTHER 0x3 274 #define VUSB_RECIP_MASK 0x1f 275 /** @} */ 276 277 /** @name USB control pipe setup packet structure (from spec) 278 * @{ */ 279 #define VUSB_REQ_SHIFT (5) 280 #define VUSB_REQ_STANDARD (0x0 << VUSB_REQ_SHIFT) 281 #define VUSB_REQ_CLASS (0x1 << VUSB_REQ_SHIFT) 282 #define VUSB_REQ_VENDOR (0x2 << VUSB_REQ_SHIFT) 283 #define VUSB_REQ_RESERVED (0x3 << VUSB_REQ_SHIFT) 284 #define VUSB_REQ_MASK (0x3 << VUSB_REQ_SHIFT) 285 /** @} */ 286 287 #define VUSB_DIR_TO_DEVICE 0x00 288 #define VUSB_DIR_TO_HOST 0x80 289 #define VUSB_DIR_MASK 0x80 290 291 /** 292 * USB Setup request (from spec) 293 */ 294 typedef struct vusb_setup 295 { 296 uint8_t bmRequestType; 297 uint8_t bRequest; 298 uint16_t wValue; 299 uint16_t wIndex; 300 uint16_t wLength; 301 } VUSBSETUP; 302 /** Pointer to a setup request. */ 303 typedef VUSBSETUP *PVUSBSETUP; 304 /** Pointer to a const setup request. */ 305 typedef const VUSBSETUP *PCVUSBSETUP; 306 307 /** @name USB Standard device requests (from spec) 308 * @{ */ 309 #define VUSB_REQ_GET_STATUS 0x00 310 #define VUSB_REQ_CLEAR_FEATURE 0x01 311 #define VUSB_REQ_SET_FEATURE 0x03 312 #define VUSB_REQ_SET_ADDRESS 0x05 313 #define VUSB_REQ_GET_DESCRIPTOR 0x06 314 #define VUSB_REQ_SET_DESCRIPTOR 0x07 315 #define VUSB_REQ_GET_CONFIGURATION 0x08 316 #define VUSB_REQ_SET_CONFIGURATION 0x09 317 #define VUSB_REQ_GET_INTERFACE 0x0a 318 #define VUSB_REQ_SET_INTERFACE 0x0b 319 #define VUSB_REQ_SYNCH_FRAME 0x0c 320 #define VUSB_REQ_MAX 0x0d 321 /** @} */ 322 323 /** @} */ /* end of grp_vusb_std */ 324 325 326 327 /** @name USB Standard version flags. 328 * @{ */ 329 /** Indicates USB 1.1 support. */ 330 #define VUSB_STDVER_11 RT_BIT(1) 331 /** Indicates USB 2.0 support. */ 332 #define VUSB_STDVER_20 RT_BIT(2) 333 /** @} */ 334 16 335 17 336 /** Pointer to a VBox USB device interface. */ … … 25 344 26 345 346 347 /** 348 * VBox USB port bitmap. 349 * 350 * Bit 0 == Port 0, ... , Bit 127 == Port 127. 351 */ 352 typedef struct VUSBPORTBITMAP 353 { 354 /** 128 bits */ 355 char ach[16]; 356 } VUSBPORTBITMAP; 357 /** Pointer to a VBox USB port bitmap. */ 358 typedef VUSBPORTBITMAP *PVUSBPORTBITMAP; 359 360 #ifndef RDESKTOP 361 362 /** 363 * The VUSB RootHub port interface provided by the HCI (down). 364 * Pair with VUSBIROOTCONNECTOR 365 */ 366 typedef struct VUSBIROOTHUBPORT 367 { 368 /** 369 * Get the number of avilable ports in the hub. 370 * 371 * @returns The number of ports available. 372 * @param pInterface Pointer to this structure. 373 * @param pAvailable Bitmap indicating the available ports. Set bit == available port. 374 */ 375 DECLR3CALLBACKMEMBER(unsigned, pfnGetAvailablePorts,(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable)); 376 377 /** 378 * Gets the supported USB versions. 379 * 380 * @returns The mask of supported USB versions. 381 * @param pInterface Pointer to this structure. 382 */ 383 DECLR3CALLBACKMEMBER(uint32_t, pfnGetUSBVersions,(PVUSBIROOTHUBPORT pInterface)); 384 385 /** 386 * A device is being attached to a port in the roothub. 387 * 388 * @param pInterface Pointer to this structure. 389 * @param pDev Pointer to the device being attached. 390 * @param uPort The port number assigned to the device. 391 */ 392 DECLR3CALLBACKMEMBER(int, pfnAttach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort)); 393 394 /** 395 * A device is being detached from a port in the roothub. 396 * 397 * @param pInterface Pointer to this structure. 398 * @param pDev Pointer to the device being detached. 399 * @param uPort The port number assigned to the device. 400 */ 401 DECLR3CALLBACKMEMBER(void, pfnDetach,(PVUSBIROOTHUBPORT pInterface, PVUSBIDEVICE pDev, unsigned uPort)); 402 403 /** 404 * Reset the root hub. 405 * 406 * @returns VBox status code. 407 * @param pInterface Pointer to this structure. 408 * @param pResetOnLinux Whether or not to do real reset on linux. 409 */ 410 DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIROOTHUBPORT pInterface, bool fResetOnLinux)); 411 412 /** 413 * Transfer completion callback routine. 414 * 415 * VUSB will call this when a transfer have been completed 416 * in a one or another way. 417 * 418 * @param pInterface Pointer to this structure. 419 * @param pUrb Pointer to the URB in question. 420 */ 421 DECLR3CALLBACKMEMBER(void, pfnXferCompletion,(PVUSBIROOTHUBPORT pInterface, PVUSBURB urb)); 422 423 /** 424 * Handle transfer errors. 425 * 426 * VUSB calls this when a transfer attempt failed. This function will respond 427 * indicating wheter to retry or complete the URB with failure. 428 * 429 * @returns Retry indicator. 430 * @param pInterface Pointer to this structure. 431 * @param pUrb Pointer to the URB in question. 432 */ 433 DECLR3CALLBACKMEMBER(bool, pfnXferError,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb)); 434 435 /** Alignment dummy. */ 436 RTR3PTR Alignment; 437 438 } VUSBIROOTHUBPORT; 439 /** VUSBIROOTHUBPORT interface ID. */ 440 #define VUSBIROOTHUBPORT_IID "e38e2978-7aa2-4860-94b6-9ef4a066d8a0" 441 442 443 /** Pointer to a VUSB RootHub connector interface. */ 444 typedef struct VUSBIROOTHUBCONNECTOR *PVUSBIROOTHUBCONNECTOR; 445 /** 446 * The VUSB RootHub connector interface provided by the VBox USB RootHub driver 447 * (up). 448 * Pair with VUSBIROOTHUBPORT. 449 */ 450 typedef struct VUSBIROOTHUBCONNECTOR 451 { 452 /** 453 * Allocates a new URB for a transfer. 454 * 455 * Either submit using pfnSubmitUrb or free using VUSBUrbFree(). 456 * 457 * @returns Pointer to a new URB. 458 * @returns NULL on failure - try again later. 459 * This will not fail if the device wasn't found. We'll fail it 460 * at submit time, since that makes the usage of this api simpler. 461 * @param pInterface Pointer to this struct. 462 * @param DstAddress The destination address of the URB. 463 * @param cbData The amount of data space required. 464 * @param cTds The amount of TD space. 465 */ 466 DECLR3CALLBACKMEMBER(PVUSBURB, pfnNewUrb,(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t cbData, uint32_t cTds)); 467 468 /** 469 * Submits a URB for transfer. 470 * The transfer will do asynchronously if possible. 471 * 472 * @returns VBox status code. 473 * @param pInterface Pointer to this struct. 474 * @param pUrb Pointer to the URB returned by pfnNewUrb. 475 * The URB will be freed in case of failure. 476 * @param pLed Pointer to USB Status LED 477 */ 478 DECLR3CALLBACKMEMBER(int, pfnSubmitUrb,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed)); 479 480 /** 481 * Call to service asynchronous URB completions in a polling fashion. 482 * 483 * Reaped URBs will be finished by calling the completion callback, 484 * thus there is no return code or input or anything from this function 485 * except for potential state changes elsewhere. 486 * 487 * @returns VINF_SUCCESS if no URBs are pending upon return. 488 * @returns VERR_TIMEOUT if one or more URBs are still in flight upon returning. 489 * @returns Other VBox status code. 490 * 491 * @param pInterface Pointer to this struct. 492 * @param cMillies Number of milliseconds to poll for completion. 493 */ 494 DECLR3CALLBACKMEMBER(void, pfnReapAsyncUrbs,(PVUSBIROOTHUBCONNECTOR pInterface, RTMSINTERVAL cMillies)); 495 496 /** 497 * Cancels and completes - with CRC failure - all in-flight async URBs. 498 * This is typically done before saving a state. 499 * 500 * @param pInterface Pointer to this struct. 501 */ 502 DECLR3CALLBACKMEMBER(void, pfnCancelAllUrbs,(PVUSBIROOTHUBCONNECTOR pInterface)); 503 504 /** 505 * Attach the device to the root hub. 506 * The device must not be attached to any hub for this call to succeed. 507 * 508 * @returns VBox status code. 509 * @param pInterface Pointer to this struct. 510 * @param pDevice Pointer to the device (interface) attach. 511 */ 512 DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)); 513 514 /** 515 * Detach the device from the root hub. 516 * The device must already be attached for this call to succeed. 517 * 518 * @returns VBox status code. 519 * @param pInterface Pointer to this struct. 520 * @param pDevice Pointer to the device (interface) to detach. 521 */ 522 DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice)); 523 524 } VUSBIROOTHUBCONNECTOR; 525 /** VUSBIROOTHUBCONNECTOR interface ID. */ 526 #define VUSBIROOTHUBCONNECTOR_IID "d9a90c59-e3ff-4dff-9754-844557c3f7a0" 527 528 529 #ifdef IN_RING3 530 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnNewUrb */ 531 DECLINLINE(PVUSBURB) VUSBIRhNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t DstAddress, uint32_t cbData, uint32_t cTds) 532 { 533 return pInterface->pfnNewUrb(pInterface, DstAddress, cbData, cTds); 534 } 535 536 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnSubmitUrb */ 537 DECLINLINE(int) VUSBIRhSubmitUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed) 538 { 539 return pInterface->pfnSubmitUrb(pInterface, pUrb, pLed); 540 } 541 542 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnReapAsyncUrbs */ 543 DECLINLINE(void) VUSBIRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, RTMSINTERVAL cMillies) 544 { 545 pInterface->pfnReapAsyncUrbs(pInterface, cMillies); 546 } 547 548 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnCancelAllUrbs */ 549 DECLINLINE(void) VUSBIRhCancelAllUrbs(PVUSBIROOTHUBCONNECTOR pInterface) 550 { 551 pInterface->pfnCancelAllUrbs(pInterface); 552 } 553 554 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnAttachDevice */ 555 DECLINLINE(int) VUSBIRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice) 556 { 557 return pInterface->pfnAttachDevice(pInterface, pDevice); 558 } 559 560 /** @copydoc VUSBIROOTHUBCONNECTOR::pfnDetachDevice */ 561 DECLINLINE(int) VUSBIRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBIDEVICE pDevice) 562 { 563 return pInterface->pfnDetachDevice(pInterface, pDevice); 564 } 565 #endif /* IN_RING3 */ 566 567 568 569 /** Pointer to a Root Hub Configuration Interface. */ 570 typedef struct VUSBIRHCONFIG *PVUSBIRHCONFIG; 571 /** 572 * Root Hub Configuration Interface (intended for MAIN). 573 * No interface pair. 574 */ 575 typedef struct VUSBIRHCONFIG 576 { 577 /** 578 * Creates a USB proxy device and attaches it to the root hub. 579 * 580 * @returns VBox status code. 581 * @param pInterface Pointer to the root hub configuration interface structure. 582 * @param pUuid Pointer to the UUID for the new device. 583 * @param fRemote Whether the device must use the VRDP backend. 584 * @param pszAddress OS specific device address. 585 * @param pvBackend An opaque pointer for the backend. Only used by 586 * the VRDP backend so far. 587 */ 588 DECLR3CALLBACKMEMBER(int, pfnCreateProxyDevice,(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend)); 589 590 /** 591 * Removes a USB proxy device from the root hub and destroys it. 592 * 593 * @returns VBox status code. 594 * @param pInterface Pointer to the root hub configuration interface structure. 595 * @param pUuid Pointer to the UUID for the device. 596 */ 597 DECLR3CALLBACKMEMBER(int, pfnDestroyProxyDevice,(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid)); 598 599 } VUSBIRHCONFIG; 600 /** VUSBIRHCONFIG interface ID. */ 601 #define VUSBIRHCONFIG_IID "c354cd97-e85f-465e-bc12-b58798465f52" 602 603 604 #ifdef IN_RING3 605 /** @copydoc VUSBIRHCONFIG::pfnCreateProxyDevice */ 606 DECLINLINE(int) VUSBIRhCreateProxyDevice(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend) 607 { 608 return pInterface->pfnCreateProxyDevice(pInterface, pUuid, fRemote, pszAddress, pvBackend); 609 } 610 611 /** @copydoc VUSBIRHCONFIG::pfnDestroyProxyDevice */ 612 DECLINLINE(int) VUSBIRhDestroyProxyDevice(PVUSBIRHCONFIG pInterface, PCRTUUID pUuid) 613 { 614 return pInterface->pfnDestroyProxyDevice(pInterface, pUuid); 615 } 616 #endif /* IN_RING3 */ 617 618 #endif /* ! RDESKTOP */ 619 620 621 /** 622 * VUSB device reset completion callback function. 623 * This is called by the reset thread when the reset has been completed. 624 * 625 * @param pDev Pointer to the virtual USB device core. 626 * @param rc The VBox status code of the reset operation. 627 * @param pvUser User specific argument. 628 * 629 * @thread The reset thread or EMT. 630 */ 631 typedef DECLCALLBACK(void) FNVUSBRESETDONE(PVUSBIDEVICE pDevice, int rc, void *pvUser); 632 /** Pointer to a device reset completion callback function (FNUSBRESETDONE). */ 633 typedef FNVUSBRESETDONE *PFNVUSBRESETDONE; 634 635 /** 636 * The state of a VUSB Device. 637 * 638 * @remark The order of these states is vital. 639 */ 640 typedef enum VUSBDEVICESTATE 641 { 642 VUSB_DEVICE_STATE_INVALID = 0, 643 VUSB_DEVICE_STATE_DETACHED, 644 VUSB_DEVICE_STATE_ATTACHED, 645 VUSB_DEVICE_STATE_POWERED, 646 VUSB_DEVICE_STATE_DEFAULT, 647 VUSB_DEVICE_STATE_ADDRESS, 648 VUSB_DEVICE_STATE_CONFIGURED, 649 VUSB_DEVICE_STATE_SUSPENDED, 650 /** The device is being reset. Don't mess with it. 651 * Next states: VUSB_DEVICE_STATE_DEFAULT, VUSB_DEVICE_STATE_DESTROYED 652 */ 653 VUSB_DEVICE_STATE_RESET, 654 /** The device has been destroy. */ 655 VUSB_DEVICE_STATE_DESTROYED, 656 /** The usual 32-bit hack. */ 657 VUSB_DEVICE_STATE_32BIT_HACK = 0x7fffffff 658 } VUSBDEVICESTATE; 659 660 #ifndef RDESKTOP 661 662 /** 663 * USB Device Interface (up). 664 * No interface pair. 665 */ 666 typedef struct VUSBIDEVICE 667 { 668 /** 669 * Resets the device. 670 * 671 * Since a device reset shall take at least 10ms from the guest point of view, 672 * it must be performed asynchronously. We create a thread which performs this 673 * operation and ensures it will take at least 10ms. 674 * 675 * At times - like init - a synchronous reset is required, this can be done 676 * by passing NULL for pfnDone. 677 * 678 * -- internal stuff, move it -- 679 * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state. 680 * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful, 681 * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed. 682 * -- internal stuff, move it -- 683 * 684 * @returns VBox status code. 685 * @param pInterface Pointer to this structure. 686 * @param fResetOnLinux Set if we can permit a real reset and a potential logical 687 * device reconnect on linux hosts. 688 * @param pfnDone Pointer to the completion routine. If NULL a synchronous 689 * reset is preformed not respecting the 10ms. 690 * @param pvUser User argument to the completion routine. 691 * @param pVM Pointer to the VM handle if callback in EMT is required. (optional) 692 */ 693 DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIDEVICE pInterface, bool fResetOnLinux, 694 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)); 695 696 /** 697 * Powers on the device. 698 * 699 * @returns VBox status code. 700 * @param pInterface Pointer to the device interface structure. 701 */ 702 DECLR3CALLBACKMEMBER(int, pfnPowerOn,(PVUSBIDEVICE pInterface)); 703 704 /** 705 * Powers off the device. 706 * 707 * @returns VBox status code. 708 * @param pInterface Pointer to the device interface structure. 709 */ 710 DECLR3CALLBACKMEMBER(int, pfnPowerOff,(PVUSBIDEVICE pInterface)); 711 712 /** 713 * Get the state of the device. 714 * 715 * @returns Device state. 716 * @param pInterface Pointer to the device interface structure. 717 */ 718 DECLR3CALLBACKMEMBER(VUSBDEVICESTATE, pfnGetState,(PVUSBIDEVICE pInterface)); 719 720 } VUSBIDEVICE; 721 /** VUSBIDEVICE interface ID. */ 722 #define VUSBIDEVICE_IID "88732dd3-0ccd-4625-b040-48804ac7a217" 723 724 725 #ifdef IN_RING3 726 /** 727 * Resets the device. 728 * 729 * Since a device reset shall take at least 10ms from the guest point of view, 730 * it must be performed asynchronously. We create a thread which performs this 731 * operation and ensures it will take at least 10ms. 732 * 733 * At times - like init - a synchronous reset is required, this can be done 734 * by passing NULL for pfnDone. 735 * 736 * -- internal stuff, move it -- 737 * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state. 738 * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful, 739 * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed. 740 * -- internal stuff, move it -- 741 * 742 * @returns VBox status code. 743 * @param pInterface Pointer to the device interface structure. 744 * @param fResetOnLinux Set if we can permit a real reset and a potential logical 745 * device reconnect on linux hosts. 746 * @param pfnDone Pointer to the completion routine. If NULL a synchronous 747 * reset is preformed not respecting the 10ms. 748 * @param pvUser User argument to the completion routine. 749 * @param pVM Pointer to the VM handle if callback in EMT is required. (optional) 750 */ 751 DECLINLINE(int) VUSBIDevReset(PVUSBIDEVICE pInterface, bool fResetOnLinux, PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM) 752 { 753 return pInterface->pfnReset(pInterface, fResetOnLinux, pfnDone, pvUser, pVM); 754 } 755 756 /** 757 * Powers on the device. 758 * 759 * @returns VBox status code. 760 * @param pInterface Pointer to the device interface structure. 761 */ 762 DECLINLINE(int) VUSBIDevPowerOn(PVUSBIDEVICE pInterface) 763 { 764 return pInterface->pfnPowerOn(pInterface); 765 } 766 767 /** 768 * Powers off the device. 769 * 770 * @returns VBox status code. 771 * @param pInterface Pointer to the device interface structure. 772 */ 773 DECLINLINE(int) VUSBIDevPowerOff(PVUSBIDEVICE pInterface) 774 { 775 return pInterface->pfnPowerOff(pInterface); 776 } 777 778 /** 779 * Get the state of the device. 780 * 781 * @returns Device state. 782 * @param pInterface Pointer to the device interface structure. 783 */ 784 DECLINLINE(VUSBDEVICESTATE) VUSBIDevGetState(PVUSBIDEVICE pInterface) 785 { 786 return pInterface->pfnGetState(pInterface); 787 } 788 #endif /* IN_RING3 */ 789 790 #endif /* ! RDESKTOP */ 791 27 792 /** @name URB 28 793 * @{ */ … … 35 800 /** Transer was ok. */ 36 801 VUSBSTATUS_OK = 0, 37 #define VUSB_XFER_OK VUSBSTATUS_OK38 802 /** Transfer stalled, endpoint halted. */ 39 803 VUSBSTATUS_STALL, 40 #define VUSB_XFER_STALL VUSBSTATUS_STALL41 804 /** Device not responding. */ 42 805 VUSBSTATUS_DNR, 43 #define VUSB_XFER_DNR VUSBSTATUS_DNR44 806 /** CRC error. */ 45 807 VUSBSTATUS_CRC, 46 #define VUSB_XFER_CRC VUSBSTATUS_CRC 47 /** Underflow error. */ 48 VUSBSTATUS_UNDERFLOW, 808 /** Data overrun error. */ 809 VUSBSTATUS_DATA_UNDERRUN, 810 /** Data overrun error. */ 811 VUSBSTATUS_DATA_OVERRUN, 812 /** The isochronous buffer hasn't been touched. */ 813 VUSBSTATUS_NOT_ACCESSED, 49 814 /** Invalid status. */ 50 815 VUSBSTATUS_INVALID = 0x7f … … 59 824 /** Control message. Used to represent a single control transfer. */ 60 825 VUSBXFERTYPE_CTRL = 0, 61 #define VUSB_TRANSFER_TYPE_CTRL VUSBXFERTYPE_CTRL62 826 /* Isochronous transfer. */ 63 827 VUSBXFERTYPE_ISOC, 64 #define VUSB_TRANSFER_TYPE_ISOC VUSBXFERTYPE_ISOC65 828 /** Bulk transfer. */ 66 829 VUSBXFERTYPE_BULK, 67 #define VUSB_TRANSFER_TYPE_BULK VUSBXFERTYPE_BULK68 830 /** Interrupt transfer. */ 69 831 VUSBXFERTYPE_INTR, 70 #define VUSB_TRANSFER_TYPE_INTR VUSBXFERTYPE_INTR71 832 /** Complete control message. Used to represent an entire control message. */ 72 833 VUSBXFERTYPE_MSG, 73 #define VUSB_TRANSFER_TYPE_MSG VUSBXFERTYPE_MSG74 834 /** Invalid transfer type. */ 75 835 VUSBXFERTYPE_INVALID = 0x7f … … 90 850 /** Out - Host to device. */ 91 851 VUSBDIRECTION_OUT = 2, 92 #define VUSB_DIRECTION_OUT 852 #define VUSB_DIRECTION_OUT VUSBDIRECTION_OUT 93 853 /** Invalid direction */ 94 854 VUSBDIRECTION_INVALID = 0x7f … … 125 885 126 886 /** 887 * Information about a isochronous packet. 888 */ 889 typedef struct VUSBURBISOCPKT 890 { 891 /** The size of the packet. 892 * IN: The packet size. I.e. the number of bytes to the next packet or end of buffer. 893 * OUT: The actual size transfered. */ 894 uint16_t cb; 895 /** The offset of the packet. (Relative to VUSBURB::abData[0].) 896 * OUT: This can be changed by the USB device if it does some kind of buffer squeezing. */ 897 uint16_t off; 898 /** The status of the transfer. 899 * IN: VUSBSTATUS_INVALID 900 * OUT: VUSBSTATUS_INVALID if nothing was done, otherwise the correct status. */ 901 VUSBSTATUS enmStatus; 902 } VUSBURBISOCPKT; 903 /** Pointer to a isochronous packet. */ 904 typedef VUSBURBISOCPKT *PVUSBURBISOCPTK; 905 /** Pointer to a const isochronous packet. */ 906 typedef const VUSBURBISOCPKT *PCVUSBURBISOCPKT; 907 908 /** 127 909 * Asynchronous USB request descriptor 128 910 */ … … 133 915 /** The USR state. */ 134 916 VUSBURBSTATE enmState; 135 136 /* Private fields not accessed by the backend. */ 137 PVUSBURB next; 138 PVUSBURB prev; 917 /** URB description, can be null. intended for logging. */ 918 char *pszDesc; 919 920 #ifdef RDESKTOP 921 /** The next URB in rdesktop-vrdp's linked list */ 922 PVUSBURB pNext; 923 /** The previous URB in rdesktop-vrdp's linked list */ 924 PVUSBURB pPrev; 925 /** The vrdp handle for the URB */ 139 926 uint32_t handle; 927 /** Pointer used to find the usb proxy device */ 928 struct VUSBDEV *pDev; 929 #endif 140 930 141 931 /** The VUSB data. */ … … 148 938 /** Pointer to the original for control messages. */ 149 939 PVUSBURB pCtrlUrb; 940 /** Pointer to the VUSB device. 941 * This may be NULL if the destination address is invalid. */ 942 struct VUSBDEV *pDev; 150 943 /** Sepcific to the pfnFree function. */ 151 944 void *pvFreeCtx; 945 /** 946 * Callback which will free the URB once it's reaped and completed. 947 * @param pUrb The URB. 948 */ 949 DECLCALLBACKMEMBER(void, pfnFree)(PVUSBURB pUrb); 152 950 /** Submit timestamp. (logging only) */ 153 951 uint64_t u64SubmitTS; … … 162 960 { 163 961 /** The endpoint descriptor address. */ 164 uint32_tEdAddr;962 RTGCPHYS32 EdAddr; 165 963 /** Number of Tds in the array. */ 166 964 uint32_t cTds; … … 168 966 struct VUSBURBHCITD 169 967 { 968 /** Type of TD (private) */ 969 uint32_t TdType; 170 970 /** The address of the */ 171 uint32_tTdAddr;971 RTGCPHYS32 TdAddr; 172 972 /** A copy of the TD. */ 173 uint32_t TdCopy[ 4];973 uint32_t TdCopy[16]; 174 974 } *paTds; 175 975 /** URB chain pointer. */ 176 976 PVUSBURB pNext; 177 /** When this URB was created. (logging only) */ 977 /** When this URB was created. 978 * (Used for isochronous frames and for logging.) */ 178 979 uint32_t u32FrameNo; 179 980 /** Flag indicating that the TDs have been unlinked. */ … … 190 991 } Dev; 191 992 192 /** The device - can be NULL untill submit is attempted. 193 * This is set when allocating the URB. */ 194 struct VUSBDEV *pDev; 993 #ifndef RDESKTOP 994 /** The USB device instance this belongs to. 995 * This is NULL if the device address is invalid, in which case this belongs to the hub. */ 996 PPDMUSBINS pUsbIns; 997 #endif 195 998 /** The device address. 196 999 * This is set at allocation time. */ … … 198 1001 199 1002 /** The endpoint. 200 * IN: Must be set before submitting the URB. */ 1003 * IN: Must be set before submitting the URB. 1004 * @remark This does not have the high bit (direction) set! */ 201 1005 uint8_t EndPt; 202 1006 /** The transfer type. … … 212 1016 * OUT: This is set when reaping the URB. */ 213 1017 VUSBSTATUS enmStatus; 1018 1019 /** The number of isochronous packets describe in aIsocPkts. 1020 * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */ 1021 uint32_t cIsocPkts; 1022 /** The iso packets within abData. 1023 * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */ 1024 VUSBURBISOCPKT aIsocPkts[8]; 1025 214 1026 /** The message length. 215 1027 * IN: The amount of data to send / receive - set at allocation time. … … 223 1035 224 1036 /** The magic value of a valid VUSBURB. (Murakami Haruki) */ 225 #define VUSBURB_MAGIC 0x194901121037 #define VUSBURB_MAGIC UINT32_C(0x19490112) 226 1038 227 1039 /** @} */ 1040 1041 1042 /** @} */ 1043 1044 RT_C_DECLS_END 1045 1046 #endif
Note:
See TracChangeset
for help on using the changeset viewer.