aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c153
1 files changed, 152 insertions, 1 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index a3a17caae439..9a46339ce47e 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -21,6 +21,7 @@
21#include "wext.h" 21#include "wext.h"
22#include "debugfs.h" 22#include "debugfs.h"
23#include "assoc.h" 23#include "assoc.h"
24#include "join.h"
24 25
25#define DRIVER_RELEASE_VERSION "322.p1" 26#define DRIVER_RELEASE_VERSION "322.p1"
26const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION 27const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
@@ -246,6 +247,66 @@ static ssize_t libertas_anycast_set(struct device * dev,
246 return strlen(buf); 247 return strlen(buf);
247} 248}
248 249
250int libertas_add_rtap(wlan_private *priv);
251void libertas_remove_rtap(wlan_private *priv);
252
253/**
254 * Get function for sysfs attribute rtap
255 */
256static ssize_t libertas_rtap_get(struct device * dev,
257 struct device_attribute *attr, char * buf)
258{
259 wlan_private *priv = (wlan_private *) dev->driver_data;
260 wlan_adapter *adapter = priv->adapter;
261 return snprintf(buf, 5, "0x%X\n", adapter->monitormode);
262}
263
264/**
265 * Set function for sysfs attribute rtap
266 */
267static ssize_t libertas_rtap_set(struct device * dev,
268 struct device_attribute *attr, const char * buf, size_t count)
269{
270 int monitor_mode;
271 wlan_private *priv = (wlan_private *) dev->driver_data;
272 wlan_adapter *adapter = priv->adapter;
273
274 sscanf(buf, "%x", &monitor_mode);
275 if (monitor_mode != WLAN_MONITOR_OFF) {
276 if(adapter->monitormode == monitor_mode)
277 return strlen(buf);
278 if (adapter->monitormode == WLAN_MONITOR_OFF) {
279 if (adapter->mode == IW_MODE_INFRA)
280 libertas_send_deauthentication(priv);
281 else if (adapter->mode == IW_MODE_ADHOC)
282 libertas_stop_adhoc_network(priv);
283 libertas_add_rtap(priv);
284 }
285 adapter->monitormode = monitor_mode;
286 }
287
288 else {
289 if(adapter->monitormode == WLAN_MONITOR_OFF)
290 return strlen(buf);
291 adapter->monitormode = WLAN_MONITOR_OFF;
292 libertas_remove_rtap(priv);
293 netif_wake_queue(priv->dev);
294 netif_wake_queue(priv->mesh_dev);
295 }
296
297 libertas_prepare_and_send_command(priv,
298 CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
299 CMD_OPTION_WAITFORRSP, 0, &adapter->monitormode);
300 return strlen(buf);
301}
302
303/**
304 * libertas_rtap attribute to be exported per mshX interface
305 * through sysfs (/sys/class/net/mshX/libertas-rtap)
306 */
307static DEVICE_ATTR(libertas_rtap, 0644, libertas_rtap_get,
308 libertas_rtap_set );
309
249/** 310/**
250 * anycast_mask attribute to be exported per mshX interface 311 * anycast_mask attribute to be exported per mshX interface
251 * through sysfs (/sys/class/net/mshX/anycast_mask) 312 * through sysfs (/sys/class/net/mshX/anycast_mask)
@@ -480,6 +541,10 @@ static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,
480 int ret; 541 int ret;
481 542
482 lbs_deb_enter(LBS_DEB_MESH); 543 lbs_deb_enter(LBS_DEB_MESH);
544 if(priv->adapter->monitormode != WLAN_MONITOR_OFF) {
545 netif_stop_queue(dev);
546 return -EOPNOTSUPP;
547 }
483 548
484 SET_MESH_FRAME(skb); 549 SET_MESH_FRAME(skb);
485 550
@@ -494,10 +559,16 @@ static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,
494 */ 559 */
495static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) 560static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
496{ 561{
562 wlan_private *priv = dev->priv;
497 int ret; 563 int ret;
498 564
499 lbs_deb_enter(LBS_DEB_NET); 565 lbs_deb_enter(LBS_DEB_NET);
500 566
567 if(priv->adapter->monitormode != WLAN_MONITOR_OFF) {
568 netif_stop_queue(dev);
569 return -EOPNOTSUPP;
570 }
571
501 UNSET_MESH_FRAME(skb); 572 UNSET_MESH_FRAME(skb);
502 573
503 ret = libertas_hard_start_xmit(skb, dev); 574 ret = libertas_hard_start_xmit(skb, dev);
@@ -517,7 +588,7 @@ static void libertas_tx_timeout(struct net_device *dev)
517 dev->trans_start = jiffies; 588 dev->trans_start = jiffies;
518 589
519 if (priv->adapter->currenttxskb) { 590 if (priv->adapter->currenttxskb) {
520 if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { 591 if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
521 /* If we are here, we have not received feedback from 592 /* If we are here, we have not received feedback from
522 the previous packet. Assume TX_FAIL and move on. */ 593 the previous packet. Assume TX_FAIL and move on. */
523 priv->adapter->eventcause = 0x01000000; 594 priv->adapter->eventcause = 0x01000000;
@@ -1169,6 +1240,9 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
1169 spin_lock_init(&priv->adapter->driver_lock); 1240 spin_lock_init(&priv->adapter->driver_lock);
1170 init_waitqueue_head(&priv->adapter->cmd_pending); 1241 init_waitqueue_head(&priv->adapter->cmd_pending);
1171 priv->adapter->nr_cmd_pending = 0; 1242 priv->adapter->nr_cmd_pending = 0;
1243 priv->rtap_net_dev = NULL;
1244 if (device_create_file(dmdev, &dev_attr_libertas_rtap))
1245 goto err_kzalloc;
1172 goto done; 1246 goto done;
1173 1247
1174err_kzalloc: 1248err_kzalloc:
@@ -1333,6 +1407,7 @@ int libertas_remove_card(wlan_private *priv)
1333 1407
1334 lbs_deb_enter(LBS_DEB_NET); 1408 lbs_deb_enter(LBS_DEB_NET);
1335 1409
1410 libertas_remove_rtap(priv);
1336 if (!priv) 1411 if (!priv)
1337 goto out; 1412 goto out;
1338 1413
@@ -1342,6 +1417,7 @@ int libertas_remove_card(wlan_private *priv)
1342 goto out; 1417 goto out;
1343 1418
1344 dev = priv->dev; 1419 dev = priv->dev;
1420 device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
1345 1421
1346 netif_stop_queue(priv->dev); 1422 netif_stop_queue(priv->dev);
1347 netif_carrier_off(priv->dev); 1423 netif_carrier_off(priv->dev);
@@ -1537,6 +1613,81 @@ static void libertas_exit_module(void)
1537 lbs_deb_leave(LBS_DEB_MAIN); 1613 lbs_deb_leave(LBS_DEB_MAIN);
1538} 1614}
1539 1615
1616/*
1617 * rtap interface support fuctions
1618 */
1619
1620static int libertas_rtap_open(struct net_device *dev)
1621{
1622 netif_carrier_off(dev);
1623 netif_stop_queue(dev);
1624 return 0;
1625}
1626
1627static int libertas_rtap_stop(struct net_device *dev)
1628{
1629 return 0;
1630}
1631
1632static int libertas_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
1633{
1634 netif_stop_queue(dev);
1635 return -EOPNOTSUPP;
1636}
1637
1638static struct net_device_stats *libertas_rtap_get_stats(struct net_device *dev)
1639{
1640 wlan_private *priv = dev->priv;
1641 return &priv->ieee->stats;
1642}
1643
1644
1645void libertas_remove_rtap(wlan_private *priv)
1646{
1647 if (priv->rtap_net_dev == NULL)
1648 return;
1649 unregister_netdev(priv->rtap_net_dev);
1650 free_ieee80211(priv->rtap_net_dev);
1651 priv->rtap_net_dev = NULL;
1652}
1653
1654int libertas_add_rtap(wlan_private *priv)
1655{
1656 int rc = 0;
1657
1658 if (priv->rtap_net_dev)
1659 return -EPERM;
1660
1661 priv->rtap_net_dev = alloc_ieee80211(0);
1662 if (priv->rtap_net_dev == NULL)
1663 return -ENOMEM;
1664
1665
1666 priv->ieee = netdev_priv(priv->rtap_net_dev);
1667
1668 strcpy(priv->rtap_net_dev->name, "rtap%d");
1669
1670 priv->rtap_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
1671 priv->rtap_net_dev->open = libertas_rtap_open;
1672 priv->rtap_net_dev->stop = libertas_rtap_stop;
1673 priv->rtap_net_dev->get_stats = libertas_rtap_get_stats;
1674 priv->rtap_net_dev->hard_start_xmit = libertas_rtap_hard_start_xmit;
1675 priv->rtap_net_dev->set_multicast_list = libertas_set_multicast_list;
1676 priv->rtap_net_dev->priv = priv;
1677
1678 priv->ieee->iw_mode = IW_MODE_MONITOR;
1679
1680 rc = register_netdev(priv->rtap_net_dev);
1681 if (rc) {
1682 free_ieee80211(priv->rtap_net_dev);
1683 priv->rtap_net_dev = NULL;
1684 return rc;
1685 }
1686
1687 return 0;
1688}
1689
1690
1540module_init(libertas_init_module); 1691module_init(libertas_init_module);
1541module_exit(libertas_exit_module); 1692module_exit(libertas_exit_module);
1542 1693