diff --git a/common b/common
index 15d47a6..94f95e3 160000
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 15d47a6bedef727075895311282d9f5f5186b49d
+Subproject commit 94f95e3d83fe677bfc4aaebb23badc3abc56366a
diff --git a/sys/dvb/gstdvbsrc.c b/sys/dvb/gstdvbsrc.c
index 5a05b87..8a4defe 100644
--- a/sys/dvb/gstdvbsrc.c
+++ b/sys/dvb/gstdvbsrc.c
@@ -97,7 +97,8 @@ enum
   ARG_DVBSRC_HIERARCHY_INF,
   ARG_DVBSRC_TUNE,
   ARG_DVBSRC_INVERSION,
-  ARG_DVBSRC_STATS_REPORTING_INTERVAL
+  ARG_DVBSRC_STATS_REPORTING_INTERVAL,
+  ARG_DVBSRC_TIMEOUT,
 };
 
 static void gst_dvbsrc_output_frontend_stats (GstDvbSrc * src);
@@ -435,6 +436,11 @@ gst_dvbsrc_class_init (GstDvbSrcClass * klass)
           "stats-reporting-interval",
           "The number of reads before reporting frontend stats",
           0, G_MAXUINT, 100, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, ARG_DVBSRC_TIMEOUT,
+      g_param_spec_uint64 ("timeout", "Timeout",
+          "Post a message after timeout microseconds (0 = disabled)", 0,
+          G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE));
 }
 
 /* initialize the new element
@@ -469,6 +475,7 @@ gst_dvbsrc_init (GstDvbSrc * object, GstDvbSrcClass * klass)
   object->send_diseqc = FALSE;
   object->code_rate_hp = FEC_AUTO;
   object->tune_mutex = g_mutex_new ();
+  object->timeout = DEFAULT_TIMEOUT;
 }
 
 
@@ -606,10 +613,12 @@ gst_dvbsrc_set_property (GObject * _object, guint prop_id,
       object->stats_interval = g_value_get_uint (value);
       object->stats_counter = 0;
       break;
+    case ARG_DVBSRC_TIMEOUT:
+      object->timeout = g_value_get_uint64 (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
-
 }
 
 static void
@@ -670,6 +679,9 @@ gst_dvbsrc_get_property (GObject * _object, guint prop_id,
     case ARG_DVBSRC_STATS_REPORTING_INTERVAL:
       g_value_set_uint (value, object->stats_interval);
       break;
+    case ARG_DVBSRC_TIMEOUT:
+      g_value_set_uint64 (value, object->timeout);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -869,80 +881,64 @@ gst_dvbsrc_plugin_init (GstPlugin * plugin)
 }
 
 static GstBuffer *
-read_device (int fd, int adapter_number, int frontend_number, int size,
-    GstDvbSrc * object)
+gst_dvbsrc_read_device (GstDvbSrc * object, int size)
 {
-  int count = 0;
-  struct pollfd pfd[1];
-  int ret_val = 0;
-  guint attempts = 0;
-  const int TIMEOUT = 100;
-
+  gint count = 0;
+  gint ret_val = 0;
   GstBuffer *buf = gst_buffer_new_and_alloc (size);
+  GstClockTime timeout = object->timeout * GST_USECOND;
 
   g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
-
-  if (fd < 0) {
+  
+  if (object->fd_dvr < 0)
     return NULL;
-  }
-
-  pfd[0].fd = fd;
-  pfd[0].events = POLLIN;
-
-  while (count < size && !object->need_unlock) {
-    ret_val = poll (pfd, 1, TIMEOUT);
-    if (ret_val > 0) {
-      if (pfd[0].revents & POLLIN) {
-        int tmp = 0;
-
-        tmp = read (fd, GST_BUFFER_DATA (buf) + count, size - count);
-        if (tmp < 0) {
-          GST_WARNING
-              ("Unable to read from device: /dev/dvb/adapter%d/dvr%d (%d)",
-              adapter_number, frontend_number, errno);
-          attempts += 1;
-          if (attempts % 10 == 0) {
-            GST_WARNING
-                ("Unable to read from device after %u attempts: /dev/dvb/adapter%d/dvr%d",
-                attempts, adapter_number, frontend_number);
-          }
 
-        } else
-          count = count + tmp;
-      } else {
-        GST_LOG ("revents = %d\n", pfd[0].revents);
-      }
-    } else if (ret_val == 0) {  // poll timeout
-      attempts += 1;
-      GST_INFO ("Reading from device /dev/dvb/adapter%d/dvr%d timedout (%d)",
-          adapter_number, frontend_number, attempts);
-
-      if (attempts % 10 == 0) {
-        GST_WARNING
-            ("Unable to read after %u attempts from device: /dev/dvb/adapter%d/dvr%d (%d)",
-            attempts, adapter_number, frontend_number, errno);
-        gst_element_post_message (GST_ELEMENT_CAST (object),
+  while (count < size) {
+    ret_val = gst_poll_wait (object->poll, timeout);
+    GST_LOG_OBJECT (object, "select returned %d", ret_val);
+    if (G_UNLIKELY (ret_val < 0)) {
+      if (errno == EBUSY)
+	goto stopped;
+      else
+	goto select_error;
+    }
+    else if (G_UNLIKELY (ret_val == 0)) {
+      /* timeout, post element message */
+      gst_element_post_message (GST_ELEMENT_CAST (object),
             gst_message_new_element (GST_OBJECT (object),
                 gst_structure_empty_new ("dvb-read-failure")));
-
-      }
-    } else if (errno == -EINTR) {       // poll interrupted
-      if (attempts % 50 == 0) {
-        gst_buffer_unref (buf);
-        return NULL;
-      };
     }
-
-  }
-
-  if (!count) {
-    gst_buffer_unref (buf);
-    return NULL;
+    else {
+      int nread =
+	read (object->fd_dvr, GST_BUFFER_DATA (buf) + count, size - count);
+
+      if (G_UNLIKELY(nread < 0)) {
+	GST_WARNING_OBJECT
+	  (object, "Unable to read from device: /dev/dvb/adapter%d/dvr%d (%d)",
+	   object->adapter_number, object->frontend_number, errno);
+	gst_element_post_message (GST_ELEMENT_CAST (object),
+	    gst_message_new_element (GST_OBJECT (object),
+                gst_structure_empty_new ("dvb-read-failure")));
+        }
+      else
+	count = count + nread;
+    }
   }
 
   GST_BUFFER_SIZE (buf) = count;
   GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
   return buf;
+
+stopped:
+  GST_DEBUG_OBJECT (object, "stop called");
+  gst_buffer_unref (buf);
+  return NULL;
+
+select_error:
+  GST_ELEMENT_ERROR (object, RESOURCE, READ, (NULL),
+      ("select error %d: %s (%d)", ret_val, g_strerror (errno), errno));
+  gst_buffer_unref (buf);
+  return NULL;
 }
 
 static GstFlowReturn
@@ -965,8 +961,7 @@ gst_dvbsrc_create (GstPushSrc * element, GstBuffer ** buf)
   if (object->fd_dvr > -1) {
     /* --- Read TS from DVR device --- */
     GST_DEBUG_OBJECT (object, "Reading from DVR device");
-    *buf = read_device (object->fd_dvr, object->adapter_number,
-        object->frontend_number, buffer_size, object);
+    *buf = gst_dvbsrc_read_device (object, buffer_size);
     if (*buf != NULL) {
       GstCaps *caps;
 
@@ -975,11 +970,6 @@ gst_dvbsrc_create (GstPushSrc * element, GstBuffer ** buf)
       caps = gst_pad_get_caps (GST_BASE_SRC_PAD (object));
       gst_buffer_set_caps (*buf, caps);
       gst_caps_unref (caps);
-    } else {
-      GST_DEBUG_OBJECT (object, "Failed to read from device");
-      gst_element_post_message (GST_ELEMENT_CAST (object),
-          gst_message_new_element (GST_OBJECT (object),
-              gst_structure_empty_new ("dvb-read-failure")));
     }
 
     if (object->stats_interval != 0 &&
@@ -1043,7 +1033,22 @@ gst_dvbsrc_start (GstBaseSrc * bsrc)
     close (src->fd_frontend);
     return FALSE;
   }
-  src->need_unlock = FALSE;
+  if (!(src->poll = gst_poll_new (TRUE))) {
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
+        ("could not create an fdset: %s (%d)", g_strerror (errno),
+            errno));
+    /* unset filters also */
+    gst_dvbsrc_unset_pes_filters (src);
+    close (src->fd_frontend);
+    return FALSE;
+  }
+  else 
+  {
+    gst_poll_fd_init (&src->poll_fd_dvr);
+    src->poll_fd_dvr.fd = src->fd_dvr;
+    gst_poll_add_fd (src->poll, &src->poll_fd_dvr);
+    gst_poll_fd_ctl_read (src->poll, &src->poll_fd_dvr, TRUE);
+  }
 
   return TRUE;
 }
@@ -1054,6 +1059,11 @@ gst_dvbsrc_stop (GstBaseSrc * bsrc)
   GstDvbSrc *src = GST_DVBSRC (bsrc);
 
   gst_dvbsrc_close_devices (src);
+  if (src->poll) {
+    gst_poll_free(src->poll);
+    src->poll = NULL;
+  }
+
   return TRUE;
 }
 
@@ -1062,7 +1072,7 @@ gst_dvbsrc_unlock (GstBaseSrc * bsrc)
 {
   GstDvbSrc *src = GST_DVBSRC (bsrc);
 
-  src->need_unlock = TRUE;
+  gst_poll_set_flushing (src->poll, TRUE);
   return TRUE;
 }
 
@@ -1071,7 +1081,7 @@ gst_dvbsrc_unlock_stop (GstBaseSrc * bsrc)
 {
   GstDvbSrc *src = GST_DVBSRC (bsrc);
 
-  src->need_unlock = FALSE;
+  gst_poll_set_flushing (src->poll, FALSE);
   return TRUE;
 }
 
diff --git a/sys/dvb/gstdvbsrc.h b/sys/dvb/gstdvbsrc.h
index 273aa2a..e3b5fc4 100644
--- a/sys/dvb/gstdvbsrc.h
+++ b/sys/dvb/gstdvbsrc.h
@@ -23,6 +23,7 @@ G_BEGIN_DECLS
 #define DEFAULT_SYMBOL_RATE 0
 #define DEFAULT_BUFFER_SIZE  8192
 #define DEFAULT_DISEQC_SRC -1   /* disabled */
+#define DEFAULT_TIMEOUT 1000000 /* 1 second */
 
 #define MAX_FILTERS 32
 
@@ -58,6 +59,8 @@ G_BEGIN_DECLS
     int fd_frontend;
     int fd_dvr;
     int fd_filters[MAX_FILTERS];
+    GstPoll *poll;
+    GstPollFD poll_fd_dvr;
 
     guint16 pids[MAX_FILTERS];
     unsigned int freq;
@@ -74,11 +77,11 @@ G_BEGIN_DECLS
     int transmission_mode;
     int hierarchy_information;
     int inversion;
+    guint64 timeout;
 
     GstDvbSrcPol pol;
     guint stats_interval;
     guint stats_counter;
-    gboolean need_unlock;
   };
 
   struct _GstDvbSrcClass
