]> Pileus Git - ~andy/linux/blob - drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / 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/kmod.h>
34 #include <linux/slab.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                 list_for_each_entry(network, &ieee->network_list, list) {
222                         i++;
223
224                         if ((stop-ev) < 200) {
225                                 err = -E2BIG;
226                                 break;
227                         }
228                         if (ieee->scan_age == 0 ||
229                             time_after(network->last_scanned + ieee->scan_age, jiffies)) {
230                                 ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
231                         } else
232                                 IEEE80211_DEBUG_SCAN(
233                                         "Not showing network '%s ("
234                                         "%pM)' due to age (%lums).\n",
235                                         escape_essid(network->ssid,
236                                                      network->ssid_len),
237                                         network->bssid,
238                                         (jiffies - network->last_scanned) / (HZ / 100));
239                 }
240         }
241         spin_unlock_irqrestore(&ieee->lock, flags);
242         up(&ieee->wx_sem);
243         wrqu->data.length = ev -  extra;
244         wrqu->data.flags = 0;
245         IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
246
247         return err;
248 }
249
250 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
251                             struct iw_request_info *info,
252                             union iwreq_data *wrqu, char *keybuf)
253 {
254         struct iw_point *erq = &(wrqu->encoding);
255         struct net_device *dev = ieee->dev;
256         struct ieee80211_security sec = {
257                 .flags = 0
258         };
259         int i, key, key_provided, len;
260         struct ieee80211_crypt_data **crypt;
261
262         IEEE80211_DEBUG_WX("SET_ENCODE\n");
263
264         key = erq->flags & IW_ENCODE_INDEX;
265         if (key) {
266                 if (key > WEP_KEYS)
267                         return -EINVAL;
268                 key--;
269                 key_provided = 1;
270         } else {
271                 key_provided = 0;
272                 key = ieee->tx_keyidx;
273         }
274
275         IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
276                            "provided" : "default");
277
278         crypt = &ieee->crypt[key];
279
280         if (erq->flags & IW_ENCODE_DISABLED) {
281                 if (key_provided && *crypt) {
282                         IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
283                                            key);
284                         ieee80211_crypt_delayed_deinit(ieee, crypt);
285                 } else
286                         IEEE80211_DEBUG_WX("Disabling encryption.\n");
287
288                 /* Check all the keys to see if any are still configured,
289                  * and if no key index was provided, de-init them all */
290                 for (i = 0; i < WEP_KEYS; i++) {
291                         if (ieee->crypt[i] != NULL) {
292                                 if (key_provided)
293                                         break;
294                                 ieee80211_crypt_delayed_deinit(
295                                         ieee, &ieee->crypt[i]);
296                         }
297                 }
298
299                 if (i == WEP_KEYS) {
300                         sec.enabled = 0;
301                         sec.level = SEC_LEVEL_0;
302                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
303                 }
304
305                 goto done;
306         }
307
308
309
310         sec.enabled = 1;
311         sec.flags |= SEC_ENABLED;
312
313         if (*crypt != NULL && (*crypt)->ops != NULL &&
314             strcmp((*crypt)->ops->name, "WEP") != 0) {
315                 /* changing to use WEP; deinit previously used algorithm
316                  * on this key */
317                 ieee80211_crypt_delayed_deinit(ieee, crypt);
318         }
319
320         if (*crypt == NULL) {
321                 struct ieee80211_crypt_data *new_crypt;
322
323                 /* take WEP into use */
324                 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
325                                     GFP_KERNEL);
326                 if (new_crypt == NULL)
327                         return -ENOMEM;
328                 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
329                 if (!new_crypt->ops)
330                         new_crypt->ops = ieee80211_get_crypto_ops("WEP");
331
332                 if (new_crypt->ops)
333                         new_crypt->priv = new_crypt->ops->init(key);
334
335                 if (!new_crypt->ops || !new_crypt->priv) {
336                         kfree(new_crypt);
337                         new_crypt = NULL;
338
339                         netdev_warn(ieee->dev,
340                                     "could not initialize WEP: load module ieee80211_crypt_wep\n");
341                         return -EOPNOTSUPP;
342                 }
343                 *crypt = new_crypt;
344         }
345
346         /* If a new key was provided, set it up */
347         if (erq->length > 0) {
348                 len = erq->length <= 5 ? 5 : 13;
349                 memcpy(sec.keys[key], keybuf, erq->length);
350                 if (len > erq->length)
351                         memset(sec.keys[key] + erq->length, 0,
352                                len - erq->length);
353                 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
354                                    key, escape_essid(sec.keys[key], len),
355                                    erq->length, len);
356                 sec.key_sizes[key] = len;
357                 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
358                                        (*crypt)->priv);
359                 sec.flags |= (1 << key);
360                 /* This ensures a key will be activated if no key is
361                  * explicitly set */
362                 if (key == sec.active_key)
363                         sec.flags |= SEC_ACTIVE_KEY;
364                 ieee->tx_keyidx = key;//by wb 080312
365         } else {
366                 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
367                                              NULL, (*crypt)->priv);
368                 if (len == 0) {
369                         /* Set a default key of all 0 */
370                         IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
371                                            key);
372                         memset(sec.keys[key], 0, 13);
373                         (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
374                                                (*crypt)->priv);
375                         sec.key_sizes[key] = 13;
376                         sec.flags |= (1 << key);
377                 }
378
379                 /* No key data - just set the default TX key index */
380                 if (key_provided) {
381                         IEEE80211_DEBUG_WX(
382                                 "Setting key %d to default Tx key.\n", key);
383                         ieee->tx_keyidx = key;
384                         sec.active_key = key;
385                         sec.flags |= SEC_ACTIVE_KEY;
386                 }
387         }
388
389  done:
390         ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
391         sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
392         sec.flags |= SEC_AUTH_MODE;
393         IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
394                            "OPEN" : "SHARED KEY");
395
396         /* For now we just support WEP, so only set that security level...
397          * TODO: When WPA is added this is one place that needs to change */
398         sec.flags |= SEC_LEVEL;
399         sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
400
401         if (ieee->set_security)
402                 ieee->set_security(dev, &sec);
403
404         /* Do not reset port if card is in Managed mode since resetting will
405          * generate new IEEE 802.11 authentication which may end up in looping
406          * with IEEE 802.1X.  If your hardware requires a reset after WEP
407          * configuration (for example... Prism2), implement the reset_port in
408          * the callbacks structures used to initialize the 802.11 stack. */
409         if (ieee->reset_on_keychange &&
410             ieee->iw_mode != IW_MODE_INFRA &&
411             ieee->reset_port && ieee->reset_port(dev)) {
412                 netdev_dbg(ieee->dev, "reset_port failed\n");
413                 return -EINVAL;
414         }
415         return 0;
416 }
417
418 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
419                             struct iw_request_info *info,
420                             union iwreq_data *wrqu, char *keybuf)
421 {
422         struct iw_point *erq = &(wrqu->encoding);
423         int len, key;
424         struct ieee80211_crypt_data *crypt;
425
426         IEEE80211_DEBUG_WX("GET_ENCODE\n");
427
428         if (ieee->iw_mode == IW_MODE_MONITOR)
429                 return -1;
430
431         key = erq->flags & IW_ENCODE_INDEX;
432         if (key) {
433                 if (key > WEP_KEYS)
434                         return -EINVAL;
435                 key--;
436         } else
437                 key = ieee->tx_keyidx;
438
439         crypt = ieee->crypt[key];
440         erq->flags = key + 1;
441
442         if (crypt == NULL || crypt->ops == NULL) {
443                 erq->length = 0;
444                 erq->flags |= IW_ENCODE_DISABLED;
445                 return 0;
446         }
447
448         if (strcmp(crypt->ops->name, "WEP") != 0) {
449                 /* only WEP is supported with wireless extensions, so just
450                  * report that encryption is used */
451                 erq->length = 0;
452                 erq->flags |= IW_ENCODE_ENABLED;
453                 return 0;
454         }
455
456         len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
457         erq->length = (len >= 0 ? len : 0);
458
459         erq->flags |= IW_ENCODE_ENABLED;
460
461         if (ieee->open_wep)
462                 erq->flags |= IW_ENCODE_OPEN;
463         else
464                 erq->flags |= IW_ENCODE_RESTRICTED;
465
466         return 0;
467 }
468
469 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
470                                 struct iw_request_info *info,
471                                 union iwreq_data *wrqu, char *extra)
472 {
473         struct net_device *dev = ieee->dev;
474         struct iw_point *encoding = &wrqu->encoding;
475         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
476         int i, idx, ret = 0;
477         int group_key = 0;
478         const char *alg;
479         struct ieee80211_crypto_ops *ops;
480         struct ieee80211_crypt_data **crypt;
481
482         struct ieee80211_security sec = {
483                 .flags = 0,
484         };
485         //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
486         idx = encoding->flags & IW_ENCODE_INDEX;
487         if (idx) {
488                 if (idx < 1 || idx > WEP_KEYS)
489                         return -EINVAL;
490                 idx--;
491         } else
492                 idx = ieee->tx_keyidx;
493
494         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
495                 crypt = &ieee->crypt[idx];
496                 group_key = 1;
497         } else {
498                 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
499                 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
500                 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
501                         return -EINVAL;
502                 if (ieee->iw_mode == IW_MODE_INFRA)
503                         crypt = &ieee->crypt[idx];
504                 else
505                         return -EINVAL;
506         }
507
508         sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
509         if ((encoding->flags & IW_ENCODE_DISABLED) ||
510             ext->alg == IW_ENCODE_ALG_NONE) {
511                 if (*crypt)
512                         ieee80211_crypt_delayed_deinit(ieee, crypt);
513
514                 for (i = 0; i < WEP_KEYS; i++)
515                         if (ieee->crypt[i] != NULL)
516                                 break;
517
518                 if (i == WEP_KEYS) {
519                         sec.enabled = 0;
520                         // sec.encrypt = 0;
521                         sec.level = SEC_LEVEL_0;
522                         sec.flags |= SEC_LEVEL;
523                 }
524                 //printk("disabled: flag:%x\n", encoding->flags);
525                 goto done;
526         }
527
528         sec.enabled = 1;
529     //    sec.encrypt = 1;
530
531         switch (ext->alg) {
532         case IW_ENCODE_ALG_WEP:
533                 alg = "WEP";
534                 break;
535         case IW_ENCODE_ALG_TKIP:
536                 alg = "TKIP";
537                 break;
538         case IW_ENCODE_ALG_CCMP:
539                 alg = "CCMP";
540                 break;
541         default:
542                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
543                                    dev->name, ext->alg);
544                 ret = -EINVAL;
545                 goto done;
546         }
547 //      printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
548
549         ops = ieee80211_get_crypto_ops(alg);
550         if (ops == NULL)
551                 ops = ieee80211_get_crypto_ops(alg);
552         if (ops == NULL) {
553                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
554                                    dev->name, ext->alg);
555                 printk("========>unknown crypto alg %d\n", ext->alg);
556                 ret = -EINVAL;
557                 goto done;
558         }
559
560         if (*crypt == NULL || (*crypt)->ops != ops) {
561                 struct ieee80211_crypt_data *new_crypt;
562
563                 ieee80211_crypt_delayed_deinit(ieee, crypt);
564
565                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
566                 if (new_crypt == NULL) {
567                         ret = -ENOMEM;
568                         goto done;
569                 }
570                 new_crypt->ops = ops;
571                 if (new_crypt->ops)
572                         new_crypt->priv = new_crypt->ops->init(idx);
573                 if (new_crypt->priv == NULL) {
574                         kfree(new_crypt);
575                         ret = -EINVAL;
576                         goto done;
577                 }
578                 *crypt = new_crypt;
579
580         }
581
582         if (ext->key_len > 0 && (*crypt)->ops->set_key &&
583             (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
584                                    (*crypt)->priv) < 0) {
585                 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
586                 printk("key setting failed\n");
587                 ret = -EINVAL;
588                 goto done;
589         }
590 #if 1
591  //skip_host_crypt:
592         //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
593         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
594                 ieee->tx_keyidx = idx;
595                 sec.active_key = idx;
596                 sec.flags |= SEC_ACTIVE_KEY;
597         }
598
599         if (ext->alg != IW_ENCODE_ALG_NONE) {
600                 memcpy(sec.keys[idx], ext->key, ext->key_len);
601                 sec.key_sizes[idx] = ext->key_len;
602                 sec.flags |= (1 << idx);
603                 if (ext->alg == IW_ENCODE_ALG_WEP) {
604                       //  sec.encode_alg[idx] = SEC_ALG_WEP;
605                         sec.flags |= SEC_LEVEL;
606                         sec.level = SEC_LEVEL_1;
607                 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
608                       //  sec.encode_alg[idx] = SEC_ALG_TKIP;
609                         sec.flags |= SEC_LEVEL;
610                         sec.level = SEC_LEVEL_2;
611                 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
612                        // sec.encode_alg[idx] = SEC_ALG_CCMP;
613                         sec.flags |= SEC_LEVEL;
614                         sec.level = SEC_LEVEL_3;
615                 }
616                 /* Don't set sec level for group keys. */
617                 if (group_key)
618                         sec.flags &= ~SEC_LEVEL;
619         }
620 #endif
621 done:
622         if (ieee->set_security)
623                 ieee->set_security(ieee->dev, &sec);
624
625          if (ieee->reset_on_keychange &&
626             ieee->iw_mode != IW_MODE_INFRA &&
627             ieee->reset_port && ieee->reset_port(dev)) {
628                 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
629                 return -EINVAL;
630         }
631
632         return ret;
633 }
634 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
635                                struct iw_request_info *info,
636                                union iwreq_data *wrqu, char *extra)
637 {
638         struct iw_mlme *mlme = (struct iw_mlme *) extra;
639 //      printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
640 #if 1
641         switch (mlme->cmd) {
642         case IW_MLME_DEAUTH:
643         case IW_MLME_DISASSOC:
644         //      printk("disassoc now\n");
645                 ieee80211_disassociate(ieee);
646                 break;
647          default:
648                 return -EOPNOTSUPP;
649         }
650 #endif
651         return 0;
652 }
653
654 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
655                                struct iw_request_info *info,
656                                struct iw_param *data, char *extra)
657 {
658 /*
659          struct ieee80211_security sec = {
660                 .flags = SEC_AUTH_MODE,
661         }
662 */
663         //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
664         switch (data->flags & IW_AUTH_INDEX) {
665         case IW_AUTH_WPA_VERSION:
666              /*need to support wpa2 here*/
667                 //printk("wpa version:%x\n", data->value);
668                 break;
669         case IW_AUTH_CIPHER_PAIRWISE:
670         case IW_AUTH_CIPHER_GROUP:
671         case IW_AUTH_KEY_MGMT:
672                 /*
673  *                  * Host AP driver does not use these parameters and allows
674  *                                   * wpa_supplicant to control them internally.
675  *                                                    */
676                 break;
677         case IW_AUTH_TKIP_COUNTERMEASURES:
678                 ieee->tkip_countermeasures = data->value;
679                 break;
680         case IW_AUTH_DROP_UNENCRYPTED:
681                 ieee->drop_unencrypted = data->value;
682                 break;
683
684         case IW_AUTH_80211_AUTH_ALG:
685                 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0;
686                 //printk("open_wep:%d\n", ieee->open_wep);
687                 break;
688
689 #if 1
690         case IW_AUTH_WPA_ENABLED:
691                 ieee->wpa_enabled = (data->value) ? 1 : 0;
692                 //printk("enable wpa:%d\n", ieee->wpa_enabled);
693                 break;
694
695 #endif
696         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
697                 ieee->ieee802_1x = data->value;
698                 break;
699         case IW_AUTH_PRIVACY_INVOKED:
700                 ieee->privacy_invoked = data->value;
701                 break;
702         default:
703                 return -EOPNOTSUPP;
704         }
705         return 0;
706 }
707
708 #if 1
709 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
710 {
711         u8 *buf = NULL;
712
713         if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
714                 printk("return error out, len:%zu\n", len);
715         return -EINVAL;
716         }
717
718         if (len) {
719                 if (len != ie[1]+2) {
720                         printk("len:%zu, ie:%d\n", len, ie[1]);
721                         return -EINVAL;
722                 }
723                 buf = kmemdup(ie, len, GFP_KERNEL);
724                 if (buf == NULL)
725                         return -ENOMEM;
726                 kfree(ieee->wpa_ie);
727                 ieee->wpa_ie = buf;
728                 ieee->wpa_ie_len = len;
729         } else {
730                 kfree(ieee->wpa_ie);
731                 ieee->wpa_ie = NULL;
732                 ieee->wpa_ie_len = 0;
733         }
734 //      printk("<=====out %s()\n", __func__);
735
736         return 0;
737
738 }
739 #endif