Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
[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                         request_module("ieee80211_crypt_wep");
336                         new_crypt->ops = ieee80211_get_crypto_ops("WEP");
337                 }
338
339                 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
340                         new_crypt->priv = new_crypt->ops->init(key);
341
342                 if (!new_crypt->ops || !new_crypt->priv) {
343                         kfree(new_crypt);
344                         new_crypt = NULL;
345
346                         printk(KERN_WARNING "%s: could not initialize WEP: "
347                                "load module ieee80211_crypt_wep\n",
348                                dev->name);
349                         return -EOPNOTSUPP;
350                 }
351                 *crypt = new_crypt;
352         }
353
354         /* If a new key was provided, set it up */
355         if (erq->length > 0) {
356                 len = erq->length <= 5 ? 5 : 13;
357                 memcpy(sec.keys[key], keybuf, erq->length);
358                 if (len > erq->length)
359                         memset(sec.keys[key] + erq->length, 0,
360                                len - erq->length);
361                 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
362                                    key, escape_essid(sec.keys[key], len),
363                                    erq->length, len);
364                 sec.key_sizes[key] = len;
365                 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
366                                        (*crypt)->priv);
367                 sec.flags |= (1 << key);
368                 /* This ensures a key will be activated if no key is
369                  * explicitely set */
370                 if (key == sec.active_key)
371                         sec.flags |= SEC_ACTIVE_KEY;
372                 ieee->tx_keyidx = key;//by wb 080312
373         } else {
374                 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
375                                              NULL, (*crypt)->priv);
376                 if (len == 0) {
377                         /* Set a default key of all 0 */
378                         IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
379                                            key);
380                         memset(sec.keys[key], 0, 13);
381                         (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
382                                                (*crypt)->priv);
383                         sec.key_sizes[key] = 13;
384                         sec.flags |= (1 << key);
385                 }
386
387                 /* No key data - just set the default TX key index */
388                 if (key_provided) {
389                         IEEE80211_DEBUG_WX(
390                                 "Setting key %d to default Tx key.\n", key);
391                         ieee->tx_keyidx = key;
392                         sec.active_key = key;
393                         sec.flags |= SEC_ACTIVE_KEY;
394                 }
395         }
396
397  done:
398         ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
399         sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
400         sec.flags |= SEC_AUTH_MODE;
401         IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
402                            "OPEN" : "SHARED KEY");
403
404         /* For now we just support WEP, so only set that security level...
405          * TODO: When WPA is added this is one place that needs to change */
406         sec.flags |= SEC_LEVEL;
407         sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
408
409         if (ieee->set_security)
410                 ieee->set_security(dev, &sec);
411
412         /* Do not reset port if card is in Managed mode since resetting will
413          * generate new IEEE 802.11 authentication which may end up in looping
414          * with IEEE 802.1X.  If your hardware requires a reset after WEP
415          * configuration (for example... Prism2), implement the reset_port in
416          * the callbacks structures used to initialize the 802.11 stack. */
417         if (ieee->reset_on_keychange &&
418             ieee->iw_mode != IW_MODE_INFRA &&
419             ieee->reset_port && ieee->reset_port(dev)) {
420                 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
421                 return -EINVAL;
422         }
423         return 0;
424 }
425
426 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
427                             struct iw_request_info *info,
428                             union iwreq_data *wrqu, char *keybuf)
429 {
430         struct iw_point *erq = &(wrqu->encoding);
431         int len, key;
432         struct ieee80211_crypt_data *crypt;
433
434         IEEE80211_DEBUG_WX("GET_ENCODE\n");
435
436         if(ieee->iw_mode == IW_MODE_MONITOR)
437                 return -1;
438
439         key = erq->flags & IW_ENCODE_INDEX;
440         if (key) {
441                 if (key > WEP_KEYS)
442                         return -EINVAL;
443                 key--;
444         } else
445                 key = ieee->tx_keyidx;
446
447         crypt = ieee->crypt[key];
448         erq->flags = key + 1;
449
450         if (crypt == NULL || crypt->ops == NULL) {
451                 erq->length = 0;
452                 erq->flags |= IW_ENCODE_DISABLED;
453                 return 0;
454         }
455
456         if (strcmp(crypt->ops->name, "WEP") != 0) {
457                 /* only WEP is supported with wireless extensions, so just
458                  * report that encryption is used */
459                 erq->length = 0;
460                 erq->flags |= IW_ENCODE_ENABLED;
461                 return 0;
462         }
463
464         len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
465         erq->length = (len >= 0 ? len : 0);
466
467         erq->flags |= IW_ENCODE_ENABLED;
468
469         if (ieee->open_wep)
470                 erq->flags |= IW_ENCODE_OPEN;
471         else
472                 erq->flags |= IW_ENCODE_RESTRICTED;
473
474         return 0;
475 }
476
477 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
478                                struct iw_request_info *info,
479                                union iwreq_data *wrqu, char *extra)
480 {
481         struct net_device *dev = ieee->dev;
482         struct iw_point *encoding = &wrqu->encoding;
483         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
484         int i, idx, ret = 0;
485         int group_key = 0;
486         const char *alg, *module;
487         struct ieee80211_crypto_ops *ops;
488         struct ieee80211_crypt_data **crypt;
489
490         struct ieee80211_security sec = {
491                 .flags = 0,
492         };
493         //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
494         idx = encoding->flags & IW_ENCODE_INDEX;
495         if (idx) {
496                 if (idx < 1 || idx > WEP_KEYS)
497                         return -EINVAL;
498                 idx--;
499         } else
500                 idx = ieee->tx_keyidx;
501
502         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
503                 crypt = &ieee->crypt[idx];
504                 group_key = 1;
505         } else {
506                 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
507                 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
508                 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
509                         return -EINVAL;
510                 if (ieee->iw_mode == IW_MODE_INFRA)
511                         crypt = &ieee->crypt[idx];
512                 else
513                         return -EINVAL;
514         }
515
516         sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
517         if ((encoding->flags & IW_ENCODE_DISABLED) ||
518             ext->alg == IW_ENCODE_ALG_NONE) {
519                 if (*crypt)
520                         ieee80211_crypt_delayed_deinit(ieee, crypt);
521
522                 for (i = 0; i < WEP_KEYS; i++)
523                         if (ieee->crypt[i] != NULL)
524                                 break;
525
526                 if (i == WEP_KEYS) {
527                         sec.enabled = 0;
528                       //  sec.encrypt = 0;
529                         sec.level = SEC_LEVEL_0;
530                         sec.flags |= SEC_LEVEL;
531                 }
532                 //printk("disabled: flag:%x\n", encoding->flags);
533                 goto done;
534         }
535
536         sec.enabled = 1;
537     //    sec.encrypt = 1;
538
539         switch (ext->alg) {
540         case IW_ENCODE_ALG_WEP:
541                 alg = "WEP";
542                 module = "ieee80211_crypt_wep";
543                 break;
544         case IW_ENCODE_ALG_TKIP:
545                 alg = "TKIP";
546                 module = "ieee80211_crypt_tkip";
547                 break;
548         case IW_ENCODE_ALG_CCMP:
549                 alg = "CCMP";
550                 module = "ieee80211_crypt_ccmp";
551                 break;
552         default:
553                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
554                                    dev->name, ext->alg);
555                 ret = -EINVAL;
556                 goto done;
557         }
558 //      printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
559
560          ops = ieee80211_get_crypto_ops(alg);
561         if (ops == NULL) {
562                 request_module(module);
563                 ops = ieee80211_get_crypto_ops(alg);
564         }
565         if (ops == NULL) {
566                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
567                                    dev->name, ext->alg);
568                 printk("========>unknown crypto alg %d\n", ext->alg);
569                 ret = -EINVAL;
570                 goto done;
571         }
572
573         if (*crypt == NULL || (*crypt)->ops != ops) {
574                 struct ieee80211_crypt_data *new_crypt;
575
576                 ieee80211_crypt_delayed_deinit(ieee, crypt);
577
578                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
579                 if (new_crypt == NULL) {
580                         ret = -ENOMEM;
581                         goto done;
582                 }
583                 new_crypt->ops = ops;
584                 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
585                         new_crypt->priv = new_crypt->ops->init(idx);
586                 if (new_crypt->priv == NULL) {
587                         kfree(new_crypt);
588                         ret = -EINVAL;
589                         goto done;
590                 }
591                 *crypt = new_crypt;
592
593         }
594
595         if (ext->key_len > 0 && (*crypt)->ops->set_key &&
596             (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
597                                    (*crypt)->priv) < 0) {
598                 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
599                 printk("key setting failed\n");
600                 ret = -EINVAL;
601                 goto done;
602         }
603 #if 1
604  //skip_host_crypt:
605         //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
606         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
607                 ieee->tx_keyidx = idx;
608                 sec.active_key = idx;
609                 sec.flags |= SEC_ACTIVE_KEY;
610         }
611
612         if (ext->alg != IW_ENCODE_ALG_NONE) {
613                 memcpy(sec.keys[idx], ext->key, ext->key_len);
614                 sec.key_sizes[idx] = ext->key_len;
615                 sec.flags |= (1 << idx);
616                 if (ext->alg == IW_ENCODE_ALG_WEP) {
617                       //  sec.encode_alg[idx] = SEC_ALG_WEP;
618                         sec.flags |= SEC_LEVEL;
619                         sec.level = SEC_LEVEL_1;
620                 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
621                       //  sec.encode_alg[idx] = SEC_ALG_TKIP;
622                         sec.flags |= SEC_LEVEL;
623                         sec.level = SEC_LEVEL_2;
624                 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
625                        // sec.encode_alg[idx] = SEC_ALG_CCMP;
626                         sec.flags |= SEC_LEVEL;
627                         sec.level = SEC_LEVEL_3;
628                 }
629                 /* Don't set sec level for group keys. */
630                 if (group_key)
631                         sec.flags &= ~SEC_LEVEL;
632         }
633 #endif
634 done:
635         if (ieee->set_security)
636                 ieee->set_security(ieee->dev, &sec);
637
638          if (ieee->reset_on_keychange &&
639             ieee->iw_mode != IW_MODE_INFRA &&
640             ieee->reset_port && ieee->reset_port(dev)) {
641                 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
642                 return -EINVAL;
643         }
644
645         return ret;
646 }
647 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
648                                struct iw_request_info *info,
649                                union iwreq_data *wrqu, char *extra)
650 {
651         struct iw_mlme *mlme = (struct iw_mlme *) extra;
652 //      printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
653 #if 1
654         switch (mlme->cmd) {
655         case IW_MLME_DEAUTH:
656         case IW_MLME_DISASSOC:
657         //      printk("disassoc now\n");
658                 ieee80211_disassociate(ieee);
659                 break;
660          default:
661                 return -EOPNOTSUPP;
662         }
663 #endif
664         return 0;
665 }
666
667 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
668                                struct iw_request_info *info,
669                                struct iw_param *data, char *extra)
670 {
671 /*
672          struct ieee80211_security sec = {
673                 .flags = SEC_AUTH_MODE,
674         }
675 */
676         //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
677         switch (data->flags & IW_AUTH_INDEX) {
678         case IW_AUTH_WPA_VERSION:
679              /*need to support wpa2 here*/
680                 //printk("wpa version:%x\n", data->value);
681                 break;
682         case IW_AUTH_CIPHER_PAIRWISE:
683         case IW_AUTH_CIPHER_GROUP:
684         case IW_AUTH_KEY_MGMT:
685                 /*
686  *                  * Host AP driver does not use these parameters and allows
687  *                                   * wpa_supplicant to control them internally.
688  *                                                    */
689                 break;
690         case IW_AUTH_TKIP_COUNTERMEASURES:
691                 ieee->tkip_countermeasures = data->value;
692                 break;
693         case IW_AUTH_DROP_UNENCRYPTED:
694                 ieee->drop_unencrypted = data->value;
695                 break;
696
697         case IW_AUTH_80211_AUTH_ALG:
698                 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
699                 //printk("open_wep:%d\n", ieee->open_wep);
700                 break;
701
702 #if 1
703         case IW_AUTH_WPA_ENABLED:
704                 ieee->wpa_enabled = (data->value)?1:0;
705                 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
706                 break;
707
708 #endif
709         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
710                 ieee->ieee802_1x = data->value;
711                 break;
712         case IW_AUTH_PRIVACY_INVOKED:
713                 ieee->privacy_invoked = data->value;
714                 break;
715         default:
716                 return -EOPNOTSUPP;
717         }
718         return 0;
719 }
720
721 #if 1
722 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
723 {
724         u8 *buf = NULL;
725
726         if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
727         {
728                 printk("return error out, len:%zu\n", len);
729         return -EINVAL;
730         }
731
732         if (len)
733         {
734                 if (len != ie[1]+2){
735                         printk("len:%zu, ie:%d\n", len, ie[1]);
736                         return -EINVAL;
737                 }
738                 buf = kmalloc(len, GFP_KERNEL);
739                 if (buf == NULL)
740                         return -ENOMEM;
741                 memcpy(buf, ie, len);
742                 kfree(ieee->wpa_ie);
743                 ieee->wpa_ie = buf;
744                 ieee->wpa_ie_len = len;
745         }
746         else{
747                 if (ieee->wpa_ie)
748                 kfree(ieee->wpa_ie);
749                 ieee->wpa_ie = NULL;
750                 ieee->wpa_ie_len = 0;
751         }
752 //      printk("<=====out %s()\n", __func__);
753
754         return 0;
755
756 }
757 #endif