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