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