-
#include "wifi_hal.h"
#ifndef __WIFI_HAL_GSCAN_H__
const unsigned MAX_BUCKETS = 16;
const unsigned MAX_HOTLIST_APS = 128;
const unsigned MAX_SIGNIFICANT_CHANGE_APS = 64;
-const unsigned MAX_PNO_SSID = 64;
+const unsigned MAX_EPNO_NETWORKS = 64;
const unsigned MAX_HOTLIST_SSID = 8;
const unsigned MAX_BLACKLIST_BSSID = 16;
const unsigned MAX_AP_CACHE_PER_SCAN = 32;
wifi_gscan_capabilities *capabilities);
typedef enum {
- WIFI_SCAN_BUFFER_FULL,
- WIFI_SCAN_COMPLETE,
+ WIFI_SCAN_RESULTS_AVAILABLE, // reported when REPORT_EVENTS_EACH_SCAN is set and a scan
+ // completes. WIFI_SCAN_THRESHOLD_NUM_SCANS or
+ // WIFI_SCAN_THRESHOLD_PERCENT can be reported instead if the
+ // reason for the event is available; however, at most one of
+ // these events should be reported per scan. If there are
+ // multiple buckets that were scanned this period and one has the
+ // EACH_SCAN flag set then this event should be prefered.
+ WIFI_SCAN_THRESHOLD_NUM_SCANS, // can be reported when REPORT_EVENTS_EACH_SCAN is not set and
+ // report_threshold_num_scans is reached.
+ WIFI_SCAN_THRESHOLD_PERCENT, // can be reported when REPORT_EVENTS_EACH_SCAN is not set and
+ // report_threshold_percent is reached.
+ WIFI_SCAN_DISABLED, // reported when currently executing gscans are disabled.
+ // start_gscan will need to be called again in order to continue
+ // scanning. This is intended to indicate abnormal scan
+ // terminations (not those as a result of stop_gscan).
} wifi_scan_event;
// other fields
} wifi_scan_result;
+static_assert(MAX_BUCKETS <= 8 * sizeof(unsigned),
+ "The buckets_scanned bitset is represented by an unsigned int and cannot support this many "
+ "buckets on this platform.");
typedef struct {
- /* reported when report_threshold is reached in scan cache */
- void (*on_scan_results_available) (wifi_request_id id, unsigned num_results_available);
-
/* reported when each probe response is received, if report_events
- * enabled in wifi_scan_cmd_params */
- void (*on_full_scan_result) (wifi_request_id id, wifi_scan_result *result);
+ * enabled in wifi_scan_cmd_params. buckets_scanned is a bitset of the
+ * buckets that are currently being scanned. See the buckets_scanned field
+ * in the wifi_cached_scan_results struct for more details.
+ */
+ void (*on_full_scan_result) (wifi_request_id id, wifi_scan_result *result,
+ unsigned buckets_scanned);
- /* optional event - indicates progress of scanning statemachine */
- void (*on_scan_event) (wifi_scan_event event, unsigned status);
+ /* indicates progress of scanning statemachine */
+ void (*on_scan_event) (wifi_request_id id, wifi_scan_event event);
} wifi_scan_result_handler;
/* Add channel class */
} wifi_scan_channel_spec;
-#define REPORT_EVENTS_BUFFER_FULL 0
-#define REPORT_EVENTS_EACH_SCAN 1
-#define REPORT_EVENTS_FULL_RESULTS 2
-#define REPORT_EVENTS_NO_BATCH 4
+#define REPORT_EVENTS_EACH_SCAN (1 << 0)
+#define REPORT_EVENTS_FULL_RESULTS (1 << 1)
+#define REPORT_EVENTS_NO_BATCH (1 << 2)
+#define REPORT_EVENTS_CONTEXT_HUB (1 << 3)
typedef struct {
int bucket; // bucket index, 0 based
// for exponential backoff bucket this is the min_period
/* report_events semantics -
* This is a bit field; which defines following bits -
- * REPORT_EVENTS_BUFFER_FULL => report only when scan history is % full
- * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan
+ * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan. If this is not set
+ * then scan completion events should be reported if
+ * report_threshold_percent or report_threshold_num_scans is
+ * reached.
* REPORT_EVENTS_FULL_RESULTS => forward scan results (beacons/probe responses + IEs)
* in real time to HAL, in addition to completion events
* Note: To keep backward compatibility, fire completion
* events regardless of REPORT_EVENTS_EACH_SCAN.
- * REPORT_EVENTS_NO_BATCH => controls batching, 0 => batching, 1 => no batching
+ * REPORT_EVENTS_NO_BATCH => controls if scans for this bucket should be placed in the
+ * history buffer
+ * REPORT_EVENTS_CONTEXT_HUB => forward full scan results in real time and completion events
+ * to context hub
*/
byte report_events;
int max_period; // if max_period is non zero or different than period, then this bucket is
wifi_scan_bucket_spec buckets[MAX_BUCKETS];
} wifi_scan_cmd_params;
-/* Start periodic GSCAN */
+/*
+ * Start periodic GSCAN
+ * When this is called all requested buckets should be scanned, starting the beginning of the cycle
+ *
+ * For example:
+ * If there are two buckets specified
+ * - Bucket 1: period=10s
+ * - Bucket 2: period=20s
+ * - Bucket 3: period=30s
+ * Then the following scans should occur
+ * - t=0 buckets 1, 2, and 3 are scanned
+ * - t=10 bucket 1 is scanned
+ * - t=20 bucket 1 and 2 are scanned
+ * - t=30 bucket 1 and 3 are scanned
+ * - t=40 bucket 1 and 2 are scanned
+ * - t=50 bucket 1 is scanned
+ * - t=60 buckets 1, 2, and 3 are scanned
+ * - and the patter repeats
+ *
+ * If any scan does not occur or is incomplete (error, interrupted, etc) then a cached scan result
+ * should still be recorded with the WIFI_SCAN_FLAG_INTERRUPTED flag set.
+ */
wifi_error wifi_start_gscan(wifi_request_id id, wifi_interface_handle iface,
wifi_scan_cmd_params params, wifi_scan_result_handler handler);
/* Get the GSCAN cached scan results */
typedef struct {
int scan_id; // a unique identifier for the scan unit
- int flags; // a bitmask with additional
- // information about scan
+ int flags; // a bitmask with additional
+ // information about scan.
+ unsigned buckets_scanned; // a bitset of the buckets that were scanned.
+ // for example a value of 13 (0b1101) would
+ // indicate that buckets 0, 2 and 3 were
+ // scanned to produce this list of results.
+ // should be set to 0 if this information is
+ // not available.
int num_results; // number of bssids retrieved by the scan
wifi_scan_result results[MAX_AP_CACHE_PER_SCAN]; // scan results - one for each bssid
} wifi_cached_scan_results;
ssid_threshold_param ssid[MAX_HOTLIST_SSID]; // hotlist SSIDs
} wifi_ssid_hotlist_params;
-
-/* Set the SSID Hotlist */
-wifi_error wifi_set_ssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
- wifi_ssid_hotlist_params params, wifi_hotlist_ssid_handler handler);
-
-/* Clear the SSID Hotlist */
-wifi_error wifi_reset_ssid_hotlist(wifi_request_id id, wifi_interface_handle iface);
-
-
/* BSSID blacklist */
typedef struct {
int num_bssid; // number of blacklisted BSSIDs
wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
wifi_bssid_params params);
-
/* Significant wifi change */
typedef struct {
mac_addr bssid; // BSSID
/* Random MAC OUI for PNO */
wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui);
-// Whether directed scan needs to be performed (for hidden SSIDs)
-#define WIFI_PNO_FLAG_DIRECTED_SCAN = 1
-// Whether PNO event shall be triggered if the network is found on A band
-#define WIFI_PNO_FLAG_A_BAND = 2
-// Whether PNO event shall be triggered if the network is found on G band
-#define WIFI_PNO_FLAG_G_BAND = 4
-// Whether strict matching is required (i.e. firmware shall not match on the entire SSID)
-#define WIFI_PNO_FLAG_STRICT_MATCH = 8
-
-// Code for matching the beacon AUTH IE - additional codes TBD
-#define WIFI_PNO_AUTH_CODE_OPEN 1 // open
-#define WIFI_PNO_AUTH_CODE_PSK 2 // WPA_PSK or WPA2PSK
-#define WIFI_PNO_AUTH_CODE_EAPOL 4 // any EAPOL
// Enhanced PNO:
// Enhanced PNO feature is expected to be enabled all of the time (e.g. screen lit) and may thus
-// requires firmware to store a large number of networks, covering the whole list of known network.
+// require firmware to store a large number of networks, covering the whole list of known networks.
// Therefore, it is acceptable for firmware to store a crc24, crc32 or other short hash of the SSID,
// such that a low but non-zero probability of collision exist. With that scheme it should be
// possible for firmware to keep an entry as small as 4 bytes for each pno network.
// For instance, a firmware pn0 entry can be implemented in the form of:
-// PNO ENTRY = crc24(3 bytes) | RSSI_THRESHOLD>>3 (5 bits) | auth flags(3 bits)
+// PNO ENTRY = crc24(3 bytes) | flags>>3 (5 bits) | auth flags(3 bits)
+//
+// No scans should be automatically performed by the chip. Instead all scan results from gscan
+// should be scored and the wifi_epno_handler on_network_found callback should be called with
+// the scan results.
//
// A PNO network shall be reported once, that is, once a network is reported by firmware
// its entry shall be marked as "done" until framework calls wifi_set_epno_list again.
// Calling wifi_set_epno_list shall reset the "done" status of pno networks in firmware.
+//
+// A network should only be considered found if its RSSI is above the minimum RSSI for its
+// frequency range (min5GHz_rssi and min24GHz_rssi for 5GHz and 2.4GHz networks respectively).
+// When disconnected the list of scan results should be returned if any network is found.
+// When connected the scan results shall be reported only if the score of any network in the scan
+// is greater than that of the currently connected BSSID.
+//
+// The FW should calculate the score of all the candidates (including currently connected one)
+// with following equation:
+// RSSI score = (RSSI + 85) * 4;
+// If RSSI score > initial_score_max , RSSI score = initial_score_max;
+// final score = RSSI score
+// + current_connection_bonus (if currently connected BSSID)
+// + same_network_bonus (if network has SAME_NETWORK flag)
+// + secure_bonus (if the network is not open)
+// + band5GHz_bonus (if BSSID is on 5G)
+// If there is a BSSID’s score > current BSSID’s score, then report the cached scan results
+// at the end of the scan (excluding the ones on blacklist) to the upper layer.
+// Additionally, all BSSIDs that are in the BSSID blacklist should be ignored by Enhanced PNO
+
+// Whether directed scan needs to be performed (for hidden SSIDs)
+#define WIFI_PNO_FLAG_DIRECTED_SCAN (1 << 0)
+// Whether PNO event shall be triggered if the network is found on A band
+#define WIFI_PNO_FLAG_A_BAND (1 << 1)
+// Whether PNO event shall be triggered if the network is found on G band
+#define WIFI_PNO_FLAG_G_BAND (1 << 2)
+// Whether strict matching is required
+// If required then the firmware must store the network's SSID and not just a hash
+#define WIFI_PNO_FLAG_STRICT_MATCH (1 << 3)
+// If this SSID should be considered the same network as the currently connected one for scoring
+#define WIFI_PNO_FLAG_SAME_NETWORK (1 << 4)
+
+// Code for matching the beacon AUTH IE - additional codes TBD
+#define WIFI_PNO_AUTH_CODE_OPEN (1 << 0) // open
+#define WIFI_PNO_AUTH_CODE_PSK (1 << 1) // WPA_PSK or WPA2PSK
+#define WIFI_PNO_AUTH_CODE_EAPOL (1 << 2) // any EAPOL
+
typedef struct {
- char ssid[32+1];
- byte rssi_threshold; // threshold for considering this SSID as found, required granularity for
- // this threshold is 4dBm to 8dBm
- byte flags; // WIFI_PNO_FLAG_XXX
+ char ssid[32+1]; // null terminated
+ byte flags; // WIFI_PNO_FLAG_XXX
byte auth_bit_field; // auth bit field for matching WPA IE
} wifi_epno_network;
-/* PNO list */
+/* ePNO Parameters */
typedef struct {
- int num_networks; // number of SSIDs
- wifi_epno_network networks[]; // PNO networks
+ int min5GHz_rssi; // minimum 5GHz RSSI for a BSSID to be considered
+ int min24GHz_rssi; // minimum 2.4GHz RSSI for a BSSID to be considered
+ int initial_score_max; // the maximum score that a network can have before bonuses
+ int current_connection_bonus; // only report when there is a network's score this much higher
+ // than the current connection.
+ int same_network_bonus; // score bonus for all networks with the same network flag
+ int secure_bonus; // score bonus for networks that are not open
+ int band5GHz_bonus; // 5GHz RSSI score bonus (applied to all 5GHz networks)
+ int num_networks; // number of wifi_epno_network objects
+ wifi_epno_network networks[MAX_EPNO_NETWORKS]; // PNO networks
} wifi_epno_params;
typedef struct {
} wifi_epno_handler;
-/* Set the PNO list */
+/* Set the ePNO list - enable ePNO with the given parameters */
wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
- int num_networks, wifi_epno_network *networks, wifi_epno_handler handler);
+ const wifi_epno_params *epno_params, wifi_epno_handler handler);
+/* Reset the ePNO list - no ePNO networks should be matched after this */
+wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface);
-/* SSID white list */
-/* Note that this feature requires firmware to be able to indicate to kernel sme and wpa_supplicant
- * that the SSID of the network has changed
- * and thus requires further changed in cfg80211 stack, for instance,
- * the below function would change:
-
- void __cfg80211_roamed(struct wireless_dev *wdev,
- struct cfg80211_bss *bss,
- const u8 *req_ie, size_t req_ie_len,
- const u8 *resp_ie, size_t resp_ie_len)
- * when firmware roam to a new SSID the corresponding link layer stats info need to be updated:
- struct wifi_interface_link_layer_info;
- */
-typedef struct {
- char ssid[32+1]; // null terminated
-} wifi_ssid;
-
-wifi_error wifi_set_ssid_white_list(wifi_request_id id, wifi_interface_handle iface,
- int num_networks, wifi_ssid *ssids);
-
-/* Set G-SCAN roam parameters */
-/**
- * Firmware roaming is implemented with two modes:
- * 1- "Alert" mode roaming, (Note: alert roaming is the pre-L roaming, whereas firmware is
- * "urgently" hunting for another BSSID because the RSSI is low, or because many successive
- * beacons have been lost or other bad link conditions).
- * 2- "Lazy" mode, where firmware is hunting for a better BSSID or white listed SSID even though
- * the RSSI of the link is good.
- * Lazy mode is configured thru G-scan, that is, the results of G-scans are compared to the
- * current RSSI and fed thru the roaming engine.
- * Lazy scan will be enabled (and or throttled down by reducing the number of G-scans) by
- * framework only in certain conditions, such as:
- * - no real time (VO/VI) traffic at the interface
- * - low packet rate for BE/BK packets a the interface
- * - system conditions (screen lit/dark) etc...
- *
- * For consistency, the roam parameters will always be configured by framework such that:
- *
- * condition 1- A_band_boost_threshold >= (alert_roam_rssi_trigger + 10)
- * This condition ensures that Lazy roam doesn't cause the device to roam to a 5GHz BSSID whose RSSI
- * is lower than the alert threshold, which would consequently trigger a roam to a low RSSI BSSID,
- * hence triggering alert mode roaming.
- * In other words, in alert mode, the A_band parameters may safely be ignored by WiFi chipset.
- *
- * condition 2- A_band_boost_threshold > A_band_penalty_factor
- *
- */
-
-/**
- * Example:
- * A_band_boost_threshold = -65
- * A_band_penalty_threshold = -75
- * A_band_boost_factor = 4
- * A_band_penalty_factor = 2
- * A_band_max_boost = 50
- *
- * a 5GHz RSSI value is transformed as below:
- * -20 -> -20+ 50 = 30
- * -60 -> -60 + 4 * (-60 - A_band_boost_threshold) = -60 + 16 = -44
- * -70 -> -70
- * -80 -> -80 - 2 * (A_band_penalty_threshold - (-80)) = -80 - 10 = -90
- */
-
-typedef struct {
- // Lazy roam parameters
- // A_band_XX parameters are applied to 5GHz BSSIDs when comparing with a 2.4GHz BSSID
- // they may not be applied when comparing two 5GHz BSSIDs
- int A_band_boost_threshold; // RSSI threshold above which 5GHz RSSI is favored
- int A_band_penalty_threshold; // RSSI threshold below which 5GHz RSSI is penalized
- int A_band_boost_factor; // factor by which 5GHz RSSI is boosted
- // boost=RSSI_measured-5GHz_boost_threshold)*5GHz_boost_factor
- int A_band_penalty_factor; // factor by which 5GHz RSSI is penalized
- // penalty=(5GHz_penalty_factor-RSSI_measured)*5GHz_penalty_factor
- int A_band_max_boost; // maximum boost that can be applied to a 5GHz RSSI
-
- // Hysteresis: ensuring the currently associated BSSID is favored
- // so as to prevent ping-pong situations
- int lazy_roam_hysteresis; // boost applied to current BSSID
-
- // Alert mode enable, i.e. configuring when firmware enters alert mode
- int alert_roam_rssi_trigger; // RSSI below which "Alert" roam is enabled
-} wifi_roam_params;
-
-wifi_error wifi_set_gscan_roam_params(wifi_request_id id, wifi_interface_handle iface,
- wifi_roam_params * params);
-
-/**
- * Enable/Disable "Lazy" roam
- */
-wifi_error wifi_enable_lazy_roam(wifi_request_id id, wifi_interface_handle iface, int enable);
-
-/**
- * Per BSSID preference
- */
-typedef struct {
- mac_addr bssid;
- int rssi_modifier; // modifier applied to the RSSI of the BSSID for the purpose of comparing
- // it with other roam candidate
-} wifi_bssid_preference;
-
-wifi_error wifi_set_bssid_preference(wifi_request_id id, wifi_interface_handle iface,
- int num_bssid, wifi_bssid_preference *prefs);
typedef struct {
int id; // identifier of this network block, report this in event
wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface);
#endif
-