You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
688 lines
24 KiB
688 lines
24 KiB
/*
|
|
* 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/services/gnss.h"
|
|
|
|
#include <inttypes.h>
|
|
#include <stddef.h>
|
|
#include <stdint.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/services.h"
|
|
#include "chre/pal/gnss.h"
|
|
|
|
/************************************************
|
|
* Prototypes
|
|
***********************************************/
|
|
|
|
static enum ChppAppErrorCode chppDispatchGnssRequest(void *serviceContext,
|
|
uint8_t *buf, size_t len);
|
|
static void chppGnssServiceNotifyReset(void *serviceContext);
|
|
|
|
/************************************************
|
|
* Private Definitions
|
|
***********************************************/
|
|
|
|
/**
|
|
* Configuration parameters for this service
|
|
*/
|
|
static const struct ChppService kGnssServiceConfig = {
|
|
.descriptor.uuid = CHPP_UUID_GNSS_STANDARD,
|
|
|
|
// Human-readable name
|
|
.descriptor.name = "GNSS",
|
|
|
|
// Version
|
|
.descriptor.version.major = 1,
|
|
.descriptor.version.minor = 0,
|
|
.descriptor.version.patch = 0,
|
|
|
|
// Notifies service if CHPP is reset
|
|
.resetNotifierFunctionPtr = &chppGnssServiceNotifyReset,
|
|
|
|
// Client request dispatch function pointer
|
|
.requestDispatchFunctionPtr = &chppDispatchGnssRequest,
|
|
|
|
// Client notification dispatch function pointer
|
|
.notificationDispatchFunctionPtr = NULL, // Not supported
|
|
|
|
// Min length is the entire header
|
|
.minLength = sizeof(struct ChppAppHeader),
|
|
};
|
|
|
|
/**
|
|
* Structure to maintain state for the GNSS service and its Request/Response
|
|
* (RR) functionality.
|
|
*/
|
|
struct ChppGnssServiceState {
|
|
struct ChppServiceState service; // GNSS service state
|
|
const struct chrePalGnssApi *api; // GNSS PAL API
|
|
|
|
// Based on chre/pal/gnss.h and chrePalGnssApi
|
|
struct ChppRequestResponseState open; // Service init state
|
|
struct ChppRequestResponseState close; // Service deinit state
|
|
struct ChppRequestResponseState getCapabilities; // Get Capabilities state
|
|
struct ChppRequestResponseState
|
|
controlLocationSession; // Control Location measurement state
|
|
struct ChppRequestResponseState
|
|
controlMeasurementSession; // Control Raw GNSS measurement state
|
|
struct ChppRequestResponseState
|
|
configurePassiveLocationListener; // Configure Passive location receiving
|
|
// state
|
|
};
|
|
|
|
// Note: The CHRE PAL API only allows for one definition - see comment in WWAN
|
|
// service for details.
|
|
// Note: There is no notion of a cookie in the CHRE GNSS API so we need to use
|
|
// the global service state (gGnssServiceContext) directly in all callbacks.
|
|
struct ChppGnssServiceState gGnssServiceContext;
|
|
|
|
/************************************************
|
|
* Prototypes
|
|
***********************************************/
|
|
|
|
static enum ChppAppErrorCode chppGnssServiceOpen(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader);
|
|
static enum ChppAppErrorCode chppGnssServiceClose(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader);
|
|
static enum ChppAppErrorCode chppGnssServiceGetCapabilities(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader);
|
|
static enum ChppAppErrorCode chppGnssServiceControlLocationSession(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
|
|
static enum ChppAppErrorCode chppGnssServiceControlMeasurementSession(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
|
|
static enum ChppAppErrorCode chppGnssServiceConfigurePassiveLocationListener(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
|
|
|
|
static void chppGnssServiceRequestStateResyncCallback(void);
|
|
static void chppGnssServiceLocationStatusChangeCallback(bool enabled,
|
|
uint8_t errorCode);
|
|
static void chppGnssServiceLocationEventCallback(
|
|
struct chreGnssLocationEvent *event);
|
|
static void chppGnssServiceMeasurementStatusChangeCallback(bool enabled,
|
|
uint8_t errorCode);
|
|
static void chppGnssServiceMeasurementEventCallback(
|
|
struct chreGnssDataEvent *event);
|
|
|
|
/************************************************
|
|
* Private Functions
|
|
***********************************************/
|
|
|
|
/**
|
|
* Dispatches a client request from the transport layer that is determined to be
|
|
* for the GNSS service. If the result of the dispatch is an error, this
|
|
* function responds to the client with the same error.
|
|
*
|
|
* This function is called from the app layer using its function pointer given
|
|
* during service registration.
|
|
*
|
|
* @param serviceContext Maintains status for each service 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 chppDispatchGnssRequest(void *serviceContext,
|
|
uint8_t *buf, size_t len) {
|
|
struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
|
|
buf += sizeof(struct ChppAppHeader);
|
|
len -= sizeof(struct ChppAppHeader);
|
|
|
|
struct ChppGnssServiceState *gnssServiceContext =
|
|
(struct ChppGnssServiceState *)serviceContext;
|
|
struct ChppRequestResponseState *rRState = NULL;
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
bool dispatched = true;
|
|
|
|
switch (rxHeader->command) {
|
|
case CHPP_GNSS_OPEN: {
|
|
rRState = &gnssServiceContext->open;
|
|
chppServiceTimestampRequest(rRState, rxHeader);
|
|
error = chppGnssServiceOpen(gnssServiceContext, rxHeader);
|
|
break;
|
|
}
|
|
|
|
case CHPP_GNSS_CLOSE: {
|
|
rRState = &gnssServiceContext->close;
|
|
chppServiceTimestampRequest(rRState, rxHeader);
|
|
error = chppGnssServiceClose(gnssServiceContext, rxHeader);
|
|
break;
|
|
}
|
|
|
|
case CHPP_GNSS_GET_CAPABILITIES: {
|
|
rRState = &gnssServiceContext->getCapabilities;
|
|
chppServiceTimestampRequest(rRState, rxHeader);
|
|
error = chppGnssServiceGetCapabilities(gnssServiceContext, rxHeader);
|
|
break;
|
|
}
|
|
|
|
case CHPP_GNSS_CONTROL_LOCATION_SESSION: {
|
|
rRState = &gnssServiceContext->controlLocationSession;
|
|
chppServiceTimestampRequest(rRState, rxHeader);
|
|
error = chppGnssServiceControlLocationSession(gnssServiceContext,
|
|
rxHeader, buf, len);
|
|
break;
|
|
}
|
|
|
|
case CHPP_GNSS_CONTROL_MEASUREMENT_SESSION: {
|
|
rRState = &gnssServiceContext->controlMeasurementSession;
|
|
chppServiceTimestampRequest(rRState, rxHeader);
|
|
error = chppGnssServiceControlMeasurementSession(gnssServiceContext,
|
|
rxHeader, buf, len);
|
|
break;
|
|
}
|
|
|
|
case CHPP_GNSS_CONFIGURE_PASSIVE_LOCATION_LISTENER: {
|
|
rRState = &gnssServiceContext->configurePassiveLocationListener;
|
|
chppServiceTimestampRequest(rRState, rxHeader);
|
|
error = chppGnssServiceConfigurePassiveLocationListener(
|
|
gnssServiceContext, rxHeader, buf, len);
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
dispatched = false;
|
|
error = CHPP_APP_ERROR_INVALID_COMMAND;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dispatched == true && error != CHPP_APP_ERROR_NONE) {
|
|
// Request was dispatched but an error was returned. Close out
|
|
// chppServiceTimestampRequest()
|
|
chppServiceTimestampResponse(rRState);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Initializes the GNSS service upon an open request from the client and
|
|
* responds to the client with the result.
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
* @param requestHeader App layer header of the request.
|
|
*
|
|
* @return Indicates the result of this function call.
|
|
*/
|
|
static enum ChppAppErrorCode chppGnssServiceOpen(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader) {
|
|
static const struct chrePalGnssCallbacks palCallbacks = {
|
|
.requestStateResync = chppGnssServiceRequestStateResyncCallback,
|
|
.locationStatusChangeCallback =
|
|
chppGnssServiceLocationStatusChangeCallback,
|
|
.locationEventCallback = chppGnssServiceLocationEventCallback,
|
|
.measurementStatusChangeCallback =
|
|
chppGnssServiceMeasurementStatusChangeCallback,
|
|
.measurementEventCallback = chppGnssServiceMeasurementEventCallback,
|
|
};
|
|
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
|
|
if (gnssServiceContext->service.openState == CHPP_OPEN_STATE_OPENED) {
|
|
CHPP_LOGE("GNSS service already open");
|
|
CHPP_DEBUG_ASSERT(false);
|
|
error = CHPP_APP_ERROR_INVALID_COMMAND;
|
|
|
|
} else if (!gnssServiceContext->api->open(
|
|
gnssServiceContext->service.appContext->systemApi,
|
|
&palCallbacks)) {
|
|
CHPP_LOGE("GNSS PAL open failed");
|
|
CHPP_DEBUG_ASSERT(false);
|
|
error = CHPP_APP_ERROR_BEYOND_CHPP;
|
|
|
|
} else {
|
|
CHPP_LOGI("GNSS service opened");
|
|
gnssServiceContext->service.openState = CHPP_OPEN_STATE_OPENED;
|
|
|
|
struct ChppAppHeader *response =
|
|
chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
|
|
size_t responseLen = sizeof(*response);
|
|
|
|
if (response == NULL) {
|
|
CHPP_LOG_OOM();
|
|
error = CHPP_APP_ERROR_OOM;
|
|
} else {
|
|
chppSendTimestampedResponseOrFail(&gnssServiceContext->service,
|
|
&gnssServiceContext->open, response,
|
|
responseLen);
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Deinitializes the GNSS service.
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
* @param requestHeader App layer header of the request.
|
|
*
|
|
* @return Indicates the result of this function call.
|
|
*/
|
|
static enum ChppAppErrorCode chppGnssServiceClose(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader) {
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
|
|
gnssServiceContext->api->close();
|
|
gnssServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
|
|
|
|
CHPP_LOGI("GNSS service closed");
|
|
|
|
struct ChppAppHeader *response =
|
|
chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
|
|
size_t responseLen = sizeof(*response);
|
|
|
|
if (response == NULL) {
|
|
CHPP_LOG_OOM();
|
|
error = CHPP_APP_ERROR_OOM;
|
|
} else {
|
|
chppSendTimestampedResponseOrFail(&gnssServiceContext->service,
|
|
&gnssServiceContext->close, response,
|
|
responseLen);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Notifies the service of an incoming reset.
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
*/
|
|
static void chppGnssServiceNotifyReset(void *serviceContext) {
|
|
struct ChppGnssServiceState *gnssServiceContext =
|
|
(struct ChppGnssServiceState *)serviceContext;
|
|
|
|
if (gnssServiceContext->service.openState != CHPP_OPEN_STATE_OPENED) {
|
|
CHPP_LOGW("GNSS service reset but wasn't open");
|
|
} else {
|
|
CHPP_LOGI("GNSS service reset. Closing");
|
|
gnssServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
|
|
gnssServiceContext->api->close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves a set of flags indicating the GNSS features supported by the
|
|
* current implementation.
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
* @param requestHeader App layer header of the request.
|
|
*
|
|
* @return Indicates the result of this function call.
|
|
*/
|
|
static enum ChppAppErrorCode chppGnssServiceGetCapabilities(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader) {
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
|
|
struct ChppGnssGetCapabilitiesResponse *response =
|
|
chppAllocServiceResponseFixed(requestHeader,
|
|
struct ChppGnssGetCapabilitiesResponse);
|
|
size_t responseLen = sizeof(*response);
|
|
|
|
if (response == NULL) {
|
|
CHPP_LOG_OOM();
|
|
error = CHPP_APP_ERROR_OOM;
|
|
} else {
|
|
response->params.capabilities = gnssServiceContext->api->getCapabilities();
|
|
|
|
CHPP_LOGD("chppGnssServiceGetCapabilities returning 0x%" PRIx32
|
|
", %" PRIuSIZE " bytes",
|
|
response->params.capabilities, responseLen);
|
|
chppSendTimestampedResponseOrFail(&gnssServiceContext->service,
|
|
&gnssServiceContext->getCapabilities,
|
|
response, responseLen);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Start/stop/modify the GNSS location session.
|
|
*
|
|
* This function returns an error code synchronously.
|
|
* A subsequent call to chppGnssServiceLocationStatusChangeCallback() will be
|
|
* used to communicate the result of this request (as a service response).
|
|
* A subsequent call to chppGnssServiceLocationEventCallback() will be used to
|
|
* communicate the location fixes (as service notifications).
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
* @param requestHeader App layer header of the request.
|
|
* @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 chppGnssServiceControlLocationSession(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
|
|
UNUSED_VAR(requestHeader);
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
|
|
if (len < sizeof(struct ChppGnssControlLocationSessionParameters)) {
|
|
error = CHPP_APP_ERROR_INVALID_ARG;
|
|
|
|
} else {
|
|
struct ChppGnssControlLocationSessionParameters *parameters =
|
|
(struct ChppGnssControlLocationSessionParameters *)buf;
|
|
|
|
if (!gnssServiceContext->api->controlLocationSession(
|
|
parameters->enable, parameters->minIntervalMs,
|
|
parameters->minTimeToNextFixMs)) {
|
|
error = CHPP_APP_ERROR_UNSPECIFIED;
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Start/stop/modify the raw GNSS measurement session.
|
|
*
|
|
* This function returns an error code synchronously.
|
|
* A subsequent call to chppGnssServiceMeasurementStatusChangeCallback() will be
|
|
* used to communicate the result of this request (as a service response).
|
|
* A subsequent call to chppGnssServiceMeasurementEventCallback() will be used
|
|
* to communicate the measurements (as service notifications).
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
* @param requestHeader App layer header of the request.
|
|
* @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 chppGnssServiceControlMeasurementSession(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
|
|
UNUSED_VAR(requestHeader);
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
|
|
if (len < sizeof(struct ChppGnssControlMeasurementSessionParameters)) {
|
|
error = CHPP_APP_ERROR_INVALID_ARG;
|
|
|
|
} else {
|
|
struct ChppGnssControlMeasurementSessionParameters *parameters =
|
|
(struct ChppGnssControlMeasurementSessionParameters *)buf;
|
|
|
|
if (!gnssServiceContext->api->controlMeasurementSession(
|
|
parameters->enable, parameters->minIntervalMs)) {
|
|
error = CHPP_APP_ERROR_UNSPECIFIED;
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Configures whether to opportunistically deliver any location fixes produced
|
|
* for other clients of the GNSS engine.
|
|
*
|
|
* This function returns an error code synchronously.
|
|
* A subsequent call to chppGnssServiceLocationEventCallback() will be used to
|
|
* communicate the location fixes (as service notifications).
|
|
*
|
|
* @param serviceContext Maintains status for each service instance.
|
|
* @param requestHeader App layer header of the request.
|
|
* @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 chppGnssServiceConfigurePassiveLocationListener(
|
|
struct ChppGnssServiceState *gnssServiceContext,
|
|
struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
|
|
UNUSED_VAR(requestHeader);
|
|
enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
|
|
|
|
if (len < sizeof(struct ChppGnssConfigurePassiveLocationListenerParameters)) {
|
|
error = CHPP_APP_ERROR_INVALID_ARG;
|
|
} else {
|
|
struct ChppGnssConfigurePassiveLocationListenerParameters *parameters =
|
|
(struct ChppGnssConfigurePassiveLocationListenerParameters *)buf;
|
|
|
|
if (!gnssServiceContext->api->configurePassiveLocationListener(
|
|
parameters->enable)) {
|
|
error = CHPP_APP_ERROR_UNSPECIFIED;
|
|
|
|
} else {
|
|
struct ChppAppHeader *response =
|
|
chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
|
|
size_t responseLen = sizeof(*response);
|
|
|
|
if (response == NULL) {
|
|
CHPP_LOG_OOM();
|
|
error = CHPP_APP_ERROR_OOM;
|
|
} else {
|
|
chppSendTimestampedResponseOrFail(
|
|
&gnssServiceContext->service,
|
|
&gnssServiceContext->configurePassiveLocationListener, response,
|
|
responseLen);
|
|
}
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* GNSS PAL callback to request that the core CHRE system re-send requests for
|
|
* any active sessions and its current passive location listener setting.
|
|
*/
|
|
static void chppGnssServiceRequestStateResyncCallback(void) {
|
|
struct ChppAppHeader *notification =
|
|
chppAllocServiceNotificationFixed(struct ChppAppHeader);
|
|
size_t notificationLen = sizeof(*notification);
|
|
|
|
if (notification == NULL) {
|
|
CHPP_LOG_OOM();
|
|
CHPP_ASSERT(false);
|
|
|
|
} else {
|
|
notification->handle = gGnssServiceContext.service.handle;
|
|
notification->command = CHPP_GNSS_REQUEST_STATE_RESYNC_NOTIFICATION;
|
|
|
|
chppEnqueueTxDatagramOrFail(
|
|
gGnssServiceContext.service.appContext->transportContext, notification,
|
|
notificationLen);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GNSS PAL callback to inform the CHRE of the result of changes to the location
|
|
* session status.
|
|
*/
|
|
static void chppGnssServiceLocationStatusChangeCallback(bool enabled,
|
|
uint8_t errorCode) {
|
|
// Recreate request header
|
|
struct ChppAppHeader requestHeader = {
|
|
.handle = gGnssServiceContext.service.handle,
|
|
.transaction = gGnssServiceContext.controlLocationSession.transaction,
|
|
.command = CHPP_GNSS_CONTROL_LOCATION_SESSION,
|
|
};
|
|
|
|
struct ChppGnssControlLocationSessionResponse *response =
|
|
chppAllocServiceResponseFixed(
|
|
&requestHeader, struct ChppGnssControlLocationSessionResponse);
|
|
size_t responseLen = sizeof(*response);
|
|
|
|
if (response == NULL) {
|
|
CHPP_LOG_OOM();
|
|
CHPP_ASSERT(false);
|
|
|
|
} else {
|
|
response->enabled = enabled;
|
|
response->errorCode = errorCode;
|
|
|
|
chppSendTimestampedResponseOrFail(
|
|
&gGnssServiceContext.service,
|
|
&gGnssServiceContext.controlLocationSession, response, responseLen);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GNSS PAL callback to pass GNSS location fixes to the core CHRE system.
|
|
*/
|
|
static void chppGnssServiceLocationEventCallback(
|
|
struct chreGnssLocationEvent *event) {
|
|
// Craft response per parser script
|
|
struct ChppGnssLocationEventWithHeader *notification = NULL;
|
|
size_t notificationLen = 0;
|
|
|
|
if (!chppGnssLocationEventFromChre(event, ¬ification, ¬ificationLen)) {
|
|
CHPP_LOGE("LocationEvent conversion failed (OOM?)");
|
|
|
|
notification = chppMalloc(sizeof(struct ChppAppHeader));
|
|
if (notification == NULL) {
|
|
CHPP_LOG_OOM();
|
|
} else {
|
|
notificationLen = sizeof(struct ChppAppHeader);
|
|
}
|
|
}
|
|
|
|
if (notification != NULL) {
|
|
notification->header.handle = gGnssServiceContext.service.handle;
|
|
notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
|
|
notification->header.transaction =
|
|
0; // Because we don't know this is in response to a Location Session
|
|
// or Passive Location Listener
|
|
notification->header.error =
|
|
(notificationLen > sizeof(struct ChppAppHeader))
|
|
? CHPP_APP_ERROR_NONE
|
|
: CHPP_APP_ERROR_CONVERSION_FAILED;
|
|
notification->header.command = CHPP_GNSS_LOCATION_RESULT_NOTIFICATION;
|
|
|
|
chppEnqueueTxDatagramOrFail(
|
|
gGnssServiceContext.service.appContext->transportContext, notification,
|
|
notificationLen);
|
|
}
|
|
|
|
gGnssServiceContext.api->releaseLocationEvent(event);
|
|
}
|
|
|
|
/**
|
|
* GNSS PAL callback to inform the CHRE of the result of changes to the raw GNSS
|
|
* measurement session status.
|
|
*/
|
|
static void chppGnssServiceMeasurementStatusChangeCallback(bool enabled,
|
|
uint8_t errorCode) {
|
|
// Recreate request header
|
|
struct ChppAppHeader requestHeader = {
|
|
.handle = gGnssServiceContext.service.handle,
|
|
.transaction = gGnssServiceContext.controlMeasurementSession.transaction,
|
|
.command = CHPP_GNSS_CONTROL_MEASUREMENT_SESSION,
|
|
};
|
|
|
|
struct ChppGnssControlMeasurementSessionResponse *response =
|
|
chppAllocServiceResponseFixed(
|
|
&requestHeader, struct ChppGnssControlMeasurementSessionResponse);
|
|
size_t responseLen = sizeof(*response);
|
|
|
|
if (response == NULL) {
|
|
CHPP_LOG_OOM();
|
|
CHPP_ASSERT(false);
|
|
|
|
} else {
|
|
response->enabled = enabled;
|
|
response->errorCode = errorCode;
|
|
|
|
chppSendTimestampedResponseOrFail(
|
|
&gGnssServiceContext.service,
|
|
&gGnssServiceContext.controlMeasurementSession, response, responseLen);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GNSS PAL callback to pass raw GNSS measurement data to the core CHRE system.
|
|
*/
|
|
static void chppGnssServiceMeasurementEventCallback(
|
|
struct chreGnssDataEvent *event) {
|
|
// Craft response per parser script
|
|
struct ChppGnssDataEventWithHeader *notification = NULL;
|
|
size_t notificationLen = 0;
|
|
|
|
if (!chppGnssDataEventFromChre(event, ¬ification, ¬ificationLen)) {
|
|
CHPP_LOGE("DataEvent conversion failed (OOM?) ID=%" PRIu8,
|
|
gGnssServiceContext.controlMeasurementSession.transaction);
|
|
|
|
notification = chppMalloc(sizeof(struct ChppAppHeader));
|
|
if (notification == NULL) {
|
|
CHPP_LOG_OOM();
|
|
} else {
|
|
notificationLen = sizeof(struct ChppAppHeader);
|
|
}
|
|
}
|
|
|
|
if (notification != NULL) {
|
|
notification->header.handle = gGnssServiceContext.service.handle;
|
|
notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
|
|
notification->header.transaction =
|
|
gGnssServiceContext.controlMeasurementSession.transaction;
|
|
notification->header.error =
|
|
(notificationLen > sizeof(struct ChppAppHeader))
|
|
? CHPP_APP_ERROR_NONE
|
|
: CHPP_APP_ERROR_CONVERSION_FAILED;
|
|
notification->header.command = CHPP_GNSS_MEASUREMENT_RESULT_NOTIFICATION;
|
|
|
|
chppEnqueueTxDatagramOrFail(
|
|
gGnssServiceContext.service.appContext->transportContext, notification,
|
|
notificationLen);
|
|
}
|
|
|
|
gGnssServiceContext.api->releaseMeasurementDataEvent(event);
|
|
}
|
|
|
|
/************************************************
|
|
* Public Functions
|
|
***********************************************/
|
|
|
|
void chppRegisterGnssService(struct ChppAppState *appContext) {
|
|
gGnssServiceContext.api = chrePalGnssGetApi(CHPP_PAL_GNSS_API_VERSION);
|
|
|
|
if (gGnssServiceContext.api == NULL) {
|
|
CHPP_LOGE(
|
|
"GNSS PAL API version not compatible with CHPP. Cannot register GNSS "
|
|
"service");
|
|
CHPP_DEBUG_ASSERT(false);
|
|
|
|
} else {
|
|
gGnssServiceContext.service.appContext = appContext;
|
|
gGnssServiceContext.service.handle = chppRegisterService(
|
|
appContext, (void *)&gGnssServiceContext, &kGnssServiceConfig);
|
|
CHPP_DEBUG_ASSERT(gGnssServiceContext.service.handle);
|
|
}
|
|
}
|
|
|
|
void chppDeregisterGnssService(struct ChppAppState *appContext) {
|
|
// TODO
|
|
|
|
UNUSED_VAR(appContext);
|
|
}
|