diff --git a/src/can/can.cpp b/src/can/can.cpp
index 3f8f55f59a9f2db22ccb07b22528d01032a3d20d..920f70f76e0ac1628ea19db9c9ebd09b13a9d417 100755
--- a/src/can/can.cpp
+++ b/src/can/can.cpp
@@ -1,24 +1,79 @@
 #include "can.h"
+#include "commexceptions.h"
+#include <string.h>
+#include <iostream>
+#include <math.h>
+#include <errno.h>
 
 CCAN::CCAN(const std::string &comm_id) : CComm(comm_id)
 {
-
+  this->can_socket_fd=-1;
+  this->req_can_id=-1;
+  // initialize the thread attributes
+  this->thread_server=CThreadServer::instance();
+  this->can_thread_id=comm_id + "_can_thread";
+  this->thread_server->create_thread(this->can_thread_id);
+  this->thread_server->attach_thread(this->can_thread_id,this->can_thread,this);
+  // initialize the event atributes
+  this->event_server=CEventServer::instance();
+  this->new_frame_event_id=comm_id + "_new_frame_event_id";
+  this->event_server->create_event(this->new_frame_event_id);
+  this->frame_error_event_id=comm_id + "_frame_error_event_id";
+  this->event_server->create_event(this->frame_error_event_id);
+  this->data_requested_event_id=comm_id + "_data_requested_event_id";
+  this->event_server->create_event(this->data_requested_event_id);
+  this->finish_can_thread_event_id=comm_id + "_finish_can_thread_event_id";
+  this->event_server->create_event(this->finish_can_thread_event_id);
 }
 
 void CCAN::hard_open(void *comm_dev)
 {
+  std::string *can_dev=(std::string *)comm_dev;
+  struct sockaddr_can addr;
+  struct ifreq ifr;
+
+  if ((this->can_socket_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) 
+  {
+    /* handle exceptions */
+    throw CCommException(_HERE_,"impossible to create the socket-CAN",this->get_id());
+  }
+  addr.can_family = AF_CAN;
+  std::cout << *can_dev << std::endl;
+  strcpy(ifr.ifr_name, can_dev->c_str());
+  ioctl(this->can_socket_fd, SIOCGIFINDEX, &ifr);
+  addr.can_ifindex = ifr.ifr_ifindex;
 
+  if (bind(this->can_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) 
+  {
+    /* handle exceptions */
+    throw CCommException(_HERE_,"impossible to connect the socket-CAN",this->get_id());
+  }
 }
 
 void CCAN::hard_config(void *config)
 {
-  /* do nothing */
+  // start the can thread
+  this->thread_server->start_thread(this->can_thread_id);
 }
 
 int CCAN::hard_read(unsigned char *data, int len)
 {
   int num_read=0;
 
+  if(this->can_socket_fd!=-1)
+  {
+    if((num_read=::read(this->can_socket_fd,data,len))==-1)
+    {
+      /* handle exceptions */
+      throw CCommException(_HERE_,"Error while reading from the socket.",this->comm_id);
+    }
+  }
+  else
+  {
+    /* handle exceptions */
+    throw CCommException(_HERE_,"The socket-CAN has not been properly opened.",this->comm_id);
+  }
+
   return num_read;
 }
 
@@ -26,28 +81,239 @@ int CCAN::hard_write(unsigned char *data, int len)
 {
   int num_write=0;
 
+  if(this->can_socket_fd!=-1)
+  {
+    if((num_write=::write(this->can_socket_fd,data,len))==-1)
+    {
+      /* handle exceptions */
+      throw CCommException(_HERE_,"Error while writing to the socket.",this->comm_id);
+    }
+  }
+  else
+  {
+    /* handle exceptions */
+    throw CCommException(_HERE_,"The socket-CAN has not been properly opened.",this->comm_id);
+  }
+
   return num_write;
 }
 
 int CCAN::hard_get_num_data(void)
 {
+  unsigned char data[1024];
   int num;
 
+  if(this->can_socket_fd!=-1)
+  {
+    if((num=recv(this->can_socket_fd,data,1024,MSG_PEEK))==-1)
+//    if(ioctl(this->can_socket_fd,FIONREAD,&num)==-1)
+    {
+      std::cout << errno << std::endl;
+      /* handle exceptions */
+      throw CCommException(_HERE_,"Error while getting the number of bytes available from the socket.",this->comm_id);
+    }
+  }
+  else
+  {
+    /* handle exceptions */
+    throw CCommException(_HERE_,"The socket-CAN has not been properly opened.",this->comm_id);
+  }
+
   return num;
 }
 
 int CCAN::hard_wait_comm_event(void)
 {
+  fd_set receive_set,error_set;
+  int max_fd,wait_result=0;
+
+  max_fd=this->can_socket_fd+1;
+  FD_ZERO(&receive_set);
+  FD_SET(this->can_socket_fd,&receive_set);
+  FD_ZERO(&error_set);
+  FD_SET(this->can_socket_fd,&error_set);
+  wait_result=select(max_fd,&receive_set,NULL,&error_set,NULL);
+  if(wait_result==-1)
+  {
+    /* handle exceptions */
+    throw CCommException(_HERE_,"Error while waiting for socket events",this->comm_id);
+  }
+  else
+  {
+    if(FD_ISSET(this->can_socket_fd,&receive_set))/* data has been received */
+      return 1;
+    if(FD_ISSET(this->can_socket_fd,&error_set))
+      return 2;
+  }
+
   return -1;
 }
 
 void CCAN::hard_close(void)
 {
+  // close the can device
+  if(this->can_socket_fd!=-1)
+    ::close(this->can_socket_fd);
+  // free all the resources
+  if(this->finish_can_thread_event_id!="")
+  {
+    this->event_server->set_event(this->finish_can_thread_event_id);
+    this->thread_server->end_thread(this->can_thread_id);
+    this->thread_server->detach_thread(this->can_thread_id);
+    this->thread_server->delete_thread(this->can_thread_id);
+    this->can_thread_id="";
+    this->event_server->delete_event(this->finish_can_thread_event_id);
+    this->finish_can_thread_event_id="";
+  }
+  if(this->new_frame_event_id!="")
+  {
+    this->event_server->delete_event(this->new_frame_event_id);
+    this->new_frame_event_id="";
+  }
+  if(this->frame_error_event_id!="")
+  {
+    this->event_server->delete_event(this->frame_error_event_id);
+    this->frame_error_event_id="";
+  }
+  if(this->data_requested_event_id!="")
+  {
+    this->event_server->delete_event(this->data_requested_event_id);
+    this->data_requested_event_id="";
+  }
+}
 
+void *CCAN::can_thread(void *param)
+{
+  static struct can_frame new_frame;
+  std::list<std::string> events;
+  CCAN *can=(CCAN *)param;
+  unsigned int event_id,num;
+  bool end=false;
+
+  events.push_back(can->finish_can_thread_event_id);
+  events.push_back(can->get_rx_event_id());
+  while(!end)
+  {
+    event_id=can->event_server->wait_first(events);
+    if(event_id==0)
+      end=true;
+    else
+    {
+      can->can_access.enter();
+      // process the incomming data
+      num=can->get_num_data();
+      while(num>=sizeof(struct can_frame))// there is a whole frame in the input buffer
+      {
+        can->read((unsigned char *)&new_frame,sizeof(struct can_frame));
+        if(new_frame.can_id&CAN_RTR_FLAG)
+        {
+          // save the requested can_id
+          can->req_can_id=new_frame.can_id;
+          // activate the event
+          can->event_server->set_event(can->data_requested_event_id);
+        }
+        else
+        {
+          //puch the new frame into the queue
+          can->rx_frames.push(new_frame);
+          // activate the event
+          can->event_server->set_event(can->new_frame_event_id);
+        }
+        num-=sizeof(struct can_frame);
+      }
+      can->can_access.exit();
+    }
+  }
+ 
+  pthread_exit(NULL);
 }
 
-CCAN::~CCAN()
+void CCAN::open(const std::string &can_dev)
+{
+  CComm::open((void *)&can_dev);
+  this->config();
+}
+
+std::string CCAN::get_new_frame_event_id(void)
+{
+  return this->new_frame_event_id;
+}
+
+std::string CCAN::get_frame_error_event_id(void)
+{
+  return this->frame_error_event_id;
+}
+
+std::string CCAN::get_data_requested_event_id(void)
+{
+  return this->data_requested_event_id;
+}
+
+unsigned int CCAN::get_requested_can_id(void)
+{ 
+  return this->req_can_id;
+}
+
+void CCAN::write_frame(unsigned int can_id, unsigned char *data, int len)
 {
+  int num_frames=ceil((double)len/8.0),i,j;
+  struct can_frame frame;
+
+  // check the identifier format
+  if((can_id&(~CAN_SFF_MASK))!=0)// it's an extended identifier
+    can_id=can_id|CAN_EFF_FLAG;
+
+  for(i=0;i<num_frames;i++)
+  {
+    // generate all the frames
+    frame.can_id=can_id;
+    if((len-8*i)<8)
+      frame.can_dlc=len-8*i;
+    else
+      frame.can_dlc=8;
+    for(j=0;j<frame.can_dlc;j++)
+      frame.data[j]=data[i*8+j];
+    // send the frames
+    this->write((unsigned char *)&frame,sizeof(struct can_frame));
+  }
+}
+
+void CCAN::read_frame(unsigned int *can_id, unsigned char *data, int *len)
+{
+  struct can_frame frame;
+  int i=0;
+
+  this->can_access.enter();
+  if(!this->rx_frames.empty())
+  {
+    frame=this->rx_frames.front();
+    this->rx_frames.pop();
+    *can_id=frame.can_id;
+    *len=frame.can_dlc;
+    for(i=0;i<frame.can_dlc;i++)
+      data[i]=frame.data[i];
+  }
+  else
+  {
+    /* handle exceptions */
+  }
+  this->can_access.exit();
+}
 
+void CCAN::add_id_filter(unsigned short int start_id, unsigned short int end_id)
+{
+
+}
+
+void CCAN::clear_id_filters(void)
+{
+
+}
+
+CCAN::~CCAN()
+{
+  // close the can device
+  if(this->can_socket_fd!=-1)
+    this->close();
 }
 
diff --git a/src/can/can.h b/src/can/can.h
index 8c9630dcfc2bd5565b17cd13949e85a69326d246..6cbd314c51c12b6f62799d4e5dbf4ca1f48b349f 100755
--- a/src/can/can.h
+++ b/src/can/can.h
@@ -4,14 +4,41 @@
 #include "comm.h"
 #include "mutex.h"
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <net/if.h>
+#include <linux/can.h>
+#include <linux/can/bcm.h>
+
+#include "threadserver.h"
+#include "eventserver.h"
+#include <queue>
+
 /**
  * \brief CAN driver
  *
  */
 
-class CCAN : public CComm
+class CCAN : protected CComm
 {
   private:
+    // can device identifier
+    int can_socket_fd;
+    unsigned int req_can_id;
+    // thread attributes
+    CThreadServer *thread_server;
+    std::string can_thread_id;
+    // event attributes
+    CEventServer *event_server;
+    std::string new_frame_event_id;// public event
+    std::string frame_error_event_id;// public event
+    std::string data_requested_event_id;// public event
+    std::string finish_can_thread_event_id;// private event
+    // intranal received frame buffer
+    std::queue<struct can_frame> rx_frames;
+    CMutex can_access;
   protected:
      /**
       * \brief Function to actually open the device
@@ -147,6 +174,10 @@ class CCAN : public CComm
      * exception class defined by the inherited class.
      */
     virtual void hard_close(void);
+    /** 
+     * \brief
+     */
+    static void *can_thread(void *param);
   public:
     /**
      * \brief default constructor
@@ -160,6 +191,42 @@ class CCAN : public CComm
      *                 class.
      */
     CCAN(const std::string &comm_id);
+    /** 
+     * \brief
+     */
+    void open(const std::string &can_dev);
+    /** 
+     * \brief
+     */
+    std::string get_new_frame_event_id(void);
+    /** 
+     * \brief
+     */
+    std::string get_frame_error_event_id(void);
+    /** 
+     * \brief
+     */
+    std::string get_data_requested_event_id(void);
+    /** 
+     * \brief
+     */
+    unsigned int get_requested_can_id(void);
+    /** 
+     * \brief
+     */
+    void write_frame(unsigned int can_id, unsigned char *data, int len);
+    /** 
+     * \brief
+     */
+    void read_frame(unsigned int *can_id, unsigned char *data, int *len);
+    /** 
+     * \brief
+     */
+    void add_id_filter(unsigned short int start_id, unsigned short int end_id=-1);
+    /** 
+     * \brief
+     */
+    void clear_id_filters(void); 
     /**
      * \brief Destructor
      *
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index e90ba1216e40736893f854cbed0c5e47597b159f..2f64dc6df46887e61623f5955f9986e1a3987c5e 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -4,6 +4,18 @@ ADD_EXECUTABLE(test_rs232 test_rs232.cpp)
 # edit the following line to add the necessary libraries
 TARGET_LINK_LIBRARIES(test_rs232 ${IRIUTILS_LIBRARY} comm pthread)
 
+# edit the following line to add the source code for the example and the name of the executable
+ADD_EXECUTABLE(test_can test_can.cpp)
+
+# edit the following line to add the necessary libraries
+TARGET_LINK_LIBRARIES(test_can ${IRIUTILS_LIBRARY} comm pthread)
+
+# edit the following line to add the source code for the example and the name of the executable
+ADD_EXECUTABLE(test_can_rx test_can_rx.cpp)
+
+# edit the following line to add the necessary libraries
+TARGET_LINK_LIBRARIES(test_can_rx ${IRIUTILS_LIBRARY} comm pthread)
+
 IF(BUILD_FTDI)
   ADD_EXECUTABLE(test_ftdi test_ftdi.cpp)
 
diff --git a/src/examples/test_can.cpp b/src/examples/test_can.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..9fdb13c795704c37778843dc87251e7983eba67e
--- /dev/null
+++ b/src/examples/test_can.cpp
@@ -0,0 +1,45 @@
+#include "eventserver.h"
+#include "threadserver.h"
+#include "commexceptions.h"
+#include "can.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+#include <iostream>
+
+#include <linux/can/raw.h>
+#include <linux/can.h>
+
+const std::string can_dev="can0";
+
+/**
+ * \example test_can.cpp
+ *
+ */
+int main(int argc,char *argv[])
+{
+  CCAN can_port("can_port");
+  unsigned char data[10];
+  int i=0;
+  
+  try{
+    can_port.open(can_dev);
+    data[0]=0x01;
+    data[1]=0x02;
+    data[2]=0x03;
+    data[3]=0x04;
+    data[4]=0x05;
+    data[5]=0x06;
+    data[6]=0x07;
+    data[7]=0x08;
+    data[8]=0x09;
+    data[9]=0x0A;
+    for(i=0;i<5;i++)
+    {
+      can_port.write_frame(0x200,data,10);
+      sleep(1);
+    }
+  }catch(CCommException &e){
+    std::cout << e.what() << std::endl;
+  }
+}
diff --git a/src/examples/test_can_rx.cpp b/src/examples/test_can_rx.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..ba541bcf1adb917397456f1280e39e24ac8ae463
--- /dev/null
+++ b/src/examples/test_can_rx.cpp
@@ -0,0 +1,45 @@
+#include "eventserver.h"
+#include "threadserver.h"
+#include "commexceptions.h"
+#include "can.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+#include <iostream>
+
+#include <linux/can/raw.h>
+#include <linux/can.h>
+
+const std::string can_dev="can1";
+
+/**
+ * \example test_can.cpp
+ *
+ */
+int main(int argc,char *argv[])
+{
+  CEventServer *event_server=CEventServer::instance();
+  std::list<std::string> events;
+  CCAN can_port("can_port");
+  unsigned char data[8];
+  unsigned int can_id;
+  int i=0,len;
+  
+  events.push_back(can_port.get_new_frame_event_id());
+  try{
+    can_port.open(can_dev);
+    while(1)
+    {
+      event_server->wait_all(events);
+      can_port.read_frame(&can_id,data,&len);
+      std::cout << "can id: 0x" << std::hex << can_id << std::endl;
+      std::cout << "length: " << len << std::endl;
+      std::cout << "data: ";
+      for(i=0;i<len;i++)
+        std::cout << "0x" << std::hex << (int)data[i];
+      std::cout << std::endl;
+    }
+  }catch(CCommException &e){
+    std::cout << e.what() << std::endl;
+  }
+}