/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation, nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define LOG_NDDEBUG 0 #define LOG_TAG "LocSvc_api_rpc" #include #include #ifndef USE_GLIB #include #endif /* USE_GLIB */ #include #include #include #include #include #include #include #ifdef USE_GLIB #include #endif #include #include using namespace loc_core; #define LOC_XTRA_INJECT_DEFAULT_TIMEOUT (3100) #define XTRA_BLOCK_SIZE (3072) #define LOC_IOCTL_DEFAULT_TIMEOUT 1000 // 1000 milli-seconds #define LOC_NI_NOTIF_KEY_ADDRESS "Address" /*=========================================================================== FUNCTION loc_event_cb DESCRIPTION This is the callback function registered by loc_open. DEPENDENCIES N/A RETURN VALUE RPC_LOC_API_SUCCESS SIDE EFFECTS N/A ===========================================================================*/ static int32 loc_event_cb ( void* user, rpc_loc_client_handle_type client_handle, rpc_loc_event_mask_type loc_event, const rpc_loc_event_payload_u_type* loc_event_payload ) { MODEM_LOG_CALLFLOW(%s, loc_get_event_name(loc_event)); loc_callback_log(loc_event, loc_event_payload); int32 ret_val = ((LocApiRpc*)user)->locEventCB(client_handle, loc_event, loc_event_payload); EXIT_LOG(%d, ret_val); return ret_val; } /*=========================================================================== FUNCTION loc_eng_rpc_global_cb DESCRIPTION This is the callback function registered by loc_open for RPC global events DEPENDENCIES N/A RETURN VALUE RPC_LOC_API_SUCCESS SIDE EFFECTS N/A ===========================================================================*/ static void loc_rpc_global_cb(void* user, CLIENT* clnt, enum rpc_reset_event event) { MODEM_LOG_CALLFLOW(%s, loc_get_rpc_reset_event_name(event)); ((LocApiRpc*)user)->locRpcGlobalCB(clnt, event); EXIT_LOG(%p, VOID_RET); } const LOC_API_ADAPTER_EVENT_MASK_T LocApiRpc::maskAll = LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT | LOC_API_ADAPTER_BIT_SATELLITE_REPORT | LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST | LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST | LOC_API_ADAPTER_BIT_IOCTL_REPORT | LOC_API_ADAPTER_BIT_STATUS_REPORT | LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT | LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; const rpc_loc_event_mask_type LocApiRpc::locBits[] = { RPC_LOC_EVENT_PARSED_POSITION_REPORT, RPC_LOC_EVENT_SATELLITE_REPORT, RPC_LOC_EVENT_NMEA_1HZ_REPORT, RPC_LOC_EVENT_NMEA_POSITION_REPORT, RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST, RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST, RPC_LOC_EVENT_LOCATION_SERVER_REQUEST, RPC_LOC_EVENT_IOCTL_REPORT, RPC_LOC_EVENT_STATUS_REPORT, RPC_LOC_EVENT_WPS_NEEDED_REQUEST }; // constructor LocApiRpc::LocApiRpc(const MsgTask* msgTask, LOC_API_ADAPTER_EVENT_MASK_T exMask, ContextBase* context) : LocApiBase(msgTask, exMask, context), client_handle(RPC_LOC_CLIENT_HANDLE_INVALID), dataEnableLastSet(-1) { memset(apnLastSet, 0, sizeof(apnLastSet)); loc_api_glue_init(); } LocApiRpc::~LocApiRpc() { close(); } rpc_loc_event_mask_type LocApiRpc::convertMask(LOC_API_ADAPTER_EVENT_MASK_T mask) { rpc_loc_event_mask_type newMask = 0; for (unsigned int i = 0, bit=1; 0 != mask; i++, bit<<=1) { if (mask & bit) { newMask |= locBits[i]; mask ^= bit; } } return newMask; } rpc_loc_lock_e_type LocApiRpc::convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask) { if (isGpsLockAll(lockMask)) return RPC_LOC_LOCK_ALL; if (isGpsLockMO(lockMask)) return RPC_LOC_LOCK_MI; if (isGpsLockMT(lockMask)) return RPC_LOC_LOCK_MT; if (isGpsLockNone(lockMask)) return RPC_LOC_LOCK_NONE; return (rpc_loc_lock_e_type)lockMask; } enum loc_api_adapter_err LocApiRpc::convertErr(int rpcErr) { switch(rpcErr) { case RPC_LOC_API_SUCCESS: return LOC_API_ADAPTER_ERR_SUCCESS; case RPC_LOC_API_GENERAL_FAILURE: return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; case RPC_LOC_API_UNSUPPORTED: return LOC_API_ADAPTER_ERR_UNSUPPORTED; case RPC_LOC_API_INVALID_HANDLE: return LOC_API_ADAPTER_ERR_INVALID_HANDLE; case RPC_LOC_API_INVALID_PARAMETER: return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; case RPC_LOC_API_ENGINE_BUSY: return LOC_API_ADAPTER_ERR_ENGINE_BUSY; case RPC_LOC_API_PHONE_OFFLINE: return LOC_API_ADAPTER_ERR_PHONE_OFFLINE; case RPC_LOC_API_TIMEOUT: return LOC_API_ADAPTER_ERR_TIMEOUT; case RPC_LOC_API_RPC_MODEM_RESTART: return LOC_API_ADAPTER_ERR_ENGINE_DOWN; case RPC_LOC_API_RPC_FAILURE: return LOC_API_ADAPTER_ERR_FAILURE; default: return LOC_API_ADAPTER_ERR_UNKNOWN; } } void LocApiRpc::locRpcGlobalCB(CLIENT* clnt, enum rpc_reset_event event) { static rpc_loc_engine_state_e_type last_state = RPC_LOC_ENGINE_STATE_MAX; switch (event) { case RPC_SUBSYSTEM_RESTART_BEGIN: if (RPC_LOC_ENGINE_STATE_OFF != last_state) { last_state = RPC_LOC_ENGINE_STATE_OFF; handleEngineDownEvent(); } break; case RPC_SUBSYSTEM_RESTART_END: if (RPC_LOC_ENGINE_STATE_ON != last_state) { last_state = RPC_LOC_ENGINE_STATE_ON; handleEngineUpEvent(); } break; } } int32 LocApiRpc::locEventCB(rpc_loc_client_handle_type client_handle, rpc_loc_event_mask_type loc_event, const rpc_loc_event_payload_u_type* loc_event_payload) { // Parsed report if (loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT) { reportPosition(&loc_event_payload->rpc_loc_event_payload_u_type_u. parsed_location_report); } // Satellite report if (loc_event & RPC_LOC_EVENT_SATELLITE_REPORT) { reportSv(&loc_event_payload->rpc_loc_event_payload_u_type_u.gnss_report); } // Status report if (loc_event & RPC_LOC_EVENT_STATUS_REPORT) { reportStatus(&loc_event_payload->rpc_loc_event_payload_u_type_u.status_report); } // NMEA if (loc_event & RPC_LOC_EVENT_NMEA_1HZ_REPORT) { reportNmea(&(loc_event_payload->rpc_loc_event_payload_u_type_u.nmea_report)); } // XTRA support: supports only XTRA download if (loc_event & RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST) { if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event == RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ) { requestXtraData(); } else if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event == RPC_LOC_ASSIST_DATA_TIME_REQ) { requestTime(); } else if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event == RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ) { requestLocation(); } } // AGPS data request if (loc_event & RPC_LOC_EVENT_LOCATION_SERVER_REQUEST) { ATLEvent(&loc_event_payload->rpc_loc_event_payload_u_type_u. loc_server_request); } // NI notify request if (loc_event & RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST) { NIEvent(&loc_event_payload->rpc_loc_event_payload_u_type_u.ni_request); } return RPC_LOC_API_SUCCESS;//We simply want to return sucess here as we do not want to // cause any issues in RPC thread context } enum loc_api_adapter_err LocApiRpc::open(LOC_API_ADAPTER_EVENT_MASK_T mask) { enum loc_api_adapter_err ret_val = LOC_API_ADAPTER_ERR_SUCCESS; // RPC does not dynamically update the event mask. And in the // case of RPC, all we support are positioning (gps + agps) // masks anyways, so we simply mask all of them on always. // After doing so the first time in a power cycle, we know there // will the following if condition will never be true any more. mask = maskAll; if (mask != mMask) { if (RPC_LOC_CLIENT_HANDLE_INVALID != client_handle) { close(); } mMask = mask; // it is important to cap the mask here, because not all LocApi's // can enable the same bits, e.g. foreground and bckground. client_handle = loc_open(convertMask(mask), loc_event_cb, loc_rpc_global_cb, this); if (client_handle < 0) { mMask = 0; client_handle = RPC_LOC_CLIENT_HANDLE_INVALID; ret_val = LOC_API_ADAPTER_ERR_INVALID_HANDLE; } } return ret_val; } enum loc_api_adapter_err LocApiRpc::close() { if (RPC_LOC_CLIENT_HANDLE_INVALID != client_handle) { loc_clear(client_handle); } loc_close(client_handle); mMask = 0; client_handle = RPC_LOC_CLIENT_HANDLE_INVALID; return LOC_API_ADAPTER_ERR_SUCCESS; } enum loc_api_adapter_err LocApiRpc::startFix(const LocPosMode& posMode) { LOC_LOGD("LocApiRpc::startFix() called"); return convertErr( loc_start_fix(client_handle) ); } enum loc_api_adapter_err LocApiRpc::stopFix() { LOC_LOGD("LocApiRpc::stopFix() called"); return convertErr( loc_stop_fix(client_handle) ); } enum loc_api_adapter_err LocApiRpc::setPositionMode(const LocPosMode& posMode) { rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_fix_criteria_s_type *fix_criteria_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.fix_criteria; rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_SET_FIX_CRITERIA; rpc_loc_operation_mode_e_type op_mode; int ret_val; const LocPosMode* fixCriteria = &posMode; ALOGD ("loc_eng_set_position mode, client = %d, interval = %d, mode = %d\n", (int32) client_handle, fixCriteria->min_interval, fixCriteria->mode); switch (fixCriteria->mode) { case LOC_POSITION_MODE_MS_BASED: op_mode = RPC_LOC_OPER_MODE_MSB; break; case LOC_POSITION_MODE_MS_ASSISTED: op_mode = RPC_LOC_OPER_MODE_MSA; break; case LOC_POSITION_MODE_RESERVED_1: op_mode = RPC_LOC_OPER_MODE_SPEED_OPTIMAL; break; case LOC_POSITION_MODE_RESERVED_2: op_mode = RPC_LOC_OPER_MODE_ACCURACY_OPTIMAL; break; case LOC_POSITION_MODE_RESERVED_3: op_mode = RPC_LOC_OPER_MODE_DATA_OPTIMAL; break; case LOC_POSITION_MODE_RESERVED_4: case LOC_POSITION_MODE_RESERVED_5: op_mode = RPC_LOC_OPER_MODE_MSA; fix_criteria_ptr->preferred_response_time = 0; break; default: op_mode = RPC_LOC_OPER_MODE_STANDALONE; } fix_criteria_ptr->valid_mask = RPC_LOC_FIX_CRIT_VALID_PREFERRED_OPERATION_MODE | RPC_LOC_FIX_CRIT_VALID_RECURRENCE_TYPE; fix_criteria_ptr->min_interval = fixCriteria->min_interval; fix_criteria_ptr->preferred_operation_mode = op_mode; fix_criteria_ptr->min_interval = fixCriteria->min_interval; fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_MIN_INTERVAL; if (fixCriteria->preferred_accuracy > 0) { fix_criteria_ptr->preferred_accuracy = fixCriteria->preferred_accuracy; fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_PREFERRED_ACCURACY; } if (fixCriteria->preferred_time > 0) { fix_criteria_ptr->preferred_response_time = fixCriteria->preferred_time; fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_PREFERRED_RESPONSE_TIME; } switch (fixCriteria->recurrence) { case GPS_POSITION_RECURRENCE_SINGLE: fix_criteria_ptr->recurrence_type = RPC_LOC_SINGLE_FIX; break; case GPS_POSITION_RECURRENCE_PERIODIC: default: fix_criteria_ptr->recurrence_type = RPC_LOC_PERIODIC_FIX; break; } ioctl_data.disc = ioctl_type; ret_val = loc_eng_ioctl (client_handle, ioctl_type, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL /* No output information is expected*/); return convertErr(ret_val); } enum loc_api_adapter_err LocApiRpc::setTime(GpsUtcTime time, int64_t timeReference, int uncertainty) { rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_assist_data_time_s_type *time_info_ptr; rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_INJECT_UTC_TIME; int ret_val; LOC_LOGD ("loc_eng_inject_time, uncertainty = %d\n", uncertainty); time_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_time; time_info_ptr->time_utc = time; time_info_ptr->time_utc += (int64_t)(ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION - timeReference); time_info_ptr->uncertainty = uncertainty; // Uncertainty in ms ioctl_data.disc = ioctl_type; ret_val = loc_eng_ioctl (client_handle, ioctl_type, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL /* No output information is expected*/); return convertErr(ret_val); } enum loc_api_adapter_err LocApiRpc::injectPosition(double latitude, double longitude, float accuracy) { /* IOCTL data */ rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_assist_data_pos_s_type *assistance_data_position = &ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_position; int ret_val; /************************************************ * Fill in latitude, longitude & accuracy ************************************************/ /* This combo is required */ assistance_data_position->valid_mask = RPC_LOC_ASSIST_POS_VALID_LATITUDE | RPC_LOC_ASSIST_POS_VALID_LONGITUDE | RPC_LOC_ASSIST_POS_VALID_HOR_UNC_CIRCULAR | RPC_LOC_ASSIST_POS_VALID_CONFIDENCE_HORIZONTAL; assistance_data_position->latitude = latitude; assistance_data_position->longitude = longitude; assistance_data_position->hor_unc_circular = accuracy; /* Meters assumed */ assistance_data_position->confidence_horizontal = 63; /* 63% (1 std dev) assumed */ /* Log */ LOC_LOGD("Inject coarse position Lat=%lf, Lon=%lf, Acc=%.2lf\n", (double) assistance_data_position->latitude, (double) assistance_data_position->longitude, (double) assistance_data_position->hor_unc_circular); ret_val = loc_eng_ioctl( client_handle, RPC_LOC_IOCTL_INJECT_POSITION, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL /* No output information is expected*/); return convertErr(ret_val); } enum loc_api_adapter_err LocApiRpc::informNiResponse(GpsUserResponseType userResponse, const void* passThroughData) { rpc_loc_ioctl_data_u_type data; rpc_loc_ioctl_callback_s_type callback_payload; memcpy(&data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.ni_event_pass_back, passThroughData, sizeof (rpc_loc_ni_event_s_type)); rpc_loc_ni_user_resp_e_type resp; switch (userResponse) { case GPS_NI_RESPONSE_ACCEPT: data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp = RPC_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT; break; case GPS_NI_RESPONSE_DENY: data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp = RPC_LOC_NI_LCS_NOTIFY_VERIFY_DENY; break; case GPS_NI_RESPONSE_NORESP: default: data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp = RPC_LOC_NI_LCS_NOTIFY_VERIFY_NORESP; break; } return convertErr( loc_eng_ioctl(client_handle, RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE, &data, LOC_IOCTL_DEFAULT_TIMEOUT, &callback_payload) ); } enum loc_api_adapter_err LocApiRpc::setAPN(char* apn, int len, boolean force) { enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS; int size = sizeof(apnLastSet); if (force || memcmp(apnLastSet, apn, size)) { if (len < size) { // size will be not larger than its original value size = len + 1; } memcpy(apnLastSet, apn, size); if (!isInSession()) { rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_LBS_APN_PROFILE, {0}}; ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].srv_system_type = LOC_APN_PROFILE_SRV_SYS_MAX; ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].pdp_type = LOC_APN_PROFILE_PDN_TYPE_IPV4; memcpy(&(ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].apn_name), apn, size); rtv = convertErr( loc_eng_ioctl (client_handle, RPC_LOC_IOCTL_SET_LBS_APN_PROFILE, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL) ); } } return rtv; } void LocApiRpc::setInSession(bool inSession) { if (!inSession) { enableData(dataEnableLastSet, true); setAPN(apnLastSet, sizeof(apnLastSet)-1, true); } } enum loc_api_adapter_err LocApiRpc::setServer(const char* url, int len) { rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_server_info_s_type *server_info_ptr; rpc_loc_ioctl_e_type ioctl_cmd; ioctl_cmd = RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR; ioctl_data.disc = ioctl_cmd; server_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr; server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_URL; server_info_ptr->addr_info.disc = server_info_ptr->addr_type; server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.length = len; #if (AMSS_VERSION==3200) server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_val = (char*) url; server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_len= len; #else strlcpy(server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr, url, sizeof server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr); #endif /* #if (AMSS_VERSION==3200) */ LOC_LOGD ("loc_eng_set_server, addr = %s\n", url); return convertErr( loc_eng_ioctl (client_handle, ioctl_cmd, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL /* No output information is expected*/) ); } enum loc_api_adapter_err LocApiRpc::setServer(unsigned int ip, int port, LocServerType type) { rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_server_info_s_type *server_info_ptr; rpc_loc_ioctl_e_type ioctl_cmd; switch (type) { case LOC_AGPS_MPC_SERVER: ioctl_cmd = RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR; break; case LOC_AGPS_CUSTOM_PDE_SERVER: ioctl_cmd = RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR; break; default: ioctl_cmd = RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR; break; } ioctl_data.disc = ioctl_cmd; server_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr; server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_IPV4; server_info_ptr->addr_info.disc = server_info_ptr->addr_type; server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.ipv4.addr = ip; server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.ipv4.port = port; LOC_LOGD ("setServer, addr = %X:%d\n", (unsigned int) ip, (unsigned int) port); return convertErr( loc_eng_ioctl (client_handle, ioctl_cmd, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL /* No output information is expected*/) ); } enum loc_api_adapter_err LocApiRpc::enableData(int enable, boolean force) { enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS; if (force || dataEnableLastSet != enable) { dataEnableLastSet = enable; if (!isInSession()) { rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_DATA_ENABLE, {0}}; ioctl_data.rpc_loc_ioctl_data_u_type_u.data_enable = enable; rtv = convertErr( loc_eng_ioctl (client_handle, RPC_LOC_IOCTL_SET_DATA_ENABLE, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL) ); } } return rtv; } enum loc_api_adapter_err LocApiRpc::deleteAidingData(GpsAidingData bits) { rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_DELETE_ASSIST_DATA, {0}}; ioctl_data.rpc_loc_ioctl_data_u_type_u.assist_data_delete.type = bits; return convertErr( loc_eng_ioctl (client_handle, RPC_LOC_IOCTL_DELETE_ASSIST_DATA, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL) ); } void LocApiRpc::reportPosition(const rpc_loc_parsed_position_s_type *location_report_ptr) { LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT; UlpLocation location = {0}; GpsLocationExtended locationExtended = {0}; location.size = sizeof(location); locationExtended.size = sizeof(locationExtended); if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SESSION_STATUS) { // Process the position from final and intermediate reports if (location_report_ptr->session_status == RPC_LOC_SESS_STATUS_SUCCESS || location_report_ptr->session_status == RPC_LOC_SESS_STATUS_IN_PROGESS) { // Latitude & Longitude if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LATITUDE) && (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LONGITUDE) && (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->valid_mask & RPC_LOC_POS_VALID_TIMESTAMP_UTC) { location.gpsLocation.timestamp = location_report_ptr->timestamp_utc; } // Altitude if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_ELLIPSOID ) { location.gpsLocation.flags |= GPS_LOCATION_HAS_ALTITUDE; location.gpsLocation.altitude = location_report_ptr->altitude_wrt_ellipsoid; } // Speed if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_HORIZONTAL) && (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_VERTICAL)) { location.gpsLocation.flags |= GPS_LOCATION_HAS_SPEED; location.gpsLocation.speed = sqrt(location_report_ptr->speed_horizontal * location_report_ptr->speed_horizontal + location_report_ptr->speed_vertical * location_report_ptr->speed_vertical); } // Heading if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HEADING) { location.gpsLocation.flags |= GPS_LOCATION_HAS_BEARING; location.gpsLocation.bearing = location_report_ptr->heading; } // Uncertainty (circular) if ( (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HOR_UNC_CIRCULAR) ) { location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY; location.gpsLocation.accuracy = location_report_ptr->hor_unc_circular; } // Technology Mask tech_Mask |= location_report_ptr->technology_mask; //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->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_MEAN_SEA_LEVEL) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL; locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitude_wrt_mean_sea_level; } if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_MAGNETIC_VARIATION ) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV; locationExtended.magneticDeviation = location_report_ptr->magnetic_deviation; } if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_VERTICAL_UNC) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC; locationExtended.vert_unc = location_report_ptr->vert_unc; } if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_UNC) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC; locationExtended.speed_unc = location_report_ptr->speed_unc; } LOC_LOGV("reportPosition: fire callback\n"); enum loc_sess_status fixStatus = (location_report_ptr->session_status == RPC_LOC_SESS_STATUS_IN_PROGESS ? LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS); LocApiBase::reportPosition(location, locationExtended, (void*)location_report_ptr, fixStatus, tech_Mask); } } else { LocApiBase::reportPosition(location, locationExtended, NULL, LOC_SESS_FAILURE); LOC_LOGV("loc_eng_report_position: ignore position report " "when session status = %d\n", location_report_ptr->session_status); } } else { LOC_LOGV("loc_eng_report_position: ignore position report " "when session status is not set\n"); } } void LocApiRpc::reportSv(const rpc_loc_gnss_info_s_type *gnss_report_ptr) { GpsSvStatus SvStatus = {0}; GpsLocationExtended locationExtended = {0}; locationExtended.size = sizeof(locationExtended); int num_svs_max = 0; const rpc_loc_sv_info_s_type *sv_info_ptr; if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_COUNT) { num_svs_max = gnss_report_ptr->sv_count; if (num_svs_max > GPS_MAX_SVS) { num_svs_max = GPS_MAX_SVS; } } if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_LIST) { SvStatus.num_svs = 0; for (int i = 0; i < num_svs_max; i++) { sv_info_ptr = &(gnss_report_ptr->sv_list.sv_list_val[i]); if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SYSTEM) { if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GPS) { SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvStatus); SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn; // We only have the data field to report gps eph and alm mask if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_EPH) && (sv_info_ptr->has_eph == 1)) { SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->prn-1)); } if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_ALM) && (sv_info_ptr->has_alm == 1)) { SvStatus.almanac_mask |= (1 << (sv_info_ptr->prn-1)); } if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) && (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK)) { SvStatus.used_in_fix_mask |= (1 << (sv_info_ptr->prn-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 == RPC_LOC_SV_SYSTEM_SBAS) { SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + 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 == RPC_LOC_SV_SYSTEM_GLONASS) { SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + (65-1); } // Unsupported SV system else { continue; } } if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SNR) { SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr; } if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_ELEVATION) { SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation; } if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_AZIMUTH) { SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth; } SvStatus.num_svs++; } } if ((gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_POS_DOP) && (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_HOR_DOP) && (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_VERT_DOP)) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP; locationExtended.pdop = gnss_report_ptr->position_dop; locationExtended.hdop = gnss_report_ptr->horizontal_dop; locationExtended.vdop = gnss_report_ptr->vertical_dop; } if (SvStatus.num_svs >= 0) { LocApiBase::reportSv(SvStatus, locationExtended, (void*)gnss_report_ptr); } } void LocApiRpc::reportStatus(const rpc_loc_status_event_s_type *status_report_ptr) { if (status_report_ptr->event == RPC_LOC_STATUS_EVENT_ENGINE_STATE) { if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_ON) { LocApiBase::reportStatus(GPS_STATUS_ENGINE_ON); LocApiBase::reportStatus(GPS_STATUS_SESSION_BEGIN); } else if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_OFF) { LocApiBase::reportStatus(GPS_STATUS_SESSION_END); LocApiBase::reportStatus(GPS_STATUS_ENGINE_OFF); } else { LocApiBase::reportStatus(GPS_STATUS_NONE); } } } void LocApiRpc::reportNmea(const rpc_loc_nmea_report_s_type *nmea_report_ptr) { #if (AMSS_VERSION==3200) LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences.nmea_sentences_val, nmea_report_ptr->nmea_sentences.nmea_sentences_len); #else LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences, nmea_report_ptr->length); LOC_LOGD("loc_eng_report_nmea: $%c%c%c\n", nmea_report_ptr->nmea_sentences[3], nmea_report_ptr->nmea_sentences[4], nmea_report_ptr->nmea_sentences[5]); #endif /* #if (AMSS_VERSION==3200) */ } enum loc_api_adapter_err LocApiRpc::setXtraData(char* data, int length) { int rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE; int total_parts; uint8 part; uint16 part_len; uint16 len_injected; rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA; rpc_loc_predicted_orbits_data_s_type *predicted_orbits_data_ptr; LOC_LOGD("qct_loc_eng_inject_xtra_data, xtra size = %d, data ptr = 0x%lx\n", length, (long) data); predicted_orbits_data_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.predicted_orbits_data; predicted_orbits_data_ptr->format_type = RPC_LOC_PREDICTED_ORBITS_XTRA; predicted_orbits_data_ptr->total_size = length; total_parts = (length - 1) / XTRA_BLOCK_SIZE + 1; predicted_orbits_data_ptr->total_parts = total_parts; len_injected = 0; // O bytes injected ioctl_data.disc = ioctl_type; // XTRA injection starts with part 1 for (part = 1; part <= total_parts; part++) { predicted_orbits_data_ptr->part = part; predicted_orbits_data_ptr->part_len = XTRA_BLOCK_SIZE; if (XTRA_BLOCK_SIZE > (length - len_injected)) { predicted_orbits_data_ptr->part_len = length - len_injected; } predicted_orbits_data_ptr->data_ptr.data_ptr_len = predicted_orbits_data_ptr->part_len; predicted_orbits_data_ptr->data_ptr.data_ptr_val = data + len_injected; LOC_LOGD("qct_loc_eng_inject_xtra_data, part %d/%d, len = %d, total = %d\n", predicted_orbits_data_ptr->part, total_parts, predicted_orbits_data_ptr->part_len, len_injected); if (part < total_parts) { // No callback in this case rpc_ret_val = loc_ioctl (client_handle, ioctl_type, &ioctl_data); if (rpc_ret_val != RPC_LOC_API_SUCCESS) { LOC_LOGE("loc_ioctl for xtra error: %s\n", loc_get_ioctl_status_name(rpc_ret_val)); break; } //Add a delay of 10 ms so that repeated RPC calls dont starve the modem processor usleep(10 * 1000); } else // part == total_parts { // Last part injection, will need to wait for callback if (!loc_eng_ioctl(client_handle, ioctl_type, &ioctl_data, LOC_XTRA_INJECT_DEFAULT_TIMEOUT, NULL)) { rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE; } break; // done with injection } len_injected += predicted_orbits_data_ptr->part_len; LOC_LOGD("loc_ioctl XTRA injected length: %d\n", len_injected); } return convertErr(rpc_ret_val); } /* Request the Xtra Server Url from the modem */ enum loc_api_adapter_err LocApiRpc::requestXtraServer() { loc_api_adapter_err err; rpc_loc_ioctl_data_u_type data; rpc_loc_ioctl_callback_s_type callback_data; err = convertErr(loc_eng_ioctl(client_handle, RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE, &data, LOC_IOCTL_DEFAULT_TIMEOUT, &callback_data)); if (LOC_API_ADAPTER_ERR_SUCCESS != err) { LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: err=%d\n", err); return err; } else if (RPC_LOC_SESS_STATUS_SUCCESS != callback_data.status) { LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: status=%ld\n", callback_data.status); return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; } else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.type) { LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the type expected! type=%d\n", callback_data.type); return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; } else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.data.disc) { LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the disc expected! disc=%d\n", callback_data.data.disc); return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; } reportXtraServer(callback_data.data.rpc_loc_ioctl_callback_data_u_type_u. predicted_orbits_data_source.servers[0], callback_data.data.rpc_loc_ioctl_callback_data_u_type_u. predicted_orbits_data_source.servers[1], callback_data.data.rpc_loc_ioctl_callback_data_u_type_u. predicted_orbits_data_source.servers[2], 255); return LOC_API_ADAPTER_ERR_SUCCESS; } enum loc_api_adapter_err LocApiRpc::atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bearer, AGpsType agpsType) { rpc_loc_server_open_status_e_type open_status = is_succ ? RPC_LOC_SERVER_OPEN_SUCCESS : RPC_LOC_SERVER_OPEN_FAIL; rpc_loc_ioctl_data_u_type ioctl_data; if (AGPS_TYPE_INVALID == agpsType) { rpc_loc_server_open_status_s_type *conn_open_status_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_open_status; // Fill in data ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS; conn_open_status_ptr->conn_handle = handle; conn_open_status_ptr->open_status = open_status; #if (AMSS_VERSION==3200) conn_open_status_ptr->apn_name = apn; /* requires APN */ #else if (is_succ) { strlcpy(conn_open_status_ptr->apn_name, apn, sizeof conn_open_status_ptr->apn_name); } else { conn_open_status_ptr->apn_name[0] = 0; } #endif /* #if (AMSS_VERSION==3200) */ LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS open %s, APN name = [%s]\n", log_succ_fail_string(is_succ), apn); } else { rpc_loc_server_multi_open_status_s_type *conn_multi_open_status_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.multi_conn_open_status; // Fill in data ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS; conn_multi_open_status_ptr->conn_handle = handle; conn_multi_open_status_ptr->open_status = open_status; if (is_succ) { strlcpy(conn_multi_open_status_ptr->apn_name, apn, sizeof conn_multi_open_status_ptr->apn_name); } else { conn_multi_open_status_ptr->apn_name[0] = 0; } switch(bearer) { case AGPS_APN_BEARER_IPV4: conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IP; break; case AGPS_APN_BEARER_IPV6: conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV6; break; case AGPS_APN_BEARER_IPV4V6: conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV4V6; break; default: conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_PPP; } LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS open %s, APN name = [%s], pdp_type = %d\n", log_succ_fail_string(is_succ), apn, conn_multi_open_status_ptr->pdp_type); } // Make the IOCTL call return convertErr( loc_eng_ioctl(client_handle, ioctl_data.disc, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL) ); } enum loc_api_adapter_err LocApiRpc::atlCloseStatus(int handle, int is_succ) { rpc_loc_ioctl_data_u_type ioctl_data; ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS; rpc_loc_server_close_status_s_type *conn_close_status_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_close_status; conn_close_status_ptr->conn_handle = handle; conn_close_status_ptr->close_status = is_succ ? RPC_LOC_SERVER_CLOSE_SUCCESS : RPC_LOC_SERVER_CLOSE_FAIL; // Make the IOCTL call return convertErr( loc_eng_ioctl(client_handle, ioctl_data.disc, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL) ); } void LocApiRpc::ATLEvent(const rpc_loc_server_request_s_type *server_request_ptr) { int connHandle; AGpsType agps_type; LOC_LOGV("RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST event %s)", loc_get_event_atl_open_name(server_request_ptr->event)); switch (server_request_ptr->event) { case RPC_LOC_SERVER_REQUEST_MULTI_OPEN: connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.conn_handle; if (server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.connection_type == RPC_LOC_SERVER_CONNECTION_LBS) { agps_type = AGPS_TYPE_SUPL; LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n type - AGPS_TYPE_SUPL\n handle - %d", connHandle); } else { agps_type = AGPS_TYPE_WWAN_ANY; LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n type - AGPS_TYPE_WWAN_ANY\n handle - %d", connHandle); } requestATL(connHandle, agps_type); break; case RPC_LOC_SERVER_REQUEST_OPEN: connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.open_req.conn_handle; LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_OPEN\n handle - %d", connHandle); requestATL(connHandle, AGPS_TYPE_INVALID); break; case RPC_LOC_SERVER_REQUEST_CLOSE: connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.close_req.conn_handle; LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_CLOSE\n handle - %d", connHandle); releaseATL(connHandle); break; default: LOC_LOGE("ATLEvent: event type %d invalid", server_request_ptr->event); } } void LocApiRpc::NIEvent(const rpc_loc_ni_event_s_type *ni_req) { GpsNiNotification notif = {0}; switch (ni_req->event) { case RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ: { const rpc_loc_ni_vx_notify_verify_req_s_type *vx_req = &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.vx_req; LOC_LOGI("VX Notification"); notif.ni_type = GPS_NI_TYPE_VOICE; // Requestor ID hexcode(notif.requestor_id, sizeof notif.requestor_id, vx_req->requester_id.requester_id, vx_req->requester_id.requester_id_length); notif.text_encoding = 0; // No text and no encoding notif.requestor_id_encoding = convertNiEncodingType(vx_req->encoding_scheme); NIEventFillVerfiyType(notif, vx_req->notification_priv_type); } break; case RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ: { const rpc_loc_ni_umts_cp_notify_verify_req_s_type *umts_cp_req = &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.umts_cp_req; LOC_LOGI("UMTS CP Notification\n"); notif.ni_type= GPS_NI_TYPE_UMTS_CTRL_PLANE; // Stores notification text #if (AMSS_VERSION==3200) hexcode(notif.text, sizeof notif.text, umts_cp_req->notification_text.notification_text_val, umts_cp_req->notification_length); hexcode(notif.requestor_id, sizeof notif.requestor_id, umts_cp_req->requestor_id.requestor_id_string.requestor_id_string_val, umts_cp_req->requestor_id.string_len); #else hexcode(notif.text, sizeof notif.text, umts_cp_req->notification_text, umts_cp_req->notification_length); hexcode(notif.requestor_id, sizeof notif.requestor_id, umts_cp_req->requestor_id.requestor_id_string, umts_cp_req->requestor_id.string_len); #endif notif.text_encoding = convertNiEncodingType(umts_cp_req->datacoding_scheme); notif.requestor_id_encoding = notif.text_encoding; NIEventFillVerfiyType(notif, umts_cp_req->notification_priv_type); // LCS address (using extras field) if (umts_cp_req->ext_client_address_data.ext_client_address_len != 0) { // 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; #if (AMSS_VERSION==3200) address_source = umts_cp_req->ext_client_address_data.ext_client_address.ext_client_address_val; #else address_source = umts_cp_req->ext_client_address_data.ext_client_address; #endif /* #if (AMSS_VERSION==3200) */ char lcs_addr[32]; // Decoded LCS address for UMTS CP NI addr_len = decodeAddress(lcs_addr, sizeof lcs_addr, address_source, umts_cp_req->ext_client_address_data.ext_client_address_len); // The address is ASCII string if (addr_len) { strlcat(notif.extras, lcs_addr, sizeof notif.extras); } } } break; case RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ: { const rpc_loc_ni_supl_notify_verify_req_s_type *supl_req = &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req; LOC_LOGI("SUPL Notification\n"); notif.ni_type = GPS_NI_TYPE_UMTS_SUPL; if (supl_req->flags & RPC_LOC_NI_CLIENT_NAME_PRESENT) { #if (AMSS_VERSION==3200) hexcode(notif.text, sizeof notif.text, supl_req->client_name.client_name_string.client_name_string_val, /* buffer */ supl_req->client_name.string_len /* length */ ); #else hexcode(notif.text, sizeof notif.text, supl_req->client_name.client_name_string, /* buffer */ supl_req->client_name.string_len /* length */ ); #endif /* #if (AMSS_VERSION==3200) */ LOC_LOGV("SUPL NI: client_name: %s len=%d", notif.text, supl_req->client_name.string_len); } else { LOC_LOGV("SUPL NI: client_name not present."); } // Requestor ID if (supl_req->flags & RPC_LOC_NI_REQUESTOR_ID_PRESENT) { #if (AMSS_VERSION==3200) hexcode(notif.requestor_id, sizeof notif.requestor_id, supl_req->requestor_id.requestor_id_string.requestor_id_string_val, /* buffer */ supl_req->requestor_id.string_len /* length */ ); #else hexcode(notif.requestor_id, sizeof notif.requestor_id, supl_req->requestor_id.requestor_id_string, /* buffer */ supl_req->requestor_id.string_len /* length */ ); #endif /* #if (AMSS_VERSION==3200) */ LOC_LOGV("SUPL NI: requestor_id: %s len=%d", notif.requestor_id, supl_req->requestor_id.string_len); } else { LOC_LOGV("SUPL NI: requestor_id not present."); } // Encoding type if (supl_req->flags & RPC_LOC_NI_ENCODING_TYPE_PRESENT) { notif.text_encoding = convertNiEncodingType(supl_req->datacoding_scheme); notif.requestor_id_encoding = notif.text_encoding; } else { notif.text_encoding = notif.requestor_id_encoding = GPS_ENC_UNKNOWN; } NIEventFillVerfiyType(notif, ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req.notification_priv_type); } break; default: LOC_LOGE("Unknown NI event: %x\n", (int) ni_req->event); return; } // this copy will get freed in loc_eng_ni when loc_ni_respond() is called rpc_loc_ni_event_s_type *copy = (rpc_loc_ni_event_s_type *)malloc(sizeof(*copy)); memcpy(copy, ni_req, sizeof(*copy)); requestNiNotify(notif, (const void*)copy); } int LocApiRpc::NIEventFillVerfiyType(GpsNiNotification ¬if, rpc_loc_ni_notify_verify_e_type notif_priv) { switch (notif_priv) { case RPC_LOC_NI_USER_NO_NOTIFY_NO_VERIFY: notif.notify_flags = 0; notif.default_response = GPS_NI_RESPONSE_NORESP; return 1; case RPC_LOC_NI_USER_NOTIFY_ONLY: notif.notify_flags = GPS_NI_NEED_NOTIFY; notif.default_response = GPS_NI_RESPONSE_NORESP; return 1; case RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP: notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; notif.default_response = GPS_NI_RESPONSE_ACCEPT; return 1; case RPC_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP: notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; notif.default_response = GPS_NI_RESPONSE_DENY; return 1; case RPC_LOC_NI_USER_PRIVACY_OVERRIDE: notif.notify_flags = GPS_NI_PRIVACY_OVERRIDE; notif.default_response = GPS_NI_RESPONSE_NORESP; return 1; default: return 0; } } enum loc_api_adapter_err LocApiRpc::setSUPLVersion(uint32_t version) { rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_SUPL_VERSION, {0}}; ioctl_data.rpc_loc_ioctl_data_u_type_u.supl_version = (int)version; return convertErr( loc_eng_ioctl (client_handle, RPC_LOC_IOCTL_SET_SUPL_VERSION, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL) ); } GpsNiEncodingType LocApiRpc::convertNiEncodingType(int loc_encoding) { switch (loc_encoding) { case RPC_LOC_NI_SUPL_UTF8: return GPS_ENC_SUPL_UTF8; case RPC_LOC_NI_SUPL_UCS2: return GPS_ENC_SUPL_UCS2; case RPC_LOC_NI_SUPL_GSM_DEFAULT: return GPS_ENC_SUPL_GSM_DEFAULT; case RPC_LOC_NI_SS_LANGUAGE_UNSPEC: return GPS_ENC_SUPL_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM default: return GPS_ENC_UNKNOWN; } } LocApiBase* getLocApi(const MsgTask* msgTask, LOC_API_ADAPTER_EVENT_MASK_T exMask, ContextBase *context) { return new LocApiRpc(msgTask, exMask, context); } /*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 */ int LocApiRpc::setGpsLock(LOC_GPS_LOCK_MASK lockMask) { rpc_loc_ioctl_data_u_type ioctl_data; boolean ret_val; LOC_LOGD("%s:%d]: lock: %x\n", __func__, __LINE__, lockMask); ioctl_data.rpc_loc_ioctl_data_u_type_u.engine_lock = convertGpsLockMask(lockMask); ioctl_data.disc = RPC_LOC_IOCTL_SET_ENGINE_LOCK; ret_val = loc_eng_ioctl (loc_eng_data.client_handle, RPC_LOC_IOCTL_SET_ENGINE_LOCK, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, NULL /* No output information is expected*/); LOC_LOGD("%s:%d]: ret_val: %d\n", __func__, __LINE__, (int)ret_val); return (ret_val == TRUE ? 0 : -1); } /* Returns Current value of GPS lock on success -1 on failure */ int LocApiRpc :: getGpsLock() { rpc_loc_ioctl_data_u_type ioctl_data; rpc_loc_ioctl_callback_s_type callback_payload; boolean ret_val; int ret=0; LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); ret_val = loc_eng_ioctl (loc_eng_data.client_handle, RPC_LOC_IOCTL_GET_ENGINE_LOCK, &ioctl_data, LOC_IOCTL_DEFAULT_TIMEOUT, &callback_payload); if(ret_val == TRUE) { ret = (int)callback_payload.data.engine_lock; LOC_LOGD("%s:%d]: Lock type: %d\n", __func__, __LINE__, ret); } else { LOC_LOGE("%s:%d]: Ioctl failed", __func__, __LINE__); ret = -1; } LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__); return ret; }