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, &notification, &notificationLen)) {
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, &notification, &notificationLen)) {
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