J
Jason
I have an application that uses an attached GPS through the COM port.
Unfortunately it seems that time has moved on and more and more GPS devices
are native "HID" devices connected to a USB port. (Good news for Vista 64bit
users I guess!) Unfortunately as far as I can tell I need to use Raw Input
from User32.dll in order to find the GPS device and register my application
to receive data from it. The problem I am having is I don't know how to
setup my RAWINPUTDEVICE structure for the GPS so I can register it. I
thought I would try to use GetRawInputDeviceList to get a list of all the
RawInput devices (Successful, good examples online) and then take each
device in the list and call GetRawDeviceInfo with the RIDI_DEVICEINFO flag
in order to get the RID_DEVICE_INFO struct populated with the detailed
information I need in order to create a proper RAWINPUTDEVICE. Unfortunately
this is where I am failing. The RID_DEVICE_INFO structure uses a C/C++ union
in it and I have no idea how to set this up in C# properly. Here is some
code:
The examples I saw suggested setting up the structs like so:
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_HID
{
[MarshalAs(UnmanagedType.U4)]
public int dwVendorId;
[MarshalAs(UnmanagedType.U4)]
public int dwProductId;
[MarshalAs(UnmanagedType.U4)]
public int dwVersionNumber;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
}
Not sure how to approach this with the RID_DEVICE_INFO though. I tried:
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO
{
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.U4)]
public int dwType;
[MarshalAs(UnmanagedType.Struct)]
public RID_DEVICE_INFO_MOUSE mouse;
[MarshalAs(UnmanagedType.Struct)]
public RID_DEVICE_INFO_KEYBOARD keyboard;
[MarshalAs(UnmanagedType.Struct)]
public RID_DEVICE_INFO_HID hid;
}
I also tried an explicit definition with Offsets since I think this is the
proper way to emulate a union in C#
[StructLayout(LayoutKind.Explicit)]
internal struct RID_DEVICE_INFO
{
[System.Runtime.InteropServices.FieldOffset(0)]
public int cbSize;
[System.Runtime.InteropServices.FieldOffset(0)]
public int dwType;
[System.Runtime.InteropServices.FieldOffset(8)]
public RID_DEVICE_INFO_MOUSE mouse;
[System.Runtime.InteropServices.FieldOffset(8)]
public RID_DEVICE_INFO_KEYBOARD keyboard;
[System.Runtime.InteropServices.FieldOffset(8)]
public RID_DEVICE_INFO_HID hid;
}
Then basically I call the GetRawInputDeviceInfo and try to create a
RID_DEVICE_INFO from the resulting pointer. I think this is what is going
wrong:
GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICEINFO, IntPtr.Zero, ref
pcbSize);
if (pcbSize > 0)
{
//Try getting Device Info
RID_DEVICE_INFO ridi = new RID_DEVICE_INFO();
ridi.cbSize = pcbSize;
IntPtr pData = Marshal.AllocHGlobal((int)pcbSize);
GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICEINFO,
pData, ref pcbSize);
ridi = (RID_DEVICE_INFO)Marshal.PtrToStructure(pData,
typeof(RID_DEVICE_INFO)); ///Problematic line
Marshal.FreeHGlobal(pData);
if (ridi.dwType == RIM_TYPEHID)
{
System.Diagnostics.Debug.WriteLine("UsagePage: " +
ridi.hid.usUsagePage);
System.Diagnostics.Debug.WriteLine("Usage: " +
ridi.hid.usUsage);
}
}
Marshalling the Pointer to the info data into the info structure just seems
to return junk. It's the same junk each time, but junk. For example the
dwType in the ridi should match the one in the rid and be 0,1, or 2. But the
ridi.dwType often is some large number. It seems as if I can't marshal the
pointer properly or the struct that I'm using is messed up in someway and is
unable to accept the marshalled data. I don't know which side I've gotten
wrong.
Anyone have any helpful pointers for me? Also if you think this topic
belongs in a different newsgroup left me know.
Thanks,
Jason
Unfortunately it seems that time has moved on and more and more GPS devices
are native "HID" devices connected to a USB port. (Good news for Vista 64bit
users I guess!) Unfortunately as far as I can tell I need to use Raw Input
from User32.dll in order to find the GPS device and register my application
to receive data from it. The problem I am having is I don't know how to
setup my RAWINPUTDEVICE structure for the GPS so I can register it. I
thought I would try to use GetRawInputDeviceList to get a list of all the
RawInput devices (Successful, good examples online) and then take each
device in the list and call GetRawDeviceInfo with the RIDI_DEVICEINFO flag
in order to get the RID_DEVICE_INFO struct populated with the detailed
information I need in order to create a proper RAWINPUTDEVICE. Unfortunately
this is where I am failing. The RID_DEVICE_INFO structure uses a C/C++ union
in it and I have no idea how to set this up in C# properly. Here is some
code:
The examples I saw suggested setting up the structs like so:
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_HID
{
[MarshalAs(UnmanagedType.U4)]
public int dwVendorId;
[MarshalAs(UnmanagedType.U4)]
public int dwProductId;
[MarshalAs(UnmanagedType.U4)]
public int dwVersionNumber;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
}
Not sure how to approach this with the RID_DEVICE_INFO though. I tried:
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO
{
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.U4)]
public int dwType;
[MarshalAs(UnmanagedType.Struct)]
public RID_DEVICE_INFO_MOUSE mouse;
[MarshalAs(UnmanagedType.Struct)]
public RID_DEVICE_INFO_KEYBOARD keyboard;
[MarshalAs(UnmanagedType.Struct)]
public RID_DEVICE_INFO_HID hid;
}
I also tried an explicit definition with Offsets since I think this is the
proper way to emulate a union in C#
[StructLayout(LayoutKind.Explicit)]
internal struct RID_DEVICE_INFO
{
[System.Runtime.InteropServices.FieldOffset(0)]
public int cbSize;
[System.Runtime.InteropServices.FieldOffset(0)]
public int dwType;
[System.Runtime.InteropServices.FieldOffset(8)]
public RID_DEVICE_INFO_MOUSE mouse;
[System.Runtime.InteropServices.FieldOffset(8)]
public RID_DEVICE_INFO_KEYBOARD keyboard;
[System.Runtime.InteropServices.FieldOffset(8)]
public RID_DEVICE_INFO_HID hid;
}
Then basically I call the GetRawInputDeviceInfo and try to create a
RID_DEVICE_INFO from the resulting pointer. I think this is what is going
wrong:
GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICEINFO, IntPtr.Zero, ref
pcbSize);
if (pcbSize > 0)
{
//Try getting Device Info
RID_DEVICE_INFO ridi = new RID_DEVICE_INFO();
ridi.cbSize = pcbSize;
IntPtr pData = Marshal.AllocHGlobal((int)pcbSize);
GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICEINFO,
pData, ref pcbSize);
ridi = (RID_DEVICE_INFO)Marshal.PtrToStructure(pData,
typeof(RID_DEVICE_INFO)); ///Problematic line
Marshal.FreeHGlobal(pData);
if (ridi.dwType == RIM_TYPEHID)
{
System.Diagnostics.Debug.WriteLine("UsagePage: " +
ridi.hid.usUsagePage);
System.Diagnostics.Debug.WriteLine("Usage: " +
ridi.hid.usUsage);
}
}
Marshalling the Pointer to the info data into the info structure just seems
to return junk. It's the same junk each time, but junk. For example the
dwType in the ridi should match the one in the rid and be 0,1, or 2. But the
ridi.dwType often is some large number. It seems as if I can't marshal the
pointer properly or the struct that I'm using is messed up in someway and is
unable to accept the marshalled data. I don't know which side I've gotten
wrong.
Anyone have any helpful pointers for me? Also if you think this topic
belongs in a different newsgroup left me know.
Thanks,
Jason