xref: /aosp_15_r20/system/chre/chpp/services/wifi.c (revision 84e339476a462649f82315436d70fd732297a399)
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 ChppEndpointState service;  // CHPP service state
77   const struct chrePalWifiApi *api;  // WiFi PAL API
78 
79   // Based on chre/pal/wifi.h and chrePalWifiApi
80   struct ChppIncomingRequestState open;             // Service init state
81   struct ChppIncomingRequestState close;            // Service deinit state
82   struct ChppIncomingRequestState getCapabilities;  // Get Capabilities state
83   struct ChppIncomingRequestState
84       configureScanMonitorAsync;  // Configure scan monitor state
85   struct ChppIncomingRequestState requestScanAsync;     // Request scan state
86   struct ChppIncomingRequestState requestRangingAsync;  // Request ranging state
87   struct ChppIncomingRequestState
88       requestNanSubscribe;  // Request Nan Subscription state
89   struct ChppIncomingRequestState
90       requestNanSubscribeCancel;  // Request Nan Subscription cancelation state
91   struct ChppIncomingRequestState
92       requestNanRangingAsync;  // Request NAN ranging state
93 };
94 
95 // Note: The CHRE PAL API only allows for one definition - see comment in WWAN
96 // service for details.
97 // Note: There is no notion of a cookie in the CHRE WiFi API so we need to use
98 // the global service state (gWifiServiceContext) directly in all callbacks.
99 struct ChppWifiServiceState gWifiServiceContext;
100 
101 /************************************************
102  *  Prototypes
103  ***********************************************/
104 
105 static enum ChppAppErrorCode chppWifiServiceOpen(
106     struct ChppWifiServiceState *wifiServiceContext,
107     struct ChppAppHeader *requestHeader);
108 static enum ChppAppErrorCode chppWifiServiceClose(
109     struct ChppWifiServiceState *wifiServiceContext,
110     struct ChppAppHeader *requestHeader);
111 static enum ChppAppErrorCode chppWifiServiceGetCapabilities(
112     struct ChppWifiServiceState *wifiServiceContext,
113     struct ChppAppHeader *requestHeader);
114 static enum ChppAppErrorCode chppWifiServiceConfigureScanMonitorAsync(
115     struct ChppWifiServiceState *wifiServiceContext,
116     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
117 static enum ChppAppErrorCode chppWifiServiceRequestScanAsync(
118     struct ChppWifiServiceState *wifiServiceContext,
119     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
120 static enum ChppAppErrorCode chppWifiServiceRequestRangingAsync(
121     struct ChppWifiServiceState *wifiServiceContext,
122     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
123 static enum ChppAppErrorCode chppWifiServiceRequestNanSubscribe(
124     struct ChppWifiServiceState *wifiServiceContext,
125     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
126 static enum ChppAppErrorCode chppWifiServiceRequestNanSubscribeCancel(
127     struct ChppWifiServiceState *wifiServiceContext,
128     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
129 static bool chppWifiServiceRequestNanRanging(
130     struct ChppWifiServiceState *wifiServiceContext,
131     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len);
132 
133 static void chppWifiServiceScanMonitorStatusChangeCallback(bool enabled,
134                                                            uint8_t errorCode);
135 static void chppWifiServiceScanResponseCallback(bool pending,
136                                                 uint8_t errorCode);
137 static void chppWifiServiceScanEventCallback(struct chreWifiScanEvent *event);
138 static void chppWifiServiceRangingEventCallback(
139     uint8_t errorCode, struct chreWifiRangingEvent *event);
140 static void chppWifiServiceNanIdentifierCallback(uint8_t errorCode,
141                                                  uint32_t subscriptionId);
142 static void chppWifiServiceNanDiscoveryCallback(
143     struct chreWifiNanDiscoveryEvent *event);
144 static void chppWifiServiceNanLostCallback(uint32_t subscriptionId,
145                                            uint32_t publisherId);
146 static void chppWifiServiceNanTerminatedCallback(uint32_t reason,
147                                                  uint32_t subscriptionId);
148 static void chppWifiServiceNanSubscriptionCanceledCallback(
149     uint8_t errorCode, uint32_t subscriptionId);
150 
151 /************************************************
152  *  Private Functions
153  ***********************************************/
154 
155 /**
156  * Dispatches a client request from the transport layer that is determined to be
157  * for the WiFi service. If the result of the dispatch is an error, this
158  * function responds to the client with the same error.
159  *
160  * This function is called from the app layer using its function pointer given
161  * during service registration.
162  *
163  * @param serviceContext Maintains status for each service instance.
164  * @param buf Input data. Cannot be null.
165  * @param len Length of input data in bytes.
166  *
167  * @return Indicates the result of this function call.
168  */
chppDispatchWifiRequest(void * serviceContext,uint8_t * buf,size_t len)169 static enum ChppAppErrorCode chppDispatchWifiRequest(void *serviceContext,
170                                                      uint8_t *buf, size_t len) {
171   struct ChppAppHeader *rxHeader = (struct ChppAppHeader *)buf;
172   buf += sizeof(struct ChppAppHeader);
173   len -= sizeof(struct ChppAppHeader);
174 
175   struct ChppWifiServiceState *wifiServiceContext =
176       (struct ChppWifiServiceState *)serviceContext;
177   struct ChppIncomingRequestState *inReqState = NULL;
178   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
179   bool dispatched = true;
180 
181   switch (rxHeader->command) {
182     case CHPP_WIFI_OPEN: {
183       inReqState = &wifiServiceContext->open;
184       chppTimestampIncomingRequest(inReqState, rxHeader);
185       error = chppWifiServiceOpen(wifiServiceContext, rxHeader);
186       break;
187     }
188 
189     case CHPP_WIFI_CLOSE: {
190       inReqState = &wifiServiceContext->close;
191       chppTimestampIncomingRequest(inReqState, rxHeader);
192       error = chppWifiServiceClose(wifiServiceContext, rxHeader);
193       break;
194     }
195 
196     case CHPP_WIFI_GET_CAPABILITIES: {
197       inReqState = &wifiServiceContext->getCapabilities;
198       chppTimestampIncomingRequest(inReqState, rxHeader);
199       error = chppWifiServiceGetCapabilities(wifiServiceContext, rxHeader);
200       break;
201     }
202 
203     case CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC: {
204       inReqState = &wifiServiceContext->configureScanMonitorAsync;
205       chppTimestampIncomingRequest(inReqState, rxHeader);
206       error = chppWifiServiceConfigureScanMonitorAsync(wifiServiceContext,
207                                                        rxHeader, buf, len);
208       break;
209     }
210 
211     case CHPP_WIFI_REQUEST_SCAN_ASYNC: {
212       inReqState = &wifiServiceContext->requestScanAsync;
213       chppTimestampIncomingRequest(inReqState, rxHeader);
214       error = chppWifiServiceRequestScanAsync(wifiServiceContext, rxHeader, buf,
215                                               len);
216       break;
217     }
218 
219     case CHPP_WIFI_REQUEST_RANGING_ASYNC: {
220       inReqState = &wifiServiceContext->requestRangingAsync;
221       chppTimestampIncomingRequest(inReqState, rxHeader);
222       error = chppWifiServiceRequestRangingAsync(wifiServiceContext, rxHeader,
223                                                  buf, len);
224       break;
225     }
226 
227     case CHPP_WIFI_REQUEST_NAN_SUB: {
228       inReqState = &wifiServiceContext->requestNanSubscribe;
229       chppTimestampIncomingRequest(inReqState, rxHeader);
230       error = chppWifiServiceRequestNanSubscribe(wifiServiceContext, rxHeader,
231                                                  buf, len);
232       break;
233     }
234 
235     case CHPP_WIFI_REQUEST_NAN_SUB_CANCEL: {
236       inReqState = &wifiServiceContext->requestNanSubscribeCancel;
237       chppTimestampIncomingRequest(inReqState, rxHeader);
238       error = chppWifiServiceRequestNanSubscribeCancel(wifiServiceContext,
239                                                        rxHeader, buf, len);
240       break;
241     };
242 
243     case CHPP_WIFI_REQUEST_NAN_RANGING_ASYNC: {
244       inReqState = &wifiServiceContext->requestNanRangingAsync;
245       chppTimestampIncomingRequest(inReqState, rxHeader);
246       error = chppWifiServiceRequestNanRanging(wifiServiceContext, rxHeader,
247                                                buf, len);
248       break;
249     }
250 
251     default: {
252       dispatched = false;
253       error = CHPP_APP_ERROR_INVALID_COMMAND;
254       break;
255     }
256   }
257 
258   if (dispatched == true && error != CHPP_APP_ERROR_NONE) {
259     // Request was dispatched but an error was returned. Close out
260     // chppTimestampIncomingRequest()
261     chppTimestampOutgoingResponse(inReqState);
262   }
263 
264   return error;
265 }
266 
267 /**
268  * Initializes the WiFi service upon an open request from the client and
269  * responds to the client with the result.
270  *
271  * @param serviceContext Maintains status for each service instance.
272  * @param requestHeader App layer header of the request.
273  *
274  * @return Indicates the result of this function call.
275  */
chppWifiServiceOpen(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader)276 static enum ChppAppErrorCode chppWifiServiceOpen(
277     struct ChppWifiServiceState *wifiServiceContext,
278     struct ChppAppHeader *requestHeader) {
279   static const struct chrePalWifiCallbacks palCallbacks = {
280       .scanMonitorStatusChangeCallback =
281           chppWifiServiceScanMonitorStatusChangeCallback,
282       .scanResponseCallback = chppWifiServiceScanResponseCallback,
283       .scanEventCallback = chppWifiServiceScanEventCallback,
284       .rangingEventCallback = chppWifiServiceRangingEventCallback,
285       .nanServiceIdentifierCallback = chppWifiServiceNanIdentifierCallback,
286       .nanServiceDiscoveryCallback = chppWifiServiceNanDiscoveryCallback,
287       .nanServiceLostCallback = chppWifiServiceNanLostCallback,
288       .nanServiceTerminatedCallback = chppWifiServiceNanTerminatedCallback,
289       .nanSubscriptionCanceledCallback =
290           chppWifiServiceNanSubscriptionCanceledCallback,
291   };
292 
293   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
294 
295   if (wifiServiceContext->service.openState == CHPP_OPEN_STATE_OPENED) {
296     CHPP_DEBUG_ASSERT_LOG(false, "WiFi service already open");
297     error = CHPP_APP_ERROR_INVALID_COMMAND;
298 
299   } else if (!wifiServiceContext->api->open(
300                  wifiServiceContext->service.appContext->systemApi,
301                  &palCallbacks)) {
302     CHPP_DEBUG_ASSERT_LOG(false, "WiFi PAL open failed");
303     error = CHPP_APP_ERROR_BEYOND_CHPP;
304 
305   } else {
306     CHPP_LOGD("WiFi service opened");
307     wifiServiceContext->service.openState = CHPP_OPEN_STATE_OPENED;
308 
309     struct ChppAppHeader *response =
310         chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
311     size_t responseLen = sizeof(*response);
312 
313     if (response == NULL) {
314       CHPP_LOG_OOM();
315       error = CHPP_APP_ERROR_OOM;
316     } else {
317       chppSendTimestampedResponseOrFail(wifiServiceContext->service.appContext,
318                                         &wifiServiceContext->open, response,
319                                         responseLen);
320     }
321   }
322 
323   return error;
324 }
325 
326 /**
327  * Deinitializes the WiFi service.
328  *
329  * @param serviceContext Maintains status for each service instance.
330  * @param requestHeader App layer header of the request.
331  *
332  * @return Indicates the result of this function call.
333  */
chppWifiServiceClose(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader)334 static enum ChppAppErrorCode chppWifiServiceClose(
335     struct ChppWifiServiceState *wifiServiceContext,
336     struct ChppAppHeader *requestHeader) {
337   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
338 
339   wifiServiceContext->api->close();
340   wifiServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
341 
342   CHPP_LOGD("WiFi service closed");
343 
344   struct ChppAppHeader *response =
345       chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
346   size_t responseLen = sizeof(*response);
347 
348   if (response == NULL) {
349     CHPP_LOG_OOM();
350     error = CHPP_APP_ERROR_OOM;
351   } else {
352     chppSendTimestampedResponseOrFail(wifiServiceContext->service.appContext,
353                                       &wifiServiceContext->close, response,
354                                       responseLen);
355   }
356   return error;
357 }
358 
359 /**
360  * Notifies the service of an incoming reset.
361  *
362  * @param serviceContext Maintains status for each service instance.
363  */
chppWifiServiceNotifyReset(void * serviceContext)364 static void chppWifiServiceNotifyReset(void *serviceContext) {
365   struct ChppWifiServiceState *wifiServiceContext =
366       (struct ChppWifiServiceState *)serviceContext;
367 
368   if (wifiServiceContext->service.openState != CHPP_OPEN_STATE_OPENED) {
369     CHPP_LOGW("WiFi service reset but wasn't open");
370   } else {
371     CHPP_LOGD("WiFi service reset. Closing");
372     wifiServiceContext->service.openState = CHPP_OPEN_STATE_CLOSED;
373     wifiServiceContext->api->close();
374   }
375 }
376 
377 /**
378  * Retrieves a set of flags indicating the WiFi features supported by the
379  * current implementation.
380  *
381  * @param serviceContext Maintains status for each service instance.
382  * @param requestHeader App layer header of the request.
383  *
384  * @return Indicates the result of this function call.
385  */
chppWifiServiceGetCapabilities(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader)386 static enum ChppAppErrorCode chppWifiServiceGetCapabilities(
387     struct ChppWifiServiceState *wifiServiceContext,
388     struct ChppAppHeader *requestHeader) {
389   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
390 
391   struct ChppWifiGetCapabilitiesResponse *response = chppAllocResponseFixed(
392       requestHeader, struct ChppWifiGetCapabilitiesResponse);
393   size_t responseLen = sizeof(*response);
394 
395   if (response == NULL) {
396     CHPP_LOG_OOM();
397     error = CHPP_APP_ERROR_OOM;
398   } else {
399     response->params.capabilities = wifiServiceContext->api->getCapabilities();
400 
401     CHPP_LOGD("chppWifiServiceGetCapabilities returning 0x%" PRIx32
402               ", %" PRIuSIZE " bytes",
403               response->params.capabilities, responseLen);
404     chppSendTimestampedResponseOrFail(wifiServiceContext->service.appContext,
405                                       &wifiServiceContext->getCapabilities,
406                                       response, responseLen);
407   }
408 
409   return error;
410 }
411 
412 /**
413  * Configures whether scanEventCallback receives unsolicited scan results, i.e.
414  * the results of scans not performed at the request of CHRE.
415  *
416  * This function returns an error code synchronously.
417  * A subsequent call to chppWifiServiceScanMonitorStatusChangeCallback() will be
418  * used to communicate the result of this request (as a service response).
419  *
420  * @param serviceContext Maintains status for each service instance.
421  * @param requestHeader App layer header of the request.
422  * @param buf Input data. Cannot be null.
423  * @param len Length of input data in bytes.
424  *
425  * @return Indicates the result of this function call.
426  */
chppWifiServiceConfigureScanMonitorAsync(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)427 static enum ChppAppErrorCode chppWifiServiceConfigureScanMonitorAsync(
428     struct ChppWifiServiceState *wifiServiceContext,
429     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
430   UNUSED_VAR(requestHeader);
431   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
432 
433   if (len < sizeof(bool)) {
434     error = CHPP_APP_ERROR_INVALID_ARG;
435   } else {
436     bool *enable = (bool *)buf;
437     if (!wifiServiceContext->api->configureScanMonitor(*enable)) {
438       error = CHPP_APP_ERROR_UNSPECIFIED;
439     }
440   }
441 
442   return error;
443 }
444 
445 /**
446  * Request that the WiFi chipset perform a scan, or deliver results from its
447  * cache if the parameters allow for it.
448  *
449  * This function returns an error code synchronously.
450  * A subsequent call to chppWifiServiceScanResponseCallback() will be used to
451  * communicate the result of this request (as a service response).
452  * A subsequent call to chppWifiServiceScanEventCallback() will be used to
453  * communicate the scan results (as a service notification).
454  *
455  * @param serviceContext Maintains status for each service instance.
456  * @param requestHeader App layer header of the request.
457  * @param buf Input data. Cannot be null.
458  * @param len Length of input data in bytes.
459  *
460  * @return Indicates the result of this function call.
461  */
chppWifiServiceRequestScanAsync(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)462 static enum ChppAppErrorCode chppWifiServiceRequestScanAsync(
463     struct ChppWifiServiceState *wifiServiceContext,
464     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
465   UNUSED_VAR(requestHeader);
466   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
467 
468   struct chreWifiScanParams *chre =
469       chppWifiScanParamsToChre((struct ChppWifiScanParams *)buf, len);
470 
471   if (chre == NULL) {
472     CHPP_LOGE(
473         "WifiServiceRequestScanAsync CHPP -> CHRE conversion failed. Input "
474         "len=%" PRIuSIZE,
475         len);
476     error = CHPP_APP_ERROR_INVALID_ARG;
477 
478   } else {
479     if (!wifiServiceContext->api->requestScan(chre)) {
480       error = CHPP_APP_ERROR_UNSPECIFIED;
481     }
482 
483     if (chre->frequencyListLen > 0) {
484       void *frequencyList = CHPP_CONST_CAST_POINTER(chre->frequencyList);
485       CHPP_FREE_AND_NULLIFY(frequencyList);
486     }
487     if (chre->ssidListLen > 0) {
488       void *ssidList = CHPP_CONST_CAST_POINTER(chre->ssidList);
489       CHPP_FREE_AND_NULLIFY(ssidList);
490     }
491     CHPP_FREE_AND_NULLIFY(chre);
492   }
493 
494   return error;
495 }
496 
497 /**
498  * Request that the WiFi chipset perform RTT ranging against a set of access
499  * points specified in params.
500  *
501  * This function returns an error code synchronously.
502  * A subsequent call to chppWifiServiceRangingEventCallback() will be used to
503  * communicate the ranging results (as a service notification).
504  *
505  * @param serviceContext Maintains status for each service instance.
506  * @param requestHeader App layer header of the request.
507  * @param buf Input data. Cannot be null.
508  * @param len Length of input data in bytes.
509  *
510  * @return Indicates the result of this function call.
511  */
chppWifiServiceRequestRangingAsync(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)512 static enum ChppAppErrorCode chppWifiServiceRequestRangingAsync(
513     struct ChppWifiServiceState *wifiServiceContext,
514     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
515   UNUSED_VAR(requestHeader);
516   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
517 
518   struct chreWifiRangingParams *chre =
519       chppWifiRangingParamsToChre((struct ChppWifiRangingParams *)buf, len);
520 
521   if (chre == NULL) {
522     CHPP_LOGE(
523         "WifiServiceRequestRangingAsync CHPP -> CHRE conversion failed. Input "
524         "len=%" PRIuSIZE,
525         len);
526     error = CHPP_APP_ERROR_INVALID_ARG;
527 
528   } else {
529     if (!wifiServiceContext->api->requestRanging(chre)) {
530       error = CHPP_APP_ERROR_UNSPECIFIED;
531 
532     } else {
533       struct ChppAppHeader *response =
534           chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
535       size_t responseLen = sizeof(*response);
536 
537       if (response == NULL) {
538         CHPP_LOG_OOM();
539         error = CHPP_APP_ERROR_OOM;
540       } else {
541         chppSendTimestampedResponseOrFail(
542             wifiServiceContext->service.appContext,
543             &wifiServiceContext->requestRangingAsync, response, responseLen);
544       }
545     }
546 
547     if (chre->targetListLen > 0) {
548       void *targetList = CHPP_CONST_CAST_POINTER(chre->targetList);
549       CHPP_FREE_AND_NULLIFY(targetList);
550     }
551     CHPP_FREE_AND_NULLIFY(chre);
552   }
553 
554   return error;
555 }
556 
chppWifiServiceRequestNanSubscribe(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)557 static enum ChppAppErrorCode chppWifiServiceRequestNanSubscribe(
558     struct ChppWifiServiceState *wifiServiceContext,
559     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
560   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
561 
562   struct chreWifiNanSubscribeConfig *chreConfig =
563       chppWifiNanSubscribeConfigToChre((struct ChppWifiNanSubscribeConfig *)buf,
564                                        len);
565   if (chreConfig == NULL) {
566     CHPP_LOGE(
567         "WifiServiceNanSubscribeConfig CHPP -> CHRE conversion failed."
568         "Input len: %" PRIuSIZE,
569         len);
570     error = CHPP_APP_ERROR_INVALID_ARG;
571   } else {
572     if (!wifiServiceContext->api->nanSubscribe(chreConfig)) {
573       error = CHPP_APP_ERROR_UNSPECIFIED;
574 
575     } else {
576       struct ChppAppHeader *response =
577           chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
578       size_t responseLen = sizeof(*response);
579 
580       if (response == NULL) {
581         CHPP_LOG_OOM();
582         error = CHPP_APP_ERROR_OOM;
583       } else {
584         chppSendTimestampedResponseOrFail(
585             wifiServiceContext->service.appContext,
586             &wifiServiceContext->requestNanSubscribe, response, responseLen);
587       }
588     }
589   }
590   return error;
591 }
592 
chppWifiServiceRequestNanSubscribeCancel(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)593 static enum ChppAppErrorCode chppWifiServiceRequestNanSubscribeCancel(
594     struct ChppWifiServiceState *wifiServiceContext,
595     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
596   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
597 
598   if (len < sizeof(struct ChppWifiNanSubscribeCancelRequest)) {
599     CHPP_LOGE(
600         "WifiServiceRequestNanSubscribecancel invalid input len = %" PRIuSIZE,
601         len);
602     error = CHPP_APP_ERROR_INVALID_ARG;
603   } else {
604     struct ChppWifiNanSubscribeCancelRequest *chppRequest =
605         (struct ChppWifiNanSubscribeCancelRequest *)buf;
606     uint32_t subscriptionId = chppRequest->subscriptionId;
607     if (!wifiServiceContext->api->nanSubscribeCancel(subscriptionId)) {
608       error = CHPP_APP_ERROR_UNSPECIFIED;
609 
610     } else {
611       struct ChppAppHeader *response =
612           chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
613       size_t responseLen = sizeof(*response);
614 
615       if (response == NULL) {
616         CHPP_LOG_OOM();
617         error = CHPP_APP_ERROR_OOM;
618       } else {
619         chppSendTimestampedResponseOrFail(
620             wifiServiceContext->service.appContext,
621             &wifiServiceContext->requestNanSubscribeCancel, response,
622             responseLen);
623       }
624     }
625   }
626   return error;
627 }
628 
chppWifiServiceRequestNanRanging(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)629 static bool chppWifiServiceRequestNanRanging(
630     struct ChppWifiServiceState *wifiServiceContext,
631     struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
632   enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
633 
634   struct chreWifiNanRangingParams *chreParams = chppWifiNanRangingParamsToChre(
635       (struct ChppWifiNanRangingParams *)buf, len);
636   if (chreParams == NULL) {
637     CHPP_LOGE(
638         "WifiServiceRequestNanRanging CHPP -> CHRE conversion failed. "
639         "Input len: %" PRIuSIZE,
640         len);
641     error = CHPP_APP_ERROR_INVALID_ARG;
642 
643   } else {
644     if (!wifiServiceContext->api->requestNanRanging(chreParams)) {
645       error = CHPP_APP_ERROR_UNSPECIFIED;
646 
647     } else {
648       struct ChppAppHeader *response =
649           chppAllocResponseFixed(requestHeader, struct ChppAppHeader);
650       size_t responseLen = sizeof(*response);
651 
652       if (response == NULL) {
653         CHPP_LOG_OOM();
654         error = CHPP_APP_ERROR_OOM;
655       } else {
656         chppSendTimestampedResponseOrFail(
657             wifiServiceContext->service.appContext,
658             &wifiServiceContext->requestNanRangingAsync, response, responseLen);
659       }
660     }
661   }
662   return error;
663 }
664 
665 /**
666  * PAL callback with the result of changes to the scan monitor registration
667  * status requested via configureScanMonitor.
668  *
669  * @param enabled true if the scan monitor is currently active
670  * @param errorCode An error code from enum chreError
671  */
chppWifiServiceScanMonitorStatusChangeCallback(bool enabled,uint8_t errorCode)672 static void chppWifiServiceScanMonitorStatusChangeCallback(bool enabled,
673                                                            uint8_t errorCode) {
674   // Recreate request header
675   struct ChppAppHeader requestHeader = {
676       .handle = gWifiServiceContext.service.handle,
677       .transaction = gWifiServiceContext.configureScanMonitorAsync.transaction,
678       .command = CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC,
679   };
680 
681   struct ChppWifiConfigureScanMonitorAsyncResponse *response =
682       chppAllocResponseFixed(&requestHeader,
683                              struct ChppWifiConfigureScanMonitorAsyncResponse);
684   size_t responseLen = sizeof(*response);
685 
686   if (response == NULL) {
687     CHPP_LOG_OOM();
688     CHPP_ASSERT(false);
689 
690   } else {
691     response->params.enabled = enabled;
692     response->params.errorCode = errorCode;
693 
694     chppSendTimestampedResponseOrFail(
695         gWifiServiceContext.service.appContext,
696         &gWifiServiceContext.configureScanMonitorAsync, response, responseLen);
697   }
698 }
699 
700 /**
701  * PAL callback with the result of a requestScan.
702  *
703  * @param pending true if the request was successful.
704  * @param errorCode An error code from enum chreError.
705  */
chppWifiServiceScanResponseCallback(bool pending,uint8_t errorCode)706 static void chppWifiServiceScanResponseCallback(bool pending,
707                                                 uint8_t errorCode) {
708   // Recreate request header
709   struct ChppAppHeader requestHeader = {
710       .handle = gWifiServiceContext.service.handle,
711       .transaction = gWifiServiceContext.requestScanAsync.transaction,
712       .command = CHPP_WIFI_REQUEST_SCAN_ASYNC,
713   };
714 
715   struct ChppWifiRequestScanResponse *response = chppAllocResponseFixed(
716       &requestHeader, struct ChppWifiRequestScanResponse);
717   size_t responseLen = sizeof(*response);
718 
719   if (response == NULL) {
720     CHPP_LOG_OOM();
721     CHPP_ASSERT(false);
722 
723   } else {
724     response->params.pending = pending;
725     response->params.errorCode = errorCode;
726 
727     chppSendTimestampedResponseOrFail(gWifiServiceContext.service.appContext,
728                                       &gWifiServiceContext.requestScanAsync,
729                                       response, responseLen);
730   }
731 }
732 
733 /**
734  * PAL callback with WiFi scan results.
735  *
736  * @param event Scan result data.
737  */
chppWifiServiceScanEventCallback(struct chreWifiScanEvent * event)738 static void chppWifiServiceScanEventCallback(struct chreWifiScanEvent *event) {
739   // Craft response per parser script
740   struct ChppWifiScanEventWithHeader *notification = NULL;
741   size_t notificationLen = 0;
742 
743   CHPP_DEBUG_ASSERT(chppCheckWifiScanEventNotification(event));
744 
745   if (!chppWifiScanEventFromChre(event, &notification, &notificationLen)) {
746     CHPP_LOGE("ScanEvent conversion failed (OOM?). ID=%" PRIu8,
747               gWifiServiceContext.requestScanAsync.transaction);
748 
749     notification = chppMalloc(sizeof(struct ChppAppHeader));
750     if (notification == NULL) {
751       CHPP_LOG_OOM();
752     } else {
753       notificationLen = sizeof(struct ChppAppHeader);
754     }
755   }
756 
757   if (notification != NULL) {
758     notification->header.handle = gWifiServiceContext.service.handle;
759     notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
760     notification->header.transaction =
761         gWifiServiceContext.requestScanAsync.transaction;
762     notification->header.error =
763         (notificationLen > sizeof(struct ChppAppHeader))
764             ? CHPP_APP_ERROR_NONE
765             : CHPP_APP_ERROR_CONVERSION_FAILED;
766     notification->header.command = CHPP_WIFI_REQUEST_SCAN_ASYNC;
767 
768     chppEnqueueTxDatagramOrFail(
769         gWifiServiceContext.service.appContext->transportContext, notification,
770         notificationLen);
771   }
772 
773   gWifiServiceContext.api->releaseScanEvent(event);
774 }
775 
776 /**
777  * PAL callback with RTT ranging results from the WiFi module.
778  *
779  * @param errorCode An error code from enum chreError.
780  * @param event Ranging data.
781  */
chppWifiServiceRangingEventCallback(uint8_t errorCode,struct chreWifiRangingEvent * event)782 static void chppWifiServiceRangingEventCallback(
783     uint8_t errorCode, struct chreWifiRangingEvent *event) {
784   struct ChppWifiRangingEventWithHeader *notification = NULL;
785   size_t notificationLen = 0;
786 
787   if (!chppWifiRangingEventFromChre(event, &notification, &notificationLen)) {
788     CHPP_LOGE("RangingEvent conversion failed (OOM?) ID=%" PRIu8,
789               gWifiServiceContext.requestRangingAsync.transaction);
790 
791     notification = chppMalloc(sizeof(struct ChppAppHeader));
792     if (notification == NULL) {
793       CHPP_LOG_OOM();
794     } else {
795       notificationLen = sizeof(struct ChppAppHeader);
796     }
797   }
798 
799   if (notification != NULL) {
800     uint16_t command = CHPP_WIFI_REQUEST_RANGING_ASYNC;
801 
802     // Per CHRE's API contract, only one kind of ranging request can be pending
803     // at a time - use the higher of the two for the notification.
804     uint8_t transaction =
805         MAX(gWifiServiceContext.requestRangingAsync.transaction,
806             gWifiServiceContext.requestNanRangingAsync.transaction);
807     notification->header.handle = gWifiServiceContext.service.handle;
808     notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
809     notification->header.transaction = transaction;
810     notification->header.command = command;
811     notification->header.error =
812         (notificationLen > sizeof(struct ChppAppHeader))
813             ? CHPP_APP_ERROR_NONE
814             : CHPP_APP_ERROR_CONVERSION_FAILED;
815 
816     if (errorCode != CHRE_ERROR_NONE) {
817       notification->header.error = CHPP_APP_ERROR_BEYOND_CHPP;
818       notificationLen = MIN(notificationLen, sizeof(struct ChppAppHeader));
819     }
820 
821     chppEnqueueTxDatagramOrFail(
822         gWifiServiceContext.service.appContext->transportContext, notification,
823         notificationLen);
824   }
825 
826   gWifiServiceContext.api->releaseRangingEvent(event);
827 }
828 
829 /**
830  * PAL callback with NAN service subscription identifier information.
831  *
832  * @param errorCode Error code indicating if a NAN subscription failed. The
833  *        subscriptionId field is only valid if the error code is
834  *        CHRE_ERROR_NONE.
835  * @param subscriptionId The ID assigned to the service subscription request.
836  *        This value is only valid if the error code is CHRE_ERROR_NONE.
837  */
chppWifiServiceNanIdentifierCallback(uint8_t errorCode,uint32_t subscriptionId)838 static void chppWifiServiceNanIdentifierCallback(uint8_t errorCode,
839                                                  uint32_t subscriptionId) {
840   size_t idLen = sizeof(struct ChppWifiNanServiceIdentifier);
841   struct ChppWifiNanServiceIdentifier *id = chppMalloc(idLen);
842   if (id == NULL) {
843     CHPP_LOG_OOM();
844   } else {
845     id->header.command = CHPP_WIFI_REQUEST_NAN_SUB;
846     id->header.handle = gWifiServiceContext.service.handle;
847     id->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
848     id->header.error = CHPP_APP_ERROR_NONE;
849     id->header.transaction =
850         gWifiServiceContext.requestNanSubscribe.transaction;
851     id->errorCode = errorCode;
852     id->subscriptionId = subscriptionId;
853 
854     chppEnqueueTxDatagramOrFail(
855         gWifiServiceContext.service.appContext->transportContext, id, idLen);
856   }
857 }
858 
859 /**
860  * PAL callback with NAN service discovery information.
861  *
862  * @param event Information about a discovered publishing service.
863  */
chppWifiServiceNanDiscoveryCallback(struct chreWifiNanDiscoveryEvent * event)864 static void chppWifiServiceNanDiscoveryCallback(
865     struct chreWifiNanDiscoveryEvent *event) {
866   struct ChppWifiNanDiscoveryEventWithHeader *notif = NULL;
867   size_t notifLen = 0;
868 
869   if (!chppWifiNanDiscoveryEventFromChre(event, &notif, &notifLen)) {
870     CHPP_LOGE("Discovery event conversion failed");
871     notif = chppMalloc(sizeof(struct ChppAppHeader));
872     if (notif == NULL) {
873       CHPP_LOG_OOM();
874     } else {
875       notifLen = sizeof(struct ChppAppHeader);
876     }
877   }
878 
879   if (notif != NULL) {
880     notif->header.handle = gWifiServiceContext.service.handle;
881     notif->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
882     notif->header.error = (notifLen > sizeof(struct ChppAppHeader))
883                               ? CHPP_APP_ERROR_NONE
884                               : CHPP_APP_ERROR_CONVERSION_FAILED;
885     notif->header.command = CHPP_WIFI_NOTIFICATION_NAN_SERVICE_DISCOVERY;
886 
887     chppEnqueueTxDatagramOrFail(
888         gWifiServiceContext.service.appContext->transportContext, notif,
889         notifLen);
890   }
891 
892   if (event != NULL) {
893     gWifiServiceContext.api->releaseNanDiscoveryEvent(event);
894   }
895 }
896 
897 /**
898  * PAL callback invoked when a publishing NAN service goes away.
899  *
900  * @param subscriptionId ID of the subscribing service.
901  * @param publisherId ID of the publishing service that has gone away.
902  */
chppWifiServiceNanLostCallback(uint32_t subscriptionId,uint32_t publisherId)903 static void chppWifiServiceNanLostCallback(uint32_t subscriptionId,
904                                            uint32_t publisherId) {
905   struct chreWifiNanSessionLostEvent chreEvent = {
906       .id = subscriptionId,
907       .peerId = publisherId,
908   };
909   struct ChppWifiNanSessionLostEventWithHeader *notif = NULL;
910   size_t notifLen = 0;
911 
912   if (!chppWifiNanSessionLostEventFromChre(&chreEvent, &notif, &notifLen)) {
913     CHPP_LOGE("Session lost event conversion failed");
914     notif = chppMalloc(sizeof(struct ChppAppHeader));
915     if (notif == NULL) {
916       CHPP_LOG_OOM();
917     } else {
918       notifLen = sizeof(struct ChppAppHeader);
919     }
920   }
921 
922   if (notif != NULL) {
923     notif->header.handle = gWifiServiceContext.service.handle;
924     notif->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
925     notif->header.error = (notifLen > sizeof(struct ChppAppHeader))
926                               ? CHPP_APP_ERROR_NONE
927                               : CHPP_APP_ERROR_CONVERSION_FAILED;
928     notif->header.command = CHPP_WIFI_NOTIFICATION_NAN_SERVICE_LOST;
929 
930     chppEnqueueTxDatagramOrFail(
931         gWifiServiceContext.service.appContext->transportContext, notif,
932         notifLen);
933   }
934 }
935 
936 /**
937  * PAL callback invoked when a NAN service subscription is terminated.
938  *
939  * @param reason Error code indicating the reason for the termination.
940  * @param subscriptionId The subscription ID of the terminated NAN service.
941  */
chppWifiServiceNanTerminatedCallback(uint32_t reason,uint32_t subscriptionId)942 static void chppWifiServiceNanTerminatedCallback(uint32_t reason,
943                                                  uint32_t subscriptionId) {
944   uint8_t chreReason = (uint8_t)reason;
945   struct chreWifiNanSessionTerminatedEvent chreEvent = {
946       .id = subscriptionId,
947       .reason = chreReason,
948   };
949   struct ChppWifiNanSessionTerminatedEventWithHeader *notif = NULL;
950   size_t notifLen = 0;
951 
952   if (!chppWifiNanSessionTerminatedEventFromChre(&chreEvent, &notif,
953                                                  &notifLen)) {
954     CHPP_LOGE("Session terminated event conversion failed");
955     notif = chppMalloc(sizeof(struct ChppAppHeader));
956     if (notif == NULL) {
957       CHPP_LOG_OOM();
958     } else {
959       notifLen = sizeof(struct ChppAppHeader);
960     }
961   }
962 
963   if (notif != NULL) {
964     notif->header.handle = gWifiServiceContext.service.handle;
965     notif->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
966     notif->header.error = (notifLen > sizeof(struct ChppAppHeader))
967                               ? CHPP_APP_ERROR_NONE
968                               : CHPP_APP_ERROR_CONVERSION_FAILED;
969     notif->header.command = CHPP_WIFI_NOTIFICATION_NAN_SERVICE_TERMINATED;
970 
971     chppEnqueueTxDatagramOrFail(
972         gWifiServiceContext.service.appContext->transportContext, notif,
973         notifLen);
974   }
975 }
976 
977 /**
978  * PAL callback invoked when a NAN service subscription is canceled.
979  *
980  * @param errorCode A value in @ref chreError indicating the result of the
981  *        cancelation, with CHRE_ERROR_NONE indicating success.
982  * @param subscriptionId The subscription ID of the canceled NAN service.
983  */
chppWifiServiceNanSubscriptionCanceledCallback(uint8_t errorCode,uint32_t subscriptionId)984 static void chppWifiServiceNanSubscriptionCanceledCallback(
985     uint8_t errorCode, uint32_t subscriptionId) {
986   size_t responseLen = sizeof(struct ChppWifiNanSubscriptionCanceledResponse);
987   struct ChppWifiNanSubscriptionCanceledResponse *response =
988       chppMalloc(responseLen);
989   if (response == NULL) {
990     CHPP_LOG_OOM();
991   } else {
992     response->header.command = CHPP_WIFI_REQUEST_NAN_SUB_CANCEL;
993     response->header.handle = gWifiServiceContext.service.handle;
994     response->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
995     response->header.error = CHPP_APP_ERROR_NONE;
996     response->header.transaction =
997         gWifiServiceContext.requestNanSubscribeCancel.transaction;
998     response->errorCode = errorCode;
999     response->subscriptionId = subscriptionId;
1000 
1001     chppEnqueueTxDatagramOrFail(
1002         gWifiServiceContext.service.appContext->transportContext, response,
1003         responseLen);
1004   }
1005 }
1006 
1007 /************************************************
1008  *  Public Functions
1009  ***********************************************/
1010 
chppRegisterWifiService(struct ChppAppState * appContext)1011 void chppRegisterWifiService(struct ChppAppState *appContext) {
1012   gWifiServiceContext.api = chrePalWifiGetApi(CHRE_PAL_WIFI_API_V1_2);
1013 
1014   chppCheckWifiScanEventNotificationReset();
1015 
1016   if (gWifiServiceContext.api == NULL) {
1017     CHPP_DEBUG_ASSERT_LOG(false,
1018                           "WiFi PAL API incompatible. Cannot register service");
1019 
1020   } else {
1021     chppRegisterService(appContext, (void *)&gWifiServiceContext,
1022                         &gWifiServiceContext.service, NULL /*outReqStates*/,
1023                         &kWifiServiceConfig);
1024     CHPP_DEBUG_ASSERT(gWifiServiceContext.service.handle);
1025   }
1026 }
1027 
chppDeregisterWifiService(struct ChppAppState * appContext)1028 void chppDeregisterWifiService(struct ChppAppState *appContext) {
1029   // TODO
1030 
1031   UNUSED_VAR(appContext);
1032 }
1033