Markus Steinmann
Markus Steinmann

Reputation: 71

kext hid under 10.7 unload failed but 10.6 works flawless

I'm working on a virtual USB bus driver for MacOSX (Windows already running) connected via network with a linux box. It works fine under 10.6 and 10.7 with a mass storage device and HID devices like mice or keyboards.

But removing devices (unplugging) or more simple unload the kext fails for HID devices under 10.7(.5) because of one remaining instance (retain count does not go down to zero after detach). My 10.6 and 10.7 test environments are identically MacBooksPro 8.2 i7.

Sometimes after a while (5-50minutes) the kext becomes free without an action from my side. It seems not to depend an changing power mode.

Yes, I have USBFamily logging lib and a lot of output, but between working (kextunload ok) and not working run I find no difference in the loggings, even with logging level 7.

Because of mass storage devices seem to work well, I guess the problem is inside die HID driver stack especially under 10.7?

Are there any known differences to remove an USB HID device driver stack between 10.6 and 10.7?

My kext is a (virtual) ControllerV3 derivated class establishing/creating an USBDevice for any real plugged (at the remote linux box) USB device. Using XCode 4.4.1.

Thanks in advance for any idea or hint, regards Markus

PS: Looks a little bit odd to me that under 10.7 so many HID objects are on top of the driver stack. After kextunload (with failure "..VirDevice has 1 instance") they seem still alive. But this in 100% the same a local plugged and unplugged Logitech mouse.

From me are only the lowest both objects MsVirBus (virtual USB bus, derivated from IOUSBControllerV3 ) and the Mouse@xaffe003f with is an IOUSBDevice derivated object.

Driver Stack after kextunload

Upvotes: 3

Views: 455

Answers (1)

pmdj
pmdj

Reputation: 23448

I don't have deep experience with the HID stack, but I can give you some general IOKit/kext advice on how to track down the source of this kind of problem.

kextunload calls terminate() on all your objects in the I/O registry. This means there are two cases why you might end up unable to unload the kext:

  1. terminate() fails or fails to remove all child objects

  2. The remaining live objects are all not in the I/O registry

Check with the ioreg command whether any of your objects remain in the I/O registry. Also check what clients they have, as those will typically prevent removal.

If the registry is clear of your objects, you've most likely got a retain/release mismatch. I gave some suggestions on tracking these down in this answer so I won't repeat that here. It also doesn't seem likely as your kext eventually does unload and works on 10.6.

If you have objects left in the I/O registry, you'll need to track down why those are still there. If you aren't already overriding terminate() in your classes, add dummy overrides which just forward the call to the base class implementation. But wrap that forwarding call with logging output, and output whether the call succeeds. If you're already overriding terminate, add similar logging. You may also want to add similar logging for didTerminate(), as termination can be asynchronous.

You should be passing terminate() down the device tree to your clients when a USB device is unplugged. I'd check in the equivalent part of the EHCI controller code to see whether any special arguments etc. are required for this.

Upvotes: 2

Related Questions