diff options
author | Marcelo Tosatti <marcelo@kvack.org> | 2007-02-10 09:25:27 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 11:00:54 -0400 |
commit | 876c9d3aeb989cf1961f2c228d309ba5dcfb1172 (patch) | |
tree | 239e9db92d13abc799c1ffc5304d8ec1503dbc61 /drivers/net/wireless/libertas/join.c | |
parent | 35c3404efa7407811b706453f83d39b2539dcbd0 (diff) |
[PATCH] Marvell Libertas 8388 802.11b/g USB driver
Add the Marvell Libertas 8388 802.11 USB driver.
Signed-off-by: Marcelo Tosatti <marcelo@kvack.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/join.c')
-rw-r--r-- | drivers/net/wireless/libertas/join.c | 1055 |
1 files changed, 1055 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c new file mode 100644 index 000000000000..11682cbe752b --- /dev/null +++ b/drivers/net/wireless/libertas/join.c | |||
@@ -0,0 +1,1055 @@ | |||
1 | /** | ||
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 | ||
5 | * to the firmware. | ||
6 | */ | ||
7 | #include <linux/netdevice.h> | ||
8 | #include <linux/if_arp.h> | ||
9 | #include <linux/wireless.h> | ||
10 | |||
11 | #include <net/iw_handler.h> | ||
12 | |||
13 | #include "host.h" | ||
14 | #include "decl.h" | ||
15 | #include "join.h" | ||
16 | #include "dev.h" | ||
17 | |||
18 | /** | ||
19 | * @brief This function finds out the common rates between rate1 and rate2. | ||
20 | * | ||
21 | * It will fill common rates in rate1 as output if found. | ||
22 | * | ||
23 | * NOTE: Setting the MSB of the basic rates need to be taken | ||
24 | * care, either before or after calling this function | ||
25 | * | ||
26 | * @param adapter A pointer to wlan_adapter structure | ||
27 | * @param rate1 the buffer which keeps input and output | ||
28 | * @param rate1_size the size of rate1 buffer | ||
29 | * @param rate2 the buffer which keeps rate2 | ||
30 | * @param rate2_size the size of rate2 buffer. | ||
31 | * | ||
32 | * @return 0 or -1 | ||
33 | */ | ||
34 | static int get_common_rates(wlan_adapter * adapter, u8 * rate1, | ||
35 | int rate1_size, u8 * rate2, int rate2_size) | ||
36 | { | ||
37 | u8 *ptr = rate1; | ||
38 | int ret = 0; | ||
39 | u8 tmp[30]; | ||
40 | int i; | ||
41 | |||
42 | memset(&tmp, 0, sizeof(tmp)); | ||
43 | memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp))); | ||
44 | memset(rate1, 0, rate1_size); | ||
45 | |||
46 | /* Mask the top bit of the original values */ | ||
47 | for (i = 0; tmp[i] && i < sizeof(tmp); i++) | ||
48 | tmp[i] &= 0x7F; | ||
49 | |||
50 | for (i = 0; rate2[i] && i < rate2_size; i++) { | ||
51 | /* Check for Card Rate in tmp, excluding the top bit */ | ||
52 | if (strchr(tmp, rate2[i] & 0x7F)) { | ||
53 | /* values match, so copy the Card Rate to rate1 */ | ||
54 | *rate1++ = rate2[i]; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp)); | ||
59 | lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size); | ||
60 | lbs_dbg_hex("Common rates:", ptr, rate1_size); | ||
61 | lbs_pr_debug(1, "Tx datarate is set to 0x%X\n", adapter->datarate); | ||
62 | |||
63 | if (!adapter->is_datarate_auto) { | ||
64 | while (*ptr) { | ||
65 | if ((*ptr & 0x7f) == adapter->datarate) { | ||
66 | ret = 0; | ||
67 | goto done; | ||
68 | } | ||
69 | ptr++; | ||
70 | } | ||
71 | lbs_pr_alert( "Previously set fixed data rate %#x isn't " | ||
72 | "compatible with the network.\n", adapter->datarate); | ||
73 | |||
74 | ret = -1; | ||
75 | goto done; | ||
76 | } | ||
77 | |||
78 | ret = 0; | ||
79 | done: | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | int libertas_send_deauth(wlan_private * priv) | ||
84 | { | ||
85 | wlan_adapter *adapter = priv->adapter; | ||
86 | int ret = 0; | ||
87 | |||
88 | if (adapter->inframode == wlan802_11infrastructure && | ||
89 | adapter->connect_status == libertas_connected) | ||
90 | ret = libertas_send_deauthentication(priv); | ||
91 | else | ||
92 | ret = -ENOTSUPP; | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | int libertas_do_adhocstop_ioctl(wlan_private * priv) | ||
98 | { | ||
99 | wlan_adapter *adapter = priv->adapter; | ||
100 | int ret = 0; | ||
101 | |||
102 | if (adapter->inframode == wlan802_11ibss && | ||
103 | adapter->connect_status == libertas_connected) | ||
104 | ret = libertas_stop_adhoc_network(priv); | ||
105 | else | ||
106 | ret = -ENOTSUPP; | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * @brief Associate to a specific BSS discovered in a scan | ||
113 | * | ||
114 | * @param priv A pointer to wlan_private structure | ||
115 | * @param pbssdesc Pointer to the BSS descriptor to associate with. | ||
116 | * | ||
117 | * @return 0-success, otherwise fail | ||
118 | */ | ||
119 | int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc) | ||
120 | { | ||
121 | wlan_adapter *adapter = priv->adapter; | ||
122 | int ret; | ||
123 | |||
124 | ENTER(); | ||
125 | |||
126 | ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate, | ||
127 | 0, cmd_option_waitforrsp, | ||
128 | 0, pbssdesc->macaddress); | ||
129 | |||
130 | if (ret) { | ||
131 | LEAVE(); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | /* set preamble to firmware */ | ||
136 | if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble) | ||
137 | adapter->preamble = cmd_type_short_preamble; | ||
138 | else | ||
139 | adapter->preamble = cmd_type_long_preamble; | ||
140 | |||
141 | libertas_set_radio_control(priv); | ||
142 | |||
143 | ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate, | ||
144 | 0, cmd_option_waitforrsp, 0, pbssdesc); | ||
145 | |||
146 | LEAVE(); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * @brief Start an Adhoc Network | ||
152 | * | ||
153 | * @param priv A pointer to wlan_private structure | ||
154 | * @param adhocssid The ssid of the Adhoc Network | ||
155 | * @return 0--success, -1--fail | ||
156 | */ | ||
157 | int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid) | ||
158 | { | ||
159 | wlan_adapter *adapter = priv->adapter; | ||
160 | int ret = 0; | ||
161 | |||
162 | adapter->adhoccreate = 1; | ||
163 | |||
164 | if (!adapter->capinfo.shortpreamble) { | ||
165 | lbs_pr_debug(1, "AdhocStart: Long preamble\n"); | ||
166 | adapter->preamble = cmd_type_long_preamble; | ||
167 | } else { | ||
168 | lbs_pr_debug(1, "AdhocStart: Short preamble\n"); | ||
169 | adapter->preamble = cmd_type_short_preamble; | ||
170 | } | ||
171 | |||
172 | libertas_set_radio_control(priv); | ||
173 | |||
174 | lbs_pr_debug(1, "Adhoc channel = %d\n", adapter->adhocchannel); | ||
175 | lbs_pr_debug(1, "curbssparams.channel = %d\n", | ||
176 | adapter->curbssparams.channel); | ||
177 | lbs_pr_debug(1, "curbssparams.band = %d\n", adapter->curbssparams.band); | ||
178 | |||
179 | ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start, | ||
180 | 0, cmd_option_waitforrsp, 0, adhocssid); | ||
181 | |||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * @brief Join an adhoc network found in a previous scan | ||
187 | * | ||
188 | * @param priv A pointer to wlan_private structure | ||
189 | * @param pbssdesc Pointer to a BSS descriptor found in a previous scan | ||
190 | * to attempt to join | ||
191 | * | ||
192 | * @return 0--success, -1--fail | ||
193 | */ | ||
194 | int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc) | ||
195 | { | ||
196 | wlan_adapter *adapter = priv->adapter; | ||
197 | int ret = 0; | ||
198 | |||
199 | lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid =%s\n", | ||
200 | adapter->curbssparams.ssid.ssid); | ||
201 | lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n", | ||
202 | adapter->curbssparams.ssid.ssidlength); | ||
203 | lbs_pr_debug(1, "libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid); | ||
204 | lbs_pr_debug(1, "libertas_join_adhoc_network: ssid len =%u\n", | ||
205 | pbssdesc->ssid.ssidlength); | ||
206 | |||
207 | /* check if the requested SSID is already joined */ | ||
208 | if (adapter->curbssparams.ssid.ssidlength | ||
209 | && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid) | ||
210 | && (adapter->curbssparams.bssdescriptor.inframode == | ||
211 | wlan802_11ibss)) { | ||
212 | |||
213 | lbs_pr_debug(1, | ||
214 | "ADHOC_J_CMD: New ad-hoc SSID is the same as current, " | ||
215 | "not attempting to re-join"); | ||
216 | |||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | /*Use shortpreamble only when both creator and card supports | ||
221 | short preamble */ | ||
222 | if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) { | ||
223 | lbs_pr_debug(1, "AdhocJoin: Long preamble\n"); | ||
224 | adapter->preamble = cmd_type_long_preamble; | ||
225 | } else { | ||
226 | lbs_pr_debug(1, "AdhocJoin: Short preamble\n"); | ||
227 | adapter->preamble = cmd_type_short_preamble; | ||
228 | } | ||
229 | |||
230 | libertas_set_radio_control(priv); | ||
231 | |||
232 | lbs_pr_debug(1, "curbssparams.channel = %d\n", | ||
233 | adapter->curbssparams.channel); | ||
234 | lbs_pr_debug(1, "curbssparams.band = %c\n", adapter->curbssparams.band); | ||
235 | |||
236 | adapter->adhoccreate = 0; | ||
237 | |||
238 | ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join, | ||
239 | 0, cmd_option_waitforrsp, | ||
240 | OID_802_11_SSID, pbssdesc); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | int libertas_stop_adhoc_network(wlan_private * priv) | ||
246 | { | ||
247 | return libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_stop, | ||
248 | 0, cmd_option_waitforrsp, 0, NULL); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * @brief Send Deauthentication Request | ||
253 | * | ||
254 | * @param priv A pointer to wlan_private structure | ||
255 | * @return 0--success, -1--fail | ||
256 | */ | ||
257 | int libertas_send_deauthentication(wlan_private * priv) | ||
258 | { | ||
259 | return libertas_prepare_and_send_command(priv, cmd_802_11_deauthenticate, | ||
260 | 0, cmd_option_waitforrsp, 0, NULL); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * @brief Set Idle Off | ||
265 | * | ||
266 | * @param priv A pointer to wlan_private structure | ||
267 | * @return 0 --success, otherwise fail | ||
268 | */ | ||
269 | int libertas_idle_off(wlan_private * priv) | ||
270 | { | ||
271 | wlan_adapter *adapter = priv->adapter; | ||
272 | int ret = 0; | ||
273 | const u8 zeromac[] = { 0, 0, 0, 0, 0, 0 }; | ||
274 | int i; | ||
275 | |||
276 | ENTER(); | ||
277 | |||
278 | if (adapter->connect_status == libertas_disconnected) { | ||
279 | if (adapter->inframode == wlan802_11infrastructure) { | ||
280 | if (memcmp(adapter->previousbssid, zeromac, | ||
281 | sizeof(zeromac)) != 0) { | ||
282 | |||
283 | lbs_pr_debug(1, "Previous SSID = %s\n", | ||
284 | adapter->previousssid.ssid); | ||
285 | lbs_pr_debug(1, "Previous BSSID = " | ||
286 | "%02x:%02x:%02x:%02x:%02x:%02x:\n", | ||
287 | adapter->previousbssid[0], | ||
288 | adapter->previousbssid[1], | ||
289 | adapter->previousbssid[2], | ||
290 | adapter->previousbssid[3], | ||
291 | adapter->previousbssid[4], | ||
292 | adapter->previousbssid[5]); | ||
293 | |||
294 | i = libertas_find_SSID_in_list(adapter, | ||
295 | &adapter->previousssid, | ||
296 | adapter->previousbssid, | ||
297 | adapter->inframode); | ||
298 | |||
299 | if (i < 0) { | ||
300 | libertas_send_specific_BSSID_scan(priv, | ||
301 | adapter-> | ||
302 | previousbssid, | ||
303 | 1); | ||
304 | i = libertas_find_SSID_in_list(adapter, | ||
305 | &adapter-> | ||
306 | previousssid, | ||
307 | adapter-> | ||
308 | previousbssid, | ||
309 | adapter-> | ||
310 | inframode); | ||
311 | } | ||
312 | |||
313 | if (i < 0) { | ||
314 | /* If the BSSID could not be found, try just the SSID */ | ||
315 | i = libertas_find_SSID_in_list(adapter, | ||
316 | &adapter-> | ||
317 | previousssid, NULL, | ||
318 | adapter-> | ||
319 | inframode); | ||
320 | } | ||
321 | |||
322 | if (i < 0) { | ||
323 | libertas_send_specific_SSID_scan(priv, | ||
324 | &adapter-> | ||
325 | previousssid, | ||
326 | 1); | ||
327 | i = libertas_find_SSID_in_list(adapter, | ||
328 | &adapter-> | ||
329 | previousssid, NULL, | ||
330 | adapter-> | ||
331 | inframode); | ||
332 | } | ||
333 | |||
334 | if (i >= 0) { | ||
335 | ret = | ||
336 | wlan_associate(priv, | ||
337 | &adapter-> | ||
338 | scantable[i]); | ||
339 | } | ||
340 | } | ||
341 | } else if (adapter->inframode == wlan802_11ibss) { | ||
342 | ret = libertas_prepare_and_send_command(priv, | ||
343 | cmd_802_11_ad_hoc_start, | ||
344 | 0, | ||
345 | cmd_option_waitforrsp, | ||
346 | 0, &adapter->previousssid); | ||
347 | } | ||
348 | } | ||
349 | /* else it is connected */ | ||
350 | |||
351 | lbs_pr_debug(1, "\nwlanidle is off"); | ||
352 | LEAVE(); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * @brief Set Idle On | ||
358 | * | ||
359 | * @param priv A pointer to wlan_private structure | ||
360 | * @return 0 --success, otherwise fail | ||
361 | */ | ||
362 | int libertas_idle_on(wlan_private * priv) | ||
363 | { | ||
364 | wlan_adapter *adapter = priv->adapter; | ||
365 | int ret = 0; | ||
366 | |||
367 | if (adapter->connect_status == libertas_connected) { | ||
368 | if (adapter->inframode == wlan802_11infrastructure) { | ||
369 | lbs_pr_debug(1, "Previous SSID = %s\n", | ||
370 | adapter->previousssid.ssid); | ||
371 | memmove(&adapter->previousssid, | ||
372 | &adapter->curbssparams.ssid, | ||
373 | sizeof(struct WLAN_802_11_SSID)); | ||
374 | libertas_send_deauth(priv); | ||
375 | |||
376 | } else if (adapter->inframode == wlan802_11ibss) { | ||
377 | ret = libertas_stop_adhoc_network(priv); | ||
378 | } | ||
379 | |||
380 | } | ||
381 | |||
382 | lbs_pr_debug(1, "\nwlanidle is on"); | ||
383 | |||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * @brief This function prepares command of authenticate. | ||
389 | * | ||
390 | * @param priv A pointer to wlan_private structure | ||
391 | * @param cmd A pointer to cmd_ds_command structure | ||
392 | * @param pdata_buf Void cast of pointer to a BSSID to authenticate with | ||
393 | * | ||
394 | * @return 0 or -1 | ||
395 | */ | ||
396 | int libertas_cmd_80211_authenticate(wlan_private * priv, | ||
397 | struct cmd_ds_command *cmd, | ||
398 | void *pdata_buf) | ||
399 | { | ||
400 | wlan_adapter *adapter = priv->adapter; | ||
401 | struct cmd_ds_802_11_authenticate *pauthenticate = | ||
402 | &cmd->params.auth; | ||
403 | u8 *bssid = pdata_buf; | ||
404 | |||
405 | cmd->command = cpu_to_le16(cmd_802_11_authenticate); | ||
406 | cmd->size = | ||
407 | cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) | ||
408 | + S_DS_GEN); | ||
409 | |||
410 | pauthenticate->authtype = adapter->secinfo.authmode; | ||
411 | memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); | ||
412 | |||
413 | lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n", | ||
414 | bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | int libertas_cmd_80211_deauthenticate(wlan_private * priv, | ||
420 | struct cmd_ds_command *cmd) | ||
421 | { | ||
422 | wlan_adapter *adapter = priv->adapter; | ||
423 | struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; | ||
424 | |||
425 | ENTER(); | ||
426 | |||
427 | cmd->command = cpu_to_le16(cmd_802_11_deauthenticate); | ||
428 | cmd->size = | ||
429 | cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + | ||
430 | S_DS_GEN); | ||
431 | |||
432 | /* set AP MAC address */ | ||
433 | memmove(dauth->macaddr, adapter->curbssparams.bssid, | ||
434 | ETH_ALEN); | ||
435 | |||
436 | /* Reason code 3 = Station is leaving */ | ||
437 | #define REASON_CODE_STA_LEAVING 3 | ||
438 | dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); | ||
439 | |||
440 | LEAVE(); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | int libertas_cmd_80211_associate(wlan_private * priv, | ||
445 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
446 | { | ||
447 | wlan_adapter *adapter = priv->adapter; | ||
448 | struct cmd_ds_802_11_associate *passo = &cmd->params.associate; | ||
449 | int ret = 0; | ||
450 | struct bss_descriptor *pbssdesc; | ||
451 | u8 *card_rates; | ||
452 | u8 *pos; | ||
453 | int card_rates_size; | ||
454 | u16 tmpcap; | ||
455 | struct mrvlietypes_ssidparamset *ssid; | ||
456 | struct mrvlietypes_phyparamset *phy; | ||
457 | struct mrvlietypes_ssparamset *ss; | ||
458 | struct mrvlietypes_ratesparamset *rates; | ||
459 | struct mrvlietypes_rsnparamset *rsn; | ||
460 | |||
461 | ENTER(); | ||
462 | |||
463 | pbssdesc = pdata_buf; | ||
464 | pos = (u8 *) passo; | ||
465 | |||
466 | if (!adapter) { | ||
467 | ret = -1; | ||
468 | goto done; | ||
469 | } | ||
470 | |||
471 | cmd->command = cpu_to_le16(cmd_802_11_associate); | ||
472 | |||
473 | /* Save so we know which BSS Desc to use in the response handler */ | ||
474 | adapter->pattemptedbssdesc = pbssdesc; | ||
475 | |||
476 | memcpy(passo->peerstaaddr, | ||
477 | pbssdesc->macaddress, sizeof(passo->peerstaaddr)); | ||
478 | pos += sizeof(passo->peerstaaddr); | ||
479 | |||
480 | /* set the listen interval */ | ||
481 | passo->listeninterval = adapter->listeninterval; | ||
482 | |||
483 | pos += sizeof(passo->capinfo); | ||
484 | pos += sizeof(passo->listeninterval); | ||
485 | pos += sizeof(passo->bcnperiod); | ||
486 | pos += sizeof(passo->dtimperiod); | ||
487 | |||
488 | ssid = (struct mrvlietypes_ssidparamset *) pos; | ||
489 | ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
490 | ssid->header.len = pbssdesc->ssid.ssidlength; | ||
491 | memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len); | ||
492 | pos += sizeof(ssid->header) + ssid->header.len; | ||
493 | ssid->header.len = cpu_to_le16(ssid->header.len); | ||
494 | |||
495 | phy = (struct mrvlietypes_phyparamset *) pos; | ||
496 | phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); | ||
497 | phy->header.len = sizeof(phy->fh_ds.dsparamset); | ||
498 | memcpy(&phy->fh_ds.dsparamset, | ||
499 | &pbssdesc->phyparamset.dsparamset.currentchan, | ||
500 | sizeof(phy->fh_ds.dsparamset)); | ||
501 | pos += sizeof(phy->header) + phy->header.len; | ||
502 | phy->header.len = cpu_to_le16(phy->header.len); | ||
503 | |||
504 | ss = (struct mrvlietypes_ssparamset *) pos; | ||
505 | ss->header.type = cpu_to_le16(TLV_TYPE_CF); | ||
506 | ss->header.len = sizeof(ss->cf_ibss.cfparamset); | ||
507 | pos += sizeof(ss->header) + ss->header.len; | ||
508 | ss->header.len = cpu_to_le16(ss->header.len); | ||
509 | |||
510 | rates = (struct mrvlietypes_ratesparamset *) pos; | ||
511 | rates->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
512 | |||
513 | memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES); | ||
514 | |||
515 | card_rates = libertas_supported_rates; | ||
516 | card_rates_size = sizeof(libertas_supported_rates); | ||
517 | |||
518 | if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES, | ||
519 | card_rates, card_rates_size)) { | ||
520 | ret = -1; | ||
521 | goto done; | ||
522 | } | ||
523 | |||
524 | rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES); | ||
525 | adapter->curbssparams.numofrates = rates->header.len; | ||
526 | |||
527 | pos += sizeof(rates->header) + rates->header.len; | ||
528 | rates->header.len = cpu_to_le16(rates->header.len); | ||
529 | |||
530 | if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) { | ||
531 | rsn = (struct mrvlietypes_rsnparamset *) pos; | ||
532 | rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */ | ||
533 | rsn->header.type = cpu_to_le16(rsn->header.type); | ||
534 | rsn->header.len = (u16) adapter->wpa_ie[1]; | ||
535 | memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len); | ||
536 | lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn, | ||
537 | sizeof(rsn->header) + rsn->header.len); | ||
538 | pos += sizeof(rsn->header) + rsn->header.len; | ||
539 | rsn->header.len = cpu_to_le16(rsn->header.len); | ||
540 | } | ||
541 | |||
542 | /* update curbssparams */ | ||
543 | adapter->curbssparams.channel = | ||
544 | (pbssdesc->phyparamset.dsparamset.currentchan); | ||
545 | |||
546 | /* Copy the infra. association rates into Current BSS state structure */ | ||
547 | memcpy(&adapter->curbssparams.datarates, &rates->rates, | ||
548 | min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len)); | ||
549 | |||
550 | lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len); | ||
551 | |||
552 | /* set IBSS field */ | ||
553 | if (pbssdesc->inframode == wlan802_11infrastructure) { | ||
554 | #define CAPINFO_ESS_MODE 1 | ||
555 | passo->capinfo.ess = CAPINFO_ESS_MODE; | ||
556 | } | ||
557 | |||
558 | if (libertas_parse_dnld_countryinfo_11d(priv)) { | ||
559 | ret = -1; | ||
560 | goto done; | ||
561 | } | ||
562 | |||
563 | cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); | ||
564 | |||
565 | /* set the capability info at last */ | ||
566 | memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo)); | ||
567 | tmpcap &= CAPINFO_MASK; | ||
568 | lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", | ||
569 | tmpcap, CAPINFO_MASK); | ||
570 | tmpcap = cpu_to_le16(tmpcap); | ||
571 | memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo)); | ||
572 | |||
573 | done: | ||
574 | LEAVE(); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, | ||
579 | struct cmd_ds_command *cmd, void *pssid) | ||
580 | { | ||
581 | wlan_adapter *adapter = priv->adapter; | ||
582 | struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; | ||
583 | int ret = 0; | ||
584 | int cmdappendsize = 0; | ||
585 | int i; | ||
586 | u16 tmpcap; | ||
587 | struct bss_descriptor *pbssdesc; | ||
588 | struct WLAN_802_11_SSID *ssid = pssid; | ||
589 | |||
590 | ENTER(); | ||
591 | |||
592 | if (!adapter) { | ||
593 | ret = -1; | ||
594 | goto done; | ||
595 | } | ||
596 | |||
597 | cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start); | ||
598 | |||
599 | pbssdesc = &adapter->curbssparams.bssdescriptor; | ||
600 | adapter->pattemptedbssdesc = pbssdesc; | ||
601 | |||
602 | /* | ||
603 | * Fill in the parameters for 2 data structures: | ||
604 | * 1. cmd_ds_802_11_ad_hoc_start command | ||
605 | * 2. adapter->scantable[i] | ||
606 | * | ||
607 | * Driver will fill up SSID, bsstype,IBSS param, Physical Param, | ||
608 | * probe delay, and cap info. | ||
609 | * | ||
610 | * Firmware will fill up beacon period, DTIM, Basic rates | ||
611 | * and operational rates. | ||
612 | */ | ||
613 | |||
614 | memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE); | ||
615 | |||
616 | memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength); | ||
617 | |||
618 | lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID); | ||
619 | |||
620 | memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE); | ||
621 | memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength); | ||
622 | |||
623 | pbssdesc->ssid.ssidlength = ssid->ssidlength; | ||
624 | |||
625 | /* set the BSS type */ | ||
626 | adhs->bsstype = cmd_bss_type_ibss; | ||
627 | pbssdesc->inframode = wlan802_11ibss; | ||
628 | adhs->beaconperiod = adapter->beaconperiod; | ||
629 | |||
630 | /* set Physical param set */ | ||
631 | #define DS_PARA_IE_ID 3 | ||
632 | #define DS_PARA_IE_LEN 1 | ||
633 | |||
634 | adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID; | ||
635 | adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN; | ||
636 | |||
637 | WARN_ON(!adapter->adhocchannel); | ||
638 | |||
639 | lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n", | ||
640 | adapter->adhocchannel); | ||
641 | |||
642 | adapter->curbssparams.channel = adapter->adhocchannel; | ||
643 | |||
644 | pbssdesc->channel = adapter->adhocchannel; | ||
645 | adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel; | ||
646 | |||
647 | memcpy(&pbssdesc->phyparamset, | ||
648 | &adhs->phyparamset, sizeof(union ieeetypes_phyparamset)); | ||
649 | |||
650 | /* set IBSS param set */ | ||
651 | #define IBSS_PARA_IE_ID 6 | ||
652 | #define IBSS_PARA_IE_LEN 2 | ||
653 | |||
654 | adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID; | ||
655 | adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN; | ||
656 | adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow; | ||
657 | memcpy(&pbssdesc->ssparamset, | ||
658 | &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset)); | ||
659 | |||
660 | /* set capability info */ | ||
661 | adhs->cap.ess = 0; | ||
662 | adhs->cap.ibss = 1; | ||
663 | pbssdesc->cap.ibss = 1; | ||
664 | |||
665 | /* probedelay */ | ||
666 | adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time); | ||
667 | |||
668 | /* set up privacy in adapter->scantable[i] */ | ||
669 | if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) { | ||
670 | |||
671 | #define AD_HOC_CAP_PRIVACY_ON 1 | ||
672 | lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus set, privacy to WEP\n"); | ||
673 | pbssdesc->privacy = wlan802_11privfilter8021xWEP; | ||
674 | adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON; | ||
675 | } else { | ||
676 | lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus NOT set, Setting " | ||
677 | "privacy to ACCEPT ALL\n"); | ||
678 | pbssdesc->privacy = wlan802_11privfilteracceptall; | ||
679 | } | ||
680 | |||
681 | memset(adhs->datarate, 0, sizeof(adhs->datarate)); | ||
682 | |||
683 | if (adapter->adhoc_grate_enabled) { | ||
684 | memcpy(adhs->datarate, libertas_adhoc_rates_g, | ||
685 | min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g))); | ||
686 | } else { | ||
687 | memcpy(adhs->datarate, libertas_adhoc_rates_b, | ||
688 | min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b))); | ||
689 | } | ||
690 | |||
691 | /* Find the last non zero */ | ||
692 | for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ; | ||
693 | |||
694 | adapter->curbssparams.numofrates = i; | ||
695 | |||
696 | /* Copy the ad-hoc creating rates into Current BSS state structure */ | ||
697 | memcpy(&adapter->curbssparams.datarates, | ||
698 | &adhs->datarate, adapter->curbssparams.numofrates); | ||
699 | |||
700 | lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", | ||
701 | adhs->datarate[0], adhs->datarate[1], | ||
702 | adhs->datarate[2], adhs->datarate[3]); | ||
703 | |||
704 | lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n"); | ||
705 | |||
706 | if (libertas_create_dnld_countryinfo_11d(priv)) { | ||
707 | lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); | ||
708 | ret = -1; | ||
709 | goto done; | ||
710 | } | ||
711 | |||
712 | cmd->size = | ||
713 | cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) | ||
714 | + S_DS_GEN + cmdappendsize); | ||
715 | |||
716 | memcpy(&tmpcap, &adhs->cap, sizeof(u16)); | ||
717 | tmpcap = cpu_to_le16(tmpcap); | ||
718 | memcpy(&adhs->cap, &tmpcap, sizeof(u16)); | ||
719 | |||
720 | ret = 0; | ||
721 | done: | ||
722 | LEAVE(); | ||
723 | return ret; | ||
724 | } | ||
725 | |||
726 | int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv, | ||
727 | struct cmd_ds_command *cmd) | ||
728 | { | ||
729 | cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_stop); | ||
730 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, | ||
736 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
737 | { | ||
738 | wlan_adapter *adapter = priv->adapter; | ||
739 | struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj; | ||
740 | struct bss_descriptor *pbssdesc = pdata_buf; | ||
741 | int cmdappendsize = 0; | ||
742 | int ret = 0; | ||
743 | u8 *card_rates; | ||
744 | int card_rates_size; | ||
745 | u16 tmpcap; | ||
746 | int i; | ||
747 | |||
748 | ENTER(); | ||
749 | |||
750 | adapter->pattemptedbssdesc = pbssdesc; | ||
751 | |||
752 | cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join); | ||
753 | |||
754 | padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss; | ||
755 | |||
756 | padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod; | ||
757 | |||
758 | memcpy(&padhocjoin->bssdescriptor.BSSID, | ||
759 | &pbssdesc->macaddress, ETH_ALEN); | ||
760 | |||
761 | memcpy(&padhocjoin->bssdescriptor.SSID, | ||
762 | &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength); | ||
763 | |||
764 | memcpy(&padhocjoin->bssdescriptor.phyparamset, | ||
765 | &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset)); | ||
766 | |||
767 | memcpy(&padhocjoin->bssdescriptor.ssparamset, | ||
768 | &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset)); | ||
769 | |||
770 | memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo)); | ||
771 | tmpcap &= CAPINFO_MASK; | ||
772 | |||
773 | lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", | ||
774 | tmpcap, CAPINFO_MASK); | ||
775 | memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap, | ||
776 | sizeof(struct ieeetypes_capinfo)); | ||
777 | |||
778 | /* information on BSSID descriptor passed to FW */ | ||
779 | lbs_pr_debug(1, | ||
780 | "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n", | ||
781 | padhocjoin->bssdescriptor.BSSID[0], | ||
782 | padhocjoin->bssdescriptor.BSSID[1], | ||
783 | padhocjoin->bssdescriptor.BSSID[2], | ||
784 | padhocjoin->bssdescriptor.BSSID[3], | ||
785 | padhocjoin->bssdescriptor.BSSID[4], | ||
786 | padhocjoin->bssdescriptor.BSSID[5], | ||
787 | padhocjoin->bssdescriptor.SSID); | ||
788 | |||
789 | lbs_pr_debug(1, "ADHOC_J_CMD: Data Rate = %x\n", | ||
790 | (u32) padhocjoin->bssdescriptor.datarates); | ||
791 | |||
792 | /* failtimeout */ | ||
793 | padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); | ||
794 | |||
795 | /* probedelay */ | ||
796 | padhocjoin->probedelay = | ||
797 | cpu_to_le16(cmd_scan_probe_delay_time); | ||
798 | |||
799 | /* Copy Data rates from the rates recorded in scan response */ | ||
800 | memset(padhocjoin->bssdescriptor.datarates, 0, | ||
801 | sizeof(padhocjoin->bssdescriptor.datarates)); | ||
802 | memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates, | ||
803 | min(sizeof(padhocjoin->bssdescriptor.datarates), | ||
804 | sizeof(pbssdesc->datarates))); | ||
805 | |||
806 | card_rates = libertas_supported_rates; | ||
807 | card_rates_size = sizeof(libertas_supported_rates); | ||
808 | |||
809 | adapter->curbssparams.channel = pbssdesc->channel; | ||
810 | |||
811 | if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates, | ||
812 | sizeof(padhocjoin->bssdescriptor.datarates), | ||
813 | card_rates, card_rates_size)) { | ||
814 | lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n"); | ||
815 | ret = -1; | ||
816 | goto done; | ||
817 | } | ||
818 | |||
819 | /* Find the last non zero */ | ||
820 | for (i = 0; i < sizeof(padhocjoin->bssdescriptor.datarates) | ||
821 | && padhocjoin->bssdescriptor.datarates[i]; i++) ; | ||
822 | |||
823 | adapter->curbssparams.numofrates = i; | ||
824 | |||
825 | /* | ||
826 | * Copy the adhoc joining rates to Current BSS State structure | ||
827 | */ | ||
828 | memcpy(adapter->curbssparams.datarates, | ||
829 | padhocjoin->bssdescriptor.datarates, | ||
830 | adapter->curbssparams.numofrates); | ||
831 | |||
832 | padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow = | ||
833 | cpu_to_le16(pbssdesc->atimwindow); | ||
834 | |||
835 | if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) { | ||
836 | padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON; | ||
837 | } | ||
838 | |||
839 | if (adapter->psmode == wlan802_11powermodemax_psp) { | ||
840 | /* wake up first */ | ||
841 | enum WLAN_802_11_POWER_MODE Localpsmode; | ||
842 | |||
843 | Localpsmode = wlan802_11powermodecam; | ||
844 | ret = libertas_prepare_and_send_command(priv, | ||
845 | cmd_802_11_ps_mode, | ||
846 | cmd_act_set, | ||
847 | 0, 0, &Localpsmode); | ||
848 | |||
849 | if (ret) { | ||
850 | ret = -1; | ||
851 | goto done; | ||
852 | } | ||
853 | } | ||
854 | |||
855 | if (libertas_parse_dnld_countryinfo_11d(priv)) { | ||
856 | ret = -1; | ||
857 | goto done; | ||
858 | } | ||
859 | |||
860 | cmd->size = | ||
861 | cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) | ||
862 | + S_DS_GEN + cmdappendsize); | ||
863 | |||
864 | memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap, | ||
865 | sizeof(struct ieeetypes_capinfo)); | ||
866 | tmpcap = cpu_to_le16(tmpcap); | ||
867 | |||
868 | memcpy(&padhocjoin->bssdescriptor.cap, | ||
869 | &tmpcap, sizeof(struct ieeetypes_capinfo)); | ||
870 | |||
871 | done: | ||
872 | LEAVE(); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | int libertas_ret_80211_associate(wlan_private * priv, | ||
877 | struct cmd_ds_command *resp) | ||
878 | { | ||
879 | wlan_adapter *adapter = priv->adapter; | ||
880 | int ret = 0; | ||
881 | union iwreq_data wrqu; | ||
882 | struct ieeetypes_assocrsp *passocrsp; | ||
883 | struct bss_descriptor *pbssdesc; | ||
884 | |||
885 | ENTER(); | ||
886 | |||
887 | passocrsp = (struct ieeetypes_assocrsp *) & resp->params; | ||
888 | |||
889 | if (passocrsp->statuscode) { | ||
890 | |||
891 | libertas_mac_event_disconnected(priv); | ||
892 | |||
893 | lbs_pr_debug(1, | ||
894 | "ASSOC_RESP: Association failed, status code = %d\n", | ||
895 | passocrsp->statuscode); | ||
896 | |||
897 | ret = -1; | ||
898 | goto done; | ||
899 | } | ||
900 | |||
901 | lbs_dbg_hex("ASSOC_RESP:", (void *)&resp->params, | ||
902 | le16_to_cpu(resp->size) - S_DS_GEN); | ||
903 | |||
904 | /* Send a Media Connected event, according to the Spec */ | ||
905 | adapter->connect_status = libertas_connected; | ||
906 | |||
907 | /* Set the attempted BSSID Index to current */ | ||
908 | pbssdesc = adapter->pattemptedbssdesc; | ||
909 | |||
910 | lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid); | ||
911 | |||
912 | /* Set the new SSID to current SSID */ | ||
913 | memcpy(&adapter->curbssparams.ssid, | ||
914 | &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID)); | ||
915 | |||
916 | /* Set the new BSSID (AP's MAC address) to current BSSID */ | ||
917 | memcpy(adapter->curbssparams.bssid, | ||
918 | pbssdesc->macaddress, ETH_ALEN); | ||
919 | |||
920 | /* Make a copy of current BSSID descriptor */ | ||
921 | memcpy(&adapter->curbssparams.bssdescriptor, | ||
922 | pbssdesc, sizeof(struct bss_descriptor)); | ||
923 | |||
924 | lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n", | ||
925 | adapter->currentpacketfilter); | ||
926 | |||
927 | adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0; | ||
928 | adapter->NF[TYPE_RXPD][TYPE_AVG] = 0; | ||
929 | |||
930 | memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR)); | ||
931 | memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF)); | ||
932 | adapter->nextSNRNF = 0; | ||
933 | adapter->numSNRNF = 0; | ||
934 | |||
935 | netif_carrier_on(priv->wlan_dev.netdev); | ||
936 | netif_wake_queue(priv->wlan_dev.netdev); | ||
937 | |||
938 | lbs_pr_debug(1, "ASSOC_RESP: Associated \n"); | ||
939 | |||
940 | memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN); | ||
941 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
942 | wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); | ||
943 | |||
944 | done: | ||
945 | LEAVE(); | ||
946 | return ret; | ||
947 | } | ||
948 | |||
949 | int libertas_ret_80211_disassociate(wlan_private * priv, | ||
950 | struct cmd_ds_command *resp) | ||
951 | { | ||
952 | ENTER(); | ||
953 | |||
954 | libertas_mac_event_disconnected(priv); | ||
955 | |||
956 | LEAVE(); | ||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | int libertas_ret_80211_ad_hoc_start(wlan_private * priv, | ||
961 | struct cmd_ds_command *resp) | ||
962 | { | ||
963 | wlan_adapter *adapter = priv->adapter; | ||
964 | int ret = 0; | ||
965 | u16 command = le16_to_cpu(resp->command); | ||
966 | u16 result = le16_to_cpu(resp->result); | ||
967 | struct cmd_ds_802_11_ad_hoc_result *padhocresult; | ||
968 | union iwreq_data wrqu; | ||
969 | struct bss_descriptor *pbssdesc; | ||
970 | |||
971 | ENTER(); | ||
972 | |||
973 | padhocresult = &resp->params.result; | ||
974 | |||
975 | lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size)); | ||
976 | lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command); | ||
977 | lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result); | ||
978 | |||
979 | pbssdesc = adapter->pattemptedbssdesc; | ||
980 | |||
981 | /* | ||
982 | * Join result code 0 --> SUCCESS | ||
983 | */ | ||
984 | if (result) { | ||
985 | lbs_pr_debug(1, "ADHOC_RESP failed\n"); | ||
986 | if (adapter->connect_status == libertas_connected) { | ||
987 | libertas_mac_event_disconnected(priv); | ||
988 | } | ||
989 | |||
990 | memset(&adapter->curbssparams.bssdescriptor, | ||
991 | 0x00, sizeof(adapter->curbssparams.bssdescriptor)); | ||
992 | |||
993 | LEAVE(); | ||
994 | return -1; | ||
995 | } | ||
996 | |||
997 | /* | ||
998 | * Now the join cmd should be successful | ||
999 | * If BSSID has changed use SSID to compare instead of BSSID | ||
1000 | */ | ||
1001 | lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid); | ||
1002 | |||
1003 | /* Send a Media Connected event, according to the Spec */ | ||
1004 | adapter->connect_status = libertas_connected; | ||
1005 | |||
1006 | if (command == cmd_ret_802_11_ad_hoc_start) { | ||
1007 | /* Update the created network descriptor with the new BSSID */ | ||
1008 | memcpy(pbssdesc->macaddress, | ||
1009 | padhocresult->BSSID, ETH_ALEN); | ||
1010 | } else { | ||
1011 | |||
1012 | /* Make a copy of current BSSID descriptor, only needed for join since | ||
1013 | * the current descriptor is already being used for adhoc start | ||
1014 | */ | ||
1015 | memmove(&adapter->curbssparams.bssdescriptor, | ||
1016 | pbssdesc, sizeof(struct bss_descriptor)); | ||
1017 | } | ||
1018 | |||
1019 | /* Set the BSSID from the joined/started descriptor */ | ||
1020 | memcpy(&adapter->curbssparams.bssid, | ||
1021 | pbssdesc->macaddress, ETH_ALEN); | ||
1022 | |||
1023 | /* Set the new SSID to current SSID */ | ||
1024 | memcpy(&adapter->curbssparams.ssid, | ||
1025 | &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID)); | ||
1026 | |||
1027 | netif_carrier_on(priv->wlan_dev.netdev); | ||
1028 | netif_wake_queue(priv->wlan_dev.netdev); | ||
1029 | |||
1030 | memset(&wrqu, 0, sizeof(wrqu)); | ||
1031 | memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN); | ||
1032 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1033 | wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); | ||
1034 | |||
1035 | lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n"); | ||
1036 | lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel); | ||
1037 | lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1038 | padhocresult->BSSID[0], padhocresult->BSSID[1], | ||
1039 | padhocresult->BSSID[2], padhocresult->BSSID[3], | ||
1040 | padhocresult->BSSID[4], padhocresult->BSSID[5]); | ||
1041 | |||
1042 | LEAVE(); | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | int libertas_ret_80211_ad_hoc_stop(wlan_private * priv, | ||
1047 | struct cmd_ds_command *resp) | ||
1048 | { | ||
1049 | ENTER(); | ||
1050 | |||
1051 | libertas_mac_event_disconnected(priv); | ||
1052 | |||
1053 | LEAVE(); | ||
1054 | return 0; | ||
1055 | } | ||