1 // SPDX-License-Identifier: GPL-2.0
2 /* IEEE 802.11 SoftMAC layer
3 * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
5 * Mostly extracted from the rtl8180-sa2400 driver for the
6 * in-kernel generic ieee802.11 stack.
8 * Some pieces of code might be stolen from ipw2100 driver
9 * copyright of who own it's copyright ;-)
11 * PS wx handler mostly stolen from hostap, copyright who
12 * own it's copyright ;-)
14 #include <linux/etherdevice.h>
18 /* FIXME: add A freqs */
20 const long rtllib_wlan_frequencies[] = {
21 2412, 2417, 2422, 2427,
22 2432, 2437, 2442, 2447,
23 2452, 2457, 2462, 2467,
26 EXPORT_SYMBOL(rtllib_wlan_frequencies);
29 int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
30 union iwreq_data *wrqu, char *b)
33 struct iw_freq *fwrq = &wrqu->freq;
35 mutex_lock(&ieee->wx_mutex);
37 if (ieee->iw_mode == IW_MODE_INFRA) {
42 /* if setting by freq convert to channel */
44 if ((fwrq->m >= (int) 2.412e8 &&
45 fwrq->m <= (int) 2.487e8)) {
46 int f = fwrq->m / 100000;
49 while ((c < 14) && (f != rtllib_wlan_frequencies[c]))
52 /* hack to fall through */
58 if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
62 } else { /* Set the channel */
64 if (ieee->active_channel_map[fwrq->m] != 1) {
68 ieee->current_network.channel = fwrq->m;
69 ieee->set_chan(ieee->dev, ieee->current_network.channel);
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);
81 mutex_unlock(&ieee->wx_mutex);
84 EXPORT_SYMBOL(rtllib_wx_set_freq);
87 int rtllib_wx_get_freq(struct rtllib_device *ieee,
88 struct iw_request_info *a,
89 union iwreq_data *wrqu, char *b)
91 struct iw_freq *fwrq = &wrqu->freq;
93 if (ieee->current_network.channel == 0)
95 fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] *
100 EXPORT_SYMBOL(rtllib_wx_get_freq);
102 int rtllib_wx_get_wap(struct rtllib_device *ieee,
103 struct iw_request_info *info,
104 union iwreq_data *wrqu, char *extra)
108 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
110 if (ieee->iw_mode == IW_MODE_MONITOR)
113 /* We want avoid to give to the user inconsistent infos*/
114 spin_lock_irqsave(&ieee->lock, flags);
116 if (ieee->state != RTLLIB_LINKED &&
117 ieee->state != RTLLIB_LINKED_SCANNING &&
120 eth_zero_addr(wrqu->ap_addr.sa_data);
122 memcpy(wrqu->ap_addr.sa_data,
123 ieee->current_network.bssid, ETH_ALEN);
125 spin_unlock_irqrestore(&ieee->lock, flags);
129 EXPORT_SYMBOL(rtllib_wx_get_wap);
132 int rtllib_wx_set_wap(struct rtllib_device *ieee,
133 struct iw_request_info *info,
134 union iwreq_data *awrq,
141 short ifup = ieee->proto_started;
142 struct sockaddr *temp = (struct sockaddr *)awrq;
144 rtllib_stop_scan_syncro(ieee);
146 mutex_lock(&ieee->wx_mutex);
147 /* use ifconfig hw ether */
148 if (ieee->iw_mode == IW_MODE_MASTER) {
153 if (temp->sa_family != ARPHRD_ETHER) {
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);
162 spin_unlock_irqrestore(&ieee->lock, flags);
169 rtllib_stop_protocol(ieee, true);
171 /* just to avoid to give inconsistent infos in the
172 * get wx method. not really needed otherwise
174 spin_lock_irqsave(&ieee->lock, flags);
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);
180 spin_unlock_irqrestore(&ieee->lock, flags);
183 rtllib_start_protocol(ieee);
185 mutex_unlock(&ieee->wx_mutex);
188 EXPORT_SYMBOL(rtllib_wx_set_wap);
190 int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,
191 union iwreq_data *wrqu, char *b)
196 if (ieee->iw_mode == IW_MODE_MONITOR)
199 /* We want avoid to give to the user inconsistent infos*/
200 spin_lock_irqsave(&ieee->lock, flags);
202 if (ieee->current_network.ssid[0] == '\0' ||
203 ieee->current_network.ssid_len == 0) {
208 if (ieee->state != RTLLIB_LINKED &&
209 ieee->state != RTLLIB_LINKED_SCANNING &&
210 ieee->ssid_set == 0) {
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;
220 spin_unlock_irqrestore(&ieee->lock, flags);
225 EXPORT_SYMBOL(rtllib_wx_get_essid);
227 int rtllib_wx_set_rate(struct rtllib_device *ieee,
228 struct iw_request_info *info,
229 union iwreq_data *wrqu, char *extra)
232 u32 target_rate = wrqu->bitrate.value;
234 ieee->rate = target_rate/100000;
237 EXPORT_SYMBOL(rtllib_wx_set_rate);
239 int rtllib_wx_get_rate(struct rtllib_device *ieee,
240 struct iw_request_info *info,
241 union iwreq_data *wrqu, char *extra)
245 tmp_rate = TxCountToDataRate(ieee,
246 ieee->softmac_stats.CurrentShowTxate);
247 wrqu->bitrate.value = tmp_rate * 500000;
251 EXPORT_SYMBOL(rtllib_wx_get_rate);
254 int rtllib_wx_set_rts(struct rtllib_device *ieee,
255 struct iw_request_info *info,
256 union iwreq_data *wrqu, char *extra)
258 if (wrqu->rts.disabled || !wrqu->rts.fixed)
259 ieee->rts = DEFAULT_RTS_THRESHOLD;
261 if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
262 wrqu->rts.value > MAX_RTS_THRESHOLD)
264 ieee->rts = wrqu->rts.value;
268 EXPORT_SYMBOL(rtllib_wx_set_rts);
270 int rtllib_wx_get_rts(struct rtllib_device *ieee,
271 struct iw_request_info *info,
272 union iwreq_data *wrqu, char *extra)
274 wrqu->rts.value = ieee->rts;
275 wrqu->rts.fixed = 0; /* no auto select */
276 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
279 EXPORT_SYMBOL(rtllib_wx_get_rts);
281 int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
282 union iwreq_data *wrqu, char *b)
284 int set_mode_status = 0;
286 rtllib_stop_scan_syncro(ieee);
287 mutex_lock(&ieee->wx_mutex);
288 switch (wrqu->mode) {
289 case IW_MODE_MONITOR:
294 wrqu->mode = IW_MODE_INFRA;
297 set_mode_status = -EINVAL;
301 if (wrqu->mode == ieee->iw_mode)
304 if (wrqu->mode == IW_MODE_MONITOR) {
305 ieee->dev->type = ARPHRD_IEEE80211;
306 rtllib_EnableNetMonitorMode(ieee->dev, false);
308 ieee->dev->type = ARPHRD_ETHER;
309 if (ieee->iw_mode == IW_MODE_MONITOR)
310 rtllib_DisableNetMonitorMode(ieee->dev, false);
313 if (!ieee->proto_started) {
314 ieee->iw_mode = wrqu->mode;
316 rtllib_stop_protocol(ieee, true);
317 ieee->iw_mode = wrqu->mode;
318 rtllib_start_protocol(ieee);
322 mutex_unlock(&ieee->wx_mutex);
323 return set_mode_status;
325 EXPORT_SYMBOL(rtllib_wx_set_mode);
327 void rtllib_wx_sync_scan_wq(void *data)
329 struct rtllib_device *ieee = container_of_work_rsl(data,
330 struct rtllib_device, wx_sync_scan_wq);
332 enum ht_extchnl_offset chan_offset = 0;
333 enum ht_channel_width bandwidth = 0;
336 if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
337 rtllib_start_scan_syncro(ieee, 0);
341 chan = ieee->current_network.channel;
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);
349 rtllib_stop_all_queues(ieee);
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 */
359 if (ieee->ScanOperationBackupHandler)
360 ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP);
362 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT &&
363 ieee->pHTInfo->bCurBW40MHz) {
365 chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
366 bandwidth = (enum ht_channel_width)ieee->pHTInfo->bCurBW40MHz;
367 RT_TRACE(COMP_DBG, "Scan in 40M, force to 20M first:%d, %d\n",
368 chan_offset, bandwidth);
369 ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20,
370 HT_EXTCHNL_OFFSET_NO_EXT);
373 rtllib_start_scan_syncro(ieee, 0);
376 RT_TRACE(COMP_DBG, "Scan in 20M, back to 40M\n");
377 if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
378 ieee->set_chan(ieee->dev, chan + 2);
379 else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
380 ieee->set_chan(ieee->dev, chan - 2);
382 ieee->set_chan(ieee->dev, chan);
383 ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
385 ieee->set_chan(ieee->dev, chan);
388 if (ieee->ScanOperationBackupHandler)
389 ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE);
391 ieee->state = RTLLIB_LINKED;
392 ieee->link_change(ieee->dev);
394 /* Notify AP that I wake up again */
395 rtllib_sta_ps_send_null_frame(ieee, 0);
397 if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 ||
398 ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
399 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
400 ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
403 if (ieee->data_hard_resume)
404 ieee->data_hard_resume(ieee->dev);
406 if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
407 rtllib_start_send_beacons(ieee);
409 rtllib_wake_all_queues(ieee);
412 mutex_unlock(&ieee->wx_mutex);
416 int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
417 union iwreq_data *wrqu, char *b)
421 mutex_lock(&ieee->wx_mutex);
423 if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
428 if (ieee->state == RTLLIB_LINKED) {
429 schedule_work(&ieee->wx_sync_scan_wq);
430 /* intentionally forget to up sem */
435 mutex_unlock(&ieee->wx_mutex);
438 EXPORT_SYMBOL(rtllib_wx_set_scan);
440 int rtllib_wx_set_essid(struct rtllib_device *ieee,
441 struct iw_request_info *a,
442 union iwreq_data *wrqu, char *extra)
449 rtllib_stop_scan_syncro(ieee);
450 mutex_lock(&ieee->wx_mutex);
452 proto_started = ieee->proto_started;
454 len = min_t(__u16, wrqu->essid.length, IW_ESSID_MAX_SIZE);
456 if (ieee->iw_mode == IW_MODE_MONITOR) {
461 for (i = 0; i < len; i++) {
469 rtllib_stop_protocol(ieee, true);
472 /* this is just to be sure that the GET wx callback
473 * has consistent infos. not needed otherwise
475 spin_lock_irqsave(&ieee->lock, flags);
477 if (wrqu->essid.flags && wrqu->essid.length) {
478 strncpy(ieee->current_network.ssid, extra, len);
479 ieee->current_network.ssid_len = len;
480 ieee->cannot_notify = false;
484 ieee->current_network.ssid[0] = '\0';
485 ieee->current_network.ssid_len = 0;
487 spin_unlock_irqrestore(&ieee->lock, flags);
490 rtllib_start_protocol(ieee);
492 mutex_unlock(&ieee->wx_mutex);
495 EXPORT_SYMBOL(rtllib_wx_set_essid);
497 int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
498 union iwreq_data *wrqu, char *b)
500 wrqu->mode = ieee->iw_mode;
503 EXPORT_SYMBOL(rtllib_wx_get_mode);
505 int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
506 struct iw_request_info *info,
507 union iwreq_data *wrqu, char *extra)
510 int *parms = (int *)extra;
511 int enable = (parms[0] > 0);
512 short prev = ieee->raw_tx;
514 mutex_lock(&ieee->wx_mutex);
521 netdev_info(ieee->dev, "raw TX is %s\n",
522 ieee->raw_tx ? "enabled" : "disabled");
524 if (ieee->iw_mode == IW_MODE_MONITOR) {
525 if (prev == 0 && ieee->raw_tx) {
526 if (ieee->data_hard_resume)
527 ieee->data_hard_resume(ieee->dev);
529 netif_carrier_on(ieee->dev);
532 if (prev && ieee->raw_tx == 1)
533 netif_carrier_off(ieee->dev);
536 mutex_unlock(&ieee->wx_mutex);
540 EXPORT_SYMBOL(rtllib_wx_set_rawtx);
542 int rtllib_wx_get_name(struct rtllib_device *ieee,
543 struct iw_request_info *info,
544 union iwreq_data *wrqu, char *extra)
546 strcpy(wrqu->name, "802.11");
548 if (ieee->modulation & RTLLIB_CCK_MODULATION)
549 strcat(wrqu->name, "b");
550 if (ieee->modulation & RTLLIB_OFDM_MODULATION)
551 strcat(wrqu->name, "g");
552 if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
553 strcat(wrqu->name, "n");
556 EXPORT_SYMBOL(rtllib_wx_get_name);
559 /* this is mostly stolen from hostap */
560 int rtllib_wx_set_power(struct rtllib_device *ieee,
561 struct iw_request_info *info,
562 union iwreq_data *wrqu, char *extra)
566 if ((!ieee->sta_wake_up) ||
567 (!ieee->enter_sleep_state) ||
568 (!ieee->ps_is_queue_empty)) {
569 netdev_warn(ieee->dev,
570 "%s(): PS mode is tried to be use but driver missed a callback\n",
575 mutex_lock(&ieee->wx_mutex);
577 if (wrqu->power.disabled) {
578 RT_TRACE(COMP_DBG, "===>%s(): power disable\n", __func__);
579 ieee->ps = RTLLIB_PS_DISABLED;
582 if (wrqu->power.flags & IW_POWER_TIMEOUT) {
583 ieee->ps_timeout = wrqu->power.value / 1000;
584 RT_TRACE(COMP_DBG, "===>%s():ps_timeout is %d\n", __func__,
588 if (wrqu->power.flags & IW_POWER_PERIOD)
589 ieee->ps_period = wrqu->power.value / 1000;
591 switch (wrqu->power.flags & IW_POWER_MODE) {
592 case IW_POWER_UNICAST_R:
593 ieee->ps = RTLLIB_PS_UNICAST;
595 case IW_POWER_MULTICAST_R:
596 ieee->ps = RTLLIB_PS_MBCAST;
599 ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST;
611 mutex_unlock(&ieee->wx_mutex);
615 EXPORT_SYMBOL(rtllib_wx_set_power);
617 /* this is stolen from hostap */
618 int rtllib_wx_get_power(struct rtllib_device *ieee,
619 struct iw_request_info *info,
620 union iwreq_data *wrqu, char *extra)
622 mutex_lock(&ieee->wx_mutex);
624 if (ieee->ps == RTLLIB_PS_DISABLED) {
625 wrqu->power.disabled = 1;
629 wrqu->power.disabled = 0;
631 if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
632 wrqu->power.flags = IW_POWER_TIMEOUT;
633 wrqu->power.value = ieee->ps_timeout * 1000;
635 wrqu->power.flags = IW_POWER_PERIOD;
636 wrqu->power.value = ieee->ps_period * 1000;
639 if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) ==
640 (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST))
641 wrqu->power.flags |= IW_POWER_ALL_R;
642 else if (ieee->ps & RTLLIB_PS_MBCAST)
643 wrqu->power.flags |= IW_POWER_MULTICAST_R;
645 wrqu->power.flags |= IW_POWER_UNICAST_R;
648 mutex_unlock(&ieee->wx_mutex);
652 EXPORT_SYMBOL(rtllib_wx_get_power);