Index: configure
===================================================================
--- configure.orig	2008-03-05 17:14:10.000000000 -0800
+++ configure	2008-03-05 17:17:38.000000000 -0800
@@ -158,6 +158,7 @@
   echo "  --disable-v4l            disable Video4Linux support"
   echo "  --disable-ivtv           disable ivtv support (PVR-x50) req. v4l support"
   echo "  --disable-dvb            disable DVB support"
+  echo "  --disable-r5000          disable support for R5000 USB STBs"
   echo "  --dvb-path=HDRLOC        location of directory containing"
   echo "                           'linux/dvb/frontend.h', not the"
   echo "                           directory with frontend.h [$dvb_path]"
@@ -888,6 +889,7 @@
     hdhomerun
     iptv
     ivtv
+    r5000
     joystick_menu
     libfftw3
     lirc
@@ -1042,6 +1044,7 @@
 dbox2_deps="backend"
 dvb_deps="backend"
 firewire_deps="backend"
+r5000_deps="backend"
 iptv_deps="backend"
 ivtv_deps="backend v4l"
 hdhomerun_deps="backend"
@@ -1175,6 +1178,7 @@
 hdhomerun="yes"
 iptv="yes"
 ivtv="yes"
+r5000="yes"
 joystick_menu="default"
 lamemp3="yes"
 lirc="yes"
@@ -2972,6 +2976,7 @@
   echo "DBox2 support             ${dbox2-no}"
   echo "HDHomeRun support         ${hdhomerun-no}"
   echo "IPTV support              ${iptv-no}"
+  echo "R5000 support             ${r5000-no}"
 fi
 
 if enabled frontend; then
Index: libs/libmythtv/cardutil.h
===================================================================
--- libs/libmythtv/cardutil.h.orig	2008-03-05 17:13:09.000000000 -0800
+++ libs/libmythtv/cardutil.h	2008-03-05 17:17:38.000000000 -0800
@@ -53,6 +53,7 @@
         FIREWIRE,
         HDHOMERUN,
         FREEBOX,
+        R5000,
     };
 
     static enum CARD_TYPES toCardType(const QString &name)
@@ -81,6 +82,8 @@
             return HDHOMERUN;
         if ("FREEBOX" == name)
             return FREEBOX;
+        if ("R5000" == name)
+            return R5000;
         return ERROR_UNKNOWN;
     }
 
@@ -89,13 +92,15 @@
         return
             (rawtype != "DVB")       &&
             (rawtype != "FIREWIRE")  && (rawtype != "DBOX2")   &&
-            (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX");
+            (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") &&
+	    (rawtype != "R5000");
     }
 
     static bool         IsUnscanable(const QString &rawtype)
     {
         return
-            (rawtype == "FIREWIRE")  || (rawtype == "DBOX2");
+            (rawtype == "FIREWIRE")  || (rawtype == "DBOX2") ||
+	    (rawtype == "R5000");
     }
 
     static bool         IsEITCapable(const QString &rawtype)
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro.orig	2008-03-05 17:13:55.000000000 -0800
+++ libs/libmythtv/libmythtv.pro	2008-03-15 07:26:37.000000000 -0700
@@ -491,6 +491,23 @@
         DEFINES += USING_DVB
     }
 
+    #Support for R5000 usb device
+    using_r5000 {
+        HEADERS += r5000channel.h           r5000recorder.h
+        HEADERS += r5000signalmonitor.h     r5000device.h
+	HEADERS += r5000/r5000.h            r5000/libusb_augment.h
+	HEADERS += r5000/r5000_internal.h   r5000/r5000init.h
+
+        SOURCES += r5000channel.cpp         r5000recorder.cpp
+        SOURCES += r5000signalmonitor.cpp   r5000device.cpp
+	SOURCES += r5000/r5000.c            r5000/libusb_augment.c
+	SOURCES += r5000/r5k_vip.c          r5000/r5k_directv.c
+	SOURCES += r5000/r5k_sat.c          r5000/r5k_misc.c
+
+	LIBS += -lusb
+        DEFINES += USING_R5000
+    }
+
     DEFINES += USING_BACKEND
 }
 
Index: libs/libmythtv/signalmonitor.h
===================================================================
--- libs/libmythtv/signalmonitor.h.orig	2008-03-05 17:13:09.000000000 -0800
+++ libs/libmythtv/signalmonitor.h	2008-03-05 17:17:38.000000000 -0800
@@ -297,7 +297,8 @@
             (cardtype.upper() == "HDTV")      ||
             (cardtype.upper() == "HDHOMERUN") ||
             (cardtype.upper() == "FIREWIRE")  ||
-            (cardtype.upper() == "FREEBOX"));
+            (cardtype.upper() == "FREEBOX")   ||
+            (cardtype.upper() == "R5000"));
 }
 
 inline bool SignalMonitor::IsSupported(const QString &cardtype)
Index: libs/libmythtv/signalmonitor.cpp
===================================================================
--- libs/libmythtv/signalmonitor.cpp.orig	2008-03-05 17:13:09.000000000 -0800
+++ libs/libmythtv/signalmonitor.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -41,6 +41,11 @@
 #   include "firewirechannel.h"
 #endif
 
+#ifdef USING_R5000
+#   include "r5000signalmonitor.h"
+#   include "r5000channel.h"
+#endif
+
 #undef DBG_SM
 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
     "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
@@ -127,6 +132,14 @@
             signalMonitor = new FirewireSignalMonitor(db_cardnum, fc);
     }
 #endif
+#ifdef USING_R5000
+    if (cardtype.upper() == "R5000")
+    {
+        R5000Channel *fc = dynamic_cast<R5000Channel*>(channel);
+        if (fc)
+            signalMonitor = new R5000SignalMonitor(db_cardnum, fc);
+    }
+#endif
 
     if (!signalMonitor)
     {
Index: libs/libmythtv/cardutil.cpp
===================================================================
--- libs/libmythtv/cardutil.cpp.orig	2008-03-05 17:13:09.000000000 -0800
+++ libs/libmythtv/cardutil.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -1457,7 +1457,8 @@
     if (("FIREWIRE"  == cardtype) ||
         ("FREEBOX"   == cardtype) ||
         ("DBOX2"     == cardtype) ||
-        ("HDHOMERUN" == cardtype))
+        ("HDHOMERUN" == cardtype) ||
+        ("R5000"     == cardtype))
     {
         ret += "MPEG2TS";
     }
@@ -1582,7 +1583,8 @@
     if (("FIREWIRE"  == cardtype) ||
         ("FREEBOX"   == cardtype) ||
         ("DBOX2"     == cardtype) ||
-        ("HDHOMERUN" == cardtype))
+        ("HDHOMERUN" == cardtype) ||
+	("R5000"     == cardtype))
     {
         inputs += "MPEG2TS";
     }
Index: libs/libmythtv/videosource.cpp
===================================================================
--- libs/libmythtv/videosource.cpp.orig	2008-03-05 17:13:56.000000000 -0800
+++ libs/libmythtv/videosource.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -36,6 +36,7 @@
 #include "frequencies.h"
 #include "diseqcsettings.h"
 #include "firewiredevice.h"
+#include "r5000device.h"
 #include "compat.h"
 
 
@@ -1297,6 +1298,58 @@
     }
 };
 
+class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage
+{
+  public:
+    R5000Serial(const CaptureCard &parent) :
+        ComboBoxSetting(this),
+        CaptureCardDBStorage(this, parent, "videodevice")
+    {
+        setLabel(QObject::tr("Serial #"));
+#ifdef USING_R5000
+        QStringList serials = R5000Device::GetSTBList();
+        for (uint i = 0; i < serials.size(); i++)
+        {
+            addSelection(serials[i]);
+        }
+#endif // USING_FIREWIRE
+    }
+};
+
+class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage
+{
+  public:
+    R5000Model(const CaptureCard  &parent) :
+      ComboBoxSetting(this),
+      CaptureCardDBStorage(this, parent, "firewire_model")
+    {
+        setLabel(QObject::tr("R5000 STB type"));
+        addSelection("VIP211/VIP622/DISH411");
+        addSelection("DIRECTV");
+        addSelection("STARCHOICE/DSR");
+        addSelection("HDD-200");
+        QString help = QObject::tr(
+            "Choose the type of R5000 enabled STB you are using.");
+        setHelpText(help);
+    }
+};
+class R5000ConfigurationGroup : public VerticalConfigurationGroup
+{
+  public:
+    R5000ConfigurationGroup(CaptureCard& a_parent):
+       VerticalConfigurationGroup(false, true, false, false),
+       parent(a_parent)
+    {
+        setUseLabel(false);
+        addChild(new R5000Serial(parent));
+        addChild(new R5000Model(parent));
+        addChild(new SingleCardInput(parent));
+    };
+
+  private:
+    CaptureCard &parent;
+};
+
 class IPTVHost : public LineEditSetting, public CaptureCardDBStorage
 {
   public:
@@ -1481,6 +1534,10 @@
 #ifdef USING_IPTV
     addTarget("FREEBOX",   new IPTVConfigurationGroup(parent));
 #endif // USING_IPTV
+
+#ifdef USING_R5000
+    addTarget("R5000", new R5000ConfigurationGroup(parent));
+#endif // USING_R5000
 }
 
 void CaptureCardGroup::triggerChanged(const QString& value) 
@@ -1668,6 +1725,10 @@
 #ifdef USING_IPTV
     setting->addSelection(QObject::tr("Network Recorder"), "FREEBOX");
 #endif // USING_IPTV
+
+#ifdef USING_R5000
+    setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000");
+#endif // USING_R5000
 }
 
 class CardID : public SelectLabelSetting, public CardInputDBStorage
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp.orig	2008-03-05 17:14:24.000000000 -0800
+++ libs/libmythtv/tv_rec.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -50,6 +50,7 @@
 #include "hdhrchannel.h"
 #include "iptvchannel.h"
 #include "firewirechannel.h"
+#include "r5000channel.h"
 
 #include "recorderbase.h"
 #include "NuppelVideoRecorder.h"
@@ -59,6 +60,7 @@
 #include "hdhrrecorder.h"
 #include "iptvrecorder.h"
 #include "firewirerecorder.h"
+#include "r5000recorder.h"
 
 #ifdef USING_V4L
 #include "channel.h"
@@ -199,6 +201,16 @@
         init_run = true;
 #endif
     }    
+    else if (genOpt.cardtype == "R5000")
+    {
+#ifdef USING_R5000
+        channel = new R5000Channel(this, genOpt.videodev, fwOpt.model);
+        if (!channel->Open())
+            return false;
+        InitChannel(genOpt.defaultinput, startchannel);
+        init_run = true;
+#endif
+    }
     else // "V4L" or "MPEG", ie, analog TV
     {
 #ifdef USING_V4L
@@ -1017,6 +1029,12 @@
         recorder->SetOption("mrl", genOpt.videodev);
 #endif // USING_IPTV
     }
+    else if (genOpt.cardtype == "R5000")
+    {
+#ifdef USING_R5000
+        recorder = new R5000Recorder(this, GetR5000Channel());
+#endif // USING_R5000
+    }
     else
     {
 #ifdef USING_V4L
@@ -1230,6 +1248,15 @@
 #endif // USING_FIREWIRE
 }
 
+R5000Channel *TVRec::GetR5000Channel(void)
+{
+#ifdef USING_R5000
+    return dynamic_cast<R5000Channel*>(channel);
+#else
+    return NULL;
+#endif // USING_R5000
+}
+
 Channel *TVRec::GetV4LChannel(void)
 {
 #ifdef USING_V4L
Index: libs/libmythtv/transporteditor.cpp
===================================================================
--- libs/libmythtv/transporteditor.cpp.orig	2008-03-05 17:13:09.000000000 -0800
+++ libs/libmythtv/transporteditor.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -735,7 +735,8 @@
         left->addChild(new Modulation(id, nType));
     }
     else if ((CardUtil::FIREWIRE == nType) ||
-             (CardUtil::FREEBOX  == nType))
+             (CardUtil::FREEBOX  == nType) ||
+             (CardUtil::R5000    == nType))
     {
         left->addChild(new DTVStandard(id, true, true));
     }
Index: libs/libmythtv/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h.orig	2008-03-05 17:13:09.000000000 -0800
+++ libs/libmythtv/tv_rec.h	2008-03-05 17:17:38.000000000 -0800
@@ -39,6 +39,7 @@
 class FirewireChannel;
 class Channel;
 class HDHRChannel;
+class R5000Channel;
 
 class MPEGStreamData;
 class ProgramMapTable;
@@ -281,6 +282,7 @@
     HDHRChannel  *GetHDHRChannel(void);
     DVBChannel   *GetDVBChannel(void);
     FirewireChannel *GetFirewireChannel(void);
+    R5000Channel *GetR5000Channel(void);
     Channel      *GetV4LChannel(void);
 
     bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
Index: libs/libmythtv/r5000channel.cpp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000channel.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,187 @@
+/**
+ *  R5000Channel
+ *  Copyright (c) 2005 by Jim Westfall, Dave Abrahams
+ *  Copyright (c) 2006 by Daniel Kristjansson
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "mythcontext.h"
+#include "tv_rec.h"
+#include "r5000channel.h"
+
+#define LOC QString("R5kChan(%1): ").arg(GetDevice())
+#define LOC_WARN QString("R5kChan(%1), Warning: ").arg(GetDevice())
+#define LOC_ERR QString("R5kChan(%1), Error: ").arg(GetDevice())
+
+R5000Channel::R5000Channel(TVRec *parent, const QString &_videodevice,const QString &_r5ktype) :
+    DTVChannel(parent),
+    videodevice(_videodevice),
+    device(NULL),
+    current_channel(0),
+    isopen(false)
+{
+    int type = R5000Device::GetDeviceType(_r5ktype);
+    device = new R5000Device(type, videodevice);
+
+    InitializeInputs();
+}
+
+bool R5000Channel::SetChannelByString(const QString &channum)
+{
+    QString loc = LOC + QString("SetChannelByString(%1)").arg(channum);
+    bool ok = true;
+    VERBOSE(VB_CHANNEL, loc);
+
+    InputMap::const_iterator it = inputs.find(currentInputID);
+    if (it == inputs.end())
+        return false;
+
+    QString tvformat, modulation, freqtable, freqid, dtv_si_std;
+    int finetune;
+    uint64_t frequency;
+    int mpeg_prog_num;
+    uint atsc_major, atsc_minor, mplexid, tsid, netid;
+    if (!ChannelUtil::GetChannelData(
+        (*it)->sourceid, channum,
+        tvformat, modulation, freqtable, freqid,
+        finetune, frequency,
+        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
+        mplexid, commfree))
+    {
+        VERBOSE(VB_IMPORTANT, loc + " " + QString(
+                    "Requested channel '%1' is on input '%2' "
+                    "which is in a busy input group")
+                .arg(channum).arg(currentInputID));
+
+        return false;
+    }
+    uint mplexid_restriction;
+    if (!IsInputAvailable(currentInputID, mplexid_restriction))
+    {
+        VERBOSE(VB_IMPORTANT, loc + " " + QString(
+                    "Requested channel '%1' is on input '%2' "
+                    "which is in a busy input group")
+                .arg(channum).arg(currentInputID));
+
+        return false;
+    }
+
+    uint ichan = freqid.toUInt(&ok);
+    ok = isopen && SetChannelByNumber(ichan);
+
+    if (ok)
+    {
+        // Set the current channum to the new channel's channum
+        curchannelname = QDeepCopy<QString>(channum);
+        (*it)->startChanNum = QDeepCopy<QString>(channum);
+    }
+
+    VERBOSE(VB_CHANNEL, loc + " " + ((ok) ? "success" : "failure"));
+
+    return ok;
+}
+
+bool R5000Channel::Open(void)
+{
+    VERBOSE(VB_CHANNEL, LOC + "Open()");
+
+    if (inputs.find(currentInputID) == inputs.end())
+        return false;
+
+    if (!device)
+        return false;
+
+    if (isopen)
+        return true;
+
+    if (!device->OpenPort())
+        return false;
+
+    isopen = true;
+
+    return true;
+}
+
+void R5000Channel::Close(void)
+{
+    VERBOSE(VB_CHANNEL, LOC + "Close()");
+    if (isopen)
+    {
+        device->ClosePort();
+        isopen = false;
+    }
+}
+
+QString R5000Channel::GetDevice(void) const
+{
+    return videodevice;
+}
+
+bool R5000Channel::SetPowerState(bool on)
+{
+    if (!isopen)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                "SetPowerState() called on closed R5000Channel.");
+
+        return false;
+    }
+
+    return device->SetPowerState(on);
+}
+
+R5000Device::PowerState R5000Channel::GetPowerState(void) const
+{
+    if (!isopen)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                "GetPowerState() called on closed R5000Channel.");
+
+        return R5000Device::kAVCPowerQueryFailed;
+    }
+
+    return device->GetPowerState();
+}
+
+bool R5000Channel::Retune(void)
+{
+    VERBOSE(VB_CHANNEL, LOC + "Retune()");
+
+    if (R5000Device::kAVCPowerOff == GetPowerState())
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                "STB is turned off, must be on to retune.");
+
+        return false;
+    }
+
+    if (current_channel)
+        return SetChannelByNumber(current_channel);
+
+    return false;
+}
+
+bool R5000Channel::SetChannelByNumber(int channel)
+{
+    VERBOSE(VB_CHANNEL, QString("SetChannelByNumber(%1)").arg(channel));
+    current_channel = channel;
+
+    if (R5000Device::kAVCPowerOff == GetPowerState())
+    {
+        VERBOSE(VB_IMPORTANT, LOC_WARN +
+                "STB is turned off, must be on to set channel.");
+
+        SetSIStandard("mpeg");
+        SetDTVInfo(0,0,0,0,1);
+
+        return true; // signal monitor will call retune later...
+    }
+
+    if (!device->SetChannel(fw_opts.model, 0, channel))
+        return false;
+
+    SetSIStandard("mpeg");
+    SetDTVInfo(0,0,0,0,1);
+
+    return true;
+}
Index: libs/libmythtv/r5000device.cpp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000device.cpp	2008-03-15 08:20:39.000000000 -0700
@@ -0,0 +1,407 @@
+/**
+ *  R5000Device
+ *  Copyright (c) 2008 by Alan Nisota
+ *  Copyright (c) 2005 by Jim Westfall
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+// Qt headers
+#include <qdeepcopy.h>
+
+// MythTV headers
+#include "r5000device.h"
+#include "mythcontext.h"
+#include "pespacket.h"
+
+#define LOC      QString("R5kDev: ")
+#define LOC_WARN QString("R5kDev, Warning: ")
+#define LOC_ERR  QString("R5kDev, Error: ")
+
+QMap<uint64_t,QString> R5000Device::s_id_to_model;
+QMutex                 R5000Device::s_static_lock;
+
+unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data)
+{
+    R5000Device *fw = (R5000Device*) callback_data;
+    if (! fw)
+        return 0;
+    if (len > 0)
+        fw->BroadcastToListeners(tspacket, len);
+    return 1;
+}
+
+
+class R5kPriv
+{
+  public:
+    R5kPriv() :
+        reset_timer_on(false),
+        run_port_handler(false), is_port_handler_running(false),
+        channel(-1),
+        is_streaming(false)
+    {
+    }
+
+    bool             reset_timer_on;
+    MythTimer        reset_timer;
+
+    bool             run_port_handler;
+    bool             is_port_handler_running;
+    QMutex           start_stop_port_handler_lock;
+
+    int              channel;
+
+    bool             is_streaming;
+
+    QDateTime        stop_streaming_timer;
+    pthread_t        port_handler_thread;
+
+    static QMutex           s_lock;
+};
+QMutex          R5kPriv::s_lock;
+
+//callback functions
+void *r5000_device_port_handler_thunk(void *param);
+
+R5000Device::R5000Device(int type, QString serial) :
+    m_type(type),
+    m_serial(serial),
+    m_last_channel(0),      m_last_crc(0),
+    m_buffer_cleared(true), m_open_port_cnt(0),
+    m_lock(false),          m_priv(new R5kPriv())
+{
+  usbdev = NULL;
+}
+
+R5000Device::~R5000Device()
+{
+    if (usbdev)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port");
+        while(usbdev)
+            ClosePort();
+    }
+
+    if (m_priv)
+    {
+        delete m_priv;
+        m_priv = NULL;
+    }
+}
+
+void R5000Device::AddListener(TSDataListener *listener)
+{
+    if (listener)
+    {
+        vector<TSDataListener*>::iterator it =
+            find(m_listeners.begin(), m_listeners.end(), listener);
+
+        if (it == m_listeners.end())
+            m_listeners.push_back(listener);
+    }
+
+    VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size());
+    if (!m_listeners.empty())
+    {
+        StartStreaming();
+    }
+}
+
+void R5000Device::RemoveListener(TSDataListener *listener)
+{
+    vector<TSDataListener*>::iterator it = m_listeners.end();
+
+    do
+    {
+        it = find(m_listeners.begin(), m_listeners.end(), listener);
+        if (it != m_listeners.end())
+            m_listeners.erase(it);
+    }
+    while (it != m_listeners.end());
+
+    VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size());
+    if (m_listeners.empty())
+    {
+        StopStreaming();
+    }
+}
+
+bool R5000Device::StartStreaming(void)
+{
+    if (m_priv->is_streaming)
+        return m_priv->is_streaming;
+
+    if (! usbdev)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Device not open");
+        return false;
+    }
+    if (r5000_start_stream(usbdev))
+    {
+        m_priv->is_streaming = true;
+    }
+    else
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming ");
+    }
+
+    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- done");
+
+    return m_priv->is_streaming;
+}
+
+bool R5000Device::StopStreaming(void)
+{
+    if (m_priv->is_streaming)
+    {
+        VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really");
+
+        m_priv->is_streaming = false;
+
+        r5000_stop_stream(usbdev);
+    }
+
+    VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming");
+
+    return true;
+}
+
+bool R5000Device::SetPowerState(bool on)
+{
+    QMutexLocker locker(&m_lock);
+    QString cmdStr = (on) ? "on" : "off";
+    VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr));
+    if(r5000_get_power_state(usbdev) != on)
+      r5000_toggle_on_off(usbdev);
+    return true;
+}
+
+R5000Device::PowerState R5000Device::GetPowerState(void)
+{
+    QMutexLocker locker(&m_lock);
+    int on_off;
+
+    VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State");
+    on_off = r5000_get_power_state(usbdev);
+    VERBOSE(VB_CHANNEL, LOC + (on_off ? "On" : "Off"));
+    return on_off ? kAVCPowerOn : kAVCPowerOff;
+}
+
+bool R5000Device::SetChannel(const QString &panel_model,
+                                uint alt_method, uint channel)
+{
+    VERBOSE(VB_CHANNEL, QString("SetChannel(model %1, alt %2, chan %3)")
+            .arg(panel_model).arg(alt_method).arg(channel));
+
+    QMutexLocker locker(&m_lock);
+    VERBOSE(VB_CHANNEL, "SetChannel() -- locked");
+    if(! r5000_change_channel(usbdev, channel))
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to set channel");
+    return true;
+}
+
+void R5000Device::BroadcastToListeners(
+    const unsigned char *data, uint dataSize)
+{
+    if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) &&
+        ((data[1] & 0x1f) == 0) && (data[2] == 0))
+    {
+        ProcessPATPacket(*((const TSPacket*)data));
+    }
+
+    vector<TSDataListener*>::iterator it = m_listeners.begin();
+    for (; it != m_listeners.end(); ++it)
+        (*it)->AddData(data, dataSize);
+}
+
+void R5000Device::SetLastChannel(const uint channel)
+{
+    m_buffer_cleared = (channel == m_last_channel);
+    m_last_channel   = channel;
+
+    VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2")
+            .arg(channel).arg(m_buffer_cleared ? "yes" : "no"));
+}
+
+void R5000Device::ProcessPATPacket(const TSPacket &tspacket)
+{
+    if (!tspacket.TransportError() && !tspacket.ScramplingControl() &&
+        tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID())
+    {
+        PESPacket pes = PESPacket::View(tspacket);
+        uint crc = pes.CalcCRC();
+        m_buffer_cleared |= (crc != m_last_crc);
+        m_last_crc = crc;
+#if 0
+        VERBOSE(VB_RECORD, LOC +
+                QString("ProcessPATPacket: CRC 0x%1 cleared: %2")
+                .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no"));
+#endif
+    }
+    else
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's");
+    }
+}
+
+QString R5000Device::GetModelName(uint vendor_id, uint model_id)
+{
+    QMutexLocker locker(&s_static_lock);
+/*
+    if (s_id_to_model.empty())
+        fw_init(s_id_to_model);
+
+    QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id];
+
+    if (ret.isEmpty())
+        return "GENERIC";
+*/
+    return "R5000";
+}
+
+bool R5000Device::IsSTBSupported(const QString &panel_model)
+{
+    return true;
+}
+
+bool R5000Device::OpenPort(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread");
+    QMutexLocker mlocker(&m_lock);
+    VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread -- locked");
+    if(usbdev) {
+        m_open_port_cnt++;
+        return true;
+    }
+
+    if(m_serial) {
+      VERBOSE(VB_RECORD, LOC + "Opening R5000 device with serial#: "+ m_serial);
+      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.ascii());
+    } else {
+      VERBOSE(VB_RECORD, LOC + "Opening R5000 device with unknown serial#");
+      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL);
+    }
+    if(! usbdev) {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to open R5000 device");
+        return false;
+    }
+
+    VERBOSE(VB_RECORD, LOC + "Starting port handler thread");
+    m_priv->run_port_handler = true;
+    pthread_create(&m_priv->port_handler_thread, NULL,
+                   r5000_device_port_handler_thunk, this);
+
+    VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to start");
+    while (!m_priv->is_port_handler_running)
+    {
+        m_lock.unlock();
+        usleep(5000);
+        m_lock.lock();
+    }
+
+    VERBOSE(VB_RECORD, LOC + "Port handler thread started");
+
+    m_open_port_cnt++;
+
+    return true;
+}
+
+bool R5000Device::ClosePort(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread");
+    QMutexLocker locker(&m_priv->start_stop_port_handler_lock);
+    VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread -- locked");
+
+    QMutexLocker mlocker(&m_lock);
+
+    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 (!usbdev)
+        return false;
+
+    VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to stop");
+    m_priv->run_port_handler = false;
+    while (m_priv->is_port_handler_running)
+    {
+        m_lock.unlock();
+        usleep(5000);
+        m_lock.lock();
+    }
+    VERBOSE(VB_RECORD, LOC + "Joining port handler thread");
+    pthread_join(m_priv->port_handler_thread, NULL);
+
+    r5000_close(usbdev);
+    usbdev = NULL;
+
+    return true;
+}
+
+void *r5000_device_port_handler_thunk(void *param)
+{
+    R5000Device *mon = (R5000Device*) param;
+    mon->RunPortHandler();
+    return NULL;
+}
+
+void R5000Device::RunPortHandler(void)
+{
+    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- start");
+    m_lock.lock();
+    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- got first lock");
+    m_priv->is_port_handler_running = true;
+    m_lock.unlock();
+
+    while (m_priv->run_port_handler)
+    {
+        if (m_priv->is_streaming) {
+            // This will timeout after 10ms regardless of data availability
+            r5000_loop_iterate(usbdev, 10);
+        } else {
+            usleep(10000);
+        }
+    }
+
+    m_lock.lock();
+    m_priv->is_port_handler_running = false;
+    m_lock.unlock();
+    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- end");
+}
+
+QStringList R5000Device::GetSTBList(void)
+{
+    QStringList STBList;
+    int i;
+    r5kenum_t r5k_stbs;
+    if (! r5000_find_stbs(&r5k_stbs))
+        VERBOSE(VB_IMPORTANT, LOC + "Locating R5000 devices failed."
+                                    "  This may be a permission problem");
+
+    for (i = 0; i < r5k_stbs.count; i++)
+        STBList.append((char *)r5k_stbs.serial[i]);
+    return STBList;
+}
+
+int R5000Device::GetDeviceType(const QString &r5ktype)
+{
+  QString type = r5ktype.upper();
+  if(type == "DIRECTV") {
+    return R5K_STB_DIRECTV;
+  } else if(type == "VIP211/VIP622/DISH411" ||
+            type == "VIP211/VIP422") {
+    return R5K_STB_VIP;
+  } else if(type == "STARCHOICE/DSR") {
+    return R5K_STB_DSR;
+  } else if(type == "HDD-200") {
+    return R5K_STB_HDD;
+  } else {
+    return R5K_STB_VIP;
+  }
+}
Index: libs/libmythtv/r5000recorder.cpp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000recorder.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,238 @@
+/**
+ *  R5000Recorder
+ *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+// MythTV includes
+#include "r5000recorder.h"
+#include "r5000channel.h"
+#include "mythcontext.h"
+#include "mpegtables.h"
+#include "mpegstreamdata.h"
+#include "tv_rec.h"
+
+#define LOC QString("R5000RecBase(%1): ").arg(channel->GetDevice())
+#define LOC_ERR QString("R5000RecBase(%1), Error: ").arg(channel->GetDevice())
+
+R5000Recorder::R5000Recorder(TVRec *rec, R5000Channel *chan) :
+    DTVRecorder(rec), _mpeg_stream_data(NULL),
+    channel(chan), isopen(false)
+{
+}
+
+R5000Recorder::~R5000Recorder()
+{
+    SetStreamData(NULL);
+    Close();
+}
+
+bool R5000Recorder::Open(void)
+{
+    if (!isopen)
+        isopen = channel->GetR5000Device()->OpenPort();
+
+    return isopen;
+}
+
+void R5000Recorder::Close(void)
+{
+    if (isopen)
+    {
+        channel->GetR5000Device()->ClosePort();
+        isopen = false;
+    }
+}
+
+void R5000Recorder::StartStreaming(void)
+{
+    channel->GetR5000Device()->AddListener(this);
+}
+
+void R5000Recorder::StopStreaming(void)
+{
+    channel->GetR5000Device()->RemoveListener(this);
+}
+
+void R5000Recorder::StartRecording(void)
+{
+    VERBOSE(VB_RECORD, LOC + "StartRecording");
+
+    if (!Open())
+    {
+        _error = true;
+        return;
+    }
+
+    _request_recording = true;
+    _recording = true;
+
+    StartStreaming();
+
+    while (_request_recording)
+    {
+        if (!PauseAndWait())
+            usleep(50 * 1000);
+    }
+
+    StopStreaming();
+    FinishRecording();
+
+    _recording = false;
+}
+
+void R5000Recorder::AddData(const unsigned char *data, uint len)
+{
+    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;
+    }
+
+    buffer.insert(buffer.end(), data, data + len);
+    bufsz += len;
+
+    int sync_at = -1;
+    for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
+    {
+        if (buffer[i] == SYNC_BYTE)
+            sync_at = i;
+    }
+
+    if (sync_at < 0)
+        return;
+
+    if (bufsz < 30 * TSPacket::SIZE)
+        return; // build up a little buffer
+
+    while (sync_at + TSPacket::SIZE < bufsz)
+    {
+        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
+                              &buffer[0] + sync_at)));
+
+        sync_at += TSPacket::SIZE;
+    }
+
+    buffer.erase(buffer.begin(), buffer.begin() + sync_at);
+
+    return;
+}
+
+void R5000Recorder::ProcessTSPacket(const TSPacket &tspacket)
+{
+    if (tspacket.TransportError())
+        return;
+
+    if (tspacket.ScramplingControl())
+        return;
+
+    if (tspacket.HasAdaptationField())
+        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 == GetStreamData()->VideoPIDSingleProgram())
+        {
+            _buffer_packets = !FindMPEG2Keyframes(&tspacket);
+            BufferedWrite(tspacket);
+        }
+        else if (GetStreamData()->IsAudioPID(lpid))
+        {
+            _buffer_packets = !FindAudioKeyframes(&tspacket);
+            BufferedWrite(tspacket);
+        }
+        else if (GetStreamData()->IsListeningPID(lpid))
+            GetStreamData()->HandleTSTables(&tspacket);
+        else if (GetStreamData()->IsWritingPID(lpid))
+            BufferedWrite(tspacket);
+    }
+}
+
+void R5000Recorder::SetOptionsFromProfile(RecordingProfile *profile,
+                                                 const QString &videodev,
+                                                 const QString &audiodev,
+                                                 const QString &vbidev)
+{
+    (void)videodev;
+    (void)audiodev;
+    (void)vbidev;
+    (void)profile;
+}
+
+// documented in recorderbase.cpp
+bool R5000Recorder::PauseAndWait(int timeout)
+{
+    if (request_pause)
+    {
+        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause");
+        if (!paused)
+        {
+            StopStreaming();
+            paused = true;
+            pauseWait.wakeAll();
+            if (tvrec)
+                tvrec->RecorderPaused();
+        }
+        unpauseWait.wait(timeout);
+    }
+    if (!request_pause && paused)
+    {
+        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause");
+        StartStreaming();
+        paused = false;
+    }
+    return paused;
+}
+
+void R5000Recorder::SetStreamData(MPEGStreamData *data)
+{
+    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin");
+    if (data == _mpeg_stream_data)
+    {
+        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0");
+        return;
+    }
+
+    MPEGStreamData *old_data = _mpeg_stream_data;
+    _mpeg_stream_data = data;
+    if (old_data)
+        delete old_data;
+
+    if (data)
+    {
+        data->AddMPEGSPListener(this);
+
+        if (data->DesiredProgram() >= 0)
+            data->SetDesiredProgram(data->DesiredProgram());
+    }
+    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1");
+}
+
+void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
+{
+    if (!pat) {
+        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)");
+        return;
+    }
+    int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
+    pat->tsheader()->SetContinuityCounter(next);
+    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));
+}
+
+void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
+{
+    if (!pmt) {
+        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)");
+        return;
+    }
+    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
+    pmt->tsheader()->SetContinuityCounter(next);
+    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));
+}
Index: libs/libmythtv/r5000signalmonitor.cpp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000signalmonitor.cpp	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,312 @@
+// -*- 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 "atscstreamdata.h"
+#include "mpegtables.h"
+#include "atsctables.h"
+#include "r5000channel.h"
+#include "r5000signalmonitor.h"
+
+#define LOC QString("R5kSM(%1): ").arg(channel->GetDevice())
+#define LOC_WARN QString("R5kSM(%1), Warning: ").arg(channel->GetDevice())
+#define LOC_ERR QString("R5kSM(%1), Error: ").arg(channel->GetDevice())
+
+const uint R5000SignalMonitor::kPowerTimeout  = 3000; /* ms */
+const uint R5000SignalMonitor::kBufferTimeout = 5000; /* ms */
+
+QMap<void*,uint> R5000SignalMonitor::pat_keys;
+QMutex           R5000SignalMonitor::pat_keys_lock;
+
+/** \fn R5000SignalMonitor::R5000SignalMonitor(int,R5000Channel*,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 R5000Channel for card
+ *  \param _flags   Flags to start with
+ *  \param _name    Name for Qt signal debugging
+ */
+R5000SignalMonitor::R5000SignalMonitor(
+    int db_cardnum,
+    R5000Channel *_channel,
+    uint64_t _flags, const char *_name) :
+    DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
+    dtvMonitorRunning(false),
+    stb_needs_retune(true),
+    stb_needs_to_wait_for_pat(false),
+    stb_needs_to_wait_for_power(false)
+{
+    VERBOSE(VB_CHANNEL, LOC + "ctor");
+
+    signalStrength.SetThreshold(65);
+
+    AddFlags(kDTVSigMon_WaitForSig);
+
+    stb_needs_retune =
+        (R5000Device::kAVCPowerOff == _channel->GetPowerState());
+}
+
+/** \fn R5000SignalMonitor::~R5000SignalMonitor()
+ *  \brief Stops signal monitoring and table monitoring threads.
+ */
+R5000SignalMonitor::~R5000SignalMonitor()
+{
+    VERBOSE(VB_CHANNEL, LOC + "dtor");
+    Stop();
+}
+
+void R5000SignalMonitor::deleteLater(void)
+{
+    disconnect(); // disconnect signals we may be sending...
+    Stop();
+    DTVSignalMonitor::deleteLater();
+}
+
+/** \fn R5000SignalMonitor::Stop(void)
+ *  \brief Stop signal monitoring and table monitoring threads.
+ */
+void R5000SignalMonitor::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 R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat)
+{
+    AddFlags(kDTVSigMon_PATSeen);
+
+    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel);
+    bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared();
+    if (crc_bogus && stb_needs_to_wait_for_pat &&
+        (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout))
+    {
+        VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT");
+        uint tsid = pat->TransportStreamID();
+        GetStreamData()->SetVersionPAT(tsid, -1,0);
+        return;
+    }
+
+    if (crc_bogus && stb_needs_to_wait_for_pat)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out");
+        stb_needs_to_wait_for_pat = false;
+    }
+
+    DTVSignalMonitor::HandlePAT(pat);
+}
+
+void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt)
+{
+    VERBOSE(VB_CHANNEL, LOC + "HandlePMT()");
+
+    AddFlags(kDTVSigMon_PMTSeen);
+
+    if (!HasFlags(kDTVSigMon_PATMatch))
+    {
+        GetStreamData()->SetVersionPMT(pnum, -1,0);
+        VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT");
+        return;
+    }
+
+    DTVSignalMonitor::HandlePMT(pnum, pmt);
+}
+
+void *R5000SignalMonitor::TableMonitorThread(void *param)
+{
+    R5000SignalMonitor *mon = (R5000SignalMonitor*) param;
+    mon->RunTableMonitor();
+    return NULL;
+}
+
+void R5000SignalMonitor::RunTableMonitor(void)
+{
+    stb_needs_to_wait_for_pat = true;
+    stb_wait_for_pat_timer.start();
+    dtvMonitorRunning = true;
+
+    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin");
+
+    R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel);
+    if (!lchan)
+    {
+        VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end");
+        dtvMonitorRunning = false;
+        return;
+    }
+
+    R5000Device *dev = lchan->GetR5000Device();
+
+    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 R5000SignalMonitor::AddData(const unsigned char *data, uint len)
+{
+    if (!dtvMonitorRunning)
+        return;
+
+    if (GetStreamData())
+        GetStreamData()->ProcessData((unsigned char *)data, len);
+}
+
+/** \fn R5000SignalMonitor::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 R5000SignalMonitor::UpdateValues(void)
+{
+    if (!running || exit)
+        return;
+
+    if (dtvMonitorRunning)
+    {
+        EmitR5000Signals();
+        if (IsAllGood())
+            emit AllGood();
+        // TODO dtv signals...
+
+        update_done = true;
+        return;
+    }
+
+    if (stb_needs_to_wait_for_power &&
+        (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout))
+    {
+        return;
+    }
+    stb_needs_to_wait_for_power = false;
+
+    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel);
+
+    if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch))
+    {
+        bool retried = false;
+        while (true)
+        {
+            R5000Device::PowerState power = fwchan->GetPowerState();
+            if (R5000Device::kAVCPowerOn == power)
+            {
+                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
+            }
+            else if (R5000Device::kAVCPowerOff == power)
+            {
+                AddFlags(kFWSigMon_PowerSeen);
+                fwchan->SetPowerState(true);
+                stb_wait_for_power_timer.start();
+                stb_needs_to_wait_for_power = true;
+            }
+            else
+            {
+                bool qfailed = (R5000Device::kAVCPowerQueryFailed == power);
+                if (qfailed && !retried)
+                {
+                    retried = true;
+                    continue;
+                }
+
+                VERBOSE(VB_RECORD, "Can't determine if STB is power on, "
+                        "assuming it is...");
+                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
+            }
+            break;
+        }
+    }
+
+    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);
+    }
+
+    EmitR5000Signals();
+    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 R5000SignalMonitor::EmitR5000Signals(void)
+ *  \brief Emits signals for lock, signal strength, etc.
+ */
+void R5000SignalMonitor::EmitR5000Signals(void)
+{
+    // Emit signals..
+    EMIT(StatusSignalLock, signalLock);
+    if (HasFlags(kDTVSigMon_WaitForSig))
+        EMIT(StatusSignalStrength, signalStrength);
+}
+
+#undef EMIT
Index: libs/libmythtv/r5000channel.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000channel.h	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,51 @@
+/**
+ *  R5000Channel
+ *  Copyright (c) 2008 by Alan Nisota
+ *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _R5000CHANNEL_H_
+#define _R5000CHANNEL_H_
+
+#include "tv_rec.h"
+#include "dtvchannel.h"
+#include "r5000device.h"
+
+class R5000Channel : public DTVChannel
+{
+  public:
+    R5000Channel(TVRec *parent, const QString &videodevice,
+                    const QString &_r5ktype);
+    ~R5000Channel() { Close(); }
+
+    // Commands
+    virtual bool Open(void);
+    virtual 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);
+
+    // Sets
+    virtual bool SetChannelByString(const QString &chan);
+    virtual bool SetChannelByNumber(int channel);
+    virtual bool SetPowerState(bool on);
+
+    // Gets
+    virtual bool IsOpen(void) const { return isopen; }
+    virtual R5000Device::PowerState GetPowerState(void) const;
+    virtual QString GetDevice(void) const;
+    virtual R5000Device *GetR5000Device(void) { return device; }
+
+  protected:
+    QString            videodevice;
+    FireWireDBOptions  fw_opts;
+    R5000Device    *device;
+    uint               current_channel;
+    bool               isopen;
+};
+
+#endif // _FIREWIRECHANNEL_H_
Index: libs/libmythtv/r5000device.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000device.h	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,110 @@
+/**
+ *  R5000Device
+ *  Copyright (c) 2005 by Jim Westfall
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _R5000_DEVICE_H_
+#define _R5000_DEVICE_H_
+
+// C++ headers
+#include <vector>
+using namespace std;
+
+// Qt headers
+#include <qstring.h>
+#include <qmutex.h>
+
+// MythTV headers
+#include "streamlisteners.h"
+
+extern "C" {
+#include "r5000/r5000.h"
+}
+
+class TSPacket;
+class R5kPriv;
+class R5000Device
+{
+  public:
+
+    // Public enums
+    typedef enum
+    {
+        kAVCPowerOn,
+        kAVCPowerOff,
+        kAVCPowerUnknown,
+        kAVCPowerQueryFailed,
+    } PowerState;
+
+
+    // AVC param 0
+    typedef enum
+    {
+        kAVCPowerStateOn           = 0x70,
+        kAVCPowerStateOff          = 0x60,
+        kAVCPowerStateQuery        = 0x7f,
+    } IEEE1394UnitPowerParam0;
+
+    R5000Device(int type, QString serial);
+    ~R5000Device();
+
+    bool OpenPort(void);
+    bool ClosePort(void);
+    void RunPortHandler(void);
+
+    // Commands
+    virtual bool ResetBus(void) { return false; }
+
+    virtual void AddListener(TSDataListener*);
+    virtual void RemoveListener(TSDataListener*);
+
+    // Sets
+    virtual bool SetPowerState(bool on);
+    virtual bool SetChannel(const QString &panel_model,
+                            uint alt_method, uint channel);
+
+    // Gets
+    bool IsSTBBufferCleared(void) const { return m_buffer_cleared; }
+
+    // non-const Gets
+    virtual PowerState GetPowerState(void);
+
+    // Statics
+    static bool IsSTBSupported(const QString &model);
+    static QString GetModelName(uint vendorid, uint modelid);
+    static QStringList GetSTBList(void);
+    static int GetDeviceType(const QString &r5ktype);
+    void BroadcastToListeners(
+        const unsigned char *data, uint dataSize);
+
+  protected:
+
+    bool GetSubunitInfo(uint8_t table[32]);
+
+    void SetLastChannel(uint channel);
+    void ProcessPATPacket(const TSPacket&);
+    bool StartStreaming(void);
+    bool StopStreaming(void);
+
+    int                      m_type;
+    QString                  m_serial;
+    uint                     m_subunitid;
+    uint                     m_speed;
+    uint                     m_last_channel;
+    uint                     m_last_crc;
+    bool                     m_buffer_cleared;
+
+    uint                     m_open_port_cnt;
+    vector<TSDataListener*>  m_listeners;
+    mutable QMutex           m_lock;
+
+    /// Vendor ID + Model ID to R5000Device STB model string
+    static QMap<uint64_t,QString> s_id_to_model;
+    static QMutex                 s_static_lock;
+private:
+    r5kdev_t                 *usbdev;
+    R5kPriv                  *m_priv;
+};
+
+#endif // _FIREWIRE_DEVICE_H_
Index: libs/libmythtv/r5000recorder.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000recorder.h	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,72 @@
+/**
+ *  R5000Recorder
+ *  Copyright (c) 2005 by Jim Westfall
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _R5000RECORDER_H_
+#define _R5000RECORDER_H_
+
+// MythTV headers
+#include "dtvrecorder.h"
+#include "tspacket.h"
+#include "streamlisteners.h"
+
+class TVRec;
+class R5000Channel;
+
+/** \class R5000Recorder
+ *  \brief This is a specialization of DTVRecorder used to
+ *         handle DVB and ATSC streams from a firewire input.
+ *
+ *  \sa DTVRecorder
+ */
+class R5000Recorder : public DTVRecorder,
+                         public MPEGSingleProgramStreamListener,
+                         public TSDataListener
+{
+    friend class MPEGStreamData;
+    friend class TSPacketProcessor;
+
+  public:
+    R5000Recorder(TVRec *rec, R5000Channel *chan);
+    virtual ~R5000Recorder();
+
+    // Commands
+    bool Open(void);
+    void Close(void);
+
+    void StartStreaming(void);
+    void StopStreaming(void);
+
+    void StartRecording(void);
+    bool PauseAndWait(int timeout = 100);
+
+    void AddData(const unsigned char *data, uint dataSize);
+    void ProcessTSPacket(const TSPacket &tspacket);
+
+    // Sets
+    void SetOptionsFromProfile(RecordingProfile *profile,
+                               const QString &videodev,
+                               const QString &audiodev,
+                               const QString &vbidev);
+    void SetStreamData(MPEGStreamData*);
+
+    // Gets
+    MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; }
+
+    // MPEG Single Program
+    void HandleSingleProgramPAT(ProgramAssociationTable*);
+    void HandleSingleProgramPMT(ProgramMapTable*);
+
+  protected:
+    R5000Recorder(TVRec *rec);
+
+  private:
+    MPEGStreamData        *_mpeg_stream_data;
+    R5000Channel       *channel;
+    bool                   isopen;
+    vector<unsigned char>  buffer;
+};
+
+#endif //  _R5000RECORDER_H_
Index: libs/libmythtv/r5000signalmonitor.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000signalmonitor.h	2008-03-05 17:17:38.000000000 -0800
@@ -0,0 +1,67 @@
+// -*- Mode: c++ -*-
+
+#ifndef _R5000SIGNALMONITOR_H_
+#define _R5000SIGNALMONITOR_H_
+
+#include <qmap.h>
+#include <qmutex.h>
+#include <qdatetime.h>
+
+#include "dtvsignalmonitor.h"
+#include "firewiredevice.h"
+#include "util.h"
+
+class R5000Channel;
+
+class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener
+{
+    Q_OBJECT
+
+  public:
+    R5000SignalMonitor(int db_cardnum, R5000Channel *_channel,
+                          uint64_t _flags = kFWSigMon_WaitForPower,
+                          const char *_name = "R5000SignalMonitor");
+
+    virtual void HandlePAT(const ProgramAssociationTable*);
+    virtual void HandlePMT(uint, const ProgramMapTable*);
+
+    void Stop(void);
+
+  public slots:
+    void deleteLater(void);
+
+  protected:
+    R5000SignalMonitor(void);
+    R5000SignalMonitor(const R5000SignalMonitor&);
+    virtual ~R5000SignalMonitor();
+
+    virtual void UpdateValues(void);
+    void EmitR5000Signals(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_pat;
+    bool               stb_needs_to_wait_for_power;
+    MythTimer          stb_wait_for_pat_timer;
+    MythTimer          stb_wait_for_power_timer;
+
+    vector<unsigned char> buffer;
+
+    static QMap<void*,uint> pat_keys;
+    static QMutex           pat_keys_lock;
+};
+
+#endif // _R5000SIGNALMONITOR_H_
Index: libs/libmythtv/r5000/libusb_augment.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/libusb_augment.c	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,297 @@
+// 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/
+
+// libusb_augment.c
+// $Revision$
+// $Date$
+
+// Hopefully, the functions in this file will become part of libusb.
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+#include <string.h>
+#include <signal.h>
+#define LIBUSB_AUGMENT
+#include "libusb_augment.h"
+
+// Taken from libusb file usbi.h because usb.h
+// hides the definition of usb_dev_handle.
+extern int usb_debug;
+
+struct usb_dev_handle {
+  int fd;
+
+  struct usb_bus *bus;
+  struct usb_device *device;
+
+  int config;
+  int interface;
+  int altsetting;
+
+  /* Added by RMT so implementations can store other per-open-device data */
+  void *impl_info;
+};
+
+// Taken from libusb file error.h to supply error handling macro definition.
+typedef enum {
+  USB_ERROR_TYPE_NONE = 0,
+  USB_ERROR_TYPE_STRING,
+  USB_ERROR_TYPE_ERRNO,
+} usb_error_type_t;
+
+extern char usb_error_str[1024];
+extern usb_error_type_t usb_error_type;
+
+#define USB_ERROR_STR(format, args...) \
+	do { \
+	  usb_error_type = USB_ERROR_TYPE_STRING; \
+	  snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
+          if (usb_debug >= 2) \
+            fprintf(stderr, "USB error: %s\n", usb_error_str); \
+	} while (0)
+
+static int urb_signr = 0;
+void (*urb_completion_callback)(struct usbdevfs_urb *) = NULL;
+#define USB_ASYNC_COMPLETION_SIGNAL (SIGRTMIN + 5)
+
+void urb_completion_handler(int signum, siginfo_t *info, void *context)
+{
+   struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr;
+   struct usbdevfs_urb *context1;
+   usb_dev_handle *dev = (usb_dev_handle *)urb->usercontext;
+   int ret;
+   if (info->si_code != SI_ASYNCIO ||
+       info->si_signo != USB_ASYNC_COMPLETION_SIGNAL) {
+       return;
+   }
+   if(info->si_errno != 0) {
+     USB_ERROR_STR("Async URB Completion failed: %s", strerror(info->si_errno));
+     return;
+   }
+   ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context1);
+   if(ret  < 0) {
+     USB_ERROR_STR("Failed to read URB: %s", strerror(-ret));
+     return;
+   }
+   if(context1 != urb) {
+     USB_ERROR_STR("Reaped unexpected urb");
+     return;
+   }
+   if(urb_completion_callback)
+     urb_completion_callback(urb);
+}
+
+int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *))
+{
+  urb_completion_callback = cb;
+  urb_signr = USB_ASYNC_COMPLETION_SIGNAL;
+  struct sigaction usb_linux_sa;
+  usb_linux_sa.sa_sigaction = urb_completion_handler;
+  sigfillset(&usb_linux_sa.sa_mask);
+  usb_linux_sa.sa_flags = SA_SIGINFO;
+  usb_linux_sa.sa_flags |= SA_ONSTACK;
+  sigaction(USB_ASYNC_COMPLETION_SIGNAL, &usb_linux_sa, NULL);
+  return 0;
+}
+
+struct usbdevfs_urb *usb_bulk_setup(
+                struct usbdevfs_urb *iso_urb, // URB pointer-pointer.
+		unsigned char ep,  // Device endpoint.
+		char *bytes,       // Data buffer pointer.
+		int size) {        // Size of the buffer.
+  struct usbdevfs_urb *local_urb;
+
+  // No more than 16384 bytes can be transferred at a time.
+  if (size > 16384) {
+    USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL));
+    return NULL;
+  }
+  local_urb = iso_urb;
+  if (!local_urb) {
+    local_urb = (struct usbdevfs_urb *) calloc(1, sizeof(struct usbdevfs_urb));
+    if (!local_urb) {
+      USB_ERROR_STR("error on packet size: %s", strerror(EINVAL));
+      return NULL;
+    }
+  }
+  local_urb->type = USBDEVFS_URB_TYPE_BULK;
+  local_urb->endpoint = ep;
+  local_urb->status = 0;
+  local_urb->flags = 0;
+  local_urb->buffer = bytes;
+  local_urb->buffer_length = size;
+  local_urb->actual_length = 0;
+  local_urb->start_frame = 0;
+  local_urb->number_of_packets = 0;
+  local_urb->error_count = 0;
+  local_urb->signr = urb_signr;
+  local_urb->usercontext = (void *) 0;
+  return local_urb;
+}
+// Reading and writing are the same except for the endpoint
+int usb_isochronous_setup(struct usbdevfs_urb **iso_urb, // URB pointer-pointer.
+			  unsigned char ep,  // Device endpoint.
+			  int pktsize,       // Endpoint packet size.
+			  char *bytes,       // Data buffer pointer.
+			  int size) {        // Size of the buffer.
+  struct usbdevfs_urb *local_urb;
+  // int ret
+  // was unused /lindi
+  int pktcount, fullpkts, partpktsize, packets, urb_size;
+
+  // No more than 32768 bytes can be transferred at a time.
+  if (size > 32768) {
+    USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL));
+    return -EINVAL;
+  }
+
+  // Determine the number of packets that need to be created based upon the
+  // amount of data to be transferred, and the maximum packet size of the
+  // endpoint.
+
+  // Find integral number of full packets.
+  //fprintf(stderr, "buf size: %d\n", size);
+  //fprintf(stderr, "iso size: %d\n", pktsize);
+  fullpkts = size / pktsize;
+  //fprintf(stderr, "Number of full packets: %d\n", fullpkts);
+  // Find length of partial packet.
+  partpktsize = size % pktsize;
+  //fprintf(stderr, "Size of partial packet: %d\n", partpktsize);
+  // Find total number of packets to be transfered.
+  packets = fullpkts + ((partpktsize > 0) ? 1 : 0);
+  //fprintf(stderr, "Total number of packets: %d\n", packets);
+  // Limit the number of packets transfered according to
+  // the Linux usbdevfs maximum read/write buffer size.
+  if ((packets < 1) || (packets > 128)) {
+    USB_ERROR_STR("error on packet size: %s", strerror(EINVAL));
+    return -EINVAL;
+  }
+
+  // If necessary, allocate the urb and packet
+  // descriptor structures from the heap.
+  local_urb = *iso_urb;
+  if (!local_urb) {
+    urb_size = sizeof(struct usbdevfs_urb) +
+      packets * sizeof(struct usb_iso_packet_desc);
+    local_urb = (struct usbdevfs_urb *) calloc(1, urb_size);
+    if (!local_urb) {
+      USB_ERROR_STR("error on packet size: %s", strerror(EINVAL));
+      return -ENOMEM;
+    }
+  }
+
+  // Set up each packet for the data to be transferred.
+  for (pktcount = 0; pktcount < fullpkts; pktcount++) {
+    local_urb->iso_frame_desc[pktcount].length = pktsize;
+    local_urb->iso_frame_desc[pktcount].actual_length = 0;
+    local_urb->iso_frame_desc[pktcount].status = 0;
+  }
+
+  // Set up the last packet for the partial data to be transferred.
+  if (partpktsize > 0) {
+    local_urb->iso_frame_desc[pktcount].length = partpktsize;
+    local_urb->iso_frame_desc[pktcount].actual_length = 0;
+    local_urb->iso_frame_desc[pktcount++].status = 0;
+  }
+
+  // Set up the URB structure.
+  local_urb->type = USBDEVFS_URB_TYPE_ISO;
+  //fprintf(stderr, "type: %d\n", local_urb->type);
+  local_urb->endpoint = ep;
+  //fprintf(stderr, "endpoint: 0x%x\n", local_urb->endpoint);
+  local_urb->status = 0;
+  local_urb->flags = USBDEVFS_URB_ISO_ASAP; // Additional flags here?
+  //fprintf(stderr, "flags: %d\n", local_urb->flags);
+  local_urb->buffer = bytes;
+  //fprintf(stderr, "buffer: 0x%x\n", local_urb->buffer);
+  local_urb->buffer_length = size;
+  //fprintf(stderr, "buffer_length: %d\n", local_urb->buffer_length);
+  local_urb->actual_length = 0;
+  local_urb->start_frame = 0;
+  //fprintf(stderr, "start_frame: %d\n", local_urb->start_frame);
+  local_urb->number_of_packets = pktcount;
+  //fprintf(stderr, "number_of_packets: %d\n", local_urb->number_of_packets);
+  local_urb->error_count = 0;
+  local_urb->signr = 0;
+  //fprintf(stderr, "signr: %d\n", local_urb->signr);
+  local_urb->usercontext = (void *) 0;
+  *iso_urb = local_urb;
+  return 0;
+}
+
+
+int usb_urb_submit(usb_dev_handle *dev,     // Open usb device handle.
+		   struct usbdevfs_urb *iso_urb,        // Pointer to URB.
+		   struct timeval *tv_submit) { // Time structure pointer.
+  int ret;
+
+  iso_urb->usercontext = dev;
+  // Get actual time, of the URB submission.
+  if(tv_submit)
+    gettimeofday(tv_submit, NULL);
+  // Submit the URB through an IOCTL call.
+  ret = ioctl(dev->fd, USBDEVFS_SUBMITURB, iso_urb);
+  //fprintf(stderr, "start_frame now: %d\n", iso_urb->start_frame);
+  //fprintf(stderr, "submit ioctl return value: %d\n", ret);
+  if (ret < 0) {
+    //fprintf(stderr, "error submitting URB: %s\n", strerror(errno));
+    USB_ERROR_STR("error submitting URB: %s", strerror(errno));
+    return -errno;
+  }
+  return ret;
+}
+
+
+int usb_urb_reap(usb_dev_handle *dev,     // Open usb device handle.
+		 struct usbdevfs_urb *iso_urb,        // Pointer to URB.
+		 int timeout) {           // Attempt timeout (usec).
+  struct timeval tv_ref, tv_msec, tv;
+  void *context;
+  int waiting, ret;
+  struct pollfd ufd[1];
+
+  // Get actual time, and add the timeout value. The result is the absolute
+  // time where we have to quit waiting for an isochronous message.
+  ufd[0].fd = dev->fd;
+  ufd[0].events = POLLIN | POLLOUT;
+  ufd[0].revents = 0;
+  ret = poll(ufd, 1, timeout);
+  if(ret <= 0)
+    return -ETIMEDOUT;
+
+  //fprintf(stderr, "preparing to reap\n");
+  ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context);
+
+  /*
+   * If there was an error, that wasn"t EAGAIN (no completion), then
+   * something happened during the reaping and we should return that
+   * error now
+   */
+  //fprintf(stderr, "reap ioctl return value: %d\n", ret);
+  if (ret < 0) {
+    USB_ERROR_STR("error reaping interrupt URB: %s",
+		  strerror(errno));
+    return -errno;
+  }
+
+  //fprintf(stderr, "actual_length: %d\n", iso_urb->actual_length);
+  //fprintf(stderr, "URB status: %d\n", iso_urb->status);
+  //fprintf(stderr, "error count: %d\n", iso_urb->error_count);
+
+  //fprintf(stderr, "waiting done\n");
+  if(iso_urb != context) {
+    fprintf(stderr, "Expected urb: %p but got %p\n", iso_urb, context);
+    return -1;
+  }
+  //fprintf(stderr, "Total bytes: %d\n", bytesdone);
+  return iso_urb->actual_length;
+}
+
+int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb)
+{
+  return ioctl(dev->fd, USBDEVFS_DISCARDURB, iso_urb);
+}
Index: libs/libmythtv/r5000/libusb_augment.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/libusb_augment.h	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,23 @@
+// libusb_augment.h
+// $Revision$
+// $Date$
+
+#ifdef LIBUSB_AUGMENT
+// Taken from libusb file linux.h to provide the URB structure definitions.
+struct usb_iso_packet_desc {
+  unsigned int length;
+  unsigned int actual_length;
+  unsigned int status;
+};
+#endif
+
+int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *));
+struct usbdevfs_urb *usb_bulk_setup(struct usbdevfs_urb *iso_urb, unsigned char ep,
+		   char *bytes, int size);
+int usb_isochronous_setup(struct usbdevfs_urb **iso_urb, unsigned char ep,
+			  int pktsize, char *bytes, int size);
+int usb_urb_submit(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb,
+		   struct timeval *tv_rsubmit);
+int usb_urb_reap(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb,
+		 int timeout_usec);
+int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb);
Index: libs/libmythtv/r5000/r5000.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5000.c	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,416 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef R5K_DEBUG
+char strmfile[256] = "/tmp/strm";
+int fd = -1;
+#endif
+
+#ifdef R5K_RAWUSB
+int usbfd = -1;
+#endif
+#include "r5000_internal.h"
+#include "libusb_augment.h"
+#include "r5000init.h"
+
+#define R5K_WARM_VID 0x0547
+#define R5K_WARM_PID 0x1002
+
+#define MAX_URBS_IN_FLIGHT 128
+#define R5K_URB_BUFFER_SIZE (1 << 14)
+
+static int r5000_usb_init = 0;
+enum {
+  R5K_PMT_START = 0x01,
+  R5K_PMT_READY = 0x02
+};
+
+int r5000_create_urbs(r5kdev_t *r5kdev)
+{
+  int i;
+  r5kdev->urbs = (struct usbdevfs_urb *)malloc(sizeof(struct usbdevfs_urb) * MAX_URBS_IN_FLIGHT);
+  r5kdev->buffer = malloc(R5K_URB_BUFFER_SIZE * MAX_URBS_IN_FLIGHT);
+  for(i = 0; i < MAX_URBS_IN_FLIGHT; i++) {
+    usb_bulk_setup(&r5kdev->urbs[i], 0x82, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE);
+  }
+  r5kdev->nexturb = 0;
+  return 1;
+}
+
+int r5000_free_urbs(r5kdev_t *r5kdev)
+{
+  free(r5kdev->urbs);
+  free(r5kdev->buffer);
+  return 0;
+}
+
+usb_dev_handle *r5000_locate_device(
+    unsigned short vendor_id, unsigned short product_id, int skip)
+{
+  struct usb_bus *bus;
+  struct usb_device *dev;
+  usb_dev_handle *device_handle = 0;
+  usb_find_busses();
+  usb_find_devices();
+
+  for (bus = usb_get_busses(); bus && !device_handle; bus = bus->next)
+  {
+    for (dev = bus->devices; dev && !device_handle; dev = dev->next)
+    {
+      if (dev->descriptor.idVendor == vendor_id &&
+          dev->descriptor.idProduct == product_id)
+      {
+        device_handle = usb_open(dev);
+        if(device_handle && skip) {
+          usb_close(device_handle);
+          device_handle = NULL;
+          skip--;
+        }
+      }
+    }
+  }
+
+  if (device_handle) {
+    int open_status = usb_set_configuration(device_handle,1);
+
+    open_status = usb_claim_interface(device_handle,0);
+
+    open_status = usb_set_altinterface(device_handle,0);
+  }
+  return (device_handle);
+}
+
+int r5000_init(r5kdev_t *r5kdev) {
+  int i, bytes;
+  unsigned char *ptr, *serial = r5kdev->serial;
+  unsigned char datain[0x80];
+  bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000);
+  for(i = 0; i < R5K_INIT_SERIAL; i++) {
+    PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen);
+    if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep);
+    usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000);
+    if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep);
+    bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000);
+    PRINTHEX("Read:\n", datain, bytes);
+    if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) {
+      fprintf(stderr, "R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes);
+      return 0;
+    }
+  }
+
+  //last read is serial #
+  if (datain[0] != 0x08) {
+    fprintf(stderr, "R5000 initialization failed reading serial #\n");
+    return 0;
+  }
+  for(ptr = datain + 6; ptr < datain + 13; ptr++) {
+    *serial++ = ( *ptr >= '0' && *ptr <= 'z' ) ? *ptr : '*';
+  }
+  *serial = 0;
+
+  //complete initialization now
+  for(; i < R5K_INIT_MAX; i++) {
+    PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen);
+    if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep);
+    usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000);
+    if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep);
+    bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000);
+    PRINTHEX("Read:\n", datain, bytes);
+    if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) {
+      fprintf(stderr, "R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes);
+      return 0;
+    }
+  }
+  return 1;
+}
+
+int r5000_start_stream(r5kdev_t *r5kdev)
+{
+  unsigned char data[0x80];
+  int bytes;
+  int i;
+  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle;
+
+  if(! r5kdev->urbs)
+    r5000_create_urbs(r5kdev);
+
+  data[0] = 0x30;
+  usb_bulk_write(handle, 1, data, 1, 5000);
+  bytes = usb_bulk_read(handle, 129, data, 2, 5000);
+
+  //0x50 sets byte mode.  Use '0x60' to set word mode
+  data[0] = r5kdev->read_words ? 0x60: 0x50;
+  usb_bulk_write(handle, 1, data, 1, 5000);
+
+  for(i=0; i < MAX_URBS_IN_FLIGHT; i++) {
+    usb_urb_submit(handle, &r5kdev->urbs[i], NULL);
+  }
+  r5kdev->nexturb = 0;
+  r5kdev->streaming = 1;
+  if(r5kdev->start_stream)
+    r5kdev->start_stream(r5kdev);
+  return 1;
+}
+
+int r5000_stop_stream(r5kdev_t *r5kdev)
+{
+  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle;
+  struct usbdevfs_urb *urbs = (struct usbdevfs_urb *)r5kdev->urbs;
+  int i;
+
+  if(r5kdev->streaming) {
+    for(i=0; i < MAX_URBS_IN_FLIGHT; i++)
+      usb_urb_cancel(handle, &urbs[i]);
+    r5kdev->streaming = 0;
+  }
+  return 1;
+}
+
+r5kdev_t *r5000_open(r5ktype_t type,
+                     unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data),
+                     void *cb_data,
+                     const char *serial)
+{
+  r5kdev_t *r5kdev, r5kd;
+  struct usb_dev_handle *handle;
+  int count = 0;
+  memset(&r5kd, 0, sizeof(r5kdev_t));
+
+  if(! r5000_usb_init) {
+    int bus_count, dev_count;
+    usb_init();
+    bus_count = usb_find_busses();
+    dev_count = usb_find_devices();
+    if(bus_count == 0 || dev_count ==0) {
+      fprintf(stderr, "R5000 failed to locate any R5000 devices.  Are you sure you have permissions set properly?\n");
+      return NULL;
+    }
+    r5000_usb_init = 1;
+  }
+#ifdef R5K_DEBUG
+  fd = open(strmfile, O_RDONLY);
+#endif
+#ifdef R5K_RAWUSB
+  usbfd = open("raw.av", O_WRONLY | O_CREAT | O_TRUNC);
+#endif
+  while(count < R5K_MAX_DEVS) {
+    r5kd.handle = r5000_locate_device(R5K_WARM_VID, R5K_WARM_PID, count);
+    if(! r5kd.handle)
+      return NULL;
+    if (! r5000_init(&r5kd)) {
+      usb_close(r5kd.handle);
+      return NULL;
+    }
+    if(! serial || memcmp(serial, r5kd.serial, 8) == 0)
+      break;
+    count++;
+    usb_close(r5kd.handle);
+  }
+  r5kdev = (r5kdev_t *)malloc(sizeof(r5kdev_t));
+  *r5kdev = r5kd;
+  r5kdev->urbs = NULL;
+  r5kdev->cb = cb;
+  r5kdev->cb_data = cb_data;
+  switch(type) {
+    case R5K_STB_VIP:
+      vip_init(r5kdev);
+      r5kdev->stb_type = R5K_STB_VIP;
+      break;
+    case R5K_STB_DIRECTV:
+      directv_init(r5kdev);
+      r5kdev->stb_type = R5K_STB_DIRECTV;
+      break;
+    case R5K_STB_DSR:
+    case R5K_STB_HDD:
+      sat_init(r5kdev, type);
+      r5kdev->stb_type = type;
+      break;
+    default:
+      fprintf(stderr, "Unknown STB type %d specified.\n", type);
+      vip_init(r5kdev);
+      r5kdev->stb_type = R5K_STB_VIP;
+      break;
+  }
+  return r5kdev;
+}
+
+int r5000_close(r5kdev_t *r5kdev)
+{
+  if(! r5kdev)
+    return 1;
+  if(r5kdev->urbs) {
+    if(r5kdev->streaming)
+      r5000_stop_stream(r5kdev);
+    r5000_free_urbs(r5kdev);
+  }
+  usb_close(r5kdev->handle);
+#ifdef R5K_RAWUSB
+  if(usbfd >= 0) close(usbfd);
+#endif
+  switch(r5kdev->stb_type) {
+    case R5K_STB_VIP:
+      vip_free(r5kdev);
+      break;
+    case R5K_STB_DIRECTV:
+      directv_free(r5kdev);
+      break;
+    case R5K_STB_DSR:
+    case R5K_STB_HDD:
+      sat_free(r5kdev);
+      break;
+  }
+  free(r5kdev);
+  return 1;
+}
+
+int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec)
+{
+  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle;
+  struct usbdevfs_urb *urbs = (struct usbdevfs_urb *)r5kdev->urbs;
+  int len;
+  unsigned char *buf;
+  if(! r5kdev->streaming)
+    return -1;
+  len = usb_urb_reap(handle, &urbs[r5kdev->nexturb], timeout_usec);
+  if(len <= 0) {
+    if(len != -ETIMEDOUT)
+      fprintf(stderr, "(%d) Reap failed at %08x: %s\n", r5kdev->nexturb, r5kdev->bytes_read, strerror(errno));
+    return len;
+  }
+  buf = r5kdev->buffer + (R5K_URB_BUFFER_SIZE*r5kdev->nexturb);
+#ifdef R5K_RAWUSB
+  if(usbfd >= 0) write(usbfd, buf, len);
+#endif
+#ifdef R5K_DEBUG
+  if(fd >= 0)
+    len = read(fd, buf, len);
+#endif
+  r5kdev->process_block(r5kdev, buf, len);
+  r5kdev->bytes_read += len;
+  usb_urb_submit(handle, &urbs[r5kdev->nexturb], NULL);
+  r5kdev->nexturb = (r5kdev->nexturb + 1) % MAX_URBS_IN_FLIGHT;
+  return 0;
+}
+
+//use this to read a status frame.  It doesn't do anything special
+//but makes it obvious what data is expected
+int r5000_read_status(r5kdev_t *r5kdev, unsigned char *buf)
+{
+  return usb_bulk_read(r5kdev->handle, 129, buf, 128, 5000);
+}
+
+int r5000_get_power_state(r5kdev_t *r5kdev)
+{
+  unsigned char data1[1]  = { 0x30 };
+  unsigned char data2[0x80];
+  int count = 10;
+  while(count--) {
+    r5000_read_status(r5kdev, data2);
+    usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000);
+    usleep(100000);
+    if(usb_bulk_read(r5kdev->handle, 1, data2, 2, 5000) == 2 &&
+       data2[0] == 0x0a && (data2[1] & 0x4e) == 0x4c)
+      return (!!(data2[1] == 0x4d));
+    usleep(100000);
+  }
+  fprintf(stderr, "R5000 failed to read power state.  Assuming ON state\n");
+  return 1;
+}
+
+int r5000_toggle_on_off(r5kdev_t *r5kdev)
+{
+  unsigned char data1[1]  = { 0x30 };
+  unsigned char data3[0x80], on_off, new_state;
+  int len;
+  int count = 20;
+  on_off = r5000_get_power_state(r5kdev);
+  if(! r5kdev->button) {
+    fprintf(stderr, "No button IR commands defined for this device!\n");
+    return on_off;
+  }
+  //fprintf(stderr, "Start state: %s\n", on_off ? "On" : "Off");
+  usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000);
+  usleep(100000);
+  usb_bulk_write(r5kdev->handle, 1, r5kdev->button->power, r5kdev->button->len, 5000);
+  usleep(100000);
+  len = usb_bulk_read(r5kdev->handle, 1, data3, 2, 5000);
+  usleep(100000);
+  while(count-- && (new_state = r5000_get_power_state(r5kdev)) == on_off)
+    usleep(100000);
+  //fprintf(stderr, "End state: %s\n", !on_off ? "On" : "Off");
+  return new_state;
+}
+
+int r5000_change_channel(r5kdev_t *r5kdev, int chan)
+{
+  int pos = 1000000, digit;
+  unsigned char data2[0x80];
+  unsigned char *ptr;
+  if(! r5kdev->button) {
+    fprintf(stderr, "No button IR commands defined for this device!\n");
+    return;
+  }
+  r5000_read_status(r5kdev, data2);
+  usb_bulk_write(r5kdev->handle, 1, r5kdev->button->clear, r5kdev->button->len, 5000);
+  usleep(r5kdev->button->delay);
+  while(pos != 0 && (chan/pos) == 0)
+    pos /= 10;
+  if(pos == 0)
+    pos = 1;
+  while(pos != 0) {
+    digit = chan / pos;
+    switch(digit) {
+      case 0 : ptr = r5kdev->button->b0; break;
+      case 1 : ptr = r5kdev->button->b1; break;
+      case 2 : ptr = r5kdev->button->b2; break;
+      case 3 : ptr = r5kdev->button->b3; break;
+      case 4 : ptr = r5kdev->button->b4; break;
+      case 5 : ptr = r5kdev->button->b5; break;
+      case 6 : ptr = r5kdev->button->b6; break;
+      case 7 : ptr = r5kdev->button->b7; break;
+      case 8 : ptr = r5kdev->button->b8; break;
+      case 9 : ptr = r5kdev->button->b9; break;
+    }
+    usb_bulk_write(r5kdev->handle, 1, ptr, r5kdev->button->len, 5000);
+    chan -= digit*pos;
+    pos/= 10;
+    usleep(r5kdev->button->delay);
+  }
+  usb_bulk_write(r5kdev->handle, 1, r5kdev->button->enter, r5kdev->button->len, 5000);
+  r5kdev->channel = chan;
+  return 1;
+}
+
+int r5000_find_stbs(r5kenum_t *devs)
+{
+  r5kdev_t r5kdev;
+  devs->count = 0;
+  if(! r5000_usb_init) {
+    int bus_count, dev_count;
+    usb_init();
+    bus_count = usb_find_busses();
+    dev_count = usb_find_devices();
+    if(bus_count == 0 || dev_count ==0) {
+      fprintf(stderr, "R5000 failed to locate any R5000 devices.  Are you sure you have permissions set properly?\n");
+      return 0;
+    }
+    r5000_usb_init = 1;
+  }
+  while(devs->count < R5K_MAX_DEVS) {
+    r5kdev.handle = r5000_locate_device(R5K_WARM_VID, R5K_WARM_PID, devs->count);
+    if(! r5kdev.handle)
+      break;
+    if(! r5000_init(&r5kdev)) {
+      usb_close(r5kdev.handle);
+      return 0;
+    }
+    memcpy(devs->serial[devs->count], r5kdev.serial, 8);
+    devs->count++;
+    usb_close(r5kdev.handle);
+  }
+  return 1;
+}
Index: libs/libmythtv/r5000/r5000.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5000.h	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,31 @@
+#ifndef R5000_H
+#define R5000_H
+
+#ifndef r5kdev_t
+#define r5kdev_t void
+#endif
+
+#define R5K_MAX_DEVS 10
+typedef struct {
+  unsigned char serial[R5K_MAX_DEVS][8];
+  int count;
+} r5kenum_t;
+
+typedef enum {
+  R5K_STB_VIP = 0,
+  R5K_STB_DIRECTV,
+  R5K_STB_HDD,
+  R5K_STB_DSR,
+  R5K_STB_MAX,
+} r5ktype_t;
+
+extern r5kdev_t *r5000_open(r5ktype_t type, unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), void *cb_data, const char *serial);
+extern int r5000_close(r5kdev_t *r5kdev);
+extern int r5000_start_stream(r5kdev_t *r5kdev);
+extern int r5000_stop_stream(r5kdev_t *r5kdev);
+extern int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec);
+extern int r5000_get_power_state(r5kdev_t *r5kdev);
+extern int r5000_toggle_on_off(r5kdev_t *r5kdev);
+extern int r5000_change_channel(r5kdev_t *r5kdev, int chan);
+extern int r5000_find_stbs(r5kenum_t *devs);
+#endif //R5000_H
Index: libs/libmythtv/r5000/r5000_internal.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5000_internal.h	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,93 @@
+#ifndef R5000_INT_H
+#define R5000_INT_H
+
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+
+#define PRINTHEX(str, data, len) if(0) do { \
+  int _i; \
+  fprintf(stderr, str); \
+  for(_i = 0; _i < (len); _i++) { \
+    fprintf(stderr, "%02x ", (data)[_i]); \
+    if((_i % 16) == 15) fprintf(stderr, "\n"); \
+  } \
+  if(_i % 16) fprintf(stderr, "\n"); \
+} while(0)
+
+#define R5K_MAX_BUTTON_SIZE 0x80
+#define R5K_MAX_PIDS 10
+#define IS_VIDEO(x) ((x) == 0x02 || (x) == 0x1b)
+
+struct r5k_descriptor {
+  unsigned char d[10];
+};
+
+struct r5k_epid {
+  int pid;
+  unsigned char id;
+  struct r5k_descriptor desc;
+};
+
+struct r5000_buttons {
+  int len;
+  int delay;
+  unsigned char b0[R5K_MAX_BUTTON_SIZE];
+  unsigned char b1[R5K_MAX_BUTTON_SIZE];
+  unsigned char b2[R5K_MAX_BUTTON_SIZE];
+  unsigned char b3[R5K_MAX_BUTTON_SIZE];
+  unsigned char b4[R5K_MAX_BUTTON_SIZE];
+  unsigned char b5[R5K_MAX_BUTTON_SIZE];
+  unsigned char b6[R5K_MAX_BUTTON_SIZE];
+  unsigned char b7[R5K_MAX_BUTTON_SIZE];
+  unsigned char b8[R5K_MAX_BUTTON_SIZE];
+  unsigned char b9[R5K_MAX_BUTTON_SIZE];
+  unsigned char clear[R5K_MAX_BUTTON_SIZE];
+  unsigned char enter[R5K_MAX_BUTTON_SIZE];
+  unsigned char power[R5K_MAX_BUTTON_SIZE];
+};
+
+struct r5kdev {
+  usb_dev_handle *handle;
+  unsigned char serial[8];
+  struct usbdevfs_urb *urbs;
+  unsigned char *buffer;
+  int stb_type;
+  int read_words;
+  void (*process_block)(struct r5kdev *r5kdev, unsigned char *buf, int len);
+  void (*start_stream)(struct r5kdev *r5kdev);
+  void *stbdata;
+  unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data);
+  void *cb_data;
+  int nexturb;
+  int streaming;
+  int bytes_read;
+  struct r5000_buttons *button;
+  int channel;
+  unsigned char pmt_pkt[188];
+  unsigned char num_pmt_entries;
+  unsigned char pmt_state;
+  unsigned char pmt_next_cc;
+  struct r5k_epid pmt[R5K_MAX_PIDS];
+} r5kdev_t;
+#define r5kdev_t struct r5kdev
+
+#include "r5000.h"
+
+extern unsigned char r5000_pat_pkt[188];
+extern struct r5k_descriptor r5000_pmt_audio_desc;
+extern struct r5k_descriptor r5000_pmt_video_desc;
+extern void r5000_send_pmt(r5kdev_t *r5kdev);
+
+//Support for all DirecTV boxes
+extern void directv_init(r5kdev_t *r5kdev);
+extern void directv_free(r5kdev_t *r5kdev);
+
+//Support for ViP series Dish Network boxes
+extern void vip_init(r5kdev_t *r5kdev);
+extern void vip_free(r5kdev_t *r5kdev);
+
+//Support for HDD and DSR series satellite/cable boxes
+extern void sat_init(r5kdev_t *r5kdev, r5ktype_t type);
+extern void sat_free(r5kdev_t *r5kdev);
+
+#endif
Index: libs/libmythtv/r5000/r5k_vip.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5k_vip.c	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,266 @@
+//Support for Dish Network ViP211/ViP422 boxes
+#include <stdio.h>
+#include <string.h>
+#include "r5000_internal.h"
+
+struct r5000_vip {
+  unsigned char leftover[188];
+  int offset;
+};
+
+struct r5000_buttons vip_button_cmd =
+{
+0x40, //len
+400000, //delay
+//button 0:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 1:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 2:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 3:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 4:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 5:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 6:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 7:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 8:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//button 9:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e,
+ 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//Clear:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//Enter:
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+},
+//Power
+{
+ 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a,
+ 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e,
+}
+};
+
+void vip_add_pmt(r5kdev_t *r5kdev, int pid, int table_id)
+{
+  int i;
+  int is_video = IS_VIDEO(table_id);
+
+  for(i = 0; i < r5kdev->num_pmt_entries; i++) {
+    if(r5kdev->pmt[i].pid == pid) {
+      if(r5kdev->pmt[i].id == table_id)
+        return;
+      //different table_id for existing pid.  Reset
+      r5kdev->num_pmt_entries = 0;
+      r5kdev->pmt_state = 0;
+      r5kdev->pmt_pkt[0] = 0;
+      break;
+    }
+    if(is_video) {
+      if(IS_VIDEO(r5kdev->pmt[i].id)) {
+        //a video entry already exists.  Reset
+        r5kdev->num_pmt_entries = 0;
+        r5kdev->pmt_state = 0;
+        r5kdev->pmt_pkt[0] = 0;
+        break;
+      }
+    }
+  }
+  //Didn't find this PID, add it
+  if(i == R5K_MAX_PIDS)
+    return;
+  printf("Adding %04x: %02x @ %08x\n", pid, table_id, r5kdev->bytes_read);
+  r5kdev->pmt[r5kdev->num_pmt_entries].pid = pid;
+  r5kdev->pmt[r5kdev->num_pmt_entries].id  = table_id;
+  r5kdev->pmt[r5kdev->num_pmt_entries].desc = is_video ? r5000_pmt_video_desc : r5000_pmt_audio_desc;
+  r5kdev->num_pmt_entries++;
+  r5kdev->pmt_state |= is_video ? 0x01 : 0x02;
+}
+
+void vip_force_pmt(r5kdev_t *r5kdev, unsigned char *buf)
+{
+  int stream_id, pid, afc, af_size = 0;
+  pid = ((buf[1] << 8) | buf[2]) & 0x1fff;
+  if(pid == 0x1fff)
+    return;
+  if(pid == 0) {
+    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data);
+    if(r5kdev->pmt_state == 0x03)
+      r5000_send_pmt(r5kdev);
+  } else {
+    if(pid != 0x21)
+      r5kdev->cb(buf, 188, r5kdev->cb_data);
+    //Only interested in PES packets starting in this TS packet
+    if (!buf[1] & 0x40)
+      return;
+    afc = (buf[3]>>4) & 0x03;
+    if(afc == 0x2)
+      return;
+    if(afc == 0x3)
+      af_size = buf[4]+1;
+    if(buf[4+af_size] != 0x00 || buf[5+af_size] != 0x00 || buf[6+af_size] != 0x01)
+      return;
+    //We have a PES packet
+    stream_id = buf[7+af_size];
+    if((stream_id & 0xf0) == 0xe0) {
+      //Video stream (we need the adaptation field)
+      if(afc != 0x03)
+        return;
+      if(0) {
+        int i;
+        for(i = 0; i < af_size+8; i++) {
+          printf("%02x ", buf[i]);
+          if((i %16) == 15)
+            printf("\n");
+        }
+        printf("\n");
+      }
+      if(buf[5] & 0x02) {
+        // Has private data, this is MPEG4
+        vip_add_pmt(r5kdev, pid, 0x1b);
+      } else if(buf[5] & 0x10) {
+        // Has PCR and no private data, this is MPEG2
+        vip_add_pmt(r5kdev, pid, 0x02);
+      }
+    } else if((stream_id & 0xf0) == 0xc0) {
+      //Audio stream
+      vip_add_pmt(r5kdev, pid, 0x04);
+    } else if(stream_id  == 0xbd) {
+      //Audio stream
+      vip_add_pmt(r5kdev, pid, 0x81);
+    }
+  }
+}
+
+static void vip_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len)
+{
+  struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata;
+
+  int pos;
+  int sync = 1;
+  if(! r5kdev->streaming)
+    return;
+  if(len <= 0)
+    return;
+
+  pos = vip->offset;
+  while(pos < len) {
+      if(buf[pos] != 0x47 || (pos <len-1 && buf[pos+1] == 0xff))
+        goto nosync;
+      // If we get here, buf[pos] == 0x47
+      if(vip->offset) {
+        //previous data exists and is part of a good packet
+        memcpy(vip->leftover+188-vip->offset, buf, vip->offset);
+        vip_force_pmt(r5kdev, vip->leftover);
+        vip->offset = 0;
+      }
+      if(pos+188 < len) {
+        //at least one full packet is available
+        if(buf[pos+188] != 0x47)
+          goto nosync;
+      } else {
+        //Out of data, but the partial packet may be ok.
+        memcpy(vip->leftover, buf+pos, len-pos);
+        vip->offset = 188-(len-pos);
+        break;
+      }
+      //If we get here, we have a good packet
+      vip_force_pmt(r5kdev, buf+pos);
+      if(! sync)
+        printf("(%d) Found sync at %08x\n", r5kdev->nexturb, r5kdev->bytes_read+pos);
+      sync = 1;
+      pos+=188;
+      continue;
+  nosync:
+      vip->offset=0;
+      if(sync)
+        printf("(%d)Lost sync at %08x\n", r5kdev->nexturb, r5kdev->bytes_read+pos);
+      sync = 0;
+      pos++;
+  }
+}
+
+static void vip_start_stream(r5kdev_t *r5kdev)
+{
+  struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata;
+  vip->offset = 0;
+}
+
+void vip_init(r5kdev_t *r5kdev)
+{
+  struct r5000_vip *vip = (struct r5000_vip *)malloc(sizeof(struct r5000_vip));
+  r5kdev->stbdata = vip;
+  r5kdev->process_block = vip_process_block;
+  r5kdev->start_stream  = vip_start_stream;
+  r5kdev->button = &vip_button_cmd;
+}
+
+void vip_free(r5kdev_t *r5kdev)
+{
+  free(r5kdev->stbdata);
+}
+
Index: libs/libmythtv/r5000/r5k_directv.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5k_directv.c	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,393 @@
+//Support for DirecTV boxes
+#include <netinet/in.h>
+#include <string.h>
+
+#include "r5000_internal.h"
+
+#define DTV_VPID 0x1322
+#define DTV_APID 0x1333
+#define DTV_PAT_PMT_COUNT 5000
+
+struct r5000_dtv {
+  unsigned char vbuf[188*2+4];
+  unsigned char abuf[188*2+6];
+  unsigned char *video;
+  unsigned char *audio;
+  unsigned int vpos;
+  unsigned int apos;
+  unsigned int vstart;
+  unsigned int astart;
+  unsigned int video_cc;
+  unsigned int audio_cc;
+  unsigned int vstate;
+  unsigned int pic_pos;
+  int alen;
+  unsigned int pat_pmt_count;
+};
+
+struct r5000_buttons directv_button_cmd =
+{
+0x49, //len
+400000, //delay
+//button 0:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 1:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 2:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 3:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 4:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 5:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 6:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 7:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 8:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//button 9:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//Clear:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//Enter:
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+},
+//Power
+{
+    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05,
+    0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f,
+    0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05,
+}
+};
+
+static int directv_make_empty_pes(unsigned char *ptr, unsigned char type)
+{
+  ptr[0] = 0x00;
+  ptr[1] = 0x00;
+  ptr[2] = 0x01;
+  ptr[3] = type;
+  ptr[4] = 0x00;
+  ptr[5] = 0x00;
+  ptr[6] = 0x80;
+  ptr[7] = 0x00; //2 MSB represent PTS/DTS flag
+  ptr[8] = 0x0a;
+  ptr[9]  = 0xff;
+  ptr[10] = 0xff;
+  ptr[11] = 0xff;
+  ptr[12] = 0xff;
+  ptr[13] = 0xff;
+  ptr[14] = 0xff;
+  ptr[15] = 0xff;
+  ptr[16] = 0xff;
+  ptr[17] = 0xff;
+  ptr[18] = 0xff;
+  return 19;
+}
+
+static void directv_make_pespts(unsigned char *outptr, unsigned int pts)
+{
+        pts = htonl(pts);
+        unsigned char *inpts = (unsigned char *)&pts;
+        outptr[0] = 0x01 |
+                    ((inpts[0] & 0xC0) >>5);
+        outptr[1] = ((inpts[0] & 0x3F) << 2) |
+                    ((inpts[1] & 0xC0) >> 6);
+        outptr[2] = 0x01 | ((inpts[1] & 0x3F) << 2) |
+                    ((inpts[2] & 0x80) >> 6);
+        outptr[3] = ((inpts[2] & 0x7F) << 1) |
+                    ((inpts[3] & 0x80) >> 7);
+        outptr[4] = 0x01 | ((inpts[3] & 0x7F) << 1);
+}
+
+static void directv_update_video_pes(unsigned char *ptr, int pos)
+{
+  //pos points at the 1st char after a pic start code
+  int picture_coding_type;
+  int hdr_len;
+  unsigned int pts1, dts1;
+  unsigned char *buf = ptr + pos;
+  picture_coding_type = (buf[1] >> 3) & 0x07;
+  hdr_len = (picture_coding_type > 1) ? 5 : 4;
+  if(buf[hdr_len + 3] == 0xb5)
+    hdr_len += 9;
+  if(buf[hdr_len + 3] == 0xb2) {
+    pts1 = ((buf[hdr_len+6] & 0x03)   << 30) +
+           ((buf[hdr_len+7] & 0x7f) << 23) +
+           ((buf[hdr_len+8])          << 15) +
+           ((buf[hdr_len+9] & 0x7f) << 8) +
+           buf[hdr_len+10];
+    dts1 = ((buf[hdr_len+13] & 0x03)   << 30) +
+           ((buf[hdr_len+14] & 0x7f) << 23) +
+           ((buf[hdr_len+15])          << 15) +
+           ((buf[hdr_len+16] & 0x7f) << 8) +
+           buf[hdr_len+17];
+    //NOTE:  This is wrong.  DSS timestamps only have a resolution of 2^32/300
+    //printf("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0);
+    ptr[7] |= 0xc0;
+    directv_make_pespts(ptr+9, pts1/300);
+    ptr[9] |= 0x30;
+    directv_make_pespts(ptr+14, dts1/300);
+    ptr[14] |= 0x10;
+  }
+}
+
+static void directv_fix_audio_pts(unsigned char *ptr)
+{
+  unsigned int pts = ((ptr[0] & 0x06) << 29) +
+                     (ptr[1] << 22) +
+                     ((ptr[2] & 0xfe) << 14) +
+                     (ptr[3] << 7) +
+                     (ptr[4] >> 1);
+  directv_make_pespts(ptr, pts/300);
+  ptr[0] |= 0x20;
+}
+
+
+static void directv_write_ts(r5kdev_t *r5kdev, unsigned char *ptr, int len, int pid, int start, int *cc)
+{
+  int stuff = 184 - len;
+  //Note:  we know that there are 188 bytes allocated before 'ptr'
+  //       that we can use for the header
+  if(stuff > 0) {
+    int stuff1 = stuff;
+    while(stuff1 > 2) {
+      *--ptr = 0xff;
+      stuff1--;
+    }
+    if(stuff1 == 2) {
+      *--ptr = 0x00;
+    }
+    *--ptr = stuff - 1;
+    *--ptr = 0x30 | *cc;
+  } else {
+    *--ptr = 0x10 | *cc;
+  }
+  *--ptr = pid & 0xff;
+  *--ptr = (start << 6) | (pid >> 8);
+  *--ptr = 0x47;
+  r5kdev->cb(ptr, 188, r5kdev->cb_data);
+  *cc = (*cc+1) & 0x0f;
+}
+
+static void directv_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len)
+{
+  int i;
+  struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata;
+  for(i = 0; i < len; i+=2) {
+    unsigned char data = buf[i];
+    unsigned char type = buf[i+1];
+    if(0xff == type) {
+      //video
+      dtv->video[dtv->vpos++] = data;
+      if(dtv->vpos > 4 && dtv->video[dtv->vpos-2] == 0x01 &&
+         dtv->video[dtv->vpos-3] == 0x00 && dtv->video[dtv->vpos-4] == 0x00) {
+        if (data == 0xe0) {
+          //HD video header (PES)
+          directv_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc);
+          dtv->pat_pmt_count++;
+          dtv->video[0] = 0x00;
+          dtv->video[1] = 0x00;
+          dtv->video[2] = 0x01;
+          dtv->video[3] = 0xe0;
+          dtv->vpos = 4;
+          dtv->vstart = 1;
+          dtv->vstate = data;
+        } else if (data == 0xb3 || data == 0x00) {
+          if (dtv->vstate == 0xff) {
+            dtv->vstate = data;
+            directv_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc);
+            dtv->pat_pmt_count++;
+            //Create a PES header, but no PTS/DTS info yet so just use stuffing bytes
+            dtv->vpos = directv_make_empty_pes(dtv->video, 0xe0);
+            dtv->video[dtv->vpos++] = 0x00;
+            dtv->video[dtv->vpos++] = 0x00;
+            dtv->video[dtv->vpos++] = 0x01;
+            dtv->video[dtv->vpos++] = data;
+            dtv->vstart = 1;
+            dtv->pic_pos = dtv->vpos;
+          }
+        }
+      }
+      if(dtv->vpos == 188) {
+        if (dtv->vstate == 0x00)
+          //We found pic frame without a PES header (SD)
+          directv_update_video_pes(dtv->video, dtv->pic_pos);
+        directv_write_ts(r5kdev, dtv->video, 184, DTV_VPID, dtv->vstart, &dtv->video_cc);
+        dtv->pat_pmt_count++;
+        dtv->video[0] = dtv->video[184];
+        dtv->video[1] = dtv->video[185];
+        dtv->video[2] = dtv->video[186];
+        dtv->video[3] = dtv->video[187];
+        dtv->vpos = 4;
+        dtv->vstart = 0;
+        dtv->vstate = 0xff;
+      }
+    } else if(0xfe == type) {
+      //audio
+      dtv->audio[dtv->apos++] = data;
+      dtv->alen--;
+      if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xbd && dtv->audio[dtv->apos-4] == 0x01 &&
+         dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) {
+        dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data;
+        directv_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc);
+        dtv->pat_pmt_count++;
+        dtv->audio[0] = 0x00;
+        dtv->audio[1] = 0x00;
+        dtv->audio[2] = 0x01;
+        dtv->audio[3] = 0xbd;
+        dtv->audio[4] = dtv->audio[dtv->apos-2];
+        dtv->audio[5] = data;
+        dtv->apos = 6;
+        dtv->astart = 1;
+        r5kdev->pmt[1].id = 0x81; //AC3
+      } else if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xc0 && dtv->audio[dtv->apos-4] == 0x01 &&
+           dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) {
+        dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data;
+        directv_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc);
+        dtv->pat_pmt_count++;
+        dtv->audio[0] = 0x00;
+        dtv->audio[1] = 0x00;
+        dtv->audio[2] = 0x01;
+        dtv->audio[3] = 0xc0;
+        dtv->audio[4] = (dtv->alen + 3) >> 8;
+        dtv->audio[5] = (dtv->alen + 3) & 0xff;
+        dtv->audio[6] = 0x80;
+        dtv->audio[7] = 0x80;
+        dtv->audio[8] = 0x05;
+        dtv->apos = 9;
+        dtv->astart = 1;
+        r5kdev->pmt[1].id = 0x04; //MP2
+      } else if(dtv->apos == 190) {
+        if(dtv->astart && dtv->audio[3] == 0xc0)
+          directv_fix_audio_pts(dtv->audio+9);
+        directv_write_ts(r5kdev, dtv->audio, 184, DTV_APID, dtv->astart, &dtv->audio_cc);
+        dtv->pat_pmt_count++;
+        dtv->audio[0] = dtv->audio[184];
+        dtv->audio[1] = dtv->audio[185];
+        dtv->audio[2] = dtv->audio[186];
+        dtv->audio[3] = dtv->audio[187];
+        dtv->audio[4] = dtv->audio[188];
+        dtv->audio[5] = dtv->audio[189];
+        dtv->apos = 6;
+        dtv->astart = 0;
+      }
+    }
+  }
+  if(r5kdev->pmt[1].id && dtv->pat_pmt_count > DTV_PAT_PMT_COUNT) {
+    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data);
+    r5000_send_pmt(r5kdev);
+    dtv->pat_pmt_count = 0;
+  }
+}
+
+static void directv_start_stream(r5kdev_t *r5kdev)
+{
+  struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata;
+  dtv->vstart = 0;
+  dtv->astart = 0;
+  dtv->vpos = 0;
+  dtv->apos = 0;
+  dtv->video_cc = 0;
+  dtv->audio_cc = 0;
+  dtv->vstate = 0;
+  dtv->pat_pmt_count = DTV_PAT_PMT_COUNT;
+}
+void directv_init(r5kdev_t *r5kdev)
+{
+  struct r5000_dtv *dtv = (struct r5000_dtv *)calloc(1, sizeof(struct r5000_dtv));
+  dtv->video = dtv->vbuf + 188;
+  dtv->audio = dtv->abuf + 188;
+  dtv->pat_pmt_count = DTV_PAT_PMT_COUNT;
+  dtv->vstate = 0xff;
+  r5kdev->stbdata = dtv;
+  r5kdev->pmt[0].id = 0x02; //MPEG2
+  r5kdev->pmt[0].pid = DTV_VPID;
+  r5kdev->pmt[1].id = 0x00;
+  r5kdev->pmt[1].pid = DTV_APID;
+  r5kdev->pmt[1].desc = r5000_pmt_audio_desc;
+  r5kdev->num_pmt_entries = 2;
+  r5kdev->process_block = directv_process_block;
+  r5kdev->start_stream  = directv_start_stream;
+  r5kdev->button = &directv_button_cmd;
+  r5kdev->read_words = 1;
+}
+
+void directv_free(r5kdev_t *r5kdev)
+{
+  free(r5kdev->stbdata);
+}
Index: libs/libmythtv/r5000/r5k_misc.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5k_misc.c	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <string.h>
+#include "r5000_internal.h"
+
+unsigned char r5000_pat_pkt[188] = {
+0x47, 0x40, 0x00, 0x13, 0x00, 0x00, 0xb0, 0x0d, 0x00, 0x06, 0xc5, 0x00, 0x00, 0x00, 0x01, 0xe0,
+0x21, 0x19, 0x3a, 0x82, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+
+struct r5k_descriptor r5000_pmt_audio_desc = {{0x06, 0x0a, 0x04, 0x65, 0x6e, 0x67, 0x00}};
+struct r5k_descriptor r5000_pmt_video_desc = {{0x00}};
+
+//taken and adapted from libdtv, (c) Rolf Hakenes
+// CRC32 lookup table for polynomial 0x04c11db7
+static unsigned int crc_table[256] = {
+   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+   0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+   0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+   0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+   0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+   0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+   0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+   0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+   0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+   0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+   0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+   0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+   0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+   0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+   0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+   0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+   0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+   0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+   0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+   0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+   0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+   0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+   0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
+
+static void r5000_calc_crc(unsigned char *out, const unsigned char *d, int len)
+{
+   register int i;
+   unsigned int crc = 0xFFFFFFFF;
+   const unsigned char *u=(unsigned char*)d; // Saves '& 0xff'
+
+   for (i=0; i<len; i++)
+      crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];
+
+   *out++ = (crc >> 24) & 0xff;
+   *out++ = (crc >> 16) & 0xff;
+   *out++ = (crc >> 8) & 0xff;
+   *out++ = (crc >> 0) & 0xff;
+}
+
+static void r5000_build_pmt(r5kdev_t *r5kdev)
+{
+  int i;
+  unsigned char *ptr;
+  unsigned char ts[188] = {
+  0x47, 0x40, 0x21, 0x10,
+  0x00, 0x02,
+  0xb0, 0x00,  //length
+  0x00, 0x01,
+  0xc3, 0x00, 0x00,
+  0xf0, 0x00,  //PCR_PID
+  0xf0, 0x00}; //Program Info Length
+  ts[3] = 0x10 | r5kdev->pmt_next_cc;
+  printf("Building PMT\n");
+  ptr = ts + 17;
+  for(i = 0; i < r5kdev->num_pmt_entries; i++) {
+    *ptr++ = r5kdev->pmt[i].id;
+    *ptr++ = 0xe0 | (r5kdev->pmt[i].pid>>8);
+    *ptr++ = r5kdev->pmt[i].pid & 0xff;
+    *ptr++ = 0xf0;
+    if(IS_VIDEO(r5kdev->pmt[i].id)) {
+      *ptr++ = 0x00;
+      ts[13] = 0xe0 | (r5kdev->pmt[i].pid >> 8);
+      ts[14] = r5kdev->pmt[i].pid & 0xff;
+    } else {
+      memcpy(ptr, r5kdev->pmt[i].desc.d, r5kdev->pmt[i].desc.d[0]+1);
+      ptr += r5kdev->pmt[i].desc.d[0]+1;
+    }
+  }
+  ts[7] = (ptr - ts) - 8/*header*/ + 4/*CRC*/;
+  r5000_calc_crc(ptr, ts + 5, (ptr - ts) - 5);
+  memset(ptr+4, 0xff, 188 - (ptr - ts - 4));
+  memcpy(r5kdev->pmt_pkt, ts, 188);
+}
+
+void r5000_send_pmt(r5kdev_t *r5kdev)
+{
+  if(r5kdev->pmt_pkt[0] != 0x47) {
+    r5000_build_pmt(r5kdev);
+  }
+  r5kdev->pmt_pkt[3] = 0x10 | r5kdev->pmt_next_cc;
+  r5kdev->pmt_next_cc = (r5kdev->pmt_next_cc + 1) & 0x0f;
+  r5kdev->cb(r5kdev->pmt_pkt, 188, r5kdev->cb_data);
+}
Index: libs/libmythtv/r5000/r5k_sat.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5k_sat.c	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,334 @@
+//Support for Dish Network ViP211/ViP422 boxes
+#include <stdio.h>
+#include <string.h>
+#include "r5000_internal.h"
+
+#define DTV_PAT_PMT_COUNT 5000
+#define MAX_PKT_SIZE 272
+#define MAX_PAT_SECTIONS 1
+#define MAX_SIDS 200
+#define MAX_EPIDS 5
+
+struct pat {
+  int version;
+  unsigned char last_section;
+  unsigned char section_seen[MAX_PAT_SECTIONS];
+  unsigned int pmts[MAX_SIDS];
+  int pmt_count;
+};
+
+struct sids {
+  unsigned short sid;
+  struct r5k_epid epid[MAX_EPIDS];
+  unsigned char epid_count;
+};
+
+struct r5000_sat {
+  unsigned char buf[MAX_PKT_SIZE];
+  unsigned int pos;
+  int offset;
+  unsigned char sync;
+  unsigned char bytesize;
+  unsigned char sync_byte;
+  unsigned int has_sync_byte;
+  unsigned int pat_pmt_count;
+  unsigned int packet_size;
+  unsigned int allowed_packet_size[8];
+
+  struct pat pats;
+  struct sids *sids;
+};
+
+static int sat_read_pat_pkt(unsigned char *pes, struct pat *pat, unsigned int size) {
+  unsigned int sec, end;
+  int version;
+  unsigned char *ptr, last_sec;
+
+  if (pes[0] != 0x00) {
+    printf(
+             "read_pat: expected PAT table 0x00 but got 0x%02x\n", pes[0]);
+    return 1;
+  }
+  end = (((pes[1] & 0x03) << 8 | pes[2]) + 3 - 4);
+  if(end > size-4) {
+    printf("read_pat: invalid PAT table size (%d > %d)\n", end, size-4);
+    return 1;
+  }
+  version = (pes[5] >> 1) & 0x1f;
+  sec = pes[6];
+  last_sec = pes[7];
+  if(last_sec >= MAX_PAT_SECTIONS) {
+    printf("read_pat: illegal section count %d > %d\n",
+             last_sec, MAX_PAT_SECTIONS);
+    return 1;
+  }
+  if (pat->version != version || last_sec != pat->last_section) {
+    pat->version = version;
+    pat->last_section = last_sec;
+    pat->pmt_count = 0;
+  }
+  if(pat->section_seen[sec])
+    return 0;
+  pat->section_seen[sec] = 1;
+  for(ptr = pes + 8; ptr < pes + end; ptr += 4) {
+    int sid, pid;
+    struct filter *filt;
+    sid = (ptr[0] << 8) | ptr[1];
+    pid = ((ptr[2] & 0x1F) << 8) | ptr[3];
+    if(sid != 0) {
+      printf("found PID: %04x for sid: %d\n", pid, sid);
+      pat->pmts[pat->pmt_count++] = (sid << 16) | pid;
+    }
+  }
+  return 0;
+}
+
+static int sat_read_pmt_pkt(unsigned char *buf, struct sids *sids,
+                    unsigned int size) {
+  //
+  // NOTE we aren't using last_sec here yet!
+  //
+
+  struct sids *sidptr = sids;
+  unsigned int count, skip, pos;
+  int sid, sec, last_sec, pcrpid, epid, type;
+  if (buf[0] != 0x02) {
+    printf("read_pmt expected table 0x02 but got 0x%02x\n", buf[0]);
+    return -1;
+  }
+  count = (((buf[1] & 0x03) << 8) | buf[2]) + 3 - 4;
+  sid = (buf[3] << 8) | buf[4];
+  sec = buf[6];
+  last_sec = buf[7];
+  pcrpid = ((buf[8] & 0x1F) << 8) | buf[9];
+  skip = ((buf[10] & 0x03) << 8) | buf[11];
+  if(skip > count - 12 || count > size) {
+    printf("skip: %d > count: %d - 12 || count > size: %d\n",
+           skip, count, size);
+    return -1;
+  }
+
+  printf("read_pmt: sid: %d pcrpid: %d skip: %d count: %d\n", sid, pcrpid, skip, count);
+  while(sidptr->sid != 0) {
+    if(sidptr->sid == sid)
+      break;
+    sidptr++;
+  }
+  if(sidptr->sid != 0) {
+    printf("Already seen sid: %d\n", sid);
+    return -1;
+  }
+  sidptr->sid = sid;
+  sidptr->epid_count = 0;
+  for(pos = 12 + skip; pos < count;) {
+    int j;
+    struct r5k_epid *pidptr = &sidptr->epid[sidptr->epid_count];
+    type = buf[pos];
+    epid = ((buf[pos+1] & 0x1F) << 8) | buf[pos+2];
+    skip = ((buf[pos+3] & 0x03) << 8) | buf[pos+4];
+    pidptr->pid = epid;
+    pidptr->id  = type;
+    memcpy(pidptr->desc.d, buf + 4, skip + 1);
+    sidptr->epid_count++;
+    printf("read_pmt: epid %04x (type %02x) mapped to sid %d\n", epid, type, sid);
+    pos += 5 + skip;
+  }
+  ++sidptr;
+  sidptr->sid = 0;
+  return 0;
+}
+void sat_add_pmt(r5kdev_t *r5kdev, struct r5k_epid *epid)
+{
+  int i;
+  int is_video = IS_VIDEO(epid->id);
+
+  for(i = 0; i < r5kdev->num_pmt_entries; i++) {
+    if(r5kdev->pmt[i].pid == epid->pid) {
+      if(r5kdev->pmt[i].id == epid->id)
+        return;
+      //different table_id for existing pid.  Reset
+      r5kdev->num_pmt_entries = 0;
+      r5kdev->pmt_state = 0;
+      r5kdev->pmt_pkt[0] = 0;
+      break;
+    }
+    if(is_video) {
+      if(IS_VIDEO(r5kdev->pmt[i].id)) {
+        //a video entry already exists.  Reset
+        r5kdev->num_pmt_entries = 0;
+        r5kdev->pmt_state = 0;
+        r5kdev->pmt_pkt[0] = 0;
+        break;
+      }
+    }
+  }
+  //Didn't find this PID, add it
+  if(i == R5K_MAX_PIDS)
+    return;
+  printf("Adding %04x: %02x @ %08x\n", epid->pid, epid->id, r5kdev->bytes_read);
+  r5kdev->pmt[r5kdev->num_pmt_entries++] = *epid;
+  r5kdev->pmt_state |= is_video ? 0x01 : 0x02;
+}
+
+void sat_process_ts(r5kdev_t *r5kdev, unsigned char *buf)
+{
+  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata;
+  int stream_id, pid, afc, af_size = 0;
+  int i, j, k;
+  pid = ((buf[1] << 8) | buf[2]) & 0x1fff;
+  if(pid == 0x1fff)
+    return;
+  if(! sat->pats.pmt_count) {
+    if(pid != 0 || !buf[1] & 0x40)
+      return;
+    sat_read_pat_pkt(buf+buf[4]+5, &sat->pats, 188-buf[4]-5);
+    if(sat->pats.pmt_count)
+      sat->sids = calloc(1, sizeof(struct sids)*(sat->pats.pmt_count+1));
+  } else {
+    if(! r5kdev->num_pmt_entries) {
+      for(i = 0; i < sat->pats.pmt_count; i++) {
+        if(pid == (unsigned short)(sat->pats.pmts[i])) {
+          if(buf[1] & 0x40 && buf[4]+5 < 188 && buf[buf[4]+5] == 0x02) {
+            sat_read_pmt_pkt(buf+buf[4]+5, sat->sids, 188-buf[4]-5);
+          }
+          break;
+        }
+        for(j = 0; j < sat->sids[i].epid_count; j++) {
+          if(pid == sat->sids[i].epid[j].pid) {
+            if(sat->sids[i].epid[j].id == 0x80 ||
+               IS_VIDEO(sat->sids[i].epid[j].id)) {
+              if(! r5kdev->channel)
+                r5kdev->channel = sat->sids[i].sid;
+              if(r5kdev->channel == sat->sids[i].sid) {
+                //Found unencrypted video.  Choose this one
+                // Assume this is MPEG2.  Don't know what MPEG4 looks like yet
+                sat_add_pmt(r5kdev, &sat->sids[i].epid[j]);
+                for(k = 0; k < sat->sids[i].epid_count; k++) {
+                  if(sat->sids[i].epid[k].id == 0x81 ||
+                     sat->sids[i].epid[k].id == 0xbd) {
+                    sat_add_pmt(r5kdev, &sat->sids[i].epid[k]);
+                  }
+                }
+                r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data);
+                r5000_send_pmt(r5kdev);
+                sat->pat_pmt_count = 0;
+              }
+            }
+          }
+        }
+      }
+    } else {
+printf("PID: %04x\n", pid);
+      for(i = 0; i < r5kdev->num_pmt_entries; i++) {
+        if(pid == r5kdev->pmt[i].pid) {
+          r5kdev->cb(sat->buf, 188, r5kdev->cb_data);
+          sat->pat_pmt_count++;
+          break;
+        }
+      }
+    }
+  }
+}
+
+static void sat_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len)
+{
+  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata;
+
+  int pos;
+  int sync = 1;
+  if(! r5kdev->streaming)
+    return;
+  if(len <= 0)
+    return;
+
+  for(pos = sat->offset; pos < len; pos += sat->bytesize) {
+    if(! sat->sync) {
+      if(buf[pos] == 0x47) {
+        int i;
+        if(pos == 0x1344)
+          printf("here\n");
+        if (pos + (sat->allowed_packet_size[0]<<1) < len) {
+          if((buf[pos+1] & 0xfc) == 0xfc && (buf[pos+3] & 0xfc) == 0xfc &&
+             (buf[pos+5] & 0xfc) == 0xfc && (buf[pos+7] & 0xfc) == 0xfc) {
+             sat->bytesize = 2;
+          }
+          for(i=0; sat->allowed_packet_size[i] != 0; i++) {
+            if(buf[pos+(sat->allowed_packet_size[i] * sat->bytesize)] == 0x47) {
+              printf("(%d) Found %d byte sync at %08x: bytesize = %d\n",
+                    r5kdev->nexturb, sat->allowed_packet_size[i],
+                    r5kdev->bytes_read+pos, sat->bytesize);
+              sat->packet_size = sat->allowed_packet_size[i];
+              sat->sync = 1;
+              sat->buf[0] = 0x47;
+              sat->pos = 1;
+              break;
+            }
+          }
+        }
+      }
+      continue;
+    }
+    if (sat->pos == 0 && buf[pos] != 0x47) {
+      sat->sync = 0;
+      sat->bytesize = 1;
+      printf("(%d)Lost sync at %08x\n", r5kdev->nexturb,
+             r5kdev->bytes_read+pos);
+      continue;
+    }
+    if(sat->pos == 3 && (buf[pos] & 0xc0) != 0x00) {
+      // Encrypted channel, skip this packet
+      sat->pos = 0;
+      pos += sat->bytesize * (sat->packet_size - 4); //Loop adds additional 2
+      continue;
+    }
+    sat->buf[sat->pos++] = buf[pos];
+    if (sat->pos == sat->packet_size) {
+      sat_process_ts(r5kdev, sat->buf);
+      //if packet size > 188, assume remaining bytes are parity and ignore
+      sat->pos = 0;
+    }
+  }
+  sat->offset = pos - len;
+  if(1 && r5kdev->pmt_state == 0x03 && sat->pat_pmt_count > DTV_PAT_PMT_COUNT) {
+    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data);
+    r5000_send_pmt(r5kdev);
+    sat->pat_pmt_count = 0;
+  }
+}
+
+static void sat_start_stream(r5kdev_t *r5kdev)
+{
+  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata;
+  sat->offset = 0;
+  sat->sync = 0;
+  sat->pos = 0;
+  sat->bytesize = 1;
+}
+
+void sat_init(r5kdev_t *r5kdev, r5ktype_t type)
+{
+  struct r5000_sat *sat =
+                   (struct r5000_sat *)calloc(1, sizeof(struct r5000_sat));
+  r5kdev->stbdata = sat;
+  sat->pat_pmt_count = DTV_PAT_PMT_COUNT;
+  if(type == R5K_STB_HDD) {
+    sat->sync_byte = 0xff;
+    sat->has_sync_byte = 1;
+    sat->allowed_packet_size[0] = 272;
+    sat->allowed_packet_size[1] = 233;
+    sat->allowed_packet_size[2] = 204;
+    sat->allowed_packet_size[3] = 188;
+    sat->allowed_packet_size[4] = 0;
+  } else {
+    sat->allowed_packet_size[0] = 188;
+    sat->allowed_packet_size[1] = 0;
+  }
+  r5kdev->process_block = sat_process_block;
+  r5kdev->start_stream  = sat_start_stream;
+}
+
+void sat_free(r5kdev_t *r5kdev)
+{
+  free(r5kdev->stbdata);
+}
+
Index: libs/libmythtv/r5000/r5000init.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libs/libmythtv/r5000/r5000init.h	2008-03-15 08:18:45.000000000 -0700
@@ -0,0 +1,61 @@
+#ifndef R5000_INIT_H
+#define R5000_INIT_H
+
+#define R5K_INIT_MAX 9
+#define R5K_INIT_SERIAL 8
+#define R5K_DEFAULT_SLEEP 100000
+struct {
+  int rsleep;
+  int rlen;
+  int wsleep;
+  int wlen;
+  unsigned char data[0x40];
+} r5kinit[R5K_INIT_MAX] = {
+// 0
+{R5K_DEFAULT_SLEEP, -1, 0, 64,
+    {0x30}},
+// 1
+{R5K_DEFAULT_SLEEP, 1, 0, 64,
+    {0x08, 0x00, 0x20, 0x00, 0x00, 0x3a, 0xd4, 0x29, 0x7c, 0x56, 0x31, 0x44, 0x86, 0x6d, 0x0d, 0x0d,
+     0x1b, 0x0a, 0xad, 0x0f, 0xd0, 0x2e, 0x94, 0x3f, 0xd4, 0x08, 0xa2, 0x4b, 0x68, 0x14, 0x1f, 0x13,
+     0x04, 0x62, 0x1b, 0x14, 0xb9, 0x69, 0xcc, 0x25, 0x91, 0x06, 0xc9, 0x26, 0xf9, 0x41, 0x64, 0x46,
+     0x7d, 0x17, 0x61, 0x09, 0x5c, 0x5b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+// 2
+{R5K_DEFAULT_SLEEP, 1, 0, 64,
+    {0x08, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+// 3
+{R5K_DEFAULT_SLEEP, 1, 0, 64,
+    {0x08, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+// 4
+{R5K_DEFAULT_SLEEP, 1, R5K_DEFAULT_SLEEP, 64,
+    {0x08, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+// 5
+{R5K_DEFAULT_SLEEP, 26, 0, 6,
+    {0x08, 0x01, 0x00, 0x00, 0x01, 0x14}},
+// 6
+{R5K_DEFAULT_SLEEP, 1, 0, 64,
+    {0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+// 7
+{R5K_DEFAULT_SLEEP, 22, 0, 64,
+    {0x08, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+// 8
+{R5K_DEFAULT_SLEEP, 4, 0, 1,
+    {0x20}}
+};
+
+#endif

