diff -du -r pcmcia-cs-3.1.31/wireless/hermes.h pcmcia-cs-3.1.31-patched/wireless/hermes.h
--- pcmcia-cs-3.1.31/wireless/hermes.h	Tue Oct  9 19:34:06 2001
+++ pcmcia-cs-3.1.31-patched/wireless/hermes.h	Wed Feb 27 15:12:46 2002
@@ -233,8 +233,60 @@
 /* Wavelan-II Management Protocol frame */
 #define		HERMES_RXSTAT_WMP		(0x6000)
 
+/* Inquiry constants and data types */
+
+#define HERMES_INQ_TALLIES		(0xF100)
+#define HERMES_INQ_SCAN			(0xF101)
+#define HERMES_INQ_LINKSTATUS		(0xF200)
+
 #ifdef __KERNEL__
 
+struct hermes_tallies_frame {
+	u16 TxUnicastFrames;
+	u16 TxMulticastFrames;
+	u16 TxFragments;
+	u16 TxUnicastOctets;
+	u16 TxMulticastOctets;
+	u16 TxDeferredTransmissions;
+	u16 TxSingleRetryFrames;
+	u16 TxMultipleRetryFrames;
+	u16 TxRetryLimitExceeded;
+	u16 TxDiscards;
+	u16 RxUnicastFrames;
+	u16 RxMulticastFrames;
+	u16 RxFragments;
+	u16 RxUnicastOctets;
+	u16 RxMulticastOctets;
+	u16 RxFCSErrors;
+	u16 RxDiscards_NoBuffer;
+	u16 TxDiscardsWrongSA;
+	u16 RxWEPUndecryptable;
+	u16 RxMsgInMsgFragments;
+	u16 RxMsgInBadMsgFragments;
+	/* Those last are probably not available in very old firmwares */
+	u16 RxDiscards_WEPICVError;
+	u16 RxDiscards_WEPExcluded;
+} __attribute__ ((packed));
+
+/* modified by patrik@cqure.net */
+/* Grabbed from wlan-ng - Thanks Mark... - Jean II
+ * This is the result of a scan inquiry command */
+/* Structure describing info about an Access Point */
+struct hermes_scan_apinfo {
+	u16 channel;		/* Channel where the AP sits */
+  	u16 level;		/* Signal level */
+  	u16 noise;		/* Noise level */
+	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+       u16 beacon_interv;      /* Beacon Interval ? */
+       u16 capabilities;	/* Capabilities ? */
+       u16 essidlen;           /* ESSID length */
+	u8 essid[32];		/* ESSID of the network */
+} __attribute__ ((packed));
+/* Container */
+struct hermes_scan_frame {
+  struct hermes_scan_apinfo aps[35];        /* Scan result */
+} __attribute__ ((packed));
+ 
 /* Basic control structure */
 typedef struct hermes {
 	uint iobase;
@@ -313,6 +365,15 @@
 
 	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), 
 				 0, &resp);
+}
+
+/* Initiate an INQUIRE command (tallies or scan).  The result will come as an
+ * information frame in __dldwd_ev_info() */
+static inline int hermes_inquire(hermes_t *hw, u16 rid)
+{
+	hermes_response_t resp;
+
+	return hermes_docmd_wait(hw, HERMES_CMD_INQ, rid, &resp);
 }
 
 #define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
diff -du -r pcmcia-cs-3.1.31/wireless/orinoco.c pcmcia-cs-3.1.31-patched/wireless/orinoco.c
--- pcmcia-cs-3.1.31/wireless/orinoco.c	Fri Oct 19 20:53:20 2001
+++ pcmcia-cs-3.1.31-patched/wireless/orinoco.c	Wed Feb 27 15:42:15 2002
@@ -237,6 +237,8 @@
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/list.h>
+#include <linux/netlink.h>
+#include <net/sock.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -341,6 +343,13 @@
 	uint16_t qual, signal, noise;
 } __PACKED__ dldwd_commsqual_t;
 
+/* sniffing stuff added by Patrik Karlsson, patrik@cqure.net 20020201 */
+/* Netlink interface(s) */
+static struct sock	*nl_indicate = NULL;
+
+#define APSTATUS_NL_SOCK_IND NETLINK_USERSOCK
+#define APSTATUS_NL_MCAST_GRP_SNIFF 0x00000002
+
 #define TX_TIMEOUT (4*HZ) /* 4 second timeout */
 
 /*
@@ -399,6 +408,9 @@
 static int dldwd_proc_init(void);
 static void dldwd_proc_cleanup(void);
 
+/* dummy functions */
+void p80211ind_rx(struct sock *sk, int len);
+
 /*
  * Inline functions
  */
@@ -1083,9 +1095,110 @@
 
 static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw)
 {
-	DEBUG(3, "%s: Information frame received.\n", priv->ndev.name);
-	/* We don't actually do anything about it - we assume the MAC
-	   controller can deal with it */
+	struct net_device *dev = &priv->ndev;
+	u16 infofid;
+	struct {
+		u16 len;
+		u16 type;
+	} __attribute__ ((packed)) info;
+	int err;
+
+	/* This is an answer to an INQUIRE command that we did earlier,
+	 * or an information "event" generated by the card
+	 * The controller return to us a pseudo frame containing
+	 * the information in question - Jean II */
+	infofid = hermes_read_regn(hw, INFOFID);
+	DEBUG(3, "%s: __dldwd_ev_info(): INFOFID=0x%04x\n", dev->name,
+	      infofid);
+
+	/* Read the info frame header - don't try too hard */
+	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
+			       infofid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading info frame. "
+		       "Frame dropped.\n", dev->name, err);
+		return;
+	}
+	
+	switch (le16_to_cpu(info.type)) {
+
+	  /* 
+	   * do the actual scanning, 20020201 patrik@cqure.net
+	   */
+	case HERMES_INQ_SCAN: {
+	  struct hermes_scan_frame scan;
+	  struct sk_buff *skb;
+	  int len = le16_to_cpu(info.len) - 1;
+
+	  /* len seems to be 25 even if its longer */
+	  if ( len >= 25 )
+	    len = sizeof(struct hermes_scan_apinfo);
+
+	  hermes_read_words(hw, HERMES_DATA1, (void *)&scan, len);
+
+	  if ( ( skb = alloc_skb(len, GFP_ATOMIC) ) == NULL ) {
+	    DEBUG(2, "alloc_skb failed trying to allocate %d bytes\n", len);
+	    return;
+	  }
+
+	  skb_put(skb, len);
+	  memcpy(skb->data, &scan, len);
+
+
+	  /* create a netlink socket to listen to */
+	  nl_indicate =  netlink_kernel_create( APSTATUS_NL_SOCK_IND, &p80211ind_rx);
+
+	  netlink_broadcast(nl_indicate, skb, 0, APSTATUS_NL_MCAST_GRP_SNIFF, 
+			    GFP_ATOMIC);
+
+	  sock_release(nl_indicate->socket);
+	   
+	  break;
+
+	}
+	case HERMES_INQ_TALLIES: {
+		struct hermes_tallies_frame tallies;
+		struct iw_statistics *wstats = &priv->wstats;
+		int len = le16_to_cpu(info.len) - 1;
+		
+		if (len > (sizeof(tallies) / 2)) {
+			DEBUG(1, "%s: tallies frame too long.\n", dev->name);
+			len = sizeof(tallies) / 2;
+		}
+		
+		/* Read directly the data (no seek) */
+		hermes_read_words(hw, HERMES_DATA1, (void *) &tallies, len);
+		
+		/* Increment our various counters */
+		/* wstats->discard.nwid - no wrong BSSID stuff */
+		wstats->discard.code +=
+			le16_to_cpu(tallies.RxWEPUndecryptable);
+		if (len == (sizeof(tallies) / 2))  
+			wstats->discard.code +=
+				le16_to_cpu(tallies.RxDiscards_WEPICVError) +
+				le16_to_cpu(tallies.RxDiscards_WEPExcluded);
+		wstats->discard.misc +=
+			le16_to_cpu(tallies.TxDiscardsWrongSA);
+#if WIRELESS_EXT > 11
+		wstats->discard.fragment +=
+			le16_to_cpu(tallies.RxMsgInBadMsgFragments);
+		wstats->discard.retries +=
+			le16_to_cpu(tallies.TxRetryLimitExceeded);
+		/* wstats->miss.beacon - no match */
+#if ORINOCO_DEBUG > 3
+		/* Hack for debugging - should not be taken as an example */
+		wstats->discard.nwid += le16_to_cpu(tallies.TxUnicastFrames);
+		wstats->miss.beacon += le16_to_cpu(tallies.RxUnicastFrames);
+#endif
+#endif /* WIRELESS_EXT > 11 */
+	}
+	break;
+	default:
+		DEBUG(1, "%s: Unknown information frame received (type %04x).\n",
+		      priv->ndev.name, le16_to_cpu(info.type));
+		/* We don't actually do anything about it */
+		break;
+	}
 }
 
 static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw)
@@ -3602,6 +3715,17 @@
 			      total, buf);
 }
 
+/*
+ * Empty dummy function, theres nothing to see here
+ */
+static int
+orinoco_proc_get_hermes_cmds(char *page, char **start, off_t requested_offset,
+			   int requested_len, int *eof, void *data)
+{
+  return 0;
+}
+
+
 /* initialise the /proc subsystem for the hermes driver, creating the
  * separate entries */
 static int
@@ -3624,6 +3748,43 @@
 	return err;
 }
 
+/* copy-paste linux-wlan-ng */
+/* userland data not supported */
+void p80211ind_rx(struct sock *sk, int len)
+{
+	return;
+}
+
+
+int
+orinoco_send_scan_cmd(dldwd_priv_t *priv) {
+
+  hermes_inquire(&priv->hw, HERMES_INQ_SCAN);
+  
+  return 0;
+}
+
+int
+orinoco_proc_set_hermes_cmds(struct file *file, const char *buffer,
+		   unsigned long count, void *context) 
+{
+  char buf[256];
+
+  /* copy - paste code from elsewere in kernel */
+  if (count > 250)
+    return -EPERM;
+  if (copy_from_user(buf, buffer, count))
+    return -EFAULT;
+  
+  buf[count] = 0;
+  
+  if (!strncmp(buf, "apscan", 6)) {
+    orinoco_send_scan_cmd(context);
+  }
+
+  return -EL3RST;
+}
+
 int
 dldwd_proc_dev_init(dldwd_priv_t *dev)
 {
@@ -3653,6 +3814,16 @@
 		printk(KERN_ERR "Unable to initialise /proc/hermes/%s/recs.\n",  ndev->name);
 		goto fail;
 	}
+
+	dev->dir_cmds = NULL;
+	dev->dir_cmds = create_proc_read_entry("cmds", S_IFREG | S_IRUGO,
+						dev->dir_dev, orinoco_proc_get_hermes_cmds, dev);
+	if (dev->dir_cmds == NULL) {
+		printk(KERN_ERR "Unable to initialise /proc/hermes/%s/cmds.\n",  ndev->name);
+ 		goto fail;
+ 	}
+ 
+	dev->dir_cmds->write_proc = orinoco_proc_set_hermes_cmds;
 
 	return 0;
  fail:
diff -du -r pcmcia-cs-3.1.31/wireless/orinoco.h pcmcia-cs-3.1.31-patched/wireless/orinoco.h
--- pcmcia-cs-3.1.31/wireless/orinoco.h	Tue Oct  9 20:01:32 2001
+++ pcmcia-cs-3.1.31-patched/wireless/orinoco.h	Wed Feb 27 14:36:47 2002
@@ -102,6 +102,7 @@
 	struct proc_dir_entry *dir_dev;
 	struct proc_dir_entry *dir_regs;
 	struct proc_dir_entry *dir_recs;
+	struct proc_dir_entry *dir_cmds;
 } dldwd_priv_t;
 
 /*====================================================================*/
