[PATCH] libertas: move channel changing into association framework
[deliverable/linux.git] / drivers / net / wireless / libertas / join.c
1 /**
2 * Functions implementing wlan infrastructure and adhoc join routines,
3 * IOCTL handlers as well as command preperation and response routines
4 * for sending adhoc start, adhoc join, and association commands
5 * to the firmware.
6 */
7 #include <linux/netdevice.h>
8 #include <linux/if_arp.h>
9 #include <linux/wireless.h>
10
11 #include <net/iw_handler.h>
12
13 #include "host.h"
14 #include "decl.h"
15 #include "join.h"
16 #include "dev.h"
17
18 #define AD_HOC_CAP_PRIVACY_ON 1
19
20 /**
21 * @brief This function finds out the common rates between rate1 and rate2.
22 *
23 * It will fill common rates in rate1 as output if found.
24 *
25 * NOTE: Setting the MSB of the basic rates need to be taken
26 * care, either before or after calling this function
27 *
28 * @param adapter A pointer to wlan_adapter structure
29 * @param rate1 the buffer which keeps input and output
30 * @param rate1_size the size of rate1 buffer
31 * @param rate2 the buffer which keeps rate2
32 * @param rate2_size the size of rate2 buffer.
33 *
34 * @return 0 or -1
35 */
36 static int get_common_rates(wlan_adapter * adapter, u8 * rate1,
37 int rate1_size, u8 * rate2, int rate2_size)
38 {
39 u8 *ptr = rate1;
40 int ret = 0;
41 u8 tmp[30];
42 int i;
43
44 memset(&tmp, 0, sizeof(tmp));
45 memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp)));
46 memset(rate1, 0, rate1_size);
47
48 /* Mask the top bit of the original values */
49 for (i = 0; tmp[i] && i < sizeof(tmp); i++)
50 tmp[i] &= 0x7F;
51
52 for (i = 0; rate2[i] && i < rate2_size; i++) {
53 /* Check for Card Rate in tmp, excluding the top bit */
54 if (strchr(tmp, rate2[i] & 0x7F)) {
55 /* values match, so copy the Card Rate to rate1 */
56 *rate1++ = rate2[i];
57 }
58 }
59
60 lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp));
61 lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size);
62 lbs_dbg_hex("Common rates:", ptr, rate1_size);
63 lbs_deb_join("Tx datarate is set to 0x%X\n", adapter->datarate);
64
65 if (!adapter->is_datarate_auto) {
66 while (*ptr) {
67 if ((*ptr & 0x7f) == adapter->datarate) {
68 ret = 0;
69 goto done;
70 }
71 ptr++;
72 }
73 lbs_pr_alert( "Previously set fixed data rate %#x isn't "
74 "compatible with the network.\n", adapter->datarate);
75
76 ret = -1;
77 goto done;
78 }
79
80 ret = 0;
81 done:
82 return ret;
83 }
84
85 int libertas_send_deauth(wlan_private * priv)
86 {
87 wlan_adapter *adapter = priv->adapter;
88 int ret = 0;
89
90 if (adapter->mode == IW_MODE_INFRA &&
91 adapter->connect_status == libertas_connected)
92 ret = libertas_send_deauthentication(priv);
93 else
94 ret = -ENOTSUPP;
95
96 return ret;
97 }
98
99 /**
100 * @brief Associate to a specific BSS discovered in a scan
101 *
102 * @param priv A pointer to wlan_private structure
103 * @param pbssdesc Pointer to the BSS descriptor to associate with.
104 *
105 * @return 0-success, otherwise fail
106 */
107 int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
108 {
109 wlan_adapter *adapter = priv->adapter;
110 int ret;
111
112 lbs_deb_enter(LBS_DEB_JOIN);
113
114 ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate,
115 0, cmd_option_waitforrsp,
116 0, pbssdesc->bssid);
117
118 if (ret)
119 goto done;
120
121 /* set preamble to firmware */
122 if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble)
123 adapter->preamble = cmd_type_short_preamble;
124 else
125 adapter->preamble = cmd_type_long_preamble;
126
127 libertas_set_radio_control(priv);
128
129 ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate,
130 0, cmd_option_waitforrsp, 0, pbssdesc);
131
132 done:
133 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
134 return ret;
135 }
136
137 /**
138 * @brief Start an Adhoc Network
139 *
140 * @param priv A pointer to wlan_private structure
141 * @param adhocssid The ssid of the Adhoc Network
142 * @return 0--success, -1--fail
143 */
144 int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid)
145 {
146 wlan_adapter *adapter = priv->adapter;
147 int ret = 0;
148
149 adapter->adhoccreate = 1;
150
151 if (!adapter->capinfo.shortpreamble) {
152 lbs_deb_join("AdhocStart: Long preamble\n");
153 adapter->preamble = cmd_type_long_preamble;
154 } else {
155 lbs_deb_join("AdhocStart: Short preamble\n");
156 adapter->preamble = cmd_type_short_preamble;
157 }
158
159 libertas_set_radio_control(priv);
160
161 lbs_deb_join("curbssparams.channel = %d\n",
162 adapter->curbssparams.channel);
163 lbs_deb_join("curbssparams.band = %d\n", adapter->curbssparams.band);
164
165 ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start,
166 0, cmd_option_waitforrsp, 0, adhocssid);
167
168 return ret;
169 }
170
171 /**
172 * @brief Join an adhoc network found in a previous scan
173 *
174 * @param priv A pointer to wlan_private structure
175 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
176 * to attempt to join
177 *
178 * @return 0--success, -1--fail
179 */
180 int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc)
181 {
182 wlan_adapter *adapter = priv->adapter;
183 int ret = 0;
184
185 lbs_deb_join("libertas_join_adhoc_network: CurBss.ssid =%s\n",
186 adapter->curbssparams.ssid.ssid);
187 lbs_deb_join("libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
188 adapter->curbssparams.ssid.ssidlength);
189 lbs_deb_join("libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid);
190 lbs_deb_join("libertas_join_adhoc_network: ssid len =%u\n",
191 pbssdesc->ssid.ssidlength);
192
193 /* check if the requested SSID is already joined */
194 if (adapter->curbssparams.ssid.ssidlength
195 && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid)
196 && (adapter->mode == IW_MODE_ADHOC)) {
197
198 lbs_deb_join(
199 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
200 "not attempting to re-join");
201
202 return -1;
203 }
204
205 /*Use shortpreamble only when both creator and card supports
206 short preamble */
207 if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
208 lbs_deb_join("AdhocJoin: Long preamble\n");
209 adapter->preamble = cmd_type_long_preamble;
210 } else {
211 lbs_deb_join("AdhocJoin: Short preamble\n");
212 adapter->preamble = cmd_type_short_preamble;
213 }
214
215 libertas_set_radio_control(priv);
216
217 lbs_deb_join("curbssparams.channel = %d\n",
218 adapter->curbssparams.channel);
219 lbs_deb_join("curbssparams.band = %c\n", adapter->curbssparams.band);
220
221 adapter->adhoccreate = 0;
222
223 ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join,
224 0, cmd_option_waitforrsp,
225 OID_802_11_SSID, pbssdesc);
226
227 return ret;
228 }
229
230 int libertas_stop_adhoc_network(wlan_private * priv)
231 {
232 return libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_stop,
233 0, cmd_option_waitforrsp, 0, NULL);
234 }
235
236 /**
237 * @brief Send Deauthentication Request
238 *
239 * @param priv A pointer to wlan_private structure
240 * @return 0--success, -1--fail
241 */
242 int libertas_send_deauthentication(wlan_private * priv)
243 {
244 return libertas_prepare_and_send_command(priv, cmd_802_11_deauthenticate,
245 0, cmd_option_waitforrsp, 0, NULL);
246 }
247
248 /**
249 * @brief This function prepares command of authenticate.
250 *
251 * @param priv A pointer to wlan_private structure
252 * @param cmd A pointer to cmd_ds_command structure
253 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
254 *
255 * @return 0 or -1
256 */
257 int libertas_cmd_80211_authenticate(wlan_private * priv,
258 struct cmd_ds_command *cmd,
259 void *pdata_buf)
260 {
261 wlan_adapter *adapter = priv->adapter;
262 struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
263 int ret = -1;
264 u8 *bssid = pdata_buf;
265
266 cmd->command = cpu_to_le16(cmd_802_11_authenticate);
267 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
268 + S_DS_GEN);
269
270 /* translate auth mode to 802.11 defined wire value */
271 switch (adapter->secinfo.auth_mode) {
272 case IW_AUTH_ALG_OPEN_SYSTEM:
273 pauthenticate->authtype = 0x00;
274 break;
275 case IW_AUTH_ALG_SHARED_KEY:
276 pauthenticate->authtype = 0x01;
277 break;
278 case IW_AUTH_ALG_LEAP:
279 pauthenticate->authtype = 0x80;
280 break;
281 default:
282 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
283 adapter->secinfo.auth_mode);
284 goto out;
285 }
286
287 memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
288
289 lbs_deb_join("AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
290 bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
291 ret = 0;
292
293 out:
294 return ret;
295 }
296
297 int libertas_cmd_80211_deauthenticate(wlan_private * priv,
298 struct cmd_ds_command *cmd)
299 {
300 wlan_adapter *adapter = priv->adapter;
301 struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
302
303 lbs_deb_enter(LBS_DEB_JOIN);
304
305 cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
306 cmd->size =
307 cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
308 S_DS_GEN);
309
310 /* set AP MAC address */
311 memmove(dauth->macaddr, adapter->curbssparams.bssid,
312 ETH_ALEN);
313
314 /* Reason code 3 = Station is leaving */
315 #define REASON_CODE_STA_LEAVING 3
316 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
317
318 lbs_deb_leave(LBS_DEB_JOIN);
319 return 0;
320 }
321
322 int libertas_cmd_80211_associate(wlan_private * priv,
323 struct cmd_ds_command *cmd, void *pdata_buf)
324 {
325 wlan_adapter *adapter = priv->adapter;
326 struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
327 int ret = 0;
328 struct bss_descriptor *pbssdesc;
329 u8 *card_rates;
330 u8 *pos;
331 int card_rates_size;
332 u16 tmpcap;
333 struct mrvlietypes_ssidparamset *ssid;
334 struct mrvlietypes_phyparamset *phy;
335 struct mrvlietypes_ssparamset *ss;
336 struct mrvlietypes_ratesparamset *rates;
337 struct mrvlietypes_rsnparamset *rsn;
338
339 lbs_deb_enter(LBS_DEB_JOIN);
340
341 pbssdesc = pdata_buf;
342 pos = (u8 *) passo;
343
344 if (!adapter) {
345 ret = -1;
346 goto done;
347 }
348
349 cmd->command = cpu_to_le16(cmd_802_11_associate);
350
351 /* Save so we know which BSS Desc to use in the response handler */
352 adapter->pattemptedbssdesc = pbssdesc;
353
354 memcpy(passo->peerstaaddr,
355 pbssdesc->bssid, sizeof(passo->peerstaaddr));
356 pos += sizeof(passo->peerstaaddr);
357
358 /* set the listen interval */
359 passo->listeninterval = adapter->listeninterval;
360
361 pos += sizeof(passo->capinfo);
362 pos += sizeof(passo->listeninterval);
363 pos += sizeof(passo->bcnperiod);
364 pos += sizeof(passo->dtimperiod);
365
366 ssid = (struct mrvlietypes_ssidparamset *) pos;
367 ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
368 ssid->header.len = pbssdesc->ssid.ssidlength;
369 memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
370 pos += sizeof(ssid->header) + ssid->header.len;
371 ssid->header.len = cpu_to_le16(ssid->header.len);
372
373 phy = (struct mrvlietypes_phyparamset *) pos;
374 phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
375 phy->header.len = sizeof(phy->fh_ds.dsparamset);
376 memcpy(&phy->fh_ds.dsparamset,
377 &pbssdesc->phyparamset.dsparamset.currentchan,
378 sizeof(phy->fh_ds.dsparamset));
379 pos += sizeof(phy->header) + phy->header.len;
380 phy->header.len = cpu_to_le16(phy->header.len);
381
382 ss = (struct mrvlietypes_ssparamset *) pos;
383 ss->header.type = cpu_to_le16(TLV_TYPE_CF);
384 ss->header.len = sizeof(ss->cf_ibss.cfparamset);
385 pos += sizeof(ss->header) + ss->header.len;
386 ss->header.len = cpu_to_le16(ss->header.len);
387
388 rates = (struct mrvlietypes_ratesparamset *) pos;
389 rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
390
391 memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
392
393 card_rates = libertas_supported_rates;
394 card_rates_size = sizeof(libertas_supported_rates);
395
396 if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES,
397 card_rates, card_rates_size)) {
398 ret = -1;
399 goto done;
400 }
401
402 rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
403 adapter->curbssparams.numofrates = rates->header.len;
404
405 pos += sizeof(rates->header) + rates->header.len;
406 rates->header.len = cpu_to_le16(rates->header.len);
407
408 if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
409 rsn = (struct mrvlietypes_rsnparamset *) pos;
410 rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */
411 rsn->header.type = cpu_to_le16(rsn->header.type);
412 rsn->header.len = (u16) adapter->wpa_ie[1];
413 memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
414 lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
415 sizeof(rsn->header) + rsn->header.len);
416 pos += sizeof(rsn->header) + rsn->header.len;
417 rsn->header.len = cpu_to_le16(rsn->header.len);
418 }
419
420 /* update curbssparams */
421 adapter->curbssparams.channel =
422 (pbssdesc->phyparamset.dsparamset.currentchan);
423
424 /* Copy the infra. association rates into Current BSS state structure */
425 memcpy(&adapter->curbssparams.datarates, &rates->rates,
426 min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
427
428 lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
429
430 /* set IBSS field */
431 if (pbssdesc->mode == IW_MODE_INFRA) {
432 #define CAPINFO_ESS_MODE 1
433 passo->capinfo.ess = CAPINFO_ESS_MODE;
434 }
435
436 if (libertas_parse_dnld_countryinfo_11d(priv)) {
437 ret = -1;
438 goto done;
439 }
440
441 cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
442
443 /* set the capability info at last */
444 memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
445 tmpcap &= CAPINFO_MASK;
446 lbs_deb_join("ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
447 tmpcap, CAPINFO_MASK);
448 tmpcap = cpu_to_le16(tmpcap);
449 memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
450
451 done:
452 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
453 return ret;
454 }
455
456 int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
457 struct cmd_ds_command *cmd, void *pssid)
458 {
459 wlan_adapter *adapter = priv->adapter;
460 struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
461 int ret = 0;
462 int cmdappendsize = 0;
463 int i;
464 u16 tmpcap;
465 struct bss_descriptor *pbssdesc;
466 struct WLAN_802_11_SSID *ssid = pssid;
467
468 lbs_deb_enter(LBS_DEB_JOIN);
469
470 if (!adapter) {
471 ret = -1;
472 goto done;
473 }
474
475 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
476
477 pbssdesc = &adapter->curbssparams.bssdescriptor;
478 adapter->pattemptedbssdesc = pbssdesc;
479
480 /*
481 * Fill in the parameters for 2 data structures:
482 * 1. cmd_ds_802_11_ad_hoc_start command
483 * 2. adapter->scantable[i]
484 *
485 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
486 * probe delay, and cap info.
487 *
488 * Firmware will fill up beacon period, DTIM, Basic rates
489 * and operational rates.
490 */
491
492 memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
493
494 memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
495
496 lbs_deb_join("ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
497
498 memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
499 memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
500
501 pbssdesc->ssid.ssidlength = ssid->ssidlength;
502
503 /* set the BSS type */
504 adhs->bsstype = cmd_bss_type_ibss;
505 pbssdesc->mode = IW_MODE_ADHOC;
506 adhs->beaconperiod = adapter->beaconperiod;
507
508 /* set Physical param set */
509 #define DS_PARA_IE_ID 3
510 #define DS_PARA_IE_LEN 1
511
512 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
513 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
514
515 WARN_ON(!adapter->curbssparams.channel);
516
517 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
518 adapter->curbssparams.channel);
519
520 pbssdesc->channel = adapter->curbssparams.channel;
521 adhs->phyparamset.dsparamset.currentchan = adapter->curbssparams.channel;
522
523 memcpy(&pbssdesc->phyparamset,
524 &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
525
526 /* set IBSS param set */
527 #define IBSS_PARA_IE_ID 6
528 #define IBSS_PARA_IE_LEN 2
529
530 adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
531 adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
532 adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
533 memcpy(&pbssdesc->ssparamset,
534 &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
535
536 /* set capability info */
537 adhs->cap.ess = 0;
538 adhs->cap.ibss = 1;
539 pbssdesc->cap.ibss = 1;
540
541 /* probedelay */
542 adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
543
544 /* set up privacy in adapter->scantable[i] */
545 if (adapter->secinfo.wep_enabled) {
546 lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
547 pbssdesc->privacy = wlan802_11privfilter8021xWEP;
548 adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
549 } else {
550 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
551 pbssdesc->privacy = wlan802_11privfilteracceptall;
552 }
553
554 memset(adhs->datarate, 0, sizeof(adhs->datarate));
555
556 if (adapter->adhoc_grate_enabled) {
557 memcpy(adhs->datarate, libertas_adhoc_rates_g,
558 min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g)));
559 } else {
560 memcpy(adhs->datarate, libertas_adhoc_rates_b,
561 min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b)));
562 }
563
564 /* Find the last non zero */
565 for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ;
566
567 adapter->curbssparams.numofrates = i;
568
569 /* Copy the ad-hoc creating rates into Current BSS state structure */
570 memcpy(&adapter->curbssparams.datarates,
571 &adhs->datarate, adapter->curbssparams.numofrates);
572
573 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
574 adhs->datarate[0], adhs->datarate[1],
575 adhs->datarate[2], adhs->datarate[3]);
576
577 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
578
579 if (libertas_create_dnld_countryinfo_11d(priv)) {
580 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
581 ret = -1;
582 goto done;
583 }
584
585 cmd->size =
586 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
587 + S_DS_GEN + cmdappendsize);
588
589 memcpy(&tmpcap, &adhs->cap, sizeof(u16));
590 tmpcap = cpu_to_le16(tmpcap);
591 memcpy(&adhs->cap, &tmpcap, sizeof(u16));
592
593 ret = 0;
594 done:
595 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
596 return ret;
597 }
598
599 int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
600 struct cmd_ds_command *cmd)
601 {
602 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_stop);
603 cmd->size = cpu_to_le16(S_DS_GEN);
604
605 return 0;
606 }
607
608 int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
609 struct cmd_ds_command *cmd, void *pdata_buf)
610 {
611 wlan_adapter *adapter = priv->adapter;
612 struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
613 struct bss_descriptor *pbssdesc = pdata_buf;
614 int cmdappendsize = 0;
615 int ret = 0;
616 u8 *card_rates;
617 int card_rates_size;
618 u16 tmpcap;
619 int i;
620
621 lbs_deb_enter(LBS_DEB_JOIN);
622
623 adapter->pattemptedbssdesc = pbssdesc;
624
625 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
626
627 padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
628
629 padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
630
631 memcpy(&padhocjoin->bssdescriptor.BSSID,
632 &pbssdesc->bssid, ETH_ALEN);
633
634 memcpy(&padhocjoin->bssdescriptor.SSID,
635 &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
636
637 memcpy(&padhocjoin->bssdescriptor.phyparamset,
638 &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
639
640 memcpy(&padhocjoin->bssdescriptor.ssparamset,
641 &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
642
643 memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
644 tmpcap &= CAPINFO_MASK;
645
646 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
647 tmpcap, CAPINFO_MASK);
648 memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
649 sizeof(struct ieeetypes_capinfo));
650
651 /* information on BSSID descriptor passed to FW */
652 lbs_deb_join(
653 "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
654 padhocjoin->bssdescriptor.BSSID[0],
655 padhocjoin->bssdescriptor.BSSID[1],
656 padhocjoin->bssdescriptor.BSSID[2],
657 padhocjoin->bssdescriptor.BSSID[3],
658 padhocjoin->bssdescriptor.BSSID[4],
659 padhocjoin->bssdescriptor.BSSID[5],
660 padhocjoin->bssdescriptor.SSID);
661
662 /* failtimeout */
663 padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
664
665 /* probedelay */
666 padhocjoin->probedelay =
667 cpu_to_le16(cmd_scan_probe_delay_time);
668
669 /* Copy Data rates from the rates recorded in scan response */
670 memset(padhocjoin->bssdescriptor.datarates, 0,
671 sizeof(padhocjoin->bssdescriptor.datarates));
672 memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
673 min(sizeof(padhocjoin->bssdescriptor.datarates),
674 sizeof(pbssdesc->datarates)));
675
676 card_rates = libertas_supported_rates;
677 card_rates_size = sizeof(libertas_supported_rates);
678
679 adapter->curbssparams.channel = pbssdesc->channel;
680
681 if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
682 sizeof(padhocjoin->bssdescriptor.datarates),
683 card_rates, card_rates_size)) {
684 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
685 ret = -1;
686 goto done;
687 }
688
689 /* Find the last non zero */
690 for (i = 0; i < sizeof(padhocjoin->bssdescriptor.datarates)
691 && padhocjoin->bssdescriptor.datarates[i]; i++) ;
692
693 adapter->curbssparams.numofrates = i;
694
695 /*
696 * Copy the adhoc joining rates to Current BSS State structure
697 */
698 memcpy(adapter->curbssparams.datarates,
699 padhocjoin->bssdescriptor.datarates,
700 adapter->curbssparams.numofrates);
701
702 padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
703 cpu_to_le16(pbssdesc->atimwindow);
704
705 if (adapter->secinfo.wep_enabled) {
706 padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
707 }
708
709 if (adapter->psmode == wlan802_11powermodemax_psp) {
710 /* wake up first */
711 enum WLAN_802_11_POWER_MODE Localpsmode;
712
713 Localpsmode = wlan802_11powermodecam;
714 ret = libertas_prepare_and_send_command(priv,
715 cmd_802_11_ps_mode,
716 cmd_act_set,
717 0, 0, &Localpsmode);
718
719 if (ret) {
720 ret = -1;
721 goto done;
722 }
723 }
724
725 if (libertas_parse_dnld_countryinfo_11d(priv)) {
726 ret = -1;
727 goto done;
728 }
729
730 cmd->size =
731 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
732 + S_DS_GEN + cmdappendsize);
733
734 memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
735 sizeof(struct ieeetypes_capinfo));
736 tmpcap = cpu_to_le16(tmpcap);
737
738 memcpy(&padhocjoin->bssdescriptor.cap,
739 &tmpcap, sizeof(struct ieeetypes_capinfo));
740
741 done:
742 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
743 return ret;
744 }
745
746 int libertas_ret_80211_associate(wlan_private * priv,
747 struct cmd_ds_command *resp)
748 {
749 wlan_adapter *adapter = priv->adapter;
750 int ret = 0;
751 union iwreq_data wrqu;
752 struct ieeetypes_assocrsp *passocrsp;
753 struct bss_descriptor *pbssdesc;
754
755 lbs_deb_enter(LBS_DEB_JOIN);
756
757 passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
758
759 if (passocrsp->statuscode) {
760
761 libertas_mac_event_disconnected(priv);
762
763 lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
764 passocrsp->statuscode);
765
766 ret = -1;
767 goto done;
768 }
769
770 lbs_dbg_hex("ASSOC_RESP:", (void *)&resp->params,
771 le16_to_cpu(resp->size) - S_DS_GEN);
772
773 /* Send a Media Connected event, according to the Spec */
774 adapter->connect_status = libertas_connected;
775
776 /* Set the attempted BSSID Index to current */
777 pbssdesc = adapter->pattemptedbssdesc;
778
779 lbs_deb_join("ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
780
781 /* Set the new SSID to current SSID */
782 memcpy(&adapter->curbssparams.ssid,
783 &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
784
785 /* Set the new BSSID (AP's MAC address) to current BSSID */
786 memcpy(adapter->curbssparams.bssid,
787 pbssdesc->bssid, ETH_ALEN);
788
789 /* Make a copy of current BSSID descriptor */
790 memcpy(&adapter->curbssparams.bssdescriptor,
791 pbssdesc, sizeof(struct bss_descriptor));
792
793 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
794 adapter->currentpacketfilter);
795
796 adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
797 adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
798
799 memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
800 memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
801 adapter->nextSNRNF = 0;
802 adapter->numSNRNF = 0;
803
804 netif_carrier_on(priv->dev);
805 netif_wake_queue(priv->dev);
806
807 netif_carrier_on(priv->mesh_dev);
808 netif_wake_queue(priv->mesh_dev);
809
810 lbs_deb_join("ASSOC_RESP: Associated \n");
811
812 memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
813 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
814 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
815
816 done:
817 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
818 return ret;
819 }
820
821 int libertas_ret_80211_disassociate(wlan_private * priv,
822 struct cmd_ds_command *resp)
823 {
824 lbs_deb_enter(LBS_DEB_JOIN);
825
826 libertas_mac_event_disconnected(priv);
827
828 lbs_deb_leave(LBS_DEB_JOIN);
829 return 0;
830 }
831
832 int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
833 struct cmd_ds_command *resp)
834 {
835 wlan_adapter *adapter = priv->adapter;
836 int ret = 0;
837 u16 command = le16_to_cpu(resp->command);
838 u16 result = le16_to_cpu(resp->result);
839 struct cmd_ds_802_11_ad_hoc_result *padhocresult;
840 union iwreq_data wrqu;
841 struct bss_descriptor *pbssdesc;
842
843 lbs_deb_enter(LBS_DEB_JOIN);
844
845 padhocresult = &resp->params.result;
846
847 lbs_deb_join("ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
848 lbs_deb_join("ADHOC_S_RESP: command = %x\n", command);
849 lbs_deb_join("ADHOC_S_RESP: result = %x\n", result);
850
851 pbssdesc = adapter->pattemptedbssdesc;
852
853 /*
854 * Join result code 0 --> SUCCESS
855 */
856 if (result) {
857 lbs_deb_join("ADHOC_RESP failed\n");
858 if (adapter->connect_status == libertas_connected) {
859 libertas_mac_event_disconnected(priv);
860 }
861
862 memset(&adapter->curbssparams.bssdescriptor,
863 0x00, sizeof(adapter->curbssparams.bssdescriptor));
864
865 ret = -1;
866 goto done;
867 }
868
869 /*
870 * Now the join cmd should be successful
871 * If BSSID has changed use SSID to compare instead of BSSID
872 */
873 lbs_deb_join("ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid);
874
875 /* Send a Media Connected event, according to the Spec */
876 adapter->connect_status = libertas_connected;
877
878 if (command == cmd_ret_802_11_ad_hoc_start) {
879 /* Update the created network descriptor with the new BSSID */
880 memcpy(pbssdesc->bssid, padhocresult->BSSID, ETH_ALEN);
881 } else {
882
883 /* Make a copy of current BSSID descriptor, only needed for join since
884 * the current descriptor is already being used for adhoc start
885 */
886 memmove(&adapter->curbssparams.bssdescriptor,
887 pbssdesc, sizeof(struct bss_descriptor));
888 }
889
890 /* Set the BSSID from the joined/started descriptor */
891 memcpy(&adapter->curbssparams.bssid, pbssdesc->bssid, ETH_ALEN);
892
893 /* Set the new SSID to current SSID */
894 memcpy(&adapter->curbssparams.ssid,
895 &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
896
897 netif_carrier_on(priv->dev);
898 netif_wake_queue(priv->dev);
899
900 netif_carrier_on(priv->mesh_dev);
901 netif_wake_queue(priv->mesh_dev);
902
903 memset(&wrqu, 0, sizeof(wrqu));
904 memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
905 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
906 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
907
908 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
909 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
910 lbs_deb_join("ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
911 padhocresult->BSSID[0], padhocresult->BSSID[1],
912 padhocresult->BSSID[2], padhocresult->BSSID[3],
913 padhocresult->BSSID[4], padhocresult->BSSID[5]);
914
915 done:
916 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
917 return ret;
918 }
919
920 int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
921 struct cmd_ds_command *resp)
922 {
923 lbs_deb_enter(LBS_DEB_JOIN);
924
925 libertas_mac_event_disconnected(priv);
926
927 lbs_deb_leave(LBS_DEB_JOIN);
928 return 0;
929 }
This page took 0.071957 seconds and 5 git commands to generate.