android13/system/chre/chpp/clients/gnss.c

862 lines
29 KiB
C

/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "chpp/clients/gnss.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "chpp/app.h"
#include "chpp/clients.h"
#include "chpp/clients/discovery.h"
#include "chpp/common/gnss.h"
#include "chpp/common/gnss_types.h"
#include "chpp/common/standard_uuids.h"
#include "chpp/log.h"
#include "chpp/macros.h"
#include "chpp/memory.h"
#include "chre/pal/gnss.h"
#include "chre_api/chre/gnss.h"
#ifndef CHPP_GNSS_DISCOVERY_TIMEOUT_MS
#define CHPP_GNSS_DISCOVERY_TIMEOUT_MS CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS
#endif
/************************************************
* Prototypes
***********************************************/
static enum ChppAppErrorCode chppDispatchGnssResponse(void *clientContext,
uint8_t *buf, size_t len);
static enum ChppAppErrorCode chppDispatchGnssNotification(void *clientContext,
uint8_t *buf,
size_t len);
static bool chppGnssClientInit(void *clientContext, uint8_t handle,
struct ChppVersion serviceVersion);
static void chppGnssClientDeinit(void *clientContext);
static void chppGnssClientNotifyReset(void *clientContext);
static void chppGnssClientNotifyMatch(void *clientContext);
/************************************************
* Private Definitions
***********************************************/
/**
* Structure to maintain state for the GNSS client and its Request/Response
* (RR) functionality.
*/
struct ChppGnssClientState {
struct ChppClientState client; // GNSS client state
const struct chrePalGnssApi *api; // GNSS PAL API
struct ChppRequestResponseState rRState[CHPP_GNSS_CLIENT_REQUEST_MAX + 1];
uint32_t capabilities; // Cached GetCapabilities result
bool requestStateResyncPending; // requestStateResync() is waiting to be
// processed
bool capabilitiesValid; // Flag to indicate if the capabilities result
// is valid
};
// Note: This global definition of gGnssClientContext supports only one
// instance of the CHPP GNSS client at a time.
struct ChppGnssClientState gGnssClientContext;
static const struct chrePalSystemApi *gSystemApi;
static const struct chrePalGnssCallbacks *gCallbacks;
/**
* Configuration parameters for this client
*/
static const struct ChppClient kGnssClientConfig = {
.descriptor.uuid = CHPP_UUID_GNSS_STANDARD,
// Version
.descriptor.version.major = 1,
.descriptor.version.minor = 0,
.descriptor.version.patch = 0,
// Notifies client if CHPP is reset
.resetNotifierFunctionPtr = &chppGnssClientNotifyReset,
// Notifies client if they are matched to a service
.matchNotifierFunctionPtr = &chppGnssClientNotifyMatch,
// Service response dispatch function pointer
.responseDispatchFunctionPtr = &chppDispatchGnssResponse,
// Service notification dispatch function pointer
.notificationDispatchFunctionPtr = &chppDispatchGnssNotification,
// Service response dispatch function pointer
.initFunctionPtr = &chppGnssClientInit,
// Service notification dispatch function pointer
.deinitFunctionPtr = &chppGnssClientDeinit,
// Number of request-response states in the rRStates array.
.rRStateCount = ARRAY_SIZE(gGnssClientContext.rRState),
// Min length is the entire header
.minLength = sizeof(struct ChppAppHeader),
};
/************************************************
* Prototypes
***********************************************/
static bool chppGnssClientOpen(const struct chrePalSystemApi *systemApi,
const struct chrePalGnssCallbacks *callbacks);
static void chppGnssClientClose(void);
static uint32_t chppGnssClientGetCapabilities(void);
static bool chppGnssClientControlLocationSession(bool enable,
uint32_t minIntervalMs,
uint32_t minTimeToNextFixMs);
static void chppGnssClientReleaseLocationEvent(
struct chreGnssLocationEvent *event);
static bool chppGnssClientControlMeasurementSession(bool enable,
uint32_t minIntervalMs);
static void chppGnssClientReleaseMeasurementDataEvent(
struct chreGnssDataEvent *event);
static bool chppGnssClientConfigurePassiveLocationListener(bool enable);
static void chppGnssCloseResult(struct ChppGnssClientState *clientContext,
uint8_t *buf, size_t len);
static void chppGnssGetCapabilitiesResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
static void chppGnssControlLocationSessionResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
static void chppGnssControlMeasurementSessionResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
static void chppGnssConfigurePassiveLocationListenerResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
static void chppGnssStateResyncNotification(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
static void chppGnssLocationResultNotification(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
static void chppGnssMeasurementResultNotification(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len);
/************************************************
* Private Functions
***********************************************/
/**
* Dispatches a service response from the transport layer that is determined to
* be for the GNSS client.
*
* This function is called from the app layer using its function pointer given
* during client registration.
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*
* @return Indicates the result of this function call.
*/
static enum ChppAppErrorCode chppDispatchGnssResponse(void *clientContext,
uint8_t *buf,
size_t len) {
struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
struct ChppGnssClientState *gnssClientContext =
(struct ChppGnssClientState *)clientContext;
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
if (rxHeader->command > CHPP_GNSS_CLIENT_REQUEST_MAX) {
error = CHPP_APP_ERROR_INVALID_COMMAND;
} else if (!chppClientTimestampResponse(
&gnssClientContext->client,
&gnssClientContext->rRState[rxHeader->command], rxHeader)) {
error = CHPP_APP_ERROR_UNEXPECTED_RESPONSE;
} else {
switch (rxHeader->command) {
case CHPP_GNSS_OPEN: {
chppClientProcessOpenResponse(&gnssClientContext->client, buf, len);
if (gnssClientContext->requestStateResyncPending) {
gCallbacks->requestStateResync();
gnssClientContext->requestStateResyncPending = false;
}
break;
}
case CHPP_GNSS_CLOSE: {
chppGnssCloseResult(gnssClientContext, buf, len);
break;
}
case CHPP_GNSS_GET_CAPABILITIES: {
chppGnssGetCapabilitiesResult(gnssClientContext, buf, len);
break;
}
case CHPP_GNSS_CONTROL_LOCATION_SESSION: {
chppGnssControlLocationSessionResult(gnssClientContext, buf, len);
break;
}
case CHPP_GNSS_CONTROL_MEASUREMENT_SESSION: {
chppGnssControlMeasurementSessionResult(gnssClientContext, buf, len);
break;
}
case CHPP_GNSS_CONFIGURE_PASSIVE_LOCATION_LISTENER: {
chppGnssConfigurePassiveLocationListenerResult(gnssClientContext, buf,
len);
break;
}
default: {
error = CHPP_APP_ERROR_INVALID_COMMAND;
break;
}
}
}
return error;
}
/**
* Dispatches a service notification from the transport layer that is determined
* to be for the GNSS client.
*
* This function is called from the app layer using its function pointer given
* during client registration.
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*
* @return Indicates the result of this function call.
*/
static enum ChppAppErrorCode chppDispatchGnssNotification(void *clientContext,
uint8_t *buf,
size_t len) {
struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
struct ChppGnssClientState *gnssClientContext =
(struct ChppGnssClientState *)clientContext;
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
switch (rxHeader->command) {
case CHPP_GNSS_REQUEST_STATE_RESYNC_NOTIFICATION: {
chppGnssStateResyncNotification(gnssClientContext, buf, len);
break;
}
case CHPP_GNSS_LOCATION_RESULT_NOTIFICATION: {
chppGnssLocationResultNotification(gnssClientContext, buf, len);
break;
}
case CHPP_GNSS_MEASUREMENT_RESULT_NOTIFICATION: {
chppGnssMeasurementResultNotification(gnssClientContext, buf, len);
break;
}
default: {
error = CHPP_APP_ERROR_INVALID_COMMAND;
break;
}
}
return error;
}
/**
* Initializes the client and provides its handle number and the version of the
* matched service when/if it the client is matched with a service during
* discovery.
*
* @param clientContext Maintains status for each client instance.
* @param handle Handle number for this client.
* @param serviceVersion Version of the matched service.
*
* @return True if client is compatible and successfully initialized.
*/
static bool chppGnssClientInit(void *clientContext, uint8_t handle,
struct ChppVersion serviceVersion) {
UNUSED_VAR(serviceVersion);
struct ChppGnssClientState *gnssClientContext =
(struct ChppGnssClientState *)clientContext;
chppClientInit(&gnssClientContext->client, handle);
return true;
}
/**
* Deinitializes the client.
*
* @param clientContext Maintains status for each client instance.
*/
static void chppGnssClientDeinit(void *clientContext) {
struct ChppGnssClientState *gnssClientContext =
(struct ChppGnssClientState *)clientContext;
chppClientDeinit(&gnssClientContext->client);
}
/**
* Notifies the client of an incoming reset.
*
* @param clientContext Maintains status for each client instance.
*/
static void chppGnssClientNotifyReset(void *clientContext) {
struct ChppGnssClientState *gnssClientContext =
(struct ChppGnssClientState *)clientContext;
chppClientCloseOpenRequests(&gnssClientContext->client, &kGnssClientConfig,
false /* clearOnly */);
if (gnssClientContext->client.openState != CHPP_OPEN_STATE_OPENED &&
!gnssClientContext->client.pseudoOpen) {
CHPP_LOGW("GNSS client reset but wasn't open");
} else {
CHPP_LOGI("GNSS client reopening from state=%" PRIu8,
gnssClientContext->client.openState);
gnssClientContext->requestStateResyncPending = true;
chppClientSendOpenRequest(&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_OPEN],
CHPP_GNSS_OPEN,
/*blocking=*/false);
}
}
/**
* Notifies the client of being matched to a service.
*
* @param clientContext Maintains status for each client instance.
*/
static void chppGnssClientNotifyMatch(void *clientContext) {
struct ChppGnssClientState *gnssClientContext =
(struct ChppGnssClientState *)clientContext;
if (gnssClientContext->client.pseudoOpen) {
CHPP_LOGD("Pseudo-open GNSS client opening");
chppClientSendOpenRequest(&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_OPEN],
CHPP_GNSS_OPEN,
/*blocking=*/false);
}
}
/**
* Handles the service response for the close client request.
*
* This function is called from chppDispatchGnssResponse().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssCloseResult(struct ChppGnssClientState *clientContext,
uint8_t *buf, size_t len) {
// TODO
UNUSED_VAR(clientContext);
UNUSED_VAR(buf);
UNUSED_VAR(len);
}
/**
* Handles the service response for the get capabilities client request.
*
* This function is called from chppDispatchGnssResponse().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssGetCapabilitiesResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
if (len < sizeof(struct ChppGnssGetCapabilitiesResponse)) {
CHPP_LOGE("Bad GNSS capabilities len=%" PRIuSIZE, len);
} else {
struct ChppGnssGetCapabilitiesParameters *result =
&((struct ChppGnssGetCapabilitiesResponse *)buf)->params;
CHPP_LOGD("chppGnssGetCapabilitiesResult received capabilities=0x%" PRIx32,
result->capabilities);
CHPP_ASSERT((result->capabilities & CHPP_GNSS_DEFAULT_CAPABILITIES) ==
CHPP_GNSS_DEFAULT_CAPABILITIES);
if (result->capabilities != CHPP_GNSS_DEFAULT_CAPABILITIES) {
CHPP_LOGE("GNSS capabilities 0x%" PRIx32 " != 0x%" PRIx32,
result->capabilities, CHPP_GNSS_DEFAULT_CAPABILITIES);
}
clientContext->capabilitiesValid = true;
clientContext->capabilities = result->capabilities;
}
}
/**
* Handles the service response for the Control Location Session client request.
*
* This function is called from chppDispatchGnssResponse().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssControlLocationSessionResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
UNUSED_VAR(clientContext);
if (len < sizeof(struct ChppGnssControlLocationSessionResponse)) {
// Short response length indicates an error
gCallbacks->locationStatusChangeCallback(
false, chppAppShortResponseErrorHandler(buf, len, "ControlLocation"));
} else {
struct ChppGnssControlLocationSessionResponse *result =
(struct ChppGnssControlLocationSessionResponse *)buf;
CHPP_LOGD(
"chppGnssControlLocationSessionResult received enable=%d, "
"errorCode=%" PRIu8,
result->enabled, result->errorCode);
gCallbacks->locationStatusChangeCallback(result->enabled,
result->errorCode);
}
}
/**
* Handles the service response for the Control Measurement Session client
* request.
*
* This function is called from chppDispatchGnssResponse().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssControlMeasurementSessionResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
UNUSED_VAR(clientContext);
if (len < sizeof(struct ChppGnssControlMeasurementSessionResponse)) {
// Short response length indicates an error
gCallbacks->measurementStatusChangeCallback(
false, chppAppShortResponseErrorHandler(buf, len, "Measurement"));
} else {
struct ChppGnssControlMeasurementSessionResponse *result =
(struct ChppGnssControlMeasurementSessionResponse *)buf;
CHPP_LOGD(
"chppGnssControlMeasurementSessionResult received enable=%d, "
"errorCode=%" PRIu8,
result->enabled, result->errorCode);
gCallbacks->measurementStatusChangeCallback(result->enabled,
result->errorCode);
}
}
/**
* Handles the service response for the Configure Passive Location Listener
* client request.
*
* This function is called from chppDispatchGnssResponse().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssConfigurePassiveLocationListenerResult(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
UNUSED_VAR(clientContext);
UNUSED_VAR(len);
struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
if (rxHeader->error != CHPP_APP_ERROR_NONE) {
CHPP_DEBUG_ASSERT_LOG(false, "Passive scan failed at service");
} else {
CHPP_LOGD(
"WiFi ConfigurePassiveLocationListener request accepted at service");
}
}
/**
* Handles the State Resync service notification.
*
* This function is called from chppDispatchGnssNotification().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssStateResyncNotification(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
UNUSED_VAR(buf);
UNUSED_VAR(len);
if (clientContext->client.openState == CHPP_OPEN_STATE_WAITING_TO_OPEN) {
// If the GNSS client is waiting for the open to proceed, the CHRE handler
// for requestStateResync() may fail, so we set a flag to process it later
// when the open has succeeded.
clientContext->requestStateResyncPending = true;
} else {
gCallbacks->requestStateResync();
clientContext->requestStateResyncPending = false;
}
}
/**
* Handles the Location Result service notification.
*
* This function is called from chppDispatchGnssNotification().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssLocationResultNotification(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
UNUSED_VAR(clientContext);
CHPP_LOGD("chppGnssLocationResultNotification received data len=%" PRIuSIZE,
len);
buf += sizeof(struct ChppAppHeader);
len -= sizeof(struct ChppAppHeader);
struct chreGnssLocationEvent *chre =
chppGnssLocationEventToChre((struct ChppGnssLocationEvent *)buf, len);
if (chre == NULL) {
CHPP_LOGE("Location result conversion failed: len=%" PRIuSIZE, len);
} else {
gCallbacks->locationEventCallback(chre);
}
}
/**
* Handles the Measurement Result service notification.
*
* This function is called from chppDispatchGnssNotification().
*
* @param clientContext Maintains status for each client instance.
* @param buf Input data. Cannot be null.
* @param len Length of input data in bytes.
*/
static void chppGnssMeasurementResultNotification(
struct ChppGnssClientState *clientContext, uint8_t *buf, size_t len) {
UNUSED_VAR(clientContext);
CHPP_LOGD(
"chppGnssMeasurementResultNotification received data len=%" PRIuSIZE,
len);
buf += sizeof(struct ChppAppHeader);
len -= sizeof(struct ChppAppHeader);
struct chreGnssDataEvent *chre =
chppGnssDataEventToChre((struct ChppGnssDataEvent *)buf, len);
if (chre == NULL) {
CHPP_LOGE("Measurement result conversion failed len=%" PRIuSIZE, len);
} else {
gCallbacks->measurementEventCallback(chre);
}
}
/**
* Initializes the GNSS client upon an open request from CHRE and responds
* with the result.
*
* @param systemApi CHRE system function pointers.
* @param callbacks CHRE entry points.
*
* @return True if successful. False otherwise.
*/
static bool chppGnssClientOpen(const struct chrePalSystemApi *systemApi,
const struct chrePalGnssCallbacks *callbacks) {
CHPP_DEBUG_ASSERT(systemApi != NULL);
CHPP_DEBUG_ASSERT(callbacks != NULL);
bool result = false;
gSystemApi = systemApi;
gCallbacks = callbacks;
CHPP_LOGD("GNSS client opening");
if (gGnssClientContext.client.appContext == NULL) {
CHPP_LOGE("GNSS client app is null");
} else {
if (chppWaitForDiscoveryComplete(gGnssClientContext.client.appContext,
CHPP_GNSS_DISCOVERY_TIMEOUT_MS)) {
result = chppClientSendOpenRequest(
&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_OPEN], CHPP_GNSS_OPEN,
/*blocking=*/true);
}
// Since CHPP_GNSS_DEFAULT_CAPABILITIES is mandatory, we can always
// pseudo-open and return true. Otherwise, these should have been gated.
chppClientPseudoOpen(&gGnssClientContext.client);
result = true;
}
return result;
}
/**
* Deinitializes the GNSS client.
*/
static void chppGnssClientClose(void) {
// Remote
struct ChppAppHeader *request = chppAllocClientRequestCommand(
&gGnssClientContext.client, CHPP_GNSS_CLOSE);
if (request == NULL) {
CHPP_LOG_OOM();
} else if (chppSendTimestampedRequestAndWait(
&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_CLOSE], request,
sizeof(*request))) {
gGnssClientContext.client.openState = CHPP_OPEN_STATE_CLOSED;
gGnssClientContext.capabilities = CHRE_GNSS_CAPABILITIES_NONE;
gGnssClientContext.capabilitiesValid = false;
chppClientCloseOpenRequests(&gGnssClientContext.client, &kGnssClientConfig,
true /* clearOnly */);
}
}
/**
* Retrieves a set of flags indicating the GNSS features supported by the
* current implementation.
*
* @return Capabilities flags.
*/
static uint32_t chppGnssClientGetCapabilities(void) {
uint32_t capabilities = CHPP_GNSS_DEFAULT_CAPABILITIES;
if (gGnssClientContext.capabilitiesValid) {
// Result already cached
capabilities = gGnssClientContext.capabilities;
} else {
struct ChppAppHeader *request = chppAllocClientRequestCommand(
&gGnssClientContext.client, CHPP_GNSS_GET_CAPABILITIES);
if (request == NULL) {
CHPP_LOG_OOM();
} else {
if (chppSendTimestampedRequestAndWait(
&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_GET_CAPABILITIES], request,
sizeof(*request))) {
// Success. gGnssClientContext.capabilities is now populated
if (gGnssClientContext.capabilitiesValid) {
capabilities = gGnssClientContext.capabilities;
}
}
}
}
return capabilities;
}
/**
* Start/stop/modify the GNSS location session used for clients of the CHRE
* API.
*
* @param enable true to start/modify the session, false to stop the
* session. If false, other parameters are ignored.
* @param minIntervalMs See chreGnssLocationSessionStartAsync()
* @param minTimeToNextFixMs See chreGnssLocationSessionStartAsync()
*
* @return True indicates the request was sent off to the service.
*/
static bool chppGnssClientControlLocationSession(bool enable,
uint32_t minIntervalMs,
uint32_t minTimeToNextFixMs) {
bool result = false;
struct ChppGnssControlLocationSessionRequest *request =
chppAllocClientRequestFixed(&gGnssClientContext.client,
struct ChppGnssControlLocationSessionRequest);
if (request == NULL) {
CHPP_LOG_OOM();
} else {
request->header.command = CHPP_GNSS_CONTROL_LOCATION_SESSION;
request->params.enable = enable;
request->params.minIntervalMs = minIntervalMs;
request->params.minTimeToNextFixMs = minTimeToNextFixMs;
result = chppSendTimestampedRequestOrFail(
&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_CONTROL_LOCATION_SESSION],
request, sizeof(*request), CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS);
}
return result;
}
/**
* Releases the memory held for the location event callback.
*
* @param event Location event to be released.
*/
static void chppGnssClientReleaseLocationEvent(
struct chreGnssLocationEvent *event) {
CHPP_FREE_AND_NULLIFY(event);
}
/**
* Start/stop/modify the raw GNSS measurement session used for clients of the
* CHRE API.
*
* @param enable true to start/modify the session, false to stop the
* session. If false, other parameters are ignored.
* @param minIntervalMs See chreGnssMeasurementSessionStartAsync()
*
* @return True indicates the request was sent off to the service.
*/
static bool chppGnssClientControlMeasurementSession(bool enable,
uint32_t minIntervalMs) {
bool result = false;
struct ChppGnssControlMeasurementSessionRequest *request =
chppAllocClientRequestFixed(
&gGnssClientContext.client,
struct ChppGnssControlMeasurementSessionRequest);
if (request == NULL) {
CHPP_LOG_OOM();
} else {
request->header.command = CHPP_GNSS_CONTROL_MEASUREMENT_SESSION;
request->params.enable = enable;
request->params.minIntervalMs = minIntervalMs;
result = chppSendTimestampedRequestOrFail(
&gGnssClientContext.client,
&gGnssClientContext.rRState[CHPP_GNSS_CONTROL_MEASUREMENT_SESSION],
request, sizeof(*request), CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS);
}
return result;
}
/**
* Releases the memory held for the measurement event callback.
*
* @param event Measurement event to be released.
*/
static void chppGnssClientReleaseMeasurementDataEvent(
struct chreGnssDataEvent *event) {
if (event->measurement_count > 0) {
void *measurements = CHPP_CONST_CAST_POINTER(event->measurements);
CHPP_FREE_AND_NULLIFY(measurements);
}
CHPP_FREE_AND_NULLIFY(event);
}
/**
* Starts/stops opportunistic delivery of location fixes.
*
* @param enable true to turn the passive location listener on, false to
* turn it off.
*
* @return True indicates the request was sent off to the service.
*/
static bool chppGnssClientConfigurePassiveLocationListener(bool enable) {
bool result = false;
struct ChppGnssConfigurePassiveLocationListenerRequest *request =
chppAllocClientRequestFixed(
&gGnssClientContext.client,
struct ChppGnssConfigurePassiveLocationListenerRequest);
if (request == NULL) {
CHPP_LOG_OOM();
} else {
request->header.command = CHPP_GNSS_CONFIGURE_PASSIVE_LOCATION_LISTENER;
request->params.enable = enable;
result = chppSendTimestampedRequestOrFail(
&gGnssClientContext.client,
&gGnssClientContext
.rRState[CHPP_GNSS_CONFIGURE_PASSIVE_LOCATION_LISTENER],
request, sizeof(*request), CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT);
}
return result;
}
/************************************************
* Public Functions
***********************************************/
void chppRegisterGnssClient(struct ChppAppState *appContext) {
chppRegisterClient(appContext, (void *)&gGnssClientContext,
&gGnssClientContext.client, gGnssClientContext.rRState,
&kGnssClientConfig);
}
void chppDeregisterGnssClient(struct ChppAppState *appContext) {
// TODO
UNUSED_VAR(appContext);
}
struct ChppClientState *getChppGnssClientState(void) {
return &gGnssClientContext.client;
}
#ifdef CHPP_CLIENT_ENABLED_GNSS
#ifdef CHPP_CLIENT_ENABLED_CHRE_GNSS
const struct chrePalGnssApi *chrePalGnssGetApi(uint32_t requestedApiVersion) {
#else
const struct chrePalGnssApi *chppPalGnssGetApi(uint32_t requestedApiVersion) {
#endif
static const struct chrePalGnssApi api = {
.moduleVersion = CHPP_PAL_GNSS_API_VERSION,
.open = chppGnssClientOpen,
.close = chppGnssClientClose,
.getCapabilities = chppGnssClientGetCapabilities,
.controlLocationSession = chppGnssClientControlLocationSession,
.releaseLocationEvent = chppGnssClientReleaseLocationEvent,
.controlMeasurementSession = chppGnssClientControlMeasurementSession,
.releaseMeasurementDataEvent = chppGnssClientReleaseMeasurementDataEvent,
.configurePassiveLocationListener =
chppGnssClientConfigurePassiveLocationListener,
};
CHPP_STATIC_ASSERT(
CHRE_PAL_GNSS_API_CURRENT_VERSION == CHPP_PAL_GNSS_API_VERSION,
"A newer CHRE PAL API version is available. Please update.");
if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(api.moduleVersion,
requestedApiVersion)) {
return NULL;
} else {
return &api;
}
}
#endif