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