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