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 // Min length is the entire header
67 .minLength = sizeof(struct ChppAppHeader),
68 };
69
70 /**
71 * Structure to maintain state for the GNSS service and its Request/Response
72 * (RR) functionality.
73 */
74 struct ChppGnssServiceState {
75 struct ChppServiceState service; // GNSS service state
76 const struct chrePalGnssApi *api; // GNSS PAL API
77
78 // Based on chre/pal/gnss.h and chrePalGnssApi
79 struct ChppRequestResponseState open; // Service init state
80 struct ChppRequestResponseState close; // Service deinit state
81 struct ChppRequestResponseState getCapabilities; // Get Capabilities state
82 struct ChppRequestResponseState
83 controlLocationSession; // Control Location measurement state
84 struct ChppRequestResponseState
85 controlMeasurementSession; // Control Raw GNSS measurement state
86 struct ChppRequestResponseState
87 configurePassiveLocationListener; // Configure Passive location receiving
88 // state
89 };
90
91 // Note: The CHRE PAL API only allows for one definition - see comment in WWAN
92 // service for details.
93 // Note: There is no notion of a cookie in the CHRE GNSS API so we need to use
94 // the global service state (gGnssServiceContext) directly in all callbacks.
95 struct ChppGnssServiceState gGnssServiceContext;
96
97 /************************************************
98 * Prototypes
99 ***********************************************/
100
101 static enum ChppAppErrorCode chppGnssServiceOpen(
102 struct ChppGnssServiceState *gnssServiceContext,
103 struct ChppAppHeader *requestHeader);
104 static enum ChppAppErrorCode chppGnssServiceClose(
105 struct ChppGnssServiceState *gnssServiceContext,
106 struct ChppAppHeader *requestHeader);
107 static enum ChppAppErrorCode chppGnssServiceGetCapabilities(
108 struct ChppGnssServiceState *gnssServiceContext,
109 struct ChppAppHeader *requestHeader);
110 static enum ChppAppErrorCode chppGnssServiceControlLocationSession(
111 struct ChppGnssServiceState *gnssServiceContext,
112 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
113 static enum ChppAppErrorCode chppGnssServiceControlMeasurementSession(
114 struct ChppGnssServiceState *gnssServiceContext,
115 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
116 static enum ChppAppErrorCode chppGnssServiceConfigurePassiveLocationListener(
117 struct ChppGnssServiceState *gnssServiceContext,
118 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
119
120 static void chppGnssServiceRequestStateResyncCallback(void);
121 static void chppGnssServiceLocationStatusChangeCallback(bool enabled,
122 uint8_t errorCode);
123 static void chppGnssServiceLocationEventCallback(
124 struct chreGnssLocationEvent *event);
125 static void chppGnssServiceMeasurementStatusChangeCallback(bool enabled,
126 uint8_t errorCode);
127 static void chppGnssServiceMeasurementEventCallback(
128 struct chreGnssDataEvent *event);
129
130 /************************************************
131 * Private Functions
132 ***********************************************/
133
134 /**
135 * Dispatches a client request from the transport layer that is determined to be
136 * for the GNSS service. If the result of the dispatch is an error, this
137 * function responds to the client with the same error.
138 *
139 * This function is called from the app layer using its function pointer given
140 * during service registration.
141 *
142 * @param serviceContext Maintains status for each service instance.
143 * @param buf Input data. Cannot be null.
144 * @param len Length of input data in bytes.
145 *
146 * @return Indicates the result of this function call.
147 */
chppDispatchGnssRequest(void * serviceContext,uint8_t * buf,size_t len)148 static enum ChppAppErrorCode chppDispatchGnssRequest(void *serviceContext,
149 uint8_t *buf, size_t len) {
150 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
151 buf += sizeof(struct ChppAppHeader);
152 len -= sizeof(struct ChppAppHeader);
153
154 struct ChppGnssServiceState *gnssServiceContext =
155 (struct ChppGnssServiceState *)serviceContext;
156 struct ChppRequestResponseState *rRState = NULL;
157 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
158 bool dispatched = true;
159
160 switch (rxHeader->command) {
161 case CHPP_GNSS_OPEN: {
162 rRState = &gnssServiceContext->open;
163 chppServiceTimestampRequest(rRState, rxHeader);
164 error = chppGnssServiceOpen(gnssServiceContext, rxHeader);
165 break;
166 }
167
168 case CHPP_GNSS_CLOSE: {
169 rRState = &gnssServiceContext->close;
170 chppServiceTimestampRequest(rRState, rxHeader);
171 error = chppGnssServiceClose(gnssServiceContext, rxHeader);
172 break;
173 }
174
175 case CHPP_GNSS_GET_CAPABILITIES: {
176 rRState = &gnssServiceContext->getCapabilities;
177 chppServiceTimestampRequest(rRState, rxHeader);
178 error = chppGnssServiceGetCapabilities(gnssServiceContext, rxHeader);
179 break;
180 }
181
182 case CHPP_GNSS_CONTROL_LOCATION_SESSION: {
183 rRState = &gnssServiceContext->controlLocationSession;
184 chppServiceTimestampRequest(rRState, rxHeader);
185 error = chppGnssServiceControlLocationSession(gnssServiceContext,
186 rxHeader, buf, len);
187 break;
188 }
189
190 case CHPP_GNSS_CONTROL_MEASUREMENT_SESSION: {
191 rRState = &gnssServiceContext->controlMeasurementSession;
192 chppServiceTimestampRequest(rRState, rxHeader);
193 error = chppGnssServiceControlMeasurementSession(gnssServiceContext,
194 rxHeader, buf, len);
195 break;
196 }
197
198 case CHPP_GNSS_CONFIGURE_PASSIVE_LOCATION_LISTENER: {
199 rRState = &gnssServiceContext->configurePassiveLocationListener;
200 chppServiceTimestampRequest(rRState, rxHeader);
201 error = chppGnssServiceConfigurePassiveLocationListener(
202 gnssServiceContext, rxHeader, buf, len);
203 break;
204 }
205
206 default: {
207 dispatched = false;
208 error = CHPP_APP_ERROR_INVALID_COMMAND;
209 break;
210 }
211 }
212
213 if (dispatched == true && error != CHPP_APP_ERROR_NONE) {
214 // Request was dispatched but an error was returned. Close out
215 // chppServiceTimestampRequest()
216 chppServiceTimestampResponse(rRState);
217 }
218
219 return error;
220 }
221
222 /**
223 * Initializes the GNSS service upon an open request from the client and
224 * responds to the client with the result.
225 *
226 * @param serviceContext Maintains status for each service instance.
227 * @param requestHeader App layer header of the request.
228 *
229 * @return Indicates the result of this function call.
230 */
chppGnssServiceOpen(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader)231 static enum ChppAppErrorCode chppGnssServiceOpen(
232 struct ChppGnssServiceState *gnssServiceContext,
233 struct ChppAppHeader *requestHeader) {
234 static const struct chrePalGnssCallbacks palCallbacks = {
235 .requestStateResync = chppGnssServiceRequestStateResyncCallback,
236 .locationStatusChangeCallback =
237 chppGnssServiceLocationStatusChangeCallback,
238 .locationEventCallback = chppGnssServiceLocationEventCallback,
239 .measurementStatusChangeCallback =
240 chppGnssServiceMeasurementStatusChangeCallback,
241 .measurementEventCallback = chppGnssServiceMeasurementEventCallback,
242 };
243
244 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
245
246 if (gnssServiceContext->service.openState == CHPP_OPEN_STATE_OPENED) {
247 CHPP_LOGE("GNSS service already open");
248 CHPP_DEBUG_ASSERT(false);
249 error = CHPP_APP_ERROR_INVALID_COMMAND;
250
251 } else if (!gnssServiceContext->api->open(
252 gnssServiceContext->service.appContext->systemApi,
253 &palCallbacks)) {
254 CHPP_LOGE("GNSS PAL open failed");
255 CHPP_DEBUG_ASSERT(false);
256 error = CHPP_APP_ERROR_BEYOND_CHPP;
257
258 } else {
259 CHPP_LOGI("GNSS service opened");
260 gnssServiceContext->service.openState = CHPP_OPEN_STATE_OPENED;
261
262 struct ChppAppHeader *response =
263 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
264 size_t responseLen = sizeof(*response);
265
266 if (response == NULL) {
267 CHPP_LOG_OOM();
268 error = CHPP_APP_ERROR_OOM;
269 } else {
270 chppSendTimestampedResponseOrFail(&gnssServiceContext->service,
271 &gnssServiceContext->open, response,
272 responseLen);
273 }
274 }
275
276 return error;
277 }
278
279 /**
280 * Deinitializes the GNSS service.
281 *
282 * @param serviceContext Maintains status for each service instance.
283 * @param requestHeader App layer header of the request.
284 *
285 * @return Indicates the result of this function call.
286 */
chppGnssServiceClose(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader)287 static enum ChppAppErrorCode chppGnssServiceClose(
288 struct ChppGnssServiceState *gnssServiceContext,
289 struct ChppAppHeader *requestHeader) {
290 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
291
292 gnssServiceContext->api->close();
293 gnssServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
294
295 CHPP_LOGI("GNSS service closed");
296
297 struct ChppAppHeader *response =
298 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
299 size_t responseLen = sizeof(*response);
300
301 if (response == NULL) {
302 CHPP_LOG_OOM();
303 error = CHPP_APP_ERROR_OOM;
304 } else {
305 chppSendTimestampedResponseOrFail(&gnssServiceContext->service,
306 &gnssServiceContext->close, response,
307 responseLen);
308 }
309
310 return error;
311 }
312
313 /**
314 * Notifies the service of an incoming reset.
315 *
316 * @param serviceContext Maintains status for each service instance.
317 */
chppGnssServiceNotifyReset(void * serviceContext)318 static void chppGnssServiceNotifyReset(void *serviceContext) {
319 struct ChppGnssServiceState *gnssServiceContext =
320 (struct ChppGnssServiceState *)serviceContext;
321
322 if (gnssServiceContext->service.openState != CHPP_OPEN_STATE_OPENED) {
323 CHPP_LOGW("GNSS service reset but wasn't open");
324 } else {
325 CHPP_LOGI("GNSS service reset. Closing");
326 gnssServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
327 gnssServiceContext->api->close();
328 }
329 }
330
331 /**
332 * Retrieves a set of flags indicating the GNSS features supported by the
333 * current implementation.
334 *
335 * @param serviceContext Maintains status for each service instance.
336 * @param requestHeader App layer header of the request.
337 *
338 * @return Indicates the result of this function call.
339 */
chppGnssServiceGetCapabilities(struct ChppGnssServiceState * gnssServiceContext,struct ChppAppHeader * requestHeader)340 static enum ChppAppErrorCode chppGnssServiceGetCapabilities(
341 struct ChppGnssServiceState *gnssServiceContext,
342 struct ChppAppHeader *requestHeader) {
343 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
344
345 struct ChppGnssGetCapabilitiesResponse *response =
346 chppAllocServiceResponseFixed(requestHeader,
347 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,
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 chppAllocServiceResponseFixed(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,
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 chppAllocServiceResponseFixed(
533 &requestHeader, 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,
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 chppAllocServiceResponseFixed(
605 &requestHeader, 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,
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_LOGE(
671 "GNSS PAL API version not compatible with CHPP. Cannot register GNSS "
672 "service");
673 CHPP_DEBUG_ASSERT(false);
674
675 } else {
676 gGnssServiceContext.service.appContext = appContext;
677 gGnssServiceContext.service.handle = chppRegisterService(
678 appContext, (void *)&gGnssServiceContext, &kGnssServiceConfig);
679 CHPP_DEBUG_ASSERT(gGnssServiceContext.service.handle);
680 }
681 }
682
chppDeregisterGnssService(struct ChppAppState * appContext)683 void chppDeregisterGnssService(struct ChppAppState *appContext) {
684 // TODO
685
686 UNUSED_VAR(appContext);
687 }
688