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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 683 void chppDeregisterGnssService(struct ChppAppState *appContext) { 684 // TODO 685 686 UNUSED_VAR(appContext); 687 } 688