wifi: renew patch drivers/net/wireless
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rda5990 / rda_wlan / rda5890_wext.c
1 /**
2   * This file contains ioctl functions
3   */
4 #include <linux/ctype.h>
5 #include <linux/delay.h>
6 #include <linux/if.h>
7 #include <linux/if_arp.h>
8 #include <linux/wireless.h>
9 #include <linux/bitops.h>
10
11 #include <net/iw_handler.h>
12 #include <linux/etherdevice.h>
13
14 #include "rda5890_defs.h"
15 #include "rda5890_dev.h"
16 #include "rda5890_ioctl.h"
17 #include "rda5890_wid.h"
18 #include "rda5890_wext.h"
19
20 #define WLAN_AUTH_OPEN 0
21 #define WLAN_AUTH_SHARED_KEY 1
22 #define WLAN_AUTH_FT 2
23 #define WLAN_AUTH_LEAP 128
24
25 #define WLAN_AUTH_CHALLENGE_LEN 128
26
27 #define WLAN_CAPABILITY_ESS             (1<<0)
28 #define WLAN_CAPABILITY_IBSS            (1<<1)
29 #define WLAN_CAPABILITY_CF_POLLABLE     (1<<2)
30 #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
31 #define WLAN_CAPABILITY_PRIVACY         (1<<4)
32 #define WLAN_CAPABILITY_SHORT_PREAMBLE  (1<<5)
33 #define WLAN_CAPABILITY_PBCC            (1<<6)
34 #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
35 #define IW_AUTH_ALG_WAPI      0x08
36 #define IW_ENCODE_ALG_WAPI    0x80
37
38 static int rda5890_get_name(struct net_device *dev, struct iw_request_info *info,
39                          char *cwrq, char *extra)
40 {
41
42         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
43
44         /* We could add support for 802.11n here as needed. Jean II */
45         snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
46
47         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
48         return 0;
49 }
50
51 static int rda5890_get_freq(struct net_device *dev, struct iw_request_info *info,
52                          struct iw_freq *fwrq, char *extra)
53 {
54         //struct rda5890_private *priv =  netdev_priv(dev);
55
56         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
57
58         fwrq->m = (long)2437 * 100000;
59         fwrq->e = 1;
60
61         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
62         return 0;
63 }
64
65 static int rda5890_get_wap(struct net_device *dev, struct iw_request_info *info,
66                         struct sockaddr *awrq, char *extra)
67 {
68         struct rda5890_private *priv = (struct rda5890_private *) netdev_priv(dev);
69
70         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
71
72         if (priv->connect_status == MAC_CONNECTED) {
73                 memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
74         } else {
75                 memset(awrq->sa_data, 0, ETH_ALEN);
76         }
77         awrq->sa_family = ARPHRD_ETHER;
78
79         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
80         return 0;
81 }
82
83 static int rda5890_set_nick(struct net_device *dev, struct iw_request_info *info,
84                          struct iw_point *dwrq, char *extra)
85 {
86         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
87
88         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
89         return 0;
90 }
91
92 static int rda5890_get_nick(struct net_device *dev, struct iw_request_info *info,
93                          struct iw_point *dwrq, char *extra)
94 {
95         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
96
97         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
98         return 0;
99 }
100
101 static int rda5890_set_rts(struct net_device *dev, struct iw_request_info *info,
102                         struct iw_param *vwrq, char *extra)
103 {
104         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
105
106         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
107         return 0;
108 }
109
110 static int rda5890_get_rts(struct net_device *dev, struct iw_request_info *info,
111                         struct iw_param *vwrq, char *extra)
112 {
113         //struct rda5890_private *priv = netdev_priv(dev);
114         int ret = 0;
115         u16 val = 0;
116
117         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
118
119         val = 600;
120
121         vwrq->value = val;
122         vwrq->disabled = val > RDA5890_RTS_MAX_VALUE; /* min rts value is 0 */
123         vwrq->fixed = 1;
124
125         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
126         return ret;
127 }
128
129 static int rda5890_set_frag(struct net_device *dev, struct iw_request_info *info,
130                          struct iw_param *vwrq, char *extra)
131 {
132         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
133
134         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
135         return 0;
136 }
137
138 static int rda5890_get_frag(struct net_device *dev, struct iw_request_info *info,
139                          struct iw_param *vwrq, char *extra)
140 {
141         //struct rda5890_private *priv = netdev_priv(dev);
142         int ret = 0;
143         u16 val = 0;
144
145         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
146
147         val = 1460;
148
149         vwrq->value = val;
150         vwrq->disabled = ((val < RDA5890_FRAG_MIN_VALUE)
151                           || (val > RDA5890_FRAG_MAX_VALUE));
152         vwrq->fixed = 1;
153
154         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
155         return ret;
156 }
157
158 static int rda5890_get_mode(struct net_device *dev,
159                          struct iw_request_info *info, u32 * uwrq, char *extra)
160 {
161         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
162
163         *uwrq = IW_MODE_INFRA;
164
165         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
166         return 0;
167 }
168
169 static int rda5890_get_txpow(struct net_device *dev,
170                           struct iw_request_info *info,
171                           struct iw_param *vwrq, char *extra)
172 {
173         //struct rda5890_private *priv = netdev_priv(dev);
174
175         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
176
177         vwrq->value = 20;  // in dbm
178         vwrq->fixed = 1;
179         vwrq->disabled = 0;
180         vwrq->flags = IW_TXPOW_DBM;
181
182         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
183         return 0;
184 }
185
186 static int rda5890_set_retry(struct net_device *dev, struct iw_request_info *info,
187                           struct iw_param *vwrq, char *extra)
188 {
189         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
190
191         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
192         return 0;
193 }
194
195 static int rda5890_get_retry(struct net_device *dev, struct iw_request_info *info,
196                           struct iw_param *vwrq, char *extra)
197 {
198         //struct rda5890_private *priv = netdev_priv(dev);
199         int ret = 0;
200         u16 val = 0;
201
202         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
203
204         vwrq->disabled = 0;
205
206         if (vwrq->flags & IW_RETRY_LONG) {
207                 val = 7;
208
209                 /* Subtract 1 to convert try count to retry count */
210                 vwrq->value = val - 1;
211                 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
212         } else {
213                 val = 6;
214
215                 /* Subtract 1 to convert try count to retry count */
216                 vwrq->value = val - 1;
217                 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
218         }
219
220         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
221         return ret;
222 }
223
224 /** 
225  * 802.11b/g supported bitrates (in 500Kb/s units) 
226  */
227 u8 rda5890_bg_rates[MAX_RATES] =
228         { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 
229         0x24, 0x30, 0x48, 0x60, 0x6c,0x00, 0x00 }; 
230
231 u16 rda5890_nr_chan = 11;
232
233 /**
234  *  @brief Get Range Info
235  *
236  *  @param dev                  A pointer to net_device structure
237  *  @param info                 A pointer to iw_request_info structure
238  *  @param vwrq                 A pointer to iw_param structure
239  *  @param extra                A pointer to extra data buf
240  *  @return                     0 --success, otherwise fail
241  */
242 static int rda5890_get_range(struct net_device *dev, struct iw_request_info *info,
243                           struct iw_point *dwrq, char *extra)
244 {
245         //struct rda5890_private *priv = netdev_priv(dev);
246         struct iw_range *range = (struct iw_range *)extra;
247         int i;
248
249         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
250
251         dwrq->length = sizeof(struct iw_range);
252         memset(range, 0, sizeof(struct iw_range));
253
254         range->min_nwid = 0;
255         range->max_nwid = 0;
256
257         range->num_bitrates = sizeof(rda5890_bg_rates);
258         for (i = 0; i < range->num_bitrates; i++)
259                 range->bitrate[i] = rda5890_bg_rates[i] * 500000;
260         range->num_bitrates = i;
261
262         range->num_frequency = 0;
263
264         range->scan_capa = IW_SCAN_CAPA_ESSID;
265
266         for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
267                      && (i < rda5890_nr_chan); i++) {
268                         range->freq[range->num_frequency].i = (long)(i + 1);
269                         range->freq[range->num_frequency].m =
270                             (long)((2412 + 5 * i) * 100000);
271                         range->freq[range->num_frequency].e = 1;
272                         range->num_frequency++;
273         }
274
275         range->num_channels = range->num_frequency;
276
277         /*
278          * Set an indication of the max TCP throughput in bit/s that we can
279          * expect using this interface
280          */
281         range->throughput = 5000 * 1000;
282
283         range->min_rts = RDA5890_RTS_MIN_VALUE;
284         range->max_rts = RDA5890_RTS_MAX_VALUE;
285         range->min_frag = RDA5890_FRAG_MIN_VALUE;
286         range->max_frag = RDA5890_FRAG_MAX_VALUE;
287
288         range->encoding_size[0] = 5;
289         range->encoding_size[1] = 13;
290         range->num_encoding_sizes = 2;
291         range->max_encoding_tokens = 4;
292
293         /*
294          * Right now we support only "iwconfig ethX power on|off"
295          */
296         range->pm_capa = IW_POWER_ON;
297
298         /*
299          * Minimum version we recommend
300          */
301         range->we_version_source = 15;
302
303         /*
304          * Version we are compiled with
305          */
306         range->we_version_compiled = WIRELESS_EXT;
307
308         range->retry_capa = IW_RETRY_LIMIT;
309         range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
310
311         range->min_retry = 0;
312         range->max_retry = 14;
313
314         /*
315          * Set the qual, level and noise range values
316          */
317         range->max_qual.qual = 100;
318         range->max_qual.level = 0;
319         range->max_qual.noise = 0;
320         range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
321
322         range->avg_qual.qual = 70;
323         /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
324         range->avg_qual.level = 0;
325         range->avg_qual.noise = 0;
326         range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
327
328         range->sensitivity = 0;
329
330         /* Setup the supported power level ranges */
331         memset(range->txpower, 0, sizeof(range->txpower));
332         range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
333         range->txpower[0] = 0;
334         range->txpower[1] = 20;
335         range->num_txpower = 2;
336
337         range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
338                                 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
339                                 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
340         range->event_capa[1] = IW_EVENT_CAPA_K_1;
341
342         range->enc_capa =   IW_ENC_CAPA_WPA
343                                   | IW_ENC_CAPA_WPA2
344                                   | IW_ENC_CAPA_CIPHER_TKIP
345                                   | IW_ENC_CAPA_CIPHER_CCMP;
346
347         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
348         return 0;
349 }
350
351 static int rda5890_set_power(struct net_device *dev, struct iw_request_info *info,
352                           struct iw_param *vwrq, char *extra)
353 {
354         //struct rda5890_private *priv = netdev_priv(dev);
355
356         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
357
358         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
359         return 0;
360 }
361
362 static int rda5890_get_power(struct net_device *dev, struct iw_request_info *info,
363                           struct iw_param *vwrq, char *extra)
364 {
365         //struct rda5890_private *priv = netdev_priv(dev);
366
367         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
368
369         vwrq->value = 0;
370         vwrq->flags = 0;
371         vwrq->disabled = 0;
372
373         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
374         return 0;
375 }
376
377 static int rda5890_update_bss_stats(struct rda5890_private *priv)
378 {
379         int ret = 0;
380
381         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
382         
383         memcpy(priv->curbssparams.ssid, 
384                 priv->assoc_ssid, sizeof(priv->curbssparams.ssid));
385
386     if(priv->scan_running == 1)
387         return ret;
388
389         ret = rda5890_get_bssid(priv, priv->curbssparams.bssid);
390         if (ret) {
391                 RDA5890_ERRP("rda5890_get_bssid, ret = %d\n", ret);
392                 goto out;
393         }
394
395 #if 0
396         ret = rda5890_get_channel(priv, &priv->curbssparams.channel);
397         if (ret) {
398                 RDA5890_ERRP("rda5890_get_channel, ret = %d\n", ret);
399                 goto out;
400         }
401 #endif
402
403         ret = rda5890_get_rssi(priv, &priv->curbssparams.rssi);
404         if (ret) {
405                 RDA5890_ERRP("rda5890_get_rssi, ret = %d\n", ret);
406                 goto out;
407         }
408
409         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<< ch = %d  rssi = %d\n", __func__, priv->curbssparams.channel, priv->curbssparams.rssi);
410
411 out:
412         return ret;
413 }
414
415 static struct iw_statistics *rda5890_get_wireless_stats(struct net_device *dev)
416 {
417         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
418         int stats_valid = 0;
419         u8 snr;
420
421         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
422
423         if (priv->connect_status != MAC_CONNECTED)
424                 goto out;
425
426         rda5890_update_bss_stats(priv);
427
428         priv->wstats.miss.beacon = 0;
429         priv->wstats.discard.retries = 0;
430         priv->wstats.qual.level = priv->curbssparams.rssi > 127? priv->curbssparams.rssi - 271
431         :priv->curbssparams.rssi - 15;
432     
433         snr = priv->wstats.qual.level - RDA5890_NF_DEFAULT_SCAN_VALUE;
434         priv->wstats.qual.qual =
435                 (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - snr) *
436                  (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - snr))) /
437                 (RSSI_DIFF * RSSI_DIFF);
438         if (priv->wstats.qual.qual > 100)
439                 priv->wstats.qual.qual = 100;
440         priv->wstats.qual.noise = RDA5890_NF_DEFAULT_SCAN_VALUE;
441         priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
442
443         stats_valid = 1;
444
445 out:
446         if (!stats_valid) {
447                 priv->wstats.miss.beacon = 0;
448                 priv->wstats.discard.retries = 0;
449                 priv->wstats.qual.qual = 0;
450                 priv->wstats.qual.level = 0;
451                 priv->wstats.qual.noise = 0;
452                 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
453                 priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
454                     IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
455         }
456
457         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
458         return &priv->wstats;
459 }
460
461 static int rda5890_set_freq(struct net_device *dev, struct iw_request_info *info,
462                   struct iw_freq *fwrq, char *extra)
463 {
464         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
465
466         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
467
468
469         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
470         return 0;
471 }
472
473 static int rda5890_set_rate(struct net_device *dev, struct iw_request_info *info,
474                   struct iw_param *vwrq, char *extra)
475 {
476         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
477
478         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
479
480
481         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
482         return 0;
483 }
484
485 static int rda5890_get_rate(struct net_device *dev, struct iw_request_info *info,
486                   struct iw_param *vwrq, char *extra)
487 {
488         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
489
490         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
491
492         vwrq->fixed = 0;
493         vwrq->value = 108*500000;
494
495         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
496         return 0;
497 }
498
499 static int rda5890_set_mode(struct net_device *dev,
500                   struct iw_request_info *info, u32 * uwrq, char *extra)
501 {
502         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
503
504         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
505
506         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
507         return 0;
508 }
509
510
511 /**
512  *  @brief Get Encryption key
513  *
514  *  @param dev                  A pointer to net_device structure
515  *  @param info                 A pointer to iw_request_info structure
516  *  @param vwrq                 A pointer to iw_param structure
517  *  @param extra                A pointer to extra data buf
518  *  @return                     0 --success, otherwise fail
519  */
520 static int rda5890_get_encode(struct net_device *dev,
521                            struct iw_request_info *info,
522                            struct iw_point *dwrq, u8 * extra)
523 {
524         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
525
526         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
527
528         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
529         return 0;
530 }
531
532 /**
533  *  @brief Set Encryption key
534  *
535  *  @param dev                  A pointer to net_device structure
536  *  @param info                 A pointer to iw_request_info structure
537  *  @param vwrq                 A pointer to iw_param structure
538  *  @param extra                A pointer to extra data buf
539  *  @return                     0 --success, otherwise fail
540  */
541 static int rda5890_set_encode(struct net_device *dev,
542                     struct iw_request_info *info,
543                     struct iw_point *dwrq, char *extra)
544 {
545         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
546
547         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
548     
549         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
550         return 0;
551 }
552
553 /**
554  *  @brief Set Encryption key (internal)
555  *
556  *  @param priv                 A pointer to private card structure
557  *  @param key_material         A pointer to key material
558  *  @param key_length           length of key material
559  *  @param index                key index to set
560  *  @param set_tx_key           Force set TX key (1 = yes, 0 = no)
561  *  @return                     0 --success, otherwise fail
562  */
563 static int copy_wep_key(struct rda5890_private *priv,
564                             const char *key_material,
565                             u16 key_length,
566                             u16 index,
567                             int set_tx_key)
568 {
569         int ret = 0;
570         struct enc_key *pkey;
571
572         /* Paranoid validation of key index */
573         if (index > 3) {
574                 ret = -EINVAL;
575                 goto out;
576         }
577
578         /* validate max key length */
579         if (key_length > KEY_LEN_WEP_104) {
580                 ret = -EINVAL;
581                 goto out;
582         }
583
584         if (key_length == KEY_LEN_WEP_40) {
585                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
586                         "WEP40 : %02x%02x%02x%02x%02x\n",
587                         key_material[0], key_material[1], key_material[2],
588                         key_material[3], key_material[4]);
589         }
590         else if (key_length == KEY_LEN_WEP_104) {
591                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
592                         "WEP104 : %02x%02x%02x%02x%02x"
593                         " %02x%02x%02x%02x%02x"
594                         " %02x%02x%02x\n",
595                         key_material[0], key_material[1], key_material[2],
596                         key_material[3], key_material[4], key_material[5],
597                         key_material[6], key_material[7], key_material[8],
598                         key_material[9], key_material[10], key_material[11],
599                         key_material[12]);
600         }
601         else {
602                 RDA5890_ERRP("Error in WEP Key length %d\n", key_length);
603         }
604
605         pkey = &priv->wep_keys[index];
606
607         if (key_length > 0) {
608                 memset(pkey, 0, sizeof(struct enc_key));
609                 pkey->type = KEY_TYPE_ID_WEP;
610
611                 /* Standardize the key length */
612                 pkey->len = (key_length > KEY_LEN_WEP_40) ?
613                                 KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
614                 memcpy(pkey->key, key_material, key_length);
615         }
616
617         if (set_tx_key) {
618                 /* Ensure the chosen key is valid */
619                 if (!pkey->len) {
620                         RDA5890_ERRP("key not set, so cannot enable it\n");
621                         ret = -EINVAL;
622                         goto out;
623                 }
624                 priv->wep_tx_keyidx = index;
625         }
626
627         priv->secinfo.wep_enabled = 1;
628
629 out:
630         return ret;
631 }
632
633 static int validate_key_index(u16 def_index, u16 raw_index,
634                               u16 *out_index, u16 *is_default)
635 {
636         if (!out_index || !is_default)
637                 return -EINVAL;
638
639         /* Verify index if present, otherwise use default TX key index */
640         if (raw_index > 0) {
641                 if (raw_index > 4)
642                         return -EINVAL;
643                 *out_index = raw_index - 1;
644         } else {
645                 *out_index = def_index;
646                 *is_default = 1;
647         }
648         return 0;
649 }
650
651 static void disable_wep(struct rda5890_private *priv)
652 {
653         int i;
654
655         /* Set Open System auth mode */
656         priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
657
658         /* Clear WEP keys and mark WEP as disabled */
659         priv->secinfo.wep_enabled = 0;
660         for (i = 0; i < 4; i++)
661                 priv->wep_keys[i].len = 0;
662
663         set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
664         set_bit(ASSOC_FLAG_WEP_KEYS, &priv->assoc_flags);
665 }
666
667 static void disable_wpa(struct rda5890_private *priv)
668 {
669         memset(&priv->wpa_mcast_key, 0, sizeof (struct enc_key));
670         priv->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
671         set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &priv->assoc_flags);
672
673         memset(&priv->wpa_unicast_key, 0, sizeof (struct enc_key));
674         priv->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
675         set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &priv->assoc_flags);
676
677         priv->secinfo.WPAenabled = 0;
678         priv->secinfo.WPA2enabled = 0;
679     priv->secinfo.cipther_type = 0;
680     priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
681         set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
682 }
683
684 /**
685  *  @brief Get Extended Encryption key (WPA/802.1x and WEP)
686  *
687  *  @param dev                  A pointer to net_device structure
688  *  @param info                 A pointer to iw_request_info structure
689  *  @param vwrq                 A pointer to iw_param structure
690  *  @param extra                A pointer to extra data buf
691  *  @return                     0 on success, otherwise failure
692  */
693 static int rda5890_get_encodeext(struct net_device *dev,
694                               struct iw_request_info *info,
695                               struct iw_point *dwrq,
696                               char *extra)
697 {
698         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
699         int ret = -EINVAL;
700         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
701         int index, max_key_len;
702
703         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
704
705         max_key_len = dwrq->length - sizeof(*ext);
706         if (max_key_len < 0)
707                 goto out;
708
709         index = dwrq->flags & IW_ENCODE_INDEX;
710         if (index) {
711                 if (index < 1 || index > 4)
712                         goto out;
713                 index--;
714         } else {
715                 index = priv->wep_tx_keyidx;
716         }
717
718         if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
719             ext->alg != IW_ENCODE_ALG_WEP) {
720                 if (index != 0)
721                         goto out;
722         }
723
724         dwrq->flags = index + 1;
725         memset(ext, 0, sizeof(*ext));
726
727         if (   !priv->secinfo.wep_enabled
728             && !priv->secinfo.WPAenabled
729             && !priv->secinfo.WPA2enabled) {
730                 ext->alg = IW_ENCODE_ALG_NONE;
731                 ext->key_len = 0;
732                 dwrq->flags |= IW_ENCODE_DISABLED;
733         } else {
734                 u8 *key = NULL;
735
736                 if (   priv->secinfo.wep_enabled
737                     && !priv->secinfo.WPAenabled
738                     && !priv->secinfo.WPA2enabled) {
739                         /* WEP */
740                         ext->alg = IW_ENCODE_ALG_WEP;
741                         ext->key_len = priv->wep_keys[index].len;
742                         key = &priv->wep_keys[index].key[0];
743                 } else if (   !priv->secinfo.wep_enabled
744                            && (priv->secinfo.WPAenabled ||
745                                priv->secinfo.WPA2enabled)) {
746                         /* WPA */
747                         struct enc_key * pkey = NULL;
748
749                         if (   priv->wpa_mcast_key.len
750                             && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
751                                 pkey = &priv->wpa_mcast_key;
752                         else if (   priv->wpa_unicast_key.len
753                                  && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
754                                 pkey = &priv->wpa_unicast_key;
755
756                         if (pkey) {
757                                 if (pkey->type == KEY_TYPE_ID_AES) {
758                                         ext->alg = IW_ENCODE_ALG_CCMP;
759                                 } else {
760                                         ext->alg = IW_ENCODE_ALG_TKIP;
761                                 }
762                                 ext->key_len = pkey->len;
763                                 key = &pkey->key[0];
764                         } else {
765                                 ext->alg = IW_ENCODE_ALG_TKIP;
766                                 ext->key_len = 0;
767                         }
768                 } else {
769                         goto out;
770                 }
771
772                 if (ext->key_len > max_key_len) {
773                         ret = -E2BIG;
774                         goto out;
775                 }
776
777                 if (ext->key_len)
778                         memcpy(ext->key, key, ext->key_len);
779                 else
780                         dwrq->flags |= IW_ENCODE_NOKEY;
781                 dwrq->flags |= IW_ENCODE_ENABLED;
782         }
783         ret = 0;
784
785 out:
786         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
787         return 0;
788 }
789
790 /**
791  *  @brief Set Encryption key Extended (WPA/802.1x and WEP)
792  *
793  *  @param dev                  A pointer to net_device structure
794  *  @param info                 A pointer to iw_request_info structure
795  *  @param vwrq                 A pointer to iw_param structure
796  *  @param extra                A pointer to extra data buf
797  *  @return                     0 --success, otherwise fail
798  */
799 static int rda5890_set_encodeext(struct net_device *dev,
800                               struct iw_request_info *info,
801                               struct iw_point *dwrq,
802                               char *extra)
803 {
804         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
805         int ret = 0;
806         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
807         int alg = ext->alg;
808
809         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
810
811         if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
812                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
813                         "NO SEC\n");
814         if(test_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags))
815         {
816             if(priv->imode != 3 && priv->imode != 5)
817                     disable_wep (priv);
818         }
819                 disable_wpa (priv);
820         } else if (alg == IW_ENCODE_ALG_WEP) {
821                 u16 is_default = 0, index, set_tx_key = 0;
822
823                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
824                         "WEP, flags = 0x%04x\n", dwrq->flags);
825
826                 ret = validate_key_index(priv->wep_tx_keyidx,
827                                          (dwrq->flags & IW_ENCODE_INDEX),
828                                          &index, &is_default);
829                 if (ret)
830                         goto out;
831
832                 /* If WEP isn't enabled, or if there is no key data but a valid
833                  * index, or if the set-TX-key flag was passed, set the TX key.
834                  */
835                 if (   !priv->secinfo.wep_enabled
836                     || (dwrq->length == 0 && !is_default)
837                     || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
838                         set_tx_key = 1;
839
840                 /* Copy key to driver */
841                 ret = copy_wep_key(priv, ext->key, ext->key_len, index, set_tx_key);
842                 if (ret)
843                         goto out;
844
845                 /* Set Key to Mac */
846                 /* Move to assoc_helper_secinfo(), wep_key need to be set after imode */
847                 //ret = rda5890_set_wepkey(priv, index, ext->key, ext->key_len);
848                 //if (ret)
849                 //      goto out;
850
851                 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
852                         priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
853                 } else if (dwrq->flags & IW_ENCODE_OPEN) {
854                         priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
855                 }
856
857                 /* Mark the various WEP bits as modified */
858                 set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
859                 if (dwrq->length)
860                         set_bit(ASSOC_FLAG_WEP_KEYS, &priv->assoc_flags);
861                 if (set_tx_key)
862                         set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &priv->assoc_flags);
863         } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
864                 struct enc_key * pkey;
865
866                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
867                         "TKIP or CCMP, flags = 0x%04x, alg = %d\n", dwrq->flags, alg);
868
869                 /* validate key length */
870                 if (((alg == IW_ENCODE_ALG_TKIP)
871                         && (ext->key_len != KEY_LEN_WPA_TKIP))
872                     || ((alg == IW_ENCODE_ALG_CCMP)
873                         && (ext->key_len != KEY_LEN_WPA_AES))) {
874                                 RDA5890_ERRP("invalid size %d for key of alg, type %d\n",
875                                        ext->key_len, alg);
876                                 ret = -EINVAL;
877                                 goto out;
878                 }
879
880                 /* Copy key to driver */
881                 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
882                         pkey = &priv->wpa_mcast_key;
883                         set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &priv->assoc_flags);
884                 } else {
885                         pkey = &priv->wpa_unicast_key;
886                         set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &priv->assoc_flags);
887                 }
888
889                 memset(pkey, 0, sizeof (struct enc_key));
890                 memcpy(pkey->key, ext->key, ext->key_len);
891                 pkey->len = ext->key_len;
892                 if (pkey->len)
893                         pkey->flags |= KEY_INFO_WPA_ENABLED;
894
895                 /* Do this after zeroing key structure */
896                 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
897                         pkey->flags |= KEY_INFO_WPA_MCAST;
898                 } else {
899                         pkey->flags |= KEY_INFO_WPA_UNICAST;
900                 }
901
902                 if (alg == IW_ENCODE_ALG_TKIP) {
903                         pkey->type = KEY_TYPE_ID_TKIP;
904                         if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
905                             && !(priv->imode & (BIT6))) {
906                                 RDA5890_ERRP("imode [0x%x] not match with cipher alg TKIP\n",
907                                         priv->imode);
908                         }
909                 } else if (alg == IW_ENCODE_ALG_CCMP) {
910                         pkey->type = KEY_TYPE_ID_AES;
911                         if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
912                             && !(priv->imode & (BIT5))) {
913                                 RDA5890_ERRP("imode [0x%x] not match with cipher alg CCMP\n",
914                                         priv->imode);
915                         }
916                 }
917
918                 /* If WPA isn't enabled yet, do that now */
919                 if (   priv->secinfo.WPAenabled == 0
920                     && priv->secinfo.WPA2enabled == 0) {
921                         priv->secinfo.WPAenabled = 1;
922                         priv->secinfo.WPA2enabled = 1;
923                         set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
924                 }
925
926                 /* Set Keys to MAC*/
927                 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
928                         /* Set GTK */
929                         /* 
930                          *Always use key_id = 1 for now
931                          * need to toggle among 1, 2, 3
932                          */
933                         ret = rda5890_set_gtk(priv, 1, ext->tx_seq, IW_ENCODE_SEQ_MAX_SIZE,
934                                 pkey->key, pkey->len);
935                         if (ret)
936                                 goto out;
937                 } else {
938                         pkey->flags |= KEY_INFO_WPA_UNICAST;
939                         /* Set PTK */
940                         ret = rda5890_set_ptk(priv, pkey->key, pkey->len);
941                         if (ret)
942                                 goto out;
943                 }
944
945                 /* Only disable wep if necessary: can't waste time here. */
946                 disable_wep(priv);
947         } else if (alg == IW_ENCODE_ALG_WAPI) { //wapi
948                 if(ext->key_len != 32)
949                         goto out;
950
951                 priv->is_wapi = 1;
952
953                 /* Set Keys to MAC*/
954                 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
955                         unsigned char tmp[8];
956                         /* Set GTK */
957                         /* 
958                          * Always use key_id = 1 for now
959                          * need to toggle among 1, 2, 3
960                          */
961                         ret = rda5890_set_gtk(priv, 1, tmp, IW_ENCODE_SEQ_MAX_SIZE,
962                                 ext->key, ext->key_len);
963                         if (ret)
964                                 goto out;
965                 } else {
966                         /* Set PTK */
967                         ret = rda5890_set_ptk(priv, ext->key, ext->key_len);
968                         if (ret)
969                                 goto out;
970                 }
971         }
972
973 out:
974         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
975         return 0;
976 }
977
978 /**
979  *  @brief PMKSA cache operation (WPA/802.1x and WEP)
980  *
981  *  @param dev                  A pointer to net_device structure
982  *  @param info                 A pointer to iw_request_info structure
983  *  @param vwrq                 A pointer to iw_param structure
984  *  @param extra                A pointer to extra data buf
985  *  @return                     0 on success, otherwise failure
986  */
987 static int rda5890_set_pmksa(struct net_device *dev,
988                               struct iw_request_info *info,
989                               struct iw_point *dwrq,
990                               char *extra)
991 {
992         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
993
994         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
995
996         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
997         return 0;
998 }
999
1000 static int rda5890_set_genie(struct net_device *dev,
1001                           struct iw_request_info *info,
1002                           struct iw_point *dwrq,
1003                           char *extra)
1004 {
1005         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1006         int ret = 0;
1007
1008         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1009
1010         if(extra[0] == 0x44) //wapi ie
1011         {
1012                 unsigned char ie_len = extra[1] + 2;
1013                 rda5890_generic_set_str(priv, WID_WAPI_ASSOC_IE, extra ,ie_len);
1014                 goto out;
1015         }
1016           
1017         if (dwrq->length > MAX_WPA_IE_LEN ||
1018             (dwrq->length && extra == NULL)) {
1019                 ret = -EINVAL;
1020                 goto out;
1021         }
1022
1023         if (dwrq->length) {
1024                 memcpy(&priv->wpa_ie[0], extra, dwrq->length);
1025                 priv->wpa_ie_len = dwrq->length;
1026         } else {
1027                 memset(&priv->wpa_ie[0], 0, sizeof(priv->wpa_ie));
1028                 priv->wpa_ie_len = 0;
1029         }
1030
1031 out:
1032
1033         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1034         return ret;
1035 }
1036
1037 static int rda5890_get_genie(struct net_device *dev,
1038                           struct iw_request_info *info,
1039                           struct iw_point *dwrq,
1040                           char *extra)
1041 {
1042         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1043         int ret = 0;
1044
1045         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1046
1047         if (priv->wpa_ie_len == 0) {
1048                 dwrq->length = 0;
1049                 goto out;
1050         }
1051
1052         if (dwrq->length < priv->wpa_ie_len) {
1053                 ret = -E2BIG;
1054                 goto out;
1055         }
1056
1057         dwrq->length = priv->wpa_ie_len;
1058         memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
1059
1060 out:
1061         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1062         return ret;
1063 }
1064
1065 static int rda5890_set_auth(struct net_device *dev,
1066                          struct iw_request_info *info,
1067                          struct iw_param *dwrq,
1068                          char *extra)
1069 {
1070         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1071         int ret = 0;
1072         int updated = 0;
1073
1074         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1075
1076         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1077                 "flags = 0x%04x, value = 0x%x\n", dwrq->flags, dwrq->value);
1078
1079         switch (dwrq->flags & IW_AUTH_INDEX) {
1080         case IW_AUTH_CIPHER_PAIRWISE:
1081 #ifdef GET_SCAN_FROM_NETWORK_INFO
1082         if (dwrq->value & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) 
1083         {
1084               RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1085                     "WEP Selected \n");
1086                         priv->secinfo.wep_enabled = 1;
1087                if(dwrq->value & IW_AUTH_CIPHER_WEP104)
1088                    priv->secinfo.cipther_type |= IW_AUTH_CIPHER_WEP104;
1089                else if(dwrq->value & IW_AUTH_CIPHER_WEP40)
1090                   priv->secinfo.cipther_type |= IW_AUTH_CIPHER_WEP40;
1091                 }
1092                 if (dwrq->value & IW_AUTH_CIPHER_TKIP) {
1093                     RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1094                         "IW_AUTH_CIPHER_TKIP \n");
1095                      priv->secinfo.cipther_type |= IW_AUTH_CIPHER_TKIP;
1096                 }
1097                 if (dwrq->value & IW_AUTH_CIPHER_CCMP) {
1098                     RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1099                         "IW_AUTH_CIPHER_CCMP \n");
1100                     priv->secinfo.cipther_type |= IW_AUTH_CIPHER_CCMP;
1101                 }
1102                 if (dwrq->value & IW_AUTH_CIPHER_NONE) {
1103                     RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1104                         "OPEN System \n");
1105             priv->secinfo.cipther_type = IW_AUTH_CIPHER_NONE;
1106                 }
1107     break;
1108 #endif
1109         case IW_AUTH_TKIP_COUNTERMEASURES:
1110         case IW_AUTH_CIPHER_GROUP:
1111         case IW_AUTH_DROP_UNENCRYPTED:
1112                 /*
1113                  * rda5890 does not use these parameters
1114                  */
1115                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1116                         "DO NOT USE\n");
1117                 break;
1118
1119         case IW_AUTH_KEY_MGMT:
1120                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1121                         "KEY_MGMT, val = %d\n", dwrq->value);
1122                 priv->secinfo.key_mgmt = dwrq->value;
1123                 updated = 1;
1124                 break;
1125
1126         case IW_AUTH_WPA_VERSION:
1127                 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
1128                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1129                                 "WPA_VERSION, DISABLED\n");
1130                         priv->secinfo.WPAenabled = 0;
1131                         priv->secinfo.WPA2enabled = 0;
1132                         disable_wpa (priv);
1133                 }
1134                 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
1135                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1136                                 "WPA_VERSION, WPA\n");
1137                         priv->secinfo.WPAenabled = 1;
1138                         priv->secinfo.wep_enabled = 0;
1139                         priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1140                 }
1141                 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
1142                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1143                                 "WPA_VERSION, WPA2\n");
1144                         priv->secinfo.WPA2enabled = 1;
1145                         priv->secinfo.wep_enabled = 0;
1146                         priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1147                 }
1148                 updated = 1;
1149                 break;
1150
1151         case IW_AUTH_80211_AUTH_ALG:
1152                 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY || 
1153             dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) 
1154         {
1155             if(dwrq->value & IW_AUTH_ALG_SHARED_KEY )
1156             {
1157                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1158                                 "80211_AUTH_ALG, SHARED_KEY\n");
1159                         priv->secinfo.auth_mode |= IW_AUTH_ALG_SHARED_KEY;
1160                 }
1161                 if(dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1162                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1163                                 "80211_AUTH_ALG, OPEN\n");
1164                         priv->secinfo.auth_mode |= IW_AUTH_ALG_OPEN_SYSTEM;
1165                 }
1166         }
1167                 else if(dwrq->value & IW_AUTH_ALG_LEAP) {
1168                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1169                                 "80211_AUTH_ALG, LEAP\n");
1170                         priv->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
1171                 }
1172         else if(dwrq->value & IW_AUTH_ALG_WAPI) {
1173                         priv->secinfo.auth_mode = IW_AUTH_ALG_WAPI;
1174                 }      
1175                 else{
1176                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1177                                 "80211_AUTH_ALG, unknown\n");
1178                         ret = -EINVAL;
1179                 }
1180                 updated = 1;
1181                 break;
1182
1183         case IW_AUTH_WPA_ENABLED:
1184                 if (dwrq->value) {
1185                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1186                                 "WPA_ENABLED, value = 0x%x\n", dwrq->value);
1187                         if (!priv->secinfo.WPAenabled &&
1188                             !priv->secinfo.WPA2enabled) {
1189                                 priv->secinfo.WPAenabled = 1;
1190                                 priv->secinfo.WPA2enabled = 1;
1191                                 priv->secinfo.wep_enabled = 0;
1192                                 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1193                         }
1194                 } else {
1195                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1196                                 "WPA_ENABLED, value = ZERO\n");
1197                         priv->secinfo.WPAenabled = 0;
1198                         priv->secinfo.WPA2enabled = 0;
1199                         disable_wpa (priv);
1200                 }
1201                 updated = 1;
1202                 break;
1203
1204         default:
1205                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1206                         "NOT SUPPORT\n");
1207                 ret = -EOPNOTSUPP;
1208                 break;
1209         }
1210
1211         if (ret == 0) {
1212                 if (updated) {
1213                         set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
1214                 }
1215         }
1216
1217         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1218         return ret;
1219 }
1220
1221 static int rda5890_get_auth(struct net_device *dev,
1222                          struct iw_request_info *info,
1223                          struct iw_param *dwrq,
1224                          char *extra)
1225 {
1226         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1227         int ret = 0;
1228
1229         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1230
1231         switch (dwrq->flags & IW_AUTH_INDEX) {
1232         case IW_AUTH_KEY_MGMT:
1233                 dwrq->value = priv->secinfo.key_mgmt;
1234                 break;
1235
1236         case IW_AUTH_WPA_VERSION:
1237                 dwrq->value = 0;
1238                 if (priv->secinfo.WPAenabled)
1239                         dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
1240                 if (priv->secinfo.WPA2enabled)
1241                         dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
1242                 if (!dwrq->value)
1243                         dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
1244                 break;
1245
1246         case IW_AUTH_80211_AUTH_ALG:
1247                 dwrq->value = priv->secinfo.auth_mode;
1248                 break;
1249
1250         case IW_AUTH_WPA_ENABLED:
1251                 if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
1252                         dwrq->value = 1;
1253                 break;
1254
1255         default:
1256                 ret = -EOPNOTSUPP;
1257         }
1258
1259         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1260         return ret;
1261 }
1262
1263 static int rda5890_set_txpow(struct net_device *dev, struct iw_request_info *info,
1264                    struct iw_param *vwrq, char *extra)
1265 {
1266         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1267
1268         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1269
1270         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1271         return 0;
1272 }
1273
1274 static int rda5890_get_essid(struct net_device *dev, struct iw_request_info *info,
1275                    struct iw_point *dwrq, char *extra)
1276 {
1277         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1278
1279         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1280
1281
1282         memcpy(extra, priv->curbssparams.ssid,
1283                strlen(priv->curbssparams.ssid));
1284         dwrq->length = strlen(priv->curbssparams.ssid);
1285     extra[dwrq->length] = '\0';
1286
1287         /*
1288          * If none, we may want to get the one that was set
1289          */
1290
1291         dwrq->flags = 1;        /* active */
1292
1293         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>> \n", __func__);
1294         return 0;
1295 }
1296
1297 void rda5890_indicate_disconnected(struct rda5890_private *priv)
1298 {
1299         union iwreq_data wrqu;
1300
1301         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s <<<\n", __func__);
1302
1303         memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
1304         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1305         wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1306
1307     /*report disconnect to upper layer*/
1308         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s >>>\n", __func__);   
1309 }
1310
1311 void rda5890_indicate_connected(struct rda5890_private *priv)
1312 {
1313         union iwreq_data wrqu;
1314
1315         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s <<<\n", __func__);
1316
1317         memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
1318         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1319         wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1320
1321         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s >>>\n", __func__);
1322 }
1323
1324 void rda5890_assoc_done_worker(struct work_struct *work)
1325 {
1326     u8 bssid[6], zero_bssid[6];
1327         struct rda5890_private *priv = container_of(work, struct rda5890_private,
1328                 assoc_done_work.work);
1329
1330         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<< \n", __func__);
1331
1332     memset(bssid, 0, sizeof(bssid));
1333     memset(zero_bssid, 0, sizeof(zero_bssid));
1334     rda5890_get_bssid(priv, bssid);
1335
1336     if(memcmp(bssid, zero_bssid, sizeof(zero_bssid)))
1337     {
1338         memcpy(priv->curbssparams.bssid, bssid, sizeof(bssid));
1339     }
1340
1341     rda5890_get_rssi(priv, &priv->curbssparams.rssi);
1342     priv->curbssparams.rssi = priv->curbssparams.rssi > 127? 
1343         priv->curbssparams.rssi - 271: priv->curbssparams.rssi - 15;
1344     
1345     rda5990_assoc_power_save(priv);
1346     clear_bit(ASSOC_FLAG_ASSOC_START, &priv->assoc_flags);
1347     
1348         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1349 }
1350
1351 void rda5890_wlan_connect_worker(struct work_struct *work)
1352 {
1353         struct rda5890_private *priv = container_of(work, struct rda5890_private,
1354         wlan_connect_work.work);
1355
1356     rda5890_set_txrate(priv, 0);
1357
1358     if(priv)
1359         clear_bit(ASSOC_FLAG_WLAN_CONNECTING ,&priv->assoc_flags);
1360 }
1361
1362 //imode
1363 /* BIT0: 1 -> Security ON              0 -> OFF                          */
1364 /* BIT1: 1 -> WEP40  cypher supported  0 -> Not supported                */
1365 /* BIT2: 1 -> WEP104 cypher supported  0 -> Not supported                */
1366 /* BIT3: 1 -> WPA mode      supported  0 -> Not supported                */
1367 /* BIT4: 1 -> WPA2 (RSN)    supported  0 -> Not supported                */
1368 /* BIT5: 1 -> AES-CCMP cphr supported  0 -> Not supported                */
1369 /* BIT6: 1 -> TKIP   cypher supported  0 -> Not supported                */
1370 /* BIT7: 1 -> TSN           supported  0 -> Not supported                */
1371
1372 //authtype
1373 /* BIT0: 1 -> OPEN SYSTEM  */
1374 /* BIT1: 1 -> SHARED KEY  */
1375 /* BIT3: 1 -> WPA RSN  802.1x*/
1376 /* BIT7: 1 -> WAPI   */
1377 static int assoc_helper_secinfo(struct rda5890_private *priv, 
1378                 struct bss_descriptor *assoc_bss)
1379 {
1380         int ret = 0;
1381
1382         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1383
1384         /* set imode and key */
1385         if (   !priv->secinfo.wep_enabled
1386             && !priv->secinfo.WPAenabled
1387             && !priv->secinfo.WPA2enabled) {
1388                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1389                         "%s, NO SEC\n", __func__);
1390                 priv->imode = 0;
1391         } else {
1392                 u16 key_len = 0;
1393                 u16 i;
1394                 if (   priv->secinfo.wep_enabled
1395                     && !priv->secinfo.WPAenabled
1396                     && !priv->secinfo.WPA2enabled) {
1397                         /* WEP */
1398                         key_len = priv->wep_keys[0].len;
1399                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1400                                 "%s, WEP, len = %d\n", __func__, key_len * 8);
1401                         if (key_len == KEY_LEN_WEP_40) {
1402                                 priv->imode = BIT0 | BIT1;
1403                         }
1404                         else if (key_len == KEY_LEN_WEP_104) {
1405                                 priv->imode = BIT0 | BIT2;
1406                         }
1407                         else {
1408                                 RDA5890_ERRP("Invalide WEP Key length %d\n", key_len);
1409                                 ret = -EINVAL;
1410                                 goto out;
1411                         }
1412                 } else if (   !priv->secinfo.wep_enabled
1413                            && (priv->secinfo.WPAenabled ||
1414                                priv->secinfo.WPA2enabled)) {
1415                         /* WPA */
1416                         struct enc_key * pkey = NULL;
1417
1418                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1419                                 "%s, WPA cp:%x \n", __func__, priv->secinfo.cipther_type);
1420
1421                         if (   priv->wpa_mcast_key.len
1422                             && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
1423                                 pkey = &priv->wpa_mcast_key;
1424                         else if (   priv->wpa_unicast_key.len
1425                                  && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
1426                                 pkey = &priv->wpa_unicast_key;
1427
1428                         //priv->imode = assoc_bss->data.dot11i_info;
1429                         priv->imode = 0;
1430                         /* turn on security */
1431                         priv->imode |= (BIT0);
1432                         priv->imode &= ~(BIT3 | BIT4);
1433                         if (priv->secinfo.WPA2enabled)
1434                                 priv->imode |= (BIT4);
1435                         else if (priv->secinfo.WPAenabled)
1436                                 priv->imode |= (BIT3);
1437                         /* 
1438                          * we don't know the cipher type by now
1439                          * use dot11i_info to decide
1440                          * and use CCMP if possible
1441                          */
1442                         priv->imode &= ~(BIT5 | BIT6);
1443 #ifdef GET_SCAN_FROM_NETWORK_INFO
1444                         if (priv->secinfo.cipther_type & IW_AUTH_CIPHER_CCMP)
1445                                 priv->imode |= BIT5;
1446                         else if (priv->secinfo.cipther_type & IW_AUTH_CIPHER_TKIP)
1447                                 priv->imode |= BIT6;
1448 #else
1449                         if (assoc_bss->data.dot11i_info & (BIT5))
1450                                 priv->imode |= BIT5;
1451                         else if (assoc_bss->data.dot11i_info & (BIT6))
1452                                 priv->imode |= BIT6;
1453 #endif            
1454                 } else {
1455                         RDA5890_ERRP("WEP and WPA/WPA2 enabled simutanously\n");
1456                         ret = -EINVAL;
1457                         goto out;
1458                 }
1459         }
1460
1461         /* set authtype */
1462         if (priv->secinfo.auth_mode & IW_AUTH_ALG_OPEN_SYSTEM 
1463         || priv->secinfo.auth_mode & IW_AUTH_ALG_SHARED_KEY)
1464     {
1465
1466         if (priv->secinfo.auth_mode & IW_AUTH_ALG_OPEN_SYSTEM)
1467             {
1468                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1469                                 "%s, Open Auth, KEY_MGMT = %d, AUTH_ALG mode:%x\n", __func__, priv->secinfo.key_mgmt, priv->secinfo.auth_mode);
1470                         if (priv->secinfo.key_mgmt == 0x01) {
1471                                 /* for 802.1x, set auth type to 0x04 */
1472                                 priv->authtype = BIT3;                          
1473                         }
1474                         else 
1475                 {
1476                                 priv->authtype = BIT0;
1477                     }
1478             }
1479         else if(priv->secinfo.auth_mode & IW_AUTH_ALG_SHARED_KEY) 
1480             {
1481                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1482                                 "%s, Shared-Key Auth AUTH_ALG mode:%x \n", __func__, priv->secinfo.auth_mode);
1483                         priv->authtype = BIT1;
1484                 }
1485     }
1486     else if (priv->secinfo.auth_mode == IW_AUTH_ALG_WAPI) {
1487                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1488                         "%s, Shared-Key Auth\n", __func__);
1489                 priv->authtype = IW_AUTH_ALG_WAPI;
1490         }
1491         else if (priv->secinfo.auth_mode == IW_AUTH_ALG_LEAP) {
1492                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1493                         "%s, LEAP Auth, not supported\n", __func__);
1494                 ret = -EINVAL;
1495                 goto out;
1496         }
1497         else {
1498                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1499                         "%s, Unknown Auth\n", __func__);
1500                 ret = -EINVAL;
1501                 goto out;
1502         }
1503
1504 out:
1505         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>> \n", __func__);
1506         return ret;
1507 }
1508
1509 static struct bss_descriptor *get_bss_desc_from_scanlist(
1510                 struct rda5890_private *priv, unsigned char *ssid)
1511 {
1512         struct bss_descriptor *iter_bss;
1513         struct bss_descriptor *ret_bss = NULL;
1514         /* report all bss to upper layer */
1515         list_for_each_entry (iter_bss, &priv->network_list, list) {
1516 #ifdef  GET_SCAN_FROM_NETWORK_INFO
1517         if (strcmp(iter_bss->ssid, ssid) == 0) {
1518 #else
1519                 if (strcmp(iter_bss->data.ssid, ssid) == 0) {
1520 #endif            
1521                         ret_bss = iter_bss;
1522                         break;
1523                 }
1524         }
1525         return ret_bss;
1526 }
1527
1528 void rda5890_assoc_worker(struct work_struct *work)
1529 {
1530     static char old_imode = 0xff, old_bssid[6], assoc_count = 0;
1531         struct rda5890_private *priv = container_of(work, struct rda5890_private,
1532                 assoc_work.work);
1533         int ret = 0;
1534         struct bss_descriptor *assoc_bss;
1535
1536         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1537
1538         assoc_bss = get_bss_desc_from_scanlist(priv, priv->assoc_ssid);
1539         if (assoc_bss == NULL) {
1540                 RDA5890_ERRP("****fail to find bss in the scan list\n");
1541                 ret = -EINVAL;
1542                 goto out;
1543         }
1544
1545 #ifdef  GET_SCAN_FROM_NETWORK_INFO
1546         if(assoc_bss->rssi > 200)
1547         {
1548                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "assoc_bss rssi =%d > 200\n", assoc_bss->rssi);
1549             rda5890_rssi_up_to_200(priv);       
1550         }
1551 #else
1552         if(assoc_bss->data.rssi > 200)
1553         {
1554                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "assoc_bss rssi =%d > 200\n", assoc_bss->data.rssi);
1555             rda5890_rssi_up_to_200(priv);       
1556         }
1557 #endif    
1558 #ifdef GET_SCAN_FROM_NETWORK_INFO
1559     priv->curbssparams.channel = assoc_bss->channel; 
1560     memcpy(priv->curbssparams.bssid, assoc_bss->bssid, ETH_ALEN);
1561     memcpy(priv->curbssparams.ssid, assoc_bss->ssid,IW_ESSID_MAX_SIZE + 1);
1562 #else
1563     priv->curbssparams.channel = assoc_bss->data.channel; 
1564     memcpy(priv->curbssparams.bssid, assoc_bss->data.bssid, ETH_ALEN);
1565     memcpy(priv->curbssparams.ssid, assoc_bss->data.ssid,IW_ESSID_MAX_SIZE + 1);
1566 #endif
1567         ret = assoc_helper_secinfo(priv, assoc_bss);
1568         if (ret) {
1569                 RDA5890_ERRP("assoc_helper_secinfo fail, ret = %d\n", ret);
1570                 goto out;
1571         }
1572
1573     //if the bssid is same and the association is start then break out
1574     if((old_imode == priv->imode) && !memcmp(old_bssid, priv->assoc_bssid,6))
1575     {
1576         //WEP THE Second retry should change to shared key
1577         if((old_imode == 3 || old_imode ==  5) && assoc_count%2)  
1578         {
1579             priv->authtype = BIT1;
1580         }
1581         assoc_count ++;        
1582     }
1583     else
1584     {
1585         //save old bssid para
1586         old_imode = priv->imode;
1587         memcpy(old_bssid, priv->assoc_bssid, 6);
1588         assoc_count = 0;
1589     }
1590
1591     set_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags);    
1592     set_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags);
1593
1594     if((priv->imode == 3) || (priv->imode ==5))
1595         {
1596             if(assoc_count > 5)
1597             {
1598                 clear_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags);
1599                 clear_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags);
1600                 old_imode = 0xff;
1601             }
1602         }
1603     else
1604         {
1605             if(assoc_count)
1606             {
1607                 clear_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags);
1608                 clear_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags);
1609                 old_imode = 0xff;
1610             }
1611         }
1612     
1613     ret = rda5890_start_join(priv);
1614         if (ret) {
1615                 RDA5890_ERRP("rda5890_set_ssid fail, ret = %d\n", ret);
1616                 goto out;
1617         }
1618   
1619     if(test_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags))
1620     {       
1621         queue_delayed_work(priv->work_thread, &priv->assoc_work, 3*HZ);
1622     }
1623     
1624 out:
1625         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<< \n", __func__);
1626 }
1627
1628 static int rda5890_set_essid(struct net_device *dev, struct iw_request_info *info,
1629                 struct iw_point *dwrq, char *extra)
1630 {
1631         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1632         int ret = 0;
1633         u8 ssid[IW_ESSID_MAX_SIZE + 1];
1634         u8 ssid_len = 0;
1635         int in_ssid_len = dwrq->length;
1636
1637         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1638
1639         /* Check the size of the string */
1640         if (in_ssid_len > IW_ESSID_MAX_SIZE) {
1641                 ret = -E2BIG;
1642                 goto out;
1643         }
1644     
1645         memset(&ssid, 0, sizeof(ssid));
1646
1647         if (!dwrq->flags || !in_ssid_len) {
1648                 /* "any" SSID requested; leave SSID blank */
1649         } else {
1650                 /* Specific SSID requested */
1651                 memcpy(&ssid, extra, in_ssid_len);
1652                 ssid[in_ssid_len] = '\0';
1653                 ssid_len = in_ssid_len;
1654         }
1655
1656         if (!ssid_len) {
1657                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1658                         "requested any SSID\n");
1659         } else {
1660                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
1661                         "requested SSID len = %d ssid:%s\n",
1662                         ssid_len, ssid);
1663         }
1664
1665     if(ssid_len)
1666     {
1667         memcpy(&priv->assoc_ssid[0], ssid, sizeof(ssid));
1668         priv->assoc_ssid_len = ssid_len;
1669     }
1670
1671     if(!test_bit(ASSOC_FLAG_SSID, &priv->assoc_flags))
1672         goto out;
1673
1674     if(!test_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags))
1675     {
1676         if(ssid_len)
1677         {
1678                 cancel_delayed_work(&priv->assoc_work);
1679                 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ/2);
1680         }
1681     }
1682
1683 out:
1684         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1685         return 0;
1686 }
1687
1688 /**
1689  *  @brief Connect to the AP or Ad-hoc Network with specific bssid
1690  *
1691  *  @param dev          A pointer to net_device structure
1692  *  @param info         A pointer to iw_request_info structure
1693  *  @param awrq         A pointer to iw_param structure
1694  *  @param extra        A pointer to extra data buf
1695  *  @return             0 --success, otherwise fail
1696  */
1697 static int rda5890_set_wap(struct net_device *dev, struct iw_request_info *info,
1698                 struct sockaddr *awrq, char *extra)
1699 {
1700     unsigned char * ap_addr = NULL;
1701         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1702
1703         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1704
1705     ap_addr = awrq->sa_data;
1706     if(!test_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags)
1707         && !is_zero_eth_addr(ap_addr))
1708     {
1709         cancel_delayed_work(&priv->assoc_work);
1710         queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ/2);
1711         set_bit(ASSOC_FLAG_SSID, &priv->assoc_flags);
1712         memcpy(priv->assoc_bssid, ap_addr, 6);
1713         printk("rda5890_set_wap addr is not null \n");
1714     }
1715
1716     if(is_zero_eth_addr(ap_addr))
1717     {
1718         clear_bit(ASSOC_FLAG_SSID, &priv->assoc_flags);
1719         disable_wep( priv);
1720         disable_wpa(priv);
1721     }
1722         
1723
1724         RDA5890_ERRP("%s <<< \n connect mac: %2x:%2x:%2x:%2x:%2x:%2x \n", __func__, 
1725          ap_addr[0],ap_addr[1],ap_addr[2],ap_addr[3],ap_addr[4],ap_addr[5]);
1726     
1727         return 0;
1728 }
1729
1730 static inline char *translate_scan(struct rda5890_private *priv,
1731                                             struct iw_request_info *info,
1732                                             char *start, char *stop,
1733                                             struct bss_descriptor *bss_desc)
1734 {
1735 #ifndef GET_SCAN_FROM_NETWORK_INFO
1736         struct iw_event iwe;    /* Temporary buffer */
1737         u8 snr;
1738         struct rda5890_bss_descriptor *bss = &bss_desc->data;
1739
1740         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1741                 "translate_scan, ssid = %s\n", bss->ssid);
1742
1743         /* First entry *MUST* be the BSSID */
1744         iwe.cmd = SIOCGIWAP;
1745         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1746         memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
1747         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
1748
1749         /* SSID */
1750         iwe.cmd = SIOCGIWESSID;
1751         iwe.u.data.flags = 1;
1752         iwe.u.data.length = strlen(bss->ssid);
1753         start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1754
1755         /* Mode */
1756         iwe.cmd = SIOCGIWMODE;
1757         //iwe.u.mode = bss->mode;
1758         iwe.u.mode = IW_MODE_INFRA;
1759         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
1760
1761         /* Frequency */
1762         iwe.cmd = SIOCGIWFREQ;
1763         iwe.u.freq.m = (2412 + 5 * (bss->channel - 1)) * 100000;
1764         iwe.u.freq.e = 1;
1765         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
1766
1767         /* Add quality statistics */
1768         iwe.cmd = IWEVQUAL;
1769         iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
1770         iwe.u.qual.level = bss->rssi > 127? bss->rssi - 271: bss->rssi - 15;
1771
1772         snr = iwe.u.qual.level - RDA5890_NF_DEFAULT_SCAN_VALUE;
1773         iwe.u.qual.qual =
1774                 (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - snr) *
1775                  (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - snr))) /
1776                 (RSSI_DIFF * RSSI_DIFF);
1777         if (iwe.u.qual.qual > 100)
1778                 iwe.u.qual.qual = 100;
1779         iwe.u.qual.noise = RDA5890_NF_DEFAULT_SCAN_VALUE;
1780         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
1781
1782         /* Add encryption capability */
1783         iwe.cmd = SIOCGIWENCODE;
1784         if (bss->dot11i_info & BIT0) {
1785                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1786         } else {
1787                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1788         }
1789         iwe.u.data.length = 0;
1790         start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1791
1792 #if 0
1793         current_val = start + iwe_stream_lcp_len(info);
1794
1795         iwe.cmd = SIOCGIWRATE;
1796         iwe.u.bitrate.fixed = 0;
1797         iwe.u.bitrate.disabled = 0;
1798         iwe.u.bitrate.value = 0;
1799
1800         for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
1801                 /* Bit rate given in 500 kb/s units */
1802                 iwe.u.bitrate.value = bss->rates[j] * 500000;
1803                 current_val = iwe_stream_add_value(info, start, current_val,
1804                                                    stop, &iwe, IW_EV_PARAM_LEN);
1805         }
1806         if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
1807             && !lbs_ssid_cmp(priv->curbssparams.ssid,
1808                              priv->curbssparams.ssid_len,
1809                              bss->ssid, bss->ssid_len)) {
1810                 iwe.u.bitrate.value = 22 * 500000;
1811                 current_val = iwe_stream_add_value(info, start, current_val,
1812                                                    stop, &iwe, IW_EV_PARAM_LEN);
1813         }
1814         /* Check if we added any event */
1815         if ((current_val - start) > iwe_stream_lcp_len(info))
1816                 start = current_val;
1817 #endif
1818
1819         memset(&iwe, 0, sizeof(iwe));
1820         if (bss_desc->wpa_ie_len) {
1821                 char buf[MAX_WPA_IE_LEN];
1822
1823                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1824                         "translate_scan, wpa_ie, len %d\n", bss_desc->wpa_ie_len);
1825                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1826                         "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
1827                         bss_desc->wpa_ie[0], bss_desc->wpa_ie[1], 
1828                         bss_desc->wpa_ie[2], bss_desc->wpa_ie[3], 
1829                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 4], 
1830                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 3],
1831                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 2], 
1832                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 1]);
1833
1834                 memcpy(buf, bss_desc->wpa_ie, bss_desc->wpa_ie_len);
1835                 iwe.cmd = IWEVGENIE;
1836                 iwe.u.data.length = bss_desc->wpa_ie_len;
1837                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1838         }
1839
1840         memset(&iwe, 0, sizeof(iwe));
1841         if (bss_desc->rsn_ie_len) {
1842                 char buf[MAX_WPA_IE_LEN];
1843
1844                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1845                         "translate_scan, rsn_ie, len %d\n", bss_desc->rsn_ie_len);
1846                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1847                         "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
1848                         bss_desc->rsn_ie[0], bss_desc->rsn_ie[1], 
1849                         bss_desc->rsn_ie[2], bss_desc->rsn_ie[3], 
1850                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 4], 
1851                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 3],
1852                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 2], 
1853                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 1]);
1854
1855                 memcpy(buf, bss_desc->rsn_ie, bss_desc->rsn_ie_len);
1856                 iwe.cmd = IWEVGENIE;
1857                 iwe.u.data.length = bss_desc->rsn_ie_len;
1858                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1859         }
1860
1861         return start;
1862 #else
1863         struct iw_event iwe;    /* Temporary buffer */
1864         u8 snr;
1865         struct bss_descriptor *bss = bss_desc;
1866
1867         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1868                 "translate_scan, ssid = %s ssi=%d ssid_len=%d \n", bss->ssid, bss->rssi, bss->ssid_len);
1869
1870         /* First entry *MUST* be the BSSID */
1871         iwe.cmd = SIOCGIWAP;
1872         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1873         memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
1874         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
1875
1876         /* SSID */
1877         iwe.cmd = SIOCGIWESSID;
1878         iwe.u.data.flags = 1;
1879         iwe.u.data.length = bss->ssid_len;
1880         start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1881
1882         /* Mode */
1883         iwe.cmd = SIOCGIWMODE;
1884         iwe.u.mode = bss->mode;
1885         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
1886
1887         /* Frequency */
1888         iwe.cmd = SIOCGIWFREQ;
1889         iwe.u.freq.m = (2412 + 5 * (bss->channel - 1)) * 100000;
1890         iwe.u.freq.e = 1;
1891         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
1892
1893         /* Add quality statistics */
1894         iwe.cmd = IWEVQUAL;
1895         iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
1896         iwe.u.qual.level = bss->rssi > 127? bss->rssi - 271: bss->rssi - 15;
1897
1898         snr = iwe.u.qual.level - RDA5890_NF_DEFAULT_SCAN_VALUE;
1899         iwe.u.qual.qual =
1900                 (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - snr) *
1901                  (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - snr))) /
1902                 (RSSI_DIFF * RSSI_DIFF);
1903         if (iwe.u.qual.qual > 100)
1904                 iwe.u.qual.qual = 100;
1905         iwe.u.qual.noise = RDA5890_NF_DEFAULT_SCAN_VALUE;
1906         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
1907
1908         /* Add encryption capability */
1909         iwe.cmd = SIOCGIWENCODE;
1910         if (bss->capability & WLAN_CAPABILITY_PRIVACY) {
1911                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1912         } else {
1913                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1914         }
1915         iwe.u.data.length = 0;
1916         start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1917
1918         memset(&iwe, 0, sizeof(iwe));
1919         if (bss_desc->wpa_ie_len && !bss_desc->wapi_ie_len) {
1920                 char buf[MAX_WPA_IE_LEN];
1921
1922                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1923                         "translate_scan, wpa_ie, len %d\n", bss_desc->wpa_ie_len);
1924                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1925                         "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
1926                         bss_desc->wpa_ie[0], bss_desc->wpa_ie[1], 
1927                         bss_desc->wpa_ie[2], bss_desc->wpa_ie[3], 
1928                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 4], 
1929                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 3],
1930                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 2], 
1931                         bss_desc->wpa_ie[bss_desc->wpa_ie_len - 1]);
1932
1933                 memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
1934                 iwe.cmd = IWEVGENIE;
1935                 iwe.u.data.length = bss_desc->wpa_ie_len;
1936                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1937         }
1938
1939         memset(&iwe, 0, sizeof(iwe));
1940         if (bss_desc->rsn_ie_len && !bss_desc->wapi_ie_len) {
1941                 char buf[MAX_WPA_IE_LEN];
1942
1943                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1944                         "translate_scan, rsn_ie, len %d\n", bss_desc->rsn_ie_len);
1945                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1946                         "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
1947                         bss_desc->rsn_ie[0], bss_desc->rsn_ie[1], 
1948                         bss_desc->rsn_ie[2], bss_desc->rsn_ie[3], 
1949                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 4], 
1950                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 3],
1951                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 2], 
1952                         bss_desc->rsn_ie[bss_desc->rsn_ie_len - 1]);
1953
1954                 memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
1955                 iwe.cmd = IWEVGENIE;
1956                 iwe.u.data.length = bss_desc->rsn_ie_len;
1957                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1958         }
1959
1960         memset(&iwe, 0, sizeof(iwe));
1961         if (bss_desc->wapi_ie_len) {
1962                 char buf[100];
1963
1964                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1965                         "translate_scan, wapi_len %d\n", bss_desc->wapi_ie_len);
1966                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1967                         "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
1968                         bss_desc->wapi_ie[0], bss_desc->wapi_ie[1], 
1969                         bss_desc->wapi_ie[2], bss_desc->wapi_ie[3], 
1970                         bss_desc->wapi_ie[bss_desc->wapi_ie_len - 4], 
1971                         bss_desc->wapi_ie[bss_desc->wapi_ie_len - 3],
1972                         bss_desc->wapi_ie[bss_desc->wapi_ie_len - 2], 
1973                         bss_desc->wapi_ie[bss_desc->wapi_ie_len - 1]);
1974
1975                 memcpy(buf, bss->wapi_ie, bss->wapi_ie_len);
1976                 iwe.cmd = IWEVGENIE;
1977                 iwe.u.data.length = bss_desc->wapi_ie_len;
1978                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1979         }
1980
1981         return start;
1982 #endif
1983 }
1984
1985 int is_same_network(struct bss_descriptor *src,
1986                                   struct bss_descriptor *dst)
1987 {
1988         /* A network is only a duplicate if the channel, BSSID, and ESSID
1989          * all match.  We treat all <hidden> with the same BSSID and channel
1990          * as one network */
1991 #ifndef GET_SCAN_FROM_NETWORK_INFO
1992         return ((src->data.channel == dst->data.channel) &&
1993                 !compare_ether_addr(src->data.bssid, dst->data.bssid) &&
1994                 !memcmp(src->data.ssid, dst->data.ssid, IW_ESSID_MAX_SIZE));
1995 #else
1996         return ((src->channel == dst->channel) &&
1997                 !compare_ether_addr(src->bssid, dst->bssid) &&
1998                 !memcmp(src->ssid, dst->ssid, IW_ESSID_MAX_SIZE));
1999 #endif
2000 }
2001
2002 void clear_bss_descriptor(struct bss_descriptor *bss)
2003 {
2004         /* Don't blow away ->list, just BSS data */
2005         memset(bss, 0, offsetof(struct bss_descriptor, list));
2006 }
2007
2008 static void dump_bss_desc(struct rda5890_bss_descriptor *bss_desc)
2009 {
2010         RDA5890_DBGP("########## dump bss ##########\n");
2011         RDA5890_DBGP("ssid = %s\n", bss_desc->ssid);
2012         RDA5890_DBGP("bss_type = %d\n", bss_desc->bss_type);
2013         RDA5890_DBGP("channel = %d\n", bss_desc->channel);
2014         RDA5890_DBGP("dot11i_info = 0x%02x\n", bss_desc->dot11i_info);
2015         RDA5890_DBGP("bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", 
2016                 bss_desc->bssid[0], bss_desc->bssid[1], bss_desc->bssid[2], 
2017                 bss_desc->bssid[3], bss_desc->bssid[4], bss_desc->bssid[5]);
2018         RDA5890_DBGP("rssi = %d\n", (char)bss_desc->rssi);
2019         RDA5890_DBGP("auth_info = 0x%02x\n", bss_desc->auth_info);
2020         RDA5890_DBGP("rsn_cap = 0x%04x\n",
2021                 (bss_desc->rsn_cap[1] << 8) | bss_desc->rsn_cap[0]);
2022         RDA5890_DBGP("########## dump bss ##########\n");
2023 }
2024
2025 /* Element Ids used in Management frames in 802.11i mode */
2026 typedef enum{ IRSNELEMENT = 48,  /* RSN Information Element  */
2027               IWPAELEMENT = 221 /* WPA Information Element  */
2028 }ELEMENTID_11I_T;
2029
2030 /* CIPHER set for RSN or WPA element  */
2031 typedef enum { CIPHER_TYPE_USE_GROUP_SET  = 0,
2032                CIPHER_TYPE_WEP40          = 1,
2033                CIPHER_TYPE_TKIP           = 2,
2034                CIPHER_TYPE_CCMP           = 4,
2035                CIPHER_TYPE_WEP104         = 5
2036 } CIPHER_TYPE_T;
2037
2038 unsigned char oui_rsn[3] = {0x00, 0x0F, 0xAC};
2039 unsigned char oui_wpa[3] = {0x00, 0x50, 0xf2};
2040
2041 static void fill_rsn_wpa_ie(unsigned char *data, unsigned char ie_type,
2042                 struct rda5890_bss_descriptor *bss, size_t *len)
2043 {
2044         unsigned char index = 0;
2045         unsigned char *oui;
2046
2047         if (ie_type == IRSNELEMENT) {
2048                 oui = &oui_rsn[0];
2049
2050                 /* Set RSN Information Element element ID */
2051                 data[index] = IRSNELEMENT;
2052                 index += 2;
2053         }
2054         else {
2055                 oui = &oui_wpa[0];
2056
2057                 /* Set WPA Information Element element ID */
2058                 data[index] = IWPAELEMENT;
2059                 index += 2;
2060
2061                 /* Copy OUI */
2062                 memcpy(&data[index], oui, 3);
2063                 index += 3;
2064                 data[index++] = 0x01;
2065         }
2066
2067         /* Set the version of RSN Element to 1 */
2068         data[index++] = 1;
2069         data[index++] = 0;
2070
2071         /* Set Group Cipher Suite */
2072         memcpy(&data[index], oui, 3);
2073         index += 3;
2074         if ((bss->dot11i_info & BIT5) && !(bss->dot11i_info & BIT6)) {
2075                 /* only CCMP and !TKIP, use CCMP, otherwise, always TKIP */
2076                 data[index++] = CIPHER_TYPE_CCMP;
2077         }
2078         else {
2079                 data[index++] = CIPHER_TYPE_TKIP;
2080         }
2081
2082         /* Set Pairwise cipher Suite */
2083         if ((bss->dot11i_info & BIT5) && (bss->dot11i_info & BIT6)) {
2084                 /* both CCMP and TKIP */
2085                 data[index++] = 2;
2086                 data[index++] = 0;
2087
2088                 /* Check BIT7 to determine who goes first */
2089                 if (bss->dot11i_info & BIT7) {
2090                         /* BIT7 is 1 => CCMP goes first */
2091                         memcpy(&data[index], oui, 3);
2092                         index += 3;
2093                         data[index++] = CIPHER_TYPE_CCMP;
2094
2095                         memcpy(&data[index], oui, 3);
2096                         index += 3;
2097                         data[index++] = CIPHER_TYPE_TKIP;
2098                 }
2099                 else {
2100                 /* BIT7 is 0 => TKIP goes first */
2101                         memcpy(&data[index], oui, 3);
2102                         index += 3;
2103                         data[index++] = CIPHER_TYPE_TKIP;
2104
2105                         memcpy(&data[index], oui, 3);
2106                         index += 3;
2107                         data[index++] = CIPHER_TYPE_CCMP;
2108                 }
2109         }
2110         else if ((bss->dot11i_info & BIT5) && !(bss->dot11i_info & BIT6)) {
2111                 /* CCMP and !TKIP */
2112                 data[index++] = 1;
2113                 data[index++] = 0;
2114
2115                 memcpy(&data[index], oui, 3);
2116                 index += 3;
2117                 data[index++] = CIPHER_TYPE_CCMP;
2118         }
2119         else if (!(bss->dot11i_info & BIT5) && (bss->dot11i_info & BIT6)) {
2120                 /* !CCMP and TKIP */
2121                 data[index++] = 1;
2122                 data[index++] = 0;
2123
2124                 memcpy(&data[index], oui, 3);
2125                 index += 3;
2126                 data[index++] = CIPHER_TYPE_TKIP;
2127         }
2128         else {
2129                 /* neither CCMP nor TKIP, use TKIP for WPA, and CCMP for RSN */
2130                 data[index++] = 1;
2131                 data[index++] = 0;
2132
2133                 memcpy(&data[index], oui, 3);
2134                 index += 3;
2135                 if (ie_type == IRSNELEMENT) {
2136                         data[index++] = CIPHER_TYPE_CCMP;
2137                 }
2138                 else {
2139                         data[index++] = CIPHER_TYPE_TKIP;
2140                 }
2141         }
2142
2143         /* Set Authentication Suite */
2144         if ((bss->auth_info & 0x01) && (bss->auth_info & 0x02)) {
2145                 /* both 802.1X and PSK */
2146                 data[index++] = 2;
2147                 data[index++] = 0;
2148
2149                 memcpy(&data[index], oui, 3);
2150                 index += 3;
2151                 data[index++] = 0x01;
2152
2153                 memcpy(&data[index], oui, 3);
2154                 index += 3;
2155                 data[index++] = 0x02;
2156         }
2157         else if ((bss->auth_info & 0x01) && !(bss->auth_info & 0x02)) {
2158                 /* 802.1X and !PSK */
2159                 data[index++] = 1;
2160                 data[index++] = 0;
2161
2162                 memcpy(&data[index], oui, 3);
2163                 index += 3;
2164                 data[index++] = 0x01;
2165         }
2166         else if (!(bss->auth_info & 0x01) && (bss->auth_info & 0x02)) {
2167                 /* !802.1X and PSK */
2168                 data[index++] = 1;
2169                 data[index++] = 0;
2170
2171                 memcpy(&data[index], oui, 3);
2172                 index += 3;
2173                 data[index++] = 0x02;
2174         }
2175         else {
2176                 /* neither 802.1X nor PSK, use 802.1X */
2177                 data[index++] = 1;
2178                 data[index++] = 0;
2179
2180                 memcpy(&data[index], oui, 3);
2181                 index += 3;
2182                 data[index++] = 0x01;
2183         }
2184
2185         /* The RSN Capabilities, for RSN IE only */
2186         if (ie_type == IRSNELEMENT) {
2187                 data[index++] = bss->rsn_cap[0];
2188                 data[index++] = bss->rsn_cap[1];
2189         }
2190
2191         /* Set the length of the RSN Information Element */
2192         data[1] = (index - 2);
2193
2194         /* Return the Extended Supported Rates element length */
2195         *len = (size_t)index;
2196 }
2197
2198 /* reconstruct wpa/rsn ie from the dot11i_info and auth_info fields */
2199 /* TODO: 
2200  * assuming RSN and WPA are using same cipher suite, no space to store each
2201  * assuming grp and unicast are using same cipher suite
2202  */
2203 static void reconstruct_rsn_wpa_ie(struct bss_descriptor *bss_desc)
2204 {
2205         bss_desc->wpa_ie_len = 0;
2206         bss_desc->rsn_ie_len = 0;
2207         
2208         if (bss_desc->data.dot11i_info & BIT0) {
2209                 if (bss_desc->data.dot11i_info & BIT3) {
2210                         /* WPA IE present */
2211                         fill_rsn_wpa_ie(&bss_desc->wpa_ie[0], IWPAELEMENT, 
2212                                 &bss_desc->data, &bss_desc->wpa_ie_len);
2213                 }
2214
2215                 if (bss_desc->data.dot11i_info & BIT4) {
2216                         /* RSN IE present */
2217                         fill_rsn_wpa_ie(&bss_desc->rsn_ie[0], IRSNELEMENT, 
2218                                 &bss_desc->data, &bss_desc->rsn_ie_len);                        
2219                 }
2220         }
2221         else {
2222                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2223                         "form_rsn_ie, NO SEC\n");
2224         }
2225 }
2226
2227 void rda5890_scan_worker(struct work_struct *work)
2228 {
2229         struct rda5890_private *priv = container_of(work, struct rda5890_private,
2230                 scan_work.work);
2231         int ret = 0;
2232         struct rda5890_bss_descriptor bss_desc[RDA5890_MAX_NETWORK_NUM];
2233         int bss_index, bss_count;
2234         struct bss_descriptor *iter_bss;
2235         union iwreq_data wrqu;
2236     unsigned char fist_send = 0;
2237
2238         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2239
2240     if(test_bit(ASSOC_FLAG_ASSOC_START, &priv->assoc_flags)
2241         || test_bit(ASSOC_FLAG_WLAN_CONNECTING, &priv->assoc_flags))
2242     {
2243         cancel_delayed_work(&priv->scan_work);
2244         queue_delayed_work(priv->work_thread, &priv->scan_work, HZ/2);
2245         return;
2246     }
2247
2248         priv->scan_running = 1;
2249     
2250 #ifdef WIFI_UNLOCK_SYSTEM
2251     rda5990_wakeLock();
2252 #endif
2253
2254 #ifdef GET_SCAN_FROM_NETWORK_INFO
2255         ret = rda5890_start_scan_enable_network_info(priv);
2256 #else
2257     ret = rda5890_start_scan(priv);
2258 #endif 
2259         if (ret) {
2260                 RDA5890_ERRP("rda5890_start_scan fail, ret = %d\n", ret);
2261                 goto out;
2262         }
2263
2264         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "SCANNING ...\n");
2265         /* TODO: delay 2 sec for now, need to be put into a worker */
2266         rda5890_shedule_timeout(1500);
2267
2268 #ifndef GET_SCAN_FROM_NETWORK_INFO
2269 retry:
2270         bss_count = rda5890_get_scan_results(priv, bss_desc);
2271
2272     fist_send = (bss_count >> 8) & 0xff;
2273     bss_count &= 0xff;
2274         if (bss_count < 0 || bss_count >= RDA5890_MAX_NETWORK_NUM) {
2275                 RDA5890_ERRP("rda5890_get_scan_results fail, ret = %d\n", bss_count);
2276                 goto out;
2277         }
2278         RDA5890_DBGLAP(RDA5890_DA_WID, RDA5890_DL_TRACE,
2279                 "Get Scan Result, count = %d, fist_send= %d \n", bss_count, fist_send);
2280
2281         /* add scaned bss into list */
2282         for(bss_index = 0; bss_index < bss_count; bss_index++) {
2283                 struct bss_descriptor new;
2284                 struct bss_descriptor *found = NULL;
2285                 struct bss_descriptor *oldest = NULL;
2286
2287         if (RDA5890_DBGLA(RDA5890_DA_WEXT, RDA5890_DL_TRACE))
2288                 dump_bss_desc(&bss_desc[bss_index]);
2289
2290                 memcpy(&new.data, &bss_desc[bss_index], sizeof(struct rda5890_bss_descriptor));
2291                 reconstruct_rsn_wpa_ie(&new);
2292                 new.last_scanned = jiffies;
2293
2294                 /* Try to find this bss in the scan table */
2295                 list_for_each_entry (iter_bss, &priv->network_list, list) {
2296                         if (is_same_network(iter_bss, &new)) {
2297                                 found = iter_bss;
2298                                 break;
2299                         }
2300
2301                         if ((oldest == NULL) ||
2302                             (iter_bss->last_scanned < oldest->last_scanned))
2303                                 oldest = iter_bss;
2304                 }
2305
2306                 if (found) {
2307                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2308                                 "FOUND SAME %s, update\n", found->data.ssid);
2309                         /* found, clear it */
2310                         clear_bss_descriptor(found);
2311                 } else if (!list_empty(&priv->network_free_list)) {
2312                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2313                                 "FOUND NEW %s, add\n", new.data.ssid);
2314                         /* Pull one from the free list */
2315                         found = list_entry(priv->network_free_list.next,
2316                                            struct bss_descriptor, list);
2317                         list_move_tail(&found->list, &priv->network_list);
2318                 } else if (oldest) {
2319                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2320                                 "FOUND NEW %s, no space, replace oldest %s\n", 
2321                                 new.data.ssid, oldest->data.ssid);
2322                         /* If there are no more slots, expire the oldest */
2323                         found = oldest;
2324                         clear_bss_descriptor(found);
2325                         list_move_tail(&found->list, &priv->network_list);
2326                 } else {
2327                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2328                                 "FOUND NEW but no space to store\n");
2329                 }
2330
2331                 /* Copy the locally created newbssentry to the scan table */
2332                 memcpy(found, &new, offsetof(struct bss_descriptor, list));
2333         }
2334
2335     if(bss_count >= 5 && !fist_send)
2336         goto retry;
2337
2338 #else
2339     //do noting in get network info modle
2340
2341 #endif
2342
2343 out:
2344     priv->scan_running = 0;
2345     memset(&wrqu, 0, sizeof(union iwreq_data));
2346     wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
2347
2348         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2349
2350 #ifdef WIFI_UNLOCK_SYSTEM
2351     rda5990_wakeUnlock();
2352 #endif
2353 }
2354
2355 /**
2356  *  @brief Handle Scan Network ioctl
2357  *
2358  *  @param dev          A pointer to net_device structure
2359  *  @param info         A pointer to iw_request_info structure
2360  *  @param vwrq         A pointer to iw_param structure
2361  *  @param extra        A pointer to extra data buf
2362  *
2363  *  @return             0 --success, otherwise fail
2364  */
2365 int rda5890_set_scan(struct net_device *dev, struct iw_request_info *info,
2366                  union iwreq_data *wrqu, char *extra)
2367 {
2368         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
2369
2370         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2371
2372         if (priv->scan_running)
2373                 goto out;
2374
2375
2376     cancel_delayed_work(&priv->scan_work);
2377     queue_delayed_work(priv->work_thread, &priv->scan_work, HZ/50);
2378
2379 out:
2380         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2381         return 0;
2382 }
2383
2384 /**
2385  *  @brief  Handle Retrieve scan table ioctl
2386  *
2387  *  @param dev          A pointer to net_device structure
2388  *  @param info         A pointer to iw_request_info structure
2389  *  @param dwrq         A pointer to iw_point structure
2390  *  @param extra        A pointer to extra data buf
2391  *
2392  *  @return             0 --success, otherwise fail
2393  */
2394 int rda5890_get_scan(struct net_device *dev, struct iw_request_info *info,
2395                  struct iw_point *dwrq, char *extra)
2396 {
2397 #define SCAN_ITEM_SIZE 128
2398         struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
2399         int ret = 0;
2400         struct bss_descriptor *iter_bss;
2401         struct bss_descriptor *safe;
2402         char *ev = extra;
2403         char *stop = ev + dwrq->length;
2404
2405         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2406
2407         /* iwlist should wait until the current scan is finished */
2408         if (priv->scan_running) {
2409                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2410                         "Scan is Running, return AGAIN\n");
2411                 return -EAGAIN;
2412         }
2413
2414         /* report all bss to upper layer */
2415         list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
2416                 char *next_ev;
2417                 unsigned long stale_time;
2418
2419                 if (stop - ev < SCAN_ITEM_SIZE) {
2420                         ret = -E2BIG;
2421                         break;
2422                 }
2423
2424                 /* Prune old an old scan result */
2425                 stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
2426                 if (time_after(jiffies, stale_time)) {
2427                         list_move_tail(&iter_bss->list, &priv->network_free_list);
2428 #ifdef GET_SCAN_FROM_NETWORK_INFO              
2429                         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2430                                 "Prune Old Bss %s\n", iter_bss->ssid);
2431 #else
2432             RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2433                                 "Prune Old Bss %s\n", iter_bss->ssid);
2434 #endif
2435                         clear_bss_descriptor(iter_bss);
2436                         continue;
2437                 }
2438
2439                 /* Translate to WE format this entry */
2440                 next_ev = translate_scan(priv, info, ev, stop, iter_bss);
2441 #ifdef GET_SCAN_FROM_NETWORK_INFO        
2442                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2443                         "Report BSS %s\n", iter_bss->ssid);
2444 #else
2445         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2446             "Report BSS %s\n", iter_bss->data.ssid);
2447 #endif
2448                 if (next_ev == NULL)
2449                         continue;
2450                 ev = next_ev;
2451         }
2452         dwrq->length = (ev - extra);
2453         dwrq->flags = 0;
2454
2455         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2456         return ret;
2457 }
2458
2459 int rda5890_set_mlme(struct net_device *dev,
2460                                   struct iw_request_info *info,
2461                                   union iwreq_data *wrqu, char *extra)
2462 {
2463         //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
2464         struct iw_mlme *mlme = (struct iw_mlme *)extra;
2465         int ret = 0;
2466
2467         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2468
2469         switch (mlme->cmd) {
2470         case IW_MLME_DEAUTH:
2471                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2472                         "DEAUTH\n");
2473                 /* silently ignore */
2474                 break;
2475
2476         case IW_MLME_DISASSOC:
2477         {
2478                 unsigned char ssid[6];
2479                 memset(ssid, 0, 6);
2480                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2481                         "DISASSOC\n");
2482                 /* silently ignore */
2483                 rda5890_set_ssid((struct rda5890_private *)netdev_priv(dev) , ssid, 6);
2484         }
2485                 break;
2486         default:
2487                 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, 
2488                         "Not supported cmd %d\n", mlme->cmd);
2489                 ret = -EOPNOTSUPP;
2490         }
2491
2492         RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2493         return ret;
2494 }
2495
2496 /*
2497  * iwconfig settable callbacks
2498  */
2499 static const iw_handler rda5890_wext_handler[] = {
2500         (iw_handler) NULL,      /* SIOCSIWCOMMIT */
2501         (iw_handler) rda5890_get_name,  /* SIOCGIWNAME */
2502         (iw_handler) NULL,      /* SIOCSIWNWID */
2503         (iw_handler) NULL,      /* SIOCGIWNWID */
2504         (iw_handler) rda5890_set_freq,  /* SIOCSIWFREQ */
2505         (iw_handler) rda5890_get_freq,  /* SIOCGIWFREQ */
2506         (iw_handler) rda5890_set_mode,  /* SIOCSIWMODE */
2507         (iw_handler) rda5890_get_mode,  /* SIOCGIWMODE */
2508         (iw_handler) NULL,      /* SIOCSIWSENS */
2509         (iw_handler) NULL,      /* SIOCGIWSENS */
2510         (iw_handler) NULL,      /* SIOCSIWRANGE */
2511         (iw_handler) rda5890_get_range, /* SIOCGIWRANGE */
2512         (iw_handler) NULL,      /* SIOCSIWPRIV */
2513         (iw_handler) NULL,      /* SIOCGIWPRIV */
2514         (iw_handler) NULL,      /* SIOCSIWSTATS */
2515         (iw_handler) NULL,      /* SIOCGIWSTATS */
2516         (iw_handler) NULL,      /* SIOCSIWSPY */
2517         (iw_handler) NULL,      /* SIOCGIWSPY */
2518         (iw_handler) NULL,      /* SIOCSIWTHRSPY */
2519         (iw_handler) NULL,      /* SIOCGIWTHRSPY */
2520         (iw_handler) rda5890_set_wap,   /* SIOCSIWAP */
2521         (iw_handler) rda5890_get_wap,   /* SIOCGIWAP */
2522         (iw_handler) rda5890_set_mlme,  /* SIOCSIWMLME */
2523         (iw_handler) NULL,      /* SIOCGIWAPLIST - deprecated */
2524         (iw_handler) rda5890_set_scan,  /* SIOCSIWSCAN */
2525         (iw_handler) rda5890_get_scan,  /* SIOCGIWSCAN */
2526         (iw_handler) rda5890_set_essid, /* SIOCSIWESSID */
2527         (iw_handler) rda5890_get_essid, /* SIOCGIWESSID */
2528         (iw_handler) rda5890_set_nick,  /* SIOCSIWNICKN */
2529         (iw_handler) rda5890_get_nick,  /* SIOCGIWNICKN */
2530         (iw_handler) NULL,      /* -- hole -- */
2531         (iw_handler) NULL,      /* -- hole -- */
2532         (iw_handler) rda5890_set_rate,  /* SIOCSIWRATE */
2533         (iw_handler) rda5890_get_rate,  /* SIOCGIWRATE */
2534         (iw_handler) rda5890_set_rts,   /* SIOCSIWRTS */
2535         (iw_handler) rda5890_get_rts,   /* SIOCGIWRTS */
2536         (iw_handler) rda5890_set_frag,  /* SIOCSIWFRAG */
2537         (iw_handler) rda5890_get_frag,  /* SIOCGIWFRAG */
2538         (iw_handler) rda5890_set_txpow, /* SIOCSIWTXPOW */
2539         (iw_handler) rda5890_get_txpow, /* SIOCGIWTXPOW */
2540         (iw_handler) rda5890_set_retry, /* SIOCSIWRETRY */
2541         (iw_handler) rda5890_get_retry, /* SIOCGIWRETRY */
2542         (iw_handler) rda5890_set_encode,        /* SIOCSIWENCODE */
2543         (iw_handler) rda5890_get_encode,        /* SIOCGIWENCODE */
2544         (iw_handler) rda5890_set_power, /* SIOCSIWPOWER */
2545         (iw_handler) rda5890_get_power, /* SIOCGIWPOWER */
2546         (iw_handler) NULL,      /* -- hole -- */
2547         (iw_handler) NULL,      /* -- hole -- */
2548         (iw_handler) rda5890_set_genie, /* SIOCSIWGENIE */
2549         (iw_handler) rda5890_get_genie, /* SIOCGIWGENIE */
2550         (iw_handler) rda5890_set_auth,  /* SIOCSIWAUTH */
2551         (iw_handler) rda5890_get_auth,  /* SIOCGIWAUTH */
2552         (iw_handler) rda5890_set_encodeext,/* SIOCSIWENCODEEXT */
2553         (iw_handler) rda5890_get_encodeext,/* SIOCGIWENCODEEXT */
2554         (iw_handler) rda5890_set_pmksa,         /* SIOCSIWPMKSA */
2555 };
2556
2557 struct iw_handler_def rda5890_wext_handler_def = {
2558         .num_standard   = ARRAY_SIZE(rda5890_wext_handler),
2559         .standard       = (iw_handler *) rda5890_wext_handler,
2560         .get_wireless_stats = rda5890_get_wireless_stats,
2561 };
2562