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/clients/wifi.h"
18
19 #include <inttypes.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 #include <string.h>
24
25 #include "chpp/app.h"
26 #include "chpp/clients.h"
27 #include "chpp/clients/discovery.h"
28 #ifdef CHPP_CLIENT_ENABLED_TIMESYNC
29 #include "chpp/clients/timesync.h"
30 #endif
31 #include "chpp/common/standard_uuids.h"
32 #include "chpp/common/wifi.h"
33 #include "chpp/common/wifi_types.h"
34 #include "chpp/common/wifi_utils.h"
35 #include "chpp/log.h"
36 #include "chpp/macros.h"
37 #include "chpp/memory.h"
38 #include "chpp/time.h"
39 #include "chre/pal/wifi.h"
40 #include "chre_api/chre/wifi.h"
41
42 #ifndef CHPP_WIFI_DISCOVERY_TIMEOUT_MS
43 #define CHPP_WIFI_DISCOVERY_TIMEOUT_MS CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS
44 #endif
45
46 #ifndef CHPP_WIFI_MAX_TIMESYNC_AGE_NS
47 #define CHPP_WIFI_MAX_TIMESYNC_AGE_NS CHPP_TIMESYNC_DEFAULT_MAX_AGE_NS
48 #endif
49
50 #ifndef CHPP_WIFI_SCAN_RESULT_TIMEOUT_NS
51 #define CHPP_WIFI_SCAN_RESULT_TIMEOUT_NS \
52 (CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS - CHRE_NSEC_PER_SEC)
53 #endif
54
55 /************************************************
56 * Prototypes
57 ***********************************************/
58
59 static enum ChppAppErrorCode chppDispatchWifiResponse(void *clientContext,
60 uint8_t *buf, size_t len);
61 static enum ChppAppErrorCode chppDispatchWifiNotification(void *clientContext,
62 uint8_t *buf,
63 size_t len);
64 static bool chppWifiClientInit(void *clientContext, uint8_t handle,
65 struct ChppVersion serviceVersion);
66 static void chppWifiClientDeinit(void *clientContext);
67 static void chppWifiClientNotifyReset(void *clientContext);
68 static void chppWifiClientNotifyMatch(void *clientContext);
69
70 /************************************************
71 * Private Definitions
72 ***********************************************/
73
74 /**
75 * Structure to maintain state for the WiFi client and its Request/Response
76 * (RR) functionality.
77 */
78 struct ChppWifiClientState {
79 struct ChppEndpointState client; // CHPP client state
80 const struct chrePalWifiApi *api; // WiFi PAL API
81
82 struct ChppOutgoingRequestState
83 outReqStates[CHPP_WIFI_CLIENT_REQUEST_MAX + 1];
84
85 uint32_t capabilities; // Cached GetCapabilities result
86 bool scanMonitorEnabled; // Scan monitoring is enabled
87 bool scanMonitorSilenceCallback; // Silence callback during recovery from a
88 // service reset
89 bool capabilitiesValid; // Flag to indicate if the capabilities result
90 // is valid
91 };
92
93 // Note: This global definition of gWifiClientContext supports only one
94 // instance of the CHPP WiFi client at a time.
95 struct ChppWifiClientState gWifiClientContext;
96 static const struct chrePalSystemApi *gSystemApi;
97 static const struct chrePalWifiCallbacks *gCallbacks;
98
99 /**
100 * Configuration parameters for this client
101 */
102 static const struct ChppClient kWifiClientConfig = {
103 .descriptor.uuid = CHPP_UUID_WIFI_STANDARD,
104
105 // Version
106 .descriptor.version.major = 1,
107 .descriptor.version.minor = 0,
108 .descriptor.version.patch = 0,
109
110 // Notifies client if CHPP is reset
111 .resetNotifierFunctionPtr = &chppWifiClientNotifyReset,
112
113 // Notifies client if they are matched to a service
114 .matchNotifierFunctionPtr = &chppWifiClientNotifyMatch,
115
116 // Service response dispatch function pointer
117 .responseDispatchFunctionPtr = &chppDispatchWifiResponse,
118
119 // Service notification dispatch function pointer
120 .notificationDispatchFunctionPtr = &chppDispatchWifiNotification,
121
122 // Service response dispatch function pointer
123 .initFunctionPtr = &chppWifiClientInit,
124
125 // Service notification dispatch function pointer
126 .deinitFunctionPtr = &chppWifiClientDeinit,
127
128 // Number of request-response states in the outReqStates array.
129 .outReqCount = ARRAY_SIZE(gWifiClientContext.outReqStates),
130
131 // Min length is the entire header
132 .minLength = sizeof(struct ChppAppHeader),
133 };
134
135 /************************************************
136 * Prototypes
137 ***********************************************/
138
139 static bool chppWifiClientOpen(const struct chrePalSystemApi *systemApi,
140 const struct chrePalWifiCallbacks *callbacks);
141 static void chppWifiClientClose(void);
142 static uint32_t chppWifiClientGetCapabilities(void);
143 static bool chppWifiClientConfigureScanMonitor(bool enable);
144 static bool chppWifiClientRequestScan(const struct chreWifiScanParams *params);
145 static void chppWifiClientReleaseScanEvent(struct chreWifiScanEvent *event);
146 static bool chppWifiClientRequestRanging(
147 const struct chreWifiRangingParams *params);
148 static void chppWifiClientReleaseRangingEvent(
149 struct chreWifiRangingEvent *event);
150
151 static void chppWiFiRecoverScanMonitor(
152 struct ChppWifiClientState *clientContext);
153 static void chppWifiCloseResult(struct ChppWifiClientState *clientContext,
154 uint8_t *buf, size_t len);
155 static void chppWifiGetCapabilitiesResult(
156 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len);
157 static void chppWifiConfigureScanMonitorResult(
158 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len);
159 static void chppWifiRequestScanResult(struct ChppWifiClientState *clientContext,
160 uint8_t *buf, size_t len);
161 static void chppWifiRequestRangingResult(
162 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len);
163 static void chppWifiRequestNanSubscribeResult(uint8_t *buf, size_t len);
164
165 static void chppWifiScanEventNotification(
166 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len);
167 static void chppWifiRangingEventNotification(
168 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len);
169 static void chppWifiDiscoveryEventNotification(uint8_t *buf, size_t len);
170 static void chppWifiNanServiceLostEventNotification(uint8_t *buf, size_t len);
171 static void chppWifiNanServiceTerminatedEventNotification(uint8_t *buf,
172 size_t len);
173 static void chppWifiRequestNanSubscribeNotification(uint8_t *buf, size_t len);
174 static void chppWifiNanSubscriptionCanceledNotification(uint8_t *buf,
175 size_t len);
176 static void chppWifiNanSubscriptionCanceledResult(uint8_t *buf, size_t len);
177
178 /************************************************
179 * Private Functions
180 ***********************************************/
181
182 /**
183 * Dispatches a service response from the transport layer that is determined to
184 * be for the WiFi client.
185 *
186 * This function is called from the app layer using its function pointer given
187 * during client registration.
188 *
189 * @param clientContext Maintains status for each client instance.
190 * @param buf Input data. Cannot be null.
191 * @param len Length of input data in bytes.
192 *
193 * @return Indicates the result of this function call.
194 */
chppDispatchWifiResponse(void * clientContext,uint8_t * buf,size_t len)195 static enum ChppAppErrorCode chppDispatchWifiResponse(void *clientContext,
196 uint8_t *buf,
197 size_t len) {
198 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
199 struct ChppWifiClientState *wifiClientContext =
200 (struct ChppWifiClientState *)clientContext;
201 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
202
203 if (rxHeader->command > CHPP_WIFI_CLIENT_REQUEST_MAX) {
204 error = CHPP_APP_ERROR_INVALID_COMMAND;
205
206 } else if (!chppTimestampIncomingResponse(
207 wifiClientContext->client.appContext,
208 &wifiClientContext->outReqStates[rxHeader->command],
209 rxHeader)) {
210 error = CHPP_APP_ERROR_UNEXPECTED_RESPONSE;
211
212 } else {
213 switch (rxHeader->command) {
214 case CHPP_WIFI_OPEN: {
215 chppClientProcessOpenResponse(&wifiClientContext->client, buf, len);
216 if (rxHeader->error == CHPP_APP_ERROR_NONE) {
217 chppWiFiRecoverScanMonitor(wifiClientContext);
218 }
219 break;
220 }
221
222 case CHPP_WIFI_CLOSE: {
223 chppWifiCloseResult(wifiClientContext, buf, len);
224 break;
225 }
226
227 case CHPP_WIFI_GET_CAPABILITIES: {
228 chppWifiGetCapabilitiesResult(wifiClientContext, buf, len);
229 break;
230 }
231
232 case CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC: {
233 chppWifiConfigureScanMonitorResult(wifiClientContext, buf, len);
234 break;
235 }
236
237 case CHPP_WIFI_REQUEST_SCAN_ASYNC: {
238 chppWifiRequestScanResult(wifiClientContext, buf, len);
239 break;
240 }
241
242 case CHPP_WIFI_REQUEST_RANGING_ASYNC:
243 case CHPP_WIFI_REQUEST_NAN_RANGING_ASYNC: {
244 chppWifiRequestRangingResult(wifiClientContext, buf, len);
245 break;
246 }
247
248 case CHPP_WIFI_REQUEST_NAN_SUB: {
249 chppWifiRequestNanSubscribeResult(buf, len);
250 break;
251 }
252
253 case CHPP_WIFI_REQUEST_NAN_SUB_CANCEL: {
254 chppWifiNanSubscriptionCanceledResult(buf, len);
255 break;
256 }
257
258 default: {
259 error = CHPP_APP_ERROR_INVALID_COMMAND;
260 break;
261 }
262 }
263 }
264
265 return error;
266 }
267
268 /**
269 * Dispatches a service notification from the transport layer that is determined
270 * to be for the WiFi client.
271 *
272 * This function is called from the app layer using its function pointer given
273 * during client registration.
274 *
275 * @param clientContext Maintains status for each client instance.
276 * @param buf Input data. Cannot be null.
277 * @param len Length of input data in bytes.
278 *
279 * @return Indicates the result of this function call.
280 */
chppDispatchWifiNotification(void * clientContext,uint8_t * buf,size_t len)281 static enum ChppAppErrorCode chppDispatchWifiNotification(void *clientContext,
282 uint8_t *buf,
283 size_t len) {
284 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
285 struct ChppWifiClientState *wifiClientContext =
286 (struct ChppWifiClientState *)clientContext;
287 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
288
289 switch (rxHeader->command) {
290 case CHPP_WIFI_REQUEST_SCAN_ASYNC: {
291 chppWifiScanEventNotification(wifiClientContext, buf, len);
292 break;
293 }
294
295 case CHPP_WIFI_REQUEST_RANGING_ASYNC:
296 case CHPP_WIFI_REQUEST_NAN_RANGING_ASYNC: {
297 chppWifiRangingEventNotification(wifiClientContext, buf, len);
298 break;
299 }
300
301 case CHPP_WIFI_NOTIFICATION_NAN_SERVICE_DISCOVERY: {
302 chppWifiDiscoveryEventNotification(buf, len);
303 break;
304 }
305
306 case CHPP_WIFI_NOTIFICATION_NAN_SERVICE_LOST: {
307 chppWifiNanServiceLostEventNotification(buf, len);
308 break;
309 }
310
311 case CHPP_WIFI_NOTIFICATION_NAN_SERVICE_TERMINATED: {
312 chppWifiNanServiceTerminatedEventNotification(buf, len);
313 break;
314 }
315
316 case CHPP_WIFI_REQUEST_NAN_SUB: {
317 chppWifiRequestNanSubscribeNotification(buf, len);
318 break;
319 }
320
321 case CHPP_WIFI_REQUEST_NAN_SUB_CANCEL: {
322 chppWifiNanSubscriptionCanceledNotification(buf, len);
323 break;
324 }
325
326 default: {
327 error = CHPP_APP_ERROR_INVALID_COMMAND;
328 break;
329 }
330 }
331
332 return error;
333 }
334
335 /**
336 * Initializes the client and provides its handle number and the version of the
337 * matched service when/if it the client is matched with a service during
338 * discovery.
339 *
340 * @param clientContext Maintains status for each client instance.
341 * @param handle Handle number for this client.
342 * @param serviceVersion Version of the matched service.
343 *
344 * @return True if client is compatible and successfully initialized.
345 */
chppWifiClientInit(void * clientContext,uint8_t handle,struct ChppVersion serviceVersion)346 static bool chppWifiClientInit(void *clientContext, uint8_t handle,
347 struct ChppVersion serviceVersion) {
348 UNUSED_VAR(serviceVersion);
349
350 struct ChppWifiClientState *wifiClientContext =
351 (struct ChppWifiClientState *)clientContext;
352 chppClientInit(&wifiClientContext->client, handle);
353
354 return true;
355 }
356
357 /**
358 * Deinitializes the client.
359 *
360 * @param clientContext Maintains status for each client instance.
361 */
chppWifiClientDeinit(void * clientContext)362 static void chppWifiClientDeinit(void *clientContext) {
363 struct ChppWifiClientState *wifiClientContext =
364 (struct ChppWifiClientState *)clientContext;
365 chppClientDeinit(&wifiClientContext->client);
366 }
367
368 /**
369 * Notifies the client of an incoming reset.
370 *
371 * @param clientContext Maintains status for each client instance.
372 */
chppWifiClientNotifyReset(void * clientContext)373 static void chppWifiClientNotifyReset(void *clientContext) {
374 struct ChppWifiClientState *wifiClientContext =
375 (struct ChppWifiClientState *)clientContext;
376
377 chppClientCloseOpenRequests(&wifiClientContext->client, &kWifiClientConfig,
378 false /* clearOnly */);
379 chppCheckWifiScanEventNotificationReset();
380
381 CHPP_LOGI("WiFi client reopening from state=%" PRIu8,
382 wifiClientContext->client.openState);
383 chppClientSendOpenRequest(&wifiClientContext->client,
384 &wifiClientContext->outReqStates[CHPP_WIFI_OPEN],
385 CHPP_WIFI_OPEN,
386 /*blocking=*/false);
387 }
388
389 /**
390 * Notifies the client of being matched to a service.
391 *
392 * @param clientContext Maintains status for each client instance.
393 */
chppWifiClientNotifyMatch(void * clientContext)394 static void chppWifiClientNotifyMatch(void *clientContext) {
395 struct ChppWifiClientState *wifiClientContext =
396 (struct ChppWifiClientState *)clientContext;
397
398 if (wifiClientContext->client.pseudoOpen) {
399 CHPP_LOGD("Pseudo-open WiFi client opening");
400 chppClientSendOpenRequest(&wifiClientContext->client,
401 &wifiClientContext->outReqStates[CHPP_WIFI_OPEN],
402 CHPP_WIFI_OPEN,
403 /*blocking=*/false);
404 }
405 }
406
407 /**
408 * Restores the state of scan monitoring after an incoming reset.
409 *
410 * @param clientContext Maintains status for each client instance.
411 */
chppWiFiRecoverScanMonitor(struct ChppWifiClientState * clientContext)412 static void chppWiFiRecoverScanMonitor(
413 struct ChppWifiClientState *clientContext) {
414 if (clientContext->scanMonitorEnabled) {
415 CHPP_LOGD("Re-enabling WiFi scan monitoring after reset");
416 clientContext->scanMonitorEnabled = false;
417 clientContext->scanMonitorSilenceCallback = true;
418
419 if (!chppWifiClientConfigureScanMonitor(true)) {
420 clientContext->scanMonitorSilenceCallback = false;
421 CHPP_DEBUG_ASSERT_LOG(false, "Failed to re-enable WiFi scan monitoring");
422 }
423 }
424 }
425
426 /**
427 * Handles the service response for the close client request.
428 *
429 * This function is called from chppDispatchWifiResponse().
430 *
431 * @param clientContext Maintains status for each client instance.
432 * @param buf Input data. Cannot be null.
433 * @param len Length of input data in bytes.
434 */
chppWifiCloseResult(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)435 static void chppWifiCloseResult(struct ChppWifiClientState *clientContext,
436 uint8_t *buf, size_t len) {
437 // TODO
438 UNUSED_VAR(clientContext);
439 UNUSED_VAR(buf);
440 UNUSED_VAR(len);
441 }
442
443 /**
444 * Handles the service response for the get capabilities client request.
445 *
446 * This function is called from chppDispatchWifiResponse().
447 *
448 * @param clientContext Maintains status for each client instance.
449 * @param buf Input data. Cannot be null.
450 * @param len Length of input data in bytes.
451 */
chppWifiGetCapabilitiesResult(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)452 static void chppWifiGetCapabilitiesResult(
453 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len) {
454 if (len < sizeof(struct ChppWifiGetCapabilitiesResponse)) {
455 CHPP_LOGE("Bad WiFi capabilities len=%" PRIuSIZE, len);
456
457 } else {
458 struct ChppWifiGetCapabilitiesParameters *result =
459 &((struct ChppWifiGetCapabilitiesResponse *)buf)->params;
460
461 CHPP_LOGD("chppWifiGetCapabilitiesResult received capabilities=0x%" PRIx32,
462 result->capabilities);
463
464 CHPP_ASSERT((result->capabilities & CHPP_WIFI_DEFAULT_CAPABILITIES) ==
465 CHPP_WIFI_DEFAULT_CAPABILITIES);
466 if (result->capabilities != CHPP_WIFI_DEFAULT_CAPABILITIES) {
467 CHPP_LOGE("WiFi capabilities 0x%" PRIx32 " != 0x%" PRIx32,
468 result->capabilities, CHPP_WIFI_DEFAULT_CAPABILITIES);
469 }
470
471 clientContext->capabilitiesValid = true;
472 clientContext->capabilities = result->capabilities;
473 }
474 }
475
476 /**
477 * Handles the service response for the Configure Scan Monitor client request.
478 *
479 * This function is called from chppDispatchWifiResponse().
480 *
481 * @param clientContext Maintains status for each client instance.
482 * @param buf Input data. Cannot be null.
483 * @param len Length of input data in bytes.
484 */
chppWifiConfigureScanMonitorResult(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)485 static void chppWifiConfigureScanMonitorResult(
486 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len) {
487 UNUSED_VAR(clientContext);
488
489 if (len < sizeof(struct ChppWifiConfigureScanMonitorAsyncResponse)) {
490 // Short response length indicates an error
491 uint8_t error = chppAppShortResponseErrorHandler(buf, len, "ScanMonitor");
492 if (!gWifiClientContext.scanMonitorSilenceCallback) {
493 gCallbacks->scanMonitorStatusChangeCallback(false, error);
494 }
495 } else {
496 struct ChppWifiConfigureScanMonitorAsyncResponseParameters *result =
497 &((struct ChppWifiConfigureScanMonitorAsyncResponse *)buf)->params;
498
499 gWifiClientContext.scanMonitorEnabled = result->enabled;
500 CHPP_LOGD(
501 "chppWifiConfigureScanMonitorResult received enable=%d, "
502 "errorCode=%" PRIu8,
503 result->enabled, result->errorCode);
504
505 if (!gWifiClientContext.scanMonitorSilenceCallback) {
506 // Per the scanMonitorStatusChangeCallback API contract, unsolicited
507 // calls to scanMonitorStatusChangeCallback must not be made, and it
508 // should only be invoked as the direct result of an earlier call to
509 // configureScanMonitor.
510 gCallbacks->scanMonitorStatusChangeCallback(result->enabled,
511 result->errorCode);
512 } // Else, the WiFi subsystem has been reset and we are required to
513 // silently reenable the scan monitor.
514
515 gWifiClientContext.scanMonitorSilenceCallback = false;
516 }
517 }
518
519 /**
520 * Handles the service response for the Request Scan Result client request.
521 *
522 * This function is called from chppDispatchWifiResponse().
523 *
524 * @param clientContext Maintains status for each client instance.
525 * @param buf Input data. Cannot be null.
526 * @param len Length of input data in bytes.
527 */
chppWifiRequestScanResult(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)528 static void chppWifiRequestScanResult(struct ChppWifiClientState *clientContext,
529 uint8_t *buf, size_t len) {
530 UNUSED_VAR(clientContext);
531
532 if (len < sizeof(struct ChppWifiRequestScanResponse)) {
533 // Short response length indicates an error
534 gCallbacks->scanResponseCallback(
535 false, chppAppShortResponseErrorHandler(buf, len, "ScanRequest"));
536
537 } else {
538 struct ChppWifiRequestScanResponseParameters *result =
539 &((struct ChppWifiRequestScanResponse *)buf)->params;
540 CHPP_LOGI("Scan request success=%d at service", result->pending);
541 gCallbacks->scanResponseCallback(result->pending, result->errorCode);
542 }
543 }
544
545 /**
546 * Handles the service response for the Request Ranging Result client request.
547 *
548 * This function is called from chppDispatchWifiResponse().
549 *
550 * @param clientContext Maintains status for each client instance.
551 * @param buf Input data. Cannot be null.
552 * @param len Length of input data in bytes.
553 */
chppWifiRequestRangingResult(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)554 static void chppWifiRequestRangingResult(
555 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len) {
556 UNUSED_VAR(clientContext);
557 UNUSED_VAR(len);
558
559 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
560
561 if (rxHeader->error != CHPP_APP_ERROR_NONE) {
562 gCallbacks->rangingEventCallback(chppAppErrorToChreError(rxHeader->error),
563 NULL);
564
565 } else {
566 CHPP_LOGD("Ranging request accepted at service");
567 }
568 }
569
570 /**
571 * Handles the service response for the NAN subscribe client request.
572 *
573 * This function is called from chppDispatchWifiResponse().
574 *
575 * @param buf Input data. Cannot be null.
576 * @param len Length of input data in bytes.
577 */
chppWifiRequestNanSubscribeResult(uint8_t * buf,size_t len)578 static void chppWifiRequestNanSubscribeResult(uint8_t *buf, size_t len) {
579 UNUSED_VAR(len);
580
581 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
582
583 if (rxHeader->error != CHPP_APP_ERROR_NONE) {
584 gCallbacks->nanServiceIdentifierCallback(
585 chppAppErrorToChreError(rxHeader->error), 0 /* subscriptionId */);
586
587 } else {
588 CHPP_LOGD("NAN sub accepted at service");
589 }
590 }
591
592 /**
593 * Handles the service response for the NAN subscription cancel client request.
594 *
595 * This function is called from chppDispatchWifiResponse().
596 *
597 * @param buf Input data. Cannot be null.
598 * @param len Length of input data in bytes.
599 */
chppWifiNanSubscriptionCanceledResult(uint8_t * buf,size_t len)600 static void chppWifiNanSubscriptionCanceledResult(uint8_t *buf, size_t len) {
601 UNUSED_VAR(len);
602
603 struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
604
605 if (rxHeader->error != CHPP_APP_ERROR_NONE) {
606 gCallbacks->nanSubscriptionCanceledCallback(
607 chppAppErrorToChreError(rxHeader->error), 0 /* subscriptionId */);
608
609 } else {
610 CHPP_LOGD("NAN sub cancel accepted at service");
611 }
612 }
613
614 /**
615 * Handles the WiFi scan event service notification.
616 *
617 * This function is called from chppDispatchWifiNotification().
618 *
619 * @param clientContext Maintains status for each client instance.
620 * @param buf Input data. Cannot be null.
621 * @param len Length of input data in bytes.
622 */
chppWifiScanEventNotification(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)623 static void chppWifiScanEventNotification(
624 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len) {
625 UNUSED_VAR(clientContext);
626 CHPP_LOGD("chppWifiScanEventNotification received data len=%" PRIuSIZE, len);
627
628 buf += sizeof(struct ChppAppHeader);
629 len -= sizeof(struct ChppAppHeader);
630
631 struct chreWifiScanEvent *chre =
632 chppWifiScanEventToChre((struct ChppWifiScanEvent *)buf, len);
633
634 if (chre == NULL) {
635 CHPP_LOGE("Scan event conversion failed len=%" PRIuSIZE, len);
636 } else {
637 #ifdef CHPP_CLIENT_ENABLED_TIMESYNC
638 uint64_t correctedTime =
639 chre->referenceTime -
640 (uint64_t)chppTimesyncGetOffset(gWifiClientContext.client.appContext,
641 CHPP_WIFI_MAX_TIMESYNC_AGE_NS);
642 uint64_t currentTime = chppGetCurrentTimeNs();
643 if (correctedTime > currentTime) {
644 CHPP_LOGW("WiFi scan time overcorrected %" PRIu64 " current %" PRIu64,
645 correctedTime / CHPP_NSEC_PER_MSEC,
646 currentTime / CHPP_NSEC_PER_MSEC);
647 correctedTime = currentTime;
648 }
649 CHPP_LOGD("WiFi scan time corrected from %" PRIu64 "to %" PRIu64,
650 chre->referenceTime / CHPP_NSEC_PER_MSEC,
651 correctedTime / CHPP_NSEC_PER_MSEC);
652 chre->referenceTime = correctedTime;
653 #endif
654
655 CHPP_DEBUG_ASSERT(chppCheckWifiScanEventNotification(chre));
656
657 gCallbacks->scanEventCallback(chre);
658 }
659 }
660
661 /**
662 * Handles the WiFi ranging event service notification.
663 *
664 * This function is called from chppDispatchWifiNotification().
665 *
666 * @param clientContext Maintains status for each client instance.
667 * @param buf Input data. Cannot be null.
668 * @param len Length of input data in bytes.
669 */
chppWifiRangingEventNotification(struct ChppWifiClientState * clientContext,uint8_t * buf,size_t len)670 static void chppWifiRangingEventNotification(
671 struct ChppWifiClientState *clientContext, uint8_t *buf, size_t len) {
672 UNUSED_VAR(clientContext);
673
674 CHPP_LOGD("chppWifiRangingEventNotification received data len=%" PRIuSIZE,
675 len);
676
677 buf += sizeof(struct ChppAppHeader);
678 len -= sizeof(struct ChppAppHeader);
679
680 // Timestamp correction prior to conversion to avoid const casting issues.
681 #ifdef CHPP_CLIENT_ENABLED_TIMESYNC
682 struct ChppWifiRangingEvent *event = (struct ChppWifiRangingEvent *)buf;
683
684 for (size_t i = 0; i < event->resultCount; i++) {
685 struct ChppWifiRangingResult *results =
686 (struct ChppWifiRangingResult *)&buf[event->results.offset];
687
688 uint64_t correctedTime =
689 results[i].timestamp -
690 (uint64_t)chppTimesyncGetOffset(gWifiClientContext.client.appContext,
691 CHPP_WIFI_MAX_TIMESYNC_AGE_NS);
692 uint64_t currentTime = chppGetCurrentTimeNs();
693 if (correctedTime > currentTime) {
694 CHPP_LOGW("WiFi ranging time overcorrected %" PRIu64 " current %" PRIu64,
695 correctedTime / CHPP_NSEC_PER_MSEC,
696 currentTime / CHPP_NSEC_PER_MSEC);
697 correctedTime = currentTime;
698 }
699 CHPP_LOGD("WiFi ranging result time corrected from %" PRIu64 "to %" PRIu64,
700 results[i].timestamp / CHPP_NSEC_PER_MSEC,
701 correctedTime / CHPP_NSEC_PER_MSEC);
702 results[i].timestamp = correctedTime;
703 }
704 #endif
705
706 struct chreWifiRangingEvent *chre =
707 chppWifiRangingEventToChre((struct ChppWifiRangingEvent *)buf, len);
708
709 uint8_t error = CHRE_ERROR_NONE;
710 if (chre == NULL) {
711 error = CHRE_ERROR;
712 CHPP_LOGE("Ranging event conversion failed len=%" PRIuSIZE, len);
713 }
714
715 gCallbacks->rangingEventCallback(error, chre);
716 }
717
718 /**
719 * Handles the NAN discovery event service notification.
720 *
721 * This function is called from chppDispatchWifiNotification().
722 *
723 * @param buf Input data. Cannot be null.
724 * @param len Length of input data in bytes.
725 */
chppWifiDiscoveryEventNotification(uint8_t * buf,size_t len)726 static void chppWifiDiscoveryEventNotification(uint8_t *buf, size_t len) {
727 CHPP_LOGD("chppWifiDiscoveryEventNotification data len=%" PRIuSIZE, len);
728
729 buf += sizeof(struct ChppAppHeader);
730 len -= sizeof(struct ChppAppHeader);
731
732 struct ChppWifiNanDiscoveryEvent *chppEvent =
733 (struct ChppWifiNanDiscoveryEvent *)buf;
734 struct chreWifiNanDiscoveryEvent *event =
735 chppWifiNanDiscoveryEventToChre(chppEvent, len);
736
737 if (event == NULL) {
738 CHPP_LOGE("Discovery event CHPP -> CHRE conversion failed");
739 } else {
740 gCallbacks->nanServiceDiscoveryCallback(event);
741 }
742 }
743
744 /**
745 * Handles the NAN connection lost event service notification.
746 *
747 * This function is called from chppDispatchWifiNotification().
748 *
749 * @param buf Input data. Cannot be null.
750 * @param len Length of input data in bytes.
751 */
chppWifiNanServiceLostEventNotification(uint8_t * buf,size_t len)752 static void chppWifiNanServiceLostEventNotification(uint8_t *buf, size_t len) {
753 buf += sizeof(struct ChppAppHeader);
754 len -= sizeof(struct ChppAppHeader);
755
756 struct ChppWifiNanSessionLostEvent *chppEvent =
757 (struct ChppWifiNanSessionLostEvent *)buf;
758 struct chreWifiNanSessionLostEvent *event =
759 chppWifiNanSessionLostEventToChre(chppEvent, len);
760
761 if (event == NULL) {
762 CHPP_LOGE("Session lost event CHPP -> CHRE conversion failed");
763 } else {
764 gCallbacks->nanServiceLostCallback(event->id, event->peerId);
765 }
766 }
767
768 /**
769 * Handles the NAN subscription termination event service notification.
770 *
771 * This function is called from chppDispatchWifiNotification().
772 *
773 * @param buf Input data. Cannot be null.
774 * @param len Length of input data in bytes.
775 */
chppWifiNanServiceTerminatedEventNotification(uint8_t * buf,size_t len)776 static void chppWifiNanServiceTerminatedEventNotification(uint8_t *buf,
777 size_t len) {
778 buf += sizeof(struct ChppAppHeader);
779 len -= sizeof(struct ChppAppHeader);
780
781 struct ChppWifiNanSessionTerminatedEvent *chppEvent =
782 (struct ChppWifiNanSessionTerminatedEvent *)buf;
783 struct chreWifiNanSessionTerminatedEvent *event =
784 chppWifiNanSessionTerminatedEventToChre(chppEvent, len);
785
786 if (event == NULL) {
787 CHPP_LOGE("Session terminated event CHPP -> CHRE conversion failed");
788 } else {
789 gCallbacks->nanServiceTerminatedCallback(event->reason, event->id);
790 }
791 }
792
793 /**
794 * Handles the service response for the NAN subscribe client request.
795 *
796 * This function is called from chppDispatchWifiNotification().
797 *
798 * @param buf Input data. Cannot be null.
799 * @param len Length of input data in bytes.
800 */
chppWifiRequestNanSubscribeNotification(uint8_t * buf,size_t len)801 static void chppWifiRequestNanSubscribeNotification(uint8_t *buf, size_t len) {
802 uint8_t errorCode = CHRE_ERROR_NONE;
803 uint32_t subscriptionId = 0;
804
805 if (len < sizeof(struct ChppWifiNanServiceIdentifier)) {
806 errorCode = CHRE_ERROR;
807 } else {
808 struct ChppWifiNanServiceIdentifier *id =
809 (struct ChppWifiNanServiceIdentifier *)buf;
810 errorCode = id->errorCode;
811 subscriptionId = id->subscriptionId;
812 }
813 gCallbacks->nanServiceIdentifierCallback(errorCode, subscriptionId);
814 }
815
816 /**
817 * Handles the service response for the NAN subscription cancel client request.
818 *
819 * This function is called from chppDispatchWifiNotification().
820 *
821 * @param buf Input data. Cannot be null.
822 * @param len Length of input data in bytes.
823 */
chppWifiNanSubscriptionCanceledNotification(uint8_t * buf,size_t len)824 static void chppWifiNanSubscriptionCanceledNotification(uint8_t *buf,
825 size_t len) {
826 uint8_t errorCode = CHRE_ERROR_NONE;
827 uint32_t subscriptionId = 0;
828 if (len < (sizeof(struct ChppWifiNanSubscriptionCanceledResponse))) {
829 errorCode = CHRE_ERROR;
830 } else {
831 struct ChppWifiNanSubscriptionCanceledResponse *chppNotif =
832 (struct ChppWifiNanSubscriptionCanceledResponse *)buf;
833 errorCode = chppNotif->errorCode;
834 subscriptionId = chppNotif->subscriptionId;
835 }
836 gCallbacks->nanSubscriptionCanceledCallback(errorCode, subscriptionId);
837 }
838
839 /**
840 * Initializes the WiFi client upon an open request from CHRE and responds
841 * with the result.
842 *
843 * @param systemApi CHRE system function pointers.
844 * @param callbacks CHRE entry points.
845 *
846 * @return True if successful. False otherwise.
847 */
chppWifiClientOpen(const struct chrePalSystemApi * systemApi,const struct chrePalWifiCallbacks * callbacks)848 static bool chppWifiClientOpen(const struct chrePalSystemApi *systemApi,
849 const struct chrePalWifiCallbacks *callbacks) {
850 CHPP_DEBUG_NOT_NULL(systemApi);
851 CHPP_DEBUG_NOT_NULL(callbacks);
852
853 bool result = false;
854 gSystemApi = systemApi;
855 gCallbacks = callbacks;
856
857 CHPP_LOGD("WiFi client opening");
858 if (gWifiClientContext.client.appContext == NULL) {
859 CHPP_LOGE("WiFi client app is null");
860 } else {
861 if (chppWaitForDiscoveryComplete(gWifiClientContext.client.appContext,
862 CHPP_WIFI_DISCOVERY_TIMEOUT_MS)) {
863 result = chppClientSendOpenRequest(
864 &gWifiClientContext.client,
865 &gWifiClientContext.outReqStates[CHPP_WIFI_OPEN], CHPP_WIFI_OPEN,
866 /*blocking=*/true);
867 }
868
869 // Since CHPP_WIFI_DEFAULT_CAPABILITIES is mandatory, we can always
870 // pseudo-open and return true. Otherwise, these should have been gated.
871 chppClientPseudoOpen(&gWifiClientContext.client);
872 result = true;
873 }
874
875 return result;
876 }
877
878 /**
879 * Deinitializes the WiFi client.
880 */
chppWifiClientClose(void)881 static void chppWifiClientClose(void) {
882 // Remote
883 struct ChppAppHeader *request = chppAllocClientRequestCommand(
884 &gWifiClientContext.client, CHPP_WIFI_CLOSE);
885
886 if (request == NULL) {
887 CHPP_LOG_OOM();
888 } else if (chppClientSendTimestampedRequestAndWait(
889 &gWifiClientContext.client,
890 &gWifiClientContext.outReqStates[CHPP_WIFI_CLOSE], request,
891 sizeof(*request))) {
892 gWifiClientContext.client.openState = CHPP_OPEN_STATE_CLOSED;
893 gWifiClientContext.capabilities = CHRE_WIFI_CAPABILITIES_NONE;
894 gWifiClientContext.capabilitiesValid = false;
895 chppClientCloseOpenRequests(&gWifiClientContext.client, &kWifiClientConfig,
896 true /* clearOnly */);
897 }
898 }
899
900 /**
901 * Retrieves a set of flags indicating the WiFi features supported by the
902 * current implementation.
903 *
904 * @return Capabilities flags.
905 */
chppWifiClientGetCapabilities(void)906 static uint32_t chppWifiClientGetCapabilities(void) {
907 uint32_t capabilities = CHPP_WIFI_DEFAULT_CAPABILITIES;
908
909 if (gWifiClientContext.capabilitiesValid) {
910 // Result already cached
911 capabilities = gWifiClientContext.capabilities;
912
913 } else {
914 struct ChppAppHeader *request = chppAllocClientRequestCommand(
915 &gWifiClientContext.client, CHPP_WIFI_GET_CAPABILITIES);
916
917 if (request == NULL) {
918 CHPP_LOG_OOM();
919 } else {
920 if (chppClientSendTimestampedRequestAndWait(
921 &gWifiClientContext.client,
922 &gWifiClientContext.outReqStates[CHPP_WIFI_GET_CAPABILITIES],
923 request, sizeof(*request))) {
924 // Success. gWifiClientContext.capabilities is now populated
925 if (gWifiClientContext.capabilitiesValid) {
926 capabilities = gWifiClientContext.capabilities;
927 }
928 }
929 }
930 }
931
932 return capabilities;
933 }
934
935 /**
936 * Enables/disables receiving unsolicited scan results (scan monitoring).
937 *
938 * @param enable True to enable.
939 *
940 * @return True indicates the request was sent off to the service.
941 */
chppWifiClientConfigureScanMonitor(bool enable)942 static bool chppWifiClientConfigureScanMonitor(bool enable) {
943 bool result = false;
944
945 struct ChppWifiConfigureScanMonitorAsyncRequest *request =
946 chppAllocClientRequestFixed(
947 &gWifiClientContext.client,
948 struct ChppWifiConfigureScanMonitorAsyncRequest);
949
950 if (request == NULL) {
951 CHPP_LOG_OOM();
952 } else {
953 request->header.command = CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC;
954 request->enable = enable;
955
956 result = chppClientSendTimestampedRequestOrFail(
957 &gWifiClientContext.client,
958 &gWifiClientContext
959 .outReqStates[CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC],
960 request, sizeof(*request), CHPP_REQUEST_TIMEOUT_DEFAULT);
961 }
962
963 return result;
964 }
965
966 /**
967 * Request that the WiFi chipset perform a scan or deliver results from its
968 * cache.
969 *
970 * @param params See chreWifiRequestScanAsync().
971 *
972 * @return True indicates the request was sent off to the service.
973 */
chppWifiClientRequestScan(const struct chreWifiScanParams * params)974 static bool chppWifiClientRequestScan(const struct chreWifiScanParams *params) {
975 struct ChppWifiScanParamsWithHeader *request;
976 size_t requestLen;
977
978 bool result = chppWifiScanParamsFromChre(params, &request, &requestLen);
979
980 if (!result) {
981 CHPP_LOG_OOM();
982 } else {
983 request->header.handle = gWifiClientContext.client.handle;
984 request->header.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
985 request->header.transaction = gWifiClientContext.client.transaction++;
986 request->header.error = CHPP_APP_ERROR_NONE;
987 request->header.command = CHPP_WIFI_REQUEST_SCAN_ASYNC;
988
989 CHPP_STATIC_ASSERT(
990 CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS > CHPP_WIFI_SCAN_RESULT_TIMEOUT_NS,
991 "Chpp wifi scan timeout needs to be smaller than CHRE wifi scan "
992 "timeout");
993 result = chppClientSendTimestampedRequestOrFail(
994 &gWifiClientContext.client,
995 &gWifiClientContext.outReqStates[CHPP_WIFI_REQUEST_SCAN_ASYNC], request,
996 requestLen, CHPP_WIFI_SCAN_RESULT_TIMEOUT_NS);
997 }
998
999 return result;
1000 }
1001
1002 /**
1003 * Releases the memory held for the scan event callback.
1004 *
1005 * @param event Location event to be released.
1006 */
chppWifiClientReleaseScanEvent(struct chreWifiScanEvent * event)1007 static void chppWifiClientReleaseScanEvent(struct chreWifiScanEvent *event) {
1008 if (event->scannedFreqListLen > 0) {
1009 void *scannedFreqList = CHPP_CONST_CAST_POINTER(event->scannedFreqList);
1010 CHPP_FREE_AND_NULLIFY(scannedFreqList);
1011 }
1012
1013 if (event->resultCount > 0) {
1014 void *results = CHPP_CONST_CAST_POINTER(event->results);
1015 CHPP_FREE_AND_NULLIFY(results);
1016 }
1017
1018 CHPP_FREE_AND_NULLIFY(event);
1019 }
1020
1021 /**
1022 * Request that the WiFi chipset perform RTT ranging.
1023 *
1024 * @param params See chreWifiRequestRangingAsync().
1025 *
1026 * @return True indicates the request was sent off to the service.
1027 */
chppWifiClientRequestRanging(const struct chreWifiRangingParams * params)1028 static bool chppWifiClientRequestRanging(
1029 const struct chreWifiRangingParams *params) {
1030 struct ChppWifiRangingParamsWithHeader *request;
1031 size_t requestLen;
1032
1033 bool result = chppWifiRangingParamsFromChre(params, &request, &requestLen);
1034
1035 if (!result) {
1036 CHPP_LOG_OOM();
1037 } else {
1038 request->header.handle = gWifiClientContext.client.handle;
1039 request->header.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
1040 request->header.transaction = gWifiClientContext.client.transaction++;
1041 request->header.error = CHPP_APP_ERROR_NONE;
1042 request->header.command = CHPP_WIFI_REQUEST_RANGING_ASYNC;
1043
1044 result = chppClientSendTimestampedRequestOrFail(
1045 &gWifiClientContext.client,
1046 &gWifiClientContext.outReqStates[CHPP_WIFI_REQUEST_RANGING_ASYNC],
1047 request, requestLen, CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
1048 }
1049
1050 return result;
1051 }
1052
1053 /**
1054 * Releases the memory held for the RTT ranging event callback.
1055 *
1056 * @param event Location event to be released.
1057 */
chppWifiClientReleaseRangingEvent(struct chreWifiRangingEvent * event)1058 static void chppWifiClientReleaseRangingEvent(
1059 struct chreWifiRangingEvent *event) {
1060 if (event->resultCount > 0) {
1061 void *results = CHPP_CONST_CAST_POINTER(event->results);
1062 CHPP_FREE_AND_NULLIFY(results);
1063 }
1064
1065 CHPP_FREE_AND_NULLIFY(event);
1066 }
1067
1068 /**
1069 * Request that the WiFi chipset perform a NAN subscription.
1070 * @see chreWifiNanSubscribe for more information.
1071 *
1072 * @param config NAN service subscription configuration.
1073 * @return true if subscribe request was successful, false otherwise.
1074 */
chppWifiClientNanSubscribe(const struct chreWifiNanSubscribeConfig * config)1075 static bool chppWifiClientNanSubscribe(
1076 const struct chreWifiNanSubscribeConfig *config) {
1077 struct ChppWifiNanSubscribeConfigWithHeader *request;
1078 size_t requestLen;
1079
1080 bool result =
1081 chppWifiNanSubscribeConfigFromChre(config, &request, &requestLen);
1082
1083 if (!result) {
1084 CHPP_LOG_OOM();
1085 } else {
1086 request->header.handle = gWifiClientContext.client.handle;
1087 request->header.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
1088 request->header.transaction = gWifiClientContext.client.transaction++;
1089 request->header.error = CHPP_APP_ERROR_NONE;
1090 request->header.command = CHPP_WIFI_REQUEST_NAN_SUB;
1091
1092 result = chppClientSendTimestampedRequestOrFail(
1093 &gWifiClientContext.client,
1094 &gWifiClientContext.outReqStates[CHPP_WIFI_REQUEST_NAN_SUB], request,
1095 requestLen, CHRE_ASYNC_RESULT_TIMEOUT_NS);
1096 }
1097 return result;
1098 }
1099
1100 /**
1101 * Request the WiFi chipset to cancel a NAN subscription.
1102 * @param subscriptionId Identifier assigned by the NAN engine for a service
1103 * subscription.
1104 * @return true if cancelation request was successfully dispatched, false
1105 * otherwise.
1106 */
chppWifiClientNanSubscribeCancel(uint32_t subscriptionId)1107 static bool chppWifiClientNanSubscribeCancel(uint32_t subscriptionId) {
1108 bool result = false;
1109 struct ChppWifiNanSubscribeCancelRequest *request =
1110 chppAllocClientRequestFixed(&gWifiClientContext.client,
1111 struct ChppWifiNanSubscribeCancelRequest);
1112
1113 if (request == NULL) {
1114 CHPP_LOG_OOM();
1115 } else {
1116 request->header.handle = gWifiClientContext.client.handle;
1117 request->header.command = CHPP_WIFI_REQUEST_NAN_SUB_CANCEL;
1118 request->header.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
1119 request->header.transaction = gWifiClientContext.client.transaction++;
1120 request->header.error = CHPP_APP_ERROR_NONE;
1121 request->subscriptionId = subscriptionId;
1122
1123 result = chppClientSendTimestampedRequestAndWait(
1124 &gWifiClientContext.client,
1125 &gWifiClientContext.outReqStates[CHPP_WIFI_REQUEST_NAN_SUB_CANCEL],
1126 request, sizeof(*request));
1127 }
1128 return result;
1129 }
1130
1131 /**
1132 * Release the memory held for the NAN service discovery callback.
1133 *
1134 * @param event Discovery event to be freed.
1135 */
chppWifiClientNanReleaseDiscoveryEvent(struct chreWifiNanDiscoveryEvent * event)1136 static void chppWifiClientNanReleaseDiscoveryEvent(
1137 struct chreWifiNanDiscoveryEvent *event) {
1138 if (event != NULL) {
1139 if (event->serviceSpecificInfo != NULL) {
1140 void *info = CHPP_CONST_CAST_POINTER(event->serviceSpecificInfo);
1141 CHPP_FREE_AND_NULLIFY(info);
1142 }
1143 CHPP_FREE_AND_NULLIFY(event);
1144 }
1145 }
1146
1147 /**
1148 * Request that the WiFi chipset perform NAN ranging.
1149 *
1150 * @param params WiFi NAN ranging parameters.
1151 * @return true if the ranging request was successfully dispatched, false
1152 * otherwise.
1153 */
chppWifiClientNanRequestNanRanging(const struct chreWifiNanRangingParams * params)1154 static bool chppWifiClientNanRequestNanRanging(
1155 const struct chreWifiNanRangingParams *params) {
1156 struct ChppWifiNanRangingParamsWithHeader *request;
1157 size_t requestLen;
1158 bool result = chppWifiNanRangingParamsFromChre(params, &request, &requestLen);
1159
1160 if (!result) {
1161 CHPP_LOG_OOM();
1162 } else {
1163 request->header.handle = gWifiClientContext.client.handle;
1164 request->header.command = CHPP_WIFI_REQUEST_NAN_RANGING_ASYNC;
1165 request->header.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
1166 request->header.transaction = gWifiClientContext.client.transaction++;
1167 request->header.error = CHPP_APP_ERROR_NONE;
1168
1169 result = chppClientSendTimestampedRequestOrFail(
1170 &gWifiClientContext.client,
1171 &gWifiClientContext.outReqStates[CHPP_WIFI_REQUEST_NAN_RANGING_ASYNC],
1172 request, requestLen, CHRE_ASYNC_RESULT_TIMEOUT_NS);
1173 }
1174 return result;
1175 }
1176
chppWifiGetNanCapabilites(struct chreWifiNanCapabilities * capabilities)1177 static bool chppWifiGetNanCapabilites(
1178 struct chreWifiNanCapabilities *capabilities) {
1179 // Not implemented yet.
1180 UNUSED_VAR(capabilities);
1181 return false;
1182 }
1183
1184 /************************************************
1185 * Public Functions
1186 ***********************************************/
1187
chppRegisterWifiClient(struct ChppAppState * appContext)1188 void chppRegisterWifiClient(struct ChppAppState *appContext) {
1189 memset(&gWifiClientContext, 0, sizeof(gWifiClientContext));
1190 chppRegisterClient(appContext, (void *)&gWifiClientContext,
1191 &gWifiClientContext.client,
1192 gWifiClientContext.outReqStates, &kWifiClientConfig);
1193 }
1194
chppDeregisterWifiClient(struct ChppAppState * appContext)1195 void chppDeregisterWifiClient(struct ChppAppState *appContext) {
1196 // TODO
1197
1198 UNUSED_VAR(appContext);
1199 }
1200
getChppWifiClientState(void)1201 struct ChppEndpointState *getChppWifiClientState(void) {
1202 return &gWifiClientContext.client;
1203 }
1204
1205 #ifdef CHPP_CLIENT_ENABLED_WIFI
1206
1207 #ifdef CHPP_CLIENT_ENABLED_CHRE_WIFI
chrePalWifiGetApi(uint32_t requestedApiVersion)1208 const struct chrePalWifiApi *chrePalWifiGetApi(uint32_t requestedApiVersion) {
1209 #else
1210 const struct chrePalWifiApi *chppPalWifiGetApi(uint32_t requestedApiVersion) {
1211 #endif
1212
1213 static const struct chrePalWifiApi api = {
1214 .moduleVersion = CHPP_PAL_WIFI_API_VERSION,
1215 .open = chppWifiClientOpen,
1216 .close = chppWifiClientClose,
1217 .getCapabilities = chppWifiClientGetCapabilities,
1218 .configureScanMonitor = chppWifiClientConfigureScanMonitor,
1219 .requestScan = chppWifiClientRequestScan,
1220 .releaseScanEvent = chppWifiClientReleaseScanEvent,
1221 .requestRanging = chppWifiClientRequestRanging,
1222 .releaseRangingEvent = chppWifiClientReleaseRangingEvent,
1223 .nanSubscribe = chppWifiClientNanSubscribe,
1224 .nanSubscribeCancel = chppWifiClientNanSubscribeCancel,
1225 .releaseNanDiscoveryEvent = chppWifiClientNanReleaseDiscoveryEvent,
1226 .requestNanRanging = chppWifiClientNanRequestNanRanging,
1227 .getNanCapabilities = chppWifiGetNanCapabilites,
1228 };
1229
1230 CHPP_STATIC_ASSERT(
1231 CHRE_PAL_WIFI_API_CURRENT_VERSION == CHPP_PAL_WIFI_API_VERSION,
1232 "A newer CHRE PAL API version is available. Please update.");
1233
1234 if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(api.moduleVersion,
1235 requestedApiVersion)) {
1236 return NULL;
1237 } else {
1238 return &api;
1239 }
1240 }
1241
1242 #endif
1243