Ticket #4752: r5000_r19_trunk19501.patch

File r5000_r19_trunk19501.patch, 197.2 KB (added by anonymous, 3 years ago)

Version 19 for TRUNK

  • configure

    old new  
    179179  echo "  --disable-ivtv           disable ivtv support (PVR-x50) req. v4l support" 
    180180  echo "  --disable-hdpvr          disable HD-PVR support" 
    181181  echo "  --disable-dvb            disable DVB support" 
     182  echo "  --disable-r5000          disable support for R5000 USB STBs" 
    182183  echo "  --dvb-path=HDRLOC        location of directory containing" 
    183184  echo "                           'linux/dvb/frontend.h', not the" 
    184185  echo "                           directory with frontend.h [$dvb_path]" 
     
    10201021    hdpvr 
    10211022    iptv 
    10221023    ivtv 
     1024    r5000 
    10231025    joystick_menu 
    10241026    libfftw3 
    10251027    lirc 
     
    12111213dbox2_deps="backend" 
    12121214dvb_deps="backend" 
    12131215firewire_deps="backend" 
     1216r5000_deps="backend" 
    12141217iptv_deps="backend" 
    12151218ivtv_deps="backend v4l" 
    12161219hdpvr_deps="backend v4l" 
     
    13291332enable hdpvr 
    13301333enable iptv 
    13311334enable ivtv 
     1335enable r5000 
    13321336enable lamemp3 
    13331337enable lirc 
    13341338enable mheg 
     
    29762980enabled libfftw3 && check_lib2 fftw3.h fftw_init_threads -lfftw3_threads -lfftw3 || 
    29772981    disable libfftw3 
    29782982 
     2983enabled r5000 && has_library libusb && check_header usb.h || disable r5000 
     2984 
    29792985enabled x11 && has_library libX11 || disable x11 
    29802986enabled xrandr && check_header X11/extensions/Xrandr.h || disable xrandr 
    29812987enabled xv && has_library libXv || disable xv 
     
    33013307#  echo "DBox2 support             ${dbox2-no}" 
    33023308  echo "HDHomeRun support         ${hdhomerun-no}" 
    33033309  echo "IPTV support              ${iptv-no}" 
     3310  echo "R5000 support             ${r5000-no}" 
    33043311fi 
    33053312 
    33063313if enabled frontend; then 
  • libs/libmythtv/cardutil.h

    old new  
    5454        HDHOMERUN = 10, 
    5555        FREEBOX   = 11, 
    5656        HDPVR     = 12, 
     57        R5000     = 13, 
    5758    }; 
    5859 
    5960    static enum CARD_TYPES toCardType(const QString &name) 
     
    8485            return FREEBOX; 
    8586        if ("HDPVR" == name) 
    8687            return HDPVR; 
     88        if ("R5000" == name) 
     89            return R5000; 
    8790        return ERROR_UNKNOWN; 
    8891    } 
    8992 
     
    9295        return 
    9396            (rawtype != "DVB")       && 
    9497            (rawtype != "FIREWIRE")  && (rawtype != "DBOX2")   && 
    95             (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX"); 
     98            (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") && 
     99            (rawtype != "R5000") ; 
    96100    } 
    97101 
    98102    static bool         IsUnscanable(const QString &rawtype) 
    99103    { 
    100104        return 
    101105            (rawtype == "FIREWIRE")  || (rawtype == "DBOX2") || 
    102             (rawtype == "HDPVR"); 
     106            (rawtype == "HDPVR") || (rawtype == "R5000"); 
    103107    } 
    104108 
    105109    static bool         IsEITCapable(const QString &rawtype) 
  • libs/libmythtv/libmythtv.pro

    old new  
    540540        DEFINES += USING_DVB 
    541541    } 
    542542 
     543    #Support for R5000 usb device 
     544    using_r5000 { 
     545        HEADERS += r5000channel.h           r5000recorder.h 
     546        HEADERS += r5000signalmonitor.h     r5000device.h 
     547        HEADERS += r5000/r5000.h            r5000/libusb_augment.h 
     548        HEADERS += r5000/r5000_internal.h   r5000/r5000init.h 
     549 
     550        SOURCES += r5000channel.cpp         r5000recorder.cpp 
     551        SOURCES += r5000signalmonitor.cpp   r5000device.cpp 
     552        SOURCES += r5000/r5000.c            r5000/libusb_augment.c 
     553        SOURCES += r5000/r5k_vip.c          r5000/r5k_pes.c 
     554        SOURCES += r5000/r5k_sat.c          r5000/r5k_misc.c 
     555        SOURCES += r5000/r5k_vip_buttons.c  r5000/r5k_directv_buttons.c 
     556        SOURCES += r5000/r5k_dish6000_buttons.c 
     557 
     558        LIBS += -lusb 
     559        DEFINES += USING_R5000 
     560    } 
     561 
    543562    DEFINES += USING_BACKEND 
    544563} 
    545564 
  • libs/libmythtv/signalmonitor.h

    old new  
    288288            (cardtype.toUpper() == "HDTV")      || 
    289289            (cardtype.toUpper() == "HDHOMERUN") || 
    290290            (cardtype.toUpper() == "FIREWIRE")  || 
    291             (cardtype.toUpper() == "FREEBOX")); 
     291            (cardtype.toUpper() == "FREEBOX")   || 
     292            (cardtype.toUpper() == "R5000")); 
    292293} 
    293294 
    294295inline bool SignalMonitor::IsSupported(const QString &cardtype) 
  • libs/libmythtv/signalmonitor.cpp

    old new  
    4242#   include "firewirechannel.h" 
    4343#endif 
    4444 
     45#ifdef USING_R5000 
     46#   include "r5000signalmonitor.h" 
     47#   include "r5000channel.h" 
     48#endif 
     49 
    4550#undef DBG_SM 
    4651#define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 
    4752    "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); 
     
    129134            signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 
    130135    } 
    131136#endif 
     137#ifdef USING_R5000 
     138    if (cardtype.toUpper() == "R5000") 
     139    { 
     140        R5000Channel *fc = dynamic_cast<R5000Channel*>(channel); 
     141        if (fc) 
     142            signalMonitor = new R5000SignalMonitor(db_cardnum, fc); 
     143    } 
     144#endif 
    132145 
    133146    if (!signalMonitor) 
    134147    { 
  • libs/libmythtv/cardutil.cpp

    old new  
    16131613    if (("FIREWIRE"  == cardtype) || 
    16141614        ("FREEBOX"   == cardtype) || 
    16151615        ("DBOX2"     == cardtype) || 
    1616         ("HDHOMERUN" == cardtype)) 
     1616        ("HDHOMERUN" == cardtype) || 
     1617        ("R5000"     == cardtype)) 
    16171618    { 
    16181619        ret += "MPEG2TS"; 
    16191620    } 
     
    17831784    if (("FIREWIRE"  == cardtype) || 
    17841785        ("FREEBOX"   == cardtype) || 
    17851786        ("DBOX2"     == cardtype) || 
    1786         ("HDHOMERUN" == cardtype)) 
     1787        ("HDHOMERUN" == cardtype) || 
     1788        ("R5000"     == cardtype)) 
    17871789    { 
    17881790        inputs += "MPEG2TS"; 
    17891791    } 
  • libs/libmythtv/videosource.cpp

    old new  
    3535#include "frequencies.h" 
    3636#include "diseqcsettings.h" 
    3737#include "firewiredevice.h" 
     38#include "r5000device.h" 
    3839#include "libmythdb/compat.h" 
    3940#include "libmythdb/mythdb.h" 
    4041#include "libmythdb/mythdirs.h" 
     
    14241425    } 
    14251426}; 
    14261427 
     1428class R5000SendPowerBeforeChannel : public CheckBoxSetting, public CaptureCardDBStorage 
     1429{ 
     1430  public: 
     1431    R5000SendPowerBeforeChannel(const CaptureCard &parent) : 
     1432        CheckBoxSetting(this), 
     1433        CaptureCardDBStorage(this, parent, "dvb_on_demand") 
     1434    { 
     1435        setValue(false); 
     1436        setLabel(QObject::tr("Turn on before Channel Change")); 
     1437        setHelpText(QObject::tr( 
     1438                        "On some STBs klike the ViP211, the power on/off " 
     1439                        "detection isn't reliable if you let the box go into " 
     1440                        "standby.  This forces a 'power-on' command before " 
     1441                        "changing channels.  This will very likely do the " 
     1442                        "wrong thing for non ViP boxes.")); 
     1443 
     1444    }; 
     1445}; 
     1446 
     1447class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage 
     1448{ 
     1449  public: 
     1450    R5000Serial(const CaptureCard &parent) : 
     1451        ComboBoxSetting(this), 
     1452        CaptureCardDBStorage(this, parent, "videodevice") 
     1453    { 
     1454        setLabel(QObject::tr("Serial #")); 
     1455#ifdef USING_R5000 
     1456        QStringList serials = R5000Device::GetSTBList(); 
     1457        for (int i = 0; i < serials.size(); i++) 
     1458        { 
     1459            addSelection(serials[i]); 
     1460        } 
     1461#endif // USING_FIREWIRE 
     1462    } 
     1463}; 
     1464 
     1465class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage 
     1466{ 
     1467  public: 
     1468    R5000Model(const CaptureCard  &parent) : 
     1469      ComboBoxSetting(this), 
     1470      CaptureCardDBStorage(this, parent, "firewire_model") 
     1471    { 
     1472        setLabel(QObject::tr("R5000 STB type")); 
     1473        addSelection("VIP211"); 
     1474        addSelection("VIP411"); 
     1475        addSelection("VIP622"); 
     1476        addSelection("VIP722"); 
     1477        addSelection("BEV9242"); 
     1478        addSelection("DISH6000"); 
     1479        addSelection("DIRECTV"); 
     1480        addSelection("STARCHOICE/DSR"); 
     1481        addSelection("HDD-200"); 
     1482        QString help = QObject::tr( 
     1483            "Choose the type of R5000 enabled STB you are using."); 
     1484        setHelpText(help); 
     1485    } 
     1486}; 
     1487class R5000ConfigurationGroup : public VerticalConfigurationGroup 
     1488{ 
     1489  public: 
     1490    R5000ConfigurationGroup(CaptureCard& a_parent): 
     1491       VerticalConfigurationGroup(false, true, false, false), 
     1492       parent(a_parent) 
     1493    { 
     1494        setUseLabel(false); 
     1495        addChild(new R5000SendPowerBeforeChannel(parent)); 
     1496        addChild(new R5000Serial(parent)); 
     1497        addChild(new R5000Model(parent)); 
     1498        addChild(new SingleCardInput(parent)); 
     1499    }; 
     1500 
     1501  private: 
     1502    CaptureCard &parent; 
     1503}; 
     1504 
    14271505class IPTVHost : public LineEditSetting, public CaptureCardDBStorage 
    14281506{ 
    14291507  public: 
     
    16541732#ifdef USING_IPTV 
    16551733    addTarget("FREEBOX",   new IPTVConfigurationGroup(parent)); 
    16561734#endif // USING_IPTV 
     1735 
     1736#ifdef USING_R5000 
     1737    addTarget("R5000", new R5000ConfigurationGroup(parent)); 
     1738#endif // USING_R5000 
    16571739} 
    16581740 
    16591741void CaptureCardGroup::triggerChanged(const QString& value) 
     
    18541936#ifdef USING_IPTV 
    18551937    setting->addSelection(QObject::tr("Network Recorder"), "FREEBOX"); 
    18561938#endif // USING_IPTV 
     1939 
     1940#ifdef USING_R5000 
     1941    setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000"); 
     1942#endif // USING_R5000 
    18571943} 
    18581944 
    18591945class CardID : public SelectLabelSetting, public CardInputDBStorage 
  • libs/libmythtv/tv_rec.cpp

    old new  
    4949#include "hdhrchannel.h" 
    5050#include "iptvchannel.h" 
    5151#include "firewirechannel.h" 
     52#include "r5000channel.h" 
    5253 
    5354#include "recorderbase.h" 
    5455#include "NuppelVideoRecorder.h" 
     
    5859#include "hdhrrecorder.h" 
    5960#include "iptvrecorder.h" 
    6061#include "firewirerecorder.h" 
     62#include "r5000recorder.h" 
    6163 
    6264#ifdef USING_V4L 
    6365#include "v4lchannel.h" 
     
    202204        init_run = true; 
    203205#endif 
    204206    } 
     207    else if (genOpt.cardtype == "R5000") 
     208    { 
     209#ifdef USING_R5000 
     210        channel = new R5000Channel(this, genOpt.videodev, fwOpt.model, dvbOpt.dvb_on_demand); 
     211        if (!channel->Open()) 
     212            return false; 
     213        InitChannel(genOpt.defaultinput, startchannel); 
     214        init_run = true; 
     215#endif 
     216    } 
    205217    else // "V4L" or "MPEG", ie, analog TV 
    206218    { 
    207219#ifdef USING_V4L 
     
    10211033        recorder->SetOption("mrl", genOpt.videodev); 
    10221034#endif // USING_IPTV 
    10231035    } 
     1036    else if (genOpt.cardtype == "R5000") 
     1037    { 
     1038#ifdef USING_R5000 
     1039        recorder = new R5000Recorder(this, GetR5000Channel()); 
     1040#endif // USING_R5000 
     1041    } 
    10241042    else 
    10251043    { 
    10261044#ifdef USING_V4L 
     
    12381256#endif // USING_FIREWIRE 
    12391257} 
    12401258 
     1259R5000Channel *TVRec::GetR5000Channel(void) 
     1260{ 
     1261#ifdef USING_R5000 
     1262    return dynamic_cast<R5000Channel*>(channel); 
     1263#else 
     1264    return NULL; 
     1265#endif // USING_R5000 
     1266} 
     1267 
    12411268V4LChannel *TVRec::GetV4LChannel(void) 
    12421269{ 
    12431270#ifdef USING_V4L 
  • libs/libmythtv/transporteditor.cpp

    old new  
    734734        left->addChild(new Modulation(id, nType)); 
    735735    } 
    736736    else if ((CardUtil::FIREWIRE == nType) || 
    737              (CardUtil::FREEBOX  == nType)) 
     737             (CardUtil::FREEBOX  == nType) || 
     738             (CardUtil::R5000    == nType)) 
    738739    { 
    739740        left->addChild(new DTVStandard(id, true, true)); 
    740741    } 
  • libs/libmythtv/tv_rec.h

    old new  
    4242class FirewireChannel; 
    4343class V4LChannel; 
    4444class HDHRChannel; 
     45class R5000Channel; 
    4546 
    4647class MPEGStreamData; 
    4748class ProgramMapTable; 
     
    288289    HDHRChannel  *GetHDHRChannel(void); 
    289290    DVBChannel   *GetDVBChannel(void); 
    290291    FirewireChannel *GetFirewireChannel(void); 
     292    R5000Channel *GetR5000Channel(void); 
    291293    V4LChannel   *GetV4LChannel(void); 
    292294 
    293295    bool SetupSignalMonitor(bool enable_table_monitoring, bool notify); 
  • new file libs/libmythtv/r5000channel.cpp

    - +  
     1/** 
     2 *  R5000Channel 
     3 *  Copyright (c) 2005 by Jim Westfall, Dave Abrahams 
     4 *  Copyright (c) 2006 by Daniel Kristjansson 
     5 *  Distributed as part of MythTV under GPL v2 and later. 
     6 */ 
     7 
     8#include "mythcontext.h" 
     9#include "tv_rec.h" 
     10#include "r5000channel.h" 
     11 
     12#define LOC QString("R5kChan(%1): ").arg(GetDevice()) 
     13#define LOC_WARN QString("R5kChan(%1), Warning: ").arg(GetDevice()) 
     14#define LOC_ERR QString("R5kChan(%1), Error: ").arg(GetDevice()) 
     15 
     16R5000Channel::R5000Channel(TVRec *parent, const QString &_videodevice,const QString &_r5ktype, bool pocc) : 
     17    DTVChannel(parent), 
     18    videodevice(_videodevice), 
     19    power_on_channel_change(pocc), 
     20    device(NULL), 
     21    current_channel(""), 
     22    current_mpeg_prog(0), 
     23    isopen(false) 
     24{ 
     25    int type = R5000Device::GetDeviceType(_r5ktype); 
     26    device = new R5000Device(type, videodevice); 
     27 
     28    InitializeInputs(); 
     29} 
     30 
     31bool R5000Channel::SetChannelByString(const QString &channum) 
     32{ 
     33    QString loc = LOC + QString("SetChannelByString(%1)").arg(channum); 
     34    bool ok = false; 
     35    VERBOSE(VB_CHANNEL, loc); 
     36 
     37    InputMap::const_iterator it = inputs.find(currentInputID); 
     38    if (it == inputs.end()) 
     39        return false; 
     40 
     41    QString tvformat, modulation, freqtable, freqid, dtv_si_std; 
     42    int finetune; 
     43    uint64_t frequency; 
     44    int mpeg_prog_num; 
     45    uint atsc_major, atsc_minor, mplexid, tsid, netid; 
     46    if (!ChannelUtil::GetChannelData( 
     47        (*it)->sourceid, channum, 
     48        tvformat, modulation, freqtable, freqid, 
     49        finetune, frequency, 
     50        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid, 
     51        mplexid, commfree)) 
     52    { 
     53        VERBOSE(VB_IMPORTANT, loc + " " + QString( 
     54                    "Requested channel '%1' is on input '%2' " 
     55                    "which is in a busy input group") 
     56                .arg(channum).arg(currentInputID)); 
     57 
     58        return false; 
     59    } 
     60    uint mplexid_restriction; 
     61    if (!IsInputAvailable(currentInputID, mplexid_restriction)) 
     62    { 
     63        VERBOSE(VB_IMPORTANT, loc + " " + QString( 
     64                    "Requested channel '%1' is on input '%2' " 
     65                    "which is in a busy input group") 
     66                .arg(channum).arg(currentInputID)); 
     67 
     68        return false; 
     69    } 
     70 
     71    if (!(*it)->externalChanger.isEmpty()) 
     72    { 
     73        ok = ChangeExternalChannel(freqid); 
     74        // -1 resets any state without executing a channel change 
     75        device->SetChannel(fw_opts.model, 0, mpeg_prog_num); 
     76        SetSIStandard("mpeg"); 
     77        SetDTVInfo(0,0,0,0,1); 
     78    } 
     79    else 
     80    { 
     81        ok = isopen && SetChannelByNumber(freqid, mpeg_prog_num); 
     82    } 
     83 
     84    if (ok) 
     85    { 
     86        // Set the current channum to the new channel's channum 
     87        QString tmp = channum; 
     88        tmp.detach(); 
     89        curchannelname = tmp; 
     90        tmp.detach(); 
     91        (*it)->startChanNum = tmp; 
     92    } 
     93 
     94    VERBOSE(VB_CHANNEL, loc + " " + ((ok) ? "success" : "failure")); 
     95 
     96    return ok; 
     97} 
     98 
     99bool R5000Channel::Open(void) 
     100{ 
     101    VERBOSE(VB_CHANNEL, LOC + "Open()"); 
     102 
     103    if (inputs.find(currentInputID) == inputs.end()) 
     104        return false; 
     105 
     106    if (!device) 
     107        return false; 
     108 
     109    if (isopen) 
     110        return true; 
     111 
     112    if (!device->OpenPort()) 
     113        return false; 
     114 
     115    isopen = true; 
     116 
     117    return true; 
     118} 
     119 
     120void R5000Channel::Close(void) 
     121{ 
     122    VERBOSE(VB_CHANNEL, LOC + "Close()"); 
     123    if (isopen) 
     124    { 
     125        device->ClosePort(); 
     126        isopen = false; 
     127    } 
     128} 
     129 
     130QString R5000Channel::GetDevice(void) const 
     131{ 
     132    return videodevice; 
     133} 
     134 
     135bool R5000Channel::SetPowerState(bool on) 
     136{ 
     137    if (!isopen) 
     138    { 
     139        VERBOSE(VB_IMPORTANT, LOC_ERR + 
     140                "SetPowerState() called on closed R5000Channel."); 
     141 
     142        return false; 
     143    } 
     144 
     145    return device->SetPowerState(on); 
     146} 
     147 
     148R5000Device::PowerState R5000Channel::GetPowerState(void) const 
     149{ 
     150    if (!isopen) 
     151    { 
     152        VERBOSE(VB_IMPORTANT, LOC_ERR + 
     153                "GetPowerState() called on closed R5000Channel."); 
     154 
     155        return R5000Device::kAVCPowerQueryFailed; 
     156    } 
     157 
     158    return device->GetPowerState(); 
     159} 
     160 
     161bool R5000Channel::Retune(void) 
     162{ 
     163    VERBOSE(VB_CHANNEL, LOC + "Retune()"); 
     164 
     165    if (! power_on_channel_change && R5000Device::kAVCPowerOff == GetPowerState()) 
     166    { 
     167        VERBOSE(VB_IMPORTANT, LOC_ERR + 
     168                "STB is turned off, must be on to retune."); 
     169 
     170        return false; 
     171    } 
     172 
     173    if (current_channel.length()) 
     174        return SetChannelByNumber(current_channel, current_mpeg_prog); 
     175 
     176    return false; 
     177} 
     178 
     179bool R5000Channel::SetChannelByNumber(const QString &channel, int mpeg_prog) 
     180{ 
     181    VERBOSE(VB_CHANNEL, QString("SetChannelByNumber(%1)").arg(channel)); 
     182    current_channel = channel; 
     183    current_mpeg_prog = mpeg_prog; 
     184 
     185    if (R5000Device::kAVCPowerOff == GetPowerState()) 
     186    { 
     187        VERBOSE(VB_IMPORTANT, LOC_WARN + 
     188                "STB is turned off, must be on to set channel."); 
     189 
     190        SetSIStandard("mpeg"); 
     191        SetDTVInfo(0,0,0,0,1); 
     192 
     193        return true; // signal monitor will call retune later... 
     194    } 
     195 
     196    QString tmpchan = (power_on_channel_change ? "P" : "") + channel; 
     197    if (! device->SetChannel(fw_opts.model, tmpchan, mpeg_prog)) 
     198        return false; 
     199 
     200    SetSIStandard("mpeg"); 
     201    SetDTVInfo(0,0,0,0,1); 
     202 
     203    return true; 
     204} 
  • new file libs/libmythtv/r5000device.cpp

    - +  
     1/** 
     2 *  R5000Device 
     3 *  Copyright (c) 2008 by Alan Nisota 
     4 *  Copyright (c) 2005 by Jim Westfall 
     5 *  Distributed as part of MythTV under GPL v2 and later. 
     6 */ 
     7 
     8// MythTV headers 
     9#include "r5000device.h" 
     10#include "mythcontext.h" 
     11#include "pespacket.h" 
     12 
     13#define LOC      QString("R5kDev: ") 
     14#define LOC_WARN QString("R5kDev, Warning: ") 
     15#define LOC_ERR  QString("R5kDev, Error: ") 
     16 
     17static int r5k_init = 0; 
     18QMap<uint64_t,QString> R5000Device::s_id_to_model; 
     19QMutex                 R5000Device::s_static_lock; 
     20 
     21unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 
     22{ 
     23    R5000Device *fw = (R5000Device*) callback_data; 
     24    if (! fw) 
     25        return 0; 
     26    if (len > 0) 
     27        fw->BroadcastToListeners(tspacket, len); 
     28    return 1; 
     29} 
     30 
     31void r5000_msg(char * msg) 
     32{ 
     33    VERBOSE(VB_IMPORTANT, "R5kLib: "<<msg); 
     34} 
     35 
     36class R5kPriv 
     37{ 
     38  public: 
     39    R5kPriv() : 
     40        reset_timer_on(false), 
     41        run_port_handler(false), is_port_handler_running(false), 
     42        channel(-1), 
     43        is_streaming(false) 
     44    { 
     45    } 
     46 
     47    bool             reset_timer_on; 
     48    MythTimer        reset_timer; 
     49 
     50    bool             run_port_handler; 
     51    bool             is_port_handler_running; 
     52    QMutex           start_stop_port_handler_lock; 
     53 
     54    int              channel; 
     55 
     56    bool             is_streaming; 
     57 
     58    QDateTime        stop_streaming_timer; 
     59    pthread_t        port_handler_thread; 
     60 
     61    static QMutex           s_lock; 
     62}; 
     63QMutex          R5kPriv::s_lock; 
     64 
     65//callback functions 
     66void *r5000_device_port_handler_thunk(void *param); 
     67 
     68R5000Device::R5000Device(int type, QString serial) : 
     69    m_type(type), 
     70    m_serial(serial), 
     71    m_last_channel(""),      m_last_crc(0), 
     72    m_buffer_cleared(true), m_open_port_cnt(0), 
     73    m_lock(),          m_priv(new R5kPriv()) 
     74{ 
     75    QMutexLocker locker(&s_static_lock); 
     76    usbdev = NULL; 
     77    if (! r5k_init) 
     78      r5k_init = r5000_init(r5000_msg); 
     79} 
     80 
     81R5000Device::~R5000Device() 
     82{ 
     83    if (usbdev) 
     84    { 
     85        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 
     86        while (usbdev) 
     87            ClosePort(); 
     88    } 
     89 
     90    if (m_priv) 
     91    { 
     92        delete m_priv; 
     93        m_priv = NULL; 
     94    } 
     95} 
     96 
     97void R5000Device::AddListener(TSDataListener *listener) 
     98{ 
     99    if (listener) 
     100    { 
     101        vector<TSDataListener*>::iterator it = 
     102            find(m_listeners.begin(), m_listeners.end(), listener); 
     103 
     104        if (it == m_listeners.end()) 
     105            m_listeners.push_back(listener); 
     106    } 
     107 
     108    VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size()); 
     109    if (!m_listeners.empty()) 
     110    { 
     111        StartStreaming(); 
     112    } 
     113} 
     114 
     115void R5000Device::RemoveListener(TSDataListener *listener) 
     116{ 
     117    vector<TSDataListener*>::iterator it = m_listeners.end(); 
     118 
     119    do 
     120    { 
     121        it = find(m_listeners.begin(), m_listeners.end(), listener); 
     122        if (it != m_listeners.end()) 
     123            m_listeners.erase(it); 
     124    } 
     125    while (it != m_listeners.end()); 
     126 
     127    VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size()); 
     128    if (m_listeners.empty()) 
     129    { 
     130        StopStreaming(); 
     131    } 
     132} 
     133 
     134bool R5000Device::StartStreaming(void) 
     135{ 
     136    if (m_priv->is_streaming) 
     137        return m_priv->is_streaming; 
     138 
     139    if (! usbdev) 
     140    { 
     141        VERBOSE(VB_IMPORTANT, LOC_ERR + "Device not open"); 
     142        return false; 
     143    } 
     144    if (r5000_start_stream(usbdev)) 
     145    { 
     146        m_priv->is_streaming = true; 
     147    } 
     148    else 
     149    { 
     150        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming "); 
     151    } 
     152 
     153    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- done"); 
     154 
     155    return m_priv->is_streaming; 
     156} 
     157 
     158bool R5000Device::StopStreaming(void) 
     159{ 
     160    if (m_priv->is_streaming) 
     161    { 
     162        VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really"); 
     163 
     164        m_priv->is_streaming = false; 
     165 
     166        r5000_stop_stream(usbdev); 
     167    } 
     168 
     169    VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 
     170 
     171    return true; 
     172} 
     173 
     174bool R5000Device::SetPowerState(bool on) 
     175{ 
     176    QMutexLocker locker(&m_lock); 
     177    QString cmdStr = (on) ? "on" : "off"; 
     178    VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr)); 
     179    r5000_power_on_off(usbdev, on); 
     180    return true; 
     181} 
     182 
     183R5000Device::PowerState R5000Device::GetPowerState(void) 
     184{ 
     185    QMutexLocker locker(&m_lock); 
     186    int on_off; 
     187 
     188    VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State"); 
     189    on_off = r5000_get_power_state(usbdev); 
     190    VERBOSE(VB_CHANNEL, LOC + (on_off ? "On" : "Off")); 
     191    return on_off ? kAVCPowerOn : kAVCPowerOff; 
     192} 
     193 
     194bool R5000Device::SetChannel(const QString &panel_model, 
     195                                const QString &channel, uint mpeg_prog) 
     196{ 
     197    VERBOSE(VB_CHANNEL, QString("SetChannel(model %1, chan %2 mpeg_prog %3)") 
     198            .arg(panel_model).arg(channel).arg(mpeg_prog)); 
     199 
     200    QMutexLocker locker(&m_lock); 
     201    VERBOSE(VB_CHANNEL, "SetChannel() -- locked"); 
     202    if (! r5000_change_channel(usbdev, channel.toAscii(), mpeg_prog)) 
     203        VERBOSE(VB_IMPORTANT, LOC + "Failed to set channel"); 
     204    return true; 
     205} 
     206 
     207void R5000Device::BroadcastToListeners( 
     208    const unsigned char *data, uint dataSize) 
     209{ 
     210    if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) && 
     211        ((data[1] & 0x1f) == 0) && (data[2] == 0)) 
     212    { 
     213        ProcessPATPacket(*((const TSPacket*)data)); 
     214    } 
     215 
     216    vector<TSDataListener*>::iterator it = m_listeners.begin(); 
     217    for (; it != m_listeners.end(); ++it) 
     218        (*it)->AddData(data, dataSize); 
     219} 
     220 
     221void R5000Device::SetLastChannel(const QString &channel) 
     222{ 
     223    m_buffer_cleared = (channel == m_last_channel); 
     224    m_last_channel   = channel; 
     225 
     226    VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2") 
     227            .arg(channel).arg(m_buffer_cleared ? "yes" : "no")); 
     228} 
     229 
     230void R5000Device::ProcessPATPacket(const TSPacket &tspacket) 
     231{ 
     232    if (!tspacket.TransportError() && !tspacket.ScramplingControl() && 
     233        tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID()) 
     234    { 
     235        PESPacket pes = PESPacket::View(tspacket); 
     236        uint crc = pes.CalcCRC(); 
     237        m_buffer_cleared |= (crc != m_last_crc); 
     238        m_last_crc = crc; 
     239#if 0 
     240        VERBOSE(VB_RECORD, LOC + 
     241                QString("ProcessPATPacket: CRC 0x%1 cleared: %2") 
     242                .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no")); 
     243#endif 
     244    } 
     245    else 
     246    { 
     247        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's"); 
     248    } 
     249} 
     250 
     251QString R5000Device::GetModelName(uint vendor_id, uint model_id) 
     252{ 
     253    QMutexLocker locker(&s_static_lock); 
     254/* 
     255    if (s_id_to_model.empty()) 
     256        fw_init(s_id_to_model); 
     257 
     258    QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id]; 
     259 
     260    if (ret.isEmpty()) 
     261        return "GENERIC"; 
     262*/ 
     263    return "R5000"; 
     264} 
     265 
     266bool R5000Device::IsSTBSupported(const QString &panel_model) 
     267{ 
     268    return true; 
     269} 
     270 
     271bool R5000Device::OpenPort(void) 
     272{ 
     273    VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread"); 
     274    QMutexLocker mlocker(&m_lock); 
     275    VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread -- locked"); 
     276    if (usbdev) 
     277    { 
     278        m_open_port_cnt++; 
     279        return true; 
     280    } 
     281 
     282    if (m_serial.length()) 
     283    { 
     284      VERBOSE(VB_RECORD, LOC + QString("Opening R5000 device type %1 with serial#: "+ m_serial).arg(m_type)); 
     285      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.toAscii()); 
     286    } 
     287    else 
     288    { 
     289      VERBOSE(VB_RECORD, LOC + "Opening R5000 device with unknown serial#"); 
     290      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL); 
     291    } 
     292    if (! usbdev) 
     293    { 
     294        VERBOSE(VB_IMPORTANT, LOC + "Failed to open R5000 device"); 
     295        return false; 
     296    } 
     297 
     298    VERBOSE(VB_RECORD, LOC + "Starting port handler thread"); 
     299    m_priv->run_port_handler = true; 
     300    pthread_create(&m_priv->port_handler_thread, NULL, 
     301                   r5000_device_port_handler_thunk, this); 
     302 
     303    VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to start"); 
     304    while (!m_priv->is_port_handler_running) 
     305    { 
     306        m_lock.unlock(); 
     307        usleep(5000); 
     308        m_lock.lock(); 
     309    } 
     310 
     311    VERBOSE(VB_RECORD, LOC + "Port handler thread started"); 
     312 
     313    m_open_port_cnt++; 
     314 
     315    return true; 
     316} 
     317 
     318bool R5000Device::ClosePort(void) 
     319{ 
     320    VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread"); 
     321    QMutexLocker locker(&m_priv->start_stop_port_handler_lock); 
     322    VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread -- locked"); 
     323 
     324    QMutexLocker mlocker(&m_lock); 
     325 
     326    VERBOSE(VB_RECORD, LOC + "ClosePort()"); 
     327 
     328    if (m_open_port_cnt < 1) 
     329        return false; 
     330 
     331    m_open_port_cnt--; 
     332 
     333    if (m_open_port_cnt != 0) 
     334        return true; 
     335 
     336    if (!usbdev) 
     337        return false; 
     338 
     339    VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to stop"); 
     340    m_priv->run_port_handler = false; 
     341    while (m_priv->is_port_handler_running) 
     342    { 
     343        m_lock.unlock(); 
     344        usleep(5000); 
     345        m_lock.lock(); 
     346    } 
     347    VERBOSE(VB_RECORD, LOC + "Joining port handler thread"); 
     348    pthread_join(m_priv->port_handler_thread, NULL); 
     349 
     350    r5000_close(usbdev); 
     351    usbdev = NULL; 
     352 
     353    return true; 
     354} 
     355 
     356void *r5000_device_port_handler_thunk(void *param) 
     357{ 
     358    R5000Device *mon = (R5000Device*) param; 
     359    mon->RunPortHandler(); 
     360    return NULL; 
     361} 
     362 
     363void R5000Device::RunPortHandler(void) 
     364{ 
     365    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- start"); 
     366    m_lock.lock(); 
     367    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- got first lock"); 
     368    m_priv->is_port_handler_running = true; 
     369    m_lock.unlock(); 
     370 
     371    while (m_priv->run_port_handler) 
     372    { 
     373        if (m_priv->is_streaming) 
     374        { 
     375            // This will timeout after 10ms regardless of data availability 
     376            r5000_loop_iterate(usbdev, 10); 
     377        } 
     378        else 
     379        { 
     380            usleep(10000); 
     381        } 
     382    } 
     383 
     384    m_lock.lock(); 
     385    m_priv->is_port_handler_running = false; 
     386    m_lock.unlock(); 
     387    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- end"); 
     388} 
     389 
     390QStringList R5000Device::GetSTBList(void) 
     391{ 
     392    QStringList STBList; 
     393    int i; 
     394    r5kenum_t r5k_stbs; 
     395    if (! r5k_init) 
     396    { 
     397        r5k_init = r5000_init(r5000_msg); 
     398        if (! r5k_init) 
     399            return STBList; 
     400    } 
     401    if (! r5000_find_stbs(&r5k_stbs)) 
     402        VERBOSE(VB_IMPORTANT, LOC + "Locating R5000 devices failed." 
     403                                    "  This may be a permission problem"); 
     404 
     405    for (i = 0; i < r5k_stbs.count; i++) 
     406        STBList.append((char *)r5k_stbs.serial[i]); 
     407    return STBList; 
     408} 
     409 
     410int R5000Device::GetDeviceType(const QString &r5ktype) 
     411{ 
     412    QString type = r5ktype.toUpper(); 
     413    if (type == "DIRECTV") 
     414    { 
     415        return R5K_STB_DIRECTV; 
     416    } 
     417    else if ("VIP211/VIP622/DISH411" == type || 
     418               "VIP211/VIP422"         == type || 
     419               "VIP211"                == type || 
     420               "VIP411"                == type) 
     421    { 
     422        return R5K_STB_VIP211; 
     423    } 
     424    else if ("STARCHOICE/DSR" == type) 
     425    { 
     426        return R5K_STB_DSR; 
     427    } 
     428    else if ("HDD-200" == type) 
     429    { 
     430        return R5K_STB_HDD; 
     431    } 
     432    else if ("VIP622"  == type || 
     433               "VIP722"  == type || 
     434               "BEV9242" == type) 
     435    { 
     436        return R5K_STB_VIP622; 
     437    } 
     438    else if ("DISH6000" == type) 
     439    { 
     440        return R5K_STB_DISH6000; 
     441    } 
     442    else 
     443    { 
     444      return R5K_STB_VIP211; 
     445    } 
     446} 
  • new file libs/libmythtv/r5000recorder.cpp

    - +  
     1/** 
     2 *  R5000Recorder 
     3 *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams 
     4 *  Distributed as part of MythTV under GPL v2 and later. 
     5 */ 
     6 
     7// MythTV includes 
     8#include "r5000recorder.h" 
     9#include "r5000channel.h" 
     10#include "mythcontext.h" 
     11#include "mpegtables.h" 
     12#include "mpegstreamdata.h" 
     13#include "tv_rec.h" 
     14 
     15#define LOC QString("R5000RecBase(%1): ").arg(channel->GetDevice()) 
     16#define LOC_ERR QString("R5000RecBase(%1), Error: ").arg(channel->GetDevice()) 
     17 
     18R5000Recorder::R5000Recorder(TVRec *rec, R5000Channel *chan) : 
     19    DTVRecorder(rec), _mpeg_stream_data(NULL), 
     20    channel(chan), isopen(false) 
     21{ 
     22    //_wait_for_keyframe_option = false; 
     23} 
     24 
     25R5000Recorder::~R5000Recorder() 
     26{ 
     27    SetStreamData(NULL); 
     28    Close(); 
     29} 
     30 
     31bool R5000Recorder::Open(void) 
     32{ 
     33    if (!isopen) 
     34        isopen = channel->GetR5000Device()->OpenPort(); 
     35 
     36    return isopen; 
     37} 
     38 
     39void R5000Recorder::Close(void) 
     40{ 
     41    if (isopen) 
     42    { 
     43        channel->GetR5000Device()->ClosePort(); 
     44        isopen = false; 
     45    } 
     46} 
     47 
     48void R5000Recorder::StartStreaming(void) 
     49{ 
     50    channel->GetR5000Device()->AddListener(this); 
     51} 
     52 
     53void R5000Recorder::StopStreaming(void) 
     54{ 
     55    channel->GetR5000Device()->RemoveListener(this); 
     56} 
     57 
     58void R5000Recorder::StartRecording(void) 
     59{ 
     60    VERBOSE(VB_RECORD, LOC + "StartRecording"); 
     61 
     62    if (!Open()) 
     63    { 
     64        _error = true; 
     65        return; 
     66    } 
     67 
     68    _request_recording = true; 
     69    _recording = true; 
     70 
     71    StartStreaming(); 
     72 
     73    while (_request_recording) 
     74    { 
     75        if (!PauseAndWait()) 
     76            usleep(50 * 1000); 
     77    } 
     78 
     79    StopStreaming(); 
     80    FinishRecording(); 
     81 
     82    _recording = false; 
     83} 
     84 
     85void R5000Recorder::AddData(const unsigned char *data, uint len) 
     86{ 
     87    uint bufsz = buffer.size(); 
     88    if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) && 
     89        (TSPacket::SIZE > bufsz)) 
     90    { 
     91        if (bufsz) 
     92            buffer.clear(); 
     93 
     94        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data))); 
     95        return; 
     96    } 
     97 
     98    buffer.insert(buffer.end(), data, data + len); 
     99    bufsz += len; 
     100 
     101    int sync_at = -1; 
     102    for (uint i = 0; (i < bufsz) && (sync_at < 0); i++) 
     103    { 
     104        if (buffer[i] == SYNC_BYTE) 
     105            sync_at = i; 
     106    } 
     107 
     108    if (sync_at < 0) 
     109        return; 
     110 
     111    if (bufsz < 30 * TSPacket::SIZE) 
     112        return; // build up a little buffer 
     113 
     114    while (sync_at + TSPacket::SIZE < bufsz) 
     115    { 
     116        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>( 
     117                              &buffer[0] + sync_at))); 
     118 
     119        sync_at += TSPacket::SIZE; 
     120    } 
     121 
     122    buffer.erase(buffer.begin(), buffer.begin() + sync_at); 
     123 
     124    return; 
     125} 
     126 
     127void R5000Recorder::ProcessTSPacket(const TSPacket &tspacket) 
     128{ 
     129    if (tspacket.TransportError()) 
     130        return; 
     131 
     132    if (tspacket.ScramplingControl()) 
     133        return; 
     134 
     135    if (tspacket.HasAdaptationField()) 
     136        GetStreamData()->HandleAdaptationFieldControl(&tspacket); 
     137 
     138    if (tspacket.HasPayload()) 
     139    { 
     140        const unsigned int lpid = tspacket.PID(); 
     141        // Pass or reject packets based on PID, and parse info from them 
     142        if (lpid == GetStreamData()->VideoPIDSingleProgram()) 
     143        { 
     144            ProgramMapTable *pmt = GetStreamData()->PMTSingleProgram(); 
     145            uint video_stream_type = pmt->StreamType(pmt->FindPID(lpid)); 
     146 
     147            if (video_stream_type == StreamID::H264Video) 
     148                _buffer_packets = !FindH264Keyframes(&tspacket); 
     149            else if (StreamID::IsVideo(video_stream_type)) 
     150                _buffer_packets = !FindMPEG2Keyframes(&tspacket); 
     151 
     152            if ((video_stream_type != StreamID::H264Video) || _seen_sps) 
     153                BufferedWrite(tspacket); 
     154        } 
     155        else if (GetStreamData()->IsAudioPID(lpid)) 
     156        { 
     157            _buffer_packets = !FindAudioKeyframes(&tspacket); 
     158            BufferedWrite(tspacket); 
     159        } 
     160        else if (GetStreamData()->IsListeningPID(lpid)) 
     161            GetStreamData()->HandleTSTables(&tspacket); 
     162        else if (GetStreamData()->IsWritingPID(lpid)) 
     163            BufferedWrite(tspacket); 
     164    } 
     165} 
     166 
     167void R5000Recorder::SetOptionsFromProfile(RecordingProfile *profile, 
     168                                                 const QString &videodev, 
     169                                                 const QString &audiodev, 
     170                                                 const QString &vbidev) 
     171{ 
     172    (void)videodev; 
     173    (void)audiodev; 
     174    (void)vbidev; 
     175    (void)profile; 
     176} 
     177 
     178// documented in recorderbase.cpp 
     179bool R5000Recorder::PauseAndWait(int timeout) 
     180{ 
     181    if (request_pause) 
     182    { 
     183        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause"); 
     184        if (!paused) 
     185        { 
     186            StopStreaming(); 
     187            paused = true; 
     188            pauseWait.wakeAll(); 
     189            if (tvrec) 
     190                tvrec->RecorderPaused(); 
     191        } 
     192        QMutex unpause_lock; 
     193        unpause_lock.lock(); 
     194        unpauseWait.wait(&unpause_lock, timeout); 
     195    } 
     196    if (!request_pause && paused) 
     197    { 
     198        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause"); 
     199        StartStreaming(); 
     200        paused = false; 
     201    } 
     202    return paused; 
     203} 
     204 
     205void R5000Recorder::SetStreamData(MPEGStreamData *data) 
     206{ 
     207    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 
     208    if (data == _mpeg_stream_data) 
     209    { 
     210        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 
     211        return; 
     212    } 
     213 
     214    MPEGStreamData *old_data = _mpeg_stream_data; 
     215    _mpeg_stream_data = data; 
     216    if (old_data) 
     217        delete old_data; 
     218 
     219    if (data) 
     220    { 
     221        data->AddMPEGSPListener(this); 
     222 
     223        if (data->DesiredProgram() >= 0) 
     224            data->SetDesiredProgram(data->DesiredProgram()); 
     225    } 
     226    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 
     227} 
     228 
     229void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 
     230{ 
     231    if (!pat) 
     232    { 
     233        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 
     234        return; 
     235    } 
     236    int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 
     237    pat->tsheader()->SetContinuityCounter(next); 
     238    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 
     239} 
     240 
     241void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 
     242{ 
     243    if (!pmt) 
     244    { 
     245        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 
     246        return; 
     247    } 
     248    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 
     249    pmt->tsheader()->SetContinuityCounter(next); 
     250    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 
     251} 
  • new file libs/libmythtv/r5000signalmonitor.cpp

    - +  
     1// -*- Mode: c++ -*- 
     2// Copyright (c) 2006, Daniel Thor Kristjansson 
     3 
     4#include <pthread.h> 
     5#include <fcntl.h> 
     6#include <unistd.h> 
     7#include <sys/select.h> 
     8 
     9#include "mythcontext.h" 
     10#include "mythdbcon.h" 
     11#include "atscstreamdata.h" 
     12#include "mpegtables.h" 
     13#include "atsctables.h" 
     14#include "r5000channel.h" 
     15#include "r5000signalmonitor.h" 
     16 
     17#define LOC QString("R5kSM(%1): ").arg(channel->GetDevice()) 
     18#define LOC_WARN QString("R5kSM(%1), Warning: ").arg(channel->GetDevice()) 
     19#define LOC_ERR QString("R5kSM(%1), Error: ").arg(channel->GetDevice()) 
     20 
     21const uint R5000SignalMonitor::kPowerTimeout  = 3000; /* ms */ 
     22const uint R5000SignalMonitor::kBufferTimeout = 5000; /* ms */ 
     23 
     24QMap<void*,uint> R5000SignalMonitor::pat_keys; 
     25QMutex           R5000SignalMonitor::pat_keys_lock; 
     26 
     27/** \fn R5000SignalMonitor::R5000SignalMonitor(int,R5000Channel*,uint,const char*) 
     28 *  \brief Initializes signal lock and signal values. 
     29 * 
     30 *   Start() must be called to actually begin continuous 
     31 *   signal monitoring. The timeout is set to 3 seconds, 
     32 *   and the signal threshold is initialized to 0%. 
     33 * 
     34 *  \param db_cardnum Recorder number to monitor, 
     35 *                    if this is less than 0, SIGNAL events will not be 
     36 *                    sent to the frontend even if SetNotifyFrontend(true) 
     37 *                    is called. 
     38 *  \param _channel R5000Channel for card 
     39 *  \param _flags   Flags to start with 
     40 *  \param _name    Name for Qt signal debugging 
     41 */ 
     42R5000SignalMonitor::R5000SignalMonitor( 
     43    int db_cardnum, 
     44    R5000Channel *_channel, 
     45    uint64_t _flags, const char *_name) : 
     46    DTVSignalMonitor(db_cardnum, _channel, _flags), 
     47    dtvMonitorRunning(false), 
     48    stb_needs_retune(true), 
     49    stb_needs_to_wait_for_pat(false), 
     50    stb_needs_to_wait_for_power(false) 
     51{ 
     52    VERBOSE(VB_CHANNEL, LOC + "ctor"); 
     53 
     54    signalStrength.SetThreshold(65); 
     55 
     56    AddFlags(kSigMon_WaitForSig); 
     57 
     58    stb_needs_retune = 
     59        (R5000Device::kAVCPowerOff == _channel->GetPowerState()); 
     60} 
     61 
     62/** \fn R5000SignalMonitor::~R5000SignalMonitor() 
     63 *  \brief Stops signal monitoring and table monitoring threads. 
     64 */ 
     65R5000SignalMonitor::~R5000SignalMonitor() 
     66{ 
     67    VERBOSE(VB_CHANNEL, LOC + "dtor"); 
     68    Stop(); 
     69} 
     70 
     71/** \fn R5000SignalMonitor::Stop(void) 
     72 *  \brief Stop signal monitoring and table monitoring threads. 
     73 */ 
     74void R5000SignalMonitor::Stop(void) 
     75{ 
     76    VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 
     77    SignalMonitor::Stop(); 
     78    if (dtvMonitorRunning) 
     79    { 
     80        dtvMonitorRunning = false; 
     81        pthread_join(table_monitor_thread, NULL); 
     82    } 
     83    VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 
     84} 
     85 
     86void R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat) 
     87{ 
     88    AddFlags(kDTVSigMon_PATSeen); 
     89 
     90    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 
     91    bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared(); 
     92    if (crc_bogus && stb_needs_to_wait_for_pat && 
     93        (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) 
     94    { 
     95        VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT"); 
     96        uint tsid = pat->TransportStreamID(); 
     97        GetStreamData()->SetVersionPAT(tsid, -1,0); 
     98        return; 
     99    } 
     100 
     101    if (crc_bogus && stb_needs_to_wait_for_pat) 
     102    { 
     103        VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out"); 
     104        stb_needs_to_wait_for_pat = false; 
     105    } 
     106 
     107    DTVSignalMonitor::HandlePAT(pat); 
     108} 
     109 
     110void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt) 
     111{ 
     112    VERBOSE(VB_CHANNEL, LOC + "HandlePMT()"); 
     113 
     114    AddFlags(kDTVSigMon_PMTSeen); 
     115 
     116    if (!HasFlags(kDTVSigMon_PATMatch)) 
     117    { 
     118        GetStreamData()->SetVersionPMT(pnum, -1,0); 
     119        VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT"); 
     120        return; 
     121    } 
     122 
     123    DTVSignalMonitor::HandlePMT(pnum, pmt); 
     124} 
     125 
     126void *R5000SignalMonitor::TableMonitorThread(void *param) 
     127{ 
     128    R5000SignalMonitor *mon = (R5000SignalMonitor*) param; 
     129    mon->RunTableMonitor(); 
     130    return NULL; 
     131} 
     132 
     133void R5000SignalMonitor::RunTableMonitor(void) 
     134{ 
     135    stb_needs_to_wait_for_pat = true; 
     136    stb_wait_for_pat_timer.start(); 
     137    dtvMonitorRunning = true; 
     138 
     139    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin"); 
     140 
     141    R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel); 
     142    if (!lchan) 
     143    { 
     144        VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end"); 
     145        dtvMonitorRunning = false; 
     146        return; 
     147    } 
     148 
     149    R5000Device *dev = lchan->GetR5000Device(); 
     150 
     151    dev->OpenPort(); 
     152    dev->AddListener(this); 
     153 
     154    while (dtvMonitorRunning && GetStreamData()) 
     155        usleep(100000); 
     156 
     157    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown "); 
     158 
     159    dev->RemoveListener(this); 
     160    dev->ClosePort(); 
     161 
     162    dtvMonitorRunning = false; 
     163 
     164    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 
     165} 
     166 
     167void R5000SignalMonitor::AddData(const unsigned char *data, uint len) 
     168{ 
     169    if (!dtvMonitorRunning) 
     170        return; 
     171 
     172    if (GetStreamData()) 
     173        GetStreamData()->ProcessData((unsigned char *)data, len); 
     174} 
     175 
     176/** \fn R5000SignalMonitor::UpdateValues(void) 
     177 *  \brief Fills in frontend stats and emits status Qt signals. 
     178 * 
     179 *   This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH 
     180 *   FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain 
     181 *   statistics from the frontend. 
     182 * 
     183 *   This is automatically called by MonitorLoop(), after Start() 
     184 *   has been used to start the signal monitoring thread. 
     185 */ 
     186void R5000SignalMonitor::UpdateValues(void) 
     187{ 
     188    if (!running || exit) 
     189        return; 
     190 
     191    if (dtvMonitorRunning) 
     192    { 
     193        EmitStatus(); 
     194        if (IsAllGood()) 
     195            SendMessageAllGood(); 
     196        // TODO dtv signals... 
     197 
     198        update_done = true; 
     199        return; 
     200    } 
     201 
     202    if (stb_needs_to_wait_for_power && 
     203        (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout)) 
     204    { 
     205        return; 
     206    } 
     207    stb_needs_to_wait_for_power = false; 
     208 
     209    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 
     210 
     211    if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch)) 
     212    { 
     213        bool retried = false; 
     214        while (true) 
     215        { 
     216            R5000Device::PowerState power = fwchan->GetPowerState(); 
     217            if (R5000Device::kAVCPowerOn == power) 
     218            { 
     219                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 
     220            } 
     221            else if (R5000Device::kAVCPowerOff == power) 
     222            { 
     223                AddFlags(kFWSigMon_PowerSeen); 
     224                fwchan->SetPowerState(true); 
     225                stb_wait_for_power_timer.start(); 
     226                stb_needs_to_wait_for_power = true; 
     227            } 
     228            else 
     229            { 
     230                bool qfailed = (R5000Device::kAVCPowerQueryFailed == power); 
     231                if (qfailed && !retried) 
     232                { 
     233                    retried = true; 
     234                    continue; 
     235                } 
     236 
     237                VERBOSE(VB_RECORD, "Can't determine if STB is power on, " 
     238                        "assuming it is..."); 
     239                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 
     240            } 
     241            break; 
     242        } 
     243    } 
     244 
     245    bool isLocked = !HasFlags(kFWSigMon_WaitForPower) || 
     246        HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch); 
     247 
     248    if (isLocked && stb_needs_retune) 
     249    { 
     250        fwchan->Retune(); 
     251        isLocked = stb_needs_retune = false; 
     252    } 
     253 
     254    // Set SignalMonitorValues from info from card. 
     255    { 
     256        QMutexLocker locker(&statusLock); 
     257        signalStrength.SetValue(isLocked ? 100 : 0); 
     258        signalLock.SetValue(isLocked ? 1 : 0); 
     259    } 
     260 
     261    EmitStatus(); 
     262    if (IsAllGood()) 
     263        SendMessageAllGood(); 
     264 
     265    // Start table monitoring if we are waiting on any table 
     266    // and we have a lock. 
     267    if (isLocked && GetStreamData() && 
     268        HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 
     269                   kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 
     270                   kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 
     271    { 
     272        pthread_create(&table_monitor_thread, NULL, 
     273                       TableMonitorThread, this); 
     274 
     275        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 
     276                "Waiting for table monitor to start"); 
     277 
     278        while (!dtvMonitorRunning) 
     279            usleep(50); 
     280 
     281        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 
     282                "Table monitor started"); 
     283    } 
     284 
     285    update_done = true; 
     286} 
  • new file libs/libmythtv/r5000channel.h

    - +  
     1/** 
     2 *  R5000Channel 
     3 *  Copyright (c) 2008 by Alan Nisota 
     4 *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams 
     5 *  Distributed as part of MythTV under GPL v2 and later. 
     6 */ 
     7 
     8#ifndef _R5000CHANNEL_H_ 
     9#define _R5000CHANNEL_H_ 
     10 
     11#include "tv_rec.h" 
     12#include "dtvchannel.h" 
     13#include "r5000device.h" 
     14 
     15class R5000Channel : public DTVChannel 
     16{ 
     17  public: 
     18    R5000Channel(TVRec *parent, const QString &videodevice, 
     19                    const QString &_r5ktype, bool pocc); 
     20    ~R5000Channel() { Close(); } 
     21 
     22    // Commands 
     23    virtual bool Open(void); 
     24    virtual void Close(void); 
     25 
     26    virtual bool TuneMultiplex(uint /*mplexid*/, QString /*inputname*/) 
     27        { return false; } 
     28    virtual bool Tune(const DTVMultiplex &/*tuning*/, QString /*inputname*/) 
     29        { return false; } 
     30    virtual bool Retune(void); 
     31 
     32    // Sets 
     33    virtual bool SetChannelByString(const QString &chan); 
     34    virtual bool SetChannelByNumber(const QString &channel, int mpeg_prog); 
     35    virtual bool SetPowerState(bool on); 
     36 
     37    // Gets 
     38    virtual bool IsOpen(void) const { return isopen; } 
     39    virtual R5000Device::PowerState GetPowerState(void) const; 
     40    virtual QString GetDevice(void) const; 
     41    virtual R5000Device *GetR5000Device(void) { return device; } 
     42 
     43  protected: 
     44    QString            videodevice; 
     45    FireWireDBOptions  fw_opts; 
     46    bool               power_on_channel_change; 
     47    R5000Device        *device; 
     48    QString            current_channel; 
     49    uint               current_mpeg_prog; 
     50    bool               isopen; 
     51}; 
     52 
     53#endif // _FIREWIRECHANNEL_H_ 
  • new file libs/libmythtv/r5000device.h

    - +  
     1/** 
     2 *  R5000Device 
     3 *  Copyright (c) 2005 by Jim Westfall 
     4 *  Distributed as part of MythTV under GPL v2 and later. 
     5 */ 
     6 
     7#ifndef _R5000_DEVICE_H_ 
     8#define _R5000_DEVICE_H_ 
     9 
     10// C++ headers 
     11#include <vector> 
     12using namespace std; 
     13 
     14// Qt headers 
     15#include <qstring.h> 
     16#include <qmutex.h> 
     17 
     18// MythTV headers 
     19#include "streamlisteners.h" 
     20 
     21extern "C" { 
     22#include "r5000/r5000.h" 
     23} 
     24 
     25class TSPacket; 
     26class R5kPriv; 
     27class R5000Device 
     28{ 
     29  public: 
     30 
     31    // Public enums 
     32    typedef enum 
     33    { 
     34        kAVCPowerOn, 
     35        kAVCPowerOff, 
     36        kAVCPowerUnknown, 
     37        kAVCPowerQueryFailed, 
     38    } PowerState; 
     39 
     40 
     41    // AVC param 0 
     42    typedef enum 
     43    { 
     44        kAVCPowerStateOn           = 0x70, 
     45        kAVCPowerStateOff          = 0x60, 
     46        kAVCPowerStateQuery        = 0x7f, 
     47    } IEEE1394UnitPowerParam0; 
     48 
     49    R5000Device(int type, QString serial); 
     50    ~R5000Device(); 
     51 
     52    bool OpenPort(void); 
     53    bool ClosePort(void); 
     54    void RunPortHandler(void); 
     55 
     56    // Commands 
     57    virtual bool ResetBus(void) { return false; } 
     58 
     59    virtual void AddListener(TSDataListener*); 
     60    virtual void RemoveListener(TSDataListener*); 
     61 
     62    // Sets 
     63    virtual bool SetPowerState(bool on); 
     64    virtual bool SetChannel(const QString &panel_model, 
     65                            const QString &channel, uint mpeg_prog); 
     66 
     67    // Gets 
     68    bool IsSTBBufferCleared(void) const { return m_buffer_cleared; } 
     69 
     70    // non-const Gets 
     71    virtual PowerState GetPowerState(void); 
     72 
     73    // Statics 
     74    static bool IsSTBSupported(const QString &model); 
     75    static QString GetModelName(uint vendorid, uint modelid); 
     76    static QStringList GetSTBList(void); 
     77    static int GetDeviceType(const QString &r5ktype); 
     78    void BroadcastToListeners( 
     79        const unsigned char *data, uint dataSize); 
     80 
     81  protected: 
     82 
     83    bool GetSubunitInfo(uint8_t table[32]); 
     84 
     85    void SetLastChannel(const QString &channel); 
     86    void ProcessPATPacket(const TSPacket&); 
     87    bool StartStreaming(void); 
     88    bool StopStreaming(void); 
     89 
     90    int                      m_type; 
     91    QString                  m_serial; 
     92    uint                     m_subunitid; 
     93    uint                     m_speed; 
     94    QString                  m_last_channel; 
     95    uint                     m_last_crc; 
     96    bool                     m_buffer_cleared; 
     97 
     98    uint                     m_open_port_cnt; 
     99    vector<TSDataListener*>  m_listeners; 
     100    mutable QMutex           m_lock; 
     101 
     102    /// Vendor ID + Model ID to R5000Device STB model string 
     103    static QMap<uint64_t,QString> s_id_to_model; 
     104    static QMutex                 s_static_lock; 
     105private: 
     106    r5kdev_t                 *usbdev; 
     107    R5kPriv                  *m_priv; 
     108}; 
     109 
     110#endif // _FIREWIRE_DEVICE_H_ 
  • new file libs/libmythtv/r5000recorder.h

    - +  
     1/** 
     2 *  R5000Recorder 
     3 *  Copyright (c) 2005 by Jim Westfall 
     4 *  Distributed as part of MythTV under GPL v2 and later. 
     5 */ 
     6 
     7#ifndef _R5000RECORDER_H_ 
     8#define _R5000RECORDER_H_ 
     9 
     10// MythTV headers 
     11#include "dtvrecorder.h" 
     12#include "tspacket.h" 
     13#include "streamlisteners.h" 
     14 
     15class TVRec; 
     16class R5000Channel; 
     17 
     18/** \class R5000Recorder 
     19 *  \brief This is a specialization of DTVRecorder used to 
     20 *         handle DVB and ATSC streams from a firewire input. 
     21 * 
     22 *  \sa DTVRecorder 
     23 */ 
     24class R5000Recorder : public DTVRecorder, 
     25                         public MPEGSingleProgramStreamListener, 
     26                         public TSDataListener 
     27{ 
     28    friend class MPEGStreamData; 
     29    friend class TSPacketProcessor; 
     30 
     31  public: 
     32    R5000Recorder(TVRec *rec, R5000Channel *chan); 
     33    virtual ~R5000Recorder(); 
     34 
     35    // Commands 
     36    bool Open(void); 
     37    void Close(void); 
     38 
     39    void StartStreaming(void); 
     40    void StopStreaming(void); 
     41 
     42    void StartRecording(void); 
     43    bool PauseAndWait(int timeout = 100); 
     44 
     45    void AddData(const unsigned char *data, uint dataSize); 
     46    void ProcessTSPacket(const TSPacket &tspacket); 
     47 
     48    // Sets 
     49    void SetOptionsFromProfile(RecordingProfile *profile, 
     50                               const QString &videodev, 
     51                               const QString &audiodev, 
     52                               const QString &vbidev); 
     53    void SetStreamData(MPEGStreamData*); 
     54 
     55    // Gets 
     56    MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; } 
     57 
     58    // MPEG Single Program 
     59    void HandleSingleProgramPAT(ProgramAssociationTable*); 
     60    void HandleSingleProgramPMT(ProgramMapTable*); 
     61 
     62  protected: 
     63    R5000Recorder(TVRec *rec); 
     64 
     65  private: 
     66    MPEGStreamData        *_mpeg_stream_data; 
     67    R5000Channel       *channel; 
     68    bool                   isopen; 
     69    vector<unsigned char>  buffer; 
     70}; 
     71 
     72#endif //  _R5000RECORDER_H_ 
  • new file libs/libmythtv/r5000signalmonitor.h

    - +  
     1// -*- Mode: c++ -*- 
     2 
     3#ifndef _R5000SIGNALMONITOR_H_ 
     4#define _R5000SIGNALMONITOR_H_ 
     5 
     6#include <qmap.h> 
     7#include <qmutex.h> 
     8#include <qdatetime.h> 
     9 
     10#include "dtvsignalmonitor.h" 
     11#include "r5000device.h" 
     12#include "util.h" 
     13 
     14class R5000Channel; 
     15 
     16class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener 
     17{ 
     18  public: 
     19    R5000SignalMonitor(int db_cardnum, R5000Channel *_channel, 
     20                          uint64_t _flags = kFWSigMon_WaitForPower, 
     21                          const char *_name = "R5000SignalMonitor"); 
     22 
     23    virtual void HandlePAT(const ProgramAssociationTable*); 
     24    virtual void HandlePMT(uint, const ProgramMapTable*); 
     25 
     26    void Stop(void); 
     27 
     28  protected: 
     29    R5000SignalMonitor(void); 
     30    R5000SignalMonitor(const R5000SignalMonitor&); 
     31    virtual ~R5000SignalMonitor(); 
     32 
     33    virtual void UpdateValues(void); 
     34 
     35    static void *TableMonitorThread(void *param); 
     36    void RunTableMonitor(void); 
     37 
     38    bool SupportsTSMonitoring(void); 
     39 
     40    void AddData(const unsigned char *data, uint dataSize); 
     41 
     42  public: 
     43    static const uint kPowerTimeout; 
     44    static const uint kBufferTimeout; 
     45 
     46  protected: 
     47    bool               dtvMonitorRunning; 
     48    pthread_t          table_monitor_thread; 
     49    bool               stb_needs_retune; 
     50    bool               stb_needs_to_wait_for_pat; 
     51    bool               stb_needs_to_wait_for_power; 
     52    MythTimer          stb_wait_for_pat_timer; 
     53    MythTimer          stb_wait_for_power_timer; 
     54 
     55    vector<unsigned char> buffer; 
     56 
     57    static QMap<void*,uint> pat_keys; 
     58    static QMutex           pat_keys_lock; 
     59}; 
     60 
     61#endif // _R5000SIGNALMONITOR_H_ 
  • new file libs/libmythtv/r5000/libusb_augment.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/ 
     3 * 
     4 * This library is free software; you can redistribute it and/or 
     5 * modify it under the terms of the GNU Lesser General Public 
     6 * License as published by the Free Software Foundation; either 
     7 * version 2.1 of the License, or (at your option) any later version. 
     8 * 
     9 * This library is distributed in the hope that it will be useful, 
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     12 * Lesser General Public License for more details. 
     13 * 
     14 * You should have received a copy of the GNU Lesser General Public 
     15 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     16 */ 
     17 
     18// libusb_augment.c 
     19// $Revision$ 
     20// $Date$ 
     21 
     22// Hopefully, the functions in this file will become part of libusb. 
     23 
     24#include <stdio.h> 
     25#include <sys/ioctl.h> 
     26#include <errno.h> 
     27#include <sys/time.h> 
     28#include <sys/poll.h> 
     29#include <usb.h> 
     30#include <linux/usbdevice_fs.h> 
     31#include <string.h> 
     32#include <signal.h> 
     33#define LIBUSB_AUGMENT 
     34#include "libusb_augment.h" 
     35 
     36// Taken from libusb file usbi.h because usb.h 
     37// hides the definition of usb_dev_handle. 
     38extern int usb_debug; 
     39 
     40struct usb_dev_handle { 
     41  int fd; 
     42 
     43  struct usb_bus *bus; 
     44  struct usb_device *device; 
     45 
     46  int config; 
     47  int interface; 
     48  int altsetting; 
     49 
     50  /* Added by RMT so implementations can store other per-open-device data */ 
     51  void *impl_info; 
     52}; 
     53 
     54// Taken from libusb file error.h to supply error handling macro definition. 
     55typedef enum { 
     56  USB_ERROR_TYPE_NONE = 0, 
     57  USB_ERROR_TYPE_STRING, 
     58  USB_ERROR_TYPE_ERRNO, 
     59} usb_error_type_t; 
     60 
     61extern char usb_error_str[1024]; 
     62extern usb_error_type_t usb_error_type; 
     63 
     64#define USB_ERROR_STR(format, args...) \ 
     65        do { \ 
     66          usb_error_type = USB_ERROR_TYPE_STRING; \ 
     67          snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \ 
     68          if (usb_debug >= 2) \ 
     69            fprintf(stderr, "USB error: %s\n", usb_error_str); \ 
     70        } while (0) 
     71 
     72static int urb_signr = 0; 
     73void (*urb_completion_callback)(struct usbdevfs_urb *) = NULL; 
     74#define USB_ASYNC_COMPLETION_SIGNAL (SIGRTMIN + 5) 
     75 
     76void urb_completion_handler(int signum, siginfo_t *info, void *context) 
     77{ 
     78   struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr; 
     79   struct usbdevfs_urb *context1; 
     80   usb_dev_handle *dev = (usb_dev_handle *)urb->usercontext; 
     81   int ret; 
     82   if (info->si_code != SI_ASYNCIO || 
     83       info->si_signo != USB_ASYNC_COMPLETION_SIGNAL) { 
     84       return; 
     85   } 
     86   if(info->si_errno != 0) { 
     87     USB_ERROR_STR("Async URB Completion failed: %s", strerror(info->si_errno)); 
     88     return; 
     89   } 
     90   ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context1); 
     91   if(ret  < 0) { 
     92     USB_ERROR_STR("Failed to read URB: %s", strerror(-ret)); 
     93     return; 
     94   } 
     95   if(context1 != urb) { 
     96     USB_ERROR_STR("Reaped unexpected urb"); 
     97     return; 
     98   } 
     99   if(urb_completion_callback) 
     100     urb_completion_callback(urb); 
     101} 
     102 
     103int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *)) 
     104{ 
     105  urb_completion_callback = cb; 
     106  urb_signr = USB_ASYNC_COMPLETION_SIGNAL; 
     107  struct sigaction usb_linux_sa; 
     108  usb_linux_sa.sa_sigaction = urb_completion_handler; 
     109  sigfillset(&usb_linux_sa.sa_mask); 
     110  usb_linux_sa.sa_flags = SA_SIGINFO; 
     111  usb_linux_sa.sa_flags |= SA_ONSTACK; 
     112  sigaction(USB_ASYNC_COMPLETION_SIGNAL, &usb_linux_sa, NULL); 
     113  return 0; 
     114} 
     115 
     116struct usbdevfs_urb *usb_bulk_setup( 
     117                struct usbdevfs_urb *iso_urb, // URB pointer-pointer. 
     118                unsigned char ep,  // Device endpoint. 
     119                char *bytes,       // Data buffer pointer. 
     120                int size) {        // Size of the buffer. 
     121  struct usbdevfs_urb *local_urb; 
     122 
     123  // No more than 16384 bytes can be transferred at a time. 
     124  if (size > 16384) { 
     125    USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL)); 
     126    return NULL; 
     127  } 
     128  local_urb = iso_urb; 
     129  if (!local_urb) { 
     130    local_urb = (struct usbdevfs_urb *) calloc(1, sizeof(struct usbdevfs_urb)); 
     131    if (!local_urb) { 
     132      USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 
     133      return NULL; 
     134    } 
     135  } 
     136  local_urb->type = USBDEVFS_URB_TYPE_BULK; 
     137  local_urb->endpoint = ep; 
     138  local_urb->status = 0; 
     139  local_urb->flags = 0; 
     140  local_urb->buffer = bytes; 
     141  local_urb->buffer_length = size; 
     142  local_urb->actual_length = 0; 
     143  local_urb->start_frame = 0; 
     144  local_urb->number_of_packets = 0; 
     145  local_urb->error_count = 0; 
     146  local_urb->signr = urb_signr; 
     147  local_urb->usercontext = (void *) 0; 
     148  return local_urb; 
     149} 
     150// Reading and writing are the same except for the endpoint 
     151struct usbdevfs_urb *usb_isochronous_setup( 
     152                          struct usbdevfs_urb *iso_urb, // URB pointer-pointer. 
     153                          unsigned char ep,  // Device endpoint. 
     154                          int pktsize,       // Endpoint packet size. 
     155                          char *bytes,       // Data buffer pointer. 
     156                          int size) {        // Size of the buffer. 
     157  struct usbdevfs_urb *local_urb; 
     158  // int ret 
     159  // was unused /lindi 
     160  int pktcount, fullpkts, partpktsize, packets, urb_size; 
     161 
     162  // No more than 32768 bytes can be transferred at a time. 
     163  if (size > 32768) { 
     164    USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL)); 
     165    return NULL; 
     166  } 
     167 
     168  // Determine the number of packets that need to be created based upon the 
     169  // amount of data to be transferred, and the maximum packet size of the 
     170  // endpoint. 
     171 
     172  // Find integral number of full packets. 
     173  //fprintf(stderr, "buf size: %d\n", size); 
     174  //fprintf(stderr, "iso size: %d\n", pktsize); 
     175  fullpkts = size / pktsize; 
     176  //fprintf(stderr, "Number of full packets: %d\n", fullpkts); 
     177  // Find length of partial packet. 
     178  partpktsize = size % pktsize; 
     179  //fprintf(stderr, "Size of partial packet: %d\n", partpktsize); 
     180  // Find total number of packets to be transfered. 
     181  packets = fullpkts + ((partpktsize > 0) ? 1 : 0); 
     182  //fprintf(stderr, "Total number of packets: %d\n", packets); 
     183  // Limit the number of packets transfered according to 
     184  // the Linux usbdevfs maximum read/write buffer size. 
     185  if ((packets < 1) || (packets > 128)) { 
     186    USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 
     187    return NULL; 
     188  } 
     189 
     190  // If necessary, allocate the urb and packet 
     191  // descriptor structures from the heap. 
     192  local_urb = iso_urb; 
     193  if (!local_urb) { 
     194    urb_size = sizeof(struct usbdevfs_urb) + 
     195      packets * sizeof(struct usb_iso_packet_desc); 
     196    local_urb = (struct usbdevfs_urb *) calloc(1, urb_size); 
     197    if (!local_urb) { 
     198      USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 
     199      return NULL; 
     200    } 
     201  } 
     202 
     203  // Set up each packet for the data to be transferred. 
     204  for (pktcount = 0; pktcount < fullpkts; pktcount++) { 
     205    local_urb->iso_frame_desc[pktcount].length = pktsize; 
     206    local_urb->iso_frame_desc[pktcount].actual_length = 0; 
     207    local_urb->iso_frame_desc[pktcount].status = 0; 
     208  } 
     209 
     210  // Set up the last packet for the partial data to be transferred. 
     211  if (partpktsize > 0) { 
     212    local_urb->iso_frame_desc[pktcount].length = partpktsize; 
     213    local_urb->iso_frame_desc[pktcount].actual_length = 0; 
     214    local_urb->iso_frame_desc[pktcount++].status = 0; 
     215  } 
     216 
     217  // Set up the URB structure. 
     218  local_urb->type = USBDEVFS_URB_TYPE_ISO; 
     219  //fprintf(stderr, "type: %d\n", local_urb->type); 
     220  local_urb->endpoint = ep; 
     221  //fprintf(stderr, "endpoint: 0x%x\n", local_urb->endpoint); 
     222  local_urb->status = 0; 
     223  local_urb->flags = USBDEVFS_URB_ISO_ASAP; // Additional flags here? 
     224  //fprintf(stderr, "flags: %d\n", local_urb->flags); 
     225  local_urb->buffer = bytes; 
     226  //fprintf(stderr, "buffer: 0x%x\n", local_urb->buffer); 
     227  local_urb->buffer_length = size; 
     228  //fprintf(stderr, "buffer_length: %d\n", local_urb->buffer_length); 
     229  local_urb->actual_length = 0; 
     230  local_urb->start_frame = 0; 
     231  //fprintf(stderr, "start_frame: %d\n", local_urb->start_frame); 
     232  local_urb->number_of_packets = pktcount; 
     233  //fprintf(stderr, "number_of_packets: %d\n", local_urb->number_of_packets); 
     234  local_urb->error_count = 0; 
     235  local_urb->signr = 0; 
     236  //fprintf(stderr, "signr: %d\n", local_urb->signr); 
     237  local_urb->usercontext = (void *) 0; 
     238  return local_urb; 
     239} 
     240 
     241 
     242int usb_urb_submit(usb_dev_handle *dev,     // Open usb device handle. 
     243                   struct usbdevfs_urb *iso_urb,        // Pointer to URB. 
     244                   struct timeval *tv_submit) { // Time structure pointer. 
     245  int ret; 
     246 
     247  iso_urb->usercontext = dev; 
     248  // Get actual time, of the URB submission. 
     249  if(tv_submit) 
     250    gettimeofday(tv_submit, NULL); 
     251  // Submit the URB through an IOCTL call. 
     252  ret = ioctl(dev->fd, USBDEVFS_SUBMITURB, iso_urb); 
     253  //fprintf(stderr, "start_frame now: %d\n", iso_urb->start_frame); 
     254  //fprintf(stderr, "submit ioctl return value: %d\n", ret); 
     255  if (ret < 0) { 
     256    //fprintf(stderr, "error submitting URB: %s\n", strerror(errno)); 
     257    USB_ERROR_STR("error submitting URB: %s", strerror(errno)); 
     258    return -errno; 
     259  } 
     260  return ret; 
     261} 
     262 
     263 
     264int usb_urb_reap(usb_dev_handle *dev,     // Open usb device handle. 
     265                 struct usbdevfs_urb *iso_urb,        // Pointer to URB. 
     266                 int timeout) {           // Attempt timeout (usec). 
     267  void *context = NULL; 
     268  int ret; 
     269  struct pollfd ufd[1]; 
     270 
     271  // Get actual time, and add the timeout value. The result is the absolute 
     272  // time where we have to quit waiting for an isochronous message. 
     273  ufd[0].fd = dev->fd; 
     274  ufd[0].events = POLLIN | POLLOUT; 
     275  ufd[0].revents = 0; 
     276  ret = poll(ufd, 1, timeout); 
     277  if(ret <= 0) 
     278    return -ETIMEDOUT; 
     279 
     280  //fprintf(stderr, "preparing to reap\n"); 
     281  ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context); 
     282 
     283  /* 
     284   * If there was an error, that wasn"t EAGAIN (no completion), then 
     285   * something happened during the reaping and we should return that 
     286   * error now 
     287   */ 
     288  //fprintf(stderr, "reap ioctl return value: %d\n", ret); 
     289  if (ret < 0) { 
     290    USB_ERROR_STR("error reaping interrupt URB: %s", 
     291                  strerror(errno)); 
     292    return -errno; 
     293  } 
     294 
     295  //fprintf(stderr, "actual_length: %d\n", iso_urb->actual_length); 
     296  //fprintf(stderr, "URB status: %d\n", iso_urb->status); 
     297  //fprintf(stderr, "error count: %d\n", iso_urb->error_count); 
     298 
     299  //fprintf(stderr, "waiting done\n"); 
     300  if(context != NULL && iso_urb != context) { 
     301    fprintf(stderr, "Expected urb: %p but got %p\n", iso_urb, context); 
     302    return -1; 
     303  } 
     304  //fprintf(stderr, "Total bytes: %d\n", bytesdone); 
     305  return iso_urb->actual_length; 
     306} 
     307 
     308int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb) 
     309{ 
     310  return ioctl(dev->fd, USBDEVFS_DISCARDURB, iso_urb); 
     311} 
  • new file libs/libmythtv/r5000/libusb_augment.h

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/ 
     3 * 
     4 * This library is free software; you can redistribute it and/or 
     5 * modify it under the terms of the GNU Lesser General Public 
     6 * License as published by the Free Software Foundation; either 
     7 * version 2.1 of the License, or (at your option) any later version. 
     8 * 
     9 * This library is distributed in the hope that it will be useful, 
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     12 * Lesser General Public License for more details. 
     13 * 
     14 * You should have received a copy of the GNU Lesser General Public 
     15 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     16 */ 
     17 
     18#ifdef LIBUSB_AUGMENT 
     19// Taken from libusb file linux.h to provide the URB structure definitions. 
     20struct usb_iso_packet_desc { 
     21  unsigned int length; 
     22  unsigned int actual_length; 
     23  unsigned int status; 
     24}; 
     25#endif 
     26 
     27int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *)); 
     28struct usbdevfs_urb *usb_bulk_setup(struct usbdevfs_urb *iso_urb, unsigned char ep, 
     29                   char *bytes, int size); 
     30struct usbdevfs_urb *usb_isochronous_setup(struct usbdevfs_urb *iso_urb, 
     31                    unsigned char ep, int pktsize, char *bytes, int size); 
     32int usb_urb_submit(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb, 
     33                   struct timeval *tv_rsubmit); 
     34int usb_urb_reap(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb, 
     35                 int timeout_usec); 
     36int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb); 
  • new file libs/libmythtv/r5000/r5000.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17#include <stdio.h> 
     18#include <sys/types.h> 
     19#include <sys/stat.h> 
     20#include <fcntl.h> 
     21#include <string.h> 
     22#include <errno.h> 
     23#include <stdarg.h> 
     24 
     25#ifdef R5K_DEBUG 
     26char strmfile[256] = "/tmp/strm"; 
     27int fd = -1; 
     28#endif 
     29 
     30#ifdef R5K_RAWUSB 
     31int usbfd = -1; 
     32#endif 
     33#include "r5000_internal.h" 
     34#include "r5000init.h" 
     35 
     36#define R5K_WARM_VID 0x0547 
     37#define R5K_WARM_PID 0x1002 
     38 
     39#define MAX_URBS_IN_FLIGHT 128 
     40 
     41#ifndef USE_ISOCHRONOUS 
     42  //BULK 
     43  #define R5K_URB_BUFFER_SIZE (1 << 14) 
     44#else 
     45  //ISOCHRONOUS 
     46  #define LIBUSB_AUGMENT 
     47  #define R5K_URB_BUFFER_SIZE (1 << 15) 
     48#endif 
     49#include "libusb_augment.h" 
     50 
     51static int r5000_usb_init = 0; 
     52static struct { 
     53  unsigned char serial[R5K_MAX_DEVS][8]; 
     54  struct usb_device *dev[R5K_MAX_DEVS]; 
     55  int count; 
     56} r5000_dev_map; 
     57 
     58static void (*msgcb)(char *msg); 
     59 
     60enum { 
     61  R5K_PMT_START = 0x01, 
     62  R5K_PMT_READY = 0x02 
     63}; 
     64 
     65void r5000_print(const char *fmt, ...) 
     66{ 
     67  va_list args; 
     68  char logmsg[1024]; 
     69  va_start(args,fmt); 
     70  vsnprintf(logmsg,sizeof(logmsg),fmt,args); 
     71  va_end(args); 
     72  if(msgcb) { 
     73    //msgcb routine must ensure thread safeness 
     74    msgcb(logmsg); 
     75  } else { 
     76    fprintf(stderr, logmsg); 
     77  } 
     78} 
     79 
     80int r5000_create_urbs(r5kdev_t *r5kdev) 
     81{ 
     82  int i, urbsize; 
     83#ifndef USE_ISOCHRONOUS 
     84  urbsize = sizeof(struct usbdevfs_urb); 
     85#else 
     86  urbsize = sizeof(struct usbdevfs_urb) + sizeof(struct usb_iso_packet_desc) * R5K_URB_BUFFER_SIZE / 1024; 
     87#endif 
     88 
     89  r5kdev->buffer = malloc(R5K_URB_BUFFER_SIZE * MAX_URBS_IN_FLIGHT); 
     90  r5kdev->urbs = (struct usbdevfs_urb **)malloc(sizeof(struct usbdevfs_urb *) * MAX_URBS_IN_FLIGHT); 
     91  r5kdev->urbblk = (void *)malloc(urbsize * MAX_URBS_IN_FLIGHT); 
     92  for(i = 0; i < MAX_URBS_IN_FLIGHT; i++) { 
     93    r5kdev->urbs[i] = (struct usbdevfs_urb *)((unsigned long)r5kdev->urbblk + (urbsize * i)); 
     94#ifndef USE_ISOCHRONOUS 
     95    usb_bulk_setup(r5kdev->urbs[i], 0x82, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE); 
     96#else 
     97    usb_isochronous_setup(r5kdev->urbs[i], 0x82, 1024, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE); 
     98#endif 
     99  } 
     100  r5kdev->nexturb = 0; 
     101  return 1; 
     102} 
     103 
     104int r5000_free_urbs(r5kdev_t *r5kdev) 
     105{ 
     106  free(r5kdev->urbblk); 
     107  free(r5kdev->urbs); 
     108  free(r5kdev->buffer); 
     109  return 0; 
     110} 
     111 
     112usb_dev_handle *r5000_locate_device( 
     113    unsigned short vendor_id, unsigned short product_id, int skip) 
     114{ 
     115  struct usb_bus *bus; 
     116  struct usb_device *dev; 
     117  usb_dev_handle *device_handle = 0; 
     118  usb_find_busses(); 
     119  usb_find_devices(); 
     120 
     121  for (bus = usb_get_busses(); bus && !device_handle; bus = bus->next) 
     122  { 
     123    for (dev = bus->devices; dev && !device_handle; dev = dev->next) 
     124    { 
     125      if (dev->descriptor.idVendor == vendor_id && 
     126          dev->descriptor.idProduct == product_id) 
     127      { 
     128        device_handle = usb_open(dev); 
     129        if(device_handle && skip) { 
     130          usb_close(device_handle); 
     131          device_handle = NULL; 
     132          skip--; 
     133        } 
     134      } 
     135    } 
     136  } 
     137 
     138  if (device_handle) { 
     139    int open_status = usb_set_configuration(device_handle,1); 
     140 
     141    open_status = usb_claim_interface(device_handle,0); 
     142 
     143    open_status = usb_set_altinterface(device_handle,0); 
     144  } 
     145  return (device_handle); 
     146} 
     147 
     148int r5000_dev_init(r5kdev_t *r5kdev) { 
     149  int i, bytes; 
     150  unsigned char *ptr, *serial = r5kdev->serial; 
     151  unsigned char datain[0x80]; 
     152  bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 
     153  for(i = 0; i < R5K_INIT_SERIAL; i++) { 
     154    //PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen); 
     155    if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep); 
     156    usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000); 
     157    if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep); 
     158    bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 
     159    //PRINTHEX("Read:\n", datain, bytes); 
     160    if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) { 
     161      r5000_print("R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes); 
     162      return 0; 
     163    } 
     164  } 
     165 
     166  //last read is serial # 
     167  if (datain[0] != 0x08) { 
     168    r5000_print("R5000 initialization failed reading serial #\n"); 
     169    return 0; 
     170  } 
     171  for(ptr = datain + 6; ptr < datain + 13; ptr++) { 
     172    *serial++ = ( *ptr >= '0' && *ptr <= 'z' ) ? *ptr : '*'; 
     173  } 
     174  *serial = 0; 
     175 
     176  //complete initialization now 
     177  for(; i < R5K_INIT_MAX; i++) { 
     178    //PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen); 
     179    if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep); 
     180    usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000); 
     181    if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep); 
     182    bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 
     183    //PRINTHEX("Read:\n", datain, bytes); 
     184    if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) { 
     185      r5000_print("R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes); 
     186      return 0; 
     187    } 
     188  } 
     189  return 1; 
     190} 
     191 
     192int r5000_start_stream(r5kdev_t *r5kdev) 
     193{ 
     194  unsigned char data[0x80]; 
     195  int bytes; 
     196  int i; 
     197  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 
     198 
     199  if(! r5kdev->urbs) 
     200    r5000_create_urbs(r5kdev); 
     201 
     202  data[0] = 0x30; 
     203  usb_bulk_write(handle, 1, data, 1, 5000); 
     204  bytes = usb_bulk_read(handle, 129, data, 2, 5000); 
     205 
     206  //0x50 sets byte mode.  Use '0x60' to set word mode 
     207  data[0] = r5kdev->read_words ? 0x60: 0x50; 
     208  usb_bulk_write(handle, 1, data, 1, 5000); 
     209 
     210  for(i=0; i < MAX_URBS_IN_FLIGHT; i++) { 
     211    usb_urb_submit(handle, r5kdev->urbs[i], NULL); 
     212  } 
     213  r5kdev->nexturb = 0; 
     214  r5kdev->streaming = 1; 
     215  if(r5kdev->start_stream) 
     216    r5kdev->start_stream(r5kdev); 
     217  return 1; 
     218} 
     219 
     220int r5000_stop_stream(r5kdev_t *r5kdev) 
     221{ 
     222  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 
     223  struct usbdevfs_urb **urbs = r5kdev->urbs; 
     224  int i; 
     225 
     226  if(r5kdev->streaming) { 
     227    for(i=0; i < MAX_URBS_IN_FLIGHT; i++) 
     228      usb_urb_cancel(handle, urbs[i]); 
     229    r5kdev->streaming = 0; 
     230  } 
     231  return 1; 
     232} 
     233 
     234/* r5000_init must be called from a thread-safe context */ 
     235int r5000_init(void (*_msgcb)(char *str)) 
     236{ 
     237  int bus_count, dev_count; 
     238  r5kdev_t r5kd; 
     239  int count = 0; 
     240 
     241  msgcb = _msgcb; 
     242 
     243  if(r5000_usb_init) 
     244    return 1; 
     245  usb_init(); 
     246  bus_count = usb_find_busses(); 
     247  dev_count = usb_find_devices(); 
     248  if(bus_count == 0 || dev_count ==0) { 
     249    r5000_print("R5000 failed to locate any USB devices.  Are you sure you have permissions set properly?\n"); 
     250    return 0; 
     251  } 
     252  while(r5000_dev_map.count < R5K_MAX_DEVS) { 
     253    r5kd.handle = r5000_locate_device(R5K_WARM_VID, R5K_WARM_PID, count); 
     254    if(! r5kd.handle) 
     255      break; 
     256    if (r5000_dev_init(&r5kd)) { 
     257      memcpy(r5000_dev_map.serial[r5000_dev_map.count], r5kd.serial, 8); 
     258      r5000_dev_map.dev[r5000_dev_map.count] = usb_device(r5kd.handle); 
     259      r5000_dev_map.count++; 
     260    } 
     261    count++; 
     262    usb_close(r5kd.handle); 
     263  } 
     264  if(! r5000_dev_map.count) { 
     265    r5000_print("R5000 failed to locate any R5000 devices.  Are you sure you have permissions set properly?\n"); 
     266    return 0; 
     267  } 
     268  r5000_usb_init = 1; 
     269  return 1; 
     270} 
     271 
     272r5kdev_t *r5000_open(r5ktype_t type, 
     273                     unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), 
     274                     void *cb_data, 
     275                     const char *serial) 
     276{ 
     277  r5kdev_t *r5kdev, r5kd; 
     278  int count = 0; 
     279  memset(&r5kd, 0, sizeof(r5kdev_t)); 
     280 
     281  if(! r5000_usb_init) { 
     282    r5000_print("R5000 was not initialized before r5000_open().  Please call r5000_init() first\n"); 
     283    return NULL; 
     284  } 
     285  for(count = 0; count < r5000_dev_map.count; count++) { 
     286    if(! serial || memcmp(r5000_dev_map.serial[count], serial, 8) == 0) { 
     287      r5kd.handle = usb_open(r5000_dev_map.dev[count]); 
     288      if(! r5kd.handle) 
     289        return NULL; 
     290      usb_set_configuration(r5kd.handle,1); 
     291      usb_claim_interface(r5kd.handle,0); 
     292      usb_set_altinterface(r5kd.handle,0); 
     293      if(! r5000_dev_init(&r5kd)) { 
     294        usb_close(r5kd.handle); 
     295        return NULL; 
     296      } 
     297      break; 
     298    } 
     299  } 
     300  if(count == r5000_dev_map.count) { 
     301    //We can't get here unless a serial was specified 
     302    r5000_print("Could not locate R5000 device with serial '%s'\n", serial); 
     303    return NULL; 
     304  } 
     305#ifdef R5K_DEBUG 
     306  printf("Reading stream file: %s\n", strmfile); 
     307  fd = open(strmfile, O_RDONLY); 
     308#endif 
     309#ifdef R5K_RAWUSB 
     310  usbfd = open("raw.av", O_WRONLY | O_CREAT | O_TRUNC, 0666); 
     311#endif 
     312  r5kdev = (r5kdev_t *)malloc(sizeof(r5kdev_t)); 
     313  *r5kdev = r5kd; 
     314  r5kdev->urbs = NULL; 
     315  r5kdev->cb = cb; 
     316  r5kdev->cb_data = cb_data; 
     317  r5kdev->stb_type = type; 
     318  switch(type) { 
     319    case R5K_STB_VIP211: 
     320    case R5K_STB_VIP622: 
     321      vip_init(r5kdev); 
     322      break; 
     323    case R5K_STB_DIRECTV: 
     324    case R5K_STB_DISH6000: 
     325      pes_init(r5kdev); 
     326      break; 
     327    case R5K_STB_DSR: 
     328    case R5K_STB_HDD: 
     329      sat_init(r5kdev); 
     330      break; 
     331    default: 
     332      r5000_print("Unknown STB type %d specified.\n", type); 
     333      r5kdev->stb_type = R5K_STB_VIP211; 
     334      vip_init(r5kdev); 
     335      break; 
     336  } 
     337  return r5kdev; 
     338} 
     339 
     340int r5000_close(r5kdev_t *r5kdev) 
     341{ 
     342  if(! r5kdev) 
     343    return 1; 
     344  if(r5kdev->urbs) { 
     345    if(r5kdev->streaming) 
     346      r5000_stop_stream(r5kdev); 
     347    r5000_free_urbs(r5kdev); 
     348  } 
     349  usb_close(r5kdev->handle); 
     350#ifdef R5K_RAWUSB 
     351  if(usbfd >= 0) close(usbfd); 
     352#endif 
     353  switch(r5kdev->stb_type) { 
     354    case R5K_STB_VIP211: 
     355    case R5K_STB_VIP622: 
     356      vip_free(r5kdev); 
     357      break; 
     358    case R5K_STB_DIRECTV: 
     359    case R5K_STB_DISH6000: 
     360      pes_free(r5kdev); 
     361      break; 
     362    case R5K_STB_DSR: 
     363    case R5K_STB_HDD: 
     364      sat_free(r5kdev); 
     365      break; 
     366  } 
     367  free(r5kdev); 
     368  return 1; 
     369} 
     370 
     371int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec) 
     372{ 
     373  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 
     374  struct usbdevfs_urb **urbs = r5kdev->urbs; 
     375  int len; 
     376  unsigned char *buf; 
     377  if(! r5kdev->streaming) 
     378    return -1; 
     379  len = usb_urb_reap(handle, urbs[r5kdev->nexturb], timeout_usec); 
     380  if(len <= 0) { 
     381    if(len != -ETIMEDOUT) 
     382      r5000_print("(%d) Reap failed at %08x: %s\n", r5kdev->nexturb, r5kdev->bytes_read, strerror(errno)); 
     383    return len; 
     384  } 
     385  buf = r5kdev->buffer + (R5K_URB_BUFFER_SIZE*r5kdev->nexturb); 
     386#ifdef R5K_RAWUSB 
     387  if(usbfd >= 0) write(usbfd, buf, len); 
     388#endif 
     389#ifdef R5K_DEBUG 
     390  if(fd >= 0) { 
     391    int newlen = read(fd, buf, len); 
     392    if(newlen < len) { 
     393      r5000_print("hit end of debug file\n"); 
     394      lseek(fd, 0, SEEK_SET); 
     395      read(fd, buf + newlen, len - newlen); 
     396    } 
     397  } 
     398#endif 
     399  r5kdev->process_block(r5kdev, buf, len); 
     400  r5kdev->bytes_read += len; 
     401  usb_urb_submit(handle, urbs[r5kdev->nexturb], NULL); 
     402  r5kdev->nexturb = (r5kdev->nexturb + 1) % MAX_URBS_IN_FLIGHT; 
     403  return 0; 
     404} 
     405 
     406//use this to read a status frame.  It doesn't do anything special 
     407//but makes it obvious what data is expected 
     408int r5000_read_status(r5kdev_t *r5kdev, unsigned char *buf) 
     409{ 
     410  return usb_bulk_read(r5kdev->handle, 129, buf, 128, 5000); 
     411} 
     412 
     413int r5000_get_power_state(r5kdev_t *r5kdev) 
     414{ 
     415  unsigned char data1[1]  = { 0x30 }; 
     416  unsigned char data2[0x80]; 
     417  int count = 10; 
     418  while(count--) { 
     419    r5000_read_status(r5kdev, data2); 
     420    usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 
     421    usleep(100000); 
     422    if(usb_bulk_read(r5kdev->handle, 1, data2, 2, 5000) == 2 && 
     423       data2[0] == 0x0a && (data2[1] & 0x4e) == 0x4c) { 
     424      // The following boxes are known to be power active low: 
     425      // 4DTV 922, Dish 622/722, Bell 9242, D* 
     426      if(r5kdev->power_active_low) 
     427        return (!(data2[1] == 0x4d)); 
     428      else 
     429        return (!!(data2[1] == 0x4d)); 
     430    } 
     431    usleep(100000); 
     432  } 
     433  r5000_print("R5000 failed to read power state.  Assuming ON state\n"); 
     434  return 1; 
     435} 
     436 
     437int r5000_send_pwr_cmd(r5kdev_t *r5kdev, unsigned char *data) 
     438{ 
     439  unsigned char data1[1]  = { 0x30 }; 
     440  unsigned char data3[0x80]; 
     441  int len; 
     442  usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 
     443  usleep(100000); 
     444  usb_bulk_write(r5kdev->handle, 1, data, r5kdev->button->len, 5000); 
     445  usleep(100000); 
     446  len = usb_bulk_read(r5kdev->handle, 1, data3, 2, 5000); 
     447  usleep(100000); 
     448  return len; 
     449} 
     450 
     451int r5000_wait_pwr(r5kdev_t *r5kdev, int on_off) 
     452{ 
     453  int new_state, count = 20; 
     454  while(count-- && (new_state = r5000_get_power_state(r5kdev)) != on_off) 
     455    usleep(100000); 
     456  //r5000_print("End state: %s\n", !on_off ? "On" : "Off"); 
     457  return new_state; 
     458} 
     459 
     460int r5000_toggle_on_off(r5kdev_t *r5kdev) 
     461{ 
     462  unsigned on_off; 
     463  on_off = r5000_get_power_state(r5kdev); 
     464  if(! r5kdev->button) { 
     465    r5000_print("No button IR commands defined for this device!\n"); 
     466    return on_off; 
     467  } 
     468  //r5000_print("Start state: %s\n", on_off ? "On" : "Off"); 
     469  r5000_send_pwr_cmd(r5kdev, r5kdev->button->power); 
     470  on_off = r5000_wait_pwr(r5kdev, ! on_off); 
     471  //r5000_print("End state: %s\n", on_off ? "On" : "Off"); 
     472  return on_off; 
     473} 
     474 
     475int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on) 
     476{ 
     477  unsigned char *pwr_command; 
     478  int on_off = r5000_get_power_state(r5kdev); 
     479  if(on_off == turn_on) { 
     480    return on_off; 
     481  } 
     482  if(! r5kdev->button) { 
     483    r5000_print("No button IR commands defined for this device!\n"); 
     484    return on_off; 
     485  } 
     486  if(r5kdev->discrete_power) { 
     487    //r5000_print("Using discrete power commands\n"); 
     488    if(turn_on) { 
     489      pwr_command = r5kdev->button->power_on; 
     490    } else { 
     491      pwr_command = r5kdev->button->power_off; 
     492    } 
     493  } else { 
     494    pwr_command = r5kdev->button->power; 
     495  } 
     496  r5000_send_pwr_cmd(r5kdev, pwr_command); 
     497  return r5000_wait_pwr(r5kdev, turn_on); 
     498} 
     499 
     500int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog) 
     501{ 
     502  unsigned char data2[0x80]; 
     503  unsigned char *ptr = NULL; 
     504  const char *p; 
     505  if(! r5kdev) 
     506    return 0; 
     507  if (chan) { 
     508    if(! r5kdev->button) { 
     509      r5000_print("No button IR commands defined for this device!\n"); 
     510    } else { 
     511      r5000_read_status(r5kdev, data2); 
     512      usb_bulk_write(r5kdev->handle, 1, r5kdev->button->clear, r5kdev->button->len, 5000); 
     513      usleep(r5kdev->button->delay); 
     514      for(p = chan; *p; p++) { 
     515        ptr = NULL; 
     516        switch(*p) { 
     517          case '0' : ptr = r5kdev->button->b0; break; 
     518          case '1' : ptr = r5kdev->button->b1; break; 
     519          case '2' : ptr = r5kdev->button->b2; break; 
     520          case '3' : ptr = r5kdev->button->b3; break; 
     521          case '4' : ptr = r5kdev->button->b4; break; 
     522          case '5' : ptr = r5kdev->button->b5; break; 
     523          case '6' : ptr = r5kdev->button->b6; break; 
     524          case '7' : ptr = r5kdev->button->b7; break; 
     525          case '8' : ptr = r5kdev->button->b8; break; 
     526          case '9' : ptr = r5kdev->button->b9; break; 
     527          case 'P' : r5000_power_on_off(r5kdev, 2); break; 
     528        } 
     529        if(ptr) { 
     530          usb_bulk_write(r5kdev->handle, 1, ptr, r5kdev->button->len, 5000); 
     531        } 
     532        usleep(r5kdev->button->delay); 
     533      } 
     534      usb_bulk_write(r5kdev->handle, 1, r5kdev->button->enter, r5kdev->button->len, 5000); 
     535    } 
     536  } 
     537  r5kdev->channel = mpeg_prog; 
     538  if(r5kdev->change_channel) 
     539    r5kdev->change_channel(r5kdev); 
     540  return 1; 
     541} 
     542 
     543int r5000_find_stbs(r5kenum_t *devs) 
     544{ 
     545  devs->count = 0; 
     546  if(! r5000_usb_init) { 
     547    r5000_print("R5000 was not initialized before r5000_find_stbs().  Please call r5000_init() first\n"); 
     548    return 0; 
     549  } 
     550  devs->count = r5000_dev_map.count; 
     551  memcpy(devs->serial, r5000_dev_map.serial, 8 * r5000_dev_map.count); 
     552  return 1; 
     553} 
  • new file libs/libmythtv/r5000/r5000.h

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17#ifndef R5000_H 
     18#define R5000_H 
     19 
     20#ifndef r5kdev_t 
     21#define r5kdev_t void 
     22#endif 
     23 
     24#define R5K_MAX_DEVS 10 
     25typedef struct { 
     26  unsigned char serial[R5K_MAX_DEVS][8]; 
     27  int count; 
     28} r5kenum_t; 
     29 
     30typedef enum { 
     31  R5K_STB_VIP211 = 0, 
     32  R5K_STB_DIRECTV, 
     33  R5K_STB_HDD, 
     34  R5K_STB_DSR, 
     35  R5K_STB_VIP622, 
     36  R5K_STB_DISH6000, 
     37  R5K_STB_MAX, 
     38} r5ktype_t; 
     39 
     40extern int r5000_init(void (*_msgcb)(char *str)); 
     41extern r5kdev_t *r5000_open(r5ktype_t type, unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), void *cb_data, const char *serial); 
     42extern int r5000_close(r5kdev_t *r5kdev); 
     43extern int r5000_start_stream(r5kdev_t *r5kdev); 
     44extern int r5000_stop_stream(r5kdev_t *r5kdev); 
     45extern int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec); 
     46extern int r5000_get_power_state(r5kdev_t *r5kdev); 
     47extern int r5000_toggle_on_off(r5kdev_t *r5kdev); 
     48extern int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on); 
     49extern int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog); 
     50extern int r5000_find_stbs(r5kenum_t *devs); 
     51#endif //R5000_H 
  • new file libs/libmythtv/r5000/r5000_internal.h

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17#ifndef R5000_INT_H 
     18#define R5000_INT_H 
     19 
     20#include <usb.h> 
     21#include <linux/usbdevice_fs.h> 
     22 
     23#define PRINTHEX(str, data, len) if(1) do { \ 
     24  int _i; \ 
     25  fprintf(stderr, str); \ 
     26  for(_i = 0; _i < (len); _i++) { \ 
     27    fprintf(stderr, "%02x ", (data)[_i]); \ 
     28    if((_i % 16) == 15) fprintf(stderr, "\n"); \ 
     29  } \ 
     30  if(_i % 16) fprintf(stderr, "\n"); \ 
     31} while(0) 
     32 
     33#define R5K_MAX_BUTTON_SIZE 0x80 
     34#define R5K_MAX_PIDS 10 
     35#define IS_VIDEO(x) ((x) == 0x02 || (x) == 0x1b || (x) == 0x80) 
     36 
     37struct r5k_descriptor { 
     38  unsigned char d[10]; 
     39}; 
     40 
     41struct r5k_epid { 
     42  int pid; 
     43  unsigned char id; 
     44  struct r5k_descriptor desc; 
     45}; 
     46 
     47struct r5000_buttons { 
     48  int len; 
     49  int delay; 
     50  unsigned char b0[R5K_MAX_BUTTON_SIZE]; 
     51  unsigned char b1[R5K_MAX_BUTTON_SIZE]; 
     52  unsigned char b2[R5K_MAX_BUTTON_SIZE]; 
     53  unsigned char b3[R5K_MAX_BUTTON_SIZE]; 
     54  unsigned char b4[R5K_MAX_BUTTON_SIZE]; 
     55  unsigned char b5[R5K_MAX_BUTTON_SIZE]; 
     56  unsigned char b6[R5K_MAX_BUTTON_SIZE]; 
     57  unsigned char b7[R5K_MAX_BUTTON_SIZE]; 
     58  unsigned char b8[R5K_MAX_BUTTON_SIZE]; 
     59  unsigned char b9[R5K_MAX_BUTTON_SIZE]; 
     60  unsigned char clear[R5K_MAX_BUTTON_SIZE]; 
     61  unsigned char enter[R5K_MAX_BUTTON_SIZE]; 
     62  unsigned char power[R5K_MAX_BUTTON_SIZE]; 
     63  unsigned char power_on[R5K_MAX_BUTTON_SIZE]; 
     64  unsigned char power_off[R5K_MAX_BUTTON_SIZE]; 
     65}; 
     66 
     67struct r5kdev { 
     68  usb_dev_handle *handle; 
     69  unsigned char serial[8]; 
     70  void *urbblk; 
     71  struct usbdevfs_urb **urbs; 
     72  unsigned char *buffer; 
     73  int stb_type; 
     74  int read_words; 
     75  void (*process_block)(struct r5kdev *r5kdev, unsigned char *buf, int len); 
     76  void (*start_stream)(struct r5kdev *r5kdev); 
     77  void (*change_channel)(struct r5kdev *r5kdev); 
     78  void *stbdata; 
     79  unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data); 
     80  void *cb_data; 
     81  int nexturb; 
     82  int streaming; 
     83  int bytes_read; 
     84  struct r5000_buttons *button; 
     85  int power_active_low; 
     86  int discrete_power; 
     87  int channel; 
     88  unsigned char pmt_pkt[188]; 
     89  unsigned char num_pmt_entries; 
     90  unsigned char pmt_state; 
     91  unsigned char pmt_next_cc; 
     92  unsigned char pmt_version; 
     93  struct r5k_epid pmt[R5K_MAX_PIDS]; 
     94} r5kdev_t; 
     95#define r5kdev_t struct r5kdev 
     96 
     97#include "r5000.h" 
     98 
     99extern void r5000_print(const char *fmt, ...); 
     100extern unsigned char r5000_pat_pkt[188]; 
     101extern struct r5k_descriptor r5000_pmt_audio_desc; 
     102extern struct r5k_descriptor r5000_pmt_video_desc; 
     103extern void r5000_reset_pmt(r5kdev_t *r5kdev); 
     104extern void r5000_send_pmt(r5kdev_t *r5kdev); 
     105 
     106//Support for DirecTV and Dish/BEV 6000 boxes 
     107extern void pes_init(r5kdev_t *r5kdev); 
     108extern void pes_free(r5kdev_t *r5kdev); 
     109 
     110//Support for ViP series Dish Network boxes 
     111extern void vip_init(r5kdev_t *r5kdev); 
     112extern void vip_free(r5kdev_t *r5kdev); 
     113 
     114//Support for HDD and DSR series satellite/cable boxes 
     115extern void sat_init(r5kdev_t *r5kdev); 
     116extern void sat_free(r5kdev_t *r5kdev); 
     117 
     118//Buttons 
     119extern struct r5000_buttons vip_button_cmd; 
     120extern struct r5000_buttons directv_button_cmd; 
     121extern struct r5000_buttons dish6000_button_cmd; 
     122#endif 
  • new file libs/libmythtv/r5000/r5k_vip.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17//Support for Dish Network ViP211/ViP422 boxes 
     18#include <stdio.h> 
     19#include <string.h> 
     20#include "r5000_internal.h" 
     21 
     22struct r5000_vip { 
     23  unsigned char leftover[188]; 
     24  int offset; 
     25  int pos; 
     26}; 
     27#define CHECK_CONTINUITY 1 
     28#ifdef CHECK_CONTINUITY 
     29  static unsigned char continuity[0x2000]; 
     30#endif 
     31void vip_add_pmt(r5kdev_t *r5kdev, int pid, int table_id) 
     32{ 
     33  int i; 
     34  struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 
     35 
     36  int is_video = IS_VIDEO(table_id); 
     37 
     38  for(i = 0; i < r5kdev->num_pmt_entries; i++) { 
     39    if(r5kdev->pmt[i].pid == pid) { 
     40      if(r5kdev->pmt[i].id == table_id) 
     41        return; 
     42      //different table_id for existing pid.  Reset 
     43      r5000_reset_pmt(r5kdev); 
     44      break; 
     45    } 
     46    if(is_video) { 
     47      if(IS_VIDEO(r5kdev->pmt[i].id)) { 
     48        //a video entry already exists.  Reset 
     49        r5000_reset_pmt(r5kdev); 
     50        break; 
     51      } 
     52    } 
     53  } 
     54  //Didn't find this PID, add it 
     55  if(i == R5K_MAX_PIDS) 
     56    return; 
     57  r5000_print("Adding %04x: %02x @ %08x\n", pid, table_id, r5kdev->bytes_read + vip->pos); 
     58  r5kdev->pmt[r5kdev->num_pmt_entries].pid = pid; 
     59  r5kdev->pmt[r5kdev->num_pmt_entries].id  = table_id; 
     60  r5kdev->pmt[r5kdev->num_pmt_entries].desc = is_video ? r5000_pmt_video_desc : r5000_pmt_audio_desc; 
     61  r5kdev->num_pmt_entries++; 
     62  r5kdev->pmt_state |= is_video ? 0x01 : 0x02; 
     63} 
     64 
     65void vip_force_pmt(r5kdev_t *r5kdev, unsigned char *buf) 
     66{ 
     67  int stream_id, pid, afc, af_size = 0; 
     68 
     69  pid = ((buf[1] << 8) | buf[2]) & 0x1fff; 
     70  if(pid == 0x1fff) 
     71    return; 
     72#ifdef CHECK_CONTINUITY 
     73  if(pid >= 0x1000) { 
     74    struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 
     75    unsigned char cont = buf[3] & 0x0f; 
     76    if(continuity[pid] != cont && (buf[3] & 0x30) != 0x20) { 
     77      r5000_print("Continuity (0x%04x) %d != %d @%08x\n", 
     78                  pid, cont, continuity[pid], r5kdev->bytes_read + vip->pos); 
     79    } 
     80    continuity[pid] = (cont + 1) & 0x0f; 
     81  } 
     82#endif 
     83  if(pid == 0) { 
     84    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 
     85    if(r5kdev->pmt_state == 0x03) 
     86      r5000_send_pmt(r5kdev); 
     87  } else { 
     88    if(pid != 0x21) 
     89      r5kdev->cb(buf, 188, r5kdev->cb_data); 
     90    //Only interested in PES packets starting in this TS packet 
     91    if (!(buf[1] & 0x40)) 
     92      return; 
     93    afc = (buf[3]>>4) & 0x03; 
     94    if(afc == 0x2) 
     95      return; 
     96    if(afc == 0x3) 
     97      af_size = buf[4]+1; 
     98    if(buf[4+af_size] != 0x00 || buf[5+af_size] != 0x00 || buf[6+af_size] != 0x01) 
     99      return; 
     100    //We have a PES packet 
     101    stream_id = buf[7+af_size]; 
     102    if((stream_id & 0xf0) == 0xe0) { 
     103      //Video stream (we need the adaptation field) 
     104      if(afc != 0x03) 
     105        return; 
     106      if(0) { 
     107        PRINTHEX("data", buf, af_size+8); 
     108      } 
     109      if(buf[5] & 0x02) { 
     110        // Has private data, this is MPEG4 
     111        vip_add_pmt(r5kdev, pid, 0x1b); 
     112      } else if(buf[5] & 0x10) { 
     113        // Has PCR and no private data, this is MPEG2 
     114        vip_add_pmt(r5kdev, pid, 0x02); 
     115      } 
     116    } else if((stream_id & 0xf0) == 0xc0) { 
     117      //Audio stream 
     118      vip_add_pmt(r5kdev, pid, 0x04); 
     119    } else if(stream_id  == 0xbd) { 
     120      //Audio stream 
     121      vip_add_pmt(r5kdev, pid, 0x81); 
     122    } 
     123  } 
     124} 
     125 
     126static void vip_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 
     127{ 
     128  struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 
     129 
     130  int sync = 1; 
     131  if(! r5kdev->streaming) 
     132    return; 
     133  if(len <= 0) 
     134    return; 
     135 
     136  vip->pos = vip->offset; 
     137  while(vip->pos < len) { 
     138      if(buf[vip->pos] != 0x47 || (vip->pos <len-1 && buf[vip->pos+1] == 0xff)) 
     139        goto nosync; 
     140      // If we get here, buf[vip->pos] == 0x47 
     141      if(vip->offset) { 
     142        //previous data exists and is part of a good packet 
     143        memcpy(vip->leftover+188-vip->offset, buf, vip->offset); 
     144        vip_force_pmt(r5kdev, vip->leftover); 
     145        vip->offset = 0; 
     146      } 
     147      if(vip->pos+188 <= len) { 
     148        //at least one full packet is available 
     149        if(vip->pos+188 < len && buf[vip->pos+188] != 0x47) 
     150          goto nosync; 
     151      } else { 
     152        //Out of data, but the partial packet may be ok. 
     153        memcpy(vip->leftover, buf+vip->pos, len-vip->pos); 
     154        vip->offset = 188-(len-vip->pos); 
     155        break; 
     156      } 
     157      //If we get here, we have a good packet 
     158      vip_force_pmt(r5kdev, buf+vip->pos); 
     159      if(! sync) 
     160        r5000_print("(%d) Found sync @ %08x\n", r5kdev->nexturb, r5kdev->bytes_read+vip->pos); 
     161      sync = 1; 
     162      vip->pos+=188; 
     163      continue; 
     164  nosync: 
     165      vip->offset=0; 
     166      if(sync) 
     167        r5000_print("(%d)Lost sync @ %08x\n", r5kdev->nexturb, r5kdev->bytes_read+vip->pos); 
     168      sync = 0; 
     169      vip->pos++; 
     170  } 
     171} 
     172 
     173static void vip_start_stream(r5kdev_t *r5kdev) 
     174{ 
     175  struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 
     176  vip->offset = 0; 
     177} 
     178 
     179static void vip_change_channel(r5kdev_t *r5kdev) 
     180{ 
     181  r5000_reset_pmt(r5kdev); 
     182} 
     183 
     184void vip_init(r5kdev_t *r5kdev) 
     185{ 
     186  struct r5000_vip *vip = (struct r5000_vip *)malloc(sizeof(struct r5000_vip)); 
     187  r5kdev->stbdata = vip; 
     188  r5kdev->process_block = vip_process_block; 
     189  r5kdev->start_stream  = vip_start_stream; 
     190  r5kdev->button = &vip_button_cmd; 
     191  r5kdev->change_channel = &vip_change_channel; 
     192  r5kdev->discrete_power = 1; 
     193  if(r5kdev->stb_type == R5K_STB_VIP622) 
     194    r5kdev->power_active_low = 1; 
     195} 
     196 
     197void vip_free(r5kdev_t *r5kdev) 
     198{ 
     199  free(r5kdev->stbdata); 
     200} 
     201 
  • new file libs/libmythtv/r5000/r5k_misc.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17#include <stdio.h> 
     18#include <string.h> 
     19#include "r5000_internal.h" 
     20 
     21unsigned char r5000_pat_pkt[188] = { 
     220x47, 0x40, 0x00, 0x13, 0x00, 0x00, 0xb0, 0x0d, 0x00, 0x06, 0xc5, 0x00, 0x00, 0x00, 0x01, 0xe0, 
     230x21, 0x19, 0x3a, 0x82, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     240xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     250xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     260xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     270xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     280xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     290xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     300xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     310xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     320xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
     330xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
     34 
     35 
     36struct r5k_descriptor r5000_pmt_audio_desc = {{0x06, 0x0a, 0x04, 0x65, 0x6e, 0x67, 0x00}}; 
     37struct r5k_descriptor r5000_pmt_video_desc = {{0x00}}; 
     38 
     39//taken and adapted from libdtv, (c) Rolf Hakenes 
     40// CRC32 lookup table for polynomial 0x04c11db7 
     41static unsigned int crc_table[256] = { 
     42   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 
     43   0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 
     44   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 
     45   0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 
     46   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 
     47   0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 
     48   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 
     49   0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 
     50   0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 
     51   0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 
     52   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 
     53   0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 
     54   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 
     55   0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 
     56   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 
     57   0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 
     58   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 
     59   0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 
     60   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 
     61   0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 
     62   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 
     63   0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 
     64   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 
     65   0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 
     66   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 
     67   0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 
     68   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 
     69   0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 
     70   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 
     71   0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 
     72   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 
     73   0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 
     74   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 
     75   0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 
     76   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 
     77   0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 
     78   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 
     79   0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 
     80   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 
     81   0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 
     82   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 
     83   0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 
     84   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; 
     85 
     86static void r5000_calc_crc(unsigned char *out, const unsigned char *d, int len) 
     87{ 
     88   register int i; 
     89   unsigned int crc = 0xFFFFFFFF; 
     90   const unsigned char *u=(unsigned char*)d; // Saves '& 0xff' 
     91 
     92   for (i=0; i<len; i++) 
     93      crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)]; 
     94 
     95   *out++ = (crc >> 24) & 0xff; 
     96   *out++ = (crc >> 16) & 0xff; 
     97   *out++ = (crc >> 8) & 0xff; 
     98   *out++ = (crc >> 0) & 0xff; 
     99} 
     100 
     101static void r5000_build_pmt(r5kdev_t *r5kdev) 
     102{ 
     103  int i; 
     104  unsigned char *ptr; 
     105  unsigned char ts[188] = { 
     106  0x47, 0x40, 0x21, 0x10, 
     107  0x00, 0x02, 
     108  0xb0, 0x00,  //length 
     109  0x00, 0x01, 
     110  0xc1,        //version<<1 (5 bits) | current_next 
     111  0x00, 0x00,  //section/last_section 
     112  0xf0, 0x00,  //PCR_PID 
     113  0xf0, 0x00}; //Program Info Length 
     114 
     115  ts[3] = 0x10 | r5kdev->pmt_next_cc; 
     116 
     117  //Change the PMT version every time we rebuild the PMT 
     118  ts[10] |= r5kdev->pmt_version << 1; 
     119  r5kdev->pmt_version = (r5kdev->pmt_version + 1) % 32; 
     120 
     121  r5000_print("Building PMT\n"); 
     122  ptr = ts + 17; 
     123  for(i = 0; i < r5kdev->num_pmt_entries; i++) { 
     124    *ptr++ = r5kdev->pmt[i].id; 
     125    *ptr++ = 0xe0 | (r5kdev->pmt[i].pid>>8); 
     126    *ptr++ = r5kdev->pmt[i].pid & 0xff; 
     127    *ptr++ = 0xf0; 
     128    memcpy(ptr, r5kdev->pmt[i].desc.d, r5kdev->pmt[i].desc.d[0]+1); 
     129    ptr += r5kdev->pmt[i].desc.d[0]+1; 
     130    if(IS_VIDEO(r5kdev->pmt[i].id)) { 
     131      ts[13] = 0xe0 | (r5kdev->pmt[i].pid >> 8); 
     132      ts[14] = r5kdev->pmt[i].pid & 0xff; 
     133    } 
     134  } 
     135  ts[7] = (ptr - ts) - 8/*header*/ + 4/*CRC*/; 
     136  r5000_calc_crc(ptr, ts + 5, (ptr - ts) - 5); 
     137  memset(ptr+4, 0xff, 188 - (ptr + 4 - ts)); 
     138  memcpy(r5kdev->pmt_pkt, ts, 188); 
     139  //PRINTHEX("PMT", r5kdev->pmt_pkt, 188); 
     140} 
     141 
     142void r5000_reset_pmt(r5kdev_t *r5kdev) 
     143{ 
     144  r5kdev->num_pmt_entries = 0; 
     145  r5kdev->pmt_state = 0; 
     146  r5kdev->pmt_pkt[0] = 0; 
     147} 
     148 
     149void r5000_send_pmt(r5kdev_t *r5kdev) 
     150{ 
     151  if(r5kdev->pmt_pkt[0] != 0x47) { 
     152    r5000_build_pmt(r5kdev); 
     153  } 
     154  r5kdev->pmt_pkt[3] = 0x10 | r5kdev->pmt_next_cc; 
     155  r5kdev->pmt_next_cc = (r5kdev->pmt_next_cc + 1) & 0x0f; 
     156  r5kdev->cb(r5kdev->pmt_pkt, 188, r5kdev->cb_data); 
     157} 
  • new file libs/libmythtv/r5000/r5k_sat.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17//Support for Dish Network ViP211/ViP422 boxes 
     18#include <stdio.h> 
     19#include <string.h> 
     20#include "r5000_internal.h" 
     21 
     22#define DTV_PAT_PMT_COUNT 5000 
     23#define MAX_PKT_SIZE 272 
     24#define MAX_PAT_SECTIONS 1 
     25#define MAX_SIDS 200 
     26#define MAX_EPIDS 5 
     27 
     28struct pat { 
     29  int version; 
     30  unsigned char last_section; 
     31  unsigned char section_seen[MAX_PAT_SECTIONS]; 
     32  unsigned int crc[MAX_PAT_SECTIONS]; 
     33  unsigned int pmts[MAX_SIDS]; 
     34  int pmt_count; 
     35}; 
     36 
     37struct sids { 
     38  unsigned short sid; 
     39  unsigned int crc; 
     40  unsigned char seen_name; 
     41  struct r5k_epid epid[MAX_EPIDS]; 
     42  unsigned char epid_count; 
     43}; 
     44 
     45struct r5000_sat { 
     46  unsigned char buf[MAX_PKT_SIZE]; 
     47  unsigned int pos; 
     48  int offset; 
     49  unsigned char sync; 
     50  unsigned char bytesize; 
     51  unsigned char sync_byte; 
     52  unsigned int has_sync_byte; 
     53  unsigned int pat_pmt_count; 
     54  unsigned int packet_size; 
     55  unsigned int allowed_packet_size[8]; 
     56 
     57  unsigned int current_sid; 
     58  struct pat pats; 
     59  struct sids *sids; 
     60}; 
     61 
     62static int sat_read_pat_pkt(unsigned char *pes, struct pat *pat, unsigned int size) { 
     63  unsigned int sec, end, crc, current_next; 
     64  int version; 
     65  unsigned char *ptr, last_sec; 
     66 
     67  if (pes[0] != 0x00) { 
     68    r5000_print("read_pat: expected PAT table 0x00 but got 0x%02x\n", pes[0]); 
     69    return -1; 
     70  } 
     71  end = (((pes[1] & 0x03) << 8 | pes[2]) + 3 - 4); 
     72  if(end > size-4) { 
     73    r5000_print("read_pat: invalid PAT table size (%d > %d)\n", end, size-4); 
     74    return -1; 
     75  } 
     76  crc = (pes[end]<<24) | (pes[end+1]<<16) | (pes[end+2]<<8) | pes[end+3]; 
     77  version = (pes[5] >> 1) & 0x1f; 
     78  current_next = pes[5] & 0x01; 
     79  sec = pes[6]; 
     80  last_sec = pes[7]; 
     81  if(! current_next) 
     82    //ignore inactive PAT 
     83    return 0; 
     84  if(last_sec >= MAX_PAT_SECTIONS) { 
     85    r5000_print("read_pat: illegal section count %d > %d\n", 
     86             last_sec, MAX_PAT_SECTIONS); 
     87    return -1; 
     88  } 
     89  if (pat->version != version || last_sec != pat->last_section || 
     90      pat->crc[sec] != crc) { 
     91    pat->version = version; 
     92    pat->last_section = last_sec; 
     93    pat->pmt_count = 0; 
     94    memset(pat->section_seen, 0, sizeof(pat->section_seen)); 
     95  } 
     96  if(pat->section_seen[sec]) 
     97    return 0; 
     98  pat->crc[sec] = crc; 
     99  pat->section_seen[sec] = 1; 
     100  for(ptr = pes + 8; ptr < pes + end; ptr += 4) { 
     101    int sid, pid; 
     102    sid = (ptr[0] << 8) | ptr[1]; 
     103    pid = ((ptr[2] & 0x1F) << 8) | ptr[3]; 
     104    r5000_print("found PID: %04x for sid: %d\n", pid, sid); 
     105    if(sid != 0) { 
     106      pat->pmts[pat->pmt_count++] = (sid << 16) | pid; 
     107    } 
     108  } 
     109  return 1; 
     110} 
     111 
     112static struct sids *sat_read_pmt_pkt(unsigned char *buf, struct sids *sids, 
     113                                     unsigned int size) { 
     114  // 
     115  // NOTE we aren't using last_sec here yet! 
     116  // 
     117 
     118  struct sids *sidptr = sids; 
     119  unsigned int count, skip, pos, crc, current_next; 
     120  int sid, sec, last_sec, pcrpid, epid, type; 
     121  if (buf[0] != 0x02) { 
     122    r5000_print("read_pmt expected table 0x02 but got 0x%02x\n", buf[0]); 
     123    return NULL; 
     124  } 
     125  count = (((buf[1] & 0x03) << 8) | buf[2]) + 3 - 4; 
     126  sid = (buf[3] << 8) | buf[4]; 
     127  current_next = buf[5] & 0x01; 
     128  crc = (buf[count]<<24) | (buf[count+1]<<16) | (buf[count+2]<<8) | buf[count+3]; 
     129  sec = buf[6]; 
     130  last_sec = buf[7]; 
     131  pcrpid = ((buf[8] & 0x1F) << 8) | buf[9]; 
     132  skip = ((buf[10] & 0x03) << 8) | buf[11]; 
     133  if(skip > count - 12 || count > size) { 
     134    r5000_print("skip: %d > count: %d - 12 || count > size: %d\n", 
     135           skip, count, size); 
     136    return NULL; 
     137  } 
     138  if(! current_next) { 
     139    r5000_print("read_pmt ignoring future PMT\n"); 
     140    return NULL; 
     141  } 
     142  while(sidptr->sid != 0) { 
     143    if(sidptr->sid == sid) 
     144      break; 
     145    sidptr++; 
     146  } 
     147  if(sidptr->sid == 0) { 
     148    // We weren't expecting this sid 
     149    r5000_print("read_pmt found unexpected sid: %d\n", sidptr->sid); 
     150    return sidptr; 
     151  } 
     152  if(sidptr->crc == crc) { 
     153    //sid is unchanged 
     154    //r5000_print("read_pmt found identical crc (%08x) for %d\n", crc, sidptr->sid); 
     155    return NULL; 
     156  } 
     157  memset(sidptr, 0, sizeof(struct sids)); 
     158 
     159  r5000_print("read_pmt: sid: %d pcrpid: %d skip: %d count: %d\n", sid, pcrpid, skip, count); 
     160  sidptr->sid = sid; 
     161  sidptr->crc = crc; 
     162  sidptr->epid_count = 0; 
     163  for(pos = 12 + skip; pos < count;) { 
     164    struct r5k_epid *pidptr = &sidptr->epid[sidptr->epid_count]; 
     165    type = buf[pos]; 
     166    epid = ((buf[pos+1] & 0x1F) << 8) | buf[pos+2]; 
     167    skip = ((buf[pos+3] & 0x03) << 8) | buf[pos+4]; 
     168    pidptr->pid = epid; 
     169    pidptr->id  = type == 0x80 ? 0x02 : type; 
     170    memcpy(pidptr->desc.d, buf + pos + 4, skip + 1); 
     171    sidptr->epid_count++; 
     172    r5000_print("read_pmt: epid %04x (type %02x, skip=%d) mapped to sid %d\n", epid, type, skip, sid); 
     173    pos += 5 + skip; 
     174  } 
     175  return sidptr; 
     176} 
     177 
     178void sat_find_chname(unsigned char *buf, struct sids *sids, unsigned int size) { 
     179  struct sids *sidptr = sids; 
     180  unsigned int count; 
     181  int sid; 
     182  char str[20], *strptr = str; 
     183  while(size) { 
     184    count = (((buf[1] & 0x03) << 8) | buf[2]) + 3; 
     185    if(buf[0] == 0x41) { 
     186      buf += count; 
     187      size -= count; 
     188      continue; 
     189    } 
     190    if(buf[0] == 0xc1) { 
     191      unsigned char *ptr = buf+16; 
     192      sid = (buf[7]<<8) | buf[8]; 
     193      while(sidptr->sid != 0) { 
     194        if(sidptr->sid == sid) 
     195          break; 
     196        sidptr++; 
     197      } 
     198      if(sidptr->sid == 0) { 
     199        // We weren't expecting this sid 
     200        return; 
     201      } 
     202      if(sidptr->seen_name) 
     203        return; 
     204      sidptr->seen_name = 1; 
     205      while(*ptr >= 0x20 && *ptr < 0x7b && strptr-str < sizeof(str)-1) { 
     206        *strptr++ = *ptr++; 
     207      } 
     208      *strptr = 0; 
     209      r5000_print("sid: %d is channel %s\n", sid, str); 
     210      return; 
     211    } 
     212    return; 
     213  } 
     214} 
     215 
     216int sat_add_pmt(r5kdev_t *r5kdev, struct r5k_epid *epid) 
     217{ 
     218  int i; 
     219  int is_video = IS_VIDEO(epid->id); 
     220 
     221  for(i = 0; i < r5kdev->num_pmt_entries; i++) { 
     222    if(r5kdev->pmt[i].pid == epid->pid) { 
     223      if(r5kdev->pmt[i].id == epid->id) 
     224        return 0; 
     225      //different table_id for existing pid.  Reset 
     226      r5000_reset_pmt(r5kdev); 
     227      break; 
     228    } 
     229    if(is_video) { 
     230      if(IS_VIDEO(r5kdev->pmt[i].id)) { 
     231        //a video entry already exists.  Reset 
     232        r5000_reset_pmt(r5kdev); 
     233        break; 
     234      } 
     235    } 
     236  } 
     237  //Didn't find this PID, add it 
     238  if(i == R5K_MAX_PIDS) 
     239    return 0; 
     240  r5000_print("Adding %04x: %02x (desc_len=%d) @ %08x\n", epid->pid, epid->id, epid->desc.d[0], r5kdev->bytes_read); 
     241  r5kdev->pmt[r5kdev->num_pmt_entries++] = *epid; 
     242  r5kdev->pmt_state |= is_video ? 0x01 : 0x02; 
     243  return 1; 
     244} 
     245 
     246void sat_process_ts(r5kdev_t *r5kdev, unsigned char *buf) 
     247{ 
     248  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 
     249  int pid; 
     250  int i, j, k; 
     251  pid = ((buf[1] << 8) | buf[2]) & 0x1fff; 
     252  if(pid == 0x1fff) 
     253    return; 
     254  if(pid == 0 && (buf[1] & 0x40)) { 
     255    //Always read PAT in case we changed transponders 
     256    if(sat_read_pat_pkt(buf+buf[4]+5, &sat->pats, 188-buf[4]-5) > 0) { 
     257      r5000_print("Found new PAT\n"); 
     258      if(sat->pats.pmt_count) { 
     259        sat->sids = realloc(sat->sids, sizeof(struct sids)*(sat->pats.pmt_count+1)); 
     260        memset(sat->sids, 0, sizeof(struct sids)*(sat->pats.pmt_count+1)); 
     261        //Pre load sids so we don't overrun if the PMT changes before the PAT 
     262        for(i = 0; i < sat->pats.pmt_count; i++) { 
     263          sat->sids[i].sid = sat->pats.pmts[i]>>16; 
     264        } 
     265        sat->sids[i].sid = 0; 
     266        r5000_reset_pmt(r5kdev); 
     267      } 
     268    } else if(r5kdev->pmt_state == 0x03) { 
     269      r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 
     270      r5000_send_pmt(r5kdev); 
     271      sat->pat_pmt_count = 0; 
     272    } 
     273    return; 
     274  } 
     275  //Always reread PMT in case the pids have changed 
     276  for(i = 0; i < sat->pats.pmt_count; i++) { 
     277    if(pid == (unsigned short)(sat->pats.pmts[i])) { 
     278#if 0 
     279    { 
     280      char s[80]; 
     281      FILE *fh; 
     282      sprintf(s, "0x%04x.ts", pid); 
     283      fh= fopen(s, "a"); 
     284      fwrite(buf, 188, 1, fh); 
     285      fclose(fh); 
     286    } 
     287#endif 
     288      //r5000_print("PID: %04x - %04x (%d) %02x %02x %02x %02x %02x\n", pid, (unsigned short)(sat->pats.pmts[i]), i, buf[1], buf[2], buf[3], buf[4], buf[5]); 
     289      if(buf[1] & 0x40 && buf[4]+5 < 188) { 
     290        if(buf[buf[4]+5] == 0x02) { 
     291          struct sids *sidptr; 
     292          if((sidptr = sat_read_pmt_pkt(buf+buf[4]+5, sat->sids, 188-buf[4]-5))) { 
     293            if(sidptr->sid == 0) { 
     294              //Unexpected sid, reset PAT; 
     295              memset(&sat->pats, 0, sizeof(struct pat)); 
     296            } else if(sat->current_sid == sidptr->sid) { 
     297              r5000_reset_pmt(r5kdev); 
     298              sat->current_sid = 0; 
     299            } 
     300          } 
     301        //} else if(buf[buf[4]+5] == 0xc1 || buf[buf[4]+5] == 0x41) { 
     302        //  sat_find_chname(buf+buf[4]+5, sat->sids, 188-buf[4]-5); 
     303        } 
     304      } 
     305      return; 
     306    } 
     307    if(! sat->current_sid) { 
     308      for(j = 0; j < sat->sids[i].epid_count; j++) { 
     309        if(pid == sat->sids[i].epid[j].pid && 
     310           IS_VIDEO(sat->sids[i].epid[j].id) && 
     311           (!r5kdev->channel || r5kdev->channel == sat->sids[i].sid)) { 
     312          //Found unencrypted video.  Choose this one 
     313          // Assume this is MPEG2.  Don't know what MPEG4 looks like yet 
     314          sat->current_sid = sat->sids[i].sid; 
     315          r5000_print("Found decrypted sid %d\n", sat->current_sid); 
     316          if (sat_add_pmt(r5kdev, &sat->sids[i].epid[j])) { 
     317            //This is a new Video PID 
     318            for(k = 0; k < sat->sids[i].epid_count; k++) { 
     319              if(sat->sids[i].epid[k].id == 0x81 || 
     320                 sat->sids[i].epid[k].id == 0xbd) { 
     321                sat_add_pmt(r5kdev, &sat->sids[i].epid[k]); 
     322              } 
     323            } 
     324            r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 
     325            r5000_send_pmt(r5kdev); 
     326            sat->pat_pmt_count = 0; 
     327          } 
     328          r5kdev->cb(sat->buf, 188, r5kdev->cb_data); 
     329          return; 
     330        } 
     331      } 
     332    } 
     333  } 
     334  for(i = 0; i < r5kdev->num_pmt_entries; i++) { 
     335    if(pid == r5kdev->pmt[i].pid) { 
     336      r5kdev->cb(sat->buf, 188, r5kdev->cb_data); 
     337      sat->pat_pmt_count++; 
     338      return; 
     339    } 
     340  } 
     341#if 0 
     342  //r5000_print("Ignoring PID: %04x\n", pid); 
     343  { 
     344    char s[80]; 
     345    FILE *fh; 
     346    sprintf(s, "0x%04x.ts", pid); 
     347    fh= fopen(s, "a"); 
     348    fwrite(buf, 188, 1, fh); 
     349    fclose(fh); 
     350  } 
     351#endif 
     352} 
     353 
     354static void sat_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 
     355{ 
     356  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 
     357 
     358  int pos; 
     359  if(! r5kdev->streaming) 
     360    return; 
     361  if(len <= 0) 
     362    return; 
     363 
     364  for(pos = sat->offset; pos < len; pos += sat->bytesize) { 
     365    if(! sat->sync) { 
     366      if(buf[pos] == 0x47) { 
     367        int i; 
     368        if (pos + (sat->allowed_packet_size[0]<<1) < len) { 
     369          if((buf[pos+1] & 0xfc) == 0xfc && (buf[pos+3] & 0xfc) == 0xfc && 
     370             (buf[pos+5] & 0xfc) == 0xfc && (buf[pos+7] & 0xfc) == 0xfc) { 
     371             sat->bytesize = 2; 
     372          } 
     373          for(i=0; sat->allowed_packet_size[i] != 0; i++) { 
     374            if(buf[pos+(sat->allowed_packet_size[i] * sat->bytesize)] == 0x47) { 
     375              r5000_print("(%d) Found %d byte sync at %08x: bytesize = %d\n", 
     376                    r5kdev->nexturb, sat->allowed_packet_size[i], 
     377                    r5kdev->bytes_read+pos, sat->bytesize); 
     378              sat->packet_size = sat->allowed_packet_size[i]; 
     379              sat->sync = 1; 
     380              sat->buf[0] = 0x47; 
     381              sat->pos = 1; 
     382              break; 
     383            } 
     384          } 
     385        } 
     386      } 
     387      continue; 
     388    } 
     389    if (sat->pos == 0 && buf[pos] != 0x47) { 
     390      sat->sync = 0; 
     391      sat->bytesize = 1; 
     392      r5000_print("(%d)Lost sync at %08x\n", r5kdev->nexturb, 
     393             r5kdev->bytes_read+pos); 
     394      continue; 
     395    } 
     396    if(sat->pos == 3 && (buf[pos] & 0xc0) != 0x00) { 
     397      // Encrypted channel, skip this packet 
     398      sat->pos = 0; 
     399      pos += sat->bytesize * (sat->packet_size - 4); //Loop adds additional 2 
     400      continue; 
     401    } 
     402    sat->buf[sat->pos++] = buf[pos]; 
     403    if (sat->pos == sat->packet_size) { 
     404      sat_process_ts(r5kdev, sat->buf); 
     405      //if packet size > 188, assume remaining bytes are parity and ignore 
     406      sat->pos = 0; 
     407    } 
     408  } 
     409  sat->offset = pos - len; 
     410  if(r5kdev->pmt_state == 0x03 && sat->pat_pmt_count > DTV_PAT_PMT_COUNT) { 
     411    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 
     412    r5000_send_pmt(r5kdev); 
     413    sat->pat_pmt_count = 0; 
     414  } 
     415} 
     416 
     417static void sat_start_stream(r5kdev_t *r5kdev) 
     418{ 
     419  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 
     420  sat->offset = 0; 
     421  sat->sync = 0; 
     422  sat->pos = 0; 
     423  sat->bytesize = 1; 
     424 
     425  //Clear any defined PAT or PMT data 
     426  if(sat->sids) { 
     427    free(sat->sids); 
     428    sat->sids = 0; 
     429  } 
     430  memset(&sat->pats, 0, sizeof(struct pat)); 
     431  sat->pat_pmt_count = DTV_PAT_PMT_COUNT; 
     432} 
     433 
     434static void sat_change_channel(r5kdev_t *r5kdev) 
     435{ 
     436  r5000_reset_pmt(r5kdev); 
     437} 
     438 
     439void sat_init(r5kdev_t *r5kdev) 
     440{ 
     441  struct r5000_sat *sat = 
     442                   (struct r5000_sat *)calloc(1, sizeof(struct r5000_sat)); 
     443  r5kdev->stbdata = sat; 
     444  sat->pat_pmt_count = DTV_PAT_PMT_COUNT; 
     445  if(r5kdev->stb_type == R5K_STB_HDD) { 
     446    sat->sync_byte = 0xff; 
     447    sat->has_sync_byte = 1; 
     448    sat->allowed_packet_size[0] = 272; 
     449    sat->allowed_packet_size[1] = 233; 
     450    sat->allowed_packet_size[2] = 204; 
     451    sat->allowed_packet_size[3] = 188; 
     452    sat->allowed_packet_size[4] = 0; 
     453  } else { 
     454    sat->allowed_packet_size[0] = 188; 
     455    sat->allowed_packet_size[1] = 0; 
     456  } 
     457  r5kdev->process_block = sat_process_block; 
     458  r5kdev->start_stream  = sat_start_stream; 
     459  r5kdev->change_channel = &sat_change_channel; 
     460} 
     461 
     462void sat_free(r5kdev_t *r5kdev) 
     463{ 
     464  struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 
     465  if(sat->sids) 
     466    free(sat->sids); 
     467  free(r5kdev->stbdata); 
     468} 
     469 
  • new file libs/libmythtv/r5000/r5000init.h

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17#ifndef R5000_INIT_H 
     18#define R5000_INIT_H 
     19 
     20#define R5K_INIT_MAX 9 
     21#define R5K_INIT_SERIAL 8 
     22#define R5K_DEFAULT_SLEEP 100000 
     23struct { 
     24  int rsleep; 
     25  int rlen; 
     26  int wsleep; 
     27  int wlen; 
     28  unsigned char data[0x40]; 
     29} r5kinit[R5K_INIT_MAX] = { 
     30// 0 
     31{R5K_DEFAULT_SLEEP, -1, 0, 64, 
     32    {0x30}}, 
     33// 1 
     34{R5K_DEFAULT_SLEEP, 1, 0, 64, 
     35    {0x08, 0x00, 0x20, 0x00, 0x00, 0x3a, 0xd4, 0x29, 0x7c, 0x56, 0x31, 0x44, 0x86, 0x6d, 0x0d, 0x0d, 
     36     0x1b, 0x0a, 0xad, 0x0f, 0xd0, 0x2e, 0x94, 0x3f, 0xd4, 0x08, 0xa2, 0x4b, 0x68, 0x14, 0x1f, 0x13, 
     37     0x04, 0x62, 0x1b, 0x14, 0xb9, 0x69, 0xcc, 0x25, 0x91, 0x06, 0xc9, 0x26, 0xf9, 0x41, 0x64, 0x46, 
     38     0x7d, 0x17, 0x61, 0x09, 0x5c, 0x5b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 
     39// 2 
     40{R5K_DEFAULT_SLEEP, 1, 0, 64, 
     41    {0x08, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     42     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     43     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     44     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 
     45// 3 
     46{R5K_DEFAULT_SLEEP, 1, 0, 64, 
     47    {0x08, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     48     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     49     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     50     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 
     51// 4 
     52{R5K_DEFAULT_SLEEP, 1, R5K_DEFAULT_SLEEP, 64, 
     53    {0x08, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     54     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     55     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     56     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 
     57// 5 
     58{R5K_DEFAULT_SLEEP, 26, 0, 6, 
     59    {0x08, 0x01, 0x00, 0x00, 0x01, 0x14}}, 
     60// 6 
     61{R5K_DEFAULT_SLEEP, 1, 0, 64, 
     62    {0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     63     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     65     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 
     66// 7 
     67{R5K_DEFAULT_SLEEP, 22, 0, 64, 
     68    {0x08, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     69     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     70     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     71     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 
     72// 8 
     73{R5K_DEFAULT_SLEEP, 4, 0, 1, 
     74    {0x20}} 
     75}; 
     76 
     77#endif 
  • new file contrib/r5000/ehci-2.6.25.patch

    - +  
     1--- a/drivers/usb/host/ehci-q.c 2007-06-11 11:37:06.000000000 -0700 
     2+++ b/drivers/usb/host/ehci-q.c 2008-02-05 19:46:08.000000000 -0800 
     3@@ -751,7 +751,7 @@ 
     4                        info2 |= (EHCI_TUNE_MULT_HS << 30); 
     5                } else if (type == PIPE_BULK) { 
     6                        info1 |= (EHCI_TUNE_RL_HS << 28); 
     7-                       info1 |= 512 << 16;     /* usb2 fixed maxpacket */ 
     8+                       info1 |= ((maxp == 1024) ? 1024 : 512) << 16;   /* usb2 fixed maxpacket */ 
     9                        info2 |= (EHCI_TUNE_MULT_HS << 30); 
     10                } else {                /* PIPE_INTERRUPT */ 
     11                        info1 |= max_packet (maxp) << 16; 
  • new file contrib/r5000/r5000.hex

    - +  
     1:10000000020BBEAAAAAAAAAAAAAAAA020EFBAAAA76 
     2:10001000AAAAAA020E76AAAAAAAAAA0208B8AAAAF4 
     3:10002000AAAAAAAAAAAAAAAAAAAAAA020B31AAAAF0 
     4:10003000AAAAAA020FDEAAAAAAAAAAAAAAAAAAAA2F 
     5:10004000AAAAAA020800AAAAAAAAAA02069DAAAA5D 
     6:10005000AAAAAA020800AAAAAAAAAAAAAAAAAAAAF4 
     7:10006000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF0 
     8:10007000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE0 
     9:1000800090E6B9E0700302015B14700302020424DD 
     10:10009000FE700302029924FB7003020155147003E1 
     11:1000A00002014F147003020143147003020149243A 
     12:1000B000056003020305120FE6400302031190E6F8 
     13:1000C000BBE024FE602C14604724FD6016146031F0 
     14:1000D00024067065E52490E6B3F0E52590E6B4F0DB 
     15:1000E000020311E52C90E6B3F0E52D90E6B4F002A2 
     16:1000F0000311E52690E6B3F0E52790E6B4F002039D 
     17:1001000011E52890E6B3F0E52990E6B4F00203117A 
     18:1001100090E6BAE0FF120ECFAA06A9077B01EA49D2 
     19:10012000600DEE90E6B3F0EF90E6B4F002031190AC 
     20:10013000E6A0E04401F002031190E6A0E04401F0E3 
     21:10014000020311120FA7020311120FD6020311129C 
     22:100150000FCE020311120F95020311120FE8400394 
     23:1001600002031190E6B8E0247F602B14603C240267 
     24:1001700060030201FAA200E433FF25E0FFA204E4D9 
     25:10018000334F90E740F0E4A3F090E68AF090E68BDE 
     26:100190007402F0020311E490E740F0A3F090E68AC5 
     27:1001A000F090E68B7402F002031190E6BCE0547EFE 
     28:1001B000FF7E00E0D3948040067C007D0180047CBB 
     29:1001C000007D00EC4EFEED4F24C4F582740F3EF529 
     30:1001D00083E493FF3395E0FEEF24A1FFEE34E68F36 
     31:1001E00082F583E0540190E740F0E4A3F090E68AC2 
     32:1001F000F090E68B7402F002031190E6A0E0440157 
     33:10020000F0020311120FEA400302031190E6B8E076 
     34:1002100024FE601D2402600302031190E6BAE0B4DC 
     35:100220000105C20002031190E6A0E04401F00203C0 
     36:100230001190E6BAE0705990E6BCE0547EFF7E0073 
     37:10024000E0D3948040067C007D0180047C007D002A 
     38:10025000EC4EFEED4F24C4F582740F3EF583E4931B 
     39:10026000FF3395E0FEEF24A1FFEE34E68F82F583A5 
     40:10027000E054FEF090E6BCE05480FF131313541FCB 
     41:10028000FFE0540F2F90E683F0E04420F0020311CA 
     42:1002900090E6A0E04401F08078120FEC507390E6F5 
     43:1002A000B8E024FE60202402706790E6BAE0B40152 
     44:1002B00004D200805C90E6BAE06402605490E6A04C 
     45:1002C000E04401F0804B90E6BCE0547EFF7E00E00D 
     46:1002D000D3948040067C007D0180047C007D00EC8E 
     47:1002E0004EFEED4F24C4F582740F3EF583E493FF78 
     48:1002F0003395E0FEEF24A1FFEE34E68F82F583E034 
     49:100300004401F0800C120FEE500790E6A0E044018B 
     50:10031000F090E6A0E04480F022E4F517F516F5151C 
     51:10032000F514C205C200C204C201120A9D7E0A7FF2 
     52:10033000008E248F25752C0A752D1275220A7523BF 
     53:100340001C752A0A752B43752F0A753071EE54E01F 
     54:10035000700302045D7518007519808E1A8F1BC317 
     55:10036000749B9FFF740A9ECF2402CF3400FEE48F5B 
     56:10037000138E12F511F510F50FF50EF50DF50CAF06 
     57:1003800013AE12AD11AC10AB0FAA0EA90DA80CC381 
     58:10039000120E105026E519250FF582E518350EF5D9 
     59:1003A0008374CDF0E50F2401F50FE4350EF50EE46E 
     60:1003B000350DF50DE4350CF50C80C4E4F50FF50EA4 
     61:1003C000F50DF50CAF13AE12AD11AC10AB0FAA0EBC 
     62:1003D000A90DA80CC3120E105031AE0EAF0FE51BC5 
     63:1003E0002FF582E51A3EF583E0FDE5192FF582E54C 
     64:1003F000183EF583EDF0EF2401F50FE43EF50EE431 
     65:10040000350DF50DE4350CF50C80B98518248519EA 
     66:100410002574002480FF740A34FFFEC3E52D9FF588 
     67:100420002DE52C9EF52CC3E5279FF527E5269EF5A7 
     68:1004300026C3E5299FF529E5289EF528C3E5239FD6 
     69:10044000F523E5229EF522C3E52B9FF52BE52A9E99 
     70:10045000F52AC3E5309FF530E52F9EF52FD2E8430E 
     71:10046000D82090E668E04409F0E04402F090E65EAF 
     72:10047000E0440CF043E80443E80290E6507404F0D2 
     73:10048000000000E4F5B290E67AF043B288F58043CC 
     74:10049000A82E438804438910758B6F758DFE90E6F6 
     75:1004A0008F04F075AF07759DE1E4F59E90E65CE082 
     76:1004B000443DF0D2AF90E680E020E105D207120E75 
     77:1004C0004790E680E04408F00000000000000000D3 
     78:1004D00000E054F7F0538EF8C20530010512008099 
     79:1004E000C201300529120FE25024C2051207DB2099 
     80:1004F000001690E682E030E704E020E1EF90E6822B 
     81:10050000E030E604E020E0E4120EA3120FE4120F44 
     82:10051000F080C7C0E0C0F0C083C082C0D075D000FA 
     83:10052000C000C001C002C003C004C005C006C007AF 
     84:10053000759AE7759B80759DE130060302061A7572 
     85:100540000A00750B0090E67BE0FF7432250BF8A6DD 
     86:1005500007050BE50B7002050AE59B2480C3940692 
     87:1005600040E3E532120E2105F900058908059F10C8 
     88:1005700005DF2005B93005D240061250060A600595 
     89:10058000DACC05CCFF0000061A159B5391EF90E6DC 
     90:100590005F7408F090E68DE4F0120D670206827435 
     91:1005A000FD259BF59B5391EF90E65F7408F090E674 
     92:1005B0008DE4F0120D6702068290E7C0740AF0A382 
     93:1005C000E580F090E68F7402F00206745380F70223 
     94:1005D000067490E68F7401F08040753900803B907E 
     95:1005E000E7C074DDF0A37431F0A3742EF0A3743669 
     96:1005F000F090E68F7404F0807B53A8F785368A75F7 
     97:10060000CDFE75CC6F759E00801090E618740DF0CD 
     98:10061000806290E618740CF0805A90E67BE090E6D9 
     99:100620007CF0E59B2480FF90E68DE0FEEFC39E40CA 
     100:10063000E9E53324FEFFE59EC39F5006E4F0D206B1 
     101:100640008032C206759DE1759E00438902758E0059 
     102:10065000858A8C75C800E5367006E53542808005D0 
     103:10066000E535F4528043800890E67CE0F538438815 
     104:100670001043C8045391EF90E65F7408F090E68D44 
     105:10068000E4F0D007D006D005D004D003D002D001CA 
     106:10069000D000D0D0D082D083D0F0D0E032C0E0C043 
     107:1006A00083C082C0D075D000C000C004C005C006A1 
     108:1006B000C0075391DF90E678E05404FF7E003002DB 
     109:1006C0000BE0F430E1067C007D0180047C007D00BD 
     110:1006D000EC4EFEED4F4E6008E4FF12096F0207C8B2 
     111:1006E000E53224F860030207C8E53314604904606A 
     112:1006F000030207C8E59B2480FFBF050B059B90E61E 
     113:1007000079E534F00207C8E5372406FFE433FEAD8F 
     114:100710009BED2480FDE434FFFCC3ED9FEE6480F884 
     115:10072000EC648098500B90E67BE090E679F002074D 
     116:10073000C81209660207C8E536701CE59B2480C311 
     117:100740009406500B059B90E679E534F00207C875D6 
     118:100750003601120D67807130020F90E679E075085E 
     119:1007600000F509C202059B805FE5372406FFE433EC 
     120:10077000FEAD9BED2480FDE434FFFCC3ED9FEE64F1 
     121:1007800080F8EC648098503DE5372405FFE59B2414 
     122:1007900080B5071490E678E04440F090E679E09068 
     123:1007A000E67BF07F0112096FE5372404FFE59B2407 
     124:1007B00080B5070790E678E04420F090E679E09075 
     125:1007C000E67BF08003120966D007D006D005D0047E 
     126:1007D000D000D0D0D082D083D0E03290E682E04406 
     127:1007E000C0F090E681F04387010000000000227411 
     128:1007F00000F58690FDA57C05A3E582458370F9226E 
     129:10080000020F3900020F7F00020F6900020F510032 
     130:10081000020DA200020DD900020FF100020FF2003A 
     131:10082000020FF300020FF400020C4A00020513004D 
     132:10083000020FF500020FF600020FF700020FF8009A 
     133:10084000020FF900020FF200020FFA00020FFB0084 
     134:10085000020FFC00020FFD00020FFE00020FFF005E 
     135:1008600002100000020FF200020FF200020FF2006D 
     136:100870000210010002100200021003000210040026 
     137:10088000020F1C00021005000210060002100700F3 
     138:10089000021008000210090002100A0002100B00EA 
     139:1008A00002100C0002100D0002100E0002100F00CA 
     140:1008B0000210100002101100C0E0C083C082C0D03E 
     141:1008C0005388BF758B6F758DFEE59EC3947A507209 
     142:1008D000300313E58020E10E43800890E67CE53884 
     143:1008E000F0753800C203200313E58030E10E538019 
     144:1008F000F790E67CE538F0753800D203E538F470FF 
     145:100900003AE59EC3947A503390E67CE538F075382A 
     146:1009100000E4F00521E52194004020E59E94185064 
     147:100920001A759E00752100753800B2035388BF7593 
     148:100930003D0090E65EE04404F080224388400538A4 
     149:10094000801B53A8F75388F75388BF753800C2033C 
     150:10095000752100753D0290E65EE04404F0D0D0D0F1 
     151:1009600082D083D0E03290E678E04440F07F01EF1F 
     152:1009700014603E0460030209FF90E7C074FFF0A317 
     153:10098000E59BF090E678E090E7C2F090E678E0F43E 
     154:1009900030E604E04440F0E490E679F00000000026 
     155:1009A000000090E678E090E7C3F090E68F7405F0E1 
     156:1009B00022E533700D90E7C07410F090E68F74015B 
     157:1009C000F022759B80759DE7759EC090E67BE09058 
     158:1009D000E67CF0E5372406FFE433FEAD9BED248092 
     159:1009E000FDE434FFFCC3ED9FEE6480F8EC64809876 
     160:1009F00040D9E537240690E68FF05380F7D20222E3 
     161:100A00001201000200000040470502100000010230 
     162:100A100000010A0600020000004001000902270050 
     163:100A2000010100A0320904000003FF0000000705D7 
     164:100A30000102400000070581024000000705820214 
     165:100A400000040009022E00010100A0320904000088 
     166:100A500004FF000000070502024000000705040231 
     167:100A6000400000070586024000000705880240009C 
     168:100A7000000403090410034E00650078007400634D 
     169:100A8000006F006D001603480044002D0055005310 
     170:100A90000042002000440056005200000090E60B87 
     171:100AA0007403F000000090E6047480F0000000740D 
     172:100AB00002F000000014F0000000E4F000000090DC 
     173:100AC000E6007412F090E6017443F090E61074A012 
     174:100AD000F090E68D7401F090E61174A0F090E618A5 
     175:100AE000740DF090E6137420F090E614F090E61583 
     176:100AF000F090E61274E8F0E490E602F00000009056 
     177:100B0000E603F090E670F090E609F000000090E651 
     178:100B1000207404F0000000E490E621F00000009052 
     179:100B2000E630749AF0000000E490E631F000000036 
     180:100B300022C0E0C083C082C0D053C8FBE538D39444 
     181:100B400000400D75CDFE75CC6F153843C80480622A 
     182:100B5000E59EC39533502790E67CE0F538E5883074 
     183:100B6000E40AE535F452805388EF8007E53542808A 
     184:100B700043881075CDFE75CC6F43C8048034759ED4 
     185:100B800000E537B47719753700759DE1059E753816 
     186:100B90000075CDFE75CC6F43881043C80480135395 
     187:100BA00088EF53C8FB90E68DE4F0E535F4528043BE 
     188:100BB000A80853C87FD0D0D082D083D0E032787FCD 
     189:100BC000E4F6D8FD75813D020C05020319E493A3F8 
     190:100BD000F8E493A34003F68001F208DFF48029E4EF 
     191:100BE00093A3F85407240CC8C333C4540F4420C83B 
     192:100BF000834004F456800146F6DFE4800B010204D2 
     193:100C00000810204080900FB9E47E019360BCA3FFE0 
     194:100C1000543F30E509541FFEE493A360010ECF5406 
     195:100C2000C025E060A840B8E493A3FAE493A3F8E4F5 
     196:100C300093A3C8C582C8CAC583CAF0A3C8C582C861 
     197:100C4000CAC583CADFE9DEE780BEC0E0C0F0C0836A 
     198:100C5000C082C0D075D000C000C001C002C003C0B7 
     199:100C600004C005C006C00790E65F7404F05391EF1E 
     200:100C7000300605120CBF802CE53D7005F59E43A89B 
     201:100C800008438008E53D6401601AE53DB4020512A1 
     202:100C90000CBF801090E7C074CCF0A3E539F090E66B 
     203:100CA0008F7440F0D007D006D005D004D003D00216 
     204:100CB000D001D000D0D0D082D083D0F0D0E0327537 
     205:100CC0009AE720062AE490E7C0F0A3E59EF0A3741B 
     206:100CD000A0F0A37402F0A37497F0E4A3F0759BC690 
     207:100CE000F59E90E7C1E0D3943A400CD20680087597 
     208:100CF0009BC0C206759E3A90E7C1E0FF90E67CE09B 
     209:100D000090E67BF0AE9BEEC3748094815006E59E26 
     210:100D1000C39F40E890E68F7440F05380F7E4F53DC0 
     211:100D2000228E1C8F1D90E600E054187012E51D24E1 
     212:100D300001FFE4351CC313F51CEF13F51D8015905E 
     213:100D4000E600E05418FFBF100BE51D25E0F51DE59A 
     214:100D50001C33F51CE51D151DAE1C7002151C4E60E4 
     215:100D6000051207EF80EE2290E678E0F430E62DE001 
     216:100D70004480F0E53224F0601C24087024E533B48C 
     217:100D8000010CE536B4010790E67974A1F02290E6F3 
     218:100D90007974A0F02290E679E534F022E4FF12099C 
     219:100DA0006F22C0E0C083C08290E680E030E70E850D 
     220:100DB0002226852327852A28852B29800C852A260B 
     221:100DC000852B278522288523295391EF90E65D7492 
     222:100DD00010F0D082D083D0E032C0E0C083C08290D7 
     223:100DE000E680E030E70E852226852327852A2885A0 
     224:100DF0002B29800C852A26852B27852228852329C7 
     225:100E00005391EF90E65D7420F0D082D083D0E03231 
     226:100E1000EB9FF5F0EA9E42F0E99D42F0E89C45F038 
     227:100E200022D083D082F8E4937012740193700DA3E2 
     228:100E3000A393F8740193F5828883E4737402936832 
     229:100E400060EFA3A3A380DF30070990E680E0440AA7 
     230:100E5000F0800790E680E04408F07FDC7E05120D0C 
     231:100E60002190E65D74FFF090E65FF05391EF90E61D 
     232:100E700080E054F7F022C0E0C083C082C0D0E59E7D 
     233:100E8000C3947A501543884043800890E68FE4F07D 
     234:100E900090E65EE054FBF0753D01D0D0D082D08367 
     235:100EA000D0E03290E682E030E004E020E60B90E60D 
     236:100EB00082E030E119E030E71590E680E04401F08F 
     237:100EC0007F147E00120D2190E680E054FEF022A9EE 
     238:100ED00007AE2FAF308F828E83A3E064037017AD0F 
     239:100EE0000119ED7001228F828E83E07C002FFDECD2 
     240:100EF0003EFEAF0580DF7E007F0022C0E0C0D0E56F 
     241:100F000036D394004011E58055356007E535F4523D 
     242:100F1000808004E5354280D0D0D0E032C0E0C0838C 
     243:100F2000C0825380F77539015391BF90E651E05468 
     244:100F3000FEF0D082D083D0E032C0E0C083C082D245 
     245:100F4000015391EF90E65D7401F0D082D083D0E040 
     246:100F500032C0E0C083C082D2055391EF90E65D7449 
     247:100F600008F0D082D083D0E032C0E0C083C082538A 
     248:100F700091EF90E65D7404F0D082D083D0E032C06F 
     249:100F8000E0C083C0825391EF90E65D7402F0D0829E 
     250:100F9000D083D0E03290E740E53CF0E490E68AF080 
     251:100FA00090E68B04F0D32290E740E531F0E490E640 
     252:100FB0008AF090E68B04F0D322C182013D00C10685 
     253:100FC000013900000001020203030404050590E654 
     254:100FD000BAE0F53CD32290E6BAE0F531D32253D8FB 
     255:100FE000EF32D322D322D322D322D322D322D3222D 
     256:100FF00022323232323232323232323232323232E1 
     257:1010000032323232323232323232323232323232C0 
     258:101010003232AAAAAAAAAAAAAAAAAAAAAAAAAAAA20 
     259:10102000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA20 
     260:10103000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA10 
     261:10104000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00 
     262:10105000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF0 
     263:10106000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE0 
     264:10107000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0 
     265:10108000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0 
     266:10109000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0 
     267:1010A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0 
     268:1010B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA90 
     269:1010C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA80 
     270:1010D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA70 
     271:1010E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA60 
     272:1010F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA50 
     273:10110000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3F 
     274:10111000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2F 
     275:10112000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1F 
     276:10113000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0F 
     277:10114000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFF 
     278:10115000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEF 
     279:10116000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADF 
     280:10117000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACF 
     281:10118000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF 
     282:10119000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF 
     283:1011A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9F 
     284:1011B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8F 
     285:1011C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7F 
     286:1011D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6F 
     287:1011E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5F 
     288:1011F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4F 
     289:10120000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3E 
     290:10121000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2E 
     291:10122000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1E 
     292:10123000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0E 
     293:10124000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFE 
     294:10125000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE 
     295:10126000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADE 
     296:10127000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACE 
     297:10128000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE 
     298:10129000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE 
     299:1012A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9E 
     300:1012B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8E 
     301:1012C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7E 
     302:1012D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6E 
     303:1012E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5E 
     304:1012F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4E 
     305:10130000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3D 
     306:10131000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2D 
     307:10132000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1D 
     308:10133000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0D 
     309:10134000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFD 
     310:10135000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED 
     311:10136000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADD 
     312:10137000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD 
     313:10138000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABD 
     314:10139000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD 
     315:1013A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9D 
     316:1013B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D 
     317:1013C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7D 
     318:1013D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6D 
     319:1013E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5D 
     320:1013F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D 
     321:10140000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3C 
     322:10141000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2C 
     323:10142000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1C 
     324:10143000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0C 
     325:10144000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC 
     326:10145000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEC 
     327:10146000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADC 
     328:10147000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACC 
     329:10148000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC 
     330:10149000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC 
     331:1014A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9C 
     332:1014B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8C 
     333:1014C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7C 
     334:1014D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6C 
     335:1014E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5C 
     336:1014F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4C 
     337:10150000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3B 
     338:10151000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2B 
     339:10152000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1B 
     340:10153000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0B 
     341:10154000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFB 
     342:10155000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB 
     343:10156000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADB 
     344:10157000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACB 
     345:10158000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABB 
     346:10159000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB 
     347:1015A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9B 
     348:1015B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8B 
     349:1015C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7B 
     350:1015D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6B 
     351:1015E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5B 
     352:1015F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4B 
     353:10160000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3A 
     354:10161000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2A 
     355:10162000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1A 
     356:10163000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0A 
     357:10164000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFA 
     358:10165000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA 
     359:10166000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA 
     360:10167000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA 
     361:10168000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA 
     362:10169000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
     363:1016A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9A 
     364:1016B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8A 
     365:1016C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A 
     366:1016D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6A 
     367:1016E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5A 
     368:1016F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4A 
     369:10170000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA39 
     370:10171000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29 
     371:10172000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA19 
     372:10173000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA09 
     373:10174000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF9 
     374:10175000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9 
     375:10176000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD9 
     376:10177000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9 
     377:10178000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9 
     378:10179000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9 
     379:1017A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA99 
     380:1017B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA89 
     381:1017C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA79 
     382:1017D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA69 
     383:1017E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA59 
     384:1017F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA49 
     385:10180000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA38 
     386:10181000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA28 
     387:10182000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA18 
     388:10183000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA08 
     389:10184000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8 
     390:10185000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE8 
     391:10186000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8 
     392:10187000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 
     393:10188000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8 
     394:10189000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8 
     395:1018A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA98 
     396:1018B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA88 
     397:1018C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA78 
     398:1018D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68 
     399:1018E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA58 
     400:1018F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA48 
     401:10190000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA37 
     402:10191000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA27 
     403:10192000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA17 
     404:10193000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA07 
     405:10194000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF7 
     406:10195000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE7 
     407:10196000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7 
     408:10197000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7 
     409:10198000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7 
     410:10199000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7 
     411:1019A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA97 
     412:1019B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA87 
     413:1019C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA77 
     414:1019D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA67 
     415:1019E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA57 
     416:1019F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA47 
     417:101A0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA36 
     418:101A1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA26 
     419:101A2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA16 
     420:101A3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA06 
     421:101A4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6 
     422:101A5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE6 
     423:101A6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6 
     424:101A7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6 
     425:101A8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6 
     426:101A9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6 
     427:101AA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA96 
     428:101AB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA86 
     429:101AC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76 
     430:101AD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA66 
     431:101AE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA56 
     432:101AF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA46 
     433:101B0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA35 
     434:101B1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA25 
     435:101B2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA15 
     436:101B3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA05 
     437:101B4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5 
     438:101B5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5 
     439:101B6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5 
     440:101B7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC5 
     441:101B8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5 
     442:101B9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5 
     443:101BA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA95 
     444:101BB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA85 
     445:101BC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA75 
     446:101BD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA65 
     447:101BE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA55 
     448:101BF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA45 
     449:101C0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA34 
     450:101C1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA24 
     451:101C2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA14 
     452:101C3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA04 
     453:101C4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF4 
     454:101C5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE4 
     455:101C6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4 
     456:101C7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4 
     457:101C8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4 
     458:101C9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4 
     459:101CA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA94 
     460:101CB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA84 
     461:101CC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA74 
     462:101CD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA64 
     463:101CE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA54 
     464:101CF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA44 
     465:101D0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA33 
     466:101D1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA23 
     467:101D2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA13 
     468:101D3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA03 
     469:101D4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3 
     470:101D5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE3 
     471:101D6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3 
     472:101D7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC3 
     473:101D8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3 
     474:101D9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3 
     475:101DA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA93 
     476:101DB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA83 
     477:101DC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA73 
     478:101DD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA63 
     479:101DE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA53 
     480:101DF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA43 
     481:101E0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA32 
     482:101E1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA22 
     483:101E2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA12 
     484:101E3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA02 
     485:101E4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF2 
     486:101E5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE2 
     487:101E6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2 
     488:101E7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2 
     489:101E8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2 
     490:101E9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2 
     491:101EA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92 
     492:101EB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA82 
     493:101EC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA72 
     494:101ED000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA62 
     495:101EE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA52 
     496:101EF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA42 
     497:101F0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA31 
     498:101F1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA21 
     499:101F2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA11 
     500:101F3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA01 
     501:101F4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1 
     502:101F5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE1 
     503:101F6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1 
     504:101F7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1 
     505:101F8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1 
     506:101F9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1 
     507:101FA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA91 
     508:101FB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA81 
     509:101FC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA71 
     510:101FD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA61 
     511:101FE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA51 
     512:101FF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA41 
  • new file contrib/r5000/r5ktest.c

    - +  
     1/* Copyright 2007  Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This program is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU General Public License as 
     5 * published by the Free Software Foundation; either version 2 of 
     6 * the License, or (at your option) any later version. 
     7 * 
     8 * This program is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     11 * GNU General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU General Public License 
     14 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17#include <stdlib.h> 
     18#include <stdio.h> 
     19#include <sys/types.h> 
     20#include <sys/stat.h> 
     21#include <fcntl.h> 
     22#include <string.h> 
     23#include <getopt.h> 
     24#include "r5000/r5000.h" 
     25 
     26enum { 
     27  TOGGLE_POWER, 
     28  CHANGE_CHANNEL, 
     29  READ_STREAM, 
     30  MULTI_READ, 
     31  MULTI_OPEN, 
     32  OPEN_CLOSE, 
     33  SCAN_DEVICES, 
     34  TURN_ON, 
     35  TURN_OFF, 
     36  CHECK_POWER, 
     37  MAX_CMD, 
     38}; 
     39char cmd_names[][20] = { 
     40  {"TOGGLE_POWER"}, 
     41  {"CHANGE_CHANNEL"}, 
     42  {"READ_STREAM"}, 
     43  {"MULTI_READ"}, 
     44  {"MULTI_OPEN"}, 
     45  {"OPEN_CLOSE"}, 
     46  {"SCAN_DEVICES"}, 
     47  {"TURN_ON"}, 
     48  {"TURN_OFF"}, 
     49  {"CHECK_POWER"}, 
     50}; 
     51 
     52char stb_names[][20] = { 
     53  {"vip211"}, 
     54  {"directv"}, 
     55  {"hdd"}, 
     56  {"dsr"}, 
     57  {"vip622"}, 
     58  {"dish6000"}, 
     59  {0}, 
     60}; 
     61 
     62extern char strmfile[255]; 
     63void help(char *cmdline) { 
     64  int i; 
     65  printf("%s <-t type> <--m command> [--c channel] [--s serial] [-h]\n", cmdline); 
     66  printf("\t-t/--type type     : set STB type to type.  'type' can be either\n"); 
     67  printf("\t                     a numerical value or string.  Valid types are:\n"); 
     68  for(i = 0; stb_names[i][0] != 0; i++) { 
     69    printf("\t\t%d: %s\n", i, stb_names[i]); 
     70  } 
     71  printf("\t-m/--cmd command   : set command to execute.  'command' can be either\n"); 
     72  printf("\t                     a numerical value or string.  Valid commands are:\n"); 
     73  for(i = 0; i < MAX_CMD; i++) { 
     74    printf("\t\t%d: %s\n", i, cmd_names[i]); 
     75  } 
     76  printf("\t-c/--channel       : set channel to read (this does NOT tune\n"); 
     77  printf("\t-s/--serial serial : set serial number\n"); 
     78  printf("\t-h/--help          : show this help message\n"); 
     79  exit(0); 
     80} 
     81 
     82void printstr(char *str) 
     83{ 
     84  fprintf(stderr, "%s", str); 
     85} 
     86 
     87static unsigned char buffer[1000189]; 
     88static unsigned char *ptr = buffer; 
     89unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 
     90{ 
     91    int fd = *(int *) callback_data; 
     92    if (len <= 0) 
     93      return 0; 
     94    if(memcpy(ptr, tspacket, len)); 
     95    ptr+=len; 
     96    if(ptr-buffer > 1000000) { 
     97      write(fd, buffer, ptr-buffer); 
     98      ptr = buffer; 
     99    } 
     100    return 1; 
     101} 
     102 
     103int main(int argc, char *argv[]) 
     104{ 
     105  r5kdev_t *usbdev = NULL; 
     106  int glblfd, i, j; 
     107  unsigned char buf[0x80]; 
     108  int stb = -1; 
     109  int cmd = -1; 
     110  const char *channel = NULL; 
     111  const char *serial = NULL; 
     112  int runtime = 10; 
     113  struct option long_options[] = { 
     114    {"type", required_argument, NULL, 't'}, 
     115    {"cmd", required_argument, NULL, 'm'}, 
     116    {"channel", required_argument, NULL, 'c'}, 
     117    {"serial", required_argument, NULL, 's'}, 
     118    {"time", required_argument, NULL, 'i'}, 
     119    {"dbgfile", required_argument, NULL, 'D'}, 
     120    {"help", no_argument , NULL, 'h'}, 
     121    {0, 0, 0, 0} 
     122  }; 
     123  while (1) { 
     124    char c; 
     125    c = getopt_long (argc, argv, 
     126                     "t:m:c:s:hD:i:", 
     127                     long_options, NULL); 
     128    if(c == EOF) 
     129      break; 
     130    switch(c) { 
     131      case 't': 
     132      { 
     133        char *ptr; 
     134        int i; 
     135        stb = strtol(optarg, &ptr, 10); 
     136        if(ptr == optarg) { 
     137          stb = -1; 
     138          for(i = 0; stb_names[i][0] != 0; i++) { 
     139            if(strncasecmp(optarg, stb_names[i], strlen(stb_names[i])) == 0) { 
     140              stb = i; 
     141              break; 
     142            } 
     143          } 
     144          if(stb == -1) { 
     145            fprintf(stderr, "Unknown STB type: %s\n", optarg); 
     146            exit(-1); 
     147          } 
     148        } else if(stb < 0 || stb >= R5K_STB_MAX) { 
     149          fprintf(stderr, "Illegal STB type: %d\n", stb); 
     150          exit(-1); 
     151        } 
     152        break; 
     153      } 
     154      case 'm': 
     155      { 
     156        char *ptr; 
     157        int i; 
     158        cmd = strtol(optarg, &ptr, 10); 
     159        if(ptr == optarg) { 
     160          cmd = -1; 
     161          for(i = 0; i < MAX_CMD; i++) { 
     162            if(strncasecmp(optarg, cmd_names[i], strlen(cmd_names[i])) == 0) { 
     163              cmd = i; 
     164              break; 
     165            } 
     166          } 
     167          if(cmd == -1) { 
     168            fprintf(stderr, "Unknown command: %d\n", optarg); 
     169            exit(-1); 
     170          } 
     171        } else if(cmd < 0 || cmd >= MAX_CMD) { 
     172          fprintf(stderr, "Illegal command: %d\n", cmd); 
     173          exit(-1); 
     174        } 
     175        break; 
     176      } 
     177      case 'c': 
     178      { 
     179        int ok = 1; 
     180        char *p; 
     181        if(! strlen(optarg)) { 
     182          fprintf(stderr, "Couldn't parse channel '%s'\n", optarg); 
     183          ok = 0; 
     184        } 
     185        for(p = optarg; *p; p++) { 
     186          if(*p != 'P' && *p != ',' && (*p < '0' || *p > '9')) { 
     187            fprintf(stderr, "Couldn't parse channel '%s'\n", optarg); 
     188            ok = 0; 
     189            break; 
     190          } 
     191        } 
     192        if(ok) 
     193          channel = optarg; 
     194        break; 
     195      } 
     196      case 'i': 
     197      { 
     198        char *ptr; 
     199        runtime = strtol(optarg, &ptr, 0); 
     200        if(optarg == ptr) { 
     201          fprintf(stderr, "Couldn't parse time '%s'\n", optarg); 
     202        } 
     203        break; 
     204      } 
     205      case 's': 
     206        serial = optarg; 
     207        break; 
     208      case 'h': 
     209        help(argv[0]); 
     210        break; 
     211      case 'D': 
     212        #ifdef R5K_DEBUG 
     213          strncpy(strmfile, optarg, 255); 
     214        #else 
     215          fprintf(stderr, "--dbgfile only supported in debug mode.\nMake sure you know what you are doing!\n"); 
     216          exit(-1); 
     217        #endif 
     218    } 
     219  } 
     220  if(cmd == -1 || stb == -1) { 
     221    fprintf(stderr, "Must specify --cmd and --stb\n"); 
     222    exit(-1); 
     223  } 
     224  r5000_init(printstr); 
     225  if(cmd == SCAN_DEVICES) { 
     226    r5kenum_t devs; 
     227    printf("Scanning for R5000 devices\n"); 
     228    if(! r5000_find_stbs(&devs)) { 
     229      printf("Failed to initialize r5000 devices\n"); 
     230    } 
     231    for(i=0; i < devs.count; i++) { 
     232      printf("Found: %s\n", devs.serial[i]); 
     233    } 
     234    goto end; 
     235  } 
     236  usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 
     237  if(! usbdev) { 
     238    fprintf(stderr, "R5000 device could not be found/opened\n"); 
     239    exit(-1); 
     240  } 
     241  glblfd=open("raw.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 
     242  if(cmd == TOGGLE_POWER) { 
     243    int new_state; 
     244    printf("Toggling On/Off\n"); 
     245    new_state = r5000_toggle_on_off(usbdev); 
     246    printf("Turned power %s\n", new_state ? "On" : "Off"); 
     247  } 
     248  if(cmd == TURN_ON) { 
     249    int new_state; 
     250    printf("Turning STB On\n"); 
     251    new_state = r5000_power_on_off(usbdev, 1); 
     252    printf("Turned power %s\n", new_state ? "On" : "Off"); 
     253  } 
     254  if(cmd == TURN_OFF) { 
     255    int new_state; 
     256    printf("Turning STB Off\n"); 
     257    new_state = r5000_power_on_off(usbdev, 0); 
     258    printf("Turned power %s\n", new_state ? "On" : "Off"); 
     259  } 
     260  if(cmd == CHECK_POWER) { 
     261    int new_state; 
     262    new_state = r5000_get_power_state(usbdev); 
     263    printf("Power is currently %s\n", new_state ? "On" : "Off"); 
     264  } 
     265  if(cmd == CHANGE_CHANNEL) { 
     266    if(! channel) { 
     267      printf("Must specify a channel when using '-m CHANGE_CHANNEL'\n"); 
     268      exit(-1); 
     269    } 
     270    printf("Setting channel %s\n", channel); 
     271    r5000_change_channel(usbdev, channel, 0); 
     272  } 
     273  if(cmd == OPEN_CLOSE) { 
     274    int on_off; 
     275    printf("Doing open/close\n"); 
     276    on_off = r5000_get_power_state(usbdev); 
     277    printf("State1: %d\n", on_off); 
     278    r5000_close(usbdev); 
     279    printf("Closed\n"); 
     280    sleep(1); 
     281    usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 
     282    printf("ReOpened\n"); 
     283    on_off = r5000_get_power_state(usbdev); 
     284    printf("State2: %d\n", on_off); 
     285  } 
     286  if(cmd == READ_STREAM || cmd == MULTI_READ) { 
     287    if(channel) { 
     288      uint c; 
     289      char *ptr; 
     290      printf("Setting channel %d\n"); 
     291      c = strtol(channel, &ptr, 0); 
     292      r5000_change_channel(usbdev, NULL, c); 
     293    } 
     294    printf("Reading stream\n"); 
     295    r5000_start_stream(usbdev); 
     296    time_t t = time(NULL); 
     297    while (time(NULL) - t < runtime) 
     298    { 
     299      // This will timeout after 1ms regardless of data availability 
     300      //usleep(10000); 
     301      r5000_loop_iterate(usbdev, 10); 
     302    } 
     303    r5000_stop_stream(usbdev); 
     304  } 
     305  if(cmd == MULTI_READ) { 
     306    printf("Reading stream again\n"); 
     307    close(glblfd); 
     308    glblfd=open("raw_1.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 
     309    sleep(1); 
     310    r5000_start_stream(usbdev); 
     311    time_t t = time(NULL); 
     312    while (time(NULL) - t < 10) 
     313    { 
     314      // This will timeout after 1ms regardless of data availability 
     315      //usleep(10000); 
     316      r5000_loop_iterate(usbdev, 10); 
     317    } 
     318    r5000_stop_stream(usbdev); 
     319  } 
     320  if(cmd == MULTI_OPEN) { 
     321    printf("Doing multi-open\n"); 
     322    while(usbdev) { 
     323      time_t t; 
     324      r5000_start_stream(usbdev); 
     325      t = time(NULL); 
     326      while (time(NULL) - t < 2) 
     327      { 
     328        // This will timeout after 1ms regardless of data availability 
     329        //usleep(10000); 
     330        r5000_loop_iterate(usbdev, 10); 
     331      } 
     332      r5000_stop_stream(usbdev); 
     333      r5000_close(usbdev); 
     334      printf("Closed\n"); 
     335      sleep(1); 
     336      usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 
     337      printf("ReOpened %s\n", serial); 
     338    } 
     339    r5000_start_stream(usbdev); 
     340    time_t t = time(NULL); 
     341    while (time(NULL) - t < 10) 
     342    { 
     343      // This will timeout after 1ms regardless of data availability 
     344      //usleep(10000); 
     345      r5000_loop_iterate(usbdev, 10); 
     346    } 
     347    r5000_stop_stream(usbdev); 
     348  } 
     349end: 
     350  r5000_close(usbdev); 
     351  if(ptr != buffer) 
     352    write(glblfd, buffer, ptr-buffer); 
     353  close(glblfd); 
     354} 
  • new file contrib/r5000/README

    - +  
     1ehci-2.6.25.patch: 
     2  This patch is needed for all kernels earlier than 2.6.26.  It adds support 
     3for 1024 byte frames which the R5000 needs.  As of 2.6.26 the patch is already 
     4in the kernel. 
     5 
     6r5ktest: 
     7Compile r5ktest via: 
     8  gcc -g -o r5ktest -I../../libs/libmythtv r5ktest.c ../../libs/libmythtv/r5000/*.c -lusb 
     9 
     10############################################################################### 
     11############################################################################### 
     12In order to use the R5000 in linux, you must 1st load the firmware into the 
     13device. 
     14The easiest way to do this is with udev: 
     151) sudo cp 85-r5000.rules /etc/udev/rules.d 
     162) sudo cp r5000.hex /lib/firmware/r5000.hex 
     173) Now plug in the  R5000 STB 
     184) lsusb | grep Anchor 
     19  Bus 004 Device 013: ID 0547:1002 Anchor Chips, Inc. 
     205)ensure that the usbtest module did not load: 
     21lsmod | grep usbtest 
     22If you see the usbtest module you'll need to blacklist it and/or rmmod it 
     23 
     24-------------------------------------------------------------- 
     25If this fails at any step along the way, try the manual method: 
     26-------------------------------------------------------------- 
     27 
     28Make sure you have the following installed: 
     29  lsusb (in Debian/Ubuntu this is in the usbutils package) 
     30  fxload 
     311) Locate the device using lsusb: 
     32lsusb 
     33... 
     34Bus 001 Device 026: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit 
     352)Install the firmware (this often needs to be done via sudo/root) 
     36(depending on where usbfs is mounted): 
     37fxload -t fx2 -D /dev/bus/usb/001/026 -I r5000.hex -m 0666 
     38or 
     39fxload -t fx2 -D /proc/bus/usb/001/026 -I r5000.hex -m 0666 
     40(note that 001 is the Bus and 026 is the Device from lsusb) 
     41 
     423) Ensure that the firmware loaded: 
     43lsusb 
     44... 
     45Bus 001 Device 028: ID 0547:1002 Anchor Chips, Inc. 
     46(Note that is has a completely different name now) 
     47 
     484)ensure that the usbtest module did not load: 
     49lsmod | grep usbtest 
     50If you see the usbtest module you'll need to blacklist it and/or rmmod it 
     51############################################################################### 
     52############################################################################### 
     53 
     54Before trying to use the R5000 in mythtv, make sure it is working in r5ktest 
     55./r5ktest -t 0 -m 6 
     56Scanning for R5000 devices 
     57Found: xxxxxxx 
     58 
     59If you see something like: 
     60    R5000 initialization failed at stage 1: 
     61        Expected 1 bytes, but got -1 bytes 
     62    R5000 failed to locate any R5000 devices.  Are you sure you have 
     63        permissions set properly? 
     64Then you likely do not have permissions to access the usb device.  Try running 
     65as root. 
     66 
     67next do: 
     68./r5ktest --help 
     69and choose the correct type for your STB: 
     70   vip211 : VIP211 and VIP411 
     71   vip622 : VIP622, VIP722, BEV9242 
     72   hdd: 
     73   dsr: 
     74   directv: 
     75 
     76Now try a few commands to make sure they work properly: 
     77   ./r5ktest --type vip211 --cmd TURN_ON 
     78   ./r5ktest --type vip211 --cmd TURN_OFF 
     79   ./r5ktest --type vip211 --cmd CHANGE_CHANNEL -c <channel number> 
     80   ./r5ktest --type vip211 --cmd OPEN_CLOSE 
     81 
     82############################################################################### 
     83############################################################################### 
     84 
     85Configure mythtv: 
     86Go into myth-setup and select the R5000 device, and the relevant STB. 
     87Configure a Video Source 
     88Configure an Input 
     89To enter channels, the easiest way is to set up scehdules-direct with the provider/channels you receieve then import them from the Card-Input menu 
     90If you choose to enter them yourself, make sure to set the frequency to whatever needs to be punched into the remote to select the channel 
     91 
     92Some notes: 
     93Only ViP style STBs (Dish Network and BEV) and DirectTV STBs have channel-change capabilities.  Others need an external program 
     94 
     95At least on the ViP211, it is necessary to disable the auto-power-off on the STB, as the box will power off but the LED will remain on, and the R5000 module won't be able to detect teh power state properly.  I'm not sure whether this applies to other boxes or not. 
     96 
  • new file contrib/r5000/85-r5000.rules

    - +  
     1SUBSYSTEM=="usb", ACTION=="add", ENV{PRODUCT}=="4b4/8613/*", RUN+="/sbin/fxload -D %N -I /lib/firmware/r5000.hex -t fx2 -m 0666" 
     2SUBSYSTEM=="usb", ENV{PRODUCT}=="547/1002/*", MODE="666" 
     3 
  • new file libs/libmythtv/r5000/r5k_directv_buttons.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17//Support for DirectTV remotes 
     18 
     19#include "r5000_internal.h" 
     20 
     21struct r5000_buttons directv_button_cmd = 
     22{ 
     230x49, //len 
     24400000, //delay 
     25//button 0: 
     26{ 
     27    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     28    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     29    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     30    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     31    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     32}, 
     33//button 1: 
     34{ 
     35    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     36    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     37    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     38    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     39    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     40}, 
     41//button 2: 
     42{ 
     43    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     44    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     45    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     46    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     47    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     48}, 
     49//button 3: 
     50{ 
     51    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     52    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     53    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     54    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     55    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     56}, 
     57//button 4: 
     58{ 
     59    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     60    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     61    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     62    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     63    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     64}, 
     65//button 5: 
     66{ 
     67    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     68    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     69    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     70    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     71    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     72}, 
     73//button 6: 
     74{ 
     75    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     76    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     77    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     78    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     79    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     80}, 
     81//button 7: 
     82{ 
     83    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     84    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     85    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     86    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     87    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     88}, 
     89//button 8: 
     90{ 
     91    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     92    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     93    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     94    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 
     95    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     96}, 
     97//button 9: 
     98{ 
     99    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     100    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     101    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     102    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 
     103    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     104}, 
     105//Clear: 
     106{ 
     107    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     108    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     109    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 
     110    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
     111    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     112}, 
     113//Enter: 
     114{ 
     115    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     116    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     117    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     118    0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     119    0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     120}, 
     121//Power 
     122{ 
     123    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     124    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     125    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     126    0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     127    0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     128}, 
     129}; 
  • new file libs/libmythtv/r5000/r5k_pes.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17//Support for DirecTV boxes 
     18#include <netinet/in.h> 
     19#include <string.h> 
     20 
     21#include "r5000_internal.h" 
     22 
     23#define DTV_VPID 0x1322 
     24#define DTV_APID 0x1333 
     25#define DTV_PAT_PMT_COUNT 5000 
     26 
     27struct r5000_dtv { 
     28  unsigned char vbuf[188*2+4]; 
     29  unsigned char abuf[188*2+6]; 
     30  unsigned char *video; 
     31  unsigned char *audio; 
     32  unsigned int vpos; 
     33  unsigned int apos; 
     34  unsigned int vstart; 
     35  unsigned int astart; 
     36  unsigned int video_cc; 
     37  unsigned int audio_cc; 
     38  unsigned int vstate; 
     39  unsigned int pic_pos; 
     40  int alen; 
     41  unsigned int pat_pmt_count; 
     42}; 
     43 
     44//The following are used to convert DirectTV into TS format 
     45static int directv_make_empty_pes(unsigned char *ptr, unsigned char type) 
     46{ 
     47  ptr[0] = 0x00; 
     48  ptr[1] = 0x00; 
     49  ptr[2] = 0x01; 
     50  ptr[3] = type; 
     51  ptr[4] = 0x00; 
     52  ptr[5] = 0x00; 
     53  ptr[6] = 0x80; 
     54  ptr[7] = 0x00; //2 MSB represent PTS/DTS flag 
     55  ptr[8] = 0x0a; 
     56  ptr[9]  = 0xff; 
     57  ptr[10] = 0xff; 
     58  ptr[11] = 0xff; 
     59  ptr[12] = 0xff; 
     60  ptr[13] = 0xff; 
     61  ptr[14] = 0xff; 
     62  ptr[15] = 0xff; 
     63  ptr[16] = 0xff; 
     64  ptr[17] = 0xff; 
     65  ptr[18] = 0xff; 
     66  return 19; 
     67} 
     68 
     69static void directv_make_pespts(unsigned char *outptr, unsigned int pts) 
     70{ 
     71        pts = htonl(pts); 
     72        unsigned char *inpts = (unsigned char *)&pts; 
     73        outptr[0] = 0x01 | 
     74                    ((inpts[0] & 0xC0) >>5); 
     75        outptr[1] = ((inpts[0] & 0x3F) << 2) | 
     76                    ((inpts[1] & 0xC0) >> 6); 
     77        outptr[2] = 0x01 | ((inpts[1] & 0x3F) << 2) | 
     78                    ((inpts[2] & 0x80) >> 6); 
     79        outptr[3] = ((inpts[2] & 0x7F) << 1) | 
     80                    ((inpts[3] & 0x80) >> 7); 
     81        outptr[4] = 0x01 | ((inpts[3] & 0x7F) << 1); 
     82} 
     83 
     84static void directv_update_video_pes(unsigned char *ptr, int pos) 
     85{ 
     86  //pos points at the 1st char after a pic start code 
     87  int picture_coding_type; 
     88  int hdr_len; 
     89  unsigned int pts1, dts1; 
     90  unsigned char *buf = ptr + pos; 
     91  picture_coding_type = (buf[1] >> 3) & 0x07; 
     92  hdr_len = (picture_coding_type > 1) ? 5 : 4; 
     93  if(buf[hdr_len + 3] == 0xb5) 
     94    hdr_len += 9; 
     95  if(buf[hdr_len + 3] == 0xb2) { 
     96    pts1 = ((buf[hdr_len+6] & 0x03)   << 30) + 
     97           ((buf[hdr_len+7] & 0x7f) << 23) + 
     98           ((buf[hdr_len+8])          << 15) + 
     99           ((buf[hdr_len+9] & 0x7f) << 8) + 
     100           buf[hdr_len+10]; 
     101    dts1 = ((buf[hdr_len+13] & 0x03)   << 30) + 
     102           ((buf[hdr_len+14] & 0x7f) << 23) + 
     103           ((buf[hdr_len+15])          << 15) + 
     104           ((buf[hdr_len+16] & 0x7f) << 8) + 
     105           buf[hdr_len+17]; 
     106    //NOTE:  This is wrong.  DSS timestamps only have a resolution of 2^32/300 
     107    //r5000_print("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0); 
     108    ptr[7] |= 0xc0; 
     109    directv_make_pespts(ptr+9, pts1/300); 
     110    ptr[9] |= 0x30; 
     111    directv_make_pespts(ptr+14, dts1/300); 
     112    ptr[14] |= 0x10; 
     113  } 
     114} 
     115 
     116static void directv_fix_audio_pts(unsigned char *ptr) 
     117{ 
     118  unsigned int pts = ((ptr[0] & 0x06) << 29) + 
     119                     (ptr[1] << 22) + 
     120                     ((ptr[2] & 0xfe) << 14) + 
     121                     (ptr[3] << 7) + 
     122                     (ptr[4] >> 1); 
     123  directv_make_pespts(ptr, pts/300); 
     124  ptr[0] |= 0x20; 
     125} 
     126 
     127 
     128static void pes_write_ts(r5kdev_t *r5kdev, unsigned char *ptr, int len, int pid, int start, int *cc) 
     129{ 
     130  int stuff = 184 - len; 
     131  //Note:  we know that there are 188 bytes allocated before 'ptr' 
     132  //       that we can use for the header 
     133  if(stuff > 0) { 
     134    int stuff1 = stuff; 
     135    while(stuff1 > 2) { 
     136      *--ptr = 0xff; 
     137      stuff1--; 
     138    } 
     139    if(stuff1 == 2) { 
     140      *--ptr = 0x00; 
     141    } 
     142    *--ptr = stuff - 1; 
     143    *--ptr = 0x30 | *cc; 
     144  } else { 
     145    *--ptr = 0x10 | *cc; 
     146  } 
     147  *--ptr = pid & 0xff; 
     148  *--ptr = (start << 6) | (pid >> 8); 
     149  *--ptr = 0x47; 
     150  r5kdev->cb(ptr, 188, r5kdev->cb_data); 
     151  *cc = (*cc+1) & 0x0f; 
     152} 
     153 
     154static void pes_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 
     155{ 
     156  int i; 
     157  struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 
     158  for(i = 0; i < len; i+=2) { 
     159    unsigned char data = buf[i]; 
     160    unsigned char type = buf[i+1]; 
     161    if(0xff == type) { 
     162      //video 
     163      dtv->video[dtv->vpos++] = data; 
     164      if(dtv->vpos > 4 && dtv->video[dtv->vpos-2] == 0x01 && 
     165         dtv->video[dtv->vpos-3] == 0x00 && dtv->video[dtv->vpos-4] == 0x00) { 
     166        if (data == 0xe0) { 
     167          //HD video header (PES) 
     168          pes_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 
     169          dtv->pat_pmt_count++; 
     170          dtv->video[0] = 0x00; 
     171          dtv->video[1] = 0x00; 
     172          dtv->video[2] = 0x01; 
     173          dtv->video[3] = 0xe0; 
     174          dtv->vpos = 4; 
     175          dtv->vstart = 1; 
     176          dtv->vstate = data; 
     177        } else if (r5kdev->stb_type == R5K_STB_DIRECTV && 
     178                   (data == 0xb3 || data == 0x00)) { 
     179          if (dtv->vstate == 0xff) { 
     180            dtv->vstate = data; 
     181            pes_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 
     182            dtv->pat_pmt_count++; 
     183            //Create a PES header, but no PTS/DTS info yet so just use stuffing bytes 
     184            dtv->vpos = directv_make_empty_pes(dtv->video, 0xe0); 
     185            dtv->video[dtv->vpos++] = 0x00; 
     186            dtv->video[dtv->vpos++] = 0x00; 
     187            dtv->video[dtv->vpos++] = 0x01; 
     188            dtv->video[dtv->vpos++] = data; 
     189            dtv->vstart = 1; 
     190            dtv->pic_pos = dtv->vpos; 
     191          } 
     192        } 
     193      } 
     194      if(dtv->vpos == 188) { 
     195        if (dtv->vstate == 0x00) 
     196          //We found pic frame without a PES header (SD) 
     197          directv_update_video_pes(dtv->video, dtv->pic_pos); 
     198        pes_write_ts(r5kdev, dtv->video, 184, DTV_VPID, dtv->vstart, &dtv->video_cc); 
     199        dtv->pat_pmt_count++; 
     200        dtv->video[0] = dtv->video[184]; 
     201        dtv->video[1] = dtv->video[185]; 
     202        dtv->video[2] = dtv->video[186]; 
     203        dtv->video[3] = dtv->video[187]; 
     204        dtv->vpos = 4; 
     205        dtv->vstart = 0; 
     206        dtv->vstate = 0xff; 
     207      } 
     208    } else if(0xfe == type) { 
     209      //audio 
     210      dtv->audio[dtv->apos++] = data; 
     211      dtv->alen--; 
     212      if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xbd && dtv->audio[dtv->apos-4] == 0x01 && 
     213         dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 
     214        dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 
     215        pes_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 
     216        dtv->pat_pmt_count++; 
     217        dtv->audio[0] = 0x00; 
     218        dtv->audio[1] = 0x00; 
     219        dtv->audio[2] = 0x01; 
     220        dtv->audio[3] = 0xbd; 
     221        dtv->audio[4] = dtv->audio[dtv->apos-2]; 
     222        dtv->audio[5] = data; 
     223        dtv->apos = 6; 
     224        dtv->astart = 1; 
     225        r5kdev->pmt[1].id = 0x81; //AC3 
     226      } else if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xc0 && dtv->audio[dtv->apos-4] == 0x01 && 
     227           dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 
     228        dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 
     229        pes_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 
     230        dtv->pat_pmt_count++; 
     231        dtv->audio[0] = 0x00; 
     232        dtv->audio[1] = 0x00; 
     233        dtv->audio[2] = 0x01; 
     234        dtv->audio[3] = 0xc0; 
     235        if (r5kdev->stb_type == R5K_STB_DIRECTV) { 
     236          dtv->audio[4] = (dtv->alen + 3) >> 8; 
     237          dtv->audio[5] = (dtv->alen + 3) & 0xff; 
     238          dtv->audio[6] = 0x80; 
     239          dtv->audio[7] = 0x80; 
     240          dtv->audio[8] = 0x05; 
     241          dtv->apos = 9; 
     242        } else { 
     243          dtv->audio[4] = dtv->audio[dtv->apos-2]; 
     244          dtv->audio[5] = data; 
     245          dtv->apos = 6; 
     246        } 
     247        dtv->astart = 1; 
     248        r5kdev->pmt[1].id = 0x04; //MP2 
     249      } else if(dtv->apos == 190) { 
     250        if(dtv->astart && dtv->audio[3] == 0xc0 && r5kdev->stb_type == R5K_STB_DIRECTV) 
     251          directv_fix_audio_pts(dtv->audio+9); 
     252        pes_write_ts(r5kdev, dtv->audio, 184, DTV_APID, dtv->astart, &dtv->audio_cc); 
     253        dtv->pat_pmt_count++; 
     254        dtv->audio[0] = dtv->audio[184]; 
     255        dtv->audio[1] = dtv->audio[185]; 
     256        dtv->audio[2] = dtv->audio[186]; 
     257        dtv->audio[3] = dtv->audio[187]; 
     258        dtv->audio[4] = dtv->audio[188]; 
     259        dtv->audio[5] = dtv->audio[189]; 
     260        dtv->apos = 6; 
     261        dtv->astart = 0; 
     262      } 
     263    } 
     264  } 
     265  if(r5kdev->pmt[1].id && dtv->pat_pmt_count > DTV_PAT_PMT_COUNT) { 
     266    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 
     267    r5000_send_pmt(r5kdev); 
     268    dtv->pat_pmt_count = 0; 
     269  } 
     270} 
     271 
     272static void pes_start_stream(r5kdev_t *r5kdev) 
     273{ 
     274  struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 
     275  dtv->vstart = 0; 
     276  dtv->astart = 0; 
     277  dtv->vpos = 0; 
     278  dtv->apos = 0; 
     279  dtv->video_cc = 0; 
     280  dtv->audio_cc = 0; 
     281  dtv->vstate = 0xff; 
     282  dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 
     283} 
     284 
     285void pes_init(r5kdev_t *r5kdev) 
     286{ 
     287  struct r5000_dtv *dtv = (struct r5000_dtv *)calloc(1, sizeof(struct r5000_dtv)); 
     288  dtv->video = dtv->vbuf + 188; 
     289  dtv->audio = dtv->abuf + 188; 
     290  dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 
     291  dtv->vstate = 0xff; 
     292  r5kdev->stbdata = dtv; 
     293  r5kdev->pmt[0].id = 0x02; //MPEG2 
     294  r5kdev->pmt[0].pid = DTV_VPID; 
     295  r5kdev->pmt[0].desc = r5000_pmt_video_desc; 
     296  r5kdev->pmt[1].id = 0x00; 
     297  r5kdev->pmt[1].pid = DTV_APID; 
     298  r5kdev->pmt[1].desc = r5000_pmt_audio_desc; 
     299  r5kdev->num_pmt_entries = 2; 
     300  r5kdev->process_block = pes_process_block; 
     301  r5kdev->start_stream  = pes_start_stream; 
     302  if(r5kdev->stb_type == R5K_STB_DIRECTV) { 
     303    r5kdev->button = &directv_button_cmd; 
     304    r5kdev->power_active_low = 1; 
     305  } else { 
     306    r5kdev->button = &dish6000_button_cmd; 
     307    r5kdev->power_active_low = 0; 
     308    r5kdev->discrete_power = 1; 
     309  } 
     310  r5kdev->read_words = 1; 
     311} 
     312 
     313void pes_free(r5kdev_t *r5kdev) 
     314{ 
     315  free(r5kdev->stbdata); 
     316} 
  • new file libs/libmythtv/r5000/r5k_vip_buttons.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17//Support for Dish Network ViP211/ViP422 remotes 
     18 
     19#include "r5000_internal.h" 
     20 
     21struct r5000_buttons vip_button_cmd = 
     22{ 
     230x40, //len 
     24400000, //delay 
     25//button 0: 
     26{ 
     27 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     28 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     29 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     30 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     31}, 
     32//button 1: 
     33{ 
     34 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     35 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     36 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     37 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     38}, 
     39//button 2: 
     40{ 
     41 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     42 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     43 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     44 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     45}, 
     46//button 3: 
     47{ 
     48 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     49 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     50 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     51 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     52}, 
     53//button 4: 
     54{ 
     55 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     56 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     57 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     58 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     59}, 
     60//button 5: 
     61{ 
     62 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     63 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     64 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     65 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     66}, 
     67//button 6: 
     68{ 
     69 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     70 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     71 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     72 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     73}, 
     74//button 7: 
     75{ 
     76 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     77 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     78 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     79 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     80}, 
     81//button 8: 
     82{ 
     83 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     84 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     85 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     86 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     87}, 
     88//button 9: 
     89{ 
     90 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     91 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     92 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     93 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     94}, 
     95//Clear: 
     96{ 
     97 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     98 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     99 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     100 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     101}, 
     102//Enter: 
     103{ 
     104 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     105 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     106 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     107 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     108}, 
     109//Power 
     110{ 
     111 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     112 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     113 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     114 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     115}, 
     116//Power-On 
     117{ 
     118 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     119 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     120 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     121 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     122}, 
     123//Power-Off 
     124{ 
     125 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     126 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     127 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     128 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     129}, 
     130}; 
  • new file libs/libmythtv/r5000/r5k_dish6000_buttons.c

    - +  
     1/* Copyright 2008 Alan Nisota <alannisota@gmail.com> 
     2 * 
     3 * This library is free software; you can redistribute it and/or 
     4 * modify it under the terms of the GNU Lesser General Public 
     5 * License as published by the Free Software Foundation; either 
     6 * version 2.1 of the License, or (at your option) any later version. 
     7 * 
     8 * This library is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     11 * Lesser General Public License for more details. 
     12 * 
     13 * You should have received a copy of the GNU Lesser General Public 
     14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>. 
     15 */ 
     16 
     17//Support for Dish/BEV 6000 remotes 
     18 
     19#include "r5000_internal.h" 
     20 
     21struct r5000_buttons dish6000_button_cmd = 
     22{ 
     230x79, //len 
     24800000, //delay 
     25//button 0: 
     26{ 
     27        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     28        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     29        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     30        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     31        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     32        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     33        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     34        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 
     35}, 
     36//button 1: 
     37{ 
     38        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     39        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     40        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     41        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     42        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     43        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     44        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     45        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     46}, 
     47//button 2: 
     48{ 
     49        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     50        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     51        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     52        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     53        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     54        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     55        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     56        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 
     57}, 
     58//button 3: 
     59{ 
     60        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     61        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     62        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     63        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     64        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     65        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     66        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     67        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     68}, 
     69//button 4: 
     70{ 
     71        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     72        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     73        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     74        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     75        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     76        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     77        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     78        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     79}, 
     80//button 5: 
     81{ 
     82        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     83        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     84        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     85        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     86        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     87        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     88        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     89        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 
     90}, 
     91//button 6: 
     92{ 
     93        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     94        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     95        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     96        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     97        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     98        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     99        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     100        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     101}, 
     102//button 7: 
     103{ 
     104        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     105        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     106        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     107        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     108        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     109        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     110        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     111        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     112}, 
     113//button 8: 
     114{ 
     115        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     116        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     117        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     118        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     119        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     120        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     121        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     122        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 
     123}, 
     124//button 9: 
     125{ 
     126        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     127        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     128        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     129        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     130        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     131        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     132        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     133        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     134}, 
     135//Clear: 
     136{ 
     137        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     138        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     139        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     140        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     141        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     142        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     143        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     144        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     145}, 
     146//Enter: 
     147{ 
     148        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     149        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     150        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     151        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     152        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     153        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     154        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     155        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     156}, 
     157//Power 
     158{ 
     159        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     160        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     161        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     162        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     163        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     164        0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     165        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     166        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 
     167}, 
     168//Power-On 
     169{ 
     170        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     171        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     172        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     173        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     174        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     175        0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     176        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     177        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 
     178}, 
     179//Power-Off 
     180{ 
     181        0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     182        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     183        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     184        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     185        0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     186        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     187        0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     188        0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 
     189}, 
     190};