bcmdhd: Add cfg80211 vendor command support
Mohan Thadikamalla [Wed, 28 Oct 2015 11:04:38 +0000 (16:04 +0530)]
Issue: Soft AP is note getting enabled due vendor
country fail

Fix: Add below vendor commands to support 5GHz Soft AP
 - ANDR_WIFI_SET_COUNTRY
 - GSCAN_SUBCMD_GET_CHANNEL_LIST

This code is taken from below google source
https://android.googlesource.com/kernel/common

Bug 200148613
Bug 200123839

Change-Id: Iec642dfd2ebd6e1a2266e540ec757bfa91f9e1e9
Signed-off-by: Ecco Park <eccopark@broadcom.com>
Signed-off-by: Ashwin <ashwin.bhat@broadcom.com>
Signed-off-by: Mohan Thadikamalla <mohant@nvidia.com>
Reviewed-on: http://git-master/r/823951
Reviewed-by: Narayan Reddy <narayanr@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>

drivers/net/wireless/bcmdhd/Makefile [changed mode: 0644->0755]
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/dhd_pno.c [changed mode: 0644->0755]
drivers/net/wireless/bcmdhd/dhd_pno.h [changed mode: 0644->0755]
drivers/net/wireless/bcmdhd/include/wlioctl.h [changed mode: 0644->0755]
drivers/net/wireless/bcmdhd/wl_cfg80211.c [changed mode: 0644->0755]
drivers/net/wireless/bcmdhd/wl_cfgvendor.c [new file with mode: 0755]
drivers/net/wireless/bcmdhd/wl_cfgvendor.h

old mode 100644 (file)
new mode 100755 (executable)
index a0d4c75..c8f998e
@@ -51,6 +51,10 @@ DHDCFLAGS += -DSUPPORT_PM2_ONLY
 DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
 DHDCFLAGS += -DMIRACAST_AMPDU_SIZE=8
 
+# GScan and Vendor Ext support
+DHDCFLAGS += -DWL_VENDOR_EXT_SUPPORT
+DHDCFLAGS += -DGSCAN_SUPPORT
+
 # Early suspend
 DHDCFLAGS += -DDHD_USE_EARLYSUSPEND
 
@@ -237,7 +241,7 @@ DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o \
        bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \
        wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o wl_linux_mon.o  \
        dhd_linux_platdev.o dhd_pno.o dhd_linux_wq.o wl_cfg_btcoex.o \
-       hnd_pktq.o hnd_pktpool.o
+       hnd_pktq.o hnd_pktpool.o wl_cfgvendor.o
 
 ifneq ($(CONFIG_BCMDHD_SDIO),)
   DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o
index 7e84c63..c533a69 100644 (file)
@@ -8396,6 +8396,18 @@ dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize)
 }
 #endif /* PNO_SUPPORT */
 
+#ifdef GSCAN_SUPPORT
+/* Linux wrapper to call common dhd_pno_get_gscan */
+void *
+dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type,
+                      void *info, uint32 *len)
+{
+       dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+       return (dhd_pno_get_gscan(&dhd->pub, type, info, len));
+}
+#endif /* GSCAN_SUPPORT */
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 static void dhd_hang_process(void *dhd_info, void *event_info, u8 event)
 {
old mode 100644 (file)
new mode 100755 (executable)
index 5b4e6c9..fe39827
@@ -1134,6 +1134,156 @@ exit:
        return err;
 }
 
+#ifdef GSCAN_SUPPORT
+static void *dhd_get_gscan_batch_results(dhd_pub_t *dhd, uint32 *len)
+{
+       gscan_results_cache_t *iter, *results;
+       dhd_pno_status_info_t *_pno_state;
+       dhd_pno_params_t *_params;
+       uint16 num_scan_ids = 0, num_results = 0;
+
+       _pno_state = PNO_GET_PNOSTATE(dhd);
+       _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
+
+       iter = results = _params->params_gscan.gscan_batch_cache;
+       while (iter) {
+               num_results += iter->tot_count - iter->tot_consumed;
+               num_scan_ids++;
+               iter = iter->next;
+       }
+
+       *len = ((num_results << 16) | (num_scan_ids));
+       return results;
+}
+
+void * dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
+                          void *info, uint32 *len)
+{
+       void *ret = NULL;
+       dhd_pno_gscan_capabilities_t *ptr;
+       dhd_epno_params_t *epno_params;
+       dhd_pno_params_t *_params;
+       dhd_pno_status_info_t *_pno_state;
+
+       if (!dhd || !dhd->pno_state) {
+               DHD_ERROR(("NULL POINTER : %s\n", __FUNCTION__));
+               return NULL;
+       }
+       _pno_state = PNO_GET_PNOSTATE(dhd);
+       _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
+       if (!len) {
+               DHD_ERROR(("%s: len is NULL\n", __FUNCTION__));
+               return NULL;
+       }
+
+       switch (type) {
+               case DHD_PNO_GET_CAPABILITIES:
+                       ptr = (dhd_pno_gscan_capabilities_t *)
+                       kmalloc(sizeof(dhd_pno_gscan_capabilities_t), GFP_KERNEL);
+                       if (!ptr)
+                               break;
+                       /* Hardcoding these values for now, need to get
+                        * these values from FW, will change in a later check-in
+                        */
+                       ptr->max_scan_cache_size = GSCAN_MAX_AP_CACHE;
+                       ptr->max_scan_buckets = GSCAN_MAX_CH_BUCKETS;
+                       ptr->max_ap_cache_per_scan = GSCAN_MAX_AP_CACHE_PER_SCAN;
+                       ptr->max_rssi_sample_size = PFN_SWC_RSSI_WINDOW_MAX;
+                       ptr->max_scan_reporting_threshold = 100;
+                       ptr->max_hotlist_aps = PFN_HOTLIST_MAX_NUM_APS;
+                       ptr->max_significant_wifi_change_aps = PFN_SWC_MAX_NUM_APS;
+                       ptr->max_epno_ssid_crc32 = MAX_EPNO_SSID_NUM;
+                       ptr->max_epno_hidden_ssid = MAX_EPNO_HIDDEN_SSID;
+                       ptr->max_white_list_ssid = MAX_WHITELIST_SSID;
+                       ret = (void *)ptr;
+                       *len = sizeof(dhd_pno_gscan_capabilities_t);
+                       break;
+
+               case DHD_PNO_GET_BATCH_RESULTS:
+                       ret = dhd_get_gscan_batch_results(dhd, len);
+                       break;
+               case DHD_PNO_GET_CHANNEL_LIST:
+                       if (info) {
+                               uint16 ch_list[WL_NUMCHANNELS];
+                               uint32 *ptr, mem_needed, i;
+                               int32 err, nchan = WL_NUMCHANNELS;
+                               uint32 *gscan_band = (uint32 *) info;
+                               uint8 band = 0;
+
+                               /* No band specified?, nothing to do */
+                               if ((*gscan_band & GSCAN_BAND_MASK) == 0) {
+                                       DHD_PNO(("No band specified\n"));
+                                       *len = 0;
+                                       break;
+                               }
+
+                               /* HAL and DHD use different bits for 2.4G and
+                                * 5G in bitmap. Hence translating it here...
+                                */
+                               if (*gscan_band & GSCAN_BG_BAND_MASK)
+                                       band |= WLC_BAND_2G;
+                               if (*gscan_band & GSCAN_A_BAND_MASK)
+                                       band |= WLC_BAND_5G;
+
+                               err = _dhd_pno_get_channels(dhd, ch_list, &nchan,
+                                                         (band & GSCAN_ABG_BAND_MASK),
+                                                         !(*gscan_band & GSCAN_DFS_MASK));
+
+                               if (err < 0) {
+                                       DHD_ERROR(("%s: failed to get valid channel list\n",
+                                               __FUNCTION__));
+                                       *len = 0;
+                               } else {
+                                       mem_needed = sizeof(uint32) * nchan;
+                                       ptr = (uint32 *) kmalloc(mem_needed, GFP_KERNEL);
+                                       if (!ptr) {
+                                               DHD_ERROR(("%s: Unable to malloc %d bytes\n",
+                                                       __FUNCTION__, mem_needed));
+                                               break;
+                                       }
+                                       for (i = 0; i < nchan; i++) {
+                                               ptr[i] = wf_channel2mhz(ch_list[i],
+                                                       (ch_list[i] <= CH_MAX_2G_CHANNEL?
+                                                       WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
+                                       }
+                                       ret = ptr;
+                                       *len = mem_needed;
+                               }
+                       } else {
+                               *len = 0;
+                               DHD_ERROR(("%s: info buffer is NULL\n", __FUNCTION__));
+                       }
+                       break;
+               case DHD_PNO_GET_EPNO_SSID_ELEM:
+                       if (_params->params_gscan.num_epno_ssid >=
+                          (MAX_EPNO_SSID_NUM + MAX_EPNO_HIDDEN_SSID)) {
+                               DHD_ERROR(("Excessive number of ePNO SSIDs programmed %d\n",
+                                    _params->params_gscan.num_epno_ssid));
+                               return NULL;
+                       }
+
+                       if (!_params->params_gscan.num_epno_ssid)
+                               INIT_LIST_HEAD(&_params->params_gscan.epno_ssid_list);
+
+                       epno_params = kzalloc(sizeof(dhd_epno_params_t), GFP_KERNEL);
+                       if (!epno_params) {
+                               DHD_ERROR(("EPNO ssid: cannot alloc %zd bytes",
+                               sizeof(dhd_epno_params_t)));
+                               return NULL;
+                       }
+                       _params->params_gscan.num_epno_ssid++;
+                       epno_params->index = DHD_EPNO_DEFAULT_INDEX;
+                       list_add_tail(&epno_params->list, &_params->params_gscan.epno_ssid_list);
+                       ret = epno_params;
+               default:
+                       break;
+       }
+
+       return ret;
+
+}
+#endif /* GSCAN_SUPPORT */
+
 static int
 _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
 {
old mode 100644 (file)
new mode 100755 (executable)
index 41ef088..6be6619
 #define RESULTS_END_MARKER "----\n"
 #define SCAN_END_MARKER "####\n"
 #define AP_END_MARKER "====\n"
+#ifdef GSCAN_SUPPORT
+
+#define GSCAN_MAX_CH_BUCKETS             8
+#define GSCAN_MAX_CHANNELS_IN_BUCKET     32
+#define GSCAN_MAX_AP_CACHE_PER_SCAN      32
+#define GSCAN_MAX_AP_CACHE               320
+#define GSCAN_BG_BAND_MASK             (1 << 0)
+#define GSCAN_A_BAND_MASK              (1 << 1)
+#define GSCAN_DFS_MASK                 (1 << 2)
+#define GSCAN_ABG_BAND_MASK            (GSCAN_A_BAND_MASK | GSCAN_BG_BAND_MASK)
+#define GSCAN_BAND_MASK                (GSCAN_ABG_BAND_MASK | GSCAN_DFS_MASK)
+
+#define GSCAN_FLUSH_HOTLIST_CFG      (1 << 0)
+#define GSCAN_FLUSH_SIGNIFICANT_CFG  (1 << 1)
+#define GSCAN_FLUSH_SCAN_CFG         (1 << 2)
+#define GSCAN_FLUSH_EPNO_CFG         (1 << 3)
+#define GSCAN_FLUSH_ALL_CFG     (GSCAN_FLUSH_SCAN_CFG | \
+                                                               GSCAN_FLUSH_SIGNIFICANT_CFG | \
+                                                               GSCAN_FLUSH_HOTLIST_CFG  | \
+                                                               GSCAN_FLUSH_EPNO_CFG)
+#define DHD_EPNO_HIDDEN_SSID          (1 << 0)
+#define DHD_EPNO_A_BAND_TRIG          (1 << 1)
+#define DHD_EPNO_BG_BAND_TRIG         (1 << 2)
+#define DHD_EPNO_STRICT_MATCH         (1 << 3)
+#define DHD_PNO_USE_SSID              (DHD_EPNO_HIDDEN_SSID | DHD_EPNO_STRICT_MATCH)
+
+/* Do not change GSCAN_BATCH_RETRIEVAL_COMPLETE */
+#define GSCAN_BATCH_RETRIEVAL_COMPLETE      0
+#define GSCAN_BATCH_RETRIEVAL_IN_PROGRESS   1
+#define GSCAN_BATCH_NO_THR_SET              101
+#define GSCAN_LOST_AP_WINDOW_DEFAULT        4
+#define GSCAN_MIN_BSSID_TIMEOUT             90
+#define GSCAN_BATCH_GET_MAX_WAIT            500
+
+#define CHANNEL_BUCKET_EMPTY_INDEX                      0xFFFF
+#define GSCAN_RETRY_THRESHOLD              3
+#define MAX_EPNO_SSID_NUM                   32
+
+#endif /* GSCAN_SUPPORT */
 
 enum scan_status {
        /* SCAN ABORT by other scan */
@@ -82,6 +121,12 @@ enum index_mode {
        INDEX_OF_LEGACY_PARAMS,
        INDEX_OF_BATCH_PARAMS,
        INDEX_OF_HOTLIST_PARAMS,
+       /* GSCAN includes hotlist scan and they do not run
+        * independent of each other
+        */
+#ifdef GSCAN_SUPPORT
+       INDEX_OF_GSCAN_PARAMS = INDEX_OF_HOTLIST_PARAMS,
+#endif /* GSCAN_SUPPORT */
        INDEX_MODE_MAX
 };
 enum dhd_pno_status {
@@ -95,6 +140,47 @@ typedef struct cmd_tlv {
        char subtype;
        char reserved;
 } cmd_tlv_t;
+#ifdef GSCAN_SUPPORT
+typedef enum {
+    WIFI_BAND_UNSPECIFIED,
+    WIFI_BAND_BG = 1,                       /* 2.4 GHz                   */
+    WIFI_BAND_A = 2,                        /* 5 GHz without DFS         */
+    WIFI_BAND_A_DFS = 4,                    /* 5 GHz DFS only            */
+    WIFI_BAND_A_WITH_DFS = 6,               /* 5 GHz with DFS            */
+    WIFI_BAND_ABG = 3,                      /* 2.4 GHz + 5 GHz; no DFS   */
+    WIFI_BAND_ABG_WITH_DFS = 7,             /* 2.4 GHz + 5 GHz with DFS  */
+} gscan_wifi_band_t;
+
+typedef enum {
+       HOTLIST_LOST,
+       HOTLIST_FOUND
+} hotlist_type_t;
+
+typedef enum dhd_pno_gscan_cmd_cfg {
+       DHD_PNO_BATCH_SCAN_CFG_ID,
+       DHD_PNO_GEOFENCE_SCAN_CFG_ID,
+       DHD_PNO_SIGNIFICANT_SCAN_CFG_ID,
+       DHD_PNO_SCAN_CFG_ID,
+       DHD_PNO_GET_CAPABILITIES,
+       DHD_PNO_GET_BATCH_RESULTS,
+       DHD_PNO_GET_CHANNEL_LIST,
+       DHD_PNO_GET_EPNO_SSID_ELEM,
+       DHD_PNO_EPNO_CFG_ID,
+       DHD_PNO_GET_AUTOJOIN_CAPABILITIES
+} dhd_pno_gscan_cmd_cfg_t;
+
+typedef enum dhd_pno_mode {
+       /* Wi-Fi Legacy PNO Mode */
+       DHD_PNO_NONE_MODE   = 0,
+       DHD_PNO_LEGACY_MODE = (1 << (0)),
+       /* Wi-Fi Android BATCH SCAN Mode */
+       DHD_PNO_BATCH_MODE = (1 << (1)),
+       /* Wi-Fi Android Hotlist SCAN Mode */
+       DHD_PNO_HOTLIST_MODE = (1 << (2)),
+       /* Wi-Fi Google Android SCAN Mode */
+       DHD_PNO_GSCAN_MODE = (1 << (3))
+} dhd_pno_mode_t;
+#else
 typedef enum dhd_pno_mode {
        /* Wi-Fi Legacy PNO Mode */
        DHD_PNO_NONE_MODE = 0,
@@ -104,6 +190,7 @@ typedef enum dhd_pno_mode {
        /* Wi-Fi Android Hotlist SCAN Mode */
        DHD_PNO_HOTLIST_MODE = (1 << (2))
 } dhd_pno_mode_t;
+#endif /* GSCAN_SUPPORT */
 struct dhd_pno_ssid {
        uint32          SSID_len;
        uchar           SSID[DOT11_MAX_SSID_LEN];
@@ -185,15 +272,190 @@ struct dhd_pno_hotlist_params {
        uint16 nbssid;
        struct list_head bssid_list;
 };
+#ifdef GSCAN_SUPPORT
+#define DHD_PNO_REPORT_NO_BATCH      (1 << 2)
+
+typedef struct dhd_pno_gscan_channel_bucket {
+       uint16 bucket_freq_multiple;
+       /* band = 1 All bg band channels,
+        * band = 2 All a band channels,
+        * band = 0 chan_list channels
+        */
+       uint16 band;
+       uint8 report_flag;
+       uint8 num_channels;
+       uint16 repeat;
+       uint16 bucket_max_multiple;
+       uint16 chan_list[GSCAN_MAX_CHANNELS_IN_BUCKET];
+} dhd_pno_gscan_channel_bucket_t;
+
+
+#define DHD_PNO_AUTH_CODE_OPEN  1 /*  Open   */
+#define DHD_PNO_AUTH_CODE_PSK   2 /* WPA_PSK or WPA2PSK */
+#define DHD_PNO_AUTH_CODE_EAPOL 4 /* any EAPOL    */
+
+#define DHD_EPNO_DEFAULT_INDEX     0xFFFFFFFF
+
+typedef struct dhd_epno_params {
+       uint8 ssid[DOT11_MAX_SSID_LEN];
+       uint8 ssid_len;
+       int8 rssi_thresh;
+       uint8 flags;
+       uint8 auth;
+       /* index required only for visble ssid */
+       uint32 index;
+       struct list_head list;
+} dhd_epno_params_t;
+
+typedef struct dhd_epno_results {
+       uint8 ssid[DOT11_MAX_SSID_LEN];
+       uint8 ssid_len;
+       int8 rssi;
+       uint16 channel;
+       uint16 flags;
+       struct ether_addr bssid;
+} dhd_epno_results_t;
+
+struct dhd_pno_swc_evt_param {
+       uint16 results_rxed_so_far;
+       wl_pfn_significant_net_t *change_array;
+};
+
+typedef struct wifi_gscan_result {
+    uint64 ts;                           /* Time of discovery           */
+    char ssid[DOT11_MAX_SSID_LEN+1];     /* null terminated             */
+    struct ether_addr  macaddr;         /* BSSID                      */
+    uint32 channel;                      /* channel frequency in MHz    */
+    int32 rssi;                          /* in db                       */
+    uint64 rtt;                          /* in nanoseconds              */
+    uint64 rtt_sd;                       /* standard deviation in rtt   */
+    uint16 beacon_period;                /* units are Kusec             */
+    uint16 capability;                     /* Capability information       */
+    uint32 ie_length;                      /* byte length of Information Elements */
+    char  ie_data[1];                                  /* IE data to follow       */
+} wifi_gscan_result_t;
+
+typedef struct gscan_results_cache {
+       struct gscan_results_cache *next;
+       uint8  scan_id;
+       uint8  flag;
+       uint8  tot_count;
+       uint8  tot_consumed;
+       wifi_gscan_result_t results[1];
+} gscan_results_cache_t;
+
+typedef struct {
+    int  id;                            /* identifier of this network block, report this in event */
+    char realm[256];                    /* null terminated UTF8 encoded realm, 0 if unspecified */
+    int64_t roamingConsortiumIds[16];   /* roaming consortium ids to match, 0s if unspecified */
+    uint8 plmn[3];                      /* mcc/mnc combination as per rules, 0s if unspecified */
+} wifi_passpoint_network;
+
+typedef struct dhd_pno_gscan_capabilities {
+    int max_scan_cache_size;
+    int max_scan_buckets;
+    int max_ap_cache_per_scan;
+    int max_rssi_sample_size;
+    int max_scan_reporting_threshold;
+    int max_hotlist_aps;
+    int max_significant_wifi_change_aps;
+    int max_epno_ssid_crc32;
+    int max_epno_hidden_ssid;
+    int max_white_list_ssid;
+} dhd_pno_gscan_capabilities_t;
+
+struct dhd_pno_gscan_params {
+       int32 scan_fr;
+       uint8 bestn;
+       uint8 mscan;
+       uint8 buffer_threshold;
+       uint8 swc_nbssid_threshold;
+       uint8 swc_rssi_window_size;
+       uint8 lost_ap_window;
+       uint8 nchannel_buckets;
+       uint8 reason;
+       uint8 get_batch_flag;
+       uint8 send_all_results_flag;
+       uint16 max_ch_bucket_freq;
+       gscan_results_cache_t *gscan_batch_cache;
+       gscan_results_cache_t *gscan_hotlist_found;
+       gscan_results_cache_t *gscan_hotlist_lost;
+       uint16 nbssid_significant_change;
+       uint16 nbssid_hotlist;
+       uint16 num_epno_ssid;
+       uint8 num_visible_epno_ssid;
+       /* To keep track of visble ssid index
+        * across multiple FW configs i.e. config
+        * w/o clear in between
+        */
+       uint8 ssid_ext_last_used_index;
+       struct dhd_pno_swc_evt_param param_significant;
+       struct dhd_pno_gscan_channel_bucket channel_bucket[GSCAN_MAX_CH_BUCKETS];
+       struct list_head hotlist_bssid_list;
+       struct list_head significant_bssid_list;
+       struct list_head epno_ssid_list;
+       uint32 scan_id;
+};
+
+typedef struct gscan_scan_params {
+       int32 scan_fr;
+       uint16 nchannel_buckets;
+       struct dhd_pno_gscan_channel_bucket channel_bucket[GSCAN_MAX_CH_BUCKETS];
+} gscan_scan_params_t;
+
+typedef struct gscan_batch_params {
+       uint8 bestn;
+       uint8 mscan;
+       uint8 buffer_threshold;
+} gscan_batch_params_t;
+
+struct bssid_t {
+       struct ether_addr       macaddr;
+       int16 rssi_reporting_threshold;  /* 0 -> no reporting threshold */
+};
+
+typedef struct gscan_hotlist_scan_params {
+       uint16 lost_ap_window; /* number of scans to declare LOST */
+       uint16 nbssid;   /* number of bssids  */
+       struct bssid_t bssid[1];  /* n bssids to follow */
+} gscan_hotlist_scan_params_t;
+
+/* SWC (Significant WiFi Change) params */
+typedef struct gscan_swc_params {
+       /* Rssi averaging window size */
+       uint8 rssi_window;
+       /* Number of scans that the AP has to be absent before
+        * being declared LOST
+        */
+       uint8 lost_ap_window;
+       /* if x  Aps have a significant change generate an event. */
+       uint8 swc_threshold;
+       uint8 nbssid;
+       wl_pfn_significant_bssid_t bssid_elem_list[1];
+} gscan_swc_params_t;
+
+typedef struct dhd_pno_significant_bssid {
+       struct ether_addr BSSID;
+       int8 rssi_low_threshold;
+       int8 rssi_high_threshold;
+       struct list_head list;
+} dhd_pno_significant_bssid_t;
+#endif /* GSCAN_SUPPORT */
 typedef union dhd_pno_params {
        struct dhd_pno_legacy_params params_legacy;
        struct dhd_pno_batch_params params_batch;
        struct dhd_pno_hotlist_params params_hotlist;
+#ifdef GSCAN_SUPPORT
+       struct dhd_pno_gscan_params params_gscan;
+#endif /* GSCAN_SUPPORT */
 } dhd_pno_params_t;
 typedef struct dhd_pno_status_info {
        dhd_pub_t *dhd;
        struct work_struct work;
        struct mutex pno_mutex;
+#ifdef GSCAN_SUPPORT
+       wait_queue_head_t batch_get_wait;
+#endif /* GSCAN_SUPPORT */
        struct completion get_batch_done;
        bool wls_supported; /* wifi location service supported or not */
        enum dhd_pno_status pno_status;
@@ -226,7 +488,11 @@ dhd_dev_pno_stop_for_batch(struct net_device *dev);
 extern int
 dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid,
        struct dhd_pno_hotlist_params *hotlist_params);
-
+#ifdef GSCAN_SUPPORT
+extern void *
+dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type, void *info,
+        uint32 *len);
+#endif /* GSCAN_SUPPORT */
 /* dhd pno fuctions */
 extern int dhd_pno_stop_for_ssid(dhd_pub_t *dhd);
 extern int dhd_pno_enable(dhd_pub_t *dhd, int enable);
@@ -248,6 +514,10 @@ extern int dhd_pno_stop_for_hotlist(dhd_pub_t *dhd);
 extern int dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);
 extern int dhd_pno_init(dhd_pub_t *dhd);
 extern int dhd_pno_deinit(dhd_pub_t *dhd);
-#endif 
+#ifdef GSCAN_SUPPORT
+extern void * dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, void *info,
+                       uint32 *len);
+#endif /* GSCAN_SUPPORT */
+#endif /* PNO_SUPPORT */
 
 #endif /* __DHD_PNO_H__ */
old mode 100644 (file)
new mode 100755 (executable)
index aad57fb..b022d8d
@@ -2539,6 +2539,13 @@ enum {
 #define PFN_PARTIAL_SCAN_BIT           0
 #define PFN_PARTIAL_SCAN_MASK          1
 
+#define PFN_SWC_RSSI_WINDOW_MAX   8
+#define PFN_SWC_MAX_NUM_APS       16
+#define PFN_HOTLIST_MAX_NUM_APS   64
+
+#define MAX_EPNO_HIDDEN_SSID         8
+#define MAX_WHITELIST_SSID           2
+
 /* PFN network info structure */
 typedef struct wl_pfn_subnet_info {
        struct ether_addr BSSID;
@@ -2577,6 +2584,20 @@ typedef struct wl_pfn_scanresults {
        wl_pfn_net_info_t netinfo[1];
 } wl_pfn_scanresults_t;
 
+typedef struct wl_pfn_significant_net {
+       uint16 flags;
+       uint16 channel;
+       struct ether_addr BSSID;
+       int8 rssi[PFN_SWC_RSSI_WINDOW_MAX];
+} wl_pfn_significant_net_t;
+
+typedef struct wl_pfn_swc_results {
+       uint32 version;
+       uint32 pkt_count;
+       uint32 total_count;
+       wl_pfn_significant_net_t list[1];
+} wl_pfn_swc_results_t;
+
 /* used to report exactly one scan result */
 /* plus reports detailed scan info in bss_info */
 typedef struct wl_pfn_scanresult {
@@ -2615,6 +2636,13 @@ typedef struct wl_pfn_bssid {
        /* Bit4: suppress_lost, Bit3: suppress_found */
        uint16             flags;
 } wl_pfn_bssid_t;
+
+typedef struct wl_pfn_significant_bssid {
+       struct ether_addr       macaddr;
+       int8    rssi_low_threshold;
+       int8    rssi_high_threshold;
+} wl_pfn_significant_bssid_t;
+
 #define WL_PFN_SUPPRESSFOUND_MASK      0x08
 #define WL_PFN_SUPPRESSLOST_MASK       0x10
 #define WL_PFN_RSSI_MASK               0xff00
old mode 100644 (file)
new mode 100755 (executable)
index 4cd3be4..2d7326a
@@ -68,7 +68,6 @@
 #include <wl_cfg80211.h>
 #include <wl_cfgp2p.h>
 #include <wl_android.h>
-#include <wl_cfgvendor.h>
 #ifdef WL_NAN
 #include <wl_cfgnan.h>
 #endif /* WL_NAN */
@@ -77,6 +76,9 @@
 #include <dhd_wlfc.h>
 #endif
 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+#include <wl_cfgvendor.h>
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
 #ifdef WL11U
 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
 #error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
@@ -8458,11 +8460,14 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
 #endif
        wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
 
-       WL_DBG(("Registering Vendor80211)\n"));
-       err = cfgvendor_attach(wdev->wiphy);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+       WL_ERR(("Registering Vendor80211\n"));
+       err = wl_cfgvendor_attach(wdev->wiphy, dhd);
        if (unlikely(err < 0)) {
                WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
        }
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
+
 
        /* Now we can register wiphy with cfg80211 module */
        err = wiphy_register(wdev->wiphy);
@@ -8489,7 +8494,9 @@ static void wl_free_wdev(struct bcm_cfg80211 *cfg)
        }
        wiphy = wdev->wiphy;
 
-       cfgvendor_detach(wdev->wiphy);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+       wl_cfgvendor_detach(wdev->wiphy);
+#endif /* if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
 
        wiphy_unregister(wdev->wiphy);
        wdev->wiphy->dev.parent = NULL;
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
new file mode 100755 (executable)
index 0000000..cdd4492
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Linux cfg80211 Vendor Extension Code
+ *
+ * Copyright (C) 1999-2014, Broadcom Corporation
+ *
+ *      Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ *      As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module.  An independent module is a module which is not
+ * derived from this software.  The special exception does not apply to any
+ * modifications of the software.
+ *
+ *      Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfgvendor.c 473890 2014-04-30 01:55:06Z $
+*/
+
+/*
+ * New vendor interface additon to nl80211/cfg80211 to allow vendors
+ * to implement proprietary features over the cfg80211 stack.
+*/
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#include <linux/kernel.h>
+
+#include <bcmutils.h>
+#include <bcmwifi_channels.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+#include <dhd_cfg80211.h>
+#ifdef PNO_SUPPORT
+#include <dhd_pno.h>
+#endif /* PNO_SUPPORT */
+#ifdef RTT_SUPPORT
+#include <dhd_rtt.h>
+#endif /* RTT_SUPPORT */
+#include <proto/ethernet.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/wait.h>
+#include <linux/vmalloc.h>
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+
+#include <wlioctl.h>
+#include <wldev_common.h>
+#include <wl_cfg80211.h>
+#include <wl_cfgp2p.h>
+#include <wl_android.h>
+#include <wl_cfgvendor.h>
+#ifdef PROP_TXSTATUS
+#include <dhd_wlfc.h>
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+
+static int wl_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
+        struct net_device *dev, const void  *data, int len)
+{
+       struct sk_buff *skb;
+
+       /* Alloc the SKB for vendor_event */
+       skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+       if (unlikely(!skb)) {
+               WL_ERR(("skb alloc failed"));
+               return -ENOMEM;
+       }
+
+       /* Push the data to the skb */
+       nla_put_nohdr(skb, len, data);
+
+       return cfg80211_vendor_cmd_reply(skb);
+}
+
+static int wl_cfgvendor_priv_string_handler(struct wiphy *wiphy,
+        struct wireless_dev *wdev, const void  *data, int len)
+{
+        struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+        int err = 0;
+        int data_len = 0;
+
+        bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
+
+        if (strncmp((char *)data, BRCM_VENDOR_SCMD_CAPA, strlen(BRCM_VENDOR_SCMD_CAPA)) == 0) {
+                err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "cap", NULL, 0,
+                        cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+                if (unlikely(err)) {
+                        WL_ERR(("error (%d)\n", err));
+                        return err;
+                }
+                data_len = strlen(cfg->ioctl_buf);
+                cfg->ioctl_buf[data_len] = '\0';
+        }
+
+        err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
+                cfg->ioctl_buf, data_len+1);
+        if (unlikely(err))
+                WL_ERR(("Vendor Command reply failed ret:%d \n", err));
+        else
+                WL_INFORM(("Vendor Command reply sent successfully!\n"));
+
+        return err;
+}
+
+static int wl_cfgvendor_set_country(struct wiphy *wiphy,
+        struct wireless_dev *wdev, const void  *data, int len)
+{
+        int err = BCME_ERROR, rem, type;
+        char country_code[WLC_CNTRY_BUF_SZ] = {0};
+        const struct nlattr *iter;
+
+        nla_for_each_attr(iter, data, len, rem) {
+                type = nla_type(iter);
+                switch (type) {
+                        case ANDR_WIFI_ATTRIBUTE_COUNTRY:
+                                memcpy(country_code, nla_data(iter),
+                                        MIN(nla_len(iter), WLC_CNTRY_BUF_SZ));
+                                break;
+                        default:
+                                WL_ERR(("Unknown type: %d\n", type));
+                                return err;
+                }
+        }
+
+        err = wldev_set_country(wdev->netdev, country_code, true, true);
+        if (err < 0) {
+                WL_ERR(("Set country failed ret:%d\n", err));
+        }
+
+        return err;
+}
+
+#ifdef GSCAN_SUPPORT
+static int wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
+       struct wireless_dev *wdev, const void  *data, int len)
+{
+       int err = 0, type, band;
+       struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+       uint16 *reply = NULL;
+       uint32 reply_len = 0, num_channels, mem_needed;
+       struct sk_buff *skb;
+
+       type = nla_type(data);
+
+       if (type == GSCAN_ATTRIBUTE_BAND) {
+               band = nla_get_u32(data);
+       } else {
+               return -1;
+       }
+
+       reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
+          DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
+
+       if (!reply) {
+               WL_ERR(("Could not get channel list\n"));
+               err = -EINVAL;
+               return err;
+       }
+       num_channels =  reply_len/ sizeof(uint32);
+       mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
+
+       /* Alloc the SKB for vendor_event */
+       skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+       if (unlikely(!skb)) {
+               WL_ERR(("skb alloc failed"));
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
+       nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
+
+       err =  cfg80211_vendor_cmd_reply(skb);
+
+       if (unlikely(err))
+               WL_ERR(("Vendor Command reply failed ret:%d \n", err));
+exit:
+       kfree(reply);
+       return err;
+}
+#endif /* GSCAN_SUPPORT */
+
+static const struct wiphy_vendor_command wl_vendor_cmds [] = {
+       {
+               {
+                       .vendor_id = OUI_BRCM,
+                       .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = wl_cfgvendor_priv_string_handler
+       },
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = ANDR_WIFI_SET_COUNTRY
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = wl_cfgvendor_set_country
+       },
+#ifdef GSCAN_SUPPORT
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = wl_cfgvendor_gscan_get_channel_list
+       },
+#endif /* GSCAN_SUPPORT */
+
+};
+
+static const struct  nl80211_vendor_cmd_info wl_vendor_events [] = {
+               { OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC },
+               { OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR },
+               { OUI_GOOGLE, GOOGLE_GSCAN_SIGNIFICANT_EVENT },
+               { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT },
+               { OUI_GOOGLE, GOOGLE_GSCAN_BATCH_SCAN_EVENT },
+               { OUI_GOOGLE, GOOGLE_SCAN_FULL_RESULTS_EVENT },
+               { OUI_GOOGLE, GOOGLE_RTT_COMPLETE_EVENT },
+               { OUI_GOOGLE, GOOGLE_SCAN_COMPLETE_EVENT },
+               { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT },
+               { OUI_GOOGLE, GOOGLE_SCAN_EPNO_EVENT },
+               { OUI_GOOGLE, GOOGLE_DEBUG_RING_EVENT },
+               { OUI_GOOGLE, GOOGLE_FW_DUMP_EVENT },
+               { OUI_GOOGLE, GOOGLE_PNO_HOTSPOT_FOUND_EVENT },
+               { OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT },
+               { OUI_GOOGLE, GOOGLE_MKEEP_ALIVE_EVENT }
+};
+
+int wl_cfgvendor_attach(struct wiphy *wiphy, dhd_pub_t *dhd)
+{
+
+       WL_INFORM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
+               NL80211_CMD_VENDOR));
+
+       wiphy->vendor_commands  = wl_vendor_cmds;
+       wiphy->n_vendor_commands = ARRAY_SIZE(wl_vendor_cmds);
+       wiphy->vendor_events    = wl_vendor_events;
+       wiphy->n_vendor_events  = ARRAY_SIZE(wl_vendor_events);
+
+       return 0;
+}
+
+int wl_cfgvendor_detach(struct wiphy *wiphy)
+{
+       WL_INFORM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
+
+       wiphy->vendor_commands  = NULL;
+       wiphy->vendor_events    = NULL;
+       wiphy->n_vendor_commands = 0;
+       wiphy->n_vendor_events  = 0;
+
+       return 0;
+}
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
index 459279d..58077b3 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * Linux cfg80211 Vendor Extension Code
  *
- * Copyright (C) 1999-2015, Broadcom Corporation
- * 
+ * Copyright (C) 1999-2014, Broadcom Corporation
+ *
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * under the terms of the GNU General Public License version 2 (the "GPL"),
  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  * following added to such license:
- * 
+ *
  *      As a special exception, the copyright holders of this software give you
  * permission to link this software with independent modules, and to copy and
  * distribute the resulting executable under terms of your choice, provided that
  * the license of that module.  An independent module is a module which is not
  * derived from this software.  The special exception does not apply to any
  * modifications of the software.
- * 
+ *
  *      Notwithstanding the above, under no circumstances may you combine this
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: wl_cfgvendor.h 455257 2014-02-20 08:10:24Z $
+ * $Id: wl_cfgvendor.h 473890 2014-04-30 01:55:06Z $
  */
 
+/*
+ * New vendor interface additon to nl80211/cfg80211 to allow vendors
+ * to implement proprietary features over the cfg80211 stack.
+ */
 
 #ifndef _wl_cfgvendor_h_
 #define _wl_cfgvendor_h_
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) && !defined(VENDOR_EXT_SUPPORT)
-#define VENDOR_EXT_SUPPORT
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0) && !VENDOR_EXT_SUPPORT */
+#define OUI_BRCM    0x001018
+#define OUI_GOOGLE  0x001A11
+#define BRCM_VENDOR_SUBCMD_PRIV_STR    1
+#define ATTRIBUTE_U32_LEN                  (NLA_HDRLEN  + 4)
+#define VENDOR_ID_OVERHEAD                 ATTRIBUTE_U32_LEN
+#define VENDOR_SUBCMD_OVERHEAD             ATTRIBUTE_U32_LEN
+#define VENDOR_DATA_OVERHEAD               (NLA_HDRLEN)
+
+#define SCAN_RESULTS_COMPLETE_FLAG_LEN       ATTRIBUTE_U32_LEN
+#define SCAN_INDEX_HDR_LEN                   (NLA_HDRLEN)
+#define SCAN_ID_HDR_LEN                      ATTRIBUTE_U32_LEN
+#define SCAN_FLAGS_HDR_LEN                   ATTRIBUTE_U32_LEN
+#define GSCAN_NUM_RESULTS_HDR_LEN            ATTRIBUTE_U32_LEN
+#define GSCAN_RESULTS_HDR_LEN                (NLA_HDRLEN)
+#define GSCAN_BATCH_RESULT_HDR_LEN  (SCAN_INDEX_HDR_LEN + SCAN_ID_HDR_LEN + \
+                                                                       SCAN_FLAGS_HDR_LEN + \
+                                                               GSCAN_NUM_RESULTS_HDR_LEN + \
+                                                                       GSCAN_RESULTS_HDR_LEN)
+
+#define VENDOR_REPLY_OVERHEAD       (VENDOR_ID_OVERHEAD + \
+                                                                       VENDOR_SUBCMD_OVERHEAD + \
+                                                                       VENDOR_DATA_OVERHEAD)
+typedef enum {
+       /* don't use 0 as a valid subcommand */
+       VENDOR_NL80211_SUBCMD_UNSPECIFIED,
+
+       /* define all vendor startup commands between 0x0 and 0x0FFF */
+       VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
+       VENDOR_NL80211_SUBCMD_RANGE_END   = 0x0FFF,
+
+       /* define all GScan related commands between 0x1000 and 0x10FF */
+       ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
+       ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END   = 0x10FF,
+
+
+       /* define all RTT related commands between 0x1100 and 0x11FF */
+       ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
+       ANDROID_NL80211_SUBCMD_RTT_RANGE_END   = 0x11FF,
+
+       ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
+       ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END   = 0x12FF,
+
+       ANDROID_NL80211_SUBCMD_TDLS_RANGE_START = 0x1300,
+       ANDROID_NL80211_SUBCMD_TDLS_RANGE_END   = 0x13FF,
+
+       ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
+       ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END  = 0x14FF,
+
+       /* define all NearbyDiscovery related commands between 0x1500 and 0x15FF */
+       ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1500,
+       ANDROID_NL80211_SUBCMD_NBD_RANGE_END   = 0x15FF,
+
+       /* define all wifi calling related commands between 0x1600 and 0x16FF */
+       ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
+       ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END   = 0x16FF,
+
+       /* This is reserved for future usage */
+
+} ANDROID_VENDOR_SUB_COMMAND;
+
+enum wl_vendor_subcmd {
+       BRCM_VENDOR_SCMD_UNSPEC,
+       BRCM_VENDOR_SCMD_PRIV_STR,
+       GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
+       GSCAN_SUBCMD_SET_CONFIG,
+       GSCAN_SUBCMD_SET_SCAN_CONFIG,
+       GSCAN_SUBCMD_ENABLE_GSCAN,
+       GSCAN_SUBCMD_GET_SCAN_RESULTS,
+       GSCAN_SUBCMD_SCAN_RESULTS,
+       GSCAN_SUBCMD_SET_HOTLIST,
+       GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG,
+       GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS,
+       GSCAN_SUBCMD_GET_CHANNEL_LIST,
+       ANDR_WIFI_SUBCMD_GET_FEATURE_SET,
+       ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,
+       ANDR_WIFI_RANDOM_MAC_OUI,
+       ANDR_WIFI_NODFS_CHANNELS,
+       ANDR_WIFI_SET_COUNTRY,
+       GSCAN_SUBCMD_SET_EPNO_SSID,
+       WIFI_SUBCMD_SET_SSID_WHITELIST,
+       WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS,
+       WIFI_SUBCMD_ENABLE_LAZY_ROAM,
+       WIFI_SUBCMD_SET_BSSID_PREF,
+       WIFI_SUBCMD_SET_BSSID_BLACKLIST,
+       GSCAN_SUBCMD_ANQPO_CONFIG,
+       WIFI_SUBCMD_SET_RSSI_MONITOR,
+       RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
+       RTT_SUBCMD_CANCEL_CONFIG,
+       RTT_SUBCMD_GETCAPABILITY,
+       LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
+       DEBUG_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
+       DEBUG_TRIGGER_MEM_DUMP,
+       DEBUG_GET_MEM_DUMP,
+       DEBUG_GET_VER,
+       DEBUG_GET_RING_STATUS,
+       DEBUG_GET_RING_DATA,
+       DEBUG_GET_FEATURE,
+       DEBUG_RESET_LOGGING,
+       WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
+       WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
+       /* Add more sub commands here */
+    VENDOR_SUBCMD_MAX
+};
+
+enum gscan_attributes {
+    GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
+    GSCAN_ATTRIBUTE_BASE_PERIOD,
+    GSCAN_ATTRIBUTE_BUCKETS_BAND,
+    GSCAN_ATTRIBUTE_BUCKET_ID,
+    GSCAN_ATTRIBUTE_BUCKET_PERIOD,
+    GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
+    GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
+    GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
+    GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
+    GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
+    GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
+
+    GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
+    GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,
+    GSCAN_ATTRIBUTE_FLUSH_FEATURE,
+    GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS,
+    GSCAN_ATTRIBUTE_REPORT_EVENTS,
+    /* remaining reserved for additional attributes */
+    GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
+    GSCAN_ATTRIBUTE_FLUSH_RESULTS,
+    GSCAN_ATTRIBUTE_SCAN_RESULTS,                       /* flat array of wifi_scan_result */
+    GSCAN_ATTRIBUTE_SCAN_ID,                            /* indicates scan number */
+    GSCAN_ATTRIBUTE_SCAN_FLAGS,                         /* indicates if scan was aborted */
+    GSCAN_ATTRIBUTE_AP_FLAGS,                           /* flags on significant change event */
+    GSCAN_ATTRIBUTE_NUM_CHANNELS,
+    GSCAN_ATTRIBUTE_CHANNEL_LIST,
+
+       /* remaining reserved for additional attributes */
+
+    GSCAN_ATTRIBUTE_SSID = 40,
+    GSCAN_ATTRIBUTE_BSSID,
+    GSCAN_ATTRIBUTE_CHANNEL,
+    GSCAN_ATTRIBUTE_RSSI,
+    GSCAN_ATTRIBUTE_TIMESTAMP,
+    GSCAN_ATTRIBUTE_RTT,
+    GSCAN_ATTRIBUTE_RTTSD,
+
+    /* remaining reserved for additional attributes */
+
+    GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
+    GSCAN_ATTRIBUTE_RSSI_LOW,
+    GSCAN_ATTRIBUTE_RSSI_HIGH,
+    GSCAN_ATTRIBUTE_HOSTLIST_BSSID_ELEM,
+    GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
+
+    /* remaining reserved for additional attributes */
+    GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
+    GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
+    GSCAN_ATTRIBUTE_MIN_BREACHING,
+    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
+    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
 
-enum wl_vendor_event {
+    /* EPNO */
+    GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70,
+    GSCAN_ATTRIBUTE_EPNO_SSID,
+    GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
+    GSCAN_ATTRIBUTE_EPNO_RSSI,
+    GSCAN_ATTRIBUTE_EPNO_FLAGS,
+    GSCAN_ATTRIBUTE_EPNO_AUTH,
+    GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
+    GSCAN_ATTRIBUTE_EPNO_FLUSH,
+
+    /* Roam SSID Whitelist and BSSID pref */
+    GSCAN_ATTRIBUTE_WHITELIST_SSID = 80,
+    GSCAN_ATTRIBUTE_NUM_WL_SSID,
+    GSCAN_ATTRIBUTE_WL_SSID_LEN,
+    GSCAN_ATTRIBUTE_WL_SSID_FLUSH,
+    GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM,
+    GSCAN_ATTRIBUTE_NUM_BSSID,
+    GSCAN_ATTRIBUTE_BSSID_PREF_LIST,
+    GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH,
+    GSCAN_ATTRIBUTE_BSSID_PREF,
+    GSCAN_ATTRIBUTE_RSSI_MODIFIER,
+
+
+    /* Roam cfg */
+    GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90,
+    GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD,
+    GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR,
+    GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR,
+    GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST,
+    GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS,
+    GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER,
+    GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE,
+
+    /* BSSID blacklist */
+    GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100,
+    GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
+
+    GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110,
+    GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE,
+    GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID,
+    GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM,
+    GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
+    GSCAN_ATTRIBUTE_ANQPO_HS_PLMN,
+
+    /* Adaptive scan attributes */
+    GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120,
+    GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
+
+    GSCAN_ATTRIBUTE_MAX
+};
+
+enum gscan_bucket_attributes {
+       GSCAN_ATTRIBUTE_CH_BUCKET_1,
+       GSCAN_ATTRIBUTE_CH_BUCKET_2,
+       GSCAN_ATTRIBUTE_CH_BUCKET_3,
+       GSCAN_ATTRIBUTE_CH_BUCKET_4,
+       GSCAN_ATTRIBUTE_CH_BUCKET_5,
+       GSCAN_ATTRIBUTE_CH_BUCKET_6,
+       GSCAN_ATTRIBUTE_CH_BUCKET_7
+};
+
+enum gscan_ch_attributes {
+       GSCAN_ATTRIBUTE_CH_ID_1,
+       GSCAN_ATTRIBUTE_CH_ID_2,
+       GSCAN_ATTRIBUTE_CH_ID_3,
+       GSCAN_ATTRIBUTE_CH_ID_4,
+       GSCAN_ATTRIBUTE_CH_ID_5,
+       GSCAN_ATTRIBUTE_CH_ID_6,
+       GSCAN_ATTRIBUTE_CH_ID_7
+};
+
+enum rtt_attributes {
+       RTT_ATTRIBUTE_TARGET_CNT,
+       RTT_ATTRIBUTE_TARGET_INFO,
+       RTT_ATTRIBUTE_TARGET_MAC,
+       RTT_ATTRIBUTE_TARGET_TYPE,
+       RTT_ATTRIBUTE_TARGET_PEER,
+       RTT_ATTRIBUTE_TARGET_CHAN,
+       RTT_ATTRIBUTE_TARGET_PERIOD,
+       RTT_ATTRIBUTE_TARGET_NUM_BURST,
+       RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
+       RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
+       RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
+       RTT_ATTRIBUTE_TARGET_LCI,
+       RTT_ATTRIBUTE_TARGET_LCR,
+       RTT_ATTRIBUTE_TARGET_BURST_DURATION,
+       RTT_ATTRIBUTE_TARGET_PREAMBLE,
+       RTT_ATTRIBUTE_TARGET_BW,
+       RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
+       RTT_ATTRIBUTE_RESULTS_PER_TARGET,
+       RTT_ATTRIBUTE_RESULT_CNT,
+       RTT_ATTRIBUTE_RESULT
+};
+
+enum debug_attributes {
+       DEBUG_ATTRIBUTE_GET_DRIVER,
+       DEBUG_ATTRIBUTE_GET_FW,
+       DEBUG_ATTRIBUTE_RING_ID,
+       DEBUG_ATTRIBUTE_RING_NAME,
+       DEBUG_ATTRIBUTE_RING_FLAGS,
+       DEBUG_ATTRIBUTE_LOG_LEVEL,
+       DEBUG_ATTRIBUTE_LOG_TIME_INTVAL,
+       DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE,
+       DEBUG_ATTRIBUTE_FW_DUMP_LEN,
+       DEBUG_ATTRIBUTE_FW_DUMP_DATA,
+       DEBUG_ATTRIBUTE_RING_DATA,
+       DEBUG_ATTRIBUTE_RING_STATUS,
+       DEBUG_ATTRIBUTE_RING_NUM
+};
+
+enum mkeep_alive_attributes {
+       MKEEP_ALIVE_ATTRIBUTE_ID,
+       MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
+       MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
+       MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
+       MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
+       MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
+};
+
+enum wifi_rssi_monitor_attr {
+       RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
+       RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
+       RSSI_MONITOR_ATTRIBUTE_START,
+};
+
+typedef enum wl_vendor_event {
        BRCM_VENDOR_EVENT_UNSPEC,
-       BRCM_VENDOR_EVENT_PRIV_STR
+       BRCM_VENDOR_EVENT_PRIV_STR,
+       GOOGLE_GSCAN_SIGNIFICANT_EVENT,
+       GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT,
+       GOOGLE_GSCAN_BATCH_SCAN_EVENT,
+       GOOGLE_SCAN_FULL_RESULTS_EVENT,
+       GOOGLE_RTT_COMPLETE_EVENT,
+       GOOGLE_SCAN_COMPLETE_EVENT,
+       GOOGLE_GSCAN_GEOFENCE_LOST_EVENT,
+       GOOGLE_SCAN_EPNO_EVENT,
+       GOOGLE_DEBUG_RING_EVENT,
+       GOOGLE_FW_DUMP_EVENT,
+       GOOGLE_PNO_HOTSPOT_FOUND_EVENT,
+       GOOGLE_RSSI_MONITOR_EVENT,
+       GOOGLE_MKEEP_ALIVE_EVENT
+} wl_vendor_event_t;
+
+enum andr_wifi_attr {
+       ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
+       ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
+       ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI,
+       ANDR_WIFI_ATTRIBUTE_NODFS_SET,
+       ANDR_WIFI_ATTRIBUTE_COUNTRY
 };
 
+typedef enum wl_vendor_gscan_attribute {
+       ATTR_START_GSCAN,
+       ATTR_STOP_GSCAN,
+       ATTR_SET_SCAN_BATCH_CFG_ID, /* set batch scan params */
+       ATTR_SET_SCAN_GEOFENCE_CFG_ID, /* set list of bssids to track */
+       ATTR_SET_SCAN_SIGNIFICANT_CFG_ID, /* set list of bssids, rssi threshold etc.. */
+       ATTR_SET_SCAN_CFG_ID, /* set common scan config params here */
+       ATTR_GET_GSCAN_CAPABILITIES_ID,
+    /* Add more sub commands here */
+    ATTR_GSCAN_MAX
+} wl_vendor_gscan_attribute_t;
+
+typedef enum gscan_batch_attribute {
+       ATTR_GSCAN_BATCH_BESTN,
+       ATTR_GSCAN_BATCH_MSCAN,
+       ATTR_GSCAN_BATCH_BUFFER_THRESHOLD
+} gscan_batch_attribute_t;
+
+typedef enum gscan_geofence_attribute {
+       ATTR_GSCAN_NUM_HOTLIST_BSSID,
+       ATTR_GSCAN_HOTLIST_BSSID
+} gscan_geofence_attribute_t;
+
+typedef enum gscan_complete_event {
+       WIFI_SCAN_BUFFER_FULL,
+       WIFI_SCAN_COMPLETE
+} gscan_complete_event_t;
+
 /* Capture the BRCM_VENDOR_SUBCMD_PRIV_STRINGS* here */
 #define BRCM_VENDOR_SCMD_CAPA  "cap"
 
-#ifdef VENDOR_EXT_SUPPORT
-extern int cfgvendor_attach(struct wiphy *wiphy);
-extern int cfgvendor_detach(struct wiphy *wiphy);
-#else
-static INLINE int cfgvendor_attach(struct wiphy *wiphy) { return 0; }
-static INLINE int cfgvendor_detach(struct wiphy *wiphy) { return 0; }
-#endif /*  VENDOR_EXT_SUPPORT */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+extern int wl_cfgvendor_attach(struct wiphy *wiphy, dhd_pub_t *dhd);
+extern int wl_cfgvendor_detach(struct wiphy *wiphy);
+extern int wl_cfgvendor_send_async_event(struct wiphy *wiphy,
+                  struct net_device *dev, int event_id, const void  *data, int len);
+extern int wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
+                struct net_device *dev, void  *data, int len, wl_vendor_event_t event);
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
 
 #endif /* _wl_cfgvendor_h_ */