1 /* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
7 * Some pieces of code might be stolen from ipw2100 driver
8 * copyright of who own it's copyright ;-)
10 * PS wx handler mostly stolen from hostap, copyright who
11 * own it's copyright ;-)
13 * released under the GPL
17 #include "ieee80211.h"
19 /* FIXME: add A freqs */
21 const long ieee80211_wlan_frequencies
[] = {
22 2412, 2417, 2422, 2427,
23 2432, 2437, 2442, 2447,
24 2452, 2457, 2462, 2467,
29 int ieee80211_wx_set_freq(struct ieee80211_device
*ieee
, struct iw_request_info
*a
,
30 union iwreq_data
*wrqu
, char *b
)
33 struct iw_freq
*fwrq
= & wrqu
->freq
;
34 // printk("in %s\n",__func__);
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
!= ieee80211_wlan_frequencies
[c
]))
52 /* hack to fall through */
58 if (fwrq
->e
> 0 || fwrq
->m
> 14 || fwrq
->m
< 1 ){
62 }else { /* Set the channel */
65 ieee
->current_network
.channel
= fwrq
->m
;
66 ieee
->set_chan(ieee
->dev
, ieee
->current_network
.channel
);
68 if(ieee
->iw_mode
== IW_MODE_ADHOC
|| ieee
->iw_mode
== IW_MODE_MASTER
)
69 if(ieee
->state
== IEEE80211_LINKED
){
71 ieee80211_stop_send_beacons(ieee
);
72 ieee80211_start_send_beacons(ieee
);
83 int ieee80211_wx_get_freq(struct ieee80211_device
*ieee
,
84 struct iw_request_info
*a
,
85 union iwreq_data
*wrqu
, char *b
)
87 struct iw_freq
*fwrq
= & wrqu
->freq
;
89 if (ieee
->current_network
.channel
== 0)
92 fwrq
->m
= ieee
->current_network
.channel
;
98 int ieee80211_wx_get_wap(struct ieee80211_device
*ieee
,
99 struct iw_request_info
*info
,
100 union iwreq_data
*wrqu
, char *extra
)
104 wrqu
->ap_addr
.sa_family
= ARPHRD_ETHER
;
106 if (ieee
->iw_mode
== IW_MODE_MONITOR
)
109 /* We want avoid to give to the user inconsistent infos*/
110 spin_lock_irqsave(&ieee
->lock
, flags
);
112 if (ieee
->state
!= IEEE80211_LINKED
&&
113 ieee
->state
!= IEEE80211_LINKED_SCANNING
&&
116 memset(wrqu
->ap_addr
.sa_data
, 0, ETH_ALEN
);
118 memcpy(wrqu
->ap_addr
.sa_data
,
119 ieee
->current_network
.bssid
, ETH_ALEN
);
121 spin_unlock_irqrestore(&ieee
->lock
, flags
);
127 int ieee80211_wx_set_wap(struct ieee80211_device
*ieee
,
128 struct iw_request_info
*info
,
129 union iwreq_data
*awrq
,
134 u8 zero
[] = {0,0,0,0,0,0};
137 short ifup
= ieee
->proto_started
;//dev->flags & IFF_UP;
138 struct sockaddr
*temp
= (struct sockaddr
*)awrq
;
140 //printk("=======Set WAP:");
141 ieee
->sync_scan_hurryup
= 1;
144 /* use ifconfig hw ether */
145 if (ieee
->iw_mode
== IW_MODE_MASTER
){
150 if (temp
->sa_family
!= ARPHRD_ETHER
){
156 ieee80211_stop_protocol(ieee
);
158 /* just to avoid to give inconsistent infos in the
159 * get wx method. not really needed otherwise
161 spin_lock_irqsave(&ieee
->lock
, flags
);
163 memcpy(ieee
->current_network
.bssid
, temp
->sa_data
, ETH_ALEN
);
164 ieee
->wap_set
= memcmp(temp
->sa_data
, zero
,ETH_ALEN
)!=0;
165 //printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]);
167 spin_unlock_irqrestore(&ieee
->lock
, flags
);
170 ieee80211_start_protocol(ieee
);
177 int ieee80211_wx_get_essid(struct ieee80211_device
*ieee
, struct iw_request_info
*a
,union iwreq_data
*wrqu
,char *b
)
182 if (ieee
->iw_mode
== IW_MODE_MONITOR
)
185 /* We want avoid to give to the user inconsistent infos*/
186 spin_lock_irqsave(&ieee
->lock
, flags
);
188 if (ieee
->current_network
.ssid
[0] == '\0' ||
189 ieee
->current_network
.ssid_len
== 0){
194 if (ieee
->state
!= IEEE80211_LINKED
&&
195 ieee
->state
!= IEEE80211_LINKED_SCANNING
&&
196 ieee
->ssid_set
== 0){
200 len
= ieee
->current_network
.ssid_len
;
201 wrqu
->essid
.length
= len
;
202 strncpy(b
,ieee
->current_network
.ssid
,len
);
203 wrqu
->essid
.flags
= 1;
206 spin_unlock_irqrestore(&ieee
->lock
, flags
);
212 int ieee80211_wx_set_rate(struct ieee80211_device
*ieee
,
213 struct iw_request_info
*info
,
214 union iwreq_data
*wrqu
, char *extra
)
217 u32 target_rate
= wrqu
->bitrate
.value
;
219 //added by lizhaoming for auto mode
220 if(target_rate
== -1){
223 ieee
->rate
= target_rate
/100000;
225 //FIXME: we might want to limit rate also in management protocols.
231 int ieee80211_wx_get_rate(struct ieee80211_device
*ieee
,
232 struct iw_request_info
*info
,
233 union iwreq_data
*wrqu
, char *extra
)
236 wrqu
->bitrate
.value
= ieee
->rate
* 100000;
241 int ieee80211_wx_set_mode(struct ieee80211_device
*ieee
, struct iw_request_info
*a
,
242 union iwreq_data
*wrqu
, char *b
)
245 ieee
->sync_scan_hurryup
= 1;
249 if (wrqu
->mode
== ieee
->iw_mode
)
252 if (wrqu
->mode
== IW_MODE_MONITOR
){
254 ieee
->dev
->type
= ARPHRD_IEEE80211
;
256 ieee
->dev
->type
= ARPHRD_ETHER
;
259 if (!ieee
->proto_started
){
260 ieee
->iw_mode
= wrqu
->mode
;
262 ieee80211_stop_protocol(ieee
);
263 ieee
->iw_mode
= wrqu
->mode
;
264 ieee80211_start_protocol(ieee
);
273 void ieee80211_wx_sync_scan_wq(struct work_struct
*work
)
275 struct ieee80211_device
*ieee
= container_of(work
, struct ieee80211_device
, wx_sync_scan_wq
);
278 chan
= ieee
->current_network
.channel
;
280 if (ieee
->data_hard_stop
)
281 ieee
->data_hard_stop(ieee
->dev
);
283 ieee80211_stop_send_beacons(ieee
);
285 ieee
->state
= IEEE80211_LINKED_SCANNING
;
286 ieee
->link_change(ieee
->dev
);
288 ieee80211_start_scan_syncro(ieee
);
290 ieee
->set_chan(ieee
->dev
, chan
);
292 ieee
->state
= IEEE80211_LINKED
;
293 ieee
->link_change(ieee
->dev
);
295 if (ieee
->data_hard_resume
)
296 ieee
->data_hard_resume(ieee
->dev
);
298 if(ieee
->iw_mode
== IW_MODE_ADHOC
|| ieee
->iw_mode
== IW_MODE_MASTER
)
299 ieee80211_start_send_beacons(ieee
);
301 //YJ,add,080828, In prevent of lossing ping packet during scanning
302 //ieee80211_sta_ps_send_null_frame(ieee, false);
309 int ieee80211_wx_set_scan(struct ieee80211_device
*ieee
, struct iw_request_info
*a
,
310 union iwreq_data
*wrqu
, char *b
)
316 if (ieee
->iw_mode
== IW_MODE_MONITOR
|| !(ieee
->proto_started
)){
321 //In prevent of lossing ping packet during scanning
322 //ieee80211_sta_ps_send_null_frame(ieee, true);
325 if ( ieee
->state
== IEEE80211_LINKED
){
326 queue_work(ieee
->wq
, &ieee
->wx_sync_scan_wq
);
327 /* intentionally forget to up sem */
336 int ieee80211_wx_set_essid(struct ieee80211_device
*ieee
,
337 struct iw_request_info
*a
,
338 union iwreq_data
*wrqu
, char *extra
)
345 ieee
->sync_scan_hurryup
= 1;
349 proto_started
= ieee
->proto_started
;
351 if (wrqu
->essid
.length
> IW_ESSID_MAX_SIZE
){
356 if (ieee
->iw_mode
== IW_MODE_MONITOR
){
362 ieee80211_stop_protocol(ieee
);
364 /* this is just to be sure that the GET wx callback
365 * has consisten infos. not needed otherwise
367 spin_lock_irqsave(&ieee
->lock
, flags
);
369 if (wrqu
->essid
.flags
&& wrqu
->essid
.length
) {
371 len
= (wrqu
->essid
.length
< IW_ESSID_MAX_SIZE
) ? (wrqu
->essid
.length
) : IW_ESSID_MAX_SIZE
;
372 memset(ieee
->current_network
.ssid
, 0, ieee
->current_network
.ssid_len
); //YJ,add,080819
373 strncpy(ieee
->current_network
.ssid
, extra
, len
);
374 ieee
->current_network
.ssid_len
= len
;
376 //YJ,modified,080819,end
378 //YJ,add,080819,for hidden ap
380 memset(ieee
->current_network
.bssid
, 0, ETH_ALEN
);
381 ieee
->current_network
.capability
= 0;
383 //YJ,add,080819,for hidden ap,end
387 ieee
->current_network
.ssid
[0] = '\0';
388 ieee
->current_network
.ssid_len
= 0;
390 //printk("==========set essid %s!\n",ieee->current_network.ssid);
391 spin_unlock_irqrestore(&ieee
->lock
, flags
);
394 ieee80211_start_protocol(ieee
);
400 int ieee80211_wx_get_mode(struct ieee80211_device
*ieee
, struct iw_request_info
*a
,
401 union iwreq_data
*wrqu
, char *b
)
404 wrqu
->mode
= ieee
->iw_mode
;
408 int ieee80211_wx_set_rawtx(struct ieee80211_device
*ieee
,
409 struct iw_request_info
*info
,
410 union iwreq_data
*wrqu
, char *extra
)
413 int *parms
= (int *)extra
;
414 int enable
= (parms
[0] > 0);
415 short prev
= ieee
->raw_tx
;
424 printk(KERN_INFO
"raw TX is %s\n",
425 ieee
->raw_tx
? "enabled" : "disabled");
427 if(ieee
->iw_mode
== IW_MODE_MONITOR
)
429 if(prev
== 0 && ieee
->raw_tx
){
430 if (ieee
->data_hard_resume
)
431 ieee
->data_hard_resume(ieee
->dev
);
433 netif_carrier_on(ieee
->dev
);
436 if(prev
&& ieee
->raw_tx
== 1)
437 netif_carrier_off(ieee
->dev
);
445 int ieee80211_wx_get_name(struct ieee80211_device
*ieee
,
446 struct iw_request_info
*info
,
447 union iwreq_data
*wrqu
, char *extra
)
449 strlcpy(wrqu
->name
, "802.11", IFNAMSIZ
);
450 if(ieee
->modulation
& IEEE80211_CCK_MODULATION
){
451 strlcat(wrqu
->name
, "b", IFNAMSIZ
);
452 if(ieee
->modulation
& IEEE80211_OFDM_MODULATION
)
453 strlcat(wrqu
->name
, "/g", IFNAMSIZ
);
454 }else if(ieee
->modulation
& IEEE80211_OFDM_MODULATION
)
455 strlcat(wrqu
->name
, "g", IFNAMSIZ
);
457 if((ieee
->state
== IEEE80211_LINKED
) ||
458 (ieee
->state
== IEEE80211_LINKED_SCANNING
))
459 strlcat(wrqu
->name
," link", IFNAMSIZ
);
460 else if(ieee
->state
!= IEEE80211_NOLINK
)
461 strlcat(wrqu
->name
," .....", IFNAMSIZ
);
468 /* this is mostly stolen from hostap */
469 int ieee80211_wx_set_power(struct ieee80211_device
*ieee
,
470 struct iw_request_info
*info
,
471 union iwreq_data
*wrqu
, char *extra
)
476 (!ieee
->sta_wake_up
) ||
477 (!ieee
->ps_request_tx_ack
) ||
478 (!ieee
->enter_sleep_state
) ||
479 (!ieee
->ps_is_queue_empty
)){
481 printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
488 if (wrqu
->power
.disabled
){
489 ieee
->ps
= IEEE80211_PS_DISABLED
;
493 switch (wrqu
->power
.flags
& IW_POWER_MODE
) {
494 case IW_POWER_UNICAST_R
:
495 ieee
->ps
= IEEE80211_PS_UNICAST
;
499 ieee
->ps
= IEEE80211_PS_UNICAST
| IEEE80211_PS_MBCAST
;
503 ieee
->ps
= IEEE80211_PS_DISABLED
;
511 if (wrqu
->power
.flags
& IW_POWER_TIMEOUT
) {
513 ieee
->ps_timeout
= wrqu
->power
.value
/ 1000;
514 printk("Timeout %d\n",ieee
->ps_timeout
);
517 if (wrqu
->power
.flags
& IW_POWER_PERIOD
) {
530 /* this is stolen from hostap */
531 int ieee80211_wx_get_power(struct ieee80211_device
*ieee
,
532 struct iw_request_info
*info
,
533 union iwreq_data
*wrqu
, char *extra
)
539 if(ieee
->ps
== IEEE80211_PS_DISABLED
){
540 wrqu
->power
.disabled
= 1;
544 wrqu
->power
.disabled
= 0;
546 // if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
547 wrqu
->power
.flags
= IW_POWER_TIMEOUT
;
548 wrqu
->power
.value
= ieee
->ps_timeout
* 1000;
550 // ret = -EOPNOTSUPP;
552 //wrqu->power.flags = IW_POWER_PERIOD;
553 //wrqu->power.value = ieee->current_network.dtim_period *
554 // ieee->current_network.beacon_interval * 1024;
558 if (ieee
->ps
& IEEE80211_PS_MBCAST
)
559 wrqu
->power
.flags
|= IW_POWER_ALL_R
;
561 wrqu
->power
.flags
|= IW_POWER_UNICAST_R
;