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