Index: libs/libmythtv/firewirechannel.cpp
===================================================================
--- libs/libmythtv/firewirechannel.cpp	(revision 12229)
+++ libs/libmythtv/firewirechannel.cpp	(working copy)
@@ -1,314 +1,127 @@
 /**
  *  FirewireChannel
  *  Copyright (c) 2005 by Jim Westfall
- *  SA3250HD support Copyright (c) 2005 by Matt Porter
- *  SA4200HD/Alternate 3250 support Copyright (c) 2006 by Chris Ingrassia
  *  Distributed as part of MythTV under GPL v2 and later.
  */
 
-
-#include <iostream>
+// MythTV headers
 #include "mythcontext.h"
 #include "firewirechannel.h"
+#include "linuxfirewiredevice.h"
 
 class TVRec;
 
-#define LOC QString("FireChan: ")
-#define LOC_ERR QString("FireChan, Error: ")
+#define LOC QString("FireChan(%1): ").arg(GetDevice())
+#define LOC_WARN QString("FireChan(%1), Warning: ").arg(GetDevice())
+#define LOC_ERR QString("FireChan(%1), Error: ").arg(GetDevice())
 
-#ifndef AVC1394_PANEL_COMMAND_PASS_THROUGH
-#define AVC1394_PANEL_COMMAND_PASS_THROUGH     0x000007C00
-#endif
-
-#ifndef AVC1394_PANEL_OPERATION_0
-#define AVC1394_PANEL_OPERATION_0              0x000000020
-#endif
-
-#define DCT6200_CMD0  (AVC1394_CTYPE_CONTROL | \
-                       AVC1394_SUBUNIT_TYPE_PANEL | \
-                       AVC1394_SUBUNIT_ID_0 | \
-                       AVC1394_PANEL_COMMAND_PASS_THROUGH | \
-                       AVC1394_PANEL_OPERATION_0)
-
-// SA3250HD defines
-#define AVC1394_SA3250_OPERAND_KEY_PRESS	0xE7
-#define AVC1394_SA3250_OPERAND_KEY_RELEASE	0x67
-
-#define SA3250_CMD0   (AVC1394_CTYPE_CONTROL | \
-                       AVC1394_SUBUNIT_TYPE_PANEL | \
-                       AVC1394_SUBUNIT_ID_0 | \
-                       AVC1394_PANEL_COMMAND_PASS_THROUGH)
-#define SA3250_CMD1   (0x04 << 24)
-#define SA3250_CMD2    0xff000000
-
-// power defines
-#define AVC1394_CMD_OPERAND_POWER_STATE        0x7F
-#define STB_POWER_STATE   (AVC1394_CTYPE_STATUS | \
-                           AVC1394_SUBUNIT_TYPE_UNIT | \
-                           AVC1394_SUBUNIT_ID_IGNORE | \
-                           AVC1394_COMMAND_POWER | \
-                           AVC1394_CMD_OPERAND_POWER_STATE)
-
-#define STB_POWER_ON      (AVC1394_CTYPE_CONTROL | \
-                           AVC1394_SUBUNIT_TYPE_UNIT | \
-                           AVC1394_SUBUNIT_ID_IGNORE | \
-                           AVC1394_COMMAND_POWER | \
-                           AVC1394_CMD_OPERAND_POWER_ON)
-
-static bool is_supported(const QString &model)
+LinuxFirewireChannel::LinuxFirewireChannel(
+    FireWireDBOptions firewire_opts, TVRec *parent) :
+    FirewireChannelBase(parent),
+    fw_opts(firewire_opts),
+    device(new LinuxFirewireDevice(
+               fw_opts.port, fw_opts.node, fw_opts.speed,
+               LinuxFirewireDevice::kConnectionP2P ==
+               (uint) fw_opts.connection)),
+    current_channel(0),
+    is_port_open(false)
 {
-    return ((model == "DCT-6200") ||
-            (model == "SA3250HD") ||
-	    (model == "SA4200HD"));
 }
 
-FirewireChannel::FirewireChannel(FireWireDBOptions firewire_opts,
-                                 TVRec *parent)
-    : FirewireChannelBase(parent), fw_opts(firewire_opts), fwhandle(NULL)
+LinuxFirewireChannel::~LinuxFirewireChannel(void)
 {
-}
-
-FirewireChannel::~FirewireChannel(void)
-{
     Close();
 }
 
-bool FirewireChannel::SetChannelByNumber(int channel)
+bool LinuxFirewireChannel::Retune(void)
 {
-    // Change channel using internal changer
+    VERBOSE(VB_CHANNEL, LOC + "Retune()");
 
-    if (!is_supported(fw_opts.model))
+    if (FirewireDevice::kAVCPowerOff == GetPowerState())
     {
         VERBOSE(VB_IMPORTANT, LOC_ERR +
-                QString("Model: '%1' ").arg(fw_opts.model) +
-                "is not supported by internal channel changer.");
+                "STB is turned off, must be on to retune.");
+
         return false;
     }
 
-    int dig[3];
-    dig[0] = (channel % 1000) / 100;
-    dig[1] = (channel % 100)  / 10;
-    dig[2] = (channel % 10);
+    if (current_channel)
+        return SetChannelByNumber(current_channel);
 
-    if (fw_opts.model == "DCT-6200")
-    {
-        VERBOSE(VB_CHANNEL, LOC +
-                QString("Channel1: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
-                .arg(dig[0]).arg(dig[1])
-                .arg(dig[2]).arg(DCT6200_CMD0 | dig[0], 0, 16)
-                .arg(DCT6200_CMD0 | dig[1], 0, 16)
-                .arg(DCT6200_CMD0 | dig[2], 0, 16));
+    return false;
+}
 
-        for (uint i = 0; i < 3 ;i++)
-        {
-            quadlet_t cmd[2] =  { DCT6200_CMD0 | dig[i], 0x0, };
-            if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 2, 1))
-            {
-                 VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
-                 return false;
-            }
-            usleep(500000);
-        }
-    }
-    else if (fw_opts.model == "SA3250HD")
+bool LinuxFirewireChannel::SetChannelByNumber(int channel)
+{
+    current_channel = channel;
+
+    if (FirewireDevice::kAVCPowerOff == GetPowerState())
     {
-        dig[0] |= 0x30;
-        dig[1] |= 0x30;
-        dig[2] |= 0x30;
+        VERBOSE(VB_IMPORTANT, LOC_WARN +
+                "STB is turned off, must be on to set channel.");
 
-        quadlet_t cmd[3] =
-        {
-            SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS, 
-            SA3250_CMD1 | (dig[2] << 16) | (dig[1] << 8) | dig[0],
-            SA3250_CMD2,
-        };
+        SetSIStandard("mpeg");
+        SetCachedATSCInfo(QString("%1-1").arg(channel));
 
-        VERBOSE(VB_CHANNEL, LOC +
-                QString("Channel2: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
-                .arg(dig[0] & 0xf).arg(dig[1] & 0xf)
-                .arg(dig[2] & 0xf)
-                .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
-                .arg(cmd[2], 0, 16));
-
-        if(!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
-        {
-            VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
-            return false;
-        }
-
-        cmd[0] = SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;
-        cmd[1] = SA3250_CMD1 | (dig[0] << 16) | (dig[1] << 8) | dig[2];
-        cmd[2] = SA3250_CMD2;
-
-        VERBOSE(VB_CHANNEL, LOC +
-                QString("Channel3: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
-                .arg(dig[0] & 0xf).arg(dig[1] & 0xf)
-                .arg(dig[2] & 0xf)
-                .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
-                .arg(cmd[2], 0, 16));
-
-        if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
-        {
-            VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
-            return false;
-        }
+        return true; // signal monitor will call retune later...
     }
-    else if (fw_opts.model == "SA4200HD")
-    {
-        quadlet_t cmd[3] =
-        {
-            SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
-            SA3250_CMD1 | (channel << 8),
-            SA3250_CMD2,
-        };
 
-        VERBOSE(VB_CHANNEL, LOC +
-                QString("SA4200Channel: %1 cmds: 0x%2 0x%3 0x%4")
-                .arg(channel).arg(cmd[0], 0, 16)
-                .arg(cmd[1], 0, 16)
-                .arg(cmd[2], 0, 16));
+    if (!device->SetChannel(fw_opts.model, channel))
+        return false;
 
-        if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
-        {
-            VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
-            return false;
-        }
-    }
+    SetSIStandard("mpeg");
+    SetCachedATSCInfo(QString("%1-1").arg(channel));
 
     return true;
 }
 
-bool FirewireChannel::OpenFirewire(void)
+bool LinuxFirewireChannel::OpenFirewire(void)
 {
-    if (!is_supported(fw_opts.model))
+    VERBOSE(VB_IMPORTANT, LOC + "OpenFirewire()");
+
+    if (is_port_open)
+        return true;
+
+    if (!LinuxFirewireDevice::IsSTBSupported(fw_opts.model))
     {
         VERBOSE(VB_IMPORTANT, LOC_ERR +
                 QString("Model: '%1' ").arg(fw_opts.model) +
                 "is not supported by internal channel changer.");
-        return false;
-    }
 
-    // Open channel
-    fwhandle = raw1394_new_handle_on_port(fw_opts.port);
-    if (!fwhandle)
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle " +
-                QString("for port: %1").arg(fw_opts.port));
         return false;
     }
 
-    VERBOSE(VB_CHANNEL, LOC + "Allocated raw1394 handle " +
-            QString("for port %1").arg(fw_opts.port));
-
-    // verify node looks like a stb
-    if (!avc1394_check_subunit_type(fwhandle, fw_opts.node,
-                                    AVC1394_SUBUNIT_TYPE_TUNER))
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit "
-                "type tuner.").arg(fw_opts.node));
-        CloseFirewire();
+    if (!device->OpenPort())
         return false;
-    }
 
-    if (!avc1394_check_subunit_type(fwhandle, fw_opts.node, 
-                                    AVC1394_SUBUNIT_TYPE_PANEL))
+    if (!device->IsSTB())
     {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit "
-                "type panel.").arg(fw_opts.node));
-        CloseFirewire();
+        device->ClosePort();
         return false;
     }
 
-    // check power, power on if off
-    if (GetPowerState() == Off)
-    {
-        quadlet_t *rval, response, cmd = STB_POWER_ON;
-        VERBOSE(VB_IMPORTANT, LOC + QString("Powering on (cmd: 0x%1)")
-                                            .arg(cmd, 0, 16));
-        rval = avc1394_transaction_block(fwhandle, fw_opts.node, &cmd, 1, 1);
-        if (rval)
-        {
-            response = rval[0];
+    is_port_open = true;
 
-            if (AVC1394_MASK_RESPONSE(response) == AVC1394_RESPONSE_ACCEPTED)
-            {
-                VERBOSE(VB_IMPORTANT, LOC + QString("Power on cmd successful "
-                                                    "(0x%1)")
-                                                    .arg(response, 0, 16));
-                // allow some time for the stb to power on
-                sleep(3);
-                if (GetPowerState() == Off)
-                {
-                    VERBOSE(VB_IMPORTANT, LOC + "STB is still off!?");
-                    return false;
-                }
-                return true;
-            }
-            else
-            {
-                VERBOSE(VB_IMPORTANT, LOC + QString("Power on cmd failed "
-                                                    "(0x%1)")
-                                                    .arg(response, 0, 16));
-                return false;
-            }
-        }
-        else
-        {
-            VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)");
-            return false;
-        }
-    }
     return true;
 }
 
-void FirewireChannel::CloseFirewire(void)
+void LinuxFirewireChannel::CloseFirewire(void)
 {
-    VERBOSE(VB_CHANNEL, LOC + "Releasing raw1394 handle");
-    raw1394_destroy_handle(fwhandle);
+    VERBOSE(VB_IMPORTANT, LOC + "CloseFirewire()");
+
+    if (!is_port_open)
+        return;
+
+    device->ClosePort();
+    is_port_open = false;
 }
 
-FirewireChannel::PowerState FirewireChannel::GetPowerState(void)
+bool LinuxFirewireChannel::SetPowerState(bool on)
 {
-    quadlet_t *rval, response, cmd = STB_POWER_STATE;
+    return device->SetPowerState(on);
+}
 
-    VERBOSE(VB_CHANNEL, LOC + QString("Requesting STB Power State (cmd: 0x%1)")
-                                      .arg(STB_POWER_STATE, 0, 16));
-    rval = avc1394_transaction_block(fwhandle, fw_opts.node, &cmd, 1, 1);
-
-    if (rval)
-    {
-        response = rval[0];
-
-        if (AVC1394_MASK_RESPONSE(response) == AVC1394_RESPONSE_IMPLEMENTED)
-        {
-            if ((response & 0xFF) == AVC1394_CMD_OPERAND_POWER_ON)
-            {
-                VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: ON (0x%1)")
-                                                  .arg(response, 0, 16));
-                return On;
-            }
-            else if ((response & 0xFF) == AVC1394_CMD_OPERAND_POWER_OFF)
-            {
-                VERBOSE(VB_IMPORTANT, LOC + QString("STB Power State: OFF " 
-                                                    "(0x%1)")
-                                                    .arg(response, 0, 16));
-                return Off;
-            }
-            else
-            {
-                VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: "
-                                                  "Unknown Response (0x%1)")
-                                                  .arg(response, 0, 16));
-                return Failed;
-            }
-        }
-        else
-        {
-            VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: Failed (0x%1)")
-                                              .arg(response, 0, 16));
-            return Failed;
-        }
-    }
-    VERBOSE(VB_CHANNEL, LOC + "Failed to get STB Power State");
-    return Failed;
+FirewireDevice::PowerState LinuxFirewireChannel::GetPowerState(void) const
+{
+    return device->GetPowerState();
 }
Index: libs/libmythtv/firewirerecorderbase.h
===================================================================
--- libs/libmythtv/firewirerecorderbase.h	(revision 12229)
+++ libs/libmythtv/firewirerecorderbase.h	(working copy)
@@ -12,6 +12,9 @@
 #include "tspacket.h"
 #include "streamlisteners.h"
 
+class TVRec;
+class FirewireChannelBase;
+
 /** \class FirewireRecorderBase
  *  \brief This is a specialization of DTVRecorder used to
  *         handle DVB and ATSC streams from a firewire input.
@@ -25,8 +28,7 @@
     friend class TSPacketProcessor; 
 
   public:
-    FirewireRecorderBase(TVRec *rec);
-    ~FirewireRecorderBase(); 
+    virtual ~FirewireRecorderBase();
  
     // Commands 
     void StartRecording(void);
@@ -41,17 +43,23 @@
     void SetStreamData(MPEGStreamData*);
 
     // Gets 
-    MPEGStreamData* StreamData(void) { return _mpeg_stream_data; }
+    MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; }
 
     // MPEG Single Program
     void HandleSingleProgramPAT(ProgramAssociationTable*); 
     void HandleSingleProgramPMT(ProgramMapTable*);
 
+    // Factory
+    static FirewireRecorderBase *Init(
+        TVRec *rec, FirewireChannelBase *channel);
+
+  protected:
+    FirewireRecorderBase(TVRec *rec);
+
   private:
     virtual void Close() = 0;
-    virtual void start() = 0;
-    virtual void stop() = 0;
-    virtual bool grab_frames() = 0;
+    virtual void StartStreaming(void) = 0;
+    virtual void StopStreaming(void) = 0;
 
     MPEGStreamData  *_mpeg_stream_data; 
     TSStats          _ts_stats;   
Index: libs/libmythtv/firewirechannelbase.h
===================================================================
--- libs/libmythtv/firewirechannelbase.h	(revision 12229)
+++ libs/libmythtv/firewirechannelbase.h	(working copy)
@@ -8,43 +8,50 @@
 #ifndef LIBMYTHTV_FIREWIRECHANNELBASE_H
 #define LIBMYTHTV_FIREWIRECHANNELBASE_H
 
-#include <qstring.h>
-#include "tv_rec.h"
-#include "channelbase.h"
+#include "dtvchannel.h"
+#include "firewiredevice.h"
 
-#include "mythconfig.h"
+class TVRec;
+class FireWireDBOptions;
 
-namespace AVS
+class FirewireChannelBase : public DTVChannel
 {
-  class AVCDeviceController;
-  class AVCDevice;
-}
-
-class FirewireChannelBase : public ChannelBase
-{
   public:
-    FirewireChannelBase(TVRec *parent)   
-        : ChannelBase(parent), isopen(false) { } 
-    ~FirewireChannelBase() { Close(); }
+    // Commands
+    virtual bool Open(void);
+    virtual void Close(void);
+    virtual bool SwitchToInput(const QString &inputname, const QString &chan);
+    virtual bool SwitchToInput(int newcapchannel, bool setstarting)
+        { (void)newcapchannel; (void)setstarting; return false; }
 
-    bool Open(void);
-    void Close(void);
+    virtual bool TuneMultiplex(uint /*mplexid*/, QString /*inputname*/)
+        { return false; }
+    virtual bool Tune(const DTVMultiplex &/*tuning*/, QString /*inputname*/)
+        { return false; }
+    virtual bool Retune(void)
+        { return false; }
 
     // Sets
-    bool SetChannelByString(const QString &chan);
+    virtual bool SetChannelByString(const QString &chan);
     virtual bool SetChannelByNumber(int channel) = 0;
+    virtual bool SetPowerState(bool /*on*/) = 0;
 
     // Gets
-    bool IsOpen(void) const { return isopen; }
+    virtual bool IsOpen(void) const { return isopen; }
+    virtual FirewireDevice::PowerState GetPowerState(void) const = 0;
 
-    // Commands
-    bool SwitchToInput(const QString &inputname, const QString &chan);
-    bool SwitchToInput(int newcapchannel, bool setstarting)
-        { (void)newcapchannel; (void)setstarting; return false; }
+    // Factory method
+    static FirewireChannelBase *Init(
+        const FireWireDBOptions &firewire_opts, TVRec *parent);
 
+  protected:
+    FirewireChannelBase(TVRec *parent) :
+        DTVChannel(parent), isopen(false) { }
+    ~FirewireChannelBase() { Close(); }
+
   private:
-    virtual bool OpenFirewire() = 0;
-    virtual void CloseFirewire() = 0;
+    virtual bool OpenFirewire(void) = 0;
+    virtual void CloseFirewire(void) = 0;
 
   protected:
     bool isopen;
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 12229)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -380,6 +380,8 @@
     using_firewire  {
         HEADERS += firewirechannelbase.h       firewirerecorderbase.h
         SOURCES += firewirechannelbase.cpp     firewirerecorderbase.cpp
+        HEADERS += firewiresignalmonitor.h     firewiredevice.h
+        SOURCES += firewiresignalmonitor.cpp
 
         macx {
             HEADERS += darwinfirewirechannel.h       darwinfirewirerecorder.h
@@ -391,6 +393,8 @@
         !macx {
             HEADERS += firewirechannel.h       firewirerecorder.h
             SOURCES += firewirechannel.cpp     firewirerecorder.cpp
+            HEADERS += linuxfirewiredevice.h
+            SOURCES += linuxfirewiredevice.cpp
         }
 
         DEFINES += USING_FIREWIRE
Index: libs/libmythtv/darwinfirewirerecorder.cpp
===================================================================
--- libs/libmythtv/darwinfirewirerecorder.cpp	(revision 12229)
+++ libs/libmythtv/darwinfirewirerecorder.cpp	(working copy)
@@ -11,15 +11,16 @@
 #undef always_inline
 #include <AVCVideoServices/AVCVideoServices.h>
 
-DarwinFirewireRecorder::DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner)
- : FirewireRecorderBase(rec),
-   capture_device(
-       dynamic_cast<DarwinFirewireChannel*>(tuner)->GetAVCDevice()
-   ),
-   message_log(NULL),
-   video_stream(NULL),
-   isopen(false)
-{;}
+DarwinFirewireRecorder::DarwinFirewireRecorder(
+    TVRec *rec, DarwinFirewireChannel *channel) :
+    FirewireRecorderBase(rec),
+    capture_device(channel->GetAVCDevice()),
+    message_log(NULL),
+    video_stream(NULL),
+    isopen(false)
+{
+    SetStreamData(new MPEGStreamData(1, true));
+}
 
 DarwinFirewireRecorder::~DarwinFirewireRecorder()
 {
@@ -196,32 +197,14 @@
     this->message_log = 0;
 }
 
-void DarwinFirewireRecorder::start()
+void DarwinFirewireRecorder::StartStreaming(void)
 {
     VERBOSE(VB_RECORD, "Firewire: Starting video stream");
     this->capture_device->StartAVCDeviceStream(this->video_stream);
 }
 
-void DarwinFirewireRecorder::stop()
+void DarwinFirewireRecorder::StopStreaming(void)
 {
     VERBOSE(VB_RECORD, "Firewire: Stopping video stream");
     this->capture_device->StopAVCDeviceStream(this->video_stream);
 }
-
-bool DarwinFirewireRecorder::grab_frames()
-{
-    usleep(1000000 / 2);  // 2 times a second
-    return true;
-}        
-
-void DarwinFirewireRecorder::SetOption(const QString &name, const QString &value) 
-{
-    (void)name;
-    (void)value;
-}
-
-void DarwinFirewireRecorder::SetOption(const QString &name, int value) 
-{
-    (void)name;
-    (void)value;
-}
Index: libs/libmythtv/signalmonitor.h
===================================================================
--- libs/libmythtv/signalmonitor.h	(revision 12229)
+++ libs/libmythtv/signalmonitor.h	(working copy)
@@ -285,6 +285,7 @@
     return (CardUtil::IsDVBCardType(cardtype) ||
             (cardtype.upper() == "HDTV")      ||
             (cardtype.upper() == "HDHOMERUN") ||
+            (cardtype.upper() == "FIREWIRE")  ||
             (cardtype.upper() == "FREEBOX"));
 }
 
Index: libs/libmythtv/firewirerecorderbase.cpp
===================================================================
--- libs/libmythtv/firewirerecorderbase.cpp	(revision 12229)
+++ libs/libmythtv/firewirerecorderbase.cpp	(working copy)
@@ -5,21 +5,48 @@
  */
 
 // MythTV includes
+#include "mythconfig.h" // for CONFIG_DARWIN
 #include "firewirerecorderbase.h"
 #include "mythcontext.h"
 #include "mpegtables.h" 
 #include "mpegstreamdata.h"
 #include "tv_rec.h"
 
+#ifdef CONFIG_DARWIN
+#   include "darwinfirewirechannel.h"
+#   include "darwinfirewirerecorder.h"
+#else 
+#   include "firewirechannel.h"
+#   include "firewirerecorder.h"
+#   include "linuxfirewiredevice.h"
+#endif 
+
 #define LOC QString("FireRecBase: ") 
 #define LOC_ERR QString("FireRecBase, Error: ")
 
 const int FirewireRecorderBase::kTimeoutInSeconds = 15;
 
+FirewireRecorderBase *FirewireRecorderBase::Init(
+    TVRec *rec, FirewireChannelBase *channel)
+{
+#ifdef CONFIG_DARWIN
+    DarwinFirewireChannel *dfch =
+        dynamic_cast<DarwinFirewireChannel*>(channel);
+    if (dfch)
+        return new DarwinFirewireRecorder(rec, channel);
+#else
+    LinuxFirewireChannel *lfch =
+        dynamic_cast<LinuxFirewireChannel*>(channel);
+    if (lfch)
+        return new LinuxFirewireRecorder(rec, lfch);
+#endif
+
+    return NULL;
+}
+
 FirewireRecorderBase::FirewireRecorderBase(TVRec *rec)
     : DTVRecorder(rec), _mpeg_stream_data(NULL)
 {
-    SetStreamData(new MPEGStreamData(1, true));
 }
 
 FirewireRecorderBase::~FirewireRecorderBase()
@@ -39,20 +66,15 @@
     _request_recording = true;
     _recording = true;
    
-    start();
+    StartStreaming();
 
-    while(_request_recording) {
-       if (PauseAndWait())
-           continue;
-
-       if (!grab_frames())
-       {
-           _error = true;
-           return;
-       }
+    while (_request_recording)
+    {
+        if (!PauseAndWait())
+            usleep(250 * 1000);
     }        
     
-    stop();
+    StopStreaming();
     FinishRecording();
 
     _recording = false;
@@ -67,23 +89,23 @@
         return; 
  
     if (tspacket.HasAdaptationField()) 
-        StreamData()->HandleAdaptationFieldControl(&tspacket); 
+        GetStreamData()->HandleAdaptationFieldControl(&tspacket); 
  
     if (tspacket.HasPayload()) 
     { 
         const unsigned int lpid = tspacket.PID(); 
  
         // Pass or reject packets based on PID, and parse info from them 
-        if (lpid == StreamData()->VideoPIDSingleProgram()) 
+        if (lpid == GetStreamData()->VideoPIDSingleProgram()) 
         { 
             _buffer_packets = !FindMPEG2Keyframes(&tspacket); 
             BufferedWrite(tspacket); 
         } 
-        else if (StreamData()->IsAudioPID(lpid)) 
+        else if (GetStreamData()->IsAudioPID(lpid)) 
             BufferedWrite(tspacket); 
-        else if (StreamData()->IsListeningPID(lpid)) 
-            StreamData()->HandleTSTables(&tspacket); 
-        else if (StreamData()->IsWritingPID(lpid)) 
+        else if (GetStreamData()->IsListeningPID(lpid)) 
+            GetStreamData()->HandleTSTables(&tspacket); 
+        else if (GetStreamData()->IsWritingPID(lpid)) 
             BufferedWrite(tspacket); 
     } 
   
@@ -108,9 +130,10 @@
 {
     if (request_pause)
     {
+        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause");
         if (!paused)
         {
-            stop();
+            StopStreaming();
             paused = true;
             pauseWait.wakeAll();
             if (tvrec)
@@ -120,7 +143,8 @@
     }
     if (!request_pause && paused)
     {
-        start();
+        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause");
+        StartStreaming();
         paused = false;
     }
     return paused;
Index: libs/libmythtv/firewirerecorder.cpp
===================================================================
--- libs/libmythtv/firewirerecorder.cpp	(revision 12229)
+++ libs/libmythtv/firewirerecorder.cpp	(working copy)
@@ -8,245 +8,100 @@
 #include <pthread.h>
 #include <sys/select.h>
 
-// C++ includes
-#include <iostream>
-using namespace std;
+// Linux C includes
+#include <libraw1394/raw1394.h>
 
 // MythTV includes
 #include "firewirerecorder.h"
+#include "firewirechannel.h"
+#include "linuxfirewiredevice.h"
 #include "mythcontext.h"
 #include "mpegtables.h"
 #include "mpegstreamdata.h"
 #include "tv_rec.h"
 
-#define LOC QString("FireRec: ")
-#define LOC_ERR QString("FireRec, Error: ")
+#define LOC QString("FireRec(%1): ").arg(channel->GetDevice())
+#define LOC_ERR QString("FireRec(%1), Error: ").arg(tvrec->GetDevice())
 
-const int FirewireRecorder::kBroadcastChannel    = 63;
-const int FirewireRecorder::kConnectionP2P       = 0;
-const int FirewireRecorder::kConnectionBroadcast = 1;
-const uint FirewireRecorder::kMaxBufferedPackets = 2000;
-
-// callback function for libiec61883
-int fw_tspacket_handler(unsigned char *tspacket, int /*len*/,
-                        uint dropped, void *callback_data)
+LinuxFirewireRecorder::LinuxFirewireRecorder(
+    TVRec *rec,
+    LinuxFirewireChannel *chan) :
+    FirewireRecorderBase(rec), channel(chan), isopen(false)
 {
-    if (dropped)
-    {
-        VERBOSE(VB_RECORD, LOC_ERR +
-                QString("Dropped %1 packet(s).").arg(dropped));
-    }
-
-    if (SYNC_BYTE != tspacket[0])
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "TS packet out of sync.");
-        return 1;
-    }
-
-    FirewireRecorder *fw = (FirewireRecorder*) callback_data;
-    if (fw)
-        fw->ProcessTSPacket(*(reinterpret_cast<TSPacket*>(tspacket)));
-
-    return (fw) ? 1 : 0;
 }
 
-static QString speed_to_string(uint speed)
+LinuxFirewireRecorder::~LinuxFirewireRecorder()
 {
-    if (speed > RAW1394_ISO_SPEED_400)
-        return QString("Invalid Speed (%1)").arg(speed);
-
-    static const uint speeds[] = { 100, 200, 400, };
-    return QString("%1Mbps").arg(speeds[speed]);
+    Close();
 }
 
-bool FirewireRecorder::Open(void)
+bool LinuxFirewireRecorder::Open(void)
 {
-     if (isopen)
-         return true;
+     if (!isopen)
+         isopen = channel->GetFirewireDevice()->OpenPort();
 
-     VERBOSE(VB_RECORD, LOC +
-             QString("Initializing Port: %1, Node: %2, Speed: %3")
-             .arg(fwport).arg(fwnode).arg(speed_to_string(fwspeed)));
-
-     fwhandle = raw1394_new_handle_on_port(fwport);
-     if (!fwhandle)
-     {
-         VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " +
-                 QString("port: %1, bailing").arg(fwport) + ENO);
-         return false;
-     }
-
-     if (kConnectionP2P == fwconnection)
-     {
-          VERBOSE(VB_RECORD, LOC + "Creating P2P Connection " +
-                  QString("with Node: %1").arg(fwnode));
-          fwchannel = iec61883_cmp_connect(fwhandle,
-                                           fwnode | 0xffc0, &fwoplug,
-                                           raw1394_get_local_id(fwhandle),
-                                           &fwiplug, &fwbandwidth);
-          if (fwchannel > -1)
-          {
-	      VERBOSE(VB_RECORD, LOC +
-                      QString("Created Channel: %1, "
-                              "Bandwidth Allocation: %2")
-                      .arg(fwchannel).arg(fwbandwidth));
-          }
-     }
-     else
-     {
-         fwchannel = kBroadcastChannel - fwnode;
-
-         VERBOSE(VB_RECORD, LOC + "Creating Broadcast Connection " +
-                 QString("with Node: %1, Channel: %2").arg(fwnode)
-                 .arg(fwchannel));
-         if (iec61883_cmp_create_bcast_output(fwhandle,
-                                              fwnode | 0xffc0, 0,
-                                              fwchannel,
-                                              fwspeed) != 0)
-         {
-             VERBOSE(VB_IMPORTANT, LOC + "Failed to create connection");
-             // release raw1394 object;
-             raw1394_destroy_handle(fwhandle);
-             return false;
-         }
-         fwbandwidth = 0;
-     }
-
-     fwmpeg = iec61883_mpeg2_recv_init(fwhandle, fw_tspacket_handler, this);
-     if (!fwmpeg)
-     {
-         VERBOSE(VB_IMPORTANT, LOC +
-                 "Unable to init iec61883_mpeg2 object, bailing" + ENO);
-
-         // release raw1394 object;
-	 raw1394_destroy_handle(fwhandle);
-         return false;
-     }
-
-     // Set buffered packets size
-     size_t buffer_size = gContext->GetNumSetting("HDRingbufferSize",
-                                                  50 * TSPacket::SIZE);
-     size_t buffered_packets = min(buffer_size / 4,
-                                   (size_t) kMaxBufferedPackets);
-     iec61883_mpeg2_set_buffers(fwmpeg, buffered_packets);
-     VERBOSE(VB_IMPORTANT, LOC +
-             QString("Buffered packets %1 (%2 KB)")
-             .arg(buffered_packets).arg(buffered_packets * 4));
-
-     // Set speed if needed.
-     // Probably shouldn't even allow user to set,
-     // 100Mbps should be more the enough.
-     int curspeed = iec61883_mpeg2_get_speed(fwmpeg);
-     if (curspeed != fwspeed)
-     {
-         VERBOSE(VB_RECORD, LOC +
-                 QString("Changing Speed %1 -> %2")
-                 .arg(speed_to_string(curspeed))
-                 .arg(speed_to_string(fwspeed)));
-
-         iec61883_mpeg2_set_speed(fwmpeg, fwspeed);
-         if (fwspeed != iec61883_mpeg2_get_speed(fwmpeg))
-         {
-              VERBOSE(VB_IMPORTANT, LOC +
-                      "Unable to set firewire speed, continuing");
-         }
-     }
-
-     fwfd = raw1394_get_fd(fwhandle);
-
-     return isopen = true;
+     return isopen;
 }
 
-void FirewireRecorder::Close(void)
+void LinuxFirewireRecorder::Close(void)
 {
-    if (!isopen)
-        return;
-
-    isopen = false;
-
-    VERBOSE(VB_RECORD, LOC + "Releasing iec61883_mpeg2 object");
-    iec61883_mpeg2_close(fwmpeg);
-
-    if (fwconnection == kConnectionP2P && fwchannel > -1)
+    if (isopen)
     {
-        VERBOSE(VB_RECORD, LOC +
-                QString("Disconnecting channel %1").arg(fwchannel));
-
-        iec61883_cmp_disconnect(fwhandle, fwnode | 0xffc0, fwoplug,
-                                raw1394_get_local_id (fwhandle),
-                                fwiplug, fwchannel, fwbandwidth);
+        channel->GetFirewireDevice()->ClosePort();
+        isopen = false;
     }
+}
 
-    VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle");
-    raw1394_destroy_handle(fwhandle);
+void LinuxFirewireRecorder::StartStreaming(void)
+{
+    channel->GetFirewireDevice()->AddListener(this);
 }
 
-bool FirewireRecorder::grab_frames()
+void LinuxFirewireRecorder::StopStreaming(void)
 {
-    struct timeval tv;
-    fd_set rfds;
+    channel->GetFirewireDevice()->RemoveListener(this);
+}
 
-    FD_ZERO(&rfds); 
-    FD_SET(fwfd, &rfds); 
-    tv.tv_sec = kTimeoutInSeconds; 
-    tv.tv_usec = 0;
+void LinuxFirewireRecorder::AddData(const unsigned char *data, uint len)
+{
+    //cout<<":";
 
-    if (select(fwfd + 1, &rfds, NULL, NULL, &tv)  <= 0) 
-    { 
-        VERBOSE(VB_IMPORTANT, LOC + 
-                QString("No Input in %1 seconds [P:%2 N:%3] (select)") 
-                .arg(kTimeoutInSeconds).arg(fwport).arg(fwnode)); 
-        return false; 
+    uint bufsz = buffer.size();
+    if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) &&
+        (TSPacket::SIZE > bufsz))
+    {
+        if (bufsz)
+            buffer.clear();
+
+        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data)));
+        return;
     }
 
-    int ret = raw1394_loop_iterate(fwhandle); 
-    if (ret)
+    buffer.insert(buffer.end(), data, data + len);
+    bufsz += len;
+
+    int sync_at = -1;
+    for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
     {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " + 
-                QString("returned %1").arg(ret)); 
-        return false;
+        if (buffer[i] == SYNC_BYTE)
+            sync_at = i;
     }
 
-    return true;
-}
+    if (sync_at < 0)
+        return;
 
-void FirewireRecorder::SetOption(const QString &name, const QString &value)
-{
-    if (name == "model")
-        fwmodel = value;
-}
+    if (bufsz < 30 * TSPacket::SIZE)
+        return; // build up a little buffer
 
-void FirewireRecorder::SetOption(const QString &name, int value)
-{
-    if (name == "port")
-	fwport = value;
-    else if (name == "node")
-        fwnode = value;
-    else if (name == "speed")
+    while (sync_at + TSPacket::SIZE < bufsz)
     {
-        if (RAW1394_ISO_SPEED_100 != value &&
-            RAW1394_ISO_SPEED_200 != value &&
-            RAW1394_ISO_SPEED_400 != value)
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    QString("Unknown speed '%1', will use 100Mbps")
-                    .arg(value));
+        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
+                              &buffer[0] + sync_at)));
 
-            value = RAW1394_ISO_SPEED_100;
-        }
-        fwspeed = value;
+        sync_at += TSPacket::SIZE;
     }
-    else if (name == "connection")
-    {
-	if (kConnectionP2P       != value &&
-            kConnectionBroadcast != value)
-        {
-	    VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    QString("Unknown connection type '%1', will use P2P")
-                    .arg(fwconnection));
 
-            fwconnection = kConnectionP2P;
-        }
-	fwconnection = value;
-    }
+    buffer.erase(buffer.begin(), buffer.begin() + sync_at);
+
+    return;
 }
Index: libs/libmythtv/firewirerecorder.h
===================================================================
--- libs/libmythtv/firewirerecorder.h	(revision 12229)
+++ libs/libmythtv/firewirerecorder.h	(working copy)
@@ -4,64 +4,39 @@
  *  Distributed as part of MythTV under GPL v2 and later.
  */
 
-#ifndef FIREWIRERECORDER_H_
-#define FIREWIRERECORDER_H_
+#ifndef _LINUX_FIREWIRE_RECORDER_H_
+#define _LINUX_FIREWIRE_RECORDER_H_
 
 #include "firewirerecorderbase.h"
-#include "tsstats.h"
-#include <libraw1394/raw1394.h>
-#include <libiec61883/iec61883.h>
+#include "linuxfirewiredevice.h"
 
-/** \class FirewireRecorder
- *  \brief Linux FirewireRFecorder
+class LinuxFirewireChannel;
+
+/** \class LinuxFirewireRecorder
+ *  \brief Linux Firewire Recorder
  *
  *  \sa FirewireRecorderBase
  */
-class FirewireRecorder : public FirewireRecorderBase
+class LinuxFirewireRecorder :
+    public FirewireRecorderBase, public TSDataListener
 {
-    friend int fw_tspacket_handler(unsigned char*,int,uint,void*);
-
   public:
-    FirewireRecorder(TVRec *rec) 
-        : FirewireRecorderBase(rec),
-        fwport(-1),     fwchannel(-1), fwspeed(-1),   fwbandwidth(-1), 
-        fwfd(-1),       fwconnection(kConnectionP2P), 
-        fwoplug(-1),    fwiplug(-1),   fwmodel(""),   fwnode(0), 
-        fwhandle(NULL), fwmpeg(NULL),  isopen(false) { } 
-   ~FirewireRecorder() { Close(); }
+    LinuxFirewireRecorder(TVRec *rec, LinuxFirewireChannel *chan);
+    ~LinuxFirewireRecorder();
 
     // Commands
-    bool Open(void); 
-
-    // Sets
-    void SetOption(const QString &name, const QString &value);
-    void SetOption(const QString &name, int value);
-
-  private:
+    bool Open(void);
+    void StartStreaming(void);
+    void StopStreaming(void);
     void Close(void);
-    void start() { iec61883_mpeg2_recv_start(fwmpeg, fwchannel); } 
-    void stop() { iec61883_mpeg2_recv_stop(fwmpeg); } 
-    bool grab_frames();
 
   private:
-    int              fwport;
-    int              fwchannel;
-    int              fwspeed;
-    int              fwbandwidth;
-    int              fwfd;
-    int              fwconnection;
-    int              fwoplug;
-    int              fwiplug;
-    QString          fwmodel;
-    nodeid_t         fwnode;
-    raw1394handle_t  fwhandle;
-    iec61883_mpeg2_t fwmpeg;
-    bool             isopen;
+    void AddData(const unsigned char *data, uint dataSize);
 
-    static const int kBroadcastChannel;
-    static const int kConnectionP2P;
-    static const int kConnectionBroadcast;
-    static const uint kMaxBufferedPackets;
+  private:
+    LinuxFirewireChannel *channel;
+    bool                  isopen;
+    vector<unsigned char> buffer;
 };
 
-#endif
+#endif // _LINUX_FIREWIRE_RECORDER_H_
Index: libs/libmythtv/darwinfirewirechannel.cpp
===================================================================
--- libs/libmythtv/darwinfirewirechannel.cpp	(revision 12229)
+++ libs/libmythtv/darwinfirewirechannel.cpp	(working copy)
@@ -15,6 +15,8 @@
 #undef always_inline
 #include <AVCVideoServices/AVCVideoServices.h>
 
+#define LOC QString("DarwinFirewireChannel: ")
+#define LOC_ERR QString("DarwinFirewireChannel, Error: ")
 
 namespace
 {
@@ -84,14 +86,37 @@
     return this->device;
 }
 
+FirewireDevice::PowerState DarwinFirewireChannel::GetPowerState(void) const
+{
+    UInt8 power_state;
+    IOReturn err = device->GetPowerState(&power_state);
+
+    if (err != kIOReturnSuccess)
+        return FirewireDevice::kAVCPowerQueryFailed;
+    else if (kAVCPowerStateOff == power_state)
+        return FirewireDevice::kAVCPowerOff;
+    else if (kAVCPowerStateOn == power_state)
+        return FirewireDevice::kAVCPowerOn;
+    else
+        return FirewireDevice::kAVCPowerUnknown;
+}
+
+bool DarwinFirewireChannel::SetPowerState(bool on)
+{
+    if (on)
+        SetPowerState(kAVCPowerStateOn);
+    else
+        SetPowerState(kAVCPowerStateOff);
+
+    return true;
+}
+
 bool DarwinFirewireChannel::SetChannelByNumber(int channel)
 {
      // If the tuner is off, try to turn it on.
-     UInt8 power_state;
-     IOReturn err = this->device->GetPowerState(&power_state);
-     if (err == kIOReturnSuccess && power_state == kAVCPowerStateOff)
+     if (FirewireDevice::kAVCPowerOff == GetPowerState())
      {
-         this->device->SetPowerState(kAVCPowerStateOn);
+         SetPowerState(true);
         
          // Give it time to power up.
          usleep(2000000); // Sleep for two seconds
@@ -101,10 +126,13 @@
      err = panel.Tune(channel);
      if (err != kIOReturnSuccess)
      {
-         VERBOSE(VB_GENERAL, QString("DarwinFirewireChannel: Tuning failed: %1").arg(err,0,16));
-         VERBOSE(VB_GENERAL, QString("Ignoring error per apple example"));
+         VERBOSE(VB_GENERAL, LOC_ERR +
+                 QString("Tuning failed: %1").arg(err,0,16) +
+                 QString("Ignoring error per apple example"));
      }
+
      // Give it time to transition.        
      usleep(1000000); // Sleep for one second
+
      return true;
 }
Index: libs/libmythtv/firewiresignalmonitor.cpp
===================================================================
--- libs/libmythtv/firewiresignalmonitor.cpp	(revision 0)
+++ libs/libmythtv/firewiresignalmonitor.cpp	(revision 0)
@@ -0,0 +1,260 @@
+// -*- Mode: c++ -*-
+// Copyright (c) 2006, Daniel Thor Kristjansson
+
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include "mythcontext.h"
+#include "mythdbcon.h"
+#include "firewiresignalmonitor.h"
+#include "atscstreamdata.h"
+#include "mpegtables.h"
+#include "atsctables.h"
+
+#include "firewirechannelbase.h"
+
+#include "firewirechannel.h"
+
+#define LOC QString("FireSM(%1): ").arg(channel->GetDevice())
+#define LOC_ERR QString("FireSM(%1), Error: ").arg(channel->GetDevice())
+
+const uint FirewireSignalMonitor::kPowerTimeout  = 3000; /* ms */
+const uint FirewireSignalMonitor::kBufferTimeout = 5000; /* ms */
+
+/** \fn FirewireSignalMonitor::FirewireSignalMonitor(int,FirewireChannel*,uint,const char*)
+ *  \brief Initializes signal lock and signal values.
+ *
+ *   Start() must be called to actually begin continuous
+ *   signal monitoring. The timeout is set to 3 seconds,
+ *   and the signal threshold is initialized to 0%.
+ *
+ *  \param db_cardnum Recorder number to monitor,
+ *                    if this is less than 0, SIGNAL events will not be
+ *                    sent to the frontend even if SetNotifyFrontend(true)
+ *                    is called.
+ *  \param _channel FirewireChannel for card
+ *  \param _flags   Flags to start with
+ *  \param _name    Name for Qt signal debugging
+ */
+FirewireSignalMonitor::FirewireSignalMonitor(
+    int db_cardnum,
+    FirewireChannelBase *_channel,
+    uint _flags, const char *_name) :
+    DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
+    dtvMonitorRunning(false),
+    stb_needs_retune(true),
+    stb_needs_to_wait_for_buffer(false),
+    stb_needs_to_wait_for_power(false)
+{
+    VERBOSE(VB_CHANNEL, LOC + "ctor");
+
+    signalStrength.SetThreshold(65);
+
+    AddFlags(kDTVSigMon_WaitForSig);
+}
+
+/** \fn FirewireSignalMonitor::~FirewireSignalMonitor()
+ *  \brief Stops signal monitoring and table monitoring threads.
+ */
+FirewireSignalMonitor::~FirewireSignalMonitor()
+{
+    VERBOSE(VB_CHANNEL, LOC + "dtor");
+    Stop();
+}
+
+void FirewireSignalMonitor::deleteLater(void)
+{
+    disconnect(); // disconnect signals we may be sending...
+    Stop();
+    DTVSignalMonitor::deleteLater();
+}
+
+/** \fn FirewireSignalMonitor::Stop(void)
+ *  \brief Stop signal monitoring and table monitoring threads.
+ */
+void FirewireSignalMonitor::Stop(void)
+{
+    VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin");
+    SignalMonitor::Stop();
+    if (dtvMonitorRunning)
+    {
+        dtvMonitorRunning = false;
+        pthread_join(table_monitor_thread, NULL);
+    }
+    VERBOSE(VB_CHANNEL, LOC + "Stop() -- end");
+}
+
+void *FirewireSignalMonitor::TableMonitorThread(void *param)
+{
+    FirewireSignalMonitor *mon = (FirewireSignalMonitor*) param;
+    mon->RunTableMonitor();
+    return NULL;
+}
+
+
+void FirewireSignalMonitor::RunTableMonitor(void)
+{
+    stb_needs_to_wait_for_buffer = true; //false;
+    stb_wait_for_buffer_timer.start();
+    dtvMonitorRunning = true;
+
+    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin");
+
+    LinuxFirewireChannel *lchan = dynamic_cast<LinuxFirewireChannel*>(channel);
+    if (!lchan)
+    {
+        VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end");
+        dtvMonitorRunning = false;
+        return;
+    }
+
+    LinuxFirewireDevice *dev = lchan->GetFirewireDevice();
+
+    dev->OpenPort();
+    dev->AddListener(this);
+
+    while (dtvMonitorRunning && GetStreamData())
+        usleep(100000);
+
+    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown ");
+
+    dev->RemoveListener(this);
+    dev->ClosePort();
+
+    dtvMonitorRunning = false;
+
+    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end");
+}
+
+void FirewireSignalMonitor::AddData(const unsigned char *data, uint len)
+{
+    if (!dtvMonitorRunning)
+        return;
+
+    if (stb_needs_to_wait_for_buffer)
+    {
+        cout<<"*";
+        if (stb_wait_for_buffer_timer.elapsed() > kBufferTimeout)
+            stb_needs_to_wait_for_buffer = false;
+    }
+    else
+        cout<<".";
+
+    if (!stb_needs_to_wait_for_buffer && GetStreamData())
+        GetStreamData()->ProcessData((unsigned char *)data, len);
+}
+
+/** \fn FirewireSignalMonitor::UpdateValues(void)
+ *  \brief Fills in frontend stats and emits status Qt signals.
+ *
+ *   This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH
+ *   FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain
+ *   statistics from the frontend.
+ *
+ *   This is automatically called by MonitorLoop(), after Start()
+ *   has been used to start the signal monitoring thread.
+ */
+void FirewireSignalMonitor::UpdateValues(void)
+{
+    if (!running || exit)
+        return;
+
+    if (dtvMonitorRunning)
+    {
+        EmitFirewireSignals();
+        if (IsAllGood())
+            emit AllGood();
+        // TODO dtv signals...
+
+        update_done = true;
+        return;
+    }
+
+    if (stb_needs_to_wait_for_power &&
+        (stb_wait_for_power_timer.elapsed() < kPowerTimeout))
+    {
+        return;
+    }
+    stb_needs_to_wait_for_power = false;
+
+    FirewireChannelBase *fwchan = dynamic_cast<FirewireChannelBase*>(channel);
+
+    if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch))
+    {
+        FirewireDevice::PowerState power = fwchan->GetPowerState();
+        if (FirewireDevice::kAVCPowerOn == power)
+        {
+            AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
+        }
+        else if (FirewireDevice::kAVCPowerOff == power)
+        {
+            AddFlags(kFWSigMon_PowerSeen);
+            fwchan->SetPowerState(true);
+            stb_wait_for_power_timer.start();
+            stb_needs_to_wait_for_power = true;
+        }
+    }
+
+    bool isLocked = !HasFlags(kFWSigMon_WaitForPower) ||
+        HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch);
+
+    if (isLocked && stb_needs_retune)
+    {
+        fwchan->Retune();
+        isLocked = stb_needs_retune = false;
+    }
+
+    // Set SignalMonitorValues from info from card.
+    {
+        QMutexLocker locker(&statusLock);
+        signalStrength.SetValue(isLocked ? 100 : 0);
+        signalLock.SetValue(isLocked ? 1 : 0);
+    }
+
+    EmitFirewireSignals();
+    if (IsAllGood())
+        emit AllGood();
+
+    // Start table monitoring if we are waiting on any table
+    // and we have a lock.
+    if (isLocked && GetStreamData() &&
+        HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
+                   kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
+                   kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
+    {
+        pthread_create(&table_monitor_thread, NULL,
+                       TableMonitorThread, this);
+
+        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- "
+                "Waiting for table monitor to start");
+
+        while (!dtvMonitorRunning)
+            usleep(50);
+
+        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- "
+                "Table monitor started");
+    }
+
+    update_done = true;
+}
+
+#define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \
+    do { statusLock.lock(); \
+         SignalMonitorValue val = SIGNAL_VAL; \
+         statusLock.unlock(); \
+         emit SIGNAL_FUNC(val); } while (false)
+
+/** \fn FirewireSignalMonitor::EmitFirewireSignals(void)
+ *  \brief Emits signals for lock, signal strength, etc.
+ */
+void FirewireSignalMonitor::EmitFirewireSignals(void)
+{
+    // Emit signals..
+    EMIT(StatusSignalLock, signalLock); 
+    if (HasFlags(kDTVSigMon_WaitForSig))
+        EMIT(StatusSignalStrength, signalStrength);
+}
+
+#undef EMIT
Index: libs/libmythtv/darwinfirewirechannel.h
===================================================================
--- libs/libmythtv/darwinfirewirechannel.h	(revision 12229)
+++ libs/libmythtv/darwinfirewirechannel.h	(working copy)
@@ -24,15 +24,17 @@
   public:
     DarwinFirewireChannel(FireWireDBOptions const&, TVRec *parent);
 
+    // Sets
+    virtual bool SetChannelByNumber(int channel);
+    virtual bool SetPowerState(bool on);
+
     // Gets
-    AVS::AVCDevice* GetAVCDevice() const;
+    AVS::AVCDevice* GetAVCDevice(void) const;
+    virtual FirewireDevice::PowerState GetPowerState(void) const;
 
-    // Sets
-    bool SetChannelByNumber(int channel);
-
   private:
-    bool OpenFirewire();
-    void CloseFirewire();
+    virtual bool OpenFirewire(void);
+    virtual void CloseFirewire(void);
 
   private:
     AVS::AVCDeviceController* device_controller;
Index: libs/libmythtv/signalmonitor.cpp
===================================================================
--- libs/libmythtv/signalmonitor.cpp	(revision 12229)
+++ libs/libmythtv/signalmonitor.cpp	(working copy)
@@ -34,6 +34,11 @@
 #   include "iptvchannel.h"
 #endif
 
+#ifdef USING_FIREWIRE
+#   include "firewiresignalmonitor.h"
+#   include "firewirechannelbase.h"
+#endif
+
 #undef DBG_SM
 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
     "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
@@ -117,6 +122,15 @@
     }
 #endif
 
+#ifdef USING_FIREWIRE
+    if (cardtype.upper() == "FIREWIRE")
+    {
+        FirewireChannelBase *fc = dynamic_cast<FirewireChannelBase*>(channel);
+        if (fc)
+            signalMonitor = new FirewireSignalMonitor(db_cardnum, fc);
+    }
+#endif
+
     if (!signalMonitor)
     {
         VERBOSE(VB_IMPORTANT,
Index: libs/libmythtv/firewiresignalmonitor.h
===================================================================
--- libs/libmythtv/firewiresignalmonitor.h	(revision 0)
+++ libs/libmythtv/firewiresignalmonitor.h	(revision 0)
@@ -0,0 +1,59 @@
+// -*- Mode: c++ -*-
+
+#ifndef _FIREWIRESIGNALMONITOR_H_
+#define _FIREWIRESIGNALMONITOR_H_
+
+#include "qdatetime.h"
+
+#include "dtvsignalmonitor.h"
+#include "linuxfirewiredevice.h"
+#include "util.h"
+
+class FirewireChannelBase;
+
+class FirewireSignalMonitor : public DTVSignalMonitor, public TSDataListener
+{
+    Q_OBJECT
+
+  public:
+    FirewireSignalMonitor(int db_cardnum, FirewireChannelBase* _channel,
+                          uint _flags = kFWSigMon_WaitForPower,
+                          const char *_name = "FirewireSignalMonitor");
+
+    void Stop(void);
+
+  public slots:
+    void deleteLater(void);
+
+  protected:
+    FirewireSignalMonitor(void);
+    FirewireSignalMonitor(const FirewireSignalMonitor&);
+    virtual ~FirewireSignalMonitor();
+
+    virtual void UpdateValues(void);
+    void EmitFirewireSignals(void);
+
+    static void *TableMonitorThread(void *param);
+    void RunTableMonitor(void);
+
+    bool SupportsTSMonitoring(void);
+
+    void AddData(const unsigned char *data, uint dataSize);
+
+  public:
+    static const uint kPowerTimeout;
+    static const uint kBufferTimeout;
+
+  protected:
+    bool               dtvMonitorRunning;
+    pthread_t          table_monitor_thread;
+    bool               stb_needs_retune;
+    bool               stb_needs_to_wait_for_buffer;
+    bool               stb_needs_to_wait_for_power;
+    MythTimer          stb_wait_for_buffer_timer;
+    MythTimer          stb_wait_for_power_timer;
+
+    vector<unsigned char> buffer;
+};
+
+#endif // _FIREWIRESIGNALMONITOR_H_
Index: libs/libmythtv/darwinfirewirerecorder.h
===================================================================
--- libs/libmythtv/darwinfirewirerecorder.h	(revision 12229)
+++ libs/libmythtv/darwinfirewirerecorder.h	(working copy)
@@ -33,21 +33,17 @@
 class DarwinFirewireRecorder : public FirewireRecorderBase
 {
   public:
-    DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner);
+    DarwinFirewireRecorder(TVRec *rec, DarwinFirewireChannel *channel);
     ~DarwinFirewireRecorder();
 
     bool Open(void); 
 
-    void SetOption(const QString &name, const QString &value);
-    void SetOption(const QString &name, int value);
-
   private:
     void Close();
 
     void start();
     void stop();
     void no_data();
-    bool grab_frames();
 
     static IOReturn MPEGNoData(void* pRefCon);
     static IOReturn tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf, void *pRefCon);
Index: libs/libmythtv/firewirechannel.h
===================================================================
--- libs/libmythtv/firewirechannel.h	(revision 12229)
+++ libs/libmythtv/firewirechannel.h	(working copy)
@@ -5,46 +5,46 @@
  *  Distributed as part of MythTV under GPL v2 and later.
  */
 
+#ifndef _LINUX_FIREWIRE_CHANNEL_H_
+#define _LINUX_FIREWIRE_CHANNEL_H_
 
-#ifndef FIREWIRECHANNEL_H
-#define FIREWIRECHANNEL_H
-
 #include <qstring.h>
 #include "tv_rec.h"
 #include "firewirechannelbase.h"
-#include <libavc1394/avc1394.h>
 
 using namespace std;
 
-class FirewireChannel : public FirewireChannelBase
+class LinuxFirewireDevice;
+
+class LinuxFirewireChannel : public FirewireChannelBase
 {
   public:
-    enum PowerState {
-        On,
-        Off,
-        Failed
-    };
+    LinuxFirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent);
+    ~LinuxFirewireChannel(void);
 
-    FirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent);
-    ~FirewireChannel(void);
+    // Commands
+    virtual bool Retune(void);
 
-    bool OpenFirewire(void); 
-    void CloseFirewire(void); 
-
     // Sets
-    void SetExternalChanger(void);
-    bool SetChannelByNumber(int channel);
+    virtual bool SetChannelByNumber(int channel);
+    virtual bool SetPowerState(bool on);
 
     // Gets
-    bool IsOpen(void) const { return isopen; }
-    QString GetDevice(void) const
+    virtual QString GetDevice(void) const
         { return QString("%1:%2").arg(fw_opts.port).arg(fw_opts.node); }
-    PowerState GetPowerState(void);
+    virtual LinuxFirewireDevice *GetFirewireDevice(void)
+        { return device; }
+    virtual FirewireDevice::PowerState GetPowerState(void) const;
 
   private:
-    FireWireDBOptions  fw_opts;
-    nodeid_t           fwnode;
-    raw1394handle_t    fwhandle;
+    virtual bool OpenFirewire(void);
+    virtual void CloseFirewire(void);
+
+  private:
+    FireWireDBOptions    fw_opts;
+    LinuxFirewireDevice *device;
+    uint                 current_channel;
+    bool                 is_port_open;
 };
 
-#endif
+#endif // _LINUX_FIREWIRE_CHANNEL_H_
Index: libs/libmythtv/firewirechannelbase.cpp
===================================================================
--- libs/libmythtv/firewirechannelbase.cpp	(revision 12229)
+++ libs/libmythtv/firewirechannelbase.cpp	(working copy)
@@ -5,10 +5,27 @@
  */
 
 
-#include <iostream>
+#include "mythconfig.h" // for CONFIG_DARWIN
 #include "mythcontext.h"
 #include "firewirechannelbase.h"
+#include "tv_rec.h"
 
+#ifdef CONFIG_DARWIN
+#   include "darwinfirewirechannel.h"
+#else 
+#   include "firewirechannel.h"
+#endif 
+
+FirewireChannelBase *FirewireChannelBase::Init(
+    const FireWireDBOptions &firewire_opts, TVRec *parent)
+{
+#ifdef CONFIG_DARWIN
+    return new DarwinFirewireChannel(firewire_opts, parent);
+#else 
+    return new LinuxFirewireChannel(firewire_opts, parent);
+#endif
+}
+
 bool FirewireChannelBase::SetChannelByString(const QString &chan)
 {
     inputs[currentInputID]->startChanNum = chan; 
@@ -22,7 +39,7 @@
     return isopen && SetChannelByNumber(chan.toInt());
 }
 
-bool FirewireChannelBase::Open()
+bool FirewireChannelBase::Open(void)
 {
     if (!InitializeInputs()) 
         return false; 
@@ -39,7 +56,7 @@
     return true;
 }
 
-void FirewireChannelBase::Close()
+void FirewireChannelBase::Close(void)
 {
     if (isopen)
         CloseFirewire();
Index: libs/libmythtv/linuxfirewiredevice.h
===================================================================
--- libs/libmythtv/linuxfirewiredevice.h	(revision 0)
+++ libs/libmythtv/linuxfirewiredevice.h	(revision 0)
@@ -0,0 +1,102 @@
+/**
+ *  LinuxFirewireDevice
+ *  Copyright (c) 2005 by Jim Westfall
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _LINUX_FIREWIRE_DEVICE_H_
+#define _LINUX_FIREWIRE_DEVICE_H_
+
+#include "firewiredevice.h"
+
+class FWPriv;
+
+class LinuxFirewireDevice : public FirewireDevice
+{
+  public:
+
+    LinuxFirewireDevice(uint port, uint node, uint speed, bool use_p2p,
+                        uint av_buffer_size_in_bytes = 0);
+    ~LinuxFirewireDevice();
+
+    bool OpenPort(void);
+    bool ClosePort(void);
+
+    void AddListener(TSDataListener*);
+    void RemoveListener(TSDataListener*);
+
+    // Sets
+    bool SetPowerState(bool on);
+    bool SetChannel(const QString &panel_model, uint channel);
+
+    // Gets
+    bool IsPortOpen(void) const;
+    bool IsNodeOpen(void) const;
+    bool IsAVStreamOpen(void) const;
+    bool IsTuner(void) const;
+    bool IsPanel(void) const;
+    bool IsSTB(void) const { return IsTuner() && IsPanel(); }
+
+    // non-const Gets
+    PowerState GetPowerState(void);
+
+    // Commands
+    bool ResetBus(void);
+
+    void RunStreaming(void);
+    bool LoopIteration(uint timeout_in_msec);
+
+    void PrintDropped(uint dropped_packets);
+    void BroadcastToListeners(const unsigned char *data, uint dataSize);
+
+    // Statics
+    static inline bool IsSTBSupported(const QString &model);
+
+    // Constants
+    static const uint kBroadcastChannel;
+    static const uint kConnectionP2P;
+    static const uint kConnectionBroadcast;
+    static const uint kMaxBufferedPackets;
+
+  private:
+    bool OpenNode(void);
+    bool CloseNode(void);
+
+    bool OpenAVStream(void);
+    bool CloseAVStream(void);
+
+    bool OpenP2PNode(void);
+    bool CloseP2PNode(void);
+
+    bool OpenBroadcastNode(void);
+    bool CloseBroadcastNode(void);
+
+    bool StartStreaming(void);
+    bool StopStreaming(void);
+    bool StopStreamingLater(void);
+
+    bool SetAVStreamBufferSize(uint size_in_bytes);
+    bool SetAVStreamSpeed(uint speed);
+
+    bool IsSubunitType(uint subunit_type) const;
+
+  private:
+    uint                     m_port;
+    uint                     m_node;
+    uint                     m_speed;
+    uint                     m_bufsz;
+    bool                     m_use_p2p;
+    uint                     m_open_port_cnt;
+    FWPriv                  *m_priv;
+    vector<TSDataListener*>  m_listeners;
+};
+
+inline bool LinuxFirewireDevice::IsSTBSupported(const QString &panel_model)
+{
+    QString model = panel_model.upper();
+    return ((model == "DCT-6200") ||
+            (model == "SA3250HD") ||
+	    (model == "SA4200HD"));
+}
+
+#endif // _LINUX_FIREWIRE_DEVICE_H_
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 12229)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -48,6 +48,7 @@
 #include "dbox2channel.h"
 #include "hdhrchannel.h"
 #include "iptvchannel.h"
+#include "firewirechannelbase.h"
 
 #include "recorderbase.h"
 #include "NuppelVideoRecorder.h"
@@ -57,21 +58,12 @@
 #include "dbox2recorder.h"
 #include "hdhrrecorder.h"
 #include "iptvrecorder.h"
+#include "firewirerecorderbase.h"
 
 #ifdef USING_V4L
 #include "channel.h"
 #endif
 
-#ifdef USING_FIREWIRE
-#ifdef CONFIG_DARWIN
-#include "darwinfirewirerecorder.h"
-#include "darwinfirewirechannel.h"
-#else 
-#include "firewirerecorder.h"
-#include "firewirechannel.h"
-#endif 
-#endif
-
 #define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */
 
 #define LOC QString("TVRec(%1): ").arg(cardid)
@@ -158,12 +150,8 @@
     else if (genOpt.cardtype == "FIREWIRE")
     {
 #ifdef USING_FIREWIRE
-# ifdef CONFIG_DARWIN
-        channel = new DarwinFirewireChannel(fwOpt, this);
-# else 
-        channel = new FirewireChannel(fwOpt, this);
-# endif
-        if (!channel->Open())
+        channel = FirewireChannelBase::Init(fwOpt, this);
+        if (!channel || !channel->Open())
             return false;
         InitChannel(genOpt.defaultinput, startchannel);
         init_run = true;
@@ -831,16 +819,15 @@
     else if (genOpt.cardtype == "FIREWIRE")
     {
 #ifdef USING_FIREWIRE
-# ifdef CONFIG_DARWIN
-        recorder = new DarwinFirewireRecorder(this, this->channel);
-# else 
-        recorder = new FirewireRecorder(this);
-        recorder->SetOption("port",       fwOpt.port);
-        recorder->SetOption("node",       fwOpt.node);
-        recorder->SetOption("speed",      fwOpt.speed);
-        recorder->SetOption("model",      fwOpt.model);
-        recorder->SetOption("connection", fwOpt.connection);
-# endif // !CONFIG_DARWIN 
+        recorder = FirewireRecorderBase::Init(this, GetFirewireChannel());
+        if (recorder)
+        {
+            recorder->SetOption("port",       fwOpt.port);
+            recorder->SetOption("node",       fwOpt.node);
+            recorder->SetOption("speed",      fwOpt.speed);
+            recorder->SetOption("model",      fwOpt.model);
+            recorder->SetOption("connection", fwOpt.connection);
+        }
 #endif // USING_FIREWIRE
     }
     else if (genOpt.cardtype == "DBOX2")
@@ -1114,6 +1101,15 @@
 #endif // USING_DVB
 }
 
+FirewireChannelBase *TVRec::GetFirewireChannel(void)
+{
+#ifdef USING_FIREWIRE
+    return dynamic_cast<FirewireChannelBase*>(channel);
+#else
+    return NULL;
+#endif // USING_FIREWIRE
+}
+
 Channel *TVRec::GetV4LChannel(void)
 {
 #ifdef USING_V4L
Index: libs/libmythtv/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h	(revision 12229)
+++ libs/libmythtv/tv_rec.h	(working copy)
@@ -35,6 +35,7 @@
 class DBox2Channel;
 class DTVChannel;
 class DVBChannel;
+class FirewireChannelBase;
 class Channel;
 class HDHRChannel;
 
@@ -261,6 +262,7 @@
     DTVChannel   *GetDTVChannel(void);
     HDHRChannel  *GetHDHRChannel(void);
     DVBChannel   *GetDVBChannel(void);
+    FirewireChannelBase *GetFirewireChannel(void);
     Channel      *GetV4LChannel(void);
 
     bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
Index: libs/libmythtv/firewiredevice.h
===================================================================
--- libs/libmythtv/firewiredevice.h	(revision 0)
+++ libs/libmythtv/firewiredevice.h	(revision 0)
@@ -0,0 +1,39 @@
+/**
+ *  FirewireDevice
+ *  Copyright (c) 2005 by Jim Westfall
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _FIREWIRE_DEVICE_H_
+#define _FIREWIRE_DEVICE_H_
+
+// C++ headers
+#include <vector>
+using namespace std;
+
+#include <qstring.h>
+
+class TSDataListener
+{
+  public:
+    /// Callback function to add MPEG2 TS data
+    virtual void AddData(const unsigned char *data, uint dataSize) = 0;
+
+  protected:
+    virtual ~TSDataListener() { }
+};
+
+class FirewireDevice
+{
+  public:
+    // Public enums
+    typedef enum
+    {
+        kAVCPowerOn,
+        kAVCPowerOff,
+        kAVCPowerUnknown,
+        kAVCPowerQueryFailed,
+    } PowerState;
+};
+
+#endif // _FIREWIRE_DEVICE_H_
Index: libs/libmythtv/linuxfirewiredevice.cpp
===================================================================
--- libs/libmythtv/linuxfirewiredevice.cpp	(revision 0)
+++ libs/libmythtv/linuxfirewiredevice.cpp	(revision 0)
@@ -0,0 +1,948 @@
+/**
+ *  LinuxFirewireDevice
+ *  Copyright (c) 2005 by Jim Westfall
+ *  Copyright (c) 2006 by Daniel Kristjansson
+ *  SA3250HD support Copyright (c) 2005 by Matt Porter
+ *  SA4200HD/Alternate 3250 support Copyright (c) 2006 by Chris Ingrassia
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+// POSIX headers
+#include <pthread.h>
+#include <sys/select.h>
+
+// Linux headers
+#include <libraw1394/raw1394.h>
+#include <libiec61883/iec61883.h>
+#include <libavc1394/avc1394.h>
+
+// C++ headers
+#include <algorithm>
+using namespace std;
+
+// Qt headers
+#include <qdatetime.h>
+
+// MythTV headers
+#include "linuxfirewiredevice.h"
+#include "firewirerecorder.h"
+#include "mythcontext.h"
+
+#define LOC QString("FireDev(%1:%2): ").arg(m_port).arg(m_node)
+#define LOC_WARN QString("FireDev(%1:%2), Warning: ").arg(m_port).arg(m_node)
+#define LOC_ERR QString("FireDev(%1:%2), Error: ").arg(m_port).arg(m_node)
+
+
+#ifndef AVC1394_PANEL_COMMAND_PASS_THROUGH
+#define AVC1394_PANEL_COMMAND_PASS_THROUGH     0x000007C00
+#endif
+
+#ifndef AVC1394_PANEL_OPERATION_0
+#define AVC1394_PANEL_OPERATION_0              0x000000020
+#endif
+
+#define AVC1394_CMD_OPERAND_POWER_STATE        0x7F
+
+// Basic Panel commands
+#define PANEL_CMD0 (AVC1394_CTYPE_CONTROL | \
+                    AVC1394_SUBUNIT_TYPE_PANEL | \
+                    AVC1394_SUBUNIT_ID_0 | \
+                    AVC1394_PANEL_COMMAND_PASS_THROUGH)
+
+// Scientific Atlanta defines
+#define AVC1394_SA3250_OPERAND_KEY_PRESS	0xE7
+#define AVC1394_SA3250_OPERAND_KEY_RELEASE	0x67
+#define SA_CMD0     PANEL_CMD0
+#define SA_CMD1     AVC1394_CTYPE_GENERAL_INQUIRY
+#define SA_CMD2     0xff000000
+
+// Motorola defines
+#define MOT_CMD0  (PANEL_CMD0 | AVC1394_PANEL_OPERATION_0)
+
+class FWPriv
+{
+  public:
+    FWPriv() :
+        handle(0), avstream(0),
+        channel(-1),
+        is_p2p_node_open(false), is_bcast_node_open(false),
+        is_streaming(false), stop_streaming_timer_on(false)
+    {
+        bzero(unit_table, sizeof(unit_table));
+    }
+
+    raw1394handle_t  handle;
+    iec61883_mpeg2_t avstream;
+    quadlet_t        unit_table[8];
+    int              channel;
+    int              open_node;
+    bool             is_p2p_node_open;
+    bool             is_bcast_node_open;
+    bool             is_streaming;
+    bool             is_streaming_running;
+    bool             stop_streaming_timer_on;
+    QDateTime        stop_streaming_timer;
+    pthread_t        streaming_thread;
+};
+
+const uint LinuxFirewireDevice::kBroadcastChannel    = 63;
+const uint LinuxFirewireDevice::kConnectionP2P       = 0;
+const uint LinuxFirewireDevice::kConnectionBroadcast = 1;
+const uint LinuxFirewireDevice::kMaxBufferedPackets  = 2000;
+
+// callback function for libiec61883
+static int fw_tspacket_handler(unsigned char *tspacket, int len,
+                               uint dropped, void *callback_data);
+static QString speed_to_string(uint speed);
+static quadlet_t *send_avc_command(raw1394handle_t handle,
+                                   uint            node,
+                                   quadlet_t      *cmd,
+                                   uint            cmd_len,
+                                   uint            retry_cnt = 1);
+static void close_avc_command(raw1394handle_t handle);
+
+
+LinuxFirewireDevice::LinuxFirewireDevice(
+    uint port, uint node, uint speed, bool use_p2p,
+    uint av_buffer_size_in_bytes) :
+    m_port(port),       m_node(node),
+    m_speed(speed),     m_bufsz(av_buffer_size_in_bytes),
+    m_use_p2p(use_p2p),
+    m_open_port_cnt(0), m_priv(new FWPriv())
+{
+    if (!m_bufsz)
+        m_bufsz = gContext->GetNumSetting("HDRingbufferSize");
+}
+
+LinuxFirewireDevice::~LinuxFirewireDevice()
+{
+    if (IsPortOpen())
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port");
+        while (IsPortOpen())
+            ClosePort();
+    }
+
+    if (m_priv)
+    {
+        delete m_priv;
+        m_priv = NULL;
+    }
+}
+
+bool LinuxFirewireDevice::OpenPort(void)
+{
+    VERBOSE(VB_RECORD, LOC + "OpenPort()");
+
+    m_open_port_cnt++;
+
+    if (m_priv->handle)
+        return true;
+
+    VERBOSE(VB_RECORD, LOC + "Getting raw1394 handle "<<(m_open_port_cnt-1));
+    m_priv->handle = raw1394_new_handle_on_port(m_port);
+
+    if (!m_priv->handle)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " +
+                QString("port: %1").arg(m_port) + ENO);
+
+        return false;
+    }
+
+    if (avc1394_subunit_info(m_priv->handle, m_node, m_priv->unit_table) < 0)
+        bzero(m_priv->unit_table, sizeof(m_priv->unit_table));
+
+    QString str = "Subunit Types: ";
+
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VIDEO_MONITOR))
+        str += "Video Monitor, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_AUDIO))
+        str += "Audio, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_PRINTER))
+        str += "Printer, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_DISC_RECORDER))
+        str += "Disk Recorder, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_TAPE_RECORDER))
+        str += "Tape Recorder, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VCR))
+        str += "VCR, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_TUNER))
+        str += "Tuner, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_CA))
+        str += "CA, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VIDEO_CAMERA))
+        str += "Camera, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_PANEL))
+        str += "Panel, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_BULLETIN_BOARD))
+        str += "Bulletin Board, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_CAMERA_STORAGE))
+        str += "Camera Storage, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_MUSIC))
+        str += "Music, ";
+    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VENDOR_UNIQUE))
+        str += "Vendor Unique, ";
+
+    VERBOSE(VB_RECORD, LOC + str);
+
+    return true;
+}
+
+bool LinuxFirewireDevice::ClosePort(void)
+{
+    VERBOSE(VB_RECORD, LOC + "ClosePort()");
+
+    if (m_open_port_cnt < 1)
+        return false;
+
+    m_open_port_cnt--;
+
+    if (m_open_port_cnt != 0)
+        return true;
+
+    if (m_priv->handle)
+    {
+        if (IsNodeOpen())
+            CloseNode();
+
+        VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle "<<m_open_port_cnt);
+        raw1394_destroy_handle(m_priv->handle);
+        m_priv->handle = NULL;
+    }
+
+    return true;
+}
+
+bool LinuxFirewireDevice::OpenNode(void)
+{
+    if (m_use_p2p)
+        return OpenP2PNode();
+    else
+        return OpenBroadcastNode();
+}
+
+bool LinuxFirewireDevice::CloseNode(void)
+{
+    if (m_priv->is_p2p_node_open)
+        return CloseP2PNode();
+
+    if (m_priv->is_bcast_node_open)
+        return CloseBroadcastNode();
+
+    return true;
+}
+
+bool LinuxFirewireDevice::OpenP2PNode(void)
+{
+    if (m_priv->is_bcast_node_open)
+        return false;
+
+    if (m_priv->is_p2p_node_open)
+        return true;
+
+    VERBOSE(VB_RECORD, LOC + "Opening P2P connection");
+
+    m_priv->channel = m_node;
+    if (iec61883_cmp_create_p2p_output(m_priv->handle, m_node | 0xffc0, 0,
+                                       m_priv->channel, m_speed) != 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create P2P connection");
+
+        m_priv->channel = -1;
+        return false;
+    }
+
+    m_priv->is_p2p_node_open = true;
+
+    return true;
+}
+
+bool LinuxFirewireDevice::CloseP2PNode(void)
+{
+    if (m_priv->is_p2p_node_open && (m_priv->channel >= 0))
+    {
+        VERBOSE(VB_RECORD, LOC + "Closing P2P connection");
+
+        if (m_priv->avstream)
+            CloseAVStream();
+
+        iec61883_cmp_disconnect(m_priv->handle, m_node | 0xffc0, 0,
+                                raw1394_get_local_id(m_priv->handle),
+                                -1, m_priv->channel, 0);
+
+        m_priv->channel = -1;
+        m_priv->is_p2p_node_open = false;
+    }
+
+    return true;
+}
+
+bool LinuxFirewireDevice::OpenBroadcastNode(void)
+{
+    if (m_priv->is_p2p_node_open)
+        return false;
+
+    if (m_priv->is_bcast_node_open)
+        return true;
+
+    m_priv->channel = kBroadcastChannel - m_node;
+
+    VERBOSE(VB_RECORD, LOC + "Opening broadcast connection on " +
+            QString("node %1, channel %2")
+            .arg(m_node).arg(m_priv->channel));
+
+    if (m_priv->avstream)
+        CloseAVStream();
+
+    int err = iec61883_cmp_create_bcast_output(
+        m_priv->handle, m_node | 0xffc0, 0, m_priv->channel, m_speed);
+
+    if (err != 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                "Failed to create Broadcast connection");
+
+        m_priv->channel = -1;
+        return false;
+    }
+
+    m_priv->is_bcast_node_open = true;
+
+    return true;
+}
+
+bool LinuxFirewireDevice::CloseBroadcastNode(void)
+{
+    if (m_priv->is_bcast_node_open)
+    {
+        VERBOSE(VB_RECORD, LOC + "Closing broadcast connection");
+
+        m_priv->channel = -1;
+        m_priv->is_bcast_node_open = false;
+    }
+    return true;
+}
+
+bool LinuxFirewireDevice::OpenAVStream(void)
+{
+    VERBOSE(VB_RECORD, LOC + "OpenAVStream");
+
+    if (!IsNodeOpen() && !OpenNode())
+        return false;
+
+    if (m_priv->avstream)
+        return true;
+
+    VERBOSE(VB_RECORD, LOC + "Opening A/V stream object");
+
+    if (!m_priv->handle)
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                "Can not open AVStream without IEEE 1394 Port");
+
+        return false;
+    }
+
+    m_priv->avstream = iec61883_mpeg2_recv_init(
+        m_priv->handle, fw_tspacket_handler, this);
+
+    if (!m_priv->avstream)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Unable to open AVStream" + ENO);
+
+        return false;
+    }
+
+    iec61883_mpeg2_set_synch(m_priv->avstream, 1 /* sync on close */);
+
+    if (m_bufsz)
+        SetAVStreamBufferSize(m_bufsz);
+
+    return true;
+}
+
+bool LinuxFirewireDevice::CloseAVStream(void)
+{
+    if (!m_priv->avstream)
+        return true;
+
+    VERBOSE(VB_RECORD, LOC + "Closing A/V stream object");
+
+    while (m_listeners.size())
+        RemoveListener(m_listeners[m_listeners.size() - 1]);
+
+    if (m_priv->is_streaming)
+        StopStreaming();
+
+    iec61883_mpeg2_close(m_priv->avstream);
+    m_priv->avstream = NULL;
+
+    return true;
+}
+
+static void *streaming_thunk(void *param)
+{
+    LinuxFirewireDevice *mon = (LinuxFirewireDevice*) param;
+    mon->RunStreaming();
+    return NULL;
+}
+
+void LinuxFirewireDevice::RunStreaming(void)
+{
+    m_priv->is_streaming_running = true;
+
+    uint no_data_cnt = 0;
+    while (m_priv->is_streaming)
+    {
+        if (m_priv->stop_streaming_timer_on)
+        {
+            if (m_priv->stop_streaming_timer < QDateTime::currentDateTime())
+                break;
+
+            usleep(50000);
+            continue;
+        }
+
+        no_data_cnt = (LoopIteration(250)) ? 0 : no_data_cnt + 1;
+        if (no_data_cnt > 6)
+        {
+            ResetBus();
+            no_data_cnt = 0;
+        }
+    }
+
+    m_priv->is_streaming_running = false;
+    if (m_priv->stop_streaming_timer_on)
+    {
+        CloseAVStream();
+        CloseNode();
+        m_priv->stop_streaming_timer_on = false;
+    }
+}
+
+bool LinuxFirewireDevice::StartStreaming(void)
+{
+    m_priv->stop_streaming_timer_on = false;
+
+    if (m_priv->is_streaming)
+        return m_priv->is_streaming;
+
+    if (!IsAVStreamOpen() && !OpenAVStream())
+        return false;
+
+    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming");
+
+    if (!m_priv->avstream)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming, no A/V obj");
+        return false;
+    }
+
+    if (m_priv->channel < 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming, no channel");
+        return false;
+    }
+
+    if (iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel) == 0)
+    {
+        m_priv->is_streaming = true;
+
+        pthread_create(&m_priv->streaming_thread, NULL,
+                       streaming_thunk, this);
+
+        while (!m_priv->is_streaming_running)
+            usleep(50);
+    }
+    else
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming " + ENO);
+    }
+
+    return m_priv->is_streaming;
+}
+
+bool LinuxFirewireDevice::StopStreaming(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming");
+
+    if (m_priv->is_streaming)
+    {
+        m_priv->stop_streaming_timer_on = false;
+        m_priv->is_streaming = false;
+
+        pthread_join(m_priv->streaming_thread, NULL);
+
+        iec61883_mpeg2_recv_stop(m_priv->avstream);
+
+        raw1394_iso_recv_flush(m_priv->handle);
+    }
+
+    return true;
+}
+
+bool LinuxFirewireDevice::StopStreamingLater(void)
+{
+    if (m_priv->is_streaming && !m_priv->stop_streaming_timer_on)
+    {
+        m_priv->stop_streaming_timer =
+            QDateTime::currentDateTime().addSecs(2);
+        m_priv->stop_streaming_timer_on = true;
+    }
+
+    return true;
+}
+
+bool LinuxFirewireDevice::SetAVStreamBufferSize(uint size_in_bytes)
+{
+    if (!m_priv->avstream)
+        return false;
+
+    // Set buffered packets size
+    uint   buffer_size      = max(size_in_bytes, 50 * TSPacket::SIZE);
+    size_t buffered_packets = min(buffer_size / 4, kMaxBufferedPackets);
+
+    iec61883_mpeg2_set_buffers(m_priv->avstream, buffered_packets);
+
+    VERBOSE(VB_IMPORTANT, LOC +
+            QString("Buffered packets %1 (%2 KB)")
+            .arg(buffered_packets).arg(buffered_packets * 4));
+
+    return true;
+}
+
+bool LinuxFirewireDevice::SetAVStreamSpeed(uint speed)
+{
+    if (!m_priv->avstream)
+        return false;
+
+    uint curspeed = iec61883_mpeg2_get_speed(m_priv->avstream);
+
+    if (curspeed == speed)
+    {
+        m_speed = speed;
+        return true;
+    }
+
+    VERBOSE(VB_RECORD, LOC +
+            QString("Changing Speed %1 -> %2")
+            .arg(speed_to_string(curspeed))
+            .arg(speed_to_string(m_speed)));
+
+    iec61883_mpeg2_set_speed(m_priv->avstream, speed);
+
+    if (speed == (uint)iec61883_mpeg2_get_speed(m_priv->avstream))
+    {
+        m_speed = speed;
+        return true;
+    }
+
+    VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set firewire speed.");
+
+    return false;
+}
+
+bool LinuxFirewireDevice::IsSubunitType(uint subunit_type) const
+{
+    for (uint i = 0; i < 8; i++)
+    {
+        for (uint j = 0; j < 32; j += 8)
+        {
+            uint subunit = (m_priv->unit_table[i] >> j) & 0xff;
+            if ((subunit != 0xff) &&
+                (subunit >> 3) == AVC1394_GET_SUBUNIT_TYPE(subunit_type))
+            {
+                return true;
+            }
+        }
+    }
+    return false; 
+}
+
+bool LinuxFirewireDevice::IsTuner(void) const
+{
+    return IsSubunitType(AVC1394_SUBUNIT_TYPE_TUNER);
+}
+
+bool LinuxFirewireDevice::IsPanel(void) const
+{
+    return IsSubunitType(AVC1394_SUBUNIT_TYPE_PANEL);
+}
+
+bool LinuxFirewireDevice::IsPortOpen(void) const
+{
+    return m_priv->handle;
+}
+
+bool LinuxFirewireDevice::IsNodeOpen(void) const
+{
+    return m_priv->is_p2p_node_open || m_priv->is_bcast_node_open;
+}
+
+bool LinuxFirewireDevice::IsAVStreamOpen(void) const
+{
+    return m_priv->avstream;
+}
+
+bool LinuxFirewireDevice::ResetBus(void)
+{
+/*
+    VERBOSE(VB_IMPORTANT, LOC + "ResetBus()");
+
+    bool open_node = IsNodeOpen();
+    bool open_avstream = IsAVStreamOpen();
+    bool restart_streaming = m_priv->is_streaming;
+
+    StopStreaming();
+    CloseAVStream();
+    CloseNode();
+
+    bool ok = (raw1394_reset_bus_new(m_priv->handle, RAW1394_LONG_RESET) != 0);
+    if (!ok)
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Bus Reset failed");
+
+    if (open_node)
+        ok &= OpenNode();
+
+    if (open_avstream)
+        ok &= OpenAVStream();
+
+    if (restart_streaming)
+        ok &= StartStreaming();
+
+    return ok;
+*/
+    return true;
+}
+
+bool LinuxFirewireDevice::LoopIteration(uint timeout_in_msec)
+{
+    int fwfd = raw1394_get_fd(m_priv->handle);
+    if (fwfd < 0)
+        return false;
+
+    struct timeval tv;
+    fd_set rfds;
+
+    FD_ZERO(&rfds);
+    FD_SET(fwfd, &rfds);
+
+    tv.tv_sec  = timeout_in_msec / 1000;
+    tv.tv_usec = (timeout_in_msec % 1000) * 1000;
+
+    if (select(fwfd + 1, &rfds, NULL, NULL, &tv) <= 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString("No Input in %1 msec...")
+                .arg(timeout_in_msec));
+
+        return false;
+    }
+
+    int ret = raw1394_loop_iterate(m_priv->handle);
+    if (ret)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " + 
+                QString("returned %1").arg(ret));
+
+        return false;
+    }
+
+    return true;
+}
+
+void LinuxFirewireDevice::AddListener(TSDataListener *listener)
+{
+    if (listener)
+    {
+        RemoveListener(listener);
+        m_listeners.push_back(listener);
+    }
+
+    VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size());
+
+    if (!m_listeners.empty())
+        StartStreaming();
+}
+
+void LinuxFirewireDevice::RemoveListener(TSDataListener *listener)
+{
+    vector<TSDataListener*>::iterator it = m_listeners.end();
+
+    uint cnt = 0;
+
+    do
+    {
+        it = find(m_listeners.begin(), m_listeners.end(), listener);
+        if (it != m_listeners.end())
+        {
+            m_listeners.erase(it);
+            cnt++;
+        }
+    }
+    while (it != m_listeners.end());
+
+    if (cnt)
+    {
+        VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size());
+
+//        if (m_priv->is_streaming && m_listeners.empty())
+//            StopStreamingLater();
+
+        if (m_priv->is_streaming && m_listeners.empty())
+            StopStreaming();
+
+        CloseAVStream();
+        CloseNode();
+    }
+}
+
+void LinuxFirewireDevice::BroadcastToListeners(
+    const unsigned char *data, uint dataSize)
+{
+    vector<TSDataListener*>::iterator it = m_listeners.begin();
+    for (; it != m_listeners.end(); ++it)
+        (*it)->AddData(data, dataSize);
+}
+
+bool LinuxFirewireDevice::SetChannel(const QString &panel_model, uint channel)
+{
+    if (!IsSTBSupported(panel_model))
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                QString("Model: '%1' ").arg(panel_model) +
+                "is not supported by internal channel changer.");
+        return false;
+    }
+
+    int digit[3];
+    digit[0] = (channel % 1000) / 100;
+    digit[1] = (channel % 100)  / 10;
+    digit[2] = (channel % 10);
+
+    if (panel_model.upper() == "DCT-6200")
+    {
+        for (uint i = 0; i < 3 ;i++)
+        {
+            quadlet_t cmd[2] =
+            {
+                MOT_CMD0 | AVC1394_PANEL_OPERATION_0 | digit[i],
+                0x0,
+            };
+
+            if (!send_avc_command(m_priv->handle, m_node, cmd, 2))
+                return false;
+
+            usleep(500000);
+        }
+
+        return true;
+    }
+
+    if (panel_model.upper() == "SA4200HD")
+    {
+        quadlet_t cmd[3] =
+        {
+            SA_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
+            SA_CMD1 | (channel << 8),
+            SA_CMD2,
+        };
+
+        if (!send_avc_command(m_priv->handle, m_node, cmd, 3))
+            return false;
+
+        return true;
+    }
+   
+    if (panel_model == "SA3250HD")
+    {
+        digit[0] |= 0x30;
+        digit[1] |= 0x30;
+        digit[2] |= 0x30;
+
+        quadlet_t cmd[3] =
+        {
+            SA_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS, 
+            SA_CMD1 | (digit[2] << 16) | (digit[1] << 8) | digit[0],
+            SA_CMD2,
+        };
+
+        VERBOSE(VB_CHANNEL, LOC +
+                QString("Channel2: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
+                .arg(digit[0] & 0xf).arg(digit[1] & 0xf)
+                .arg(digit[2] & 0xf)
+                .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
+                .arg(cmd[2], 0, 16));
+
+        if (!send_avc_command(m_priv->handle, m_node, cmd, 3))
+            return false;
+
+        cmd[0] = SA_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;
+        cmd[1] = SA_CMD1 | (digit[0] << 16) | (digit[1] << 8) | digit[2];
+        cmd[2] = SA_CMD2;
+
+        VERBOSE(VB_CHANNEL, LOC +
+                QString("Channel3: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
+                .arg(digit[0] & 0xf).arg(digit[1] & 0xf)
+                .arg(digit[2] & 0xf)
+                .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
+                .arg(cmd[2], 0, 16));
+
+        if (!send_avc_command(m_priv->handle, m_node, cmd, 3))
+            return false;
+
+        return true;
+    }
+
+    return false;
+}
+
+bool LinuxFirewireDevice::SetPowerState(bool on)
+{
+    quadlet_t cmd =
+        AVC1394_CTYPE_CONTROL     | AVC1394_SUBUNIT_TYPE_UNIT |
+        AVC1394_SUBUNIT_ID_IGNORE | AVC1394_COMMAND_POWER;
+
+    cmd |= (on) ? AVC1394_CMD_OPERAND_POWER_ON : AVC1394_CMD_OPERAND_POWER_OFF;
+
+    QString cmdStr = (on) ? "on" : "off";
+    VERBOSE(VB_RECORD, LOC + QString("Powering %1 (cmd: 0x%2)")
+            .arg(cmdStr).arg(cmd, 0, 16));
+
+    quadlet_t *rval = send_avc_command(m_priv->handle, m_node, &cmd, 1);
+
+    if (!rval)
+    {
+        close_avc_command(m_priv->handle);
+        VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)");
+        return false;
+    }
+
+    quadlet_t response = rval[0];
+    close_avc_command(m_priv->handle);
+
+    if (AVC1394_MASK_RESPONSE(response) != AVC1394_RESPONSE_ACCEPTED)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                QString("Power %1 cmd failed (0x%2)")
+                .arg(cmdStr).arg(response, 0, 16));
+
+        return false;
+    }
+
+    VERBOSE(VB_RECORD, LOC +
+            QString("Power %1 cmd sent successfully (0x%2)")
+            .arg(cmdStr).arg(response, 0, 16));
+
+    return true;
+}
+
+FirewireDevice::PowerState LinuxFirewireDevice::GetPowerState(void)
+{
+    quadlet_t cmd =
+        AVC1394_CTYPE_STATUS      | AVC1394_SUBUNIT_TYPE_UNIT |
+        AVC1394_SUBUNIT_ID_IGNORE | AVC1394_COMMAND_POWER     |
+        AVC1394_CMD_OPERAND_POWER_STATE;
+
+    VERBOSE(VB_CHANNEL, LOC + QString("Requesting STB Power State (cmd: 0x%1)")
+            .arg(cmd, 0, 16));
+
+    quadlet_t *rval = send_avc_command(m_priv->handle, m_node, &cmd, 1);
+
+    if (!rval)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get STB Power State");
+        return kAVCPowerQueryFailed;
+    }
+
+    quadlet_t response = rval[0];
+    // TODO we probably need to call close_avc_command(m_priv->handle)...
+
+    QString loc = LOC + "STB Power State: ";
+    QString rs  = QString(" (0x%1)").arg(response, 0, 16);
+
+    if (AVC1394_MASK_RESPONSE(response) != AVC1394_RESPONSE_IMPLEMENTED)
+    {
+        VERBOSE(VB_CHANNEL, loc + "Query not implemented" + rs);
+        return kAVCPowerUnknown;
+    }
+
+    if (AVC1394_MASK_OPERAND0(response) == AVC1394_CMD_OPERAND_POWER_ON)
+    {
+        VERBOSE(VB_CHANNEL, loc + "On" + rs);
+        return kAVCPowerOn;
+    }
+
+    if (AVC1394_MASK_OPERAND0(response) == AVC1394_CMD_OPERAND_POWER_OFF)
+    {
+        VERBOSE(VB_CHANNEL, loc + "Off" + rs);
+        return kAVCPowerOff;
+    }
+    
+    VERBOSE(VB_IMPORTANT, LOC_ERR + "STB Power State: Unknown Response" + rs);
+
+    return kAVCPowerUnknown;
+}
+
+void LinuxFirewireDevice::PrintDropped(uint dropped_packets)
+{
+    if (dropped_packets == 1)
+    {
+        VERBOSE(VB_RECORD, LOC_ERR + "Dropped a TS packet");
+    }
+    else if (dropped_packets > 1)
+    {
+        VERBOSE(VB_RECORD, LOC_ERR + 
+                QString("Dropped %1 TS packets").arg(dropped_packets));
+    }
+}
+
+static int fw_tspacket_handler(unsigned char *tspacket, int len,
+                               uint dropped, void *callback_data)
+{
+    LinuxFirewireDevice *fw = (LinuxFirewireDevice*) callback_data;
+    if (!fw)
+        return 0;
+
+    if (dropped)
+        fw->PrintDropped(dropped);
+
+    if (len > 0)
+        fw->BroadcastToListeners(tspacket, len);
+
+    return 1;
+}
+
+static QString speed_to_string(uint speed)
+{
+    if (speed > RAW1394_ISO_SPEED_400)
+        return QString("Invalid Speed (%1)").arg(speed);
+
+    static const uint speeds[] = { 100, 200, 400, };
+    return QString("%1Mbps").arg(speeds[speed]);
+}
+
+static quadlet_t *send_avc_command(raw1394handle_t handle,
+                                   uint            node,
+                                   quadlet_t      *cmd,
+                                   uint            cmd_len,
+                                   uint            retry_cnt)
+{
+    if (!handle)
+        return NULL;
+
+    quadlet_t *ret = avc1394_transaction_block(
+        handle, node, cmd, cmd_len, retry_cnt);
+
+    if (!ret)
+        VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
+
+    return ret;
+}
+
+static void close_avc_command(raw1394handle_t handle)
+{
+    if (handle)
+        avc1394_transaction_block_close(handle);
+}
+
