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/wifi.h" 18 19 #include <inttypes.h> 20 #include <stddef.h> 21 #include <stdint.h> 22 23 #include "chpp/common/standard_uuids.h" 24 #include "chpp/common/wifi.h" 25 #include "chpp/common/wifi_types.h" 26 #include "chpp/common/wifi_utils.h" 27 #include "chpp/log.h" 28 #include "chpp/macros.h" 29 #include "chpp/services.h" 30 #include "chre/pal/wifi.h" 31 32 /************************************************ 33 * Prototypes 34 ***********************************************/ 35 36 static enum ChppAppErrorCode chppDispatchWifiRequest(void *serviceContext, 37 uint8_t *buf, size_t len); 38 static void chppWifiServiceNotifyReset(void *serviceContext); 39 40 /************************************************ 41 * Private Definitions 42 ***********************************************/ 43 44 /** 45 * Configuration parameters for this service 46 */ 47 static const struct ChppService kWifiServiceConfig = { 48 .descriptor.uuid = CHPP_UUID_WIFI_STANDARD, 49 50 // Human-readable name 51 .descriptor.name = "WiFi", 52 53 // Version 54 .descriptor.version.major = 1, 55 .descriptor.version.minor = 0, 56 .descriptor.version.patch = 0, 57 58 // Notifies service if CHPP is reset 59 .resetNotifierFunctionPtr = &chppWifiServiceNotifyReset, 60 61 // Client request dispatch function pointer 62 .requestDispatchFunctionPtr = &chppDispatchWifiRequest, 63 64 // Client notification dispatch function pointer 65 .notificationDispatchFunctionPtr = NULL, // Not supported 66 67 // Min length is the entire header 68 .minLength = sizeof(struct ChppAppHeader), 69 }; 70 71 /** 72 * Structure to maintain state for the WiFi service and its Request/Response 73 * (RR) functionality. 74 */ 75 struct ChppWifiServiceState { 76 struct ChppServiceState service; // WiFi service state 77 const struct chrePalWifiApi *api; // WiFi PAL API 78 79 // Based on chre/pal/wifi.h and chrePalWifiApi 80 struct ChppRequestResponseState open; // Service init state 81 struct ChppRequestResponseState close; // Service deinit state 82 struct ChppRequestResponseState getCapabilities; // Get Capabilities state 83 struct ChppRequestResponseState 84 configureScanMonitorAsync; // Configure scan monitor state 85 struct ChppRequestResponseState requestScanAsync; // Request scan state 86 struct ChppRequestResponseState requestRangingAsync; // Request ranging state 87 }; 88 89 // Note: The CHRE PAL API only allows for one definition - see comment in WWAN 90 // service for details. 91 // Note: There is no notion of a cookie in the CHRE WiFi API so we need to use 92 // the global service state (gWifiServiceContext) directly in all callbacks. 93 struct ChppWifiServiceState gWifiServiceContext; 94 95 /************************************************ 96 * Prototypes 97 ***********************************************/ 98 99 static enum ChppAppErrorCode chppWifiServiceOpen( 100 struct ChppWifiServiceState *wifiServiceContext, 101 struct ChppAppHeader *requestHeader); 102 static enum ChppAppErrorCode chppWifiServiceClose( 103 struct ChppWifiServiceState *wifiServiceContext, 104 struct ChppAppHeader *requestHeader); 105 static enum ChppAppErrorCode chppWifiServiceGetCapabilities( 106 struct ChppWifiServiceState *wifiServiceContext, 107 struct ChppAppHeader *requestHeader); 108 static enum ChppAppErrorCode chppWifiServiceConfigureScanMonitorAsync( 109 struct ChppWifiServiceState *wifiServiceContext, 110 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len); 111 static enum ChppAppErrorCode chppWifiServiceRequestScanAsync( 112 struct ChppWifiServiceState *wifiServiceContext, 113 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len); 114 static enum ChppAppErrorCode chppWifiServiceRequestRangingAsync( 115 struct ChppWifiServiceState *wifiServiceContext, 116 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len); 117 118 static void chppWifiServiceScanMonitorStatusChangeCallback(bool enabled, 119 uint8_t errorCode); 120 static void chppWifiServiceScanResponseCallback(bool pending, 121 uint8_t errorCode); 122 static void chppWifiServiceScanEventCallback(struct chreWifiScanEvent *event); 123 static void chppWifiServiceRangingEventCallback( 124 uint8_t errorCode, struct chreWifiRangingEvent *event); 125 126 /************************************************ 127 * Private Functions 128 ***********************************************/ 129 130 /** 131 * Dispatches a client request from the transport layer that is determined to be 132 * for the WiFi service. If the result of the dispatch is an error, this 133 * function responds to the client with the same error. 134 * 135 * This function is called from the app layer using its function pointer given 136 * during service registration. 137 * 138 * @param serviceContext Maintains status for each service instance. 139 * @param buf Input data. Cannot be null. 140 * @param len Length of input data in bytes. 141 * 142 * @return Indicates the result of this function call. 143 */ 144 static enum ChppAppErrorCode chppDispatchWifiRequest(void *serviceContext, 145 uint8_t *buf, size_t len) { 146 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf; 147 buf += sizeof(struct ChppAppHeader); 148 len -= sizeof(struct ChppAppHeader); 149 150 struct ChppWifiServiceState *wifiServiceContext = 151 (struct ChppWifiServiceState *)serviceContext; 152 struct ChppRequestResponseState *rRState = NULL; 153 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 154 bool dispatched = true; 155 156 switch (rxHeader->command) { 157 case CHPP_WIFI_OPEN: { 158 rRState = &wifiServiceContext->open; 159 chppServiceTimestampRequest(rRState, rxHeader); 160 error = chppWifiServiceOpen(wifiServiceContext, rxHeader); 161 break; 162 } 163 164 case CHPP_WIFI_CLOSE: { 165 rRState = &wifiServiceContext->close; 166 chppServiceTimestampRequest(rRState, rxHeader); 167 error = chppWifiServiceClose(wifiServiceContext, rxHeader); 168 break; 169 } 170 171 case CHPP_WIFI_GET_CAPABILITIES: { 172 rRState = &wifiServiceContext->getCapabilities; 173 chppServiceTimestampRequest(rRState, rxHeader); 174 error = chppWifiServiceGetCapabilities(wifiServiceContext, rxHeader); 175 break; 176 } 177 178 case CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC: { 179 rRState = &wifiServiceContext->configureScanMonitorAsync; 180 chppServiceTimestampRequest(rRState, rxHeader); 181 error = chppWifiServiceConfigureScanMonitorAsync(wifiServiceContext, 182 rxHeader, buf, len); 183 break; 184 } 185 186 case CHPP_WIFI_REQUEST_SCAN_ASYNC: { 187 rRState = &wifiServiceContext->requestScanAsync; 188 chppServiceTimestampRequest(rRState, rxHeader); 189 error = chppWifiServiceRequestScanAsync(wifiServiceContext, rxHeader, buf, 190 len); 191 break; 192 } 193 194 case CHPP_WIFI_REQUEST_RANGING_ASYNC: { 195 rRState = &wifiServiceContext->requestRangingAsync; 196 chppServiceTimestampRequest(rRState, rxHeader); 197 error = chppWifiServiceRequestRangingAsync(wifiServiceContext, rxHeader, 198 buf, len); 199 break; 200 } 201 202 default: { 203 dispatched = false; 204 error = CHPP_APP_ERROR_INVALID_COMMAND; 205 break; 206 } 207 } 208 209 if (dispatched == true && error != CHPP_APP_ERROR_NONE) { 210 // Request was dispatched but an error was returned. Close out 211 // chppServiceTimestampRequest() 212 chppServiceTimestampResponse(rRState); 213 } 214 215 return error; 216 } 217 218 /** 219 * Initializes the WiFi service upon an open request from the client and 220 * responds to the client with the result. 221 * 222 * @param serviceContext Maintains status for each service instance. 223 * @param requestHeader App layer header of the request. 224 * 225 * @return Indicates the result of this function call. 226 */ 227 static enum ChppAppErrorCode chppWifiServiceOpen( 228 struct ChppWifiServiceState *wifiServiceContext, 229 struct ChppAppHeader *requestHeader) { 230 static const struct chrePalWifiCallbacks palCallbacks = { 231 .scanMonitorStatusChangeCallback = 232 chppWifiServiceScanMonitorStatusChangeCallback, 233 .scanResponseCallback = chppWifiServiceScanResponseCallback, 234 .scanEventCallback = chppWifiServiceScanEventCallback, 235 .rangingEventCallback = chppWifiServiceRangingEventCallback, 236 }; 237 238 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 239 240 if (wifiServiceContext->service.openState == CHPP_OPEN_STATE_OPENED) { 241 CHPP_LOGE("WiFi service already open"); 242 CHPP_DEBUG_ASSERT(false); 243 error = CHPP_APP_ERROR_INVALID_COMMAND; 244 245 } else if (!wifiServiceContext->api->open( 246 wifiServiceContext->service.appContext->systemApi, 247 &palCallbacks)) { 248 CHPP_LOGE("WiFi PAL open failed"); 249 CHPP_DEBUG_ASSERT(false); 250 error = CHPP_APP_ERROR_BEYOND_CHPP; 251 252 } else { 253 CHPP_LOGI("WiFi service opened"); 254 wifiServiceContext->service.openState = CHPP_OPEN_STATE_OPENED; 255 256 struct ChppAppHeader *response = 257 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader); 258 size_t responseLen = sizeof(*response); 259 260 if (response == NULL) { 261 CHPP_LOG_OOM(); 262 error = CHPP_APP_ERROR_OOM; 263 } else { 264 chppSendTimestampedResponseOrFail(&wifiServiceContext->service, 265 &wifiServiceContext->open, response, 266 responseLen); 267 } 268 } 269 270 return error; 271 } 272 273 /** 274 * Deinitializes the WiFi service. 275 * 276 * @param serviceContext Maintains status for each service instance. 277 * @param requestHeader App layer header of the request. 278 * 279 * @return Indicates the result of this function call. 280 */ 281 static enum ChppAppErrorCode chppWifiServiceClose( 282 struct ChppWifiServiceState *wifiServiceContext, 283 struct ChppAppHeader *requestHeader) { 284 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 285 286 wifiServiceContext->api->close(); 287 wifiServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED; 288 289 CHPP_LOGI("WiFi service closed"); 290 291 struct ChppAppHeader *response = 292 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader); 293 size_t responseLen = sizeof(*response); 294 295 if (response == NULL) { 296 CHPP_LOG_OOM(); 297 error = CHPP_APP_ERROR_OOM; 298 } else { 299 chppSendTimestampedResponseOrFail(&wifiServiceContext->service, 300 &wifiServiceContext->close, response, 301 responseLen); 302 } 303 return error; 304 } 305 306 /** 307 * Notifies the service of an incoming reset. 308 * 309 * @param serviceContext Maintains status for each service instance. 310 */ 311 static void chppWifiServiceNotifyReset(void *serviceContext) { 312 struct ChppWifiServiceState *wifiServiceContext = 313 (struct ChppWifiServiceState *)serviceContext; 314 315 if (wifiServiceContext->service.openState != CHPP_OPEN_STATE_OPENED) { 316 CHPP_LOGW("WiFi service reset but wasn't open"); 317 } else { 318 CHPP_LOGI("WiFi service reset. Closing"); 319 wifiServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED; 320 wifiServiceContext->api->close(); 321 } 322 } 323 324 /** 325 * Retrieves a set of flags indicating the WiFi features supported by the 326 * current implementation. 327 * 328 * @param serviceContext Maintains status for each service instance. 329 * @param requestHeader App layer header of the request. 330 * 331 * @return Indicates the result of this function call. 332 */ 333 static enum ChppAppErrorCode chppWifiServiceGetCapabilities( 334 struct ChppWifiServiceState *wifiServiceContext, 335 struct ChppAppHeader *requestHeader) { 336 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 337 338 struct ChppWifiGetCapabilitiesResponse *response = 339 chppAllocServiceResponseFixed(requestHeader, 340 struct ChppWifiGetCapabilitiesResponse); 341 size_t responseLen = sizeof(*response); 342 343 if (response == NULL) { 344 CHPP_LOG_OOM(); 345 error = CHPP_APP_ERROR_OOM; 346 } else { 347 response->params.capabilities = wifiServiceContext->api->getCapabilities(); 348 349 CHPP_LOGD("chppWifiServiceGetCapabilities returning 0x%" PRIx32 350 ", %" PRIuSIZE " bytes", 351 response->params.capabilities, responseLen); 352 chppSendTimestampedResponseOrFail(&wifiServiceContext->service, 353 &wifiServiceContext->getCapabilities, 354 response, responseLen); 355 } 356 357 return error; 358 } 359 360 /** 361 * Configures whether scanEventCallback receives unsolicited scan results, i.e. 362 * the results of scans not performed at the request of CHRE. 363 * 364 * This function returns an error code synchronously. 365 * A subsequent call to chppWifiServiceScanMonitorStatusChangeCallback() will be 366 * used to communicate the result of this request (as a service response). 367 * 368 * @param serviceContext Maintains status for each service instance. 369 * @param requestHeader App layer header of the request. 370 * @param buf Input data. Cannot be null. 371 * @param len Length of input data in bytes. 372 * 373 * @return Indicates the result of this function call. 374 */ 375 static enum ChppAppErrorCode chppWifiServiceConfigureScanMonitorAsync( 376 struct ChppWifiServiceState *wifiServiceContext, 377 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) { 378 UNUSED_VAR(requestHeader); 379 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 380 381 if (len < sizeof(bool)) { 382 error = CHPP_APP_ERROR_INVALID_ARG; 383 } else { 384 bool *enable = (bool *)buf; 385 if (!wifiServiceContext->api->configureScanMonitor(*enable)) { 386 error = CHPP_APP_ERROR_UNSPECIFIED; 387 } 388 } 389 390 return error; 391 } 392 393 /** 394 * Request that the WiFi chipset perform a scan, or deliver results from its 395 * cache if the parameters allow for it. 396 * 397 * This function returns an error code synchronously. 398 * A subsequent call to chppWifiServiceScanResponseCallback() will be used to 399 * communicate the result of this request (as a service response). 400 * A subsequent call to chppWifiServiceScanEventCallback() will be used to 401 * communicate the scan results (as a service notification). 402 * 403 * @param serviceContext Maintains status for each service instance. 404 * @param requestHeader App layer header of the request. 405 * @param buf Input data. Cannot be null. 406 * @param len Length of input data in bytes. 407 * 408 * @return Indicates the result of this function call. 409 */ 410 static enum ChppAppErrorCode chppWifiServiceRequestScanAsync( 411 struct ChppWifiServiceState *wifiServiceContext, 412 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) { 413 UNUSED_VAR(requestHeader); 414 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 415 416 struct chreWifiScanParams *chre = 417 chppWifiScanParamsToChre((struct ChppWifiScanParams *)buf, len); 418 419 if (chre == NULL) { 420 CHPP_LOGE( 421 "WifiServiceRequestScanAsync CHPP -> CHRE conversion failed. Input " 422 "len=%" PRIuSIZE, 423 len); 424 error = CHPP_APP_ERROR_INVALID_ARG; 425 426 } else { 427 if (!wifiServiceContext->api->requestScan(chre)) { 428 error = CHPP_APP_ERROR_UNSPECIFIED; 429 } 430 431 if (chre->frequencyListLen > 0) { 432 void *frequencyList = CHPP_CONST_CAST_POINTER(chre->frequencyList); 433 CHPP_FREE_AND_NULLIFY(frequencyList); 434 } 435 if (chre->ssidListLen > 0) { 436 void *ssidList = CHPP_CONST_CAST_POINTER(chre->ssidList); 437 CHPP_FREE_AND_NULLIFY(ssidList); 438 } 439 CHPP_FREE_AND_NULLIFY(chre); 440 } 441 442 return error; 443 } 444 445 /** 446 * Request that the WiFi chipset perform RTT ranging against a set of access 447 * points specified in params. 448 * 449 * This function returns an error code synchronously. 450 * A subsequent call to chppWifiServiceRangingEventCallback() will be used to 451 * communicate the ranging results (as a service notification). 452 * 453 * @param serviceContext Maintains status for each service instance. 454 * @param requestHeader App layer header of the request. 455 * @param buf Input data. Cannot be null. 456 * @param len Length of input data in bytes. 457 * 458 * @return Indicates the result of this function call. 459 */ 460 static enum ChppAppErrorCode chppWifiServiceRequestRangingAsync( 461 struct ChppWifiServiceState *wifiServiceContext, 462 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) { 463 UNUSED_VAR(requestHeader); 464 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE; 465 466 struct chreWifiRangingParams *chre = 467 chppWifiRangingParamsToChre((struct ChppWifiRangingParams *)buf, len); 468 469 if (chre == NULL) { 470 CHPP_LOGE( 471 "WifiServiceRequestRangingAsync CHPP -> CHRE conversion failed. Input " 472 "len=%" PRIuSIZE, 473 len); 474 error = CHPP_APP_ERROR_INVALID_ARG; 475 476 } else { 477 if (!wifiServiceContext->api->requestRanging(chre)) { 478 error = CHPP_APP_ERROR_UNSPECIFIED; 479 480 } else { 481 struct ChppAppHeader *response = 482 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader); 483 size_t responseLen = sizeof(*response); 484 485 if (response == NULL) { 486 CHPP_LOG_OOM(); 487 error = CHPP_APP_ERROR_OOM; 488 } else { 489 chppSendTimestampedResponseOrFail( 490 &wifiServiceContext->service, 491 &wifiServiceContext->requestRangingAsync, response, responseLen); 492 } 493 } 494 495 if (chre->targetListLen > 0) { 496 void *targetList = CHPP_CONST_CAST_POINTER(chre->targetList); 497 CHPP_FREE_AND_NULLIFY(targetList); 498 } 499 CHPP_FREE_AND_NULLIFY(chre); 500 } 501 502 return error; 503 } 504 505 /** 506 * PAL callback with the result of changes to the scan monitor registration 507 * status requested via configureScanMonitor. 508 * 509 * @param enabled true if the scan monitor is currently active 510 * @param errorCode An error code from enum chreError 511 */ 512 static void chppWifiServiceScanMonitorStatusChangeCallback(bool enabled, 513 uint8_t errorCode) { 514 // Recreate request header 515 struct ChppAppHeader requestHeader = { 516 .handle = gWifiServiceContext.service.handle, 517 .transaction = gWifiServiceContext.configureScanMonitorAsync.transaction, 518 .command = CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC, 519 }; 520 521 struct ChppWifiConfigureScanMonitorAsyncResponse *response = 522 chppAllocServiceResponseFixed( 523 &requestHeader, struct ChppWifiConfigureScanMonitorAsyncResponse); 524 size_t responseLen = sizeof(*response); 525 526 if (response == NULL) { 527 CHPP_LOG_OOM(); 528 CHPP_ASSERT(false); 529 530 } else { 531 response->params.enabled = enabled; 532 response->params.errorCode = errorCode; 533 534 chppSendTimestampedResponseOrFail( 535 &gWifiServiceContext.service, 536 &gWifiServiceContext.configureScanMonitorAsync, response, responseLen); 537 } 538 } 539 540 /** 541 * PAL callback with the result of a requestScan. 542 * 543 * @param pending true if the request was successful. 544 * @param errorCode An error code from enum chreError. 545 */ 546 static void chppWifiServiceScanResponseCallback(bool pending, 547 uint8_t errorCode) { 548 // Recreate request header 549 struct ChppAppHeader requestHeader = { 550 .handle = gWifiServiceContext.service.handle, 551 .transaction = gWifiServiceContext.requestScanAsync.transaction, 552 .command = CHPP_WIFI_REQUEST_SCAN_ASYNC, 553 }; 554 555 struct ChppWifiRequestScanResponse *response = chppAllocServiceResponseFixed( 556 &requestHeader, struct ChppWifiRequestScanResponse); 557 size_t responseLen = sizeof(*response); 558 559 if (response == NULL) { 560 CHPP_LOG_OOM(); 561 CHPP_ASSERT(false); 562 563 } else { 564 response->params.pending = pending; 565 response->params.errorCode = errorCode; 566 567 chppSendTimestampedResponseOrFail(&gWifiServiceContext.service, 568 &gWifiServiceContext.requestScanAsync, 569 response, responseLen); 570 } 571 } 572 573 /** 574 * PAL callback with WiFi scan results. 575 * 576 * @param event Scan result data. 577 */ 578 static void chppWifiServiceScanEventCallback(struct chreWifiScanEvent *event) { 579 // Craft response per parser script 580 struct ChppWifiScanEventWithHeader *notification = NULL; 581 size_t notificationLen = 0; 582 583 CHPP_DEBUG_ASSERT(chppCheckWifiScanEventNotification(event)); 584 585 if (!chppWifiScanEventFromChre(event, ¬ification, ¬ificationLen)) { 586 CHPP_LOGE("ScanEvent conversion failed (OOM?). ID=%" PRIu8, 587 gWifiServiceContext.requestScanAsync.transaction); 588 589 notification = chppMalloc(sizeof(struct ChppAppHeader)); 590 if (notification == NULL) { 591 CHPP_LOG_OOM(); 592 } else { 593 notificationLen = sizeof(struct ChppAppHeader); 594 } 595 } 596 597 if (notification != NULL) { 598 notification->header.handle = gWifiServiceContext.service.handle; 599 notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION; 600 notification->header.transaction = 601 gWifiServiceContext.requestScanAsync.transaction; 602 notification->header.error = 603 (notificationLen > sizeof(struct ChppAppHeader)) 604 ? CHPP_APP_ERROR_NONE 605 : CHPP_APP_ERROR_CONVERSION_FAILED; 606 notification->header.command = CHPP_WIFI_REQUEST_SCAN_ASYNC; 607 608 chppEnqueueTxDatagramOrFail( 609 gWifiServiceContext.service.appContext->transportContext, notification, 610 notificationLen); 611 } 612 613 gWifiServiceContext.api->releaseScanEvent(event); 614 } 615 616 /** 617 * PAL callback with RTT ranging results from the WiFi module. 618 * 619 * @param errorCode An error code from enum chreError. 620 * @param event Ranging data. 621 */ 622 static void chppWifiServiceRangingEventCallback( 623 uint8_t errorCode, struct chreWifiRangingEvent *event) { 624 struct ChppWifiRangingEventWithHeader *notification = NULL; 625 size_t notificationLen = 0; 626 627 if (!chppWifiRangingEventFromChre(event, ¬ification, ¬ificationLen)) { 628 CHPP_LOGE("RangingEvent conversion failed (OOM?) ID=%" PRIu8, 629 gWifiServiceContext.requestRangingAsync.transaction); 630 631 notification = chppMalloc(sizeof(struct ChppAppHeader)); 632 if (notification == NULL) { 633 CHPP_LOG_OOM(); 634 } else { 635 notificationLen = sizeof(struct ChppAppHeader); 636 } 637 } 638 639 if (notification != NULL) { 640 notification->header.handle = gWifiServiceContext.service.handle; 641 notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION; 642 notification->header.transaction = 643 gWifiServiceContext.requestRangingAsync.transaction; 644 notification->header.error = 645 (notificationLen > sizeof(struct ChppAppHeader)) 646 ? CHPP_APP_ERROR_NONE 647 : CHPP_APP_ERROR_CONVERSION_FAILED; 648 notification->header.command = CHPP_WIFI_REQUEST_RANGING_ASYNC; 649 650 if (errorCode != CHRE_ERROR_NONE) { 651 notification->header.error = CHPP_APP_ERROR_BEYOND_CHPP; 652 notificationLen = MIN(notificationLen, sizeof(struct ChppAppHeader)); 653 } 654 655 chppEnqueueTxDatagramOrFail( 656 gWifiServiceContext.service.appContext->transportContext, notification, 657 notificationLen); 658 } 659 660 gWifiServiceContext.api->releaseRangingEvent(event); 661 } 662 663 /************************************************ 664 * Public Functions 665 ***********************************************/ 666 667 void chppRegisterWifiService(struct ChppAppState *appContext) { 668 gWifiServiceContext.api = chrePalWifiGetApi(CHRE_PAL_WIFI_API_V1_2); 669 670 chppCheckWifiScanEventNotificationReset(); 671 672 if (gWifiServiceContext.api == NULL) { 673 CHPP_LOGE( 674 "WiFi PAL API version not compatible with CHPP. Cannot register WiFi " 675 "service"); 676 CHPP_DEBUG_ASSERT(false); 677 678 } else { 679 gWifiServiceContext.service.appContext = appContext; 680 gWifiServiceContext.service.handle = chppRegisterService( 681 appContext, (void *)&gWifiServiceContext, &kWifiServiceConfig); 682 CHPP_DEBUG_ASSERT(gWifiServiceContext.service.handle); 683 } 684 } 685 686 void chppDeregisterWifiService(struct ChppAppState *appContext) { 687 // TODO 688 689 UNUSED_VAR(appContext); 690 } 691