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, ¬ification, ¬ificationLen)) {
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, ¬ification, ¬ificationLen)) {
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, ¬if, ¬ifLen)) {
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, ¬if, ¬ifLen)) {
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, ¬if,
953 ¬ifLen)) {
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