summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rda/rda_wlan/wlan_scan.c
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/net/wireless/rda/rda_wlan/wlan_scan.c
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/net/wireless/rda/rda_wlan/wlan_scan.c')
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_scan.c429
1 files changed, 429 insertions, 0 deletions
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_scan.c b/drivers/net/wireless/rda/rda_wlan/wlan_scan.c
new file mode 100755
index 00000000..1a76dbff
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_scan.c
@@ -0,0 +1,429 @@
+#include "wlan_includes.h"
+
+//#define SCAN_RESULT_DEBUG
+
+#ifndef FCS_LEN
+#define FCS_LEN 4
+#endif
+
+/* Element ID of various Information Elements */
+typedef enum {
+ ISSID = 0, /* Service Set Identifier */
+ ISUPRATES = 1, /* Supported Rates */
+ IFHPARMS = 2, /* FH parameter set */
+ IDSPARMS = 3, /* DS parameter set */
+ ICFPARMS = 4, /* CF parameter set */
+ ITIM = 5, /* Traffic Information Map */
+ IIBPARMS = 6, /* IBSS parameter set */
+ ICTEXT = 16, /* Challenge Text */
+ IERPINFO = 42, /* ERP Information */
+ IEXSUPRATES = 50, /* Extended Supported Rates */
+ IWAPI =68
+} ELEMENTID_T;
+
+/* Capability Information field bit assignments */
+typedef enum {
+ ESS = 0x01, /* ESS capability */
+ IBSS = 0x02, /* IBSS mode */
+ POLLABLE = 0x04, /* CF Pollable */
+ POLLREQ = 0x08, /* Request to be polled */
+ PRIVACY = 0x10, /* WEP encryption supported */
+ SHORTPREAMBLE = 0x20, /* Short Preamble is supported */
+ SHORTSLOT = 0x400, /* Short Slot is supported */
+ PBCC = 0x40, /* PBCC */
+ CHANNELAGILITY = 0x80, /* Channel Agility */
+ SPECTRUM_MGMT = 0x100, /* Spectrum Management */
+ DSSS_OFDM = 0x2000 /* DSSS-OFDM */
+} CAPABILITY_T;
+
+/* BSS type */
+typedef enum {
+ INFRASTRUCTURE = 1,
+ INDEPENDENT = 2,
+ ANY_BSS = 3
+} BSSTYPE_T;
+
+u8 *get_ie_elem(u8 * msa, ELEMENTID_T elm_id, u16 rx_len, u16 tag_param_offset)
+{
+ u16 index = 0;
+
+ /*************************************************************************/
+ /* Beacon Frame - Frame Body */
+ /* --------------------------------------------------------------------- */
+ /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */
+ /* --------------------------------------------------------------------- */
+ /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */
+ /* --------------------------------------------------------------------- */
+ /* */
+ /*************************************************************************/
+
+ index = tag_param_offset;
+
+ /* Search for the TIM Element Field and return if the element is found */
+ while(index < (rx_len - FCS_LEN)) {
+ if(msa[index] == elm_id){
+ return(&msa[index]);
+ }else{
+ index += (2 + msa[index + 1]);
+ }
+ }
+
+ return(0);
+}
+
+/* This function extracts the 'from ds' bit from the MAC header of the input */
+/* frame. */
+/* Returns the value in the LSB of the returned value. */
+u8 get_from_ds(u8* header)
+{
+ return ((header[1] & 0x02) >> 1);
+}
+
+/* This function extracts the 'to ds' bit from the MAC header of the input */
+/* frame. */
+/* Returns the value in the LSB of the returned value. */
+u8 get_to_ds(u8* header)
+{
+ return (header[1] & 0x01);
+}
+
+/* This function extracts the MAC Address in 'address1' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+void get_address1(u8* msa, u8* addr)
+{
+ memcpy(addr, msa + 4, 6);
+}
+
+/* This function extracts the MAC Address in 'address2' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+void get_address2(u8* msa, u8* addr)
+{
+ memcpy(addr, msa + 10, 6);
+}
+
+/* This function extracts the MAC Address in 'address3' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+void get_address3(u8* msa, u8* addr)
+{
+ memcpy(addr, msa + 16, 6);
+}
+
+/* This function extracts the BSSID from the incoming WLAN packet based on */
+/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */
+/* variable. */
+void get_BSSID(u8* data, u8* bssid)
+{
+ if(get_from_ds(data) == 1)
+ get_address2(data, bssid);
+ else if(get_to_ds(data) == 1)
+ get_address1(data, bssid);
+ else
+ get_address3(data, bssid);
+}
+
+void wlan_network_information(wlan_private * priv, u8 * info, u16 info_len)
+{
+ struct bss_descriptor *iter_bss;
+ struct bss_descriptor *bss = NULL;
+ unsigned char *pos, *end, *p;
+ unsigned char n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
+ struct ieee_ie_country_info_set *pcountryinfo;
+
+ unsigned char* msa = &info[9];
+ unsigned short msa_len = info[6] | (info[7] << 8);
+
+#if 0
+ if(priv->scan_running == WLAN_SCAN_IDLE){
+ WLAN_ERRP("is not in scan process \n");
+ goto done;
+ }
+#endif
+
+ if((msa_len - 1 + 9 ) != info_len){
+ WLAN_ERRP("rda5890_network_information verify lengh feild failed \n");
+ }
+
+ bss = kzalloc(sizeof(struct bss_descriptor), GFP_KERNEL);
+ if (bss == NULL) {
+ WLAN_ERRP("alloc bss_descriptor memory failed \n");
+ return;
+ }
+ memset(bss, 0, sizeof (struct bss_descriptor));
+ bss->rssi = info[8];
+ msa_len -= 1; // has rssi
+
+ get_BSSID(msa, bss->bssid);
+
+ end = msa + msa_len;
+
+ //mac head
+ pos = msa + 24;
+ //time stamp
+ pos += 8;
+ //beacon
+ bss->beaconperiod = *(pos) | (*(pos + 1) << 8);
+ pos += 2 ;
+ //capability
+ bss->capability = *(pos) | (*(pos + 1) << 8);
+ pos += 2;
+
+ if (bss->capability & WLAN_CAPABILITY_IBSS)
+ bss->mode = IW_MODE_ADHOC;
+ else
+ bss->mode = IW_MODE_INFRA;
+
+ /* process variable IE */
+ while (pos + 2 <= end) {
+
+ if (pos + pos[1] > end) {
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("process_bss: error in processing IE, "
+ "bytes left < IE length\n");
+#endif
+ kfree(bss);
+ return;
+ }
+
+ switch (pos[0]) {
+ case WLAN_EID_SSID:
+ bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
+ memcpy(bss->ssid, pos + 2, bss->ssid_len);
+
+ if (priv->scan_ssid_len > 0) {
+ if (bss->ssid_len != priv->scan_ssid_len) {
+ kfree(bss);
+ return;
+ }
+
+ if (memcmp(bss->ssid, priv->scan_ssid, priv->scan_ssid_len)) {
+ kfree(bss);
+ return;
+ }
+ }
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got SSID IE: '%s', len %u %d\n",
+ bss->ssid, bss->ssid_len, pos[1]);
+#endif
+ break;
+
+ case WLAN_EID_SUPP_RATES:
+ n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
+ memcpy(bss->rates, pos + 2, n_basic_rates);
+ got_basic_rates = 1;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got RATES IE\n");
+#endif
+ break;
+
+ case WLAN_EID_FH_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got FH IE\n");
+#endif
+ break;
+
+ case WLAN_EID_DS_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got DS IE\n");
+#endif
+ bss->channel = pos[2];
+ break;
+
+ case WLAN_EID_CF_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got CF IE\n");
+#endif
+ break;
+
+ case WLAN_EID_IBSS_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got IBSS IE\n");
+#endif
+ break;
+
+ case WLAN_EID_COUNTRY:
+ pcountryinfo = (struct ieee_ie_country_info_set *) pos;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got COUNTRY IE\n");
+#endif
+ break;
+
+ case WLAN_EID_EXT_SUPP_RATES:
+ /* only process extended supported rate if data rate is
+ * already found. Data rate IE should come before
+ * extended supported rate IE
+ */
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got RATESEX IE\n");
+#endif
+ if (!got_basic_rates) {
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("... but ignoring it\n");
+#endif
+ break;
+ }
+
+ n_ex_rates = pos[1];
+ if (n_basic_rates + n_ex_rates > MAX_RATES)
+ n_ex_rates = MAX_RATES - n_basic_rates;
+
+ p = bss->rates + n_basic_rates;
+ memcpy(p, pos + 2, n_ex_rates);
+ break;
+
+ case WLAN_EID_GENERIC:
+ if (pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 0x01) {
+ bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+ bss->wpa_ie = kzalloc(bss->wpa_ie_len, GFP_KERNEL);
+ if(bss->wpa_ie)
+ memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
+ else
+ bss->wpa_ie_len = 0;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got WPA IE \n");
+#endif
+ }
+
+ /* huanglei add for wps */
+ else if(pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 0x04 &&
+ (priv->version == WLAN_VERSION_91_E || priv->version == WLAN_VERSION_91_F)) {
+ bss->wps_ie_len = min(pos[1] + 2, MAX_WPS_IE_LEN);
+ bss->wps_ie = kzalloc(bss->wps_ie_len, GFP_KERNEL);
+ if(bss->wps_ie)
+ memcpy(bss->wps_ie, pos, bss->wps_ie_len);
+ else
+ bss->wps_ie_len = 0;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got WPS IE \n");
+#endif
+ }
+ else {
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
+ pos[2], pos[3], pos[4], pos[5], pos[1]);
+#endif
+ }
+ break;
+
+ case WLAN_EID_RSN:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got RSN IE\n");
+#endif
+ bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+ bss->rsn_ie = kzalloc(bss->rsn_ie_len, GFP_KERNEL);
+ if(bss->rsn_ie)
+ memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
+ else
+ bss->rsn_ie_len = 0;
+
+ break;
+
+ case IWAPI:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got WAPI IE\n");
+#endif
+ bss->wapi_ie_len = min(pos[1] + 2, 100);
+ bss->wapi_ie = kzalloc(bss->wapi_ie_len, GFP_KERNEL);
+ if(bss->wapi_ie)
+ memcpy(bss->wapi_ie, pos, bss->wapi_ie_len);
+ else
+ bss->wapi_ie_len = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ pos += pos[1] + 2;
+ }
+
+ bss->last_scanned = jiffies;
+
+ wlan_update_aver_rssi(priv, bss->bssid, bss->rssi);
+ /* add scaned bss into list */
+ if (1) {
+ struct bss_descriptor *found = NULL;
+ struct bss_descriptor *oldest = NULL;
+ struct bss_descriptor *unsed = NULL;
+ struct bss_descriptor *bss_lower_rssi = NULL;
+ s8 rssi = 0, lowRssi = 0;
+
+ spin_lock(&priv->ScanListLock);
+ /* Try to find this bss in the scan table */
+ list_for_each_entry(iter_bss, &priv->network_list, list) {
+ if (is_same_network(iter_bss, bss)) {
+ found = iter_bss;
+ break;
+ }
+
+ if (time_before(iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE, jiffies)) {
+ if(!oldest || (oldest->last_scanned > iter_bss->last_scanned))
+ oldest = iter_bss;
+ }
+
+ if (!iter_bss->ssid_len && unsed==NULL ) {
+ unsed=iter_bss;
+ break;
+ }
+
+ if(!is_zero_eth_addr(iter_bss->bssid)){
+ rssi = wlan_get_aver_rssi(priv, iter_bss->bssid);
+ if(bss_lower_rssi == NULL || rssi < lowRssi){
+ lowRssi = rssi;
+ bss_lower_rssi = iter_bss;
+ if(rssi == INVALID_RSSI)
+ break;
+ }
+ }
+ }
+
+ if (found) { // have in network list
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_DEBUG, "FOUND SAME %s, update\n", found->ssid);
+ /* found, clear it */
+ clear_bss_descriptor(found);
+ memcpy(found, bss, offsetof(struct bss_descriptor, list));
+ } else { //not have in network list
+ if (unsed) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_DEBUG,
+ "FOUND NEW %s, add\n", bss->ssid);
+ clear_bss_descriptor(unsed);
+ memcpy(unsed, bss, offsetof(struct bss_descriptor, list));
+ }else { // do not have space
+ if(oldest) { // have oldest
+ printk("**FOUND NEW %s, no space, replace oldest %s\n",
+ bss->ssid, oldest->ssid);
+ clear_bss_descriptor(oldest);
+ memcpy(oldest, bss, offsetof(struct bss_descriptor, list));
+ }else if (bss_lower_rssi) { // have lower rssi
+ printk("**FOUND NEW %s, no space, replace low_rssi %s\n",
+ bss->ssid, bss_lower_rssi->ssid);
+ clear_bss_descriptor(bss_lower_rssi);
+ memcpy(bss_lower_rssi, bss, offsetof(struct bss_descriptor, list));
+ }else { // don't have oldest
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_CRIT, "Networklist Oldest is NULL\n");
+ }
+ }
+ }
+ spin_unlock(&priv->ScanListLock);
+ }
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("rda5890_network_information .\n");
+#endif
+ kfree(bss);
+ return;
+}
+
+void wlan_report_scan_result(wlan_private * priv)
+{
+ union iwreq_data wrqu;
+ ENTER();
+ priv->scan_running = WLAN_SCAN_COMPLET;
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(priv->netDev, SIOCGIWSCAN, &wrqu, NULL);
+ wlan_mod_timer(&priv->CardToSleepTimer, 100);
+ LEAVE();
+}
+