1 /*
2 * Copyright (C) 2016 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 #ifndef _CHRE_WIFI_H_
18 #define _CHRE_WIFI_H_
19
20 /**
21 * @file
22 * WiFi (IEEE 802.11) API, currently covering scanning features useful for
23 * determining location and offloading certain connectivity scans.
24 *
25 * In this file, specification references use the following shorthand:
26 *
27 * Shorthand | Full specification name
28 * -----------+-------------------------
29 * "802.11" | IEEE Std 802.11-2007
30 * "HT" | IEEE Std 802.11n-2009
31 * "VHT" | IEEE Std 802.11ac-2013
32 *
33 */
34
35 #include <chre/common.h>
36
37 #include <stdbool.h>
38 #include <stdint.h>
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 /**
45 * The set of flags returned by chreWifiGetCapabilities().
46 * @defgroup CHRE_WIFI_CAPABILITIES
47 * @{
48 */
49
50 //! No WiFi APIs are supported
51 #define CHRE_WIFI_CAPABILITIES_NONE UINT32_C(0)
52
53 //! Listening to scan results is supported, as enabled via
54 //! chreWifiConfigureScanMonitorAsync()
55 #define CHRE_WIFI_CAPABILITIES_SCAN_MONITORING UINT32_C(1 << 0)
56
57 //! Requesting WiFi scans on-demand is supported via chreWifiRequestScanAsync()
58 #define CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN UINT32_C(1 << 1)
59
60 /** @} */
61
62 /**
63 * Produce an event ID in the block of IDs reserved for WiFi
64 * @param offset Index into WiFi event ID block; valid range [0,15]
65 */
66 #define CHRE_WIFI_EVENT_ID(offset) (CHRE_EVENT_WIFI_FIRST_EVENT + (offset))
67
68 /**
69 * nanoappHandleEvent argument: struct chreAsyncResult
70 *
71 * Communicates the asynchronous result of a request to the WiFi API. The
72 * requestType field in chreAsyncResult is set to a value from enum
73 * chreWifiRequestType.
74 */
75 #define CHRE_EVENT_WIFI_ASYNC_RESULT CHRE_WIFI_EVENT_ID(0)
76
77 /**
78 * nanoappHandleEvent argument: struct chreWifiScanEvent
79 *
80 * Provides results of a WiFi scan.
81 */
82 #define CHRE_EVENT_WIFI_SCAN_RESULT CHRE_WIFI_EVENT_ID(1)
83
84 // NOTE: Do not add new events with ID > 15; only values 0-15 are reserved
85 // (see chre/event.h)
86
87 /**
88 * The maximum amount of time that is allowed to elapse between a call to
89 * chreWifiRequestScanAsync() that returns true, and the associated
90 * CHRE_EVENT_WIFI_ASYNC_RESULT used to indicate whether the scan completed
91 * successfully or not.
92 */
93 #define CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS (30 * CHRE_NSEC_PER_SEC)
94
95 /**
96 * The current compatibility version of the chreWifiScanEvent structure,
97 * including nested structures.
98 */
99 #define CHRE_WIFI_SCAN_EVENT_VERSION UINT8_C(1)
100
101 /**
102 * Maximum number of frequencies that can be explicitly specified when
103 * requesting a scan
104 * @see #chreWifiScanParams
105 */
106 #define CHRE_WIFI_FREQUENCY_LIST_MAX_LEN (20)
107
108 /**
109 * Maximum number of SSIDs that can be explicitly specified when requesting a
110 * scan
111 * @see #chreWifiScanParams
112 */
113 #define CHRE_WIFI_SSID_LIST_MAX_LEN (20)
114
115 /**
116 * The maximum number of octets in an SSID (see 802.11 7.3.2.1)
117 */
118 #define CHRE_WIFI_SSID_MAX_LEN (32)
119
120 /**
121 * The number of octets in a BSSID (see 802.11 7.1.3.3.3)
122 */
123 #define CHRE_WIFI_BSSID_LEN (6)
124
125 /**
126 * Set of flags which can either indicate a frequency band. Specified as a bit
127 * mask to allow for combinations in future API versions.
128 * @defgroup CHRE_WIFI_BAND_MASK
129 * @{
130 */
131
132 #define CHRE_WIFI_BAND_MASK_2_4_GHZ UINT8_C(1 << 0) //!< 2.4 GHz
133 #define CHRE_WIFI_BAND_MASK_5_GHZ UINT8_C(1 << 1) //!< 5 GHz
134
135 /** @} */
136
137 /**
138 * Characteristics of a scanned device given in struct chreWifiScanResult.flags
139 * @defgroup CHRE_WIFI_SCAN_RESULT_FLAGS
140 * @{
141 */
142
143 #define CHRE_WIFI_SCAN_RESULT_FLAGS_NONE UINT8_C(0)
144
145 //! Element ID 61 (HT Operation) is present (see HT 7.3.2)
146 #define CHRE_WIFI_SCAN_RESULT_FLAGS_HT_OPS_PRESENT UINT8_C(1 << 0)
147
148 //! Element ID 192 (VHT Operation) is present (see VHT 8.4.2)
149 #define CHRE_WIFI_SCAN_RESULT_FLAGS_VHT_OPS_PRESENT UINT8_C(1 << 1)
150
151 //! Element ID 127 (Extended Capbilities) is present, and bit 70 (Fine Timing
152 //! Measurement Responder) is set to 1 (see IEEE draft 802.11mc 8.4.2.26)
153 #define CHRE_WIFI_SCAN_RESULT_FLAGS_IS_80211MC_RTT_RESPONDER UINT8_C(1 << 2)
154
155 //! HT Operation element indicates that a secondary channel is present
156 //! (see HT 7.3.2.57)
157 #define CHRE_WIFI_SCAN_RESULT_FLAGS_HAS_SECONDARY_CHANNEL_OFFSET UINT8_C(1 << 3)
158
159 //! HT Operation element indicates that the secondary channel is below the
160 //! primary channel (see HT 7.3.2.57)
161 #define CHRE_WIFI_SCAN_RESULT_FLAGS_SECONDARY_CHANNEL_OFFSET_IS_BELOW \
162 UINT8_C(1 << 4)
163
164 /** @} */
165
166 /**
167 * Identifies the authentication methods supported by an AP. Note that not every
168 * combination of flags may be possible. Based on WIFI_PNO_AUTH_CODE_* from
169 * hardware/libhardware_legacy/include/hardware_legacy/gscan.h in Android.
170 * @defgroup CHRE_WIFI_SECURITY_MODE_FLAGS
171 * @{
172 */
173
174 #define CHRE_WIFI_SECURITY_MODE_UNKONWN UINT8_C(0)
175
176 #define CHRE_WIFI_SECURITY_MODE_OPEN UINT8_C(1 << 0) //!< No auth/security
177 #define CHRE_WIFI_SECURITY_MODE_WEP UINT8_C(1 << 1)
178 #define CHRE_WIFI_SECURITY_MODE_PSK UINT8_C(1 << 2) //!< WPA-PSK or WPA2-PSK
179 #define CHRE_WIFI_SECURITY_MODE_EAP UINT8_C(1 << 3) //!< Any type of EAPOL
180
181 /** @} */
182
183 /**
184 * Identifies a WiFi frequency band
185 */
186 enum chreWifiBand {
187 CHRE_WIFI_BAND_2_4_GHZ = CHRE_WIFI_BAND_MASK_2_4_GHZ,
188 CHRE_WIFI_BAND_5_GHZ = CHRE_WIFI_BAND_MASK_5_GHZ,
189 };
190
191 /**
192 * Indicates the BSS operating channel width determined from the VHT and/or HT
193 * Operation elements. Refer to VHT 8.4.2.161 and HT 7.3.2.57.
194 */
195 enum chreWifiChannelWidth {
196 CHRE_WIFI_CHANNEL_WIDTH_20_MHZ = 0,
197 CHRE_WIFI_CHANNEL_WIDTH_40_MHZ = 1,
198 CHRE_WIFI_CHANNEL_WIDTH_80_MHZ = 2,
199 CHRE_WIFI_CHANNEL_WIDTH_160_MHZ = 3,
200 CHRE_WIFI_CHANNEL_WIDTH_80_PLUS_80_MHZ = 4,
201 };
202
203 /**
204 * Indicates the type of scan requested or performed
205 */
206 enum chreWifiScanType {
207 //! Perform a purely active scan using probe requests. Do not scan channels
208 //! restricted to use via Dynamic Frequency Selection (DFS) only.
209 CHRE_WIFI_SCAN_TYPE_ACTIVE = 0,
210
211 //! Perform an active scan on unrestricted channels, and also perform a
212 //! passive scan on channels that are restricted to use via Dynamic
213 //! Frequency Selection (DFS), e.g. the U-NIII bands 5250-5350MHz and
214 //! 5470-5725MHz in the USA as mandated by FCC regulation.
215 CHRE_WIFI_SCAN_TYPE_ACTIVE_PLUS_PASSIVE_DFS = 1,
216
217 //! Perform a passive scan, only listening for beacons.
218 CHRE_WIFI_SCAN_TYPE_PASSIVE = 2,
219 };
220
221 /**
222 * Indicates a type of request made in this API. Used to populate the resultType
223 * field of struct chreAsyncResult sent with CHRE_EVENT_WIFI_ASYNC_RESULT.
224 */
225 enum chreWifiRequestType {
226 CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR = 1,
227 CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN = 2,
228 };
229
230 /**
231 * SSID with an explicit length field, used when an array of SSIDs is supplied.
232 */
233 struct chreWifiSsidListItem {
234 //! Number of valid bytes in ssid. Valid range [0, CHRE_WIFI_SSID_MAX_LEN]
235 uint8_t ssidLen;
236
237 //! Service Set Identifier (SSID)
238 uint8_t ssid[CHRE_WIFI_SSID_MAX_LEN];
239 };
240
241 /**
242 * Data structure passed to chreWifiRequestScanAsync
243 */
244 struct chreWifiScanParams {
245 //! Set to a value from enum chreWifiScanType
246 uint8_t scanType;
247
248 //! Indicates whether the client is willing to tolerate receiving cached
249 //! results of a previous scan, and if so, the maximum age of the scan that
250 //! the client will accept. "Age" in this case is defined as the elapsed
251 //! time between when the most recent scan was completed and the request is
252 //! received, in milliseconds. If set to 0, no cached results may be
253 //! provided, and all scan results must come from a "fresh" WiFi scan, i.e.
254 //! one that completes strictly after this request is received. If more than
255 //! one scan is cached and meets this age threshold, only the newest scan is
256 //! provided.
257 uint32_t maxScanAgeMs;
258
259 //! If set to 0, scan all frequencies. Otherwise, this indicates the number
260 //! of frequencies to scan, as specified in the frequencyList array. Valid
261 //! range [0, CHRE_WIFI_FREQUENCY_LIST_MAX_LEN].
262 uint16_t frequencyListLen;
263
264 //! Pointer to an array of frequencies to scan, given as channel center
265 //! frequencies in MHz. This field may be NULL if frequencyListLen is 0.
266 const uint32_t *frequencyList;
267
268 //! If set to 0, do not restrict scan to any SSIDs. Otherwise, this
269 //! indicates the number of SSIDs in the ssidList array to be used for
270 //! directed probe requests. Not applicable and ignore when scanType is
271 //! CHRE_WIFI_SCAN_TYPE_PASSIVE.
272 uint8_t ssidListLen;
273
274 //! Pointer to an array of SSIDs to use for directed probe requests. May be
275 //! NULL if ssidListLen is 0.
276 const struct chreWifiSsidListItem *ssidList;
277 };
278
279 /**
280 * Provides information about a single access point (AP) detected in a scan.
281 */
282 struct chreWifiScanResult {
283 //! Number of milliseconds prior to referenceTime in the enclosing
284 //! chreWifiScanEvent struct when the probe response or beacon frame that
285 //! was used to populate this structure was received.
286 uint32_t ageMs;
287
288 //! Capability Information field sent by the AP (see 802.11 7.3.1.4). This
289 //! field must reflect native byte order and bit ordering, such that
290 //! (capabilityInfo & 1) gives the bit for the ESS subfield.
291 uint16_t capabilityInfo;
292
293 //! Number of valid bytes in ssid. Valid range [0, CHRE_WIFI_SSID_MAX_LEN]
294 uint8_t ssidLen;
295
296 //! Service Set Identifier (SSID), a series of 0 to 32 octets identifying
297 //! the access point. Note that this is commonly a human-readable ASCII
298 //! string, but this is not the required encoding per the standard.
299 uint8_t ssid[CHRE_WIFI_SSID_MAX_LEN];
300
301 //! Basic Service Set Identifier (BSSID), represented in big-endian byte
302 //! order, such that the first octet of the OUI is accessed in byte index 0.
303 uint8_t bssid[CHRE_WIFI_BSSID_LEN];
304
305 //! A set of flags from CHRE_WIFI_SCAN_RESULT_FLAGS_*
306 uint8_t flags;
307
308 //! RSSI (Received Signal Strength Indicator), in dBm. Typically negative.
309 int8_t rssi;
310
311 //! Operating band, set to a value from enum chreWifiBand
312 uint8_t band;
313
314 /**
315 * Indicates the center frequency of the primary 20MHz channel, given in
316 * MHz. This value is derived from the channel number via the formula:
317 *
318 * primaryChannel (MHz) = CSF + 5 * primaryChannelNumber
319 *
320 * Where CSF is the channel starting frequency (in MHz) given by the
321 * operating class/band (i.e. 2407 or 5000), and primaryChannelNumber is the
322 * channel number in the range [1, 200].
323 *
324 * Refer to VHT 22.3.14.
325 */
326 uint32_t primaryChannel;
327
328 /**
329 * If the channel width is 20 MHz, this field is not relevant and set to 0.
330 * If the channel width is 40, 80, or 160 MHz, then this denotes the channel
331 * center frequency (in MHz). If the channel is 80+80 MHz, then this denotes
332 * the center frequency of segment 0, which contains the primary channel.
333 * This value is derived from the frequency index using the same formula as
334 * for primaryChannel.
335 *
336 * Refer to VHT 8.4.2.161, and VHT 22.3.14.
337 *
338 * @see #primaryChannel
339 */
340 uint32_t centerFreqPrimary;
341
342 /**
343 * If the channel width is 80+80MHz, then this denotes the center frequency
344 * of segment 1, which does not contain the primary channel. Otherwise, this
345 * field is not relevant and set to 0.
346 *
347 * @see #centerFreqPrimary
348 */
349 uint32_t centerFreqSecondary;
350
351 //! @see #chreWifiChannelWidth
352 uint8_t channelWidth;
353
354 //! Flags from CHRE_WIFI_SECURITY_MODE_* indicating supported authentication
355 //! and associated security modes
356 //! @see CHRE_WIFI_SECURITY_MODE_FLAGS
357 uint8_t securityMode;
358
359 //! Reserved; set to 0
360 uint8_t reserved[10];
361 };
362
363 /**
364 * Data structure sent with events of type CHRE_EVENT_WIFI_SCAN_RESULT.
365 */
366 struct chreWifiScanEvent {
367 //! Indicates the version of the structure, for compatibility purposes.
368 //! Clients do not normally need to worry about this field; the CHRE
369 //! implementation guarantees that the client only receives the structure
370 //! version it expects.
371 uint8_t version;
372
373 //! The number of entries in the results array in this event. The CHRE
374 //! implementation may split scan results across multiple events for memory
375 //! concerns, etc.
376 uint8_t resultCount;
377
378 //! The total number of results returned by the scan. Allows an event
379 //! consumer to identify when it has received all events associated with a
380 //! scan.
381 uint8_t resultTotal;
382
383 //! Sequence number for this event within the series of events comprising a
384 //! complete scan result. Scan events are delivered strictly in order, i.e.
385 //! this is monotonically increasing for the results of a single scan. Valid
386 //! range [0, <number of events for scan> - 1]. The number of events for a
387 //! scan is typically given by
388 //! ceil(resultTotal / <max results per event supported by platform>).
389 uint8_t eventIndex;
390
391 //! A value from enum chreWifiScanType indicating the type of scan performed
392 uint8_t scanType;
393
394 //! If a directed scan was performed to a limited set of SSIDs, then this
395 //! identifies the number of unique SSIDs included in the probe requests.
396 //! Otherwise, this is set to 0, indicating that the scan was not limited by
397 //! SSID. Note that if this is non-zero, the list of SSIDs used is not
398 //! included in the scan event.
399 uint8_t ssidSetSize;
400
401 //! If 0, indicates that all frequencies applicable for the scanType were
402 //! scanned. Otherwise, indicates the number of frequencies scanned, as
403 //! specified in scannedFreqList.
404 uint16_t scannedFreqListLen;
405
406 //! Timestamp when the scan was completed, from the same time base as
407 //! chreGetTime() (in nanoseconds)
408 uint64_t referenceTime;
409
410 //! Pointer to an array containing scannedFreqListLen values comprising the
411 //! set of frequencies that were scanned. Frequencies are specified as
412 //! channel center frequencies in MHz. May be NULL if scannedFreqListLen is
413 //! 0.
414 const uint32_t *scannedFreqList;
415
416 //! Pointer to an array containing resultCount entries. May be NULL if
417 //! resultCount is 0.
418 const struct chreWifiScanResult *results;
419 };
420
421 /**
422 * Retrieves a set of flags indicating the WiFi features supported by the
423 * current CHRE implementation. The value returned by this function must be
424 * consistent for the entire duration of the Nanoapp's execution.
425 *
426 * The client must allow for more flags to be set in this response than it knows
427 * about, for example if the implementation supports a newer version of the API
428 * than the client was compiled against.
429 *
430 * @return A bitmask with zero or more CHRE_WIFI_CAPABILITIES_* flags set
431 *
432 * @since v1.1
433 */
434 uint32_t chreWifiGetCapabilities(void);
435
436 /**
437 * Manages a client's request to receive the results of WiFi scans performed for
438 * other purposes, for example scans done to maintain connectivity and scans
439 * requested by other clients. The presence of this request has no effect on the
440 * frequency or configuration of the WiFi scans performed - it is purely a
441 * registration by the client to receive the results of scans that would
442 * otherwise occur normally. This should include all available scan results,
443 * including those that are not normally sent to the applications processor,
444 * such as Preferred Network Offload (PNO) scans. Scan results provided because
445 * of this registration must not contain cached results - they are always
446 * expected to contain the fresh results from a recent scan.
447 *
448 * An active scan monitor subscription must persist across temporary conditions
449 * under which no WiFi scans will be performed, for example if WiFi is
450 * completely disabled via user-controlled settings, or if the WiFi system
451 * restarts independently of CHRE. Likewise, a request to enable a scan monitor
452 * subscription must succeed under normal conditions, even in circumstances
453 * where no WiFi scans will be performed. In these cases, the scan monitor
454 * implementation must produce scan results once the temporary condition is
455 * cleared, for example after WiFi is enabled by the user.
456 *
457 * These scan results are delivered to the Nanoapp's handle event callback using
458 * CHRE_EVENT_WIFI_SCAN_RESULT.
459 *
460 * An active scan monitor subscription is not necessary to receive the results
461 * of an on-demand scan request sent via chreWifiRequestScanAsync().
462 *
463 * This result of this request is delivered asynchronously via an event of type
464 * CHRE_EVENT_WIFI_ASYNC_RESULT. Refer to the note in {@link #chreAsyncResult}
465 * for more details.
466 *
467 * @param enable Set to true to enable monitoring scan results, false to
468 * disable
469 * @param cookie An opaque value that will be included in the chreAsyncResult
470 * sent in relation to this request.
471 *
472 * @return true if the request was accepted for processing, false otherwise
473 *
474 * @since v1.1
475 */
476 bool chreWifiConfigureScanMonitorAsync(bool enable, const void *cookie);
477
478 /**
479 * Sends an on-demand request for WiFi scan results. This may trigger a new
480 * scan, or be entirely serviced from cache, depending on the maxScanAgeMs
481 * parameter.
482 *
483 * This resulting status of this request is delivered asynchronously via an
484 * event of type CHRE_EVENT_WIFI_ASYNC_RESULT. The result must be delivered
485 * within CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS of the this request. Refer to the
486 * note in {@link #chreAsyncResult} for more details.
487 *
488 * A successful result provided in CHRE_EVENT_WIFI_ASYNC_RESULT indicates that
489 * the scan results will be delivered in a subsequent event (or events) of type
490 * CHRE_EVENT_WIFI_SCAN_RESULT.
491 *
492 * It is not valid for a client to request a new scan while a result is pending
493 * based on a previous scan request from the same client. In this situation, the
494 * CHRE implementation is expected to return a result with CHRE_ERROR_BUSY.
495 * However, if a scan is currently pending or in progress due to a request from
496 * another client, whether within the CHRE or otherwise, the implementation must
497 * not fail the request for this reason. If the pending scan satisfies the
498 * client's request parameters, then the implementation should use its results
499 * to satisfy the request rather than scheduling a new scan.
500 *
501 * @param params A set of parameters for the scan request. Must not be NULL.
502 * @param cookie An opaque value that will be included in the chreAsyncResult
503 * sent in relation to this request.
504 *
505 * @return true if the request was accepted for processing, false otherwise
506 *
507 * @since v1.1
508 */
509 bool chreWifiRequestScanAsync(const struct chreWifiScanParams *params,
510 const void *cookie);
511
512 /**
513 * Convenience function which calls chreWifiRequestScanAsync() with a default
514 * set of scan parameters.
515 *
516 * @param cookie An opaque value that will be included in the chreAsyncResult
517 * sent in relation to this request.
518 *
519 * @return true if the request was accepted for processing, false otherwise
520 *
521 * @since v1.1
522 */
chreWifiRequestScanAsyncDefault(const void * cookie)523 inline bool chreWifiRequestScanAsyncDefault(const void *cookie) {
524 struct chreWifiScanParams params = {};
525 params.scanType = CHRE_WIFI_SCAN_TYPE_ACTIVE;
526 params.maxScanAgeMs = 5000; // 5 seconds
527 params.frequencyListLen = 0;
528 params.ssidListLen = 0;
529 return chreWifiRequestScanAsync(¶ms, cookie);
530 }
531
532 #ifdef __cplusplus
533 }
534 #endif
535
536 #endif /* _CHRE_WIFI_H_ */
537