727cc552c5eef4e93d65b226ade2bbd8836125e6
[safe/jmp/linux-2.6] / drivers / staging / rtl8192su / ieee80211 / ieee80211_wx.c
1 /******************************************************************************
2
3   Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5   Portions of this file are based on the WEP enablement code provided by the
6   Host AP project hostap-drivers v0.1.3
7   Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8   <jkmaline@cc.hut.fi>
9   Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of version 2 of the GNU General Public License as
13   published by the Free Software Foundation.
14
15   This program is distributed in the hope that it will be useful, but WITHOUT
16   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18   more details.
19
20   You should have received a copy of the GNU General Public License along with
21   this program; if not, write to the Free Software Foundation, Inc., 59
22   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23
24   The full GNU General Public License is included in this distribution in the
25   file called LICENSE.
26
27   Contact Information:
28   James P. Ketrenos <ipw2100-admin@linux.intel.com>
29   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/kmod.h>
34 #include <linux/slab.h>
35 #include <linux/module.h>
36
37 #include "ieee80211.h"
38
39 struct modes_unit {
40         char *mode_string;
41         int mode_size;
42 };
43 struct modes_unit ieee80211_modes[] = {
44         {"a",1},
45         {"b",1},
46         {"g",1},
47         {"?",1},
48         {"N-24G",5},
49         {"N-5G",4},
50 };
51
52 #define iwe_stream_add_event_rsl iwe_stream_add_event
53
54 #define MAX_CUSTOM_LEN 64
55 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
56                                            char *start, char *stop,
57                                            struct ieee80211_network *network,
58                                            struct iw_request_info *info)
59 {
60         char custom[MAX_CUSTOM_LEN];
61         char proto_name[IFNAMSIZ];
62         char *pname = proto_name;
63         char *p;
64         struct iw_event iwe;
65         int i, j;
66         u16 max_rate, rate;
67         static u8       EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
68
69         /* First entry *MUST* be the AP MAC address */
70         iwe.cmd = SIOCGIWAP;
71         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
72         memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
73         start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
74
75         /* Remaining entries will be displayed in the order we provide them */
76
77         /* Add the ESSID */
78         iwe.cmd = SIOCGIWESSID;
79         iwe.u.data.flags = 1;
80 //      if (network->flags & NETWORK_EMPTY_ESSID) {
81         if (network->ssid_len == 0) {
82                 iwe.u.data.length = sizeof("<hidden>");
83                 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
84         } else {
85                 iwe.u.data.length = min(network->ssid_len, (u8)32);
86                 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
87         }
88         /* Add the protocol name */
89         iwe.cmd = SIOCGIWNAME;
90         for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) {
91                 if(network->mode&(1<<i)) {
92                         sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
93                         pname +=ieee80211_modes[i].mode_size;
94                 }
95         }
96         *pname = '\0';
97         snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
98         start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
99         /* Add mode */
100         iwe.cmd = SIOCGIWMODE;
101         if (network->capability &
102             (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
103                 if (network->capability & WLAN_CAPABILITY_BSS)
104                         iwe.u.mode = IW_MODE_MASTER;
105                 else
106                         iwe.u.mode = IW_MODE_ADHOC;
107                 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
108         }
109
110         /* Add frequency/channel */
111         iwe.cmd = SIOCGIWFREQ;
112 /*      iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
113         iwe.u.freq.e = 3; */
114         iwe.u.freq.m = network->channel;
115         iwe.u.freq.e = 0;
116         iwe.u.freq.i = 0;
117         start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
118         /* Add encryption capability */
119         iwe.cmd = SIOCGIWENCODE;
120         if (network->capability & WLAN_CAPABILITY_PRIVACY)
121                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
122         else
123                 iwe.u.data.flags = IW_ENCODE_DISABLED;
124         iwe.u.data.length = 0;
125         start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
126         /* Add basic and extended rates */
127         max_rate = 0;
128         p = custom;
129         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
130         for (i = 0, j = 0; i < network->rates_len; ) {
131                 if (j < network->rates_ex_len &&
132                     ((network->rates_ex[j] & 0x7F) <
133                      (network->rates[i] & 0x7F)))
134                         rate = network->rates_ex[j++] & 0x7F;
135                 else
136                         rate = network->rates[i++] & 0x7F;
137                 if (rate > max_rate)
138                         max_rate = rate;
139                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
140                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
141         }
142         for (; j < network->rates_ex_len; j++) {
143                 rate = network->rates_ex[j] & 0x7F;
144                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
145                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
146                 if (rate > max_rate)
147                         max_rate = rate;
148         }
149
150         if (network->mode >= IEEE_N_24G)//add N rate here;
151         {
152                 PHT_CAPABILITY_ELE ht_cap = NULL;
153                 bool is40M = false, isShortGI = false;
154                 u8 max_mcs = 0;
155                 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
156                         ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
157                 else
158                         ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
159                 is40M = (ht_cap->ChlWidth)?1:0;
160                 isShortGI = (ht_cap->ChlWidth)?
161                                                 ((ht_cap->ShortGI40Mhz)?1:0):
162                                                 ((ht_cap->ShortGI20Mhz)?1:0);
163
164                 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
165                 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
166                 if (rate > max_rate)
167                         max_rate = rate;
168         }
169
170         iwe.cmd = SIOCGIWRATE;
171         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
172         iwe.u.bitrate.value = max_rate * 500000;
173         start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
174                                      IW_EV_PARAM_LEN);
175
176         iwe.cmd = IWEVCUSTOM;
177         iwe.u.data.length = p - custom;
178         if (iwe.u.data.length)
179         start = iwe_stream_add_point(info, start, stop, &iwe, custom);
180
181         /* Add quality statistics */
182         /* TODO: Fix these values... */
183         iwe.cmd = IWEVQUAL;
184         iwe.u.qual.qual = network->stats.signal;
185         iwe.u.qual.level = network->stats.rssi;
186         iwe.u.qual.noise = network->stats.noise;
187         iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
188         if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
189                 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
190         if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
191                 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
192         if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
193                 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
194         iwe.u.qual.updated = 7;
195         start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
196         iwe.cmd = IWEVCUSTOM;
197         p = custom;
198
199         iwe.u.data.length = p - custom;
200         if (iwe.u.data.length)
201             start = iwe_stream_add_point(info, start, stop, &iwe, custom);
202
203         memset(&iwe, 0, sizeof(iwe));
204         if (network->wpa_ie_len)
205         {
206                 char buf[MAX_WPA_IE_LEN];
207                 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
208                 iwe.cmd = IWEVGENIE;
209                 iwe.u.data.length = network->wpa_ie_len;
210                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
211         }
212         memset(&iwe, 0, sizeof(iwe));
213         if (network->rsn_ie_len)
214         {
215                 char buf[MAX_WPA_IE_LEN];
216                 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
217                 iwe.cmd = IWEVGENIE;
218                 iwe.u.data.length = network->rsn_ie_len;
219                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
220         }
221
222         /* Add EXTRA: Age to display seconds since last beacon/probe response
223          * for given network. */
224         iwe.cmd = IWEVCUSTOM;
225         p = custom;
226         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
227                       " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
228         iwe.u.data.length = p - custom;
229         if (iwe.u.data.length)
230             start = iwe_stream_add_point(info, start, stop, &iwe, custom);
231
232         return start;
233 }
234
235 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
236                           struct iw_request_info *info,
237                           union iwreq_data *wrqu, char *extra)
238 {
239         struct ieee80211_network *network;
240         unsigned long flags;
241
242         char *ev = extra;
243 //      char *stop = ev + IW_SCAN_MAX_DATA;
244         char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
245         //char *stop = ev + IW_SCAN_MAX_DATA;
246         int i = 0;
247         int err = 0;
248         IEEE80211_DEBUG_WX("Getting scan\n");
249         down(&ieee->wx_sem);
250         spin_lock_irqsave(&ieee->lock, flags);
251
252         list_for_each_entry(network, &ieee->network_list, list) {
253                 i++;
254                 if((stop-ev)<200)
255                 {
256                         err = -E2BIG;
257                         break;
258                                                                                                 }
259                 if (ieee->scan_age == 0 ||
260                     time_after(network->last_scanned + ieee->scan_age, jiffies))
261                         ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
262                 else
263                         IEEE80211_DEBUG_SCAN(
264                                 "Not showing network '%s ("
265                                 "%pM)' due to age (%lums).\n",
266                                 escape_essid(network->ssid,
267                                              network->ssid_len),
268                                 network->bssid,
269                                 (jiffies - network->last_scanned) / (HZ / 100));
270         }
271
272         spin_unlock_irqrestore(&ieee->lock, flags);
273         up(&ieee->wx_sem);
274         wrqu->data.length = ev -  extra;
275         wrqu->data.flags = 0;
276
277         IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
278
279         return err;
280 }
281
282 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
283                             struct iw_request_info *info,
284                             union iwreq_data *wrqu, char *keybuf)
285 {
286         struct iw_point *erq = &(wrqu->encoding);
287         struct net_device *dev = ieee->dev;
288         struct ieee80211_security sec = {
289                 .flags = 0
290         };
291         int i, key, key_provided, len;
292         struct ieee80211_crypt_data **crypt;
293
294         IEEE80211_DEBUG_WX("SET_ENCODE\n");
295
296         key = erq->flags & IW_ENCODE_INDEX;
297         if (key) {
298                 if (key > WEP_KEYS)
299                         return -EINVAL;
300                 key--;
301                 key_provided = 1;
302         } else {
303                 key_provided = 0;
304                 key = ieee->tx_keyidx;
305         }
306
307         IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
308                            "provided" : "default");
309         crypt = &ieee->crypt[key];
310
311         if (erq->flags & IW_ENCODE_DISABLED) {
312                 if (key_provided && *crypt) {
313                         IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
314                                            key);
315                         ieee80211_crypt_delayed_deinit(ieee, crypt);
316                 } else
317                         IEEE80211_DEBUG_WX("Disabling encryption.\n");
318
319                 /* Check all the keys to see if any are still configured,
320                  * and if no key index was provided, de-init them all */
321                 for (i = 0; i < WEP_KEYS; i++) {
322                         if (ieee->crypt[i] != NULL) {
323                                 if (key_provided)
324                                         break;
325                                 ieee80211_crypt_delayed_deinit(
326                                         ieee, &ieee->crypt[i]);
327                         }
328                 }
329
330                 if (i == WEP_KEYS) {
331                         sec.enabled = 0;
332                         sec.level = SEC_LEVEL_0;
333                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
334                 }
335
336                 goto done;
337         }
338
339
340
341         sec.enabled = 1;
342         sec.flags |= SEC_ENABLED;
343
344         if (*crypt != NULL && (*crypt)->ops != NULL &&
345             strcmp((*crypt)->ops->name, "WEP") != 0) {
346                 /* changing to use WEP; deinit previously used algorithm
347                  * on this key */
348                 ieee80211_crypt_delayed_deinit(ieee, crypt);
349         }
350
351         if (*crypt == NULL) {
352                 struct ieee80211_crypt_data *new_crypt;
353
354                 /* take WEP into use */
355                 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
356                                     GFP_KERNEL);
357                 if (new_crypt == NULL)
358                         return -ENOMEM;
359                 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
360                 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
361                 if (!new_crypt->ops)
362                         new_crypt->ops = ieee80211_get_crypto_ops("WEP");
363                 if (new_crypt->ops)
364                         new_crypt->priv = new_crypt->ops->init(key);
365
366                 if (!new_crypt->ops || !new_crypt->priv) {
367                         kfree(new_crypt);
368                         new_crypt = NULL;
369
370                         printk(KERN_WARNING "%s: could not initialize WEP: "
371                                "load module ieee80211_crypt_wep\n",
372                                dev->name);
373                         return -EOPNOTSUPP;
374                 }
375                 *crypt = new_crypt;
376         }
377
378         /* If a new key was provided, set it up */
379         if (erq->length > 0) {
380                 len = erq->length <= 5 ? 5 : 13;
381                 memcpy(sec.keys[key], keybuf, erq->length);
382                 if (len > erq->length)
383                         memset(sec.keys[key] + erq->length, 0,
384                                len - erq->length);
385                 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
386                                    key, escape_essid(sec.keys[key], len),
387                                    erq->length, len);
388                 sec.key_sizes[key] = len;
389                 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
390                                        (*crypt)->priv);
391                 sec.flags |= (1 << key);
392                 /* This ensures a key will be activated if no key is
393                  * explicitely set */
394                 if (key == sec.active_key)
395                         sec.flags |= SEC_ACTIVE_KEY;
396                 ieee->tx_keyidx = key;
397
398         } else {
399                 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
400                                              NULL, (*crypt)->priv);
401                 if (len == 0) {
402                         /* Set a default key of all 0 */
403                         printk("Setting key %d to all zero.\n",
404                                            key);
405
406                         IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
407                                            key);
408                         memset(sec.keys[key], 0, 13);
409                         (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
410                                                (*crypt)->priv);
411                         sec.key_sizes[key] = 13;
412                         sec.flags |= (1 << key);
413                 }
414
415                 /* No key data - just set the default TX key index */
416                 if (key_provided) {
417                         IEEE80211_DEBUG_WX(
418                                 "Setting key %d to default Tx key.\n", key);
419                         ieee->tx_keyidx = key;
420                         sec.active_key = key;
421                         sec.flags |= SEC_ACTIVE_KEY;
422                 }
423         }
424
425  done:
426         ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
427         ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
428         sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
429         sec.flags |= SEC_AUTH_MODE;
430         IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
431                            "OPEN" : "SHARED KEY");
432
433         /* For now we just support WEP, so only set that security level...
434          * TODO: When WPA is added this is one place that needs to change */
435         sec.flags |= SEC_LEVEL;
436         sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
437
438         if (ieee->set_security)
439                 ieee->set_security(dev, &sec);
440
441         /* Do not reset port if card is in Managed mode since resetting will
442          * generate new IEEE 802.11 authentication which may end up in looping
443          * with IEEE 802.1X.  If your hardware requires a reset after WEP
444          * configuration (for example... Prism2), implement the reset_port in
445          * the callbacks structures used to initialize the 802.11 stack. */
446         if (ieee->reset_on_keychange &&
447             ieee->iw_mode != IW_MODE_INFRA &&
448             ieee->reset_port && ieee->reset_port(dev)) {
449                 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
450                 return -EINVAL;
451         }
452         return 0;
453 }
454
455 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
456                             struct iw_request_info *info,
457                             union iwreq_data *wrqu, char *keybuf)
458 {
459         struct iw_point *erq = &(wrqu->encoding);
460         int len, key;
461         struct ieee80211_crypt_data *crypt;
462
463         IEEE80211_DEBUG_WX("GET_ENCODE\n");
464
465         if(ieee->iw_mode == IW_MODE_MONITOR)
466                 return -1;
467
468         key = erq->flags & IW_ENCODE_INDEX;
469         if (key) {
470                 if (key > WEP_KEYS)
471                         return -EINVAL;
472                 key--;
473         } else
474                 key = ieee->tx_keyidx;
475
476         crypt = ieee->crypt[key];
477         erq->flags = key + 1;
478
479         if (crypt == NULL || crypt->ops == NULL) {
480                 erq->length = 0;
481                 erq->flags |= IW_ENCODE_DISABLED;
482                 return 0;
483         }
484
485         len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
486         erq->length = (len >= 0 ? len : 0);
487
488         erq->flags |= IW_ENCODE_ENABLED;
489
490         if (ieee->open_wep)
491                 erq->flags |= IW_ENCODE_OPEN;
492         else
493                 erq->flags |= IW_ENCODE_RESTRICTED;
494
495         return 0;
496 }
497
498 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
499                                struct iw_request_info *info,
500                                union iwreq_data *wrqu, char *extra)
501 {
502         int ret = 0;
503         struct net_device *dev = ieee->dev;
504         struct iw_point *encoding = &wrqu->encoding;
505         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
506         int i, idx;
507         int group_key = 0;
508         const char *alg;
509         struct ieee80211_crypto_ops *ops;
510         struct ieee80211_crypt_data **crypt;
511
512         struct ieee80211_security sec = {
513                 .flags = 0,
514         };
515         //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
516         idx = encoding->flags & IW_ENCODE_INDEX;
517         if (idx) {
518                 if (idx < 1 || idx > WEP_KEYS)
519                         return -EINVAL;
520                 idx--;
521         } else
522                 idx = ieee->tx_keyidx;
523
524         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
525
526                 crypt = &ieee->crypt[idx];
527
528                 group_key = 1;
529         } else {
530                 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
531                 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
532                 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
533                         return -EINVAL;
534                 if (ieee->iw_mode == IW_MODE_INFRA)
535
536                         crypt = &ieee->crypt[idx];
537
538                 else
539                         return -EINVAL;
540         }
541
542         sec.flags |= SEC_ENABLED;
543
544         if ((encoding->flags & IW_ENCODE_DISABLED) ||
545             ext->alg == IW_ENCODE_ALG_NONE) {
546                 if (*crypt)
547                         ieee80211_crypt_delayed_deinit(ieee, crypt);
548
549                 for (i = 0; i < WEP_KEYS; i++)
550
551                         if (ieee->crypt[i] != NULL)
552
553                                 break;
554
555                 if (i == WEP_KEYS) {
556                         sec.enabled = 0;
557                       //  sec.encrypt = 0;
558                         sec.level = SEC_LEVEL_0;
559                         sec.flags |= SEC_LEVEL;
560                 }
561                 //printk("disabled: flag:%x\n", encoding->flags);
562                 goto done;
563         }
564
565         sec.enabled = 1;
566     //    sec.encrypt = 1;
567
568         switch (ext->alg) {
569         case IW_ENCODE_ALG_WEP:
570                 alg = "WEP";
571                 break;
572         case IW_ENCODE_ALG_TKIP:
573                 alg = "TKIP";
574                 break;
575         case IW_ENCODE_ALG_CCMP:
576                 alg = "CCMP";
577                 break;
578         default:
579                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
580                                    dev->name, ext->alg);
581                 ret = -EINVAL;
582                 goto done;
583         }
584         printk("alg name:%s\n",alg);
585
586          ops = ieee80211_get_crypto_ops(alg);
587         if (ops == NULL)
588                 ops = ieee80211_get_crypto_ops(alg);
589         if (ops == NULL) {
590                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
591                                    dev->name, ext->alg);
592                 printk("========>unknown crypto alg %d\n", ext->alg);
593                 ret = -EINVAL;
594                 goto done;
595         }
596
597         if (*crypt == NULL || (*crypt)->ops != ops) {
598                 struct ieee80211_crypt_data *new_crypt;
599
600                 ieee80211_crypt_delayed_deinit(ieee, crypt);
601
602                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
603                 if (new_crypt == NULL) {
604                         ret = -ENOMEM;
605                         goto done;
606                 }
607                 new_crypt->ops = ops;
608                 if (new_crypt->ops)
609                         new_crypt->priv = new_crypt->ops->init(idx);
610                 if (new_crypt->priv == NULL) {
611                         kfree(new_crypt);
612                         ret = -EINVAL;
613                         goto done;
614                 }
615                 *crypt = new_crypt;
616
617         }
618
619         if (ext->key_len > 0 && (*crypt)->ops->set_key &&
620             (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
621                                    (*crypt)->priv) < 0) {
622                 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
623                 printk("key setting failed\n");
624                 ret = -EINVAL;
625                 goto done;
626         }
627 #if 1
628  //skip_host_crypt:
629         //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
630         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
631                 ieee->tx_keyidx = idx;
632                 sec.active_key = idx;
633                 sec.flags |= SEC_ACTIVE_KEY;
634         }
635
636         if (ext->alg != IW_ENCODE_ALG_NONE) {
637                 //memcpy(sec.keys[idx], ext->key, ext->key_len);
638                 sec.key_sizes[idx] = ext->key_len;
639                 sec.flags |= (1 << idx);
640                 if (ext->alg == IW_ENCODE_ALG_WEP) {
641                         sec.flags |= SEC_LEVEL;
642                         sec.level = SEC_LEVEL_1;
643                 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
644                         sec.flags |= SEC_LEVEL;
645                         sec.level = SEC_LEVEL_2;
646                 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
647                         sec.flags |= SEC_LEVEL;
648                         sec.level = SEC_LEVEL_3;
649                 }
650                 /* Don't set sec level for group keys. */
651                 if (group_key)
652                         sec.flags &= ~SEC_LEVEL;
653         }
654 #endif
655 done:
656         if (ieee->set_security)
657                 ieee->set_security(ieee->dev, &sec);
658
659          if (ieee->reset_on_keychange &&
660             ieee->iw_mode != IW_MODE_INFRA &&
661             ieee->reset_port && ieee->reset_port(dev)) {
662                 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
663                 return -EINVAL;
664         }
665
666         return ret;
667 }
668
669 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
670                                struct iw_request_info *info,
671                                union iwreq_data *wrqu, char *extra)
672 {
673         struct iw_mlme *mlme = (struct iw_mlme *) extra;
674
675         switch (mlme->cmd) {
676         case IW_MLME_DEAUTH:
677         case IW_MLME_DISASSOC:
678                 ieee80211_disassociate(ieee);
679                 break;
680          default:
681                 return -EOPNOTSUPP;
682         }
683
684         return 0;
685 }
686
687 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
688                                struct iw_request_info *info,
689                                struct iw_param *data, char *extra)
690 {
691         switch (data->flags & IW_AUTH_INDEX) {
692         case IW_AUTH_WPA_VERSION:
693              /*need to support wpa2 here*/
694                 //printk("wpa version:%x\n", data->value);
695                 break;
696         case IW_AUTH_CIPHER_PAIRWISE:
697         case IW_AUTH_CIPHER_GROUP:
698         case IW_AUTH_KEY_MGMT:
699                 /*
700  *                  * Host AP driver does not use these parameters and allows
701  *                                   * wpa_supplicant to control them internally.
702  *                                                    */
703                 break;
704         case IW_AUTH_TKIP_COUNTERMEASURES:
705                 ieee->tkip_countermeasures = data->value;
706                 break;
707         case IW_AUTH_DROP_UNENCRYPTED:
708                 ieee->drop_unencrypted = data->value;
709                 break;
710
711         case IW_AUTH_80211_AUTH_ALG:
712                 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
713         //      ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
714                 if(data->value & IW_AUTH_ALG_SHARED_KEY){
715                         ieee->open_wep = 0;
716                         ieee->auth_mode = 1;
717                 }
718                 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
719                         ieee->open_wep = 1;
720                         ieee->auth_mode = 0;
721                 }
722                 else if(data->value & IW_AUTH_ALG_LEAP){
723                         ieee->open_wep = 1;
724                         ieee->auth_mode = 2;
725                         //printk("hahahaa:LEAP\n");
726                 }
727                 else
728                         return -EINVAL;
729                 //printk("open_wep:%d\n", ieee->open_wep);
730                 break;
731
732 #if 1
733         case IW_AUTH_WPA_ENABLED:
734                 ieee->wpa_enabled = (data->value)?1:0;
735                 //printk("enable wpa:%d\n", ieee->wpa_enabled);
736                 break;
737
738 #endif
739         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
740                 ieee->ieee802_1x = data->value;
741                 break;
742         case IW_AUTH_PRIVACY_INVOKED:
743                 ieee->privacy_invoked = data->value;
744                 break;
745         default:
746                 return -EOPNOTSUPP;
747         }
748
749         return 0;
750 }
751
752 #if 1
753 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
754 {
755         u8 *buf;
756
757         if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
758         {
759         //      printk("return error out, len:%d\n", len);
760         return -EINVAL;
761         }
762
763
764         if (len)
765         {
766                 if (len != ie[1]+2)
767                 {
768                         printk("len: %Zd, ie:%d\n", len, ie[1]);
769                         return -EINVAL;
770                 }
771                 buf = kmalloc(len, GFP_KERNEL);
772                 if (buf == NULL)
773                         return -ENOMEM;
774                 memcpy(buf, ie, len);
775                 kfree(ieee->wpa_ie);
776                 ieee->wpa_ie = buf;
777                 ieee->wpa_ie_len = len;
778         }
779         else{
780                 if (ieee->wpa_ie)
781                 kfree(ieee->wpa_ie);
782                 ieee->wpa_ie = NULL;
783                 ieee->wpa_ie_len = 0;
784         }
785
786         return 0;
787
788 }
789 #endif