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 ieee->LeisurePSLeave(ieee->dev); 344 /* notify AP to be in PS mode */ 345 rtllib_sta_ps_send_null_frame(ieee, 1); 346 rtllib_sta_ps_send_null_frame(ieee, 1); 347 348 rtllib_stop_all_queues(ieee); 349 350 if (ieee->data_hard_stop) 351 ieee->data_hard_stop(ieee->dev); 352 rtllib_stop_send_beacons(ieee); 353 ieee->state = RTLLIB_LINKED_SCANNING; 354 ieee->link_change(ieee->dev); 355 /* wait for ps packet to be kicked out successfully */ 356 msleep(50); 357 358 if (ieee->ScanOperationBackupHandler) 359 ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP); 360 361 if (ieee->ht_info->bCurrentHTSupport && ieee->ht_info->enable_ht && 362 ieee->ht_info->bCurBW40MHz) { 363 b40M = 1; 364 chan_offset = ieee->ht_info->CurSTAExtChnlOffset; 365 bandwidth = (enum ht_channel_width)ieee->ht_info->bCurBW40MHz; 366 ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, 367 HT_EXTCHNL_OFFSET_NO_EXT); 368 } 369 370 rtllib_start_scan_syncro(ieee, 0); 371 372 if (b40M) { 373 if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) 374 ieee->set_chan(ieee->dev, chan + 2); 375 else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) 376 ieee->set_chan(ieee->dev, chan - 2); 377 else 378 ieee->set_chan(ieee->dev, chan); 379 ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); 380 } else { 381 ieee->set_chan(ieee->dev, chan); 382 } 383 384 if (ieee->ScanOperationBackupHandler) 385 ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE); 386 387 ieee->state = RTLLIB_LINKED; 388 ieee->link_change(ieee->dev); 389 390 /* Notify AP that I wake up again */ 391 rtllib_sta_ps_send_null_frame(ieee, 0); 392 393 if (ieee->link_detect_info.NumRecvBcnInPeriod == 0 || 394 ieee->link_detect_info.NumRecvDataInPeriod == 0) { 395 ieee->link_detect_info.NumRecvBcnInPeriod = 1; 396 ieee->link_detect_info.NumRecvDataInPeriod = 1; 397 } 398 399 if (ieee->data_hard_resume) 400 ieee->data_hard_resume(ieee->dev); 401 402 if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) 403 rtllib_start_send_beacons(ieee); 404 405 rtllib_wake_all_queues(ieee); 406 407 out: 408 mutex_unlock(&ieee->wx_mutex); 409 410 } 411 412 int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, 413 union iwreq_data *wrqu, char *b) 414 { 415 int ret = 0; 416 417 mutex_lock(&ieee->wx_mutex); 418 419 if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { 420 ret = -1; 421 goto out; 422 } 423 424 if (ieee->state == RTLLIB_LINKED) { 425 schedule_work(&ieee->wx_sync_scan_wq); 426 /* intentionally forget to up sem */ 427 return 0; 428 } 429 430 out: 431 mutex_unlock(&ieee->wx_mutex); 432 return ret; 433 } 434 EXPORT_SYMBOL(rtllib_wx_set_scan); 435 436 int rtllib_wx_set_essid(struct rtllib_device *ieee, 437 struct iw_request_info *a, 438 union iwreq_data *wrqu, char *extra) 439 { 440 441 int ret = 0, len; 442 short proto_started; 443 unsigned long flags; 444 445 rtllib_stop_scan_syncro(ieee); 446 mutex_lock(&ieee->wx_mutex); 447 448 proto_started = ieee->proto_started; 449 450 len = min_t(__u16, wrqu->essid.length, IW_ESSID_MAX_SIZE); 451 452 if (ieee->iw_mode == IW_MODE_MONITOR) { 453 ret = -1; 454 goto out; 455 } 456 457 if (proto_started) 458 rtllib_stop_protocol(ieee, true); 459 460 461 /* this is just to be sure that the GET wx callback 462 * has consistent infos. not needed otherwise 463 */ 464 spin_lock_irqsave(&ieee->lock, flags); 465 466 if (wrqu->essid.flags && wrqu->essid.length) { 467 strncpy(ieee->current_network.ssid, extra, len); 468 ieee->current_network.ssid_len = len; 469 ieee->cannot_notify = false; 470 ieee->ssid_set = 1; 471 } else { 472 ieee->ssid_set = 0; 473 ieee->current_network.ssid[0] = '\0'; 474 ieee->current_network.ssid_len = 0; 475 } 476 spin_unlock_irqrestore(&ieee->lock, flags); 477 478 if (proto_started) 479 rtllib_start_protocol(ieee); 480 out: 481 mutex_unlock(&ieee->wx_mutex); 482 return ret; 483 } 484 EXPORT_SYMBOL(rtllib_wx_set_essid); 485 486 int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, 487 union iwreq_data *wrqu, char *b) 488 { 489 wrqu->mode = ieee->iw_mode; 490 return 0; 491 } 492 EXPORT_SYMBOL(rtllib_wx_get_mode); 493 494 int rtllib_wx_set_rawtx(struct rtllib_device *ieee, 495 struct iw_request_info *info, 496 union iwreq_data *wrqu, char *extra) 497 { 498 499 int *parms = (int *)extra; 500 int enable = (parms[0] > 0); 501 short prev = ieee->raw_tx; 502 503 mutex_lock(&ieee->wx_mutex); 504 505 if (enable) 506 ieee->raw_tx = 1; 507 else 508 ieee->raw_tx = 0; 509 510 netdev_info(ieee->dev, "raw TX is %s\n", 511 ieee->raw_tx ? "enabled" : "disabled"); 512 513 if (ieee->iw_mode == IW_MODE_MONITOR) { 514 if (prev == 0 && ieee->raw_tx) { 515 if (ieee->data_hard_resume) 516 ieee->data_hard_resume(ieee->dev); 517 518 netif_carrier_on(ieee->dev); 519 } 520 521 if (prev && ieee->raw_tx == 1) 522 netif_carrier_off(ieee->dev); 523 } 524 525 mutex_unlock(&ieee->wx_mutex); 526 527 return 0; 528 } 529 EXPORT_SYMBOL(rtllib_wx_set_rawtx); 530 531 int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info, 532 union iwreq_data *wrqu, char *extra) 533 { 534 const char *b = ieee->modulation & RTLLIB_CCK_MODULATION ? "b" : ""; 535 const char *g = ieee->modulation & RTLLIB_OFDM_MODULATION ? "g" : ""; 536 const char *n = ieee->mode & (IEEE_N_24G | IEEE_N_5G) ? "n" : ""; 537 538 scnprintf(wrqu->name, sizeof(wrqu->name), "802.11%s%s%s", b, g, n); 539 return 0; 540 } 541 EXPORT_SYMBOL(rtllib_wx_get_name); 542 543 544 /* this is mostly stolen from hostap */ 545 int rtllib_wx_set_power(struct rtllib_device *ieee, 546 struct iw_request_info *info, 547 union iwreq_data *wrqu, char *extra) 548 { 549 int ret = 0; 550 551 if ((!ieee->sta_wake_up) || 552 (!ieee->enter_sleep_state) || 553 (!ieee->ps_is_queue_empty)) { 554 netdev_warn(ieee->dev, 555 "%s(): PS mode is tried to be use but driver missed a callback\n", 556 __func__); 557 return -1; 558 } 559 560 mutex_lock(&ieee->wx_mutex); 561 562 if (wrqu->power.disabled) { 563 ieee->ps = RTLLIB_PS_DISABLED; 564 goto exit; 565 } 566 if (wrqu->power.flags & IW_POWER_TIMEOUT) 567 ieee->ps_timeout = wrqu->power.value / 1000; 568 569 if (wrqu->power.flags & IW_POWER_PERIOD) 570 ieee->ps_period = wrqu->power.value / 1000; 571 572 switch (wrqu->power.flags & IW_POWER_MODE) { 573 case IW_POWER_UNICAST_R: 574 ieee->ps = RTLLIB_PS_UNICAST; 575 break; 576 case IW_POWER_MULTICAST_R: 577 ieee->ps = RTLLIB_PS_MBCAST; 578 break; 579 case IW_POWER_ALL_R: 580 ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST; 581 break; 582 583 case IW_POWER_ON: 584 break; 585 586 default: 587 ret = -EINVAL; 588 goto exit; 589 590 } 591 exit: 592 mutex_unlock(&ieee->wx_mutex); 593 return ret; 594 595 } 596 EXPORT_SYMBOL(rtllib_wx_set_power); 597 598 /* this is stolen from hostap */ 599 int rtllib_wx_get_power(struct rtllib_device *ieee, 600 struct iw_request_info *info, 601 union iwreq_data *wrqu, char *extra) 602 { 603 mutex_lock(&ieee->wx_mutex); 604 605 if (ieee->ps == RTLLIB_PS_DISABLED) { 606 wrqu->power.disabled = 1; 607 goto exit; 608 } 609 610 wrqu->power.disabled = 0; 611 612 if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { 613 wrqu->power.flags = IW_POWER_TIMEOUT; 614 wrqu->power.value = ieee->ps_timeout * 1000; 615 } else { 616 wrqu->power.flags = IW_POWER_PERIOD; 617 wrqu->power.value = ieee->ps_period * 1000; 618 } 619 620 if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == 621 (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) 622 wrqu->power.flags |= IW_POWER_ALL_R; 623 else if (ieee->ps & RTLLIB_PS_MBCAST) 624 wrqu->power.flags |= IW_POWER_MULTICAST_R; 625 else 626 wrqu->power.flags |= IW_POWER_UNICAST_R; 627 628 exit: 629 mutex_unlock(&ieee->wx_mutex); 630 return 0; 631 632 } 633 EXPORT_SYMBOL(rtllib_wx_get_power); 634