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