Ticket #4752: r5000_r16.patch

File r5000_r16.patch, 179.8 KB (added by anonymous, 3 years ago)

Version 16 for STABLE

  • configure

    old new  
    158158  echo "  --disable-v4l            disable Video4Linux support" 
    159159  echo "  --disable-ivtv           disable ivtv support (PVR-x50) req. v4l support" 
    160160  echo "  --disable-dvb            disable DVB support" 
     161  echo "  --disable-r5000          disable support for R5000 USB STBs" 
    161162  echo "  --dvb-path=HDRLOC        location of directory containing" 
    162163  echo "                           'linux/dvb/frontend.h', not the" 
    163164  echo "                           directory with frontend.h [$dvb_path]" 
     
    891892    hdhomerun 
    892893    iptv 
    893894    ivtv 
     895    r5000 
    894896    joystick_menu 
    895897    libfftw3 
    896898    lirc 
     
    10461048dbox2_deps="backend" 
    10471049dvb_deps="backend" 
    10481050firewire_deps="backend" 
     1051r5000_deps="backend" 
    10491052iptv_deps="backend" 
    10501053ivtv_deps="backend v4l" 
    10511054hdhomerun_deps="backend" 
     
    11791182hdhomerun="yes" 
    11801183iptv="yes" 
    11811184ivtv="yes" 
     1185r5000="yes" 
    11821186joystick_menu="default" 
    11831187lamemp3="yes" 
    11841188lirc="yes" 
     
    27172721enabled libfftw3 && has_library libfftw3_threads && has_header fftw3.h || 
    27182722    disable libfftw3 
    27192723 
     2724enabled r5000 && has_library libusb && check_header usb.h || disable r5000 
     2725 
    27202726enabled x11 && has_library libX11 || disable x11 
    27212727enabled xrandr && has_header X11/extensions/Xrandr.h || disable xrandr 
    27222728enabled xv && has_library libXv || disable xv 
     
    29983004  echo "DBox2 support             ${dbox2-no}" 
    29993005  echo "HDHomeRun support         ${hdhomerun-no}" 
    30003006  echo "IPTV support              ${iptv-no}" 
     3007  echo "R5000 support             ${r5000-no}" 
    30013008fi 
    30023009 
    30033010if enabled frontend; then 
  • libs/libmythtv/cardutil.h

    old new  
    5353        FIREWIRE, 
    5454        HDHOMERUN, 
    5555        FREEBOX, 
     56        R5000, 
    5657    }; 
    5758 
    5859    static enum CARD_TYPES toCardType(const QString &name) 
     
    8182            return HDHOMERUN; 
    8283        if ("FREEBOX" == name) 
    8384            return FREEBOX; 
     85        if ("R5000" == name) 
     86            return R5000; 
    8487        return ERROR_UNKNOWN; 
    8588    } 
    8689 
     
    8992        return 
    9093            (rawtype != "DVB")       && 
    9194            (rawtype != "FIREWIRE")  && (rawtype != "DBOX2")   && 
    92             (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX"); 
     95            (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") && 
     96            (rawtype != "R5000"); 
    9397    } 
    9498 
    9599    static bool         IsUnscanable(const QString &rawtype) 
    96100    { 
    97101        return 
    98             (rawtype == "FIREWIRE")  || (rawtype == "DBOX2"); 
     102            (rawtype == "FIREWIRE")  || (rawtype == "DBOX2") || 
     103            (rawtype == "R5000"); 
    99104    } 
    100105 
    101106    static bool         IsEITCapable(const QString &rawtype) 
  • libs/libmythtv/libmythtv.pro

    old new  
    496496        DEFINES += USING_DVB 
    497497    } 
    498498 
     499    #Support for R5000 usb device 
     500    using_r5000 { 
     501        HEADERS += r5000channel.h           r5000recorder.h 
     502        HEADERS += r5000signalmonitor.h     r5000device.h 
     503        HEADERS += r5000/r5000.h            r5000/libusb_augment.h 
     504        HEADERS += r5000/r5000_internal.h   r5000/r5000init.h 
     505 
     506        SOURCES += r5000channel.cpp         r5000recorder.cpp 
     507        SOURCES += r5000signalmonitor.cpp   r5000device.cpp 
     508        SOURCES += r5000/r5000.c            r5000/libusb_augment.c 
     509        SOURCES += r5000/r5k_vip.c          r5000/r5k_directv.c 
     510        SOURCES += r5000/r5k_sat.c          r5000/r5k_misc.c 
     511 
     512        LIBS += -lusb 
     513        DEFINES += USING_R5000 
     514    } 
     515 
    499516    DEFINES += USING_BACKEND 
    500517} 
    501518 
  • libs/libmythtv/signalmonitor.h

    old new  
    297297            (cardtype.upper() == "HDTV")      || 
    298298            (cardtype.upper() == "HDHOMERUN") || 
    299299            (cardtype.upper() == "FIREWIRE")  || 
    300             (cardtype.upper() == "FREEBOX")); 
     300            (cardtype.upper() == "FREEBOX")   || 
     301            (cardtype.upper() == "R5000")); 
    301302} 
    302303 
    303304inline bool SignalMonitor::IsSupported(const QString &cardtype) 
  • libs/libmythtv/signalmonitor.cpp

    old new  
    4141#   include "firewirechannel.h" 
    4242#endif 
    4343 
     44#ifdef USING_R5000 
     45#   include "r5000signalmonitor.h" 
     46#   include "r5000channel.h" 
     47#endif 
     48 
    4449#undef DBG_SM 
    4550#define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 
    4651    "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); 
     
    127132            signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 
    128133    } 
    129134#endif 
     135#ifdef USING_R5000 
     136    if (cardtype.upper() == "R5000") 
     137    { 
     138        R5000Channel *fc = dynamic_cast<R5000Channel*>(channel); 
     139        if (fc) 
     140            signalMonitor = new R5000SignalMonitor(db_cardnum, fc); 
     141    } 
     142#endif 
    130143 
    131144    if (!signalMonitor) 
    132145    { 
  • libs/libmythtv/cardutil.cpp

    old new  
    14571457    if (("FIREWIRE"  == cardtype) || 
    14581458        ("FREEBOX"   == cardtype) || 
    14591459        ("DBOX2"     == cardtype) || 
    1460         ("HDHOMERUN" == cardtype)) 
     1460        ("HDHOMERUN" == cardtype) || 
     1461        ("R5000"     == cardtype)) 
    14611462    { 
    14621463        ret += "MPEG2TS"; 
    14631464    } 
     
    15821583    if (("FIREWIRE"  == cardtype) || 
    15831584        ("FREEBOX"   == cardtype) || 
    15841585        ("DBOX2"     == cardtype) || 
    1585         ("HDHOMERUN" == cardtype)) 
     1586        ("HDHOMERUN" == cardtype) || 
     1587        ("R5000"     == cardtype)) 
    15861588    { 
    15871589        inputs += "MPEG2TS"; 
    15881590    } 
  • libs/libmythtv/videosource.cpp

    old new  
    3636#include "frequencies.h" 
    3737#include "diseqcsettings.h" 
    3838#include "firewiredevice.h" 
     39#include "r5000device.h" 
    3940#include "compat.h" 
    4041 
    4142 
     
    12991300    } 
    13001301}; 
    13011302 
     1303class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage 
     1304{ 
     1305  public: 
     1306    R5000Serial(const CaptureCard &parent) : 
     1307        ComboBoxSetting(this), 
     1308        CaptureCardDBStorage(this, parent, "videodevice") 
     1309    { 
     1310        setLabel(QObject::tr("Serial #")); 
     1311#ifdef USING_R5000 
     1312        QStringList serials = R5000Device::GetSTBList(); 
     1313        for (uint i = 0; i < serials.size(); i++) 
     1314        { 
     1315            addSelection(serials[i]); 
     1316        } 
     1317#endif // USING_FIREWIRE 
     1318    } 
     1319}; 
     1320 
     1321class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage 
     1322{ 
     1323  public: 
     1324    R5000Model(const CaptureCard  &parent) : 
     1325      ComboBoxSetting(this), 
     1326      CaptureCardDBStorage(this, parent, "firewire_model") 
     1327    { 
     1328        setLabel(QObject::tr("R5000 STB type")); 
     1329        addSelection("VIP211"); 
     1330        addSelection("VIP411"); 
     1331        addSelection("VIP622"); 
     1332        addSelection("VIP722"); 
     1333        addSelection("BEV9242"); 
     1334        addSelection("DIRECTV"); 
     1335        addSelection("STARCHOICE/DSR"); 
     1336        addSelection("HDD-200"); 
     1337        QString help = QObject::tr( 
     1338            "Choose the type of R5000 enabled STB you are using."); 
     1339        setHelpText(help); 
     1340    } 
     1341}; 
     1342class R5000ConfigurationGroup : public VerticalConfigurationGroup 
     1343{ 
     1344  public: 
     1345    R5000ConfigurationGroup(CaptureCard& a_parent): 
     1346       VerticalConfigurationGroup(false, true, false, false), 
     1347       parent(a_parent) 
     1348    { 
     1349        setUseLabel(false); 
     1350        addChild(new R5000Serial(parent)); 
     1351        addChild(new R5000Model(parent)); 
     1352        addChild(new SingleCardInput(parent)); 
     1353    }; 
     1354 
     1355  private: 
     1356    CaptureCard &parent; 
     1357}; 
     1358 
    13021359class IPTVHost : public LineEditSetting, public CaptureCardDBStorage 
    13031360{ 
    13041361  public: 
     
    14831540#ifdef USING_IPTV 
    14841541    addTarget("FREEBOX",   new IPTVConfigurationGroup(parent)); 
    14851542#endif // USING_IPTV 
     1543 
     1544#ifdef USING_R5000 
     1545    addTarget("R5000", new R5000ConfigurationGroup(parent)); 
     1546#endif // USING_R5000 
    14861547} 
    14871548 
    14881549void CaptureCardGroup::triggerChanged(const QString& value)  
     
    16701731#ifdef USING_IPTV 
    16711732    setting->addSelection(QObject::tr("Network Recorder"), "FREEBOX"); 
    16721733#endif // USING_IPTV 
     1734 
     1735#ifdef USING_R5000 
     1736    setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000"); 
     1737#endif // USING_R5000 
    16731738} 
    16741739 
    16751740class CardID : public SelectLabelSetting, public CardInputDBStorage 
  • libs/libmythtv/tv_rec.cpp

    old new  
    5050#include "hdhrchannel.h" 
    5151#include "iptvchannel.h" 
    5252#include "firewirechannel.h" 
     53#include "r5000channel.h" 
    5354 
    5455#include "recorderbase.h" 
    5556#include "NuppelVideoRecorder.h" 
     
    5960#include "hdhrrecorder.h" 
    6061#include "iptvrecorder.h" 
    6162#include "firewirerecorder.h" 
     63#include "r5000recorder.h" 
    6264 
    6365#ifdef USING_V4L 
    6466#include "channel.h" 
     
    199201        init_run = true; 
    200202#endif 
    201203    }     
     204    else if (genOpt.cardtype == "R5000") 
     205    { 
     206#ifdef USING_R5000 
     207        channel = new R5000Channel(this, genOpt.videodev, fwOpt.model); 
     208        if (!channel->Open()) 
     209            return false; 
     210        InitChannel(genOpt.defaultinput, startchannel); 
     211        init_run = true; 
     212#endif 
     213    } 
    202214    else // "V4L" or "MPEG", ie, analog TV 
    203215    { 
    204216#ifdef USING_V4L 
     
    10171029        recorder->SetOption("mrl", genOpt.videodev); 
    10181030#endif // USING_IPTV 
    10191031    } 
     1032    else if (genOpt.cardtype == "R5000") 
     1033    { 
     1034#ifdef USING_R5000 
     1035        recorder = new R5000Recorder(this, GetR5000Channel()); 
     1036#endif // USING_R5000 
     1037    } 
    10201038    else 
    10211039    { 
    10221040#ifdef USING_V4L 
     
    12301248#endif // USING_FIREWIRE 
    12311249} 
    12321250 
     1251R5000Channel *TVRec::GetR5000Channel(void) 
     1252{ 
     1253#ifdef USING_R5000 
     1254    return dynamic_cast<R5000Channel*>(channel); 
     1255#else 
     1256    return NULL; 
     1257#endif // USING_R5000 
     1258} 
     1259 
    12331260Channel *TVRec::GetV4LChannel(void) 
    12341261{ 
    12351262#ifdef USING_V4L 
  • libs/libmythtv/transporteditor.cpp

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

    old new  
    3939class FirewireChannel; 
    4040class Channel; 
    4141class HDHRChannel; 
     42class R5000Channel; 
    4243 
    4344class MPEGStreamData; 
    4445class ProgramMapTable; 
     
    281282    HDHRChannel  *GetHDHRChannel(void); 
    282283    DVBChannel   *GetDVBChannel(void); 
    283284    FirewireChannel *GetFirewireChannel(void); 
     285    R5000Channel *GetR5000Channel(void); 
    284286    Channel      *GetV4LChannel(void); 
    285287 
    286288    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) : 
     17    DTVChannel(parent), 
     18    videodevice(_videodevice), 
     19    device(NULL), 
     20    current_channel(""), 
     21    current_mpeg_prog(0), 
     22    isopen(false) 
     23{ 
     24    int type = R5000Device::GetDeviceType(_r5ktype); 
     25    device = new R5000Device(type, videodevice); 
     26 
     27    InitializeInputs(); 
     28} 
     29 
     30bool R5000Channel::SetChannelByString(const QString &channum) 
     31{ 
     32    QString loc = LOC + QString("SetChannelByString(%1)").arg(channum); 
     33    bool ok = false; 
     34    VERBOSE(VB_CHANNEL, loc); 
     35 
     36    InputMap::const_iterator it = inputs.find(currentInputID); 
     37    if (it == inputs.end()) 
     38        return false; 
     39 
     40    QString tvformat, modulation, freqtable, freqid, dtv_si_std; 
     41    int finetune; 
     42    uint64_t frequency; 
     43    int mpeg_prog_num; 
     44    uint atsc_major, atsc_minor, mplexid, tsid, netid; 
     45    if (!ChannelUtil::GetChannelData( 
     46        (*it)->sourceid, channum, 
     47        tvformat, modulation, freqtable, freqid, 
     48        finetune, frequency, 
     49        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid, 
     50        mplexid, commfree)) 
     51    { 
     52        VERBOSE(VB_IMPORTANT, loc + " " + QString( 
     53                    "Requested channel '%1' is on input '%2' " 
     54                    "which is in a busy input group") 
     55                .arg(channum).arg(currentInputID)); 
     56 
     57        return false; 
     58    } 
     59    uint mplexid_restriction; 
     60    if (!IsInputAvailable(currentInputID, mplexid_restriction)) 
     61    { 
     62        VERBOSE(VB_IMPORTANT, loc + " " + QString( 
     63                    "Requested channel '%1' is on input '%2' " 
     64                    "which is in a busy input group") 
     65                .arg(channum).arg(currentInputID)); 
     66 
     67        return false; 
     68    } 
     69 
     70    if (!(*it)->externalChanger.isEmpty()) 
     71    { 
     72        ok = ChangeExternalChannel(freqid); 
     73        // -1 resets any state without executing a channel change 
     74        device->SetChannel(fw_opts.model, 0, mpeg_prog_num); 
     75        SetSIStandard("mpeg"); 
     76        SetDTVInfo(0,0,0,0,1); 
     77    } 
     78    else 
     79    { 
     80        ok = isopen && SetChannelByNumber(freqid, mpeg_prog_num); 
     81    } 
     82 
     83    if (ok) 
     84    { 
     85        // Set the current channum to the new channel's channum 
     86        curchannelname = QDeepCopy<QString>(channum); 
     87        (*it)->startChanNum = QDeepCopy<QString>(channum); 
     88    } 
     89 
     90    VERBOSE(VB_CHANNEL, loc + " " + ((ok) ? "success" : "failure")); 
     91 
     92    return ok; 
     93} 
     94 
     95bool R5000Channel::Open(void) 
     96{ 
     97    VERBOSE(VB_CHANNEL, LOC + "Open()"); 
     98 
     99    if (inputs.find(currentInputID) == inputs.end()) 
     100        return false; 
     101 
     102    if (!device) 
     103        return false; 
     104 
     105    if (isopen) 
     106        return true; 
     107 
     108    if (!device->OpenPort()) 
     109        return false; 
     110 
     111    isopen = true; 
     112 
     113    return true; 
     114} 
     115 
     116void R5000Channel::Close(void) 
     117{ 
     118    VERBOSE(VB_CHANNEL, LOC + "Close()"); 
     119    if (isopen) 
     120    { 
     121        device->ClosePort(); 
     122        isopen = false; 
     123    } 
     124} 
     125 
     126QString R5000Channel::GetDevice(void) const 
     127{ 
     128    return videodevice; 
     129} 
     130 
     131bool R5000Channel::SetPowerState(bool on) 
     132{ 
     133    if (!isopen) 
     134    { 
     135        VERBOSE(VB_IMPORTANT, LOC_ERR + 
     136                "SetPowerState() called on closed R5000Channel."); 
     137 
     138        return false; 
     139    } 
     140 
     141    return device->SetPowerState(on); 
     142} 
     143 
     144R5000Device::PowerState R5000Channel::GetPowerState(void) const 
     145{ 
     146    if (!isopen) 
     147    { 
     148        VERBOSE(VB_IMPORTANT, LOC_ERR + 
     149                "GetPowerState() called on closed R5000Channel."); 
     150 
     151        return R5000Device::kAVCPowerQueryFailed; 
     152    } 
     153 
     154    return device->GetPowerState(); 
     155} 
     156 
     157bool R5000Channel::Retune(void) 
     158{ 
     159    VERBOSE(VB_CHANNEL, LOC + "Retune()"); 
     160 
     161    if (R5000Device::kAVCPowerOff == GetPowerState()) 
     162    { 
     163        VERBOSE(VB_IMPORTANT, LOC_ERR + 
     164                "STB is turned off, must be on to retune."); 
     165 
     166        return false; 
     167    } 
     168 
     169    if (current_channel) 
     170        return SetChannelByNumber(current_channel, current_mpeg_prog); 
     171 
     172    return false; 
     173} 
     174 
     175bool R5000Channel::SetChannelByNumber(const QString &channel, int mpeg_prog) 
     176{ 
     177    VERBOSE(VB_CHANNEL, QString("SetChannelByNumber(%1)").arg(channel)); 
     178    current_channel = channel; 
     179    current_mpeg_prog = mpeg_prog; 
     180 
     181    if (R5000Device::kAVCPowerOff == GetPowerState()) 
     182    { 
     183        VERBOSE(VB_IMPORTANT, LOC_WARN + 
     184                "STB is turned off, must be on to set channel."); 
     185 
     186        SetSIStandard("mpeg"); 
     187        SetDTVInfo(0,0,0,0,1); 
     188 
     189        return true; // signal monitor will call retune later... 
     190    } 
     191 
     192    if (!device->SetChannel(fw_opts.model, channel, mpeg_prog)) 
     193        return false; 
     194 
     195    SetSIStandard("mpeg"); 
     196    SetDTVInfo(0,0,0,0,1); 
     197 
     198    return true; 
     199} 
  • 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// Qt headers 
     9#include <qdeepcopy.h> 
     10 
     11// MythTV headers 
     12#include "r5000device.h" 
     13#include "mythcontext.h" 
     14#include "pespacket.h" 
     15 
     16#define LOC      QString("R5kDev: ") 
     17#define LOC_WARN QString("R5kDev, Warning: ") 
     18#define LOC_ERR  QString("R5kDev, Error: ") 
     19 
     20static int r5k_init = 0; 
     21QMap<uint64_t,QString> R5000Device::s_id_to_model; 
     22QMutex                 R5000Device::s_static_lock; 
     23 
     24unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 
     25{ 
     26    R5000Device *fw = (R5000Device*) callback_data; 
     27    if (! fw) 
     28        return 0; 
     29    if (len > 0) 
     30        fw->BroadcastToListeners(tspacket, len); 
     31    return 1; 
     32} 
     33 
     34void r5000_msg(char * msg) 
     35{ 
     36    VERBOSE(VB_IMPORTANT, "R5kLib: "<<msg); 
     37} 
     38 
     39class R5kPriv 
     40{ 
     41  public: 
     42    R5kPriv() : 
     43        reset_timer_on(false), 
     44        run_port_handler(false), is_port_handler_running(false), 
     45        channel(-1), 
     46        is_streaming(false) 
     47    { 
     48    } 
     49 
     50    bool             reset_timer_on; 
     51    MythTimer        reset_timer; 
     52 
     53    bool             run_port_handler; 
     54    bool             is_port_handler_running; 
     55    QMutex           start_stop_port_handler_lock; 
     56 
     57    int              channel; 
     58 
     59    bool             is_streaming; 
     60 
     61    QDateTime        stop_streaming_timer; 
     62    pthread_t        port_handler_thread; 
     63 
     64    static QMutex           s_lock; 
     65}; 
     66QMutex          R5kPriv::s_lock; 
     67 
     68//callback functions 
     69void *r5000_device_port_handler_thunk(void *param); 
     70 
     71R5000Device::R5000Device(int type, QString serial) : 
     72    m_type(type), 
     73    m_serial(serial), 
     74    m_last_channel(""),      m_last_crc(0), 
     75    m_buffer_cleared(true), m_open_port_cnt(0), 
     76    m_lock(false),          m_priv(new R5kPriv()) 
     77{ 
     78    QMutexLocker locker(&s_static_lock); 
     79    usbdev = NULL; 
     80    if(! r5k_init) 
     81      r5k_init = r5000_init(r5000_msg); 
     82} 
     83 
     84R5000Device::~R5000Device() 
     85{ 
     86    if (usbdev) 
     87    { 
     88        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 
     89        while(usbdev) 
     90            ClosePort(); 
     91    } 
     92 
     93    if (m_priv) 
     94    { 
     95        delete m_priv; 
     96        m_priv = NULL; 
     97    } 
     98} 
     99 
     100void R5000Device::AddListener(TSDataListener *listener) 
     101{ 
     102    if (listener) 
     103    { 
     104        vector<TSDataListener*>::iterator it = 
     105            find(m_listeners.begin(), m_listeners.end(), listener); 
     106 
     107        if (it == m_listeners.end()) 
     108            m_listeners.push_back(listener); 
     109    } 
     110 
     111    VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size()); 
     112    if (!m_listeners.empty()) 
     113    { 
     114        StartStreaming(); 
     115    } 
     116} 
     117 
     118void R5000Device::RemoveListener(TSDataListener *listener) 
     119{ 
     120    vector<TSDataListener*>::iterator it = m_listeners.end(); 
     121 
     122    do 
     123    { 
     124        it = find(m_listeners.begin(), m_listeners.end(), listener); 
     125        if (it != m_listeners.end()) 
     126            m_listeners.erase(it); 
     127    } 
     128    while (it != m_listeners.end()); 
     129 
     130    VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size()); 
     131    if (m_listeners.empty()) 
     132    { 
     133        StopStreaming(); 
     134    } 
     135} 
     136 
     137bool R5000Device::StartStreaming(void) 
     138{ 
     139    if (m_priv->is_streaming) 
     140        return m_priv->is_streaming; 
     141 
     142    if (! usbdev) 
     143    { 
     144        VERBOSE(VB_IMPORTANT, LOC_ERR + "Device not open"); 
     145        return false; 
     146    } 
     147    if (r5000_start_stream(usbdev)) 
     148    { 
     149        m_priv->is_streaming = true; 
     150    } 
     151    else 
     152    { 
     153        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming "); 
     154    } 
     155 
     156    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- done"); 
     157 
     158    return m_priv->is_streaming; 
     159} 
     160 
     161bool R5000Device::StopStreaming(void) 
     162{ 
     163    if (m_priv->is_streaming) 
     164    { 
     165        VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really"); 
     166 
     167        m_priv->is_streaming = false; 
     168 
     169        r5000_stop_stream(usbdev); 
     170    } 
     171 
     172    VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 
     173 
     174    return true; 
     175} 
     176 
     177bool R5000Device::SetPowerState(bool on) 
     178{ 
     179    QMutexLocker locker(&m_lock); 
     180    QString cmdStr = (on) ? "on" : "off"; 
     181    VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr)); 
     182    r5000_power_on_off(usbdev, on); 
     183    return true; 
     184} 
     185 
     186R5000Device::PowerState R5000Device::GetPowerState(void) 
     187{ 
     188    QMutexLocker locker(&m_lock); 
     189    int on_off; 
     190 
     191    VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State"); 
     192    on_off = r5000_get_power_state(usbdev); 
     193    VERBOSE(VB_CHANNEL, LOC + (on_off ? "On" : "Off")); 
     194    return on_off ? kAVCPowerOn : kAVCPowerOff; 
     195} 
     196 
     197bool R5000Device::SetChannel(const QString &panel_model, 
     198                                const QString &channel, uint mpeg_prog) 
     199{ 
     200    VERBOSE(VB_CHANNEL, QString("SetChannel(model %1, chan %2 mpeg_prog %3)") 
     201            .arg(panel_model).arg(channel).arg(mpeg_prog)); 
     202 
     203    QMutexLocker locker(&m_lock); 
     204    VERBOSE(VB_CHANNEL, "SetChannel() -- locked"); 
     205    if(! r5000_change_channel(usbdev, channel.ascii(), mpeg_prog)) 
     206        VERBOSE(VB_IMPORTANT, LOC + "Failed to set channel"); 
     207    return true; 
     208} 
     209 
     210void R5000Device::BroadcastToListeners( 
     211    const unsigned char *data, uint dataSize) 
     212{ 
     213    if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) && 
     214        ((data[1] & 0x1f) == 0) && (data[2] == 0)) 
     215    { 
     216        ProcessPATPacket(*((const TSPacket*)data)); 
     217    } 
     218 
     219    vector<TSDataListener*>::iterator it = m_listeners.begin(); 
     220    for (; it != m_listeners.end(); ++it) 
     221        (*it)->AddData(data, dataSize); 
     222} 
     223 
     224void R5000Device::SetLastChannel(const QString &channel) 
     225{ 
     226    m_buffer_cleared = (channel == m_last_channel); 
     227    m_last_channel   = channel; 
     228 
     229    VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2") 
     230            .arg(channel).arg(m_buffer_cleared ? "yes" : "no")); 
     231} 
     232 
     233void R5000Device::ProcessPATPacket(const TSPacket &tspacket) 
     234{ 
     235    if (!tspacket.TransportError() && !tspacket.ScramplingControl() && 
     236        tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID()) 
     237    { 
     238        PESPacket pes = PESPacket::View(tspacket); 
     239        uint crc = pes.CalcCRC(); 
     240        m_buffer_cleared |= (crc != m_last_crc); 
     241        m_last_crc = crc; 
     242#if 0 
     243        VERBOSE(VB_RECORD, LOC + 
     244                QString("ProcessPATPacket: CRC 0x%1 cleared: %2") 
     245                .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no")); 
     246#endif 
     247    } 
     248    else 
     249    { 
     250        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's"); 
     251    } 
     252} 
     253 
     254QString R5000Device::GetModelName(uint vendor_id, uint model_id) 
     255{ 
     256    QMutexLocker locker(&s_static_lock); 
     257/* 
     258    if (s_id_to_model.empty()) 
     259        fw_init(s_id_to_model); 
     260 
     261    QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id]; 
     262 
     263    if (ret.isEmpty()) 
     264        return "GENERIC"; 
     265*/ 
     266    return "R5000"; 
     267} 
     268 
     269bool R5000Device::IsSTBSupported(const QString &panel_model) 
     270{ 
     271    return true; 
     272} 
     273 
     274bool R5000Device::OpenPort(void) 
     275{ 
     276    VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread"); 
     277    QMutexLocker mlocker(&m_lock); 
     278    VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread -- locked"); 
     279    if(usbdev) { 
     280        m_open_port_cnt++; 
     281        return true; 
     282    } 
     283 
     284    if(m_serial) { 
     285      VERBOSE(VB_RECORD, LOC + QString("Opening R5000 device type %1 with serial#: "+ m_serial).arg(m_type)); 
     286      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.ascii()); 
     287    } else { 
     288      VERBOSE(VB_RECORD, LOC + "Opening R5000 device with unknown serial#"); 
     289      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL); 
     290    } 
     291    if(! usbdev) { 
     292        VERBOSE(VB_IMPORTANT, LOC + "Failed to open R5000 device"); 
     293        return false; 
     294    } 
     295 
     296    VERBOSE(VB_RECORD, LOC + "Starting port handler thread"); 
     297    m_priv->run_port_handler = true; 
     298    pthread_create(&m_priv->port_handler_thread, NULL, 
     299                   r5000_device_port_handler_thunk, this); 
     300 
     301    VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to start"); 
     302    while (!m_priv->is_port_handler_running) 
     303    { 
     304        m_lock.unlock(); 
     305        usleep(5000); 
     306        m_lock.lock(); 
     307    } 
     308 
     309    VERBOSE(VB_RECORD, LOC + "Port handler thread started"); 
     310 
     311    m_open_port_cnt++; 
     312 
     313    return true; 
     314} 
     315 
     316bool R5000Device::ClosePort(void) 
     317{ 
     318    VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread"); 
     319    QMutexLocker locker(&m_priv->start_stop_port_handler_lock); 
     320    VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread -- locked"); 
     321 
     322    QMutexLocker mlocker(&m_lock); 
     323 
     324    VERBOSE(VB_RECORD, LOC + "ClosePort()"); 
     325 
     326    if (m_open_port_cnt < 1) 
     327        return false; 
     328 
     329    m_open_port_cnt--; 
     330 
     331    if (m_open_port_cnt != 0) 
     332        return true; 
     333 
     334    if (!usbdev) 
     335        return false; 
     336 
     337    VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to stop"); 
     338    m_priv->run_port_handler = false; 
     339    while (m_priv->is_port_handler_running) 
     340    { 
     341        m_lock.unlock(); 
     342        usleep(5000); 
     343        m_lock.lock(); 
     344    } 
     345    VERBOSE(VB_RECORD, LOC + "Joining port handler thread"); 
     346    pthread_join(m_priv->port_handler_thread, NULL); 
     347 
     348    r5000_close(usbdev); 
     349    usbdev = NULL; 
     350 
     351    return true; 
     352} 
     353 
     354void *r5000_device_port_handler_thunk(void *param) 
     355{ 
     356    R5000Device *mon = (R5000Device*) param; 
     357    mon->RunPortHandler(); 
     358    return NULL; 
     359} 
     360 
     361void R5000Device::RunPortHandler(void) 
     362{ 
     363    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- start"); 
     364    m_lock.lock(); 
     365    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- got first lock"); 
     366    m_priv->is_port_handler_running = true; 
     367    m_lock.unlock(); 
     368 
     369    while (m_priv->run_port_handler) 
     370    { 
     371        if (m_priv->is_streaming) { 
     372            // This will timeout after 10ms regardless of data availability 
     373            r5000_loop_iterate(usbdev, 10); 
     374        } else { 
     375            usleep(10000); 
     376        } 
     377    } 
     378 
     379    m_lock.lock(); 
     380    m_priv->is_port_handler_running = false; 
     381    m_lock.unlock(); 
     382    VERBOSE(VB_RECORD, LOC + "RunPortHandler -- end"); 
     383} 
     384 
     385QStringList R5000Device::GetSTBList(void) 
     386{ 
     387    QStringList STBList; 
     388    int i; 
     389    r5kenum_t r5k_stbs; 
     390    if(! r5k_init) { 
     391        r5k_init = r5000_init(r5000_msg); 
     392        if(! r5k_init) 
     393            return STBList; 
     394    } 
     395    if (! r5000_find_stbs(&r5k_stbs)) 
     396        VERBOSE(VB_IMPORTANT, LOC + "Locating R5000 devices failed." 
     397                                    "  This may be a permission problem"); 
     398 
     399    for (i = 0; i < r5k_stbs.count; i++) 
     400        STBList.append((char *)r5k_stbs.serial[i]); 
     401    return STBList; 
     402} 
     403 
     404int R5000Device::GetDeviceType(const QString &r5ktype) 
     405{ 
     406  QString type = r5ktype.upper(); 
     407  if(type == "DIRECTV") { 
     408    return R5K_STB_DIRECTV; 
     409  } else if(type == "VIP211/VIP622/DISH411" || 
     410            type == "VIP211/VIP422" || 
     411            type == "VIP211" || 
     412            type == "VIP411") { 
     413    return R5K_STB_VIP211; 
     414  } else if(type == "STARCHOICE/DSR") { 
     415    return R5K_STB_DSR; 
     416  } else if(type == "HDD-200") { 
     417    return R5K_STB_HDD; 
     418  } else if(type == "VIP622" || 
     419            type == "VIP722" || 
     420            type == "BEV9242") { 
     421    return R5K_STB_VIP622; 
     422  } else { 
     423    return R5K_STB_VIP211; 
     424  } 
     425} 
  • 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            _buffer_packets = !FindMPEG2Keyframes(&tspacket); 
     145            BufferedWrite(tspacket); 
     146        } 
     147        else if (GetStreamData()->IsAudioPID(lpid)) 
     148        { 
     149            _buffer_packets = !FindAudioKeyframes(&tspacket); 
     150            BufferedWrite(tspacket); 
     151        } 
     152        else if (GetStreamData()->IsListeningPID(lpid)) 
     153            GetStreamData()->HandleTSTables(&tspacket); 
     154        else if (GetStreamData()->IsWritingPID(lpid)) 
     155            BufferedWrite(tspacket); 
     156    } 
     157} 
     158 
     159void R5000Recorder::SetOptionsFromProfile(RecordingProfile *profile, 
     160                                                 const QString &videodev, 
     161                                                 const QString &audiodev, 
     162                                                 const QString &vbidev) 
     163{ 
     164    (void)videodev; 
     165    (void)audiodev; 
     166    (void)vbidev; 
     167    (void)profile; 
     168} 
     169 
     170// documented in recorderbase.cpp 
     171bool R5000Recorder::PauseAndWait(int timeout) 
     172{ 
     173    if (request_pause) 
     174    { 
     175        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause"); 
     176        if (!paused) 
     177        { 
     178            StopStreaming(); 
     179            paused = true; 
     180            pauseWait.wakeAll(); 
     181            if (tvrec) 
     182                tvrec->RecorderPaused(); 
     183        } 
     184        unpauseWait.wait(timeout); 
     185    } 
     186    if (!request_pause && paused) 
     187    { 
     188        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause"); 
     189        StartStreaming(); 
     190        paused = false; 
     191    } 
     192    return paused; 
     193} 
     194 
     195void R5000Recorder::SetStreamData(MPEGStreamData *data) 
     196{ 
     197    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 
     198    if (data == _mpeg_stream_data) 
     199    { 
     200        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 
     201        return; 
     202    } 
     203 
     204    MPEGStreamData *old_data = _mpeg_stream_data; 
     205    _mpeg_stream_data = data; 
     206    if (old_data) 
     207        delete old_data; 
     208 
     209    if (data) 
     210    { 
     211        data->AddMPEGSPListener(this); 
     212 
     213        if (data->DesiredProgram() >= 0) 
     214            data->SetDesiredProgram(data->DesiredProgram()); 
     215    } 
     216    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 
     217} 
     218 
     219void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 
     220{ 
     221    if (!pat) { 
     222        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 
     223        return; 
     224    } 
     225    int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 
     226    pat->tsheader()->SetContinuityCounter(next); 
     227    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 
     228} 
     229 
     230void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 
     231{ 
     232    if (!pmt) { 
     233        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 
     234        return; 
     235    } 
     236    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 
     237    pmt->tsheader()->SetContinuityCounter(next); 
     238    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 
     239} 
  • 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, _name), 
     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(kDTVSigMon_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 
     71void R5000SignalMonitor::deleteLater(void) 
     72{ 
     73    disconnect(); // disconnect signals we may be sending... 
     74    Stop(); 
     75    DTVSignalMonitor::deleteLater(); 
     76} 
     77 
     78/** \fn R5000SignalMonitor::Stop(void) 
     79 *  \brief Stop signal monitoring and table monitoring threads. 
     80 */ 
     81void R5000SignalMonitor::Stop(void) 
     82{ 
     83    VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 
     84    SignalMonitor::Stop(); 
     85    if (dtvMonitorRunning) 
     86    { 
     87        dtvMonitorRunning = false; 
     88        pthread_join(table_monitor_thread, NULL); 
     89    } 
     90    VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 
     91} 
     92 
     93void R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat) 
     94{ 
     95    AddFlags(kDTVSigMon_PATSeen); 
     96 
     97    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 
     98    bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared(); 
     99    if (crc_bogus && stb_needs_to_wait_for_pat && 
     100        (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) 
     101    { 
     102        VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT"); 
     103        uint tsid = pat->TransportStreamID(); 
     104        GetStreamData()->SetVersionPAT(tsid, -1,0); 
     105        return; 
     106    } 
     107 
     108    if (crc_bogus && stb_needs_to_wait_for_pat) 
     109    { 
     110        VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out"); 
     111        stb_needs_to_wait_for_pat = false; 
     112    } 
     113 
     114    DTVSignalMonitor::HandlePAT(pat); 
     115} 
     116 
     117void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt) 
     118{ 
     119    VERBOSE(VB_CHANNEL, LOC + "HandlePMT()"); 
     120 
     121    AddFlags(kDTVSigMon_PMTSeen); 
     122 
     123    if (!HasFlags(kDTVSigMon_PATMatch)) 
     124    { 
     125        GetStreamData()->SetVersionPMT(pnum, -1,0); 
     126        VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT"); 
     127        return; 
     128    } 
     129 
     130    DTVSignalMonitor::HandlePMT(pnum, pmt); 
     131} 
     132 
     133void *R5000SignalMonitor::TableMonitorThread(void *param) 
     134{ 
     135    R5000SignalMonitor *mon = (R5000SignalMonitor*) param; 
     136    mon->RunTableMonitor(); 
     137    return NULL; 
     138} 
     139 
     140void R5000SignalMonitor::RunTableMonitor(void) 
     141{ 
     142    stb_needs_to_wait_for_pat = true; 
     143    stb_wait_for_pat_timer.start(); 
     144    dtvMonitorRunning = true; 
     145 
     146    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin"); 
     147 
     148    R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel); 
     149    if (!lchan) 
     150    { 
     151        VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end"); 
     152        dtvMonitorRunning = false; 
     153        return; 
     154    } 
     155 
     156    R5000Device *dev = lchan->GetR5000Device(); 
     157 
     158    dev->OpenPort(); 
     159    dev->AddListener(this); 
     160 
     161    while (dtvMonitorRunning && GetStreamData()) 
     162        usleep(100000); 
     163 
     164    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown "); 
     165 
     166    dev->RemoveListener(this); 
     167    dev->ClosePort(); 
     168 
     169    dtvMonitorRunning = false; 
     170 
     171    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 
     172} 
     173 
     174void R5000SignalMonitor::AddData(const unsigned char *data, uint len) 
     175{ 
     176    if (!dtvMonitorRunning) 
     177        return; 
     178 
     179    if (GetStreamData()) 
     180        GetStreamData()->ProcessData((unsigned char *)data, len); 
     181} 
     182 
     183/** \fn R5000SignalMonitor::UpdateValues(void) 
     184 *  \brief Fills in frontend stats and emits status Qt signals. 
     185 * 
     186 *   This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH 
     187 *   FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain 
     188 *   statistics from the frontend. 
     189 * 
     190 *   This is automatically called by MonitorLoop(), after Start() 
     191 *   has been used to start the signal monitoring thread. 
     192 */ 
     193void R5000SignalMonitor::UpdateValues(void) 
     194{ 
     195    if (!running || exit) 
     196        return; 
     197 
     198    if (dtvMonitorRunning) 
     199    { 
     200        EmitR5000Signals(); 
     201        if (IsAllGood()) 
     202            emit AllGood(); 
     203        // TODO dtv signals... 
     204 
     205        update_done = true; 
     206        return; 
     207    } 
     208 
     209    if (stb_needs_to_wait_for_power && 
     210        (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout)) 
     211    { 
     212        return; 
     213    } 
     214    stb_needs_to_wait_for_power = false; 
     215 
     216    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 
     217 
     218    if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch)) 
     219    { 
     220        bool retried = false; 
     221        while (true) 
     222        { 
     223            R5000Device::PowerState power = fwchan->GetPowerState(); 
     224            if (R5000Device::kAVCPowerOn == power) 
     225            { 
     226                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 
     227            } 
     228            else if (R5000Device::kAVCPowerOff == power) 
     229            { 
     230                AddFlags(kFWSigMon_PowerSeen); 
     231                fwchan->SetPowerState(true); 
     232                stb_wait_for_power_timer.start(); 
     233                stb_needs_to_wait_for_power = true; 
     234            } 
     235            else 
     236            { 
     237                bool qfailed = (R5000Device::kAVCPowerQueryFailed == power); 
     238                if (qfailed && !retried) 
     239                { 
     240                    retried = true; 
     241                    continue; 
     242                } 
     243 
     244                VERBOSE(VB_RECORD, "Can't determine if STB is power on, " 
     245                        "assuming it is..."); 
     246                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 
     247            } 
     248            break; 
     249        } 
     250    } 
     251 
     252    bool isLocked = !HasFlags(kFWSigMon_WaitForPower) || 
     253        HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch); 
     254 
     255    if (isLocked && stb_needs_retune) 
     256    { 
     257        fwchan->Retune(); 
     258        isLocked = stb_needs_retune = false; 
     259    } 
     260 
     261    // Set SignalMonitorValues from info from card. 
     262    { 
     263        QMutexLocker locker(&statusLock); 
     264        signalStrength.SetValue(isLocked ? 100 : 0); 
     265        signalLock.SetValue(isLocked ? 1 : 0); 
     266    } 
     267 
     268    EmitR5000Signals(); 
     269    if (IsAllGood()) 
     270        emit AllGood(); 
     271 
     272    // Start table monitoring if we are waiting on any table 
     273    // and we have a lock. 
     274    if (isLocked && GetStreamData() && 
     275        HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 
     276                   kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 
     277                   kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 
     278    { 
     279        pthread_create(&table_monitor_thread, NULL, 
     280                       TableMonitorThread, this); 
     281 
     282        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 
     283                "Waiting for table monitor to start"); 
     284 
     285        while (!dtvMonitorRunning) 
     286            usleep(50); 
     287 
     288        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 
     289                "Table monitor started"); 
     290    } 
     291 
     292    update_done = true; 
     293} 
     294 
     295#define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \ 
     296    do { statusLock.lock(); \ 
     297         SignalMonitorValue val = SIGNAL_VAL; \ 
     298         statusLock.unlock(); \ 
     299         emit SIGNAL_FUNC(val); } while (false) 
     300 
     301/** \fn R5000SignalMonitor::EmitR5000Signals(void) 
     302 *  \brief Emits signals for lock, signal strength, etc. 
     303 */ 
     304void R5000SignalMonitor::EmitR5000Signals(void) 
     305{ 
     306    // Emit signals.. 
     307    EMIT(StatusSignalLock, signalLock); 
     308    if (HasFlags(kDTVSigMon_WaitForSig)) 
     309        EMIT(StatusSignalStrength, signalStrength); 
     310} 
     311 
     312#undef EMIT 
  • 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); 
     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    R5000Device    *device; 
     47    QString            current_channel; 
     48    uint               current_mpeg_prog; 
     49    bool               isopen; 
     50}; 
     51 
     52#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 "firewiredevice.h" 
     12#include "util.h" 
     13 
     14class R5000Channel; 
     15 
     16class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener 
     17{ 
     18    Q_OBJECT 
     19 
     20  public: 
     21    R5000SignalMonitor(int db_cardnum, R5000Channel *_channel, 
     22                          uint64_t _flags = kFWSigMon_WaitForPower, 
     23                          const char *_name = "R5000SignalMonitor"); 
     24 
     25    virtual void HandlePAT(const ProgramAssociationTable*); 
     26    virtual void HandlePMT(uint, const ProgramMapTable*); 
     27 
     28    void Stop(void); 
     29 
     30  public slots: 
     31    void deleteLater(void); 
     32 
     33  protected: 
     34    R5000SignalMonitor(void); 
     35    R5000SignalMonitor(const R5000SignalMonitor&); 
     36    virtual ~R5000SignalMonitor(); 
     37 
     38    virtual void UpdateValues(void); 
     39    void EmitR5000Signals(void); 
     40 
     41    static void *TableMonitorThread(void *param); 
     42    void RunTableMonitor(void); 
     43 
     44    bool SupportsTSMonitoring(void); 
     45 
     46    void AddData(const unsigned char *data, uint dataSize); 
     47 
     48  public: 
     49    static const uint kPowerTimeout; 
     50    static const uint kBufferTimeout; 
     51 
     52  protected: 
     53    bool               dtvMonitorRunning; 
     54    pthread_t          table_monitor_thread; 
     55    bool               stb_needs_retune; 
     56    bool               stb_needs_to_wait_for_pat; 
     57    bool               stb_needs_to_wait_for_power; 
     58    MythTimer          stb_wait_for_pat_timer; 
     59    MythTimer          stb_wait_for_power_timer; 
     60 
     61    vector<unsigned char> buffer; 
     62 
     63    static QMap<void*,uint> pat_keys; 
     64    static QMutex           pat_keys_lock; 
     65}; 
     66 
     67#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  fd = open(strmfile, O_RDONLY); 
     307#endif 
     308#ifdef R5K_RAWUSB 
     309  usbfd = open("raw.av", O_WRONLY | O_CREAT | O_TRUNC, 0666); 
     310#endif 
     311  r5kdev = (r5kdev_t *)malloc(sizeof(r5kdev_t)); 
     312  *r5kdev = r5kd; 
     313  r5kdev->urbs = NULL; 
     314  r5kdev->cb = cb; 
     315  r5kdev->cb_data = cb_data; 
     316  r5kdev->stb_type = type; 
     317  switch(type) { 
     318    case R5K_STB_VIP211: 
     319    case R5K_STB_VIP622: 
     320      vip_init(r5kdev); 
     321      break; 
     322    case R5K_STB_DIRECTV: 
     323      directv_init(r5kdev); 
     324      break; 
     325    case R5K_STB_DSR: 
     326    case R5K_STB_HDD: 
     327      sat_init(r5kdev); 
     328      break; 
     329    default: 
     330      r5000_print("Unknown STB type %d specified.\n", type); 
     331      r5kdev->stb_type = R5K_STB_VIP211; 
     332      vip_init(r5kdev); 
     333      break; 
     334  } 
     335  return r5kdev; 
     336} 
     337 
     338int r5000_close(r5kdev_t *r5kdev) 
     339{ 
     340  if(! r5kdev) 
     341    return 1; 
     342  if(r5kdev->urbs) { 
     343    if(r5kdev->streaming) 
     344      r5000_stop_stream(r5kdev); 
     345    r5000_free_urbs(r5kdev); 
     346  } 
     347  usb_close(r5kdev->handle); 
     348#ifdef R5K_RAWUSB 
     349  if(usbfd >= 0) close(usbfd); 
     350#endif 
     351  switch(r5kdev->stb_type) { 
     352    case R5K_STB_VIP211: 
     353    case R5K_STB_VIP622: 
     354      vip_free(r5kdev); 
     355      break; 
     356    case R5K_STB_DIRECTV: 
     357      directv_free(r5kdev); 
     358      break; 
     359    case R5K_STB_DSR: 
     360    case R5K_STB_HDD: 
     361      sat_free(r5kdev); 
     362      break; 
     363  } 
     364  free(r5kdev); 
     365  return 1; 
     366} 
     367 
     368int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec) 
     369{ 
     370  struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 
     371  struct usbdevfs_urb **urbs = r5kdev->urbs; 
     372  int len; 
     373  unsigned char *buf; 
     374  if(! r5kdev->streaming) 
     375    return -1; 
     376  len = usb_urb_reap(handle, urbs[r5kdev->nexturb], timeout_usec); 
     377  if(len <= 0) { 
     378    if(len != -ETIMEDOUT) 
     379      r5000_print("(%d) Reap failed at %08x: %s\n", r5kdev->nexturb, r5kdev->bytes_read, strerror(errno)); 
     380    return len; 
     381  } 
     382  buf = r5kdev->buffer + (R5K_URB_BUFFER_SIZE*r5kdev->nexturb); 
     383#ifdef R5K_RAWUSB 
     384  if(usbfd >= 0) write(usbfd, buf, len); 
     385#endif 
     386#ifdef R5K_DEBUG 
     387  if(fd >= 0) 
     388    len = read(fd, buf, len); 
     389  if(len == 0) 
     390    r5000_print("hit end of debug file\n"); 
     391#endif 
     392  r5kdev->process_block(r5kdev, buf, len); 
     393  r5kdev->bytes_read += len; 
     394  usb_urb_submit(handle, urbs[r5kdev->nexturb], NULL); 
     395  r5kdev->nexturb = (r5kdev->nexturb + 1) % MAX_URBS_IN_FLIGHT; 
     396  return 0; 
     397} 
     398 
     399//use this to read a status frame.  It doesn't do anything special 
     400//but makes it obvious what data is expected 
     401int r5000_read_status(r5kdev_t *r5kdev, unsigned char *buf) 
     402{ 
     403  return usb_bulk_read(r5kdev->handle, 129, buf, 128, 5000); 
     404} 
     405 
     406int r5000_get_power_state(r5kdev_t *r5kdev) 
     407{ 
     408  unsigned char data1[1]  = { 0x30 }; 
     409  unsigned char data2[0x80]; 
     410  int count = 10; 
     411  while(count--) { 
     412    r5000_read_status(r5kdev, data2); 
     413    usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 
     414    usleep(100000); 
     415    if(usb_bulk_read(r5kdev->handle, 1, data2, 2, 5000) == 2 && 
     416       data2[0] == 0x0a && (data2[1] & 0x4e) == 0x4c) { 
     417      // The following boxes are known to be power active low: 
     418      // 4DTV 922, Dish 622/722, Bell 9242, D* 
     419      if(r5kdev->power_active_low) 
     420        return (!(data2[1] == 0x4d)); 
     421      else 
     422        return (!!(data2[1] == 0x4d)); 
     423    } 
     424    usleep(100000); 
     425  } 
     426  r5000_print("R5000 failed to read power state.  Assuming ON state\n"); 
     427  return 1; 
     428} 
     429 
     430int r5000_send_pwr_cmd(r5kdev_t *r5kdev, unsigned char *data) 
     431{ 
     432  unsigned char data1[1]  = { 0x30 }; 
     433  unsigned char data3[0x80]; 
     434  int len; 
     435  usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 
     436  usleep(100000); 
     437  usb_bulk_write(r5kdev->handle, 1, data, r5kdev->button->len, 5000); 
     438  usleep(100000); 
     439  len = usb_bulk_read(r5kdev->handle, 1, data3, 2, 5000); 
     440  usleep(100000); 
     441  return len; 
     442} 
     443 
     444int r5000_wait_pwr(r5kdev_t *r5kdev, int on_off) 
     445{ 
     446  int new_state, count = 20; 
     447  while(count-- && (new_state = r5000_get_power_state(r5kdev)) != on_off) 
     448    usleep(100000); 
     449  //r5000_print("End state: %s\n", !on_off ? "On" : "Off"); 
     450  return new_state; 
     451} 
     452 
     453int r5000_toggle_on_off(r5kdev_t *r5kdev) 
     454{ 
     455  unsigned on_off; 
     456  on_off = r5000_get_power_state(r5kdev); 
     457  if(! r5kdev->button) { 
     458    r5000_print("No button IR commands defined for this device!\n"); 
     459    return on_off; 
     460  } 
     461  //r5000_print("Start state: %s\n", on_off ? "On" : "Off"); 
     462  r5000_send_pwr_cmd(r5kdev, r5kdev->button->power); 
     463  on_off = r5000_wait_pwr(r5kdev, ! on_off); 
     464  //r5000_print("End state: %s\n", on_off ? "On" : "Off"); 
     465  return on_off; 
     466} 
     467 
     468int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on) 
     469{ 
     470  unsigned char *pwr_command; 
     471  int on_off = r5000_get_power_state(r5kdev); 
     472  if(on_off == turn_on) { 
     473    return on_off; 
     474  } 
     475  if(! r5kdev->button) { 
     476    r5000_print("No button IR commands defined for this device!\n"); 
     477    return on_off; 
     478  } 
     479  if(r5kdev->discrete_power) { 
     480    //r5000_print("Using discrete power commands\n"); 
     481    if(turn_on) { 
     482      pwr_command = r5kdev->button->power_on; 
     483    } else { 
     484      pwr_command = r5kdev->button->power_off; 
     485    } 
     486  } else { 
     487    pwr_command = r5kdev->button->power; 
     488  } 
     489  r5000_send_pwr_cmd(r5kdev, pwr_command); 
     490  return r5000_wait_pwr(r5kdev, turn_on); 
     491} 
     492 
     493int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog) 
     494{ 
     495  unsigned char data2[0x80]; 
     496  unsigned char *ptr = NULL; 
     497  const char *p; 
     498  if(! r5kdev) 
     499    return 0; 
     500  if (chan) { 
     501    if(! r5kdev->button) { 
     502      r5000_print("No button IR commands defined for this device!\n"); 
     503    } else { 
     504      r5000_read_status(r5kdev, data2); 
     505      usb_bulk_write(r5kdev->handle, 1, r5kdev->button->clear, r5kdev->button->len, 5000); 
     506      usleep(r5kdev->button->delay); 
     507      for(p = chan; *p; p++) { 
     508        switch(*p) { 
     509          case '0' : ptr = r5kdev->button->b0; break; 
     510          case '1' : ptr = r5kdev->button->b1; break; 
     511          case '2' : ptr = r5kdev->button->b2; break; 
     512          case '3' : ptr = r5kdev->button->b3; break; 
     513          case '4' : ptr = r5kdev->button->b4; break; 
     514          case '5' : ptr = r5kdev->button->b5; break; 
     515          case '6' : ptr = r5kdev->button->b6; break; 
     516          case '7' : ptr = r5kdev->button->b7; break; 
     517          case '8' : ptr = r5kdev->button->b8; break; 
     518          case '9' : ptr = r5kdev->button->b9; break; 
     519        } 
     520        if(ptr) { 
     521          usb_bulk_write(r5kdev->handle, 1, ptr, r5kdev->button->len, 5000); 
     522          usleep(r5kdev->button->delay); 
     523        } 
     524      } 
     525      usb_bulk_write(r5kdev->handle, 1, r5kdev->button->enter, r5kdev->button->len, 5000); 
     526    } 
     527  } 
     528  r5kdev->channel = mpeg_prog; 
     529  if(r5kdev->change_channel) 
     530    r5kdev->change_channel(r5kdev); 
     531  return 1; 
     532} 
     533 
     534int r5000_find_stbs(r5kenum_t *devs) 
     535{ 
     536  devs->count = 0; 
     537  if(! r5000_usb_init) { 
     538    r5000_print("R5000 was not initialized before r5000_find_stbs().  Please call r5000_init() first\n"); 
     539    return 0; 
     540  } 
     541  devs->count = r5000_dev_map.count; 
     542  memcpy(devs->serial, r5000_dev_map.serial, 8 * r5000_dev_map.count); 
     543  return 1; 
     544} 
  • 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_MAX, 
     37} r5ktype_t; 
     38 
     39extern int r5000_init(void (*_msgcb)(char *str)); 
     40extern r5kdev_t *r5000_open(r5ktype_t type, unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), void *cb_data, const char *serial); 
     41extern int r5000_close(r5kdev_t *r5kdev); 
     42extern int r5000_start_stream(r5kdev_t *r5kdev); 
     43extern int r5000_stop_stream(r5kdev_t *r5kdev); 
     44extern int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec); 
     45extern int r5000_get_power_state(r5kdev_t *r5kdev); 
     46extern int r5000_toggle_on_off(r5kdev_t *r5kdev); 
     47extern int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on); 
     48extern int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog); 
     49extern int r5000_find_stbs(r5kenum_t *devs); 
     50#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 all DirecTV boxes 
     107extern void directv_init(r5kdev_t *r5kdev); 
     108extern void directv_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#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#include "r5k_vip_buttons.h" 
     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_directv.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 
     44struct r5000_buttons directv_button_cmd = 
     45{ 
     460x49, //len 
     47400000, //delay 
     48//button 0: 
     49{ 
     50    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     51    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     52    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     53    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     54    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     55}, 
     56//button 1: 
     57{ 
     58    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     59    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     60    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     61    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     62    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     63}, 
     64//button 2: 
     65{ 
     66    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     67    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     68    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     69    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     70    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     71}, 
     72//button 3: 
     73{ 
     74    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     75    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     76    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     77    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     78    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     79}, 
     80//button 4: 
     81{ 
     82    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     83    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     84    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     85    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     86    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     87}, 
     88//button 5: 
     89{ 
     90    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     91    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     92    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     93    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     94    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     95}, 
     96//button 6: 
     97{ 
     98    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     99    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     100    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     101    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     102    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     103}, 
     104//button 7: 
     105{ 
     106    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     107    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     108    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     109    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     110    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     111}, 
     112//button 8: 
     113{ 
     114    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     115    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     116    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     117    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 
     118    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     119}, 
     120//button 9: 
     121{ 
     122    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     123    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     124    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     125    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 
     126    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     127}, 
     128//Clear: 
     129{ 
     130    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     131    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     132    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 
     133    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
     134    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     135}, 
     136//Enter: 
     137{ 
     138    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     139    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     140    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 
     141    0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 
     142    0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     143}, 
     144//Power 
     145{ 
     146    0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 
     147    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     148    0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 
     149    0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 
     150    0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 
     151} 
     152}; 
     153 
     154static int directv_make_empty_pes(unsigned char *ptr, unsigned char type) 
     155{ 
     156  ptr[0] = 0x00; 
     157  ptr[1] = 0x00; 
     158  ptr[2] = 0x01; 
     159  ptr[3] = type; 
     160  ptr[4] = 0x00; 
     161  ptr[5] = 0x00; 
     162  ptr[6] = 0x80; 
     163  ptr[7] = 0x00; //2 MSB represent PTS/DTS flag 
     164  ptr[8] = 0x0a; 
     165  ptr[9]  = 0xff; 
     166  ptr[10] = 0xff; 
     167  ptr[11] = 0xff; 
     168  ptr[12] = 0xff; 
     169  ptr[13] = 0xff; 
     170  ptr[14] = 0xff; 
     171  ptr[15] = 0xff; 
     172  ptr[16] = 0xff; 
     173  ptr[17] = 0xff; 
     174  ptr[18] = 0xff; 
     175  return 19; 
     176} 
     177 
     178static void directv_make_pespts(unsigned char *outptr, unsigned int pts) 
     179{ 
     180        pts = htonl(pts); 
     181        unsigned char *inpts = (unsigned char *)&pts; 
     182        outptr[0] = 0x01 | 
     183                    ((inpts[0] & 0xC0) >>5); 
     184        outptr[1] = ((inpts[0] & 0x3F) << 2) | 
     185                    ((inpts[1] & 0xC0) >> 6); 
     186        outptr[2] = 0x01 | ((inpts[1] & 0x3F) << 2) | 
     187                    ((inpts[2] & 0x80) >> 6); 
     188        outptr[3] = ((inpts[2] & 0x7F) << 1) | 
     189                    ((inpts[3] & 0x80) >> 7); 
     190        outptr[4] = 0x01 | ((inpts[3] & 0x7F) << 1); 
     191} 
     192 
     193static void directv_update_video_pes(unsigned char *ptr, int pos) 
     194{ 
     195  //pos points at the 1st char after a pic start code 
     196  int picture_coding_type; 
     197  int hdr_len; 
     198  unsigned int pts1, dts1; 
     199  unsigned char *buf = ptr + pos; 
     200  picture_coding_type = (buf[1] >> 3) & 0x07; 
     201  hdr_len = (picture_coding_type > 1) ? 5 : 4; 
     202  if(buf[hdr_len + 3] == 0xb5) 
     203    hdr_len += 9; 
     204  if(buf[hdr_len + 3] == 0xb2) { 
     205    pts1 = ((buf[hdr_len+6] & 0x03)   << 30) + 
     206           ((buf[hdr_len+7] & 0x7f) << 23) + 
     207           ((buf[hdr_len+8])          << 15) + 
     208           ((buf[hdr_len+9] & 0x7f) << 8) + 
     209           buf[hdr_len+10]; 
     210    dts1 = ((buf[hdr_len+13] & 0x03)   << 30) + 
     211           ((buf[hdr_len+14] & 0x7f) << 23) + 
     212           ((buf[hdr_len+15])          << 15) + 
     213           ((buf[hdr_len+16] & 0x7f) << 8) + 
     214           buf[hdr_len+17]; 
     215    //NOTE:  This is wrong.  DSS timestamps only have a resolution of 2^32/300 
     216    //r5000_print("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0); 
     217    ptr[7] |= 0xc0; 
     218    directv_make_pespts(ptr+9, pts1/300); 
     219    ptr[9] |= 0x30; 
     220    directv_make_pespts(ptr+14, dts1/300); 
     221    ptr[14] |= 0x10; 
     222  } 
     223} 
     224 
     225static void directv_fix_audio_pts(unsigned char *ptr) 
     226{ 
     227  unsigned int pts = ((ptr[0] & 0x06) << 29) + 
     228                     (ptr[1] << 22) + 
     229                     ((ptr[2] & 0xfe) << 14) + 
     230                     (ptr[3] << 7) + 
     231                     (ptr[4] >> 1); 
     232  directv_make_pespts(ptr, pts/300); 
     233  ptr[0] |= 0x20; 
     234} 
     235 
     236 
     237static void directv_write_ts(r5kdev_t *r5kdev, unsigned char *ptr, int len, int pid, int start, int *cc) 
     238{ 
     239  int stuff = 184 - len; 
     240  //Note:  we know that there are 188 bytes allocated before 'ptr' 
     241  //       that we can use for the header 
     242  if(stuff > 0) { 
     243    int stuff1 = stuff; 
     244    while(stuff1 > 2) { 
     245      *--ptr = 0xff; 
     246      stuff1--; 
     247    } 
     248    if(stuff1 == 2) { 
     249      *--ptr = 0x00; 
     250    } 
     251    *--ptr = stuff - 1; 
     252    *--ptr = 0x30 | *cc; 
     253  } else { 
     254    *--ptr = 0x10 | *cc; 
     255  } 
     256  *--ptr = pid & 0xff; 
     257  *--ptr = (start << 6) | (pid >> 8); 
     258  *--ptr = 0x47; 
     259  r5kdev->cb(ptr, 188, r5kdev->cb_data); 
     260  *cc = (*cc+1) & 0x0f; 
     261} 
     262 
     263static void directv_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 
     264{ 
     265  int i; 
     266  struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 
     267  for(i = 0; i < len; i+=2) { 
     268    unsigned char data = buf[i]; 
     269    unsigned char type = buf[i+1]; 
     270    if(0xff == type) { 
     271      //video 
     272      dtv->video[dtv->vpos++] = data; 
     273      if(dtv->vpos > 4 && dtv->video[dtv->vpos-2] == 0x01 && 
     274         dtv->video[dtv->vpos-3] == 0x00 && dtv->video[dtv->vpos-4] == 0x00) { 
     275        if (data == 0xe0) { 
     276          //HD video header (PES) 
     277          directv_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 
     278          dtv->pat_pmt_count++; 
     279          dtv->video[0] = 0x00; 
     280          dtv->video[1] = 0x00; 
     281          dtv->video[2] = 0x01; 
     282          dtv->video[3] = 0xe0; 
     283          dtv->vpos = 4; 
     284          dtv->vstart = 1; 
     285          dtv->vstate = data; 
     286        } else if (data == 0xb3 || data == 0x00) { 
     287          if (dtv->vstate == 0xff) { 
     288            dtv->vstate = data; 
     289            directv_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 
     290            dtv->pat_pmt_count++; 
     291            //Create a PES header, but no PTS/DTS info yet so just use stuffing bytes 
     292            dtv->vpos = directv_make_empty_pes(dtv->video, 0xe0); 
     293            dtv->video[dtv->vpos++] = 0x00; 
     294            dtv->video[dtv->vpos++] = 0x00; 
     295            dtv->video[dtv->vpos++] = 0x01; 
     296            dtv->video[dtv->vpos++] = data; 
     297            dtv->vstart = 1; 
     298            dtv->pic_pos = dtv->vpos; 
     299          } 
     300        } 
     301      } 
     302      if(dtv->vpos == 188) { 
     303        if (dtv->vstate == 0x00) 
     304          //We found pic frame without a PES header (SD) 
     305          directv_update_video_pes(dtv->video, dtv->pic_pos); 
     306        directv_write_ts(r5kdev, dtv->video, 184, DTV_VPID, dtv->vstart, &dtv->video_cc); 
     307        dtv->pat_pmt_count++; 
     308        dtv->video[0] = dtv->video[184]; 
     309        dtv->video[1] = dtv->video[185]; 
     310        dtv->video[2] = dtv->video[186]; 
     311        dtv->video[3] = dtv->video[187]; 
     312        dtv->vpos = 4; 
     313        dtv->vstart = 0; 
     314        dtv->vstate = 0xff; 
     315      } 
     316    } else if(0xfe == type) { 
     317      //audio 
     318      dtv->audio[dtv->apos++] = data; 
     319      dtv->alen--; 
     320      if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xbd && dtv->audio[dtv->apos-4] == 0x01 && 
     321         dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 
     322        dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 
     323        directv_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 
     324        dtv->pat_pmt_count++; 
     325        dtv->audio[0] = 0x00; 
     326        dtv->audio[1] = 0x00; 
     327        dtv->audio[2] = 0x01; 
     328        dtv->audio[3] = 0xbd; 
     329        dtv->audio[4] = dtv->audio[dtv->apos-2]; 
     330        dtv->audio[5] = data; 
     331        dtv->apos = 6; 
     332        dtv->astart = 1; 
     333        r5kdev->pmt[1].id = 0x81; //AC3 
     334      } else if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xc0 && dtv->audio[dtv->apos-4] == 0x01 && 
     335           dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 
     336        dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 
     337        directv_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 
     338        dtv->pat_pmt_count++; 
     339        dtv->audio[0] = 0x00; 
     340        dtv->audio[1] = 0x00; 
     341        dtv->audio[2] = 0x01; 
     342        dtv->audio[3] = 0xc0; 
     343        dtv->audio[4] = (dtv->alen + 3) >> 8; 
     344        dtv->audio[5] = (dtv->alen + 3) & 0xff; 
     345        dtv->audio[6] = 0x80; 
     346        dtv->audio[7] = 0x80; 
     347        dtv->audio[8] = 0x05; 
     348        dtv->apos = 9; 
     349        dtv->astart = 1; 
     350        r5kdev->pmt[1].id = 0x04; //MP2 
     351      } else if(dtv->apos == 190) { 
     352        if(dtv->astart && dtv->audio[3] == 0xc0) 
     353          directv_fix_audio_pts(dtv->audio+9); 
     354        directv_write_ts(r5kdev, dtv->audio, 184, DTV_APID, dtv->astart, &dtv->audio_cc); 
     355        dtv->pat_pmt_count++; 
     356        dtv->audio[0] = dtv->audio[184]; 
     357        dtv->audio[1] = dtv->audio[185]; 
     358        dtv->audio[2] = dtv->audio[186]; 
     359        dtv->audio[3] = dtv->audio[187]; 
     360        dtv->audio[4] = dtv->audio[188]; 
     361        dtv->audio[5] = dtv->audio[189]; 
     362        dtv->apos = 6; 
     363        dtv->astart = 0; 
     364      } 
     365    } 
     366  } 
     367  if(r5kdev->pmt[1].id && dtv->pat_pmt_count > DTV_PAT_PMT_COUNT) { 
     368    r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 
     369    r5000_send_pmt(r5kdev); 
     370    dtv->pat_pmt_count = 0; 
     371  } 
     372} 
     373 
     374static void directv_start_stream(r5kdev_t *r5kdev) 
     375{ 
     376  struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 
     377  dtv->vstart = 0; 
     378  dtv->astart = 0; 
     379  dtv->vpos = 0; 
     380  dtv->apos = 0; 
     381  dtv->video_cc = 0; 
     382  dtv->audio_cc = 0; 
     383  dtv->vstate = 0; 
     384  dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 
     385} 
     386void directv_init(r5kdev_t *r5kdev) 
     387{ 
     388  struct r5000_dtv *dtv = (struct r5000_dtv *)calloc(1, sizeof(struct r5000_dtv)); 
     389  dtv->video = dtv->vbuf + 188; 
     390  dtv->audio = dtv->abuf + 188; 
     391  dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 
     392  dtv->vstate = 0xff; 
     393  r5kdev->stbdata = dtv; 
     394  r5kdev->pmt[0].id = 0x02; //MPEG2 
     395  r5kdev->pmt[0].pid = DTV_VPID; 
     396  r5kdev->pmt[0].desc = r5000_pmt_video_desc; 
     397  r5kdev->pmt[1].id = 0x00; 
     398  r5kdev->pmt[1].pid = DTV_APID; 
     399  r5kdev->pmt[1].desc = r5000_pmt_audio_desc; 
     400  r5kdev->num_pmt_entries = 2; 
     401  r5kdev->process_block = directv_process_block; 
     402  r5kdev->start_stream  = directv_start_stream; 
     403  r5kdev->button = &directv_button_cmd; 
     404  r5kdev->power_active_low = 1; 
     405  r5kdev->read_words = 1; 
     406} 
     407 
     408void directv_free(r5kdev_t *r5kdev) 
     409{ 
     410  free(r5kdev->stbdata); 
     411} 
  • 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  {0}, 
     59}; 
     60 
     61extern char strmfile[255]; 
     62void help(char *cmdline) { 
     63  int i; 
     64  printf("%s <-t type> <--m command> [--c channel] [--s serial] [-h]\n", cmdline); 
     65  printf("\t-t/--type type     : set STB type to type.  'type' can be either\n"); 
     66  printf("\t                     a numerical value or string.  Valid types are:\n"); 
     67  for(i = 0; stb_names[i][0] != 0; i++) { 
     68    printf("\t\t%d: %s\n", i, stb_names[i]); 
     69  } 
     70  printf("\t-m/--cmd command   : set command to execute.  'command' can be either\n"); 
     71  printf("\t                     a numerical value or string.  Valid commands are:\n"); 
     72  for(i = 0; i < MAX_CMD; i++) { 
     73    printf("\t\t%d: %s\n", i, cmd_names[i]); 
     74  } 
     75  printf("\t-c/--channel       : set channel to read (this does NOT tune\n"); 
     76  printf("\t-s/--serial serial : set serial number\n"); 
     77  printf("\t-h/--help          : show this help message\n"); 
     78  exit(0); 
     79} 
     80 
     81void printstr(char *str) 
     82{ 
     83  fprintf(stderr, "%s", str); 
     84} 
     85 
     86static unsigned char buffer[1000189]; 
     87static unsigned char *ptr = buffer; 
     88unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 
     89{ 
     90    int fd = *(int *) callback_data; 
     91    if (len <= 0) 
     92      return 0; 
     93    if(memcpy(ptr, tspacket, len)); 
     94    ptr+=len; 
     95    if(ptr-buffer > 1000000) { 
     96      write(fd, buffer, ptr-buffer); 
     97      ptr = buffer; 
     98    } 
     99    return 1; 
     100} 
     101 
     102int main(int argc, char *argv[]) 
     103{ 
     104  r5kdev_t *usbdev = NULL; 
     105  int glblfd, i, j; 
     106  unsigned char buf[0x80]; 
     107  int stb = -1; 
     108  int cmd = -1; 
     109  const char *channel = NULL; 
     110  const char *serial = NULL; 
     111  int runtime = 10; 
     112  struct option long_options[] = { 
     113    {"type", required_argument, NULL, 't'}, 
     114    {"cmd", required_argument, NULL, 'm'}, 
     115    {"channel", required_argument, NULL, 'c'}, 
     116    {"serial", required_argument, NULL, 's'}, 
     117    {"time", required_argument, NULL, 'i'}, 
     118    {"dbgfile", required_argument, NULL, 'D'}, 
     119    {"help", no_argument , NULL, 'h'}, 
     120    {0, 0, 0, 0} 
     121  }; 
     122  while (1) { 
     123    char c; 
     124    c = getopt_long (argc, argv, 
     125                     "t:m:c:s:hD:i:", 
     126                     long_options, NULL); 
     127    if(c == EOF) 
     128      break; 
     129    switch(c) { 
     130      case 't': 
     131      { 
     132        char *ptr; 
     133        int i; 
     134        stb = strtol(optarg, &ptr, 10); 
     135        if(ptr == optarg) { 
     136          stb = -1; 
     137          for(i = 0; stb_names[i][0] != 0; i++) { 
     138            if(strncasecmp(optarg, stb_names[i], strlen(stb_names[i])) == 0) { 
     139              stb = i; 
     140              break; 
     141            } 
     142          } 
     143          if(stb == -1) { 
     144            fprintf(stderr, "Unknown STB type: %s\n", optarg); 
     145            exit(-1); 
     146          } 
     147        } else if(stb < 0 || stb >= R5K_STB_MAX) { 
     148          fprintf(stderr, "Illegal STB type: %d\n", stb); 
     149          exit(-1); 
     150        } 
     151        break; 
     152      } 
     153      case 'm': 
     154      { 
     155        char *ptr; 
     156        int i; 
     157        cmd = strtol(optarg, &ptr, 10); 
     158        if(ptr == optarg) { 
     159          cmd = -1; 
     160          for(i = 0; i < MAX_CMD; i++) { 
     161            if(strncasecmp(optarg, cmd_names[i], strlen(cmd_names[i])) == 0) { 
     162              cmd = i; 
     163              break; 
     164            } 
     165          } 
     166          if(cmd == -1) { 
     167            fprintf(stderr, "Unknown command: %d\n", optarg); 
     168            exit(-1); 
     169          } 
     170        } else if(cmd < 0 || cmd >= MAX_CMD) { 
     171          fprintf(stderr, "Illegal command: %d\n", cmd); 
     172          exit(-1); 
     173        } 
     174        break; 
     175      } 
     176      case 'c': 
     177      { 
     178        int ok = 1; 
     179        char *p; 
     180        if(! strlen(optarg)) { 
     181          fprintf(stderr, "Couldn't parse channel '%s'\n", channel); 
     182          ok = 0; 
     183        } 
     184        for(p = optarg; *p; p++) { 
     185          if(*p < '0' || *p > '9') { 
     186            fprintf(stderr, "Couldn't parse channel '%s'\n", channel); 
     187            ok = 0; 
     188            break; 
     189          } 
     190        } 
     191        if(ok) 
     192          channel = optarg; 
     193        break; 
     194      } 
     195      case 'i': 
     196      { 
     197        char *ptr; 
     198        runtime = strtol(optarg, &ptr, 0); 
     199        if(optarg == ptr) { 
     200          fprintf(stderr, "Couldn't parse time '%s'\n", optarg); 
     201        } 
     202        break; 
     203      } 
     204      case 's': 
     205        serial = optarg; 
     206        break; 
     207      case 'h': 
     208        help(argv[0]); 
     209        break; 
     210      case 'D': 
     211        #ifdef R5K_DEBUG 
     212          strncpy(strmfile, optarg, 255); 
     213        #else 
     214          fprintf(stderr, "--dbgfile only supported in debug mode.\nMake sure you know what you are doing!\n"); 
     215          exit(-1); 
     216        #endif 
     217    } 
     218  } 
     219  if(cmd == -1 || stb == -1) { 
     220    fprintf(stderr, "Must specify --cmd and --stb\n"); 
     221    exit(-1); 
     222  } 
     223  r5000_init(printstr); 
     224  if(cmd == SCAN_DEVICES) { 
     225    r5kenum_t devs; 
     226    printf("Scanning for R5000 devices\n"); 
     227    if(! r5000_find_stbs(&devs)) { 
     228      printf("Failed to initialize r5000 devices\n"); 
     229    } 
     230    for(i=0; i < devs.count; i++) { 
     231      printf("Found: %s\n", devs.serial[i]); 
     232    } 
     233    goto end; 
     234  } 
     235  usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 
     236  if(! usbdev) { 
     237    fprintf(stderr, "R5000 device could not be found/opened\n"); 
     238    exit(-1); 
     239  } 
     240  glblfd=open("raw.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 
     241  if(cmd == TOGGLE_POWER) { 
     242    int new_state; 
     243    printf("Toggling On/Off\n"); 
     244    new_state = r5000_toggle_on_off(usbdev); 
     245    printf("Turned power %s\n", new_state ? "On" : "Off"); 
     246  } 
     247  if(cmd == TURN_ON) { 
     248    int new_state; 
     249    printf("Turning STB On\n"); 
     250    new_state = r5000_power_on_off(usbdev, 1); 
     251    printf("Turned power %s\n", new_state ? "On" : "Off"); 
     252  } 
     253  if(cmd == TURN_OFF) { 
     254    int new_state; 
     255    printf("Turning STB Off\n"); 
     256    new_state = r5000_power_on_off(usbdev, 0); 
     257    printf("Turned power %s\n", new_state ? "On" : "Off"); 
     258  } 
     259  if(cmd == CHECK_POWER) { 
     260    int new_state; 
     261    new_state = r5000_get_power_state(usbdev); 
     262    printf("Power is currently %s\n", new_state ? "On" : "Off"); 
     263  } 
     264  if(cmd == CHANGE_CHANNEL) { 
     265    if(! channel) { 
     266      printf("Must specify a channel when using '-m CHANGE_CHANNEL'\n"); 
     267      exit(-1); 
     268    } 
     269    printf("Setting channel %s\n", channel); 
     270    r5000_change_channel(usbdev, channel, 0); 
     271  } 
     272  if(cmd == OPEN_CLOSE) { 
     273    int on_off; 
     274    printf("Doing open/close\n"); 
     275    on_off = r5000_get_power_state(usbdev); 
     276    printf("State1: %d\n", on_off); 
     277    r5000_close(usbdev); 
     278    printf("Closed\n"); 
     279    sleep(1); 
     280    usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 
     281    printf("ReOpened\n"); 
     282    on_off = r5000_get_power_state(usbdev); 
     283    printf("State2: %d\n", on_off); 
     284  } 
     285  if(cmd == READ_STREAM || cmd == MULTI_READ) { 
     286    if(channel) { 
     287      uint c; 
     288      char *ptr; 
     289      printf("Setting channel %d\n"); 
     290      c = strtol(channel, &ptr, 0); 
     291      r5000_change_channel(usbdev, NULL, c); 
     292    } 
     293    printf("Reading stream\n"); 
     294    r5000_start_stream(usbdev); 
     295    time_t t = time(NULL); 
     296    while (time(NULL) - t < runtime) 
     297    { 
     298      // This will timeout after 1ms regardless of data availability 
     299      //usleep(10000); 
     300      r5000_loop_iterate(usbdev, 10); 
     301    } 
     302    r5000_stop_stream(usbdev); 
     303  } 
     304  if(cmd == MULTI_READ) { 
     305    printf("Reading stream again\n"); 
     306    close(glblfd); 
     307    glblfd=open("raw_1.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 
     308    sleep(1); 
     309    r5000_start_stream(usbdev); 
     310    time_t t = time(NULL); 
     311    while (time(NULL) - t < 10) 
     312    { 
     313      // This will timeout after 1ms regardless of data availability 
     314      //usleep(10000); 
     315      r5000_loop_iterate(usbdev, 10); 
     316    } 
     317    r5000_stop_stream(usbdev); 
     318  } 
     319  if(cmd == MULTI_OPEN) { 
     320    printf("Doing multi-open\n"); 
     321    while(usbdev) { 
     322      time_t t; 
     323      r5000_start_stream(usbdev); 
     324      t = time(NULL); 
     325      while (time(NULL) - t < 2) 
     326      { 
     327        // This will timeout after 1ms regardless of data availability 
     328        //usleep(10000); 
     329        r5000_loop_iterate(usbdev, 10); 
     330      } 
     331      r5000_stop_stream(usbdev); 
     332      r5000_close(usbdev); 
     333      printf("Closed\n"); 
     334      sleep(1); 
     335      usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 
     336      printf("ReOpened %s\n", serial); 
     337    } 
     338    r5000_start_stream(usbdev); 
     339    time_t t = time(NULL); 
     340    while (time(NULL) - t < 10) 
     341    { 
     342      // This will timeout after 1ms regardless of data availability 
     343      //usleep(10000); 
     344      r5000_loop_iterate(usbdev, 10); 
     345    } 
     346    r5000_stop_stream(usbdev); 
     347  } 
     348end: 
     349  r5000_close(usbdev); 
     350  if(ptr != buffer) 
     351    write(glblfd, buffer, ptr-buffer); 
     352  close(glblfd); 
     353} 
  • new file libs/libmythtv/r5000/r5k_vip_buttons.h

    - +  
     1struct r5000_buttons vip_button_cmd = 
     2{ 
     30x40, //len 
     4400000, //delay 
     5//button 0: 
     6{ 
     7 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     8 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     9 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     10 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     11}, 
     12//button 1: 
     13{ 
     14 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     15 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     16 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     17 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     18}, 
     19//button 2: 
     20{ 
     21 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     22 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     23 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     24 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     25}, 
     26//button 3: 
     27{ 
     28 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     29 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     30 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     31 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     32}, 
     33//button 4: 
     34{ 
     35 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     36 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     37 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     38 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     39}, 
     40//button 5: 
     41{ 
     42 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     43 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     44 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     45 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     46}, 
     47//button 6: 
     48{ 
     49 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     50 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     51 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     52 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     53}, 
     54//button 7: 
     55{ 
     56 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     57 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     58 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     59 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     60}, 
     61//button 8: 
     62{ 
     63 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     64 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     65 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     66 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     67}, 
     68//button 9: 
     69{ 
     70 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 
     71 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     72 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     73 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     74}, 
     75//Clear: 
     76{ 
     77 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     78 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     79 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     80 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     81}, 
     82//Enter: 
     83{ 
     84 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     85 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     86 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 
     87 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     88}, 
     89//Power 
     90{ 
     91 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     92 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     93 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     94 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     95}, 
     96//Power-On 
     97{ 
     98 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     99 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     100 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 
     101 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     102}, 
     103//Power-Off 
     104{ 
     105 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 
     106 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 
     107 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 
     108 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 
     109}, 
     110}; 
  • 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. 
     14Make sure you have the following installed: 
     15  lsusb (in Debian/Ubuntu this is in the usbutils package) 
     16  fxload 
     171) Locate the device using lsusb: 
     18lsusb 
     19... 
     20Bus 001 Device 026: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit 
     212)Install the firmware (this often needs to be done via sudo/root) 
     22(depending on where usbfs is mounted): 
     23fxload -t fx2 -D /dev/bus/usb/001/026 -I r5000.hex -m 0666 
     24or 
     25fxload -t fx2 -D /proc/bus/usb/001/026 -I r5000.hex -m 0666 
     26(note that 001 is the Bus and 026 is the Device from lsusb) 
     27 
     283) Ensure that the firmware loaded: 
     29lsusb 
     30... 
     31Bus 001 Device 028: ID 0547:1002 Anchor Chips, Inc. 
     32(Note that is has a completely different name now) 
     33 
     344)ensure that the usbtest module did not load: 
     35lsmod | grep usbtest 
     36If you see the usbtest module you'll need to blacklist it and/or rmmod it 
     37############################################################################### 
     38############################################################################### 
     39 
     40Before trying to use the R5000 in mythtv, make sure it is working in r5ktest 
     41./r5ktest -t 0 -m 6 
     42Scanning for R5000 devices 
     43Found: xxxxxxx 
     44 
     45If you see something like: 
     46    R5000 initialization failed at stage 1: 
     47        Expected 1 bytes, but got -1 bytes 
     48    R5000 failed to locate any R5000 devices.  Are you sure you have 
     49        permissions set properly? 
     50Then you likely do not have permissions to access the usb device.  Try running 
     51as root. 
     52 
     53next do: 
     54./r5ktest --help 
     55and choose the correct type for your STB: 
     56   vip211 : VIP211 and VIP411 
     57   vip622 : VIP622, VIP722, BEV9242 
     58   hdd: 
     59   dsr: 
     60   directv: 
     61 
     62Now try a few commands to make sure they work properly: 
     63   ./r5ktest --type vip211 --cmd TURN_ON 
     64   ./r5ktest --type vip211 --cmd TURN_OFF 
     65   ./r5ktest --type vip211 --cmd CHANGE_CHANNEL -c <channel number> 
     66   ./r5ktest --type vip211 --cmd OPEN_CLOSE 
     67 
     68############################################################################### 
     69############################################################################### 
     70 
     71Configure mythtv: 
     72Go into myth-setup and select the R5000 device, and the relevant STB. 
     73Configure a Video Source 
     74Configure an Input 
     75To 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 
     76If 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 
     77 
     78Some notes: 
     79Only ViP style STBs (Dish Network and BEV) and DirectTV STBs have channel-change capabilities.  Others need an external program 
     80 
     81At 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. 
     82