Changeset 59374 in vbox for trunk/src/VBox/Main/src-server/darwin/iokit.cpp
- Timestamp:
- Jan 18, 2016 11:49:16 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/darwin/iokit.cpp
r59332 r59374 542 542 } DARWINUSBNOTIFY, *PDARWINUSBNOTIFY; 543 543 544 /**545 * Returns the correct class name to identify USB devices. El Capitan546 * introduced a reworked USb stack with changed names.547 * The old names are still available but the objects don't reveal all the548 * information required.549 */550 DECLINLINE(const char *)darwinGetUsbDeviceClassName(void)551 {552 return g_uMajorDarwin >= VBOX_OSX_EL_CAPTIAN_VER553 ? kIOUSBHostDeviceClassName554 : kIOUSBDeviceClassName;555 }556 544 557 545 /** … … 656 644 kern_return_t rc = IOServiceAddMatchingNotification(pNotify->NotifyPort, 657 645 kIOPublishNotification, 658 IOServiceMatching( darwinGetUsbDeviceClassName()),646 IOServiceMatching(kIOUSBDeviceClassName), 659 647 darwinUSBAttachNotification1, 660 648 pNotify, … … 665 653 rc = IOServiceAddMatchingNotification(pNotify->NotifyPort, 666 654 kIOMatchedNotification, 667 IOServiceMatching( darwinGetUsbDeviceClassName()),655 IOServiceMatching(kIOUSBDeviceClassName), 668 656 darwinUSBAttachNotification2, 669 657 pNotify, … … 674 662 rc = IOServiceAddMatchingNotification(pNotify->NotifyPort, 675 663 kIOTerminatedNotification, 676 IOServiceMatching( darwinGetUsbDeviceClassName()),664 IOServiceMatching(kIOUSBDeviceClassName), 677 665 darwinUSBDetachNotification, 678 666 pNotify, … … 800 788 } 801 789 802 803 /** 804 * Worker function for DarwinGetUSBDevices() that tries to figure out 805 * what state the device is in and set enmState. 806 * 807 * This is mostly a matter of distinguishing between devices that nobody 808 * uses, devices that can be seized and devices that cannot be grabbed. 809 * 810 * @param pCur The USB device data. 811 * @param USBDevice The USB device object. 812 * @param PropsRef The USB device properties. 813 */ 814 static void darwinDeterminUSBDeviceState(PUSBDEVICE pCur, io_object_t USBDevice, CFMutableDictionaryRef /* PropsRef */) 790 /** 791 * Finds the matching IOUSBHostDevice registry entry for the given legacy USB device interface (IOUSBDevice). 792 * 793 * @returns kern_return_t error code. 794 * @param USBDeviceLegacy The legacy device I/O Kit object. 795 * @param pUSBDevice Where to store the IOUSBHostDevice object on success. 796 */ 797 static kern_return_t darwinGetUSBHostDeviceFromLegacyDevice(io_object_t USBDeviceLegacy, io_object_t *pUSBDevice) 798 { 799 kern_return_t krc = KERN_SUCCESS; 800 uint64_t uIoRegEntryId = 0; 801 802 *pUSBDevice = 0; 803 804 /* Get the registry entry ID to match against. */ 805 krc = IORegistryEntryGetRegistryEntryID(USBDeviceLegacy, &uIoRegEntryId); 806 if (krc != KERN_SUCCESS) 807 return krc; 808 809 /* 810 * Create a matching dictionary for searching for USB Devices in the IOKit. 811 */ 812 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBHostDeviceClassName); 813 AssertReturn(RefMatchingDict, KERN_FAILURE); 814 815 /* 816 * Perform the search and get a collection of USB Device back. 817 */ 818 io_iterator_t USBDevices = NULL; 819 IOReturn rc = IOServiceGetMatchingServices(g_MasterPort, RefMatchingDict, &USBDevices); 820 AssertMsgReturn(rc == kIOReturnSuccess, ("rc=%d\n", rc), KERN_FAILURE); 821 RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */ 822 823 /* 824 * Walk the devices and check for the matching alternate registry entry ID. 825 */ 826 io_object_t USBDevice; 827 while ((USBDevice = IOIteratorNext(USBDevices)) != 0) 828 { 829 DARWIN_IOKIT_DUMP_OBJ(USBDevice); 830 831 CFMutableDictionaryRef PropsRef = 0; 832 krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions); 833 if (krc == KERN_SUCCESS) 834 { 835 uint64_t uAltRegId = 0; 836 if ( darwinDictGetU64(PropsRef, CFSTR("AppleUSBAlternateServiceRegistryID"), &uAltRegId) 837 && uAltRegId == uIoRegEntryId) 838 { 839 *pUSBDevice = USBDevice; 840 CFRelease(PropsRef); 841 break; 842 } 843 844 CFRelease(PropsRef); 845 } 846 IOObjectRelease(USBDevice); 847 } 848 IOObjectRelease(USBDevices); 849 850 return krc; 851 } 852 853 static bool darwinUSBDeviceIsGrabbedDetermineState(PUSBDEVICE pCur, io_object_t USBDevice) 854 { 855 /* 856 * Iterate the interfaces (among the children of the IOUSBDevice object). 857 */ 858 io_iterator_t Interfaces; 859 kern_return_t krc = IORegistryEntryGetChildIterator(USBDevice, kIOServicePlane, &Interfaces); 860 if (krc != KERN_SUCCESS) 861 return false; 862 863 bool fHaveOwner = false; 864 RTPROCESS Owner = NIL_RTPROCESS; 865 bool fHaveClient = false; 866 RTPROCESS Client = NIL_RTPROCESS; 867 io_object_t Interface; 868 while ((Interface = IOIteratorNext(Interfaces)) != 0) 869 { 870 io_name_t szName; 871 krc = IOObjectGetClass(Interface, szName); 872 if ( krc == KERN_SUCCESS 873 && !strcmp(szName, VBOXUSBDEVICE_CLASS_NAME)) 874 { 875 CFMutableDictionaryRef PropsRef = 0; 876 krc = IORegistryEntryCreateCFProperties(Interface, &PropsRef, kCFAllocatorDefault, kNilOptions); 877 if (krc == KERN_SUCCESS) 878 { 879 fHaveOwner = darwinDictGetProcess(PropsRef, CFSTR(VBOXUSB_OWNER_KEY), &Owner); 880 fHaveClient = darwinDictGetProcess(PropsRef, CFSTR(VBOXUSB_CLIENT_KEY), &Client); 881 CFRelease(PropsRef); 882 } 883 } 884 885 IOObjectRelease(Interface); 886 } 887 IOObjectRelease(Interfaces); 888 889 /* 890 * Calc the status. 891 */ 892 if (fHaveOwner) 893 { 894 if (Owner == RTProcSelf()) 895 pCur->enmState = !fHaveClient || Client == NIL_RTPROCESS || !Client 896 ? USBDEVICESTATE_HELD_BY_PROXY 897 : USBDEVICESTATE_USED_BY_GUEST; 898 else 899 pCur->enmState = USBDEVICESTATE_USED_BY_HOST; 900 } 901 902 return fHaveOwner; 903 } 904 905 /** 906 * Worker for determining the USB device state for devices which are not captured by the VBoxUSB driver 907 * Works for both, IOUSBDevice (legacy on release >= El Capitan) and IOUSBHostDevice (available on >= El Capitan). 908 * 909 * @returns nothing. 910 * @param pCur The USB device data. 911 * @param USBDevice I/O Kit USB device object (either IOUSBDevice or IOUSBHostDevice). 912 */ 913 static void darwinDetermineUSBDeviceStateWorker(PUSBDEVICE pCur, io_object_t USBDevice) 815 914 { 816 915 /* … … 822 921 return; 823 922 824 bool fHaveOwner = false;825 RTPROCESS Owner = NIL_RTPROCESS;826 bool fHaveClient = false;827 RTPROCESS Client = NIL_RTPROCESS;828 923 bool fUserClientOnly = true; 829 924 bool fConfigured = false; … … 831 926 bool fSeizable = true; 832 927 io_object_t Interface; 833 while ((Interface = IOIteratorNext(Interfaces)) )928 while ((Interface = IOIteratorNext(Interfaces)) != 0) 834 929 { 835 930 io_name_t szName; 836 931 krc = IOObjectGetClass(Interface, szName); 837 932 if ( krc == KERN_SUCCESS 838 && !strcmp(szName, "IOUSBInterface")) 933 && ( !strcmp(szName, "IOUSBInterface") 934 || !strcmp(szName, "IOUSBHostInterface"))) 839 935 { 840 936 fConfigured = true; … … 849 945 { 850 946 io_object_t Child1; 851 while ((Child1 = IOIteratorNext(Children1)) )947 while ((Child1 = IOIteratorNext(Children1)) != 0) 852 948 { 853 949 krc = IOObjectGetClass(Child1, szName); … … 883 979 } 884 980 } 885 /*886 * Not an interface, could it be VBoxUSBDevice?887 * If it is, get the owner and client properties.888 */889 else if ( krc == KERN_SUCCESS890 && !strcmp(szName, VBOXUSBDEVICE_CLASS_NAME))891 {892 CFMutableDictionaryRef PropsRef = 0;893 krc = IORegistryEntryCreateCFProperties(Interface, &PropsRef, kCFAllocatorDefault, kNilOptions);894 if (krc == KERN_SUCCESS)895 {896 fHaveOwner = darwinDictGetProcess(PropsRef, CFSTR(VBOXUSB_OWNER_KEY), &Owner);897 fHaveClient = darwinDictGetProcess(PropsRef, CFSTR(VBOXUSB_CLIENT_KEY), &Client);898 CFRelease(PropsRef);899 }900 }901 981 902 982 IOObjectRelease(Interface); … … 907 987 * Calc the status. 908 988 */ 909 if (fHaveOwner) 910 { 911 if (Owner == RTProcSelf()) 912 pCur->enmState = !fHaveClient || Client == NIL_RTPROCESS || !Client 913 ? USBDEVICESTATE_HELD_BY_PROXY 914 : USBDEVICESTATE_USED_BY_GUEST; 915 else 916 pCur->enmState = USBDEVICESTATE_USED_BY_HOST; 917 } 918 else if (fUserClientOnly) 919 /** @todo how to detect other user client?!? - Look for IOUSBUserClient! */ 920 pCur->enmState = !fConfigured 921 ? USBDEVICESTATE_UNUSED 922 : USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; 923 else if (!fInUse) 989 if (!fInUse) 924 990 pCur->enmState = USBDEVICESTATE_UNUSED; 925 991 else … … 929 995 } 930 996 997 /** 998 * Worker function for DarwinGetUSBDevices() that tries to figure out 999 * what state the device is in and set enmState. 1000 * 1001 * This is mostly a matter of distinguishing between devices that nobody 1002 * uses, devices that can be seized and devices that cannot be grabbed. 1003 * 1004 * @param pCur The USB device data. 1005 * @param USBDevice The USB device object. 1006 * @param PropsRef The USB device properties. 1007 */ 1008 static void darwinDeterminUSBDeviceState(PUSBDEVICE pCur, io_object_t USBDevice, CFMutableDictionaryRef /* PropsRef */) 1009 { 1010 1011 if (!darwinUSBDeviceIsGrabbedDetermineState(pCur, USBDevice)) 1012 { 1013 /* 1014 * The USB stack was completely reworked on El Capitan and the IOUSBDevice and IOUSBInterface 1015 * are deprecated and don't return the information required for the additional checks below. 1016 * We also can't directly make use of the new classes (IOUSBHostDevice and IOUSBHostInterface) 1017 * because VBoxUSB only exposes the legacy interfaces. Trying to use the new classes results in errors 1018 * because the I/O Kit USB library wants to use the new interfaces. The result is us losing the device 1019 * form the list when VBoxUSB has attached to the USB device. 1020 * 1021 * To make the checks below work we have to get hold of the IOUSBHostDevice and IOUSBHostInterface 1022 * instances for the current device. Fortunately the IOUSBHostDevice instance contains a 1023 * "AppleUSBAlternateServiceRegistryID" which points to the legacy class instance for the same device. 1024 * So just iterate over the list of IOUSBHostDevice instances and check whether the 1025 * AppleUSBAlternateServiceRegistryID property matches with the legacy instance. 1026 * 1027 * The upside is that we can keep VBoxUSB untouched and still compatible with older OS X releases. 1028 */ 1029 if (g_uMajorDarwin >= VBOX_OSX_EL_CAPTIAN_VER) 1030 { 1031 io_object_t IOUSBDeviceNew = 0; 1032 1033 io_object_t krc = darwinGetUSBHostDeviceFromLegacyDevice(USBDevice, &IOUSBDeviceNew); 1034 if ( krc == KERN_SUCCESS 1035 && IOUSBDeviceNew != 0) 1036 { 1037 darwinDetermineUSBDeviceStateWorker(pCur, IOUSBDeviceNew); 1038 IOObjectRelease(IOUSBDeviceNew); 1039 } 1040 } 1041 else 1042 darwinDetermineUSBDeviceStateWorker(pCur, USBDevice); 1043 } 1044 } 1045 931 1046 932 1047 /** … … 944 1059 * Create a matching dictionary for searching for USB Devices in the IOKit. 945 1060 */ 946 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching( darwinGetUsbDeviceClassName());1061 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBDeviceClassName); 947 1062 AssertReturn(RefMatchingDict, NULL); 948 1063 … … 1019 1134 darwinDictGetU8(PropsRef, CFSTR("PortNum"), &pCur->bPort); /* Not present in 10.11 beta 3, so ignore failure. (Is set to zero.) */ 1020 1135 uint8_t bSpeed; 1021 AssertBreak(darwinDictGetU8(PropsRef, 1022 g_uMajorDarwin >= VBOX_OSX_EL_CAPTIAN_VER 1023 ? CFSTR("USBSpeed") 1024 : CFSTR(kUSBDevicePropertySpeed), 1025 &bSpeed)); 1026 Assert(bSpeed <= 4); 1027 pCur->enmSpeed = bSpeed == 4 ? USBDEVICESPEED_SUPER /** @todo: Check what 4 really means (USB 3.1 perhaps?), seen on El Capitan. */ 1028 : bSpeed == 3 ? USBDEVICESPEED_SUPER 1136 AssertBreak(darwinDictGetU8(PropsRef, CFSTR(kUSBDevicePropertySpeed), &bSpeed)); 1137 Assert(bSpeed <= 3); 1138 pCur->enmSpeed = bSpeed == 3 ? USBDEVICESPEED_SUPER 1029 1139 : bSpeed == 2 ? USBDEVICESPEED_HIGH 1030 1140 : bSpeed == 1 ? USBDEVICESPEED_FULL … … 1177 1287 */ 1178 1288 1179 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching( darwinGetUsbDeviceClassName());1289 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBDeviceClassName); 1180 1290 AssertReturn(RefMatchingDict, NULL); 1181 1291
Note:
See TracChangeset
for help on using the changeset viewer.