diff options
Diffstat (limited to 'drivers/net/wireless/libertas/assoc.c')
-rw-r--r-- | drivers/net/wireless/libertas/assoc.c | 758 |
1 files changed, 393 insertions, 365 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index a0e440cd8967..b9b374119033 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -12,15 +12,14 @@ | |||
12 | #include "scan.h" | 12 | #include "scan.h" |
13 | #include "cmd.h" | 13 | #include "cmd.h" |
14 | 14 | ||
15 | static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp); | ||
16 | |||
17 | static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = | 15 | static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = |
18 | { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 16 | { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
19 | static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = | 17 | static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = |
20 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 18 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
21 | 19 | ||
22 | /* The firmware needs certain bits masked out of the beacon-derviced capability | 20 | /* The firmware needs the following bits masked out of the beacon-derived |
23 | * field when associating/joining to BSSs. | 21 | * capability field when associating/joining to a BSS: |
22 | * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) | ||
24 | */ | 23 | */ |
25 | #define CAPINFO_MASK (~(0xda00)) | 24 | #define CAPINFO_MASK (~(0xda00)) |
26 | 25 | ||
@@ -102,6 +101,295 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) | |||
102 | } | 101 | } |
103 | 102 | ||
104 | 103 | ||
104 | static u8 iw_auth_to_ieee_auth(u8 auth) | ||
105 | { | ||
106 | if (auth == IW_AUTH_ALG_OPEN_SYSTEM) | ||
107 | return 0x00; | ||
108 | else if (auth == IW_AUTH_ALG_SHARED_KEY) | ||
109 | return 0x01; | ||
110 | else if (auth == IW_AUTH_ALG_LEAP) | ||
111 | return 0x80; | ||
112 | |||
113 | lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * @brief This function prepares the authenticate command. AUTHENTICATE only | ||
119 | * sets the authentication suite for future associations, as the firmware | ||
120 | * handles authentication internally during the ASSOCIATE command. | ||
121 | * | ||
122 | * @param priv A pointer to struct lbs_private structure | ||
123 | * @param bssid The peer BSSID with which to authenticate | ||
124 | * @param auth The authentication mode to use (from wireless.h) | ||
125 | * | ||
126 | * @return 0 or -1 | ||
127 | */ | ||
128 | static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth) | ||
129 | { | ||
130 | struct cmd_ds_802_11_authenticate cmd; | ||
131 | int ret = -1; | ||
132 | DECLARE_MAC_BUF(mac); | ||
133 | |||
134 | lbs_deb_enter(LBS_DEB_JOIN); | ||
135 | |||
136 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
137 | memcpy(cmd.bssid, bssid, ETH_ALEN); | ||
138 | |||
139 | cmd.authtype = iw_auth_to_ieee_auth(auth); | ||
140 | |||
141 | lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", | ||
142 | print_mac(mac, bssid), cmd.authtype); | ||
143 | |||
144 | ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); | ||
145 | |||
146 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | |||
151 | static int lbs_assoc_post(struct lbs_private *priv, | ||
152 | struct cmd_ds_802_11_associate_response *resp) | ||
153 | { | ||
154 | int ret = 0; | ||
155 | union iwreq_data wrqu; | ||
156 | struct bss_descriptor *bss; | ||
157 | u16 status_code; | ||
158 | |||
159 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
160 | |||
161 | if (!priv->in_progress_assoc_req) { | ||
162 | lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); | ||
163 | ret = -1; | ||
164 | goto done; | ||
165 | } | ||
166 | bss = &priv->in_progress_assoc_req->bss; | ||
167 | |||
168 | /* | ||
169 | * Older FW versions map the IEEE 802.11 Status Code in the association | ||
170 | * response to the following values returned in resp->statuscode: | ||
171 | * | ||
172 | * IEEE Status Code Marvell Status Code | ||
173 | * 0 -> 0x0000 ASSOC_RESULT_SUCCESS | ||
174 | * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
175 | * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
176 | * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
177 | * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
178 | * others -> 0x0003 ASSOC_RESULT_REFUSED | ||
179 | * | ||
180 | * Other response codes: | ||
181 | * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) | ||
182 | * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for | ||
183 | * association response from the AP) | ||
184 | */ | ||
185 | |||
186 | status_code = le16_to_cpu(resp->statuscode); | ||
187 | if (priv->fwrelease < 0x09000000) { | ||
188 | switch (status_code) { | ||
189 | case 0x00: | ||
190 | break; | ||
191 | case 0x01: | ||
192 | lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); | ||
193 | break; | ||
194 | case 0x02: | ||
195 | lbs_deb_assoc("ASSOC_RESP: internal timer " | ||
196 | "expired while waiting for the AP\n"); | ||
197 | break; | ||
198 | case 0x03: | ||
199 | lbs_deb_assoc("ASSOC_RESP: association " | ||
200 | "refused by AP\n"); | ||
201 | break; | ||
202 | case 0x04: | ||
203 | lbs_deb_assoc("ASSOC_RESP: authentication " | ||
204 | "refused by AP\n"); | ||
205 | break; | ||
206 | default: | ||
207 | lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " | ||
208 | " unknown\n", status_code); | ||
209 | break; | ||
210 | } | ||
211 | } else { | ||
212 | /* v9+ returns the AP's association response */ | ||
213 | lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code); | ||
214 | } | ||
215 | |||
216 | if (status_code) { | ||
217 | lbs_mac_event_disconnected(priv); | ||
218 | ret = -1; | ||
219 | goto done; | ||
220 | } | ||
221 | |||
222 | lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", | ||
223 | (void *) (resp + sizeof (resp->hdr)), | ||
224 | le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr)); | ||
225 | |||
226 | /* Send a Media Connected event, according to the Spec */ | ||
227 | priv->connect_status = LBS_CONNECTED; | ||
228 | |||
229 | /* Update current SSID and BSSID */ | ||
230 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | ||
231 | priv->curbssparams.ssid_len = bss->ssid_len; | ||
232 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | ||
233 | |||
234 | priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; | ||
235 | priv->NF[TYPE_RXPD][TYPE_AVG] = 0; | ||
236 | |||
237 | memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); | ||
238 | memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); | ||
239 | priv->nextSNRNF = 0; | ||
240 | priv->numSNRNF = 0; | ||
241 | |||
242 | netif_carrier_on(priv->dev); | ||
243 | if (!priv->tx_pending_len) | ||
244 | netif_wake_queue(priv->dev); | ||
245 | |||
246 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
247 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
248 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
249 | |||
250 | done: | ||
251 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * @brief This function prepares an association-class command. | ||
257 | * | ||
258 | * @param priv A pointer to struct lbs_private structure | ||
259 | * @param assoc_req The association request describing the BSS to associate | ||
260 | * or reassociate with | ||
261 | * @param command The actual command, either CMD_802_11_ASSOCIATE or | ||
262 | * CMD_802_11_REASSOCIATE | ||
263 | * | ||
264 | * @return 0 or -1 | ||
265 | */ | ||
266 | static int lbs_associate(struct lbs_private *priv, | ||
267 | struct assoc_request *assoc_req, | ||
268 | u16 command) | ||
269 | { | ||
270 | struct cmd_ds_802_11_associate cmd; | ||
271 | int ret = 0; | ||
272 | struct bss_descriptor *bss = &assoc_req->bss; | ||
273 | u8 *pos = &(cmd.iebuf[0]); | ||
274 | u16 tmpcap, tmplen, tmpauth; | ||
275 | struct mrvl_ie_ssid_param_set *ssid; | ||
276 | struct mrvl_ie_ds_param_set *ds; | ||
277 | struct mrvl_ie_cf_param_set *cf; | ||
278 | struct mrvl_ie_rates_param_set *rates; | ||
279 | struct mrvl_ie_rsn_param_set *rsn; | ||
280 | struct mrvl_ie_auth_type *auth; | ||
281 | |||
282 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
283 | |||
284 | BUG_ON((command != CMD_802_11_ASSOCIATE) && | ||
285 | (command != CMD_802_11_REASSOCIATE)); | ||
286 | |||
287 | memset(&cmd, 0, sizeof(cmd)); | ||
288 | cmd.hdr.command = cpu_to_le16(command); | ||
289 | |||
290 | /* Fill in static fields */ | ||
291 | memcpy(cmd.bssid, bss->bssid, ETH_ALEN); | ||
292 | cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); | ||
293 | |||
294 | /* Capability info */ | ||
295 | tmpcap = (bss->capability & CAPINFO_MASK); | ||
296 | if (bss->mode == IW_MODE_INFRA) | ||
297 | tmpcap |= WLAN_CAPABILITY_ESS; | ||
298 | cmd.capability = cpu_to_le16(tmpcap); | ||
299 | lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); | ||
300 | |||
301 | /* SSID */ | ||
302 | ssid = (struct mrvl_ie_ssid_param_set *) pos; | ||
303 | ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
304 | tmplen = bss->ssid_len; | ||
305 | ssid->header.len = cpu_to_le16(tmplen); | ||
306 | memcpy(ssid->ssid, bss->ssid, tmplen); | ||
307 | pos += sizeof(ssid->header) + tmplen; | ||
308 | |||
309 | ds = (struct mrvl_ie_ds_param_set *) pos; | ||
310 | ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); | ||
311 | ds->header.len = cpu_to_le16(1); | ||
312 | ds->channel = bss->phy.ds.channel; | ||
313 | pos += sizeof(ds->header) + 1; | ||
314 | |||
315 | cf = (struct mrvl_ie_cf_param_set *) pos; | ||
316 | cf->header.type = cpu_to_le16(TLV_TYPE_CF); | ||
317 | tmplen = sizeof(*cf) - sizeof (cf->header); | ||
318 | cf->header.len = cpu_to_le16(tmplen); | ||
319 | /* IE payload should be zeroed, firmware fills it in for us */ | ||
320 | pos += sizeof(*cf); | ||
321 | |||
322 | rates = (struct mrvl_ie_rates_param_set *) pos; | ||
323 | rates->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
324 | memcpy(&rates->rates, &bss->rates, MAX_RATES); | ||
325 | tmplen = MAX_RATES; | ||
326 | if (get_common_rates(priv, rates->rates, &tmplen)) { | ||
327 | ret = -1; | ||
328 | goto done; | ||
329 | } | ||
330 | pos += sizeof(rates->header) + tmplen; | ||
331 | rates->header.len = cpu_to_le16(tmplen); | ||
332 | lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); | ||
333 | |||
334 | /* Copy the infra. association rates into Current BSS state structure */ | ||
335 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
336 | memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); | ||
337 | |||
338 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
339 | * copying to current bss rates. | ||
340 | */ | ||
341 | lbs_set_basic_rate_flags(rates->rates, tmplen); | ||
342 | |||
343 | /* Firmware v9+ indicate authentication suites as a TLV */ | ||
344 | if (priv->fwrelease >= 0x09000000) { | ||
345 | DECLARE_MAC_BUF(mac); | ||
346 | |||
347 | auth = (struct mrvl_ie_auth_type *) pos; | ||
348 | auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); | ||
349 | auth->header.len = cpu_to_le16(2); | ||
350 | tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode); | ||
351 | auth->auth = cpu_to_le16(tmpauth); | ||
352 | pos += sizeof(auth->header) + 2; | ||
353 | |||
354 | lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", | ||
355 | print_mac(mac, bss->bssid), priv->secinfo.auth_mode); | ||
356 | } | ||
357 | |||
358 | /* WPA/WPA2 IEs */ | ||
359 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { | ||
360 | rsn = (struct mrvl_ie_rsn_param_set *) pos; | ||
361 | /* WPA_IE or WPA2_IE */ | ||
362 | rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); | ||
363 | tmplen = (u16) assoc_req->wpa_ie[1]; | ||
364 | rsn->header.len = cpu_to_le16(tmplen); | ||
365 | memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); | ||
366 | lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn, | ||
367 | sizeof(rsn->header) + tmplen); | ||
368 | pos += sizeof(rsn->header) + tmplen; | ||
369 | } | ||
370 | |||
371 | cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) + | ||
372 | (u16)(pos - (u8 *) &cmd.iebuf)); | ||
373 | |||
374 | /* update curbssparams */ | ||
375 | priv->curbssparams.channel = bss->phy.ds.channel; | ||
376 | |||
377 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
378 | ret = -1; | ||
379 | goto done; | ||
380 | } | ||
381 | |||
382 | ret = lbs_cmd_with_response(priv, command, &cmd); | ||
383 | if (ret == 0) { | ||
384 | ret = lbs_assoc_post(priv, | ||
385 | (struct cmd_ds_802_11_associate_response *) &cmd); | ||
386 | } | ||
387 | |||
388 | done: | ||
389 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
390 | return ret; | ||
391 | } | ||
392 | |||
105 | /** | 393 | /** |
106 | * @brief Associate to a specific BSS discovered in a scan | 394 | * @brief Associate to a specific BSS discovered in a scan |
107 | * | 395 | * |
@@ -110,7 +398,7 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) | |||
110 | * | 398 | * |
111 | * @return 0-success, otherwise fail | 399 | * @return 0-success, otherwise fail |
112 | */ | 400 | */ |
113 | static int lbs_associate(struct lbs_private *priv, | 401 | static int lbs_try_associate(struct lbs_private *priv, |
114 | struct assoc_request *assoc_req) | 402 | struct assoc_request *assoc_req) |
115 | { | 403 | { |
116 | int ret; | 404 | int ret; |
@@ -118,11 +406,15 @@ static int lbs_associate(struct lbs_private *priv, | |||
118 | 406 | ||
119 | lbs_deb_enter(LBS_DEB_ASSOC); | 407 | lbs_deb_enter(LBS_DEB_ASSOC); |
120 | 408 | ||
121 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, | 409 | /* FW v9 and higher indicate authentication suites as a TLV in the |
122 | 0, CMD_OPTION_WAITFORRSP, | 410 | * association command, not as a separate authentication command. |
123 | 0, assoc_req->bss.bssid); | 411 | */ |
124 | if (ret) | 412 | if (priv->fwrelease < 0x09000000) { |
125 | goto out; | 413 | ret = lbs_set_authentication(priv, assoc_req->bss.bssid, |
414 | priv->secinfo.auth_mode); | ||
415 | if (ret) | ||
416 | goto out; | ||
417 | } | ||
126 | 418 | ||
127 | /* Use short preamble only when both the BSS and firmware support it */ | 419 | /* Use short preamble only when both the BSS and firmware support it */ |
128 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 420 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && |
@@ -133,14 +425,78 @@ static int lbs_associate(struct lbs_private *priv, | |||
133 | if (ret) | 425 | if (ret) |
134 | goto out; | 426 | goto out; |
135 | 427 | ||
136 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, | 428 | ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); |
137 | 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); | ||
138 | 429 | ||
139 | out: | 430 | out: |
140 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 431 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
141 | return ret; | 432 | return ret; |
142 | } | 433 | } |
143 | 434 | ||
435 | static int lbs_adhoc_post(struct lbs_private *priv, | ||
436 | struct cmd_ds_802_11_ad_hoc_result *resp) | ||
437 | { | ||
438 | int ret = 0; | ||
439 | u16 command = le16_to_cpu(resp->hdr.command); | ||
440 | u16 result = le16_to_cpu(resp->hdr.result); | ||
441 | union iwreq_data wrqu; | ||
442 | struct bss_descriptor *bss; | ||
443 | DECLARE_SSID_BUF(ssid); | ||
444 | |||
445 | lbs_deb_enter(LBS_DEB_JOIN); | ||
446 | |||
447 | if (!priv->in_progress_assoc_req) { | ||
448 | lbs_deb_join("ADHOC_RESP: no in-progress association " | ||
449 | "request\n"); | ||
450 | ret = -1; | ||
451 | goto done; | ||
452 | } | ||
453 | bss = &priv->in_progress_assoc_req->bss; | ||
454 | |||
455 | /* | ||
456 | * Join result code 0 --> SUCCESS | ||
457 | */ | ||
458 | if (result) { | ||
459 | lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); | ||
460 | if (priv->connect_status == LBS_CONNECTED) | ||
461 | lbs_mac_event_disconnected(priv); | ||
462 | ret = -1; | ||
463 | goto done; | ||
464 | } | ||
465 | |||
466 | /* Send a Media Connected event, according to the Spec */ | ||
467 | priv->connect_status = LBS_CONNECTED; | ||
468 | |||
469 | if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { | ||
470 | /* Update the created network descriptor with the new BSSID */ | ||
471 | memcpy(bss->bssid, resp->bssid, ETH_ALEN); | ||
472 | } | ||
473 | |||
474 | /* Set the BSSID from the joined/started descriptor */ | ||
475 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | ||
476 | |||
477 | /* Set the new SSID to current SSID */ | ||
478 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | ||
479 | priv->curbssparams.ssid_len = bss->ssid_len; | ||
480 | |||
481 | netif_carrier_on(priv->dev); | ||
482 | if (!priv->tx_pending_len) | ||
483 | netif_wake_queue(priv->dev); | ||
484 | |||
485 | memset(&wrqu, 0, sizeof(wrqu)); | ||
486 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
487 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
488 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
489 | |||
490 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", | ||
491 | print_ssid(ssid, bss->ssid, bss->ssid_len), | ||
492 | priv->curbssparams.bssid, | ||
493 | priv->curbssparams.channel); | ||
494 | |||
495 | done: | ||
496 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
497 | return ret; | ||
498 | } | ||
499 | |||
144 | /** | 500 | /** |
145 | * @brief Join an adhoc network found in a previous scan | 501 | * @brief Join an adhoc network found in a previous scan |
146 | * | 502 | * |
@@ -219,11 +575,10 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
219 | memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); | 575 | memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); |
220 | memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); | 576 | memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); |
221 | 577 | ||
222 | memcpy(&cmd.bss.phyparamset, &bss->phyparamset, | 578 | memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set)); |
223 | sizeof(union ieeetypes_phyparamset)); | ||
224 | 579 | ||
225 | memcpy(&cmd.bss.ssparamset, &bss->ssparamset, | 580 | memcpy(&cmd.bss.ibss, &bss->ss.ibss, |
226 | sizeof(union IEEEtypes_ssparamset)); | 581 | sizeof(struct ieee_ie_ibss_param_set)); |
227 | 582 | ||
228 | cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); | 583 | cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); |
229 | lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", | 584 | lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", |
@@ -260,7 +615,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
260 | */ | 615 | */ |
261 | lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); | 616 | lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); |
262 | 617 | ||
263 | cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow); | 618 | cmd.bss.ibss.atimwindow = bss->atimwindow; |
264 | 619 | ||
265 | if (assoc_req->secinfo.wep_enabled) { | 620 | if (assoc_req->secinfo.wep_enabled) { |
266 | u16 tmp = le16_to_cpu(cmd.bss.capability); | 621 | u16 tmp = le16_to_cpu(cmd.bss.capability); |
@@ -287,8 +642,10 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
287 | } | 642 | } |
288 | 643 | ||
289 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); | 644 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); |
290 | if (ret == 0) | 645 | if (ret == 0) { |
291 | ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); | 646 | ret = lbs_adhoc_post(priv, |
647 | (struct cmd_ds_802_11_ad_hoc_result *)&cmd); | ||
648 | } | ||
292 | 649 | ||
293 | out: | 650 | out: |
294 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 651 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -343,22 +700,24 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
343 | WARN_ON(!assoc_req->channel); | 700 | WARN_ON(!assoc_req->channel); |
344 | 701 | ||
345 | /* set Physical parameter set */ | 702 | /* set Physical parameter set */ |
346 | cmd.phyparamset.dsparamset.elementid = WLAN_EID_DS_PARAMS; | 703 | cmd.ds.header.id = WLAN_EID_DS_PARAMS; |
347 | cmd.phyparamset.dsparamset.len = 1; | 704 | cmd.ds.header.len = 1; |
348 | cmd.phyparamset.dsparamset.currentchan = assoc_req->channel; | 705 | cmd.ds.channel = assoc_req->channel; |
349 | 706 | ||
350 | /* set IBSS parameter set */ | 707 | /* set IBSS parameter set */ |
351 | cmd.ssparamset.ibssparamset.elementid = WLAN_EID_IBSS_PARAMS; | 708 | cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; |
352 | cmd.ssparamset.ibssparamset.len = 2; | 709 | cmd.ibss.header.len = 2; |
353 | cmd.ssparamset.ibssparamset.atimwindow = 0; | 710 | cmd.ibss.atimwindow = cpu_to_le16(0); |
354 | 711 | ||
355 | /* set capability info */ | 712 | /* set capability info */ |
356 | tmpcap = WLAN_CAPABILITY_IBSS; | 713 | tmpcap = WLAN_CAPABILITY_IBSS; |
357 | if (assoc_req->secinfo.wep_enabled) { | 714 | if (assoc_req->secinfo.wep_enabled || |
358 | lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n"); | 715 | assoc_req->secinfo.WPAenabled || |
716 | assoc_req->secinfo.WPA2enabled) { | ||
717 | lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n"); | ||
359 | tmpcap |= WLAN_CAPABILITY_PRIVACY; | 718 | tmpcap |= WLAN_CAPABILITY_PRIVACY; |
360 | } else | 719 | } else |
361 | lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n"); | 720 | lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n"); |
362 | 721 | ||
363 | cmd.capability = cpu_to_le16(tmpcap); | 722 | cmd.capability = cpu_to_le16(tmpcap); |
364 | 723 | ||
@@ -395,7 +754,8 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
395 | 754 | ||
396 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); | 755 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); |
397 | if (ret == 0) | 756 | if (ret == 0) |
398 | ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); | 757 | ret = lbs_adhoc_post(priv, |
758 | (struct cmd_ds_802_11_ad_hoc_result *)&cmd); | ||
399 | 759 | ||
400 | out: | 760 | out: |
401 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 761 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -720,7 +1080,7 @@ static int assoc_helper_essid(struct lbs_private *priv, | |||
720 | assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); | 1080 | assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); |
721 | if (bss != NULL) { | 1081 | if (bss != NULL) { |
722 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); | 1082 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); |
723 | ret = lbs_associate(priv, assoc_req); | 1083 | ret = lbs_try_associate(priv, assoc_req); |
724 | } else { | 1084 | } else { |
725 | lbs_deb_assoc("SSID not found; cannot associate\n"); | 1085 | lbs_deb_assoc("SSID not found; cannot associate\n"); |
726 | } | 1086 | } |
@@ -772,8 +1132,9 @@ static int assoc_helper_bssid(struct lbs_private *priv, | |||
772 | 1132 | ||
773 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); | 1133 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); |
774 | if (assoc_req->mode == IW_MODE_INFRA) { | 1134 | if (assoc_req->mode == IW_MODE_INFRA) { |
775 | ret = lbs_associate(priv, assoc_req); | 1135 | ret = lbs_try_associate(priv, assoc_req); |
776 | lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); | 1136 | lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n", |
1137 | ret); | ||
777 | } else if (assoc_req->mode == IW_MODE_ADHOC) { | 1138 | } else if (assoc_req->mode == IW_MODE_ADHOC) { |
778 | lbs_adhoc_join(priv, assoc_req); | 1139 | lbs_adhoc_join(priv, assoc_req); |
779 | } | 1140 | } |
@@ -1467,57 +1828,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) | |||
1467 | 1828 | ||
1468 | 1829 | ||
1469 | /** | 1830 | /** |
1470 | * @brief This function prepares command of authenticate. | ||
1471 | * | ||
1472 | * @param priv A pointer to struct lbs_private structure | ||
1473 | * @param cmd A pointer to cmd_ds_command structure | ||
1474 | * @param pdata_buf Void cast of pointer to a BSSID to authenticate with | ||
1475 | * | ||
1476 | * @return 0 or -1 | ||
1477 | */ | ||
1478 | int lbs_cmd_80211_authenticate(struct lbs_private *priv, | ||
1479 | struct cmd_ds_command *cmd, | ||
1480 | void *pdata_buf) | ||
1481 | { | ||
1482 | struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth; | ||
1483 | int ret = -1; | ||
1484 | u8 *bssid = pdata_buf; | ||
1485 | |||
1486 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1487 | |||
1488 | cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE); | ||
1489 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) | ||
1490 | + S_DS_GEN); | ||
1491 | |||
1492 | /* translate auth mode to 802.11 defined wire value */ | ||
1493 | switch (priv->secinfo.auth_mode) { | ||
1494 | case IW_AUTH_ALG_OPEN_SYSTEM: | ||
1495 | pauthenticate->authtype = 0x00; | ||
1496 | break; | ||
1497 | case IW_AUTH_ALG_SHARED_KEY: | ||
1498 | pauthenticate->authtype = 0x01; | ||
1499 | break; | ||
1500 | case IW_AUTH_ALG_LEAP: | ||
1501 | pauthenticate->authtype = 0x80; | ||
1502 | break; | ||
1503 | default: | ||
1504 | lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n", | ||
1505 | priv->secinfo.auth_mode); | ||
1506 | goto out; | ||
1507 | } | ||
1508 | |||
1509 | memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); | ||
1510 | |||
1511 | lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", | ||
1512 | bssid, pauthenticate->authtype); | ||
1513 | ret = 0; | ||
1514 | |||
1515 | out: | ||
1516 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
1517 | return ret; | ||
1518 | } | ||
1519 | |||
1520 | /** | ||
1521 | * @brief Deauthenticate from a specific BSS | 1831 | * @brief Deauthenticate from a specific BSS |
1522 | * | 1832 | * |
1523 | * @param priv A pointer to struct lbs_private structure | 1833 | * @param priv A pointer to struct lbs_private structure |
@@ -1550,285 +1860,3 @@ int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], | |||
1550 | return ret; | 1860 | return ret; |
1551 | } | 1861 | } |
1552 | 1862 | ||
1553 | int lbs_cmd_80211_associate(struct lbs_private *priv, | ||
1554 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
1555 | { | ||
1556 | struct cmd_ds_802_11_associate *passo = &cmd->params.associate; | ||
1557 | int ret = 0; | ||
1558 | struct assoc_request *assoc_req = pdata_buf; | ||
1559 | struct bss_descriptor *bss = &assoc_req->bss; | ||
1560 | u8 *pos; | ||
1561 | u16 tmpcap, tmplen; | ||
1562 | struct mrvlietypes_ssidparamset *ssid; | ||
1563 | struct mrvlietypes_phyparamset *phy; | ||
1564 | struct mrvlietypes_ssparamset *ss; | ||
1565 | struct mrvlietypes_ratesparamset *rates; | ||
1566 | struct mrvlietypes_rsnparamset *rsn; | ||
1567 | |||
1568 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1569 | |||
1570 | pos = (u8 *) passo; | ||
1571 | |||
1572 | if (!priv) { | ||
1573 | ret = -1; | ||
1574 | goto done; | ||
1575 | } | ||
1576 | |||
1577 | cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE); | ||
1578 | |||
1579 | memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr)); | ||
1580 | pos += sizeof(passo->peerstaaddr); | ||
1581 | |||
1582 | /* set the listen interval */ | ||
1583 | passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); | ||
1584 | |||
1585 | pos += sizeof(passo->capability); | ||
1586 | pos += sizeof(passo->listeninterval); | ||
1587 | pos += sizeof(passo->bcnperiod); | ||
1588 | pos += sizeof(passo->dtimperiod); | ||
1589 | |||
1590 | ssid = (struct mrvlietypes_ssidparamset *) pos; | ||
1591 | ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
1592 | tmplen = bss->ssid_len; | ||
1593 | ssid->header.len = cpu_to_le16(tmplen); | ||
1594 | memcpy(ssid->ssid, bss->ssid, tmplen); | ||
1595 | pos += sizeof(ssid->header) + tmplen; | ||
1596 | |||
1597 | phy = (struct mrvlietypes_phyparamset *) pos; | ||
1598 | phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); | ||
1599 | tmplen = sizeof(phy->fh_ds.dsparamset); | ||
1600 | phy->header.len = cpu_to_le16(tmplen); | ||
1601 | memcpy(&phy->fh_ds.dsparamset, | ||
1602 | &bss->phyparamset.dsparamset.currentchan, | ||
1603 | tmplen); | ||
1604 | pos += sizeof(phy->header) + tmplen; | ||
1605 | |||
1606 | ss = (struct mrvlietypes_ssparamset *) pos; | ||
1607 | ss->header.type = cpu_to_le16(TLV_TYPE_CF); | ||
1608 | tmplen = sizeof(ss->cf_ibss.cfparamset); | ||
1609 | ss->header.len = cpu_to_le16(tmplen); | ||
1610 | pos += sizeof(ss->header) + tmplen; | ||
1611 | |||
1612 | rates = (struct mrvlietypes_ratesparamset *) pos; | ||
1613 | rates->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
1614 | memcpy(&rates->rates, &bss->rates, MAX_RATES); | ||
1615 | tmplen = MAX_RATES; | ||
1616 | if (get_common_rates(priv, rates->rates, &tmplen)) { | ||
1617 | ret = -1; | ||
1618 | goto done; | ||
1619 | } | ||
1620 | pos += sizeof(rates->header) + tmplen; | ||
1621 | rates->header.len = cpu_to_le16(tmplen); | ||
1622 | lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); | ||
1623 | |||
1624 | /* Copy the infra. association rates into Current BSS state structure */ | ||
1625 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
1626 | memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); | ||
1627 | |||
1628 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
1629 | * copying to current bss rates. | ||
1630 | */ | ||
1631 | lbs_set_basic_rate_flags(rates->rates, tmplen); | ||
1632 | |||
1633 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { | ||
1634 | rsn = (struct mrvlietypes_rsnparamset *) pos; | ||
1635 | /* WPA_IE or WPA2_IE */ | ||
1636 | rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); | ||
1637 | tmplen = (u16) assoc_req->wpa_ie[1]; | ||
1638 | rsn->header.len = cpu_to_le16(tmplen); | ||
1639 | memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); | ||
1640 | lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn, | ||
1641 | sizeof(rsn->header) + tmplen); | ||
1642 | pos += sizeof(rsn->header) + tmplen; | ||
1643 | } | ||
1644 | |||
1645 | /* update curbssparams */ | ||
1646 | priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; | ||
1647 | |||
1648 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
1649 | ret = -1; | ||
1650 | goto done; | ||
1651 | } | ||
1652 | |||
1653 | cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); | ||
1654 | |||
1655 | /* set the capability info */ | ||
1656 | tmpcap = (bss->capability & CAPINFO_MASK); | ||
1657 | if (bss->mode == IW_MODE_INFRA) | ||
1658 | tmpcap |= WLAN_CAPABILITY_ESS; | ||
1659 | passo->capability = cpu_to_le16(tmpcap); | ||
1660 | lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); | ||
1661 | |||
1662 | done: | ||
1663 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1664 | return ret; | ||
1665 | } | ||
1666 | |||
1667 | int lbs_ret_80211_associate(struct lbs_private *priv, | ||
1668 | struct cmd_ds_command *resp) | ||
1669 | { | ||
1670 | int ret = 0; | ||
1671 | union iwreq_data wrqu; | ||
1672 | struct ieeetypes_assocrsp *passocrsp; | ||
1673 | struct bss_descriptor *bss; | ||
1674 | u16 status_code; | ||
1675 | |||
1676 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1677 | |||
1678 | if (!priv->in_progress_assoc_req) { | ||
1679 | lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); | ||
1680 | ret = -1; | ||
1681 | goto done; | ||
1682 | } | ||
1683 | bss = &priv->in_progress_assoc_req->bss; | ||
1684 | |||
1685 | passocrsp = (struct ieeetypes_assocrsp *) &resp->params; | ||
1686 | |||
1687 | /* | ||
1688 | * Older FW versions map the IEEE 802.11 Status Code in the association | ||
1689 | * response to the following values returned in passocrsp->statuscode: | ||
1690 | * | ||
1691 | * IEEE Status Code Marvell Status Code | ||
1692 | * 0 -> 0x0000 ASSOC_RESULT_SUCCESS | ||
1693 | * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1694 | * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1695 | * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1696 | * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1697 | * others -> 0x0003 ASSOC_RESULT_REFUSED | ||
1698 | * | ||
1699 | * Other response codes: | ||
1700 | * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) | ||
1701 | * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for | ||
1702 | * association response from the AP) | ||
1703 | */ | ||
1704 | |||
1705 | status_code = le16_to_cpu(passocrsp->statuscode); | ||
1706 | switch (status_code) { | ||
1707 | case 0x00: | ||
1708 | break; | ||
1709 | case 0x01: | ||
1710 | lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); | ||
1711 | break; | ||
1712 | case 0x02: | ||
1713 | lbs_deb_assoc("ASSOC_RESP: internal timer " | ||
1714 | "expired while waiting for the AP\n"); | ||
1715 | break; | ||
1716 | case 0x03: | ||
1717 | lbs_deb_assoc("ASSOC_RESP: association " | ||
1718 | "refused by AP\n"); | ||
1719 | break; | ||
1720 | case 0x04: | ||
1721 | lbs_deb_assoc("ASSOC_RESP: authentication " | ||
1722 | "refused by AP\n"); | ||
1723 | break; | ||
1724 | default: | ||
1725 | lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " | ||
1726 | " unknown\n", status_code); | ||
1727 | break; | ||
1728 | } | ||
1729 | |||
1730 | if (status_code) { | ||
1731 | lbs_mac_event_disconnected(priv); | ||
1732 | ret = -1; | ||
1733 | goto done; | ||
1734 | } | ||
1735 | |||
1736 | lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params, | ||
1737 | le16_to_cpu(resp->size) - S_DS_GEN); | ||
1738 | |||
1739 | /* Send a Media Connected event, according to the Spec */ | ||
1740 | priv->connect_status = LBS_CONNECTED; | ||
1741 | |||
1742 | /* Update current SSID and BSSID */ | ||
1743 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | ||
1744 | priv->curbssparams.ssid_len = bss->ssid_len; | ||
1745 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | ||
1746 | |||
1747 | priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; | ||
1748 | priv->NF[TYPE_RXPD][TYPE_AVG] = 0; | ||
1749 | |||
1750 | memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); | ||
1751 | memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); | ||
1752 | priv->nextSNRNF = 0; | ||
1753 | priv->numSNRNF = 0; | ||
1754 | |||
1755 | netif_carrier_on(priv->dev); | ||
1756 | if (!priv->tx_pending_len) | ||
1757 | netif_wake_queue(priv->dev); | ||
1758 | |||
1759 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
1760 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1761 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
1762 | |||
1763 | done: | ||
1764 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1765 | return ret; | ||
1766 | } | ||
1767 | |||
1768 | static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp) | ||
1769 | { | ||
1770 | int ret = 0; | ||
1771 | u16 command = le16_to_cpu(resp->command); | ||
1772 | u16 result = le16_to_cpu(resp->result); | ||
1773 | struct cmd_ds_802_11_ad_hoc_result *adhoc_resp; | ||
1774 | union iwreq_data wrqu; | ||
1775 | struct bss_descriptor *bss; | ||
1776 | DECLARE_SSID_BUF(ssid); | ||
1777 | |||
1778 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1779 | |||
1780 | adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp; | ||
1781 | |||
1782 | if (!priv->in_progress_assoc_req) { | ||
1783 | lbs_deb_join("ADHOC_RESP: no in-progress association " | ||
1784 | "request\n"); | ||
1785 | ret = -1; | ||
1786 | goto done; | ||
1787 | } | ||
1788 | bss = &priv->in_progress_assoc_req->bss; | ||
1789 | |||
1790 | /* | ||
1791 | * Join result code 0 --> SUCCESS | ||
1792 | */ | ||
1793 | if (result) { | ||
1794 | lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); | ||
1795 | if (priv->connect_status == LBS_CONNECTED) | ||
1796 | lbs_mac_event_disconnected(priv); | ||
1797 | ret = -1; | ||
1798 | goto done; | ||
1799 | } | ||
1800 | |||
1801 | /* Send a Media Connected event, according to the Spec */ | ||
1802 | priv->connect_status = LBS_CONNECTED; | ||
1803 | |||
1804 | if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { | ||
1805 | /* Update the created network descriptor with the new BSSID */ | ||
1806 | memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN); | ||
1807 | } | ||
1808 | |||
1809 | /* Set the BSSID from the joined/started descriptor */ | ||
1810 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | ||
1811 | |||
1812 | /* Set the new SSID to current SSID */ | ||
1813 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | ||
1814 | priv->curbssparams.ssid_len = bss->ssid_len; | ||
1815 | |||
1816 | netif_carrier_on(priv->dev); | ||
1817 | if (!priv->tx_pending_len) | ||
1818 | netif_wake_queue(priv->dev); | ||
1819 | |||
1820 | memset(&wrqu, 0, sizeof(wrqu)); | ||
1821 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
1822 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1823 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
1824 | |||
1825 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", | ||
1826 | print_ssid(ssid, bss->ssid, bss->ssid_len), | ||
1827 | priv->curbssparams.bssid, | ||
1828 | priv->curbssparams.channel); | ||
1829 | |||
1830 | done: | ||
1831 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
1832 | return ret; | ||
1833 | } | ||
1834 | |||