RawHid for 64 Bit Windows

Status
Not open for further replies.

jpatrick62

Well-known member
Recently I had a need to implement RawHid for a project I was working on. Specifically needed to configure a NRF24L01 radio channel and power setting that my Teensy 3.1 was using. So I created
a Windows program to do this and tried the RawHid dll to talk to the Teensy. Unfortunately rawhid_open() throws an BadImageFormatException

{"An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)"}

which I assume is because the dll was compiled for 32 bit Windows and I was using 64 bit.

Has anyone recompiled this dll for 64 bit? This would save me the trouble of rooting for the DDK as it appears I need a file from the Win DDK.

Anyone else run across this?
 
I have RawHID working for both 32bit and 64bit windows / OSX. Should work fine. Keep in mind that you you need to link and include different files when building your program, but if I remember correctly, Visual Studio will bark at you if you include the wrong files.

Regards,
Rob
 
Hmmm so if everyone else has got this to work in Win64 OS, then maybe I just got a bad file or something. I just downloaded this from pjrc's rawhid page and I'll try it out tonight.
 
Hmmm so if everyone else has got this to work in Win64 OS, then maybe I just got a bad file or something. I just downloaded this from pjrc's rawhid page and I'll try it out tonight.
There's no reason why you need to compile 64 bit. A 32 bit raw hid application will work fine on a 64 bit OS .

Also, you've install the windows development kits? I can't remember off hand the ones you need....
 
Thanks for the help so far everyone, appreciate it. So I set the build type in VS2013 on the .net assembly for x86 versus "Any" and now the incorrect format exception went away. So Windows just thunks the 32 bit code in a
64 bit environment, fine so far. So I built a teensy rawhid sketch that simply emits an Analog value every few secs depending on the position of the potentiometer. The rawhid_test.exe C client and the SimpleHidWrite
GUI clients both see the teensy insertion and the subsequent analog values it sends, so everything seems OK there as well. However my ultimate client will be a Windows WPF GUI so I need to make a C# client see this as well.
Here's the rub: when I try to connect via a C# client that is using the rawhid.dll via PInvoke, it keeps failing to connect.

Code:
  [DllImport("Assemblies/rawhid.dll")]
        public static extern int rawhid_open(int max, int vid, int pid, int usage_page, int usage);
        [DllImport("Assemblies/rawhid.dll")]
        unsafe public static extern int rawhid_recv(int num, void* buf, int len, int timeout);
        [DllImport("Assemblies/rawhid.dll")]
        unsafe public static extern int rawhid_send(int num, void* buf, int len, int timeout);
        [DllImport("Assemblies/rawhid.dll")]
        public static extern void rawhid_close(int num);

        bool OpenHid()
        {
            try
            {
                int r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200);
                if (r <= 0)
                {
                    r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200);
                    if (r <= 0)
                    {
                        Debug.WriteLine("no rawhid device found\n");
                        return false;
                    }
                }
                Debug.WriteLine("found rawhid device\n");
                return true;
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.ToString());
            }
            return false;
        }

These vid/pid values are correct as I can see the insertion in device manager and the C clients see the teensy as well. The rawhid_open keeps returning 0 under debug.
 
Well I compiled the C code supplied for the rawhid tester and it does indeed see my teensy. Interestingly, the rawhid_open initially fails and then succeeds on the 2nd attempt. In rawhid_open c source the HID_GetAttributes function succeeds on
the 2nd function call where it failed on the first.

Code:
ret = HidD_GetAttributes(h, &attrib);

So I suppose I'll just have to dig a bit deeper as to why a C# PInvoke to the rawhid dll can not connect where the C code version does connect to the very same teensy.
 
My code is all c±+, so I'm not really sure how much help I can be. One thing I can tell you is that there are some bugs in the windows rawhid_open code. I can't remember off hand as I rewrote most of the code, but I can tell you that it is related to some memory that's not properly released.

In my code I'm constantly checking how many matching devices are connected, and calling rawhid_open if the number counted and the number opened don't match. I made my own rawhid_count function for this purpose. Anyways, even if the rawhid_open fails on the first try, my code would just keep calling open.

Anyways, good luck.

Rob.
 
Solved the problem, although the exact issue is not been confimed yet. The issue, at least from the view of calling the rawhid dll functions from managed code, appears to
be the way initialization static variables in the dll are treated. When called within a c command line or window, the dll is loaded into memory space of the caller and the
2nd call to rawhid_open succeeds. However, it is apparent that something goes awry when this dll is loaded into managed code space, although it is not readily apparent.
What I did was add another function call to the dll to be exported called rawhid_managed_open. In this function I call rawhid_open twice in behest of the caller (the
managed code client). This works, and the managed code client thus only needs to make 1 call to rawhid_managed_open() and it is connected. I can also see data passing
back to my managed client.

Code:
int rawhid_managed_open(int max, int vid, int pid, int usage_page, int usage)
{
	int r;
	char c, buf[64];

	r = rawhid_open(max, vid, pid, usage_page, usage);
	if (r <= 0) 
	{
		// Arduino-based example is 16C0:0486:FFAB:0200
		r = rawhid_open(1, 0x16C0, 0x0486, 0xFFAB, 0x0200);
		if (r <= 0) 
		{
			printf("no rawhid device found\n");
			return -1;
		}
	}
	return r;
}

I compiled the dll as a native 64 bit dll and set my managed client as a 64 bit platform as well. Provided you are using .net 4.0 and above, and provided a few
compiler build variables are set, you can include both the unmanaged dll and the managed client in the same solution as separate projects and debug
into the dll from managed code call - pretty cool!
 
Slightly cleaner version....

Code:
int rawhid_managed_open(int max, int vid, int pid, int usage_page, int usage)
{

	int r = rawhid_open(max, vid, pid, usage_page, usage);
	if (r <= 0) 
	{
		r = rawhid_open(max, vid, pid, usage_page, usage);
		if (r <= 0) 
		{
			return -1;
		}
	}
	return r;
}
 
:eek:(Sheepish grin) Well, it looks like I may have manufactured my own trouble by inserting one wrong digit into the PID during development and that looks to be the problem with the C# to C dll problems. Honestly I don't
know how that slipped through but it did. So everything is now OK, and I even have a 64 bit .net and 64 bit rawhid dll, but the extra function export is not needed. Looking on the bright side, it was a good exercise in
managed to unmanaged dll debugging in VS, but how embarrassing.
 
Status
Not open for further replies.
Back
Top