1/** 2 * This file contains ioctl functions 3 */ 4#include <linux/ctype.h> 5#include <linux/delay.h> 6#include <linux/if.h> 7#include <linux/if_arp.h> 8#include <linux/wireless.h> 9#include <linux/bitops.h> 10 11#include <net/ieee80211.h> 12#include <net/iw_handler.h> 13 14#include "host.h" 15#include "radiotap.h" 16#include "decl.h" 17#include "defs.h" 18#include "dev.h" 19#include "join.h" 20#include "wext.h" 21#include "assoc.h" 22 23 24/** 25 * the rates supported by the card 26 */ 27static u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] = 28 { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 29 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 30}; 31 32/** 33 * @brief Convert mw value to dbm value 34 * 35 * @param mw the value of mw 36 * @return the value of dbm 37 */ 38static int mw_to_dbm(int mw) 39{ 40 if (mw < 2) 41 return 0; 42 else if (mw < 3) 43 return 3; 44 else if (mw < 4) 45 return 5; 46 else if (mw < 6) 47 return 7; 48 else if (mw < 7) 49 return 8; 50 else if (mw < 8) 51 return 9; 52 else if (mw < 10) 53 return 10; 54 else if (mw < 13) 55 return 11; 56 else if (mw < 16) 57 return 12; 58 else if (mw < 20) 59 return 13; 60 else if (mw < 25) 61 return 14; 62 else if (mw < 32) 63 return 15; 64 else if (mw < 40) 65 return 16; 66 else if (mw < 50) 67 return 17; 68 else if (mw < 63) 69 return 18; 70 else if (mw < 79) 71 return 19; 72 else if (mw < 100) 73 return 20; 74 else 75 return 21; 76} 77 78/** 79 * @brief Find the channel frequency power info with specific channel 80 * 81 * @param adapter A pointer to wlan_adapter structure 82 * @param band it can be BAND_A, BAND_G or BAND_B 83 * @param channel the channel for looking 84 * @return A pointer to struct chan_freq_power structure or NULL if not find. 85 */ 86struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * adapter, 87 u8 band, u16 channel) 88{ 89 struct chan_freq_power *cfp = NULL; 90 struct region_channel *rc; 91 int count = sizeof(adapter->region_channel) / 92 sizeof(adapter->region_channel[0]); 93 int i, j; 94 95 for (j = 0; !cfp && (j < count); j++) { 96 rc = &adapter->region_channel[j]; 97 98 if (adapter->enable11d) 99 rc = &adapter->universal_channel[j]; 100 if (!rc->valid || !rc->CFP) 101 continue; 102 if (rc->band != band) 103 continue; 104 for (i = 0; i < rc->nrcfp; i++) { 105 if (rc->CFP[i].channel == channel) { 106 cfp = &rc->CFP[i]; 107 break; 108 } 109 } 110 } 111 112 if (!cfp && channel) 113 lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find " 114 "cfp by band %d / channel %d\n", band, channel); 115 116 return cfp; 117} 118 119/** 120 * @brief Find the channel frequency power info with specific frequency 121 * 122 * @param adapter A pointer to wlan_adapter structure 123 * @param band it can be BAND_A, BAND_G or BAND_B 124 * @param freq the frequency for looking 125 * @return A pointer to struct chan_freq_power structure or NULL if not find. 126 */ 127static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter, 128 u8 band, u32 freq) 129{ 130 struct chan_freq_power *cfp = NULL; 131 struct region_channel *rc; 132 int count = sizeof(adapter->region_channel) / 133 sizeof(adapter->region_channel[0]); 134 int i, j; 135 136 for (j = 0; !cfp && (j < count); j++) { 137 rc = &adapter->region_channel[j]; 138 139 if (adapter->enable11d) 140 rc = &adapter->universal_channel[j]; 141 if (!rc->valid || !rc->CFP) 142 continue; 143 if (rc->band != band) 144 continue; 145 for (i = 0; i < rc->nrcfp; i++) { 146 if (rc->CFP[i].freq == freq) { 147 cfp = &rc->CFP[i]; 148 break; 149 } 150 } 151 } 152 153 if (!cfp && freq) 154 lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by " 155 "band %d / freq %d\n", band, freq); 156 157 return cfp; 158} 159 160 161/** 162 * @brief Set Radio On/OFF 163 * 164 * @param priv A pointer to wlan_private structure 165 * @option Radio Option 166 * @return 0 --success, otherwise fail 167 */ 168int wlan_radio_ioctl(wlan_private * priv, u8 option) 169{ 170 int ret = 0; 171 wlan_adapter *adapter = priv->adapter; 172 173 lbs_deb_enter(LBS_DEB_WEXT); 174 175 if (adapter->radioon != option) { 176 lbs_deb_wext("switching radio %s\n", option ? "on" : "off"); 177 adapter->radioon = option; 178 179 ret = libertas_prepare_and_send_command(priv, 180 cmd_802_11_radio_control, 181 cmd_act_set, 182 cmd_option_waitforrsp, 0, NULL); 183 } 184 185 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 186 return ret; 187} 188 189/** 190 * @brief Copy rates 191 * 192 * @param dest A pointer to Dest Buf 193 * @param src A pointer to Src Buf 194 * @param len The len of Src Buf 195 * @return Number of rates copyed 196 */ 197static inline int copyrates(u8 * dest, int pos, u8 * src, int len) 198{ 199 int i; 200 201 for (i = 0; i < len && src[i]; i++, pos++) { 202 if (pos >= sizeof(u8) * WLAN_SUPPORTED_RATES) 203 break; 204 dest[pos] = src[i]; 205 } 206 207 return pos; 208} 209 210/** 211 * @brief Get active data rates 212 * 213 * @param adapter A pointer to wlan_adapter structure 214 * @param rate The buf to return the active rates 215 * @return The number of rates 216 */ 217static int get_active_data_rates(wlan_adapter * adapter, 218 u8* rates) 219{ 220 int k = 0; 221 222 lbs_deb_enter(LBS_DEB_WEXT); 223 224 if (adapter->connect_status != libertas_connected) { 225 if (adapter->mode == IW_MODE_INFRA) { 226 lbs_deb_wext("infra\n"); 227 k = copyrates(rates, k, libertas_supported_rates, 228 sizeof(libertas_supported_rates)); 229 } else { 230 lbs_deb_wext("Adhoc G\n"); 231 k = copyrates(rates, k, libertas_adhoc_rates_g, 232 sizeof(libertas_adhoc_rates_g)); 233 } 234 } else { 235 k = copyrates(rates, 0, adapter->curbssparams.datarates, 236 adapter->curbssparams.numofrates); 237 } 238 239 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", k); 240 return k; 241} 242 243static int wlan_get_name(struct net_device *dev, struct iw_request_info *info, 244 char *cwrq, char *extra) 245{ 246 const char *cp; 247 char comm[6] = { "COMM-" }; 248 char mrvl[6] = { "MRVL-" }; 249 int cnt; 250 251 lbs_deb_enter(LBS_DEB_WEXT); 252 253 strcpy(cwrq, mrvl); 254 255 cp = strstr(libertas_driver_version, comm); 256 if (cp == libertas_driver_version) //skip leading "COMM-" 257 cp = libertas_driver_version + strlen(comm); 258 else 259 cp = libertas_driver_version; 260 261 cnt = strlen(mrvl); 262 cwrq += cnt; 263 while (cnt < 16 && (*cp != '-')) { 264 *cwrq++ = toupper(*cp++); 265 cnt++; 266 } 267 *cwrq = '\0'; 268 269 lbs_deb_leave(LBS_DEB_WEXT); 270 return 0; 271} 272 273static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info, 274 struct iw_freq *fwrq, char *extra) 275{ 276 wlan_private *priv = dev->priv; 277 wlan_adapter *adapter = priv->adapter; 278 struct chan_freq_power *cfp; 279 280 lbs_deb_enter(LBS_DEB_WEXT); 281 282 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, 283 adapter->curbssparams.channel); 284 285 if (!cfp) { 286 if (adapter->curbssparams.channel) 287 lbs_deb_wext("invalid channel %d\n", 288 adapter->curbssparams.channel); 289 return -EINVAL; 290 } 291 292 fwrq->m = (long)cfp->freq * 100000; 293 fwrq->e = 1; 294 295 lbs_deb_wext("freq %u\n", fwrq->m); 296 lbs_deb_leave(LBS_DEB_WEXT); 297 return 0; 298} 299 300static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info, 301 struct sockaddr *awrq, char *extra) 302{ 303 wlan_private *priv = dev->priv; 304 wlan_adapter *adapter = priv->adapter; 305 306 lbs_deb_enter(LBS_DEB_WEXT); 307 308 if (adapter->connect_status == libertas_connected) { 309 memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN); 310 } else { 311 memset(awrq->sa_data, 0, ETH_ALEN); 312 } 313 awrq->sa_family = ARPHRD_ETHER; 314 315 lbs_deb_leave(LBS_DEB_WEXT); 316 return 0; 317} 318 319static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info, 320 struct iw_point *dwrq, char *extra) 321{ 322 wlan_private *priv = dev->priv; 323 wlan_adapter *adapter = priv->adapter; 324 325 lbs_deb_enter(LBS_DEB_WEXT); 326 327 /* 328 * Check the size of the string 329 */ 330 331 if (dwrq->length > 16) { 332 return -E2BIG; 333 } 334 335 mutex_lock(&adapter->lock); 336 memset(adapter->nodename, 0, sizeof(adapter->nodename)); 337 memcpy(adapter->nodename, extra, dwrq->length); 338 mutex_unlock(&adapter->lock); 339 340 lbs_deb_leave(LBS_DEB_WEXT); 341 return 0; 342} 343 344static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info, 345 struct iw_point *dwrq, char *extra) 346{ 347 wlan_private *priv = dev->priv; 348 wlan_adapter *adapter = priv->adapter; 349 350 lbs_deb_enter(LBS_DEB_WEXT); 351 352 /* 353 * Get the Nick Name saved 354 */ 355 356 mutex_lock(&adapter->lock); 357 strncpy(extra, adapter->nodename, 16); 358 mutex_unlock(&adapter->lock); 359 360 extra[16] = '\0'; 361 362 /* 363 * If none, we may want to get the one that was set 364 */ 365 366 /* 367 * Push it out ! 368 */ 369 dwrq->length = strlen(extra) + 1; 370 371 lbs_deb_leave(LBS_DEB_WEXT); 372 return 0; 373} 374 375static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, 376 struct iw_point *dwrq, char *extra) 377{ 378 wlan_private *priv = dev->priv; 379 wlan_adapter *adapter = priv->adapter; 380 381 lbs_deb_enter(LBS_DEB_WEXT); 382 383 /* Use nickname to indicate that mesh is on */ 384 385 if (adapter->connect_status == libertas_connected) { 386 strncpy(extra, "Mesh", 12); 387 extra[12] = '\0'; 388 dwrq->length = strlen(extra) + 1; 389 } 390 391 else { 392 extra[0] = '\0'; 393 dwrq->length = 1 ; 394 } 395 396 lbs_deb_leave(LBS_DEB_WEXT); 397 return 0; 398} 399static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info, 400 struct iw_param *vwrq, char *extra) 401{ 402 int ret = 0; 403 wlan_private *priv = dev->priv; 404 wlan_adapter *adapter = priv->adapter; 405 u32 rthr = vwrq->value; 406 407 lbs_deb_enter(LBS_DEB_WEXT); 408 409 if (vwrq->disabled) { 410 adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE; 411 } else { 412 if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE) 413 return -EINVAL; 414 adapter->rtsthsd = rthr; 415 } 416 417 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, 418 cmd_act_set, cmd_option_waitforrsp, 419 OID_802_11_RTS_THRESHOLD, &rthr); 420 421 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 422 return ret; 423} 424 425static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info, 426 struct iw_param *vwrq, char *extra) 427{ 428 int ret = 0; 429 wlan_private *priv = dev->priv; 430 wlan_adapter *adapter = priv->adapter; 431 432 lbs_deb_enter(LBS_DEB_WEXT); 433 434 adapter->rtsthsd = 0; 435 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, 436 cmd_act_get, cmd_option_waitforrsp, 437 OID_802_11_RTS_THRESHOLD, NULL); 438 if (ret) 439 goto out; 440 441 vwrq->value = adapter->rtsthsd; 442 vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE) 443 || (vwrq->value > MRVDRV_RTS_MAX_VALUE)); 444 vwrq->fixed = 1; 445 446out: 447 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 448 return ret; 449} 450 451static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info, 452 struct iw_param *vwrq, char *extra) 453{ 454 int ret = 0; 455 u32 fthr = vwrq->value; 456 wlan_private *priv = dev->priv; 457 wlan_adapter *adapter = priv->adapter; 458 459 lbs_deb_enter(LBS_DEB_WEXT); 460 461 if (vwrq->disabled) { 462 adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE; 463 } else { 464 if (fthr < MRVDRV_FRAG_MIN_VALUE 465 || fthr > MRVDRV_FRAG_MAX_VALUE) 466 return -EINVAL; 467 adapter->fragthsd = fthr; 468 } 469 470 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, 471 cmd_act_set, cmd_option_waitforrsp, 472 OID_802_11_FRAGMENTATION_THRESHOLD, &fthr); 473 474 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 475 return ret; 476} 477 478static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info, 479 struct iw_param *vwrq, char *extra) 480{ 481 int ret = 0; 482 wlan_private *priv = dev->priv; 483 wlan_adapter *adapter = priv->adapter; 484 485 lbs_deb_enter(LBS_DEB_WEXT); 486 487 adapter->fragthsd = 0; 488 ret = libertas_prepare_and_send_command(priv, 489 cmd_802_11_snmp_mib, 490 cmd_act_get, cmd_option_waitforrsp, 491 OID_802_11_FRAGMENTATION_THRESHOLD, NULL); 492 if (ret) 493 goto out; 494 495 vwrq->value = adapter->fragthsd; 496 vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE) 497 || (vwrq->value > MRVDRV_FRAG_MAX_VALUE)); 498 vwrq->fixed = 1; 499 500out: 501 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 502 return ret; 503} 504 505static int wlan_get_mode(struct net_device *dev, 506 struct iw_request_info *info, u32 * uwrq, char *extra) 507{ 508 wlan_private *priv = dev->priv; 509 wlan_adapter *adapter = priv->adapter; 510 511 lbs_deb_enter(LBS_DEB_WEXT); 512 513 *uwrq = adapter->mode; 514 515 lbs_deb_leave(LBS_DEB_WEXT); 516 return 0; 517} 518 519static int mesh_wlan_get_mode(struct net_device *dev, 520 struct iw_request_info *info, u32 * uwrq, 521 char *extra) 522{ 523 lbs_deb_enter(LBS_DEB_WEXT); 524 525 *uwrq = IW_MODE_REPEAT ; 526 527 lbs_deb_leave(LBS_DEB_WEXT); 528 return 0; 529} 530 531static int wlan_get_txpow(struct net_device *dev, 532 struct iw_request_info *info, 533 struct iw_param *vwrq, char *extra) 534{ 535 int ret = 0; 536 wlan_private *priv = dev->priv; 537 wlan_adapter *adapter = priv->adapter; 538 539 lbs_deb_enter(LBS_DEB_WEXT); 540 541 ret = libertas_prepare_and_send_command(priv, 542 cmd_802_11_rf_tx_power, 543 cmd_act_tx_power_opt_get, 544 cmd_option_waitforrsp, 0, NULL); 545 546 if (ret) 547 goto out; 548 549 lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel); 550 vwrq->value = adapter->txpowerlevel; 551 vwrq->fixed = 1; 552 if (adapter->radioon) { 553 vwrq->disabled = 0; 554 vwrq->flags = IW_TXPOW_DBM; 555 } else { 556 vwrq->disabled = 1; 557 } 558 559out: 560 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 561 return ret; 562} 563 564static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info, 565 struct iw_param *vwrq, char *extra) 566{ 567 int ret = 0; 568 wlan_private *priv = dev->priv; 569 wlan_adapter *adapter = priv->adapter; 570 571 lbs_deb_enter(LBS_DEB_WEXT); 572 573 if (vwrq->flags == IW_RETRY_LIMIT) { 574 /* The MAC has a 4-bit Total_Tx_Count register 575 Total_Tx_Count = 1 + Tx_Retry_Count */ 576#define TX_RETRY_MIN 0 577#define TX_RETRY_MAX 14 578 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX) 579 return -EINVAL; 580 581 /* Adding 1 to convert retry count to try count */ 582 adapter->txretrycount = vwrq->value + 1; 583 584 ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, 585 cmd_act_set, 586 cmd_option_waitforrsp, 587 OID_802_11_TX_RETRYCOUNT, NULL); 588 589 if (ret) 590 goto out; 591 } else { 592 return -EOPNOTSUPP; 593 } 594 595out: 596 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 597 return ret; 598} 599 600static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info, 601 struct iw_param *vwrq, char *extra) 602{ 603 wlan_private *priv = dev->priv; 604 wlan_adapter *adapter = priv->adapter; 605 int ret = 0; 606 607 lbs_deb_enter(LBS_DEB_WEXT); 608 609 adapter->txretrycount = 0; 610 ret = libertas_prepare_and_send_command(priv, 611 cmd_802_11_snmp_mib, 612 cmd_act_get, cmd_option_waitforrsp, 613 OID_802_11_TX_RETRYCOUNT, NULL); 614 if (ret) 615 goto out; 616 617 vwrq->disabled = 0; 618 if (!vwrq->flags) { 619 vwrq->flags = IW_RETRY_LIMIT; 620 /* Subtract 1 to convert try count to retry count */ 621 vwrq->value = adapter->txretrycount - 1; 622 } 623 624out: 625 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 626 return ret; 627} 628 629static inline void sort_channels(struct iw_freq *freq, int num) 630{ 631 int i, j; 632 struct iw_freq temp; 633 634 for (i = 0; i < num; i++) 635 for (j = i + 1; j < num; j++) 636 if (freq[i].i > freq[j].i) { 637 temp.i = freq[i].i; 638 temp.m = freq[i].m; 639 640 freq[i].i = freq[j].i; 641 freq[i].m = freq[j].m; 642 643 freq[j].i = temp.i; 644 freq[j].m = temp.m; 645 } 646} 647 648/* data rate listing 649 MULTI_BANDS: 650 abg a b b/g 651 Infra G(12) A(8) B(4) G(12) 652 Adhoc A+B(12) A(8) B(4) B(4) 653 654 non-MULTI_BANDS: 655 b b/g 656 Infra B(4) G(12) 657 Adhoc B(4) B(4) 658 */ 659/** 660 * @brief Get Range Info 661 * 662 * @param dev A pointer to net_device structure 663 * @param info A pointer to iw_request_info structure 664 * @param vwrq A pointer to iw_param structure 665 * @param extra A pointer to extra data buf 666 * @return 0 --success, otherwise fail 667 */ 668static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, 669 struct iw_point *dwrq, char *extra) 670{ 671 int i, j; 672 wlan_private *priv = dev->priv; 673 wlan_adapter *adapter = priv->adapter; 674 struct iw_range *range = (struct iw_range *)extra; 675 struct chan_freq_power *cfp; 676 u8 rates[WLAN_SUPPORTED_RATES]; 677 678 u8 flag = 0; 679 680 lbs_deb_enter(LBS_DEB_WEXT); 681 682 dwrq->length = sizeof(struct iw_range); 683 memset(range, 0, sizeof(struct iw_range)); 684 685 range->min_nwid = 0; 686 range->max_nwid = 0; 687 688 memset(rates, 0, sizeof(rates)); 689 range->num_bitrates = get_active_data_rates(adapter, rates); 690 691 for (i = 0; i < min_t(__u8, range->num_bitrates, IW_MAX_BITRATES) && rates[i]; 692 i++) { 693 range->bitrate[i] = (rates[i] & 0x7f) * 500000; 694 } 695 range->num_bitrates = i; 696 lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES, 697 range->num_bitrates); 698 699 range->num_frequency = 0; 700 if (priv->adapter->enable11d && 701 adapter->connect_status == libertas_connected) { 702 u8 chan_no; 703 u8 band; 704 705 struct parsed_region_chan_11d *parsed_region_chan = 706 &adapter->parsed_region_chan; 707 708 if (parsed_region_chan == NULL) { 709 lbs_deb_wext("11d: parsed_region_chan is NULL\n"); 710 goto out; 711 } 712 band = parsed_region_chan->band; 713 lbs_deb_wext("band %d, nr_char %d\n", band, 714 parsed_region_chan->nr_chan); 715 716 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) 717 && (i < parsed_region_chan->nr_chan); i++) { 718 chan_no = parsed_region_chan->chanpwr[i].chan; 719 lbs_deb_wext("chan_no %d\n", chan_no); 720 range->freq[range->num_frequency].i = (long)chan_no; 721 range->freq[range->num_frequency].m = 722 (long)libertas_chan_2_freq(chan_no, band) * 100000; 723 range->freq[range->num_frequency].e = 1; 724 range->num_frequency++; 725 } 726 flag = 1; 727 } 728 if (!flag) { 729 for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) 730 && (j < sizeof(adapter->region_channel) 731 / sizeof(adapter->region_channel[0])); j++) { 732 cfp = adapter->region_channel[j].CFP; 733 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) 734 && adapter->region_channel[j].valid 735 && cfp 736 && (i < adapter->region_channel[j].nrcfp); i++) { 737 range->freq[range->num_frequency].i = 738 (long)cfp->channel; 739 range->freq[range->num_frequency].m = 740 (long)cfp->freq * 100000; 741 range->freq[range->num_frequency].e = 1; 742 cfp++; 743 range->num_frequency++; 744 } 745 } 746 } 747 748 lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", 749 IW_MAX_FREQUENCIES, range->num_frequency); 750 751 range->num_channels = range->num_frequency; 752 753 sort_channels(&range->freq[0], range->num_frequency); 754 755 /* 756 * Set an indication of the max TCP throughput in bit/s that we can 757 * expect using this interface 758 */ 759 if (i > 2) 760 range->throughput = 5000 * 1000; 761 else 762 range->throughput = 1500 * 1000; 763 764 range->min_rts = MRVDRV_RTS_MIN_VALUE; 765 range->max_rts = MRVDRV_RTS_MAX_VALUE; 766 range->min_frag = MRVDRV_FRAG_MIN_VALUE; 767 range->max_frag = MRVDRV_FRAG_MAX_VALUE; 768 769 range->encoding_size[0] = 5; 770 range->encoding_size[1] = 13; 771 range->num_encoding_sizes = 2; 772 range->max_encoding_tokens = 4; 773 774 range->min_pmp = 1000000; 775 range->max_pmp = 120000000; 776 range->min_pmt = 1000; 777 range->max_pmt = 1000000; 778 range->pmp_flags = IW_POWER_PERIOD; 779 range->pmt_flags = IW_POWER_TIMEOUT; 780 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; 781 782 /* 783 * Minimum version we recommend 784 */ 785 range->we_version_source = 15; 786 787 /* 788 * Version we are compiled with 789 */ 790 range->we_version_compiled = WIRELESS_EXT; 791 792 range->retry_capa = IW_RETRY_LIMIT; 793 range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX; 794 795 range->min_retry = TX_RETRY_MIN; 796 range->max_retry = TX_RETRY_MAX; 797 798 /* 799 * Set the qual, level and noise range values 800 */ 801 range->max_qual.qual = 100; 802 range->max_qual.level = 0; 803 range->max_qual.noise = 0; 804 range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 805 806 range->avg_qual.qual = 70; 807 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ 808 range->avg_qual.level = 0; 809 range->avg_qual.noise = 0; 810 range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 811 812 range->sensitivity = 0; 813 814 /* 815 * Setup the supported power level ranges 816 */ 817 memset(range->txpower, 0, sizeof(range->txpower)); 818 range->txpower[0] = 5; 819 range->txpower[1] = 7; 820 range->txpower[2] = 9; 821 range->txpower[3] = 11; 822 range->txpower[4] = 13; 823 range->txpower[5] = 15; 824 range->txpower[6] = 17; 825 range->txpower[7] = 19; 826 827 range->num_txpower = 8; 828 range->txpower_capa = IW_TXPOW_DBM; 829 range->txpower_capa |= IW_TXPOW_RANGE; 830 831 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | 832 IW_EVENT_CAPA_MASK(SIOCGIWAP) | 833 IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); 834 range->event_capa[1] = IW_EVENT_CAPA_K_1; 835 836 if (adapter->fwcapinfo & FW_CAPINFO_WPA) { 837 range->enc_capa = IW_ENC_CAPA_WPA 838 | IW_ENC_CAPA_WPA2 839 | IW_ENC_CAPA_CIPHER_TKIP 840 | IW_ENC_CAPA_CIPHER_CCMP; 841 } 842 843out: 844 lbs_deb_leave(LBS_DEB_WEXT); 845 return 0; 846} 847 848static int wlan_set_power(struct net_device *dev, struct iw_request_info *info, 849 struct iw_param *vwrq, char *extra) 850{ 851 wlan_private *priv = dev->priv; 852 wlan_adapter *adapter = priv->adapter; 853 854 lbs_deb_enter(LBS_DEB_WEXT); 855 856 /* PS is currently supported only in Infrastructure mode 857 * Remove this check if it is to be supported in IBSS mode also 858 */ 859 860 if (vwrq->disabled) { 861 adapter->psmode = wlan802_11powermodecam; 862 if (adapter->psstate != PS_STATE_FULL_POWER) { 863 libertas_ps_wakeup(priv, cmd_option_waitforrsp); 864 } 865 866 return 0; 867 } 868 869 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { 870 lbs_deb_wext( 871 "setting power timeout is not supported\n"); 872 return -EINVAL; 873 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { 874 lbs_deb_wext("setting power period not supported\n"); 875 return -EINVAL; 876 } 877 878 if (adapter->psmode != wlan802_11powermodecam) { 879 return 0; 880 } 881 882 adapter->psmode = wlan802_11powermodemax_psp; 883 884 if (adapter->connect_status == libertas_connected) { 885 libertas_ps_sleep(priv, cmd_option_waitforrsp); 886 } 887 888 lbs_deb_leave(LBS_DEB_WEXT); 889 return 0; 890} 891 892static int wlan_get_power(struct net_device *dev, struct iw_request_info *info, 893 struct iw_param *vwrq, char *extra) 894{ 895 wlan_private *priv = dev->priv; 896 wlan_adapter *adapter = priv->adapter; 897 int mode; 898 899 lbs_deb_enter(LBS_DEB_WEXT); 900 901 mode = adapter->psmode; 902 903 if ((vwrq->disabled = (mode == wlan802_11powermodecam)) 904 || adapter->connect_status == libertas_disconnected) 905 { 906 goto out; 907 } 908 909 vwrq->value = 0; 910 911out: 912 lbs_deb_leave(LBS_DEB_WEXT); 913 return 0; 914} 915 916static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) 917{ 918 enum { 919 POOR = 30, 920 FAIR = 60, 921 GOOD = 80, 922 VERY_GOOD = 90, 923 EXCELLENT = 95, 924 PERFECT = 100 925 }; 926 wlan_private *priv = dev->priv; 927 wlan_adapter *adapter = priv->adapter; 928 u32 rssi_qual; 929 u32 tx_qual; 930 u32 quality = 0; 931 int stats_valid = 0; 932 u8 rssi; 933 u32 tx_retries; 934 935 lbs_deb_enter(LBS_DEB_WEXT); 936 937 priv->wstats.status = adapter->mode; 938 939 /* If we're not associated, all quality values are meaningless */ 940 if (adapter->connect_status != libertas_connected) 941 goto out; 942 943 /* Quality by RSSI */ 944 priv->wstats.qual.level = 945 CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG], 946 adapter->NF[TYPE_BEACON][TYPE_NOAVG]); 947 948 if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { 949 priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; 950 } else { 951 priv->wstats.qual.noise = 952 CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); 953 } 954 955 lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level); 956 lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise); 957 958 rssi = priv->wstats.qual.level - priv->wstats.qual.noise; 959 if (rssi < 15) 960 rssi_qual = rssi * POOR / 10; 961 else if (rssi < 20) 962 rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR; 963 else if (rssi < 30) 964 rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR; 965 else if (rssi < 40) 966 rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) / 967 10 + GOOD; 968 else 969 rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) / 970 10 + VERY_GOOD; 971 quality = rssi_qual; 972 973 /* Quality by TX errors */ 974 priv->wstats.discard.retries = priv->stats.tx_errors; 975 976 tx_retries = le16_to_cpu(adapter->logmsg.retry); 977 978 if (tx_retries > 75) 979 tx_qual = (90 - tx_retries) * POOR / 15; 980 else if (tx_retries > 70) 981 tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR; 982 else if (tx_retries > 65) 983 tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; 984 else if (tx_retries > 50) 985 tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / 986 15 + GOOD; 987 else 988 tx_qual = (50 - tx_retries) * 989 (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; 990 quality = min(quality, tx_qual); 991 992 priv->wstats.discard.code = le16_to_cpu(adapter->logmsg.wepundecryptable); 993 priv->wstats.discard.fragment = le16_to_cpu(adapter->logmsg.rxfrag); 994 priv->wstats.discard.retries = tx_retries; 995 priv->wstats.discard.misc = le16_to_cpu(adapter->logmsg.ackfailure); 996 997 /* Calculate quality */ 998 priv->wstats.qual.qual = max(quality, (u32)100); 999 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 1000 stats_valid = 1; 1001 1002 /* update stats asynchronously for future calls */ 1003 libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0, 1004 0, 0, NULL); 1005 libertas_prepare_and_send_command(priv, cmd_802_11_get_log, 0, 1006 0, 0, NULL); 1007out: 1008 if (!stats_valid) { 1009 priv->wstats.miss.beacon = 0; 1010 priv->wstats.discard.retries = 0; 1011 priv->wstats.qual.qual = 0; 1012 priv->wstats.qual.level = 0; 1013 priv->wstats.qual.noise = 0; 1014 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED; 1015 priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID | 1016 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; 1017 } 1018 1019 lbs_deb_leave(LBS_DEB_WEXT); 1020 return &priv->wstats; 1021 1022 1023} 1024 1025static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, 1026 struct iw_freq *fwrq, char *extra) 1027{ 1028 int ret = -EINVAL; 1029 wlan_private *priv = dev->priv; 1030 wlan_adapter *adapter = priv->adapter; 1031 struct chan_freq_power *cfp; 1032 struct assoc_request * assoc_req; 1033 1034 lbs_deb_enter(LBS_DEB_WEXT); 1035 1036 mutex_lock(&adapter->lock); 1037 assoc_req = wlan_get_association_request(adapter); 1038 if (!assoc_req) { 1039 ret = -ENOMEM; 1040 goto out; 1041 } 1042 1043 /* If setting by frequency, convert to a channel */ 1044 if (fwrq->e == 1) { 1045 long f = fwrq->m / 100000; 1046 1047 cfp = find_cfp_by_band_and_freq(adapter, 0, f); 1048 if (!cfp) { 1049 lbs_deb_wext("invalid freq %ld\n", f); 1050 goto out; 1051 } 1052 1053 fwrq->e = 0; 1054 fwrq->m = (int) cfp->channel; 1055 } 1056 1057 /* Setting by channel number */ 1058 if (fwrq->m > 1000 || fwrq->e > 0) { 1059 goto out; 1060 } 1061 1062 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m); 1063 if (!cfp) { 1064 goto out; 1065 } 1066 1067 assoc_req->channel = fwrq->m; 1068 ret = 0; 1069 1070out: 1071 if (ret == 0) { 1072 set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags); 1073 wlan_postpone_association_work(priv); 1074 } else { 1075 wlan_cancel_association_work(priv); 1076 } 1077 mutex_unlock(&adapter->lock); 1078 1079 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1080 return ret; 1081} 1082 1083/** 1084 * @brief use index to get the data rate 1085 * 1086 * @param index The index of data rate 1087 * @return data rate or 0 1088 */ 1089u32 libertas_index_to_data_rate(u8 index) 1090{ 1091 if (index >= sizeof(libertas_wlan_data_rates)) 1092 index = 0; 1093 1094 return libertas_wlan_data_rates[index]; 1095} 1096 1097/** 1098 * @brief use rate to get the index 1099 * 1100 * @param rate data rate 1101 * @return index or 0 1102 */ 1103u8 libertas_data_rate_to_index(u32 rate) 1104{ 1105 u8 *ptr; 1106 1107 if (rate) 1108 if ((ptr = memchr(libertas_wlan_data_rates, (u8) rate, 1109 sizeof(libertas_wlan_data_rates)))) 1110 return (ptr - libertas_wlan_data_rates); 1111 1112 return 0; 1113} 1114 1115static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info, 1116 struct iw_param *vwrq, char *extra) 1117{ 1118 wlan_private *priv = dev->priv; 1119 wlan_adapter *adapter = priv->adapter; 1120 u32 data_rate; 1121 u16 action; 1122 int ret = 0; 1123 u8 rates[WLAN_SUPPORTED_RATES]; 1124 u8 *rate; 1125 1126 lbs_deb_enter(LBS_DEB_WEXT); 1127 1128 lbs_deb_wext("vwrq->value %d\n", vwrq->value); 1129 1130 if (vwrq->value == -1) { 1131 action = cmd_act_set_tx_auto; // Auto 1132 adapter->is_datarate_auto = 1; 1133 adapter->datarate = 0; 1134 } else { 1135 if (vwrq->value % 100000) { 1136 return -EINVAL; 1137 } 1138 1139 data_rate = vwrq->value / 500000; 1140 1141 memset(rates, 0, sizeof(rates)); 1142 get_active_data_rates(adapter, rates); 1143 rate = rates; 1144 while (*rate) { 1145 lbs_deb_wext("rate=0x%X, wanted data_rate 0x%X\n", *rate, 1146 data_rate); 1147 if ((*rate & 0x7f) == (data_rate & 0x7f)) 1148 break; 1149 rate++; 1150 } 1151 if (!*rate) { 1152 lbs_pr_alert("fixed data rate 0x%X out " 1153 "of range\n", data_rate); 1154 return -EINVAL; 1155 } 1156 1157 adapter->datarate = data_rate; 1158 action = cmd_act_set_tx_fix_rate; 1159 adapter->is_datarate_auto = 0; 1160 } 1161 1162 ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate, 1163 action, cmd_option_waitforrsp, 0, NULL); 1164 1165 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1166 return ret; 1167} 1168 1169static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info, 1170 struct iw_param *vwrq, char *extra) 1171{ 1172 wlan_private *priv = dev->priv; 1173 wlan_adapter *adapter = priv->adapter; 1174 1175 lbs_deb_enter(LBS_DEB_WEXT); 1176 1177 if (adapter->is_datarate_auto) { 1178 vwrq->fixed = 0; 1179 } else { 1180 vwrq->fixed = 1; 1181 } 1182 1183 vwrq->value = adapter->datarate * 500000; 1184 1185 lbs_deb_leave(LBS_DEB_WEXT); 1186 return 0; 1187} 1188 1189static int wlan_set_mode(struct net_device *dev, 1190 struct iw_request_info *info, u32 * uwrq, char *extra) 1191{ 1192 int ret = 0; 1193 wlan_private *priv = dev->priv; 1194 wlan_adapter *adapter = priv->adapter; 1195 struct assoc_request * assoc_req; 1196 1197 lbs_deb_enter(LBS_DEB_WEXT); 1198 1199 if ( (*uwrq != IW_MODE_ADHOC) 1200 && (*uwrq != IW_MODE_INFRA) 1201 && (*uwrq != IW_MODE_AUTO)) { 1202 lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq); 1203 ret = -EINVAL; 1204 goto out; 1205 } 1206 1207 mutex_lock(&adapter->lock); 1208 assoc_req = wlan_get_association_request(adapter); 1209 if (!assoc_req) { 1210 ret = -ENOMEM; 1211 wlan_cancel_association_work(priv); 1212 } else { 1213 assoc_req->mode = *uwrq; 1214 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); 1215 wlan_postpone_association_work(priv); 1216 lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq); 1217 } 1218 mutex_unlock(&adapter->lock); 1219 1220out: 1221 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1222 return ret; 1223} 1224 1225 1226/** 1227 * @brief Get Encryption key 1228 * 1229 * @param dev A pointer to net_device structure 1230 * @param info A pointer to iw_request_info structure 1231 * @param vwrq A pointer to iw_param structure 1232 * @param extra A pointer to extra data buf 1233 * @return 0 --success, otherwise fail 1234 */ 1235static int wlan_get_encode(struct net_device *dev, 1236 struct iw_request_info *info, 1237 struct iw_point *dwrq, u8 * extra) 1238{ 1239 wlan_private *priv = dev->priv; 1240 wlan_adapter *adapter = priv->adapter; 1241 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; 1242 1243 lbs_deb_enter(LBS_DEB_WEXT); 1244 1245 lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n", 1246 dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx); 1247 1248 dwrq->flags = 0; 1249 1250 /* Authentication method */ 1251 switch (adapter->secinfo.auth_mode) { 1252 case IW_AUTH_ALG_OPEN_SYSTEM: 1253 dwrq->flags = IW_ENCODE_OPEN; 1254 break; 1255 1256 case IW_AUTH_ALG_SHARED_KEY: 1257 case IW_AUTH_ALG_LEAP: 1258 dwrq->flags = IW_ENCODE_RESTRICTED; 1259 break; 1260 default: 1261 dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN; 1262 break; 1263 } 1264 1265 if ( adapter->secinfo.wep_enabled 1266 || adapter->secinfo.WPAenabled 1267 || adapter->secinfo.WPA2enabled) { 1268 dwrq->flags &= ~IW_ENCODE_DISABLED; 1269 } else { 1270 dwrq->flags |= IW_ENCODE_DISABLED; 1271 } 1272 1273 memset(extra, 0, 16); 1274 1275 mutex_lock(&adapter->lock); 1276 1277 /* Default to returning current transmit key */ 1278 if (index < 0) 1279 index = adapter->wep_tx_keyidx; 1280 1281 if ((adapter->wep_keys[index].len) && adapter->secinfo.wep_enabled) { 1282 memcpy(extra, adapter->wep_keys[index].key, 1283 adapter->wep_keys[index].len); 1284 dwrq->length = adapter->wep_keys[index].len; 1285 1286 dwrq->flags |= (index + 1); 1287 /* Return WEP enabled */ 1288 dwrq->flags &= ~IW_ENCODE_DISABLED; 1289 } else if ((adapter->secinfo.WPAenabled) 1290 || (adapter->secinfo.WPA2enabled)) { 1291 /* return WPA enabled */ 1292 dwrq->flags &= ~IW_ENCODE_DISABLED; 1293 } else { 1294 dwrq->flags |= IW_ENCODE_DISABLED; 1295 } 1296 1297 mutex_unlock(&adapter->lock); 1298 1299 dwrq->flags |= IW_ENCODE_NOKEY; 1300 1301 lbs_deb_wext("key: " MAC_FMT ", keylen %d\n", 1302 extra[0], extra[1], extra[2], 1303 extra[3], extra[4], extra[5], dwrq->length); 1304 1305 lbs_deb_wext("return flags 0x%x\n", dwrq->flags); 1306 1307 lbs_deb_leave(LBS_DEB_WEXT); 1308 return 0; 1309} 1310 1311/** 1312 * @brief Set Encryption key (internal) 1313 * 1314 * @param priv A pointer to private card structure 1315 * @param key_material A pointer to key material 1316 * @param key_length length of key material 1317 * @param index key index to set 1318 * @param set_tx_key Force set TX key (1 = yes, 0 = no) 1319 * @return 0 --success, otherwise fail 1320 */ 1321static int wlan_set_wep_key(struct assoc_request *assoc_req, 1322 const char *key_material, 1323 u16 key_length, 1324 u16 index, 1325 int set_tx_key) 1326{ 1327 int ret = 0; 1328 struct WLAN_802_11_KEY *pkey; 1329 1330 lbs_deb_enter(LBS_DEB_WEXT); 1331 1332 /* Paranoid validation of key index */ 1333 if (index > 3) { 1334 ret = -EINVAL; 1335 goto out; 1336 } 1337 1338 /* validate max key length */ 1339 if (key_length > KEY_LEN_WEP_104) { 1340 ret = -EINVAL; 1341 goto out; 1342 } 1343 1344 pkey = &assoc_req->wep_keys[index]; 1345 1346 if (key_length > 0) { 1347 memset(pkey, 0, sizeof(struct WLAN_802_11_KEY)); 1348 pkey->type = KEY_TYPE_ID_WEP; 1349 1350 /* Standardize the key length */ 1351 pkey->len = (key_length > KEY_LEN_WEP_40) ? 1352 KEY_LEN_WEP_104 : KEY_LEN_WEP_40; 1353 memcpy(pkey->key, key_material, key_length); 1354 } 1355 1356 if (set_tx_key) { 1357 /* Ensure the chosen key is valid */ 1358 if (!pkey->len) { 1359 lbs_deb_wext("key not set, so cannot enable it\n"); 1360 ret = -EINVAL; 1361 goto out; 1362 } 1363 assoc_req->wep_tx_keyidx = index; 1364 } 1365 1366 assoc_req->secinfo.wep_enabled = 1; 1367 1368out: 1369 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1370 return ret; 1371} 1372 1373static int validate_key_index(u16 def_index, u16 raw_index, 1374 u16 *out_index, u16 *is_default) 1375{ 1376 if (!out_index || !is_default) 1377 return -EINVAL; 1378 1379 /* Verify index if present, otherwise use default TX key index */ 1380 if (raw_index > 0) { 1381 if (raw_index > 4) 1382 return -EINVAL; 1383 *out_index = raw_index - 1; 1384 } else { 1385 *out_index = def_index; 1386 *is_default = 1; 1387 } 1388 return 0; 1389} 1390 1391static void disable_wep(struct assoc_request *assoc_req) 1392{ 1393 int i; 1394 1395 lbs_deb_enter(LBS_DEB_WEXT); 1396 1397 /* Set Open System auth mode */ 1398 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1399 1400 /* Clear WEP keys and mark WEP as disabled */ 1401 assoc_req->secinfo.wep_enabled = 0; 1402 for (i = 0; i < 4; i++) 1403 assoc_req->wep_keys[i].len = 0; 1404 1405 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1406 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); 1407 1408 lbs_deb_leave(LBS_DEB_WEXT); 1409} 1410 1411static void disable_wpa(struct assoc_request *assoc_req) 1412{ 1413 lbs_deb_enter(LBS_DEB_WEXT); 1414 1415 memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct WLAN_802_11_KEY)); 1416 assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST; 1417 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); 1418 1419 memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct WLAN_802_11_KEY)); 1420 assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST; 1421 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); 1422 1423 assoc_req->secinfo.WPAenabled = 0; 1424 assoc_req->secinfo.WPA2enabled = 0; 1425 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1426 1427 lbs_deb_leave(LBS_DEB_WEXT); 1428} 1429 1430/** 1431 * @brief Set Encryption key 1432 * 1433 * @param dev A pointer to net_device structure 1434 * @param info A pointer to iw_request_info structure 1435 * @param vwrq A pointer to iw_param structure 1436 * @param extra A pointer to extra data buf 1437 * @return 0 --success, otherwise fail 1438 */ 1439static int wlan_set_encode(struct net_device *dev, 1440 struct iw_request_info *info, 1441 struct iw_point *dwrq, char *extra) 1442{ 1443 int ret = 0; 1444 wlan_private *priv = dev->priv; 1445 wlan_adapter *adapter = priv->adapter; 1446 struct assoc_request * assoc_req; 1447 u16 is_default = 0, index = 0, set_tx_key = 0; 1448 1449 lbs_deb_enter(LBS_DEB_WEXT); 1450 1451 mutex_lock(&adapter->lock); 1452 assoc_req = wlan_get_association_request(adapter); 1453 if (!assoc_req) { 1454 ret = -ENOMEM; 1455 goto out; 1456 } 1457 1458 if (dwrq->flags & IW_ENCODE_DISABLED) { 1459 disable_wep (assoc_req); 1460 disable_wpa (assoc_req); 1461 goto out; 1462 } 1463 1464 ret = validate_key_index(assoc_req->wep_tx_keyidx, 1465 (dwrq->flags & IW_ENCODE_INDEX), 1466 &index, &is_default); 1467 if (ret) { 1468 ret = -EINVAL; 1469 goto out; 1470 } 1471 1472 /* If WEP isn't enabled, or if there is no key data but a valid 1473 * index, set the TX key. 1474 */ 1475 if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default)) 1476 set_tx_key = 1; 1477 1478 ret = wlan_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key); 1479 if (ret) 1480 goto out; 1481 1482 if (dwrq->length) 1483 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); 1484 if (set_tx_key) 1485 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); 1486 1487 if (dwrq->flags & IW_ENCODE_RESTRICTED) { 1488 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; 1489 } else if (dwrq->flags & IW_ENCODE_OPEN) { 1490 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1491 } 1492 1493out: 1494 if (ret == 0) { 1495 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1496 wlan_postpone_association_work(priv); 1497 } else { 1498 wlan_cancel_association_work(priv); 1499 } 1500 mutex_unlock(&adapter->lock); 1501 1502 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1503 return ret; 1504} 1505 1506/** 1507 * @brief Get Extended Encryption key (WPA/802.1x and WEP) 1508 * 1509 * @param dev A pointer to net_device structure 1510 * @param info A pointer to iw_request_info structure 1511 * @param vwrq A pointer to iw_param structure 1512 * @param extra A pointer to extra data buf 1513 * @return 0 on success, otherwise failure 1514 */ 1515static int wlan_get_encodeext(struct net_device *dev, 1516 struct iw_request_info *info, 1517 struct iw_point *dwrq, 1518 char *extra) 1519{ 1520 int ret = -EINVAL; 1521 wlan_private *priv = dev->priv; 1522 wlan_adapter *adapter = priv->adapter; 1523 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1524 int index, max_key_len; 1525 1526 lbs_deb_enter(LBS_DEB_WEXT); 1527 1528 max_key_len = dwrq->length - sizeof(*ext); 1529 if (max_key_len < 0) 1530 goto out; 1531 1532 index = dwrq->flags & IW_ENCODE_INDEX; 1533 if (index) { 1534 if (index < 1 || index > 4) 1535 goto out; 1536 index--; 1537 } else { 1538 index = adapter->wep_tx_keyidx; 1539 } 1540 1541 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY && 1542 ext->alg != IW_ENCODE_ALG_WEP) { 1543 if (index != 0 || adapter->mode != IW_MODE_INFRA) 1544 goto out; 1545 } 1546 1547 dwrq->flags = index + 1; 1548 memset(ext, 0, sizeof(*ext)); 1549 1550 if ( !adapter->secinfo.wep_enabled 1551 && !adapter->secinfo.WPAenabled 1552 && !adapter->secinfo.WPA2enabled) { 1553 ext->alg = IW_ENCODE_ALG_NONE; 1554 ext->key_len = 0; 1555 dwrq->flags |= IW_ENCODE_DISABLED; 1556 } else { 1557 u8 *key = NULL; 1558 1559 if ( adapter->secinfo.wep_enabled 1560 && !adapter->secinfo.WPAenabled 1561 && !adapter->secinfo.WPA2enabled) { 1562 /* WEP */ 1563 ext->alg = IW_ENCODE_ALG_WEP; 1564 ext->key_len = adapter->wep_keys[index].len; 1565 key = &adapter->wep_keys[index].key[0]; 1566 } else if ( !adapter->secinfo.wep_enabled 1567 && (adapter->secinfo.WPAenabled || 1568 adapter->secinfo.WPA2enabled)) { 1569 /* WPA */ 1570 struct WLAN_802_11_KEY * pkey = NULL; 1571 1572 if ( adapter->wpa_mcast_key.len 1573 && (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED)) 1574 pkey = &adapter->wpa_mcast_key; 1575 else if ( adapter->wpa_unicast_key.len 1576 && (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED)) 1577 pkey = &adapter->wpa_unicast_key; 1578 1579 if (pkey) { 1580 if (pkey->type == KEY_TYPE_ID_AES) { 1581 ext->alg = IW_ENCODE_ALG_CCMP; 1582 } else { 1583 ext->alg = IW_ENCODE_ALG_TKIP; 1584 } 1585 ext->key_len = pkey->len; 1586 key = &pkey->key[0]; 1587 } else { 1588 ext->alg = IW_ENCODE_ALG_TKIP; 1589 ext->key_len = 0; 1590 } 1591 } else { 1592 goto out; 1593 } 1594 1595 if (ext->key_len > max_key_len) { 1596 ret = -E2BIG; 1597 goto out; 1598 } 1599 1600 if (ext->key_len) 1601 memcpy(ext->key, key, ext->key_len); 1602 else 1603 dwrq->flags |= IW_ENCODE_NOKEY; 1604 dwrq->flags |= IW_ENCODE_ENABLED; 1605 } 1606 ret = 0; 1607 1608out: 1609 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1610 return ret; 1611} 1612 1613/** 1614 * @brief Set Encryption key Extended (WPA/802.1x and WEP) 1615 * 1616 * @param dev A pointer to net_device structure 1617 * @param info A pointer to iw_request_info structure 1618 * @param vwrq A pointer to iw_param structure 1619 * @param extra A pointer to extra data buf 1620 * @return 0 --success, otherwise fail 1621 */ 1622static int wlan_set_encodeext(struct net_device *dev, 1623 struct iw_request_info *info, 1624 struct iw_point *dwrq, 1625 char *extra) 1626{ 1627 int ret = 0; 1628 wlan_private *priv = dev->priv; 1629 wlan_adapter *adapter = priv->adapter; 1630 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1631 int alg = ext->alg; 1632 struct assoc_request * assoc_req; 1633 1634 lbs_deb_enter(LBS_DEB_WEXT); 1635 1636 mutex_lock(&adapter->lock); 1637 assoc_req = wlan_get_association_request(adapter); 1638 if (!assoc_req) { 1639 ret = -ENOMEM; 1640 goto out; 1641 } 1642 1643 if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) { 1644 disable_wep (assoc_req); 1645 disable_wpa (assoc_req); 1646 } else if (alg == IW_ENCODE_ALG_WEP) { 1647 u16 is_default = 0, index, set_tx_key = 0; 1648 1649 ret = validate_key_index(assoc_req->wep_tx_keyidx, 1650 (dwrq->flags & IW_ENCODE_INDEX), 1651 &index, &is_default); 1652 if (ret) 1653 goto out; 1654 1655 /* If WEP isn't enabled, or if there is no key data but a valid 1656 * index, or if the set-TX-key flag was passed, set the TX key. 1657 */ 1658 if ( !assoc_req->secinfo.wep_enabled 1659 || (dwrq->length == 0 && !is_default) 1660 || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) 1661 set_tx_key = 1; 1662 1663 /* Copy key to driver */ 1664 ret = wlan_set_wep_key (assoc_req, ext->key, ext->key_len, index, 1665 set_tx_key); 1666 if (ret) 1667 goto out; 1668 1669 if (dwrq->flags & IW_ENCODE_RESTRICTED) { 1670 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; 1671 } else if (dwrq->flags & IW_ENCODE_OPEN) { 1672 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1673 } 1674 1675 /* Mark the various WEP bits as modified */ 1676 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1677 if (dwrq->length) 1678 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); 1679 if (set_tx_key) 1680 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); 1681 } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { 1682 struct WLAN_802_11_KEY * pkey; 1683 1684 /* validate key length */ 1685 if (((alg == IW_ENCODE_ALG_TKIP) 1686 && (ext->key_len != KEY_LEN_WPA_TKIP)) 1687 || ((alg == IW_ENCODE_ALG_CCMP) 1688 && (ext->key_len != KEY_LEN_WPA_AES))) { 1689 lbs_deb_wext("invalid size %d for key of alg" 1690 "type %d\n", 1691 ext->key_len, 1692 alg); 1693 ret = -EINVAL; 1694 goto out; 1695 } 1696 1697 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { 1698 pkey = &assoc_req->wpa_mcast_key; 1699 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); 1700 } else { 1701 pkey = &assoc_req->wpa_unicast_key; 1702 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); 1703 } 1704 1705 memset(pkey, 0, sizeof (struct WLAN_802_11_KEY)); 1706 memcpy(pkey->key, ext->key, ext->key_len); 1707 pkey->len = ext->key_len; 1708 if (pkey->len) 1709 pkey->flags |= KEY_INFO_WPA_ENABLED; 1710 1711 /* Do this after zeroing key structure */ 1712 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { 1713 pkey->flags |= KEY_INFO_WPA_MCAST; 1714 } else { 1715 pkey->flags |= KEY_INFO_WPA_UNICAST; 1716 } 1717 1718 if (alg == IW_ENCODE_ALG_TKIP) { 1719 pkey->type = KEY_TYPE_ID_TKIP; 1720 } else if (alg == IW_ENCODE_ALG_CCMP) { 1721 pkey->type = KEY_TYPE_ID_AES; 1722 } else { 1723 ret = -EINVAL; 1724 goto out; 1725 } 1726 1727 /* If WPA isn't enabled yet, do that now */ 1728 if ( assoc_req->secinfo.WPAenabled == 0 1729 && assoc_req->secinfo.WPA2enabled == 0) { 1730 assoc_req->secinfo.WPAenabled = 1; 1731 assoc_req->secinfo.WPA2enabled = 1; 1732 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1733 } 1734 1735 disable_wep (assoc_req); 1736 } 1737 1738out: 1739 if (ret == 0) { 1740 wlan_postpone_association_work(priv); 1741 } else { 1742 wlan_cancel_association_work(priv); 1743 } 1744 mutex_unlock(&adapter->lock); 1745 1746 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1747 return ret; 1748} 1749 1750 1751static int wlan_set_genie(struct net_device *dev, 1752 struct iw_request_info *info, 1753 struct iw_point *dwrq, 1754 char *extra) 1755{ 1756 wlan_private *priv = dev->priv; 1757 wlan_adapter *adapter = priv->adapter; 1758 int ret = 0; 1759 struct assoc_request * assoc_req; 1760 1761 lbs_deb_enter(LBS_DEB_WEXT); 1762 1763 mutex_lock(&adapter->lock); 1764 assoc_req = wlan_get_association_request(adapter); 1765 if (!assoc_req) { 1766 ret = -ENOMEM; 1767 goto out; 1768 } 1769 1770 if (dwrq->length > MAX_WPA_IE_LEN || 1771 (dwrq->length && extra == NULL)) { 1772 ret = -EINVAL; 1773 goto out; 1774 } 1775 1776 if (dwrq->length) { 1777 memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length); 1778 assoc_req->wpa_ie_len = dwrq->length; 1779 } else { 1780 memset(&assoc_req->wpa_ie[0], 0, sizeof(adapter->wpa_ie)); 1781 assoc_req->wpa_ie_len = 0; 1782 } 1783 1784out: 1785 if (ret == 0) { 1786 set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags); 1787 wlan_postpone_association_work(priv); 1788 } else { 1789 wlan_cancel_association_work(priv); 1790 } 1791 mutex_unlock(&adapter->lock); 1792 1793 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1794 return ret; 1795} 1796 1797static int wlan_get_genie(struct net_device *dev, 1798 struct iw_request_info *info, 1799 struct iw_point *dwrq, 1800 char *extra) 1801{ 1802 int ret = 0; 1803 wlan_private *priv = dev->priv; 1804 wlan_adapter *adapter = priv->adapter; 1805 1806 lbs_deb_enter(LBS_DEB_WEXT); 1807 1808 if (adapter->wpa_ie_len == 0) { 1809 dwrq->length = 0; 1810 goto out; 1811 } 1812 1813 if (dwrq->length < adapter->wpa_ie_len) { 1814 ret = -E2BIG; 1815 goto out; 1816 } 1817 1818 dwrq->length = adapter->wpa_ie_len; 1819 memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len); 1820 1821out: 1822 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1823 return ret; 1824} 1825 1826 1827static int wlan_set_auth(struct net_device *dev, 1828 struct iw_request_info *info, 1829 struct iw_param *dwrq, 1830 char *extra) 1831{ 1832 wlan_private *priv = dev->priv; 1833 wlan_adapter *adapter = priv->adapter; 1834 struct assoc_request * assoc_req; 1835 int ret = 0; 1836 int updated = 0; 1837 1838 lbs_deb_enter(LBS_DEB_WEXT); 1839 1840 mutex_lock(&adapter->lock); 1841 assoc_req = wlan_get_association_request(adapter); 1842 if (!assoc_req) { 1843 ret = -ENOMEM; 1844 goto out; 1845 } 1846 1847 switch (dwrq->flags & IW_AUTH_INDEX) { 1848 case IW_AUTH_TKIP_COUNTERMEASURES: 1849 case IW_AUTH_CIPHER_PAIRWISE: 1850 case IW_AUTH_CIPHER_GROUP: 1851 case IW_AUTH_KEY_MGMT: 1852 case IW_AUTH_DROP_UNENCRYPTED: 1853 /* 1854 * libertas does not use these parameters 1855 */ 1856 break; 1857 1858 case IW_AUTH_WPA_VERSION: 1859 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { 1860 assoc_req->secinfo.WPAenabled = 0; 1861 assoc_req->secinfo.WPA2enabled = 0; 1862 disable_wpa (assoc_req); 1863 } 1864 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) { 1865 assoc_req->secinfo.WPAenabled = 1; 1866 assoc_req->secinfo.wep_enabled = 0; 1867 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1868 } 1869 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) { 1870 assoc_req->secinfo.WPA2enabled = 1; 1871 assoc_req->secinfo.wep_enabled = 0; 1872 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1873 } 1874 updated = 1; 1875 break; 1876 1877 case IW_AUTH_80211_AUTH_ALG: 1878 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) { 1879 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; 1880 } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) { 1881 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1882 } else if (dwrq->value & IW_AUTH_ALG_LEAP) { 1883 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP; 1884 } else { 1885 ret = -EINVAL; 1886 } 1887 updated = 1; 1888 break; 1889 1890 case IW_AUTH_WPA_ENABLED: 1891 if (dwrq->value) { 1892 if (!assoc_req->secinfo.WPAenabled && 1893 !assoc_req->secinfo.WPA2enabled) { 1894 assoc_req->secinfo.WPAenabled = 1; 1895 assoc_req->secinfo.WPA2enabled = 1; 1896 assoc_req->secinfo.wep_enabled = 0; 1897 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 1898 } 1899 } else { 1900 assoc_req->secinfo.WPAenabled = 0; 1901 assoc_req->secinfo.WPA2enabled = 0; 1902 disable_wpa (assoc_req); 1903 } 1904 updated = 1; 1905 break; 1906 1907 default: 1908 ret = -EOPNOTSUPP; 1909 break; 1910 } 1911 1912out: 1913 if (ret == 0) { 1914 if (updated) 1915 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); 1916 wlan_postpone_association_work(priv); 1917 } else if (ret != -EOPNOTSUPP) { 1918 wlan_cancel_association_work(priv); 1919 } 1920 mutex_unlock(&adapter->lock); 1921 1922 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1923 return ret; 1924} 1925 1926static int wlan_get_auth(struct net_device *dev, 1927 struct iw_request_info *info, 1928 struct iw_param *dwrq, 1929 char *extra) 1930{ 1931 int ret = 0; 1932 wlan_private *priv = dev->priv; 1933 wlan_adapter *adapter = priv->adapter; 1934 1935 lbs_deb_enter(LBS_DEB_WEXT); 1936 1937 switch (dwrq->flags & IW_AUTH_INDEX) { 1938 case IW_AUTH_WPA_VERSION: 1939 dwrq->value = 0; 1940 if (adapter->secinfo.WPAenabled) 1941 dwrq->value |= IW_AUTH_WPA_VERSION_WPA; 1942 if (adapter->secinfo.WPA2enabled) 1943 dwrq->value |= IW_AUTH_WPA_VERSION_WPA2; 1944 if (!dwrq->value) 1945 dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED; 1946 break; 1947 1948 case IW_AUTH_80211_AUTH_ALG: 1949 dwrq->value = adapter->secinfo.auth_mode; 1950 break; 1951 1952 case IW_AUTH_WPA_ENABLED: 1953 if (adapter->secinfo.WPAenabled && adapter->secinfo.WPA2enabled) 1954 dwrq->value = 1; 1955 break; 1956 1957 default: 1958 ret = -EOPNOTSUPP; 1959 } 1960 1961 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 1962 return ret; 1963} 1964 1965 1966static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info, 1967 struct iw_param *vwrq, char *extra) 1968{ 1969 int ret = 0; 1970 wlan_private *priv = dev->priv; 1971 wlan_adapter *adapter = priv->adapter; 1972 1973 u16 dbm; 1974 1975 lbs_deb_enter(LBS_DEB_WEXT); 1976 1977 if (vwrq->disabled) { 1978 wlan_radio_ioctl(priv, RADIO_OFF); 1979 return 0; 1980 } 1981 1982 adapter->preamble = cmd_type_auto_preamble; 1983 1984 wlan_radio_ioctl(priv, RADIO_ON); 1985 1986 if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) { 1987 dbm = (u16) mw_to_dbm(vwrq->value); 1988 } else 1989 dbm = (u16) vwrq->value; 1990 1991 /* auto tx power control */ 1992 1993 if (vwrq->fixed == 0) 1994 dbm = 0xffff; 1995 1996 lbs_deb_wext("txpower set %d dbm\n", dbm); 1997 1998 ret = libertas_prepare_and_send_command(priv, 1999 cmd_802_11_rf_tx_power, 2000 cmd_act_tx_power_opt_set_low, 2001 cmd_option_waitforrsp, 0, (void *)&dbm); 2002 2003 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 2004 return ret; 2005} 2006 2007static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info, 2008 struct iw_point *dwrq, char *extra) 2009{ 2010 wlan_private *priv = dev->priv; 2011 wlan_adapter *adapter = priv->adapter; 2012 2013 lbs_deb_enter(LBS_DEB_WEXT); 2014 2015 /* 2016 * Note : if dwrq->flags != 0, we should get the relevant SSID from 2017 * the SSID list... 2018 */ 2019 2020 /* 2021 * Get the current SSID 2022 */ 2023 if (adapter->connect_status == libertas_connected) { 2024 memcpy(extra, adapter->curbssparams.ssid, 2025 adapter->curbssparams.ssid_len); 2026 extra[adapter->curbssparams.ssid_len] = '\0'; 2027 } else { 2028 memset(extra, 0, 32); 2029 extra[adapter->curbssparams.ssid_len] = '\0'; 2030 } 2031 /* 2032 * If none, we may want to get the one that was set 2033 */ 2034 2035 /* To make the driver backward compatible with WPA supplicant v0.2.4 */ 2036 if (dwrq->length == 32) /* check with WPA supplicant buffer size */ 2037 dwrq->length = min_t(size_t, adapter->curbssparams.ssid_len, 2038 IW_ESSID_MAX_SIZE); 2039 else 2040 dwrq->length = adapter->curbssparams.ssid_len + 1; 2041 2042 dwrq->flags = 1; /* active */ 2043 2044 lbs_deb_leave(LBS_DEB_WEXT); 2045 return 0; 2046} 2047 2048static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info, 2049 struct iw_point *dwrq, char *extra) 2050{ 2051 wlan_private *priv = dev->priv; 2052 wlan_adapter *adapter = priv->adapter; 2053 int ret = 0; 2054 u8 ssid[IW_ESSID_MAX_SIZE]; 2055 u8 ssid_len = 0; 2056 struct assoc_request * assoc_req; 2057 int in_ssid_len = dwrq->length; 2058 2059 lbs_deb_enter(LBS_DEB_WEXT); 2060 2061 /* 2062 * WE-20 and earlier NULL pad the end of the SSID and increment 2063 * SSID length so it can be used like a string. WE-21 and later don't, 2064 * but some userspace tools aren't able to cope with the change. 2065 */ 2066 if ((in_ssid_len > 0) && (extra[in_ssid_len - 1] == '\0')) 2067 in_ssid_len--; 2068 2069 /* Check the size of the string */ 2070 if (in_ssid_len > IW_ESSID_MAX_SIZE) { 2071 ret = -E2BIG; 2072 goto out; 2073 } 2074 2075 memset(&ssid, 0, sizeof(ssid)); 2076 2077 if (!dwrq->flags || !in_ssid_len) { 2078 /* "any" SSID requested; leave SSID blank */ 2079 } else { 2080 /* Specific SSID requested */ 2081 memcpy(&ssid, extra, in_ssid_len); 2082 ssid_len = in_ssid_len; 2083 } 2084 2085 if (!ssid_len) { 2086 lbs_deb_wext("requested any SSID\n"); 2087 } else { 2088 lbs_deb_wext("requested SSID '%s'\n", 2089 escape_essid(ssid, ssid_len)); 2090 } 2091 2092out: 2093 mutex_lock(&adapter->lock); 2094 if (ret == 0) { 2095 /* Get or create the current association request */ 2096 assoc_req = wlan_get_association_request(adapter); 2097 if (!assoc_req) { 2098 ret = -ENOMEM; 2099 } else { 2100 /* Copy the SSID to the association request */ 2101 memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE); 2102 assoc_req->ssid_len = ssid_len; 2103 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); 2104 wlan_postpone_association_work(priv); 2105 } 2106 } 2107 2108 /* Cancel the association request if there was an error */ 2109 if (ret != 0) { 2110 wlan_cancel_association_work(priv); 2111 } 2112 2113 mutex_unlock(&adapter->lock); 2114 2115 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 2116 return ret; 2117} 2118 2119/** 2120 * @brief Connect to the AP or Ad-hoc Network with specific bssid 2121 * 2122 * @param dev A pointer to net_device structure 2123 * @param info A pointer to iw_request_info structure 2124 * @param awrq A pointer to iw_param structure 2125 * @param extra A pointer to extra data buf 2126 * @return 0 --success, otherwise fail 2127 */ 2128static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info, 2129 struct sockaddr *awrq, char *extra) 2130{ 2131 wlan_private *priv = dev->priv; 2132 wlan_adapter *adapter = priv->adapter; 2133 struct assoc_request * assoc_req; 2134 int ret = 0; 2135 2136 lbs_deb_enter(LBS_DEB_WEXT); 2137 2138 if (awrq->sa_family != ARPHRD_ETHER) 2139 return -EINVAL; 2140 2141 lbs_deb_wext("ASSOC: WAP: sa_data " MAC_FMT "\n", MAC_ARG(awrq->sa_data)); 2142 2143 mutex_lock(&adapter->lock); 2144 2145 /* Get or create the current association request */ 2146 assoc_req = wlan_get_association_request(adapter); 2147 if (!assoc_req) { 2148 wlan_cancel_association_work(priv); 2149 ret = -ENOMEM; 2150 } else { 2151 /* Copy the BSSID to the association request */ 2152 memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN); 2153 set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags); 2154 wlan_postpone_association_work(priv); 2155 } 2156 2157 mutex_unlock(&adapter->lock); 2158 2159 return ret; 2160} 2161 2162void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen) 2163{ 2164 char fwver[32]; 2165 2166 mutex_lock(&adapter->lock); 2167 2168 if (adapter->fwreleasenumber[3] == 0) 2169 sprintf(fwver, "%u.%u.%u", 2170 adapter->fwreleasenumber[2], 2171 adapter->fwreleasenumber[1], 2172 adapter->fwreleasenumber[0]); 2173 else 2174 sprintf(fwver, "%u.%u.%u.p%u", 2175 adapter->fwreleasenumber[2], 2176 adapter->fwreleasenumber[1], 2177 adapter->fwreleasenumber[0], 2178 adapter->fwreleasenumber[3]); 2179 2180 mutex_unlock(&adapter->lock); 2181 snprintf(fwversion, maxlen, fwver); 2182} 2183 2184 2185/* 2186 * iwconfig settable callbacks 2187 */ 2188static const iw_handler wlan_handler[] = { 2189 (iw_handler) NULL, /* SIOCSIWCOMMIT */ 2190 (iw_handler) wlan_get_name, /* SIOCGIWNAME */ 2191 (iw_handler) NULL, /* SIOCSIWNWID */ 2192 (iw_handler) NULL, /* SIOCGIWNWID */ 2193 (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */ 2194 (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */ 2195 (iw_handler) wlan_set_mode, /* SIOCSIWMODE */ 2196 (iw_handler) wlan_get_mode, /* SIOCGIWMODE */ 2197 (iw_handler) NULL, /* SIOCSIWSENS */ 2198 (iw_handler) NULL, /* SIOCGIWSENS */ 2199 (iw_handler) NULL, /* SIOCSIWRANGE */ 2200 (iw_handler) wlan_get_range, /* SIOCGIWRANGE */ 2201 (iw_handler) NULL, /* SIOCSIWPRIV */ 2202 (iw_handler) NULL, /* SIOCGIWPRIV */ 2203 (iw_handler) NULL, /* SIOCSIWSTATS */ 2204 (iw_handler) NULL, /* SIOCGIWSTATS */ 2205 iw_handler_set_spy, /* SIOCSIWSPY */ 2206 iw_handler_get_spy, /* SIOCGIWSPY */ 2207 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ 2208 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ 2209 (iw_handler) wlan_set_wap, /* SIOCSIWAP */ 2210 (iw_handler) wlan_get_wap, /* SIOCGIWAP */ 2211 (iw_handler) NULL, /* SIOCSIWMLME */ 2212 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ 2213 (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */ 2214 (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */ 2215 (iw_handler) wlan_set_essid, /* SIOCSIWESSID */ 2216 (iw_handler) wlan_get_essid, /* SIOCGIWESSID */ 2217 (iw_handler) wlan_set_nick, /* SIOCSIWNICKN */ 2218 (iw_handler) wlan_get_nick, /* SIOCGIWNICKN */ 2219 (iw_handler) NULL, /* -- hole -- */ 2220 (iw_handler) NULL, /* -- hole -- */ 2221 (iw_handler) wlan_set_rate, /* SIOCSIWRATE */ 2222 (iw_handler) wlan_get_rate, /* SIOCGIWRATE */ 2223 (iw_handler) wlan_set_rts, /* SIOCSIWRTS */ 2224 (iw_handler) wlan_get_rts, /* SIOCGIWRTS */ 2225 (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */ 2226 (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */ 2227 (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */ 2228 (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */ 2229 (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */ 2230 (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */ 2231 (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */ 2232 (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */ 2233 (iw_handler) wlan_set_power, /* SIOCSIWPOWER */ 2234 (iw_handler) wlan_get_power, /* SIOCGIWPOWER */ 2235 (iw_handler) NULL, /* -- hole -- */ 2236 (iw_handler) NULL, /* -- hole -- */ 2237 (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */ 2238 (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */ 2239 (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */ 2240 (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */ 2241 (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */ 2242 (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */ 2243 (iw_handler) NULL, /* SIOCSIWPMKSA */ 2244}; 2245 2246static const iw_handler mesh_wlan_handler[] = { 2247 (iw_handler) NULL, /* SIOCSIWCOMMIT */ 2248 (iw_handler) wlan_get_name, /* SIOCGIWNAME */ 2249 (iw_handler) NULL, /* SIOCSIWNWID */ 2250 (iw_handler) NULL, /* SIOCGIWNWID */ 2251 (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */ 2252 (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */ 2253 (iw_handler) NULL, /* SIOCSIWMODE */ 2254 (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */ 2255 (iw_handler) NULL, /* SIOCSIWSENS */ 2256 (iw_handler) NULL, /* SIOCGIWSENS */ 2257 (iw_handler) NULL, /* SIOCSIWRANGE */ 2258 (iw_handler) wlan_get_range, /* SIOCGIWRANGE */ 2259 (iw_handler) NULL, /* SIOCSIWPRIV */ 2260 (iw_handler) NULL, /* SIOCGIWPRIV */ 2261 (iw_handler) NULL, /* SIOCSIWSTATS */ 2262 (iw_handler) NULL, /* SIOCGIWSTATS */ 2263 iw_handler_set_spy, /* SIOCSIWSPY */ 2264 iw_handler_get_spy, /* SIOCGIWSPY */ 2265 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ 2266 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ 2267 (iw_handler) NULL, /* SIOCSIWAP */ 2268 (iw_handler) NULL, /* SIOCGIWAP */ 2269 (iw_handler) NULL, /* SIOCSIWMLME */ 2270 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ 2271 (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */ 2272 (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */ 2273 (iw_handler) NULL, /* SIOCSIWESSID */ 2274 (iw_handler) NULL, /* SIOCGIWESSID */ 2275 (iw_handler) NULL, /* SIOCSIWNICKN */ 2276 (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */ 2277 (iw_handler) NULL, /* -- hole -- */ 2278 (iw_handler) NULL, /* -- hole -- */ 2279 (iw_handler) wlan_set_rate, /* SIOCSIWRATE */ 2280 (iw_handler) wlan_get_rate, /* SIOCGIWRATE */ 2281 (iw_handler) wlan_set_rts, /* SIOCSIWRTS */ 2282 (iw_handler) wlan_get_rts, /* SIOCGIWRTS */ 2283 (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */ 2284 (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */ 2285 (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */ 2286 (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */ 2287 (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */ 2288 (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */ 2289 (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */ 2290 (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */ 2291 (iw_handler) wlan_set_power, /* SIOCSIWPOWER */ 2292 (iw_handler) wlan_get_power, /* SIOCGIWPOWER */ 2293 (iw_handler) NULL, /* -- hole -- */ 2294 (iw_handler) NULL, /* -- hole -- */ 2295 (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */ 2296 (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */ 2297 (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */ 2298 (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */ 2299 (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */ 2300 (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */ 2301 (iw_handler) NULL, /* SIOCSIWPMKSA */ 2302}; 2303struct iw_handler_def libertas_handler_def = { 2304 .num_standard = sizeof(wlan_handler) / sizeof(iw_handler), 2305 .standard = (iw_handler *) wlan_handler, 2306 .get_wireless_stats = wlan_get_wireless_stats, 2307}; 2308 2309struct iw_handler_def mesh_handler_def = { 2310 .num_standard = sizeof(mesh_wlan_handler) / sizeof(iw_handler), 2311 .standard = (iw_handler *) mesh_wlan_handler, 2312 .get_wireless_stats = wlan_get_wireless_stats, 2313}; 2314