gps: Import from LA.UM.5.6.r1-01900-89xx.0 release

Change-Id: Ie959cd02b338e2cd98287fc8e16d0448faa34932
This commit is contained in:
Alberto97
2017-04-22 21:41:55 +02:00
committed by Vachounet
parent d6a8e57d26
commit 57e4293652
106 changed files with 20700 additions and 0 deletions

3
gps/loc_api/Android.mk Normal file
View File

@@ -0,0 +1,3 @@
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,111 @@
ifneq ($(BUILD_TINY_ANDROID),true)
#Compile this library only for builds with the latest modem image
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libloc_eng
LOCAL_MODULE_OWNER := qcom
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
libdl \
liblog \
libloc_core \
libgps.utils \
libloc_pla
LOCAL_SRC_FILES += \
loc_eng.cpp \
loc_eng_agps.cpp \
loc_eng_xtra.cpp \
loc_eng_ni.cpp \
loc_eng_log.cpp \
loc_eng_nmea.cpp \
LocEngAdapter.cpp
LOCAL_SRC_FILES += \
loc_eng_dmn_conn.cpp \
loc_eng_dmn_conn_handler.cpp \
loc_eng_dmn_conn_thread_helper.c \
loc_eng_dmn_conn_glue_msg.c \
loc_eng_dmn_conn_glue_pipe.c
LOCAL_CFLAGS += \
-fno-short-enums \
-D_ANDROID_
LOCAL_C_INCLUDES:= \
$(LOCAL_PATH) \
$(TARGET_OUT_HEADERS)/gps.utils \
$(TARGET_OUT_HEADERS)/libloc_core \
$(TARGET_OUT_HEADERS)/libflp \
$(TARGET_OUT_HEADERS)/libloc_pla
LOCAL_COPY_HEADERS_TO:= libloc_eng/
LOCAL_COPY_HEADERS:= \
LocEngAdapter.h \
loc.h \
loc_eng.h \
loc_eng_xtra.h \
loc_eng_ni.h \
loc_eng_agps.h \
loc_eng_msg.h \
loc_eng_log.h
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := gps.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_OWNER := qcom
LOCAL_MODULE_TAGS := optional
## Libs
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
liblog \
libloc_eng \
libloc_core \
libgps.utils \
libdl \
libloc_pla
LOCAL_SRC_FILES += \
loc.cpp \
gps.c
LOCAL_CFLAGS += \
-fno-short-enums \
-D_ANDROID_ \
ifeq ($(TARGET_BUILD_VARIANT),user)
LOCAL_CFLAGS += -DTARGET_BUILD_VARIANT_USER
endif
ifeq ($(TARGET_USES_QCOM_BSP), true)
LOCAL_CFLAGS += -DTARGET_USES_QCOM_BSP
endif
## Includes
LOCAL_C_INCLUDES:= \
$(TARGET_OUT_HEADERS)/gps.utils \
$(TARGET_OUT_HEADERS)/libloc_core \
$(TARGET_OUT_HEADERS)/libflp \
$(TARGET_OUT_HEADERS)/libloc_pla
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_RELATIVE_PATH := hw
include $(BUILD_SHARED_LIBRARY)
endif # not BUILD_TINY_ANDROID

View File

@@ -0,0 +1,598 @@
/* Copyright (c) 2011-2015, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_NDDEBUG 0
#define LOG_TAG "LocSvc_EngAdapter"
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <cutils/properties.h>
#include <LocEngAdapter.h>
#include "loc_eng_msg.h"
#include "loc_log.h"
#define CHIPSET_SERIAL_NUMBER_MAX_LEN 16
#define USER_AGENT_MAX_LEN 512
using namespace loc_core;
LocInternalAdapter::LocInternalAdapter(LocEngAdapter* adapter) :
LocAdapterBase(adapter->getMsgTask()),
mLocEngAdapter(adapter)
{
}
void LocInternalAdapter::setPositionModeInt(LocPosMode& posMode) {
sendMsg(new LocEngPositionMode(mLocEngAdapter, posMode));
}
void LocInternalAdapter::startFixInt() {
sendMsg(new LocEngStartFix(mLocEngAdapter));
}
void LocInternalAdapter::stopFixInt() {
sendMsg(new LocEngStopFix(mLocEngAdapter));
}
void LocInternalAdapter::getZppInt() {
sendMsg(new LocEngGetZpp(mLocEngAdapter));
}
LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask,
void* owner, ContextBase* context,
LocThread::tCreate tCreator) :
LocAdapterBase(mask,
//Get the AFW context if VzW context has not already been intialized in
//loc_ext
context == NULL?
LocDualContext::getLocFgContext(tCreator,
NULL,
LocDualContext::mLocationHalName,
false)
:context),
mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)),
mUlp(new UlpProxyBase()), mNavigating(false),
mSupportsAgpsRequests(false),
mSupportsPositionInjection(false),
mSupportsTimeInjection(false),
mPowerVote(0)
{
memset(&mFixCriteria, 0, sizeof(mFixCriteria));
mFixCriteria.mode = LOC_POSITION_MODE_INVALID;
LOC_LOGD("LocEngAdapter created");
}
inline
LocEngAdapter::~LocEngAdapter()
{
delete mInternalAdapter;
LOC_LOGV("LocEngAdapter deleted");
}
void LocEngAdapter::setXtraUserAgent() {
struct LocSetXtraUserAgent : public LocMsg {
const ContextBase* const mContext;
inline LocSetXtraUserAgent(ContextBase* context) :
LocMsg(), mContext(context) {
}
virtual void proc() const {
char release[PROPERTY_VALUE_MAX];
char manufacture[PROPERTY_VALUE_MAX];
char model[PROPERTY_VALUE_MAX];
char board[PROPERTY_VALUE_MAX];
char brand[PROPERTY_VALUE_MAX];
char chipsetsn[CHIPSET_SERIAL_NUMBER_MAX_LEN];
char userAgent[USER_AGENT_MAX_LEN];
const char defVal[] = "-";
property_get("ro.build.version.release", release, defVal);
property_get("ro.product.manufacturer", manufacture, defVal);
property_get("ro.product.model", model, defVal);
property_get("ro.product.board", board, defVal);
property_get("ro.product.brand", brand, defVal);
getChipsetSerialNo(chipsetsn, sizeof(chipsetsn), defVal);
encodeInPlace(release, PROPERTY_VALUE_MAX);
encodeInPlace(manufacture, PROPERTY_VALUE_MAX);
encodeInPlace(model, PROPERTY_VALUE_MAX);
encodeInPlace(board, PROPERTY_VALUE_MAX);
encodeInPlace(brand, PROPERTY_VALUE_MAX);
snprintf(userAgent, sizeof(userAgent), "A/%s/%s/%s/%s/-/QCX3/s%u/-/%s/-/%s/-/-/-",
release, manufacture, model, board,
mContext->getIzatDevId(), chipsetsn, brand);
for (int i = 0; i < sizeof(userAgent) && userAgent[i]; i++) {
if (' ' == userAgent[i]) userAgent[i] = '#';
}
saveUserAgentString(userAgent, strlen(userAgent));
LOC_LOGV("%s] UserAgent %s", __func__, userAgent);
}
void saveUserAgentString(const char* data, const int len) const {
const char XTRA_FOLDER[] = "/data/misc/location/xtra";
const char USER_AGENT_FILE[] = "/data/misc/location/xtra/useragent.txt";
if (data == NULL || len < 1) {
LOC_LOGE("%s:%d]: invalid input data = %p len = %d", __func__, __LINE__, data, len);
return;
}
struct stat s;
int err = stat(XTRA_FOLDER, &s);
if (err < 0) {
if (ENOENT == errno) {
if (mkdir(XTRA_FOLDER, 0700) < 0) {
LOC_LOGE("%s:%d]: make XTRA_FOLDER failed", __func__, __LINE__);
return;
}
} else {
LOC_LOGE("%s:%d]: XTRA_FOLDER invalid", __func__, __LINE__);
return;
}
}
FILE* file = fopen(USER_AGENT_FILE, "wt");
if (file == NULL) {
LOC_LOGE("%s:%d]: open USER_AGENT_FILE failed", __func__, __LINE__);
return;
}
size_t written = fwrite(data, 1, len, file);
fclose(file);
file = NULL;
// set file permission
chmod(USER_AGENT_FILE, 0600);
if (written != len) {
LOC_LOGE("%s:%d]: write USER_AGENT_FILE failed", __func__, __LINE__);
}
}
void getChipsetSerialNo(char buf[], int buflen, const char def[]) const {
const char SOC_SERIAL_NUMBER[] = "/sys/devices/soc0/serial_number";
FILE* file = fopen(SOC_SERIAL_NUMBER, "rt");
if (file == NULL) {
// use default upon unreadable file
strlcpy(buf, def, buflen);
} else {
size_t size = fread(buf, 1, buflen - 1, file);
if (size == 0) {
// use default upon empty file
strlcpy(buf, def, buflen);
} else {
buf[size] = '\0';
}
fclose(file);
// remove trailing spaces
size_t len = strlen(buf);
while (--len >= 0 && isspace(buf[len])) {
buf[len] = '\0';
}
}
return;
}
/**
* encode the given string value such that all separator characters ('/','+','|','%')
* in the string are repaced by their corresponding encodings (%2F","%2B","%7C", "%25")
*/
static void encodeInPlace(char value[], const int size) {
char buffer[size];
struct ENCODE {
const char ch;
const char *code;
};
const ENCODE encodings[] = { {'/', "%2F"}, {'+', "%2B"}, {'|', "%7C",}, {'%', "%25"} };
const int nencodings = (int)sizeof(encodings) / sizeof(encodings[0]);
int inpos = 0, outpos = 0;
while(value[inpos] != '\0' && outpos < size - 1) {
// check if escaped character
int escchar = 0;
while(escchar < nencodings && encodings[escchar].ch != value[inpos]) {
escchar++;
}
if (escchar == nencodings) {
// non escaped character
buffer[outpos++] = value[inpos++];
continue;
}
// escaped character
int codepos = 0;
#define NUM_CHARS_IN_CODE 3
if (outpos + NUM_CHARS_IN_CODE >= size) {
// skip last character if there is insufficient space
break;
}
while(outpos < size - 1 && codepos < NUM_CHARS_IN_CODE) {
buffer[outpos++] = encodings[escchar].code[codepos++];
}
inpos++;
}
// copy to ouput
value[outpos] = '\0';
while(--outpos >= 0) {
value[outpos] = buffer[outpos];
}
}
};
sendMsg(new LocSetXtraUserAgent(mContext));
}
void LocInternalAdapter::setUlpProxy(UlpProxyBase* ulp) {
struct LocSetUlpProxy : public LocMsg {
LocAdapterBase* mAdapter;
UlpProxyBase* mUlp;
inline LocSetUlpProxy(LocAdapterBase* adapter, UlpProxyBase* ulp) :
LocMsg(), mAdapter(adapter), mUlp(ulp) {
}
virtual void proc() const {
LOC_LOGV("%s] ulp %p adapter %p", __func__,
mUlp, mAdapter);
mAdapter->setUlpProxy(mUlp);
}
};
sendMsg(new LocSetUlpProxy(mLocEngAdapter, ulp));
}
void LocEngAdapter::setUlpProxy(UlpProxyBase* ulp)
{
if (ulp == mUlp) {
//This takes care of the case when double initalization happens
//and we get the same object back for UlpProxyBase . Do nothing
return;
}
LOC_LOGV("%s] %p", __func__, ulp);
if (NULL == ulp) {
LOC_LOGE("%s:%d]: ulp pointer is NULL", __func__, __LINE__);
ulp = new UlpProxyBase();
}
if (LOC_POSITION_MODE_INVALID != mUlp->mPosMode.mode) {
// need to send this mode and start msg to ULP
ulp->sendFixMode(mUlp->mPosMode);
}
if(mUlp->mFixSet) {
ulp->sendStartFix();
}
delete mUlp;
mUlp = ulp;
}
int LocEngAdapter::setGpsLockMsg(LOC_GPS_LOCK_MASK lockMask)
{
struct LocEngAdapterGpsLock : public LocMsg {
LocEngAdapter* mAdapter;
LOC_GPS_LOCK_MASK mLockMask;
inline LocEngAdapterGpsLock(LocEngAdapter* adapter, LOC_GPS_LOCK_MASK lockMask) :
LocMsg(), mAdapter(adapter), mLockMask(lockMask)
{
locallog();
}
inline virtual void proc() const {
mAdapter->setGpsLock(mLockMask);
}
inline void locallog() const {
LOC_LOGV("LocEngAdapterGpsLock - mLockMask: %x", mLockMask);
}
inline virtual void log() const {
locallog();
}
};
sendMsg(new LocEngAdapterGpsLock(this, lockMask));
return 0;
}
void LocEngAdapter::requestPowerVote()
{
if (getPowerVoteRight()) {
/* Power voting without engine lock:
* 101: vote down, 102-104 - vote up
* These codes are used not to confuse with actual engine lock
* functionality, that can't be used in SSR scenario, as it
* conflicts with initialization sequence.
*/
bool powerUp = getPowerVote();
LOC_LOGV("LocEngAdapterVotePower - Vote Power: %d", (int)powerUp);
setGpsLock(powerUp ? 103 : 101);
}
}
void LocInternalAdapter::reportPosition(UlpLocation &location,
GpsLocationExtended &locationExtended,
void* locationExt,
enum loc_sess_status status,
LocPosTechMask loc_technology_mask)
{
sendMsg(new LocEngReportPosition(mLocEngAdapter,
location,
locationExtended,
locationExt,
status,
loc_technology_mask));
}
void LocEngAdapter::reportPosition(UlpLocation &location,
GpsLocationExtended &locationExtended,
void* locationExt,
enum loc_sess_status status,
LocPosTechMask loc_technology_mask)
{
if (! mUlp->reportPosition(location,
locationExtended,
locationExt,
status,
loc_technology_mask )) {
mInternalAdapter->reportPosition(location,
locationExtended,
locationExt,
status,
loc_technology_mask);
}
}
void LocInternalAdapter::reportSv(GnssSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt){
sendMsg(new LocEngReportSv(mLocEngAdapter, svStatus,
locationExtended, svExt));
}
void LocEngAdapter::reportSv(GnssSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt)
{
// We want to send SV info to ULP to help it in determining GNSS
// signal strength ULP will forward the SV reports to HAL without
// any modifications
if (! mUlp->reportSv(svStatus, locationExtended, svExt)) {
mInternalAdapter->reportSv(svStatus, locationExtended, svExt);
}
}
void LocEngAdapter::reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet)
{
// We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
if (! mUlp->reportSvMeasurement(svMeasurementSet)) {
//Send to Internal Adapter later if needed by LA
}
}
void LocEngAdapter::reportSvPolynomial(GnssSvPolynomial &svPolynomial)
{
// We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
if (! mUlp->reportSvPolynomial(svPolynomial)) {
//Send to Internal Adapter later if needed by LA
}
}
void LocEngAdapter::setInSession(bool inSession)
{
mNavigating = inSession;
mLocApi->setInSession(inSession);
if (!mNavigating) {
mFixCriteria.mode = LOC_POSITION_MODE_INVALID;
}
}
void LocInternalAdapter::reportStatus(GpsStatusValue status)
{
sendMsg(new LocEngReportStatus(mLocEngAdapter, status));
}
void LocEngAdapter::reportStatus(GpsStatusValue status)
{
if (!mUlp->reportStatus(status)) {
mInternalAdapter->reportStatus(status);
}
}
inline
void LocEngAdapter::reportNmea(const char* nmea, int length)
{
sendMsg(new LocEngReportNmea(mOwner, nmea, length));
}
inline
bool LocEngAdapter::reportXtraServer(const char* url1,
const char* url2,
const char* url3,
const int maxlength)
{
if (mSupportsAgpsRequests) {
sendMsg(new LocEngReportXtraServer(mOwner, url1,
url2, url3, maxlength));
}
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::requestATL(int connHandle, AGpsType agps_type)
{
if (mSupportsAgpsRequests) {
sendMsg(new LocEngRequestATL(mOwner,
connHandle, agps_type));
}
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::releaseATL(int connHandle)
{
if (mSupportsAgpsRequests) {
sendMsg(new LocEngReleaseATL(mOwner, connHandle));
}
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::requestXtraData()
{
if (mSupportsAgpsRequests) {
sendMsg(new LocEngRequestXtra(mOwner));
}
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::requestTime()
{
if (mSupportsAgpsRequests) {
sendMsg(new LocEngRequestTime(mOwner));
}
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::requestNiNotify(GpsNiNotification &notif, const void* data)
{
if (mSupportsAgpsRequests) {
notif.size = sizeof(notif);
notif.timeout = LOC_NI_NO_RESPONSE_TIME;
sendMsg(new LocEngRequestNi(mOwner, notif, data));
}
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::requestSuplES(int connHandle)
{
if (mSupportsAgpsRequests)
sendMsg(new LocEngRequestSuplEs(mOwner, connHandle));
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::reportDataCallOpened()
{
if(mSupportsAgpsRequests)
sendMsg(new LocEngSuplEsOpened(mOwner));
return mSupportsAgpsRequests;
}
inline
bool LocEngAdapter::reportDataCallClosed()
{
if(mSupportsAgpsRequests)
sendMsg(new LocEngSuplEsClosed(mOwner));
return mSupportsAgpsRequests;
}
inline
void LocEngAdapter::handleEngineDownEvent()
{
sendMsg(new LocEngDown(mOwner));
}
inline
void LocEngAdapter::handleEngineUpEvent()
{
sendMsg(new LocEngUp(mOwner));
}
enum loc_api_adapter_err LocEngAdapter::setTime(GpsUtcTime time,
int64_t timeReference,
int uncertainty)
{
loc_api_adapter_err result = LOC_API_ADAPTER_ERR_SUCCESS;
LOC_LOGD("%s:%d]: mSupportsTimeInjection is %d",
__func__, __LINE__, mSupportsTimeInjection);
if (mSupportsTimeInjection) {
LOC_LOGD("%s:%d]: Injecting time", __func__, __LINE__);
result = mLocApi->setTime(time, timeReference, uncertainty);
}
return result;
}
enum loc_api_adapter_err LocEngAdapter::setXtraVersionCheck(int check)
{
enum loc_api_adapter_err ret;
ENTRY_LOG();
enum xtra_version_check eCheck;
switch (check) {
case 0:
eCheck = DISABLED;
break;
case 1:
eCheck = AUTO;
break;
case 2:
eCheck = XTRA2;
break;
case 3:
eCheck = XTRA3;
break;
default:
eCheck = DISABLED;
}
ret = mLocApi->setXtraVersionCheck(eCheck);
EXIT_LOG(%d, ret);
return ret;
}
void LocEngAdapter::reportGnssMeasurementData(GnssData &gnssMeasurementData)
{
sendMsg(new LocEngReportGnssMeasurement(mOwner,
gnssMeasurementData));
}
/*
Set Gnss Constellation Config
*/
bool LocEngAdapter::gnssConstellationConfig()
{
LOC_LOGD("entering %s", __func__);
bool result = false;
result = mLocApi->gnssConstellationConfig();
return result;
}

View File

@@ -0,0 +1,355 @@
/* Copyright (c) 2011-2016, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_API_ENG_ADAPTER_H
#define LOC_API_ENG_ADAPTER_H
#include <ctype.h>
#include <hardware/gps.h>
#include <loc.h>
#include <loc_eng_log.h>
#include <LocAdapterBase.h>
#include <LocDualContext.h>
#include <UlpProxyBase.h>
#include <platform_lib_includes.h>
#define MAX_URL_LEN 256
using namespace loc_core;
class LocEngAdapter;
class LocInternalAdapter : public LocAdapterBase {
LocEngAdapter* mLocEngAdapter;
public:
LocInternalAdapter(LocEngAdapter* adapter);
virtual void reportPosition(UlpLocation &location,
GpsLocationExtended &locationExtended,
void* locationExt,
enum loc_sess_status status,
LocPosTechMask loc_technology_mask);
virtual void reportSv(GnssSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt);
virtual void reportStatus(GpsStatusValue status);
virtual void setPositionModeInt(LocPosMode& posMode);
virtual void startFixInt();
virtual void stopFixInt();
virtual void getZppInt();
virtual void setUlpProxy(UlpProxyBase* ulp);
};
typedef void (*loc_msg_sender)(void* loc_eng_data_p, void* msgp);
class LocEngAdapter : public LocAdapterBase {
void* mOwner;
LocInternalAdapter* mInternalAdapter;
UlpProxyBase* mUlp;
LocPosMode mFixCriteria;
bool mNavigating;
// mPowerVote is encoded as
// mPowerVote & 0x20 -- powerVoteRight
// mPowerVote & 0x10 -- power On / Off
unsigned int mPowerVote;
static const unsigned int POWER_VOTE_RIGHT = 0x20;
static const unsigned int POWER_VOTE_VALUE = 0x10;
public:
bool mSupportsAgpsRequests;
bool mSupportsPositionInjection;
bool mSupportsTimeInjection;
GnssSystemInfo mGnssInfo;
LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask,
void* owner, ContextBase* context,
LocThread::tCreate tCreator);
virtual ~LocEngAdapter();
virtual void setUlpProxy(UlpProxyBase* ulp);
void setXtraUserAgent();
inline void requestUlp(unsigned long capabilities) {
mContext->requestUlp(mInternalAdapter, capabilities);
}
inline LocInternalAdapter* getInternalAdapter() { return mInternalAdapter; }
inline UlpProxyBase* getUlpProxy() { return mUlp; }
inline void* getOwner() { return mOwner; }
inline bool hasAgpsExtendedCapabilities() {
return mContext->hasAgpsExtendedCapabilities();
}
inline bool hasCPIExtendedCapabilities() {
return mContext->hasCPIExtendedCapabilities();
}
inline bool hasNativeXtraClient() {
return mContext->hasNativeXtraClient();
}
inline const MsgTask* getMsgTask() { return mMsgTask; }
inline enum loc_api_adapter_err
startFix()
{
return mLocApi->startFix(mFixCriteria);
}
inline enum loc_api_adapter_err
stopFix()
{
return mLocApi->stopFix();
}
inline enum loc_api_adapter_err
deleteAidingData(GpsAidingData f)
{
return mLocApi->deleteAidingData(f);
}
inline enum loc_api_adapter_err
enableData(int enable)
{
return mLocApi->enableData(enable);
}
inline enum loc_api_adapter_err
setAPN(char* apn, int len)
{
return mLocApi->setAPN(apn, len);
}
inline enum loc_api_adapter_err
injectPosition(double latitude, double longitude, float accuracy)
{
return mLocApi->injectPosition(latitude, longitude, accuracy);
}
inline enum loc_api_adapter_err
setXtraData(char* data, int length)
{
return mLocApi->setXtraData(data, length);
}
inline enum loc_api_adapter_err
requestXtraServer()
{
return mLocApi->requestXtraServer();
}
inline enum loc_api_adapter_err
atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bearer, AGpsType agpsType)
{
return mLocApi->atlOpenStatus(handle, is_succ, apn, bearer, agpsType);
}
inline enum loc_api_adapter_err
atlCloseStatus(int handle, int is_succ)
{
return mLocApi->atlCloseStatus(handle, is_succ);
}
inline enum loc_api_adapter_err
setPositionMode(const LocPosMode *posMode)
{
if (NULL != posMode) {
mFixCriteria = *posMode;
}
return mLocApi->setPositionMode(mFixCriteria);
}
inline enum loc_api_adapter_err
setServer(const char* url, int len)
{
return mLocApi->setServer(url, len);
}
inline enum loc_api_adapter_err
setServer(unsigned int ip, int port,
LocServerType type)
{
return mLocApi->setServer(ip, port, type);
}
inline enum loc_api_adapter_err
informNiResponse(GpsUserResponseType userResponse, const void* passThroughData)
{
return mLocApi->informNiResponse(userResponse, passThroughData);
}
inline enum loc_api_adapter_err
setSUPLVersion(uint32_t version)
{
return mLocApi->setSUPLVersion(version);
}
inline enum loc_api_adapter_err
setNMEATypes (uint32_t typesMask)
{
return mLocApi->setNMEATypes(typesMask);
}
inline enum loc_api_adapter_err
setLPPConfig(uint32_t profile)
{
return mLocApi->setLPPConfig(profile);
}
inline enum loc_api_adapter_err
setSensorControlConfig(int sensorUsage, int sensorProvider)
{
return mLocApi->setSensorControlConfig(sensorUsage, sensorProvider);
}
inline enum loc_api_adapter_err
setSensorProperties(bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk,
bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk,
bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk,
bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk,
bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk)
{
return mLocApi->setSensorProperties(gyroBiasVarianceRandomWalk_valid, gyroBiasVarianceRandomWalk,
accelBiasVarianceRandomWalk_valid, accelBiasVarianceRandomWalk,
angleBiasVarianceRandomWalk_valid, angleBiasVarianceRandomWalk,
rateBiasVarianceRandomWalk_valid, rateBiasVarianceRandomWalk,
velocityBiasVarianceRandomWalk_valid, velocityBiasVarianceRandomWalk);
}
inline virtual enum loc_api_adapter_err
setSensorPerfControlConfig(int controlMode, int accelSamplesPerBatch, int accelBatchesPerSec,
int gyroSamplesPerBatch, int gyroBatchesPerSec,
int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh,
int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, int algorithmConfig)
{
return mLocApi->setSensorPerfControlConfig(controlMode, accelSamplesPerBatch, accelBatchesPerSec,
gyroSamplesPerBatch, gyroBatchesPerSec,
accelSamplesPerBatchHigh, accelBatchesPerSecHigh,
gyroSamplesPerBatchHigh, gyroBatchesPerSecHigh,
algorithmConfig);
}
inline virtual enum loc_api_adapter_err
setAGLONASSProtocol(unsigned long aGlonassProtocol)
{
return mLocApi->setAGLONASSProtocol(aGlonassProtocol);
}
inline virtual enum loc_api_adapter_err
setLPPeProtocol(unsigned long lppeCP, unsigned long lppeUP)
{
return mLocApi->setLPPeProtocol(lppeCP, lppeUP);
}
inline virtual int initDataServiceClient()
{
return mLocApi->initDataServiceClient();
}
inline virtual int openAndStartDataCall()
{
return mLocApi->openAndStartDataCall();
}
inline virtual void stopDataCall()
{
mLocApi->stopDataCall();
}
inline virtual void closeDataCall()
{
mLocApi->closeDataCall();
}
inline enum loc_api_adapter_err
getZpp(GpsLocation &zppLoc, LocPosTechMask &tech_mask)
{
return mLocApi->getBestAvailableZppFix(zppLoc, tech_mask);
}
enum loc_api_adapter_err setTime(GpsUtcTime time,
int64_t timeReference,
int uncertainty);
enum loc_api_adapter_err setXtraVersionCheck(int check);
inline virtual void installAGpsCert(const DerEncodedCertificate* pData,
size_t length,
uint32_t slotBitMask)
{
mLocApi->installAGpsCert(pData, length, slotBitMask);
}
virtual void handleEngineDownEvent();
virtual void handleEngineUpEvent();
virtual void reportPosition(UlpLocation &location,
GpsLocationExtended &locationExtended,
void* locationExt,
enum loc_sess_status status,
LocPosTechMask loc_technology_mask);
virtual void reportSv(GnssSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt);
virtual void reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet);
virtual void reportSvPolynomial(GnssSvPolynomial &svPolynomial);
virtual void reportStatus(GpsStatusValue status);
virtual void reportNmea(const char* nmea, int length);
virtual bool reportXtraServer(const char* url1, const char* url2,
const char* url3, const int maxlength);
virtual bool requestXtraData();
virtual bool requestTime();
virtual bool requestATL(int connHandle, AGpsType agps_type);
virtual bool releaseATL(int connHandle);
virtual bool requestNiNotify(GpsNiNotification &notify, const void* data);
virtual bool requestSuplES(int connHandle);
virtual bool reportDataCallOpened();
virtual bool reportDataCallClosed();
virtual void reportGnssMeasurementData(GnssData &gnssMeasurementData);
inline const LocPosMode& getPositionMode() const
{return mFixCriteria;}
inline virtual bool isInSession()
{ return mNavigating; }
void setInSession(bool inSession);
// Permit/prohibit power voting
inline void setPowerVoteRight(bool powerVoteRight) {
mPowerVote = powerVoteRight ? (mPowerVote | POWER_VOTE_RIGHT) :
(mPowerVote & ~POWER_VOTE_RIGHT);
}
inline bool getPowerVoteRight() const {
return (mPowerVote & POWER_VOTE_RIGHT) != 0 ;
}
// Set the power voting up/down and do actual operation if permitted
inline void setPowerVote(bool powerOn) {
mPowerVote = powerOn ? (mPowerVote | POWER_VOTE_VALUE) :
(mPowerVote & ~POWER_VOTE_VALUE);
requestPowerVote();
mContext->modemPowerVote(powerOn);
}
inline bool getPowerVote() const {
return (mPowerVote & POWER_VOTE_VALUE) != 0 ;
}
// Do power voting according to last settings if permitted
void requestPowerVote();
/*Values for lock
1 = Do not lock any position sessions
2 = Lock MI position sessions
3 = Lock MT position sessions
4 = Lock all position sessions
*/
inline int setGpsLock(LOC_GPS_LOCK_MASK lock)
{
return mLocApi->setGpsLock(lock);
}
int setGpsLockMsg(LOC_GPS_LOCK_MASK lock);
/*
Returns
Current value of GPS lock on success
-1 on failure
*/
inline int getGpsLock()
{
return mLocApi->getGpsLock();
}
/*
Set Gnss Constellation Config
*/
bool gnssConstellationConfig();
};
#endif //LOC_API_ENG_ADAPTER_H

View File

@@ -0,0 +1,73 @@
/* Copyright (c) 2011,2015 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <hardware/gps.h>
#include <stdlib.h>
#include <string.h>
extern const GpsInterface* get_gps_interface();
const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
return get_gps_interface();
}
static int open_gps(const struct hw_module_t* module, char const* name,
struct hw_device_t** device)
{
struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));
if(dev == NULL)
return -1;
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->get_gps_interface = gps__get_gps_interface;
*device = (struct hw_device_t*)dev;
return 0;
}
static struct hw_module_methods_t gps_module_methods = {
.open = open_gps
};
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = 1,
.hal_api_version = 0,
.id = GPS_HARDWARE_MODULE_ID,
.name = "loc_api GPS Module",
.author = "Qualcomm USA, Inc.",
.methods = &gps_module_methods,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
/* Copyright (c) 2011,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_H__
#define __LOC_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <ctype.h>
#include <hardware/gps.h>
#include <gps_extended.h>
#define XTRA_DATA_MAX_SIZE 100000 /*bytes*/
typedef void (*loc_location_cb_ext) (UlpLocation* location, void* locExt);
typedef void (*loc_sv_status_cb_ext) (GpsSvStatus* sv_status, void* svExt);
typedef void* (*loc_ext_parser)(void* data);
typedef struct {
loc_location_cb_ext location_cb;
gps_status_callback status_cb;
loc_sv_status_cb_ext sv_status_cb;
gps_nmea_callback nmea_cb;
gps_set_capabilities set_capabilities_cb;
gps_acquire_wakelock acquire_wakelock_cb;
gps_release_wakelock release_wakelock_cb;
gps_create_thread create_thread_cb;
loc_ext_parser location_ext_parser;
loc_ext_parser sv_ext_parser;
gps_request_utc_time request_utc_time_cb;
gnss_set_system_info set_system_info_cb;
gnss_sv_status_callback gnss_sv_status_cb;
} LocCallbacks;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif //__LOC_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
/* Copyright (c) 2009-2014, 2016 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_H
#define LOC_ENG_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
// Uncomment to keep all LOG messages (LOGD, LOGI, LOGV, etc.)
#define MAX_NUM_ATL_CONNECTIONS 2
// Define boolean type to be used by libgps on loc api module
typedef unsigned char boolean;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#include <loc.h>
#include <loc_eng_xtra.h>
#include <loc_eng_ni.h>
#include <loc_eng_agps.h>
#include <loc_cfg.h>
#include <loc_log.h>
#include <loc_eng_agps.h>
#include <LocEngAdapter.h>
// The data connection minimal open time
#define DATA_OPEN_MIN_TIME 1 /* sec */
// The system sees GPS engine turns off after inactive for this period of time
#define GPS_AUTO_OFF_TIME 2 /* secs */
#define SUCCESS TRUE
#define FAILURE FALSE
#define INVALID_ATL_CONNECTION_HANDLE -1
#define gps_conf ContextBase::mGps_conf
#define sap_conf ContextBase::mSap_conf
enum loc_nmea_provider_e_type {
NMEA_PROVIDER_AP = 0, // Application Processor Provider of NMEA
NMEA_PROVIDER_MP // Modem Processor Provider of NMEA
};
enum loc_mute_session_e_type {
LOC_MUTE_SESS_NONE = 0,
LOC_MUTE_SESS_WAIT,
LOC_MUTE_SESS_IN_SESSION
};
// Module data
typedef struct loc_eng_data_s
{
LocEngAdapter *adapter;
loc_location_cb_ext location_cb;
gps_status_callback status_cb;
loc_sv_status_cb_ext sv_status_cb;
agps_status_extended agps_status_cb;
gps_nmea_callback nmea_cb;
loc_ni_notify_callback ni_notify_cb;
gps_set_capabilities set_capabilities_cb;
gps_acquire_wakelock acquire_wakelock_cb;
gps_release_wakelock release_wakelock_cb;
gps_request_utc_time request_utc_time_cb;
gnss_set_system_info set_system_info_cb;
gnss_sv_status_callback gnss_sv_status_cb;
gnss_measurement_callback gnss_measurement_cb;
boolean intermediateFix;
AGpsStatusValue agps_status;
loc_eng_xtra_data_s_type xtra_module_data;
loc_eng_ni_data_s_type loc_eng_ni_data;
// AGPS state machines
AgpsStateMachine* agnss_nif;
AgpsStateMachine* internet_nif;
//State machine for Data Services
AgpsStateMachine* ds_nif;
// GPS engine status
GpsStatusValue engine_status;
GpsStatusValue fix_session_status;
// Aiding data information to be deleted, aiding data can only be deleted when GPS engine is off
GpsAidingData aiding_data_for_deletion;
// For muting session broadcast
loc_mute_session_e_type mute_session_state;
// For nmea generation
boolean generateNmea;
uint32_t gps_used_mask;
uint32_t glo_used_mask;
float hdop;
float pdop;
float vdop;
// Address buffers, for addressing setting before init
int supl_host_set;
char supl_host_buf[101];
int supl_port_buf;
int c2k_host_set;
char c2k_host_buf[101];
int c2k_port_buf;
int mpc_host_set;
char mpc_host_buf[101];
int mpc_port_buf;
loc_ext_parser location_ext_parser;
loc_ext_parser sv_ext_parser;
} loc_eng_data_s_type;
//loc_eng functions
int loc_eng_init(loc_eng_data_s_type &loc_eng_data,
LocCallbacks* callbacks,
LOC_API_ADAPTER_EVENT_MASK_T event,
ContextBase* context);
int loc_eng_start(loc_eng_data_s_type &loc_eng_data);
int loc_eng_stop(loc_eng_data_s_type &loc_eng_data);
void loc_eng_cleanup(loc_eng_data_s_type &loc_eng_data);
int loc_eng_inject_time(loc_eng_data_s_type &loc_eng_data,
GpsUtcTime time, int64_t timeReference,
int uncertainty);
int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data,
double latitude, double longitude,
float accuracy);
void loc_eng_delete_aiding_data(loc_eng_data_s_type &loc_eng_data,
GpsAidingData f);
int loc_eng_set_position_mode(loc_eng_data_s_type &loc_eng_data,
LocPosMode &params);
const void* loc_eng_get_extension(loc_eng_data_s_type &loc_eng_data,
const char* name);
int loc_eng_set_server_proxy(loc_eng_data_s_type &loc_eng_data,
LocServerType type, const char *hostname, int port);
void loc_eng_mute_one_session(loc_eng_data_s_type &loc_eng_data);
int loc_eng_read_config(void);
//loc_eng_agps functions
void loc_eng_agps_init(loc_eng_data_s_type &loc_eng_data,
AGpsExtCallbacks* callbacks);
int loc_eng_agps_open(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType,
const char* apn, AGpsBearerType bearerType);
int loc_eng_agps_closed(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType);
int loc_eng_agps_open_failed(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType);
void loc_eng_agps_ril_update_network_availability(loc_eng_data_s_type &loc_eng_data,
int avaiable, const char* apn);
int loc_eng_agps_install_certificates(loc_eng_data_s_type &loc_eng_data,
const DerEncodedCertificate* certificates,
size_t length);
//loc_eng_xtra functions
int loc_eng_xtra_init (loc_eng_data_s_type &loc_eng_data,
GpsXtraExtCallbacks* callbacks);
int loc_eng_xtra_inject_data(loc_eng_data_s_type &loc_eng_data,
char* data, int length);
int loc_eng_xtra_request_server(loc_eng_data_s_type &loc_eng_data);
void loc_eng_xtra_version_check(loc_eng_data_s_type &loc_eng_data, int check);
//loc_eng_ni functions
extern void loc_eng_ni_init(loc_eng_data_s_type &loc_eng_data,
GpsNiExtCallbacks *callbacks);
extern void loc_eng_ni_respond(loc_eng_data_s_type &loc_eng_data,
int notif_id, GpsUserResponseType user_response);
extern void loc_eng_ni_request_handler(loc_eng_data_s_type &loc_eng_data,
const GpsNiNotification *notif,
const void* passThrough);
extern void loc_eng_ni_reset_on_engine_restart(loc_eng_data_s_type &loc_eng_data);
void loc_eng_configuration_update (loc_eng_data_s_type &loc_eng_data,
const char* config_data, int32_t length);
int loc_eng_gps_measurement_init(loc_eng_data_s_type &loc_eng_data,
GpsMeasurementCallbacks* callbacks);
void loc_eng_gps_measurement_close(loc_eng_data_s_type &loc_eng_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif // LOC_ENG_H

View File

@@ -0,0 +1,969 @@
/* Copyright (c) 2011-2014, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_NDDEBUG 0
#define LOG_TAG "LocSvc_eng"
#include <loc_eng_agps.h>
#include <loc_eng_log.h>
#include <platform_lib_includes.h>
#include <loc_eng_dmn_conn_handler.h>
#include <loc_eng_dmn_conn.h>
#include <sys/time.h>
//======================================================================
// C callbacks
//======================================================================
// This is given to linked_list_add as the dealloc callback
// data -- an instance of Subscriber
static void deleteObj(void* data)
{
delete (Subscriber*)data;
}
// This is given to linked_list_search() as the comparison callback
// when the state manchine needs to process for particular subscriber
// fromCaller -- caller provides this obj
// fromList -- linked_list_search() function take this one from list
static bool hasSubscriber(void* fromCaller, void* fromList)
{
Notification* notification = (Notification*)fromCaller;
Subscriber* s1 = (Subscriber*)fromList;
return s1->forMe(*notification);
}
// This is gvien to linked_list_search() to notify subscriber objs
// when the state machine needs to inform all subscribers of resource
// status changes, e.g. when resource is GRANTED.
// fromCaller -- caller provides this ptr to a Notification obj.
// fromList -- linked_list_search() function take this one from list
static bool notifySubscriber(void* fromCaller, void* fromList)
{
Notification* notification = (Notification*)fromCaller;
Subscriber* s1 = (Subscriber*)fromList;
// we notify every subscriber indiscriminatively
// each subscriber decides if this notification is interesting.
return s1->notifyRsrcStatus(*notification) &&
// if we do not want to delete the subscriber from the
// the list, we must set this to false so this function
// returns false
notification->postNotifyDelete;
}
//======================================================================
// Notification
//======================================================================
const int Notification::BROADCAST_ALL = 0x80000000;
const int Notification::BROADCAST_ACTIVE = 0x80000001;
const int Notification::BROADCAST_INACTIVE = 0x80000002;
const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
//======================================================================
// Subscriber: BITSubscriber / ATLSubscriber / WIFISubscriber
//======================================================================
bool Subscriber::forMe(Notification &notification)
{
if (NULL != notification.rcver) {
return equals(notification.rcver);
} else {
return Notification::BROADCAST_ALL == notification.groupID ||
(Notification::BROADCAST_ACTIVE == notification.groupID &&
!isInactive()) ||
(Notification::BROADCAST_INACTIVE == notification.groupID &&
isInactive());
}
}
bool BITSubscriber::equals(const Subscriber *s) const
{
BITSubscriber* bitS = (BITSubscriber*)s;
return (ID == bitS->ID &&
(INADDR_NONE != (unsigned int)ID ||
0 == strncmp(mIPv6Addr, bitS->mIPv6Addr, sizeof(mIPv6Addr))));
}
bool BITSubscriber::notifyRsrcStatus(Notification &notification)
{
bool notify = forMe(notification);
if (notify) {
switch(notification.rsrcStatus)
{
case RSRC_UNSUBSCRIBE:
case RSRC_RELEASED:
loc_eng_dmn_conn_loc_api_server_data_conn(
LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
GPSONE_LOC_API_IF_RELEASE_SUCCESS);
break;
case RSRC_DENIED:
loc_eng_dmn_conn_loc_api_server_data_conn(
LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
GPSONE_LOC_API_IF_FAILURE);
break;
case RSRC_GRANTED:
loc_eng_dmn_conn_loc_api_server_data_conn(
LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
GPSONE_LOC_API_IF_REQUEST_SUCCESS);
break;
default:
notify = false;
}
}
return notify;
}
bool ATLSubscriber::notifyRsrcStatus(Notification &notification)
{
bool notify = forMe(notification);
if (notify) {
switch(notification.rsrcStatus)
{
case RSRC_UNSUBSCRIBE:
case RSRC_RELEASED:
((LocEngAdapter*)mLocAdapter)->atlCloseStatus(ID, 1);
break;
case RSRC_DENIED:
{
AGpsExtType type = mBackwardCompatibleMode ?
AGPS_TYPE_INVALID : mStateMachine->getType();
((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 0,
(char*)mStateMachine->getAPN(),
mStateMachine->getBearer(),
type);
}
break;
case RSRC_GRANTED:
{
AGpsExtType type = mBackwardCompatibleMode ?
AGPS_TYPE_INVALID : mStateMachine->getType();
((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 1,
(char*)mStateMachine->getAPN(),
mStateMachine->getBearer(),
type);
}
break;
default:
notify = false;
}
}
return notify;
}
bool WIFISubscriber::notifyRsrcStatus(Notification &notification)
{
bool notify = forMe(notification);
if (notify) {
switch(notification.rsrcStatus)
{
case RSRC_UNSUBSCRIBE:
break;
case RSRC_RELEASED:
loc_eng_dmn_conn_loc_api_server_data_conn(
senderId,
GPSONE_LOC_API_IF_RELEASE_SUCCESS);
break;
case RSRC_DENIED:
loc_eng_dmn_conn_loc_api_server_data_conn(
senderId,
GPSONE_LOC_API_IF_FAILURE);
break;
case RSRC_GRANTED:
loc_eng_dmn_conn_loc_api_server_data_conn(
senderId,
GPSONE_LOC_API_IF_REQUEST_SUCCESS);
break;
default:
notify = false;
}
}
return notify;
}
bool DSSubscriber::notifyRsrcStatus(Notification &notification)
{
bool notify = forMe(notification);
LOC_LOGD("DSSubscriber::notifyRsrcStatus. notify:%d \n",(int)(notify));
if(notify) {
switch(notification.rsrcStatus) {
case RSRC_UNSUBSCRIBE:
case RSRC_RELEASED:
case RSRC_DENIED:
case RSRC_GRANTED:
((DSStateMachine *)mStateMachine)->informStatus(notification.rsrcStatus, ID);
break;
default:
notify = false;
}
}
return notify;
}
void DSSubscriber :: setInactive()
{
mIsInactive = true;
((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID);
}
//======================================================================
// AgpsState: AgpsReleasedState / AgpsPendingState / AgpsAcquiredState
//======================================================================
// AgpsReleasedState
class AgpsReleasedState : public AgpsState
{
friend class AgpsStateMachine;
inline AgpsReleasedState(AgpsStateMachine* stateMachine) :
AgpsState(stateMachine)
{ mReleasedState = this; }
inline ~AgpsReleasedState() {}
public:
virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
inline virtual char* whoami() {return (char*)"AgpsReleasedState";}
};
AgpsState* AgpsReleasedState::onRsrcEvent(AgpsRsrcStatus event, void* data)
{
LOC_LOGD("AgpsReleasedState::onRsrcEvent; event:%d\n", (int)event);
if (mStateMachine->hasSubscribers()) {
LOC_LOGE("Error: %s subscriber list not empty!!!", whoami());
// I don't know how to recover from it. I am adding this rather
// for debugging purpose.
}
AgpsState* nextState = this;
switch (event)
{
case RSRC_SUBSCRIBE:
{
// no notification until we get RSRC_GRANTED
// but we need to add subscriber to the list
mStateMachine->addSubscriber((Subscriber*)data);
// request from connecivity service for NIF
//The if condition is added so that if the data call setup fails
//for DS State Machine, we want to retry in released state.
//for AGps State Machine, sendRsrcRequest() will always return success
if(!mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN)) {
// move the state to PENDING
nextState = mPendingState;
}
}
break;
case RSRC_UNSUBSCRIBE:
{
// the list should really be empty, nothing to remove.
// but we might as well just tell the client it is
// unsubscribed. False tolerance, right?
Subscriber* subscriber = (Subscriber*) data;
Notification notification(subscriber, event, false);
subscriber->notifyRsrcStatus(notification);
}
// break;
case RSRC_GRANTED:
case RSRC_RELEASED:
case RSRC_DENIED:
default:
LOC_LOGW("%s: unrecognized event %d", whoami(), event);
// no state change.
break;
}
LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
whoami(), nextState->whoami(), event);
return nextState;
}
// AgpsPendingState
class AgpsPendingState : public AgpsState
{
friend class AgpsStateMachine;
inline AgpsPendingState(AgpsStateMachine* stateMachine) :
AgpsState(stateMachine)
{ mPendingState = this; }
inline ~AgpsPendingState() {}
public:
virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
inline virtual char* whoami() {return (char*)"AgpsPendingState";}
};
AgpsState* AgpsPendingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
{
AgpsState* nextState = this;;
LOC_LOGD("AgpsPendingState::onRsrcEvent; event:%d\n", (int)event);
switch (event)
{
case RSRC_SUBSCRIBE:
{
// already requested for NIF resource,
// do nothing until we get RSRC_GRANTED indication
// but we need to add subscriber to the list
mStateMachine->addSubscriber((Subscriber*)data);
// no state change.
}
break;
case RSRC_UNSUBSCRIBE:
{
Subscriber* subscriber = (Subscriber*) data;
if (subscriber->waitForCloseComplete()) {
subscriber->setInactive();
} else {
// auto notify this subscriber of the unsubscribe
Notification notification(subscriber, event, true);
mStateMachine->notifySubscribers(notification);
}
// now check if there is any subscribers left
if (!mStateMachine->hasSubscribers()) {
// no more subscribers, move to RELEASED state
nextState = mReleasedState;
// tell connecivity service we can release NIF
mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
} else if (!mStateMachine->hasActiveSubscribers()) {
// only inactive subscribers, move to RELEASING state
nextState = mReleasingState;
// tell connecivity service we can release NIF
mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
}
}
break;
case RSRC_GRANTED:
{
nextState = mAcquiredState;
Notification notification(Notification::BROADCAST_ACTIVE, event, false);
// notify all subscribers NIF resource GRANTED
// by setting false, we keep subscribers on the linked list
mStateMachine->notifySubscribers(notification);
}
break;
case RSRC_RELEASED:
// no state change.
// we are expecting either GRANTED or DENIED. Handling RELEASED
// may like break our state machine in race conditions.
break;
case RSRC_DENIED:
{
nextState = mReleasedState;
Notification notification(Notification::BROADCAST_ALL, event, true);
// notify all subscribers NIF resource RELEASED or DENIED
// by setting true, we remove subscribers from the linked list
mStateMachine->notifySubscribers(notification);
}
break;
default:
LOC_LOGE("%s: unrecognized event %d", whoami(), event);
// no state change.
}
LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
whoami(), nextState->whoami(), event);
return nextState;
}
class AgpsAcquiredState : public AgpsState
{
friend class AgpsStateMachine;
inline AgpsAcquiredState(AgpsStateMachine* stateMachine) :
AgpsState(stateMachine)
{ mAcquiredState = this; }
inline ~AgpsAcquiredState() {}
public:
virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
inline virtual char* whoami() { return (char*)"AgpsAcquiredState"; }
};
AgpsState* AgpsAcquiredState::onRsrcEvent(AgpsRsrcStatus event, void* data)
{
AgpsState* nextState = this;
LOC_LOGD("AgpsAcquiredState::onRsrcEvent; event:%d\n", (int)event);
switch (event)
{
case RSRC_SUBSCRIBE:
{
// we already have the NIF resource, simply notify subscriber
Subscriber* subscriber = (Subscriber*) data;
// we have rsrc in hand, so grant it right away
Notification notification(subscriber, RSRC_GRANTED, false);
subscriber->notifyRsrcStatus(notification);
// add subscriber to the list
mStateMachine->addSubscriber(subscriber);
// no state change.
}
break;
case RSRC_UNSUBSCRIBE:
{
Subscriber* subscriber = (Subscriber*) data;
if (subscriber->waitForCloseComplete()) {
subscriber->setInactive();
} else {
// auto notify this subscriber of the unsubscribe
Notification notification(subscriber, event, true);
mStateMachine->notifySubscribers(notification);
}
// now check if there is any subscribers left
if (!mStateMachine->hasSubscribers()) {
// no more subscribers, move to RELEASED state
nextState = mReleasedState;
// tell connecivity service we can release NIF
mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
} else if (!mStateMachine->hasActiveSubscribers()) {
// only inactive subscribers, move to RELEASING state
nextState = mReleasingState;
// tell connecivity service we can release NIF
mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
}
}
break;
case RSRC_GRANTED:
LOC_LOGW("%s: %d, RSRC_GRANTED already received", whoami(), event);
// no state change.
break;
case RSRC_RELEASED:
{
LOC_LOGW("%s: %d, a force rsrc release", whoami(), event);
nextState = mReleasedState;
Notification notification(Notification::BROADCAST_ALL, event, true);
// by setting true, we remove subscribers from the linked list
mStateMachine->notifySubscribers(notification);
}
break;
case RSRC_DENIED:
// no state change.
// we are expecting RELEASED. Handling DENIED
// may like break our state machine in race conditions.
break;
default:
LOC_LOGE("%s: unrecognized event %d", whoami(), event);
// no state change.
}
LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
whoami(), nextState->whoami(), event);
return nextState;
}
// AgpsPendingState
class AgpsReleasingState : public AgpsState
{
friend class AgpsStateMachine;
inline AgpsReleasingState(AgpsStateMachine* stateMachine) :
AgpsState(stateMachine)
{ mReleasingState = this; }
inline ~AgpsReleasingState() {}
public:
virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
inline virtual char* whoami() {return (char*)"AgpsReleasingState";}
};
AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
{
AgpsState* nextState = this;;
LOC_LOGD("AgpsReleasingState::onRsrcEvent; event:%d\n", (int)event);
switch (event)
{
case RSRC_SUBSCRIBE:
{
// already requested for NIF resource,
// do nothing until we get RSRC_GRANTED indication
// but we need to add subscriber to the list
mStateMachine->addSubscriber((Subscriber*)data);
// no state change.
}
break;
case RSRC_UNSUBSCRIBE:
{
Subscriber* subscriber = (Subscriber*) data;
if (subscriber->waitForCloseComplete()) {
subscriber->setInactive();
} else {
// auto notify this subscriber of the unsubscribe
Notification notification(subscriber, event, true);
mStateMachine->notifySubscribers(notification);
}
// now check if there is any subscribers left
if (!mStateMachine->hasSubscribers()) {
// no more subscribers, move to RELEASED state
nextState = mReleasedState;
}
}
break;
case RSRC_DENIED:
// A race condition subscriber unsubscribes before AFW denies resource.
case RSRC_RELEASED:
{
nextState = mAcquiredState;
Notification notification(Notification::BROADCAST_INACTIVE, event, true);
// notify all subscribers that are active NIF resource RELEASE
// by setting false, we keep subscribers on the linked list
mStateMachine->notifySubscribers(notification);
if (mStateMachine->hasActiveSubscribers()) {
nextState = mPendingState;
// request from connecivity service for NIF
mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN);
} else {
nextState = mReleasedState;
}
}
break;
case RSRC_GRANTED:
default:
LOC_LOGE("%s: unrecognized event %d", whoami(), event);
// no state change.
}
LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
whoami(), nextState->whoami(), event);
return nextState;
}
//======================================================================
//Servicer
//======================================================================
Servicer* Servicer :: getServicer(servicerType type, void *cb_func)
{
LOC_LOGD(" Enter getServicer type:%d\n", (int)type);
switch(type) {
case servicerTypeNoCbParam:
return (new Servicer(cb_func));
case servicerTypeExt:
return (new ExtServicer(cb_func));
case servicerTypeAgps:
return (new AGpsServicer(cb_func));
default:
return NULL;
}
}
int Servicer :: requestRsrc(void *cb_data)
{
callback();
return 0;
}
int ExtServicer :: requestRsrc(void *cb_data)
{
int ret=-1;
LOC_LOGD("Enter ExtServicer :: requestRsrc\n");
ret = callbackExt(cb_data);
LOC_LOGD("Exit ExtServicer :: requestRsrc\n");
return(ret);
}
int AGpsServicer :: requestRsrc(void *cb_data)
{
callbackAGps((AGpsStatus *)cb_data);
return 0;
}
//======================================================================
// AgpsStateMachine
//======================================================================
AgpsStateMachine::AgpsStateMachine(servicerType servType,
void *cb_func,
AGpsExtType type,
bool enforceSingleSubscriber) :
mStatePtr(new AgpsReleasedState(this)),mType(type),
mAPN(NULL),
mAPNLen(0),
mBearer(AGPS_APN_BEARER_INVALID),
mEnforceSingleSubscriber(enforceSingleSubscriber),
mServicer(Servicer :: getServicer(servType, (void *)cb_func))
{
linked_list_init(&mSubscribers);
// setting up mReleasedState
mStatePtr->mPendingState = new AgpsPendingState(this);
mStatePtr->mAcquiredState = new AgpsAcquiredState(this);
mStatePtr->mReleasingState = new AgpsReleasingState(this);
// setting up mAcquiredState
mStatePtr->mAcquiredState->mReleasedState = mStatePtr;
mStatePtr->mAcquiredState->mPendingState = mStatePtr->mPendingState;
mStatePtr->mAcquiredState->mReleasingState = mStatePtr->mReleasingState;
// setting up mPendingState
mStatePtr->mPendingState->mAcquiredState = mStatePtr->mAcquiredState;
mStatePtr->mPendingState->mReleasedState = mStatePtr;
mStatePtr->mPendingState->mReleasingState = mStatePtr->mReleasingState;
// setting up mReleasingState
mStatePtr->mReleasingState->mReleasedState = mStatePtr;
mStatePtr->mReleasingState->mPendingState = mStatePtr->mPendingState;
mStatePtr->mReleasingState->mAcquiredState = mStatePtr->mAcquiredState;
}
AgpsStateMachine::~AgpsStateMachine()
{
dropAllSubscribers();
// free the 3 states. We must read out all 3 pointers first.
// Otherwise we run the risk of getting pointers from already
// freed memory.
AgpsState* acquiredState = mStatePtr->mAcquiredState;
AgpsState* releasedState = mStatePtr->mReleasedState;
AgpsState* pendindState = mStatePtr->mPendingState;
AgpsState* releasingState = mStatePtr->mReleasingState;
delete acquiredState;
delete releasedState;
delete pendindState;
delete releasingState;
delete mServicer;
linked_list_destroy(&mSubscribers);
if (NULL != mAPN) {
delete[] mAPN;
mAPN = NULL;
}
}
void AgpsStateMachine::setAPN(const char* apn, unsigned int len)
{
if (NULL != mAPN) {
delete mAPN;
}
if (NULL != apn) {
mAPN = new char[len+1];
memcpy(mAPN, apn, len);
mAPN[len] = NULL;
mAPNLen = len;
} else {
mAPN = NULL;
mAPNLen = 0;
}
}
void AgpsStateMachine::onRsrcEvent(AgpsRsrcStatus event)
{
switch (event)
{
case RSRC_GRANTED:
case RSRC_RELEASED:
case RSRC_DENIED:
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
break;
default:
LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
break;
}
}
void AgpsStateMachine::notifySubscribers(Notification& notification) const
{
if (notification.postNotifyDelete) {
// just any non NULL value to get started
Subscriber* s = (Subscriber*)~0;
while (NULL != s) {
s = NULL;
// if the last param sets to true, _search will delete
// the node from the list for us. But the problem is
// once that is done, _search returns, leaving the
// rest of the list unprocessed. So we need a loop.
linked_list_search(mSubscribers, (void**)&s, notifySubscriber,
(void*)&notification, true);
delete s;
}
} else {
// no loop needed if it the last param sets to false, which
// mean nothing gets deleted from the list.
linked_list_search(mSubscribers, NULL, notifySubscriber,
(void*)&notification, false);
}
}
void AgpsStateMachine::addSubscriber(Subscriber* subscriber) const
{
Subscriber* s = NULL;
Notification notification((const Subscriber*)subscriber);
linked_list_search(mSubscribers, (void**)&s,
hasSubscriber, (void*)&notification, false);
if (NULL == s) {
linked_list_add(mSubscribers, subscriber->clone(), deleteObj);
}
}
int AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const
{
Subscriber* s = NULL;
Notification notification(Notification::BROADCAST_ACTIVE);
linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
(void*)&notification, false);
if ((NULL == s) == (GPS_RELEASE_AGPS_DATA_CONN == action)) {
AGpsExtStatus nifRequest;
nifRequest.size = sizeof(nifRequest);
nifRequest.type = mType;
nifRequest.status = action;
if (s == NULL) {
nifRequest.ipv4_addr = INADDR_NONE;
memset(&nifRequest.addr, 0, sizeof(nifRequest.addr));
nifRequest.ssid[0] = '\0';
nifRequest.password[0] = '\0';
} else {
s->setIPAddresses(nifRequest.addr);
s->setWifiInfo(nifRequest.ssid, nifRequest.password);
}
CALLBACK_LOG_CALLFLOW("agps_cb", %s, loc_get_agps_status_name(action));
mServicer->requestRsrc((void *)&nifRequest);
}
return 0;
}
void AgpsStateMachine::subscribeRsrc(Subscriber *subscriber)
{
if (mEnforceSingleSubscriber && hasSubscribers()) {
Notification notification(Notification::BROADCAST_ALL, RSRC_DENIED, true);
notifySubscriber(&notification, subscriber);
} else {
mStatePtr = mStatePtr->onRsrcEvent(RSRC_SUBSCRIBE, (void*)subscriber);
}
}
bool AgpsStateMachine::unsubscribeRsrc(Subscriber *subscriber)
{
Subscriber* s = NULL;
Notification notification((const Subscriber*)subscriber);
linked_list_search(mSubscribers, (void**)&s,
hasSubscriber, (void*)&notification, false);
if (NULL != s) {
mStatePtr = mStatePtr->onRsrcEvent(RSRC_UNSUBSCRIBE, (void*)s);
return true;
}
return false;
}
bool AgpsStateMachine::hasActiveSubscribers() const
{
Subscriber* s = NULL;
Notification notification(Notification::BROADCAST_ACTIVE);
linked_list_search(mSubscribers, (void**)&s,
hasSubscriber, (void*)&notification, false);
return NULL != s;
}
//======================================================================
// DSStateMachine
//======================================================================
void delay_callback(void *callbackData, int result)
{
if(callbackData) {
DSStateMachine *DSSMInstance = (DSStateMachine *)callbackData;
DSSMInstance->retryCallback();
}
else {
LOC_LOGE(" NULL argument received. Failing.\n");
goto err;
}
err:
return;
}
DSStateMachine :: DSStateMachine(servicerType type, void *cb_func,
LocEngAdapter* adapterHandle):
AgpsStateMachine(type, cb_func, AGPS_TYPE_INVALID,false),
mLocAdapter(adapterHandle)
{
LOC_LOGD("%s:%d]: New DSStateMachine\n", __func__, __LINE__);
mRetries = 0;
}
void DSStateMachine :: retryCallback(void)
{
DSSubscriber *subscriber = NULL;
Notification notification(Notification::BROADCAST_ACTIVE);
linked_list_search(mSubscribers, (void**)&subscriber, hasSubscriber,
(void*)&notification, false);
if(subscriber)
mLocAdapter->requestSuplES(subscriber->ID);
else
LOC_LOGE("DSStateMachine :: retryCallback: No subscriber found." \
"Cannot retry data call\n");
return;
}
int DSStateMachine :: sendRsrcRequest(AGpsStatusValue action) const
{
DSSubscriber* s = NULL;
dsCbData cbData;
int ret=-1;
int connHandle=-1;
LOC_LOGD("Enter DSStateMachine :: sendRsrcRequest\n");
Notification notification(Notification::BROADCAST_ACTIVE);
linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
(void*)&notification, false);
if(s) {
connHandle = s->ID;
LOC_LOGD("DSStateMachine :: sendRsrcRequest - subscriber found\n");
}
else
LOC_LOGD("DSStateMachine :: sendRsrcRequest - No subscriber found\n");
cbData.action = action;
cbData.mAdapter = mLocAdapter;
ret = mServicer->requestRsrc((void *)&cbData);
//Only the request to start data call returns a success/failure
//The request to stop data call will always succeed
//Hence, the below block will only be executed when the
//request to start the data call fails
switch(ret) {
case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
LOC_LOGD("DSStateMachine :: sendRsrcRequest - Failure returned: %d\n",ret);
((DSStateMachine *)this)->incRetries();
if(mRetries > MAX_START_DATA_CALL_RETRIES) {
LOC_LOGE(" Failed to start Data call. Fallback to normal ATL SUPL\n");
informStatus(RSRC_DENIED, connHandle);
}
else {
if(loc_timer_start(DATA_CALL_RETRY_DELAY_MSEC, delay_callback, (void *)this)) {
LOC_LOGE("Error: Could not start delay thread\n");
ret = -1;
goto err;
}
}
break;
case LOC_API_ADAPTER_ERR_UNSUPPORTED:
LOC_LOGE("No profile found for emergency call. Fallback to normal SUPL ATL\n");
informStatus(RSRC_DENIED, connHandle);
break;
case LOC_API_ADAPTER_ERR_SUCCESS:
LOC_LOGD("%s:%d]: Request to start data call sent\n", __func__, __LINE__);
break;
case -1:
//One of the ways this case can be encountered is if the callback function
//receives a null argument, it just exits with -1 error
LOC_LOGE("Error: Something went wrong somewhere. Falling back to normal SUPL ATL\n");
informStatus(RSRC_DENIED, connHandle);
break;
default:
LOC_LOGE("%s:%d]: Unrecognized return value\n", __func__, __LINE__);
}
err:
LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret);
return ret;
}
void DSStateMachine :: onRsrcEvent(AgpsRsrcStatus event)
{
void* currState = (void *)mStatePtr;
LOC_LOGD("Enter DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
switch (event)
{
case RSRC_GRANTED:
LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_GRANTED\n");
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
break;
case RSRC_RELEASED:
LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_RELEASED\n");
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
//To handle the case where we get a RSRC_RELEASED in
//pending state, we translate that to a RSRC_DENIED state
//since the callback from DSI is either RSRC_GRANTED or RSRC_RELEASED
//for when the call is connected or disconnected respectively.
if((void *)mStatePtr != currState)
break;
else {
event = RSRC_DENIED;
LOC_LOGE(" Switching event to RSRC_DENIED\n");
}
case RSRC_DENIED:
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
break;
default:
LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
break;
}
LOC_LOGD("Exit DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
}
void DSStateMachine :: informStatus(AgpsRsrcStatus status, int ID) const
{
LOC_LOGD("DSStateMachine :: informStatus. Status=%d\n",(int)status);
switch(status) {
case RSRC_UNSUBSCRIBE:
mLocAdapter->atlCloseStatus(ID, 1);
break;
case RSRC_RELEASED:
mLocAdapter->closeDataCall();
break;
case RSRC_DENIED:
((DSStateMachine *)this)->mRetries = 0;
mLocAdapter->requestATL(ID, AGPS_TYPE_SUPL);
break;
case RSRC_GRANTED:
mLocAdapter->atlOpenStatus(ID, 1,
NULL,
AGPS_APN_BEARER_INVALID,
AGPS_TYPE_INVALID);
break;
default:
LOC_LOGW("DSStateMachine :: informStatus - unknown status");
}
return;
}

View File

@@ -0,0 +1,435 @@
/* Copyright (c) 2011-2014, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_ENG_AGPS_H__
#define __LOC_ENG_AGPS_H__
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include <arpa/inet.h>
#include <hardware/gps.h>
#include <gps_extended.h>
#include <loc_core_log.h>
#include <linked_list.h>
#include <loc_timer.h>
#include <LocEngAdapter.h>
#include <platform_lib_includes.h>
#if defined(USE_GLIB) && !defined(OFF_TARGET)
#include <glib.h>
#endif /* USE_GLIB */
// forward declaration
class AgpsStateMachine;
struct Subscriber;
// NIF resource events
typedef enum {
RSRC_SUBSCRIBE,
RSRC_UNSUBSCRIBE,
RSRC_GRANTED,
RSRC_RELEASED,
RSRC_DENIED,
RSRC_STATUS_MAX
} AgpsRsrcStatus;
typedef enum {
servicerTypeNoCbParam,
servicerTypeAgps,
servicerTypeExt
}servicerType;
//DS Callback struct
typedef struct {
LocEngAdapter *mAdapter;
AGpsStatusValue action;
}dsCbData;
// information bundle for subscribers
struct Notification {
// goes to every subscriber
static const int BROADCAST_ALL;
// goes to every ACTIVE subscriber
static const int BROADCAST_ACTIVE;
// goes to every INACTIVE subscriber
static const int BROADCAST_INACTIVE;
// go to a specific subscriber
const Subscriber* rcver;
// broadcast
const int groupID;
// the new resource status event
const AgpsRsrcStatus rsrcStatus;
// should the subscriber be deleted after the notification
const bool postNotifyDelete;
// convenient constructor
inline Notification(const int broadcast,
const AgpsRsrcStatus status,
const bool deleteAfterwards) :
rcver(NULL), groupID(broadcast), rsrcStatus(status),
postNotifyDelete(deleteAfterwards) {}
// convenient constructor
inline Notification(const Subscriber* subscriber,
const AgpsRsrcStatus status,
const bool deleteAfterwards) :
rcver(subscriber), groupID(-1), rsrcStatus(status),
postNotifyDelete(deleteAfterwards) {}
// convenient constructor
inline Notification(const int broadcast) :
rcver(NULL), groupID(broadcast), rsrcStatus(RSRC_STATUS_MAX),
postNotifyDelete(false) {}
// convenient constructor
inline Notification(const Subscriber* subscriber) :
rcver(subscriber), groupID(-1), rsrcStatus(RSRC_STATUS_MAX),
postNotifyDelete(false) {}
};
class AgpsState {
// allows AgpsStateMachine to access private data
// no class members are public. We don't want
// anyone but state machine to use state.
friend class AgpsStateMachine;
friend class DSStateMachine;
// state transitions are done here.
// Each state implements its own transitions (of course).
inline virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data) = 0;
protected:
// handle back to state machine
const AgpsStateMachine* mStateMachine;
// each state has pointers to all 3 states
// one of which is to itself.
AgpsState* mReleasedState;
AgpsState* mAcquiredState;
AgpsState* mPendingState;
AgpsState* mReleasingState;
inline AgpsState(const AgpsStateMachine *stateMachine) :
mStateMachine(stateMachine),
mReleasedState(NULL),
mAcquiredState(NULL),
mPendingState(NULL),
mReleasingState(NULL) {}
virtual ~AgpsState() {}
public:
// for logging purpose
inline virtual char* whoami() = 0;
};
class Servicer {
void (*callback)(void);
public:
static Servicer* getServicer(servicerType type, void *cb_func);
virtual int requestRsrc(void *cb_data);
Servicer() {}
Servicer(void *cb_func)
{ callback = (void(*)(void))(cb_func); }
virtual ~Servicer(){}
inline virtual char *whoami() {return (char*)"Servicer";}
};
class ExtServicer : public Servicer {
int (*callbackExt)(void *cb_data);
public:
int requestRsrc(void *cb_data);
ExtServicer() {}
ExtServicer(void *cb_func)
{ callbackExt = (int(*)(void *))(cb_func); }
virtual ~ExtServicer(){}
inline virtual char *whoami() {return (char*)"ExtServicer";}
};
class AGpsServicer : public Servicer {
void (*callbackAGps)(AGpsStatus* status);
public:
int requestRsrc(void *cb_data);
AGpsServicer() {}
AGpsServicer(void *cb_func)
{ callbackAGps = (void(*)(AGpsStatus *))(cb_func); }
virtual ~AGpsServicer(){}
inline virtual char *whoami() {return (char*)"AGpsServicer";}
};
class AgpsStateMachine {
protected:
// a linked list of subscribers.
void* mSubscribers;
//handle to whoever provides the service
Servicer *mServicer;
// allows AgpsState to access private data
// each state is really internal data to the
// state machine, so it should be able to
// access anything within the state machine.
friend class AgpsState;
// pointer to the current state.
AgpsState* mStatePtr;
private:
// NIF type: AGNSS or INTERNET.
const AGpsExtType mType;
// apn to the NIF. Each state machine tracks
// resource state of a particular NIF. For each
// NIF, there is also an active APN.
char* mAPN;
// for convenience, we don't do strlen each time.
unsigned int mAPNLen;
// bear
AGpsBearerType mBearer;
// ipv4 address for routing
bool mEnforceSingleSubscriber;
public:
AgpsStateMachine(servicerType servType, void *cb_func,
AGpsExtType type, bool enforceSingleSubscriber);
virtual ~AgpsStateMachine();
// self explanatory methods below
void setAPN(const char* apn, unsigned int len);
inline const char* getAPN() const { return (const char*)mAPN; }
inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; }
inline AGpsBearerType getBearer() const { return mBearer; }
inline AGpsExtType getType() const { return (AGpsExtType)mType; }
// someone, a ATL client or BIT, is asking for NIF
void subscribeRsrc(Subscriber *subscriber);
// someone, a ATL client or BIT, is done with NIF
bool unsubscribeRsrc(Subscriber *subscriber);
// add a subscriber in the linked list, if not already there.
void addSubscriber(Subscriber* subscriber) const;
virtual void onRsrcEvent(AgpsRsrcStatus event);
// put the data together and send the FW
virtual int sendRsrcRequest(AGpsStatusValue action) const;
//if list is empty, linked_list_empty returns 1
//else if list is not empty, returns 0
//so hasSubscribers() returns 1 if list is not empty
//and returns 0 if list is empty
inline bool hasSubscribers() const
{ return !linked_list_empty(mSubscribers); }
bool hasActiveSubscribers() const;
inline void dropAllSubscribers() const
{ linked_list_flush(mSubscribers); }
// private. Only a state gets to call this.
void notifySubscribers(Notification& notification) const;
};
class DSStateMachine : public AgpsStateMachine {
static const unsigned char MAX_START_DATA_CALL_RETRIES;
static const unsigned int DATA_CALL_RETRY_DELAY_MSEC;
LocEngAdapter* mLocAdapter;
unsigned char mRetries;
public:
DSStateMachine(servicerType type,
void *cb_func,
LocEngAdapter* adapterHandle);
int sendRsrcRequest(AGpsStatusValue action) const;
void onRsrcEvent(AgpsRsrcStatus event);
void retryCallback();
void informStatus(AgpsRsrcStatus status, int ID) const;
inline void incRetries() {mRetries++;}
inline virtual char *whoami() {return (char*)"DSStateMachine";}
};
// each subscriber is a AGPS client. In the case of ATL, there could be
// multiple clients from modem. In the case of BIT, there is only one
// cilent from BIT daemon.
struct Subscriber {
const uint32_t ID;
const AgpsStateMachine* mStateMachine;
inline Subscriber(const int id,
const AgpsStateMachine* stateMachine) :
ID(id), mStateMachine(stateMachine) {}
inline virtual ~Subscriber() {}
virtual void setIPAddresses(uint32_t &v4, char* v6) = 0;
virtual void setIPAddresses(struct sockaddr_storage& addr) = 0;
inline virtual void setWifiInfo(char* ssid, char* password)
{ ssid[0] = 0; password[0] = 0; }
inline virtual bool equals(const Subscriber *s) const
{ return ID == s->ID; }
// notifies a subscriber a new NIF resource status, usually
// either GRANTE, DENIED, or RELEASED
virtual bool notifyRsrcStatus(Notification &notification) = 0;
virtual bool waitForCloseComplete() { return false; }
virtual void setInactive() {}
virtual bool isInactive() { return false; }
virtual Subscriber* clone() = 0;
// checks if this notification is for me, i.e.
// either has my id, or has a broadcast id.
bool forMe(Notification &notification);
};
// BITSubscriber, created with requests from BIT daemon
struct BITSubscriber : public Subscriber {
char mIPv6Addr[16];
inline BITSubscriber(const AgpsStateMachine* stateMachine,
unsigned int ipv4, char* ipv6) :
Subscriber(ipv4, stateMachine)
{
if (NULL == ipv6) {
mIPv6Addr[0] = 0;
} else {
memcpy(mIPv6Addr, ipv6, sizeof(mIPv6Addr));
}
}
virtual bool notifyRsrcStatus(Notification &notification);
inline virtual void setIPAddresses(uint32_t &v4, char* v6)
{ v4 = ID; memcpy(v6, mIPv6Addr, sizeof(mIPv6Addr)); }
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
{ addr.ss_family = AF_INET6;/*todo: convert mIPv6Addr into addr */ }
virtual Subscriber* clone()
{
return new BITSubscriber(mStateMachine, ID, mIPv6Addr);
}
virtual bool equals(const Subscriber *s) const;
inline virtual ~BITSubscriber(){}
};
// ATLSubscriber, created with requests from ATL
struct ATLSubscriber : public Subscriber {
const LocEngAdapter* mLocAdapter;
const bool mBackwardCompatibleMode;
inline ATLSubscriber(const int id,
const AgpsStateMachine* stateMachine,
const LocEngAdapter* adapter,
const bool compatibleMode) :
Subscriber(id, stateMachine), mLocAdapter(adapter),
mBackwardCompatibleMode(compatibleMode){}
virtual bool notifyRsrcStatus(Notification &notification);
inline virtual void setIPAddresses(uint32_t &v4, char* v6)
{ v4 = INADDR_NONE; v6[0] = 0; }
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
{ addr.ss_family = AF_INET6; }
inline virtual Subscriber* clone()
{
return new ATLSubscriber(ID, mStateMachine, mLocAdapter,
mBackwardCompatibleMode);
}
inline virtual ~ATLSubscriber(){}
};
// WIFISubscriber, created with requests from MSAPM or QuIPC
struct WIFISubscriber : public Subscriber {
char * mSSID;
char * mPassword;
loc_if_req_sender_id_e_type senderId;
bool mIsInactive;
inline WIFISubscriber(const AgpsStateMachine* stateMachine,
char * ssid, char * password, loc_if_req_sender_id_e_type sender_id) :
Subscriber(sender_id, stateMachine),
mSSID(NULL == ssid ? NULL : new char[SSID_BUF_SIZE]),
mPassword(NULL == password ? NULL : new char[SSID_BUF_SIZE]),
senderId(sender_id)
{
if (NULL != mSSID)
strlcpy(mSSID, ssid, SSID_BUF_SIZE);
if (NULL != mPassword)
strlcpy(mPassword, password, SSID_BUF_SIZE);
mIsInactive = false;
}
virtual bool notifyRsrcStatus(Notification &notification);
inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
{ addr.ss_family = AF_INET6; }
inline virtual void setWifiInfo(char* ssid, char* password)
{
if (NULL != mSSID)
strlcpy(ssid, mSSID, SSID_BUF_SIZE);
else
ssid[0] = '\0';
if (NULL != mPassword)
strlcpy(password, mPassword, SSID_BUF_SIZE);
else
password[0] = '\0';
}
inline virtual bool waitForCloseComplete() { return true; }
inline virtual void setInactive() { mIsInactive = true; }
inline virtual bool isInactive() { return mIsInactive; }
virtual Subscriber* clone()
{
return new WIFISubscriber(mStateMachine, mSSID, mPassword, senderId);
}
inline virtual ~WIFISubscriber(){}
};
struct DSSubscriber : public Subscriber {
bool mIsInactive;
inline DSSubscriber(const AgpsStateMachine *stateMachine,
const int id) :
Subscriber(id, stateMachine)
{
mIsInactive = false;
}
inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
{ addr.ss_family = AF_INET6; }
virtual Subscriber* clone()
{return new DSSubscriber(mStateMachine, ID);}
virtual bool notifyRsrcStatus(Notification &notification);
inline virtual bool waitForCloseComplete() { return true; }
virtual void setInactive();
inline virtual bool isInactive()
{ return mIsInactive; }
inline virtual ~DSSubscriber(){}
inline virtual char *whoami() {return (char*)"DSSubscriber";}
};
#endif //__LOC_ENG_AGPS_H__

View File

@@ -0,0 +1,269 @@
/* Copyright (c) 2011-2012,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <linux/stat.h>
#include <fcntl.h>
#include <linux/types.h>
#include <unistd.h>
#include <errno.h>
#include <grp.h>
#include <sys/stat.h>
#include <platform_lib_includes.h>
#include "loc_eng_dmn_conn_glue_msg.h"
#include "loc_eng_dmn_conn_handler.h"
#include "loc_eng_dmn_conn.h"
#include "loc_eng_msg.h"
static int loc_api_server_msgqid;
static int loc_api_resp_msgqid;
static int quipc_msgqid;
static int msapm_msgqid;
static int msapu_msgqid;
static const char * global_loc_api_q_path = GPSONE_LOC_API_Q_PATH;
static const char * global_loc_api_resp_q_path = GPSONE_LOC_API_RESP_Q_PATH;
static const char * global_quipc_ctrl_q_path = QUIPC_CTRL_Q_PATH;
static const char * global_msapm_ctrl_q_path = MSAPM_CTRL_Q_PATH;
static const char * global_msapu_ctrl_q_path = MSAPU_CTRL_Q_PATH;
static int loc_api_server_proc_init(void *context)
{
loc_api_server_msgqid = loc_eng_dmn_conn_glue_msgget(global_loc_api_q_path, O_RDWR);
//change mode/group for the global_loc_api_q_path pipe
int result = chmod (global_loc_api_q_path, 0660);
if (result != 0)
{
LOC_LOGE("failed to change mode for %s, error = %s\n", global_loc_api_q_path, strerror(errno));
}
struct group * gps_group = getgrnam("gps");
if (gps_group != NULL)
{
result = chown (global_loc_api_q_path, -1, gps_group->gr_gid);
if (result != 0)
{
LOC_LOGE("chown for pipe failed, pipe %s, gid = %d, result = %d, error = %s\n",
global_loc_api_q_path, gps_group->gr_gid, result, strerror(errno));
}
}
else
{
LOC_LOGE("getgrnam for gps failed, error code = %d\n", errno);
}
loc_api_resp_msgqid = loc_eng_dmn_conn_glue_msgget(global_loc_api_resp_q_path, O_RDWR);
//change mode/group for the global_loc_api_resp_q_path pipe
result = chmod (global_loc_api_resp_q_path, 0660);
if (result != 0)
{
LOC_LOGE("failed to change mode for %s, error = %s\n", global_loc_api_resp_q_path, strerror(errno));
}
if (gps_group != NULL)
{
result = chown (global_loc_api_resp_q_path, -1, gps_group->gr_gid);
if (result != 0)
{
LOC_LOGE("chown for pipe failed, pipe %s, gid = %d, result = %d, error = %s\n",
global_loc_api_resp_q_path,
gps_group->gr_gid, result, strerror(errno));
}
}
quipc_msgqid = loc_eng_dmn_conn_glue_msgget(global_quipc_ctrl_q_path, O_RDWR);
msapm_msgqid = loc_eng_dmn_conn_glue_msgget(global_msapm_ctrl_q_path , O_RDWR);
msapu_msgqid = loc_eng_dmn_conn_glue_msgget(global_msapu_ctrl_q_path , O_RDWR);
LOC_LOGD("%s:%d] loc_api_server_msgqid = %d\n", __func__, __LINE__, loc_api_server_msgqid);
return 0;
}
static int loc_api_server_proc_pre(void *context)
{
return 0;
}
static int loc_api_server_proc(void *context)
{
int length, sz;
int result = 0;
static int cnt = 0;
struct ctrl_msgbuf * p_cmsgbuf;
struct ctrl_msgbuf cmsg_resp;
sz = sizeof(struct ctrl_msgbuf) + 256;
p_cmsgbuf = (struct ctrl_msgbuf *) malloc(sz);
if (!p_cmsgbuf) {
LOC_LOGE("%s:%d] Out of memory\n", __func__, __LINE__);
return -1;
}
cnt ++;
LOC_LOGD("%s:%d] %d listening on %s...\n", __func__, __LINE__, cnt, (char *) context);
length = loc_eng_dmn_conn_glue_msgrcv(loc_api_server_msgqid, p_cmsgbuf, sz);
if (length <= 0) {
free(p_cmsgbuf);
LOC_LOGE("%s:%d] fail receiving msg from gpsone_daemon, retry later\n", __func__, __LINE__);
usleep(1000);
return -1;
}
LOC_LOGD("%s:%d] received ctrl_type = %d\n", __func__, __LINE__, p_cmsgbuf->ctrl_type);
switch(p_cmsgbuf->ctrl_type) {
case GPSONE_LOC_API_IF_REQUEST:
result = loc_eng_dmn_conn_loc_api_server_if_request_handler(p_cmsgbuf, length);
break;
case GPSONE_LOC_API_IF_RELEASE:
result = loc_eng_dmn_conn_loc_api_server_if_release_handler(p_cmsgbuf, length);
break;
case GPSONE_UNBLOCK:
LOC_LOGD("%s:%d] GPSONE_UNBLOCK\n", __func__, __LINE__);
break;
default:
LOC_LOGE("%s:%d] unsupported ctrl_type = %d\n",
__func__, __LINE__, p_cmsgbuf->ctrl_type);
break;
}
free(p_cmsgbuf);
return 0;
}
static int loc_api_server_proc_post(void *context)
{
LOC_LOGD("%s:%d]\n", __func__, __LINE__);
loc_eng_dmn_conn_glue_msgremove( global_loc_api_q_path, loc_api_server_msgqid);
loc_eng_dmn_conn_glue_msgremove( global_loc_api_resp_q_path, loc_api_resp_msgqid);
loc_eng_dmn_conn_glue_msgremove( global_quipc_ctrl_q_path, quipc_msgqid);
loc_eng_dmn_conn_glue_msgremove( global_msapm_ctrl_q_path, msapm_msgqid);
loc_eng_dmn_conn_glue_msgremove( global_msapu_ctrl_q_path, msapu_msgqid);
return 0;
}
static int loc_eng_dmn_conn_unblock_proc(void)
{
struct ctrl_msgbuf cmsgbuf;
cmsgbuf.ctrl_type = GPSONE_UNBLOCK;
LOC_LOGD("%s:%d]\n", __func__, __LINE__);
loc_eng_dmn_conn_glue_msgsnd(loc_api_server_msgqid, & cmsgbuf, sizeof(cmsgbuf));
return 0;
}
static struct loc_eng_dmn_conn_thelper thelper;
int loc_eng_dmn_conn_loc_api_server_launch(thelper_create_thread create_thread_cb,
const char * loc_api_q_path, const char * resp_q_path, void *agps_handle)
{
int result;
loc_api_handle = agps_handle;
if (loc_api_q_path) global_loc_api_q_path = loc_api_q_path;
if (resp_q_path) global_loc_api_resp_q_path = resp_q_path;
result = loc_eng_dmn_conn_launch_thelper( &thelper,
loc_api_server_proc_init,
loc_api_server_proc_pre,
loc_api_server_proc,
loc_api_server_proc_post,
create_thread_cb,
(char *) global_loc_api_q_path);
if (result != 0) {
LOC_LOGE("%s:%d]\n", __func__, __LINE__);
return -1;
}
return 0;
}
int loc_eng_dmn_conn_loc_api_server_unblock(void)
{
loc_eng_dmn_conn_unblock_thelper(&thelper);
loc_eng_dmn_conn_unblock_proc();
return 0;
}
int loc_eng_dmn_conn_loc_api_server_join(void)
{
loc_eng_dmn_conn_join_thelper(&thelper);
return 0;
}
int loc_eng_dmn_conn_loc_api_server_data_conn(int sender_id, int status) {
struct ctrl_msgbuf cmsgbuf;
LOC_LOGD("%s:%d] quipc_msgqid = %d\n", __func__, __LINE__, quipc_msgqid);
cmsgbuf.ctrl_type = GPSONE_LOC_API_RESPONSE;
cmsgbuf.cmsg.cmsg_response.result = status;
switch (sender_id) {
case LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC: {
LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC", __func__, __LINE__);
if (loc_eng_dmn_conn_glue_msgsnd(quipc_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) {
LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__);
return -1;
}
break;
}
case LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM: {
LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM", __func__, __LINE__);
if (loc_eng_dmn_conn_glue_msgsnd(msapm_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) {
LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__);
return -1;
}
break;
}
case LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU: {
LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU", __func__, __LINE__);
if (loc_eng_dmn_conn_glue_msgsnd(msapu_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) {
LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__);
return -1;
}
break;
}
case LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON: {
LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON", __func__, __LINE__);
if (loc_eng_dmn_conn_glue_msgsnd(loc_api_resp_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) {
LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__);
return -1;
}
break;
}
default: {
LOC_LOGD("%s:%d] invalid sender ID!", __func__, __LINE__);
}
}
return 0;
}

View File

@@ -0,0 +1,59 @@
/* Copyright (c) 2011-2012,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_DATA_SERVER_H
#define LOC_ENG_DATA_SERVER_H
#include "loc_eng_dmn_conn_thread_helper.h"
#ifdef _ANDROID_
#define GPSONE_LOC_API_Q_PATH "/data/misc/location/gpsone_d/gpsone_loc_api_q"
#define GPSONE_LOC_API_RESP_Q_PATH "/data/misc/location/gpsone_d/gpsone_loc_api_resp_q"
#define QUIPC_CTRL_Q_PATH "/data/misc/location/gpsone_d/quipc_ctrl_q"
#define MSAPM_CTRL_Q_PATH "/data/misc/location/gpsone_d/msapm_ctrl_q"
#define MSAPU_CTRL_Q_PATH "/data/misc/location/gpsone_d/msapu_ctrl_q"
#else
#define GPSONE_LOC_API_Q_PATH "/tmp/gpsone_loc_api_q"
#define GPSONE_LOC_API_RESP_Q_PATH "/tmp/gpsone_loc_api_resp_q"
#define QUIPC_CTRL_Q_PATH "/tmp/quipc_ctrl_q"
#define MSAPM_CTRL_Q_PATH "/tmp/msapm_ctrl_q"
#define MSAPU_CTRL_Q_PATH "/tmp/msapu_ctrl_q"
#endif
int loc_eng_dmn_conn_loc_api_server_launch(thelper_create_thread create_thread_cb,
const char * loc_api_q_path, const char * ctrl_q_path, void *agps_handle);
int loc_eng_dmn_conn_loc_api_server_unblock(void);
int loc_eng_dmn_conn_loc_api_server_join(void);
int loc_eng_dmn_conn_loc_api_server_data_conn(int, int);
#endif /* LOC_ENG_DATA_SERVER_H */

View File

@@ -0,0 +1,222 @@
/* Copyright (c) 2011,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <linux/stat.h>
#include <fcntl.h>
#include <linux/types.h>
#include <platform_lib_includes.h>
#include "loc_eng_dmn_conn_glue_msg.h"
#include "loc_eng_dmn_conn_handler.h"
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_msgget
DESCRIPTION
This function get a message queue
q_path - name path of the message queue
mode -
DEPENDENCIES
None
RETURN VALUE
message queue id
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_msgget(const char * q_path, int mode)
{
int msgqid;
msgqid = loc_eng_dmn_conn_glue_pipeget(q_path, mode);
return msgqid;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_msgremove
DESCRIPTION
remove a message queue
q_path - name path of the message queue
msgqid - message queue id
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_msgremove(const char * q_path, int msgqid)
{
int result;
result = loc_eng_dmn_conn_glue_piperemove(q_path, msgqid);
return result;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_msgsnd
DESCRIPTION
Send a message
msgqid - message queue id
msgp - pointer to the message to be sent
msgsz - size of the message
DEPENDENCIES
None
RETURN VALUE
number of bytes sent out or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_msgsnd(int msgqid, const void * msgp, size_t msgsz)
{
int result;
struct ctrl_msgbuf *pmsg = (struct ctrl_msgbuf *) msgp;
pmsg->msgsz = msgsz;
result = loc_eng_dmn_conn_glue_pipewrite(msgqid, msgp, msgsz);
if (result != (int) msgsz) {
LOC_LOGE("%s:%d] pipe broken %d, msgsz = %d\n", __func__, __LINE__, result, (int) msgsz);
return -1;
}
return result;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_msgrcv
DESCRIPTION
receive a message
msgqid - message queue id
msgp - pointer to the buffer to hold the message
msgsz - size of the buffer
DEPENDENCIES
None
RETURN VALUE
number of bytes received or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_msgrcv(int msgqid, void *msgp, size_t msgbufsz)
{
int result;
struct ctrl_msgbuf *pmsg = (struct ctrl_msgbuf *) msgp;
result = loc_eng_dmn_conn_glue_piperead(msgqid, &(pmsg->msgsz), sizeof(pmsg->msgsz));
if (result != sizeof(pmsg->msgsz)) {
LOC_LOGE("%s:%d] pipe broken %d\n", __func__, __LINE__, result);
return -1;
}
if (msgbufsz < pmsg->msgsz) {
LOC_LOGE("%s:%d] msgbuf is too small %d < %d\n", __func__, __LINE__, (int) msgbufsz, (int) pmsg->msgsz);
return -1;
}
result = loc_eng_dmn_conn_glue_piperead(msgqid, (uint8_t *) msgp + sizeof(pmsg->msgsz), pmsg->msgsz - sizeof(pmsg->msgsz));
if (result != (int) (pmsg->msgsz - sizeof(pmsg->msgsz))) {
LOC_LOGE("%s:%d] pipe broken %d, msgsz = %d\n", __func__, __LINE__, result, (int) pmsg->msgsz);
return -1;
}
return pmsg->msgsz;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_msgunblock
DESCRIPTION
unblock a message queue
msgqid - message queue id
DEPENDENCIES
None
RETURN VALUE
0: success
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_msgunblock(int msgqid)
{
return loc_eng_dmn_conn_glue_pipeunblock(msgqid);
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_msgflush
DESCRIPTION
flush out the message in a queue
msgqid - message queue id
DEPENDENCIES
None
RETURN VALUE
number of bytes that are flushed out.
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_msgflush(int msgqid)
{
int length;
char buf[128];
do {
length = loc_eng_dmn_conn_glue_piperead(msgqid, buf, 128);
LOC_LOGD("%s:%d] %s\n", __func__, __LINE__, buf);
} while(length);
return length;
}

View File

@@ -0,0 +1,51 @@
/* Copyright (c) 2011, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_DMN_CONN_GLUE_MSG_H
#define LOC_ENG_DMN_CONN_GLUE_MSG_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <linux/types.h>
#include "loc_eng_dmn_conn_glue_pipe.h"
int loc_eng_dmn_conn_glue_msgget(const char * q_path, int mode);
int loc_eng_dmn_conn_glue_msgremove(const char * q_path, int msgqid);
int loc_eng_dmn_conn_glue_msgsnd(int msgqid, const void * msgp, size_t msgsz);
int loc_eng_dmn_conn_glue_msgrcv(int msgqid, void *msgp, size_t msgsz);
int loc_eng_dmn_conn_glue_msgflush(int msgqid);
int loc_eng_dmn_conn_glue_msgunblock(int msgqid);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LOC_ENG_DMN_CONN_GLUE_MSG_H */

View File

@@ -0,0 +1,215 @@
/* Copyright (c) 2011-2012,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include <unistd.h>
#include <errno.h>
// #include <linux/stat.h>
#include <fcntl.h>
// #include <linux/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "loc_eng_dmn_conn_glue_pipe.h"
#include <platform_lib_includes.h>
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_pipeget
DESCRIPTION
create a named pipe.
pipe_name - pipe name path
mode - mode
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_pipeget(const char * pipe_name, int mode)
{
int fd;
int result;
LOC_LOGD("%s, mode = %d\n", pipe_name, mode);
result = mkfifo(pipe_name, 0660);
if ((result == -1) && (errno != EEXIST)) {
LOC_LOGE("failed: %s\n", strerror(errno));
return result;
}
// The mode in mkfifo is not honoured and does not provide the
// group permissions. Doing chmod to add group permissions.
result = chmod (pipe_name, 0660);
if (result != 0){
LOC_LOGE ("%s failed to change mode for %s, error = %s\n", __func__,
pipe_name, strerror(errno));
}
fd = open(pipe_name, mode);
if (fd <= 0)
{
LOC_LOGE("failed: %s\n", strerror(errno));
}
LOC_LOGD("fd = %d, %s\n", fd, pipe_name);
return fd;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_piperemove
DESCRIPTION
remove a pipe
pipe_name - pipe name path
fd - fd for the pipe
DEPENDENCIES
None
RETURN VALUE
0: success
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_piperemove(const char * pipe_name, int fd)
{
close(fd);
if (pipe_name != NULL) {
unlink(pipe_name);
LOC_LOGD("fd = %d, %s\n", fd, pipe_name);
}
return 0;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_pipewrite
DESCRIPTION
write to a pipe
fd - fd of a pipe
buf - buffer for the data to write
sz - size of the data in buffer
DEPENDENCIES
None
RETURN VALUE
number of bytes written or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_pipewrite(int fd, const void * buf, size_t sz)
{
int result;
result = write(fd, buf, sz);
/* @todo check for non EINTR & EAGAIN, shall not do select again, select_tut Law 7) */
/* LOC_LOGD("fd = %d, buf = 0x%lx, size = %d, result = %d\n", fd, (long) buf, (int) sz, (int) result); */
return result;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_piperead
DESCRIPTION
read from a pipe
fd - fd for the pipe
buf - buffer to hold the data read from pipe
sz - size of the buffer
DEPENDENCIES
None
RETURN VALUE
number of bytes read from pipe or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_piperead(int fd, void * buf, size_t sz)
{
int len;
len = read(fd, buf, sz);
/* @todo check for non EINTR & EAGAIN, shall not do select again, select_tut Law 7) */
/* LOC_LOGD("fd = %d, buf = 0x%lx, size = %d, len = %d\n", fd, (long) buf, (int) sz, len); */
return len;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_glue_pipeunblock
DESCRIPTION
unblock a pipe
fd - fd for the pipe
DEPENDENCIES
None
RETURN VALUE
0 for success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_glue_pipeunblock(int fd)
{
int result;
struct flock flock_v;
LOC_LOGD("\n");
// result = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NDELAY);
flock_v.l_type = F_UNLCK;
flock_v.l_len = 32;
result = fcntl(fd, F_SETLK, &flock_v);
if (result < 0) {
LOC_LOGE("fcntl failure, %s\n", strerror(errno));
}
return result;
}

View File

@@ -0,0 +1,50 @@
/* Copyright (c) 2011, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_DMN_CONN_GLUE_PIPE_H
#define LOC_ENG_DMN_CONN_GLUE_PIPE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <linux/types.h>
int loc_eng_dmn_conn_glue_pipeget(const char * pipe_name, int mode);
int loc_eng_dmn_conn_glue_piperemove(const char * pipe_name, int fd);
int loc_eng_dmn_conn_glue_pipewrite(int fd, const void * buf, size_t sz);
int loc_eng_dmn_conn_glue_piperead(int fd, void * buf, size_t sz);
int loc_eng_dmn_conn_glue_pipeflush(int fd);
int loc_eng_dmn_conn_glue_pipeunblock(int fd);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LOC_ENG_DMN_CONN_GLUE_PIPE_H */

View File

@@ -0,0 +1,236 @@
/* Copyright (c) 2011-2012,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <platform_lib_includes.h>
#include "loc_eng_msg.h"
#include "loc_eng_dmn_conn.h"
#include "loc_eng_dmn_conn_handler.h"
void* loc_api_handle = NULL;
int loc_eng_dmn_conn_loc_api_server_if_request_handler(struct ctrl_msgbuf *pmsg, int len)
{
LOC_LOGD("%s:%d]\n", __func__, __LINE__);
#ifndef DEBUG_DMN_LOC_API
if (NULL == loc_api_handle) {
LOC_LOGE("%s:%d] NO agps data handle\n", __func__, __LINE__);
return 1;
}
if (NULL != loc_api_handle) {
AGpsExtType type;
switch (pmsg->cmsg.cmsg_if_request.type) {
case IF_REQUEST_TYPE_SUPL:
{
LOC_LOGD("IF_REQUEST_TYPE_SUPL");
type = AGPS_TYPE_SUPL;
break;
}
case IF_REQUEST_TYPE_WIFI:
{
LOC_LOGD("IF_REQUEST_TYPE_WIFI");
type = AGPS_TYPE_WIFI;
break;
}
case IF_REQUEST_TYPE_ANY:
{
LOC_LOGD("IF_REQUEST_TYPE_ANY");
type = AGPS_TYPE_ANY;
break;
}
default:
{
LOC_LOGD("invalid IF_REQUEST_TYPE!");
return -1;
}
}
switch (pmsg->cmsg.cmsg_if_request.sender_id) {
case IF_REQUEST_SENDER_ID_QUIPC:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_QUIPC");
LocEngReqRelWifi* msg =
new LocEngReqRelWifi(loc_api_handle,
type,
LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC,
(char*)pmsg->cmsg.cmsg_if_request.ssid,
(char*)pmsg->cmsg.cmsg_if_request.password,
true);
msg->send();
break;
}
case IF_REQUEST_SENDER_ID_MSAPM:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPM");
LocEngReqRelWifi* msg =
new LocEngReqRelWifi(loc_api_handle,
type,
LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM,
(char*)pmsg->cmsg.cmsg_if_request.ssid,
(char*)pmsg->cmsg.cmsg_if_request.password,
true);
msg->send();
break;
}
case IF_REQUEST_SENDER_ID_MSAPU:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPU");
LocEngReqRelWifi* msg =
new LocEngReqRelWifi(loc_api_handle,
type,
LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU,
(char*)pmsg->cmsg.cmsg_if_request.ssid,
(char*)pmsg->cmsg.cmsg_if_request.password,
true);
msg->send();
break;
}
case IF_REQUEST_SENDER_ID_GPSONE_DAEMON:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_GPSONE_DAEMON");
LocEngReqRelBIT* msg =
new LocEngReqRelBIT(loc_api_handle,
type,
pmsg->cmsg.cmsg_if_request.ipv4_addr,
(char*)pmsg->cmsg.cmsg_if_request.ipv6_addr,
true);
msg->send();
break;
}
default:
{
LOC_LOGD("invalid IF_REQUEST_SENDER_ID!");
return -1;
}
}
}
#else
loc_eng_dmn_conn_loc_api_server_data_conn(LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, GPSONE_LOC_API_IF_REQUEST_SUCCESS);
#endif
return 0;
}
int loc_eng_dmn_conn_loc_api_server_if_release_handler(struct ctrl_msgbuf *pmsg, int len)
{
LOC_LOGD("%s:%d]\n", __func__, __LINE__);
#ifndef DEBUG_DMN_LOC_API
AGpsExtType type;
switch (pmsg->cmsg.cmsg_if_request.type) {
case IF_REQUEST_TYPE_SUPL:
{
LOC_LOGD("IF_REQUEST_TYPE_SUPL");
type = AGPS_TYPE_SUPL;
break;
}
case IF_REQUEST_TYPE_WIFI:
{
LOC_LOGD("IF_REQUEST_TYPE_WIFI");
type = AGPS_TYPE_WIFI;
break;
}
case IF_REQUEST_TYPE_ANY:
{
LOC_LOGD("IF_REQUEST_TYPE_ANY");
type = AGPS_TYPE_ANY;
break;
}
default:
{
LOC_LOGD("invalid IF_REQUEST_TYPE!");
return -1;
}
}
switch (pmsg->cmsg.cmsg_if_request.sender_id) {
case IF_REQUEST_SENDER_ID_QUIPC:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_QUIPC");
LocEngReqRelWifi* msg =
new LocEngReqRelWifi(loc_api_handle,
type,
LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC,
(char*)pmsg->cmsg.cmsg_if_request.ssid,
(char*)pmsg->cmsg.cmsg_if_request.password,
false);
msg->send();
break;
}
case IF_REQUEST_SENDER_ID_MSAPM:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPM");
LocEngReqRelWifi* msg =
new LocEngReqRelWifi(loc_api_handle,
type,
LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM,
(char*)pmsg->cmsg.cmsg_if_request.ssid,
(char*)pmsg->cmsg.cmsg_if_request.password,
false);
msg->send();
break;
}
case IF_REQUEST_SENDER_ID_MSAPU:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPU");
LocEngReqRelWifi* msg =
new LocEngReqRelWifi(loc_api_handle,
type,
LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU,
(char*)pmsg->cmsg.cmsg_if_request.ssid,
(char*)pmsg->cmsg.cmsg_if_request.password,
false);
msg->send();
break;
}
case IF_REQUEST_SENDER_ID_GPSONE_DAEMON:
{
LOC_LOGD("IF_REQUEST_SENDER_ID_GPSONE_DAEMON");
LocEngReqRelBIT* msg =
new LocEngReqRelBIT(loc_api_handle,
type,
pmsg->cmsg.cmsg_if_request.ipv4_addr,
(char*)pmsg->cmsg.cmsg_if_request.ipv6_addr,
false);
msg->send();
break;
}
default:
{
LOC_LOGD("invalid IF_REQUEST_SENDER_ID!");
return -1;
}
}
#else
loc_eng_dmn_conn_loc_api_server_data_conn(LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, GPSONE_LOC_API_IF_RELEASE_SUCCESS);
#endif
return 0;
}

View File

@@ -0,0 +1,106 @@
/* Copyright (c) 2011-2012, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_DATA_SERVER_HANDLER
#define LOC_ENG_DATA_SERVER_HANDLER
#include <linux/types.h>
#include <arpa/inet.h>
//for SSID_BUF_SIZE
#include <hardware/gps.h>
#ifndef SSID_BUF_SIZE
#define SSID_BUF_SIZE (32+1)
#endif
enum {
/* 0x0 - 0xEF is reserved for daemon internal */
GPSONE_LOC_API_IF_REQUEST = 0xF0,
GPSONE_LOC_API_IF_RELEASE,
GPSONE_LOC_API_RESPONSE,
GPSONE_UNBLOCK,
};
enum {
GPSONE_LOC_API_IF_REQUEST_SUCCESS = 0xF0,
GPSONE_LOC_API_IF_RELEASE_SUCCESS,
GPSONE_LOC_API_IF_FAILURE,
};
struct ctrl_msg_response {
int result;
};
struct ctrl_msg_unblock {
int reserved;
};
typedef enum {
IF_REQUEST_TYPE_SUPL = 0,
IF_REQUEST_TYPE_WIFI,
IF_REQUEST_TYPE_ANY
} ctrl_if_req_type_e_type;
typedef enum {
IF_REQUEST_SENDER_ID_QUIPC = 0,
IF_REQUEST_SENDER_ID_MSAPM,
IF_REQUEST_SENDER_ID_MSAPU,
IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
IF_REQUEST_SENDER_ID_MODEM
} ctrl_if_req_sender_id_e_type;
struct ctrl_msg_if_request {
ctrl_if_req_type_e_type type;
ctrl_if_req_sender_id_e_type sender_id;
unsigned long ipv4_addr;
unsigned char ipv6_addr[16];
char ssid[SSID_BUF_SIZE];
char password[SSID_BUF_SIZE];
};
/* do not change this structure */
struct ctrl_msgbuf {
size_t msgsz;
uint16_t reserved1;
uint32_t reserved2;
uint8_t ctrl_type;
union {
struct ctrl_msg_response cmsg_response;
struct ctrl_msg_unblock cmsg_unblock;
struct ctrl_msg_if_request cmsg_if_request;
} cmsg;
};
extern void* loc_api_handle;
int loc_eng_dmn_conn_loc_api_server_if_request_handler(struct ctrl_msgbuf *pmsg, int len);
int loc_eng_dmn_conn_loc_api_server_if_release_handler(struct ctrl_msgbuf *pmsg, int len);
#endif /* LOC_ENG_DATA_SERVER_HANDLER */

View File

@@ -0,0 +1,398 @@
/* Copyright (c) 2011,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <platform_lib_includes.h>
#include "loc_eng_dmn_conn_thread_helper.h"
/*===========================================================================
FUNCTION thelper_signal_init
DESCRIPTION
This function will initialize the conditional variable resources.
thelper - thelper instance
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper)
{
int result;
thelper->thread_exit = 0;
thelper->thread_ready = 0;
result = pthread_cond_init( &thelper->thread_cond, NULL);
if (result) {
return result;
}
result = pthread_mutex_init(&thelper->thread_mutex, NULL);
if (result) {
pthread_cond_destroy(&thelper->thread_cond);
}
return result;
}
/*===========================================================================
FUNCTION
DESCRIPTION
This function will destroy the conditional variable resources
thelper - pointer to thelper instance
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper)
{
int result, ret_result = 0;
result = pthread_cond_destroy( &thelper->thread_cond);
if (result) {
ret_result = result;
}
result = pthread_mutex_destroy(&thelper->thread_mutex);
if (result) {
ret_result = result;
}
return ret_result;
}
/*===========================================================================
FUNCTION thelper_signal_wait
DESCRIPTION
This function will be blocked on the conditional variable until thelper_signal_ready
is called
thelper - pointer to thelper instance
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper)
{
int result = 0;
pthread_mutex_lock(&thelper->thread_mutex);
if (!thelper->thread_ready && !thelper->thread_exit) {
result = pthread_cond_wait(&thelper->thread_cond, &thelper->thread_mutex);
}
if (thelper->thread_exit) {
result = -1;
}
pthread_mutex_unlock(&thelper->thread_mutex);
return result;
}
/*===========================================================================
FUNCTION thelper_signal_ready
DESCRIPTION
This function will wake up the conditional variable
thelper - pointer to thelper instance
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper)
{
int result;
LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
pthread_mutex_lock(&thelper->thread_mutex);
thelper->thread_ready = 1;
result = pthread_cond_signal(&thelper->thread_cond);
pthread_mutex_unlock(&thelper->thread_mutex);
return result;
}
/*===========================================================================
FUNCTION thelper_signal_block
DESCRIPTION
This function will set the thread ready to 0 to block the thelper_signal_wait
thelper - pointer to thelper instance
DEPENDENCIES
None
RETURN VALUE
if thread_ready is set
SIDE EFFECTS
N/A
===========================================================================*/
int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper)
{
int result = thelper->thread_ready;
LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
pthread_mutex_lock(&thelper->thread_mutex);
thelper->thread_ready = 0;
pthread_mutex_unlock(&thelper->thread_mutex);
return result;
}
/*===========================================================================
FUNCTION thelper_main
DESCRIPTION
This function is the main thread. It will be launched as a child thread
data - pointer to the instance
DEPENDENCIES
None
RETURN VALUE
NULL
SIDE EFFECTS
N/A
===========================================================================*/
static void * thelper_main(void *data)
{
int result = 0;
struct loc_eng_dmn_conn_thelper * thelper = (struct loc_eng_dmn_conn_thelper *) data;
if (thelper->thread_proc_init) {
result = thelper->thread_proc_init(thelper->thread_context);
if (result < 0) {
thelper->thread_exit = 1;
thelper_signal_ready(thelper);
LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
return NULL;
}
}
thelper_signal_ready(thelper);
if (thelper->thread_proc_pre) {
result = thelper->thread_proc_pre(thelper->thread_context);
if (result < 0) {
thelper->thread_exit = 1;
LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
return NULL;
}
}
do {
if (thelper->thread_proc) {
result = thelper->thread_proc(thelper->thread_context);
if (result < 0) {
thelper->thread_exit = 1;
LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
}
}
} while (thelper->thread_exit == 0);
if (thelper->thread_proc_post) {
result = thelper->thread_proc_post(thelper->thread_context);
}
if (result != 0) {
LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
}
return NULL;
}
static void thelper_main_2(void *data)
{
thelper_main(data);
return;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_launch_thelper
DESCRIPTION
This function will initialize the thread context and launch the thelper_main
thelper - pointer to thelper instance
thread_proc_init - The initialization function pointer
thread_proc_pre - The function to call before task loop and after initialization
thread_proc - The task loop
thread_proc_post - The function to call after the task loop
context - the context for the above four functions
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper,
int (*thread_proc_init) (void * context),
int (*thread_proc_pre) (void * context),
int (*thread_proc) (void * context),
int (*thread_proc_post) (void * context),
thelper_create_thread create_thread_cb,
void * context)
{
int result;
thelper_signal_init(thelper);
if (context) {
thelper->thread_context = context;
}
thelper->thread_proc_init = thread_proc_init;
thelper->thread_proc_pre = thread_proc_pre;
thelper->thread_proc = thread_proc;
thelper->thread_proc_post = thread_proc_post;
LOC_LOGD("%s:%d] 0x%lx call pthread_create\n", __func__, __LINE__, (long) thelper);
if (create_thread_cb) {
result = 0;
thelper->thread_id = create_thread_cb("loc_eng_dmn_conn",
thelper_main_2, (void *)thelper);
} else {
result = pthread_create(&thelper->thread_id, NULL,
thelper_main, (void *)thelper);
}
if (result != 0) {
LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
return -1;
}
LOC_LOGD("%s:%d] 0x%lx pthread_create done\n", __func__, __LINE__, (long) thelper);
thelper_signal_wait(thelper);
LOC_LOGD("%s:%d] 0x%lx pthread ready\n", __func__, __LINE__, (long) thelper);
return thelper->thread_exit;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_unblock_thelper
DESCRIPTION
This function unblocks thelper_main to release the thread
thelper - pointer to thelper instance
DEPENDENCIES
None
RETURN VALUE
0: success
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper)
{
LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
thelper->thread_exit = 1;
return 0;
}
/*===========================================================================
FUNCTION loc_eng_dmn_conn_join_thelper
thelper - pointer to thelper instance
DESCRIPTION
This function will wait for the thread of thelper_main to finish
DEPENDENCIES
None
RETURN VALUE
0: success or negative value for failure
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper)
{
int result;
LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
result = pthread_join(thelper->thread_id, NULL);
if (result != 0) {
LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
}
LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
thelper_signal_destroy(thelper);
return result;
}

View File

@@ -0,0 +1,74 @@
/* Copyright (c) 2011, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_ENG_DMN_CONN_THREAD_HELPER_H__
#define __LOC_ENG_DMN_CONN_THREAD_HELPER_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <pthread.h>
struct loc_eng_dmn_conn_thelper {
unsigned char thread_exit;
unsigned char thread_ready;
pthread_cond_t thread_cond;
pthread_mutex_t thread_mutex;
pthread_t thread_id;
void * thread_context;
int (*thread_proc_init) (void * context);
int (*thread_proc_pre) (void * context);
int (*thread_proc) (void * context);
int (*thread_proc_post) (void * context);
};
typedef pthread_t (* thelper_create_thread)(const char* name, void (*start)(void *), void* arg);
int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper,
int (*thread_proc_init) (void * context),
int (*thread_proc_pre) (void * context),
int (*thread_proc) (void * context),
int (*thread_proc_post) (void * context),
thelper_create_thread create_thread_cb,
void * context);
int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper);
int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper);
/* if only need to use signal */
int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper);
int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper);
int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper);
int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper);
int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __LOC_ENG_DMN_CONN_THREAD_HELPER_H__ */

View File

@@ -0,0 +1,35 @@
/* Copyright (c) 2011-2013, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_NDDEBUG 0
#define LOG_TAG "LocSvc_eng"
#include "loc_log.h"
#include "loc_eng_log.h"

View File

@@ -0,0 +1,44 @@
/* Copyright (c) 2011-2013, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_LOG_H
#define LOC_ENG_LOG_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <ctype.h>
#ifdef __cplusplus
}
#endif
#endif /* LOC_ENG_LOG_H */

View File

@@ -0,0 +1,306 @@
/* Copyright (c) 2011-2014, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_MSG_H
#define LOC_ENG_MSG_H
#include <hardware/gps.h>
#include <gps_extended.h>
#include <stdlib.h>
#include <string.h>
#include <loc_eng_log.h>
#include <loc_eng.h>
#include <MsgTask.h>
#include <LocEngAdapter.h>
#include <platform_lib_includes.h>
#ifndef SSID_BUF_SIZE
#define SSID_BUF_SIZE (32+1)
#endif
#if defined(USE_GLIB) && !defined(OFF_TARGET)
#include <glib.h>
#endif /* USE_GLIB */
#include "platform_lib_includes.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
using namespace loc_core;
struct LocEngPositionMode : public LocMsg {
LocEngAdapter* mAdapter;
const LocPosMode mPosMode;
LocEngPositionMode(LocEngAdapter* adapter, LocPosMode &mode);
virtual void proc() const;
virtual void log() const;
void send() const;
};
struct LocEngStartFix : public LocMsg {
LocEngAdapter* mAdapter;
LocEngStartFix(LocEngAdapter* adapter);
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngStopFix : public LocMsg {
LocEngAdapter* mAdapter;
LocEngStopFix(LocEngAdapter* adapter);
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngReportPosition : public LocMsg {
LocAdapterBase* mAdapter;
const UlpLocation mLocation;
const GpsLocationExtended mLocationExtended;
const void* mLocationExt;
const enum loc_sess_status mStatus;
const LocPosTechMask mTechMask;
LocEngReportPosition(LocAdapterBase* adapter,
UlpLocation &loc,
GpsLocationExtended &locExtended,
void* locExt,
enum loc_sess_status st,
LocPosTechMask technology);
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngReportSv : public LocMsg {
LocAdapterBase* mAdapter;
const GnssSvStatus mSvStatus;
const GpsLocationExtended mLocationExtended;
const void* mSvExt;
LocEngReportSv(LocAdapterBase* adapter,
GnssSvStatus &sv,
GpsLocationExtended &locExtended,
void* svExtended);
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngReportStatus : public LocMsg {
LocAdapterBase* mAdapter;
const GpsStatusValue mStatus;
LocEngReportStatus(LocAdapterBase* adapter,
GpsStatusValue engineStatus);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngReportNmea : public LocMsg {
void* mLocEng;
char* const mNmea;
const int mLen;
LocEngReportNmea(void* locEng,
const char* data, int len);
inline virtual ~LocEngReportNmea()
{
delete[] mNmea;
}
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngReportXtraServer : public LocMsg {
void* mLocEng;
int mMaxLen;
char *mServers;
LocEngReportXtraServer(void* locEng,
const char *url1, const char *url2,
const char *url3, const int maxlength);
inline virtual ~LocEngReportXtraServer()
{
delete[] mServers;
}
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngSuplEsOpened : public LocMsg {
void* mLocEng;
LocEngSuplEsOpened(void* locEng);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngSuplEsClosed : public LocMsg {
void* mLocEng;
LocEngSuplEsClosed(void* locEng);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngRequestSuplEs : public LocMsg {
void* mLocEng;
const int mID;
LocEngRequestSuplEs(void* locEng, int id);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngRequestATL : public LocMsg {
void* mLocEng;
const int mID;
const AGpsExtType mType;
LocEngRequestATL(void* locEng, int id,
AGpsExtType agps_type);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngReleaseATL : public LocMsg {
void* mLocEng;
const int mID;
LocEngReleaseATL(void* locEng, int id);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngReqRelBIT : public LocMsg {
void* mLocEng;
const AGpsExtType mType;
const int mIPv4Addr;
char* const mIPv6Addr;
const bool mIsReq;
LocEngReqRelBIT(void* instance, AGpsExtType type,
int ipv4, char* ipv6, bool isReq);
virtual ~LocEngReqRelBIT();
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngReqRelWifi : public LocMsg {
void* mLocEng;
const AGpsExtType mType;
const loc_if_req_sender_id_e_type mSenderId;
char* const mSSID;
char* const mPassword;
const bool mIsReq;
LocEngReqRelWifi(void* locEng, AGpsExtType type,
loc_if_req_sender_id_e_type sender_id,
char* s, char* p, bool isReq);
virtual ~LocEngReqRelWifi();
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngRequestXtra : public LocMsg {
void* mLocEng;
LocEngRequestXtra(void* locEng);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngRequestTime : public LocMsg {
void* mLocEng;
LocEngRequestTime(void* locEng);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngRequestNi : public LocMsg {
void* mLocEng;
const GpsNiNotification mNotify;
const void *mPayload;
LocEngRequestNi(void* locEng,
GpsNiNotification &notif,
const void* data);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngDown : public LocMsg {
void* mLocEng;
LocEngDown(void* locEng);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngUp : public LocMsg {
void* mLocEng;
LocEngUp(void* locEng);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
struct LocEngGetZpp : public LocMsg {
LocEngAdapter* mAdapter;
LocEngGetZpp(LocEngAdapter* adapter);
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
struct LocEngReportGnssMeasurement : public LocMsg {
void* mLocEng;
const GnssData mGnssData;
LocEngReportGnssMeasurement(void* locEng,
GnssData &gnssData);
virtual void proc() const;
void locallog() const;
virtual void log() const;
};
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LOC_ENG_MSG_H */

View File

@@ -0,0 +1,413 @@
/* Copyright (c) 2009-2014, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_NDDEBUG 0
#define LOG_TAG "LocSvc_eng"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <MsgTask.h>
#include <loc_eng.h>
#include <platform_lib_includes.h>
using namespace loc_core;
/*=============================================================================
*
* DATA DECLARATION
*
*============================================================================*/
/*=============================================================================
*
* FUNCTION DECLARATIONS
*
*============================================================================*/
static void* ni_thread_proc(void *args);
struct LocEngInformNiResponse : public LocMsg {
LocEngAdapter* mAdapter;
const GpsUserResponseType mResponse;
const void *mPayload;
inline LocEngInformNiResponse(LocEngAdapter* adapter,
GpsUserResponseType resp,
const void* data) :
LocMsg(), mAdapter(adapter),
mResponse(resp), mPayload(data)
{
locallog();
}
inline ~LocEngInformNiResponse()
{
// this is a bit weird since mPayload is not
// allocated by this class. But there is no better way.
// mPayload actually won't be NULL here.
free((void*)mPayload);
}
inline virtual void proc() const
{
mAdapter->informNiResponse(mResponse, mPayload);
}
inline void locallog() const
{
LOC_LOGV("LocEngInformNiResponse - "
"response: %s\n mPayload: %p",
loc_get_ni_response_name(mResponse),
mPayload);
}
inline virtual void log() const
{
locallog();
}
};
/*===========================================================================
FUNCTION loc_eng_ni_request_handler
DESCRIPTION
Displays the NI request and awaits user input. If a previous request is
in session, it is ignored.
RETURN VALUE
none
===========================================================================*/
void loc_eng_ni_request_handler(loc_eng_data_s_type &loc_eng_data,
const GpsNiNotification *notif,
const void* passThrough)
{
ENTRY_LOG();
char lcs_addr[32]; // Decoded LCS address for UMTS CP NI
loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data;
loc_eng_ni_session_s_type* pSession = NULL;
if (NULL == loc_eng_data.ni_notify_cb) {
EXIT_LOG(%s, "loc_eng_ni_init hasn't happened yet.");
return;
}
if (notif->ni_type == GPS_NI_TYPE_EMERGENCY_SUPL) {
if (NULL != loc_eng_ni_data_p->sessionEs.rawRequest) {
LOC_LOGW("loc_eng_ni_request_handler, supl es NI in progress, new supl es NI ignored, type: %d",
notif->ni_type);
if (NULL != passThrough) {
free((void*)passThrough);
}
} else {
pSession = &loc_eng_ni_data_p->sessionEs;
}
} else {
if (NULL != loc_eng_ni_data_p->session.rawRequest ||
NULL != loc_eng_ni_data_p->sessionEs.rawRequest) {
LOC_LOGW("loc_eng_ni_request_handler, supl NI in progress, new supl NI ignored, type: %d",
notif->ni_type);
if (NULL != passThrough) {
free((void*)passThrough);
}
} else {
pSession = &loc_eng_ni_data_p->session;
}
}
if (pSession) {
/* Save request */
pSession->rawRequest = (void*)passThrough;
pSession->reqID = ++loc_eng_ni_data_p->reqIDCounter;
pSession->adapter = loc_eng_data.adapter;
/* Fill in notification */
((GpsNiNotification*)notif)->notification_id = pSession->reqID;
if (notif->notify_flags == GPS_NI_PRIVACY_OVERRIDE)
{
loc_eng_mute_one_session(loc_eng_data);
}
/* Log requestor ID and text for debugging */
LOC_LOGI("Notification: notif_type: %d, timeout: %d, default_resp: %d", notif->ni_type, notif->timeout, notif->default_response);
LOC_LOGI(" requestor_id: %s (encoding: %d)", notif->requestor_id, notif->requestor_id_encoding);
LOC_LOGI(" text: %s text (encoding: %d)", notif->text, notif->text_encoding);
if (notif->extras[0])
{
LOC_LOGI(" extras: %s", notif->extras);
}
/* For robustness, spawn a thread at this point to timeout to clear up the notification status, even though
* the OEM layer in java does not do so.
**/
pSession->respTimeLeft = 5 + (notif->timeout != 0 ? notif->timeout : LOC_NI_NO_RESPONSE_TIME);
LOC_LOGI("Automatically sends 'no response' in %d seconds (to clear status)\n", pSession->respTimeLeft);
int rc = 0;
rc = pthread_create(&pSession->thread, NULL, ni_thread_proc, pSession);
if (rc)
{
LOC_LOGE("Loc NI thread is not created.\n");
}
rc = pthread_detach(pSession->thread);
if (rc)
{
LOC_LOGE("Loc NI thread is not detached.\n");
}
CALLBACK_LOG_CALLFLOW("ni_notify_cb - id", %d, notif->notification_id);
loc_eng_data.ni_notify_cb((GpsNiNotification*)notif, gps_conf.SUPL_ES != 0);
}
EXIT_LOG(%s, VOID_RET);
}
/*===========================================================================
FUNCTION ni_thread_proc
===========================================================================*/
static void* ni_thread_proc(void *args)
{
ENTRY_LOG();
loc_eng_ni_session_s_type* pSession = (loc_eng_ni_session_s_type*)args;
int rc = 0; /* return code from pthread calls */
struct timeval present_time;
struct timespec expire_time;
LOC_LOGD("Starting Loc NI thread...\n");
pthread_mutex_lock(&pSession->tLock);
/* Calculate absolute expire time */
gettimeofday(&present_time, NULL);
expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
expire_time.tv_nsec = present_time.tv_usec * 1000;
LOC_LOGD("ni_thread_proc-Time out set for abs time %ld with delay %d sec\n",
(long) expire_time.tv_sec, pSession->respTimeLeft );
while (!pSession->respRecvd)
{
rc = pthread_cond_timedwait(&pSession->tCond,
&pSession->tLock,
&expire_time);
if (rc == ETIMEDOUT)
{
pSession->resp = GPS_NI_RESPONSE_NORESP;
LOC_LOGD("ni_thread_proc-Thread time out after valting for specified time. Ret Val %d\n",rc );
break;
}
}
LOC_LOGD("ni_thread_proc-Java layer has sent us a user response and return value from "
"pthread_cond_timedwait = %d\n",rc );
pSession->respRecvd = FALSE; /* Reset the user response flag for the next session*/
LOC_LOGD("pSession->resp is %d\n",pSession->resp);
// adding this check to support modem restart, in which case, we need the thread
// to exit without calling sending data. We made sure that rawRequest is NULL in
// loc_eng_ni_reset_on_engine_restart()
LocEngAdapter* adapter = pSession->adapter;
LocEngInformNiResponse *msg = NULL;
if (NULL != pSession->rawRequest) {
if (pSession->resp != GPS_NI_RESPONSE_IGNORE) {
LOC_LOGD("pSession->resp != GPS_NI_RESPONSE_IGNORE \n");
msg = new LocEngInformNiResponse(adapter,
pSession->resp,
pSession->rawRequest);
} else {
LOC_LOGD("this is the ignore reply for SUPL ES\n");
free(pSession->rawRequest);
}
pSession->rawRequest = NULL;
}
pthread_mutex_unlock(&pSession->tLock);
pSession->respTimeLeft = 0;
pSession->reqID = 0;
if (NULL != msg) {
LOC_LOGD("ni_thread_proc: adapter->sendMsg(msg)\n");
adapter->sendMsg(msg);
}
EXIT_LOG(%s, VOID_RET);
return NULL;
}
void loc_eng_ni_reset_on_engine_restart(loc_eng_data_s_type &loc_eng_data)
{
ENTRY_LOG();
loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data;
if (NULL == loc_eng_data.ni_notify_cb) {
EXIT_LOG(%s, "loc_eng_ni_init hasn't happened yet.");
return;
}
// only if modem has requested but then died.
if (NULL != loc_eng_ni_data_p->sessionEs.rawRequest) {
free(loc_eng_ni_data_p->sessionEs.rawRequest);
loc_eng_ni_data_p->sessionEs.rawRequest = NULL;
pthread_mutex_lock(&loc_eng_ni_data_p->sessionEs.tLock);
// the goal is to wake up ni_thread_proc
// and let it exit.
loc_eng_ni_data_p->sessionEs.respRecvd = TRUE;
pthread_cond_signal(&loc_eng_ni_data_p->sessionEs.tCond);
pthread_mutex_unlock(&loc_eng_ni_data_p->sessionEs.tLock);
}
if (NULL != loc_eng_ni_data_p->session.rawRequest) {
free(loc_eng_ni_data_p->session.rawRequest);
loc_eng_ni_data_p->session.rawRequest = NULL;
pthread_mutex_lock(&loc_eng_ni_data_p->session.tLock);
// the goal is to wake up ni_thread_proc
// and let it exit.
loc_eng_ni_data_p->session.respRecvd = TRUE;
pthread_cond_signal(&loc_eng_ni_data_p->session.tCond);
pthread_mutex_unlock(&loc_eng_ni_data_p->session.tLock);
}
EXIT_LOG(%s, VOID_RET);
}
/*===========================================================================
FUNCTION loc_eng_ni_init
DESCRIPTION
This function initializes the NI interface
DEPENDENCIES
NONE
RETURN VALUE
None
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_ni_init(loc_eng_data_s_type &loc_eng_data, GpsNiExtCallbacks *callbacks)
{
ENTRY_LOG_CALLFLOW();
if(callbacks == NULL)
EXIT_LOG(%s, "loc_eng_ni_init: failed, cb is NULL");
else if (NULL == callbacks->notify_cb) {
EXIT_LOG(%s, "loc_eng_ni_init: failed, no cb.");
} else if (NULL != loc_eng_data.ni_notify_cb) {
EXIT_LOG(%s, "loc_eng_ni_init: already inited.");
} else {
loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data;
loc_eng_ni_data_p->sessionEs.respTimeLeft = 0;
loc_eng_ni_data_p->sessionEs.respRecvd = FALSE;
loc_eng_ni_data_p->sessionEs.rawRequest = NULL;
loc_eng_ni_data_p->sessionEs.reqID = 0;
pthread_cond_init(&loc_eng_ni_data_p->sessionEs.tCond, NULL);
pthread_mutex_init(&loc_eng_ni_data_p->sessionEs.tLock, NULL);
loc_eng_ni_data_p->session.respTimeLeft = 0;
loc_eng_ni_data_p->session.respRecvd = FALSE;
loc_eng_ni_data_p->session.rawRequest = NULL;
loc_eng_ni_data_p->session.reqID = 0;
pthread_cond_init(&loc_eng_ni_data_p->session.tCond, NULL);
pthread_mutex_init(&loc_eng_ni_data_p->session.tLock, NULL);
loc_eng_data.ni_notify_cb = callbacks->notify_cb;
EXIT_LOG(%s, VOID_RET);
}
}
/*===========================================================================
FUNCTION loc_eng_ni_respond
DESCRIPTION
This function receives user response from upper layer framework
DEPENDENCIES
NONE
RETURN VALUE
None
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_ni_respond(loc_eng_data_s_type &loc_eng_data,
int notif_id, GpsUserResponseType user_response)
{
ENTRY_LOG_CALLFLOW();
loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data;
loc_eng_ni_session_s_type* pSession = NULL;
if (NULL == loc_eng_data.ni_notify_cb) {
EXIT_LOG(%s, "loc_eng_ni_init hasn't happened yet.");
return;
}
if (notif_id == loc_eng_ni_data_p->sessionEs.reqID &&
NULL != loc_eng_ni_data_p->sessionEs.rawRequest) {
pSession = &loc_eng_ni_data_p->sessionEs;
// ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
if (user_response == GPS_NI_RESPONSE_ACCEPT &&
NULL != loc_eng_ni_data_p->session.rawRequest) {
pthread_mutex_lock(&loc_eng_ni_data_p->session.tLock);
loc_eng_ni_data_p->session.resp = GPS_NI_RESPONSE_IGNORE;
loc_eng_ni_data_p->session.respRecvd = TRUE;
pthread_cond_signal(&loc_eng_ni_data_p->session.tCond);
pthread_mutex_unlock(&loc_eng_ni_data_p->session.tLock);
}
} else if (notif_id == loc_eng_ni_data_p->session.reqID &&
NULL != loc_eng_ni_data_p->session.rawRequest) {
pSession = &loc_eng_ni_data_p->session;
}
if (pSession) {
LOC_LOGI("loc_eng_ni_respond: send user response %d for notif %d", user_response, notif_id);
pthread_mutex_lock(&pSession->tLock);
pSession->resp = user_response;
pSession->respRecvd = TRUE;
pthread_cond_signal(&pSession->tCond);
pthread_mutex_unlock(&pSession->tLock);
}
else {
LOC_LOGE("loc_eng_ni_respond: notif_id %d not an active session", notif_id);
}
EXIT_LOG(%s, VOID_RET);
}

View File

@@ -0,0 +1,59 @@
/* Copyright (c) 2009,2011,2014 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_NI_H
#define LOC_ENG_NI_H
#include <stdbool.h>
#include <LocEngAdapter.h>
#define LOC_NI_NO_RESPONSE_TIME 20 /* secs */
#define LOC_NI_NOTIF_KEY_ADDRESS "Address"
#define GPS_NI_RESPONSE_IGNORE 4
typedef struct {
pthread_t thread; /* NI thread */
int respTimeLeft; /* examine time for NI response */
bool respRecvd; /* NI User reponse received or not from Java layer*/
void* rawRequest;
int reqID; /* ID to check against response */
GpsUserResponseType resp;
pthread_cond_t tCond;
pthread_mutex_t tLock;
LocEngAdapter* adapter;
} loc_eng_ni_session_s_type;
typedef struct {
loc_eng_ni_session_s_type session; /* SUPL NI Session */
loc_eng_ni_session_s_type sessionEs; /* Emergency SUPL NI Session */
int reqIDCounter;
} loc_eng_ni_data_s_type;
#endif /* LOC_ENG_NI_H */

View File

@@ -0,0 +1,924 @@
/* Copyright (c) 2012, 2016, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_NDDEBUG 0
#define LOG_TAG "LocSvc_eng_nmea"
#include <loc_eng.h>
#include <loc_eng_nmea.h>
#include <math.h>
#include <platform_lib_includes.h>
/*===========================================================================
FUNCTION loc_eng_nmea_send
DESCRIPTION
send out NMEA sentence
DEPENDENCIES
NONE
RETURN VALUE
Total length of the nmea sentence
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_nmea_send(char *pNmea, int length, loc_eng_data_s_type *loc_eng_data_p)
{
struct timeval tv;
gettimeofday(&tv, (struct timezone *) NULL);
int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
if (loc_eng_data_p->nmea_cb != NULL)
loc_eng_data_p->nmea_cb(now, pNmea, length);
LOC_LOGD("NMEA <%s", pNmea);
}
/*===========================================================================
FUNCTION loc_eng_nmea_put_checksum
DESCRIPTION
Generate NMEA sentences generated based on position report
DEPENDENCIES
NONE
RETURN VALUE
Total length of the nmea sentence
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_nmea_put_checksum(char *pNmea, int maxSize)
{
uint8_t checksum = 0;
int length = 0;
pNmea++; //skip the $
while (*pNmea != '\0')
{
checksum ^= *pNmea++;
length++;
}
// length now contains nmea sentence string length not including $ sign.
int checksumLength = snprintf(pNmea,(maxSize-length-1),"*%02X\r\n", checksum);
// total length of nmea sentence is length of nmea sentence inc $ sign plus
// length of checksum (+1 is to cover the $ character in the length).
return (length + checksumLength + 1);
}
/*===========================================================================
FUNCTION loc_eng_nmea_generate_pos
DESCRIPTION
Generate NMEA sentences generated based on position report
Currently below sentences are generated within this function:
- $GPGSA : GPS DOP and active SVs
- $GNGSA : GLONASS DOP and active SVs
- $GPVTG : Track made good and ground speed
- $GPRMC : Recommended minimum navigation information
- $GPGGA : Time, position and fix related data
DEPENDENCIES
NONE
RETURN VALUE
0
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
const UlpLocation &location,
const GpsLocationExtended &locationExtended,
unsigned char generate_nmea)
{
ENTRY_LOG();
time_t utcTime(location.gpsLocation.timestamp/1000);
tm * pTm = gmtime(&utcTime);
if (NULL == pTm) {
LOC_LOGE("gmtime failed");
return;
}
char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
char* pMarker = sentence;
int lengthRemaining = sizeof(sentence);
int length = 0;
int utcYear = pTm->tm_year % 100; // 2 digit year
int utcMonth = pTm->tm_mon + 1; // tm_mon starts at zero
int utcDay = pTm->tm_mday;
int utcHours = pTm->tm_hour;
int utcMinutes = pTm->tm_min;
int utcSeconds = pTm->tm_sec;
int utcMSeconds = (location.gpsLocation.timestamp)%1000;
if (generate_nmea) {
// ------------------
// ------$GPGSA------
// ------------------
uint32_t svUsedCount = 0;
uint32_t svUsedList[32] = {0};
uint32_t mask = loc_eng_data_p->gps_used_mask;
for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++)
{
if (mask & 1)
svUsedList[svUsedCount++] = i;
mask = mask >> 1;
}
// clear the cache so they can't be used again
loc_eng_data_p->gps_used_mask = 0;
char fixType;
if (svUsedCount == 0)
fixType = '1'; // no fix
else if (svUsedCount <= 3)
fixType = '2'; // 2D fix
else
fixType = '3'; // 3D fix
length = snprintf(pMarker, lengthRemaining, "$GPGSA,A,%c,", fixType);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
for (uint8_t i = 0; i < 12; i++) // only the first 12 sv go in sentence
{
if (i < svUsedCount)
length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]);
else
length = snprintf(pMarker, lengthRemaining, ",");
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{ // dop is in locationExtended, (QMI)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
locationExtended.pdop,
locationExtended.hdop,
locationExtended.vdop);
}
else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0)
{ // dop was cached from sv report (RPC)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
loc_eng_data_p->pdop,
loc_eng_data_p->hdop,
loc_eng_data_p->vdop);
}
else
{ // no dop
length = snprintf(pMarker, lengthRemaining, ",,");
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------
// ------$GNGSA------
// ------------------
uint32_t gloUsedCount = 0;
uint32_t gloUsedList[32] = {0};
// Reset locals for GNGSA sentence generation
pMarker = sentence;
lengthRemaining = sizeof(sentence);
mask = loc_eng_data_p->glo_used_mask;
fixType = '\0';
// Parse the glonass sv mask, and fetch glo sv ids
// Mask corresponds to the offset.
// GLONASS SV ids are from 65-96
const int GLONASS_SV_ID_OFFSET = 64;
for (uint8_t i = 1; mask > 0 && gloUsedCount < 32; i++)
{
if (mask & 1)
gloUsedList[gloUsedCount++] = i + GLONASS_SV_ID_OFFSET;
mask = mask >> 1;
}
// clear the cache so they can't be used again
loc_eng_data_p->glo_used_mask = 0;
if (gloUsedCount == 0)
fixType = '1'; // no fix
else if (gloUsedCount <= 3)
fixType = '2'; // 2D fix
else
fixType = '3'; // 3D fix
// Start printing the sentence
// Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v*cc
// GNGSA : for glonass SVs
// a : Mode : A : Automatic, allowed to automatically switch 2D/3D
// x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
// xx : 12 SV ID
// p.p : Position DOP (Dilution of Precision)
// h.h : Horizontal DOP
// v.v : Vertical DOP
// cc : Checksum value
length = snprintf(pMarker, lengthRemaining, "$GNGSA,A,%c,", fixType);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
// Add first 12 GLONASS satellite IDs
for (uint8_t i = 0; i < 12; i++)
{
if (i < gloUsedCount)
length = snprintf(pMarker, lengthRemaining, "%02d,", gloUsedList[i]);
else
length = snprintf(pMarker, lengthRemaining, ",");
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
// Add the position/horizontal/vertical DOP values
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{ // dop is in locationExtended, (QMI)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
locationExtended.pdop,
locationExtended.hdop,
locationExtended.vdop);
}
else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0)
{ // dop was cached from sv report (RPC)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
loc_eng_data_p->pdop,
loc_eng_data_p->hdop,
loc_eng_data_p->vdop);
}
else
{ // no dop
length = snprintf(pMarker, lengthRemaining, ",,");
}
/* Sentence is ready, add checksum and broadcast */
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------
// ------$GPVTG------
// ------------------
pMarker = sentence;
lengthRemaining = sizeof(sentence);
if (location.gpsLocation.flags & GPS_LOCATION_HAS_BEARING)
{
float magTrack = location.gpsLocation.bearing;
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV)
{
float magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation;
if (magTrack < 0.0)
magTrack += 360.0;
else if (magTrack > 360.0)
magTrack -= 360.0;
}
length = snprintf(pMarker, lengthRemaining, "$GPVTG,%.1lf,T,%.1lf,M,", location.gpsLocation.bearing, magTrack);
}
else
{
length = snprintf(pMarker, lengthRemaining, "$GPVTG,,T,,M,");
}
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (location.gpsLocation.flags & GPS_LOCATION_HAS_SPEED)
{
float speedKnots = location.gpsLocation.speed * (3600.0/1852.0);
float speedKmPerHour = location.gpsLocation.speed * 3.6;
length = snprintf(pMarker, lengthRemaining, "%.1lf,N,%.1lf,K,", speedKnots, speedKmPerHour);
}
else
{
length = snprintf(pMarker, lengthRemaining, ",N,,K,");
}
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (!(location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG))
length = snprintf(pMarker, lengthRemaining, "%c", 'N'); // N means no fix
else if (LOC_POSITION_MODE_STANDALONE == loc_eng_data_p->adapter->getPositionMode().mode)
length = snprintf(pMarker, lengthRemaining, "%c", 'A'); // A means autonomous
else
length = snprintf(pMarker, lengthRemaining, "%c", 'D'); // D means differential
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------
// ------$GPRMC------
// ------------------
pMarker = sentence;
lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GPRMC,%02d%02d%02d.%02d,A," ,
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 & GPS_LOCATION_HAS_LAT_LONG)
{
double latitude = location.gpsLocation.latitude;
double longitude = location.gpsLocation.longitude;
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 (location.gpsLocation.flags & GPS_LOCATION_HAS_SPEED)
{
float speedKnots = location.gpsLocation.speed * (3600.0/1852.0);
length = snprintf(pMarker, lengthRemaining, "%.1lf,", speedKnots);
}
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 & GPS_LOCATION_HAS_BEARING)
{
length = snprintf(pMarker, lengthRemaining, "%.1lf,", location.gpsLocation.bearing);
}
else
{
length = snprintf(pMarker, lengthRemaining, ",");
}
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
length = snprintf(pMarker, lengthRemaining, "%2.2d%2.2d%2.2d,",
utcDay, utcMonth, utcYear);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV)
{
float magneticVariation = locationExtended.magneticDeviation;
char direction;
if (magneticVariation < 0.0)
{
direction = 'W';
magneticVariation *= -1.0;
}
else
{
direction = 'E';
}
length = snprintf(pMarker, lengthRemaining, "%.1lf,%c,",
magneticVariation, direction);
}
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 & GPS_LOCATION_HAS_LAT_LONG))
length = snprintf(pMarker, lengthRemaining, "%c", 'N'); // N means no fix
else if (LOC_POSITION_MODE_STANDALONE == loc_eng_data_p->adapter->getPositionMode().mode)
length = snprintf(pMarker, lengthRemaining, "%c", 'A'); // A means autonomous
else
length = snprintf(pMarker, lengthRemaining, "%c", 'D'); // D means differential
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------
// ------$GPGGA------
// ------------------
pMarker = sentence;
lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GPGGA,%02d%02d%02d.%02d," ,
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 & GPS_LOCATION_HAS_LAT_LONG)
{
double latitude = location.gpsLocation.latitude;
double longitude = location.gpsLocation.longitude;
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;
char gpsQuality;
if (!(location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG))
gpsQuality = '0'; // 0 means no fix
else if (LOC_POSITION_MODE_STANDALONE == loc_eng_data_p->adapter->getPositionMode().mode)
gpsQuality = '1'; // 1 means GPS fix
else
gpsQuality = '2'; // 2 means DGPS fix
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{ // dop is in locationExtended, (QMI)
length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,",
gpsQuality, svUsedCount, locationExtended.hdop);
}
else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0)
{ // dop was cached from sv report (RPC)
length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,",
gpsQuality, svUsedCount, loc_eng_data_p->hdop);
}
else
{ // no hdop
length = snprintf(pMarker, lengthRemaining, "%c,%02d,,",
gpsQuality, 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,M,",
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 & GPS_LOCATION_HAS_ALTITUDE) &&
(locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL))
{
length = snprintf(pMarker, lengthRemaining, "%.1lf,M,,",
location.gpsLocation.altitude - locationExtended.altitudeMeanSeaLevel);
}
else
{
length = snprintf(pMarker, lengthRemaining,",,,");
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
}
//Send blank NMEA reports for non-final fixes
else {
strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
}
// clear the dop cache so they can't be used again
loc_eng_data_p->pdop = 0;
loc_eng_data_p->hdop = 0;
loc_eng_data_p->vdop = 0;
EXIT_LOG(%d, 0);
}
/*===========================================================================
FUNCTION loc_eng_nmea_generate_sv
DESCRIPTION
Generate NMEA sentences generated based on sv report
DEPENDENCIES
NONE
RETURN VALUE
0
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p,
const GnssSvStatus &svStatus, const GpsLocationExtended &locationExtended)
{
ENTRY_LOG();
char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
char* pMarker = sentence;
int lengthRemaining = sizeof(sentence);
int length = 0;
int svCount = svStatus.num_svs;
int sentenceCount = 0;
int sentenceNumber = 1;
int svNumber = 1;
int gpsCount = 0;
int glnCount = 0;
//Count GPS SVs for saparating GPS from GLONASS and throw others
loc_eng_data_p->gps_used_mask = 0;
loc_eng_data_p->glo_used_mask = 0;
for(svNumber=1; svNumber <= svCount; svNumber++) {
if (GNSS_CONSTELLATION_GPS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
// cache the used in fix mask, as it will be needed to send $GPGSA
// during the position report
if (GNSS_SV_FLAGS_USED_IN_FIX == (svStatus.gnss_sv_list[svNumber - 1].flags & GNSS_SV_FLAGS_USED_IN_FIX))
{
loc_eng_data_p->gps_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1));
}
gpsCount++;
}
else if (GNSS_CONSTELLATION_GLONASS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
// cache the used in fix mask, as it will be needed to send $GNGSA
// during the position report
if (GNSS_SV_FLAGS_USED_IN_FIX == (svStatus.gnss_sv_list[svNumber - 1].flags & GNSS_SV_FLAGS_USED_IN_FIX))
{
loc_eng_data_p->glo_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1));
}
glnCount++;
}
}
// ------------------
// ------$GPGSV------
// ------------------
if (gpsCount <= 0)
{
// no svs in view, so just send a blank $GPGSV sentence
strlcpy(sentence, "$GPGSV,1,1,0,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
}
else
{
svNumber = 1;
sentenceNumber = 1;
sentenceCount = gpsCount/4 + (gpsCount % 4 != 0);
while (sentenceNumber <= sentenceCount)
{
pMarker = sentence;
lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GPGSV,%d,%d,%02d",
sentenceCount, sentenceNumber, gpsCount);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
for (int i=0; (svNumber <= svCount) && (i < 4); svNumber++)
{
if (GNSS_CONSTELLATION_GPS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
svStatus.gnss_sv_list[svNumber-1].svid,
(int)(0.5 + svStatus.gnss_sv_list[svNumber-1].elevation), //float to int
(int)(0.5 + svStatus.gnss_sv_list[svNumber-1].azimuth)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (svStatus.gnss_sv_list[svNumber-1].c_n0_dbhz > 0)
{
length = snprintf(pMarker, lengthRemaining,"%02d",
(int)(0.5 + svStatus.gnss_sv_list[svNumber-1].c_n0_dbhz)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
i++;
}
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
sentenceNumber++;
} //while
} //if
// ------------------
// ------$GLGSV------
// ------------------
if (glnCount <= 0)
{
// no svs in view, so just send a blank $GLGSV sentence
strlcpy(sentence, "$GLGSV,1,1,0,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
}
else
{
svNumber = 1;
sentenceNumber = 1;
sentenceCount = glnCount/4 + (glnCount % 4 != 0);
while (sentenceNumber <= sentenceCount)
{
pMarker = sentence;
lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GLGSV,%d,%d,%02d",
sentenceCount, sentenceNumber, glnCount);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
for (int i=0; (svNumber <= svCount) && (i < 4); svNumber++)
{
if (GNSS_CONSTELLATION_GLONASS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
svStatus.gnss_sv_list[svNumber - 1].svid,
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].elevation), //float to int
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].azimuth)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (svStatus.gnss_sv_list[svNumber - 1].c_n0_dbhz > 0)
{
length = snprintf(pMarker, lengthRemaining,"%02d",
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].c_n0_dbhz)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
i++;
}
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
sentenceNumber++;
} //while
}//if
// For RPC, the DOP are sent during sv report, so cache them
// now to be sent during position report.
// For QMI, the DOP will be in position report.
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{
loc_eng_data_p->pdop = locationExtended.pdop;
loc_eng_data_p->hdop = locationExtended.hdop;
loc_eng_data_p->vdop = locationExtended.vdop;
}
else
{
loc_eng_data_p->pdop = 0;
loc_eng_data_p->hdop = 0;
loc_eng_data_p->vdop = 0;
}
EXIT_LOG(%d, 0);
}

View File

@@ -0,0 +1,43 @@
/* Copyright (c) 2012, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_NMEA_H
#define LOC_ENG_NMEA_H
#include <hardware/gps.h>
#include <gps_extended.h>
#define NMEA_SENTENCE_MAX_LENGTH 200
void loc_eng_nmea_send(char *pNmea, int length, loc_eng_data_s_type *loc_eng_data_p);
int loc_eng_nmea_put_checksum(char *pNmea, int maxSize);
void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p, const GnssSvStatus &svStatus, const GpsLocationExtended &locationExtended);
void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p, const UlpLocation &location, const GpsLocationExtended &locationExtended, unsigned char generate_nmea);
#endif // LOC_ENG_NMEA_H

View File

@@ -0,0 +1,219 @@
/* Copyright (c) 2009-2014, 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_NDDEBUG 0
#define LOG_TAG "LocSvc_eng"
#include <loc_eng.h>
#include <MsgTask.h>
#include <platform_lib_includes.h>
using namespace loc_core;
struct LocEngRequestXtraServer : public LocMsg {
LocEngAdapter* mAdapter;
inline LocEngRequestXtraServer(LocEngAdapter* adapter) :
LocMsg(), mAdapter(adapter)
{
locallog();
}
inline virtual void proc() const {
mAdapter->requestXtraServer();
}
inline void locallog() const {
LOC_LOGV("LocEngRequestXtraServer");
}
inline virtual void log() const {
locallog();
}
};
struct LocEngInjectXtraData : public LocMsg {
LocEngAdapter* mAdapter;
char* mData;
const int mLen;
inline LocEngInjectXtraData(LocEngAdapter* adapter,
char* data, int len):
LocMsg(), mAdapter(adapter),
mData(new char[len]), mLen(len)
{
memcpy((void*)mData, (void*)data, len);
locallog();
}
inline ~LocEngInjectXtraData()
{
delete[] mData;
}
inline virtual void proc() const {
mAdapter->setXtraData(mData, mLen);
}
inline void locallog() const {
LOC_LOGV("length: %d\n data: %p", mLen, mData);
}
inline virtual void log() const {
locallog();
}
};
struct LocEngSetXtraVersionCheck : public LocMsg {
LocEngAdapter *mAdapter;
int mCheck;
inline LocEngSetXtraVersionCheck(LocEngAdapter* adapter,
int check):
mAdapter(adapter), mCheck(check) {}
inline virtual void proc() const {
locallog();
mAdapter->setXtraVersionCheck(mCheck);
}
inline void locallog() const {
LOC_LOGD("%s:%d]: mCheck: %d",
__func__, __LINE__, mCheck);
}
inline virtual void log() const {
locallog();
}
};
/*===========================================================================
FUNCTION loc_eng_xtra_init
DESCRIPTION
Initialize XTRA module.
DEPENDENCIES
N/A
RETURN VALUE
0: success
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_xtra_init (loc_eng_data_s_type &loc_eng_data,
GpsXtraExtCallbacks* callbacks)
{
int ret_val = -1;
loc_eng_xtra_data_s_type *xtra_module_data_ptr;
ENTRY_LOG();
if(!loc_eng_data.adapter->mSupportsTimeInjection
|| loc_eng_data.adapter->hasNativeXtraClient()) {
LOC_LOGD("XTRA is already supported. disable it here.\n");
EXIT_LOG(%d, 1); // return 1 denote failure
return 1;
}
if(callbacks == NULL) {
LOC_LOGE("loc_eng_xtra_init: failed, cb is NULL");
} else {
xtra_module_data_ptr = &loc_eng_data.xtra_module_data;
xtra_module_data_ptr->download_request_cb = callbacks->download_request_cb;
xtra_module_data_ptr->report_xtra_server_cb = callbacks->report_xtra_server_cb;
ret_val = 0;
}
EXIT_LOG(%d, ret_val);
return ret_val;
}
/*===========================================================================
FUNCTION loc_eng_xtra_inject_data
DESCRIPTION
Injects XTRA file into the engine but buffers the data if engine is busy.
DEPENDENCIES
N/A
RETURN VALUE
0
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_xtra_inject_data(loc_eng_data_s_type &loc_eng_data,
char* data, int length)
{
ENTRY_LOG();
LocEngAdapter* adapter = loc_eng_data.adapter;
adapter->sendMsg(new LocEngInjectXtraData(adapter, data, length));
EXIT_LOG(%d, 0);
return 0;
}
/*===========================================================================
FUNCTION loc_eng_xtra_request_server
DESCRIPTION
Request the Xtra server url from the modem
DEPENDENCIES
N/A
RETURN VALUE
0
SIDE EFFECTS
N/A
===========================================================================*/
int loc_eng_xtra_request_server(loc_eng_data_s_type &loc_eng_data)
{
ENTRY_LOG();
LocEngAdapter* adapter = loc_eng_data.adapter;
adapter->sendMsg(new LocEngRequestXtraServer(adapter));
EXIT_LOG(%d, 0);
return 0;
}
/*===========================================================================
FUNCTION loc_eng_xtra_version_check
DESCRIPTION
Injects the enable/disable value for checking XTRA version
that is specified in gps.conf
DEPENDENCIES
N/A
RETURN VALUE
none
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_xtra_version_check(loc_eng_data_s_type &loc_eng_data,
int check)
{
ENTRY_LOG();
LocEngAdapter *adapter = loc_eng_data.adapter;
adapter->sendMsg(new LocEngSetXtraVersionCheck(adapter, check));
EXIT_LOG(%d, 0);
}

View File

@@ -0,0 +1,47 @@
/* Copyright (c) 2009,2011 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
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_XTRA_H
#define LOC_ENG_XTRA_H
#include <hardware/gps.h>
// Module data
typedef struct
{
// loc_eng_ioctl_cb_data_s_type ioctl_cb_data;
gps_xtra_download_request download_request_cb;
report_xtra_server report_xtra_server_cb;
// XTRA data buffer
char *xtra_data_for_injection; // NULL if no pending data
int xtra_data_len;
} loc_eng_xtra_data_s_type;
#endif // LOC_ENG_XTRA_H