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]

Comments (12)

  1. Patrick Berny says:

    Hi John:

    could you envision an event-driven mechanism to drive the whole thing, maybe for the next Windows Mobile. For navigation type apps that happen to use the parsed api, doing polling underneath potentially just increases the latency, which can affect the customer experience negatively. The positioning on the map gets delayed, so you might get the friendly voice telling you to turn right just as you hit an intersection, instead of a bit before, that sort of thing. How about passing the hNewLocationData from the GPSOpenDevice into the driver underneath (via some new ioctl?) ?

    Best regards, Patrick

  2. cenet says:

    Patrick – thank you for this feedback.  We’re actually looking into mechanism where the app can direcly ask the GPS driver for position on-demand (though if you read this blog you’ll see my standard "I can’t promise future feature" line :().  You could potentially also set the poll interval to be say 100ms or smaller, that keeps CPU churning a bit more but given GPS tends to be power hog anyway it may not impact battery so badly.  

    For nav apps, I’d hope they’d be smart about giving 10-15 seconds notice before a turn came up (I don’t know the standard) so hopefully any delay introduced as-is wouldn’t put you in middle of intersection.  NMEA polling is similiar to pollDriver (just mechanism is different) so hopefully by the time data gets to app it’s not so different.

    John

  3. Patrick Berny says:

    NMEA polling is similiar to pollDriver (just mechanism is different) so hopefully by the time data gets to app it’s not so different.

    But with nmea polling from com port you probably are using the ReadIntervalTimeout and ReadTotalTimeoutConstant timeout value to throttle the actual polling, so if data has been coming in, you will return quicker than with having a timer on the outside and then doing the non-blocking IOCTL_GPS_DRIVER_GET_LOCATION_V1 call. So I would expect the nmea poll to have less delay than poll driver, or am I missing something?

    Note on the side, nave apps traditionally give a notice a long time before and then just about 50-100 yards before you need to make the turn, that’s the one you don’t want to come too late.

    I absolutely agree on the gps being quite demanding on the battery though, so increasing the pollling might not be too bad after all.

  4. cenet says:

    Patrick – for NMEA polling I actually call into the driver itself and block (since this is just how the serial drivers are, and they take the CommTimeouts settings), for poll-driver GPSID itself is the one throttling the calls.  Both calls for ReadFile() & the PollDriver IOCTL should be pretty fast, mainly limited by the underlying GPS driver itself.  The poll driver may actually end up being slightly faster because it doesn’t have to parse out NMEA string, whereas the NMEA one will of course.

    No matter what, though, I’d think that the time delays between both shouldn’t be too bad – no one has complained in actual practice yet about the NMEA one, though poll driver is new and hasn’t had the tires kicked in by real use yet.

    John

  5. Rajesh says:

    Hi ,

    Could somebody please let me know how to call  AppA [console application exe]   from AppB ? [Both are windows CE apps]. Where I can find some sample code for that.?

    thanks in advance.

    Rajesh

  6. cenet says:

    Rajesh, please check out http://blogs.msdn.com/cenet/archive/2005/07/13/438424.aspx for an intro to interprocess communication on CE.  For future questions I’d recommend posting on a newsgroup since the interface (in my opinion) is easier to deal with, http://blogs.msdn.com/cenet/archive/2005/12/05/500181.aspx has a list of newsgroups I check daily

    John

  7. Kamal Aanand R says:

    Hi Group!

    I was facinated to find that there is something like the GPS intermediate driver and quickly pounced on it the API. It immediately threw some location info and was quite happy.

    But on close examination on the location info, I see some problem.

    I have a Compaq HP Ipaq 6965 phone and am based at Bangalore, India. If I try to locate my position using the GPS Interemediate driver (_gpsDevicePosition.LatitudeInDegreesMinutesSeconds), I get the result as 0d 12′ 57.19555390000001". There is something seriously wrong as I get a 0 degree as the result. I also noticed that the degree has been offset to the minutes and the miutes has been offset to the seconds.

    To counter check, I directly read the content from COM7. The location that I parsed from my $GPRMC (NMEA Sentence) was 12°57.186299"N. This gives me the correct degree as 12 and not 0. I am in a fix!

    Has anybody come across such a situation or do you have any answers for me to try out?? Thanks.

    Kamal Aanand R

  8. amvyas82 says:

    Is it possible to include this GPS intermediate driver in to the WinCE 5.0 manually? Can we make WinCE 5.0 support GPSID?

  9. cenet says:

    I’m afraid GPSID on CE 5.0 isn’t possible due to various legal/licensing type agreements with the way that we ship the code.  Sorry I don’t have a better answer for you here.

    John

  10. cenet says:

    Kamal – to answer your question, I think you’re running into the issue described here:

    http://blogs.msdn.com/cenet/archive/2006/02/10/windows-ce-gpsid-its-c-wrapper-and-device-emulator-interaction-issues.aspx

    Apologies on very delayed response.  I’d recommend a newsgroup for questions like this, listed http://blogs.msdn.com/cenet/archive/2005/12/05/500181.aspx.

    John

  11. wz2b says:

    Should this work in WM5 as well?

  12. cenet says:

    I’m afraid it won’t work in WM5 or WM6.  Basically the way our WM release dates are staggered a bit differently than the general embededd, and it just happened that I had time to do this in CE6 but it was too late for WM*.  This absolutely will be present in WM7.

Skip to main content