#include <CoreFoundation/CoreFoundation.h>
#include <DiskArbitration/DiskArbitration.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
#include "ExternalMedia.h"
#include "SetActive.h"
#include "PrivateLib.h"
#if !TARGET_OS_EMBEDDED
#define _kExternalMediaAssertionName "com.apple.powermanagement.externalmediamounted"
static bool weLikeTheDisk(DADiskRef disk);
static void adjustExternalDiskAssertion(void);
static void _DiskDisappeared(DADiskRef disk, void *context);
static void _DiskAppeared(DADiskRef disk, void * context);
static CFMutableSetRef gExternalMediaSet = NULL;
static int gDiskAssertionID = kIOPMNullAssertionID;
static DASessionRef gDASession = NULL;
__private_extern__ void ExternalMedia_prime(void)
{
gExternalMediaSet = CFSetCreateMutable(0, 0, &kCFTypeSetCallBacks);
if (!gExternalMediaSet)
return;
gDASession = DASessionCreate(0);
DARegisterDiskAppearedCallback(gDASession, kDADiskDescriptionMatchVolumeMountable, _DiskAppeared, NULL);
DARegisterDiskDisappearedCallback(gDASession, kDADiskDescriptionMatchVolumeMountable, _DiskDisappeared, NULL);
DASessionScheduleWithRunLoop(gDASession, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
static void _DiskDisappeared(DADiskRef disk, void *context)
{
if (weLikeTheDisk(disk))
{
CFSetRemoveValue(gExternalMediaSet, disk);
adjustExternalDiskAssertion();
}
}
static void _DiskAppeared(DADiskRef disk, void * context)
{
if (weLikeTheDisk(disk))
{
CFSetSetValue(gExternalMediaSet, disk);
adjustExternalDiskAssertion();
}
}
static bool weLikeTheDisk(DADiskRef disk)
{
CFDictionaryRef description = NULL;
CFStringRef protocol = NULL;
bool ret = false;
description = DADiskCopyDescription(disk);
if (description) {
protocol = CFDictionaryGetValue(description, kDADiskDescriptionDeviceProtocolKey);
if (protocol && CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeUSB)))
{
ret = true;
}
CFRelease(description);
}
return ret;
}
static void adjustExternalDiskAssertion()
{
CFIndex deviceCount = CFSetGetCount(gExternalMediaSet);
if ((0 == deviceCount)
&& (kIOPMNullAssertionID != gDiskAssertionID))
{
InternalAssertionRelease(gDiskAssertionID);
gDiskAssertionID = kIOPMNullAssertionID;
return;
}
if ((0 < deviceCount)
&& (kIOPMNullAssertionID == gDiskAssertionID))
{
InternalAssertionCreate(_kExternalMediaAssertionName,
_kIOPMAssertionTypeExternalMediaCStr,
&gDiskAssertionID);
return;
}
return;
}
#endif