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 #define AD_HOC_CAP_PRIVACY_ON 1
23 * @brief This function finds out the common rates between rate1 and rate2.
25 * It will fill common rates in rate1 as output if found.
27 * NOTE: Setting the MSB of the basic rates need to be taken
28 * care, either before or after calling this function
30 * @param adapter A pointer to wlan_adapter structure
31 * @param rate1 the buffer which keeps input and output
32 * @param rate1_size the size of rate1 buffer
33 * @param rate2 the buffer which keeps rate2
34 * @param rate2_size the size of rate2 buffer.
38 static int get_common_rates(wlan_adapter
* adapter
, u8
* rate1
,
39 int rate1_size
, u8
* rate2
, int rate2_size
)
46 memset(&tmp
, 0, sizeof(tmp
));
47 memcpy(&tmp
, rate1
, min_t(size_t, rate1_size
, sizeof(tmp
)));
48 memset(rate1
, 0, rate1_size
);
50 /* Mask the top bit of the original values */
51 for (i
= 0; tmp
[i
] && i
< sizeof(tmp
); i
++)
54 for (i
= 0; rate2
[i
] && i
< rate2_size
; i
++) {
55 /* Check for Card Rate in tmp, excluding the top bit */
56 if (strchr(tmp
, rate2
[i
] & 0x7F)) {
57 /* values match, so copy the Card Rate to rate1 */
62 lbs_dbg_hex("rate1 (AP) rates:", tmp
, sizeof(tmp
));
63 lbs_dbg_hex("rate2 (Card) rates:", rate2
, rate2_size
);
64 lbs_dbg_hex("Common rates:", ptr
, rate1_size
);
65 lbs_deb_join("Tx datarate is set to 0x%X\n", adapter
->datarate
);
67 if (!adapter
->is_datarate_auto
) {
69 if ((*ptr
& 0x7f) == adapter
->datarate
) {
75 lbs_pr_alert( "Previously set fixed data rate %#x isn't "
76 "compatible with the network.\n", adapter
->datarate
);
87 int libertas_send_deauth(wlan_private
* priv
)
89 wlan_adapter
*adapter
= priv
->adapter
;
92 if (adapter
->mode
== IW_MODE_INFRA
&&
93 adapter
->connect_status
== libertas_connected
)
94 ret
= libertas_send_deauthentication(priv
);
102 * @brief Associate to a specific BSS discovered in a scan
104 * @param priv A pointer to wlan_private structure
105 * @param pbssdesc Pointer to the BSS descriptor to associate with.
107 * @return 0-success, otherwise fail
109 int wlan_associate(wlan_private
* priv
, struct assoc_request
* assoc_req
)
111 wlan_adapter
*adapter
= priv
->adapter
;
114 lbs_deb_enter(LBS_DEB_JOIN
);
116 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_authenticate
,
117 0, cmd_option_waitforrsp
,
118 0, assoc_req
->bss
.bssid
);
123 /* set preamble to firmware */
124 if (adapter
->capinfo
.shortpreamble
&& assoc_req
->bss
.cap
.shortpreamble
)
125 adapter
->preamble
= cmd_type_short_preamble
;
127 adapter
->preamble
= cmd_type_long_preamble
;
129 libertas_set_radio_control(priv
);
131 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_associate
,
132 0, cmd_option_waitforrsp
, 0, assoc_req
);
135 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
140 * @brief Start an Adhoc Network
142 * @param priv A pointer to wlan_private structure
143 * @param adhocssid The ssid of the Adhoc Network
144 * @return 0--success, -1--fail
146 int libertas_start_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
148 wlan_adapter
*adapter
= priv
->adapter
;
151 adapter
->adhoccreate
= 1;
153 if (!adapter
->capinfo
.shortpreamble
) {
154 lbs_deb_join("AdhocStart: Long preamble\n");
155 adapter
->preamble
= cmd_type_long_preamble
;
157 lbs_deb_join("AdhocStart: Short preamble\n");
158 adapter
->preamble
= cmd_type_short_preamble
;
161 libertas_set_radio_control(priv
);
163 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req
->channel
);
164 lbs_deb_join("AdhocStart: band = %d\n", assoc_req
->band
);
166 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_ad_hoc_start
,
167 0, cmd_option_waitforrsp
, 0, assoc_req
);
173 * @brief Join an adhoc network found in a previous scan
175 * @param priv A pointer to wlan_private structure
176 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
179 * @return 0--success, -1--fail
181 int libertas_join_adhoc_network(wlan_private
* priv
, struct assoc_request
* assoc_req
)
183 wlan_adapter
*adapter
= priv
->adapter
;
184 struct bss_descriptor
* bss
= &assoc_req
->bss
;
187 lbs_deb_join("libertas_join_adhoc_network: CurBss.ssid =%s\n",
188 adapter
->curbssparams
.ssid
.ssid
);
189 lbs_deb_join("libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
190 adapter
->curbssparams
.ssid
.ssidlength
);
191 lbs_deb_join("libertas_join_adhoc_network: ssid = '%s'\n",
193 lbs_deb_join("libertas_join_adhoc_network: ssid len = %u\n",
194 bss
->ssid
.ssidlength
);
196 /* check if the requested SSID is already joined */
197 if (adapter
->curbssparams
.ssid
.ssidlength
198 && !libertas_SSID_cmp(&bss
->ssid
, &adapter
->curbssparams
.ssid
)
199 && (adapter
->mode
== IW_MODE_ADHOC
)) {
201 "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
202 "not attempting to re-join");
206 /*Use shortpreamble only when both creator and card supports
208 if (!bss
->cap
.shortpreamble
|| !adapter
->capinfo
.shortpreamble
) {
209 lbs_deb_join("AdhocJoin: Long preamble\n");
210 adapter
->preamble
= cmd_type_long_preamble
;
212 lbs_deb_join("AdhocJoin: Short preamble\n");
213 adapter
->preamble
= cmd_type_short_preamble
;
216 libertas_set_radio_control(priv
);
218 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req
->channel
);
219 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req
->band
);
221 adapter
->adhoccreate
= 0;
223 ret
= libertas_prepare_and_send_command(priv
, cmd_802_11_ad_hoc_join
,
224 0, cmd_option_waitforrsp
,
225 OID_802_11_SSID
, assoc_req
);
230 int libertas_stop_adhoc_network(wlan_private
* priv
)
232 return libertas_prepare_and_send_command(priv
, cmd_802_11_ad_hoc_stop
,
233 0, cmd_option_waitforrsp
, 0, NULL
);
237 * @brief Send Deauthentication Request
239 * @param priv A pointer to wlan_private structure
240 * @return 0--success, -1--fail
242 int libertas_send_deauthentication(wlan_private
* priv
)
244 return libertas_prepare_and_send_command(priv
, cmd_802_11_deauthenticate
,
245 0, cmd_option_waitforrsp
, 0, NULL
);
249 * @brief This function prepares command of authenticate.
251 * @param priv A pointer to wlan_private structure
252 * @param cmd A pointer to cmd_ds_command structure
253 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
257 int libertas_cmd_80211_authenticate(wlan_private
* priv
,
258 struct cmd_ds_command
*cmd
,
261 wlan_adapter
*adapter
= priv
->adapter
;
262 struct cmd_ds_802_11_authenticate
*pauthenticate
= &cmd
->params
.auth
;
264 u8
*bssid
= pdata_buf
;
266 cmd
->command
= cpu_to_le16(cmd_802_11_authenticate
);
267 cmd
->size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate
)
270 /* translate auth mode to 802.11 defined wire value */
271 switch (adapter
->secinfo
.auth_mode
) {
272 case IW_AUTH_ALG_OPEN_SYSTEM
:
273 pauthenticate
->authtype
= 0x00;
275 case IW_AUTH_ALG_SHARED_KEY
:
276 pauthenticate
->authtype
= 0x01;
278 case IW_AUTH_ALG_LEAP
:
279 pauthenticate
->authtype
= 0x80;
282 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
283 adapter
->secinfo
.auth_mode
);
287 memcpy(pauthenticate
->macaddr
, bssid
, ETH_ALEN
);
289 lbs_deb_join("AUTH_CMD: Bssid is : " MAC_FMT
"\n", MAC_ARG(bssid
));
296 int libertas_cmd_80211_deauthenticate(wlan_private
* priv
,
297 struct cmd_ds_command
*cmd
)
299 wlan_adapter
*adapter
= priv
->adapter
;
300 struct cmd_ds_802_11_deauthenticate
*dauth
= &cmd
->params
.deauth
;
302 lbs_deb_enter(LBS_DEB_JOIN
);
304 cmd
->command
= cpu_to_le16(cmd_802_11_deauthenticate
);
306 cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate
) +
309 /* set AP MAC address */
310 memmove(dauth
->macaddr
, adapter
->curbssparams
.bssid
,
313 /* Reason code 3 = Station is leaving */
314 #define REASON_CODE_STA_LEAVING 3
315 dauth
->reasoncode
= cpu_to_le16(REASON_CODE_STA_LEAVING
);
317 lbs_deb_leave(LBS_DEB_JOIN
);
321 int libertas_cmd_80211_associate(wlan_private
* priv
,
322 struct cmd_ds_command
*cmd
, void *pdata_buf
)
324 wlan_adapter
*adapter
= priv
->adapter
;
325 struct cmd_ds_802_11_associate
*passo
= &cmd
->params
.associate
;
327 struct assoc_request
* assoc_req
= pdata_buf
;
328 struct bss_descriptor
* bss
= &assoc_req
->bss
;
333 struct mrvlietypes_ssidparamset
*ssid
;
334 struct mrvlietypes_phyparamset
*phy
;
335 struct mrvlietypes_ssparamset
*ss
;
336 struct mrvlietypes_ratesparamset
*rates
;
337 struct mrvlietypes_rsnparamset
*rsn
;
339 lbs_deb_enter(LBS_DEB_JOIN
);
348 cmd
->command
= cpu_to_le16(cmd_802_11_associate
);
350 memcpy(passo
->peerstaaddr
, bss
->bssid
, sizeof(passo
->peerstaaddr
));
351 pos
+= sizeof(passo
->peerstaaddr
);
353 /* set the listen interval */
354 passo
->listeninterval
= adapter
->listeninterval
;
356 pos
+= sizeof(passo
->capinfo
);
357 pos
+= sizeof(passo
->listeninterval
);
358 pos
+= sizeof(passo
->bcnperiod
);
359 pos
+= sizeof(passo
->dtimperiod
);
361 ssid
= (struct mrvlietypes_ssidparamset
*) pos
;
362 ssid
->header
.type
= cpu_to_le16(TLV_TYPE_SSID
);
363 ssid
->header
.len
= bss
->ssid
.ssidlength
;
364 memcpy(ssid
->ssid
, bss
->ssid
.ssid
, ssid
->header
.len
);
365 pos
+= sizeof(ssid
->header
) + ssid
->header
.len
;
366 ssid
->header
.len
= cpu_to_le16(ssid
->header
.len
);
368 phy
= (struct mrvlietypes_phyparamset
*) pos
;
369 phy
->header
.type
= cpu_to_le16(TLV_TYPE_PHY_DS
);
370 phy
->header
.len
= sizeof(phy
->fh_ds
.dsparamset
);
371 memcpy(&phy
->fh_ds
.dsparamset
,
372 &bss
->phyparamset
.dsparamset
.currentchan
,
373 sizeof(phy
->fh_ds
.dsparamset
));
374 pos
+= sizeof(phy
->header
) + phy
->header
.len
;
375 phy
->header
.len
= cpu_to_le16(phy
->header
.len
);
377 ss
= (struct mrvlietypes_ssparamset
*) pos
;
378 ss
->header
.type
= cpu_to_le16(TLV_TYPE_CF
);
379 ss
->header
.len
= sizeof(ss
->cf_ibss
.cfparamset
);
380 pos
+= sizeof(ss
->header
) + ss
->header
.len
;
381 ss
->header
.len
= cpu_to_le16(ss
->header
.len
);
383 rates
= (struct mrvlietypes_ratesparamset
*) pos
;
384 rates
->header
.type
= cpu_to_le16(TLV_TYPE_RATES
);
386 memcpy(&rates
->rates
, &bss
->libertas_supported_rates
, WLAN_SUPPORTED_RATES
);
388 card_rates
= libertas_supported_rates
;
389 card_rates_size
= sizeof(libertas_supported_rates
);
391 if (get_common_rates(adapter
, rates
->rates
, WLAN_SUPPORTED_RATES
,
392 card_rates
, card_rates_size
)) {
397 rates
->header
.len
= min_t(size_t, strlen(rates
->rates
), WLAN_SUPPORTED_RATES
);
398 adapter
->curbssparams
.numofrates
= rates
->header
.len
;
400 pos
+= sizeof(rates
->header
) + rates
->header
.len
;
401 rates
->header
.len
= cpu_to_le16(rates
->header
.len
);
403 if (assoc_req
->secinfo
.WPAenabled
|| assoc_req
->secinfo
.WPA2enabled
) {
404 rsn
= (struct mrvlietypes_rsnparamset
*) pos
;
405 rsn
->header
.type
= (u16
) assoc_req
->wpa_ie
[0]; /* WPA_IE or WPA2_IE */
406 rsn
->header
.type
= cpu_to_le16(rsn
->header
.type
);
407 rsn
->header
.len
= (u16
) assoc_req
->wpa_ie
[1];
408 memcpy(rsn
->rsnie
, &assoc_req
->wpa_ie
[2], rsn
->header
.len
);
409 lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8
*) rsn
,
410 sizeof(rsn
->header
) + rsn
->header
.len
);
411 pos
+= sizeof(rsn
->header
) + rsn
->header
.len
;
412 rsn
->header
.len
= cpu_to_le16(rsn
->header
.len
);
415 /* update curbssparams */
416 adapter
->curbssparams
.channel
=
417 (bss
->phyparamset
.dsparamset
.currentchan
);
419 /* Copy the infra. association rates into Current BSS state structure */
420 memcpy(&adapter
->curbssparams
.datarates
, &rates
->rates
,
421 min_t(size_t, sizeof(adapter
->curbssparams
.datarates
), rates
->header
.len
));
423 lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n", rates
->header
.len
);
426 if (bss
->mode
== IW_MODE_INFRA
) {
427 #define CAPINFO_ESS_MODE 1
428 passo
->capinfo
.ess
= CAPINFO_ESS_MODE
;
431 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
436 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*) passo
) + S_DS_GEN
);
438 /* set the capability info at last */
439 memcpy(&tmpcap
, &bss
->cap
, sizeof(passo
->capinfo
));
440 tmpcap
&= CAPINFO_MASK
;
441 lbs_deb_join("ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
442 tmpcap
, CAPINFO_MASK
);
443 tmpcap
= cpu_to_le16(tmpcap
);
444 memcpy(&passo
->capinfo
, &tmpcap
, sizeof(passo
->capinfo
));
447 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
451 int libertas_cmd_80211_ad_hoc_start(wlan_private
* priv
,
452 struct cmd_ds_command
*cmd
, void *pdata_buf
)
454 wlan_adapter
*adapter
= priv
->adapter
;
455 struct cmd_ds_802_11_ad_hoc_start
*adhs
= &cmd
->params
.ads
;
457 int cmdappendsize
= 0;
460 struct assoc_request
* assoc_req
= pdata_buf
;
462 lbs_deb_enter(LBS_DEB_JOIN
);
469 cmd
->command
= cpu_to_le16(cmd_802_11_ad_hoc_start
);
472 * Fill in the parameters for 2 data structures:
473 * 1. cmd_ds_802_11_ad_hoc_start command
474 * 2. adapter->scantable[i]
476 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
477 * probe delay, and cap info.
479 * Firmware will fill up beacon period, DTIM, Basic rates
480 * and operational rates.
483 memset(adhs
->SSID
, 0, IW_ESSID_MAX_SIZE
);
484 memcpy(adhs
->SSID
, assoc_req
->ssid
.ssid
, assoc_req
->ssid
.ssidlength
);
486 lbs_deb_join("ADHOC_S_CMD: SSID = %s\n", adhs
->SSID
);
488 /* set the BSS type */
489 adhs
->bsstype
= cmd_bss_type_ibss
;
490 adapter
->mode
= IW_MODE_ADHOC
;
491 adhs
->beaconperiod
= adapter
->beaconperiod
;
493 /* set Physical param set */
494 #define DS_PARA_IE_ID 3
495 #define DS_PARA_IE_LEN 1
497 adhs
->phyparamset
.dsparamset
.elementid
= DS_PARA_IE_ID
;
498 adhs
->phyparamset
.dsparamset
.len
= DS_PARA_IE_LEN
;
500 WARN_ON(!assoc_req
->channel
);
502 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
505 adhs
->phyparamset
.dsparamset
.currentchan
= assoc_req
->channel
;
507 /* set IBSS param set */
508 #define IBSS_PARA_IE_ID 6
509 #define IBSS_PARA_IE_LEN 2
511 adhs
->ssparamset
.ibssparamset
.elementid
= IBSS_PARA_IE_ID
;
512 adhs
->ssparamset
.ibssparamset
.len
= IBSS_PARA_IE_LEN
;
513 adhs
->ssparamset
.ibssparamset
.atimwindow
= adapter
->atimwindow
;
515 /* set capability info */
520 adhs
->probedelay
= cpu_to_le16(cmd_scan_probe_delay_time
);
522 /* set up privacy in adapter->scantable[i] */
523 if (assoc_req
->secinfo
.wep_enabled
) {
524 lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
525 adhs
->cap
.privacy
= AD_HOC_CAP_PRIVACY_ON
;
527 lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
530 memset(adhs
->datarate
, 0, sizeof(adhs
->datarate
));
532 if (adapter
->adhoc_grate_enabled
) {
533 memcpy(adhs
->datarate
, libertas_adhoc_rates_g
,
534 min(sizeof(adhs
->datarate
), sizeof(libertas_adhoc_rates_g
)));
536 memcpy(adhs
->datarate
, libertas_adhoc_rates_b
,
537 min(sizeof(adhs
->datarate
), sizeof(libertas_adhoc_rates_b
)));
540 /* Find the last non zero */
541 for (i
= 0; i
< sizeof(adhs
->datarate
) && adhs
->datarate
[i
]; i
++) ;
543 adapter
->curbssparams
.numofrates
= i
;
545 /* Copy the ad-hoc creating rates into Current BSS state structure */
546 memcpy(&adapter
->curbssparams
.datarates
,
547 &adhs
->datarate
, adapter
->curbssparams
.numofrates
);
549 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
550 adhs
->datarate
[0], adhs
->datarate
[1],
551 adhs
->datarate
[2], adhs
->datarate
[3]);
553 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
555 if (libertas_create_dnld_countryinfo_11d(priv
)) {
556 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
562 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start
)
563 + S_DS_GEN
+ cmdappendsize
);
565 memcpy(&tmpcap
, &adhs
->cap
, sizeof(u16
));
566 tmpcap
= cpu_to_le16(tmpcap
);
567 memcpy(&adhs
->cap
, &tmpcap
, sizeof(u16
));
571 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
575 int libertas_cmd_80211_ad_hoc_stop(wlan_private
* priv
,
576 struct cmd_ds_command
*cmd
)
578 cmd
->command
= cpu_to_le16(cmd_802_11_ad_hoc_stop
);
579 cmd
->size
= cpu_to_le16(S_DS_GEN
);
584 int libertas_cmd_80211_ad_hoc_join(wlan_private
* priv
,
585 struct cmd_ds_command
*cmd
, void *pdata_buf
)
587 wlan_adapter
*adapter
= priv
->adapter
;
588 struct cmd_ds_802_11_ad_hoc_join
*padhocjoin
= &cmd
->params
.adj
;
589 struct assoc_request
* assoc_req
= pdata_buf
;
590 struct bss_descriptor
*bss
= &assoc_req
->bss
;
591 int cmdappendsize
= 0;
598 lbs_deb_enter(LBS_DEB_JOIN
);
600 cmd
->command
= cpu_to_le16(cmd_802_11_ad_hoc_join
);
602 padhocjoin
->bssdescriptor
.bsstype
= cmd_bss_type_ibss
;
604 padhocjoin
->bssdescriptor
.beaconperiod
= bss
->beaconperiod
;
606 memcpy(&padhocjoin
->bssdescriptor
.BSSID
, &bss
->bssid
, ETH_ALEN
);
607 memcpy(&padhocjoin
->bssdescriptor
.SSID
, &bss
->ssid
.ssid
, bss
->ssid
.ssidlength
);
609 memcpy(&padhocjoin
->bssdescriptor
.phyparamset
,
610 &bss
->phyparamset
, sizeof(union ieeetypes_phyparamset
));
612 memcpy(&padhocjoin
->bssdescriptor
.ssparamset
,
613 &bss
->ssparamset
, sizeof(union IEEEtypes_ssparamset
));
615 memcpy(&tmpcap
, &bss
->cap
, sizeof(struct ieeetypes_capinfo
));
616 tmpcap
&= CAPINFO_MASK
;
618 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
619 tmpcap
, CAPINFO_MASK
);
620 memcpy(&padhocjoin
->bssdescriptor
.cap
, &tmpcap
,
621 sizeof(struct ieeetypes_capinfo
));
623 /* information on BSSID descriptor passed to FW */
625 "ADHOC_J_CMD: BSSID = " MAC_FMT
", SSID = '%s'\n",
626 MAC_ARG(padhocjoin
->bssdescriptor
.BSSID
),
627 padhocjoin
->bssdescriptor
.SSID
);
630 padhocjoin
->failtimeout
= cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT
);
633 padhocjoin
->probedelay
=
634 cpu_to_le16(cmd_scan_probe_delay_time
);
636 /* Copy Data rates from the rates recorded in scan response */
637 memset(padhocjoin
->bssdescriptor
.datarates
, 0,
638 sizeof(padhocjoin
->bssdescriptor
.datarates
));
639 memcpy(padhocjoin
->bssdescriptor
.datarates
, bss
->datarates
,
640 min(sizeof(padhocjoin
->bssdescriptor
.datarates
),
641 sizeof(bss
->datarates
)));
643 card_rates
= libertas_supported_rates
;
644 card_rates_size
= sizeof(libertas_supported_rates
);
646 adapter
->curbssparams
.channel
= bss
->channel
;
648 if (get_common_rates(adapter
, padhocjoin
->bssdescriptor
.datarates
,
649 sizeof(padhocjoin
->bssdescriptor
.datarates
),
650 card_rates
, card_rates_size
)) {
651 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
656 /* Find the last non zero */
657 for (i
= 0; i
< sizeof(padhocjoin
->bssdescriptor
.datarates
)
658 && padhocjoin
->bssdescriptor
.datarates
[i
]; i
++) ;
660 adapter
->curbssparams
.numofrates
= i
;
663 * Copy the adhoc joining rates to Current BSS State structure
665 memcpy(adapter
->curbssparams
.datarates
,
666 padhocjoin
->bssdescriptor
.datarates
,
667 adapter
->curbssparams
.numofrates
);
669 padhocjoin
->bssdescriptor
.ssparamset
.ibssparamset
.atimwindow
=
670 cpu_to_le16(bss
->atimwindow
);
672 if (assoc_req
->secinfo
.wep_enabled
) {
673 padhocjoin
->bssdescriptor
.cap
.privacy
= AD_HOC_CAP_PRIVACY_ON
;
676 if (adapter
->psmode
== wlan802_11powermodemax_psp
) {
678 enum WLAN_802_11_POWER_MODE Localpsmode
;
680 Localpsmode
= wlan802_11powermodecam
;
681 ret
= libertas_prepare_and_send_command(priv
,
692 if (libertas_parse_dnld_countryinfo_11d(priv
, bss
)) {
698 cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join
)
699 + S_DS_GEN
+ cmdappendsize
);
701 memcpy(&tmpcap
, &padhocjoin
->bssdescriptor
.cap
,
702 sizeof(struct ieeetypes_capinfo
));
703 tmpcap
= cpu_to_le16(tmpcap
);
705 memcpy(&padhocjoin
->bssdescriptor
.cap
,
706 &tmpcap
, sizeof(struct ieeetypes_capinfo
));
709 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
713 int libertas_ret_80211_associate(wlan_private
* priv
,
714 struct cmd_ds_command
*resp
)
716 wlan_adapter
*adapter
= priv
->adapter
;
718 union iwreq_data wrqu
;
719 struct ieeetypes_assocrsp
*passocrsp
;
720 struct bss_descriptor
* bss
;
722 lbs_deb_enter(LBS_DEB_JOIN
);
724 if (!adapter
->in_progress_assoc_req
) {
725 lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
729 bss
= &adapter
->in_progress_assoc_req
->bss
;
731 passocrsp
= (struct ieeetypes_assocrsp
*) & resp
->params
;
733 if (passocrsp
->statuscode
) {
734 libertas_mac_event_disconnected(priv
);
736 lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
737 passocrsp
->statuscode
);
743 lbs_dbg_hex("ASSOC_RESP:", (void *)&resp
->params
,
744 le16_to_cpu(resp
->size
) - S_DS_GEN
);
746 /* Send a Media Connected event, according to the Spec */
747 adapter
->connect_status
= libertas_connected
;
749 lbs_deb_join("ASSOC_RESP: %s\n", bss
->ssid
.ssid
);
751 /* Update current SSID and BSSID */
752 memcpy(&adapter
->curbssparams
.ssid
,
753 &bss
->ssid
, sizeof(struct WLAN_802_11_SSID
));
754 memcpy(adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
756 lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
757 adapter
->currentpacketfilter
);
759 adapter
->SNR
[TYPE_RXPD
][TYPE_AVG
] = 0;
760 adapter
->NF
[TYPE_RXPD
][TYPE_AVG
] = 0;
762 memset(adapter
->rawSNR
, 0x00, sizeof(adapter
->rawSNR
));
763 memset(adapter
->rawNF
, 0x00, sizeof(adapter
->rawNF
));
764 adapter
->nextSNRNF
= 0;
765 adapter
->numSNRNF
= 0;
767 netif_carrier_on(priv
->dev
);
768 netif_wake_queue(priv
->dev
);
770 netif_carrier_on(priv
->mesh_dev
);
771 netif_wake_queue(priv
->mesh_dev
);
773 lbs_deb_join("ASSOC_RESP: Associated \n");
775 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
776 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
777 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
780 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
784 int libertas_ret_80211_disassociate(wlan_private
* priv
,
785 struct cmd_ds_command
*resp
)
787 lbs_deb_enter(LBS_DEB_JOIN
);
789 libertas_mac_event_disconnected(priv
);
791 lbs_deb_leave(LBS_DEB_JOIN
);
795 int libertas_ret_80211_ad_hoc_start(wlan_private
* priv
,
796 struct cmd_ds_command
*resp
)
798 wlan_adapter
*adapter
= priv
->adapter
;
800 u16 command
= le16_to_cpu(resp
->command
);
801 u16 result
= le16_to_cpu(resp
->result
);
802 struct cmd_ds_802_11_ad_hoc_result
*padhocresult
;
803 union iwreq_data wrqu
;
804 struct bss_descriptor
*bss
;
806 lbs_deb_enter(LBS_DEB_JOIN
);
808 padhocresult
= &resp
->params
.result
;
810 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp
->size
));
811 lbs_deb_join("ADHOC_RESP: command = %x\n", command
);
812 lbs_deb_join("ADHOC_RESP: result = %x\n", result
);
814 if (!adapter
->in_progress_assoc_req
) {
815 lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
819 bss
= &adapter
->in_progress_assoc_req
->bss
;
822 * Join result code 0 --> SUCCESS
825 lbs_deb_join("ADHOC_RESP: failed\n");
826 if (adapter
->connect_status
== libertas_connected
) {
827 libertas_mac_event_disconnected(priv
);
834 * Now the join cmd should be successful
835 * If BSSID has changed use SSID to compare instead of BSSID
837 lbs_deb_join("ADHOC_RESP: %s\n", bss
->ssid
.ssid
);
839 /* Send a Media Connected event, according to the Spec */
840 adapter
->connect_status
= libertas_connected
;
842 if (command
== cmd_ret_802_11_ad_hoc_start
) {
843 /* Update the created network descriptor with the new BSSID */
844 memcpy(bss
->bssid
, padhocresult
->BSSID
, ETH_ALEN
);
847 /* Set the BSSID from the joined/started descriptor */
848 memcpy(&adapter
->curbssparams
.bssid
, bss
->bssid
, ETH_ALEN
);
850 /* Set the new SSID to current SSID */
851 memcpy(&adapter
->curbssparams
.ssid
, &bss
->ssid
,
852 sizeof(struct WLAN_802_11_SSID
));
854 netif_carrier_on(priv
->dev
);
855 netif_wake_queue(priv
->dev
);
857 netif_carrier_on(priv
->mesh_dev
);
858 netif_wake_queue(priv
->mesh_dev
);
860 memset(&wrqu
, 0, sizeof(wrqu
));
861 memcpy(wrqu
.ap_addr
.sa_data
, adapter
->curbssparams
.bssid
, ETH_ALEN
);
862 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
863 wireless_send_event(priv
->dev
, SIOCGIWAP
, &wrqu
, NULL
);
865 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
866 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter
->curbssparams
.channel
);
867 lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT
"\n",
868 MAC_ARG(padhocresult
->BSSID
));
871 lbs_deb_leave_args(LBS_DEB_JOIN
, "ret %d", ret
);
875 int libertas_ret_80211_ad_hoc_stop(wlan_private
* priv
,
876 struct cmd_ds_command
*resp
)
878 lbs_deb_enter(LBS_DEB_JOIN
);
880 libertas_mac_event_disconnected(priv
);
882 lbs_deb_leave(LBS_DEB_JOIN
);