// 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;
}