1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "chpp/services/gnss.h"
18
19 #include <inttypes.h>
20 #include <stddef.h>
21 #include <stdint.h>
22
23 #include "chpp/common/gnss.h"
24 #include "chpp/common/gnss_types.h"
25 #include "chpp/common/standard_uuids.h"
26 #include "chpp/log.h"
27 #include "chpp/macros.h"
28 #include "chpp/services.h"
29 #include "chre/pal/gnss.h"
30
31 /************************************************
32 * Prototypes
33 ***********************************************/
34
35 static enum ChppAppErrorCode chppDispatchGnssRequest(void *serviceContext,
36 uint8_t *buf, size_t len);
37 static void chppGnssServiceNotifyReset(void *serviceContext);
38
39 /************************************************
40 * Private Definitions
41 ***********************************************/
42
43 /**
44 * Configuration parameters for this service
45 */
46 static const struct ChppService kGnssServiceConfig = {
47 .descriptor.uuid = CHPP_UUID_GNSS_STANDARD,
48
49 // Human-readable name
50 .descriptor.name = "GNSS",
51
52 // Version
53 .descriptor.version.major = 1,
54 .descriptor.version.minor = 0,
55 .descriptor.version.patch = 0,
56
57 // Notifies service if CHPP is reset
58 .resetNotifierFunctionPtr = &chppGnssServiceNotifyReset,
59
60 // Client request dispatch function pointer
61 .requestDispatchFunctionPtr = &chppDispatchGnssRequest,
62
63 // Client notification dispatch function pointer
64 .notificationDispatchFunctionPtr = NULL, // Not supported
65
66 // Client timeout function pointer
67 .timeoutFunctionPtr = NULL, // Not used
68
69 // Min length is the entire header
70 .minLength = sizeof(struct ChppAppHeader),
71 };
72
73 /**
74 * Structure to maintain state for the GNSS service and its Request/Response
75 * (RR) functionality.
76 */
77 struct ChppGnssServiceState {
78 struct ChppEndpointState service; // CHPP service state
79 const struct chrePalGnssApi *api; // GNSS PAL API
80
81 // Based on chre/pal/gnss.h and chrePalGnssApi
82 struct ChppIncomingRequestState open; // Service init state
83 struct ChppIncomingRequestState close; // Service deinit state
84 struct ChppIncomingRequestState getCapabilities; // Get Capabilities state
85 struct ChppIncomingRequestState
86 controlLocationSession; // Control Location measurement state
87 struct ChppIncomingRequestState
88 controlMeasurementSession; // Control Raw GNSS measurement state
89 struct ChppIncomingRequestState
90 configurePassiveLocationListener; // Configure Passive location receiving
91 // state
92 };
93
94 // Note: The CHRE PAL API only allows for one definition - see comment in WWAN
95 // service for details.
96 // Note: There is no notion of a cookie in the CHRE GNSS API so we need to use
97 // the global service state (gGnssServiceContext) directly in all callbacks.
98 struct ChppGnssServiceState gGnssServiceContext;
99
100 /************************************************
101 * Prototypes
102 ***********************************************/
103
104 static enum ChppAppErrorCode chppGnssServiceOpen(
105 struct ChppGnssServiceState *gnssServiceContext,
106 struct ChppAppHeader *requestHeader);
107 static enum ChppAppErrorCode chppGnssServiceClose(
108 struct ChppGnssServiceState *gnssServiceContext,
109 struct ChppAppHeader *requestHeader);
110 static enum ChppAppErrorCode chppGnssServiceGetCapabilities(
111 struct ChppGnssServiceState *gnssServiceContext,
112 struct ChppAppHeader *requestHeader);
113 static enum ChppAppErrorCode chppGnssServiceControlLocationSession(
114 struct ChppGnssServiceState *gnssServiceContext,
115 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
116 static enum ChppAppErrorCode chppGnssServiceControlMeasurementSession(
117 struct ChppGnssServiceState *gnssServiceContext,
118 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
119 static enum ChppAppErrorCode chppGnssServiceConfigurePassiveLocationListener(
120 struct ChppGnssServiceState *gnssServiceContext,
121 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
122
123 static void chppGnssServiceRequestStateResyncCallback(void);
124 static void chppGnssServiceLocationStatusChangeCallback(bool enabled,
125 uint8_t errorCode);
126 static void chppGnssServiceLocationEventCallback(
127 struct chreGnssLocationEvent *event);
128 static void chppGnssServiceMeasurementStatusChangeCallback(bool enabled,
129 uint8_t errorCode);
130 static void chppGnssServiceMeasurementEventCallback(
131 struct chreGnssDataEvent *event);
132
133 /************************************************
134 * Private Functions
135 ***********************************************/
136
137 /**
138 * Dispatches a client request from the transport layer that is determined to be
139 * for the GNSS service. If the result of the dispatch is an error, this
140 * function responds to the client with the same error.
141 *
142 * This function is called from the app layer using its function pointer given
143 * during service registration.
144 *
145 * @param serviceContext Maintains status for each service instance.
146 * @param buf Input data. Cannot be null.
147 * @param len Length of input data in bytes.
148 *
149 * @return Indicates the result of this function call.
150 */
chppDispatchGnssRequest(void * serviceContext,uint8_t * buf,size_t len)151 static enum ChppAppErrorCode chppDispatchGnssRequest(void *serviceContext,
152 uint8_t *buf, size_t len) {
153 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
154 buf += sizeof(struct ChppAppHeader);
155 len -= sizeof(struct ChppAppHeader);
156
157 struct ChppGnssServiceState *gnssServiceContext =
158 (struct ChppGnssServiceState *)serviceContext;
159 struct ChppIncomingRequestState *inReqState = NULL;
160 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
161 bool dispatched = true;
162
163 switch (rxHeader->command) {
164 case CHPP_GNSS_OPEN: {
165 inReqState = &gnssServiceContext->open;
166 chppTimestampIncomingRequest(inReqState, rxHeader);
167 error = chppGnssServiceOpen(gnssServiceContext, rxHeader);
168 break;
169 }
170
171 case CHPP_GNSS_CLOSE: {
172 inReqState = &gnssServiceContext->close;
173 chppTimestampIncomingRequest(inReqState, rxHeader);
174 error = chppGnssServiceClose(gnssServiceContext, rxHeader);
175 break;
176 }
177
178 case CHPP_GNSS_GET_CAPABILITIES: {
179 inReqState = &gnssServiceContext->getCapabilities;
180 chppTimestampIncomingRequest(inReqState, rxHeader);
181 error = chppGnssServiceGetCapabilities(gnssServiceContext, rxHeader);
182 break;
183 }
184
185 case CHPP_GNSS_CONTROL_LOCATION_SESSION: {
186 inReqState = &gnssServiceContext->controlLocationSession;
187 chppTimestampIncomingRequest(inReqState, rxHeader);
188 error = chppGnssServiceControlLocationSession(gnssServiceContext,
189 rxHeader, buf, len);
190 break;
191 }
192
193 case CHPP_GNSS_CONTROL_MEASUREMENT_SESSION: {
194 inReqState = &gnssServiceContext->controlMeasurementSession;
195 chppTimestampIncomingRequest(inReqState, rxHeader);
196 error = chppGnssServiceControlMeasurementSession(gnssServiceContext,
197 rxHeader, buf, len);
198 break;
199 }
200
201 case CHPP_GNSS_CONFIGURE_PASSIVE_LOCATION_LISTENER: {
202 inReqState = &gnssServiceContext->configurePassiveLocationListener;
203 chppTimestampIncomingRequest(inReqState, rxHeader);
204 error = chppGnssServiceConfigurePassiveLocationListener(
205 gnssServiceContext, rxHeader, buf, len);
206 break;
207 }
208
209 default: {
210 dispatched = false;
211 error = CHPP_APP_ERROR_INVALID_COMMAND;
212 break;
213 }
214 }
215
216 if (dispatched == true && error != CHPP_APP_ERROR_NONE) {
217 // Request was dispatched but an error was returned. Close out
218 // chppTimestampIncomingRequest()
219 chppTimestampOutgoingResponse(inReqState);
220 }
221
222 return error;
223 }
224
225 /**
226 * Initializes the GNSS service upon an open request from the client and
227 * responds to the client with the result.
228 *
229 * @param serviceContext Maintains status for each service instance.
230 * @param requestHeader App layer header of the request.
231 *
232 * @return Indicates the result of this function call.
233 */
chppGnssServiceOpen(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader)234 static enum ChppAppErrorCode chppGnssServiceOpen(
235 struct ChppGnssServiceState *gnssServiceContext,
236 struct ChppAppHeader *requestHeader) {
237 static const struct chrePalGnssCallbacks palCallbacks = {
238 .requestStateResync = chppGnssServiceRequestStateResyncCallback,
239 .locationStatusChangeCallback =
240 chppGnssServiceLocationStatusChangeCallback,
241 .locationEventCallback = chppGnssServiceLocationEventCallback,
242 .measurementStatusChangeCallback =
243 chppGnssServiceMeasurementStatusChangeCallback,
244 .measurementEventCallback = chppGnssServiceMeasurementEventCallback,
245 };
246
247 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
248
249 if (gnssServiceContext->service.openState == CHPP_OPEN_STATE_OPENED) {
250 CHPP_DEBUG_ASSERT_LOG(false, "GNSS service already open");
251 error = CHPP_APP_ERROR_INVALID_COMMAND;
252
253 } else if (!gnssServiceContext->api->open(
254 gnssServiceContext->service.appContext->systemApi,
255 &palCallbacks)) {
256 CHPP_DEBUG_ASSERT_LOG(false, "GNSS PAL open failed");
257 error = CHPP_APP_ERROR_BEYOND_CHPP;
258
259 } else {
260 CHPP_LOGD("GNSS service opened");
261 gnssServiceContext->service.openState = CHPP_OPEN_STATE_OPENED;
262
263 struct ChppAppHeader *response =
264 chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
265 size_t responseLen = sizeof(*response);
266
267 if (response == NULL) {
268 CHPP_LOG_OOM();
269 error = CHPP_APP_ERROR_OOM;
270 } else {
271 chppSendTimestampedResponseOrFail(gnssServiceContext->service.appContext,
272 &gnssServiceContext->open, response,
273 responseLen);
274 }
275 }
276
277 return error;
278 }
279
280 /**
281 * Deinitializes the GNSS service.
282 *
283 * @param serviceContext Maintains status for each service instance.
284 * @param requestHeader App layer header of the request.
285 *
286 * @return Indicates the result of this function call.
287 */
chppGnssServiceClose(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader)288 static enum ChppAppErrorCode chppGnssServiceClose(
289 struct ChppGnssServiceState *gnssServiceContext,
290 struct ChppAppHeader *requestHeader) {
291 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
292
293 gnssServiceContext->api->close();
294 gnssServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
295
296 CHPP_LOGD("GNSS service closed");
297
298 struct ChppAppHeader *response =
299 chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
300 size_t responseLen = sizeof(*response);
301
302 if (response == NULL) {
303 CHPP_LOG_OOM();
304 error = CHPP_APP_ERROR_OOM;
305 } else {
306 chppSendTimestampedResponseOrFail(gnssServiceContext->service.appContext,
307 &gnssServiceContext->close, response,
308 responseLen);
309 }
310
311 return error;
312 }
313
314 /**
315 * Notifies the service of an incoming reset.
316 *
317 * @param serviceContext Maintains status for each service instance.
318 */
chppGnssServiceNotifyReset(void * serviceContext)319 static void chppGnssServiceNotifyReset(void *serviceContext) {
320 struct ChppGnssServiceState *gnssServiceContext =
321 (struct ChppGnssServiceState *)serviceContext;
322
323 if (gnssServiceContext->service.openState != CHPP_OPEN_STATE_OPENED) {
324 CHPP_LOGW("GNSS service reset but wasn't open");
325 } else {
326 CHPP_LOGD("GNSS service reset. Closing");
327 gnssServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
328 gnssServiceContext->api->close();
329 }
330 }
331
332 /**
333 * Retrieves a set of flags indicating the GNSS features supported by the
334 * current implementation.
335 *
336 * @param serviceContext Maintains status for each service instance.
337 * @param requestHeader App layer header of the request.
338 *
339 * @return Indicates the result of this function call.
340 */
chppGnssServiceGetCapabilities(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader)341 static enum ChppAppErrorCode chppGnssServiceGetCapabilities(
342 struct ChppGnssServiceState *gnssServiceContext,
343 struct ChppAppHeader *requestHeader) {
344 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
345
346 struct ChppGnssGetCapabilitiesResponse *response = chppAllocResponseFixed(
347 requestHeader, struct ChppGnssGetCapabilitiesResponse);
348 size_t responseLen = sizeof(*response);
349
350 if (response == NULL) {
351 CHPP_LOG_OOM();
352 error = CHPP_APP_ERROR_OOM;
353 } else {
354 response->params.capabilities = gnssServiceContext->api->getCapabilities();
355
356 CHPP_LOGD("chppGnssServiceGetCapabilities returning 0x%" PRIx32
357 ", %" PRIuSIZE " bytes",
358 response->params.capabilities, responseLen);
359 chppSendTimestampedResponseOrFail(gnssServiceContext->service.appContext,
360 &gnssServiceContext->getCapabilities,
361 response, responseLen);
362 }
363
364 return error;
365 }
366
367 /**
368 * Start/stop/modify the GNSS location session.
369 *
370 * This function returns an error code synchronously.
371 * A subsequent call to chppGnssServiceLocationStatusChangeCallback() will be
372 * used to communicate the result of this request (as a service response).
373 * A subsequent call to chppGnssServiceLocationEventCallback() will be used to
374 * communicate the location fixes (as service notifications).
375 *
376 * @param serviceContext Maintains status for each service instance.
377 * @param requestHeader App layer header of the request.
378 * @param buf Input data. Cannot be null.
379 * @param len Length of input data in bytes.
380 *
381 * @return Indicates the result of this function call.
382 */
chppGnssServiceControlLocationSession(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)383 static enum ChppAppErrorCode chppGnssServiceControlLocationSession(
384 struct ChppGnssServiceState *gnssServiceContext,
385 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
386 UNUSED_VAR(requestHeader);
387 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
388
389 if (len < sizeof(struct ChppGnssControlLocationSessionParameters)) {
390 error = CHPP_APP_ERROR_INVALID_ARG;
391
392 } else {
393 struct ChppGnssControlLocationSessionParameters *parameters =
394 (struct ChppGnssControlLocationSessionParameters *)buf;
395
396 if (!gnssServiceContext->api->controlLocationSession(
397 parameters->enable, parameters->minIntervalMs,
398 parameters->minTimeToNextFixMs)) {
399 error = CHPP_APP_ERROR_UNSPECIFIED;
400 }
401 }
402
403 return error;
404 }
405
406 /**
407 * Start/stop/modify the raw GNSS measurement session.
408 *
409 * This function returns an error code synchronously.
410 * A subsequent call to chppGnssServiceMeasurementStatusChangeCallback() will be
411 * used to communicate the result of this request (as a service response).
412 * A subsequent call to chppGnssServiceMeasurementEventCallback() will be used
413 * to communicate the measurements (as service notifications).
414 *
415 * @param serviceContext Maintains status for each service instance.
416 * @param requestHeader App layer header of the request.
417 * @param buf Input data. Cannot be null.
418 * @param len Length of input data in bytes.
419 *
420 * @return Indicates the result of this function call.
421 */
chppGnssServiceControlMeasurementSession(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)422 static enum ChppAppErrorCode chppGnssServiceControlMeasurementSession(
423 struct ChppGnssServiceState *gnssServiceContext,
424 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
425 UNUSED_VAR(requestHeader);
426 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
427
428 if (len < sizeof(struct ChppGnssControlMeasurementSessionParameters)) {
429 error = CHPP_APP_ERROR_INVALID_ARG;
430
431 } else {
432 struct ChppGnssControlMeasurementSessionParameters *parameters =
433 (struct ChppGnssControlMeasurementSessionParameters *)buf;
434
435 if (!gnssServiceContext->api->controlMeasurementSession(
436 parameters->enable, parameters->minIntervalMs)) {
437 error = CHPP_APP_ERROR_UNSPECIFIED;
438 }
439 }
440
441 return error;
442 }
443
444 /**
445 * Configures whether to opportunistically deliver any location fixes produced
446 * for other clients of the GNSS engine.
447 *
448 * This function returns an error code synchronously.
449 * A subsequent call to chppGnssServiceLocationEventCallback() will be used to
450 * communicate the location fixes (as service notifications).
451 *
452 * @param serviceContext Maintains status for each service instance.
453 * @param requestHeader App layer header of the request.
454 * @param buf Input data. Cannot be null.
455 * @param len Length of input data in bytes.
456 *
457 * @return Indicates the result of this function call.
458 */
chppGnssServiceConfigurePassiveLocationListener(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)459 static enum ChppAppErrorCode chppGnssServiceConfigurePassiveLocationListener(
460 struct ChppGnssServiceState *gnssServiceContext,
461 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
462 UNUSED_VAR(requestHeader);
463 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
464
465 if (len < sizeof(struct ChppGnssConfigurePassiveLocationListenerParameters)) {
466 error = CHPP_APP_ERROR_INVALID_ARG;
467 } else {
468 struct ChppGnssConfigurePassiveLocationListenerParameters *parameters =
469 (struct ChppGnssConfigurePassiveLocationListenerParameters *)buf;
470
471 if (!gnssServiceContext->api->configurePassiveLocationListener(
472 parameters->enable)) {
473 error = CHPP_APP_ERROR_UNSPECIFIED;
474
475 } else {
476 struct ChppAppHeader *response =
477 chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
478 size_t responseLen = sizeof(*response);
479
480 if (response == NULL) {
481 CHPP_LOG_OOM();
482 error = CHPP_APP_ERROR_OOM;
483 } else {
484 chppSendTimestampedResponseOrFail(
485 gnssServiceContext->service.appContext,
486 &gnssServiceContext->configurePassiveLocationListener, response,
487 responseLen);
488 }
489 }
490 }
491
492 return error;
493 }
494
495 /**
496 * GNSS PAL callback to request that the core CHRE system re-send requests for
497 * any active sessions and its current passive location listener setting.
498 */
chppGnssServiceRequestStateResyncCallback(void)499 static void chppGnssServiceRequestStateResyncCallback(void) {
500 struct ChppAppHeader *notification =
501 chppAllocServiceNotificationFixed(struct ChppAppHeader);
502 size_t notificationLen = sizeof(*notification);
503
504 if (notification == NULL) {
505 CHPP_LOG_OOM();
506 CHPP_ASSERT(false);
507
508 } else {
509 notification->handle = gGnssServiceContext.service.handle;
510 notification->command = CHPP_GNSS_REQUEST_STATE_RESYNC_NOTIFICATION;
511
512 chppEnqueueTxDatagramOrFail(
513 gGnssServiceContext.service.appContext->transportContext, notification,
514 notificationLen);
515 }
516 }
517
518 /**
519 * GNSS PAL callback to inform the CHRE of the result of changes to the location
520 * session status.
521 */
chppGnssServiceLocationStatusChangeCallback(bool enabled,uint8_t errorCode)522 static void chppGnssServiceLocationStatusChangeCallback(bool enabled,
523 uint8_t errorCode) {
524 // Recreate request header
525 struct ChppAppHeader requestHeader = {
526 .handle = gGnssServiceContext.service.handle,
527 .transaction = gGnssServiceContext.controlLocationSession.transaction,
528 .command = CHPP_GNSS_CONTROL_LOCATION_SESSION,
529 };
530
531 struct ChppGnssControlLocationSessionResponse *response =
532 chppAllocResponseFixed(&requestHeader,
533 struct ChppGnssControlLocationSessionResponse);
534 size_t responseLen = sizeof(*response);
535
536 if (response == NULL) {
537 CHPP_LOG_OOM();
538 CHPP_ASSERT(false);
539
540 } else {
541 response->enabled = enabled;
542 response->errorCode = errorCode;
543
544 chppSendTimestampedResponseOrFail(
545 gGnssServiceContext.service.appContext,
546 &gGnssServiceContext.controlLocationSession, response, responseLen);
547 }
548 }
549
550 /**
551 * GNSS PAL callback to pass GNSS location fixes to the core CHRE system.
552 */
chppGnssServiceLocationEventCallback(struct chreGnssLocationEvent * event)553 static void chppGnssServiceLocationEventCallback(
554 struct chreGnssLocationEvent *event) {
555 // Craft response per parser script
556 struct ChppGnssLocationEventWithHeader *notification = NULL;
557 size_t notificationLen = 0;
558
559 if (!chppGnssLocationEventFromChre(event, ¬ification, ¬ificationLen)) {
560 CHPP_LOGE("LocationEvent conversion failed (OOM?)");
561
562 notification = chppMalloc(sizeof(struct ChppAppHeader));
563 if (notification == NULL) {
564 CHPP_LOG_OOM();
565 } else {
566 notificationLen = sizeof(struct ChppAppHeader);
567 }
568 }
569
570 if (notification != NULL) {
571 notification->header.handle = gGnssServiceContext.service.handle;
572 notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
573 notification->header.transaction =
574 0; // Because we don't know this is in response to a Location Session
575 // or Passive Location Listener
576 notification->header.error =
577 (notificationLen > sizeof(struct ChppAppHeader))
578 ? CHPP_APP_ERROR_NONE
579 : CHPP_APP_ERROR_CONVERSION_FAILED;
580 notification->header.command = CHPP_GNSS_LOCATION_RESULT_NOTIFICATION;
581
582 chppEnqueueTxDatagramOrFail(
583 gGnssServiceContext.service.appContext->transportContext, notification,
584 notificationLen);
585 }
586
587 gGnssServiceContext.api->releaseLocationEvent(event);
588 }
589
590 /**
591 * GNSS PAL callback to inform the CHRE of the result of changes to the raw GNSS
592 * measurement session status.
593 */
chppGnssServiceMeasurementStatusChangeCallback(bool enabled,uint8_t errorCode)594 static void chppGnssServiceMeasurementStatusChangeCallback(bool enabled,
595 uint8_t errorCode) {
596 // Recreate request header
597 struct ChppAppHeader requestHeader = {
598 .handle = gGnssServiceContext.service.handle,
599 .transaction = gGnssServiceContext.controlMeasurementSession.transaction,
600 .command = CHPP_GNSS_CONTROL_MEASUREMENT_SESSION,
601 };
602
603 struct ChppGnssControlMeasurementSessionResponse *response =
604 chppAllocResponseFixed(&requestHeader,
605 struct ChppGnssControlMeasurementSessionResponse);
606 size_t responseLen = sizeof(*response);
607
608 if (response == NULL) {
609 CHPP_LOG_OOM();
610 CHPP_ASSERT(false);
611
612 } else {
613 response->enabled = enabled;
614 response->errorCode = errorCode;
615
616 chppSendTimestampedResponseOrFail(
617 gGnssServiceContext.service.appContext,
618 &gGnssServiceContext.controlMeasurementSession, response, responseLen);
619 }
620 }
621
622 /**
623 * GNSS PAL callback to pass raw GNSS measurement data to the core CHRE system.
624 */
chppGnssServiceMeasurementEventCallback(struct chreGnssDataEvent * event)625 static void chppGnssServiceMeasurementEventCallback(
626 struct chreGnssDataEvent *event) {
627 // Craft response per parser script
628 struct ChppGnssDataEventWithHeader *notification = NULL;
629 size_t notificationLen = 0;
630
631 if (!chppGnssDataEventFromChre(event, ¬ification, ¬ificationLen)) {
632 CHPP_LOGE("DataEvent conversion failed (OOM?) ID=%" PRIu8,
633 gGnssServiceContext.controlMeasurementSession.transaction);
634
635 notification = chppMalloc(sizeof(struct ChppAppHeader));
636 if (notification == NULL) {
637 CHPP_LOG_OOM();
638 } else {
639 notificationLen = sizeof(struct ChppAppHeader);
640 }
641 }
642
643 if (notification != NULL) {
644 notification->header.handle = gGnssServiceContext.service.handle;
645 notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
646 notification->header.transaction =
647 gGnssServiceContext.controlMeasurementSession.transaction;
648 notification->header.error =
649 (notificationLen > sizeof(struct ChppAppHeader))
650 ? CHPP_APP_ERROR_NONE
651 : CHPP_APP_ERROR_CONVERSION_FAILED;
652 notification->header.command = CHPP_GNSS_MEASUREMENT_RESULT_NOTIFICATION;
653
654 chppEnqueueTxDatagramOrFail(
655 gGnssServiceContext.service.appContext->transportContext, notification,
656 notificationLen);
657 }
658
659 gGnssServiceContext.api->releaseMeasurementDataEvent(event);
660 }
661
662 /************************************************
663 * Public Functions
664 ***********************************************/
665
chppRegisterGnssService(struct ChppAppState * appContext)666 void chppRegisterGnssService(struct ChppAppState *appContext) {
667 gGnssServiceContext.api = chrePalGnssGetApi(CHPP_PAL_GNSS_API_VERSION);
668
669 if (gGnssServiceContext.api == NULL) {
670 CHPP_DEBUG_ASSERT_LOG(false,
671 "GNSS PAL API incompatible. Cannot register service");
672
673 } else {
674 chppRegisterService(appContext, (void *)&gGnssServiceContext,
675 &gGnssServiceContext.service, NULL /*outReqState*/,
676 &kGnssServiceConfig);
677 CHPP_DEBUG_ASSERT(gGnssServiceContext.service.handle);
678 }
679 }
680
chppDeregisterGnssService(struct ChppAppState * appContext)681 void chppDeregisterGnssService(struct ChppAppState *appContext) {
682 // TODO
683
684 UNUSED_VAR(appContext);
685 }
686