1 /* IEEE 802.11 SoftMAC layer 2 * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> 3 * 4 * Mostly extracted from the rtl8180-sa2400 driver for the 5 * in-kernel generic ieee802.11 stack. 6 * 7 * Some pieces of code might be stolen from ipw2100 driver 8 * copyright of who own it's copyright ;-) 9 * 10 * PS wx handler mostly stolen from hostap, copyright who 11 * own it's copyright ;-) 12 * 13 * released under the GPL 14 */ 15 16 17 #include <linux/etherdevice.h> 18 19 #include "rtllib.h" 20 #include "dot11d.h" 21 /* FIXME: add A freqs */ 22 23 const long rtllib_wlan_frequencies[] = { 24 2412, 2417, 2422, 2427, 25 2432, 2437, 2442, 2447, 26 2452, 2457, 2462, 2467, 27 2472, 2484 28 }; 29 EXPORT_SYMBOL(rtllib_wlan_frequencies); 30 31 32 int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, 33 union iwreq_data *wrqu, char *b) 34 { 35 int ret; 36 struct iw_freq *fwrq = &wrqu->freq; 37 38 mutex_lock(&ieee->wx_mutex); 39 40 if (ieee->iw_mode == IW_MODE_INFRA) { 41 ret = 0; 42 goto out; 43 } 44 45 /* if setting by freq convert to channel */ 46 if (fwrq->e == 1) { 47 if ((fwrq->m >= (int) 2.412e8 && 48 fwrq->m <= (int) 2.487e8)) { 49 int f = fwrq->m / 100000; 50 int c = 0; 51 52 while ((c < 14) && (f != rtllib_wlan_frequencies[c])) 53 c++; 54 55 /* hack to fall through */ 56 fwrq->e = 0; 57 fwrq->m = c + 1; 58 } 59 } 60 61 if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) { 62 ret = -EOPNOTSUPP; 63 goto out; 64 65 } else { /* Set the channel */ 66 67 if (ieee->active_channel_map[fwrq->m] != 1) { 68 ret = -EINVAL; 69 goto out; 70 } 71 ieee->current_network.channel = fwrq->m; 72 ieee->set_chan(ieee->dev, ieee->current_network.channel); 73 74 if (ieee->iw_mode == IW_MODE_ADHOC || 75 ieee->iw_mode == IW_MODE_MASTER) 76 if (ieee->state == RTLLIB_LINKED) { 77 rtllib_stop_send_beacons(ieee); 78 rtllib_start_send_beacons(ieee); 79 } 80 } 81 82 ret = 0; 83 out: 84 mutex_unlock(&ieee->wx_mutex); 85 return ret; 86 } 87 EXPORT_SYMBOL(rtllib_wx_set_freq); 88 89 90 int rtllib_wx_get_freq(struct rtllib_device *ieee, 91 struct iw_request_info *a, 92 union iwreq_data *wrqu, char *b) 93 { 94 struct iw_freq *fwrq = &wrqu->freq; 95 96 if (ieee->current_network.channel == 0) 97 return -1; 98 fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] * 99 100000; 100 fwrq->e = 1; 101 return 0; 102 } 103 EXPORT_SYMBOL(rtllib_wx_get_freq); 104 105 int rtllib_wx_get_wap(struct rtllib_device *ieee, 106 struct iw_request_info *info, 107 union iwreq_data *wrqu, char *extra) 108 { 109 unsigned long flags; 110 111 wrqu->ap_addr.sa_family = ARPHRD_ETHER; 112 113 if (ieee->iw_mode == IW_MODE_MONITOR) 114 return -1; 115 116 /* We want avoid to give to the user inconsistent infos*/ 117 spin_lock_irqsave(&ieee->lock, flags); 118 119 if (ieee->state != RTLLIB_LINKED && 120 ieee->state != RTLLIB_LINKED_SCANNING && 121 ieee->wap_set == 0) 122 123 eth_zero_addr(wrqu->ap_addr.sa_data); 124 else 125 memcpy(wrqu->ap_addr.sa_data, 126 ieee->current_network.bssid, ETH_ALEN); 127 128 spin_unlock_irqrestore(&ieee->lock, flags); 129 130 return 0; 131 } 132 EXPORT_SYMBOL(rtllib_wx_get_wap); 133 134 135 int rtllib_wx_set_wap(struct rtllib_device *ieee, 136 struct iw_request_info *info, 137 union iwreq_data *awrq, 138 char *extra) 139 { 140 141 int ret = 0; 142 unsigned long flags; 143 144 short ifup = ieee->proto_started; 145 struct sockaddr *temp = (struct sockaddr *)awrq; 146 147 rtllib_stop_scan_syncro(ieee); 148 149 mutex_lock(&ieee->wx_mutex); 150 /* use ifconfig hw ether */ 151 if (ieee->iw_mode == IW_MODE_MASTER) { 152 ret = -1; 153 goto out; 154 } 155 156 if (temp->sa_family != ARPHRD_ETHER) { 157 ret = -EINVAL; 158 goto out; 159 } 160 161 if (is_zero_ether_addr(temp->sa_data)) { 162 spin_lock_irqsave(&ieee->lock, flags); 163 ether_addr_copy(ieee->current_network.bssid, temp->sa_data); 164 ieee->wap_set = 0; 165 spin_unlock_irqrestore(&ieee->lock, flags); 166 ret = -1; 167 goto out; 168 } 169 170 171 if (ifup) 172 rtllib_stop_protocol(ieee, true); 173 174 /* just to avoid to give inconsistent infos in the 175 * get wx method. not really needed otherwise 176 */ 177 spin_lock_irqsave(&ieee->lock, flags); 178 179 ieee->cannot_notify = false; 180 ether_addr_copy(ieee->current_network.bssid, temp->sa_data); 181 ieee->wap_set = !is_zero_ether_addr(temp->sa_data); 182 183 spin_unlock_irqrestore(&ieee->lock, flags); 184 185 if (ifup) 186 rtllib_start_protocol(ieee); 187 out: 188 mutex_unlock(&ieee->wx_mutex); 189 return ret; 190 } 191 EXPORT_SYMBOL(rtllib_wx_set_wap); 192 193 int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a, 194 union iwreq_data *wrqu, char *b) 195 { 196 int len, ret = 0; 197 unsigned long flags; 198 199 if (ieee->iw_mode == IW_MODE_MONITOR) 200 return -1; 201 202 /* We want avoid to give to the user inconsistent infos*/ 203 spin_lock_irqsave(&ieee->lock, flags); 204 205 if (ieee->current_network.ssid[0] == '\0' || 206 ieee->current_network.ssid_len == 0) { 207 ret = -1; 208 goto out; 209 } 210 211 if (ieee->state != RTLLIB_LINKED && 212 ieee->state != RTLLIB_LINKED_SCANNING && 213 ieee->ssid_set == 0) { 214 ret = -1; 215 goto out; 216 } 217 len = ieee->current_network.ssid_len; 218 wrqu->essid.length = len; 219 strncpy(b, ieee->current_network.ssid, len); 220 wrqu->essid.flags = 1; 221 222 out: 223 spin_unlock_irqrestore(&ieee->lock, flags); 224 225 return ret; 226 227 } 228 EXPORT_SYMBOL(rtllib_wx_get_essid); 229 230 int rtllib_wx_set_rate(struct rtllib_device *ieee, 231 struct iw_request_info *info, 232 union iwreq_data *wrqu, char *extra) 233 { 234 235 u32 target_rate = wrqu->bitrate.value; 236 237 ieee->rate = target_rate/100000; 238 return 0; 239 } 240 EXPORT_SYMBOL(rtllib_wx_set_rate); 241 242 int rtllib_wx_get_rate(struct rtllib_device *ieee, 243 struct iw_request_info *info, 244 union iwreq_data *wrqu, char *extra) 245 { 246 u32 tmp_rate; 247 248 tmp_rate = TxCountToDataRate(ieee, 249 ieee->softmac_stats.CurrentShowTxate); 250 wrqu->bitrate.value = tmp_rate * 500000; 251 252 return 0; 253 } 254 EXPORT_SYMBOL(rtllib_wx_get_rate); 255 256 257 int rtllib_wx_set_rts(struct rtllib_device *ieee, 258 struct iw_request_info *info, 259 union iwreq_data *wrqu, char *extra) 260 { 261 if (wrqu->rts.disabled || !wrqu->rts.fixed) 262 ieee->rts = DEFAULT_RTS_THRESHOLD; 263 else { 264 if (wrqu->rts.value < MIN_RTS_THRESHOLD || 265 wrqu->rts.value > MAX_RTS_THRESHOLD) 266 return -EINVAL; 267 ieee->rts = wrqu->rts.value; 268 } 269 return 0; 270 } 271 EXPORT_SYMBOL(rtllib_wx_set_rts); 272 273 int rtllib_wx_get_rts(struct rtllib_device *ieee, 274 struct iw_request_info *info, 275 union iwreq_data *wrqu, char *extra) 276 { 277 wrqu->rts.value = ieee->rts; 278 wrqu->rts.fixed = 0; /* no auto select */ 279 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); 280 return 0; 281 } 282 EXPORT_SYMBOL(rtllib_wx_get_rts); 283 284 int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, 285 union iwreq_data *wrqu, char *b) 286 { 287 int set_mode_status = 0; 288 289 rtllib_stop_scan_syncro(ieee); 290 mutex_lock(&ieee->wx_mutex); 291 switch (wrqu->mode) { 292 case IW_MODE_MONITOR: 293 case IW_MODE_ADHOC: 294 case IW_MODE_INFRA: 295 break; 296 case IW_MODE_AUTO: 297 wrqu->mode = IW_MODE_INFRA; 298 break; 299 default: 300 set_mode_status = -EINVAL; 301 goto out; 302 } 303 304 if (wrqu->mode == ieee->iw_mode) 305 goto out; 306 307 if (wrqu->mode == IW_MODE_MONITOR) { 308 ieee->dev->type = ARPHRD_IEEE80211; 309 rtllib_EnableNetMonitorMode(ieee->dev, false); 310 } else { 311 ieee->dev->type = ARPHRD_ETHER; 312 if (ieee->iw_mode == IW_MODE_MONITOR) 313 rtllib_DisableNetMonitorMode(ieee->dev, false); 314 } 315 316 if (!ieee->proto_started) { 317 ieee->iw_mode = wrqu->mode; 318 } else { 319 rtllib_stop_protocol(ieee, true); 320 ieee->iw_mode = wrqu->mode; 321 rtllib_start_protocol(ieee); 322 } 323 324 out: 325 mutex_unlock(&ieee->wx_mutex); 326 return set_mode_status; 327 } 328 EXPORT_SYMBOL(rtllib_wx_set_mode); 329 330 void rtllib_wx_sync_scan_wq(void *data) 331 { 332 struct rtllib_device *ieee = container_of_work_rsl(data, 333 struct rtllib_device, wx_sync_scan_wq); 334 short chan; 335 enum ht_extchnl_offset chan_offset = 0; 336 enum ht_channel_width bandwidth = 0; 337 int b40M = 0; 338 339 if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { 340 rtllib_start_scan_syncro(ieee, 0); 341 goto out; 342 } 343 344 chan = ieee->current_network.channel; 345 346 if (ieee->LeisurePSLeave) 347 ieee->LeisurePSLeave(ieee->dev); 348 /* notify AP to be in PS mode */ 349 rtllib_sta_ps_send_null_frame(ieee, 1); 350 rtllib_sta_ps_send_null_frame(ieee, 1); 351 352 rtllib_stop_all_queues(ieee); 353 354 if (ieee->data_hard_stop) 355 ieee->data_hard_stop(ieee->dev); 356 rtllib_stop_send_beacons(ieee); 357 ieee->state = RTLLIB_LINKED_SCANNING; 358 ieee->link_change(ieee->dev); 359 /* wait for ps packet to be kicked out successfully */ 360 msleep(50); 361 362 if (ieee->ScanOperationBackupHandler) 363 ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP); 364 365 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && 366 ieee->pHTInfo->bCurBW40MHz) { 367 b40M = 1; 368 chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; 369 bandwidth = (enum ht_channel_width)ieee->pHTInfo->bCurBW40MHz; 370 RT_TRACE(COMP_DBG, "Scan in 40M, force to 20M first:%d, %d\n", 371 chan_offset, bandwidth); 372 ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, 373 HT_EXTCHNL_OFFSET_NO_EXT); 374 } 375 376 rtllib_start_scan_syncro(ieee, 0); 377 378 if (b40M) { 379 RT_TRACE(COMP_DBG, "Scan in 20M, back to 40M\n"); 380 if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) 381 ieee->set_chan(ieee->dev, chan + 2); 382 else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) 383 ieee->set_chan(ieee->dev, chan - 2); 384 else 385 ieee->set_chan(ieee->dev, chan); 386 ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); 387 } else { 388 ieee->set_chan(ieee->dev, chan); 389 } 390 391 if (ieee->ScanOperationBackupHandler) 392 ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE); 393 394 ieee->state = RTLLIB_LINKED; 395 ieee->link_change(ieee->dev); 396 397 /* Notify AP that I wake up again */ 398 rtllib_sta_ps_send_null_frame(ieee, 0); 399 400 if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || 401 ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) { 402 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; 403 ieee->LinkDetectInfo.NumRecvDataInPeriod = 1; 404 } 405 406 if (ieee->data_hard_resume) 407 ieee->data_hard_resume(ieee->dev); 408 409 if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) 410 rtllib_start_send_beacons(ieee); 411 412 rtllib_wake_all_queues(ieee); 413 414 out: 415 mutex_unlock(&ieee->wx_mutex); 416 417 } 418 419 int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, 420 union iwreq_data *wrqu, char *b) 421 { 422 int ret = 0; 423 424 mutex_lock(&ieee->wx_mutex); 425 426 if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { 427 ret = -1; 428 goto out; 429 } 430 431 if (ieee->state == RTLLIB_LINKED) { 432 schedule_work(&ieee->wx_sync_scan_wq); 433 /* intentionally forget to up sem */ 434 return 0; 435 } 436 437 out: 438 mutex_unlock(&ieee->wx_mutex); 439 return ret; 440 } 441 EXPORT_SYMBOL(rtllib_wx_set_scan); 442 443 int rtllib_wx_set_essid(struct rtllib_device *ieee, 444 struct iw_request_info *a, 445 union iwreq_data *wrqu, char *extra) 446 { 447 448 int ret = 0, len, i; 449 short proto_started; 450 unsigned long flags; 451 452 rtllib_stop_scan_syncro(ieee); 453 mutex_lock(&ieee->wx_mutex); 454 455 proto_started = ieee->proto_started; 456 457 len = min_t(__u16, wrqu->essid.length, IW_ESSID_MAX_SIZE); 458 459 if (ieee->iw_mode == IW_MODE_MONITOR) { 460 ret = -1; 461 goto out; 462 } 463 464 for (i = 0; i < len; i++) { 465 if (extra[i] < 0) { 466 ret = -1; 467 goto out; 468 } 469 } 470 471 if (proto_started) 472 rtllib_stop_protocol(ieee, true); 473 474 475 /* this is just to be sure that the GET wx callback 476 * has consistent infos. not needed otherwise 477 */ 478 spin_lock_irqsave(&ieee->lock, flags); 479 480 if (wrqu->essid.flags && wrqu->essid.length) { 481 strncpy(ieee->current_network.ssid, extra, len); 482 ieee->current_network.ssid_len = len; 483 ieee->cannot_notify = false; 484 ieee->ssid_set = 1; 485 } else { 486 ieee->ssid_set = 0; 487 ieee->current_network.ssid[0] = '\0'; 488 ieee->current_network.ssid_len = 0; 489 } 490 spin_unlock_irqrestore(&ieee->lock, flags); 491 492 if (proto_started) 493 rtllib_start_protocol(ieee); 494 out: 495 mutex_unlock(&ieee->wx_mutex); 496 return ret; 497 } 498 EXPORT_SYMBOL(rtllib_wx_set_essid); 499 500 int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, 501 union iwreq_data *wrqu, char *b) 502 { 503 wrqu->mode = ieee->iw_mode; 504 return 0; 505 } 506 EXPORT_SYMBOL(rtllib_wx_get_mode); 507 508 int rtllib_wx_set_rawtx(struct rtllib_device *ieee, 509 struct iw_request_info *info, 510 union iwreq_data *wrqu, char *extra) 511 { 512 513 int *parms = (int *)extra; 514 int enable = (parms[0] > 0); 515 short prev = ieee->raw_tx; 516 517 mutex_lock(&ieee->wx_mutex); 518 519 if (enable) 520 ieee->raw_tx = 1; 521 else 522 ieee->raw_tx = 0; 523 524 netdev_info(ieee->dev, "raw TX is %s\n", 525 ieee->raw_tx ? "enabled" : "disabled"); 526 527 if (ieee->iw_mode == IW_MODE_MONITOR) { 528 if (prev == 0 && ieee->raw_tx) { 529 if (ieee->data_hard_resume) 530 ieee->data_hard_resume(ieee->dev); 531 532 netif_carrier_on(ieee->dev); 533 } 534 535 if (prev && ieee->raw_tx == 1) 536 netif_carrier_off(ieee->dev); 537 } 538 539 mutex_unlock(&ieee->wx_mutex); 540 541 return 0; 542 } 543 EXPORT_SYMBOL(rtllib_wx_set_rawtx); 544 545 int rtllib_wx_get_name(struct rtllib_device *ieee, 546 struct iw_request_info *info, 547 union iwreq_data *wrqu, char *extra) 548 { 549 strcpy(wrqu->name, "802.11"); 550 551 if (ieee->modulation & RTLLIB_CCK_MODULATION) 552 strcat(wrqu->name, "b"); 553 if (ieee->modulation & RTLLIB_OFDM_MODULATION) 554 strcat(wrqu->name, "g"); 555 if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) 556 strcat(wrqu->name, "n"); 557 return 0; 558 } 559 EXPORT_SYMBOL(rtllib_wx_get_name); 560 561 562 /* this is mostly stolen from hostap */ 563 int rtllib_wx_set_power(struct rtllib_device *ieee, 564 struct iw_request_info *info, 565 union iwreq_data *wrqu, char *extra) 566 { 567 int ret = 0; 568 569 if ((!ieee->sta_wake_up) || 570 (!ieee->enter_sleep_state) || 571 (!ieee->ps_is_queue_empty)) { 572 netdev_warn(ieee->dev, 573 "%s(): PS mode is tried to be use but driver missed a callback\n", 574 __func__); 575 return -1; 576 } 577 578 mutex_lock(&ieee->wx_mutex); 579 580 if (wrqu->power.disabled) { 581 RT_TRACE(COMP_DBG, "===>%s(): power disable\n", __func__); 582 ieee->ps = RTLLIB_PS_DISABLED; 583 goto exit; 584 } 585 if (wrqu->power.flags & IW_POWER_TIMEOUT) { 586 ieee->ps_timeout = wrqu->power.value / 1000; 587 RT_TRACE(COMP_DBG, "===>%s():ps_timeout is %d\n", __func__, 588 ieee->ps_timeout); 589 } 590 591 if (wrqu->power.flags & IW_POWER_PERIOD) 592 ieee->ps_period = wrqu->power.value / 1000; 593 594 switch (wrqu->power.flags & IW_POWER_MODE) { 595 case IW_POWER_UNICAST_R: 596 ieee->ps = RTLLIB_PS_UNICAST; 597 break; 598 case IW_POWER_MULTICAST_R: 599 ieee->ps = RTLLIB_PS_MBCAST; 600 break; 601 case IW_POWER_ALL_R: 602 ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST; 603 break; 604 605 case IW_POWER_ON: 606 break; 607 608 default: 609 ret = -EINVAL; 610 goto exit; 611 612 } 613 exit: 614 mutex_unlock(&ieee->wx_mutex); 615 return ret; 616 617 } 618 EXPORT_SYMBOL(rtllib_wx_set_power); 619 620 /* this is stolen from hostap */ 621 int rtllib_wx_get_power(struct rtllib_device *ieee, 622 struct iw_request_info *info, 623 union iwreq_data *wrqu, char *extra) 624 { 625 mutex_lock(&ieee->wx_mutex); 626 627 if (ieee->ps == RTLLIB_PS_DISABLED) { 628 wrqu->power.disabled = 1; 629 goto exit; 630 } 631 632 wrqu->power.disabled = 0; 633 634 if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { 635 wrqu->power.flags = IW_POWER_TIMEOUT; 636 wrqu->power.value = ieee->ps_timeout * 1000; 637 } else { 638 wrqu->power.flags = IW_POWER_PERIOD; 639 wrqu->power.value = ieee->ps_period * 1000; 640 } 641 642 if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == 643 (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) 644 wrqu->power.flags |= IW_POWER_ALL_R; 645 else if (ieee->ps & RTLLIB_PS_MBCAST) 646 wrqu->power.flags |= IW_POWER_MULTICAST_R; 647 else 648 wrqu->power.flags |= IW_POWER_UNICAST_R; 649 650 exit: 651 mutex_unlock(&ieee->wx_mutex); 652 return 0; 653 654 } 655 EXPORT_SYMBOL(rtllib_wx_get_power); 656