Currently I study the Microsoft Documentation about drivers.
The are plenty of examples in the documentaion but there is something that is not very clear. When you develope a driver for a piece of hardware you must set an entry point and and a callback for when the device is pluged in, but you dont have to specify an identifier for your device.
How does Windows know that this specific driver is for my hardware?
Does the INF files that are generated with the .sys file contain that information?
Related
I've seen two ways to install Windows drivers.
a. Using both SYS file and INF file. (such as NDIS driver)
b. Only use SYS file, the driver will be loaded by a service. (such as drivers in
C:\Windows\System32\drivers)
So, my question is:
1. What kind of drivers or situations require INF a file?
2. What is the root cause of this difference?
There are different kinds of drivers on Windows. Each type of driver has its own story for how the driver is installed. Here are a few common types of drivers.
PNP device driver. A PNP device driver operates a device in the device tree. PNP drivers are loaded by PNP when the device is enumerated by its parent bus. In order for PNP to know which type of device your driver supports (and a bunch of other stuff), you need a PNP-style INF that describes your driver.
SCM-managed driver (sometimes called "legacy driver"). SCM loads these drivers based on the same rules it uses to start NT services. SCM does not require any INF. You can register a new driver with SCM by simply running sc.exe create my_cool_driver type=kernel binPath=c:\my\driver.sys start=auto or calling the CreateService API. But if you already have an INF for other reasons, you can use any style of INF to do the same via the AddService directive.
NDIS lightweight filter (LWF) driver. LWFs are not loaded by NDIS; NDIS doesn't care how they're loaded. Most LWFs choose to be loaded by SCM, since that's easy to control. An NetCfg-style INF is still required, though, since NDIS needs to know what types of network adapters to attach the filter to (Ethernet vs WLAN, for example).
Export driver. An export driver is loaded by the memory manager when Mm is trying to load some other driver that imports functions from it. An export driver is just a kernel equivalent of a DLL — it just provides APIs to other drivers. Export drivers don't need an INF; they just need to be put into the right directory on disk. If you already have an INF for other reasons, you can use the CopyFiles directive to do this.
WinUSB driver. WinUSB is a built-in driver that delegates most of the responsibilities of managing a USB device to usermode APIs, so any application can easily do simple things with the device. This means pretty much any application can be the driver for the device. If the USB device puts certain data in its hardware descriptor, Windows will know to automatically set up WinUSB, so no INF is required. But if the hardware does not advertise that it needs WinUSB, then you'll need a WinUSB-style INF to tell Windows to set up WinUSB for you. Beyond that, you don't need an INF to call WinUSB APIs from your application.
If you're just experimenting and want to call a few kernel APIs for fun, you can choose any type of driver. Most people find that an SCM-managed driver is the easiest, since you don't need any INF and you get full control over when the driver starts and stops. But in any other situation, the choice of driver type is largely dictated by the problem you're trying to solve. For example, if you're writing a driver for a PCI GPU, you must use a PNP driver, and therefore must have a PCI-style INF.
I am writing the firmware for a USB HID device. When it is connected to a Windows PC (running Windows 8.1, if that makes any difference) it gets listed in Device Manager, under "Human Interface Devices", as "HID-compliant vendor-defined device". For obvious reasons it would be preferable for a nicer description to be shown.
I'd have guessed that the description would be taken from the USB string descriptor table, perhaps from the entry specified in the device descriptor as containing the product name. This doesn't appear to happen. Perhaps there is an error in my descriptors, but when I connect a USB analyser during enumeration it correctly identifies the manufacturer name, product name, and serial number string.
A little googling suggests that the Device Manager's descriptions can be controlled from a driver's .inf file, but this device doesn't have its own drivers.
Am I out of luck, or is there a way for an HID device to determine how it is described by the Device Manager? If there is, what is it?
(Related prior SO question: Rename a USB HID device under Windows. An answer to that question says that you need to write a Windows device driver to do this, but comments on the answer indicate that this shouldn't apply to HID devices, and the answerer concedes this. Unfortunately no further suggestions are to be found there. That question may actually be trying to ask essentially the same thing as I am, but if so it's ill-titled; I am not trying to rename anything.)
I have developed a USB device that communicates with linux over a simple but proprietary interface and some custom Linux drivers. My goal is to port this to Windows without writing windows drivers. What I would like to do is find an open source or inbuilt class driver for windows that would look like a COM port in Windows. Then I would tailor the embedded software to match what ever protocol and descriptors the virtual COM port expects to see.
The idea would be that I could plug my device in to a Windows machine and a relatively high speed COM port would appear with out me having to develop Windows drivers for it.
I have been looking at the USB CDC (Communications Device Class) documentation and it looks promising, but I don't know which sub interface would be best to use so that it would show up as a COM port.
Has anyone here done any work like this before or could provide some insight?
Specifically:
Are there virtual COM drivers "built in" to windows or would I need a 3rd party driver.
Which CDC sub class should I use for simple RS232 emulation (No need for modem AT commands, etc)
Is there a better option to do what I am trying to do.
Thanks
There is a USB-to-serial driver built in to Windows that will do what you want. It is called usbser.sys:
http://support.microsoft.com/kb/837637
You will have to write an INF file and distribute that to your users, but that will not be too hard because it is only a few kilobytes of text and you can find examples online.
I'm not aware of any great documentation for this driver by Microsoft, so my advice would be to find some other device that uses it, such as Pololu Wixel, and copy what they did.
Here are the device descriptors we used and the special control tranfers we had to implement:
https://github.com/pololu/wixel-sdk/blob/master/libraries/src/usb_cdc_acm/usb_cdc_acm.c
You can see our INF file, wixel_serial.inf, by downloading the software and looking in the drivers folder:
http://www.pololu.com/docs/0J46/3.a
(There are other files in there that are not necessary for you.)
You can also look at the Arduino Uno because they use the same driver.
Whatever you do, please don't use our USB Vendor ID in your product! You need to get your own.
Update: In Windows 10, you don't need an INF file anymore because of the new usbser.inf driver that comes with Windows.
If you are using a UART you can easily interface it to a FTDI USB chip like http://www.ftdichip.com/Products/ICs/FT232R.htm or a Prolific like http://www.prolific.com.tw/eng/products.asp?id=59
For development, prototype and testing I have half dozen of these laying around http://www.pololu.com/catalog/product/391
I connect it directly to the UART pins on AVR and 8051 micros.
This may not be considered to be directly programming related but I am at a loss to know where else to ask. I have tried looking at a variety of websites but so far Google has not been my friend.
I am having trouble finding out whether I need to write my own device driver for the various windows/linux/mac platforms that the device I am developing may be connected to, or whether the functionality is provided by the standard drivers.
My device is a USB CDC (communications device) that appears as a COM: port. It also includes a battery charger that will, once the device has been enumerated require the full 5 unit load (500mA) supply current that can be drawn from the USB connector. My problem is that if the USB driver in the host decides that it cannot deliver the full supply current then it should fail to enumerate the device.
If, as a fallback, I provide a second configuration set that only allows the device to draw 1 unit load from the interface connector will the standard drivers enumerate the device using this configuration.
You need to write a .inf file for Windows that ties up your device VID and PID with the system usbser.sys. Mine looks like this (Replace YourCompany as necessary, put in your VID and PID (in hex), and change the DriverVer line to whatever date and version you want):
; -----------------------------------------------------------------------------
; XP/2000 USB Comms Port Setup
; -----------------------------------------------------------------------------
[Version]
DriverVer=12/03/2008,1.0.0000.0000
Signature="$Windows NT$"
Class=Ports
ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318}
Provider=%YourCompany%
[DestinationDirs]
DefaultDestDir=10,system32\drivers
DriverCopyFiles=12
[ControlFlags]
ExcludeFromSelect = *
[Manufacturer]
%YourCOmpany%=YourCompanySerialPort
[YourCompanySerialPort]
%YourCompanyUSBSerialPort%=YOURCOMPANYUSB,USB\VID_1234&PID_ABCD
;
; Win 2000/XP
;
[YOURCOMPANYUSB]
Include=mdmcpq.inf
CopyFiles=FakeModemCopyFileSection
[YOURCOMPANYUSB.HW]
AddReg=YOURCOMPANYUSBAddReg.HW
[YOURCOMPANYUSBAddReg.HW]
HKR,,DevLoader,0,*ntkern
HKR,,NTMPDriver,,"usbser.sys"
[YOURCOMPANYUSB.Services]
AddService=usbser, 0x00000002, FuncDrv_Service_Inst
[FuncDrv_Service_Inst]
DisplayName=%USBFilterString%
ServiceType= 1
StartType = 3
ErrorControl = 0
ServiceBinary = %12%\usbser.sys
[Strings]
YourCompany="YourCompany"
YourCompanySerialPort="Your Company USB Serial Port"
USBFilterString = "USB Serial Service"
Note this works with 32 bit OSs only. It also works with Vista although the file header doesn't say so!
Be aware that some versions of usbser.sys have significant problems, including bluescreening, for example when transferring packets that are exact multiples of 64 bytes. If you're using XP SP2 or previous then install hotfix KB943198. XP SP3 and Vista are fine.
For the Mac you simply need to report your device class correctly and the driver scan picks up the correct drivers. (Windows ignores the device class which is why you need to supply the .inf file).
EDIT: Sorry, I should have been clearer. This will not fail to enumerate if it can't draw the full load - I'm not sure that's possible.
You are correct on the driver question. When the device is plugged in and goes through the enumeration process it is required to stay < 100mA. The host will interrogate and determine the configuration(s). If there are more than one which support different power levels, then the driver will need to decide to select the appropriate configuration. If there is only high-power and it is not available, then it will not enumerate the device. In general, the standard driver doing CDC wouldn't be aware of the different device level configurations that would possible and so would require some degree of customization to handle them.
I am not sure about power question but ther is pleanty CDC drivers (or I think there is) so you could use one. For the power question, the solution with many configuration is probably good one, I have never encountered this in work (I have USB analyzer) but at home sometimes when I have 3 or more different devices that requires power from USB I got failed enumeration. I supose this is operating system choice if it can't supply power to new device it cut's it off (sensible choice as it can't power it). This is my gues rather checking USB standart.
If your device reports a device ID that the host OS already supports,
then they won't need a driver.
You may need to impersonate an existing USB uart. Data sheets are readily available.
(But I figure you already knew that.)
I'm not sure that the host OS will honour your multi-configuration idea.
But give it a punt so we all know!
If your device is connecting as USB CDC-ACM device to the windows desktop host, the windows desktop already provides the driver usbser.sys. But there are some some issues in windows Vista. You just need the inf to install the usbser.sys on desktop. For WinCE you do not have the driver and for you need to write or get one from any third party vendor. Here is one
http://www.em.avant-garde-lab.com/Products.html
If your device specifies itself as self powered in its device descriptor then the host would rely on the devices self power capability. You can check at usb.org for details.
Thanks.
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!