initial commit
[oweals/openwrt.git] / openwrt / package / openwrt / wlcompat.c
1 // insert header here
2 // mbm. gpl.
3
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
10 #include <net/iw_handler.h>
11 #include <wlioctl.h>
12
13 #define DEBUG
14
15 static struct net_device *dev;
16
17 static int wl_ioctl(struct net_device *dev, int cmd, void *buf, int len)
18 {
19         mm_segment_t old_fs = get_fs();
20         struct ifreq ifr;
21         int ret;
22         wl_ioctl_t ioc;
23         ioc.cmd = cmd;
24         ioc.buf = buf;
25         ioc.len = len;
26         strncpy(ifr.ifr_name, dev->name, IFNAMSIZ);
27         ifr.ifr_data = (caddr_t) &ioc;
28         set_fs(KERNEL_DS);
29         ret = dev->do_ioctl(dev,&ifr,SIOCDEVPRIVATE);
30         set_fs (old_fs);
31         return ret;
32 }
33
34
35 static int wlcompat_ioctl(struct net_device *dev,
36                          struct iw_request_info *info,
37                          union iwreq_data *wrqu,
38                          char *extra)
39 {
40         switch (info->cmd) {
41                 case SIOCGIWNAME:
42                         strcpy(wrqu->name, "IEEE 802.11-DS");
43                         break;
44                 case SIOCGIWFREQ:
45                 {
46                         channel_info_t ci;
47                         wl_ioctl(dev,WLC_GET_CHANNEL, &ci, sizeof(ci));
48                         wrqu->freq.m = ci.target_channel;
49                         wrqu->freq.e = 0;
50                         break;
51                 }
52                 case SIOCGIWAP:
53                 {
54                         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
55                         wl_ioctl(dev,WLC_GET_BSSID,wrqu->ap_addr.sa_data,6);
56                         break;
57                 }
58                 case SIOCGIWESSID:
59                 {
60                         wlc_ssid_t ssid;
61                         wl_ioctl(dev,WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t));
62                         wrqu->essid.flags = wrqu->data.flags = 1;
63                         wrqu->essid.length = wrqu->data.length = ssid.SSID_len + 1;
64                         memcpy(extra,ssid.SSID,ssid.SSID_len + 1);
65                         break;
66                 }
67                 case SIOCGIWRTS:
68                 {
69                         wl_ioctl(dev,WLC_GET_RTS,&(wrqu->rts.value),sizeof(int));
70                         break;
71                 }
72                 case SIOCGIWFRAG:
73                 {
74                         wl_ioctl(dev,WLC_GET_FRAG,&(wrqu->frag.value),sizeof(int));
75                         break;
76                 }
77                 case SIOCGIWTXPOW:
78                 {
79                         wrqu->txpower.value = 0;
80                         wl_ioctl(dev,WLC_GET_TXPWR, &(wrqu->txpower.value), sizeof(int));
81                         wrqu->txpower.fixed = 0;
82                         wrqu->txpower.disabled = 0;
83                         wrqu->txpower.flags = IW_TXPOW_MWATT;
84                         break;
85                 }
86                 case SIOCGIWENCODE:
87                 {
88                         wrqu->data.flags = IW_ENCODE_DISABLED;
89                         break;
90                 }
91         }
92         return 0;
93 }
94
95 static const iw_handler  wlcompat_handler[] = {
96         NULL,                   /* SIOCSIWNAME */
97         wlcompat_ioctl,         /* SIOCGIWNAME */
98         NULL,                   /* SIOCSIWNWID */
99         NULL,                   /* SIOCGIWNWID */
100         NULL,                   /* SIOCSIWFREQ */
101         wlcompat_ioctl,         /* SIOCGIWFREQ */
102         NULL,                   /* SIOCSIWMODE */
103         NULL,                   /* SIOCGIWMODE */
104         NULL,                   /* SIOCSIWSENS */
105         NULL,                   /* SIOCGIWSENS */
106         NULL,                   /* SIOCSIWRANGE */
107         NULL,                   /* SIOCGIWRANGE */
108         NULL,                   /* SIOCSIWPRIV */
109         NULL,                   /* SIOCGIWPRIV */
110         NULL,                   /* SIOCSIWSTATS */
111         NULL,                   /* SIOCGIWSTATS */
112         iw_handler_set_spy,     /* SIOCSIWSPY */
113         iw_handler_get_spy,     /* SIOCGIWSPY */
114         iw_handler_set_thrspy,  /* SIOCSIWTHRSPY */
115         iw_handler_get_thrspy,  /* SIOCGIWTHRSPY */
116         NULL,                   /* SIOCSIWAP */
117         wlcompat_ioctl,         /* SIOCGIWAP */
118         NULL,                   /* -- hole -- */
119         NULL,                   /* SIOCGIWAPLIST */
120         NULL,                   /* -- hole -- */
121         NULL,                   /* -- hole -- */
122         NULL,                   /* SIOCSIWESSID */
123         wlcompat_ioctl,         /* SIOCGIWESSID */
124         NULL,                   /* SIOCSIWNICKN */
125         NULL,                   /* SIOCGIWNICKN */
126         NULL,                   /* -- hole -- */
127         NULL,                   /* -- hole -- */
128         NULL,                   /* SIOCSIWRATE */
129         NULL,                   /* SIOCGIWRATE */
130         NULL,                   /* SIOCSIWRTS */
131         wlcompat_ioctl,         /* SIOCGIWRTS */
132         NULL,                   /* SIOCSIWFRAG */
133         wlcompat_ioctl,         /* SIOCGIWFRAG */
134         NULL,                   /* SIOCSIWTXPOW */
135         wlcompat_ioctl,         /* SIOCGIWTXPOW */
136         NULL,                   /* SIOCSIWRETRY */
137         NULL,                   /* SIOCGIWRETRY */
138         NULL,                   /* SIOCSIWENCODE */
139         wlcompat_ioctl,         /* SIOCGIWENCODE */
140 };
141
142 static const struct iw_handler_def      wlcompat_handler_def =
143 {
144         .standard       = (iw_handler *) wlcompat_handler,
145         .num_standard   = sizeof(wlcompat_handler)/sizeof(iw_handler),
146         .private        = NULL,
147         .num_private    = 0,
148         .private_args   = NULL, 
149         .num_private_args = 0,
150 };
151
152 #ifdef DEBUG
153 static int (*old_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
154 static int new_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
155         int ret = old_ioctl(dev,ifr,cmd);
156         printk("dev: %s ioctl: 0x%04x\n",dev->name,cmd);
157         if (cmd==SIOCDEVPRIVATE) {
158                 int x;
159                 wl_ioctl_t *ioc = (wl_ioctl_t *)ifr->ifr_data;
160                 unsigned char *buf = ioc->buf;
161                 printk("   cmd: %d buf: 0x%08x len: %d\n",ioc->cmd,&(ioc->buf),ioc->len);
162                 printk("   ->");
163                 for (x=0;x<ioc->len && x<128 ;x++) {
164                         printk("%02X",buf[x]);
165                 }
166                 printk("\n");
167         }
168         return ret;
169 }
170 #endif
171
172 static int __init wlcompat_init()
173 {
174         dev = dev_get_by_name("eth1");
175 #ifdef DEBUG
176         old_ioctl = dev->do_ioctl;
177         dev->do_ioctl = new_ioctl;
178 #endif
179         dev->wireless_handlers = (struct iw_handler_def *)&wlcompat_handler_def;
180         return 0;
181 }
182
183 static void __exit wlcompat_exit()
184 {
185         dev->wireless_handlers = NULL;
186 #ifdef DEBUG
187         dev->do_ioctl = old_ioctl;
188 #endif
189         return;
190 }
191
192 EXPORT_NO_SYMBOLS;
193 MODULE_AUTHOR("openwrt.org");
194 MODULE_LICENSE("GPL");
195
196 module_init(wlcompat_init);
197 module_exit(wlcompat_exit);