bool IOWorkLoop::init() { // The super init and gateLock allocation MUST be done first. if ( !super::init() ) return false; // Allocate our ExpansionData if it hasn't been allocated already. if ( !reserved ) { reserved = IONew(ExpansionData,1); if ( !reserved ) return false; bzero(reserved,sizeof(ExpansionData)); } #if DEBUG OSBacktrace ( reserved->allocationBacktrace, sizeof ( reserved->allocationBacktrace ) / sizeof ( reserved->allocationBacktrace[0] ) ); #endif if ( gateLock == NULL ) { if ( !( gateLock = IORecursiveLockAlloc()) ) return false; } if ( workToDoLock == NULL ) { if ( !(workToDoLock = IOSimpleLockAlloc()) ) return false; IOSimpleLockInit(workToDoLock); workToDo = false; } if (!reserved) { reserved = IONew(ExpansionData, 1); reserved->options = 0; } IOStatisticsRegisterCounter(); if ( controlG == NULL ) { controlG = IOCommandGate::commandGate( this, OSMemberFunctionCast( IOCommandGate::Action, this, &IOWorkLoop::_maintRequest)); if ( !controlG ) return false; // Point the controlGate at the workLoop. Usually addEventSource // does this automatically. The problem is in this case addEventSource // uses the control gate and it has to be bootstrapped. controlG->setWorkLoop(this); if (addEventSource(controlG) != kIOReturnSuccess) return false; } if ( workThread == NULL ) { thread_continue_t cptr = OSMemberFunctionCast( thread_continue_t, this, &IOWorkLoop::threadMain); if (KERN_SUCCESS != kernel_thread_start(cptr, this, &workThread)) return false; } (void) thread_set_tag(workThread, THREAD_TAG_IOWORKLOOP); return true; }
bool ApplePS2Mouse::start(IOService * provider) { DEBUG_LOG("%s::start called\n", getName()); // // The driver has been instructed to start. This is called after a // successful probe and match. // if (!super::start(provider)) return false; // // Maintain a pointer to and retain the provider object. // _device = (ApplePS2MouseDevice *)provider; _device->retain(); // // Setup workloop with command gate for thread syncronization... // IOWorkLoop* pWorkLoop = getWorkLoop(); _cmdGate = IOCommandGate::commandGate(this); if (!pWorkLoop || !_cmdGate) { _device->release(); return false; } pWorkLoop->addEventSource(_cmdGate); // // Setup button timer event source // _buttonTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ApplePS2Mouse::onButtonTimer)); if (_buttonTimer) pWorkLoop->addEventSource(_buttonTimer); // // Lock the controller during initialization // _device->lock(); // // Reset and enable the mouse. // resetMouse(); // // Install our driver's interrupt handler, for asynchronous data delivery. // _device->installInterruptAction(this, OSMemberFunctionCast(PS2InterruptAction, this, &ApplePS2Mouse::interruptOccurred), OSMemberFunctionCast(PS2PacketAction, this, &ApplePS2Mouse::packetReady)); _interruptHandlerInstalled = true; // now safe to allow other threads _device->unlock(); // // Install our power control handler. // _device->installPowerControlAction( this,OSMemberFunctionCast (PS2PowerControlAction,this, &ApplePS2Mouse::setDevicePowerState) ); _powerControlHandlerInstalled = true; // // Install message hook for keyboard to trackpad communication // if (actliketrackpad) { _device->installMessageAction( this, OSMemberFunctionCast(PS2MessageAction, this, &ApplePS2Mouse::receiveMessage)); _messageHandlerInstalled = true; } return true; }
bool darwin_iwi4965::start(IOService *provider) { UInt16 reg; //linking the kext control clone to the driver: clone=this; firstifup=0; do { if ( super::start(provider) == 0) { IOLog("%s ERR: super::start failed\n", getName()); break; } if ( (fPCIDevice = OSDynamicCast(IOPCIDevice, provider)) == 0) { IOLog("%s ERR: fPCIDevice == 0 :(\n", getName()); break; } fPCIDevice->retain(); if (fPCIDevice->open(this) == 0) { IOLog("%s ERR: fPCIDevice->open(this) failed\n", getName()); break; } // Request domain power. // Without this, the PCIDevice may be in state 0, and the // PCI config space may be invalid if the machine has been // sleeping. if (fPCIDevice->requestPowerDomainState(kIOPMPowerOn, (IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState ) != IOPMNoErr) { IOLog("%s Power thingi failed\n", getName()); break; } UInt16 reg16; reg16 = fPCIDevice->configRead16(kIOPCIConfigCommand); reg16 |= (kIOPCICommandBusMaster | kIOPCICommandMemorySpace | kIOPCICommandMemWrInvalidate); reg16 &= ~kIOPCICommandIOSpace; // disable I/O space fPCIDevice->configWrite16(kIOPCIConfigCommand,reg16); irqNumber = fPCIDevice->configRead8(kIOPCIConfigInterruptLine); vendorID = fPCIDevice->configRead16(kIOPCIConfigVendorID); deviceID = fPCIDevice->configRead16(kIOPCIConfigDeviceID); pciReg = fPCIDevice->configRead16(kIOPCIConfigRevisionID); map = fPCIDevice->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0, kIOMapInhibitCache); if (map == 0) { IOLog("%s map is zero\n", getName()); break; } ioBase = map->getPhysicalAddress(); memBase = (UInt16 *)map->getVirtualAddress(); memDes = map->getMemoryDescriptor(); mem = fPCIDevice->getDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0); memDes->initWithPhysicalAddress(ioBase, map->getLength(), kIODirectionOutIn); /* We disable the RETRY_TIMEOUT register (0x41) to keep * PCI Tx retries from interfering with C3 CPU state */ reg = fPCIDevice->configRead16(0x40); if((reg & 0x0000ff00) != 0) fPCIDevice->configWrite16(0x40, reg & 0xffff00ff); IOLog("%s iomemory length: 0x%x @ 0x%x\n", getName(), map->getLength(), ioBase); IOLog("%s virt: 0x%x physical: 0x%x\n", getName(), memBase, ioBase); IOLog("%s IRQ: %d, Vendor ID: %04x, Product ID: %04x\n", getName(), irqNumber, vendorID, deviceID); fWorkLoop = (IOWorkLoop *) getWorkLoop(); if (!fWorkLoop) { IOLog("%s ERR: start - getWorkLoop failed\n", getName()); break; } fInterruptSrc = IOInterruptEventSource::interruptEventSource( this, (IOInterruptEventAction) &darwin_iwi4965::interruptOccurred, provider); if(!fInterruptSrc || (fWorkLoop->addEventSource(fInterruptSrc) != kIOReturnSuccess)) { IOLog("%s fInterruptSrc error\n", getName()); break;; } // This is important. If the interrupt line is shared with other devices, // then the interrupt vector will be enabled only if all corresponding // interrupt event sources are enabled. To avoid masking interrupts for // other devices that are sharing the interrupt line, the event source // is enabled immediately. fInterruptSrc->enable(); //mutex=IOLockAlloc(); fTransmitQueue = createOutputQueue(); if (fTransmitQueue == NULL) { IWI_ERR("ERR: getOutputQueue()\n"); break; } fTransmitQueue->setCapacity(1024); //priv=NULL; iwl_pci_probe(); if (!priv) break; iwl_hw_nic_init(priv); iwl_hw_nic_reset(priv); if (attachInterface((IONetworkInterface **) &fNetif, false) == false) { IOLog("%s attach failed\n", getName()); break; } setProperty(kIOMinPacketSize,12); setProperty(kIOMaxPacketSize, IWL_RX_BUF_SIZE); //setProperty(kIOFeatures, kIONetworkFeatureNoBSDWait|kIONetworkFeatureSoftwareVlan); fNetif->registerOutputHandler(this,getOutputHandler()); fNetif->registerService(); registerService(); mediumDict = OSDictionary::withCapacity(MEDIUM_TYPE_INVALID + 1); addMediumType(kIOMediumIEEE80211None, 0, MEDIUM_TYPE_NONE); addMediumType(kIOMediumIEEE80211Auto, 0, MEDIUM_TYPE_AUTO); publishMediumDictionary(mediumDict); setCurrentMedium(mediumTable[MEDIUM_TYPE_AUTO]); setSelectedMedium(mediumTable[MEDIUM_TYPE_AUTO]); setLinkStatus(kIONetworkLinkValid, mediumTable[MEDIUM_TYPE_AUTO]); //kext control registration: //these functions registers the control which enables //the user to interact with the driver struct kern_ctl_reg ep_ctl; // Initialize control kern_ctl_ref kctlref; bzero(&ep_ctl, sizeof(ep_ctl)); ep_ctl.ctl_id = 0; /* OLD STYLE: ep_ctl.ctl_id = kEPCommID; */ ep_ctl.ctl_unit = 0; strcpy(ep_ctl.ctl_name,"insanelymac.iwidarwin.control"); ep_ctl.ctl_flags = 0; ep_ctl.ctl_connect = ConnectClient; ep_ctl.ctl_disconnect = disconnectClient; ep_ctl.ctl_send = setSelectedNetwork; ep_ctl.ctl_setopt = configureConnection; ep_ctl.ctl_getopt = sendNetworkList; errno_t error = ctl_register(&ep_ctl, &kctlref); queue_te(12,OSMemberFunctionCast(thread_call_func_t,this,&darwin_iwi4965::check_firstup),NULL,NULL,false); queue_te(12,OSMemberFunctionCast(thread_call_func_t,this,&darwin_iwi4965::check_firstup),priv,1000,true); return true; // end start successfully } while (false); //stop(provider); //free(); return false; // end start insuccessfully }
bool ACPIProbe::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } profiles = OSDictionary::withCapacity(0); profileList = OSArray::withCapacity(0); OSObject *object = NULL; // Try to load configuration provided by ACPI device if (kIOReturnSuccess == acpiDevice->evaluateObject("LIST", &object) && object) { if (OSArray *list = OSDynamicCast(OSArray, object)) { for (unsigned int i = 0; i < list->getCount(); i++) { if (OSString *method = OSDynamicCast(OSString, list->getObject(i))) { if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) { if (OSArray *config = OSDynamicCast(OSArray, object)) { if (config->getCount() > 4) { OSString *pName = OSDynamicCast(OSString, config->getObject(0)); OSNumber *pInterval = OSDynamicCast(OSNumber, config->getObject(1)); OSNumber *pTimeout = OSDynamicCast(OSNumber, config->getObject(2)); OSNumber *pVerbose = OSDynamicCast(OSNumber, config->getObject(3)); OSArray *pMethods = OSArray::withCapacity(config->getCount() - 4); for (unsigned int offset = 4; offset < config->getCount(); offset++) { if (OSString *methodName = OSDynamicCast(OSString, config->getObject(offset))) { pMethods->setObject(methodName); } } addProfile(pName, pMethods, pInterval, pTimeout, pVerbose); } } OSSafeRelease(object); } } } OSSafeRelease(list); } } else { ACPISensorsErrorLog("profile definition table (LIST) not found"); } // Try to load configuration from info.plist if (profiles->getCount() == 0) { if (OSDictionary *configuration = getConfigurationNode()) { OSString *pName = OSDynamicCast(OSString, configuration->getObject("ProfileName")); OSNumber *pInterval = OSDynamicCast(OSNumber, configuration->getObject("PollingInterval")); OSNumber *pTimeout = OSDynamicCast(OSNumber, configuration->getObject("PollingTimeout")); OSBoolean *pVerboseBool = OSDynamicCast(OSBoolean, configuration->getObject("VerboseLog")); OSNumber *pVerbose = OSNumber::withNumber(pVerboseBool->getValue() ? 1 : 0, 8); OSArray *pMethods = OSDynamicCast(OSArray, configuration->getObject("MethodsToPoll")); addProfile(pName, pMethods, pInterval, pTimeout, pVerbose); } } if (this->profiles->getCount()) { // Parse active profile if (kIOReturnSuccess == acpiDevice->evaluateObject("ACTV", &object) && object) { if (OSString *method = OSDynamicCast(OSString, object)) { if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) { if (OSArray *config = OSDynamicCast(OSArray, object)) { if (config->getCount() > 4) { if (OSString *profile = OSDynamicCast(OSString, config->getObject(0))) { if (!(activeProfile = (ACPIProbeProfile *)profiles->getObject(profile))) { activeProfile = (ACPIProbeProfile *)profileList->getObject(0); } } } } OSSafeRelease(object); } OSSafeRelease(method); } } // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ACPIProbe::woorkloopTimerEvent)))) { ACPISensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { ACPISensorsFatalLog("failed to add timer event source into workloop"); return false; } timerEventSource->setTimeoutMS(100); //ACPISensorsInfoLog("%d method%s registered", methods->getCount(), methods->getCount() > 1 ? "s" : ""); } // two power states - off and on static const IOPMPowerState powerStates[2] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // register interest in power state changes PMinit(); provider->joinPMtree(this); registerPowerDriver(this, (IOPMPowerState *)powerStates, 2); registerService(); ACPISensorsInfoLog("started"); return true; }
bool LPCSensors::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &LPCSensors::woorkloopTimerEvent)))) { HWSensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { HWSensorsFatalLog("failed to add timer event source into workloop"); return false; } // two power states - off and on static const IOPMPowerState powerStates[2] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // register interest in power state changes PMinit(); provider->joinPMtree(this); registerPowerDriver(this, (IOPMPowerState *)powerStates, 2); registerService(); HWSensorsInfoLog("started"); return true; }
bool AtherosL1Ethernet::start(IOService *provider) { DbgPrint("start()\n"); at_adapter *adapter=&adapter_; if (!BASE::start(provider)) { ErrPrint("Couldn't start BASE\n"); return false; } adapter->pdev = OSDynamicCast(IOPCIDevice, provider); if (!adapter->pdev) { ErrPrint("Unable to cast provider\n"); return false; } adapter->pdev->retain(); adapter->pdev->open(this); //Adding Mac OS X PHY's mediumDict = OSDictionary::withCapacity(MEDIUM_INDEX_COUNT + 1); OSAddNetworkMedium(kIOMediumEthernetAuto, 0, MEDIUM_INDEX_AUTO); OSAddNetworkMedium(kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, 10 * MBit, MEDIUM_INDEX_10HD); OSAddNetworkMedium(kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, 10 * MBit, MEDIUM_INDEX_10FD); OSAddNetworkMedium(kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, 100 * MBit, MEDIUM_INDEX_100HD); OSAddNetworkMedium(kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, 100 * MBit, MEDIUM_INDEX_100FD); OSAddNetworkMedium(kIOMediumEthernet1000BaseTX | kIOMediumOptionHalfDuplex, 1000 * MBit, MEDIUM_INDEX_1000HD); OSAddNetworkMedium(kIOMediumEthernet1000BaseTX | kIOMediumOptionFullDuplex, 1000 * MBit, MEDIUM_INDEX_1000FD); if (!publishMediumDictionary(mediumDict)) return false; if (!atProbe()) //Fix false reporting int probe function { ErrPrint("Couldn't probe adapter\n"); stop(provider); return false; } workLoop_ = getWorkLoop(); if (!workLoop_) { ErrPrint("workLoop is not exists\n"); stop(provider); return false; } transmitQueue_ = getOutputQueue(); if (!transmitQueue_) { ErrPrint("transmitQueue is not exists\n"); stop(provider); return false; } //Looking for MSI interrupt index int msi_index = -1; int intr_index = 0, intr_type = 0; IOReturn intr_ret; while (true) { intr_ret = provider->getInterruptType(intr_index, &intr_type); if (intr_ret != kIOReturnSuccess) break; if (intr_type & kIOInterruptTypePCIMessaged) msi_index = intr_index; intr_index++; } if (msi_index != -1) { DbgPrint("MSI interrupt index %d\n", msi_index); intSource_ = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &AtherosL1Ethernet::atIntr), adapter->pdev, msi_index); } if (msi_index == -1 || intSource_ == NULL) { DbgPrint("MSI index was not found or MSI interrupt couldn't be enabled\n"); intSource_ = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &AtherosL1Ethernet::atIntr), adapter->pdev); } //Adding interrupt to our workloop event sources if (!intSource_ || workLoop_->addEventSource(intSource_) != kIOReturnSuccess) { if (!intSource_) ErrPrint("Couldn't create interrupt source\n"); else ErrPrint("Couldn't attach interrupt source\n"); stop(provider); return false; } //Attaching dynamic link layer if (!this->attachInterface(reinterpret_cast<IONetworkInterface **>(&netIface_)), false) { DbgPrint("Failed to attach data link layer\n"); return false; } intSource_->enable(); /* allocate Tx / RX descriptor resources */ if (at_setup_ring_resources(adapter)) { ErrPrint("Couldn't allocate ring descriptors\n"); adapter->pdev->close(this); return kIOReturnError; } netIface_->registerService(); adapter->pdev->close(this); return true; }
void net_habitue_device_SC101::doSubmitIO(outstanding_io *io) { bool isWrite = (io->buffer->getDirection() == kIODirectionOut); UInt32 ioLen = (io->nblks * SECTOR_SIZE); mbuf_t m; retryResolve(); if (isWrite) { KDEBUG("%p write %d %d (%d)", io, io->block, io->nblks, _outstandingCount); psan_put_t req; bzero(&req, sizeof(req)); req.ctrl.cmd = PSAN_PUT; req.ctrl.seq = ((net_habitue_driver_SC101 *)getProvider())->getSequenceNumber(); req.ctrl.len_power = POWER_OF_2(ioLen); req.sector = htonl(io->block); if (mbuf_allocpacket(MBUF_WAITOK, sizeof(req) + ioLen, NULL, &m) != 0) KINFO("mbuf_allocpacket failed!"); // TODO(iwade) handle if (mbuf_copyback(m, 0, sizeof(req), &req, MBUF_WAITOK) != 0) KINFO("mbuf_copyback failed!"); // TODO(iwade) handle if (!mbuf_buffer(io->buffer, 0, m, sizeof(req), ioLen)) KINFO("mbuf_buffer failed"); // TODO(iwade) handle io->outstanding.seq = ntohs(req.ctrl.seq); io->outstanding.len = sizeof(psan_put_response_t); io->outstanding.cmd = PSAN_PUT_RESPONSE; } else { KDEBUG("%p read %d %d (%d)", io, io->block, io->nblks, _outstandingCount); psan_get_t req; bzero(&req, sizeof(req)); req.ctrl.cmd = PSAN_GET; req.ctrl.seq = ((net_habitue_driver_SC101 *)getProvider())->getSequenceNumber(); req.ctrl.len_power = POWER_OF_2(ioLen); req.sector = htonl(io->block); if (mbuf_allocpacket(MBUF_WAITOK, sizeof(req), NULL, &m) != 0) KINFO("mbuf_allocpacket failed!"); // TODO(iwade) handle if (mbuf_copyback(m, 0, sizeof(req), &req, MBUF_WAITOK) != 0) KINFO("mbuf_copyback failed!"); // TODO(iwade) handle io->outstanding.seq = ntohs(req.ctrl.seq); io->outstanding.len = sizeof(psan_get_response_t) + ioLen; io->outstanding.cmd = PSAN_GET_RESPONSE; } io->outstanding.packetHandler = OSMemberFunctionCast(PacketHandler, this, &net_habitue_device_SC101::handleAsyncIOPacket); io->outstanding.timeoutHandler = OSMemberFunctionCast(TimeoutHandler, this, &net_habitue_device_SC101::handleAsyncIOTimeout); io->outstanding.target = this; io->outstanding.ctx = io; io->outstanding.timeout_ms = io->timeout_ms; ((net_habitue_driver_SC101 *)getProvider())->sendPacket((sockaddr_in *)io->addr->getBytesNoCopy(), m, &io->outstanding); }
int VoodooI2CHIDDevice::initHIDDevice(I2CDevice *hid_device) { int ret; UInt16 hidRegister; ihid = (i2c_hid*)IOMalloc(sizeof(i2c_hid)); ihid->client = hid_device; ret = i2c_hid_acpi_pdata(ihid); ihid->client = hid_device; hidRegister = ihid->pdata.hid_descriptor_address; ihid->wHIDDescRegister = (__le16)hidRegister; ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE); if (ret < 0) goto err; //ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON); //if(ret<0) // goto err; ret = i2c_hid_fetch_hid_descriptor(ihid); if (ret < 0) goto err; setProperty("HIDDescLength", (UInt32)ihid->hdesc.wHIDDescLength, 32); setProperty("bcdVersion", (UInt32)ihid->hdesc.bcdVersion, 32); setProperty("ReportDescLength", (UInt32)ihid->hdesc.wReportDescLength, 32); setProperty("ReportDescRegister", (UInt32)ihid->hdesc.wReportDescRegister, 32); setProperty("InputRegister", (UInt32)ihid->hdesc.wInputRegister, 32); setProperty("MaxInputLength", (UInt32)ihid->hdesc.wMaxInputLength, 32); setProperty("OutputRegister", (UInt32)ihid->hdesc.wOutputRegister, 32); setProperty("MaxOutputLength", (UInt32)ihid->hdesc.wMaxOutputLength, 32); setProperty("CommandRegister", (UInt32)ihid->hdesc.wCommandRegister, 32); setProperty("DataRegister", (UInt32)ihid->hdesc.wDataRegister, 32); setProperty("vendorID", (UInt32)ihid->hdesc.wVendorID, 32); setProperty("productID", (UInt32)ihid->hdesc.wProductID, 32); setProperty("VersionID", (UInt32)ihid->hdesc.wVersionID, 32); hid_device->workLoop = (IOWorkLoop*)getWorkLoop(); if(!hid_device->workLoop) { IOLog("%s::%s::Failed to get workloop\n", getName(), _controller->_dev->name); stop(this); return -1; } hid_device->workLoop->retain(); /* hid_device->interruptSource = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &VoodooI2CHIDDevice::InterruptOccured), hid_device->provider); if (hid_device->workLoop->addEventSource(hid_device->interruptSource) != kIOReturnSuccess) { IOLog("%s::%s::Could not add interrupt source to workloop\n", getName(), _controller->_dev->name); stop(this); return -1; } hid_device->interruptSource->enable(); */ hid_device->timerSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &VoodooI2CHIDDevice::i2c_hid_get_input)); if (!hid_device->timerSource){ goto err; } hid_device->workLoop->addEventSource(hid_device->timerSource); hid_device->timerSource->setTimeoutMS(10); /* hid_device->commandGate = IOCommandGate::commandGate(this); if (!hid_device->commandGate || (_dev->workLoop->addEventSource(hid_device->commandGate) != kIOReturnSuccess)) { IOLog("%s::%s::Failed to open HID command gate\n", getName(), _dev->name); return -1; } */ i2c_hid_get_report_descriptor(ihid); initialize_wrapper(); registerService(); return 0; err: i2c_hid_free_buffers(ihid, HID_MIN_BUFFER_SIZE); IOFree(ihid, sizeof(i2c_hid)); return ret; }
* * Called by AppleSmartBatteryManagerUserClient */ IOReturn AppleSmartBatteryManager::performExternalTransactionGated( void *arg0, void *arg1, void *arg2 __unused, void *arg3 __unused) { IOSMBusTransaction *trans = (IOSMBusTransaction *)arg0; IOReturn *return_code = (IOReturn *)arg1; *return_code = fProvider->performTransaction( trans, /* transaction */ OSMemberFunctionCast( IOSMBusTransactionCompletion, /* completion */ this, &AppleSmartBatteryManager::transactionCompletion), (OSObject *)this, /* target */ (void *)trans); /* ref */ if(kIOReturnSuccess != *return_code) return kIOReturnSuccess; /* Sleep the caller's thread until the transaction completion returns */ fManagerGate->commandSleep(trans, THREAD_UNINT); /* at this point our transaction is complete; return */ return kIOReturnSuccess; }
bool ApplePS2Keyboard::start(IOService * provider) { OSBoolean *xml_swap_CAPSLOCK_CTRL; OSBoolean *xml_swap_ALT_WIN; OSBoolean *xml_use_right_modifier_into_HANGUL_HANJA; OSBoolean *xml_make_APP_into_RWIN; OSBoolean *xml_swap_GRAVE_EUROPE2; OSBoolean *xml_make_APP_into_AppleFN; // // The driver has been instructed to start. This is called after a // successful attach. // if (!super::start(provider)) return false; // // Maintain a pointer to and retain the provider object. // _device = (ApplePS2KeyboardDevice *)provider; _device->retain(); // // Configure user preferences from Info.plist // xml_swap_CAPSLOCK_CTRL = OSDynamicCast( OSBoolean, getProperty("Swap capslock and left control")); if (xml_swap_CAPSLOCK_CTRL) { if ( xml_swap_CAPSLOCK_CTRL->getValue()) { char temp = _PS2ToADBMap[0x3a]; _PS2ToADBMap[0x3a] = _PS2ToADBMap[0x1d]; _PS2ToADBMap[0x1d] = temp; } } xml_swap_ALT_WIN = OSDynamicCast( OSBoolean, getProperty("Swap command and option")); if (xml_swap_ALT_WIN) { if ( xml_swap_ALT_WIN->getValue()) { char temp = _PS2ToADBMap[0x38]; _PS2ToADBMap[0x38] = _PS2ToADBMap[0x15b]; _PS2ToADBMap[0x15b] = temp; temp = _PS2ToADBMap[0x138]; _PS2ToADBMap[0x138] = _PS2ToADBMap[0x15c]; _PS2ToADBMap[0x15c] = temp; } } xml_use_right_modifier_into_HANGUL_HANJA = OSDynamicCast( \ OSBoolean, getProperty("Make right modifier keys into Hangul and Hanja")); if (xml_use_right_modifier_into_HANGUL_HANJA) { if ( xml_use_right_modifier_into_HANGUL_HANJA->getValue()) { _PS2ToADBMap[0x138] = _PS2ToADBMap[0xf2]; // Right alt becomes Hangul _PS2ToADBMap[0x11d] = _PS2ToADBMap[0xf1]; // Right control becomes Hanja } } xml_make_APP_into_RWIN = OSDynamicCast( OSBoolean, getProperty("Make Application key into right windows")); if (xml_make_APP_into_RWIN) { if ( xml_make_APP_into_RWIN->getValue()) _PS2ToADBMap[0x15d] = _PS2ToADBMap[0x15c]; } // not implemented yet. // Apple Fn key works well, but no combined key action was made. xml_make_APP_into_AppleFN = OSDynamicCast( OSBoolean, getProperty("Make Application key into Apple Fn key")); if (xml_make_APP_into_AppleFN) { if ( xml_make_APP_into_AppleFN->getValue()) { _PS2ToADBMap[0x15d] = 0x3f; } } // ISO specific mapping to match ADB keyboards // This should really be done in the keymaps. xml_swap_GRAVE_EUROPE2 = OSDynamicCast( OSBoolean, getProperty("Use ISO layout keyboard")); if (xml_swap_GRAVE_EUROPE2) { if ( xml_swap_GRAVE_EUROPE2->getValue()) { char temp = _PS2ToADBMap[0x29]; //Grave '~' _PS2ToADBMap[0x29] = _PS2ToADBMap[0x56]; //Europe2 '¤º' _PS2ToADBMap[0x56] = temp; } } // now load PS2 -> PS2 configuration data OSArray* pArray = OSDynamicCast(OSArray, getProperty("Custom PS2 Map")); if (NULL != pArray) { for (int i = 0; i < pArray->getCount(); i++) { OSString* pString = OSDynamicCast(OSString, pArray->getObject(i)); if (NULL == pString) continue; const char* psz = pString->getCStringNoCopy(); // check for comment if (';' == *psz) continue; // otherwise, try to parse it UInt16 scanIn, scanOut; if (!parseRemap(psz, scanIn, scanOut)) { IOLog("VoodooPS2Keyboard: invalid custom PS2 map entry: \"%s\"\n", psz); continue; } // must be normal scan code or extended, nothing else UInt8 exIn = scanIn >> 8; UInt8 exOut = scanOut >> 8; if ((exIn != 0 && exIn != 0xe0) || (exOut != 0 && exOut != 0xe0)) { IOLog("VoodooPS2Keyboard: scan code invalid for PS2 map entry: \"%s\"\n", psz); continue; } // modify PS2 to PS2 map per remap entry int index = (scanIn & 0xff) + (exIn == 0xe0 ? KBV_NUM_SCANCODES : 0); assert(index < countof(_PS2ToPS2Map)); _PS2ToPS2Map[index] = (scanOut & 0xff) + (exOut == 0xe0 ? KBV_NUM_SCANCODES : 0); } } // now load PS2 -> ADB configuration data pArray = OSDynamicCast(OSArray, getProperty("Custom ADB Map")); if (NULL != pArray) { for (int i = 0; i < pArray->getCount(); i++) { OSString* pString = OSDynamicCast(OSString, pArray->getObject(i)); if (NULL == pString) continue; const char* psz = pString->getCStringNoCopy(); // check for comment if (';' == *psz) continue; // otherwise, try to parse it UInt16 scanIn, adbOut; if (!parseRemap(psz, scanIn, adbOut)) { IOLog("VoodooPS2Keyboard: invalid custom ADB map entry: \"%s\"\n", psz); continue; } // must be normal scan code or extended, nothing else, adbOut is only a byte UInt8 exIn = scanIn >> 8; if ((exIn != 0 && exIn != 0xe0) || adbOut > 0xFF) { IOLog("VoodooPS2Keyboard: scan code invalid for ADB map entry: \"%s\"\n", psz); continue; } // modify PS2 to ADB map per remap entry int index = (scanIn & 0xff) + (exIn == 0xe0 ? ADB_CONVERTER_EX_START : 0); assert(index < countof(_PS2ToADBMap)); _PS2ToADBMap[index] = adbOut; } } // get time before sleep button takes effect OSNumber* num; if ((num = OSDynamicCast(OSNumber, getProperty("SleepPressTime")))) maxsleeppresstime = (uint64_t)num->unsigned32BitValue() * (uint64_t)1000000; // // Reset and enable the keyboard. // initKeyboard(); // // Install our driver's interrupt handler, for asynchronous data delivery. // _device->installInterruptAction(this, OSMemberFunctionCast(PS2InterruptAction,this,&ApplePS2Keyboard::interruptOccurred)); _interruptHandlerInstalled = true; // // Install our power control handler. // _device->installPowerControlAction( this, OSMemberFunctionCast(PS2PowerControlAction,this, &ApplePS2Keyboard::setDevicePowerState )); _powerControlHandlerInstalled = true; return true; }
// Class start bool VoodooPState::start(IOService * provider) { if (!IOService::start(provider)) return false; // Printout banner InfoLog("%s %s (%s) %s %s [%s]", KextProductName, KextVersion, KextConfig, KextBuildDate, KextBuildTime, KextOSX); InfoLog("based on VoodooPower 1.2.3."); // Setup workloop and timer IOWorkLoop* WorkLoop = getWorkLoop(); if (!WorkLoop) return false; TimerEventSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &VoodooPState::LoopTimerEvent)); if (!TimerEventSource) return false; if (kIOReturnSuccess != WorkLoop->addEventSource(TimerEventSource)) { return false; } // Get a SimpleLock SimpleLock = IOSimpleLockAlloc(); if (!SimpleLock) return false; // Publish the static characteristics OSDictionary * dictionary = OSDictionary::withCapacity(13); if (!dictionary) return false; OSArray * array = OSArray::withCapacity(PStateCount); if (!array) return false; setDictionaryNumber(keyCpuCoreTech, CpuCoreTech, dictionary); setDictionaryNumber(keyFrontSideBus, CpuFSB, dictionary); for (int i = 0; i < PStateCount; i++) { OSDictionary * pdictionary = OSDictionary::withCapacity(3); if (!pdictionary) return false; setDictionaryNumber(keyCurrentFrequency, PState[i].frequency, pdictionary); setDictionaryNumber(keyCurrentVoltage, PState[i].voltage, pdictionary); setDictionaryNumber(keyFid, PState[i].fid, pdictionary); setDictionaryNumber(keyDid, PState[i].did, pdictionary); setDictionaryNumber(keyVid, PState[i].vid, pdictionary); array->setObject(i, pdictionary); pdictionary->release(); } setDictionaryArray(keyPStates, array, dictionary); setDictionaryString(keyProductName, KextProductName, dictionary); setDictionaryString(keyProductVersion, KextVersion, dictionary); setDictionaryString(keyBuildConfig, KextConfig, dictionary); setDictionaryString(keyBuildDate, KextBuildDate, dictionary); setDictionaryString(keyBuildTime, KextBuildTime, dictionary); setDictionaryNumber(keyTimerInterval, TimerInterval, dictionary); setProperty(keyCharacteristics, dictionary); array->release(); dictionary->release(); // set initial pstate Request = ColdStart ? (PStateCount-1) : 0; // hot/cold start gPEClockFrequencyInfo.cpu_frequency_max_hz = VoodooFrequencyProc(this,&PState[0]) * Mega; gPEClockFrequencyInfo.cpu_frequency_min_hz = VoodooFrequencyProc(this,&PState[PStateCount-1]) * Mega; LoopTimerEvent(); // Finalize and kick off the loop this->registerService(0); Ready = true; return true; }
bool IOHIDLibUserClient::start(IOService *provider) { OSDictionary *matching = NULL; if (!super::start(provider)) return false; fNub = OSDynamicCast(IOHIDDevice, provider); if (!fNub) return false; fWL = getWorkLoop(); if (!fWL) return false; fWL->retain(); OSNumber *primaryUsage = (OSNumber*)fNub->copyProperty(kIOHIDPrimaryUsageKey); OSNumber *primaryUsagePage = (OSNumber*)fNub->copyProperty(kIOHIDPrimaryUsagePageKey); if ((OSDynamicCast(OSNumber, primaryUsagePage) && (primaryUsagePage->unsigned32BitValue() == kHIDPage_GenericDesktop)) && (OSDynamicCast(OSNumber, primaryUsage) && ((primaryUsage->unsigned32BitValue() == kHIDUsage_GD_Keyboard) || (primaryUsage->unsigned32BitValue() == kHIDUsage_GD_Keypad)))) { fNubIsKeyboard = true; } OSSafeReleaseNULL(primaryUsage); OSSafeReleaseNULL(primaryUsagePage); IOCommandGate * cmdGate = IOCommandGate::commandGate(this); if (!cmdGate) goto ABORT_START; fWL->addEventSource(cmdGate); fGate = cmdGate; fResourceES = IOInterruptEventSource::interruptEventSource (this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &IOHIDLibUserClient::resourceNotificationGated)); if ( !fResourceES ) goto ABORT_START; fWL->addEventSource(fResourceES); // Get notified everytime Root properties change matching = serviceMatching("IOResources"); fResourceNotification = addMatchingNotification( gIOPublishNotification, matching, OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &IOHIDLibUserClient::resourceNotification), this); matching->release(); matching = NULL; if ( !fResourceNotification ) goto ABORT_START; return true; ABORT_START: if (fResourceES) { fWL->removeEventSource(fResourceES); fResourceES->release(); fResourceES = 0; } if (fGate) { fWL->removeEventSource(fGate); fGate->release(); fGate = 0; } fWL->release(); fWL = 0; return false; }
bool AppleACPIBatteryDevice::start(IOService *provider) { OSNumber *debugPollingSetting; fProvider = OSDynamicCast(AppleACPIBatteryManager, provider); if (!fProvider || !super::start(provider)) { return false; } debugPollingSetting = (OSNumber *)fProvider->getProperty(kBatteryPollingDebugKey); if( debugPollingSetting && OSDynamicCast(OSNumber, debugPollingSetting) ) { /* We set our polling interval to the "BatteryPollingPeriodOverride" property's value, in seconds. Polling Period of 0 causes us to poll endlessly in a loop for testing. */ fPollingInterval = debugPollingSetting->unsigned32BitValue(); fPollingOverridden = true; } else { fPollingInterval = kDefaultPollInterval; fPollingOverridden = false; } fBatteryPresent = false; fACConnected = false; fACChargeCapable = false; fWorkLoop = getWorkLoop(); fPollTimer = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast( IOTimerEventSource::Action, this, &AppleACPIBatteryDevice::pollingTimeOut) ); fBatteryReadAllTimer = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast( IOTimerEventSource::Action, this, &AppleACPIBatteryDevice::incompleteReadTimeOut) ); if( !fWorkLoop || !fPollTimer || (kIOReturnSuccess != fWorkLoop->addEventSource(fPollTimer)) ) { return false; } // Publish the intended period in seconds that our "time remaining" // estimate is wildly inaccurate after wake from sleep. setProperty( kIOPMPSInvalidWakeSecondsKey, kSecondsUntilValidOnWake, NUM_BITS); // Publish the necessary time period (in seconds) that a battery // calibrating tool must wait to allow the battery to settle after // charge and after discharge. setProperty( kIOPMPSPostChargeWaitSecondsKey, kPostChargeWaitSeconds, NUM_BITS); setProperty( kIOPMPSPostDishargeWaitSecondsKey, kPostDischargeWaitSeconds, NUM_BITS); #if TEST i=0; #endif // zero out battery state with argument (do_set == true) clearBatteryState(false); //if system not startup, battery capacity status can't update. waitingForSystemStartup(); return true; }
/****************************************************************************** * CodecCommander::start - start kernel extension and init PM ******************************************************************************/ bool CodecCommander::start(IOService *provider) { IOLog("CodecCommander: Version 2.2.1 starting.\n"); if (!provider || !super::start(provider)) { DEBUG_LOG("CodecCommander: Error loading kernel extension.\n"); return false; } // Retrieve HDEF device from IORegistry IORegistryEntry *hdaDeviceEntry = IORegistryEntry::fromPath(mConfiguration->getHDADevicePath()); if (hdaDeviceEntry != NULL) { mIntelHDA = new IntelHDA(hdaDeviceEntry, PIO, mConfiguration->getCodecNumber()); OSSafeRelease(hdaDeviceEntry); } else { DEBUG_LOG("CodecCommander: Device \"%s\" is unreachable, start aborted.\n", mConfiguration->getHDADevicePath()); return false; } if (mConfiguration->getUpdateNodes()) { IOSleep(mConfiguration->getSendDelay()); // need to wait a bit until codec can actually respond to immediate verbs int k = 0; // array index // Fetch Pin Capabilities from the range of nodes DEBUG_LOG("CodecCommander: Getting EAPD supported node list (limited to %d)\n", MAX_EAPD_NODES); for (int nodeId = mIntelHDA->getStartingNode(); nodeId <= mIntelHDA->getTotalNodes(); nodeId++) { UInt32 response = mIntelHDA->sendCommand(nodeId, HDA_VERB_GET_PARAM, HDA_PARM_PINCAP); if (response == -1) { DEBUG_LOG("CodecCommander: Failed to retrieve pin capabilities for node 0x%02x.\n", nodeId); continue; } // if bit 16 is set in pincap - node supports EAPD if (HDA_PINCAP_IS_EAPD_CAPABLE(response)) { eapdCapableNodes[k] = nodeId; k++; IOLog("CodecCommander: NID=0x%02x supports EAPD, will update state after sleep\n", nodeId); } } /* IOLog("CodecCommander:: Set 0x0A result: 0x%08x\n", mIntelHDA->sendCommand(0x0A, HDA_VERB_SET_AMP_GAIN, HDA_PARM_AMP_GAIN_SET(0x80, 0, 1, 1, 1, 0, 1))); IOLog("CodecCommander:: Set 0x0B result: 0x%08x\n", mIntelHDA->sendCommand(0x0B, HDA_VERB_SET_AMP_GAIN, HDA_PARM_AMP_GAIN_SET(0x80, 0, 1, 1, 1, 0, 1))); IOLog("CodecCommander:: Set 0x0C result: 0x%08x\n", mIntelHDA->sendCommand(0x0C, HDA_VERB_SET_AMP_GAIN, HDA_PARM_AMP_GAIN_SET(0x80, 0, 1, 1, 1, 0, 1))); for (int nodeId = mIntelHDA->getStartingNode(); nodeId <= mIntelHDA->getTotalNodes(); nodeId++) { UInt16 payload = HDA_PARM_AMP_GAIN_GET(0, 1, 1);//AC_AMP_GET_OUTPUT | AC_AMP_GET_LEFT; UInt32 response = mIntelHDA->sendCommand(nodeId, HDA_VERB_GET_AMP_GAIN, payload); if (response == -1) { DEBUG_LOG("Failed to retrieve amp gain settings for node 0x%02x.\n", nodeId); continue; } IOLog("CodecCommander:: [Amp Gain] Node: 0x%04x, Response: 0x%08x\n", nodeId, response); } */ } // Execute any custom commands registered for initialization handleStateChange(kStateInit); // notify about extra feature requests if (mConfiguration->getCheckInfinite()) DEBUG_LOG("CodecCommander: Infinite workloop requested, will start now!\n"); // init power state management & set state as PowerOn PMinit(); registerPowerDriver(this, powerStateArray, kPowerStateCount); provider->joinPMtree(this); // setup workloop and timer mWorkLoop = IOWorkLoop::workLoop(); mTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &CodecCommander::onTimerAction)); if (!mWorkLoop || !mTimer) stop(provider);; if (mWorkLoop->addEventSource(mTimer) != kIOReturnSuccess) stop(provider); this->registerService(0); return true; }
IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void) { return OSMemberFunctionCast(IOInterruptAction, this, &IOSharedInterruptController::handleInterrupt); }
/* * performExternalWordTransaction * * Called by AppleSmartBatteryManagerUserClient */ IOReturn AppleSmartBatteryManager::performExternalTransaction( void *in, void *out, IOByteCount inSize, IOByteCount *outSize) { uint16_t i; uint16_t retryAttempts = 0; IOSMBusTransaction newTransaction; IOReturn transactionSuccess; EXSMBUSInputStruct *inSMBus = (EXSMBUSInputStruct *)in; EXSMBUSOutputStruct *outSMBus = (EXSMBUSOutputStruct *)out; if (!inSMBus || !outSMBus) return kIOReturnBadArgument; /* Attempt up to 5 transactions if we get failures */ do { bzero(&newTransaction, sizeof(IOSMBusTransaction)); // Input: bus address if (kSMBusAppleDoublerAddr == inSMBus->batterySelector || kSMBusBatteryAddr == inSMBus->batterySelector || kSMBusManagerAddr == inSMBus->batterySelector || kSMBusChargerAddr == inSMBus->batterySelector) { newTransaction.address = inSMBus->batterySelector; } else { if (0 == inSMBus->batterySelector) { newTransaction.address = kSMBusBatteryAddr; } else { newTransaction.address = kSMBusManagerAddr; } } // Input: command newTransaction.command = inSMBus->address; // Input: Read/Write Word/Block switch (inSMBus->type) { case kEXWriteWord: newTransaction.protocol = kIOSMBusProtocolWriteWord; newTransaction.sendDataCount = 2; break; case kEXReadWord: newTransaction.protocol = kIOSMBusProtocolReadWord; newTransaction.sendDataCount = 0; break; case kEXWriteBlock: newTransaction.protocol = kIOSMBusProtocolWriteBlock; // rdar://5433060 workaround for SMC SMBus blockCount bug // For block writes, clients always increment inByteCount +1 // greater than the actual byte count. // We decrement it here for IOSMBusController. newTransaction.sendDataCount = inSMBus->inByteCount - 1; break; case kEXReadBlock: newTransaction.protocol = kIOSMBusProtocolReadBlock; newTransaction.sendDataCount = 0; break; case kEXWriteByte: newTransaction.protocol = kIOSMBusProtocolWriteByte; newTransaction.sendDataCount = 1; break; case kEXReadByte: newTransaction.protocol = kIOSMBusProtocolReadByte; newTransaction.sendDataCount = 0; break; case kEXSendByte: newTransaction.protocol = kIOSMBusProtocolSendByte; newTransaction.sendDataCount = 0; break; default: return kIOReturnBadArgument; } // Input: copy data into transaction // only need to copy data for write operations if ((kIOSMBusProtocolWriteWord == newTransaction.protocol) || (kIOSMBusProtocolWriteBlock == newTransaction.protocol)) { for(i = 0; i<MAX_SMBUS_DATA_SIZE; i++) { newTransaction.sendData[i] = inSMBus->inBuf[i]; } } if (inSMBus->flags & kEXFlagRetry) { if (retryAttempts >= kMaxRetries) { // Don't read off the end of the table... retryAttempts = kMaxRetries - 1; } // If this is a retry-on-failure, spin for a few microseconds IODelay( retryDelaysTable[retryAttempts] ); } fManagerGate->runAction( (IOCommandGate::Action)OSMemberFunctionCast( IOCommandGate::Action, this, &AppleSmartBatteryManager::performExternalTransactionGated), (void *)&newTransaction, (void *)&transactionSuccess, NULL, NULL); /* Output: status */ if ((kIOReturnSuccess == transactionSuccess) && (kIOSMBusStatusOK == newTransaction.status)) { outSMBus->status = kIOReturnSuccess; } else { switch (newTransaction.status) { case kIOSMBusStatusUnknownFailure: case kIOSMBusStatusDeviceAddressNotAcknowledged: case kIOSMBusStatusDeviceError: case kIOSMBusStatusDeviceCommandAccessDenied: case kIOSMBusStatusUnknownHostError: outSMBus->status = kIOReturnNoDevice; break; case kIOSMBusStatusTimeout: case kIOSMBusStatusBusy: outSMBus->status = kIOReturnTimeout; break; case kIOSMBusStatusHostUnsupportedProtocol: outSMBus->status = kIOReturnUnsupported; break; default: outSMBus->status = kIOReturnInternalError; break; } } /* Retry this transaction if we received a failure */ } while ((inSMBus->flags & kEXFlagRetry) && (outSMBus->status != kIOReturnSuccess) && (++retryAttempts < kMaxRetries)); /* Output: read word/read block results */ if (((kIOSMBusProtocolReadWord == newTransaction.protocol) || (kIOSMBusProtocolReadBlock == newTransaction.protocol) || (kIOSMBusProtocolReadByte == newTransaction.protocol)) && (kIOSMBusStatusOK == newTransaction.status)) { outSMBus->outByteCount = newTransaction.receiveDataCount; for(i = 0; i<outSMBus->outByteCount; i++) { outSMBus->outBuf[i] = newTransaction.receiveData[i]; } } return kIOReturnSuccess; }
/****************************************************************************** * CodecCommander::start - start kernel extension and init PM ******************************************************************************/ bool CodecCommander::start(IOService *provider) { DEBUG_LOG("CodecCommander: cc: commander version 2.1.1 starting\n"); if(!provider || !super::start( provider )) { DEBUG_LOG("CodecCommander: cc: error loading kext\n"); return false; } // notify about extra feature requests if (generatePop && checkInfinite) { DEBUG_LOG("CodecCommander: cc: stream requested, will *pop* upon wake or fugue-wake\n"); } if (checkInfinite) { DEBUG_LOG("CodecCommander: cc: infinite workloop requested, will start now!\n"); } if (generatePop && !checkInfinite) { DEBUG_LOG("CodecCommander: cc: stream requested, will *pop* upon wake\n"); } // start virtual keyboard device _keyboardDevice = new CCHIDKeyboardDevice; if ( !_keyboardDevice || !_keyboardDevice->init() || !_keyboardDevice->attach(this) ) { _keyboardDevice->release(); DEBUG_LOG("CodecCommander: hi: unable to create keyboard device\n"); } else { DEBUG_LOG("CodecCommander: hi: keyboard device created\n"); _keyboardDevice->registerService(); } // determine HDEF ACPI device path in IORegistry IORegistryEntry *hdaDeviceEntry = IORegistryEntry::fromPath(hdaDevicePath); if (hdaDeviceEntry != NULL) { IOService *service = OSDynamicCast(IOService, hdaDeviceEntry); // get address field from IODeviceMemory if (service != NULL && service->getDeviceMemoryCount() != 0) { ioregEntry = service->getDeviceMemoryWithIndex(0); } hdaDeviceEntry->release(); } else { DEBUG_LOG("CodecCommander: %s is unreachable\n",hdaDevicePath); return false; } // init power state management & set state as PowerOn PMinit(); registerPowerDriver(this, powerStateArray, kPowerStateCount); provider->joinPMtree(this); // setup workloop and timer fWorkLoop = IOWorkLoop::workLoop(); fTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &CodecCommander::onTimerAction)); if (!fWorkLoop || !fTimer) stop(provider);; if (fWorkLoop->addEventSource(fTimer) != kIOReturnSuccess) stop(provider); this->registerService(0); return true; }
bool MacRISC2CPU::start(IOService *provider) { kern_return_t result; IORegistryEntry *cpusRegEntry, *uniNRegEntry, *mpicRegEntry, *devicetreeRegEntry; OSIterator *cpusIterator; OSData *tmpData; IOService *service; const OSSymbol *interruptControllerName; OSData *interruptData; OSArray *tmpArray; UInt32 maxCPUs, uniNVersion, physCPU; ml_processor_info_t processor_info; #if enableUserClientInterface DFScontMode = 0; fWorkLoop = 0; DFS_Status = false; GPU_Status = kGPUHigh; vStepped = false; #endif // callPlatformFunction symbols mpic_getProvider = OSSymbol::withCString("mpic_getProvider"); mpic_getIPIVector= OSSymbol::withCString("mpic_getIPIVector"); mpic_setCurrentTaskPriority = OSSymbol::withCString("mpic_setCurrentTaskPriority"); mpic_setUpForSleep = OSSymbol::withCString("mpic_setUpForSleep"); mpic_dispatchIPI = OSSymbol::withCString("mpic_dispatchIPI"); keyLargo_restoreRegisterState = OSSymbol::withCString("keyLargo_restoreRegisterState"); keyLargo_syncTimeBase = OSSymbol::withCString("keyLargo_syncTimeBase"); keyLargo_saveRegisterState = OSSymbol::withCString("keyLargo_saveRegisterState"); keyLargo_turnOffIO = OSSymbol::withCString("keyLargo_turnOffIO"); keyLargo_writeRegUInt8 = OSSymbol::withCString("keyLargo_writeRegUInt8"); keyLargo_getHostKeyLargo = OSSymbol::withCString("keyLargo_getHostKeyLargo"); keyLargo_setPowerSupply = OSSymbol::withCString("setPowerSupply"); uniN_setPowerState = OSSymbol::withCString(kUniNSetPowerState); uniN_setAACKDelay = OSSymbol::withCString(kUniNSetAACKDelay); pmu_cpuReset = OSSymbol::withCString("cpuReset"); ati_prepareDMATransaction = OSSymbol::withCString(kIOFBPrepareDMAValueKey); ati_performDMATransaction = OSSymbol::withCString(kIOFBPerformDMAValueKey); macRISC2PE = OSDynamicCast(MacRISC2PE, getPlatform()); if (macRISC2PE == 0) return false; if (!super::start(provider)) return false; // Get the Uni-N Version. uniNRegEntry = fromPath("/uni-n", gIODTPlane); if (uniNRegEntry == 0) return false; tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("device-rev")); if (tmpData == 0) return false; uniNVersion = *(long *)tmpData->getBytesNoCopy(); // Find out if this is the boot CPU. bootCPU = false; tmpData = OSDynamicCast(OSData, provider->getProperty("state")); if (tmpData == 0) return false; if (!strcmp((char *)tmpData->getBytesNoCopy(), "running")) bootCPU = true; // Count the CPUs. numCPUs = 0; cpusRegEntry = fromPath("/cpus", gIODTPlane); if (cpusRegEntry == 0) return false; cpusIterator = cpusRegEntry->getChildIterator(gIODTPlane); while (cpusIterator->getNextObject()) numCPUs++; cpusIterator->release(); // [3830950] - The bootCPU driver inits globals for all instances (like gCPUIC) so if we're not the // boot CPU driver we wait here for that driver to finish its initialization if ((numCPUs > 1) && !bootCPU) // Wait for bootCPU driver to say it's up and running (void) waitForService (resourceMatching ("BootCPU")); // Limit the number of CPUs to one if uniNVersion is 1.0.7 or less. if (uniNVersion < kUniNVersion107) numCPUs = 1; // Limit the number of CPUs by the cpu=# boot arg. if (PE_parse_boot_arg("cpus", &maxCPUs)) { if (numCPUs > maxCPUs) numCPUs = maxCPUs; } ignoreSpeedChange = false; doSleep = false; topLevelPCIBridgeCount = 0; // Get the "flush-on-lock" property from the first cpu node. flushOnLock = false; cpusRegEntry = fromPath("/cpus/@0", gIODTPlane); if (cpusRegEntry == 0) return false; if (cpusRegEntry->getProperty("flush-on-lock") != 0) flushOnLock = true; // Set flushOnLock when numCPUs is not one. if (numCPUs != 1) flushOnLock = true; // If system is PowerMac3,5 (TowerG4), then set flushOnLock to disable nap devicetreeRegEntry = fromPath("/", gIODTPlane); tmpData = OSDynamicCast(OSData, devicetreeRegEntry->getProperty("model")); if (tmpData == 0) return false; #if 0 if(!strcmp((char *)tmpData->getBytesNoCopy(), "PowerMac3,5")) flushOnLock = true; #endif // Get the physical CPU number from the "reg" property. tmpData = OSDynamicCast(OSData, provider->getProperty("reg")); if (tmpData == 0) return false; physCPU = *(long *)tmpData->getBytesNoCopy(); setCPUNumber(physCPU); // Get the gpio offset for soft reset from the "soft-reset" property. tmpData = OSDynamicCast(OSData, provider->getProperty("soft-reset")); if (tmpData == 0) { if (physCPU == 0) soft_reset_offset = 0x5B; else soft_reset_offset = 0x5C; } else soft_reset_offset = *(long *)tmpData->getBytesNoCopy(); // Get the gpio offset for timebase enable from the "timebase-enable" property. tmpData = OSDynamicCast(OSData, provider->getProperty("timebase-enable")); if (tmpData == 0) timebase_enable_offset = 0x73; else timebase_enable_offset = *(long *)tmpData->getBytesNoCopy(); // See if reset is needed on wake resetOnWake = (provider->getProperty ("reset-on-wake") != NULL); if (resetOnWake) { vm_address_t reserveMem; reserveMem = (vm_address_t)IOMallocAligned (PAGE_SIZE, PAGE_SIZE); // Get one page (which we keep forever) if (reserveMem) { // map it reserveMemDesc = IOMemoryDescriptor::withAddress (reserveMem, PAGE_SIZE, kIODirectionNone, NULL); if (reserveMemDesc) { // get the physical address reserveMemPhys = reserveMemDesc->getPhysicalAddress(); } } } // On machines with a 'vmin' property in the CPU Node we need to make sure to tell the kernel to // ml_set_processor_voltage on needed processors. needVSetting = (provider->getProperty( "vmin" ) != 0); // While techincally the Apollo7PM machines do need AACK delay, it is already set in the bootROM // since we boot slow. We don't want the machine to switch AACKdelay off when we run DFS high so // setting this to false will take care of the issue. needAACKDelay = false; if (bootCPU) { gCPUIC = new IOCPUInterruptController; if (gCPUIC == 0) return false; if (gCPUIC->initCPUInterruptController(numCPUs) != kIOReturnSuccess) return false; gCPUIC->attach(this); gCPUIC->registerCPUInterruptController(); } // Get the l2cr value from the property list. tmpData = OSDynamicCast(OSData, provider->getProperty("l2cr")); if (tmpData != 0) { l2crValue = *(long *)tmpData->getBytesNoCopy() & 0x7FFFFFFF; } else { l2crValue = mfl2cr() & 0x7FFFFFFF; } // Wait for KeyLargo to show up. keyLargo = waitForService(serviceMatching("KeyLargo")); if (keyLargo == 0) return false; keyLargo->callPlatformFunction (keyLargo_getHostKeyLargo, false, &keyLargo, 0, 0, 0); if (keyLargo == 0) { kprintf ("MacRISC2CPU::start - getHostKeyLargo returned nil\n"); return false; } // Wait for MPIC to show up. mpic = waitForService(serviceMatching("AppleMPICInterruptController")); if (mpic == 0) return false; // Set the Interrupt Properties for this cpu. mpic->callPlatformFunction(mpic_getProvider, false, (void *)&mpicRegEntry, 0, 0, 0); interruptControllerName = IODTInterruptControllerName(mpicRegEntry); mpic->callPlatformFunction(mpic_getIPIVector, false, (void *)&physCPU, (void *)&interruptData, 0, 0); if ((interruptControllerName == 0) || (interruptData == 0)) return false; tmpArray = OSArray::withCapacity(1); tmpArray->setObject(interruptControllerName); cpuNub->setProperty(gIOInterruptControllersKey, tmpArray); tmpArray->release(); tmpArray = OSArray::withCapacity(1); tmpArray->setObject(interruptData); cpuNub->setProperty(gIOInterruptSpecifiersKey, tmpArray); tmpArray->release(); setCPUState(kIOCPUStateUninitalized); // necessary bootCPU initialization is done, so release other CPU drivers to do their thing // other drivers need to be unblocked *before* we call processor_start otherwise we deadlock if (bootCPU) publishResource ("BootCPU", this); if (physCPU < numCPUs) { processor_info.cpu_id = (cpu_id_t)this; processor_info.boot_cpu = bootCPU; processor_info.start_paddr = 0x0100; processor_info.l2cr_value = l2crValue; processor_info.supports_nap = !flushOnLock; processor_info.time_base_enable = OSMemberFunctionCast(time_base_enable_t, this, &MacRISC2CPU::enableCPUTimeBase); // [4091924] // Register this CPU with mach. result = ml_processor_register(&processor_info, &machProcessor, &ipi_handler); if (result == KERN_FAILURE) return false; processor_start(machProcessor); } // Before to go to sleep we wish to disable the napping mode so that the PMU // will not shutdown the system while going to sleep: service = waitForService(serviceMatching("IOPMrootDomain")); pmRootDomain = OSDynamicCast(IOPMrootDomain, service); if (pmRootDomain != 0) { kprintf("Register MacRISC2CPU %ld to acknowledge power changes\n", getCPUNumber()); pmRootDomain->registerInterestedDriver(this); // Join the Power Management Tree to receive setAggressiveness calls. PMinit(); provider->joinPMtree(this); } // Finds PMU and UniN so in quiesce we can put the machine to sleep. // I can not put these calls there because quiesce runs in interrupt // context and waitForService may block. pmu = waitForService(serviceMatching("ApplePMU")); uniN = waitForService(serviceMatching("AppleUniN")); if ((pmu == 0) || (uniN == 0)) return false; if (macRISC2PE->hasPMon) { // Find the platform monitor, if present service = waitForService(resourceMatching("IOPlatformMonitor")); ioPMon = OSDynamicCast (IOPlatformMonitor, service->getProperty("IOPlatformMonitor")); if (!ioPMon) return false; ioPMonDict = OSDictionary::withCapacity(2); if (!ioPMonDict) { ioPMon = NULL; } else { ioPMonDict->setObject (kIOPMonTypeKey, OSSymbol::withCString (kIOPMonTypeCPUCon)); ioPMonDict->setObject (kIOPMonCPUIDKey, OSNumber::withNumber ((long long)getCPUNumber(), 32)); if (messageClient (kIOPMonMessageRegister, ioPMon, (void *)ioPMonDict) != kIOReturnSuccess) { // IOPMon doesn't need to know about us, so don't bother with it IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformMonitor\n"); ioPMonDict->release(); ioPMon = NULL; } } } if (macRISC2PE->hasPPlugin) { IOService *ioPPlugin; OSDictionary *ioPPluginDict; // Find the platform plugin, if present service = waitForService(resourceMatching("IOPlatformPlugin")); ioPPlugin = OSDynamicCast (IOService, service->getProperty("IOPlatformPlugin")); if (!ioPPlugin) return false; ioPPluginDict = OSDictionary::withCapacity(2); if (ioPPluginDict) { ioPPluginDict->setObject ("cpu-id", OSNumber::withNumber ((long long)getCPUNumber(), 32)); // Register with the plugin - same API as for platform monitor if (messageClient (kIOPMonMessageRegister, ioPPlugin, (void *)ioPPluginDict) != kIOReturnSuccess) { // ioPPlugin doesn't need to know about us, so don't bother with it IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformPlugin\n"); } ioPPluginDict->release(); // Not needed any more } } #if enableUserClientInterface // // UserClient stuff... // fWorkLoop = getWorkLoop(); if(!fWorkLoop) { IOLog("MacRISC2CPU::start ERROR: failed to find a fWorkLoop\n"); } if(!initTimers()) { IOLog("MacRISC2CPU::start ERROR: failed to init the timers\n"); } #endif registerService(); return true; }
void SoftU2FUserClient::frameReceived(IOMemoryDescriptor *report) { if (isInactive()) return; _commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &SoftU2FUserClient::frameReceivedGated), report); }
void MacRISC2CPU::initCPU(bool boot) { IOPCIBridge *pciDriver; UInt32 i; if (!boot && bootCPU) { // Tell Uni-N to enter normal mode. uniN->callPlatformFunction (uniN_setPowerState, false, (void *)kUniNNormal, (void *)0, (void *)0, (void *)0); if (!processorSpeedChange) { // Notify our pci children to restore their state for (i = 0; i < topLevelPCIBridgeCount; i++) if (pciDriver = topLevelPCIBridges[i]) // Got the driver - send the message pciDriver->setDevicePowerState (NULL, 3); if (resetOnWake && (!gPHibernateState || !*gPHibernateState)) { bool doAGPRecovery; IOReturn result; doAGPRecovery = false; if (macRISC2PE->atiDriver) { // Restore ATI config space macRISC2PE->atiDriver->restoreDeviceState(); if (macRISC2PE->gpuSensor) { // Call ATI through the sensor driver to prep for the DMA transaction result = macRISC2PE->gpuSensor->callPlatformFunction (ati_prepareDMATransaction, false, (void *)reserveMemDesc, 0, 0, 0); if (result == kIOReturnSuccess) { if (macRISC2PE->atiDriver && macRISC2PE->agpBridgeDriver) { // Issue resetAGP to turn on AGP macRISC2PE->atiDriver->resetAGP(); // Turn off GART (turned on by resetAGP) macRISC2PE->agpBridgeDriver->configWrite32(macRISC2PE->agpBridgeDriver->getBridgeSpace(), 0x94, 0); // Call ATI to do the dummy DMA transfer as a test result = macRISC2PE->gpuSensor->callPlatformFunction (ati_performDMATransaction, false, (void *)reserveMemDesc, 0, 0, 0); // Issue resetAGP to turn off AGP (so it's in state later s/w expects) macRISC2PE->atiDriver->resetAGP(); if (result == kIOReturnDMAError) // DMA failed, to the recovery procedure doAGPRecovery = true; } } } } if (doAGPRecovery) { kprintf("MacRISC2CPU::initCPU - AGP recovery required, issuing cpuReset\n"); pmu->callPlatformFunction (pmu_cpuReset, false, 0, 0, 0, 0); while (1) /* spin waiting for restart*/ ; } } // Continue the wake process keyLargo->callPlatformFunction(keyLargo_restoreRegisterState, false, 0, 0, 0, 0); // Enables the interrupts for this CPU. if (macRISC2PE->getMachineType() == kMacRISC2TypePowerMac) { haveSleptMPIC = false; kprintf("MacRISC2CPU::initCPU %ld -> mpic->setUpForSleep off", getCPUNumber()); mpic->callPlatformFunction(mpic_setUpForSleep, false, (void *)false, (void *)getCPUNumber(), 0, 0); } } } kprintf("MacRISC2CPU::initCPU %ld Here!\n", getCPUNumber()); // Set time base. if (bootCPU) keyLargo->callPlatformFunction(keyLargo_syncTimeBase, false, 0, 0, 0, 0); if (boot) { if (gCPUIC) gCPUIC->enableCPUInterrupt(this); else panic ("MacRISC2CPU: gCPUIC uninitialized for CPU %ld\n", getCPUNumber()); // Register and enable IPIs. cpuNub->registerInterrupt(0, this, OSMemberFunctionCast(IOInterruptAction, this, &MacRISC2CPU::ipiHandler), 0); // [4091924] cpuNub->enableInterrupt(0); } // [5376988] - MPIC is no longer automatically setting priority to 0 so now must do this in all cases, not just non-boot case long priority = 0; mpic->callPlatformFunction(mpic_setCurrentTaskPriority, false, (void *)&priority, 0, 0, 0); setCPUState(kIOCPUStateRunning); }
bool ApplePS2Keyboard::start(IOService * provider) { keyi=false; // // The driver has been instructed to start. This is called after a // successful attach. // if (!super::start(provider)) return false; // // Maintain a pointer to and retain the provider object. // _device = (ApplePS2KeyboardDevice *)provider; _device->retain(); if (kOSBooleanTrue == getProperty("Make capslock into control")) { emacsMode = true; } else { emacsMode = false; } if (kOSBooleanTrue == getProperty("Swap alt and windows key")) { macintoshMode = true; } else { macintoshMode = false; } // // Install our driver's interrupt handler, for asynchronous data delivery. // _device->installInterruptAction(this, /*(PS2InterruptAction)&ApplePS2Keyboard::interruptOccurred*/ OSMemberFunctionCast(PS2InterruptAction, this, &ApplePS2Keyboard::interruptOccurred)); _interruptHandlerInstalled = true; // // Initialize the keyboard LED state. // setLEDs(_ledState); // // Enable the keyboard clock (should already be so), the keyboard IRQ line, // and the keyboard Kscan -> scan code translation mode. // setCommandByte(kCB_EnableKeyboardIRQ | kCB_TranslateMode, kCB_DisableKeyboardClock); // // Finally, we enable the keyboard itself, so that it may start reporting // key events. // setKeyboardEnable(true); // // Install our power control handler. // _device->installPowerControlAction( this, /*(PS2PowerControlAction) &ApplePS2Keyboard::setDevicePowerState*/ OSMemberFunctionCast(PS2PowerControlAction, this, &ApplePS2Keyboard::setDevicePowerState) ); _powerControlHandlerInstalled = true; return true; }
bool ApplePS2CypressTouchPad::start( IOService * provider ) { UInt64 enabledProperty; UInt64 disabledProperty; // // The driver has been instructed to start. This is called after a // successful probe and match. // if (!super::start(provider)) return false; // // Maintain a pointer to and retain the provider object. // _device = (ApplePS2MouseDevice *) provider; _device->retain(); // // Announce hardware properties. // IOLog("CYPRESS: ApplePS2Trackpad: Cypress Trackpad firmware v%d\n", (UInt8)(_touchPadVersion)); // // Advertise some supported features (tapping, edge scrolling). // // enabledProperty = 1; // disabledProperty = 0; // setProperty("Clicking", enabledProperty, // sizeof(enabledProperty) * 8); // setProperty("DragLock", disabledProperty, // sizeof(disabledProperty) * 8); // setProperty("Dragging", disabledProperty, // sizeof(disabledProperty) * 8); // setProperty("TrackpadScroll", enabledProperty, // sizeof(enabledProperty) * 8); // setProperty("TrackpadHorizScroll", enabledProperty, // sizeof(enabledProperty) * 8); // setProperty("CypressFourFingerHorizSwipeGesture", ( _fourFingerHorizSwipeGesture ? enabledProperty : disabledProperty), // sizeof(enabledProperty) * 8); // setProperty("CypressFourFingerVertSwipeGesture", ( _fourFingerVertSwipeGesture ? enabledProperty : disabledProperty), // sizeof(enabledProperty) * 8); // setProperty("CypressFiveFingerScreenLock", ( _fiveFingerScreenLock ? enabledProperty : disabledProperty), // sizeof(enabledProperty) * 8); // setProperty("CypressFiveFingerSleep", (_fiveFingerSleep ? enabledProperty : disabledProperty), // sizeof(enabledProperty) * 8); // setProperty("CypressThreeFingerDrag", (_threeFingerDrag ? enabledProperty : disabledProperty), // sizeof(enabledProperty) * 8); // float i = 200; // setProperty("1FingersMaxTapTime", i, sizeof(i) * 8); // setProperty("2FingersMaxTapTime", i, sizeof(i) * 8); // setProperty("3FingersMaxTapTime", i, sizeof(i) * 8); // // Must add this property to let our superclass know that it should handle // trackpad acceleration settings from user space. Without this, tracking // speed adjustments from the mouse prefs panel have no effect. // setProperty(kIOHIDPointerAccelerationTypeKey, kIOHIDTrackpadAccelerationType); setProperty(kIOHIDScrollAccelerationTypeKey, kIOHIDTrackpadScrollAccelerationKey); // // Lock the controller during initialization // _device->lock(); if (_touchPadVersion > 11) _tapFrameMax = 11; setTouchpadModeByte(); _device->installInterruptAction(this, OSMemberFunctionCast(PS2InterruptAction, this, &ApplePS2CypressTouchPad::interruptOccurred), OSMemberFunctionCast(PS2PacketAction, this, &ApplePS2CypressTouchPad::packetReady)); _interruptHandlerInstalled = true; // now safe to allow other threads _device->unlock(); // // Install our power control handler. // _device->installPowerControlAction( this, OSMemberFunctionCast(PS2PowerControlAction,this, &ApplePS2CypressTouchPad::setDevicePowerState) ); _powerControlHandlerInstalled = true; return true; }