Binary files orinoco-cvs-pure/.orinoco.c.swo and orinoco-cvs/.orinoco.c.swo differ
Binary files orinoco-cvs-pure/.orinoco.c.swp and orinoco-cvs/.orinoco.c.swp differ
Common subdirectories: orinoco-cvs-pure/CVS and orinoco-cvs/CVS
diff -u --new-file orinoco-cvs-pure/orinoco.c orinoco-cvs/orinoco.c
--- orinoco-cvs-pure/orinoco.c	2004-02-26 14:04:18.000000000 -0500
+++ orinoco-cvs/orinoco.c	2004-02-26 20:03:42.000000000 -0500
@@ -430,6 +430,7 @@
  *	o Fix recognition of Intersil x.x.1 firmware (Pavel Roskin).
  *	o Don't let unprivileged users use dump_recs (Pavel Roskin).
  *	o RF monitor mode support (Pavel Roskin).
+ *	o Prism2 and Prism2AVS header support, FCS byte support (Mike Kershaw)
  *
  * TODO
  *	o Handle de-encapsulation within network layer, provide 802.11
@@ -486,6 +487,7 @@
 #include "hermes_rid.h"
 #include "orinoco.h"
 #include "ieee802_11.h"
+#include "prism2header.h"
 
 /********************************************************************/
 /* Module information											   */
@@ -1133,7 +1135,7 @@
  *
  * Call context: interrupt
  */
-static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, int len)
+static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, struct hermes_rx_descriptor *rxdesc, int len)
 {
 	u32 hdrlen = 30;	/* return full header by default */
 	u32 datalen = 0;
@@ -1144,6 +1146,11 @@
 	struct orinoco_private *priv = dev->priv;
 	struct net_device_stats *stats = &priv->stats;
 	hermes_t *hw = &priv->hw;
+	int skballoclen;
+	uint8_t *datap;
+	p80211msg_lnxind_wlansniffrm_t  *prism2hdr;
+	prism2_avs_80211_v1_header *prism2avshdr;
+	uint8_t fcsquad[4] = {0xFF, 0xFF, 0xFF, 0xFF};
 
 	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 
 				   HERMES_802_11_OFFSET);
@@ -1196,7 +1203,19 @@
 		goto drop;
 	}
 
-	skb = dev_alloc_skb(hdrlen + datalen);
+	/* Handle allocation for different custom headers */
+	if (priv->prism2header == 1 && dev->type == ARPHRD_IEEE80211_PRISM) 
+		skballoclen = hdrlen + datalen + sizeof(p80211msg_lnxind_wlansniffrm_t);
+	else if (priv->prism2header == 2 && dev->type == ARPHRD_IEEE80211_PRISM) 
+		skballoclen = hdrlen + datalen + sizeof(prism2_avs_80211_v1_header);
+	else
+		skballoclen = hdrlen + datalen;
+
+	/* Handle FCS bytes */
+	if (priv->fcsbytes)
+		skballoclen = skballoclen + 4;
+   
+	skb = dev_alloc_skb(skballoclen);
 	if (!skb) {
 		printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
 			   dev->name);
@@ -1204,13 +1223,99 @@
 		goto drop;
 	}
 
+	skb_put(skb, skballoclen); 
+
+	/* Do we build a custom header?  Only attach it if we're in the right linktype */
+	if (priv->prism2header == 1 && dev->type == ARPHRD_IEEE80211_PRISM) {
+		datap = skb->data + sizeof(p80211msg_lnxind_wlansniffrm_t);
+		prism2hdr = (p80211msg_lnxind_wlansniffrm_t *) skb->data;
+
+		/* Initialize the message members */
+		prism2hdr->msgcode = DIDmsg_lnxind_wlansniffrm;
+		prism2hdr->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
+		strcpy(prism2hdr->devname, priv->ndev->name);
+
+		prism2hdr->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+		prism2hdr->hosttime.status = 0;
+		prism2hdr->hosttime.len = 4;
+		prism2hdr->hosttime.data = jiffies;
+
+		prism2hdr->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+		prism2hdr->mactime.status = 0;
+		prism2hdr->mactime.len = 4;
+		prism2hdr->mactime.data = rxdesc->time;
+
+		prism2hdr->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+		prism2hdr->channel.status = P80211ENUM_msgitem_status_no_value;
+		prism2hdr->channel.len = 4;
+		prism2hdr->channel.data = 0;
+
+		prism2hdr->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+		prism2hdr->rssi.status = P80211ENUM_msgitem_status_no_value;
+		prism2hdr->rssi.len = 4;
+		prism2hdr->rssi.data = 0;
+
+		prism2hdr->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
+		prism2hdr->sq.status = P80211ENUM_msgitem_status_no_value;
+		prism2hdr->sq.len = 4;
+		prism2hdr->sq.data = 0;
+
+		prism2hdr->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+		prism2hdr->signal.status = 0;
+		prism2hdr->signal.len = 4;
+		prism2hdr->signal.data = rxdesc->signal;
+
+		prism2hdr->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+		prism2hdr->noise.status = 0;
+		prism2hdr->noise.len = 4;
+		prism2hdr->noise.data = rxdesc->silence;
+
+		prism2hdr->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+		prism2hdr->rate.status = 0;
+		prism2hdr->rate.len = 4;
+		prism2hdr->rate.data = rxdesc->rate / 5; /* set to 802.11 units */
+
+		prism2hdr->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+		prism2hdr->istx.status = 0;
+		prism2hdr->istx.len = 4;
+		prism2hdr->istx.data = 0;
+
+		prism2hdr->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+		prism2hdr->frmlen.status = 0;
+		prism2hdr->frmlen.len = 4;
+		prism2hdr->frmlen.data = hdrlen + datalen;
+	} else if (priv->prism2header == 2 && dev->type == ARPHRD_IEEE80211_PRISM) {
+		datap = skb->data + sizeof(prism2_avs_80211_v1_header);
+		prism2avshdr = (prism2_avs_80211_v1_header *) skb->data;
+
+		prism2avshdr->version = htonl(P80211CAPTURE_VERSION);
+		prism2avshdr->length = htonl(sizeof(prism2_avs_80211_v1_header));
+		prism2avshdr->mactime = __cpu_to_be64(rxdesc->time) * 1000;
+		prism2avshdr->hosttime = __cpu_to_be64(jiffies);
+		prism2avshdr->phytype = htonl(4); /* 802.11b */
+		prism2avshdr->channel = htonl(0);
+		prism2avshdr->datarate = htonl(rxdesc->rate);
+		prism2avshdr->antenna = htonl(0);
+		prism2avshdr->priority = htonl(0);
+		prism2avshdr->ssi_type = htonl(3); /* ssi raw */
+		prism2avshdr->ssi_signal = htonl(rxdesc->signal);
+		prism2avshdr->ssi_noise = htonl(rxdesc->silence);
+		prism2avshdr->preamble = htonl(0); /* Unknown */
+		prism2avshdr->encoding = htonl(1); /* CCK */
+	} else {
+		datap = skb->data;
+	}
+	
 	/* Copy the 802.11 header to the skb */
+	/*
 	memcpy(skb_put(skb, hdrlen), &(hdr.frame_ctl), hdrlen);
+	*/
+	memcpy(datap, &(hdr.frame_ctl), hdrlen);
 	skb->mac.raw = skb->data;
 
 	/* If any, copy the data from the card to the skb */
 	if (datalen > 0) {
-		err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
+		err = hermes_bap_pread(hw, IRQ_BAP, datap + hdrlen,
 				 (datalen + 1) & ~1, rxfid,
 				 HERMES_802_2_OFFSET);
 		if (err) {
@@ -1220,6 +1325,10 @@
 		}
 	}
 
+	/* Attach the FCS if requested */
+	if (priv->fcsbytes)
+		memcpy(skb->data + skballoclen - 4, fcsquad, 4);
+
 	skb->dev = dev;
 	skb->ip_summed = CHECKSUM_NONE;
 	skb->pkt_type = PACKET_OTHERHOST;
@@ -1298,7 +1407,7 @@
 	
 	/* Handle monitor frames */
 	if (port == 7) {
-		orinoco_rx_monitor(dev, rxfid, length);
+		orinoco_rx_monitor(dev, rxfid, &desc, length);
 		return;
 	}
 
@@ -2075,9 +2184,17 @@
 		}
 	}
 
-	if (priv->iw_mode == IW_MODE_MONITOR && dev->type != ARPHRD_IEEE80211) {
+	/* Enable monitor mode if we're not already in it */
+	if (priv->iw_mode == IW_MODE_MONITOR && dev->type != ARPHRD_IEEE80211 &&
+		dev->type != ARPHRD_IEEE80211_PRISM) {
 		/* Enable monitor mode */
-		dev->type = ARPHRD_IEEE80211;
+
+		/* Set the link type */
+		if (priv->prism2header)
+			dev->type = ARPHRD_IEEE80211_PRISM;
+		else
+			dev->type = ARPHRD_IEEE80211;
+
 		err = hermes_docmd_wait(hw,
 					HERMES_CMD_MONITOR | HERMES_MONITOR_ENABLE,
 					0, NULL);
@@ -2085,7 +2202,9 @@
 			return err;
 	}
 
-	if (priv->iw_mode != IW_MODE_MONITOR && dev->type == ARPHRD_IEEE80211) {
+	/* Disable monitor mode if we're not already out of it */
+	if (priv->iw_mode != IW_MODE_MONITOR && 
+		(dev->type == ARPHRD_IEEE80211 || dev->type == ARPHRD_IEEE80211_PRISM)) {
 		/* Disable monitor mode */
 		dev->type = ARPHRD_ETHER;
 		err = hermes_docmd_wait(hw,
@@ -2653,6 +2772,10 @@
 	priv->wep_on = 0;
 	priv->tx_key = 0;
 
+	/* Don't turn on the rfmon fancy stuff by default */
+	priv->prism2header = 0;
+	priv->fcsbytes = 0;
+
 	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
 	if (err == -EIO) {
 		/* Try workaround for old Symbol firmware bug */
@@ -4369,6 +4492,60 @@
 }
 #endif	/* WIRELESS_EXT > 13 */
 
+/* Set the prism2 headers */
+static int orinoco_ioctl_setprism2header(struct net_device *dev,
+					 struct iw_request_info *info,
+					 void *wrqu,
+					 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int val = *( (int *) extra );
+	unsigned long flags;
+
+	if (orinoco_lock(priv, &flags) != 0)
+		return -EBUSY;
+
+	/* Only allow legal values: 0 off, 1 prism2, 2 prism2avs */
+	if (val < 0 || val > 2)
+		return -EINVAL;
+
+	/* If we're in rfmon, update the linktype appropriately */
+	if (priv->iw_mode == IW_MODE_MONITOR && dev->type != ARPHRD_IEEE80211_PRISM && val) {
+		printk(KERN_DEBUG "setting type ieee80211_prism\n");
+		dev->type = ARPHRD_IEEE80211_PRISM;
+	} else if (priv->iw_mode == IW_MODE_MONITOR && dev->type != ARPHRD_IEEE80211 && val == 0) {
+		printk(KERN_DEBUG "setting type ieee80211\n");
+		dev->type = ARPHRD_IEEE80211;
+	}
+	
+	priv->prism2header = val;
+
+	orinoco_unlock(priv, &flags);
+	return 0;
+}
+
+/* Set if we append trailing FCS bytes */
+static int orinoco_ioctl_setfcsbytes(struct net_device *dev,
+					 struct iw_request_info *info,
+					 void *wrqu,
+					 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int val = *( (int *) extra );
+	unsigned long flags;
+
+	if (orinoco_lock(priv, &flags) != 0)
+		return -EBUSY;
+
+	if (val < 0 || val > 1)
+		return -EINVAL;
+	
+	priv->fcsbytes = val;
+
+	orinoco_unlock(priv, &flags);
+	return 0;
+}
+
 /* Commit handler, called after set operations */
 static int orinoco_ioctl_commit(struct net_device *dev,
 				struct iw_request_info *info,
@@ -4461,6 +4638,12 @@
 	{ SIOCIWFIRSTPRIV + 0x7, 0,
 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 	  "get_ibssport" },
+	{ SIOCIWFIRSTPRIV + 0x8,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_prismheader" },
+	{ SIOCIWFIRSTPRIV + 0x10,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_fcsbytes" },
 	{ SIOCIWLASTPRIV, 0, 0, "dump_recs" },
 };
 
@@ -4538,6 +4721,8 @@
 	(iw_handler) orinoco_ioctl_getpreamble,		/* SIOCIWFIRSTPRIV + 5 */
 	(iw_handler) orinoco_ioctl_setibssport,		/* SIOCIWFIRSTPRIV + 6 */
 	(iw_handler) orinoco_ioctl_getibssport,		/* SIOCIWFIRSTPRIV + 7 */
+	(iw_handler) orinoco_ioctl_setprism2header, /* SIOCIWFIRSTPRIV + 8 */
+	(iw_handler) orinoco_ioctl_setfcsbytes,	 /* SIOCIWFIRSTPRIV + 10 */
 	[SIOCIWLASTPRIV - SIOCIWFIRSTPRIV] (iw_handler) orinoco_debug_dump_recs,
 };
 
diff -u --new-file orinoco-cvs-pure/orinoco.h orinoco-cvs/orinoco.h
--- orinoco-cvs-pure/orinoco.h	2004-02-26 14:04:18.000000000 -0500
+++ orinoco-cvs/orinoco.h	2004-02-26 11:25:12.000000000 -0500
@@ -123,6 +123,11 @@
 	u32	scan_mode;		/* Type of scan done */
 	char *	scan_result;		/* Result of previous scan */
 	int	scan_len;		/* Lenght of result */
+
+	/* rfmon format */
+	int prism2header; /* Attach no header, prism2, or prism2_avs to rfmon packets */
+	int fcsbytes; /* Attach a bogus 4-byte FCS to packets */
+
 };
 
 #ifdef ORINOCO_DEBUG
diff -u --new-file orinoco-cvs-pure/prism2header.h orinoco-cvs/prism2header.h
--- orinoco-cvs-pure/prism2header.h	1969-12-31 19:00:00.000000000 -0500
+++ orinoco-cvs/prism2header.h	2004-02-26 19:58:37.000000000 -0500
@@ -0,0 +1,98 @@
+#ifndef _PRISM2HEADER_H
+#define _PRISM2HEADER_H
+
+#define WLAN_DEVNAMELEN_MAX 16
+
+/* message data item for INT, BOUNDEDINT, ENUMINT */
+typedef struct p80211item_uint32
+{
+	uint32_t		did		__attribute__ ((packed));
+	uint16_t		status	__attribute__ ((packed));
+	uint16_t		len		__attribute__ ((packed));
+	uint32_t		data	__attribute__ ((packed));
+} __attribute__ ((packed)) p80211item_uint32_t;
+
+typedef struct p80211msg
+{
+	uint32_t	msgcode		__attribute__ ((packed));
+	uint32_t	msglen		__attribute__ ((packed));
+	uint8_t	devname[WLAN_DEVNAMELEN_MAX]	__attribute__ ((packed));
+} __attribute__ ((packed)) p80211msg_t;
+
+#define DIDmsg_lnxind_wlansniffrm 0x0041
+#define DIDmsg_lnxind_wlansniffrm_hosttime 0x1041
+#define DIDmsg_lnxind_wlansniffrm_mactime 0x2041
+#define DIDmsg_lnxind_wlansniffrm_channel 0x3041
+#define DIDmsg_lnxind_wlansniffrm_rssi 0x4041
+#define DIDmsg_lnxind_wlansniffrm_sq 0x5041
+#define DIDmsg_lnxind_wlansniffrm_signal 0x6041
+#define DIDmsg_lnxind_wlansniffrm_noise 0x7041
+#define DIDmsg_lnxind_wlansniffrm_rate 0x8041
+#define DIDmsg_lnxind_wlansniffrm_istx 0x9041
+#define DIDmsg_lnxind_wlansniffrm_frmlen 0xA041
+
+typedef struct p80211msg_lnxind_wlansniffrm
+{
+	uint32_t		msgcode;
+	uint32_t		msglen;
+	uint8_t			devname[WLAN_DEVNAMELEN_MAX];
+	p80211item_uint32_t	hosttime;
+	p80211item_uint32_t	mactime;
+	p80211item_uint32_t	channel;
+	p80211item_uint32_t	rssi;
+	p80211item_uint32_t	sq;
+	p80211item_uint32_t	signal;
+	p80211item_uint32_t	noise;
+	p80211item_uint32_t	rate;
+	p80211item_uint32_t	istx;
+	p80211item_uint32_t	frmlen;
+} __attribute__ ((packed)) p80211msg_lnxind_wlansniffrm_t;
+
+#define P80211ENUM_resultcode_success		1
+#define P80211ENUM_resultcode_invalid_parameters	2
+#define P80211ENUM_resultcode_not_supported	3
+#define P80211ENUM_resultcode_timeout		4
+#define P80211ENUM_resultcode_too_many_req	5
+#define P80211ENUM_resultcode_refused		6
+#define P80211ENUM_resultcode_bss_already	7
+#define P80211ENUM_resultcode_invalid_access	8
+#define P80211ENUM_resultcode_invalid_mibattribute	9
+#define P80211ENUM_resultcode_cant_set_readonly_mib	10
+#define P80211ENUM_resultcode_implementation_failure	11
+#define P80211ENUM_resultcode_cant_get_writeonly_mib	12
+#define P80211ENUM_msgitem_status_data_ok		0
+#define P80211ENUM_msgitem_status_no_value		1
+#define P80211ENUM_msgitem_status_invalid_itemname	2
+#define P80211ENUM_msgitem_status_invalid_itemdata	3
+#define P80211ENUM_msgitem_status_missing_itemdata	4
+#define P80211ENUM_msgitem_status_incomplete_itemdata	5
+#define P80211ENUM_msgitem_status_invalid_msg_did	6
+#define P80211ENUM_msgitem_status_invalid_mib_did	7
+#define P80211ENUM_msgitem_status_missing_conv_func	8
+#define P80211ENUM_msgitem_status_string_too_long	9
+#define P80211ENUM_msgitem_status_data_out_of_range	10
+#define P80211ENUM_msgitem_status_string_too_short	11
+#define P80211ENUM_msgitem_status_missing_valid_func	12
+#define P80211ENUM_msgitem_status_unknown		13
+#define P80211ENUM_msgitem_status_invalid_did		14
+#define P80211ENUM_msgitem_status_missing_print_func	15
+
+#define P80211CAPTURE_VERSION	 0x80211001
+typedef struct {
+	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;
+} prism2_avs_80211_v1_header;
+
+#endif /* _PRISM2HEADER_H */
