ASoC: fsl: Add S/PDIF CPU DAI driver
[deliverable/linux.git] / drivers / staging / csr / sme_wext.c
1 /*
2 * ---------------------------------------------------------------------------
3 * FILE: sme_wext.c
4 *
5 * PURPOSE:
6 * Handlers for ioctls from iwconfig.
7 * These provide the control plane operations.
8 *
9 * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
10 *
11 * Refer to LICENSE.txt included with this source code for details on
12 * the license terms.
13 *
14 * ---------------------------------------------------------------------------
15 */
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>
23
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)
31
32 /* Workaround for the wpa_supplicant hanging issue - disabled on Android */
33 #ifndef ANDROID_BUILD
34 #define CSR_WIFI_WEXT_HANG_WORKAROUND
35 #endif
36
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
44
45
46 /*
47 * ---------------------------------------------------------------------------
48 * Helper functions
49 * ---------------------------------------------------------------------------
50 */
51
52 /*
53 * ---------------------------------------------------------------------------
54 * wext_freq_to_channel
55 * channel_to_mhz
56 *
57 * These functions convert between channel number and frequency.
58 *
59 * Arguments:
60 * ch Channel number, as defined in 802.11 specs
61 * m, e Mantissa and exponent as provided by wireless extension.
62 *
63 * Returns:
64 * channel or frequency (in MHz) value
65 * ---------------------------------------------------------------------------
66 */
67 static int
68 wext_freq_to_channel(int m, int e)
69 {
70 int mhz;
71
72 mhz = m;
73 while (e < 6) {
74 mhz /= 10;
75 e++;
76 }
77 while (e > 6) {
78 mhz *= 10;
79 e--;
80 }
81
82 if (mhz >= 5000) {
83 return ((mhz - 5000) / 5);
84 }
85
86 if (mhz == 2482) {
87 return 14;
88 }
89
90 if (mhz >= 2407) {
91 return ((mhz - 2407) / 5);
92 }
93
94 return 0;
95 } /* wext_freq_to_channel() */
96
97 static int
98 channel_to_mhz(int ch, int dot11a)
99 {
100
101 if (ch == 0) return 0;
102 if (ch > 200) return 0;
103
104 /* 5G */
105 if (dot11a) {
106 return (5000 + (5 * ch));
107 }
108
109 /* 2.4G */
110 if (ch == 14) {
111 return 2484;
112 }
113
114 if ((ch < 14) && (ch > 0)) {
115 return (2407 + (5 * ch));
116 }
117
118 return 0;
119 }
120 #ifdef CSR_SUPPORT_WEXT_AP
121 void uf_sme_wext_ap_set_defaults(unifi_priv_t *priv)
122 {
123 memcpy(priv->ap_config.ssid.ssid, "defaultssid", sizeof("defaultssid"));
124
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;
130
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*/
138
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;
142
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;
164
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;
185
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;
189
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;
196
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);
206 }
207 #endif
208 /*
209 * ---------------------------------------------------------------------------
210 * uf_sme_wext_set_defaults
211 *
212 * Set up power-on defaults for driver config.
213 *
214 * Note: The SME Management API *cannot* be used in this function.
215 *
216 * Arguments:
217 * priv Pointer to device private context struct
218 *
219 * Returns:
220 * None.
221 * ---------------------------------------------------------------------------
222 */
223 void
224 uf_sme_wext_set_defaults(unifi_priv_t *priv)
225 {
226 memset(&priv->connection_config, 0, sizeof(CsrWifiSmeConnectionConfig));
227
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;
236
237 priv->wep_tx_key_index = 0;
238
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
247
248
249 } /* uf_sme_wext_set_defaults() */
250
251
252 /*
253 * ---------------------------------------------------------------------------
254 * WEXT methods
255 * ---------------------------------------------------------------------------
256 */
257
258 /*
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
274 *
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.
279 *
280 * Arguments:
281 * None.
282 *
283 * Returns:
284 * None.
285 * ---------------------------------------------------------------------------
286 */
287 static int
288 iwprivsdefs(struct net_device *dev, struct iw_request_info *info,
289 union iwreq_data *wrqu, char *extra)
290 {
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;
296
297 unifi_trace(priv, UDBG1, "iwprivs80211defaults: reload defaults\n");
298
299 uf_sme_wext_set_defaults(priv);
300
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;
306 }
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;
313 }
314
315 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
316 powerConfig.listenIntervalTu = 100;
317 powerConfig.rxDtims = 1;
318
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;
323 }
324
325 return 0;
326 } /* iwprivsdefs() */
327
328 static int
329 iwprivs80211ps(struct net_device *dev, struct iw_request_info *info,
330 union iwreq_data *wrqu, char *extra)
331 {
332 int r = 0;
333 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
334 unifi_priv_t *priv = interfacePriv->privPtr;
335
336 int ps_mode = (int)(*extra);
337 CsrWifiSmePowerConfig powerConfig;
338
339 unifi_trace(priv, UDBG1, "iwprivs80211ps: power save mode = %d\n", ps_mode);
340
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;
345 }
346
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;
360 }
361
362 r = sme_mgt_power_config_set(priv, &powerConfig);
363 if (r) {
364 unifi_error(priv, "iwprivs80211ps: Set unifi_PowerConfigValue failed.\n");
365 }
366
367 return r;
368 }
369
370 static int
371 iwprivg80211ps(struct net_device *dev, struct iw_request_info *info,
372 union iwreq_data *wrqu, char *extra)
373 {
374 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
375 unifi_priv_t *priv = interfacePriv->privPtr;
376
377 CsrWifiSmePowerConfig powerConfig;
378 int r;
379
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;
384 }
385
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;
412 }
413
414 wrqu->data.length = strlen(extra) + 1;
415
416 return 0;
417 }
418
419 static int
420 iwprivssmedebug(struct net_device *dev, struct iw_request_info *info,
421 union iwreq_data *wrqu, char *extra)
422 {
423 /* No longer supported on the API */
424 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE)
425 unifi_debug_buf_dump();
426 #endif
427
428 return 0;
429 }
430
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
437
438 static int hex_look_up(char x)
439 {
440 if(x>='0' && x<='9')
441 return (x-48);
442 if(x>= 'a' && x <= 'f')
443 return (x-87);
444 return -1;
445 }
446
447 static int power (int a, int b)
448 {
449 int i;
450 int num =1;
451 for(i=0;i<b;i++)
452 num *=a;
453 return num;
454 }
455
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)
459 {
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;
464
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;
474 }
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;
479 }
480 switch (param_type) {
481 case PARAM_TYPE_INT:
482 {
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);
487 }
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;
496 }
497 }
498 *pdst_int = num;
499 unifi_trace(priv, UDBG2, "decode_parameter_from_string:decoded int = %d\n", *pdst_int);
500 }
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;
507 }
508 } else {
509 unifi_error(priv, "decode_parameter_from_string: Token:%s not found in %s \n", token, orig_str);
510 return -1;
511 }
512 return 0;
513 }
514 static int store_ap_advanced_config_from_string(unifi_priv_t *priv, char *param_str)
515 {
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;
520
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;
527 }
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;
534 }
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;
541 }
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;
550 }
551 if(strstr(phy_mode, "g")) {
552 ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_G;
553 }
554 if(strstr(phy_mode, "n")) {
555 ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_N;
556 }
557 ap_mac_config->supportedRatesCount =
558 uf_configure_supported_rates(ap_mac_config->supportedRates, ap_mac_config->phySupportedBitmap);
559 }
560 return ret;
561 }
562
563 static int store_ap_config_from_string( unifi_priv_t * priv, char *param_str)
564
565 {
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;
577 }
578 if (decode_parameter_from_string(priv, &str_ptr, "ASCII_CMD=",
579 PARAM_TYPE_STRING, sub_cmd, 6) != 0) {
580 return -1;
581 }
582 if (strncmp(sub_cmd, "AP_CFG", 6)) {
583
584 if(!strncmp(sub_cmd , "ADVCFG", 6)) {
585 return store_ap_advanced_config_from_string(priv, str_ptr);
586 }
587 unifi_error(priv, "store_ap_config_from_string: sub_cmd:%s != 'AP_CFG or ADVCFG'!\n", sub_cmd);
588 return -1;
589 }
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;
597 }
598 ap_config->ssid.length = strlen(ap_config->ssid.ssid);
599
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;
605 }
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");
613 }
614 }
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;
620
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;
625 }
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;
636 }
637
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;
642 }
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;
656 }
657
658 static int
659 iwprivsapstart(struct net_device *dev, struct iw_request_info *info,
660 union iwreq_data *wrqu, char *extra)
661 {
662 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
663 unifi_priv_t *priv = interfacePriv->privPtr;
664 int r;
665
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);
670 }
671 return r;
672 }
673
674 static int
675 iwprivsapconfig(struct net_device *dev, struct iw_request_info *info,
676 union iwreq_data *wrqu, char *extra)
677 {
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;
682
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)))
687 {
688 return -ENOMEM;
689 }
690 if (copy_from_user(cfg_str, wrqu->data.pointer, wrqu->data.length)) {
691 kfree(cfg_str);
692 return -EFAULT;
693 }
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;
702
703 }
704 } else {
705 unifi_error(priv, "iwprivsapconfig argument length = 0 \n");
706 return -EIO;
707 }
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);
717 }
718 }
719 kfree(cfg_str);
720 return r;
721 }
722
723 static int
724 iwprivsapstop(struct net_device *dev, struct iw_request_info *info,
725 union iwreq_data *wrqu, char *extra)
726 {
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;
731
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);
736 }
737 return r;
738 }
739
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)
744 {
745 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
746 unifi_priv_t *priv = interfacePriv->privPtr;
747
748 unifi_trace(priv, UDBG1, "iwprivsapfwreload\n" );
749 return 0;
750 }
751
752 static int
753 iwprivsstackstart(struct net_device *dev, struct iw_request_info *info,
754 union iwreq_data *wrqu, char *extra)
755 {
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;
760 }
761
762 static int
763 iwprivsstackstop(struct net_device *dev, struct iw_request_info *info,
764 union iwreq_data *wrqu, char *extra)
765 {
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;
770
771 unifi_trace(priv, UDBG1, "iwprivsstackstop\n" );
772
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;
785 }
786
787 if(r) {
788 unifi_error(priv, "iwprivsstackstop Stack stop failed : %d\n", -r);
789 }
790 return 0;
791 }
792 #endif /* ANDROID_BUILD */
793 #endif /* CSR_SUPPORT_WEXT_AP */
794
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)
799 {
800 u8 enable;
801 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
802 unifi_priv_t *priv = interfacePriv->privPtr;
803
804 unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" );
805
806 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
807 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
808 unifi_error(priv, "iwprivsconfwapi: not permitted in Mode %d\n",
809 interfacePriv->interfaceMode);
810 return -EPERM;
811 }
812
813 enable = *(u8*)(extra);
814
815 if (enable) {
816 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
817 priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
818 priv->connection_config.encryptionModeMask |=
819 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4;
820 } else {
821 priv->connection_config.authModeMask &= ~(CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI);
822 priv->connection_config.encryptionModeMask &=
823 ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4);
824 }
825
826 return 0;
827 }
828
829 static int
830 iwprivswpikey(struct net_device *dev, struct iw_request_info *info,
831 union iwreq_data *wrqu, char *extra)
832 {
833 int r = 0, i;
834 CsrWifiSmeKey key;
835 unifiio_wapi_key_t inKey;
836 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
837 unifi_priv_t *priv = interfacePriv->privPtr;
838
839 unifi_trace(priv, UDBG1, "iwprivswpikey\n" );
840
841 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
842 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
843 unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
844 interfacePriv->interfaceMode);
845 return -EPERM;
846 }
847
848 inKey = *(unifiio_wapi_key_t*)(extra);
849
850 if (inKey.unicastKey) {
851 key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
852 } else {
853 key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
854 }
855
856 key.keyIndex = inKey.keyIndex;
857
858 /* memcpy(key.keyRsc, inKey.keyRsc, 16); */
859 for (i = 0; i < 16; i+= 2)
860 {
861 key.keyRsc[i/2] = inKey.keyRsc[i+1] << 8 | inKey.keyRsc[i];
862 }
863
864 memcpy(key.address.a, inKey.address, 6);
865 key.keyLength = 32;
866 memcpy(key.key, inKey.key, 32);
867 key.authenticator = 0;
868 key.wepTxKey = 0;
869
870 unifi_trace(priv, UDBG1, "keyType = %d, keyIndex = %d, wepTxKey = %d, keyRsc = %x:%x, auth = %d, address = %x:%x, "
871 "keylength = %d, key = %x:%x\n", key.keyType, key.keyIndex, key.wepTxKey,
872 key.keyRsc[0], key.keyRsc[7], key.authenticator,
873 key.address.a[0], key.address.a[5], key.keyLength, key.key[0],
874 key.key[15]);
875
876 r = sme_mgt_key(priv, &key, CSR_WIFI_SME_LIST_ACTION_ADD);
877 if (r) {
878 unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
879 return convert_sme_error(r);
880 }
881
882 return r;
883 }
884 #endif
885
886
887 static int
888 unifi_giwname(struct net_device *dev, struct iw_request_info *info,
889 union iwreq_data *wrqu, char *extra)
890 {
891 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
892 unifi_priv_t *priv = interfacePriv->privPtr;
893 char *name = wrqu->name;
894 unifi_trace(priv, UDBG2, "unifi_giwname\n");
895
896 if (priv->if_index == CSR_INDEX_5G) {
897 strcpy(name, "IEEE 802.11-a");
898 } else {
899 strcpy(name, "IEEE 802.11-bgn");
900 }
901 return 0;
902 } /* unifi_giwname() */
903
904
905 static int
906 unifi_siwfreq(struct net_device *dev, struct iw_request_info *info,
907 union iwreq_data *wrqu, char *extra)
908 {
909 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
910 unifi_priv_t *priv = interfacePriv->privPtr;
911 struct iw_freq *freq = (struct iw_freq *)wrqu;
912
913 unifi_trace(priv, UDBG2, "unifi_siwfreq\n");
914
915 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
916 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
917 unifi_error(priv, "unifi_siwfreq: not permitted in Mode %d\n",
918 interfacePriv->interfaceMode);
919 return -EPERM;
920 }
921
922
923 /*
924 * Channel is stored in the connection configuration,
925 * and set later when ask for a connection.
926 */
927 if ((freq->e == 0) && (freq->m <= 1000)) {
928 priv->connection_config.adhocChannel = freq->m;
929 } else {
930 priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e);
931 }
932
933 return 0;
934 } /* unifi_siwfreq() */
935
936
937 static int
938 unifi_giwfreq(struct net_device *dev, struct iw_request_info *info,
939 union iwreq_data *wrqu, char *extra)
940 {
941 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
942 unifi_priv_t *priv = interfacePriv->privPtr;
943 struct iw_freq *freq = (struct iw_freq *)wrqu;
944 int err = 0;
945 CsrWifiSmeConnectionInfo connectionInfo;
946
947 unifi_trace(priv, UDBG2, "unifi_giwfreq\n");
948 CHECK_INITED(priv);
949
950 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
951 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
952 unifi_error(priv, "unifi_giwfreq: not permitted in Mode %d\n",
953 interfacePriv->interfaceMode);
954 return -EPERM;
955 }
956
957
958 UF_RTNL_UNLOCK();
959 err = sme_mgt_connection_info_get(priv, &connectionInfo);
960 UF_RTNL_LOCK();
961
962 freq->m = channel_to_mhz(connectionInfo.channelNumber,
963 (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0));
964 freq->e = 6;
965
966 return convert_sme_error(err);
967 } /* unifi_giwfreq() */
968
969
970 static int
971 unifi_siwmode(struct net_device *dev, struct iw_request_info *info,
972 union iwreq_data *wrqu, char *extra)
973 {
974 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
975 unifi_priv_t *priv = interfacePriv->privPtr;
976
977 unifi_trace(priv, UDBG2, "unifi_siwmode\n");
978
979 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
980 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
981 unifi_error(priv, "unifi_siwmode: not permitted in Mode %d\n",
982 interfacePriv->interfaceMode);
983 return -EPERM;
984 }
985
986
987 switch(wrqu->mode) {
988 case IW_MODE_ADHOC:
989 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ADHOC;
990 break;
991 case IW_MODE_INFRA:
992 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE;
993 break;
994 case IW_MODE_AUTO:
995 priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ANY_BSS;
996 break;
997 default:
998 unifi_notice(priv, "Unknown IW MODE value.\n");
999 }
1000
1001 /* Clear the SSID and BSSID configuration */
1002 priv->connection_config.ssid.length = 0;
1003 memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1004
1005 return 0;
1006 } /* unifi_siwmode() */
1007
1008
1009
1010 static int
1011 unifi_giwmode(struct net_device *dev, struct iw_request_info *info,
1012 union iwreq_data *wrqu, char *extra)
1013 {
1014 int r = 0;
1015 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1016 unifi_priv_t *priv = interfacePriv->privPtr;
1017 CsrWifiSmeConnectionConfig connectionConfig;
1018
1019 unifi_trace(priv, UDBG2, "unifi_giwmode\n");
1020 CHECK_INITED(priv);
1021
1022 unifi_trace(priv, UDBG2, "unifi_giwmode: Exisitng mode = 0x%x\n",
1023 interfacePriv->interfaceMode);
1024 switch(interfacePriv->interfaceMode) {
1025 case CSR_WIFI_ROUTER_CTRL_MODE_STA:
1026 case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI:
1027 wrqu->mode = IW_MODE_INFRA;
1028 break;
1029 case CSR_WIFI_ROUTER_CTRL_MODE_AP:
1030 case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO:
1031 wrqu->mode = IW_MODE_MASTER;
1032 break;
1033 case CSR_WIFI_ROUTER_CTRL_MODE_IBSS:
1034 wrqu->mode = IW_MODE_ADHOC;
1035 break;
1036 case CSR_WIFI_ROUTER_CTRL_MODE_P2P:
1037 case CSR_WIFI_ROUTER_CTRL_MODE_NONE:
1038 UF_RTNL_UNLOCK();
1039 r = sme_mgt_connection_config_get(priv, &connectionConfig);
1040 UF_RTNL_LOCK();
1041 if (r == 0) {
1042 switch(connectionConfig.bssType) {
1043 case CSR_WIFI_SME_BSS_TYPE_ADHOC:
1044 wrqu->mode = IW_MODE_ADHOC;
1045 break;
1046 case CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE:
1047 wrqu->mode = IW_MODE_INFRA;
1048 break;
1049 default:
1050 wrqu->mode = IW_MODE_AUTO;
1051 unifi_notice(priv, "Unknown IW MODE value.\n");
1052 }
1053 }
1054 break;
1055 default:
1056 wrqu->mode = IW_MODE_AUTO;
1057 unifi_notice(priv, "Unknown IW MODE value.\n");
1058
1059 }
1060 unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode);
1061 return r;
1062 } /* unifi_giwmode() */
1063
1064
1065
1066 static int
1067 unifi_giwrange(struct net_device *dev, struct iw_request_info *info,
1068 union iwreq_data *wrqu, char *extra)
1069 {
1070 struct iw_point *dwrq = &wrqu->data;
1071 struct iw_range *range = (struct iw_range *) extra;
1072 int i;
1073
1074 unifi_trace(NULL, UDBG2, "unifi_giwrange\n");
1075
1076 dwrq->length = sizeof(struct iw_range);
1077 memset(range, 0, sizeof(*range));
1078 range->min_nwid = 0x0000;
1079 range->max_nwid = 0x0000;
1080
1081 /*
1082 * Don't report the frequency/channel table, then the channel
1083 * number returned elsewhere will be printed as a channel number.
1084 */
1085
1086 /* Ranges of values reported in quality structs */
1087 range->max_qual.qual = 40; /* Max expected qual value */
1088 range->max_qual.level = -120; /* Noise floor in dBm */
1089 range->max_qual.noise = -120; /* Noise floor in dBm */
1090
1091
1092 /* space for IW_MAX_BITRATES (8 up to WE15, 32 later) */
1093 i = 0;
1094 #if WIRELESS_EXT > 15
1095 range->bitrate[i++] = 2 * 500000;
1096 range->bitrate[i++] = 4 * 500000;
1097 range->bitrate[i++] = 11 * 500000;
1098 range->bitrate[i++] = 22 * 500000;
1099 range->bitrate[i++] = 12 * 500000;
1100 range->bitrate[i++] = 18 * 500000;
1101 range->bitrate[i++] = 24 * 500000;
1102 range->bitrate[i++] = 36 * 500000;
1103 range->bitrate[i++] = 48 * 500000;
1104 range->bitrate[i++] = 72 * 500000;
1105 range->bitrate[i++] = 96 * 500000;
1106 range->bitrate[i++] = 108 * 500000;
1107 #else
1108 range->bitrate[i++] = 2 * 500000;
1109 range->bitrate[i++] = 4 * 500000;
1110 range->bitrate[i++] = 11 * 500000;
1111 range->bitrate[i++] = 22 * 500000;
1112 range->bitrate[i++] = 24 * 500000;
1113 range->bitrate[i++] = 48 * 500000;
1114 range->bitrate[i++] = 96 * 500000;
1115 range->bitrate[i++] = 108 * 500000;
1116 #endif /* WIRELESS_EXT < 16 */
1117 range->num_bitrates = i;
1118
1119 range->max_encoding_tokens = NUM_WEPKEYS;
1120 range->num_encoding_sizes = 2;
1121 range->encoding_size[0] = 5;
1122 range->encoding_size[1] = 13;
1123
1124 range->we_version_source = 20;
1125 range->we_version_compiled = WIRELESS_EXT;
1126
1127 /* Number of channels available in h/w */
1128 range->num_channels = 14;
1129 /* Number of entries in freq[] array */
1130 range->num_frequency = 14;
1131 for (i = 0; (i < range->num_frequency) && (i < IW_MAX_FREQUENCIES); i++) {
1132 int chan = i + 1;
1133 range->freq[i].i = chan;
1134 range->freq[i].m = channel_to_mhz(chan, 0);
1135 range->freq[i].e = 6;
1136 }
1137 if ((i+3) < IW_MAX_FREQUENCIES) {
1138 range->freq[i].i = 36;
1139 range->freq[i].m = channel_to_mhz(36, 1);
1140 range->freq[i].e = 6;
1141 range->freq[i+1].i = 40;
1142 range->freq[i+1].m = channel_to_mhz(40, 1);
1143 range->freq[i+1].e = 6;
1144 range->freq[i+2].i = 44;
1145 range->freq[i+2].m = channel_to_mhz(44, 1);
1146 range->freq[i+2].e = 6;
1147 range->freq[i+3].i = 48;
1148 range->freq[i+3].m = channel_to_mhz(48, 1);
1149 range->freq[i+3].e = 6;
1150 }
1151
1152 #if WIRELESS_EXT > 16
1153 /* Event capability (kernel + driver) */
1154 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
1155 IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
1156 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
1157 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
1158 range->event_capa[1] = IW_EVENT_CAPA_K_1;
1159 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
1160 IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
1161 IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
1162 IW_EVENT_CAPA_MASK(IWEVEXPIRED));
1163 #endif /* WIRELESS_EXT > 16 */
1164
1165 #if WIRELESS_EXT > 17
1166 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1167 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1168 #endif /* WIRELESS_EXT > 17 */
1169
1170
1171 return 0;
1172 } /* unifi_giwrange() */
1173
1174
1175 static int
1176 unifi_siwap(struct net_device *dev, struct iw_request_info *info,
1177 union iwreq_data *wrqu, char *extra)
1178 {
1179 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1180 unifi_priv_t *priv = interfacePriv->privPtr;
1181 int err = 0;
1182
1183 CHECK_INITED(priv);
1184
1185 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1186 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1187 unifi_error(priv, "unifi_siwap: not permitted in Mode %d\n",
1188 interfacePriv->interfaceMode);
1189 return -EPERM;
1190 }
1191
1192
1193 if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) {
1194 return -EINVAL;
1195 }
1196
1197 unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n",
1198 wrqu->ap_addr.sa_data);
1199
1200 if (is_zero_ether_addr(wrqu->ap_addr.sa_data)) {
1201 priv->ignore_bssid_join = FALSE;
1202 err = sme_mgt_disconnect(priv);
1203 if (err) {
1204 unifi_trace(priv, UDBG4, "unifi_siwap: Disconnect failed, status %d\n", err);
1205 }
1206 return 0;
1207 }
1208
1209 if (priv->ignore_bssid_join) {
1210 unifi_trace(priv, UDBG4, "unifi_siwap: ignoring second join\n");
1211 priv->ignore_bssid_join = FALSE;
1212 } else {
1213 memcpy(priv->connection_config.bssid.a, wrqu->ap_addr.sa_data, ETH_ALEN);
1214 unifi_trace(priv, UDBG1, "unifi_siwap: Joining %X:%X:%X:%X:%X:%X\n",
1215 priv->connection_config.bssid.a[0],
1216 priv->connection_config.bssid.a[1],
1217 priv->connection_config.bssid.a[2],
1218 priv->connection_config.bssid.a[3],
1219 priv->connection_config.bssid.a[4],
1220 priv->connection_config.bssid.a[5]);
1221 err = sme_mgt_connect(priv);
1222 if (err) {
1223 unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err);
1224 return convert_sme_error(err);
1225 }
1226 }
1227
1228 return 0;
1229 } /* unifi_siwap() */
1230
1231
1232 static int
1233 unifi_giwap(struct net_device *dev, struct iw_request_info *info,
1234 union iwreq_data *wrqu, char *extra)
1235 {
1236 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1237 unifi_priv_t *priv = interfacePriv->privPtr;
1238 CsrWifiSmeConnectionInfo connectionInfo;
1239 int r = 0;
1240 u8 *bssid;
1241
1242 CHECK_INITED(priv);
1243 unifi_trace(priv, UDBG2, "unifi_giwap\n");
1244
1245 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1246 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1247 unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n",
1248 interfacePriv->interfaceMode);
1249 return -EPERM;
1250 }
1251
1252 UF_RTNL_UNLOCK();
1253 r = sme_mgt_connection_info_get(priv, &connectionInfo);
1254 UF_RTNL_LOCK();
1255
1256 if (r == 0) {
1257 bssid = connectionInfo.bssid.a;
1258 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1259 unifi_trace(priv, UDBG4, "unifi_giwap: BSSID = %pM\n", bssid);
1260
1261 memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
1262 } else {
1263 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1264 }
1265
1266 return 0;
1267 } /* unifi_giwap() */
1268
1269
1270 static int
1271 unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
1272 union iwreq_data *wrqu, char *extra)
1273 {
1274 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1275 unifi_priv_t *priv = interfacePriv->privPtr;
1276 int r;
1277 CsrWifiSsid scan_ssid;
1278 unsigned char *channel_list = NULL;
1279 int chans_good = 0;
1280 #if WIRELESS_EXT > 17
1281 struct iw_point *data = &wrqu->data;
1282 struct iw_scan_req *req = (struct iw_scan_req *) extra;
1283 #endif
1284
1285 CHECK_INITED(priv);
1286
1287 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1288 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1289 unifi_error(priv, "unifi_siwscan: not permitted in Mode %d\n",
1290 interfacePriv->interfaceMode);
1291 return -EPERM;
1292 }
1293
1294
1295 #if WIRELESS_EXT > 17
1296 /* Providing a valid channel list will force an active scan */
1297 if (req) {
1298 if ((req->num_channels > 0) && (req->num_channels < IW_MAX_FREQUENCIES)) {
1299 channel_list = kmalloc(req->num_channels, GFP_KERNEL);
1300 if (channel_list) {
1301 int i;
1302 for (i = 0; i < req->num_channels; i++) {
1303 /* Convert frequency to channel number */
1304 int ch = wext_freq_to_channel(req->channel_list[i].m,
1305 req->channel_list[i].e);
1306 if (ch) {
1307 channel_list[chans_good++] = ch;
1308 }
1309 }
1310 unifi_trace(priv, UDBG1,
1311 "SIWSCAN: Scanning %d channels\n", chans_good);
1312 } else {
1313 /* Fall back to scanning all */
1314 unifi_error(priv, "SIWSCAN: Can't alloc channel_list (%d)\n",
1315 req->num_channels);
1316 }
1317 }
1318 }
1319
1320 if (req && (data->flags & IW_SCAN_THIS_ESSID)) {
1321 memcpy(scan_ssid.ssid, req->essid, req->essid_len);
1322 scan_ssid.length = req->essid_len;
1323 unifi_trace(priv, UDBG1,
1324 "SIWSCAN: Scanning for %.*s\n",
1325 scan_ssid.length, scan_ssid.ssid);
1326 } else
1327 #endif
1328 {
1329 unifi_trace(priv, UDBG1, "SIWSCAN: Scanning for all APs\n");
1330 scan_ssid.length = 0;
1331 }
1332
1333 r = sme_mgt_scan_full(priv, &scan_ssid, chans_good, channel_list);
1334 if (r) {
1335 unifi_error(priv, "SIWSCAN: Scan returned error %d\n", r);
1336 } else {
1337 unifi_trace(priv, UDBG1, "SIWSCAN: Scan done\n");
1338 wext_send_scan_results_event(priv);
1339 }
1340
1341 if (channel_list) {
1342 kfree(channel_list);
1343 }
1344
1345 return r;
1346
1347 } /* unifi_siwscan() */
1348
1349
1350 static const unsigned char *
1351 unifi_find_info_element(int id, const unsigned char *info, int len)
1352 {
1353 const unsigned char *ie = info;
1354
1355 while (len > 1)
1356 {
1357 int e_id, e_len;
1358 e_id = ie[0];
1359 e_len = ie[1];
1360
1361 /* Return if we find a match */
1362 if (e_id == id)
1363 {
1364 return ie;
1365 }
1366
1367 len -= (e_len + 2);
1368 ie += (e_len + 2);
1369 }
1370
1371 return NULL;
1372 } /* unifi_find_info_element() */
1373
1374
1375 /*
1376 * Translate scan data returned from the card to a card independent
1377 * format that the Wireless Tools will understand - Jean II
1378 */
1379 int
1380 unifi_translate_scan(struct net_device *dev,
1381 struct iw_request_info *info,
1382 char *current_ev, char *end_buf,
1383 CsrWifiSmeScanResult *scan_data,
1384 int scan_index)
1385 {
1386 struct iw_event iwe; /* Temporary buffer */
1387 unsigned char *info_elems;
1388 int info_elem_len;
1389 const unsigned char *elem;
1390 u16 capabilities;
1391 int signal, noise, snr;
1392 char *start_buf = current_ev;
1393 char *current_val; /* For rates */
1394 int i, r;
1395
1396 info_elems = scan_data->informationElements;
1397 info_elem_len = scan_data->informationElementsLength;
1398
1399 if (!scan_data->informationElementsLength || !scan_data->informationElements) {
1400 unifi_error(NULL, "*** NULL SCAN IEs ***\n");
1401 return -EIO;
1402 }
1403
1404 /* get capinfo bits */
1405 capabilities = scan_data->capabilityInformation;
1406
1407 unifi_trace(NULL, UDBG5, "Capabilities: 0x%x\n", capabilities);
1408
1409 /* First entry *MUST* be the AP MAC address */
1410 memset(&iwe, 0, sizeof(iwe));
1411 iwe.cmd = SIOCGIWAP;
1412 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1413 memcpy(iwe.u.ap_addr.sa_data, scan_data->bssid.a, ETH_ALEN);
1414 iwe.len = IW_EV_ADDR_LEN;
1415 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_ADDR_LEN);
1416 if (r < 0) {
1417 return r;
1418 }
1419 start_buf += r;
1420
1421 /* Other entries will be displayed in the order we give them */
1422
1423 /* Add the ESSID */
1424 /* find SSID in Info Elems */
1425 elem = unifi_find_info_element(IE_SSID_ID, info_elems, info_elem_len);
1426 if (elem) {
1427 int e_len = elem[1];
1428 const unsigned char *e_ptr = elem + 2;
1429 unsigned char buf[33];
1430
1431 memset(&iwe, 0, sizeof(iwe));
1432 iwe.cmd = SIOCGIWESSID;
1433 iwe.u.essid.length = e_len;
1434 if (iwe.u.essid.length > 32) {
1435 iwe.u.essid.length = 32;
1436 }
1437 iwe.u.essid.flags = scan_index;
1438 memcpy(buf, e_ptr, iwe.u.essid.length);
1439 buf[iwe.u.essid.length] = '\0';
1440 r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, buf);
1441 if (r < 0) {
1442 return r;
1443 }
1444 start_buf += r;
1445
1446 }
1447
1448 /* Add mode */
1449 memset(&iwe, 0, sizeof(iwe));
1450 iwe.cmd = SIOCGIWMODE;
1451 if (scan_data->bssType == CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE) {
1452 iwe.u.mode = IW_MODE_INFRA;
1453 } else {
1454 iwe.u.mode = IW_MODE_ADHOC;
1455 }
1456 iwe.len = IW_EV_UINT_LEN;
1457 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_UINT_LEN);
1458 if (r < 0) {
1459 return r;
1460 }
1461 start_buf += r;
1462
1463 /* Add frequency. iwlist will convert to channel using table given in giwrange */
1464 memset(&iwe, 0, sizeof(iwe));
1465 iwe.cmd = SIOCGIWFREQ;
1466 iwe.u.freq.m = scan_data->channelFrequency;
1467 iwe.u.freq.e = 6;
1468 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_FREQ_LEN);
1469 if (r < 0) {
1470 return r;
1471 }
1472 start_buf += r;
1473
1474
1475 /* Add quality statistics */
1476 iwe.cmd = IWEVQUAL;
1477 /*
1478 * level and noise below are mapped into an unsigned 8 bit number,
1479 * ranging from [-192; 63]. The way this is achieved is simply to
1480 * add 0x100 onto the number if it is negative,
1481 * once clipped to the correct range.
1482 */
1483 signal = scan_data->rssi; /* This value is in dBm */
1484 /* Clip range of snr */
1485 snr = (scan_data->snr > 0) ? scan_data->snr : 0; /* In dB relative, from 0 - 255 */
1486 snr = (snr < 255) ? snr : 255;
1487 noise = signal - snr;
1488
1489 /* Clip range of signal */
1490 signal = (signal < 63) ? signal : 63;
1491 signal = (signal > -192) ? signal : -192;
1492
1493 /* Clip range of noise */
1494 noise = (noise < 63) ? noise : 63;
1495 noise = (noise > -192) ? noise : -192;
1496
1497 /* Make u8 */
1498 signal = ( signal < 0 ) ? signal + 0x100 : signal;
1499 noise = ( noise < 0 ) ? noise + 0x100 : noise;
1500
1501 iwe.u.qual.level = (u8)signal; /* -192 : 63 */
1502 iwe.u.qual.noise = (u8)noise; /* -192 : 63 */
1503 iwe.u.qual.qual = snr; /* 0 : 255 */
1504 iwe.u.qual.updated = 0;
1505 #if WIRELESS_EXT > 16
1506 iwe.u.qual.updated |= IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED |
1507 IW_QUAL_QUAL_UPDATED;
1508 #if WIRELESS_EXT > 18
1509 iwe.u.qual.updated |= IW_QUAL_DBM;
1510 #endif
1511 #endif
1512 r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_QUAL_LEN);
1513 if (r < 0) {
1514 return r;
1515 }
1516 start_buf += r;
1517
1518 /* Add encryption capability */
1519 iwe.cmd = SIOCGIWENCODE;
1520 if (capabilities & SIG_CAP_PRIVACY) {
1521 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1522 } else {
1523 iwe.u.data.flags = IW_ENCODE_DISABLED;
1524 }
1525 iwe.u.data.length = 0;
1526 iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
1527 r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, "");
1528 if (r < 0) {
1529 return r;
1530 }
1531 start_buf += r;
1532
1533
1534 /*
1535 * Rate : stuffing multiple values in a single event require a bit
1536 * more of magic - Jean II
1537 */
1538 current_val = start_buf + IW_EV_LCP_LEN;
1539
1540 iwe.cmd = SIOCGIWRATE;
1541 /* Those two flags are ignored... */
1542 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1543
1544 elem = unifi_find_info_element(IE_SUPPORTED_RATES_ID,
1545 info_elems, info_elem_len);
1546 if (elem) {
1547 int e_len = elem[1];
1548 const unsigned char *e_ptr = elem + 2;
1549
1550 /*
1551 * Count how many rates we have.
1552 * Zero marks the end of the list, if the list is not truncated.
1553 */
1554 /* Max 8 values */
1555 for (i = 0; i < e_len; i++) {
1556 if (e_ptr[i] == 0) {
1557 break;
1558 }
1559 /* Bit rate given in 500 kb/s units (+ 0x80) */
1560 iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1561 /* Add new value to event */
1562 r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1563 if (r < 0) {
1564 return r;
1565 }
1566 current_val +=r;
1567
1568 }
1569 }
1570 elem = unifi_find_info_element(IE_EXTENDED_SUPPORTED_RATES_ID,
1571 info_elems, info_elem_len);
1572 if (elem) {
1573 int e_len = elem[1];
1574 const unsigned char *e_ptr = elem + 2;
1575
1576 /*
1577 * Count how many rates we have.
1578 * Zero marks the end of the list, if the list is not truncated.
1579 */
1580 /* Max 8 values */
1581 for (i = 0; i < e_len; i++) {
1582 if (e_ptr[i] == 0) {
1583 break;
1584 }
1585 /* Bit rate given in 500 kb/s units (+ 0x80) */
1586 iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000);
1587 /* Add new value to event */
1588 r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
1589 if (r < 0) {
1590 return r;
1591 }
1592 current_val +=r;
1593 }
1594 }
1595 /* Check if we added any rates event */
1596 if ((current_val - start_buf) > IW_EV_LCP_LEN) {
1597 start_buf = current_val;
1598 }
1599
1600
1601 #if WIRELESS_EXT > 17
1602 memset(&iwe, 0, sizeof(iwe));
1603 iwe.cmd = IWEVGENIE;
1604 iwe.u.data.length = info_elem_len;
1605
1606 r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, info_elems);
1607 if (r < 0) {
1608 return r;
1609 }
1610
1611 start_buf += r;
1612 #endif /* WE > 17 */
1613
1614 return (start_buf - current_ev);
1615 } /* unifi_translate_scan() */
1616
1617
1618
1619 static int
1620 unifi_giwscan(struct net_device *dev, struct iw_request_info *info,
1621 union iwreq_data *wrqu, char *extra)
1622 {
1623 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1624 unifi_priv_t *priv = interfacePriv->privPtr;
1625 struct iw_point *dwrq = &wrqu->data;
1626 int r;
1627
1628 CHECK_INITED(priv);
1629
1630 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1631 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1632 unifi_error(priv, "unifi_giwscan: not permitted in Mode %d\n",
1633 interfacePriv->interfaceMode);
1634 return -EPERM;
1635 }
1636
1637
1638 unifi_trace(priv, UDBG1,
1639 "unifi_giwscan: buffer (%d bytes) \n",
1640 dwrq->length);
1641 UF_RTNL_UNLOCK();
1642 r = sme_mgt_scan_results_get_async(priv, info, extra, dwrq->length);
1643 UF_RTNL_LOCK();
1644 if (r < 0) {
1645 unifi_trace(priv, UDBG1,
1646 "unifi_giwscan: buffer (%d bytes) not big enough.\n",
1647 dwrq->length);
1648 return r;
1649 }
1650
1651 dwrq->length = r;
1652 dwrq->flags = 0;
1653
1654 return 0;
1655 } /* unifi_giwscan() */
1656
1657
1658 /*
1659 * ---------------------------------------------------------------------------
1660 * unifi_siwessid
1661 *
1662 * Request to join a network or start and AdHoc.
1663 *
1664 * Arguments:
1665 * dev Pointer to network device struct.
1666 * info Pointer to broken-out ioctl request.
1667 * data Pointer to argument data.
1668 * essid Pointer to string giving name of network to join
1669 * or start
1670 *
1671 * Returns:
1672 * 0 on success and everything complete
1673 * -EINPROGRESS to have the higher level call the commit method.
1674 * ---------------------------------------------------------------------------
1675 */
1676 static int
1677 unifi_siwessid(struct net_device *dev, struct iw_request_info *info,
1678 struct iw_point *data, char *essid)
1679 {
1680 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1681 unifi_priv_t *priv = interfacePriv->privPtr;
1682 int len;
1683 int err = 0;
1684
1685 CHECK_INITED(priv);
1686
1687 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1688 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1689 unifi_error(priv, "unifi_siwessid: not permitted in Mode %d\n",
1690 interfacePriv->interfaceMode);
1691 return -EPERM;
1692 }
1693
1694
1695 len = 0;
1696 if (data->flags & 1) {
1697 /* Limit length */
1698 len = data->length;
1699 if (len > UNIFI_MAX_SSID_LEN) {
1700 len = UNIFI_MAX_SSID_LEN;
1701 }
1702 }
1703
1704 #ifdef UNIFI_DEBUG
1705 {
1706 char essid_str[UNIFI_MAX_SSID_LEN+1];
1707 int i;
1708
1709 for (i = 0; i < len; i++) {
1710 essid_str[i] = (isprint(essid[i]) ? essid[i] : '?');
1711 }
1712 essid_str[i] = '\0';
1713
1714 unifi_trace(priv, UDBG1, "unifi_siwessid: asked for '%*s' (%d)\n", len, essid_str, len);
1715 unifi_trace(priv, UDBG2, " with authModeMask = %d", priv->connection_config.authModeMask);
1716 }
1717 #endif
1718
1719 memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
1720 if (len) {
1721 if (essid[len - 1] == 0) {
1722 len --;
1723 }
1724
1725 memcpy(priv->connection_config.ssid.ssid, essid, len);
1726 priv->connection_config.ssid.length = len;
1727
1728 } else {
1729 priv->connection_config.ssid.length = 0;
1730 }
1731
1732 UF_RTNL_UNLOCK();
1733 err = sme_mgt_connect(priv);
1734 UF_RTNL_LOCK();
1735 if (err) {
1736 unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err);
1737 return convert_sme_error(err);
1738 }
1739
1740 return 0;
1741 } /* unifi_siwessid() */
1742
1743
1744 static int
1745 unifi_giwessid(struct net_device *dev, struct iw_request_info *info,
1746 union iwreq_data *wrqu, char *essid)
1747 {
1748 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1749 unifi_priv_t *priv = interfacePriv->privPtr;
1750 struct iw_point *data = &wrqu->essid;
1751 CsrWifiSmeConnectionInfo connectionInfo;
1752 int r = 0;
1753
1754 unifi_trace(priv, UDBG2, "unifi_giwessid\n");
1755 CHECK_INITED(priv);
1756
1757 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
1758 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
1759 unifi_error(priv, "unifi_giwessid: not permitted in Mode %d\n",
1760 interfacePriv->interfaceMode);
1761 return -EPERM;
1762 }
1763
1764 UF_RTNL_UNLOCK();
1765 r = sme_mgt_connection_info_get(priv, &connectionInfo);
1766 UF_RTNL_LOCK();
1767
1768 if (r == 0) {
1769 data->length = connectionInfo.ssid.length;
1770 strncpy(essid,
1771 connectionInfo.ssid.ssid,
1772 data->length);
1773 data->flags = 1; /* active */
1774
1775 unifi_trace(priv, UDBG2, "unifi_giwessid: %.*s\n",
1776 data->length, essid);
1777 }
1778
1779
1780 return 0;
1781 } /* unifi_giwessid() */
1782
1783
1784 static int
1785 unifi_siwrate(struct net_device *dev, struct iw_request_info *info,
1786 union iwreq_data *wrqu, char *extra)
1787 {
1788 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1789 unifi_priv_t *priv = interfacePriv->privPtr;
1790 struct iw_param *args = &wrqu->bitrate;
1791 CsrWifiSmeMibConfig mibConfig;
1792 int r;
1793
1794 CHECK_INITED(priv);
1795 unifi_trace(priv, UDBG2, "unifi_siwrate\n");
1796
1797 /*
1798 * If args->fixed == 0, value is max rate or -1 for best
1799 * If args->fixed == 1, value is rate to set or -1 for best
1800 * args->disabled and args->flags are not used in SIOCSIWRATE
1801 */
1802
1803 /* Get, modify and set the MIB data */
1804 UF_RTNL_UNLOCK();
1805 r = sme_mgt_mib_config_get(priv, &mibConfig);
1806 UF_RTNL_LOCK();
1807 if (r) {
1808 unifi_error(priv, "unifi_siwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1809 return r;
1810 }
1811
1812 /* Default to auto rate algorithm */
1813 /* in 500Kbit/s, 0 means auto */
1814 mibConfig.unifiFixTxDataRate = 0;
1815
1816 if (args->value != -1) {
1817 mibConfig.unifiFixTxDataRate = args->value / 500000;
1818 }
1819
1820 /* 1 means rate is a maximum, 2 means rate is a set value */
1821 if (args->fixed == 1) {
1822 mibConfig.unifiFixMaxTxDataRate = 0;
1823 } else {
1824 mibConfig.unifiFixMaxTxDataRate = 1;
1825 }
1826 UF_RTNL_UNLOCK();
1827 r = sme_mgt_mib_config_set(priv, &mibConfig);
1828 UF_RTNL_LOCK();
1829 if (r) {
1830 unifi_error(priv, "unifi_siwrate: Set CsrWifiSmeMibConfigValue failed.\n");
1831 return r;
1832 }
1833
1834
1835 return 0;
1836 } /* unifi_siwrate() */
1837
1838
1839
1840 static int
1841 unifi_giwrate(struct net_device *dev, struct iw_request_info *info,
1842 union iwreq_data *wrqu, char *extra)
1843 {
1844 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1845 unifi_priv_t *priv = interfacePriv->privPtr;
1846 struct iw_param *args = &wrqu->bitrate;
1847 int r;
1848 int bitrate, flag;
1849 CsrWifiSmeMibConfig mibConfig;
1850 CsrWifiSmeConnectionStats connectionStats;
1851
1852 unifi_trace(priv, UDBG2, "unifi_giwrate\n");
1853 CHECK_INITED(priv);
1854
1855 flag = 0;
1856 bitrate = 0;
1857 UF_RTNL_UNLOCK();
1858 r = sme_mgt_mib_config_get(priv, &mibConfig);
1859 UF_RTNL_LOCK();
1860 if (r) {
1861 unifi_error(priv, "unifi_giwrate: Get CsrWifiSmeMibConfigValue failed.\n");
1862 return r;
1863 }
1864
1865 bitrate = mibConfig.unifiFixTxDataRate;
1866 flag = mibConfig.unifiFixMaxTxDataRate;
1867
1868 /* Used the value returned by the SME if MIB returns 0 */
1869 if (bitrate == 0) {
1870 UF_RTNL_UNLOCK();
1871 r = sme_mgt_connection_stats_get(priv, &connectionStats);
1872 UF_RTNL_LOCK();
1873 /* Ignore errors, we may be disconnected */
1874 if (r == 0) {
1875 bitrate = connectionStats.unifiTxDataRate;
1876 }
1877 }
1878
1879 args->value = bitrate * 500000;
1880 args->fixed = !flag;
1881
1882 return 0;
1883 } /* unifi_giwrate() */
1884
1885
1886 static int
1887 unifi_siwrts(struct net_device *dev, struct iw_request_info *info,
1888 union iwreq_data *wrqu, char *extra)
1889 {
1890 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1891 unifi_priv_t *priv = interfacePriv->privPtr;
1892 int val = wrqu->rts.value;
1893 int r = 0;
1894 CsrWifiSmeMibConfig mibConfig;
1895
1896 unifi_trace(priv, UDBG2, "unifi_siwrts\n");
1897 CHECK_INITED(priv);
1898
1899 if (wrqu->rts.disabled) {
1900 val = 2347;
1901 }
1902
1903 if ( (val < 0) || (val > 2347) )
1904 {
1905 return -EINVAL;
1906 }
1907
1908 /* Get, modify and set the MIB data */
1909 UF_RTNL_UNLOCK();
1910 r = sme_mgt_mib_config_get(priv, &mibConfig);
1911 UF_RTNL_LOCK();
1912 if (r) {
1913 unifi_error(priv, "unifi_siwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1914 return r;
1915 }
1916 mibConfig.dot11RtsThreshold = val;
1917 UF_RTNL_UNLOCK();
1918 r = sme_mgt_mib_config_set(priv, &mibConfig);
1919 UF_RTNL_LOCK();
1920 if (r) {
1921 unifi_error(priv, "unifi_siwrts: Set CsrWifiSmeMibConfigValue failed.\n");
1922 return r;
1923 }
1924
1925 return 0;
1926 }
1927
1928
1929 static int
1930 unifi_giwrts(struct net_device *dev, struct iw_request_info *info,
1931 union iwreq_data *wrqu, char *extra)
1932 {
1933 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1934 unifi_priv_t *priv = interfacePriv->privPtr;
1935 int r;
1936 int rts_thresh;
1937 CsrWifiSmeMibConfig mibConfig;
1938
1939 unifi_trace(priv, UDBG2, "unifi_giwrts\n");
1940 CHECK_INITED(priv);
1941
1942 UF_RTNL_UNLOCK();
1943 r = sme_mgt_mib_config_get(priv, &mibConfig);
1944 UF_RTNL_LOCK();
1945 if (r) {
1946 unifi_error(priv, "unifi_giwrts: Get CsrWifiSmeMibConfigValue failed.\n");
1947 return r;
1948 }
1949
1950 rts_thresh = mibConfig.dot11RtsThreshold;
1951 if (rts_thresh > 2347) {
1952 rts_thresh = 2347;
1953 }
1954
1955 wrqu->rts.value = rts_thresh;
1956 wrqu->rts.disabled = (rts_thresh == 2347);
1957 wrqu->rts.fixed = 1;
1958
1959 return 0;
1960 }
1961
1962
1963 static int
1964 unifi_siwfrag(struct net_device *dev, struct iw_request_info *info,
1965 union iwreq_data *wrqu, char *extra)
1966 {
1967 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
1968 unifi_priv_t *priv = interfacePriv->privPtr;
1969 int val = wrqu->frag.value;
1970 int r = 0;
1971 CsrWifiSmeMibConfig mibConfig;
1972
1973 unifi_trace(priv, UDBG2, "unifi_siwfrag\n");
1974 CHECK_INITED(priv);
1975
1976 if (wrqu->frag.disabled)
1977 val = 2346;
1978
1979 if ( (val < 256) || (val > 2347) )
1980 return -EINVAL;
1981
1982 /* Get, modify and set the MIB data */
1983 UF_RTNL_UNLOCK();
1984 r = sme_mgt_mib_config_get(priv, &mibConfig);
1985 UF_RTNL_LOCK();
1986 if (r) {
1987 unifi_error(priv, "unifi_siwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
1988 return r;
1989 }
1990 /* Fragmentation Threashold must be even */
1991 mibConfig.dot11FragmentationThreshold = (val & ~0x1);
1992 UF_RTNL_UNLOCK();
1993 r = sme_mgt_mib_config_set(priv, &mibConfig);
1994 UF_RTNL_LOCK();
1995 if (r) {
1996 unifi_error(priv, "unifi_siwfrag: Set CsrWifiSmeMibConfigValue failed.\n");
1997 return r;
1998 }
1999
2000 return 0;
2001 }
2002
2003
2004 static int
2005 unifi_giwfrag(struct net_device *dev, struct iw_request_info *info,
2006 union iwreq_data *wrqu, char *extra)
2007 {
2008 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2009 unifi_priv_t *priv = interfacePriv->privPtr;
2010 int r;
2011 int frag_thresh;
2012 CsrWifiSmeMibConfig mibConfig;
2013
2014 unifi_trace(priv, UDBG2, "unifi_giwfrag\n");
2015 CHECK_INITED(priv);
2016
2017 UF_RTNL_UNLOCK();
2018 r = sme_mgt_mib_config_get(priv, &mibConfig);
2019 UF_RTNL_LOCK();
2020 if (r) {
2021 unifi_error(priv, "unifi_giwfrag: Get CsrWifiSmeMibConfigValue failed.\n");
2022 return r;
2023 }
2024
2025 frag_thresh = mibConfig.dot11FragmentationThreshold;
2026
2027 /* Build the return structure */
2028 wrqu->frag.value = frag_thresh;
2029 wrqu->frag.disabled = (frag_thresh >= 2346);
2030 wrqu->frag.fixed = 1;
2031
2032 return 0;
2033 }
2034
2035
2036 static int
2037 unifi_siwencode(struct net_device *dev, struct iw_request_info *info,
2038 union iwreq_data *wrqu, char *extra)
2039 {
2040 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2041 unifi_priv_t *priv = interfacePriv->privPtr;
2042 struct iw_point *erq = &wrqu->encoding;
2043 int index;
2044 int rc = 0;
2045 int privacy = -1;
2046 CsrWifiSmeKey sme_key;
2047
2048 unifi_trace(priv, UDBG2, "unifi_siwencode\n");
2049
2050 CHECK_INITED(priv);
2051
2052 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2053 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2054 unifi_error(priv, "unifi_siwencode: not permitted in Mode %d\n",
2055 interfacePriv->interfaceMode);
2056 return -EPERM;
2057 }
2058
2059
2060 /*
2061 * Key index is encoded in the flags.
2062 * 0 - use current default,
2063 * 1-4 - if a key value is given set that key
2064 * if not use that key
2065 */
2066 index = (erq->flags & IW_ENCODE_INDEX); /* key number, 1-4 */
2067 if ((index < 0) || (index > 4)) {
2068 unifi_error(priv, "unifi_siwencode: Request to set an invalid key (index:%d)", index);
2069 return -EINVAL;
2070 }
2071
2072 /*
2073 * Basic checking: do we have a key to set ?
2074 * The IW_ENCODE_NOKEY flag is set when no key is present (only change flags),
2075 * but older versions rely on sending a key id 1-4.
2076 */
2077 if (erq->length > 0) {
2078
2079 /* Check the size of the key */
2080 if ((erq->length > LARGE_KEY_SIZE) || (erq->length < SMALL_KEY_SIZE)) {
2081 unifi_error(priv, "unifi_siwencode: Request to set an invalid key (length:%d)",
2082 erq->length);
2083 return -EINVAL;
2084 }
2085
2086 /* Check the index (none (i.e. 0) means use current) */
2087 if ((index < 1) || (index > 4)) {
2088 /* If we do not have a previous key, use 1 as default */
2089 if (!priv->wep_tx_key_index) {
2090 priv->wep_tx_key_index = 1;
2091 }
2092 index = priv->wep_tx_key_index;
2093 }
2094
2095 /* If we didn't have a key and a valid index is set, we want to remember it*/
2096 if (!priv->wep_tx_key_index) {
2097 priv->wep_tx_key_index = index;
2098 }
2099
2100 unifi_trace(priv, UDBG1, "Tx key Index is %d\n", priv->wep_tx_key_index);
2101
2102 privacy = 1;
2103
2104 /* Check if the key is not marked as invalid */
2105 if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
2106
2107 unifi_trace(priv, UDBG1, "New %s key (len=%d, index=%d)\n",
2108 (priv->wep_tx_key_index == index) ? "tx" : "",
2109 erq->length, index);
2110
2111 sme_key.wepTxKey = (priv->wep_tx_key_index == index);
2112 if (priv->wep_tx_key_index == index) {
2113 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2114 } else {
2115 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2116 }
2117 /* Key index is zero based in SME but 1 based in wext */
2118 sme_key.keyIndex = (index - 1);
2119 sme_key.keyLength = erq->length;
2120 sme_key.authenticator = 0;
2121 memset(sme_key.address.a, 0xFF, ETH_ALEN);
2122 memcpy(sme_key.key, extra, erq->length);
2123
2124 UF_RTNL_UNLOCK();
2125 rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2126 UF_RTNL_LOCK();
2127 if (rc) {
2128 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2129 return convert_sme_error(rc);
2130 }
2131
2132 /* Store the key to be reported by the SIOCGIWENCODE handler */
2133 priv->wep_keys[index - 1].len = erq->length;
2134 memcpy(priv->wep_keys[index - 1].key, extra, erq->length);
2135 }
2136 } else {
2137 /*
2138 * No additional key data, so it must be a request to change the
2139 * active key.
2140 */
2141 if (index != 0) {
2142 unifi_trace(priv, UDBG1, "Tx key Index is %d\n", index - 1);
2143
2144 /* Store the index to be reported by the SIOCGIWENCODE handler */
2145 priv->wep_tx_key_index = index;
2146
2147 sme_key.wepTxKey = 1;
2148 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2149
2150 /* Key index is zero based in SME but 1 based in wext */
2151 sme_key.keyIndex = (index - 1);
2152 sme_key.keyLength = 0;
2153 sme_key.authenticator = 0;
2154 UF_RTNL_UNLOCK();
2155 rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2156 UF_RTNL_LOCK();
2157 if (rc) {
2158 unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc);
2159 return convert_sme_error(rc);
2160 }
2161
2162 /* Turn on encryption */
2163 privacy = 1;
2164 }
2165 }
2166
2167 /* Read the flags */
2168 if (erq->flags & IW_ENCODE_DISABLED) {
2169 /* disable encryption */
2170 unifi_trace(priv, UDBG1, "disable WEP encryption\n");
2171 privacy = 0;
2172
2173 priv->wep_tx_key_index = 0;
2174
2175 unifi_trace(priv, UDBG1, "IW_ENCODE_DISABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2176 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2177 }
2178
2179 if (erq->flags & IW_ENCODE_RESTRICTED) {
2180 /* Use shared key auth */
2181 unifi_trace(priv, UDBG1, "IW_ENCODE_RESTRICTED: CSR_WIFI_SME_AUTH_MODE_80211_SHARED\n");
2182 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2183
2184 /* Turn on encryption */
2185 privacy = 1;
2186 }
2187 if (erq->flags & IW_ENCODE_OPEN) {
2188 unifi_trace(priv, UDBG1, "IW_ENCODE_OPEN: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2189 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2190 }
2191
2192 /* Commit the changes to flags if needed */
2193 if (privacy != -1) {
2194 priv->connection_config.privacyMode = privacy ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2195 priv->connection_config.encryptionModeMask = privacy ? (CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 |
2196 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 |
2197 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2198 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104) :
2199 CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2200 }
2201
2202 return convert_sme_error(rc);
2203
2204 } /* unifi_siwencode() */
2205
2206
2207
2208 static int
2209 unifi_giwencode(struct net_device *dev, struct iw_request_info *info,
2210 union iwreq_data *wrqu, char *extra)
2211 {
2212 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2213 unifi_priv_t *priv = interfacePriv->privPtr;
2214 struct iw_point *erq = &wrqu->encoding;
2215
2216 unifi_trace(priv, UDBG2, "unifi_giwencode\n");
2217
2218 CHECK_INITED(priv);
2219
2220 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2221 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2222 unifi_error(priv, "unifi_giwencode: not permitted in Mode %d\n",
2223 interfacePriv->interfaceMode);
2224 return -EPERM;
2225 }
2226
2227
2228 if (priv->connection_config.authModeMask == CSR_WIFI_SME_AUTH_MODE_80211_SHARED) {
2229 erq->flags = IW_ENCODE_RESTRICTED;
2230 }
2231 else {
2232 if (priv->connection_config.privacyMode == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) {
2233 erq->flags = IW_ENCODE_DISABLED;
2234 } else {
2235 erq->flags = IW_ENCODE_OPEN;
2236 }
2237 }
2238
2239 erq->length = 0;
2240
2241 if (erq->flags != IW_ENCODE_DISABLED) {
2242 int index = priv->wep_tx_key_index;
2243
2244 if ((index > 0) && (index <= NUM_WEPKEYS)) {
2245 erq->flags |= (index & IW_ENCODE_INDEX);
2246 erq->length = priv->wep_keys[index - 1].len;
2247 memcpy(extra, priv->wep_keys[index - 1].key, erq->length);
2248 } else {
2249 unifi_notice(priv, "unifi_giwencode: Surprise, do not have a valid key index (%d)\n",
2250 index);
2251 }
2252 }
2253
2254 return 0;
2255 } /* unifi_giwencode() */
2256
2257
2258 static int
2259 unifi_siwpower(struct net_device *dev, struct iw_request_info *info,
2260 union iwreq_data *wrqu, char *extra)
2261 {
2262 struct iw_param *args = &wrqu->power;
2263 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2264 unifi_priv_t *priv = interfacePriv->privPtr;
2265 int listen_interval, wake_for_dtim;
2266 int r = 0;
2267 CsrWifiSmePowerConfig powerConfig;
2268
2269 unifi_trace(priv, UDBG2, "unifi_siwpower\n");
2270
2271 CHECK_INITED(priv);
2272
2273 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2274 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2275 unifi_error(priv, "unifi_siwpower: not permitted in Mode %d\n",
2276 interfacePriv->interfaceMode);
2277 return -EPERM;
2278 }
2279
2280 UF_RTNL_UNLOCK();
2281 r = sme_mgt_power_config_get(priv, &powerConfig);
2282 UF_RTNL_LOCK();
2283 if (r) {
2284 unifi_error(priv, "unifi_siwpower: Get unifi_PowerConfigValue failed.\n");
2285 return r;
2286 }
2287
2288 listen_interval = -1;
2289 wake_for_dtim = -1;
2290 if (args->disabled) {
2291 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
2292 }
2293 else
2294 {
2295 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
2296
2297 switch (args->flags & IW_POWER_TYPE) {
2298 case 0:
2299 /* not specified */
2300 break;
2301 case IW_POWER_PERIOD:
2302 listen_interval = args->value / 1000;
2303 break;
2304 default:
2305 return -EINVAL;
2306 }
2307
2308 switch (args->flags & IW_POWER_MODE) {
2309 case 0:
2310 /* not specified */
2311 break;
2312 case IW_POWER_UNICAST_R:
2313 /* not interested in broadcast packets */
2314 wake_for_dtim = 0;
2315 break;
2316 case IW_POWER_ALL_R:
2317 /* yes, we are interested in broadcast packets */
2318 wake_for_dtim = 1;
2319 break;
2320 default:
2321 return -EINVAL;
2322 }
2323 }
2324
2325 if (listen_interval > 0) {
2326 powerConfig.listenIntervalTu = listen_interval;
2327 unifi_trace(priv, UDBG4, "unifi_siwpower: new Listen Interval = %d.\n",
2328 powerConfig.listenIntervalTu);
2329 }
2330
2331 if (wake_for_dtim >= 0) {
2332 powerConfig.rxDtims = wake_for_dtim;
2333 }
2334 UF_RTNL_UNLOCK();
2335 r = sme_mgt_power_config_set(priv, &powerConfig);
2336 UF_RTNL_LOCK();
2337 if (r) {
2338 unifi_error(priv, "unifi_siwpower: Set unifi_PowerConfigValue failed.\n");
2339 return r;
2340 }
2341
2342 return 0;
2343 } /* unifi_siwpower() */
2344
2345
2346 static int
2347 unifi_giwpower(struct net_device *dev, struct iw_request_info *info,
2348 union iwreq_data *wrqu, char *extra)
2349 {
2350 struct iw_param *args = &wrqu->power;
2351 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2352 unifi_priv_t *priv = interfacePriv->privPtr;
2353 CsrWifiSmePowerConfig powerConfig;
2354 int r;
2355
2356 unifi_trace(priv, UDBG2, "unifi_giwpower\n");
2357
2358 CHECK_INITED(priv);
2359
2360 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2361 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2362 unifi_error(priv, "unifi_giwpower: not permitted in Mode %d\n",
2363 interfacePriv->interfaceMode);
2364 return -EPERM;
2365 }
2366
2367
2368 args->flags = 0;
2369 UF_RTNL_UNLOCK();
2370 r = sme_mgt_power_config_get(priv, &powerConfig);
2371 UF_RTNL_LOCK();
2372 if (r) {
2373 unifi_error(priv, "unifi_giwpower: Get unifi_PowerConfigValue failed.\n");
2374 return r;
2375 }
2376
2377 unifi_trace(priv, UDBG4, "unifi_giwpower: mode=%d\n",
2378 powerConfig.powerSaveLevel);
2379
2380 args->disabled = (powerConfig.powerSaveLevel == CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW);
2381 if (args->disabled) {
2382 args->flags = 0;
2383 return 0;
2384 }
2385
2386 args->value = powerConfig.listenIntervalTu * 1000;
2387 args->flags |= IW_POWER_PERIOD;
2388
2389 if (powerConfig.rxDtims) {
2390 args->flags |= IW_POWER_ALL_R;
2391 } else {
2392 args->flags |= IW_POWER_UNICAST_R;
2393 }
2394
2395 return 0;
2396 } /* unifi_giwpower() */
2397
2398
2399 /*
2400 * ---------------------------------------------------------------------------
2401 * unifi_siwcommit - handler for SIOCSIWCOMMIT
2402 *
2403 * Apply all the parameters that have been set.
2404 * In practice this means:
2405 * - do a scan
2406 * - join a network or start an AdHoc
2407 * - authenticate and associate.
2408 *
2409 * Arguments:
2410 * None.
2411 *
2412 * Returns:
2413 * None.
2414 * ---------------------------------------------------------------------------
2415 */
2416 static int
2417 unifi_siwcommit(struct net_device *dev, struct iw_request_info *info,
2418 union iwreq_data *wrqu, char *extra)
2419 {
2420 return 0;
2421 } /* unifi_siwcommit() */
2422
2423
2424
2425 static int
2426 unifi_siwmlme(struct net_device *dev, struct iw_request_info *info,
2427 union iwreq_data *wrqu, char *extra)
2428 {
2429 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2430 unifi_priv_t *priv = interfacePriv->privPtr;
2431 struct iw_mlme *mlme = (struct iw_mlme *)extra;
2432
2433 unifi_trace(priv, UDBG2, "unifi_siwmlme\n");
2434 CHECK_INITED(priv);
2435
2436 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2437 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2438 unifi_error(priv, "unifi_siwmlme: not permitted in Mode %d\n",
2439 interfacePriv->interfaceMode);
2440 return -EPERM;
2441 }
2442
2443
2444 switch (mlme->cmd) {
2445 case IW_MLME_DEAUTH:
2446 case IW_MLME_DISASSOC:
2447 UF_RTNL_UNLOCK();
2448 sme_mgt_disconnect(priv);
2449 UF_RTNL_LOCK();
2450 break;
2451 default:
2452 return -EOPNOTSUPP;
2453 }
2454
2455 return 0;
2456 } /* unifi_siwmlme() */
2457
2458
2459 /*
2460 * ---------------------------------------------------------------------------
2461 * unifi_siwgenie
2462 * unifi_giwgenie
2463 *
2464 * WPA : Generic IEEE 802.11 information element (e.g., for WPA/RSN/WMM).
2465 * Handlers for SIOCSIWGENIE, SIOCGIWGENIE - set/get generic IE
2466 *
2467 * The host program (e.g. wpa_supplicant) uses this call to set the
2468 * additional IEs to accompany the next (Associate?) request.
2469 *
2470 * Arguments:
2471 * None.
2472 *
2473 * Returns:
2474 * None.
2475 * Notes:
2476 * From wireless.h:
2477 * This ioctl uses struct iw_point and data buffer that includes IE id
2478 * and len fields. More than one IE may be included in the
2479 * request. Setting the generic IE to empty buffer (len=0) removes the
2480 * generic IE from the driver.
2481 * ---------------------------------------------------------------------------
2482 */
2483 static int
2484 unifi_siwgenie(struct net_device *dev, struct iw_request_info *info,
2485 union iwreq_data *wrqu, char *extra)
2486 {
2487 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2488 unifi_priv_t *priv = interfacePriv->privPtr;
2489 int len;
2490
2491 unifi_trace(priv, UDBG2, "unifi_siwgenie\n");
2492
2493 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2494 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2495 unifi_error(priv, "unifi_siwgenie: not permitted in Mode %d\n",
2496 interfacePriv->interfaceMode);
2497 return -EPERM;
2498 }
2499
2500
2501 if ( priv->connection_config.mlmeAssociateReqInformationElements) {
2502 kfree( priv->connection_config.mlmeAssociateReqInformationElements);
2503 }
2504 priv->connection_config.mlmeAssociateReqInformationElementsLength = 0;
2505 priv->connection_config.mlmeAssociateReqInformationElements = NULL;
2506
2507 len = wrqu->data.length;
2508 if (len == 0) {
2509 return 0;
2510 }
2511
2512 priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL);
2513 if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) {
2514 return -ENOMEM;
2515 }
2516
2517 priv->connection_config.mlmeAssociateReqInformationElementsLength = len;
2518 memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len);
2519
2520 return 0;
2521 } /* unifi_siwgenie() */
2522
2523
2524 static int
2525 unifi_giwgenie(struct net_device *dev, struct iw_request_info *info,
2526 union iwreq_data *wrqu, char *extra)
2527 {
2528 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2529 unifi_priv_t *priv = interfacePriv->privPtr;
2530 int len;
2531
2532 unifi_trace(priv, UDBG2, "unifi_giwgenie\n");
2533
2534 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2535 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2536 unifi_error(priv, "unifi_giwgenie: not permitted in Mode %d\n",
2537 interfacePriv->interfaceMode);
2538 return -EPERM;
2539 }
2540
2541
2542 len = priv->connection_config.mlmeAssociateReqInformationElementsLength;
2543
2544 if (len == 0) {
2545 wrqu->data.length = 0;
2546 return 0;
2547 }
2548
2549 if (wrqu->data.length < len) {
2550 return -E2BIG;
2551 }
2552
2553 wrqu->data.length = len;
2554 memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len);
2555
2556 return 0;
2557 } /* unifi_giwgenie() */
2558
2559
2560 /*
2561 * ---------------------------------------------------------------------------
2562 * unifi_siwauth
2563 * unifi_giwauth
2564 *
2565 * Handlers for SIOCSIWAUTH, SIOCGIWAUTH
2566 * Set/get various authentication parameters.
2567 *
2568 * Arguments:
2569 *
2570 *
2571 * Returns:
2572 * None.
2573 * ---------------------------------------------------------------------------
2574 */
2575 static int
2576 _unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2577 union iwreq_data *wrqu, char *extra)
2578 {
2579 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2580 unifi_priv_t *priv = interfacePriv->privPtr;
2581 CsrWifiSmeAuthModeMask new_auth;
2582
2583 unifi_trace(priv, UDBG2, "unifi_siwauth\n");
2584
2585 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2586 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2587 unifi_error(priv, "unifi_siwauth: not permitted in Mode %d\n",
2588 interfacePriv->interfaceMode);
2589 return -EPERM;
2590 }
2591
2592
2593 /*
2594 * This ioctl is safe to call even when UniFi is powered off.
2595 * wpa_supplicant calls it to test whether we support WPA.
2596 */
2597
2598 switch (wrqu->param.flags & IW_AUTH_INDEX) {
2599
2600 case IW_AUTH_WPA_ENABLED:
2601 unifi_trace(priv, UDBG1, "IW_AUTH_WPA_ENABLED: %d\n", wrqu->param.value);
2602
2603 if (wrqu->param.value == 0) {
2604 unifi_trace(priv, UDBG5, "IW_AUTH_WPA_ENABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n");
2605 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2606 }
2607 break;
2608
2609 case IW_AUTH_PRIVACY_INVOKED:
2610 unifi_trace(priv, UDBG1, "IW_AUTH_PRIVACY_INVOKED: %d\n", wrqu->param.value);
2611
2612 priv->connection_config.privacyMode = wrqu->param.value ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED;
2613 if (wrqu->param.value == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED)
2614 {
2615 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2616 }
2617 break;
2618
2619 case IW_AUTH_80211_AUTH_ALG:
2620 /*
2621 IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
2622 IW_AUTH_ALG_SHARED_KEY 0x00000002
2623 IW_AUTH_ALG_LEAP 0x00000004
2624 */
2625 new_auth = 0;
2626 if (wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) {
2627 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_OPEN_SYSTEM)\n", wrqu->param.value);
2628 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2629 }
2630 if (wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) {
2631 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_SHARED_KEY)\n", wrqu->param.value);
2632 new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_SHARED;
2633 }
2634 if (wrqu->param.value & IW_AUTH_ALG_LEAP) {
2635 /* Initial exchanges using open-system to set EAP */
2636 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_LEAP)\n", wrqu->param.value);
2637 new_auth |= CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X;
2638 }
2639 if (new_auth == 0) {
2640 unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: invalid value %d\n",
2641 wrqu->param.value);
2642 return -EINVAL;
2643 } else {
2644 priv->connection_config.authModeMask = new_auth;
2645 }
2646 break;
2647
2648 case IW_AUTH_WPA_VERSION:
2649 unifi_trace(priv, UDBG1, "IW_AUTH_WPA_VERSION: %d\n", wrqu->param.value);
2650 priv->ignore_bssid_join = TRUE;
2651 /*
2652 IW_AUTH_WPA_VERSION_DISABLED 0x00000001
2653 IW_AUTH_WPA_VERSION_WPA 0x00000002
2654 IW_AUTH_WPA_VERSION_WPA2 0x00000004
2655 */
2656
2657 if (!(wrqu->param.value & IW_AUTH_WPA_VERSION_DISABLED)) {
2658
2659 priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN;
2660
2661 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA) {
2662 unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA, WPA-PSK\n");
2663 priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK);
2664 }
2665 if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA2) {
2666 unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA2, WPA2-PSK\n");
2667 priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK);
2668 }
2669 }
2670 break;
2671
2672 case IW_AUTH_CIPHER_PAIRWISE:
2673 unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_PAIRWISE: %d\n", wrqu->param.value);
2674 /*
2675 * one of:
2676 IW_AUTH_CIPHER_NONE 0x00000001
2677 IW_AUTH_CIPHER_WEP40 0x00000002
2678 IW_AUTH_CIPHER_TKIP 0x00000004
2679 IW_AUTH_CIPHER_CCMP 0x00000008
2680 IW_AUTH_CIPHER_WEP104 0x00000010
2681 */
2682
2683 priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
2684
2685 if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2686 priv->connection_config.encryptionModeMask |=
2687 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2688 }
2689 if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2690 priv->connection_config.encryptionModeMask |=
2691 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2692 }
2693 if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2694 priv->connection_config.encryptionModeMask |=
2695 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2696 }
2697 if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2698 priv->connection_config.encryptionModeMask |=
2699 CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2700 }
2701
2702 break;
2703
2704 case IW_AUTH_CIPHER_GROUP:
2705 unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_GROUP: %d\n", wrqu->param.value);
2706 /*
2707 * Use the WPA version and the group cipher suite to set the permitted
2708 * group key in the MIB. f/w uses this value to validate WPA and RSN IEs
2709 * in the probe responses from the desired BSS(ID)
2710 */
2711
2712 priv->connection_config.encryptionModeMask &= ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 |
2713 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 |
2714 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP |
2715 CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP);
2716 if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
2717 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40;
2718 }
2719 if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
2720 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104;
2721 }
2722 if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
2723 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP;
2724 }
2725 if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
2726 priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP;
2727 }
2728
2729 break;
2730
2731 case IW_AUTH_KEY_MGMT:
2732 unifi_trace(priv, UDBG1, "IW_AUTH_KEY_MGMT: %d\n", wrqu->param.value);
2733 /*
2734 IW_AUTH_KEY_MGMT_802_1X 1
2735 IW_AUTH_KEY_MGMT_PSK 2
2736 */
2737 if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK)) {
2738 /* Check for explicitly set mode. */
2739 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2740 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK;
2741 }
2742 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2743 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA;
2744 }
2745 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA: %d\n",
2746 priv->connection_config.authModeMask);
2747 }
2748 if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK)) {
2749 /* Check for explicitly set mode. */
2750 if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) {
2751 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK;
2752 }
2753 if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) {
2754 priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2;
2755 }
2756 unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA2: %d\n",
2757 priv->connection_config.authModeMask);
2758 }
2759
2760 break;
2761 case IW_AUTH_TKIP_COUNTERMEASURES:
2762 /*
2763 * Set to true at the start of the 60 second backup-off period
2764 * following 2 MichaelMIC failures within 60s.
2765 */
2766 unifi_trace(priv, UDBG1, "IW_AUTH_TKIP_COUNTERMEASURES: %d\n", wrqu->param.value);
2767 break;
2768
2769 case IW_AUTH_DROP_UNENCRYPTED:
2770 /*
2771 * Set to true on init.
2772 * Set to false just before associate if encryption will not be
2773 * required.
2774 *
2775 * Note this is not the same as the 802.1X controlled port
2776 */
2777 unifi_trace(priv, UDBG1, "IW_AUTH_DROP_UNENCRYPTED: %d\n", wrqu->param.value);
2778 break;
2779
2780 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2781 /*
2782 * This is set by wpa_supplicant to allow unencrypted EAPOL messages
2783 * even if pairwise keys are set when not using WPA. IEEE 802.1X
2784 * specifies that these frames are not encrypted, but WPA encrypts
2785 * them when pairwise keys are in use.
2786 * I think the UniFi f/w handles this decision for us.
2787 */
2788 unifi_trace(priv, UDBG1, "IW_AUTH_RX_UNENCRYPTED_EAPOL: %d\n", wrqu->param.value);
2789 break;
2790
2791 case IW_AUTH_ROAMING_CONTROL:
2792 unifi_trace(priv, UDBG1, "IW_AUTH_ROAMING_CONTROL: %d\n", wrqu->param.value);
2793 break;
2794
2795 default:
2796 unifi_trace(priv, UDBG1, "Unsupported auth param %d to 0x%X\n",
2797 wrqu->param.flags & IW_AUTH_INDEX,
2798 wrqu->param.value);
2799 return -EOPNOTSUPP;
2800 }
2801
2802 unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask);
2803
2804 return 0;
2805 } /* _unifi_siwauth() */
2806
2807
2808 static int
2809 unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
2810 union iwreq_data *wrqu, char *extra)
2811 {
2812 int err = 0;
2813
2814 UF_RTNL_UNLOCK();
2815 err = _unifi_siwauth(dev, info, wrqu, extra);
2816 UF_RTNL_LOCK();
2817
2818 return err;
2819 } /* unifi_siwauth() */
2820
2821
2822 static int
2823 unifi_giwauth(struct net_device *dev, struct iw_request_info *info,
2824 union iwreq_data *wrqu, char *extra)
2825 {
2826 unifi_trace(NULL, UDBG2, "unifi_giwauth\n");
2827 return -EOPNOTSUPP;
2828 } /* unifi_giwauth() */
2829
2830 /*
2831 * ---------------------------------------------------------------------------
2832 * unifi_siwencodeext
2833 * unifi_giwencodeext
2834 *
2835 * Handlers for SIOCSIWENCODEEXT, SIOCGIWENCODEEXT - set/get
2836 * encoding token & mode
2837 *
2838 * Arguments:
2839 * None.
2840 *
2841 * Returns:
2842 * None.
2843 *
2844 * Notes:
2845 * For WPA/WPA2 we don't take note of the IW_ENCODE_EXT_SET_TX_KEY flag.
2846 * This flag means "use this key to encode transmissions"; we just
2847 * assume only one key will be set and that is the one to use.
2848 * ---------------------------------------------------------------------------
2849 */
2850 static int
2851 _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
2852 union iwreq_data *wrqu, char *extra)
2853 {
2854 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
2855 unifi_priv_t *priv = interfacePriv->privPtr;
2856 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
2857 int r = 0;
2858 unsigned char *keydata;
2859 unsigned char tkip_key[32];
2860 int keyid;
2861 unsigned char *a = (unsigned char *)ext->addr.sa_data;
2862 CsrWifiSmeKey sme_key;
2863 CsrWifiSmeKeyType key_type;
2864
2865 CHECK_INITED(priv);
2866
2867 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
2868 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
2869 unifi_error(priv, "unifi_siwencodeext: not permitted in Mode %d\n",
2870 interfacePriv->interfaceMode);
2871 return -EPERM;
2872 }
2873
2874
2875 unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n",
2876 wrqu->encoding.flags, ext->alg, ext->ext_flags,
2877 ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX));
2878 unifi_trace(priv, UDBG3, " addr=%pM\n", a);
2879
2880 if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
2881 /* This means use a different key (given by key_idx) for Tx. */
2882 /* NYI */
2883 unifi_trace(priv, UDBG1, KERN_ERR "unifi_siwencodeext: NYI should change tx key id here!!\n");
2884 return -ENOTSUPP;
2885 }
2886
2887 memset(&sme_key, 0, sizeof(sme_key));
2888
2889 keydata = (unsigned char *)(ext + 1);
2890 keyid = (wrqu->encoding.flags & IW_ENCODE_INDEX);
2891
2892 /*
2893 * Check for request to delete keys for an address.
2894 */
2895 /* Pick out request for no privacy. */
2896 if (ext->alg == IW_ENCODE_ALG_NONE) {
2897
2898 unifi_trace(priv, UDBG1, "Deleting %s key %d\n",
2899 (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? "GROUP" : "PAIRWISE",
2900 keyid);
2901
2902 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
2903 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2904 } else {
2905 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2906 }
2907 sme_key.keyIndex = (keyid - 1);
2908 sme_key.keyLength = 0;
2909 sme_key.authenticator = 0;
2910 memcpy(sme_key.address.a, a, ETH_ALEN);
2911 UF_RTNL_UNLOCK();
2912 r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_REMOVE);
2913 UF_RTNL_LOCK();
2914 if (r) {
2915 unifi_error(priv, "Delete key request was rejected with result %d\n", r);
2916 return convert_sme_error(r);
2917 }
2918
2919 return 0;
2920 }
2921
2922 /*
2923 * Request is to set a key, not delete
2924 */
2925
2926 /* Pick out WEP and use set_wep_key(). */
2927 if (ext->alg == IW_ENCODE_ALG_WEP) {
2928 /* WEP-40, WEP-104 */
2929
2930 /* Check for valid key length */
2931 if (!((ext->key_len == 5) || (ext->key_len == 13))) {
2932 unifi_trace(priv, UDBG1, KERN_ERR "Invalid length for WEP key: %d\n", ext->key_len);
2933 return -EINVAL;
2934 }
2935
2936 unifi_trace(priv, UDBG1, "Setting WEP key %d tx:%d\n",
2937 keyid, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY);
2938
2939 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
2940 sme_key.wepTxKey = TRUE;
2941 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE;
2942 } else {
2943 sme_key.wepTxKey = FALSE;
2944 sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP;
2945 }
2946 sme_key.keyIndex = (keyid - 1);
2947 sme_key.keyLength = ext->key_len;
2948 sme_key.authenticator = 0;
2949 memset(sme_key.address.a, 0xFF, ETH_ALEN);
2950 memcpy(sme_key.key, keydata, ext->key_len);
2951 UF_RTNL_UNLOCK();
2952 r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
2953 UF_RTNL_LOCK();
2954 if (r) {
2955 unifi_error(priv, "siwencodeext: Set key failed (%d)", r);
2956 return convert_sme_error(r);
2957 }
2958
2959 return 0;
2960 }
2961
2962 /*
2963 *
2964 * If we reach here, we are dealing with a WPA/WPA2 key
2965 *
2966 */
2967 if (ext->key_len > 32) {
2968 return -EINVAL;
2969 }
2970
2971 /*
2972 * TKIP keys from wpa_supplicant need swapping.
2973 * What about other supplicants (when they come along)?
2974 */
2975 if ((ext->alg == IW_ENCODE_ALG_TKIP) && (ext->key_len == 32)) {
2976 memcpy(tkip_key, keydata, 16);
2977 memcpy(tkip_key + 16, keydata + 24, 8);
2978 memcpy(tkip_key + 24, keydata + 16, 8);
2979 keydata = tkip_key;
2980 }
2981
2982 key_type = (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ?
2983 CSR_WIFI_SME_KEY_TYPE_GROUP : /* Group Key */
2984 CSR_WIFI_SME_KEY_TYPE_PAIRWISE; /* Pairwise Key */
2985
2986 sme_key.keyType = key_type;
2987 sme_key.keyIndex = (keyid - 1);
2988 sme_key.keyLength = ext->key_len;
2989 sme_key.authenticator = 0;
2990 memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN);
2991 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
2992
2993 unifi_trace(priv, UDBG5, "RSC first 6 bytes = %*phC\n",
2994 6, ext->rx_seq);
2995
2996 /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */
2997 sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0];
2998 sme_key.keyRsc[1] = ext->rx_seq[3] << 8 | ext->rx_seq[2];
2999 sme_key.keyRsc[2] = ext->rx_seq[5] << 8 | ext->rx_seq[4];
3000 sme_key.keyRsc[3] = ext->rx_seq[7] << 8 | ext->rx_seq[6];
3001
3002 }
3003
3004 memcpy(sme_key.key, keydata, ext->key_len);
3005 UF_RTNL_UNLOCK();
3006 r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD);
3007 UF_RTNL_LOCK();
3008 if (r) {
3009 unifi_error(priv, "SETKEYS request was rejected with result %d\n", r);
3010 return convert_sme_error(r);
3011 }
3012
3013 return r;
3014 } /* _unifi_siwencodeext() */
3015
3016
3017 static int
3018 unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
3019 union iwreq_data *wrqu, char *extra)
3020 {
3021 int err = 0;
3022
3023 err = _unifi_siwencodeext(dev, info, wrqu, extra);
3024
3025 return err;
3026 } /* unifi_siwencodeext() */
3027
3028
3029 static int
3030 unifi_giwencodeext(struct net_device *dev, struct iw_request_info *info,
3031 union iwreq_data *wrqu, char *extra)
3032 {
3033 return -EOPNOTSUPP;
3034 } /* unifi_giwencodeext() */
3035
3036
3037 /*
3038 * ---------------------------------------------------------------------------
3039 * unifi_siwpmksa
3040 *
3041 * SIOCSIWPMKSA - PMKSA cache operation
3042 * The caller passes a pmksa structure:
3043 * - cmd one of ADD, REMOVE, FLUSH
3044 * - bssid MAC address
3045 * - pmkid ID string (16 bytes)
3046 *
3047 * Arguments:
3048 * None.
3049 *
3050 * Returns:
3051 * None.
3052 *
3053 * Notes:
3054 * This is not needed since we provide a siwgenie method.
3055 * ---------------------------------------------------------------------------
3056 */
3057 #define UNIFI_PMKID_KEY_SIZE 16
3058 static int
3059 unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info,
3060 union iwreq_data *wrqu, char *extra)
3061 {
3062 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3063 unifi_priv_t *priv = interfacePriv->privPtr;
3064 struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
3065 CsrResult r = 0;
3066 CsrWifiSmePmkidList pmkid_list;
3067 CsrWifiSmePmkid pmkid;
3068 CsrWifiSmeListAction action;
3069
3070 CHECK_INITED(priv);
3071
3072 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
3073 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
3074 unifi_error(priv, "unifi_siwpmksa: not permitted in Mode %d\n",
3075 interfacePriv->interfaceMode);
3076 return -EPERM;
3077 }
3078
3079
3080 unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %pM\n", pmksa->cmd,
3081 pmksa->bssid.sa_data);
3082
3083 pmkid_list.pmkids = NULL;
3084 switch (pmksa->cmd) {
3085 case IW_PMKSA_ADD:
3086 pmkid_list.pmkids = &pmkid;
3087 action = CSR_WIFI_SME_LIST_ACTION_ADD;
3088 pmkid_list.pmkidsCount = 1;
3089 memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3090 memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3091 break;
3092 case IW_PMKSA_REMOVE:
3093 pmkid_list.pmkids = &pmkid;
3094 action = CSR_WIFI_SME_LIST_ACTION_REMOVE;
3095 pmkid_list.pmkidsCount = 1;
3096 memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN);
3097 memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE);
3098 break;
3099 case IW_PMKSA_FLUSH:
3100 /* Replace current PMKID's with an empty list */
3101 pmkid_list.pmkidsCount = 0;
3102 action = CSR_WIFI_SME_LIST_ACTION_FLUSH;
3103 break;
3104 default:
3105 unifi_notice(priv, "SIWPMKSA: Unknown command (0x%x)\n", pmksa->cmd);
3106 return -EINVAL;
3107 }
3108
3109 /* Set the Value the pmkid's will have 1 added OR 1 removed OR be cleared at this point */
3110 UF_RTNL_UNLOCK();
3111 r = sme_mgt_pmkid(priv, action, &pmkid_list);
3112 UF_RTNL_LOCK();
3113 if (r) {
3114 unifi_error(priv, "SIWPMKSA: Set PMKID's Failed.\n");
3115 }
3116
3117 return r;
3118
3119 } /* unifi_siwpmksa() */
3120
3121
3122 /*
3123 * ---------------------------------------------------------------------------
3124 * unifi_get_wireless_stats
3125 *
3126 * get_wireless_stats method for Linux wireless extensions.
3127 *
3128 * Arguments:
3129 * dev Pointer to associated netdevice.
3130 *
3131 * Returns:
3132 * Pointer to iw_statistics struct.
3133 * ---------------------------------------------------------------------------
3134 */
3135 struct iw_statistics *
3136 unifi_get_wireless_stats(struct net_device *dev)
3137 {
3138 netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
3139 unifi_priv_t *priv = interfacePriv->privPtr;
3140
3141 if (priv->init_progress != UNIFI_INIT_COMPLETED) {
3142 return NULL;
3143 }
3144
3145 return &priv->wext_wireless_stats;
3146 } /* unifi_get_wireless_stats() */
3147
3148
3149 /*
3150 * Structures to export the Wireless Handlers
3151 */
3152
3153 static const struct iw_priv_args unifi_private_args[] = {
3154 /*{ cmd, set_args, get_args, name } */
3155 { SIOCIWS80211POWERSAVEPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3156 IW_PRIV_TYPE_NONE, "iwprivs80211ps" },
3157 { SIOCIWG80211POWERSAVEPRIV, IW_PRIV_TYPE_NONE,
3158 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IWPRIV_POWER_SAVE_MAX_STRING, "iwprivg80211ps" },
3159 { SIOCIWS80211RELOADDEFAULTSPRIV, IW_PRIV_TYPE_NONE,
3160 IW_PRIV_TYPE_NONE, "iwprivsdefs" },
3161 { SIOCIWSSMEDEBUGPRIV, IW_PRIV_TYPE_CHAR | IWPRIV_SME_DEBUG_MAX_STRING, IW_PRIV_TYPE_NONE, "iwprivssmedebug" },
3162 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3163 { SIOCIWSCONFWAPIPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
3164 IW_PRIV_TYPE_NONE, "iwprivsconfwapi" },
3165 { SIOCIWSWAPIKEYPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(unifiio_wapi_key_t),
3166 IW_PRIV_TYPE_NONE, "iwprivswpikey" },
3167 #endif
3168 #ifdef CSR_SUPPORT_WEXT_AP
3169 { SIOCIWSAPCFGPRIV, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_NONE, "AP_SET_CFG" },
3170 { SIOCIWSAPSTARTPRIV, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "AP_BSS_START" },
3171 { SIOCIWSAPSTOPPRIV, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0,
3172 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "AP_BSS_STOP" },
3173 #ifdef ANDROID_BUILD
3174 { SIOCIWSFWRELOADPRIV, IW_PRIV_TYPE_CHAR |256,
3175 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "WL_FW_RELOAD" },
3176 { SIOCIWSSTACKSTART, 0,
3177 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "START" },
3178 { SIOCIWSSTACKSTOP, 0,
3179 IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "STOP" },
3180 #endif /* ANDROID_BUILD */
3181 #endif /* CSR_SUPPORT_WEXT_AP */
3182 };
3183
3184 static const iw_handler unifi_handler[] =
3185 {
3186 (iw_handler) unifi_siwcommit, /* SIOCSIWCOMMIT */
3187 (iw_handler) unifi_giwname, /* SIOCGIWNAME */
3188 (iw_handler) NULL, /* SIOCSIWNWID */
3189 (iw_handler) NULL, /* SIOCGIWNWID */
3190 (iw_handler) unifi_siwfreq, /* SIOCSIWFREQ */
3191 (iw_handler) unifi_giwfreq, /* SIOCGIWFREQ */
3192 (iw_handler) unifi_siwmode, /* SIOCSIWMODE */
3193 (iw_handler) unifi_giwmode, /* SIOCGIWMODE */
3194 (iw_handler) NULL, /* SIOCSIWSENS */
3195 (iw_handler) NULL, /* SIOCGIWSENS */
3196 (iw_handler) NULL, /* SIOCSIWRANGE */
3197 (iw_handler) unifi_giwrange, /* SIOCGIWRANGE */
3198 (iw_handler) NULL, /* SIOCSIWPRIV */
3199 (iw_handler) NULL, /* SIOCGIWPRIV */
3200 (iw_handler) NULL, /* SIOCSIWSTATS */
3201 (iw_handler) NULL, /* SIOCGIWSTATS */
3202 (iw_handler) NULL, /* SIOCSIWSPY */
3203 (iw_handler) NULL, /* SIOCGIWSPY */
3204 (iw_handler) NULL, /* SIOCSIWTHRSPY */
3205 (iw_handler) NULL, /* SIOCGIWTHRSPY */
3206 (iw_handler) unifi_siwap, /* SIOCSIWAP */
3207 (iw_handler) unifi_giwap, /* SIOCGIWAP */
3208 #if WIRELESS_EXT > 17
3209 /* WPA : IEEE 802.11 MLME requests */
3210 unifi_siwmlme, /* SIOCSIWMLME, request MLME operation */
3211 #else
3212 (iw_handler) NULL, /* -- hole -- */
3213 #endif
3214 (iw_handler) NULL, /* SIOCGIWAPLIST */
3215 (iw_handler) unifi_siwscan, /* SIOCSIWSCAN */
3216 (iw_handler) unifi_giwscan, /* SIOCGIWSCAN */
3217 (iw_handler) unifi_siwessid, /* SIOCSIWESSID */
3218 (iw_handler) unifi_giwessid, /* SIOCGIWESSID */
3219 (iw_handler) NULL, /* SIOCSIWNICKN */
3220 (iw_handler) NULL, /* SIOCGIWNICKN */
3221 (iw_handler) NULL, /* -- hole -- */
3222 (iw_handler) NULL, /* -- hole -- */
3223 unifi_siwrate, /* SIOCSIWRATE */
3224 unifi_giwrate, /* SIOCGIWRATE */
3225 unifi_siwrts, /* SIOCSIWRTS */
3226 unifi_giwrts, /* SIOCGIWRTS */
3227 unifi_siwfrag, /* SIOCSIWFRAG */
3228 unifi_giwfrag, /* SIOCGIWFRAG */
3229 (iw_handler) NULL, /* SIOCSIWTXPOW */
3230 (iw_handler) NULL, /* SIOCGIWTXPOW */
3231 (iw_handler) NULL, /* SIOCSIWRETRY */
3232 (iw_handler) NULL, /* SIOCGIWRETRY */
3233 unifi_siwencode, /* SIOCSIWENCODE */
3234 unifi_giwencode, /* SIOCGIWENCODE */
3235 unifi_siwpower, /* SIOCSIWPOWER */
3236 unifi_giwpower, /* SIOCGIWPOWER */
3237 #if WIRELESS_EXT > 17
3238 (iw_handler) NULL, /* -- hole -- */
3239 (iw_handler) NULL, /* -- hole -- */
3240
3241 /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). */
3242 unifi_siwgenie, /* SIOCSIWGENIE */ /* set generic IE */
3243 unifi_giwgenie, /* SIOCGIWGENIE */ /* get generic IE */
3244
3245 /* WPA : Authentication mode parameters */
3246 unifi_siwauth, /* SIOCSIWAUTH */ /* set authentication mode params */
3247 unifi_giwauth, /* SIOCGIWAUTH */ /* get authentication mode params */
3248
3249 /* WPA : Extended version of encoding configuration */
3250 unifi_siwencodeext, /* SIOCSIWENCODEEXT */ /* set encoding token & mode */
3251 unifi_giwencodeext, /* SIOCGIWENCODEEXT */ /* get encoding token & mode */
3252
3253 /* WPA2 : PMKSA cache management */
3254 unifi_siwpmksa, /* SIOCSIWPMKSA */ /* PMKSA cache operation */
3255 (iw_handler) NULL, /* -- hole -- */
3256 #endif /* WIRELESS_EXT > 17 */
3257 };
3258
3259
3260 static const iw_handler unifi_private_handler[] =
3261 {
3262 iwprivs80211ps, /* SIOCIWFIRSTPRIV */
3263 iwprivg80211ps, /* SIOCIWFIRSTPRIV + 1 */
3264 iwprivsdefs, /* SIOCIWFIRSTPRIV + 2 */
3265 (iw_handler) NULL,
3266 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
3267 iwprivsconfwapi, /* SIOCIWFIRSTPRIV + 4 */
3268 (iw_handler) NULL, /* SIOCIWFIRSTPRIV + 5 */
3269 iwprivswpikey, /* SIOCIWFIRSTPRIV + 6 */
3270 #else
3271 (iw_handler) NULL,
3272 (iw_handler) NULL,
3273 (iw_handler) NULL,
3274 #endif
3275 (iw_handler) NULL,
3276 iwprivssmedebug, /* SIOCIWFIRSTPRIV + 8 */
3277 #ifdef CSR_SUPPORT_WEXT_AP
3278 (iw_handler) NULL,
3279 iwprivsapconfig,
3280 (iw_handler) NULL,
3281 iwprivsapstart,
3282 (iw_handler) NULL,
3283 iwprivsapstop,
3284 (iw_handler) NULL,
3285 #ifdef ANDROID_BUILD
3286 iwprivsapfwreload,
3287 (iw_handler) NULL,
3288 iwprivsstackstart,
3289 (iw_handler) NULL,
3290 iwprivsstackstop,
3291 #else
3292 (iw_handler) NULL,
3293 (iw_handler) NULL,
3294 (iw_handler) NULL,
3295 (iw_handler) NULL,
3296 (iw_handler) NULL,
3297 #endif /* ANDROID_BUILD */
3298 #else
3299 (iw_handler) NULL,
3300 (iw_handler) NULL,
3301 (iw_handler) NULL,
3302 (iw_handler) NULL,
3303 (iw_handler) NULL,
3304 (iw_handler) NULL,
3305 (iw_handler) NULL,
3306 (iw_handler) NULL,
3307 (iw_handler) NULL,
3308 (iw_handler) NULL,
3309 (iw_handler) NULL,
3310 (iw_handler) NULL,
3311 #endif /* CSR_SUPPORT_WEXT_AP */
3312 };
3313
3314 struct iw_handler_def unifi_iw_handler_def =
3315 {
3316 .num_standard = sizeof(unifi_handler) / sizeof(iw_handler),
3317 .num_private = sizeof(unifi_private_handler) / sizeof(iw_handler),
3318 .num_private_args = sizeof(unifi_private_args) / sizeof(struct iw_priv_args),
3319 .standard = (iw_handler *) unifi_handler,
3320 .private = (iw_handler *) unifi_private_handler,
3321 .private_args = (struct iw_priv_args *) unifi_private_args,
3322 #if IW_HANDLER_VERSION >= 6
3323 .get_wireless_stats = unifi_get_wireless_stats,
3324 #endif
3325 };
3326
3327
This page took 0.114199 seconds and 5 git commands to generate.