--- a/mythtv/libs/libmythtv/firewiredevice.cpp
+++ b/mythtv/libs/libmythtv/firewiredevice.cpp
@@ -30,7 +30,7 @@
     m_speed(speed),
     m_last_channel(0),      m_last_crc(0),
     m_buffer_cleared(true), m_open_port_cnt(0),
-    m_lock()
+    m_lock(), m_is_no_input(false), m_error(false)
 {
 }
 
@@ -68,6 +68,24 @@
         QString("RemoveListener() %1").arg(m_listeners.size()));
 }
 
+TSDataListener * FirewireDevice::GetTopListener(void) const
+{
+    if (m_listeners.empty())
+        return NULL;
+    return m_listeners.back();
+}
+
+bool  FirewireDevice::GetAndResetIsNoInput(void)
+{
+    if (!m_is_no_input)
+        return false;
+    QMutexLocker locker(&m_lock);
+    bool ret = m_is_no_input;
+    m_is_no_input = false;
+    return ret;
+}
+
+
 bool FirewireDevice::SetPowerState(bool on)
 {
     QMutexLocker locker(&m_lock);
--- a/mythtv/libs/libmythtv/firewiredevice.h
+++ b/mythtv/libs/libmythtv/firewiredevice.h
@@ -199,6 +199,7 @@
 
     virtual void AddListener(TSDataListener*);
     virtual void RemoveListener(TSDataListener*);
+    bool GetAndResetIsNoInput(void);
 
     // Sets
     virtual bool SetPowerState(bool on);
@@ -208,6 +209,8 @@
     // Gets
     virtual bool IsPortOpen(void) const = 0;
     bool IsSTBBufferCleared(void) const { return m_buffer_cleared; }
+    TSDataListener * GetTopListener(void) const;
+    bool IsError(void) const { return m_error; }
 
     // non-const Gets
     virtual PowerState GetPowerState(void);
@@ -240,6 +243,9 @@
     uint                     m_open_port_cnt;
     vector<TSDataListener*>  m_listeners;
     mutable QMutex           m_lock;
+    // Indicator for trapping "No Input in xxx msec" errors
+    bool                     m_is_no_input;
+    bool                     m_error;
 
     /// Vendor ID + Model ID to FirewireDevice STB model string
     static QMap<uint64_t,QString> s_id_to_model;
--- a/mythtv/libs/libmythtv/firewirerecorder.cpp
+++ b/mythtv/libs/libmythtv/firewirerecorder.cpp
@@ -27,21 +27,28 @@
 
 bool FirewireRecorder::Open(void)
 {
-    if (!isopen)
-    {
-        isopen = channel->GetFirewireDevice()->OpenPort();
-        ResetForNewFile();
-    }
+    // Note that the firewire device can be opened multiple
+    // times without being closed in between. The close
+    // keeps track of this and actually only closes when
+    // the number of opens gets down to 0
+
+    isopen = channel->GetFirewireDevice()->OpenPort();
+
+    // ResetForNewFile was called from here. Moved to run()
+    // because Open() can be called more than once per file
+    // and we should call ResetForNewFile only once per file.
+    // -- Peter Bennett 2012-04-06
+
     return isopen;
 }
 
-void FirewireRecorder::Close(void)
+bool FirewireRecorder::Close(void)
 {
-    if (isopen)
-    {
-        channel->GetFirewireDevice()->ClosePort();
-        isopen = false;
-    }
+    // Close decrements the open count and may leave
+    // the device open if the open count is not zero.
+    channel->GetFirewireDevice()->ClosePort();
+    isopen = channel->GetFirewireDevice()->IsPortOpen();
+    return isopen;
 }
 
 void FirewireRecorder::StartStreaming(void)
@@ -56,42 +63,163 @@
 
 void FirewireRecorder::run(void)
 {
-    LOG(VB_RECORD, LOG_INFO, LOC + "run");
-
-    if (!Open())
-    {
-        _error = "Failed to open firewire device";
-        LOG(VB_GENERAL, LOG_ERR, LOC + _error);
-        return;
-    }
-
-    {
-        QMutexLocker locker(&pauseLock);
-        request_recording = true;
-        recording = true;
-        recordingWait.wakeAll();
-    }
+    bool is_no_input = false;
+    bool must_save_listeners = false;
+    vector<TSDataListener*>  saved_listeners;
+    int number_opens = 1;
+    time_t time_last_reset = 0;
+    bool done_wakeAll = false;
+    bool done_ResetForNewFile = false;
+
+    LOG(VB_RECORD, LOG_INFO, LOC + "run " + curRecording->GetTitle());
+
+    // This loop contains logic to handle a firewire no input
+    // error. When the firewire device reports no input
+    // received for 400 msec, this is indication of a problem
+    // that does not go away. To fix the error we close the
+    // firewire port and open it again in this loop.
+    // -- Peter Bennett 2012-04-05
+
+    do {
+        while(number_opens > 0)
+        {
+            if (!Open())
+            {
+                _error = "Failed to open firewire device";
+                LOG(VB_GENERAL, LOG_ERR, LOC + _error);
+                return;
+            }
+            number_opens--;
+        }
+        // Moved here from Open() because Open() can be called more
+        // than once per file and we should call ResetForNewFile only
+        // once per file
+        // -- Peter Bennett 2012-04-06
+        if (!done_ResetForNewFile)
+        {
+            ResetForNewFile();
+            done_ResetForNewFile = true;
+        }
+        if (!done_wakeAll)
+        {
+            QMutexLocker locker(&pauseLock);
+            request_recording = true;
+            recording = true;
+            recordingWait.wakeAll();
+            done_wakeAll = true;
+        }
+        else
+        {
+            request_recording = true;
+            recording = true;
+        }
 
-    StartStreaming();
+        if (saved_listeners.empty())
+            StartStreaming();
+        else
+        {
+            // Restore Listeners
+            int count = 0;
+            TSDataListener* listener;
+            listener = saved_listeners.back();
+            while (listener!=NULL)
+            {
+                LOG(VB_RECORD, LOG_INFO, LOC + QString("Restoring listener %1").arg(++count));
+                channel->GetFirewireDevice()->AddListener(listener);
+                saved_listeners.pop_back();
+                if (saved_listeners.empty())
+                    listener = NULL;
+                else
+                    listener = saved_listeners.back();
+            }
+        }
+        // If adding listeners caused a failure, cancel recording
+        if (channel->GetFirewireDevice()->IsError()) {
+            _error = "Failed to add listeners to firewire device";
+            LOG(VB_GENERAL, LOG_ERR, LOC + _error);
+        }
+        while (IsRecordingRequested() && !IsErrored())
+        {
+            if (is_no_input)
+            {
+                time_t now = time(NULL);
+                time_t elapsed = now - time_last_reset;
+                // if less than 30 seconds since last reset,
+                // ignore the error and let bus reset maybe fix it
+                if (elapsed <= 30) {
+                    LOG(VB_RECORD, LOG_ERR, LOC + QString("Repeated Firewire No Input Error - Try Bus Reset."));
+                    is_no_input = false;
+                }
+                // if between 30 seconds and 5 minutes since
+                // last reset - we have a persistent error -
+                // fail the recording
+                if (elapsed > 30 && elapsed <= 300) {
+                    LOG(VB_GENERAL, LOG_ERR, LOC + QString("Repeated Firewire No Input Error - Recording Fails."));
+                    is_no_input = false;
+                    _error = "Repeated Firewire No Input Error - Recording Fails.";
+                    request_recording = false;
+                }
+                // if more than 5 minutes since last reset,
+                // or this is the first reset, proceed with reset
+                if (elapsed > 300) {
+                    LOG(VB_GENERAL, LOG_ERR, LOC + QString("Firewire No Input Error - Resetting device."));
+                    request_recording = false;
+                    is_no_input = false;
+                    must_save_listeners = true;
+                    time_last_reset = now;
+                }
+            }
+            if (PauseAndWait())
+                continue;
 
-    while (IsRecordingRequested() && !IsErrored())
-    {
-        if (PauseAndWait())
-            continue;
+            if (!IsRecordingRequested())
+                break;
 
-        if (!IsRecordingRequested())
-            break;
+            {   // sleep 0.25 seconds unless StopRecording() or Unpause() is called,
+                // just to avoid running this too often.
+                // Changed from 1 second to 250ms to reduce delay in recovering
+                // from "No Input in 400 msec" errors  - Peter Bennett 5/3/2012
+                QMutexLocker locker(&pauseLock);
+                if (!request_recording || request_pause)
+                    continue;
+                unpauseWait.wait(&pauseLock, 250);
+            }
+
+            // Look at firewire device to see if it is having
+            // an error. The call GetAndResetIsNoInput
+            // resets the indicator in thread safe way so that
+            // only one thread will handle repairing
+            // the broken firewire connection.
+            if (!must_save_listeners && channel->GetFirewireDevice()->GetAndResetIsNoInput())
+                is_no_input = true;
+        }
 
-        {   // sleep 1 seconds unless StopRecording() or Unpause() is called,
-            // just to avoid running this too often.
-            QMutexLocker locker(&pauseLock);
-            if (!request_recording || request_pause)
-                continue;
-            unpauseWait.wait(&pauseLock, 1000);
+        if (must_save_listeners)
+        {
+            // Remove And Save Listeners. This may not be thread
+            // safe if others are concurrently adding or removing
+            // listeners. That should not happen.
+            int count = 0;
+            TSDataListener* listener;
+            listener = channel->GetFirewireDevice()->GetTopListener();
+            while (listener != NULL)
+            {
+                LOG(VB_RECORD, LOG_INFO, LOC + QString("Saving listener %1").arg(++count));
+                saved_listeners.push_back(listener);
+                channel->GetFirewireDevice()->RemoveListener(listener);
+                listener = channel->GetFirewireDevice()->GetTopListener();
+            }
+            must_save_listeners = false;
+            number_opens = 0;
+            while(Close())
+                number_opens++;
+            LOG(VB_RECORD, LOG_INFO, LOC + QString("Number of closes: %1").arg(++number_opens));
         }
     }
+    while(!saved_listeners.empty());
 
     StopStreaming();
+    Close();
     FinishRecording();
 
     QMutexLocker locker(&pauseLock);
--- a/mythtv/libs/libmythtv/firewirerecorder.h
+++ b/mythtv/libs/libmythtv/firewirerecorder.h
@@ -34,7 +34,7 @@
 
     // Commands
     bool Open(void);
-    void Close(void);
+    bool Close(void);
 
     void StartStreaming(void);
     void StopStreaming(void);
--- a/mythtv/libs/libmythtv/firewiresignalmonitor.cpp
+++ b/mythtv/libs/libmythtv/firewiresignalmonitor.cpp
@@ -152,11 +152,86 @@
 
     FirewireDevice *dev = lchan->GetFirewireDevice();
 
-    dev->OpenPort();
-    dev->AddListener(this);
+    // This loop contains logic to handle a firewire no input
+    // error. When the firewire device reports no input
+    // received for 400 msec, this is indication of a problem
+    // that does not go away. To fix the error we close the
+    // firewire port and open it again in this loop.
+    // -- Peter Bennett 2012-04-05
+
+    bool is_no_input = false;
+    bool must_save_listeners = false;
+    vector<TSDataListener*>  saved_listeners;
+    int number_opens = 1;
+
+    do {
+        while(number_opens > 0)
+        {
+            dev->OpenPort();
+            number_opens--;
+        }
+        if (saved_listeners.empty())
+            dev->AddListener(this);
+        else
+        {
+            // Restore Listeners
+            int count = 0;
+            TSDataListener* listener;
+            listener = saved_listeners.back();
+            while (listener!=NULL)
+            {
+                LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Restoring listener %1").arg(++count));
+                dev->AddListener(listener);
+                saved_listeners.pop_back();
+                if (saved_listeners.empty())
+                    listener = NULL;
+                else
+                    listener = saved_listeners.back();
+            }
+        }
+        while (dtvMonitorRunning && GetStreamData() && !must_save_listeners)
+        {
+            if (is_no_input)
+            {
+                // proceed with reset
+                LOG(VB_GENERAL, LOG_ERR, LOC + QString("Firewire No Input Error - Resetting device."));
+                is_no_input = false;
+                must_save_listeners = true;
+            }
+            usleep(10000);
+
+            // Look at firewire device to see if it is having
+            // an error. The call GetAndResetIsNoInput
+            // resets the indicator in thread safe way so that
+            // only one thread will handle repairing
+            // the broken firewire connection.
+            if (!must_save_listeners && dev->GetAndResetIsNoInput())
+                is_no_input = true;
+        }
+        if (must_save_listeners)
+        {
+            // Remove And Save Listeners. This may not be thread
+            // safe if others are concurrently adding or removing
+            // listeners. That should not happen.
+            int count = 0;
+            TSDataListener* listener;
+            listener = dev->GetTopListener();
+            while (listener != NULL)
+            {
+                LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Saving listener %1").arg(++count));
+                saved_listeners.push_back(listener);
+                dev->RemoveListener(listener);
+                listener = dev->GetTopListener();
+            }
+            must_save_listeners = false;
+            number_opens = 0;
+            while(dev->ClosePort())
+                number_opens++;
+            LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Number of closes: %1").arg(++number_opens));
+        }
+    }
+    while(!saved_listeners.empty());
 
-    while (dtvMonitorRunning && GetStreamData())
-        usleep(10000);
 
     LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- shutdown ");
 
--- a/mythtv/libs/libmythtv/linuxfirewiredevice.cpp
+++ b/mythtv/libs/libmythtv/linuxfirewiredevice.cpp
@@ -274,6 +274,7 @@
         LOG(VB_GENERAL, LOG_ERR, LOC + QString("Not an STB"));
 
         mlocker.unlock();
+        locker.unlock();
         ClosePort();
 
         return false;
@@ -352,9 +353,11 @@
 
     if (!m_listeners.empty())
     {
-        OpenNode();
-        OpenAVStream();
-        StartStreaming();
+        m_error = !OpenNode();
+        if (!m_error)
+            m_error = !OpenAVStream();
+        if (!m_error)
+            m_error = !StartStreaming();
     }
 }
 
@@ -590,6 +593,7 @@
 {
     LOG(VB_RECORD, LOG_INFO, LOC + "RunPortHandler -- start");
     m_lock.lock();
+    m_is_no_input = false;
     LOG(VB_RECORD, LOG_INFO, LOC + "RunPortHandler -- got first lock");
     m_priv->is_port_handler_running = true;
     m_priv->port_handler_wait.wakeAll();
@@ -644,6 +648,12 @@
 
             LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No Input in %1 msec...")
                     .arg(m_priv->no_data_cnt * kNoDataTimeout));
+            // Set indicator for endless no data errors
+            // so that FirewireRecorder can reset the device
+            if (m_priv->no_data_cnt == 8)
+            {
+                m_is_no_input = true;
+            }
         }
 
         // Confirm that we won't block, now that we have the lock...
