epoc-gps-module.cpp

Go to the documentation of this file.
00001 #include "epoc-gps-module.hpp"
00002 
00003 #include "er_errors.h"
00004 #include "utils_cl2.h"
00005 
00006 CPosModuleStatAo* CPosModuleStatAo::NewL(MObserverPosMod& aObserver)
00007 {
00008   CPosModuleStatAo* obj = new (ELeave) CPosModuleStatAo(aObserver);
00009   CleanupStack::PushL(obj);
00010   obj->ConstructL();
00011   CleanupStack::Pop(obj);
00012   return obj;
00013 }
00014 
00015 CPosModuleStatAo::~CPosModuleStatAo()
00016 {
00017   Cancel();
00018   SESSION_CLOSE_IF_OPEN(iPositionServer);
00019 }
00020 
00021 CPosModuleStatAo::CPosModuleStatAo(MObserverPosMod& aObserver) :
00022   CActive(CActive::EPriorityStandard), 
00023   iObserver(aObserver)
00024 {
00025   CActiveScheduler::Add(this);
00026 }
00027 
00028 void CPosModuleStatAo::ConstructL()
00029 {
00030   LEAVE_IF_ERROR_OR_SET_SESSION_OPEN(iPositionServer, iPositionServer.Connect());
00031   iPositionModuleStatusEvent.SetRequestedEvents(TPositionModuleStatusEventBase::EEventDeviceStatus|TPositionModuleStatusEventBase::EEventSystemModuleEvent);
00032 }
00033 
00034 void CPosModuleStatAo::MakeRequest()
00035 {
00036   if (!IsActive()) {
00037     iPositionServer.NotifyModuleStatusEvent(iPositionModuleStatusEvent, iStatus);
00038     SetActive();
00039   }
00040 }
00041 
00042 void CPosModuleStatAo::DoCancel()
00043 {
00044   // Ignoring the undocumented error code.
00045   iPositionServer.CancelRequest(EPositionServerNotifyModuleStatusEvent);
00046 }
00047 
00048 TInt CPosModuleStatAo::RunError(TInt aErrCode)
00049 {
00050   TRAPD(errCode, iObserver.PosModErrorL(aErrCode));
00051   if (errCode)
00052     iObserver.PosModLeave(errCode);
00053   return KErrNone;
00054 }
00055 
00056 void CPosModuleStatAo::PosModChange()
00057 {
00058   TRAPD(errCode, iObserver.PosModChangeL());
00059   if (errCode)
00060     iObserver.PosModLeave(errCode);
00061 }
00062 
00063 // Returns the module ID of the best (and good enough) available
00064 // module. Returns KPositionNullModuleId if nothing suitable is found.
00065 // The 'aModifiers' parameter(s) indicates what kind of a module is
00066 // "best".
00067 TPositionModuleId CPosModuleStatAo::ChooseBestPositionerL(TInt aModifiers)
00068 {
00069   TUint numModules;
00070   User::LeaveIfError(iPositionServer.GetNumModules(numModules));
00071   TUint i;
00072   TPositionModuleInfo moduleInfo;
00073   int bestScore = -1;
00074   int bestIndex = -1;
00075   for (i=0; i<numModules; i++) {
00076     User::LeaveIfError(iPositionServer.GetModuleInfoByIndex(i, moduleInfo));
00077 
00078 #if __DO_LOGGING__
00079     {
00080       TBuf<KPositionMaxModuleName> moduleName;
00081       moduleInfo.GetModuleName(moduleName);
00082       gchar* nameString = ConvToUtf8CStringL(moduleName);
00083       logg("considering positioning module '%s'", nameString);
00084       g_free(nameString);
00085     }
00086 #endif
00087 
00088     TPositionModuleStatus moduleStatus;
00089     TInt moduleStatusError = iPositionServer.GetModuleStatus(moduleStatus, moduleInfo.ModuleId());
00090     
00091     // See lbscommon.h for interpretations for the values.
00092     logg("moduleInfo: %s stat=%d loc=%d tech=%02x caps=%04x",
00093    moduleInfo.IsAvailable() ? "available" : "unavailable",
00094    moduleStatus.DeviceStatus(),
00095    moduleInfo.DeviceLocation(),
00096    moduleInfo.TechnologyType(),
00097    moduleInfo.Capabilities());
00098 
00099     if (moduleInfo.IsAvailable() &&
00100   !moduleStatusError && 
00101   (moduleStatus.DeviceStatus() != TPositionModuleStatus::EDeviceDisabled) &&
00102   (moduleInfo.Capabilities() & TPositionModuleInfo::ECapabilitySatellite) &&
00103   (moduleInfo.TechnologyType() != TPositionModuleInfo::ETechnologyUnknown) &&
00104         // We might want to allow network positioning (particularly
00105         // for WLAN based positioning on devices that support it), but
00106         // it is dangerous as it may involve frequent queries over the
00107         // network. Should at least make sure we are not roaming
00108         // before allowing it. xxx
00109   (moduleInfo.TechnologyType() != TPositionModuleInfo::ETechnologyNetwork) &&
00110   (moduleInfo.DeviceLocation() != TPositionModuleInfo::EDeviceUnknown)) {
00111       int score = 0;
00112       if (moduleInfo.DeviceLocation() == TPositionModuleInfo::EDeviceExternal) {
00113   /*
00114     // Not required: Bluetooth GPS can be disabled globally in
00115           // the device settings. See the Position application in 
00116           // S60 3.0 devices, and the settings dialog in later devices.
00117     if (iPlatformVersion.iMajor == 3 && iPlatformVersion.iMinor == 0)
00118     // Avoid the BT device search dialog.
00119     continue;
00120   */
00121   if (aModifiers & KAllowExternal)
00122     score += 0x100;
00123   else
00124     continue;
00125       }
00126       if (moduleInfo.TechnologyType() == TPositionModuleInfo::ETechnologyAssisted) {
00127   if (aModifiers & KAllowAssisted)
00128     score += 0x10;
00129   else
00130     continue;
00131       }
00132 
00133       // Given the choice between 'Wi-Fi/Network' and 'Network based'
00134       // we would like to favor the former. But they both have the
00135       // same TechnologyType and Capabilities. We could consider
00136       // making better use of TPositionQuality, perhaps that would do
00137       // the trick. Not sure if this code is ever going to be of any
00138       // use.
00139       TPositionQuality quality;
00140       moduleInfo.GetPositionQuality(quality);
00141       TReal32 accuracy = quality.VerticalAccuracy();
00142       if (!Math::IsNaN(accuracy)) {
00143   //logg("vertical accuracy %g", accuracy);
00144   score += 0x1; // bonus for having some accuracy value
00145       }
00146 
00147       logg("module score is %d", score);
00148       if (score > bestScore) {
00149   bestScore = score;
00150   bestIndex = i;
00151       }
00152     }
00153   }
00154   if (bestIndex >= 0) {
00155     User::LeaveIfError(iPositionServer.GetModuleInfoByIndex(bestIndex, moduleInfo));
00156 
00157     {
00158       TBuf<KPositionMaxModuleName> moduleName;
00159       moduleInfo.GetModuleName(moduleName);
00160       gchar* nameString = ConvToUtf8CStringL(moduleName);
00161       dblogg("chose positioning module '%s'", nameString);
00162       guilogf("gps: chose module '%s'", nameString);
00163       g_free(nameString);
00164     }
00165 
00166     return moduleInfo.ModuleId();
00167   }
00168   return KPositionNullModuleId;
00169 }
00170 
00171 static TBool DeviceNotAvailable(TPositionModuleStatus::TDeviceStatus deviceStatus)
00172 {
00173   return ((deviceStatus == TPositionModuleStatus::EDeviceUnknown) ||
00174     (deviceStatus == TPositionModuleStatus::EDeviceDisabled) ||
00175     (deviceStatus == TPositionModuleStatus::EDeviceError));
00176 }
00177 
00178 void CPosModuleStatAo::RunL()
00179 {
00180   TInt errCode = iStatus.Int();
00181   logg("positioning module status event (%d)", errCode);
00182 
00183   if (errCode) {
00184     RunError(errCode);
00185     return;
00186   }
00187 
00188   // We are interested in these kinds of events:
00189   // * current module is removed
00190   // * currently used module stops working in some way
00191   // * some other (possibly better) module becomes available
00192   // * a new (possibly better) module is installed
00193   // Note also that there might not be a current module at all.
00194 
00195   TPositionModuleId moduleId = iPositionModuleStatusEvent.ModuleId();
00196   assert(moduleId != KPositionNullModuleId);
00197 
00198   TBool aboutCurrent = iObserver.PosModIsCurrent(moduleId);
00199 
00200   TPositionModuleStatus moduleStatus;
00201   iPositionModuleStatusEvent.GetModuleStatus(moduleStatus);
00202     
00203   TPositionModuleStatusEventBase::TModuleEvent occurredEvents = 
00204     iPositionModuleStatusEvent.OccurredEvents();
00205   logg("occurred position events: %d", (int)occurredEvents);
00206 
00207   if (occurredEvents & TPositionModuleStatusEventBase::EEventDeviceStatus) {
00208     TPositionModuleStatus::TDeviceStatus deviceStatus = 
00209       moduleStatus.DeviceStatus();
00210 #if __DO_LOGGING__
00211     const char* deviceStatusStr;
00212     switch (deviceStatus)
00213       {
00214       case TPositionModuleStatus::EDeviceUnknown:
00215   {
00216     deviceStatusStr = "EDeviceUnknown";
00217     break;
00218   }
00219       case TPositionModuleStatus::EDeviceError:
00220   {
00221     deviceStatusStr = "EDeviceError";
00222     break;
00223   }
00224       case TPositionModuleStatus::EDeviceDisabled:
00225   {
00226     deviceStatusStr = "EDeviceDisabled";
00227     break;
00228   }
00229       case TPositionModuleStatus::EDeviceInactive:
00230   {
00231     deviceStatusStr = "EDeviceInactive";
00232     break;
00233   }
00234       case TPositionModuleStatus::EDeviceInitialising:
00235   {
00236     deviceStatusStr = "EDeviceInitialising";
00237     break;
00238   }
00239       case TPositionModuleStatus::EDeviceStandBy:
00240   {
00241     deviceStatusStr = "EDeviceStandBy";
00242     break;
00243   }
00244       case TPositionModuleStatus::EDeviceReady:
00245   {
00246     deviceStatusStr = "EDeviceReady";
00247     break;
00248   }
00249       case TPositionModuleStatus::EDeviceActive:
00250   {
00251     deviceStatusStr = "EDeviceActive";
00252     break;
00253   }
00254       default:
00255   {
00256     deviceStatusStr = "<unknown>";
00257     break;
00258   }
00259       }
00260       
00261     logg("%s device status now %d (%s)", 
00262    aboutCurrent ? "current" : "other", 
00263    deviceStatus, deviceStatusStr);
00264 #endif
00265     if (aboutCurrent && DeviceNotAvailable(deviceStatus)) {
00266       PosModChange(); // current module unavailable
00267     } else if (!aboutCurrent && !DeviceNotAvailable(deviceStatus)) {
00268       // May not be mean that it actually is new, but recompute best
00269       // one anyway.
00270       PosModChange(); // new module available
00271     }
00272   }
00273 
00274   // Can it ever really happen that we get both a system module event
00275   // and a non-system module event? Doesn't matter, we handle it all
00276   // the same way.
00277   if (occurredEvents & TPositionModuleStatusEventBase::EEventSystemModuleEvent) {
00278     TPositionModuleStatusEventBase::TSystemModuleEvent systemModuleEvent = 
00279       iPositionModuleStatusEvent.SystemModuleEvent();
00280     logg("system module event was %d", (int)systemModuleEvent);
00281     if (aboutCurrent &&
00282   ((systemModuleEvent == TPositionModuleStatusEventBase::ESystemError) || 
00283    (systemModuleEvent == TPositionModuleStatusEventBase::ESystemModuleRemoved))) {
00284       PosModChange(); // current module unavailable
00285     } else if (!aboutCurrent &&
00286          ((systemModuleEvent == TPositionModuleStatusEventBase::ESystemModuleInstalled))) {
00287       PosModChange(); // new module available
00288     }
00289   }
00290 }
00291 
00292 /**
00293 
00294 Copyright 2009-2011 Helsinki Institute for Information Technology
00295 (HIIT) and the authors. All rights reserved.
00296 
00297 Authors: Tero Hasu <tero.hasu@hut.fi>
00298 
00299 Permission is hereby granted, free of charge, to any person
00300 obtaining a copy of this software and associated documentation files
00301 (the "Software"), to deal in the Software without restriction,
00302 including without limitation the rights to use, copy, modify, merge,
00303 publish, distribute, sublicense, and/or sell copies of the Software,
00304 and to permit persons to whom the Software is furnished to do so,
00305 subject to the following conditions:
00306 
00307 The above copyright notice and this permission notice shall be
00308 included in all copies or substantial portions of the Software.
00309 
00310 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00311 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00312 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00313 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
00314 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00315 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00316 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00317 SOFTWARE.
00318 
00319  **/
00320 

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:52 2011 by Doxygen 1.6.1