diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7be414a62b21a47fb686222faa578f83e79ea575..4358a0628181ac7372db7a43ba58268f703576ed 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -33,9 +33,9 @@ ELSE(FTDI_INCLUDE_DIR AND FTDI_LIBRARY)
 ENDIF(FTDI_INCLUDE_DIR AND FTDI_LIBRARY)
 
 # edit the following line to add all the source code files of the library
-SET(sources ./comm.cpp ./commexceptions.cpp ./serial/rs232.cpp ./serial/rs232exceptions.cpp  ./sockets/socket.cpp ./sockets/socketclient.cpp ./sockets/socketserver.cpp ./sockets/socketexceptions.cpp)
+SET(sources ./comm.cpp ./commexceptions.cpp ./serial/rs232.cpp ./serial/rs232exceptions.cpp  ./sockets/socket.cpp ./sockets/socketclient.cpp ./sockets/socketserver.cpp ./sockets/socketexceptions.cpp ./can/can.cpp)
 # edit the following line to add all the header files of the library
-SET(headers ./comm.h ./commexceptions.h ./serial/rs232.h ./serial/rs232exceptions.h ./sockets/socket.h ./sockets/socketclient.h ./sockets/socketserver.h ./sockets/socketexceptions.h)
+SET(headers ./comm.h ./commexceptions.h ./serial/rs232.h ./serial/rs232exceptions.h ./sockets/socket.h ./sockets/socketclient.h ./sockets/socketserver.h ./sockets/socketexceptions.h ./can/can.h)
 
 IF(BUILD_FTDI)
   SET(sources ${sources} ./usb_ftdi/ftdiserver.cpp ./usb_ftdi/ftdimodule.cpp ./usb_ftdi/ftdiexceptions.cpp)
@@ -50,7 +50,7 @@ FIND_PACKAGE(iriutils REQUIRED)
 INCLUDE_DIRECTORIES(${iriutils_INCLUDE_DIR})
 
 # edit the following line to add the necessary include directories
-INCLUDE_DIRECTORIES(./serial ./usb_ftdi ./sockets)
+INCLUDE_DIRECTORIES(./serial ./usb_ftdi ./sockets ./can)
 
 IF(BUILD_FTDI)
   INCLUDE_DIRECTORIES(${FTDI_INCLUDE_DIR})
diff --git a/src/can/can.cpp b/src/can/can.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..3f8f55f59a9f2db22ccb07b22528d01032a3d20d
--- /dev/null
+++ b/src/can/can.cpp
@@ -0,0 +1,53 @@
+#include "can.h"
+
+CCAN::CCAN(const std::string &comm_id) : CComm(comm_id)
+{
+
+}
+
+void CCAN::hard_open(void *comm_dev)
+{
+
+}
+
+void CCAN::hard_config(void *config)
+{
+  /* do nothing */
+}
+
+int CCAN::hard_read(unsigned char *data, int len)
+{
+  int num_read=0;
+
+  return num_read;
+}
+
+int CCAN::hard_write(unsigned char *data, int len)
+{
+  int num_write=0;
+
+  return num_write;
+}
+
+int CCAN::hard_get_num_data(void)
+{
+  int num;
+
+  return num;
+}
+
+int CCAN::hard_wait_comm_event(void)
+{
+  return -1;
+}
+
+void CCAN::hard_close(void)
+{
+
+}
+
+CCAN::~CCAN()
+{
+
+}
+
diff --git a/src/can/can.h b/src/can/can.h
new file mode 100755
index 0000000000000000000000000000000000000000..8c9630dcfc2bd5565b17cd13949e85a69326d246
--- /dev/null
+++ b/src/can/can.h
@@ -0,0 +1,172 @@
+#ifndef _CAN_H
+#define _CAN_H
+
+#include "comm.h"
+#include "mutex.h"
+
+/**
+ * \brief CAN driver
+ *
+ */
+
+class CCAN : public CComm
+{
+  private:
+  protected:
+     /**
+      * \brief Function to actually open the device
+      *
+      * This function is called automatically when the base class open() function
+      * is called. By default, it initializes the socket file descriptor using the
+      * socket() system call. But, if the object has been created by the 
+      * create_socket() function, this function does nothing.
+      *
+      * This class does not need any parameter since the socket is created by 
+      * default using a TCP/IP protocol and the AF_INET socket family. So the
+      * argument passed to this function is ignored and may be NULL.
+      * 
+      * This function can throw any CSocketException object exception or the generic 
+      * CCommException class.
+      *
+      * \param comm_dev this parameter is ignored in this case and can be set to NULL.
+      *                 It is only keeped for backward compatiblity with the CComm
+      *                 class.
+      */
+    virtual void hard_open(void *comm_dev=NULL);
+    /**
+      * \brief Function to actually configure the device
+      * 
+      * This function is called automatically when the base class config() function
+      * is called. In this case this function does nothing, since all the necessay
+      * parameters are provide to the open() function. However, it is necessary to 
+      * call the config() function to successfully change the internal state of the
+      * communication device.
+      *
+      * The provided parameter in this case can be NULL since no configuration is
+      * needed. This function can throw any CCommException object exception or else 
+      * any exception class defined by the inherited class.
+      *
+      * \param config This parameter is not used since no configuration is required.
+      *               It is only keeped for backward compatiblity with the CComm
+      *               class.
+      */
+     virtual void hard_config(void *config=NULL);
+    /**
+     * \brief Function to actually read from the device
+     *
+     * This function is automatically called when the new data received event is 
+     * activated. The read() function from the base class gets data from the 
+     * internal queue, so this function is not used. It must try to read the 
+     * ammount of data specified and store it in the data buffer provided without 
+     * blocking. Also, it must return the number of bytes actually read from the 
+     * devicve, since they may be different than the desired value.
+     *
+     * In case of any error, this function throws a CSocketException exception.
+     *
+     * \param data a reference to the buffer where the received data must be 
+     * copied. The necessary memory for this buffer must be allocated before 
+     * calling this function and have enough size to store all the desired data.
+     * If this buffer is not initialized, the function throws an exception.
+     *
+     * \param len a positive interger that indicates the number of byte to be
+     * read from the communication device. This value must be at most the length 
+     * of the data buffer provided to the function.
+     *
+     * \return an integer with the number of bytes actually read. These number 
+     * coincide with the desired number if there is enough data in the internal 
+     * queue, but it could be smaller if not.
+     */
+    virtual int hard_read(unsigned char *data, int len);
+    /**
+     * \brief Hard write function
+     *
+     * This function is automatically called when the base class write() function
+     * is called. It must try to write the desired ammount of data to the communication 
+     * device without blocking. Also it must return the number of bytes actually
+     * written to the communication device since they may be different from the
+     * desired value.
+     *
+     * In case of any error, this function throws a CSocketException exception.
+     *
+     * \param data a reference to the buffer with the data must be send to the 
+     * device. The necessary memory for this buffer must be allocated before 
+     * calling this function and have enough size to store all the desired data.
+     * If this buffer is not initialized, the function throws an exception.
+     *
+     * \param len a positive interger that indicates the number of byte to be
+     * written to the communication device. This value must be at most the length 
+     * of the data buffer provided to the function.
+     *
+     * \return an integer with the number of bytes actually written. These number 
+     * coincide with the desired number if there is enough data in the internal 
+     * queue, but it could be smaller if not.
+     */
+    virtual int hard_write(unsigned char *data, int len);
+    /**
+     * \brief Function to actually get the number of bytes availables
+     *
+     * This function is called when the new data received event is activated.
+     * It must get the number of data bytes available from the communication
+     * device and return its value without blocking.
+     *
+     * In case of any error, this function throws a CSocketException exception.
+     *
+     * \return an integer with the number of bytes available in the receive queue. 
+     * This value can be 0 if there is no data available, but there is ni upper
+     * limit in its value.
+     */
+    virtual int hard_get_num_data(void);
+    /**
+     * \brief Function to actually wait for a given communication event 
+     *
+     * This function is called in the internal communciation thread to wait for 
+     * any event on the communuication device. It must check for any event on the
+     * device (reception, end of transmission or error) and return the
+     * corresponding identifier. When an event is activated, this function must 
+     * return to allow the base class to handle it, and the it is called again
+     * to wait for the next event.
+     *
+     * This function can throw any CCommException object exception or else any
+     * exception class defined by the inherited class.
+     *
+     * \return -1 if there has been any error or else the identifier of the 
+     *         communciation event:
+     *
+     * - 1 for the new data received event
+     * - 2 for the error event
+     */
+    virtual int hard_wait_comm_event(void);
+    /** 
+     * \brief Hard close function
+     *
+     * This function is called when the base class close() funciton is called. It
+     * must free the device handle initialized by the open() function and also free
+     * any other resource allocated by the inherited class.
+     *
+     * This function can throw any CCommException object exception or else any
+     * exception class defined by the inherited class.
+     */
+    virtual void hard_close(void);
+  public:
+    /**
+     * \brief default constructor
+     *
+     * This constructor creates a new CSocket object. It does not open a physical 
+     * socket, it only allocates the necessary resources to use it.
+     *
+     * \param comm_id  A null terminated string which identifies the 
+     *                 communications device. This string is used to created a
+     *                 unique identifier for all the threads and events of the
+     *                 class.
+     */
+    CCAN(const std::string &comm_id);
+    /**
+     * \brief Destructor
+     *
+     * This destructor does nothing. The base class destructor is the one in 
+     * charge of freeing all the allocated resources.
+     */
+    virtual ~CCAN();
+};
+
+#endif