OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * |
| 3 * Copyright (c) 2004-2010 Atheros Communications Inc. |
| 4 * All rights reserved. |
| 5 * |
| 6 * |
| 7 // This program is free software; you can redistribute it and/or modify |
| 8 // it under the terms of the GNU General Public License version 2 as |
| 9 // published by the Free Software Foundation; |
| 10 // |
| 11 // Software distributed under the License is distributed on an "AS |
| 12 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| 13 // implied. See the License for the specific language governing |
| 14 // rights and limitations under the License. |
| 15 // |
| 16 // |
| 17 * |
| 18 */ |
| 19 |
| 20 #include "ar6000_drv.h" |
| 21 |
| 22 static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi); |
| 23 extern unsigned int wmitimeout; |
| 24 extern A_WAITQUEUE_HEAD arEvent; |
| 25 |
| 26 #if WIRELESS_EXT > 14 |
| 27 /* |
| 28 * Encode a WPA or RSN information element as a custom |
| 29 * element using the hostap format. |
| 30 */ |
| 31 static u_int |
| 32 encode_ie(void *buf, size_t bufsize, |
| 33 const u_int8_t *ie, size_t ielen, |
| 34 const char *leader, size_t leader_len) |
| 35 { |
| 36 u_int8_t *p; |
| 37 int i; |
| 38 |
| 39 if (bufsize < leader_len) |
| 40 return 0; |
| 41 p = buf; |
| 42 memcpy(p, leader, leader_len); |
| 43 bufsize -= leader_len; |
| 44 p += leader_len; |
| 45 for (i = 0; i < ielen && bufsize > 2; i++) |
| 46 { |
| 47 p += sprintf(p, "%02x", ie[i]); |
| 48 bufsize -= 2; |
| 49 } |
| 50 return (i == ielen ? p - (u_int8_t *)buf : 0); |
| 51 } |
| 52 #endif /* WIRELESS_EXT > 14 */ |
| 53 |
| 54 void |
| 55 ar6000_scan_node(void *arg, bss_t *ni) |
| 56 { |
| 57 struct iw_event iwe; |
| 58 #if WIRELESS_EXT > 14 |
| 59 char buf[256]; |
| 60 #endif |
| 61 struct ar_giwscan_param *param; |
| 62 A_CHAR *current_ev; |
| 63 A_CHAR *end_buf; |
| 64 struct ieee80211_common_ie *cie; |
| 65 A_CHAR *current_val; |
| 66 A_INT32 j; |
| 67 A_UINT32 rate_len, data_len = 0; |
| 68 |
| 69 param = (struct ar_giwscan_param *)arg; |
| 70 |
| 71 current_ev = param->current_ev; |
| 72 end_buf = param->end_buf; |
| 73 |
| 74 cie = &ni->ni_cie; |
| 75 |
| 76 if ((end_buf - current_ev) > IW_EV_ADDR_LEN) |
| 77 { |
| 78 A_MEMZERO(&iwe, sizeof(iwe)); |
| 79 iwe.cmd = SIOCGIWAP; |
| 80 iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
| 81 A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6); |
| 82 current_ev = iwe_stream_add_event( |
| 83 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 84 param->info, |
| 85 #endif |
| 86 current_ev, end_buf, &iwe, |
| 87 IW_EV_ADDR_LEN); |
| 88 } |
| 89 param->bytes_needed += IW_EV_ADDR_LEN; |
| 90 |
| 91 data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN; |
| 92 if ((end_buf - current_ev) > data_len) |
| 93 { |
| 94 A_MEMZERO(&iwe, sizeof(iwe)); |
| 95 iwe.cmd = SIOCGIWESSID; |
| 96 iwe.u.data.flags = 1; |
| 97 iwe.u.data.length = cie->ie_ssid[1]; |
| 98 current_ev = iwe_stream_add_point( |
| 99 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 100 param->info, |
| 101 #endif |
| 102 current_ev, end_buf, &iwe, |
| 103 &cie->ie_ssid[2]); |
| 104 } |
| 105 param->bytes_needed += data_len; |
| 106 |
| 107 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) { |
| 108 if ((end_buf - current_ev) > IW_EV_UINT_LEN) |
| 109 { |
| 110 A_MEMZERO(&iwe, sizeof(iwe)); |
| 111 iwe.cmd = SIOCGIWMODE; |
| 112 iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ? |
| 113 IW_MODE_MASTER : IW_MODE_ADHOC; |
| 114 current_ev = iwe_stream_add_event( |
| 115 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 116 param->info, |
| 117 #endif |
| 118 current_ev, end_buf, &iwe, |
| 119 IW_EV_UINT_LEN); |
| 120 } |
| 121 param->bytes_needed += IW_EV_UINT_LEN; |
| 122 } |
| 123 |
| 124 if ((end_buf - current_ev) > IW_EV_FREQ_LEN) |
| 125 { |
| 126 A_MEMZERO(&iwe, sizeof(iwe)); |
| 127 iwe.cmd = SIOCGIWFREQ; |
| 128 iwe.u.freq.m = cie->ie_chan * 100000; |
| 129 iwe.u.freq.e = 1; |
| 130 current_ev = iwe_stream_add_event( |
| 131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 132 param->info, |
| 133 #endif |
| 134 current_ev, end_buf, &iwe, |
| 135 IW_EV_FREQ_LEN); |
| 136 } |
| 137 param->bytes_needed += IW_EV_FREQ_LEN; |
| 138 |
| 139 if ((end_buf - current_ev) > IW_EV_QUAL_LEN) |
| 140 { |
| 141 A_MEMZERO(&iwe, sizeof(iwe)); |
| 142 iwe.cmd = IWEVQUAL; |
| 143 ar6000_set_quality(&iwe.u.qual, ni->ni_snr); |
| 144 current_ev = iwe_stream_add_event( |
| 145 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 146 param->info, |
| 147 #endif |
| 148 current_ev, end_buf, &iwe, |
| 149 IW_EV_QUAL_LEN); |
| 150 } |
| 151 param->bytes_needed += IW_EV_QUAL_LEN; |
| 152 |
| 153 if ((end_buf - current_ev) > IW_EV_POINT_LEN) |
| 154 { |
| 155 A_MEMZERO(&iwe, sizeof(iwe)); |
| 156 iwe.cmd = SIOCGIWENCODE; |
| 157 if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) { |
| 158 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; |
| 159 } else { |
| 160 iwe.u.data.flags = IW_ENCODE_DISABLED; |
| 161 } |
| 162 iwe.u.data.length = 0; |
| 163 current_ev = iwe_stream_add_point( |
| 164 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 165 param->info, |
| 166 #endif |
| 167 current_ev, end_buf, &iwe, ""); |
| 168 } |
| 169 param->bytes_needed += IW_EV_POINT_LEN; |
| 170 |
| 171 /* supported bit rate */ |
| 172 A_MEMZERO(&iwe, sizeof(iwe)); |
| 173 iwe.cmd = SIOCGIWRATE; |
| 174 iwe.u.bitrate.fixed = 0; |
| 175 iwe.u.bitrate.disabled = 0; |
| 176 iwe.u.bitrate.value = 0; |
| 177 current_val = current_ev + IW_EV_LCP_LEN; |
| 178 param->bytes_needed += IW_EV_LCP_LEN; |
| 179 |
| 180 if (cie->ie_rates != NULL) { |
| 181 rate_len = cie->ie_rates[1]; |
| 182 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN)); |
| 183 if ((end_buf - current_ev) > data_len) |
| 184 { |
| 185 for (j = 0; j < rate_len; j++) { |
| 186 unsigned char val; |
| 187 val = cie->ie_rates[2 + j]; |
| 188 iwe.u.bitrate.value = |
| 189 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000); |
| 190 current_val = iwe_stream_add_value( |
| 191 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 192 param->info, |
| 193 #endif |
| 194 current_ev, |
| 195 current_val, |
| 196 end_buf, |
| 197 &iwe, |
| 198 IW_EV_PARAM_LEN); |
| 199 } |
| 200 } |
| 201 param->bytes_needed += data_len; |
| 202 } |
| 203 |
| 204 if (cie->ie_xrates != NULL) { |
| 205 rate_len = cie->ie_xrates[1]; |
| 206 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN)); |
| 207 if ((end_buf - current_ev) > data_len) |
| 208 { |
| 209 for (j = 0; j < rate_len; j++) { |
| 210 unsigned char val; |
| 211 val = cie->ie_xrates[2 + j]; |
| 212 iwe.u.bitrate.value = |
| 213 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000); |
| 214 current_val = iwe_stream_add_value( |
| 215 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 216 param->info, |
| 217 #endif |
| 218 current_ev, |
| 219 current_val, |
| 220 end_buf, |
| 221 &iwe, |
| 222 IW_EV_PARAM_LEN); |
| 223 } |
| 224 } |
| 225 param->bytes_needed += data_len; |
| 226 } |
| 227 /* remove fixed header if no rates were added */ |
| 228 if ((current_val - current_ev) > IW_EV_LCP_LEN) |
| 229 current_ev = current_val; |
| 230 |
| 231 #if WIRELESS_EXT >= 18 |
| 232 /* IE */ |
| 233 if (cie->ie_wpa != NULL) { |
| 234 data_len = cie->ie_wpa[1] + 2 + IW_EV_POINT_LEN; |
| 235 if ((end_buf - current_ev) > data_len) |
| 236 { |
| 237 A_MEMZERO(&iwe, sizeof(iwe)); |
| 238 iwe.cmd = IWEVGENIE; |
| 239 iwe.u.data.length = cie->ie_wpa[1] + 2; |
| 240 current_ev = iwe_stream_add_point( |
| 241 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 242 param->info, |
| 243 #endif |
| 244 current_ev, end_buf, &iwe, cie->ie_wpa); |
| 245 } |
| 246 param->bytes_needed += data_len; |
| 247 } |
| 248 |
| 249 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) { |
| 250 data_len = cie->ie_rsn[1] + 2 + IW_EV_POINT_LEN; |
| 251 if ((end_buf - current_ev) > data_len) |
| 252 { |
| 253 A_MEMZERO(&iwe, sizeof(iwe)); |
| 254 iwe.cmd = IWEVGENIE; |
| 255 iwe.u.data.length = cie->ie_rsn[1] + 2; |
| 256 current_ev = iwe_stream_add_point( |
| 257 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 258 param->info, |
| 259 #endif |
| 260 current_ev, end_buf, &iwe, cie->ie_rsn); |
| 261 } |
| 262 param->bytes_needed += data_len; |
| 263 } |
| 264 |
| 265 #endif /* WIRELESS_EXT >= 18 */ |
| 266 |
| 267 if ((end_buf - current_ev) > IW_EV_CHAR_LEN) |
| 268 { |
| 269 /* protocol */ |
| 270 A_MEMZERO(&iwe, sizeof(iwe)); |
| 271 iwe.cmd = SIOCGIWNAME; |
| 272 #define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484))) |
| 273 if (CHAN_IS_11A(cie->ie_chan)) { |
| 274 if (cie->ie_htcap) { |
| 275 /* 11na */ |
| 276 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11na"); |
| 277 } |
| 278 else { |
| 279 /* 11a */ |
| 280 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a"); |
| 281 } |
| 282 } else if ((cie->ie_erp) || (cie->ie_xrates)) { |
| 283 if (cie->ie_htcap) { |
| 284 /* 11ng */ |
| 285 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11ng"); |
| 286 } |
| 287 else { |
| 288 /* 11g */ |
| 289 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g"); |
| 290 } |
| 291 } else { |
| 292 /* 11b */ |
| 293 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b"); |
| 294 } |
| 295 current_ev = iwe_stream_add_event( |
| 296 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 297 param->info, |
| 298 #endif |
| 299 current_ev, end_buf, &iwe, IW_EV_CHAR_LEN); |
| 300 } |
| 301 param->bytes_needed += IW_EV_CHAR_LEN; |
| 302 |
| 303 #if WIRELESS_EXT > 14 |
| 304 A_MEMZERO(&iwe, sizeof(iwe)); |
| 305 iwe.cmd = IWEVCUSTOM; |
| 306 iwe.u.data.length = snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconI
nt); |
| 307 data_len = iwe.u.data.length + IW_EV_POINT_LEN; |
| 308 if ((end_buf - current_ev) > data_len) |
| 309 { |
| 310 current_ev = iwe_stream_add_point( |
| 311 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 312 param->info, |
| 313 #endif |
| 314 current_ev, end_buf, &iwe, buf); |
| 315 } |
| 316 param->bytes_needed += data_len; |
| 317 |
| 318 #if WIRELESS_EXT < 18 |
| 319 if (cie->ie_wpa != NULL) { |
| 320 static const char wpa_leader[] = "wpa_ie="; |
| 321 data_len = (sizeof(wpa_leader) - 1) + ((cie->ie_wpa[1]+2) * 2) + IW_EV_P
OINT_LEN; |
| 322 if ((end_buf - current_ev) > data_len) |
| 323 { |
| 324 A_MEMZERO(&iwe, sizeof(iwe)); |
| 325 iwe.cmd = IWEVCUSTOM; |
| 326 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa, |
| 327 cie->ie_wpa[1]+2, |
| 328 wpa_leader, sizeof(wpa_leader)-1); |
| 329 |
| 330 if (iwe.u.data.length != 0) { |
| 331 current_ev = iwe_stream_add_point( |
| 332 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 333 param->info, |
| 334 #endif |
| 335 current_ev, end_buf, &iwe, buf); |
| 336 } |
| 337 } |
| 338 param->bytes_needed += data_len; |
| 339 } |
| 340 |
| 341 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) { |
| 342 static const char rsn_leader[] = "rsn_ie="; |
| 343 data_len = (sizeof(rsn_leader) - 1) + ((cie->ie_rsn[1]+2) * 2) + IW_EV_P
OINT_LEN; |
| 344 if ((end_buf - current_ev) > data_len) |
| 345 { |
| 346 A_MEMZERO(&iwe, sizeof(iwe)); |
| 347 iwe.cmd = IWEVCUSTOM; |
| 348 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn, |
| 349 cie->ie_rsn[1]+2, |
| 350 rsn_leader, sizeof(rsn_leader)-1); |
| 351 |
| 352 if (iwe.u.data.length != 0) { |
| 353 current_ev = iwe_stream_add_point( |
| 354 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 355 param->info, |
| 356 #endif |
| 357 current_ev, end_buf, &iwe, buf); |
| 358 } |
| 359 } |
| 360 param->bytes_needed += data_len; |
| 361 } |
| 362 #endif /* WIRELESS_EXT < 18 */ |
| 363 |
| 364 if (cie->ie_wmm != NULL) { |
| 365 static const char wmm_leader[] = "wmm_ie="; |
| 366 data_len = (sizeof(wmm_leader) - 1) + ((cie->ie_wmm[1]+2) * 2) + IW_EV_P
OINT_LEN; |
| 367 if ((end_buf - current_ev) > data_len) |
| 368 { |
| 369 A_MEMZERO(&iwe, sizeof(iwe)); |
| 370 iwe.cmd = IWEVCUSTOM; |
| 371 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm, |
| 372 cie->ie_wmm[1]+2, |
| 373 wmm_leader, sizeof(wmm_leader)-1); |
| 374 if (iwe.u.data.length != 0) { |
| 375 current_ev = iwe_stream_add_point( |
| 376 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 377 param->info, |
| 378 #endif |
| 379 current_ev, end_buf, &iwe, buf); |
| 380 } |
| 381 } |
| 382 param->bytes_needed += data_len; |
| 383 } |
| 384 |
| 385 if (cie->ie_ath != NULL) { |
| 386 static const char ath_leader[] = "ath_ie="; |
| 387 data_len = (sizeof(ath_leader) - 1) + ((cie->ie_ath[1]+2) * 2) + IW_EV_P
OINT_LEN; |
| 388 if ((end_buf - current_ev) > data_len) |
| 389 { |
| 390 A_MEMZERO(&iwe, sizeof(iwe)); |
| 391 iwe.cmd = IWEVCUSTOM; |
| 392 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath, |
| 393 cie->ie_ath[1]+2, |
| 394 ath_leader, sizeof(ath_leader)-1); |
| 395 if (iwe.u.data.length != 0) { |
| 396 current_ev = iwe_stream_add_point( |
| 397 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 398 param->info, |
| 399 #endif |
| 400 current_ev, end_buf, &iwe, buf); |
| 401 } |
| 402 } |
| 403 param->bytes_needed += data_len; |
| 404 } |
| 405 |
| 406 #ifdef WAPI_ENABLE |
| 407 if (cie->ie_wapi != NULL) { |
| 408 static const char wapi_leader[] = "wapi_ie="; |
| 409 data_len = (sizeof(wapi_leader) - 1) + ((cie->ie_wapi[1] + 2) * 2) + IW_
EV_POINT_LEN; |
| 410 if ((end_buf - current_ev) > data_len) { |
| 411 A_MEMZERO(&iwe, sizeof(iwe)); |
| 412 iwe.cmd = IWEVCUSTOM; |
| 413 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wapi, |
| 414 cie->ie_wapi[1] + 2, |
| 415 wapi_leader, sizeof(wapi_leader) - 1); |
| 416 if (iwe.u.data.length != 0) { |
| 417 current_ev = iwe_stream_add_point( |
| 418 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 419 param->info, |
| 420 #endif |
| 421 current_ev, end_buf, &iwe, buf); |
| 422 } |
| 423 } |
| 424 param->bytes_needed += data_len; |
| 425 } |
| 426 #endif /* WAPI_ENABLE */ |
| 427 |
| 428 #endif /* WIRELESS_EXT > 14 */ |
| 429 |
| 430 #if WIRELESS_EXT >= 18 |
| 431 if (cie->ie_wsc != NULL) { |
| 432 data_len = (cie->ie_wsc[1] + 2) + IW_EV_POINT_LEN; |
| 433 if ((end_buf - current_ev) > data_len) |
| 434 { |
| 435 A_MEMZERO(&iwe, sizeof(iwe)); |
| 436 iwe.cmd = IWEVGENIE; |
| 437 iwe.u.data.length = cie->ie_wsc[1] + 2; |
| 438 current_ev = iwe_stream_add_point( |
| 439 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 440 param->info, |
| 441 #endif |
| 442 current_ev, end_buf, &iwe, cie->ie_wsc); |
| 443 } |
| 444 param->bytes_needed += data_len; |
| 445 } |
| 446 #endif /* WIRELESS_EXT >= 18 */ |
| 447 |
| 448 param->current_ev = current_ev; |
| 449 } |
| 450 |
| 451 int |
| 452 ar6000_ioctl_giwscan(struct net_device *dev, |
| 453 struct iw_request_info *info, |
| 454 struct iw_point *data, char *extra) |
| 455 { |
| 456 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 457 struct ar_giwscan_param param; |
| 458 |
| 459 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 460 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 461 return -EOPNOTSUPP; |
| 462 } |
| 463 |
| 464 if (ar->arWlanState == WLAN_DISABLED) { |
| 465 return -EIO; |
| 466 } |
| 467 |
| 468 if (ar->arWmiReady == FALSE) { |
| 469 return -EIO; |
| 470 } |
| 471 |
| 472 param.current_ev = extra; |
| 473 param.end_buf = extra + data->length; |
| 474 param.bytes_needed = 0; |
| 475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) |
| 476 param.info = info; |
| 477 #endif |
| 478 |
| 479 /* Translate data to WE format */ |
| 480 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, ¶m); |
| 481 |
| 482 /* check if bytes needed is greater than bytes consumed */ |
| 483 if (param.bytes_needed > (param.current_ev - extra)) |
| 484 { |
| 485 /* Request one byte more than needed, because when "data->length" equals
bytes_needed, |
| 486 it is not possible to add the last event data as all iwe_stream_add_xxxx
x() functions |
| 487 checks whether (cur_ptr + ev_len) < end_ptr, due to this one more retry
would happen*/ |
| 488 data->length = param.bytes_needed + 1; |
| 489 |
| 490 return -E2BIG; |
| 491 } |
| 492 |
| 493 return 0; |
| 494 } |
| 495 |
| 496 extern int reconnect_flag; |
| 497 /* SIOCSIWESSID */ |
| 498 static int |
| 499 ar6000_ioctl_siwessid(struct net_device *dev, |
| 500 struct iw_request_info *info, |
| 501 struct iw_point *data, char *ssid) |
| 502 { |
| 503 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 504 A_STATUS status; |
| 505 A_UINT8 arNetworkType; |
| 506 A_UINT8 prevMode = ar->arNetworkType; |
| 507 |
| 508 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 509 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 510 return -EOPNOTSUPP; |
| 511 } |
| 512 |
| 513 if (ar->bIsDestroyProgress) { |
| 514 return -EBUSY; |
| 515 } |
| 516 |
| 517 if (ar->arWlanState == WLAN_DISABLED) { |
| 518 return -EIO; |
| 519 } |
| 520 |
| 521 if (ar->arWmiReady == FALSE) { |
| 522 return -EIO; |
| 523 } |
| 524 |
| 525 #if defined(WIRELESS_EXT) |
| 526 if (WIRELESS_EXT >= 20) { |
| 527 data->length += 1; |
| 528 } |
| 529 #endif |
| 530 |
| 531 /* |
| 532 * iwconfig passes a null terminated string with length including this |
| 533 * so we need to account for this |
| 534 */ |
| 535 if (data->flags && (!data->length || (data->length == 1) || |
| 536 ((data->length - 1) > sizeof(ar->arSsid)))) |
| 537 { |
| 538 /* |
| 539 * ssid is invalid |
| 540 */ |
| 541 return -EINVAL; |
| 542 } |
| 543 |
| 544 if (ar->arNextMode == AP_NETWORK) { |
| 545 /* SSID change for AP network - Will take effect on commit */ |
| 546 if(A_MEMCMP(ar->arSsid,ssid,32) != 0) { |
| 547 ar->arSsidLen = data->length - 1; |
| 548 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen); |
| 549 ar->ap_profile_flag = 1; /* There is a change in profile */ |
| 550 } |
| 551 return 0; |
| 552 } else if(ar->arNetworkType == AP_NETWORK) { |
| 553 A_UINT8 ctr; |
| 554 struct sk_buff *skb; |
| 555 |
| 556 /* We are switching from AP to STA | IBSS mode, cleanup the AP state */ |
| 557 for (ctr=0; ctr < AP_MAX_NUM_STA; ctr++) { |
| 558 remove_sta(ar, ar->sta_list[ctr].mac, 0); |
| 559 } |
| 560 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 561 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { |
| 562 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); |
| 563 A_NETBUF_FREE(skb); |
| 564 } |
| 565 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 566 } |
| 567 |
| 568 /* Added for bug 25178, return an IOCTL error instead of target returning |
| 569 Illegal parameter error when either the BSSID or channel is missing |
| 570 and we cannot scan during connect. |
| 571 */ |
| 572 if (data->flags) { |
| 573 if (ar->arSkipScan == TRUE && |
| 574 (ar->arChannelHint == 0 || |
| 575 (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] && |
| 576 !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5]))) |
| 577 { |
| 578 return -EINVAL; |
| 579 } |
| 580 } |
| 581 |
| 582 if (down_interruptible(&ar->arSem)) { |
| 583 return -ERESTARTSYS; |
| 584 } |
| 585 |
| 586 if (ar->bIsDestroyProgress) { |
| 587 up(&ar->arSem); |
| 588 return -EBUSY; |
| 589 } |
| 590 |
| 591 if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) { |
| 592 /* |
| 593 * sleep until the command queue drains |
| 594 */ |
| 595 wait_event_interruptible_timeout(arEvent, |
| 596 ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ
); |
| 597 if (signal_pending(current)) { |
| 598 return -EINTR; |
| 599 } |
| 600 } |
| 601 |
| 602 if (!data->flags) { |
| 603 arNetworkType = ar->arNetworkType; |
| 604 ar6000_init_profile_info(ar); |
| 605 ar->arNetworkType = arNetworkType; |
| 606 } |
| 607 |
| 608 /* Update the arNetworkType */ |
| 609 ar->arNetworkType = ar->arNextMode; |
| 610 |
| 611 |
| 612 if ((prevMode != AP_NETWORK) && ((ar->arSsidLen) || (!data->flags))) |
| 613 { |
| 614 if ((!data->flags) || |
| 615 (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) || |
| 616 (ar->arSsidLen != (data->length - 1))) |
| 617 { |
| 618 /* |
| 619 * SSID set previously or essid off has been issued. |
| 620 * |
| 621 * Disconnect Command is issued in two cases after wmi is ready |
| 622 * (1) ssid is different from the previous setting |
| 623 * (2) essid off has been issued |
| 624 * |
| 625 */ |
| 626 if (ar->arWmiReady == TRUE) { |
| 627 reconnect_flag = 0; |
| 628 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0); |
| 629 status = wmi_disconnect_cmd(ar->arWmi); |
| 630 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 631 ar->arSsidLen = 0; |
| 632 if (ar->arSkipScan == FALSE) { |
| 633 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); |
| 634 } |
| 635 if (!data->flags) { |
| 636 up(&ar->arSem); |
| 637 return 0; |
| 638 } |
| 639 } else { |
| 640 up(&ar->arSem); |
| 641 } |
| 642 } |
| 643 else |
| 644 { |
| 645 /* |
| 646 * SSID is same, so we assume profile hasn't changed. |
| 647 * If the interface is up and wmi is ready, we issue |
| 648 * a reconnect cmd. Issue a reconnect only we are already |
| 649 * connected. |
| 650 */ |
| 651 if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE)) |
| 652 { |
| 653 reconnect_flag = TRUE; |
| 654 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid, |
| 655 ar->arChannelHint); |
| 656 up(&ar->arSem); |
| 657 if (status != A_OK) { |
| 658 return -EIO; |
| 659 } |
| 660 return 0; |
| 661 } |
| 662 else{ |
| 663 /* |
| 664 * Dont return if connect is pending. |
| 665 */ |
| 666 if(!(ar->arConnectPending)) { |
| 667 up(&ar->arSem); |
| 668 return 0; |
| 669 } |
| 670 } |
| 671 } |
| 672 } |
| 673 |
| 674 ar->arSsidLen = data->length - 1; |
| 675 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen); |
| 676 |
| 677 /* The ssid length check prevents second "essid off" from the user, |
| 678 to be treated as a connect cmd. The second "essid off" is ignored. |
| 679 */ |
| 680 if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) ) |
| 681 { |
| 682 if((ADHOC_NETWORK != ar->arNetworkType) && |
| 683 (NONE_AUTH==ar->arAuthMode) && |
| 684 (WEP_CRYPT==ar->arPairwiseCrypto)) { |
| 685 ar6000_install_static_wep_keys(ar); |
| 686 } |
| 687 |
| 688 if (!ar->arUserBssFilter) { |
| 689 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) { |
| 690 up(&ar->arSem); |
| 691 return -EIO; |
| 692 } |
| 693 } |
| 694 #ifdef WAPI_ENABLE |
| 695 if (ar->arWapiEnable) { |
| 696 ar->arPairwiseCrypto = WAPI_CRYPT; |
| 697 ar->arPairwiseCryptoLen = 0; |
| 698 ar->arGroupCrypto = WAPI_CRYPT; |
| 699 ar->arGroupCryptoLen = 0; |
| 700 ar->arAuthMode = NONE_AUTH; |
| 701 ar->arConnectCtrlFlags |= CONNECT_IGNORE_WPAx_GROUP_CIPHER; |
| 702 } |
| 703 #endif |
| 704 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Connect called with authmode %d
dot11 auth %d"\ |
| 705 " PW crypto %d PW crypto Len %d GRP crypto %d"\ |
| 706 " GRP crypto Len %d\n", |
| 707 ar->arAuthMode, ar->arDot11AuthMode, |
| 708 ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, |
| 709 ar->arGroupCrypto, ar->arGroupCryptoLen)); |
| 710 reconnect_flag = 0; |
| 711 status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, |
| 712 ar->arDot11AuthMode, ar->arAuthMode, |
| 713 ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, |
| 714 ar->arGroupCrypto,ar->arGroupCryptoLen, |
| 715 ar->arSsidLen, ar->arSsid, |
| 716 ar->arReqBssid, ar->arChannelHint, |
| 717 ar->arConnectCtrlFlags); |
| 718 |
| 719 if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && |
| 720 ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMod
e))) |
| 721 { |
| 722 A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); |
| 723 } |
| 724 |
| 725 ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; |
| 726 up(&ar->arSem); |
| 727 |
| 728 if (status != A_OK) { |
| 729 return -EIO; |
| 730 } |
| 731 ar->arConnectPending = TRUE; |
| 732 }else{ |
| 733 up(&ar->arSem); |
| 734 } |
| 735 return 0; |
| 736 } |
| 737 |
| 738 /* SIOCGIWESSID */ |
| 739 static int |
| 740 ar6000_ioctl_giwessid(struct net_device *dev, |
| 741 struct iw_request_info *info, |
| 742 struct iw_point *data, char *essid) |
| 743 { |
| 744 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 745 |
| 746 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 747 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 748 return -EOPNOTSUPP; |
| 749 } |
| 750 |
| 751 if (ar->arWlanState == WLAN_DISABLED) { |
| 752 return -EIO; |
| 753 } |
| 754 |
| 755 if (!ar->arSsidLen) { |
| 756 return -EINVAL; |
| 757 } |
| 758 |
| 759 data->flags = 1; |
| 760 data->length = ar->arSsidLen; |
| 761 A_MEMCPY(essid, ar->arSsid, ar->arSsidLen); |
| 762 |
| 763 return 0; |
| 764 } |
| 765 |
| 766 |
| 767 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar) |
| 768 { |
| 769 A_UINT8 index; |
| 770 A_UINT8 keyUsage; |
| 771 |
| 772 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { |
| 773 if (ar->arWepKeyList[index].arKeyLen) { |
| 774 keyUsage = GROUP_USAGE; |
| 775 if (index == ar->arDefTxKeyIndex) { |
| 776 keyUsage |= TX_USAGE; |
| 777 } |
| 778 wmi_addKey_cmd(ar->arWmi, |
| 779 index, |
| 780 WEP_CRYPT, |
| 781 keyUsage, |
| 782 ar->arWepKeyList[index].arKeyLen, |
| 783 NULL, |
| 784 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL, |
| 785 NO_SYNC_WMIFLAG); |
| 786 } |
| 787 } |
| 788 } |
| 789 |
| 790 /* |
| 791 * SIOCSIWRATE |
| 792 */ |
| 793 int |
| 794 ar6000_ioctl_siwrate(struct net_device *dev, |
| 795 struct iw_request_info *info, |
| 796 struct iw_param *rrq, char *extra) |
| 797 { |
| 798 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 799 A_UINT32 kbps; |
| 800 |
| 801 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 802 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 803 return -EOPNOTSUPP; |
| 804 } |
| 805 |
| 806 if (rrq->fixed) { |
| 807 kbps = rrq->value / 1000; /* rrq->value is in bps */ |
| 808 } else { |
| 809 kbps = -1; /* -1 indicates auto rate */ |
| 810 } |
| 811 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL) |
| 812 { |
| 813 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps)); |
| 814 return -EINVAL; |
| 815 } |
| 816 ar->arBitRate = kbps; |
| 817 if(ar->arWmiReady == TRUE) |
| 818 { |
| 819 if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) { |
| 820 return -EINVAL; |
| 821 } |
| 822 } |
| 823 return 0; |
| 824 } |
| 825 |
| 826 /* |
| 827 * SIOCGIWRATE |
| 828 */ |
| 829 int |
| 830 ar6000_ioctl_giwrate(struct net_device *dev, |
| 831 struct iw_request_info *info, |
| 832 struct iw_param *rrq, char *extra) |
| 833 { |
| 834 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 835 int ret = 0; |
| 836 |
| 837 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 838 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 839 return -EOPNOTSUPP; |
| 840 } |
| 841 |
| 842 if (ar->bIsDestroyProgress) { |
| 843 return -EBUSY; |
| 844 } |
| 845 |
| 846 if (down_interruptible(&ar->arSem)) { |
| 847 return -ERESTARTSYS; |
| 848 } |
| 849 |
| 850 if (ar->bIsDestroyProgress) { |
| 851 up(&ar->arSem); |
| 852 return -EBUSY; |
| 853 } |
| 854 |
| 855 if(ar->arWmiReady == TRUE) |
| 856 { |
| 857 ar->arBitRate = 0xFFFF; |
| 858 if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) { |
| 859 up(&ar->arSem); |
| 860 return -EIO; |
| 861 } |
| 862 wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmiti
meout * HZ); |
| 863 if (signal_pending(current)) { |
| 864 ret = -EINTR; |
| 865 } |
| 866 } |
| 867 /* If the interface is down or wmi is not ready or the target is not |
| 868 connected - return the value stored in the device structure */ |
| 869 if (!ret) { |
| 870 if (ar->arBitRate == -1) { |
| 871 rrq->fixed = TRUE; |
| 872 rrq->value = 0; |
| 873 } else { |
| 874 rrq->value = ar->arBitRate * 1000; |
| 875 } |
| 876 } |
| 877 |
| 878 up(&ar->arSem); |
| 879 |
| 880 return ret; |
| 881 } |
| 882 |
| 883 /* |
| 884 * SIOCSIWTXPOW |
| 885 */ |
| 886 static int |
| 887 ar6000_ioctl_siwtxpow(struct net_device *dev, |
| 888 struct iw_request_info *info, |
| 889 struct iw_param *rrq, char *extra) |
| 890 { |
| 891 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 892 A_UINT8 dbM; |
| 893 |
| 894 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 895 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 896 return -EOPNOTSUPP; |
| 897 } |
| 898 |
| 899 if (ar->arWlanState == WLAN_DISABLED) { |
| 900 return -EIO; |
| 901 } |
| 902 |
| 903 if (rrq->disabled) { |
| 904 return -EOPNOTSUPP; |
| 905 } |
| 906 |
| 907 if (rrq->fixed) { |
| 908 if (rrq->flags != IW_TXPOW_DBM) { |
| 909 return -EOPNOTSUPP; |
| 910 } |
| 911 ar->arTxPwr= dbM = rrq->value; |
| 912 ar->arTxPwrSet = TRUE; |
| 913 } else { |
| 914 ar->arTxPwr = dbM = 0; |
| 915 ar->arTxPwrSet = FALSE; |
| 916 } |
| 917 if(ar->arWmiReady == TRUE) |
| 918 { |
| 919 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM)); |
| 920 wmi_set_txPwr_cmd(ar->arWmi, dbM); |
| 921 } |
| 922 return 0; |
| 923 } |
| 924 |
| 925 /* |
| 926 * SIOCGIWTXPOW |
| 927 */ |
| 928 int |
| 929 ar6000_ioctl_giwtxpow(struct net_device *dev, |
| 930 struct iw_request_info *info, |
| 931 struct iw_param *rrq, char *extra) |
| 932 { |
| 933 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 934 int ret = 0; |
| 935 |
| 936 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 937 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 938 return -EOPNOTSUPP; |
| 939 } |
| 940 |
| 941 if (ar->bIsDestroyProgress) { |
| 942 return -EBUSY; |
| 943 } |
| 944 |
| 945 if (ar->arWlanState == WLAN_DISABLED) { |
| 946 return -EIO; |
| 947 } |
| 948 |
| 949 if (down_interruptible(&ar->arSem)) { |
| 950 return -ERESTARTSYS; |
| 951 } |
| 952 |
| 953 if (ar->bIsDestroyProgress) { |
| 954 up(&ar->arSem); |
| 955 return -EBUSY; |
| 956 } |
| 957 |
| 958 if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE)) |
| 959 { |
| 960 ar->arTxPwr = 0; |
| 961 |
| 962 if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) { |
| 963 up(&ar->arSem); |
| 964 return -EIO; |
| 965 } |
| 966 |
| 967 wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout *
HZ); |
| 968 |
| 969 if (signal_pending(current)) { |
| 970 ret = -EINTR; |
| 971 } |
| 972 } |
| 973 /* If the interace is down or wmi is not ready or target is not connected |
| 974 then return value stored in the device structure */ |
| 975 |
| 976 if (!ret) { |
| 977 if (ar->arTxPwrSet == TRUE) { |
| 978 rrq->fixed = TRUE; |
| 979 } |
| 980 rrq->value = ar->arTxPwr; |
| 981 rrq->flags = IW_TXPOW_DBM; |
| 982 // |
| 983 // IWLIST need this flag to get TxPower |
| 984 // |
| 985 rrq->disabled = 0; |
| 986 } |
| 987 |
| 988 up(&ar->arSem); |
| 989 |
| 990 return ret; |
| 991 } |
| 992 |
| 993 /* |
| 994 * SIOCSIWRETRY |
| 995 * since iwconfig only provides us with one max retry value, we use it |
| 996 * to apply to data frames of the BE traffic class. |
| 997 */ |
| 998 static int |
| 999 ar6000_ioctl_siwretry(struct net_device *dev, |
| 1000 struct iw_request_info *info, |
| 1001 struct iw_param *rrq, char *extra) |
| 1002 { |
| 1003 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1004 |
| 1005 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 1006 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 1007 return -EOPNOTSUPP; |
| 1008 } |
| 1009 |
| 1010 if (ar->arWlanState == WLAN_DISABLED) { |
| 1011 return -EIO; |
| 1012 } |
| 1013 |
| 1014 if (rrq->disabled) { |
| 1015 return -EOPNOTSUPP; |
| 1016 } |
| 1017 |
| 1018 if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) { |
| 1019 return -EOPNOTSUPP; |
| 1020 } |
| 1021 |
| 1022 if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) { |
| 1023 return - EINVAL; |
| 1024 } |
| 1025 if(ar->arWmiReady == TRUE) |
| 1026 { |
| 1027 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE, |
| 1028 rrq->value, 0) != A_OK){ |
| 1029 return -EINVAL; |
| 1030 } |
| 1031 } |
| 1032 ar->arMaxRetries = rrq->value; |
| 1033 return 0; |
| 1034 } |
| 1035 |
| 1036 /* |
| 1037 * SIOCGIWRETRY |
| 1038 */ |
| 1039 static int |
| 1040 ar6000_ioctl_giwretry(struct net_device *dev, |
| 1041 struct iw_request_info *info, |
| 1042 struct iw_param *rrq, char *extra) |
| 1043 { |
| 1044 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1045 |
| 1046 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 1047 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 1048 return -EOPNOTSUPP; |
| 1049 } |
| 1050 |
| 1051 if (ar->arWlanState == WLAN_DISABLED) { |
| 1052 return -EIO; |
| 1053 } |
| 1054 |
| 1055 rrq->disabled = 0; |
| 1056 switch (rrq->flags & IW_RETRY_TYPE) { |
| 1057 case IW_RETRY_LIFETIME: |
| 1058 return -EOPNOTSUPP; |
| 1059 break; |
| 1060 case IW_RETRY_LIMIT: |
| 1061 rrq->flags = IW_RETRY_LIMIT; |
| 1062 switch (rrq->flags & IW_RETRY_MODIFIER) { |
| 1063 case IW_RETRY_MIN: |
| 1064 rrq->flags |= IW_RETRY_MIN; |
| 1065 rrq->value = WMI_MIN_RETRIES; |
| 1066 break; |
| 1067 case IW_RETRY_MAX: |
| 1068 rrq->flags |= IW_RETRY_MAX; |
| 1069 rrq->value = ar->arMaxRetries; |
| 1070 break; |
| 1071 } |
| 1072 break; |
| 1073 } |
| 1074 return 0; |
| 1075 } |
| 1076 |
| 1077 /* |
| 1078 * SIOCSIWENCODE |
| 1079 */ |
| 1080 static int |
| 1081 ar6000_ioctl_siwencode(struct net_device *dev, |
| 1082 struct iw_request_info *info, |
| 1083 struct iw_point *erq, char *keybuf) |
| 1084 { |
| 1085 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1086 int index; |
| 1087 A_INT32 auth = 0; |
| 1088 |
| 1089 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 1090 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 1091 return -EOPNOTSUPP; |
| 1092 } |
| 1093 |
| 1094 if(ar->arNextMode != AP_NETWORK) { |
| 1095 /* |
| 1096 * Static WEP Keys should be configured before setting the SSID |
| 1097 */ |
| 1098 if (ar->arSsid[0] && erq->length) { |
| 1099 return -EIO; |
| 1100 } |
| 1101 } |
| 1102 |
| 1103 if (ar->arWlanState == WLAN_DISABLED) { |
| 1104 return -EIO; |
| 1105 } |
| 1106 |
| 1107 index = erq->flags & IW_ENCODE_INDEX; |
| 1108 |
| 1109 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) || |
| 1110 ((index - 1) > WMI_MAX_KEY_INDEX))) |
| 1111 { |
| 1112 return -EIO; |
| 1113 } |
| 1114 |
| 1115 if (erq->flags & IW_ENCODE_DISABLED) { |
| 1116 /* |
| 1117 * Encryption disabled |
| 1118 */ |
| 1119 if (index) { |
| 1120 /* |
| 1121 * If key index was specified then clear the specified key |
| 1122 */ |
| 1123 index--; |
| 1124 A_MEMZERO(ar->arWepKeyList[index].arKey, |
| 1125 sizeof(ar->arWepKeyList[index].arKey)); |
| 1126 ar->arWepKeyList[index].arKeyLen = 0; |
| 1127 } |
| 1128 ar->arDot11AuthMode = OPEN_AUTH; |
| 1129 ar->arPairwiseCrypto = NONE_CRYPT; |
| 1130 ar->arGroupCrypto = NONE_CRYPT; |
| 1131 ar->arAuthMode = NONE_AUTH; |
| 1132 } else { |
| 1133 /* |
| 1134 * Enabling WEP encryption |
| 1135 */ |
| 1136 if (index) { |
| 1137 index--; /* keyindex is off base 1 in iwconfig */ |
| 1138 } |
| 1139 |
| 1140 if (erq->flags & IW_ENCODE_OPEN) { |
| 1141 auth |= OPEN_AUTH; |
| 1142 ar->arDefTxKeyIndex = index; |
| 1143 } |
| 1144 if (erq->flags & IW_ENCODE_RESTRICTED) { |
| 1145 auth |= SHARED_AUTH; |
| 1146 } |
| 1147 |
| 1148 if (!auth) { |
| 1149 auth = OPEN_AUTH; |
| 1150 } |
| 1151 |
| 1152 if (erq->length) { |
| 1153 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) { |
| 1154 return -EIO; |
| 1155 } |
| 1156 |
| 1157 A_MEMZERO(ar->arWepKeyList[index].arKey, |
| 1158 sizeof(ar->arWepKeyList[index].arKey)); |
| 1159 A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length); |
| 1160 ar->arWepKeyList[index].arKeyLen = erq->length; |
| 1161 ar->arDot11AuthMode = auth; |
| 1162 } else { |
| 1163 if (ar->arWepKeyList[index].arKeyLen == 0) { |
| 1164 return -EIO; |
| 1165 } |
| 1166 ar->arDefTxKeyIndex = index; |
| 1167 |
| 1168 if(ar->arSsidLen && ar->arWepKeyList[index].arKeyLen) { |
| 1169 wmi_addKey_cmd(ar->arWmi, |
| 1170 index, |
| 1171 WEP_CRYPT, |
| 1172 GROUP_USAGE | TX_USAGE, |
| 1173 ar->arWepKeyList[index].arKeyLen, |
| 1174 NULL, |
| 1175 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, N
ULL, |
| 1176 NO_SYNC_WMIFLAG); |
| 1177 } |
| 1178 } |
| 1179 |
| 1180 ar->arPairwiseCrypto = WEP_CRYPT; |
| 1181 ar->arGroupCrypto = WEP_CRYPT; |
| 1182 ar->arAuthMode = NONE_AUTH; |
| 1183 } |
| 1184 |
| 1185 if(ar->arNextMode != AP_NETWORK) { |
| 1186 /* |
| 1187 * profile has changed. Erase ssid to signal change |
| 1188 */ |
| 1189 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 1190 ar->arSsidLen = 0; |
| 1191 } |
| 1192 ar->ap_profile_flag = 1; /* There is a change in profile */ |
| 1193 return 0; |
| 1194 } |
| 1195 |
| 1196 static int |
| 1197 ar6000_ioctl_giwencode(struct net_device *dev, |
| 1198 struct iw_request_info *info, |
| 1199 struct iw_point *erq, char *key) |
| 1200 { |
| 1201 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1202 A_UINT8 keyIndex; |
| 1203 struct ar_wep_key *wk; |
| 1204 |
| 1205 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 1206 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 1207 return -EOPNOTSUPP; |
| 1208 } |
| 1209 |
| 1210 if (ar->arWlanState == WLAN_DISABLED) { |
| 1211 return -EIO; |
| 1212 } |
| 1213 |
| 1214 if (ar->arPairwiseCrypto == NONE_CRYPT) { |
| 1215 erq->length = 0; |
| 1216 erq->flags = IW_ENCODE_DISABLED; |
| 1217 } else { |
| 1218 if (ar->arPairwiseCrypto == WEP_CRYPT) { |
| 1219 /* get the keyIndex */ |
| 1220 keyIndex = erq->flags & IW_ENCODE_INDEX; |
| 1221 if (0 == keyIndex) { |
| 1222 keyIndex = ar->arDefTxKeyIndex; |
| 1223 } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) || |
| 1224 (keyIndex - 1 > WMI_MAX_KEY_INDEX)) |
| 1225 { |
| 1226 keyIndex = WMI_MIN_KEY_INDEX; |
| 1227 } else { |
| 1228 keyIndex--; |
| 1229 } |
| 1230 erq->flags = keyIndex + 1; |
| 1231 erq->flags &= ~IW_ENCODE_DISABLED; |
| 1232 wk = &ar->arWepKeyList[keyIndex]; |
| 1233 if (erq->length > wk->arKeyLen) { |
| 1234 erq->length = wk->arKeyLen; |
| 1235 } |
| 1236 if (wk->arKeyLen) { |
| 1237 A_MEMCPY(key, wk->arKey, erq->length); |
| 1238 } |
| 1239 } else { |
| 1240 erq->flags &= ~IW_ENCODE_DISABLED; |
| 1241 if (ar->user_saved_keys.keyOk) { |
| 1242 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen; |
| 1243 if (erq->length) { |
| 1244 A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->
length); |
| 1245 } |
| 1246 } else { |
| 1247 erq->length = 1; // not really printing any key but let iwcon
fig know enc is on |
| 1248 } |
| 1249 } |
| 1250 |
| 1251 if (ar->arDot11AuthMode & OPEN_AUTH) { |
| 1252 erq->flags |= IW_ENCODE_OPEN; |
| 1253 } |
| 1254 if (ar->arDot11AuthMode & SHARED_AUTH) { |
| 1255 erq->flags |= IW_ENCODE_RESTRICTED; |
| 1256 } |
| 1257 } |
| 1258 |
| 1259 return 0; |
| 1260 } |
| 1261 |
| 1262 #if WIRELESS_EXT >= 18 |
| 1263 /* |
| 1264 * SIOCSIWGENIE |
| 1265 */ |
| 1266 static int |
| 1267 ar6000_ioctl_siwgenie(struct net_device *dev, |
| 1268 struct iw_request_info *info, |
| 1269 struct iw_point *erq, char *extra) |
| 1270 { |
| 1271 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1272 |
| 1273 #ifdef WAPI_ENABLE |
| 1274 A_UINT8 *ie = erq->pointer; |
| 1275 A_UINT8 ie_type = ie[0]; |
| 1276 A_UINT16 ie_length = erq->length; |
| 1277 A_UINT8 wapi_ie[128]; |
| 1278 #endif |
| 1279 |
| 1280 if (ar->arWmiReady == FALSE) { |
| 1281 return -EIO; |
| 1282 } |
| 1283 #ifdef WAPI_ENABLE |
| 1284 if (ie_type == IEEE80211_ELEMID_WAPI) { |
| 1285 if(copy_from_user(wapi_ie, ie, ie_length)) |
| 1286 return -EIO; |
| 1287 wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie); |
| 1288 } |
| 1289 #endif |
| 1290 return 0; |
| 1291 } |
| 1292 |
| 1293 |
| 1294 /* |
| 1295 * SIOCGIWGENIE |
| 1296 */ |
| 1297 static int |
| 1298 ar6000_ioctl_giwgenie(struct net_device *dev, |
| 1299 struct iw_request_info *info, |
| 1300 struct iw_point *erq, char *extra) |
| 1301 { |
| 1302 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1303 |
| 1304 if (ar->arWmiReady == FALSE) { |
| 1305 return -EIO; |
| 1306 } |
| 1307 erq->length = 0; |
| 1308 erq->flags = 0; |
| 1309 |
| 1310 return 0; |
| 1311 } |
| 1312 |
| 1313 /* |
| 1314 * SIOCSIWAUTH |
| 1315 */ |
| 1316 static int |
| 1317 ar6000_ioctl_siwauth(struct net_device *dev, |
| 1318 struct iw_request_info *info, |
| 1319 struct iw_param *data, char *extra) |
| 1320 { |
| 1321 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1322 |
| 1323 A_BOOL profChanged; |
| 1324 A_UINT16 param; |
| 1325 A_INT32 ret; |
| 1326 A_INT32 value; |
| 1327 |
| 1328 if (ar->arWmiReady == FALSE) { |
| 1329 return -EIO; |
| 1330 } |
| 1331 |
| 1332 if (ar->arWlanState == WLAN_DISABLED) { |
| 1333 return -EIO; |
| 1334 } |
| 1335 |
| 1336 param = data->flags & IW_AUTH_INDEX; |
| 1337 value = data->value; |
| 1338 profChanged = TRUE; |
| 1339 ret = 0; |
| 1340 |
| 1341 switch (param) { |
| 1342 case IW_AUTH_WPA_VERSION: |
| 1343 if (value & IW_AUTH_WPA_VERSION_DISABLED) { |
| 1344 ar->arAuthMode = NONE_AUTH; |
| 1345 } else if (value & IW_AUTH_WPA_VERSION_WPA) { |
| 1346 ar->arAuthMode = WPA_AUTH; |
| 1347 } else if (value & IW_AUTH_WPA_VERSION_WPA2) { |
| 1348 ar->arAuthMode = WPA2_AUTH; |
| 1349 } else { |
| 1350 ret = -1; |
| 1351 profChanged = FALSE; |
| 1352 } |
| 1353 break; |
| 1354 case IW_AUTH_CIPHER_PAIRWISE: |
| 1355 if (value & IW_AUTH_CIPHER_NONE) { |
| 1356 ar->arPairwiseCrypto = NONE_CRYPT; |
| 1357 ar->arPairwiseCryptoLen = 0; |
| 1358 } else if (value & IW_AUTH_CIPHER_WEP40) { |
| 1359 ar->arPairwiseCrypto = WEP_CRYPT; |
| 1360 ar->arPairwiseCryptoLen = 5; |
| 1361 } else if (value & IW_AUTH_CIPHER_TKIP) { |
| 1362 ar->arPairwiseCrypto = TKIP_CRYPT; |
| 1363 ar->arPairwiseCryptoLen = 0; |
| 1364 } else if (value & IW_AUTH_CIPHER_CCMP) { |
| 1365 ar->arPairwiseCrypto = AES_CRYPT; |
| 1366 ar->arPairwiseCryptoLen = 0; |
| 1367 } else if (value & IW_AUTH_CIPHER_WEP104) { |
| 1368 ar->arPairwiseCrypto = WEP_CRYPT; |
| 1369 ar->arPairwiseCryptoLen = 13; |
| 1370 } else { |
| 1371 ret = -1; |
| 1372 profChanged = FALSE; |
| 1373 } |
| 1374 break; |
| 1375 case IW_AUTH_CIPHER_GROUP: |
| 1376 if (value & IW_AUTH_CIPHER_NONE) { |
| 1377 ar->arGroupCrypto = NONE_CRYPT; |
| 1378 ar->arGroupCryptoLen = 0; |
| 1379 } else if (value & IW_AUTH_CIPHER_WEP40) { |
| 1380 ar->arGroupCrypto = WEP_CRYPT; |
| 1381 ar->arGroupCryptoLen = 5; |
| 1382 } else if (value & IW_AUTH_CIPHER_TKIP) { |
| 1383 ar->arGroupCrypto = TKIP_CRYPT; |
| 1384 ar->arGroupCryptoLen = 0; |
| 1385 } else if (value & IW_AUTH_CIPHER_CCMP) { |
| 1386 ar->arGroupCrypto = AES_CRYPT; |
| 1387 ar->arGroupCryptoLen = 0; |
| 1388 } else if (value & IW_AUTH_CIPHER_WEP104) { |
| 1389 ar->arGroupCrypto = WEP_CRYPT; |
| 1390 ar->arGroupCryptoLen = 13; |
| 1391 } else { |
| 1392 ret = -1; |
| 1393 profChanged = FALSE; |
| 1394 } |
| 1395 break; |
| 1396 case IW_AUTH_KEY_MGMT: |
| 1397 if (value & IW_AUTH_KEY_MGMT_PSK) { |
| 1398 if (WPA_AUTH == ar->arAuthMode) { |
| 1399 ar->arAuthMode = WPA_PSK_AUTH; |
| 1400 } else if (WPA2_AUTH == ar->arAuthMode) { |
| 1401 ar->arAuthMode = WPA2_PSK_AUTH; |
| 1402 } else { |
| 1403 ret = -1; |
| 1404 } |
| 1405 } else if (!(value & IW_AUTH_KEY_MGMT_802_1X)) { |
| 1406 ar->arAuthMode = NONE_AUTH; |
| 1407 } |
| 1408 break; |
| 1409 case IW_AUTH_TKIP_COUNTERMEASURES: |
| 1410 wmi_set_tkip_countermeasures_cmd(ar->arWmi, value); |
| 1411 profChanged = FALSE; |
| 1412 break; |
| 1413 case IW_AUTH_DROP_UNENCRYPTED: |
| 1414 profChanged = FALSE; |
| 1415 break; |
| 1416 case IW_AUTH_80211_AUTH_ALG: |
| 1417 ar->arDot11AuthMode = 0; |
| 1418 if (value & IW_AUTH_ALG_OPEN_SYSTEM) { |
| 1419 ar->arDot11AuthMode |= OPEN_AUTH; |
| 1420 } |
| 1421 if (value & IW_AUTH_ALG_SHARED_KEY) { |
| 1422 ar->arDot11AuthMode |= SHARED_AUTH; |
| 1423 } |
| 1424 if (value & IW_AUTH_ALG_LEAP) { |
| 1425 ar->arDot11AuthMode = LEAP_AUTH; |
| 1426 } |
| 1427 if(ar->arDot11AuthMode == 0) { |
| 1428 ret = -1; |
| 1429 profChanged = FALSE; |
| 1430 } |
| 1431 break; |
| 1432 case IW_AUTH_WPA_ENABLED: |
| 1433 if (!value) { |
| 1434 ar->arAuthMode = NONE_AUTH; |
| 1435 /* when the supplicant is stopped, it calls this |
| 1436 * handler with value=0. The followings need to be |
| 1437 * reset if the STA were to connect again |
| 1438 * without security |
| 1439 */ |
| 1440 ar->arDot11AuthMode = OPEN_AUTH; |
| 1441 ar->arPairwiseCrypto = NONE_CRYPT; |
| 1442 ar->arPairwiseCryptoLen = 0; |
| 1443 ar->arGroupCrypto = NONE_CRYPT; |
| 1444 ar->arGroupCryptoLen = 0; |
| 1445 } |
| 1446 break; |
| 1447 case IW_AUTH_RX_UNENCRYPTED_EAPOL: |
| 1448 profChanged = FALSE; |
| 1449 break; |
| 1450 case IW_AUTH_ROAMING_CONTROL: |
| 1451 profChanged = FALSE; |
| 1452 break; |
| 1453 case IW_AUTH_PRIVACY_INVOKED: |
| 1454 if (!value) { |
| 1455 ar->arPairwiseCrypto = NONE_CRYPT; |
| 1456 ar->arPairwiseCryptoLen = 0; |
| 1457 ar->arGroupCrypto = NONE_CRYPT; |
| 1458 ar->arGroupCryptoLen = 0; |
| 1459 } |
| 1460 break; |
| 1461 #ifdef WAPI_ENABLE |
| 1462 case IW_AUTH_WAPI_ENABLED: |
| 1463 ar->arWapiEnable = value; |
| 1464 break; |
| 1465 #endif |
| 1466 default: |
| 1467 ret = -1; |
| 1468 profChanged = FALSE; |
| 1469 break; |
| 1470 } |
| 1471 |
| 1472 if (profChanged == TRUE) { |
| 1473 /* |
| 1474 * profile has changed. Erase ssid to signal change |
| 1475 */ |
| 1476 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 1477 ar->arSsidLen = 0; |
| 1478 } |
| 1479 |
| 1480 return ret; |
| 1481 } |
| 1482 |
| 1483 |
| 1484 /* |
| 1485 * SIOCGIWAUTH |
| 1486 */ |
| 1487 static int |
| 1488 ar6000_ioctl_giwauth(struct net_device *dev, |
| 1489 struct iw_request_info *info, |
| 1490 struct iw_param *data, char *extra) |
| 1491 { |
| 1492 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1493 A_UINT16 param; |
| 1494 A_INT32 ret; |
| 1495 |
| 1496 if (ar->arWmiReady == FALSE) { |
| 1497 return -EIO; |
| 1498 } |
| 1499 |
| 1500 if (ar->arWlanState == WLAN_DISABLED) { |
| 1501 return -EIO; |
| 1502 } |
| 1503 |
| 1504 param = data->flags & IW_AUTH_INDEX; |
| 1505 ret = 0; |
| 1506 data->value = 0; |
| 1507 |
| 1508 |
| 1509 switch (param) { |
| 1510 case IW_AUTH_WPA_VERSION: |
| 1511 if (ar->arAuthMode == NONE_AUTH) { |
| 1512 data->value |= IW_AUTH_WPA_VERSION_DISABLED; |
| 1513 } else if (ar->arAuthMode == WPA_AUTH) { |
| 1514 data->value |= IW_AUTH_WPA_VERSION_WPA; |
| 1515 } else if (ar->arAuthMode == WPA2_AUTH) { |
| 1516 data->value |= IW_AUTH_WPA_VERSION_WPA2; |
| 1517 } else { |
| 1518 ret = -1; |
| 1519 } |
| 1520 break; |
| 1521 case IW_AUTH_CIPHER_PAIRWISE: |
| 1522 if (ar->arPairwiseCrypto == NONE_CRYPT) { |
| 1523 data->value |= IW_AUTH_CIPHER_NONE; |
| 1524 } else if (ar->arPairwiseCrypto == WEP_CRYPT) { |
| 1525 if (ar->arPairwiseCryptoLen == 13) { |
| 1526 data->value |= IW_AUTH_CIPHER_WEP104; |
| 1527 } else { |
| 1528 data->value |= IW_AUTH_CIPHER_WEP104; |
| 1529 } |
| 1530 } else if (ar->arPairwiseCrypto == TKIP_CRYPT) { |
| 1531 data->value |= IW_AUTH_CIPHER_TKIP; |
| 1532 } else if (ar->arPairwiseCrypto == AES_CRYPT) { |
| 1533 data->value |= IW_AUTH_CIPHER_CCMP; |
| 1534 } else { |
| 1535 ret = -1; |
| 1536 } |
| 1537 break; |
| 1538 case IW_AUTH_CIPHER_GROUP: |
| 1539 if (ar->arGroupCrypto == NONE_CRYPT) { |
| 1540 data->value |= IW_AUTH_CIPHER_NONE; |
| 1541 } else if (ar->arGroupCrypto == WEP_CRYPT) { |
| 1542 if (ar->arGroupCryptoLen == 13) { |
| 1543 data->value |= IW_AUTH_CIPHER_WEP104; |
| 1544 } else { |
| 1545 data->value |= IW_AUTH_CIPHER_WEP104; |
| 1546 } |
| 1547 } else if (ar->arGroupCrypto == TKIP_CRYPT) { |
| 1548 data->value |= IW_AUTH_CIPHER_TKIP; |
| 1549 } else if (ar->arGroupCrypto == AES_CRYPT) { |
| 1550 data->value |= IW_AUTH_CIPHER_CCMP; |
| 1551 } else { |
| 1552 ret = -1; |
| 1553 } |
| 1554 break; |
| 1555 case IW_AUTH_KEY_MGMT: |
| 1556 if ((ar->arAuthMode == WPA_PSK_AUTH) || |
| 1557 (ar->arAuthMode == WPA2_PSK_AUTH)) { |
| 1558 data->value |= IW_AUTH_KEY_MGMT_PSK; |
| 1559 } else if ((ar->arAuthMode == WPA_AUTH) || |
| 1560 (ar->arAuthMode == WPA2_AUTH)) { |
| 1561 data->value |= IW_AUTH_KEY_MGMT_802_1X; |
| 1562 } |
| 1563 break; |
| 1564 case IW_AUTH_TKIP_COUNTERMEASURES: |
| 1565 // TODO. Save countermeassure enable/disable |
| 1566 data->value = 0; |
| 1567 break; |
| 1568 case IW_AUTH_DROP_UNENCRYPTED: |
| 1569 break; |
| 1570 case IW_AUTH_80211_AUTH_ALG: |
| 1571 if (ar->arDot11AuthMode == OPEN_AUTH) { |
| 1572 data->value |= IW_AUTH_ALG_OPEN_SYSTEM; |
| 1573 } else if (ar->arDot11AuthMode == SHARED_AUTH) { |
| 1574 data->value |= IW_AUTH_ALG_SHARED_KEY; |
| 1575 } else if (ar->arDot11AuthMode == LEAP_AUTH) { |
| 1576 data->value |= IW_AUTH_ALG_LEAP; |
| 1577 } else { |
| 1578 ret = -1; |
| 1579 } |
| 1580 break; |
| 1581 case IW_AUTH_WPA_ENABLED: |
| 1582 if (ar->arAuthMode == NONE_AUTH) { |
| 1583 data->value = 0; |
| 1584 } else { |
| 1585 data->value = 1; |
| 1586 } |
| 1587 break; |
| 1588 case IW_AUTH_RX_UNENCRYPTED_EAPOL: |
| 1589 break; |
| 1590 case IW_AUTH_ROAMING_CONTROL: |
| 1591 break; |
| 1592 case IW_AUTH_PRIVACY_INVOKED: |
| 1593 if (ar->arPairwiseCrypto == NONE_CRYPT) { |
| 1594 data->value = 0; |
| 1595 } else { |
| 1596 data->value = 1; |
| 1597 } |
| 1598 break; |
| 1599 #ifdef WAPI_ENABLE |
| 1600 case IW_AUTH_WAPI_ENABLED: |
| 1601 data->value = ar->arWapiEnable; |
| 1602 break; |
| 1603 #endif |
| 1604 default: |
| 1605 ret = -1; |
| 1606 break; |
| 1607 } |
| 1608 |
| 1609 return 0; |
| 1610 } |
| 1611 |
| 1612 /* |
| 1613 * SIOCSIWPMKSA |
| 1614 */ |
| 1615 static int |
| 1616 ar6000_ioctl_siwpmksa(struct net_device *dev, |
| 1617 struct iw_request_info *info, |
| 1618 struct iw_point *data, char *extra) |
| 1619 { |
| 1620 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1621 A_INT32 ret; |
| 1622 A_STATUS status; |
| 1623 struct iw_pmksa *pmksa; |
| 1624 |
| 1625 pmksa = (struct iw_pmksa *)extra; |
| 1626 |
| 1627 if (ar->arWmiReady == FALSE) { |
| 1628 return -EIO; |
| 1629 } |
| 1630 |
| 1631 ret = 0; |
| 1632 status = A_OK; |
| 1633 |
| 1634 switch (pmksa->cmd) { |
| 1635 case IW_PMKSA_ADD: |
| 1636 status = wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid.sa_data, pmksa->pm
kid, TRUE); |
| 1637 break; |
| 1638 case IW_PMKSA_REMOVE: |
| 1639 status = wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid.sa_data, pmksa->pm
kid, FALSE); |
| 1640 break; |
| 1641 case IW_PMKSA_FLUSH: |
| 1642 break; |
| 1643 default: |
| 1644 ret=-1; |
| 1645 break; |
| 1646 } |
| 1647 if (status != A_OK) { |
| 1648 ret = -1; |
| 1649 } |
| 1650 |
| 1651 return ret; |
| 1652 } |
| 1653 |
| 1654 #ifdef WAPI_ENABLE |
| 1655 |
| 1656 #define PN_INIT 0x5c365c36 |
| 1657 |
| 1658 static int ar6000_set_wapi_key(struct net_device *dev, |
| 1659 struct iw_request_info *info, |
| 1660 struct iw_point *erq, char *extra) |
| 1661 { |
| 1662 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1663 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
| 1664 KEY_USAGE keyUsage = 0; |
| 1665 A_INT32 keyLen; |
| 1666 A_UINT8 *keyData; |
| 1667 A_INT32 index; |
| 1668 A_UINT32 *PN; |
| 1669 A_INT32 i; |
| 1670 A_STATUS status; |
| 1671 A_UINT8 wapiKeyRsc[16]; |
| 1672 CRYPTO_TYPE keyType = WAPI_CRYPT; |
| 1673 const A_UINT8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
| 1674 |
| 1675 index = erq->flags & IW_ENCODE_INDEX; |
| 1676 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) || |
| 1677 ((index - 1) > WMI_MAX_KEY_INDEX))) { |
| 1678 return -EIO; |
| 1679 } |
| 1680 |
| 1681 index--; |
| 1682 if (index < 0 || index > 4) { |
| 1683 return -EIO; |
| 1684 } |
| 1685 keyData = (A_UINT8 *)(ext + 1); |
| 1686 keyLen = erq->length - sizeof(struct iw_encode_ext); |
| 1687 A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc)); |
| 1688 |
| 1689 if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) { |
| 1690 keyUsage |= GROUP_USAGE; |
| 1691 PN = (A_UINT32 *)wapiKeyRsc; |
| 1692 for (i = 0; i < 4; i++) { |
| 1693 PN[i] = PN_INIT; |
| 1694 } |
| 1695 } else { |
| 1696 keyUsage |= PAIRWISE_USAGE; |
| 1697 } |
| 1698 status = wmi_addKey_cmd(ar->arWmi, |
| 1699 index, |
| 1700 keyType, |
| 1701 keyUsage, |
| 1702 keyLen, |
| 1703 wapiKeyRsc, |
| 1704 keyData, |
| 1705 KEY_OP_INIT_WAPIPN, |
| 1706 NULL, |
| 1707 SYNC_BEFORE_WMIFLAG); |
| 1708 if (A_OK != status) { |
| 1709 return -EIO; |
| 1710 } |
| 1711 return 0; |
| 1712 } |
| 1713 |
| 1714 #endif |
| 1715 |
| 1716 /* |
| 1717 * SIOCSIWENCODEEXT |
| 1718 */ |
| 1719 static int |
| 1720 ar6000_ioctl_siwencodeext(struct net_device *dev, |
| 1721 struct iw_request_info *info, |
| 1722 struct iw_point *erq, char *extra) |
| 1723 { |
| 1724 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1725 A_INT32 index; |
| 1726 struct iw_encode_ext *ext; |
| 1727 KEY_USAGE keyUsage; |
| 1728 A_INT32 keyLen; |
| 1729 A_UINT8 *keyData; |
| 1730 A_UINT8 keyRsc[8]; |
| 1731 A_STATUS status; |
| 1732 CRYPTO_TYPE keyType; |
| 1733 #ifdef USER_KEYS |
| 1734 struct ieee80211req_key ik; |
| 1735 #endif /* USER_KEYS */ |
| 1736 |
| 1737 if (ar->arWlanState == WLAN_DISABLED) { |
| 1738 return -EIO; |
| 1739 } |
| 1740 |
| 1741 #ifdef USER_KEYS |
| 1742 ar->user_saved_keys.keyOk = FALSE; |
| 1743 #endif /* USER_KEYS */ |
| 1744 |
| 1745 index = erq->flags & IW_ENCODE_INDEX; |
| 1746 |
| 1747 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) || |
| 1748 ((index - 1) > WMI_MAX_KEY_INDEX))) |
| 1749 { |
| 1750 return -EIO; |
| 1751 } |
| 1752 |
| 1753 ext = (struct iw_encode_ext *)extra; |
| 1754 if (erq->flags & IW_ENCODE_DISABLED) { |
| 1755 /* |
| 1756 * Encryption disabled |
| 1757 */ |
| 1758 if (index) { |
| 1759 /* |
| 1760 * If key index was specified then clear the specified key |
| 1761 */ |
| 1762 index--; |
| 1763 A_MEMZERO(ar->arWepKeyList[index].arKey, |
| 1764 sizeof(ar->arWepKeyList[index].arKey)); |
| 1765 ar->arWepKeyList[index].arKeyLen = 0; |
| 1766 } |
| 1767 } else { |
| 1768 /* |
| 1769 * Enabling WEP encryption |
| 1770 */ |
| 1771 if (index) { |
| 1772 index--; /* keyindex is off base 1 in iwconfig */ |
| 1773 } |
| 1774 |
| 1775 keyUsage = 0; |
| 1776 keyLen = erq->length - sizeof(struct iw_encode_ext); |
| 1777 |
| 1778 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { |
| 1779 keyUsage = TX_USAGE; |
| 1780 ar->arDefTxKeyIndex = index; |
| 1781 // Just setting the key index |
| 1782 if (keyLen == 0) { |
| 1783 return 0; |
| 1784 } |
| 1785 } |
| 1786 |
| 1787 if (keyLen <= 0) { |
| 1788 return -EIO; |
| 1789 } |
| 1790 |
| 1791 /* key follows iw_encode_ext */ |
| 1792 keyData = (A_UINT8 *)(ext + 1); |
| 1793 |
| 1794 switch (ext->alg) { |
| 1795 case IW_ENCODE_ALG_WEP: |
| 1796 keyType = WEP_CRYPT; |
| 1797 #ifdef USER_KEYS |
| 1798 ik.ik_type = IEEE80211_CIPHER_WEP; |
| 1799 #endif /* USER_KEYS */ |
| 1800 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(keyLen)) { |
| 1801 return -EIO; |
| 1802 } |
| 1803 |
| 1804 // Check whether it is static wep |
| 1805 if (!ar->arConnected) { |
| 1806 A_MEMZERO(ar->arWepKeyList[index].arKey, |
| 1807 sizeof(ar->arWepKeyList[index].arKey)); |
| 1808 A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen); |
| 1809 ar->arWepKeyList[index].arKeyLen = keyLen; |
| 1810 |
| 1811 return 0; |
| 1812 } |
| 1813 break; |
| 1814 case IW_ENCODE_ALG_TKIP: |
| 1815 keyType = TKIP_CRYPT; |
| 1816 #ifdef USER_KEYS |
| 1817 ik.ik_type = IEEE80211_CIPHER_TKIP; |
| 1818 #endif /* USER_KEYS */ |
| 1819 break; |
| 1820 case IW_ENCODE_ALG_CCMP: |
| 1821 keyType = AES_CRYPT; |
| 1822 #ifdef USER_KEYS |
| 1823 ik.ik_type = IEEE80211_CIPHER_AES_CCM; |
| 1824 #endif /* USER_KEYS */ |
| 1825 break; |
| 1826 #ifdef WAPI_ENABLE |
| 1827 case IW_ENCODE_ALG_SM4: |
| 1828 if (ar->arWapiEnable) { |
| 1829 return ar6000_set_wapi_key(dev, info, erq, extra); |
| 1830 } else { |
| 1831 return -EIO; |
| 1832 } |
| 1833 #endif |
| 1834 case IW_ENCODE_ALG_PMK: |
| 1835 ar->arConnectCtrlFlags |= CONNECT_DO_WPA_OFFLOAD; |
| 1836 return wmi_set_pmk_cmd(ar->arWmi, keyData); |
| 1837 default: |
| 1838 return -EIO; |
| 1839 } |
| 1840 |
| 1841 |
| 1842 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { |
| 1843 keyUsage |= GROUP_USAGE; |
| 1844 } else { |
| 1845 keyUsage |= PAIRWISE_USAGE; |
| 1846 } |
| 1847 |
| 1848 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { |
| 1849 A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc)); |
| 1850 } else { |
| 1851 A_MEMZERO(keyRsc, sizeof(keyRsc)); |
| 1852 } |
| 1853 |
| 1854 if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMod
e)) && |
| 1855 (GROUP_USAGE & keyUsage)) |
| 1856 { |
| 1857 A_UNTIMEOUT(&ar->disconnect_timer); |
| 1858 } |
| 1859 |
| 1860 status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage, |
| 1861 keyLen, keyRsc, |
| 1862 keyData, KEY_OP_INIT_VAL, |
| 1863 ext->addr.sa_data, |
| 1864 SYNC_BOTH_WMIFLAG); |
| 1865 if (status != A_OK) { |
| 1866 return -EIO; |
| 1867 } |
| 1868 |
| 1869 #ifdef USER_KEYS |
| 1870 ik.ik_keyix = index; |
| 1871 ik.ik_keylen = keyLen; |
| 1872 memcpy(ik.ik_keydata, keyData, keyLen); |
| 1873 memcpy(&ik.ik_keyrsc, keyRsc, sizeof(keyRsc)); |
| 1874 memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN); |
| 1875 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { |
| 1876 memcpy(&ar->user_saved_keys.bcast_ik, &ik, |
| 1877 sizeof(struct ieee80211req_key)); |
| 1878 } else { |
| 1879 memcpy(&ar->user_saved_keys.ucast_ik, &ik, |
| 1880 sizeof(struct ieee80211req_key)); |
| 1881 } |
| 1882 ar->user_saved_keys.keyOk = TRUE; |
| 1883 #endif /* USER_KEYS */ |
| 1884 } |
| 1885 |
| 1886 |
| 1887 return 0; |
| 1888 } |
| 1889 |
| 1890 /* |
| 1891 * SIOCGIWENCODEEXT |
| 1892 */ |
| 1893 static int |
| 1894 ar6000_ioctl_giwencodeext(struct net_device *dev, |
| 1895 struct iw_request_info *info, |
| 1896 struct iw_point *erq, char *extra) |
| 1897 { |
| 1898 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1899 |
| 1900 if (ar->arWlanState == WLAN_DISABLED) { |
| 1901 return -EIO; |
| 1902 } |
| 1903 |
| 1904 if (ar->arPairwiseCrypto == NONE_CRYPT) { |
| 1905 erq->length = 0; |
| 1906 erq->flags = IW_ENCODE_DISABLED; |
| 1907 } else { |
| 1908 erq->length = 0; |
| 1909 } |
| 1910 |
| 1911 return 0; |
| 1912 } |
| 1913 #endif // WIRELESS_EXT >= 18 |
| 1914 |
| 1915 #if WIRELESS_EXT > 20 |
| 1916 static int ar6000_ioctl_siwpower(struct net_device *dev, |
| 1917 struct iw_request_info *info, |
| 1918 union iwreq_data *wrqu, char *extra) |
| 1919 { |
| 1920 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1921 WMI_POWER_MODE power_mode; |
| 1922 |
| 1923 if (ar->arWlanState == WLAN_DISABLED) { |
| 1924 return -EIO; |
| 1925 } |
| 1926 |
| 1927 if (wrqu->power.disabled) |
| 1928 power_mode = MAX_PERF_POWER; |
| 1929 else |
| 1930 power_mode = REC_POWER; |
| 1931 |
| 1932 if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0) |
| 1933 return -EIO; |
| 1934 return 0; |
| 1935 } |
| 1936 |
| 1937 static int ar6000_ioctl_giwpower(struct net_device *dev, |
| 1938 struct iw_request_info *info, |
| 1939 union iwreq_data *wrqu, char *extra) |
| 1940 { |
| 1941 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1942 |
| 1943 if (ar->arWlanState == WLAN_DISABLED) { |
| 1944 return -EIO; |
| 1945 } |
| 1946 |
| 1947 if(!ar->arWmi){ |
| 1948 return -EIO; |
| 1949 } |
| 1950 return wmi_get_power_mode_cmd(ar->arWmi); |
| 1951 } |
| 1952 #endif // WIRELESS_EXT > 20 |
| 1953 |
| 1954 /* |
| 1955 * SIOCGIWNAME |
| 1956 */ |
| 1957 int |
| 1958 ar6000_ioctl_giwname(struct net_device *dev, |
| 1959 struct iw_request_info *info, |
| 1960 char *name, char *extra) |
| 1961 { |
| 1962 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1963 |
| 1964 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 1965 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 1966 return -EOPNOTSUPP; |
| 1967 } |
| 1968 |
| 1969 if (ar->arWlanState == WLAN_DISABLED) { |
| 1970 return -EIO; |
| 1971 } |
| 1972 |
| 1973 switch (ar->arPhyCapability) { |
| 1974 case (WMI_11A_CAPABILITY): |
| 1975 strncpy(name, "AR6000 802.11a", IFNAMSIZ); |
| 1976 break; |
| 1977 case (WMI_11G_CAPABILITY): |
| 1978 strncpy(name, "AR6000 802.11g", IFNAMSIZ); |
| 1979 break; |
| 1980 case (WMI_11AG_CAPABILITY): |
| 1981 strncpy(name, "AR6000 802.11ag", IFNAMSIZ); |
| 1982 break; |
| 1983 case (WMI_11NA_CAPABILITY): |
| 1984 strncpy(name, "AR6000 802.11na", IFNAMSIZ); |
| 1985 break; |
| 1986 case (WMI_11NG_CAPABILITY): |
| 1987 strncpy(name, "AR6000 802.11ng", IFNAMSIZ); |
| 1988 break; |
| 1989 case (WMI_11NAG_CAPABILITY): |
| 1990 strncpy(name, "AR6000 802.11nag", IFNAMSIZ); |
| 1991 break; |
| 1992 default: |
| 1993 strncpy(name, "AR6000 802.11", IFNAMSIZ); |
| 1994 break; |
| 1995 } |
| 1996 |
| 1997 return 0; |
| 1998 } |
| 1999 |
| 2000 /* |
| 2001 * SIOCSIWFREQ |
| 2002 */ |
| 2003 int |
| 2004 ar6000_ioctl_siwfreq(struct net_device *dev, |
| 2005 struct iw_request_info *info, |
| 2006 struct iw_freq *freq, char *extra) |
| 2007 { |
| 2008 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2009 |
| 2010 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2011 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2012 return -EOPNOTSUPP; |
| 2013 } |
| 2014 |
| 2015 if (ar->arWlanState == WLAN_DISABLED) { |
| 2016 return -EIO; |
| 2017 } |
| 2018 |
| 2019 /* |
| 2020 * We support limiting the channels via wmiconfig. |
| 2021 * |
| 2022 * We use this command to configure the channel hint for the connect cmd |
| 2023 * so it is possible the target will end up connecting to a different |
| 2024 * channel. |
| 2025 */ |
| 2026 if (freq->e > 1) { |
| 2027 return -EINVAL; |
| 2028 } else if (freq->e == 1) { |
| 2029 ar->arChannelHint = freq->m / 100000; |
| 2030 } else { |
| 2031 if(freq->m) { |
| 2032 ar->arChannelHint = wlan_ieee2freq(freq->m); |
| 2033 } else { |
| 2034 /* Auto Channel Selection */ |
| 2035 ar->arChannelHint = 0; |
| 2036 } |
| 2037 } |
| 2038 |
| 2039 ar->ap_profile_flag = 1; /* There is a change in profile */ |
| 2040 |
| 2041 A_PRINTF("channel hint set to %d\n", ar->arChannelHint); |
| 2042 return 0; |
| 2043 } |
| 2044 |
| 2045 /* |
| 2046 * SIOCGIWFREQ |
| 2047 */ |
| 2048 int |
| 2049 ar6000_ioctl_giwfreq(struct net_device *dev, |
| 2050 struct iw_request_info *info, |
| 2051 struct iw_freq *freq, char *extra) |
| 2052 { |
| 2053 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2054 |
| 2055 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2056 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2057 return -EOPNOTSUPP; |
| 2058 } |
| 2059 |
| 2060 if (ar->arWlanState == WLAN_DISABLED) { |
| 2061 return -EIO; |
| 2062 } |
| 2063 |
| 2064 if (ar->arNetworkType == AP_NETWORK) { |
| 2065 if(ar->arChannelHint) { |
| 2066 freq->m = ar->arChannelHint * 100000; |
| 2067 } else if(ar->arACS) { |
| 2068 freq->m = ar->arACS * 100000; |
| 2069 } else { |
| 2070 return -EINVAL; |
| 2071 } |
| 2072 } else { |
| 2073 if (ar->arConnected != TRUE) { |
| 2074 return -EINVAL; |
| 2075 } else { |
| 2076 freq->m = ar->arBssChannel * 100000; |
| 2077 } |
| 2078 } |
| 2079 |
| 2080 freq->e = 1; |
| 2081 |
| 2082 return 0; |
| 2083 } |
| 2084 |
| 2085 /* |
| 2086 * SIOCSIWMODE |
| 2087 */ |
| 2088 int |
| 2089 ar6000_ioctl_siwmode(struct net_device *dev, |
| 2090 struct iw_request_info *info, |
| 2091 __u32 *mode, char *extra) |
| 2092 { |
| 2093 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2094 |
| 2095 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2096 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2097 return -EOPNOTSUPP; |
| 2098 } |
| 2099 |
| 2100 if (ar->arWlanState == WLAN_DISABLED) { |
| 2101 return -EIO; |
| 2102 } |
| 2103 |
| 2104 /* |
| 2105 * clear SSID during mode switch in connected state |
| 2106 */ |
| 2107 if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHO
C_NETWORK)) && (ar->arConnected == TRUE) ){ |
| 2108 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 2109 ar->arSsidLen = 0; |
| 2110 } |
| 2111 |
| 2112 switch (*mode) { |
| 2113 case IW_MODE_INFRA: |
| 2114 ar->arNextMode = INFRA_NETWORK; |
| 2115 break; |
| 2116 case IW_MODE_ADHOC: |
| 2117 ar->arNextMode = ADHOC_NETWORK; |
| 2118 break; |
| 2119 case IW_MODE_MASTER: |
| 2120 ar->arNextMode = AP_NETWORK; |
| 2121 break; |
| 2122 default: |
| 2123 return -EINVAL; |
| 2124 } |
| 2125 |
| 2126 /* clear all shared parameters between AP and STA|IBSS modes when we |
| 2127 * switch between them. Switch between STA & IBSS modes does'nt clear |
| 2128 * the shared profile. This is as per the original design for switching |
| 2129 * between STA & IBSS. |
| 2130 */ |
| 2131 if (ar->arNetworkType == AP_NETWORK || ar->arNextMode == AP_NETWORK) { |
| 2132 ar->arDot11AuthMode = OPEN_AUTH; |
| 2133 ar->arAuthMode = NONE_AUTH; |
| 2134 ar->arPairwiseCrypto = NONE_CRYPT; |
| 2135 ar->arPairwiseCryptoLen = 0; |
| 2136 ar->arGroupCrypto = NONE_CRYPT; |
| 2137 ar->arGroupCryptoLen = 0; |
| 2138 ar->arChannelHint = 0; |
| 2139 ar->arBssChannel = 0; |
| 2140 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); |
| 2141 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 2142 ar->arSsidLen = 0; |
| 2143 } |
| 2144 |
| 2145 /* SSID has to be cleared to trigger a profile change while switching |
| 2146 * between STA & IBSS modes having the same SSID |
| 2147 */ |
| 2148 if (ar->arNetworkType != ar->arNextMode) { |
| 2149 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 2150 ar->arSsidLen = 0; |
| 2151 } |
| 2152 |
| 2153 return 0; |
| 2154 } |
| 2155 |
| 2156 /* |
| 2157 * SIOCGIWMODE |
| 2158 */ |
| 2159 int |
| 2160 ar6000_ioctl_giwmode(struct net_device *dev, |
| 2161 struct iw_request_info *info, |
| 2162 __u32 *mode, char *extra) |
| 2163 { |
| 2164 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2165 |
| 2166 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2167 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2168 return -EOPNOTSUPP; |
| 2169 } |
| 2170 |
| 2171 if (ar->arWlanState == WLAN_DISABLED) { |
| 2172 return -EIO; |
| 2173 } |
| 2174 |
| 2175 switch (ar->arNetworkType) { |
| 2176 case INFRA_NETWORK: |
| 2177 *mode = IW_MODE_INFRA; |
| 2178 break; |
| 2179 case ADHOC_NETWORK: |
| 2180 *mode = IW_MODE_ADHOC; |
| 2181 break; |
| 2182 case AP_NETWORK: |
| 2183 *mode = IW_MODE_MASTER; |
| 2184 break; |
| 2185 default: |
| 2186 return -EIO; |
| 2187 } |
| 2188 return 0; |
| 2189 } |
| 2190 |
| 2191 /* |
| 2192 * SIOCSIWSENS |
| 2193 */ |
| 2194 int |
| 2195 ar6000_ioctl_siwsens(struct net_device *dev, |
| 2196 struct iw_request_info *info, |
| 2197 struct iw_param *sens, char *extra) |
| 2198 { |
| 2199 return 0; |
| 2200 } |
| 2201 |
| 2202 /* |
| 2203 * SIOCGIWSENS |
| 2204 */ |
| 2205 int |
| 2206 ar6000_ioctl_giwsens(struct net_device *dev, |
| 2207 struct iw_request_info *info, |
| 2208 struct iw_param *sens, char *extra) |
| 2209 { |
| 2210 sens->value = 0; |
| 2211 sens->fixed = 1; |
| 2212 |
| 2213 return 0; |
| 2214 } |
| 2215 |
| 2216 /* |
| 2217 * SIOCGIWRANGE |
| 2218 */ |
| 2219 int |
| 2220 ar6000_ioctl_giwrange(struct net_device *dev, |
| 2221 struct iw_request_info *info, |
| 2222 struct iw_point *data, char *extra) |
| 2223 { |
| 2224 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2225 struct iw_range *range = (struct iw_range *) extra; |
| 2226 int i, ret = 0; |
| 2227 |
| 2228 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2229 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2230 return -EOPNOTSUPP; |
| 2231 } |
| 2232 |
| 2233 if (ar->bIsDestroyProgress) { |
| 2234 return -EBUSY; |
| 2235 } |
| 2236 |
| 2237 if (ar->arWmiReady == FALSE) { |
| 2238 return -EIO; |
| 2239 } |
| 2240 |
| 2241 if (ar->arWlanState == WLAN_DISABLED) { |
| 2242 return -EIO; |
| 2243 } |
| 2244 |
| 2245 if (down_interruptible(&ar->arSem)) { |
| 2246 return -ERESTARTSYS; |
| 2247 } |
| 2248 |
| 2249 if (ar->bIsDestroyProgress) { |
| 2250 up(&ar->arSem); |
| 2251 return -EBUSY; |
| 2252 } |
| 2253 |
| 2254 ar->arNumChannels = -1; |
| 2255 A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList)); |
| 2256 |
| 2257 if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) { |
| 2258 up(&ar->arSem); |
| 2259 return -EIO; |
| 2260 } |
| 2261 |
| 2262 wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeou
t * HZ); |
| 2263 |
| 2264 if (signal_pending(current)) { |
| 2265 up(&ar->arSem); |
| 2266 return -EINTR; |
| 2267 } |
| 2268 |
| 2269 data->length = sizeof(struct iw_range); |
| 2270 A_MEMZERO(range, sizeof(struct iw_range)); |
| 2271 |
| 2272 range->txpower_capa = 0; |
| 2273 |
| 2274 range->min_pmp = 1 * 1024; |
| 2275 range->max_pmp = 65535 * 1024; |
| 2276 range->min_pmt = 1 * 1024; |
| 2277 range->max_pmt = 1000 * 1024; |
| 2278 range->pmp_flags = IW_POWER_PERIOD; |
| 2279 range->pmt_flags = IW_POWER_TIMEOUT; |
| 2280 range->pm_capa = 0; |
| 2281 |
| 2282 range->we_version_compiled = WIRELESS_EXT; |
| 2283 range->we_version_source = 13; |
| 2284 |
| 2285 range->retry_capa = IW_RETRY_LIMIT; |
| 2286 range->retry_flags = IW_RETRY_LIMIT; |
| 2287 range->min_retry = 0; |
| 2288 range->max_retry = 255; |
| 2289 |
| 2290 range->num_frequency = range->num_channels = ar->arNumChannels; |
| 2291 for (i = 0; i < ar->arNumChannels; i++) { |
| 2292 range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]); |
| 2293 range->freq[i].m = ar->arChannelList[i] * 100000; |
| 2294 range->freq[i].e = 1; |
| 2295 /* |
| 2296 * Linux supports max of 32 channels, bail out once you |
| 2297 * reach the max. |
| 2298 */ |
| 2299 if (i == IW_MAX_FREQUENCIES) { |
| 2300 break; |
| 2301 } |
| 2302 } |
| 2303 |
| 2304 /* Max quality is max field value minus noise floor */ |
| 2305 range->max_qual.qual = 0xff - 161; |
| 2306 |
| 2307 /* |
| 2308 * In order to use dBm measurements, 'level' must be lower |
| 2309 * than any possible measurement (see iw_print_stats() in |
| 2310 * wireless tools). It's unclear how this is meant to be |
| 2311 * done, but setting zero in these values forces dBm and |
| 2312 * the actual numbers are not used. |
| 2313 */ |
| 2314 range->max_qual.level = 0; |
| 2315 range->max_qual.noise = 0; |
| 2316 |
| 2317 range->sensitivity = 3; |
| 2318 |
| 2319 range->max_encoding_tokens = 4; |
| 2320 /* XXX query driver to find out supported key sizes */ |
| 2321 range->num_encoding_sizes = 3; |
| 2322 range->encoding_size[0] = 5; /* 40-bit */ |
| 2323 range->encoding_size[1] = 13; /* 104-bit */ |
| 2324 range->encoding_size[2] = 16; /* 128-bit */ |
| 2325 |
| 2326 range->num_bitrates = 0; |
| 2327 |
| 2328 /* estimated maximum TCP throughput values (bps) */ |
| 2329 range->throughput = 22000000; |
| 2330 |
| 2331 range->min_rts = 0; |
| 2332 range->max_rts = 2347; |
| 2333 range->min_frag = 256; |
| 2334 range->max_frag = 2346; |
| 2335 |
| 2336 up(&ar->arSem); |
| 2337 |
| 2338 return ret; |
| 2339 } |
| 2340 |
| 2341 |
| 2342 /* |
| 2343 * SIOCSIWAP |
| 2344 * This ioctl is used to set the desired bssid for the connect command. |
| 2345 */ |
| 2346 int |
| 2347 ar6000_ioctl_siwap(struct net_device *dev, |
| 2348 struct iw_request_info *info, |
| 2349 struct sockaddr *ap_addr, char *extra) |
| 2350 { |
| 2351 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2352 |
| 2353 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2354 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2355 return -EOPNOTSUPP; |
| 2356 } |
| 2357 |
| 2358 if (ar->arWlanState == WLAN_DISABLED) { |
| 2359 return -EIO; |
| 2360 } |
| 2361 |
| 2362 if (ap_addr->sa_family != ARPHRD_ETHER) { |
| 2363 return -EIO; |
| 2364 } |
| 2365 |
| 2366 if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) { |
| 2367 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); |
| 2368 } else { |
| 2369 A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid)); |
| 2370 } |
| 2371 |
| 2372 return 0; |
| 2373 } |
| 2374 |
| 2375 /* |
| 2376 * SIOCGIWAP |
| 2377 */ |
| 2378 int |
| 2379 ar6000_ioctl_giwap(struct net_device *dev, |
| 2380 struct iw_request_info *info, |
| 2381 struct sockaddr *ap_addr, char *extra) |
| 2382 { |
| 2383 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2384 |
| 2385 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2386 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2387 return -EOPNOTSUPP; |
| 2388 } |
| 2389 |
| 2390 if (ar->arWlanState == WLAN_DISABLED) { |
| 2391 return -EIO; |
| 2392 } |
| 2393 |
| 2394 if (ar->arNetworkType == AP_NETWORK) { |
| 2395 A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN); |
| 2396 ap_addr->sa_family = ARPHRD_ETHER; |
| 2397 return 0; |
| 2398 } |
| 2399 |
| 2400 if (ar->arConnected != TRUE) { |
| 2401 return -EINVAL; |
| 2402 } |
| 2403 |
| 2404 A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid)); |
| 2405 ap_addr->sa_family = ARPHRD_ETHER; |
| 2406 |
| 2407 return 0; |
| 2408 } |
| 2409 |
| 2410 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) |
| 2411 /* |
| 2412 * SIOCSIWMLME |
| 2413 */ |
| 2414 int |
| 2415 ar6000_ioctl_siwmlme(struct net_device *dev, |
| 2416 struct iw_request_info *info, |
| 2417 struct iw_point *data, char *extra) |
| 2418 { |
| 2419 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2420 |
| 2421 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2422 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2423 return -EOPNOTSUPP; |
| 2424 } |
| 2425 |
| 2426 if (ar->bIsDestroyProgress) { |
| 2427 return -EBUSY; |
| 2428 } |
| 2429 |
| 2430 if (ar->arWlanState == WLAN_DISABLED) { |
| 2431 return -EIO; |
| 2432 } |
| 2433 |
| 2434 if (ar->arWmiReady == FALSE) { |
| 2435 return -EIO; |
| 2436 } |
| 2437 |
| 2438 if (ar->arNetworkType == AP_NETWORK) { |
| 2439 return -EINVAL; |
| 2440 } |
| 2441 |
| 2442 if (down_interruptible(&ar->arSem)) { |
| 2443 return -ERESTARTSYS; |
| 2444 } |
| 2445 |
| 2446 if (ar->bIsDestroyProgress) { |
| 2447 up(&ar->arSem); |
| 2448 return -EBUSY; |
| 2449 } |
| 2450 |
| 2451 if (data->pointer && data->length == sizeof(struct iw_mlme)) { |
| 2452 |
| 2453 A_UINT8 arNetworkType; |
| 2454 struct iw_mlme mlme; |
| 2455 |
| 2456 if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme))) |
| 2457 return -EIO; |
| 2458 |
| 2459 switch (mlme.cmd) { |
| 2460 |
| 2461 case IW_MLME_DEAUTH: |
| 2462 /* ignore it */ |
| 2463 break; |
| 2464 |
| 2465 case IW_MLME_DISASSOC: |
| 2466 if ((ar->arConnected != TRUE) || |
| 2467 (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) { |
| 2468 |
| 2469 up(&ar->arSem); |
| 2470 return -EINVAL; |
| 2471 } |
| 2472 wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0); |
| 2473 arNetworkType = ar->arNetworkType; |
| 2474 ar6000_init_profile_info(ar); |
| 2475 ar->arNetworkType = arNetworkType; |
| 2476 reconnect_flag = 0; |
| 2477 wmi_disconnect_cmd(ar->arWmi); |
| 2478 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 2479 ar->arSsidLen = 0; |
| 2480 if (ar->arSkipScan == FALSE) { |
| 2481 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); |
| 2482 } |
| 2483 break; |
| 2484 |
| 2485 case IW_MLME_AUTH: |
| 2486 /* fall through */ |
| 2487 case IW_MLME_ASSOC: |
| 2488 /* fall through */ |
| 2489 default: |
| 2490 up(&ar->arSem); |
| 2491 return -EOPNOTSUPP; |
| 2492 } |
| 2493 } |
| 2494 |
| 2495 up(&ar->arSem); |
| 2496 return 0; |
| 2497 } |
| 2498 #endif /* LINUX_VERSION_CODE */ |
| 2499 |
| 2500 /* |
| 2501 * SIOCGIWAPLIST |
| 2502 */ |
| 2503 int |
| 2504 ar6000_ioctl_iwaplist(struct net_device *dev, |
| 2505 struct iw_request_info *info, |
| 2506 struct iw_point *data, char *extra) |
| 2507 { |
| 2508 return -EIO; /* for now */ |
| 2509 } |
| 2510 |
| 2511 /* |
| 2512 * SIOCSIWSCAN |
| 2513 */ |
| 2514 int |
| 2515 ar6000_ioctl_siwscan(struct net_device *dev, |
| 2516 struct iw_request_info *info, |
| 2517 struct iw_point *data, char *extra) |
| 2518 { |
| 2519 #define ACT_DWELLTIME_DEFAULT 105 |
| 2520 #define HOME_TXDRAIN_TIME 100 |
| 2521 #define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT |
| 2522 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2523 int ret = 0; |
| 2524 |
| 2525 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2526 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2527 return -EOPNOTSUPP; |
| 2528 } |
| 2529 |
| 2530 if (ar->arWmiReady == FALSE) { |
| 2531 return -EIO; |
| 2532 } |
| 2533 |
| 2534 if (ar->arWlanState == WLAN_DISABLED) { |
| 2535 return -EIO; |
| 2536 } |
| 2537 |
| 2538 if (!ar->arUserBssFilter) { |
| 2539 if (wmi_bssfilter_cmd(ar->arWmi, (ar->arConnected ? ALL_BUT_BSS_FILTER :
ALL_BSS_FILTER), 0) != A_OK) { |
| 2540 return -EIO; |
| 2541 } |
| 2542 } |
| 2543 |
| 2544 if (ar->arConnected) { |
| 2545 if (wmi_get_stats_cmd(ar->arWmi) != A_OK) { |
| 2546 return -EIO; |
| 2547 } |
| 2548 } |
| 2549 |
| 2550 #ifdef ANDROID_ENV |
| 2551 #if WIRELESS_EXT >= 18 |
| 2552 if (data->pointer && (data->length == sizeof(struct iw_scan_req))) |
| 2553 { |
| 2554 if ((data->flags & IW_SCAN_THIS_ESSID) == IW_SCAN_THIS_ESSID) |
| 2555 { |
| 2556 struct iw_scan_req req; |
| 2557 if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req))) |
| 2558 return -EIO; |
| 2559 if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_l
en, req.essid) != A_OK) |
| 2560 return -EIO; |
| 2561 } |
| 2562 else |
| 2563 { |
| 2564 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) !=
A_OK) |
| 2565 return -EIO; |
| 2566 } |
| 2567 } |
| 2568 else |
| 2569 { |
| 2570 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK
) |
| 2571 return -EIO; |
| 2572 } |
| 2573 #endif |
| 2574 #endif |
| 2575 |
| 2576 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \ |
| 2577 0, 0, 0, NULL) != A_OK) { |
| 2578 ret = -EIO; |
| 2579 } |
| 2580 |
| 2581 return ret; |
| 2582 #undef ACT_DWELLTIME_DEFAULT |
| 2583 #undef HOME_TXDRAIN_TIME |
| 2584 #undef SCAN_INT |
| 2585 } |
| 2586 |
| 2587 |
| 2588 /* |
| 2589 * Units are in db above the noise floor. That means the |
| 2590 * rssi values reported in the tx/rx descriptors in the |
| 2591 * driver are the SNR expressed in db. |
| 2592 * |
| 2593 * If you assume that the noise floor is -95, which is an |
| 2594 * excellent assumption 99.5 % of the time, then you can |
| 2595 * derive the absolute signal level (i.e. -95 + rssi). |
| 2596 * There are some other slight factors to take into account |
| 2597 * depending on whether the rssi measurement is from 11b, |
| 2598 * 11g, or 11a. These differences are at most 2db and |
| 2599 * can be documented. |
| 2600 * |
| 2601 * NB: various calculations are based on the orinoco/wavelan |
| 2602 * drivers for compatibility |
| 2603 */ |
| 2604 static void |
| 2605 ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi) |
| 2606 { |
| 2607 if (rssi < 0) { |
| 2608 iq->qual = 0; |
| 2609 } else { |
| 2610 iq->qual = rssi; |
| 2611 } |
| 2612 |
| 2613 /* NB: max is 94 because noise is hardcoded to 161 */ |
| 2614 if (iq->qual > 94) |
| 2615 iq->qual = 94; |
| 2616 |
| 2617 iq->noise = 161; /* -95dBm */ |
| 2618 iq->level = iq->noise + iq->qual; |
| 2619 iq->updated = 7; |
| 2620 } |
| 2621 |
| 2622 |
| 2623 int |
| 2624 ar6000_ioctl_siwcommit(struct net_device *dev, |
| 2625 struct iw_request_info *info, |
| 2626 struct iw_point *data, char *extra) |
| 2627 { |
| 2628 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2629 |
| 2630 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) { |
| 2631 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd); |
| 2632 return -EOPNOTSUPP; |
| 2633 } |
| 2634 |
| 2635 if (ar->arWmiReady == FALSE) { |
| 2636 return -EIO; |
| 2637 } |
| 2638 |
| 2639 if (ar->arWlanState == WLAN_DISABLED) { |
| 2640 return -EIO; |
| 2641 } |
| 2642 |
| 2643 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AP: SSID %s freq %d authmode %d dot
11 auth %d"\ |
| 2644 " PW crypto %d GRP crypto %d\n", |
| 2645 ar->arSsid, ar->arChannelHint, |
| 2646 ar->arAuthMode, ar->arDot11AuthMode, |
| 2647 ar->arPairwiseCrypto, ar->arGroupCrypto)); |
| 2648 |
| 2649 ar6000_ap_mode_profile_commit(ar); |
| 2650 |
| 2651 /* if there is a profile switch from STA|IBSS mode to AP mode, |
| 2652 * update the host driver association state for the STA|IBSS mode. |
| 2653 */ |
| 2654 if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) { |
| 2655 ar->arConnectPending = FALSE; |
| 2656 ar->arConnected = FALSE; |
| 2657 /* Stop getting pkts from upper stack */ |
| 2658 netif_stop_queue(ar->arNetDev); |
| 2659 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); |
| 2660 ar->arBssChannel = 0; |
| 2661 ar->arBeaconInterval = 0; |
| 2662 |
| 2663 /* Flush the Tx queues */ |
| 2664 ar6000_TxDataCleanup(ar); |
| 2665 |
| 2666 /* Start getting pkts from upper stack */ |
| 2667 netif_wake_queue(ar->arNetDev); |
| 2668 } |
| 2669 |
| 2670 return 0; |
| 2671 } |
| 2672 |
| 2673 /* Structures to export the Wireless Handlers */ |
| 2674 static const iw_handler ath_handlers[] = { |
| 2675 (iw_handler) ar6000_ioctl_siwcommit, /* SIOCSIWCOMMIT */ |
| 2676 (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */ |
| 2677 (iw_handler) NULL, /* SIOCSIWNWID */ |
| 2678 (iw_handler) NULL, /* SIOCGIWNWID */ |
| 2679 (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */ |
| 2680 (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */ |
| 2681 (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */ |
| 2682 (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */ |
| 2683 (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */ |
| 2684 (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */ |
| 2685 (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */ |
| 2686 (iw_handler) ar6000_ioctl_giwrange, /* SIOCGIWRANGE */ |
| 2687 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ |
| 2688 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ |
| 2689 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ |
| 2690 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ |
| 2691 (iw_handler) NULL, /* SIOCSIWSPY */ |
| 2692 (iw_handler) NULL, /* SIOCGIWSPY */ |
| 2693 (iw_handler) NULL, /* SIOCSIWTHRSPY */ |
| 2694 (iw_handler) NULL, /* SIOCGIWTHRSPY */ |
| 2695 (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */ |
| 2696 (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */ |
| 2697 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) |
| 2698 (iw_handler) ar6000_ioctl_siwmlme, /* SIOCSIWMLME */ |
| 2699 #else |
| 2700 (iw_handler) NULL, /* -- hole -- */ |
| 2701 #endif /* LINUX_VERSION_CODE */ |
| 2702 (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */ |
| 2703 (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */ |
| 2704 (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */ |
| 2705 (iw_handler) ar6000_ioctl_siwessid, /* SIOCSIWESSID */ |
| 2706 (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */ |
| 2707 (iw_handler) NULL, /* SIOCSIWNICKN */ |
| 2708 (iw_handler) NULL, /* SIOCGIWNICKN */ |
| 2709 (iw_handler) NULL, /* -- hole -- */ |
| 2710 (iw_handler) NULL, /* -- hole -- */ |
| 2711 (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */ |
| 2712 (iw_handler) ar6000_ioctl_giwrate, /* SIOCGIWRATE */ |
| 2713 (iw_handler) NULL, /* SIOCSIWRTS */ |
| 2714 (iw_handler) NULL, /* SIOCGIWRTS */ |
| 2715 (iw_handler) NULL, /* SIOCSIWFRAG */ |
| 2716 (iw_handler) NULL, /* SIOCGIWFRAG */ |
| 2717 (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */ |
| 2718 (iw_handler) ar6000_ioctl_giwtxpow, /* SIOCGIWTXPOW */ |
| 2719 (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */ |
| 2720 (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */ |
| 2721 (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */ |
| 2722 (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */ |
| 2723 #if WIRELESS_EXT > 20 |
| 2724 (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */ |
| 2725 (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */ |
| 2726 #endif // WIRELESS_EXT > 20 |
| 2727 #if WIRELESS_EXT >= 18 |
| 2728 (iw_handler) NULL, /* -- hole -- */ |
| 2729 (iw_handler) NULL, /* -- hole -- */ |
| 2730 (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */ |
| 2731 (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */ |
| 2732 (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */ |
| 2733 (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */ |
| 2734 (iw_handler) ar6000_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ |
| 2735 (iw_handler) ar6000_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ |
| 2736 (iw_handler) ar6000_ioctl_siwpmksa, /* SIOCSIWPMKSA */ |
| 2737 #endif // WIRELESS_EXT >= 18 |
| 2738 }; |
| 2739 |
| 2740 struct iw_handler_def ath_iw_handler_def = { |
| 2741 .standard = (iw_handler *)ath_handlers, |
| 2742 .num_standard = ARRAY_SIZE(ath_handlers), |
| 2743 .private = NULL, |
| 2744 .num_private = 0, |
| 2745 }; |
OLD | NEW |