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  * These scan results are delivered to the Nanoapp's handle event callback using
449  * CHRE_EVENT_WIFI_SCAN_RESULT.
450  *
451  * An active scan monitor subscription is not necessary to receive the results
452  * of an on-demand scan request sent via chreWifiRequestScanAsync().
453  *
454  * This result of this request is delivered asynchronously via an event of type
455  * CHRE_EVENT_WIFI_ASYNC_RESULT. Refer to the note in {@link #chreAsyncResult}
456  * for more details.
457  *
458  * @param enable Set to true to enable monitoring scan results, false to
459  *        disable
460  * @param cookie An opaque value that will be included in the chreAsyncResult
461  *        sent in relation to this request.
462  *
463  * @return true if the request was accepted for processing, false otherwise
464  *
465  * @since v1.1
466  */
467 bool chreWifiConfigureScanMonitorAsync(bool enable, const void *cookie);
468 
469 /**
470  * Sends an on-demand request for WiFi scan results. This may trigger a new
471  * scan, or be entirely serviced from cache, depending on the maxScanAgeMs
472  * parameter.
473  *
474  * This resulting status of this request is delivered asynchronously via an
475  * event of type CHRE_EVENT_WIFI_ASYNC_RESULT. The result must be delivered
476  * within CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS of the this request. Refer to the
477  * note in {@link #chreAsyncResult} for more details.
478  *
479  * A successful result provided in CHRE_EVENT_WIFI_ASYNC_RESULT indicates that
480  * the scan results will be delivered in a subsequent event (or events) of type
481  * CHRE_EVENT_WIFI_SCAN_RESULT.
482  *
483  * It is not valid for a client to request a new scan while a result is pending
484  * based on a previous scan request from the same client. In this situation, the
485  * CHRE implementation is expected to return a result with CHRE_ERROR_BUSY.
486  * However, if a scan is currently pending or in progress due to a request from
487  * another client, whether within the CHRE or otherwise, the implementation must
488  * not fail the request for this reason. If the pending scan satisfies the
489  * client's request parameters, then the implementation should use its results
490  * to satisfy the request rather than scheduling a new scan.
491  *
492  * @param params A set of parameters for the scan request. Must not be NULL.
493  * @param cookie An opaque value that will be included in the chreAsyncResult
494  *        sent in relation to this request.
495  *
496  * @return true if the request was accepted for processing, false otherwise
497  *
498  * @since v1.1
499  */
500 bool chreWifiRequestScanAsync(const struct chreWifiScanParams *params,
501                               const void *cookie);
502 
503 /**
504  * Convenience function which calls chreWifiRequestScanAsync() with a default
505  * set of scan parameters.
506  *
507  * @param cookie An opaque value that will be included in the chreAsyncResult
508  *        sent in relation to this request.
509  *
510  * @return true if the request was accepted for processing, false otherwise
511  *
512  * @since v1.1
513  */
chreWifiRequestScanAsyncDefault(const void * cookie)514 inline bool chreWifiRequestScanAsyncDefault(const void *cookie) {
515     struct chreWifiScanParams params = {};
516     params.scanType         = CHRE_WIFI_SCAN_TYPE_ACTIVE;
517     params.maxScanAgeMs     = 5000;  // 5 seconds
518     params.frequencyListLen = 0;
519     params.ssidListLen      = 0;
520     return chreWifiRequestScanAsync(&params, cookie);
521 }
522 
523 #ifdef __cplusplus
524 }
525 #endif
526 
527 #endif  /* _CHRE_WIFI_H_ */
528