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