Changeset 60147 in vbox for trunk/src/VBox/Main
- Timestamp:
- Mar 23, 2016 10:58:52 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/linux/USBGetDevices.cpp
r60146 r60147 5 5 6 6 /* 7 * Copyright (C) 2006-201 2Oracle Corporation7 * Copyright (C) 2006-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 102 102 103 103 /** 104 * "reads" the number suffix. It's more like validating it and 105 * skipping the necessary number of chars. 104 * "reads" the number suffix. 105 * 106 * It's more like validating it and skipping the necessary number of chars. 106 107 */ 107 108 static int usbReadSkipSuffix(char **ppszNext) … … 188 189 * Reads a USB number returning the number and the position of the next character to parse. 189 190 */ 190 static int usb ReadNum(const char *pszValue, unsigned uBase, uint32_t u32Mask, PCUSBSUFF paSuffs, void *pvNum, char **ppszNext)191 static int usbfsReadNum(const char *pszValue, unsigned uBase, uint32_t u32Mask, PCUSBSUFF paSuffs, void *pvNum, char **ppszNext) 191 192 { 192 193 /* … … 246 247 else 247 248 { 248 int rc = usb ReadSkipSuffix(&pszNext);249 int rc = usbfsReadSkipSuffix(&pszNext); 249 250 if (RT_FAILURE(rc)) 250 251 return rc; … … 267 268 268 269 269 static int usb Read8(const char *pszValue, unsigned uBase, uint8_t *pu8, char **ppszNext)270 { 271 return usb ReadNum(pszValue, uBase, 0xff, NULL, pu8, ppszNext);272 } 273 274 275 static int usb Read16(const char *pszValue, unsigned uBase, uint16_t *pu16, char **ppszNext)276 { 277 return usb ReadNum(pszValue, uBase, 0xffff, NULL, pu16, ppszNext);270 static int usbfsRead8(const char *pszValue, unsigned uBase, uint8_t *pu8, char **ppszNext) 271 { 272 return usbfsReadNum(pszValue, uBase, 0xff, NULL, pu8, ppszNext); 273 } 274 275 276 static int usbfsRead16(const char *pszValue, unsigned uBase, uint16_t *pu16, char **ppszNext) 277 { 278 return usbfsReadNum(pszValue, uBase, 0xffff, NULL, pu16, ppszNext); 278 279 } 279 280 … … 291 292 * The returned number contains the integer part in the high byte and the decimal part in the low byte. 292 293 */ 293 static int usb ReadBCD(const char *pszValue, unsigned uBase, uint16_t *pu16, char **ppszNext)294 static int usbfsReadBCD(const char *pszValue, unsigned uBase, uint16_t *pu16, char **ppszNext) 294 295 { 295 296 /* … … 341 342 * Validate and skip stuff following the number. 342 343 */ 343 int rc = usb ReadSkipSuffix(&pszNext);344 int rc = usbfsReadNum(&pszNext); 344 345 if (RT_FAILURE(rc)) 345 346 return rc; … … 362 363 * this usually goes unnoticed) then we mercilessly force it to be so. 363 364 */ 364 static int usb ReadStr(const char *pszValue, const char **ppsz)365 static int usbfsReadStr(const char *pszValue, const char **ppsz) 365 366 { 366 367 char *psz; … … 382 383 * Skips the current property. 383 384 */ 384 static char *usb ReadSkip(char *pszValue)385 static char *usbfsReadSkip(char *pszValue) 385 386 { 386 387 char *psz = strchr(pszValue, '='); … … 399 400 * Determine the USB speed. 400 401 */ 401 static int usb ReadSpeed(const char *pszValue, USBDEVICESPEED *pSpd, char **ppszNext)402 static int usbfsReadSpeed(const char *pszValue, USBDEVICESPEED *pSpd, char **ppszNext) 402 403 { 403 404 pszValue = RTStrStripL(pszValue); … … 423 424 * Compare a prefix and returns pointer to the char following it if it matches. 424 425 */ 425 static char *usb Prefix(char *psz, const char *pszPref, size_t cchPref)426 static char *usbfsPrefix(char *psz, const char *pszPref, size_t cchPref) 426 427 { 427 428 if (strncmp(psz, pszPref, cchPref)) … … 513 514 514 515 /** Just a worker for USBProxyServiceLinux::getDevices that avoids some code duplication. */ 515 static int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, const char *pcszUsbfsRoot,516 bool testfs, int rc)516 static int usbfsAddDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, const char *pcszUsbfsRoot, 517 bool testfs, int rc) 517 518 { 518 519 /* usbDeterminState requires the address. */ … … 551 552 552 553 553 static int openDevicesFile(const char *pcszUsbfsRoot, FILE **ppFile)554 static int usbfsOpenDevicesFile(const char *pcszUsbfsRoot, FILE **ppFile) 554 555 { 555 556 char *pszPath; … … 566 567 } 567 568 569 568 570 /** 569 571 * USBProxyService::getDevices() implementation for usbfs. The @a testfs flag … … 572 574 * we expect. 573 575 */ 574 static PUSBDEVICE getDevicesFromUsbfs(const char *pcszUsbfsRoot, bool testfs)576 static PUSBDEVICE usbfsGetDevices(const char *pcszUsbfsRoot, bool testfs) 575 577 { 576 578 PUSBDEVICE pFirst = NULL; 577 579 FILE *pFile = NULL; 578 580 int rc; 579 rc = openDevicesFile(pcszUsbfsRoot, &pFile);581 rc = usbfsOpenDevicesFile(pcszUsbfsRoot, &pFile); 580 582 if (RT_SUCCESS(rc)) 581 583 { … … 618 620 continue; 619 621 psz = RTStrStripL(psz + 3); 620 #define PREFIX(str) ( (pszValue = usb Prefix(psz, str, sizeof(str) - 1)) != NULL )622 #define PREFIX(str) ( (pszValue = usbfsPrefix(psz, str, sizeof(str) - 1)) != NULL ) 621 623 switch (ch) 622 624 { … … 637 639 AssertMsg(cHits >= 3 || cHits == 0, ("cHits=%d\n", cHits)); 638 640 if (cHits >= 3) 639 rc = addDeviceToChain(&Dev, &pFirst, &ppNext, pcszUsbfsRoot, testfs, rc);641 rc = usbfsAddDeviceToChain(&Dev, &pFirst, &ppNext, pcszUsbfsRoot, testfs, rc); 640 642 else 641 643 deviceFreeMembers(&Dev); … … 650 652 { 651 653 if (PREFIX("Bus=")) 652 rc = usb Read8(pszValue, 10, &Dev.bBus, &psz);654 rc = usbfsRead8(pszValue, 10, &Dev.bBus, &psz); 653 655 else if (PREFIX("Port=")) 654 rc = usb Read8(pszValue, 10, &Dev.bPort, &psz);656 rc = usbfsRead8(pszValue, 10, &Dev.bPort, &psz); 655 657 else if (PREFIX("Spd=")) 656 rc = usb ReadSpeed(pszValue, &Dev.enmSpeed, &psz);658 rc = usbfsReadSpeed(pszValue, &Dev.enmSpeed, &psz); 657 659 else if (PREFIX("Dev#=")) 658 rc = usb Read8(pszValue, 10, &Dev.bDevNum, &psz);660 rc = usbfsRead8(pszValue, 10, &Dev.bDevNum, &psz); 659 661 else 660 psz = usb ReadSkip(psz);662 psz = usbfsReadSkip(psz); 661 663 psz = RTStrStripL(psz); 662 664 } … … 688 690 { 689 691 if (PREFIX("Ver=")) 690 rc = usb ReadBCD(pszValue, 16, &Dev.bcdUSB, &psz);692 rc = usbfsReadBCD(pszValue, 16, &Dev.bcdUSB, &psz); 691 693 else if (PREFIX("Cls=")) 692 694 { 693 rc = usb Read8(pszValue, 16, &Dev.bDeviceClass, &psz);695 rc = usbfsRead8(pszValue, 16, &Dev.bDeviceClass, &psz); 694 696 if (RT_SUCCESS(rc) && Dev.bDeviceClass == 9 /* HUB */) 695 697 Dev.enmState = USBDEVICESTATE_UNSUPPORTED; 696 698 } 697 699 else if (PREFIX("Sub=")) 698 rc = usb Read8(pszValue, 16, &Dev.bDeviceSubClass, &psz);700 rc = usbfsRead8(pszValue, 16, &Dev.bDeviceSubClass, &psz); 699 701 else if (PREFIX("Prot=")) 700 rc = usb Read8(pszValue, 16, &Dev.bDeviceProtocol, &psz);702 rc = usbfsRead8(pszValue, 16, &Dev.bDeviceProtocol, &psz); 701 703 //else if (PREFIX("MxPS=")) 702 704 // rc = usbRead16(pszValue, 10, &Dev.wMaxPacketSize, &psz); 703 705 else if (PREFIX("#Cfgs=")) 704 rc = usb Read8(pszValue, 10, &Dev.bNumConfigurations, &psz);706 rc = usbfsRead8(pszValue, 10, &Dev.bNumConfigurations, &psz); 705 707 else 706 psz = usb ReadSkip(psz);708 psz = usbfsReadSkip(psz); 707 709 psz = RTStrStripL(psz); 708 710 } … … 721 723 { 722 724 if (PREFIX("Vendor=")) 723 rc = usb Read16(pszValue, 16, &Dev.idVendor, &psz);725 rc = usbfsRead16(pszValue, 16, &Dev.idVendor, &psz); 724 726 else if (PREFIX("ProdID=")) 725 rc = usb Read16(pszValue, 16, &Dev.idProduct, &psz);727 rc = usbfsRead16(pszValue, 16, &Dev.idProduct, &psz); 726 728 else if (PREFIX("Rev=")) 727 rc = usb ReadBCD(pszValue, 16, &Dev.bcdDevice, &psz);729 rc = usbfsReadBCD(pszValue, 16, &Dev.bcdDevice, &psz); 728 730 else 729 psz = usb ReadSkip(psz);731 psz = usbfsReadSkip(psz); 730 732 psz = RTStrStripL(psz); 731 733 } … … 738 740 case 'S': 739 741 if (PREFIX("Manufacturer=")) 740 rc = usb ReadStr(pszValue, &Dev.pszManufacturer);742 rc = usbfsReadStr(pszValue, &Dev.pszManufacturer); 741 743 else if (PREFIX("Product=")) 742 rc = usb ReadStr(pszValue, &Dev.pszProduct);744 rc = usbfsReadStr(pszValue, &Dev.pszProduct); 743 745 else if (PREFIX("SerialNumber=")) 744 746 { 745 rc = usb ReadStr(pszValue, &Dev.pszSerialNumber);747 rc = usbfsReadStr(pszValue, &Dev.pszSerialNumber); 746 748 if (RT_SUCCESS(rc)) 747 749 Dev.u64SerialHash = USBLibHashSerial(pszValue); … … 781 783 { 782 784 const char *pszDriver = NULL; 783 rc = usb ReadStr(pszValue, &pszDriver);785 rc = usbfsReadStr(pszValue, &pszDriver); 784 786 if ( !pszDriver 785 787 || !*pszDriver … … 797 799 { 798 800 uint8_t bInterfaceClass; 799 rc = usb Read8(pszValue, 16, &bInterfaceClass, &psz);801 rc = usbfsRead8(pszValue, 16, &bInterfaceClass, &psz); 800 802 if (RT_SUCCESS(rc) && bInterfaceClass == 9 /* HUB */) 801 803 Dev.enmState = USBDEVICESTATE_UNSUPPORTED; 802 804 } 803 805 else 804 psz = usb ReadSkip(psz);806 psz = usbfsReadSkip(psz); 805 807 psz = RTStrStripL(psz); 806 808 } … … 830 832 AssertMsg(cHits >= 3 || cHits == 0, ("cHits=%d\n", cHits)); 831 833 if (cHits >= 3) 832 rc = addDeviceToChain(&Dev, &pFirst, &ppNext, pcszUsbfsRoot, testfs, rc);834 rc = usbfsAddDeviceToChain(&Dev, &pFirst, &ppNext, pcszUsbfsRoot, testfs, rc); 833 835 834 836 /* … … 852 854 #ifdef VBOX_USB_WITH_SYSFS 853 855 854 static void USBDevInfoCleanup(USBDeviceInfo *pSelf)856 static void usbsysfsCleanupDevInfo(USBDeviceInfo *pSelf) 855 857 { 856 858 RTStrFree(pSelf->mDevice); … … 860 862 } 861 863 862 static int USBDevInfoInit(USBDeviceInfo *pSelf, const char *aDevice, 863 864 865 static int usbsysfsInitDevInfo(USBDeviceInfo *pSelf, const char *aDevice, const char *aSystemID) 864 866 { 865 867 pSelf->mDevice = aDevice ? RTStrDup(aDevice) : NULL; … … 868 870 if ((aDevice && !pSelf->mDevice) || (aSystemID && ! pSelf->mSysfsPath)) 869 871 { 870 USBDevInfoCleanup(pSelf);872 usbsysfsCleanupDevInfo(pSelf); 871 873 return 0; 872 874 } … … 876 878 #define USBDEVICE_MAJOR 189 877 879 878 /** Calculate the bus (a.k.a root hub) number of a USB device from it's sysfs 879 * path. sysfs nodes representing root hubs have file names of the form 880 /** 881 * Calculate the bus (a.k.a root hub) number of a USB device from it's sysfs 882 * path. 883 * 884 * sysfs nodes representing root hubs have file names of the form 880 885 * usb<n>, where n is the bus number; other devices start with that number. 881 886 * See [http://www.linux-usb.org/FAQ.html#i6] and 882 887 * [http://www.kernel.org/doc/Documentation/usb/proc_usb_info.txt] for 883 888 * equivalent information about usbfs. 889 * 884 890 * @returns a bus number greater than 0 on success or 0 on failure. 885 891 */ 886 static unsigned usb GetBusFromSysfsPath(const char *pcszPath)892 static unsigned usbsysfsGetBusFromPath(const char *pcszPath) 887 893 { 888 894 const char *pcszFile = strrchr(pcszPath, '/'); … … 896 902 } 897 903 898 /** Calculate the device number of a USB device. See 899 * drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. */ 900 static dev_t usbMakeDevNum(unsigned bus, unsigned device) 904 905 /** 906 * Calculate the device number of a USB device. 907 * 908 * See drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. 909 */ 910 static dev_t usbsysfsMakeDevNum(unsigned bus, unsigned device) 901 911 { 902 912 AssertReturn(bus > 0, 0); … … 906 916 } 907 917 918 908 919 /** 909 920 * If a file @a pcszNode from /sys/bus/usb/devices is a device rather than an 910 921 * interface add an element for the device to @a pvecDevInfo. 911 922 */ 912 static int addIfDevice(const char *pcszDevicesRoot, 913 const char *pcszNode, 914 VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo) 923 static int usbsysfsAddIfDevice(const char *pcszDevicesRoot, const char *pcszNode, VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo) 915 924 { 916 925 const char *pcszFile = strrchr(pcszNode, '/'); … … 919 928 if (strchr(pcszFile, ':')) 920 929 return VINF_SUCCESS; 921 unsigned bus = usbGetBusFromSysfsPath(pcszNode); 930 931 unsigned bus = usbsysfsGetBusFromPath(pcszNode); 922 932 if (!bus) 923 933 return VINF_SUCCESS; 934 924 935 int device = RTLinuxSysFsReadIntFile(10, "%s/devnum", pcszNode); 925 936 if (device < 0) 926 937 return VINF_SUCCESS; 927 dev_t devnum = usbMakeDevNum(bus, device); 938 939 dev_t devnum = usbsysfsMakeDevNum(bus, device); 928 940 if (!devnum) 929 941 return VINF_SUCCESS; 942 930 943 char szDevPath[RTPATH_MAX]; 931 944 ssize_t cchDevPath; … … 938 951 939 952 USBDeviceInfo info; 940 if (USBDevInfoInit(&info, szDevPath, pcszNode)) 941 if (RT_SUCCESS(VEC_PUSH_BACK_OBJ(pvecDevInfo, USBDeviceInfo, 942 &info))) 953 if (usbsysfsInitDevInfo(&info, szDevPath, pcszNode)) 954 { 955 int rc = VEC_PUSH_BACK_OBJ(pvecDevInfo, USBDeviceInfo, &info); 956 if (RT_SUCCESS(rc)) 943 957 return VINF_SUCCESS; 944 USBDevInfoCleanup(&info); 958 } 959 usbsysfsCleanupDevInfo(&info); 945 960 return VERR_NO_MEMORY; 946 961 } 947 962 948 /** The logic for testing whether a sysfs address corresponds to an 949 * interface of a device. Both must be referenced by their canonical 950 * sysfs paths. This is not tested, as the test requires file-system 951 * interaction. */ 952 static bool muiIsAnInterfaceOf(const char *pcszIface, const char *pcszDev) 963 964 /** 965 * The logic for testing whether a sysfs address corresponds to an interface of 966 * a device. 967 * 968 * Both must be referenced by their canonical sysfs paths. This is not tested, 969 * as the test requires file-system interaction. 970 */ 971 static bool usbsysfsMuiIsAnInterfaceOf(const char *pcszIface, const char *pcszDev) 953 972 { 954 973 size_t cchDev = strlen(pcszDev); … … 959 978 Assert(pcszDev[0] == '/'); 960 979 Assert(pcszDev[cchDev - 1] != '/'); 980 961 981 /* If this passes, pcszIface is at least cchDev long */ 962 982 if (strncmp(pcszIface, pcszDev, cchDev)) 963 983 return false; 984 964 985 /* If this passes, pcszIface is longer than cchDev */ 965 986 if (pcszIface[cchDev] != '/') 966 987 return false; 988 967 989 /* In sysfs an interface is an immediate subdirectory of the device */ 968 990 if (strchr(pcszIface + cchDev + 1, '/')) 969 991 return false; 992 970 993 /* And it always has a colon in its name */ 971 994 if (!strchr(pcszIface + cchDev + 1, ':')) 972 995 return false; 996 973 997 /* And hopefully we have now elimitated everything else */ 974 998 return true; 975 999 } 1000 976 1001 977 1002 #ifdef DEBUG … … 983 1008 testIsAnInterfaceOf() 984 1009 { 985 Assert( muiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0",1010 Assert(usbsysfsMuiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0", 986 1011 "/sys/devices/pci0000:00/0000:00:1a.0/usb3")); 987 Assert(! muiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-1",1012 Assert(!usbsysfsMuiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-1", 988 1013 "/sys/devices/pci0000:00/0000:00:1a.0/usb3")); 989 Assert(! muiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0/driver",1014 Assert(!usbsysfsMuiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0/driver", 990 1015 "/sys/devices/pci0000:00/0000:00:1a.0/usb3")); 991 1016 } … … 995 1020 #endif /* DEBUG */ 996 1021 1022 997 1023 /** 998 1024 * Tell whether a file in /sys/bus/usb/devices is an interface rather than a 999 * device. To be used with getDeviceInfoFromSysfs().1000 */ 1001 static int addIfInterfaceOf(const char *pcszNode, USBDeviceInfo *pInfo)1002 { 1003 if (! muiIsAnInterfaceOf(pcszNode, pInfo->mSysfsPath))1025 * device. 1026 */ 1027 static int usbsysfsAddIfInterfaceOf(const char *pcszNode, USBDeviceInfo *pInfo) 1028 { 1029 if (!usbsysfsMuiIsAnInterfaceOf(pcszNode, pInfo->mSysfsPath)) 1004 1030 return VINF_SUCCESS; 1031 1005 1032 char *pszDup = (char *)RTStrDup(pcszNode); 1006 1033 if (pszDup) 1007 if (RT_SUCCESS(VEC_PUSH_BACK_PTR(&pInfo->mvecpszInterfaces, 1008 char *, pszDup))) 1034 { 1035 int rc = VEC_PUSH_BACK_PTR(&pInfo->mvecpszInterfaces, char *, pszDup); 1036 if (RT_SUCCESS(rc)) 1009 1037 return VINF_SUCCESS; 1010 RTStrFree(pszDup); 1038 RTStrFree(pszDup); 1039 } 1011 1040 return VERR_NO_MEMORY; 1012 1041 } 1013 1042 1014 /** Helper for readFilePaths(). Adds the entries from the open directory 1015 * @a pDir to the vector @a pvecpchDevs using either the full path or the 1016 * realpath() and skipping hidden files and files on which realpath() fails. */ 1017 static int readFilePathsFromDir(const char *pcszPath, DIR *pDir, 1018 VECTOR_PTR(char *) *pvecpchDevs) 1043 1044 /** 1045 * Helper for usbsysfsReadFilePaths(). 1046 * 1047 * Adds the entries from the open directory @a pDir to the vector @a pvecpchDevs 1048 * using either the full path or the realpath() and skipping hidden files and 1049 * files on which realpath() fails. 1050 */ 1051 static int usbsysfsReadFilePathsFromDir(const char *pcszPath, DIR *pDir, VECTOR_PTR(char *) *pvecpchDevs) 1019 1052 { 1020 1053 struct dirent entry, *pResult; … … 1024 1057 err = readdir_r(pDir, &entry, &pResult)) 1025 1058 { 1026 char szPath[RTPATH_MAX + 1], szRealPath[RTPATH_MAX + 1], *pszPath; 1059 char szPath[RTPATH_MAX + 1]; 1060 char szRealPath[RTPATH_MAX + 1]; 1027 1061 if (entry.d_name[0] == '.') 1028 1062 continue; 1029 if (snprintf(szPath, sizeof(szPath), "%s/%s", pcszPath, 1030 entry.d_name) < 0) 1031 return RTErrConvertFromErrno(errno); 1063 if (snprintf(szPath, sizeof(szPath), "%s/%s", pcszPath, entry.d_name) < 0) 1064 return RTErrConvertFromErrno(errno); /** @todo r=bird: snprintf isn't document to set errno. Also, wouldn't it be better to continue on errors? Finally, you don't need to copy pcszPath each time... */ 1032 1065 if (!realpath(szPath, szRealPath)) 1033 1066 return RTErrConvertFromErrno(errno); 1034 pszPath = RTStrDup(szRealPath);1067 char *pszPath = RTStrDup(szRealPath); 1035 1068 if (!pszPath) 1036 1069 return VERR_NO_MEMORY; … … 1040 1073 return RTErrConvertFromErrno(err); 1041 1074 } 1075 1042 1076 1043 1077 /** … … 1050 1084 * @param withRealPath whether to canonicalise the filename with realpath 1051 1085 */ 1052 static int readFilePaths(const char *pcszPath, VECTOR_PTR(char *) *pvecpchDevs) 1053 { 1054 DIR *pDir; 1055 int rc; 1056 1086 static int usbsysfsReadFilePaths(const char *pcszPath, VECTOR_PTR(char *) *pvecpchDevs) 1087 { 1057 1088 AssertPtrReturn(pvecpchDevs, EINVAL); 1058 1089 AssertReturn(VEC_SIZE_PTR(pvecpchDevs) == 0, EINVAL); 1059 1090 AssertPtrReturn(pcszPath, EINVAL); 1060 1091 1061 pDir = opendir(pcszPath);1092 DIR *pDir = opendir(pcszPath); 1062 1093 if (!pDir) 1063 1094 return RTErrConvertFromErrno(errno); 1064 rc = readFilePathsFromDir(pcszPath, pDir, pvecpchDevs);1095 int rc = usbsysfsReadFilePathsFromDir(pcszPath, pDir, pvecpchDevs); 1065 1096 if (closedir(pDir) < 0 && RT_SUCCESS(rc)) 1066 1097 rc = RTErrConvertFromErrno(errno); … … 1068 1099 } 1069 1100 1101 1070 1102 /** 1071 1103 * Logic for USBSysfsEnumerateHostDevices. 1104 * 1072 1105 * @param pvecDevInfo vector of device information structures to add device 1073 1106 * information to … … 1075 1108 * to simplify exit logic 1076 1109 */ 1077 static int doSysfsEnumerateHostDevices(const char *pcszDevicesRoot, 1078 VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo, 1079 VECTOR_PTR(char *) *pvecpchDevs) 1080 { 1081 char **ppszEntry; 1082 USBDeviceInfo *pInfo; 1083 int rc; 1110 static int usbsysfsEnumerateHostDevicesWorker(const char *pcszDevicesRoot, 1111 VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo, 1112 VECTOR_PTR(char *) *pvecpchDevs) 1113 { 1084 1114 1085 1115 AssertPtrReturn(pvecDevInfo, VERR_INVALID_POINTER); 1086 1116 LogFlowFunc (("pvecDevInfo=%p\n", pvecDevInfo)); 1087 1117 1088 rc = readFilePaths("/sys/bus/usb/devices", pvecpchDevs);1118 int rc = usbsysfsReadFilePaths("/sys/bus/usb/devices", pvecpchDevs); 1089 1119 if (RT_FAILURE(rc)) 1090 1120 return rc; 1121 1122 char **ppszEntry; 1091 1123 VEC_FOR_EACH(pvecpchDevs, char *, ppszEntry) 1092 if (RT_FAILURE(rc = addIfDevice(pcszDevicesRoot, *ppszEntry, 1093 pvecDevInfo))) 1124 { 1125 rc = usbsysfsAddIfDevice(pcszDevicesRoot, *ppszEntry, pvecDevInfo)) 1126 if (RT_FAILURE(rc)) 1094 1127 return rc; 1128 } 1129 1130 USBDeviceInfo *pInfo; 1095 1131 VEC_FOR_EACH(pvecDevInfo, USBDeviceInfo, pInfo) 1096 1132 VEC_FOR_EACH(pvecpchDevs, char *, ppszEntry) 1097 if (RT_FAILURE(rc = addIfInterfaceOf(*ppszEntry, pInfo))) 1133 { 1134 rc = usbsysfsAddIfInterfaceOf(*ppszEntry, pInfo); 1135 if (RT_FAILURE(rc)) 1098 1136 return rc; 1137 } 1099 1138 return VINF_SUCCESS; 1100 1139 } 1101 1140 1102 static int USBSysfsEnumerateHostDevices(const char *pcszDevicesRoot, 1103 1141 1142 static int usbsysfsEnumerateHostDevices(const char *pcszDevicesRoot, VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo) 1104 1143 { 1105 1144 VECTOR_PTR(char *) vecpchDevs; 1106 int rc = VERR_NOT_IMPLEMENTED;1107 1145 1108 1146 AssertReturn(VEC_SIZE_OBJ(pvecDevInfo) == 0, VERR_INVALID_PARAMETER); 1109 1147 LogFlowFunc(("entered\n")); 1110 1148 VEC_INIT_PTR(&vecpchDevs, char *, RTStrFree); 1111 rc = doSysfsEnumerateHostDevices(pcszDevicesRoot, pvecDevInfo, 1112 &vecpchDevs); 1149 int rc = usbsysfsEnumerateHostDevicesWorker(pcszDevicesRoot, pvecDevInfo, &vecpchDevs); 1113 1150 VEC_CLEANUP_PTR(&vecpchDevs); 1114 1151 LogFlowFunc(("rc=%Rrc\n", rc)); 1115 1152 return rc; 1116 1153 } 1154 1117 1155 1118 1156 /** … … 1138 1176 * @param pu8Port Where to store the port number. 1139 1177 */ 1140 static int usb GetPortFromSysfsPath(const char *pszPath, uint8_t *pu8Port)1178 static int usbsysfsGetPortFromStr(const char *pszPath, uint8_t *pu8Port) 1141 1179 { 1142 1180 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); … … 1178 1216 return VERR_NOT_SUPPORTED; 1179 1217 } 1180 else 1181 { 1182 const char *pszLastPort = pchDot != NULL 1183 ? pchDot + 1 1184 : pchDash + 1; 1185 int rc = RTStrToUInt8Full(pszLastPort, 10, pu8Port); 1186 if (rc != VINF_SUCCESS) 1187 { 1188 Log(("usbGetPortFromSysfsPath(%s): failed [3], rc=%Rrc\n", pszPath, rc)); 1189 return VERR_INVALID_PARAMETER; 1190 } 1191 if (*pu8Port == 0) 1192 { 1193 Log(("usbGetPortFromSysfsPath(%s): failed [4]\n", pszPath)); 1194 return VERR_INVALID_PARAMETER; 1195 } 1196 1197 /* usbfs compatibility, 0-based port number. */ 1198 *pu8Port -= 1; 1199 } 1218 1219 const char *pszLastPort = pchDot != NULL 1220 ? pchDot + 1 1221 : pchDash + 1; 1222 int rc = RTStrToUInt8Full(pszLastPort, 10, pu8Port); 1223 if (rc != VINF_SUCCESS) 1224 { 1225 Log(("usbGetPortFromSysfsPath(%s): failed [3], rc=%Rrc\n", pszPath, rc)); 1226 return VERR_INVALID_PARAMETER; 1227 } 1228 if (*pu8Port == 0) 1229 { 1230 Log(("usbGetPortFromSysfsPath(%s): failed [4]\n", pszPath)); 1231 return VERR_INVALID_PARAMETER; 1232 } 1233 1234 /* usbfs compatibility, 0-based port number. */ 1235 *pu8Port -= 1; 1200 1236 return VINF_SUCCESS; 1201 1237 } … … 1207 1243 * @todo This is really common code. 1208 1244 */ 1209 DECLINLINE(void)usbLogDevice(PUSBDEVICE pDev)1245 static void usbLogDevice(PUSBDEVICE pDev) 1210 1246 { 1211 1247 NOREF(pDev); 1212 1213 Log3(("USB device:\n")); 1214 Log3(("Product: %s (%x)\n", pDev->pszProduct, pDev->idProduct)); 1215 Log3(("Manufacturer: %s (Vendor ID %x)\n", pDev->pszManufacturer, pDev->idVendor)); 1216 Log3(("Serial number: %s (%llx)\n", pDev->pszSerialNumber, pDev->u64SerialHash)); 1217 Log3(("Device revision: %d\n", pDev->bcdDevice)); 1218 Log3(("Device class: %x\n", pDev->bDeviceClass)); 1219 Log3(("Device subclass: %x\n", pDev->bDeviceSubClass)); 1220 Log3(("Device protocol: %x\n", pDev->bDeviceProtocol)); 1221 Log3(("USB version number: %d\n", pDev->bcdUSB)); 1222 Log3(("Device speed: %s\n", 1223 pDev->enmSpeed == USBDEVICESPEED_UNKNOWN ? "unknown" 1224 : pDev->enmSpeed == USBDEVICESPEED_LOW ? "1.5 MBit/s" 1225 : pDev->enmSpeed == USBDEVICESPEED_FULL ? "12 MBit/s" 1226 : pDev->enmSpeed == USBDEVICESPEED_HIGH ? "480 MBit/s" 1227 : pDev->enmSpeed == USBDEVICESPEED_SUPER ? "5.0 GBit/s" 1228 : pDev->enmSpeed == USBDEVICESPEED_VARIABLE ? "variable" 1229 : "invalid")); 1230 Log3(("Number of configurations: %d\n", pDev->bNumConfigurations)); 1231 Log3(("Bus number: %d\n", pDev->bBus)); 1232 Log3(("Port number: %d\n", pDev->bPort)); 1233 Log3(("Device number: %d\n", pDev->bDevNum)); 1234 Log3(("Device state: %s\n", 1235 pDev->enmState == USBDEVICESTATE_UNSUPPORTED ? "unsupported" 1236 : pDev->enmState == USBDEVICESTATE_USED_BY_HOST ? "in use by host" 1237 : pDev->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE ? "in use by host, possibly capturable" 1238 : pDev->enmState == USBDEVICESTATE_UNUSED ? "not in use" 1239 : pDev->enmState == USBDEVICESTATE_HELD_BY_PROXY ? "held by proxy" 1240 : pDev->enmState == USBDEVICESTATE_USED_BY_GUEST ? "used by guest" 1241 : "invalid")); 1242 Log3(("OS device address: %s\n", pDev->pszAddress)); 1243 } 1244 1245 /** 1248 if (LogIs3Enabled()) 1249 { 1250 Log3(("USB device:\n")); 1251 Log3(("Product: %s (%x)\n", pDev->pszProduct, pDev->idProduct)); 1252 Log3(("Manufacturer: %s (Vendor ID %x)\n", pDev->pszManufacturer, pDev->idVendor)); 1253 Log3(("Serial number: %s (%llx)\n", pDev->pszSerialNumber, pDev->u64SerialHash)); 1254 Log3(("Device revision: %d\n", pDev->bcdDevice)); 1255 Log3(("Device class: %x\n", pDev->bDeviceClass)); 1256 Log3(("Device subclass: %x\n", pDev->bDeviceSubClass)); 1257 Log3(("Device protocol: %x\n", pDev->bDeviceProtocol)); 1258 Log3(("USB version number: %d\n", pDev->bcdUSB)); 1259 Log3(("Device speed: %s\n", 1260 pDev->enmSpeed == USBDEVICESPEED_UNKNOWN ? "unknown" 1261 : pDev->enmSpeed == USBDEVICESPEED_LOW ? "1.5 MBit/s" 1262 : pDev->enmSpeed == USBDEVICESPEED_FULL ? "12 MBit/s" 1263 : pDev->enmSpeed == USBDEVICESPEED_HIGH ? "480 MBit/s" 1264 : pDev->enmSpeed == USBDEVICESPEED_SUPER ? "5.0 GBit/s" 1265 : pDev->enmSpeed == USBDEVICESPEED_VARIABLE ? "variable" 1266 : "invalid")); 1267 Log3(("Number of configurations: %d\n", pDev->bNumConfigurations)); 1268 Log3(("Bus number: %d\n", pDev->bBus)); 1269 Log3(("Port number: %d\n", pDev->bPort)); 1270 Log3(("Device number: %d\n", pDev->bDevNum)); 1271 Log3(("Device state: %s\n", 1272 pDev->enmState == USBDEVICESTATE_UNSUPPORTED ? "unsupported" 1273 : pDev->enmState == USBDEVICESTATE_USED_BY_HOST ? "in use by host" 1274 : pDev->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE ? "in use by host, possibly capturable" 1275 : pDev->enmState == USBDEVICESTATE_UNUSED ? "not in use" 1276 : pDev->enmState == USBDEVICESTATE_HELD_BY_PROXY ? "held by proxy" 1277 : pDev->enmState == USBDEVICESTATE_USED_BY_GUEST ? "used by guest" 1278 : "invalid")); 1279 Log3(("OS device address: %s\n", pDev->pszAddress)); 1280 } 1281 } 1282 1283 1284 /** 1285 * Converts a sysfs BCD value into a uint16_t. 1286 * 1246 1287 * In contrast to usbReadBCD() this function can handle BCD values without 1247 1288 * a decimal separator. This is necessary for parsing bcdDevice. 1289 * 1248 1290 * @param pszBuf Pointer to the string buffer. 1249 1291 * @param pu15 Pointer to the return value. 1250 1292 * @returns IPRT status code. 1251 1293 */ 1252 static int convertSysfsStrToBCD(const char *pszBuf, uint16_t *pu16)1294 static int usbsysfsConvertStrToBCD(const char *pszBuf, uint16_t *pu16) 1253 1295 { 1254 1296 char *pszNext; … … 1284 1326 #endif /* VBOX_USB_WITH_SYSFS */ 1285 1327 1286 static void fillInDeviceFromSysfs(USBDEVICE *Dev, USBDeviceInfo *pInfo)1328 static void usbsysfsFillInDevice(USBDEVICE *pDev, USBDeviceInfo *pInfo) 1287 1329 { 1288 1330 int rc; … … 1290 1332 1291 1333 /* Fill in the simple fields */ 1292 Dev->enmState = USBDEVICESTATE_UNUSED;1293 Dev->bBus = usbGetBusFromSysfsPath(pszSysfsPath);1294 Dev->bDeviceClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceClass", pszSysfsPath);1295 Dev->bDeviceSubClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceSubClass", pszSysfsPath);1296 Dev->bDeviceProtocol = RTLinuxSysFsReadIntFile(16, "%s/bDeviceProtocol", pszSysfsPath);1297 Dev->bNumConfigurations = RTLinuxSysFsReadIntFile(10, "%s/bNumConfigurations", pszSysfsPath);1298 Dev->idVendor = RTLinuxSysFsReadIntFile(16, "%s/idVendor", pszSysfsPath);1299 Dev->idProduct = RTLinuxSysFsReadIntFile(16, "%s/idProduct", pszSysfsPath);1300 Dev->bDevNum = RTLinuxSysFsReadIntFile(10, "%s/devnum", pszSysfsPath);1334 pDev->enmState = USBDEVICESTATE_UNUSED; 1335 pDev->bBus = usbsysfsGetBusFromPath(pszSysfsPath); 1336 pDev->bDeviceClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceClass", pszSysfsPath); 1337 pDev->bDeviceSubClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceSubClass", pszSysfsPath); 1338 pDev->bDeviceProtocol = RTLinuxSysFsReadIntFile(16, "%s/bDeviceProtocol", pszSysfsPath); 1339 pDev->bNumConfigurations = RTLinuxSysFsReadIntFile(10, "%s/bNumConfigurations", pszSysfsPath); 1340 pDev->idVendor = RTLinuxSysFsReadIntFile(16, "%s/idVendor", pszSysfsPath); 1341 pDev->idProduct = RTLinuxSysFsReadIntFile(16, "%s/idProduct", pszSysfsPath); 1342 pDev->bDevNum = RTLinuxSysFsReadIntFile(10, "%s/devnum", pszSysfsPath); 1301 1343 1302 1344 /* Now deal with the non-numeric bits. */ … … 1307 1349 1308 1350 /* For simplicity, we just do strcmps on the next one. */ 1309 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/speed", 1310 pszSysfsPath); 1351 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/speed", pszSysfsPath); 1311 1352 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1312 Dev->enmState = USBDEVICESTATE_UNSUPPORTED;1353 pDev->enmState = USBDEVICESTATE_UNSUPPORTED; 1313 1354 else 1314 Dev->enmSpeed = !strcmp(szBuf, "1.5") ? USBDEVICESPEED_LOW 1315 : !strcmp(szBuf, "12") ? USBDEVICESPEED_FULL 1316 : !strcmp(szBuf, "480") ? USBDEVICESPEED_HIGH 1317 : !strcmp(szBuf, "5000") ? USBDEVICESPEED_SUPER 1318 : USBDEVICESPEED_UNKNOWN; 1319 1320 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/version", 1321 pszSysfsPath); 1355 pDev->enmSpeed = !strcmp(szBuf, "1.5") ? USBDEVICESPEED_LOW 1356 : !strcmp(szBuf, "12") ? USBDEVICESPEED_FULL 1357 : !strcmp(szBuf, "480") ? USBDEVICESPEED_HIGH 1358 : !strcmp(szBuf, "5000") ? USBDEVICESPEED_SUPER 1359 : USBDEVICESPEED_UNKNOWN; 1360 1361 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/version", pszSysfsPath); 1322 1362 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1323 Dev->enmState = USBDEVICESTATE_UNSUPPORTED;1363 pDev->enmState = USBDEVICESTATE_UNSUPPORTED; 1324 1364 else 1325 1365 { 1326 rc = convertSysfsStrToBCD(szBuf, &Dev->bcdUSB);1366 rc = usbsysfsConvertStrToBCD(szBuf, &pDev->bcdUSB); 1327 1367 if (RT_FAILURE(rc)) 1328 1368 { 1329 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1330 Dev->bcdUSB = (uint16_t)-1; 1331 } 1332 } 1333 1334 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/bcdDevice", 1335 pszSysfsPath); 1369 pDev->enmState = USBDEVICESTATE_UNSUPPORTED; 1370 pDev->bcdUSB = UINT16_MAX 1371 } 1372 } 1373 1374 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/bcdDevice", pszSysfsPath); 1336 1375 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1337 Dev->bcdDevice = (uint16_t)-1;1376 pDev->bcdDevice = UINT16_MAX; 1338 1377 else 1339 1378 { 1340 rc = convertSysfsStrToBCD(szBuf, &Dev->bcdDevice);1379 rc = usbsysfsConvertStrToBCD(szBuf, &pDev->bcdDevice); 1341 1380 if (RT_FAILURE(rc)) 1342 Dev->bcdDevice = (uint16_t)-1;1381 pDev->bcdDevice = UINT16_MAX; 1343 1382 } 1344 1383 1345 1384 /* Now do things that need string duplication */ 1346 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/product", 1347 pszSysfsPath); 1385 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/product", pszSysfsPath); 1348 1386 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1349 1387 { 1350 1388 usbPurgeEncoding(szBuf); 1351 Dev->pszProduct = RTStrDup(szBuf); 1352 } 1353 1354 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/serial", 1355 pszSysfsPath); 1389 pDev->pszProduct = RTStrDup(szBuf); 1390 } 1391 1392 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/serial", pszSysfsPath); 1356 1393 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1357 1394 { 1358 1395 usbPurgeEncoding(szBuf); 1359 Dev->pszSerialNumber = RTStrDup(szBuf); 1360 Dev->u64SerialHash = USBLibHashSerial(szBuf); 1361 } 1362 1363 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/manufacturer", 1364 pszSysfsPath); 1396 pDev->pszSerialNumber = RTStrDup(szBuf); 1397 pDev->u64SerialHash = USBLibHashSerial(szBuf); 1398 } 1399 1400 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/manufacturer", pszSysfsPath); 1365 1401 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1366 1402 { 1367 1403 usbPurgeEncoding(szBuf); 1368 Dev->pszManufacturer = RTStrDup(szBuf);1404 pDev->pszManufacturer = RTStrDup(szBuf); 1369 1405 } 1370 1406 1371 1407 /* Work out the port number */ 1372 if (RT_FAILURE(usb GetPortFromSysfsPath(pszSysfsPath, &Dev->bPort)))1373 Dev->enmState = USBDEVICESTATE_UNSUPPORTED;1408 if (RT_FAILURE(usbsysfsGetPortFromStr(pszSysfsPath, &pDev->bPort))) 1409 pDev->enmState = USBDEVICESTATE_UNSUPPORTED; 1374 1410 1375 1411 /* Check the interfaces to see if we can support the device. */ … … 1377 1413 VEC_FOR_EACH(&pInfo->mvecpszInterfaces, char *, ppszIf) 1378 1414 { 1379 ssize_t cb = RTLinuxSysFsGetLinkDest(szBuf, sizeof(szBuf), "%s/driver", 1380 *ppszIf); 1381 if (cb > 0 && Dev->enmState != USBDEVICESTATE_UNSUPPORTED) 1382 Dev->enmState = (strcmp(szBuf, "hub") == 0) 1383 ? USBDEVICESTATE_UNSUPPORTED 1384 : USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; 1385 if (RTLinuxSysFsReadIntFile(16, "%s/bInterfaceClass", 1386 *ppszIf) == 9 /* hub */) 1387 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1415 ssize_t cb = RTLinuxSysFsGetLinkDest(szBuf, sizeof(szBuf), "%s/driver", *ppszIf); 1416 if (cb > 0 && pDev->enmState != USBDEVICESTATE_UNSUPPORTED) 1417 pDev->enmState = (strcmp(szBuf, "hub") == 0) 1418 ? USBDEVICESTATE_UNSUPPORTED 1419 : USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; 1420 if (RTLinuxSysFsReadIntFile(16, "%s/bInterfaceClass", *ppszIf) == 9 /* hub */) 1421 pDev->enmState = USBDEVICESTATE_UNSUPPORTED; 1388 1422 } 1389 1423 … … 1392 1426 * them. */ 1393 1427 char *pszAddress = NULL; 1394 RTStrAPrintf(&pszAddress, "sysfs:%s//device:%s", pszSysfsPath, 1395 pInfo->mDevice); 1396 Dev->pszAddress = pszAddress; 1397 Dev->pszBackend = RTStrDup("host"); 1428 RTStrAPrintf(&pszAddress, "sysfs:%s//device:%s", pszSysfsPath, pInfo->mDevice); 1429 pDev->pszAddress = pszAddress; 1430 pDev->pszBackend = RTStrDup("host"); 1398 1431 1399 1432 /* Work out from the data collected whether we can support this device. */ 1400 Dev->enmState = usbDeterminState(Dev); 1401 usbLogDevice(Dev); 1402 } 1433 pDev->enmState = usbDeterminState(pDev); 1434 usbLogDevice(pDev); 1435 } 1436 1403 1437 1404 1438 /** 1405 1439 * USBProxyService::getDevices() implementation for sysfs. 1406 1440 */ 1407 static PUSBDEVICE getDevicesFromSysfs(const char *pcszDevicesRoot, bool testfs)1441 static PUSBDEVICE usbsysfsGetDevices(const char *pcszDevicesRoot, bool testfs) 1408 1442 { 1409 1443 #ifdef VBOX_USB_WITH_SYSFS … … 1415 1449 int rc; 1416 1450 1417 VEC_INIT_OBJ(&vecDevInfo, USBDeviceInfo, USBDevInfoCleanup);1418 rc = USBSysfsEnumerateHostDevices(pcszDevicesRoot, &vecDevInfo);1451 VEC_INIT_OBJ(&vecDevInfo, USBDeviceInfo, usbsysfsCleanupDevInfo); 1452 rc = usbsysfsEnumerateHostDevices(pcszDevicesRoot, &vecDevInfo); 1419 1453 if (RT_FAILURE(rc)) 1420 1454 return NULL; 1421 1455 VEC_FOR_EACH(&vecDevInfo, USBDeviceInfo, pInfo) 1422 1456 { 1423 USBDEVICE * Dev = (USBDEVICE *)RTMemAllocZ(sizeof(USBDEVICE));1424 if (! Dev)1457 USBDEVICE *pDev = (USBDEVICE *)RTMemAllocZ(sizeof(USBDEVICE)); 1458 if (!pDev) 1425 1459 rc = VERR_NO_MEMORY; 1426 1460 if (RT_SUCCESS(rc)) 1427 { 1428 fillInDeviceFromSysfs(Dev, pInfo); 1429 } 1461 usbsysfsFillInDevice(pDev, pInfo); 1430 1462 if ( RT_SUCCESS(rc) 1431 && ( Dev->enmState != USBDEVICESTATE_UNSUPPORTED1463 && ( pDev->enmState != USBDEVICESTATE_UNSUPPORTED 1432 1464 || testfs) 1433 && Dev->pszAddress != NULL1465 && pDev->pszAddress != NULL 1434 1466 ) 1435 1467 { 1436 1468 if (pLast != NULL) 1437 1469 { 1438 pLast->pNext = Dev;1470 pLast->pNext = pDev; 1439 1471 pLast = pLast->pNext; 1440 1472 } 1441 1473 else 1442 pFirst = pLast = Dev;1474 pFirst = pLast = pDev; 1443 1475 } 1444 1476 else 1445 deviceFree( Dev);1477 deviceFree(pDev); 1446 1478 if (RT_FAILURE(rc)) 1447 1479 break; … … 1458 1490 1459 1491 #ifdef UNIT_TEST 1492 1460 1493 /* Set up mock functions for USBProxyLinuxCheckDeviceRoot - here dlsym and close 1461 1494 * for the inotify presence check. */ … … 1483 1516 # define dlsym testDLSym 1484 1517 # define close(a) do {} while (0) 1485 #endif 1486 1487 /** Is inotify available and working on this system? This is a requirement 1488 * for using USB with sysfs */ 1489 static bool inotifyAvailable(void) 1518 1519 #endif /* UNIT_TEST */ 1520 1521 /** 1522 * Is inotify available and working on this system? 1523 * 1524 * This is a requirement for using USB with sysfs 1525 */ 1526 static bool usbsysfsInotifyAvailable(void) 1490 1527 { 1491 1528 int (*inotify_init)(void); … … 1502 1539 1503 1540 #ifdef UNIT_TEST 1541 1504 1542 # undef dlsym 1505 1543 # undef close 1506 #endif 1507 1508 #ifdef UNIT_TEST 1544 1509 1545 /** Unit test list of usbfs addresses of connected devices. */ 1510 static const char ** s_pacszUsbfsDeviceAddresses = NULL;1546 static const char **g_papszUsbfsDeviceAddresses = NULL; 1511 1547 1512 1548 static PUSBDEVICE testGetUsbfsDevices(const char *pcszUsbfsRoot, bool testfs) … … 1514 1550 const char **pcsz; 1515 1551 PUSBDEVICE pList = NULL, pTail = NULL; 1516 for (pcsz = s_pacszUsbfsDeviceAddresses; pcsz && *pcsz; ++pcsz)1552 for (pcsz = g_papszUsbfsDeviceAddresses; pcsz && *pcsz; ++pcsz) 1517 1553 { 1518 1554 PUSBDEVICE pNext = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE)); … … 1534 1570 return pList; 1535 1571 } 1536 # define getDevicesFromUsbfs testGetUsbfsDevices1572 # define usbfsGetDevices testGetUsbfsDevices 1537 1573 1538 1574 /** … … 1541 1577 * @param pacszDeviceAddresses NULL terminated array of usbfs device addresses 1542 1578 */ 1543 void TestUSBSetAvailableUsbfsDevices(const char **pa cszDeviceAddresses)1544 { 1545 s_pacszUsbfsDeviceAddresses = pacszDeviceAddresses;1579 void TestUSBSetAvailableUsbfsDevices(const char **papszDeviceAddresses) 1580 { 1581 g_papszUsbfsDeviceAddresses = papszDeviceAddresses; 1546 1582 } 1547 1583 1548 1584 /** Unit test list of files reported as accessible by access(3). We only do 1549 1585 * accessible or not accessible. */ 1550 static const char ** s_pacszAccessibleFiles = NULL;1586 static const char **g_papszAccessibleFiles = NULL; 1551 1587 1552 1588 static int testAccess(const char *pcszPath, int mode) 1553 1589 { 1554 1590 const char **pcsz; 1555 for (pcsz = s_pacszAccessibleFiles; pcsz && *pcsz; ++pcsz)1591 for (pcsz = g_papszAccessibleFiles; pcsz && *pcsz; ++pcsz) 1556 1592 if (!RTStrCmp(pcszPath, *pcsz)) 1557 1593 return 0; … … 1560 1596 # define access testAccess 1561 1597 1598 1562 1599 /** 1563 1600 * Specify the list of files that access will report as accessible (at present 1564 1601 * we only do accessible or not accessible) during unit testing (of 1565 1602 * USBProxyLinuxGetDevices) 1566 * @param pa cszAccessibleFiles NULL terminated array of file paths to be1603 * @param papszAccessibleFiles NULL terminated array of file paths to be 1567 1604 * reported accessible 1568 1605 */ 1569 void TestUSBSetAccessibleFiles(const char **pacszAccessibleFiles) 1570 { 1571 s_pacszAccessibleFiles = pacszAccessibleFiles; 1572 } 1573 #endif 1574 1575 #ifdef UNIT_TEST 1606 void TestUSBSetAccessibleFiles(const char **papszAccessibleFiles) 1607 { 1608 g_papszAccessibleFiles = papszAccessibleFiles; 1609 } 1610 1611 1576 1612 # ifdef UNIT_TEST 1577 1613 /** The path we pretend the usbfs root is located at, or NULL. */ … … 1591 1627 # endif 1592 1628 1629 1593 1630 /** Select which access methods will be available to the @a init method 1594 1631 * during unit testing, and (hack!) what return code it will see from … … 1604 1641 s_rcTestMethodInitResult = rcMethodInitResult; 1605 1642 } 1643 1606 1644 1607 1645 /** Specify the environment that the @a init method will see during unit … … 1633 1671 && !RTStrNCmp(pcszFile, s_pcszTestUsbfsRoot, strlen(s_pcszTestUsbfsRoot)) \ 1634 1672 && !RTStrCmp(pcszFile + strlen(s_pcszTestUsbfsRoot), "/devices")) 1635 #endif 1636 1637 /** 1673 1674 #endif /* UNIT_TEST */ 1675 1676 /** 1677 * Use USBFS-like or sysfs/device node-like access method? 1678 * 1638 1679 * Selects the access method that will be used to access USB devices based on 1639 1680 * what is available on the host and what if anything the user has specified 1640 1681 * in the environment. 1682 * 1641 1683 * @returns iprt status value 1642 1684 * @param pfUsingUsbfsDevices on success this will be set to true if … … 1646 1688 * device nodes will be stored here 1647 1689 */ 1648 int USBProxyLinuxChooseMethod(bool *pfUsingUsbfsDevices, 1649 const char **ppcszDevicesRoot) 1690 int USBProxyLinuxChooseMethod(bool *pfUsingUsbfsDevices, const char **ppcszDevicesRoot) 1650 1691 { 1651 1692 /* … … 1658 1699 * the root they provide for validity. 1659 1700 */ 1660 bool fUsbfsChosen = false, fSysfsChosen = false; 1701 bool fUsbfsChosen = false; 1702 bool fSysfsChosen = false; 1661 1703 const char *pcszUsbFromEnv = RTEnvGet("VBOX_USB"); 1662 1704 const char *pcszUsbRoot = NULL; … … 1710 1752 } 1711 1753 /* else */ 1712 return 1713 1714 1715 1754 return pcszUsbFromEnv ? VERR_NOT_FOUND 1755 : RTDirExists("/dev/vboxusb") ? VERR_VUSB_USB_DEVICE_PERMISSION 1756 : RTFileExists("/proc/bus/usb/devices") ? VERR_VUSB_USBFS_PERMISSION 1757 : VERR_NOT_FOUND; 1716 1758 } 1717 1759 … … 1725 1767 /** 1726 1768 * Check whether a USB device tree root is usable 1769 * 1727 1770 * @param pcszRoot the path to the root of the device tree 1728 1771 * @param fIsDeviceNodes whether this is a device node (or usbfs) tree … … 1739 1782 { 1740 1783 fOK = true; 1741 pDevices = getDevicesFromUsbfs(pcszRoot, true);1784 pDevices = usbfsGetDevices(pcszRoot, true); 1742 1785 if (pDevices) 1743 1786 { … … 1751 1794 } 1752 1795 } 1753 else/* device nodes */1754 if (inotifyAvailable() && !access(pcszRoot, R_OK | X_OK))1755 1796 /* device nodes */ 1797 else if (usbsysfsInotifyAvailable() && !access(pcszRoot, R_OK | X_OK)) 1798 fOK = true; 1756 1799 return fOK; 1757 1800 } 1758 1801 1759 1802 #ifdef UNIT_TEST 1760 # undef getDevicesFromUsbfs1803 # undef usbfsGetDevices 1761 1804 # undef access 1762 1805 #endif … … 1773 1816 { 1774 1817 if (!fUseSysfs) 1775 return getDevicesFromUsbfs(pcszDevicesRoot, false);1776 return getDevicesFromSysfs(pcszDevicesRoot, false);1777 } 1818 return usbfsGetDevices(pcszDevicesRoot, false); 1819 return usbsysfsGetDevices(pcszDevicesRoot, false); 1820 }
Note:
See TracChangeset
for help on using the changeset viewer.