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 struct ChppRequestResponseState
88 requestNanSubscribe; // Request Nan Subscription state
89 struct ChppRequestResponseState
90 requestNanSubscribeCancel; // Request Nan Subscription cancelation state
91 struct ChppRequestResponseState
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 ChppRequestResponseState *rRState = NULL;
178 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
179 bool dispatched = true;
180
181 switch (rxHeader->command) {
182 case CHPP_WIFI_OPEN: {
183 rRState = &wifiServiceContext->open;
184 chppServiceTimestampRequest(rRState, rxHeader);
185 error = chppWifiServiceOpen(wifiServiceContext, rxHeader);
186 break;
187 }
188
189 case CHPP_WIFI_CLOSE: {
190 rRState = &wifiServiceContext->close;
191 chppServiceTimestampRequest(rRState, rxHeader);
192 error = chppWifiServiceClose(wifiServiceContext, rxHeader);
193 break;
194 }
195
196 case CHPP_WIFI_GET_CAPABILITIES: {
197 rRState = &wifiServiceContext->getCapabilities;
198 chppServiceTimestampRequest(rRState, rxHeader);
199 error = chppWifiServiceGetCapabilities(wifiServiceContext, rxHeader);
200 break;
201 }
202
203 case CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC: {
204 rRState = &wifiServiceContext->configureScanMonitorAsync;
205 chppServiceTimestampRequest(rRState, rxHeader);
206 error = chppWifiServiceConfigureScanMonitorAsync(wifiServiceContext,
207 rxHeader, buf, len);
208 break;
209 }
210
211 case CHPP_WIFI_REQUEST_SCAN_ASYNC: {
212 rRState = &wifiServiceContext->requestScanAsync;
213 chppServiceTimestampRequest(rRState, rxHeader);
214 error = chppWifiServiceRequestScanAsync(wifiServiceContext, rxHeader, buf,
215 len);
216 break;
217 }
218
219 case CHPP_WIFI_REQUEST_RANGING_ASYNC: {
220 rRState = &wifiServiceContext->requestRangingAsync;
221 chppServiceTimestampRequest(rRState, rxHeader);
222 error = chppWifiServiceRequestRangingAsync(wifiServiceContext, rxHeader,
223 buf, len);
224 break;
225 }
226
227 case CHPP_WIFI_REQUEST_NAN_SUB: {
228 rRState = &wifiServiceContext->requestNanSubscribe;
229 chppServiceTimestampRequest(rRState, rxHeader);
230 error = chppWifiServiceRequestNanSubscribe(wifiServiceContext, rxHeader,
231 buf, len);
232 break;
233 }
234
235 case CHPP_WIFI_REQUEST_NAN_SUB_CANCEL: {
236 rRState = &wifiServiceContext->requestNanSubscribeCancel;
237 chppServiceTimestampRequest(rRState, rxHeader);
238 error = chppWifiServiceRequestNanSubscribeCancel(wifiServiceContext,
239 rxHeader, buf, len);
240 break;
241 };
242
243 case CHPP_WIFI_REQUEST_NAN_RANGING_ASYNC: {
244 rRState = &wifiServiceContext->requestNanRangingAsync;
245 chppServiceTimestampRequest(rRState, 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 // chppServiceTimestampRequest()
261 chppServiceTimestampResponse(rRState);
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 chppAllocServiceResponseFixed(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,
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 chppAllocServiceResponseFixed(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,
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 =
392 chppAllocServiceResponseFixed(requestHeader,
393 struct ChppWifiGetCapabilitiesResponse);
394 size_t responseLen = sizeof(*response);
395
396 if (response == NULL) {
397 CHPP_LOG_OOM();
398 error = CHPP_APP_ERROR_OOM;
399 } else {
400 response->params.capabilities = wifiServiceContext->api->getCapabilities();
401
402 CHPP_LOGD("chppWifiServiceGetCapabilities returning 0x%" PRIx32
403 ", %" PRIuSIZE " bytes",
404 response->params.capabilities, responseLen);
405 chppSendTimestampedResponseOrFail(&wifiServiceContext->service,
406 &wifiServiceContext->getCapabilities,
407 response, responseLen);
408 }
409
410 return error;
411 }
412
413 /**
414 * Configures whether scanEventCallback receives unsolicited scan results, i.e.
415 * the results of scans not performed at the request of CHRE.
416 *
417 * This function returns an error code synchronously.
418 * A subsequent call to chppWifiServiceScanMonitorStatusChangeCallback() will be
419 * used to communicate the result of this request (as a service response).
420 *
421 * @param serviceContext Maintains status for each service instance.
422 * @param requestHeader App layer header of the request.
423 * @param buf Input data. Cannot be null.
424 * @param len Length of input data in bytes.
425 *
426 * @return Indicates the result of this function call.
427 */
chppWifiServiceConfigureScanMonitorAsync(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)428 static enum ChppAppErrorCode chppWifiServiceConfigureScanMonitorAsync(
429 struct ChppWifiServiceState *wifiServiceContext,
430 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
431 UNUSED_VAR(requestHeader);
432 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
433
434 if (len < sizeof(bool)) {
435 error = CHPP_APP_ERROR_INVALID_ARG;
436 } else {
437 bool *enable = (bool *)buf;
438 if (!wifiServiceContext->api->configureScanMonitor(*enable)) {
439 error = CHPP_APP_ERROR_UNSPECIFIED;
440 }
441 }
442
443 return error;
444 }
445
446 /**
447 * Request that the WiFi chipset perform a scan, or deliver results from its
448 * cache if the parameters allow for it.
449 *
450 * This function returns an error code synchronously.
451 * A subsequent call to chppWifiServiceScanResponseCallback() will be used to
452 * communicate the result of this request (as a service response).
453 * A subsequent call to chppWifiServiceScanEventCallback() will be used to
454 * communicate the scan results (as a service notification).
455 *
456 * @param serviceContext Maintains status for each service instance.
457 * @param requestHeader App layer header of the request.
458 * @param buf Input data. Cannot be null.
459 * @param len Length of input data in bytes.
460 *
461 * @return Indicates the result of this function call.
462 */
chppWifiServiceRequestScanAsync(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)463 static enum ChppAppErrorCode chppWifiServiceRequestScanAsync(
464 struct ChppWifiServiceState *wifiServiceContext,
465 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
466 UNUSED_VAR(requestHeader);
467 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
468
469 struct chreWifiScanParams *chre =
470 chppWifiScanParamsToChre((struct ChppWifiScanParams *)buf, len);
471
472 if (chre == NULL) {
473 CHPP_LOGE(
474 "WifiServiceRequestScanAsync CHPP -> CHRE conversion failed. Input "
475 "len=%" PRIuSIZE,
476 len);
477 error = CHPP_APP_ERROR_INVALID_ARG;
478
479 } else {
480 if (!wifiServiceContext->api->requestScan(chre)) {
481 error = CHPP_APP_ERROR_UNSPECIFIED;
482 }
483
484 if (chre->frequencyListLen > 0) {
485 void *frequencyList = CHPP_CONST_CAST_POINTER(chre->frequencyList);
486 CHPP_FREE_AND_NULLIFY(frequencyList);
487 }
488 if (chre->ssidListLen > 0) {
489 void *ssidList = CHPP_CONST_CAST_POINTER(chre->ssidList);
490 CHPP_FREE_AND_NULLIFY(ssidList);
491 }
492 CHPP_FREE_AND_NULLIFY(chre);
493 }
494
495 return error;
496 }
497
498 /**
499 * Request that the WiFi chipset perform RTT ranging against a set of access
500 * points specified in params.
501 *
502 * This function returns an error code synchronously.
503 * A subsequent call to chppWifiServiceRangingEventCallback() will be used to
504 * communicate the ranging results (as a service notification).
505 *
506 * @param serviceContext Maintains status for each service instance.
507 * @param requestHeader App layer header of the request.
508 * @param buf Input data. Cannot be null.
509 * @param len Length of input data in bytes.
510 *
511 * @return Indicates the result of this function call.
512 */
chppWifiServiceRequestRangingAsync(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)513 static enum ChppAppErrorCode chppWifiServiceRequestRangingAsync(
514 struct ChppWifiServiceState *wifiServiceContext,
515 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
516 UNUSED_VAR(requestHeader);
517 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
518
519 struct chreWifiRangingParams *chre =
520 chppWifiRangingParamsToChre((struct ChppWifiRangingParams *)buf, len);
521
522 if (chre == NULL) {
523 CHPP_LOGE(
524 "WifiServiceRequestRangingAsync CHPP -> CHRE conversion failed. Input "
525 "len=%" PRIuSIZE,
526 len);
527 error = CHPP_APP_ERROR_INVALID_ARG;
528
529 } else {
530 if (!wifiServiceContext->api->requestRanging(chre)) {
531 error = CHPP_APP_ERROR_UNSPECIFIED;
532
533 } else {
534 struct ChppAppHeader *response =
535 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
536 size_t responseLen = sizeof(*response);
537
538 if (response == NULL) {
539 CHPP_LOG_OOM();
540 error = CHPP_APP_ERROR_OOM;
541 } else {
542 chppSendTimestampedResponseOrFail(
543 &wifiServiceContext->service,
544 &wifiServiceContext->requestRangingAsync, response, responseLen);
545 }
546 }
547
548 if (chre->targetListLen > 0) {
549 void *targetList = CHPP_CONST_CAST_POINTER(chre->targetList);
550 CHPP_FREE_AND_NULLIFY(targetList);
551 }
552 CHPP_FREE_AND_NULLIFY(chre);
553 }
554
555 return error;
556 }
557
chppWifiServiceRequestNanSubscribe(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)558 static enum ChppAppErrorCode chppWifiServiceRequestNanSubscribe(
559 struct ChppWifiServiceState *wifiServiceContext,
560 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
561 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
562
563 struct chreWifiNanSubscribeConfig *chreConfig =
564 chppWifiNanSubscribeConfigToChre((struct ChppWifiNanSubscribeConfig *)buf,
565 len);
566 if (chreConfig == NULL) {
567 CHPP_LOGE(
568 "WifiServiceNanSubscribeConfig CHPP -> CHRE conversion failed."
569 "Input len: %" PRIuSIZE,
570 len);
571 error = CHPP_APP_ERROR_INVALID_ARG;
572 } else {
573 if (!wifiServiceContext->api->nanSubscribe(chreConfig)) {
574 error = CHPP_APP_ERROR_UNSPECIFIED;
575
576 } else {
577 struct ChppAppHeader *response =
578 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
579 size_t responseLen = sizeof(*response);
580
581 if (response == NULL) {
582 CHPP_LOG_OOM();
583 error = CHPP_APP_ERROR_OOM;
584 } else {
585 chppSendTimestampedResponseOrFail(
586 &wifiServiceContext->service,
587 &wifiServiceContext->requestNanSubscribe, response, responseLen);
588 }
589 }
590 }
591 return error;
592 }
593
chppWifiServiceRequestNanSubscribeCancel(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)594 static enum ChppAppErrorCode chppWifiServiceRequestNanSubscribeCancel(
595 struct ChppWifiServiceState *wifiServiceContext,
596 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
597 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
598
599 if (len < sizeof(struct ChppWifiNanSubscribeCancelRequest)) {
600 CHPP_LOGE(
601 "WifiServiceRequestNanSubscribecancel invalid input len = %" PRIuSIZE,
602 len);
603 error = CHPP_APP_ERROR_INVALID_ARG;
604 } else {
605 struct ChppWifiNanSubscribeCancelRequest *chppRequest =
606 (struct ChppWifiNanSubscribeCancelRequest *)buf;
607 uint32_t subscriptionId = chppRequest->subscriptionId;
608 if (!wifiServiceContext->api->nanSubscribeCancel(subscriptionId)) {
609 error = CHPP_APP_ERROR_UNSPECIFIED;
610
611 } else {
612 struct ChppAppHeader *response =
613 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
614 size_t responseLen = sizeof(*response);
615
616 if (response == NULL) {
617 CHPP_LOG_OOM();
618 error = CHPP_APP_ERROR_OOM;
619 } else {
620 chppSendTimestampedResponseOrFail(
621 &wifiServiceContext->service,
622 &wifiServiceContext->requestNanSubscribeCancel, response,
623 responseLen);
624 }
625 }
626 }
627 return error;
628 }
629
chppWifiServiceRequestNanRanging(struct ChppWifiServiceState * wifiServiceContext,struct ChppAppHeader * requestHeader,uint8_t * buf,size_t len)630 static bool chppWifiServiceRequestNanRanging(
631 struct ChppWifiServiceState *wifiServiceContext,
632 struct ChppAppHeader *requestHeader, uint8_t *buf, size_t len) {
633 enum ChppAppErrorCode error = CHPP_APP_ERROR_NONE;
634
635 struct chreWifiNanRangingParams *chreParams = chppWifiNanRangingParamsToChre(
636 (struct ChppWifiNanRangingParams *)buf, len);
637 if (chreParams == NULL) {
638 CHPP_LOGE(
639 "WifiServiceRequestNanRanging CHPP -> CHRE conversion failed. "
640 "Input len: %" PRIuSIZE,
641 len);
642 error = CHPP_APP_ERROR_INVALID_ARG;
643
644 } else {
645 if (!wifiServiceContext->api->requestNanRanging(chreParams)) {
646 error = CHPP_APP_ERROR_UNSPECIFIED;
647
648 } else {
649 struct ChppAppHeader *response =
650 chppAllocServiceResponseFixed(requestHeader, struct ChppAppHeader);
651 size_t responseLen = sizeof(*response);
652
653 if (response == NULL) {
654 CHPP_LOG_OOM();
655 error = CHPP_APP_ERROR_OOM;
656 } else {
657 chppSendTimestampedResponseOrFail(
658 &wifiServiceContext->service,
659 &wifiServiceContext->requestNanRangingAsync, response, responseLen);
660 }
661 }
662 }
663 return error;
664 }
665
666 /**
667 * PAL callback with the result of changes to the scan monitor registration
668 * status requested via configureScanMonitor.
669 *
670 * @param enabled true if the scan monitor is currently active
671 * @param errorCode An error code from enum chreError
672 */
chppWifiServiceScanMonitorStatusChangeCallback(bool enabled,uint8_t errorCode)673 static void chppWifiServiceScanMonitorStatusChangeCallback(bool enabled,
674 uint8_t errorCode) {
675 // Recreate request header
676 struct ChppAppHeader requestHeader = {
677 .handle = gWifiServiceContext.service.handle,
678 .transaction = gWifiServiceContext.configureScanMonitorAsync.transaction,
679 .command = CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC,
680 };
681
682 struct ChppWifiConfigureScanMonitorAsyncResponse *response =
683 chppAllocServiceResponseFixed(
684 &requestHeader, struct ChppWifiConfigureScanMonitorAsyncResponse);
685 size_t responseLen = sizeof(*response);
686
687 if (response == NULL) {
688 CHPP_LOG_OOM();
689 CHPP_ASSERT(false);
690
691 } else {
692 response->params.enabled = enabled;
693 response->params.errorCode = errorCode;
694
695 chppSendTimestampedResponseOrFail(
696 &gWifiServiceContext.service,
697 &gWifiServiceContext.configureScanMonitorAsync, response, responseLen);
698 }
699 }
700
701 /**
702 * PAL callback with the result of a requestScan.
703 *
704 * @param pending true if the request was successful.
705 * @param errorCode An error code from enum chreError.
706 */
chppWifiServiceScanResponseCallback(bool pending,uint8_t errorCode)707 static void chppWifiServiceScanResponseCallback(bool pending,
708 uint8_t errorCode) {
709 // Recreate request header
710 struct ChppAppHeader requestHeader = {
711 .handle = gWifiServiceContext.service.handle,
712 .transaction = gWifiServiceContext.requestScanAsync.transaction,
713 .command = CHPP_WIFI_REQUEST_SCAN_ASYNC,
714 };
715
716 struct ChppWifiRequestScanResponse *response = chppAllocServiceResponseFixed(
717 &requestHeader, struct ChppWifiRequestScanResponse);
718 size_t responseLen = sizeof(*response);
719
720 if (response == NULL) {
721 CHPP_LOG_OOM();
722 CHPP_ASSERT(false);
723
724 } else {
725 response->params.pending = pending;
726 response->params.errorCode = errorCode;
727
728 chppSendTimestampedResponseOrFail(&gWifiServiceContext.service,
729 &gWifiServiceContext.requestScanAsync,
730 response, responseLen);
731 }
732 }
733
734 /**
735 * PAL callback with WiFi scan results.
736 *
737 * @param event Scan result data.
738 */
chppWifiServiceScanEventCallback(struct chreWifiScanEvent * event)739 static void chppWifiServiceScanEventCallback(struct chreWifiScanEvent *event) {
740 // Craft response per parser script
741 struct ChppWifiScanEventWithHeader *notification = NULL;
742 size_t notificationLen = 0;
743
744 CHPP_DEBUG_ASSERT(chppCheckWifiScanEventNotification(event));
745
746 if (!chppWifiScanEventFromChre(event, ¬ification, ¬ificationLen)) {
747 CHPP_LOGE("ScanEvent conversion failed (OOM?). ID=%" PRIu8,
748 gWifiServiceContext.requestScanAsync.transaction);
749
750 notification = chppMalloc(sizeof(struct ChppAppHeader));
751 if (notification == NULL) {
752 CHPP_LOG_OOM();
753 } else {
754 notificationLen = sizeof(struct ChppAppHeader);
755 }
756 }
757
758 if (notification != NULL) {
759 notification->header.handle = gWifiServiceContext.service.handle;
760 notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
761 notification->header.transaction =
762 gWifiServiceContext.requestScanAsync.transaction;
763 notification->header.error =
764 (notificationLen > sizeof(struct ChppAppHeader))
765 ? CHPP_APP_ERROR_NONE
766 : CHPP_APP_ERROR_CONVERSION_FAILED;
767 notification->header.command = CHPP_WIFI_REQUEST_SCAN_ASYNC;
768
769 chppEnqueueTxDatagramOrFail(
770 gWifiServiceContext.service.appContext->transportContext, notification,
771 notificationLen);
772 }
773
774 gWifiServiceContext.api->releaseScanEvent(event);
775 }
776
777 /**
778 * PAL callback with RTT ranging results from the WiFi module.
779 *
780 * @param errorCode An error code from enum chreError.
781 * @param event Ranging data.
782 */
chppWifiServiceRangingEventCallback(uint8_t errorCode,struct chreWifiRangingEvent * event)783 static void chppWifiServiceRangingEventCallback(
784 uint8_t errorCode, struct chreWifiRangingEvent *event) {
785 struct ChppWifiRangingEventWithHeader *notification = NULL;
786 size_t notificationLen = 0;
787
788 if (!chppWifiRangingEventFromChre(event, ¬ification, ¬ificationLen)) {
789 CHPP_LOGE("RangingEvent conversion failed (OOM?) ID=%" PRIu8,
790 gWifiServiceContext.requestRangingAsync.transaction);
791
792 notification = chppMalloc(sizeof(struct ChppAppHeader));
793 if (notification == NULL) {
794 CHPP_LOG_OOM();
795 } else {
796 notificationLen = sizeof(struct ChppAppHeader);
797 }
798 }
799
800 if (notification != NULL) {
801 uint16_t command = CHPP_WIFI_REQUEST_RANGING_ASYNC;
802
803 // Per CHRE's API contract, only one kind of ranging request can be pending
804 // at a time - use the higher of the two for the notification.
805 uint8_t transaction =
806 MAX(gWifiServiceContext.requestRangingAsync.transaction,
807 gWifiServiceContext.requestNanRangingAsync.transaction);
808 notification->header.handle = gWifiServiceContext.service.handle;
809 notification->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
810 notification->header.transaction = transaction;
811 notification->header.command = command;
812 notification->header.error =
813 (notificationLen > sizeof(struct ChppAppHeader))
814 ? CHPP_APP_ERROR_NONE
815 : CHPP_APP_ERROR_CONVERSION_FAILED;
816
817 if (errorCode != CHRE_ERROR_NONE) {
818 notification->header.error = CHPP_APP_ERROR_BEYOND_CHPP;
819 notificationLen = MIN(notificationLen, sizeof(struct ChppAppHeader));
820 }
821
822 chppEnqueueTxDatagramOrFail(
823 gWifiServiceContext.service.appContext->transportContext, notification,
824 notificationLen);
825 }
826
827 gWifiServiceContext.api->releaseRangingEvent(event);
828 }
829
830 /**
831 * PAL callback with NAN service subscription identifier information.
832 *
833 * @param errorCode Error code indicating if a NAN subscription failed. The
834 * subscriptionId field is only valid if the error code is
835 * CHRE_ERROR_NONE.
836 * @param subscriptionId The ID assigned to the service subscription request.
837 * This value is only valid if the error code is CHRE_ERROR_NONE.
838 */
chppWifiServiceNanIdentifierCallback(uint8_t errorCode,uint32_t subscriptionId)839 static void chppWifiServiceNanIdentifierCallback(uint8_t errorCode,
840 uint32_t subscriptionId) {
841 size_t idLen = sizeof(struct ChppWifiNanServiceIdentifier);
842 struct ChppWifiNanServiceIdentifier *id = chppMalloc(idLen);
843 if (id == NULL) {
844 CHPP_LOG_OOM();
845 } else {
846 id->header.command = CHPP_WIFI_REQUEST_NAN_SUB;
847 id->header.handle = gWifiServiceContext.service.handle;
848 id->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
849 id->header.error = CHPP_APP_ERROR_NONE;
850 id->header.transaction =
851 gWifiServiceContext.requestNanSubscribe.transaction;
852 id->errorCode = errorCode;
853 id->subscriptionId = subscriptionId;
854
855 chppEnqueueTxDatagramOrFail(
856 gWifiServiceContext.service.appContext->transportContext, id, idLen);
857 }
858 }
859
860 /**
861 * PAL callback with NAN service discovery information.
862 *
863 * @param event Information about a discovered publishing service.
864 */
chppWifiServiceNanDiscoveryCallback(struct chreWifiNanDiscoveryEvent * event)865 static void chppWifiServiceNanDiscoveryCallback(
866 struct chreWifiNanDiscoveryEvent *event) {
867 struct ChppWifiNanDiscoveryEventWithHeader *notif = NULL;
868 size_t notifLen = 0;
869
870 if (!chppWifiNanDiscoveryEventFromChre(event, ¬if, ¬ifLen)) {
871 CHPP_LOGE("Discovery event conversion failed");
872 notif = chppMalloc(sizeof(struct ChppAppHeader));
873 if (notif == NULL) {
874 CHPP_LOG_OOM();
875 } else {
876 notifLen = sizeof(struct ChppAppHeader);
877 }
878 }
879
880 if (notif != NULL) {
881 notif->header.handle = gWifiServiceContext.service.handle;
882 notif->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
883 notif->header.error = (notifLen > sizeof(struct ChppAppHeader))
884 ? CHPP_APP_ERROR_NONE
885 : CHPP_APP_ERROR_CONVERSION_FAILED;
886 notif->header.command = CHPP_WIFI_NOTIFICATION_NAN_SERVICE_DISCOVERY;
887
888 chppEnqueueTxDatagramOrFail(
889 gWifiServiceContext.service.appContext->transportContext, notif,
890 notifLen);
891 }
892
893 if (event != NULL) {
894 gWifiServiceContext.api->releaseNanDiscoveryEvent(event);
895 }
896 }
897
898 /**
899 * PAL callback invoked when a publishing NAN service goes away.
900 *
901 * @param subscriptionId ID of the subscribing service.
902 * @param publisherId ID of the publishing service that has gone away.
903 */
chppWifiServiceNanLostCallback(uint32_t subscriptionId,uint32_t publisherId)904 static void chppWifiServiceNanLostCallback(uint32_t subscriptionId,
905 uint32_t publisherId) {
906 struct chreWifiNanSessionLostEvent chreEvent = {
907 .id = subscriptionId,
908 .peerId = publisherId,
909 };
910 struct ChppWifiNanSessionLostEventWithHeader *notif = NULL;
911 size_t notifLen = 0;
912
913 if (!chppWifiNanSessionLostEventFromChre(&chreEvent, ¬if, ¬ifLen)) {
914 CHPP_LOGE("Session lost event conversion failed");
915 notif = chppMalloc(sizeof(struct ChppAppHeader));
916 if (notif == NULL) {
917 CHPP_LOG_OOM();
918 } else {
919 notifLen = sizeof(struct ChppAppHeader);
920 }
921 }
922
923 if (notif != NULL) {
924 notif->header.handle = gWifiServiceContext.service.handle;
925 notif->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
926 notif->header.error = (notifLen > sizeof(struct ChppAppHeader))
927 ? CHPP_APP_ERROR_NONE
928 : CHPP_APP_ERROR_CONVERSION_FAILED;
929 notif->header.command = CHPP_WIFI_NOTIFICATION_NAN_SERVICE_LOST;
930
931 chppEnqueueTxDatagramOrFail(
932 gWifiServiceContext.service.appContext->transportContext, notif,
933 notifLen);
934 }
935 }
936
937 /**
938 * PAL callback invoked when a NAN service subscription is terminated.
939 *
940 * @param reason Error code indicating the reason for the termination.
941 * @param subscriptionId The subscription ID of the terminated NAN service.
942 */
chppWifiServiceNanTerminatedCallback(uint32_t reason,uint32_t subscriptionId)943 static void chppWifiServiceNanTerminatedCallback(uint32_t reason,
944 uint32_t subscriptionId) {
945 uint8_t chreReason = (uint8_t)reason;
946 struct chreWifiNanSessionTerminatedEvent chreEvent = {
947 .id = subscriptionId,
948 .reason = chreReason,
949 };
950 struct ChppWifiNanSessionTerminatedEventWithHeader *notif = NULL;
951 size_t notifLen = 0;
952
953 if (!chppWifiNanSessionTerminatedEventFromChre(&chreEvent, ¬if,
954 ¬ifLen)) {
955 CHPP_LOGE("Session terminated event conversion failed");
956 notif = chppMalloc(sizeof(struct ChppAppHeader));
957 if (notif == NULL) {
958 CHPP_LOG_OOM();
959 } else {
960 notifLen = sizeof(struct ChppAppHeader);
961 }
962 }
963
964 if (notif != NULL) {
965 notif->header.handle = gWifiServiceContext.service.handle;
966 notif->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
967 notif->header.error = (notifLen > sizeof(struct ChppAppHeader))
968 ? CHPP_APP_ERROR_NONE
969 : CHPP_APP_ERROR_CONVERSION_FAILED;
970 notif->header.command = CHPP_WIFI_NOTIFICATION_NAN_SERVICE_TERMINATED;
971
972 chppEnqueueTxDatagramOrFail(
973 gWifiServiceContext.service.appContext->transportContext, notif,
974 notifLen);
975 }
976 }
977
978 /**
979 * PAL callback invoked when a NAN service subscription is canceled.
980 *
981 * @param errorCode A value in @ref chreError indicating the result of the
982 * cancelation, with CHRE_ERROR_NONE indicating success.
983 * @param subscriptionId The subscription ID of the canceled NAN service.
984 */
chppWifiServiceNanSubscriptionCanceledCallback(uint8_t errorCode,uint32_t subscriptionId)985 static void chppWifiServiceNanSubscriptionCanceledCallback(
986 uint8_t errorCode, uint32_t subscriptionId) {
987 size_t responseLen = sizeof(struct ChppWifiNanSubscriptionCanceledResponse);
988 struct ChppWifiNanSubscriptionCanceledResponse *response =
989 chppMalloc(responseLen);
990 if (response == NULL) {
991 CHPP_LOG_OOM();
992 } else {
993 response->header.command = CHPP_WIFI_REQUEST_NAN_SUB_CANCEL;
994 response->header.handle = gWifiServiceContext.service.handle;
995 response->header.type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
996 response->header.error = CHPP_APP_ERROR_NONE;
997 response->header.transaction =
998 gWifiServiceContext.requestNanSubscribeCancel.transaction;
999 response->errorCode = errorCode;
1000 response->subscriptionId = subscriptionId;
1001
1002 chppEnqueueTxDatagramOrFail(
1003 gWifiServiceContext.service.appContext->transportContext, response,
1004 responseLen);
1005 }
1006 }
1007
1008 /************************************************
1009 * Public Functions
1010 ***********************************************/
1011
chppRegisterWifiService(struct ChppAppState * appContext)1012 void chppRegisterWifiService(struct ChppAppState *appContext) {
1013 gWifiServiceContext.api = chrePalWifiGetApi(CHRE_PAL_WIFI_API_V1_2);
1014
1015 chppCheckWifiScanEventNotificationReset();
1016
1017 if (gWifiServiceContext.api == NULL) {
1018 CHPP_DEBUG_ASSERT_LOG(false,
1019 "WiFi PAL API incompatible. Cannot register service");
1020
1021 } else {
1022 chppRegisterService(appContext, (void *)&gWifiServiceContext,
1023 &gWifiServiceContext.service, &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