I am trying to write the C# equivalent to the following:
typedef struct BATT_ID
{
UINT8 nBattID[8];
} BATT_ID, *PBATT_ID;
HANDLE g_hDevice;
// Connect to the driver
g_hDevice = CreateFile(L"BAT1:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
void GetBattID(PBATT_ID pBattId)
{
// ... snipped code to check g_hDevice is valid ...
DeviceIoControl(g_hDevice, SOMO650_PWR_GET_BATT_ID, NULL, 0, pBattId, sizeof(BATT_ID), dwByteReturn, NULL))
}
// once BATT_ID has been filled it can be formatte开发者_StackOverflow中文版d as follows
wsprintf(strInfo, TEXT("%02X:%02X:%02X:%02X:%02X:%02X"), BattID.nBattID[6], BattID.nBattID[5], BattID.nBattID[4], BattID.nBattID[3], BattID.nBattID[2], BattID.nBattID[1]);
The code is connecting to the power driver of a Windows Mobile device and attempting to retrieve the battery Id.
This is for the latest ROM version of the SoMo650 and Socket are only able to provide sample code in C.I can successfully do everything (as best as I can tell) apart from calling DeviceIoControl as I don't know how to translate the BATT_ID structure into C#.
I'm guessing that as it's a structure and DeviceIoControl expects a pointer I shoould be looking at Marshal.PtrToStructure() but I have very little C experience and feel very out of my depth.
Any assitance would be greatly appreciated.
You might be better to use the Smart Device Framework which has a battery control in place..see here for the download link for the community edition.
Edit: If you still want the pinvoke equivalent of the structure look here:
[StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BATT_ID { [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I8)] public int[] nBattId; };
Then prior to p/invoking, you need the signature for the 'DeviceIoControl' as shown:
[DllImport("coredll.dll", EntryPoint="DeviceIoControl", SetLastError=true)] internal static extern int DeviceIoControlCE( int hDevice, int dwIoControlCode, byte[] lpInBuffer, int nInBufferSize, byte[] lpOutBuffer, int nOutBufferSize, ref int lpBytesReturned, IntPtr lpOverlapped);
The call would look like this:
IntPtr ptr = IntPtr.Zero; BATT_ID battId; int sz = Marshal.SizeOf(battId.GetType()); ptr = Marshal.AllocHGlobal(sz); Marshal.StructureToPtr((BATT_ID)battId, ptr, false); byte[] pBattId = ptr.ToPointer(); out int bytesReturned = 0; DeviceIoControl(handle, IOCONTROL_ID, null, 0, pBattId, sz, ref bytesReturned, IntPtr.Zero); battId = Marshal.PtrToStructure(ptr, battId.GetType()); Marshal.FreeHGlobal(ptr);
I hope I have this right...
Edit#2: As ctacke (thanks!) pointed out my code sample is wrong...
unsigned byte[8] battId; DeviceIoControl(g_hDevice, SOMO650_PWR_GET_BATT_ID, null, 0, battId, Marshal.SizeOf(battId), ref bytesReturned, IntPtr.Zero);
Basically you have a structure that is 8 bytes. Just pass in a byte[] that is 8 bytes long to the DeviceIoControl call. There is no need to call AllocHGlobal, or do any other wacky marshaling.
精彩评论