| /* 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 Foundatoin, 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_NDEBUG 0 |
| #define LOG_TAG "LocSvc_ApiV02" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <math.h> |
| |
| #include <hardware/gps.h> |
| |
| #ifndef USE_GLIB |
| #include <utils/SystemClock.h> |
| #endif /* USE_GLIB */ |
| #include <LocApiV02.h> |
| #include <loc_api_v02_log.h> |
| #include <loc_api_sync_req.h> |
| #include <loc_util_log.h> |
| #include <gps_extended.h> |
| #include "platform_lib_includes.h" |
| |
| using namespace loc_core; |
| |
| /* Default session id ; TBD needs incrementing for each */ |
| #define LOC_API_V02_DEF_SESSION_ID (1) |
| |
| /* UMTS CP Address key*/ |
| #define LOC_NI_NOTIF_KEY_ADDRESS "Address" |
| |
| /* GPS SV Id offset */ |
| #define GPS_SV_ID_OFFSET (1) |
| |
| /* GLONASS SV Id offset */ |
| #define GLONASS_SV_ID_OFFSET (65) |
| |
| /* SV ID range */ |
| #define SV_ID_RANGE (32) |
| |
| #define BDS_SV_ID_OFFSET (201) |
| |
| /* BeiDou SV ID RANGE*/ |
| #define BDS_SV_ID_RANGE QMI_LOC_DELETE_MAX_BDS_SV_INFO_LENGTH_V02 |
| |
| /* GPS week unknown*/ |
| #define C_GPS_WEEK_UNKNOWN (65535) |
| |
| /* seconds per week*/ |
| #define WEEK_MSECS (60*60*24*7*1000) |
| |
| /* static event callbacks that call the LocApiV02 callbacks*/ |
| |
| /* global event callback, call the eventCb function in loc api adapter v02 |
| instance */ |
| static void globalEventCb(locClientHandleType clientHandle, |
| uint32_t eventId, |
| const locClientEventIndUnionType eventPayload, |
| void* pClientCookie) |
| { |
| MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(eventId)); |
| LocApiV02 *locApiV02Instance = |
| (LocApiV02 *)pClientCookie; |
| |
| LOC_LOGV ("%s:%d] client = %p, event id = %d, client cookie ptr = %p\n", |
| __func__, __LINE__, clientHandle, eventId, pClientCookie); |
| |
| // return if null is passed |
| if( NULL == locApiV02Instance) |
| { |
| LOC_LOGE ("%s:%d] NULL object passed : client = %p, event id = %d\n", |
| __func__, __LINE__, clientHandle, eventId); |
| return; |
| } |
| locApiV02Instance->eventCb(clientHandle, eventId, eventPayload); |
| } |
| |
| /* global response callback, it calls the sync request process |
| indication function to unblock the request that is waiting on this |
| response indication*/ |
| static void globalRespCb(locClientHandleType clientHandle, |
| uint32_t respId, |
| const locClientRespIndUnionType respPayload, |
| void* pClientCookie) |
| { |
| MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(respId)); |
| LocApiV02 *locApiV02Instance = |
| (LocApiV02 *)pClientCookie; |
| |
| |
| LOC_LOGV ("%s:%d] client = %p, resp id = %d, client cookie ptr = %p\n", |
| __func__, __LINE__, clientHandle, respId, pClientCookie); |
| |
| if( NULL == locApiV02Instance) |
| { |
| LOC_LOGE ("%s:%d] NULL object passed : client = %p, resp id = %d\n", |
| __func__, __LINE__, clientHandle, respId); |
| return; |
| } |
| // process the sync call |
| // use pDeleteAssistDataInd as a dummy pointer |
| loc_sync_process_ind(clientHandle, respId, |
| (void *)respPayload.pDeleteAssistDataInd); |
| } |
| |
| /* global error callback, it will call the handle service down |
| function in the loc api adapter instance. */ |
| static void globalErrorCb (locClientHandleType clientHandle, |
| locClientErrorEnumType errorId, |
| void *pClientCookie) |
| { |
| LocApiV02 *locApiV02Instance = |
| (LocApiV02 *)pClientCookie; |
| |
| LOC_LOGV ("%s:%d] client = %p, error id = %d\n, client cookie ptr = %p\n", |
| __func__, __LINE__, clientHandle, errorId, pClientCookie); |
| if( NULL == locApiV02Instance) |
| { |
| LOC_LOGE ("%s:%d] NULL object passed : client = %p, error id = %d\n", |
| __func__, __LINE__, clientHandle, errorId); |
| return; |
| } |
| locApiV02Instance->errorCb(clientHandle, errorId); |
| } |
| |
| /* global structure containing the callbacks */ |
| locClientCallbacksType globalCallbacks = |
| { |
| sizeof(locClientCallbacksType), |
| globalEventCb, |
| globalRespCb, |
| globalErrorCb |
| }; |
| |
| /* Constructor for LocApiV02 */ |
| LocApiV02 :: LocApiV02(const MsgTask* msgTask, |
| LOC_API_ADAPTER_EVENT_MASK_T exMask, |
| ContextBase* context): |
| LocApiBase(msgTask, exMask, context), |
| clientHandle(LOC_CLIENT_INVALID_HANDLE_VALUE), |
| dsClientHandle(NULL), mGnssMeasurementSupported(sup_unknown), |
| mQmiMask(0), mInSession(false), mEngineOn(false) |
| { |
| // initialize loc_sync_req interface |
| loc_sync_req_init(); |
| } |
| |
| /* Destructor for LocApiV02 */ |
| LocApiV02 :: ~LocApiV02() |
| { |
| close(); |
| } |
| |
| LocApiBase* getLocApi(const MsgTask *msgTask, |
| LOC_API_ADAPTER_EVENT_MASK_T exMask, |
| ContextBase* context) |
| { |
| LOC_LOGD("%s:%d]: Creating new LocApiV02", __func__, __LINE__); |
| return new LocApiV02(msgTask, exMask, context); |
| } |
| |
| /* Initialize a loc api v02 client */ |
| enum loc_api_adapter_err |
| LocApiV02 :: open(LOC_API_ADAPTER_EVENT_MASK_T mask) |
| { |
| enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS; |
| LOC_API_ADAPTER_EVENT_MASK_T newMask = mMask | (mask & ~mExcludedMask); |
| locClientEventMaskType qmiMask = convertMask(newMask); |
| LOC_LOGD("%s:%d]: Enter mMask: %x; mask: %x; newMask: %x mQmiMask: %lld qmiMask: %lld", |
| __func__, __LINE__, mMask, mask, newMask, mQmiMask, qmiMask); |
| /* If the client is already open close it first */ |
| if(LOC_CLIENT_INVALID_HANDLE_VALUE == clientHandle) |
| { |
| locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; |
| |
| LOC_LOGV ("%s:%d]: reference to this = %p passed in \n", |
| __func__, __LINE__, this); |
| /* initialize the loc api v02 interface, note that |
| the locClientOpen() function will block if the |
| service is unavailable for a fixed time out */ |
| |
| // it is important to cap the mask here, because not all LocApi's |
| // can enable the same bits, e.g. foreground and bckground. |
| status = locClientOpen(adjustMaskForNoSession(qmiMask), &globalCallbacks, |
| &clientHandle, (void *)this); |
| mMask = newMask; |
| mQmiMask = qmiMask; |
| if (eLOC_CLIENT_SUCCESS != status || |
| clientHandle == LOC_CLIENT_INVALID_HANDLE_VALUE ) |
| { |
| mMask = 0; |
| mQmiMask = 0; |
| LOC_LOGE ("%s:%d]: locClientOpen failed, status = %s\n", __func__, |
| __LINE__, loc_get_v02_client_status_name(status)); |
| rtv = LOC_API_ADAPTER_ERR_FAILURE; |
| } |
| } else if (newMask != mMask) { |
| // it is important to cap the mask here, because not all LocApi's |
| // can enable the same bits, e.g. foreground and bckground. |
| if (!registerEventMask(qmiMask)) { |
| // we do not update mMask here, because it did not change |
| // as the mask update has failed. |
| rtv = LOC_API_ADAPTER_ERR_FAILURE; |
| } |
| else { |
| mMask = newMask; |
| mQmiMask = qmiMask; |
| } |
| } |
| LOC_LOGD("%s:%d]: Exit mMask: %x; mask: %x mQmiMask: %llx qmiMask: %llx", |
| __func__, __LINE__, mMask, mask, mQmiMask, qmiMask); |
| |
| if (LOC_API_ADAPTER_ERR_SUCCESS == rtv) { |
| cacheGnssMeasurementSupport(); |
| } |
| |
| return rtv; |
| } |
| |
| bool LocApiV02 :: registerEventMask(locClientEventMaskType qmiMask) |
| { |
| if (!mInSession) { |
| qmiMask = adjustMaskForNoSession(qmiMask); |
| } |
| LOC_LOGD("%s:%d]: mQmiMask=%lld qmiMask=%lld", |
| __func__, __LINE__, mQmiMask, qmiMask); |
| return locClientRegisterEventMask(clientHandle, qmiMask); |
| } |
| |
| locClientEventMaskType LocApiV02 :: adjustMaskForNoSession(locClientEventMaskType qmiMask) |
| { |
| LOC_LOGD("%s:%d]: before qmiMask=%lld", |
| __func__, __LINE__, qmiMask); |
| locClientEventMaskType clearMask = QMI_LOC_EVENT_MASK_POSITION_REPORT_V02 | |
| QMI_LOC_EVENT_MASK_GNSS_SV_INFO_V02 | |
| QMI_LOC_EVENT_MASK_NMEA_V02 | |
| QMI_LOC_EVENT_MASK_ENGINE_STATE_V02 | |
| QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02; |
| |
| qmiMask = qmiMask & ~clearMask; |
| LOC_LOGD("%s:%d]: after qmiMask=%lld", |
| __func__, __LINE__, qmiMask); |
| return qmiMask; |
| } |
| |
| enum loc_api_adapter_err LocApiV02 :: close() |
| { |
| enum loc_api_adapter_err rtv = |
| // success if either client is already invalid, or |
| // we successfully close the handle |
| (LOC_CLIENT_INVALID_HANDLE_VALUE == clientHandle || |
| eLOC_CLIENT_SUCCESS == locClientClose(&clientHandle)) ? |
| LOC_API_ADAPTER_ERR_SUCCESS : LOC_API_ADAPTER_ERR_FAILURE; |
| |
| mMask = 0; |
| clientHandle = LOC_CLIENT_INVALID_HANDLE_VALUE; |
| |
| return rtv; |
| } |
| |
| /* start positioning session */ |
| enum loc_api_adapter_err LocApiV02 :: startFix(const LocPosMode& fixCriteria) |
| { |
| locClientStatusEnumType status; |
| locClientReqUnionType req_union; |
| |
| qmiLocStartReqMsgT_v02 start_msg; |
| |
| qmiLocSetOperationModeReqMsgT_v02 set_mode_msg; |
| qmiLocSetOperationModeIndMsgT_v02 set_mode_ind; |
| |
| // clear all fields, validity masks |
| memset (&start_msg, 0, sizeof(start_msg)); |
| memset (&set_mode_msg, 0, sizeof(set_mode_msg)); |
| memset (&set_mode_ind, 0, sizeof(set_mode_ind)); |
| |
| LOC_LOGV("%s:%d]: start \n", __func__, __LINE__); |
| fixCriteria.logv(); |
| |
| mInSession = true; |
| registerEventMask(mQmiMask); |
| |
| // fill in the start request |
| switch(fixCriteria.mode) |
| { |
| case LOC_POSITION_MODE_MS_BASED: |
| set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSB_V02; |
| break; |
| |
| case LOC_POSITION_MODE_MS_ASSISTED: |
| set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSA_V02; |
| break; |
| |
| case LOC_POSITION_MODE_RESERVED_4: |
| set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_CELL_ID_V02; |
| break; |
| |
| case LOC_POSITION_MODE_RESERVED_5: |
| set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_WWAN_V02; |
| break; |
| |
| default: |
| set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_STANDALONE_V02; |
| break; |
| } |
| |
| req_union.pSetOperationModeReq = &set_mode_msg; |
| |
| // send the mode first, before the start message. |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_OPERATION_MODE_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_OPERATION_MODE_IND_V02, |
| &set_mode_ind); // NULL? |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != set_mode_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: set opertion mode failed status = %s, " |
| "ind..status = %s\n", __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(set_mode_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; // error |
| } |
| |
| start_msg.minInterval_valid = 1; |
| start_msg.minInterval = fixCriteria.min_interval; |
| |
| if (fixCriteria.preferred_accuracy >= 0) { |
| start_msg.horizontalAccuracyLevel_valid = 1; |
| |
| if (fixCriteria.preferred_accuracy <= 100) |
| { |
| // fix needs high accuracy |
| start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_HIGH_V02; |
| } |
| else if (fixCriteria.preferred_accuracy <= 1000) |
| { |
| //fix needs med accuracy |
| start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_MED_V02; |
| } |
| else |
| { |
| //fix needs low accuracy |
| start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_LOW_V02; |
| } |
| } |
| |
| start_msg.fixRecurrence_valid = 1; |
| if(GPS_POSITION_RECURRENCE_SINGLE == fixCriteria.recurrence) |
| { |
| start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_SINGLE_V02; |
| } |
| else |
| { |
| start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_PERIODIC_V02; |
| } |
| |
| //dummy session id |
| // TBD: store session ID, check for session id in pos reports. |
| start_msg.sessionId = LOC_API_V02_DEF_SESSION_ID; |
| |
| if (fixCriteria.credentials[0] != 0) { |
| int size1 = sizeof(start_msg.applicationId.applicationName); |
| int size2 = sizeof(fixCriteria.credentials); |
| int len = ((size1 < size2) ? size1 : size2) - 1; |
| memcpy(start_msg.applicationId.applicationName, |
| fixCriteria.credentials, |
| len); |
| |
| size1 = sizeof(start_msg.applicationId.applicationProvider); |
| size2 = sizeof(fixCriteria.provider); |
| len = ((size1 < size2) ? size1 : size2) - 1; |
| memcpy(start_msg.applicationId.applicationProvider, |
| fixCriteria.provider, |
| len); |
| |
| start_msg.applicationId_valid = 1; |
| } |
| |
| // config Altitude Assumed |
| start_msg.configAltitudeAssumed_valid = 1; |
| start_msg.configAltitudeAssumed = eQMI_LOC_ALTITUDE_ASSUMED_IN_GNSS_SV_INFO_DISABLED_V02; |
| |
| req_union.pStartReq = &start_msg; |
| |
| status = locClientSendReq (clientHandle, QMI_LOC_START_REQ_V02, |
| req_union ); |
| |
| if( eLOC_CLIENT_SUCCESS == status) |
| { |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| /* stop a positioning session */ |
| enum loc_api_adapter_err LocApiV02 :: stopFix() |
| { |
| locClientStatusEnumType status; |
| locClientReqUnionType req_union; |
| |
| qmiLocStopReqMsgT_v02 stop_msg; |
| |
| LOC_LOGD(" %s:%d]: stop called \n", __func__, __LINE__); |
| |
| memset(&stop_msg, 0, sizeof(stop_msg)); |
| |
| // dummy session id |
| stop_msg.sessionId = LOC_API_V02_DEF_SESSION_ID; |
| |
| req_union.pStopReq = &stop_msg; |
| |
| status = locClientSendReq(clientHandle, |
| QMI_LOC_STOP_REQ_V02, |
| req_union); |
| |
| mInSession = false; |
| // if engine on never happend, deregister events |
| // without waiting for Engine Off |
| if (!mEngineOn) { |
| registerEventMask(mQmiMask); |
| } |
| |
| if( eLOC_CLIENT_SUCCESS == status) |
| { |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| LOC_LOGE("%s:%d]: error = %s\n",__func__, __LINE__, |
| loc_get_v02_client_status_name(status)); |
| return (LOC_API_ADAPTER_ERR_GENERAL_FAILURE); |
| } |
| |
| /* set the positioning fix criteria */ |
| enum loc_api_adapter_err LocApiV02 :: setPositionMode( |
| const LocPosMode& posMode) |
| { |
| if(isInSession()) |
| { |
| //fix is in progress, send a restart |
| LOC_LOGD ("%s:%d]: fix is in progress restarting the fix with new " |
| "criteria\n", __func__, __LINE__); |
| |
| return( startFix(posMode)); |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* inject time into the position engine */ |
| enum loc_api_adapter_err LocApiV02 :: |
| setTime(GpsUtcTime time, int64_t timeReference, int uncertainty) |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocInjectUtcTimeReqMsgT_v02 inject_time_msg; |
| qmiLocInjectUtcTimeIndMsgT_v02 inject_time_ind; |
| |
| memset(&inject_time_msg, 0, sizeof(inject_time_msg)); |
| |
| inject_time_ind.status = eQMI_LOC_GENERAL_FAILURE_V02; |
| |
| inject_time_msg.timeUtc = time; |
| |
| inject_time_msg.timeUtc += (int64_t)(ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION - timeReference); |
| |
| inject_time_msg.timeUnc = uncertainty; |
| |
| req_union.pInjectUtcTimeReq = &inject_time_msg; |
| |
| LOC_LOGV ("%s:%d]: uncertainty = %d\n", __func__, __LINE__, |
| uncertainty); |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_INJECT_UTC_TIME_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INJECT_UTC_TIME_IND_V02, |
| &inject_time_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != inject_time_ind.status) |
| { |
| LOC_LOGE ("%s:%d] status = %s, ind..status = %s\n", __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(inject_time_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* inject position into the position engine */ |
| enum loc_api_adapter_err LocApiV02 :: |
| injectPosition(double latitude, double longitude, float accuracy) |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocInjectPositionReqMsgT_v02 inject_pos_msg; |
| qmiLocInjectPositionIndMsgT_v02 inject_pos_ind; |
| |
| memset(&inject_pos_msg, 0, sizeof(inject_pos_msg)); |
| |
| inject_pos_msg.latitude_valid = 1; |
| inject_pos_msg.latitude = latitude; |
| |
| inject_pos_msg.longitude_valid = 1; |
| inject_pos_msg.longitude = longitude; |
| |
| inject_pos_msg.horUncCircular_valid = 1; |
| |
| inject_pos_msg.horUncCircular = accuracy; //meters assumed |
| |
| inject_pos_msg.horConfidence_valid = 1; |
| |
| inject_pos_msg.horConfidence = 63; // 63% (1 std dev assumed) |
| |
| /* Log */ |
| LOC_LOGD("%s:%d]: Lat=%lf, Lon=%lf, Acc=%.2lf\n", __func__, __LINE__, |
| inject_pos_msg.latitude, inject_pos_msg.longitude, |
| inject_pos_msg.horUncCircular); |
| |
| req_union.pInjectPositionReq = &inject_pos_msg; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_INJECT_POSITION_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INJECT_POSITION_IND_V02, |
| &inject_pos_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != inject_pos_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: error! status = %s, inject_pos_ind.status = %s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(inject_pos_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* delete assistance date */ |
| enum loc_api_adapter_err LocApiV02 :: deleteAidingData(GpsAidingData f) |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocDeleteAssistDataReqMsgT_v02 delete_req; |
| qmiLocDeleteAssistDataIndMsgT_v02 delete_resp; |
| |
| memset(&delete_req, 0, sizeof(delete_req)); |
| memset(&delete_resp, 0, sizeof(delete_resp)); |
| |
| if( f == GPS_DELETE_ALL ) |
| { |
| delete_req.deleteAllFlag = true; |
| } |
| |
| else |
| { |
| /* to keep track of svInfoList for GPS and GLO*/ |
| uint32_t curr_sv_len = 0; |
| uint32_t curr_sv_idx = 0; |
| uint32_t sv_id = 0; |
| |
| if((f & GPS_DELETE_EPHEMERIS ) || ( f & GPS_DELETE_ALMANAC )) |
| { |
| /* do delete for all GPS SV's */ |
| |
| curr_sv_len += SV_ID_RANGE; |
| |
| sv_id = GPS_SV_ID_OFFSET; |
| |
| delete_req.deleteSvInfoList_valid = 1; |
| |
| delete_req.deleteSvInfoList_len = curr_sv_len; |
| |
| LOC_LOGV("%s:%d]: Delete GPS SV info for index %d to %d" |
| "and sv id %d to %d \n", |
| __func__, __LINE__, curr_sv_idx, curr_sv_len - 1, |
| sv_id, sv_id+SV_ID_RANGE); |
| |
| for( uint32_t i = curr_sv_idx; i< curr_sv_len ; i++, sv_id++ ) |
| { |
| delete_req.deleteSvInfoList[i].gnssSvId = sv_id; |
| |
| delete_req.deleteSvInfoList[i].system = eQMI_LOC_SV_SYSTEM_GPS_V02; |
| |
| if(f & GPS_DELETE_EPHEMERIS ) |
| { |
| // set ephemeris mask for all GPS SV's |
| delete_req.deleteSvInfoList[i].deleteSvInfoMask |= |
| QMI_LOC_MASK_DELETE_EPHEMERIS_V02; |
| } |
| |
| if( f & GPS_DELETE_ALMANAC ) |
| { |
| delete_req.deleteSvInfoList[i].deleteSvInfoMask |= |
| QMI_LOC_MASK_DELETE_ALMANAC_V02; |
| } |
| } |
| // increment the current index |
| curr_sv_idx += SV_ID_RANGE; |
| |
| } |
| |
| if( f & GPS_DELETE_TIME_GPS ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GPS_TIME_V02; |
| } |
| |
| if(f & GPS_DELETE_POSITION ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_POSITION_V02; |
| } |
| |
| if(f & GPS_DELETE_TIME ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_TIME_V02; |
| } |
| |
| if(f & GPS_DELETE_IONO ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_IONO_V02; |
| } |
| |
| if(f & GPS_DELETE_UTC ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_UTC_V02; |
| } |
| |
| if(f & GPS_DELETE_HEALTH ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_HEALTH_V02; |
| } |
| |
| if(f & GPS_DELETE_SVDIR ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GPS_SVDIR_V02; |
| } |
| if(f & GPS_DELETE_SADATA ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_SADATA_V02; |
| } |
| if(f & GPS_DELETE_RTI ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_RTI_V02; |
| } |
| if(f & GPS_DELETE_CELLDB_INFO ) |
| { |
| delete_req.deleteCellDbDataMask_valid = 1; |
| delete_req.deleteCellDbDataMask = |
| ( QMI_LOC_MASK_DELETE_CELLDB_POS_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_LATEST_GPS_POS_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_OTA_POS_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_EXT_REF_POS_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_TIMETAG_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_CELLID_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_CACHED_CELLID_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_LAST_SRV_CELL_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_CUR_SRV_CELL_V02 | |
| QMI_LOC_MASK_DELETE_CELLDB_NEIGHBOR_INFO_V02) ; |
| |
| } |
| if(f & GPS_DELETE_ALMANAC_CORR ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GPS_ALM_CORR_V02; |
| } |
| if(f & GPS_DELETE_FREQ_BIAS_EST ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_FREQ_BIAS_EST_V02; |
| } |
| if ( (f & GPS_DELETE_EPHEMERIS_GLO ) || (f & GPS_DELETE_ALMANAC_GLO )) |
| { |
| /* do delete for all GLONASS SV's (65 - 96) |
| */ |
| curr_sv_len += SV_ID_RANGE; |
| |
| sv_id = GLONASS_SV_ID_OFFSET; |
| |
| delete_req.deleteSvInfoList_valid = 1; |
| |
| delete_req.deleteSvInfoList_len = curr_sv_len; |
| |
| LOC_LOGV("%s:%d]: Delete GLO SV info for index %d to %d" |
| "and sv id %d to %d \n", |
| __func__, __LINE__, curr_sv_idx, curr_sv_len - 1, |
| sv_id, sv_id+SV_ID_RANGE); |
| |
| |
| for( uint32_t i = curr_sv_idx; i< curr_sv_len ; i++, sv_id++ ) |
| { |
| delete_req.deleteSvInfoList[i].gnssSvId = sv_id; |
| |
| delete_req.deleteSvInfoList[i].system = eQMI_LOC_SV_SYSTEM_GLONASS_V02; |
| |
| if(f & GPS_DELETE_EPHEMERIS ) |
| { |
| // set ephemeris mask for all GPS SV's |
| delete_req.deleteSvInfoList[i].deleteSvInfoMask |= |
| QMI_LOC_MASK_DELETE_EPHEMERIS_V02; |
| } |
| |
| if( f & GPS_DELETE_ALMANAC ) |
| { |
| delete_req.deleteSvInfoList[i].deleteSvInfoMask |= |
| QMI_LOC_MASK_DELETE_ALMANAC_V02; |
| } |
| } |
| curr_sv_idx += SV_ID_RANGE; |
| } |
| |
| if(f & GPS_DELETE_SVDIR_GLO ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GLO_SVDIR_V02; |
| } |
| |
| if(f & GPS_DELETE_SVSTEER_GLO ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GLO_SVSTEER_V02; |
| } |
| |
| if(f & GPS_DELETE_ALMANAC_CORR_GLO ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GLO_ALM_CORR_V02; |
| } |
| |
| if(f & GPS_DELETE_TIME_GLO ) |
| { |
| delete_req.deleteGnssDataMask_valid = 1; |
| delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GLO_TIME_V02; |
| } |
| } |
| |
| req_union.pDeleteAssistDataReq = &delete_req; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_DELETE_ASSIST_DATA_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_DELETE_ASSIST_DATA_IND_V02, |
| &delete_resp); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != delete_resp.status) |
| { |
| LOC_LOGE ("%s:%d]: error! status = %s, delete_resp.status = %s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(delete_resp.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* send NI user repsonse to the engine */ |
| enum loc_api_adapter_err LocApiV02 :: |
| informNiResponse(GpsUserResponseType userResponse, |
| const void* passThroughData) |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| |
| qmiLocNiUserRespReqMsgT_v02 ni_resp; |
| qmiLocNiUserRespIndMsgT_v02 ni_resp_ind; |
| |
| qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *request_pass_back = |
| (qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *)passThroughData; |
| |
| memset(&ni_resp,0, sizeof(ni_resp)); |
| |
| memset(&ni_resp_ind,0, sizeof(ni_resp_ind)); |
| |
| switch (userResponse) |
| { |
| case GPS_NI_RESPONSE_ACCEPT: |
| ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT_V02; |
| break; |
| case GPS_NI_RESPONSE_DENY: |
| ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_DENY_V02; |
| break; |
| case GPS_NI_RESPONSE_NORESP: |
| ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_NORESP_V02; |
| break; |
| default: |
| return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; |
| } |
| |
| LOC_LOGV(" %s:%d]: NI response: %d\n", __func__, __LINE__, |
| ni_resp.userResp); |
| |
| ni_resp.notificationType = request_pass_back->notificationType; |
| |
| // copy SUPL payload from request |
| if(request_pass_back->NiSuplInd_valid == 1) |
| { |
| ni_resp.NiSuplPayload_valid = 1; |
| memcpy(&(ni_resp.NiSuplPayload), &(request_pass_back->NiSuplInd), |
| sizeof(qmiLocNiSuplNotifyVerifyStructT_v02)); |
| |
| } |
| // should this be an "else if"?? we don't need to decide |
| |
| // copy UMTS-CP payload from request |
| if( request_pass_back->NiUmtsCpInd_valid == 1 ) |
| { |
| ni_resp.NiUmtsCpPayload_valid = 1; |
| memcpy(&(ni_resp.NiUmtsCpPayload), &(request_pass_back->NiUmtsCpInd), |
| sizeof(qmiLocNiUmtsCpNotifyVerifyStructT_v02)); |
| } |
| |
| //copy Vx payload from the request |
| if( request_pass_back->NiVxInd_valid == 1) |
| { |
| ni_resp.NiVxPayload_valid = 1; |
| memcpy(&(ni_resp.NiVxPayload), &(request_pass_back->NiVxInd), |
| sizeof(qmiLocNiVxNotifyVerifyStructT_v02)); |
| } |
| |
| // copy Vx service interaction payload from the request |
| if(request_pass_back->NiVxServiceInteractionInd_valid == 1) |
| { |
| ni_resp.NiVxServiceInteractionPayload_valid = 1; |
| memcpy(&(ni_resp.NiVxServiceInteractionPayload), |
| &(request_pass_back->NiVxServiceInteractionInd), |
| sizeof(qmiLocNiVxServiceInteractionStructT_v02)); |
| } |
| |
| // copy Network Initiated SUPL Version 2 Extension |
| if (request_pass_back->NiSuplVer2ExtInd_valid == 1) |
| { |
| ni_resp.NiSuplVer2ExtPayload_valid = 1; |
| memcpy(&(ni_resp.NiSuplVer2ExtPayload), |
| &(request_pass_back->NiSuplVer2ExtInd), |
| sizeof(qmiLocNiSuplVer2ExtStructT_v02)); |
| } |
| |
| // copy SUPL Emergency Notification |
| if(request_pass_back->suplEmergencyNotification_valid) |
| { |
| ni_resp.suplEmergencyNotification_valid = 1; |
| memcpy(&(ni_resp.suplEmergencyNotification), |
| &(request_pass_back->suplEmergencyNotification), |
| sizeof(qmiLocEmergencyNotificationStructT_v02)); |
| } |
| |
| req_union.pNiUserRespReq = &ni_resp; |
| |
| status = loc_sync_send_req ( |
| clientHandle, QMI_LOC_NI_USER_RESPONSE_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_NI_USER_RESPONSE_IND_V02, &ni_resp_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != ni_resp_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: error! status = %s, ni_resp_ind.status = %s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(ni_resp_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* Set UMTs SLP server URL */ |
| enum loc_api_adapter_err LocApiV02 :: setServer( |
| const char* url, int len) |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocSetServerReqMsgT_v02 set_server_req; |
| qmiLocSetServerIndMsgT_v02 set_server_ind; |
| |
| if(len < 0 || len > sizeof(set_server_req.urlAddr)) |
| { |
| LOC_LOGE("%s:%d]: len = %d greater than max allowed url length\n", |
| __func__, __LINE__, len); |
| |
| return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; |
| } |
| |
| memset(&set_server_req, 0, sizeof(set_server_req)); |
| |
| LOC_LOGD("%s:%d]:, url = %s, len = %d\n", __func__, __LINE__, url, len); |
| |
| set_server_req.serverType = eQMI_LOC_SERVER_TYPE_UMTS_SLP_V02; |
| |
| set_server_req.urlAddr_valid = 1; |
| |
| strlcpy(set_server_req.urlAddr, url, sizeof(set_server_req.urlAddr)); |
| |
| req_union.pSetServerReq = &set_server_req; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_SERVER_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_SERVER_IND_V02, |
| &set_server_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != set_server_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: error status = %s, set_server_ind.status = %s\n", |
| __func__,__LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(set_server_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| enum loc_api_adapter_err LocApiV02 :: |
| setServer(unsigned int ip, int port, LocServerType type) |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocSetServerReqMsgT_v02 set_server_req; |
| qmiLocSetServerIndMsgT_v02 set_server_ind; |
| qmiLocServerTypeEnumT_v02 set_server_cmd; |
| |
| switch (type) { |
| case LOC_AGPS_MPC_SERVER: |
| set_server_cmd = eQMI_LOC_SERVER_TYPE_CDMA_MPC_V02; |
| break; |
| case LOC_AGPS_CUSTOM_PDE_SERVER: |
| set_server_cmd = eQMI_LOC_SERVER_TYPE_CUSTOM_PDE_V02; |
| break; |
| default: |
| set_server_cmd = eQMI_LOC_SERVER_TYPE_CDMA_PDE_V02; |
| break; |
| } |
| |
| memset(&set_server_req, 0, sizeof(set_server_req)); |
| |
| LOC_LOGD("%s:%d]:, ip = %u, port = %d\n", __func__, __LINE__, ip, port); |
| |
| set_server_req.serverType = set_server_cmd; |
| set_server_req.ipv4Addr_valid = 1; |
| set_server_req.ipv4Addr.addr = ip; |
| set_server_req.ipv4Addr.port = port; |
| |
| req_union.pSetServerReq = &set_server_req; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_SERVER_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_SERVER_IND_V02, |
| &set_server_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != set_server_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: error status = %s, set_server_ind.status = %s\n", |
| __func__,__LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(set_server_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* Inject XTRA data, this module breaks down the XTRA |
| file into "chunks" and injects them one at a time */ |
| enum loc_api_adapter_err LocApiV02 :: setXtraData( |
| char* data, int length) |
| { |
| locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; |
| int total_parts; |
| uint8_t part; |
| uint16_t len_injected; |
| |
| locClientReqUnionType req_union; |
| qmiLocInjectPredictedOrbitsDataReqMsgT_v02 inject_xtra; |
| qmiLocInjectPredictedOrbitsDataIndMsgT_v02 inject_xtra_ind; |
| |
| req_union.pInjectPredictedOrbitsDataReq = &inject_xtra; |
| |
| LOC_LOGD("%s:%d]: xtra size = %d\n", __func__, __LINE__, length); |
| |
| inject_xtra.formatType_valid = 1; |
| inject_xtra.formatType = eQMI_LOC_PREDICTED_ORBITS_XTRA_V02; |
| inject_xtra.totalSize = length; |
| |
| total_parts = ((length - 1) / QMI_LOC_MAX_PREDICTED_ORBITS_PART_LEN_V02) + 1; |
| |
| inject_xtra.totalParts = total_parts; |
| |
| len_injected = 0; // O bytes injected |
| |
| // XTRA injection starts with part 1 |
| for (part = 1; part <= total_parts; part++) |
| { |
| inject_xtra.partNum = part; |
| |
| if (QMI_LOC_MAX_PREDICTED_ORBITS_PART_LEN_V02 > (length - len_injected)) |
| { |
| inject_xtra.partData_len = length - len_injected; |
| } |
| else |
| { |
| inject_xtra.partData_len = QMI_LOC_MAX_PREDICTED_ORBITS_PART_LEN_V02; |
| } |
| |
| // copy data into the message |
| memcpy(inject_xtra.partData, data+len_injected, inject_xtra.partData_len); |
| |
| LOC_LOGD("[%s:%d] part %d/%d, len = %d, total injected = %d\n", |
| __func__, __LINE__, |
| inject_xtra.partNum, total_parts, inject_xtra.partData_len, |
| len_injected); |
| |
| status = loc_sync_send_req( clientHandle, |
| QMI_LOC_INJECT_PREDICTED_ORBITS_DATA_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INJECT_PREDICTED_ORBITS_DATA_IND_V02, |
| &inject_xtra_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != inject_xtra_ind.status || |
| inject_xtra.partNum != inject_xtra_ind.partNum) |
| { |
| LOC_LOGE ("%s:%d]: failed status = %s, inject_pos_ind.status = %s," |
| " part num = %d, ind.partNum = %d\n", __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(inject_xtra_ind.status), |
| inject_xtra.partNum, inject_xtra_ind.partNum); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| break; |
| } |
| |
| len_injected += inject_xtra.partData_len; |
| LOC_LOGD("%s:%d]: XTRA injected length: %d\n", __func__, __LINE__, |
| len_injected); |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* Request the Xtra Server Url from the modem */ |
| enum loc_api_adapter_err LocApiV02 :: requestXtraServer() |
| { |
| locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; |
| |
| locClientReqUnionType req_union; |
| qmiLocGetPredictedOrbitsDataSourceIndMsgT_v02 request_xtra_server_ind; |
| |
| status = loc_sync_send_req( clientHandle, |
| QMI_LOC_GET_PREDICTED_ORBITS_DATA_SOURCE_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_GET_PREDICTED_ORBITS_DATA_SOURCE_IND_V02, |
| &request_xtra_server_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != request_xtra_server_ind.status || |
| false == request_xtra_server_ind.serverList_valid || |
| 0 == request_xtra_server_ind.serverList.serverList_len) |
| { |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| |
| if (request_xtra_server_ind.serverList.serverList_len == 1) |
| { |
| reportXtraServer(request_xtra_server_ind.serverList.serverList[0].serverUrl, |
| "", |
| "", |
| QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); |
| } |
| else if (request_xtra_server_ind.serverList.serverList_len == 2) |
| { |
| reportXtraServer(request_xtra_server_ind.serverList.serverList[0].serverUrl, |
| request_xtra_server_ind.serverList.serverList[1].serverUrl, |
| "", |
| QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); |
| } |
| else |
| { |
| reportXtraServer(request_xtra_server_ind.serverList.serverList[0].serverUrl, |
| request_xtra_server_ind.serverList.serverList[1].serverUrl, |
| request_xtra_server_ind.serverList.serverList[2].serverUrl, |
| QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| enum loc_api_adapter_err LocApiV02 :: atlOpenStatus( |
| int handle, int is_succ, char* apn, AGpsBearerType bear, |
| AGpsType agpsType) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| qmiLocInformLocationServerConnStatusReqMsgT_v02 conn_status_req; |
| qmiLocInformLocationServerConnStatusIndMsgT_v02 conn_status_ind; |
| |
| |
| LOC_LOGD("%s:%d]: ATL open handle = %d, is_succ = %d, " |
| "APN = [%s], bearer = %d \n", __func__, __LINE__, |
| handle, is_succ, apn, bear); |
| |
| memset(&conn_status_req, 0, sizeof(conn_status_req)); |
| memset(&conn_status_ind, 0, sizeof(conn_status_ind)); |
| |
| // Fill in data |
| conn_status_req.connHandle = handle; |
| |
| conn_status_req.requestType = eQMI_LOC_SERVER_REQUEST_OPEN_V02; |
| |
| if(is_succ) |
| { |
| conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02; |
| |
| if(apn != NULL) |
| strlcpy(conn_status_req.apnProfile.apnName, apn, |
| sizeof(conn_status_req.apnProfile.apnName) ); |
| |
| switch(bear) |
| { |
| case AGPS_APN_BEARER_IPV4: |
| conn_status_req.apnProfile.pdnType = |
| eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4_V02; |
| conn_status_req.apnProfile_valid = 1; |
| break; |
| |
| case AGPS_APN_BEARER_IPV6: |
| conn_status_req.apnProfile.pdnType = |
| eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV6_V02; |
| conn_status_req.apnProfile_valid = 1; |
| break; |
| |
| case AGPS_APN_BEARER_IPV4V6: |
| conn_status_req.apnProfile.pdnType = |
| eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4V6_V02; |
| conn_status_req.apnProfile_valid = 1; |
| break; |
| |
| case AGPS_APN_BEARER_INVALID: |
| conn_status_req.apnProfile_valid = 0; |
| break; |
| |
| default: |
| LOC_LOGE("%s:%d]:invalid bearer type\n",__func__,__LINE__); |
| conn_status_req.apnProfile_valid = 0; |
| return LOC_API_ADAPTER_ERR_INVALID_HANDLE; |
| } |
| |
| } |
| else |
| { |
| conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_FAILURE_V02; |
| } |
| |
| req_union.pInformLocationServerConnStatusReq = &conn_status_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_IND_V02, |
| &conn_status_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != conn_status_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(conn_status_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| |
| } |
| |
| |
| /* close atl connection */ |
| enum loc_api_adapter_err LocApiV02 :: atlCloseStatus( |
| int handle, int is_succ) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| qmiLocInformLocationServerConnStatusReqMsgT_v02 conn_status_req; |
| qmiLocInformLocationServerConnStatusIndMsgT_v02 conn_status_ind; |
| |
| LOC_LOGD("%s:%d]: ATL close handle = %d, is_succ = %d\n", |
| __func__, __LINE__, handle, is_succ); |
| |
| memset(&conn_status_req, 0, sizeof(conn_status_req)); |
| memset(&conn_status_ind, 0, sizeof(conn_status_ind)); |
| |
| // Fill in data |
| conn_status_req.connHandle = handle; |
| |
| conn_status_req.requestType = eQMI_LOC_SERVER_REQUEST_CLOSE_V02; |
| |
| if(is_succ) |
| { |
| conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02; |
| } |
| else |
| { |
| conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_FAILURE_V02; |
| } |
| |
| req_union.pInformLocationServerConnStatusReq = &conn_status_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_IND_V02, |
| &conn_status_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != conn_status_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(conn_status_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the SUPL version */ |
| enum loc_api_adapter_err LocApiV02 :: setSUPLVersion(uint32_t version) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| |
| qmiLocSetProtocolConfigParametersReqMsgT_v02 supl_config_req; |
| qmiLocSetProtocolConfigParametersIndMsgT_v02 supl_config_ind; |
| |
| LOC_LOGD("%s:%d]: supl version = %d\n", __func__, __LINE__, version); |
| |
| |
| memset(&supl_config_req, 0, sizeof(supl_config_req)); |
| memset(&supl_config_ind, 0, sizeof(supl_config_ind)); |
| |
| supl_config_req.suplVersion_valid = 1; |
| // SUPL version from MSByte to LSByte: |
| // (reserved)(major version)(minor version)(serviceIndicator) |
| |
| supl_config_req.suplVersion = (version == 0x00020000)? |
| eQMI_LOC_SUPL_VERSION_2_0_V02 : eQMI_LOC_SUPL_VERSION_1_0_V02; |
| |
| req_union.pSetProtocolConfigParametersReq = &supl_config_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02, |
| &supl_config_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != supl_config_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(supl_config_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the configuration for LTE positioning profile (LPP) */ |
| enum loc_api_adapter_err LocApiV02 :: setLPPConfig(uint32_t profile) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| qmiLocSetProtocolConfigParametersReqMsgT_v02 lpp_config_req; |
| qmiLocSetProtocolConfigParametersIndMsgT_v02 lpp_config_ind; |
| |
| LOC_LOGD("%s:%d]: lpp profile = %d\n", __func__, __LINE__, profile); |
| |
| memset(&lpp_config_req, 0, sizeof(lpp_config_req)); |
| memset(&lpp_config_ind, 0, sizeof(lpp_config_ind)); |
| |
| lpp_config_req.lppConfig_valid = 1; |
| |
| lpp_config_req.lppConfig = profile; |
| |
| req_union.pSetProtocolConfigParametersReq = &lpp_config_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02, |
| &lpp_config_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != lpp_config_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(lpp_config_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the Sensor Configuration */ |
| enum loc_api_adapter_err LocApiV02 :: setSensorControlConfig( |
| int sensorsDisabled, int sensorProvider) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| |
| qmiLocSetSensorControlConfigReqMsgT_v02 sensor_config_req; |
| qmiLocSetSensorControlConfigIndMsgT_v02 sensor_config_ind; |
| |
| LOC_LOGD("%s:%d]: sensors disabled = %d\n", __func__, __LINE__, sensorsDisabled); |
| |
| memset(&sensor_config_req, 0, sizeof(sensor_config_req)); |
| memset(&sensor_config_ind, 0, sizeof(sensor_config_ind)); |
| |
| sensor_config_req.sensorsUsage_valid = 1; |
| sensor_config_req.sensorsUsage = (sensorsDisabled == 1) ? eQMI_LOC_SENSOR_CONFIG_SENSOR_USE_DISABLE_V02 |
| : eQMI_LOC_SENSOR_CONFIG_SENSOR_USE_ENABLE_V02; |
| |
| sensor_config_req.sensorProvider_valid = 1; |
| sensor_config_req.sensorProvider = (sensorProvider == 1 || sensorProvider == 4) ? |
| eQMI_LOC_SENSOR_CONFIG_USE_PROVIDER_SSC_V02 : |
| eQMI_LOC_SENSOR_CONFIG_USE_PROVIDER_NATIVE_V02; |
| |
| req_union.pSetSensorControlConfigReq = &sensor_config_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_SENSOR_CONTROL_CONFIG_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_SENSOR_CONTROL_CONFIG_IND_V02, |
| &sensor_config_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != sensor_config_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(sensor_config_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the Sensor Properties */ |
| enum loc_api_adapter_err LocApiV02 :: 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) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| |
| qmiLocSetSensorPropertiesReqMsgT_v02 sensor_prop_req; |
| qmiLocSetSensorPropertiesIndMsgT_v02 sensor_prop_ind; |
| |
| LOC_LOGI("%s:%d]: sensors prop: gyroBiasRandomWalk = %f, accelRandomWalk = %f, " |
| "angleRandomWalk = %f, rateRandomWalk = %f, velocityRandomWalk = %f\n", |
| __func__, __LINE__, gyroBiasVarianceRandomWalk, accelBiasVarianceRandomWalk, |
| angleBiasVarianceRandomWalk, rateBiasVarianceRandomWalk, velocityBiasVarianceRandomWalk); |
| |
| memset(&sensor_prop_req, 0, sizeof(sensor_prop_req)); |
| memset(&sensor_prop_ind, 0, sizeof(sensor_prop_ind)); |
| |
| /* Set the validity bit and value for each sensor property */ |
| sensor_prop_req.gyroBiasVarianceRandomWalk_valid = gyroBiasVarianceRandomWalk_valid; |
| sensor_prop_req.gyroBiasVarianceRandomWalk = gyroBiasVarianceRandomWalk; |
| |
| sensor_prop_req.accelerationRandomWalkSpectralDensity_valid = accelBiasVarianceRandomWalk_valid; |
| sensor_prop_req.accelerationRandomWalkSpectralDensity = accelBiasVarianceRandomWalk; |
| |
| sensor_prop_req.angleRandomWalkSpectralDensity_valid = angleBiasVarianceRandomWalk_valid; |
| sensor_prop_req.angleRandomWalkSpectralDensity = angleBiasVarianceRandomWalk; |
| |
| sensor_prop_req.rateRandomWalkSpectralDensity_valid = rateBiasVarianceRandomWalk_valid; |
| sensor_prop_req.rateRandomWalkSpectralDensity = rateBiasVarianceRandomWalk; |
| |
| sensor_prop_req.velocityRandomWalkSpectralDensity_valid = velocityBiasVarianceRandomWalk_valid; |
| sensor_prop_req.velocityRandomWalkSpectralDensity = velocityBiasVarianceRandomWalk; |
| |
| req_union.pSetSensorPropertiesReq = &sensor_prop_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_SENSOR_PROPERTIES_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_SENSOR_PROPERTIES_IND_V02, |
| &sensor_prop_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != sensor_prop_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(sensor_prop_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the Sensor Performance Config */ |
| enum loc_api_adapter_err LocApiV02 :: setSensorPerfControlConfig(int controlMode, |
| int accelSamplesPerBatch, int accelBatchesPerSec, |
| int gyroSamplesPerBatch, int gyroBatchesPerSec, |
| int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh, |
| int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, |
| int algorithmConfig) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| |
| qmiLocSetSensorPerformanceControlConfigReqMsgT_v02 sensor_perf_config_req; |
| qmiLocSetSensorPerformanceControlConfigIndMsgT_v02 sensor_perf_config_ind; |
| |
| LOC_LOGD("%s:%d]: Sensor Perf Control Config (performanceControlMode)(%u) " |
| "accel(#smp,#batches) (%u,%u) gyro(#smp,#batches) (%u,%u) " |
| "accel_high(#smp,#batches) (%u,%u) gyro_high(#smp,#batches) (%u,%u) " |
| "algorithmConfig(%u)\n", |
| __FUNCTION__, |
| __LINE__, |
| controlMode, |
| accelSamplesPerBatch, |
| accelBatchesPerSec, |
| gyroSamplesPerBatch, |
| gyroBatchesPerSec, |
| accelSamplesPerBatchHigh, |
| accelBatchesPerSecHigh, |
| gyroSamplesPerBatchHigh, |
| gyroBatchesPerSecHigh, |
| algorithmConfig |
| ); |
| |
| memset(&sensor_perf_config_req, 0, sizeof(sensor_perf_config_req)); |
| memset(&sensor_perf_config_ind, 0, sizeof(sensor_perf_config_ind)); |
| |
| sensor_perf_config_req.performanceControlMode_valid = 1; |
| sensor_perf_config_req.performanceControlMode = (qmiLocSensorPerformanceControlModeEnumT_v02)controlMode; |
| sensor_perf_config_req.accelSamplingSpec_valid = 1; |
| sensor_perf_config_req.accelSamplingSpec.batchesPerSecond = accelBatchesPerSec; |
| sensor_perf_config_req.accelSamplingSpec.samplesPerBatch = accelSamplesPerBatch; |
| sensor_perf_config_req.gyroSamplingSpec_valid = 1; |
| sensor_perf_config_req.gyroSamplingSpec.batchesPerSecond = gyroBatchesPerSec; |
| sensor_perf_config_req.gyroSamplingSpec.samplesPerBatch = gyroSamplesPerBatch; |
| sensor_perf_config_req.accelSamplingSpecHigh_valid = 1; |
| sensor_perf_config_req.accelSamplingSpecHigh.batchesPerSecond = accelBatchesPerSecHigh; |
| sensor_perf_config_req.accelSamplingSpecHigh.samplesPerBatch = accelSamplesPerBatchHigh; |
| sensor_perf_config_req.gyroSamplingSpecHigh_valid = 1; |
| sensor_perf_config_req.gyroSamplingSpecHigh.batchesPerSecond = gyroBatchesPerSecHigh; |
| sensor_perf_config_req.gyroSamplingSpecHigh.samplesPerBatch = gyroSamplesPerBatchHigh; |
| sensor_perf_config_req.algorithmConfig_valid = 1; |
| sensor_perf_config_req.algorithmConfig = algorithmConfig; |
| |
| req_union.pSetSensorPerformanceControlConfigReq = &sensor_perf_config_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_SENSOR_PERFORMANCE_CONTROL_CONFIGURATION_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_SENSOR_PERFORMANCE_CONTROL_CONFIGURATION_IND_V02, |
| &sensor_perf_config_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != sensor_perf_config_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(sensor_perf_config_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the External Power Config */ |
| enum loc_api_adapter_err LocApiV02 :: setExtPowerConfig(int isBatteryCharging) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| |
| qmiLocSetExternalPowerConfigReqMsgT_v02 ext_pwr_req; |
| qmiLocGetExternalPowerConfigIndMsgT_v02 ext_pwr_ind; |
| |
| LOC_LOGI("%s:%d]: Ext Pwr Config (isBatteryCharging)(%u)", |
| __FUNCTION__, |
| __LINE__, |
| isBatteryCharging |
| ); |
| |
| memset(&ext_pwr_req, 0, sizeof(ext_pwr_req)); |
| memset(&ext_pwr_ind, 0, sizeof(ext_pwr_ind)); |
| |
| switch(isBatteryCharging) |
| { |
| /* Charging */ |
| case 1: |
| ext_pwr_req.externalPowerState = eQMI_LOC_EXTERNAL_POWER_CONNECTED_V02; |
| break; |
| |
| /* Not charging */ |
| case 0: |
| ext_pwr_req.externalPowerState = eQMI_LOC_EXTERNAL_POWER_NOT_CONNECTED_V02; |
| break; |
| |
| default: |
| LOC_LOGE("%s:%d]: Invalid ext power state = %d!", |
| __FUNCTION__, |
| __LINE__, |
| isBatteryCharging); |
| return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; |
| break; |
| } |
| |
| req_union.pSetExternalPowerConfigReq = &ext_pwr_req; |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_EXTERNAL_POWER_CONFIG_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_EXTERNAL_POWER_CONFIG_IND_V02, |
| &ext_pwr_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != ext_pwr_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %d, ind..status = %d ", |
| __func__, __LINE__, result, ext_pwr_ind.status); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* set the Positioning Protocol on A-GLONASS system */ |
| enum loc_api_adapter_err LocApiV02 :: setAGLONASSProtocol(unsigned long aGlonassProtocol) |
| { |
| locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; |
| locClientReqUnionType req_union; |
| qmiLocSetProtocolConfigParametersReqMsgT_v02 aGlonassProtocol_req; |
| qmiLocSetProtocolConfigParametersIndMsgT_v02 aGlonassProtocol_ind; |
| |
| memset(&aGlonassProtocol_req, 0, sizeof(aGlonassProtocol_req)); |
| memset(&aGlonassProtocol_ind, 0, sizeof(aGlonassProtocol_ind)); |
| |
| aGlonassProtocol_req.assistedGlonassProtocolMask_valid = 1; |
| aGlonassProtocol_req.assistedGlonassProtocolMask = aGlonassProtocol; |
| |
| req_union.pSetProtocolConfigParametersReq = &aGlonassProtocol_req; |
| |
| LOC_LOGD("%s:%d]: aGlonassProtocolMask = 0x%x\n", __func__, __LINE__, |
| aGlonassProtocol_req.assistedGlonassProtocolMask); |
| |
| result = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02, |
| &aGlonassProtocol_ind); |
| |
| if(result != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != aGlonassProtocol_ind.status) |
| { |
| LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(result), |
| loc_get_v02_qmi_status_name(aGlonassProtocol_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /* Convert event mask from loc eng to loc_api_v02 format */ |
| locClientEventMaskType LocApiV02 :: convertMask( |
| LOC_API_ADAPTER_EVENT_MASK_T mask) |
| { |
| locClientEventMaskType eventMask = 0; |
| LOC_LOGD("%s:%d]: adapter mask = %u\n", __func__, __LINE__, mask); |
| |
| if (mask & LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT) |
| eventMask |= QMI_LOC_EVENT_MASK_POSITION_REPORT_V02; |
| |
| if (mask & LOC_API_ADAPTER_BIT_SATELLITE_REPORT) |
| eventMask |= QMI_LOC_EVENT_MASK_GNSS_SV_INFO_V02; |
| |
| /* treat NMEA_1Hz and NMEA_POSITION_REPORT the same*/ |
| if ((mask & LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT) || |
| (mask & LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT) ) |
| eventMask |= QMI_LOC_EVENT_MASK_NMEA_V02; |
| |
| if (mask & LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST) |
| eventMask |= QMI_LOC_EVENT_MASK_NI_NOTIFY_VERIFY_REQ_V02; |
| |
| if (mask & LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST) |
| { |
| // TBD: This needs to be decoupled in the HAL |
| eventMask |= QMI_LOC_EVENT_MASK_INJECT_PREDICTED_ORBITS_REQ_V02; |
| eventMask |= QMI_LOC_EVENT_MASK_INJECT_TIME_REQ_V02; |
| eventMask |= QMI_LOC_EVENT_MASK_INJECT_POSITION_REQ_V02; |
| } |
| |
| if (mask & LOC_API_ADAPTER_BIT_STATUS_REPORT) |
| { |
| eventMask |= (QMI_LOC_EVENT_MASK_ENGINE_STATE_V02); |
| } |
| |
| if (mask & LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST) |
| eventMask |= QMI_LOC_EVENT_MASK_LOCATION_SERVER_CONNECTION_REQ_V02; |
| |
| if (mask & LOC_API_ADAPTER_REQUEST_WIFI) |
| eventMask |= QMI_LOC_EVENT_MASK_WIFI_REQ_V02; |
| |
| if (mask & LOC_API_ADAPTER_SENSOR_STATUS) |
| eventMask |= QMI_LOC_EVENT_MASK_SENSOR_STREAMING_READY_STATUS_V02; |
| |
| if (mask & LOC_API_ADAPTER_REQUEST_TIME_SYNC) |
| eventMask |= QMI_LOC_EVENT_MASK_TIME_SYNC_REQ_V02; |
| |
| if (mask & LOC_API_ADAPTER_REPORT_SPI) |
| eventMask |= QMI_LOC_EVENT_MASK_SET_SPI_STREAMING_REPORT_V02; |
| |
| if (mask & LOC_API_ADAPTER_REPORT_NI_GEOFENCE) |
| eventMask |= QMI_LOC_EVENT_MASK_NI_GEOFENCE_NOTIFICATION_V02; |
| |
| if (mask & LOC_API_ADAPTER_GEOFENCE_GEN_ALERT) |
| eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_GEN_ALERT_V02; |
| |
| if (mask & LOC_API_ADAPTER_REPORT_GENFENCE_BREACH) |
| eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BREACH_NOTIFICATION_V02; |
| |
| if (mask & LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT) |
| eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BATCH_BREACH_NOTIFICATION_V02; |
| |
| if (mask & LOC_API_ADAPTER_PEDOMETER_CTRL) |
| eventMask |= QMI_LOC_EVENT_MASK_PEDOMETER_CONTROL_V02; |
| |
| if (mask & LOC_API_ADAPTER_MOTION_CTRL) |
| eventMask |= QMI_LOC_EVENT_MASK_MOTION_DATA_CONTROL_V02; |
| |
| if (mask & LOC_API_ADAPTER_REQUEST_WIFI_AP_DATA) |
| eventMask |= QMI_LOC_EVENT_MASK_INJECT_WIFI_AP_DATA_REQ_V02; |
| |
| if(mask & LOC_API_ADAPTER_BIT_BATCH_FULL) |
| eventMask |= QMI_LOC_EVENT_MASK_BATCH_FULL_NOTIFICATION_V02; |
| |
| if(mask & LOC_API_ADAPTER_BIT_BATCHED_POSITION_REPORT) |
| eventMask |= QMI_LOC_EVENT_MASK_LIVE_BATCHED_POSITION_REPORT_V02; |
| |
| if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) |
| eventMask |= QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02; |
| |
| return eventMask; |
| } |
| |
| qmiLocLockEnumT_v02 LocApiV02 :: convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask) |
| { |
| if (isGpsLockAll(lockMask)) |
| return eQMI_LOC_LOCK_ALL_V02; |
| if (isGpsLockMO(lockMask)) |
| return eQMI_LOC_LOCK_MI_V02; |
| if (isGpsLockMT(lockMask)) |
| return eQMI_LOC_LOCK_MT_V02; |
| if (isGpsLockNone(lockMask)) |
| return eQMI_LOC_LOCK_NONE_V02; |
| return (qmiLocLockEnumT_v02)lockMask; |
| } |
| |
| /* Convert error from loc_api_v02 to loc eng format*/ |
| enum loc_api_adapter_err LocApiV02 :: convertErr( |
| locClientStatusEnumType status) |
| { |
| switch( status) |
| { |
| case LOC_API_ADAPTER_ERR_SUCCESS: |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| |
| case eLOC_CLIENT_FAILURE_GENERAL: |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| |
| case eLOC_CLIENT_FAILURE_UNSUPPORTED: |
| return LOC_API_ADAPTER_ERR_UNSUPPORTED; |
| |
| case eLOC_CLIENT_FAILURE_INVALID_PARAMETER: |
| return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; |
| |
| case eLOC_CLIENT_FAILURE_ENGINE_BUSY: |
| return LOC_API_ADAPTER_ERR_ENGINE_BUSY; |
| |
| case eLOC_CLIENT_FAILURE_PHONE_OFFLINE: |
| return LOC_API_ADAPTER_ERR_PHONE_OFFLINE; |
| |
| case eLOC_CLIENT_FAILURE_TIMEOUT: |
| return LOC_API_ADAPTER_ERR_TIMEOUT; |
| |
| case eLOC_CLIENT_FAILURE_INVALID_HANDLE: |
| return LOC_API_ADAPTER_ERR_INVALID_HANDLE; |
| |
| case eLOC_CLIENT_FAILURE_SERVICE_NOT_PRESENT: |
| return LOC_API_ADAPTER_ERR_SERVICE_NOT_PRESENT; |
| |
| default: |
| return LOC_API_ADAPTER_ERR_FAILURE; |
| } |
| } |
| |
| /* convert position report to loc eng format and send the converted |
| position to loc eng */ |
| |
| void LocApiV02 :: reportPosition ( |
| const qmiLocEventPositionReportIndMsgT_v02 *location_report_ptr) |
| { |
| UlpLocation location; |
| LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT; |
| LOC_LOGD("Reporting postion from V2 Adapter\n"); |
| memset(&location, 0, sizeof (UlpLocation)); |
| location.size = sizeof(location); |
| GpsLocationExtended locationExtended; |
| memset(&locationExtended, 0, sizeof (GpsLocationExtended)); |
| locationExtended.size = sizeof(locationExtended); |
| // Process the position from final and intermediate reports |
| |
| if( (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_SUCCESS_V02) || |
| (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02) |
| ) |
| { |
| // Latitude & Longitude |
| if( (location_report_ptr->latitude_valid == 1 ) && |
| (location_report_ptr->longitude_valid == 1) && |
| (location_report_ptr->latitude != 0 || |
| location_report_ptr->longitude!= 0)) |
| { |
| location.gpsLocation.flags |= GPS_LOCATION_HAS_LAT_LONG; |
| location.gpsLocation.latitude = location_report_ptr->latitude; |
| location.gpsLocation.longitude = location_report_ptr->longitude; |
| |
| // Time stamp (UTC) |
| if(location_report_ptr->timestampUtc_valid == 1) |
| { |
| location.gpsLocation.timestamp = location_report_ptr->timestampUtc; |
| } |
| |
| // Altitude |
| if(location_report_ptr->altitudeWrtEllipsoid_valid == 1 ) |
| { |
| location.gpsLocation.flags |= GPS_LOCATION_HAS_ALTITUDE; |
| location.gpsLocation.altitude = location_report_ptr->altitudeWrtEllipsoid; |
| } |
| |
| // Speed |
| if((location_report_ptr->speedHorizontal_valid == 1) && |
| (location_report_ptr->speedVertical_valid ==1 ) ) |
| { |
| location.gpsLocation.flags |= GPS_LOCATION_HAS_SPEED; |
| location.gpsLocation.speed = sqrt( |
| (location_report_ptr->speedHorizontal * |
| location_report_ptr->speedHorizontal) + |
| (location_report_ptr->speedVertical * |
| location_report_ptr->speedVertical) ); |
| } |
| |
| // Heading |
| if(location_report_ptr->heading_valid == 1) |
| { |
| location.gpsLocation.flags |= GPS_LOCATION_HAS_BEARING; |
| location.gpsLocation.bearing = location_report_ptr->heading; |
| } |
| |
| // Uncertainty (circular) |
| if( (location_report_ptr->horUncCircular_valid ) ) |
| { |
| location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY; |
| location.gpsLocation.accuracy = location_report_ptr->horUncCircular; |
| } |
| |
| // Technology Mask |
| tech_Mask |= location_report_ptr->technologyMask; |
| |
| //Mark the location source as from GNSS |
| location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; |
| location.position_source = ULP_LOCATION_IS_FROM_GNSS; |
| if (location_report_ptr->magneticDeviation_valid) |
| { |
| locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV; |
| locationExtended.magneticDeviation = location_report_ptr->magneticDeviation; |
| } |
| |
| if (location_report_ptr->DOP_valid) |
| { |
| locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP; |
| locationExtended.pdop = location_report_ptr->DOP.PDOP; |
| locationExtended.hdop = location_report_ptr->DOP.HDOP; |
| locationExtended.vdop = location_report_ptr->DOP.VDOP; |
| } |
| |
| if (location_report_ptr->altitudeWrtMeanSeaLevel_valid) |
| { |
| locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL; |
| locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitudeWrtMeanSeaLevel; |
| } |
| |
| if (location_report_ptr->vertUnc_valid) |
| { |
| locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC; |
| locationExtended.vert_unc = location_report_ptr->vertUnc; |
| } |
| |
| if (location_report_ptr->speedUnc_valid ) |
| { |
| locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC; |
| locationExtended.speed_unc = location_report_ptr->speedUnc; |
| } |
| |
| LocApiBase::reportPosition( location, |
| locationExtended, |
| (void*)location_report_ptr, |
| (location_report_ptr->sessionStatus |
| == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02 ? |
| LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS), |
| tech_Mask); |
| } |
| } |
| else |
| { |
| LocApiBase::reportPosition(location, |
| locationExtended, |
| NULL, |
| LOC_SESS_FAILURE); |
| |
| LOC_LOGD("%s:%d]: Ignoring position report with sess status = %d, " |
| "fix id = %u\n", __func__, __LINE__, |
| location_report_ptr->sessionStatus, |
| location_report_ptr->fixId ); |
| } |
| } |
| |
| /* convert satellite report to loc eng format and send the converted |
| report to loc eng */ |
| void LocApiV02 :: reportSv ( |
| const qmiLocEventGnssSvInfoIndMsgT_v02 *gnss_report_ptr) |
| { |
| GpsSvStatus SvStatus; |
| GpsLocationExtended locationExtended; |
| int num_svs_max, i; |
| const qmiLocSvInfoStructT_v02 *sv_info_ptr; |
| |
| LOC_LOGV ("%s:%d]: num of sv = %d\n", __func__, __LINE__, |
| gnss_report_ptr->svList_len); |
| |
| num_svs_max = 0; |
| memset (&SvStatus, 0, sizeof (GpsSvStatus)); |
| memset(&locationExtended, 0, sizeof (GpsLocationExtended)); |
| locationExtended.size = sizeof(locationExtended); |
| if(gnss_report_ptr->svList_valid == 1) |
| { |
| num_svs_max = gnss_report_ptr->svList_len; |
| if(num_svs_max > GPS_MAX_SVS) |
| { |
| num_svs_max = GPS_MAX_SVS; |
| } |
| SvStatus.num_svs = 0; |
| for(i = 0; i < num_svs_max; i++) |
| { |
| sv_info_ptr = &(gnss_report_ptr->svList[i]); |
| if((sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SYSTEM_V02) && |
| (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_GNSS_SVID_V02) |
| && (sv_info_ptr->gnssSvId != 0 )) |
| { |
| if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_GPS_V02) |
| { |
| SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvStatus); |
| SvStatus.sv_list[SvStatus.num_svs].prn = (int)sv_info_ptr->gnssSvId; |
| |
| // We only have the data field to report gps eph and alm mask |
| if(sv_info_ptr->validMask & |
| QMI_LOC_SV_INFO_MASK_VALID_SVINFO_MASK_V02) |
| { |
| if(sv_info_ptr->svInfoMask & |
| QMI_LOC_SVINFO_MASK_HAS_EPHEMERIS_V02) |
| { |
| SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->gnssSvId-1)); |
| } |
| if(sv_info_ptr->svInfoMask & |
| QMI_LOC_SVINFO_MASK_HAS_ALMANAC_V02) |
| { |
| SvStatus.almanac_mask |= (1 << (sv_info_ptr->gnssSvId-1)); |
| } |
| } |
| |
| if((sv_info_ptr->validMask & |
| QMI_LOC_SV_INFO_MASK_VALID_PROCESS_STATUS_V02) |
| && |
| (sv_info_ptr->svStatus == eQMI_LOC_SV_STATUS_TRACK_V02)) |
| { |
| SvStatus.used_in_fix_mask |= (1 << (sv_info_ptr->gnssSvId-1)); |
| } |
| } |
| // SBAS: GPS RPN: 120-151, |
| // In exteneded measurement report, we follow nmea standard, |
| // which is from 33-64. |
| else if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_SBAS_V02) |
| { |
| SvStatus.sv_list[SvStatus.num_svs].prn = |
| sv_info_ptr->gnssSvId + 33 - 120; |
| } |
| // Gloness: Slot id: 1-32 |
| // In extended measurement report, we follow nmea standard, |
| // which is 65-96 |
| else if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_GLONASS_V02) |
| { |
| SvStatus.sv_list[SvStatus.num_svs].prn = |
| sv_info_ptr->gnssSvId + (65-1); |
| } |
| // Unsupported SV system |
| else |
| { |
| continue; |
| } |
| } |
| |
| if(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SNR_V02 ) |
| { |
| SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr; |
| } |
| |
| if(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_ELEVATION_V02) |
| { |
| SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation; |
| } |
| |
| if(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_AZIMUTH_V02) |
| { |
| SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth; |
| } |
| |
| SvStatus.num_svs++; |
| } |
| } |
| |
| if (SvStatus.num_svs >= 0) |
| { |
| LOC_LOGV ("%s:%d]: firing SV callback\n", __func__, __LINE__); |
| LocApiBase::reportSv(SvStatus, |
| locationExtended, |
| (void*)gnss_report_ptr); |
| } |
| } |
| |
| /* convert engine state report to loc eng format and send the converted |
| report to loc eng */ |
| void LocApiV02 :: reportEngineState ( |
| const qmiLocEventEngineStateIndMsgT_v02 *engine_state_ptr) |
| { |
| |
| LOC_LOGV("%s:%d]: state = %d\n", __func__, __LINE__, |
| engine_state_ptr->engineState); |
| |
| struct MsgUpdateEngineState : public LocMsg { |
| LocApiV02* mpLocApiV02; |
| bool mEngineOn; |
| inline MsgUpdateEngineState(LocApiV02* pLocApiV02, bool engineOn) : |
| LocMsg(), mpLocApiV02(pLocApiV02), mEngineOn(engineOn) {} |
| inline virtual void proc() const { |
| // If EngineOn is true and InSession is false and Engine is just turned off, |
| // then unregister the gps tracking specific event masks |
| if (mpLocApiV02->mEngineOn && !mpLocApiV02->mInSession && !mEngineOn) { |
| mpLocApiV02->registerEventMask(mpLocApiV02->mQmiMask); |
| } |
| mpLocApiV02->mEngineOn = mEngineOn; |
| } |
| }; |
| |
| if (engine_state_ptr->engineState == eQMI_LOC_ENGINE_STATE_ON_V02) |
| { |
| sendMsg(new MsgUpdateEngineState(this, true)); |
| reportStatus(GPS_STATUS_ENGINE_ON); |
| reportStatus(GPS_STATUS_SESSION_BEGIN); |
| } |
| else if (engine_state_ptr->engineState == eQMI_LOC_ENGINE_STATE_OFF_V02) |
| { |
| sendMsg(new MsgUpdateEngineState(this, false)); |
| reportStatus(GPS_STATUS_SESSION_END); |
| reportStatus(GPS_STATUS_ENGINE_OFF); |
| } |
| else |
| { |
| reportStatus(GPS_STATUS_NONE); |
| } |
| |
| } |
| |
| /* convert fix session state report to loc eng format and send the converted |
| report to loc eng */ |
| void LocApiV02 :: reportFixSessionState ( |
| const qmiLocEventFixSessionStateIndMsgT_v02 *fix_session_state_ptr) |
| { |
| GpsStatusValue status; |
| LOC_LOGD("%s:%d]: state = %d\n", __func__, __LINE__, |
| fix_session_state_ptr->sessionState); |
| |
| status = GPS_STATUS_NONE; |
| if (fix_session_state_ptr->sessionState == eQMI_LOC_FIX_SESSION_STARTED_V02) |
| { |
| status = GPS_STATUS_SESSION_BEGIN; |
| } |
| else if (fix_session_state_ptr->sessionState |
| == eQMI_LOC_FIX_SESSION_FINISHED_V02) |
| { |
| status = GPS_STATUS_SESSION_END; |
| } |
| reportStatus(status); |
| } |
| |
| /* convert NMEA report to loc eng format and send the converted |
| report to loc eng */ |
| void LocApiV02 :: reportNmea ( |
| const qmiLocEventNmeaIndMsgT_v02 *nmea_report_ptr) |
| { |
| |
| LocApiBase::reportNmea(nmea_report_ptr->nmea, |
| strlen(nmea_report_ptr->nmea)); |
| |
| LOC_LOGD("%s:%d]: $%c%c%c\n", __func__, __LINE__, |
| nmea_report_ptr->nmea[3], nmea_report_ptr->nmea[4], |
| nmea_report_ptr->nmea[5]); |
| } |
| |
| /* convert and report an ATL request to loc engine */ |
| void LocApiV02 :: reportAtlRequest( |
| const qmiLocEventLocationServerConnectionReqIndMsgT_v02 * server_request_ptr) |
| { |
| uint32_t connHandle = server_request_ptr->connHandle; |
| // service ATL open request; copy the WWAN type |
| if(server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_OPEN_V02 ) |
| { |
| AGpsType agpsType; |
| switch(server_request_ptr->wwanType) |
| { |
| case eQMI_LOC_WWAN_TYPE_INTERNET_V02: |
| agpsType = AGPS_TYPE_WWAN_ANY; |
| requestATL(connHandle, agpsType); |
| break; |
| case eQMI_LOC_WWAN_TYPE_AGNSS_V02: |
| agpsType = AGPS_TYPE_SUPL; |
| requestATL(connHandle, agpsType); |
| break; |
| case eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02: |
| requestSuplES(connHandle); |
| break; |
| default: |
| agpsType = AGPS_TYPE_WWAN_ANY; |
| requestATL(connHandle, agpsType); |
| break; |
| } |
| } |
| // service the ATL close request |
| else if (server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_CLOSE_V02) |
| { |
| releaseATL(connHandle); |
| } |
| } |
| |
| /* conver the NI report to loc eng format and send t loc engine */ |
| void LocApiV02 :: reportNiRequest( |
| const qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *ni_req_ptr) |
| { |
| GpsNiNotification notif; |
| |
| /* initialize the notification*/ |
| memset(notif.extras, 0, sizeof notif.extras); |
| memset(notif.text, 0, sizeof notif.text); |
| memset(notif.requestor_id, 0, sizeof notif.requestor_id); |
| |
| /* NI timeout gets overwritten in LocApiEngAdapter, |
| initializing to 0 here */ |
| notif.timeout = 0; |
| |
| notif.text_encoding = GPS_ENC_NONE ; |
| |
| notif.requestor_id_encoding = GPS_ENC_UNKNOWN; |
| |
| notif.notify_flags = 0; |
| |
| notif.default_response = GPS_NI_RESPONSE_NORESP; |
| |
| /*Handle Vx request */ |
| if(ni_req_ptr->NiVxInd_valid == 1) |
| { |
| const qmiLocNiVxNotifyVerifyStructT_v02 *vx_req = &(ni_req_ptr->NiVxInd); |
| |
| notif.ni_type = GPS_NI_TYPE_VOICE; |
| |
| // Requestor ID, the requestor id recieved is NULL terminated |
| hexcode(notif.requestor_id, sizeof notif.requestor_id, |
| (char *)vx_req->requestorId, vx_req->requestorId_len ); |
| } |
| |
| /* Handle UMTS CP request*/ |
| else if(ni_req_ptr->NiUmtsCpInd_valid == 1) |
| { |
| const qmiLocNiUmtsCpNotifyVerifyStructT_v02 *umts_cp_req = |
| &ni_req_ptr->NiUmtsCpInd; |
| |
| notif.ni_type = GPS_NI_TYPE_UMTS_CTRL_PLANE; |
| |
| /* notificationText should always be a NULL terminated string */ |
| hexcode(notif.text, sizeof notif.text, |
| (char *)umts_cp_req->notificationText, |
| umts_cp_req->notificationText_len); |
| |
| /* Store requestor ID */ |
| hexcode(notif.requestor_id, sizeof(notif.requestor_id), |
| (char *)umts_cp_req->requestorId.codedString, |
| umts_cp_req->requestorId.codedString_len); |
| |
| /* convert encodings */ |
| notif.text_encoding = convertNiEncoding(umts_cp_req->dataCodingScheme); |
| |
| notif.requestor_id_encoding = |
| convertNiEncoding(umts_cp_req->requestorId.dataCodingScheme); |
| |
| /* LCS address (using extras field) */ |
| if ( umts_cp_req->clientAddress_len != 0) |
| { |
| char lcs_addr[32]; // Decoded LCS address for UMTS CP NI |
| |
| // Copy LCS Address into notif.extras in the format: Address = 012345 |
| strlcat(notif.extras, LOC_NI_NOTIF_KEY_ADDRESS, sizeof (notif.extras)); |
| strlcat(notif.extras, " = ", sizeof notif.extras); |
| int addr_len = 0; |
| const char *address_source = NULL; |
| address_source = (char *)umts_cp_req->clientAddress; |
| // client Address is always NULL terminated |
| addr_len = decodeAddress(lcs_addr, sizeof(lcs_addr), address_source, |
| umts_cp_req->clientAddress_len); |
| |
| // The address is ASCII string |
| if (addr_len) |
| { |
| strlcat(notif.extras, lcs_addr, sizeof notif.extras); |
| } |
| } |
| |
| } |
| else if(ni_req_ptr->NiSuplInd_valid == 1) |
| { |
| const qmiLocNiSuplNotifyVerifyStructT_v02 *supl_req = |
| &ni_req_ptr->NiSuplInd; |
| |
| notif.ni_type = GPS_NI_TYPE_UMTS_SUPL; |
| |
| // Client name |
| if (supl_req->valid_flags & QMI_LOC_SUPL_CLIENT_NAME_MASK_V02) |
| { |
| hexcode(notif.text, sizeof(notif.text), |
| (char *)supl_req->clientName.formattedString, |
| supl_req->clientName.formattedString_len); |
| LOC_LOGV("%s:%d]: SUPL NI: client_name: %s \n", __func__, __LINE__, |
| notif.text); |
| } |
| else |
| { |
| LOC_LOGV("%s:%d]: SUPL NI: client_name not present.", |
| __func__, __LINE__); |
| } |
| |
| // Requestor ID |
| if (supl_req->valid_flags & QMI_LOC_SUPL_REQUESTOR_ID_MASK_V02) |
| { |
| hexcode(notif.requestor_id, sizeof notif.requestor_id, |
| (char*)supl_req->requestorId.formattedString, |
| supl_req->requestorId.formattedString_len ); |
| |
| LOC_LOGV("%s:%d]: SUPL NI: requestor_id: %s \n", __func__, __LINE__, |
| notif.requestor_id); |
| } |
| else |
| { |
| LOC_LOGV("%s:%d]: SUPL NI: requestor_id not present.", |
| __func__, __LINE__); |
| } |
| |
| // Encoding type |
| if (supl_req->valid_flags & QMI_LOC_SUPL_DATA_CODING_SCHEME_MASK_V02) |
| { |
| notif.text_encoding = convertNiEncoding(supl_req->dataCodingScheme); |
| |
| notif.requestor_id_encoding = convertNiEncoding(supl_req->dataCodingScheme); |
| } |
| else |
| { |
| notif.text_encoding = notif.requestor_id_encoding = GPS_ENC_UNKNOWN; |
| } |
| |
| // ES SUPL |
| if(ni_req_ptr->suplEmergencyNotification_valid ==1) |
| { |
| const qmiLocEmergencyNotificationStructT_v02 *supl_emergency_request = |
| &ni_req_ptr->suplEmergencyNotification; |
| |
| notif.ni_type = GPS_NI_TYPE_EMERGENCY_SUPL; |
| } |
| |
| } //ni_req_ptr->NiSuplInd_valid == 1 |
| else |
| { |
| LOC_LOGE("%s:%d]: unknown request event \n",__func__, __LINE__); |
| return; |
| } |
| |
| // Set default_response & notify_flags |
| convertNiNotifyVerifyType(¬if, ni_req_ptr->notificationType); |
| |
| qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *ni_req_copy_ptr = |
| (qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *)malloc(sizeof(*ni_req_copy_ptr)); |
| |
| if( NULL != ni_req_copy_ptr) |
| { |
| memcpy(ni_req_copy_ptr, ni_req_ptr, sizeof(*ni_req_copy_ptr)); |
| |
| requestNiNotify(notif, (const void*)ni_req_copy_ptr); |
| } |
| else |
| { |
| LOC_LOGE("%s:%d]: Error copying NI request\n", __func__, __LINE__); |
| } |
| |
| } |
| |
| /* Report the Xtra Server Url from the modem to HAL*/ |
| void LocApiV02 :: reportXtraServerUrl( |
| const qmiLocEventInjectPredictedOrbitsReqIndMsgT_v02* |
| server_request_ptr) |
| { |
| |
| if (server_request_ptr->serverList.serverList_len == 1) |
| { |
| reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl, |
| "", |
| "", |
| QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); |
| } |
| else if (server_request_ptr->serverList.serverList_len == 2) |
| { |
| reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl, |
| server_request_ptr->serverList.serverList[1].serverUrl, |
| "", |
| QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); |
| } |
| else |
| { |
| reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl, |
| server_request_ptr->serverList.serverList[1].serverUrl, |
| server_request_ptr->serverList.serverList[2].serverUrl, |
| QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); |
| } |
| |
| } |
| |
| /* convert Ni Encoding type from QMI_LOC to loc eng format */ |
| GpsNiEncodingType LocApiV02 ::convertNiEncoding( |
| qmiLocNiDataCodingSchemeEnumT_v02 loc_encoding) |
| { |
| GpsNiEncodingType enc = GPS_ENC_UNKNOWN; |
| |
| switch (loc_encoding) |
| { |
| case eQMI_LOC_NI_SUPL_UTF8_V02: |
| enc = GPS_ENC_SUPL_UTF8; |
| break; |
| case eQMI_LOC_NI_SUPL_UCS2_V02: |
| enc = GPS_ENC_SUPL_UCS2; |
| break; |
| case eQMI_LOC_NI_SUPL_GSM_DEFAULT_V02: |
| enc = GPS_ENC_SUPL_GSM_DEFAULT; |
| break; |
| case eQMI_LOC_NI_SS_LANGUAGE_UNSPEC_V02: |
| enc = GPS_ENC_SUPL_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM |
| break; |
| default: |
| break; |
| } |
| |
| return enc; |
| } |
| |
| /*convert NI notify verify type from QMI LOC to loc eng format*/ |
| bool LocApiV02 :: convertNiNotifyVerifyType ( |
| GpsNiNotification *notif, |
| qmiLocNiNotifyVerifyEnumT_v02 notif_priv) |
| { |
| switch (notif_priv) |
| { |
| case eQMI_LOC_NI_USER_NO_NOTIFY_NO_VERIFY_V02: |
| notif->notify_flags = 0; |
| break; |
| |
| case eQMI_LOC_NI_USER_NOTIFY_ONLY_V02: |
| notif->notify_flags = GPS_NI_NEED_NOTIFY; |
| break; |
| |
| case eQMI_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP_V02: |
| notif->notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; |
| notif->default_response = GPS_NI_RESPONSE_ACCEPT; |
| break; |
| |
| case eQMI_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP_V02: |
| notif->notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; |
| notif->default_response = GPS_NI_RESPONSE_DENY; |
| break; |
| |
| case eQMI_LOC_NI_USER_NOTIFY_VERIFY_PRIVACY_OVERRIDE_V02: |
| notif->notify_flags = GPS_NI_PRIVACY_OVERRIDE; |
| break; |
| |
| default: |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* convert and report GNSS measurement data to loc eng */ |
| void LocApiV02 :: reportGnssMeasurementData( |
| const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_report_ptr) |
| { |
| LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__); |
| |
| GpsData gpsMeasurementData; |
| memset (&gpsMeasurementData, 0, sizeof(GpsData)); |
| |
| int svMeasurment_len = 0; |
| |
| // size |
| gpsMeasurementData.size = sizeof(GpsData); |
| |
| // number of measurements |
| if (gnss_measurement_report_ptr.svMeasurement_valid) { |
| svMeasurment_len = |
| gnss_measurement_report_ptr.svMeasurement_len; |
| gpsMeasurementData.measurement_count = svMeasurment_len; |
| LOC_LOGV ("%s:%d]: there are %d SV measurements\n", |
| __func__, __LINE__, svMeasurment_len); |
| } else { |
| LOC_LOGV ("%s:%d]: there is no valid SV measurements\n", |
| __func__, __LINE__); |
| } |
| |
| if (svMeasurment_len != 0 && |
| gnss_measurement_report_ptr.system == eQMI_LOC_SV_SYSTEM_GPS_V02) { |
| |
| // the array of measurements |
| int index = 0; |
| while(svMeasurment_len > 0) { |
| convertGpsMeasurements(gpsMeasurementData.measurements[index], |
| gnss_measurement_report_ptr.svMeasurement[index]); |
| index++; |
| svMeasurment_len--; |
| } |
| |
| // the GPS clock time reading |
| convertGpsClock(gpsMeasurementData.clock, |
| gnss_measurement_report_ptr); |
| |
| // calling the base |
| LOC_LOGV ("%s:%d]: calling LocApiBase::reportGpsMeasurementData.\n", |
| __func__, __LINE__); |
| LocApiBase::reportGpsMeasurementData(gpsMeasurementData); |
| } else { |
| LOC_LOGV ("%s:%d]: There is no GPS measurement.\n", |
| __func__, __LINE__); |
| } |
| } |
| |
| /*convert GpsMeasurement type from QMI LOC to loc eng format*/ |
| void LocApiV02 :: convertGpsMeasurements (GpsMeasurement& gpsMeasurement, |
| const qmiLocSVMeasurementStructT_v02& gnss_measurement_info) |
| { |
| LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__); |
| |
| // size |
| gpsMeasurement.size = sizeof(GpsMeasurement); |
| |
| // flag initiation |
| int flags = 0; |
| |
| // prn |
| gpsMeasurement.prn = gnss_measurement_info.gnssSvId; |
| |
| // time_offset_ns |
| gpsMeasurement.time_offset_ns = 0; |
| |
| // state & received_gps_tow_ns |
| uint64_t validMask = gnss_measurement_info.measurementStatus & |
| gnss_measurement_info.validMeasStatusMask; |
| uint64_t bitSynMask = QMI_LOC_MASK_MEAS_STATUS_BE_CONFIRM_V02 | |
| QMI_LOC_MASK_MEAS_STATUS_SB_VALID_V02; |
| |
| if (validMask & QMI_LOC_MASK_MEAS_STATUS_MS_VALID_V02) { |
| /* sub-frame decode & TOW decode */ |
| gpsMeasurement.state = GPS_MEASUREMENT_STATE_SUBFRAME_SYNC | |
| GPS_MEASUREMENT_STATE_TOW_DECODED | |
| GPS_MEASUREMENT_STATE_BIT_SYNC | |
| GPS_MEASUREMENT_STATE_CODE_LOCK; |
| gpsMeasurement.received_gps_tow_ns = |
| ((double)gnss_measurement_info.svTimeSpeed.svTimeMs + |
| (double)gnss_measurement_info.svTimeSpeed.svTimeSubMs) * 1e6; |
| |
| } else if ((validMask & bitSynMask) == bitSynMask) { |
| /* bit sync */ |
| gpsMeasurement.state = GPS_MEASUREMENT_STATE_BIT_SYNC | |
| GPS_MEASUREMENT_STATE_CODE_LOCK; |
| gpsMeasurement.received_gps_tow_ns = |
| fmod(((double)gnss_measurement_info.svTimeSpeed.svTimeMs + |
| (double)gnss_measurement_info.svTimeSpeed.svTimeSubMs), 20) * 1e6; |
| |
| } else if (validMask & QMI_LOC_MASK_MEAS_STATUS_SM_VALID_V02) { |
| /* code lock */ |
| gpsMeasurement.state = GPS_MEASUREMENT_STATE_CODE_LOCK; |
| gpsMeasurement.received_gps_tow_ns = |
| (double)gnss_measurement_info.svTimeSpeed.svTimeSubMs * 1e6; |
| |
| } else { |
| /* by default */ |
| gpsMeasurement.state = GPS_MEASUREMENT_STATE_UNKNOWN; |
| gpsMeasurement.received_gps_tow_ns = 0; |
| } |
| |
| // c_n0_dbhz |
| gpsMeasurement.c_n0_dbhz = gnss_measurement_info.CNo/10.0; |
| |
| // pseudorange_rate_mps |
| gpsMeasurement.pseudorange_rate_mps = |
| gnss_measurement_info.svTimeSpeed.dopplerShift; |
| |
| // pseudorange_rate_uncertainty_mps |
| gpsMeasurement.pseudorange_rate_uncertainty_mps = |
| gnss_measurement_info.svTimeSpeed.dopplerShiftUnc; |
| |
| // accumulated_delta_range_state |
| gpsMeasurement.accumulated_delta_range_state = GPS_ADR_STATE_UNKNOWN; |
| |
| gpsMeasurement.flags = flags; |
| |
| LOC_LOGV(" %s:%d]: GNSS measurement raw data received form modem: \n" |
| " Input => gnssSvId | CNo " |
| "| measurementStatus | dopplerShift |" |
| " dopplerShiftUnc| svTimeMs | svTimeSubMs" |
| " | validMeasStatusMask | \n" |
| " Input => %d | %d | 0x%04x%04x | %f | %f | %u | %f | 0x%04x%04x |\n", |
| __func__, __LINE__, |
| gnss_measurement_info.gnssSvId, // %d |
| gnss_measurement_info.CNo, // %d |
| (uint32_t)(gnss_measurement_info.measurementStatus >> 32), // %04x Upper 32 |
| (uint32_t)(gnss_measurement_info.measurementStatus & 0xFFFFFFFF), // %04x Lower 32 |
| gnss_measurement_info.svTimeSpeed.dopplerShift, // %f |
| gnss_measurement_info.svTimeSpeed.dopplerShiftUnc, // %f |
| gnss_measurement_info.svTimeSpeed.svTimeMs, // %u |
| gnss_measurement_info.svTimeSpeed.svTimeSubMs, // %f |
| (uint32_t)(gnss_measurement_info.validMeasStatusMask >> 32), // %04x Upper 32 |
| (uint32_t)(gnss_measurement_info.validMeasStatusMask & 0xFFFFFFFF) // %04x Lower 32 |
| ); |
| |
| LOC_LOGV(" %s:%d]: GNSS measurement data after conversion: \n" |
| " Output => size | prn | time_offset_ns | state |" |
| " received_gps_tow_ns| c_n0_dbhz | pseudorange_rate_mps |" |
| " pseudorange_rate_uncertainty_mps |" |
| " accumulated_delta_range_state | flags \n" |
| " Output => %d | %d | %f | %d | %lld | %f | %f | %f | %d | %d \n", |
| __func__, __LINE__, |
| gpsMeasurement.size, // %d |
| gpsMeasurement.prn, // %d |
| gpsMeasurement.time_offset_ns, // %f |
| gpsMeasurement.state, // %d |
| gpsMeasurement.received_gps_tow_ns, // %lld |
| gpsMeasurement.c_n0_dbhz, // %f |
| gpsMeasurement.pseudorange_rate_mps, // %f |
| gpsMeasurement.pseudorange_rate_uncertainty_mps, // %f |
| gpsMeasurement.accumulated_delta_range_state, // %d |
| gpsMeasurement.flags // %d |
| ); |
| } |
| |
| /*convert GpsClock type from QMI LOC to loc eng format*/ |
| void LocApiV02 :: convertGpsClock (GpsClock& gpsClock, |
| const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_info) |
| { |
| LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__); |
| |
| // size |
| gpsClock.size = sizeof(GpsClock); |
| |
| // flag initiation |
| int flags = 0; |
| |
| // type & time_ns |
| if (gnss_measurement_info.systemTime_valid && |
| gnss_measurement_info.systemTimeExt_valid) { |
| |
| uint16_t systemWeek = gnss_measurement_info.systemTime.systemWeek; |
| uint32_t systemMsec = gnss_measurement_info.systemTime.systemMsec; |
| float sysClkBias = gnss_measurement_info.systemTime.systemClkTimeBias; |
| float sysClkUncMs = gnss_measurement_info.systemTime.systemClkTimeUncMs; |
| int sourceOfTime = gnss_measurement_info.systemTimeExt.sourceOfTime; |
| bool isTimeValid = (sysClkUncMs <= 15.0f); // 15ms |
| |
| if(systemWeek != C_GPS_WEEK_UNKNOWN && isTimeValid) { |
| gpsClock.type = GPS_CLOCK_TYPE_GPS_TIME; |
| double temp = (double)(systemWeek) * (double)WEEK_MSECS + (double)systemMsec; |
| gpsClock.time_ns = (double)temp*1e6 - |
| (double)((int)(sysClkBias*1e6)); |
| } else { |
| gpsClock.type = GPS_CLOCK_TYPE_UNKNOWN; |
| } |
| } else { |
| gpsClock.type = GPS_CLOCK_TYPE_UNKNOWN; |
| } |
| |
| LOC_LOGV(" %s:%d]: GNSS measurement clock data received form modem: \n" |
| " Input => systemTime_valid | systemTimeExt_valid | systemWeek" |
| " | systemMsec | systemClkTimeBias" |
| " | systemClkTimeUncMs | sourceOfTime \n" |
| " Input => %d | %d | %d | %d | %f | %f | %d \n", |
| __func__, __LINE__, |
| gnss_measurement_info.systemTime_valid, // %d |
| gnss_measurement_info.systemTimeExt_valid, // %d |
| gnss_measurement_info.systemTime.systemWeek, // %d |
| gnss_measurement_info.systemTime.systemMsec, // %d |
| gnss_measurement_info.systemTime.systemClkTimeBias, // %f |
| gnss_measurement_info.systemTime.systemClkTimeUncMs, // %f |
| gnss_measurement_info.systemTimeExt.sourceOfTime); // %d |
| |
| LOC_LOGV(" %s:%d]: GNSS measurement clock after conversion: \n" |
| " Output => type | time_ns \n" |
| " Output => %d | %lld \n", __func__, __LINE__, |
| gpsClock.type, // %d |
| gpsClock.time_ns); // %lld |
| |
| gpsClock.flags = flags; |
| } |
| |
| /* event callback registered with the loc_api v02 interface */ |
| void LocApiV02 :: eventCb(locClientHandleType clientHandle, |
| uint32_t eventId, locClientEventIndUnionType eventPayload) |
| { |
| LOC_LOGD("%s:%d]: event id = %d\n", __func__, __LINE__, |
| eventId); |
| |
| switch(eventId) |
| { |
| //Position Report |
| case QMI_LOC_EVENT_POSITION_REPORT_IND_V02: |
| reportPosition(eventPayload.pPositionReportEvent); |
| break; |
| |
| // Satellite report |
| case QMI_LOC_EVENT_GNSS_SV_INFO_IND_V02: |
| reportSv(eventPayload.pGnssSvInfoReportEvent); |
| break; |
| |
| // Status report |
| case QMI_LOC_EVENT_ENGINE_STATE_IND_V02: |
| reportEngineState(eventPayload.pEngineState); |
| break; |
| |
| case QMI_LOC_EVENT_FIX_SESSION_STATE_IND_V02: |
| reportFixSessionState(eventPayload.pFixSessionState); |
| break; |
| |
| // NMEA |
| case QMI_LOC_EVENT_NMEA_IND_V02: |
| reportNmea(eventPayload.pNmeaReportEvent); |
| break; |
| |
| // XTRA request |
| case QMI_LOC_EVENT_INJECT_PREDICTED_ORBITS_REQ_IND_V02: |
| LOC_LOGD("%s:%d]: XTRA download request\n", __func__, |
| __LINE__); |
| reportXtraServerUrl(eventPayload.pInjectPredictedOrbitsReqEvent); |
| requestXtraData(); |
| break; |
| |
| // time request |
| case QMI_LOC_EVENT_INJECT_TIME_REQ_IND_V02: |
| LOC_LOGD("%s:%d]: Time request\n", __func__, |
| __LINE__); |
| requestTime(); |
| break; |
| |
| //position request |
| case QMI_LOC_EVENT_INJECT_POSITION_REQ_IND_V02: |
| LOC_LOGD("%s:%d]: Position request\n", __func__, |
| __LINE__); |
| requestLocation(); |
| break; |
| |
| // NI request |
| case QMI_LOC_EVENT_NI_NOTIFY_VERIFY_REQ_IND_V02: |
| reportNiRequest(eventPayload.pNiNotifyVerifyReqEvent); |
| break; |
| |
| // AGPS connection request |
| case QMI_LOC_EVENT_LOCATION_SERVER_CONNECTION_REQ_IND_V02: |
| reportAtlRequest(eventPayload.pLocationServerConnReqEvent); |
| break; |
| |
| // GNSS Measurement Report |
| case QMI_LOC_EVENT_GNSS_MEASUREMENT_REPORT_IND_V02: |
| reportGnssMeasurementData(*eventPayload.pGnssSvRawInfoEvent); |
| break; |
| } |
| } |
| |
| /* Call the service LocAdapterBase down event*/ |
| void LocApiV02 :: errorCb(locClientHandleType handle, |
| locClientErrorEnumType errorId) |
| { |
| if(errorId == eLOC_CLIENT_ERROR_SERVICE_UNAVAILABLE) |
| { |
| LOC_LOGE("%s:%d]: Service unavailable error\n", |
| __func__, __LINE__); |
| |
| handleEngineDownEvent(); |
| |
| /* immediately send the engine up event so that |
| the loc engine re-initializes the adapter and the |
| loc-api_v02 interface */ |
| |
| handleEngineUpEvent(); |
| } |
| } |
| |
| static void ds_client_global_event_cb(ds_client_status_enum_type result, |
| void *loc_adapter_cookie) |
| { |
| LocApiV02 *locApiV02Instance = |
| (LocApiV02 *)loc_adapter_cookie; |
| locApiV02Instance->ds_client_event_cb(result); |
| return; |
| } |
| |
| void LocApiV02::ds_client_event_cb(ds_client_status_enum_type result) |
| { |
| if(result == E_DS_CLIENT_DATA_CALL_CONNECTED) { |
| LOC_LOGD("%s:%d]: Emergency call is up", __func__, __LINE__); |
| reportDataCallOpened(); |
| } |
| else if(result == E_DS_CLIENT_DATA_CALL_DISCONNECTED) { |
| LOC_LOGE("%s:%d]: Emergency call is stopped", __func__, __LINE__); |
| reportDataCallClosed(); |
| } |
| return; |
| } |
| |
| ds_client_cb_data ds_client_cb = { |
| ds_client_global_event_cb |
| }; |
| |
| int LocApiV02 :: initDataServiceClient() |
| { |
| int ret=0; |
| ret = ds_client_init(); |
| LOC_LOGD("%s:%d]: ret = %d\n", __func__, __LINE__,ret); |
| return ret; |
| } |
| |
| int LocApiV02 :: openAndStartDataCall() |
| { |
| enum loc_api_adapter_err ret; |
| int profile_index; |
| int pdp_type; |
| ds_client_status_enum_type result = ds_client_open_call(&dsClientHandle, |
| &ds_client_cb, |
| (void *)this, |
| &profile_index, |
| &pdp_type); |
| if(result == E_DS_CLIENT_SUCCESS) { |
| result = ds_client_start_call(dsClientHandle, profile_index, pdp_type); |
| |
| if(result == E_DS_CLIENT_SUCCESS) { |
| LOC_LOGD("%s:%d]: Request to start Emergency call sent\n", |
| __func__, __LINE__); |
| ret = LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| else { |
| LOC_LOGE("%s:%d]: Unable to bring up emergency call using DS. result = %d", |
| __func__, __LINE__, (int)result); |
| ret = LOC_API_ADAPTER_ERR_UNSUPPORTED; |
| } |
| } |
| else if(result == E_DS_CLIENT_RETRY_LATER) { |
| LOC_LOGE("%s:%d]: Could not start emergency call. Retry after delay\n", |
| __func__, __LINE__); |
| ret = LOC_API_ADAPTER_ERR_ENGINE_BUSY; |
| } |
| else { |
| LOC_LOGE("%s:%d]: Unable to bring up emergency call using DS. ret = %d", |
| __func__, __LINE__, (int)ret); |
| ret = LOC_API_ADAPTER_ERR_UNSUPPORTED; |
| } |
| |
| return (int)ret; |
| } |
| |
| void LocApiV02 :: stopDataCall() |
| { |
| ds_client_status_enum_type ret = |
| ds_client_stop_call(dsClientHandle); |
| if (ret == E_DS_CLIENT_SUCCESS) { |
| LOC_LOGD("%s:%d]: Request to Close SUPL ES call sent\n", __func__, __LINE__); |
| } |
| else { |
| if (ret == E_DS_CLIENT_FAILURE_INVALID_HANDLE) { |
| LOC_LOGE("%s:%d]: Conn handle not found for SUPL ES", |
| __func__, __LINE__); |
| } |
| LOC_LOGE("%s:%d]: Could not close SUPL ES call. Ret: %d\n" |
| ,__func__, __LINE__, ret); |
| } |
| return; |
| } |
| |
| void LocApiV02 :: closeDataCall() |
| { |
| ds_client_close_call(&dsClientHandle); |
| LOC_LOGD("%s:%d]: Release data client handle\n", __func__, __LINE__); |
| return; |
| } |
| |
| enum loc_api_adapter_err LocApiV02 :: |
| getWwanZppFix(GpsLocation &zppLoc) |
| { |
| locClientReqUnionType req_union; |
| qmiLocGetAvailWwanPositionReqMsgT_v02 zpp_req; |
| qmiLocGetAvailWwanPositionIndMsgT_v02 zpp_ind; |
| memset(&zpp_ind, 0, sizeof(zpp_ind)); |
| memset(&zpp_req, 0, sizeof(zpp_req)); |
| |
| req_union.pGetAvailWwanPositionReq = &zpp_req; |
| |
| LOC_LOGD("%s:%d]: Get ZPP Fix from available wwan position\n", __func__, __LINE__); |
| |
| locClientStatusEnumType status = |
| loc_sync_send_req(clientHandle, |
| QMI_LOC_GET_AVAILABLE_WWAN_POSITION_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_GET_AVAILABLE_WWAN_POSITION_IND_V02, |
| &zpp_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != zpp_ind.status) { |
| LOC_LOGE ("%s:%d]: error! status = %s, zpp_ind.status = %s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(zpp_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| LOC_LOGD("Got Zpp fix location validity (lat:%d, lon:%d, timestamp:%d accuracy:%d)", |
| zpp_ind.latitude_valid, |
| zpp_ind.longitude_valid, |
| zpp_ind.timestampUtc_valid, |
| zpp_ind.horUncCircular_valid); |
| |
| LOC_LOGD("(%.7f, %.7f), timestamp %llu, accuracy %f", |
| zpp_ind.latitude, |
| zpp_ind.longitude, |
| zpp_ind.timestampUtc, |
| zpp_ind.horUncCircular); |
| |
| zppLoc.size = sizeof(GpsLocation); |
| if (zpp_ind.timestampUtc_valid) { |
| zppLoc.timestamp = zpp_ind.timestampUtc; |
| } |
| else { |
| // no valid flag in GpsLocation structure to indicate if timestamp field is valid |
| zppLoc.timestamp = -1; |
| } |
| |
| if ((zpp_ind.latitude_valid == false) || |
| (zpp_ind.longitude_valid == false) || |
| (zpp_ind.horUncCircular_valid == false)) { |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| zppLoc.flags = GPS_LOCATION_HAS_LAT_LONG | GPS_LOCATION_HAS_ACCURACY; |
| zppLoc.latitude = zpp_ind.latitude; |
| zppLoc.longitude = zpp_ind.longitude; |
| zppLoc.accuracy = zpp_ind.horUncCircular; |
| |
| if (zpp_ind.altitudeWrtEllipsoid_valid) { |
| zppLoc.flags |= GPS_LOCATION_HAS_ALTITUDE; |
| zppLoc.altitude = zpp_ind.altitudeWrtEllipsoid; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| enum loc_api_adapter_err LocApiV02 :: getBestAvailableZppFix(GpsLocation & zppLoc) |
| { |
| LocPosTechMask tech_mask; |
| return getBestAvailableZppFix(zppLoc, tech_mask); |
| } |
| |
| enum loc_api_adapter_err LocApiV02 :: |
| getBestAvailableZppFix(GpsLocation &zppLoc, LocPosTechMask &tech_mask) |
| { |
| locClientReqUnionType req_union; |
| |
| qmiLocGetBestAvailablePositionIndMsgT_v02 zpp_ind; |
| qmiLocGetBestAvailablePositionReqMsgT_v02 zpp_req; |
| |
| memset(&zpp_ind, 0, sizeof(zpp_ind)); |
| memset(&zpp_req, 0, sizeof(zpp_req)); |
| |
| req_union.pGetBestAvailablePositionReq = &zpp_req; |
| |
| LOC_LOGD("%s:%d]: Get ZPP Fix from best available source\n", __func__, __LINE__); |
| |
| locClientStatusEnumType status = |
| loc_sync_send_req(clientHandle, |
| QMI_LOC_GET_BEST_AVAILABLE_POSITION_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_GET_BEST_AVAILABLE_POSITION_IND_V02, |
| &zpp_ind); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != zpp_ind.status) { |
| LOC_LOGE ("%s:%d]: error! status = %s, zpp_ind.status = %s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(zpp_ind.status)); |
| |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| LOC_LOGD("Got Zpp fix location validity (lat:%d, lon:%d, timestamp:%d accuracy:%d)", |
| zpp_ind.latitude_valid, |
| zpp_ind.longitude_valid, |
| zpp_ind.timestampUtc_valid, |
| zpp_ind.horUncCircular_valid); |
| |
| LOC_LOGD("(%.7f, %.7f), timestamp %llu, accuracy %f", |
| zpp_ind.latitude, |
| zpp_ind.longitude, |
| zpp_ind.timestampUtc, |
| zpp_ind.horUncCircular); |
| |
| zppLoc.size = sizeof(GpsLocation); |
| if (zpp_ind.timestampUtc_valid) { |
| zppLoc.timestamp = zpp_ind.timestampUtc; |
| } |
| else { |
| // no valid flag in GpsLocation structure to indicate if timestamp field is valid |
| zppLoc.timestamp = -1; |
| } |
| |
| if ((zpp_ind.latitude_valid == false) || |
| (zpp_ind.longitude_valid == false) || |
| (zpp_ind.horUncCircular_valid == false)) { |
| return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; |
| } |
| |
| zppLoc.flags = GPS_LOCATION_HAS_LAT_LONG | GPS_LOCATION_HAS_ACCURACY; |
| zppLoc.latitude = zpp_ind.latitude; |
| zppLoc.longitude = zpp_ind.longitude; |
| zppLoc.accuracy = zpp_ind.horUncCircular; |
| |
| if (zpp_ind.altitudeWrtEllipsoid_valid) { |
| zppLoc.flags |= GPS_LOCATION_HAS_ALTITUDE; |
| zppLoc.altitude = zpp_ind.altitudeWrtEllipsoid; |
| } |
| |
| if (zpp_ind.horSpeed_valid) { |
| zppLoc.flags |= GPS_LOCATION_HAS_SPEED; |
| zppLoc.speed = zpp_ind.horSpeed; |
| } |
| |
| if (zpp_ind.heading_valid) { |
| zppLoc.flags |= GPS_LOCATION_HAS_BEARING; |
| zppLoc.bearing = zpp_ind.heading; |
| } |
| |
| if (zpp_ind.technologyMask_valid) { |
| tech_mask = zpp_ind.technologyMask; |
| } |
| |
| return LOC_API_ADAPTER_ERR_SUCCESS; |
| } |
| |
| /*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 |
| |
| Returns values: |
| zero on success; non-zero on failure |
| */ |
| int LocApiV02 :: setGpsLock(LOC_GPS_LOCK_MASK lockMask) |
| { |
| qmiLocSetEngineLockReqMsgT_v02 setEngineLockReq; |
| qmiLocSetEngineLockIndMsgT_v02 setEngineLockInd; |
| locClientStatusEnumType status; |
| locClientReqUnionType req_union; |
| int ret=0; |
| |
| LOC_LOGD("%s:%d]: Set Gps Lock: %x\n", __func__, __LINE__, lockMask); |
| setEngineLockReq.lockType = convertGpsLockMask(lockMask); |
| req_union.pSetEngineLockReq = &setEngineLockReq; |
| memset(&setEngineLockInd, 0, sizeof(setEngineLockInd)); |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_ENGINE_LOCK_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_ENGINE_LOCK_IND_V02, |
| &setEngineLockInd); |
| |
| if(status != eLOC_CLIENT_SUCCESS || setEngineLockInd.status != eQMI_LOC_SUCCESS_V02) { |
| LOC_LOGE("%s:%d]: Set engine lock failed. status: %s, ind status:%s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(setEngineLockInd.status)); |
| ret = -1; |
| } |
| LOC_LOGD("%s:%d]: exit\n", __func__, __LINE__); |
| return ret; |
| } |
| /* |
| Returns |
| Current value of GPS Lock on success |
| -1 on failure |
| */ |
| int LocApiV02 :: getGpsLock() |
| { |
| qmiLocGetEngineLockReqMsgT_v02 getEngineLockReq; |
| qmiLocGetEngineLockIndMsgT_v02 getEngineLockInd; |
| locClientStatusEnumType status; |
| locClientReqUnionType req_union; |
| int ret=0; |
| LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); |
| memset(&getEngineLockInd, 0, sizeof(getEngineLockInd)); |
| |
| //Passing req_union as a parameter even though this request has no payload |
| //since NULL or 0 gives an error during compilation |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_GET_ENGINE_LOCK_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_GET_ENGINE_LOCK_IND_V02, |
| &getEngineLockInd); |
| if(status != eLOC_CLIENT_SUCCESS || getEngineLockInd.status != eQMI_LOC_SUCCESS_V02) { |
| LOC_LOGE("%s:%d]: Set engine lock failed. status: %s, ind status:%s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(getEngineLockInd.status)); |
| ret = -1; |
| } |
| else { |
| if(getEngineLockInd.lockType_valid) { |
| ret = (int)getEngineLockInd.lockType; |
| LOC_LOGD("%s:%d]: Lock Type: %d\n", __func__, __LINE__, ret); |
| } |
| else { |
| LOC_LOGE("%s:%d]: Lock Type not valid\n", __func__, __LINE__); |
| ret = -1; |
| } |
| } |
| LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__); |
| return ret; |
| } |
| |
| void LocApiV02 :: installAGpsCert(const DerEncodedCertificate* pData, |
| size_t numberOfCerts, |
| uint32_t slotBitMask) |
| { |
| LOC_LOGD("%s:%d]:, slot mask=%u number of certs=%u", |
| __func__, __LINE__, slotBitMask, numberOfCerts); |
| |
| uint8_t certIndex = 0; |
| for (uint8_t slot = 0; slot <= AGPS_CERTIFICATE_MAX_SLOTS-1; slot++, slotBitMask >>= 1) |
| { |
| if (slotBitMask & 1) //slot is writable |
| { |
| if (certIndex < numberOfCerts && pData[certIndex].data && pData[certIndex].length > 0) |
| { |
| LOC_LOGD("%s:%d]:, Inject cert#%u slot=%u length=%u", |
| __func__, __LINE__, certIndex, slot, pData[certIndex].length); |
| |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocInjectSuplCertificateReqMsgT_v02 injectCertReq; |
| qmiLocInjectSuplCertificateIndMsgT_v02 injectCertInd; |
| |
| memset(&injectCertReq, 0, sizeof(injectCertReq)); |
| injectCertReq.suplCertId = slot; |
| injectCertReq.suplCertData_len = pData[certIndex].length; |
| memcpy(injectCertReq.suplCertData, pData[certIndex].data, pData[certIndex].length); |
| |
| req_union.pInjectSuplCertificateReq = &injectCertReq; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_INJECT_SUPL_CERTIFICATE_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INJECT_SUPL_CERTIFICATE_IND_V02, |
| &injectCertInd); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != injectCertInd.status) |
| { |
| LOC_LOGE ("%s:%d]: inject-error status = %s, set_server_ind.status = %s", |
| __func__,__LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(injectCertInd.status)); |
| } |
| |
| certIndex++; //move to next cert |
| |
| } else { |
| |
| LOC_LOGD("%s:%d]:, Delete slot=%u", |
| __func__, __LINE__, slot); |
| |
| // A fake cert is injected first before delete is called to workaround |
| // an issue that is seen with trying to delete an empty slot. |
| { |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocInjectSuplCertificateReqMsgT_v02 injectFakeCertReq; |
| qmiLocInjectSuplCertificateIndMsgT_v02 injectFakeCertInd; |
| |
| memset(&injectFakeCertReq, 0, sizeof(injectFakeCertReq)); |
| injectFakeCertReq.suplCertId = slot; |
| injectFakeCertReq.suplCertData_len = 1; |
| injectFakeCertReq.suplCertData[0] = 1; |
| |
| req_union.pInjectSuplCertificateReq = &injectFakeCertReq; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_INJECT_SUPL_CERTIFICATE_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_INJECT_SUPL_CERTIFICATE_IND_V02, |
| &injectFakeCertInd); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != injectFakeCertInd.status) |
| { |
| LOC_LOGE ("%s:%d]: inject-fake-error status = %s, set_server_ind.status = %s", |
| __func__,__LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(injectFakeCertInd.status)); |
| } |
| } |
| |
| locClientReqUnionType req_union; |
| locClientStatusEnumType status; |
| qmiLocDeleteSuplCertificateReqMsgT_v02 deleteCertReq; |
| qmiLocDeleteSuplCertificateIndMsgT_v02 deleteCertInd; |
| |
| memset(&deleteCertReq, 0, sizeof(deleteCertReq)); |
| deleteCertReq.suplCertId = slot; |
| deleteCertReq.suplCertId_valid = 1; |
| |
| req_union.pDeleteSuplCertificateReq = &deleteCertReq; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_DELETE_SUPL_CERTIFICATE_REQ_V02, |
| req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_DELETE_SUPL_CERTIFICATE_IND_V02, |
| &deleteCertInd); |
| |
| if (status != eLOC_CLIENT_SUCCESS || |
| eQMI_LOC_SUCCESS_V02 != deleteCertInd.status) |
| { |
| LOC_LOGE("%s:%d]: delete-error status = %s, set_server_ind.status = %s", |
| __func__,__LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(deleteCertInd.status)); |
| } |
| } |
| } else { |
| LOC_LOGD("%s:%d]:, Not writable slot=%u", |
| __func__, __LINE__, slot); |
| } |
| } |
| |
| } |
| |
| /* |
| Returns |
| 0: update the gps reporting event successfully |
| -1: on failure |
| */ |
| int LocApiV02 :: updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event, |
| loc_registration_mask_status isEnabled) |
| { |
| LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); |
| |
| return open((isEnabled == LOC_REGISTRATION_MASK_ENABLED)?(mMask|event):(mMask&~event)); |
| } |
| |
| bool LocApiV02 :: gnssConstellationConfig() |
| { |
| return mGnssMeasurementSupported == sup_yes; |
| } |
| |
| void LocApiV02 :: cacheGnssMeasurementSupport() |
| { |
| if (sup_unknown == mGnssMeasurementSupported) { |
| if ((mQmiMask & QMI_LOC_EVENT_MASK_POSITION_REPORT_V02) == |
| QMI_LOC_EVENT_MASK_POSITION_REPORT_V02) { |
| /*for GNSS Measurement service, use |
| QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02 |
| to check if modem support this feature or not*/ |
| LOC_LOGD("%s:%d]: set GNSS measurement to report gps measurement only.\n", |
| __func__, __LINE__); |
| |
| qmiLocSetGNSSConstRepConfigReqMsgT_v02 setGNSSConstRepConfigReq; |
| qmiLocSetGNSSConstRepConfigIndMsgT_v02 setGNSSConstRepConfigInd; |
| memset(&setGNSSConstRepConfigReq, 0, sizeof(setGNSSConstRepConfigReq)); |
| memset(&setGNSSConstRepConfigInd, 0, sizeof(setGNSSConstRepConfigInd)); |
| |
| locClientStatusEnumType status; |
| locClientReqUnionType req_union; |
| |
| setGNSSConstRepConfigReq.measReportConfig_valid = true; |
| setGNSSConstRepConfigReq.measReportConfig = eQMI_SYSTEM_GPS_V02; |
| req_union.pSetGNSSConstRepConfigReq = &setGNSSConstRepConfigReq; |
| |
| status = loc_sync_send_req(clientHandle, |
| QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02, |
| req_union, |
| LOC_ENGINE_SYNC_REQUEST_TIMEOUT, |
| QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_IND_V02, |
| &setGNSSConstRepConfigInd); |
| |
| if(status != eLOC_CLIENT_SUCCESS || |
| setGNSSConstRepConfigInd.status != eQMI_LOC_SUCCESS_V02) { |
| LOC_LOGD("%s:%d]: Set GNSS constellation failed." |
| " status: %s, ind status:%s\n", |
| __func__, __LINE__, |
| loc_get_v02_client_status_name(status), |
| loc_get_v02_qmi_status_name(setGNSSConstRepConfigInd.status)); |
| mGnssMeasurementSupported = sup_no; |
| } else { |
| LOC_LOGD("%s:%d]: Set GNSS constellation succeeded.\n", |
| __func__, __LINE__); |
| mGnssMeasurementSupported = sup_yes; |
| } |
| } |
| } |
| |
| LOC_LOGV("%s:%d]: mGnssMeasurementSupported is %d\n", __func__, __LINE__, mGnssMeasurementSupported); |
| } |