initial commit with v3.6.7
[linux-3.6.7-moxart.git] / drivers / staging / csr / sme_wext.c
blob7e85907e29a3ecc9edb49495a10ee45e1f62b835
1 /*
2 * ---------------------------------------------------------------------------
3 * FILE: sme_wext.c
5 * PURPOSE:
6 * Handlers for ioctls from iwconfig.
7 * These provide the control plane operations.
9 * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
11 * Refer to LICENSE.txt included with this source code for details on
12 * the license terms.
14 * ---------------------------------------------------------------------------
16 #include <linux/types.h>
17 #include <linux/etherdevice.h>
18 #include <linux/if_arp.h>
19 #include <asm/uaccess.h>
20 #include <linux/ctype.h>
21 #include "unifi_priv.h"
22 #include <linux/rtnetlink.h>
24 #define CHECK_INITED(_priv) \
25 do { \
26 if (_priv->init_progress != UNIFI_INIT_COMPLETED) { \
27 unifi_trace(_priv, UDBG2, "%s unifi not ready, failing wext call\n", __FUNCTION__); \
28 return -ENODEV; \
29 } \
30 } while (0)
32 /* Workaround for the wpa_supplicant hanging issue - disabled on Android */
33 #ifndef ANDROID_BUILD
34 #define CSR_WIFI_WEXT_HANG_WORKAROUND
35 #endif
37 #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND
38 # define UF_RTNL_LOCK() rtnl_lock()
39 # define UF_RTNL_UNLOCK() rtnl_unlock()
40 #else
41 # define UF_RTNL_LOCK()
42 # define UF_RTNL_UNLOCK()
43 #endif
47 * ---------------------------------------------------------------------------
48 * Helper functions
49 * ---------------------------------------------------------------------------
53 * ---------------------------------------------------------------------------
54 * wext_freq_to_channel
55 * channel_to_mhz
57 * These functions convert between channel number and frequency.
59 * Arguments:
60 * ch Channel number, as defined in 802.11 specs
61 * m, e Mantissa and exponent as provided by wireless extension.
63 * Returns:
64 * channel or frequency (in MHz) value
65 * ---------------------------------------------------------------------------
67 static int
68 wext_freq_to_channel(int m, int e)
70 int mhz;
72 mhz = m;
73 while (e < 6) {
74 mhz /= 10;
75 e++;
77 while (e > 6) {
78 mhz *= 10;
79 e--;
82 if (mhz >= 5000) {
83 return ((mhz - 5000) / 5);
86 if (mhz == 2482) {
87 return 14;
90 if (mhz >= 2407) {
91 return ((mhz - 2407) / 5);
94 return 0;
95 } /* wext_freq_to_channel() */
97 static int
98 channel_to_mhz(int ch, int dot11a)
101 if (ch == 0) return 0;
102 if (ch > 200) return 0;
104 /* 5G */
105 if (dot11a) {
106 return (5000 + (5 * ch));
109 /* 2.4G */
110 if (ch == 14) {
111 return 2484;
114 if ((ch < 14) && (ch > 0)) {
115 return (2407 + (5 * ch));
118 return 0;
120 #ifdef CSR_SUPPORT_WEXT_AP
121 void uf_sme_wext_ap_set_defaults(unifi_priv_t *priv)
123 memcpy(priv->ap_config.ssid.ssid,"defaultssid",sizeof("defaultssid"));
125 priv->ap_config.ssid.length = 8;
126 priv->ap_config.channel = 6;
127 priv->ap_config.if_index = 1;
128 priv->ap_config.credentials.authType = 0;
129 priv->ap_config.max_connections=8;
131 priv->group_sec_config.apGroupkeyTimeout = 0;
132 priv->group_sec_config.apStrictGtkRekey = 0;
133 priv->group_sec_config.apGmkTimeout = 0;
134 priv->group_sec_config.apResponseTimeout = 100; /* Default*/
135 priv->group_sec_config.apRetransLimit = 3; /* Default*/
136 /* Set default params even if they may not be used*/
137 /* Until Here*/
139 priv->ap_mac_config.preamble = CSR_WIFI_SME_USE_LONG_PREAMBLE;
140 priv->ap_mac_config.shortSlotTimeEnabled = FALSE;
141 priv->ap_mac_config.ctsProtectionType=CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC;
143 priv->ap_mac_config.wmmEnabled = TRUE;
144 priv->ap_mac_config.wmmApParams[0].cwMin=4;
145 priv->ap_mac_config.wmmApParams[0].cwMax=10;
146 priv->ap_mac_config.wmmApParams[0].aifs=3;
147 priv->ap_mac_config.wmmApParams[0].txopLimit=0;
148 priv->ap_mac_config.wmmApParams[0].admissionControlMandatory=FALSE;
149 priv->ap_mac_config.wmmApParams[1].cwMin=4;
150 priv->ap_mac_config.wmmApParams[1].cwMax=10;
151 priv->ap_mac_config.wmmApParams[1].aifs=7;
152 priv->ap_mac_config.wmmApParams[1].txopLimit=0;
153 priv->ap_mac_config.wmmApParams[1].admissionControlMandatory=FALSE;
154 priv->ap_mac_config.wmmApParams[2].cwMin=3;
155 priv->ap_mac_config.wmmApParams[2].cwMax=4;
156 priv->ap_mac_config.wmmApParams[2].aifs=1;
157 priv->ap_mac_config.wmmApParams[2].txopLimit=94;
158 priv->ap_mac_config.wmmApParams[2].admissionControlMandatory=FALSE;
159 priv->ap_mac_config.wmmApParams[3].cwMin=2;
160 priv->ap_mac_config.wmmApParams[3].cwMax=3;
161 priv->ap_mac_config.wmmApParams[3].aifs=1;
162 priv->ap_mac_config.wmmApParams[3].txopLimit=47;
163 priv->ap_mac_config.wmmApParams[3].admissionControlMandatory=FALSE;
165 priv->ap_mac_config.wmmApBcParams[0].cwMin=4;
166 priv->ap_mac_config.wmmApBcParams[0].cwMax=10;
167 priv->ap_mac_config.wmmApBcParams[0].aifs=3;
168 priv->ap_mac_config.wmmApBcParams[0].txopLimit=0;
169 priv->ap_mac_config.wmmApBcParams[0].admissionControlMandatory=FALSE;
170 priv->ap_mac_config.wmmApBcParams[1].cwMin=4;
171 priv->ap_mac_config.wmmApBcParams[1].cwMax=10;
172 priv->ap_mac_config.wmmApBcParams[1].aifs=7;
173 priv->ap_mac_config.wmmApBcParams[1].txopLimit=0;
174 priv->ap_mac_config.wmmApBcParams[1].admissionControlMandatory=FALSE;
175 priv->ap_mac_config.wmmApBcParams[2].cwMin=3;
176 priv->ap_mac_config.wmmApBcParams[2].cwMax=4;
177 priv->ap_mac_config.wmmApBcParams[2].aifs=2;
178 priv->ap_mac_config.wmmApBcParams[2].txopLimit=94;
179 priv->ap_mac_config.wmmApBcParams[2].admissionControlMandatory=FALSE;
180 priv->ap_mac_config.wmmApBcParams[3].cwMin=2;
181 priv->ap_mac_config.wmmApBcParams[3].cwMax=3;
182 priv->ap_mac_config.wmmApBcParams[3].aifs=2;
183 priv->ap_mac_config.wmmApBcParams[3].txopLimit=47;
184 priv->ap_mac_config.wmmApBcParams[3].admissionControlMandatory=FALSE;
186 priv->ap_mac_config.accessType=CSR_WIFI_AP_ACCESS_TYPE_NONE;
187 priv->ap_mac_config.macAddressListCount=0;
188 priv->ap_mac_config.macAddressList=NULL;
190 priv->ap_mac_config.apHtParams.rxStbc=1;
191 priv->ap_mac_config.apHtParams.rifsModeAllowed=TRUE;
192 priv->ap_mac_config.apHtParams.greenfieldSupported=FALSE;
193 priv->ap_mac_config.apHtParams.shortGi20MHz=TRUE;
194 priv->ap_mac_config.apHtParams.htProtection=0;
195 priv->ap_mac_config.apHtParams.dualCtsProtection=FALSE;
197 priv->ap_mac_config.phySupportedBitmap =
198 (CSR_WIFI_SME_AP_PHY_SUPPORT_B|CSR_WIFI_SME_AP_PHY_SUPPORT_G|CSR_WIFI_SME_AP_PHY_SUPPORT_N);
199 priv->ap_mac_config.beaconInterval= 100;
200 priv->ap_mac_config.dtimPeriod=3;
201 priv->ap_mac_config.maxListenInterval=0x00ff;/* Set it to a large value
202 to enable different types of
203 devices to join us */
204 priv->ap_mac_config.supportedRatesCount =
205 uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap);
207 #endif
209 * ---------------------------------------------------------------------------
210 * uf_sme_wext_set_defaults
212 * Set up power-on defaults for driver config.
214 * Note: The SME Management API *cannot* be used in this function.
216 * Arguments:
217 * priv Pointer to device private context struct
219 * Returns:
220 * None.
221 * ---------------------------------------------------------------------------
223 void
224 uf_sme_wext_set_defaults(unifi_priv_t *priv)
226 memset(&priv->connection_config, 0, sizeof(CsrWifiSmeConnectionConfig));
228 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE;
229 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
230 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
231 priv->connection_config.privacyMode = CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
232 priv->connection_config.wmmQosInfo = 0xFF;
233 priv->connection_config.ifIndex = CSR_WIFI_SME_RADIO_IF_BOTH;
234 priv->connection_config.adhocJoinOnly = FALSE;
235 priv->connection_config.adhocChannel = 6;
237 priv->wep_tx_key_index = 0;
239 priv->wext_wireless_stats.qual.qual = 0;
240 priv->wext_wireless_stats.qual.level = 0;
241 priv->wext_wireless_stats.qual.noise = 0;
242 priv->wext_wireless_stats.qual.updated = 0x70;
243 #ifdef CSR_SUPPORT_WEXT_AP
244 /* Initialize the default configuration for AP */
245 uf_sme_wext_ap_set_defaults(priv);
246 #endif
249 } /* uf_sme_wext_set_defaults() */
253 * ---------------------------------------------------------------------------
254 * WEXT methods
255 * ---------------------------------------------------------------------------
259 * ---------------------------------------------------------------------------
260 * unifi_giwname - handler for SIOCGIWNAME
261 * unifi_siwfreq - handler for SIOCSIWFREQ
262 * unifi_giwfreq - handler for SIOCGIWFREQ
263 * unifi_siwmode - handler for SIOCSIWMODE
264 * unifi_giwmode - handler for SIOCGIWMODE
265 * unifi_giwrange - handler for SIOCGIWRANGE
266 * unifi_siwap - handler for SIOCSIWAP
267 * unifi_giwap - handler for SIOCGIWAP
268 * unifi_siwscan - handler for SIOCSIWSCAN
269 * unifi_giwscan - handler for SIOCGIWSCAN
270 * unifi_siwessid - handler for SIOCSIWESSID
271 * unifi_giwessid - handler for SIOCGIWESSID
272 * unifi_siwencode - handler for SIOCSIWENCODE
273 * unifi_giwencode - handler for SIOCGIWENCODE
275 * Handler functions for IW extensions.
276 * These are registered via the unifi_iw_handler_def struct below
277 * and called by the generic IW driver support code.
278 * See include/net/iw_handler.h.
280 * Arguments:
281 * None.
283 * Returns:
284 * None.
285 * ---------------------------------------------------------------------------
287 static int
288 iwprivsdefs(struct net_device *dev, struct iw_request_info *info,
289 union iwreq_data *wrqu, char *extra)
291 int r;
292 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
293 unifi_priv_t *priv = interfacePriv->privPtr;
294 CsrWifiSmeMibConfig mibConfig;
295 CsrWifiSmePowerConfig powerConfig;
297 unifi_trace(priv, UDBG1, "iwprivs80211defaults: reload defaults\n");
299 uf_sme_wext_set_defaults(priv);
301 /* Get, modify and set the MIB data */
302 r = sme_mgt_mib_config_get(priv, &mibConfig);
303 if (r) {
304 unifi_error(priv, "iwprivs80211defaults: Get CsrWifiSmeMibConfigValue failed.\n");
305 return r;
307 mibConfig.dot11RtsThreshold = 2347;
308 mibConfig.dot11FragmentationThreshold = 2346;
309 r = sme_mgt_mib_config_set(priv, &mibConfig);
310 if (r) {
311 unifi_error(priv, "iwprivs80211defaults: Set CsrWifiSmeMibConfigValue failed.\n");
312 return r;
315 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
316 powerConfig.listenIntervalTu = 100;
317 powerConfig.rxDtims = 1;
319 r = sme_mgt_power_config_set(priv, &powerConfig);
320 if (r) {
321 unifi_error(priv, "iwprivs80211defaults: Set unifi_PowerConfigValue failed.\n");
322 return r;
325 return 0;
326 } /* iwprivsdefs() */
328 static int
329 iwprivs80211ps(struct net_device *dev, struct iw_request_info *info,
330 union iwreq_data *wrqu, char *extra)
332 int r = 0;
333 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
334 unifi_priv_t *priv = interfacePriv->privPtr;
336 int ps_mode = (int)(*extra);
337 CsrWifiSmePowerConfig powerConfig;
339 unifi_trace(priv, UDBG1, "iwprivs80211ps: power save mode = %d\n", ps_mode);
341 r = sme_mgt_power_config_get(priv, &powerConfig);
342 if (r) {
343 unifi_error(priv, "iwprivs80211ps: Get unifi_PowerConfigValue failed.\n");
344 return r;
347 switch (ps_mode) {
348 case CSR_PMM_ACTIVE_MODE:
349 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
350 break;
351 case CSR_PMM_POWER_SAVE:
352 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
353 break;
354 case CSR_PMM_FAST_POWER_SAVE:
355 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED;
356 break;
357 default:
358 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO;
359 break;
362 r = sme_mgt_power_config_set(priv, &powerConfig);
363 if (r) {
364 unifi_error(priv, "iwprivs80211ps: Set unifi_PowerConfigValue failed.\n");
367 return r;
370 static int
371 iwprivg80211ps(struct net_device *dev, struct iw_request_info *info,
372 union iwreq_data *wrqu, char *extra)
374 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
375 unifi_priv_t *priv = interfacePriv->privPtr;
377 CsrWifiSmePowerConfig powerConfig;
378 int r;
380 r = sme_mgt_power_config_get(priv, &powerConfig);
381 if (r) {
382 unifi_error(priv, "iwprivg80211ps: Get 802.11 power mode failed.\n");
383 return r;
386 switch (powerConfig.powerSaveLevel) {
387 case CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW:
388 snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
389 "Power save mode: %d (Active)",
390 powerConfig.powerSaveLevel);
391 break;
392 case CSR_WIFI_SME_POWER_SAVE_LEVEL_MED:
393 snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
394 "Power save mode: %d (Fast)",
395 powerConfig.powerSaveLevel);
396 break;
397 case CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH:
398 snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
399 "Power save mode: %d (Full)",
400 powerConfig.powerSaveLevel);
401 break;
402 case CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO:
403 snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
404 "Power save mode: %d (Auto)",
405 powerConfig.powerSaveLevel);
406 break;
407 default:
408 snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING,
409 "Power save mode: %d (Unknown)",
410 powerConfig.powerSaveLevel);
411 break;
414 wrqu->data.length = strlen(extra) + 1;
416 return 0;
419 static int
420 iwprivssmedebug(struct net_device *dev, struct iw_request_info *info,
421 union iwreq_data *wrqu, char *extra)
423 /* No longer supported on the API */
424 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE)
425 unifi_debug_buf_dump();
426 #endif
428 return 0;
431 #ifdef CSR_SUPPORT_WEXT_AP
432 #define PARAM_TYPE_INT 0
433 #define PARAM_TYPE_STRING 1
434 #define CSR_WIFI_MAX_SSID_LEN 32
435 #define CSR_WIFI_MAX_SEC_LEN 16
436 #define CSR_WIFI_MAX_KEY_LEN 65
438 static int hex_look_up(char x)
440 if(x>='0' && x<='9')
441 return (x-48);
442 if(x>= 'a' && x <= 'f')
443 return (x-87);
444 return -1;
447 static int power (int a, int b)
449 int i;
450 int num =1;
451 for(i=0;i<b;i++)
452 num *=a;
453 return num;
456 static int decode_parameter_from_string(unifi_priv_t* priv, char **str_ptr,
457 const char *token, int param_type,
458 void *dst, int param_max_len)
460 u8 int_str[7] = "0";
461 u32 param_str_len;
462 u8 *param_str_begin,*param_str_end;
463 u8 *orig_str = *str_ptr;
465 if (!strncmp(*str_ptr, token, strlen(token))) {
466 strsep(str_ptr, "=,");
467 param_str_begin = *str_ptr;
468 strsep(str_ptr, "=,");
469 if (*str_ptr == NULL) {
470 param_str_len = strlen(param_str_begin);
471 } else {
472 param_str_end = *str_ptr-1;
473 param_str_len = param_str_end - param_str_begin;
475 unifi_trace(priv,UDBG2,"'token:%s', len:%d, ", token, param_str_len);
476 if (param_str_len > param_max_len) {
477 unifi_notice(priv,"extracted param len:%d is > MAX:%d\n",param_str_len, param_max_len);
478 param_str_len = param_max_len;
480 switch (param_type) {
481 case PARAM_TYPE_INT:
483 u32 *pdst_int = dst,num =0;
484 int i,j=0;
485 if (param_str_len > sizeof(int_str)) {
486 param_str_len = sizeof(int_str);
488 memcpy(int_str, param_str_begin, param_str_len);
489 for(i = param_str_len; i>0;i--) {
490 if(int_str[i-1] >= '0' && int_str[i-1] <='9') {
491 num += ((int_str[i-1]-'0')*power(10,j));
492 j++;
493 } else {
494 unifi_error(priv,"decode_parameter_from_string:not a number %c\n",(int_str[i-1]));
495 return -1;
498 *pdst_int = num;
499 unifi_trace(priv,UDBG2,"decode_parameter_from_string:decoded int = %d\n",*pdst_int);
501 break;
502 default:
503 memcpy(dst, param_str_begin, param_str_len);
504 *((char *)dst + param_str_len) = 0;
505 unifi_trace(priv,UDBG2,"decode_parameter_from_string:decoded string = %s\n",(char *)dst);
506 break;
508 } else {
509 unifi_error(priv,"decode_parameter_from_string: Token:%s not found in %s \n",token,orig_str);
510 return -1;
512 return 0;
514 static int store_ap_advanced_config_from_string(unifi_priv_t *priv, char *param_str)
516 char * str_ptr=param_str;
517 int ret = 0,tmp_var;
518 char phy_mode[6];
519 CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config;
521 /* Check for BI */
522 ret = decode_parameter_from_string(priv, &str_ptr, "BI=",
523 PARAM_TYPE_INT, &tmp_var, 5);
524 if(ret) {
525 unifi_error(priv,"store_ap_advanced_config_from_string: BI not found\n");
526 return -1;
528 ap_mac_config->beaconInterval = tmp_var;
529 ret = decode_parameter_from_string(priv, &str_ptr, "DTIM_PER=",
530 PARAM_TYPE_INT, &tmp_var, 5);
531 if(ret) {
532 unifi_error(priv,"store_ap_advanced_config_from_string: DTIM_PER not found\n");
533 return -1;
535 ap_mac_config->dtimPeriod = tmp_var;
536 ret = decode_parameter_from_string(priv, &str_ptr, "WMM=",
537 PARAM_TYPE_INT, &tmp_var, 5);
538 if(ret) {
539 unifi_error(priv,"store_ap_advanced_config_from_string: WMM not found\n");
540 return -1;
542 ap_mac_config->wmmEnabled = tmp_var;
543 ret = decode_parameter_from_string(priv, &str_ptr, "PHY=",
544 PARAM_TYPE_STRING, phy_mode, 5);
545 if(ret) {
546 unifi_error(priv,"store_ap_advanced_config_from_string: PHY not found\n");
547 } else {
548 if(strstr(phy_mode,"b")){
549 ap_mac_config->phySupportedBitmap = CSR_WIFI_SME_AP_PHY_SUPPORT_B;
551 if(strstr(phy_mode,"g")) {
552 ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_G;
554 if(strstr(phy_mode,"n")) {
555 ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_N;
557 ap_mac_config->supportedRatesCount =
558 uf_configure_supported_rates(ap_mac_config->supportedRates, ap_mac_config->phySupportedBitmap);
560 return ret;
563 static int store_ap_config_from_string( unifi_priv_t * priv,char *param_str)
566 char *str_ptr = param_str;
567 char sub_cmd[16];
568 char sec[CSR_WIFI_MAX_SEC_LEN];
569 char key[CSR_WIFI_MAX_KEY_LEN];
570 int ret = 0,tmp_var;
571 CsrWifiSmeApConfig_t *ap_config = &priv->ap_config;
572 CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config;
573 memset(sub_cmd, 0, sizeof(sub_cmd));
574 if(!strstr(param_str,"END")) {
575 unifi_error(priv,"store_ap_config_from_string:Invalid config string:%s\n",param_str);
576 return -1;
578 if (decode_parameter_from_string(priv,&str_ptr, "ASCII_CMD=",
579 PARAM_TYPE_STRING, sub_cmd, 6) != 0) {
580 return -1;
582 if (strncmp(sub_cmd, "AP_CFG", 6)) {
584 if(!strncmp(sub_cmd ,"ADVCFG", 6)) {
585 return store_ap_advanced_config_from_string(priv, str_ptr);
587 unifi_error(priv,"store_ap_config_from_string: sub_cmd:%s != 'AP_CFG or ADVCFG'!\n", sub_cmd);
588 return -1;
590 memset(ap_config, 0, sizeof(CsrWifiSmeApConfig_t));
591 ret = decode_parameter_from_string(priv,&str_ptr, "SSID=",
592 PARAM_TYPE_STRING, ap_config->ssid.ssid,
593 CSR_WIFI_MAX_SSID_LEN);
594 if(ret) {
595 unifi_error(priv,"store_ap_config_from_string: SSID not found\n");
596 return -1;
598 ap_config->ssid.length = strlen(ap_config->ssid.ssid);
600 ret = decode_parameter_from_string(priv, &str_ptr, "SEC=",
601 PARAM_TYPE_STRING, sec, CSR_WIFI_MAX_SEC_LEN);
602 if(ret) {
603 unifi_error(priv,"store_ap_config_from_string: SEC not found\n");
604 return -1;
606 ret = decode_parameter_from_string(priv,&str_ptr, "KEY=",
607 PARAM_TYPE_STRING, key, CSR_WIFI_MAX_KEY_LEN);
608 if(!strcasecmp(sec,"open")) {
609 unifi_trace(priv,UDBG2,"store_ap_config_from_string: security open");
610 ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM;
611 if(ret) {
612 unifi_notice(priv,"store_ap_config_from_string: KEY not found:fine with Open\n");
615 else if(!strcasecmp(sec,"wpa2-psk")) {
616 int i,j=0;
617 CsrWifiNmeApAuthPers *pers =
618 ((CsrWifiNmeApAuthPers *)&(ap_config->credentials.nmeAuthType.authTypePersonal));
619 u8 *psk = pers->authPers_credentials.psk.psk;
621 unifi_trace(priv,UDBG2,"store_ap_config_from_string: security WPA2");
622 if(ret) {
623 unifi_error(priv,"store_ap_config_from_string: KEY not found for WPA2\n");
624 return -1;
626 ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL;
627 pers->authSupport = CSR_WIFI_SME_RSN_AUTH_WPA2PSK;
628 pers->rsnCapabilities =0;
629 pers->wapiCapabilities =0;
630 pers->pskOrPassphrase=CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK;
631 pers->authPers_credentials.psk.encryptionMode =
632 (CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP |CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP) ;
633 for(i=0;i<32;i++){
634 psk[i] = (16*hex_look_up(key[j]))+hex_look_up(key[j+1]);
635 j+=2;
638 } else {
639 unifi_notice(priv,"store_ap_config_from_string: Unknown security: Assuming Open");
640 ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM;
641 return -1;
643 /* Get the decoded value in a temp int variable to ensure that other fields within the struct
644 which are of type other than int are not over written */
645 ret = decode_parameter_from_string(priv,&str_ptr, "CHANNEL=", PARAM_TYPE_INT, &tmp_var, 5);
646 if(ret)
647 return -1;
648 ap_config->channel = tmp_var;
649 ret = decode_parameter_from_string(priv,&str_ptr, "PREAMBLE=", PARAM_TYPE_INT, &tmp_var, 5);
650 if(ret)
651 return -1;
652 ap_mac_config->preamble = tmp_var;
653 ret = decode_parameter_from_string(priv,&str_ptr, "MAX_SCB=", PARAM_TYPE_INT, &tmp_var, 5);
654 ap_config->max_connections = tmp_var;
655 return ret;
658 static int
659 iwprivsapstart(struct net_device *dev, struct iw_request_info *info,
660 union iwreq_data *wrqu, char *extra)
662 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
663 unifi_priv_t *priv = interfacePriv->privPtr;
664 int r;
666 unifi_trace(priv, UDBG1, "iwprivsapstart\n" );
667 r = sme_ap_start(priv,interfacePriv->InterfaceTag,&priv->ap_config);
668 if(r) {
669 unifi_error(priv,"iwprivsapstart AP START failed : %d\n",-r);
671 return r;
674 static int
675 iwprivsapconfig(struct net_device *dev, struct iw_request_info *info,
676 union iwreq_data *wrqu, char *extra)
678 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
679 unifi_priv_t *priv = interfacePriv->privPtr;
680 char *cfg_str = NULL;
681 int r;
683 unifi_trace(priv, UDBG1, "iwprivsapconfig\n" );
684 if (wrqu->data.length != 0) {
685 char *str;
686 if (!(cfg_str = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
688 return -ENOMEM;
690 if (copy_from_user(cfg_str, wrqu->data.pointer, wrqu->data.length)) {
691 kfree(cfg_str);
692 return -EFAULT;
694 cfg_str[wrqu->data.length] = 0;
695 unifi_trace(priv,UDBG2,"length:%d\n",wrqu->data.length);
696 unifi_trace(priv,UDBG2,"AP configuration string:%s\n",cfg_str);
697 str = cfg_str;
698 if ((r = store_ap_config_from_string(priv,str))) {
699 unifi_error(priv, "iwprivsapconfig:Failed to decode the string %d\n",r);
700 kfree(cfg_str);
701 return -EIO;
704 } else {
705 unifi_error(priv,"iwprivsapconfig argument length = 0 \n");
706 return -EIO;
708 r = sme_ap_config(priv, &priv->ap_mac_config, &priv->group_sec_config);
709 if(r) {
710 unifi_error(priv,"iwprivsapstop AP Config failed : %d\n",-r);
711 } else if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
712 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
713 unifi_trace(priv, UDBG1, "iwprivsapconfig: Starting the AP");
714 r = sme_ap_start(priv,interfacePriv->InterfaceTag,&priv->ap_config);
715 if(r) {
716 unifi_error(priv,"iwprivsapstart AP START failed : %d\n",-r);
719 kfree(cfg_str);
720 return r;
723 static int
724 iwprivsapstop(struct net_device *dev, struct iw_request_info *info,
725 union iwreq_data *wrqu, char *extra)
727 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
728 unifi_priv_t *priv = interfacePriv->privPtr;
729 int r;
730 u16 interface_tag = interfacePriv->InterfaceTag;
732 unifi_trace(priv, UDBG1, "iwprivsapstop\n" );
733 r = sme_ap_stop(priv,interface_tag);
734 if(r) {
735 unifi_error(priv,"iwprivsapstop AP STOP failed : %d\n",-r);
737 return r;
740 #ifdef ANDROID_BUILD
741 static int
742 iwprivsapfwreload(struct net_device *dev, struct iw_request_info *info,
743 union iwreq_data *wrqu, char *extra)
745 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
746 unifi_priv_t *priv = interfacePriv->privPtr;
748 unifi_trace(priv, UDBG1, "iwprivsapfwreload\n" );
749 return 0;
752 static int
753 iwprivsstackstart(struct net_device *dev, struct iw_request_info *info,
754 union iwreq_data *wrqu, char *extra)
756 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
757 unifi_priv_t *priv = interfacePriv->privPtr;
758 unifi_trace(priv, UDBG1, "iwprivsstackstart\n" );
759 return 0;
762 static int
763 iwprivsstackstop(struct net_device *dev, struct iw_request_info *info,
764 union iwreq_data *wrqu, char *extra)
766 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
767 unifi_priv_t *priv = interfacePriv->privPtr;
768 int r = 0;
769 u16 interface_tag = interfacePriv->InterfaceTag;
771 unifi_trace(priv, UDBG1, "iwprivsstackstop\n" );
773 switch(interfacePriv->interfaceMode) {
774 case CSR_WIFI_ROUTER_CTRL_MODE_STA:
775 case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI:
776 case CSR_WIFI_ROUTER_CTRL_MODE_IBSS:
777 r = sme_mgt_disconnect(priv);
778 break;
779 case CSR_WIFI_ROUTER_CTRL_MODE_AP:
780 case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO:
781 r = sme_ap_stop(priv,interface_tag);
782 break;
783 default :
784 break;
787 if(r) {
788 unifi_error(priv,"iwprivsstackstop Stack stop failed : %d\n",-r);
790 return 0;
792 #endif /* ANDROID_BUILD */
793 #endif /* CSR_SUPPORT_WEXT_AP */
795 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
796 static int
797 iwprivsconfwapi(struct net_device *dev, struct iw_request_info *info,
798 union iwreq_data *wrqu, char *extra)
800 u8 enable;
801 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
802 unifi_priv_t *priv = interfacePriv->privPtr;
803 func_enter();
805 unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" );
807 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
808 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
809 unifi_error(priv, "iwprivsconfwapi: not permitted in Mode %d\n",
810 interfacePriv->interfaceMode);
811 return -EPERM;
814 enable = *(u8*)(extra);
816 if (enable) {
817 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
818 priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
819 priv->connection_config.encryptionModeMask |=
820 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4;
821 } else {
822 priv->connection_config.authModeMask &= ~(CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
823 priv->connection_config.encryptionModeMask &=
824 ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4);
827 func_exit();
828 return 0;
831 static int
832 iwprivswpikey(struct net_device *dev, struct iw_request_info *info,
833 union iwreq_data *wrqu, char *extra)
835 int r = 0, i;
836 CsrWifiSmeKey key;
837 unifiio_wapi_key_t inKey;
838 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
839 unifi_priv_t *priv = interfacePriv->privPtr;
840 func_enter();
842 unifi_trace(priv, UDBG1, "iwprivswpikey\n" );
844 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
845 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
846 unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
847 interfacePriv->interfaceMode);
848 return -EPERM;
851 inKey = *(unifiio_wapi_key_t*)(extra);
853 if (inKey.unicastKey) {
854 key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
855 } else {
856 key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
859 key.keyIndex = inKey.keyIndex;
861 /* memcpy(key.keyRsc, inKey.keyRsc, 16); */
862 for (i = 0; i < 16; i+= 2)
864 key.keyRsc[i/2] = inKey.keyRsc[i+1] << 8 | inKey.keyRsc[i];
867 memcpy(key.address.a, inKey.address, 6);
868 key.keyLength = 32;
869 memcpy(key.key, inKey.key, 32);
870 key.authenticator = 0;
871 key.wepTxKey = 0;
873 unifi_trace(priv, UDBG1, "keyType = %d, keyIndex = %d, wepTxKey = %d, keyRsc = %x:%x, auth = %d, address = %x:%x, "
874 "keylength = %d, key = %x:%x\n", key.keyType, key.keyIndex, key.wepTxKey,
875 key.keyRsc[0], key.keyRsc[7], key.authenticator,
876 key.address.a[0], key.address.a[5], key.keyLength, key.key[0],
877 key.key[15]);
879 r = sme_mgt_key(priv, &key, CSR_WIFI_SME_LIST_ACTION_ADD);
880 if (r) {
881 unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
882 return convert_sme_error(r);
885 func_exit();
886 return r;
888 #endif
891 static int
892 unifi_giwname(struct net_device *dev, struct iw_request_info *info,
893 union iwreq_data *wrqu, char *extra)
895 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
896 unifi_priv_t *priv = interfacePriv->privPtr;
897 char *name = wrqu->name;
898 unifi_trace(priv, UDBG2, "unifi_giwname\n");
900 if (priv->if_index == CSR_INDEX_5G) {
901 strcpy(name, "IEEE 802.11-a");
902 } else {
903 strcpy(name, "IEEE 802.11-bgn");
905 return 0;
906 } /* unifi_giwname() */
909 static int
910 unifi_siwfreq(struct net_device *dev, struct iw_request_info *info,
911 union iwreq_data *wrqu, char *extra)
913 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
914 unifi_priv_t *priv = interfacePriv->privPtr;
915 struct iw_freq *freq = (struct iw_freq *)wrqu;
917 func_enter();
918 unifi_trace(priv, UDBG2, "unifi_siwfreq\n");
920 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
921 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
922 unifi_error(priv, "unifi_siwfreq: not permitted in Mode %d\n",
923 interfacePriv->interfaceMode);
924 return -EPERM;
929 * Channel is stored in the connection configuration,
930 * and set later when ask for a connection.
932 if ((freq->e == 0) && (freq->m <= 1000)) {
933 priv->connection_config.adhocChannel = freq->m;
934 } else {
935 priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e);
938 func_exit();
939 return 0;
940 } /* unifi_siwfreq() */
943 static int
944 unifi_giwfreq(struct net_device *dev, struct iw_request_info *info,
945 union iwreq_data *wrqu, char *extra)
947 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
948 unifi_priv_t *priv = interfacePriv->privPtr;
949 struct iw_freq *freq = (struct iw_freq *)wrqu;
950 int err = 0;
951 CsrWifiSmeConnectionInfo connectionInfo;
953 func_enter();
954 unifi_trace(priv, UDBG2, "unifi_giwfreq\n");
955 CHECK_INITED(priv);
957 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
958 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
959 unifi_error(priv, "unifi_giwfreq: not permitted in Mode %d\n",
960 interfacePriv->interfaceMode);
961 return -EPERM;
965 UF_RTNL_UNLOCK();
966 err = sme_mgt_connection_info_get(priv, &connectionInfo);
967 UF_RTNL_LOCK();
969 freq->m = channel_to_mhz(connectionInfo.channelNumber,
970 (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0));
971 freq->e = 6;
973 func_exit();
974 return convert_sme_error(err);
975 } /* unifi_giwfreq() */
978 static int
979 unifi_siwmode(struct net_device *dev, struct iw_request_info *info,
980 union iwreq_data *wrqu, char *extra)
982 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
983 unifi_priv_t *priv = interfacePriv->privPtr;
985 func_enter();
986 unifi_trace(priv, UDBG2, "unifi_siwmode\n");
988 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
989 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
990 unifi_error(priv, "unifi_siwmode: not permitted in Mode %d\n",
991 interfacePriv->interfaceMode);
992 return -EPERM;
996 switch(wrqu->mode) {
997 case IW_MODE_ADHOC:
998 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ADHOC;
999 break;
1000 case IW_MODE_INFRA:
1001 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE;
1002 break;
1003 case IW_MODE_AUTO:
1004 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ANY_BSS;
1005 break;
1006 default:
1007 unifi_notice(priv, "Unknown IW MODE value.\n");
1010 /* Clear the SSID and BSSID configuration */
1011 priv->connection_config.ssid.length = 0;
1012 memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1014 func_exit();
1015 return 0;
1016 } /* unifi_siwmode() */
1020 static int
1021 unifi_giwmode(struct net_device *dev, struct iw_request_info *info,
1022 union iwreq_data *wrqu, char *extra)
1024 int r = 0;
1025 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1026 unifi_priv_t *priv = interfacePriv->privPtr;
1027 CsrWifiSmeConnectionConfig connectionConfig;
1029 func_enter();
1030 unifi_trace(priv, UDBG2, "unifi_giwmode\n");
1031 CHECK_INITED(priv);
1033 unifi_trace(priv, UDBG2, "unifi_giwmode: Exisitng mode = 0x%x\n",
1034 interfacePriv->interfaceMode);
1035 switch(interfacePriv->interfaceMode) {
1036 case CSR_WIFI_ROUTER_CTRL_MODE_STA:
1037 case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI:
1038 wrqu->mode = IW_MODE_INFRA;
1039 break;
1040 case CSR_WIFI_ROUTER_CTRL_MODE_AP:
1041 case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO:
1042 wrqu->mode = IW_MODE_MASTER;
1043 break;
1044 case CSR_WIFI_ROUTER_CTRL_MODE_IBSS:
1045 wrqu->mode = IW_MODE_ADHOC;
1046 break;
1047 case CSR_WIFI_ROUTER_CTRL_MODE_P2P:
1048 case CSR_WIFI_ROUTER_CTRL_MODE_NONE:
1049 UF_RTNL_UNLOCK();
1050 r = sme_mgt_connection_config_get(priv, &connectionConfig);
1051 UF_RTNL_LOCK();
1052 if (r == 0) {
1053 switch(connectionConfig.bssType) {
1054 case CSR_WIFI_SME_BSS_TYPE_ADHOC:
1055 wrqu->mode = IW_MODE_ADHOC;
1056 break;
1057 case CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE:
1058 wrqu->mode = IW_MODE_INFRA;
1059 break;
1060 default:
1061 wrqu->mode = IW_MODE_AUTO;
1062 unifi_notice(priv, "Unknown IW MODE value.\n");
1065 break;
1066 default:
1067 wrqu->mode = IW_MODE_AUTO;
1068 unifi_notice(priv, "Unknown IW MODE value.\n");
1071 unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode);
1072 func_exit();
1073 return r;
1074 } /* unifi_giwmode() */
1078 static int
1079 unifi_giwrange(struct net_device *dev, struct iw_request_info *info,
1080 union iwreq_data *wrqu, char *extra)
1082 struct iw_point *dwrq = &wrqu->data;
1083 struct iw_range *range = (struct iw_range *) extra;
1084 int i;
1086 unifi_trace(NULL, UDBG2, "unifi_giwrange\n");
1088 dwrq->length = sizeof(struct iw_range);
1089 memset(range, 0, sizeof(*range));
1090 range->min_nwid = 0x0000;
1091 range->max_nwid = 0x0000;
1094 * Don't report the frequency/channel table, then the channel
1095 * number returned elsewhere will be printed as a channel number.
1098 /* Ranges of values reported in quality structs */
1099 range->max_qual.qual = 40; /* Max expected qual value */
1100 range->max_qual.level = -120; /* Noise floor in dBm */
1101 range->max_qual.noise = -120; /* Noise floor in dBm */
1104 /* space for IW_MAX_BITRATES (8 up to WE15, 32 later) */
1105 i = 0;
1106 #if WIRELESS_EXT > 15
1107 range->bitrate[i++] = 2 * 500000;
1108 range->bitrate[i++] = 4 * 500000;
1109 range->bitrate[i++] = 11 * 500000;
1110 range->bitrate[i++] = 22 * 500000;
1111 range->bitrate[i++] = 12 * 500000;
1112 range->bitrate[i++] = 18 * 500000;
1113 range->bitrate[i++] = 24 * 500000;
1114 range->bitrate[i++] = 36 * 500000;
1115 range->bitrate[i++] = 48 * 500000;
1116 range->bitrate[i++] = 72 * 500000;
1117 range->bitrate[i++] = 96 * 500000;
1118 range->bitrate[i++] = 108 * 500000;
1119 #else
1120 range->bitrate[i++] = 2 * 500000;
1121 range->bitrate[i++] = 4 * 500000;
1122 range->bitrate[i++] = 11 * 500000;
1123 range->bitrate[i++] = 22 * 500000;
1124 range->bitrate[i++] = 24 * 500000;
1125 range->bitrate[i++] = 48 * 500000;
1126 range->bitrate[i++] = 96 * 500000;
1127 range->bitrate[i++] = 108 * 500000;
1128 #endif /* WIRELESS_EXT < 16 */
1129 range->num_bitrates = i;
1131 range->max_encoding_tokens = NUM_WEPKEYS;
1132 range->num_encoding_sizes = 2;
1133 range->encoding_size[0] = 5;
1134 range->encoding_size[1] = 13;
1136 range->we_version_source = 20;
1137 range->we_version_compiled = WIRELESS_EXT;
1139 /* Number of channels available in h/w */
1140 range->num_channels = 14;
1141 /* Number of entries in freq[] array */
1142 range->num_frequency = 14;
1143 for (i = 0; (i < range->num_frequency) && (i < IW_MAX_FREQUENCIES); i++) {
1144 int chan = i + 1;
1145 range->freq[i].i = chan;
1146 range->freq[i].m = channel_to_mhz(chan, 0);
1147 range->freq[i].e = 6;
1149 if ((i+3) < IW_MAX_FREQUENCIES) {
1150 range->freq[i].i = 36;
1151 range->freq[i].m = channel_to_mhz(36, 1);
1152 range->freq[i].e = 6;
1153 range->freq[i+1].i = 40;
1154 range->freq[i+1].m = channel_to_mhz(40, 1);
1155 range->freq[i+1].e = 6;
1156 range->freq[i+2].i = 44;
1157 range->freq[i+2].m = channel_to_mhz(44, 1);
1158 range->freq[i+2].e = 6;
1159 range->freq[i+3].i = 48;
1160 range->freq[i+3].m = channel_to_mhz(48, 1);
1161 range->freq[i+3].e = 6;
1164 #if WIRELESS_EXT > 16
1165 /* Event capability (kernel + driver) */
1166 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
1167 IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
1168 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
1169 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
1170 range->event_capa[1] = IW_EVENT_CAPA_K_1;
1171 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
1172 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
1173 IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
1174 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
1175 #endif /* WIRELESS_EXT > 16 */
1177 #if WIRELESS_EXT > 17
1178 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1179 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1180 #endif /* WIRELESS_EXT > 17 */
1183 return 0;
1184 } /* unifi_giwrange() */
1187 static int
1188 unifi_siwap(struct net_device *dev, struct iw_request_info *info,
1189 union iwreq_data *wrqu, char *extra)
1191 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1192 unifi_priv_t *priv = interfacePriv->privPtr;
1193 int err = 0;
1194 const unsigned char zero_bssid[ETH_ALEN] = {0x00, 0x00, 0x00,
1195 0x00, 0x00, 0x00};
1197 func_enter();
1199 CHECK_INITED(priv);
1201 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1202 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1203 unifi_error(priv, "unifi_siwap: not permitted in Mode %d\n",
1204 interfacePriv->interfaceMode);
1205 return -EPERM;
1209 if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) {
1210 return -EINVAL;
1213 unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n",
1214 wrqu->ap_addr.sa_data);
1216 if (!memcmp(wrqu->ap_addr.sa_data, zero_bssid, ETH_ALEN)) {
1217 priv->ignore_bssid_join = FALSE;
1218 err = sme_mgt_disconnect(priv);
1219 if (err) {
1220 unifi_trace(priv, UDBG4, "unifi_siwap: Disconnect failed, status %d\n", err);
1222 return 0;
1225 if (priv->ignore_bssid_join) {
1226 unifi_trace(priv, UDBG4, "unifi_siwap: ignoring second join\n");
1227 priv->ignore_bssid_join = FALSE;
1228 } else {
1229 memcpy(priv->connection_config.bssid.a, wrqu->ap_addr.sa_data, ETH_ALEN);
1230 unifi_trace(priv, UDBG1, "unifi_siwap: Joining %X:%X:%X:%X:%X:%X\n",
1231 priv->connection_config.bssid.a[0],
1232 priv->connection_config.bssid.a[1],
1233 priv->connection_config.bssid.a[2],
1234 priv->connection_config.bssid.a[3],
1235 priv->connection_config.bssid.a[4],
1236 priv->connection_config.bssid.a[5]);
1237 err = sme_mgt_connect(priv);
1238 if (err) {
1239 unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err);
1240 func_exit();
1241 return convert_sme_error(err);
1244 func_exit();
1246 return 0;
1247 } /* unifi_siwap() */
1250 static int
1251 unifi_giwap(struct net_device *dev, struct iw_request_info *info,
1252 union iwreq_data *wrqu, char *extra)
1254 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1255 unifi_priv_t *priv = interfacePriv->privPtr;
1256 CsrWifiSmeConnectionInfo connectionInfo;
1257 int r = 0;
1258 u8 *bssid;
1260 func_enter();
1262 CHECK_INITED(priv);
1263 unifi_trace(priv, UDBG2, "unifi_giwap\n");
1265 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1266 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1267 unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
1268 interfacePriv->interfaceMode);
1269 return -EPERM;
1272 UF_RTNL_UNLOCK();
1273 r = sme_mgt_connection_info_get(priv, &connectionInfo);
1274 UF_RTNL_LOCK();
1276 if (r == 0) {
1277 bssid = connectionInfo.bssid.a;
1278 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1279 unifi_trace(priv, UDBG4, "unifi_giwap: BSSID = %pM\n", bssid);
1281 memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
1282 } else {
1283 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1286 func_exit();
1287 return 0;
1288 } /* unifi_giwap() */
1291 static int
1292 unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
1293 union iwreq_data *wrqu, char *extra)
1295 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1296 unifi_priv_t *priv = interfacePriv->privPtr;
1297 int scantype;
1298 int r;
1299 CsrWifiSsid scan_ssid;
1300 unsigned char *channel_list = NULL;
1301 int chans_good = 0;
1302 #if WIRELESS_EXT > 17
1303 struct iw_point *data = &wrqu->data;
1304 struct iw_scan_req *req = (struct iw_scan_req *) extra;
1305 #endif
1307 func_enter();
1309 CHECK_INITED(priv);
1311 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1312 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1313 unifi_error(priv, "unifi_siwscan: not permitted in Mode %d\n",
1314 interfacePriv->interfaceMode);
1315 return -EPERM;
1319 scantype = UNIFI_SCAN_ACTIVE;
1321 #if WIRELESS_EXT > 17
1322 /* Providing a valid channel list will force an active scan */
1323 if (req) {
1324 if ((req->num_channels > 0) && (req->num_channels < IW_MAX_FREQUENCIES)) {
1325 channel_list = kmalloc(req->num_channels, GFP_KERNEL);
1326 if (channel_list) {
1327 int i;
1328 for (i = 0; i < req->num_channels; i++) {
1329 /* Convert frequency to channel number */
1330 int ch = wext_freq_to_channel(req->channel_list[i].m,
1331 req->channel_list[i].e);
1332 if (ch) {
1333 channel_list[chans_good++] = ch;
1336 unifi_trace(priv, UDBG1,
1337 "SIWSCAN: Scanning %d channels\n", chans_good);
1338 } else {
1339 /* Fall back to scanning all */
1340 unifi_error(priv, "SIWSCAN: Can't alloc channel_list (%d)\n",
1341 req->num_channels);
1346 if (req && (data->flags & IW_SCAN_THIS_ESSID)) {
1347 memcpy(scan_ssid.ssid, req->essid, req->essid_len);
1348 scan_ssid.length = req->essid_len;
1349 unifi_trace(priv, UDBG1,
1350 "SIWSCAN: Scanning for %.*s\n",
1351 scan_ssid.length, scan_ssid.ssid);
1352 } else
1353 #endif
1355 unifi_trace(priv, UDBG1, "SIWSCAN: Scanning for all APs\n");
1356 scan_ssid.length = 0;
1359 r = sme_mgt_scan_full(priv, &scan_ssid, chans_good, channel_list);
1360 if (r) {
1361 unifi_error(priv, "SIWSCAN: Scan returned error %d\n", r);
1362 } else {
1363 unifi_trace(priv, UDBG1, "SIWSCAN: Scan done\n");
1364 wext_send_scan_results_event(priv);
1367 if (channel_list) {
1368 kfree(channel_list);
1371 func_exit();
1372 return r;
1374 } /* unifi_siwscan() */
1377 static const unsigned char *
1378 unifi_find_info_element(int id, const unsigned char *info, int len)
1380 const unsigned char *ie = info;
1382 while (len > 1)
1384 int e_id, e_len;
1385 e_id = ie[0];
1386 e_len = ie[1];
1388 /* Return if we find a match */
1389 if (e_id == id)
1391 return ie;
1394 len -= (e_len + 2);
1395 ie += (e_len + 2);
1398 return NULL;
1399 } /* unifi_find_info_element() */
1403 * Translate scan data returned from the card to a card independent
1404 * format that the Wireless Tools will understand - Jean II
1407 unifi_translate_scan(struct net_device *dev,
1408 struct iw_request_info *info,
1409 char *current_ev, char *end_buf,
1410 CsrWifiSmeScanResult *scan_data,
1411 int scan_index)
1413 struct iw_event iwe; /* Temporary buffer */
1414 unsigned char *info_elems;
1415 int info_elem_len;
1416 const unsigned char *elem;
1417 u16 capabilities;
1418 int signal, noise, snr;
1419 char *start_buf = current_ev;
1420 char *current_val; /* For rates */
1421 int i, r;
1423 info_elems = scan_data->informationElements;
1424 info_elem_len = scan_data->informationElementsLength;
1426 if (!scan_data->informationElementsLength || !scan_data->informationElements) {
1427 unifi_error(NULL, "*** NULL SCAN IEs ***\n");
1428 return -EIO;
1431 /* get capinfo bits */
1432 capabilities = scan_data->capabilityInformation;
1434 unifi_trace(NULL, UDBG5, "Capabilities: 0x%x\n", capabilities);
1436 /* First entry *MUST* be the AP MAC address */
1437 memset(&iwe, 0, sizeof(iwe));
1438 iwe.cmd = SIOCGIWAP;
1439 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1440 memcpy(iwe.u.ap_addr.sa_data, scan_data->bssid.a, ETH_ALEN);
1441 iwe.len = IW_EV_ADDR_LEN;
1442 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_ADDR_LEN);
1443 if (r < 0) {
1444 return r;
1446 start_buf += r;
1448 /* Other entries will be displayed in the order we give them */
1450 /* Add the ESSID */
1451 /* find SSID in Info Elems */
1452 elem = unifi_find_info_element(IE_SSID_ID, info_elems, info_elem_len);
1453 if (elem) {
1454 int e_len = elem[1];
1455 const unsigned char *e_ptr = elem + 2;
1456 unsigned char buf[33];
1458 memset(&iwe, 0, sizeof(iwe));
1459 iwe.cmd = SIOCGIWESSID;
1460 iwe.u.essid.length = e_len;
1461 if (iwe.u.essid.length > 32) {
1462 iwe.u.essid.length = 32;
1464 iwe.u.essid.flags = scan_index;
1465 memcpy(buf, e_ptr, iwe.u.essid.length);
1466 buf[iwe.u.essid.length] = '\0';
1467 r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, buf);
1468 if (r < 0) {
1469 return r;
1471 start_buf += r;
1475 /* Add mode */
1476 memset(&iwe, 0, sizeof(iwe));
1477 iwe.cmd = SIOCGIWMODE;
1478 if (scan_data->bssType == CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE) {
1479 iwe.u.mode = IW_MODE_INFRA;
1480 } else {
1481 iwe.u.mode = IW_MODE_ADHOC;
1483 iwe.len = IW_EV_UINT_LEN;
1484 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_UINT_LEN);
1485 if (r < 0) {
1486 return r;
1488 start_buf += r;
1490 /* Add frequency. iwlist will convert to channel using table given in giwrange */
1491 memset(&iwe, 0, sizeof(iwe));
1492 iwe.cmd = SIOCGIWFREQ;
1493 iwe.u.freq.m = scan_data->channelFrequency;
1494 iwe.u.freq.e = 6;
1495 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_FREQ_LEN);
1496 if (r < 0) {
1497 return r;
1499 start_buf += r;
1502 /* Add quality statistics */
1503 iwe.cmd = IWEVQUAL;
1505 * level and noise below are mapped into an unsigned 8 bit number,
1506 * ranging from [-192; 63]. The way this is achieved is simply to
1507 * add 0x100 onto the number if it is negative,
1508 * once clipped to the correct range.
1510 signal = scan_data->rssi; /* This value is in dBm */
1511 /* Clip range of snr */
1512 snr = (scan_data->snr > 0) ? scan_data->snr : 0; /* In dB relative, from 0 - 255 */
1513 snr = (snr < 255) ? snr : 255;
1514 noise = signal - snr;
1516 /* Clip range of signal */
1517 signal = (signal < 63) ? signal : 63;
1518 signal = (signal > -192) ? signal : -192;
1520 /* Clip range of noise */
1521 noise = (noise < 63) ? noise : 63;
1522 noise = (noise > -192) ? noise : -192;
1524 /* Make u8 */
1525 signal = ( signal < 0 ) ? signal + 0x100 : signal;
1526 noise = ( noise < 0 ) ? noise + 0x100 : noise;
1528 iwe.u.qual.level = (u8)signal; /* -192 : 63 */
1529 iwe.u.qual.noise = (u8)noise; /* -192 : 63 */
1530 iwe.u.qual.qual = snr; /* 0 : 255 */
1531 iwe.u.qual.updated = 0;
1532 #if WIRELESS_EXT > 16
1533 iwe.u.qual.updated |= IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED |
1534 IW_QUAL_QUAL_UPDATED;
1535 #if WIRELESS_EXT > 18
1536 iwe.u.qual.updated |= IW_QUAL_DBM;
1537 #endif
1538 #endif
1539 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_QUAL_LEN);
1540 if (r < 0) {
1541 return r;
1543 start_buf += r;
1545 /* Add encryption capability */
1546 iwe.cmd = SIOCGIWENCODE;
1547 if (capabilities & SIG_CAP_PRIVACY) {
1548 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1549 } else {
1550 iwe.u.data.flags = IW_ENCODE_DISABLED;
1552 iwe.u.data.length = 0;
1553 iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
1554 r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, "");
1555 if (r < 0) {
1556 return r;
1558 start_buf += r;
1562 * Rate : stuffing multiple values in a single event require a bit
1563 * more of magic - Jean II
1565 current_val = start_buf + IW_EV_LCP_LEN;
1567 iwe.cmd = SIOCGIWRATE;
1568 /* Those two flags are ignored... */
1569 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1571 elem = unifi_find_info_element(IE_SUPPORTED_RATES_ID,
1572 info_elems, info_elem_len);
1573 if (elem) {
1574 int e_len = elem[1];
1575 const unsigned char *e_ptr = elem + 2;
1578 * Count how many rates we have.
1579 * Zero marks the end of the list, if the list is not truncated.
1581 /* Max 8 values */
1582 for (i = 0; i < e_len; i++) {
1583 if (e_ptr[i] == 0) {
1584 break;
1586 /* Bit rate given in 500 kb/s units (+ 0x80) */
1587 iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1588 /* Add new value to event */
1589 r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1590 if (r < 0) {
1591 return r;
1593 current_val +=r;
1597 elem = unifi_find_info_element(IE_EXTENDED_SUPPORTED_RATES_ID,
1598 info_elems, info_elem_len);
1599 if (elem) {
1600 int e_len = elem[1];
1601 const unsigned char *e_ptr = elem + 2;
1604 * Count how many rates we have.
1605 * Zero marks the end of the list, if the list is not truncated.
1607 /* Max 8 values */
1608 for (i = 0; i < e_len; i++) {
1609 if (e_ptr[i] == 0) {
1610 break;
1612 /* Bit rate given in 500 kb/s units (+ 0x80) */
1613 iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1614 /* Add new value to event */
1615 r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1616 if (r < 0) {
1617 return r;
1619 current_val +=r;
1622 /* Check if we added any rates event */
1623 if ((current_val - start_buf) > IW_EV_LCP_LEN) {
1624 start_buf = current_val;
1628 #if WIRELESS_EXT > 17
1629 memset(&iwe, 0, sizeof(iwe));
1630 iwe.cmd = IWEVGENIE;
1631 iwe.u.data.length = info_elem_len;
1633 r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, info_elems);
1634 if (r < 0) {
1635 return r;
1638 start_buf += r;
1639 #endif /* WE > 17 */
1641 return (start_buf - current_ev);
1642 } /* unifi_translate_scan() */
1646 static int
1647 unifi_giwscan(struct net_device *dev, struct iw_request_info *info,
1648 union iwreq_data *wrqu, char *extra)
1650 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1651 unifi_priv_t *priv = interfacePriv->privPtr;
1652 struct iw_point *dwrq = &wrqu->data;
1653 int r;
1655 CHECK_INITED(priv);
1657 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1658 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1659 unifi_error(priv, "unifi_giwscan: not permitted in Mode %d\n",
1660 interfacePriv->interfaceMode);
1661 return -EPERM;
1665 unifi_trace(priv, UDBG1,
1666 "unifi_giwscan: buffer (%d bytes) \n",
1667 dwrq->length);
1668 UF_RTNL_UNLOCK();
1669 r = sme_mgt_scan_results_get_async(priv, info, extra, dwrq->length);
1670 UF_RTNL_LOCK();
1671 if (r < 0) {
1672 unifi_trace(priv, UDBG1,
1673 "unifi_giwscan: buffer (%d bytes) not big enough.\n",
1674 dwrq->length);
1675 return r;
1678 dwrq->length = r;
1679 dwrq->flags = 0;
1681 return 0;
1682 } /* unifi_giwscan() */
1686 * ---------------------------------------------------------------------------
1687 * unifi_siwessid
1689 * Request to join a network or start and AdHoc.
1691 * Arguments:
1692 * dev Pointer to network device struct.
1693 * info Pointer to broken-out ioctl request.
1694 * data Pointer to argument data.
1695 * essid Pointer to string giving name of network to join
1696 * or start
1698 * Returns:
1699 * 0 on success and everything complete
1700 * -EINPROGRESS to have the higher level call the commit method.
1701 * ---------------------------------------------------------------------------
1703 static int
1704 unifi_siwessid(struct net_device *dev, struct iw_request_info *info,
1705 struct iw_point *data, char *essid)
1707 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1708 unifi_priv_t *priv = interfacePriv->privPtr;
1709 int len;
1710 int err = 0;
1712 func_enter();
1713 CHECK_INITED(priv);
1715 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1716 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1717 unifi_error(priv, "unifi_siwessid: not permitted in Mode %d\n",
1718 interfacePriv->interfaceMode);
1719 return -EPERM;
1723 len = 0;
1724 if (data->flags & 1) {
1725 /* Limit length */
1726 len = data->length;
1727 if (len > UNIFI_MAX_SSID_LEN) {
1728 len = UNIFI_MAX_SSID_LEN;
1732 #ifdef UNIFI_DEBUG
1734 char essid_str[UNIFI_MAX_SSID_LEN+1];
1735 int i;
1737 for (i = 0; i < len; i++) {
1738 essid_str[i] = (isprint(essid[i]) ? essid[i] : '?');
1740 essid_str[i] = '\0';
1742 unifi_trace(priv, UDBG1, "unifi_siwessid: asked for '%*s' (%d)\n", len, essid_str, len);
1743 unifi_trace(priv, UDBG2, " with authModeMask = %d", priv->connection_config.authModeMask);
1745 #endif
1747 memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1748 if (len) {
1749 if (essid[len - 1] == 0) {
1750 len --;
1753 memcpy(priv->connection_config.ssid.ssid, essid, len);
1754 priv->connection_config.ssid.length = len;
1756 } else {
1757 priv->connection_config.ssid.length = 0;
1760 UF_RTNL_UNLOCK();
1761 err = sme_mgt_connect(priv);
1762 UF_RTNL_LOCK();
1763 if (err) {
1764 unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err);
1765 func_exit();
1766 return convert_sme_error(err);
1769 func_exit();
1770 return 0;
1771 } /* unifi_siwessid() */
1774 static int
1775 unifi_giwessid(struct net_device *dev, struct iw_request_info *info,
1776 union iwreq_data *wrqu, char *essid)
1778 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1779 unifi_priv_t *priv = interfacePriv->privPtr;
1780 struct iw_point *data = &wrqu->essid;
1781 CsrWifiSmeConnectionInfo connectionInfo;
1782 int r = 0;
1784 func_enter();
1785 unifi_trace(priv, UDBG2, "unifi_giwessid\n");
1786 CHECK_INITED(priv);
1788 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1789 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1790 unifi_error(priv, "unifi_giwessid: not permitted in Mode %d\n",
1791 interfacePriv->interfaceMode);
1792 return -EPERM;
1795 UF_RTNL_UNLOCK();
1796 r = sme_mgt_connection_info_get(priv, &connectionInfo);
1797 UF_RTNL_LOCK();
1799 if (r == 0) {
1800 data->length = connectionInfo.ssid.length;
1801 strncpy(essid,
1802 connectionInfo.ssid.ssid,
1803 data->length);
1804 data->flags = 1; /* active */
1806 unifi_trace(priv, UDBG2, "unifi_giwessid: %.*s\n",
1807 data->length, essid);
1810 func_exit();
1812 return 0;
1813 } /* unifi_giwessid() */
1816 static int
1817 unifi_siwrate(struct net_device *dev, struct iw_request_info *info,
1818 union iwreq_data *wrqu, char *extra)
1820 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1821 unifi_priv_t *priv = interfacePriv->privPtr;
1822 struct iw_param *args = &wrqu->bitrate;
1823 CsrWifiSmeMibConfig mibConfig;
1824 int r;
1826 func_enter();
1828 CHECK_INITED(priv);
1829 unifi_trace(priv, UDBG2, "unifi_siwrate\n");
1832 * If args->fixed == 0, value is max rate or -1 for best
1833 * If args->fixed == 1, value is rate to set or -1 for best
1834 * args->disabled and args->flags are not used in SIOCSIWRATE
1837 /* Get, modify and set the MIB data */
1838 UF_RTNL_UNLOCK();
1839 r = sme_mgt_mib_config_get(priv, &mibConfig);
1840 UF_RTNL_LOCK();
1841 if (r) {
1842 unifi_error(priv, "unifi_siwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1843 return r;
1846 /* Default to auto rate algorithm */
1847 /* in 500Kbit/s, 0 means auto */
1848 mibConfig.unifiFixTxDataRate = 0;
1850 if (args->value != -1) {
1851 mibConfig.unifiFixTxDataRate = args->value / 500000;
1854 /* 1 means rate is a maximum, 2 means rate is a set value */
1855 if (args->fixed == 1) {
1856 mibConfig.unifiFixMaxTxDataRate = 0;
1857 } else {
1858 mibConfig.unifiFixMaxTxDataRate = 1;
1860 UF_RTNL_UNLOCK();
1861 r = sme_mgt_mib_config_set(priv, &mibConfig);
1862 UF_RTNL_LOCK();
1863 if (r) {
1864 unifi_error(priv, "unifi_siwrate: Set CsrWifiSmeMibConfigValue failed.\n");
1865 return r;
1868 func_exit();
1870 return 0;
1871 } /* unifi_siwrate() */
1875 static int
1876 unifi_giwrate(struct net_device *dev, struct iw_request_info *info,
1877 union iwreq_data *wrqu, char *extra)
1879 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1880 unifi_priv_t *priv = interfacePriv->privPtr;
1881 struct iw_param *args = &wrqu->bitrate;
1882 int r;
1883 int bitrate, flag;
1884 CsrWifiSmeMibConfig mibConfig;
1885 CsrWifiSmeConnectionStats connectionStats;
1887 func_enter();
1888 unifi_trace(priv, UDBG2, "unifi_giwrate\n");
1889 CHECK_INITED(priv);
1891 flag = 0;
1892 bitrate = 0;
1893 UF_RTNL_UNLOCK();
1894 r = sme_mgt_mib_config_get(priv, &mibConfig);
1895 UF_RTNL_LOCK();
1896 if (r) {
1897 unifi_error(priv, "unifi_giwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1898 return r;
1901 bitrate = mibConfig.unifiFixTxDataRate;
1902 flag = mibConfig.unifiFixMaxTxDataRate;
1904 /* Used the value returned by the SME if MIB returns 0 */
1905 if (bitrate == 0) {
1906 UF_RTNL_UNLOCK();
1907 r = sme_mgt_connection_stats_get(priv, &connectionStats);
1908 UF_RTNL_LOCK();
1909 /* Ignore errors, we may be disconnected */
1910 if (r == 0) {
1911 bitrate = connectionStats.unifiTxDataRate;
1915 args->value = bitrate * 500000;
1916 args->fixed = !flag;
1918 func_exit();
1920 return 0;
1921 } /* unifi_giwrate() */
1924 static int
1925 unifi_siwrts(struct net_device *dev, struct iw_request_info *info,
1926 union iwreq_data *wrqu, char *extra)
1928 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1929 unifi_priv_t *priv = interfacePriv->privPtr;
1930 int val = wrqu->rts.value;
1931 int r = 0;
1932 CsrWifiSmeMibConfig mibConfig;
1934 unifi_trace(priv, UDBG2, "unifi_siwrts\n");
1935 CHECK_INITED(priv);
1937 if (wrqu->rts.disabled) {
1938 val = 2347;
1941 if ( (val < 0) || (val > 2347) )
1943 return -EINVAL;
1946 /* Get, modify and set the MIB data */
1947 UF_RTNL_UNLOCK();
1948 r = sme_mgt_mib_config_get(priv, &mibConfig);
1949 UF_RTNL_LOCK();
1950 if (r) {
1951 unifi_error(priv, "unifi_siwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1952 return r;
1954 mibConfig.dot11RtsThreshold = val;
1955 UF_RTNL_UNLOCK();
1956 r = sme_mgt_mib_config_set(priv, &mibConfig);
1957 UF_RTNL_LOCK();
1958 if (r) {
1959 unifi_error(priv, "unifi_siwrts: Set CsrWifiSmeMibConfigValue failed.\n");
1960 return r;
1963 return 0;
1967 static int
1968 unifi_giwrts(struct net_device *dev, struct iw_request_info *info,
1969 union iwreq_data *wrqu, char *extra)
1971 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1972 unifi_priv_t *priv = interfacePriv->privPtr;
1973 int r;
1974 int rts_thresh;
1975 CsrWifiSmeMibConfig mibConfig;
1977 unifi_trace(priv, UDBG2, "unifi_giwrts\n");
1978 CHECK_INITED(priv);
1980 UF_RTNL_UNLOCK();
1981 r = sme_mgt_mib_config_get(priv, &mibConfig);
1982 UF_RTNL_LOCK();
1983 if (r) {
1984 unifi_error(priv, "unifi_giwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1985 return r;
1988 rts_thresh = mibConfig.dot11RtsThreshold;
1989 if (rts_thresh > 2347) {
1990 rts_thresh = 2347;
1993 wrqu->rts.value = rts_thresh;
1994 wrqu->rts.disabled = (rts_thresh == 2347);
1995 wrqu->rts.fixed = 1;
1997 return 0;
2001 static int
2002 unifi_siwfrag(struct net_device *dev, struct iw_request_info *info,
2003 union iwreq_data *wrqu, char *extra)
2005 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2006 unifi_priv_t *priv = interfacePriv->privPtr;
2007 int val = wrqu->frag.value;
2008 int r = 0;
2009 CsrWifiSmeMibConfig mibConfig;
2011 unifi_trace(priv, UDBG2, "unifi_siwfrag\n");
2012 CHECK_INITED(priv);
2014 if (wrqu->frag.disabled)
2015 val = 2346;
2017 if ( (val < 256) || (val > 2347) )
2018 return -EINVAL;
2020 /* Get, modify and set the MIB data */
2021 UF_RTNL_UNLOCK();
2022 r = sme_mgt_mib_config_get(priv, &mibConfig);
2023 UF_RTNL_LOCK();
2024 if (r) {
2025 unifi_error(priv, "unifi_siwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
2026 return r;
2028 /* Fragmentation Threashold must be even */
2029 mibConfig.dot11FragmentationThreshold = (val & ~0x1);
2030 UF_RTNL_UNLOCK();
2031 r = sme_mgt_mib_config_set(priv, &mibConfig);
2032 UF_RTNL_LOCK();
2033 if (r) {
2034 unifi_error(priv, "unifi_siwfrag: Set CsrWifiSmeMibConfigValue failed.\n");
2035 return r;
2038 return 0;
2042 static int
2043 unifi_giwfrag(struct net_device *dev, struct iw_request_info *info,
2044 union iwreq_data *wrqu, char *extra)
2046 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2047 unifi_priv_t *priv = interfacePriv->privPtr;
2048 int r;
2049 int frag_thresh;
2050 CsrWifiSmeMibConfig mibConfig;
2052 unifi_trace(priv, UDBG2, "unifi_giwfrag\n");
2053 CHECK_INITED(priv);
2055 UF_RTNL_UNLOCK();
2056 r = sme_mgt_mib_config_get(priv, &mibConfig);
2057 UF_RTNL_LOCK();
2058 if (r) {
2059 unifi_error(priv, "unifi_giwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
2060 return r;
2063 frag_thresh = mibConfig.dot11FragmentationThreshold;
2065 /* Build the return structure */
2066 wrqu->frag.value = frag_thresh;
2067 wrqu->frag.disabled = (frag_thresh >= 2346);
2068 wrqu->frag.fixed = 1;
2070 return 0;
2074 static int
2075 unifi_siwencode(struct net_device *dev, struct iw_request_info *info,
2076 union iwreq_data *wrqu, char *extra)
2078 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2079 unifi_priv_t *priv = interfacePriv->privPtr;
2080 struct iw_point *erq = &wrqu->encoding;
2081 int index;
2082 int rc = 0;
2083 int privacy = -1;
2084 CsrWifiSmeKey sme_key;
2086 func_enter();
2087 unifi_trace(priv, UDBG2, "unifi_siwencode\n");
2089 CHECK_INITED(priv);
2091 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2092 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2093 unifi_error(priv, "unifi_siwencode: not permitted in Mode %d\n",
2094 interfacePriv->interfaceMode);
2095 return -EPERM;
2100 * Key index is encoded in the flags.
2101 * 0 - use current default,
2102 * 1-4 - if a key value is given set that key
2103 * if not use that key
2105 index = (erq->flags & IW_ENCODE_INDEX); /* key number, 1-4 */
2106 if ((index < 0) || (index > 4)) {
2107 unifi_error(priv, "unifi_siwencode: Request to set an invalid key (index:%d)", index);
2108 return -EINVAL;
2112 * Basic checking: do we have a key to set ?
2113 * The IW_ENCODE_NOKEY flag is set when no key is present (only change flags),
2114 * but older versions rely on sending a key id 1-4.
2116 if (erq->length > 0) {
2118 /* Check the size of the key */
2119 if ((erq->length > LARGE_KEY_SIZE) || (erq->length < SMALL_KEY_SIZE)) {
2120 unifi_error(priv, "unifi_siwencode: Request to set an invalid key (length:%d)",
2121 erq->length);
2122 return -EINVAL;
2125 /* Check the index (none (i.e. 0) means use current) */
2126 if ((index < 1) || (index > 4)) {
2127 /* If we do not have a previous key, use 1 as default */
2128 if (!priv->wep_tx_key_index) {
2129 priv->wep_tx_key_index = 1;
2131 index = priv->wep_tx_key_index;
2134 /* If we didn't have a key and a valid index is set, we want to remember it*/
2135 if (!priv->wep_tx_key_index) {
2136 priv->wep_tx_key_index = index;
2139 unifi_trace(priv, UDBG1, "Tx key Index is %d\n", priv->wep_tx_key_index);
2141 privacy = 1;
2143 /* Check if the key is not marked as invalid */
2144 if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
2146 unifi_trace(priv, UDBG1, "New %s key (len=%d, index=%d)\n",
2147 (priv->wep_tx_key_index == index) ? "tx" : "",
2148 erq->length, index);
2150 sme_key.wepTxKey = (priv->wep_tx_key_index == index);
2151 if (priv->wep_tx_key_index == index) {
2152 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2153 } else {
2154 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2156 /* Key index is zero based in SME but 1 based in wext */
2157 sme_key.keyIndex = (index - 1);
2158 sme_key.keyLength = erq->length;
2159 sme_key.authenticator = 0;
2160 memset(sme_key.address.a, 0xFF, ETH_ALEN);
2161 memcpy(sme_key.key, extra, erq->length);
2163 UF_RTNL_UNLOCK();
2164 rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2165 UF_RTNL_LOCK();
2166 if (rc) {
2167 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2168 return convert_sme_error(rc);
2171 /* Store the key to be reported by the SIOCGIWENCODE handler */
2172 priv->wep_keys[index - 1].len = erq->length;
2173 memcpy(priv->wep_keys[index - 1].key, extra, erq->length);
2175 } else {
2177 * No additional key data, so it must be a request to change the
2178 * active key.
2180 if (index != 0) {
2181 unifi_trace(priv, UDBG1, "Tx key Index is %d\n", index - 1);
2183 /* Store the index to be reported by the SIOCGIWENCODE handler */
2184 priv->wep_tx_key_index = index;
2186 sme_key.wepTxKey = 1;
2187 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2189 /* Key index is zero based in SME but 1 based in wext */
2190 sme_key.keyIndex = (index - 1);
2191 sme_key.keyLength = 0;
2192 sme_key.authenticator = 0;
2193 UF_RTNL_UNLOCK();
2194 rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2195 UF_RTNL_LOCK();
2196 if (rc) {
2197 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2198 return convert_sme_error(rc);
2201 /* Turn on encryption */
2202 privacy = 1;
2206 /* Read the flags */
2207 if (erq->flags & IW_ENCODE_DISABLED) {
2208 /* disable encryption */
2209 unifi_trace(priv, UDBG1, "disable WEP encryption\n");
2210 privacy = 0;
2212 priv->wep_tx_key_index = 0;
2214 unifi_trace(priv, UDBG1, "IW_ENCODE_DISABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2215 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2218 if (erq->flags & IW_ENCODE_RESTRICTED) {
2219 /* Use shared key auth */
2220 unifi_trace(priv, UDBG1, "IW_ENCODE_RESTRICTED: CSR_WIFI_SME_AUTH_MODE_80211_SHARED\n");
2221 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2223 /* Turn on encryption */
2224 privacy = 1;
2226 if (erq->flags & IW_ENCODE_OPEN) {
2227 unifi_trace(priv, UDBG1, "IW_ENCODE_OPEN: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2228 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2231 /* Commit the changes to flags if needed */
2232 if (privacy != -1) {
2233 priv->connection_config.privacyMode = privacy ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2234 priv->connection_config.encryptionModeMask = privacy ? (CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 |
2235 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 |
2236 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2237 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104) :
2238 CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2241 func_exit_r(rc);
2242 return convert_sme_error(rc);
2244 } /* unifi_siwencode() */
2248 static int
2249 unifi_giwencode(struct net_device *dev, struct iw_request_info *info,
2250 union iwreq_data *wrqu, char *extra)
2252 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2253 unifi_priv_t *priv = interfacePriv->privPtr;
2254 struct iw_point *erq = &wrqu->encoding;
2256 unifi_trace(priv, UDBG2, "unifi_giwencode\n");
2258 CHECK_INITED(priv);
2260 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2261 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2262 unifi_error(priv, "unifi_giwencode: not permitted in Mode %d\n",
2263 interfacePriv->interfaceMode);
2264 return -EPERM;
2268 if (priv->connection_config.authModeMask == CSR_WIFI_SME_AUTH_MODE_80211_SHARED) {
2269 erq->flags = IW_ENCODE_RESTRICTED;
2271 else {
2272 if (priv->connection_config.privacyMode == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) {
2273 erq->flags = IW_ENCODE_DISABLED;
2274 } else {
2275 erq->flags = IW_ENCODE_OPEN;
2279 erq->length = 0;
2281 if (erq->flags != IW_ENCODE_DISABLED) {
2282 int index = priv->wep_tx_key_index;
2284 if ((index > 0) && (index <= NUM_WEPKEYS)) {
2285 erq->flags |= (index & IW_ENCODE_INDEX);
2286 erq->length = priv->wep_keys[index - 1].len;
2287 memcpy(extra, priv->wep_keys[index - 1].key, erq->length);
2288 } else {
2289 unifi_notice(priv, "unifi_giwencode: Surprise, do not have a valid key index (%d)\n",
2290 index);
2294 return 0;
2295 } /* unifi_giwencode() */
2298 static int
2299 unifi_siwpower(struct net_device *dev, struct iw_request_info *info,
2300 union iwreq_data *wrqu, char *extra)
2302 struct iw_param *args = &wrqu->power;
2303 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2304 unifi_priv_t *priv = interfacePriv->privPtr;
2305 int listen_interval, wake_for_dtim;
2306 int r = 0;
2307 CsrWifiSmePowerConfig powerConfig;
2309 unifi_trace(priv, UDBG2, "unifi_siwpower\n");
2311 CHECK_INITED(priv);
2313 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2314 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2315 unifi_error(priv, "unifi_siwpower: not permitted in Mode %d\n",
2316 interfacePriv->interfaceMode);
2317 return -EPERM;
2320 UF_RTNL_UNLOCK();
2321 r = sme_mgt_power_config_get(priv, &powerConfig);
2322 UF_RTNL_LOCK();
2323 if (r) {
2324 unifi_error(priv, "unifi_siwpower: Get unifi_PowerConfigValue failed.\n");
2325 return r;
2328 listen_interval = -1;
2329 wake_for_dtim = -1;
2330 if (args->disabled) {
2331 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
2333 else
2335 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
2337 switch (args->flags & IW_POWER_TYPE) {
2338 case 0:
2339 /* not specified */
2340 break;
2341 case IW_POWER_PERIOD:
2342 listen_interval = args->value / 1000;
2343 break;
2344 default:
2345 return -EINVAL;
2348 switch (args->flags & IW_POWER_MODE) {
2349 case 0:
2350 /* not specified */
2351 break;
2352 case IW_POWER_UNICAST_R:
2353 /* not interested in broadcast packets */
2354 wake_for_dtim = 0;
2355 break;
2356 case IW_POWER_ALL_R:
2357 /* yes, we are interested in broadcast packets */
2358 wake_for_dtim = 1;
2359 break;
2360 default:
2361 return -EINVAL;
2365 if (listen_interval > 0) {
2366 powerConfig.listenIntervalTu = listen_interval;
2367 unifi_trace(priv, UDBG4, "unifi_siwpower: new Listen Interval = %d.\n",
2368 powerConfig.listenIntervalTu);
2371 if (wake_for_dtim >= 0) {
2372 powerConfig.rxDtims = wake_for_dtim;
2374 UF_RTNL_UNLOCK();
2375 r = sme_mgt_power_config_set(priv, &powerConfig);
2376 UF_RTNL_LOCK();
2377 if (r) {
2378 unifi_error(priv, "unifi_siwpower: Set unifi_PowerConfigValue failed.\n");
2379 return r;
2382 return 0;
2383 } /* unifi_siwpower() */
2386 static int
2387 unifi_giwpower(struct net_device *dev, struct iw_request_info *info,
2388 union iwreq_data *wrqu, char *extra)
2390 struct iw_param *args = &wrqu->power;
2391 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2392 unifi_priv_t *priv = interfacePriv->privPtr;
2393 CsrWifiSmePowerConfig powerConfig;
2394 int r;
2396 unifi_trace(priv, UDBG2, "unifi_giwpower\n");
2398 CHECK_INITED(priv);
2400 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2401 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2402 unifi_error(priv, "unifi_giwpower: not permitted in Mode %d\n",
2403 interfacePriv->interfaceMode);
2404 return -EPERM;
2408 args->flags = 0;
2409 UF_RTNL_UNLOCK();
2410 r = sme_mgt_power_config_get(priv, &powerConfig);
2411 UF_RTNL_LOCK();
2412 if (r) {
2413 unifi_error(priv, "unifi_giwpower: Get unifi_PowerConfigValue failed.\n");
2414 return r;
2417 unifi_trace(priv, UDBG4, "unifi_giwpower: mode=%d\n",
2418 powerConfig.powerSaveLevel);
2420 args->disabled = (powerConfig.powerSaveLevel == CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW);
2421 if (args->disabled) {
2422 args->flags = 0;
2423 return 0;
2426 args->value = powerConfig.listenIntervalTu * 1000;
2427 args->flags |= IW_POWER_PERIOD;
2429 if (powerConfig.rxDtims) {
2430 args->flags |= IW_POWER_ALL_R;
2431 } else {
2432 args->flags |= IW_POWER_UNICAST_R;
2435 return 0;
2436 } /* unifi_giwpower() */
2440 * ---------------------------------------------------------------------------
2441 * unifi_siwcommit - handler for SIOCSIWCOMMIT
2443 * Apply all the parameters that have been set.
2444 * In practice this means:
2445 * - do a scan
2446 * - join a network or start an AdHoc
2447 * - authenticate and associate.
2449 * Arguments:
2450 * None.
2452 * Returns:
2453 * None.
2454 * ---------------------------------------------------------------------------
2456 static int
2457 unifi_siwcommit(struct net_device *dev, struct iw_request_info *info,
2458 union iwreq_data *wrqu, char *extra)
2460 return 0;
2461 } /* unifi_siwcommit() */
2465 static int
2466 unifi_siwmlme(struct net_device *dev, struct iw_request_info *info,
2467 union iwreq_data *wrqu, char *extra)
2469 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2470 unifi_priv_t *priv = interfacePriv->privPtr;
2471 struct iw_mlme *mlme = (struct iw_mlme *)extra;
2472 func_enter();
2474 unifi_trace(priv, UDBG2, "unifi_siwmlme\n");
2475 CHECK_INITED(priv);
2477 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2478 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2479 unifi_error(priv, "unifi_siwmlme: not permitted in Mode %d\n",
2480 interfacePriv->interfaceMode);
2481 return -EPERM;
2485 switch (mlme->cmd) {
2486 case IW_MLME_DEAUTH:
2487 case IW_MLME_DISASSOC:
2488 UF_RTNL_UNLOCK();
2489 sme_mgt_disconnect(priv);
2490 UF_RTNL_LOCK();
2491 break;
2492 default:
2493 func_exit_r(-EOPNOTSUPP);
2494 return -EOPNOTSUPP;
2497 func_exit();
2498 return 0;
2499 } /* unifi_siwmlme() */
2503 * ---------------------------------------------------------------------------
2504 * unifi_siwgenie
2505 * unifi_giwgenie
2507 * WPA : Generic IEEE 802.11 information element (e.g., for WPA/RSN/WMM).
2508 * Handlers for SIOCSIWGENIE, SIOCGIWGENIE - set/get generic IE
2510 * The host program (e.g. wpa_supplicant) uses this call to set the
2511 * additional IEs to accompany the next (Associate?) request.
2513 * Arguments:
2514 * None.
2516 * Returns:
2517 * None.
2518 * Notes:
2519 * From wireless.h:
2520 * This ioctl uses struct iw_point and data buffer that includes IE id
2521 * and len fields. More than one IE may be included in the
2522 * request. Setting the generic IE to empty buffer (len=0) removes the
2523 * generic IE from the driver.
2524 * ---------------------------------------------------------------------------
2526 static int
2527 unifi_siwgenie(struct net_device *dev, struct iw_request_info *info,
2528 union iwreq_data *wrqu, char *extra)
2530 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2531 unifi_priv_t *priv = interfacePriv->privPtr;
2532 int len;
2534 func_enter();
2535 unifi_trace(priv, UDBG2, "unifi_siwgenie\n");
2537 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2538 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2539 unifi_error(priv, "unifi_siwgenie: not permitted in Mode %d\n",
2540 interfacePriv->interfaceMode);
2541 return -EPERM;
2545 if ( priv->connection_config.mlmeAssociateReqInformationElements) {
2546 kfree( priv->connection_config.mlmeAssociateReqInformationElements);
2548 priv->connection_config.mlmeAssociateReqInformationElementsLength = 0;
2549 priv->connection_config.mlmeAssociateReqInformationElements = NULL;
2551 len = wrqu->data.length;
2552 if (len == 0) {
2553 func_exit();
2554 return 0;
2557 priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL);
2558 if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) {
2559 func_exit();
2560 return -ENOMEM;
2563 priv->connection_config.mlmeAssociateReqInformationElementsLength = len;
2564 memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len);
2566 func_exit();
2567 return 0;
2568 } /* unifi_siwgenie() */
2571 static int
2572 unifi_giwgenie(struct net_device *dev, struct iw_request_info *info,
2573 union iwreq_data *wrqu, char *extra)
2575 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2576 unifi_priv_t *priv = interfacePriv->privPtr;
2577 int len;
2579 func_enter();
2580 unifi_trace(priv, UDBG2, "unifi_giwgenie\n");
2582 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2583 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2584 unifi_error(priv, "unifi_giwgenie: not permitted in Mode %d\n",
2585 interfacePriv->interfaceMode);
2586 return -EPERM;
2590 len = priv->connection_config.mlmeAssociateReqInformationElementsLength;
2592 if (len == 0) {
2593 wrqu->data.length = 0;
2594 return 0;
2597 if (wrqu->data.length < len) {
2598 return -E2BIG;
2601 wrqu->data.length = len;
2602 memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len);
2604 func_exit();
2605 return 0;
2606 } /* unifi_giwgenie() */
2610 * ---------------------------------------------------------------------------
2611 * unifi_siwauth
2612 * unifi_giwauth
2614 * Handlers for SIOCSIWAUTH, SIOCGIWAUTH
2615 * Set/get various authentication parameters.
2617 * Arguments:
2620 * Returns:
2621 * None.
2622 * ---------------------------------------------------------------------------
2624 static int
2625 _unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2626 union iwreq_data *wrqu, char *extra)
2628 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2629 unifi_priv_t *priv = interfacePriv->privPtr;
2630 CsrWifiSmeAuthModeMask new_auth;
2632 func_enter();
2633 unifi_trace(priv, UDBG2, "unifi_siwauth\n");
2635 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2636 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2637 unifi_error(priv, "unifi_siwauth: not permitted in Mode %d\n",
2638 interfacePriv->interfaceMode);
2639 return -EPERM;
2644 * This ioctl is safe to call even when UniFi is powered off.
2645 * wpa_supplicant calls it to test whether we support WPA.
2648 switch (wrqu->param.flags & IW_AUTH_INDEX) {
2650 case IW_AUTH_WPA_ENABLED:
2651 unifi_trace(priv, UDBG1, "IW_AUTH_WPA_ENABLED: %d\n", wrqu->param.value);
2653 if (wrqu->param.value == 0) {
2654 unifi_trace(priv, UDBG5, "IW_AUTH_WPA_ENABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2655 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2657 break;
2659 case IW_AUTH_PRIVACY_INVOKED:
2660 unifi_trace(priv, UDBG1, "IW_AUTH_PRIVACY_INVOKED: %d\n", wrqu->param.value);
2662 priv->connection_config.privacyMode = wrqu->param.value ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2663 if (wrqu->param.value == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED)
2665 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2667 break;
2669 case IW_AUTH_80211_AUTH_ALG:
2671 IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
2672 IW_AUTH_ALG_SHARED_KEY 0x00000002
2673 IW_AUTH_ALG_LEAP 0x00000004
2675 new_auth = 0;
2676 if (wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) {
2677 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_OPEN_SYSTEM)\n", wrqu->param.value);
2678 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2680 if (wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) {
2681 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_SHARED_KEY)\n", wrqu->param.value);
2682 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2684 if (wrqu->param.value & IW_AUTH_ALG_LEAP) {
2685 /* Initial exchanges using open-system to set EAP */
2686 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_LEAP)\n", wrqu->param.value);
2687 new_auth |= CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X;
2689 if (new_auth == 0) {
2690 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: invalid value %d\n",
2691 wrqu->param.value);
2692 return -EINVAL;
2693 } else {
2694 priv->connection_config.authModeMask = new_auth;
2696 break;
2698 case IW_AUTH_WPA_VERSION:
2699 unifi_trace(priv, UDBG1, "IW_AUTH_WPA_VERSION: %d\n", wrqu->param.value);
2700 priv->ignore_bssid_join = TRUE;
2702 IW_AUTH_WPA_VERSION_DISABLED 0x00000001
2703 IW_AUTH_WPA_VERSION_WPA 0x00000002
2704 IW_AUTH_WPA_VERSION_WPA2 0x00000004
2707 if (!(wrqu->param.value & IW_AUTH_WPA_VERSION_DISABLED)) {
2709 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2711 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA) {
2712 unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA, WPA-PSK\n");
2713 priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK);
2715 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA2) {
2716 unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA2, WPA2-PSK\n");
2717 priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK);
2720 break;
2722 case IW_AUTH_CIPHER_PAIRWISE:
2723 unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_PAIRWISE: %d\n", wrqu->param.value);
2725 * one of:
2726 IW_AUTH_CIPHER_NONE 0x00000001
2727 IW_AUTH_CIPHER_WEP40 0x00000002
2728 IW_AUTH_CIPHER_TKIP 0x00000004
2729 IW_AUTH_CIPHER_CCMP 0x00000008
2730 IW_AUTH_CIPHER_WEP104 0x00000010
2733 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2735 if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2736 priv->connection_config.encryptionModeMask |=
2737 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2739 if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2740 priv->connection_config.encryptionModeMask |=
2741 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2743 if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2744 priv->connection_config.encryptionModeMask |=
2745 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2747 if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2748 priv->connection_config.encryptionModeMask |=
2749 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2752 break;
2754 case IW_AUTH_CIPHER_GROUP:
2755 unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_GROUP: %d\n", wrqu->param.value);
2757 * Use the WPA version and the group cipher suite to set the permitted
2758 * group key in the MIB. f/w uses this value to validate WPA and RSN IEs
2759 * in the probe responses from the desired BSS(ID)
2762 priv->connection_config.encryptionModeMask &= ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2763 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 |
2764 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP |
2765 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP);
2766 if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2767 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2769 if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2770 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2772 if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2773 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2775 if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2776 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2779 break;
2781 case IW_AUTH_KEY_MGMT:
2782 unifi_trace(priv, UDBG1, "IW_AUTH_KEY_MGMT: %d\n", wrqu->param.value);
2784 IW_AUTH_KEY_MGMT_802_1X 1
2785 IW_AUTH_KEY_MGMT_PSK 2
2787 if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK)) {
2788 /* Check for explicitly set mode. */
2789 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2790 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK;
2792 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2793 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA;
2795 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA: %d\n",
2796 priv->connection_config.authModeMask);
2798 if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK)) {
2799 /* Check for explicitly set mode. */
2800 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2801 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK;
2803 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2804 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2;
2806 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA2: %d\n",
2807 priv->connection_config.authModeMask);
2810 break;
2811 case IW_AUTH_TKIP_COUNTERMEASURES:
2813 * Set to true at the start of the 60 second backup-off period
2814 * following 2 MichaelMIC failures within 60s.
2816 unifi_trace(priv, UDBG1, "IW_AUTH_TKIP_COUNTERMEASURES: %d\n", wrqu->param.value);
2817 break;
2819 case IW_AUTH_DROP_UNENCRYPTED:
2821 * Set to true on init.
2822 * Set to false just before associate if encryption will not be
2823 * required.
2825 * Note this is not the same as the 802.1X controlled port
2827 unifi_trace(priv, UDBG1, "IW_AUTH_DROP_UNENCRYPTED: %d\n", wrqu->param.value);
2828 break;
2830 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2832 * This is set by wpa_supplicant to allow unencrypted EAPOL messages
2833 * even if pairwise keys are set when not using WPA. IEEE 802.1X
2834 * specifies that these frames are not encrypted, but WPA encrypts
2835 * them when pairwise keys are in use.
2836 * I think the UniFi f/w handles this decision for us.
2838 unifi_trace(priv, UDBG1, "IW_AUTH_RX_UNENCRYPTED_EAPOL: %d\n", wrqu->param.value);
2839 break;
2841 case IW_AUTH_ROAMING_CONTROL:
2842 unifi_trace(priv, UDBG1, "IW_AUTH_ROAMING_CONTROL: %d\n", wrqu->param.value);
2843 break;
2845 default:
2846 unifi_trace(priv, UDBG1, "Unsupported auth param %d to 0x%X\n",
2847 wrqu->param.flags & IW_AUTH_INDEX,
2848 wrqu->param.value);
2849 return -EOPNOTSUPP;
2852 unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask);
2853 func_exit();
2855 return 0;
2856 } /* _unifi_siwauth() */
2859 static int
2860 unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2861 union iwreq_data *wrqu, char *extra)
2863 int err = 0;
2865 UF_RTNL_UNLOCK();
2866 err = _unifi_siwauth(dev, info, wrqu, extra);
2867 UF_RTNL_LOCK();
2869 return err;
2870 } /* unifi_siwauth() */
2873 static int
2874 unifi_giwauth(struct net_device *dev, struct iw_request_info *info,
2875 union iwreq_data *wrqu, char *extra)
2877 unifi_trace(NULL, UDBG2, "unifi_giwauth\n");
2878 return -EOPNOTSUPP;
2879 } /* unifi_giwauth() */
2882 * ---------------------------------------------------------------------------
2883 * unifi_siwencodeext
2884 * unifi_giwencodeext
2886 * Handlers for SIOCSIWENCODEEXT, SIOCGIWENCODEEXT - set/get
2887 * encoding token & mode
2889 * Arguments:
2890 * None.
2892 * Returns:
2893 * None.
2895 * Notes:
2896 * For WPA/WPA2 we don't take note of the IW_ENCODE_EXT_SET_TX_KEY flag.
2897 * This flag means "use this key to encode transmissions"; we just
2898 * assume only one key will be set and that is the one to use.
2899 * ---------------------------------------------------------------------------
2901 static int
2902 _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
2903 union iwreq_data *wrqu, char *extra)
2905 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2906 unifi_priv_t *priv = interfacePriv->privPtr;
2907 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
2908 int r = 0;
2909 unsigned char *keydata;
2910 unsigned char tkip_key[32];
2911 int keyid;
2912 unsigned char *a = (unsigned char *)ext->addr.sa_data;
2913 CsrWifiSmeKey sme_key;
2914 CsrWifiSmeKeyType key_type;
2916 func_enter();
2918 CHECK_INITED(priv);
2920 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2921 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2922 unifi_error(priv, "unifi_siwencodeext: not permitted in Mode %d\n",
2923 interfacePriv->interfaceMode);
2924 return -EPERM;
2928 unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n",
2929 wrqu->encoding.flags, ext->alg, ext->ext_flags,
2930 ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX));
2931 unifi_trace(priv, UDBG3, " addr=%pM\n", a);
2933 if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
2934 /* This means use a different key (given by key_idx) for Tx. */
2935 /* NYI */
2936 unifi_trace(priv, UDBG1, KERN_ERR "unifi_siwencodeext: NYI should change tx key id here!!\n");
2937 return -ENOTSUPP;
2940 memset(&sme_key, 0, sizeof(sme_key));
2942 keydata = (unsigned char *)(ext + 1);
2943 keyid = (wrqu->encoding.flags & IW_ENCODE_INDEX);
2946 * Check for request to delete keys for an address.
2948 /* Pick out request for no privacy. */
2949 if (ext->alg == IW_ENCODE_ALG_NONE) {
2951 unifi_trace(priv, UDBG1, "Deleting %s key %d\n",
2952 (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? "GROUP" : "PAIRWISE",
2953 keyid);
2955 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
2956 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2957 } else {
2958 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2960 sme_key.keyIndex = (keyid - 1);
2961 sme_key.keyLength = 0;
2962 sme_key.authenticator = 0;
2963 memcpy(sme_key.address.a, a, ETH_ALEN);
2964 UF_RTNL_UNLOCK();
2965 r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_REMOVE);
2966 UF_RTNL_LOCK();
2967 if (r) {
2968 unifi_error(priv, "Delete key request was rejected with result %d\n", r);
2969 return convert_sme_error(r);
2972 return 0;
2976 * Request is to set a key, not delete
2979 /* Pick out WEP and use set_wep_key(). */
2980 if (ext->alg == IW_ENCODE_ALG_WEP) {
2981 /* WEP-40, WEP-104 */
2983 /* Check for valid key length */
2984 if (!((ext->key_len == 5) || (ext->key_len == 13))) {
2985 unifi_trace(priv, UDBG1, KERN_ERR "Invalid length for WEP key: %d\n", ext->key_len);
2986 return -EINVAL;
2989 unifi_trace(priv, UDBG1, "Setting WEP key %d tx:%d\n",
2990 keyid, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY);
2992 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
2993 sme_key.wepTxKey = TRUE;
2994 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2995 } else {
2996 sme_key.wepTxKey = FALSE;
2997 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2999 sme_key.keyIndex = (keyid - 1);
3000 sme_key.keyLength = ext->key_len;
3001 sme_key.authenticator = 0;
3002 memset(sme_key.address.a, 0xFF, ETH_ALEN);
3003 memcpy(sme_key.key, keydata, ext->key_len);
3004 UF_RTNL_UNLOCK();
3005 r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
3006 UF_RTNL_LOCK();
3007 if (r) {
3008 unifi_error(priv, "siwencodeext: Set key failed (%d)", r);
3009 return convert_sme_error(r);
3012 return 0;
3017 * If we reach here, we are dealing with a WPA/WPA2 key
3020 if (ext->key_len > 32) {
3021 return -EINVAL;
3025 * TKIP keys from wpa_supplicant need swapping.
3026 * What about other supplicants (when they come along)?
3028 if ((ext->alg == IW_ENCODE_ALG_TKIP) && (ext->key_len == 32)) {
3029 memcpy(tkip_key, keydata, 16);
3030 memcpy(tkip_key + 16, keydata + 24, 8);
3031 memcpy(tkip_key + 24, keydata + 16, 8);
3032 keydata = tkip_key;
3035 key_type = (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ?
3036 CSR_WIFI_SME_KEY_TYPE_GROUP : /* Group Key */
3037 CSR_WIFI_SME_KEY_TYPE_PAIRWISE; /* Pairwise Key */
3039 sme_key.keyType = key_type;
3040 sme_key.keyIndex = (keyid - 1);
3041 sme_key.keyLength = ext->key_len;
3042 sme_key.authenticator = 0;
3043 memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN);
3044 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
3046 unifi_trace(priv, UDBG5, "RSC first 6 bytes = %02X:%02X:%02X:%02X:%02X:%02X\n",
3047 ext->rx_seq[0], ext->rx_seq[1], ext->rx_seq[2], ext->rx_seq[3], ext->rx_seq[4], ext->rx_seq[5]);
3049 /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */
3050 sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0];
3051 sme_key.keyRsc[1] = ext->rx_seq[3] << 8 | ext->rx_seq[2];
3052 sme_key.keyRsc[2] = ext->rx_seq[5] << 8 | ext->rx_seq[4];
3053 sme_key.keyRsc[3] = ext->rx_seq[7] << 8 | ext->rx_seq[6];
3057 memcpy(sme_key.key, keydata, ext->key_len);
3058 UF_RTNL_UNLOCK();
3059 r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
3060 UF_RTNL_LOCK();
3061 if (r) {
3062 unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
3063 return convert_sme_error(r);
3066 func_exit();
3067 return r;
3068 } /* _unifi_siwencodeext() */
3071 static int
3072 unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
3073 union iwreq_data *wrqu, char *extra)
3075 int err = 0;
3077 err = _unifi_siwencodeext(dev, info, wrqu, extra);
3079 return err;
3080 } /* unifi_siwencodeext() */
3083 static int
3084 unifi_giwencodeext(struct net_device *dev, struct iw_request_info *info,
3085 union iwreq_data *wrqu, char *extra)
3087 return -EOPNOTSUPP;
3088 } /* unifi_giwencodeext() */
3092 * ---------------------------------------------------------------------------
3093 * unifi_siwpmksa
3095 * SIOCSIWPMKSA - PMKSA cache operation
3096 * The caller passes a pmksa structure:
3097 * - cmd one of ADD, REMOVE, FLUSH
3098 * - bssid MAC address
3099 * - pmkid ID string (16 bytes)
3101 * Arguments:
3102 * None.
3104 * Returns:
3105 * None.
3107 * Notes:
3108 * This is not needed since we provide a siwgenie method.
3109 * ---------------------------------------------------------------------------
3111 #define UNIFI_PMKID_KEY_SIZE 16
3112 static int
3113 unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info,
3114 union iwreq_data *wrqu, char *extra)
3116 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3117 unifi_priv_t *priv = interfacePriv->privPtr;
3118 struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
3119 CsrResult r = 0;
3120 CsrWifiSmePmkidList pmkid_list;
3121 CsrWifiSmePmkid pmkid;
3122 CsrWifiSmeListAction action;
3124 CHECK_INITED(priv);
3126 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
3127 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
3128 unifi_error(priv, "unifi_siwpmksa: not permitted in Mode %d\n",
3129 interfacePriv->interfaceMode);
3130 return -EPERM;
3134 unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %pM\n", pmksa->cmd,
3135 pmksa->bssid.sa_data);
3137 pmkid_list.pmkids = NULL;
3138 switch (pmksa->cmd) {
3139 case IW_PMKSA_ADD:
3140 pmkid_list.pmkids = &pmkid;
3141 action = CSR_WIFI_SME_LIST_ACTION_ADD;
3142 pmkid_list.pmkidsCount = 1;
3143 memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3144 memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3145 break;
3146 case IW_PMKSA_REMOVE:
3147 pmkid_list.pmkids = &pmkid;
3148 action = CSR_WIFI_SME_LIST_ACTION_REMOVE;
3149 pmkid_list.pmkidsCount = 1;
3150 memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3151 memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3152 break;
3153 case IW_PMKSA_FLUSH:
3154 /* Replace current PMKID's with an empty list */
3155 pmkid_list.pmkidsCount = 0;
3156 action = CSR_WIFI_SME_LIST_ACTION_FLUSH;
3157 break;
3158 default:
3159 unifi_notice(priv, "SIWPMKSA: Unknown command (0x%x)\n", pmksa->cmd);
3160 return -EINVAL;
3163 /* Set the Value the pmkid's will have 1 added OR 1 removed OR be cleared at this point */
3164 UF_RTNL_UNLOCK();
3165 r = sme_mgt_pmkid(priv, action, &pmkid_list);
3166 UF_RTNL_LOCK();
3167 if (r) {
3168 unifi_error(priv, "SIWPMKSA: Set PMKID's Failed.\n");
3171 return r;
3173 } /* unifi_siwpmksa() */
3177 * ---------------------------------------------------------------------------
3178 * unifi_get_wireless_stats
3180 * get_wireless_stats method for Linux wireless extensions.
3182 * Arguments:
3183 * dev Pointer to associated netdevice.
3185 * Returns:
3186 * Pointer to iw_statistics struct.
3187 * ---------------------------------------------------------------------------
3189 struct iw_statistics *
3190 unifi_get_wireless_stats(struct net_device *dev)
3192 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3193 unifi_priv_t *priv = interfacePriv->privPtr;
3195 if (priv->init_progress != UNIFI_INIT_COMPLETED) {
3196 return NULL;
3199 return &priv->wext_wireless_stats;
3200 } /* unifi_get_wireless_stats() */
3204 * Structures to export the Wireless Handlers
3207 static const struct iw_priv_args unifi_private_args[] = {
3208 /*{ cmd, set_args, get_args, name } */
3209 { SIOCIWS80211POWERSAVEPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3210 IW_PRIV_TYPE_NONE, "iwprivs80211ps" },
3211 { SIOCIWG80211POWERSAVEPRIV, IW_PRIV_TYPE_NONE,
3212 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IWPRIV_POWER_SAVE_MAX_STRING, "iwprivg80211ps" },
3213 { SIOCIWS80211RELOADDEFAULTSPRIV, IW_PRIV_TYPE_NONE,
3214 IW_PRIV_TYPE_NONE, "iwprivsdefs" },
3215 { SIOCIWSSMEDEBUGPRIV, IW_PRIV_TYPE_CHAR | IWPRIV_SME_DEBUG_MAX_STRING, IW_PRIV_TYPE_NONE, "iwprivssmedebug" },
3216 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3217 { SIOCIWSCONFWAPIPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3218 IW_PRIV_TYPE_NONE, "iwprivsconfwapi" },
3219 { SIOCIWSWAPIKEYPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(unifiio_wapi_key_t),
3220 IW_PRIV_TYPE_NONE, "iwprivswpikey" },
3221 #endif
3222 #ifdef CSR_SUPPORT_WEXT_AP
3223 { SIOCIWSAPCFGPRIV, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_NONE, "AP_SET_CFG" },
3224 { SIOCIWSAPSTARTPRIV, 0,IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING,"AP_BSS_START" },
3225 { SIOCIWSAPSTOPPRIV, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0,
3226 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "AP_BSS_STOP" },
3227 #ifdef ANDROID_BUILD
3228 { SIOCIWSFWRELOADPRIV, IW_PRIV_TYPE_CHAR |256,
3229 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "WL_FW_RELOAD" },
3230 { SIOCIWSSTACKSTART, 0,
3231 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "START" },
3232 { SIOCIWSSTACKSTOP, 0,
3233 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "STOP" },
3234 #endif /* ANDROID_BUILD */
3235 #endif /* CSR_SUPPORT_WEXT_AP */
3238 static const iw_handler unifi_handler[] =
3240 (iw_handler) unifi_siwcommit, /* SIOCSIWCOMMIT */
3241 (iw_handler) unifi_giwname, /* SIOCGIWNAME */
3242 (iw_handler) NULL, /* SIOCSIWNWID */
3243 (iw_handler) NULL, /* SIOCGIWNWID */
3244 (iw_handler) unifi_siwfreq, /* SIOCSIWFREQ */
3245 (iw_handler) unifi_giwfreq, /* SIOCGIWFREQ */
3246 (iw_handler) unifi_siwmode, /* SIOCSIWMODE */
3247 (iw_handler) unifi_giwmode, /* SIOCGIWMODE */
3248 (iw_handler) NULL, /* SIOCSIWSENS */
3249 (iw_handler) NULL, /* SIOCGIWSENS */
3250 (iw_handler) NULL, /* SIOCSIWRANGE */
3251 (iw_handler) unifi_giwrange, /* SIOCGIWRANGE */
3252 (iw_handler) NULL, /* SIOCSIWPRIV */
3253 (iw_handler) NULL, /* SIOCGIWPRIV */
3254 (iw_handler) NULL, /* SIOCSIWSTATS */
3255 (iw_handler) NULL, /* SIOCGIWSTATS */
3256 (iw_handler) NULL, /* SIOCSIWSPY */
3257 (iw_handler) NULL, /* SIOCGIWSPY */
3258 (iw_handler) NULL, /* SIOCSIWTHRSPY */
3259 (iw_handler) NULL, /* SIOCGIWTHRSPY */
3260 (iw_handler) unifi_siwap, /* SIOCSIWAP */
3261 (iw_handler) unifi_giwap, /* SIOCGIWAP */
3262 #if WIRELESS_EXT > 17
3263 /* WPA : IEEE 802.11 MLME requests */
3264 unifi_siwmlme, /* SIOCSIWMLME, request MLME operation */
3265 #else
3266 (iw_handler) NULL, /* -- hole -- */
3267 #endif
3268 (iw_handler) NULL, /* SIOCGIWAPLIST */
3269 (iw_handler) unifi_siwscan, /* SIOCSIWSCAN */
3270 (iw_handler) unifi_giwscan, /* SIOCGIWSCAN */
3271 (iw_handler) unifi_siwessid, /* SIOCSIWESSID */
3272 (iw_handler) unifi_giwessid, /* SIOCGIWESSID */
3273 (iw_handler) NULL, /* SIOCSIWNICKN */
3274 (iw_handler) NULL, /* SIOCGIWNICKN */
3275 (iw_handler) NULL, /* -- hole -- */
3276 (iw_handler) NULL, /* -- hole -- */
3277 unifi_siwrate, /* SIOCSIWRATE */
3278 unifi_giwrate, /* SIOCGIWRATE */
3279 unifi_siwrts, /* SIOCSIWRTS */
3280 unifi_giwrts, /* SIOCGIWRTS */
3281 unifi_siwfrag, /* SIOCSIWFRAG */
3282 unifi_giwfrag, /* SIOCGIWFRAG */
3283 (iw_handler) NULL, /* SIOCSIWTXPOW */
3284 (iw_handler) NULL, /* SIOCGIWTXPOW */
3285 (iw_handler) NULL, /* SIOCSIWRETRY */
3286 (iw_handler) NULL, /* SIOCGIWRETRY */
3287 unifi_siwencode, /* SIOCSIWENCODE */
3288 unifi_giwencode, /* SIOCGIWENCODE */
3289 unifi_siwpower, /* SIOCSIWPOWER */
3290 unifi_giwpower, /* SIOCGIWPOWER */
3291 #if WIRELESS_EXT > 17
3292 (iw_handler) NULL, /* -- hole -- */
3293 (iw_handler) NULL, /* -- hole -- */
3295 /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). */
3296 unifi_siwgenie, /* SIOCSIWGENIE */ /* set generic IE */
3297 unifi_giwgenie, /* SIOCGIWGENIE */ /* get generic IE */
3299 /* WPA : Authentication mode parameters */
3300 unifi_siwauth, /* SIOCSIWAUTH */ /* set authentication mode params */
3301 unifi_giwauth, /* SIOCGIWAUTH */ /* get authentication mode params */
3303 /* WPA : Extended version of encoding configuration */
3304 unifi_siwencodeext, /* SIOCSIWENCODEEXT */ /* set encoding token & mode */
3305 unifi_giwencodeext, /* SIOCGIWENCODEEXT */ /* get encoding token & mode */
3307 /* WPA2 : PMKSA cache management */
3308 unifi_siwpmksa, /* SIOCSIWPMKSA */ /* PMKSA cache operation */
3309 (iw_handler) NULL, /* -- hole -- */
3310 #endif /* WIRELESS_EXT > 17 */
3314 static const iw_handler unifi_private_handler[] =
3316 iwprivs80211ps, /* SIOCIWFIRSTPRIV */
3317 iwprivg80211ps, /* SIOCIWFIRSTPRIV + 1 */
3318 iwprivsdefs, /* SIOCIWFIRSTPRIV + 2 */
3319 (iw_handler) NULL,
3320 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3321 iwprivsconfwapi, /* SIOCIWFIRSTPRIV + 4 */
3322 (iw_handler) NULL, /* SIOCIWFIRSTPRIV + 5 */
3323 iwprivswpikey, /* SIOCIWFIRSTPRIV + 6 */
3324 #else
3325 (iw_handler) NULL,
3326 (iw_handler) NULL,
3327 (iw_handler) NULL,
3328 #endif
3329 (iw_handler) NULL,
3330 iwprivssmedebug, /* SIOCIWFIRSTPRIV + 8 */
3331 #ifdef CSR_SUPPORT_WEXT_AP
3332 (iw_handler) NULL,
3333 iwprivsapconfig,
3334 (iw_handler) NULL,
3335 iwprivsapstart,
3336 (iw_handler) NULL,
3337 iwprivsapstop,
3338 (iw_handler) NULL,
3339 #ifdef ANDROID_BUILD
3340 iwprivsapfwreload,
3341 (iw_handler) NULL,
3342 iwprivsstackstart,
3343 (iw_handler) NULL,
3344 iwprivsstackstop,
3345 #else
3346 (iw_handler) NULL,
3347 (iw_handler) NULL,
3348 (iw_handler) NULL,
3349 (iw_handler) NULL,
3350 (iw_handler) NULL,
3351 #endif /* ANDROID_BUILD */
3352 #else
3353 (iw_handler) NULL,
3354 (iw_handler) NULL,
3355 (iw_handler) NULL,
3356 (iw_handler) NULL,
3357 (iw_handler) NULL,
3358 (iw_handler) NULL,
3359 (iw_handler) NULL,
3360 (iw_handler) NULL,
3361 (iw_handler) NULL,
3362 (iw_handler) NULL,
3363 (iw_handler) NULL,
3364 (iw_handler) NULL,
3365 #endif /* CSR_SUPPORT_WEXT_AP */
3368 struct iw_handler_def unifi_iw_handler_def =
3370 .num_standard = sizeof(unifi_handler) / sizeof(iw_handler),
3371 .num_private = sizeof(unifi_private_handler) / sizeof(iw_handler),
3372 .num_private_args = sizeof(unifi_private_args) / sizeof(struct iw_priv_args),
3373 .standard = (iw_handler *) unifi_handler,
3374 .private = (iw_handler *) unifi_private_handler,
3375 .private_args = (struct iw_priv_args *) unifi_private_args,
3376 #if IW_HANDLER_VERSION >= 6
3377 .get_wireless_stats = unifi_get_wireless_stats,
3378 #endif