123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /* zd_netdev.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
- #include <net/ieee80211.h>
- #include <net/ieee80211softmac.h>
- #include <net/ieee80211softmac_wx.h>
- #include <net/iw_handler.h>
- #include "zd_def.h"
- #include "zd_netdev.h"
- #include "zd_mac.h"
- #include "zd_ieee80211.h"
- /* Region 0 means reset regdomain to default. */
- static int zd_set_regdomain(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- const u8 *regdomain = (u8 *)req;
- return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain);
- }
- static int zd_get_regdomain(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- u8 *regdomain = (u8 *)req;
- if (!regdomain)
- return -EINVAL;
- *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev));
- return 0;
- }
- static const struct iw_priv_args zd_priv_args[] = {
- {
- .cmd = ZD_PRIV_SET_REGDOMAIN,
- .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
- .name = "set_regdomain",
- },
- {
- .cmd = ZD_PRIV_GET_REGDOMAIN,
- .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
- .name = "get_regdomain",
- },
- };
- #define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV]
- static const iw_handler zd_priv_handler[] = {
- PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain,
- PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain,
- };
- static int iw_get_name(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- /* FIXME: check whether 802.11a will also supported */
- strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ);
- return 0;
- }
- static int iw_get_nick(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- strcpy(extra, "zd1211");
- req->data.length = strlen(extra);
- req->data.flags = 1;
- return 0;
- }
- static int iw_set_freq(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- int r;
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct iw_freq *freq = &req->freq;
- u8 channel;
- r = zd_find_channel(&channel, freq);
- if (r < 0)
- return r;
- r = zd_mac_request_channel(mac, channel);
- return r;
- }
- static int iw_get_freq(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- int r;
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct iw_freq *freq = &req->freq;
- u8 channel;
- u8 flags;
- r = zd_mac_get_channel(mac, &channel, &flags);
- if (r)
- return r;
- freq->flags = (flags & MAC_FIXED_CHANNEL) ?
- IW_FREQ_FIXED : IW_FREQ_AUTO;
- dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
- (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
- return zd_channel_to_freq(freq, channel);
- }
- static int iw_set_mode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
- }
- static int iw_get_mode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
- }
- static int iw_get_range(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
- {
- struct iw_range *range = (struct iw_range *)extra;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
- req->data.length = sizeof(*range);
- return zd_mac_get_range(zd_netdev_mac(netdev), range);
- }
- static int iw_set_encode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
- {
- return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
- data, extra);
- }
- static int iw_get_encode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
- {
- return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
- data, extra);
- }
- static int iw_set_encodeext(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
- {
- return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
- data, extra);
- }
- static int iw_get_encodeext(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
- {
- return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
- data, extra);
- }
- #define WX(x) [(x)-SIOCIWFIRST]
- static const iw_handler zd_standard_iw_handlers[] = {
- WX(SIOCGIWNAME) = iw_get_name,
- WX(SIOCGIWNICKN) = iw_get_nick,
- WX(SIOCSIWFREQ) = iw_set_freq,
- WX(SIOCGIWFREQ) = iw_get_freq,
- WX(SIOCSIWMODE) = iw_set_mode,
- WX(SIOCGIWMODE) = iw_get_mode,
- WX(SIOCGIWRANGE) = iw_get_range,
- WX(SIOCSIWENCODE) = iw_set_encode,
- WX(SIOCGIWENCODE) = iw_get_encode,
- WX(SIOCSIWENCODEEXT) = iw_set_encodeext,
- WX(SIOCGIWENCODEEXT) = iw_get_encodeext,
- WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
- WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
- WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
- WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
- WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
- WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
- WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
- WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
- WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
- WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
- WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
- WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
- WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme,
- };
- static const struct iw_handler_def iw_handler_def = {
- .standard = zd_standard_iw_handlers,
- .num_standard = ARRAY_SIZE(zd_standard_iw_handlers),
- .private = zd_priv_handler,
- .num_private = ARRAY_SIZE(zd_priv_handler),
- .private_args = zd_priv_args,
- .num_private_args = ARRAY_SIZE(zd_priv_args),
- .get_wireless_stats = zd_mac_get_wireless_stats,
- };
- struct net_device *zd_netdev_alloc(struct usb_interface *intf)
- {
- int r;
- struct net_device *netdev;
- struct zd_mac *mac;
- netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
- if (!netdev) {
- dev_dbg_f(&intf->dev, "out of memory\n");
- return NULL;
- }
- mac = zd_netdev_mac(netdev);
- r = zd_mac_init(mac, netdev, intf);
- if (r) {
- usb_set_intfdata(intf, NULL);
- free_ieee80211(netdev);
- return NULL;
- }
- SET_MODULE_OWNER(netdev);
- SET_NETDEV_DEV(netdev, &intf->dev);
- dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
- dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
- netdev->open = zd_mac_open;
- netdev->stop = zd_mac_stop;
- /* netdev->get_stats = */
- /* netdev->set_multicast_list = */
- netdev->set_mac_address = zd_mac_set_mac_address;
- netdev->wireless_handlers = &iw_handler_def;
- /* netdev->ethtool_ops = */
- return netdev;
- }
- void zd_netdev_free(struct net_device *netdev)
- {
- if (!netdev)
- return;
- zd_mac_clear(zd_netdev_mac(netdev));
- free_ieee80211(netdev);
- }
- void zd_netdev_disconnect(struct net_device *netdev)
- {
- unregister_netdev(netdev);
- }
|