aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/rx.c
diff options
context:
space:
mode:
authorLuis Carlos Cobo <luisca@cozybit.com>2007-08-02 13:16:55 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:13 -0400
commit965f8bbc6c92233600b176f4c80299f6766df9bd (patch)
tree85043fb97112a148d69171b744568fa78de2e05d /drivers/net/wireless/libertas/rx.c
parent9483f03150cbfa1f706355b7f9d218d6086c6fce (diff)
[PATCH] libertas: monitor mode support for OLPC firmware
Driver support for the monitor mode support that will be available in the next OLPC 'bleeding edge' Marvell firmware release (most likely, 5.110.16.p2). To activate monitor mode, echo mode > /sys/class/net/{ethX,mshX}/device/libertas_rtap where mode is the hex mask that specifies which frames to sniff (in short, 0x1 for data, 0x2 for all management but beacons, 0x4 for beacons). Any non zero mode will activate the monitor mode, inhibiting transmission in ethX and mshX interfaces and routing all the incoming traffic to a new rtapX interface that will output the packets in 802.11+radiotap headers format. Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/rx.c')
-rw-r--r--drivers/net/wireless/libertas/rx.c49
1 files changed, 21 insertions, 28 deletions
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 83a7765fd23c..09def943b910 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -138,12 +138,15 @@ void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
138{ 138{
139 lbs_deb_rx("skb->data %p\n", skb->data); 139 lbs_deb_rx("skb->data %p\n", skb->data);
140 140
141 if (priv->mesh_dev && IS_MESH_FRAME(skb)) 141 if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
142 skb->protocol = eth_type_trans(skb, priv->mesh_dev); 142 skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
143 else 143 } else {
144 skb->protocol = eth_type_trans(skb, priv->dev); 144 if (priv->mesh_dev && IS_MESH_FRAME(skb))
145 skb->protocol = eth_type_trans(skb, priv->mesh_dev);
146 else
147 skb->protocol = eth_type_trans(skb, priv->dev);
148 }
145 skb->ip_summed = CHECKSUM_UNNECESSARY; 149 skb->ip_summed = CHECKSUM_UNNECESSARY;
146
147 netif_rx(skb); 150 netif_rx(skb);
148} 151}
149 152
@@ -170,7 +173,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
170 173
171 lbs_deb_enter(LBS_DEB_RX); 174 lbs_deb_enter(LBS_DEB_RX);
172 175
173 if (priv->adapter->linkmode == WLAN_LINKMODE_802_11) 176 if (priv->adapter->monitormode != WLAN_MONITOR_OFF)
174 return process_rxed_802_11_packet(priv, skb); 177 return process_rxed_802_11_packet(priv, skb);
175 178
176 p_rx_pkt = (struct rxpackethdr *) skb->data; 179 p_rx_pkt = (struct rxpackethdr *) skb->data;
@@ -290,21 +293,22 @@ static u8 convert_mv_rate_to_radiotap(u8 rate)
290 return 11; 293 return 11;
291 case 3: /* 11 Mbps */ 294 case 3: /* 11 Mbps */
292 return 22; 295 return 22;
293 case 4: /* 6 Mbps */ 296 /* case 4: reserved */
297 case 5: /* 6 Mbps */
294 return 12; 298 return 12;
295 case 5: /* 9 Mbps */ 299 case 6: /* 9 Mbps */
296 return 18; 300 return 18;
297 case 6: /* 12 Mbps */ 301 case 7: /* 12 Mbps */
298 return 24; 302 return 24;
299 case 7: /* 18 Mbps */ 303 case 8: /* 18 Mbps */
300 return 36; 304 return 36;
301 case 8: /* 24 Mbps */ 305 case 9: /* 24 Mbps */
302 return 48; 306 return 48;
303 case 9: /* 36 Mbps */ 307 case 10: /* 36 Mbps */
304 return 72; 308 return 72;
305 case 10: /* 48 Mbps */ 309 case 11: /* 48 Mbps */
306 return 96; 310 return 96;
307 case 11: /* 54 Mbps */ 311 case 12: /* 54 Mbps */
308 return 108; 312 return 108;
309 } 313 }
310 lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate); 314 lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
@@ -355,14 +359,13 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
355 skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); 359 skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
356 360
357 /* create the exported radio header */ 361 /* create the exported radio header */
358 switch (priv->adapter->radiomode) { 362 if(priv->adapter->monitormode == WLAN_MONITOR_OFF) {
359 case WLAN_RADIOMODE_NONE:
360 /* no radio header */ 363 /* no radio header */
361 /* chop the rxpd */ 364 /* chop the rxpd */
362 skb_pull(skb, sizeof(struct rxpd)); 365 skb_pull(skb, sizeof(struct rxpd));
363 break; 366 }
364 367
365 case WLAN_RADIOMODE_RADIOTAP: 368 else {
366 /* radiotap header */ 369 /* radiotap header */
367 radiotap_hdr.hdr.it_version = 0; 370 radiotap_hdr.hdr.it_version = 0;
368 /* XXX must check this value for pad */ 371 /* XXX must check this value for pad */
@@ -400,16 +403,6 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
400 rx_radiotap_hdr)); 403 rx_radiotap_hdr));
401 memcpy(pradiotap_hdr, &radiotap_hdr, 404 memcpy(pradiotap_hdr, &radiotap_hdr,
402 sizeof(struct rx_radiotap_hdr)); 405 sizeof(struct rx_radiotap_hdr));
403 break;
404
405 default:
406 /* unknown header */
407 lbs_pr_alert("Unknown radiomode %i\n",
408 priv->adapter->radiomode);
409 /* don't export any header */
410 /* chop the rxpd */
411 skb_pull(skb, sizeof(struct rxpd));
412 break;
413 } 406 }
414 407
415 /* Take the data rate from the rxpd structure 408 /* Take the data rate from the rxpd structure