I'm trying to write a very simple user client that - just for now - writes into the kernel log from user space. If the following code worked, it would write "Hello World" to the log.
I have verified that I've got the right IOService - com_soggywizards_Foo - with the call to IOObjectGetClass in the code below.
Always IOServiceOpen returns kIOReturnUnsupported. However when it is called, my user client then shows up in IORegistryExplorer. I can also see it in ioreg.
It appears as if IOServiceOpen is instantiating the user client but returning its result before that instantion is complete.
The call to IOServiceOpen is in the "doOpen" function:
int main(int argc, const char * argv[]) {
CFMutableDictionaryRef dict = NULL;
dict = IOServiceMatching( "com_soggywizards_Foo" );
kern_return_t result;
io_iterator_t it = NULL;
result = IOServiceGetMatchingServices( kIOMasterPortDefault,
(CFDictionaryRef)dict,
&it);
if ( result != KERN_SUCCESS ){
fprintf( stderr, "IOServiceGetMatchingServices failed 0x%x\n", result );
exit( 1 );
}
io_service_t service = IOIteratorNext( it );
if ( service == (io_service_t)NULL ){
fprintf( stderr, "IOIteratorNext cant find service\n " );
exit( 1 );
}
char name[ 256 ];
result = IOObjectGetClass( service, name );
cout << "service: " << name << endl; // prints "service: com_soggywizards_Foo"
io_connect_t connect;
result = doOpen( service, &connect );
if ( result != KERN_SUCCESS ) return 1;
result = logMessage( "Hello World\n", connect );
if ( result != KERN_SUCCESS ) return 1;
return 0;
}
kern_return_t doOpen( io_service_t service, io_connect_t *connect )
{
kern_return_t result = IOServiceOpen( service, mach_task_self(), 0, connect ); // returns 0xe00002c7
if ( result != KERN_SUCCESS ) fprintf( stderr, "IOServiceOpen failed: 0x%x\n", result );
else{
result = openUserClient( *connect );
if ( result != KERN_SUCCESS ) fprintf( stderr, "openUserClient failed: 0x%x\n", result );
}
return result;
}
the kernel log shows my user client's initWithTask being called, with super::initWithTask succeeding. Also my user client's start method is called.
I am unclear as to whether the user client needs to call registerService()
. However, ioreg says its registered even if I don't call it.
Does your driver class, or one of its superclasses other than
IOService
itself, override thenewUserClient()
method? If a superclass overrides it, and you want to add an extra user client type, you'll need to override it yourself as well. If you're already overriding it, you'll need to show us its code as that's likely where your problem lies.(Generally, it looks like your problem is kernel side, so if in doubt post that code.)
Regarding
registerService()
: You need to call this if you want yourIOService
object to be matched, and it is ready to accept clients that found by matching - i.e. found byIOServiceGetMatchingServices()
or similar functions in either user or kernel space, including an IOKit personality of a kext.