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>
18 #define AD_HOC_CAP_PRIVACY_ON 1
21 * @brief This function finds out the common rates between rate1 and rate2.
23 * It will fill common rates in rate1 as output if found.
25 * NOTE: Setting the MSB of the basic rates need to be taken
26 * care, either before or after calling this function
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.
36 static int get_common_rates(wlan_adapter
* adapter
, u8
* rate1
,
37 int rate1_size
, u8
* rate2
, int rate2_size
)
44 memset(&tmp
, 0, sizeof(tmp
));
45 memcpy(&tmp
, rate1
, min_t(size_t, rate1_size
, sizeof(tmp
)));
46 memset(rate1
, 0, rate1_size
);
48 /* Mask the top bit of the original values */
49 for (i
= 0; tmp
[i
] && i
< sizeof(tmp
); i
++)
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 */
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
);
65 if (!adapter
->is_datarate_auto
) {
67 if ((*ptr
& 0x7f) == adapter
->datarate
) {
73 lbs_pr_alert( "Previously set fixed data rate %#x isn't "
74 "compatible with the network.\n", adapter
->datarate
);
85 int libertas_send_deauth(wlan_private
* priv
)
87 wlan_adapter
*adapter
= priv
->adapter
;
90 if (adapter
->mode
== IW_MODE_INFRA
&&
91 adapter
->connect_status
== libertas_connected
)
92 ret
= libertas_send_deauthentication(priv
);
100 * @brief Associate to a specific BSS discovered in a scan
102 * @param priv A pointer to wlan_private structure
103 * @param pbssdesc Pointer to the BSS descriptor to associate with.
105 * @return 0-success, otherwise fail
107 int wlan_associate(wlan_private
* priv
, struct bss_descriptor
* pbssdesc
)
109 wlan_adapter
*adapter
= priv
->adapter
;
112 lbs_deb_enter(LBS_DEB_JOIN
);
114 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_authenticate
,
115 0, cmd_option_waitforrsp
,
121 /* set preamble to firmware */
122 if (adapter
->capinfo
.shortpreamble
&& pbssdesc
->cap
.shortpreamble
)
123 adapter
->preamble
= cmd_type_short_preamble
;
125 adapter
->preamble
= cmd_type_long_preamble
;
127 libertas_set_radio_control(priv
);
129 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_associate
,
130 0, cmd_option_waitforrsp
, 0, pbssdesc
);
133 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
138 * @brief Start an Adhoc Network
140 * @param priv A pointer to wlan_private structure
141 * @param adhocssid The ssid of the Adhoc Network
142 * @return 0--success, -1--fail
144 int libertas_start_adhoc_network(wlan_private
* priv
, struct WLAN_802_11_SSID
*adhocssid
)
146 wlan_adapter
*adapter
= priv
->adapter
;
149 adapter
->adhoccreate
= 1;
151 if (!adapter
->capinfo
.shortpreamble
) {
152 lbs_deb_join("AdhocStart: Long preamble\n");
153 adapter
->preamble
= cmd_type_long_preamble
;
155 lbs_deb_join("AdhocStart: Short preamble\n");
156 adapter
->preamble
= cmd_type_short_preamble
;
159 libertas_set_radio_control(priv
);
161 lbs_deb_join("curbssparams.channel = %d\n",
162 adapter
->curbssparams
.channel
);
163 lbs_deb_join("curbssparams.band = %d\n", adapter
->curbssparams
.band
);
165 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_ad_hoc_start
,
166 0, cmd_option_waitforrsp
, 0, adhocssid
);
172 * @brief Join an adhoc network found in a previous scan
174 * @param priv A pointer to wlan_private structure
175 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
178 * @return 0--success, -1--fail
180 int libertas_join_adhoc_network(wlan_private
* priv
, struct bss_descriptor
* pbssdesc
)
182 wlan_adapter
*adapter
= priv
->adapter
;
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
);
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
)) {
199 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
200 "not attempting to re-join");
205 /*Use shortpreamble only when both creator and card supports
207 if (!pbssdesc
->cap
.shortpreamble
|| !adapter
->capinfo
.shortpreamble
) {
208 lbs_deb_join("AdhocJoin: Long preamble\n");
209 adapter
->preamble
= cmd_type_long_preamble
;
211 lbs_deb_join("AdhocJoin: Short preamble\n");
212 adapter
->preamble
= cmd_type_short_preamble
;
215 libertas_set_radio_control(priv
);
217 lbs_deb_join("curbssparams.channel = %d\n",
218 adapter
->curbssparams
.channel
);
219 lbs_deb_join("curbssparams.band = %c\n", adapter
->curbssparams
.band
);
221 adapter
->adhoccreate
= 0;
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
);
230 int libertas_stop_adhoc_network(wlan_private
* priv
)
232 return libertas_prepare_and_send_command(priv
, cmd_802_11_ad_hoc_stop
,
233 0, cmd_option_waitforrsp
, 0, NULL
);
237 * @brief Send Deauthentication Request
239 * @param priv A pointer to wlan_private structure
240 * @return 0--success, -1--fail
242 int libertas_send_deauthentication(wlan_private
* priv
)
244 return libertas_prepare_and_send_command(priv
, cmd_802_11_deauthenticate
,
245 0, cmd_option_waitforrsp
, 0, NULL
);
249 * @brief This function prepares command of authenticate.
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
257 int libertas_cmd_80211_authenticate(wlan_private
* priv
,
258 struct cmd_ds_command
*cmd
,
261 wlan_adapter
*adapter
= priv
->adapter
;
262 struct cmd_ds_802_11_authenticate
*pauthenticate
= &cmd
->params
.auth
;
264 u8
*bssid
= pdata_buf
;
266 cmd
->command
= cpu_to_le16(cmd_802_11_authenticate
);
267 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate
)
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;
275 case IW_AUTH_ALG_SHARED_KEY
:
276 pauthenticate
->authtype
= 0x01;
278 case IW_AUTH_ALG_LEAP
:
279 pauthenticate
->authtype
= 0x80;
282 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
283 adapter
->secinfo
.auth_mode
);
287 memcpy(pauthenticate
->macaddr
, bssid
, ETH_ALEN
);
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]);
297 int libertas_cmd_80211_deauthenticate(wlan_private
* priv
,
298 struct cmd_ds_command
*cmd
)
300 wlan_adapter
*adapter
= priv
->adapter
;
301 struct cmd_ds_802_11_deauthenticate
*dauth
= &cmd
->params
.deauth
;
303 lbs_deb_enter(LBS_DEB_JOIN
);
305 cmd
->command
= cpu_to_le16(cmd_802_11_deauthenticate
);
307 cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate
) +
310 /* set AP MAC address */
311 memmove(dauth
->macaddr
, adapter
->curbssparams
.bssid
,
314 /* Reason code 3 = Station is leaving */
315 #define REASON_CODE_STA_LEAVING 3
316 dauth
->reasoncode
= cpu_to_le16(REASON_CODE_STA_LEAVING
);
318 lbs_deb_leave(LBS_DEB_JOIN
);
322 int libertas_cmd_80211_associate(wlan_private
* priv
,
323 struct cmd_ds_command
*cmd
, void *pdata_buf
)
325 wlan_adapter
*adapter
= priv
->adapter
;
326 struct cmd_ds_802_11_associate
*passo
= &cmd
->params
.associate
;
328 struct bss_descriptor
*pbssdesc
;
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
;
339 lbs_deb_enter(LBS_DEB_JOIN
);
341 pbssdesc
= pdata_buf
;
349 cmd
->command
= cpu_to_le16(cmd_802_11_associate
);
351 /* Save so we know which BSS Desc to use in the response handler */
352 adapter
->pattemptedbssdesc
= pbssdesc
;
354 memcpy(passo
->peerstaaddr
,
355 pbssdesc
->bssid
, sizeof(passo
->peerstaaddr
));
356 pos
+= sizeof(passo
->peerstaaddr
);
358 /* set the listen interval */
359 passo
->listeninterval
= adapter
->listeninterval
;
361 pos
+= sizeof(passo
->capinfo
);
362 pos
+= sizeof(passo
->listeninterval
);
363 pos
+= sizeof(passo
->bcnperiod
);
364 pos
+= sizeof(passo
->dtimperiod
);
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
);
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
);
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
);
388 rates
= (struct mrvlietypes_ratesparamset
*) pos
;
389 rates
->header
.type
= cpu_to_le16(TLV_TYPE_RATES
);
391 memcpy(&rates
->rates
, &pbssdesc
->libertas_supported_rates
, WLAN_SUPPORTED_RATES
);
393 card_rates
= libertas_supported_rates
;
394 card_rates_size
= sizeof(libertas_supported_rates
);
396 if (get_common_rates(adapter
, rates
->rates
, WLAN_SUPPORTED_RATES
,
397 card_rates
, card_rates_size
)) {
402 rates
->header
.len
= min_t(size_t, strlen(rates
->rates
), WLAN_SUPPORTED_RATES
);
403 adapter
->curbssparams
.numofrates
= rates
->header
.len
;
405 pos
+= sizeof(rates
->header
) + rates
->header
.len
;
406 rates
->header
.len
= cpu_to_le16(rates
->header
.len
);
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
);
420 /* update curbssparams */
421 adapter
->curbssparams
.channel
=
422 (pbssdesc
->phyparamset
.dsparamset
.currentchan
);
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
));
428 lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n", rates
->header
.len
);
431 if (pbssdesc
->mode
== IW_MODE_INFRA
) {
432 #define CAPINFO_ESS_MODE 1
433 passo
->capinfo
.ess
= CAPINFO_ESS_MODE
;
436 if (libertas_parse_dnld_countryinfo_11d(priv
)) {
441 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*) passo
) + S_DS_GEN
);
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
));
452 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
456 int libertas_cmd_80211_ad_hoc_start(wlan_private
* priv
,
457 struct cmd_ds_command
*cmd
, void *pssid
)
459 wlan_adapter
*adapter
= priv
->adapter
;
460 struct cmd_ds_802_11_ad_hoc_start
*adhs
= &cmd
->params
.ads
;
462 int cmdappendsize
= 0;
465 struct bss_descriptor
*pbssdesc
;
466 struct WLAN_802_11_SSID
*ssid
= pssid
;
468 lbs_deb_enter(LBS_DEB_JOIN
);
475 cmd
->command
= cpu_to_le16(cmd_802_11_ad_hoc_start
);
477 pbssdesc
= &adapter
->curbssparams
.bssdescriptor
;
478 adapter
->pattemptedbssdesc
= pbssdesc
;
481 * Fill in the parameters for 2 data structures:
482 * 1. cmd_ds_802_11_ad_hoc_start command
483 * 2. adapter->scantable[i]
485 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
486 * probe delay, and cap info.
488 * Firmware will fill up beacon period, DTIM, Basic rates
489 * and operational rates.
492 memset(adhs
->SSID
, 0, IW_ESSID_MAX_SIZE
);
494 memcpy(adhs
->SSID
, ssid
->ssid
, ssid
->ssidlength
);
496 lbs_deb_join("ADHOC_S_CMD: SSID = %s\n", adhs
->SSID
);
498 memset(pbssdesc
->ssid
.ssid
, 0, IW_ESSID_MAX_SIZE
);
499 memcpy(pbssdesc
->ssid
.ssid
, ssid
->ssid
, ssid
->ssidlength
);
501 pbssdesc
->ssid
.ssidlength
= ssid
->ssidlength
;
503 /* set the BSS type */
504 adhs
->bsstype
= cmd_bss_type_ibss
;
505 pbssdesc
->mode
= IW_MODE_ADHOC
;
506 adhs
->beaconperiod
= adapter
->beaconperiod
;
508 /* set Physical param set */
509 #define DS_PARA_IE_ID 3
510 #define DS_PARA_IE_LEN 1
512 adhs
->phyparamset
.dsparamset
.elementid
= DS_PARA_IE_ID
;
513 adhs
->phyparamset
.dsparamset
.len
= DS_PARA_IE_LEN
;
515 WARN_ON(!adapter
->curbssparams
.channel
);
517 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
518 adapter
->curbssparams
.channel
);
520 pbssdesc
->channel
= adapter
->curbssparams
.channel
;
521 adhs
->phyparamset
.dsparamset
.currentchan
= adapter
->curbssparams
.channel
;
523 memcpy(&pbssdesc
->phyparamset
,
524 &adhs
->phyparamset
, sizeof(union ieeetypes_phyparamset
));
526 /* set IBSS param set */
527 #define IBSS_PARA_IE_ID 6
528 #define IBSS_PARA_IE_LEN 2
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
));
536 /* set capability info */
539 pbssdesc
->cap
.ibss
= 1;
542 adhs
->probedelay
= cpu_to_le16(cmd_scan_probe_delay_time
);
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
;
550 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
551 pbssdesc
->privacy
= wlan802_11privfilteracceptall
;
554 memset(adhs
->datarate
, 0, sizeof(adhs
->datarate
));
556 if (adapter
->adhoc_grate_enabled
) {
557 memcpy(adhs
->datarate
, libertas_adhoc_rates_g
,
558 min(sizeof(adhs
->datarate
), sizeof(libertas_adhoc_rates_g
)));
560 memcpy(adhs
->datarate
, libertas_adhoc_rates_b
,
561 min(sizeof(adhs
->datarate
), sizeof(libertas_adhoc_rates_b
)));
564 /* Find the last non zero */
565 for (i
= 0; i
< sizeof(adhs
->datarate
) && adhs
->datarate
[i
]; i
++) ;
567 adapter
->curbssparams
.numofrates
= i
;
569 /* Copy the ad-hoc creating rates into Current BSS state structure */
570 memcpy(&adapter
->curbssparams
.datarates
,
571 &adhs
->datarate
, adapter
->curbssparams
.numofrates
);
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]);
577 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
579 if (libertas_create_dnld_countryinfo_11d(priv
)) {
580 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
586 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start
)
587 + S_DS_GEN
+ cmdappendsize
);
589 memcpy(&tmpcap
, &adhs
->cap
, sizeof(u16
));
590 tmpcap
= cpu_to_le16(tmpcap
);
591 memcpy(&adhs
->cap
, &tmpcap
, sizeof(u16
));
595 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
599 int libertas_cmd_80211_ad_hoc_stop(wlan_private
* priv
,
600 struct cmd_ds_command
*cmd
)
602 cmd
->command
= cpu_to_le16(cmd_802_11_ad_hoc_stop
);
603 cmd
->size
= cpu_to_le16(S_DS_GEN
);
608 int libertas_cmd_80211_ad_hoc_join(wlan_private
* priv
,
609 struct cmd_ds_command
*cmd
, void *pdata_buf
)
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;
621 lbs_deb_enter(LBS_DEB_JOIN
);
623 adapter
->pattemptedbssdesc
= pbssdesc
;
625 cmd
->command
= cpu_to_le16(cmd_802_11_ad_hoc_join
);
627 padhocjoin
->bssdescriptor
.bsstype
= cmd_bss_type_ibss
;
629 padhocjoin
->bssdescriptor
.beaconperiod
= pbssdesc
->beaconperiod
;
631 memcpy(&padhocjoin
->bssdescriptor
.BSSID
,
632 &pbssdesc
->bssid
, ETH_ALEN
);
634 memcpy(&padhocjoin
->bssdescriptor
.SSID
,
635 &pbssdesc
->ssid
.ssid
, pbssdesc
->ssid
.ssidlength
);
637 memcpy(&padhocjoin
->bssdescriptor
.phyparamset
,
638 &pbssdesc
->phyparamset
, sizeof(union ieeetypes_phyparamset
));
640 memcpy(&padhocjoin
->bssdescriptor
.ssparamset
,
641 &pbssdesc
->ssparamset
, sizeof(union IEEEtypes_ssparamset
));
643 memcpy(&tmpcap
, &pbssdesc
->cap
, sizeof(struct ieeetypes_capinfo
));
644 tmpcap
&= CAPINFO_MASK
;
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
));
651 /* information on BSSID descriptor passed to FW */
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
);
663 padhocjoin
->failtimeout
= cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT
);
666 padhocjoin
->probedelay
=
667 cpu_to_le16(cmd_scan_probe_delay_time
);
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
)));
676 card_rates
= libertas_supported_rates
;
677 card_rates_size
= sizeof(libertas_supported_rates
);
679 adapter
->curbssparams
.channel
= pbssdesc
->channel
;
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");
689 /* Find the last non zero */
690 for (i
= 0; i
< sizeof(padhocjoin
->bssdescriptor
.datarates
)
691 && padhocjoin
->bssdescriptor
.datarates
[i
]; i
++) ;
693 adapter
->curbssparams
.numofrates
= i
;
696 * Copy the adhoc joining rates to Current BSS State structure
698 memcpy(adapter
->curbssparams
.datarates
,
699 padhocjoin
->bssdescriptor
.datarates
,
700 adapter
->curbssparams
.numofrates
);
702 padhocjoin
->bssdescriptor
.ssparamset
.ibssparamset
.atimwindow
=
703 cpu_to_le16(pbssdesc
->atimwindow
);
705 if (adapter
->secinfo
.wep_enabled
) {
706 padhocjoin
->bssdescriptor
.cap
.privacy
= AD_HOC_CAP_PRIVACY_ON
;
709 if (adapter
->psmode
== wlan802_11powermodemax_psp
) {
711 enum WLAN_802_11_POWER_MODE Localpsmode
;
713 Localpsmode
= wlan802_11powermodecam
;
714 ret
= libertas_prepare_and_send_command(priv
,
725 if (libertas_parse_dnld_countryinfo_11d(priv
)) {
731 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join
)
732 + S_DS_GEN
+ cmdappendsize
);
734 memcpy(&tmpcap
, &padhocjoin
->bssdescriptor
.cap
,
735 sizeof(struct ieeetypes_capinfo
));
736 tmpcap
= cpu_to_le16(tmpcap
);
738 memcpy(&padhocjoin
->bssdescriptor
.cap
,
739 &tmpcap
, sizeof(struct ieeetypes_capinfo
));
742 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
746 int libertas_ret_80211_associate(wlan_private
* priv
,
747 struct cmd_ds_command
*resp
)
749 wlan_adapter
*adapter
= priv
->adapter
;
751 union iwreq_data wrqu
;
752 struct ieeetypes_assocrsp
*passocrsp
;
753 struct bss_descriptor
*pbssdesc
;
755 lbs_deb_enter(LBS_DEB_JOIN
);
757 passocrsp
= (struct ieeetypes_assocrsp
*) & resp
->params
;
759 if (passocrsp
->statuscode
) {
761 libertas_mac_event_disconnected(priv
);
763 lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
764 passocrsp
->statuscode
);
770 lbs_dbg_hex("ASSOC_RESP:", (void *)&resp
->params
,
771 le16_to_cpu(resp
->size
) - S_DS_GEN
);
773 /* Send a Media Connected event, according to the Spec */
774 adapter
->connect_status
= libertas_connected
;
776 /* Set the attempted BSSID Index to current */
777 pbssdesc
= adapter
->pattemptedbssdesc
;
779 lbs_deb_join("ASSOC_RESP: %s\n", pbssdesc
->ssid
.ssid
);
781 /* Set the new SSID to current SSID */
782 memcpy(&adapter
->curbssparams
.ssid
,
783 &pbssdesc
->ssid
, sizeof(struct WLAN_802_11_SSID
));
785 /* Set the new BSSID (AP's MAC address) to current BSSID */
786 memcpy(adapter
->curbssparams
.bssid
,
787 pbssdesc
->bssid
, ETH_ALEN
);
789 /* Make a copy of current BSSID descriptor */
790 memcpy(&adapter
->curbssparams
.bssdescriptor
,
791 pbssdesc
, sizeof(struct bss_descriptor
));
793 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
794 adapter
->currentpacketfilter
);
796 adapter
->SNR
[TYPE_RXPD
][TYPE_AVG
] = 0;
797 adapter
->NF
[TYPE_RXPD
][TYPE_AVG
] = 0;
799 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
800 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
801 adapter
->nextSNRNF
= 0;
802 adapter
->numSNRNF
= 0;
804 netif_carrier_on(priv
->dev
);
805 netif_wake_queue(priv
->dev
);
807 netif_carrier_on(priv
->mesh_dev
);
808 netif_wake_queue(priv
->mesh_dev
);
810 lbs_deb_join("ASSOC_RESP: Associated \n");
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
);
817 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
821 int libertas_ret_80211_disassociate(wlan_private
* priv
,
822 struct cmd_ds_command
*resp
)
824 lbs_deb_enter(LBS_DEB_JOIN
);
826 libertas_mac_event_disconnected(priv
);
828 lbs_deb_leave(LBS_DEB_JOIN
);
832 int libertas_ret_80211_ad_hoc_start(wlan_private
* priv
,
833 struct cmd_ds_command
*resp
)
835 wlan_adapter
*adapter
= priv
->adapter
;
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
;
843 lbs_deb_enter(LBS_DEB_JOIN
);
845 padhocresult
= &resp
->params
.result
;
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
);
851 pbssdesc
= adapter
->pattemptedbssdesc
;
854 * Join result code 0 --> SUCCESS
857 lbs_deb_join("ADHOC_RESP failed\n");
858 if (adapter
->connect_status
== libertas_connected
) {
859 libertas_mac_event_disconnected(priv
);
862 memset(&adapter
->curbssparams
.bssdescriptor
,
863 0x00, sizeof(adapter
->curbssparams
.bssdescriptor
));
870 * Now the join cmd should be successful
871 * If BSSID has changed use SSID to compare instead of BSSID
873 lbs_deb_join("ADHOC_J_RESP %s\n", pbssdesc
->ssid
.ssid
);
875 /* Send a Media Connected event, according to the Spec */
876 adapter
->connect_status
= libertas_connected
;
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
);
883 /* Make a copy of current BSSID descriptor, only needed for join since
884 * the current descriptor is already being used for adhoc start
886 memmove(&adapter
->curbssparams
.bssdescriptor
,
887 pbssdesc
, sizeof(struct bss_descriptor
));
890 /* Set the BSSID from the joined/started descriptor */
891 memcpy(&adapter
->curbssparams
.bssid
, pbssdesc
->bssid
, ETH_ALEN
);
893 /* Set the new SSID to current SSID */
894 memcpy(&adapter
->curbssparams
.ssid
,
895 &pbssdesc
->ssid
, sizeof(struct WLAN_802_11_SSID
));
897 netif_carrier_on(priv
->dev
);
898 netif_wake_queue(priv
->dev
);
900 netif_carrier_on(priv
->mesh_dev
);
901 netif_wake_queue(priv
->mesh_dev
);
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
);
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]);
916 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
920 int libertas_ret_80211_ad_hoc_stop(wlan_private
* priv
,
921 struct cmd_ds_command
*resp
)
923 lbs_deb_enter(LBS_DEB_JOIN
);
925 libertas_mac_event_disconnected(priv
);
927 lbs_deb_leave(LBS_DEB_JOIN
);