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
21
/* FIXME: add A freqs */
23
const long rtllib_wlan_frequencies[] = {
24
2412, 2417, 2422, 2427,
25
2432, 2437, 2442, 2447,
26
2452, 2457, 2462, 2467,
31
int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
32
union iwreq_data *wrqu, char *b)
35
struct iw_freq *fwrq = & wrqu->freq;
39
if(ieee->iw_mode == IW_MODE_INFRA){
44
/* if setting by freq convert to channel */
46
if ((fwrq->m >= (int) 2.412e8 &&
47
fwrq->m <= (int) 2.487e8)) {
48
int f = fwrq->m / 100000;
51
while ((c < 14) && (f != rtllib_wlan_frequencies[c]))
54
/* hack to fall through */
60
if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){
64
}else { /* Set the channel */
67
if (ieee->active_channel_map[fwrq->m] != 1) {
72
ieee->current_network.channel = fwrq->m;
73
ieee->set_chan(ieee->dev, ieee->current_network.channel);
75
if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
76
if(ieee->state == RTLLIB_LINKED){
78
rtllib_stop_send_beacons(ieee);
79
rtllib_start_send_beacons(ieee);
90
#ifdef _RTL8192_EXT_PATCH_
91
int rtllib_wx_get_freq(struct rtllib_device *ieee,
92
struct iw_request_info *a,
93
union iwreq_data *wrqu, char *b, u8 is_mesh)
95
int rtllib_wx_get_freq(struct rtllib_device *ieee,
96
struct iw_request_info *a,
97
union iwreq_data *wrqu, char *b)
100
struct iw_freq *fwrq = & wrqu->freq;
102
#ifdef _RTL8192_EXT_PATCH_
105
if (ieee->current_mesh_network.channel == 0)
107
fwrq->m = rtllib_wlan_frequencies[ieee->current_mesh_network.channel-1] * 100000;
113
if (ieee->current_network.channel == 0)
115
fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] * 100000;
121
int rtllib_wx_get_wap(struct rtllib_device *ieee,
122
struct iw_request_info *info,
123
union iwreq_data *wrqu, char *extra)
127
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
129
if (ieee->iw_mode == IW_MODE_MONITOR)
132
/* We want avoid to give to the user inconsistent infos*/
133
spin_lock_irqsave(&ieee->lock, flags);
135
if (ieee->state != RTLLIB_LINKED &&
136
ieee->state != RTLLIB_LINKED_SCANNING &&
139
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
141
memcpy(wrqu->ap_addr.sa_data,
142
ieee->current_network.bssid, ETH_ALEN);
144
spin_unlock_irqrestore(&ieee->lock, flags);
150
int rtllib_wx_set_wap(struct rtllib_device *ieee,
151
struct iw_request_info *info,
152
union iwreq_data *awrq,
157
u8 zero[] = {0,0,0,0,0,0};
160
short ifup = ieee->proto_started;
161
struct sockaddr *temp = (struct sockaddr *)awrq;
163
rtllib_stop_scan_syncro(ieee);
166
/* use ifconfig hw ether */
167
if (ieee->iw_mode == IW_MODE_MASTER){
172
if (temp->sa_family != ARPHRD_ETHER){
177
if (memcmp(temp->sa_data, zero,ETH_ALEN) == 0){
178
spin_lock_irqsave(&ieee->lock, flags);
179
memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
181
spin_unlock_irqrestore(&ieee->lock, flags);
188
rtllib_stop_protocol(ieee,true);
190
/* just to avoid to give inconsistent infos in the
191
* get wx method. not really needed otherwise
193
spin_lock_irqsave(&ieee->lock, flags);
195
ieee->cannot_notify = false;
196
memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
197
ieee->wap_set = (memcmp(temp->sa_data, zero,ETH_ALEN)!=0);
199
spin_unlock_irqrestore(&ieee->lock, flags);
202
rtllib_start_protocol(ieee);
208
int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b)
213
if (ieee->iw_mode == IW_MODE_MONITOR)
216
/* We want avoid to give to the user inconsistent infos*/
217
spin_lock_irqsave(&ieee->lock, flags);
219
if (ieee->current_network.ssid[0] == '\0' ||
220
ieee->current_network.ssid_len == 0){
225
if (ieee->state != RTLLIB_LINKED &&
226
ieee->state != RTLLIB_LINKED_SCANNING &&
227
ieee->ssid_set == 0){
231
len = ieee->current_network.ssid_len;
232
wrqu->essid.length = len;
233
strncpy(b,ieee->current_network.ssid,len);
234
wrqu->essid.flags = 1;
237
spin_unlock_irqrestore(&ieee->lock, flags);
243
int rtllib_wx_set_rate(struct rtllib_device *ieee,
244
struct iw_request_info *info,
245
union iwreq_data *wrqu, char *extra)
248
u32 target_rate = wrqu->bitrate.value;
250
ieee->rate = target_rate/100000;
254
int rtllib_wx_get_rate(struct rtllib_device *ieee,
255
struct iw_request_info *info,
256
union iwreq_data *wrqu, char *extra)
259
#if defined RTL8192SU
260
if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G))
261
tmp_rate = ieee->rate;
262
else if (ieee->mode & IEEE_N_5G)
264
else if (ieee->mode & IEEE_N_24G) {
265
if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
266
tmp_rate = HTHalfMcsToDataRate(ieee, 15);
268
tmp_rate = HTMcsToDataRate(ieee, 15);
270
#elif defined RTL8192SE || defined RTL8192CE
271
tmp_rate = ieee->rtl_11n_user_show_rates(ieee->dev);
273
tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
275
wrqu->bitrate.value = tmp_rate * 500000;
281
int rtllib_wx_set_rts(struct rtllib_device *ieee,
282
struct iw_request_info *info,
283
union iwreq_data *wrqu, char *extra)
285
if (wrqu->rts.disabled || !wrqu->rts.fixed)
286
ieee->rts = DEFAULT_RTS_THRESHOLD;
289
if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
290
wrqu->rts.value > MAX_RTS_THRESHOLD)
292
ieee->rts = wrqu->rts.value;
297
int rtllib_wx_get_rts(struct rtllib_device *ieee,
298
struct iw_request_info *info,
299
union iwreq_data *wrqu, char *extra)
301
wrqu->rts.value = ieee->rts;
302
wrqu->rts.fixed = 0; /* no auto select */
303
wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
307
int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
308
union iwreq_data *wrqu, char *b)
310
int set_mode_status = 0;
312
rtllib_stop_scan_syncro(ieee);
314
switch (wrqu->mode) {
315
case IW_MODE_MONITOR:
318
#ifdef _RTL8192_EXT_PATCH_
323
wrqu->mode = IW_MODE_INFRA;
326
set_mode_status = -EINVAL;
330
if (wrqu->mode == ieee->iw_mode)
333
if (wrqu->mode == IW_MODE_MONITOR) {
334
#if defined(RTLLIB_RADIOTAP) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
335
ieee->dev->type = ARPHRD_IEEE80211_RADIOTAP;
337
ieee->dev->type = ARPHRD_IEEE80211;
339
rtllib_EnableNetMonitorMode(ieee->dev,false);
342
ieee->dev->type = ARPHRD_ETHER;
343
if (ieee->iw_mode == IW_MODE_MONITOR)
344
rtllib_DisableNetMonitorMode(ieee->dev,false);
347
if (!ieee->proto_started) {
348
ieee->iw_mode = wrqu->mode;
350
rtllib_stop_protocol(ieee,true);
351
ieee->iw_mode = wrqu->mode;
352
#if defined (RTL8192S_WAPI_SUPPORT)
353
if(ieee->iw_mode == IW_MODE_ADHOC)
354
ieee->wapiInfo.bWapiPSK = true;
356
rtllib_start_protocol(ieee);
361
return set_mode_status;
364
void rtllib_wx_sync_scan_wq(void *data)
366
struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, wx_sync_scan_wq);
368
HT_EXTCHNL_OFFSET chan_offset=0;
369
HT_CHANNEL_WIDTH bandwidth=0;
371
static int count = 0;
373
if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){
374
rtllib_start_scan_syncro(ieee, 0);
378
chan = ieee->current_network.channel;
381
if (ieee->LeisurePSLeave) {
382
ieee->LeisurePSLeave(ieee->dev);
384
/* notify AP to be in PS mode */
385
rtllib_sta_ps_send_null_frame(ieee, 1);
386
rtllib_sta_ps_send_null_frame(ieee, 1);
389
rtllib_stop_all_queues(ieee);
391
if (ieee->data_hard_stop)
392
ieee->data_hard_stop(ieee->dev);
393
rtllib_stop_send_beacons(ieee);
394
ieee->state = RTLLIB_LINKED_SCANNING;
395
ieee->link_change(ieee->dev);
396
/* wait for ps packet to be kicked out successfully */
399
if(ieee->ScanOperationBackupHandler)
400
ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_BACKUP);
402
if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
404
chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
405
bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
406
printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
407
ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
410
rtllib_start_scan_syncro(ieee, 0);
413
printk("Scan in 20M, back to 40M\n");
414
if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
415
ieee->set_chan(ieee->dev, chan + 2);
416
else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
417
ieee->set_chan(ieee->dev, chan - 2);
419
ieee->set_chan(ieee->dev, chan);
420
ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
422
ieee->set_chan(ieee->dev, chan);
425
if(ieee->ScanOperationBackupHandler)
426
ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_RESTORE);
428
ieee->state = RTLLIB_LINKED;
429
ieee->link_change(ieee->dev);
432
/* Notify AP that I wake up again */
433
rtllib_sta_ps_send_null_frame(ieee, 0);
436
if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 ||
437
ieee->LinkDetectInfo.NumRecvDataInPeriod == 0 ) {
438
ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
439
ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
442
if (ieee->data_hard_resume)
443
ieee->data_hard_resume(ieee->dev);
445
if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
446
rtllib_start_send_beacons(ieee);
448
rtllib_wake_all_queues(ieee);
456
int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
457
union iwreq_data *wrqu, char *b)
463
if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){
468
if ( ieee->state == RTLLIB_LINKED){
469
queue_work_rsl(ieee->wq, &ieee->wx_sync_scan_wq);
470
/* intentionally forget to up sem */
479
int rtllib_wx_set_essid(struct rtllib_device *ieee,
480
struct iw_request_info *a,
481
union iwreq_data *wrqu, char *extra)
488
rtllib_stop_scan_syncro(ieee);
491
proto_started = ieee->proto_started;
493
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
494
len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
496
len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
499
if (len > IW_ESSID_MAX_SIZE){
504
if (ieee->iw_mode == IW_MODE_MONITOR){
509
for (i=0; i<len; i++){
517
rtllib_stop_protocol(ieee,true);
520
/* this is just to be sure that the GET wx callback
521
* has consisten infos. not needed otherwise
523
spin_lock_irqsave(&ieee->lock, flags);
525
if (wrqu->essid.flags && wrqu->essid.length) {
526
strncpy(ieee->current_network.ssid, extra, len);
527
ieee->current_network.ssid_len = len;
531
for (i=0; i<len; i++)
532
printk("%c:%d ", extra[i], extra[i]);
536
ieee->cannot_notify = false;
541
ieee->current_network.ssid[0] = '\0';
542
ieee->current_network.ssid_len = 0;
544
spin_unlock_irqrestore(&ieee->lock, flags);
547
rtllib_start_protocol(ieee);
553
int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
554
union iwreq_data *wrqu, char *b)
556
#ifdef _RTL8192_EXT_PATCH_
557
if(ieee->iw_mode == IW_MODE_MESH) {
558
/* WEXT could not show mesh mode properly,
560
if(ieee->only_mesh) {
563
wrqu->mode = IW_MODE_INFRA;
568
wrqu->mode = ieee->iw_mode;
572
int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
573
struct iw_request_info *info,
574
union iwreq_data *wrqu, char *extra)
577
int *parms = (int *)extra;
578
int enable = (parms[0] > 0);
579
short prev = ieee->raw_tx;
588
printk(KERN_INFO"raw TX is %s\n",
589
ieee->raw_tx ? "enabled" : "disabled");
591
if(ieee->iw_mode == IW_MODE_MONITOR)
593
if(prev == 0 && ieee->raw_tx){
594
if (ieee->data_hard_resume)
595
ieee->data_hard_resume(ieee->dev);
597
netif_carrier_on(ieee->dev);
600
if(prev && ieee->raw_tx == 1)
601
netif_carrier_off(ieee->dev);
609
int rtllib_wx_get_name(struct rtllib_device *ieee,
610
struct iw_request_info *info,
611
union iwreq_data *wrqu, char *extra)
613
strcpy(wrqu->name, "802.11");
615
if (ieee->modulation & RTLLIB_CCK_MODULATION)
616
strcat(wrqu->name, "b");
617
if (ieee->modulation & RTLLIB_OFDM_MODULATION)
618
strcat(wrqu->name, "g");
619
if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
620
strcat(wrqu->name, "n");
622
if((ieee->state == RTLLIB_LINKED) ||
623
(ieee->state == RTLLIB_LINKED_SCANNING))
624
strcat(wrqu->name," linked");
625
else if(ieee->state != RTLLIB_NOLINK)
626
strcat(wrqu->name," link..");
632
/* this is mostly stolen from hostap */
633
int rtllib_wx_set_power(struct rtllib_device *ieee,
634
struct iw_request_info *info,
635
union iwreq_data *wrqu, char *extra)
640
(!ieee->sta_wake_up) ||
641
(!ieee->enter_sleep_state) ||
642
(!ieee->ps_is_queue_empty)){
644
RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): PS mode is tryied to be use but driver missed a callback\n\n",__FUNCTION__);
651
if (wrqu->power.disabled){
652
printk("===>%s(): power disable\n",__FUNCTION__);
653
ieee->ps = RTLLIB_PS_DISABLED;
656
if (wrqu->power.flags & IW_POWER_TIMEOUT) {
657
ieee->ps_timeout = wrqu->power.value / 1000;
658
printk("===>%s():ps_timeout is %d\n",__FUNCTION__,ieee->ps_timeout);
661
if (wrqu->power.flags & IW_POWER_PERIOD) {
663
ieee->ps_period = wrqu->power.value / 1000;
666
switch (wrqu->power.flags & IW_POWER_MODE) {
667
case IW_POWER_UNICAST_R:
668
ieee->ps = RTLLIB_PS_UNICAST;
670
case IW_POWER_MULTICAST_R:
671
ieee->ps = RTLLIB_PS_MBCAST;
674
ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST;
691
/* this is stolen from hostap */
692
int rtllib_wx_get_power(struct rtllib_device *ieee,
693
struct iw_request_info *info,
694
union iwreq_data *wrqu, char *extra)
700
if(ieee->ps == RTLLIB_PS_DISABLED){
701
wrqu->power.disabled = 1;
705
wrqu->power.disabled = 0;
707
if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
708
wrqu->power.flags = IW_POWER_TIMEOUT;
709
wrqu->power.value = ieee->ps_timeout * 1000;
711
wrqu->power.flags = IW_POWER_PERIOD;
712
wrqu->power.value = ieee->ps_period * 1000;
715
if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST))
716
wrqu->power.flags |= IW_POWER_ALL_R;
717
else if (ieee->ps & RTLLIB_PS_MBCAST)
718
wrqu->power.flags |= IW_POWER_MULTICAST_R;
720
wrqu->power.flags |= IW_POWER_UNICAST_R;
728
#ifndef BUILT_IN_RTLLIB
729
EXPORT_SYMBOL_RSL(rtllib_wx_get_essid);
730
EXPORT_SYMBOL_RSL(rtllib_wx_set_essid);
731
EXPORT_SYMBOL_RSL(rtllib_wx_set_rate);
732
EXPORT_SYMBOL_RSL(rtllib_wx_get_rate);
733
EXPORT_SYMBOL_RSL(rtllib_wx_set_wap);
734
EXPORT_SYMBOL_RSL(rtllib_wx_get_wap);
735
EXPORT_SYMBOL_RSL(rtllib_wx_set_mode);
736
EXPORT_SYMBOL_RSL(rtllib_wx_get_mode);
737
EXPORT_SYMBOL_RSL(rtllib_wx_set_scan);
738
EXPORT_SYMBOL_RSL(rtllib_wx_get_freq);
739
EXPORT_SYMBOL_RSL(rtllib_wx_set_freq);
740
EXPORT_SYMBOL_RSL(rtllib_wx_set_rawtx);
741
EXPORT_SYMBOL_RSL(rtllib_wx_get_name);
742
EXPORT_SYMBOL_RSL(rtllib_wx_set_power);
743
EXPORT_SYMBOL_RSL(rtllib_wx_get_power);
744
EXPORT_SYMBOL_RSL(rtllib_wlan_frequencies);
745
EXPORT_SYMBOL_RSL(rtllib_wx_set_rts);
746
EXPORT_SYMBOL_RSL(rtllib_wx_get_rts);