GPS Poll Driver Sample

I mention here that the information about the GPSID poll driver is now included in WinCE 6.  If you are an OEM implementing a GPS driver on CE6 and you're not natively spitting out NMEA but would have to generate NMEA only for GPSID to parse, I'd highly recommend that you check out this information.

To help get you started, I'm including sample code that shows how to implement a poll driver.  As I call out at the top of the file, this is a simple illustrative sample only.  In this case I hard-code a starting position and change it slightly every time that the driver is called in order to simulate movement.  As you can see it's not rocket science to plug into the GPSID interface, the tricky portion is controlling your actual GPS device of course!

<PollService.cpp>

// WARNING: THIS CODE HAS NO SECURITY CHECKS, HAS NOT BEEN PROPERLY TESTED, AND IS FOR ILLUSTRATIVE
// PURPOSES ONLY.  IT MUST NOT BE SHIPPED AS-IS

// Simple server to test GPSID and POLL based drivers.
// This is an extremely primitive service, just enough to test basic GPSID
// interactions.  The hard-core dev tests for POLL drivers are in ..\whiteBox\PollDriver.cpp

/* This is the sample registry to use this service
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\Poll]
"InterfaceType" = "Poll"
"CommPort" = "GPP0:"

[HKEY_LOCAL_MACHINE\Services\GPSPollService]
   "Dll"="PollService"
   "Order"=dword:15
   "Keep"=dword:1
   "Index"=dword:0
   "Prefix"="GPP"

*/

#include <windows.h>
#include <service.h>
#include <gpsapi.h>
#include <gpsDev.h>

DWORD g_dwServiceState = SERVICE_STATE_ON;

// Position we return is based on this data, though we'll change it slightly over time
// to make things more interesting.
static GPS_POSITION gpsData = {1, sizeof(GPS_POSITION),  0x0003ffff, 0, {2001, 3, 0, 1, 21, 10, 54, 0}, 4723.7722, -12011.9324, (FLOAT)0.06, (FLOAT)76.77,  18.1,
                          (FLOAT)364.5, (FLOAT)-18.3, GPS_FIX_QUALITY_GPS, GPS_FIX_3D, GPS_FIX_SELECTION_AUTO, (FLOAT) 2.2,
                          (FLOAT)1.2, (FLOAT)1.8, 7, { 0x05, 0x11, 0x1e, 0x18, 0x19, 0x06, 0x0a, 0, 0, 0, 0, 0 }, 8,
                            { 0x1e, 0x06, 0x0a, 0x18, 0x05, 0x19, 0x11, 0x07, 0, 0, 0, 0 }, // rgdwSatellitesInViewPRNs
                            { 0x40, 0x36, 0x2e, 0x2d, 0x2d, 0x0e, 0x0e, 0x05, 0, 0, 0, 0 }, // rgdwSatellitesInViewElevation
                            { 0x0ea,0x126,0x083,0x036,0x0b6,0x12d,0x0e7,0x142,0,0,0,0 }, // rgdwSatellitesInViewAzimuth
                            { 0x02f,0x02b,0x02f,0x02e,0x02e,0x028,0x02a,0x02a,0,0,0,0} // rgdwSatellitesInViewSignalToNoiseRatio
};

extern "C" DWORD GPP_Init (DWORD dwData) {
 return TRUE;
}

extern "C" BOOL GPP_Deinit(DWORD dwData) {
 return TRUE;
}

extern "C" DWORD GPP_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode) {
 return TRUE;
}

extern "C" BOOL GPP_Close (DWORD dwData) {
 return TRUE;
}

extern "C" BOOL GPP_IOControl(DWORD dwData, DWORD dwCode, PBYTE pBufIn,
                              DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
                              PDWORD pdwActualOut)
{
 DWORD dwError = ERROR_INVALID_PARAMETER;
 // Control code sent to start a service.
 switch (dwCode) {
 case IOCTL_SERVICE_START:
     g_dwServiceState = SERVICE_STATE_ON;
 break;

 case IOCTL_SERVICE_STOP:
  g_dwServiceState = SERVICE_STATE_OFF;
 break;   
 
 case IOCTL_SERVICE_STATUS:
  *(DWORD *)pBufOut = g_dwServiceState;
  *pdwActualOut = sizeof(DWORD);
 break;

 // GPSID requests current location...
 case IOCTL_GPS_DRIVER_GET_LOCATION_V1:
  if (g_dwServiceState == SERVICE_STATE_ON) {
   ASSERT((pBufOut != NULL) && (dwLenOut == sizeof(GPS_POSITION)));
   gpsData.dblLatitude  += 0.04;
   gpsData.dblLongitude -= 0.05;
   memcpy(pBufOut,&gpsData,sizeof(gpsData));
   *pdwActualOut = sizeof(gpsData);
  }
  else {
   SetLastError(ERROR_SERVICE_NOT_ACTIVE);
   return FALSE;
  }
 break;

 default:
  SetLastError(ERROR_INVALID_PARAMETER);
  return FALSE;
 break;
 }

 return TRUE;
}

extern "C" BOOL WINAPI DllEntry( HANDLE hInstDll, DWORD fdwReason,
                 LPVOID lpvReserved) {
 return TRUE;
}

<PollService.def>

LIBRARY     POLLSERVICE

EXPORTS
    GPP_Init
    GPP_Deinit
    GPP_Open
    GPP_Close
    GPP_IOControl

[Author: John Spaith]