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>
10 #include <linux/etherdevice.h>
12 #include <net/iw_handler.h>
20 /* Supported rates for ad-hoc B mode */
21 static u8 adhoc_rates_b
[5] = { 0x02, 0x04, 0x0b, 0x16, 0x00 };
23 /* The firmware needs certain bits masked out of the beacon-derviced capability
24 * field when associating/joining to BSSs.
26 #define CAPINFO_MASK (~(0xda00))
29 * @brief This function finds common rates between rate1 and card rates.
31 * It will fill common rates in rate1 as output if found.
33 * NOTE: Setting the MSB of the basic rates need to be taken
34 * care, either before or after calling this function
36 * @param adapter A pointer to wlan_adapter structure
37 * @param rate1 the buffer which keeps input and output
38 * @param rate1_size the size of rate1 buffer; new size of buffer on return
42 static int get_common_rates(wlan_adapter
* adapter
, u8
* rates
, u16
*rates_size
)
44 u8
*card_rates
= libertas_bg_rates
;
45 size_t num_card_rates
= sizeof(libertas_bg_rates
);
50 /* For each rate in card_rates that exists in rate1, copy to tmp */
51 for (i
= 0; card_rates
[i
] && (i
< num_card_rates
); i
++) {
52 for (j
= 0; rates
[j
] && (j
< *rates_size
); j
++) {
53 if (rates
[j
] == card_rates
[i
])
54 tmp
[tmp_size
++] = card_rates
[i
];
58 lbs_deb_hex(LBS_DEB_JOIN
, "AP rates ", rates
, *rates_size
);
59 lbs_deb_hex(LBS_DEB_JOIN
, "card rates ", card_rates
, num_card_rates
);
60 lbs_deb_hex(LBS_DEB_JOIN
, "common rates", tmp
, tmp_size
);
61 lbs_deb_join("Tx datarate is currently 0x%X\n", adapter
->cur_rate
);
63 if (!adapter
->auto_rate
) {
64 for (i
= 0; i
< tmp_size
; i
++) {
65 if (tmp
[i
] == adapter
->cur_rate
)
68 lbs_pr_alert("Previously set fixed data rate %#x isn't "
69 "compatible with the network.\n", adapter
->cur_rate
);
76 memset(rates
, 0, *rates_size
);
77 *rates_size
= min_t(int, tmp_size
, *rates_size
);
78 memcpy(rates
, tmp
, *rates_size
);
84 * @brief Sets the MSB on basic rates as the firmware requires
86 * Scan through an array and set the MSB for basic data rates.
88 * @param rates buffer of data rates
89 * @param len size of buffer
91 static void libertas_set_basic_rate_flags(u8
* rates
, size_t len
)
95 for (i
= 0; i
< len
; i
++) {
96 if (rates
[i
] == 0x02 || rates
[i
] == 0x04 ||
97 rates
[i
] == 0x0b || rates
[i
] == 0x16)
103 * @brief Unsets the MSB on basic rates
105 * Scan through an array and unset the MSB for basic data rates.
107 * @param rates buffer of data rates
108 * @param len size of buffer
110 void libertas_unset_basic_rate_flags(u8
* rates
, size_t len
)
114 for (i
= 0; i
< len
; i
++)
120 * @brief Associate to a specific BSS discovered in a scan
122 * @param priv A pointer to wlan_private structure
123 * @param pbssdesc Pointer to the BSS descriptor to associate with.
125 * @return 0-success, otherwise fail
127 int wlan_associate(wlan_private
* priv
, struct assoc_request
* assoc_req
)
129 wlan_adapter
*adapter
= priv
->adapter
;
132 lbs_deb_enter(LBS_DEB_JOIN
);
134 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AUTHENTICATE
,
135 0, CMD_OPTION_WAITFORRSP
,
136 0, assoc_req
->bss
.bssid
);
141 /* set preamble to firmware */
142 if ( (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
143 && (assoc_req
->bss
.capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
))
144 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
146 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
148 libertas_set_radio_control(priv
);
150 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_ASSOCIATE
,
151 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
154 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
159 * @brief Start an Adhoc Network
161 * @param priv A pointer to wlan_private structure
162 * @param adhocssid The ssid of the Adhoc Network
163 * @return 0--success, -1--fail
165 int libertas_start_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
167 wlan_adapter
*adapter
= priv
->adapter
;
170 adapter
->adhoccreate
= 1;
172 if (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
) {
173 lbs_deb_join("AdhocStart: Short preamble\n");
174 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
176 lbs_deb_join("AdhocStart: Long preamble\n");
177 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
180 libertas_set_radio_control(priv
);
182 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req
->channel
);
183 lbs_deb_join("AdhocStart: band = %d\n", assoc_req
->band
);
185 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_START
,
186 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
192 * @brief Join an adhoc network found in a previous scan
194 * @param priv A pointer to wlan_private structure
195 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
198 * @return 0--success, -1--fail
200 int libertas_join_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
202 wlan_adapter
*adapter
= priv
->adapter
;
203 struct bss_descriptor
* bss
= &assoc_req
->bss
;
206 lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
208 escape_essid(adapter
->curbssparams
.ssid
,
209 adapter
->curbssparams
.ssid_len
),
210 adapter
->curbssparams
.ssid_len
);
211 lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
212 __func__
, escape_essid(bss
->ssid
, bss
->ssid_len
),
215 /* check if the requested SSID is already joined */
216 if ( adapter
->curbssparams
.ssid_len
217 && !libertas_ssid_cmp(adapter
->curbssparams
.ssid
,
218 adapter
->curbssparams
.ssid_len
,
219 bss
->ssid
, bss
->ssid_len
)
220 && (adapter
->mode
== IW_MODE_ADHOC
)
221 && (adapter
->connect_status
== LIBERTAS_CONNECTED
)) {
222 union iwreq_data wrqu
;
224 lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
225 "current, not attempting to re-join");
227 /* Send the re-association event though, because the association
228 * request really was successful, even if just a null-op.
230 memset(&wrqu
, 0, sizeof(wrqu
));
231 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
,
233 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
234 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
238 /* Use shortpreamble only when both creator and card supports
240 if ( !(bss
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
241 || !(adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)) {
242 lbs_deb_join("AdhocJoin: Long preamble\n");
243 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
245 lbs_deb_join("AdhocJoin: Short preamble\n");
246 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
249 libertas_set_radio_control(priv
);
251 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req
->channel
);
252 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req
->band
);
254 adapter
->adhoccreate
= 0;
256 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_JOIN
,
257 0, CMD_OPTION_WAITFORRSP
,
258 OID_802_11_SSID
, assoc_req
);
264 int libertas_stop_adhoc_network(wlan_private
* priv
)
266 return libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_STOP
,
267 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
271 * @brief Send Deauthentication Request
273 * @param priv A pointer to wlan_private structure
274 * @return 0--success, -1--fail
276 int libertas_send_deauthentication(wlan_private
* priv
)
278 return libertas_prepare_and_send_command(priv
, CMD_802_11_DEAUTHENTICATE
,
279 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
283 * @brief This function prepares command of authenticate.
285 * @param priv A pointer to wlan_private structure
286 * @param cmd A pointer to cmd_ds_command structure
287 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
291 int libertas_cmd_80211_authenticate(wlan_private
* priv
,
292 struct cmd_ds_command
*cmd
,
295 wlan_adapter
*adapter
= priv
->adapter
;
296 struct cmd_ds_802_11_authenticate
*pauthenticate
= &cmd
->params
.auth
;
298 u8
*bssid
= pdata_buf
;
300 lbs_deb_enter(LBS_DEB_JOIN
);
302 cmd
->command
= cpu_to_le16(CMD_802_11_AUTHENTICATE
);
303 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate
)
306 /* translate auth mode to 802.11 defined wire value */
307 switch (adapter
->secinfo
.auth_mode
) {
308 case IW_AUTH_ALG_OPEN_SYSTEM
:
309 pauthenticate
->authtype
= 0x00;
311 case IW_AUTH_ALG_SHARED_KEY
:
312 pauthenticate
->authtype
= 0x01;
314 case IW_AUTH_ALG_LEAP
:
315 pauthenticate
->authtype
= 0x80;
318 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
319 adapter
->secinfo
.auth_mode
);
323 memcpy(pauthenticate
->macaddr
, bssid
, ETH_ALEN
);
325 lbs_deb_join("AUTH_CMD: BSSID is : " MAC_FMT
" auth=0x%X\n",
326 MAC_ARG(bssid
), pauthenticate
->authtype
);
330 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
334 int libertas_cmd_80211_deauthenticate(wlan_private
* priv
,
335 struct cmd_ds_command
*cmd
)
337 wlan_adapter
*adapter
= priv
->adapter
;
338 struct cmd_ds_802_11_deauthenticate
*dauth
= &cmd
->params
.deauth
;
340 lbs_deb_enter(LBS_DEB_JOIN
);
342 cmd
->command
= cpu_to_le16(CMD_802_11_DEAUTHENTICATE
);
343 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate
) +
346 /* set AP MAC address */
347 memmove(dauth
->macaddr
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
349 /* Reason code 3 = Station is leaving */
350 #define REASON_CODE_STA_LEAVING 3
351 dauth
->reasoncode
= cpu_to_le16(REASON_CODE_STA_LEAVING
);
353 lbs_deb_leave(LBS_DEB_JOIN
);
357 int libertas_cmd_80211_associate(wlan_private
* priv
,
358 struct cmd_ds_command
*cmd
, void *pdata_buf
)
360 wlan_adapter
*adapter
= priv
->adapter
;
361 struct cmd_ds_802_11_associate
*passo
= &cmd
->params
.associate
;
363 struct assoc_request
* assoc_req
= pdata_buf
;
364 struct bss_descriptor
* bss
= &assoc_req
->bss
;
367 struct mrvlietypes_ssidparamset
*ssid
;
368 struct mrvlietypes_phyparamset
*phy
;
369 struct mrvlietypes_ssparamset
*ss
;
370 struct mrvlietypes_ratesparamset
*rates
;
371 struct mrvlietypes_rsnparamset
*rsn
;
373 lbs_deb_enter(LBS_DEB_JOIN
);
382 cmd
->command
= cpu_to_le16(CMD_802_11_ASSOCIATE
);
384 memcpy(passo
->peerstaaddr
, bss
->bssid
, sizeof(passo
->peerstaaddr
));
385 pos
+= sizeof(passo
->peerstaaddr
);
387 /* set the listen interval */
388 passo
->listeninterval
= cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL
);
390 pos
+= sizeof(passo
->capability
);
391 pos
+= sizeof(passo
->listeninterval
);
392 pos
+= sizeof(passo
->bcnperiod
);
393 pos
+= sizeof(passo
->dtimperiod
);
395 ssid
= (struct mrvlietypes_ssidparamset
*) pos
;
396 ssid
->header
.type
= cpu_to_le16(TLV_TYPE_SSID
);
397 tmplen
= bss
->ssid_len
;
398 ssid
->header
.len
= cpu_to_le16(tmplen
);
399 memcpy(ssid
->ssid
, bss
->ssid
, tmplen
);
400 pos
+= sizeof(ssid
->header
) + tmplen
;
402 phy
= (struct mrvlietypes_phyparamset
*) pos
;
403 phy
->header
.type
= cpu_to_le16(TLV_TYPE_PHY_DS
);
404 tmplen
= sizeof(phy
->fh_ds
.dsparamset
);
405 phy
->header
.len
= cpu_to_le16(tmplen
);
406 memcpy(&phy
->fh_ds
.dsparamset
,
407 &bss
->phyparamset
.dsparamset
.currentchan
,
409 pos
+= sizeof(phy
->header
) + tmplen
;
411 ss
= (struct mrvlietypes_ssparamset
*) pos
;
412 ss
->header
.type
= cpu_to_le16(TLV_TYPE_CF
);
413 tmplen
= sizeof(ss
->cf_ibss
.cfparamset
);
414 ss
->header
.len
= cpu_to_le16(tmplen
);
415 pos
+= sizeof(ss
->header
) + tmplen
;
417 rates
= (struct mrvlietypes_ratesparamset
*) pos
;
418 rates
->header
.type
= cpu_to_le16(TLV_TYPE_RATES
);
419 memcpy(&rates
->rates
, &bss
->rates
, MAX_RATES
);
421 if (get_common_rates(adapter
, rates
->rates
, &tmplen
)) {
425 pos
+= sizeof(rates
->header
) + tmplen
;
426 rates
->header
.len
= cpu_to_le16(tmplen
);
427 lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen
);
429 /* Copy the infra. association rates into Current BSS state structure */
430 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
431 memcpy(&adapter
->curbssparams
.rates
, &rates
->rates
, tmplen
);
433 /* Set MSB on basic rates as the firmware requires, but _after_
434 * copying to current bss rates.
436 libertas_set_basic_rate_flags(rates
->rates
, tmplen
);
438 if (assoc_req
->secinfo
.WPAenabled
|| assoc_req
->secinfo
.WPA2enabled
) {
439 rsn
= (struct mrvlietypes_rsnparamset
*) pos
;
440 /* WPA_IE or WPA2_IE */
441 rsn
->header
.type
= cpu_to_le16((u16
) assoc_req
->wpa_ie
[0]);
442 tmplen
= (u16
) assoc_req
->wpa_ie
[1];
443 rsn
->header
.len
= cpu_to_le16(tmplen
);
444 memcpy(rsn
->rsnie
, &assoc_req
->wpa_ie
[2], tmplen
);
445 lbs_deb_hex(LBS_DEB_JOIN
, "ASSOC_CMD: RSN IE", (u8
*) rsn
,
446 sizeof(rsn
->header
) + tmplen
);
447 pos
+= sizeof(rsn
->header
) + tmplen
;
450 /* update curbssparams */
451 adapter
->curbssparams
.channel
= bss
->phyparamset
.dsparamset
.currentchan
;
453 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
458 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*) passo
) + S_DS_GEN
);
460 /* set the capability info */
461 tmpcap
= (bss
->capability
& CAPINFO_MASK
);
462 if (bss
->mode
== IW_MODE_INFRA
)
463 tmpcap
|= WLAN_CAPABILITY_ESS
;
464 passo
->capability
= cpu_to_le16(tmpcap
);
465 lbs_deb_join("ASSOC_CMD: capability=%4X CAPINFO_MASK=%4X\n",
466 tmpcap
, CAPINFO_MASK
);
469 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
473 int libertas_cmd_80211_ad_hoc_start(wlan_private
* priv
,
474 struct cmd_ds_command
*cmd
, void *pdata_buf
)
476 wlan_adapter
*adapter
= priv
->adapter
;
477 struct cmd_ds_802_11_ad_hoc_start
*adhs
= &cmd
->params
.ads
;
479 int cmdappendsize
= 0;
480 struct assoc_request
* assoc_req
= pdata_buf
;
484 lbs_deb_enter(LBS_DEB_JOIN
);
491 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_START
);
494 * Fill in the parameters for 2 data structures:
495 * 1. cmd_ds_802_11_ad_hoc_start command
496 * 2. adapter->scantable[i]
498 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
499 * probe delay, and cap info.
501 * Firmware will fill up beacon period, DTIM, Basic rates
502 * and operational rates.
505 memset(adhs
->ssid
, 0, IW_ESSID_MAX_SIZE
);
506 memcpy(adhs
->ssid
, assoc_req
->ssid
, assoc_req
->ssid_len
);
508 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
509 escape_essid(assoc_req
->ssid
, assoc_req
->ssid_len
),
510 assoc_req
->ssid_len
);
512 /* set the BSS type */
513 adhs
->bsstype
= CMD_BSS_TYPE_IBSS
;
514 adapter
->mode
= IW_MODE_ADHOC
;
515 adhs
->beaconperiod
= cpu_to_le16(MRVDRV_BEACON_INTERVAL
);
517 /* set Physical param set */
518 #define DS_PARA_IE_ID 3
519 #define DS_PARA_IE_LEN 1
521 adhs
->phyparamset
.dsparamset
.elementid
= DS_PARA_IE_ID
;
522 adhs
->phyparamset
.dsparamset
.len
= DS_PARA_IE_LEN
;
524 WARN_ON(!assoc_req
->channel
);
526 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
529 adhs
->phyparamset
.dsparamset
.currentchan
= assoc_req
->channel
;
531 /* set IBSS param set */
532 #define IBSS_PARA_IE_ID 6
533 #define IBSS_PARA_IE_LEN 2
535 adhs
->ssparamset
.ibssparamset
.elementid
= IBSS_PARA_IE_ID
;
536 adhs
->ssparamset
.ibssparamset
.len
= IBSS_PARA_IE_LEN
;
537 adhs
->ssparamset
.ibssparamset
.atimwindow
= 0;
539 /* set capability info */
540 tmpcap
= WLAN_CAPABILITY_IBSS
;
541 if (assoc_req
->secinfo
.wep_enabled
) {
542 lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
543 tmpcap
|= WLAN_CAPABILITY_PRIVACY
;
545 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
547 adhs
->capability
= cpu_to_le16(tmpcap
);
550 adhs
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
552 memset(adhs
->rates
, 0, sizeof(adhs
->rates
));
553 ratesize
= min(sizeof(adhs
->rates
), sizeof(adhoc_rates_b
));
554 memcpy(adhs
->rates
, adhoc_rates_b
, ratesize
);
556 /* Copy the ad-hoc creating rates into Current BSS state structure */
557 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
558 memcpy(&adapter
->curbssparams
.rates
, &adhs
->rates
, ratesize
);
560 /* Set MSB on basic rates as the firmware requires, but _after_
561 * copying to current bss rates.
563 libertas_set_basic_rate_flags(adhs
->rates
, ratesize
);
565 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
566 adhs
->rates
[0], adhs
->rates
[1], adhs
->rates
[2], adhs
->rates
[3]);
568 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
570 if (libertas_create_dnld_countryinfo_11d(priv
)) {
571 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
576 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start
) +
577 S_DS_GEN
+ cmdappendsize
);
581 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
585 int libertas_cmd_80211_ad_hoc_stop(wlan_private
* priv
,
586 struct cmd_ds_command
*cmd
)
588 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_STOP
);
589 cmd
->size
= cpu_to_le16(S_DS_GEN
);
594 int libertas_cmd_80211_ad_hoc_join(wlan_private
* priv
,
595 struct cmd_ds_command
*cmd
, void *pdata_buf
)
597 wlan_adapter
*adapter
= priv
->adapter
;
598 struct cmd_ds_802_11_ad_hoc_join
*join_cmd
= &cmd
->params
.adj
;
599 struct assoc_request
* assoc_req
= pdata_buf
;
600 struct bss_descriptor
*bss
= &assoc_req
->bss
;
601 int cmdappendsize
= 0;
605 lbs_deb_enter(LBS_DEB_JOIN
);
607 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_JOIN
);
609 join_cmd
->bss
.type
= CMD_BSS_TYPE_IBSS
;
610 join_cmd
->bss
.beaconperiod
= cpu_to_le16(bss
->beaconperiod
);
612 memcpy(&join_cmd
->bss
.bssid
, &bss
->bssid
, ETH_ALEN
);
613 memcpy(&join_cmd
->bss
.ssid
, &bss
->ssid
, bss
->ssid_len
);
615 memcpy(&join_cmd
->bss
.phyparamset
, &bss
->phyparamset
,
616 sizeof(union ieeetypes_phyparamset
));
618 memcpy(&join_cmd
->bss
.ssparamset
, &bss
->ssparamset
,
619 sizeof(union IEEEtypes_ssparamset
));
621 join_cmd
->bss
.capability
= cpu_to_le16(bss
->capability
& CAPINFO_MASK
);
622 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
623 bss
->capability
, CAPINFO_MASK
);
625 /* information on BSSID descriptor passed to FW */
627 "ADHOC_J_CMD: BSSID = " MAC_FMT
", SSID = '%s'\n",
628 MAC_ARG(join_cmd
->bss
.bssid
), join_cmd
->bss
.ssid
);
631 join_cmd
->failtimeout
= cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT
);
634 join_cmd
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
636 adapter
->curbssparams
.channel
= bss
->channel
;
638 /* Copy Data rates from the rates recorded in scan response */
639 memset(join_cmd
->bss
.rates
, 0, sizeof(join_cmd
->bss
.rates
));
640 ratesize
= min_t(u16
, sizeof(join_cmd
->bss
.rates
), MAX_RATES
);
641 memcpy(join_cmd
->bss
.rates
, bss
->rates
, ratesize
);
642 if (get_common_rates(adapter
, join_cmd
->bss
.rates
, &ratesize
)) {
643 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
648 /* Copy the ad-hoc creating rates into Current BSS state structure */
649 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
650 memcpy(&adapter
->curbssparams
.rates
, join_cmd
->bss
.rates
, ratesize
);
652 /* Set MSB on basic rates as the firmware requires, but _after_
653 * copying to current bss rates.
655 libertas_set_basic_rate_flags(join_cmd
->bss
.rates
, ratesize
);
657 join_cmd
->bss
.ssparamset
.ibssparamset
.atimwindow
=
658 cpu_to_le16(bss
->atimwindow
);
660 if (assoc_req
->secinfo
.wep_enabled
) {
661 u16 tmp
= le16_to_cpu(join_cmd
->bss
.capability
);
662 tmp
|= WLAN_CAPABILITY_PRIVACY
;
663 join_cmd
->bss
.capability
= cpu_to_le16(tmp
);
666 if (adapter
->psmode
== WLAN802_11POWERMODEMAX_PSP
) {
670 Localpsmode
= cpu_to_le32(WLAN802_11POWERMODECAM
);
671 ret
= libertas_prepare_and_send_command(priv
,
682 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
687 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join
) +
688 S_DS_GEN
+ cmdappendsize
);
691 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
695 int libertas_ret_80211_associate(wlan_private
* priv
,
696 struct cmd_ds_command
*resp
)
698 wlan_adapter
*adapter
= priv
->adapter
;
700 union iwreq_data wrqu
;
701 struct ieeetypes_assocrsp
*passocrsp
;
702 struct bss_descriptor
* bss
;
705 lbs_deb_enter(LBS_DEB_JOIN
);
707 if (!adapter
->in_progress_assoc_req
) {
708 lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
712 bss
= &adapter
->in_progress_assoc_req
->bss
;
714 passocrsp
= (struct ieeetypes_assocrsp
*) & resp
->params
;
717 * Older FW versions map the IEEE 802.11 Status Code in the association
718 * response to the following values returned in passocrsp->statuscode:
720 * IEEE Status Code Marvell Status Code
721 * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
722 * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
723 * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
724 * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
725 * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
726 * others -> 0x0003 ASSOC_RESULT_REFUSED
728 * Other response codes:
729 * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
730 * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
731 * association response from the AP)
734 status_code
= le16_to_cpu(passocrsp
->statuscode
);
735 switch (status_code
) {
737 lbs_deb_join("ASSOC_RESP: Association succeeded\n");
740 lbs_deb_join("ASSOC_RESP: Association failed; invalid "
741 "parameters (status code %d)\n", status_code
);
744 lbs_deb_join("ASSOC_RESP: Association failed; internal timer "
745 "expired while waiting for the AP (status code %d)"
749 lbs_deb_join("ASSOC_RESP: Association failed; association "
750 "was refused by the AP (status code %d)\n",
754 lbs_deb_join("ASSOC_RESP: Association failed; authentication "
755 "was refused by the AP (status code %d)\n",
759 lbs_deb_join("ASSOC_RESP: Association failed; reason unknown "
760 "(status code %d)\n", status_code
);
765 libertas_mac_event_disconnected(priv
);
770 lbs_deb_hex(LBS_DEB_JOIN
, "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 lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
777 escape_essid(bss
->ssid
, bss
->ssid_len
));
779 /* Update current SSID and BSSID */
780 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
781 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
782 memcpy(adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
784 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
785 adapter
->currentpacketfilter
);
787 adapter
->SNR
[TYPE_RXPD
][TYPE_AVG
] = 0;
788 adapter
->NF
[TYPE_RXPD
][TYPE_AVG
] = 0;
790 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
791 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
792 adapter
->nextSNRNF
= 0;
793 adapter
->numSNRNF
= 0;
795 netif_carrier_on(priv
->dev
);
796 netif_wake_queue(priv
->dev
);
798 if (priv
->mesh_dev
) {
799 netif_carrier_on(priv
->mesh_dev
);
800 netif_wake_queue(priv
->mesh_dev
);
803 lbs_deb_join("ASSOC_RESP: Associated \n");
805 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
806 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
807 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
810 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
814 int libertas_ret_80211_disassociate(wlan_private
* priv
,
815 struct cmd_ds_command
*resp
)
817 lbs_deb_enter(LBS_DEB_JOIN
);
819 libertas_mac_event_disconnected(priv
);
821 lbs_deb_leave(LBS_DEB_JOIN
);
825 int libertas_ret_80211_ad_hoc_start(wlan_private
* priv
,
826 struct cmd_ds_command
*resp
)
828 wlan_adapter
*adapter
= priv
->adapter
;
830 u16 command
= le16_to_cpu(resp
->command
);
831 u16 result
= le16_to_cpu(resp
->result
);
832 struct cmd_ds_802_11_ad_hoc_result
*padhocresult
;
833 union iwreq_data wrqu
;
834 struct bss_descriptor
*bss
;
836 lbs_deb_enter(LBS_DEB_JOIN
);
838 padhocresult
= &resp
->params
.result
;
840 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp
->size
));
841 lbs_deb_join("ADHOC_RESP: command = %x\n", command
);
842 lbs_deb_join("ADHOC_RESP: result = %x\n", result
);
844 if (!adapter
->in_progress_assoc_req
) {
845 lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
849 bss
= &adapter
->in_progress_assoc_req
->bss
;
852 * Join result code 0 --> SUCCESS
855 lbs_deb_join("ADHOC_RESP: failed\n");
856 if (adapter
->connect_status
== LIBERTAS_CONNECTED
) {
857 libertas_mac_event_disconnected(priv
);
864 * Now the join cmd should be successful
865 * If BSSID has changed use SSID to compare instead of BSSID
867 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
868 escape_essid(bss
->ssid
, bss
->ssid_len
));
870 /* Send a Media Connected event, according to the Spec */
871 adapter
->connect_status
= LIBERTAS_CONNECTED
;
873 if (command
== CMD_RET(CMD_802_11_AD_HOC_START
)) {
874 /* Update the created network descriptor with the new BSSID */
875 memcpy(bss
->bssid
, padhocresult
->bssid
, ETH_ALEN
);
878 /* Set the BSSID from the joined/started descriptor */
879 memcpy(&adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
881 /* Set the new SSID to current SSID */
882 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
883 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
885 netif_carrier_on(priv
->dev
);
886 netif_wake_queue(priv
->dev
);
888 if (priv
->mesh_dev
) {
889 netif_carrier_on(priv
->mesh_dev
);
890 netif_wake_queue(priv
->mesh_dev
);
893 memset(&wrqu
, 0, sizeof(wrqu
));
894 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
895 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
896 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
898 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
899 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter
->curbssparams
.channel
);
900 lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT
"\n",
901 MAC_ARG(padhocresult
->bssid
));
904 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
908 int libertas_ret_80211_ad_hoc_stop(wlan_private
* priv
,
909 struct cmd_ds_command
*resp
)
911 lbs_deb_enter(LBS_DEB_JOIN
);
913 libertas_mac_event_disconnected(priv
);
915 lbs_deb_leave(LBS_DEB_JOIN
);