diff options
Diffstat (limited to 'openwrt/package')
-rw-r--r-- | openwrt/package/openwrt/wlcompat.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/openwrt/package/openwrt/wlcompat.c b/openwrt/package/openwrt/wlcompat.c new file mode 100644 index 000000000..11757e542 --- /dev/null +++ b/openwrt/package/openwrt/wlcompat.c @@ -0,0 +1,197 @@ +// insert header here +// mbm. gpl. + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/if_arp.h> +#include <asm/uaccess.h> + +#include <net/iw_handler.h> +#include <wlioctl.h> + +#define DEBUG + +static struct net_device *dev; + +static int wl_ioctl(struct net_device *dev, int cmd, void *buf, int len) +{ + mm_segment_t old_fs = get_fs(); + struct ifreq ifr; + int ret; + wl_ioctl_t ioc; + ioc.cmd = cmd; + ioc.buf = buf; + ioc.len = len; + strncpy(ifr.ifr_name, dev->name, IFNAMSIZ); + ifr.ifr_data = (caddr_t) &ioc; + set_fs(KERNEL_DS); + ret = dev->do_ioctl(dev,&ifr,SIOCDEVPRIVATE); + set_fs (old_fs); + return ret; +} + + +static int wlcompat_ioctl(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + switch (info->cmd) { + case SIOCGIWNAME: + strcpy(wrqu->name, "IEEE 802.11-DS"); + break; + case SIOCGIWFREQ: + { + channel_info_t ci; + wl_ioctl(dev,WLC_GET_CHANNEL, &ci, sizeof(ci)); + wrqu->freq.m = ci.target_channel; + wrqu->freq.e = 0; + break; + } + case SIOCGIWAP: + { + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + wl_ioctl(dev,WLC_GET_BSSID,wrqu->ap_addr.sa_data,6); + break; + } + case SIOCGIWESSID: + { + wlc_ssid_t ssid; + wl_ioctl(dev,WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t)); + wrqu->essid.flags = wrqu->data.flags = 1; + wrqu->essid.length = wrqu->data.length = ssid.SSID_len + 1; + memcpy(extra,ssid.SSID,ssid.SSID_len + 1); + break; + } + case SIOCGIWRTS: + { + wl_ioctl(dev,WLC_GET_RTS,&(wrqu->rts.value),sizeof(int)); + break; + } + case SIOCGIWFRAG: + { + wl_ioctl(dev,WLC_GET_FRAG,&(wrqu->frag.value),sizeof(int)); + break; + } + case SIOCGIWTXPOW: + { + wrqu->txpower.value = 0; + wl_ioctl(dev,WLC_GET_TXPWR, &(wrqu->txpower.value), sizeof(int)); + wrqu->txpower.fixed = 0; + wrqu->txpower.disabled = 0; + wrqu->txpower.flags = IW_TXPOW_MWATT; + break; + } + case SIOCGIWENCODE: + { + wrqu->data.flags = IW_ENCODE_DISABLED; + break; + } + } + return 0; +} + +static const iw_handler wlcompat_handler[] = { + NULL, /* SIOCSIWNAME */ + wlcompat_ioctl, /* SIOCGIWNAME */ + NULL, /* SIOCSIWNWID */ + NULL, /* SIOCGIWNWID */ + NULL, /* SIOCSIWFREQ */ + wlcompat_ioctl, /* SIOCGIWFREQ */ + NULL, /* SIOCSIWMODE */ + NULL, /* SIOCGIWMODE */ + NULL, /* SIOCSIWSENS */ + NULL, /* SIOCGIWSENS */ + NULL, /* SIOCSIWRANGE */ + NULL, /* SIOCGIWRANGE */ + NULL, /* SIOCSIWPRIV */ + NULL, /* SIOCGIWPRIV */ + NULL, /* SIOCSIWSTATS */ + NULL, /* SIOCGIWSTATS */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ + NULL, /* SIOCSIWAP */ + wlcompat_ioctl, /* SIOCGIWAP */ + NULL, /* -- hole -- */ + NULL, /* SIOCGIWAPLIST */ + NULL, /* -- hole -- */ + NULL, /* -- hole -- */ + NULL, /* SIOCSIWESSID */ + wlcompat_ioctl, /* SIOCGIWESSID */ + NULL, /* SIOCSIWNICKN */ + NULL, /* SIOCGIWNICKN */ + NULL, /* -- hole -- */ + NULL, /* -- hole -- */ + NULL, /* SIOCSIWRATE */ + NULL, /* SIOCGIWRATE */ + NULL, /* SIOCSIWRTS */ + wlcompat_ioctl, /* SIOCGIWRTS */ + NULL, /* SIOCSIWFRAG */ + wlcompat_ioctl, /* SIOCGIWFRAG */ + NULL, /* SIOCSIWTXPOW */ + wlcompat_ioctl, /* SIOCGIWTXPOW */ + NULL, /* SIOCSIWRETRY */ + NULL, /* SIOCGIWRETRY */ + NULL, /* SIOCSIWENCODE */ + wlcompat_ioctl, /* SIOCGIWENCODE */ +}; + +static const struct iw_handler_def wlcompat_handler_def = +{ + .standard = (iw_handler *) wlcompat_handler, + .num_standard = sizeof(wlcompat_handler)/sizeof(iw_handler), + .private = NULL, + .num_private = 0, + .private_args = NULL, + .num_private_args = 0, +}; + +#ifdef DEBUG +static int (*old_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); +static int new_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { + int ret = old_ioctl(dev,ifr,cmd); + printk("dev: %s ioctl: 0x%04x\n",dev->name,cmd); + if (cmd==SIOCDEVPRIVATE) { + int x; + wl_ioctl_t *ioc = (wl_ioctl_t *)ifr->ifr_data; + unsigned char *buf = ioc->buf; + printk(" cmd: %d buf: 0x%08x len: %d\n",ioc->cmd,&(ioc->buf),ioc->len); + printk(" ->"); + for (x=0;x<ioc->len && x<128 ;x++) { + printk("%02X",buf[x]); + } + printk("\n"); + } + return ret; +} +#endif + +static int __init wlcompat_init() +{ + dev = dev_get_by_name("eth1"); +#ifdef DEBUG + old_ioctl = dev->do_ioctl; + dev->do_ioctl = new_ioctl; +#endif + dev->wireless_handlers = (struct iw_handler_def *)&wlcompat_handler_def; + return 0; +} + +static void __exit wlcompat_exit() +{ + dev->wireless_handlers = NULL; +#ifdef DEBUG + dev->do_ioctl = old_ioctl; +#endif + return; +} + +EXPORT_NO_SYMBOLS; +MODULE_AUTHOR("openwrt.org"); +MODULE_LICENSE("GPL"); + +module_init(wlcompat_init); +module_exit(wlcompat_exit); |