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>
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 assoc_request
* assoc_req
)
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
,
116 0, assoc_req
->bss
.bssid
);
121 /* set preamble to firmware */
122 if ( (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
123 && (assoc_req
->bss
.capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
))
124 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
126 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
128 libertas_set_radio_control(priv
);
130 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_ASSOCIATE
,
131 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
134 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
139 * @brief Start an Adhoc Network
141 * @param priv A pointer to wlan_private structure
142 * @param adhocssid The ssid of the Adhoc Network
143 * @return 0--success, -1--fail
145 int libertas_start_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
147 wlan_adapter
*adapter
= priv
->adapter
;
150 adapter
->adhoccreate
= 1;
152 if (adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
) {
153 lbs_deb_join("AdhocStart: Short preamble\n");
154 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
156 lbs_deb_join("AdhocStart: Long preamble\n");
157 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
160 libertas_set_radio_control(priv
);
162 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req
->channel
);
163 lbs_deb_join("AdhocStart: band = %d\n", assoc_req
->band
);
165 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_START
,
166 0, CMD_OPTION_WAITFORRSP
, 0, assoc_req
);
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 assoc_request
* assoc_req
)
182 wlan_adapter
*adapter
= priv
->adapter
;
183 struct bss_descriptor
* bss
= &assoc_req
->bss
;
186 lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
188 escape_essid(adapter
->curbssparams
.ssid
,
189 adapter
->curbssparams
.ssid_len
),
190 adapter
->curbssparams
.ssid_len
);
191 lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
192 __func__
, escape_essid(bss
->ssid
, bss
->ssid_len
),
195 /* check if the requested SSID is already joined */
196 if (adapter
->curbssparams
.ssid_len
197 && !libertas_ssid_cmp(adapter
->curbssparams
.ssid
,
198 adapter
->curbssparams
.ssid_len
,
199 bss
->ssid
, bss
->ssid_len
)
200 && (adapter
->mode
== IW_MODE_ADHOC
)) {
202 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
203 "not attempting to re-join");
207 /* Use shortpreamble only when both creator and card supports
209 if ( !(bss
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)
210 || !(adapter
->capability
& WLAN_CAPABILITY_SHORT_PREAMBLE
)) {
211 lbs_deb_join("AdhocJoin: Long preamble\n");
212 adapter
->preamble
= CMD_TYPE_LONG_PREAMBLE
;
214 lbs_deb_join("AdhocJoin: Short preamble\n");
215 adapter
->preamble
= CMD_TYPE_SHORT_PREAMBLE
;
218 libertas_set_radio_control(priv
);
220 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req
->channel
);
221 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req
->band
);
223 adapter
->adhoccreate
= 0;
225 ret
= libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_JOIN
,
226 0, CMD_OPTION_WAITFORRSP
,
227 OID_802_11_SSID
, assoc_req
);
232 int libertas_stop_adhoc_network(wlan_private
* priv
)
234 return libertas_prepare_and_send_command(priv
, CMD_802_11_AD_HOC_STOP
,
235 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
239 * @brief Send Deauthentication Request
241 * @param priv A pointer to wlan_private structure
242 * @return 0--success, -1--fail
244 int libertas_send_deauthentication(wlan_private
* priv
)
246 return libertas_prepare_and_send_command(priv
, CMD_802_11_DEAUTHENTICATE
,
247 0, CMD_OPTION_WAITFORRSP
, 0, NULL
);
251 * @brief This function prepares command of authenticate.
253 * @param priv A pointer to wlan_private structure
254 * @param cmd A pointer to cmd_ds_command structure
255 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
259 int libertas_cmd_80211_authenticate(wlan_private
* priv
,
260 struct cmd_ds_command
*cmd
,
263 wlan_adapter
*adapter
= priv
->adapter
;
264 struct cmd_ds_802_11_authenticate
*pauthenticate
= &cmd
->params
.auth
;
266 u8
*bssid
= pdata_buf
;
268 lbs_deb_enter(LBS_DEB_JOIN
);
270 cmd
->command
= cpu_to_le16(CMD_802_11_AUTHENTICATE
);
271 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate
)
274 /* translate auth mode to 802.11 defined wire value */
275 switch (adapter
->secinfo
.auth_mode
) {
276 case IW_AUTH_ALG_OPEN_SYSTEM
:
277 pauthenticate
->authtype
= 0x00;
279 case IW_AUTH_ALG_SHARED_KEY
:
280 pauthenticate
->authtype
= 0x01;
282 case IW_AUTH_ALG_LEAP
:
283 pauthenticate
->authtype
= 0x80;
286 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
287 adapter
->secinfo
.auth_mode
);
291 memcpy(pauthenticate
->macaddr
, bssid
, ETH_ALEN
);
293 lbs_deb_join("AUTH_CMD: BSSID is : " MAC_FMT
" auth=0x%X\n",
294 MAC_ARG(bssid
), pauthenticate
->authtype
);
298 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
302 int libertas_cmd_80211_deauthenticate(wlan_private
* priv
,
303 struct cmd_ds_command
*cmd
)
305 wlan_adapter
*adapter
= priv
->adapter
;
306 struct cmd_ds_802_11_deauthenticate
*dauth
= &cmd
->params
.deauth
;
308 lbs_deb_enter(LBS_DEB_JOIN
);
310 cmd
->command
= cpu_to_le16(CMD_802_11_DEAUTHENTICATE
);
311 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate
) +
314 /* set AP MAC address */
315 memmove(dauth
->macaddr
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
317 /* Reason code 3 = Station is leaving */
318 #define REASON_CODE_STA_LEAVING 3
319 dauth
->reasoncode
= cpu_to_le16(REASON_CODE_STA_LEAVING
);
321 lbs_deb_leave(LBS_DEB_JOIN
);
325 int libertas_cmd_80211_associate(wlan_private
* priv
,
326 struct cmd_ds_command
*cmd
, void *pdata_buf
)
328 wlan_adapter
*adapter
= priv
->adapter
;
329 struct cmd_ds_802_11_associate
*passo
= &cmd
->params
.associate
;
331 struct assoc_request
* assoc_req
= pdata_buf
;
332 struct bss_descriptor
* bss
= &assoc_req
->bss
;
337 struct mrvlietypes_ssidparamset
*ssid
;
338 struct mrvlietypes_phyparamset
*phy
;
339 struct mrvlietypes_ssparamset
*ss
;
340 struct mrvlietypes_ratesparamset
*rates
;
341 struct mrvlietypes_rsnparamset
*rsn
;
343 lbs_deb_enter(LBS_DEB_JOIN
);
352 cmd
->command
= cpu_to_le16(CMD_802_11_ASSOCIATE
);
354 memcpy(passo
->peerstaaddr
, bss
->bssid
, sizeof(passo
->peerstaaddr
));
355 pos
+= sizeof(passo
->peerstaaddr
);
357 /* set the listen interval */
358 passo
->listeninterval
= cpu_to_le16(adapter
->listeninterval
);
360 pos
+= sizeof(passo
->capability
);
361 pos
+= sizeof(passo
->listeninterval
);
362 pos
+= sizeof(passo
->bcnperiod
);
363 pos
+= sizeof(passo
->dtimperiod
);
365 ssid
= (struct mrvlietypes_ssidparamset
*) pos
;
366 ssid
->header
.type
= cpu_to_le16(TLV_TYPE_SSID
);
367 tmplen
= bss
->ssid_len
;
368 ssid
->header
.len
= cpu_to_le16(tmplen
);
369 memcpy(ssid
->ssid
, bss
->ssid
, tmplen
);
370 pos
+= sizeof(ssid
->header
) + tmplen
;
372 phy
= (struct mrvlietypes_phyparamset
*) pos
;
373 phy
->header
.type
= cpu_to_le16(TLV_TYPE_PHY_DS
);
374 tmplen
= sizeof(phy
->fh_ds
.dsparamset
);
375 phy
->header
.len
= cpu_to_le16(tmplen
);
376 memcpy(&phy
->fh_ds
.dsparamset
,
377 &bss
->phyparamset
.dsparamset
.currentchan
,
379 pos
+= sizeof(phy
->header
) + tmplen
;
381 ss
= (struct mrvlietypes_ssparamset
*) pos
;
382 ss
->header
.type
= cpu_to_le16(TLV_TYPE_CF
);
383 tmplen
= sizeof(ss
->cf_ibss
.cfparamset
);
384 ss
->header
.len
= cpu_to_le16(tmplen
);
385 pos
+= sizeof(ss
->header
) + tmplen
;
387 rates
= (struct mrvlietypes_ratesparamset
*) pos
;
388 rates
->header
.type
= cpu_to_le16(TLV_TYPE_RATES
);
390 memcpy(&rates
->rates
, &bss
->libertas_supported_rates
, WLAN_SUPPORTED_RATES
);
392 card_rates
= libertas_supported_rates
;
393 card_rates_size
= sizeof(libertas_supported_rates
);
395 if (get_common_rates(adapter
, rates
->rates
, WLAN_SUPPORTED_RATES
,
396 card_rates
, card_rates_size
)) {
401 tmplen
= min_t(size_t, strlen(rates
->rates
), WLAN_SUPPORTED_RATES
);
402 adapter
->curbssparams
.numofrates
= tmplen
;
404 pos
+= sizeof(rates
->header
) + tmplen
;
405 rates
->header
.len
= cpu_to_le16(tmplen
);
407 if (assoc_req
->secinfo
.WPAenabled
|| assoc_req
->secinfo
.WPA2enabled
) {
408 rsn
= (struct mrvlietypes_rsnparamset
*) pos
;
409 /* WPA_IE or WPA2_IE */
410 rsn
->header
.type
= cpu_to_le16((u16
) assoc_req
->wpa_ie
[0]);
411 tmplen
= (u16
) assoc_req
->wpa_ie
[1];
412 rsn
->header
.len
= cpu_to_le16(tmplen
);
413 memcpy(rsn
->rsnie
, &assoc_req
->wpa_ie
[2], tmplen
);
414 lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8
*) rsn
,
415 sizeof(rsn
->header
) + tmplen
);
416 pos
+= sizeof(rsn
->header
) + tmplen
;
419 /* update curbssparams */
420 adapter
->curbssparams
.channel
= bss
->phyparamset
.dsparamset
.currentchan
;
422 /* Copy the infra. association rates into Current BSS state structure */
423 memcpy(&adapter
->curbssparams
.datarates
, &rates
->rates
,
424 min_t(size_t, sizeof(adapter
->curbssparams
.datarates
),
425 cpu_to_le16(rates
->header
.len
)));
427 lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n",
428 cpu_to_le16(rates
->header
.len
));
430 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
435 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*) passo
) + S_DS_GEN
);
437 /* set the capability info */
438 tmpcap
= (bss
->capability
& CAPINFO_MASK
);
439 if (bss
->mode
== IW_MODE_INFRA
)
440 tmpcap
|= WLAN_CAPABILITY_ESS
;
441 passo
->capability
= cpu_to_le16(tmpcap
);
442 lbs_deb_join("ASSOC_CMD: capability=%4X CAPINFO_MASK=%4X\n",
443 tmpcap
, CAPINFO_MASK
);
446 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
450 int libertas_cmd_80211_ad_hoc_start(wlan_private
* priv
,
451 struct cmd_ds_command
*cmd
, void *pdata_buf
)
453 wlan_adapter
*adapter
= priv
->adapter
;
454 struct cmd_ds_802_11_ad_hoc_start
*adhs
= &cmd
->params
.ads
;
456 int cmdappendsize
= 0;
458 struct assoc_request
* assoc_req
= pdata_buf
;
461 lbs_deb_enter(LBS_DEB_JOIN
);
468 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_START
);
471 * Fill in the parameters for 2 data structures:
472 * 1. cmd_ds_802_11_ad_hoc_start command
473 * 2. adapter->scantable[i]
475 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
476 * probe delay, and cap info.
478 * Firmware will fill up beacon period, DTIM, Basic rates
479 * and operational rates.
482 memset(adhs
->ssid
, 0, IW_ESSID_MAX_SIZE
);
483 memcpy(adhs
->ssid
, assoc_req
->ssid
, assoc_req
->ssid_len
);
485 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
486 escape_essid(assoc_req
->ssid
, assoc_req
->ssid_len
),
487 assoc_req
->ssid_len
);
489 /* set the BSS type */
490 adhs
->bsstype
= CMD_BSS_TYPE_IBSS
;
491 adapter
->mode
= IW_MODE_ADHOC
;
492 adhs
->beaconperiod
= cpu_to_le16(adapter
->beaconperiod
);
494 /* set Physical param set */
495 #define DS_PARA_IE_ID 3
496 #define DS_PARA_IE_LEN 1
498 adhs
->phyparamset
.dsparamset
.elementid
= DS_PARA_IE_ID
;
499 adhs
->phyparamset
.dsparamset
.len
= DS_PARA_IE_LEN
;
501 WARN_ON(!assoc_req
->channel
);
503 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
506 adhs
->phyparamset
.dsparamset
.currentchan
= assoc_req
->channel
;
508 /* set IBSS param set */
509 #define IBSS_PARA_IE_ID 6
510 #define IBSS_PARA_IE_LEN 2
512 adhs
->ssparamset
.ibssparamset
.elementid
= IBSS_PARA_IE_ID
;
513 adhs
->ssparamset
.ibssparamset
.len
= IBSS_PARA_IE_LEN
;
514 adhs
->ssparamset
.ibssparamset
.atimwindow
= cpu_to_le16(adapter
->atimwindow
);
516 /* set capability info */
517 tmpcap
= WLAN_CAPABILITY_IBSS
;
518 if (assoc_req
->secinfo
.wep_enabled
) {
519 lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
520 tmpcap
|= WLAN_CAPABILITY_PRIVACY
;
522 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
524 adhs
->capability
= cpu_to_le16(tmpcap
);
527 adhs
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
529 memset(adhs
->datarate
, 0, sizeof(adhs
->datarate
));
531 if (adapter
->adhoc_grate_enabled
) {
532 memcpy(adhs
->datarate
, libertas_adhoc_rates_g
,
533 min(sizeof(adhs
->datarate
), sizeof(libertas_adhoc_rates_g
)));
535 memcpy(adhs
->datarate
, libertas_adhoc_rates_b
,
536 min(sizeof(adhs
->datarate
), sizeof(libertas_adhoc_rates_b
)));
539 /* Find the last non zero */
540 for (i
= 0; i
< sizeof(adhs
->datarate
) && adhs
->datarate
[i
]; i
++) ;
542 adapter
->curbssparams
.numofrates
= i
;
544 /* Copy the ad-hoc creating rates into Current BSS state structure */
545 memcpy(&adapter
->curbssparams
.datarates
,
546 &adhs
->datarate
, adapter
->curbssparams
.numofrates
);
548 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
549 adhs
->datarate
[0], adhs
->datarate
[1],
550 adhs
->datarate
[2], adhs
->datarate
[3]);
552 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
554 if (libertas_create_dnld_countryinfo_11d(priv
)) {
555 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
560 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start
) +
561 S_DS_GEN
+ cmdappendsize
);
565 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
569 int libertas_cmd_80211_ad_hoc_stop(wlan_private
* priv
,
570 struct cmd_ds_command
*cmd
)
572 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_STOP
);
573 cmd
->size
= cpu_to_le16(S_DS_GEN
);
578 int libertas_cmd_80211_ad_hoc_join(wlan_private
* priv
,
579 struct cmd_ds_command
*cmd
, void *pdata_buf
)
581 wlan_adapter
*adapter
= priv
->adapter
;
582 struct cmd_ds_802_11_ad_hoc_join
*join_cmd
= &cmd
->params
.adj
;
583 struct assoc_request
* assoc_req
= pdata_buf
;
584 struct bss_descriptor
*bss
= &assoc_req
->bss
;
585 int cmdappendsize
= 0;
591 lbs_deb_enter(LBS_DEB_JOIN
);
593 cmd
->command
= cpu_to_le16(CMD_802_11_AD_HOC_JOIN
);
595 join_cmd
->bss
.type
= CMD_BSS_TYPE_IBSS
;
596 join_cmd
->bss
.beaconperiod
= cpu_to_le16(bss
->beaconperiod
);
598 memcpy(&join_cmd
->bss
.bssid
, &bss
->bssid
, ETH_ALEN
);
599 memcpy(&join_cmd
->bss
.ssid
, &bss
->ssid
, bss
->ssid_len
);
601 memcpy(&join_cmd
->bss
.phyparamset
, &bss
->phyparamset
,
602 sizeof(union ieeetypes_phyparamset
));
604 memcpy(&join_cmd
->bss
.ssparamset
, &bss
->ssparamset
,
605 sizeof(union IEEEtypes_ssparamset
));
607 join_cmd
->bss
.capability
= cpu_to_le16(bss
->capability
& CAPINFO_MASK
);
608 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
609 bss
->capability
, CAPINFO_MASK
);
611 /* information on BSSID descriptor passed to FW */
613 "ADHOC_J_CMD: BSSID = " MAC_FMT
", SSID = '%s'\n",
614 MAC_ARG(join_cmd
->bss
.bssid
), join_cmd
->bss
.ssid
);
617 join_cmd
->failtimeout
= cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT
);
620 join_cmd
->probedelay
= cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME
);
622 /* Copy Data rates from the rates recorded in scan response */
623 memset(join_cmd
->bss
.datarates
, 0, sizeof(join_cmd
->bss
.datarates
));
624 memcpy(join_cmd
->bss
.datarates
, bss
->datarates
,
625 min(sizeof(join_cmd
->bss
.datarates
), sizeof(bss
->datarates
)));
627 card_rates
= libertas_supported_rates
;
628 card_rates_size
= sizeof(libertas_supported_rates
);
630 adapter
->curbssparams
.channel
= bss
->channel
;
632 if (get_common_rates(adapter
, join_cmd
->bss
.datarates
,
633 sizeof(join_cmd
->bss
.datarates
),
634 card_rates
, card_rates_size
)) {
635 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
640 /* Find the last non zero */
641 for (i
= 0; i
< sizeof(join_cmd
->bss
.datarates
)
642 && join_cmd
->bss
.datarates
[i
]; i
++) ;
644 adapter
->curbssparams
.numofrates
= i
;
647 * Copy the adhoc joining rates to Current BSS State structure
649 memcpy(adapter
->curbssparams
.datarates
,
650 join_cmd
->bss
.datarates
,
651 adapter
->curbssparams
.numofrates
);
653 join_cmd
->bss
.ssparamset
.ibssparamset
.atimwindow
=
654 cpu_to_le16(bss
->atimwindow
);
656 if (assoc_req
->secinfo
.wep_enabled
) {
657 u16 tmp
= le16_to_cpu(join_cmd
->bss
.capability
);
658 tmp
|= WLAN_CAPABILITY_PRIVACY
;
659 join_cmd
->bss
.capability
= cpu_to_le16(tmp
);
662 if (adapter
->psmode
== WLAN802_11POWERMODEMAX_PSP
) {
666 Localpsmode
= cpu_to_le32(WLAN802_11POWERMODECAM
);
667 ret
= libertas_prepare_and_send_command(priv
,
678 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
683 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join
) +
684 S_DS_GEN
+ cmdappendsize
);
687 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
691 int libertas_ret_80211_associate(wlan_private
* priv
,
692 struct cmd_ds_command
*resp
)
694 wlan_adapter
*adapter
= priv
->adapter
;
696 union iwreq_data wrqu
;
697 struct ieeetypes_assocrsp
*passocrsp
;
698 struct bss_descriptor
* bss
;
700 lbs_deb_enter(LBS_DEB_JOIN
);
702 if (!adapter
->in_progress_assoc_req
) {
703 lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
707 bss
= &adapter
->in_progress_assoc_req
->bss
;
709 passocrsp
= (struct ieeetypes_assocrsp
*) & resp
->params
;
711 if (le16_to_cpu(passocrsp
->statuscode
)) {
712 libertas_mac_event_disconnected(priv
);
714 lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
715 le16_to_cpu(passocrsp
->statuscode
));
721 lbs_dbg_hex("ASSOC_RESP:", (void *)&resp
->params
,
722 le16_to_cpu(resp
->size
) - S_DS_GEN
);
724 /* Send a Media Connected event, according to the Spec */
725 adapter
->connect_status
= LIBERTAS_CONNECTED
;
727 lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
728 escape_essid(bss
->ssid
, bss
->ssid_len
));
730 /* Update current SSID and BSSID */
731 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
732 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
733 memcpy(adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
735 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
736 adapter
->currentpacketfilter
);
738 adapter
->SNR
[TYPE_RXPD
][TYPE_AVG
] = 0;
739 adapter
->NF
[TYPE_RXPD
][TYPE_AVG
] = 0;
741 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
742 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
743 adapter
->nextSNRNF
= 0;
744 adapter
->numSNRNF
= 0;
746 netif_carrier_on(priv
->dev
);
747 netif_wake_queue(priv
->dev
);
749 netif_carrier_on(priv
->mesh_dev
);
750 netif_wake_queue(priv
->mesh_dev
);
752 lbs_deb_join("ASSOC_RESP: Associated \n");
754 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
755 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
756 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
759 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
763 int libertas_ret_80211_disassociate(wlan_private
* priv
,
764 struct cmd_ds_command
*resp
)
766 lbs_deb_enter(LBS_DEB_JOIN
);
768 libertas_mac_event_disconnected(priv
);
770 lbs_deb_leave(LBS_DEB_JOIN
);
774 int libertas_ret_80211_ad_hoc_start(wlan_private
* priv
,
775 struct cmd_ds_command
*resp
)
777 wlan_adapter
*adapter
= priv
->adapter
;
779 u16 command
= le16_to_cpu(resp
->command
);
780 u16 result
= le16_to_cpu(resp
->result
);
781 struct cmd_ds_802_11_ad_hoc_result
*padhocresult
;
782 union iwreq_data wrqu
;
783 struct bss_descriptor
*bss
;
785 lbs_deb_enter(LBS_DEB_JOIN
);
787 padhocresult
= &resp
->params
.result
;
789 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp
->size
));
790 lbs_deb_join("ADHOC_RESP: command = %x\n", command
);
791 lbs_deb_join("ADHOC_RESP: result = %x\n", result
);
793 if (!adapter
->in_progress_assoc_req
) {
794 lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
798 bss
= &adapter
->in_progress_assoc_req
->bss
;
801 * Join result code 0 --> SUCCESS
804 lbs_deb_join("ADHOC_RESP: failed\n");
805 if (adapter
->connect_status
== LIBERTAS_CONNECTED
) {
806 libertas_mac_event_disconnected(priv
);
813 * Now the join cmd should be successful
814 * If BSSID has changed use SSID to compare instead of BSSID
816 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
817 escape_essid(bss
->ssid
, bss
->ssid_len
));
819 /* Send a Media Connected event, according to the Spec */
820 adapter
->connect_status
= LIBERTAS_CONNECTED
;
822 if (command
== CMD_RET_802_11_AD_HOC_START
) {
823 /* Update the created network descriptor with the new BSSID */
824 memcpy(bss
->bssid
, padhocresult
->bssid
, ETH_ALEN
);
827 /* Set the BSSID from the joined/started descriptor */
828 memcpy(&adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
830 /* Set the new SSID to current SSID */
831 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
, IW_ESSID_MAX_SIZE
);
832 adapter
->curbssparams
.ssid_len
= bss
->ssid_len
;
834 netif_carrier_on(priv
->dev
);
835 netif_wake_queue(priv
->dev
);
837 netif_carrier_on(priv
->mesh_dev
);
838 netif_wake_queue(priv
->mesh_dev
);
840 memset(&wrqu
, 0, sizeof(wrqu
));
841 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
842 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
843 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
845 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
846 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter
->curbssparams
.channel
);
847 lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT
"\n",
848 MAC_ARG(padhocresult
->BSSID
));
851 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
855 int libertas_ret_80211_ad_hoc_stop(wlan_private
* priv
,
856 struct cmd_ds_command
*resp
)
858 lbs_deb_enter(LBS_DEB_JOIN
);
860 libertas_mac_event_disconnected(priv
);
862 lbs_deb_leave(LBS_DEB_JOIN
);