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 =
403 u8 *bssid = pdata_buf;
405 cmd->command = cpu_to_le16(cmd_802_11_authenticate);
407 cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
410 pauthenticate->authtype = adapter->secinfo.authmode;
411 memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
413 lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
414 bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
419 int libertas_cmd_80211_deauthenticate(wlan_private * priv,
420 struct cmd_ds_command *cmd)
422 wlan_adapter *adapter = priv->adapter;
423 struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
427 cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
429 cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
432 /* set AP MAC address */
433 memmove(dauth->macaddr, adapter->curbssparams.bssid,
436 /* Reason code 3 = Station is leaving */
437 #define REASON_CODE_STA_LEAVING 3
438 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
444 int libertas_cmd_80211_associate(wlan_private * priv,
445 struct cmd_ds_command *cmd, void *pdata_buf)
447 wlan_adapter *adapter = priv->adapter;
448 struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
450 struct bss_descriptor *pbssdesc;
455 struct mrvlietypes_ssidparamset *ssid;
456 struct mrvlietypes_phyparamset *phy;
457 struct mrvlietypes_ssparamset *ss;
458 struct mrvlietypes_ratesparamset *rates;
459 struct mrvlietypes_rsnparamset *rsn;
463 pbssdesc = pdata_buf;
471 cmd->command = cpu_to_le16(cmd_802_11_associate);
473 /* Save so we know which BSS Desc to use in the response handler */
474 adapter->pattemptedbssdesc = pbssdesc;
476 memcpy(passo->peerstaaddr,
477 pbssdesc->macaddress, sizeof(passo->peerstaaddr));
478 pos += sizeof(passo->peerstaaddr);
480 /* set the listen interval */
481 passo->listeninterval = adapter->listeninterval;
483 pos += sizeof(passo->capinfo);
484 pos += sizeof(passo->listeninterval);
485 pos += sizeof(passo->bcnperiod);
486 pos += sizeof(passo->dtimperiod);
488 ssid = (struct mrvlietypes_ssidparamset *) pos;
489 ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
490 ssid->header.len = pbssdesc->ssid.ssidlength;
491 memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
492 pos += sizeof(ssid->header) + ssid->header.len;
493 ssid->header.len = cpu_to_le16(ssid->header.len);
495 phy = (struct mrvlietypes_phyparamset *) pos;
496 phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
497 phy->header.len = sizeof(phy->fh_ds.dsparamset);
498 memcpy(&phy->fh_ds.dsparamset,
499 &pbssdesc->phyparamset.dsparamset.currentchan,
500 sizeof(phy->fh_ds.dsparamset));
501 pos += sizeof(phy->header) + phy->header.len;
502 phy->header.len = cpu_to_le16(phy->header.len);
504 ss = (struct mrvlietypes_ssparamset *) pos;
505 ss->header.type = cpu_to_le16(TLV_TYPE_CF);
506 ss->header.len = sizeof(ss->cf_ibss.cfparamset);
507 pos += sizeof(ss->header) + ss->header.len;
508 ss->header.len = cpu_to_le16(ss->header.len);
510 rates = (struct mrvlietypes_ratesparamset *) pos;
511 rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
513 memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
515 card_rates = libertas_supported_rates;
516 card_rates_size = sizeof(libertas_supported_rates);
518 if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES,
519 card_rates, card_rates_size)) {
524 rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
525 adapter->curbssparams.numofrates = rates->header.len;
527 pos += sizeof(rates->header) + rates->header.len;
528 rates->header.len = cpu_to_le16(rates->header.len);
530 if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
531 rsn = (struct mrvlietypes_rsnparamset *) pos;
532 rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */
533 rsn->header.type = cpu_to_le16(rsn->header.type);
534 rsn->header.len = (u16) adapter->wpa_ie[1];
535 memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
536 lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
537 sizeof(rsn->header) + rsn->header.len);
538 pos += sizeof(rsn->header) + rsn->header.len;
539 rsn->header.len = cpu_to_le16(rsn->header.len);
542 /* update curbssparams */
543 adapter->curbssparams.channel =
544 (pbssdesc->phyparamset.dsparamset.currentchan);
546 /* Copy the infra. association rates into Current BSS state structure */
547 memcpy(&adapter->curbssparams.datarates, &rates->rates,
548 min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
550 lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
553 if (pbssdesc->inframode == wlan802_11infrastructure) {
554 #define CAPINFO_ESS_MODE 1
555 passo->capinfo.ess = CAPINFO_ESS_MODE;
558 if (libertas_parse_dnld_countryinfo_11d(priv)) {
563 cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
565 /* set the capability info at last */
566 memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
567 tmpcap &= CAPINFO_MASK;
568 lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
569 tmpcap, CAPINFO_MASK);
570 tmpcap = cpu_to_le16(tmpcap);
571 memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
578 int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
579 struct cmd_ds_command *cmd, void *pssid)
581 wlan_adapter *adapter = priv->adapter;
582 struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
584 int cmdappendsize = 0;
587 struct bss_descriptor *pbssdesc;
588 struct WLAN_802_11_SSID *ssid = pssid;
597 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
599 pbssdesc = &adapter->curbssparams.bssdescriptor;
600 adapter->pattemptedbssdesc = pbssdesc;
603 * Fill in the parameters for 2 data structures:
604 * 1. cmd_ds_802_11_ad_hoc_start command
605 * 2. adapter->scantable[i]
607 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
608 * probe delay, and cap info.
610 * Firmware will fill up beacon period, DTIM, Basic rates
611 * and operational rates.
614 memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
616 memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
618 lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
620 memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
621 memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
623 pbssdesc->ssid.ssidlength = ssid->ssidlength;
625 /* set the BSS type */
626 adhs->bsstype = cmd_bss_type_ibss;
627 pbssdesc->inframode = wlan802_11ibss;
628 adhs->beaconperiod = adapter->beaconperiod;
630 /* set Physical param set */
631 #define DS_PARA_IE_ID 3
632 #define DS_PARA_IE_LEN 1
634 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
635 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
637 WARN_ON(!adapter->adhocchannel);
639 lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n",
640 adapter->adhocchannel);
642 adapter->curbssparams.channel = adapter->adhocchannel;
644 pbssdesc->channel = adapter->adhocchannel;
645 adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
647 memcpy(&pbssdesc->phyparamset,
648 &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
650 /* set IBSS param set */
651 #define IBSS_PARA_IE_ID 6
652 #define IBSS_PARA_IE_LEN 2
654 adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
655 adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
656 adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
657 memcpy(&pbssdesc->ssparamset,
658 &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
660 /* set capability info */
663 pbssdesc->cap.ibss = 1;
666 adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
668 /* set up privacy in adapter->scantable[i] */
669 if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
671 #define AD_HOC_CAP_PRIVACY_ON 1
672 lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus set, privacy to WEP\n");
673 pbssdesc->privacy = wlan802_11privfilter8021xWEP;
674 adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
676 lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus NOT set, Setting "
677 "privacy to ACCEPT ALL\n");
678 pbssdesc->privacy = wlan802_11privfilteracceptall;
681 memset(adhs->datarate, 0, sizeof(adhs->datarate));
683 if (adapter->adhoc_grate_enabled) {
684 memcpy(adhs->datarate, libertas_adhoc_rates_g,
685 min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g)));
687 memcpy(adhs->datarate, libertas_adhoc_rates_b,
688 min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b)));
691 /* Find the last non zero */
692 for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ;
694 adapter->curbssparams.numofrates = i;
696 /* Copy the ad-hoc creating rates into Current BSS state structure */
697 memcpy(&adapter->curbssparams.datarates,
698 &adhs->datarate, adapter->curbssparams.numofrates);
700 lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
701 adhs->datarate[0], adhs->datarate[1],
702 adhs->datarate[2], adhs->datarate[3]);
704 lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n");
706 if (libertas_create_dnld_countryinfo_11d(priv)) {
707 lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
713 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
714 + S_DS_GEN + cmdappendsize);
716 memcpy(&tmpcap, &adhs->cap, sizeof(u16));
717 tmpcap = cpu_to_le16(tmpcap);
718 memcpy(&adhs->cap, &tmpcap, sizeof(u16));
726 int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
727 struct cmd_ds_command *cmd)
729 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_stop);
730 cmd->size = cpu_to_le16(S_DS_GEN);
735 int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
736 struct cmd_ds_command *cmd, void *pdata_buf)
738 wlan_adapter *adapter = priv->adapter;
739 struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
740 struct bss_descriptor *pbssdesc = pdata_buf;
741 int cmdappendsize = 0;
750 adapter->pattemptedbssdesc = pbssdesc;
752 cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
754 padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
756 padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
758 memcpy(&padhocjoin->bssdescriptor.BSSID,
759 &pbssdesc->macaddress, ETH_ALEN);
761 memcpy(&padhocjoin->bssdescriptor.SSID,
762 &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
764 memcpy(&padhocjoin->bssdescriptor.phyparamset,
765 &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
767 memcpy(&padhocjoin->bssdescriptor.ssparamset,
768 &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
770 memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
771 tmpcap &= CAPINFO_MASK;
773 lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
774 tmpcap, CAPINFO_MASK);
775 memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
776 sizeof(struct ieeetypes_capinfo));
778 /* information on BSSID descriptor passed to FW */
780 "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
781 padhocjoin->bssdescriptor.BSSID[0],
782 padhocjoin->bssdescriptor.BSSID[1],
783 padhocjoin->bssdescriptor.BSSID[2],
784 padhocjoin->bssdescriptor.BSSID[3],
785 padhocjoin->bssdescriptor.BSSID[4],
786 padhocjoin->bssdescriptor.BSSID[5],
787 padhocjoin->bssdescriptor.SSID);
789 lbs_pr_debug(1, "ADHOC_J_CMD: Data Rate = %x\n",
790 (u32) padhocjoin->bssdescriptor.datarates);
793 padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
796 padhocjoin->probedelay =
797 cpu_to_le16(cmd_scan_probe_delay_time);
799 /* Copy Data rates from the rates recorded in scan response */
800 memset(padhocjoin->bssdescriptor.datarates, 0,
801 sizeof(padhocjoin->bssdescriptor.datarates));
802 memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
803 min(sizeof(padhocjoin->bssdescriptor.datarates),
804 sizeof(pbssdesc->datarates)));
806 card_rates = libertas_supported_rates;
807 card_rates_size = sizeof(libertas_supported_rates);
809 adapter->curbssparams.channel = pbssdesc->channel;
811 if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
812 sizeof(padhocjoin->bssdescriptor.datarates),
813 card_rates, card_rates_size)) {
814 lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n");
819 /* Find the last non zero */
820 for (i = 0; i < sizeof(padhocjoin->bssdescriptor.datarates)
821 && padhocjoin->bssdescriptor.datarates[i]; i++) ;
823 adapter->curbssparams.numofrates = i;
826 * Copy the adhoc joining rates to Current BSS State structure
828 memcpy(adapter->curbssparams.datarates,
829 padhocjoin->bssdescriptor.datarates,
830 adapter->curbssparams.numofrates);
832 padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
833 cpu_to_le16(pbssdesc->atimwindow);
835 if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
836 padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
839 if (adapter->psmode == wlan802_11powermodemax_psp) {
841 enum WLAN_802_11_POWER_MODE Localpsmode;
843 Localpsmode = wlan802_11powermodecam;
844 ret = libertas_prepare_and_send_command(priv,
855 if (libertas_parse_dnld_countryinfo_11d(priv)) {
861 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
862 + S_DS_GEN + cmdappendsize);
864 memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
865 sizeof(struct ieeetypes_capinfo));
866 tmpcap = cpu_to_le16(tmpcap);
868 memcpy(&padhocjoin->bssdescriptor.cap,
869 &tmpcap, sizeof(struct ieeetypes_capinfo));
876 int libertas_ret_80211_associate(wlan_private * priv,
877 struct cmd_ds_command *resp)
879 wlan_adapter *adapter = priv->adapter;
881 union iwreq_data wrqu;
882 struct ieeetypes_assocrsp *passocrsp;
883 struct bss_descriptor *pbssdesc;
887 passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
889 if (passocrsp->statuscode) {
891 libertas_mac_event_disconnected(priv);
894 "ASSOC_RESP: Association failed, status code = %d\n",
895 passocrsp->statuscode);
901 lbs_dbg_hex("ASSOC_RESP:", (void *)&resp->params,
902 le16_to_cpu(resp->size) - S_DS_GEN);
904 /* Send a Media Connected event, according to the Spec */
905 adapter->connect_status = libertas_connected;
907 /* Set the attempted BSSID Index to current */
908 pbssdesc = adapter->pattemptedbssdesc;
910 lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
912 /* Set the new SSID to current SSID */
913 memcpy(&adapter->curbssparams.ssid,
914 &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
916 /* Set the new BSSID (AP's MAC address) to current BSSID */
917 memcpy(adapter->curbssparams.bssid,
918 pbssdesc->macaddress, ETH_ALEN);
920 /* Make a copy of current BSSID descriptor */
921 memcpy(&adapter->curbssparams.bssdescriptor,
922 pbssdesc, sizeof(struct bss_descriptor));
924 lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n",
925 adapter->currentpacketfilter);
927 adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
928 adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
930 memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
931 memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
932 adapter->nextSNRNF = 0;
933 adapter->numSNRNF = 0;
935 netif_carrier_on(priv->wlan_dev.netdev);
936 netif_wake_queue(priv->wlan_dev.netdev);
938 lbs_pr_debug(1, "ASSOC_RESP: Associated \n");
940 memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
941 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
942 wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
949 int libertas_ret_80211_disassociate(wlan_private * priv,
950 struct cmd_ds_command *resp)
954 libertas_mac_event_disconnected(priv);
960 int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
961 struct cmd_ds_command *resp)
963 wlan_adapter *adapter = priv->adapter;
965 u16 command = le16_to_cpu(resp->command);
966 u16 result = le16_to_cpu(resp->result);
967 struct cmd_ds_802_11_ad_hoc_result *padhocresult;
968 union iwreq_data wrqu;
969 struct bss_descriptor *pbssdesc;
973 padhocresult = &resp->params.result;
975 lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
976 lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command);
977 lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result);
979 pbssdesc = adapter->pattemptedbssdesc;
982 * Join result code 0 --> SUCCESS
985 lbs_pr_debug(1, "ADHOC_RESP failed\n");
986 if (adapter->connect_status == libertas_connected) {
987 libertas_mac_event_disconnected(priv);
990 memset(&adapter->curbssparams.bssdescriptor,
991 0x00, sizeof(adapter->curbssparams.bssdescriptor));
998 * Now the join cmd should be successful
999 * If BSSID has changed use SSID to compare instead of BSSID
1001 lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid);
1003 /* Send a Media Connected event, according to the Spec */
1004 adapter->connect_status = libertas_connected;
1006 if (command == cmd_ret_802_11_ad_hoc_start) {
1007 /* Update the created network descriptor with the new BSSID */
1008 memcpy(pbssdesc->macaddress,
1009 padhocresult->BSSID, ETH_ALEN);
1012 /* Make a copy of current BSSID descriptor, only needed for join since
1013 * the current descriptor is already being used for adhoc start
1015 memmove(&adapter->curbssparams.bssdescriptor,
1016 pbssdesc, sizeof(struct bss_descriptor));
1019 /* Set the BSSID from the joined/started descriptor */
1020 memcpy(&adapter->curbssparams.bssid,
1021 pbssdesc->macaddress, ETH_ALEN);
1023 /* Set the new SSID to current SSID */
1024 memcpy(&adapter->curbssparams.ssid,
1025 &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
1027 netif_carrier_on(priv->wlan_dev.netdev);
1028 netif_wake_queue(priv->wlan_dev.netdev);
1030 memset(&wrqu, 0, sizeof(wrqu));
1031 memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
1032 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1033 wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
1035 lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
1036 lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
1037 lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
1038 padhocresult->BSSID[0], padhocresult->BSSID[1],
1039 padhocresult->BSSID[2], padhocresult->BSSID[3],
1040 padhocresult->BSSID[4], padhocresult->BSSID[5]);
1046 int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
1047 struct cmd_ds_command *resp)
1051 libertas_mac_event_disconnected(priv);