iokit.cpp revision a1360dcc0d6de125bf051b34a69e8d8cd268f82a
de6a40dbdd4712e5a9398b8519a59b1eaeab2f5aChristian Maeder * Main - Darwin IOKit Routines.
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian Maeder * Because IOKit makes use of COM like interfaces, it does not mix very
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * well with COM/XPCOM and must therefore be isolated from it using a
3f69b6948966979163bdfe8331c38833d5d90ecdChristian Maeder * simpler C interface.
f3a94a197960e548ecd6520bb768cb0d547457bbChristian Maeder * Copyright (C) 2006-2007 innotek GmbH
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * This file is part of VirtualBox Open Source Edition (OSE), as
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * available from http://www.virtualbox.org. This file is free software;
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * you can redistribute it and/or modify it under the terms of the GNU
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * General Public License as published by the Free Software Foundation,
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
d1126d58419412635564085406d3779325b33ae0Till Mossakowski * distribution. VirtualBox OSE is distributed in the hope that it will
7660d5932a1fb9677d07889714b677a059af2b2fChristian Maeder * be useful, but WITHOUT ANY WARRANTY of any kind.
ad270004874ce1d0697fb30d7309f180553bb315Christian Maeder * If you received this file as part of a commercial VirtualBox
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * distribution, then only the terms of your commercial VirtualBox
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski * license agreement apply instead of the previous paragraph.
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder/*******************************************************************************
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder* Header Files *
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski*******************************************************************************/
2dfb9a95c5586f73abda1d0f369d6d154b159452Sonja Gröning#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
0b7c8279c741857d1681160f8b4144a9430ffa7fTill Mossakowski#include <IOKit/scsi-commands/SCSITaskLib.h>
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder/*******************************************************************************
f4255fa60f8dcaa8f21ce60b2820c228a19e39aeChristian Maeder* Defined Constants And Macros *
f4255fa60f8dcaa8f21ce60b2820c228a19e39aeChristian Maeder*******************************************************************************/
f4255fa60f8dcaa8f21ce60b2820c228a19e39aeChristian Maeder/** An attempt at catching reference leaks. */
5c358300e78157f4bfaf5415c70e1096a9205b61Christian Maeder#define MY_CHECK_CREFS(cRefs) do { AssertMsg(cRefs < 25, ("%ld\n", cRefs)); NOREF(cRefs); } while (0)
5c358300e78157f4bfaf5415c70e1096a9205b61Christian Maeder/** Contains the pid of the current client. If 0, the kernel is the current client. */
5c358300e78157f4bfaf5415c70e1096a9205b61Christian Maeder/** Contains the pid of the filter owner (i.e. the VBoxSVC pid). */
5c358300e78157f4bfaf5415c70e1096a9205b61Christian Maeder/** The VBoxUSBDevice class name. */
5c358300e78157f4bfaf5415c70e1096a9205b61Christian Maeder#define VBOXUSBDEVICE_CLASS_NAME "org_virtualbox_VBoxUSBDevice"
578b677874296e4ba48e57b5e4b4b0270d995603Christian Maeder/*******************************************************************************
578b677874296e4ba48e57b5e4b4b0270d995603Christian Maeder* Global Variables *
88ece6e49930670e8fd3ee79c89a2e918d2fbd0cChristian Maeder*******************************************************************************/
578b677874296e4ba48e57b5e4b4b0270d995603Christian Maeder/** The IO Master Port. */
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * Lazily opens the master port.
d48085f765fca838c1d972d2123601997174583dChristian Maeder * @returns true if the port is open, false on failure (very unlikely).
d48085f765fca838c1d972d2123601997174583dChristian Maeder kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &g_MasterPort);
a39a820684c1974350f46593025e0bb279f41bc6Christian Maeder * Gets an unsigned 8-bit integer value.
f4255fa60f8dcaa8f21ce60b2820c228a19e39aeChristian Maeder * @returns Success indicator (true/false).
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * @param DictRef The dictionary.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @param KeyStrRef The key name.
975642b989852fc24119c59cf40bc1af653608ffChristian Maeder * @param pu8 Where to store the key value.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maederstatic bool darwinDictGetU8(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint8_t *pu8)
975642b989852fc24119c59cf40bc1af653608ffChristian Maeder CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
975642b989852fc24119c59cf40bc1af653608ffChristian Maeder if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt8Type, pu8))
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder return false;
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * Gets an unsigned 16-bit integer value.
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * @returns Success indicator (true/false).
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * @param DictRef The dictionary.
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * @param KeyStrRef The key name.
975642b989852fc24119c59cf40bc1af653608ffChristian Maeder * @param pu16 Where to store the key value.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maederstatic bool darwinDictGetU16(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint16_t *pu16)
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
f454c20b6c126bea7d31d400cc8824b9ee8cc6eaChristian Maeder if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt16Type, pu16))
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder return false;
8731f7b93b26083dc34a2c0937cd6493b42f2c2cTill Mossakowski * Gets an unsigned 32-bit integer value.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @returns Success indicator (true/false).
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @param DictRef The dictionary.
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * @param KeyStrRef The key name.
abe0293c13ccb9c7c864e780181f370155de5658Christian Maeder * @param pu32 Where to store the key value.
ee34c4e1b244e46682a84bc52224f52289bd1950Christian Maederstatic bool darwinDictGetU32(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint32_t *pu32)
ee34c4e1b244e46682a84bc52224f52289bd1950Christian Maeder CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt32Type, pu32))
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder return false;
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * Gets an unsigned 64-bit integer value.
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder * @returns Success indicator (true/false).
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder * @param DictRef The dictionary.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @param KeyStrRef The key name.
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder * @param pu64 Where to store the key value.
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maederstatic bool darwinDictGetU64(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint64_t *pu64)
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt64Type, pu64))
10f1342d686ed68712a2b25ed65fa5a18f9c3db7Christian Maeder return false;
f7d2e793728bbb7fd185e027eb9dfd7b9dd11c21Christian Maeder * Gets a RTPROCESS value.
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder * @returns Success indicator (true/false).
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder * @param DictRef The dictionary.
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder * @param KeyStrRef The key name.
27e8de893356be63440b1b8aa2c4f19fbaf399acChristian Maeder * @param pProcess Where to store the key value.
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maederstatic bool darwinDictGetProccess(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, PRTPROCESS pProcess)
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder switch (sizeof(*pProcess))
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder case sizeof(uint16_t): return darwinDictGetU16(DictRef, KeyStrRef, (uint16_t *)pProcess);
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder case sizeof(uint32_t): return darwinDictGetU32(DictRef, KeyStrRef, (uint32_t *)pProcess);
10f1342d686ed68712a2b25ed65fa5a18f9c3db7Christian Maeder case sizeof(uint64_t): return darwinDictGetU64(DictRef, KeyStrRef, (uint64_t *)pProcess);
26d11a256b1433604a3dbc69913b520fff7586acChristian Maeder AssertMsgFailedReturn(("%d\n", sizeof(*pProcess)), false);
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder * Gets string value, converted to UTF-8 and put in a IPRT string buffer.
ee34c4e1b244e46682a84bc52224f52289bd1950Christian Maeder * @returns Success indicator (true/false).
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @param DictRef The dictionary.
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder * @param KeyStrRef The key name.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @param ppsz Where to store the key value. Free with RTStrFree. Set to NULL on failure.
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maederstatic bool darwinDictGetString(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, char **ppsz)
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
ee34c4e1b244e46682a84bc52224f52289bd1950Christian Maeder if (CFStringGetCString((CFStringRef)ValRef, szBuf, sizeof(szBuf), kCFStringEncodingUTF8))
d48085f765fca838c1d972d2123601997174583dChristian Maeder return false;
6f5bf1e81c4669f7c605e13548861a1207b0c7e8Christian Maeder# define DARWIN_IOKIT_LOG_FLUSH() do {} while (0)
6f5bf1e81c4669f7c605e13548861a1207b0c7e8Christian Maeder# define DARWIN_IOKIT_DUMP_OBJ(o) do {} while (0)
78d4b9e3558a2523c3335b1399385ac7d246f0c1Christian Maeder# define DARWIN_IOKIT_LOG_FLUSH() RTStrmFlush(g_pStdOut)
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder# define DARWIN_IOKIT_DUMP_OBJ(o) darwinDumpObj(o)
d48085f765fca838c1d972d2123601997174583dChristian Maeder * Callback for dumping a dictionary key.
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder * @param pvKey The key name.
d48085f765fca838c1d972d2123601997174583dChristian Maeder * @param pvValue The key value
d48085f765fca838c1d972d2123601997174583dChristian Maeder * @param pvUser The recursion depth.
26d11a256b1433604a3dbc69913b520fff7586acChristian Maederstatic void darwinDumpDictCallback(const void *pvKey, const void *pvValue, void *pvUser)
7c2d602a73afe304ac0ca225ecff42b2ae8bdab3Christian Maeder /* display the key name. */
ee34c4e1b244e46682a84bc52224f52289bd1950Christian Maeder char *pszKey = (char *)RTMemTmpAlloc(1024);
03fc25805985563b679dd75c31a6e05287c1632eChristian Maeder if (!CFStringGetCString((CFStringRef)pvKey, pszKey, 1024, kCFStringEncodingUTF8))
6f5bf1e81c4669f7c605e13548861a1207b0c7e8Christian Maeder strcpy(pszKey, "CFStringGetCString failure");
6f5bf1e81c4669f7c605e13548861a1207b0c7e8Christian Maeder DARWIN_IOKIT_LOG(("%+*s%s", (int)(uintptr_t)pvUser, "", pszKey));
6f5bf1e81c4669f7c605e13548861a1207b0c7e8Christian Maeder /* display the value type */
ee34c4e1b244e46682a84bc52224f52289bd1950Christian Maeder /* display the value */
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder CFDictionaryApplyFunction((CFDictionaryRef)pvValue, darwinDumpDictCallback, (void *)((uintptr_t)pvUser + 4));
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder DARWIN_IOKIT_LOG(("%-*s}\n", (int)(uintptr_t)pvUser, ""));
char ch;
long long ll;
float rf;
double rd;
memset(&u, 0, sizeof(u));
case kCFNumberSInt16Type: DARWIN_IOKIT_LOG(("SInt16] = %RI16 (%#RX16)\n", NumType, u.s16, u.s16)); break;
case kCFNumberSInt32Type: DARWIN_IOKIT_LOG(("SInt32] = %RI32 (%#RX32)\n", NumType, u.s32, u.s32)); break;
case kCFNumberSInt64Type: DARWIN_IOKIT_LOG(("SInt64] = %RI64 (%#RX64)\n", NumType, u.s64, u.s64)); break;
case kCFNumberLongLongType: DARWIN_IOKIT_LOG(("long long] = %lld (%#llx)\n", NumType, u.ll, u.ll)); break;
case kCFNumberCFIndexType: DARWIN_IOKIT_LOG(("CFIndex] = %lld (%#llx)\n", NumType, (long long)u.iCF, (long long)u.iCF)); break;
typedef struct DARWINUSBNOTIFY
void *DarwinSubscribeUSBNotifications(void)
return pNotify;
return NULL;
if (!pNotify)
static io_object_t darwinFindObjectByClass(io_object_t Object, const char *pszClass, io_name_t pszNameBuf)
return NULL;
if (GrandChild)
return Child;
if (MediaObj)
static void darwinDeterminUSBDeviceState(PUSBDEVICE pCur, io_object_t USBDevice, CFMutableDictionaryRef PropsRef)
bool fUserClientOnly = true;
bool fConfigured = false;
bool fInUse = false;
bool fSeizable = true;
fConfigured = true;
fUserClientOnly = false;
fSeizable = false;
fSeizable = false;
fInUse = true;
fInUse = true;
&& !Owner)
else if (fUserClientOnly)
else if (!fInUse)
kern_return_t krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions);
bool fOk = false;
pCur->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; /* just a default, we'll try harder in a bit. */
//IOReturn (*GetConfigurationDescriptorPtr)(void *self, UInt8 configIndex, IOUSBConfigurationDescriptorPtr *desc);
//IOReturn (*CreateInterfaceIterator)(void *self, IOUSBFindInterfaceRequest *req, io_iterator_t *iter);
if (pTail)
fOk = true;
if ( ( !pKeyboard
else if ( ( !pMouse
if (pKeyboard)
if (pMouse)
return pHead;
int vrc;
* This code is a short version of the Open method in USBProxyDevice-darwin.cpp stuff.
switch (chValue)
CFDictionarySetValue(RefMatchingDict, chValue == 'p' ? CFSTR(kUSBProductID) : CFSTR(kUSBVendorID), Num);
psz++;
} while (*psz);
unsigned cMatches = 0;
cMatches++;
kern_return_t krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions);
if ( ( !u64SessionId
&& ( !u32LocationId
if (!USBDevice)
return VERR_VUSB_DEVICE_NAME_NOT_FOUND;
LogRel(("USB: Failed to open device '%s', plug-in creation failed with irc=%#x.\n", pszAddress, irc));
LogRel(("USB: Failed to open device '%s', plug-in creation failed with irc=%#x.\n", pszAddress, irc));
return vrc;
* (This enumeration must be identical to the one performed in DrvHostBase.cpp.)
kern_return_t krc = IORegistryEntryCreateCFProperties(DVDService, &PropsRef, kCFAllocatorDefault, kNilOptions);
CFDictionaryRef DevCharRef = (CFDictionaryRef)CFDictionaryGetValue(PropsRef, CFSTR(kIOPropertyDeviceCharacteristicsKey));
if (DevCharRef)
if ( ValueRef
if ( ValueRef
if (pNew)
if (pTail)
return pHead;