|
Many places suggest System.Runtime.InteropServices.Marshal.SystemDefaultCharSize (1 on 32bit, 2 on 64bit). How would you get that to round up to 8 on 64 bit though? You could do things to round it manually but if you are doing that, it is just as bad as what I am currently using:
.cbSize = IntPtr.Size == 8 ? 8 : 5;
These places (such as pinvoke.net) have never actually bothered testing on 64 bit, though, and it just ends up setting it to 4+2=6. They just assume it works because on 32 bit, 4+1=5.
Is there anything anywhere that can define the packing size that SetupApi is using on the particular system at runtime?
|
|
|
|
|
On my system, Windows XP Pro 32-bit, Marshal.SystemDefaultCharSize returns 2 and not 1. That's why I decided to use the IntPtr.SizeOf() instead. It will have a different size on either platform, 4 for 32-bit, and 8 for 64-bit.
As far as getting the structure sizes to 5 and 8, it should happen automatically when you compile for the 64-bit OS because of structure alignment.
I'll install Windows Server 2003 64-bit on one of my computers down stairs and give it a try and see what I come up with. I'll run 2 scenarios: 1 - app compiled 32-bit running on 64-bit, then I will try app compiled 64-bit running on 64-bit and what turns up.
I probably won't get to it till Monday though. I'll be gone all day tomorrow.
|
|
|
|
|
Yes, I didn't really believe that the 64 bit version would be any more Unicode than the 32 bit version but many places suggest it without having tried it. On both 32 and 64bit, and on both Marshal.SystemDefaultCharSize = 1 and Marshal.SystemDefaultCharSize = 2, the SetupDiGetDeviceInterfaceDetail[^] function seems to always use non-Unicode ( _A ?) anyway.
I can see how it would be 5 on 32bit and 8 on 64bit, assuming that both use 8 bit characters but 64bit rounds the 5 up to 8, but the only way it is done automatically is if you manually set the packing on the struct. Pack=1 gives 5, Pack=8 gives 8. However, I can't see how to get 32bit to pack with 1 and 64bit to pack with 8 at runtime and anything to find this value at compile time will not work (may as well compile one version with the constant value 5 and one with the constant value 8 and distribute them separately, which is not what .net is about). It's really something to do with what SetupApi is using. Pack=0 (default platform packing) seems to be 8 for both 32 and 64bit regardless of what SetupApi is using.
Unless there is some way of pulling the packing size that SetupApi is using on the machine at runtime, so that it can be used to round up, there is no way of doing this better than the small conditional that I gave in my previous message. Even with 4+IntPtr.Size/2 (which I don't think would work anyway, this would be 6 on 32bit and 8 on 64bit but on every 32 bit machine I have tried (XP, 2003 and Vista), 5 is required and on every 64 bit machine I have tried (XP, 2003 and Vista), 8 is required), you still need to know whether it should be rounding up to 8, for example.
I think ideally it would just be something like "Round 5 (or maybe 6) up to GetSetupApiPackSizeFromDll()" to work on all current and future systems at runtime.
modified on Sunday, July 27, 2008 4:31 AM
|
|
|
|
|
The use of a function to return the pack size is probably the most reasonable solution. You could probably use the version number and/or size of the SetupAPI dll to determine which structure size should be used. Which ever way is used will most likely break in the future. But hey, it's Microsoft...
On another note, if anyone is updating this library, it would be nice to have a couple extra features.
1. Maintain a list of connected devices in the HIDDevice class. Users of my Data Terminal can have more than one connected at a time.
2. Be able to turn ON and OFF asyn'c reads from the usb port. Sometimes I need to send a command to the terminal which will return information immediately. So it would be nice to have a Write/Read command.
With those two features added, I think this library would be complete.
|
|
|
|
|
I've been working on this problem for a different application.
I found that on Vista 32-bit, the cbSize for SP_DEVICE_INTERFACE_DETAIL_DATA is 6, not 5. This seems to do with the SystemDefaultCharSize being 2 in Vista (Unicode).
So, I've been testing the following code as a solution for XP x86, Vista x86, and Vista x64:
didd.cbSize = 4 + Marshal.SystemDefaultCharSize;
if (IntPtr.Size == 8) didd.cbSize += 2;
|
|
|
|
|
As I said, it must always be 5 on 32bit and 8 on 64bit, regardless of whether the OS is unicode by default. This is to do with the packing size on 32 bit (Pack=1) and on 64bit (Pack=8) for SetupApi. There's no better way of setting this than just using a conditional such as
didd.cbSize = IntPtr.Size == 8 ? 8 : 5;
If you can think of a way that can tell the packing size that SetupApi wants (and don't bother with the Pack=0 automatic packing), that would be more flexible for the future (128bit?) but unless you can get that, there is nothing you can do that will be better than a little conditional.
What you really want to do is set it to 5 and then round it up to a multiple of the packing size (1 on 32bit, 8 on 64bit). 5 rounded up to a multiple 8 will always be 8 though, so you may as well just put it right there in the code.
Using the default character size is not reliable. What you have used there will be 4+1=5 on XP32 (works) and 4+2+2=8 on Vista 64 (works) but 4+2=6 on Vista 32 (doesn't work).
|
|
|
|
|
|
Maybe you should read the rest of this thread. I made that post while I started this thread (answering my own question because nobody else would) and since then it has been posted back 2 or 3 times by other people in this same thread.
Consider using libhidnet on sourceforge, which has support for Windows 32bit, Windows 64bit and Unix/Linux/Mac
|
|
|
|
|
Hi,
Yeah, sorry about that. I didn't see the other posts - either I'm not used to CP like you or something went wrong... no idea.
Anyway, I saw you'd mentioned one bug, but that post covered another. Not to worry anyway, to date this project was the best I'd found.
Thank you for this, and for pointing me to HID.net, although I'll probably stick with this library.
|
|
|
|
|
Hello guys,
I have tried recently to run the program, but as i debugged it, it seems it can't find my usb flash drive. The "while" statement :
while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface))
{....}
in
public static HIDDevice FindDevice(int nVid, int nPid, Type oType)
doesn't reach my usb's vendor_id and product_id
Thanks for your time!
|
|
|
|
|
Hi eythimis,
Because a USB Flash Drive doesn't belong to the HID device class you can't find him right now. In most cases a Flas Drive is a (bulk) USB Mass storage Device. You can change the GUID ID (Search for the right GUID on the internet) in the program code to find the device. But Interfacing a bulk device does need other code, so anything but recognising shall need some additional coding.
Greetings wimar
|
|
|
|
|
I'm having a similar issue but using a Magtek HID device... i have 4 HID devices installed on this machine - but when i hit while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface))
...it evaluates the first item and then falls out of the loop without evaluating any other items. I'm going to dig into the windows API - but thought you might have a quicker solution.
|
|
|
|
|
Hi there, I need to get Specified Device to return the Product Name and vendor Name, but there's a problem when I try to Find the Specified Device :
This is the code I put after Device Arrived :
private void usb_OnDeviceArrived(object sender, EventArgs e)
{
this.lb_message.Items.Add("Found a Device");
HIDDevice hid1 = SpecifiedDevice.FindSpecifiedDevice(int.Parse("4D8", System.Globalization.NumberStyles.HexNumber), int.Parse("FF9D", System.Globalization.NumberStyles.HexNumber));
}
and it raised error :
Additional information: Msg:UsbLibrary.HIDDeviceException: Msg:Failed to get the detailed data from the hid. WinEr:00000000
at UsbLibrary.HIDDevice.Initialise(String strPath) in C:\Documents and Settings\wimar.GRAFIDRUK\My Documents\Avans School\BLOK 12\Project RF Sniffer\PC Applicatie\Sniffer\UsbLibrary\HIDDevice.cs:line 111
at UsbLibrary.HIDDevice.FindDevice(Int32 nVid, Int32 nPid, Type oType) in C:\Documents and Settings\wimar.GRAFIDRUK\My Documents\Avans School\BLOK 12\Project RF Sniffer\PC Applicatie\Sniffer\UsbLibrary\HIDDevice.cs:line 257
What's Wrong ?
|
|
|
|
|
The error goes from HIDDevice.cs (Ln.265)
oNewDevice.Initialise(strDevicePath);
where the strDevicePath = "\\\\?\\hid#vid_04d8&pid_ff9d#6&3aa3f0e7&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
|
|
|
|
|
I have got to same problem with Mr.Iwan Budihalim.
oNewDevice.Initialise(strDevicePath);
where the strDevicePath = "\\?\hid#vid_067e&pid_0100#6&369a9828&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
I want to get data of barcode reader. Please help me!
Hoac Tai Thien
|
|
|
|
|
Same problem with same error as above.
I'm running WinXP and compiling with Visual C# 2008 Express.
Anybody found the reason????
|
|
|
|
|
I have had the same problems. I changed tehe parameters FILE_SHARE_READ | FILE_SHARE_WRITE in the CreatFile function.
Change the code in HIDDevice.cs and try one of this solutions:
// Create the file from the device path
// m_hHandle = CreateFile(strPath, GENERIC_READ | GENERIC_WRITE, 0,
// IntPtr.Zero, Win32Usb.OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, IntPtr.Zero);
// NEW --- 1. Solution
m_hHandle = CreateFile(strPath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, // changed from 0
IntPtr.Zero,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
// NEW --- 2. Solution
m_hHandle = CreateFile(
DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
0);
regards Jan
|
|
|
|
|
It's Working Thank you
|
|
|
|
|
|
Thank youuuuu!
|
|
|
|
|
How to get Product Name & Vendor Name of HID Device using C# ?
Thanks.
|
|
|
|
|
In the HIDDevice file there is a method called FindDevice(int nVid, int nPid, Type oType), in this method you will find code to get the product en vendor id. by using the GetDevicePath(hInfoSet, ref oInterface); will return a string with informatie like vendor and product id.
greetings wimar
|
|
|
|
|
Do you have any example of using FindDevice and GetDevicePath ?
Thanks
|
|
|
|
|
Hi wimar!
I have a doubt about this sample project!
When i try to run the sample. I found that i can get the device path success but CreateFile always failed! The system report the error message is "access is denied"! What's happened?
I use the File.Exist() function to test the device path always return false.
Thanks moonz_wu!
|
|
|
|
|
Hi Moonz_wu,
Are you using a hid device that is alway in use and locked by Windows? For example a mouse or keyboard. Because of devices from this type you can find the device path but you can't access it and will give the error you describe.
Greetings Wimar
|
|
|
|
|