1/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation, nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#define LOG_TAG "LocSvc_SystemStatus"
30
31#include <string>
32#include <stdlib.h>
33#include <string.h>
34#include <sys/time.h>
35#include <pthread.h>
36#include <platform_lib_log_util.h>
37#include <loc_nmea.h>
38#include <SystemStatus.h>
39
40namespace loc_core
41{
42
43/******************************************************************************
44 SystemStatusNmeaBase - base class for all NMEA parsers
45******************************************************************************/
46class SystemStatusNmeaBase
47{
48protected:
49    std::vector<std::string> mField;
50
51    SystemStatusNmeaBase(const char *str_in, uint32_t len_in)
52    {
53        // check size and talker
54        if (!loc_nmea_is_debug(str_in, len_in)) {
55            return;
56        }
57
58        std::string parser(str_in);
59        std::string::size_type index = 0;
60
61        // verify checksum field
62        index = parser.find("*");
63        if (index == std::string::npos) {
64            return;
65        }
66        parser[index] = ',';
67
68        // tokenize parser
69        while (1) {
70            std::string str;
71            index = parser.find(",");
72            if (index == std::string::npos) {
73                break;
74            }
75            str = parser.substr(0, index);
76            parser = parser.substr(index + 1);
77            mField.push_back(str);
78        }
79    }
80
81    virtual ~SystemStatusNmeaBase() { }
82
83public:
84    static const uint32_t NMEA_MINSIZE = DEBUG_NMEA_MINSIZE;
85    static const uint32_t NMEA_MAXSIZE = DEBUG_NMEA_MAXSIZE;
86};
87
88/******************************************************************************
89 SystemStatusPQWM1
90******************************************************************************/
91class SystemStatusPQWM1
92{
93public:
94    uint16_t mGpsWeek;    // x1
95    uint32_t mGpsTowMs;   // x2
96    uint8_t  mTimeValid;  // x3
97    uint8_t  mTimeSource; // x4
98    int32_t  mTimeUnc;    // x5
99    int32_t  mClockFreqBias; // x6
100    int32_t  mClockFreqBiasUnc; // x7
101    uint8_t  mXoState;    // x8
102    int32_t  mPgaGain;    // x9
103    uint32_t mGpsBpAmpI;  // xA
104    uint32_t mGpsBpAmpQ;  // xB
105    uint32_t mAdcI;       // xC
106    uint32_t mAdcQ;       // xD
107    uint32_t mJammerGps;  // xE
108    uint32_t mJammerGlo;  // xF
109    uint32_t mJammerBds;  // x10
110    uint32_t mJammerGal;  // x11
111    uint32_t mRecErrorRecovery; // x12
112    double   mAgcGps;     // x13
113    double   mAgcGlo;     // x14
114    double   mAgcBds;     // x15
115    double   mAgcGal;     // x16
116    int32_t  mLeapSeconds;// x17
117    int32_t  mLeapSecUnc; // x18
118};
119
120// parser
121class SystemStatusPQWM1parser : public SystemStatusNmeaBase
122{
123private:
124    enum
125    {
126        eTalker = 0,
127        eGpsWeek = 1,
128        eGpsTowMs = 2,
129        eTimeValid = 3,
130        eTimeSource = 4,
131        eTimeUnc = 5,
132        eClockFreqBias = 6,
133        eClockFreqBiasUnc = 7,
134        eXoState = 8,
135        ePgaGain = 9,
136        eGpsBpAmpI = 10,
137        eGpsBpAmpQ = 11,
138        eAdcI = 12,
139        eAdcQ = 13,
140        eJammerGps = 14,
141        eJammerGlo = 15,
142        eJammerBds = 16,
143        eJammerGal = 17,
144        eRecErrorRecovery = 18,
145        eAgcGps = 19,
146        eAgcGlo = 20,
147        eAgcBds = 21,
148        eAgcGal = 22,
149        eLeapSeconds = 23,
150        eLeapSecUnc = 24,
151        eMax
152    };
153    SystemStatusPQWM1 mM1;
154
155public:
156    inline uint16_t   getGpsWeek()    { return mM1.mGpsWeek; }
157    inline uint32_t   getGpsTowMs()   { return mM1.mGpsTowMs; }
158    inline uint8_t    getTimeValid()  { return mM1.mTimeValid; }
159    inline uint8_t    getTimeSource() { return mM1.mTimeSource; }
160    inline int32_t    getTimeUnc()    { return mM1.mTimeUnc; }
161    inline int32_t    getClockFreqBias() { return mM1.mClockFreqBias; }
162    inline int32_t    getClockFreqBiasUnc() { return mM1.mClockFreqBiasUnc; }
163    inline uint8_t    getXoState()    { return mM1.mXoState;}
164    inline int32_t    getPgaGain()    { return mM1.mPgaGain;          }
165    inline uint32_t   getGpsBpAmpI()  { return mM1.mGpsBpAmpI;        }
166    inline uint32_t   getGpsBpAmpQ()  { return mM1.mGpsBpAmpQ;        }
167    inline uint32_t   getAdcI()       { return mM1.mAdcI;             }
168    inline uint32_t   getAdcQ()       { return mM1.mAdcQ;             }
169    inline uint32_t   getJammerGps()  { return mM1.mJammerGps;        }
170    inline uint32_t   getJammerGlo()  { return mM1.mJammerGlo;        }
171    inline uint32_t   getJammerBds()  { return mM1.mJammerBds;        }
172    inline uint32_t   getJammerGal()  { return mM1.mJammerGal;        }
173    inline uint32_t   getAgcGps()     { return mM1.mAgcGps;           }
174    inline uint32_t   getAgcGlo()     { return mM1.mAgcGlo;           }
175    inline uint32_t   getAgcBds()     { return mM1.mAgcBds;           }
176    inline uint32_t   getAgcGal()     { return mM1.mAgcGal;           }
177    inline uint32_t   getRecErrorRecovery() { return mM1.mRecErrorRecovery; }
178    inline int32_t    getLeapSeconds(){ return mM1.mLeapSeconds; }
179    inline int32_t    getLeapSecUnc() { return mM1.mLeapSecUnc; }
180
181    SystemStatusPQWM1parser(const char *str_in, uint32_t len_in)
182        : SystemStatusNmeaBase(str_in, len_in)
183    {
184        memset(&mM1, 0, sizeof(mM1));
185        if (mField.size() < eMax) {
186            LOC_LOGE("PQWM1parser - invalid size=%d", mField.size());
187            mM1.mTimeValid = 0;
188            return;
189        }
190        mM1.mGpsWeek = atoi(mField[eGpsWeek].c_str());
191        mM1.mGpsTowMs = atoi(mField[eGpsTowMs].c_str());
192        mM1.mTimeValid = atoi(mField[eTimeValid].c_str());
193        mM1.mTimeSource = atoi(mField[eTimeSource].c_str());
194        mM1.mTimeUnc = atoi(mField[eTimeUnc].c_str());
195        mM1.mClockFreqBias = atoi(mField[eClockFreqBias].c_str());
196        mM1.mClockFreqBiasUnc = atoi(mField[eClockFreqBiasUnc].c_str());
197        mM1.mXoState = atoi(mField[eXoState].c_str());
198        mM1.mPgaGain = atoi(mField[ePgaGain].c_str());
199        mM1.mGpsBpAmpI = atoi(mField[eGpsBpAmpI].c_str());
200        mM1.mGpsBpAmpQ = atoi(mField[eGpsBpAmpQ].c_str());
201        mM1.mAdcI = atoi(mField[eAdcI].c_str());
202        mM1.mAdcQ = atoi(mField[eAdcQ].c_str());
203        mM1.mJammerGps = atoi(mField[eJammerGps].c_str());
204        mM1.mJammerGlo = atoi(mField[eJammerGlo].c_str());
205        mM1.mJammerBds = atoi(mField[eJammerBds].c_str());
206        mM1.mJammerGal = atoi(mField[eJammerGal].c_str());
207        mM1.mRecErrorRecovery = atoi(mField[eRecErrorRecovery].c_str());
208        mM1.mAgcGps = atof(mField[eAgcGps].c_str());
209        mM1.mAgcGlo = atof(mField[eAgcGlo].c_str());
210        mM1.mAgcBds = atof(mField[eAgcBds].c_str());
211        mM1.mAgcGal = atof(mField[eAgcGal].c_str());
212        mM1.mLeapSeconds = atoi(mField[eLeapSeconds].c_str());
213        mM1.mLeapSecUnc = atoi(mField[eLeapSecUnc].c_str());
214    }
215
216    inline SystemStatusPQWM1& get() { return mM1;} //getparser
217};
218
219/******************************************************************************
220 SystemStatusPQWP1
221******************************************************************************/
222class SystemStatusPQWP1
223{
224public:
225    uint8_t  mEpiValidity; // x4
226    float    mEpiLat;    // x5
227    float    mEpiLon;    // x6
228    float    mEpiAlt;    // x7
229    float    mEpiHepe;   // x8
230    float    mEpiAltUnc; // x9
231    uint8_t  mEpiSrc;    // x10
232};
233
234class SystemStatusPQWP1parser : public SystemStatusNmeaBase
235{
236private:
237    enum
238    {
239        eTalker = 0,
240        eUtcTime = 1,
241        eEpiValidity = 2,
242        eEpiLat = 3,
243        eEpiLon = 4,
244        eEpiAlt = 5,
245        eEpiHepe = 6,
246        eEpiAltUnc = 7,
247        eEpiSrc = 8,
248        eMax
249    };
250    SystemStatusPQWP1 mP1;
251
252public:
253    inline uint8_t    getEpiValidity() { return mP1.mEpiValidity;      }
254    inline float      getEpiLat() { return mP1.mEpiLat;           }
255    inline float      getEpiLon() { return mP1.mEpiLon;           }
256    inline float      getEpiAlt() { return mP1.mEpiAlt;           }
257    inline float      getEpiHepe() { return mP1.mEpiHepe;          }
258    inline float      getEpiAltUnc() { return mP1.mEpiAltUnc;        }
259    inline uint8_t    getEpiSrc() { return mP1.mEpiSrc;           }
260
261    SystemStatusPQWP1parser(const char *str_in, uint32_t len_in)
262        : SystemStatusNmeaBase(str_in, len_in)
263    {
264        if (mField.size() < eMax) {
265            return;
266        }
267        memset(&mP1, 0, sizeof(mP1));
268        mP1.mEpiValidity = strtol(mField[eEpiValidity].c_str(), NULL, 16);
269        mP1.mEpiLat = atof(mField[eEpiLat].c_str());
270        mP1.mEpiLon = atof(mField[eEpiLon].c_str());
271        mP1.mEpiAlt = atof(mField[eEpiAlt].c_str());
272        mP1.mEpiHepe = atoi(mField[eEpiHepe].c_str());
273        mP1.mEpiAltUnc = atof(mField[eEpiAltUnc].c_str());
274        mP1.mEpiSrc = atoi(mField[eEpiSrc].c_str());
275    }
276
277    inline SystemStatusPQWP1& get() { return mP1;}
278};
279
280/******************************************************************************
281 SystemStatusPQWP2
282******************************************************************************/
283class SystemStatusPQWP2
284{
285public:
286    float    mBestLat;   // x4
287    float    mBestLon;   // x5
288    float    mBestAlt;   // x6
289    float    mBestHepe;  // x7
290    float    mBestAltUnc; // x8
291};
292
293class SystemStatusPQWP2parser : public SystemStatusNmeaBase
294{
295private:
296    enum
297    {
298        eTalker = 0,
299        eUtcTime = 1,
300        eBestLat = 2,
301        eBestLon = 3,
302        eBestAlt = 4,
303        eBestHepe = 5,
304        eBestAltUnc = 6,
305        eMax
306    };
307    SystemStatusPQWP2 mP2;
308
309public:
310    inline float      getBestLat() { return mP2.mBestLat;          }
311    inline float      getBestLon() { return mP2.mBestLon;          }
312    inline float      getBestAlt() { return mP2.mBestAlt;          }
313    inline float      getBestHepe() { return mP2.mBestHepe;         }
314    inline float      getBestAltUnc() { return mP2.mBestAltUnc;       }
315
316    SystemStatusPQWP2parser(const char *str_in, uint32_t len_in)
317        : SystemStatusNmeaBase(str_in, len_in)
318    {
319        if (mField.size() < eMax) {
320            return;
321        }
322        memset(&mP2, 0, sizeof(mP2));
323        mP2.mBestLat = atof(mField[eBestLat].c_str());
324        mP2.mBestLon = atof(mField[eBestLon].c_str());
325        mP2.mBestAlt = atof(mField[eBestAlt].c_str());
326        mP2.mBestHepe = atof(mField[eBestHepe].c_str());
327        mP2.mBestAltUnc = atof(mField[eBestAltUnc].c_str());
328    }
329
330    inline SystemStatusPQWP2& get() { return mP2;}
331};
332
333/******************************************************************************
334 SystemStatusPQWP3
335******************************************************************************/
336class SystemStatusPQWP3
337{
338public:
339    uint8_t   mXtraValidMask;
340    uint32_t  mGpsXtraAge;
341    uint32_t  mGloXtraAge;
342    uint32_t  mBdsXtraAge;
343    uint32_t  mGalXtraAge;
344    uint32_t  mQzssXtraAge;
345    uint32_t  mGpsXtraValid;
346    uint32_t  mGloXtraValid;
347    uint64_t  mBdsXtraValid;
348    uint64_t  mGalXtraValid;
349    uint8_t   mQzssXtraValid;
350};
351
352class SystemStatusPQWP3parser : public SystemStatusNmeaBase
353{
354private:
355    enum
356    {
357        eTalker = 0,
358        eUtcTime = 1,
359        eXtraValidMask = 2,
360        eGpsXtraAge = 3,
361        eGloXtraAge = 4,
362        eBdsXtraAge = 5,
363        eGalXtraAge = 6,
364        eQzssXtraAge = 7,
365        eGpsXtraValid = 8,
366        eGloXtraValid = 9,
367        eBdsXtraValid = 10,
368        eGalXtraValid = 11,
369        eQzssXtraValid = 12,
370        eMax
371    };
372    SystemStatusPQWP3 mP3;
373
374public:
375    inline uint8_t    getXtraValid() { return mP3.mXtraValidMask;   }
376    inline uint32_t   getGpsXtraAge() { return mP3.mGpsXtraAge;       }
377    inline uint32_t   getGloXtraAge() { return mP3.mGloXtraAge;       }
378    inline uint32_t   getBdsXtraAge() { return mP3.mBdsXtraAge;       }
379    inline uint32_t   getGalXtraAge() { return mP3.mGalXtraAge;       }
380    inline uint32_t   getQzssXtraAge() { return mP3.mQzssXtraAge;      }
381    inline uint32_t   getGpsXtraValid() { return mP3.mGpsXtraValid;     }
382    inline uint32_t   getGloXtraValid() { return mP3.mGloXtraValid;     }
383    inline uint64_t   getBdsXtraValid() { return mP3.mBdsXtraValid;     }
384    inline uint64_t   getGalXtraValid() { return mP3.mGalXtraValid;     }
385    inline uint8_t    getQzssXtraValid() { return mP3.mQzssXtraValid;    }
386
387    SystemStatusPQWP3parser(const char *str_in, uint32_t len_in)
388        : SystemStatusNmeaBase(str_in, len_in)
389    {
390        if (mField.size() < eMax) {
391            return;
392        }
393        memset(&mP3, 0, sizeof(mP3));
394        mP3.mXtraValidMask = strtol(mField[eXtraValidMask].c_str(), NULL, 16);
395        mP3.mGpsXtraAge = atoi(mField[eGpsXtraAge].c_str());
396        mP3.mGloXtraAge = atoi(mField[eGloXtraAge].c_str());
397        mP3.mBdsXtraAge = atoi(mField[eBdsXtraAge].c_str());
398        mP3.mGalXtraAge = atoi(mField[eGalXtraAge].c_str());
399        mP3.mQzssXtraAge = atoi(mField[eQzssXtraAge].c_str());
400        mP3.mGpsXtraValid = strtol(mField[eGpsXtraValid].c_str(), NULL, 16);
401        mP3.mGloXtraValid = strtol(mField[eGloXtraValid].c_str(), NULL, 16);
402        mP3.mBdsXtraValid = strtol(mField[eBdsXtraValid].c_str(), NULL, 16);
403        mP3.mGalXtraValid = strtol(mField[eGalXtraValid].c_str(), NULL, 16);
404        mP3.mQzssXtraValid = strtol(mField[eQzssXtraValid].c_str(), NULL, 16);
405    }
406
407    inline SystemStatusPQWP3& get() { return mP3;}
408};
409
410/******************************************************************************
411 SystemStatusPQWP4
412******************************************************************************/
413class SystemStatusPQWP4
414{
415public:
416    uint32_t  mGpsEpheValid;
417    uint32_t  mGloEpheValid;
418    uint64_t  mBdsEpheValid;
419    uint64_t  mGalEpheValid;
420    uint8_t   mQzssEpheValid;
421};
422
423class SystemStatusPQWP4parser : public SystemStatusNmeaBase
424{
425private:
426    enum
427    {
428        eTalker = 0,
429        eUtcTime = 1,
430        eGpsEpheValid = 2,
431        eGloEpheValid = 3,
432        eBdsEpheValid = 4,
433        eGalEpheValid = 5,
434        eQzssEpheValid = 6,
435        eMax
436    };
437    SystemStatusPQWP4 mP4;
438
439public:
440    inline uint32_t   getGpsEpheValid() { return mP4.mGpsEpheValid;     }
441    inline uint32_t   getGloEpheValid() { return mP4.mGloEpheValid;     }
442    inline uint64_t   getBdsEpheValid() { return mP4.mBdsEpheValid;     }
443    inline uint64_t   getGalEpheValid() { return mP4.mGalEpheValid;     }
444    inline uint8_t    getQzssEpheValid() { return mP4.mQzssEpheValid;    }
445
446    SystemStatusPQWP4parser(const char *str_in, uint32_t len_in)
447        : SystemStatusNmeaBase(str_in, len_in)
448    {
449        if (mField.size() < eMax) {
450            return;
451        }
452        memset(&mP4, 0, sizeof(mP4));
453        mP4.mGpsEpheValid = strtol(mField[eGpsEpheValid].c_str(), NULL, 16);
454        mP4.mGloEpheValid = strtol(mField[eGloEpheValid].c_str(), NULL, 16);
455        mP4.mBdsEpheValid = strtol(mField[eBdsEpheValid].c_str(), NULL, 16);
456        mP4.mGalEpheValid = strtol(mField[eGalEpheValid].c_str(), NULL, 16);
457        mP4.mQzssEpheValid = strtol(mField[eQzssEpheValid].c_str(), NULL, 16);
458    }
459
460    inline SystemStatusPQWP4& get() { return mP4;}
461};
462
463/******************************************************************************
464 SystemStatusPQWP5
465******************************************************************************/
466class SystemStatusPQWP5
467{
468public:
469    uint32_t  mGpsUnknownMask;
470    uint32_t  mGloUnknownMask;
471    uint64_t  mBdsUnknownMask;
472    uint64_t  mGalUnknownMask;
473    uint8_t   mQzssUnknownMask;
474    uint32_t  mGpsGoodMask;
475    uint32_t  mGloGoodMask;
476    uint64_t  mBdsGoodMask;
477    uint64_t  mGalGoodMask;
478    uint8_t   mQzssGoodMask;
479    uint32_t  mGpsBadMask;
480    uint32_t  mGloBadMask;
481    uint64_t  mBdsBadMask;
482    uint64_t  mGalBadMask;
483    uint8_t   mQzssBadMask;
484};
485
486class SystemStatusPQWP5parser : public SystemStatusNmeaBase
487{
488private:
489    enum
490    {
491        eTalker = 0,
492        eUtcTime = 1,
493        eGpsUnknownMask = 2,
494        eGloUnknownMask = 3,
495        eBdsUnknownMask = 4,
496        eGalUnknownMask = 5,
497        eQzssUnknownMask = 6,
498        eGpsGoodMask = 7,
499        eGloGoodMask = 8,
500        eBdsGoodMask = 9,
501        eGalGoodMask = 10,
502        eQzssGoodMask = 11,
503        eGpsBadMask = 12,
504        eGloBadMask = 13,
505        eBdsBadMask = 14,
506        eGalBadMask = 15,
507        eQzssBadMask = 16,
508        eMax
509    };
510    SystemStatusPQWP5 mP5;
511
512public:
513    inline uint32_t   getGpsUnknownMask() { return mP5.mGpsUnknownMask;   }
514    inline uint32_t   getGloUnknownMask() { return mP5.mGloUnknownMask;   }
515    inline uint64_t   getBdsUnknownMask() { return mP5.mBdsUnknownMask;   }
516    inline uint64_t   getGalUnknownMask() { return mP5.mGalUnknownMask;   }
517    inline uint8_t    getQzssUnknownMask() { return mP5.mQzssUnknownMask;  }
518    inline uint32_t   getGpsGoodMask() { return mP5.mGpsGoodMask;      }
519    inline uint32_t   getGloGoodMask() { return mP5.mGloGoodMask;      }
520    inline uint64_t   getBdsGoodMask() { return mP5.mBdsGoodMask;      }
521    inline uint64_t   getGalGoodMask() { return mP5.mGalGoodMask;      }
522    inline uint8_t    getQzssGoodMask() { return mP5.mQzssGoodMask;     }
523    inline uint32_t   getGpsBadMask() { return mP5.mGpsBadMask;       }
524    inline uint32_t   getGloBadMask() { return mP5.mGloBadMask;       }
525    inline uint64_t   getBdsBadMask() { return mP5.mBdsBadMask;       }
526    inline uint64_t   getGalBadMask() { return mP5.mGalBadMask;       }
527    inline uint8_t    getQzssBadMask() { return mP5.mQzssBadMask;      }
528
529    SystemStatusPQWP5parser(const char *str_in, uint32_t len_in)
530        : SystemStatusNmeaBase(str_in, len_in)
531    {
532        if (mField.size() < eMax) {
533            return;
534        }
535        memset(&mP5, 0, sizeof(mP5));
536        mP5.mGpsUnknownMask = strtol(mField[eGpsUnknownMask].c_str(), NULL, 16);
537        mP5.mGloUnknownMask = strtol(mField[eGloUnknownMask].c_str(), NULL, 16);
538        mP5.mBdsUnknownMask = strtol(mField[eBdsUnknownMask].c_str(), NULL, 16);
539        mP5.mGalUnknownMask = strtol(mField[eGalUnknownMask].c_str(), NULL, 16);
540        mP5.mQzssUnknownMask = strtol(mField[eQzssUnknownMask].c_str(), NULL, 16);
541        mP5.mGpsGoodMask = strtol(mField[eGpsGoodMask].c_str(), NULL, 16);
542        mP5.mGloGoodMask = strtol(mField[eGloGoodMask].c_str(), NULL, 16);
543        mP5.mBdsGoodMask = strtol(mField[eBdsGoodMask].c_str(), NULL, 16);
544        mP5.mGalGoodMask = strtol(mField[eGalGoodMask].c_str(), NULL, 16);
545        mP5.mQzssGoodMask = strtol(mField[eQzssGoodMask].c_str(), NULL, 16);
546        mP5.mGpsBadMask = strtol(mField[eGpsBadMask].c_str(), NULL, 16);
547        mP5.mGloBadMask = strtol(mField[eGloBadMask].c_str(), NULL, 16);
548        mP5.mBdsBadMask = strtol(mField[eBdsBadMask].c_str(), NULL, 16);
549        mP5.mGalBadMask = strtol(mField[eGalBadMask].c_str(), NULL, 16);
550        mP5.mQzssBadMask = strtol(mField[eQzssBadMask].c_str(), NULL, 16);
551    }
552
553    inline SystemStatusPQWP5& get() { return mP5;}
554};
555
556/******************************************************************************
557 SystemStatusPQWP6parser
558******************************************************************************/
559class SystemStatusPQWP6
560{
561public:
562    uint32_t  mFixInfoMask;
563};
564
565class SystemStatusPQWP6parser : public SystemStatusNmeaBase
566{
567private:
568    enum
569    {
570        eTalker = 0,
571        eUtcTime = 1,
572        eFixInfoMask = 2,
573        eMax
574    };
575    SystemStatusPQWP6 mP6;
576
577public:
578    inline uint32_t   getFixInfoMask() { return mP6.mFixInfoMask;      }
579
580    SystemStatusPQWP6parser(const char *str_in, uint32_t len_in)
581        : SystemStatusNmeaBase(str_in, len_in)
582    {
583        if (mField.size() < eMax) {
584            return;
585        }
586        memset(&mP6, 0, sizeof(mP6));
587        mP6.mFixInfoMask = strtol(mField[eFixInfoMask].c_str(), NULL, 16);
588    }
589
590    inline SystemStatusPQWP6& get() { return mP6;}
591};
592
593/******************************************************************************
594 SystemStatusPQWP7parser
595******************************************************************************/
596class SystemStatusPQWP7
597{
598public:
599    SystemStatusNav mNav[SV_ALL_NUM];
600};
601
602class SystemStatusPQWP7parser : public SystemStatusNmeaBase
603{
604private:
605    enum
606    {
607        eTalker = 0,
608        eUtcTime = 1,
609        eMax = 2 + SV_ALL_NUM*3
610    };
611    SystemStatusPQWP7 mP7;
612
613public:
614    SystemStatusPQWP7parser(const char *str_in, uint32_t len_in)
615        : SystemStatusNmeaBase(str_in, len_in)
616    {
617        if (mField.size() < eMax) {
618            LOC_LOGE("PQWP7parser - invalid size=%d", mField.size());
619            return;
620        }
621        for (uint32_t i=0; i<SV_ALL_NUM; i++) {
622            mP7.mNav[i].mType   = GnssEphemerisType(atoi(mField[i*3+2].c_str()));
623            mP7.mNav[i].mSource = GnssEphemerisSource(atoi(mField[i*3+3].c_str()));
624            mP7.mNav[i].mAgeSec = atoi(mField[i*3+4].c_str());
625        }
626    }
627
628    inline SystemStatusPQWP7& get() { return mP7;}
629};
630
631/******************************************************************************
632 SystemStatusPQWS1parser
633******************************************************************************/
634class SystemStatusPQWS1
635{
636public:
637    uint32_t  mFixInfoMask;
638    uint32_t  mHepeLimit;
639};
640
641class SystemStatusPQWS1parser : public SystemStatusNmeaBase
642{
643private:
644    enum
645    {
646        eTalker = 0,
647        eUtcTime = 1,
648        eFixInfoMask = 2,
649        eHepeLimit = 3,
650        eMax
651    };
652    SystemStatusPQWS1 mS1;
653
654public:
655    inline uint16_t   getFixInfoMask() { return mS1.mFixInfoMask;      }
656    inline uint32_t   getHepeLimit()   { return mS1.mHepeLimit;      }
657
658    SystemStatusPQWS1parser(const char *str_in, uint32_t len_in)
659        : SystemStatusNmeaBase(str_in, len_in)
660    {
661        if (mField.size() < eMax) {
662            return;
663        }
664        memset(&mS1, 0, sizeof(mS1));
665        mS1.mFixInfoMask = atoi(mField[eFixInfoMask].c_str());
666        mS1.mHepeLimit = atoi(mField[eHepeLimit].c_str());
667    }
668
669    inline SystemStatusPQWS1& get() { return mS1;}
670};
671
672/******************************************************************************
673 SystemStatusTimeAndClock
674******************************************************************************/
675SystemStatusTimeAndClock::SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea) :
676    mGpsWeek(nmea.mGpsWeek),
677    mGpsTowMs(nmea.mGpsTowMs),
678    mTimeValid(nmea.mTimeValid),
679    mTimeSource(nmea.mTimeSource),
680    mTimeUnc(nmea.mTimeUnc),
681    mClockFreqBias(nmea.mClockFreqBias),
682    mClockFreqBiasUnc(nmea.mClockFreqBiasUnc),
683    mLeapSeconds(nmea.mLeapSeconds),
684    mLeapSecUnc(nmea.mLeapSecUnc)
685{
686}
687
688bool SystemStatusTimeAndClock::equals(SystemStatusTimeAndClock& peer)
689{
690    if ((mGpsWeek != peer.mGpsWeek) ||
691        (mGpsTowMs != peer.mGpsTowMs) ||
692        (mTimeValid != peer.mTimeValid) ||
693        (mTimeSource != peer.mTimeSource) ||
694        (mTimeUnc != peer.mTimeUnc) ||
695        (mClockFreqBias != peer.mClockFreqBias) ||
696        (mClockFreqBiasUnc != peer.mClockFreqBiasUnc) ||
697        (mLeapSeconds != peer.mLeapSeconds) ||
698        (mLeapSecUnc != peer.mLeapSecUnc)) {
699        return false;
700    }
701    return true;
702}
703
704void SystemStatusTimeAndClock::dump()
705{
706    LOC_LOGV("TimeAndClock: u=%ld:%ld g=%d:%d v=%d ts=%d tu=%d b=%d bu=%d ls=%d lu=%d",
707             mUtcTime.tv_sec, mUtcTime.tv_nsec,
708             mGpsWeek,
709             mGpsTowMs,
710             mTimeValid,
711             mTimeSource,
712             mTimeUnc,
713             mClockFreqBias,
714             mClockFreqBiasUnc,
715             mLeapSeconds,
716             mLeapSecUnc);
717    return;
718}
719
720/******************************************************************************
721 SystemStatusXoState
722******************************************************************************/
723SystemStatusXoState::SystemStatusXoState(const SystemStatusPQWM1& nmea) :
724    mXoState(nmea.mXoState)
725{
726}
727
728bool SystemStatusXoState::equals(SystemStatusXoState& peer)
729{
730    if (mXoState != peer.mXoState) {
731        return false;
732    }
733    return true;
734}
735
736void SystemStatusXoState::dump()
737{
738    LOC_LOGV("XoState: u=%ld:%ld x=%d",
739             mUtcTime.tv_sec, mUtcTime.tv_nsec,
740             mXoState);
741    return;
742}
743
744/******************************************************************************
745 SystemStatusRfAndParams
746******************************************************************************/
747SystemStatusRfAndParams::SystemStatusRfAndParams(const SystemStatusPQWM1& nmea) :
748    mPgaGain(nmea.mPgaGain),
749    mGpsBpAmpI(nmea.mGpsBpAmpI),
750    mGpsBpAmpQ(nmea.mGpsBpAmpQ),
751    mAdcI(nmea.mAdcI),
752    mAdcQ(nmea.mAdcQ),
753    mJammerGps(nmea.mJammerGps),
754    mJammerGlo(nmea.mJammerGlo),
755    mJammerBds(nmea.mJammerBds),
756    mJammerGal(nmea.mJammerGal),
757    mAgcGps(nmea.mAgcGps),
758    mAgcGlo(nmea.mAgcGlo),
759    mAgcBds(nmea.mAgcBds),
760    mAgcGal(nmea.mAgcGal)
761{
762}
763
764bool SystemStatusRfAndParams::equals(SystemStatusRfAndParams& peer)
765{
766    if ((mPgaGain != peer.mPgaGain) ||
767        (mGpsBpAmpI != peer.mGpsBpAmpI) ||
768        (mGpsBpAmpQ != peer.mGpsBpAmpQ) ||
769        (mAdcI != peer.mAdcI) ||
770        (mAdcQ != peer.mAdcQ) ||
771        (mJammerGps != peer.mJammerGps) ||
772        (mJammerGlo != peer.mJammerGlo) ||
773        (mJammerBds != peer.mJammerBds) ||
774        (mJammerGal != peer.mJammerGal) ||
775        (mAgcGps != peer.mAgcGps) ||
776        (mAgcGlo != peer.mAgcGlo) ||
777        (mAgcBds != peer.mAgcBds) ||
778        (mAgcGal != peer.mAgcGal)) {
779        return false;
780    }
781    return true;
782}
783
784void SystemStatusRfAndParams::dump()
785{
786    LOC_LOGV("RfAndParams: u=%ld:%ld p=%d bi=%d bq=%d ai=%d aq=%d "
787             "jgp=%d jgl=%d jbd=%d jga=%d "
788             "agp=%lf agl=%lf abd=%lf aga=%lf",
789             mUtcTime.tv_sec, mUtcTime.tv_nsec,
790             mPgaGain,
791             mGpsBpAmpI,
792             mGpsBpAmpQ,
793             mAdcI,
794             mAdcQ,
795             mJammerGps,
796             mJammerGlo,
797             mJammerBds,
798             mJammerGal,
799             mAgcGps,
800             mAgcGlo,
801             mAgcBds,
802             mAgcGal);
803    return;
804}
805
806/******************************************************************************
807 SystemStatusErrRecovery
808******************************************************************************/
809SystemStatusErrRecovery::SystemStatusErrRecovery(const SystemStatusPQWM1& nmea) :
810    mRecErrorRecovery(nmea.mRecErrorRecovery)
811{
812}
813
814bool SystemStatusErrRecovery::equals(SystemStatusErrRecovery& peer)
815{
816    if (mRecErrorRecovery != peer.mRecErrorRecovery) {
817        return false;
818    }
819    return true;
820}
821
822void SystemStatusErrRecovery::dump()
823{
824    LOC_LOGV("ErrRecovery: u=%ld:%ld e=%d",
825             mUtcTime.tv_sec, mUtcTime.tv_nsec,
826             mRecErrorRecovery);
827    return;
828}
829
830/******************************************************************************
831 SystemStatusInjectedPosition
832******************************************************************************/
833SystemStatusInjectedPosition::SystemStatusInjectedPosition(const SystemStatusPQWP1& nmea) :
834    mEpiValidity(nmea.mEpiValidity),
835    mEpiLat(nmea.mEpiLat),
836    mEpiLon(nmea.mEpiLon),
837    mEpiAlt(nmea.mEpiAlt),
838    mEpiHepe(nmea.mEpiHepe),
839    mEpiAltUnc(nmea.mEpiAltUnc),
840    mEpiSrc(nmea.mEpiSrc)
841{
842}
843
844bool SystemStatusInjectedPosition::equals(SystemStatusInjectedPosition& peer)
845{
846    if ((mEpiValidity != peer.mEpiValidity) ||
847        (mEpiLat != peer.mEpiLat) ||
848        (mEpiLon != peer.mEpiLon) ||
849        (mEpiAlt != peer.mEpiAlt) ||
850        (mEpiHepe != peer.mEpiHepe) ||
851        (mEpiAltUnc != peer.mEpiAltUnc) ||
852        (mEpiSrc != peer.mEpiSrc)) {
853        return false;
854    }
855    return true;
856}
857
858void SystemStatusInjectedPosition::dump()
859{
860    LOC_LOGV("InjectedPosition: u=%ld:%ld v=%x la=%f lo=%f al=%f he=%f au=%f es=%d",
861             mUtcTime.tv_sec, mUtcTime.tv_nsec,
862             mEpiValidity,
863             mEpiLat,
864             mEpiLon,
865             mEpiAlt,
866             mEpiHepe,
867             mEpiAltUnc,
868             mEpiSrc);
869    return;
870}
871
872/******************************************************************************
873 SystemStatusBestPosition
874******************************************************************************/
875SystemStatusBestPosition::SystemStatusBestPosition(const SystemStatusPQWP2& nmea) :
876    mValid(true),
877    mBestLat(nmea.mBestLat),
878    mBestLon(nmea.mBestLon),
879    mBestAlt(nmea.mBestAlt),
880    mBestHepe(nmea.mBestHepe),
881    mBestAltUnc(nmea.mBestAltUnc)
882{
883}
884
885bool SystemStatusBestPosition::equals(SystemStatusBestPosition& peer)
886{
887    if ((mBestLat != peer.mBestLat) ||
888        (mBestLon != peer.mBestLon) ||
889        (mBestAlt != peer.mBestAlt) ||
890        (mBestHepe != peer.mBestHepe) ||
891        (mBestAltUnc != peer.mBestAltUnc)) {
892        return false;
893    }
894    return true;
895}
896
897void SystemStatusBestPosition::dump()
898{
899    LOC_LOGV("BestPosition: u=%ld:%ld la=%f lo=%f al=%f he=%f au=%f",
900             mUtcTime.tv_sec, mUtcTime.tv_nsec,
901             mBestLat,
902             mBestLon,
903             mBestAlt,
904             mBestHepe,
905             mBestAltUnc);
906    return;
907}
908
909/******************************************************************************
910 SystemStatusXtra
911******************************************************************************/
912SystemStatusXtra::SystemStatusXtra(const SystemStatusPQWP3& nmea) :
913    mXtraValidMask(nmea.mXtraValidMask),
914    mGpsXtraAge(nmea.mGpsXtraAge),
915    mGloXtraAge(nmea.mGloXtraAge),
916    mBdsXtraAge(nmea.mBdsXtraAge),
917    mGalXtraAge(nmea.mGalXtraAge),
918    mQzssXtraAge(nmea.mQzssXtraAge),
919    mGpsXtraValid(nmea.mGpsXtraValid),
920    mGloXtraValid(nmea.mGloXtraValid),
921    mBdsXtraValid(nmea.mBdsXtraValid),
922    mGalXtraValid(nmea.mGalXtraValid),
923    mQzssXtraValid(nmea.mQzssXtraValid)
924{
925}
926
927bool SystemStatusXtra::equals(SystemStatusXtra& peer)
928{
929    if ((mXtraValidMask != peer.mXtraValidMask) ||
930        (mGpsXtraAge != peer.mGpsXtraAge) ||
931        (mGloXtraAge != peer.mGloXtraAge) ||
932        (mBdsXtraAge != peer.mBdsXtraAge) ||
933        (mGalXtraAge != peer.mGalXtraAge) ||
934        (mQzssXtraAge != peer.mQzssXtraAge) ||
935        (mGpsXtraValid != peer.mGpsXtraValid) ||
936        (mGloXtraValid != peer.mGloXtraValid) ||
937        (mBdsXtraValid != peer.mBdsXtraValid) ||
938        (mGalXtraValid != peer.mGalXtraValid) ||
939        (mQzssXtraValid != peer.mQzssXtraValid)) {
940        return false;
941    }
942    return true;
943}
944
945void SystemStatusXtra::dump()
946{
947    LOC_LOGV("SystemStatusXtra: u=%ld:%ld m=%x a=%d:%d:%d:%d:%d v=%x:%x:%x:%x:%x",
948             mUtcTime.tv_sec, mUtcTime.tv_nsec,
949             mXtraValidMask,
950             mGpsXtraAge,
951             mGloXtraAge,
952             mBdsXtraAge,
953             mGalXtraAge,
954             mQzssXtraAge,
955             mGpsXtraValid,
956             mGloXtraValid,
957             mBdsXtraValid,
958             mGalXtraValid,
959             mQzssXtraValid);
960    return;
961}
962
963/******************************************************************************
964 SystemStatusEphemeris
965******************************************************************************/
966SystemStatusEphemeris::SystemStatusEphemeris(const SystemStatusPQWP4& nmea) :
967    mGpsEpheValid(nmea.mGpsEpheValid),
968    mGloEpheValid(nmea.mGloEpheValid),
969    mBdsEpheValid(nmea.mBdsEpheValid),
970    mGalEpheValid(nmea.mGalEpheValid),
971    mQzssEpheValid(nmea.mQzssEpheValid)
972{
973}
974
975bool SystemStatusEphemeris::equals(SystemStatusEphemeris& peer)
976{
977    if ((mGpsEpheValid != peer.mGpsEpheValid) ||
978        (mGloEpheValid != peer.mGloEpheValid) ||
979        (mBdsEpheValid != peer.mBdsEpheValid) ||
980        (mGalEpheValid != peer.mGalEpheValid) ||
981        (mQzssEpheValid != peer.mQzssEpheValid)) {
982        return false;
983    }
984    return true;
985}
986
987void SystemStatusEphemeris::dump()
988{
989    LOC_LOGV("Ephemeris: u=%ld:%ld ev=%x:%x:%x:%x:%x",
990             mUtcTime.tv_sec, mUtcTime.tv_nsec,
991             mGpsEpheValid,
992             mGloEpheValid,
993             mBdsEpheValid,
994             mGalEpheValid,
995             mQzssEpheValid);
996    return;
997}
998
999/******************************************************************************
1000 SystemStatusSvHealth
1001******************************************************************************/
1002SystemStatusSvHealth::SystemStatusSvHealth(const SystemStatusPQWP5& nmea) :
1003    mGpsUnknownMask(nmea.mGpsUnknownMask),
1004    mGloUnknownMask(nmea.mGloUnknownMask),
1005    mBdsUnknownMask(nmea.mBdsUnknownMask),
1006    mGalUnknownMask(nmea.mGalUnknownMask),
1007    mQzssUnknownMask(nmea.mQzssUnknownMask),
1008    mGpsGoodMask(nmea.mGpsGoodMask),
1009    mGloGoodMask(nmea.mGloGoodMask),
1010    mBdsGoodMask(nmea.mBdsGoodMask),
1011    mGalGoodMask(nmea.mGalGoodMask),
1012    mQzssGoodMask(nmea.mQzssGoodMask),
1013    mGpsBadMask(nmea.mGpsBadMask),
1014    mGloBadMask(nmea.mGloBadMask),
1015    mBdsBadMask(nmea.mBdsBadMask),
1016    mGalBadMask(nmea.mGalBadMask),
1017    mQzssBadMask(nmea.mQzssBadMask)
1018{
1019}
1020
1021bool SystemStatusSvHealth::equals(SystemStatusSvHealth& peer)
1022{
1023    if ((mGpsUnknownMask != peer.mGpsUnknownMask) ||
1024        (mGloUnknownMask != peer.mGloUnknownMask) ||
1025        (mBdsUnknownMask != peer.mBdsUnknownMask) ||
1026        (mGalUnknownMask != peer.mGalUnknownMask) ||
1027        (mQzssUnknownMask != peer.mQzssUnknownMask) ||
1028        (mGpsGoodMask != peer.mGpsGoodMask) ||
1029        (mGloGoodMask != peer.mGloGoodMask) ||
1030        (mBdsGoodMask != peer.mBdsGoodMask) ||
1031        (mGalGoodMask != peer.mGalGoodMask) ||
1032        (mQzssGoodMask != peer.mQzssGoodMask) ||
1033        (mGpsBadMask != peer.mGpsBadMask) ||
1034        (mGloBadMask != peer.mGloBadMask) ||
1035        (mBdsBadMask != peer.mBdsBadMask) ||
1036        (mGalBadMask != peer.mGalBadMask) ||
1037        (mQzssBadMask != peer.mQzssBadMask)) {
1038        return false;
1039    }
1040    return true;
1041}
1042
1043void SystemStatusSvHealth::dump()
1044{
1045    LOC_LOGV("SvHealth: u=%ld:%ld u=%x:%x:%x:%x:%x g=%x:%x:%x:%x:%x b=%x:%x:%x:%x:%x",
1046             mUtcTime.tv_sec, mUtcTime.tv_nsec,
1047             mGpsUnknownMask,
1048             mGloUnknownMask,
1049             mBdsUnknownMask,
1050             mGalUnknownMask,
1051             mQzssUnknownMask,
1052             mGpsGoodMask,
1053             mGloGoodMask,
1054             mBdsGoodMask,
1055             mGalGoodMask,
1056             mQzssGoodMask,
1057             mGpsBadMask,
1058             mGloBadMask,
1059             mBdsBadMask,
1060             mGalBadMask,
1061             mQzssBadMask);
1062    return;
1063}
1064
1065/******************************************************************************
1066 SystemStatusPdr
1067******************************************************************************/
1068SystemStatusPdr::SystemStatusPdr(const SystemStatusPQWP6& nmea) :
1069    mFixInfoMask(nmea.mFixInfoMask)
1070{
1071}
1072
1073bool SystemStatusPdr::equals(SystemStatusPdr& peer)
1074{
1075    if (mFixInfoMask != peer.mFixInfoMask) {
1076        return false;
1077    }
1078    return true;
1079}
1080
1081void SystemStatusPdr::dump()
1082{
1083    LOC_LOGV("Pdr: u=%ld:%ld m=%x",
1084             mUtcTime.tv_sec, mUtcTime.tv_nsec,
1085             mFixInfoMask);
1086    return;
1087}
1088
1089/******************************************************************************
1090 SystemStatusNavData
1091******************************************************************************/
1092SystemStatusNavData::SystemStatusNavData(const SystemStatusPQWP7& nmea)
1093{
1094    for (uint32_t i=0; i<SV_ALL_NUM; i++) {
1095        mNav[i] = nmea.mNav[i];
1096    }
1097}
1098
1099bool SystemStatusNavData::equals(SystemStatusNavData& peer)
1100{
1101    for (uint32_t i=0; i<SV_ALL_NUM; i++) {
1102        if ((mNav[i].mType != peer.mNav[i].mType) ||
1103            (mNav[i].mSource != peer.mNav[i].mSource) ||
1104            (mNav[i].mAgeSec != peer.mNav[i].mAgeSec)) {
1105            return false;
1106        }
1107    }
1108    return true;
1109}
1110
1111void SystemStatusNavData::dump()
1112{
1113    LOC_LOGV("NavData: u=%ld:%ld",
1114            mUtcTime.tv_sec, mUtcTime.tv_nsec);
1115    for (uint32_t i=0; i<SV_ALL_NUM; i++) {
1116        LOC_LOGV("i=%d type=%d src=%d age=%d",
1117            i, mNav[i].mType, mNav[i].mSource, mNav[i].mAgeSec);
1118    }
1119    return;
1120}
1121
1122/******************************************************************************
1123 SystemStatusPositionFailure
1124******************************************************************************/
1125SystemStatusPositionFailure::SystemStatusPositionFailure(const SystemStatusPQWS1& nmea) :
1126    mFixInfoMask(nmea.mFixInfoMask),
1127    mHepeLimit(nmea.mHepeLimit)
1128{
1129}
1130
1131bool SystemStatusPositionFailure::equals(SystemStatusPositionFailure& peer)
1132{
1133    if ((mFixInfoMask != peer.mFixInfoMask) ||
1134        (mHepeLimit != peer.mHepeLimit)) {
1135        return false;
1136    }
1137    return true;
1138}
1139
1140void SystemStatusPositionFailure::dump()
1141{
1142    LOC_LOGV("PositionFailure: u=%ld:%ld m=%d h=%d",
1143             mUtcTime.tv_sec, mUtcTime.tv_nsec,
1144             mFixInfoMask,
1145             mHepeLimit);
1146    return;
1147}
1148
1149/******************************************************************************
1150 SystemStatusLocation
1151******************************************************************************/
1152bool SystemStatusLocation::equals(SystemStatusLocation& peer)
1153{
1154    if ((mLocation.gpsLocation.latitude != peer.mLocation.gpsLocation.latitude) ||
1155        (mLocation.gpsLocation.longitude != peer.mLocation.gpsLocation.longitude) ||
1156        (mLocation.gpsLocation.altitude != peer.mLocation.gpsLocation.altitude)) {
1157        return false;
1158    }
1159    return true;
1160}
1161
1162void SystemStatusLocation::dump()
1163{
1164    LOC_LOGV("Location: lat=%f lon=%f alt=%f spd=%f",
1165             mLocation.gpsLocation.latitude,
1166             mLocation.gpsLocation.longitude,
1167             mLocation.gpsLocation.altitude,
1168             mLocation.gpsLocation.speed);
1169    return;
1170}
1171
1172/******************************************************************************
1173 SystemStatus
1174******************************************************************************/
1175pthread_mutex_t SystemStatus::mMutexSystemStatus = PTHREAD_MUTEX_INITIALIZER;
1176
1177SystemStatus::SystemStatus()
1178{
1179    mCache.mLocation.clear();
1180
1181    mCache.mTimeAndClock.clear();
1182    mCache.mXoState.clear();
1183    mCache.mRfAndParams.clear();
1184    mCache.mErrRecovery.clear();
1185
1186    mCache.mInjectedPosition.clear();
1187    mCache.mBestPosition.clear();
1188    mCache.mXtra.clear();
1189    mCache.mEphemeris.clear();
1190    mCache.mSvHealth.clear();
1191    mCache.mPdr.clear();
1192    mCache.mNavData.clear();
1193
1194    mCache.mPositionFailure.clear();
1195}
1196
1197/******************************************************************************
1198 SystemStatus - M1 functions
1199******************************************************************************/
1200bool SystemStatus::setTimeAndCLock(const SystemStatusPQWM1& nmea)
1201{
1202    SystemStatusTimeAndClock s(nmea);
1203    if (!mCache.mTimeAndClock.empty() && mCache.mTimeAndClock.back().equals(s)) {
1204        mCache.mTimeAndClock.back().mUtcReported = s.mUtcReported;
1205    } else {
1206        mCache.mTimeAndClock.push_back(s);
1207        if (mCache.mTimeAndClock.size() > maxTimeAndClock) {
1208            mCache.mTimeAndClock.erase(mCache.mTimeAndClock.begin());
1209        }
1210    }
1211    return true;
1212}
1213
1214bool SystemStatus::setXoState(const SystemStatusPQWM1& nmea)
1215{
1216    SystemStatusXoState s(nmea);
1217    if (!mCache.mXoState.empty() && mCache.mXoState.back().equals(s)) {
1218        mCache.mXoState.back().mUtcReported = s.mUtcReported;
1219    } else {
1220        mCache.mXoState.push_back(s);
1221        if (mCache.mXoState.size() > maxXoState) {
1222            mCache.mXoState.erase(mCache.mXoState.begin());
1223        }
1224    }
1225    return true;
1226}
1227
1228bool SystemStatus::setRfAndParams(const SystemStatusPQWM1& nmea)
1229{
1230    SystemStatusRfAndParams s(nmea);
1231    if (!mCache.mRfAndParams.empty() && mCache.mRfAndParams.back().equals(s)) {
1232        mCache.mRfAndParams.back().mUtcReported = s.mUtcReported;
1233    } else {
1234        mCache.mRfAndParams.push_back(s);
1235        if (mCache.mRfAndParams.size() > maxRfAndParams) {
1236            mCache.mRfAndParams.erase(mCache.mRfAndParams.begin());
1237        }
1238    }
1239    return true;
1240}
1241
1242bool SystemStatus::setErrRecovery(const SystemStatusPQWM1& nmea)
1243{
1244    SystemStatusErrRecovery s(nmea);
1245    if (!mCache.mErrRecovery.empty() && mCache.mErrRecovery.back().equals(s)) {
1246        mCache.mErrRecovery.back().mUtcReported = s.mUtcReported;
1247    } else {
1248        mCache.mErrRecovery.push_back(s);
1249        if (mCache.mErrRecovery.size() > maxErrRecovery) {
1250            mCache.mErrRecovery.erase(mCache.mErrRecovery.begin());
1251        }
1252    }
1253    return true;
1254}
1255
1256/******************************************************************************
1257 SystemStatus - Px functions
1258******************************************************************************/
1259bool SystemStatus::setInjectedPosition(const SystemStatusPQWP1& nmea)
1260{
1261    SystemStatusInjectedPosition s(nmea);
1262    if (!mCache.mInjectedPosition.empty() && mCache.mInjectedPosition.back().equals(s)) {
1263        mCache.mInjectedPosition.back().mUtcReported = s.mUtcReported;
1264    } else {
1265        mCache.mInjectedPosition.push_back(s);
1266        if (mCache.mInjectedPosition.size() > maxInjectedPosition) {
1267            mCache.mInjectedPosition.erase(mCache.mInjectedPosition.begin());
1268        }
1269    }
1270    return true;
1271}
1272
1273bool SystemStatus::setBestPosition(const SystemStatusPQWP2& nmea)
1274{
1275    SystemStatusBestPosition s(nmea);
1276    if (!mCache.mBestPosition.empty() && mCache.mBestPosition.back().equals(s)) {
1277        mCache.mBestPosition.back().mUtcReported = s.mUtcReported;
1278    } else {
1279        mCache.mBestPosition.push_back(s);
1280        if (mCache.mBestPosition.size() > maxBestPosition) {
1281            mCache.mBestPosition.erase(mCache.mBestPosition.begin());
1282        }
1283    }
1284    return true;
1285}
1286
1287bool SystemStatus::setXtra(const SystemStatusPQWP3& nmea)
1288{
1289    SystemStatusXtra s(nmea);
1290    if (!mCache.mXtra.empty() && mCache.mXtra.back().equals(s)) {
1291        mCache.mXtra.back().mUtcReported = s.mUtcReported;
1292    } else {
1293        mCache.mXtra.push_back(s);
1294        if (mCache.mXtra.size() > maxXtra) {
1295            mCache.mXtra.erase(mCache.mXtra.begin());
1296        }
1297    }
1298    return true;
1299}
1300
1301bool SystemStatus::setEphemeris(const SystemStatusPQWP4& nmea)
1302{
1303    SystemStatusEphemeris s(nmea);
1304    if (!mCache.mEphemeris.empty() && mCache.mEphemeris.back().equals(s)) {
1305        mCache.mEphemeris.back().mUtcReported = s.mUtcReported;
1306    } else {
1307        mCache.mEphemeris.push_back(s);
1308        if (mCache.mEphemeris.size() > maxEphemeris) {
1309            mCache.mEphemeris.erase(mCache.mEphemeris.begin());
1310        }
1311    }
1312    return true;
1313}
1314
1315bool SystemStatus::setSvHealth(const SystemStatusPQWP5& nmea)
1316{
1317    SystemStatusSvHealth s(nmea);
1318    if (!mCache.mSvHealth.empty() && mCache.mSvHealth.back().equals(s)) {
1319        mCache.mSvHealth.back().mUtcReported = s.mUtcReported;
1320    } else {
1321        mCache.mSvHealth.push_back(s);
1322        if (mCache.mSvHealth.size() > maxSvHealth) {
1323            mCache.mSvHealth.erase(mCache.mSvHealth.begin());
1324        }
1325    }
1326    return true;
1327}
1328
1329bool SystemStatus::setPdr(const SystemStatusPQWP6& nmea)
1330{
1331    SystemStatusPdr s(nmea);
1332    if (!mCache.mPdr.empty() && mCache.mPdr.back().equals(s)) {
1333        mCache.mPdr.back().mUtcReported = s.mUtcReported;
1334    } else {
1335        mCache.mPdr.push_back(s);
1336        if (mCache.mPdr.size() > maxPdr) {
1337            mCache.mPdr.erase(mCache.mPdr.begin());
1338        }
1339    }
1340    return true;
1341}
1342
1343bool SystemStatus::setNavData(const SystemStatusPQWP7& nmea)
1344{
1345    SystemStatusNavData s(nmea);
1346    if (!mCache.mNavData.empty() && mCache.mNavData.back().equals(s)) {
1347        mCache.mNavData.back().mUtcReported = s.mUtcReported;
1348    } else {
1349        mCache.mNavData.push_back(s);
1350        if (mCache.mNavData.size() > maxNavData) {
1351            mCache.mNavData.erase(mCache.mNavData.begin());
1352        }
1353    }
1354    return true;
1355}
1356
1357/******************************************************************************
1358 SystemStatus - Sx functions
1359******************************************************************************/
1360bool SystemStatus::setPositionFailure(const SystemStatusPQWS1& nmea)
1361{
1362    SystemStatusPositionFailure s(nmea);
1363    if (!mCache.mPositionFailure.empty() && mCache.mPositionFailure.back().equals(s)) {
1364        mCache.mPositionFailure.back().mUtcReported = s.mUtcReported;
1365    } else {
1366        mCache.mPositionFailure.push_back(s);
1367        if (mCache.mPositionFailure.size() > maxPositionFailure) {
1368            mCache.mPositionFailure.erase(mCache.mPositionFailure.begin());
1369        }
1370    }
1371    return true;
1372}
1373
1374/******************************************************************************
1375@brief      API to set report data into internal buffer
1376
1377@param[In]  data pointer to the NMEA string
1378@param[In]  len  length of the NMEA string
1379
1380@return     true when successfully done
1381******************************************************************************/
1382static uint32_t cnt = 0;
1383static uint32_t cnt_m1 = 0;
1384static uint32_t cnt_p1 = 0;
1385static uint32_t cnt_p2 = 0;
1386static uint32_t cnt_p3 = 0;
1387static uint32_t cnt_p4 = 0;
1388static uint32_t cnt_p5 = 0;
1389static uint32_t cnt_p6 = 0;
1390static uint32_t cnt_p7 = 0;
1391static uint32_t cnt_s1 = 0;
1392
1393bool SystemStatus::setNmeaString(const char *data, uint32_t len)
1394{
1395    bool ret = false;
1396    if (!loc_nmea_is_debug(data, len)) {
1397        return false;
1398    }
1399
1400    char buf[SystemStatusNmeaBase::NMEA_MAXSIZE + 1] = { 0 };
1401    strlcpy(buf, data, sizeof(buf));
1402
1403    pthread_mutex_lock(&mMutexSystemStatus);
1404
1405    // parse the received nmea strings here
1406    if      (0 == strncmp(data, "$PQWM1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1407        SystemStatusPQWM1 s = SystemStatusPQWM1parser(buf, len).get();
1408        ret  = setTimeAndCLock(s);
1409        ret |= setXoState(s);
1410        ret |= setRfAndParams(s);
1411        ret |= setErrRecovery(s);
1412        cnt_m1++;
1413    }
1414    else if (0 == strncmp(data, "$PQWP1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1415        ret = setInjectedPosition(SystemStatusPQWP1parser(buf, len).get());
1416        cnt_p1++;
1417    }
1418    else if (0 == strncmp(data, "$PQWP2", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1419        ret = setBestPosition(SystemStatusPQWP2parser(buf, len).get());
1420        cnt_p2++;
1421    }
1422    else if (0 == strncmp(data, "$PQWP3", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1423        ret = setXtra(SystemStatusPQWP3parser(buf, len).get());
1424        cnt_p3++;
1425    }
1426    else if (0 == strncmp(data, "$PQWP4", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1427        ret = setEphemeris(SystemStatusPQWP4parser(buf, len).get());
1428        cnt_p4++;
1429    }
1430    else if (0 == strncmp(data, "$PQWP5", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1431        ret = setSvHealth(SystemStatusPQWP5parser(buf, len).get());
1432        cnt_p5++;
1433    }
1434    else if (0 == strncmp(data, "$PQWP6", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1435        ret = setPdr(SystemStatusPQWP6parser(buf, len).get());
1436        cnt_p6++;
1437    }
1438    else if (0 == strncmp(data, "$PQWP7", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1439        ret = setNavData(SystemStatusPQWP7parser(buf, len).get());
1440        cnt_p7++;
1441    }
1442    else if (0 == strncmp(data, "$PQWS1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
1443        ret = setPositionFailure(SystemStatusPQWS1parser(buf, len).get());
1444        cnt_s1++;
1445    }
1446    else {
1447        // do nothing
1448    }
1449    cnt++;
1450    LOC_LOGV("setNmeaString: cnt=%d M:%d 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d S:%d",
1451             cnt,
1452             cnt_m1,
1453             cnt_p1,
1454             cnt_p2,
1455             cnt_p3,
1456             cnt_p4,
1457             cnt_p5,
1458             cnt_p6,
1459             cnt_p7,
1460             cnt_s1);
1461
1462    pthread_mutex_unlock(&mMutexSystemStatus);
1463    return ret;
1464}
1465
1466/******************************************************************************
1467@brief      API to set report position data into internal buffer
1468
1469@param[In]  UlpLocation
1470
1471@return     true when successfully done
1472******************************************************************************/
1473bool SystemStatus::eventPosition(const UlpLocation& location,
1474                                 const GpsLocationExtended& locationEx)
1475{
1476    SystemStatusLocation s(location, locationEx);
1477    if (!mCache.mLocation.empty() && mCache.mLocation.back().equals(s)) {
1478        mCache.mLocation.back().mUtcReported = s.mUtcReported;
1479    }
1480    else {
1481        mCache.mLocation.push_back(s);
1482        if (mCache.mLocation.size() > maxLocation) {
1483            mCache.mLocation.erase(mCache.mLocation.begin());
1484        }
1485    }
1486    LOC_LOGV("eventPosition - lat=%f lon=%f alt=%f speed=%f",
1487             s.mLocation.gpsLocation.latitude,
1488             s.mLocation.gpsLocation.longitude,
1489             s.mLocation.gpsLocation.altitude,
1490             s.mLocation.gpsLocation.speed);
1491    return true;
1492}
1493
1494/******************************************************************************
1495@brief      API to get report data into a given buffer
1496
1497@param[In]  reference to report buffer
1498@param[In]  bool flag to identify latest only or entire buffer
1499
1500@return     true when successfully done
1501******************************************************************************/
1502bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) const
1503{
1504    pthread_mutex_lock(&mMutexSystemStatus);
1505
1506    if (isLatestOnly) {
1507        // push back only the latest report and return it
1508        report.mLocation.clear();
1509        if (mCache.mLocation.size() >= 1) {
1510            report.mLocation.push_back(mCache.mLocation.back());
1511            report.mLocation.back().dump();
1512        }
1513
1514        report.mTimeAndClock.clear();
1515        if (mCache.mTimeAndClock.size() >= 1) {
1516            report.mTimeAndClock.push_back(mCache.mTimeAndClock.back());
1517            report.mTimeAndClock.back().dump();
1518        }
1519        report.mXoState.clear();
1520        if (mCache.mXoState.size() >= 1) {
1521            report.mXoState.push_back(mCache.mXoState.back());
1522            report.mXoState.back().dump();
1523        }
1524        report.mRfAndParams.clear();
1525        if (mCache.mRfAndParams.size() >= 1) {
1526            report.mRfAndParams.push_back(mCache.mRfAndParams.back());
1527            report.mRfAndParams.back().dump();
1528        }
1529        report.mErrRecovery.clear();
1530        if (mCache.mErrRecovery.size() >= 1) {
1531            report.mErrRecovery.push_back(mCache.mErrRecovery.back());
1532            report.mErrRecovery.back().dump();
1533        }
1534
1535        report.mInjectedPosition.clear();
1536        if (mCache.mInjectedPosition.size() >= 1) {
1537            report.mInjectedPosition.push_back(mCache.mInjectedPosition.back());
1538            report.mInjectedPosition.back().dump();
1539        }
1540        report.mBestPosition.clear();
1541        if (mCache.mBestPosition.size() >= 1) {
1542            report.mBestPosition.push_back(mCache.mBestPosition.back());
1543            report.mBestPosition.back().dump();
1544        }
1545        report.mXtra.clear();
1546        if (mCache.mXtra.size() >= 1) {
1547            report.mXtra.push_back(mCache.mXtra.back());
1548            report.mXtra.back().dump();
1549        }
1550        report.mEphemeris.clear();
1551        if (mCache.mEphemeris.size() >= 1) {
1552            report.mEphemeris.push_back(mCache.mEphemeris.back());
1553            report.mEphemeris.back().dump();
1554        }
1555        report.mSvHealth.clear();
1556        if (mCache.mSvHealth.size() >= 1) {
1557            report.mSvHealth.push_back(mCache.mSvHealth.back());
1558            report.mSvHealth.back().dump();
1559        }
1560        report.mPdr.clear();
1561        if (mCache.mPdr.size() >= 1) {
1562            report.mPdr.push_back(mCache.mPdr.back());
1563            report.mPdr.back().dump();
1564        }
1565        report.mNavData.clear();
1566        if (mCache.mNavData.size() >= 1) {
1567            report.mNavData.push_back(mCache.mNavData.back());
1568            report.mNavData.back().dump();
1569        }
1570
1571        report.mPositionFailure.clear();
1572        if (mCache.mPositionFailure.size() >= 1) {
1573            report.mPositionFailure.push_back(mCache.mPositionFailure.back());
1574            report.mPositionFailure.back().dump();
1575        }
1576    }
1577    else {
1578        // copy entire reports and return them
1579        report.mLocation.clear();
1580
1581        report.mTimeAndClock.clear();
1582        report.mXoState.clear();
1583        report.mRfAndParams.clear();
1584        report.mErrRecovery.clear();
1585
1586        report.mInjectedPosition.clear();
1587        report.mBestPosition.clear();
1588        report.mXtra.clear();
1589        report.mEphemeris.clear();
1590        report.mSvHealth.clear();
1591        report.mPdr.clear();
1592        report.mNavData.clear();
1593
1594        report.mPositionFailure.clear();
1595        report = mCache;
1596    }
1597
1598    pthread_mutex_unlock(&mMutexSystemStatus);
1599    return true;
1600}
1601
1602/******************************************************************************
1603@brief      API to set default report data
1604
1605@param[In]  none
1606
1607@return     true when successfully done
1608******************************************************************************/
1609bool SystemStatus::setDefaultReport(void)
1610{
1611    pthread_mutex_lock(&mMutexSystemStatus);
1612
1613    mCache.mLocation.push_back(SystemStatusLocation());
1614    if (mCache.mLocation.size() > maxLocation) {
1615        mCache.mLocation.erase(mCache.mLocation.begin());
1616    }
1617
1618    mCache.mTimeAndClock.push_back(SystemStatusTimeAndClock());
1619    if (mCache.mTimeAndClock.size() > maxTimeAndClock) {
1620        mCache.mTimeAndClock.erase(mCache.mTimeAndClock.begin());
1621    }
1622    mCache.mXoState.push_back(SystemStatusXoState());
1623    if (mCache.mXoState.size() > maxXoState) {
1624        mCache.mXoState.erase(mCache.mXoState.begin());
1625    }
1626    mCache.mRfAndParams.push_back(SystemStatusRfAndParams());
1627    if (mCache.mRfAndParams.size() > maxRfAndParams) {
1628        mCache.mRfAndParams.erase(mCache.mRfAndParams.begin());
1629    }
1630    mCache.mErrRecovery.push_back(SystemStatusErrRecovery());
1631    if (mCache.mErrRecovery.size() > maxErrRecovery) {
1632        mCache.mErrRecovery.erase(mCache.mErrRecovery.begin());
1633    }
1634
1635    mCache.mInjectedPosition.push_back(SystemStatusInjectedPosition());
1636    if (mCache.mInjectedPosition.size() > maxInjectedPosition) {
1637        mCache.mInjectedPosition.erase(mCache.mInjectedPosition.begin());
1638    }
1639    mCache.mBestPosition.push_back(SystemStatusBestPosition());
1640    if (mCache.mBestPosition.size() > maxBestPosition) {
1641        mCache.mBestPosition.erase(mCache.mBestPosition.begin());
1642    }
1643    mCache.mXtra.push_back(SystemStatusXtra());
1644    if (mCache.mXtra.size() > maxXtra) {
1645        mCache.mXtra.erase(mCache.mXtra.begin());
1646    }
1647    mCache.mEphemeris.push_back(SystemStatusEphemeris());
1648    if (mCache.mEphemeris.size() > maxEphemeris) {
1649        mCache.mEphemeris.erase(mCache.mEphemeris.begin());
1650    }
1651    mCache.mSvHealth.push_back(SystemStatusSvHealth());
1652    if (mCache.mSvHealth.size() > maxSvHealth) {
1653        mCache.mSvHealth.erase(mCache.mSvHealth.begin());
1654    }
1655    mCache.mPdr.push_back(SystemStatusPdr());
1656    if (mCache.mPdr.size() > maxPdr) {
1657        mCache.mPdr.erase(mCache.mPdr.begin());
1658    }
1659    mCache.mNavData.push_back(SystemStatusNavData());
1660    if (mCache.mNavData.size() > maxNavData) {
1661        mCache.mNavData.erase(mCache.mNavData.begin());
1662    }
1663
1664    mCache.mPositionFailure.push_back(SystemStatusPositionFailure());
1665    if (mCache.mPositionFailure.size() > maxPositionFailure) {
1666        mCache.mPositionFailure.erase(mCache.mPositionFailure.begin());
1667    }
1668
1669    pthread_mutex_unlock(&mMutexSystemStatus);
1670    return true;
1671}
1672
1673} // namespace loc_core
1674
1675