My USB Function Driver Doesn't Load If Dongle Is Attached At Boot - macos

This is new just today. It's been working well for a while now.
When functioning normally, the driver will match on the USB device's
product and vendor IDs, then will load and operate.
It's a USB video adapter so under normal operation, one sees a blurred
image of the desktop until login, then you get a second screen that
works correctly with Display Preferences.
But just today, if the dongle is attached at boot the driver doesn't
load and the USB-attached monitor doesn't show an image.
If I unplug the dongle then plug it back in, it works.
If the dongle is not attached during boot, then plugged in after
reaching the desktop, it works.
If the dongle is attached during boot, and I later use kextutil to
load it, kextutil reports success but it doesn't load.
I speculate it is a problem with matching but don't understand what
could have gone wrong.
It's a signed driver that's now in /Library/Extensions; previously it was unsigned, in /System/Library/Extensions, with System Integrity Protection disabled.
There are two other drivers in the product that are not USB function drivers. They load just fine. All three drivers work together to create a virtual frame buffer then display it.

This could be caused by a bunch of different things. A few suggestions:
Have you verified that ::probe() and ::start() are not being called on your driver class? If they return NULL/false, that will cause behaviour as described.
What's the situation in the IORegistry when your driver has failed to load for a cold-plugged device? Does the nub you match have any client objects?
Have you ruled out a kext cache problem? (E.g. are there any errors when the OS regenerates the kext cache and prelinked kernel?)
Posting your Info.plist might also help - it's possible the problem lies there.

Related

Serial Mouse device crashes using virtual desktop

I have some old serial based USB touchscreen systems that would be expensive to replace with new hardware.
They are connected in the following manner:
Serial Mouse -> Serial to USB adapter -> Thin Client -> Virtual Machine
Everything works great with one issue. I'm experiencing a driver crash everything user either logs off, shutdown, or reboots. The current workaround has been to disable the serial mouse device before logging off which is a real pain. As long as the device is disabled, everything works great.
I did a lot of research on this issue by taking memory dumps of the crash virtual machines.
It seems like when the user logs off, the USB device is abruptly disconnected and then Windows tries to disable the device gracefully and waits until it is confirmed, thus hanging forever. In assembly it appears to call a .sys file that never returns back.
Is there anything that can be done with an issue like that? Can you change the device shutdown order? Or perhaps tell Windows to not ensure the plug and play device is shutdown? I doubt the vendor would be willing to change their driver.
I wrote a custom solution to this problem.
The application uses the ShutdownBlockReasonCreate API call to block Windows from shutting down. It then listens for reboots or logoffs using the WM_QUERYENDSESSION API call. When it gets this, it disabled the devices and then destroys the shutdown block created.
A real pain but it works

Replace Windows USB Class Driver with a custom driver?

I wonder if anyone can help at all, a bit of a specialist problem this.
I have an application that needs to read and analyse a number of USB devices (not simultaneously, they are each run in seperate tests and could in theory be run on different machines).
Each of the USB devices is based on the USB HID class, and are manufactured by different companies, none of these USB devices are designed to be run on PC, but are meant for a different platform, however for the purposes of testing the devices the client has requested that the test application is run from a PC.
Some of the devices will start up, be recognised by windows which will initialise and start them correctly using the generic HID class driver built into windows, the devices will then start sending correct data packets of the data to be tested.
Some of the devices will start up, be recognised by windows which will try to start them but fail to fully to initialise them leaving them in a half initialised state. This is fine, as I can use my beagle protocol analyser to capture the initialisation packets from the genuine platform and then use the LibUSBDotNet library to replicate the remaining packets in the initialisation sequence and get them to start sending the packets correctly.
The problem I have is with one particular device (though there are some more I haven't tested yet so it's quite possible one of those may also exhibit the same problem). The issue is the the Windows HID class driver recognises the device and trys to initialise and start it, this works after a fashion and the device starts sending data.
The problem is that the data being sent is different to that which is sent to the genuine platform (containing only a subset of the full data). It's as though windows has initialised the device into a different mode.
When I capture the initialisation packets from both the PC and the genuine platform using my USB protocol analyser I see that Windows is sending some slightly different initialisation packets. Using LibUSBDotNet to resend the correct packets once Windows has already started the device seems to have no effect.
My problem is that I need to stop windows from trying to initialise the device using the standard HID class driver, I've tried removing the driver in Device Manager but it still initialises it (and the driver is magically reassigned in device manager). I've done some investigation and there are possible alternatives:
Create a specific driver which windows will assign to the particular VID/PID of the device but that does nothing, then I can use LibUSBDotNet to send the correct initialisation sequence to the device from within my own code.
Use something like WinUSB to create a proper driver for the device (or possibly to create a "dead" driver like 1.
Will a driver with a specific VID/PID defined be used by windows in preference to it's inbuilt USB HID class driver? If not then I would be wasting my time going down this route?
Note, my mac initialises the problem device correctly, and I've asked the question of the client whether the application can be developed for Mac and their answer was frustrating Windows only.
I've no experience in writing proper Windows drivers, though I have experience in talking to USB at a relatively low level (so that part doesn't worry too much). Can anyone suggest a good course of action (before I potentially waste weeks investigating how to write drivers for the PC only to find my selected course of action can't deliver what I required).
Any help or suggest much appreciated.
Thanks,
Rich
Added after trying suggestions below:
I tried using the LibUsbDotNet inf wizard to create the necessary files and install them and this appeared to work - certainly the device was now appearing in Device Manager as a libusb-win32 device - not HID device and the associated driver was libusb driver. Even after doing this the device still seems to become initialised and start sending the wrong type of data packets although now those packets are no longer handled by the class driver and are just lost.
I also came across Zadig which has a similar inf creation wizard for WinUSB and this had exactly the same result.
A colleague has suggested that it might not be windows itself that is switching the device into this mode, rather the device identifying that it is connected to a windows machine and switching itself into this mode. I suspect this is the case, in which case I am stuck - time to have another conversation with the client.
Many thanks for the help.
You're using libusb-win32 as a filter driver; that is, the HidUsb device driver is assigned and loaded for your device, but then the libusb-win32 driver is loaded on top and gives you unobstructed access to the hardware.
If you don't want a HidUsb (or any other class driver) to perform any communication "on your behalf", simply associate libusb-win32 as a device driver with your hardware. For this, you'd have to create an .INF file associating it with the VID/PID/Revision of each USB device. If I recall correctly, libusb-win32 even comes with a utility to generate such .INF files.
If you install this .INF file e.g. with PnpUtil.exe (available on Vista or higher), you might still run into issues where, although you're a better match than the generic HID driver, the HID driver is still selected.
The generic HID driver matches devices by their Compatible IDs (i.e. by a USB interface class) while you'd be matching by Hardware IDs (which have higher priority). However, Windows might give priority to other aspects, such as your driver being unsigned. Read: How Windows Selects Drivers
Luckily, even in that scenario, signing drivers with a self-generated certificate (use CertUtil.exe, MakeCat.exe and SignTool.exe) is not too difficult.

Codeless kext loading problem

I have created a codeless kext so that one of my USB devices does not get kidnapped by the AppleUSBUHCI driver. When I plug one in, it should be loading a different driver. It happens with both an FTDI and CSR device.
I put together my kext, and the info.plist looks a lot like the example here: http://www.projectosx.com/forum/index.php?showtopic=798 just with different VID/PID.
I ran kextutil with -entZ and the only warning was that I had a different CFBundleId for my personality. I followed the instructions here, Reading and writing to USB (HID) interrupt endpoints on Mac, to get it loaded.
When I loaded the kext, it said it loaded successfully, but I cannot see it with kextstat, and when I plug in my device it still gets hijacked. When I try to do a kextunload, it says the kext was not loaded.
Any help would be appreciated.
From the Apple lists, I learned that codeless kexts will not show up with kextstat unless they link to an existing driver. My personality that linked to the IOKit bundle would only show after load if it had stub code.
For my device, I found an existing driver for similar devices, and first injected a personality into that driver. I was able to verify it loaded when I plugged in my device, and I could open my device. I restored that driver to the original state. Then I created a codeless kext with the personality I had injected in to the existing driver. That driver then got loaded when I plugged in my device and I was then able to communicate with my device.
The solution to my original problem was the CFBundleIdentifier for my original codeless kext and the bcdDevice. From http://lists.apple.com/archives/usb/2009/Aug/msg00050.html, I got hints about different types of codeless kexts and realized I needed to use the CFBundleIdentifier for the existing driver.

Make driver load automatically when USB device is inserted

I'm using a Limited User account under Windows XP, and I'm having a bit of trouble getting my Adaptoid (the most coveted N64 controller -> USB adapter, because of it's support for sending raw N64 controller commands + the fact that it's been discontinued) to work smoothly: as installed, the included software requires Administrator privileges to load the driver.
Presumably, it is possible to arrange for the driver to be loaded automatically when the Adaptoid is inserted by adding some stuff to the INF file for the driver (wishna1.inf):
the question is, what stuff?
(It would also suit me just as well if the driver could be automatically loaded when anything attempted to open \Device\Wish_NA1, or even to have it automatically loaded at every boot, really, but doing it on insertion seems like the right way.)
Note: I do have access to an administrative account, it's just that I prefer not to have to use it day-to-day.
First of all, let's clarify that a USB device has a Plug & Play driver on Windows 2000 and higher, so services start modes are irrelevant. The driver will have an entry as a "service" in the registry, but its start mode is irrelevant here.
Let's split the problem into two parts:
Installing driver for the device: This requires administrative privileges. This happens when you insert a USB device into a port for the first time. Windows goes over your .INF files to find one that matches your hardware. If the driver is WHQL-certified, it'll load automatically. Otherwise, you'd see the dreaded Add New Hardware wizard. If you're running as admin, a few clicks on Next should be enough to install it. Otherwise, better have that Administrator password ready.
Loading the driver for the device: Once the device is installed, the driver will be loaded each time this device is inserted into this USB port without requiring any additional user intervention. Ever noticed how a USB printer, camera or disk drive load much faster the second time you plug it in? That's because that's just loading, without installing.
From looking at the .INF, it looks valid. Also, it's not WHQL-certified, so you'd have to install it manually.
I'm assuming when you insert the Adaptoid, you get an Add New Hardware wizard. If you point it manually to the installation directory, does the Adaptoid install and function? Does it appear in the Device Manager?
P.S. USB devices which have a serial number are an exception. They're installed once for all USB ports. Those devices are rather uncommon, though.

IWDFDevice::CreateWdfFile returns ERROR_INVALID_FUNCTION?

I am writing a UMDF sensor driver for a device that connects to the system via Bluetooth and is accessible as an HID input device. I saw the "Sensor Development Kit" sample driver and noticed that it works with the Freescale hardware via HID also though it connects to the system via USB. Is there any difference in the way the UMDF driver communicates with the device in case it connects to the system via Bluetooth? For some reason, I find that the call to CreateWdfFile returns ERROR_INVALID_FUNCTION even when I have the device paired with the system. I am able to access the device directly via HID just fine.
In the INF for the driver I have specified the hardware ID like so - HID\VID_1234&PID_5678 (haven't used the actual IDs here). Is this sufficient for the UMDF framework to determine which driver it should use further down the stack? Or is there something else that one needs to do?
I managed to resolve this one myself. Turns out I wasn't using the correct hardware ID. On a whim I looked up what hardware IDs the bluetooth device had been registered with under HKLM\SYSTEM\CurrentControlSet\Enum\HID and used another ID that had been given there and voila! - IWDFDevice::CreateWdfFile worked! :) And sure enough, this is described quite clearly on MSDN here. So, all's good!

Resources