GPSID: Problem & workaround on recent WM6 release


Background
A number of customers on a recent WM6 versions have run into a problem where GPSGetPosition returns ERROR_INVALID_PARAMETER always, even on apps that worked fine in the past.  The newsgroup thread is here.


The device I’ve reproed and tested on was an HTC P3300, but based on newsgroup thread I think other devices may have been affected also.


I have determined the cause and a workaround for the problem.  It’ll take a while to get a real fix, but we’re working on that too.


Underlying Cause
In a future Windows Mobile, we’re exposing extensions to the GPS_POSITION and GPS_DEVICE structures.  GPSID is actually aware of the extended structure already – in WM6 AKU0.4 & above, also known as 18120+ builds.  The reason being that GPS chips can do some “magic” with this stuff even before we actually expose the structures to app developers.  (It’s a very long story, if you’re not a GPS OEM you don’t care.)  Because the structure is larger, it means the sizeof() checks on it have changed but sizeof(GPS_POSITION) that you’re passing in has not changed because you’re using the same GPS_POSITION as always.  The MS GPSID allows the old struct size for legacy.


What complicates things is that OEMs are allowed to replace GPSID on their device, because they may want to tweak it in order to work with their GPS chips.  I don’t have the source, but I’m almost positive what’s happening is that an OEM GPSID is checking only against the extended GPS_POSITION size and hence is failing when it gets the original GPS_POSITION.


Workaround
Your application can lie about how big a structure it is passing in to worakround this.  So if your application gets ERROR_INVALID_PARAMETER, it can pass in the sizes of the new struct.  Here’s code below.  I tested this with an HTC 3300 and was successfully able to get my lat/long using this.  GPSGetDeviceState has similar issue so I’m including code for it, too.


// Retrieves GPS location data and prints it to the screen.
void GetLocationAndPrint(HANDLE hGPS) {
    BYTE gpsPositionRaw[376];
    GPS_POSITION *pGpsLocation = (GPS_POSITION*)gpsPositionRaw;
   
    pGpsLocation->dwVersion = GPS_VERSION_1;
    pGpsLocation->dwSize    = sizeof(gpsPositionRaw);
 
    DWORD dw = GPSGetPosition(hGPS,pGpsLocation,1000,0);
    if (dw != ERROR_SUCCESS) {
        wprintf(L”GPSGetPosition() fails, GLE = 0x%08x\r\n”,dw);
        DebugBreak();
        return;
    }


    PrintGPSPosition(pGpsLocation);
}


void GetDeviceStateAndPrint(void) {
    BYTE gpsDeviceRaw[332];


    GPS_DEVICE *pGpsDevice = (GPS_DEVICE *)gpsDeviceRaw;
    pGpsDevice->dwVersion = GPS_VERSION_1;
    pGpsDevice->dwSize = sizeof(gpsDeviceRaw);
 
    DWORD dw = GPSGetDeviceState(pGpsDevice);
    if (dw != ERROR_SUCCESS) {
        wprintf(L”GPSGetDeviceState() fails, GLE = 0x%08x\r\n”,dw);
        DebugBreak();
        return;
    }
    PrintGPSDeviceState(pGpsDevice);
}


Going Forward
This is clearly a stop-gag solution.  There’s no way that we expect our customers to recompile existing apps for a new WM release, especially considering how hard it is to get applications signed/tested/deployed.  I have alerted the OEM to the problem and am coordinating with them on rolling out a fix.  I’ll provide an update when I can.


Once again I apologize for the pain that this has caused and the delay.


John

Comments (9)

  1. dbaabaa says:

    Pl send me the details at nitin.intel@gmail.com

    or pl send the compiled ROM file for WM6

  2. cenet says:

    What details specifically would you want?  

    I can’t send the ROM, you would need to get that from your carrier because they need to put special drivers for your phone on it.  The GPSID changes are already part of the WM ROM.

  3. Anonymous says:

    Where could I find information about the extended GPS_POSITION and GPS_DEVICE structure? Are you going to expose the information with WM 6.1? Thanks.

  4. Anonymous says:

    Well, it seems that best way is to do for(pGpsDevice->dwSize=16, … pGpsDevice->dwSize++) until max size or return from GGPSGetDeviceState returns somethin gelse than ERROR_INVALID_PARAMETER. This way I have found out that valid size is 217 rather than 332 or 344 as reported through forums…

  5. cenet says:

    The extended GPS_POSITION & API stuff unfortunately is not being exposed to ISV’s in WM 6.1.  If you are an OEM, you should be able to work with your technical account manager to get into Jetstream, since the extensions will be available for OEM’s only.

    (The extended API mmm is referring to basically allows applications to configure optional params of GPS devices, assuming the device supports it, like QoS.)

    The reason we’re not exposing the extension to ISV’s in WM6.X timeframe is that it requires public header file changes and we don’t have a model to drop a single header file into your SDK.  This means we would have to re-create the entire WM6 SDK for WM6.1 and in theory every WM6.1 developer would have to download it.  Since the SDK is like 500MB or so (it includes the emulators which is why it’s so huge, there’s unfortunately not a way to split this up) we just can’t force that big of a download on everyone.

    It will be documented & exposed for developers in WM7.

    John

  6. cenet says:

    lef – which device are you on?  217 seems really weird, unless an OEM made some sort of change we’re not aware of.  Thanks

    John

  7. Anonymous says:

    Hello everyone,

    can someone translate me the code of the workaround to C# or VB.NET, please?

    Thank you,

    Daniel

  8. cenet says:

    You’ll probably have better luck on a newsgroup; the commentary on the blog and especially older posts tends to be light.

    microsoft.public.pocketpc.developer would probably be a good starting point.

    I don’t know VB.Net so I’m not able to help personally.

    Good luck.