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