- pmso = new PMSettingObject;
- if (!pmso || !pmso->init())
- goto fail;
-
- pmsh = new PMSettingHandle;
- if (!pmsh || !pmsh->init())
- goto fail;
-
- queue_init(&pmso->calloutQueue);
- pmso->parent = parent_arg;
- pmso->func = handler_arg;
- pmso->target = target_arg;
- pmso->refcon = refcon_arg;
- pmso->settingCount = settingCount;
-
- pmso->retain(); // handle holds a retain on pmso
- pmsh->pmso = pmso;
- pmso->pmsh = pmsh;
-
- pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t)*settingCount);
- if (pmso->publishedFeatureID) {
- for (unsigned int i=0; i<settingCount; i++) {
- // Since there is now at least one listener to this setting, publish
- // PM root domain support for it.
- parent_arg->publishPMSetting( settings[i],
- supportedPowerSources, &pmso->publishedFeatureID[i] );
- }
- }
-
- *handle_obj = pmsh;
- return pmso;
-
-fail:
- if (pmso) pmso->release();
- if (pmsh) pmsh->release();
- return NULL;
-}
-
-void PMSettingObject::free( void )
-{
- if (publishedFeatureID) {
- for (uint32_t i=0; i<settingCount; i++) {
- if (publishedFeatureID[i]) {
- parent->removePublishedFeature( publishedFeatureID[i] );
- }
- }
-
- IOFree(publishedFeatureID, sizeof(uint32_t) * settingCount);
- }
-
- super::free();
-}
-
-void PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
-{
- (*func)(target, type, object, refcon);
-}
-
-void PMSettingObject::clientHandleFreed( void )
-{
- parent->deregisterPMSettingObject(this);
-}
-
-// MARK: -
-// MARK: IOPMTimeline
-
-#undef super
-#define super OSObject
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-IOPMTimeline *IOPMTimeline::timeline(IOPMrootDomain *root_domain)
-{
- IOPMTimeline *myself;
-
- if (!root_domain)
- return NULL;
-
- myself = new IOPMTimeline;
-
- if (myself) {
- myself->owner = root_domain;
- myself->init();
- }
-
- return myself;
-}
-
-bool IOPMTimeline::init(void)
-{
- if (!super::init()) {
- return false;
- }
-
- logLock = IOLockAlloc();
-
- // Fresh timeline, no events logged yet
- this->numEventsLoggedThisPeriod = 0;
- this->sleepCycleInProgress = false;
-
- //this->setEventsRecordingLevel(1); // TODO
- this->setEventsTrackedCount(kIOPMDefaultSystemEventsTracked);
-
- return true;
-}
-
-void IOPMTimeline::free(void)
-{
- if (pmTraceMemoryDescriptor) {
- pmTraceMemoryDescriptor->release();
- pmTraceMemoryDescriptor = NULL;
- }
-
- IOLockFree(logLock);
-
- super::free();
-}
-
-IOMemoryDescriptor *IOPMTimeline::getPMTraceMemoryDescriptor()
-{
- return pmTraceMemoryDescriptor;
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-bool IOPMTimeline::setProperties(OSDictionary *d)
-{
- OSNumber *n = NULL;
- OSBoolean *b = NULL;
- bool changed = false;
-
- /* Changes size of detailed events buffer */
- n = (OSNumber *)d->getObject(kIOPMTimelineSystemNumberTrackedKey);
- if (OSDynamicCast(OSNumber, n))
- {
- changed = true;
- this->setEventsTrackedCount(n->unsigned32BitValue());
- }
-
-
- /* enables or disables system events */
- b = (OSBoolean *)d->getObject(kIOPMTimelineEnabledKey);
- if (b)
- {
- changed = true;
- this->setEventsRecordingLevel((int)(kOSBooleanTrue == b));
- }
-
- return changed;
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-OSDictionary *IOPMTimeline::copyInfoDictionary(void)
-{
- OSDictionary *out = OSDictionary::withCapacity(3);
- OSNumber *n = NULL;
-
- if (!out || !hdr)
- return NULL;
-
- n = OSNumber::withNumber(hdr->sizeEntries, 32);
- out->setObject(kIOPMTimelineSystemNumberTrackedKey, n);
- n->release();
-
- n = OSNumber::withNumber(hdr->sizeBytes, 32);
- out->setObject(kIOPMTimelineSystemBufferSizeKey, n);
- n->release();
-
- // bool
- out->setObject(kIOPMTimelineEnabledKey, eventsRecordingLevel ? kOSBooleanTrue : kOSBooleanFalse);
-
- return out;
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-/* IOPMTimeline::recordSystemPowerEvent()
- *
- * Expected "type" arguments are listed in IOPMPrivate.h under enum "SystemEventTypes"
- * Type arguments include "system events", and "Intermediate events"
- *
- * - System Events have paired "start" and "stop" events.
- * - A start event shall be followed by a stop event.
- * - Any number of Intermediate Events may fall between the
- * start and stop events.
- * - Intermediate events are meaningless outside the bounds of a system event's
- * start & stoup routines.
- * - It's invalid to record a Start event without a following Stop event; e.g. two
- * Start events without an intervenining Stop event is invalid.
- *
- * Buffer invariants
- * - The first recorded system event shall be preceded by an entry with type == 0
- * - IOPMTimeline may choose not to record intermediate events while there's not
- * a system event in process.
- */
-IOReturn IOPMTimeline::recordSystemPowerEvent( PMEventDetails *details )
-{
- static bool wakeDonePending = true;
- IOPMSystemEventRecord *record_to = NULL;
- OSString *swUUIDKey = NULL;
- uint32_t useIndex = 0;
-
- if (!details)
- return kIOReturnBadArgument;
-
- if (!traceBuffer)
- return kIOReturnNotReady;
-
- if (details->eventType == kIOPMEventTypeWakeDone)
- {
- if(!wakeDonePending)
- return kIOReturnBadArgument;
- }
-
- IOLockLock(logLock);
-
- if (details->eventType == kIOPMEventTypeWake) {
- wakeDonePending = true;
- } else if (details->eventType == kIOPMEventTypeWakeDone) {
- wakeDonePending = false;
- }
-
- systemState = details->eventType;
-
- useIndex = _atomicIndexIncrement(&hdr->index, hdr->sizeEntries);
-
- // The entry immediately after the latest entry (and thus
- // immediately before the first entry) shall have a type 0.
- if (useIndex + 1 >= hdr->sizeEntries) {
- traceBuffer[useIndex + 1].eventType = 0;
- } else {
- traceBuffer[0].eventType = 0;
- }
-
- record_to = &traceBuffer[useIndex];
- bzero(record_to, sizeof(IOPMSystemEventRecord));
-
- /*****/
- record_to->eventType = details->eventType;
- record_to->eventReason = details->reason;
- record_to->eventResult = details->result;
- pmEventTimeStamp(&record_to->timestamp);
-
- // If caller doesn't provide a UUID, we'll use the UUID that's posted
- // on IOPMrootDomain under key kIOPMSleepWakeUUIDKey
- if (!details->uuid) {
- swUUIDKey = OSDynamicCast(OSString, owner->copyProperty(kIOPMSleepWakeUUIDKey));
-
- if (swUUIDKey)
- details->uuid = swUUIDKey->getCStringNoCopy();
- }
-
- if (details->uuid)
- strncpy(record_to->uuid, details->uuid, kMaxPMStringLength);
-
- if (swUUIDKey)
- swUUIDKey->release();
-
- numEventsLoggedThisPeriod++;
- /*****/
-
- IOLockUnlock(logLock);
-
- return kIOReturnSuccess;
-
-}
-
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-IOReturn IOPMTimeline::recordDetailedPowerEvent( PMEventDetails *details )
-{
- IOPMSystemEventRecord *record_to = NULL;
- uint32_t useIndex;
-
- if (!details->eventType || !details->ownerName)
- return kIOReturnBadArgument;
-
- IOLockLock(logLock);
-
- useIndex = _atomicIndexIncrement(&hdr->index, hdr->sizeEntries);
-
- record_to = (IOPMSystemEventRecord *)&traceBuffer[useIndex];
- bzero(record_to, sizeof(IOPMSystemEventRecord));
-
- /*****/
- record_to->eventType = details->eventType;
- if (details->ownerName && (strlen(details->ownerName) > 1)) {
- strlcpy( record_to->ownerName,
- details->ownerName,
- sizeof(record_to->ownerName));
- }
-
- record_to->ownerDisambiguateID = details->ownerUnique;
-
- if (details->interestName && (strlen(details->interestName) > 1)) {
- strlcpy(record_to->interestName,
- details->interestName,
- sizeof(record_to->interestName));
- }
-
- record_to->oldState = details->oldState;
- record_to->newState = details->newState;
- record_to->eventResult = details->result;
- record_to->elapsedTimeUS = details->elapsedTimeUS;
- pmEventTimeStamp(&record_to->timestamp);
-
- numEventsLoggedThisPeriod++;
- /*****/
-
- IOLockUnlock(logLock);
- return kIOReturnSuccess;
-}
-
-uint32_t IOPMTimeline::getNumEventsLoggedThisPeriod() {
- return this->numEventsLoggedThisPeriod;
-}
-
-void IOPMTimeline::setNumEventsLoggedThisPeriod(uint32_t newCount) {
- this->numEventsLoggedThisPeriod = newCount;
-}
-
-bool IOPMTimeline::isSleepCycleInProgress() {
- return this->sleepCycleInProgress;
-}
-
-void IOPMTimeline::setSleepCycleInProgressFlag(bool flag) {
- this->sleepCycleInProgress = flag;
-}
-//*********************************************************************************
-//*********************************************************************************
-//*********************************************************************************
-
-void IOPMTimeline::setEventsTrackedCount(uint32_t newTracked)
-{
- size_t make_buf_size = 0;
-
- make_buf_size = sizeof(IOPMTraceBufferHeader) + (newTracked * sizeof(IOPMSystemEventRecord));
-
- IOLockLock(logLock);
-
- if (pmTraceMemoryDescriptor) {
- pmTraceMemoryDescriptor->release();
- pmTraceMemoryDescriptor = NULL;
- }
-
- hdr = NULL;
- traceBuffer = NULL;
-
- if (0 == newTracked)
- {
- IOLog("IOPMrootDomain -> erased buffer.\n");
- goto exit;
- }
-
- pmTraceMemoryDescriptor = IOBufferMemoryDescriptor::withOptions(
- kIOMemoryKernelUserShared | kIODirectionIn | kIOMemoryMapperNone,
- make_buf_size);
-
- if (!pmTraceMemoryDescriptor)
- {
- IOLog("IOPMRootDomain -> IOBufferMemoryDescriptor(%d) returns NULL\n", (int)make_buf_size);
- goto exit;
- }
-
- pmTraceMemoryDescriptor->prepare(kIODirectionIn);
-
- // Header occupies the first sizeof(IOPMTraceBufferHeader) bytes
- hdr = (IOPMTraceBufferHeader *)pmTraceMemoryDescriptor->getBytesNoCopy();