// didTerminate is called at the end of the termination process. It is a notification // that a provider has been terminated, sent after recursing up the stack, in leaf-to-root order. bool PsychtoolboxKernelDriverUserClient::didTerminate(IOService* provider, IOOptionBits options, bool* defer) { // IOLog("PsychtoolboxKernelDriverUserClient::didTerminate()\n"); // If all pending I/O has been terminated, close our provider. If I/O is still outstanding, set defer to true // and the user client will not have stop called on it. closeUserClient(); *defer = false; return super::didTerminate(provider, options, defer); }
bool USER_CLIENT_CLASS_NAME::didTerminate(IOService* provider, IOOptionBits options, bool* defer) { IOLog("%s[%p]::%s(%p, %d, %p)\n", getName(), this, __FUNCTION__, provider, options, defer); // If all pending I/O has been terminated, close our provider. If I/O is still outstanding, set defer to true // and the user client will not have stop called on it. closeUserClient(); *defer = false; return DSuper::didTerminate(provider, options, defer); }
// clientClose is called as a result of the user process calling IOServiceClose. IOReturn PsychtoolboxKernelDriverUserClient::clientClose(void) { // IOLog("PsychtoolboxKernelDriverUserClient::clientClose()\n"); // Defensive coding in case the user process called IOServiceClose // without calling closeUserClient first. (void) closeUserClient(); // Inform the user process that this user client is no longer available. This will also cause the // user client instance to be destroyed. // // terminate would return false if the user process still had this user client open. // This should never happen in our case because this code path is only reached if the user process // explicitly requests closing the connection to the user client. bool success = terminate(); if (!success) { IOLog("PsychtoolboxKernelDriverUserClient::clientClose(): terminate() failed.\n"); } // DON'T call super::clientClose, which just returns kIOReturnUnsupported. return kIOReturnSuccess; }