]>
Commit | Line | Data |
---|---|---|
ecdfa446 GKH |
1 | /* IEEE 802.11 SoftMAC layer |
2 | * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it> | |
3 | * | |
4 | * Mostly extracted from the rtl8180-sa2400 driver for the | |
5 | * in-kernel generic ieee802.11 stack. | |
6 | * | |
7 | * Some pieces of code might be stolen from ipw2100 driver | |
8 | * copyright of who own it's copyright ;-) | |
9 | * | |
10 | * PS wx handler mostly stolen from hostap, copyright who | |
11 | * own it's copyright ;-) | |
12 | * | |
13 | * released under the GPL | |
14 | */ | |
15 | ||
16 | ||
94a79942 LF |
17 | #include "rtllib.h" |
18 | #include "rtl_core.h" | |
ecdfa446 GKH |
19 | #ifdef ENABLE_DOT11D |
20 | #include "dot11d.h" | |
21 | #endif | |
22 | /* FIXME: add A freqs */ | |
23 | ||
94a79942 | 24 | const long rtllib_wlan_frequencies[] = { |
ecdfa446 GKH |
25 | 2412, 2417, 2422, 2427, |
26 | 2432, 2437, 2442, 2447, | |
27 | 2452, 2457, 2462, 2467, | |
28 | 2472, 2484 | |
29 | }; | |
30 | ||
31 | ||
94a79942 | 32 | int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, |
ecdfa446 GKH |
33 | union iwreq_data *wrqu, char *b) |
34 | { | |
35 | int ret; | |
36 | struct iw_freq *fwrq = & wrqu->freq; | |
37 | ||
38 | down(&ieee->wx_sem); | |
39 | ||
94a79942 LF |
40 | if (ieee->iw_mode == IW_MODE_INFRA){ |
41 | ret = 0; | |
ecdfa446 GKH |
42 | goto out; |
43 | } | |
44 | ||
45 | /* if setting by freq convert to channel */ | |
46 | if (fwrq->e == 1) { | |
47 | if ((fwrq->m >= (int) 2.412e8 && | |
48 | fwrq->m <= (int) 2.487e8)) { | |
49 | int f = fwrq->m / 100000; | |
50 | int c = 0; | |
51 | ||
94a79942 | 52 | while ((c < 14) && (f != rtllib_wlan_frequencies[c])) |
ecdfa446 GKH |
53 | c++; |
54 | ||
55 | /* hack to fall through */ | |
56 | fwrq->e = 0; | |
57 | fwrq->m = c + 1; | |
58 | } | |
59 | } | |
60 | ||
61 | if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){ | |
62 | ret = -EOPNOTSUPP; | |
63 | goto out; | |
64 | ||
65 | }else { /* Set the channel */ | |
66 | ||
67 | #ifdef ENABLE_DOT11D | |
94a79942 | 68 | if (ieee->active_channel_map[fwrq->m] != 1) { |
ecdfa446 GKH |
69 | ret = -EINVAL; |
70 | goto out; | |
71 | } | |
72 | #endif | |
73 | ieee->current_network.channel = fwrq->m; | |
94a79942 | 74 | ieee->set_chan(ieee->dev, ieee->current_network.channel); |
ecdfa446 | 75 | |
94a79942 LF |
76 | if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) |
77 | if (ieee->state == RTLLIB_LINKED){ | |
ecdfa446 | 78 | |
94a79942 LF |
79 | rtllib_stop_send_beacons(ieee); |
80 | rtllib_start_send_beacons(ieee); | |
ecdfa446 GKH |
81 | } |
82 | } | |
83 | ||
84 | ret = 0; | |
85 | out: | |
86 | up(&ieee->wx_sem); | |
87 | return ret; | |
88 | } | |
89 | ||
90 | ||
94a79942 | 91 | int rtllib_wx_get_freq(struct rtllib_device *ieee, |
ecdfa446 GKH |
92 | struct iw_request_info *a, |
93 | union iwreq_data *wrqu, char *b) | |
94 | { | |
95 | struct iw_freq *fwrq = & wrqu->freq; | |
96 | ||
97 | if (ieee->current_network.channel == 0) | |
98 | return -1; | |
94a79942 | 99 | fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] * 100000; |
ecdfa446 | 100 | fwrq->e = 1; |
ecdfa446 GKH |
101 | return 0; |
102 | } | |
103 | ||
94a79942 | 104 | int rtllib_wx_get_wap(struct rtllib_device *ieee, |
ecdfa446 GKH |
105 | struct iw_request_info *info, |
106 | union iwreq_data *wrqu, char *extra) | |
107 | { | |
108 | unsigned long flags; | |
94a79942 | 109 | |
ecdfa446 GKH |
110 | wrqu->ap_addr.sa_family = ARPHRD_ETHER; |
111 | ||
112 | if (ieee->iw_mode == IW_MODE_MONITOR) | |
113 | return -1; | |
114 | ||
115 | /* We want avoid to give to the user inconsistent infos*/ | |
116 | spin_lock_irqsave(&ieee->lock, flags); | |
117 | ||
94a79942 LF |
118 | if (ieee->state != RTLLIB_LINKED && |
119 | ieee->state != RTLLIB_LINKED_SCANNING && | |
ecdfa446 GKH |
120 | ieee->wap_set == 0) |
121 | ||
122 | memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); | |
123 | else | |
124 | memcpy(wrqu->ap_addr.sa_data, | |
125 | ieee->current_network.bssid, ETH_ALEN); | |
126 | ||
127 | spin_unlock_irqrestore(&ieee->lock, flags); | |
128 | ||
129 | return 0; | |
130 | } | |
131 | ||
132 | ||
94a79942 | 133 | int rtllib_wx_set_wap(struct rtllib_device *ieee, |
ecdfa446 GKH |
134 | struct iw_request_info *info, |
135 | union iwreq_data *awrq, | |
136 | char *extra) | |
137 | { | |
138 | ||
139 | int ret = 0; | |
140 | u8 zero[] = {0,0,0,0,0,0}; | |
141 | unsigned long flags; | |
142 | ||
94a79942 | 143 | short ifup = ieee->proto_started; |
ecdfa446 GKH |
144 | struct sockaddr *temp = (struct sockaddr *)awrq; |
145 | ||
94a79942 | 146 | rtllib_stop_scan_syncro(ieee); |
ecdfa446 GKH |
147 | |
148 | down(&ieee->wx_sem); | |
149 | /* use ifconfig hw ether */ | |
150 | if (ieee->iw_mode == IW_MODE_MASTER){ | |
151 | ret = -1; | |
152 | goto out; | |
153 | } | |
154 | ||
155 | if (temp->sa_family != ARPHRD_ETHER){ | |
156 | ret = -EINVAL; | |
157 | goto out; | |
158 | } | |
159 | ||
94a79942 LF |
160 | if (memcmp(temp->sa_data, zero,ETH_ALEN) == 0){ |
161 | spin_lock_irqsave(&ieee->lock, flags); | |
162 | memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); | |
163 | ieee->wap_set = 0; | |
164 | spin_unlock_irqrestore(&ieee->lock, flags); | |
165 | ret = -1; | |
166 | goto out; | |
167 | } | |
168 | ||
169 | ||
ecdfa446 | 170 | if (ifup) |
94a79942 | 171 | rtllib_stop_protocol(ieee,true); |
ecdfa446 GKH |
172 | |
173 | /* just to avoid to give inconsistent infos in the | |
174 | * get wx method. not really needed otherwise | |
175 | */ | |
176 | spin_lock_irqsave(&ieee->lock, flags); | |
177 | ||
94a79942 | 178 | ieee->cannot_notify = false; |
ecdfa446 | 179 | memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); |
94a79942 | 180 | ieee->wap_set = (memcmp(temp->sa_data, zero,ETH_ALEN)!=0); |
ecdfa446 GKH |
181 | |
182 | spin_unlock_irqrestore(&ieee->lock, flags); | |
183 | ||
184 | if (ifup) | |
94a79942 | 185 | rtllib_start_protocol(ieee); |
ecdfa446 GKH |
186 | out: |
187 | up(&ieee->wx_sem); | |
188 | return ret; | |
189 | } | |
190 | ||
94a79942 | 191 | int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b) |
ecdfa446 GKH |
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 | ||
94a79942 LF |
208 | if (ieee->state != RTLLIB_LINKED && |
209 | ieee->state != RTLLIB_LINKED_SCANNING && | |
ecdfa446 GKH |
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 | ||
94a79942 | 226 | int rtllib_wx_set_rate(struct rtllib_device *ieee, |
ecdfa446 GKH |
227 | struct iw_request_info *info, |
228 | union iwreq_data *wrqu, char *extra) | |
229 | { | |
230 | ||
231 | u32 target_rate = wrqu->bitrate.value; | |
232 | ||
233 | ieee->rate = target_rate/100000; | |
ecdfa446 GKH |
234 | return 0; |
235 | } | |
236 | ||
94a79942 | 237 | int rtllib_wx_get_rate(struct rtllib_device *ieee, |
ecdfa446 GKH |
238 | struct iw_request_info *info, |
239 | union iwreq_data *wrqu, char *extra) | |
240 | { | |
94a79942 LF |
241 | u32 tmp_rate = 0; |
242 | #if defined RTL8192SU | |
243 | if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G)) | |
244 | tmp_rate = ieee->rate; | |
245 | else if (ieee->mode & IEEE_N_5G) | |
246 | tmp_rate = 580; | |
247 | else if (ieee->mode & IEEE_N_24G) { | |
248 | if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) | |
249 | tmp_rate = HTHalfMcsToDataRate(ieee, 15); | |
250 | else | |
251 | tmp_rate = HTMcsToDataRate(ieee, 15); | |
252 | } | |
253 | #elif defined RTL8192SE || defined RTL8192CE | |
254 | tmp_rate = ieee->rtl_11n_user_show_rates(ieee->dev); | |
255 | #else | |
256 | tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate); | |
257 | #endif | |
ecdfa446 GKH |
258 | wrqu->bitrate.value = tmp_rate * 500000; |
259 | ||
260 | return 0; | |
261 | } | |
262 | ||
263 | ||
94a79942 | 264 | int rtllib_wx_set_rts(struct rtllib_device *ieee, |
ecdfa446 GKH |
265 | struct iw_request_info *info, |
266 | union iwreq_data *wrqu, char *extra) | |
267 | { | |
268 | if (wrqu->rts.disabled || !wrqu->rts.fixed) | |
269 | ieee->rts = DEFAULT_RTS_THRESHOLD; | |
270 | else | |
271 | { | |
272 | if (wrqu->rts.value < MIN_RTS_THRESHOLD || | |
273 | wrqu->rts.value > MAX_RTS_THRESHOLD) | |
274 | return -EINVAL; | |
275 | ieee->rts = wrqu->rts.value; | |
276 | } | |
277 | return 0; | |
278 | } | |
279 | ||
94a79942 | 280 | int rtllib_wx_get_rts(struct rtllib_device *ieee, |
ecdfa446 GKH |
281 | struct iw_request_info *info, |
282 | union iwreq_data *wrqu, char *extra) | |
283 | { | |
284 | wrqu->rts.value = ieee->rts; | |
285 | wrqu->rts.fixed = 0; /* no auto select */ | |
286 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); | |
287 | return 0; | |
288 | } | |
94a79942 LF |
289 | |
290 | int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, | |
ecdfa446 GKH |
291 | union iwreq_data *wrqu, char *b) |
292 | { | |
94a79942 | 293 | int set_mode_status = 0; |
ecdfa446 | 294 | |
94a79942 | 295 | rtllib_stop_scan_syncro(ieee); |
ecdfa446 | 296 | down(&ieee->wx_sem); |
94a79942 LF |
297 | switch (wrqu->mode) { |
298 | case IW_MODE_MONITOR: | |
299 | case IW_MODE_ADHOC: | |
300 | case IW_MODE_INFRA: | |
301 | break; | |
302 | case IW_MODE_AUTO: | |
303 | wrqu->mode = IW_MODE_INFRA; | |
304 | break; | |
305 | default: | |
306 | set_mode_status = -EINVAL; | |
307 | goto out; | |
308 | } | |
ecdfa446 GKH |
309 | |
310 | if (wrqu->mode == ieee->iw_mode) | |
311 | goto out; | |
312 | ||
94a79942 | 313 | if (wrqu->mode == IW_MODE_MONITOR) { |
ecdfa446 | 314 | ieee->dev->type = ARPHRD_IEEE80211; |
94a79942 | 315 | rtllib_EnableNetMonitorMode(ieee->dev,false); |
94a79942 | 316 | } else { |
ecdfa446 | 317 | ieee->dev->type = ARPHRD_ETHER; |
94a79942 LF |
318 | if (ieee->iw_mode == IW_MODE_MONITOR) |
319 | rtllib_DisableNetMonitorMode(ieee->dev,false); | |
ecdfa446 GKH |
320 | } |
321 | ||
94a79942 | 322 | if (!ieee->proto_started) { |
ecdfa446 | 323 | ieee->iw_mode = wrqu->mode; |
94a79942 LF |
324 | } else { |
325 | rtllib_stop_protocol(ieee,true); | |
ecdfa446 | 326 | ieee->iw_mode = wrqu->mode; |
94a79942 | 327 | rtllib_start_protocol(ieee); |
ecdfa446 GKH |
328 | } |
329 | ||
330 | out: | |
331 | up(&ieee->wx_sem); | |
94a79942 | 332 | return set_mode_status; |
ecdfa446 GKH |
333 | } |
334 | ||
94a79942 | 335 | void rtllib_wx_sync_scan_wq(void *data) |
ecdfa446 | 336 | { |
94a79942 | 337 | struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, wx_sync_scan_wq); |
ecdfa446 GKH |
338 | short chan; |
339 | HT_EXTCHNL_OFFSET chan_offset=0; | |
340 | HT_CHANNEL_WIDTH bandwidth=0; | |
341 | int b40M = 0; | |
342 | static int count = 0; | |
65a43784 | 343 | |
94a79942 LF |
344 | if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){ |
345 | rtllib_start_scan_syncro(ieee, 0); | |
346 | goto out; | |
65a43784 | 347 | } |
348 | ||
94a79942 LF |
349 | chan = ieee->current_network.channel; |
350 | ||
351 | if (ieee->LeisurePSLeave) | |
352 | ieee->LeisurePSLeave(ieee->dev); | |
65a43784 | 353 | /* notify AP to be in PS mode */ |
94a79942 LF |
354 | rtllib_sta_ps_send_null_frame(ieee, 1); |
355 | rtllib_sta_ps_send_null_frame(ieee, 1); | |
356 | ||
357 | rtllib_stop_all_queues(ieee); | |
65a43784 | 358 | |
ecdfa446 | 359 | if (ieee->data_hard_stop) |
94a79942 LF |
360 | ieee->data_hard_stop(ieee->dev); |
361 | rtllib_stop_send_beacons(ieee); | |
362 | ieee->state = RTLLIB_LINKED_SCANNING; | |
363 | ieee->link_change(ieee->dev); | |
364 | /* wait for ps packet to be kicked out successfully */ | |
365 | msleep(50); | |
ecdfa446 | 366 | |
94a79942 LF |
367 | if (ieee->ScanOperationBackupHandler) |
368 | ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_BACKUP); | |
ecdfa446 | 369 | |
ecdfa446 GKH |
370 | if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) { |
371 | b40M = 1; | |
372 | chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; | |
373 | bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz; | |
94a79942 LF |
374 | RT_TRACE(COMP_DBG, "Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth); |
375 | ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); | |
ecdfa446 | 376 | } |
94a79942 LF |
377 | |
378 | rtllib_start_scan_syncro(ieee, 0); | |
379 | ||
ecdfa446 | 380 | if (b40M) { |
94a79942 | 381 | RT_TRACE(COMP_DBG, "Scan in 20M, back to 40M\n"); |
ecdfa446 | 382 | if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) |
94a79942 | 383 | ieee->set_chan(ieee->dev, chan + 2); |
ecdfa446 | 384 | else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) |
94a79942 | 385 | ieee->set_chan(ieee->dev, chan - 2); |
ecdfa446 | 386 | else |
94a79942 LF |
387 | ieee->set_chan(ieee->dev, chan); |
388 | ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); | |
ecdfa446 | 389 | } else { |
94a79942 | 390 | ieee->set_chan(ieee->dev, chan); |
ecdfa446 GKH |
391 | } |
392 | ||
94a79942 LF |
393 | if (ieee->ScanOperationBackupHandler) |
394 | ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_RESTORE); | |
395 | ||
396 | ieee->state = RTLLIB_LINKED; | |
397 | ieee->link_change(ieee->dev); | |
65a43784 | 398 | |
65a43784 | 399 | /* Notify AP that I wake up again */ |
94a79942 | 400 | rtllib_sta_ps_send_null_frame(ieee, 0); |
65a43784 | 401 | |
94a79942 LF |
402 | if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || |
403 | ieee->LinkDetectInfo.NumRecvDataInPeriod == 0 ) { | |
ecdfa446 GKH |
404 | ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; |
405 | ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; | |
406 | } | |
94a79942 | 407 | |
ecdfa446 | 408 | if (ieee->data_hard_resume) |
94a79942 | 409 | ieee->data_hard_resume(ieee->dev); |
ecdfa446 | 410 | |
94a79942 LF |
411 | if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) |
412 | rtllib_start_send_beacons(ieee); | |
413 | ||
414 | rtllib_wake_all_queues(ieee); | |
ecdfa446 | 415 | |
ecdfa446 | 416 | count = 0; |
94a79942 | 417 | out: |
ecdfa446 GKH |
418 | up(&ieee->wx_sem); |
419 | ||
420 | } | |
421 | ||
94a79942 | 422 | int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, |
ecdfa446 GKH |
423 | union iwreq_data *wrqu, char *b) |
424 | { | |
425 | int ret = 0; | |
426 | ||
427 | down(&ieee->wx_sem); | |
428 | ||
429 | if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){ | |
430 | ret = -1; | |
431 | goto out; | |
432 | } | |
433 | ||
94a79942 LF |
434 | if ( ieee->state == RTLLIB_LINKED){ |
435 | queue_work_rsl(ieee->wq, &ieee->wx_sync_scan_wq); | |
ecdfa446 GKH |
436 | /* intentionally forget to up sem */ |
437 | return 0; | |
438 | } | |
439 | ||
440 | out: | |
441 | up(&ieee->wx_sem); | |
442 | return ret; | |
443 | } | |
444 | ||
94a79942 | 445 | int rtllib_wx_set_essid(struct rtllib_device *ieee, |
ecdfa446 GKH |
446 | struct iw_request_info *a, |
447 | union iwreq_data *wrqu, char *extra) | |
448 | { | |
449 | ||
94a79942 | 450 | int ret=0,len,i; |
ecdfa446 GKH |
451 | short proto_started; |
452 | unsigned long flags; | |
453 | ||
94a79942 | 454 | rtllib_stop_scan_syncro(ieee); |
ecdfa446 GKH |
455 | down(&ieee->wx_sem); |
456 | ||
457 | proto_started = ieee->proto_started; | |
458 | ||
94a79942 | 459 | len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE; |
94a79942 LF |
460 | |
461 | if (len > IW_ESSID_MAX_SIZE){ | |
ecdfa446 GKH |
462 | ret= -E2BIG; |
463 | goto out; | |
464 | } | |
465 | ||
466 | if (ieee->iw_mode == IW_MODE_MONITOR){ | |
467 | ret= -1; | |
468 | goto out; | |
469 | } | |
470 | ||
94a79942 LF |
471 | for (i=0; i<len; i++){ |
472 | if (extra[i] < 0){ | |
473 | ret= -1; | |
474 | goto out; | |
475 | } | |
65a43784 | 476 | } |
ecdfa446 | 477 | |
94a79942 LF |
478 | if (proto_started) |
479 | rtllib_stop_protocol(ieee,true); | |
480 | ||
ecdfa446 GKH |
481 | |
482 | /* this is just to be sure that the GET wx callback | |
483 | * has consisten infos. not needed otherwise | |
484 | */ | |
485 | spin_lock_irqsave(&ieee->lock, flags); | |
486 | ||
487 | if (wrqu->essid.flags && wrqu->essid.length) { | |
94a79942 LF |
488 | strncpy(ieee->current_network.ssid, extra, len); |
489 | ieee->current_network.ssid_len = len; | |
490 | ieee->cannot_notify = false; | |
ecdfa446 GKH |
491 | ieee->ssid_set = 1; |
492 | } | |
493 | else{ | |
494 | ieee->ssid_set = 0; | |
495 | ieee->current_network.ssid[0] = '\0'; | |
496 | ieee->current_network.ssid_len = 0; | |
497 | } | |
498 | spin_unlock_irqrestore(&ieee->lock, flags); | |
499 | ||
500 | if (proto_started) | |
94a79942 | 501 | rtllib_start_protocol(ieee); |
ecdfa446 GKH |
502 | out: |
503 | up(&ieee->wx_sem); | |
504 | return ret; | |
505 | } | |
506 | ||
94a79942 | 507 | int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, |
ecdfa446 GKH |
508 | union iwreq_data *wrqu, char *b) |
509 | { | |
ecdfa446 GKH |
510 | wrqu->mode = ieee->iw_mode; |
511 | return 0; | |
512 | } | |
513 | ||
94a79942 | 514 | int rtllib_wx_set_rawtx(struct rtllib_device *ieee, |
ecdfa446 GKH |
515 | struct iw_request_info *info, |
516 | union iwreq_data *wrqu, char *extra) | |
517 | { | |
518 | ||
519 | int *parms = (int *)extra; | |
520 | int enable = (parms[0] > 0); | |
521 | short prev = ieee->raw_tx; | |
522 | ||
523 | down(&ieee->wx_sem); | |
524 | ||
94a79942 | 525 | if (enable) |
ecdfa446 GKH |
526 | ieee->raw_tx = 1; |
527 | else | |
528 | ieee->raw_tx = 0; | |
529 | ||
530 | printk(KERN_INFO"raw TX is %s\n", | |
531 | ieee->raw_tx ? "enabled" : "disabled"); | |
532 | ||
94a79942 | 533 | if (ieee->iw_mode == IW_MODE_MONITOR) |
ecdfa446 | 534 | { |
94a79942 | 535 | if (prev == 0 && ieee->raw_tx){ |
ecdfa446 | 536 | if (ieee->data_hard_resume) |
94a79942 | 537 | ieee->data_hard_resume(ieee->dev); |
ecdfa446 GKH |
538 | |
539 | netif_carrier_on(ieee->dev); | |
540 | } | |
541 | ||
94a79942 | 542 | if (prev && ieee->raw_tx == 1) |
ecdfa446 GKH |
543 | netif_carrier_off(ieee->dev); |
544 | } | |
545 | ||
546 | up(&ieee->wx_sem); | |
547 | ||
548 | return 0; | |
549 | } | |
550 | ||
94a79942 | 551 | int rtllib_wx_get_name(struct rtllib_device *ieee, |
ecdfa446 GKH |
552 | struct iw_request_info *info, |
553 | union iwreq_data *wrqu, char *extra) | |
554 | { | |
555 | strcpy(wrqu->name, "802.11"); | |
94a79942 LF |
556 | |
557 | if (ieee->modulation & RTLLIB_CCK_MODULATION) | |
ecdfa446 | 558 | strcat(wrqu->name, "b"); |
94a79942 | 559 | if (ieee->modulation & RTLLIB_OFDM_MODULATION) |
ecdfa446 GKH |
560 | strcat(wrqu->name, "g"); |
561 | if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) | |
3ef5a262 | 562 | strcat(wrqu->name, "n"); |
ecdfa446 GKH |
563 | return 0; |
564 | } | |
565 | ||
566 | ||
567 | /* this is mostly stolen from hostap */ | |
94a79942 | 568 | int rtllib_wx_set_power(struct rtllib_device *ieee, |
ecdfa446 GKH |
569 | struct iw_request_info *info, |
570 | union iwreq_data *wrqu, char *extra) | |
571 | { | |
572 | int ret = 0; | |
94a79942 LF |
573 | #if 1 |
574 | if ( | |
ecdfa446 | 575 | (!ieee->sta_wake_up) || |
ecdfa446 GKH |
576 | (!ieee->enter_sleep_state) || |
577 | (!ieee->ps_is_queue_empty)){ | |
578 | ||
94a79942 LF |
579 | RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): PS mode is tryied to be use but driver missed a callback\n\n",__func__); |
580 | ||
ecdfa446 GKH |
581 | return -1; |
582 | } | |
94a79942 | 583 | #endif |
ecdfa446 GKH |
584 | down(&ieee->wx_sem); |
585 | ||
586 | if (wrqu->power.disabled){ | |
94a79942 LF |
587 | RT_TRACE(COMP_DBG, "===>%s(): power disable\n",__func__); |
588 | ieee->ps = RTLLIB_PS_DISABLED; | |
ecdfa446 GKH |
589 | goto exit; |
590 | } | |
591 | if (wrqu->power.flags & IW_POWER_TIMEOUT) { | |
ecdfa446 | 592 | ieee->ps_timeout = wrqu->power.value / 1000; |
94a79942 | 593 | RT_TRACE(COMP_DBG, "===>%s():ps_timeout is %d\n",__func__,ieee->ps_timeout); |
ecdfa446 GKH |
594 | } |
595 | ||
596 | if (wrqu->power.flags & IW_POWER_PERIOD) { | |
94a79942 | 597 | |
ecdfa446 | 598 | ieee->ps_period = wrqu->power.value / 1000; |
94a79942 | 599 | |
ecdfa446 GKH |
600 | } |
601 | switch (wrqu->power.flags & IW_POWER_MODE) { | |
602 | case IW_POWER_UNICAST_R: | |
94a79942 | 603 | ieee->ps = RTLLIB_PS_UNICAST; |
ecdfa446 GKH |
604 | break; |
605 | case IW_POWER_MULTICAST_R: | |
94a79942 | 606 | ieee->ps = RTLLIB_PS_MBCAST; |
ecdfa446 GKH |
607 | break; |
608 | case IW_POWER_ALL_R: | |
94a79942 | 609 | ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST; |
ecdfa446 GKH |
610 | break; |
611 | ||
612 | case IW_POWER_ON: | |
ecdfa446 GKH |
613 | break; |
614 | ||
615 | default: | |
616 | ret = -EINVAL; | |
617 | goto exit; | |
618 | ||
619 | } | |
620 | exit: | |
621 | up(&ieee->wx_sem); | |
622 | return ret; | |
623 | ||
624 | } | |
625 | ||
626 | /* this is stolen from hostap */ | |
94a79942 | 627 | int rtllib_wx_get_power(struct rtllib_device *ieee, |
ecdfa446 GKH |
628 | struct iw_request_info *info, |
629 | union iwreq_data *wrqu, char *extra) | |
630 | { | |
631 | int ret =0; | |
632 | ||
633 | down(&ieee->wx_sem); | |
634 | ||
94a79942 | 635 | if (ieee->ps == RTLLIB_PS_DISABLED) { |
ecdfa446 GKH |
636 | wrqu->power.disabled = 1; |
637 | goto exit; | |
638 | } | |
639 | ||
640 | wrqu->power.disabled = 0; | |
641 | ||
642 | if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { | |
643 | wrqu->power.flags = IW_POWER_TIMEOUT; | |
644 | wrqu->power.value = ieee->ps_timeout * 1000; | |
645 | } else { | |
ecdfa446 GKH |
646 | wrqu->power.flags = IW_POWER_PERIOD; |
647 | wrqu->power.value = ieee->ps_period * 1000; | |
ecdfa446 GKH |
648 | } |
649 | ||
94a79942 LF |
650 | if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) |
651 | wrqu->power.flags |= IW_POWER_ALL_R; | |
652 | else if (ieee->ps & RTLLIB_PS_MBCAST) | |
ecdfa446 GKH |
653 | wrqu->power.flags |= IW_POWER_MULTICAST_R; |
654 | else | |
655 | wrqu->power.flags |= IW_POWER_UNICAST_R; | |
656 | ||
657 | exit: | |
658 | up(&ieee->wx_sem); | |
659 | return ret; | |
660 | ||
661 | } |