aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2008-04-02 10:27:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:40 -0400
commit245bf20f9c159f8d35befbc038997096b759459c (patch)
treeefa49f9090e2933689140d8725d1bbcbcafb7f8c /drivers/net/wireless/libertas/scan.c
parent697900ac14528e985b66f471ecb81082fc00baa9 (diff)
libertas: move association code from scan.c into assoc.c
Besides code moving, I did the following changes: * made some functions static * removed some unneeded #include's * made patch checkpatch.pl clean Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r--drivers/net/wireless/libertas/scan.c364
1 files changed, 1 insertions, 363 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 1c7003d7de43..e72c97a0d6c1 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,22 +4,13 @@
4 * IOCTL handlers as well as command preperation and response routines 4 * IOCTL handlers as well as command preperation and response routines
5 * for sending scan commands to the firmware. 5 * for sending scan commands to the firmware.
6 */ 6 */
7#include <linux/ctype.h>
8#include <linux/if.h>
9#include <linux/netdevice.h>
10#include <linux/wireless.h>
11#include <linux/etherdevice.h> 7#include <linux/etherdevice.h>
12
13#include <net/ieee80211.h>
14#include <net/iw_handler.h>
15
16#include <asm/unaligned.h> 8#include <asm/unaligned.h>
17 9
18#include "host.h" 10#include "host.h"
19#include "decl.h" 11#include "decl.h"
20#include "dev.h" 12#include "dev.h"
21#include "scan.h" 13#include "scan.h"
22#include "assoc.h"
23#include "cmd.h" 14#include "cmd.h"
24 15
25//! Approximate amount of data needed to pass a scan result back to iwlist 16//! Approximate amount of data needed to pass a scan result back to iwlist
@@ -110,69 +101,6 @@ int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
110 return memcmp(ssid1, ssid2, ssid1_len); 101 return memcmp(ssid1, ssid2, ssid1_len);
111} 102}
112 103
113static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
114 struct bss_descriptor *match_bss)
115{
116 if (!secinfo->wep_enabled && !secinfo->WPAenabled
117 && !secinfo->WPA2enabled
118 && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
119 && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
120 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
121 return 1;
122 else
123 return 0;
124}
125
126static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
127 struct bss_descriptor *match_bss)
128{
129 if (secinfo->wep_enabled && !secinfo->WPAenabled
130 && !secinfo->WPA2enabled
131 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
132 return 1;
133 else
134 return 0;
135}
136
137static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
138 struct bss_descriptor *match_bss)
139{
140 if (!secinfo->wep_enabled && secinfo->WPAenabled
141 && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
142 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
143 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
144 )
145 return 1;
146 else
147 return 0;
148}
149
150static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
151 struct bss_descriptor *match_bss)
152{
153 if (!secinfo->wep_enabled && secinfo->WPA2enabled
154 && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
155 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
156 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
157 )
158 return 1;
159 else
160 return 0;
161}
162
163static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
164 struct bss_descriptor *match_bss)
165{
166 if (!secinfo->wep_enabled && !secinfo->WPAenabled
167 && !secinfo->WPA2enabled
168 && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
169 && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
170 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
171 return 1;
172 else
173 return 0;
174}
175
176static inline int is_same_network(struct bss_descriptor *src, 104static inline int is_same_network(struct bss_descriptor *src,
177 struct bss_descriptor *dst) 105 struct bss_descriptor *dst)
178{ 106{
@@ -185,78 +113,6 @@ static inline int is_same_network(struct bss_descriptor *src,
185 !memcmp(src->ssid, dst->ssid, src->ssid_len)); 113 !memcmp(src->ssid, dst->ssid, src->ssid_len));
186} 114}
187 115
188/**
189 * @brief Check if a scanned network compatible with the driver settings
190 *
191 * WEP WPA WPA2 ad-hoc encrypt Network
192 * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
193 * 0 0 0 0 NONE 0 0 0 yes No security
194 * 1 0 0 0 NONE 1 0 0 yes Static WEP
195 * 0 1 0 0 x 1x 1 x yes WPA
196 * 0 0 1 0 x 1x x 1 yes WPA2
197 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
198 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
199 *
200 *
201 * @param priv A pointer to struct lbs_private
202 * @param index Index in scantable to check against current driver settings
203 * @param mode Network mode: Infrastructure or IBSS
204 *
205 * @return Index in scantable, or error code if negative
206 */
207static int is_network_compatible(struct lbs_private *priv,
208 struct bss_descriptor *bss, uint8_t mode)
209{
210 int matched = 0;
211
212 lbs_deb_enter(LBS_DEB_SCAN);
213
214 if (bss->mode != mode)
215 goto done;
216
217 if ((matched = match_bss_no_security(&priv->secinfo, bss))) {
218 goto done;
219 } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) {
220 goto done;
221 } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) {
222 lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
223 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
224 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
225 priv->secinfo.wep_enabled ? "e" : "d",
226 priv->secinfo.WPAenabled ? "e" : "d",
227 priv->secinfo.WPA2enabled ? "e" : "d",
228 (bss->capability & WLAN_CAPABILITY_PRIVACY));
229 goto done;
230 } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) {
231 lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
232 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
233 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
234 priv->secinfo.wep_enabled ? "e" : "d",
235 priv->secinfo.WPAenabled ? "e" : "d",
236 priv->secinfo.WPA2enabled ? "e" : "d",
237 (bss->capability & WLAN_CAPABILITY_PRIVACY));
238 goto done;
239 } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) {
240 lbs_deb_scan("is_network_compatible() dynamic WEP: "
241 "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
242 bss->wpa_ie[0], bss->rsn_ie[0],
243 (bss->capability & WLAN_CAPABILITY_PRIVACY));
244 goto done;
245 }
246
247 /* bss security settings don't match those configured on card */
248 lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
249 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
250 bss->wpa_ie[0], bss->rsn_ie[0],
251 priv->secinfo.wep_enabled ? "e" : "d",
252 priv->secinfo.WPAenabled ? "e" : "d",
253 priv->secinfo.WPA2enabled ? "e" : "d",
254 (bss->capability & WLAN_CAPABILITY_PRIVACY));
255
256done:
257 lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
258 return matched;
259}
260 116
261 117
262 118
@@ -341,7 +197,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
341 return chanidx; 197 return chanidx;
342} 198}
343 199
344
345/* 200/*
346 * Add SSID TLV of the form: 201 * Add SSID TLV of the form:
347 * 202 *
@@ -359,7 +214,6 @@ static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
359 return sizeof(ssid_tlv->header) + priv->scan_ssid_len; 214 return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
360} 215}
361 216
362
363/* 217/*
364 * Add CHANLIST TLV of the form 218 * Add CHANLIST TLV of the form
365 * 219 *
@@ -398,7 +252,6 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
398 return sizeof(chan_tlv->header) + size; 252 return sizeof(chan_tlv->header) + size;
399} 253}
400 254
401
402/* 255/*
403 * Add RATES TLV of the form 256 * Add RATES TLV of the form
404 * 257 *
@@ -433,7 +286,6 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv)
433 return sizeof(rate_tlv->header) + i; 286 return sizeof(rate_tlv->header) + i;
434} 287}
435 288
436
437/* 289/*
438 * Generate the CMD_802_11_SCAN command with the proper tlv 290 * Generate the CMD_802_11_SCAN command with the proper tlv
439 * for a bunch of channels. 291 * for a bunch of channels.
@@ -482,12 +334,9 @@ out:
482 return ret; 334 return ret;
483} 335}
484 336
485
486/** 337/**
487 * @brief Internal function used to start a scan based on an input config 338 * @brief Internal function used to start a scan based on an input config
488 * 339 *
489 * Also used from debugfs
490 *
491 * Use the input user scan configuration information when provided in 340 * Use the input user scan configuration information when provided in
492 * order to send the appropriate scan commands to firmware to populate or 341 * order to send the appropriate scan commands to firmware to populate or
493 * update the internal driver scan table 342 * update the internal driver scan table
@@ -497,7 +346,7 @@ out:
497 * 346 *
498 * @return 0 or < 0 if error 347 * @return 0 or < 0 if error
499 */ 348 */
500static int lbs_scan_networks(struct lbs_private *priv, int full_scan) 349int lbs_scan_networks(struct lbs_private *priv, int full_scan)
501{ 350{
502 int ret = -ENOMEM; 351 int ret = -ENOMEM;
503 struct chanscanparamset *chan_list; 352 struct chanscanparamset *chan_list;
@@ -627,9 +476,6 @@ out:
627 return ret; 476 return ret;
628} 477}
629 478
630
631
632
633void lbs_scan_worker(struct work_struct *work) 479void lbs_scan_worker(struct work_struct *work)
634{ 480{
635 struct lbs_private *priv = 481 struct lbs_private *priv =
@@ -881,214 +727,6 @@ done:
881} 727}
882 728
883/** 729/**
884 * @brief This function finds a specific compatible BSSID in the scan list
885 *
886 * Used in association code
887 *
888 * @param priv A pointer to struct lbs_private
889 * @param bssid BSSID to find in the scan list
890 * @param mode Network mode: Infrastructure or IBSS
891 *
892 * @return index in BSSID list, or error return code (< 0)
893 */
894struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
895 uint8_t *bssid, uint8_t mode)
896{
897 struct bss_descriptor *iter_bss;
898 struct bss_descriptor *found_bss = NULL;
899
900 lbs_deb_enter(LBS_DEB_SCAN);
901
902 if (!bssid)
903 goto out;
904
905 lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
906
907 /* Look through the scan table for a compatible match. The loop will
908 * continue past a matched bssid that is not compatible in case there
909 * is an AP with multiple SSIDs assigned to the same BSSID
910 */
911 mutex_lock(&priv->lock);
912 list_for_each_entry (iter_bss, &priv->network_list, list) {
913 if (compare_ether_addr(iter_bss->bssid, bssid))
914 continue; /* bssid doesn't match */
915 switch (mode) {
916 case IW_MODE_INFRA:
917 case IW_MODE_ADHOC:
918 if (!is_network_compatible(priv, iter_bss, mode))
919 break;
920 found_bss = iter_bss;
921 break;
922 default:
923 found_bss = iter_bss;
924 break;
925 }
926 }
927 mutex_unlock(&priv->lock);
928
929out:
930 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
931 return found_bss;
932}
933
934/**
935 * @brief This function finds ssid in ssid list.
936 *
937 * Used in association code
938 *
939 * @param priv A pointer to struct lbs_private
940 * @param ssid SSID to find in the list
941 * @param bssid BSSID to qualify the SSID selection (if provided)
942 * @param mode Network mode: Infrastructure or IBSS
943 *
944 * @return index in BSSID list
945 */
946struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
947 uint8_t *ssid, uint8_t ssid_len,
948 uint8_t *bssid, uint8_t mode,
949 int channel)
950{
951 u32 bestrssi = 0;
952 struct bss_descriptor * iter_bss = NULL;
953 struct bss_descriptor * found_bss = NULL;
954 struct bss_descriptor * tmp_oldest = NULL;
955
956 lbs_deb_enter(LBS_DEB_SCAN);
957
958 mutex_lock(&priv->lock);
959
960 list_for_each_entry (iter_bss, &priv->network_list, list) {
961 if ( !tmp_oldest
962 || (iter_bss->last_scanned < tmp_oldest->last_scanned))
963 tmp_oldest = iter_bss;
964
965 if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
966 ssid, ssid_len) != 0)
967 continue; /* ssid doesn't match */
968 if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
969 continue; /* bssid doesn't match */
970 if ((channel > 0) && (iter_bss->channel != channel))
971 continue; /* channel doesn't match */
972
973 switch (mode) {
974 case IW_MODE_INFRA:
975 case IW_MODE_ADHOC:
976 if (!is_network_compatible(priv, iter_bss, mode))
977 break;
978
979 if (bssid) {
980 /* Found requested BSSID */
981 found_bss = iter_bss;
982 goto out;
983 }
984
985 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
986 bestrssi = SCAN_RSSI(iter_bss->rssi);
987 found_bss = iter_bss;
988 }
989 break;
990 case IW_MODE_AUTO:
991 default:
992 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
993 bestrssi = SCAN_RSSI(iter_bss->rssi);
994 found_bss = iter_bss;
995 }
996 break;
997 }
998 }
999
1000out:
1001 mutex_unlock(&priv->lock);
1002 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
1003 return found_bss;
1004}
1005
1006/**
1007 * @brief This function finds the best SSID in the Scan List
1008 *
1009 * Search the scan table for the best SSID that also matches the current
1010 * adapter network preference (infrastructure or adhoc)
1011 *
1012 * @param priv A pointer to struct lbs_private
1013 *
1014 * @return index in BSSID list
1015 */
1016static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *priv,
1017 uint8_t mode)
1018{
1019 uint8_t bestrssi = 0;
1020 struct bss_descriptor *iter_bss;
1021 struct bss_descriptor *best_bss = NULL;
1022
1023 lbs_deb_enter(LBS_DEB_SCAN);
1024
1025 mutex_lock(&priv->lock);
1026
1027 list_for_each_entry (iter_bss, &priv->network_list, list) {
1028 switch (mode) {
1029 case IW_MODE_INFRA:
1030 case IW_MODE_ADHOC:
1031 if (!is_network_compatible(priv, iter_bss, mode))
1032 break;
1033 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1034 break;
1035 bestrssi = SCAN_RSSI(iter_bss->rssi);
1036 best_bss = iter_bss;
1037 break;
1038 case IW_MODE_AUTO:
1039 default:
1040 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1041 break;
1042 bestrssi = SCAN_RSSI(iter_bss->rssi);
1043 best_bss = iter_bss;
1044 break;
1045 }
1046 }
1047
1048 mutex_unlock(&priv->lock);
1049 lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
1050 return best_bss;
1051}
1052
1053/**
1054 * @brief Find the best AP
1055 *
1056 * Used from association worker.
1057 *
1058 * @param priv A pointer to struct lbs_private structure
1059 * @param pSSID A pointer to AP's ssid
1060 *
1061 * @return 0--success, otherwise--fail
1062 */
1063int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid,
1064 uint8_t *out_ssid_len, uint8_t preferred_mode,
1065 uint8_t *out_mode)
1066{
1067 int ret = -1;
1068 struct bss_descriptor *found;
1069
1070 lbs_deb_enter(LBS_DEB_SCAN);
1071
1072 priv->scan_ssid_len = 0;
1073 lbs_scan_networks(priv, 1);
1074 if (priv->surpriseremoved)
1075 goto out;
1076
1077 found = lbs_find_best_ssid_in_list(priv, preferred_mode);
1078 if (found && (found->ssid_len > 0)) {
1079 memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
1080 *out_ssid_len = found->ssid_len;
1081 *out_mode = found->mode;
1082 ret = 0;
1083 }
1084
1085out:
1086 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
1087 return ret;
1088}
1089
1090
1091/**
1092 * @brief Send a scan command for all available channels filtered on a spec 730 * @brief Send a scan command for all available channels filtered on a spec
1093 * 731 *
1094 * Used in association code and from debugfs 732 * Used in association code and from debugfs