I have a few FTDI devices connected to my Mac. They all have the same description, PID, and VID. I want to be able to specify to FT_OpenEx() which one I want to open.
I can use the IO Kit APIs to get the bus location ID of the device I'm interested. The FT_OpenEX() API allows me to pass in a location instead of a description or serial number.
However, the FT APIs that return location IDs return values that look nothing like bus location IDs. One of the devices I have connected has a bus location ID of 0x1a127000, bus when I use the FT APIs to get the locations of all devices, it will say things like 0x1a051 and 0x1a052.
Is there any way to convert from IO Kit bus location ID and the FT location, or otherwise specify which device to use?
I recently had a similar problem: on some locations and devices I got 0 as location id. I wrote a request for assistance to FTDI and this is what I got:
We tested a USB 3.0 host PCI card found it not compatible with our
drivers for the following reason.
Existing host ports on a Windows machine are given a name in the
format: \device\usbfdo-# where # is a number.
The USB 3.0 card is known as a \device\device# where # is a number.
The USB 3.0 host port does not follow the standard naming convention
on a windows machine we do not attempt to open this port to send
device ID to when enumerating and trying to load drivers.
As we expect Microsoft to follow convention when they add support for
3.0, we expect the problem to go away from our point of view. As such we are still of the opinion the problem lies with the 3.0 host and not
our drivers.
Even if it was possible to make changes to support this host
controller it is highly probable that the next host device you try
(different manufacturer) will have another variant requiring a
different modification. This would not be a sustainable model and goes
against the PnP ethos of USB.
We believe this issue has been resolved in Windows 8. We are currently
working on the certification of our new windows 8 driver, I expect
this to be available by the end of February.
This is not very satisfying but at least it describes why it is not working. When I have time I will try to get the location id by using libusbX and then opening it with the FTDI API routines.
Not sure when that will be, though...
Veit
Since I already did this for linux once and have a working solution, I thought I'd try to figure it out for the mac as well.
I am not sure if I did this correctly but here's what I came up with:
Basically, you take the MacOSX location id right shift 16 bits, binary & with 0xff00 and add the device address.
That should be equal to the location ID you get from the ftdi driver.
Example:
In the "System Information" program I can find my USB device and see something like this:
Location ID: 0x14100000 / 21
That seems to be the "location id / device number".
Now plug it into that formula:
0x141000000>>16 = 0x1410
0x1410&0xff00 = 0x1400
0x1400|21 = 0x1415
So in decimal notation the location id is: 5141 which matches what FTDI returned. Note that 21 used above is 0x15 in hex.
I just figured this out 30 minutes ago so if there are problems with this implementation let me know. I need this to work reliably as well. I tried putting a hub between the mac and the device and the formula still applies.
The IOKit calls are:
kr = (*dev)->GetLocationID(dev, &locationid);
kr = (*dev)->GetDeviceAddress(dev, &address);
described at the apple developer reference website.
EDIT
since you have 5 digits in your FTDI location id, I would be interested in what your device device number is. Maybe my method doesn't hold up under your circumstances?
Related
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 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.
We are a small hardware manufacturer. Most of our products use USB for programming the controllers used.
The current situation is that programming the hardware (part of the assembly processor) is rather labour intensive.
Each time a new USB device gets plugged in Windows prompts for a driver install. This means that for each new product we have to go through a process of "no, don't go to internet" --> "yes, search automatically" --> "done". We even have to do this twice for each product.
I have been experimenting with the Windows preinstaller (DPInst), but this seems to only facilitate a succesful "yes, search automatically" part.
Is there a way to have the drivers installed fully automatically after plugging in the USB device?
Kind Regards,
Ronald
I take it your devices have a unique USB serial number, and hence each one is detected as a new device that hasn't been seen before.
If so, then the solution is this, from http://www.lvr.com/usbfaq.htm:
During device testing, we attach many
devices that are identical except for
the serial numbers. How can I prevent
Windows from asking to install a new
driver every time a device is
attached?
The method described below causes
Windows 2000 and XP to ignore a
device's serial number. It's
recommended for test environments
only.
This registry key controls whether
Windows uses or ignores device serial
numbers:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\UsbFlags]
It's possible to ignore all serial
numbers, though this approach is NOT
recommended. To ignore all serial
numbers, in the above key, change this
value to zero:
GlobalDisableSerNumGen = 1
To ignore the serial number for an
individual device, create an entry
under the above ...\UsbFlags key. The
name must start with "IgnoreHWSerNum"
followed by the vendor and product ID
of the device. A value of 1 = "disable
the serial number."
Example (Vendor ID = 0925h, Product ID
= 016Ah):
IgnoreHWSerNum0925016A= 1
An alternative hardware/firmware solution is to disable the device USB serial number during production (e.g. with a link, possibly one made by a test fixture). Without a USB serial number, Windows will assign a pseudo serial-number to the device, based on its position in the connection tree. That wouldn't be likely to change during a production run, so all devices would then be treated as identical and Windows wouldn't bother with the new driver stuff.
I had the same problem 5 years ago.
The main problem is that the installation of USB drivers after Plug&Play of the coresponding device works under the LocalSystem account. To have no security problems Microsoft allows silent installation of drivers only signed by Microsoft. Starting with Windows Server 2003 there are documented way (see http://www.microsoft.com/whdc/driver/install/authenticode.mspx).
If you have a managed corporate environment (you can prepare computers which will use your Plug&Play devices), then there are a workaround which solves the problem on Windows XP. I suggested it 5 years ago for one of my customer. It works perfect since about 5 years in environment with some of 10000 Windows XP computers.
The idea for the solution is very easy: your drivers (for example the CAT file) must be signed with the signature which
has both 1.3.6.1.5.5.7.3.3 ("Code Signing") and 1.3.6.1.4.1.311.10.3.6 ("Windows System Component Verification") OIDs as Enhanced key usage (EKU) extension
the certificate or it's parent certificate must be installed in the Machine's Root (Trusted Root Certification) or AuthRoot (Third-Party Root Certification Authorities) certificate store
If you do this on a Windows XP computer, the operating system will interpret your driver like Microsoft signed driver.
Morver you shoud insert in the registry the path to the source of the driver.
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!