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
7 #include <linux/netdevice.h>
8 #include <linux/if_arp.h>
9 #include <linux/wireless.h>
11 #include <net/iw_handler.h>
19 * @brief This function finds out the common rates between rate1 and rate2.
21 * It will fill common rates in rate1 as output if found.
23 * NOTE: Setting the MSB of the basic rates need to be taken
24 * care, either before or after calling this function
26 * @param adapter A pointer to wlan_adapter structure
27 * @param rate1 the buffer which keeps input and output
28 * @param rate1_size the size of rate1 buffer
29 * @param rate2 the buffer which keeps rate2
30 * @param rate2_size the size of rate2 buffer.
34 static int get_common_rates(wlan_adapter * adapter, u8 * rate1,
35 int rate1_size, u8 * rate2, int rate2_size)
42 memset(&tmp, 0, sizeof(tmp));
43 memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp)));
44 memset(rate1, 0, rate1_size);
46 /* Mask the top bit of the original values */
47 for (i = 0; tmp[i] && i < sizeof(tmp); i++)
50 for (i = 0; rate2[i] && i < rate2_size; i++) {
51 /* Check for Card Rate in tmp, excluding the top bit */
52 if (strchr(tmp, rate2[i] & 0x7F)) {
53 /* values match, so copy the Card Rate to rate1 */
58 lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp));
59 lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size);
60 lbs_dbg_hex("Common rates:", ptr, rate1_size);
61 lbs_pr_debug(1, "Tx datarate is set to 0x%X\n", adapter->datarate);
63 if (!adapter->is_datarate_auto) {
65 if ((*ptr & 0x7f) == adapter->datarate) {
71 lbs_pr_alert( "Previously set fixed data rate %#x isn't "
72 "compatible with the network.\n", adapter->datarate);
83 int libertas_send_deauth(wlan_private * priv)
85 wlan_adapter *adapter = priv->adapter;
88 if (adapter->inframode == wlan802_11infrastructure &&
89 adapter->connect_status == libertas_connected)
90 ret = libertas_send_deauthentication(priv);
97 int libertas_do_adhocstop_ioctl(wlan_private * priv)
99 wlan_adapter *adapter = priv->adapter;
102 if (adapter->inframode == wlan802_11ibss &&
103 adapter->connect_status == libertas_connected)
104 ret = libertas_stop_adhoc_network(priv);
112 * @brief Associate to a specific BSS discovered in a scan
114 * @param priv A pointer to wlan_private structure
115 * @param pbssdesc Pointer to the BSS descriptor to associate with.
117 * @return 0-success, otherwise fail
119 int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
121 wlan_adapter *adapter = priv->adapter;
126 ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate,
127 0, cmd_option_waitforrsp,
128 0, pbssdesc->macaddress);
135 /* set preamble to firmware */
136 if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble)
137 adapter->preamble = cmd_type_short_preamble;
139 adapter->preamble = cmd_type_long_preamble;
141 libertas_set_radio_control(priv);
143 ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate,
144 0, cmd_option_waitforrsp, 0, pbssdesc);
151 * @brief Start an Adhoc Network
153 * @param priv A pointer to wlan_private structure
154 * @param adhocssid The ssid of the Adhoc Network
155 * @return 0--success, -1--fail
157 int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid)
159 wlan_adapter *adapter = priv->adapter;
162 adapter->adhoccreate = 1;
164 if (!adapter->capinfo.shortpreamble) {
165 lbs_pr_debug(1, "AdhocStart: Long preamble\n");
166 adapter->preamble = cmd_type_long_preamble;
168 lbs_pr_debug(1, "AdhocStart: Short preamble\n");
169 adapter->preamble = cmd_type_short_preamble;
172 libertas_set_radio_control(priv);
174 lbs_pr_debug(1, "Adhoc channel = %d\n", adapter->adhocchannel);
175 lbs_pr_debug(1, "curbssparams.channel = %d\n",
176 adapter->curbssparams.channel);
177 lbs_pr_debug(1, "curbssparams.band = %d\n", adapter->curbssparams.band);
179 ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start,
180 0, cmd_option_waitforrsp, 0, adhocssid);
186 * @brief Join an adhoc network found in a previous scan
188 * @param priv A pointer to wlan_private structure
189 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
192 * @return 0--success, -1--fail
194 int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc)
196 wlan_adapter *adapter = priv->adapter;
199 lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid =%s\n",
200 adapter->curbssparams.ssid.ssid);
201 lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
202 adapter->curbssparams.ssid.ssidlength);
203 lbs_pr_debug(1, "libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid);
204 lbs_pr_debug(1, "libertas_join_adhoc_network: ssid len =%u\n",
205 pbssdesc->ssid.ssidlength);
207 /* check if the requested SSID is already joined */
208 if (adapter->curbssparams.ssid.ssidlength
209 && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid)
210 && (adapter->curbssparams.bssdescriptor.inframode ==
214 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
215 "not attempting to re-join");
220 /*Use shortpreamble only when both creator and card supports
222 if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
223 lbs_pr_debug(1, "AdhocJoin: Long preamble\n");
224 adapter->preamble = cmd_type_long_preamble;
226 lbs_pr_debug(1, "AdhocJoin: Short preamble\n");
227 adapter->preamble = cmd_type_short_preamble;
230 libertas_set_radio_control(priv);
232 lbs_pr_debug(1, "curbssparams.channel = %d\n",
233 adapter->curbssparams.channel);
234 lbs_pr_debug(1, "curbssparams.band = %c\n", adapter->curbssparams.band);
236 adapter->adhoccreate = 0;
238 ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join,
239 0, cmd_option_waitforrsp,
240 OID_802_11_SSID, pbssdesc);
245 int libertas_stop_adhoc_network(wlan_private * priv)
247 return libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_stop,
248 0, cmd_option_waitforrsp, 0, NULL);
252 * @brief Send Deauthentication Request
254 * @param priv A pointer to wlan_private structure
255 * @return 0--success, -1--fail
257 int libertas_send_deauthentication(wlan_private * priv)
259 return libertas_prepare_and_send_command(priv, cmd_802_11_deauthenticate,
260 0, cmd_option_waitforrsp, 0, NULL);
264 * @brief Set Idle Off
266 * @param priv A pointer to wlan_private structure
267 * @return 0 --success, otherwise fail
269 int libertas_idle_off(wlan_private * priv)
271 wlan_adapter *adapter = priv->adapter;
273 const u8 zeromac[] = { 0, 0, 0, 0, 0, 0 };
278 if (adapter->connect_status == libertas_disconnected) {
279 if (adapter->inframode == wlan802_11infrastructure) {
280 if (memcmp(adapter->previousbssid, zeromac,
281 sizeof(zeromac)) != 0) {
283 lbs_pr_debug(1, "Previous SSID = %s\n",
284 adapter->previousssid.ssid);
285 lbs_pr_debug(1, "Previous BSSID = "
286 "%02x:%02x:%02x:%02x:%02x:%02x:\n",
287 adapter->previousbssid[0],
288 adapter->previousbssid[1],
289 adapter->previousbssid[2],
290 adapter->previousbssid[3],
291 adapter->previousbssid[4],
292 adapter->previousbssid[5]);
294 i = libertas_find_SSID_in_list(adapter,
295 &adapter->previousssid,
296 adapter->previousbssid,
300 libertas_send_specific_BSSID_scan(priv,
304 i = libertas_find_SSID_in_list(adapter,
314 /* If the BSSID could not be found, try just the SSID */
315 i = libertas_find_SSID_in_list(adapter,
323 libertas_send_specific_SSID_scan(priv,
327 i = libertas_find_SSID_in_list(adapter,
341 } else if (adapter->inframode == wlan802_11ibss) {
342 ret = libertas_prepare_and_send_command(priv,
343 cmd_802_11_ad_hoc_start,
345 cmd_option_waitforrsp,
346 0, &adapter->previousssid);
349 /* else it is connected */
351 lbs_pr_debug(1, "\nwlanidle is off");
359 * @param priv A pointer to wlan_private structure
360 * @return 0 --success, otherwise fail
362 int libertas_idle_on(wlan_private * priv)
364 wlan_adapter *adapter = priv->adapter;
367 if (adapter->connect_status == libertas_connected) {
368 if (adapter->inframode == wlan802_11infrastructure) {
369 lbs_pr_debug(1, "Previous SSID = %s\n",
370 adapter->previousssid.ssid);
371 memmove(&adapter->previousssid,
372 &adapter->curbssparams.ssid,
373 sizeof(struct WLAN_802_11_SSID));
374 libertas_send_deauth(priv);
376 } else if (adapter->inframode == wlan802_11ibss) {
377 ret = libertas_stop_adhoc_network(priv);
382 lbs_pr_debug(1, "\nwlanidle is on");
388 * @brief This function prepares command of authenticate.
390 * @param priv A pointer to wlan_private structure
391 * @param cmd A pointer to cmd_ds_command structure
392 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
396 int libertas_cmd_80211_authenticate(wlan_private * priv,
397 struct cmd_ds_command *cmd,
400 wlan_adapter *adapter = priv->adapter;
401 struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
403 u8 *bssid = pdata_buf;
405 cmd->command = cpu_to_le16(cmd_802_11_authenticate);
406 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
409 /* translate auth mode to 802.11 defined wire value */
410 switch (adapter->secinfo.auth_mode) {
411 case IW_AUTH_ALG_OPEN_SYSTEM:
412 pauthenticate->authtype = 0x00;
414 case IW_AUTH_ALG_SHARED_KEY:
415 pauthenticate->authtype = 0x01;
417 case IW_AUTH_ALG_LEAP:
418 pauthenticate->authtype = 0x80;
421 lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n",
422 adapter->secinfo.auth_mode);
426 memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
428 lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
429 bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
436 int libertas_cmd_80211_deauthenticate(wlan_private * priv,
437 struct cmd_ds_command *cmd)
439 wlan_adapter *adapter = priv->adapter;
440 struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
444 cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
446 cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
449 /* set AP MAC address */
450 memmove(dauth->macaddr, adapter->curbssparams.bssid,
453 /* Reason code 3 = Station is leaving */
454 #define REASON_CODE_STA_LEAVING 3
455 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
461 int libertas_cmd_80211_associate(wlan_private * priv,
462 struct cmd_ds_command *cmd, void *pdata_buf)
464 wlan_adapter *adapter = priv->adapter;
465 struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
467 struct bss_descriptor *pbssdesc;
472 struct mrvlietypes_ssidparamset *ssid;
473 struct mrvlietypes_phyparamset *phy;
474 struct mrvlietypes_ssparamset *ss;
475 struct mrvlietypes_ratesparamset *rates;
476 struct mrvlietypes_rsnparamset *rsn;
480 pbssdesc = pdata_buf;
488 cmd->command = cpu_to_le16(cmd_802_11_associate);
490 /* Save so we know which BSS Desc to use in the response handler */
491 adapter->pattemptedbssdesc = pbssdesc;
493 memcpy(passo->peerstaaddr,
494 pbssdesc->macaddress, sizeof(passo->peerstaaddr));
495 pos += sizeof(passo->peerstaaddr);
497 /* set the listen interval */
498 passo->listeninterval = adapter->listeninterval;
500 pos += sizeof(passo->capinfo);
501 pos += sizeof(passo->listeninterval);
502 pos += sizeof(passo->bcnperiod);
503 pos += sizeof(passo->dtimperiod);
505 ssid = (struct mrvlietypes_ssidparamset *) pos;
506 ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
507 ssid->header.len = pbssdesc->ssid.ssidlength;
508 memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
509 pos += sizeof(ssid->header) + ssid->header.len;
510 ssid->header.len = cpu_to_le16(ssid->header.len);
512 phy = (struct mrvlietypes_phyparamset *) pos;
513 phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
514 phy->header.len = sizeof(phy->fh_ds.dsparamset);
515 memcpy(&phy->fh_ds.dsparamset,
516 &pbssdesc->phyparamset.dsparamset.currentchan,
517 sizeof(phy->fh_ds.dsparamset));
518 pos += sizeof(phy->header) + phy->header.len;
519 phy->header.len = cpu_to_le16(phy->header.len);
521 ss = (struct mrvlietypes_ssparamset *) pos;
522 ss->header.type = cpu_to_le16(TLV_TYPE_CF);
523 ss->header.len = sizeof(ss->cf_ibss.cfparamset);
524 pos += sizeof(ss->header) + ss->header.len;
525 ss->header.len = cpu_to_le16(ss->header.len);
527 rates = (struct mrvlietypes_ratesparamset *) pos;
528 rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
530 memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
532 card_rates = libertas_supported_rates;
533 card_rates_size = sizeof(libertas_supported_rates);
535 if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES,
536 card_rates, card_rates_size)) {
541 rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
542 adapter->curbssparams.numofrates = rates->header.len;
544 pos += sizeof(rates->header) + rates->header.len;
545 rates->header.len = cpu_to_le16(rates->header.len);
547 if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
548 rsn = (struct mrvlietypes_rsnparamset *) pos;
549 rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */
550 rsn->header.type = cpu_to_le16(rsn->header.type);
551 rsn->header.len = (u16) adapter->wpa_ie[1];
552 memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
553 lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
554 sizeof(rsn->header) + rsn->header.len);
555 pos += sizeof(rsn->header) + rsn->header.len;
556 rsn->header.len = cpu_to_le16(rsn->header.len);
559 /* update curbssparams */
560 adapter->curbssparams.channel =
561 (pbssdesc->phyparamset.dsparamset.currentchan);
563 /* Copy the infra. association rates into Current BSS state structure */
564 memcpy(&adapter->curbssparams.datarates, &rates->rates,
565 min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
567 lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
570 if (pbssdesc->inframode == wlan802_11infrastructure) {
571 #define CAPINFO_ESS_MODE 1
572 passo->capinfo.ess = CAPINFO_ESS_MODE;
575 if (libertas_parse_dnld_countryinfo_11d(priv)) {
580 cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
582 /* set the capability info at last */
583 memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
584 tmpcap &= CAPINFO_MASK;
585 lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
586 tmpcap, CAPINFO_MASK);
587 tmpcap = cpu_to_le16(tmpcap);
588 memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
595 int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
596 struct cmd_ds_command *cmd, void *pssid)
598 wlan_adapter *adapter = priv->adapter;
599 struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
601 int cmdappendsize = 0;
604 struct bss_descriptor *pbssdesc;
605 struct WLAN_802_11_SSID *ssid = pssid;
614 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
616 pbssdesc = &adapter->curbssparams.bssdescriptor;
617 adapter->pattemptedbssdesc = pbssdesc;
620 * Fill in the parameters for 2 data structures:
621 * 1. cmd_ds_802_11_ad_hoc_start command
622 * 2. adapter->scantable[i]
624 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
625 * probe delay, and cap info.
627 * Firmware will fill up beacon period, DTIM, Basic rates
628 * and operational rates.
631 memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
633 memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
635 lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
637 memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
638 memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
640 pbssdesc->ssid.ssidlength = ssid->ssidlength;
642 /* set the BSS type */
643 adhs->bsstype = cmd_bss_type_ibss;
644 pbssdesc->inframode = wlan802_11ibss;
645 adhs->beaconperiod = adapter->beaconperiod;
647 /* set Physical param set */
648 #define DS_PARA_IE_ID 3
649 #define DS_PARA_IE_LEN 1
651 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
652 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
654 WARN_ON(!adapter->adhocchannel);
656 lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n",
657 adapter->adhocchannel);
659 adapter->curbssparams.channel = adapter->adhocchannel;
661 pbssdesc->channel = adapter->adhocchannel;
662 adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
664 memcpy(&pbssdesc->phyparamset,
665 &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
667 /* set IBSS param set */
668 #define IBSS_PARA_IE_ID 6
669 #define IBSS_PARA_IE_LEN 2
671 adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
672 adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
673 adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
674 memcpy(&pbssdesc->ssparamset,
675 &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
677 /* set capability info */
680 pbssdesc->cap.ibss = 1;
683 adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
685 /* set up privacy in adapter->scantable[i] */
686 if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
688 #define AD_HOC_CAP_PRIVACY_ON 1
689 lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus set, privacy to WEP\n");
690 pbssdesc->privacy = wlan802_11privfilter8021xWEP;
691 adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
693 lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus NOT set, Setting "
694 "privacy to ACCEPT ALL\n");
695 pbssdesc->privacy = wlan802_11privfilteracceptall;
698 memset(adhs->datarate, 0, sizeof(adhs->datarate));
700 if (adapter->adhoc_grate_enabled) {
701 memcpy(adhs->datarate, libertas_adhoc_rates_g,
702 min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g)));
704 memcpy(adhs->datarate, libertas_adhoc_rates_b,
705 min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b)));
708 /* Find the last non zero */
709 for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ;
711 adapter->curbssparams.numofrates = i;
713 /* Copy the ad-hoc creating rates into Current BSS state structure */
714 memcpy(&adapter->curbssparams.datarates,
715 &adhs->datarate, adapter->curbssparams.numofrates);
717 lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
718 adhs->datarate[0], adhs->datarate[1],
719 adhs->datarate[2], adhs->datarate[3]);
721 lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n");
723 if (libertas_create_dnld_countryinfo_11d(priv)) {
724 lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
730 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
731 + S_DS_GEN + cmdappendsize);
733 memcpy(&tmpcap, &adhs->cap, sizeof(u16));
734 tmpcap = cpu_to_le16(tmpcap);
735 memcpy(&adhs->cap, &tmpcap, sizeof(u16));
743 int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
744 struct cmd_ds_command *cmd)
746 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_stop);
747 cmd->size = cpu_to_le16(S_DS_GEN);
752 int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
753 struct cmd_ds_command *cmd, void *pdata_buf)
755 wlan_adapter *adapter = priv->adapter;
756 struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
757 struct bss_descriptor *pbssdesc = pdata_buf;
758 int cmdappendsize = 0;
767 adapter->pattemptedbssdesc = pbssdesc;
769 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
771 padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
773 padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
775 memcpy(&padhocjoin->bssdescriptor.BSSID,
776 &pbssdesc->macaddress, ETH_ALEN);
778 memcpy(&padhocjoin->bssdescriptor.SSID,
779 &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
781 memcpy(&padhocjoin->bssdescriptor.phyparamset,
782 &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
784 memcpy(&padhocjoin->bssdescriptor.ssparamset,
785 &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
787 memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
788 tmpcap &= CAPINFO_MASK;
790 lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
791 tmpcap, CAPINFO_MASK);
792 memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
793 sizeof(struct ieeetypes_capinfo));
795 /* information on BSSID descriptor passed to FW */
797 "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
798 padhocjoin->bssdescriptor.BSSID[0],
799 padhocjoin->bssdescriptor.BSSID[1],
800 padhocjoin->bssdescriptor.BSSID[2],
801 padhocjoin->bssdescriptor.BSSID[3],
802 padhocjoin->bssdescriptor.BSSID[4],
803 padhocjoin->bssdescriptor.BSSID[5],
804 padhocjoin->bssdescriptor.SSID);
806 lbs_pr_debug(1, "ADHOC_J_CMD: Data Rate = %x\n",
807 (u32) padhocjoin->bssdescriptor.datarates);
810 padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
813 padhocjoin->probedelay =
814 cpu_to_le16(cmd_scan_probe_delay_time);
816 /* Copy Data rates from the rates recorded in scan response */
817 memset(padhocjoin->bssdescriptor.datarates, 0,
818 sizeof(padhocjoin->bssdescriptor.datarates));
819 memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
820 min(sizeof(padhocjoin->bssdescriptor.datarates),
821 sizeof(pbssdesc->datarates)));
823 card_rates = libertas_supported_rates;
824 card_rates_size = sizeof(libertas_supported_rates);
826 adapter->curbssparams.channel = pbssdesc->channel;
828 if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
829 sizeof(padhocjoin->bssdescriptor.datarates),
830 card_rates, card_rates_size)) {
831 lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n");
836 /* Find the last non zero */
837 for (i = 0; i < sizeof(padhocjoin->bssdescriptor.datarates)
838 && padhocjoin->bssdescriptor.datarates[i]; i++) ;
840 adapter->curbssparams.numofrates = i;
843 * Copy the adhoc joining rates to Current BSS State structure
845 memcpy(adapter->curbssparams.datarates,
846 padhocjoin->bssdescriptor.datarates,
847 adapter->curbssparams.numofrates);
849 padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
850 cpu_to_le16(pbssdesc->atimwindow);
852 if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
853 padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
856 if (adapter->psmode == wlan802_11powermodemax_psp) {
858 enum WLAN_802_11_POWER_MODE Localpsmode;
860 Localpsmode = wlan802_11powermodecam;
861 ret = libertas_prepare_and_send_command(priv,
872 if (libertas_parse_dnld_countryinfo_11d(priv)) {
878 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
879 + S_DS_GEN + cmdappendsize);
881 memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
882 sizeof(struct ieeetypes_capinfo));
883 tmpcap = cpu_to_le16(tmpcap);
885 memcpy(&padhocjoin->bssdescriptor.cap,
886 &tmpcap, sizeof(struct ieeetypes_capinfo));
893 int libertas_ret_80211_associate(wlan_private * priv,
894 struct cmd_ds_command *resp)
896 wlan_adapter *adapter = priv->adapter;
898 union iwreq_data wrqu;
899 struct ieeetypes_assocrsp *passocrsp;
900 struct bss_descriptor *pbssdesc;
904 passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
906 if (passocrsp->statuscode) {
908 libertas_mac_event_disconnected(priv);
911 "ASSOC_RESP: Association failed, status code = %d\n",
912 passocrsp->statuscode);
918 lbs_dbg_hex("ASSOC_RESP:", (void *)&resp->params,
919 le16_to_cpu(resp->size) - S_DS_GEN);
921 /* Send a Media Connected event, according to the Spec */
922 adapter->connect_status = libertas_connected;
924 /* Set the attempted BSSID Index to current */
925 pbssdesc = adapter->pattemptedbssdesc;
927 lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
929 /* Set the new SSID to current SSID */
930 memcpy(&adapter->curbssparams.ssid,
931 &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
933 /* Set the new BSSID (AP's MAC address) to current BSSID */
934 memcpy(adapter->curbssparams.bssid,
935 pbssdesc->macaddress, ETH_ALEN);
937 /* Make a copy of current BSSID descriptor */
938 memcpy(&adapter->curbssparams.bssdescriptor,
939 pbssdesc, sizeof(struct bss_descriptor));
941 lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n",
942 adapter->currentpacketfilter);
944 adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
945 adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
947 memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
948 memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
949 adapter->nextSNRNF = 0;
950 adapter->numSNRNF = 0;
952 netif_carrier_on(priv->wlan_dev.netdev);
953 netif_wake_queue(priv->wlan_dev.netdev);
955 lbs_pr_debug(1, "ASSOC_RESP: Associated \n");
957 memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
958 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
959 wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
966 int libertas_ret_80211_disassociate(wlan_private * priv,
967 struct cmd_ds_command *resp)
971 libertas_mac_event_disconnected(priv);
977 int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
978 struct cmd_ds_command *resp)
980 wlan_adapter *adapter = priv->adapter;
982 u16 command = le16_to_cpu(resp->command);
983 u16 result = le16_to_cpu(resp->result);
984 struct cmd_ds_802_11_ad_hoc_result *padhocresult;
985 union iwreq_data wrqu;
986 struct bss_descriptor *pbssdesc;
990 padhocresult = &resp->params.result;
992 lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
993 lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command);
994 lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result);
996 pbssdesc = adapter->pattemptedbssdesc;
999 * Join result code 0 --> SUCCESS
1002 lbs_pr_debug(1, "ADHOC_RESP failed\n");
1003 if (adapter->connect_status == libertas_connected) {
1004 libertas_mac_event_disconnected(priv);
1007 memset(&adapter->curbssparams.bssdescriptor,
1008 0x00, sizeof(adapter->curbssparams.bssdescriptor));
1015 * Now the join cmd should be successful
1016 * If BSSID has changed use SSID to compare instead of BSSID
1018 lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid);
1020 /* Send a Media Connected event, according to the Spec */
1021 adapter->connect_status = libertas_connected;
1023 if (command == cmd_ret_802_11_ad_hoc_start) {
1024 /* Update the created network descriptor with the new BSSID */
1025 memcpy(pbssdesc->macaddress,
1026 padhocresult->BSSID, ETH_ALEN);
1029 /* Make a copy of current BSSID descriptor, only needed for join since
1030 * the current descriptor is already being used for adhoc start
1032 memmove(&adapter->curbssparams.bssdescriptor,
1033 pbssdesc, sizeof(struct bss_descriptor));
1036 /* Set the BSSID from the joined/started descriptor */
1037 memcpy(&adapter->curbssparams.bssid,
1038 pbssdesc->macaddress, ETH_ALEN);
1040 /* Set the new SSID to current SSID */
1041 memcpy(&adapter->curbssparams.ssid,
1042 &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
1044 netif_carrier_on(priv->wlan_dev.netdev);
1045 netif_wake_queue(priv->wlan_dev.netdev);
1047 memset(&wrqu, 0, sizeof(wrqu));
1048 memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
1049 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1050 wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
1052 lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
1053 lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
1054 lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
1055 padhocresult->BSSID[0], padhocresult->BSSID[1],
1056 padhocresult->BSSID[2], padhocresult->BSSID[3],
1057 padhocresult->BSSID[4], padhocresult->BSSID[5]);
1063 int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
1064 struct cmd_ds_command *resp)
1068 libertas_mac_event_disconnected(priv);