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 };
25 * @brief This function finds common rates between rate1 and card rates.
27 * It will fill common rates in rate1 as output if found.
29 * NOTE: Setting the MSB of the basic rates need to be taken
30 * care, either before or after calling this function
32 * @param adapter A pointer to wlan_adapter structure
33 * @param rate1 the buffer which keeps input and output
34 * @param rate1_size the size of rate1 buffer; new size of buffer on return
38 static int get_common_rates(wlan_adapter
* adapter
, u8
* rates
, u16
*rates_size
)
40 u8
*card_rates
= libertas_bg_rates
;
41 size_t num_card_rates
= sizeof(libertas_bg_rates
);
46 /* For each rate in card_rates that exists in rate1, copy to tmp */
47 for (i
= 0; card_rates
[i
] && (i
< num_card_rates
); i
++) {
48 for (j
= 0; rates
[j
] && (j
< *rates_size
); j
++) {
49 if (rates
[j
] == card_rates
[i
])
50 tmp
[tmp_size
++] = card_rates
[i
];
54 lbs_deb_hex(LBS_DEB_JOIN
, "AP rates ", rates
, *rates_size
);
55 lbs_deb_hex(LBS_DEB_JOIN
, "card rates ", card_rates
, num_card_rates
);
56 lbs_deb_hex(LBS_DEB_JOIN
, "common rates", tmp
, tmp_size
);
57 lbs_deb_join("Tx datarate is currently 0x%X\n", adapter
->cur_rate
);
59 if (!adapter
->auto_rate
) {
60 for (i
= 0; i
< tmp_size
; i
++) {
61 if (tmp
[i
] == adapter
->cur_rate
)
64 lbs_pr_alert("Previously set fixed data rate %#x isn't "
65 "compatible with the network.\n", adapter
->cur_rate
);
72 memset(rates
, 0, *rates_size
);
73 *rates_size
= min_t(int, tmp_size
, *rates_size
);
74 memcpy(rates
, tmp
, *rates_size
);
80 * @brief Sets the MSB on basic rates as the firmware requires
82 * Scan through an array and set the MSB for basic data rates.
84 * @param rates buffer of data rates
85 * @param len size of buffer
87 static void libertas_set_basic_rate_flags(u8
* rates
, size_t len
)
91 for (i
= 0; i
< len
; i
++) {
92 if (rates
[i
] == 0x02 || rates
[i
] == 0x04 ||
93 rates
[i
] == 0x0b || rates
[i
] == 0x16)
99 * @brief Unsets the MSB on basic rates
101 * Scan through an array and unset the MSB for basic data rates.
103 * @param rates buffer of data rates
104 * @param len size of buffer
106 void libertas_unset_basic_rate_flags(u8
* rates
, size_t len
)
110 for (i
= 0; i
< len
; i
++)
116 * @brief Associate to a specific BSS discovered in a scan
118 * @param priv A pointer to wlan_private structure
119 * @param pbssdesc Pointer to the BSS descriptor to associate with.
121 * @return 0-success, otherwise fail
123 int wlan_associate(wlan_private
* priv
, struct assoc_request
* assoc_req
)
125 wlan_adapter
*adapter
= priv
->adapter
;
128 lbs_deb_enter(LBS_DEB_JOIN
);
130 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AUTHENTICATE
,
131 0, CMD_OPTION_WAITFORRSP
,
132 0, assoc_req
->bss
.bssid
);
137 /* set preamble to firmware */
138 if ( (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
139 && (assoc_req
->bss
.capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
))
140 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
142 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
144 libertas_set_radio_control(priv
);
146 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_ASSOCIATE
,
147 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
150 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
155 * @brief Start an Adhoc Network
157 * @param priv A pointer to wlan_private structure
158 * @param adhocssid The ssid of the Adhoc Network
159 * @return 0--success, -1--fail
161 int libertas_start_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
163 wlan_adapter
*adapter
= priv
->adapter
;
166 adapter
->adhoccreate
= 1;
168 if (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
) {
169 lbs_deb_join("AdhocStart: Short preamble\n");
170 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
172 lbs_deb_join("AdhocStart: Long preamble\n");
173 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
176 libertas_set_radio_control(priv
);
178 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req
->channel
);
179 lbs_deb_join("AdhocStart: band = %d\n", assoc_req
->band
);
181 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_START
,
182 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
188 * @brief Join an adhoc network found in a previous scan
190 * @param priv A pointer to wlan_private structure
191 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
194 * @return 0--success, -1--fail
196 int libertas_join_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
198 wlan_adapter
*adapter
= priv
->adapter
;
199 struct bss_descriptor
* bss
= &assoc_req
->bss
;
202 lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
204 escape_essid(adapter
->curbssparams
.ssid
,
205 adapter
->curbssparams
.ssid_len
),
206 adapter
->curbssparams
.ssid_len
);
207 lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
208 __func__
, escape_essid(bss
->ssid
, bss
->ssid_len
),
211 /* check if the requested SSID is already joined */
212 if (adapter
->curbssparams
.ssid_len
213 && !libertas_ssid_cmp(adapter
->curbssparams
.ssid
,
214 adapter
->curbssparams
.ssid_len
,
215 bss
->ssid
, bss
->ssid_len
)
216 && (adapter
->mode
== IW_MODE_ADHOC
)) {
218 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
219 "not attempting to re-join");
223 /* Use shortpreamble only when both creator and card supports
225 if ( !(bss
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
226 || !(adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)) {
227 lbs_deb_join("AdhocJoin: Long preamble\n");
228 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
230 lbs_deb_join("AdhocJoin: Short preamble\n");
231 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
234 libertas_set_radio_control(priv
);
236 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req
->channel
);
237 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req
->band
);
239 adapter
->adhoccreate
= 0;
241 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_JOIN
,
242 0, CMD_OPTION_WAITFORRSP
,
243 OID_802_11_SSID
, assoc_req
);
248 int libertas_stop_adhoc_network(wlan_private
* priv
)
250 return libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_STOP
,
251 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
255 * @brief Send Deauthentication Request
257 * @param priv A pointer to wlan_private structure
258 * @return 0--success, -1--fail
260 int libertas_send_deauthentication(wlan_private
* priv
)
262 return libertas_prepare_and_send_command(priv
, CMD_802_11_DEAUTHENTICATE
,
263 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
267 * @brief This function prepares command of authenticate.
269 * @param priv A pointer to wlan_private structure
270 * @param cmd A pointer to cmd_ds_command structure
271 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
275 int libertas_cmd_80211_authenticate(wlan_private
* priv
,
276 struct cmd_ds_command
*cmd
,
279 wlan_adapter
*adapter
= priv
->adapter
;
280 struct cmd_ds_802_11_authenticate
*pauthenticate
= &cmd
->params
.auth
;
282 u8
*bssid
= pdata_buf
;
284 lbs_deb_enter(LBS_DEB_JOIN
);
286 cmd
->command
= cpu_to_le16(CMD_802_11_AUTHENTICATE
);
287 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate
)
290 /* translate auth mode to 802.11 defined wire value */
291 switch (adapter
->secinfo
.auth_mode
) {
292 case IW_AUTH_ALG_OPEN_SYSTEM
:
293 pauthenticate
->authtype
= 0x00;
295 case IW_AUTH_ALG_SHARED_KEY
:
296 pauthenticate
->authtype
= 0x01;
298 case IW_AUTH_ALG_LEAP
:
299 pauthenticate
->authtype
= 0x80;
302 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
303 adapter
->secinfo
.auth_mode
);
307 memcpy(pauthenticate
->macaddr
, bssid
, ETH_ALEN
);
309 lbs_deb_join("AUTH_CMD: BSSID is : " MAC_FMT
" auth=0x%X\n",
310 MAC_ARG(bssid
), pauthenticate
->authtype
);
314 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
318 int libertas_cmd_80211_deauthenticate(wlan_private
* priv
,
319 struct cmd_ds_command
*cmd
)
321 wlan_adapter
*adapter
= priv
->adapter
;
322 struct cmd_ds_802_11_deauthenticate
*dauth
= &cmd
->params
.deauth
;
324 lbs_deb_enter(LBS_DEB_JOIN
);
326 cmd
->command
= cpu_to_le16(CMD_802_11_DEAUTHENTICATE
);
327 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate
) +
330 /* set AP MAC address */
331 memmove(dauth
->macaddr
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
333 /* Reason code 3 = Station is leaving */
334 #define REASON_CODE_STA_LEAVING 3
335 dauth
->reasoncode
= cpu_to_le16(REASON_CODE_STA_LEAVING
);
337 lbs_deb_leave(LBS_DEB_JOIN
);
341 int libertas_cmd_80211_associate(wlan_private
* priv
,
342 struct cmd_ds_command
*cmd
, void *pdata_buf
)
344 wlan_adapter
*adapter
= priv
->adapter
;
345 struct cmd_ds_802_11_associate
*passo
= &cmd
->params
.associate
;
347 struct assoc_request
* assoc_req
= pdata_buf
;
348 struct bss_descriptor
* bss
= &assoc_req
->bss
;
351 struct mrvlietypes_ssidparamset
*ssid
;
352 struct mrvlietypes_phyparamset
*phy
;
353 struct mrvlietypes_ssparamset
*ss
;
354 struct mrvlietypes_ratesparamset
*rates
;
355 struct mrvlietypes_rsnparamset
*rsn
;
357 lbs_deb_enter(LBS_DEB_JOIN
);
366 cmd
->command
= cpu_to_le16(CMD_802_11_ASSOCIATE
);
368 memcpy(passo
->peerstaaddr
, bss
->bssid
, sizeof(passo
->peerstaaddr
));
369 pos
+= sizeof(passo
->peerstaaddr
);
371 /* set the listen interval */
372 passo
->listeninterval
= cpu_to_le16(adapter
->listeninterval
);
374 pos
+= sizeof(passo
->capability
);
375 pos
+= sizeof(passo
->listeninterval
);
376 pos
+= sizeof(passo
->bcnperiod
);
377 pos
+= sizeof(passo
->dtimperiod
);
379 ssid
= (struct mrvlietypes_ssidparamset
*) pos
;
380 ssid
->header
.type
= cpu_to_le16(TLV_TYPE_SSID
);
381 tmplen
= bss
->ssid_len
;
382 ssid
->header
.len
= cpu_to_le16(tmplen
);
383 memcpy(ssid
->ssid
, bss
->ssid
, tmplen
);
384 pos
+= sizeof(ssid
->header
) + tmplen
;
386 phy
= (struct mrvlietypes_phyparamset
*) pos
;
387 phy
->header
.type
= cpu_to_le16(TLV_TYPE_PHY_DS
);
388 tmplen
= sizeof(phy
->fh_ds
.dsparamset
);
389 phy
->header
.len
= cpu_to_le16(tmplen
);
390 memcpy(&phy
->fh_ds
.dsparamset
,
391 &bss
->phyparamset
.dsparamset
.currentchan
,
393 pos
+= sizeof(phy
->header
) + tmplen
;
395 ss
= (struct mrvlietypes_ssparamset
*) pos
;
396 ss
->header
.type
= cpu_to_le16(TLV_TYPE_CF
);
397 tmplen
= sizeof(ss
->cf_ibss
.cfparamset
);
398 ss
->header
.len
= cpu_to_le16(tmplen
);
399 pos
+= sizeof(ss
->header
) + tmplen
;
401 rates
= (struct mrvlietypes_ratesparamset
*) pos
;
402 rates
->header
.type
= cpu_to_le16(TLV_TYPE_RATES
);
403 memcpy(&rates
->rates
, &bss
->rates
, MAX_RATES
);
405 if (get_common_rates(adapter
, rates
->rates
, &tmplen
)) {
409 pos
+= sizeof(rates
->header
) + tmplen
;
410 rates
->header
.len
= cpu_to_le16(tmplen
);
411 lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen
);
413 /* Copy the infra. association rates into Current BSS state structure */
414 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
415 memcpy(&adapter
->curbssparams
.rates
, &rates
->rates
, tmplen
);
417 /* Set MSB on basic rates as the firmware requires, but _after_
418 * copying to current bss rates.
420 libertas_set_basic_rate_flags(rates
->rates
, tmplen
);
422 if (assoc_req
->secinfo
.WPAenabled
|| assoc_req
->secinfo
.WPA2enabled
) {
423 rsn
= (struct mrvlietypes_rsnparamset
*) pos
;
424 /* WPA_IE or WPA2_IE */
425 rsn
->header
.type
= cpu_to_le16((u16
) assoc_req
->wpa_ie
[0]);
426 tmplen
= (u16
) assoc_req
->wpa_ie
[1];
427 rsn
->header
.len
= cpu_to_le16(tmplen
);
428 memcpy(rsn
->rsnie
, &assoc_req
->wpa_ie
[2], tmplen
);
429 lbs_deb_hex(LBS_DEB_JOIN
, "ASSOC_CMD: RSN IE", (u8
*) rsn
,
430 sizeof(rsn
->header
) + tmplen
);
431 pos
+= sizeof(rsn
->header
) + tmplen
;
434 /* update curbssparams */
435 adapter
->curbssparams
.channel
= bss
->phyparamset
.dsparamset
.currentchan
;
437 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
442 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*) passo
) + S_DS_GEN
);
444 /* set the capability info */
445 tmpcap
= (bss
->capability
& CAPINFO_MASK
);
446 if (bss
->mode
== IW_MODE_INFRA
)
447 tmpcap
|= WLAN_CAPABILITY_ESS
;
448 passo
->capability
= cpu_to_le16(tmpcap
);
449 lbs_deb_join("ASSOC_CMD: capability=%4X CAPINFO_MASK=%4X\n",
450 tmpcap
, CAPINFO_MASK
);
453 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
457 int libertas_cmd_80211_ad_hoc_start(wlan_private
* priv
,
458 struct cmd_ds_command
*cmd
, void *pdata_buf
)
460 wlan_adapter
*adapter
= priv
->adapter
;
461 struct cmd_ds_802_11_ad_hoc_start
*adhs
= &cmd
->params
.ads
;
463 int cmdappendsize
= 0;
464 struct assoc_request
* assoc_req
= pdata_buf
;
468 lbs_deb_enter(LBS_DEB_JOIN
);
475 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_START
);
478 * Fill in the parameters for 2 data structures:
479 * 1. cmd_ds_802_11_ad_hoc_start command
480 * 2. adapter->scantable[i]
482 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
483 * probe delay, and cap info.
485 * Firmware will fill up beacon period, DTIM, Basic rates
486 * and operational rates.
489 memset(adhs
->ssid
, 0, IW_ESSID_MAX_SIZE
);
490 memcpy(adhs
->ssid
, assoc_req
->ssid
, assoc_req
->ssid_len
);
492 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
493 escape_essid(assoc_req
->ssid
, assoc_req
->ssid_len
),
494 assoc_req
->ssid_len
);
496 /* set the BSS type */
497 adhs
->bsstype
= CMD_BSS_TYPE_IBSS
;
498 adapter
->mode
= IW_MODE_ADHOC
;
499 adhs
->beaconperiod
= cpu_to_le16(adapter
->beaconperiod
);
501 /* set Physical param set */
502 #define DS_PARA_IE_ID 3
503 #define DS_PARA_IE_LEN 1
505 adhs
->phyparamset
.dsparamset
.elementid
= DS_PARA_IE_ID
;
506 adhs
->phyparamset
.dsparamset
.len
= DS_PARA_IE_LEN
;
508 WARN_ON(!assoc_req
->channel
);
510 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
513 adhs
->phyparamset
.dsparamset
.currentchan
= assoc_req
->channel
;
515 /* set IBSS param set */
516 #define IBSS_PARA_IE_ID 6
517 #define IBSS_PARA_IE_LEN 2
519 adhs
->ssparamset
.ibssparamset
.elementid
= IBSS_PARA_IE_ID
;
520 adhs
->ssparamset
.ibssparamset
.len
= IBSS_PARA_IE_LEN
;
521 adhs
->ssparamset
.ibssparamset
.atimwindow
= cpu_to_le16(adapter
->atimwindow
);
523 /* set capability info */
524 tmpcap
= WLAN_CAPABILITY_IBSS
;
525 if (assoc_req
->secinfo
.wep_enabled
) {
526 lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
527 tmpcap
|= WLAN_CAPABILITY_PRIVACY
;
529 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
531 adhs
->capability
= cpu_to_le16(tmpcap
);
534 adhs
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
536 memset(adhs
->rates
, 0, sizeof(adhs
->rates
));
537 if (adapter
->adhoc_grate_enabled
) {
538 ratesize
= min(sizeof(adhs
->rates
), sizeof(libertas_bg_rates
));
539 memcpy(adhs
->rates
, libertas_bg_rates
, ratesize
);
541 ratesize
= min(sizeof(adhs
->rates
), sizeof(adhoc_rates_b
));
542 memcpy(adhs
->rates
, adhoc_rates_b
, ratesize
);
545 /* Copy the ad-hoc creating rates into Current BSS state structure */
546 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
547 memcpy(&adapter
->curbssparams
.rates
, &adhs
->rates
, ratesize
);
549 /* Set MSB on basic rates as the firmware requires, but _after_
550 * copying to current bss rates.
552 libertas_set_basic_rate_flags(adhs
->rates
, ratesize
);
554 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
555 adhs
->rates
[0], adhs
->rates
[1], adhs
->rates
[2], adhs
->rates
[3]);
557 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
559 if (libertas_create_dnld_countryinfo_11d(priv
)) {
560 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
565 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start
) +
566 S_DS_GEN
+ cmdappendsize
);
570 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
574 int libertas_cmd_80211_ad_hoc_stop(wlan_private
* priv
,
575 struct cmd_ds_command
*cmd
)
577 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_STOP
);
578 cmd
->size
= cpu_to_le16(S_DS_GEN
);
583 int libertas_cmd_80211_ad_hoc_join(wlan_private
* priv
,
584 struct cmd_ds_command
*cmd
, void *pdata_buf
)
586 wlan_adapter
*adapter
= priv
->adapter
;
587 struct cmd_ds_802_11_ad_hoc_join
*join_cmd
= &cmd
->params
.adj
;
588 struct assoc_request
* assoc_req
= pdata_buf
;
589 struct bss_descriptor
*bss
= &assoc_req
->bss
;
590 int cmdappendsize
= 0;
594 lbs_deb_enter(LBS_DEB_JOIN
);
596 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_JOIN
);
598 join_cmd
->bss
.type
= CMD_BSS_TYPE_IBSS
;
599 join_cmd
->bss
.beaconperiod
= cpu_to_le16(bss
->beaconperiod
);
601 memcpy(&join_cmd
->bss
.bssid
, &bss
->bssid
, ETH_ALEN
);
602 memcpy(&join_cmd
->bss
.ssid
, &bss
->ssid
, bss
->ssid_len
);
604 memcpy(&join_cmd
->bss
.phyparamset
, &bss
->phyparamset
,
605 sizeof(union ieeetypes_phyparamset
));
607 memcpy(&join_cmd
->bss
.ssparamset
, &bss
->ssparamset
,
608 sizeof(union IEEEtypes_ssparamset
));
610 join_cmd
->bss
.capability
= cpu_to_le16(bss
->capability
& CAPINFO_MASK
);
611 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
612 bss
->capability
, CAPINFO_MASK
);
614 /* information on BSSID descriptor passed to FW */
616 "ADHOC_J_CMD: BSSID = " MAC_FMT
", SSID = '%s'\n",
617 MAC_ARG(join_cmd
->bss
.bssid
), join_cmd
->bss
.ssid
);
620 join_cmd
->failtimeout
= cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT
);
623 join_cmd
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
625 adapter
->curbssparams
.channel
= bss
->channel
;
627 /* Copy Data rates from the rates recorded in scan response */
628 memset(join_cmd
->bss
.rates
, 0, sizeof(join_cmd
->bss
.rates
));
629 ratesize
= min_t(u16
, sizeof(join_cmd
->bss
.rates
), MAX_RATES
);
630 memcpy(join_cmd
->bss
.rates
, bss
->rates
, ratesize
);
631 if (get_common_rates(adapter
, join_cmd
->bss
.rates
, &ratesize
)) {
632 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
637 /* Copy the ad-hoc creating rates into Current BSS state structure */
638 memset(&adapter
->curbssparams
.rates
, 0, sizeof(adapter
->curbssparams
.rates
));
639 memcpy(&adapter
->curbssparams
.rates
, join_cmd
->bss
.rates
, ratesize
);
641 /* Set MSB on basic rates as the firmware requires, but _after_
642 * copying to current bss rates.
644 libertas_set_basic_rate_flags(join_cmd
->bss
.rates
, ratesize
);
646 join_cmd
->bss
.ssparamset
.ibssparamset
.atimwindow
=
647 cpu_to_le16(bss
->atimwindow
);
649 if (assoc_req
->secinfo
.wep_enabled
) {
650 u16 tmp
= le16_to_cpu(join_cmd
->bss
.capability
);
651 tmp
|= WLAN_CAPABILITY_PRIVACY
;
652 join_cmd
->bss
.capability
= cpu_to_le16(tmp
);
655 if (adapter
->psmode
== WLAN802_11POWERMODEMAX_PSP
) {
659 Localpsmode
= cpu_to_le32(WLAN802_11POWERMODECAM
);
660 ret
= libertas_prepare_and_send_command(priv
,
671 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
676 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join
) +
677 S_DS_GEN
+ cmdappendsize
);
680 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
684 int libertas_ret_80211_associate(wlan_private
* priv
,
685 struct cmd_ds_command
*resp
)
687 wlan_adapter
*adapter
= priv
->adapter
;
689 union iwreq_data wrqu
;
690 struct ieeetypes_assocrsp
*passocrsp
;
691 struct bss_descriptor
* bss
;
693 lbs_deb_enter(LBS_DEB_JOIN
);
695 if (!adapter
->in_progress_assoc_req
) {
696 lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
700 bss
= &adapter
->in_progress_assoc_req
->bss
;
702 passocrsp
= (struct ieeetypes_assocrsp
*) & resp
->params
;
704 if (le16_to_cpu(passocrsp
->statuscode
)) {
705 libertas_mac_event_disconnected(priv
);
707 lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
708 le16_to_cpu(passocrsp
->statuscode
));
714 lbs_deb_hex(LBS_DEB_JOIN
, "ASSOC_RESP", (void *)&resp
->params
,
715 le16_to_cpu(resp
->size
) - S_DS_GEN
);
717 /* Send a Media Connected event, according to the Spec */
718 adapter
->connect_status
= LIBERTAS_CONNECTED
;
720 lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
721 escape_essid(bss
->ssid
, bss
->ssid_len
));
723 /* Update current SSID and BSSID */
724 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
725 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
726 memcpy(adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
728 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
729 adapter
->currentpacketfilter
);
731 adapter
->SNR
[TYPE_RXPD
][TYPE_AVG
] = 0;
732 adapter
->NF
[TYPE_RXPD
][TYPE_AVG
] = 0;
734 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
735 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
736 adapter
->nextSNRNF
= 0;
737 adapter
->numSNRNF
= 0;
739 netif_carrier_on(priv
->dev
);
740 netif_wake_queue(priv
->dev
);
742 if (priv
->mesh_dev
) {
743 netif_carrier_on(priv
->mesh_dev
);
744 netif_wake_queue(priv
->mesh_dev
);
747 lbs_deb_join("ASSOC_RESP: Associated \n");
749 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
750 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
751 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
754 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
758 int libertas_ret_80211_disassociate(wlan_private
* priv
,
759 struct cmd_ds_command
*resp
)
761 lbs_deb_enter(LBS_DEB_JOIN
);
763 libertas_mac_event_disconnected(priv
);
765 lbs_deb_leave(LBS_DEB_JOIN
);
769 int libertas_ret_80211_ad_hoc_start(wlan_private
* priv
,
770 struct cmd_ds_command
*resp
)
772 wlan_adapter
*adapter
= priv
->adapter
;
774 u16 command
= le16_to_cpu(resp
->command
);
775 u16 result
= le16_to_cpu(resp
->result
);
776 struct cmd_ds_802_11_ad_hoc_result
*padhocresult
;
777 union iwreq_data wrqu
;
778 struct bss_descriptor
*bss
;
780 lbs_deb_enter(LBS_DEB_JOIN
);
782 padhocresult
= &resp
->params
.result
;
784 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp
->size
));
785 lbs_deb_join("ADHOC_RESP: command = %x\n", command
);
786 lbs_deb_join("ADHOC_RESP: result = %x\n", result
);
788 if (!adapter
->in_progress_assoc_req
) {
789 lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
793 bss
= &adapter
->in_progress_assoc_req
->bss
;
796 * Join result code 0 --> SUCCESS
799 lbs_deb_join("ADHOC_RESP: failed\n");
800 if (adapter
->connect_status
== LIBERTAS_CONNECTED
) {
801 libertas_mac_event_disconnected(priv
);
808 * Now the join cmd should be successful
809 * If BSSID has changed use SSID to compare instead of BSSID
811 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
812 escape_essid(bss
->ssid
, bss
->ssid_len
));
814 /* Send a Media Connected event, according to the Spec */
815 adapter
->connect_status
= LIBERTAS_CONNECTED
;
817 if (command
== CMD_RET(CMD_802_11_AD_HOC_START
)) {
818 /* Update the created network descriptor with the new BSSID */
819 memcpy(bss
->bssid
, padhocresult
->bssid
, ETH_ALEN
);
822 /* Set the BSSID from the joined/started descriptor */
823 memcpy(&adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
825 /* Set the new SSID to current SSID */
826 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
827 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
829 netif_carrier_on(priv
->dev
);
830 netif_wake_queue(priv
->dev
);
832 if (priv
->mesh_dev
) {
833 netif_carrier_on(priv
->mesh_dev
);
834 netif_wake_queue(priv
->mesh_dev
);
837 memset(&wrqu
, 0, sizeof(wrqu
));
838 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
839 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
840 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
842 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
843 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter
->curbssparams
.channel
);
844 lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT
"\n",
845 MAC_ARG(padhocresult
->bssid
));
848 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
852 int libertas_ret_80211_ad_hoc_stop(wlan_private
* priv
,
853 struct cmd_ds_command
*resp
)
855 lbs_deb_enter(LBS_DEB_JOIN
);
857 libertas_mac_event_disconnected(priv
);
859 lbs_deb_leave(LBS_DEB_JOIN
);