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