[PATCH 4/14 linux-2.6.7-rc1] prism54: add support for avs header in

From: Luis R. Rodriguez
Date: Mon May 24 2004 - 03:44:26 EST



2004-03-19 Aurelien Alleaume <slts@xxxxxxx>

* islpci_eth.[c,h], islpci_dev.[c,h], isl_ioctl.[c,h] : added
support for avs header in monitor mode. Based on the work of
Antonio Eugenio Burriel <aeb@xxxxxxxxxxxxxxx>. Unified packets
header (rfmon_header and rx_annex) for iwspy.j

* Some minor things (oid_mgt.[c,h]).

--
GnuPG Key fingerprint = 113F B290 C6D2 0251 4D84 A34A 6ADD 4937 E20A 525E
2004-03-19 Aurelien Alleaume <slts@xxxxxxx>

* islpci_eth.[c,h], islpci_dev.[c,h], isl_ioctl.[c,h] : added support
for avs header in monitor mode. Based on the work of Antonio Eugenio
Burriel <aeb@xxxxxxxxxxxxxxx>. Unified packets header (rfmon_header and
rx_annex) for iwspy.

* Some minor things (oid_mgt.[c,h]).

Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/isl_ioctl.c
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v
retrieving revision 1.145
retrieving revision 1.148
diff -u -r1.145 -r1.148
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/isl_ioctl.c 18 Mar 2004 15:27:44 -0000 1.145
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/isl_ioctl.c 19 Mar 2004 23:03:58 -0000 1.148
@@ -1,4 +1,4 @@
-/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v 1.145 2004/03/18 15:27:44 ajfa Exp $
+/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v 1.148 2004/03/19 23:03:58 ajfa Exp $
*
* Copyright (C) 2002 Intersil Americas Inc.
* (C) 2003,2004 Aurelien Alleaume <slts@xxxxxxx>
@@ -327,34 +327,15 @@
{
islpci_private *priv = netdev_priv(ndev);
int rvalue;
- u32 c = 0;
+ u32 c;

- /* prepare the structure for the set object */
- if (fwrq->m < 1000)
- /* structure value contains a channel indication */
- c = fwrq->m;
- else {
- /* structure contains a frequency indication and fwrq->e = 1 */
- int f = fwrq->m / 100000;
-
- if (fwrq->e != 1)
- return -EINVAL;
- if ((f >= 2412) && (f <= 2484)) {
- while ((c < 14) && (f != frequency_list_bg[c]))
- c++;
- if (c >= 14)
- return -EINVAL;
- } else if ((f >= (int) 5170) && (f <= (int) 5320)) {
- while ((c < 12) && (f != frequency_list_a[c]))
- c++;
- if (c >= 12)
- return -EINVAL;
- } else
- return -EINVAL;
- c++;
- }
+ if (fwrq->m < 1000)
+ /* we have a channel number */
+ c = fwrq->m;
+ else
+ c = (fwrq->e == 1) ? channel_of_freq(fwrq->m / 100000) : 0;

- rvalue = mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c);
+ rvalue = c ? mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c) : -EINVAL;

/* Call commit handler */
return (rvalue ? rvalue : -EINPROGRESS);
@@ -410,7 +391,7 @@

mgt_commit(priv);
priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR)
- ? ARPHRD_IEEE80211 : ARPHRD_ETHER;
+ ? priv->monitor_type : ARPHRD_ETHER;
up_write(&priv->mib_sem);

return 0;
@@ -1963,6 +1944,28 @@
}

int
+prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info,
+ __u32 * uwrq, char *extra)
+{
+ islpci_private *priv = netdev_priv(ndev);
+ priv->monitor_type =
+ (*uwrq ? ARPHRD_IEEE80211_PRISM : ARPHRD_IEEE80211);
+ if (priv->iw_mode == IW_MODE_MONITOR)
+ priv->ndev->type = priv->monitor_type;
+
+ return 0;
+}
+
+int
+prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info,
+ __u32 * uwrq, char *extra)
+{
+ islpci_private *priv = netdev_priv(ndev);
+ *uwrq = (priv->monitor_type == ARPHRD_IEEE80211_PRISM);
+ return 0;
+}
+
+int
prism54_set_maxframeburst(struct net_device *ndev, struct iw_request_info *info,
__u32 * uwrq, char *extra)
{
@@ -2198,6 +2201,9 @@
#define PRISM54_SET_OID_STR SIOCIWFIRSTPRIV+20
#define PRISM54_SET_OID_ADDR SIOCIWFIRSTPRIV+22

+#define PRISM54_GET_PRISMHDR SIOCIWFIRSTPRIV+23
+#define PRISM54_SET_PRISMHDR SIOCIWFIRSTPRIV+24
+
#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x }
#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x }
#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x }
@@ -2212,6 +2218,10 @@
static const struct iw_priv_args prism54_private_args[] = {
/*{ cmd, set_args, get_args, name } */
{PRISM54_RESET, 0, 0, "reset"},
+ {PRISM54_GET_PRISMHDR, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_prismhdr"},
+ {PRISM54_SET_PRISMHDR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+ "set_prismhdr"},
{PRISM54_GET_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getPolicy"},
{PRISM54_SET_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
@@ -2321,7 +2331,8 @@
(iw_handler) prism54_set_raw,
(iw_handler) NULL,
(iw_handler) prism54_set_raw,
-
+ (iw_handler) prism54_get_prismhdr,
+ (iw_handler) prism54_set_prismhdr,
};

const struct iw_handler_def prism54_handler_def = {
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/isl_oid.h
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/isl_oid.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/isl_oid.h 18 Mar 2004 15:27:44 -0000 1.5
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/isl_oid.h 19 Mar 2004 20:54:33 -0000 1.6
@@ -1,5 +1,5 @@
/*
- * $Id: isl_oid.h,v 1.5 2004/03/18 15:27:44 ajfa Exp $
+ * $Id: isl_oid.h,v 1.6 2004/03/19 20:54:33 ajfa Exp $
*
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@xxxxxxx>
* Copyright (C) 2004 Luis R. Rodriguez <mcgrof@xxxxxxxxxxxxxxxxxx>
@@ -91,19 +91,6 @@
u16 mhz[0];
} __attribute__ ((packed));

-struct obj_rx_annex {
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u32 something0;
- u32 time;
- u16 something1;
- u16 rate;
- u16 freq;
- u16 something2;
- u8 rssi;
- u8 pad[3];
-} __attribute__ ((packed));
-
/*
* in case everything's ok, the inlined function below will be
* optimized away by the compiler...
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_dev.c
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_dev.c 18 Mar 2004 11:44:17 -0000 1.71
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_dev.c 19 Mar 2004 20:54:33 -0000 1.72
@@ -1,4 +1,4 @@
-/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v 1.71 2004/03/18 11:44:17 ajfa Exp $
+/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v 1.72 2004/03/19 20:54:33 ajfa Exp $
*
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@xxxxxxx>
@@ -715,9 +715,9 @@
priv = netdev_priv(ndev);
priv->ndev = ndev;
priv->pdev = pdev;
-
+ priv->monitor_type = ARPHRD_IEEE80211;
priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
- ARPHRD_IEEE80211: ARPHRD_ETHER;
+ priv->monitor_type : ARPHRD_ETHER;

/* save the start and end address of the PCI memory area */
ndev->mem_start = (unsigned long) priv->device_base;
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_dev.h
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_dev.h 18 Mar 2004 15:27:44 -0000 1.57
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_dev.h 19 Mar 2004 20:54:33 -0000 1.58
@@ -1,4 +1,4 @@
-/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.57 2004/03/18 15:27:44 ajfa Exp $
+/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.58 2004/03/19 20:54:33 ajfa Exp $
*
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2003 Herbert Valerio Riedel <hvr@xxxxxxx>
@@ -114,6 +114,8 @@

struct iw_spy_data spy_data; /* iwspy support */

+ int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
+
struct islpci_acl acl;

/* PCI bus allocation & configuration members */
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_eth.c
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v
retrieving revision 1.31
retrieving revision 1.33
diff -u -r1.31 -r1.33
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_eth.c 18 Mar 2004 15:27:44 -0000 1.31
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_eth.c 19 Mar 2004 23:03:58 -0000 1.33
@@ -1,4 +1,4 @@
-/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.31 2004/03/18 15:27:44 ajfa Exp $
+/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.33 2004/03/19 23:03:58 ajfa Exp $
*
* Copyright (C) 2002 Intersil Americas Inc.
* Copyright (C) 2004 Aurelien Alleaume <slts@xxxxxxx>
@@ -24,10 +24,12 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/if_arp.h>

#include "isl_38xx.h"
#include "islpci_eth.h"
#include "islpci_mgt.h"
+#include "oid_mgt.h"

/******************************************************************************
Network Interface functions
@@ -246,6 +248,69 @@
return err;
}

+static inline int
+islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
+{
+ /* The card reports full 802.11 packets but with a 20 bytes
+ * header and without the FCS. But there a is a bit that
+ * indicates if the packet is corrupted :-) */
+ struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data;
+ if (hdr->flags & 0x01)
+ /* This one is bad. Drop it ! */
+ return -1;
+ if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) {
+ struct avs_80211_1_header *avs;
+ /* extract the relevant data from the header */
+ u32 clock = hdr->clock;
+ u8 rate = hdr->rate;
+ u16 freq = be16_to_cpu(hdr->freq);
+ u8 rssi = hdr->rssi;
+
+ skb_pull(*skb, sizeof (struct rfmon_header));
+
+ if (skb_headroom(*skb) < sizeof (struct avs_80211_1_header)) {
+ struct sk_buff *newskb = skb_copy_expand(*skb,
+ sizeof (struct
+ avs_80211_1_header),
+ 0, GFP_ATOMIC);
+ if (newskb) {
+ kfree_skb(*skb);
+ *skb = newskb;
+ } else
+ return -1;
+ /* This behavior is not very subtile... */
+ }
+
+ /* make room for the new header and fill it. */
+ avs =
+ (struct avs_80211_1_header *) skb_push(*skb,
+ sizeof (struct
+ avs_80211_1_header));
+
+ avs->version = htonl(P80211CAPTURE_VERSION);
+ avs->length = htonl(sizeof (struct avs_80211_1_header));
+ avs->mactime = __cpu_to_be64(clock);
+ avs->hosttime = __cpu_to_be64(jiffies);
+ avs->phytype = htonl(6); /*OFDM: 6 for (g), 8 for (a) */
+ avs->channel = htonl(channel_of_freq(freq));
+ avs->datarate = htonl(rate * 5);
+ avs->antenna = htonl(0); /*unknown */
+ avs->priority = htonl(0); /*unknown */
+ avs->ssi_type = htonl(2); /*2: dBm, 3: raw RSSI */
+ avs->ssi_signal = htonl(rssi);
+ avs->ssi_noise = htonl(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */
+ avs->preamble = htonl(0); /*unknown */
+ avs->encoding = htonl(0); /*unknown */
+ } else
+ skb_pull(*skb, sizeof (struct rfmon_header));
+
+ (*skb)->protocol = htons(ETH_P_802_2);
+ (*skb)->mac.raw = (*skb)->data;
+ (*skb)->pkt_type = PACKET_OTHERHOST;
+
+ return 0;
+}
+
int
islpci_eth_receive(islpci_private *priv)
{
@@ -315,37 +380,29 @@
/* do some additional sk_buff and network layer parameters */
skb->dev = ndev;

- /* take care of monitor mode */
- if (priv->iw_mode == IW_MODE_MONITOR) {
- /* The card reports full 802.11 packets but with a 20 bytes
- * header and without the FCS. But there a is a bit that
- * indicates if the packet is corrupted :-) */
- if (skb->data[8] & 0x01)
- /* This one is bad. Drop it ! */
- discard = 1;
- skb_pull(skb, 20);
- skb->protocol = htons(ETH_P_802_2);
- skb->mac.raw = skb->data;
- skb->pkt_type = PACKET_OTHERHOST;
- } else {
+ /* take care of monitor mode and spy monitoring. */
+ if (priv->iw_mode == IW_MODE_MONITOR)
+ discard = islpci_monitor_rx(priv, &skb);
+ else {
if (skb->data[2 * ETH_ALEN] == 0) {
/* The packet has a rx_annex. Read it for spy monitoring, Then
* remove it, while keeping the 2 leading MAC addr.
*/
struct iw_quality wstats;
- struct obj_rx_annex *annex =
- (struct obj_rx_annex *) skb->data;
- wstats.level = annex->rssi;
+ struct rx_annex_header *annex =
+ (struct rx_annex_header *) skb->data;
+ wstats.level = annex->rfmon.rssi;
/* The noise value can be a bit outdated if nobody's
* reading wireless stats... */
- wstats.noise = priv->iwstatistics.qual.noise;
+ wstats.noise = priv->local_iwstatistics.qual.noise;
wstats.qual = wstats.level - wstats.noise;
wstats.updated = 0x07;
/* Update spy records */
wireless_spy_update(ndev, annex->addr2, &wstats);
- /* 20 = sizeof(struct obj_rx_annex) - 2*ETH_ALEN */
- memcpy(skb->data + 20, skb->data, 2 * ETH_ALEN);
- skb_pull(skb, 20);
+
+ memcpy(skb->data + sizeof (struct rfmon_header),
+ skb->data, 2 * ETH_ALEN);
+ skb_pull(skb, sizeof (struct rfmon_header));
}
skb->protocol = eth_type_trans(skb, ndev);
}
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_eth.h
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_eth.h 18 Mar 2004 11:44:17 -0000 1.6
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/islpci_eth.h 19 Mar 2004 20:54:33 -0000 1.7
@@ -1,4 +1,4 @@
-/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v 1.6 2004/03/18 11:44:17 ajfa Exp $
+/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v 1.7 2004/03/19 20:54:33 ajfa Exp $
*
* Copyright (C) 2002 Intersil Americas Inc.
*
@@ -23,6 +23,47 @@
#include "isl_38xx.h"
#include "islpci_dev.h"

+struct rfmon_header {
+ u16 unk0; /* = 0x0000 */
+ u16 length; /* = 0x1400 */
+ u32 clock; /* 1MHz clock */
+ u8 flags;
+ u8 unk1;
+ u8 rate;
+ u8 unk2;
+ u16 freq;
+ u16 unk3;
+ u8 rssi;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+struct rx_annex_header {
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ struct rfmon_header rfmon;
+} __attribute__ ((packed));
+
+/* wlan-ng (and hopefully others) AVS header, version one. Fields in
+ * network byte order. */
+#define P80211CAPTURE_VERSION 0x80211001
+
+struct avs_80211_1_header {
+ uint32_t version;
+ uint32_t length;
+ uint64_t mactime;
+ uint64_t hosttime;
+ uint32_t phytype;
+ uint32_t channel;
+ uint32_t datarate;
+ uint32_t antenna;
+ uint32_t priority;
+ uint32_t ssi_type;
+ int32_t ssi_signal;
+ int32_t ssi_noise;
+ uint32_t preamble;
+ uint32_t encoding;
+};
+
void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *);
int islpci_eth_transmit(struct sk_buff *, struct net_device *);
int islpci_eth_receive(islpci_private *);
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/oid_mgt.c
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/oid_mgt.c,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -r1.9 -r1.11
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/oid_mgt.c 18 Mar 2004 15:27:44 -0000 1.9
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/oid_mgt.c 19 Mar 2004 23:03:58 -0000 1.11
@@ -31,6 +31,27 @@
5240, 5260, 5280, 5300, 5320
};

+int
+channel_of_freq(int f)
+{
+ int c = 0;
+
+ if ((f >= 2412) && (f <= 2484)) {
+ while ((c < 14) && (f != frequency_list_bg[c]))
+ c++;
+ if (c >= 14)
+ return 0;
+ } else if ((f >= (int) 5170) && (f <= (int) 5320)) {
+ while ((c < 12) && (f != frequency_list_a[c]))
+ c++;
+ if (c >= 12)
+ return 0;
+ } else
+ return 0;
+
+ return ++c;
+}
+
#define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t}
#define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED)
#define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32)
Index: linux-2.6.7-rc1/drivers/net/wireless/prism54/oid_mgt.h
===================================================================
RCS file: /var/lib/cvs/prism54-ng/ksrc/oid_mgt.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- linux-2.6.7-rc1/drivers/net/wireless/prism54/oid_mgt.h 18 Mar 2004 15:27:44 -0000 1.4
+++ linux-2.6.7-rc1/drivers/net/wireless/prism54/oid_mgt.h 19 Mar 2004 20:54:33 -0000 1.5
@@ -28,9 +28,10 @@

void mgt_clean(islpci_private *);

+/* I don't know where to put these 3 */
extern const int frequency_list_bg[];
-
extern const int frequency_list_a[];
+int channel_of_freq(int);

void mgt_le_to_cpu(int, void *);

Attachment: pgp00000.pgp
Description: PGP signature