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