diff -pruN player-1.6.5/acinclude.m4 player-1.6.5-rfid/acinclude.m4
--- player-1.6.5/acinclude.m4	2005-04-05 06:18:30.000000000 +0200
+++ player-1.6.5-rfid/acinclude.m4	2006-02-01 10:38:07.000000000 +0100
@@ -265,6 +265,11 @@ PLAYER_ADD_DRIVER([laserbarcode],[driver
 PLAYER_ADD_DRIVER([laservisualbarcode],[drivers/fiducial],[yes],[],[],[])
 PLAYER_ADD_DRIVER([laservisualbw],[drivers/fiducial],[yes],[],[],[])
 
+dnl (@) rbrusu [--- RFID
+PLAYER_ADD_DRIVER([insideM300],[drivers/rfid],[yes],[],[],[])
+PLAYER_ADD_DRIVER([skyetekM1],[drivers/rfid],[yes],[],[],[])
+dnl ---]
+
 dnl - added a header check to stop this building on OS X - rtv
 PLAYER_ADD_DRIVER([linuxjoystick],[drivers/joystick],[yes],[linux/joystick.h],[],[])
 
diff -pruN player-1.6.5/client_libs/c++/Makefile.am player-1.6.5-rfid/client_libs/c++/Makefile.am
--- player-1.6.5/client_libs/c++/Makefile.am	2005-05-03 01:42:29.000000000 +0200
+++ player-1.6.5-rfid/client_libs/c++/Makefile.am	2006-02-01 10:52:31.000000000 +0100
@@ -50,7 +50,10 @@ libplayerclient_a_SOURCES =   clientprox
                               energyproxy.cc \
                               speechrecognitionproxy.cc \
                               simulationproxy.cc \
-                              logproxy.cc
+                              logproxy.cc \
+			      rfidproxy.cc
+# (@) rbrusu [--- RFID
+# ---]
                               #bpsproxy.cc
                               #bpsproxy.h
 
diff -pruN player-1.6.5/client_libs/c++/playerclient.h player-1.6.5-rfid/client_libs/c++/playerclient.h
--- player-1.6.5/client_libs/c++/playerclient.h	2005-05-04 17:05:42.000000000 +0200
+++ player-1.6.5-rfid/client_libs/c++/playerclient.h	2006-02-01 10:52:49.000000000 +0100
@@ -2688,6 +2688,42 @@ class LogProxy : public ClientProxy
   virtual void Print();
 };	   
 
+// (@) rbrusu [--- RFID
+class RFIDTag
+{
+  public:
+    unsigned short type;
+    unsigned short guid[PLAYER_RFID_MAX_GUID];
+};
+/** 
+
+The @p RFIDProxy class is used to control a  @ref
+player_interface_rfid device.  It contains no methods.  
+*/
+class RFIDProxy : public ClientProxy
+{
+
+  public:
+    
+    /** number of tags */
+    int tags_count;
+    /** Array containing arrays of the latest RFID tags data. */
+    RFIDTag tags[PLAYER_RFID_MAX_TAGS];
+   
+    /** Constructor.
+        Leave the access field empty to start unconnected.
+    */
+    RFIDProxy(PlayerClient* pc, unsigned short index, 
+                unsigned char access='c');
+    ~RFIDProxy();
+
+    // interface that all proxies must provide
+    void FillData(player_msghdr_t hdr, const char* buffer);
+    
+    /// Print out current tag information.
+    void Print();
+};
+// ---]
 
 /** @} */
 /** @} */
diff -pruN player-1.6.5/client_libs/c++/rfidproxy.cc player-1.6.5-rfid/client_libs/c++/rfidproxy.cc
--- player-1.6.5/client_libs/c++/rfidproxy.cc	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/client_libs/c++/rfidproxy.cc	2006-01-31 17:50:32.000000000 +0100
@@ -0,0 +1,75 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2000-2003
+ *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
+ *                      
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * Author: Radu Bogdan Rusu
+ * client-side RFID device 
+ */
+
+#include <playerclient.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+
+RFIDProxy::RFIDProxy(PlayerClient* pc, unsigned short index,
+            unsigned char access):
+            ClientProxy(pc,PLAYER_RFID_CODE,index,access)
+{
+}
+
+RFIDProxy::~RFIDProxy()
+{
+}
+
+void RFIDProxy::FillData(player_msghdr_t hdr, const char* buffer)
+{
+  if(hdr.size != sizeof(player_rfid_data_t))
+  {
+    if(player_debug_level(-1) >= 1)
+      fprintf(stderr,"WARNING: expected %d bytes of RFID data, but "
+              "received %d. Unexpected results may ensue.\n",
+              sizeof(player_rfid_data_t),hdr.size);
+  }
+  tags_count = ntohs(((player_rfid_data_t*)buffer)->tags_count);
+
+  // fill the rfid buffer
+  for(int i = 0; i < tags_count; i++)
+  {
+	tags[i].type = ((player_rfid_data_t*)buffer)->tags[i].type;
+ 	for(int j = 0; j < PLAYER_RFID_MAX_GUID; j++)
+		tags[i].guid[j] = ((player_rfid_data_t*)buffer)->tags[i].guid[j];
+  }
+}
+
+// interface that all proxies SHOULD provide
+void RFIDProxy::Print()
+{
+  printf ("tags count = %d\n", tags_count);
+  for(int i = 0; i < tags_count && i < PLAYER_RFID_MAX_TAGS; i++)
+  {
+    for(int j = 0; j < PLAYER_RFID_MAX_GUID; j++)
+      printf("%2x ", tags[i].guid[j]);
+   puts("");
+  }
+}
diff -pruN player-1.6.5/client_libs/c++/test/Makefile.am player-1.6.5-rfid/client_libs/c++/test/Makefile.am
--- player-1.6.5/client_libs/c++/test/Makefile.am	2005-05-03 01:42:29.000000000 +0200
+++ player-1.6.5-rfid/client_libs/c++/test/Makefile.am	2006-02-01 10:53:10.000000000 +0100
@@ -38,7 +38,10 @@ test_SOURCES = test_blobfinder.cc \
                test_localize.cc \
                test_audiomixer.cc \
                test_blinkenlight.cc \
-               test_camera.cc
+               test_camera.cc \
+	       test_rfid.cc
+# (@) rbrusu [--- RFID
+# ---]
                #test_idar.cc \
                #test_idarturret.cc
                #test_misc.cc
diff -pruN player-1.6.5/client_libs/c++/test/test.cc player-1.6.5-rfid/client_libs/c++/test/test.cc
--- player-1.6.5/client_libs/c++/test/test.cc	2005-05-03 01:42:29.000000000 +0200
+++ player-1.6.5-rfid/client_libs/c++/test/test.cc	2006-02-01 10:53:21.000000000 +0100
@@ -173,6 +173,11 @@ int main(int argc, const char *argv[])
     if(strcmp(device, "camera") == 0 || strcmp(device, "all") == 0)
       test_camera(&client, index);
 
+// (@) rbrusu [--- RFID
+    // RFID device
+    if(strcmp(device, "rfid") == 0 || strcmp(device, "all") == 0)
+      test_rfid(&client, index);
+// ---]
 
     // BPS device
     /*
diff -pruN player-1.6.5/client_libs/c++/test/test.h player-1.6.5-rfid/client_libs/c++/test/test.h
--- player-1.6.5/client_libs/c++/test/test.h	2005-05-03 01:42:29.000000000 +0200
+++ player-1.6.5-rfid/client_libs/c++/test/test.h	2006-02-01 10:53:35.000000000 +0100
@@ -54,7 +54,9 @@ int test_audiomixer(PlayerClient* client
 int test_blobfinder(PlayerClient* client, int index);
 int test_blinkenlight(PlayerClient* client, int index);
 int test_camera(PlayerClient* client, int index);
-
+// (@) rbrusu [--- RFID
+int test_rfid(PlayerClient* client, int index);
+// ---]
 //int test_bps(PlayerClient* client, int index);
 
 #endif // TEST_H
diff -pruN player-1.6.5/client_libs/c++/test/test_rfid.cc player-1.6.5-rfid/client_libs/c++/test/test_rfid.cc
--- player-1.6.5/client_libs/c++/test/test_rfid.cc	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/client_libs/c++/test/test_rfid.cc	2006-01-31 17:49:45.000000000 +0100
@@ -0,0 +1,61 @@
+/*
+ * a test for the C++ RFIDProxy
+ */
+
+#include "playerclient.h"
+#include "test.h"
+#include <unistd.h>
+#include <math.h>
+
+
+
+int
+test_rfid(PlayerClient* client, int index)
+{
+  unsigned char access;
+  RFIDProxy lp(client,index,'r');
+
+  printf("device [rfid] index [%d]\n", index);
+
+  TEST("subscribing (read)");
+  if((lp.ChangeAccess(PLAYER_READ_MODE,&access) < 0) ||
+     (access != PLAYER_READ_MODE))
+  {
+    FAIL();
+    printf("DRIVER: %s\n", lp.driver_name);
+    return -1;
+  }
+  PASS();
+  printf("DRIVER: %s\n", lp.driver_name);
+
+  // wait for the rfid to warm up
+  for(int i=0;i<20;i++)
+    client->Read();
+
+  for(int t = 0; t < 100; t++)
+  {
+    TEST1("reading data (attempt %d)", t);
+
+    if(client->Read() < 0)
+    {
+      FAIL();
+      return(-1);
+    }
+
+    PASS();
+    lp.Print();
+  }
+
+  TEST("unsubscribing");
+  if((lp.ChangeAccess(PLAYER_CLOSE_MODE,&access) < 0) ||
+     (access != PLAYER_CLOSE_MODE))
+  {
+    FAIL();
+    return -1;
+  }
+
+  PASS();
+
+  return(0);
+}
+
diff -pruN player-1.6.5/client_libs/libplayerc/bindings/python/playerc.i player-1.6.5-rfid/client_libs/libplayerc/bindings/python/playerc.i
--- player-1.6.5/client_libs/libplayerc/bindings/python/playerc.i	2005-04-22 06:37:59.000000000 +0200
+++ player-1.6.5-rfid/client_libs/libplayerc/bindings/python/playerc.i	2006-02-01 10:54:08.000000000 +0100
@@ -190,6 +190,19 @@
   }
 }
 
+// (@) rbrusu [--- RFID
+// Arrays of playerc_rfid_tag_t
+%typemap(out) playerc_rfid_tag_t [ANY]
+{
+  int i;
+  $result = PyTuple_New(arg1->tags_count);
+  for (i = 0; i < arg1->tags_count; i++) 
+  {
+    PyObject *o = SWIG_NewPointerObj($1 + i, SWIGTYPE_p_playerc_rfid_tag_t, 0);
+    PyTuple_SetItem($result,i,o);
+  }
+}
+// ---]
 
 // Provide thread-support on some functions
 %exception read
diff -pruN player-1.6.5/client_libs/libplayerc/dev_rfid.c player-1.6.5-rfid/client_libs/libplayerc/dev_rfid.c
--- player-1.6.5/client_libs/libplayerc/dev_rfid.c	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/client_libs/libplayerc/dev_rfid.c	2006-01-31 17:00:28.000000000 +0100
@@ -0,0 +1,107 @@
+/* 
+ *  libplayerc : a Player client library
+ *  Copyright (C) Andrew Howard 2002-2003
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) Andrew Howard 2003
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/***************************************************************************
+ * Desc: RFID reader proxy
+ * Author: Radu Bogdan Rusu
+ * Date: 31 January 2006
+ **************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "playerc.h"
+#include "error.h"
+
+
+// Create a new rfid proxy
+playerc_rfid_t *playerc_rfid_create(playerc_client_t *client, int index)
+{
+	playerc_rfid_t *device;
+	device = malloc(sizeof(playerc_rfid_t));
+	memset(device, 0, sizeof(playerc_rfid_t));
+	playerc_device_init(&device->info, client, PLAYER_RFID_CODE, index,
+					   (playerc_putdata_fn_t) playerc_rfid_putdata);
+
+  return device;
+}
+
+
+// Destroy a rfid proxy
+void playerc_rfid_destroy(playerc_rfid_t *device)
+{
+	playerc_device_term(&device->info);
+	free(device);
+}
+
+
+// Subscribe to the rfid device
+int playerc_rfid_subscribe(playerc_rfid_t *device, int access)
+{
+	return playerc_device_subscribe(&device->info, access);
+}
+
+
+// Un-subscribe from the rfid device
+int playerc_rfid_unsubscribe(playerc_rfid_t *device)
+{
+	return playerc_device_unsubscribe(&device->info);
+}
+
+// Process incoming data
+void playerc_rfid_putdata(playerc_rfid_t *device, player_msghdr_t *header,
+						  player_rfid_data_t *data, size_t len)
+{
+	int i, j;
+	
+	device->tags_count = ntohs(data->tags_count);
+	for (i = 0; i < device->tags_count; i++)
+	{
+		if (i >= PLAYERC_RFID_MAX_TAGS)
+			break;
+		device->tags[i].type = data->tags[i].type;
+		for (j = 0; j < PLAYERC_RFID_MAX_GUID; j++)
+			device->tags[i].guid[j] = data->tags[i].guid[j];
+	}
+	return;
+}
+
diff -pruN player-1.6.5/client_libs/libplayerc/Makefile.am player-1.6.5-rfid/client_libs/libplayerc/Makefile.am
--- player-1.6.5/client_libs/libplayerc/Makefile.am	2005-05-14 22:15:13.000000000 +0200
+++ player-1.6.5-rfid/client_libs/libplayerc/Makefile.am	2006-02-01 10:54:39.000000000 +0100
@@ -40,7 +40,10 @@ libplayerc_a_SOURCES = playerc.h \
 		       dev_dio.c \
 		       dev_simulation.c \
 		       dev_gripper.c \
-		       dev_speech.c
+		       dev_speech.c \
+		       dev_rfid.c
+# (@) rbrusu [--- RFID
+# ---]
 
 libplayerc_a_LIBADD = $(top_builddir)/replace/*.o
 
diff -pruN player-1.6.5/client_libs/libplayerc/playerc.h player-1.6.5-rfid/client_libs/libplayerc/playerc.h
--- player-1.6.5/client_libs/libplayerc/playerc.h	2005-04-22 06:43:22.000000000 +0200
+++ player-1.6.5-rfid/client_libs/libplayerc/playerc.h	2006-02-01 10:55:16.000000000 +0100
@@ -91,11 +91,13 @@ extern "C" {
 #define PLAYERC_FIDUCIAL_MAX_SAMPLES    PLAYER_FIDUCIAL_MAX_SAMPLES
 #define PLAYERC_SONAR_MAX_SAMPLES       PLAYER_SONAR_MAX_SAMPLES
 #define PLAYERC_BUMPER_MAX_SAMPLES      PLAYER_BUMPER_MAX_SAMPLES
-#define PLAYERC_IR_MAX_SAMPLES		      PLAYER_IR_MAX_SAMPLES
+#define PLAYERC_IR_MAX_SAMPLES		PLAYER_IR_MAX_SAMPLES
 #define PLAYERC_BLOBFINDER_MAX_BLOBS    PLAYER_BLOBFINDER_MAX_BLOBS
 #define PLAYERC_WIFI_MAX_LINKS          PLAYER_WIFI_MAX_LINKS
-
-  
+// (@) rbrusu [--- RFID
+#define PLAYERC_RFID_MAX_TAGS		PLAYER_RFID_MAX_TAGS
+#define PLAYERC_RFID_MAX_GUID		PLAYER_RFID_MAX_GUID
+// ---]
 
 /** @addtogroup player_clientlib_libplayerc libplayerc */
 /** @{ */
@@ -2120,6 +2122,57 @@ int playerc_speech_say (playerc_speech_t
 /** @} */
 /***************************************************************************/
 
+/**************************************************************************/
+/** @defgroup playerc_proxy_rfid rfid
+
+The rfid proxy provides an interface to the digital input/output sensors.
+
+@{
+*/
+
+// (@) rbrusu [--- RFID
+/** @brief Structure describing a single RFID tag. */
+typedef struct
+{
+    /** Tag type. */
+    uint8_t type;
+    /** The Globally Unique IDentifier (GUID) of the tag. */
+    uint8_t guid[PLAYERC_RFID_MAX_GUID];
+}  playerc_rfidtag_t;
+
+/** @brief RFID proxy data. */
+typedef struct
+{
+  /** Device info; must be at the start of all device structures. */
+  playerc_device_t info;
+
+  /** The number of RFID tags found. */
+  uint16_t tags_count;
+
+  /** The list of RFID tags. */
+  playerc_rfidtag_t tags[PLAYERC_RFID_MAX_TAGS];
+} playerc_rfid_t;
+
+
+/** @brief Create a rfid proxy. */
+playerc_rfid_t *playerc_rfid_create(playerc_client_t *client, int index);
+
+/** @brief Destroy a rfid proxy. */
+void playerc_rfid_destroy(playerc_rfid_t *device);
+
+/** @brief Subscribe to the rfid device. */
+int playerc_rfid_subscribe(playerc_rfid_t *device, int access);
+
+/** @brief Un-subscribe from the rfid device. */
+int playerc_rfid_unsubscribe(playerc_rfid_t *device);
+
+/** @brief @internal Parse data from incoming packet */
+void playerc_rfid_putdata(playerc_rfid_t *device, player_msghdr_t *header,
+					      player_rfid_data_t *data, size_t len);
+
+/** @} */
+/***************************************************************************/
+// ---]
 
 /**************************************************************************/
 /** @} (proxies) */
diff -pruN player-1.6.5/client_libs/libplayerc/test/Makefile.am player-1.6.5-rfid/client_libs/libplayerc/test/Makefile.am
--- player-1.6.5/client_libs/libplayerc/test/Makefile.am	2005-01-18 18:37:07.000000000 +0100
+++ player-1.6.5-rfid/client_libs/libplayerc/test/Makefile.am	2006-02-01 10:55:35.000000000 +0100
@@ -16,7 +16,7 @@ test_SOURCES = test.c \
                test_camera.c \
                test_fiducial.c \
                test_gps.c \
-							 test_joystick.c \
+		test_joystick.c \
                test_laser.c \
                test_localize.c \
                test_log.c \
@@ -29,7 +29,10 @@ test_SOURCES = test.c \
                test_ptz.c \
                test_sonar.c \
                test_truth.c \
-               test_wifi.c
+               test_wifi.c \
+	       test_rfid.c
+# (@) rbrusu [--- RFID
+# ---]
 
 clean-local:
 	rm -f test
diff -pruN player-1.6.5/client_libs/libplayerc/test/test.c player-1.6.5-rfid/client_libs/libplayerc/test/test.c
--- player-1.6.5/client_libs/libplayerc/test/test.c	2004-11-11 02:45:02.000000000 +0100
+++ player-1.6.5-rfid/client_libs/libplayerc/test/test.c	2006-02-01 10:55:54.000000000 +0100
@@ -179,7 +179,12 @@ int main(int argc, const char *argv[])
       case PLAYER_WIFI_CODE:
         test_wifi(client, client->devinfos[i].index);
         break;
-        
+// (@) rbrusu [--- RFID
+      // RFID device
+      case PLAYER_RFID_CODE:
+        test_rfid(client, client->devinfos[i].index);
+        break;
+// ---]
       default:
         printf("no test for interface [%s]\n",
                playerc_lookup_name(client->devinfos[i].code));
diff -pruN player-1.6.5/client_libs/libplayerc/test/test_rfid.c player-1.6.5-rfid/client_libs/libplayerc/test/test_rfid.c
--- player-1.6.5/client_libs/libplayerc/test/test_rfid.c	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/client_libs/libplayerc/test/test_rfid.c	2006-01-31 17:03:06.000000000 +0100
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * Desc: Tests for the RFID device
+ * Author: Radu Bogdan Rusu
+ * Date: 31 January 2006
+ **************************************************************************/
+
+#include "test.h"
+#include "playerc.h"
+
+// Basic RFID test
+int test_rfid(playerc_client_t *client, int index)
+{
+  int t, i, j;
+  void *rdevice;
+  playerc_rfid_t *device;
+
+  printf("device [rfid] index [%d]\n", index);
+
+  device = playerc_rfid_create(client, index);
+
+  TEST("subscribing (read)");
+  if (playerc_rfid_subscribe(device, PLAYER_READ_MODE) == 0)
+    PASS();
+  else
+    FAIL();
+
+  for (t = 0; t < 10; t++)
+  {
+    TEST1("reading data (attempt %d)", t);
+
+    do
+      rdevice = playerc_client_read(client);
+    while (rdevice == client);
+    
+    if (rdevice == device)
+    {
+      PASS();
+      printf("rfid tags count: [%d] \n", device->tags_count);
+      for (i = 0; i < device->tags_count; i++)
+      {
+        for (j = 0; j < PLAYERC_RFID_MAX_GUID; j++)
+    	    printf("[%2x] ", device->tags[i].guid[j]);
+        printf ("\n");
+      }
+      printf("\n");
+    }
+    else
+    {
+      FAIL();
+      break;
+    }
+  }
+  
+  TEST("unsubscribing");
+  if (playerc_rfid_unsubscribe(device) == 0)
+    PASS();
+  else
+    FAIL();
+  
+  playerc_rfid_destroy(device);
+  
+  return 0;
+}
diff -pruN player-1.6.5/client_libs/libplayerc/utils.c player-1.6.5-rfid/client_libs/libplayerc/utils.c
--- player-1.6.5/client_libs/libplayerc/utils.c	2004-11-11 02:45:02.000000000 +0100
+++ player-1.6.5-rfid/client_libs/libplayerc/utils.c	2006-02-01 10:56:15.000000000 +0100
@@ -98,7 +98,10 @@ const char *playerc_lookup_name(int code
       return PLAYER_MAP_STRING;
     case PLAYER_LOG_CODE:
       return PLAYER_LOG_STRING;
-	
+// (@) rbrusu [--- RFID
+    case PLAYER_RFID_CODE:
+      return PLAYER_RFID_STRING;
+// ---]	
     default:
       break;
   }
@@ -153,6 +156,10 @@ int playerc_lookup_code(const char *name
     return PLAYER_MAP_CODE;
   if (strcmp(name, PLAYER_LOG_STRING) == 0)
     return PLAYER_LOG_CODE;
+// (@) rbrusu [--- RFID
+  if (strcmp(name, PLAYER_RFID_STRING) == 0)
+    return PLAYER_RFID_CODE;
+// ---]
   return -1;
 }
 
diff -pruN player-1.6.5/config/rfid.cfg player-1.6.5-rfid/config/rfid.cfg
--- player-1.6.5/config/rfid.cfg	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/config/rfid.cfg	2006-02-01 10:47:38.000000000 +0100
@@ -0,0 +1,19 @@
+# Example configuration file for:
+
+# Inside Contactless M300/R300 2G RFID reader
+driver
+(
+  name "insideM300"
+  provides ["rfid:0"]
+  port "/dev/ttyS0"
+  speed 9600
+)
+
+# Skyetek M1/M1-mini RFID reader
+driver
+(
+  name "skyetekM1"
+  provides ["rfid:1"]
+  port "/dev/ttyS1"
+  speed 9600
+)
diff -pruN player-1.6.5/configure.in player-1.6.5-rfid/configure.in
--- player-1.6.5/configure.in	2005-07-29 02:59:17.000000000 +0200
+++ player-1.6.5-rfid/configure.in	2006-02-01 10:37:48.000000000 +0100
@@ -312,6 +312,9 @@ AC_OUTPUT(Makefile
           server/drivers/localization/amcl/map/Makefile
           server/drivers/localization/amcl/models/Makefile
           server/drivers/service_adv/Makefile
+dnl (@) rbrusu [--- RFID
+          server/drivers/rfid/Makefile
+dnl ---]
 dnl DEPRECATED          server/drivers/blobfinder/shapetracker/Makefile
           server/drivers/map/Makefile
           server/drivers/joystick/Makefile 
diff -pruN player-1.6.5/server/deviceregistry.cc player-1.6.5-rfid/server/deviceregistry.cc
--- player-1.6.5/server/deviceregistry.cc	2005-04-05 06:18:30.000000000 +0200
+++ player-1.6.5-rfid/server/deviceregistry.cc	2006-02-01 10:37:00.000000000 +0100
@@ -368,6 +368,14 @@ void NomadSonar_Register(DriverTable *dr
 //void NomadSpeech_Register(DriverTable *driverTable);
 #endif
 
+// (@) rbrusu [--- RFID
+#ifdef INCLUDE_INSIDEM300
+void InsideM300_Register (DriverTable* table);
+#endif
+#ifdef INCLUDE_SKYETEKM1
+void SkyetekM1_Register (DriverTable* table);
+#endif
+// ---]
 
 /* this array lists the interfaces that Player knows how to load
  *
@@ -417,6 +425,9 @@ player_interface_t interfaces[] = {
   {PLAYER_JOYSTICK_CODE, PLAYER_JOYSTICK_STRING},
   {PLAYER_SPEECH_RECOGNITION_CODE, PLAYER_SPEECH_RECOGNITION_STRING},
   {PLAYER_OPAQUE_CODE, PLAYER_OPAQUE_STRING},
+// (@) rbrusu [--- RFID
+  {PLAYER_RFID_CODE, PLAYER_RFID_STRING},
+// ---]
   {0,NULL}
 };
 
@@ -813,4 +824,13 @@ register_devices()
   //StgEnergy_Register(driverTable);
   //StgBlinkenlight_Register(driverTable);
 #endif
+
+// (@) rbrusu [--- RFID
+#ifdef INCLUDE_INSIDEM300
+  InsideM300_Register (driverTable);
+#endif
+#ifdef INCLUDE_SKYETEKM1
+  SkyetekM1_Register (driverTable);
+#endif
+// ---]
 }
diff -pruN player-1.6.5/server/drivers/Makefile.am player-1.6.5-rfid/server/drivers/Makefile.am
--- player-1.6.5/server/drivers/Makefile.am	2004-09-16 07:19:55.000000000 +0200
+++ player-1.6.5-rfid/server/drivers/Makefile.am	2006-02-01 10:38:31.000000000 +0100
@@ -21,4 +21,10 @@ shell \
 speech \
 stage \
 waveform \
-wifi 
+wifi \
+rfid
+# (@) rbrusu [--- RFID
+# Old: wifi
+# New: wifi \
+#      rfid
+# ---]
diff -pruN player-1.6.5/server/drivers/rfid/insideM300.cc player-1.6.5-rfid/server/drivers/rfid/insideM300.cc
--- player-1.6.5/server/drivers/rfid/insideM300.cc	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/server/drivers/rfid/insideM300.cc	2006-01-31 14:47:39.000000000 +0100
@@ -0,0 +1,726 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2000
+ *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+/*
+ Desc: Driver for the INSIDE M-300/R-300 2G RFID reader
+ Author: Radu Bogdan Rusu
+ Date: 25 Jan 2006
+ CVS: $Id: insideM300.cc,v 1.00 2006/01/25 14:50:01 rusu Exp $
+*/
+
+/** @addtogroup drivers Drivers */
+/** @{ */
+/** @defgroup player_driver_insideM300 insideM300
+
+The insideM300 driver controls the Inside Contactless M300/R300 2G RFID reader (13.56Mhz). 
+Currently, only ISO 15693 tags are supported.
+
+@par Compile-time dependencies
+
+- none
+
+@par Provides
+
+- @ref player_interface_rfid
+
+@par Requires
+
+- none
+
+@par Configuration requests
+
+- PLAYER_RFID_GET_GEOM
+- PLAYER_RFID_GET_CONFIG
+  
+@par Configuration file options
+
+- port (string)
+  - Default: "/dev/ttyS0"
+  - Serial port to which the Inside M300/R300 2G reader is attached.  If you are using a
+    USB/232 or USB/422 converter, this will be "/dev/ttyUSBx".
+
+- rate (integer)
+  - Default: 9600
+  - Baud rate. Valid values are 9600, 19600, 38400, 57600 and 115200.
+
+@par Example 
+
+@verbatim
+driver
+(
+  name "insideM300"
+  provides ["rfid:0"]
+  port "/dev/ttyS0"
+  rate "57600"
+)
+@endverbatim
+
+@par Authors
+
+Radu Bogdan Rusu
+
+*/
+/** @} */
+  
+
+  
+#if HAVE_CONFIG_H
+  #include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+#include <netinet/in.h>  /* for struct sockaddr_in, htons(3) */
+#include <sys/ioctl.h>
+
+#include "playertime.h"
+#include "playercommon.h"
+#include "drivertable.h"
+#include "driver.h"
+#include "error.h"
+#include "player.h"
+extern PlayerTime* GlobalTime;
+
+#define DEFAULT_RFID_PORT "/dev/ttyS0"
+#define DEFAULT_RFID_RATE 9600
+
+// ISO 7816-4 command set format
+#define CMD_CLASS 0
+#define CMD_INSTR 1
+#define CMD_P1_P  2
+#define CMD_P2_P  3
+#define CMD_P3_P  4
+
+// T=0 protocol direction
+#define ISO_NONE   0x00
+#define ISO_IN     0x01
+#define ISO_OUT    0x02
+#define ISO_IN_OUT 0x03
+
+// STATUS DEFINITION
+#define STATUS_OK                  0x9000
+#define RESET_EEPROM_SUCCESFUL     0x3B00
+#define P3_INCORRECT               0x6700
+#define P1_P2_INCORRECT            0x6B00
+#define CLASS_NOT_RECOGNIZED       0x6E00
+#define INSTRUCTION_NOT_RECOGNIZED 0x6D00
+#define CARD_NOT_IDENTIFIED        0x6982
+#define COMMAND_FLOW_INCORRECT     0x9835
+#define CARD_NOT_FOUND             0x6A82
+#define EEPROM_RERROR              0x6200
+
+// The InsideM300 device class.
+class InsideM300 : public Driver
+{
+	public:
+		// Constructor
+		InsideM300 (ConfigFile* cf, int section);
+
+		int Setup ();
+		int Shutdown ();
+
+	private:
+
+		// Main function for device thread.
+		virtual void Main  ();
+		void CheckConfig   ();
+		void CheckCommands ();
+		void RefreshData   ();
+		
+		// Port file descriptor
+		int                fd;
+		// Initial serial port attributes
+		struct termios     initial_options;
+
+		// RFID interface
+		player_device_id_t rfid_id;
+		player_rfid_data_t rfid_data;
+		player_rfid_cmd_t  rfid_cmd;
+		
+		const char*        portName;
+		int                portSpeed;
+		
+		// 0=select just a single tag (no anticollision)
+		// 1=select all tags in the RFID field (anticollision)
+		int                selectTagMultiple;
+
+		// Inside functions
+		int           CouplerSynchronize ();
+		void          WriteByte          (unsigned char byte);
+		unsigned char ReadByte           ();
+		unsigned int  ReadStatusWord     ();
+		int           SelectTags ();
+		unsigned int  SendISOCommand     (unsigned char typeISO, int dataOutLen,
+										  unsigned char commandType, unsigned char p1,
+										  unsigned char p2, unsigned char p3,
+										  unsigned char *dataIn, unsigned char *dataOut);
+		unsigned int  IsoExchange (unsigned char typeISO, unsigned char *ISOCommand,
+								   int dataInLen, unsigned char *dataIn,
+								   int dataOutLen, unsigned char *dataOut);
+		void InsideInventory (int maskLength, int chipMask, unsigned char *globalChipAnswer);
+		unsigned int ResetField ();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// a factory creation function
+Driver* InsideM300_Init (ConfigFile* cf, int section)
+{
+	// Create and return a new instance of this driver
+	return ((Driver*)(new InsideM300 (cf, section)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// a driver registration function
+void InsideM300_Register (DriverTable* table)
+{
+	table->AddDriver ("insideM300", InsideM300_Init);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor
+InsideM300::InsideM300 (ConfigFile* cf, int section)
+	: Driver (cf, section)
+{
+	if (cf->ReadDeviceId(&(this->rfid_id), section, "provides",
+		PLAYER_RFID_CODE, -1, NULL) == 0)
+	{
+		if (this->AddInterface(this->rfid_id, PLAYER_ALL_MODE,
+			sizeof(player_rfid_data_t), 0, 1, 1) != 0)
+		{
+			this->SetError(-1);
+			return;
+		}
+	}
+
+	
+	this->portName  = cf->ReadString (section, "port", DEFAULT_RFID_PORT);
+	this->portSpeed = cf->ReadInt (section, "speed", DEFAULT_RFID_RATE);
+	
+	// Enable the anticollision mode
+	this->selectTagMultiple = 1;
+	
+	return;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Set up the device
+int InsideM300::Setup ()
+{
+	unsigned int status;
+	unsigned char chipAnswer[24];
+	unsigned char ISOCommand[4];
+	
+	// Open serial port
+	this->fd = open (this->portName, O_RDWR | O_NOCTTY);
+	if (this->fd < 0)
+	{
+		PLAYER_ERROR2 ("> Connecting to Inside M300/R300 on [%s]; [%s]...[failed!]",
+					   (char*) this->portName, strerror (errno));
+		return (-1);
+	}
+	PLAYER_MSG0 (1, "> Connecting to Inside M300/R300...[done]");
+
+	// Change port settings
+	struct termios options;
+/*
+	tcflag_t c_iflag;		// input mode flags
+	tcflag_t c_oflag;		// output mode flags
+	tcflag_t c_cflag;		// control mode flags
+	tcflag_t c_lflag;		// local mode flags
+	cc_t c_line;			// line discipline
+	cc_t c_cc[NCCS];		// control characters
+*/
+	bzero (&options, sizeof (options)); // clear the struct for new port settings
+	
+	// Get the current port settings
+	if (tcgetattr (this->fd, &options) != 0) {
+		PLAYER_ERROR (">> Unable to get serial port attributes !");
+		return (-1);
+	}
+	tcgetattr (this->fd, &this->initial_options);
+	
+	// turn off break sig, cr->nl, parity off, 8 bit strip, flow control
+	options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+
+	// turn off echo, canonical mode, extended processing, signals
+	options.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG);
+
+	options.c_cflag |= (CSTOPB);    // use two stop bits
+	options.c_cflag |= (PARENB);    // generate parity bits (if PARODD not set, even parity)
+	options.c_cflag &= ~(CSIZE );   // clear size
+	options.c_cflag |= (CS8);       // set bit size (default is 8)
+	options.c_oflag &= ~(OPOST);    // turn output processing off
+
+	// read will be satisfied if a single character is read, or TIME is exceeded (t = TIME *0.1 s)
+	options.c_cc[VTIME] = 1;
+	options.c_cc[VMIN] = 0;
+
+	// Set the baudrate to the given portSpeed
+	cfsetispeed (&options, this->portSpeed);
+	cfsetospeed (&options, this->portSpeed);
+	
+	// Activate the settings for the port
+	if (tcsetattr (this->fd, TCSAFLUSH, &options) < 0)
+	{
+		PLAYER_ERROR (">> Unable to set serial port attributes !");
+		return (-1);
+	}
+
+	// Make sure queues are empty before we begin
+	tcflush (this->fd, TCIOFLUSH);
+
+	// Synchronizing buffer
+	int result = CouplerSynchronize ();
+	if (result != 0) {
+		PLAYER_ERROR (">> Unable to synchronize with the reader !");
+		return (-1);
+	}
+	
+	// Get the current port settings
+	if (tcgetattr (this->fd, &options) != 0) {
+		PLAYER_ERROR (">> Unable to get serial port attributes !");
+		return (-1);
+	}
+	// read will be satisfied if a single character is read, or TIME is exceeded (t = TIME *0.1 s)
+	options.c_cc[VTIME] = 1;
+	options.c_cc[VMIN] = 1;
+	// Activate the settings for the port
+	if (tcsetattr (this->fd, TCSANOW, &options) !=0 )
+	{
+		PLAYER_ERROR (">> Unable to set serial port attributes !");
+		return (-1);
+	}
+
+	ISOCommand[0] = 0x21;
+	// 0xF4 = SET_STATUS
+	status = SendISOCommand (ISO_IN, 0, 0xF4, 0x03, 0x5E, 0x01, ISOCommand, chipAnswer);
+	if (status != STATUS_OK)
+		PLAYER_WARN1 (">> Error 0x%x while sending ISO command (F4035E0121) !", status);
+	
+	ISOCommand[0] = 0x31;
+	// 0xF4 = SET_STATUS
+	status = SendISOCommand (ISO_IN, 0, 0xF4, 0x03, 0x5F, 0x01, ISOCommand, chipAnswer);
+	if (status != STATUS_OK)
+		PLAYER_WARN1 (">> Error 0x%x while sending ISO command (F4035F0131) !", status);
+	
+	ISOCommand[0] = 0x3B;
+	// 0xF4 = SET_STATUS
+	status = SendISOCommand (ISO_IN, 0, 0xF4, 0x03, 0x6B, 0x01, ISOCommand, chipAnswer);
+	if (status != STATUS_OK)
+		PLAYER_WARN1 (">> Error 0x%x while sending ISO command (F4036B013B) !", status);
+
+	status = ResetField ();
+	if (status != STATUS_OK)
+		PLAYER_WARN1 (">> Error 0x%x while resetting field !", status);
+	
+	// Start the device thread
+	StartThread ();
+
+	return (0);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Shutdown the device
+int InsideM300::Shutdown ()
+{
+	// Stop the driver thread
+	StopThread ();
+
+	// Close the serial port
+	tcsetattr (this->fd, TCSANOW, &this->initial_options);
+	close (this->fd);
+	
+	PLAYER_MSG0 (1, "> InsideM300 driver shutting down... [done]");
+	return (0);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Main function for device thread
+void InsideM300::Main () 
+{
+	// Zero data
+	memset (&this->rfid_data, 0, sizeof (this->rfid_data));
+	
+	timespec sleepTime = {0, 0};
+	
+	// The main loop; interact with the device here
+	while (true)
+	{
+		// test if we are supposed to cancel
+		pthread_testcancel ();
+		
+		// Check for and handle configuration requests, using Driver::GetConfig ()
+		this->CheckConfig ();
+		
+		// Check for and execute commands, using Driver::GetCommand()
+		this->CheckCommands ();
+		
+		// Interact with the device, and push out the resulting data, using
+		// Driver::PutData()
+		this->RefreshData ();
+		
+		nanosleep (&sleepTime, NULL);
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CheckConfig function
+void InsideM300::CheckConfig ()
+{
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CheckCommands function
+void InsideM300::CheckCommands ()
+{
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RefreshData function
+void InsideM300::RefreshData ()
+{
+	memset (&this->rfid_data, 0, sizeof (this->rfid_data));
+	
+	// Get the time at which we started reading
+	// This will be a pretty good estimate of when the phenomena occured
+	struct timeval time;
+	GlobalTime->GetTime(&time);
+	
+	// Anticollision mode
+	SelectTags ();
+
+	this->rfid_data.tags_count = htons (this->rfid_data.tags_count);
+
+	// Write the RFID data
+	PutData (this->rfid_id, &this->rfid_data, sizeof (this->rfid_data), &time);
+	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WriteByte function
+void InsideM300::WriteByte (unsigned char buf)
+{
+	int wresult;
+	wresult = write (this->fd, &buf, 1);
+	if (wresult < 0)
+		PLAYER_WARN (">> Error while writing 1 byte !");
+}	
+
+////////////////////////////////////////////////////////////////////////////////
+// ReadByte function
+unsigned char InsideM300::ReadByte ()
+{
+	unsigned char buf;
+	int bresult = read (this->fd, &buf, 1);
+	if (bresult == 0)
+		return (0);
+	return buf;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReadStatusWord function
+unsigned int InsideM300::ReadStatusWord ()
+{
+	unsigned int status;
+
+	status  = (ReadByte () << 8);
+	status |=  ReadByte ();
+
+	return status;
+}
+////////////////////////////////////////////////////////////////////////////////
+// CouplerSynchronize function
+// Return 0 if synchronization succeeded, -1 otherwise.
+int InsideM300::CouplerSynchronize ()
+{
+	unsigned int status = 0;
+	int          i;
+
+	// try a couple of times (12 attempts) to synchronize with the coupler
+	for (i = 0; i < 7; i++)
+	{
+		WriteByte (0x00);              // send 0x00 to the coupler
+		status = ReadStatusWord ();    // read the status word
+
+		// check to see if the status word matches one of the known error codes
+		if ((status == P1_P2_INCORRECT)            ||
+			(status == INSTRUCTION_NOT_RECOGNIZED) ||
+			(status == CLASS_NOT_RECOGNIZED)       ||
+			(status == COMMAND_FLOW_INCORRECT)     ||
+			(status == CARD_NOT_FOUND))
+			return (0);                // synchronization succeeded
+	} 
+
+	return (-1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SendISOCommand
+unsigned int InsideM300::SendISOCommand (unsigned char typeISO, int dataOutLen,
+										 unsigned char commandType, unsigned char p1,
+										 unsigned char p2, unsigned char p3,
+										 unsigned char *dataIn, unsigned char *dataOut)
+{
+	unsigned char ISOCommand[5];
+	int           dataInLen = 0;
+
+	if ((typeISO == ISO_IN) || (typeISO == ISO_IN_OUT)) 
+		dataInLen = p3;
+
+	// Prepare the command
+	ISOCommand[CMD_CLASS] = 0x80;           // command class
+	ISOCommand[CMD_INSTR] = commandType;    // command type
+	ISOCommand[CMD_P1_P]  = p1;
+	ISOCommand[CMD_P2_P]  = p2;
+	ISOCommand[CMD_P3_P]  = p3;
+
+	// Send ISO Command
+	return (IsoExchange (typeISO, ISOCommand, dataInLen, dataIn, dataOutLen, dataOut));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IsoExchange
+unsigned int InsideM300::IsoExchange (unsigned char typeISO, unsigned char *ISOCommand,
+									  int dataInLen, unsigned char *dataIn,
+									  int dataOutLen, unsigned char *dataOut)
+{
+	// Local variable declaration
+	unsigned char ACK;
+	unsigned int  status;
+
+	int i; //for counter
+
+	// Send command
+	WriteByte (ISOCommand[CMD_CLASS]);
+	//printf ("Writing .%x", p_abCommand[CMD_CLASS]);
+	WriteByte (ISOCommand[CMD_INSTR]);
+	//printf (".%x", p_abCommand[CMD_INSTR]);
+	WriteByte (ISOCommand[CMD_P1_P]);
+	//printf (".%x", p_abCommand[CMD_P1_P]);
+	WriteByte (ISOCommand[CMD_P2_P]);
+	//printf (".%x", p_abCommand[CMD_P2_P]);
+	WriteByte (ISOCommand[CMD_P3_P]);
+	//printf (".%x [5 bytes]\n", p_abCommand[CMD_P3_P]);
+
+	switch (typeISO)
+	{
+		case ISO_NONE :                     // Neither data sent nor received
+			return ReadStatusWord ();
+
+		case ISO_IN :
+		// Verify ACK
+			ACK = ReadByte ();
+			if (ACK != ISOCommand[CMD_INSTR])
+			{
+				status = (ACK<<8);
+				status = status | ReadByte ();
+				return status;
+			}
+			for (i = 0; i < dataInLen ; i++)
+			{
+				WriteByte (dataIn[i]);      // Send buffer data
+			}
+			return ReadStatusWord ();
+
+		case ISO_OUT :
+		// Verify ACK
+			ACK = ReadByte ();
+			if (ACK != ISOCommand[CMD_INSTR])
+			{
+				status  = (ACK << 8);
+				status |= ReadByte ();
+				return status;
+			}
+			for (i = 0; i < dataOutLen; i++)
+				dataOut[i] = ReadByte ();   // Grab buffer data
+			return ReadStatusWord ();
+
+		case ISO_IN_OUT :
+		// Verify ACK
+			ACK = ReadByte ();
+			if (ACK != ISOCommand[CMD_INSTR])
+			{
+				status = (ACK<<8);
+				status = status | ReadByte ();
+				return status;
+			}
+			for (i = 0; i < dataInLen ; i++)
+				WriteByte (dataIn[i]);      // Send buffer data in
+		// Verify ACK
+			ACK = ReadByte ();
+			if (ACK != ISOCommand[CMD_INSTR])
+			{
+				status = (ACK<<8);
+				status = status | ReadByte ();
+				return status;
+			}
+			for (i = 0; i < dataOutLen; i++)
+				dataOut[i] = ReadByte ();   // Grab buffer data out
+			return ReadStatusWord();
+		default: 
+			return (0);
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReadMultipleTags function
+int InsideM300::SelectTags ()
+{
+	unsigned int  status, iStatus;
+	unsigned char chipAnswer[24], globalChipAnswer[24];
+	unsigned char ISOCommand[10];
+	int           chipMask;
+	
+	status = ResetField ();
+	if (status != STATUS_OK)
+		PLAYER_WARN1 (">> Error 0x%x while resetting field !", status);
+	
+	ISOCommand[0] = 0x36; ISOCommand[1] = 0x01;
+	ISOCommand[2] = 0x00; ISOCommand[3] = 0x00;
+	// 0xC2 = TRANSMIT - Basic inventory command
+	iStatus = SendISOCommand (ISO_IN, 0, 0xC2, 0xF3, 0x0A, 0x04, ISOCommand, chipAnswer);
+	
+	int tagsFound = 1;
+	while (tagsFound != 0) {
+		
+		ISOCommand[0] = 0x00;
+		// 0xC0 = GET_RESPONSE - get chip UID
+		status = SendISOCommand (ISO_OUT, 10, 0xC0, 0x00, 0x00, 0x0A, ISOCommand, chipAnswer);
+		chipMask = chipAnswer[2];
+		
+		switch (iStatus) {
+			case STATUS_OK:
+			{
+				this->rfid_data.tags[this->rfid_data.tags_count].type = chipAnswer[1];
+				int j;
+				for (j = 0; j < 8; j++)
+					this->rfid_data.tags[this->rfid_data.tags_count].guid[j] = chipAnswer [9-j];
+				this->rfid_data.tags_count++;
+			
+				tagsFound = 0;
+				break;
+			}
+			case CARD_NOT_IDENTIFIED:
+			{
+				InsideInventory (1, chipMask, globalChipAnswer);
+			
+				bzero (&ISOCommand, sizeof (ISOCommand));
+				int k;
+				for (k = 2; k < 10; k++)
+					ISOCommand[k] = globalChipAnswer[k-2];
+			
+				ISOCommand[0] = 0x20; ISOCommand[1] = 0x02;
+				// 0xC2 = TRANSMIT (Note: get Chip Answer)
+				status = SendISOCommand (ISO_IN, 0, 0xC2, 0xB3, 0x00, 0x0A, ISOCommand, chipAnswer);
+			
+				bzero (&ISOCommand, sizeof (ISOCommand));
+				ISOCommand[0] = 0x36; ISOCommand[1] = 0x01;
+				ISOCommand[2] = 0x00; ISOCommand[3] = 0x00;
+				// 0xC2 = TRANSMIT (Note: get Chip Answer)
+				iStatus = SendISOCommand (ISO_IN, 0, 0xC2, 0xF3, 0x0A, 0x04, ISOCommand, chipAnswer);
+				break;
+			}
+			default:
+			{
+				tagsFound = 0;
+				break;
+			}
+		}
+	}
+	return (0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// InsideInventory function
+void InsideM300::InsideInventory (int maskLength, int chipMask, unsigned char *globalChipAnswer)
+{
+	unsigned int  status, iStatus;
+	unsigned char ISOCommand[5];
+	unsigned char chipAnswer[24];
+	int i;
+	
+	if (maskLength > 15)
+		return;
+	
+	ISOCommand[0] = 0x36; ISOCommand[1] = 0x01;
+	ISOCommand[2] = 0x00; ISOCommand[3] = 0x00 + maskLength;
+	ISOCommand[4] = 0x00 + chipMask;
+	
+	// Masked Inventory command
+	iStatus = SendISOCommand (ISO_IN, 0, 0xC2, 0xF3, 0x0A, 0x05, ISOCommand, chipAnswer);
+	// Get UID
+	status  = SendISOCommand (ISO_OUT, 10, 0xC0, 0x00, 0x00, 0x0A, NULL, chipAnswer);
+
+	chipMask = chipAnswer[2];
+
+	switch (iStatus)
+	{
+		case STATUS_OK:
+		{
+			for (i = 0; i < 8; i++)
+				globalChipAnswer[i] = chipAnswer[i+2];
+			
+			this->rfid_data.tags[this->rfid_data.tags_count].type = chipAnswer[1];
+			int j;
+			for (j = 0; j < 8; j++)
+				this->rfid_data.tags[this->rfid_data.tags_count].guid[j] = chipAnswer [9-j];
+			this->rfid_data.tags_count++;
+			
+			break;
+		}
+		case CARD_NOT_IDENTIFIED:
+		{
+			InsideInventory (maskLength + 1, chipMask, globalChipAnswer);
+			break;
+		}
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ResetField function
+unsigned int InsideM300::ResetField ()
+{
+	unsigned char ISOCommand[5];
+	unsigned char dataIn[2] = {0x00, 0x00}; // Data in initialisation
+
+	// Prepare the command
+	ISOCommand[CMD_CLASS] = 0x80;
+	ISOCommand[CMD_INSTR] = 0xF4;
+	ISOCommand[CMD_P1_P]  = 0x40;
+	ISOCommand[CMD_P2_P]  = 0x00;
+	ISOCommand[CMD_P3_P]  = 0x01;
+
+	// Send ISO Command
+	return (IsoExchange (ISO_IN, ISOCommand, 1, dataIn, 0, NULL));
+}
diff -pruN player-1.6.5/server/drivers/rfid/Makefile.am player-1.6.5-rfid/server/drivers/rfid/Makefile.am
--- player-1.6.5/server/drivers/rfid/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/server/drivers/rfid/Makefile.am	2006-01-27 16:11:36.000000000 +0100
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = @INSIDEM300_LIB@ @SKYETEKM1_LIB@ 
+
+AM_CPPFLAGS = -Wall -I$(top_srcdir)/server
+
+EXTRA_LIBRARIES = libinsideM300.a libskyetekM1.a
+
+libinsideM300_a_SOURCES = insideM300.cc
+libskyetekM1_a_SOURCES = skyetekM1.cc
+
diff -pruN player-1.6.5/server/drivers/rfid/skyetekM1.cc player-1.6.5-rfid/server/drivers/rfid/skyetekM1.cc
--- player-1.6.5/server/drivers/rfid/skyetekM1.cc	1970-01-01 01:00:00.000000000 +0100
+++ player-1.6.5-rfid/server/drivers/rfid/skyetekM1.cc	2006-01-31 16:59:53.000000000 +0100
@@ -0,0 +1,592 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2000  
+ *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+/*
+ Desc: Driver for the SkyeTek M1/M1-mini RFID readers
+ Author: Radu Bogdan Rusu
+ Date: 27 Jan 2006
+ CVS: $Id: skyetekM1.cc,v 1.00 2006/01/27 16:08:00 rusu Exp $
+*/
+
+/** @addtogroup drivers Drivers */
+/** @{ */
+/** @defgroup player_driver_skyetekM1 skyetekM1
+
+The skyetekM1 driver controls the SkyeTek M1/M1-mini RFID readers (13.56Mhz). 
+Currently, only ISO 15693 tags are supported.
+
+@par Compile-time dependencies
+
+- none
+
+@par Provides
+
+- @ref player_interface_rfid
+
+@par Requires
+
+- none
+
+@par Configuration requests
+
+- PLAYER_RFID_GET_GEOM
+
+@par Configuration file options
+
+- port (string)
+  - Default: "/dev/ttyS0"
+  - Serial port to which the SkyeTek M1/M1-mini reader is attached.  If you are using a
+    USB/232 or USB/422 converter, this will be "/dev/ttyUSBx".
+
+- rate (integer)
+  - Default: 9600
+  - Baud rate. Valid values are 9600, 19600, 38400, 57600 and 115200.
+
+@par Example 
+
+@verbatim
+driver
+(
+  name "skyetekM1"
+  provides ["rfid:0"]
+  port "/dev/ttyS0"
+  rate "9600"
+)
+@endverbatim
+
+@par Authors
+
+Radu Bogdan Rusu
+
+*/
+/** @} */
+
+
+#if HAVE_CONFIG_H
+  #include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <netinet/in.h>  /* for struct sockaddr_in, htons(3) */
+
+#include "playertime.h"
+#include "playercommon.h"
+#include "drivertable.h"
+#include "driver.h"
+#include "error.h"
+#include "player.h"
+extern PlayerTime* GlobalTime;
+
+#define DEFAULT_RFID_PORT "/dev/ttyS0"
+#define DEFAULT_RFID_RATE 9600
+
+// Flag Fields
+#define RID_F                  0x80
+#define TID_F                  0x40
+#define CRC_F                  0x20
+#define AFI_F                  0x10
+#define RF_F                   0x08
+#define LOCK_F                 0x04
+#define INV_F                  0x02
+#define LOOP_F                 0x01
+
+// The SkyetekM1 device class.
+class SkyetekM1 : public Driver
+{
+	public:
+		// Constructor
+		SkyetekM1 (ConfigFile* cf, int section);
+
+		int Setup ();
+		int Shutdown ();
+
+	private:
+
+		// Main function for device thread.
+		virtual void Main  ();
+		void CheckConfig   ();
+		void CheckCommands ();
+		void RefreshData   ();
+		
+		// Port file descriptor
+		int                fd;
+		// Initial serial port attributes
+		struct termios     initial_options;
+
+		// RFID interface
+		player_device_id_t rfid_id;
+		player_rfid_data_t rfid_data;
+		player_rfid_cmd_t  rfid_cmd;
+		
+		const char*        portName;
+		int                portSpeed;
+		
+		// 0=select just a single tag (no anticollision)
+		// 1=select all tags in the RFID field (anticollision)
+		int                selectTagMultiple;
+
+		// Inside functions
+		unsigned int  CRC16       (unsigned char *dataP, unsigned char n);
+		unsigned char VerifyCRC   (unsigned char *resp);
+		void WriteSerial (unsigned char *mdmData, unsigned char commandLen);
+		int  ReadSerial  (unsigned char *mdmData, unsigned char commandLen);
+		int  S_ReadWrite (unsigned char *mdmData, unsigned char length, 
+						  unsigned char *response);
+		void SelectTags  ();
+		unsigned char Wake  ();
+		unsigned char Sleep ();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// a factory creation function
+Driver* SkyetekM1_Init (ConfigFile* cf, int section)
+{
+	// Create and return a new instance of this driver
+	return ((Driver*)(new SkyetekM1 (cf, section)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// a driver registration function
+void SkyetekM1_Register (DriverTable* table)
+{
+	table->AddDriver ("skyetekM1", SkyetekM1_Init);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor
+SkyetekM1::SkyetekM1 (ConfigFile* cf, int section)
+	: Driver (cf, section)
+{
+	if (cf->ReadDeviceId(&(this->rfid_id), section, "provides",
+		PLAYER_RFID_CODE, -1, NULL) == 0)
+	{
+		if (this->AddInterface(this->rfid_id, PLAYER_ALL_MODE,
+			sizeof(player_rfid_data_t), 0, 1, 1) != 0)
+		{
+			this->SetError(-1);
+			return;
+		}
+	}
+
+	
+	this->portName  = cf->ReadString (section, "port", DEFAULT_RFID_PORT);
+	this->portSpeed = cf->ReadInt (section, "speed", DEFAULT_RFID_RATE);
+	
+	// Enable the anticollision mode
+	this->selectTagMultiple = 1;
+	
+	return;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Set up the device
+int SkyetekM1::Setup ()
+{
+	
+	// Open serial port
+	this->fd = open (this->portName, O_RDWR);
+	if (this->fd < 0)
+	{
+		PLAYER_ERROR2 ("> Connecting to Skyetek M1 on [%s]; [%s]...[failed!]",
+					   (char*) this->portName, strerror (errno));
+		return (-1);
+	}
+	PLAYER_MSG0 (1, "> Connecting to Skyetek M1...[done]");
+
+	// Change port settings
+	struct termios options;
+/*
+	tcflag_t c_iflag;		// input mode flags
+	tcflag_t c_oflag;		// output mode flags
+	tcflag_t c_cflag;		// control mode flags
+	tcflag_t c_lflag;		// local mode flags
+	cc_t c_line;			// line discipline
+	cc_t c_cc[NCCS];		// control characters
+*/
+	bzero (&options, sizeof (options)); // clear the struct for new port settings
+	
+	// Get the current port settings
+	if (tcgetattr (this->fd, &options) != 0) {
+		PLAYER_ERROR (">> Unable to get serial port attributes !");
+		return (-1);
+	}
+	tcgetattr (this->fd, &this->initial_options);
+	
+	// turn off break sig, cr->nl, parity off, 8 bit strip, flow control
+	options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+
+	// turn off echo, canonical mode, extended processing, signals
+	options.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG);
+
+	options.c_cflag &= ~(CSTOPB);   // use one stop bit
+	options.c_cflag &= ~(PARENB);   // no parity (if PARODD not set, even parity)
+	options.c_cflag &= ~(CSIZE );   // clear size
+	options.c_cflag |= (CS8);       // set bit size (default is 8)
+	options.c_oflag &= ~(OPOST);    // turn output processing off
+
+	// read will be satisfied if a single character is read, or TIME is exceeded (t = TIME *0.1 s)
+	options.c_cc[VTIME] = 10;
+	options.c_cc[VMIN] = 0;
+
+	// Set the baudrate to the given portSpeed
+	cfsetispeed (&options, this->portSpeed);
+	cfsetospeed (&options, this->portSpeed);
+	
+	// Activate the settings for the port
+	if (tcsetattr (this->fd, TCSAFLUSH, &options) < 0)
+	{
+		PLAYER_ERROR (">> Unable to set serial port attributes !");
+		return (-1);
+	}
+
+	// Make sure queues are empty before we begin
+	tcflush (this->fd, TCIOFLUSH);
+		
+	// Start the device thread
+	StartThread ();
+
+	return (0);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Shutdown the device
+int SkyetekM1::Shutdown ()
+{
+	// Stop the driver thread
+	StopThread ();
+
+	// Close the serial port
+	tcsetattr (this->fd, TCSANOW, &this->initial_options);
+	close (this->fd);
+	
+	PLAYER_MSG0 (1, "> SkyetekM1 driver shutting down... [done]");
+	return (0);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Main function for device thread
+void SkyetekM1::Main () 
+{
+	// Zero data
+	memset (&this->rfid_data, 0, sizeof (this->rfid_data));
+	
+	timespec sleepTime = {0, 0};
+	
+	// The main loop; interact with the device here
+	while (true)
+	{
+		// test if we are supposed to cancel
+		pthread_testcancel ();
+		
+		// Check for and handle configuration requests, using Driver::GetConfig ()
+		this->CheckConfig ();
+		
+		// Check for and execute commands, using Driver::GetCommand()
+		this->CheckCommands ();
+		
+		// Interact with the device, and push out the resulting data, using
+		// Driver::PutData()
+		this->RefreshData ();
+		
+		nanosleep (&sleepTime, NULL);
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CheckConfig function
+void SkyetekM1::CheckConfig ()
+{
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CheckCommands function
+void SkyetekM1::CheckCommands ()
+{
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RefreshData function
+void SkyetekM1::RefreshData ()
+{
+	memset (&this->rfid_data, 0, sizeof (this->rfid_data));
+	
+	// Get the time at which we started reading
+	// This will be a pretty good estimate of when the phenomena occured
+	struct timeval time;
+	GlobalTime->GetTime(&time);
+	
+	// Anticollision mode
+	SelectTags ();
+	Wake ();
+
+	this->rfid_data.tags_count = htons (this->rfid_data.tags_count);
+
+	// Write the RFID data
+	PutData (this->rfid_id, &this->rfid_data, sizeof (this->rfid_data), &time);
+	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WriteSerial function
+void SkyetekM1::WriteSerial (unsigned char *mdmData, unsigned char commandLen)
+{
+	int wresult;
+	wresult = write (this->fd, mdmData, commandLen);
+	if (wresult < 0)
+		PLAYER_WARN1 (">> Error while writing %d bytes !", commandLen);
+}	
+
+////////////////////////////////////////////////////////////////////////////////
+// ReadSerial function
+int SkyetekM1::ReadSerial (unsigned char *mdmData, unsigned char commandLen)
+{
+	int bytes_read = read (this->fd, mdmData, commandLen);
+	return bytes_read;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SelectTags function
+void SkyetekM1::SelectTags ()
+{
+	unsigned char command_buf[80], response_buf[80];
+	unsigned char i = 1;
+	unsigned int crc_check;
+
+	// REQUEST for SELECT_TAG: MSGLEN|FLAGS|0x14|rid|TAGTYPE|tid|AFI|CRC
+	// ---[ Build the request ]---
+	command_buf[i++] = 0x22;             // SEL_TAG_INV (CRC_F, INV_F enabled)
+	command_buf[i++] = 0x14;             // SELECT_TAG (set command (0x14))
+	// set reader ID - empty (no RID)
+	command_buf[i++] = 0x00;             // AUTODETECT (0x00)
+
+	
+	command_buf[0] = i + 1;              // set message length
+	
+	crc_check = CRC16 (command_buf, i);
+	command_buf[i++] = crc_check >> 8;   // set CRC
+	command_buf[i++] = crc_check & 0x00FF;
+
+	// copy the command buffer and prepare to write - OK
+	int j;
+	unsigned char temp[80];
+	temp[0] = 0x02;                  // Start of Transmission (STX = 0x02)
+	for (j = 0; j < i+1; j++)
+		temp[j+1] = command_buf[j];	
+	WriteSerial (temp, i + 1);
+	
+	// poll for reader response
+	while (response_buf[2] != 0x94)
+	{
+		ReadSerial (response_buf, 3);
+		int len = 0;
+		if (response_buf[0] == 0x02)
+			len = response_buf[1];
+		
+		unsigned char TID[len];
+		bzero (&TID, sizeof (TID)); // clear the struct for new port settings
+		usleep (10000); // sleep for 10ms
+		ReadSerial (TID, len);
+		if (response_buf[2] == 0x94)
+			break;
+		
+		if (response_buf[0] == 0x02)
+		{
+			this->rfid_data.tags[this->rfid_data.tags_count].type = TID[0];
+			int j;
+			for (j = 0; j < 9; j++)
+				this->rfid_data.tags[this->rfid_data.tags_count].guid[j] = TID[j+1];
+			this->rfid_data.tags_count++;
+		}
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// S_ReadWrite function
+int SkyetekM1::S_ReadWrite (unsigned char *mdmData, 
+							unsigned char length, unsigned char *response)
+{
+	unsigned char temp[80], read_data[80];
+	bool read_done = FALSE;
+	int tmp_count = 0;
+	int i;
+	
+	// copy the command buffer and prepare to write
+	temp[0] = 0x02;                  // Start of Transmission (STX = 0x02)
+	for (i = 0; i < length + 1; i++)
+		temp[i+1] = mdmData[i];	
+	
+	WriteSerial (temp, length + 1);
+	
+	// sleep for 10ms
+	usleep (10000);
+	
+	while (!read_done)
+	{ 
+		tmp_count++;
+	
+		ReadSerial (read_data, sizeof (read_data));
+		
+		int m = 0;
+
+		while (m != sizeof (read_data))
+		{
+			response[m] = read_data[m];
+			m++;
+		}
+				
+		if (tmp_count > 10)
+			read_done = TRUE;
+		
+		if ((read_data[0] = 0x02) && (read_data[1] <= 0x50))
+			read_done = TRUE;
+		
+		usleep (10000);               // Sleep for 10ms
+	}
+
+	return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// CRC16 function
+unsigned int SkyetekM1::CRC16 (unsigned char *dataP, unsigned char n)
+{
+	unsigned char i, j;     // byte counter, bit counter
+	unsigned int  crc_16;   // calculation
+
+	crc_16 = 0x0000;        // PRESET value
+
+	for (i = 0; i < n; i++) // check each byte in the array
+	{
+		crc_16 ^= *dataP++;
+
+		for (j = 0; j < 8; j++) 	  // test each bit in the byte
+			if (crc_16 & 0x0001)
+			{
+				crc_16 >>= 1;
+				crc_16 ^= 0x8408; // POLYNOMIAL x^16+x^12+x^5+1
+			}
+			else
+				crc_16 >>= 1;
+	}
+	return (crc_16);	// returns calculated crc (16 bits)
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// VerifyCRC function
+unsigned char SkyetekM1::VerifyCRC (unsigned char *resp)
+{
+	unsigned char i = 0;
+	unsigned char ret_crc[80];
+	unsigned int  crc_check;
+
+	int k = 0;
+	
+	for (k = 0; k < (int)((resp[1])-1); k++)
+	{
+		ret_crc[i] = resp[k+1];
+		i++;
+	}	
+
+	crc_check = CRC16 (ret_crc, i);
+	
+	if ((resp[i+1] == (crc_check >> 8)) && (resp[i+2] == (crc_check & 0x00FF)))
+		return 0;
+	else
+		return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sleep function
+unsigned char SkyetekM1::Sleep ()
+{
+	unsigned char command_buf[80], response_buf[80];
+	unsigned char i = 0;
+	unsigned int crc_check;
+	int      s_rwStatus;
+	
+	// binary mode command format: msgLen|flags|command|startblock|numblocks|crc
+	command_buf[i++] = 0x07;             // set msg length
+	command_buf[i++] = CRC_F;            // set flags
+	command_buf[i++] = 0x42;             // WRITE_SYS (set command)
+	
+	command_buf[i++] = 0x04;             // OP_MODE
+	command_buf[i++] = 0x01;             // set number of blocks to write
+	command_buf[i++] = 0x00;             // set data to write
+
+	crc_check = CRC16 (command_buf, i);
+	command_buf[i++] = crc_check >> 8;   // set CRC
+	command_buf[i++] = crc_check & 0x00FF;
+	
+	// copy the command buffer and prepare to write
+	s_rwStatus = S_ReadWrite (command_buf, i, response_buf);
+	
+	// verify return CRC
+	if (VerifyCRC (response_buf))
+		return 0x81;                     // BAD_CRC
+	
+	return response_buf[2];
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Wake function
+unsigned char SkyetekM1::Wake ()
+{
+
+	unsigned char command_buf[80], response_buf[80];
+	unsigned char i = 0;
+	unsigned int crc_check;
+	int      s_rwStatus;
+	
+	// binary mode command format: msgLen|flags|command|startblock|numblocks|crc
+	command_buf[i++] = 0x07;             // set msg length
+	command_buf[i++] = CRC_F;            // set flags
+	command_buf[i++] = 0x42;             // WRITE_SYS (set command)
+	command_buf[i++] = 0x04;             // OP_MODE
+	command_buf[i++] = 0x01;             // set number of blocks to write
+	command_buf[i++] = 0xFF;             // set data to write
+	command_buf[0]   = i + 1;            // set msg Length
+
+	crc_check = CRC16 (command_buf, i);
+	command_buf[i++] = crc_check >> 8;   // set CRC
+	command_buf[i++] = crc_check & 0x00FF;
+	
+	// copy the command buffer and prepare to write
+	s_rwStatus = S_ReadWrite (command_buf, i, response_buf);
+	
+	// verify return CRC
+	if (VerifyCRC (response_buf))
+		return 0x81;                     // BAD_CRC
+	
+	return response_buf[2];
+}
+
diff -pruN player-1.6.5/server/player.h player-1.6.5-rfid/server/player.h
--- player-1.6.5/server/player.h	2005-03-18 23:38:18.000000000 +0100
+++ player-1.6.5-rfid/server/player.h	2006-02-01 10:35:59.000000000 +0100
@@ -98,6 +98,9 @@
 #define PLAYER_JOYSTICK_CODE       ((uint16_t)49)  // Joytstick
 #define PLAYER_SPEECH_RECOGNITION_CODE  ((uint16_t)50)  // speech recognitionI/O
 #define PLAYER_OPAQUE_CODE         ((uint16_t)51)  // plugin interface
+// (@) rbrusu [--- RFID
+#define PLAYER_RFID_CODE           ((uint16_t)52)  // RFID reader interface
+// ---]
 
 /* the currently assigned device strings */
 #define PLAYER_NULL_STRING           "null"
@@ -143,6 +146,9 @@
 #define PLAYER_CAMERA_STRING         "camera"
 #define PLAYER_JOYSTICK_STRING       "joystick"
 #define PLAYER_OPAQUE_STRING         "opaque"
+// (@) rbrusu [--- RFID
+#define PLAYER_RFID_STRING           "rfid"
+// ---]
 
 /* The maximum number of devices the server will support. */
 #define PLAYER_MAX_DEVICES 256
@@ -3320,4 +3326,62 @@ typedef struct player_speech_recognition
 /** @} */
 
 
+// (@) rbrusu [--- RFID
+/*************************************************************************/
+/** @addtogroup interfaces */
+/** @{ */
+/** @defgroup player_interface_rfid rfid
+
+The RFID interface provides access to a RFID reader.
+
+@{
+ */
+ 
+/** The maximum number of tags that can be detected in the RFID field in total. */
+#define PLAYER_RFID_MAX_TAGS 30
+/** The maximum number of digits a RFID tag can have. */
+#define PLAYER_RFID_MAX_GUID 8
+
+/* Config request codes */
+/** Configuration request: put the reader in sleep mode (false) or wake it up (true) */
+#define PLAYER_RFID_POWER_REQ           ((uint8_t)1)
+/** Configuration request: read data from the RFID tag - to be implemented */
+#define PLAYER_RFID_READTAG_REQ         ((uint8_t)2)
+/** Configuration request: write data to the RFID tag - to be implemented */
+#define PLAYER_RFID_WRITETAG_REQ        ((uint8_t)3)
+/** Configuration request: lock data blocks of a RFID tag - to be implemented */
+#define PLAYER_RFID_LOCKTAG_REQ         ((uint8_t)4)
+
+/** @brief Structure describing a single RFID tag. */
+typedef struct player_rfid_tag
+{
+	/** Tag type. */
+	uint8_t type;
+	/** The Globally Unique IDentifier (GUID) of the tag. */
+	uint8_t guid[PLAYER_RFID_MAX_GUID];
+} __PACKED__ player_rfid_tag_t;
+
+/** @brief Data
+
+The RFID data packet.  */
+typedef struct player_rfid_data
+{
+	/** The number of RFID tags found. */
+	uint16_t tags_count;
+	/** The list of RFID tags. */
+	player_rfid_tag_t tags[PLAYER_RFID_MAX_TAGS];
+} __PACKED__ player_rfid_data_t;
+
+/** @brief Command
+
+The RFID interface accepts commands, such as... (?) */
+typedef struct player_rfid_cmd
+{
+    uint8_t temp;
+} __PACKED__ player_rfid_cmd_t;
+
+/** @} */
+/** @} */
+// ---]
+
 #endif /* PLAYER_H */
