4 #include <linux/config.h>
5 #include <linux/module.h>
6 #include <linux/init.h>
7 #include <linux/if_arp.h>
8 #include <asm/uaccess.h>
9 #include <linux/wireless.h>
11 #include <net/iw_handler.h>
16 static struct net_device
*dev
;
18 /* The frequency of each channel in MHz */
19 const long channel_frequency
[] = {
20 2412, 2417, 2422, 2427, 2432, 2437, 2442,
21 2447, 2452, 2457, 2462, 2467, 2472, 2484
23 #define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
25 static int wl_ioctl(struct net_device
*dev
, int cmd
, void *buf
, int len
)
27 mm_segment_t old_fs
= get_fs();
34 strncpy(ifr
.ifr_name
, dev
->name
, IFNAMSIZ
);
35 ifr
.ifr_data
= (caddr_t
) &ioc
;
37 ret
= dev
->do_ioctl(dev
,&ifr
,SIOCDEVPRIVATE
);
42 static int wlcompat_ioctl_getiwrange(struct net_device
*dev
,
46 struct iw_range
*range
;
48 range
= (struct iw_range
*) extra
;
50 range
->we_version_compiled
= WIRELESS_EXT
;
51 range
->we_version_source
= WIRELESS_EXT
;
53 range
->min_nwid
= range
->max_nwid
= 0;
55 range
->num_channels
= NUM_CHANNELS
;
57 for (i
= 0; i
< NUM_CHANNELS
; i
++) {
58 range
->freq
[k
].i
= i
+ 1;
59 range
->freq
[k
].m
= channel_frequency
[i
] * 100000;
62 if (k
>= IW_MAX_FREQUENCIES
)
65 range
->num_frequency
= k
;
66 range
->sensitivity
= 3;
68 /* nbd: don't know what this means, but other drivers set it this way */
69 range
->pmp_flags
= IW_POWER_PERIOD
;
70 range
->pmt_flags
= IW_POWER_TIMEOUT
;
71 range
->pm_capa
= IW_POWER_PERIOD
| IW_POWER_TIMEOUT
| IW_POWER_UNICAST_R
;
74 if (wl_ioctl(dev
, WLC_GET_RTS
, &range
->max_rts
, sizeof(int)) < 0)
75 range
->max_rts
= 2347;
77 range
->min_frag
= 256;
79 if (wl_ioctl(dev
, WLC_GET_FRAG
, &range
->max_frag
, sizeof(int)) < 0)
80 range
->max_frag
= 2346;
83 range
->max_pmp
= 65535000;
85 range
->max_pmt
= 65535 * 1000;
87 range
->txpower_capa
= IW_TXPOW_MWATT
;
92 static int wlcompat_ioctl(struct net_device
*dev
,
93 struct iw_request_info
*info
,
94 union iwreq_data
*wrqu
,
99 strcpy(wrqu
->name
, "IEEE 802.11-DS");
105 if (wl_ioctl(dev
,WLC_GET_CHANNEL
, &ci
, sizeof(ci
)) < 0)
108 wrqu
->freq
.m
= ci
.target_channel
;
114 if (wrqu
->freq
.e
== 1) {
116 int f
= wrqu
->freq
.m
/ 100000;
117 while ((channel
< NUM_CHANNELS
+ 1) && (f
!= channel_frequency
[channel
]))
120 if (channel
== NUM_CHANNELS
) // channel not found
124 wrqu
->freq
.m
= channel
+ 1;
126 if ((wrqu
->freq
.e
== 0) && (wrqu
->freq
.m
< 1000)) {
127 if (wl_ioctl(dev
, WLC_SET_CHANNEL
, &wrqu
->freq
.m
, sizeof(int)) < 0)
136 wrqu
->ap_addr
.sa_family
= ARPHRD_ETHER
;
137 if (wl_ioctl(dev
,WLC_GET_BSSID
,wrqu
->ap_addr
.sa_data
,6) < 0)
145 if (wl_ioctl(dev
,WLC_GET_SSID
, &ssid
, sizeof(wlc_ssid_t
)) < 0)
148 wrqu
->essid
.flags
= wrqu
->data
.flags
= 1;
149 wrqu
->essid
.length
= wrqu
->data
.length
= ssid
.SSID_len
+ 1;
150 memcpy(extra
,ssid
.SSID
,ssid
.SSID_len
+ 1);
156 memset(&ssid
, 0, sizeof(ssid
));
157 ssid
.SSID_len
= strlen(extra
);
158 if (ssid
.SSID_len
> WLC_ESSID_MAX_SIZE
)
159 ssid
.SSID_len
= WLC_ESSID_MAX_SIZE
;
160 memcpy(ssid
.SSID
, extra
, ssid
.SSID_len
);
161 if (wl_ioctl(dev
, WLC_SET_SSID
, &ssid
, sizeof(ssid
)) < 0)
167 if (wl_ioctl(dev
,WLC_GET_RTS
,&(wrqu
->rts
.value
),sizeof(int)) < 0)
173 if (wl_ioctl(dev
,WLC_SET_RTS
,&(wrqu
->rts
.value
),sizeof(int)) < 0)
179 if (wl_ioctl(dev
,WLC_GET_FRAG
,&(wrqu
->frag
.value
),sizeof(int)) < 0)
185 if (wl_ioctl(dev
,WLC_SET_FRAG
,&(wrqu
->frag
.value
),sizeof(int)) < 0)
191 wrqu
->txpower
.value
= 0;
192 if (wl_ioctl(dev
,WLC_GET_TXPWR
, &(wrqu
->txpower
.value
), sizeof(int)) < 0)
194 wrqu
->txpower
.fixed
= 0;
195 wrqu
->txpower
.disabled
= 0;
196 wrqu
->txpower
.flags
= IW_TXPOW_MWATT
;
201 if (wrqu
->txpower
.flags
!= IW_TXPOW_MWATT
)
204 if (wl_ioctl(dev
, WLC_SET_TXPWR
, &wrqu
->txpower
.value
, sizeof(int)) < 0)
209 wrqu
->data
.flags
= IW_ENCODE_DISABLED
;
214 return wlcompat_ioctl_getiwrange(dev
, extra
);
219 int ap
= -1, infra
= -1, passive
= 0, wet
= 0;
221 switch (wrqu
->mode
) {
222 case IW_MODE_MONITOR
:
246 if (wl_ioctl(dev
, WLC_SET_PASSIVE
, &passive
, sizeof(passive
)) < 0)
248 if (wl_ioctl(dev
, WLC_SET_MONITOR
, &passive
, sizeof(passive
)) < 0)
250 if (wl_ioctl(dev
, WLC_SET_WET
, &wet
, sizeof(wet
)) < 0)
253 if (wl_ioctl(dev
, WLC_SET_AP
, &ap
, sizeof(ap
)) < 0)
256 if (wl_ioctl(dev
, WLC_SET_INFRA
, &infra
, sizeof(infra
)) < 0)
264 int ap
, infra
, wet
, passive
;
266 if (wl_ioctl(dev
, WLC_GET_AP
, &ap
, sizeof(ap
)) < 0)
268 if (wl_ioctl(dev
, WLC_GET_INFRA
, &infra
, sizeof(infra
)) < 0)
270 if (wl_ioctl(dev
, WLC_GET_PASSIVE
, &passive
, sizeof(passive
)) < 0)
272 if (wl_ioctl(dev
, WLC_GET_WET
, &wet
, sizeof(wet
)) < 0)
276 wrqu
->mode
= IW_MODE_MONITOR
;
278 wrqu
->mode
= IW_MODE_ADHOC
;
281 wrqu
->mode
= IW_MODE_MASTER
;
284 wrqu
->mode
= IW_MODE_REPEAT
;
286 wrqu
->mode
= IW_MODE_INFRA
;
301 static const iw_handler wlcompat_handler
[] = {
302 NULL
, /* SIOCSIWCOMMIT */
303 wlcompat_ioctl
, /* SIOCGIWNAME */
304 NULL
, /* SIOCSIWNWID */
305 NULL
, /* SIOCGIWNWID */
306 wlcompat_ioctl
, /* SIOCSIWFREQ */
307 wlcompat_ioctl
, /* SIOCGIWFREQ */
308 wlcompat_ioctl
, /* SIOCSIWMODE */
309 wlcompat_ioctl
, /* SIOCGIWMODE */
310 NULL
, /* SIOCSIWSENS */
311 NULL
, /* SIOCGIWSENS */
312 NULL
, /* SIOCSIWRANGE, unused */
313 wlcompat_ioctl
, /* SIOCGIWRANGE */
314 NULL
, /* SIOCSIWPRIV */
315 NULL
, /* SIOCGIWPRIV */
316 NULL
, /* SIOCSIWSTATS */
317 NULL
, /* SIOCGIWSTATS */
318 iw_handler_set_spy
, /* SIOCSIWSPY */
319 iw_handler_get_spy
, /* SIOCGIWSPY */
320 iw_handler_set_thrspy
, /* SIOCSIWTHRSPY */
321 iw_handler_get_thrspy
, /* SIOCGIWTHRSPY */
322 NULL
, /* SIOCSIWAP */
323 wlcompat_ioctl
, /* SIOCGIWAP */
324 NULL
, /* -- hole -- */
325 NULL
, /* SIOCGIWAPLIST */
326 NULL
, /* -- hole -- */
327 NULL
, /* -- hole -- */
328 wlcompat_ioctl
, /* SIOCSIWESSID */
329 wlcompat_ioctl
, /* SIOCGIWESSID */
330 NULL
, /* SIOCSIWNICKN */
331 NULL
, /* SIOCGIWNICKN */
332 NULL
, /* -- hole -- */
333 NULL
, /* -- hole -- */
334 NULL
, /* SIOCSIWRATE */
335 NULL
, /* SIOCGIWRATE */
336 wlcompat_ioctl
, /* SIOCSIWRTS */
337 wlcompat_ioctl
, /* SIOCGIWRTS */
338 wlcompat_ioctl
, /* SIOCSIWFRAG */
339 wlcompat_ioctl
, /* SIOCGIWFRAG */
340 wlcompat_ioctl
, /* SIOCSIWTXPOW */
341 wlcompat_ioctl
, /* SIOCGIWTXPOW */
342 NULL
, /* SIOCSIWRETRY */
343 NULL
, /* SIOCGIWRETRY */
344 NULL
, /* SIOCSIWENCODE */
345 wlcompat_ioctl
, /* SIOCGIWENCODE */
348 static const struct iw_handler_def wlcompat_handler_def
=
350 .standard
= (iw_handler
*) wlcompat_handler
,
351 .num_standard
= sizeof(wlcompat_handler
)/sizeof(iw_handler
),
354 .private_args
= NULL
,
355 .num_private_args
= 0,
359 static int (*old_ioctl
)(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
);
360 static int new_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
) {
361 int ret
= old_ioctl(dev
,ifr
,cmd
);
362 printk("dev: %s ioctl: 0x%04x\n",dev
->name
,cmd
);
363 if (cmd
==SIOCDEVPRIVATE
) {
365 wl_ioctl_t
*ioc
= (wl_ioctl_t
*)ifr
->ifr_data
;
366 unsigned char *buf
= ioc
->buf
;
367 printk(" cmd: %d buf: 0x%08x len: %d\n",ioc
->cmd
,&(ioc
->buf
),ioc
->len
);
369 for (x
=0;x
<ioc
->len
&& x
<128 ;x
++) {
370 printk("%02X",buf
[x
]);
378 static int __init
wlcompat_init()
380 dev
= dev_get_by_name("eth1");
382 old_ioctl
= dev
->do_ioctl
;
383 dev
->do_ioctl
= new_ioctl
;
385 dev
->wireless_handlers
= (struct iw_handler_def
*)&wlcompat_handler_def
;
389 static void __exit
wlcompat_exit()
391 dev
->wireless_handlers
= NULL
;
393 dev
->do_ioctl
= old_ioctl
;
399 MODULE_AUTHOR("openwrt.org");
400 MODULE_LICENSE("GPL");
402 module_init(wlcompat_init
);
403 module_exit(wlcompat_exit
);