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