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