Question

Our embedded systems programmer has developed the shell of a virtual serial port driver for our mobile hardware, and I have been filling in the methods to get it to work. The driver does work as expected, it simulates a COM port for a USB device that is spewing out NMEA strings (GPS data).

I type WM6 for short, but the OS is WM6.1 if it makes any difference.

The problem I am having is that the driver does not load at start up of the device on WM6 only. The driver was developed for both CE5 and WM6, but on CE5 the driver "does" load at boot, which is pointing me to a WM6 configuration issue. It maybe worth noting at this point that the driver will load in WM6 and CE5 using ActivateDevice() method, this is what I have been using so far for WM6, a small test app to launch the driver so I can at least test the driver is working on WM6.

The registry is already populated with the required keys for the startup of the driver. So the driver should load at startup without any issues. HKEY_LOCAL_MACHINE\Drivers\BuiltIn contains a sub key A36D_GPS_COM, and in that key is contained.

DeviceArrayIndex: 0

DeviceType: 0

Dll: A36D.dll

Flags: 0

Friendly Name: A36D GPS COM Port

Index: 8

Order: 3

Prefix: COM

Priority: 0

Priority: 256

From what I can tell there are generally 2 common answers to this issue which I have already investigated. These ideas were given to me by the embedded programmer but I researched how to do them myself.

1) The COM port is already in use when the driver tries to load, even if that COM port is eventually free once the device is loaded. I have changed the Index value in the registry from between 1 to 20 and rebooted the device, and the driver does not load onto a specified COM port. So to try and test this more thoroughly, I have moved another device to from COM9 to COM8 and moved my driver to COM9 (using the above registry settings). The other device driver loads at startup on COM8 quite happily but my device driver will not boot up on COM9. I have even tried tweaking the other settings but still it doesn't load the at boot.

2) Another possible issues and difference between CE5 and WM6 is security. So using the MSDN article http://msdn.microsoft.com/en-us/library/bb737570.aspx I have worked on signing and XML provisioning. Using a privileged key (not expired), The A36D.dll is signed in visual studio and the created installation CAB file is also signed with the same key. A _setup.xml file is created and appended to the cab file so that the signed key is added to the certificate store. The CAB file is signed again with the same key to ensure it is still valid. In addition the _setup.xml is packaged into its own .CPF file. Both the CAB and CPF files do add the key to the certificate stores "HKEY_LOCAL_MACHINE\Comm\Security\SystemCertificates" so know this is working. As a matter of caution I have installed it to the Privileged, Unprivileged, ROOT and SPC certificate stores. But the device driver still does not load into device.exe when the mobile device boots.

Other than a workaround of a start-up application that calls ActivateDevice() on the driver, I am stumped on how to get this driver to load at start-up.

I find it very odd it works in CE5 but not in WM6, I just don't know of anything else that could be causing issues.

Does anyone have any further suggestions that can be tried.

All help appreciated.

Was it helpful?

Solution

I am more familiar with Windows CE, but here are a couple of things:

  • Did you add a debug print in the DllMain function to see whether it is called?
  • Did you check for a dependency break. Could it be that somehow you have a Dll available under CE 5 that is not there under WM6?

OTHER TIPS

This is an answer, but not the 'right' one. It is merely a work around the loading issue. I figured this out over a week ago but did not want to use it as the solution. So this is hopefully just a temp fix.

The following code is used to load the driver manually, Its written in C# using C++ calls, I am used to C# which is why I did a C# project not a C++ one. Those who use C++ will undoubtedly create this in a C++ app.

public class LoadDriver
{
    [DllImport("coredll.dll", SetLastError = true)]
    public extern static IntPtr ActivateDevice(string lpszDevKey, int dwClientInfo);
    [DllImport("coredll.dll", SetLastError = true)]
    public static extern void SignalStarted( uint dw);

    public static void Main(string[] args)
    {
        Cursor.Current = Cursors.Default;
        IntPtr handle = ActivateDevice("Drivers\\BuiltIn\\A36D_GPS_COM", 0);
        if(handle != IntPtr.Zero)
        {
            Console.Write("Success");
        }

        if (args.Length > 0)
        {
            try
            {
                SignalStarted(uint.Parse(args[0]));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

Now in order for this to work it needs to be run at startup, so i added in the required registry keys.

"HKEY_LOCAL_MACHINE/init"
Launch62 = A36D_loaddriver.exe
Depend62 = "32 00"

"32 00" is to ensure it loads after the shell32.exe

Now the the startup of the device, the driver is activated in device.exe.

As to the signing/registry issue, this is still being looked into.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top