How do I P/Invoke DeviceIoControl with IOCTL_SERVICE_STOP?
-
venerdì 3 aprile 2009 09:33
Hi,
We have a problem with Bluetooth on the fleet of handhelds we use.
Regularly, the Bluetooth will refuse to connect to a belt receipt printer.
They are WinCE 4.2 devices running a NETCF 1.0 SP3 application.
We use version 1.4 of the OpenNETCF SDF to interface with the MS BT stack via the Winsock interface.
A workaround is to put the handheld into standby, and wake it again.
Now, there is an exe called btloader and I can stop and start the Bluetooth with "btloader stop/start card"
Built from some MS sample code, it appears to disable and enable the Bluetooth (the BT tools icon disappears and returns)
But, it's only there on older handhelds (guess the didn't include it when they built the new firmwares)
MSDN document about this sample: http://msdn.microsoft.com/en-us/library/aa915894.aspx
From the article:
HANDLE hDev = CreateFile ( L"BTD0:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
If the stream opens successfully, applications can manage the stack's characteristics through the DeviceIoControl call
IOCTL function Service IOCTL_SERVICE_START
Card start.
IOCTL_SERVICE_STOP
Card stop.
So, I wrote the following code:
Now, CreateFile works.using System; using System.Text; using System.Data; using System.Runtime.InteropServices; using OpenNETCF.IO; namespace BTLoader { class Class1 { //#define FILE_DEVICE_SERVICE 0x00000104 private const UInt32 FILE_DEVICE_SERVICE = 0x00000104; //#define METHOD_BUFFERED 0 private const UInt32 METHOD_BUFFERED = 0; //#define FILE_ANY_ACCESS 0 private const UInt32 FILE_ANY_ACCESS = 0; //WINBASEAPI BOOL WINAPI DeviceIoControl (HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped); [DllImport("coredll.dll")] public static extern UInt32 DeviceIoControl(IntPtr hDevice, UInt32 dwIoControlCode, IntPtr lpInBuf, UInt32 nInBufSize, IntPtr lpOutBuf, UInt32 nOutBufSize, ref UInt32 lpBytesReturned, IntPtr lpOverlapped); [DllImport("CoreDll.dll", EntryPoint="GetLastError")] public static extern int GetLastError(); static void Main(string[] args) { // HANDLE hDev = CreateFile ( // L"BTD0:", // GENERIC_READ | GENERIC_WRITE, // FILE_SHARE_READ | FILE_SHARE_WRITE, // NULL, OPEN_EXISTING, 0, NULL // ); // If the stream opens successfully, applications can manage the stack's characteristics through the DeviceIoControl call. In this example, the following services are demonstrated. // // IOCTL function Service // IOCTL_SERVICE_START Card start. // IOCTL_SERVICE_STOP Card stop. // IOCTL_SERVICE_CONSOLE Console on or off. // IOCTL_SERVICE_DEBUG DebugOut console/serial, debug <mask>. UInt32 iBytesReturned = 0; UInt32 iWorked; int iError; IntPtr hDev = FileEx.CreateFile("BTD0:", FileAccess.Read | FileAccess.Write, FileShare.Read | FileShare.Write, FileCreateDisposition.OpenExisting, 0); iWorked = DeviceIoControl(hDev, IOCTL_SERVICE_STOP(), IntPtr.Zero, 0, IntPtr.Zero, 0, ref iBytesReturned, IntPtr.Zero); if(iWorked != 0) { iWorked = DeviceIoControl(hDev, IOCTL_SERVICE_START(), IntPtr.Zero, 0, IntPtr.Zero, 0, ref iBytesReturned, IntPtr.Zero); if(iWorked == 0) iError = GetLastError(); } else { iError = GetLastError(); } } // // Start the service that has been in inactive state. Return code: SERVICE_SUCCESS or error code. // //#define IOCTL_SERVICE_START CTL_CODE(FILE_DEVICE_SERVICE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) private static UInt32 IOCTL_SERVICE_START() { return CTL_CODE(FILE_DEVICE_SERVICE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS); } // // Stop service, but do not unload service's DLL // //#define IOCTL_SERVICE_STOP CTL_CODE(FILE_DEVICE_SERVICE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) private static UInt32 IOCTL_SERVICE_STOP() { return CTL_CODE(FILE_DEVICE_SERVICE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS); } // // Macro definition for defining IOCTL and FSCTL function control codes. Note // that function codes 0-2047 are reserved for Microsoft Corporation, and // 2048-4095 are reserved for customers. // //#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ // ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ // ) private static UInt32 CTL_CODE( UInt32 DeviceType, UInt32 Function, UInt32 Method, UInt32 Access) { UInt32 output; output = ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method); return output; } } }
DeviceIOControl with SERVICE_START works, but returns an already started error (of course)
But, DeviceIOControl with SERVICE_STOP just, stops. DeviceIOControl never returns.
I've seen another example where it passes "card" into lbInBuf as an array of WCHARs, no idea how you would p/invoke it though.
All I got it to do was give me Invalid Param: Bad Pointer errors.
How do you create a pointer to a managed type?
Anyway, can anybody help me in getting this to work? Or supply the source code for BTLoader?
Thanks,
James.
Tutte le risposte
-
venerdì 25 dicembre 2009 04:15Hi,
Did you solve the problem?
How did you set the FILE_DEVICE_SERVICE value? what will be the value for a WinCE 6.0 device?
Thanks,
Alon
Alon -
giovedì 21 gennaio 2010 10:06
Hi,
Yes I did solve the problem.
I shall post the code here later, I'll need to tidy it up a bit.
J.- Contrassegnato come risposta JNeave giovedì 21 gennaio 2010 10:08
-
domenica 15 aprile 2012 16:29Hello JNeave, you never did post your code. I'm stuck in the same problem. If you can find it. Thanks !

