2 * This file contains ioctl functions
4 #include <linux/ctype.h>
5 #include <linux/delay.h>
7 #include <linux/if_arp.h>
8 #include <linux/wireless.h>
9 #include <linux/bitops.h>
11 #include <net/iw_handler.h>
12 #include <linux/etherdevice.h>
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"
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
25 #define WLAN_AUTH_CHALLENGE_LEN 128
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
38 static int rda5890_get_name(struct net_device *dev, struct iw_request_info *info,
39 char *cwrq, char *extra)
42 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
44 /* We could add support for 802.11n here as needed. Jean II */
45 snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
47 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
51 static int rda5890_get_freq(struct net_device *dev, struct iw_request_info *info,
52 struct iw_freq *fwrq, char *extra)
54 //struct rda5890_private *priv = netdev_priv(dev);
56 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
58 fwrq->m = (long)2437 * 100000;
61 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
65 static int rda5890_get_wap(struct net_device *dev, struct iw_request_info *info,
66 struct sockaddr *awrq, char *extra)
68 struct rda5890_private *priv = (struct rda5890_private *) netdev_priv(dev);
70 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
72 if (priv->connect_status == MAC_CONNECTED) {
73 memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
75 memset(awrq->sa_data, 0, ETH_ALEN);
77 awrq->sa_family = ARPHRD_ETHER;
79 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
83 static int rda5890_set_nick(struct net_device *dev, struct iw_request_info *info,
84 struct iw_point *dwrq, char *extra)
86 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
88 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
92 static int rda5890_get_nick(struct net_device *dev, struct iw_request_info *info,
93 struct iw_point *dwrq, char *extra)
95 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
97 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
101 static int rda5890_set_rts(struct net_device *dev, struct iw_request_info *info,
102 struct iw_param *vwrq, char *extra)
104 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
106 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
110 static int rda5890_get_rts(struct net_device *dev, struct iw_request_info *info,
111 struct iw_param *vwrq, char *extra)
113 //struct rda5890_private *priv = netdev_priv(dev);
117 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
122 vwrq->disabled = val > RDA5890_RTS_MAX_VALUE; /* min rts value is 0 */
125 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
129 static int rda5890_set_frag(struct net_device *dev, struct iw_request_info *info,
130 struct iw_param *vwrq, char *extra)
132 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
134 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
138 static int rda5890_get_frag(struct net_device *dev, struct iw_request_info *info,
139 struct iw_param *vwrq, char *extra)
141 //struct rda5890_private *priv = netdev_priv(dev);
145 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
150 vwrq->disabled = ((val < RDA5890_FRAG_MIN_VALUE)
151 || (val > RDA5890_FRAG_MAX_VALUE));
154 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
158 static int rda5890_get_mode(struct net_device *dev,
159 struct iw_request_info *info, u32 * uwrq, char *extra)
161 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
163 *uwrq = IW_MODE_INFRA;
165 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
169 static int rda5890_get_txpow(struct net_device *dev,
170 struct iw_request_info *info,
171 struct iw_param *vwrq, char *extra)
173 //struct rda5890_private *priv = netdev_priv(dev);
175 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
177 vwrq->value = 20; // in dbm
180 vwrq->flags = IW_TXPOW_DBM;
182 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
186 static int rda5890_set_retry(struct net_device *dev, struct iw_request_info *info,
187 struct iw_param *vwrq, char *extra)
189 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
191 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
195 static int rda5890_get_retry(struct net_device *dev, struct iw_request_info *info,
196 struct iw_param *vwrq, char *extra)
198 //struct rda5890_private *priv = netdev_priv(dev);
202 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
206 if (vwrq->flags & IW_RETRY_LONG) {
209 /* Subtract 1 to convert try count to retry count */
210 vwrq->value = val - 1;
211 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
215 /* Subtract 1 to convert try count to retry count */
216 vwrq->value = val - 1;
217 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
220 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
225 * 802.11b/g supported bitrates (in 500Kb/s units)
227 u8 rda5890_bg_rates[MAX_RATES] =
228 { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18,
229 0x24, 0x30, 0x48, 0x60, 0x6c,0x00, 0x00 };
231 u16 rda5890_nr_chan = 11;
234 * @brief Get Range Info
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
242 static int rda5890_get_range(struct net_device *dev, struct iw_request_info *info,
243 struct iw_point *dwrq, char *extra)
245 //struct rda5890_private *priv = netdev_priv(dev);
246 struct iw_range *range = (struct iw_range *)extra;
249 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
251 dwrq->length = sizeof(struct iw_range);
252 memset(range, 0, sizeof(struct iw_range));
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;
262 range->num_frequency = 0;
264 range->scan_capa = IW_SCAN_CAPA_ESSID;
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++;
275 range->num_channels = range->num_frequency;
278 * Set an indication of the max TCP throughput in bit/s that we can
279 * expect using this interface
281 range->throughput = 5000 * 1000;
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;
288 range->encoding_size[0] = 5;
289 range->encoding_size[1] = 13;
290 range->num_encoding_sizes = 2;
291 range->max_encoding_tokens = 4;
294 * Right now we support only "iwconfig ethX power on|off"
296 range->pm_capa = IW_POWER_ON;
299 * Minimum version we recommend
301 range->we_version_source = 15;
304 * Version we are compiled with
306 range->we_version_compiled = WIRELESS_EXT;
308 range->retry_capa = IW_RETRY_LIMIT;
309 range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
311 range->min_retry = 0;
312 range->max_retry = 14;
315 * Set the qual, level and noise range values
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;
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;
328 range->sensitivity = 0;
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;
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;
342 range->enc_capa = IW_ENC_CAPA_WPA
344 | IW_ENC_CAPA_CIPHER_TKIP
345 | IW_ENC_CAPA_CIPHER_CCMP;
347 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
351 static int rda5890_set_power(struct net_device *dev, struct iw_request_info *info,
352 struct iw_param *vwrq, char *extra)
354 //struct rda5890_private *priv = netdev_priv(dev);
356 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
358 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
362 static int rda5890_get_power(struct net_device *dev, struct iw_request_info *info,
363 struct iw_param *vwrq, char *extra)
365 //struct rda5890_private *priv = netdev_priv(dev);
367 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
373 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
377 static int rda5890_update_bss_stats(struct rda5890_private *priv)
381 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
383 memcpy(priv->curbssparams.ssid,
384 priv->assoc_ssid, sizeof(priv->curbssparams.ssid));
386 if(priv->scan_running == 1)
389 ret = rda5890_get_bssid(priv, priv->curbssparams.bssid);
391 RDA5890_ERRP("rda5890_get_bssid, ret = %d\n", ret);
396 ret = rda5890_get_channel(priv, &priv->curbssparams.channel);
398 RDA5890_ERRP("rda5890_get_channel, ret = %d\n", ret);
403 ret = rda5890_get_rssi(priv, &priv->curbssparams.rssi);
405 RDA5890_ERRP("rda5890_get_rssi, ret = %d\n", ret);
409 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<< ch = %d rssi = %d\n", __func__, priv->curbssparams.channel, priv->curbssparams.rssi);
415 static struct iw_statistics *rda5890_get_wireless_stats(struct net_device *dev)
417 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
421 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
423 if (priv->connect_status != MAC_CONNECTED)
426 rda5890_update_bss_stats(priv);
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;
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;
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;
457 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
458 return &priv->wstats;
461 static int rda5890_set_freq(struct net_device *dev, struct iw_request_info *info,
462 struct iw_freq *fwrq, char *extra)
464 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
466 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
469 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
473 static int rda5890_set_rate(struct net_device *dev, struct iw_request_info *info,
474 struct iw_param *vwrq, char *extra)
476 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
478 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
481 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
485 static int rda5890_get_rate(struct net_device *dev, struct iw_request_info *info,
486 struct iw_param *vwrq, char *extra)
488 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
490 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
493 vwrq->value = 108*500000;
495 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
499 static int rda5890_set_mode(struct net_device *dev,
500 struct iw_request_info *info, u32 * uwrq, char *extra)
502 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
504 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
506 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
512 * @brief Get Encryption key
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
520 static int rda5890_get_encode(struct net_device *dev,
521 struct iw_request_info *info,
522 struct iw_point *dwrq, u8 * extra)
524 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
526 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
528 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
533 * @brief Set Encryption key
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
541 static int rda5890_set_encode(struct net_device *dev,
542 struct iw_request_info *info,
543 struct iw_point *dwrq, char *extra)
545 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
547 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
549 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
554 * @brief Set Encryption key (internal)
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
563 static int copy_wep_key(struct rda5890_private *priv,
564 const char *key_material,
570 struct enc_key *pkey;
572 /* Paranoid validation of key index */
578 /* validate max key length */
579 if (key_length > KEY_LEN_WEP_104) {
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]);
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"
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],
602 RDA5890_ERRP("Error in WEP Key length %d\n", key_length);
605 pkey = &priv->wep_keys[index];
607 if (key_length > 0) {
608 memset(pkey, 0, sizeof(struct enc_key));
609 pkey->type = KEY_TYPE_ID_WEP;
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);
618 /* Ensure the chosen key is valid */
620 RDA5890_ERRP("key not set, so cannot enable it\n");
624 priv->wep_tx_keyidx = index;
627 priv->secinfo.wep_enabled = 1;
633 static int validate_key_index(u16 def_index, u16 raw_index,
634 u16 *out_index, u16 *is_default)
636 if (!out_index || !is_default)
639 /* Verify index if present, otherwise use default TX key index */
643 *out_index = raw_index - 1;
645 *out_index = def_index;
651 static void disable_wep(struct rda5890_private *priv)
655 /* Set Open System auth mode */
656 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
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;
663 set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
664 set_bit(ASSOC_FLAG_WEP_KEYS, &priv->assoc_flags);
667 static void disable_wpa(struct rda5890_private *priv)
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);
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);
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);
685 * @brief Get Extended Encryption key (WPA/802.1x and WEP)
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
693 static int rda5890_get_encodeext(struct net_device *dev,
694 struct iw_request_info *info,
695 struct iw_point *dwrq,
698 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
700 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
701 int index, max_key_len;
703 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
705 max_key_len = dwrq->length - sizeof(*ext);
709 index = dwrq->flags & IW_ENCODE_INDEX;
711 if (index < 1 || index > 4)
715 index = priv->wep_tx_keyidx;
718 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
719 ext->alg != IW_ENCODE_ALG_WEP) {
724 dwrq->flags = index + 1;
725 memset(ext, 0, sizeof(*ext));
727 if ( !priv->secinfo.wep_enabled
728 && !priv->secinfo.WPAenabled
729 && !priv->secinfo.WPA2enabled) {
730 ext->alg = IW_ENCODE_ALG_NONE;
732 dwrq->flags |= IW_ENCODE_DISABLED;
736 if ( priv->secinfo.wep_enabled
737 && !priv->secinfo.WPAenabled
738 && !priv->secinfo.WPA2enabled) {
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)) {
747 struct enc_key * pkey = NULL;
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;
757 if (pkey->type == KEY_TYPE_ID_AES) {
758 ext->alg = IW_ENCODE_ALG_CCMP;
760 ext->alg = IW_ENCODE_ALG_TKIP;
762 ext->key_len = pkey->len;
765 ext->alg = IW_ENCODE_ALG_TKIP;
772 if (ext->key_len > max_key_len) {
778 memcpy(ext->key, key, ext->key_len);
780 dwrq->flags |= IW_ENCODE_NOKEY;
781 dwrq->flags |= IW_ENCODE_ENABLED;
786 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
791 * @brief Set Encryption key Extended (WPA/802.1x and WEP)
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
799 static int rda5890_set_encodeext(struct net_device *dev,
800 struct iw_request_info *info,
801 struct iw_point *dwrq,
804 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
806 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
809 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
811 if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
812 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
814 if(test_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags))
816 if(priv->imode != 3 && priv->imode != 5)
820 } else if (alg == IW_ENCODE_ALG_WEP) {
821 u16 is_default = 0, index, set_tx_key = 0;
823 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
824 "WEP, flags = 0x%04x\n", dwrq->flags);
826 ret = validate_key_index(priv->wep_tx_keyidx,
827 (dwrq->flags & IW_ENCODE_INDEX),
828 &index, &is_default);
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.
835 if ( !priv->secinfo.wep_enabled
836 || (dwrq->length == 0 && !is_default)
837 || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
840 /* Copy key to driver */
841 ret = copy_wep_key(priv, ext->key, ext->key_len, index, set_tx_key);
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);
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;
857 /* Mark the various WEP bits as modified */
858 set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
860 set_bit(ASSOC_FLAG_WEP_KEYS, &priv->assoc_flags);
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;
866 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
867 "TKIP or CCMP, flags = 0x%04x, alg = %d\n", dwrq->flags, alg);
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",
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);
885 pkey = &priv->wpa_unicast_key;
886 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &priv->assoc_flags);
889 memset(pkey, 0, sizeof (struct enc_key));
890 memcpy(pkey->key, ext->key, ext->key_len);
891 pkey->len = ext->key_len;
893 pkey->flags |= KEY_INFO_WPA_ENABLED;
895 /* Do this after zeroing key structure */
896 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
897 pkey->flags |= KEY_INFO_WPA_MCAST;
899 pkey->flags |= KEY_INFO_WPA_UNICAST;
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",
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",
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);
927 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
930 *Always use key_id = 1 for now
931 * need to toggle among 1, 2, 3
933 ret = rda5890_set_gtk(priv, 1, ext->tx_seq, IW_ENCODE_SEQ_MAX_SIZE,
934 pkey->key, pkey->len);
938 pkey->flags |= KEY_INFO_WPA_UNICAST;
940 ret = rda5890_set_ptk(priv, pkey->key, pkey->len);
945 /* Only disable wep if necessary: can't waste time here. */
947 } else if (alg == IW_ENCODE_ALG_WAPI) { //wapi
948 if(ext->key_len != 32)
954 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
955 unsigned char tmp[8];
958 * Always use key_id = 1 for now
959 * need to toggle among 1, 2, 3
961 ret = rda5890_set_gtk(priv, 1, tmp, IW_ENCODE_SEQ_MAX_SIZE,
962 ext->key, ext->key_len);
967 ret = rda5890_set_ptk(priv, ext->key, ext->key_len);
974 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
979 * @brief PMKSA cache operation (WPA/802.1x and WEP)
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
987 static int rda5890_set_pmksa(struct net_device *dev,
988 struct iw_request_info *info,
989 struct iw_point *dwrq,
992 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
994 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
996 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1000 static int rda5890_set_genie(struct net_device *dev,
1001 struct iw_request_info *info,
1002 struct iw_point *dwrq,
1005 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1008 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1010 if(extra[0] == 0x44) //wapi ie
1012 unsigned char ie_len = extra[1] + 2;
1013 rda5890_generic_set_str(priv, WID_WAPI_ASSOC_IE, extra ,ie_len);
1017 if (dwrq->length > MAX_WPA_IE_LEN ||
1018 (dwrq->length && extra == NULL)) {
1024 memcpy(&priv->wpa_ie[0], extra, dwrq->length);
1025 priv->wpa_ie_len = dwrq->length;
1027 memset(&priv->wpa_ie[0], 0, sizeof(priv->wpa_ie));
1028 priv->wpa_ie_len = 0;
1033 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1037 static int rda5890_get_genie(struct net_device *dev,
1038 struct iw_request_info *info,
1039 struct iw_point *dwrq,
1042 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1045 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1047 if (priv->wpa_ie_len == 0) {
1052 if (dwrq->length < priv->wpa_ie_len) {
1057 dwrq->length = priv->wpa_ie_len;
1058 memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
1061 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1065 static int rda5890_set_auth(struct net_device *dev,
1066 struct iw_request_info *info,
1067 struct iw_param *dwrq,
1070 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1074 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1076 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1077 "flags = 0x%04x, value = 0x%x\n", dwrq->flags, dwrq->value);
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))
1084 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
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;
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;
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;
1102 if (dwrq->value & IW_AUTH_CIPHER_NONE) {
1103 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1105 priv->secinfo.cipther_type = IW_AUTH_CIPHER_NONE;
1109 case IW_AUTH_TKIP_COUNTERMEASURES:
1110 case IW_AUTH_CIPHER_GROUP:
1111 case IW_AUTH_DROP_UNENCRYPTED:
1113 * rda5890 does not use these parameters
1115 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
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;
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;
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;
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;
1151 case IW_AUTH_80211_AUTH_ALG:
1152 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY ||
1153 dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM)
1155 if(dwrq->value & IW_AUTH_ALG_SHARED_KEY )
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;
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;
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;
1172 else if(dwrq->value & IW_AUTH_ALG_WAPI) {
1173 priv->secinfo.auth_mode = IW_AUTH_ALG_WAPI;
1176 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1177 "80211_AUTH_ALG, unknown\n");
1183 case IW_AUTH_WPA_ENABLED:
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;
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;
1205 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1213 set_bit(ASSOC_FLAG_SECINFO, &priv->assoc_flags);
1217 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1221 static int rda5890_get_auth(struct net_device *dev,
1222 struct iw_request_info *info,
1223 struct iw_param *dwrq,
1226 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1229 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1231 switch (dwrq->flags & IW_AUTH_INDEX) {
1232 case IW_AUTH_KEY_MGMT:
1233 dwrq->value = priv->secinfo.key_mgmt;
1236 case IW_AUTH_WPA_VERSION:
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;
1243 dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
1246 case IW_AUTH_80211_AUTH_ALG:
1247 dwrq->value = priv->secinfo.auth_mode;
1250 case IW_AUTH_WPA_ENABLED:
1251 if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
1259 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1263 static int rda5890_set_txpow(struct net_device *dev, struct iw_request_info *info,
1264 struct iw_param *vwrq, char *extra)
1266 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1268 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1270 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1274 static int rda5890_get_essid(struct net_device *dev, struct iw_request_info *info,
1275 struct iw_point *dwrq, char *extra)
1277 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1279 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1282 memcpy(extra, priv->curbssparams.ssid,
1283 strlen(priv->curbssparams.ssid));
1284 dwrq->length = strlen(priv->curbssparams.ssid);
1285 extra[dwrq->length] = '\0';
1288 * If none, we may want to get the one that was set
1291 dwrq->flags = 1; /* active */
1293 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>> \n", __func__);
1297 void rda5890_indicate_disconnected(struct rda5890_private *priv)
1299 union iwreq_data wrqu;
1301 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s <<<\n", __func__);
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);
1307 /*report disconnect to upper layer*/
1308 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s >>>\n", __func__);
1311 void rda5890_indicate_connected(struct rda5890_private *priv)
1313 union iwreq_data wrqu;
1315 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s <<<\n", __func__);
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);
1321 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_NORM, "%s >>>\n", __func__);
1324 void rda5890_assoc_done_worker(struct work_struct *work)
1326 u8 bssid[6], zero_bssid[6];
1327 struct rda5890_private *priv = container_of(work, struct rda5890_private,
1328 assoc_done_work.work);
1330 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<< \n", __func__);
1332 memset(bssid, 0, sizeof(bssid));
1333 memset(zero_bssid, 0, sizeof(zero_bssid));
1334 rda5890_get_bssid(priv, bssid);
1336 if(memcmp(bssid, zero_bssid, sizeof(zero_bssid)))
1338 memcpy(priv->curbssparams.bssid, bssid, sizeof(bssid));
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;
1345 rda5990_assoc_power_save(priv);
1346 clear_bit(ASSOC_FLAG_ASSOC_START, &priv->assoc_flags);
1348 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1351 void rda5890_wlan_connect_worker(struct work_struct *work)
1353 struct rda5890_private *priv = container_of(work, struct rda5890_private,
1354 wlan_connect_work.work);
1356 rda5890_set_txrate(priv, 0);
1359 clear_bit(ASSOC_FLAG_WLAN_CONNECTING ,&priv->assoc_flags);
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 */
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)
1382 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
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__);
1394 if ( priv->secinfo.wep_enabled
1395 && !priv->secinfo.WPAenabled
1396 && !priv->secinfo.WPA2enabled) {
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;
1404 else if (key_len == KEY_LEN_WEP_104) {
1405 priv->imode = BIT0 | BIT2;
1408 RDA5890_ERRP("Invalide WEP Key length %d\n", key_len);
1412 } else if ( !priv->secinfo.wep_enabled
1413 && (priv->secinfo.WPAenabled ||
1414 priv->secinfo.WPA2enabled)) {
1416 struct enc_key * pkey = NULL;
1418 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1419 "%s, WPA cp:%x \n", __func__, priv->secinfo.cipther_type);
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;
1428 //priv->imode = assoc_bss->data.dot11i_info;
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);
1438 * we don't know the cipher type by now
1439 * use dot11i_info to decide
1440 * and use CCMP if possible
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;
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;
1455 RDA5890_ERRP("WEP and WPA/WPA2 enabled simutanously\n");
1462 if (priv->secinfo.auth_mode & IW_AUTH_ALG_OPEN_SYSTEM
1463 || priv->secinfo.auth_mode & IW_AUTH_ALG_SHARED_KEY)
1466 if (priv->secinfo.auth_mode & IW_AUTH_ALG_OPEN_SYSTEM)
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;
1476 priv->authtype = BIT0;
1479 else if(priv->secinfo.auth_mode & IW_AUTH_ALG_SHARED_KEY)
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;
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;
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__);
1498 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1499 "%s, Unknown Auth\n", __func__);
1505 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>> \n", __func__);
1509 static struct bss_descriptor *get_bss_desc_from_scanlist(
1510 struct rda5890_private *priv, unsigned char *ssid)
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) {
1519 if (strcmp(iter_bss->data.ssid, ssid) == 0) {
1528 void rda5890_assoc_worker(struct work_struct *work)
1530 static char old_imode = 0xff, old_bssid[6], assoc_count = 0;
1531 struct rda5890_private *priv = container_of(work, struct rda5890_private,
1534 struct bss_descriptor *assoc_bss;
1536 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
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");
1545 #ifdef GET_SCAN_FROM_NETWORK_INFO
1546 if(assoc_bss->rssi > 200)
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);
1552 if(assoc_bss->data.rssi > 200)
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);
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);
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);
1567 ret = assoc_helper_secinfo(priv, assoc_bss);
1569 RDA5890_ERRP("assoc_helper_secinfo fail, ret = %d\n", ret);
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))
1576 //WEP THE Second retry should change to shared key
1577 if((old_imode == 3 || old_imode == 5) && assoc_count%2)
1579 priv->authtype = BIT1;
1585 //save old bssid para
1586 old_imode = priv->imode;
1587 memcpy(old_bssid, priv->assoc_bssid, 6);
1591 set_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags);
1592 set_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags);
1594 if((priv->imode == 3) || (priv->imode ==5))
1598 clear_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags);
1599 clear_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags);
1607 clear_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags);
1608 clear_bit(ASSOC_FLAG_ASSOC_START ,&priv->assoc_flags);
1613 ret = rda5890_start_join(priv);
1615 RDA5890_ERRP("rda5890_set_ssid fail, ret = %d\n", ret);
1619 if(test_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags))
1621 queue_delayed_work(priv->work_thread, &priv->assoc_work, 3*HZ);
1625 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<< \n", __func__);
1628 static int rda5890_set_essid(struct net_device *dev, struct iw_request_info *info,
1629 struct iw_point *dwrq, char *extra)
1631 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1633 u8 ssid[IW_ESSID_MAX_SIZE + 1];
1635 int in_ssid_len = dwrq->length;
1637 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1639 /* Check the size of the string */
1640 if (in_ssid_len > IW_ESSID_MAX_SIZE) {
1645 memset(&ssid, 0, sizeof(ssid));
1647 if (!dwrq->flags || !in_ssid_len) {
1648 /* "any" SSID requested; leave SSID blank */
1650 /* Specific SSID requested */
1651 memcpy(&ssid, extra, in_ssid_len);
1652 ssid[in_ssid_len] = '\0';
1653 ssid_len = in_ssid_len;
1657 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1658 "requested any SSID\n");
1660 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1661 "requested SSID len = %d ssid:%s\n",
1667 memcpy(&priv->assoc_ssid[0], ssid, sizeof(ssid));
1668 priv->assoc_ssid_len = ssid_len;
1671 if(!test_bit(ASSOC_FLAG_SSID, &priv->assoc_flags))
1674 if(!test_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags))
1678 cancel_delayed_work(&priv->assoc_work);
1679 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ/2);
1684 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
1689 * @brief Connect to the AP or Ad-hoc Network with specific bssid
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
1697 static int rda5890_set_wap(struct net_device *dev, struct iw_request_info *info,
1698 struct sockaddr *awrq, char *extra)
1700 unsigned char * ap_addr = NULL;
1701 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
1703 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
1705 ap_addr = awrq->sa_data;
1706 if(!test_bit(ASSOC_FLAG_ASSOC_RETRY, &priv->assoc_flags)
1707 && !is_zero_eth_addr(ap_addr))
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");
1716 if(is_zero_eth_addr(ap_addr))
1718 clear_bit(ASSOC_FLAG_SSID, &priv->assoc_flags);
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]);
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)
1735 #ifndef GET_SCAN_FROM_NETWORK_INFO
1736 struct iw_event iwe; /* Temporary buffer */
1738 struct rda5890_bss_descriptor *bss = &bss_desc->data;
1740 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
1741 "translate_scan, ssid = %s\n", bss->ssid);
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);
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);
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);
1762 iwe.cmd = SIOCGIWFREQ;
1763 iwe.u.freq.m = (2412 + 5 * (bss->channel - 1)) * 100000;
1765 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
1767 /* Add quality statistics */
1769 iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
1770 iwe.u.qual.level = bss->rssi > 127? bss->rssi - 271: bss->rssi - 15;
1772 snr = iwe.u.qual.level - RDA5890_NF_DEFAULT_SCAN_VALUE;
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);
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;
1787 iwe.u.data.flags = IW_ENCODE_DISABLED;
1789 iwe.u.data.length = 0;
1790 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1793 current_val = start + iwe_stream_lcp_len(info);
1795 iwe.cmd = SIOCGIWRATE;
1796 iwe.u.bitrate.fixed = 0;
1797 iwe.u.bitrate.disabled = 0;
1798 iwe.u.bitrate.value = 0;
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);
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);
1814 /* Check if we added any event */
1815 if ((current_val - start) > iwe_stream_lcp_len(info))
1816 start = current_val;
1819 memset(&iwe, 0, sizeof(iwe));
1820 if (bss_desc->wpa_ie_len) {
1821 char buf[MAX_WPA_IE_LEN];
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]);
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);
1840 memset(&iwe, 0, sizeof(iwe));
1841 if (bss_desc->rsn_ie_len) {
1842 char buf[MAX_WPA_IE_LEN];
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]);
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);
1863 struct iw_event iwe; /* Temporary buffer */
1865 struct bss_descriptor *bss = bss_desc;
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);
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);
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);
1883 iwe.cmd = SIOCGIWMODE;
1884 iwe.u.mode = bss->mode;
1885 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
1888 iwe.cmd = SIOCGIWFREQ;
1889 iwe.u.freq.m = (2412 + 5 * (bss->channel - 1)) * 100000;
1891 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
1893 /* Add quality statistics */
1895 iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
1896 iwe.u.qual.level = bss->rssi > 127? bss->rssi - 271: bss->rssi - 15;
1898 snr = iwe.u.qual.level - RDA5890_NF_DEFAULT_SCAN_VALUE;
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);
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;
1913 iwe.u.data.flags = IW_ENCODE_DISABLED;
1915 iwe.u.data.length = 0;
1916 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
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];
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]);
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);
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];
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]);
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);
1960 memset(&iwe, 0, sizeof(iwe));
1961 if (bss_desc->wapi_ie_len) {
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]);
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);
1985 int is_same_network(struct bss_descriptor *src,
1986 struct bss_descriptor *dst)
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
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));
1996 return ((src->channel == dst->channel) &&
1997 !compare_ether_addr(src->bssid, dst->bssid) &&
1998 !memcmp(src->ssid, dst->ssid, IW_ESSID_MAX_SIZE));
2002 void clear_bss_descriptor(struct bss_descriptor *bss)
2004 /* Don't blow away ->list, just BSS data */
2005 memset(bss, 0, offsetof(struct bss_descriptor, list));
2008 static void dump_bss_desc(struct rda5890_bss_descriptor *bss_desc)
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");
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 */
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
2038 unsigned char oui_rsn[3] = {0x00, 0x0F, 0xAC};
2039 unsigned char oui_wpa[3] = {0x00, 0x50, 0xf2};
2041 static void fill_rsn_wpa_ie(unsigned char *data, unsigned char ie_type,
2042 struct rda5890_bss_descriptor *bss, size_t *len)
2044 unsigned char index = 0;
2047 if (ie_type == IRSNELEMENT) {
2050 /* Set RSN Information Element element ID */
2051 data[index] = IRSNELEMENT;
2057 /* Set WPA Information Element element ID */
2058 data[index] = IWPAELEMENT;
2062 memcpy(&data[index], oui, 3);
2064 data[index++] = 0x01;
2067 /* Set the version of RSN Element to 1 */
2071 /* Set Group Cipher Suite */
2072 memcpy(&data[index], oui, 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;
2079 data[index++] = CIPHER_TYPE_TKIP;
2082 /* Set Pairwise cipher Suite */
2083 if ((bss->dot11i_info & BIT5) && (bss->dot11i_info & BIT6)) {
2084 /* both CCMP and TKIP */
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);
2093 data[index++] = CIPHER_TYPE_CCMP;
2095 memcpy(&data[index], oui, 3);
2097 data[index++] = CIPHER_TYPE_TKIP;
2100 /* BIT7 is 0 => TKIP goes first */
2101 memcpy(&data[index], oui, 3);
2103 data[index++] = CIPHER_TYPE_TKIP;
2105 memcpy(&data[index], oui, 3);
2107 data[index++] = CIPHER_TYPE_CCMP;
2110 else if ((bss->dot11i_info & BIT5) && !(bss->dot11i_info & BIT6)) {
2111 /* CCMP and !TKIP */
2115 memcpy(&data[index], oui, 3);
2117 data[index++] = CIPHER_TYPE_CCMP;
2119 else if (!(bss->dot11i_info & BIT5) && (bss->dot11i_info & BIT6)) {
2120 /* !CCMP and TKIP */
2124 memcpy(&data[index], oui, 3);
2126 data[index++] = CIPHER_TYPE_TKIP;
2129 /* neither CCMP nor TKIP, use TKIP for WPA, and CCMP for RSN */
2133 memcpy(&data[index], oui, 3);
2135 if (ie_type == IRSNELEMENT) {
2136 data[index++] = CIPHER_TYPE_CCMP;
2139 data[index++] = CIPHER_TYPE_TKIP;
2143 /* Set Authentication Suite */
2144 if ((bss->auth_info & 0x01) && (bss->auth_info & 0x02)) {
2145 /* both 802.1X and PSK */
2149 memcpy(&data[index], oui, 3);
2151 data[index++] = 0x01;
2153 memcpy(&data[index], oui, 3);
2155 data[index++] = 0x02;
2157 else if ((bss->auth_info & 0x01) && !(bss->auth_info & 0x02)) {
2158 /* 802.1X and !PSK */
2162 memcpy(&data[index], oui, 3);
2164 data[index++] = 0x01;
2166 else if (!(bss->auth_info & 0x01) && (bss->auth_info & 0x02)) {
2167 /* !802.1X and PSK */
2171 memcpy(&data[index], oui, 3);
2173 data[index++] = 0x02;
2176 /* neither 802.1X nor PSK, use 802.1X */
2180 memcpy(&data[index], oui, 3);
2182 data[index++] = 0x01;
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];
2191 /* Set the length of the RSN Information Element */
2192 data[1] = (index - 2);
2194 /* Return the Extended Supported Rates element length */
2195 *len = (size_t)index;
2198 /* reconstruct wpa/rsn ie from the dot11i_info and auth_info fields */
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
2203 static void reconstruct_rsn_wpa_ie(struct bss_descriptor *bss_desc)
2205 bss_desc->wpa_ie_len = 0;
2206 bss_desc->rsn_ie_len = 0;
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);
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);
2222 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2223 "form_rsn_ie, NO SEC\n");
2227 void rda5890_scan_worker(struct work_struct *work)
2229 struct rda5890_private *priv = container_of(work, struct rda5890_private,
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;
2238 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2240 if(test_bit(ASSOC_FLAG_ASSOC_START, &priv->assoc_flags)
2241 || test_bit(ASSOC_FLAG_WLAN_CONNECTING, &priv->assoc_flags))
2243 cancel_delayed_work(&priv->scan_work);
2244 queue_delayed_work(priv->work_thread, &priv->scan_work, HZ/2);
2248 priv->scan_running = 1;
2250 #ifdef WIFI_UNLOCK_SYSTEM
2254 #ifdef GET_SCAN_FROM_NETWORK_INFO
2255 ret = rda5890_start_scan_enable_network_info(priv);
2257 ret = rda5890_start_scan(priv);
2260 RDA5890_ERRP("rda5890_start_scan fail, ret = %d\n", ret);
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);
2268 #ifndef GET_SCAN_FROM_NETWORK_INFO
2270 bss_count = rda5890_get_scan_results(priv, bss_desc);
2272 fist_send = (bss_count >> 8) & 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);
2278 RDA5890_DBGLAP(RDA5890_DA_WID, RDA5890_DL_TRACE,
2279 "Get Scan Result, count = %d, fist_send= %d \n", bss_count, fist_send);
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;
2287 if (RDA5890_DBGLA(RDA5890_DA_WEXT, RDA5890_DL_TRACE))
2288 dump_bss_desc(&bss_desc[bss_index]);
2290 memcpy(&new.data, &bss_desc[bss_index], sizeof(struct rda5890_bss_descriptor));
2291 reconstruct_rsn_wpa_ie(&new);
2292 new.last_scanned = jiffies;
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)) {
2301 if ((oldest == NULL) ||
2302 (iter_bss->last_scanned < oldest->last_scanned))
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 */
2324 clear_bss_descriptor(found);
2325 list_move_tail(&found->list, &priv->network_list);
2327 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2328 "FOUND NEW but no space to store\n");
2331 /* Copy the locally created newbssentry to the scan table */
2332 memcpy(found, &new, offsetof(struct bss_descriptor, list));
2335 if(bss_count >= 5 && !fist_send)
2339 //do noting in get network info modle
2344 priv->scan_running = 0;
2345 memset(&wrqu, 0, sizeof(union iwreq_data));
2346 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
2348 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2350 #ifdef WIFI_UNLOCK_SYSTEM
2351 rda5990_wakeUnlock();
2356 * @brief Handle Scan Network ioctl
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
2363 * @return 0 --success, otherwise fail
2365 int rda5890_set_scan(struct net_device *dev, struct iw_request_info *info,
2366 union iwreq_data *wrqu, char *extra)
2368 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
2370 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2372 if (priv->scan_running)
2376 cancel_delayed_work(&priv->scan_work);
2377 queue_delayed_work(priv->work_thread, &priv->scan_work, HZ/50);
2380 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2385 * @brief Handle Retrieve scan table ioctl
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
2392 * @return 0 --success, otherwise fail
2394 int rda5890_get_scan(struct net_device *dev, struct iw_request_info *info,
2395 struct iw_point *dwrq, char *extra)
2397 #define SCAN_ITEM_SIZE 128
2398 struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
2400 struct bss_descriptor *iter_bss;
2401 struct bss_descriptor *safe;
2403 char *stop = ev + dwrq->length;
2405 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
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");
2414 /* report all bss to upper layer */
2415 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
2417 unsigned long stale_time;
2419 if (stop - ev < SCAN_ITEM_SIZE) {
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);
2432 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2433 "Prune Old Bss %s\n", iter_bss->ssid);
2435 clear_bss_descriptor(iter_bss);
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);
2445 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2446 "Report BSS %s\n", iter_bss->data.ssid);
2448 if (next_ev == NULL)
2452 dwrq->length = (ev - extra);
2455 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2459 int rda5890_set_mlme(struct net_device *dev,
2460 struct iw_request_info *info,
2461 union iwreq_data *wrqu, char *extra)
2463 //struct rda5890_private *priv = (struct rda5890_private *)netdev_priv(dev);
2464 struct iw_mlme *mlme = (struct iw_mlme *)extra;
2467 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s >>>\n", __func__);
2469 switch (mlme->cmd) {
2470 case IW_MLME_DEAUTH:
2471 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2473 /* silently ignore */
2476 case IW_MLME_DISASSOC:
2478 unsigned char ssid[6];
2480 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2482 /* silently ignore */
2483 rda5890_set_ssid((struct rda5890_private *)netdev_priv(dev) , ssid, 6);
2487 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE,
2488 "Not supported cmd %d\n", mlme->cmd);
2492 RDA5890_DBGLAP(RDA5890_DA_WEXT, RDA5890_DL_TRACE, "%s <<<\n", __func__);
2497 * iwconfig settable callbacks
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 */
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,