/* * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include "ExternalMedia.h" #include "PMAssertions.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 IOPMAssertionID 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; /* We will create an ExternalMedia assertion if any of these disks are present. That will prevent deep sleep. USB hard drive : Protocol = USB USB thumb drive : Protocol = USB SD Card : Protocol = USB, Protocol = Secure Digital External drive : Interconnect Location = External These disks do not cause us to create an ExternalMedia assertion; CD/DVD : Protocol = ATAPI Disk Image : Protocol = Disk Image */ description = DADiskCopyDescription(disk); if (description) { if (CFDictionaryGetValue(description, kDADiskDescriptionDeviceInternalKey) == kCFBooleanFalse) { ret = true; } else { protocol = CFDictionaryGetValue(description, kDADiskDescriptionDeviceProtocolKey); if (protocol && (CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeUSB)) || CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeSecureDigital)))) { ret = true; } } CFRelease(description); } return ret; } /*****************************************************************************/ static void adjustExternalDiskAssertion() { CFIndex deviceCount = CFSetGetCount(gExternalMediaSet); if (0 == deviceCount) { /* * Release assertion */ InternalReleaseAssertion(&gDiskAssertionID); return; } if (0 < deviceCount) { /* * Create new assertion */ CFMutableDictionaryRef assertionDescription = NULL; assertionDescription = _IOPMAssertionDescriptionCreate( _kIOPMAssertionTypeExternalMedia, CFSTR(_kExternalMediaAssertionName), NULL, CFSTR("An external media device is attached."), NULL, 0, NULL); InternalCreateAssertion(assertionDescription, &gDiskAssertionID); CFRelease(assertionDescription); return; } return; } #endif