mirror of
https://github.com/OpenIntelWireless/itlwm.git
synced 2024-11-25 13:56:13 +00:00
1054 lines
35 KiB
C++
1054 lines
35 KiB
C++
//
|
|
// AirportItlwmV2.cpp
|
|
// AirportItlwm-Sonoma
|
|
//
|
|
// Created by qcwap on 2023/6/27.
|
|
// Copyright © 2023 钟先耀. All rights reserved.
|
|
//
|
|
|
|
#include "AirportItlwmV2.hpp"
|
|
#include <sys/_netstat.h>
|
|
#include <crypto/sha1.h>
|
|
#include <net80211/ieee80211_priv.h>
|
|
#include <net80211/ieee80211_var.h>
|
|
|
|
#include "AirportItlwmSkywalkInterface.hpp"
|
|
#include "IOPCIEDeviceWrapper.hpp"
|
|
|
|
#define super IO80211Controller
|
|
OSDefineMetaClassAndStructors(AirportItlwm, IO80211Controller);
|
|
OSDefineMetaClassAndStructors(CTimeout, OSObject)
|
|
|
|
IO80211WorkQueue *_fWorkloop;
|
|
IOCommandGate *_fCommandGate;
|
|
|
|
void AirportItlwm::releaseAll()
|
|
{
|
|
OSSafeReleaseNULL(driverLogPipe);
|
|
OSSafeReleaseNULL(driverDataPathPipe);
|
|
OSSafeReleaseNULL(driverSnapshotsPipe);
|
|
OSSafeReleaseNULL(driverFaultReporter);
|
|
if (fHalService) {
|
|
fHalService->release();
|
|
fHalService = NULL;
|
|
}
|
|
if (_fWorkloop) {
|
|
if (_fCommandGate) {
|
|
// _fCommandGate->disable();
|
|
_fWorkloop->removeEventSource(_fCommandGate);
|
|
_fCommandGate->release();
|
|
_fCommandGate = NULL;
|
|
}
|
|
if (scanSource) {
|
|
scanSource->cancelTimeout();
|
|
scanSource->disable();
|
|
_fWorkloop->removeEventSource(scanSource);
|
|
scanSource->release();
|
|
scanSource = NULL;
|
|
}
|
|
if (fWatchdogWorkLoop && watchdogTimer) {
|
|
watchdogTimer->cancelTimeout();
|
|
fWatchdogWorkLoop->removeEventSource(watchdogTimer);
|
|
watchdogTimer->release();
|
|
watchdogTimer = NULL;
|
|
fWatchdogWorkLoop->release();
|
|
fWatchdogWorkLoop = NULL;
|
|
}
|
|
_fWorkloop->release();
|
|
_fWorkloop = NULL;
|
|
}
|
|
unregistPM();
|
|
}
|
|
|
|
void AirportItlwm::
|
|
eventHandler(struct ieee80211com *ic, int msgCode, void *data)
|
|
{
|
|
AirportItlwm *that = OSDynamicCast(AirportItlwm, ic->ic_ac.ac_if.controller);
|
|
IO80211SkywalkInterface *interface = that->fNetIf;
|
|
if (!interface)
|
|
return;
|
|
switch (msgCode) {
|
|
case IEEE80211_EVT_COUNTRY_CODE_UPDATE:
|
|
interface->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED, NULL, 0, 0);
|
|
break;
|
|
case IEEE80211_EVT_STA_ASSOC_DONE:
|
|
interface->postMessage(APPLE80211_M_ASSOC_DONE, NULL, 0, 0);
|
|
break;
|
|
case IEEE80211_EVT_STA_DEAUTH:
|
|
interface->postMessage(APPLE80211_M_DEAUTH_RECEIVED, NULL, 0, 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AirportItlwm::watchdogAction(IOTimerEventSource *timer)
|
|
{
|
|
struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;
|
|
(*ifp->if_watchdog)(ifp);
|
|
watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);
|
|
}
|
|
|
|
void AirportItlwm::fakeScanDone(OSObject *owner, IOTimerEventSource *sender)
|
|
{
|
|
UInt32 msg = 0;
|
|
AirportItlwm *that = (AirportItlwm *)owner;
|
|
that->fNetIf->postMessage(APPLE80211_M_SCAN_DONE, &msg, 4, 0);
|
|
}
|
|
|
|
bool AirportItlwm::init(OSDictionary *properties)
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
bool ret = super::init(properties);
|
|
awdlSyncEnable = true;
|
|
power_state = 0;
|
|
memset(geo_location_cc, 0, sizeof(geo_location_cc));
|
|
return ret;
|
|
}
|
|
|
|
IOService* AirportItlwm::probe(IOService *provider, SInt32 *score)
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
IOPCIEDeviceWrapper *wrapper = OSDynamicCast(IOPCIEDeviceWrapper, provider);
|
|
if (!wrapper) {
|
|
XYLog("%s Not a IOPCIEDeviceWrapper instance\n", __FUNCTION__);
|
|
return NULL;
|
|
}
|
|
pciNub = wrapper->pciNub;
|
|
fHalService = wrapper->fHalService;
|
|
if (!pciNub || !fHalService) {
|
|
XYLog("%s Not a valid IOPCIEDeviceWrapper instance\n", __FUNCTION__);
|
|
return NULL;
|
|
}
|
|
return super::probe(provider, score);
|
|
}
|
|
|
|
#define LOWER32(x) ((uint64_t)(x) & 0xffffffff)
|
|
#define HIGHER32(x) ((uint64_t)(x) >> 32)
|
|
|
|
bool AirportItlwm::
|
|
initCCLogs()
|
|
{
|
|
CCPipeOptions driverLogOptions = { 0 };
|
|
driverLogOptions.pipe_type = 0;
|
|
driverLogOptions.log_data_type = 1;
|
|
driverLogOptions.pipe_size = 0x200000;
|
|
driverLogOptions.min_log_size_notify = 0xccccc;
|
|
driverLogOptions.notify_threshold = 1000;
|
|
strlcpy(driverLogOptions.file_name, "Itlwm_Logs", sizeof(driverLogOptions.file_name));
|
|
snprintf(driverLogOptions.name, sizeof(driverLogOptions.name), "wlan%d", 0);
|
|
strlcpy(driverLogOptions.directory_name, "WiFi", sizeof(driverLogOptions.directory_name));
|
|
driverLogOptions.pad9 = 0x1000000;
|
|
driverLogOptions.pad10 = 2;
|
|
driverLogOptions.file_options = 0;
|
|
driverLogOptions.log_policy = 0;
|
|
driverLogPipe = CCPipe::withOwnerNameCapacity(this, "com.zxystd.AirportItlwm", "DriverLogs", &driverLogOptions);
|
|
XYLog("%s driverLogPipeRet %d\n", __FUNCTION__, driverLogPipe != NULL);
|
|
|
|
memset(&driverLogOptions, 0, sizeof(driverLogOptions));
|
|
driverLogOptions.pipe_type = 0;
|
|
driverLogOptions.log_data_type = 0;
|
|
driverLogOptions.pipe_size = 0x200000;
|
|
driverLogOptions.min_log_size_notify = 0xccccc;
|
|
driverLogOptions.notify_threshold = 1000;
|
|
strlcpy(driverLogOptions.file_name, "AppleBCMWLAN_Datapath", sizeof(driverLogOptions.file_name));
|
|
strlcpy(driverLogOptions.directory_name, "WiFi", sizeof(driverLogOptions.directory_name));
|
|
driverLogOptions.pad9 = HIGHER32(0x202800000);
|
|
driverLogOptions.pad10 = LOWER32(0x202800000);
|
|
driverLogOptions.file_options = 0;
|
|
driverLogOptions.log_policy = 0;
|
|
driverDataPathPipe = CCPipe::withOwnerNameCapacity(this, "com.zxystd.AirportItlwm", "DatapathEvents", &driverLogOptions);
|
|
XYLog("%s driverDataPathPipeRet %d\n", __FUNCTION__, driverDataPathPipe != NULL);
|
|
|
|
memset(&driverLogOptions, 0, sizeof(driverLogOptions));
|
|
driverLogOptions.pipe_type = 0x200000001;
|
|
driverLogOptions.log_data_type = 2;
|
|
strlcpy(driverLogOptions.file_name, "StateSnapshots", sizeof(driverLogOptions.file_name));
|
|
strlcpy(driverLogOptions.name, "0", sizeof(driverLogOptions.name));
|
|
strlcpy(driverLogOptions.directory_name, "WiFi", sizeof(driverLogOptions.directory_name));
|
|
driverLogOptions.pipe_size = 128;
|
|
driverSnapshotsPipe = CCPipe::withOwnerNameCapacity(this, "com.zxystd.AirportItlwm", "StateSnapshots", &driverLogOptions);
|
|
XYLog("%s driverSnapshotsPipeRet %d\n", __FUNCTION__, driverSnapshotsPipe != NULL);
|
|
|
|
CCStreamOptions faultReportOptions = { 0 };
|
|
faultReportOptions.stream_type = 1;
|
|
faultReportOptions.console_level = 0xFFFFFFFFFFFFFFFF;
|
|
driverFaultReporter = CCStream::withPipeAndName(driverSnapshotsPipe, "FaultReporter", &faultReportOptions);
|
|
XYLog("%s driverFaultReporterRet %d\n", __FUNCTION__, driverFaultReporter != NULL);
|
|
return driverLogPipe && driverDataPathPipe && driverSnapshotsPipe && driverFaultReporter;
|
|
}
|
|
|
|
bool AirportItlwm::start(IOService *provider)
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
struct IOSkywalkEthernetInterface::RegistrationInfo registInfo;
|
|
int boot_value = 0;
|
|
|
|
UInt8 builtIn = 0;
|
|
setProperty("built-in", OSData::withBytes(&builtIn, sizeof(builtIn)));
|
|
setProperty("DriverKitDriver", kOSBooleanFalse);
|
|
if (!super::start(provider)) {
|
|
return false;
|
|
}
|
|
pciNub->setBusMasterEnable(true);
|
|
pciNub->setIOEnable(true);
|
|
pciNub->setMemoryEnable(true);
|
|
pciNub->configWrite8(0x41, 0);
|
|
if (pciNub->requestPowerDomainState(kIOPMPowerOn,
|
|
(IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState) != IOPMNoErr) {
|
|
super::stop(provider);
|
|
return false;
|
|
}
|
|
if (initPCIPowerManagment(pciNub) == false) {
|
|
super::stop(pciNub);
|
|
return false;
|
|
}
|
|
if (_fWorkloop == NULL) {
|
|
XYLog("No _fWorkloop!!\n");
|
|
super::stop(pciNub);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
_fCommandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)AirportItlwm::tsleepHandler);
|
|
if (_fCommandGate == 0) {
|
|
XYLog("No command gate!!\n");
|
|
super::stop(pciNub);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
_fWorkloop->addEventSource(_fCommandGate);
|
|
const IONetworkMedium *primaryMedium;
|
|
if (!createMediumTables(&primaryMedium) ||
|
|
!setCurrentMedium(primaryMedium) || !setSelectedMedium(primaryMedium)) {
|
|
XYLog("setup medium fail\n");
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
fHalService->initWithController(this, _fWorkloop, _fCommandGate);
|
|
fHalService->get80211Controller()->ic_event_handler = eventHandler;
|
|
|
|
if (PE_parse_boot_argn("-novht", &boot_value, sizeof(boot_value)))
|
|
fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOVHT;
|
|
if (PE_parse_boot_argn("-noht40", &boot_value, sizeof(boot_value)))
|
|
fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOHT40;
|
|
|
|
if (!fHalService->attach(pciNub)) {
|
|
XYLog("attach fail\n");
|
|
super::stop(pciNub);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
fWatchdogWorkLoop = IOWorkLoop::workLoop();
|
|
if (fWatchdogWorkLoop == NULL) {
|
|
XYLog("init watchdog workloop fail\n");
|
|
fHalService->detach(pciNub);
|
|
super::stop(pciNub);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
watchdogTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &AirportItlwm::watchdogAction));
|
|
if (!watchdogTimer) {
|
|
XYLog("init watchdog fail\n");
|
|
fHalService->detach(pciNub);
|
|
super::stop(pciNub);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
fWatchdogWorkLoop->addEventSource(watchdogTimer);
|
|
scanSource = IOTimerEventSource::timerEventSource(this, &fakeScanDone);
|
|
_fWorkloop->addEventSource(scanSource);
|
|
scanSource->enable();
|
|
|
|
fNetIf = new AirportItlwmSkywalkInterface;
|
|
if (!fNetIf->init(this)) {
|
|
XYLog("Skywalk interface init fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
fNetIf->setInterfaceRole(1);
|
|
fNetIf->setInterfaceId(1);
|
|
|
|
if (!initCCLogs()) {
|
|
XYLog("CCLog init fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
if (!fNetIf->attach(this)) {
|
|
XYLog("attach to service fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
if (!attachInterface(fNetIf, this)) {
|
|
XYLog("attach to interface fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
if (!IONetworkController::attachInterface((IONetworkInterface **)&bsdInterface, true)) {
|
|
XYLog("attach to IONetworkController interface fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
memset(®istInfo, 0, sizeof(registInfo));
|
|
if (!fNetIf->initRegistrationInfo(®istInfo, 1, sizeof(registInfo))) {
|
|
XYLog("initRegistrationInfo fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
if (!fNetIf->initRegistrationInfo(®istInfo, 1, sizeof(registInfo))) {
|
|
XYLog("initRegistrationInfo fail\n");
|
|
super::stop(provider);
|
|
releaseAll();
|
|
return false;
|
|
}
|
|
fNetIf->mExpansionData->fRegistrationInfo = (struct IOSkywalkNetworkInterface::RegistrationInfo *)IOMalloc(sizeof(struct IOSkywalkNetworkInterface::RegistrationInfo));
|
|
fNetIf->mExpansionData2->fRegistrationInfo = (struct IOSkywalkEthernetInterface::RegistrationInfo *)IOMalloc(sizeof(struct IOSkywalkEthernetInterface::RegistrationInfo));
|
|
memcpy(fNetIf->mExpansionData->fRegistrationInfo, ®istInfo, sizeof(registInfo));
|
|
memcpy(fNetIf->mExpansionData2->fRegistrationInfo, ®istInfo, sizeof(registInfo));
|
|
if (fNetIf->getInterfaceRole() == 1)
|
|
fNetIf->deferBSDAttach(true);
|
|
fNetIf->start(this);
|
|
|
|
setLinkStatus(kIONetworkLinkValid);
|
|
if (TAILQ_EMPTY(&fHalService->get80211Controller()->ic_ess))
|
|
fHalService->get80211Controller()->ic_flags |= IEEE80211_F_AUTO_JOIN;
|
|
registerService();
|
|
return true;
|
|
}
|
|
|
|
void AirportItlwm::stop(IOService *provider)
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;
|
|
super::stop(provider);
|
|
disableAdapter(bsdInterface);
|
|
setLinkStatus(kIONetworkLinkValid);
|
|
fHalService->detach(pciNub);
|
|
ether_ifdetach(ifp);
|
|
detachInterface(fNetIf, true);
|
|
OSSafeReleaseNULL(fNetIf);
|
|
releaseAll();
|
|
}
|
|
|
|
void AirportItlwm::free()
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
if (fHalService != NULL) {
|
|
fHalService->release();
|
|
fHalService = NULL;
|
|
}
|
|
if (syncFrameTemplate != NULL && syncFrameTemplateLength > 0) {
|
|
IOFree(syncFrameTemplate, syncFrameTemplateLength);
|
|
syncFrameTemplateLength = 0;
|
|
syncFrameTemplate = NULL;
|
|
}
|
|
if (roamProfile != NULL) {
|
|
IOFree(roamProfile, sizeof(struct apple80211_roam_profile_band_data));
|
|
roamProfile = NULL;
|
|
}
|
|
if (btcProfile != NULL) {
|
|
IOFree(btcProfile, sizeof(struct apple80211_btc_profiles_data));
|
|
btcProfile = NULL;
|
|
}
|
|
super::free();
|
|
}
|
|
|
|
bool AirportItlwm::createWorkQueue()
|
|
{
|
|
XYLog("%s %d\n", __FUNCTION__, _fWorkloop != 0);
|
|
return _fWorkloop != 0;
|
|
}
|
|
|
|
IO80211WorkQueue *AirportItlwm::getWorkQueue()
|
|
{
|
|
return _fWorkloop;
|
|
}
|
|
|
|
void *AirportItlwm::getFaultReporterFromDriver()
|
|
{
|
|
return driverFaultReporter;
|
|
}
|
|
|
|
IOReturn AirportItlwm::enable(IO80211SkywalkInterface *netif)
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
super::enable(netif);
|
|
_fCommandGate->enable();
|
|
if (power_state)
|
|
enableAdapter(bsdInterface);
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::disable(IO80211SkywalkInterface *netif)
|
|
{
|
|
XYLog("%s\n", __PRETTY_FUNCTION__);
|
|
super::disable(netif);
|
|
setLinkStatus(kIONetworkLinkValid);
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
bool AirportItlwm::configureInterface(IONetworkInterface *netif)
|
|
{
|
|
IONetworkData *nd;
|
|
struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;
|
|
|
|
if (super::configureInterface(netif) == false) {
|
|
XYLog("super failed\n");
|
|
return false;
|
|
}
|
|
|
|
nd = netif->getParameter(kIONetworkStatsKey);
|
|
if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) {
|
|
XYLog("network statistics buffer unavailable?\n");
|
|
return false;
|
|
}
|
|
ifp->netStat = fpNetStats;
|
|
ether_ifattach(ifp, OSDynamicCast(IOEthernetInterface, netif));
|
|
fpNetStats->collisions = 0;
|
|
#ifdef __PRIVATE_SPI__
|
|
netif->configureOutputPullModel(fHalService->getDriverInfo()->getTxQueueSize(), 0, 0, IOEthernetInterface::kOutputPacketSchedulingModelNormal, 0);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
IONetworkInterface *AirportItlwm::createInterface()
|
|
{
|
|
AirportItlwmEthernetInterface *netif = new AirportItlwmEthernetInterface;
|
|
if (!netif)
|
|
return NULL;
|
|
if (!netif->initWithSkywalkInterfaceAndProvider(this, fNetIf)) {
|
|
netif->release();
|
|
return NULL;
|
|
}
|
|
return netif;
|
|
}
|
|
|
|
bool AirportItlwm::createMediumTables(const IONetworkMedium **primary)
|
|
{
|
|
IONetworkMedium *medium;
|
|
|
|
OSDictionary *mediumDict = OSDictionary::withCapacity(2);
|
|
if (mediumDict == NULL) {
|
|
XYLog("Cannot allocate OSDictionary\n");
|
|
return false;
|
|
}
|
|
|
|
medium = IONetworkMedium::medium(kIOMediumIEEE80211, 54000000);
|
|
IONetworkMedium::addMedium(mediumDict, medium);
|
|
medium->release();
|
|
if (primary) {
|
|
*primary = medium;
|
|
}
|
|
medium = IONetworkMedium::medium(kIOMediumIEEE80211None, 0);
|
|
IONetworkMedium::addMedium(mediumDict, medium);
|
|
medium->release();
|
|
|
|
bool result = publishMediumDictionary(mediumDict);
|
|
if (!result) {
|
|
XYLog("Cannot publish medium dictionary!\n");
|
|
}
|
|
|
|
mediumDict->release();
|
|
return result;
|
|
}
|
|
|
|
IOReturn AirportItlwm::selectMedium(const IONetworkMedium *medium) {
|
|
setSelectedMedium(medium);
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
bool AirportItlwm::
|
|
setLinkStatus(UInt32 status, const IONetworkMedium * activeMedium, UInt64 speed, OSData * data)
|
|
{
|
|
struct _ifnet *ifq = &fHalService->get80211Controller()->ic_ac.ac_if;
|
|
if (status == currentStatus) {
|
|
return true;
|
|
}
|
|
bool ret = super::setLinkStatus(status, activeMedium, speed, data);
|
|
currentStatus = status;
|
|
if (fNetIf) {
|
|
if (status & kIONetworkLinkActive) {
|
|
#ifdef __PRIVATE_SPI__
|
|
bsdInterface->startOutputThread();
|
|
#endif
|
|
getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkUp, (void *)0);
|
|
// fNetIf->setLinkQualityMetric(100);
|
|
} else if (!(status & kIONetworkLinkNoNetworkChange)) {
|
|
#ifdef __PRIVATE_SPI__
|
|
bsdInterface->stopOutputThread();
|
|
bsdInterface->flushOutputQueue();
|
|
#endif
|
|
ifq_flush(&ifq->if_snd);
|
|
mq_purge(&fHalService->get80211Controller()->ic_mgtq);
|
|
getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkDown, (void *)fHalService->get80211Controller()->ic_deauth_reason);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3)
|
|
{
|
|
AirportItlwm *that = OSDynamicCast(AirportItlwm, target);
|
|
IOReturn ret = that->fNetIf->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1);
|
|
that->fNetIf->setRunningState((IO80211LinkState)(uint64_t)arg0 == kIO80211NetworkLinkUp);
|
|
that->fNetIf->postMessage(APPLE80211_M_LINK_CHANGED, NULL, 0, false);
|
|
that->fNetIf->postMessage(APPLE80211_M_BSSID_CHANGED, NULL, 0, false);
|
|
that->fNetIf->postMessage(APPLE80211_M_SSID_CHANGED, NULL, 0, false);
|
|
if ((IO80211LinkState)(uint64_t)arg0 == kIO80211NetworkLinkUp) {
|
|
that->fNetIf->reportLinkStatus(3, 0x80);
|
|
} else {
|
|
that->fNetIf->reportLinkStatus(1, 0);
|
|
}
|
|
that->bsdInterface->setLinkState((IO80211LinkState)(uint64_t)arg0);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef __PRIVATE_SPI__
|
|
IOReturn AirportItlwm::outputStart(IONetworkInterface *interface, IOOptionBits options)
|
|
{
|
|
struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;
|
|
mbuf_t m = NULL;
|
|
if (ifq_is_oactive(&ifp->if_snd))
|
|
return kIOReturnNoResources;
|
|
while (kIOReturnSuccess == interface->dequeueOutputPackets(1, &m)) {
|
|
if (outputPacket(m, NULL)!= kIOReturnOutputSuccess ||
|
|
ifq_is_oactive(&ifp->if_snd))
|
|
return kIOReturnNoResources;
|
|
}
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::networkInterfaceNotification(
|
|
IONetworkInterface * interface,
|
|
uint32_t type,
|
|
void * argument )
|
|
{
|
|
XYLog("%s\n", __FUNCTION__);
|
|
return kIOReturnSuccess;
|
|
}
|
|
#endif
|
|
|
|
extern const char* hexdump(uint8_t *buf, size_t len);
|
|
|
|
UInt32 AirportItlwm::outputPacket(mbuf_t m, void *param)
|
|
{
|
|
// XYLog("%s\n", __FUNCTION__);
|
|
IOReturn ret = kIOReturnOutputSuccess;
|
|
struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if;
|
|
|
|
if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || ifp->if_snd.queue == NULL) {
|
|
if (m && mbuf_type(m) != MBUF_TYPE_FREE)
|
|
freePacket(m);
|
|
return kIOReturnOutputDropped;
|
|
}
|
|
if (m == NULL) {
|
|
XYLog("%s m==NULL!!\n", __FUNCTION__);
|
|
ifp->netStat->outputErrors++;
|
|
ret = kIOReturnOutputDropped;
|
|
}
|
|
if (!(mbuf_flags(m) & MBUF_PKTHDR) ){
|
|
XYLog("%s pkthdr is NULL!!\n", __FUNCTION__);
|
|
ifp->netStat->outputErrors++;
|
|
freePacket(m);
|
|
ret = kIOReturnOutputDropped;
|
|
}
|
|
if (mbuf_type(m) == MBUF_TYPE_FREE) {
|
|
XYLog("%s mbuf is FREE!!\n", __FUNCTION__);
|
|
ifp->netStat->outputErrors++;
|
|
ret = kIOReturnOutputDropped;
|
|
}
|
|
size_t len = mbuf_len(m);
|
|
ether_header_t *eh = (ether_header_t *)mbuf_data(m);
|
|
if (len >= sizeof(ether_header_t) && eh->ether_type == htons(ETHERTYPE_PAE)) { // EAPOL packet
|
|
const char* dump = hexdump((uint8_t*)mbuf_data(m), len);
|
|
XYLog("output EAPOL packet, len: %zu, data: %s\n", len, dump ? dump : "Failed to allocate memory");
|
|
if (dump)
|
|
IOFree((void*)dump, 3 * len + 1);
|
|
}
|
|
if (!ifp->if_snd.queue->lockEnqueue(m)) {
|
|
freePacket(m);
|
|
ret = kIOReturnOutputDropped;
|
|
}
|
|
(*ifp->if_start)(ifp);
|
|
return ret;
|
|
}
|
|
|
|
const OSString * AirportItlwm::newVendorString() const
|
|
{
|
|
return OSString::withCString("Apple");
|
|
}
|
|
|
|
const OSString * AirportItlwm::newModelString() const
|
|
{
|
|
return OSString::withCString(fHalService->getDriverInfo()->getFirmwareName());
|
|
}
|
|
|
|
IOReturn AirportItlwm::getHardwareAddress(IOEthernetAddress *addrP)
|
|
{
|
|
if (IEEE80211_ADDR_EQ(etheranyaddr, fHalService->get80211Controller()->ic_myaddr))
|
|
return kIOReturnError;
|
|
else {
|
|
IEEE80211_ADDR_COPY(addrP, fHalService->get80211Controller()->ic_myaddr);
|
|
return kIOReturnSuccess;
|
|
}
|
|
}
|
|
|
|
IOReturn AirportItlwm::setHardwareAddress(const void *addrP, UInt32 addrBytes)
|
|
{
|
|
if (!fNetIf || !addrP)
|
|
return kIOReturnError;
|
|
if_setlladdr(&fHalService->get80211Controller()->ic_ac.ac_if, (const UInt8 *)addrP);
|
|
if (fHalService->get80211Controller()->ic_state > IEEE80211_S_INIT) {
|
|
fHalService->disable(bsdInterface);
|
|
fHalService->enable(bsdInterface);
|
|
}
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
UInt32 AirportItlwm::getFeatures() const
|
|
{
|
|
return fHalService->getDriverInfo()->supportedFeatures();
|
|
}
|
|
|
|
IOReturn AirportItlwm::setPromiscuousMode(IOEnetPromiscuousMode mode)
|
|
{
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::setMulticastMode(IOEnetMulticastMode mode)
|
|
{
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::setMulticastList(IOEthernetAddress* addr, UInt32 len)
|
|
{
|
|
return fHalService->getDriverController()->setMulticastList(addr, len);
|
|
}
|
|
|
|
IOReturn AirportItlwm::getPacketFilters(const OSSymbol *group, UInt32 *filters) const
|
|
{
|
|
IOReturn rtn = kIOReturnSuccess;
|
|
if (group == gIOEthernetWakeOnLANFilterGroup && magicPacketSupported)
|
|
*filters = kIOEthernetWakeOnMagicPacket;
|
|
else if (group == gIONetworkFilterGroup)
|
|
*filters = kIOPacketFilterMulticast | kIOPacketFilterPromiscuous;
|
|
else
|
|
rtn = IOEthernetController::getPacketFilters(group, filters);
|
|
return rtn;
|
|
}
|
|
|
|
SInt32 AirportItlwm::
|
|
enableFeature(IO80211FeatureCode code, void *data)
|
|
{
|
|
if (code == kIO80211Feature80211n) {
|
|
return 0;
|
|
}
|
|
return 102;
|
|
}
|
|
|
|
bool AirportItlwm::getLogPipes(CCPipe**logPipe, CCPipe**eventPipe, CCPipe**snapshotsPipe)
|
|
{
|
|
bool ret = false;
|
|
if (logPipe) {
|
|
*logPipe = driverLogPipe;
|
|
ret = true;
|
|
}
|
|
if (eventPipe) {
|
|
*eventPipe = driverDataPathPipe;
|
|
ret = true;
|
|
}
|
|
if (snapshotsPipe) {
|
|
*snapshotsPipe = driverSnapshotsPipe;
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define APPLE80211_CAPA_AWDL_FEATURE_AUTO_UNLOCK 0x00000004
|
|
#define APPLE80211_CAPA_AWDL_FEATURE_WOW 0x00000080
|
|
|
|
IOReturn AirportItlwm::
|
|
getCARD_CAPABILITIES(OSObject *object,
|
|
struct apple80211_capability_data *cd)
|
|
{
|
|
uint32_t caps = fHalService->get80211Controller()->ic_caps;
|
|
memset(cd, 0, sizeof(struct apple80211_capability_data));
|
|
|
|
if (caps & IEEE80211_C_WEP)
|
|
cd->capabilities[0] |= 1 << APPLE80211_CAP_WEP;
|
|
if (caps & IEEE80211_C_RSN)
|
|
cd->capabilities[0] |= 1 << APPLE80211_CAP_TKIP | 1 << APPLE80211_CAP_AES_CCM;
|
|
// Disable not implemented capabilities
|
|
// if (caps & IEEE80211_C_PMGT)
|
|
// cd->capabilities[0] |= 1 << APPLE80211_CAP_PMGT;
|
|
// if (caps & IEEE80211_C_IBSS)
|
|
// cd->capabilities[0] |= 1 << APPLE80211_CAP_IBSS;
|
|
// if (caps & IEEE80211_C_HOSTAP)
|
|
// cd->capabilities[0] |= 1 << APPLE80211_CAP_HOSTAP;
|
|
// AES not enabled, like on Apple cards
|
|
|
|
if (caps & IEEE80211_C_SHSLOT)
|
|
cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHSLOT - 8);
|
|
if (caps & IEEE80211_C_SHPREAMBLE)
|
|
cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHPREAMBLE - 8);
|
|
if (caps & IEEE80211_C_RSN)
|
|
cd->capabilities[1] |= 1 << (APPLE80211_CAP_WPA1 - 8) | 1 << (APPLE80211_CAP_WPA2 - 8) | 1 << (APPLE80211_CAP_TKIPMIC - 8);
|
|
// Disable not implemented capabilities
|
|
// if (caps & IEEE80211_C_TXPMGT)
|
|
// cd->capabilities[1] |= 1 << (APPLE80211_CAP_TXPMGT - 8);
|
|
// if (caps & IEEE80211_C_MONITOR)
|
|
// cd->capabilities[1] |= 1 << (APPLE80211_CAP_MONITOR - 8);
|
|
// WPA not enabled, like on Apple cards
|
|
|
|
cd->version = APPLE80211_VERSION;
|
|
cd->capabilities[2] = 0xFF; // BURST, WME, SHORT_GI_40MHZ, SHORT_GI_20MHZ, WOW, TSN, ?, ?
|
|
cd->capabilities[3] = 0x2B;
|
|
cd->capabilities[5] = 0x40;
|
|
cd->capabilities[6] = (
|
|
// 1 | //MFP capable
|
|
0x8 |
|
|
0x4 |
|
|
0x80
|
|
);
|
|
*(uint16_t *)&cd->capabilities[8] = 0x201;
|
|
//
|
|
// cd->capabilities[2] |= 0x10;
|
|
// cd->capabilities[5] |= 0x1;
|
|
//
|
|
// cd->capabilities[2] |= 0x2;
|
|
//
|
|
// cd->capabilities[3] |= 0x20;
|
|
//
|
|
// cd->capabilities[0] |= 0x80;
|
|
//
|
|
// cd->capabilities[3] |= 0x80;
|
|
// cd->capabilities[4] |= 0x4;
|
|
//
|
|
// cd->capabilities[4] |= 0x1;
|
|
// cd->capabilities[3] |= 0x1;
|
|
// cd->capabilities[6] |= 0x8;
|
|
//
|
|
// cd->capabilities[3] |= 3;
|
|
// cd->capabilities[4] |= 2;
|
|
// cd->capabilities[6] |= 0x10;
|
|
// cd->capabilities[5] |= 0x20;
|
|
// cd->capabilities[5] |= 0x80;
|
|
//
|
|
// if (cd->capabilities[6] & 0x20) {
|
|
// cd->capabilities[2] |= 8;
|
|
// }
|
|
// cd->capabilities[5] |= 8;
|
|
// cd->capabilities[8] |= 2;
|
|
//
|
|
// cd->capabilities[11] |= (2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80);
|
|
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
getDRIVER_VERSION(OSObject *object,
|
|
struct apple80211_version_data *hv)
|
|
{
|
|
if (!hv)
|
|
return kIOReturnError;
|
|
hv->version = APPLE80211_VERSION;
|
|
snprintf(hv->string, sizeof(hv->string), "itlwm: %s%s fw: %s", ITLWM_VERSION, GIT_COMMIT, fHalService->getDriverInfo()->getFirmwareVersion());
|
|
hv->string_len = strlen(hv->string);
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
getHARDWARE_VERSION(OSObject *object,
|
|
struct apple80211_version_data *hv)
|
|
{
|
|
if (!hv)
|
|
return kIOReturnError;
|
|
hv->version = APPLE80211_VERSION;
|
|
strncpy(hv->string, fHalService->getDriverInfo()->getFirmwareVersion(), sizeof(hv->string));
|
|
hv->string_len = strlen(fHalService->getDriverInfo()->getFirmwareVersion());
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
getCOUNTRY_CODE(OSObject *object,
|
|
struct apple80211_country_code_data *cd)
|
|
{
|
|
char user_override_cc[3];
|
|
const char *cc_fw = fHalService->getDriverInfo()->getFirmwareCountryCode();
|
|
|
|
if (!cd)
|
|
return kIOReturnError;
|
|
cd->version = APPLE80211_VERSION;
|
|
memset(user_override_cc, 0, sizeof(user_override_cc));
|
|
PE_parse_boot_argn("itlwm_cc", user_override_cc, 3);
|
|
/* user_override_cc > firmware_cc > geo_location_cc */
|
|
strncpy((char*)cd->cc, user_override_cc[0] ? user_override_cc : ((cc_fw[0] == 'Z' && cc_fw[1] == 'Z' && geo_location_cc[0]) ? geo_location_cc : cc_fw), sizeof(cd->cc));
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
setCOUNTRY_CODE(OSObject *object, struct apple80211_country_code_data *data)
|
|
{
|
|
XYLog("%s cc=%s\n", __FUNCTION__, data->cc);
|
|
if (data && data->cc[0] != 120 && data->cc[0] != 88) {
|
|
memcpy(geo_location_cc, data->cc, sizeof(geo_location_cc));
|
|
fNetIf->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED, NULL, 0, 0);
|
|
}
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
getPOWER(OSObject *object,
|
|
struct apple80211_power_data *pd)
|
|
{
|
|
if (!pd)
|
|
return kIOReturnError;
|
|
pd->version = APPLE80211_VERSION;
|
|
pd->num_radios = 4;
|
|
pd->power_state[0] = power_state;
|
|
pd->power_state[1] = power_state;
|
|
pd->power_state[2] = power_state;
|
|
pd->power_state[3] = power_state;
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
setPOWER(OSObject *object,
|
|
struct apple80211_power_data *pd)
|
|
{
|
|
if (!pd)
|
|
return kIOReturnError;
|
|
IOLog("itlwm: setPOWER: num_radios[%d] power_state(0:%u 1:%u 2:%u 3:%u)\n", pd->num_radios, pd->power_state[0], pd->power_state[1], pd->power_state[2], pd->power_state[3]);
|
|
if (pd->num_radios > 0) {
|
|
bool isRunning = (fHalService->get80211Controller()->ic_ac.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != 0;
|
|
if (pd->power_state[0] == 0) {
|
|
changePowerStateToPriv(1);
|
|
if (isRunning) {
|
|
net80211_ifstats(fHalService->get80211Controller());
|
|
disableAdapter(bsdInterface);
|
|
}
|
|
} else {
|
|
changePowerStateToPriv(2);
|
|
if (!isRunning)
|
|
enableAdapter(bsdInterface);
|
|
}
|
|
power_state = (pd->power_state[0]);
|
|
}
|
|
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
SInt32 AirportItlwm::apple80211_ioctl(IO80211SkywalkInterface *interface,unsigned long cmd,void *data, bool b1, bool b2)
|
|
{
|
|
if (!ml_at_interrupt_context())
|
|
XYLog("%s cmd: %s b1: %d b2: %d\n", __FUNCTION__, convertApple80211IOCTLToString((unsigned int)cmd), b1, b2);
|
|
return super::apple80211_ioctl(interface, cmd, data, b1, b2);
|
|
}
|
|
|
|
SInt32 AirportItlwm::apple80211SkywalkRequest(UInt request,int cmd,IO80211SkywalkInterface *interface,void *data)
|
|
{
|
|
if (!ml_at_interrupt_context())
|
|
XYLog("%s 1 cmd: %s request: %d\n", __FUNCTION__, convertApple80211IOCTLToString(cmd), request);
|
|
return kIOReturnUnsupported;
|
|
}
|
|
|
|
SInt32 AirportItlwm::apple80211SkywalkRequest(UInt request,int cmd,IO80211SkywalkInterface *interface,void *data,void *)
|
|
{
|
|
if (!ml_at_interrupt_context())
|
|
XYLog("%s 2 cmd: %s request: %d\n", __FUNCTION__, convertApple80211IOCTLToString(cmd), request);
|
|
return kIOReturnUnsupported;
|
|
}
|
|
|
|
IOReturn AirportItlwm::enableAdapter(IONetworkInterface *netif)
|
|
{
|
|
fHalService->enable(netif);
|
|
watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod);
|
|
watchdogTimer->enable();
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
void AirportItlwm::disableAdapter(IONetworkInterface *netif)
|
|
{
|
|
watchdogTimer->cancelTimeout();
|
|
watchdogTimer->disable();
|
|
fHalService->disable(netif);
|
|
}
|
|
|
|
IOReturn AirportItlwm::
|
|
tsleepHandler(OSObject* owner, void* arg0, void* arg1, void* arg2, void* arg3)
|
|
{
|
|
AirportItlwm* dev = OSDynamicCast(AirportItlwm, owner);
|
|
if (dev == 0)
|
|
return kIOReturnError;
|
|
|
|
if (arg1 == 0) {
|
|
if (_fCommandGate->commandSleep(arg0, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)
|
|
return kIOReturnSuccess;
|
|
else
|
|
return kIOReturnTimeout;
|
|
} else {
|
|
AbsoluteTime deadline;
|
|
clock_interval_to_deadline((*(int*)arg1), kNanosecondScale, reinterpret_cast<uint64_t*> (&deadline));
|
|
if (_fCommandGate->commandSleep(arg0, deadline, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED)
|
|
return kIOReturnSuccess;
|
|
else
|
|
return kIOReturnTimeout;
|
|
}
|
|
}
|
|
|
|
bool AirportItlwm::initPCIPowerManagment(IOPCIDevice *provider)
|
|
{
|
|
UInt16 reg16;
|
|
|
|
reg16 = provider->configRead16(kIOPCIConfigCommand);
|
|
|
|
reg16 |= ( kIOPCICommandBusMaster |
|
|
kIOPCICommandMemorySpace |
|
|
kIOPCICommandMemWrInvalidate );
|
|
|
|
reg16 &= ~kIOPCICommandIOSpace; // disable I/O space
|
|
|
|
provider->configWrite16( kIOPCIConfigCommand, reg16 );
|
|
provider->findPCICapability(kIOPCIPowerManagementCapability,
|
|
&pmPCICapPtr);
|
|
if (pmPCICapPtr) {
|
|
UInt16 pciPMCReg = provider->configRead32( pmPCICapPtr ) >> 16;
|
|
if (pciPMCReg & kPCIPMCPMESupportFromD3Cold)
|
|
magicPacketSupported = true;
|
|
provider->configWrite16((pmPCICapPtr + 4), 0x8000 );
|
|
IOSleep(10);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static IOPMPowerState powerStateArray[kPowerStateCount] =
|
|
{
|
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
{1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
void AirportItlwm::unregistPM()
|
|
{
|
|
if (powerOffThreadCall) {
|
|
thread_call_free(powerOffThreadCall);
|
|
powerOffThreadCall = NULL;
|
|
}
|
|
if (powerOnThreadCall) {
|
|
thread_call_free(powerOnThreadCall);
|
|
powerOnThreadCall = NULL;
|
|
}
|
|
}
|
|
|
|
IOReturn AirportItlwm::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker)
|
|
{
|
|
IOReturn result = IOPMAckImplied;
|
|
|
|
if (pmPowerState == powerStateOrdinal)
|
|
return result;
|
|
switch (powerStateOrdinal) {
|
|
case kPowerStateOff:
|
|
if (powerOffThreadCall) {
|
|
retain();
|
|
if (thread_call_enter(powerOffThreadCall))
|
|
release();
|
|
result = 5000000;
|
|
}
|
|
break;
|
|
case kPowerStateOn:
|
|
if (powerOnThreadCall) {
|
|
retain();
|
|
if (thread_call_enter(powerOnThreadCall))
|
|
release();
|
|
result = 5000000;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
IOReturn AirportItlwm::setWakeOnMagicPacket(bool active)
|
|
{
|
|
magicPacketEnabled = active;
|
|
return kIOReturnSuccess;
|
|
}
|
|
|
|
static void handleSetPowerStateOff(thread_call_param_t param0,
|
|
thread_call_param_t param1)
|
|
{
|
|
AirportItlwm *self = (AirportItlwm *)param0;
|
|
|
|
if (param1 == 0)
|
|
{
|
|
self->getCommandGate()->runAction((IOCommandGate::Action)
|
|
handleSetPowerStateOff,
|
|
(void *) 1);
|
|
}
|
|
else
|
|
{
|
|
self->setPowerStateOff();
|
|
self->release();
|
|
}
|
|
}
|
|
|
|
static void handleSetPowerStateOn(thread_call_param_t param0,
|
|
thread_call_param_t param1)
|
|
{
|
|
AirportItlwm *self = (AirportItlwm *) param0;
|
|
|
|
if (param1 == 0)
|
|
{
|
|
self->getCommandGate()->runAction((IOCommandGate::Action)
|
|
handleSetPowerStateOn,
|
|
(void *) 1);
|
|
}
|
|
else
|
|
{
|
|
self->setPowerStateOn();
|
|
self->release();
|
|
}
|
|
}
|
|
|
|
IOReturn AirportItlwm::registerWithPolicyMaker(IOService *policyMaker)
|
|
{
|
|
IOReturn ret;
|
|
|
|
pmPowerState = kPowerStateOn;
|
|
pmPolicyMaker = policyMaker;
|
|
|
|
powerOffThreadCall = thread_call_allocate(
|
|
(thread_call_func_t)handleSetPowerStateOff,
|
|
(thread_call_param_t)this);
|
|
powerOnThreadCall = thread_call_allocate(
|
|
(thread_call_func_t)handleSetPowerStateOn,
|
|
(thread_call_param_t)this);
|
|
ret = pmPolicyMaker->registerPowerDriver(this,
|
|
powerStateArray,
|
|
kPowerStateCount);
|
|
return ret;
|
|
}
|
|
|
|
void AirportItlwm::setPowerStateOff()
|
|
{
|
|
XYLog("%s\n", __FUNCTION__);
|
|
pmPowerState = kPowerStateOff;
|
|
disableAdapter(bsdInterface);
|
|
pmPolicyMaker->acknowledgeSetPowerState();
|
|
}
|
|
|
|
void AirportItlwm::setPowerStateOn()
|
|
{
|
|
XYLog("%s\n", __FUNCTION__);
|
|
pmPowerState = kPowerStateOn;
|
|
pmPolicyMaker->acknowledgeSetPowerState();
|
|
}
|