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 /* The firmware needs certain bits masked out of the beacon-derviced capability
21 * field when associating/joining to BSSs.
23 #define CAPINFO_MASK (~(0xda00))
26 * @brief This function finds common rates between rate1 and card rates.
28 * It will fill common rates in rate1 as output if found.
30 * NOTE: Setting the MSB of the basic rates need to be taken
31 * care, either before or after calling this function
33 * @param adapter A pointer to struct lbs_adapter structure
34 * @param rate1 the buffer which keeps input and output
35 * @param rate1_size the size of rate1 buffer; new size of buffer on return
39 static int get_common_rates(struct lbs_adapter
*adapter
,
43 u8
*card_rates
= lbs_bg_rates
;
44 size_t num_card_rates
= sizeof(lbs_bg_rates
);
49 /* For each rate in card_rates that exists in rate1, copy to tmp */
50 for (i
= 0; card_rates
[i
] && (i
< num_card_rates
); i
++) {
51 for (j
= 0; rates
[j
] && (j
< *rates_size
); j
++) {
52 if (rates
[j
] == card_rates
[i
])
53 tmp
[tmp_size
++] = card_rates
[i
];
57 lbs_deb_hex(LBS_DEB_JOIN
, "AP rates ", rates
, *rates_size
);
58 lbs_deb_hex(LBS_DEB_JOIN
, "card rates ", card_rates
, num_card_rates
);
59 lbs_deb_hex(LBS_DEB_JOIN
, "common rates", tmp
, tmp_size
);
60 lbs_deb_join("Tx datarate is currently 0x%X\n", adapter
->cur_rate
);
62 if (!adapter
->auto_rate
) {
63 for (i
= 0; i
< tmp_size
; i
++) {
64 if (tmp
[i
] == adapter
->cur_rate
)
67 lbs_pr_alert("Previously set fixed data rate %#x isn't "
68 "compatible with the network.\n", adapter
->cur_rate
);
75 memset(rates
, 0, *rates_size
);
76 *rates_size
= min_t(int, tmp_size
, *rates_size
);
77 memcpy(rates
, tmp
, *rates_size
);
83 * @brief Sets the MSB on basic rates as the firmware requires
85 * Scan through an array and set the MSB for basic data rates.
87 * @param rates buffer of data rates
88 * @param len size of buffer
90 static void lbs_set_basic_rate_flags(u8
*rates
, size_t len
)
94 for (i
= 0; i
< len
; i
++) {
95 if (rates
[i
] == 0x02 || rates
[i
] == 0x04 ||
96 rates
[i
] == 0x0b || rates
[i
] == 0x16)
102 * @brief Unsets the MSB on basic rates
104 * Scan through an array and unset the MSB for basic data rates.
106 * @param rates buffer of data rates
107 * @param len size of buffer
109 void lbs_unset_basic_rate_flags(u8
*rates
, size_t len
)
113 for (i
= 0; i
< len
; i
++)
119 * @brief Associate to a specific BSS discovered in a scan
121 * @param priv A pointer to struct lbs_private structure
122 * @param pbssdesc Pointer to the BSS descriptor to associate with.
124 * @return 0-success, otherwise fail
126 int lbs_associate(struct lbs_private
*priv
, struct assoc_request
*assoc_req
)
128 struct lbs_adapter
*adapter
= priv
->adapter
;
131 lbs_deb_enter(LBS_DEB_JOIN
);
133 ret
= lbs_prepare_and_send_command(priv
, CMD_802_11_AUTHENTICATE
,
134 0, CMD_OPTION_WAITFORRSP
,
135 0, assoc_req
->bss
.bssid
);
140 /* set preamble to firmware */
141 if ( (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
142 && (assoc_req
->bss
.capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
))
143 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
145 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
147 lbs_set_radio_control(priv
);
149 ret
= lbs_prepare_and_send_command(priv
, CMD_802_11_ASSOCIATE
,
150 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
153 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
158 * @brief Start an Adhoc Network
160 * @param priv A pointer to struct lbs_private structure
161 * @param adhocssid The ssid of the Adhoc Network
162 * @return 0--success, -1--fail
164 int lbs_start_adhoc_network(struct lbs_private
*priv
,
165 struct assoc_request
*assoc_req
)
167 struct lbs_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 lbs_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
= lbs_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 struct lbs_private structure
195 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
198 * @return 0--success, -1--fail
200 int lbs_join_adhoc_network(struct lbs_private
*priv
,
201 struct assoc_request
*assoc_req
)
203 struct lbs_adapter
*adapter
= priv
->adapter
;
204 struct bss_descriptor
* bss
= &assoc_req
->bss
;
207 lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
209 escape_essid(adapter
->curbssparams
.ssid
,
210 adapter
->curbssparams
.ssid_len
),
211 adapter
->curbssparams
.ssid_len
);
212 lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
213 __func__
, escape_essid(bss
->ssid
, bss
->ssid_len
),
216 /* check if the requested SSID is already joined */
217 if ( adapter
->curbssparams
.ssid_len
218 && !lbs_ssid_cmp(adapter
->curbssparams
.ssid
,
219 adapter
->curbssparams
.ssid_len
,
220 bss
->ssid
, bss
->ssid_len
)
221 && (adapter
->mode
== IW_MODE_ADHOC
)
222 && (adapter
->connect_status
== LBS_CONNECTED
)) {
223 union iwreq_data wrqu
;
225 lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
226 "current, not attempting to re-join");
228 /* Send the re-association event though, because the association
229 * request really was successful, even if just a null-op.
231 memset(&wrqu
, 0, sizeof(wrqu
));
232 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
,
234 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
235 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
239 /* Use shortpreamble only when both creator and card supports
241 if ( !(bss
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
242 || !(adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)) {
243 lbs_deb_join("AdhocJoin: Long preamble\n");
244 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
246 lbs_deb_join("AdhocJoin: Short preamble\n");
247 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
250 lbs_set_radio_control(priv
);
252 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req
->channel
);
253 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req
->band
);
255 adapter
->adhoccreate
= 0;
257 ret
= lbs_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_JOIN
,
258 0, CMD_OPTION_WAITFORRSP
,
259 OID_802_11_SSID
, assoc_req
);
265 int lbs_stop_adhoc_network(struct lbs_private
*priv
)
267 return lbs_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_STOP
,
268 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
272 * @brief Send Deauthentication Request
274 * @param priv A pointer to struct lbs_private structure
275 * @return 0--success, -1--fail
277 int lbs_send_deauthentication(struct lbs_private
*priv
)
279 return lbs_prepare_and_send_command(priv
, CMD_802_11_DEAUTHENTICATE
,
280 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
284 * @brief This function prepares command of authenticate.
286 * @param priv A pointer to struct lbs_private structure
287 * @param cmd A pointer to cmd_ds_command structure
288 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
292 int lbs_cmd_80211_authenticate(struct lbs_private
*priv
,
293 struct cmd_ds_command
*cmd
,
296 struct lbs_adapter
*adapter
= priv
->adapter
;
297 struct cmd_ds_802_11_authenticate
*pauthenticate
= &cmd
->params
.auth
;
299 u8
*bssid
= pdata_buf
;
300 DECLARE_MAC_BUF(mac
);
302 lbs_deb_enter(LBS_DEB_JOIN
);
304 cmd
->command
= cpu_to_le16(CMD_802_11_AUTHENTICATE
);
305 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate
)
308 /* translate auth mode to 802.11 defined wire value */
309 switch (adapter
->secinfo
.auth_mode
) {
310 case IW_AUTH_ALG_OPEN_SYSTEM
:
311 pauthenticate
->authtype
= 0x00;
313 case IW_AUTH_ALG_SHARED_KEY
:
314 pauthenticate
->authtype
= 0x01;
316 case IW_AUTH_ALG_LEAP
:
317 pauthenticate
->authtype
= 0x80;
320 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
321 adapter
->secinfo
.auth_mode
);
325 memcpy(pauthenticate
->macaddr
, bssid
, ETH_ALEN
);
327 lbs_deb_join("AUTH_CMD: BSSID is : %s auth=0x%X\n",
328 print_mac(mac
, bssid
), pauthenticate
->authtype
);
332 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
336 int lbs_cmd_80211_deauthenticate(struct lbs_private
*priv
,
337 struct cmd_ds_command
*cmd
)
339 struct lbs_adapter
*adapter
= priv
->adapter
;
340 struct cmd_ds_802_11_deauthenticate
*dauth
= &cmd
->params
.deauth
;
342 lbs_deb_enter(LBS_DEB_JOIN
);
344 cmd
->command
= cpu_to_le16(CMD_802_11_DEAUTHENTICATE
);
345 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate
) +
348 /* set AP MAC address */
349 memmove(dauth
->macaddr
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
351 /* Reason code 3 = Station is leaving */
352 #define REASON_CODE_STA_LEAVING 3
353 dauth
->reasoncode
= cpu_to_le16(REASON_CODE_STA_LEAVING
);
355 lbs_deb_leave(LBS_DEB_JOIN
);
359 int lbs_cmd_80211_associate(struct lbs_private
*priv
,
360 struct cmd_ds_command
*cmd
, void *pdata_buf
)
362 struct lbs_adapter
*adapter
= priv
->adapter
;
363 struct cmd_ds_802_11_associate
*passo
= &cmd
->params
.associate
;
365 struct assoc_request
* assoc_req
= pdata_buf
;
366 struct bss_descriptor
* bss
= &assoc_req
->bss
;
369 struct mrvlietypes_ssidparamset
*ssid
;
370 struct mrvlietypes_phyparamset
*phy
;
371 struct mrvlietypes_ssparamset
*ss
;
372 struct mrvlietypes_ratesparamset
*rates
;
373 struct mrvlietypes_rsnparamset
*rsn
;
375 lbs_deb_enter(LBS_DEB_JOIN
);
384 cmd
->command
= cpu_to_le16(CMD_802_11_ASSOCIATE
);
386 memcpy(passo
->peerstaaddr
, bss
->bssid
, sizeof(passo
->peerstaaddr
));
387 pos
+= sizeof(passo
->peerstaaddr
);
389 /* set the listen interval */
390 passo
->listeninterval
= cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL
);
392 pos
+= sizeof(passo
->capability
);
393 pos
+= sizeof(passo
->listeninterval
);
394 pos
+= sizeof(passo
->bcnperiod
);
395 pos
+= sizeof(passo
->dtimperiod
);
397 ssid
= (struct mrvlietypes_ssidparamset
*) pos
;
398 ssid
->header
.type
= cpu_to_le16(TLV_TYPE_SSID
);
399 tmplen
= bss
->ssid_len
;
400 ssid
->header
.len
= cpu_to_le16(tmplen
);
401 memcpy(ssid
->ssid
, bss
->ssid
, tmplen
);
402 pos
+= sizeof(ssid
->header
) + tmplen
;
404 phy
= (struct mrvlietypes_phyparamset
*) pos
;
405 phy
->header
.type
= cpu_to_le16(TLV_TYPE_PHY_DS
);
406 tmplen
= sizeof(phy
->fh_ds
.dsparamset
);
407 phy
->header
.len
= cpu_to_le16(tmplen
);
408 memcpy(&phy
->fh_ds
.dsparamset
,
409 &bss
->phyparamset
.dsparamset
.currentchan
,
411 pos
+= sizeof(phy
->header
) + tmplen
;
413 ss
= (struct mrvlietypes_ssparamset
*) pos
;
414 ss
->header
.type
= cpu_to_le16(TLV_TYPE_CF
);
415 tmplen
= sizeof(ss
->cf_ibss
.cfparamset
);
416 ss
->header
.len
= cpu_to_le16(tmplen
);
417 pos
+= sizeof(ss
->header
) + tmplen
;
419 rates
= (struct mrvlietypes_ratesparamset
*) pos
;
420 rates
->header
.type
= cpu_to_le16(TLV_TYPE_RATES
);
421 memcpy(&rates
->rates
, &bss
->rates
, MAX_RATES
);
423 if (get_common_rates(adapter
, rates
->rates
, &tmplen
)) {
427 pos
+= sizeof(rates
->header
) + tmplen
;
428 rates
->header
.len
= cpu_to_le16(tmplen
);
429 lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen
);
431 /* Copy the infra. association rates into Current BSS state structure */
432 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
433 memcpy(&adapter
->curbssparams
.rates
, &rates
->rates
, tmplen
);
435 /* Set MSB on basic rates as the firmware requires, but _after_
436 * copying to current bss rates.
438 lbs_set_basic_rate_flags(rates
->rates
, tmplen
);
440 if (assoc_req
->secinfo
.WPAenabled
|| assoc_req
->secinfo
.WPA2enabled
) {
441 rsn
= (struct mrvlietypes_rsnparamset
*) pos
;
442 /* WPA_IE or WPA2_IE */
443 rsn
->header
.type
= cpu_to_le16((u16
) assoc_req
->wpa_ie
[0]);
444 tmplen
= (u16
) assoc_req
->wpa_ie
[1];
445 rsn
->header
.len
= cpu_to_le16(tmplen
);
446 memcpy(rsn
->rsnie
, &assoc_req
->wpa_ie
[2], tmplen
);
447 lbs_deb_hex(LBS_DEB_JOIN
, "ASSOC_CMD: RSN IE", (u8
*) rsn
,
448 sizeof(rsn
->header
) + tmplen
);
449 pos
+= sizeof(rsn
->header
) + tmplen
;
452 /* update curbssparams */
453 adapter
->curbssparams
.channel
= bss
->phyparamset
.dsparamset
.currentchan
;
455 if (lbs_parse_dnld_countryinfo_11d(priv
, bss
)) {
460 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*) passo
) + S_DS_GEN
);
462 /* set the capability info */
463 tmpcap
= (bss
->capability
& CAPINFO_MASK
);
464 if (bss
->mode
== IW_MODE_INFRA
)
465 tmpcap
|= WLAN_CAPABILITY_ESS
;
466 passo
->capability
= cpu_to_le16(tmpcap
);
467 lbs_deb_join("ASSOC_CMD: capability=%4X CAPINFO_MASK=%4X\n",
468 tmpcap
, CAPINFO_MASK
);
471 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
475 int lbs_cmd_80211_ad_hoc_start(struct lbs_private
*priv
,
476 struct cmd_ds_command
*cmd
, void *pdata_buf
)
478 struct lbs_adapter
*adapter
= priv
->adapter
;
479 struct cmd_ds_802_11_ad_hoc_start
*adhs
= &cmd
->params
.ads
;
481 int cmdappendsize
= 0;
482 struct assoc_request
* assoc_req
= pdata_buf
;
486 lbs_deb_enter(LBS_DEB_JOIN
);
493 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_START
);
496 * Fill in the parameters for 2 data structures:
497 * 1. cmd_ds_802_11_ad_hoc_start command
498 * 2. adapter->scantable[i]
500 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
501 * probe delay, and cap info.
503 * Firmware will fill up beacon period, DTIM, Basic rates
504 * and operational rates.
507 memset(adhs
->ssid
, 0, IW_ESSID_MAX_SIZE
);
508 memcpy(adhs
->ssid
, assoc_req
->ssid
, assoc_req
->ssid_len
);
510 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
511 escape_essid(assoc_req
->ssid
, assoc_req
->ssid_len
),
512 assoc_req
->ssid_len
);
514 /* set the BSS type */
515 adhs
->bsstype
= CMD_BSS_TYPE_IBSS
;
516 adapter
->mode
= IW_MODE_ADHOC
;
517 if (adapter
->beacon_period
== 0)
518 adapter
->beacon_period
= MRVDRV_BEACON_INTERVAL
;
519 adhs
->beaconperiod
= cpu_to_le16(adapter
->beacon_period
);
521 /* set Physical param set */
522 #define DS_PARA_IE_ID 3
523 #define DS_PARA_IE_LEN 1
525 adhs
->phyparamset
.dsparamset
.elementid
= DS_PARA_IE_ID
;
526 adhs
->phyparamset
.dsparamset
.len
= DS_PARA_IE_LEN
;
528 WARN_ON(!assoc_req
->channel
);
530 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
533 adhs
->phyparamset
.dsparamset
.currentchan
= assoc_req
->channel
;
535 /* set IBSS param set */
536 #define IBSS_PARA_IE_ID 6
537 #define IBSS_PARA_IE_LEN 2
539 adhs
->ssparamset
.ibssparamset
.elementid
= IBSS_PARA_IE_ID
;
540 adhs
->ssparamset
.ibssparamset
.len
= IBSS_PARA_IE_LEN
;
541 adhs
->ssparamset
.ibssparamset
.atimwindow
= 0;
543 /* set capability info */
544 tmpcap
= WLAN_CAPABILITY_IBSS
;
545 if (assoc_req
->secinfo
.wep_enabled
) {
546 lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
547 tmpcap
|= WLAN_CAPABILITY_PRIVACY
;
549 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
551 adhs
->capability
= cpu_to_le16(tmpcap
);
554 adhs
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
556 memset(adhs
->rates
, 0, sizeof(adhs
->rates
));
557 ratesize
= min(sizeof(adhs
->rates
), sizeof(lbs_bg_rates
));
558 memcpy(adhs
->rates
, lbs_bg_rates
, ratesize
);
560 /* Copy the ad-hoc creating rates into Current BSS state structure */
561 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
562 memcpy(&adapter
->curbssparams
.rates
, &adhs
->rates
, ratesize
);
564 /* Set MSB on basic rates as the firmware requires, but _after_
565 * copying to current bss rates.
567 lbs_set_basic_rate_flags(adhs
->rates
, ratesize
);
569 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
570 adhs
->rates
[0], adhs
->rates
[1], adhs
->rates
[2], adhs
->rates
[3]);
572 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
574 if (lbs_create_dnld_countryinfo_11d(priv
)) {
575 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
580 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start
) +
581 S_DS_GEN
+ cmdappendsize
);
585 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
589 int lbs_cmd_80211_ad_hoc_stop(struct lbs_private
*priv
,
590 struct cmd_ds_command
*cmd
)
592 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_STOP
);
593 cmd
->size
= cpu_to_le16(S_DS_GEN
);
598 int lbs_cmd_80211_ad_hoc_join(struct lbs_private
*priv
,
599 struct cmd_ds_command
*cmd
, void *pdata_buf
)
601 struct lbs_adapter
*adapter
= priv
->adapter
;
602 struct cmd_ds_802_11_ad_hoc_join
*join_cmd
= &cmd
->params
.adj
;
603 struct assoc_request
* assoc_req
= pdata_buf
;
604 struct bss_descriptor
*bss
= &assoc_req
->bss
;
605 int cmdappendsize
= 0;
608 DECLARE_MAC_BUF(mac
);
610 lbs_deb_enter(LBS_DEB_JOIN
);
612 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_JOIN
);
614 join_cmd
->bss
.type
= CMD_BSS_TYPE_IBSS
;
615 join_cmd
->bss
.beaconperiod
= cpu_to_le16(bss
->beaconperiod
);
617 memcpy(&join_cmd
->bss
.bssid
, &bss
->bssid
, ETH_ALEN
);
618 memcpy(&join_cmd
->bss
.ssid
, &bss
->ssid
, bss
->ssid_len
);
620 memcpy(&join_cmd
->bss
.phyparamset
, &bss
->phyparamset
,
621 sizeof(union ieeetypes_phyparamset
));
623 memcpy(&join_cmd
->bss
.ssparamset
, &bss
->ssparamset
,
624 sizeof(union IEEEtypes_ssparamset
));
626 join_cmd
->bss
.capability
= cpu_to_le16(bss
->capability
& CAPINFO_MASK
);
627 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
628 bss
->capability
, CAPINFO_MASK
);
630 /* information on BSSID descriptor passed to FW */
632 "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
633 print_mac(mac
, join_cmd
->bss
.bssid
),
637 join_cmd
->failtimeout
= cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT
);
640 join_cmd
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
642 adapter
->curbssparams
.channel
= bss
->channel
;
644 /* Copy Data rates from the rates recorded in scan response */
645 memset(join_cmd
->bss
.rates
, 0, sizeof(join_cmd
->bss
.rates
));
646 ratesize
= min_t(u16
, sizeof(join_cmd
->bss
.rates
), MAX_RATES
);
647 memcpy(join_cmd
->bss
.rates
, bss
->rates
, ratesize
);
648 if (get_common_rates(adapter
, join_cmd
->bss
.rates
, &ratesize
)) {
649 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
654 /* Copy the ad-hoc creating rates into Current BSS state structure */
655 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
656 memcpy(&adapter
->curbssparams
.rates
, join_cmd
->bss
.rates
, ratesize
);
658 /* Set MSB on basic rates as the firmware requires, but _after_
659 * copying to current bss rates.
661 lbs_set_basic_rate_flags(join_cmd
->bss
.rates
, ratesize
);
663 join_cmd
->bss
.ssparamset
.ibssparamset
.atimwindow
=
664 cpu_to_le16(bss
->atimwindow
);
666 if (assoc_req
->secinfo
.wep_enabled
) {
667 u16 tmp
= le16_to_cpu(join_cmd
->bss
.capability
);
668 tmp
|= WLAN_CAPABILITY_PRIVACY
;
669 join_cmd
->bss
.capability
= cpu_to_le16(tmp
);
672 if (adapter
->psmode
== LBS802_11POWERMODEMAX_PSP
) {
676 Localpsmode
= cpu_to_le32(LBS802_11POWERMODECAM
);
677 ret
= lbs_prepare_and_send_command(priv
,
688 if (lbs_parse_dnld_countryinfo_11d(priv
, bss
)) {
693 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join
) +
694 S_DS_GEN
+ cmdappendsize
);
697 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
701 int lbs_ret_80211_associate(struct lbs_private
*priv
,
702 struct cmd_ds_command
*resp
)
704 struct lbs_adapter
*adapter
= priv
->adapter
;
706 union iwreq_data wrqu
;
707 struct ieeetypes_assocrsp
*passocrsp
;
708 struct bss_descriptor
* bss
;
711 lbs_deb_enter(LBS_DEB_JOIN
);
713 if (!adapter
->in_progress_assoc_req
) {
714 lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
718 bss
= &adapter
->in_progress_assoc_req
->bss
;
720 passocrsp
= (struct ieeetypes_assocrsp
*) & resp
->params
;
723 * Older FW versions map the IEEE 802.11 Status Code in the association
724 * response to the following values returned in passocrsp->statuscode:
726 * IEEE Status Code Marvell Status Code
727 * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
728 * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
729 * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
730 * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
731 * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
732 * others -> 0x0003 ASSOC_RESULT_REFUSED
734 * Other response codes:
735 * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
736 * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
737 * association response from the AP)
740 status_code
= le16_to_cpu(passocrsp
->statuscode
);
741 switch (status_code
) {
743 lbs_deb_join("ASSOC_RESP: Association succeeded\n");
746 lbs_deb_join("ASSOC_RESP: Association failed; invalid "
747 "parameters (status code %d)\n", status_code
);
750 lbs_deb_join("ASSOC_RESP: Association failed; internal timer "
751 "expired while waiting for the AP (status code %d)"
755 lbs_deb_join("ASSOC_RESP: Association failed; association "
756 "was refused by the AP (status code %d)\n",
760 lbs_deb_join("ASSOC_RESP: Association failed; authentication "
761 "was refused by the AP (status code %d)\n",
765 lbs_deb_join("ASSOC_RESP: Association failed; reason unknown "
766 "(status code %d)\n", status_code
);
771 lbs_mac_event_disconnected(priv
);
776 lbs_deb_hex(LBS_DEB_JOIN
, "ASSOC_RESP", (void *)&resp
->params
,
777 le16_to_cpu(resp
->size
) - S_DS_GEN
);
779 /* Send a Media Connected event, according to the Spec */
780 adapter
->connect_status
= LBS_CONNECTED
;
782 lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
783 escape_essid(bss
->ssid
, bss
->ssid_len
));
785 /* Update current SSID and BSSID */
786 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
787 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
788 memcpy(adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
790 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
791 adapter
->currentpacketfilter
);
793 adapter
->SNR
[TYPE_RXPD
][TYPE_AVG
] = 0;
794 adapter
->NF
[TYPE_RXPD
][TYPE_AVG
] = 0;
796 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
797 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
798 adapter
->nextSNRNF
= 0;
799 adapter
->numSNRNF
= 0;
801 netif_carrier_on(priv
->dev
);
802 netif_wake_queue(priv
->dev
);
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 lbs_ret_80211_disassociate(struct lbs_private
*priv
,
815 struct cmd_ds_command
*resp
)
817 lbs_deb_enter(LBS_DEB_JOIN
);
819 lbs_mac_event_disconnected(priv
);
821 lbs_deb_leave(LBS_DEB_JOIN
);
825 int lbs_ret_80211_ad_hoc_start(struct lbs_private
*priv
,
826 struct cmd_ds_command
*resp
)
828 struct lbs_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
;
835 DECLARE_MAC_BUF(mac
);
837 lbs_deb_enter(LBS_DEB_JOIN
);
839 padhocresult
= &resp
->params
.result
;
841 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp
->size
));
842 lbs_deb_join("ADHOC_RESP: command = %x\n", command
);
843 lbs_deb_join("ADHOC_RESP: result = %x\n", result
);
845 if (!adapter
->in_progress_assoc_req
) {
846 lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
850 bss
= &adapter
->in_progress_assoc_req
->bss
;
853 * Join result code 0 --> SUCCESS
856 lbs_deb_join("ADHOC_RESP: failed\n");
857 if (adapter
->connect_status
== LBS_CONNECTED
) {
858 lbs_mac_event_disconnected(priv
);
865 * Now the join cmd should be successful
866 * If BSSID has changed use SSID to compare instead of BSSID
868 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
869 escape_essid(bss
->ssid
, bss
->ssid_len
));
871 /* Send a Media Connected event, according to the Spec */
872 adapter
->connect_status
= LBS_CONNECTED
;
874 if (command
== CMD_RET(CMD_802_11_AD_HOC_START
)) {
875 /* Update the created network descriptor with the new BSSID */
876 memcpy(bss
->bssid
, padhocresult
->bssid
, ETH_ALEN
);
879 /* Set the BSSID from the joined/started descriptor */
880 memcpy(&adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
882 /* Set the new SSID to current SSID */
883 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
884 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
886 netif_carrier_on(priv
->dev
);
887 netif_wake_queue(priv
->dev
);
889 memset(&wrqu
, 0, sizeof(wrqu
));
890 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
891 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
892 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
894 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
895 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter
->curbssparams
.channel
);
896 lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
897 print_mac(mac
, padhocresult
->bssid
));
900 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
904 int lbs_ret_80211_ad_hoc_stop(struct lbs_private
*priv
,
905 struct cmd_ds_command
*resp
)
907 lbs_deb_enter(LBS_DEB_JOIN
);
909 lbs_mac_event_disconnected(priv
);
911 lbs_deb_leave(LBS_DEB_JOIN
);