Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 127 additions & 17 deletions RealtekCardReader/RealtekUSBCardReaderController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1749,25 +1749,97 @@ void RealtekUSBCardReaderController::prepareToSleep()
void RealtekUSBCardReaderController::prepareToWakeUp()
{
pinfo("Prepare to wake up...");


// Reset the card event lock
this->cardEventLock = 0;
this->isCardPresentBefore = false;

// Clear any stale transfer state
this->clearError();

// The builtin USB card reader disconnects from the system when the computer sleeps
// and reconnects when the computer wakes up on some platforms.
// (The kernel will stop the driver when the computer wakes up and
// starts a new instance of this driver when the card reader is up.)
// If the driver fails to reset the hardware, then this is the sign of such a behavior.
if (this->resetHardware() == kIOReturnSuccess)
IOReturn retVal = this->resetHardware();

if (retVal == kIOReturnSuccess)
{
// Attach the card if present
super::prepareToWakeUp();

this->resumePollingThread();

pinfo("The hardware is ready.");

retVal = this->initHardware();

if (retVal == kIOReturnSuccess)
{
super::prepareToWakeUp();
this->resumePollingThread();
}
}
else
}

//
// MARK: - Termination Handling (NEW)
//

///
/// Called before termination begins
///
bool RealtekUSBCardReaderController::willTerminate(IOService* provider, IOOptionBits options)
{

// Stop all activity immediately
this->pausePollingThread();

// Abort any pending transfers
if (this->inputPipe != nullptr)
{
this->inputPipe->abort();
}

if (this->outputPipe != nullptr)
{
this->outputPipe->abort();
}

// Close all connections to clear busy state
if (this->interface != nullptr && this->interface->isOpen(this))
{
this->interface->close(this);
}

if (this->device != nullptr && this->device->isOpen(this))
{
this->device->close(this);
}

return super::willTerminate(provider, options);
}

///
/// Called after termination is complete
///
bool RealtekUSBCardReaderController::didTerminate(IOService* provider, IOOptionBits options, bool* defer)
{
// Make sure everything is cleaned up
if (this->interface != nullptr && this->interface->isOpen(this))
{
this->interface->close(this);
}

if (this->device != nullptr && this->device->isOpen(this))
{
perr("Failed to reset the hardware when the driver wakes up.");
this->device->close(this);
}

return super::didTerminate(provider, options, defer);
}

///
/// Handle termination
///
bool RealtekUSBCardReaderController::terminate(IOOptionBits options)
{
// Stop polling immediately
this->pausePollingThread();

return super::terminate(options);
}

//
Expand Down Expand Up @@ -2027,7 +2099,7 @@ void RealtekUSBCardReaderController::setDeviceProperties()
}

//
// MARK: - Polling Device Status
// MARK: - Polling Device Status (FIXED)
//

///
Expand Down Expand Up @@ -2057,6 +2129,17 @@ void RealtekUSBCardReaderController::pausePollingThread()
void RealtekUSBCardReaderController::resumePollingThread()
{
// For consistency, let's protect ourselves even though it is not needed

if (this->timer == nullptr || this->commandGate == nullptr)
{
return;
}

if (this->isInactive())
{
return;
}

auto action = [&]() -> IOReturn
{
this->timer->enable();
Expand Down Expand Up @@ -2394,9 +2477,24 @@ void RealtekUSBCardReaderController::tearDownPollingTimer()
if (this->timer != nullptr)
{
this->pausePollingThread();

this->workLoop->removeEventSource(this->timer);


if (this->commandGate != nullptr)
{
auto action = [&]() -> IOReturn
{
this->timer->cancelTimeout();
this->timer->disable();
return kIOReturnSuccess;
};

IOCommandGateRunAction(this->commandGate, action);
}

if (this->workLoop != nullptr)
{
this->workLoop->removeEventSource(this->timer);
}

this->timer->release();

this->timer = nullptr;
Expand Down Expand Up @@ -2607,3 +2705,15 @@ void RealtekUSBCardReaderController::stop(IOService* provider)

super::stop(provider);
}

void RealtekUSBCardReaderController::free()
{
// Final cleanup
OSSafeReleaseNULL(this->timer);
OSSafeReleaseNULL(this->inputPipe);
OSSafeReleaseNULL(this->outputPipe);
OSSafeReleaseNULL(this->interface);
OSSafeReleaseNULL(this->device);

super::free();
}
14 changes: 14 additions & 0 deletions RealtekCardReader/RealtekUSBCardReaderController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,20 @@ class RealtekUSBCardReaderController: public RealtekCardReaderController
/// @param provider An instance of USB host device that represents the card reader
///
void stop(IOService* provider) override;

///
/// Override free functions to make sure objects are released when system sleep.
///
void free() override;

/// Override functions to make sure objects are released when system sleep.
bool willTerminate(IOService* provider, IOOptionBits options) override;

/// Override functions to make sure objects are released when system sleep.
bool didTerminate(IOService* provider, IOOptionBits options, bool* defer) override;

/// Override functions to make sure objects are released when system sleep.
bool terminate(IOOptionBits options = 0) override;
};

#endif /* RealtekUSBCardReaderController_hpp */