Closed lvs1974 closed 6 years ago
This has been implemented only for NON_RESIDENT = 1 and TARGET_ELCAPITAN:
IOService* BrcmPatchRAM::probe(IOService *provider, SInt32 *probeScore)
{
uint64_t start_time, end_time, nano_secs;
DebugLog("probe\n");
if (mCompletionLock)
{
AlwaysLog("probe is already run, exit.\n");
return NULL;
}
AlwaysLog("Version %s starting on OS X Darwin %d.%d.\n", OSKextGetCurrentVersionString(), version_major, version_minor);
// preference towards starting BrcmPatchRAM2.kext when BrcmPatchRAM.kext also exists
*probeScore = 2000;
clock_get_uptime(&start_time);
mCompletionLock = IOLockAlloc();
if (!mCompletionLock)
return NULL;
AlwaysLog("Provider name is %s, and his provider name is %s\n", provider->getName(), provider->getProvider()->getName());
IOService *rootProvider = provider->getProvider();
if (rootProvider)
{
OSIterator *iter = rootProvider->getClientIterator();
if (iter)
{
IOService *client;
while ((client = (IOService *) iter->getNextObject()))
{
uint64_t sessionID = 0;
OSNumber *session = OSDynamicCast(OSNumber, client->getProperty("sessionID"));
if (session != 0)
sessionID = session->unsigned64BitValue();
AlwaysLog("Client name is %s, sessionID=\"0x%llx\"\n", client->getName(), sessionID);
mDevice.setDevice(client);
if (!mDevice.getValidatedDevice())
{
AlwaysLog("Provider type is incorrect (not IOUSBDevice or IOUSBHostDevice)\n");
break;
}
// personality strings depend on version
initBrcmStrings();
OSString* displayName = OSDynamicCast(OSString, getProperty(kDisplayName));
if (displayName)
client->setProperty(kUSBProductString, displayName);
mVendorId = mDevice.getVendorID();
mProductId = mDevice.getProductID();
// get firmware here to pre-cache for eventual use on wakeup or now
if (OSString* firmwareKey = OSDynamicCast(OSString, getProperty(kFirmwareKey)))
{
if (BrcmFirmwareStore* firmwareStore = getFirmwareStore())
firmwareStore->getFirmware(mVendorId, mProductId, firmwareKey);
}
uploadFirmware();
publishPersonality();
clock_get_uptime(&end_time);
absolutetime_to_nanoseconds(end_time - start_time, &nano_secs);
uint64_t milli_secs = nano_secs / 1000000;
AlwaysLog("Processing time %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000);
// maybe residency is not required for 10.11?
mDevice.setDevice(NULL);
}
iter->release();
}
}
return NULL;
}
And it would be nice to free mCompletionLock:
void BrcmPatchRAM::free()
{
DebugLog("free\n");
if (mCompletionLock)
{
IOLockFree(mCompletionLock);
mCompletionLock = NULL;
}
}
FYI: From what I see, the PR does not contain the suggested code changes...
Note: mCompletionLock is freed in stop.
And I don't think the suggested code is doing what that author thinks it is doing. But it is executing the uploadFirmware/etc multiple times.
I have managed to fix one very strange issue: after a numerous cycles of sleep/wake my bluetooth stopped working, in log I discovered: (kernel) BrcmPatchRAM2: [13d3:3404]: Not responding - Delaying next read. (kernel) BrcmPatchRAM2: [13d3:3404]: device request failed ("0xe00002ed (UNDEFINED)" 0xe00002ed). (kernel) BrcmPatchRAM2: [13d3:3404]: Not responding - Delaying next read. (kernel) BrcmPatchRAM2: [13d3:3404]: device request failed ("0xe00002d8 (UNDEFINED)" 0xe00002d8). (kernel) BrcmPatchRAM2: [13d3:3404]: continuousRead - Failed to queue read (0xe00002d8)
I had a look to the IOReg and saw two devices with the same name: BCM20702A0, but they had different sessionID. My fix is quite simple (I believe you could improve it): get the root provider for current BCM20702A0 device, iterate over all client and try to perform a firmware upgrade for all of them.