aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/assoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/assoc.c')
-rw-r--r--drivers/net/wireless/libertas/assoc.c744
1 files changed, 332 insertions, 412 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index a267d6e65f03..4ddf44b2758b 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -8,6 +8,7 @@
8#include "scan.h" 8#include "scan.h"
9#include "cmd.h" 9#include "cmd.h"
10 10
11static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp);
11 12
12static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = 13static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
13 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 14 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -20,12 +21,88 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
20#define CAPINFO_MASK (~(0xda00)) 21#define CAPINFO_MASK (~(0xda00))
21 22
22 23
24/**
25 * @brief This function finds common rates between rates and card rates.
26 *
27 * It will fill common rates in rates as output if found.
28 *
29 * NOTE: Setting the MSB of the basic rates need to be taken
30 * care, either before or after calling this function
31 *
32 * @param priv A pointer to struct lbs_private structure
33 * @param rates the buffer which keeps input and output
34 * @param rates_size the size of rate1 buffer; new size of buffer on return
35 *
36 * @return 0 on success, or -1 on error
37 */
38static int get_common_rates(struct lbs_private *priv,
39 u8 *rates,
40 u16 *rates_size)
41{
42 u8 *card_rates = lbs_bg_rates;
43 size_t num_card_rates = sizeof(lbs_bg_rates);
44 int ret = 0, i, j;
45 u8 tmp[30];
46 size_t tmp_size = 0;
47
48 /* For each rate in card_rates that exists in rate1, copy to tmp */
49 for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
50 for (j = 0; rates[j] && (j < *rates_size); j++) {
51 if (rates[j] == card_rates[i])
52 tmp[tmp_size++] = card_rates[i];
53 }
54 }
55
56 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
57 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
58 lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
59 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
60
61 if (!priv->enablehwauto) {
62 for (i = 0; i < tmp_size; i++) {
63 if (tmp[i] == priv->cur_rate)
64 goto done;
65 }
66 lbs_pr_alert("Previously set fixed data rate %#x isn't "
67 "compatible with the network.\n", priv->cur_rate);
68 ret = -1;
69 goto done;
70 }
71 ret = 0;
72
73done:
74 memset(rates, 0, *rates_size);
75 *rates_size = min_t(int, tmp_size, *rates_size);
76 memcpy(rates, tmp, *rates_size);
77 return ret;
78}
79
80
81/**
82 * @brief Sets the MSB on basic rates as the firmware requires
83 *
84 * Scan through an array and set the MSB for basic data rates.
85 *
86 * @param rates buffer of data rates
87 * @param len size of buffer
88 */
89static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
90{
91 int i;
92
93 for (i = 0; i < len; i++) {
94 if (rates[i] == 0x02 || rates[i] == 0x04 ||
95 rates[i] == 0x0b || rates[i] == 0x16)
96 rates[i] |= 0x80;
97 }
98}
99
23 100
24/** 101/**
25 * @brief Associate to a specific BSS discovered in a scan 102 * @brief Associate to a specific BSS discovered in a scan
26 * 103 *
27 * @param priv A pointer to struct lbs_private structure 104 * @param priv A pointer to struct lbs_private structure
28 * @param pbssdesc Pointer to the BSS descriptor to associate with. 105 * @param assoc_req The association request describing the BSS to associate with
29 * 106 *
30 * @return 0-success, otherwise fail 107 * @return 0-success, otherwise fail
31 */ 108 */
@@ -33,29 +110,29 @@ static int lbs_associate(struct lbs_private *priv,
33 struct assoc_request *assoc_req) 110 struct assoc_request *assoc_req)
34{ 111{
35 int ret; 112 int ret;
113 u8 preamble = RADIO_PREAMBLE_LONG;
36 114
37 lbs_deb_enter(LBS_DEB_ASSOC); 115 lbs_deb_enter(LBS_DEB_ASSOC);
38 116
39 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, 117 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
40 0, CMD_OPTION_WAITFORRSP, 118 0, CMD_OPTION_WAITFORRSP,
41 0, assoc_req->bss.bssid); 119 0, assoc_req->bss.bssid);
42
43 if (ret) 120 if (ret)
44 goto done; 121 goto out;
45 122
46 /* set preamble to firmware */ 123 /* Use short preamble only when both the BSS and firmware support it */
47 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && 124 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
48 (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) 125 (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
49 priv->preamble = CMD_TYPE_SHORT_PREAMBLE; 126 preamble = RADIO_PREAMBLE_SHORT;
50 else
51 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
52 127
53 lbs_set_radio_control(priv); 128 ret = lbs_set_radio(priv, preamble, 1);
129 if (ret)
130 goto out;
54 131
55 ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, 132 ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
56 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); 133 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
57 134
58done: 135out:
59 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 136 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
60 return ret; 137 return ret;
61} 138}
@@ -64,17 +141,22 @@ done:
64 * @brief Join an adhoc network found in a previous scan 141 * @brief Join an adhoc network found in a previous scan
65 * 142 *
66 * @param priv A pointer to struct lbs_private structure 143 * @param priv A pointer to struct lbs_private structure
67 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan 144 * @param assoc_req The association request describing the BSS to join
68 * to attempt to join
69 * 145 *
70 * @return 0--success, -1--fail 146 * @return 0 on success, error on failure
71 */ 147 */
72static int lbs_join_adhoc_network(struct lbs_private *priv, 148static int lbs_adhoc_join(struct lbs_private *priv,
73 struct assoc_request *assoc_req) 149 struct assoc_request *assoc_req)
74{ 150{
151 struct cmd_ds_802_11_ad_hoc_join cmd;
75 struct bss_descriptor *bss = &assoc_req->bss; 152 struct bss_descriptor *bss = &assoc_req->bss;
153 u8 preamble = RADIO_PREAMBLE_LONG;
154 DECLARE_MAC_BUF(mac);
155 u16 ratesize = 0;
76 int ret = 0; 156 int ret = 0;
77 157
158 lbs_deb_enter(LBS_DEB_ASSOC);
159
78 lbs_deb_join("current SSID '%s', ssid length %u\n", 160 lbs_deb_join("current SSID '%s', ssid length %u\n",
79 escape_essid(priv->curbssparams.ssid, 161 escape_essid(priv->curbssparams.ssid,
80 priv->curbssparams.ssid_len), 162 priv->curbssparams.ssid_len),
@@ -106,29 +188,106 @@ static int lbs_join_adhoc_network(struct lbs_private *priv,
106 goto out; 188 goto out;
107 } 189 }
108 190
109 /* Use shortpreamble only when both creator and card supports 191 /* Use short preamble only when both the BSS and firmware support it */
110 short preamble */ 192 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
111 if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) || 193 (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
112 !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
113 lbs_deb_join("AdhocJoin: Long preamble\n");
114 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
115 } else {
116 lbs_deb_join("AdhocJoin: Short preamble\n"); 194 lbs_deb_join("AdhocJoin: Short preamble\n");
117 priv->preamble = CMD_TYPE_SHORT_PREAMBLE; 195 preamble = RADIO_PREAMBLE_SHORT;
118 } 196 }
119 197
120 lbs_set_radio_control(priv); 198 ret = lbs_set_radio(priv, preamble, 1);
199 if (ret)
200 goto out;
121 201
122 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); 202 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
123 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); 203 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
124 204
125 priv->adhoccreate = 0; 205 priv->adhoccreate = 0;
206 priv->curbssparams.channel = bss->channel;
126 207
127 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN, 208 /* Build the join command */
128 0, CMD_OPTION_WAITFORRSP, 209 memset(&cmd, 0, sizeof(cmd));
129 OID_802_11_SSID, assoc_req); 210 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
211
212 cmd.bss.type = CMD_BSS_TYPE_IBSS;
213 cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
214
215 memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
216 memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
217
218 memcpy(&cmd.bss.phyparamset, &bss->phyparamset,
219 sizeof(union ieeetypes_phyparamset));
220
221 memcpy(&cmd.bss.ssparamset, &bss->ssparamset,
222 sizeof(union IEEEtypes_ssparamset));
223
224 cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
225 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
226 bss->capability, CAPINFO_MASK);
227
228 /* information on BSSID descriptor passed to FW */
229 lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
230 print_mac(mac, cmd.bss.bssid), cmd.bss.ssid);
231
232 /* Only v8 and below support setting these */
233 if (priv->fwrelease < 0x09000000) {
234 /* failtimeout */
235 cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
236 /* probedelay */
237 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
238 }
239
240 /* Copy Data rates from the rates recorded in scan response */
241 memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
242 ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES);
243 memcpy(cmd.bss.rates, bss->rates, ratesize);
244 if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
245 lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
246 ret = -1;
247 goto out;
248 }
249
250 /* Copy the ad-hoc creation rates into Current BSS state structure */
251 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
252 memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
253
254 /* Set MSB on basic rates as the firmware requires, but _after_
255 * copying to current bss rates.
256 */
257 lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
258
259 cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow);
260
261 if (assoc_req->secinfo.wep_enabled) {
262 u16 tmp = le16_to_cpu(cmd.bss.capability);
263 tmp |= WLAN_CAPABILITY_PRIVACY;
264 cmd.bss.capability = cpu_to_le16(tmp);
265 }
266
267 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
268 __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
269
270 /* wake up first */
271 ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
272 CMD_ACT_SET, 0, 0,
273 &local_ps_mode);
274 if (ret) {
275 ret = -1;
276 goto out;
277 }
278 }
279
280 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
281 ret = -1;
282 goto out;
283 }
284
285 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
286 if (ret == 0)
287 ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
130 288
131out: 289out:
290 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
132 return ret; 291 return ret;
133} 292}
134 293
@@ -136,39 +295,131 @@ out:
136 * @brief Start an Adhoc Network 295 * @brief Start an Adhoc Network
137 * 296 *
138 * @param priv A pointer to struct lbs_private structure 297 * @param priv A pointer to struct lbs_private structure
139 * @param adhocssid The ssid of the Adhoc Network 298 * @param assoc_req The association request describing the BSS to start
140 * @return 0--success, -1--fail 299 *
300 * @return 0 on success, error on failure
141 */ 301 */
142static int lbs_start_adhoc_network(struct lbs_private *priv, 302static int lbs_adhoc_start(struct lbs_private *priv,
143 struct assoc_request *assoc_req) 303 struct assoc_request *assoc_req)
144{ 304{
305 struct cmd_ds_802_11_ad_hoc_start cmd;
306 u8 preamble = RADIO_PREAMBLE_LONG;
307 size_t ratesize = 0;
308 u16 tmpcap = 0;
145 int ret = 0; 309 int ret = 0;
146 310
147 priv->adhoccreate = 1; 311 lbs_deb_enter(LBS_DEB_ASSOC);
148 312
149 if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { 313 if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
150 lbs_deb_join("AdhocStart: Short preamble\n"); 314 lbs_deb_join("ADHOC_START: Will use short preamble\n");
151 priv->preamble = CMD_TYPE_SHORT_PREAMBLE; 315 preamble = RADIO_PREAMBLE_SHORT;
152 } else {
153 lbs_deb_join("AdhocStart: Long preamble\n");
154 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
155 } 316 }
156 317
157 lbs_set_radio_control(priv); 318 ret = lbs_set_radio(priv, preamble, 1);
319 if (ret)
320 goto out;
158 321
159 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel); 322 /* Build the start command */
160 lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band); 323 memset(&cmd, 0, sizeof(cmd));
324 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
161 325
162 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START, 326 memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
163 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); 327
328 lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
329 escape_essid(assoc_req->ssid, assoc_req->ssid_len),
330 assoc_req->ssid_len);
164 331
332 cmd.bsstype = CMD_BSS_TYPE_IBSS;
333
334 if (priv->beacon_period == 0)
335 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
336 cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
337
338 WARN_ON(!assoc_req->channel);
339
340 /* set Physical parameter set */
341 cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET;
342 cmd.phyparamset.dsparamset.len = 1;
343 cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
344
345 /* set IBSS parameter set */
346 cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET;
347 cmd.ssparamset.ibssparamset.len = 2;
348 cmd.ssparamset.ibssparamset.atimwindow = 0;
349
350 /* set capability info */
351 tmpcap = WLAN_CAPABILITY_IBSS;
352 if (assoc_req->secinfo.wep_enabled) {
353 lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n");
354 tmpcap |= WLAN_CAPABILITY_PRIVACY;
355 } else
356 lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n");
357
358 cmd.capability = cpu_to_le16(tmpcap);
359
360 /* Only v8 and below support setting probe delay */
361 if (priv->fwrelease < 0x09000000)
362 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
363
364 ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
365 memcpy(cmd.rates, lbs_bg_rates, ratesize);
366
367 /* Copy the ad-hoc creating rates into Current BSS state structure */
368 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
369 memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
370
371 /* Set MSB on basic rates as the firmware requires, but _after_
372 * copying to current bss rates.
373 */
374 lbs_set_basic_rate_flags(cmd.rates, ratesize);
375
376 lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
377 cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
378
379 if (lbs_create_dnld_countryinfo_11d(priv)) {
380 lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
381 ret = -1;
382 goto out;
383 }
384
385 lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
386 assoc_req->channel, assoc_req->band);
387
388 priv->adhoccreate = 1;
389 priv->mode = IW_MODE_ADHOC;
390
391 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
392 if (ret == 0)
393 ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
394
395out:
396 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
165 return ret; 397 return ret;
166} 398}
167 399
168int lbs_stop_adhoc_network(struct lbs_private *priv) 400/**
401 * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
402 *
403 * @param priv A pointer to struct lbs_private structure
404 * @return 0 on success, or an error
405 */
406int lbs_adhoc_stop(struct lbs_private *priv)
169{ 407{
170 return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP, 408 struct cmd_ds_802_11_ad_hoc_stop cmd;
171 0, CMD_OPTION_WAITFORRSP, 0, NULL); 409 int ret;
410
411 lbs_deb_enter(LBS_DEB_JOIN);
412
413 memset(&cmd, 0, sizeof (cmd));
414 cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
415
416 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
417
418 /* Clean up everything even if there was an error */
419 lbs_mac_event_disconnected(priv);
420
421 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
422 return ret;
172} 423}
173 424
174static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, 425static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
@@ -480,14 +731,14 @@ static int assoc_helper_essid(struct lbs_private *priv,
480 if (bss != NULL) { 731 if (bss != NULL) {
481 lbs_deb_assoc("SSID found, will join\n"); 732 lbs_deb_assoc("SSID found, will join\n");
482 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); 733 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
483 lbs_join_adhoc_network(priv, assoc_req); 734 lbs_adhoc_join(priv, assoc_req);
484 } else { 735 } else {
485 /* else send START command */ 736 /* else send START command */
486 lbs_deb_assoc("SSID not found, creating adhoc network\n"); 737 lbs_deb_assoc("SSID not found, creating adhoc network\n");
487 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, 738 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
488 IW_ESSID_MAX_SIZE); 739 IW_ESSID_MAX_SIZE);
489 assoc_req->bss.ssid_len = assoc_req->ssid_len; 740 assoc_req->bss.ssid_len = assoc_req->ssid_len;
490 lbs_start_adhoc_network(priv, assoc_req); 741 lbs_adhoc_start(priv, assoc_req);
491 } 742 }
492 } 743 }
493 744
@@ -520,7 +771,7 @@ static int assoc_helper_bssid(struct lbs_private *priv,
520 ret = lbs_associate(priv, assoc_req); 771 ret = lbs_associate(priv, assoc_req);
521 lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); 772 lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
522 } else if (assoc_req->mode == IW_MODE_ADHOC) { 773 } else if (assoc_req->mode == IW_MODE_ADHOC) {
523 lbs_join_adhoc_network(priv, assoc_req); 774 lbs_adhoc_join(priv, assoc_req);
524 } 775 }
525 776
526out: 777out:
@@ -1029,7 +1280,9 @@ void lbs_association_worker(struct work_struct *work)
1029 */ 1280 */
1030 if (priv->mode == IW_MODE_INFRA) { 1281 if (priv->mode == IW_MODE_INFRA) {
1031 if (should_deauth_infrastructure(priv, assoc_req)) { 1282 if (should_deauth_infrastructure(priv, assoc_req)) {
1032 ret = lbs_send_deauthentication(priv); 1283 ret = lbs_cmd_80211_deauthenticate(priv,
1284 priv->curbssparams.bssid,
1285 WLAN_REASON_DEAUTH_LEAVING);
1033 if (ret) { 1286 if (ret) {
1034 lbs_deb_assoc("Deauthentication due to new " 1287 lbs_deb_assoc("Deauthentication due to new "
1035 "configuration request failed: %d\n", 1288 "configuration request failed: %d\n",
@@ -1038,7 +1291,7 @@ void lbs_association_worker(struct work_struct *work)
1038 } 1291 }
1039 } else if (priv->mode == IW_MODE_ADHOC) { 1292 } else if (priv->mode == IW_MODE_ADHOC) {
1040 if (should_stop_adhoc(priv, assoc_req)) { 1293 if (should_stop_adhoc(priv, assoc_req)) {
1041 ret = lbs_stop_adhoc_network(priv); 1294 ret = lbs_adhoc_stop(priv);
1042 if (ret) { 1295 if (ret) {
1043 lbs_deb_assoc("Teardown of AdHoc network due to " 1296 lbs_deb_assoc("Teardown of AdHoc network due to "
1044 "new configuration request failed: %d\n", 1297 "new configuration request failed: %d\n",
@@ -1214,94 +1467,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
1214 1467
1215 1468
1216/** 1469/**
1217 * @brief This function finds common rates between rate1 and card rates.
1218 *
1219 * It will fill common rates in rate1 as output if found.
1220 *
1221 * NOTE: Setting the MSB of the basic rates need to be taken
1222 * care, either before or after calling this function
1223 *
1224 * @param priv A pointer to struct lbs_private structure
1225 * @param rate1 the buffer which keeps input and output
1226 * @param rate1_size the size of rate1 buffer; new size of buffer on return
1227 *
1228 * @return 0 or -1
1229 */
1230static int get_common_rates(struct lbs_private *priv,
1231 u8 *rates,
1232 u16 *rates_size)
1233{
1234 u8 *card_rates = lbs_bg_rates;
1235 size_t num_card_rates = sizeof(lbs_bg_rates);
1236 int ret = 0, i, j;
1237 u8 tmp[30];
1238 size_t tmp_size = 0;
1239
1240 /* For each rate in card_rates that exists in rate1, copy to tmp */
1241 for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
1242 for (j = 0; rates[j] && (j < *rates_size); j++) {
1243 if (rates[j] == card_rates[i])
1244 tmp[tmp_size++] = card_rates[i];
1245 }
1246 }
1247
1248 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
1249 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
1250 lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
1251 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
1252
1253 if (!priv->enablehwauto) {
1254 for (i = 0; i < tmp_size; i++) {
1255 if (tmp[i] == priv->cur_rate)
1256 goto done;
1257 }
1258 lbs_pr_alert("Previously set fixed data rate %#x isn't "
1259 "compatible with the network.\n", priv->cur_rate);
1260 ret = -1;
1261 goto done;
1262 }
1263 ret = 0;
1264
1265done:
1266 memset(rates, 0, *rates_size);
1267 *rates_size = min_t(int, tmp_size, *rates_size);
1268 memcpy(rates, tmp, *rates_size);
1269 return ret;
1270}
1271
1272
1273/**
1274 * @brief Sets the MSB on basic rates as the firmware requires
1275 *
1276 * Scan through an array and set the MSB for basic data rates.
1277 *
1278 * @param rates buffer of data rates
1279 * @param len size of buffer
1280 */
1281static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
1282{
1283 int i;
1284
1285 for (i = 0; i < len; i++) {
1286 if (rates[i] == 0x02 || rates[i] == 0x04 ||
1287 rates[i] == 0x0b || rates[i] == 0x16)
1288 rates[i] |= 0x80;
1289 }
1290}
1291
1292/**
1293 * @brief Send Deauthentication Request
1294 *
1295 * @param priv A pointer to struct lbs_private structure
1296 * @return 0--success, -1--fail
1297 */
1298int lbs_send_deauthentication(struct lbs_private *priv)
1299{
1300 return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
1301 0, CMD_OPTION_WAITFORRSP, 0, NULL);
1302}
1303
1304/**
1305 * @brief This function prepares command of authenticate. 1470 * @brief This function prepares command of authenticate.
1306 * 1471 *
1307 * @param priv A pointer to struct lbs_private structure 1472 * @param priv A pointer to struct lbs_private structure
@@ -1353,26 +1518,37 @@ out:
1353 return ret; 1518 return ret;
1354} 1519}
1355 1520
1356int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, 1521/**
1357 struct cmd_ds_command *cmd) 1522 * @brief Deauthenticate from a specific BSS
1523 *
1524 * @param priv A pointer to struct lbs_private structure
1525 * @param bssid The specific BSS to deauthenticate from
1526 * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
1527 *
1528 * @return 0 on success, error on failure
1529 */
1530int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
1531 u16 reason)
1358{ 1532{
1359 struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; 1533 struct cmd_ds_802_11_deauthenticate cmd;
1534 int ret;
1360 1535
1361 lbs_deb_enter(LBS_DEB_JOIN); 1536 lbs_deb_enter(LBS_DEB_JOIN);
1362 1537
1363 cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE); 1538 memset(&cmd, 0, sizeof(cmd));
1364 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + 1539 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1365 S_DS_GEN); 1540 memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
1541 cmd.reasoncode = cpu_to_le16(reason);
1366 1542
1367 /* set AP MAC address */ 1543 ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
1368 memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
1369 1544
1370 /* Reason code 3 = Station is leaving */ 1545 /* Clean up everything even if there was an error; can't assume that
1371#define REASON_CODE_STA_LEAVING 3 1546 * we're still authenticated to the AP after trying to deauth.
1372 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); 1547 */
1548 lbs_mac_event_disconnected(priv);
1373 1549
1374 lbs_deb_leave(LBS_DEB_JOIN); 1550 lbs_deb_leave(LBS_DEB_JOIN);
1375 return 0; 1551 return ret;
1376} 1552}
1377 1553
1378int lbs_cmd_80211_associate(struct lbs_private *priv, 1554int lbs_cmd_80211_associate(struct lbs_private *priv,
@@ -1489,231 +1665,6 @@ done:
1489 return ret; 1665 return ret;
1490} 1666}
1491 1667
1492int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
1493 struct cmd_ds_command *cmd, void *pdata_buf)
1494{
1495 struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
1496 int ret = 0;
1497 int cmdappendsize = 0;
1498 struct assoc_request *assoc_req = pdata_buf;
1499 u16 tmpcap = 0;
1500 size_t ratesize = 0;
1501
1502 lbs_deb_enter(LBS_DEB_JOIN);
1503
1504 if (!priv) {
1505 ret = -1;
1506 goto done;
1507 }
1508
1509 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
1510
1511 /*
1512 * Fill in the parameters for 2 data structures:
1513 * 1. cmd_ds_802_11_ad_hoc_start command
1514 * 2. priv->scantable[i]
1515 *
1516 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
1517 * probe delay, and cap info.
1518 *
1519 * Firmware will fill up beacon period, DTIM, Basic rates
1520 * and operational rates.
1521 */
1522
1523 memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
1524 memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
1525
1526 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
1527 escape_essid(assoc_req->ssid, assoc_req->ssid_len),
1528 assoc_req->ssid_len);
1529
1530 /* set the BSS type */
1531 adhs->bsstype = CMD_BSS_TYPE_IBSS;
1532 priv->mode = IW_MODE_ADHOC;
1533 if (priv->beacon_period == 0)
1534 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
1535 adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
1536
1537 /* set Physical param set */
1538#define DS_PARA_IE_ID 3
1539#define DS_PARA_IE_LEN 1
1540
1541 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
1542 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
1543
1544 WARN_ON(!assoc_req->channel);
1545
1546 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
1547 assoc_req->channel);
1548
1549 adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
1550
1551 /* set IBSS param set */
1552#define IBSS_PARA_IE_ID 6
1553#define IBSS_PARA_IE_LEN 2
1554
1555 adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
1556 adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
1557 adhs->ssparamset.ibssparamset.atimwindow = 0;
1558
1559 /* set capability info */
1560 tmpcap = WLAN_CAPABILITY_IBSS;
1561 if (assoc_req->secinfo.wep_enabled) {
1562 lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
1563 "setting privacy on\n");
1564 tmpcap |= WLAN_CAPABILITY_PRIVACY;
1565 } else {
1566 lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
1567 "setting privacy off\n");
1568 }
1569 adhs->capability = cpu_to_le16(tmpcap);
1570
1571 /* probedelay */
1572 adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1573
1574 memset(adhs->rates, 0, sizeof(adhs->rates));
1575 ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
1576 memcpy(adhs->rates, lbs_bg_rates, ratesize);
1577
1578 /* Copy the ad-hoc creating rates into Current BSS state structure */
1579 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1580 memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
1581
1582 /* Set MSB on basic rates as the firmware requires, but _after_
1583 * copying to current bss rates.
1584 */
1585 lbs_set_basic_rate_flags(adhs->rates, ratesize);
1586
1587 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
1588 adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
1589
1590 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
1591
1592 if (lbs_create_dnld_countryinfo_11d(priv)) {
1593 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
1594 ret = -1;
1595 goto done;
1596 }
1597
1598 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
1599 S_DS_GEN + cmdappendsize);
1600
1601 ret = 0;
1602done:
1603 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1604 return ret;
1605}
1606
1607int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
1608{
1609 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
1610 cmd->size = cpu_to_le16(S_DS_GEN);
1611
1612 return 0;
1613}
1614
1615int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
1616 struct cmd_ds_command *cmd, void *pdata_buf)
1617{
1618 struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
1619 struct assoc_request *assoc_req = pdata_buf;
1620 struct bss_descriptor *bss = &assoc_req->bss;
1621 int cmdappendsize = 0;
1622 int ret = 0;
1623 u16 ratesize = 0;
1624 DECLARE_MAC_BUF(mac);
1625
1626 lbs_deb_enter(LBS_DEB_JOIN);
1627
1628 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
1629
1630 join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
1631 join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
1632
1633 memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
1634 memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
1635
1636 memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
1637 sizeof(union ieeetypes_phyparamset));
1638
1639 memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
1640 sizeof(union IEEEtypes_ssparamset));
1641
1642 join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
1643 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
1644 bss->capability, CAPINFO_MASK);
1645
1646 /* information on BSSID descriptor passed to FW */
1647 lbs_deb_join(
1648 "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
1649 print_mac(mac, join_cmd->bss.bssid),
1650 join_cmd->bss.ssid);
1651
1652 /* failtimeout */
1653 join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1654
1655 /* probedelay */
1656 join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1657
1658 priv->curbssparams.channel = bss->channel;
1659
1660 /* Copy Data rates from the rates recorded in scan response */
1661 memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
1662 ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
1663 memcpy(join_cmd->bss.rates, bss->rates, ratesize);
1664 if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
1665 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
1666 ret = -1;
1667 goto done;
1668 }
1669
1670 /* Copy the ad-hoc creating rates into Current BSS state structure */
1671 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1672 memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
1673
1674 /* Set MSB on basic rates as the firmware requires, but _after_
1675 * copying to current bss rates.
1676 */
1677 lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
1678
1679 join_cmd->bss.ssparamset.ibssparamset.atimwindow =
1680 cpu_to_le16(bss->atimwindow);
1681
1682 if (assoc_req->secinfo.wep_enabled) {
1683 u16 tmp = le16_to_cpu(join_cmd->bss.capability);
1684 tmp |= WLAN_CAPABILITY_PRIVACY;
1685 join_cmd->bss.capability = cpu_to_le16(tmp);
1686 }
1687
1688 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1689 /* wake up first */
1690 __le32 Localpsmode;
1691
1692 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1693 ret = lbs_prepare_and_send_command(priv,
1694 CMD_802_11_PS_MODE,
1695 CMD_ACT_SET,
1696 0, 0, &Localpsmode);
1697
1698 if (ret) {
1699 ret = -1;
1700 goto done;
1701 }
1702 }
1703
1704 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
1705 ret = -1;
1706 goto done;
1707 }
1708
1709 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
1710 S_DS_GEN + cmdappendsize);
1711
1712done:
1713 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1714 return ret;
1715}
1716
1717int lbs_ret_80211_associate(struct lbs_private *priv, 1668int lbs_ret_80211_associate(struct lbs_private *priv,
1718 struct cmd_ds_command *resp) 1669 struct cmd_ds_command *resp)
1719{ 1670{
@@ -1815,34 +1766,19 @@ done:
1815 return ret; 1766 return ret;
1816} 1767}
1817 1768
1818int lbs_ret_80211_disassociate(struct lbs_private *priv) 1769static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
1819{
1820 lbs_deb_enter(LBS_DEB_JOIN);
1821
1822 lbs_mac_event_disconnected(priv);
1823
1824 lbs_deb_leave(LBS_DEB_JOIN);
1825 return 0;
1826}
1827
1828int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1829 struct cmd_ds_command *resp)
1830{ 1770{
1831 int ret = 0; 1771 int ret = 0;
1832 u16 command = le16_to_cpu(resp->command); 1772 u16 command = le16_to_cpu(resp->command);
1833 u16 result = le16_to_cpu(resp->result); 1773 u16 result = le16_to_cpu(resp->result);
1834 struct cmd_ds_802_11_ad_hoc_result *padhocresult; 1774 struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
1835 union iwreq_data wrqu; 1775 union iwreq_data wrqu;
1836 struct bss_descriptor *bss; 1776 struct bss_descriptor *bss;
1837 DECLARE_MAC_BUF(mac); 1777 DECLARE_MAC_BUF(mac);
1838 1778
1839 lbs_deb_enter(LBS_DEB_JOIN); 1779 lbs_deb_enter(LBS_DEB_JOIN);
1840 1780
1841 padhocresult = &resp->params.result; 1781 adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp;
1842
1843 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
1844 lbs_deb_join("ADHOC_RESP: command = %x\n", command);
1845 lbs_deb_join("ADHOC_RESP: result = %x\n", result);
1846 1782
1847 if (!priv->in_progress_assoc_req) { 1783 if (!priv->in_progress_assoc_req) {
1848 lbs_deb_join("ADHOC_RESP: no in-progress association " 1784 lbs_deb_join("ADHOC_RESP: no in-progress association "
@@ -1856,26 +1792,19 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1856 * Join result code 0 --> SUCCESS 1792 * Join result code 0 --> SUCCESS
1857 */ 1793 */
1858 if (result) { 1794 if (result) {
1859 lbs_deb_join("ADHOC_RESP: failed\n"); 1795 lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
1860 if (priv->connect_status == LBS_CONNECTED) 1796 if (priv->connect_status == LBS_CONNECTED)
1861 lbs_mac_event_disconnected(priv); 1797 lbs_mac_event_disconnected(priv);
1862 ret = -1; 1798 ret = -1;
1863 goto done; 1799 goto done;
1864 } 1800 }
1865 1801
1866 /*
1867 * Now the join cmd should be successful
1868 * If BSSID has changed use SSID to compare instead of BSSID
1869 */
1870 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
1871 escape_essid(bss->ssid, bss->ssid_len));
1872
1873 /* Send a Media Connected event, according to the Spec */ 1802 /* Send a Media Connected event, according to the Spec */
1874 priv->connect_status = LBS_CONNECTED; 1803 priv->connect_status = LBS_CONNECTED;
1875 1804
1876 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { 1805 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
1877 /* Update the created network descriptor with the new BSSID */ 1806 /* Update the created network descriptor with the new BSSID */
1878 memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN); 1807 memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN);
1879 } 1808 }
1880 1809
1881 /* Set the BSSID from the joined/started descriptor */ 1810 /* Set the BSSID from the joined/started descriptor */
@@ -1894,22 +1823,13 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1894 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 1823 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1895 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); 1824 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1896 1825
1897 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); 1826 lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n",
1898 lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel); 1827 escape_essid(bss->ssid, bss->ssid_len),
1899 lbs_deb_join("ADHOC_RESP: BSSID = %s\n", 1828 print_mac(mac, priv->curbssparams.bssid),
1900 print_mac(mac, padhocresult->bssid)); 1829 priv->curbssparams.channel);
1901 1830
1902done: 1831done:
1903 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); 1832 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1904 return ret; 1833 return ret;
1905} 1834}
1906 1835
1907int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
1908{
1909 lbs_deb_enter(LBS_DEB_JOIN);
1910
1911 lbs_mac_event_disconnected(priv);
1912
1913 lbs_deb_leave(LBS_DEB_JOIN);
1914 return 0;
1915}