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
);