diff options
author | Raghuram Subramani <raghus2247@gmail.com> | 2024-10-14 20:38:19 +0530 |
---|---|---|
committer | Raghuram Subramani <raghus2247@gmail.com> | 2024-10-14 20:38:19 +0530 |
commit | 86a968c3f424cb70e03cccb24cabf9751f6f636d (patch) | |
tree | 5aedd15a754e4c0de8a015a4fd2c2e5c0698a22b /gps/utils | |
parent | ea30e6e77df9c7a651f22bcc5797b8a3f33703dc (diff) |
update gps stack
Diffstat (limited to 'gps/utils')
-rw-r--r-- | gps/utils/Android.mk | 4 | ||||
-rw-r--r-- | gps/utils/LocIpc.cpp | 481 | ||||
-rw-r--r-- | gps/utils/LocIpc.h | 209 | ||||
-rw-r--r-- | gps/utils/LocSharedLock.h | 20 | ||||
-rw-r--r-- | gps/utils/LocThread.cpp | 4 | ||||
-rw-r--r-- | gps/utils/Makefile.am | 70 | ||||
-rw-r--r-- | gps/utils/MsgTask.cpp | 7 | ||||
-rw-r--r-- | gps/utils/configure.ac | 82 | ||||
-rw-r--r-- | gps/utils/gps-utils.pc.in | 10 | ||||
-rw-r--r-- | gps/utils/gps_extended.h | 14 | ||||
-rw-r--r-- | gps/utils/gps_extended_c.h | 1362 | ||||
-rw-r--r-- | gps/utils/linked_list.h | 2 | ||||
-rw-r--r-- | gps/utils/loc_cfg.cpp | 317 | ||||
-rw-r--r-- | gps/utils/loc_cfg.h | 23 | ||||
-rw-r--r-- | gps/utils/loc_gps.h | 22 | ||||
-rw-r--r-- | gps/utils/loc_misc_utils.cpp | 31 | ||||
-rw-r--r-- | gps/utils/loc_misc_utils.h | 28 | ||||
-rw-r--r-- | gps/utils/loc_nmea.cpp | 1347 | ||||
-rw-r--r-- | gps/utils/loc_nmea.h | 39 | ||||
-rw-r--r-- | gps/utils/loc_target.cpp | 57 | ||||
-rw-r--r-- | gps/utils/loc_target.h | 4 | ||||
-rw-r--r-- | gps/utils/log_util.h | 33 | ||||
-rw-r--r-- | gps/utils/msg_q.c | 45 | ||||
-rw-r--r-- | gps/utils/msg_q.h | 23 |
24 files changed, 3275 insertions, 959 deletions
diff --git a/gps/utils/Android.mk b/gps/utils/Android.mk index ec6bf05..88ad487 100644 --- a/gps/utils/Android.mk +++ b/gps/utils/Android.mk @@ -9,6 +9,7 @@ include $(CLEAR_VARS) ## Libs LOCAL_SHARED_LIBRARIES := \ + libdl \ libutils \ libcutils \ liblog \ @@ -46,6 +47,9 @@ LOCAL_HEADER_LIBRARIES := \ liblocation_api_headers LOCAL_MODULE := libgps.utils +LOCAL_SANITIZE += $(GNSS_SANITIZE) +# activate the following line for debug purposes only, comment out for production +#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG) LOCAL_VENDOR_MODULE := true LOCAL_MODULE_TAGS := optional diff --git a/gps/utils/LocIpc.cpp b/gps/utils/LocIpc.cpp index 675664a..64d27cb 100644 --- a/gps/utils/LocIpc.cpp +++ b/gps/utils/LocIpc.cpp @@ -30,8 +30,14 @@ #include <sys/types.h> #include <sys/stat.h> #include <errno.h> +#include <netinet/in.h> +#include <netdb.h> +#include <loc_misc_utils.h> #include <log_util.h> -#include "LocIpc.h" +#include <LocIpc.h> +#include <algorithm> + +using namespace std; namespace loc_util { @@ -40,198 +46,369 @@ namespace loc_util { #endif #define LOG_TAG "LocSvc_LocIpc" -#define LOC_MSG_BUF_LEN 8192 -#define LOC_MSG_HEAD "$MSGLEN$" -#define LOC_MSG_ABORT "LocIpcMsg::ABORT" +#define SOCK_OP_AND_LOG(buf, length, opable, rtv, exe) \ + if (nullptr == (buf) || 0 == (length)) { \ + LOC_LOGe("Invalid inputs: buf - %p, length - %u", (buf), (length)); \ + } else if (!(opable)) { \ + LOC_LOGe("Invalid object: operable - %d", (opable)); \ + } else { \ + rtv = (exe); \ + if (-1 == rtv) { \ + LOC_LOGw("failed reason: %s", strerror(errno)); \ + } \ + } -class LocIpcRunnable : public LocRunnable { -friend LocIpc; -public: - LocIpcRunnable(LocIpc& locIpc, const std::string& ipcName) - : mLocIpc(locIpc), mIpcName(ipcName) {} - bool run() override { - if (!mLocIpc.startListeningBlocking(mIpcName)) { - LOC_LOGe("listen to socket failed"); +const char Sock::MSG_ABORT[] = "LocIpc::Sock::ABORT"; +const char Sock::LOC_IPC_HEAD[] = "$MSGLEN$"; +ssize_t Sock::send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr, + socklen_t addrlen) const { + ssize_t rtv = -1; + SOCK_OP_AND_LOG(buf, len, isValid(), rtv, sendto(buf, len, flags, destAddr, addrlen)); + return rtv; +} +ssize_t Sock::recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags, + struct sockaddr *srcAddr, socklen_t *addrlen, int sid) const { + ssize_t rtv = -1; + if (-1 == sid) { + sid = mSid; + } // else it sid would be connection based socket id for recv + SOCK_OP_AND_LOG(dataCb.get(), mMaxTxSize, isValid(), rtv, + recvfrom(recver, dataCb, sid, flags, srcAddr, addrlen)); + return rtv; +} +ssize_t Sock::sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr, + socklen_t addrlen) const { + ssize_t rtv = -1; + if (len <= mMaxTxSize) { + rtv = ::sendto(mSid, buf, len, flags, destAddr, addrlen); + } else { + std::string head(LOC_IPC_HEAD + to_string(len)); + rtv = ::sendto(mSid, head.c_str(), head.length(), flags, destAddr, addrlen); + if (rtv > 0) { + for (size_t offset = 0; offset < len && rtv > 0; offset += rtv) { + rtv = ::sendto(mSid, (char*)buf + offset, min(len - offset, (size_t)mMaxTxSize), + flags, destAddr, addrlen); + } + rtv = (rtv > 0) ? (head.length() + len) : -1; } - - return false; } -private: - LocIpc& mLocIpc; - const std::string mIpcName; -}; - -bool LocIpc::startListeningNonBlocking(const std::string& name) { - mRunnable = new LocIpcRunnable(*this, name); - std::string threadName("LocIpc-"); - threadName.append(name); - return mThread.start(threadName.c_str(), mRunnable); + return rtv; } +ssize_t Sock::recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, + int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const { + std::string msg(mMaxTxSize, 0); + ssize_t nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen); + if (nBytes > 0) { + if (strncmp(msg.data(), MSG_ABORT, sizeof(MSG_ABORT)) == 0) { + LOC_LOGi("recvd abort msg.data %s", msg.data()); + nBytes = 0; + } else if (strncmp(msg.data(), LOC_IPC_HEAD, sizeof(LOC_IPC_HEAD) - 1)) { + // short message + msg.resize(nBytes); + dataCb->onReceive(msg.data(), nBytes, &recver); + } else { + // long message + size_t msgLen = 0; + sscanf(msg.data() + sizeof(LOC_IPC_HEAD) - 1, "%zu", &msgLen); + msg.resize(msgLen); + for (size_t msgLenReceived = 0; (msgLenReceived < msgLen) && (nBytes > 0); + msgLenReceived += nBytes) { + nBytes = ::recvfrom(sid, &(msg[msgLenReceived]), msg.size() - msgLenReceived, + flags, srcAddr, addrlen); + } + if (nBytes > 0) { + nBytes = msgLen; + dataCb->onReceive(msg.data(), nBytes, &recver); + } + } + } -bool LocIpc::startListeningBlocking(const std::string& name) { + return nBytes; +} +ssize_t Sock::sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen) { + return send(MSG_ABORT, sizeof(MSG_ABORT), flags, destAddr, addrlen); +} - int fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) { - LOC_LOGe("create socket error. reason:%s", strerror(errno)); - return false; +class LocIpcLocalSender : public LocIpcSender { +protected: + shared_ptr<Sock> mSock; + struct sockaddr_un mAddr; + inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); } + inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const { + return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr)); } +public: + inline LocIpcLocalSender(const char* name) : LocIpcSender(), + mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_UNIX, SOCK_DGRAM, 0)))), + mAddr({.sun_family = AF_UNIX, {}}) { + if (mSock != nullptr && mSock->isValid()) { + snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name); + } + } +}; - if ((unlink(name.c_str()) < 0) && (errno != ENOENT)) { - LOC_LOGw("unlink socket error. reason:%s", strerror(errno)); +class LocIpcLocalRecver : public LocIpcLocalSender, public LocIpcRecver { +protected: + inline virtual ssize_t recv() const override { + socklen_t size = sizeof(mAddr); + return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size); } +public: + inline LocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, const char* name) : + LocIpcLocalSender(name), LocIpcRecver(listener, *this) { - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name.c_str()); + if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) { + LOC_LOGw("unlink socket error. reason:%s", strerror(errno)); + } - umask(0157); + umask(0157); + if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) { + LOC_LOGe("bind socket error. sock fd: %d: %s, reason: %s", mSock->mSid, + mAddr.sun_path, strerror(errno)); + mSock->close(); + } + } + inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); } + inline virtual const char* getName() const override { return mAddr.sun_path; }; + inline virtual void abort() const override { + if (isSendable()) { + mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr)); + } + } +}; - if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - LOC_LOGe("bind socket error. reason:%s", strerror(errno)); - ::close(fd); - fd = -1; - return false; +class LocIpcInetSender : public LocIpcSender { +protected: + int mSockType; + shared_ptr<Sock> mSock; + const string mName; + sockaddr_in mAddr; + inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); } + virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const { + return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr)); + } +public: + inline LocIpcInetSender(const LocIpcInetSender& sender) : + mSockType(sender.mSockType), mSock(sender.mSock), + mName(sender.mName), mAddr(sender.mAddr) { + } + inline LocIpcInetSender(const char* name, int32_t port, int sockType) : LocIpcSender(), + mSockType(sockType), + mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, mSockType, 0)))), + mName((nullptr == name) ? "" : name), + mAddr({.sin_family = AF_INET, .sin_port = htons(port), + .sin_addr = {htonl(INADDR_ANY)}}) { + if (mSock != nullptr && mSock->isValid() && nullptr != name) { + struct hostent* hp = gethostbyname(name); + if (nullptr != hp) { + memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length); + } + } } - mIpcFd = fd; + unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override { + return make_unique<SockRecver>(listener, *this, mSock); + } +}; - // inform that the socket is ready to receive message - onListenerReady(); +class LocIpcInetTcpSender : public LocIpcInetSender { +protected: + mutable bool mFirstTime; - ssize_t nBytes = 0; - std::string msg = ""; - std::string abort = LOC_MSG_ABORT; - while (1) { - msg.resize(LOC_MSG_BUF_LEN); - nBytes = ::recvfrom(mIpcFd, (void*)(msg.data()), msg.size(), 0, NULL, NULL); - if (nBytes < 0) { - break; - } else if (nBytes == 0) { - continue; + virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const { + if (mFirstTime) { + mFirstTime = false; + ::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr)); } + return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr)); + } - if (strncmp(msg.data(), abort.c_str(), abort.length()) == 0) { - LOC_LOGi("recvd abort msg.data %s", msg.data()); - break; +public: + inline LocIpcInetTcpSender(const char* name, int32_t port) : + LocIpcInetSender(name, port, SOCK_STREAM), + mFirstTime(true) {} +}; + +class LocIpcInetRecver : public LocIpcInetSender, public LocIpcRecver { + int32_t mPort; +protected: + virtual ssize_t recv() const = 0; +public: + inline LocIpcInetRecver(const shared_ptr<ILocIpcListener>& listener, const char* name, + int32_t port, int sockType) : + LocIpcInetSender(name, port, sockType), LocIpcRecver(listener, *this), + mPort(port) { + if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) { + LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno)); + mSock->close(); + } + } + inline virtual ~LocIpcInetRecver() {} + inline virtual const char* getName() const override { return mName.data(); }; + inline virtual void abort() const override { + if (isSendable()) { + sockaddr_in loopBackAddr = {.sin_family = AF_INET, .sin_port = htons(mPort), + .sin_addr = {htonl(INADDR_LOOPBACK)}}; + mSock->sendAbort(0, (struct sockaddr*)&loopBackAddr, sizeof(loopBackAddr)); } + } + inline virtual unique_ptr<LocIpcSender> getLastSender() const override { + return make_unique<LocIpcInetSender>(static_cast<const LocIpcInetSender&>(*this)); + } +}; - if (strncmp(msg.data(), LOC_MSG_HEAD, sizeof(LOC_MSG_HEAD) - 1)) { - // short message - msg.resize(nBytes); - onReceive(msg); - } else { - // long message - size_t msgLen = 0; - sscanf(msg.data(), LOC_MSG_HEAD"%zu", &msgLen); - msg.resize(msgLen); - size_t msgLenReceived = 0; - while ((msgLenReceived < msgLen) && (nBytes > 0)) { - nBytes = recvfrom(mIpcFd, (void*)&(msg[msgLenReceived]), - msg.size() - msgLenReceived, 0, NULL, NULL); - msgLenReceived += nBytes; - } - if (nBytes > 0) { - onReceive(msg); - } else { - break; +class LocIpcInetTcpRecver : public LocIpcInetRecver { + mutable int32_t mConnFd; +protected: + inline virtual ssize_t recv() const override { + socklen_t size = sizeof(mAddr); + if (-1 == mConnFd && mSock->isValid()) { + if (::listen(mSock->mSid, 3) < 0 || + (mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) { + mSock->close(); + mConnFd = -1; } } + return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd); } +public: + inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name, + int32_t port) : + LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {} + inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);} +}; - if (mStopRequested) { - mStopRequested = false; - return true; - } else { - LOC_LOGe("cannot read socket. reason:%s", strerror(errno)); - (void)::close(mIpcFd); - mIpcFd = -1; - return false; +class LocIpcInetUdpRecver : public LocIpcInetRecver { +protected: + inline virtual ssize_t recv() const override { + socklen_t size = sizeof(mAddr); + return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size); } -} - -void LocIpc::stopListening() { +public: + inline LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name, + int32_t port) : + LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {} - const char *socketName = nullptr; - mStopRequested = true; + inline virtual ~LocIpcInetUdpRecver() {} +}; - if (mRunnable) { - std::string abort = LOC_MSG_ABORT; - socketName = (reinterpret_cast<LocIpcRunnable *>(mRunnable))->mIpcName.c_str(); - send(socketName, abort); - mRunnable = nullptr; +class LocIpcRunnable : public LocRunnable { + bool mAbortCalled; + LocIpc& mLocIpc; + unique_ptr<LocIpcRecver> mIpcRecver; +public: + inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) : + mAbortCalled(false), + mLocIpc(locIpc), + mIpcRecver(std::move(ipcRecver)) {} + inline bool run() override { + if (mIpcRecver != nullptr) { + mLocIpc.startBlockingListening(*(mIpcRecver.get())); + if (!mAbortCalled) { + LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called"); + } + } + // return false so the calling thread exits while loop + return false; } - - if (mIpcFd >= 0) { - if (::close(mIpcFd)) { - LOC_LOGe("cannot close socket:%s", strerror(errno)); + inline void abort() { + mAbortCalled = true; + if (mIpcRecver != nullptr) { + mIpcRecver->abort(); } - mIpcFd = -1; } +}; - //delete from the file system at the end - if (socketName) { - unlink(socketName); +bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) { + if (ipcRecver != nullptr && ipcRecver->isRecvable()) { + std::string threadName("LocIpc-"); + threadName.append(ipcRecver->getName()); + mRunnable = new LocIpcRunnable(*this, ipcRecver); + return mThread.start(threadName.c_str(), mRunnable); + } else { + LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle"); + return false; } } -bool LocIpc::send(const char name[], const std::string& data) { - return send(name, (const uint8_t*)data.c_str(), data.length()); -} - -bool LocIpc::send(const char name[], const uint8_t data[], uint32_t length) { - - bool result = true; - int fd = ::socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) { - LOC_LOGe("create socket error. reason:%s", strerror(errno)); +bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) { + if (ipcRecver.isRecvable()) { + // inform that the socket is ready to receive message + ipcRecver.onListenerReady(); + while (ipcRecver.recvData()); + return true; + } else { + LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle"); return false; } - - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name); - - result = sendData(fd, addr, data, length); - - (void)::close(fd); - return result; } +void LocIpc::stopNonBlockingListening() { + if (mRunnable) { + mRunnable->abort(); + mRunnable = nullptr; + } +} -bool LocIpc::sendData(int fd, const sockaddr_un &addr, const uint8_t data[], uint32_t length) { +void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) { + if (ipcRecver.isRecvable()) { + ipcRecver.abort(); + } +} - bool result = true; +bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) { + return sender.sendData(data, length, msgId); +} - if (length <= LOC_MSG_BUF_LEN) { - if (::sendto(fd, data, length, 0, - (struct sockaddr*)&addr, sizeof(addr)) < 0) { - LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); - result = false; - } - } else { - std::string head = LOC_MSG_HEAD; - head.append(std::to_string(length)); - if (::sendto(fd, head.c_str(), head.length(), 0, - (struct sockaddr*)&addr, sizeof(addr)) < 0) { - LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); - result = false; - } else { - size_t sentBytes = 0; - while(sentBytes < length) { - size_t partLen = length - sentBytes; - if (partLen > LOC_MSG_BUF_LEN) { - partLen = LOC_MSG_BUF_LEN; - } - ssize_t rv = ::sendto(fd, data + sentBytes, partLen, 0, - (struct sockaddr*)&addr, sizeof(addr)); - if (rv < 0) { - LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); - result = false; - break; - } - sentBytes += rv; - } - } - } - return result; +shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) { + return make_shared<LocIpcLocalSender>(localSockName); +} +unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, + const char* localSockName) { + return make_unique<LocIpcLocalRecver>(listener, localSockName); +} +static void* sLibQrtrHandle = nullptr; +static const char* sLibQrtrName = "libloc_socket.so"; +shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) { + typedef shared_ptr<LocIpcSender> (*creator_t) (int, int); + static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName, + "_ZN8loc_util22createLocIpcQrtrSenderEii"); + return (nullptr == creator) ? nullptr : creator(service, instance); +} +unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener, + int service, int instance) { + typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int); + static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName, +#ifdef USE_GLIB + "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii"); +#else + "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii"); +#endif + return (nullptr == creator) ? nullptr : creator(listener, service, instance); +} +shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) { + return make_shared<LocIpcInetTcpSender>(serverName, port); +} +unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, + const char* serverName, int32_t port) { + return make_unique<LocIpcInetTcpRecver>(listener, serverName, port); +} +shared_ptr<LocIpcSender> LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) { + return make_shared<LocIpcInetSender>(serverName, port, SOCK_DGRAM); +} +unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, + const char* serverName, int32_t port) { + return make_unique<LocIpcInetUdpRecver>(listener, serverName, port); +} +pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> + LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) { + typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int); + static void* sLibEmuHandle = nullptr; + static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so", + "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi"); + return (nullptr == creator) ? + make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) : + creator(listener, instance); } } diff --git a/gps/utils/LocIpc.h b/gps/utils/LocIpc.h index 364093b..d6f8d1d 100644 --- a/gps/utils/LocIpc.h +++ b/gps/utils/LocIpc.h @@ -27,8 +27,8 @@ * */ -#ifndef __LOC_SOCKET__ -#define __LOC_SOCKET__ +#ifndef __LOC_IPC__ +#define __LOC_IPC__ #include <string> #include <memory> @@ -37,33 +37,71 @@ #include <sys/un.h> #include <LocThread.h> +using namespace std; + namespace loc_util { + +class LocIpcRecver; class LocIpcSender; +class LocIpcRunnable; + +class ILocIpcListener { +protected: + inline virtual ~ILocIpcListener() {} +public: + // LocIpc client can overwrite this function to get notification + // when the socket for LocIpc is ready to receive messages. + inline virtual void onListenerReady() {} + virtual void onReceive(const char* data, uint32_t len, const LocIpcRecver* recver) = 0; +}; + class LocIpc { -friend LocIpcSender; public: - inline LocIpc() : mIpcFd(-1), mStopRequested(false), mRunnable(nullptr) {} - inline virtual ~LocIpc() { stopListening(); } + inline LocIpc() : mRunnable(nullptr) {} + inline virtual ~LocIpc() { + stopNonBlockingListening(); + } + + static shared_ptr<LocIpcSender> + getLocIpcLocalSender(const char* localSockName); + static shared_ptr<LocIpcSender> + getLocIpcInetUdpSender(const char* serverName, int32_t port); + static shared_ptr<LocIpcSender> + getLocIpcInetTcpSender(const char* serverName, int32_t port); + static shared_ptr<LocIpcSender> + getLocIpcQrtrSender(int service, int instance); + + static unique_ptr<LocIpcRecver> + getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, + const char* localSockName); + static unique_ptr<LocIpcRecver> + getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, + const char* serverName, int32_t port); + static unique_ptr<LocIpcRecver> + getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, + const char* serverName, int32_t port); + static unique_ptr<LocIpcRecver> + getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener, + int service, int instance); + + static pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> + getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, + int instance); // Listen for new messages in current thread. Calling this funciton will - // block current thread. The listening can be stopped by calling stopListening(). - // - // Argument name is the path of the unix local socket to be listened. - // The function will return true on success, and false on failure. - bool startListeningBlocking(const std::string& name); + // block current thread. + // The listening can be stopped by calling stopBlockingListening() passing + // in the same ipcRecver obj handle. + static bool startBlockingListening(LocIpcRecver& ipcRecver); + static void stopBlockingListening(LocIpcRecver& ipcRecver); // Create a new LocThread and listen for new messages in it. // Calling this function will return immediately and won't block current thread. - // The listening can be stopped by calling stopListening(). - // - // Argument name is the path of the unix local socket to be be listened. - // The function will return true on success, and false on failure. - bool startListeningNonBlocking(const std::string& name); - - // Stop listening to new messages. - void stopListening(); + // The listening can be stopped by calling stopNonBlockingListening(). + bool startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver); + void stopNonBlockingListening(); // Send out a message. // Call this function to send a message in argument data to socket in argument name. @@ -71,83 +109,98 @@ public: // Argument name contains the name of the target unix socket. data contains the // message to be sent out. Convert your message to a string before calling this function. // The function will return true on success, and false on failure. - static bool send(const char name[], const std::string& data); - static bool send(const char name[], const uint8_t data[], uint32_t length); - -protected: - // Callback function for receiving incoming messages. - // Override this function in your derived class to process incoming messages. - // For each received message, this callback function will be called once. - // This callback function will be called in the calling thread of startListeningBlocking - // or in the new LocThread created by startListeningNonBlocking. - // - // Argument data contains the received message. You need to parse it. - inline virtual void onReceive(const std::string& /*data*/) {} - - // LocIpc client can overwrite this function to get notification - // when the socket for LocIpc is ready to receive messages. - inline virtual void onListenerReady() {} + static bool send(LocIpcSender& sender, const uint8_t data[], + uint32_t length, int32_t msgId = -1); private: - static bool sendData(int fd, const sockaddr_un& addr, - const uint8_t data[], uint32_t length); - - int mIpcFd; - bool mStopRequested; LocThread mThread; - LocRunnable *mRunnable; + LocIpcRunnable *mRunnable; }; +/* this is only when client needs to implement Sender / Recver that are not already provided by + the factor methods prvoided by LocIpc. */ + class LocIpcSender { +protected: + LocIpcSender() = default; + virtual bool isOperable() const = 0; + virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const = 0; public: - // Constructor of LocIpcSender class - // - // Argument destSocket contains the full path name of destination socket. - // This class hides generated fd and destination address object from user. - inline LocIpcSender(const char* destSocket): - LocIpcSender(std::make_shared<int>(::socket(AF_UNIX, SOCK_DGRAM, 0)), destSocket) { - if (-1 == *mSocket) { - mSocket = nullptr; - } + virtual ~LocIpcSender() = default; + virtual void informRecverRestarted() {} + inline bool isSendable() const { return isOperable(); } + inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const { + return isSendable() && (send(data, length, msgId) > 0); } - - // Replicate a new LocIpcSender object with new destination socket. - inline LocIpcSender* replicate(const char* destSocket) { - return (nullptr == mSocket) ? nullptr : new LocIpcSender(mSocket, destSocket); + virtual unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) { + return nullptr; } +}; - inline ~LocIpcSender() { - if (nullptr != mSocket && mSocket.unique()) { - ::close(*mSocket); - } +class LocIpcRecver { + LocIpcSender& mIpcSender; +protected: + const shared_ptr<ILocIpcListener> mDataCb; + inline LocIpcRecver(const shared_ptr<ILocIpcListener>& listener, LocIpcSender& sender) : + mIpcSender(sender), mDataCb(listener) {} + LocIpcRecver(LocIpcRecver const& recver) = delete; + LocIpcRecver& operator=(LocIpcRecver const& recver) = delete; + virtual ssize_t recv() const = 0; +public: + virtual ~LocIpcRecver() = default; + inline bool recvData() const { return isRecvable() && (recv() > 0); } + inline bool isRecvable() const { return mDataCb != nullptr && mIpcSender.isSendable(); } + virtual void onListenerReady() { if (mDataCb != nullptr) mDataCb->onListenerReady(); } + inline virtual unique_ptr<LocIpcSender> getLastSender() const { + return nullptr; } + virtual void abort() const = 0; + virtual const char* getName() const = 0; +}; - // Send out a message. - // Call this function to send a message - // - // Argument data and length contains the message to be sent out. - // Return true when succeeded - inline bool send(const uint8_t data[], uint32_t length) { - bool rtv = false; - if (nullptr != mSocket && nullptr != data) { - rtv = LocIpc::sendData(*mSocket, mDestAddr, data, length); +class Sock { + static const char MSG_ABORT[]; + static const char LOC_IPC_HEAD[]; + const uint32_t mMaxTxSize; + ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr, + socklen_t addrlen) const; + ssize_t recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, + int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const; +public: + int mSid; + inline Sock(int sid, const uint32_t maxTxSize = 8192) : mMaxTxSize(maxTxSize), mSid(sid) {} + inline ~Sock() { close(); } + inline bool isValid() const { return -1 != mSid; } + ssize_t send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr, + socklen_t addrlen) const; + ssize_t recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags, + struct sockaddr *srcAddr, socklen_t *addrlen, int sid = -1) const; + ssize_t sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen); + inline void close() { + if (isValid()) { + ::close(mSid); + mSid = -1; } - return rtv; } +}; -private: - std::shared_ptr<int> mSocket; - struct sockaddr_un mDestAddr; - - inline LocIpcSender( - const std::shared_ptr<int>& mySocket, const char* destSocket) : mSocket(mySocket) { - if ((nullptr != mSocket) && (-1 != *mSocket) && (nullptr != destSocket)) { - mDestAddr.sun_family = AF_UNIX; - snprintf(mDestAddr.sun_path, sizeof(mDestAddr.sun_path), "%s", destSocket); - } +class SockRecver : public LocIpcRecver { + shared_ptr<Sock> mSock; +protected: + inline virtual ssize_t recv() const override { + return mSock->recv(*this, mDataCb, 0, nullptr, nullptr); + } +public: + inline SockRecver(const shared_ptr<ILocIpcListener>& listener, + LocIpcSender& sender, shared_ptr<Sock> sock) : + LocIpcRecver(listener, sender), mSock(sock) { + } + inline virtual const char* getName() const override { + return "SockRecver"; } + inline virtual void abort() const override {} }; } -#endif //__LOC_SOCKET__ +#endif //__LOC_IPC__ diff --git a/gps/utils/LocSharedLock.h b/gps/utils/LocSharedLock.h index 7fe6237..a7af35e 100644 --- a/gps/utils/LocSharedLock.h +++ b/gps/utils/LocSharedLock.h @@ -30,10 +30,28 @@ #define __LOC_SHARED_LOCK__ #include <stddef.h> +#ifndef FEATURE_EXTERNAL_AP #include <cutils/atomic.h> +#endif /* FEATURE_EXTERNAL_AP */ #include <pthread.h> -// This is a utility created for use cases such that there are more than +#ifdef FEATURE_EXTERNAL_AP +#include <atomic> + +inline int32_t android_atomic_inc(volatile int32_t *addr) +{ + volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr; + return std::atomic_fetch_add_explicit(a, 1, std::memory_order_release); +} + +inline int32_t android_atomic_dec(volatile int32_t *addr) +{ + volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr; + return std::atomic_fetch_sub_explicit(a, 1, std::memory_order_release); +} + +#endif /* FEATURE_EXTERNAL_AP */ + // This is a utility created for use cases such that there are more than // one client who need to share the same lock, but it is not predictable // which of these clients is to last to go away. This shared lock deletes // itself when the last client calls its drop() method. To add a cient, diff --git a/gps/utils/LocThread.cpp b/gps/utils/LocThread.cpp index c1052cb..568a6bb 100644 --- a/gps/utils/LocThread.cpp +++ b/gps/utils/LocThread.cpp @@ -85,8 +85,8 @@ LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, if (mThandle) { // set thread name char lname[16]; - int len = (sizeof(lname)>sizeof(threadName)) ? - (sizeof(threadName) -1):(sizeof(lname) - 1); + int len = (sizeof(lname) > (strlen(threadName) + 1)) ? + (strlen(threadName)):(sizeof(lname) - 1); memcpy(lname, threadName, len); lname[len] = 0; // set the thread name here diff --git a/gps/utils/Makefile.am b/gps/utils/Makefile.am deleted file mode 100644 index 3801fdd..0000000 --- a/gps/utils/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -ACLOCAL_AMFLAGS = -I m4 - -AM_CFLAGS = -Wundef \ - -MD \ - -Wno-trigraphs \ - -g -O0 \ - -fno-inline \ - -fno-short-enums \ - -fpic \ - -I./ \ - -std=c++11 \ - $(LOCPLA_CFLAGS) - -libgps_utils_la_h_sources = \ - msg_q.h \ - linked_list.h \ - loc_cfg.h \ - loc_log.h \ - loc_target.h \ - loc_timer.h \ - MsgTask.h \ - LocHeap.h \ - LocThread.h \ - LocTimer.h \ - LocIpc.h \ - loc_misc_utils.h \ - loc_nmea.h \ - gps_extended_c.h \ - gps_extended.h \ - loc_gps.h \ - log_util.h - -libgps_utils_la_c_sources = \ - linked_list.c \ - msg_q.c \ - loc_cfg.cpp \ - loc_log.cpp \ - loc_target.cpp \ - LocHeap.cpp \ - LocTimer.cpp \ - LocThread.cpp \ - LocIpc.cpp \ - MsgTask.cpp \ - loc_misc_utils.cpp \ - loc_nmea.cpp - -library_includedir = $(pkgincludedir) - -library_include_HEADERS = $(libgps_utils_la_h_sources) - -libgps_utils_la_SOURCES = $(libgps_utils_la_c_sources) - -if USE_GLIB -libgps_utils_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ -libgps_utils_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 -libgps_utils_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ -else -libgps_utils_la_CFLAGS = $(AM_CFLAGS) -libgps_utils_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0 -libgps_utils_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -endif - -libgps_utils_la_LIBADD = $(CUTILS_LIBS) - -#Create and Install libraries -lib_LTLIBRARIES = libgps_utils.la - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = gps-utils.pc -EXTRA_DIST = $(pkgconfig_DATA) diff --git a/gps/utils/MsgTask.cpp b/gps/utils/MsgTask.cpp index eaead5c..73a77fd 100644 --- a/gps/utils/MsgTask.cpp +++ b/gps/utils/MsgTask.cpp @@ -74,16 +74,19 @@ void MsgTask::destroy() { } void MsgTask::sendMsg(const LocMsg* msg) const { - if (msg) { + if (msg && this) { msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy); } else { - LOC_LOGE("%s: msg is NULL", __func__); + LOC_LOGE("%s: msg is %p and this is %p", + __func__, msg, this); } } void MsgTask::prerun() { +#ifndef FEATURE_EXTERNAL_AP // make sure we do not run in background scheduling group set_sched_policy(gettid(), SP_FOREGROUND); +#endif /* FEATURE_EXTERNAL_AP */ } bool MsgTask::run() { diff --git a/gps/utils/configure.ac b/gps/utils/configure.ac deleted file mode 100644 index 639f8c4..0000000 --- a/gps/utils/configure.ac +++ /dev/null @@ -1,82 +0,0 @@ -# configure.ac -- Autoconf script for gps gps-utils -# -# Process this file with autoconf to produce a configure script - -# Requires autoconf tool later than 2.61 -AC_PREREQ(2.61) -# Initialize the gps gps-utils package version 1.0.0 -AC_INIT([gps-utils],1.0.0) -# Does not strictly follow GNU Coding standards -AM_INIT_AUTOMAKE([foreign]) -# Disables auto rebuilding of configure, Makefile.ins -AM_MAINTAINER_MODE -# Verifies the --srcdir is correct by checking for the path -AC_CONFIG_SRCDIR([Makefile.am]) -# defines some macros variable to be included by source -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_MACRO_DIR([m4]) - -# Checks for programs. -AC_PROG_LIBTOOL -AC_PROG_CXX -AC_PROG_CC -AM_PROG_CC_C_O -AC_PROG_AWK -AC_PROG_CPP -AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_MAKE_SET -PKG_PROG_PKG_CONFIG - -# Checks for libraries. -PKG_CHECK_MODULES([CUTILS], [libcutils]) -AC_SUBST([CUTILS_CFLAGS]) -AC_SUBST([CUTILS_LIBS]) - -AC_ARG_WITH([core_includes], - AC_HELP_STRING([--with-core-includes=@<:@dir@:>@], - [Specify the location of the core headers]), - [core_incdir=$withval], - with_core_includes=no) - -if test "x$with_core_includes" != "xno"; then - CPPFLAGS="${CPPFLAGS} -I${core_incdir}" -fi - -AC_ARG_WITH([locpla_includes], - AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@], - [specify the path to locpla-includes in loc-pla_git.bb]), - [locpla_incdir=$withval], - with_locpla_includes=no) - -if test "x$with_locpla_includes" != "xno"; then - AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}") -fi - -AC_SUBST([CPPFLAGS]) - -AC_ARG_WITH([glib], - AC_HELP_STRING([--with-glib], - [enable glib, building HLOS systems which use glib])) - -if (test "x${with_glib}" = "xyes"); then - AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) - PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, - AC_MSG_ERROR(GThread >= 2.16 is required)) - PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, - AC_MSG_ERROR(GLib >= 2.16 is required)) - GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" - GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" - - AC_SUBST(GLIB_CFLAGS) - AC_SUBST(GLIB_LIBS) -fi - -AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") - -AC_CONFIG_FILES([ \ - Makefile \ - gps-utils.pc - ]) - -AC_OUTPUT diff --git a/gps/utils/gps-utils.pc.in b/gps/utils/gps-utils.pc.in deleted file mode 100644 index a988731..0000000 --- a/gps/utils/gps-utils.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: gps-utils -Description: QTI GPS Location utils -Version: @VERSION -Libs: -L${libdir} -lgps_utils -Cflags: -I${includedir}/gps-utils diff --git a/gps/utils/gps_extended.h b/gps/utils/gps_extended.h index dc6ad1e..2455629 100644 --- a/gps/utils/gps_extended.h +++ b/gps/utils/gps_extended.h @@ -55,14 +55,19 @@ struct LocPosMode bool share_position; char credentials[14]; char provider[8]; + GnssPowerMode powerMode; + uint32_t timeBetweenMeasurements; LocPosMode(LocPositionMode m, LocGpsPositionRecurrence recr, uint32_t gap, uint32_t accu, uint32_t time, - bool sp, const char* cred, const char* prov) : + bool sp, const char* cred, const char* prov, + GnssPowerMode pMode = GNSS_POWER_MODE_INVALID, + uint32_t tbm = 0) : mode(m), recurrence(recr), min_interval(gap < GPS_MIN_POSSIBLE_FIX_INTERVAL_MS ? GPS_MIN_POSSIBLE_FIX_INTERVAL_MS : gap), preferred_accuracy(accu), preferred_time(time), - share_position(sp) { + share_position(sp), powerMode(pMode), + timeBetweenMeasurements(tbm) { memset(credentials, 0, sizeof(credentials)); memset(provider, 0, sizeof(provider)); if (NULL != cred) { @@ -78,7 +83,8 @@ struct LocPosMode recurrence(LOC_GPS_POSITION_RECURRENCE_PERIODIC), min_interval(GPS_DEFAULT_FIX_INTERVAL_MS), preferred_accuracy(50), preferred_time(120000), - share_position(true) { + share_position(true), powerMode(GNSS_POWER_MODE_INVALID), + timeBetweenMeasurements(GPS_DEFAULT_FIX_INTERVAL_MS) { memset(credentials, 0, sizeof(credentials)); memset(provider, 0, sizeof(provider)); } @@ -90,6 +96,8 @@ struct LocPosMode anotherMode.min_interval == min_interval && anotherMode.preferred_accuracy == preferred_accuracy && anotherMode.preferred_time == preferred_time && + anotherMode.powerMode == powerMode && + anotherMode.timeBetweenMeasurements == timeBetweenMeasurements && !strncmp(anotherMode.credentials, credentials, sizeof(credentials)-1) && !strncmp(anotherMode.provider, provider, sizeof(provider)-1); } diff --git a/gps/utils/gps_extended_c.h b/gps/utils/gps_extended_c.h index 5479bec..69a659e 100644 --- a/gps/utils/gps_extended_c.h +++ b/gps/utils/gps_extended_c.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -35,7 +35,12 @@ #include <string.h> #include <loc_gps.h> #include <LocationAPI.h> -#include <time.h> + +struct timespec32_t { + uint32_t tv_sec; /* seconds */ + uint32_t tv_nsec; /* and nanoseconds */ +}; + /** * @file @@ -57,6 +62,8 @@ extern "C" { /** LocGpsLocation has valid map index */ #define LOC_GPS_LOCATION_HAS_MAP_INDEX 0x0200 +#define GNSS_INVALID_JAMMER_IND 0x7FFFFFFF + /** Sizes for indoor fields */ #define GPS_LOCATION_MAP_URL_SIZE 400 #define GPS_LOCATION_MAP_INDEX_SIZE 16 @@ -65,20 +72,16 @@ extern "C" { #define ULP_LOCATION_IS_FROM_HYBRID 0x0001 /** Position source is GNSS only */ #define ULP_LOCATION_IS_FROM_GNSS 0x0002 -/** Position source is ZPP only */ -#define ULP_LOCATION_IS_FROM_ZPP 0x0004 /** Position is from a Geofence Breach Event */ -#define ULP_LOCATION_IS_FROM_GEOFENCE 0X0008 +#define ULP_LOCATION_IS_FROM_GEOFENCE 0X0004 /** Position is from Hardware FLP */ -#define ULP_LOCATION_IS_FROM_HW_FLP 0x0010 +#define ULP_LOCATION_IS_FROM_HW_FLP 0x0008 /** Position is from NLP */ -#define ULP_LOCATION_IS_FROM_NLP 0x0020 -/** Position is from PIP */ -#define ULP_LOCATION_IS_FROM_PIP 0x0040 +#define ULP_LOCATION_IS_FROM_NLP 0x0010 /** Position is from external DR solution*/ -#define ULP_LOCATION_IS_FROM_EXT_DR 0X0080 +#define ULP_LOCATION_IS_FROM_EXT_DR 0X0020 /** Raw GNSS position fixes */ -#define ULP_LOCATION_IS_FROM_GNSS_RAW 0X0100 +#define ULP_LOCATION_IS_FROM_GNSS_RAW 0X0040 typedef uint32_t LocSvInfoSource; /** SVinfo source is GNSS/DR */ @@ -95,6 +98,12 @@ typedef uint32_t LocSvInfoSource; #define LOC_AGPS_CERTIFICATE_MAX_LENGTH 2000 #define LOC_AGPS_CERTIFICATE_MAX_SLOTS 10 +/* TBM Threshold for tracking in background power mode : in millis */ +#define TRACKING_TBM_THRESHOLD_MILLIS 480000 + +/** Maximum number of satellites in an ephemeris report. */ +#define GNSS_EPHEMERIS_LIST_MAX_SIZE_V02 32 + typedef uint32_t LocPosTechMask; #define LOC_POS_TECH_MASK_DEFAULT ((LocPosTechMask)0x00000000) #define LOC_POS_TECH_MASK_SATELLITE ((LocPosTechMask)0x00000001) @@ -105,6 +114,7 @@ typedef uint32_t LocPosTechMask; #define LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION ((LocPosTechMask)0x00000020) #define LOC_POS_TECH_MASK_AFLT ((LocPosTechMask)0x00000040) #define LOC_POS_TECH_MASK_HYBRID ((LocPosTechMask)0x00000080) +#define LOC_POS_TECH_MASK_PPE ((LocPosTechMask)0x00000100) enum loc_registration_mask_status { LOC_REGISTRATION_MASK_ENABLED, @@ -117,28 +127,27 @@ typedef enum { LOC_SUPPORTED_FEATURE_WIFI_AP_DATA_INJECT_2_V02, /**< Support Wifi AP data inject version 2 feature */ LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02, /**< Support debug NMEA feature */ LOC_SUPPORTED_FEATURE_GNSS_ONLY_POSITION_REPORT, /**< Support GNSS Only position reports */ - LOC_SUPPORTED_FEATURE_FDCL /**< Support FDCL */ + LOC_SUPPORTED_FEATURE_FDCL, /**< Support FDCL */ + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02, /**< Support constellation enablement */ + LOC_SUPPORTED_FEATURE_AGPM_V02, /**< Support AGPM feature */ + LOC_SUPPORTED_FEATURE_XTRA_INTEGRITY, /**< Support XTRA integrity */ + LOC_SUPPORTED_FEATURE_FDCL_2, /**< Support FDCL V2 */ + LOC_SUPPORTED_FEATURE_LOCATION_PRIVACY /**< Support location privacy */ } loc_supported_feature_enum; typedef struct { /** set to sizeof(UlpLocation) */ - size_t size; + uint32_t size; LocGpsLocation gpsLocation; /* Provider indicator for HYBRID or GPS */ uint16_t position_source; LocPosTechMask tech_mask; - /*allows HAL to pass additional information related to the location */ - int rawDataSize; /* in # of bytes */ - void * rawData; - bool is_indoor; - float floor_number; - char map_url[GPS_LOCATION_MAP_URL_SIZE]; - unsigned char map_index[GPS_LOCATION_MAP_INDEX_SIZE]; + bool unpropagatedPosition; } UlpLocation; typedef struct { /** set to sizeof(UlpNmea) */ - size_t size; + uint32_t size; char nmea_str[ULP_MAX_NMEA_STRING_SIZE]; unsigned int len; } UlpNmea; @@ -163,21 +172,47 @@ typedef int16_t AGpsBearerType; #define AGPS_APN_BEARER_IPV6 2 #define AGPS_APN_BEARER_IPV4V6 3 -typedef enum { - AGPS_CB_PRIORITY_LOW = 1, - AGPS_CB_PRIORITY_MED = 2, - AGPS_CB_PRIORITY_HIGH = 3 -} AgpsCbPriority; +typedef uint32_t LocApnTypeMask; +/**< Denotes APN type for Default/Internet traffic */ +#define LOC_APN_TYPE_MASK_DEFAULT ((LocApnTypeMask)0x00000001) +/**< Denotes APN type for IP Multimedia Subsystem */ +#define LOC_APN_TYPE_MASK_IMS ((LocApnTypeMask)0x00000002) +/**< Denotes APN type for Multimedia Messaging Service */ +#define LOC_APN_TYPE_MASK_MMS ((LocApnTypeMask)0x00000004) +/**< Denotes APN type for Dial Up Network */ +#define LOC_APN_TYPE_MASK_DUN ((LocApnTypeMask)0x00000008) +/**< Denotes APN type for Secure User Plane Location */ +#define LOC_APN_TYPE_MASK_SUPL ((LocApnTypeMask)0x00000010) +/**< Denotes APN type for High Priority Mobile Data */ +#define LOC_APN_TYPE_MASK_HIPRI ((LocApnTypeMask)0x00000020) +/**< Denotes APN type for over the air administration */ +#define LOC_APN_TYPE_MASK_FOTA ((LocApnTypeMask)0x00000040) +/**< Denotes APN type for Carrier Branded Services */ +#define LOC_APN_TYPE_MASK_CBS ((LocApnTypeMask)0x00000080) +/**< Denotes APN type for Initial Attach */ +#define LOC_APN_TYPE_MASK_IA ((LocApnTypeMask)0x00000100) +/**< Denotes APN type for emergency */ +#define LOC_APN_TYPE_MASK_EMERGENCY ((LocApnTypeMask)0x00000200) + +typedef uint32_t AGpsTypeMask; +#define AGPS_ATL_TYPE_SUPL ((AGpsTypeMask)0x00000001) +#define AGPS_ATL_TYPE_SUPL_ES ((AGpsTypeMask)0x00000002) +#define AGPS_ATL_TYPE_WWAN ((AGpsTypeMask)0x00000004) typedef struct { void* statusV4Cb; - AgpsCbPriority cbPriority; + AGpsTypeMask atlType; } AgpsCbInfo; +typedef struct { + void* visibilityControlCb; + void* isInEmergencySession; +} NfwCbInfo; + /** GPS extended callback structure. */ typedef struct { /** set to sizeof(LocGpsCallbacks) */ - size_t size; + uint32_t size; loc_gps_set_capabilities set_capabilities_cb; loc_gps_acquire_wakelock acquire_wakelock_cb; loc_gps_release_wakelock release_wakelock_cb; @@ -201,7 +236,7 @@ typedef struct { /** Represents the status of AGPS. */ typedef struct { /** set to sizeof(AGpsExtStatus) */ - size_t size; + uint32_t size; AGpsExtType type; LocAGpsStatusValue status; @@ -237,7 +272,8 @@ typedef enum loc_server_type { LOC_AGPS_CDMA_PDE_SERVER, LOC_AGPS_CUSTOM_PDE_SERVER, LOC_AGPS_MPC_SERVER, - LOC_AGPS_SUPL_SERVER + LOC_AGPS_SUPL_SERVER, + LOC_AGPS_MO_SUPL_SERVER } LocServerType; typedef enum loc_position_mode_type { @@ -273,7 +309,7 @@ typedef enum loc_position_mode_type { #define GPS_DEFAULT_FIX_INTERVAL_MS 1000 /** Flags to indicate which values are valid in a GpsLocationExtended. */ -typedef uint32_t GpsLocationExtendedFlags; +typedef uint64_t GpsLocationExtendedFlags; /** GpsLocationExtended has valid pdop, hdop, vdop. */ #define GPS_LOCATION_EXTENDED_HAS_DOP 0x0001 /** GpsLocationExtended has valid altitude mean sea level. */ @@ -312,8 +348,49 @@ typedef uint32_t GpsLocationExtendedFlags; #define GPS_LOCATION_EXTENDED_HAS_GPS_TIME 0x20000 /** GpsLocationExtended has Extended Dilution of Precision */ #define GPS_LOCATION_EXTENDED_HAS_EXT_DOP 0x40000 -/** GpsLocationExtended has Elapsed Time */ -#define GPS_LOCATION_EXTENDED_HAS_ELAPSED_TIME 0x80000 +/** GpsLocationExtended has North standard deviation */ +#define GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV 0x80000 +/** GpsLocationExtended has East standard deviation*/ +#define GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV 0x100000 +/** GpsLocationExtended has North Velocity */ +#define GPS_LOCATION_EXTENDED_HAS_NORTH_VEL 0x200000 +/** GpsLocationExtended has East Velocity */ +#define GPS_LOCATION_EXTENDED_HAS_EAST_VEL 0x400000 +/** GpsLocationExtended has up Velocity */ +#define GPS_LOCATION_EXTENDED_HAS_UP_VEL 0x800000 +/** GpsLocationExtended has North Velocity Uncertainty */ +#define GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC 0x1000000 +/** GpsLocationExtended has East Velocity Uncertainty */ +#define GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC 0x2000000 +/** GpsLocationExtended has up Velocity Uncertainty */ +#define GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC 0x4000000 +/** GpsLocationExtended has Clock Bias */ +#define GPS_LOCATION_EXTENDED_HAS_CLOCK_BIAS 0x8000000 +/** GpsLocationExtended has Clock Bias std deviation*/ +#define GPS_LOCATION_EXTENDED_HAS_CLOCK_BIAS_STD_DEV 0x10000000 +/** GpsLocationExtended has Clock drift*/ +#define GPS_LOCATION_EXTENDED_HAS_CLOCK_DRIFT 0x20000000 +/** GpsLocationExtended has Clock drift std deviation**/ +#define GPS_LOCATION_EXTENDED_HAS_CLOCK_DRIFT_STD_DEV 0x40000000 +/** GpsLocationExtended has leap seconds **/ +#define GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS 0x80000000 +/** GpsLocationExtended has time uncertainty **/ +#define GPS_LOCATION_EXTENDED_HAS_TIME_UNC 0x100000000 +/** GpsLocationExtended has heading rate **/ +#define GPS_LOCATION_EXTENDED_HAS_HEADING_RATE 0x200000000 +/** GpsLocationExtended has multiband signals **/ +#define GPS_LOCATION_EXTENDED_HAS_MULTIBAND 0x400000000 +/** GpsLocationExtended has sensor calibration confidence */ +#define GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE 0x800000000 +/** GpsLocationExtended has sensor calibration status */ +#define GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS 0x1000000000 +/** GpsLocationExtended has the engine type that produced this + * position, the bit mask will only be set when there are two + * or more position engines running in the system */ +#define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE 0x2000000000 + /** GpsLocationExtended has the engine mask that indicates the + * set of engines contribute to the fix. */ +#define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK 0x4000000000 typedef uint32_t LocNavSolutionMask; /* Bitmask to specify whether SBAS ionospheric correction is used */ @@ -324,6 +401,14 @@ typedef uint32_t LocNavSolutionMask; #define LOC_NAV_MASK_SBAS_CORRECTION_LONG ((LocNavSolutionMask)0x0004) /**< Bitmask to specify whether SBAS integrity information is used */ #define LOC_NAV_MASK_SBAS_INTEGRITY ((LocNavSolutionMask)0x0008) +/**< Bitmask to specify whether Position Report is DGNSS corrected */ +#define LOC_NAV_MASK_DGNSS_CORRECTION ((LocNavSolutionMask)0x0010) +/**< Bitmask to specify whether Position Report is RTK corrected */ +#define LOC_NAV_MASK_RTK_CORRECTION ((LocNavSolutionMask)0x0020) +/**< Bitmask to specify whether Position Report is PPP corrected */ +#define LOC_NAV_MASK_PPP_CORRECTION ((LocNavSolutionMask)0x0040) +/**< Bitmask to specify whether Position Report is RTK fixed corrected */ +#define LOC_NAV_MASK_RTK_FIXED_CORRECTION ((LocNavSolutionMask)0x0080) typedef uint32_t LocPosDataMask; /* Bitmask to specify whether Navigation data has Forward Acceleration */ @@ -336,10 +421,29 @@ typedef uint32_t LocPosDataMask; #define LOC_NAV_DATA_HAS_YAW_RATE ((LocPosDataMask)0x0008) /* Bitmask to specify whether Navigation data has Body pitch */ #define LOC_NAV_DATA_HAS_PITCH ((LocPosDataMask)0x0010) +/* Bitmask to specify whether Navigation data has Forward Acceleration Unc */ +#define LOC_NAV_DATA_HAS_LONG_ACCEL_UNC ((LocPosDataMask)0x0020) +/* Bitmask to specify whether Navigation data has Sideward Acceleration Unc*/ +#define LOC_NAV_DATA_HAS_LAT_ACCEL_UNC ((LocPosDataMask)0x0040) +/* Bitmask to specify whether Navigation data has Vertical Acceleration Unc*/ +#define LOC_NAV_DATA_HAS_VERT_ACCEL_UNC ((LocPosDataMask)0x0080) +/* Bitmask to specify whether Navigation data has Heading Rate Unc*/ +#define LOC_NAV_DATA_HAS_YAW_RATE_UNC ((LocPosDataMask)0x0100) +/* Bitmask to specify whether Navigation data has Body pitch Unc*/ +#define LOC_NAV_DATA_HAS_PITCH_UNC ((LocPosDataMask)0x0200) + +typedef uint32_t GnssAdditionalSystemInfoMask; +/* Bitmask to specify whether Tauc is valid */ +#define GNSS_ADDITIONAL_SYSTEMINFO_HAS_TAUC ((GnssAdditionalSystemInfoMask)0x0001) +/* Bitmask to specify whether leapSec is valid */ +#define GNSS_ADDITIONAL_SYSTEMINFO_HAS_LEAP_SEC ((GnssAdditionalSystemInfoMask)0x0002) + /** GPS PRN Range */ #define GPS_SV_PRN_MIN 1 #define GPS_SV_PRN_MAX 32 +#define SBAS_SV_PRN_MIN 33 +#define SBAS_SV_PRN_MAX 64 #define GLO_SV_PRN_MIN 65 #define GLO_SV_PRN_MAX 96 #define QZSS_SV_PRN_MIN 193 @@ -348,17 +452,8 @@ typedef uint32_t LocPosDataMask; #define BDS_SV_PRN_MAX 235 #define GAL_SV_PRN_MIN 301 #define GAL_SV_PRN_MAX 336 - -typedef uint32_t LocPosTechMask; -#define LOC_POS_TECH_MASK_DEFAULT ((LocPosTechMask)0x00000000) -#define LOC_POS_TECH_MASK_SATELLITE ((LocPosTechMask)0x00000001) -#define LOC_POS_TECH_MASK_CELLID ((LocPosTechMask)0x00000002) -#define LOC_POS_TECH_MASK_WIFI ((LocPosTechMask)0x00000004) -#define LOC_POS_TECH_MASK_SENSORS ((LocPosTechMask)0x00000008) -#define LOC_POS_TECH_MASK_REFERENCE_LOCATION ((LocPosTechMask)0x00000010) -#define LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION ((LocPosTechMask)0x00000020) -#define LOC_POS_TECH_MASK_AFLT ((LocPosTechMask)0x00000040) -#define LOC_POS_TECH_MASK_HYBRID ((LocPosTechMask)0x00000080) +#define NAVIC_SV_PRN_MIN 401 +#define NAVIC_SV_PRN_MAX 414 typedef enum { LOC_RELIABILITY_NOT_SET = 0, @@ -368,8 +463,14 @@ typedef enum { LOC_RELIABILITY_HIGH = 4 }LocReliability; +typedef enum { + LOC_IN_EMERGENCY_UNKNOWN = 0, + LOC_IN_EMERGENCY_SET = 1, + LOC_IN_EMERGENCY_NOT_SET = 2 +}LocInEmergency; + typedef struct { - struct timespec apTimeStamp; + struct timespec32_t apTimeStamp; /*boottime received from pps-ktimer*/ float apTimeStampUncertaintyMs; /* timestamp uncertainty in milli seconds */ @@ -381,22 +482,55 @@ typedef struct { uint64_t gal_sv_used_ids_mask; uint64_t bds_sv_used_ids_mask; uint64_t qzss_sv_used_ids_mask; + uint64_t navic_sv_used_ids_mask; } GnssSvUsedInPosition; +typedef struct { + uint64_t gps_l1ca_sv_used_ids_mask; // GPS L1CA + uint64_t gps_l1c_sv_used_ids_mask; // GPS L1C + uint64_t gps_l2_sv_used_ids_mask; // GPS L2 + uint64_t gps_l5_sv_used_ids_mask; // GPS L5 + uint64_t glo_g1_sv_used_ids_mask; // GLO G1 + uint64_t glo_g2_sv_used_ids_mask; // GLO G2 + uint64_t gal_e1_sv_used_ids_mask; // GAL E1 + uint64_t gal_e5a_sv_used_ids_mask; // GAL E5A + uint64_t gal_e5b_sv_used_ids_mask; // GAL E5B + uint64_t bds_b1i_sv_used_ids_mask; // BDS B1I + uint64_t bds_b1c_sv_used_ids_mask; // BDS B1C + uint64_t bds_b2i_sv_used_ids_mask; // BDS B2I + uint64_t bds_b2ai_sv_used_ids_mask; // BDS B2AI + uint64_t qzss_l1ca_sv_used_ids_mask; // QZSS L1CA + uint64_t qzss_l1s_sv_used_ids_mask; // QZSS L1S + uint64_t qzss_l2_sv_used_ids_mask; // QZSS L2 + uint64_t qzss_l5_sv_used_ids_mask; // QZSS L5 + uint64_t sbas_l1_sv_used_ids_mask; // SBAS L1 + uint64_t bds_b2aq_sv_used_ids_mask; // BDS B2AQ +} GnssSvMbUsedInPosition; + /* Body Frame parameters */ typedef struct { /** Contains Body frame LocPosDataMask bits. */ uint32_t bodyFrameDatamask; /* Forward Acceleration in body frame (m/s2)*/ float longAccel; + /** Uncertainty of Forward Acceleration in body frame */ + float longAccelUnc; /* Sideward Acceleration in body frame (m/s2)*/ float latAccel; + /** Uncertainty of Side-ward Acceleration in body frame */ + float latAccelUnc; /* Vertical Acceleration in body frame (m/s2)*/ float vertAccel; + /** Uncertainty of Vertical Acceleration in body frame */ + float vertAccelUnc; /* Heading Rate (Radians/second) */ float yawRate; + /** Uncertainty of Heading Rate */ + float yawRateUnc; /* Body pitch (Radians) */ float pitch; + /** Uncertainty of Body pitch */ + float pitchRadUnc; }LocPositionDynamics; typedef struct { @@ -434,12 +568,143 @@ typedef struct { uint32_t gpsTimeOfWeekMs; }GPSTimeStruct; +typedef uint8_t CarrierPhaseAmbiguityType; +#define CARRIER_PHASE_AMBIGUITY_RESOLUTION_NONE ((CarrierPhaseAmbiguityType)0) +#define CARRIER_PHASE_AMBIGUITY_RESOLUTION_FLOAT ((CarrierPhaseAmbiguityType)1) +#define CARRIER_PHASE_AMBIGUITY_RESOLUTION_FIXED ((CarrierPhaseAmbiguityType)2) + +/** GNSS Signal Type and RF Band */ +typedef uint32_t GnssSignalTypeMask; +/** GPS L1CA Signal */ +#define GNSS_SIGNAL_GPS_L1CA ((GnssSignalTypeMask)0x00000001ul) +/** GPS L1C Signal */ +#define GNSS_SIGNAL_GPS_L1C ((GnssSignalTypeMask)0x00000002ul) +/** GPS L2 RF Band */ +#define GNSS_SIGNAL_GPS_L2 ((GnssSignalTypeMask)0x00000004ul) +/** GPS L5 RF Band */ +#define GNSS_SIGNAL_GPS_L5 ((GnssSignalTypeMask)0x00000008ul) +/** GLONASS G1 (L1OF) RF Band */ +#define GNSS_SIGNAL_GLONASS_G1 ((GnssSignalTypeMask)0x00000010ul) +/** GLONASS G2 (L2OF) RF Band */ +#define GNSS_SIGNAL_GLONASS_G2 ((GnssSignalTypeMask)0x00000020ul) +/** GALILEO E1 RF Band */ +#define GNSS_SIGNAL_GALILEO_E1 ((GnssSignalTypeMask)0x00000040ul) +/** GALILEO E5A RF Band */ +#define GNSS_SIGNAL_GALILEO_E5A ((GnssSignalTypeMask)0x00000080ul) +/** GALILEO E5B RF Band */ +#define GNSS_SIGNAL_GALILIEO_E5B ((GnssSignalTypeMask)0x00000100ul) +/** BEIDOU B1_I RF Band */ +#define GNSS_SIGNAL_BEIDOU_B1I ((GnssSignalTypeMask)0x00000200ul) +/** BEIDOU B1C RF Band */ +#define GNSS_SIGNAL_BEIDOU_B1C ((GnssSignalTypeMask)0x00000400ul) +/** BEIDOU B2_I RF Band */ +#define GNSS_SIGNAL_BEIDOU_B2I ((GnssSignalTypeMask)0x00000800ul) +/** BEIDOU B2A_I RF Band */ +#define GNSS_SIGNAL_BEIDOU_B2AI ((GnssSignalTypeMask)0x00001000ul) +/** QZSS L1CA RF Band */ +#define GNSS_SIGNAL_QZSS_L1CA ((GnssSignalTypeMask)0x00002000ul) +/** QZSS L1S RF Band */ +#define GNSS_SIGNAL_QZSS_L1S ((GnssSignalTypeMask)0x00004000ul) +/** QZSS L2 RF Band */ +#define GNSS_SIGNAL_QZSS_L2 ((GnssSignalTypeMask)0x00008000ul) +/** QZSS L5 RF Band */ +#define GNSS_SIGNAL_QZSS_L5 ((GnssSignalTypeMask)0x00010000ul) +/** SBAS L1 RF Band */ +#define GNSS_SIGNAL_SBAS_L1 ((GnssSignalTypeMask)0x00020000ul) +/** NAVIC L5 RF Band */ +#define GNSS_SIGNAL_NAVIC_L5 ((GnssSignalTypeMask)0x00040000ul) +/** BEIDOU B2A_Q RF Band */ +#define GNSS_SIGNAL_BEIDOU_B2AQ ((GnssSignalTypeMask)0x00080000ul) + +typedef uint16_t GnssMeasUsageStatusBitMask; +/** Used in fix */ +#define GNSS_MEAS_USED_IN_PVT ((GnssMeasUsageStatusBitMask)0x00000001ul) +/** Measurement is Bad */ +#define GNSS_MEAS_USAGE_STATUS_BAD_MEAS ((GnssMeasUsageStatusBitMask)0x00000002ul) +/** Measurement has too low C/N */ +#define GNSS_MEAS_USAGE_STATUS_CNO_TOO_LOW ((GnssMeasUsageStatusBitMask)0x00000004ul) +/** Measurement has too low elevation */ +#define GNSS_MEAS_USAGE_STATUS_ELEVATION_TOO_LOW ((GnssMeasUsageStatusBitMask)0x00000008ul) +/** No ephemeris available for this measurement */ +#define GNSS_MEAS_USAGE_STATUS_NO_EPHEMERIS ((GnssMeasUsageStatusBitMask)0x00000010ul) +/** No corrections available for the measurement */ +#define GNSS_MEAS_USAGE_STATUS_NO_CORRECTIONS ((GnssMeasUsageStatusBitMask)0x00000020ul) +/** Corrections has timed out for the measurement */ +#define GNSS_MEAS_USAGE_STATUS_CORRECTION_TIMEOUT ((GnssMeasUsageStatusBitMask)0x00000040ul) +/** Measurement is unhealthy */ +#define GNSS_MEAS_USAGE_STATUS_UNHEALTHY ((GnssMeasUsageStatusBitMask)0x00000080ul) +/** Configuration is disabled for this measurement */ +#define GNSS_MEAS_USAGE_STATUS_CONFIG_DISABLED ((GnssMeasUsageStatusBitMask)0x00000100ul) +/** Measurement not used for other reasons */ +#define GNSS_MEAS_USAGE_STATUS_OTHER ((GnssMeasUsageStatusBitMask)0x00000200ul) + +/** Flags to indicate valid fields in epMeasUsageInfo */ +typedef uint16_t GnssMeasUsageInfoValidityMask; +#define GNSS_PSEUDO_RANGE_RESIDUAL_VALID ((GnssMeasUsageInfoValidityMask)0x00000001ul) +#define GNSS_DOPPLER_RESIDUAL_VALID ((GnssMeasUsageInfoValidityMask)0x00000002ul) +#define GNSS_CARRIER_PHASE_RESIDUAL_VALID ((GnssMeasUsageInfoValidityMask)0x00000004ul) +#define GNSS_CARRIER_PHASE_AMBIGUITY_TYPE_VALID ((GnssMeasUsageInfoValidityMask)0x00000008ul) + +typedef uint16_t GnssSvPolyStatusMask; +#define GNSS_SV_POLY_SRC_ALM_CORR_V02 ((GnssSvPolyStatusMask)0x01) +#define GNSS_SV_POLY_GLO_STR4_V02 ((GnssSvPolyStatusMask)0x02) +#define GNSS_SV_POLY_DELETE_V02 ((GnssSvPolyStatusMask)0x04) +#define GNSS_SV_POLY_SRC_GAL_FNAV_OR_INAV_V02 ((GnssSvPolyStatusMask)0x08) +typedef uint16_t GnssSvPolyStatusMaskValidity; +#define GNSS_SV_POLY_SRC_ALM_CORR_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x01) +#define GNSS_SV_POLY_GLO_STR4_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x02) +#define GNSS_SV_POLY_DELETE_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x04) +#define GNSS_SV_POLY_SRC_GAL_FNAV_OR_INAV_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x08) + + +typedef struct { + /** Specifies GNSS signal type + Mandatory Field*/ + GnssSignalTypeMask gnssSignalType; + /** Specifies GNSS Constellation Type + Mandatory Field*/ + Gnss_LocSvSystemEnumType gnssConstellation; + /** GNSS SV ID. + For GPS: 1 to 32 + For GLONASS: 65 to 96. When slot-number to SV ID mapping is unknown, set as 255. + For SBAS: 120 to 151 + For QZSS-L1CA:193 to 197 + For BDS: 201 to 237 + For GAL: 301 to 336 */ + uint16_t gnssSvId; + /** GLONASS frequency number + 7. + Valid only for a GLONASS system and + is to be ignored for all other systems. + Range: 1 to 14 */ + uint8_t gloFrequency; + /** Carrier phase ambiguity type. */ + CarrierPhaseAmbiguityType carrierPhaseAmbiguityType; + /** Validity mask */ + GnssMeasUsageStatusBitMask measUsageStatusMask; + /** Specifies measurement usage status + Mandatory Field*/ + GnssMeasUsageInfoValidityMask validityMask; + /** Computed pseudorange residual. + Unit: Meters */ + float pseudorangeResidual; + /** Computed doppler residual. + Unit: Meters/sec*/ + float dopplerResidual; + /** Computed carrier phase residual. + Unit: Cycles*/ + float carrierPhaseResidual; + /** Carrier phase ambiguity value. + Unit: Cycles*/ + float carrierPhasAmbiguity; +} GpsMeasUsageInfo; + + /** Represents gps location extended. */ typedef struct { /** set to sizeof(GpsLocationExtended) */ - size_t size; + uint32_t size; /** Contains GpsLocationExtendedFlags bits. */ - uint32_t flags; + uint64_t flags; /** Contains the Altitude wrt mean sea level */ float altitudeMeanSeaLevel; /** Contains Position Dilusion of Precision. */ @@ -470,6 +735,8 @@ typedef struct { Gnss_ApTimeStampStructType timeStamp; /** Gnss sv used in position data */ GnssSvUsedInPosition gnss_sv_used_ids; + /** Gnss sv used in position data for multiband */ + GnssSvMbUsedInPosition gnss_mb_sv_used_ids; /** Nav solution mask to indicate sbas corrections */ LocNavSolutionMask navSolutionMask; /** Position technology used in computing this fix */ @@ -477,13 +744,75 @@ typedef struct { /** SV Info source used in computing this fix */ LocSvInfoSource sv_source; /** Body Frame Dynamics: 4wayAcceleration and pitch set with validity */ - LocPositionDynamics bodyFrameData; + GnssLocationPositionDynamics bodyFrameData; /** GPS Time */ GPSTimeStruct gpsTime; - /** Elapsed Time */ - int64_t elapsedTime; + GnssSystemTime gnssSystemTime; /** Dilution of precision associated with this position*/ LocExtDOP extDOP; + /** North standard deviation. + Unit: Meters */ + float northStdDeviation; + /** East standard deviation. + Unit: Meters */ + float eastStdDeviation; + /** North Velocity. + Unit: Meters/sec */ + float northVelocity; + /** East Velocity. + Unit: Meters/sec */ + float eastVelocity; + /** Up Velocity. + Unit: Meters/sec */ + float upVelocity; + /** North Velocity standard deviation. + Unit: Meters/sec */ + float northVelocityStdDeviation; + /** East Velocity standard deviation. + Unit: Meters/sec */ + float eastVelocityStdDeviation; + /** Up Velocity standard deviation + Unit: Meters/sec */ + float upVelocityStdDeviation; + /** Estimated clock bias. Unit: Nano seconds */ + float clockbiasMeter; + /** Estimated clock bias std deviation. Unit: Nano seconds */ + float clockBiasStdDeviationMeter; + /** Estimated clock drift. Unit: Meters/sec */ + float clockDrift; + /** Estimated clock drift std deviation. Unit: Meters/sec */ + float clockDriftStdDeviation; + /** Number of valid reference stations. Range:[0-4] */ + uint8_t numValidRefStations; + /** Reference station(s) number */ + uint16_t referenceStation[4]; + /** Number of measurements received for use in fix. + Shall be used as maximum index in-to svUsageInfo[]. + Set to 0, if svUsageInfo reporting is not supported. + Range: 0-EP_GNSS_MAX_MEAS */ + uint8_t numOfMeasReceived; + /** Measurement Usage Information */ + GpsMeasUsageInfo measUsageInfo[GNSS_SV_MAX]; + /** Leap Seconds */ + uint8_t leapSeconds; + /** Time uncertainty in milliseconds */ + float timeUncMs; + /** Heading Rate is in NED frame. + Range: 0 to 359.999. 946 + Unit: Degrees per Seconds */ + float headingRateDeg; + /** Sensor calibration confidence percent. Range: 0 - 100 */ + uint8_t calibrationConfidence; + DrCalibrationStatusMask calibrationStatus; + /* location engine type. When the fix. when the type is set to + LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated + reports from all engines running on the system (e.g.: + DR/SPE/PPE). To check which location engine contributes to + the fused output, check for locOutputEngMask. */ + LocOutputEngineType locOutputEngType; + /* when loc output eng type is set to fused, this field + indicates the set of engines contribute to the fix. */ + PositioningEngineMask locOutputEngMask; } GpsLocationExtended; enum loc_sess_status { @@ -492,6 +821,13 @@ enum loc_sess_status { LOC_SESS_FAILURE }; +// struct that contains complete position info from engine +typedef struct { + UlpLocation location; + GpsLocationExtended locationExtended; + enum loc_sess_status sessionStatus; +} EngineLocationInfo; + // Nmea sentence types mask typedef uint32_t NmeaSentenceTypesMask; #define LOC_NMEA_MASK_GGA_V02 ((NmeaSentenceTypesMask)0x00000001) /**< Enable GGA type */ @@ -512,6 +848,20 @@ typedef uint32_t NmeaSentenceTypesMask; #define LOC_NMEA_MASK_PQGSA_V02 ((NmeaSentenceTypesMask)0x00008000) /**< Enable PQGSA type */ #define LOC_NMEA_MASK_PQGSV_V02 ((NmeaSentenceTypesMask)0x00010000) /**< Enable PQGSV type */ #define LOC_NMEA_MASK_DEBUG_V02 ((NmeaSentenceTypesMask)0x00020000) /**< Enable DEBUG type */ +#define LOC_NMEA_MASK_GPDTM_V02 ((NmeaSentenceTypesMask)0x00040000) /**< Enable GPDTM type */ +#define LOC_NMEA_MASK_GNGGA_V02 ((NmeaSentenceTypesMask)0x00080000) /**< Enable GNGGA type */ +#define LOC_NMEA_MASK_GNRMC_V02 ((NmeaSentenceTypesMask)0x00100000) /**< Enable GNRMC type */ +#define LOC_NMEA_MASK_GNVTG_V02 ((NmeaSentenceTypesMask)0x00200000) /**< Enable GNVTG type */ +#define LOC_NMEA_MASK_GAGNS_V02 ((NmeaSentenceTypesMask)0x00400000) /**< Enable GAGNS type */ +#define LOC_NMEA_MASK_GBGGA_V02 ((NmeaSentenceTypesMask)0x00800000) /**< Enable GBGGA type */ +#define LOC_NMEA_MASK_GBGSA_V02 ((NmeaSentenceTypesMask)0x01000000) /**< Enable GBGSA type */ +#define LOC_NMEA_MASK_GBGSV_V02 ((NmeaSentenceTypesMask)0x02000000) /**< Enable GBGSV type */ +#define LOC_NMEA_MASK_GBRMC_V02 ((NmeaSentenceTypesMask)0x04000000) /**< Enable GBRMC type */ +#define LOC_NMEA_MASK_GBVTG_V02 ((NmeaSentenceTypesMask)0x08000000) /**< Enable GBVTG type */ +#define LOC_NMEA_MASK_GQGSV_V02 ((NmeaSentenceTypesMask)0x10000000) /**< Enable GQGSV type */ +#define LOC_NMEA_MASK_GIGSV_V02 ((NmeaSentenceTypesMask)0x20000000) /**< Enable GIGSV type */ +#define LOC_NMEA_MASK_GNDTM_V02 ((NmeaSentenceTypesMask)0x40000000) /**< Enable GNDTM type */ + // all bitmasks of general supported NMEA sentenses - debug is not part of this #define LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK (LOC_NMEA_MASK_GGA_V02 | LOC_NMEA_MASK_RMC_V02 | \ @@ -519,7 +869,12 @@ typedef uint32_t NmeaSentenceTypesMask; LOC_NMEA_MASK_PQXFI_V02 | LOC_NMEA_MASK_PSTIS_V02 | LOC_NMEA_MASK_GLGSV_V02 | \ LOC_NMEA_MASK_GNGSA_V02 | LOC_NMEA_MASK_GNGNS_V02 | LOC_NMEA_MASK_GARMC_V02 | \ LOC_NMEA_MASK_GAGSV_V02 | LOC_NMEA_MASK_GAGSA_V02 | LOC_NMEA_MASK_GAVTG_V02 | \ - LOC_NMEA_MASK_GAGGA_V02 | LOC_NMEA_MASK_PQGSA_V02 | LOC_NMEA_MASK_PQGSV_V02) + LOC_NMEA_MASK_GAGGA_V02 | LOC_NMEA_MASK_PQGSA_V02 | LOC_NMEA_MASK_PQGSV_V02 | \ + LOC_NMEA_MASK_GPDTM_V02 | LOC_NMEA_MASK_GNGGA_V02 | LOC_NMEA_MASK_GNRMC_V02 | \ + LOC_NMEA_MASK_GNVTG_V02 | LOC_NMEA_MASK_GAGNS_V02 | LOC_NMEA_MASK_GBGGA_V02 | \ + LOC_NMEA_MASK_GBGSA_V02 | LOC_NMEA_MASK_GBGSV_V02 | LOC_NMEA_MASK_GBRMC_V02 | \ + LOC_NMEA_MASK_GBVTG_V02 | LOC_NMEA_MASK_GQGSV_V02 | LOC_NMEA_MASK_GIGSV_V02 | \ + LOC_NMEA_MASK_GNDTM_V02) typedef enum { LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC = 0, @@ -583,8 +938,8 @@ enum loc_api_adapter_event_index { LOC_API_ADAPTER_BATCH_FULL, // Batching on full LOC_API_ADAPTER_BATCHED_POSITION_REPORT, // Batching on fix LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT, // - LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT, //GNSS Measurement Report - LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT, //GNSS SV Polynomial Report + LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT, // GNSS Measurement Report + LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT, // GNSS SV Polynomial Report LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ, // GDT upload start request LOC_API_ADAPTER_GDT_UPLOAD_END_REQ, // GDT upload end request LOC_API_ADAPTER_GNSS_MEASUREMENT, // GNSS Measurement report @@ -594,6 +949,12 @@ enum loc_api_adapter_event_index { LOC_API_ADAPTER_REQUEST_POSITION_INJECTION, // Position injection request LOC_API_ADAPTER_BATCH_STATUS, // batch status LOC_API_ADAPTER_FDCL_SERVICE_REQ, // FDCL service request + LOC_API_ADAPTER_REPORT_UNPROPAGATED_POSITION, // Unpropagated Position report + LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ, // BS observation data request + LOC_API_ADAPTER_GNSS_SV_EPHEMERIS_REPORT, // GNSS SV Ephemeris Report + LOC_API_ADAPTER_LOC_SYSTEM_INFO, // Location system info event + LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT, // GNSS SV nHz measurement report + LOC_API_ADAPTER_EVENT_REPORT_INFO, // Event report info LOC_API_ADAPTER_EVENT_MAX }; @@ -630,7 +991,12 @@ enum loc_api_adapter_event_index { #define LOC_API_ADAPTER_BIT_POSITION_INJECTION_REQUEST (1<<LOC_API_ADAPTER_REQUEST_POSITION_INJECTION) #define LOC_API_ADAPTER_BIT_BATCH_STATUS (1<<LOC_API_ADAPTER_BATCH_STATUS) #define LOC_API_ADAPTER_BIT_FDCL_SERVICE_REQ (1ULL<<LOC_API_ADAPTER_FDCL_SERVICE_REQ) - +#define LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_UNPROPAGATED_POSITION) +#define LOC_API_ADAPTER_BIT_BS_OBS_DATA_SERVICE_REQ (1ULL<<LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ) +#define LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT (1ULL<<LOC_API_ADAPTER_GNSS_SV_EPHEMERIS_REPORT) +#define LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO (1ULL<<LOC_API_ADAPTER_LOC_SYSTEM_INFO) +#define LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT (1ULL<<LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT) +#define LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO (1ULL<<LOC_API_ADAPTER_EVENT_REPORT_INFO) typedef uint64_t LOC_API_ADAPTER_EVENT_MASK_T; @@ -663,7 +1029,8 @@ typedef uint32_t LOC_GPS_LOCK_MASK; #define GNSS_SV_POLY_XYZ_0_TH_ORDER_COEFF_MAX_SIZE 3 #define GNSS_SV_POLY_XYZ_N_TH_ORDER_COEFF_MAX_SIZE 9 #define GNSS_SV_POLY_SV_CLKBIAS_COEFF_MAX_SIZE 4 -#define GNSS_LOC_SV_MEAS_LIST_MAX_SIZE 16 +/** Max number of GNSS SV measurement */ +#define GNSS_LOC_SV_MEAS_LIST_MAX_SIZE 128 enum ulp_gnss_sv_measurement_valid_flags{ @@ -708,9 +1075,19 @@ enum ulp_gnss_sv_poly_valid_flags{ ULP_GNSS_SV_POLY_ELEVATIONUNC, ULP_GNSS_SV_POLY_VELO_COEFF, ULP_GNSS_SV_POLY_ENHANCED_IOD, - - ULP_GNSS_SV_POLY_VALID_FLAGS - + ULP_GNSS_SV_POLY_GPS_ISC_L1CA, + ULP_GNSS_SV_POLY_GPS_ISC_L2C, + ULP_GNSS_SV_POLY_GPS_ISC_L5I5, + ULP_GNSS_SV_POLY_GPS_ISC_L5Q5, + ULP_GNSS_SV_POLY_GPS_TGD, + ULP_GNSS_SV_POLY_GLO_TGD_G1G2, + ULP_GNSS_SV_POLY_BDS_TGD_B1, + ULP_GNSS_SV_POLY_BDS_TGD_B2, + ULP_GNSS_SV_POLY_BDS_TGD_B2A, + ULP_GNSS_SV_POLY_BDS_ISC_B2A, + ULP_GNSS_SV_POLY_GAL_BGD_E1E5A, + ULP_GNSS_SV_POLY_GAL_BGD_E1E5B, + ULP_GNSS_SV_POLY_NAVIC_TGD_L5 }; #define ULP_GNSS_SV_POLY_BIT_GLO_FREQ (1<<ULP_GNSS_SV_POLY_GLO_FREQ) @@ -731,25 +1108,19 @@ enum ulp_gnss_sv_poly_valid_flags{ #define ULP_GNSS_SV_POLY_BIT_ELEVATIONUNC (1<<ULP_GNSS_SV_POLY_ELEVATIONUNC) #define ULP_GNSS_SV_POLY_BIT_VELO_COEFF (1<<ULP_GNSS_SV_POLY_VELO_COEFF) #define ULP_GNSS_SV_POLY_BIT_ENHANCED_IOD (1<<ULP_GNSS_SV_POLY_ENHANCED_IOD) - - -typedef enum -{ - GNSS_LOC_SV_SYSTEM_GPS = 1, - /**< GPS satellite. */ - GNSS_LOC_SV_SYSTEM_GALILEO = 2, - /**< GALILEO satellite. */ - GNSS_LOC_SV_SYSTEM_SBAS = 3, - /**< SBAS satellite. */ - GNSS_LOC_SV_SYSTEM_COMPASS = 4, - /**< COMPASS satellite. */ - GNSS_LOC_SV_SYSTEM_GLONASS = 5, - /**< GLONASS satellite. */ - GNSS_LOC_SV_SYSTEM_BDS = 6, - /**< BDS satellite. */ - GNSS_LOC_SV_SYSTEM_QZSS = 7 - /**< QZSS satellite. */ -} Gnss_LocSvSystemEnumType; +#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L1CA (1<<ULP_GNSS_SV_POLY_GPS_ISC_L1CA) +#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L2C (1<<ULP_GNSS_SV_POLY_GPS_ISC_L2C) +#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L5I5 (1<<ULP_GNSS_SV_POLY_GPS_ISC_L5I5) +#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L5Q5 (1<<ULP_GNSS_SV_POLY_GPS_ISC_L5Q5) +#define ULP_GNSS_SV_POLY_BIT_GPS_TGD (1<<ULP_GNSS_SV_POLY_GPS_TGD) +#define ULP_GNSS_SV_POLY_BIT_GLO_TGD_G1G2 (1<<ULP_GNSS_SV_POLY_GLO_TGD_G1G2) +#define ULP_GNSS_SV_POLY_BIT_BDS_TGD_B1 (1<<ULP_GNSS_SV_POLY_BDS_TGD_B1) +#define ULP_GNSS_SV_POLY_BIT_BDS_TGD_B2 (1<<ULP_GNSS_SV_POLY_BDS_TGD_B2) +#define ULP_GNSS_SV_POLY_BIT_BDS_TGD_B2A (1<<ULP_GNSS_SV_POLY_BDS_TGD_B2A) +#define ULP_GNSS_SV_POLY_BIT_BDS_ISC_B2A (1<<ULP_GNSS_SV_POLY_BDS_ISC_B2A) +#define ULP_GNSS_SV_POLY_BIT_GAL_BGD_E1E5A (1<<ULP_GNSS_SV_POLY_GAL_BGD_E1E5A) +#define ULP_GNSS_SV_POLY_BIT_GAL_BGD_E1E5B (1<<ULP_GNSS_SV_POLY_GAL_BGD_E1E5B) +#define ULP_GNSS_SV_POLY_BIT_NAVIC_TGD_L5 (1<<ULP_GNSS_SV_POLY_NAVIC_TGD_L5) typedef enum { @@ -765,7 +1136,7 @@ typedef enum typedef struct { - size_t size; + uint32_t size; float clockDrift; /**< Receiver clock Drift \n - Units: meter per sec \n @@ -779,7 +1150,7 @@ typedef struct typedef struct { - size_t size; + uint32_t size; uint8_t leapSec; /**< GPS time leap second delta to UTC time \n - Units: sec \n @@ -800,7 +1171,7 @@ typedef enum typedef struct { - size_t size; + uint32_t size; uint32_t validMask; /* Validity mask as per Gnss_LocInterSystemBiasValidMaskType */ @@ -812,71 +1183,12 @@ typedef struct /**< System-1 to System-2 Time Bias uncertainty \n - Units: msec \n */ -}Gnss_InterSystemBiasStructType; +} Gnss_InterSystemBiasStructType; -typedef struct -{ - size_t size; - uint16_t systemWeek; - /**< System week number for GPS, BDS and GAL satellite systems. \n - Set to 65535 when invalid or not available. \n - Not valid for GLONASS system. \n - */ - - uint32_t systemMsec; - /**< System time msec. Time of Week for GPS, BDS, GAL and - Time of Day for GLONASS. - - Units: msec \n - */ - float systemClkTimeBias; - /**< System clock time bias \n - - Units: msec \n - System time = systemMsec - systemClkTimeBias \n - */ - float systemClkTimeUncMs; - /**< Single sided maximum time bias uncertainty \n - - Units: msec \n - */ -}Gnss_LocSystemTimeStructType; - typedef struct { - size_t size; - uint8_t gloFourYear; - /**< GLONASS four year number from 1996. Refer to GLONASS ICD.\n - Applicable only for GLONASS and shall be ignored for other constellations. \n - If unknown shall be set to 255 - */ - - uint16_t gloDays; - /**< GLONASS day number in four years. Refer to GLONASS ICD. - Applicable only for GLONASS and shall be ignored for other constellations. \n - If unknown shall be set to 65535 - */ - - uint32_t gloMsec; - /**< GLONASS time of day in msec. Refer to GLONASS ICD. - - Units: msec \n - */ - - float gloClkTimeBias; - /**< System clock time bias (sub-millisecond) \n - - Units: msec \n - System time = systemMsec - systemClkTimeBias \n - */ - - float gloClkTimeUncMs; - /**< Single sided maximum time bias uncertainty \n - - Units: msec \n - */ -}Gnss_LocGloTimeStructType; /* Type */ - -typedef struct { - - size_t size; - uint32_t refFCount; - /**< Receiver frame counter value at reference tick */ + uint32_t size; uint8_t systemRtc_valid; /**< Validity indicator for System RTC */ @@ -886,13 +1198,8 @@ typedef struct { - Units: msec \n */ - uint32_t sourceOfTime; - /**< Source of time information */ - }Gnss_LocGnssTimeExtStructType; - - typedef enum { GNSS_LOC_MEAS_STATUS_NULL = 0x00000000, @@ -927,7 +1234,7 @@ typedef enum typedef struct { - size_t size; + uint32_t size; uint32_t svMs; /**< Satellite time milisecond.\n For GPS, BDS, GAL range of 0 thru (604800000-1) \n @@ -985,10 +1292,12 @@ typedef enum /**< SV is being tracked */ }Gnss_LocSvSearchStatusEnumT; - typedef struct { - size_t size; + uint32_t size; + Gnss_LocSvSystemEnumType gnssSystem; + // 0 signal type mask indicates invalid value + GnssSignalTypeMask gnssSignalTypeMask; uint16_t gnssSvId; /**< GNSS SV ID. \begin{itemize1} @@ -1110,70 +1419,112 @@ typedef struct /**< Satellite Elevation - Units: radians \n */ -} Gnss_SVMeasurementStructType; - -/**< Maximum number of satellites in measurement block for given system. */ - -typedef struct -{ - size_t size; - Gnss_LocSvSystemEnumType system; - /**< Specifies the Satellite System Type - */ - bool isSystemTimeValid; - /**< Indicates whether System Time is Valid:\n - - 0x01 (TRUE) -- System Time is valid \n - - 0x00 (FALSE) -- System Time is not valid - */ - Gnss_LocSystemTimeStructType systemTime; - /**< System Time Information \n + uint64_t validMeasStatusMask; + /**< Bitmask indicating SV measurement status Validity. + Valid bitmasks: \n + If any MSB bit in 0xFFC0000000000000 DONT_USE is set, the measurement + must not be used by the client. + @MASK() */ - bool isGloTime_valid; - Gnss_LocGloTimeStructType gloTime; + bool carrierPhaseUncValid; + /**< Validity flag for SV direction */ - bool isSystemTimeExt_valid; - Gnss_LocGnssTimeExtStructType systemTimeExt; + float carrierPhaseUnc; - uint8_t numSvs; - /* Number of SVs in this report block */ - Gnss_SVMeasurementStructType svMeasurement[GNSS_LOC_SV_MEAS_LIST_MAX_SIZE]; - /**< Satellite measurement Information \n - */ -} Gnss_ClockMeasurementStructType; +} Gnss_SVMeasurementStructType; + +typedef uint64_t GpsSvMeasHeaderFlags; +#define GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND 0x00000001 +#define GNSS_SV_MEAS_HEADER_HAS_CLOCK_FREQ 0x00000002 +#define GNSS_SV_MEAS_HEADER_HAS_AP_TIMESTAMP 0x00000004 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_GLO_INTER_SYSTEM_BIAS 0x00000008 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_BDS_INTER_SYSTEM_BIAS 0x00000010 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_GAL_INTER_SYSTEM_BIAS 0x00000020 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_GLO_INTER_SYSTEM_BIAS 0x00000040 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_GLO_INTER_SYSTEM_BIAS 0x00000080 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_BDS_INTER_SYSTEM_BIAS 0x00000100 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME 0x00000200 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME 0x00000400 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME 0x00000800 +#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME 0x00001000 +#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME 0x00002000 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME_EXT 0x00004000 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME_EXT 0x00008000 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME_EXT 0x00010000 +#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME_EXT 0x00020000 +#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME_EXT 0x00040000 +#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L5_TIME_BIAS 0x00080000 +#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5A_TIME_BIAS 0x00100000 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_NAVIC_INTER_SYSTEM_BIAS 0x00200000 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_NAVIC_INTER_SYSTEM_BIAS 0x00400000 +#define GNSS_SV_MEAS_HEADER_HAS_GLO_NAVIC_INTER_SYSTEM_BIAS 0x00800000 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_NAVIC_INTER_SYSTEM_BIAS 0x01000000 +#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME 0x02000000 +#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME_EXT 0x04000000 typedef struct { - size_t size; - uint8_t seqNum; - /**< Current message Number */ - uint8_t maxMessageNum; - /**< Maximum number of message that will be sent for present time epoch. */ + uint32_t size; + // see defines in GNSS_SV_MEAS_HEADER_HAS_XXX_XXX + uint64_t flags; - bool leapSecValid; Gnss_LeapSecondInfoStructType leapSec; - Gnss_InterSystemBiasStructType gpsGloInterSystemBias; + Gnss_LocRcvrClockFrequencyInfoStructType clockFreq; /* Freq */ - Gnss_InterSystemBiasStructType gpsBdsInterSystemBias; + Gnss_ApTimeStampStructType apBootTimeStamp; + Gnss_InterSystemBiasStructType gpsGloInterSystemBias; + Gnss_InterSystemBiasStructType gpsBdsInterSystemBias; Gnss_InterSystemBiasStructType gpsGalInterSystemBias; - Gnss_InterSystemBiasStructType bdsGloInterSystemBias; - Gnss_InterSystemBiasStructType galGloInterSystemBias; - Gnss_InterSystemBiasStructType galBdsInterSystemBias; + Gnss_InterSystemBiasStructType gpsNavicInterSystemBias; + Gnss_InterSystemBiasStructType galNavicInterSystemBias; + Gnss_InterSystemBiasStructType gloNavicInterSystemBias; + Gnss_InterSystemBiasStructType bdsNavicInterSystemBias; + Gnss_InterSystemBiasStructType gpsL1L5TimeBias; + Gnss_InterSystemBiasStructType galE1E5aTimeBias; + + GnssSystemTimeStructType gpsSystemTime; + GnssSystemTimeStructType galSystemTime; + GnssSystemTimeStructType bdsSystemTime; + GnssSystemTimeStructType qzssSystemTime; + GnssSystemTimeStructType navicSystemTime; + GnssGloTimeStructType gloSystemTime; + + /** GPS system RTC time information. */ + Gnss_LocGnssTimeExtStructType gpsSystemTimeExt; + /** GAL system RTC time information. */ + Gnss_LocGnssTimeExtStructType galSystemTimeExt; + /** BDS system RTC time information. */ + Gnss_LocGnssTimeExtStructType bdsSystemTimeExt; + /** QZSS system RTC time information. */ + Gnss_LocGnssTimeExtStructType qzssSystemTimeExt; + /** GLONASS system RTC time information. */ + Gnss_LocGnssTimeExtStructType gloSystemTimeExt; + /** NAVIC system RTC time information. */ + Gnss_LocGnssTimeExtStructType navicSystemTimeExt; +} GnssSvMeasurementHeader; - bool clockFreqValid; - Gnss_LocRcvrClockFrequencyInfoStructType clockFreq; /* Freq */ - bool gnssMeasValid; - Gnss_ClockMeasurementStructType gnssMeas; - Gnss_ApTimeStampStructType timeStamp; +typedef struct { + uint32_t size; + bool isNhz; + GnssSvMeasurementHeader svMeasSetHeader; + uint32_t svMeasCount; + Gnss_SVMeasurementStructType svMeas[GNSS_LOC_SV_MEAS_LIST_MAX_SIZE]; } GnssSvMeasurementSet; +typedef struct { + uint32_t size; // set to sizeof(GnssMeasurements) + GnssSvMeasurementSet gnssSvMeasurementSet; + GnssMeasurementsNotification gnssMeasNotification; +} GnssMeasurements; + typedef enum { GNSS_SV_POLY_COEFF_VALID = 0x01, @@ -1200,7 +1551,7 @@ typedef enum typedef struct { - size_t size; + uint32_t size; uint16_t gnssSvId; /* GPS: 1-32, GLO: 65-96, 0: Invalid, SBAS: 120-151, BDS:201-237,GAL:301 to 336 @@ -1209,10 +1560,8 @@ typedef struct int8_t freqNum; /* Freq index, only valid if u_SysInd is GLO */ - uint8_t svPolyFlags; - /* Indicate the validity of the elements - as per Gnss_SvPolyStatusMaskType - */ + GnssSvPolyStatusMaskValidity svPolyStatusMaskValidity; + GnssSvPolyStatusMask svPolyStatusMask; uint32_t is_valid; @@ -1244,8 +1593,518 @@ typedef struct double velCoef[GNSS_SV_POLY_VELOCITY_COEF_MAX_SIZE]; /* Coefficients of velocity poly */ uint32_t enhancedIOD; /* Enhanced Reference Time */ + float gpsIscL1ca; + float gpsIscL2c; + float gpsIscL5I5; + float gpsIscL5Q5; + float gpsTgd; + float gloTgdG1G2; + float bdsTgdB1; + float bdsTgdB2; + float bdsTgdB2a; + float bdsIscB2a; + float galBgdE1E5a; + float galBgdE1E5b; + float navicTgdL5; } GnssSvPolynomial; +typedef enum { + GNSS_EPH_ACTION_UPDATE_SRC_UNKNOWN_V02 = 0, /**<Update ephemeris. Source of ephemeris is unknown */ + GNSS_EPH_ACTION_UPDATE_SRC_OTA_V02 = 1, /**<Update ephemeris. Source of ephemeris is OTA */ + GNSS_EPH_ACTION_UPDATE_SRC_NETWORK_V02 = 2, /**<Update ephemeris. Source of ephemeris is Network */ + GNSS_EPH_ACTION_UPDATE_MAX_V02 = 999, /**<Max value for update ephemeris action. DO NOT USE */ + GNSS_EPH_ACTION_DELETE_SRC_UNKNOWN_V02 = 1000, /**<Delete previous ephemeris from unknown source */ + GNSS_EPH_ACTION_DELETE_SRC_NETWORK_V02 = 1001, /**<Delete previous ephemeris from network */ + GNSS_EPH_ACTION_DELETE_SRC_OTA_V02 = 1002, /**<Delete previous ephemeris from OTA */ + GNSS_EPH_ACTION_DELETE_MAX_V02 = 1999, /**<Max value for delete ephemeris action. DO NOT USE */ +} GnssEphAction; + +typedef enum { + GAL_EPH_SIGNAL_SRC_UNKNOWN_V02 = 0, /**< GALILEO signal is unknown */ + GAL_EPH_SIGNAL_SRC_E1B_V02 = 1, /**< GALILEO signal is E1B */ + GAL_EPH_SIGNAL_SRC_E5A_V02 = 2, /**< GALILEO signal is E5A */ + GAL_EPH_SIGNAL_SRC_E5B_V02 = 3, /**< GALILEO signal is E5B */ +} GalEphSignalSource; + +typedef struct { + uint16_t gnssSvId; + /**< GNSS SV ID. + - Type: uint16 + \begin{itemize1} + \item Range: \begin{itemize1} + \item For GPS: 1 to 32 + \item For QZSS: 193 to 197 + \item For BDS: 201 to 237 + \item For GAL: 301 to 336 + \vspace{-0.18in} \end{itemize1} \end{itemize1} */ + + GnssEphAction updateAction; + /**< Specifies the action and source of ephemeris. \n + - Type: int32 enum */ + + uint16_t IODE; + /**< Issue of data ephemeris used (unit-less). \n + GPS: IODE 8 bits.\n + BDS: AODE 5 bits. \n + GAL: SIS IOD 10 bits. \n + - Type: uint16 + - Units: Unit-less */ + + double aSqrt; + /**< Square root of semi-major axis. \n + - Type: double + - Units: Square Root of Meters */ + + double deltaN; + /**< Mean motion difference from computed value. \n + - Type: double + - Units: Radians/Second */ + + double m0; + /**< Mean anomaly at reference time. \n + - Type: double + - Units: Radians */ + + double eccentricity; + /**< Eccentricity . \n + - Type: double + - Units: Unit-less */ + + double omega0; + /**< Longitude of ascending node of orbital plane at the weekly epoch. \n + - Type: double + - Units: Radians */ + + double i0; + /**< Inclination angle at reference time. \n + - Type: double + - Units: Radians */ + + double omega; + /**< Argument of Perigee. \n + - Type: double + - Units: Radians */ + + double omegaDot; + /**< Rate of change of right ascension. \n + - Type: double + - Units: Radians/Second */ + + double iDot; + /**< Rate of change of inclination angle. \n + - Type: double + - Units: Radians/Second */ + + double cUc; + /**< Amplitude of the cosine harmonic correction term to the argument of latitude. \n + - Type: double + - Units: Radians */ + + double cUs; + /**< Amplitude of the sine harmonic correction term to the argument of latitude. \n + - Type: double + - Units: Radians */ + + double cRc; + /**< Amplitude of the cosine harmonic correction term to the orbit radius. \n + - Type: double + - Units: Meters */ + + double cRs; + /**< Amplitude of the sine harmonic correction term to the orbit radius. \n + - Type: double + - Units: Meters */ + + double cIc; + /**< Amplitude of the cosine harmonic correction term to the angle of inclination. \n + - Type: double + - Units: Radians */ + + double cIs; + /**< Amplitude of the sine harmonic correction term to the angle of inclination. \n + - Type: double + - Units: Radians */ + + uint32_t toe; + /**< Reference time of ephemeris. \n + - Type: uint32 + - Units: Seconds */ + + uint32_t toc; + /**< Clock data reference time of week. \n + - Type: uint32 + - Units: Seconds */ + + double af0; + /**< Clock bias correction coefficient. \n + - Type: double + - Units: Seconds */ + + double af1; + /**< Clock drift coefficient. \n + - Type: double + - Units: Seconds/Second */ + + double af2; + /**< Clock drift rate correction coefficient. \n + - Type: double + - Units: Seconds/Seconds^2 */ + +} GnssEphCommon; + +/* GPS Navigation Model Info */ +typedef struct { + GnssEphCommon commonEphemerisData; + /**< Common ephemeris data. */ + + uint8_t signalHealth; + /**< Signal health. \n + Bit 0 : L5 Signal Health. \n + Bit 1 : L2 Signal Health. \n + Bit 2 : L1 Signal Health. \n + - Type: uint8 + - Values: 3 bit mask of signal health, where set bit indicates unhealthy signal */ + + uint8_t URAI; + /**< User Range Accuracy Index. \n + - Type: uint8 + - Units: Unit-less */ + + uint8_t codeL2; + /**< Indicates which codes are commanded ON for the L2 channel (2-bits). \n + - Type: uint8 + Valid Values: \n + - 00 : Reserved + - 01 : P code ON + - 10 : C/A code ON */ + + uint8_t dataFlagL2P; + /**< L2 P-code indication flag. \n + - Type: uint8 + - Value 1 indicates that the Nav data stream was commanded OFF on the P-code of the L2 channel. */ + + double tgd; + /**< Time of group delay. \n + - Type: double + - Units: Seconds */ + + uint8_t fitInterval; + /**< Indicates the curve-fit interval used by the CS. \n + - Type: uint8 + Valid Values: + - 0 : Four hours + - 1 : Greater than four hours */ + + uint16_t IODC; + /**< Issue of Data, Clock. \n + - Type: uint16 + - Units: Unit-less */ +} GpsEphemeris; + +/* GLONASS Navigation Model Info */ +typedef struct { + + uint16_t gnssSvId; + /**< GNSS SV ID. + - Type: uint16 + - Range: 65 to 96 if known. When the slot number to SV ID mapping is unknown, set to 255 */ + + GnssEphAction updateAction; + /**< Specifies the action and source of ephemeris. \n + - Type: int32 enum */ + + uint8_t bnHealth; + /**< SV health flags. \n + - Type: uint8 + Valid Values: \n + - 0 : Healthy + - 1 : Unhealthy */ + + uint8_t lnHealth; + /**< Ln SV health flags. GLONASS-M. \n + - Type: uint8 + Valid Values: \n + - 0 : Healthy + - 1 : Unhealthy */ + + uint8_t tb; + /**< Index of a time interval within current day according to UTC(SU) + 03 hours 00 min. \n + - Type: uint8 + - Units: Unit-less */ + + uint8_t ft; + /**< SV accuracy index. \n + - Type: uint8 + - Units: Unit-less */ + + uint8_t gloM; + /**< GLONASS-M flag. \n + - Type: uint8 + Valid Values: \n + - 0 : GLONASS + - 1 : GLONASS-M */ + + uint8_t enAge; + /**< Characterizes "Age" of current information. \n + - Type: uint8 + - Units: Days */ + + uint8_t gloFrequency; + /**< GLONASS frequency number + 8. \n + - Type: uint8 + - Range: 1 to 14 + */ + + uint8_t p1; + /**< Time interval between two adjacent values of tb parameter. \n + - Type: uint8 + - Units: Minutes */ + + uint8_t p2; + /**< Flag of oddness ("1") or evenness ("0") of the value of tb \n + for intervals 30 or 60 minutes. \n + - Type: uint8 */ + + float deltaTau; + /**< Time difference between navigation RF signal transmitted in L2 sub-band \n + and aviation RF signal transmitted in L1 sub-band. \n + - Type: floating point + - Units: Seconds */ + + double position[3]; + /**< Satellite XYZ position. \n + - Type: array of doubles + - Units: Meters */ + + double velocity[3]; + /**< Satellite XYZ velocity. \n + - Type: array of doubles + - Units: Meters/Second */ + + double acceleration[3]; + /**< Satellite XYZ sola-luni acceleration. \n + - Type: array of doubles + - Units: Meters/Second^2 */ + + float tauN; + /**< Satellite clock correction relative to GLONASS time. \n + - Type: floating point + - Units: Seconds */ + + float gamma; + /**< Relative deviation of predicted carrier frequency value \n + from nominal value at the instant tb. \n + - Type: floating point + - Units: Unit-less */ + + double toe; + /**< Complete ephemeris time, including N4, NT and Tb. \n + [(N4-1)*1461 + (NT-1)]*86400 + tb*900 \n + - Type: double + - Units: Seconds */ + + uint16_t nt; + /**< Current date, calendar number of day within four-year interval. \n + Starting from the 1-st of January in a leap year. \n + - Type: uint16 + - Units: Days */ +} GlonassEphemeris; + +/* BDS Navigation Model Info */ +typedef struct { + + GnssEphCommon commonEphemerisData; + /**< Common ephemeris data. */ + + uint8_t svHealth; + /**< Satellite health information applied to both B1 and B2 (SatH1). \n + - Type: uint8 + Valid Values: \n + - 0 : Healthy + - 1 : Unhealthy */ + + uint8_t AODC; + /**< Age of data clock. \n + - Type: uint8 + - Units: Hours */ + + double tgd1; + /**< Equipment group delay differential on B1 signal. \n + - Type: double + - Units: Nano-Seconds */ + + double tgd2; + /**< Equipment group delay differential on B2 signal. \n + - Type: double + - Units: Nano-Seconds */ + + uint8_t URAI; + /**< User range accuracy index (4-bits). \n + - Type: uint8 + - Units: Unit-less */ +} BdsEphemeris; + +/* GALIELO Navigation Model Info */ +typedef struct { + + GnssEphCommon commonEphemerisData; + /**< Common ephemeris data. */ + + GalEphSignalSource dataSourceSignal; + /**< Galileo Signal Source. \n + Valid Values: \n + - GAL_EPH_SIGNAL_SRC_UNKNOWN (0) -- GALILEO signal is unknown + - GAL_EPH_SIGNAL_SRC_E1B (1) -- GALILEO signal is E1B + - GAL_EPH_SIGNAL_SRC_E5A (2) -- GALILEO signal is E5A + - GAL_EPH_SIGNAL_SRC_E5B (3) -- GALILEO signal is E5B */ + + uint8_t sisIndex; + /**< Signal-in-space index for dual frequency E1-E5b/E5a depending on dataSignalSource. \n + - Type: uint8 + - Units: Unit-less */ + + double bgdE1E5a; + /**< E1-E5a Broadcast group delay from F/Nav (E5A). \n + - Type: double + - Units: Seconds */ + + double bgdE1E5b; + /**< E1-E5b Broadcast group delay from I/Nav (E1B or E5B). \n + For E1B or E5B signal, both bgdE1E5a and bgdE1E5b are valid. \n + For E5A signal, only bgdE1E5a is valid. \n + Signal source identified using dataSignalSource. \n + - Type: double + - Units: Seconds */ + + uint8_t svHealth; + /**< SV health status of signal identified by dataSourceSignal. \n + - Type: uint8 + Valid Values: \n + - 0 : Healthy + - 1 : Unhealthy */ +} GalileoEphemeris; + +/** GPS Navigation model for each SV */ +typedef struct { + uint16_t numOfEphemeris; + GpsEphemeris gpsEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02]; +} GpsEphemerisResponse; + +/** GLONASS Navigation model for each SV */ +typedef struct { + uint16_t numOfEphemeris; + GlonassEphemeris gloEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02]; +} GlonassEphemerisResponse; + +/** BDS Navigation model for each SV */ +typedef struct { + uint16_t numOfEphemeris; + BdsEphemeris bdsEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02]; +} BdsEphemerisResponse; + +/** GALILEO Navigation model for each SV */ +typedef struct { + uint16_t numOfEphemeris; + GalileoEphemeris galEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02]; +} GalileoEphemerisResponse; + +/** QZSS Navigation model for each SV */ +typedef struct { + uint16_t numOfEphemeris; + GpsEphemeris qzssEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02]; +} QzssEphemerisResponse; + + +typedef struct { + /** Indicates GNSS Constellation Type + Mandatory field */ + Gnss_LocSvSystemEnumType gnssConstellation; + + /** GPS System Time of the ephemeris report */ + bool isSystemTimeValid; + GnssSystemTimeStructType systemTime; + + union { + /** GPS Ephemeris */ + GpsEphemerisResponse gpsEphemeris; + /** GLONASS Ephemeris */ + GlonassEphemerisResponse glonassEphemeris; + /** BDS Ephemeris */ + BdsEphemerisResponse bdsEphemeris; + /** GALILEO Ephemeris */ + GalileoEphemerisResponse galileoEphemeris; + /** QZSS Ephemeris */ + QzssEphemerisResponse qzssEphemeris; + } ephInfo; +} GnssSvEphemerisReport; + +typedef struct { + /** GPS System Time of the iono model report */ + bool isSystemTimeValid; + GnssSystemTimeStructType systemTime; + + /** Indicates GNSS Constellation Type */ + Gnss_LocSvSystemEnumType gnssConstellation; + + float alpha0; + /**< Klobuchar Model Parameter Alpha 0. + - Type: float + - Unit: Seconds + */ + + float alpha1; + /**< Klobuchar Model Parameter Alpha 1. + - Type: float + - Unit: Seconds / Semi-Circle + */ + + float alpha2; + /**< Klobuchar Model Parameter Alpha 2. + - Type: float + - Unit: Seconds / Semi-Circle^2 + */ + + float alpha3; + /**< Klobuchar Model Parameter Alpha 3. + - Type: float + - Unit: Seconds / Semi-Circle^3 + */ + + float beta0; + /**< Klobuchar Model Parameter Beta 0. + - Type: float + - Unit: Seconds + */ + + float beta1; + /**< Klobuchar Model Parameter Beta 1. + - Type: float + - Unit: Seconds / Semi-Circle + */ + + float beta2; + /**< Klobuchar Model Parameter Beta 2. + - Type: float + - Unit: Seconds / Semi-Circle^2 + */ + + float beta3; + /**< Klobuchar Model Parameter Beta 3. + - Type: float + - Unit: Seconds / Semi-Circle^3 + */ +} GnssKlobucharIonoModel; + +typedef struct { + /** GPS System Time of the report */ + bool isSystemTimeValid; + GnssSystemTimeStructType systemTime; + + GnssAdditionalSystemInfoMask validityMask; + double tauC; + int8_t leapSec; +} GnssAdditionalSystemInfo; + /* Various Short Range Node Technology type*/ typedef enum { SRN_AP_DATA_TECH_TYPE_NONE, @@ -1266,44 +2125,114 @@ typedef enum { typedef struct { - size_t size; + uint32_t size; Gnss_SrnTech srnTechType; /* SRN Technology type in request */ bool srnRequest; /* scan - start(true) or stop(false) */ bool e911Mode; /* If in E911 emergency */ Gnss_Srn_MacAddr_Type macAddrType; /* SRN AP MAC Address type */ } GnssSrnDataReq; +/* Mask indicating enabled or disabled constellations */ +typedef uint64_t GnssSvTypesMask; +typedef enum { + GNSS_SV_TYPES_MASK_GLO_BIT = (1<<0), + GNSS_SV_TYPES_MASK_BDS_BIT = (1<<1), + GNSS_SV_TYPES_MASK_QZSS_BIT = (1<<2), + GNSS_SV_TYPES_MASK_GAL_BIT = (1<<3), + GNSS_SV_TYPES_MASK_NAVIC_BIT = (1<<4), +} GnssSvTypesMaskBits; + +/* This SV Type config is injected directly to GNSS Adapter + * bypassing Location API */ +typedef struct { + uint32_t size; // set to sizeof(GnssSvTypeConfig) + // Enabled Constellations + GnssSvTypesMask enabledSvTypesMask; + // Disabled Constellations + GnssSvTypesMask blacklistedSvTypesMask; +} GnssSvTypeConfig; + +/* Provides the current GNSS SV Type configuration to the client. + * This is fetched via direct call to GNSS Adapter bypassing + * Location API */ +typedef std::function<void( + const GnssSvTypeConfig& config +)> GnssSvTypeConfigCallback; + /* * Represents the status of AGNSS augmented to support IPv4. */ struct AGnssExtStatusIpV4 { - AGpsExtType type; - LocAGpsStatusValue status; + AGpsExtType type; + LocApnTypeMask apnTypeMask; + LocAGpsStatusValue status; /* * 32-bit IPv4 address. */ - uint32_t ipV4Addr; + uint32_t ipV4Addr; }; /* * Represents the status of AGNSS augmented to support IPv6. */ struct AGnssExtStatusIpV6 { - AGpsExtType type; - LocAGpsStatusValue status; + AGpsExtType type; + LocApnTypeMask apnTypeMask; + LocAGpsStatusValue status; /* * 128-bit IPv6 address. */ - uint8_t ipV6Addr[16]; + uint8_t ipV6Addr[16]; }; +/* +* Represents the the Nfw Notification structure +*/ +#define GNSS_MAX_NFW_APP_STRING_LEN 64 +#define GNSS_MAX_NFW_STRING_LEN 20 + +typedef enum { + GNSS_NFW_CTRL_PLANE = 0, + GNSS_NFW_SUPL = 1, + GNSS_NFW_IMS = 10, + GNSS_NFW_SIM = 11, + GNSS_NFW_OTHER_PROTOCOL_STACK = 100 +} GnssNfwProtocolStack; + +typedef enum { + GNSS_NFW_CARRIER = 0, + GNSS_NFW_OEM = 10, + GNSS_NFW_MODEM_CHIPSET_VENDOR = 11, + GNSS_NFW_GNSS_CHIPSET_VENDOR = 12, + GNSS_NFW_OTHER_CHIPSET_VENDOR = 13, + GNSS_NFW_AUTOMOBILE_CLIENT = 20, + GNSS_NFW_OTHER_REQUESTOR = 100 +} GnssNfwRequestor; + +typedef enum { + GNSS_NFW_REJECTED = 0, + GNSS_NFW_ACCEPTED_NO_LOCATION_PROVIDED = 1, + GNSS_NFW_ACCEPTED_LOCATION_PROVIDED = 2, +} GnssNfwResponseType; + +typedef struct { + char proxyAppPackageName[GNSS_MAX_NFW_APP_STRING_LEN]; + GnssNfwProtocolStack protocolStack; + char otherProtocolStackName[GNSS_MAX_NFW_STRING_LEN]; + GnssNfwRequestor requestor; + char requestorId[GNSS_MAX_NFW_STRING_LEN]; + GnssNfwResponseType responseType; + bool inEmergencyMode; + bool isCachedLocation; +} GnssNfwNotification; + /* ODCPI Request Info */ enum OdcpiRequestType { ODCPI_REQUEST_TYPE_START, ODCPI_REQUEST_TYPE_STOP }; struct OdcpiRequestInfo { - size_t size; + uint32_t size; OdcpiRequestType type; uint32_t tbfMillis; bool isEmergencyMode; @@ -1319,6 +2248,12 @@ typedef std::function<void(const OdcpiRequestInfo& request)> OdcpiRequestCallbac typedef void (*AgnssStatusIpV4Cb)(AGnssExtStatusIpV4 status); /* +* Callback with NFW information. +*/ +typedef void(*NfwStatusCb)(GnssNfwNotification notification); +typedef bool(*IsInEmergencySession)(void); + +/* * Callback with AGNSS(IpV6) status information. * * @param status Will be of type AGnssExtStatusIpV6. @@ -1332,8 +2267,21 @@ typedef void (*LocAgpsOpenResultCb)(bool isSuccess, AGpsExtType agpsType, const typedef void (*LocAgpsCloseResultCb)(bool isSuccess, AGpsExtType agpsType, void* userDataPtr); /* Shared resources of LocIpc */ -#define LOC_IPC_HAL "/dev/socket/location/socket_hal" -#define LOC_IPC_XTRA "/dev/socket/location/xtra/socket_xtra" +#define LOC_IPC_HAL "/dev/socket/location/socket_hal" +#define LOC_IPC_XTRA "/dev/socket/location/xtra/socket_xtra" + +#define SOCKET_DIR_LOCATION "/dev/socket/location/" +#define SOCKET_DIR_EHUB "/dev/socket/location/ehub/" +#define SOCKET_TO_LOCATION_HAL_DAEMON "/dev/socket/loc_client/hal_daemon" + +#define SOCKET_LOC_CLIENT_DIR "/dev/socket/loc_client/" +#define EAP_LOC_CLIENT_DIR "/data/vendor/location/extap_locclient/" + +#define LOC_CLIENT_NAME_PREFIX "toclient" + +typedef uint64_t NetworkHandle; +#define NETWORK_HANDLE_UNKNOWN ~0 +#define MAX_NETWORK_HANDLES 10 #ifdef __cplusplus } diff --git a/gps/utils/linked_list.h b/gps/utils/linked_list.h index a85f09a..0b33ecb 100644 --- a/gps/utils/linked_list.h +++ b/gps/utils/linked_list.h @@ -50,6 +50,8 @@ typedef enum /**< Failed because an there were not enough resources. */ eLINKED_LIST_INSUFFICIENT_BUFFER = -5, /**< Failed because an the supplied buffer was too small. */ + eLINKED_LIST_EMPTY = -6 + /**< Failed because list is empty. */ }linked_list_err_type; /*=========================================================================== diff --git a/gps/utils/loc_cfg.cpp b/gps/utils/loc_cfg.cpp index e646ea8..8baf8ca 100644 --- a/gps/utils/loc_cfg.cpp +++ b/gps/utils/loc_cfg.cpp @@ -37,7 +37,7 @@ #include <ctype.h> #include <unistd.h> #include <time.h> -#include <pwd.h> +#include <grp.h> #include <errno.h> #include <loc_cfg.h> #include <loc_pla.h> @@ -57,14 +57,15 @@ /* Parameter data */ static uint32_t DEBUG_LEVEL = 0xff; static uint32_t TIMESTAMP = 0; -static uint32_t LOC_MODEM_EMULATOR = 0; +static uint32_t DATUM_TYPE = 0; +static bool sVendorEnhanced = true; /* Parameter spec table */ static const loc_param_s_type loc_param_table[] = { {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'}, {"TIMESTAMP", &TIMESTAMP, NULL, 'n'}, - {"LOC_MODEM_EMULATOR", &LOC_MODEM_EMULATOR, NULL, 'n'}, + {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'}, }; static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type); @@ -87,21 +88,34 @@ const char LOC_PATH_APDR_CONF[] = LOC_PATH_APDR_CONF_STR; const char LOC_PATH_XTWIFI_CONF[] = LOC_PATH_XTWIFI_CONF_STR; const char LOC_PATH_QUIPC_CONF[] = LOC_PATH_QUIPC_CONF_STR; -bool isXtraDaemonEnabled() { - bool enabled = property_get_bool("persist.sys.xtra-daemon.enabled", false); - LOC_LOGe("xtra-daemon enabled: %d\n", enabled); - return enabled; +bool isVendorEnhanced() { + return sVendorEnhanced; +} +void setVendorEnhanced(bool vendorEnhanced) { + sVendorEnhanced = vendorEnhanced; } /*=========================================================================== -FUNCTION loc_modem_emulator_enabled +FUNCTION loc_get_datum_type DESCRIPTION - Provides access to Modem Emulator config item. + get datum type + +PARAMETERS: + N/A + +DEPENDENCIES + N/A + +RETURN VALUE + DATUM TYPE + +SIDE EFFECTS + N/A ===========================================================================*/ -uint32_t loc_modem_emulator_enabled() +int loc_get_datum_type() { - return LOC_MODEM_EMULATOR; + return DATUM_TYPE; } /*=========================================================================== @@ -147,7 +161,7 @@ int loc_set_config_entry(const loc_param_s_type* config_entry, loc_param_v_type* else { strlcpy((char*) config_entry->param_ptr, config_value->param_str_value, - LOC_MAX_PARAM_STRING + 1); + LOC_MAX_PARAM_STRING); } /* Log INI values */ LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__, @@ -446,19 +460,18 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta #define CONFIG_MASK_AUTOPLATFORM_ALL 0x10 #define CONFIG_MASK_AUTOPLATFORM_FOUND 0x20 #define CONFIG_MASK_AUTOPLATFORM_CHECK 0x30 +#define CONFIG_MASK_SOCID_ALL 0x40 +#define CONFIG_MASK_SOCID_FOUND 0x80 +#define CONFIG_MASK_SOCID_CHECK 0xc0 #define LOC_FEATURE_MASK_GTP_WIFI_BASIC 0x01 #define LOC_FEATURE_MASK_GTP_WIFI_PREMIUM 0X02 #define LOC_FEATURE_MASK_GTP_CELL_BASIC 0X04 #define LOC_FEATURE_MASK_GTP_CELL_PREMIUM 0X08 -#define LOC_FEATURE_MASK_GTP_AP_CELL_BASIC LOC_FEATURE_MASK_GTP_CELL_BASIC -#define LOC_FEATURE_MASK_GTP_AP_CELL_PREMIUM LOC_FEATURE_MASK_GTP_CELL_PREMIUM #define LOC_FEATURE_MASK_SAP_BASIC 0x40 #define LOC_FEATURE_MASK_SAP_PREMIUM 0X80 #define LOC_FEATURE_MASK_GTP_WAA_BASIC 0X100 -#define LOC_FEATURE_MASK_GTP_WAA_PREMIUM 0x200 #define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC 0X400 -#define LOC_FEATURE_MASK_GTP_MODEM_CELL_PREMIUM 0X800 #define LOC_FEATURE_MASK_ODCPI 0x1000 #define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT 0x2000 #define LOC_FEATURE_MASK_SUPL_WIFI 0x4000 @@ -473,17 +486,18 @@ typedef struct { unsigned int loc_feature_mask; char platform_list[LOC_MAX_PARAM_STRING]; char baseband[LOC_MAX_PARAM_STRING]; + char low_ram_targets[LOC_MAX_PARAM_STRING]; + char soc_id_list[LOC_MAX_PARAM_STRING]; unsigned int sglte_target; - char feature_gtp_cell_proc[LOC_MAX_PARAM_STRING]; + char feature_gtp_mode[LOC_MAX_PARAM_STRING]; char feature_gtp_waa[LOC_MAX_PARAM_STRING]; - char feature_gtp_cell[LOC_MAX_PARAM_STRING]; - char feature_gtp_wifi[LOC_MAX_PARAM_STRING]; char feature_sap[LOC_MAX_PARAM_STRING]; char feature_odcpi[LOC_MAX_PARAM_STRING]; char feature_free_wifi_scan_inject[LOC_MAX_PARAM_STRING]; char feature_supl_wifi[LOC_MAX_PARAM_STRING]; char feature_wifi_supplicant_info[LOC_MAX_PARAM_STRING]; char auto_platform[LOC_MAX_PARAM_STRING]; + unsigned int vendor_enhanced_process; } loc_launcher_conf; /* process configuration parameters */ @@ -496,9 +510,7 @@ static const loc_param_s_type gps_conf_parameter_table[] = { /* location feature conf, e.g.: izat.conf feature mode table*/ static const loc_param_s_type loc_feature_conf_table[] = { - {"GTP_CELL_PROC", &conf.feature_gtp_cell_proc, NULL, 's'}, - {"GTP_CELL", &conf.feature_gtp_cell, NULL, 's'}, - {"GTP_WIFI", &conf.feature_gtp_wifi, NULL, 's'}, + {"GTP_MODE", &conf.feature_gtp_mode, NULL, 's'}, {"GTP_WAA", &conf.feature_gtp_waa, NULL, 's'}, {"SAP", &conf.feature_sap, NULL, 's'}, {"ODCPI", &conf.feature_odcpi, NULL, 's'}, @@ -509,15 +521,18 @@ static const loc_param_s_type loc_feature_conf_table[] = { /* location process conf, e.g.: izat.conf Parameter spec table */ static const loc_param_s_type loc_process_conf_parameter_table[] = { - {"PROCESS_NAME", &conf.proc_name, NULL, 's'}, - {"PROCESS_ARGUMENT", &conf.proc_argument, NULL, 's'}, - {"PROCESS_STATE", &conf.proc_status, NULL, 's'}, - {"PROCESS_GROUPS", &conf.group_list, NULL, 's'}, - {"PREMIUM_FEATURE", &conf.premium_feature, NULL, 'n'}, - {"IZAT_FEATURE_MASK", &conf.loc_feature_mask, NULL, 'n'}, - {"PLATFORMS", &conf.platform_list, NULL, 's'}, - {"BASEBAND", &conf.baseband, NULL, 's'}, - {"HARDWARE_TYPE", &conf.auto_platform, NULL, 's'}, + {"PROCESS_NAME", &conf.proc_name, NULL, 's'}, + {"PROCESS_ARGUMENT", &conf.proc_argument, NULL, 's'}, + {"PROCESS_STATE", &conf.proc_status, NULL, 's'}, + {"PROCESS_GROUPS", &conf.group_list, NULL, 's'}, + {"PREMIUM_FEATURE", &conf.premium_feature, NULL, 'n'}, + {"IZAT_FEATURE_MASK", &conf.loc_feature_mask, NULL, 'n'}, + {"PLATFORMS", &conf.platform_list, NULL, 's'}, + {"SOC_IDS", &conf.soc_id_list, NULL, 's'}, + {"BASEBAND", &conf.baseband, NULL, 's'}, + {"LOW_RAM_TARGETS", &conf.low_ram_targets, NULL, 's'}, + {"HARDWARE_TYPE", &conf.auto_platform, NULL, 's'}, + {"VENDOR_ENHANCED_PROCESS", &conf.vendor_enhanced_process, NULL, 'n'}, }; /*=========================================================================== @@ -553,17 +568,17 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p gid_t gid_list[LOC_PROCESS_MAX_NUM_GROUPS]; char *split_strings[MAX_NUM_STRINGS]; int name_length=0, group_list_length=0, platform_length=0, baseband_length=0, ngroups=0, ret=0; - int auto_platform_length = 0; + int auto_platform_length = 0, soc_id_list_length=0; int group_index=0, nstrings=0, status_length=0; FILE* conf_fp = nullptr; char platform_name[PROPERTY_VALUE_MAX], baseband_name[PROPERTY_VALUE_MAX]; - char autoplatform_name[PROPERTY_VALUE_MAX]; + int low_ram_target=0; + char autoplatform_name[PROPERTY_VALUE_MAX], socid_value[PROPERTY_VALUE_MAX]; unsigned int loc_service_mask=0; - char config_mask = 0; + unsigned char config_mask = 0; unsigned char proc_list_length=0; int gtp_cell_ap_enabled = 0; char arg_gtp_waa[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; - char arg_gtp_ap_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; char arg_gtp_modem_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; char arg_gtp_wifi[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; char arg_sap[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; @@ -580,7 +595,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p //Form argument strings strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); - strlcat(arg_gtp_ap_cell, LOC_FEATURE_GTP_AP_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); strlcat(arg_gtp_modem_cell, LOC_FEATURE_GTP_MODEM_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); strlcat(arg_gtp_wifi, LOC_FEATURE_GTP_WIFI, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); strlcat(arg_sap, LOC_FEATURE_SAP, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); @@ -591,86 +605,42 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p loc_get_target_baseband(baseband_name, sizeof(baseband_name)); //Identify if this is an automotive platform loc_get_auto_platform_name(autoplatform_name,sizeof(autoplatform_name)); + //Identify if this is a low ram target from ro.config.low_ram property + low_ram_target = loc_identify_low_ram_target(); + // Get the soc-id for this device. + loc_get_device_soc_id(socid_value, sizeof(socid_value)); UTIL_READ_CONF(conf_file_name, loc_feature_conf_table); - //Set service mask for GTP_WIFI - if(strcmp(conf.feature_gtp_wifi, "DISABLED") == 0) { - LOC_LOGD("%s:%d]: GTP WIFI DISABLED", __func__, __LINE__); + //Set service mask for GTP_MODE + if(strcmp(conf.feature_gtp_mode, "DISABLED") == 0) { + LOC_LOGD("%s:%d]: GTP MODE DISABLED", __func__, __LINE__); } - else if(strcmp(conf.feature_gtp_wifi, "BASIC") == 0) { - LOC_LOGD("%s:%d]: Setting GTP WIFI to mode: BASIC", __func__, __LINE__); - loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC; + else if(strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) { + LOC_LOGD("%s:%d]: Setting GTP MODE to mode: LEGACY_WWAN", __func__, __LINE__); + loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; } - //conf file has a garbage value - else { - LOC_LOGE("%s:%d]: Unrecognized value for GTP WIFI Mode."\ - " Setting GTP WIFI to default mode: BASIC", __func__, __LINE__); + else if(strcmp(conf.feature_gtp_mode, "SDK") == 0) { + LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__); loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC; } - - //Set service mask for GTP_CELL - //Using a temp variable here to indicate wheter GTP cell is - //enabled on the AP or modem. This variable will be used in - //further checks below. An alternative was to compare the - //string again in each place which would've been more expensive - if(strcmp(conf.feature_gtp_cell_proc, "AP") == 0) { - gtp_cell_ap_enabled = 1; - } - - if(strcmp(conf.feature_gtp_cell, "PREMIUM") == 0) { - LOC_LOGE("%s:%d]: Error: location feature GTP CELL does not support PREMIUM mode" \ - " available modes are BASIC and DISABLED. Starting feature in BASIC mode", - __func__, __LINE__); - if(gtp_cell_ap_enabled) { - loc_service_mask |= LOC_FEATURE_MASK_GTP_AP_CELL_BASIC; - } - else { - loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; - } - } - else if(strcmp(conf.feature_gtp_cell, "BASIC") == 0) { - LOC_LOGD("%s:%d]: Setting GTP CELL to mode: BASIC", __func__, __LINE__); - if(gtp_cell_ap_enabled) { - loc_service_mask |= LOC_FEATURE_MASK_GTP_AP_CELL_BASIC; - } - else { - loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; - } - } - else if(strcmp(conf.feature_gtp_cell, "DISABLED") == 0) { - LOC_LOGD("%s:%d]: GTP CELL DISABLED", __func__, __LINE__); - } //conf file has a garbage value else { - LOC_LOGE("%s:%d]: Unrecognized value for GTP CELL Mode." \ - " Setting GTP CELL to default mode: BASIC", __func__, __LINE__); - if(gtp_cell_ap_enabled) { - loc_service_mask |= LOC_FEATURE_MASK_GTP_AP_CELL_BASIC; - } - else { - loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; - } + LOC_LOGE("%s:%d]: Unrecognized value for GTP MODE Mode."\ + " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__); } - //Set service mask for GTP_WAA - if(strcmp(conf.feature_gtp_waa, "PREMIUM") == 0) { - LOC_LOGE("%s:%d]: Error: location feature GTP WAA does not support PREMIUM mode" \ - " available modes are BASIC and DISABLED. Starting feature in BASIC mode", - __func__, __LINE__); - loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC; - } - else if(strcmp(conf.feature_gtp_waa, "BASIC") == 0) { - LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__); - loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC; + if(strcmp(conf.feature_gtp_waa, "BASIC") == 0) { + LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__); + loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC; } else if(strcmp(conf.feature_gtp_waa, "DISABLED") == 0) { - LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__); + LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__); } //conf file has a garbage value else { - LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\ - " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__); + LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\ + " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__); } //Set service mask for SAP @@ -682,6 +652,9 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p LOC_LOGD("%s:%d]: Setting SAP to mode: BASIC", __func__, __LINE__); loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC; } + else if(strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) { + LOC_LOGD("%s:%d]: Setting SAP to mode: MODEM_DEFAULT", __func__, __LINE__); + } else if(strcmp(conf.feature_sap, "DISABLED") == 0) { LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__); } @@ -808,18 +781,19 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p baseband_length = (int)strlen(conf.baseband); status_length = (int)strlen(conf.proc_status); auto_platform_length = (int)strlen(conf.auto_platform); + soc_id_list_length = (int)strlen(conf.soc_id_list); if(!name_length || !group_list_length || !platform_length || - !baseband_length || !status_length || !auto_platform_length) { + !baseband_length || !status_length || !auto_platform_length || !soc_id_list_length) { LOC_LOGE("%s:%d]: Error: i: %d; One of the parameters not specified in conf file", __func__, __LINE__, i); continue; } - if (strcmp(conf.proc_name, "xtra-daemon") == 0 && !isXtraDaemonEnabled()) { - LOC_LOGE("%s:%d]: Process xtra-daemon is disabled via property", - __func__, __LINE__); - child_proc[j].proc_status = DISABLED_FROM_CONF; + if (!isVendorEnhanced() && (conf.vendor_enhanced_process != 0)) { + LOC_LOGD("%s:%d]: Process %s is disabled via vendor enhanced process check", + __func__, __LINE__, conf.proc_name); + child_proc[j].proc_status = DISABLED_VIA_VENDOR_ENHANCED_CHECK; continue; } @@ -844,18 +818,15 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p child_proc[j].num_groups = 0; ngroups = loc_util_split_string(conf.group_list, split_strings, MAX_NUM_STRINGS, ' '); -#ifdef __ANDROID__ for(i=0; i<ngroups; i++) { - struct passwd* pwd = getpwnam(split_strings[i]); - if (pwd) { - child_proc[j].group_list[i] = pwd->pw_gid; + struct group* grp = getgrnam(split_strings[i]); + if (grp) { + child_proc[j].group_list[child_proc[j].num_groups] = grp->gr_gid; child_proc[j].num_groups++; - LOC_LOGD("%s:%d]:Group %s = %d matches child_group: %d\n", - __func__, __LINE__, split_strings[i], - pwd->pw_gid,child_proc[j].group_list[i]); + LOC_LOGd("Group %s = %d", split_strings[i], grp->gr_gid); } } -#endif + nstrings = loc_util_split_string(conf.platform_list, split_strings, MAX_NUM_STRINGS, ' '); if(strcmp("all", split_strings[0]) == 0) { if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) { @@ -884,6 +855,34 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } } + // SOC Id's check + nstrings = loc_util_split_string(conf.soc_id_list, split_strings, MAX_NUM_STRINGS, ' '); + if (strcmp("all", split_strings[0]) == 0) { + if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) { + LOC_LOGd("Enabled for all SOC ids\n"); + config_mask |= CONFIG_MASK_SOCID_ALL; + } + else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) { + config_mask |= CONFIG_MASK_SOCID_FOUND; + for (i = 2; i < nstrings; i++) { + if (strcmp(socid_value, split_strings[i]) == 0) { + LOC_LOGd("Disabled for SOC id %s\n", socid_value); + config_mask &= ~CONFIG_MASK_SOCID_FOUND; + break; + } + } + } + } + else { + for (i = 0; i < nstrings; i++) { + if (strcmp(socid_value, split_strings[i]) == 0) { + LOC_LOGd("Matched SOC id : %s\n", split_strings[i]); + config_mask |= CONFIG_MASK_SOCID_FOUND; + break; + } + } + } + nstrings = loc_util_split_string(conf.baseband, split_strings, MAX_NUM_STRINGS, ' '); if(strcmp("all", split_strings[0]) == 0) { if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) { @@ -936,10 +935,19 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } } + nstrings = loc_util_split_string(conf.low_ram_targets, split_strings, MAX_NUM_STRINGS, ' '); + if (!strcmp("DISABLED", split_strings[0]) && low_ram_target) { + LOC_LOGd("Disabled for low ram targets\n"); + child_proc[j].proc_status = DISABLED; + continue; + } + if((config_mask & CONFIG_MASK_TARGET_CHECK) && (config_mask & CONFIG_MASK_BASEBAND_CHECK) && (config_mask & CONFIG_MASK_AUTOPLATFORM_CHECK) && - (child_proc[j].proc_status != DISABLED_FROM_CONF)) { + (config_mask & CONFIG_MASK_SOCID_CHECK) && + (child_proc[j].proc_status != DISABLED_FROM_CONF) && + (child_proc[j].proc_status != DISABLED_VIA_VENDOR_ENHANCED_CHECK)) { //Set args //The first argument passed through argv is usually the name of the @@ -949,8 +957,7 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p i = 0; char* temp_arg = ('/' == child_proc[j].name[0][0]) ? (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0]; - i++; - strlcpy (child_proc[j].args[i], temp_arg, sizeof (child_proc[j].args[i])); + strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[i++])); if(conf.premium_feature) { if(conf.loc_feature_mask & loc_service_mask) { @@ -982,51 +989,13 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } if(conf.loc_feature_mask & (LOC_FEATURE_MASK_GTP_CELL_BASIC | LOC_FEATURE_MASK_GTP_CELL_PREMIUM )) { - if(loc_service_mask & LOC_FEATURE_MASK_GTP_AP_CELL_BASIC){ - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_basic, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_AP_CELL_PREMIUM){ - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) { + if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) { strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, LOC_PROCESS_MAX_ARG_STR_LENGTH); strlcpy(child_proc[j].args[i++], arg_basic, LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_PREMIUM) { - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); } else { - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, LOC_PROCESS_MAX_ARG_STR_LENGTH); strlcpy(child_proc[j].args[i++], arg_disabled, @@ -1034,28 +1003,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } } if(conf.loc_feature_mask & - (LOC_FEATURE_MASK_GTP_WAA_BASIC | LOC_FEATURE_MASK_GTP_WAA_PREMIUM)) { - if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_basic, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_PREMIUM) { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else - { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - } - if(conf.loc_feature_mask & (LOC_FEATURE_MASK_SAP_BASIC | LOC_FEATURE_MASK_SAP_PREMIUM)) { if(loc_service_mask & LOC_FEATURE_MASK_SAP_BASIC) { strlcpy(child_proc[j].args[i++], arg_sap, @@ -1077,6 +1024,22 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p LOC_PROCESS_MAX_ARG_STR_LENGTH); } } + + if(conf.loc_feature_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) { + if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) { + strlcpy(child_proc[j].args[i++], arg_gtp_waa, + LOC_PROCESS_MAX_ARG_STR_LENGTH); + strlcpy(child_proc[j].args[i++], arg_basic, + LOC_PROCESS_MAX_ARG_STR_LENGTH); + } + else + { + strlcpy(child_proc[j].args[i++], arg_gtp_waa, + LOC_PROCESS_MAX_ARG_STR_LENGTH); + strlcpy(child_proc[j].args[i++], arg_disabled, + LOC_PROCESS_MAX_ARG_STR_LENGTH); + } + } IF_LOC_LOGD { LOC_LOGD("%s:%d]: %s args\n", __func__, __LINE__, child_proc[j].name[0]); for(unsigned int k=0; k<LOC_PROCESS_MAX_NUM_ARGS; k++) { diff --git a/gps/utils/loc_cfg.h b/gps/utils/loc_cfg.h index 652d86e..5c77dc6 100644 --- a/gps/utils/loc_cfg.h +++ b/gps/utils/loc_cfg.h @@ -37,7 +37,7 @@ #include <grp.h> #define LOC_MAX_PARAM_NAME 80 -#define LOC_MAX_PARAM_STRING 80 +#define LOC_MAX_PARAM_STRING 172 #define LOC_MAX_PARAM_LINE (LOC_MAX_PARAM_NAME + LOC_MAX_PARAM_STRING) #define LOC_FEATURE_MODE_DISABLED "DISABLED" @@ -72,19 +72,20 @@ *============================================================================*/ typedef struct { - const char *param_name; - void *param_ptr; - uint8_t *param_set; /* indicate value set by config file */ - char param_type; /* 'n' for number, - 's' for string, - 'f' for double */ + const char *param_name; + void *param_ptr; /* for string type, buf size need to be LOC_MAX_PARAM_STRING */ + uint8_t *param_set; /* indicate value set by config file */ + char param_type; /* 'n' for number, + 's' for string, NOTE: buf size need to be LOC_MAX_PARAM_STRING + 'f' for double */ } loc_param_s_type; typedef enum { ENABLED, RUNNING, DISABLED, - DISABLED_FROM_CONF + DISABLED_FROM_CONF, + DISABLED_VIA_VENDOR_ENHANCED_CHECK } loc_process_e_status; typedef struct { @@ -112,6 +113,8 @@ extern "C" { * MODULE EXPORTED FUNCTIONS * *============================================================================*/ +bool isVendorEnhanced(); +void setVendorEnhanced(bool vendorEnhanced); void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table, uint32_t table_length); @@ -132,9 +135,7 @@ extern const char LOC_PATH_QUIPC_CONF[]; int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr, loc_process_info_s_type** process_info_table_ptr); - -uint32_t loc_modem_emulator_enabled(); - +int loc_get_datum_type(); #ifdef __cplusplus } #endif diff --git a/gps/utils/loc_gps.h b/gps/utils/loc_gps.h index 5e915a3..eae7383 100644 --- a/gps/utils/loc_gps.h +++ b/gps/utils/loc_gps.h @@ -100,6 +100,19 @@ typedef uint16_t LocGpsLocationFlags; #define LOC_GPS_LOCATION_HAS_ACCURACY 0x0010 /** LocGpsLocation has valid vertical uncertainity */ #define LOC_GPS_LOCATION_HAS_VERT_UNCERTAINITY 0x0040 +/** LocGpsLocation has valid spoof mask */ +#define LOC_GPS_LOCATION_HAS_SPOOF_MASK 0x0080 +/** LocGpsLocation has valid speed accuracy */ +#define LOC_GPS_LOCATION_HAS_SPEED_ACCURACY 0x0100 +/** LocGpsLocation has valid bearing accuracy */ +#define LOC_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0200 + +/** Spoof mask in LocGpsLocation */ +typedef uint32_t LocGpsSpoofMask; +#define LOC_GPS_LOCATION_NONE_SPOOFED 0x0000 +#define LOC_GPS_LOCATION_POSITION_SPOOFED 0x0001 +#define LOC_GPS_LOCATION_TIME_SPOOFED 0x0002 +#define LOC_GPS_LOCATION_NAVIGATION_DATA_SPOOFED 0x0004 /** Flags for the loc_gps_set_capabilities callback. */ @@ -142,13 +155,18 @@ typedef uint16_t LocGpsAidingData; #define LOC_GPS_DELETE_SVSTEER 0x0100 #define LOC_GPS_DELETE_SADATA 0x0200 #define LOC_GPS_DELETE_RTI 0x0400 +#define LOC_GPS_DELETE_MB_DATA 0x0800 #define LOC_GPS_DELETE_CELLDB_INFO 0x8000 #define LOC_GPS_DELETE_ALL 0xFFFF /** AGPS type */ typedef uint16_t LocAGpsType; +#define LOC_AGPS_TYPE_ANY 0 #define LOC_AGPS_TYPE_SUPL 1 #define LOC_AGPS_TYPE_C2K 2 +#define LOC_AGPS_TYPE_WWAN_ANY 3 +#define LOC_AGPS_TYPE_WIFI 4 +#define LOC_AGPS_TYPE_SUPL_ES 5 typedef uint16_t LocAGpsSetIDType; #define LOC_AGPS_SETID_TYPE_NONE 0 @@ -530,9 +548,11 @@ typedef uint8_t LocGnssConstellationType; /** Represents a location. */ typedef struct { /** set to sizeof(LocGpsLocation) */ - size_t size; + uint32_t size; /** Contains LocGpsLocationFlags bits. */ uint16_t flags; + /** The spoof mask */ + LocGpsSpoofMask spoof_mask; /** Represents latitude in degrees. */ double latitude; /** Represents longitude in degrees. */ diff --git a/gps/utils/loc_misc_utils.cpp b/gps/utils/loc_misc_utils.cpp index b7c8406..70fdbc3 100644 --- a/gps/utils/loc_misc_utils.cpp +++ b/gps/utils/loc_misc_utils.cpp @@ -30,6 +30,7 @@ #define LOG_TAG "LocSvc_misc_utils" #include <stdio.h> #include <string.h> +#include <dlfcn.h> #include <log_util.h> #include <loc_misc_utils.h> #include <ctype.h> @@ -112,3 +113,33 @@ void loc_util_trim_space(char *org_string) err: return; } + +inline void logDlError(const char* failedCall) { + const char * err = dlerror(); + LOC_LOGe("%s error: %s", failedCall, (nullptr == err) ? "unknown" : err); +} + +void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName) +{ + void* sym = nullptr; + if ((nullptr != libHandle || nullptr != libName) && nullptr != symName) { + if (nullptr == libHandle) { + libHandle = dlopen(libName, RTLD_NOW); + if (nullptr == libHandle) { + logDlError("dlopen"); + } + } + // NOT else, as libHandle gets assigned 5 line above + if (nullptr != libHandle) { + sym = dlsym(libHandle, symName); + if (nullptr == sym) { + logDlError("dlsym"); + } + } + } else { + LOC_LOGe("Either libHandle (%p) or libName (%p) must not be null; " + "symName (%p) can not be null.", libHandle, libName, symName); + } + + return sym; +} diff --git a/gps/utils/loc_misc_utils.h b/gps/utils/loc_misc_utils.h index 7d66d84..fad1b6d 100644 --- a/gps/utils/loc_misc_utils.h +++ b/gps/utils/loc_misc_utils.h @@ -92,6 +92,34 @@ SIDE EFFECTS N/A ===========================================================================*/ void loc_util_trim_space(char *org_string); + +/*=========================================================================== +FUNCTION dlGetSymFromLib + +DESCRIPTION + Handy function to get a pointer to a symbol from a library. + + If libHandle is not null, it will be used as the handle to the library. In + that case libName wll not be used; + libHandle is an in / out parameter. + If libHandle is null, libName will be used to dlopen. + Either libHandle or libName must not be nullptr. + symName must not be null. + +DEPENDENCIES + N/A + +RETURN VALUE + pointer to symName. Could be nullptr if + Parameters are incorrect; or + libName can not be opened; or + symName can not be found. + +SIDE EFFECTS + N/A +===========================================================================*/ +void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName); + #ifdef __cplusplus } #endif diff --git a/gps/utils/loc_nmea.cpp b/gps/utils/loc_nmea.cpp index 558dc65..24197ff 100644 --- a/gps/utils/loc_nmea.cpp +++ b/gps/utils/loc_nmea.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,24 +33,87 @@ #include <math.h> #include <log_util.h> #include <loc_pla.h> +#include <loc_cfg.h> #define GLONASS_SV_ID_OFFSET 64 +#define QZSS_SV_ID_OFFSET (-192) +#define MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION 64 #define MAX_SATELLITES_IN_USE 12 +#define MSEC_IN_ONE_WEEK 604800000ULL +#define UTC_GPS_OFFSET_MSECS 315964800000ULL // GNSS system id according to NMEA spec #define SYSTEM_ID_GPS 1 #define SYSTEM_ID_GLONASS 2 #define SYSTEM_ID_GALILEO 3 -// Extended systems -#define SYSTEM_ID_BEIDOU 4 +#define SYSTEM_ID_BDS 4 #define SYSTEM_ID_QZSS 5 +#define SYSTEM_ID_NAVIC 6 + +//GNSS signal id according to NMEA spec +#define SIGNAL_ID_ALL_SIGNALS 0 +#define SIGNAL_ID_GPS_L1CA 1 +#define SIGNAL_ID_GPS_L1P 2 +#define SIGNAL_ID_GPS_L1M 3 +#define SIGNAL_ID_GPS_L2P 4 +#define SIGNAL_ID_GPS_L2CM 5 +#define SIGNAL_ID_GPS_L2CL 6 +#define SIGNAL_ID_GPS_L5I 7 +#define SIGNAL_ID_GPS_L5Q 8 + + +#define SIGNAL_ID_GLO_G1CA 1 +#define SIGNAL_ID_GLO_G1P 2 +#define SIGNAL_ID_GLO_G2CA 3 +#define SIGNAL_ID_GLO_G2P 4 + + +#define SIGNAL_ID_GAL_E5A 1 +#define SIGNAL_ID_GAL_E5B 2 +#define SIGNAL_ID_GAL_E5AB 3 +#define SIGNAL_ID_GAL_E6A 4 +#define SIGNAL_ID_GAL_E6BC 5 +#define SIGNAL_ID_GAL_L1A 6 +#define SIGNAL_ID_GAL_L1BC 7 + +#define SIGNAL_ID_BDS_B1I 1 +#define SIGNAL_ID_BDS_B1Q 2 +#define SIGNAL_ID_BDS_B1C 3 +#define SIGNAL_ID_BDS_B1A 4 +#define SIGNAL_ID_BDS_B2A 5 +#define SIGNAL_ID_BDS_B2B 6 +#define SIGNAL_ID_BDS_B2AB 7 +#define SIGNAL_ID_BDS_B3I 8 +#define SIGNAL_ID_BDS_B3Q 9 +#define SIGNAL_ID_BDS_B3A 0xA +#define SIGNAL_ID_BDS_B2I 0xB +#define SIGNAL_ID_BDS_B2Q 0xC + +#define SIGNAL_ID_QZSS_L1CA 1 +#define SIGNAL_ID_QZSS_L1CD 2 +#define SIGNAL_ID_QZSS_L1CP 3 +#define SIGNAL_ID_QZSS_LIS 4 +#define SIGNAL_ID_QZSS_L2CM 5 +#define SIGNAL_ID_QZSS_L2CL 6 +#define SIGNAL_ID_QZSS_L5I 7 +#define SIGNAL_ID_QZSS_L5Q 8 +#define SIGNAL_ID_QZSS_L6D 9 +#define SIGNAL_ID_QZSS_L6E 0xA + +#define SIGNAL_ID_NAVIC_L5SPS 1 +#define SIGNAL_ID_NAVIC_SSPS 2 +#define SIGNAL_ID_NAVIC_L5RS 3 +#define SIGNAL_ID_NAVIC_SRS 4 +#define SIGNAL_ID_NAVIC_L1SPS 5 + typedef struct loc_nmea_sv_meta_s { char talker[3]; LocGnssConstellationType svType; - uint32_t mask; + uint64_t mask; uint32_t svCount; + uint32_t totalSvUsedCount; uint32_t svIdOffset; uint32_t signalId; uint32_t systemId; @@ -58,22 +121,260 @@ typedef struct loc_nmea_sv_meta_s typedef struct loc_sv_cache_info_s { - uint32_t gps_used_mask; - uint32_t glo_used_mask; - uint32_t gal_used_mask; - uint32_t qzss_used_mask; - uint32_t bds_used_mask; - uint32_t gps_count; - uint32_t glo_count; - uint32_t gal_count; - uint32_t qzss_count; - uint32_t bds_count; + uint64_t gps_used_mask; + uint64_t glo_used_mask; + uint64_t gal_used_mask; + uint64_t qzss_used_mask; + uint64_t bds_used_mask; + uint64_t navic_used_mask; + uint32_t gps_l1_count; + uint32_t gps_l5_count; + uint32_t glo_g1_count; + uint32_t glo_g2_count; + uint32_t gal_e1_count; + uint32_t gal_e5_count; + uint32_t qzss_l1_count; + uint32_t qzss_l5_count; + uint32_t bds_b1_count; + uint32_t bds_b2_count; + uint32_t navic_l5_count; float hdop; float pdop; float vdop; } loc_sv_cache_info; /*=========================================================================== +FUNCTION convert_Lla_to_Ecef + +DESCRIPTION + Convert LLA to ECEF + +DEPENDENCIES + NONE + +RETURN VALUE + NONE + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void convert_Lla_to_Ecef(const LocLla& plla, LocEcef& pecef) +{ + double r; + + r = MAJA / sqrt(1.0 - ESQR * sin(plla.lat) * sin(plla.lat)); + pecef.X = (r + plla.alt) * cos(plla.lat) * cos(plla.lon); + pecef.Y = (r + plla.alt) * cos(plla.lat) * sin(plla.lon); + pecef.Z = (r * OMES + plla.alt) * sin(plla.lat); +} + +/*=========================================================================== +FUNCTION convert_WGS84_to_PZ90 + +DESCRIPTION + Convert datum from WGS84 to PZ90 + +DEPENDENCIES + NONE + +RETURN VALUE + NONE + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void convert_WGS84_to_PZ90(const LocEcef& pWGS84, LocEcef& pPZ90) +{ + double deltaX = DatumConstFromWGS84[0]; + double deltaY = DatumConstFromWGS84[1]; + double deltaZ = DatumConstFromWGS84[2]; + double deltaScale = DatumConstFromWGS84[3]; + double rotX = DatumConstFromWGS84[4]; + double rotY = DatumConstFromWGS84[5]; + double rotZ = DatumConstFromWGS84[6]; + + pPZ90.X = deltaX + deltaScale * (pWGS84.X + rotZ * pWGS84.Y - rotY * pWGS84.Z); + pPZ90.Y = deltaY + deltaScale * (pWGS84.Y - rotZ * pWGS84.X + rotX * pWGS84.Z); + pPZ90.Z = deltaZ + deltaScale * (pWGS84.Z + rotY * pWGS84.X - rotX * pWGS84.Y); +} + +/*=========================================================================== +FUNCTION convert_Ecef_to_Lla + +DESCRIPTION + Convert ECEF to LLA + +DEPENDENCIES + NONE + +RETURN VALUE + NONE + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void convert_Ecef_to_Lla(const LocEcef& pecef, LocLla& plla) +{ + double p, r; + double EcefA = C_PZ90A; + double EcefB = C_PZ90B; + double Ecef1Mf; + double EcefE2; + double Mu; + double Smu; + double Cmu; + double Phi; + double Sphi; + double N; + + p = sqrt(pecef.X * pecef.X + pecef.Y * pecef.Y); + r = sqrt(p * p + pecef.Z * pecef.Z); + if (r < 1.0) { + plla.lat = 1.0; + plla.lon = 1.0; + plla.alt = 1.0; + } + Ecef1Mf = 1.0 - (EcefA - EcefB) / EcefA; + EcefE2 = 1.0 - (EcefB * EcefB) / (EcefA * EcefA); + if (p > 1.0) { + Mu = atan2(pecef.Z * (Ecef1Mf + EcefE2 * EcefA / r), p); + } else { + if (pecef.Z > 0.0) { + Mu = M_PI / 2.0; + } else { + Mu = -M_PI / 2.0; + } + } + Smu = sin(Mu); + Cmu = cos(Mu); + Phi = atan2(pecef.Z * Ecef1Mf + EcefE2 * EcefA * Smu * Smu * Smu, + Ecef1Mf * (p - EcefE2 * EcefA * Cmu * Cmu * Cmu)); + Sphi = sin(Phi); + N = EcefA / sqrt(1.0 - EcefE2 * Sphi * Sphi); + plla.alt = p * cos(Phi) + pecef.Z * Sphi - EcefA * EcefA/N; + plla.lat = Phi; + if ( p > 1.0) { + plla.lon = atan2(pecef.Y, pecef.X); + } else { + plla.lon = 0.0; + } +} + +/*=========================================================================== +FUNCTION convert_signalType_to_signalId + +DESCRIPTION + convert signalType to signal ID + +DEPENDENCIES + NONE + +RETURN VALUE + value of signal ID + +SIDE EFFECTS + N/A + +===========================================================================*/ +static uint32_t convert_signalType_to_signalId(GnssSignalTypeMask signalType) +{ + uint32_t signalId = SIGNAL_ID_ALL_SIGNALS; + + switch (signalType) { + case GNSS_SIGNAL_GPS_L1CA: + signalId = SIGNAL_ID_GPS_L1CA; + break; + case GNSS_SIGNAL_GPS_L2: + signalId = SIGNAL_ID_GPS_L2CL; + break; + case GNSS_SIGNAL_GPS_L5: + signalId = SIGNAL_ID_GPS_L5Q; + break; + case GNSS_SIGNAL_GLONASS_G1: + signalId = SIGNAL_ID_GLO_G1CA; + break; + case GNSS_SIGNAL_GLONASS_G2: + signalId = SIGNAL_ID_GLO_G2CA; + break; + case GNSS_SIGNAL_GALILEO_E1: + signalId = SIGNAL_ID_GAL_L1BC; + break; + case GNSS_SIGNAL_GALILEO_E5A: + signalId = SIGNAL_ID_GAL_E5A; + break; + case GNSS_SIGNAL_GALILEO_E5B: + signalId = SIGNAL_ID_GAL_E5B; + break; + case GNSS_SIGNAL_QZSS_L1CA: + signalId = SIGNAL_ID_QZSS_L1CA; + break; + case GNSS_SIGNAL_QZSS_L2: + signalId = SIGNAL_ID_QZSS_L2CL; + break; + case GNSS_SIGNAL_QZSS_L5: + signalId = SIGNAL_ID_QZSS_L5Q; + break; + case GNSS_SIGNAL_BEIDOU_B1I: + signalId = SIGNAL_ID_BDS_B1I; + break; + case GNSS_SIGNAL_BEIDOU_B1C: + signalId = SIGNAL_ID_BDS_B1C; + break; + case GNSS_SIGNAL_BEIDOU_B2I: + signalId = SIGNAL_ID_BDS_B2I; + break; + case GNSS_SIGNAL_BEIDOU_B2AI: + case GNSS_SIGNAL_BEIDOU_B2AQ: + signalId = SIGNAL_ID_BDS_B2A; + break; + case GNSS_SIGNAL_NAVIC_L5: + signalId = SIGNAL_ID_NAVIC_L5SPS; + break; + default: + signalId = SIGNAL_ID_ALL_SIGNALS; + } + + return signalId; + +} + +/*=========================================================================== +FUNCTION get_sv_count_from_mask + +DESCRIPTION + get the sv count from bit mask + +DEPENDENCIES + NONE + +RETURN VALUE + value of sv count + +SIDE EFFECTS + N/A + +===========================================================================*/ +static uint32_t get_sv_count_from_mask(uint64_t svMask, int totalSvCount) +{ + int index = 0; + uint32_t svCount = 0; + + if(totalSvCount > MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION) { + LOC_LOGE("total SV count in this constellation %d exceeded limit %d", + totalSvCount, MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION); + } + for(index = 0; index < totalSvCount; index++) { + if(svMask & 0x1) + svCount += 1; + svMask >>= 1; + } + return svCount; +} + +/*=========================================================================== FUNCTION loc_nmea_sv_meta_init DESCRIPTION @@ -92,6 +393,7 @@ SIDE EFFECTS static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, loc_sv_cache_info& sv_cache_info, GnssSvType svType, + GnssSignalTypeMask signalType, bool needCombine) { memset(&sv_meta, 0, sizeof(sv_meta)); @@ -103,56 +405,97 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'P'; sv_meta.mask = sv_cache_info.gps_used_mask; - sv_meta.svCount = sv_cache_info.gps_count; - sv_meta.signalId = 1; sv_meta.systemId = SYSTEM_ID_GPS; + if (GNSS_SIGNAL_GPS_L1CA == signalType) { + sv_meta.svCount = sv_cache_info.gps_l1_count; + } else if (GNSS_SIGNAL_GPS_L5 == signalType) { + sv_meta.svCount = sv_cache_info.gps_l5_count; + } break; case GNSS_SV_TYPE_GLONASS: sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'L'; sv_meta.mask = sv_cache_info.glo_used_mask; - sv_meta.svCount = sv_cache_info.glo_count; // GLONASS SV ids are from 65-96 sv_meta.svIdOffset = GLONASS_SV_ID_OFFSET; - sv_meta.signalId = 1; sv_meta.systemId = SYSTEM_ID_GLONASS; + if (GNSS_SIGNAL_GLONASS_G1 == signalType) { + sv_meta.svCount = sv_cache_info.glo_g1_count; + } else if (GNSS_SIGNAL_GLONASS_G2 == signalType) { + sv_meta.svCount = sv_cache_info.glo_g2_count; + } break; case GNSS_SV_TYPE_GALILEO: sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'A'; sv_meta.mask = sv_cache_info.gal_used_mask; - sv_meta.svCount = sv_cache_info.gal_count; - sv_meta.signalId = 7; sv_meta.systemId = SYSTEM_ID_GALILEO; + if (GNSS_SIGNAL_GALILEO_E1 == signalType) { + sv_meta.svCount = sv_cache_info.gal_e1_count; + } else if (GNSS_SIGNAL_GALILEO_E5A == signalType) { + sv_meta.svCount = sv_cache_info.gal_e5_count; + } break; case GNSS_SV_TYPE_QZSS: - sv_meta.talker[0] = 'P'; + sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'Q'; sv_meta.mask = sv_cache_info.qzss_used_mask; - sv_meta.svCount = sv_cache_info.qzss_count; - // QZSS SV ids are from 193-197. So keep svIdOffset 0 - sv_meta.signalId = 0; + // QZSS SV ids are from 193-199. So keep svIdOffset -192 + sv_meta.svIdOffset = QZSS_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_QZSS; + if (GNSS_SIGNAL_QZSS_L1CA == signalType) { + sv_meta.svCount = sv_cache_info.qzss_l1_count; + } else if (GNSS_SIGNAL_QZSS_L5 == signalType) { + sv_meta.svCount = sv_cache_info.qzss_l5_count; + } break; case GNSS_SV_TYPE_BEIDOU: - sv_meta.talker[0] = 'P'; - sv_meta.talker[1] = 'Q'; + sv_meta.talker[0] = 'G'; + sv_meta.talker[1] = 'B'; sv_meta.mask = sv_cache_info.bds_used_mask; - sv_meta.svCount = sv_cache_info.bds_count; // BDS SV ids are from 201-235. So keep svIdOffset 0 - sv_meta.signalId = 0; - sv_meta.systemId = SYSTEM_ID_BEIDOU; + sv_meta.systemId = SYSTEM_ID_BDS; + if (GNSS_SIGNAL_BEIDOU_B1I == signalType) { + sv_meta.svCount = sv_cache_info.bds_b1_count; + } else if (GNSS_SIGNAL_BEIDOU_B2AI == signalType) { + sv_meta.svCount = sv_cache_info.bds_b2_count; + } + break; + case GNSS_SV_TYPE_NAVIC: + sv_meta.talker[0] = 'G'; + sv_meta.talker[1] = 'I'; + sv_meta.mask = sv_cache_info.navic_used_mask; + // NAVIC SV ids are from 401-414. So keep svIdOffset 0 + sv_meta.systemId = SYSTEM_ID_NAVIC; + if (GNSS_SIGNAL_NAVIC_L5 == signalType) { + sv_meta.svCount = sv_cache_info.navic_l5_count; + } break; default: LOC_LOGE("NMEA Error unknow constellation type: %d", svType); return NULL; } + sv_meta.signalId = convert_signalType_to_signalId(signalType); + sv_meta.totalSvUsedCount = + get_sv_count_from_mask(sv_cache_info.gps_used_mask, + GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1) + + get_sv_count_from_mask(sv_cache_info.glo_used_mask, + GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1) + + get_sv_count_from_mask(sv_cache_info.gal_used_mask, + GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1) + + get_sv_count_from_mask(sv_cache_info.qzss_used_mask, + QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1) + + get_sv_count_from_mask(sv_cache_info.bds_used_mask, + BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1) + + get_sv_count_from_mask(sv_cache_info.navic_used_mask, + NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1); if (needCombine && (sv_cache_info.gps_used_mask ? 1 : 0) + (sv_cache_info.glo_used_mask ? 1 : 0) + (sv_cache_info.gal_used_mask ? 1 : 0) + (sv_cache_info.qzss_used_mask ? 1 : 0) + - (sv_cache_info.bds_used_mask ? 1 : 0) > 1) + (sv_cache_info.bds_used_mask ? 1 : 0) + + (sv_cache_info.navic_used_mask ? 1 : 0) > 1) { // If GPS, GLONASS, Galileo, QZSS, BDS etc. are combined // to obtain the reported position solution, @@ -240,27 +583,31 @@ static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtende int length = 0; uint32_t svUsedCount = 0; - uint32_t svUsedList[32] = {0}; + uint32_t svUsedList[64] = {0}; char fixType = '\0'; const char* talker = sv_meta_p->talker; uint32_t svIdOffset = sv_meta_p->svIdOffset; - uint32_t mask = sv_meta_p->mask; + uint64_t mask = sv_meta_p->mask; + + if(sv_meta_p->svType != GNSS_SV_TYPE_GLONASS) { + svIdOffset = 0; + } - for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) + for (uint8_t i = 1; mask > 0 && svUsedCount < 64; i++) { if (mask & 1) svUsedList[svUsedCount++] = i + svIdOffset; mask = mask >> 1; } - if (svUsedCount == 0 && GNSS_SV_TYPE_GPS != sv_meta_p->svType) + if (svUsedCount == 0) return 0; - if (svUsedCount == 0) + if (sv_meta_p->totalSvUsedCount == 0) fixType = '1'; // no fix - else if (svUsedCount <= 3) + else if (sv_meta_p->totalSvUsedCount <= 3) fixType = '2'; // 2D fix else fixType = '3'; // 3D fix @@ -371,13 +718,9 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, const char* talker = sv_meta_p->talker; uint32_t svIdOffset = sv_meta_p->svIdOffset; int svCount = sv_meta_p->svCount; - if (svCount <= 0) { - // no svs in view, so just send a blank $--GSV sentence - snprintf(sentence, lengthRemaining, "$%sGSV,1,1,0,%d", talker, sv_meta_p->signalId); - length = loc_nmea_put_checksum(sentence, bufSize); - nmeaArraystr.push_back(sentence); + LOC_LOGV("No SV in view for talker ID:%s, signal ID:%X", talker, sv_meta_p->signalId); return; } @@ -403,10 +746,49 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, for (int i=0; (svNumber <= svNotify.count) && (i < 4); svNumber++) { - if (sv_meta_p->svType == svNotify.gnssSvs[svNumber - 1].type) + GnssSignalTypeMask signalType = svNotify.gnssSvs[svNumber-1].gnssSignalTypeMask; + if (0 == signalType) { + // If no signal type in report, it means default L1,G1,E1,B1I + switch (svNotify.gnssSvs[svNumber - 1].type) + { + case GNSS_SV_TYPE_GPS: + signalType = GNSS_SIGNAL_GPS_L1CA; + break; + case GNSS_SV_TYPE_GLONASS: + signalType = GNSS_SIGNAL_GLONASS_G1; + break; + case GNSS_SV_TYPE_GALILEO: + signalType = GNSS_SIGNAL_GALILEO_E1; + break; + case GNSS_SV_TYPE_QZSS: + signalType = GNSS_SIGNAL_QZSS_L1CA; + break; + case GNSS_SV_TYPE_BEIDOU: + signalType = GNSS_SIGNAL_BEIDOU_B1I; + break; + case GNSS_SV_TYPE_SBAS: + signalType = GNSS_SIGNAL_SBAS_L1; + break; + case GNSS_SV_TYPE_NAVIC: + signalType = GNSS_SIGNAL_NAVIC_L5; + break; + default: + LOC_LOGE("NMEA Error unknow constellation type: %d", + svNotify.gnssSvs[svNumber - 1].type); + continue; + } + } + + if (sv_meta_p->svType == svNotify.gnssSvs[svNumber - 1].type && + sv_meta_p->signalId == convert_signalType_to_signalId(signalType)) { + uint16_t svId = svNotify.gnssSvs[svNumber - 1].svId; + // For QZSS we adjusted SV id's in GnssAdapter, we need to re-adjust here + if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svNumber - 1].type) { + svId = svId - (QZSS_SV_PRN_MIN - 1); + } length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,", - svNotify.gnssSvs[svNumber - 1].svId + svIdOffset, + svId + svIdOffset, (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int @@ -438,7 +820,7 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, } // append signalId - length = snprintf(pMarker, lengthRemaining,",%d",sv_meta_p->signalId); + length = snprintf(pMarker, lengthRemaining,",%X",sv_meta_p->signalId); pMarker += length; lengthRemaining -= length; @@ -450,6 +832,330 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, } /*=========================================================================== +FUNCTION loc_nmea_generate_DTM + +DESCRIPTION + Generate NMEA DTM sentences generated based on position report + +DEPENDENCIES + NONE + +RETURN VALUE + NONE + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_nmea_generate_DTM(const LocLla &ref_lla, + const LocLla &local_lla, + char *talker, + char *sentence, + int bufSize) +{ + char* pMarker = sentence; + int lengthRemaining = bufSize; + int length = 0; + int datum_type; + char ref_datum[4] = {0}; + char local_datum[4] = {0}; + double lla_offset[3] = {0}; + char latHem, longHem; + double latMins, longMins; + + + + datum_type = loc_get_datum_type(); + switch (datum_type) { + case LOC_GNSS_DATUM_WGS84: + ref_datum[0] = 'W'; + ref_datum[1] = '8'; + ref_datum[2] = '4'; + local_datum[0] = 'P'; + local_datum[1] = '9'; + local_datum[2] = '0'; + break; + case LOC_GNSS_DATUM_PZ90: + ref_datum[0] = 'P'; + ref_datum[1] = '9'; + ref_datum[2] = '0'; + local_datum[0] = 'W'; + local_datum[1] = '8'; + local_datum[2] = '4'; + break; + default: + break; + } + length = snprintf(pMarker , lengthRemaining , "$%sDTM,%s,," , talker, local_datum); + if (length < 0 || length >= lengthRemaining) { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + lla_offset[0] = local_lla.lat - ref_lla.lat; + lla_offset[1] = fmod(local_lla.lon - ref_lla.lon, 360.0); + if (lla_offset[1] < -180.0) { + lla_offset[1] += 360.0; + } else if ( lla_offset[1] > 180.0) { + lla_offset[1] -= 360.0; + } + lla_offset[2] = local_lla.alt - ref_lla.alt; + if (lla_offset[0] > 0.0) { + latHem = 'N'; + } else { + latHem = 'S'; + lla_offset[0] *= -1.0; + } + latMins = fmod(lla_offset[0] * 60.0, 60.0); + if (lla_offset[1] < 0.0) { + longHem = 'W'; + lla_offset[1] *= -1.0; + }else { + longHem = 'E'; + } + longMins = fmod(lla_offset[1] * 60.0, 60.0); + length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,%.3lf,", + (uint8_t)floor(lla_offset[0]), latMins, latHem, + (uint8_t)floor(lla_offset[1]), longMins, longHem, lla_offset[2]); + if (length < 0 || length >= lengthRemaining) { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + length = snprintf(pMarker , lengthRemaining , "%s" , ref_datum); + if (length < 0 || length >= lengthRemaining) { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + length = loc_nmea_put_checksum(sentence, bufSize); +} + +/*=========================================================================== +FUNCTION get_utctime_with_leapsecond_transition + +DESCRIPTION + This function returns true if the position report is generated during + leap second transition period. If not, then the utc timestamp returned + will be set to the timestamp in the position report. If it is, + then the utc timestamp returned will need to take into account + of the leap second transition so that proper calendar year/month/date + can be calculated from the returned utc timestamp. + +DEPENDENCIES + NONE + +RETURN VALUE + true: position report is generated in leap second transition period. + +SIDE EFFECTS + N/A + +===========================================================================*/ +static bool get_utctime_with_leapsecond_transition( + const UlpLocation &location, + const GpsLocationExtended &locationExtended, + const LocationSystemInfo &systemInfo, + LocGpsUtcTime &utcPosTimestamp) +{ + bool inTransition = false; + + // position report is not generated during leap second transition, + // we can use the UTC timestamp from position report as is + utcPosTimestamp = location.gpsLocation.timestamp; + + // Check whether we are in leap second transition. + // If so, per NMEA spec, we need to display the extra second in format of 23:59:60 + // with year/month/date not getting advanced. + if ((locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GPS_TIME) && + ((systemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) && + (systemInfo.leapSecondSysInfo.leapSecondInfoMask & + LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT))) { + + const LeapSecondChangeInfo &leapSecondChangeInfo = + systemInfo.leapSecondSysInfo.leapSecondChangeInfo; + const GnssSystemTimeStructType &gpsTimestampLsChange = + leapSecondChangeInfo.gpsTimestampLsChange; + + uint64_t gpsTimeLsChange = gpsTimestampLsChange.systemWeek * MSEC_IN_ONE_WEEK + + gpsTimestampLsChange.systemMsec; + uint64_t gpsTimePosReport = locationExtended.gpsTime.gpsWeek * MSEC_IN_ONE_WEEK + + locationExtended.gpsTime.gpsTimeOfWeekMs; + // we are only dealing with positive leap second change, as negative + // leap second change has never occurred and should not occur in future + if (leapSecondChangeInfo.leapSecondsAfterChange > + leapSecondChangeInfo.leapSecondsBeforeChange) { + // leap second adjustment is always 1 second at a time. It can happen + // every quarter end and up to four times per year. + if ((gpsTimePosReport >= gpsTimeLsChange) && + (gpsTimePosReport < (gpsTimeLsChange + 1000))) { + inTransition = true; + utcPosTimestamp = gpsTimeLsChange + UTC_GPS_OFFSET_MSECS - + leapSecondChangeInfo.leapSecondsBeforeChange * 1000; + + // we substract 1000 milli-seconds from UTC timestmap in order to calculate the + // proper year, month and date during leap second transtion. + // Let us give an example, assuming leap second transition is scheduled on 2019, + // Dec 31st mid night. When leap second transition is happening, + // instead of outputting the time as 2020, Jan, 1st, 00 hour, 00 min, and 00 sec. + // The time need to be displayed as 2019, Dec, 31st, 23 hour, 59 min and 60 sec. + utcPosTimestamp -= 1000; + } + } + } + return inTransition; +} + +/*=========================================================================== +FUNCTION loc_nmea_get_fix_quality + +DESCRIPTION + This function obtains the fix quality for GGA sentence, mode indicator + for RMC and VTG sentence based on nav solution mask and tech mask in + the postion report. + +DEPENDENCIES + NONE + +Output parameter + ggaGpsQuality: gps quality field in GGA sentence + rmcModeIndicator: mode indicator field in RMC sentence + vtgModeIndicator: mode indicator field in VTG sentence + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_nmea_get_fix_quality(const UlpLocation & location, + const GpsLocationExtended & locationExtended, + bool custom_gga_fix_quality, + char ggaGpsQuality[3], + char & rmcModeIndicator, + char & vtgModeIndicator) { + + ggaGpsQuality[0] = '0'; // 0 means no fix + rmcModeIndicator = 'N'; // N means no fix + vtgModeIndicator = 'N'; // N means no fix + + do { + // GGA fix quality is defined in NMEA spec as below: + // https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_GGA.html + // Fix quality: 0 = invalid + // 1 = GPS fix (SPS) + // 2 = DGPS fix + // 3 = PPS fix + // 4 = Real Time Kinematic + // 5 = Float RTK + // 6 = estimated (dead reckoning) (2.3 feature) + // 7 = Manual input mode + // 8 = Simulation mode + if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)){ + break; + } + // NOTE: Order of the check is important + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK) { + if (LOC_NAV_MASK_PPP_CORRECTION & locationExtended.navSolutionMask) { + ggaGpsQuality[0] = '2'; // 2 means DGPS fix + rmcModeIndicator = 'P'; // P means precise + vtgModeIndicator = 'P'; // P means precise + break; + } else if (LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask){ + ggaGpsQuality[0] = '4'; // 4 means RTK Fixed fix + rmcModeIndicator = 'R'; // use R (RTK fixed) + vtgModeIndicator = 'D'; // use D (differential) as + // no RTK fixed defined for VTG in NMEA 183 spec + break; + } else if (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask){ + ggaGpsQuality[0] = '5'; // 5 means RTK float fix + rmcModeIndicator = 'F'; // F means RTK float fix + vtgModeIndicator = 'D'; // use D (differential) as + // no RTK float defined for VTG in NMEA 183 spec + break; + } else if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask){ + ggaGpsQuality[0] = '2'; // 2 means DGPS fix + rmcModeIndicator = 'D'; // D means differential + vtgModeIndicator = 'D'; // D means differential + break; + } else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask){ + ggaGpsQuality[0] = '2'; // 2 means DGPS fix + rmcModeIndicator = 'D'; // D means differential + vtgModeIndicator = 'D'; // D means differential + break; + } + } + // NOTE: Order of the check is important + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) { + if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask){ + ggaGpsQuality[0] = '1'; // 1 means GPS + rmcModeIndicator = 'A'; // A means autonomous + vtgModeIndicator = 'A'; // A means autonomous + break; + } else if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){ + ggaGpsQuality[0] = '6'; // 6 means estimated (dead reckoning) + rmcModeIndicator = 'E'; // E means estimated (dead reckoning) + vtgModeIndicator = 'E'; // E means estimated (dead reckoning) + break; + } + } + } while (0); + + do { + // check for customized nmea enabled or not + // with customized GGA quality enabled + // PPP fix w/o sensor: 59, PPP fix w/ sensor: 69 + // DGNSS/SBAS correction fix w/o sensor: 2, w/ sensor: 62 + // RTK fixed fix w/o sensor: 4, w/ sensor: 64 + // RTK float fix w/o sensor: 5, w/ sensor: 65 + // SPE fix w/o sensor: 1, and w/ sensor: 61 + // Sensor dead reckoning fix: 6 + if (true == custom_gga_fix_quality) { + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK) { + // PPP fix w/o sensor: fix quality will now be 59 + // PPP fix w sensor: fix quality will now be 69 + if (LOC_NAV_MASK_PPP_CORRECTION & locationExtended.navSolutionMask) { + if ((locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) && + (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask)) { + ggaGpsQuality[0] = '6'; + ggaGpsQuality[1] = '9'; + } else { + ggaGpsQuality[0] = '5'; + ggaGpsQuality[1] = '9'; + } + break; + } + } + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) { + if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){ + char ggaQuality_copy = ggaGpsQuality[0]; + ggaGpsQuality[0] = '6'; // 6 sensor assisted + // RTK fixed fix w/ sensor: fix quality will now be 64 + // RTK float fix w/ sensor: 65 + // DGNSS and/or SBAS correction fix and w/ sensor: 62 + // GPS fix without correction and w/ sensor: 61 + if ((LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask)|| + (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask)|| + (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask)|| + (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask)|| + (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask)) { + ggaGpsQuality[1] = ggaQuality_copy; + break; + } + } + } + } + } while (0); + + LOC_LOGv("gps quality: %s, rmc mode indicator: %c, vtg mode indicator: %c", + ggaGpsQuality, rmcModeIndicator, vtgModeIndicator); +} + +/*=========================================================================== FUNCTION loc_nmea_generate_pos DESCRIPTION @@ -475,11 +1181,20 @@ SIDE EFFECTS ===========================================================================*/ void loc_nmea_generate_pos(const UlpLocation &location, const GpsLocationExtended &locationExtended, + const LocationSystemInfo &systemInfo, unsigned char generate_nmea, + bool custom_gga_fix_quality, std::vector<std::string> &nmeaArraystr) { ENTRY_LOG(); - time_t utcTime(location.gpsLocation.timestamp/1000); + + LocGpsUtcTime utcPosTimestamp = 0; + bool inLsTransition = false; + + inLsTransition = get_utctime_with_leapsecond_transition + (location, locationExtended, systemInfo, utcPosTimestamp); + + time_t utcTime(utcPosTimestamp/1000); tm * pTm = gmtime(&utcTime); if (NULL == pTm) { LOC_LOGE("gmtime failed"); @@ -487,6 +1202,10 @@ void loc_nmea_generate_pos(const UlpLocation &location, } char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char sentence_DTM[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char sentence_RMC[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char sentence_GNS[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char sentence_GGA[NMEA_SENTENCE_MAX_LENGTH] = {0}; char* pMarker = sentence; int lengthRemaining = sizeof(sentence); int length = 0; @@ -497,22 +1216,45 @@ void loc_nmea_generate_pos(const UlpLocation &location, int utcMinutes = pTm->tm_min; int utcSeconds = pTm->tm_sec; int utcMSeconds = (location.gpsLocation.timestamp)%1000; - loc_sv_cache_info sv_cache_info = {}; + int datum_type = loc_get_datum_type(); + LocEcef ecef_w84; + LocEcef ecef_p90; + LocLla lla_w84; + LocLla lla_p90; + LocLla ref_lla; + LocLla local_lla; + + if (inLsTransition) { + // During leap second transition, we need to display the extra + // leap second of hour, minute, second as (23:59:60) + utcHours = 23; + utcMinutes = 59; + utcSeconds = 60; + // As UTC timestamp is freezing during leap second transition, + // retrieve milli-seconds portion from GPS timestamp. + utcMSeconds = locationExtended.gpsTime.gpsTimeOfWeekMs % 1000; + } + + loc_sv_cache_info sv_cache_info = {}; if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) { sv_cache_info.gps_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask; sv_cache_info.glo_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask; sv_cache_info.gal_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask; - sv_cache_info.qzss_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask; sv_cache_info.bds_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask; + sv_cache_info.qzss_used_mask = + locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask; + sv_cache_info.navic_used_mask = + locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask; } + if (generate_nmea) { char talker[3] = {'G', 'P', '\0'}; + char modeIndicator[7] = {0}; uint32_t svUsedCount = 0; uint32_t count = 0; loc_nmea_sv_meta sv_meta; @@ -521,8 +1263,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, true), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, + GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr); if (count > 0) { svUsedCount += count; @@ -535,8 +1277,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, true), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, + GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr); if (count > 0) { svUsedCount += count; @@ -549,8 +1291,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, true), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, + GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr); if (count > 0) { svUsedCount += count; @@ -558,31 +1300,39 @@ void loc_nmea_generate_pos(const UlpLocation &location, talker[1] = sv_meta.talker[1]; } - // -------------------------- - // ---$PQGSA/$GNGSA (QZSS)--- - // -------------------------- - + // ---------------------------- + // ---$GBGSA/$GNGSA (BEIDOU)--- + // ---------------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, + GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr); if (count > 0) { svUsedCount += count; - // talker should be default "GP". If GPS, GLO etc is used, it should be "GN" + talker[0] = sv_meta.talker[0]; + talker[1] = sv_meta.talker[1]; } - // ---------------------------- - // ---$PQGSA/$GNGSA (BEIDOU)--- - // ---------------------------- + // -------------------------- + // ---$GQGSA/$GNGSA (QZSS)--- + // -------------------------- + count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, + GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr); if (count > 0) { svUsedCount += count; - // talker should be default "GP". If GPS, GLO etc is used, it should be "GN" + talker[0] = sv_meta.talker[0]; + talker[1] = sv_meta.talker[1]; } + char ggaGpsQuality[3] = {'0', '\0', '\0'}; + char rmcModeIndicator = 'N'; + char vtgModeIndicator = 'N'; + loc_nmea_get_fix_quality(location, locationExtended, custom_gga_fix_quality, + ggaGpsQuality, rmcModeIndicator, vtgModeIndicator); + // ------------------- // ------$--VTG------- // ------------------- @@ -637,27 +1387,57 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) - // N means no fix - length = snprintf(pMarker, lengthRemaining, "%c", 'N'); - else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) - // D means differential - length = snprintf(pMarker, lengthRemaining, "%c", 'D'); - else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) - // E means estimated (dead reckoning) - length = snprintf(pMarker, lengthRemaining, "%c", 'E'); - else // A means autonomous - length = snprintf(pMarker, lengthRemaining, "%c", 'A'); + length = snprintf(pMarker, lengthRemaining, "%c", vtgModeIndicator); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); + memset(&ecef_w84, 0, sizeof(ecef_w84)); + memset(&ecef_p90, 0, sizeof(ecef_p90)); + memset(&lla_w84, 0, sizeof(lla_w84)); + memset(&lla_p90, 0, sizeof(lla_p90)); + memset(&ref_lla, 0, sizeof(ref_lla)); + memset(&local_lla, 0, sizeof(local_lla)); + lla_w84.lat = location.gpsLocation.latitude / 180.0 * M_PI; + lla_w84.lon = location.gpsLocation.longitude / 180.0 * M_PI; + lla_w84.alt = location.gpsLocation.altitude; + + convert_Lla_to_Ecef(lla_w84, ecef_w84); + convert_WGS84_to_PZ90(ecef_w84, ecef_p90); + convert_Ecef_to_Lla(ecef_p90, lla_p90); + + switch (datum_type) { + case LOC_GNSS_DATUM_WGS84: + ref_lla.lat = location.gpsLocation.latitude; + ref_lla.lon = location.gpsLocation.longitude; + ref_lla.alt = location.gpsLocation.altitude; + local_lla.lat = lla_p90.lat / M_PI * 180.0; + local_lla.lon = lla_p90.lon / M_PI * 180.0; + local_lla.alt = lla_p90.alt; + break; + case LOC_GNSS_DATUM_PZ90: + ref_lla.lat = lla_p90.lat / M_PI * 180.0; + ref_lla.lon = lla_p90.lon / M_PI * 180.0; + ref_lla.alt = lla_p90.alt; + local_lla.lat = location.gpsLocation.latitude; + local_lla.lon = location.gpsLocation.longitude; + local_lla.alt = location.gpsLocation.altitude; + break; + default: + break; + } + + // ------------------- + // ------$--DTM------- + // ------------------- + loc_nmea_generate_DTM(ref_lla, local_lla, talker, sentence_DTM, sizeof(sentence_DTM)); + // ------------------- // ------$--RMC------- // ------------------- - pMarker = sentence; - lengthRemaining = sizeof(sentence); + pMarker = sentence_RMC; + lengthRemaining = sizeof(sentence_RMC); length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A," , talker, utcHours, utcMinutes, utcSeconds,utcMSeconds/10); @@ -672,8 +1452,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) { - double latitude = location.gpsLocation.latitude; - double longitude = location.gpsLocation.longitude; + double latitude = ref_lla.lat; + double longitude = ref_lla.lon; char latHemisphere; char lonHemisphere; double latMinutes; @@ -795,17 +1575,176 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) - // N means no fix - length = snprintf(pMarker, lengthRemaining, "%c", 'N'); + length = snprintf(pMarker, lengthRemaining, "%c", rmcModeIndicator); + pMarker += length; + lengthRemaining -= length; + + // hardcode Navigation Status field to 'V' + length = snprintf(pMarker, lengthRemaining, ",%c", 'V'); + pMarker += length; + lengthRemaining -= length; + + length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC)); + + // ------------------- + // ------$--GNS------- + // ------------------- + + pMarker = sentence_GNS; + lengthRemaining = sizeof(sentence_GNS); + + length = snprintf(pMarker, lengthRemaining, "$%sGNS,%02d%02d%02d.%02d," , + talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) + { + double latitude = ref_lla.lat; + double longitude = ref_lla.lon; + char latHemisphere; + char lonHemisphere; + double latMinutes; + double lonMinutes; + + if (latitude > 0) + { + latHemisphere = 'N'; + } + else + { + latHemisphere = 'S'; + latitude *= -1.0; + } + + if (longitude < 0) + { + lonHemisphere = 'W'; + longitude *= -1.0; + } + else + { + lonHemisphere = 'E'; + } + + latMinutes = fmod(latitude * 60.0 , 60.0); + lonMinutes = fmod(longitude * 60.0 , 60.0); + + length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,", + (uint8_t)floor(latitude), latMinutes, latHemisphere, + (uint8_t)floor(longitude),lonMinutes, lonHemisphere); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,,,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if(!(sv_cache_info.gps_used_mask ? 1 : 0)) + modeIndicator[0] = 'N'; else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) - // D means differential - length = snprintf(pMarker, lengthRemaining, "%c", 'D'); + modeIndicator[0] = 'D'; else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) - // E means estimated (dead reckoning) - length = snprintf(pMarker, lengthRemaining, "%c", 'E'); - else // A means autonomous - length = snprintf(pMarker, lengthRemaining, "%c", 'A'); + modeIndicator[0] = 'E'; + else + modeIndicator[0] = 'A'; + if(!(sv_cache_info.glo_used_mask ? 1 : 0)) + modeIndicator[1] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[1] = 'E'; + else + modeIndicator[1] = 'A'; + if(!(sv_cache_info.gal_used_mask ? 1 : 0)) + modeIndicator[2] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[2] = 'E'; + else + modeIndicator[2] = 'A'; + if(!(sv_cache_info.bds_used_mask ? 1 : 0)) + modeIndicator[3] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[3] = 'E'; + else + modeIndicator[3] = 'A'; + if(!(sv_cache_info.qzss_used_mask ? 1 : 0)) + modeIndicator[4] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[4] = 'E'; + else + modeIndicator[4] = 'A'; + if(!(sv_cache_info.navic_used_mask ? 1 : 0)) + modeIndicator[5] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[5] = 'E'; + else + modeIndicator[5] = 'A'; + modeIndicator[6] = '\0'; + for(int index = 5; index > 0 && 'N' == modeIndicator[index]; index--) { + modeIndicator[index] = '\0'; + } + length = snprintf(pMarker, lengthRemaining,"%s,", modeIndicator); + + pMarker += length; + lengthRemaining -= length; + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) { + length = snprintf(pMarker, lengthRemaining, "%02d,%.1f,", + svUsedCount, locationExtended.hdop); + } + else { // no hdop + length = snprintf(pMarker, lengthRemaining, "%02d,,", + svUsedCount); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,", + locationExtended.altitudeMeanSeaLevel); + } + else + { + length = snprintf(pMarker, lengthRemaining,","); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if ((location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) && + (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,,", + ref_lla.alt - locationExtended.altitudeMeanSeaLevel); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,"); + } pMarker += length; lengthRemaining -= length; @@ -815,15 +1754,15 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); - nmeaArraystr.push_back(sentence); + length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS)); + // ------------------- // ------$--GGA------- // ------------------- - pMarker = sentence; - lengthRemaining = sizeof(sentence); + pMarker = sentence_GGA; + lengthRemaining = sizeof(sentence_GGA); length = snprintf(pMarker, lengthRemaining, "$%sGGA,%02d%02d%02d.%02d," , talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); @@ -838,8 +1777,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) { - double latitude = location.gpsLocation.latitude; - double longitude = location.gpsLocation.longitude; + double latitude = ref_lla.lat; + double longitude = ref_lla.lon; char latHemisphere; char lonHemisphere; double latMinutes; @@ -885,28 +1824,18 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - char gpsQuality; - if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) - gpsQuality = '0'; // 0 means no fix - else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) - gpsQuality = '2'; // 2 means DGPS fix - else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) - gpsQuality = '6'; // 6 means estimated (dead reckoning) - else - gpsQuality = '1'; // 1 means GPS fix - // Number of satellites in use, 00-12 if (svUsedCount > MAX_SATELLITES_IN_USE) svUsedCount = MAX_SATELLITES_IN_USE; if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) { - length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,", - gpsQuality, svUsedCount, locationExtended.hdop); + length = snprintf(pMarker, lengthRemaining, "%s,%02d,%.1f,", + ggaGpsQuality, svUsedCount, locationExtended.hdop); } else { // no hdop - length = snprintf(pMarker, lengthRemaining, "%c,%02d,,", - gpsQuality, svUsedCount); + length = snprintf(pMarker, lengthRemaining, "%s,%02d,,", + ggaGpsQuality, svUsedCount); } if (length < 0 || length >= lengthRemaining) @@ -939,35 +1868,52 @@ void loc_nmea_generate_pos(const UlpLocation &location, (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)) { length = snprintf(pMarker, lengthRemaining, "%.1lf,M,,", - location.gpsLocation.altitude - locationExtended.altitudeMeanSeaLevel); + ref_lla.alt - locationExtended.altitudeMeanSeaLevel); } else { length = snprintf(pMarker, lengthRemaining,",,,"); } - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); - nmeaArraystr.push_back(sentence); + length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA)); + + // ------$--DTM------- + nmeaArraystr.push_back(sentence_DTM); + // ------$--RMC------- + nmeaArraystr.push_back(sentence_RMC); + if(LOC_GNSS_DATUM_PZ90 == datum_type) { + // ------$--DTM------- + nmeaArraystr.push_back(sentence_DTM); + } + // ------$--GNS------- + nmeaArraystr.push_back(sentence_GNS); + if(LOC_GNSS_DATUM_PZ90 == datum_type) { + // ------$--DTM------- + nmeaArraystr.push_back(sentence_DTM); + } + // ------$--GGA------- + nmeaArraystr.push_back(sentence_GGA); + } //Send blank NMEA reports for non-final fixes else { - strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$PQGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPDTM,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); + strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence)); + strlcpy(sentence, "$GPGNS,,,,,,N,,,,,,,V", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); @@ -1017,9 +1963,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.gps_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.gps_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if (GNSS_SIGNAL_GPS_L5 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) { + sv_cache_info.gps_l5_count++; + } else { + // GNSS_SIGNAL_GPS_L1CA or default + // If no signal type in report, it means default L1 + sv_cache_info.gps_l1_count++; } - sv_cache_info.gps_count++; } else if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svNumber - 1].type) { @@ -1029,9 +1981,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.glo_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.glo_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if (GNSS_SIGNAL_GLONASS_G2 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){ + sv_cache_info.glo_g2_count++; + } else { + // GNSS_SIGNAL_GLONASS_G1 or default + // If no signal type in report, it means default G1 + sv_cache_info.glo_g1_count++; } - sv_cache_info.glo_count++; } else if (GNSS_SV_TYPE_GALILEO == svNotify.gnssSvs[svNumber - 1].type) { @@ -1041,9 +1999,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.gal_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.gal_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if(GNSS_SIGNAL_GALILEO_E5A == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){ + sv_cache_info.gal_e5_count++; + } else { + // GNSS_SIGNAL_GALILEO_E1 or default + // If no signal type in report, it means default E1 + sv_cache_info.gal_e1_count++; } - sv_cache_info.gal_count++; } else if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svNumber - 1].type) { @@ -1053,9 +2017,17 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.qzss_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + // For QZSS we adjusted SV id's in GnssAdapter, we need to re-adjust here + sv_cache_info.qzss_used_mask |= + (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - (QZSS_SV_PRN_MIN - 1) - 1)); + } + if (GNSS_SIGNAL_QZSS_L5 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) { + sv_cache_info.qzss_l5_count++; + } else { + // GNSS_SIGNAL_QZSS_L1CA or default + // If no signal type in report, it means default L1 + sv_cache_info.qzss_l1_count++; } - sv_cache_info.qzss_count++; } else if (GNSS_SV_TYPE_BEIDOU == svNotify.gnssSvs[svNumber - 1].type) { @@ -1065,50 +2037,117 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.bds_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.bds_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if(GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){ + sv_cache_info.bds_b2_count++; + } else { + // GNSS_SIGNAL_BEIDOU_B1I or default + // If no signal type in report, it means default B1I + sv_cache_info.bds_b1_count++; + } + } + else if (GNSS_SV_TYPE_NAVIC == svNotify.gnssSvs[svNumber - 1].type) + { + // cache the used in fix mask, as it will be needed to send $PQGSA + // during the position report + if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT == + (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & + GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) + { + sv_cache_info.navic_used_mask |= + (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); } - sv_cache_info.bds_count++; + // GNSS_SIGNAL_NAVIC_L5 is the only signal type for NAVIC + sv_cache_info.navic_l5_count++; } } loc_nmea_sv_meta sv_meta; - // ------------------ - // ------$GPGSV------ - // ------------------ + // --------------------- + // ------$GPGSV:L1CA---- + // --------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, false), nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, + GNSS_SIGNAL_GPS_L1CA, false), nmeaArraystr); + + // --------------------- + // ------$GPGSV:L5------ + // --------------------- - // ------------------ - // ------$GLGSV------ - // ------------------ + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, + GNSS_SIGNAL_GPS_L5, false), nmeaArraystr); + // --------------------- + // ------$GLGSV:G1------ + // --------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, + GNSS_SIGNAL_GLONASS_G1, false), nmeaArraystr); - // ------------------ - // ------$GAGSV------ - // ------------------ + // --------------------- + // ------$GLGSV:G2------ + // --------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, + GNSS_SIGNAL_GLONASS_G2, false), nmeaArraystr); + + // --------------------- + // ------$GAGSV:E1------ + // --------------------- + + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, + GNSS_SIGNAL_GALILEO_E1, false), nmeaArraystr); // ------------------------- - // ------$PQGSV (QZSS)------ + // ------$GAGSV:E5A--------- // ------------------------- + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, + GNSS_SIGNAL_GALILEO_E5A, false), nmeaArraystr); + + // ----------------------------- + // ------$PQGSV (QZSS):L1CA----- + // ----------------------------- + + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, + GNSS_SIGNAL_QZSS_L1CA, false), nmeaArraystr); + + // ----------------------------- + // ------$PQGSV (QZSS):L5------- + // ----------------------------- + + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, + GNSS_SIGNAL_QZSS_L5, false), nmeaArraystr); + // ----------------------------- + // ------$PQGSV (BEIDOU:B1I)---- + // ----------------------------- + + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, + GNSS_SIGNAL_BEIDOU_B1I,false), nmeaArraystr); + + // ----------------------------- + // ------$PQGSV (BEIDOU:B2AI)--- + // ----------------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, false), nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, + GNSS_SIGNAL_BEIDOU_B2AI,false), nmeaArraystr); - // --------------------------- - // ------$PQGSV (BEIDOU)------ - // --------------------------- + // ----------------------------- + // ------$GIGSV (NAVIC:L5)------ + // ----------------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_NAVIC, + GNSS_SIGNAL_NAVIC_L5,false), nmeaArraystr); EXIT_LOG(%d, 0); } diff --git a/gps/utils/loc_nmea.h b/gps/utils/loc_nmea.h index 585a9c1..a9cafb7 100644 --- a/gps/utils/loc_nmea.h +++ b/gps/utils/loc_nmea.h @@ -35,12 +35,51 @@ #include <string> #define NMEA_SENTENCE_MAX_LENGTH 200 +/** gnss datum type */ +#define LOC_GNSS_DATUM_WGS84 0 +#define LOC_GNSS_DATUM_PZ90 1 + +/* len of semi major axis of ref ellips*/ +#define MAJA (6378137.0) +/* flattening coef of ref ellipsoid*/ +#define FLAT (1.0/298.2572235630) +/* 1st eccentricity squared*/ +#define ESQR (FLAT*(2.0 - FLAT)) +/*1 minus eccentricity squared*/ +#define OMES (1.0 - ESQR) +#define MILARCSEC2RAD (4.848136811095361e-09) +/*semi major axis */ +#define C_PZ90A (6378136.0) +/*semi minor axis */ +#define C_PZ90B (6356751.3618) +/* Transformation from WGS84 to PZ90 + * Cx,Cy,Cz,Rs,Rx,Ry,Rz,C_SYS_A,C_SYS_B*/ +const double DatumConstFromWGS84[9] = + {+0.003, +0.001, 0.000, (1.0+(0.000*1E-6)), (-0.019*MILARCSEC2RAD), + (+0.042*MILARCSEC2RAD), (-0.002*MILARCSEC2RAD), C_PZ90A, C_PZ90B}; + +/** Represents a LTP*/ +typedef struct { + double lat; + double lon; + double alt; +} LocLla; + +/** Represents a ECEF*/ +typedef struct { + double X; + double Y; + double Z; +} LocEcef; + void loc_nmea_generate_sv(const GnssSvNotification &svNotify, std::vector<std::string> &nmeaArraystr); void loc_nmea_generate_pos(const UlpLocation &location, const GpsLocationExtended &locationExtended, + const LocationSystemInfo &systemInfo, unsigned char generate_nmea, + bool custom_gga_fix_quality, std::vector<std::string> &nmeaArraystr); #define DEBUG_NMEA_MINSIZE 6 diff --git a/gps/utils/loc_target.cpp b/gps/utils/loc_target.cpp index 569f3a7..3ee42e6 100644 --- a/gps/utils/loc_target.cpp +++ b/gps/utils/loc_target.cpp @@ -54,6 +54,7 @@ #define STR_MTP "MTP" #define STR_APQ "apq" #define STR_SDC "sdc" // alternative string for APQ targets +#define STR_QCS "qcs" // string for Gen9 APQ targets #define STR_MSM "msm" #define STR_SDM "sdm" // alternative string for MSM targets #define STR_APQ_NO_WGR "baseband_apq_nowgr" @@ -79,6 +80,11 @@ static int read_a_line(const char * file_path, char * line, int line_size) int len; fgets(line, line_size, fp); len = strlen(line); + while ('\n' == line[len-1]) { + // If there is a new line at end of string, replace it with NULL + line[len-1] = '\0'; + len--; + } len = len < line_size - 1? len : line_size - 1; line[len] = '\0'; LOC_LOGD("cat %s: %s", file_path, line); @@ -129,16 +135,53 @@ void loc_get_auto_platform_name(char *platform_name, int array_length) } } +/*Reads the property ro.config.low_ram to identify if this is a low ram target + Returns: + 0 if not a low ram target + 1 if this is a low ram target +*/ +int loc_identify_low_ram_target() +{ + int ret = 0; + char low_ram_target[PROPERTY_VALUE_MAX]; + property_get("ro.config.low_ram", low_ram_target, ""); + LOC_LOGd("low ram target: %s\n", low_ram_target); + return !(strncmp(low_ram_target, "true", PROPERTY_VALUE_MAX)); +} + +/*The character array passed to this function should have length + of atleast PROPERTY_VALUE_MAX*/ +/* Reads the soc_id node and return the soc_id value */ +void loc_get_device_soc_id(char *soc_id_value, int array_length) +{ + static const char soc_id[] = "/sys/devices/soc0/soc_id"; + static const char soc_id_dep[] = "/sys/devices/system/soc/soc0/id"; + int return_val = 0; + + if (soc_id_value && (array_length >= PROPERTY_VALUE_MAX)) { + if (!access(soc_id, F_OK)) { + return_val = read_a_line(soc_id, soc_id_value, array_length); + } else { + return_val = read_a_line(soc_id_dep, soc_id_value, array_length); + } + if (0 == return_val) { + LOC_LOGd("SOC Id value: %s\n", soc_id_value); + } else { + LOC_LOGe("Unable to read the soc_id value\n"); + } + } else { + LOC_LOGe("Null parameter or array length less than PROPERTY_VALUE_MAX\n"); + } +} + unsigned int loc_get_target(void) { if (gTarget != (unsigned int)-1) return gTarget; static const char hw_platform[] = "/sys/devices/soc0/hw_platform"; - static const char id[] = "/sys/devices/soc0/soc_id"; static const char hw_platform_dep[] = "/sys/devices/system/soc/soc0/hw_platform"; - static const char id_dep[] = "/sys/devices/system/soc/soc0/id"; static const char mdm[] = "/target"; // mdm target we are using char rd_hw_platform[LINE_LEN]; @@ -154,11 +197,8 @@ unsigned int loc_get_target(void) } else { read_a_line(hw_platform_dep, rd_hw_platform, LINE_LEN); } - if (!access(id, F_OK)) { - read_a_line(id, rd_id, LINE_LEN); - } else { - read_a_line(id_dep, rd_id, LINE_LEN); - } + // Get the soc-id for this device. + loc_get_device_soc_id(rd_id, sizeof(rd_id)); /*check automotive platform*/ loc_get_auto_platform_name(rd_auto_platform, sizeof(rd_auto_platform)); @@ -175,7 +215,8 @@ unsigned int loc_get_target(void) } if( !memcmp(baseband, STR_APQ, LENGTH(STR_APQ)) || - !memcmp(baseband, STR_SDC, LENGTH(STR_SDC)) ) { + !memcmp(baseband, STR_SDC, LENGTH(STR_SDC)) || + !memcmp(baseband, STR_QCS, LENGTH(STR_QCS)) ) { if( !memcmp(rd_id, MPQ8064_ID_1, LENGTH(MPQ8064_ID_1)) && IS_STR_END(rd_id[LENGTH(MPQ8064_ID_1)]) ) diff --git a/gps/utils/loc_target.h b/gps/utils/loc_target.h index 172b475..2dcd895 100644 --- a/gps/utils/loc_target.h +++ b/gps/utils/loc_target.h @@ -54,6 +54,10 @@ void loc_get_platform_name(char *platform_name, int array_length); /*The character array passed to this function should have length of atleast PROPERTY_VALUE_MAX*/ void loc_get_auto_platform_name(char *platform_name, int array_length); +int loc_identify_low_ram_target(); +/*The character array passed to this function should have length + of atleast PROPERTY_VALUE_MAX*/ +void loc_get_device_soc_id(char *soc_id_value, int array_length); /* Please remember to update 'target_name' in loc_log.cpp, if do any changes to this enum. */ diff --git a/gps/utils/log_util.h b/gps/utils/log_util.h index feb4d3c..192baeb 100644 --- a/gps/utils/log_util.h +++ b/gps/utils/log_util.h @@ -39,13 +39,41 @@ #include <stdio.h> #include <string.h> #include <sys/types.h> +#include <sys/time.h> #include <unistd.h> -#include <cutils/log.h> #ifndef LOG_TAG #define LOG_TAG "GPS_UTILS" #endif /* LOG_TAG */ +// LE targets with no logcat support +#ifdef FEATURE_EXTERNAL_AP +#include <syslog.h> +#define ALOGE(...) syslog(LOG_ERR, "LOC_LOGE: " __VA_ARGS__); +#define ALOGW(...) syslog(LOG_WARNING, "LOC_LOGW: " __VA_ARGS__); +#define ALOGI(...) syslog(LOG_NOTICE, "LOC_LOGI: " __VA_ARGS__); +#define ALOGD(...) syslog(LOG_DEBUG, "LOC_LOGD: " __VA_ARGS__); +#define ALOGV(...) syslog(LOG_NOTICE, "LOC_LOGV: " __VA_ARGS__); +#else /* FEATURE_EXTERNAL_AP */ +#define TS_PRINTF(format, x...) \ +{ \ + struct timeval tv; \ + struct timezone tz; \ + int hh, mm, ss; \ + gettimeofday(&tv, &tz); \ + hh = tv.tv_sec/3600%24; \ + mm = (tv.tv_sec%3600)/60; \ + ss = tv.tv_sec%60; \ + fprintf(stdout,"%02d:%02d:%02d.%06ld]" format "\n", hh, mm, ss, tv.tv_usec, ##x); \ +} + +#define ALOGE(format, x...) TS_PRINTF("E/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGW(format, x...) TS_PRINTF("W/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGI(format, x...) TS_PRINTF("I/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGD(format, x...) TS_PRINTF("D/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGV(format, x...) TS_PRINTF("V/%s (%d): " format , LOG_TAG, getpid(), ##x) +#endif /* FEATURE_EXTERNAL_AP */ + #endif /* #if defined (USE_ANDROID_LOGGING) || defined (ANDROID) */ #ifdef __cplusplus @@ -148,6 +176,7 @@ extern char* get_timestamp(char* str, unsigned long buf_size); #define LOG_I(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGI, ID, WHAT, SPEC, VAL) #define LOG_V(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGV, ID, WHAT, SPEC, VAL) #define LOG_E(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGE, ID, WHAT, SPEC, VAL) +#define LOG_D(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGD, ID, WHAT, SPEC, VAL) #define ENTRY_LOG() LOG_V(ENTRY_TAG, __FUNCTION__, %s, "") #define EXIT_LOG(SPEC, VAL) LOG_V(EXIT_TAG, __FUNCTION__, SPEC, VAL) @@ -165,6 +194,8 @@ extern char* get_timestamp(char* str, unsigned long buf_size); #define EXIT_LOG_CALLFLOW(SPEC, VAL) LOG_I(TO_MODEM, __FUNCTION__, SPEC, VAL) // Used for logging callflow from Modem(TO_MODEM, __FUNCTION__, %s, "") #define MODEM_LOG_CALLFLOW(SPEC, VAL) LOG_I(FROM_MODEM, __FUNCTION__, SPEC, VAL) +// Used for logging high frequency callflow from Modem(TO_MODEM, __FUNCTION__, %s, "") +#define MODEM_LOG_CALLFLOW_DEBUG(SPEC, VAL) LOG_D(FROM_MODEM, __FUNCTION__, SPEC, VAL) // Used for logging callflow to Android Framework #define CALLBACK_LOG_CALLFLOW(CB, SPEC, VAL) LOG_I(TO_AFW, CB, SPEC, VAL) diff --git a/gps/utils/msg_q.c b/gps/utils/msg_q.c index 76c1478..2d49b4a 100644 --- a/gps/utils/msg_q.c +++ b/gps/utils/msg_q.c @@ -267,6 +267,51 @@ msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj) /*=========================================================================== + FUNCTION: msg_q_rmv + + ===========================================================================*/ +msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj) +{ + msq_q_err_type rv; + if (msg_q_data == NULL) { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + + if (msg_obj == NULL) { + LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_PARAMETER; + } + + msg_q* p_msg_q = (msg_q*)msg_q_data; + + pthread_mutex_lock(&p_msg_q->list_mutex); + + if (p_msg_q->unblocked) { + LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eMSG_Q_UNAVAILABLE_RESOURCE; + } + + if (linked_list_empty(p_msg_q->msg_list)) { + LOC_LOGW("%s: list is empty !!\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eLINKED_LIST_EMPTY; + } + + rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj)); + + pthread_mutex_unlock(&p_msg_q->list_mutex); + + LOC_LOGV("%s: Removed message %p rv = %d\n", __FUNCTION__, *msg_obj, rv); + + return rv; +} + + + +/*=========================================================================== + FUNCTION: msg_q_flush ===========================================================================*/ diff --git a/gps/utils/msg_q.h b/gps/utils/msg_q.h index 453b8ce..16df494 100644 --- a/gps/utils/msg_q.h +++ b/gps/utils/msg_q.h @@ -158,6 +158,29 @@ SIDE EFFECTS msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj); /*=========================================================================== +FUNCTION msg_q_rmv + +DESCRIPTION + Remove data from the message queue. msg_obj is the oldest message received + and pointer is simply removed from message queue. + + msg_q_data: Message Queue to copy data from into msgp. + msg_obj: Pointer to space to copy msg_q contents to. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj); + + +/*=========================================================================== FUNCTION msg_q_flush DESCRIPTION |