1 /* Copyright (C) 2006, Red Hat, Inc. */
3 #include <linux/etherdevice.h>
11 static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
12 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
13 static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
14 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
16 /* The firmware needs certain bits masked out of the beacon-derviced capability
17 * field when associating/joining to BSSs.
19 #define CAPINFO_MASK (~(0xda00))
24 * @brief Associate to a specific BSS discovered in a scan
26 * @param priv A pointer to struct lbs_private structure
27 * @param pbssdesc Pointer to the BSS descriptor to associate with.
29 * @return 0-success, otherwise fail
31 static int lbs_associate(struct lbs_private *priv,
32 struct assoc_request *assoc_req)
36 lbs_deb_enter(LBS_DEB_ASSOC);
38 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
39 0, CMD_OPTION_WAITFORRSP,
40 0, assoc_req->bss.bssid);
45 /* set preamble to firmware */
46 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
47 (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
48 priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
50 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
52 lbs_set_radio_control(priv);
54 ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
55 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
58 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
63 * @brief Join an adhoc network found in a previous scan
65 * @param priv A pointer to struct lbs_private structure
66 * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
69 * @return 0--success, -1--fail
71 static int lbs_join_adhoc_network(struct lbs_private *priv,
72 struct assoc_request *assoc_req)
74 struct bss_descriptor *bss = &assoc_req->bss;
77 lbs_deb_join("current SSID '%s', ssid length %u\n",
78 escape_essid(priv->curbssparams.ssid,
79 priv->curbssparams.ssid_len),
80 priv->curbssparams.ssid_len);
81 lbs_deb_join("requested ssid '%s', ssid length %u\n",
82 escape_essid(bss->ssid, bss->ssid_len),
85 /* check if the requested SSID is already joined */
86 if (priv->curbssparams.ssid_len &&
87 !lbs_ssid_cmp(priv->curbssparams.ssid,
88 priv->curbssparams.ssid_len,
89 bss->ssid, bss->ssid_len) &&
90 (priv->mode == IW_MODE_ADHOC) &&
91 (priv->connect_status == LBS_CONNECTED)) {
92 union iwreq_data wrqu;
94 lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
95 "current, not attempting to re-join");
97 /* Send the re-association event though, because the association
98 * request really was successful, even if just a null-op.
100 memset(&wrqu, 0, sizeof(wrqu));
101 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
103 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
104 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
108 /* Use shortpreamble only when both creator and card supports
110 if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
111 !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
112 lbs_deb_join("AdhocJoin: Long preamble\n");
113 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
115 lbs_deb_join("AdhocJoin: Short preamble\n");
116 priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
119 lbs_set_radio_control(priv);
121 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
122 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
124 priv->adhoccreate = 0;
126 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
127 0, CMD_OPTION_WAITFORRSP,
128 OID_802_11_SSID, assoc_req);
135 * @brief Start an Adhoc Network
137 * @param priv A pointer to struct lbs_private structure
138 * @param adhocssid The ssid of the Adhoc Network
139 * @return 0--success, -1--fail
141 static int lbs_start_adhoc_network(struct lbs_private *priv,
142 struct assoc_request *assoc_req)
146 priv->adhoccreate = 1;
148 if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
149 lbs_deb_join("AdhocStart: Short preamble\n");
150 priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
152 lbs_deb_join("AdhocStart: Long preamble\n");
153 priv->preamble = CMD_TYPE_LONG_PREAMBLE;
156 lbs_set_radio_control(priv);
158 lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
159 lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
161 ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
162 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
167 int lbs_stop_adhoc_network(struct lbs_private *priv)
169 return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
170 0, CMD_OPTION_WAITFORRSP, 0, NULL);
173 static int assoc_helper_essid(struct lbs_private *priv,
174 struct assoc_request * assoc_req)
177 struct bss_descriptor * bss;
180 lbs_deb_enter(LBS_DEB_ASSOC);
182 /* FIXME: take channel into account when picking SSIDs if a channel
186 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
187 channel = assoc_req->channel;
189 lbs_deb_assoc("SSID '%s' requested\n",
190 escape_essid(assoc_req->ssid, assoc_req->ssid_len));
191 if (assoc_req->mode == IW_MODE_INFRA) {
192 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
193 assoc_req->ssid_len);
195 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
196 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
198 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
199 ret = lbs_associate(priv, assoc_req);
201 lbs_deb_assoc("SSID not found; cannot associate\n");
203 } else if (assoc_req->mode == IW_MODE_ADHOC) {
204 /* Scan for the network, do not save previous results. Stale
205 * scan data will cause us to join a non-existant adhoc network
207 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
208 assoc_req->ssid_len);
210 /* Search for the requested SSID in the scan table */
211 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
212 assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
214 lbs_deb_assoc("SSID found, will join\n");
215 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
216 lbs_join_adhoc_network(priv, assoc_req);
218 /* else send START command */
219 lbs_deb_assoc("SSID not found, creating adhoc network\n");
220 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
222 assoc_req->bss.ssid_len = assoc_req->ssid_len;
223 lbs_start_adhoc_network(priv, assoc_req);
227 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
232 static int assoc_helper_bssid(struct lbs_private *priv,
233 struct assoc_request * assoc_req)
236 struct bss_descriptor * bss;
237 DECLARE_MAC_BUF(mac);
239 lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %s",
240 print_mac(mac, assoc_req->bssid));
242 /* Search for index position in list for requested MAC */
243 bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
246 lbs_deb_assoc("ASSOC: WAP: BSSID %s not found, "
247 "cannot associate.\n", print_mac(mac, assoc_req->bssid));
251 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
252 if (assoc_req->mode == IW_MODE_INFRA) {
253 ret = lbs_associate(priv, assoc_req);
254 lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
255 } else if (assoc_req->mode == IW_MODE_ADHOC) {
256 lbs_join_adhoc_network(priv, assoc_req);
260 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
265 static int assoc_helper_associate(struct lbs_private *priv,
266 struct assoc_request * assoc_req)
268 int ret = 0, done = 0;
270 lbs_deb_enter(LBS_DEB_ASSOC);
272 /* If we're given and 'any' BSSID, try associating based on SSID */
274 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
275 if (compare_ether_addr(bssid_any, assoc_req->bssid)
276 && compare_ether_addr(bssid_off, assoc_req->bssid)) {
277 ret = assoc_helper_bssid(priv, assoc_req);
282 if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
283 ret = assoc_helper_essid(priv, assoc_req);
286 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
291 static int assoc_helper_mode(struct lbs_private *priv,
292 struct assoc_request * assoc_req)
296 lbs_deb_enter(LBS_DEB_ASSOC);
298 if (assoc_req->mode == priv->mode)
301 if (assoc_req->mode == IW_MODE_INFRA) {
302 if (priv->psstate != PS_STATE_FULL_POWER)
303 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
304 priv->psmode = LBS802_11POWERMODECAM;
307 priv->mode = assoc_req->mode;
308 ret = lbs_prepare_and_send_command(priv,
310 0, CMD_OPTION_WAITFORRSP,
311 OID_802_11_INFRASTRUCTURE_MODE,
312 /* Shoot me now */ (void *) (size_t) assoc_req->mode);
315 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
320 int lbs_update_channel(struct lbs_private *priv)
324 /* the channel in f/w could be out of sync; get the current channel */
325 lbs_deb_enter(LBS_DEB_ASSOC);
327 ret = lbs_get_channel(priv);
329 priv->curbssparams.channel = ret;
332 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
336 static int assoc_helper_channel(struct lbs_private *priv,
337 struct assoc_request * assoc_req)
341 lbs_deb_enter(LBS_DEB_ASSOC);
343 ret = lbs_update_channel(priv);
345 lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
349 if (assoc_req->channel == priv->curbssparams.channel)
352 if (priv->mesh_dev) {
353 /* Change mesh channel first; 21.p21 firmware won't let
354 you change channel otherwise (even though it'll return
356 lbs_mesh_config(priv, 0, assoc_req->channel);
359 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
360 priv->curbssparams.channel, assoc_req->channel);
362 ret = lbs_set_channel(priv, assoc_req->channel);
364 lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
366 /* FIXME: shouldn't need to grab the channel _again_ after setting
367 * it since the firmware is supposed to return the new channel, but
369 ret = lbs_update_channel(priv);
371 lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
375 if (assoc_req->channel != priv->curbssparams.channel) {
376 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
381 if ( assoc_req->secinfo.wep_enabled
382 && (assoc_req->wep_keys[0].len
383 || assoc_req->wep_keys[1].len
384 || assoc_req->wep_keys[2].len
385 || assoc_req->wep_keys[3].len)) {
386 /* Make sure WEP keys are re-sent to firmware */
387 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
390 /* Must restart/rejoin adhoc networks after channel change */
391 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
395 lbs_mesh_config(priv, 1, priv->curbssparams.channel);
398 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
403 static int assoc_helper_wep_keys(struct lbs_private *priv,
404 struct assoc_request *assoc_req)
409 lbs_deb_enter(LBS_DEB_ASSOC);
411 /* Set or remove WEP keys */
412 if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
413 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
414 ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
416 ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
421 /* enable/disable the MAC's WEP packet filter */
422 if (assoc_req->secinfo.wep_enabled)
423 priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
425 priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
427 lbs_set_mac_control(priv);
429 mutex_lock(&priv->lock);
431 /* Copy WEP keys into priv wep key fields */
432 for (i = 0; i < 4; i++) {
433 memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
434 sizeof(struct enc_key));
436 priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
438 mutex_unlock(&priv->lock);
441 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
445 static int assoc_helper_secinfo(struct lbs_private *priv,
446 struct assoc_request * assoc_req)
452 lbs_deb_enter(LBS_DEB_ASSOC);
454 memcpy(&priv->secinfo, &assoc_req->secinfo,
455 sizeof(struct lbs_802_11_security));
457 lbs_set_mac_control(priv);
459 /* If RSN is already enabled, don't try to enable it again, since
460 * ENABLE_RSN resets internal state machines and will clobber the
461 * 4-way WPA handshake.
464 /* Get RSN enabled/disabled */
465 ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
467 lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
471 /* Don't re-enable RSN if it's already enabled */
472 do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
476 /* Set RSN enabled/disabled */
477 ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
480 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
485 static int assoc_helper_wpa_keys(struct lbs_private *priv,
486 struct assoc_request * assoc_req)
489 unsigned int flags = assoc_req->flags;
491 lbs_deb_enter(LBS_DEB_ASSOC);
493 /* Work around older firmware bug where WPA unicast and multicast
494 * keys must be set independently. Seen in SDIO parts with firmware
498 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
499 clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
500 ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
501 assoc_req->flags = flags;
507 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
508 clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
510 ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
511 assoc_req->flags = flags;
515 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
520 static int assoc_helper_wpa_ie(struct lbs_private *priv,
521 struct assoc_request * assoc_req)
525 lbs_deb_enter(LBS_DEB_ASSOC);
527 if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
528 memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
529 priv->wpa_ie_len = assoc_req->wpa_ie_len;
531 memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
532 priv->wpa_ie_len = 0;
535 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
540 static int should_deauth_infrastructure(struct lbs_private *priv,
541 struct assoc_request * assoc_req)
545 if (priv->connect_status != LBS_CONNECTED)
548 lbs_deb_enter(LBS_DEB_ASSOC);
549 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
550 lbs_deb_assoc("Deauthenticating due to new SSID\n");
555 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
556 if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
557 lbs_deb_assoc("Deauthenticating due to new security\n");
563 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
564 lbs_deb_assoc("Deauthenticating due to new BSSID\n");
569 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
570 lbs_deb_assoc("Deauthenticating due to channel switch\n");
575 /* FIXME: deal with 'auto' mode somehow */
576 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
577 if (assoc_req->mode != IW_MODE_INFRA) {
578 lbs_deb_assoc("Deauthenticating due to leaving "
586 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
591 static int should_stop_adhoc(struct lbs_private *priv,
592 struct assoc_request * assoc_req)
594 lbs_deb_enter(LBS_DEB_ASSOC);
596 if (priv->connect_status != LBS_CONNECTED)
599 if (lbs_ssid_cmp(priv->curbssparams.ssid,
600 priv->curbssparams.ssid_len,
601 assoc_req->ssid, assoc_req->ssid_len) != 0)
604 /* FIXME: deal with 'auto' mode somehow */
605 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
606 if (assoc_req->mode != IW_MODE_ADHOC)
610 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
611 if (assoc_req->channel != priv->curbssparams.channel)
615 lbs_deb_leave(LBS_DEB_ASSOC);
620 void lbs_association_worker(struct work_struct *work)
622 struct lbs_private *priv = container_of(work, struct lbs_private,
624 struct assoc_request * assoc_req = NULL;
626 int find_any_ssid = 0;
627 DECLARE_MAC_BUF(mac);
629 lbs_deb_enter(LBS_DEB_ASSOC);
631 mutex_lock(&priv->lock);
632 assoc_req = priv->pending_assoc_req;
633 priv->pending_assoc_req = NULL;
634 priv->in_progress_assoc_req = assoc_req;
635 mutex_unlock(&priv->lock);
641 "Association Request:\n"
651 escape_essid(assoc_req->ssid, assoc_req->ssid_len),
652 assoc_req->channel, assoc_req->band, assoc_req->mode,
653 print_mac(mac, assoc_req->bssid),
654 assoc_req->secinfo.WPAenabled ? " WPA" : "",
655 assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
656 assoc_req->secinfo.wep_enabled ? " WEP" : "",
657 assoc_req->secinfo.auth_mode);
659 /* If 'any' SSID was specified, find an SSID to associate with */
660 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
661 && !assoc_req->ssid_len)
664 /* But don't use 'any' SSID if there's a valid locked BSSID to use */
665 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
666 if (compare_ether_addr(assoc_req->bssid, bssid_any)
667 && compare_ether_addr(assoc_req->bssid, bssid_off))
674 ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
675 &assoc_req->ssid_len, assoc_req->mode, &new_mode);
677 lbs_deb_assoc("Could not find best network\n");
682 /* Ensure we switch to the mode of the AP */
683 if (assoc_req->mode == IW_MODE_AUTO) {
684 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
685 assoc_req->mode = new_mode;
690 * Check if the attributes being changing require deauthentication
691 * from the currently associated infrastructure access point.
693 if (priv->mode == IW_MODE_INFRA) {
694 if (should_deauth_infrastructure(priv, assoc_req)) {
695 ret = lbs_send_deauthentication(priv);
697 lbs_deb_assoc("Deauthentication due to new "
698 "configuration request failed: %d\n",
702 } else if (priv->mode == IW_MODE_ADHOC) {
703 if (should_stop_adhoc(priv, assoc_req)) {
704 ret = lbs_stop_adhoc_network(priv);
706 lbs_deb_assoc("Teardown of AdHoc network due to "
707 "new configuration request failed: %d\n",
714 /* Send the various configuration bits to the firmware */
715 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
716 ret = assoc_helper_mode(priv, assoc_req);
721 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
722 ret = assoc_helper_channel(priv, assoc_req);
727 if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
728 || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
729 ret = assoc_helper_wep_keys(priv, assoc_req);
734 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
735 ret = assoc_helper_secinfo(priv, assoc_req);
740 if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
741 ret = assoc_helper_wpa_ie(priv, assoc_req);
746 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
747 || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
748 ret = assoc_helper_wpa_keys(priv, assoc_req);
753 /* SSID/BSSID should be the _last_ config option set, because they
754 * trigger the association attempt.
756 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
757 || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
760 ret = assoc_helper_associate(priv, assoc_req);
762 lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
767 if (priv->connect_status != LBS_CONNECTED) {
768 lbs_deb_assoc("ASSOC: association unsuccessful, "
774 lbs_deb_assoc("associated to %s\n",
775 print_mac(mac, priv->curbssparams.bssid));
776 lbs_prepare_and_send_command(priv,
778 0, CMD_OPTION_WAITFORRSP, 0, NULL);
786 lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
790 mutex_lock(&priv->lock);
791 priv->in_progress_assoc_req = NULL;
792 mutex_unlock(&priv->lock);
796 lbs_deb_leave(LBS_DEB_ASSOC);
801 * Caller MUST hold any necessary locks
803 struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
805 struct assoc_request * assoc_req;
807 lbs_deb_enter(LBS_DEB_ASSOC);
808 if (!priv->pending_assoc_req) {
809 priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
811 if (!priv->pending_assoc_req) {
812 lbs_pr_info("Not enough memory to allocate association"
818 /* Copy current configuration attributes to the association request,
819 * but don't overwrite any that are already set.
821 assoc_req = priv->pending_assoc_req;
822 if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
823 memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
825 assoc_req->ssid_len = priv->curbssparams.ssid_len;
828 if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
829 assoc_req->channel = priv->curbssparams.channel;
831 if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
832 assoc_req->band = priv->curbssparams.band;
834 if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
835 assoc_req->mode = priv->mode;
837 if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
838 memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
842 if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
844 for (i = 0; i < 4; i++) {
845 memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
846 sizeof(struct enc_key));
850 if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
851 assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
853 if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
854 memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
855 sizeof(struct enc_key));
858 if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
859 memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
860 sizeof(struct enc_key));
863 if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
864 memcpy(&assoc_req->secinfo, &priv->secinfo,
865 sizeof(struct lbs_802_11_security));
868 if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
869 memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
871 assoc_req->wpa_ie_len = priv->wpa_ie_len;
874 lbs_deb_leave(LBS_DEB_ASSOC);
880 * @brief This function finds common rates between rate1 and card rates.
882 * It will fill common rates in rate1 as output if found.
884 * NOTE: Setting the MSB of the basic rates need to be taken
885 * care, either before or after calling this function
887 * @param priv A pointer to struct lbs_private structure
888 * @param rate1 the buffer which keeps input and output
889 * @param rate1_size the size of rate1 buffer; new size of buffer on return
893 static int get_common_rates(struct lbs_private *priv,
897 u8 *card_rates = lbs_bg_rates;
898 size_t num_card_rates = sizeof(lbs_bg_rates);
903 /* For each rate in card_rates that exists in rate1, copy to tmp */
904 for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
905 for (j = 0; rates[j] && (j < *rates_size); j++) {
906 if (rates[j] == card_rates[i])
907 tmp[tmp_size++] = card_rates[i];
911 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
912 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
913 lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
914 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
916 if (!priv->auto_rate) {
917 for (i = 0; i < tmp_size; i++) {
918 if (tmp[i] == priv->cur_rate)
921 lbs_pr_alert("Previously set fixed data rate %#x isn't "
922 "compatible with the network.\n", priv->cur_rate);
929 memset(rates, 0, *rates_size);
930 *rates_size = min_t(int, tmp_size, *rates_size);
931 memcpy(rates, tmp, *rates_size);
937 * @brief Sets the MSB on basic rates as the firmware requires
939 * Scan through an array and set the MSB for basic data rates.
941 * @param rates buffer of data rates
942 * @param len size of buffer
944 static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
948 for (i = 0; i < len; i++) {
949 if (rates[i] == 0x02 || rates[i] == 0x04 ||
950 rates[i] == 0x0b || rates[i] == 0x16)
956 * @brief Send Deauthentication Request
958 * @param priv A pointer to struct lbs_private structure
959 * @return 0--success, -1--fail
961 int lbs_send_deauthentication(struct lbs_private *priv)
963 return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
964 0, CMD_OPTION_WAITFORRSP, 0, NULL);
968 * @brief This function prepares command of authenticate.
970 * @param priv A pointer to struct lbs_private structure
971 * @param cmd A pointer to cmd_ds_command structure
972 * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
976 int lbs_cmd_80211_authenticate(struct lbs_private *priv,
977 struct cmd_ds_command *cmd,
980 struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
982 u8 *bssid = pdata_buf;
983 DECLARE_MAC_BUF(mac);
985 lbs_deb_enter(LBS_DEB_JOIN);
987 cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
988 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
991 /* translate auth mode to 802.11 defined wire value */
992 switch (priv->secinfo.auth_mode) {
993 case IW_AUTH_ALG_OPEN_SYSTEM:
994 pauthenticate->authtype = 0x00;
996 case IW_AUTH_ALG_SHARED_KEY:
997 pauthenticate->authtype = 0x01;
999 case IW_AUTH_ALG_LEAP:
1000 pauthenticate->authtype = 0x80;
1003 lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
1004 priv->secinfo.auth_mode);
1008 memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
1010 lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
1011 print_mac(mac, bssid), pauthenticate->authtype);
1015 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1019 int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
1020 struct cmd_ds_command *cmd)
1022 struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
1024 lbs_deb_enter(LBS_DEB_JOIN);
1026 cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
1027 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
1030 /* set AP MAC address */
1031 memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
1033 /* Reason code 3 = Station is leaving */
1034 #define REASON_CODE_STA_LEAVING 3
1035 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
1037 lbs_deb_leave(LBS_DEB_JOIN);
1041 int lbs_cmd_80211_associate(struct lbs_private *priv,
1042 struct cmd_ds_command *cmd, void *pdata_buf)
1044 struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
1046 struct assoc_request *assoc_req = pdata_buf;
1047 struct bss_descriptor *bss = &assoc_req->bss;
1050 struct mrvlietypes_ssidparamset *ssid;
1051 struct mrvlietypes_phyparamset *phy;
1052 struct mrvlietypes_ssparamset *ss;
1053 struct mrvlietypes_ratesparamset *rates;
1054 struct mrvlietypes_rsnparamset *rsn;
1056 lbs_deb_enter(LBS_DEB_ASSOC);
1065 cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
1067 memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
1068 pos += sizeof(passo->peerstaaddr);
1070 /* set the listen interval */
1071 passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
1073 pos += sizeof(passo->capability);
1074 pos += sizeof(passo->listeninterval);
1075 pos += sizeof(passo->bcnperiod);
1076 pos += sizeof(passo->dtimperiod);
1078 ssid = (struct mrvlietypes_ssidparamset *) pos;
1079 ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
1080 tmplen = bss->ssid_len;
1081 ssid->header.len = cpu_to_le16(tmplen);
1082 memcpy(ssid->ssid, bss->ssid, tmplen);
1083 pos += sizeof(ssid->header) + tmplen;
1085 phy = (struct mrvlietypes_phyparamset *) pos;
1086 phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
1087 tmplen = sizeof(phy->fh_ds.dsparamset);
1088 phy->header.len = cpu_to_le16(tmplen);
1089 memcpy(&phy->fh_ds.dsparamset,
1090 &bss->phyparamset.dsparamset.currentchan,
1092 pos += sizeof(phy->header) + tmplen;
1094 ss = (struct mrvlietypes_ssparamset *) pos;
1095 ss->header.type = cpu_to_le16(TLV_TYPE_CF);
1096 tmplen = sizeof(ss->cf_ibss.cfparamset);
1097 ss->header.len = cpu_to_le16(tmplen);
1098 pos += sizeof(ss->header) + tmplen;
1100 rates = (struct mrvlietypes_ratesparamset *) pos;
1101 rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
1102 memcpy(&rates->rates, &bss->rates, MAX_RATES);
1104 if (get_common_rates(priv, rates->rates, &tmplen)) {
1108 pos += sizeof(rates->header) + tmplen;
1109 rates->header.len = cpu_to_le16(tmplen);
1110 lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
1112 /* Copy the infra. association rates into Current BSS state structure */
1113 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1114 memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
1116 /* Set MSB on basic rates as the firmware requires, but _after_
1117 * copying to current bss rates.
1119 lbs_set_basic_rate_flags(rates->rates, tmplen);
1121 if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
1122 rsn = (struct mrvlietypes_rsnparamset *) pos;
1123 /* WPA_IE or WPA2_IE */
1124 rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
1125 tmplen = (u16) assoc_req->wpa_ie[1];
1126 rsn->header.len = cpu_to_le16(tmplen);
1127 memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
1128 lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
1129 sizeof(rsn->header) + tmplen);
1130 pos += sizeof(rsn->header) + tmplen;
1133 /* update curbssparams */
1134 priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
1136 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
1141 cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
1143 /* set the capability info */
1144 tmpcap = (bss->capability & CAPINFO_MASK);
1145 if (bss->mode == IW_MODE_INFRA)
1146 tmpcap |= WLAN_CAPABILITY_ESS;
1147 passo->capability = cpu_to_le16(tmpcap);
1148 lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
1151 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1155 int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
1156 struct cmd_ds_command *cmd, void *pdata_buf)
1158 struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
1160 int cmdappendsize = 0;
1161 struct assoc_request *assoc_req = pdata_buf;
1163 size_t ratesize = 0;
1165 lbs_deb_enter(LBS_DEB_JOIN);
1172 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
1175 * Fill in the parameters for 2 data structures:
1176 * 1. cmd_ds_802_11_ad_hoc_start command
1177 * 2. priv->scantable[i]
1179 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
1180 * probe delay, and cap info.
1182 * Firmware will fill up beacon period, DTIM, Basic rates
1183 * and operational rates.
1186 memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
1187 memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
1189 lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
1190 escape_essid(assoc_req->ssid, assoc_req->ssid_len),
1191 assoc_req->ssid_len);
1193 /* set the BSS type */
1194 adhs->bsstype = CMD_BSS_TYPE_IBSS;
1195 priv->mode = IW_MODE_ADHOC;
1196 if (priv->beacon_period == 0)
1197 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
1198 adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
1200 /* set Physical param set */
1201 #define DS_PARA_IE_ID 3
1202 #define DS_PARA_IE_LEN 1
1204 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
1205 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
1207 WARN_ON(!assoc_req->channel);
1209 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
1210 assoc_req->channel);
1212 adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
1214 /* set IBSS param set */
1215 #define IBSS_PARA_IE_ID 6
1216 #define IBSS_PARA_IE_LEN 2
1218 adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
1219 adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
1220 adhs->ssparamset.ibssparamset.atimwindow = 0;
1222 /* set capability info */
1223 tmpcap = WLAN_CAPABILITY_IBSS;
1224 if (assoc_req->secinfo.wep_enabled) {
1225 lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
1226 "setting privacy on\n");
1227 tmpcap |= WLAN_CAPABILITY_PRIVACY;
1229 lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
1230 "setting privacy off\n");
1232 adhs->capability = cpu_to_le16(tmpcap);
1235 adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1237 memset(adhs->rates, 0, sizeof(adhs->rates));
1238 ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
1239 memcpy(adhs->rates, lbs_bg_rates, ratesize);
1241 /* Copy the ad-hoc creating rates into Current BSS state structure */
1242 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1243 memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
1245 /* Set MSB on basic rates as the firmware requires, but _after_
1246 * copying to current bss rates.
1248 lbs_set_basic_rate_flags(adhs->rates, ratesize);
1250 lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
1251 adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
1253 lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
1255 if (lbs_create_dnld_countryinfo_11d(priv)) {
1256 lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
1261 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
1262 S_DS_GEN + cmdappendsize);
1266 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1270 int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
1272 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
1273 cmd->size = cpu_to_le16(S_DS_GEN);
1278 int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
1279 struct cmd_ds_command *cmd, void *pdata_buf)
1281 struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
1282 struct assoc_request *assoc_req = pdata_buf;
1283 struct bss_descriptor *bss = &assoc_req->bss;
1284 int cmdappendsize = 0;
1287 DECLARE_MAC_BUF(mac);
1289 lbs_deb_enter(LBS_DEB_JOIN);
1291 cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
1293 join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
1294 join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
1296 memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
1297 memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
1299 memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
1300 sizeof(union ieeetypes_phyparamset));
1302 memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
1303 sizeof(union IEEEtypes_ssparamset));
1305 join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
1306 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
1307 bss->capability, CAPINFO_MASK);
1309 /* information on BSSID descriptor passed to FW */
1311 "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
1312 print_mac(mac, join_cmd->bss.bssid),
1313 join_cmd->bss.ssid);
1316 join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1319 join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1321 priv->curbssparams.channel = bss->channel;
1323 /* Copy Data rates from the rates recorded in scan response */
1324 memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
1325 ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
1326 memcpy(join_cmd->bss.rates, bss->rates, ratesize);
1327 if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
1328 lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
1333 /* Copy the ad-hoc creating rates into Current BSS state structure */
1334 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1335 memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
1337 /* Set MSB on basic rates as the firmware requires, but _after_
1338 * copying to current bss rates.
1340 lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
1342 join_cmd->bss.ssparamset.ibssparamset.atimwindow =
1343 cpu_to_le16(bss->atimwindow);
1345 if (assoc_req->secinfo.wep_enabled) {
1346 u16 tmp = le16_to_cpu(join_cmd->bss.capability);
1347 tmp |= WLAN_CAPABILITY_PRIVACY;
1348 join_cmd->bss.capability = cpu_to_le16(tmp);
1351 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1355 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1356 ret = lbs_prepare_and_send_command(priv,
1359 0, 0, &Localpsmode);
1367 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
1372 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
1373 S_DS_GEN + cmdappendsize);
1376 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1380 int lbs_ret_80211_associate(struct lbs_private *priv,
1381 struct cmd_ds_command *resp)
1384 union iwreq_data wrqu;
1385 struct ieeetypes_assocrsp *passocrsp;
1386 struct bss_descriptor *bss;
1389 lbs_deb_enter(LBS_DEB_ASSOC);
1391 if (!priv->in_progress_assoc_req) {
1392 lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
1396 bss = &priv->in_progress_assoc_req->bss;
1398 passocrsp = (struct ieeetypes_assocrsp *) &resp->params;
1401 * Older FW versions map the IEEE 802.11 Status Code in the association
1402 * response to the following values returned in passocrsp->statuscode:
1404 * IEEE Status Code Marvell Status Code
1405 * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
1406 * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1407 * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1408 * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1409 * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
1410 * others -> 0x0003 ASSOC_RESULT_REFUSED
1412 * Other response codes:
1413 * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
1414 * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
1415 * association response from the AP)
1418 status_code = le16_to_cpu(passocrsp->statuscode);
1419 switch (status_code) {
1423 lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
1426 lbs_deb_assoc("ASSOC_RESP: internal timer "
1427 "expired while waiting for the AP\n");
1430 lbs_deb_assoc("ASSOC_RESP: association "
1434 lbs_deb_assoc("ASSOC_RESP: authentication "
1438 lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
1439 " unknown\n", status_code);
1444 lbs_mac_event_disconnected(priv);
1449 lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
1450 le16_to_cpu(resp->size) - S_DS_GEN);
1452 /* Send a Media Connected event, according to the Spec */
1453 priv->connect_status = LBS_CONNECTED;
1455 /* Update current SSID and BSSID */
1456 memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
1457 priv->curbssparams.ssid_len = bss->ssid_len;
1458 memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
1460 priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
1461 priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
1463 memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
1464 memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
1465 priv->nextSNRNF = 0;
1468 netif_carrier_on(priv->dev);
1469 if (!priv->tx_pending_len)
1470 netif_wake_queue(priv->dev);
1472 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
1473 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1474 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1477 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1481 int lbs_ret_80211_disassociate(struct lbs_private *priv)
1483 lbs_deb_enter(LBS_DEB_JOIN);
1485 lbs_mac_event_disconnected(priv);
1487 lbs_deb_leave(LBS_DEB_JOIN);
1491 int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
1492 struct cmd_ds_command *resp)
1495 u16 command = le16_to_cpu(resp->command);
1496 u16 result = le16_to_cpu(resp->result);
1497 struct cmd_ds_802_11_ad_hoc_result *padhocresult;
1498 union iwreq_data wrqu;
1499 struct bss_descriptor *bss;
1500 DECLARE_MAC_BUF(mac);
1502 lbs_deb_enter(LBS_DEB_JOIN);
1504 padhocresult = &resp->params.result;
1506 lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
1507 lbs_deb_join("ADHOC_RESP: command = %x\n", command);
1508 lbs_deb_join("ADHOC_RESP: result = %x\n", result);
1510 if (!priv->in_progress_assoc_req) {
1511 lbs_deb_join("ADHOC_RESP: no in-progress association "
1516 bss = &priv->in_progress_assoc_req->bss;
1519 * Join result code 0 --> SUCCESS
1522 lbs_deb_join("ADHOC_RESP: failed\n");
1523 if (priv->connect_status == LBS_CONNECTED)
1524 lbs_mac_event_disconnected(priv);
1530 * Now the join cmd should be successful
1531 * If BSSID has changed use SSID to compare instead of BSSID
1533 lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
1534 escape_essid(bss->ssid, bss->ssid_len));
1536 /* Send a Media Connected event, according to the Spec */
1537 priv->connect_status = LBS_CONNECTED;
1539 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
1540 /* Update the created network descriptor with the new BSSID */
1541 memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
1544 /* Set the BSSID from the joined/started descriptor */
1545 memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
1547 /* Set the new SSID to current SSID */
1548 memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
1549 priv->curbssparams.ssid_len = bss->ssid_len;
1551 netif_carrier_on(priv->dev);
1552 if (!priv->tx_pending_len)
1553 netif_wake_queue(priv->dev);
1555 memset(&wrqu, 0, sizeof(wrqu));
1556 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
1557 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1558 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1560 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
1561 lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
1562 lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
1563 print_mac(mac, padhocresult->bssid));
1566 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
1570 int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
1572 lbs_deb_enter(LBS_DEB_JOIN);
1574 lbs_mac_event_disconnected(priv);
1576 lbs_deb_leave(LBS_DEB_JOIN);