Ticket #1648: firewire-sm-v21.patch

File firewire-sm-v21.patch, 90.0 KB (added by danielk, 20 years ago)

Updated patch, adds locking to LinuxFirewireDevice and restores auto-reset

  • libs/libmythtv/firewirechannel.cpp

     
    11/**
    22 *  FirewireChannel
    33 *  Copyright (c) 2005 by Jim Westfall
    4  *  SA3250HD support Copyright (c) 2005 by Matt Porter
    5  *  SA4200HD/Alternate 3250 support Copyright (c) 2006 by Chris Ingrassia
    64 *  Distributed as part of MythTV under GPL v2 and later.
    75 */
    86
    9 
    10 #include <iostream>
     7// MythTV headers
    118#include "mythcontext.h"
    129#include "firewirechannel.h"
     10#include "linuxfirewiredevice.h"
    1311
    1412class TVRec;
    1513
    16 #define LOC QString("FireChan: ")
    17 #define LOC_ERR QString("FireChan, Error: ")
     14#define LOC QString("FireChan(%1): ").arg(GetDevice())
     15#define LOC_WARN QString("FireChan(%1), Warning: ").arg(GetDevice())
     16#define LOC_ERR QString("FireChan(%1), Error: ").arg(GetDevice())
    1817
    19 #ifndef AVC1394_PANEL_COMMAND_PASS_THROUGH
    20 #define AVC1394_PANEL_COMMAND_PASS_THROUGH     0x000007C00
    21 #endif
    22 
    23 #ifndef AVC1394_PANEL_OPERATION_0
    24 #define AVC1394_PANEL_OPERATION_0              0x000000020
    25 #endif
    26 
    27 #define DCT6200_CMD0  (AVC1394_CTYPE_CONTROL | \
    28                        AVC1394_SUBUNIT_TYPE_PANEL | \
    29                        AVC1394_SUBUNIT_ID_0 | \
    30                        AVC1394_PANEL_COMMAND_PASS_THROUGH | \
    31                        AVC1394_PANEL_OPERATION_0)
    32 
    33 // SA3250HD defines
    34 #define AVC1394_SA3250_OPERAND_KEY_PRESS        0xE7
    35 #define AVC1394_SA3250_OPERAND_KEY_RELEASE      0x67
    36 
    37 #define SA3250_CMD0   (AVC1394_CTYPE_CONTROL | \
    38                        AVC1394_SUBUNIT_TYPE_PANEL | \
    39                        AVC1394_SUBUNIT_ID_0 | \
    40                        AVC1394_PANEL_COMMAND_PASS_THROUGH)
    41 #define SA3250_CMD1   (0x04 << 24)
    42 #define SA3250_CMD2    0xff000000
    43 
    44 // power defines
    45 #define AVC1394_CMD_OPERAND_POWER_STATE        0x7F
    46 #define STB_POWER_STATE   (AVC1394_CTYPE_STATUS | \
    47                            AVC1394_SUBUNIT_TYPE_UNIT | \
    48                            AVC1394_SUBUNIT_ID_IGNORE | \
    49                            AVC1394_COMMAND_POWER | \
    50                            AVC1394_CMD_OPERAND_POWER_STATE)
    51 
    52 #define STB_POWER_ON      (AVC1394_CTYPE_CONTROL | \
    53                            AVC1394_SUBUNIT_TYPE_UNIT | \
    54                            AVC1394_SUBUNIT_ID_IGNORE | \
    55                            AVC1394_COMMAND_POWER | \
    56                            AVC1394_CMD_OPERAND_POWER_ON)
    57 
    58 static bool is_supported(const QString &model)
     18LinuxFirewireChannel::LinuxFirewireChannel(
     19    FireWireDBOptions firewire_opts, TVRec *parent) :
     20    FirewireChannelBase(parent),
     21    fw_opts(firewire_opts),
     22    device(new LinuxFirewireDevice(
     23               fw_opts.port, fw_opts.node, fw_opts.speed,
     24               LinuxFirewireDevice::kConnectionP2P ==
     25               (uint) fw_opts.connection)),
     26    current_channel(0),
     27    is_port_open(false)
    5928{
    60     return ((model == "DCT-6200") ||
    61             (model == "SA3250HD") ||
    62             (model == "SA4200HD"));
    6329}
    6430
    65 FirewireChannel::FirewireChannel(FireWireDBOptions firewire_opts,
    66                                  TVRec *parent)
    67     : FirewireChannelBase(parent), fw_opts(firewire_opts), fwhandle(NULL)
     31LinuxFirewireChannel::~LinuxFirewireChannel(void)
    6832{
    69 }
    70 
    71 FirewireChannel::~FirewireChannel(void)
    72 {
    7333    Close();
    7434}
    7535
    76 bool FirewireChannel::SetChannelByNumber(int channel)
     36bool LinuxFirewireChannel::Retune(void)
    7737{
    78     // Change channel using internal changer
     38    VERBOSE(VB_CHANNEL, LOC + "Retune()");
    7939
    80     if (!is_supported(fw_opts.model))
     40    if (FirewireDevice::kAVCPowerOff == GetPowerState())
    8141    {
    8242        VERBOSE(VB_IMPORTANT, LOC_ERR +
    83                 QString("Model: '%1' ").arg(fw_opts.model) +
    84                 "is not supported by internal channel changer.");
     43                "STB is turned off, must be on to retune.");
     44
    8545        return false;
    8646    }
    8747
    88     int dig[3];
    89     dig[0] = (channel % 1000) / 100;
    90     dig[1] = (channel % 100)  / 10;
    91     dig[2] = (channel % 10);
     48    if (current_channel)
     49        return SetChannelByNumber(current_channel);
    9250
    93     if (fw_opts.model == "DCT-6200")
    94     {
    95         VERBOSE(VB_CHANNEL, LOC +
    96                 QString("Channel1: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
    97                 .arg(dig[0]).arg(dig[1])
    98                 .arg(dig[2]).arg(DCT6200_CMD0 | dig[0], 0, 16)
    99                 .arg(DCT6200_CMD0 | dig[1], 0, 16)
    100                 .arg(DCT6200_CMD0 | dig[2], 0, 16));
     51    return false;
     52}
    10153
    102         for (uint i = 0; i < 3 ;i++)
    103         {
    104             quadlet_t cmd[2] =  { DCT6200_CMD0 | dig[i], 0x0, };
    105             if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 2, 1))
    106             {
    107                  VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    108                  return false;
    109             }
    110             usleep(500000);
    111         }
    112     }
    113     else if (fw_opts.model == "SA3250HD")
     54bool LinuxFirewireChannel::SetChannelByNumber(int channel)
     55{
     56    current_channel = channel;
     57
     58    if (FirewireDevice::kAVCPowerOff == GetPowerState())
    11459    {
    115         dig[0] |= 0x30;
    116         dig[1] |= 0x30;
    117         dig[2] |= 0x30;
     60        VERBOSE(VB_IMPORTANT, LOC_WARN +
     61                "STB is turned off, must be on to set channel.");
    11862
    119         quadlet_t cmd[3] =
    120         {
    121             SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
    122             SA3250_CMD1 | (dig[2] << 16) | (dig[1] << 8) | dig[0],
    123             SA3250_CMD2,
    124         };
     63        SetSIStandard("mpeg");
     64        SetCachedATSCInfo(QString("%1-1").arg(channel));
    12565
    126         VERBOSE(VB_CHANNEL, LOC +
    127                 QString("Channel2: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
    128                 .arg(dig[0] & 0xf).arg(dig[1] & 0xf)
    129                 .arg(dig[2] & 0xf)
    130                 .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
    131                 .arg(cmd[2], 0, 16));
    132 
    133         if(!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
    134         {
    135             VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    136             return false;
    137         }
    138 
    139         cmd[0] = SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;
    140         cmd[1] = SA3250_CMD1 | (dig[0] << 16) | (dig[1] << 8) | dig[2];
    141         cmd[2] = SA3250_CMD2;
    142 
    143         VERBOSE(VB_CHANNEL, LOC +
    144                 QString("Channel3: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
    145                 .arg(dig[0] & 0xf).arg(dig[1] & 0xf)
    146                 .arg(dig[2] & 0xf)
    147                 .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
    148                 .arg(cmd[2], 0, 16));
    149 
    150         if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
    151         {
    152             VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    153             return false;
    154         }
     66        return true; // signal monitor will call retune later...
    15567    }
    156     else if (fw_opts.model == "SA4200HD")
    157     {
    158         quadlet_t cmd[3] =
    159         {
    160             SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
    161             SA3250_CMD1 | (channel << 8),
    162             SA3250_CMD2,
    163         };
    16468
    165         VERBOSE(VB_CHANNEL, LOC +
    166                 QString("SA4200Channel: %1 cmds: 0x%2 0x%3 0x%4")
    167                 .arg(channel).arg(cmd[0], 0, 16)
    168                 .arg(cmd[1], 0, 16)
    169                 .arg(cmd[2], 0, 16));
     69    if (!device->SetChannel(fw_opts.model, channel))
     70        return false;
    17071
    171         if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
    172         {
    173             VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    174             return false;
    175         }
    176     }
     72    SetSIStandard("mpeg");
     73    SetCachedATSCInfo(QString("%1-1").arg(channel));
    17774
    17875    return true;
    17976}
    18077
    181 bool FirewireChannel::OpenFirewire(void)
     78bool LinuxFirewireChannel::OpenFirewire(void)
    18279{
    183     if (!is_supported(fw_opts.model))
     80    if (is_port_open)
     81        return true;
     82
     83    if (!LinuxFirewireDevice::IsSTBSupported(fw_opts.model))
    18484    {
    18585        VERBOSE(VB_IMPORTANT, LOC_ERR +
    18686                QString("Model: '%1' ").arg(fw_opts.model) +
    18787                "is not supported by internal channel changer.");
    188         return false;
    189     }
    19088
    191     // Open channel
    192     fwhandle = raw1394_new_handle_on_port(fw_opts.port);
    193     if (!fwhandle)
    194     {
    195         VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle " +
    196                 QString("for port: %1").arg(fw_opts.port));
    19789        return false;
    19890    }
    19991
    200     VERBOSE(VB_CHANNEL, LOC + "Allocated raw1394 handle " +
    201             QString("for port %1").arg(fw_opts.port));
    202 
    203     // verify node looks like a stb
    204     if (!avc1394_check_subunit_type(fwhandle, fw_opts.node,
    205                                     AVC1394_SUBUNIT_TYPE_TUNER))
    206     {
    207         VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit "
    208                 "type tuner.").arg(fw_opts.node));
    209         CloseFirewire();
     92    if (!device->OpenPort())
    21093        return false;
    211     }
    21294
    213     if (!avc1394_check_subunit_type(fwhandle, fw_opts.node,
    214                                     AVC1394_SUBUNIT_TYPE_PANEL))
     95    if (!device->IsSTB())
    21596    {
    216         VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit "
    217                 "type panel.").arg(fw_opts.node));
    218         CloseFirewire();
     97        device->ClosePort();
    21998        return false;
    22099    }
    221100
    222     // check power, power on if off
    223     if (GetPowerState() == Off)
    224     {
    225         quadlet_t *rval, response, cmd = STB_POWER_ON;
    226         VERBOSE(VB_IMPORTANT, LOC + QString("Powering on (cmd: 0x%1)")
    227                                             .arg(cmd, 0, 16));
    228         rval = avc1394_transaction_block(fwhandle, fw_opts.node, &cmd, 1, 1);
    229         if (rval)
    230         {
    231             response = rval[0];
     101    is_port_open = true;
    232102
    233             if (AVC1394_MASK_RESPONSE(response) == AVC1394_RESPONSE_ACCEPTED)
    234             {
    235                 VERBOSE(VB_IMPORTANT, LOC + QString("Power on cmd successful "
    236                                                     "(0x%1)")
    237                                                     .arg(response, 0, 16));
    238                 // allow some time for the stb to power on
    239                 sleep(3);
    240                 if (GetPowerState() == Off)
    241                 {
    242                     VERBOSE(VB_IMPORTANT, LOC + "STB is still off!?");
    243                     return false;
    244                 }
    245                 return true;
    246             }
    247             else
    248             {
    249                 VERBOSE(VB_IMPORTANT, LOC + QString("Power on cmd failed "
    250                                                     "(0x%1)")
    251                                                     .arg(response, 0, 16));
    252                 return false;
    253             }
    254         }
    255         else
    256         {
    257             VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)");
    258             return false;
    259         }
    260     }
    261103    return true;
    262104}
    263105
    264 void FirewireChannel::CloseFirewire(void)
     106void LinuxFirewireChannel::CloseFirewire(void)
    265107{
    266     VERBOSE(VB_CHANNEL, LOC + "Releasing raw1394 handle");
    267     raw1394_destroy_handle(fwhandle);
     108    if (!is_port_open)
     109        return;
     110
     111    device->ClosePort();
     112    is_port_open = false;
    268113}
    269114
    270 FirewireChannel::PowerState FirewireChannel::GetPowerState(void)
     115bool LinuxFirewireChannel::SetPowerState(bool on)
    271116{
    272     quadlet_t *rval, response, cmd = STB_POWER_STATE;
     117    return device->SetPowerState(on);
     118}
    273119
    274     VERBOSE(VB_CHANNEL, LOC + QString("Requesting STB Power State (cmd: 0x%1)")
    275                                       .arg(STB_POWER_STATE, 0, 16));
    276     rval = avc1394_transaction_block(fwhandle, fw_opts.node, &cmd, 1, 1);
    277 
    278     if (rval)
    279     {
    280         response = rval[0];
    281 
    282         if (AVC1394_MASK_RESPONSE(response) == AVC1394_RESPONSE_IMPLEMENTED)
    283         {
    284             if ((response & 0xFF) == AVC1394_CMD_OPERAND_POWER_ON)
    285             {
    286                 VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: ON (0x%1)")
    287                                                   .arg(response, 0, 16));
    288                 return On;
    289             }
    290             else if ((response & 0xFF) == AVC1394_CMD_OPERAND_POWER_OFF)
    291             {
    292                 VERBOSE(VB_IMPORTANT, LOC + QString("STB Power State: OFF "
    293                                                     "(0x%1)")
    294                                                     .arg(response, 0, 16));
    295                 return Off;
    296             }
    297             else
    298             {
    299                 VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: "
    300                                                   "Unknown Response (0x%1)")
    301                                                   .arg(response, 0, 16));
    302                 return Failed;
    303             }
    304         }
    305         else
    306         {
    307             VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: Failed (0x%1)")
    308                                               .arg(response, 0, 16));
    309             return Failed;
    310         }
    311     }
    312     VERBOSE(VB_CHANNEL, LOC + "Failed to get STB Power State");
    313     return Failed;
     120FirewireDevice::PowerState LinuxFirewireChannel::GetPowerState(void) const
     121{
     122    return device->GetPowerState();
    314123}
  • libs/libmythtv/firewirerecorderbase.h

     
    1212#include "tspacket.h"
    1313#include "streamlisteners.h"
    1414
     15class TVRec;
     16class FirewireChannelBase;
     17
    1518/** \class FirewireRecorderBase
    1619 *  \brief This is a specialization of DTVRecorder used to
    1720 *         handle DVB and ATSC streams from a firewire input.
     
    2528    friend class TSPacketProcessor;
    2629
    2730  public:
    28     FirewireRecorderBase(TVRec *rec);
    29     ~FirewireRecorderBase();
     31    virtual ~FirewireRecorderBase();
    3032 
    3133    // Commands
    3234    void StartRecording(void);
     
    4143    void SetStreamData(MPEGStreamData*);
    4244
    4345    // Gets
    44     MPEGStreamData* StreamData(void) { return _mpeg_stream_data; }
     46    MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; }
    4547
    4648    // MPEG Single Program
    4749    void HandleSingleProgramPAT(ProgramAssociationTable*);
    4850    void HandleSingleProgramPMT(ProgramMapTable*);
    4951
     52    // Factory
     53    static FirewireRecorderBase *Init(
     54        TVRec *rec, FirewireChannelBase *channel);
     55
     56  protected:
     57    FirewireRecorderBase(TVRec *rec);
     58
    5059  private:
    5160    virtual void Close() = 0;
    52     virtual void start() = 0;
    53     virtual void stop() = 0;
    54     virtual bool grab_frames() = 0;
     61    virtual void StartStreaming(void) = 0;
     62    virtual void StopStreaming(void) = 0;
    5563
    5664    MPEGStreamData  *_mpeg_stream_data;
    5765    TSStats          _ts_stats;   
  • libs/libmythtv/firewirechannelbase.h

     
    88#ifndef LIBMYTHTV_FIREWIRECHANNELBASE_H
    99#define LIBMYTHTV_FIREWIRECHANNELBASE_H
    1010
    11 #include <qstring.h>
    12 #include "tv_rec.h"
    13 #include "channelbase.h"
     11#include "dtvchannel.h"
     12#include "firewiredevice.h"
    1413
    15 #include "mythconfig.h"
     14class TVRec;
     15class FireWireDBOptions;
    1616
    17 namespace AVS
     17class FirewireChannelBase : public DTVChannel
    1818{
    19   class AVCDeviceController;
    20   class AVCDevice;
    21 }
    22 
    23 class FirewireChannelBase : public ChannelBase
    24 {
    2519  public:
    26     FirewireChannelBase(TVRec *parent)   
    27         : ChannelBase(parent), isopen(false) { }
    28     ~FirewireChannelBase() { Close(); }
     20    // Commands
     21    virtual bool Open(void);
     22    virtual void Close(void);
     23    virtual bool SwitchToInput(const QString &inputname, const QString &chan);
     24    virtual bool SwitchToInput(int newcapchannel, bool setstarting)
     25        { (void)newcapchannel; (void)setstarting; return false; }
    2926
    30     bool Open(void);
    31     void Close(void);
     27    virtual bool TuneMultiplex(uint /*mplexid*/, QString /*inputname*/)
     28        { return false; }
     29    virtual bool Tune(const DTVMultiplex &/*tuning*/, QString /*inputname*/)
     30        { return false; }
     31    virtual bool Retune(void)
     32        { return false; }
    3233
    3334    // Sets
    34     bool SetChannelByString(const QString &chan);
     35    virtual bool SetChannelByString(const QString &chan);
    3536    virtual bool SetChannelByNumber(int channel) = 0;
     37    virtual bool SetPowerState(bool /*on*/) = 0;
    3638
    3739    // Gets
    38     bool IsOpen(void) const { return isopen; }
     40    virtual bool IsOpen(void) const { return isopen; }
     41    virtual FirewireDevice::PowerState GetPowerState(void) const = 0;
    3942
    40     // Commands
    41     bool SwitchToInput(const QString &inputname, const QString &chan);
    42     bool SwitchToInput(int newcapchannel, bool setstarting)
    43         { (void)newcapchannel; (void)setstarting; return false; }
     43    // Factory method
     44    static FirewireChannelBase *Init(
     45        const FireWireDBOptions &firewire_opts, TVRec *parent);
    4446
     47  protected:
     48    FirewireChannelBase(TVRec *parent) :
     49        DTVChannel(parent), isopen(false) { }
     50    ~FirewireChannelBase() { Close(); }
     51
    4552  private:
    46     virtual bool OpenFirewire() = 0;
    47     virtual void CloseFirewire() = 0;
     53    virtual bool OpenFirewire(void) = 0;
     54    virtual void CloseFirewire(void) = 0;
    4855
    4956  protected:
    5057    bool isopen;
  • libs/libmythtv/libmythtv.pro

     
    380380    using_firewire  {
    381381        HEADERS += firewirechannelbase.h       firewirerecorderbase.h
    382382        SOURCES += firewirechannelbase.cpp     firewirerecorderbase.cpp
     383        HEADERS += firewiresignalmonitor.h     firewiredevice.h
     384        SOURCES += firewiresignalmonitor.cpp
    383385
    384386        macx {
    385387            HEADERS += darwinfirewirechannel.h       darwinfirewirerecorder.h
     
    391393        !macx {
    392394            HEADERS += firewirechannel.h       firewirerecorder.h
    393395            SOURCES += firewirechannel.cpp     firewirerecorder.cpp
     396            HEADERS += linuxfirewiredevice.h
     397            SOURCES += linuxfirewiredevice.cpp
    394398        }
    395399
    396400        DEFINES += USING_FIREWIRE
  • libs/libmythtv/darwinfirewirerecorder.cpp

     
    1111#undef always_inline
    1212#include <AVCVideoServices/AVCVideoServices.h>
    1313
    14 DarwinFirewireRecorder::DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner)
    15  : FirewireRecorderBase(rec),
    16    capture_device(
    17        dynamic_cast<DarwinFirewireChannel*>(tuner)->GetAVCDevice()
    18    ),
    19    message_log(NULL),
    20    video_stream(NULL),
    21    isopen(false)
    22 {;}
     14DarwinFirewireRecorder::DarwinFirewireRecorder(
     15    TVRec *rec, DarwinFirewireChannel *channel) :
     16    FirewireRecorderBase(rec),
     17    capture_device(channel->GetAVCDevice()),
     18    message_log(NULL),
     19    video_stream(NULL),
     20    isopen(false)
     21{
     22    SetStreamData(new MPEGStreamData(1, true));
     23}
    2324
    2425DarwinFirewireRecorder::~DarwinFirewireRecorder()
    2526{
     
    196197    this->message_log = 0;
    197198}
    198199
    199 void DarwinFirewireRecorder::start()
     200void DarwinFirewireRecorder::StartStreaming(void)
    200201{
    201202    VERBOSE(VB_RECORD, "Firewire: Starting video stream");
    202203    this->capture_device->StartAVCDeviceStream(this->video_stream);
    203204}
    204205
    205 void DarwinFirewireRecorder::stop()
     206void DarwinFirewireRecorder::StopStreaming(void)
    206207{
    207208    VERBOSE(VB_RECORD, "Firewire: Stopping video stream");
    208209    this->capture_device->StopAVCDeviceStream(this->video_stream);
    209210}
    210 
    211 bool DarwinFirewireRecorder::grab_frames()
    212 {
    213     usleep(1000000 / 2);  // 2 times a second
    214     return true;
    215 }       
    216 
    217 void DarwinFirewireRecorder::SetOption(const QString &name, const QString &value)
    218 {
    219     (void)name;
    220     (void)value;
    221 }
    222 
    223 void DarwinFirewireRecorder::SetOption(const QString &name, int value)
    224 {
    225     (void)name;
    226     (void)value;
    227 }
  • libs/libmythtv/dbcheck.cpp

     
    1010#include "mythdbcon.h"
    1111
    1212/// This is the DB schema version expected by the running MythTV instance.
    13 const QString currentDatabaseVersion = "1172";
     13const QString currentDatabaseVersion = "1173";
    1414
    1515static bool UpdateDBVersionNumber(const QString &newnumber);
    1616static bool performActualUpdate(const QString updates[], QString version,
     
    27722772            return false;
    27732773    }
    27742774
     2775    if (dbver == "1172")
     2776    {
     2777        // Add Firewire and DBox2 default recording profiles..
     2778        const QString updates[] = {
     2779"UPDATE capturecard SET channel_timeout = 9000 WHERE cardtype = 'FIREWIRE';",
     2780""
     2781};
     2782        if (!performActualUpdate(updates, "1173", dbver))
     2783            return false;
     2784    }
     2785
    27752786//"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22
    27762787//"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22
    27772788//"ALTER TABLE recordedmarkup DROP COLUMN offset;" in 0.22
  • libs/libmythtv/signalmonitor.h

     
    285285    return (CardUtil::IsDVBCardType(cardtype) ||
    286286            (cardtype.upper() == "HDTV")      ||
    287287            (cardtype.upper() == "HDHOMERUN") ||
     288            (cardtype.upper() == "FIREWIRE")  ||
    288289            (cardtype.upper() == "FREEBOX"));
    289290}
    290291
  • libs/libmythtv/firewirerecorderbase.cpp

     
    55 */
    66
    77// MythTV includes
     8#include "mythconfig.h" // for CONFIG_DARWIN
    89#include "firewirerecorderbase.h"
    910#include "mythcontext.h"
    1011#include "mpegtables.h"
    1112#include "mpegstreamdata.h"
    1213#include "tv_rec.h"
    1314
     15#ifdef CONFIG_DARWIN
     16#   include "darwinfirewirechannel.h"
     17#   include "darwinfirewirerecorder.h"
     18#else
     19#   include "firewirechannel.h"
     20#   include "firewirerecorder.h"
     21#   include "linuxfirewiredevice.h"
     22#endif
     23
    1424#define LOC QString("FireRecBase: ")
    1525#define LOC_ERR QString("FireRecBase, Error: ")
    1626
    1727const int FirewireRecorderBase::kTimeoutInSeconds = 15;
    1828
     29FirewireRecorderBase *FirewireRecorderBase::Init(
     30    TVRec *rec, FirewireChannelBase *channel)
     31{
     32#ifdef CONFIG_DARWIN
     33    DarwinFirewireChannel *dfch =
     34        dynamic_cast<DarwinFirewireChannel*>(channel);
     35    if (dfch)
     36        return new DarwinFirewireRecorder(rec, channel);
     37#else
     38    LinuxFirewireChannel *lfch =
     39        dynamic_cast<LinuxFirewireChannel*>(channel);
     40    if (lfch)
     41        return new LinuxFirewireRecorder(rec, lfch);
     42#endif
     43
     44    return NULL;
     45}
     46
    1947FirewireRecorderBase::FirewireRecorderBase(TVRec *rec)
    2048    : DTVRecorder(rec), _mpeg_stream_data(NULL)
    2149{
    22     SetStreamData(new MPEGStreamData(1, true));
    2350}
    2451
    2552FirewireRecorderBase::~FirewireRecorderBase()
     
    3966    _request_recording = true;
    4067    _recording = true;
    4168   
    42     start();
     69    StartStreaming();
    4370
    44     while(_request_recording) {
    45        if (PauseAndWait())
    46            continue;
    47 
    48        if (!grab_frames())
    49        {
    50            _error = true;
    51            return;
    52        }
     71    while (_request_recording)
     72    {
     73        if (!PauseAndWait())
     74            usleep(250 * 1000);
    5375    }       
    5476   
    55     stop();
     77    StopStreaming();
    5678    FinishRecording();
    5779
    5880    _recording = false;
     
    6789        return;
    6890 
    6991    if (tspacket.HasAdaptationField())
    70         StreamData()->HandleAdaptationFieldControl(&tspacket);
     92        GetStreamData()->HandleAdaptationFieldControl(&tspacket);
    7193 
    7294    if (tspacket.HasPayload())
    7395    {
    7496        const unsigned int lpid = tspacket.PID();
    7597 
    7698        // Pass or reject packets based on PID, and parse info from them
    77         if (lpid == StreamData()->VideoPIDSingleProgram())
     99        if (lpid == GetStreamData()->VideoPIDSingleProgram())
    78100        {
    79101            _buffer_packets = !FindMPEG2Keyframes(&tspacket);
    80102            BufferedWrite(tspacket);
    81103        }
    82         else if (StreamData()->IsAudioPID(lpid))
     104        else if (GetStreamData()->IsAudioPID(lpid))
    83105            BufferedWrite(tspacket);
    84         else if (StreamData()->IsListeningPID(lpid))
    85             StreamData()->HandleTSTables(&tspacket);
    86         else if (StreamData()->IsWritingPID(lpid))
     106        else if (GetStreamData()->IsListeningPID(lpid))
     107            GetStreamData()->HandleTSTables(&tspacket);
     108        else if (GetStreamData()->IsWritingPID(lpid))
    87109            BufferedWrite(tspacket);
    88110    }
    89111 
     
    108130{
    109131    if (request_pause)
    110132    {
     133        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause");
    111134        if (!paused)
    112135        {
    113             stop();
     136            StopStreaming();
    114137            paused = true;
    115138            pauseWait.wakeAll();
    116139            if (tvrec)
     
    120143    }
    121144    if (!request_pause && paused)
    122145    {
    123         start();
     146        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause");
     147        StartStreaming();
    124148        paused = false;
    125149    }
    126150    return paused;
  • libs/libmythtv/firewirerecorder.cpp

     
    88#include <pthread.h>
    99#include <sys/select.h>
    1010
    11 // C++ includes
    12 #include <iostream>
    13 using namespace std;
     11// Linux C includes
     12#include <libraw1394/raw1394.h>
    1413
    1514// MythTV includes
    1615#include "firewirerecorder.h"
     16#include "firewirechannel.h"
     17#include "linuxfirewiredevice.h"
    1718#include "mythcontext.h"
    1819#include "mpegtables.h"
    1920#include "mpegstreamdata.h"
    2021#include "tv_rec.h"
    2122
    22 #define LOC QString("FireRec: ")
    23 #define LOC_ERR QString("FireRec, Error: ")
     23#define LOC QString("FireRec(%1): ").arg(channel->GetDevice())
     24#define LOC_ERR QString("FireRec(%1), Error: ").arg(tvrec->GetDevice())
    2425
    25 const int FirewireRecorder::kBroadcastChannel    = 63;
    26 const int FirewireRecorder::kConnectionP2P       = 0;
    27 const int FirewireRecorder::kConnectionBroadcast = 1;
    28 const uint FirewireRecorder::kMaxBufferedPackets = 2000;
    29 
    30 // callback function for libiec61883
    31 int fw_tspacket_handler(unsigned char *tspacket, int /*len*/,
    32                         uint dropped, void *callback_data)
     26LinuxFirewireRecorder::LinuxFirewireRecorder(
     27    TVRec *rec,
     28    LinuxFirewireChannel *chan) :
     29    FirewireRecorderBase(rec), channel(chan), isopen(false)
    3330{
    34     if (dropped)
    35     {
    36         VERBOSE(VB_RECORD, LOC_ERR +
    37                 QString("Dropped %1 packet(s).").arg(dropped));
    38     }
    39 
    40     if (SYNC_BYTE != tspacket[0])
    41     {
    42         VERBOSE(VB_IMPORTANT, LOC_ERR + "TS packet out of sync.");
    43         return 1;
    44     }
    45 
    46     FirewireRecorder *fw = (FirewireRecorder*) callback_data;
    47     if (fw)
    48         fw->ProcessTSPacket(*(reinterpret_cast<TSPacket*>(tspacket)));
    49 
    50     return (fw) ? 1 : 0;
    5131}
    5232
    53 static QString speed_to_string(uint speed)
     33LinuxFirewireRecorder::~LinuxFirewireRecorder()
    5434{
    55     if (speed > RAW1394_ISO_SPEED_400)
    56         return QString("Invalid Speed (%1)").arg(speed);
    57 
    58     static const uint speeds[] = { 100, 200, 400, };
    59     return QString("%1Mbps").arg(speeds[speed]);
     35    Close();
    6036}
    6137
    62 bool FirewireRecorder::Open(void)
     38bool LinuxFirewireRecorder::Open(void)
    6339{
    64      if (isopen)
    65          return true;
     40     if (!isopen)
     41         isopen = channel->GetFirewireDevice()->OpenPort();
    6642
    67      VERBOSE(VB_RECORD, LOC +
    68              QString("Initializing Port: %1, Node: %2, Speed: %3")
    69              .arg(fwport).arg(fwnode).arg(speed_to_string(fwspeed)));
    70 
    71      fwhandle = raw1394_new_handle_on_port(fwport);
    72      if (!fwhandle)
    73      {
    74          VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " +
    75                  QString("port: %1, bailing").arg(fwport) + ENO);
    76          return false;
    77      }
    78 
    79      if (kConnectionP2P == fwconnection)
    80      {
    81           VERBOSE(VB_RECORD, LOC + "Creating P2P Connection " +
    82                   QString("with Node: %1").arg(fwnode));
    83           fwchannel = iec61883_cmp_connect(fwhandle,
    84                                            fwnode | 0xffc0, &fwoplug,
    85                                            raw1394_get_local_id(fwhandle),
    86                                            &fwiplug, &fwbandwidth);
    87           if (fwchannel > -1)
    88           {
    89               VERBOSE(VB_RECORD, LOC +
    90                       QString("Created Channel: %1, "
    91                               "Bandwidth Allocation: %2")
    92                       .arg(fwchannel).arg(fwbandwidth));
    93           }
    94      }
    95      else
    96      {
    97          fwchannel = kBroadcastChannel - fwnode;
    98 
    99          VERBOSE(VB_RECORD, LOC + "Creating Broadcast Connection " +
    100                  QString("with Node: %1, Channel: %2").arg(fwnode)
    101                  .arg(fwchannel));
    102          if (iec61883_cmp_create_bcast_output(fwhandle,
    103                                               fwnode | 0xffc0, 0,
    104                                               fwchannel,
    105                                               fwspeed) != 0)
    106          {
    107              VERBOSE(VB_IMPORTANT, LOC + "Failed to create connection");
    108              // release raw1394 object;
    109              raw1394_destroy_handle(fwhandle);
    110              return false;
    111          }
    112          fwbandwidth = 0;
    113      }
    114 
    115      fwmpeg = iec61883_mpeg2_recv_init(fwhandle, fw_tspacket_handler, this);
    116      if (!fwmpeg)
    117      {
    118          VERBOSE(VB_IMPORTANT, LOC +
    119                  "Unable to init iec61883_mpeg2 object, bailing" + ENO);
    120 
    121          // release raw1394 object;
    122          raw1394_destroy_handle(fwhandle);
    123          return false;
    124      }
    125 
    126      // Set buffered packets size
    127      size_t buffer_size = gContext->GetNumSetting("HDRingbufferSize",
    128                                                   50 * TSPacket::SIZE);
    129      size_t buffered_packets = min(buffer_size / 4,
    130                                    (size_t) kMaxBufferedPackets);
    131      iec61883_mpeg2_set_buffers(fwmpeg, buffered_packets);
    132      VERBOSE(VB_IMPORTANT, LOC +
    133              QString("Buffered packets %1 (%2 KB)")
    134              .arg(buffered_packets).arg(buffered_packets * 4));
    135 
    136      // Set speed if needed.
    137      // Probably shouldn't even allow user to set,
    138      // 100Mbps should be more the enough.
    139      int curspeed = iec61883_mpeg2_get_speed(fwmpeg);
    140      if (curspeed != fwspeed)
    141      {
    142          VERBOSE(VB_RECORD, LOC +
    143                  QString("Changing Speed %1 -> %2")
    144                  .arg(speed_to_string(curspeed))
    145                  .arg(speed_to_string(fwspeed)));
    146 
    147          iec61883_mpeg2_set_speed(fwmpeg, fwspeed);
    148          if (fwspeed != iec61883_mpeg2_get_speed(fwmpeg))
    149          {
    150               VERBOSE(VB_IMPORTANT, LOC +
    151                       "Unable to set firewire speed, continuing");
    152          }
    153      }
    154 
    155      fwfd = raw1394_get_fd(fwhandle);
    156 
    157      return isopen = true;
     43     return isopen;
    15844}
    15945
    160 void FirewireRecorder::Close(void)
     46void LinuxFirewireRecorder::Close(void)
    16147{
    162     if (!isopen)
    163         return;
    164 
    165     isopen = false;
    166 
    167     VERBOSE(VB_RECORD, LOC + "Releasing iec61883_mpeg2 object");
    168     iec61883_mpeg2_close(fwmpeg);
    169 
    170     if (fwconnection == kConnectionP2P && fwchannel > -1)
     48    if (isopen)
    17149    {
    172         VERBOSE(VB_RECORD, LOC +
    173                 QString("Disconnecting channel %1").arg(fwchannel));
    174 
    175         iec61883_cmp_disconnect(fwhandle, fwnode | 0xffc0, fwoplug,
    176                                 raw1394_get_local_id (fwhandle),
    177                                 fwiplug, fwchannel, fwbandwidth);
     50        channel->GetFirewireDevice()->ClosePort();
     51        isopen = false;
    17852    }
     53}
    17954
    180     VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle");
    181     raw1394_destroy_handle(fwhandle);
     55void LinuxFirewireRecorder::StartStreaming(void)
     56{
     57    channel->GetFirewireDevice()->AddListener(this);
    18258}
    18359
    184 bool FirewireRecorder::grab_frames()
     60void LinuxFirewireRecorder::StopStreaming(void)
    18561{
    186     struct timeval tv;
    187     fd_set rfds;
     62    channel->GetFirewireDevice()->RemoveListener(this);
     63}
    18864
    189     FD_ZERO(&rfds);
    190     FD_SET(fwfd, &rfds);
    191     tv.tv_sec = kTimeoutInSeconds;
    192     tv.tv_usec = 0;
     65void LinuxFirewireRecorder::AddData(const unsigned char *data, uint len)
     66{
     67    //cout<<":";
    19368
    194     if (select(fwfd + 1, &rfds, NULL, NULL, &tv)  <= 0)
    195     {
    196         VERBOSE(VB_IMPORTANT, LOC +
    197                 QString("No Input in %1 seconds [P:%2 N:%3] (select)")
    198                 .arg(kTimeoutInSeconds).arg(fwport).arg(fwnode));
    199         return false;
     69    uint bufsz = buffer.size();
     70    if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) &&
     71        (TSPacket::SIZE > bufsz))
     72    {
     73        if (bufsz)
     74            buffer.clear();
     75
     76        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data)));
     77        return;
    20078    }
    20179
    202     int ret = raw1394_loop_iterate(fwhandle);
    203     if (ret)
     80    buffer.insert(buffer.end(), data, data + len);
     81    bufsz += len;
     82
     83    int sync_at = -1;
     84    for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
    20485    {
    205         VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " +
    206                 QString("returned %1").arg(ret));
    207         return false;
     86        if (buffer[i] == SYNC_BYTE)
     87            sync_at = i;
    20888    }
    20989
    210     return true;
    211 }
     90    if (sync_at < 0)
     91        return;
    21292
    213 void FirewireRecorder::SetOption(const QString &name, const QString &value)
    214 {
    215     if (name == "model")
    216         fwmodel = value;
    217 }
     93    if (bufsz < 30 * TSPacket::SIZE)
     94        return; // build up a little buffer
    21895
    219 void FirewireRecorder::SetOption(const QString &name, int value)
    220 {
    221     if (name == "port")
    222         fwport = value;
    223     else if (name == "node")
    224         fwnode = value;
    225     else if (name == "speed")
     96    while (sync_at + TSPacket::SIZE < bufsz)
    22697    {
    227         if (RAW1394_ISO_SPEED_100 != value &&
    228             RAW1394_ISO_SPEED_200 != value &&
    229             RAW1394_ISO_SPEED_400 != value)
    230         {
    231             VERBOSE(VB_IMPORTANT, LOC_ERR +
    232                     QString("Unknown speed '%1', will use 100Mbps")
    233                     .arg(value));
     98        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
     99                              &buffer[0] + sync_at)));
    234100
    235             value = RAW1394_ISO_SPEED_100;
    236         }
    237         fwspeed = value;
     101        sync_at += TSPacket::SIZE;
    238102    }
    239     else if (name == "connection")
    240     {
    241         if (kConnectionP2P       != value &&
    242             kConnectionBroadcast != value)
    243         {
    244             VERBOSE(VB_IMPORTANT, LOC_ERR +
    245                     QString("Unknown connection type '%1', will use P2P")
    246                     .arg(fwconnection));
    247103
    248             fwconnection = kConnectionP2P;
    249         }
    250         fwconnection = value;
    251     }
     104    buffer.erase(buffer.begin(), buffer.begin() + sync_at);
     105
     106    return;
    252107}
  • libs/libmythtv/firewirerecorder.h

     
    44 *  Distributed as part of MythTV under GPL v2 and later.
    55 */
    66
    7 #ifndef FIREWIRERECORDER_H_
    8 #define FIREWIRERECORDER_H_
     7#ifndef _LINUX_FIREWIRE_RECORDER_H_
     8#define _LINUX_FIREWIRE_RECORDER_H_
    99
    1010#include "firewirerecorderbase.h"
    11 #include "tsstats.h"
    12 #include <libraw1394/raw1394.h>
    13 #include <libiec61883/iec61883.h>
     11#include "linuxfirewiredevice.h"
    1412
    15 /** \class FirewireRecorder
    16  *  \brief Linux FirewireRFecorder
     13class LinuxFirewireChannel;
     14
     15/** \class LinuxFirewireRecorder
     16 *  \brief Linux Firewire Recorder
    1717 *
    1818 *  \sa FirewireRecorderBase
    1919 */
    20 class FirewireRecorder : public FirewireRecorderBase
     20class LinuxFirewireRecorder :
     21    public FirewireRecorderBase, public TSDataListener
    2122{
    22     friend int fw_tspacket_handler(unsigned char*,int,uint,void*);
    23 
    2423  public:
    25     FirewireRecorder(TVRec *rec)
    26         : FirewireRecorderBase(rec),
    27         fwport(-1),     fwchannel(-1), fwspeed(-1),   fwbandwidth(-1),
    28         fwfd(-1),       fwconnection(kConnectionP2P),
    29         fwoplug(-1),    fwiplug(-1),   fwmodel(""),   fwnode(0),
    30         fwhandle(NULL), fwmpeg(NULL),  isopen(false) { }
    31    ~FirewireRecorder() { Close(); }
     24    LinuxFirewireRecorder(TVRec *rec, LinuxFirewireChannel *chan);
     25    ~LinuxFirewireRecorder();
    3226
    3327    // Commands
    34     bool Open(void);
    35 
    36     // Sets
    37     void SetOption(const QString &name, const QString &value);
    38     void SetOption(const QString &name, int value);
    39 
    40   private:
     28    bool Open(void);
     29    void StartStreaming(void);
     30    void StopStreaming(void);
    4131    void Close(void);
    42     void start() { iec61883_mpeg2_recv_start(fwmpeg, fwchannel); }
    43     void stop() { iec61883_mpeg2_recv_stop(fwmpeg); }
    44     bool grab_frames();
    4532
    4633  private:
    47     int              fwport;
    48     int              fwchannel;
    49     int              fwspeed;
    50     int              fwbandwidth;
    51     int              fwfd;
    52     int              fwconnection;
    53     int              fwoplug;
    54     int              fwiplug;
    55     QString          fwmodel;
    56     nodeid_t         fwnode;
    57     raw1394handle_t  fwhandle;
    58     iec61883_mpeg2_t fwmpeg;
    59     bool             isopen;
     34    void AddData(const unsigned char *data, uint dataSize);
    6035
    61     static const int kBroadcastChannel;
    62     static const int kConnectionP2P;
    63     static const int kConnectionBroadcast;
    64     static const uint kMaxBufferedPackets;
     36  private:
     37    LinuxFirewireChannel *channel;
     38    bool                  isopen;
     39    vector<unsigned char> buffer;
    6540};
    6641
    67 #endif
     42#endif // _LINUX_FIREWIRE_RECORDER_H_
  • libs/libmythtv/darwinfirewirechannel.cpp

     
    1515#undef always_inline
    1616#include <AVCVideoServices/AVCVideoServices.h>
    1717
     18#define LOC QString("DarwinFirewireChannel: ")
     19#define LOC_ERR QString("DarwinFirewireChannel, Error: ")
    1820
    1921namespace
    2022{
     
    8486    return this->device;
    8587}
    8688
     89FirewireDevice::PowerState DarwinFirewireChannel::GetPowerState(void) const
     90{
     91    UInt8 power_state;
     92    IOReturn err = device->GetPowerState(&power_state);
     93
     94    if (err != kIOReturnSuccess)
     95        return FirewireDevice::kAVCPowerQueryFailed;
     96    else if (kAVCPowerStateOff == power_state)
     97        return FirewireDevice::kAVCPowerOff;
     98    else if (kAVCPowerStateOn == power_state)
     99        return FirewireDevice::kAVCPowerOn;
     100    else
     101        return FirewireDevice::kAVCPowerUnknown;
     102}
     103
     104bool DarwinFirewireChannel::SetPowerState(bool on)
     105{
     106    if (on)
     107        SetPowerState(kAVCPowerStateOn);
     108    else
     109        SetPowerState(kAVCPowerStateOff);
     110
     111    return true;
     112}
     113
    87114bool DarwinFirewireChannel::SetChannelByNumber(int channel)
    88115{
    89116     // If the tuner is off, try to turn it on.
    90      UInt8 power_state;
    91      IOReturn err = this->device->GetPowerState(&power_state);
    92      if (err == kIOReturnSuccess && power_state == kAVCPowerStateOff)
     117     if (FirewireDevice::kAVCPowerOff == GetPowerState())
    93118     {
    94          this->device->SetPowerState(kAVCPowerStateOn);
     119         SetPowerState(true);
    95120       
    96121         // Give it time to power up.
    97122         usleep(2000000); // Sleep for two seconds
     
    101126     err = panel.Tune(channel);
    102127     if (err != kIOReturnSuccess)
    103128     {
    104          VERBOSE(VB_GENERAL, QString("DarwinFirewireChannel: Tuning failed: %1").arg(err,0,16));
    105          VERBOSE(VB_GENERAL, QString("Ignoring error per apple example"));
     129         VERBOSE(VB_GENERAL, LOC_ERR +
     130                 QString("Tuning failed: %1").arg(err,0,16) +
     131                 QString("Ignoring error per apple example"));
    106132     }
     133
    107134     // Give it time to transition.       
    108135     usleep(1000000); // Sleep for one second
     136
    109137     return true;
    110138}
  • libs/libmythtv/firewiresignalmonitor.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 "firewiresignalmonitor.h"
     12#include "atscstreamdata.h"
     13#include "mpegtables.h"
     14#include "atsctables.h"
     15
     16#include "firewirechannelbase.h"
     17
     18#include "firewirechannel.h"
     19
     20#define LOC QString("FireSM(%1): ").arg(channel->GetDevice())
     21#define LOC_WARN QString("FireSM(%1), Warning: ").arg(channel->GetDevice())
     22#define LOC_ERR QString("FireSM(%1), Error: ").arg(channel->GetDevice())
     23
     24const uint FirewireSignalMonitor::kPowerTimeout  = 3000; /* ms */
     25const uint FirewireSignalMonitor::kBufferTimeout = 5000; /* ms */
     26
     27QMap<void*,uint> FirewireSignalMonitor::pat_keys;
     28QMutex           FirewireSignalMonitor::pat_keys_lock;
     29
     30/** \fn FirewireSignalMonitor::FirewireSignalMonitor(int,FirewireChannel*,uint,const char*)
     31 *  \brief Initializes signal lock and signal values.
     32 *
     33 *   Start() must be called to actually begin continuous
     34 *   signal monitoring. The timeout is set to 3 seconds,
     35 *   and the signal threshold is initialized to 0%.
     36 *
     37 *  \param db_cardnum Recorder number to monitor,
     38 *                    if this is less than 0, SIGNAL events will not be
     39 *                    sent to the frontend even if SetNotifyFrontend(true)
     40 *                    is called.
     41 *  \param _channel FirewireChannel for card
     42 *  \param _flags   Flags to start with
     43 *  \param _name    Name for Qt signal debugging
     44 */
     45FirewireSignalMonitor::FirewireSignalMonitor(
     46    int db_cardnum,
     47    FirewireChannelBase *_channel,
     48    uint _flags, const char *_name) :
     49    DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
     50    dtvMonitorRunning(false),
     51    stb_needs_retune(true),
     52    stb_needs_to_wait_for_pat(false),
     53    stb_needs_to_wait_for_power(false)
     54{
     55    VERBOSE(VB_CHANNEL, LOC + "ctor");
     56
     57    signalStrength.SetThreshold(65);
     58
     59    AddFlags(kDTVSigMon_WaitForSig);
     60
     61    stb_needs_retune =
     62        (FirewireDevice::kAVCPowerOff == _channel->GetPowerState());
     63}
     64
     65/** \fn FirewireSignalMonitor::~FirewireSignalMonitor()
     66 *  \brief Stops signal monitoring and table monitoring threads.
     67 */
     68FirewireSignalMonitor::~FirewireSignalMonitor()
     69{
     70    VERBOSE(VB_CHANNEL, LOC + "dtor");
     71    Stop();
     72}
     73
     74void FirewireSignalMonitor::deleteLater(void)
     75{
     76    disconnect(); // disconnect signals we may be sending...
     77    Stop();
     78    DTVSignalMonitor::deleteLater();
     79}
     80
     81/** \fn FirewireSignalMonitor::Stop(void)
     82 *  \brief Stop signal monitoring and table monitoring threads.
     83 */
     84void FirewireSignalMonitor::Stop(void)
     85{
     86    VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin");
     87    SignalMonitor::Stop();
     88    if (dtvMonitorRunning)
     89    {
     90        dtvMonitorRunning = false;
     91        pthread_join(table_monitor_thread, NULL);
     92    }
     93    VERBOSE(VB_CHANNEL, LOC + "Stop() -- end");
     94}
     95
     96void FirewireSignalMonitor::HandlePAT(const ProgramAssociationTable *pat)
     97{
     98    AddFlags(kDTVSigMon_PATSeen);
     99
     100    {
     101        QMutexLocker locker(&pat_keys_lock);
     102        const uint crc = pat_keys[channel];
     103
     104        VERBOSE(VB_CHANNEL, LOC + "HandlePAT() CRC: 0x"
     105                <<hex<<pat->CalcCRC()<<"|0x"<<crc<<dec);
     106
     107        bool crc_bogus = (pat->CalcCRC() == crc);
     108        if (crc_bogus && stb_needs_to_wait_for_pat &&
     109            (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout))
     110        {
     111            VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT");
     112            uint tsid = pat->TransportStreamID();
     113            GetStreamData()->SetVersionPAT(tsid, -1,0);
     114            return;
     115        }
     116
     117        if (crc_bogus && stb_needs_to_wait_for_pat)
     118        {
     119            VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out");
     120            stb_needs_to_wait_for_pat = false;
     121        }
     122           
     123        pat_keys[channel] = pat->CalcCRC();
     124    }
     125
     126    DTVSignalMonitor::HandlePAT(pat);
     127}
     128
     129void FirewireSignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt)
     130{
     131    VERBOSE(VB_CHANNEL, LOC + "HandlePMT()");
     132
     133    AddFlags(kDTVSigMon_PMTSeen);
     134
     135    if (!HasFlags(kDTVSigMon_PATMatch))
     136    {
     137        GetStreamData()->SetVersionPMT(pnum, -1,0);
     138        VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT");
     139        return;
     140    }
     141
     142    DTVSignalMonitor::HandlePMT(pnum, pmt);
     143}
     144
     145void *FirewireSignalMonitor::TableMonitorThread(void *param)
     146{
     147    FirewireSignalMonitor *mon = (FirewireSignalMonitor*) param;
     148    mon->RunTableMonitor();
     149    return NULL;
     150}
     151
     152void FirewireSignalMonitor::RunTableMonitor(void)
     153{
     154    stb_needs_to_wait_for_pat = true;
     155    stb_wait_for_pat_timer.start();
     156    dtvMonitorRunning = true;
     157
     158    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin");
     159
     160    LinuxFirewireChannel *lchan = dynamic_cast<LinuxFirewireChannel*>(channel);
     161    if (!lchan)
     162    {
     163        VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end");
     164        dtvMonitorRunning = false;
     165        return;
     166    }
     167
     168    LinuxFirewireDevice *dev = lchan->GetFirewireDevice();
     169
     170    dev->OpenPort();
     171    dev->AddListener(this);
     172
     173    while (dtvMonitorRunning && GetStreamData())
     174        usleep(100000);
     175
     176    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown ");
     177
     178    dev->RemoveListener(this);
     179    dev->ClosePort();
     180
     181    dtvMonitorRunning = false;
     182
     183    VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end");
     184}
     185
     186void FirewireSignalMonitor::AddData(const unsigned char *data, uint len)
     187{
     188    if (!dtvMonitorRunning)
     189        return;
     190
     191    if (GetStreamData())
     192        GetStreamData()->ProcessData((unsigned char *)data, len);
     193}
     194
     195/** \fn FirewireSignalMonitor::UpdateValues(void)
     196 *  \brief Fills in frontend stats and emits status Qt signals.
     197 *
     198 *   This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH
     199 *   FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain
     200 *   statistics from the frontend.
     201 *
     202 *   This is automatically called by MonitorLoop(), after Start()
     203 *   has been used to start the signal monitoring thread.
     204 */
     205void FirewireSignalMonitor::UpdateValues(void)
     206{
     207    if (!running || exit)
     208        return;
     209
     210    if (dtvMonitorRunning)
     211    {
     212        EmitFirewireSignals();
     213        if (IsAllGood())
     214            emit AllGood();
     215        // TODO dtv signals...
     216
     217        update_done = true;
     218        return;
     219    }
     220
     221    if (stb_needs_to_wait_for_power &&
     222        (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout))
     223    {
     224        return;
     225    }
     226    stb_needs_to_wait_for_power = false;
     227
     228    FirewireChannelBase *fwchan = dynamic_cast<FirewireChannelBase*>(channel);
     229
     230    if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch))
     231    {
     232        FirewireDevice::PowerState power = fwchan->GetPowerState();
     233        if (FirewireDevice::kAVCPowerOn == power)
     234        {
     235            AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
     236        }
     237        else if (FirewireDevice::kAVCPowerOff == power)
     238        {
     239            AddFlags(kFWSigMon_PowerSeen);
     240            fwchan->SetPowerState(true);
     241            stb_wait_for_power_timer.start();
     242            stb_needs_to_wait_for_power = true;
     243        }
     244    }
     245
     246    bool isLocked = !HasFlags(kFWSigMon_WaitForPower) ||
     247        HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch);
     248
     249    if (isLocked && stb_needs_retune)
     250    {
     251        fwchan->Retune();
     252        isLocked = stb_needs_retune = false;
     253    }
     254
     255    // Set SignalMonitorValues from info from card.
     256    {
     257        QMutexLocker locker(&statusLock);
     258        signalStrength.SetValue(isLocked ? 100 : 0);
     259        signalLock.SetValue(isLocked ? 1 : 0);
     260    }
     261
     262    EmitFirewireSignals();
     263    if (IsAllGood())
     264        emit AllGood();
     265
     266    // Start table monitoring if we are waiting on any table
     267    // and we have a lock.
     268    if (isLocked && GetStreamData() &&
     269        HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
     270                   kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
     271                   kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
     272    {
     273        pthread_create(&table_monitor_thread, NULL,
     274                       TableMonitorThread, this);
     275
     276        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- "
     277                "Waiting for table monitor to start");
     278
     279        while (!dtvMonitorRunning)
     280            usleep(50);
     281
     282        VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- "
     283                "Table monitor started");
     284    }
     285
     286    update_done = true;
     287}
     288
     289#define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \
     290    do { statusLock.lock(); \
     291         SignalMonitorValue val = SIGNAL_VAL; \
     292         statusLock.unlock(); \
     293         emit SIGNAL_FUNC(val); } while (false)
     294
     295/** \fn FirewireSignalMonitor::EmitFirewireSignals(void)
     296 *  \brief Emits signals for lock, signal strength, etc.
     297 */
     298void FirewireSignalMonitor::EmitFirewireSignals(void)
     299{
     300    // Emit signals..
     301    EMIT(StatusSignalLock, signalLock);
     302    if (HasFlags(kDTVSigMon_WaitForSig))
     303        EMIT(StatusSignalStrength, signalStrength);
     304}
     305
     306#undef EMIT
  • libs/libmythtv/darwinfirewirechannel.h

     
    2424  public:
    2525    DarwinFirewireChannel(FireWireDBOptions const&, TVRec *parent);
    2626
     27    // Sets
     28    virtual bool SetChannelByNumber(int channel);
     29    virtual bool SetPowerState(bool on);
     30
    2731    // Gets
    28     AVS::AVCDevice* GetAVCDevice() const;
     32    AVS::AVCDevice* GetAVCDevice(void) const;
     33    virtual FirewireDevice::PowerState GetPowerState(void) const;
    2934
    30     // Sets
    31     bool SetChannelByNumber(int channel);
    32 
    3335  private:
    34     bool OpenFirewire();
    35     void CloseFirewire();
     36    virtual bool OpenFirewire(void);
     37    virtual void CloseFirewire(void);
    3638
    3739  private:
    3840    AVS::AVCDeviceController* device_controller;
  • libs/libmythtv/signalmonitor.cpp

     
    3434#   include "iptvchannel.h"
    3535#endif
    3636
     37#ifdef USING_FIREWIRE
     38#   include "firewiresignalmonitor.h"
     39#   include "firewirechannelbase.h"
     40#endif
     41
    3742#undef DBG_SM
    3843#define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
    3944    "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
     
    117122    }
    118123#endif
    119124
     125#ifdef USING_FIREWIRE
     126    if (cardtype.upper() == "FIREWIRE")
     127    {
     128        FirewireChannelBase *fc = dynamic_cast<FirewireChannelBase*>(channel);
     129        if (fc)
     130            signalMonitor = new FirewireSignalMonitor(db_cardnum, fc);
     131    }
     132#endif
     133
    120134    if (!signalMonitor)
    121135    {
    122136        VERBOSE(VB_IMPORTANT,
  • libs/libmythtv/firewiresignalmonitor.h

     
     1// -*- Mode: c++ -*-
     2
     3#ifndef _FIREWIRESIGNALMONITOR_H_
     4#define _FIREWIRESIGNALMONITOR_H_
     5
     6#include <qmap.h>
     7#include <qmutex.h>
     8#include <qdatetime.h>
     9
     10#include "dtvsignalmonitor.h"
     11#include "linuxfirewiredevice.h"
     12#include "util.h"
     13
     14class FirewireChannelBase;
     15
     16class FirewireSignalMonitor : public DTVSignalMonitor, public TSDataListener
     17{
     18    Q_OBJECT
     19
     20  public:
     21    FirewireSignalMonitor(int db_cardnum, FirewireChannelBase* _channel,
     22                          uint _flags = kFWSigMon_WaitForPower,
     23                          const char *_name = "FirewireSignalMonitor");
     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    FirewireSignalMonitor(void);
     35    FirewireSignalMonitor(const FirewireSignalMonitor&);
     36    virtual ~FirewireSignalMonitor();
     37
     38    virtual void UpdateValues(void);
     39    void EmitFirewireSignals(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 // _FIREWIRESIGNALMONITOR_H_
  • libs/libmythtv/darwinfirewirerecorder.h

     
    3333class DarwinFirewireRecorder : public FirewireRecorderBase
    3434{
    3535  public:
    36     DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner);
     36    DarwinFirewireRecorder(TVRec *rec, DarwinFirewireChannel *channel);
    3737    ~DarwinFirewireRecorder();
    3838
    3939    bool Open(void);
    4040
    41     void SetOption(const QString &name, const QString &value);
    42     void SetOption(const QString &name, int value);
    43 
    4441  private:
    4542    void Close();
    4643
    4744    void start();
    4845    void stop();
    4946    void no_data();
    50     bool grab_frames();
    5147
    5248    static IOReturn MPEGNoData(void* pRefCon);
    5349    static IOReturn tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf, void *pRefCon);
  • libs/libmythtv/firewirechannel.h

     
    55 *  Distributed as part of MythTV under GPL v2 and later.
    66 */
    77
     8#ifndef _LINUX_FIREWIRE_CHANNEL_H_
     9#define _LINUX_FIREWIRE_CHANNEL_H_
    810
    9 #ifndef FIREWIRECHANNEL_H
    10 #define FIREWIRECHANNEL_H
    11 
    1211#include <qstring.h>
    1312#include "tv_rec.h"
    1413#include "firewirechannelbase.h"
    15 #include <libavc1394/avc1394.h>
    1614
    1715using namespace std;
    1816
    19 class FirewireChannel : public FirewireChannelBase
     17class LinuxFirewireDevice;
     18
     19class LinuxFirewireChannel : public FirewireChannelBase
    2020{
    2121  public:
    22     enum PowerState {
    23         On,
    24         Off,
    25         Failed
    26     };
     22    LinuxFirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent);
     23    ~LinuxFirewireChannel(void);
    2724
    28     FirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent);
    29     ~FirewireChannel(void);
     25    // Commands
     26    virtual bool Retune(void);
    3027
    31     bool OpenFirewire(void);
    32     void CloseFirewire(void);
    33 
    3428    // Sets
    35     void SetExternalChanger(void);
    36     bool SetChannelByNumber(int channel);
     29    virtual bool SetChannelByNumber(int channel);
     30    virtual bool SetPowerState(bool on);
    3731
    3832    // Gets
    39     bool IsOpen(void) const { return isopen; }
    40     QString GetDevice(void) const
     33    virtual QString GetDevice(void) const
    4134        { return QString("%1:%2").arg(fw_opts.port).arg(fw_opts.node); }
    42     PowerState GetPowerState(void);
     35    virtual LinuxFirewireDevice *GetFirewireDevice(void)
     36        { return device; }
     37    virtual FirewireDevice::PowerState GetPowerState(void) const;
    4338
    4439  private:
    45     FireWireDBOptions  fw_opts;
    46     nodeid_t           fwnode;
    47     raw1394handle_t    fwhandle;
     40    virtual bool OpenFirewire(void);
     41    virtual void CloseFirewire(void);
     42
     43  private:
     44    FireWireDBOptions    fw_opts;
     45    LinuxFirewireDevice *device;
     46    uint                 current_channel;
     47    bool                 is_port_open;
    4848};
    4949
    50 #endif
     50#endif // _LINUX_FIREWIRE_CHANNEL_H_
  • libs/libmythtv/videosource.cpp

     
    10311031        hg1->addChild(new FirewireNode(parent));
    10321032        hg1->addChild(new FirewireSpeed(parent));
    10331033        addChild(hg1);
    1034         addChild(new FirewireInput(parent));
     1034
     1035        FirewireInput *defaultinput = new FirewireInput(parent);
     1036        addChild(defaultinput);
     1037        defaultinput->setVisible(false);
     1038
     1039        addChild(new ChannelTimeout(parent, 9000));
    10351040    };
     1041
    10361042  private:
    10371043    CaptureCard &parent;
    10381044};
     
    11861192        HDHRCardInput *defaultinput = new HDHRCardInput(parent);
    11871193        addChild(defaultinput);
    11881194        defaultinput->setVisible(false);
     1195
     1196        addChild(new SignalTimeout(parent, 1000));
     1197        addChild(new ChannelTimeout(parent, 3000));
    11891198    };
    11901199
    11911200  private:
  • libs/libmythtv/firewirechannelbase.cpp

     
    55 */
    66
    77
    8 #include <iostream>
     8#include "mythconfig.h" // for CONFIG_DARWIN
    99#include "mythcontext.h"
    1010#include "firewirechannelbase.h"
     11#include "tv_rec.h"
    1112
     13#ifdef CONFIG_DARWIN
     14#   include "darwinfirewirechannel.h"
     15#else
     16#   include "firewirechannel.h"
     17#endif
     18
     19FirewireChannelBase *FirewireChannelBase::Init(
     20    const FireWireDBOptions &firewire_opts, TVRec *parent)
     21{
     22#ifdef CONFIG_DARWIN
     23    return new DarwinFirewireChannel(firewire_opts, parent);
     24#else
     25    return new LinuxFirewireChannel(firewire_opts, parent);
     26#endif
     27}
     28
    1229bool FirewireChannelBase::SetChannelByString(const QString &chan)
    1330{
    1431    inputs[currentInputID]->startChanNum = chan;
     
    2239    return isopen && SetChannelByNumber(chan.toInt());
    2340}
    2441
    25 bool FirewireChannelBase::Open()
     42bool FirewireChannelBase::Open(void)
    2643{
    2744    if (!InitializeInputs())
    2845        return false;
     
    3956    return true;
    4057}
    4158
    42 void FirewireChannelBase::Close()
     59void FirewireChannelBase::Close(void)
    4360{
    4461    if (isopen)
    4562        CloseFirewire();
  • libs/libmythtv/linuxfirewiredevice.h

     
     1/**
     2 *  LinuxFirewireDevice
     3 *  Copyright (c) 2005 by Jim Westfall
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7#ifndef _LINUX_FIREWIRE_DEVICE_H_
     8#define _LINUX_FIREWIRE_DEVICE_H_
     9
     10#include <qmutex.h>
     11
     12#include "firewiredevice.h"
     13
     14class FWPriv;
     15
     16class LinuxFirewireDevice : public FirewireDevice
     17{
     18    friend void *linux_firewire_device_streaming_thunk(void *param);
     19    friend int linux_firewire_device_tspacket_handler(
     20        unsigned char *tspacket, int len, uint dropped, void *callback_data);
     21
     22  public:
     23
     24    LinuxFirewireDevice(uint port, uint node, uint speed, bool use_p2p,
     25                        uint av_buffer_size_in_bytes = 0);
     26    ~LinuxFirewireDevice();
     27
     28    bool OpenPort(void);
     29    bool ClosePort(void);
     30
     31    void AddListener(TSDataListener*);
     32    void RemoveListener(TSDataListener*);
     33
     34    // Sets
     35    bool SetPowerState(bool on);
     36    bool SetChannel(const QString &panel_model, uint channel);
     37
     38    // Gets
     39    bool IsPortOpen(void) const;
     40    bool IsTuner(void) const;
     41    bool IsPanel(void) const;
     42    bool IsSTB(void) const;
     43
     44    // non-const Gets
     45    PowerState GetPowerState(void);
     46
     47    // Statics
     48    static inline bool IsSTBSupported(const QString &model);
     49
     50    // Constants
     51    static const uint kBroadcastChannel;
     52    static const uint kConnectionP2P;
     53    static const uint kConnectionBroadcast;
     54    static const uint kMaxBufferedPackets;
     55
     56  private:
     57    bool OpenNode(void);
     58    bool CloseNode(void);
     59
     60    bool OpenAVStream(void);
     61    bool CloseAVStream(void);
     62
     63    bool OpenP2PNode(void);
     64    bool CloseP2PNode(void);
     65
     66    bool OpenBroadcastNode(void);
     67    bool CloseBroadcastNode(void);
     68
     69    bool StartStreaming(void);
     70    bool StopStreaming(void);
     71    bool StopStreamingLater(void);
     72
     73    bool ResetBus(void);
     74
     75    void RunStreaming(void);
     76    bool LoopIteration(uint timeout_in_msec);
     77    void PrintDropped(uint dropped_packets);
     78    void BroadcastToListeners(const unsigned char *data, uint dataSize);
     79
     80    bool SetAVStreamBufferSize(uint size_in_bytes);
     81    bool SetAVStreamSpeed(uint speed);
     82
     83    bool IsNodeOpen(void) const;
     84    bool IsAVStreamOpen(void) const;
     85    bool IsSubunitType(uint subunit_type) const;
     86
     87  private:
     88    uint                     m_port;
     89    uint                     m_node;
     90    uint                     m_speed;
     91    uint                     m_bufsz;
     92    bool                     m_use_p2p;
     93    bool                     m_resetting;
     94    uint                     m_open_port_cnt;
     95    FWPriv                  *m_priv;
     96    vector<TSDataListener*>  m_listeners;
     97
     98    mutable QMutex           m_lock;
     99};
     100
     101inline bool LinuxFirewireDevice::IsSTBSupported(const QString &panel_model)
     102{
     103    QString model = panel_model.upper();
     104    return ((model == "DCT-6200") ||
     105            (model == "SA3250HD") ||
     106            (model == "SA4200HD"));
     107}
     108
     109#endif // _LINUX_FIREWIRE_DEVICE_H_
  • libs/libmythtv/tv_rec.cpp

     
    4848#include "dbox2channel.h"
    4949#include "hdhrchannel.h"
    5050#include "iptvchannel.h"
     51#include "firewirechannelbase.h"
    5152
    5253#include "recorderbase.h"
    5354#include "NuppelVideoRecorder.h"
     
    5758#include "dbox2recorder.h"
    5859#include "hdhrrecorder.h"
    5960#include "iptvrecorder.h"
     61#include "firewirerecorderbase.h"
    6062
    6163#ifdef USING_V4L
    6264#include "channel.h"
    6365#endif
    6466
    65 #ifdef USING_FIREWIRE
    66 #ifdef CONFIG_DARWIN
    67 #include "darwinfirewirerecorder.h"
    68 #include "darwinfirewirechannel.h"
    69 #else
    70 #include "firewirerecorder.h"
    71 #include "firewirechannel.h"
    72 #endif
    73 #endif
    74 
    7567#define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */
    7668
    7769#define LOC QString("TVRec(%1): ").arg(cardid)
     
    158150    else if (genOpt.cardtype == "FIREWIRE")
    159151    {
    160152#ifdef USING_FIREWIRE
    161 # ifdef CONFIG_DARWIN
    162         channel = new DarwinFirewireChannel(fwOpt, this);
    163 # else
    164         channel = new FirewireChannel(fwOpt, this);
    165 # endif
    166         if (!channel->Open())
     153        channel = FirewireChannelBase::Init(fwOpt, this);
     154        if (!channel || !channel->Open())
    167155            return false;
    168156        InitChannel(genOpt.defaultinput, startchannel);
    169157        init_run = true;
     
    831819    else if (genOpt.cardtype == "FIREWIRE")
    832820    {
    833821#ifdef USING_FIREWIRE
    834 # ifdef CONFIG_DARWIN
    835         recorder = new DarwinFirewireRecorder(this, this->channel);
    836 # else
    837         recorder = new FirewireRecorder(this);
    838         recorder->SetOption("port",       fwOpt.port);
    839         recorder->SetOption("node",       fwOpt.node);
    840         recorder->SetOption("speed",      fwOpt.speed);
    841         recorder->SetOption("model",      fwOpt.model);
    842         recorder->SetOption("connection", fwOpt.connection);
    843 # endif // !CONFIG_DARWIN
     822        recorder = FirewireRecorderBase::Init(this, GetFirewireChannel());
     823        if (recorder)
     824        {
     825            recorder->SetOption("port",       fwOpt.port);
     826            recorder->SetOption("node",       fwOpt.node);
     827            recorder->SetOption("speed",      fwOpt.speed);
     828            recorder->SetOption("model",      fwOpt.model);
     829            recorder->SetOption("connection", fwOpt.connection);
     830        }
    844831#endif // USING_FIREWIRE
    845832    }
    846833    else if (genOpt.cardtype == "DBOX2")
     
    11141101#endif // USING_DVB
    11151102}
    11161103
     1104FirewireChannelBase *TVRec::GetFirewireChannel(void)
     1105{
     1106#ifdef USING_FIREWIRE
     1107    return dynamic_cast<FirewireChannelBase*>(channel);
     1108#else
     1109    return NULL;
     1110#endif // USING_FIREWIRE
     1111}
     1112
    11171113Channel *TVRec::GetV4LChannel(void)
    11181114{
    11191115#ifdef USING_V4L
  • libs/libmythtv/tv_rec.h

     
    3535class DBox2Channel;
    3636class DTVChannel;
    3737class DVBChannel;
     38class FirewireChannelBase;
    3839class Channel;
    3940class HDHRChannel;
    4041
     
    261262    DTVChannel   *GetDTVChannel(void);
    262263    HDHRChannel  *GetHDHRChannel(void);
    263264    DVBChannel   *GetDVBChannel(void);
     265    FirewireChannelBase *GetFirewireChannel(void);
    264266    Channel      *GetV4LChannel(void);
    265267
    266268    bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
  • libs/libmythtv/firewiredevice.h

     
     1/**
     2 *  FirewireDevice
     3 *  Copyright (c) 2005 by Jim Westfall
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7#ifndef _FIREWIRE_DEVICE_H_
     8#define _FIREWIRE_DEVICE_H_
     9
     10// C++ headers
     11#include <vector>
     12using namespace std;
     13
     14#include <qstring.h>
     15
     16class TSDataListener
     17{
     18  public:
     19    /// Callback function to add MPEG2 TS data
     20    virtual void AddData(const unsigned char *data, uint dataSize) = 0;
     21
     22  protected:
     23    virtual ~TSDataListener() { }
     24};
     25
     26class FirewireDevice
     27{
     28  public:
     29    // Public enums
     30    typedef enum
     31    {
     32        kAVCPowerOn,
     33        kAVCPowerOff,
     34        kAVCPowerUnknown,
     35        kAVCPowerQueryFailed,
     36    } PowerState;
     37};
     38
     39#endif // _FIREWIRE_DEVICE_H_
  • libs/libmythtv/linuxfirewiredevice.cpp

     
     1/**
     2 *  LinuxFirewireDevice
     3 *  Copyright (c) 2005 by Jim Westfall
     4 *  Copyright (c) 2006 by Daniel Kristjansson
     5 *  SA3250HD support Copyright (c) 2005 by Matt Porter
     6 *  SA4200HD/Alternate 3250 support Copyright (c) 2006 by Chris Ingrassia
     7 *  Distributed as part of MythTV under GPL v2 and later.
     8 */
     9
     10// POSIX headers
     11#include <pthread.h>
     12#include <sys/select.h>
     13
     14// Linux headers
     15#include <libraw1394/raw1394.h>
     16#include <libiec61883/iec61883.h>
     17#include <libavc1394/avc1394.h>
     18
     19// C++ headers
     20#include <algorithm>
     21using namespace std;
     22
     23// Qt headers
     24#include <qdatetime.h>
     25
     26// MythTV headers
     27#include "linuxfirewiredevice.h"
     28#include "firewirerecorder.h"
     29#include "mythcontext.h"
     30
     31#define LOC QString("FireDev(%1:%2): ").arg(m_port).arg(m_node)
     32#define LOC_WARN QString("FireDev(%1:%2), Warning: ").arg(m_port).arg(m_node)
     33#define LOC_ERR QString("FireDev(%1:%2), Error: ").arg(m_port).arg(m_node)
     34
     35
     36#ifndef AVC1394_PANEL_COMMAND_PASS_THROUGH
     37#define AVC1394_PANEL_COMMAND_PASS_THROUGH     0x000007C00
     38#endif
     39
     40#ifndef AVC1394_PANEL_OPERATION_0
     41#define AVC1394_PANEL_OPERATION_0              0x000000020
     42#endif
     43
     44#define AVC1394_CMD_OPERAND_POWER_STATE        0x7F
     45
     46// Basic Panel commands
     47#define PANEL_CMD0 (AVC1394_CTYPE_CONTROL | \
     48                    AVC1394_SUBUNIT_TYPE_PANEL | \
     49                    AVC1394_SUBUNIT_ID_0 | \
     50                    AVC1394_PANEL_COMMAND_PASS_THROUGH)
     51
     52// Scientific Atlanta defines
     53#define AVC1394_SA3250_OPERAND_KEY_PRESS        0xE7
     54#define AVC1394_SA3250_OPERAND_KEY_RELEASE      0x67
     55#define SA_CMD0     PANEL_CMD0
     56#define SA_CMD1     AVC1394_CTYPE_GENERAL_INQUIRY
     57#define SA_CMD2     0xff000000
     58
     59// Motorola defines
     60#define MOT_CMD0  (PANEL_CMD0 | AVC1394_PANEL_OPERATION_0)
     61
     62class FWPriv
     63{
     64  public:
     65    FWPriv() :
     66        handle(0), avstream(0),
     67        channel(-1),
     68        is_p2p_node_open(false), is_bcast_node_open(false),
     69        is_streaming(false)
     70    {
     71        bzero(unit_table, sizeof(unit_table));
     72    }
     73
     74    raw1394handle_t  handle;
     75    iec61883_mpeg2_t avstream;
     76    quadlet_t        unit_table[8];
     77    int              channel;
     78    int              open_node;
     79    bool             is_p2p_node_open;
     80    bool             is_bcast_node_open;
     81    bool             is_streaming;
     82    bool             is_streaming_running;
     83    QDateTime        stop_streaming_timer;
     84    pthread_t        streaming_thread;
     85};
     86
     87const uint LinuxFirewireDevice::kBroadcastChannel    = 63;
     88const uint LinuxFirewireDevice::kConnectionP2P       = 0;
     89const uint LinuxFirewireDevice::kConnectionBroadcast = 1;
     90const uint LinuxFirewireDevice::kMaxBufferedPackets  = 2000;
     91
     92// callback function for libiec61883
     93int linux_firewire_device_tspacket_handler(
     94    unsigned char *tspacket, int len, uint dropped, void *callback_data);
     95static QString speed_to_string(uint speed);
     96static quadlet_t *send_avc_command(raw1394handle_t handle,
     97                                   uint            node,
     98                                   quadlet_t      *cmd,
     99                                   uint            cmd_len,
     100                                   uint            retry_cnt = 1);
     101static void close_avc_command(raw1394handle_t handle);
     102
     103
     104LinuxFirewireDevice::LinuxFirewireDevice(
     105    uint port, uint node, uint speed, bool use_p2p,
     106    uint av_buffer_size_in_bytes) :
     107    m_port(port),       m_node(node),
     108    m_speed(speed),     m_bufsz(av_buffer_size_in_bytes),
     109    m_use_p2p(use_p2p), m_resetting(false),
     110    m_open_port_cnt(0), m_priv(new FWPriv()),
     111    m_lock(false)
     112{
     113    if (!m_bufsz)
     114        m_bufsz = gContext->GetNumSetting("HDRingbufferSize");
     115}
     116
     117LinuxFirewireDevice::~LinuxFirewireDevice()
     118{
     119    if (IsPortOpen())
     120    {
     121        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port");
     122        while (IsPortOpen())
     123            ClosePort();
     124    }
     125
     126    if (m_priv)
     127    {
     128        delete m_priv;
     129        m_priv = NULL;
     130    }
     131}
     132
     133bool LinuxFirewireDevice::OpenPort(void)
     134{
     135    QMutexLocker locker(&m_lock);
     136
     137    VERBOSE(VB_RECORD, LOC + "OpenPort()");
     138
     139    m_open_port_cnt++;
     140
     141    if (m_priv->handle)
     142        return true;
     143
     144    VERBOSE(VB_RECORD, LOC + "Getting raw1394 handle "<<(m_open_port_cnt-1));
     145    m_priv->handle = raw1394_new_handle_on_port(m_port);
     146
     147    if (!m_priv->handle)
     148    {
     149        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " +
     150                QString("port: %1").arg(m_port) + ENO);
     151
     152        return false;
     153    }
     154
     155    if (avc1394_subunit_info(m_priv->handle, m_node, m_priv->unit_table) < 0)
     156        bzero(m_priv->unit_table, sizeof(m_priv->unit_table));
     157
     158    QString str = "Subunit Types: ";
     159
     160    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VIDEO_MONITOR))
     161        str += "Video Monitor, ";
     162    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_AUDIO))
     163        str += "Audio, ";
     164    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_PRINTER))
     165        str += "Printer, ";
     166    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_DISC_RECORDER))
     167        str += "Disk Recorder, ";
     168    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_TAPE_RECORDER))
     169        str += "Tape Recorder, ";
     170    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VCR))
     171        str += "VCR, ";
     172    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_TUNER))
     173        str += "Tuner, ";
     174    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_CA))
     175        str += "CA, ";
     176    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VIDEO_CAMERA))
     177        str += "Camera, ";
     178    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_PANEL))
     179        str += "Panel, ";
     180    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_BULLETIN_BOARD))
     181        str += "Bulletin Board, ";
     182    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_CAMERA_STORAGE))
     183        str += "Camera Storage, ";
     184    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_MUSIC))
     185        str += "Music, ";
     186    if (IsSubunitType(AVC1394_SUBUNIT_TYPE_VENDOR_UNIQUE))
     187        str += "Vendor Unique, ";
     188
     189    VERBOSE(VB_RECORD, LOC + str);
     190
     191    return true;
     192}
     193
     194bool LinuxFirewireDevice::ClosePort(void)
     195{
     196    QMutexLocker locker(&m_lock);
     197
     198    VERBOSE(VB_RECORD, LOC + "ClosePort()");
     199
     200    if (m_open_port_cnt < 1)
     201        return false;
     202
     203    m_open_port_cnt--;
     204
     205    if (m_open_port_cnt != 0)
     206        return true;
     207
     208    if (m_priv->handle)
     209    {
     210        if (IsNodeOpen())
     211            CloseNode();
     212
     213        VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle "<<m_open_port_cnt);
     214        raw1394_destroy_handle(m_priv->handle);
     215        m_priv->handle = NULL;
     216    }
     217
     218    return true;
     219}
     220
     221bool LinuxFirewireDevice::OpenNode(void)
     222{
     223    if (m_use_p2p)
     224        return OpenP2PNode();
     225    else
     226        return OpenBroadcastNode();
     227}
     228
     229bool LinuxFirewireDevice::CloseNode(void)
     230{
     231    if (m_priv->is_p2p_node_open)
     232        return CloseP2PNode();
     233
     234    if (m_priv->is_bcast_node_open)
     235        return CloseBroadcastNode();
     236
     237    return true;
     238}
     239
     240bool LinuxFirewireDevice::OpenP2PNode(void)
     241{
     242    if (m_priv->is_bcast_node_open)
     243        return false;
     244
     245    if (m_priv->is_p2p_node_open)
     246        return true;
     247
     248    VERBOSE(VB_RECORD, LOC + "Opening P2P connection");
     249
     250    m_priv->channel = m_node;
     251    if (iec61883_cmp_create_p2p_output(m_priv->handle, m_node | 0xffc0, 0,
     252                                       m_priv->channel, m_speed) != 0)
     253    {
     254        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create P2P connection");
     255
     256        m_priv->channel = -1;
     257        return false;
     258    }
     259
     260    m_priv->is_p2p_node_open = true;
     261
     262    return true;
     263}
     264
     265bool LinuxFirewireDevice::CloseP2PNode(void)
     266{
     267    if (m_priv->is_p2p_node_open && (m_priv->channel >= 0))
     268    {
     269        VERBOSE(VB_RECORD, LOC + "Closing P2P connection");
     270
     271        if (m_priv->avstream)
     272            CloseAVStream();
     273
     274        iec61883_cmp_disconnect(m_priv->handle, m_node | 0xffc0, 0,
     275                                raw1394_get_local_id(m_priv->handle),
     276                                -1, m_priv->channel, 0);
     277
     278        m_priv->channel = -1;
     279        m_priv->is_p2p_node_open = false;
     280    }
     281
     282    return true;
     283}
     284
     285bool LinuxFirewireDevice::OpenBroadcastNode(void)
     286{
     287    if (m_priv->is_p2p_node_open)
     288        return false;
     289
     290    if (m_priv->is_bcast_node_open)
     291        return true;
     292
     293    m_priv->channel = kBroadcastChannel - m_node;
     294
     295    VERBOSE(VB_RECORD, LOC + "Opening broadcast connection on " +
     296            QString("node %1, channel %2")
     297            .arg(m_node).arg(m_priv->channel));
     298
     299    if (m_priv->avstream)
     300        CloseAVStream();
     301
     302    int err = iec61883_cmp_create_bcast_output(
     303        m_priv->handle, m_node | 0xffc0, 0, m_priv->channel, m_speed);
     304
     305    if (err != 0)
     306    {
     307        VERBOSE(VB_IMPORTANT, LOC_ERR +
     308                "Failed to create Broadcast connection");
     309
     310        m_priv->channel = -1;
     311        return false;
     312    }
     313
     314    m_priv->is_bcast_node_open = true;
     315
     316    return true;
     317}
     318
     319bool LinuxFirewireDevice::CloseBroadcastNode(void)
     320{
     321    if (m_priv->is_bcast_node_open)
     322    {
     323        VERBOSE(VB_RECORD, LOC + "Closing broadcast connection");
     324
     325        m_priv->channel = -1;
     326        m_priv->is_bcast_node_open = false;
     327    }
     328    return true;
     329}
     330
     331bool LinuxFirewireDevice::OpenAVStream(void)
     332{
     333    VERBOSE(VB_RECORD, LOC + "OpenAVStream");
     334
     335    if (!IsNodeOpen() && !OpenNode())
     336        return false;
     337
     338    if (m_priv->avstream)
     339        return true;
     340
     341    VERBOSE(VB_RECORD, LOC + "Opening A/V stream object");
     342
     343    if (!m_priv->handle)
     344    {
     345        VERBOSE(VB_IMPORTANT, LOC +
     346                "Can not open AVStream without IEEE 1394 Port");
     347
     348        return false;
     349    }
     350
     351    m_priv->avstream = iec61883_mpeg2_recv_init(
     352        m_priv->handle, linux_firewire_device_tspacket_handler, this);
     353
     354    if (!m_priv->avstream)
     355    {
     356        VERBOSE(VB_IMPORTANT, LOC + "Unable to open AVStream" + ENO);
     357
     358        return false;
     359    }
     360
     361    iec61883_mpeg2_set_synch(m_priv->avstream, 1 /* sync on close */);
     362
     363    if (m_bufsz)
     364        SetAVStreamBufferSize(m_bufsz);
     365
     366    return true;
     367}
     368
     369bool LinuxFirewireDevice::CloseAVStream(void)
     370{
     371    if (!m_priv->avstream)
     372        return true;
     373
     374    VERBOSE(VB_RECORD, LOC + "Closing A/V stream object");
     375
     376    while (!m_resetting && m_listeners.size())
     377        RemoveListener(m_listeners[m_listeners.size() - 1]);
     378
     379    if (m_priv->is_streaming)
     380        StopStreaming();
     381
     382    iec61883_mpeg2_close(m_priv->avstream);
     383    m_priv->avstream = NULL;
     384
     385    return true;
     386}
     387
     388void *linux_firewire_device_streaming_thunk(void *param)
     389{
     390    LinuxFirewireDevice *mon = (LinuxFirewireDevice*) param;
     391    mon->RunStreaming();
     392    return NULL;
     393}
     394
     395void LinuxFirewireDevice::RunStreaming(void)
     396{
     397    VERBOSE(VB_RECORD, LOC + "RunStreaming -- start");
     398    m_lock.lock();
     399    m_priv->is_streaming_running = true;
     400
     401    uint no_data_cnt = 0;
     402    while (m_priv->is_streaming)
     403    {
     404        no_data_cnt = (LoopIteration(50)) ? 0 : no_data_cnt + 1;
     405
     406        if (m_priv->is_streaming && (no_data_cnt > 30))
     407        {
     408            no_data_cnt = 0;
     409
     410            iec61883_mpeg2_recv_stop(m_priv->avstream);
     411            raw1394_iso_recv_flush(m_priv->handle);
     412            m_priv->is_streaming = false;
     413            ResetBus();
     414            iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel);
     415            m_priv->is_streaming = true;
     416        }
     417    }
     418
     419    m_priv->is_streaming_running = false;
     420    m_lock.unlock();
     421    VERBOSE(VB_RECORD, LOC + "RunStreaming -- end");
     422}
     423
     424bool LinuxFirewireDevice::StartStreaming(void)
     425{
     426    if (m_priv->is_streaming)
     427        return m_priv->is_streaming;
     428
     429    if (!IsAVStreamOpen() && !OpenAVStream())
     430        return false;
     431
     432    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming");
     433
     434    if (!m_priv->avstream)
     435    {
     436        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming, no A/V obj");
     437        return false;
     438    }
     439
     440    if (m_priv->channel < 0)
     441    {
     442        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming, no channel");
     443        return false;
     444    }
     445
     446    if (iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel) == 0)
     447    {
     448        m_priv->is_streaming = true;
     449
     450        pthread_create(&m_priv->streaming_thread, NULL,
     451                       linux_firewire_device_streaming_thunk, this);
     452
     453        m_lock.unlock();
     454        while (!m_priv->is_streaming_running)
     455            usleep(50);
     456        m_lock.lock();
     457    }
     458    else
     459    {
     460        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming " + ENO);
     461    }
     462
     463    return m_priv->is_streaming;
     464}
     465
     466bool LinuxFirewireDevice::StopStreaming(void)
     467{
     468    VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming");
     469
     470    if (m_priv->is_streaming)
     471    {
     472        m_priv->is_streaming = false;
     473
     474        VERBOSE(VB_RECORD, LOC + "Waiting for A/V streaming to stop");
     475        m_lock.unlock();
     476        while (m_priv->is_streaming_running)
     477            usleep(50);
     478        m_lock.lock();
     479
     480        VERBOSE(VB_RECORD, LOC + "Joining A/V streaming thread");
     481        pthread_join(m_priv->streaming_thread, NULL);
     482
     483        iec61883_mpeg2_recv_stop(m_priv->avstream);
     484
     485        raw1394_iso_recv_flush(m_priv->handle);
     486    }
     487
     488    VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming");
     489
     490    return true;
     491}
     492
     493bool LinuxFirewireDevice::StopStreamingLater(void)
     494{
     495    // TODO
     496    return true;
     497}
     498
     499bool LinuxFirewireDevice::SetAVStreamBufferSize(uint size_in_bytes)
     500{
     501    if (!m_priv->avstream)
     502        return false;
     503
     504    // Set buffered packets size
     505    uint   buffer_size      = max(size_in_bytes, 50 * TSPacket::SIZE);
     506    size_t buffered_packets = min(buffer_size / 4, kMaxBufferedPackets);
     507
     508    iec61883_mpeg2_set_buffers(m_priv->avstream, buffered_packets);
     509
     510    VERBOSE(VB_IMPORTANT, LOC +
     511            QString("Buffered packets %1 (%2 KB)")
     512            .arg(buffered_packets).arg(buffered_packets * 4));
     513
     514    return true;
     515}
     516
     517bool LinuxFirewireDevice::SetAVStreamSpeed(uint speed)
     518{
     519    if (!m_priv->avstream)
     520        return false;
     521
     522    uint curspeed = iec61883_mpeg2_get_speed(m_priv->avstream);
     523
     524    if (curspeed == speed)
     525    {
     526        m_speed = speed;
     527        return true;
     528    }
     529
     530    VERBOSE(VB_RECORD, LOC +
     531            QString("Changing Speed %1 -> %2")
     532            .arg(speed_to_string(curspeed))
     533            .arg(speed_to_string(m_speed)));
     534
     535    iec61883_mpeg2_set_speed(m_priv->avstream, speed);
     536
     537    if (speed == (uint)iec61883_mpeg2_get_speed(m_priv->avstream))
     538    {
     539        m_speed = speed;
     540        return true;
     541    }
     542
     543    VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set firewire speed.");
     544
     545    return false;
     546}
     547
     548bool LinuxFirewireDevice::IsSubunitType(uint subunit_type) const
     549{
     550    for (uint i = 0; i < 8; i++)
     551    {
     552        for (uint j = 0; j < 32; j += 8)
     553        {
     554            uint subunit = (m_priv->unit_table[i] >> j) & 0xff;
     555            if ((subunit != 0xff) &&
     556                (subunit >> 3) == AVC1394_GET_SUBUNIT_TYPE(subunit_type))
     557            {
     558                return true;
     559            }
     560        }
     561    }
     562    return false;
     563}
     564
     565bool LinuxFirewireDevice::IsTuner(void) const
     566{
     567    QMutexLocker locker(&m_lock);
     568
     569    return IsSubunitType(AVC1394_SUBUNIT_TYPE_TUNER);
     570}
     571
     572bool LinuxFirewireDevice::IsPanel(void) const
     573{
     574    QMutexLocker locker(&m_lock);
     575
     576    return IsSubunitType(AVC1394_SUBUNIT_TYPE_PANEL);
     577}
     578
     579bool LinuxFirewireDevice::IsSTB(void) const
     580{
     581    QMutexLocker locker(&m_lock);
     582
     583    return (IsSubunitType(AVC1394_SUBUNIT_TYPE_TUNER) &&
     584            IsSubunitType(AVC1394_SUBUNIT_TYPE_PANEL));
     585}
     586
     587bool LinuxFirewireDevice::IsPortOpen(void) const
     588{
     589    QMutexLocker locker(&m_lock);
     590
     591    return m_priv->handle;
     592}
     593
     594bool LinuxFirewireDevice::IsNodeOpen(void) const
     595{
     596    return m_priv->is_p2p_node_open || m_priv->is_bcast_node_open;
     597}
     598
     599bool LinuxFirewireDevice::IsAVStreamOpen(void) const
     600{
     601    return m_priv->avstream;
     602}
     603
     604bool LinuxFirewireDevice::ResetBus(void)
     605{
     606    if (m_priv->is_streaming)
     607    {
     608        VERBOSE(VB_IMPORTANT, LOC_ERR +
     609                "ResetBus() can not be called while streaming");
     610    }
     611
     612    m_resetting = true;
     613    VERBOSE(VB_IMPORTANT, LOC + "ResetBus() -- begin");
     614
     615    bool open_node     = IsNodeOpen();
     616    bool open_avstream = IsAVStreamOpen();
     617
     618    CloseAVStream();
     619    CloseNode();
     620
     621    bool ok = (raw1394_reset_bus_new(m_priv->handle, RAW1394_LONG_RESET) == 0);
     622    if (!ok)
     623        VERBOSE(VB_IMPORTANT, LOC_ERR + "Bus Reset failed" + ENO);
     624
     625    if (open_node)
     626        ok &= OpenNode();
     627
     628    if (open_avstream)
     629        ok &= OpenAVStream();
     630
     631    VERBOSE(VB_IMPORTANT, LOC + "ResetBus() -- end");
     632    m_resetting = false;
     633
     634    return ok;
     635}
     636
     637bool LinuxFirewireDevice::LoopIteration(uint timeout_in_msec)
     638{
     639    if (m_resetting)
     640        return true;
     641
     642    int fwfd = raw1394_get_fd(m_priv->handle);
     643    if (fwfd < 0)
     644        return false;
     645
     646    struct timeval tv;
     647    fd_set rfds;
     648
     649    FD_ZERO(&rfds);
     650    FD_SET(fwfd, &rfds);
     651
     652    tv.tv_sec  = timeout_in_msec / 1000;
     653    tv.tv_usec = (timeout_in_msec % 1000) * 1000;
     654
     655    m_lock.unlock();
     656    if (select(fwfd + 1, &rfds, NULL, NULL, &tv) <= 0)
     657    {
     658        m_lock.lock();
     659        VERBOSE(VB_IMPORTANT, LOC + QString("No Input in %1 msec...")
     660                .arg(timeout_in_msec));
     661
     662        return false;
     663    }
     664    m_lock.lock();
     665
     666    int ret = raw1394_loop_iterate(m_priv->handle);
     667    if (ret)
     668    {
     669        VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " +
     670                QString("returned %1").arg(ret));
     671
     672        return false;
     673    }
     674
     675    return true;
     676}
     677
     678void LinuxFirewireDevice::AddListener(TSDataListener *listener)
     679{
     680    QMutexLocker locker(&m_lock);
     681
     682    if (listener)
     683    {
     684        vector<TSDataListener*>::iterator it =
     685            find(m_listeners.begin(), m_listeners.end(), listener);
     686
     687        if (it == m_listeners.end())
     688            m_listeners.push_back(listener);
     689    }
     690
     691    VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size());
     692
     693    if (!m_listeners.empty())
     694        StartStreaming();
     695}
     696
     697void LinuxFirewireDevice::RemoveListener(TSDataListener *listener)
     698{
     699    QMutexLocker locker(&m_lock);
     700
     701    vector<TSDataListener*>::iterator it = m_listeners.end();
     702
     703    uint cnt = 0;
     704
     705    do
     706    {
     707        it = find(m_listeners.begin(), m_listeners.end(), listener);
     708        if (it != m_listeners.end())
     709        {
     710            m_listeners.erase(it);
     711            cnt++;
     712        }
     713    }
     714    while (it != m_listeners.end());
     715
     716    if (cnt)
     717    {
     718        VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size());
     719
     720        if (m_priv->is_streaming && m_listeners.empty())
     721            StopStreaming();
     722
     723        CloseAVStream();
     724        CloseNode();
     725    }
     726}
     727
     728void LinuxFirewireDevice::BroadcastToListeners(
     729    const unsigned char *data, uint dataSize)
     730{
     731    vector<TSDataListener*>::iterator it = m_listeners.begin();
     732    for (; it != m_listeners.end(); ++it)
     733        (*it)->AddData(data, dataSize);
     734}
     735
     736bool LinuxFirewireDevice::SetChannel(const QString &panel_model, uint channel)
     737{
     738    QMutexLocker locker(&m_lock);
     739
     740    if (!IsSTBSupported(panel_model))
     741    {
     742        VERBOSE(VB_IMPORTANT, LOC_ERR +
     743                QString("Model: '%1' ").arg(panel_model) +
     744                "is not supported by internal channel changer.");
     745        return false;
     746    }
     747
     748    int digit[3];
     749    digit[0] = (channel % 1000) / 100;
     750    digit[1] = (channel % 100)  / 10;
     751    digit[2] = (channel % 10);
     752
     753    if (panel_model.upper() == "DCT-6200")
     754    {
     755        for (uint i = 0; i < 3 ;i++)
     756        {
     757            quadlet_t cmd[2] =
     758            {
     759                MOT_CMD0 | AVC1394_PANEL_OPERATION_0 | digit[i],
     760                0x0,
     761            };
     762
     763            if (!send_avc_command(m_priv->handle, m_node, cmd, 2))
     764                return false;
     765
     766            usleep(500000);
     767        }
     768
     769        return true;
     770    }
     771
     772    if (panel_model.upper() == "SA4200HD")
     773    {
     774        quadlet_t cmd[3] =
     775        {
     776            SA_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
     777            SA_CMD1 | (channel << 8),
     778            SA_CMD2,
     779        };
     780
     781        if (!send_avc_command(m_priv->handle, m_node, cmd, 3))
     782            return false;
     783
     784        return true;
     785    }
     786   
     787    if (panel_model == "SA3250HD")
     788    {
     789        digit[0] |= 0x30;
     790        digit[1] |= 0x30;
     791        digit[2] |= 0x30;
     792
     793        quadlet_t cmd[3] =
     794        {
     795            SA_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
     796            SA_CMD1 | (digit[2] << 16) | (digit[1] << 8) | digit[0],
     797            SA_CMD2,
     798        };
     799
     800        VERBOSE(VB_CHANNEL, LOC +
     801                QString("Channel2: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
     802                .arg(digit[0] & 0xf).arg(digit[1] & 0xf)
     803                .arg(digit[2] & 0xf)
     804                .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
     805                .arg(cmd[2], 0, 16));
     806
     807        if (!send_avc_command(m_priv->handle, m_node, cmd, 3))
     808            return false;
     809
     810        cmd[0] = SA_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;
     811        cmd[1] = SA_CMD1 | (digit[0] << 16) | (digit[1] << 8) | digit[2];
     812        cmd[2] = SA_CMD2;
     813
     814        VERBOSE(VB_CHANNEL, LOC +
     815                QString("Channel3: %1%2%3 cmds: 0x%4, 0x%5, 0x%6")
     816                .arg(digit[0] & 0xf).arg(digit[1] & 0xf)
     817                .arg(digit[2] & 0xf)
     818                .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16)
     819                .arg(cmd[2], 0, 16));
     820
     821        if (!send_avc_command(m_priv->handle, m_node, cmd, 3))
     822            return false;
     823
     824        return true;
     825    }
     826
     827    return false;
     828}
     829
     830bool LinuxFirewireDevice::SetPowerState(bool on)
     831{
     832    QMutexLocker locker(&m_lock);
     833
     834    quadlet_t cmd =
     835        AVC1394_CTYPE_CONTROL     | AVC1394_SUBUNIT_TYPE_UNIT |
     836        AVC1394_SUBUNIT_ID_IGNORE | AVC1394_COMMAND_POWER;
     837
     838    cmd |= (on) ? AVC1394_CMD_OPERAND_POWER_ON : AVC1394_CMD_OPERAND_POWER_OFF;
     839
     840    QString cmdStr = (on) ? "on" : "off";
     841    VERBOSE(VB_RECORD, LOC + QString("Powering %1 (cmd: 0x%2)")
     842            .arg(cmdStr).arg(cmd, 0, 16));
     843
     844    quadlet_t *rval = send_avc_command(m_priv->handle, m_node, &cmd, 1);
     845
     846    if (!rval)
     847    {
     848        close_avc_command(m_priv->handle);
     849        VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)");
     850        return false;
     851    }
     852
     853    quadlet_t response = rval[0];
     854    close_avc_command(m_priv->handle);
     855
     856    if (AVC1394_MASK_RESPONSE(response) != AVC1394_RESPONSE_ACCEPTED)
     857    {
     858        VERBOSE(VB_IMPORTANT, LOC_ERR +
     859                QString("Power %1 cmd failed (0x%2)")
     860                .arg(cmdStr).arg(response, 0, 16));
     861
     862        return false;
     863    }
     864
     865    VERBOSE(VB_RECORD, LOC +
     866            QString("Power %1 cmd sent successfully (0x%2)")
     867            .arg(cmdStr).arg(response, 0, 16));
     868
     869    return true;
     870}
     871
     872FirewireDevice::PowerState LinuxFirewireDevice::GetPowerState(void)
     873{
     874    QMutexLocker locker(&m_lock);
     875
     876    quadlet_t cmd =
     877        AVC1394_CTYPE_STATUS      | AVC1394_SUBUNIT_TYPE_UNIT |
     878        AVC1394_SUBUNIT_ID_IGNORE | AVC1394_COMMAND_POWER     |
     879        AVC1394_CMD_OPERAND_POWER_STATE;
     880
     881    VERBOSE(VB_CHANNEL, LOC + QString("Requesting STB Power State (cmd: 0x%1)")
     882            .arg(cmd, 0, 16));
     883
     884    quadlet_t *rval = send_avc_command(m_priv->handle, m_node, &cmd, 1);
     885
     886    if (!rval)
     887    {
     888        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get STB Power State");
     889        return kAVCPowerQueryFailed;
     890    }
     891
     892    quadlet_t response = rval[0];
     893    // TODO we probably need to call close_avc_command(m_priv->handle)...
     894
     895    QString loc = LOC + "STB Power State: ";
     896    QString rs  = QString(" (0x%1)").arg(response, 0, 16);
     897
     898    if (AVC1394_MASK_RESPONSE(response) != AVC1394_RESPONSE_IMPLEMENTED)
     899    {
     900        VERBOSE(VB_CHANNEL, loc + "Query not implemented" + rs);
     901        return kAVCPowerUnknown;
     902    }
     903
     904    if (AVC1394_MASK_OPERAND0(response) == AVC1394_CMD_OPERAND_POWER_ON)
     905    {
     906        VERBOSE(VB_CHANNEL, loc + "On" + rs);
     907        return kAVCPowerOn;
     908    }
     909
     910    if (AVC1394_MASK_OPERAND0(response) == AVC1394_CMD_OPERAND_POWER_OFF)
     911    {
     912        VERBOSE(VB_CHANNEL, loc + "Off" + rs);
     913        return kAVCPowerOff;
     914    }
     915   
     916    VERBOSE(VB_IMPORTANT, LOC_ERR + "STB Power State: Unknown Response" + rs);
     917
     918    return kAVCPowerUnknown;
     919}
     920
     921void LinuxFirewireDevice::PrintDropped(uint dropped_packets)
     922{
     923    if (dropped_packets == 1)
     924    {
     925        VERBOSE(VB_RECORD, LOC_ERR + "Dropped a TS packet");
     926    }
     927    else if (dropped_packets > 1)
     928    {
     929        VERBOSE(VB_RECORD, LOC_ERR +
     930                QString("Dropped %1 TS packets").arg(dropped_packets));
     931    }
     932}
     933
     934int linux_firewire_device_tspacket_handler(
     935    unsigned char *tspacket, int len, uint dropped, void *callback_data)
     936{
     937    LinuxFirewireDevice *fw = (LinuxFirewireDevice*) callback_data;
     938    if (!fw)
     939        return 0;
     940
     941    if (dropped)
     942        fw->PrintDropped(dropped);
     943
     944    if (len > 0)
     945        fw->BroadcastToListeners(tspacket, len);
     946
     947    return 1;
     948}
     949
     950static QString speed_to_string(uint speed)
     951{
     952    if (speed > RAW1394_ISO_SPEED_400)
     953        return QString("Invalid Speed (%1)").arg(speed);
     954
     955    static const uint speeds[] = { 100, 200, 400, };
     956    return QString("%1Mbps").arg(speeds[speed]);
     957}
     958
     959static quadlet_t *send_avc_command(raw1394handle_t handle,
     960                                   uint            node,
     961                                   quadlet_t      *cmd,
     962                                   uint            cmd_len,
     963                                   uint            retry_cnt)
     964{
     965    if (!handle)
     966        return NULL;
     967
     968    quadlet_t *ret = avc1394_transaction_block(
     969        handle, node, cmd, cmd_len, retry_cnt);
     970
     971    if (!ret)
     972        VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
     973
     974    return ret;
     975}
     976
     977static void close_avc_command(raw1394handle_t handle)
     978{
     979    if (handle)
     980        avc1394_transaction_block_close(handle);
     981}
     982