I'm trying to do Apple's "Kernel Extension" Tutorial. I've created a project file, created the Info.plist, built it, used kextlibs to learn the dependencies, added them to the Info.plist, rebuilt, copied to /tmp, used kextutil to test it. Everything fine so far. When I try loading the kext, though, my start/stop/probe functions never seem to get called. My IOLog messages don't appear in /var/log/system.log.
In fact, system.log does not show anything. kernel.log does after I activated kext logging with sysctl -w debug.kextlog=0x0007780E. kernel.log says: "Kext ch.digorydoo.driver.XinputDevice successfully resolved dependencies." Then: "Flushing nonloaded kexts and other unused data." Maybe my class immediately gets flushed?
My class appears at the end of kextstat, but with 0 references. The same with ioclasscount. In ioreg, my class does not appear.
I've set IOProviderClass to IOResources, so it should always have a reference, right? I've properly set IOMatchCategory.
Any help?!!?! Thanks a lot!
EDIT: Here's my Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>ch.digorydoo.driver.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>KEXT</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>IOKitPersonalities</key>
<dict>
<key>Generic Xinput Gamepad</key>
<dict>
<key>CFBundleIdentifier</key>
<string>ch.digorydoo.driver.${PRODUCT_NAME:rfc1034identifier}</string>
<key>IOProviderClass</key>
<string>IOResources</string>
<key>IOMatchCategory</key>
<string>ch_digorydoo_driver_XinputDevice</string>
<key>IOClass</key>
<string>ch_digorydoo_driver_XinputDevice</string>
<key>IOKitDebug</key>
<integer>65535</integer>
</dict>
</dict>
<key>OSBundleLibraries</key>
<dict>
<key>com.apple.kpi.iokit</key>
<string>10.8</string>
<key>com.apple.kpi.libkern</key>
<string>10.8</string>
<key>com.apple.kpi.mach</key>
<string>10.8</string>
</dict>
</dict>
</plist>
Still no clue why my simple KEXT is not started. Here's the output from kextutil:
$ kextutil -t -n XinputDevice.kext
No kernel file specified; using running kernel for linking.
Notice: XinputDevice.kext has debug properties set.
XinputDevice.kext appears to be loadable (including linkage for on-disk libraries).
Note that when I load the KEXT, it says 'loadable NOT including linkage', but then all the same says it loaded it:
$ kextutil -v 4 XinputDevice.kext
Kext library architecture set to i386.
Kext library recording diagnostics for: validation authentication dependencies warnings.
Notice: XinputDevice.kext has debug properties set.
XinputDevice.kext appears to be loadable (not including linkage for on-disk libraries).
Loading XinputDevice.kext.
Reading load info for all kexts.
Reading loaded kext info from kernel.
Adding /private/tmp/XinputDevice.kext to mkext.
/private/tmp/XinputDevice.kext added 29260-byte noncompressed executable to mkext.
Created mkext for architecture i386 containing 1 kexts.
Loading XinputDevice.kext.
(kernel) Received request from user space to load kext ch.digorydoo.driver.XinputDevice.
(kernel) Recorded kext ch.digorydoo.driver.XinputDevice as a candidate for inclusion in prelinked kernel.
(kernel) Loading kext ch.digorydoo.driver.XinputDevice.
(kernel) Allocated link buffer for kext ch.digorydoo.driver.XinputDevice at 0x4d1e6000 (8192 bytes).
(kernel) Kext ch.digorydoo.driver.XinputDevice executable loaded; 2 pages at 0x4d1e6000 (load tag 114).
(kernel) Kext ch.digorydoo.driver.XinputDevice calling module start function. ####
(kernel) Kext ch.digorydoo.driver.XinputDevice registered class ch_digorydoo_driver_XinputDevice.
(kernel) Kext ch.digorydoo.driver.XinputDevice has IOService subclass ch_digorydoo_driver_XinputDevice; enabling autounload.
(kernel) Kext ch.digorydoo.driver.XinputDevice is now started.
(kernel) Kext ch.digorydoo.driver.XinputDevice sending 1 personality to the IOCatalogue and starting matching.
(kernel) Kext ch.digorydoo.driver.XinputDevice loaded.
Successfully loaded XinputDevice.kext.
XinputDevice.kext successfully loaded (or already loaded).
On the line above that I marked with a ####, it says the start function was called. But that's not true, since my start() calls IOLog, which should write a message in /var/log/system.log, which but it doesn't.
Here's what shows up in /var/log/kernel.log:
Jan 5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice, v1.0 registered and available for loading.
Jan 5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice resolving dependencies.
Jan 5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice added dependency com.apple.kpi.mach.
Jan 5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice added dependency com.apple.kpi.iokit.
Jan 5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice added dependency com.apple.kpi.libkern.
Jan 5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice successfully resolved dependencies.
Jan 5 15:20:00 karaboudjan3 kernel[0]: Flushing nonloaded kexts and other unused data.
In fact, the class is loaded, but no instance is created:
$ ioclasscount | grep digory
ch_digorydoo_driver_XinputDevice = 0
$ kextstat | grep digory
116 0 0x106f000 0x2000 0x1000 ch.digorydoo.driver.XinputDevice (1.0.0) <5 4 3>
The class does not show up in the I/O registry:
$ ioreg | grep Xinput
$ ioreg | grep digory
No instance means no call to init or start, hence no IOLog. If no one uses the class, it clearly does not show up in the registry of live objects.
My conclusion is that the tutorial must be wrong! The class is never instantiated even though its provider class is IOResources!
I tried replacing IOResources with IOUSBDevice. Since I'm not providing any idProduct or idVendor, any USB device should match. Unless I'm mistaken, the daemon listening to USB devices should instantiate my class and call probe() to see if this is the right driver for the device.
Unfortunately, I still didn't get any log messages in system.log!! Which daemon is responsible for USB devices? Maybe there's a driver that somehow "eats" the newly plugged device before my KEXT gets a chance? How can I track down which driver the daemon chooses?
Any hints?!?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With