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