Ticket #1648: firewire-sm-v31.patch

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

Fixes another bug, the Firewire recorder was tuning on the channum instead of the freqid

  • configure

     
    24502450
    24512451if test x"$firewire_cable_box" = x"yes" ; then
    24522452    firewire_cable_box="no"
    2453     if has_library libiec61883 -a has_library libavc1394 ; then
     2453    if has_library libiec61883 -a has_library libavc1394 -a has_library librom1394; then
    24542454        if test x`which pkg-config 2>/dev/null` != x"" ; then
    24552455            if `pkg-config --atleast-version 0.5.0 libavc1394` ; then
    24562456                if `pkg-config --atleast-version 1.0.0 libiec61883` ; then
     
    34343434  if test x"$darwin" = x"yes" ; then
    34353435      echo "CONFIG_MAC_AVC=$mac_avc" >>  $MYTH_CONFIG_MAK
    34363436  else
    3437       echo "CONFIG_FIREWIRE_LIBS=-lraw1394 -liec61883 -lavc1394" >>  $MYTH_CONFIG_MAK
     3437      echo "CONFIG_FIREWIRE_LIBS=-lraw1394 -liec61883 -lavc1394 -lrom1394" >>  $MYTH_CONFIG_MAK
    34383438  fi
    34393439fi
    34403440
  • libs/libmythtv/firewirechannel.cpp

     
    11/**
    22 *  FirewireChannel
    3  *  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
     3 *  Copyright (c) 2005 by Jim Westfall, Dave Abrahams
     4 *  Copyright (c) 2006 by Daniel Kristjansson
    65 *  Distributed as part of MythTV under GPL v2 and later.
    76 */
    87
    9 
    10 #include <iostream>
    118#include "mythcontext.h"
     9#include "tv_rec.h"
     10#include "linuxfirewiredevice.h"
     11#include "darwinfirewiredevice.h"
    1212#include "firewirechannel.h"
    1313
    14 class TVRec;
     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())
    1517
    16 #define LOC QString("FireChan: ")
    17 #define LOC_ERR QString("FireChan, Error: ")
    18 
    19 #ifndef AVC1394_PANEL_COMMAND_PASS_THROUGH
    20 #define AVC1394_PANEL_COMMAND_PASS_THROUGH     0x000007C00
     18FirewireChannel::FirewireChannel(TVRec *parent, const QString &_videodevice,
     19                                 const FireWireDBOptions &firewire_opts) :
     20    DTVChannel(parent),
     21    videodevice(_videodevice),
     22    fw_opts(firewire_opts),
     23    device(NULL),
     24    current_channel(0),
     25    isopen(false)
     26{
     27    uint64_t guid = videodevice.toULongLong(NULL, 16);
     28    uint subunitid = 0; // we only support first tuner on STB...
     29#ifdef USING_LINUX_FIREWIRE
     30    device = new LinuxFirewireDevice(
     31        guid, subunitid, fw_opts.speed,
     32        LinuxFirewireDevice::kConnectionP2P == (uint) fw_opts.connection);
     33#elif USING_OSX_FIREWIRE
     34    device = new DarwinFirewireDevice(guid, subunitid, fw_opts.speed);
    2135#endif
    2236
    23 #ifndef AVC1394_PANEL_OPERATION_0
    24 #define AVC1394_PANEL_OPERATION_0              0x000000020
    25 #endif
     37    InitializeInputs();
     38}
    2639
    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)
     40bool FirewireChannel::SetChannelByString(const QString &channum)
     41{
     42    InputMap::const_iterator it = inputs.find(currentInputID);
     43    if (it == inputs.end())
     44        return false;
    3245
    33 // SA3250HD defines
    34 #define AVC1394_SA3250_OPERAND_KEY_PRESS        0xE7
    35 #define AVC1394_SA3250_OPERAND_KEY_RELEASE      0x67
     46    // Fetch tuning data from the database.
     47    QString tvformat, modulation, freqtable, freqid, dtv_si_std;
     48    int finetune;
     49    uint64_t frequency;
     50    int mpeg_prog_num;
     51    uint atsc_major, atsc_minor, mplexid, tsid, netid;
    3652
    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
     53    if (!ChannelUtil::GetChannelData(
     54        (*it)->sourceid, channum,
     55        tvformat, modulation, freqtable, freqid,
     56        finetune, frequency,
     57        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
     58        mplexid, commfree))
     59    {
     60        return false;
     61    }
    4362
    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)
     63    bool ok = false;
     64    if (!(*it)->externalChanger.isEmpty())
     65        ok = ChangeExternalChannel(freqid);
     66    else
     67    {
     68        uint ichan = freqid.toUInt(&ok);
     69        ok = ok && isopen && SetChannelByNumber(ichan);
     70    }
    5171
    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)
     72    if (ok)
     73    {
     74        // Set the current channum to the new channel's channum
     75        curchannelname = QDeepCopy<QString>(channum);
     76        (*it)->startChanNum = QDeepCopy<QString>(channum);
     77    }
    5778
    58 static bool is_supported(const QString &model)
    59 {
    60     return ((model == "DCT-6200") ||
    61             (model == "SA3250HD") ||
    62             (model == "SA4200HD"));
     79    return ok;
    6380}
    6481
    65 FirewireChannel::FirewireChannel(FireWireDBOptions firewire_opts,
    66                                  TVRec *parent)
    67     : FirewireChannelBase(parent), fw_opts(firewire_opts), fwhandle(NULL)
     82bool FirewireChannel::Open(void)
    6883{
    69 }
     84    VERBOSE(VB_CHANNEL, LOC + "Open()");
    7085
    71 FirewireChannel::~FirewireChannel(void)
    72 {
    73     Close();
    74 }
     86    if (inputs.find(currentInputID) == inputs.end())
     87        return false;
    7588
    76 bool FirewireChannel::SetChannelByNumber(int channel)
    77 {
    78     // Change channel using internal changer
     89    if (!device)
     90        return false;
    7991
    80     if (!is_supported(fw_opts.model))
     92    if (isopen)
     93        return true;
     94
     95    InputMap::const_iterator it = inputs.find(currentInputID);
     96    if (!FirewireDevice::IsSTBSupported(fw_opts.model) &&
     97        (*it)->externalChanger.isEmpty())
    8198    {
    8299        VERBOSE(VB_IMPORTANT, LOC_ERR +
    83                 QString("Model: '%1' ").arg(fw_opts.model) +
    84                 "is not supported by internal channel changer.");
     100                QString("Model: '%1' is not supported.").arg(fw_opts.model));
     101
    85102        return false;
    86103    }
    87104
    88     int dig[3];
    89     dig[0] = (channel % 1000) / 100;
    90     dig[1] = (channel % 100)  / 10;
    91     dig[2] = (channel % 10);
     105    if (!device->OpenPort())
     106        return false;
    92107
    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));
     108    isopen = true;
    101109
    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")
     110    return true;
     111}
     112
     113void FirewireChannel::Close(void)
     114{
     115    VERBOSE(VB_CHANNEL, LOC + "Close()");
     116    if (isopen)
    114117    {
    115         dig[0] |= 0x30;
    116         dig[1] |= 0x30;
    117         dig[2] |= 0x30;
     118        device->ClosePort();
     119        isopen = false;
     120    }
     121}
    118122
    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         };
     123bool FirewireChannel::SwitchToInput(const QString &input, const QString &chan)
     124{
     125    int inputNum = GetInputByName(input);
     126    if (inputNum < 0)
     127        return false;
    125128
    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));
     129    return SetChannelByString(chan);
     130}
    132131
    133         if(!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
    134         {
    135             VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    136             return false;
    137         }
     132bool FirewireChannel::SwitchToInput(int newInputNum, bool setstarting)
     133{
     134    (void) setstarting;
    138135
    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;
     136    InputMap::const_iterator it = inputs.find(newInputNum);
     137    if (it == inputs.end() || (*it)->startChanNum.isEmpty())
     138        return false;
    142139
    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));
     140    return SetChannelByString((*it)->startChanNum);
     141}
    149142
    150         if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
    151         {
    152             VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    153             return false;
    154         }
    155     }
    156     else if (fw_opts.model == "SA4200HD")
     143QString FirewireChannel::GetDevice(void) const
     144{
     145    return videodevice;
     146}
     147
     148bool FirewireChannel::SetPowerState(bool on)
     149{
     150    if (!isopen)
    157151    {
    158         quadlet_t cmd[3] =
    159         {
    160             SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS,
    161             SA3250_CMD1 | (channel << 8),
    162             SA3250_CMD2,
    163         };
     152        VERBOSE(VB_IMPORTANT, LOC_ERR +
     153                "SetPowerState() called on closed FirewireChannel.");
    164154
    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));
    170 
    171         if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1))
    172         {
    173             VERBOSE(VB_IMPORTANT, "AVC transaction failed.");
    174             return false;
    175         }
     155        return false;
    176156    }
    177157
    178     return true;
     158    return device->SetPowerState(on);
    179159}
    180160
    181 bool FirewireChannel::OpenFirewire(void)
     161FirewireDevice::PowerState FirewireChannel::GetPowerState(void) const
    182162{
    183     if (!is_supported(fw_opts.model))
     163    if (!isopen)
    184164    {
    185165        VERBOSE(VB_IMPORTANT, LOC_ERR +
    186                 QString("Model: '%1' ").arg(fw_opts.model) +
    187                 "is not supported by internal channel changer.");
    188         return false;
    189     }
     166                "GetPowerState() called on closed FirewireChannel.");
    190167
    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));
    197         return false;
     168        return FirewireDevice::kAVCPowerQueryFailed;
    198169    }
    199170
    200     VERBOSE(VB_CHANNEL, LOC + "Allocated raw1394 handle " +
    201             QString("for port %1").arg(fw_opts.port));
     171    return device->GetPowerState();
     172}
    202173
    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();
    210         return false;
    211     }
     174bool FirewireChannel::Retune(void)
     175{
     176    VERBOSE(VB_CHANNEL, LOC + "Retune()");
    212177
    213     if (!avc1394_check_subunit_type(fwhandle, fw_opts.node,
    214                                     AVC1394_SUBUNIT_TYPE_PANEL))
     178    if (FirewireDevice::kAVCPowerOff == GetPowerState())
    215179    {
    216         VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit "
    217                 "type panel.").arg(fw_opts.node));
    218         CloseFirewire();
     180        VERBOSE(VB_IMPORTANT, LOC_ERR +
     181                "STB is turned off, must be on to retune.");
     182
    219183        return false;
    220184    }
    221185
    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];
     186    if (current_channel)
     187        return SetChannelByNumber(current_channel);
    232188
    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     }
    261     return true;
     189    return false;
    262190}
    263191
    264 void FirewireChannel::CloseFirewire(void)
     192bool FirewireChannel::SetChannelByNumber(int channel)
    265193{
    266     VERBOSE(VB_CHANNEL, LOC + "Releasing raw1394 handle");
    267     raw1394_destroy_handle(fwhandle);
    268 }
     194    current_channel = channel;
    269195
    270 FirewireChannel::PowerState FirewireChannel::GetPowerState(void)
    271 {
    272     quadlet_t *rval, response, cmd = STB_POWER_STATE;
    273 
    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)
     196    if (FirewireDevice::kAVCPowerOff == GetPowerState())
    279197    {
    280         response = rval[0];
     198        VERBOSE(VB_IMPORTANT, LOC_WARN +
     199                "STB is turned off, must be on to set channel.");
    281200
    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         }
     201        SetSIStandard("mpeg");
     202        SetCachedATSCInfo(QString("%1-1").arg(channel));
     203
     204        return true; // signal monitor will call retune later...
    311205    }
    312     VERBOSE(VB_CHANNEL, LOC + "Failed to get STB Power State");
    313     return Failed;
     206
     207    if (!device->SetChannel(fw_opts.model, 0, channel))
     208        return false;
     209
     210    SetSIStandard("mpeg");
     211    SetCachedATSCInfo(QString("%1-1").arg(channel));
     212
     213    return true;
    314214}
  • libs/libmythtv/firewirerecorderbase.h

     
    1 /**
    2  *  FirewireRecorderBase
    3  *  Copyright (c) 2005 by Jim Westfall
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 #ifndef FIREWIRERECORDERBASE_H_
    8 #define FIREWIRERECORDERBASE_H_
    9 
    10 #include "dtvrecorder.h"
    11 #include "tsstats.h"
    12 #include "tspacket.h"
    13 #include "streamlisteners.h"
    14 
    15 /** \class FirewireRecorderBase
    16  *  \brief This is a specialization of DTVRecorder used to
    17  *         handle DVB and ATSC streams from a firewire input.
    18  *
    19  *  \sa DTVRecorder
    20  */
    21 class FirewireRecorderBase : public DTVRecorder,
    22                              public MPEGSingleProgramStreamListener
    23 {
    24     friend class MPEGStreamData;
    25     friend class TSPacketProcessor;
    26 
    27   public:
    28     FirewireRecorderBase(TVRec *rec);
    29     ~FirewireRecorderBase();
    30  
    31     // Commands
    32     void StartRecording(void);
    33     void ProcessTSPacket(const TSPacket &tspacket);
    34     bool PauseAndWait(int timeout = 100);
    35 
    36     // Sets
    37     void SetOptionsFromProfile(RecordingProfile *profile,
    38                                const QString &videodev,
    39                                const QString &audiodev,
    40                                const QString &vbidev);
    41     void SetStreamData(MPEGStreamData*);
    42 
    43     // Gets
    44     MPEGStreamData* StreamData(void) { return _mpeg_stream_data; }
    45 
    46     // MPEG Single Program
    47     void HandleSingleProgramPAT(ProgramAssociationTable*);
    48     void HandleSingleProgramPMT(ProgramMapTable*);
    49 
    50   private:
    51     virtual void Close() = 0;
    52     virtual void start() = 0;
    53     virtual void stop() = 0;
    54     virtual bool grab_frames() = 0;
    55 
    56     MPEGStreamData  *_mpeg_stream_data;
    57     TSStats          _ts_stats;   
    58 
    59   protected:
    60     static const int  kTimeoutInSeconds;
    61 };
    62 
    63 #endif
  • libs/libmythtv/firewirechannelbase.h

     
    1 /**
    2  *  FirewireChannelBase
    3  *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 
    8 #ifndef LIBMYTHTV_FIREWIRECHANNELBASE_H
    9 #define LIBMYTHTV_FIREWIRECHANNELBASE_H
    10 
    11 #include <qstring.h>
    12 #include "tv_rec.h"
    13 #include "channelbase.h"
    14 
    15 #include "mythconfig.h"
    16 
    17 namespace AVS
    18 {
    19   class AVCDeviceController;
    20   class AVCDevice;
    21 }
    22 
    23 class FirewireChannelBase : public ChannelBase
    24 {
    25   public:
    26     FirewireChannelBase(TVRec *parent)   
    27         : ChannelBase(parent), isopen(false) { }
    28     ~FirewireChannelBase() { Close(); }
    29 
    30     bool Open(void);
    31     void Close(void);
    32 
    33     // Sets
    34     bool SetChannelByString(const QString &chan);
    35     virtual bool SetChannelByNumber(int channel) = 0;
    36 
    37     // Gets
    38     bool IsOpen(void) const { return isopen; }
    39 
    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; }
    44 
    45   private:
    46     virtual bool OpenFirewire() = 0;
    47     virtual void CloseFirewire() = 0;
    48 
    49   protected:
    50     bool isopen;
    51 };
    52 
    53 #endif
  • libs/libmythtv/firewiredevice.cpp

     
     1/**
     2 *  FirewireDevice
     3 *  Copyright (c) 2005 by Jim Westfall
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7// Qt headers
     8#include <qdeepcopy.h>
     9
     10// MythTV headers
     11#include "linuxfirewiredevice.h"
     12#include "darwinfirewiredevice.h"
     13#include "mythcontext.h"
     14#include "pespacket.h"
     15
     16#define LOC      QString("FireDev(%1): ").arg(m_guid)
     17#define LOC_WARN QString("FireDev(%1), Warning: ").arg(m_guid)
     18#define LOC_ERR  QString("FireDev(%1), Error: ").arg(m_guid)
     19
     20
     21AVCInfo::AVCInfo() :
     22    port(-1), node(-1),
     23    guid(0), specid(0), vendorid(0), modelid(0),
     24    firmware_revision(0), product_name(QString::null)
     25{
     26}
     27
     28AVCInfo::AVCInfo(const AVCInfo &o) :
     29    port(o.port),         node(o.node),
     30    guid(o.guid),         specid(o.specid),
     31    vendorid(o.vendorid), modelid(o.modelid),
     32    firmware_revision(o.firmware_revision),
     33    product_name(QDeepCopy<QString>(o.product_name))
     34{
     35}
     36
     37AVCInfo &AVCInfo::operator=(const AVCInfo &o)
     38{
     39    port     = o.port;
     40    node     = o.node;
     41    guid     = o.guid;
     42    specid   = o.specid;
     43    vendorid = o.vendorid;
     44    modelid  = o.modelid;
     45    firmware_revision = o.firmware_revision;
     46    product_name = QDeepCopy<QString>(o.product_name);
     47
     48    return *this;
     49}
     50
     51QString AVCInfo::GetGUIDString(void) const
     52{
     53    QString g0 = QString("%1").arg((uint32_t) (guid >> 32), 0, 16);
     54    QString g1 = QString("%1").arg((uint32_t) guid, 0, 16);
     55
     56    while (g0.length() < 8)
     57        g0 = "0" + g0;
     58    while (g1.length() < 8)
     59        g1 = "0" + g1;
     60
     61    return QDeepCopy<QString>(g0.upper() + g1.upper());
     62}
     63
     64static void fw_init(QMap<uint64_t,QString> &id_to_model);
     65
     66QMap<uint64_t,QString> FirewireDevice::s_id_to_model;
     67QMutex                 FirewireDevice::s_static_lock;
     68
     69FirewireDevice::FirewireDevice(uint64_t guid, uint subunitid, uint speed) :
     70    m_guid(guid),           m_subunitid(subunitid),
     71    m_speed(speed),
     72    m_last_channel(0),      m_last_crc(0),
     73    m_buffer_cleared(true), m_open_port_cnt(0),
     74    m_lock(false)
     75{
     76}
     77
     78void FirewireDevice::AddListener(TSDataListener *listener)
     79{
     80    QMutexLocker locker(&m_lock);
     81
     82    if (listener)
     83    {
     84        vector<TSDataListener*>::iterator it =
     85            find(m_listeners.begin(), m_listeners.end(), listener);
     86
     87        if (it == m_listeners.end())
     88            m_listeners.push_back(listener);
     89    }
     90
     91    VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size());
     92}
     93
     94void FirewireDevice::RemoveListener(TSDataListener *listener)
     95{
     96    QMutexLocker locker(&m_lock);
     97
     98    vector<TSDataListener*>::iterator it = m_listeners.end();
     99
     100    do
     101    {
     102        it = find(m_listeners.begin(), m_listeners.end(), listener);
     103        if (it != m_listeners.end())
     104            m_listeners.erase(it);
     105    }
     106    while (it != m_listeners.end());
     107
     108    VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size());
     109}
     110
     111bool FirewireDevice::SetPowerState(bool on)
     112{
     113    QMutexLocker locker(&m_lock);
     114
     115    vector<uint8_t> cmd;
     116    vector<uint8_t> ret;
     117
     118    cmd.push_back(kAVCControlCommand);
     119    cmd.push_back(kAVCSubunitTypeUnit | kAVCSubunitIdIgnore);
     120    cmd.push_back(kAVCUnitPowerOpcode);
     121    cmd.push_back((on) ? kAVCPowerStateOn : kAVCPowerStateOff);
     122
     123    QString cmdStr = (on) ? "on" : "off";
     124    VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr));
     125
     126    if (SendAVCCommand(cmd, ret, -1))
     127    {
     128        VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)");
     129        return false;
     130    }
     131
     132    if (kAVCAcceptedStatus != ret[0])
     133    {
     134        VERBOSE(VB_IMPORTANT, LOC_ERR +
     135                QString("Power %1 failed").arg(cmdStr));
     136
     137        return false;
     138    }
     139
     140    VERBOSE(VB_RECORD, LOC +
     141            QString("Power %1 cmd sent successfully").arg(cmdStr));
     142
     143    return true;
     144}
     145
     146FirewireDevice::PowerState FirewireDevice::GetPowerState(void)
     147{
     148    QMutexLocker locker(&m_lock);
     149
     150    vector<uint8_t> cmd;
     151    vector<uint8_t> ret;
     152
     153    cmd.push_back(kAVCStatusInquiryCommand);
     154    cmd.push_back(kAVCSubunitTypeUnit | kAVCSubunitIdIgnore);
     155    cmd.push_back(kAVCUnitPowerOpcode);
     156    cmd.push_back(kAVCPowerStateQuery);
     157
     158    VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State");
     159
     160    if (!SendAVCCommand(cmd, ret, -1))
     161    {
     162        VERBOSE(VB_IMPORTANT, LOC_ERR + "Power cmd failed (no response)");
     163        return kAVCPowerQueryFailed;
     164    }
     165
     166    QString loc = LOC + "STB Power State: ";
     167
     168    if (ret[0] != kAVCResponseImplemented)
     169    {
     170        VERBOSE(VB_CHANNEL, loc + "Query not implemented");
     171        return kAVCPowerUnknown;
     172    }
     173
     174    // check 1st operand..
     175    if (ret[3] == kAVCPowerStateOn)
     176    {
     177        VERBOSE(VB_CHANNEL, loc + "On");
     178        return kAVCPowerOn;
     179    }
     180
     181    if (ret[3] == kAVCPowerStateOff)
     182    {
     183        VERBOSE(VB_CHANNEL, loc + "Off");
     184        return kAVCPowerOff;
     185    }
     186
     187    VERBOSE(VB_IMPORTANT, LOC_ERR + "STB Power State: Unknown Response");
     188
     189    return kAVCPowerUnknown;
     190}
     191
     192bool FirewireDevice::GetSubunitInfo(uint8_t table[32])
     193{
     194    memset(table, 0xff, 32 * sizeof(uint8_t));
     195
     196    for (uint i = 0; i < 8; i++)
     197    {
     198        vector<uint8_t> cmd;
     199        vector<uint8_t> ret;
     200
     201        cmd.push_back(kAVCStatusInquiryCommand);
     202        cmd.push_back(kAVCSubunitTypeUnit | kAVCSubunitIdIgnore);
     203        cmd.push_back(kAVCUnitSubunitInfoOpcode);
     204        cmd.push_back((i<<4) | 0x07);
     205        cmd.push_back(0xFF);
     206        cmd.push_back(0xFF);
     207        cmd.push_back(0xFF);
     208        cmd.push_back(0xFF);
     209
     210        if (!SendAVCCommand(cmd, ret, -1))
     211            return false;
     212
     213        if (ret.size() >= 8)
     214        {
     215            table[(i<<2)+0] = ret[4];
     216            table[(i<<2)+1] = ret[5];
     217            table[(i<<2)+2] = ret[6];
     218            table[(i<<2)+3] = ret[7];
     219        }
     220    }
     221
     222    return true;
     223}
     224
     225bool FirewireDevice::SetChannel(const QString &panel_model,
     226                                uint alt_method, uint channel)
     227{
     228    QMutexLocker locker(&m_lock);
     229
     230    if (!IsSTBSupported(panel_model))
     231    {
     232        VERBOSE(VB_IMPORTANT, LOC_ERR +
     233                QString("Model: '%1' ").arg(panel_model) +
     234                "is not supported by internal channel changer.");
     235        return false;
     236    }
     237
     238    int digit[3];
     239    digit[0] = (channel % 1000) / 100;
     240    digit[1] = (channel % 100)  / 10;
     241    digit[2] = (channel % 10);
     242
     243    if (m_subunitid >= kAVCSubunitIdExtended)
     244        return false;
     245
     246    vector<uint8_t> cmd;
     247    vector<uint8_t> ret;
     248
     249    if ((panel_model.upper() == "GENERIC") ||
     250        (panel_model.upper() == "SA4200HD"))
     251    {
     252        cmd.push_back(kAVCControlCommand);
     253        cmd.push_back(kAVCSubunitTypePanel | m_subunitid);
     254        cmd.push_back(kAVCPanelPassThrough);
     255        cmd.push_back(kAVCPanelKeyTuneFunction | kAVCPanelKeyPress);
     256
     257        cmd.push_back(4); // operand length
     258        cmd.push_back((channel>>8) & 0x0f);
     259        cmd.push_back(channel & 0xff);
     260        cmd.push_back(0x00);
     261        cmd.push_back(0x00);
     262
     263        if (!SendAVCCommand(cmd, ret, -1))
     264            return false;
     265
     266        bool press_ok = (kAVCAcceptedStatus == ret[0]);
     267
     268        cmd[3]= kAVCPanelKeyTuneFunction | kAVCPanelKeyRelease;
     269        if (!SendAVCCommand(cmd, ret, -1))
     270            return false;
     271
     272        bool release_ok = (kAVCAcceptedStatus == ret[0]);
     273
     274        if (!press_ok && !release_ok)
     275        {
     276            VERBOSE(VB_IMPORTANT, LOC_ERR + "Tuning failed");
     277            return false;
     278        }
     279
     280        SetLastChannel(channel);
     281        return true;
     282    }
     283
     284    bool is_mot = ((panel_model.upper() == "DCT-6200") ||
     285                   (panel_model.upper() == "DCT-6212") ||
     286                   (panel_model.upper() == "DCT-6216"));
     287
     288    if (is_mot && !alt_method)
     289    {
     290        for (uint i = 0; i < 3 ;i++)
     291        {
     292            cmd.push_back(kAVCControlCommand);
     293            cmd.push_back(kAVCSubunitTypePanel | m_subunitid);
     294            cmd.push_back(kAVCPanelPassThrough);
     295            cmd.push_back(kAVCPanelKey0 + digit[i] | kAVCPanelKeyPress);
     296            cmd.push_back(0x00);
     297            cmd.push_back(0x00);
     298            cmd.push_back(0x00);
     299            cmd.push_back(0x00);
     300
     301            if (!SendAVCCommand(cmd, ret, -1))
     302                return false;
     303
     304            usleep(500000);
     305        }
     306
     307        SetLastChannel(channel);
     308        return true;
     309    }
     310
     311    if (is_mot && alt_method)
     312    {
     313        cmd.push_back(kAVCControlCommand);
     314        cmd.push_back(kAVCSubunitTypePanel | m_subunitid);
     315        cmd.push_back(kAVCPanelPassThrough);
     316        cmd.push_back(kAVCPanelKeyTuneFunction | kAVCPanelKeyPress);
     317
     318        cmd.push_back(4); // operand length
     319        cmd.push_back((channel>>8) & 0x0f);
     320        cmd.push_back(channel & 0xff);
     321        cmd.push_back(0x00);
     322        cmd.push_back(0xff);
     323
     324        if (!SendAVCCommand(cmd, ret, -1))
     325            return false;
     326
     327        SetLastChannel(channel);
     328        return true;
     329    }
     330
     331    if (panel_model.upper() == "SA3250HD")
     332    {
     333        cmd.push_back(kAVCControlCommand);
     334        cmd.push_back(kAVCSubunitTypePanel | m_subunitid);
     335        cmd.push_back(kAVCPanelPassThrough);
     336        cmd.push_back(kAVCPanelKeyTuneFunction | kAVCPanelKeyRelease);
     337
     338        cmd.push_back(4); // operand length
     339        cmd.push_back(0x30 | digit[2]);
     340        cmd.push_back(0x30 | digit[1]);
     341        cmd.push_back(0x30 | digit[0]);
     342        cmd.push_back(0xff);
     343
     344        if (!SendAVCCommand(cmd, ret, -1))
     345            return false;
     346
     347        cmd[5] = 0x30 | digit[0];
     348        cmd[6] = 0x30 | digit[1];
     349        cmd[7] = 0x30 | digit[2];
     350
     351        if (!SendAVCCommand(cmd, ret, -1))
     352            return false;
     353
     354        SetLastChannel(channel);
     355        return true;
     356    }
     357
     358    return false;
     359}
     360
     361void FirewireDevice::BroadcastToListeners(
     362    const unsigned char *data, uint dataSize)
     363{
     364    if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) &&
     365        ((data[1] & 0x1f) == 0) && (data[2] == 0))
     366    {
     367        ProcessPATPacket(*((const TSPacket*)data));
     368    }
     369
     370    vector<TSDataListener*>::iterator it = m_listeners.begin();
     371    for (; it != m_listeners.end(); ++it)
     372        (*it)->AddData(data, dataSize);
     373}
     374
     375void FirewireDevice::SetLastChannel(const uint channel)
     376{
     377    m_buffer_cleared = (channel == m_last_channel);
     378    m_last_channel   = channel;
     379
     380    VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2")
     381            .arg(channel).arg(m_buffer_cleared ? "yes" : "no"));
     382}
     383
     384void FirewireDevice::ProcessPATPacket(const TSPacket &tspacket)
     385{
     386    if (!tspacket.TransportError() && !tspacket.ScramplingControl() &&
     387        tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID())
     388    {
     389        PESPacket pes = PESPacket::View(tspacket);
     390        uint crc = pes.CalcCRC();
     391        m_buffer_cleared |= (crc != m_last_crc);
     392        m_last_crc = crc;
     393        VERBOSE(VB_RECORD, LOC +
     394                QString("ProcessPATPacket: CRC 0x%1 cleared: %2")
     395                .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no"));
     396    }
     397    else
     398    {
     399        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's");
     400    }
     401}
     402
     403QString FirewireDevice::GetModelName(uint vendor_id, uint model_id)
     404{
     405    QMutexLocker locker(&s_static_lock);
     406    if (s_id_to_model.empty())
     407        fw_init(s_id_to_model);
     408
     409    QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id];
     410
     411    if (ret.isEmpty())
     412        return "GENERIC";
     413
     414    return QDeepCopy<QString>(ret);
     415}
     416
     417vector<AVCInfo> FirewireDevice::GetSTBList(void)
     418{
     419    vector<AVCInfo> list;
     420
     421#ifdef USING_LINUX_FIREWIRE
     422    list = LinuxFirewireDevice::GetSTBList();
     423#elif USING_OSX_FIREWIRE
     424    list = DarwinFirewireDevice::GetSTBList();
     425#endif
     426
     427//#define DEBUG_AVC_INFO
     428#ifdef DEBUG_AVC_INFO
     429    AVCInfo info;
     430    info.guid     = 0x0016928a7b600001ULL;
     431    info.specid   = 0x0;
     432    info.vendorid = 0x000014f8;
     433    info.modelid  = 0x00001072;
     434    info.firmware_revision = 0x0;
     435    info.product_name = "Explorer 4200 HD";
     436    list.push_back(info);
     437
     438    info.guid     = 0xff2145a850e39810ULL;
     439    info.specid   = 0x0;
     440    info.vendorid = 0x000014f8;
     441    info.modelid  = 0x00000be0;
     442    info.firmware_revision = 0x0;
     443    info.product_name = "Explorer 3250 HD";
     444    list.push_back(info);
     445#endif // DEBUG_AVC_INFO
     446
     447    return list;
     448}
     449
     450bool FirewireDevice::IsSubunitType(
     451    const uint8_t unit_table[32], IEEE1394UnitAddress subunit_type)
     452{
     453    for (uint i = 0; i < 32; i++)
     454    {
     455        int subunit = unit_table[i];
     456        if ((subunit != 0xff) &&
     457            (subunit & kAVCSubunitTypeUnit) == subunit_type)
     458        {
     459            return true;
     460        }
     461    }
     462
     463    return false;
     464}
     465
     466QString FirewireDevice::GetSubunitInfoString(const uint8_t table[32])
     467{
     468    QString str = "Subunit Types: ";
     469
     470    if (IsSubunitType(table, kAVCSubunitTypeVideoMonitor))
     471        str += "Video Monitor, ";
     472    if (IsSubunitType(table, kAVCSubunitTypeAudio))
     473        str += "Audio, ";
     474    if (IsSubunitType(table, kAVCSubunitTypePrinter))
     475        str += "Printer, ";
     476    if (IsSubunitType(table, kAVCSubunitTypeDiscRecorder))
     477        str += "Disk Recorder, ";
     478    if (IsSubunitType(table, kAVCSubunitTypeTapeRecorder))
     479        str += "Tape Recorder, ";
     480    if (IsSubunitType(table, kAVCSubunitTypeTuner))
     481        str += "Tuner, ";
     482    if (IsSubunitType(table, kAVCSubunitTypeCA))
     483        str += "CA, ";
     484    if (IsSubunitType(table, kAVCSubunitTypeVideoCamera))
     485        str += "Camera, ";
     486    if (IsSubunitType(table, kAVCSubunitTypePanel))
     487        str += "Panel, ";
     488    if (IsSubunitType(table, kAVCSubunitTypeBulletinBoard))
     489        str += "Bulletin Board, ";
     490    if (IsSubunitType(table, kAVCSubunitTypeCameraStorage))
     491        str += "Camera Storage, ";
     492    if (IsSubunitType(table, kAVCSubunitTypeMusic))
     493        str += "Music, ";
     494    if (IsSubunitType(table, kAVCSubunitTypeVendorUnique))
     495        str += "Vendor Unique, ";
     496
     497    return str;
     498}
     499
     500static void fw_init(QMap<uint64_t,QString> &id_to_model)
     501{
     502    id_to_model[0x11e6ULL << 32 | 0x0be0] = "SA3250HD";
     503    id_to_model[0x14f8ULL << 32 | 0x0be0] = "SA3250HD";
     504    id_to_model[0x1692ULL << 32 | 0x0be0] = "SA3250HD";
     505
     506    id_to_model[0x11e6ULL << 32 | 0x1072] = "SA4200HD";
     507    id_to_model[0x14f8ULL << 32 | 0x1072] = "SA4200HD";
     508    id_to_model[0x1692ULL << 32 | 0x1072] = "SA4200HD";
     509
     510    const uint64_t motorolla_vendor_ids[] =
     511    {   /* 6200 */
     512        0x0ce5,    0x0e5c,    0x1225,    0x0f9f,    0x1180,
     513        0x12c9,    0x11ae,    0x152f,    0x14e8,    0x16b5,    0x1371,
     514        /* 6412 */
     515        0x0f9f,    0x152f,
     516        /* 6416 */
     517        0x17ee,
     518    };
     519    const uint motorolla_vendor_id_cnt =
     520        sizeof(motorolla_vendor_ids) / sizeof(uint32_t);
     521
     522    const uint32_t motorolla_6200model_ids[] = { 0x620a, 0x6200, };
     523    const uint32_t motorolla_6212model_ids[] = { 0x64ca, 0x64cb, };
     524    const uint32_t motorolla_6216model_ids[] = { 0x646b, };
     525
     526    for (uint i = 0; i < motorolla_vendor_id_cnt; i++)
     527        for (uint j = 0; j < 2; j++)
     528            id_to_model[motorolla_vendor_ids[i] << 32 |
     529                        motorolla_6200model_ids[j]] = "DCT-6200";
     530
     531    for (uint i = 0; i < motorolla_vendor_id_cnt; i++)
     532        for (uint j = 0; j < 2; j++)
     533            id_to_model[motorolla_vendor_ids[i] << 32 |
     534                        motorolla_6212model_ids[j]] = "DCT-6212";
     535
     536    for (uint i = 0; i < motorolla_vendor_id_cnt; i++)
     537        for (uint j = 0; j < 2; j++)
     538            id_to_model[motorolla_vendor_ids[i] << 32 |
     539                        motorolla_6216model_ids[j]] = "DCT-6216";
     540}
  • libs/libmythtv/videosource.h

     
    417417    DiSEqCDevTree      *diseqc_tree;
    418418};
    419419
     420class FirewireGUID;
     421class FirewireModel : public ComboBoxSetting, public CaptureCardDBStorage
     422{
     423    Q_OBJECT
     424
     425  public:
     426    FirewireModel(const CaptureCard &parent, const FirewireGUID*);
     427
     428  public slots:
     429    void SetGUID(const QString&);
     430
     431  private:
     432    const FirewireGUID *guid;
     433};
     434
     435class FirewireDesc : public TransLabelSetting
     436{
     437    Q_OBJECT
     438
     439  public:
     440    FirewireDesc(const FirewireGUID *_guid) :
     441        TransLabelSetting(), guid(_guid) { }
     442
     443  public slots:
     444    void SetGUID(const QString&);
     445
     446  private:
     447    const FirewireGUID *guid;
     448};
     449
     450
    420451class CaptureCardGroup : public TriggeredConfigurationGroup
    421452{
    422453    Q_OBJECT
  • libs/libmythtv/libmythtv.pro

     
    377377    }
    378378
    379379    # Support for cable boxes that provide Firewire out
    380     using_firewire  {
    381         HEADERS += firewirechannelbase.h       firewirerecorderbase.h
    382         SOURCES += firewirechannelbase.cpp     firewirerecorderbase.cpp
     380    using_firewire {
     381        HEADERS += firewirechannel.h           firewirerecorder.h
     382        HEADERS += firewiresignalmonitor.h     firewiredevice.h
     383        SOURCES += firewirechannel.cpp         firewirerecorder.cpp
     384        SOURCES += firewiresignalmonitor.cpp   firewiredevice.cpp
    383385
    384386        macx {
    385             HEADERS += darwinfirewirechannel.h       darwinfirewirerecorder.h
    386             SOURCES += darwinfirewirechannel.cpp     darwinfirewirerecorder.cpp
    387             HEADERS += selectavcdevice.h
    388             SOURCES += selectavcdevice.cpp
     387            HEADERS += darwinfirewiredevice.h   darwinavcinfo.h
     388            SOURCES += darwinfirewiredevice.cpp darwinavcinfo.cpp
     389            DEFINES += USING_OSX_FIREWIRE
    389390        }
    390391       
    391392        !macx {
    392             HEADERS += firewirechannel.h       firewirerecorder.h
    393             SOURCES += firewirechannel.cpp     firewirerecorder.cpp
     393            HEADERS += linuxfirewiredevice.h
     394            SOURCES += linuxfirewiredevice.cpp
     395            DEFINES += USING_LINUX_FIREWIRE
    394396        }
    395397
    396398        DEFINES += USING_FIREWIRE
  • libs/libmythtv/darwinfirewirerecorder.cpp

     
    1 /**
    2  *  DarwinDarwinFirewireRecorder
    3  *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 // MythTV includes
    8 #include "darwinfirewirerecorder.h"
    9 #include "tspacket.h"
    10 
    11 #undef always_inline
    12 #include <AVCVideoServices/AVCVideoServices.h>
    13 
    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 {;}
    23 
    24 DarwinFirewireRecorder::~DarwinFirewireRecorder()
    25 {
    26     this->Close();
    27 }
    28 
    29 // Various message callbacks.
    30 IOReturn DarwinFirewireRecorder::MPEGNoData(void *pRefCon)
    31 {
    32    
    33     DarwinFirewireRecorder* self = static_cast<DarwinFirewireRecorder*>(pRefCon);
    34     self->no_data();
    35     return 0;
    36 }
    37 
    38 void DarwinFirewireRecorder::no_data()
    39 {
    40     VERBOSE(
    41         VB_IMPORTANT,
    42         QString("Firewire: No Input in %1 seconds").arg(kTimeoutInSeconds));
    43 }
    44 
    45 namespace
    46 {
    47   void avs_log_message(char *pString)
    48   {
    49       // I don't know what QString does with plain char*, but surely it
    50       // treats char const* as an NTBS.
    51       char const* s = pString;
    52 
    53       VERBOSE(VB_GENERAL,QString("Firewire MPEG2Receiver log: %1")
    54               .arg(s));
    55   }
    56 
    57   void avs_message_received(
    58       UInt32 msg, UInt32 param1, UInt32 param2, void *pRefCon)
    59   {
    60       (void)pRefCon;
    61 
    62       VERBOSE(VB_RECORD,QString("Firewire MPEG2Receiver message: %1")
    63               .arg(msg));
    64 
    65       switch (msg)
    66       {
    67       case AVS::kMpeg2ReceiverAllocateIsochPort:
    68           VERBOSE(
    69               VB_RECORD,
    70               QString("Firewire MPEG2Receiver allocated channel: %1, speed %2")
    71                   .arg(param2).arg(param1)
    72           );
    73           break;
    74 
    75       case AVS::kMpeg2ReceiverDCLOverrun:
    76           VERBOSE(
    77               VB_IMPORTANT,
    78               QString("Firewire MPEG2Receiver DCL Overrun")
    79           );
    80           break;
    81 
    82       case AVS::kMpeg2ReceiverReceivedBadPacket:
    83           VERBOSE(
    84               VB_IMPORTANT,
    85               QString("Firewire MPEG2Receiver Received Bad Packet ")
    86           );
    87           break;
    88 
    89       default:
    90           break;
    91       }
    92   }
    93 
    94   bool find_capture_device(AVS::AVCDevice* d)
    95   {
    96       // We'd check isMPEGDevice, but it turns out that for the
    97       // DCT-6200, Apple doesn't set that flag.  So instead we rule
    98       // out DV devices.
    99       // A more general OSX AVCRecorder class that also handles DV
    100       // devices might not check either flag.
    101       return d->isAttached && !d->isDVDevice
    102 //          && (d->hasTapeSubunit || d->hasMonitorOrTunerSubunit)
    103           ;
    104   }
    105 
    106   IOReturn device_controller_notification(AVS::AVCDeviceController *, void *, AVS::AVCDevice*)
    107   {
    108       return 0;
    109   }     
    110 }
    111 
    112 IOReturn DarwinFirewireRecorder::tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf,void *pRefCon)
    113 {
    114     DarwinFirewireRecorder* self = static_cast<DarwinFirewireRecorder*>(pRefCon);
    115     if (!self)
    116         return kIOReturnBadArgument;
    117 
    118     for (UInt32 i = 0; i < tsPacketCount; ++i)
    119         self->ProcessTSPacket(*(reinterpret_cast<TSPacket*>(ppBuf[i])));
    120 
    121     return 0;
    122 }
    123 
    124 
    125 bool DarwinFirewireRecorder::Open()
    126 {
    127      if (isopen)
    128          return true;
    129    
    130      VERBOSE(VB_GENERAL,QString("Firewire: Creating logger object"));
    131 
    132      this->message_log = new AVS::StringLogger(avs_log_message);
    133      if (!this->message_log)
    134      {
    135          VERBOSE(VB_IMPORTANT, QString("Firewire: Couldn't create logger") );
    136          return false;
    137      }
    138 
    139      // If we don't set this immediately, Close() will refuse to clean
    140      // up after whatever mess we make here
    141      this->isopen = true;
    142 
    143      VERBOSE(VB_GENERAL,QString("Firewire: Creating MPEG-2 device stream"));
    144      
    145      // This not only builds an MPEG2Receiver object but also starts dedicated real-time threads.
    146      this->video_stream = capture_device->CreateMPEGReceiverForDevicePlug(
    147          0,                // Plug number.  Why is zero always OK?  I
    148                            // don't know, but that's what Apple's
    149                            // examples do.
    150          tspacket_callback,
    151          this,
    152          avs_message_received,
    153          this,
    154          this->message_log,
    155          AVS::kCyclesPerReceiveSegment,
    156          // Why multiply by 2 instead of using the default,
    157          // kNumReceiveSegments?  Because it's what Apple's only
    158          // example of the use of this function does.
    159          AVS::kNumReceiveSegments*2);
    160          
    161      if (!this->video_stream)
    162      {
    163          VERBOSE(VB_IMPORTANT, QString("Firewire: Couldn't create MPEG-2 device stream") );
    164          this->Close();
    165          return false;
    166      }
    167 
    168         // We could set the channel to receive on, but it doesn't seem
    169         // like we need to, and if the device is already transmitting it
    170         // could lead to inefficiency because the device stream is smart
    171         // enough to avoid allocating new bandwidth.
    172 
    173         // Register a no-data notification callback
    174         video_stream->pMPEGReceiver->registerNoDataNotificationCallback(
    175         MPEGNoData, this, kTimeoutInSeconds * 1000);
    176 
    177      return true;
    178 }
    179 
    180 void DarwinFirewireRecorder::Close()
    181 {
    182     if (!isopen)
    183         return;
    184    
    185     isopen = false;
    186 
    187     if (this->video_stream)
    188     {
    189         this->stop();
    190         VERBOSE(VB_RECORD, "Firewire: Destroying device stream");
    191         this->capture_device->DestroyAVCDeviceStream(this->video_stream);
    192         this->video_stream = 0;
    193     }
    194 
    195     delete this->message_log;
    196     this->message_log = 0;
    197 }
    198 
    199 void DarwinFirewireRecorder::start()
    200 {
    201     VERBOSE(VB_RECORD, "Firewire: Starting video stream");
    202     this->capture_device->StartAVCDeviceStream(this->video_stream);
    203 }
    204 
    205 void DarwinFirewireRecorder::stop()
    206 {
    207     VERBOSE(VB_RECORD, "Firewire: Stopping video stream");
    208     this->capture_device->StopAVCDeviceStream(this->video_stream);
    209 }
    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/scanwizardhelpers.h

     
    4949class AnalogPane;
    5050class STPane;
    5151class DVBUtilsImportPane;
     52class QApplication;
    5253
    5354/// Max range of the ScanProgressPopup progress bar
    5455#define PROGRESS_MAX  1000
     
    8687
    8788class ScannerEvent : public QCustomEvent
    8889{
     90    friend class QApplication; // to suppress Apple gcc warning
     91
    8992  public:
    9093    enum TYPE
    9194    {
  • 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 = "1173";
     13const QString currentDatabaseVersion = "1174";
    1414
    1515static bool UpdateDBVersionNumber(const QString &newnumber);
    1616static bool performActualUpdate(const QString updates[], QString version,
     
    27822782            return false;
    27832783    }
    27842784
     2785    if (dbver == "1173")
     2786    {
     2787        const QString updates[] = {
     2788"DELETE FROM capturecard WHERE cardtype = 'FIREWIRE';",
     2789""
     2790};
     2791        if (!performActualUpdate(updates, "1174", dbver))
     2792            return false;
     2793    }
     2794
    27852795//"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22
    27862796//"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22
    27872797//"ALTER TABLE recordedmarkup DROP COLUMN offset;" in 0.22
     
    27902800//"ALTER TABLE cardinput DROP lnb_lof_switch;" in 0.22
    27912801//"ALTER TABLE cardinput DROP lnb_lof_hi;" in 0.22
    27922802//"ALTER TABLE cardinput DROP lnb_lof_lo;" in 0.22
     2803//"ALTER TABLE capturecard DROP firewire_port;" in 0.22
     2804//"ALTER TABLE capturecard DROP firewire_node;" in 0.22
    27932805
    27942806    return true;
    27952807}
  • 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/darwinfirewiredevice.cpp

     
     1/**
     2 *  DarwinFirewireChannel
     3 *  Copyright (c) 2005 by Jim Westfall
     4 *  SA3250HD support Copyright (c) 2005 by Matt Porter
     5 *  Copyright (c) 2006 by Dave Abrahams
     6 *  Distributed as part of MythTV under GPL v2 and later.
     7 */
     8
     9// POSIX headers
     10#include <pthread.h>
     11
     12// OS X headers
     13#undef always_inline
     14#include <IOKit/IOMessage.h>
     15#include <IOKit/IOKitLib.h>
     16#include <IOKit/firewire/IOFireWireLib.h>
     17#include <IOKit/firewire/IOFireWireLibIsoch.h>
     18#include <IOKit/firewire/IOFireWireFamilyCommon.h>
     19#include <IOKit/avc/IOFireWireAVCLib.h>
     20
     21// Std C++ headers
     22#include <vector>
     23using namespace std;
     24
     25// MythTV headers
     26#include "darwinfirewiredevice.h"
     27#include "darwinavcinfo.h"
     28#include "mythcontext.h"
     29
     30// Apple Firewire example headers
     31#include <AVCVideoServices/StringLogger.h>
     32#include <AVCVideoServices/MPEG2Receiver.h>
     33
     34// header not used because it also requires MPEG2Transmitter.h
     35//#include <AVCVideoServices/FireWireMPEG.h>
     36namespace AVS
     37{
     38    IOReturn CreateMPEG2Receiver(
     39        MPEG2Receiver           **ppReceiver,
     40        DataPushProc              dataPushProcHandler,
     41        void                     *pDataPushProcRefCon = nil,
     42        MPEG2ReceiverMessageProc  messageProcHandler  = nil,
     43        void                     *pMessageProcRefCon  = nil,
     44        StringLogger             *stringLogger        = nil,
     45        IOFireWireLibNubRef       nubInterface        = nil,
     46        unsigned int              cyclesPerSegment    =
     47            kCyclesPerReceiveSegment,
     48        unsigned int              numSegments         =
     49            kNumReceiveSegments,
     50        bool                      doIRMAllocations    = false);
     51    IOReturn DestroyMPEG2Receiver(MPEG2Receiver *pReceiver);
     52}
     53
     54#define LOC      QString("DFireDev(): ")
     55#define LOC_WARN QString("DFireDev(), Warning: ")
     56#define LOC_ERR  QString("DFireDev(), Error: ")
     57
     58#define kAnyAvailableIsochChannel 0xFFFFFFFF
     59#define kNoDataTimeout            250 /* msec */
     60
     61static IOReturn dfd_tspacket_handler_thunk(
     62    long unsigned int tsPacketCount, UInt32 **ppBuf, void *callback_data);
     63static void dfd_update_device_list(void *dfd, io_iterator_t iterator);
     64static void dfd_streaming_log_message(char *pString);
     65
     66class DFDPriv
     67{
     68  public:
     69    DFDPriv() :
     70        controller_thread_cf_ref(NULL), controller_thread_running(false),
     71        notify_port(NULL), notify_source(NULL), deviter(NULL),
     72        is_streaming(false), avstream(NULL), logger(NULL)
     73    {
     74        logger = new AVS::StringLogger(dfd_streaming_log_message);
     75    }
     76
     77    ~DFDPriv()
     78    {
     79        avcinfo_list_t::iterator it = devices.begin();
     80        for (; it != devices.end(); ++it)
     81            delete (*it);
     82        devices.clear();
     83
     84        if (logger)
     85        {
     86            delete logger;
     87            logger = NULL;
     88        }
     89    }
     90
     91    pthread_t                 controller_thread;
     92    CFRunLoopRef              controller_thread_cf_ref;
     93    bool                      controller_thread_running;
     94
     95    IONotificationPortRef     notify_port;
     96    CFRunLoopSourceRef        notify_source;
     97    io_iterator_t             deviter;
     98
     99    bool                      is_streaming;
     100    AVS::MPEG2Receiver       *avstream;
     101    AVS::StringLogger        *logger;
     102
     103    avcinfo_list_t            devices;
     104};
     105
     106DarwinFirewireDevice::DarwinFirewireDevice(
     107    uint64_t guid, uint subunitid, uint speed) :
     108    FirewireDevice(guid, subunitid, speed),
     109    m_node(0), m_priv(new DFDPriv())
     110{
     111}
     112
     113DarwinFirewireDevice::~DarwinFirewireDevice()
     114{
     115    if (IsPortOpen())
     116    {
     117        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port");
     118        while (IsPortOpen())
     119            ClosePort();
     120    }
     121
     122    if (m_priv)
     123    {
     124        delete m_priv;
     125        m_priv = NULL;
     126    }
     127}
     128
     129void DarwinFirewireDevice::RunController(void)
     130{
     131    m_priv->controller_thread_cf_ref = CFRunLoopGetCurrent();
     132
     133    // Set up IEEE-1394 bus change notification
     134    mach_port_t master_port;
     135    int ret = IOMasterPort(bootstrap_port, &master_port);
     136    if (kIOReturnSuccess == ret)
     137    {
     138        m_priv->notify_port   = IONotificationPortCreate(master_port);
     139        m_priv->notify_source = IONotificationPortGetRunLoopSource(
     140            m_priv->notify_port);
     141
     142        CFRunLoopAddSource(m_priv->controller_thread_cf_ref,
     143                           m_priv->notify_source,
     144                           kCFRunLoopDefaultMode);
     145
     146        ret = IOServiceAddMatchingNotification(
     147            m_priv->notify_port, kIOMatchedNotification,
     148            IOServiceMatching("IOFireWireAVCUnit"),
     149            dfd_update_device_list, this, &m_priv->deviter);
     150    }
     151
     152    if (kIOReturnSuccess == ret)
     153        dfd_update_device_list(this, m_priv->deviter);
     154
     155    m_priv->controller_thread_running = true;
     156
     157    if (kIOReturnSuccess == ret)
     158        CFRunLoopRun();
     159
     160    QMutexLocker locker(&m_lock); // ensure that controller_thread_running seen
     161
     162    m_priv->controller_thread_running = false;
     163}
     164
     165void DarwinFirewireDevice::StartController(void)
     166{
     167    m_lock.unlock();
     168
     169    pthread_create(&m_priv->controller_thread, NULL,
     170                   dfd_controller_thunk, this);
     171
     172    m_lock.lock();
     173    while (!m_priv->controller_thread_running)
     174    {
     175        m_lock.unlock();
     176        usleep(5000);
     177        m_lock.lock();
     178    }
     179}
     180
     181void DarwinFirewireDevice::StopController(void)
     182{
     183    if (!m_priv->controller_thread_running)
     184        return;
     185
     186    if (m_priv->deviter)
     187    {
     188        IOObjectRelease(m_priv->deviter);
     189        m_priv->deviter = NULL;
     190    }
     191   
     192    if (m_priv->notify_source)
     193    {
     194        CFRunLoopSourceInvalidate(m_priv->notify_source);
     195        m_priv->notify_source = NULL;
     196    }
     197
     198    if (m_priv->notify_port)
     199    {
     200        IONotificationPortDestroy(m_priv->notify_port);
     201        m_priv->notify_port = NULL;
     202    }
     203
     204    CFRunLoopStop(m_priv->controller_thread_cf_ref);
     205   
     206    while (m_priv->controller_thread_running)
     207    {
     208        m_lock.unlock();
     209        usleep(100 * 1000);
     210        m_lock.lock();
     211    }
     212}
     213
     214bool DarwinFirewireDevice::OpenPort(void)
     215{
     216    QMutexLocker locker(&m_lock);
     217
     218    VERBOSE(VB_RECORD, LOC + "OpenPort()");
     219
     220    if (GetInfoPtr() && GetInfoPtr()->IsOpen())
     221    {
     222        m_open_port_cnt++;
     223        return true;
     224    }
     225
     226    StartController();
     227
     228    if (!m_priv->controller_thread_running)
     229    {
     230        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to start firewire thread.");
     231        return false;
     232    }
     233
     234    if (!GetInfoPtr())
     235    {
     236        VERBOSE(VB_IMPORTANT, LOC_ERR + "No IEEE-1394 device at " +
     237                QString("guid: 0x%1").arg(m_guid,0,16));
     238       
     239        StopController();
     240        return false;
     241    }
     242
     243    VERBOSE(VB_RECORD, LOC + "Opening AVC Device");
     244    VERBOSE(VB_RECORD, LOC + GetSubunitInfoString(GetInfoPtr()->unit_table));
     245
     246    if (!IsSubunitType(GetInfoPtr()->unit_table, kAVCSubunitTypeTuner) ||
     247        !IsSubunitType(GetInfoPtr()->unit_table, kAVCSubunitTypePanel))
     248    {
     249        VERBOSE(VB_IMPORTANT, LOC_ERR + QString("No STB at guid: 0x%1")
     250                .arg(m_guid,0,16));
     251
     252        StopController();
     253        return false;
     254    }
     255
     256    bool ok = GetInfoPtr()->Open(m_priv->controller_thread_cf_ref);
     257    if (!ok)
     258    {
     259        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for port");
     260
     261        return false;
     262    }
     263
     264    // TODO we should set m_node...
     265
     266    m_open_port_cnt++;
     267
     268    return true;
     269}
     270
     271bool DarwinFirewireDevice::ClosePort(void)
     272{
     273    QMutexLocker locker(&m_lock);
     274
     275    VERBOSE(VB_RECORD, LOC + "ClosePort()");
     276
     277    if (m_open_port_cnt < 1)
     278        return false;
     279
     280    m_open_port_cnt--;
     281
     282    if (m_open_port_cnt != 0)
     283        return true;
     284
     285    if (GetInfoPtr() && GetInfoPtr()->IsOpen())
     286    {
     287        VERBOSE(VB_RECORD, LOC + "Closing AVC Device");
     288
     289        GetInfoPtr()->Close();
     290    }
     291
     292    StopController();
     293
     294    return true;
     295}
     296
     297bool DarwinFirewireDevice::OpenAVStream(void)
     298{
     299    if (IsAVStreamOpen())
     300        return true;
     301
     302    int max_speed = GetMaxSpeed();
     303    VERBOSE(VB_IMPORTANT, "Max Speed: "<<max_speed<<" Our speed: "<<m_speed);
     304    m_speed = min((uint)max_speed, m_speed);
     305
     306    uint fwchan = 0;
     307    bool streaming = IsSTBStreaming(&fwchan);
     308    VERBOSE(VB_IMPORTANT, QString("STB is %1already streaming on fwchan: %2")
     309            .arg(streaming?"":"not ").arg(fwchan));
     310
     311    // TODO we should use the stream if it already exists,
     312    //      this is especially true if it is a broadcast stream...
     313
     314    int ret = AVS::CreateMPEG2Receiver(
     315        &m_priv->avstream,
     316        dfd_tspacket_handler_thunk, this,
     317        dfd_stream_msg, this,
     318        m_priv->logger /* StringLogger */,
     319        GetInfoPtr()->fw_handle,
     320        AVS::kCyclesPerReceiveSegment,
     321        AVS::kNumReceiveSegments,
     322        true /* p2p */);
     323
     324    if (kIOReturnSuccess != ret)
     325    {
     326        VERBOSE(VB_IMPORTANT, LOC_ERR + "Couldn't create A/V stream object");
     327        return false;
     328    }
     329
     330    m_priv->avstream->registerNoDataNotificationCallback(
     331        dfd_no_data_notification, this, kNoDataTimeout);
     332
     333    return true;
     334}
     335
     336int DarwinFirewireDevice::GetMaxSpeed(void) // oMPR read
     337{
     338    IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
     339    io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
     340
     341    FWAddress addr(0xffff, 0xf0000900, m_node);
     342    uint32_t val;
     343    int ret = (*fw_handle)->ReadQuadlet(
     344        fw_handle, dev, &addr, (UInt32*) &val, false, 0);
     345
     346    return (int)((ret == kIOReturnSuccess) ? ((val>>30) & 0x3) : 0xffffffff);
     347}
     348
     349bool DarwinFirewireDevice::IsSTBStreaming(uint *fw_channel)
     350{
     351    IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
     352    io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
     353
     354    FWAddress addr(0xffff, 0xf0000904, m_node);
     355    uint32_t val;
     356    int ret = (*fw_handle)->ReadQuadlet(
     357        fw_handle, dev, &addr, (UInt32*) &val, false, 0);
     358
     359    if (ret != kIOReturnSuccess)
     360        return false;
     361
     362    if (val & (kIOFWPCRBroadcast | kIOFWPCRP2PCount))
     363    {
     364        if (fw_channel)
     365            *fw_channel = (val & kIOFWPCRChannel) >> kIOFWPCRChannelPhase;
     366
     367        return true;
     368    }
     369
     370    return false;
     371}
     372
     373bool DarwinFirewireDevice::CloseAVStream(void)
     374{
     375    if (!m_priv->avstream)
     376        return true;
     377
     378    StopStreaming();
     379
     380    VERBOSE(VB_RECORD, LOC + "Destroying A/V stream object");
     381    AVS::DestroyMPEG2Receiver(m_priv->avstream);
     382    m_priv->avstream = NULL;
     383
     384    return true;
     385}
     386
     387bool DarwinFirewireDevice::IsAVStreamOpen(void) const
     388{
     389    return m_priv->avstream;
     390}
     391
     392bool DarwinFirewireDevice::StartStreaming(void)
     393{
     394    if (m_priv->is_streaming)
     395        return m_priv->is_streaming;
     396
     397    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming");
     398
     399    if (!IsAVStreamOpen() && !OpenAVStream())
     400    {
     401        VERBOSE(VB_IMPORTANT, LOC + "Starting A/V streaming: FAILED");
     402        return false;
     403    }
     404
     405    m_priv->avstream->setReceiveIsochChannel(kAnyAvailableIsochChannel);
     406    m_priv->avstream->setReceiveIsochSpeed((IOFWSpeed) m_speed);
     407    int ret = m_priv->avstream->startReceive();
     408
     409    m_priv->is_streaming = (kIOReturnSuccess == ret);
     410
     411    VERBOSE(VB_IMPORTANT, LOC + "Starting A/V streaming: "
     412            <<((m_priv->is_streaming)?"success":"failure"));
     413
     414    return m_priv->is_streaming;
     415}
     416
     417bool DarwinFirewireDevice::StopStreaming(void)
     418{
     419    if (!m_priv->is_streaming)
     420        return true;
     421
     422    VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming");
     423
     424    bool ok = (kIOReturnSuccess == m_priv->avstream->stopReceive());
     425    m_priv->is_streaming = !ok;
     426
     427    if (!ok)
     428    {
     429        VERBOSE(VB_RECORD, LOC_ERR + "Failed to stop A/V streaming");
     430        return false;
     431    }
     432
     433    VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming");
     434    return true;
     435}
     436
     437bool DarwinFirewireDevice::SendAVCCommand(const vector<uint8_t> &cmd,
     438                                          vector<uint8_t>       &result,
     439                                          int                   retry_cnt)
     440{
     441    return GetInfoPtr()->SendAVCCommand(cmd, result, retry_cnt);
     442}
     443
     444bool DarwinFirewireDevice::IsPortOpen(void) const
     445{
     446    QMutexLocker locker(&m_lock);
     447
     448    if (!GetInfoPtr())
     449        return false;
     450
     451    return GetInfoPtr()->IsOpen();
     452}
     453
     454void DarwinFirewireDevice::AddListener(TSDataListener *listener)
     455{
     456    FirewireDevice::AddListener(listener);
     457
     458    QMutexLocker locker(&m_lock);
     459    if (!m_listeners.empty())
     460        StartStreaming();
     461}
     462
     463void DarwinFirewireDevice::RemoveListener(TSDataListener *listener)
     464{
     465    FirewireDevice::RemoveListener(listener);
     466
     467    QMutexLocker locker(&m_lock);
     468    if (m_priv->is_streaming && m_listeners.empty())
     469    {
     470        StopStreaming();
     471        CloseAVStream();
     472    }
     473}
     474
     475void DarwinFirewireDevice::BroadcastToListeners(
     476    const unsigned char *data, uint dataSize)
     477{
     478    QMutexLocker locker(&m_lock);
     479    FirewireDevice::BroadcastToListeners(data, dataSize);
     480}
     481
     482void DarwinFirewireDevice::PrintNoDataMessage(void)
     483{
     484    VERBOSE(VB_IMPORTANT, LOC_WARN +
     485            QString("No Input in %1 msecs").arg(kNoDataTimeout));
     486}
     487
     488void DarwinFirewireDevice::ProcessStreamingMessage(
     489    uint32_t msg, uint32_t param1, uint32_t param2)
     490{
     491    int plug_number = 0;
     492
     493    if (AVS::kMpeg2ReceiverAllocateIsochPort == msg)
     494    {
     495        int speed = param1, fw_channel = param2;
     496
     497        bool ok = UpdatePlugRegister(
     498            plug_number, fw_channel, speed, true, false);
     499
     500        VERBOSE(VB_IMPORTANT, LOC + QString("AllocateIsochPort(%1,%2) %3")
     501                .arg(fw_channel).arg(speed).arg(((ok)?"ok":"error")));
     502    }
     503    else if (AVS::kMpeg2ReceiverReleaseIsochPort == msg)
     504    {
     505        int ret = UpdatePlugRegister(plug_number, -1, -1, false, true);
     506
     507        VERBOSE(VB_IMPORTANT, LOC + "ReleaseIsochPort "
     508                <<((kIOReturnSuccess == ret)?"ok":"error"));
     509    }
     510    else if (AVS::kMpeg2ReceiverDCLOverrun == msg)
     511    {
     512        VERBOSE(VB_IMPORTANT, LOC_ERR + "DCL Overrun");
     513    }
     514    else if (AVS::kMpeg2ReceiverReceivedBadPacket == msg)
     515    {
     516        VERBOSE(VB_IMPORTANT, LOC_ERR + "Received Bad Packet");
     517    }
     518    else
     519    {
     520        VERBOSE(VB_GENERAL, LOC +
     521                QString("Streaming Message: %1").arg(msg));
     522    }
     523}
     524
     525vector<AVCInfo> DarwinFirewireDevice::GetSTBList(void)
     526{
     527    vector<AVCInfo> list;
     528
     529    {
     530        DarwinFirewireDevice dev(0,0,0);
     531
     532        dev.m_lock.lock();
     533        dev.StartController();
     534        dev.m_lock.unlock();
     535
     536        list = dev.GetSTBListPrivate();
     537
     538        dev.m_lock.lock();
     539        dev.StopController();
     540        dev.m_lock.unlock();
     541    }
     542
     543    return list;
     544}
     545
     546vector<AVCInfo> DarwinFirewireDevice::GetSTBListPrivate(void)
     547{
     548    VERBOSE(VB_IMPORTANT, "GetSTBListPrivate -- begin");
     549    QMutexLocker locker(&m_lock);
     550    VERBOSE(VB_IMPORTANT, "GetSTBListPrivate -- got lock");
     551
     552    vector<AVCInfo> list;
     553
     554    avcinfo_list_t::iterator it = m_priv->devices.begin();
     555    for (; it != m_priv->devices.end(); ++it)
     556    {
     557        if (IsSubunitType((*it)->unit_table, kAVCSubunitTypeTuner) &&
     558            IsSubunitType((*it)->unit_table, kAVCSubunitTypePanel))
     559        {
     560            list.push_back(*(*it));
     561        }
     562    }
     563
     564    VERBOSE(VB_IMPORTANT, "GetSTBListPrivate -- end");
     565    return list;
     566}
     567
     568void DarwinFirewireDevice::UpdateDeviceListItem(uint64_t guid, void *pitem)
     569{
     570    QMutexLocker locker(&m_lock);
     571
     572    avcinfo_list_t::iterator it = m_priv->devices.find(guid);
     573
     574    if (it == m_priv->devices.end())
     575    {
     576        DarwinAVCInfo *ptr = new DarwinAVCInfo();
     577
     578        VERBOSE(VB_IMPORTANT, "Adding device list item 0x"
     579                <<hex<<guid<<" ptr: "<<ptr<<dec);
     580
     581        m_priv->devices[guid] = ptr;
     582        it = m_priv->devices.find(guid);
     583    }
     584
     585    io_object_t &item = *((io_object_t*) pitem);
     586    if (it != m_priv->devices.end())
     587    {
     588        (*it)->Update(guid, m_priv->notify_port,
     589                      m_priv->controller_thread_cf_ref, item);
     590    }
     591}
     592
     593DarwinAVCInfo *DarwinFirewireDevice::GetInfoPtr(void)
     594{
     595    avcinfo_list_t::iterator it = m_priv->devices.find(m_guid);
     596    return (it == m_priv->devices.end()) ? NULL : *it;
     597}
     598
     599const DarwinAVCInfo *DarwinFirewireDevice::GetInfoPtr(void) const
     600{
     601    avcinfo_list_t::iterator it = m_priv->devices.find(m_guid);
     602    return (it == m_priv->devices.end()) ? NULL : *it;
     603}
     604
     605// Various message callbacks.
     606
     607void *dfd_controller_thunk(void *param)
     608{
     609    ((DarwinFirewireDevice*)param)->RunController();
     610    return NULL;
     611}
     612
     613void dfd_update_device_list_item(
     614    DarwinFirewireDevice *dev, uint64_t guid, void *item)
     615{
     616    dev->UpdateDeviceListItem(guid, item);
     617}
     618
     619int dfd_no_data_notification(void *callback_data)
     620{
     621    ((DarwinFirewireDevice*)callback_data)->PrintNoDataMessage();
     622
     623    return kIOReturnSuccess;
     624}
     625
     626void dfd_stream_msg(long unsigned int msg, long unsigned int param1,
     627                    long unsigned int param2, void *callback_data)
     628{
     629    ((DarwinFirewireDevice*)callback_data)->
     630        ProcessStreamingMessage(msg, param1, param2);
     631}
     632
     633int dfd_tspacket_handler(uint tsPacketCount, uint32_t **ppBuf,
     634                         void *callback_data)
     635{
     636    DarwinFirewireDevice *fw = (DarwinFirewireDevice*) callback_data;
     637    if (!fw)
     638        return kIOReturnBadArgument;
     639
     640    for (uint32_t i = 0; i < tsPacketCount; ++i)
     641        fw->BroadcastToListeners((const unsigned char*) ppBuf[i], 188);
     642
     643    return kIOReturnSuccess;
     644}
     645
     646static IOReturn dfd_tspacket_handler_thunk(
     647    long unsigned int tsPacketCount, UInt32 **ppBuf, void *callback_data)
     648{
     649    return dfd_tspacket_handler(
     650        tsPacketCount, (uint32_t**)ppBuf, callback_data);
     651}
     652
     653static void dfd_update_device_list(void *dfd, io_iterator_t deviter)
     654{
     655    DarwinFirewireDevice *dev = (DarwinFirewireDevice*) dfd;
     656
     657    io_object_t it = NULL;
     658    while ((it = IOIteratorNext(deviter)))
     659    {
     660        uint64_t guid = 0;
     661
     662        CFMutableDictionaryRef props;
     663        int ret = IORegistryEntryCreateCFProperties(
     664            it, &props, kCFAllocatorDefault, kNilOptions);
     665
     666        if (kIOReturnSuccess == ret)
     667        {
     668            CFNumberRef GUIDDesc = (CFNumberRef)
     669                CFDictionaryGetValue(props, CFSTR("GUID"));
     670            CFNumberGetValue(GUIDDesc, kCFNumberSInt64Type, &guid);
     671            CFRelease(props);
     672            dfd_update_device_list_item(dev, guid, &it);
     673        }
     674    }
     675}
     676
     677static void dfd_streaming_log_message(char *msg)
     678{
     679    VERBOSE(VB_RECORD, QString("MPEG2Receiver: %1").arg(msg));
     680}
     681
     682bool DarwinFirewireDevice::UpdatePlugRegisterPrivate(
     683    uint plug_number, int new_fw_chan, int new_speed,
     684    bool add_plug, bool remove_plug)
     685{
     686    if (!GetInfoPtr())
     687        return false;
     688
     689    IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
     690    if (!fw_handle)
     691        return false;
     692
     693    io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
     694
     695    // Read the register
     696    uint      low_addr = kPCRBaseAddress + 4 + (plug_number << 2);
     697    FWAddress addr(0xffff, low_addr, m_node);
     698    uint32_t  old_plug_val;
     699    if (kIOReturnSuccess != (*fw_handle)->ReadQuadlet(
     700            fw_handle, dev, &addr, (UInt32*) &old_plug_val, false, 0))
     701    {
     702        return false;
     703    }
     704
     705    int old_plug_cnt = (old_plug_val >> 24) & 0x3f;
     706    int old_fw_chan  = (old_plug_val >> 16) & 0x3f;
     707    int old_speed    = (old_plug_val >> 14) & 0x03;
     708
     709    int new_plug_cnt = (int) old_plug_cnt;
     710    new_plug_cnt += ((add_plug) ? 1 : 0) - ((remove_plug) ? 1 : 0);
     711    if ((new_plug_cnt > 0x3f) || (new_plug_cnt < 0))
     712    {
     713        VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid Plug Count "<<new_plug_cnt);
     714
     715        return false;
     716    }
     717
     718    new_fw_chan = (new_fw_chan >= 0) ? new_fw_chan : old_fw_chan;
     719    if (old_plug_cnt && (new_fw_chan != old_fw_chan))
     720    {
     721        VERBOSE(VB_IMPORTANT, LOC_WARN +
     722                "Ignoring FWChan change request, plug already open");
     723
     724        new_fw_chan = old_fw_chan;
     725    }
     726
     727    new_speed = (new_speed >= 0) ? new_speed : old_speed;
     728    if (old_plug_cnt && (new_speed != old_speed))
     729    {
     730        VERBOSE(VB_IMPORTANT, LOC_WARN +
     731                "Ignoring speed change request, plug already open");
     732
     733        new_speed = old_speed;
     734    }
     735
     736    uint32_t new_plug_val = old_plug_val;
     737
     738    new_plug_val &= ~(0x3f<<24);
     739    new_plug_val &= (remove_plug) ? ~kIOFWPCRBroadcast : ~0x0;
     740    new_plug_val |= (new_plug_cnt & 0x3f) << 24;
     741
     742    new_plug_val &= ~(0x3f<<16);
     743    new_plug_val |= (new_fw_chan & 0x3F) << 16;
     744
     745    new_plug_val &= ~(0x03<<14);
     746    new_plug_val |= (new_speed & 0x03) << 14;
     747
     748    return (kIOReturnSuccess == (*fw_handle)->CompareSwap(
     749                fw_handle, dev, &addr, old_plug_val, new_plug_val, false, 0));
     750}
     751
     752bool DarwinFirewireDevice::UpdatePlugRegister(
     753    uint plug_number, int fw_chan, int speed,
     754    bool add_plug, bool remove_plug, uint retry_cnt)
     755{
     756    if (!GetInfoPtr() || !GetInfoPtr()->fw_handle)
     757        return false;
     758
     759    bool ok = false;
     760
     761    for (uint i = 0; (i < retry_cnt) && !ok; i++)
     762    {
     763        ok = UpdatePlugRegisterPrivate(
     764            plug_number, fw_chan, speed, add_plug, remove_plug);
     765    }
     766
     767    return ok;
     768}
  • libs/libmythtv/firewirerecorderbase.cpp

     
    1 /**
    2  *  FirewireRecorder
    3  *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 // MythTV includes
    8 #include "firewirerecorderbase.h"
    9 #include "mythcontext.h"
    10 #include "mpegtables.h"
    11 #include "mpegstreamdata.h"
    12 #include "tv_rec.h"
    13 
    14 #define LOC QString("FireRecBase: ")
    15 #define LOC_ERR QString("FireRecBase, Error: ")
    16 
    17 const int FirewireRecorderBase::kTimeoutInSeconds = 15;
    18 
    19 FirewireRecorderBase::FirewireRecorderBase(TVRec *rec)
    20     : DTVRecorder(rec), _mpeg_stream_data(NULL)
    21 {
    22     SetStreamData(new MPEGStreamData(1, true));
    23 }
    24 
    25 FirewireRecorderBase::~FirewireRecorderBase()
    26 {
    27     SetStreamData(NULL);
    28 }
    29 
    30 void FirewireRecorderBase::StartRecording(void) {
    31  
    32     VERBOSE(VB_RECORD, LOC + "StartRecording");
    33 
    34     if (!Open()) {
    35         _error = true;       
    36         return;
    37     }
    38 
    39     _request_recording = true;
    40     _recording = true;
    41    
    42     start();
    43 
    44     while(_request_recording) {
    45        if (PauseAndWait())
    46            continue;
    47 
    48        if (!grab_frames())
    49        {
    50            _error = true;
    51            return;
    52        }
    53     }       
    54    
    55     stop();
    56     FinishRecording();
    57 
    58     _recording = false;
    59 
    60 
    61 void FirewireRecorderBase::ProcessTSPacket(const TSPacket &tspacket)
    62 {
    63     if (tspacket.TransportError())
    64         return;
    65  
    66     if (tspacket.ScramplingControl())
    67         return;
    68  
    69     if (tspacket.HasAdaptationField())
    70         StreamData()->HandleAdaptationFieldControl(&tspacket);
    71  
    72     if (tspacket.HasPayload())
    73     {
    74         const unsigned int lpid = tspacket.PID();
    75  
    76         // Pass or reject packets based on PID, and parse info from them
    77         if (lpid == StreamData()->VideoPIDSingleProgram())
    78         {
    79             _buffer_packets = !FindMPEG2Keyframes(&tspacket);
    80             BufferedWrite(tspacket);
    81         }
    82         else if (StreamData()->IsAudioPID(lpid))
    83             BufferedWrite(tspacket);
    84         else if (StreamData()->IsListeningPID(lpid))
    85             StreamData()->HandleTSTables(&tspacket);
    86         else if (StreamData()->IsWritingPID(lpid))
    87             BufferedWrite(tspacket);
    88     }
    89  
    90     _ts_stats.IncrTSPacketCount();
    91     if (0 == _ts_stats.TSPacketCount()%1000000)
    92         VERBOSE(VB_RECORD, _ts_stats.toString());
    93 }
    94 
    95 void FirewireRecorderBase::SetOptionsFromProfile(RecordingProfile *profile,
    96                                              const QString &videodev,
    97                                              const QString &audiodev,
    98                                              const QString &vbidev)
    99 {
    100     (void)videodev;
    101     (void)audiodev;
    102     (void)vbidev;
    103     (void)profile;
    104 }
    105 
    106 // documented in recorderbase.cpp
    107 bool FirewireRecorderBase::PauseAndWait(int timeout)
    108 {
    109     if (request_pause)
    110     {
    111         if (!paused)
    112         {
    113             stop();
    114             paused = true;
    115             pauseWait.wakeAll();
    116             if (tvrec)
    117                 tvrec->RecorderPaused();
    118         }
    119         unpauseWait.wait(timeout);
    120     }
    121     if (!request_pause && paused)
    122     {
    123         start();
    124         paused = false;
    125     }
    126     return paused;
    127 }
    128 
    129 void FirewireRecorderBase::SetStreamData(MPEGStreamData *data)
    130 {
    131     if (data == _mpeg_stream_data)
    132         return;
    133 
    134     MPEGStreamData *old_data = _mpeg_stream_data;
    135     _mpeg_stream_data = data;
    136 
    137     if (data)
    138         data->AddMPEGSPListener(this);
    139 
    140     if (old_data)
    141         delete old_data;
    142 }
    143 
    144 void FirewireRecorderBase::HandleSingleProgramPAT(
    145     ProgramAssociationTable *pat)
    146 {
    147     if (!pat)
    148         return;
    149  
    150     int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
    151     pat->tsheader()->SetContinuityCounter(next);
    152     BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));
    153 }
    154  
    155 void FirewireRecorderBase::HandleSingleProgramPMT(ProgramMapTable *pmt)
    156 {
    157     if (!pmt)
    158         return;
    159  
    160     int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
    161     pmt->tsheader()->SetContinuityCounter(next);
    162     BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));
    163 }
  • libs/libmythtv/firewirerecorder.cpp

     
    11/**
    22 *  FirewireRecorder
    3  *  Copyright (c) 2005 by Jim Westfall
     3 *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
    44 *  Distributed as part of MythTV under GPL v2 and later.
    55 */
    66
    7 // C includes
    8 #include <pthread.h>
    9 #include <sys/select.h>
    10 
    11 // C++ includes
    12 #include <iostream>
    13 using namespace std;
    14 
    157// MythTV includes
    168#include "firewirerecorder.h"
     9#include "firewirechannel.h"
    1710#include "mythcontext.h"
    1811#include "mpegtables.h"
    1912#include "mpegstreamdata.h"
    2013#include "tv_rec.h"
    2114
    22 #define LOC QString("FireRec: ")
    23 #define LOC_ERR QString("FireRec, Error: ")
     15#define LOC QString("FireRecBase(%1): ").arg(channel->GetDevice())
     16#define LOC_ERR QString("FireRecBase(%1), Error: ").arg(channel->GetDevice())
    2417
    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)
     18FirewireRecorder::FirewireRecorder(TVRec *rec, FirewireChannel *chan) :
     19    DTVRecorder(rec), _mpeg_stream_data(NULL),
     20    channel(chan), isopen(false)
    3321{
    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;
    5122}
    5223
    53 static QString speed_to_string(uint speed)
     24FirewireRecorder::~FirewireRecorder()
    5425{
    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]);
     26    SetStreamData(NULL);
     27    Close();
    6028}
    6129
    6230bool FirewireRecorder::Open(void)
    6331{
    64      if (isopen)
    65          return true;
     32    if (!isopen)
     33        isopen = channel->GetFirewireDevice()->OpenPort();
    6634
    67      VERBOSE(VB_RECORD, LOC +
    68              QString("Initializing Port: %1, Node: %2, Speed: %3")
    69              .arg(fwport).arg(fwnode).arg(speed_to_string(fwspeed)));
     35    return isopen;
     36}
    7037
    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      }
     38void FirewireRecorder::Close(void)
     39{
     40    if (isopen)
     41    {
     42        channel->GetFirewireDevice()->ClosePort();
     43        isopen = false;
     44    }
     45}
    7846
    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;
     47void FirewireRecorder::StartStreaming(void)
     48{
     49    channel->GetFirewireDevice()->AddListener(this);
     50}
    9851
    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      }
     52void FirewireRecorder::StopStreaming(void)
     53{
     54    channel->GetFirewireDevice()->RemoveListener(this);
     55}
    11456
    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);
     57void FirewireRecorder::StartRecording(void)
     58{
     59    VERBOSE(VB_RECORD, LOC + "StartRecording");
    12060
    121          // release raw1394 object;
    122          raw1394_destroy_handle(fwhandle);
    123          return false;
    124      }
     61    if (!Open())
     62    {
     63        _error = true;
     64        return;
     65    }
    12566
    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));
     67    _request_recording = true;
     68    _recording = true;
    13569
    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)));
     70    StartStreaming();
    14671
    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      }
     72    while (_request_recording)
     73    {
     74        if (!PauseAndWait())
     75            usleep(50 * 1000);
     76    }
    15477
    155      fwfd = raw1394_get_fd(fwhandle);
     78    StopStreaming();
     79    FinishRecording();
    15680
    157      return isopen = true;
     81    _recording = false;
    15882}
    15983
    160 void FirewireRecorder::Close(void)
     84void FirewireRecorder::AddData(const unsigned char *data, uint len)
    16185{
    162     if (!isopen)
     86    uint bufsz = buffer.size();
     87    if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) &&
     88        (TSPacket::SIZE > bufsz))
     89    {
     90        if (bufsz)
     91            buffer.clear();
     92
     93        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data)));
    16394        return;
     95    }
    16496
    165     isopen = false;
     97    buffer.insert(buffer.end(), data, data + len);
     98    bufsz += len;
    16699
    167     VERBOSE(VB_RECORD, LOC + "Releasing iec61883_mpeg2 object");
    168     iec61883_mpeg2_close(fwmpeg);
     100    int sync_at = -1;
     101    for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
     102    {
     103        if (buffer[i] == SYNC_BYTE)
     104            sync_at = i;
     105    }
    169106
    170     if (fwconnection == kConnectionP2P && fwchannel > -1)
     107    if (sync_at < 0)
     108        return;
     109
     110    if (bufsz < 30 * TSPacket::SIZE)
     111        return; // build up a little buffer
     112
     113    while (sync_at + TSPacket::SIZE < bufsz)
    171114    {
    172         VERBOSE(VB_RECORD, LOC +
    173                 QString("Disconnecting channel %1").arg(fwchannel));
     115        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
     116                              &buffer[0] + sync_at)));
    174117
    175         iec61883_cmp_disconnect(fwhandle, fwnode | 0xffc0, fwoplug,
    176                                 raw1394_get_local_id (fwhandle),
    177                                 fwiplug, fwchannel, fwbandwidth);
     118        sync_at += TSPacket::SIZE;
    178119    }
    179120
    180     VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle");
    181     raw1394_destroy_handle(fwhandle);
     121    buffer.erase(buffer.begin(), buffer.begin() + sync_at);
     122
     123    return;
    182124}
    183125
    184 bool FirewireRecorder::grab_frames()
     126void FirewireRecorder::ProcessTSPacket(const TSPacket &tspacket)
    185127{
    186     struct timeval tv;
    187     fd_set rfds;
     128    if (tspacket.TransportError())
     129        return;
    188130
    189     FD_ZERO(&rfds);
    190     FD_SET(fwfd, &rfds);
    191     tv.tv_sec = kTimeoutInSeconds;
    192     tv.tv_usec = 0;
     131    if (tspacket.ScramplingControl())
     132        return;
    193133
    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;
    200     }
     134    if (tspacket.HasAdaptationField())
     135        GetStreamData()->HandleAdaptationFieldControl(&tspacket);
    201136
    202     int ret = raw1394_loop_iterate(fwhandle);
    203     if (ret)
     137    if (tspacket.HasPayload())
    204138    {
    205         VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " +
    206                 QString("returned %1").arg(ret));
    207         return false;
    208     }
     139        const unsigned int lpid = tspacket.PID();
    209140
    210     return true;
     141        // Pass or reject packets based on PID, and parse info from them
     142        if (lpid == GetStreamData()->VideoPIDSingleProgram())
     143        {
     144            _buffer_packets = !FindMPEG2Keyframes(&tspacket);
     145            BufferedWrite(tspacket);
     146        }
     147        else if (GetStreamData()->IsAudioPID(lpid))
     148            BufferedWrite(tspacket);
     149        else if (GetStreamData()->IsListeningPID(lpid))
     150            GetStreamData()->HandleTSTables(&tspacket);
     151        else if (GetStreamData()->IsWritingPID(lpid))
     152            BufferedWrite(tspacket);
     153    }
    211154}
    212155
    213 void FirewireRecorder::SetOption(const QString &name, const QString &value)
     156void FirewireRecorder::SetOptionsFromProfile(RecordingProfile *profile,
     157                                                 const QString &videodev,
     158                                                 const QString &audiodev,
     159                                                 const QString &vbidev)
    214160{
    215     if (name == "model")
    216         fwmodel = value;
     161    (void)videodev;
     162    (void)audiodev;
     163    (void)vbidev;
     164    (void)profile;
    217165}
    218166
    219 void FirewireRecorder::SetOption(const QString &name, int value)
     167// documented in recorderbase.cpp
     168bool FirewireRecorder::PauseAndWait(int timeout)
    220169{
    221     if (name == "port")
    222         fwport = value;
    223     else if (name == "node")
    224         fwnode = value;
    225     else if (name == "speed")
     170    if (request_pause)
    226171    {
    227         if (RAW1394_ISO_SPEED_100 != value &&
    228             RAW1394_ISO_SPEED_200 != value &&
    229             RAW1394_ISO_SPEED_400 != value)
     172        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause");
     173        if (!paused)
    230174        {
    231             VERBOSE(VB_IMPORTANT, LOC_ERR +
    232                     QString("Unknown speed '%1', will use 100Mbps")
    233                     .arg(value));
    234 
    235             value = RAW1394_ISO_SPEED_100;
     175            StopStreaming();
     176            paused = true;
     177            pauseWait.wakeAll();
     178            if (tvrec)
     179                tvrec->RecorderPaused();
    236180        }
    237         fwspeed = value;
     181        unpauseWait.wait(timeout);
    238182    }
    239     else if (name == "connection")
     183    if (!request_pause && paused)
    240184    {
    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));
     185        VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause");
     186        StartStreaming();
     187        paused = false;
     188    }
     189    return paused;
     190}
    247191
    248             fwconnection = kConnectionP2P;
    249         }
    250         fwconnection = value;
     192void FirewireRecorder::SetStreamData(MPEGStreamData *data)
     193{
     194    if (data == _mpeg_stream_data)
     195        return;
     196
     197    MPEGStreamData *old_data = _mpeg_stream_data;
     198    _mpeg_stream_data = data;
     199    if (old_data)
     200        delete old_data;
     201
     202    if (data)
     203    {
     204        data->AddMPEGSPListener(this);
     205
     206        if (data->DesiredProgram() >= 0)
     207            data->SetDesiredProgram(data->DesiredProgram());
    251208    }
    252209}
     210
     211void FirewireRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
     212{
     213    if (!pat)
     214        return;
     215
     216    int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
     217    pat->tsheader()->SetContinuityCounter(next);
     218    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));
     219}
     220
     221void FirewireRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
     222{
     223    if (!pmt)
     224        return;
     225
     226    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
     227    pmt->tsheader()->SetContinuityCounter(next);
     228    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));
     229}
  • 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 _FIREWIRERECORDER_H_
     8#define _FIREWIRERECORDER_H_
    99
    10 #include "firewirerecorderbase.h"
    11 #include "tsstats.h"
    12 #include <libraw1394/raw1394.h>
    13 #include <libiec61883/iec61883.h>
     10// MythTV headers
     11#include "dtvrecorder.h"
     12#include "tspacket.h"
     13#include "streamlisteners.h"
    1414
     15class TVRec;
     16class FirewireChannel;
     17
    1518/** \class FirewireRecorder
    16  *  \brief Linux FirewireRFecorder
     19 *  \brief This is a specialization of DTVRecorder used to
     20 *         handle DVB and ATSC streams from a firewire input.
    1721 *
    18  *  \sa FirewireRecorderBase
     22 *  \sa DTVRecorder
    1923 */
    20 class FirewireRecorder : public FirewireRecorderBase
     24class FirewireRecorder : public DTVRecorder,
     25                         public MPEGSingleProgramStreamListener,
     26                         public TSDataListener
    2127{
    22     friend int fw_tspacket_handler(unsigned char*,int,uint,void*);
     28    friend class MPEGStreamData;
     29    friend class TSPacketProcessor;
    2330
    2431  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(); }
     32    FirewireRecorder(TVRec *rec, FirewireChannel *chan);
     33    virtual ~FirewireRecorder();
    3234
    3335    // Commands
    34     bool Open(void);
     36    bool Open(void);
     37    void Close(void);
    3538
     39    void StartStreaming(void);
     40    void StopStreaming(void);
     41
     42    void StartRecording(void);
     43    bool PauseAndWait(int timeout = 100);
     44
     45    void AddData(const unsigned char *data, uint dataSize);
     46    void ProcessTSPacket(const TSPacket &tspacket);
     47
    3648    // Sets
    37     void SetOption(const QString &name, const QString &value);
    38     void SetOption(const QString &name, int value);
     49    void SetOptionsFromProfile(RecordingProfile *profile,
     50                               const QString &videodev,
     51                               const QString &audiodev,
     52                               const QString &vbidev);
     53    void SetStreamData(MPEGStreamData*);
    3954
    40   private:
    41     void Close(void);
    42     void start() { iec61883_mpeg2_recv_start(fwmpeg, fwchannel); }
    43     void stop() { iec61883_mpeg2_recv_stop(fwmpeg); }
    44     bool grab_frames();
     55    // Gets
     56    MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; }
    4557
     58    // MPEG Single Program
     59    void HandleSingleProgramPAT(ProgramAssociationTable*);
     60    void HandleSingleProgramPMT(ProgramMapTable*);
     61
     62  protected:
     63    FirewireRecorder(TVRec *rec);
     64
    4665  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;
    60 
    61     static const int kBroadcastChannel;
    62     static const int kConnectionP2P;
    63     static const int kConnectionBroadcast;
    64     static const uint kMaxBufferedPackets;
     66    MPEGStreamData        *_mpeg_stream_data;
     67    FirewireChannel       *channel;
     68    bool                   isopen;
     69    vector<unsigned char>  buffer;
    6570};
    6671
    67 #endif
     72#endif //  _FIREWIRERECORDER_H_
  • libs/libmythtv/darwinavcinfo.cpp

     
     1/**
     2 *  DarwinFirewireChannel
     3 *  Copyright (c) 2006 by Daniel Kristjansson
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7// Std C++ headers
     8#include <vector>
     9using namespace std;
     10
     11// MythTV headers
     12#include "darwinavcinfo.h"
     13#include "mythcontext.h"
     14
     15#ifndef kIOFireWireAVCLibUnitInterfaceID2
     16#define kIOFireWireAVCLibUnitInterfaceID2 \
     17    CFUUIDGetConstantUUIDWithBytes( \
     18        NULL, \
     19        0x85, 0xB5, 0xE9, 0x54, 0x0A, 0xEF, 0x11, 0xD8, \
     20        0x8D, 0x19, 0x00, 0x03, 0x93, 0x91, 0x4A, 0xBA)
     21#endif
     22
     23static void dfd_device_change_msg(
     24    void*, io_service_t, natural_t messageType, void*);
     25
     26void DarwinAVCInfo::Update(uint64_t _guid, IONotificationPortRef notify_port,
     27                           CFRunLoopRef &thread_cf_ref, io_object_t obj)
     28{
     29    IOObjectRelease(fw_device_notifier_ref);
     30    IOObjectRelease(fw_node_ref);
     31    IOObjectRelease(fw_device_ref);
     32    IOObjectRelease(fw_service_ref);
     33    IOObjectRelease(avc_service_ref);
     34
     35    avc_service_ref = obj;
     36
     37    IORegistryEntryGetParentEntry(
     38        avc_service_ref, kIOServicePlane, &fw_service_ref);
     39    IORegistryEntryGetParentEntry(
     40        fw_service_ref,  kIOServicePlane, &fw_device_ref);
     41    IORegistryEntryGetParentEntry(
     42        fw_device_ref,   kIOServicePlane, &fw_node_ref);
     43
     44    if (notify_port)
     45    {
     46        IOServiceAddInterestNotification(
     47            notify_port, obj, kIOGeneralInterest,
     48            dfd_device_change_msg, this,
     49            &fw_device_notifier_ref);
     50    }
     51
     52    if (guid == _guid)
     53        return; // we're done
     54
     55    guid = _guid;
     56
     57    //////////////////////////
     58    // get basic info
     59
     60    CFMutableDictionaryRef props;
     61    int ret = IORegistryEntryCreateCFProperties(
     62        obj, &props, kCFAllocatorDefault, kNilOptions);
     63    if (kIOReturnSuccess != ret)
     64        return; // this is bad
     65
     66    CFNumberRef specDesc = (CFNumberRef)
     67        CFDictionaryGetValue(props, CFSTR("Unit_Spec_ID"));
     68    CFNumberGetValue(specDesc, kCFNumberSInt32Type, &specid);
     69
     70    CFNumberRef typeDesc = (CFNumberRef)
     71        CFDictionaryGetValue(props, CFSTR("Unit_Type"));
     72    CFNumberGetValue(typeDesc, kCFNumberSInt32Type, &modelid);
     73
     74    CFNumberRef vendorDesc = (CFNumberRef)
     75        CFDictionaryGetValue(props, CFSTR("Vendor_ID"));
     76    CFNumberGetValue(vendorDesc, kCFNumberSInt32Type, &vendorid);
     77
     78    CFNumberRef versionDesc = (CFNumberRef)
     79        CFDictionaryGetValue(props, CFSTR("Unit_SW_Version"));
     80    CFNumberGetValue(versionDesc, kCFNumberSInt32Type, &firmware_revision);
     81
     82    CFStringRef tmp0 = (CFStringRef)
     83        CFDictionaryGetValue(props, CFSTR("FireWire Product Name"));
     84    if (tmp0)
     85    {
     86        char tmp1[1024];
     87        bzero(tmp1, sizeof(tmp1));
     88        CFStringGetCString(tmp0, tmp1, sizeof(tmp1) - sizeof(char),
     89                           kCFStringEncodingMacRoman);
     90        product_name = QString("%1").arg(tmp1);
     91    }
     92
     93    CFRelease(props);
     94
     95    //////////////////////////
     96    // get subunit info
     97
     98    VERBOSE(VB_RECORD, "Scanning guid: 0x"<<hex<<guid<<dec);
     99
     100    bool wasOpen = IsAVCInterfaceOpen();
     101    if (OpenAVCInterface(thread_cf_ref))
     102    {
     103        memset(unit_table, 0xff, 32 * sizeof(uint8_t));
     104
     105        for (uint i = 0; i < 8; i++)
     106        {
     107            vector<uint8_t> cmd;
     108            vector<uint8_t> ret;
     109
     110            cmd.push_back(FirewireDevice::kAVCStatusInquiryCommand);
     111            cmd.push_back(FirewireDevice::kAVCSubunitTypeUnit |
     112                          FirewireDevice::kAVCSubunitIdIgnore);
     113            cmd.push_back(FirewireDevice::kAVCUnitSubunitInfoOpcode);
     114            cmd.push_back((i<<4) | 0x07);
     115            cmd.push_back(0xFF);
     116            cmd.push_back(0xFF);
     117            cmd.push_back(0xFF);
     118            cmd.push_back(0xFF);
     119
     120            if (!SendAVCCommand(cmd, ret, -1))
     121            {
     122                VERBOSE(VB_IMPORTANT, "SendAVCCommand failed");
     123                continue;
     124            }
     125
     126            if (ret.size() >= 8)
     127            {
     128                unit_table[(i<<2)+0] = ret[4];
     129                unit_table[(i<<2)+1] = ret[5];
     130                unit_table[(i<<2)+2] = ret[6];
     131                unit_table[(i<<2)+3] = ret[7];
     132
     133                VERBOSE(VB_RECORD, "Added subunits:"<<hex
     134                        <<" 0x"<<((int)ret[4])<<" 0x"<<((int)ret[5])
     135                        <<" 0x"<<((int)ret[6])<<" 0x"<<((int)ret[7])
     136                        <<" filt:"
     137                        <<" 0x"<<(ret[4] & FirewireDevice::kAVCSubunitTypeUnit)
     138                        <<" 0x"<<(ret[5] & FirewireDevice::kAVCSubunitTypeUnit)
     139                        <<" 0x"<<(ret[6] & FirewireDevice::kAVCSubunitTypeUnit)
     140                        <<" 0x"<<(ret[7] & FirewireDevice::kAVCSubunitTypeUnit)
     141                        <<dec);
     142            }
     143        }
     144
     145        if (!wasOpen)
     146            CloseAVCInterface();
     147    }
     148}
     149
     150bool DarwinAVCInfo::SendAVCCommand(
     151    const vector<uint8_t> &cmd,
     152    vector<uint8_t>       &result,
     153    int                   /*retry_cnt*/)
     154{
     155    result.clear();
     156
     157    uint32_t result_length = 4096;
     158    uint8_t response[4096];
     159
     160    if (!avc_handle)
     161        return false;
     162
     163    int ret = (*avc_handle)->
     164        AVCCommand(avc_handle, (const UInt8*) &cmd[0], cmd.size(),
     165                   response, (UInt32*) &result_length);
     166
     167    if (ret != kIOReturnSuccess)
     168        return false;
     169
     170    if (result_length)
     171        result.insert(result.end(), response, response + result_length);
     172
     173    return true;
     174}
     175
     176bool DarwinAVCInfo::Open(CFRunLoopRef &thread_cf_ref)
     177{
     178    if (IsOpen())
     179        return true;
     180
     181    if (!OpenAVCInterface(thread_cf_ref))
     182        return false;
     183
     184    if (!OpenDeviceInterface(thread_cf_ref))
     185    {
     186        CloseAVCInterface();
     187        return false;
     188    }
     189
     190    return true;
     191}
     192
     193void DarwinAVCInfo::Close(void)
     194{
     195    CloseDeviceInterface();
     196    CloseAVCInterface();
     197}
     198
     199bool DarwinAVCInfo::OpenAVCInterface(CFRunLoopRef &thread_cf_ref)
     200{
     201    if (IsAVCInterfaceOpen())
     202        return true;
     203
     204    if (!avc_service_ref)
     205        return false;
     206
     207    IOCFPlugInInterface **input_plug;
     208    int32_t dummy;
     209    int ret = IOCreatePlugInInterfaceForService(
     210        avc_service_ref, kIOFireWireAVCLibUnitTypeID, kIOCFPlugInInterfaceID,
     211        &input_plug, (SInt32*) &dummy);
     212
     213    if (kIOReturnSuccess != ret)
     214        return false;
     215
     216    // Try to get post-Jaguar interface
     217    HRESULT err = (*input_plug)->QueryInterface(
     218            input_plug, CFUUIDGetUUIDBytes(kIOFireWireAVCLibUnitInterfaceID2),
     219            (void**) &avc_handle);
     220
     221    // On failure, try Jaguar interface
     222    if (S_OK != err)
     223    {
     224        err = (*input_plug)->QueryInterface(
     225            input_plug, CFUUIDGetUUIDBytes(kIOFireWireAVCLibUnitInterfaceID),
     226            (void**) &avc_handle);
     227    }
     228
     229    if (S_OK != err)
     230    {
     231        (*input_plug)->Release(input_plug);
     232        return false;
     233    }
     234
     235    // Add avc_handle to the event loop
     236    ret = (*avc_handle)->addCallbackDispatcherToRunLoop(
     237        avc_handle, thread_cf_ref);
     238
     239    (*input_plug)->Release(input_plug);
     240
     241    if (kIOReturnSuccess != ret)
     242    {
     243        (*avc_handle)->Release(avc_handle);
     244        avc_handle = NULL;
     245        return false;
     246    }
     247
     248    ret = (*avc_handle)->open(avc_handle);
     249    if (kIOReturnSuccess != ret)
     250    {
     251        (*avc_handle)->Release(avc_handle);
     252        avc_handle = NULL;
     253        return false;
     254    }
     255
     256    return true;
     257}
     258
     259void DarwinAVCInfo::CloseAVCInterface(void)
     260{
     261    if (!avc_handle)
     262        return;
     263
     264    (*avc_handle)->removeCallbackDispatcherFromRunLoop(avc_handle);
     265    (*avc_handle)->close(avc_handle);
     266    (*avc_handle)->Release(avc_handle);
     267
     268    avc_handle = NULL;
     269}
     270
     271bool DarwinAVCInfo::OpenDeviceInterface(CFRunLoopRef &thread_cf_ref)
     272{
     273    if (fw_handle)
     274        return true;
     275
     276    if (!avc_handle)
     277        return false;
     278
     279    IOCFPlugInInterface **input_plug;
     280    int32_t dummy;
     281    int ret = IOCreatePlugInInterfaceForService(
     282        fw_device_ref, kIOFireWireLibTypeID, kIOCFPlugInInterfaceID,
     283        &input_plug, (SInt32*) &dummy);
     284
     285    if (kIOReturnSuccess != ret)
     286        return false;
     287
     288    HRESULT err = (*input_plug)->QueryInterface(
     289        input_plug, CFUUIDGetUUIDBytes(kIOFireWireNubInterfaceID),
     290        (void**) &fw_handle);
     291
     292    if (S_OK != err)
     293    {
     294        (*input_plug)->Release(input_plug);
     295        return false;
     296    }
     297
     298    // Add fw_handle to the event loop
     299    ret = (*fw_handle)->AddCallbackDispatcherToRunLoop(
     300        fw_handle, thread_cf_ref);
     301
     302    (*input_plug)->Release(input_plug);
     303
     304    if (kIOReturnSuccess == ret)
     305    {
     306        // open the interface
     307        ret = (*fw_handle)->OpenWithSessionRef(
     308            fw_handle, (*avc_handle)->getSessionRef(avc_handle));
     309    }
     310
     311    if (kIOReturnSuccess != ret)
     312    {
     313        (*fw_handle)->Release(fw_handle);
     314        fw_handle = NULL;
     315        return false;
     316    }
     317
     318    return true;
     319}
     320
     321void DarwinAVCInfo::CloseDeviceInterface(void)
     322{
     323    if (!fw_handle)
     324        return;
     325
     326    (*fw_handle)->RemoveCallbackDispatcherFromRunLoop(fw_handle);
     327    (*fw_handle)->Close(fw_handle);
     328    (*fw_handle)->Release(fw_handle);
     329
     330    fw_handle = NULL;
     331}
     332
     333static void dfd_device_change_msg(
     334    void*, io_service_t, natural_t messageType, void*)
     335{
     336    QString loc = "dfd_device_change_msg() : ";
     337
     338    if (kIOMessageServiceIsTerminated == messageType)
     339    {
     340        VERBOSE(VB_RECORD, loc + "disconnect");
     341        // stop printing no data messages.. don't try to open
     342        return;
     343    }
     344
     345    if (kIOMessageServiceIsAttemptingOpen == messageType)
     346    {
     347        VERBOSE(VB_RECORD, loc + "attempting open");
     348        return;
     349    }
     350
     351
     352    if (kIOMessageServiceWasClosed == messageType)
     353    {
     354        VERBOSE(VB_RECORD, loc + "closed");
     355        // fill unit_table
     356        return;
     357    }
     358
     359    if (kIOMessageServiceIsResumed == messageType)
     360    {
     361        VERBOSE(VB_RECORD, loc + "re-connected");
     362        // re-establish any p2p connections & resume streaming
     363        // set channel again
     364        return;
     365    }
     366
     367    if (kIOMessageServiceIsTerminated == messageType)
     368        VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsTerminated");
     369    else if (kIOMessageServiceIsSuspended == messageType)
     370        VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsSuspended");
     371    else if (kIOMessageServiceIsResumed == messageType)
     372        VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsResumed");
     373    else if (kIOMessageServiceIsRequestingClose == messageType)
     374        VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsRequestingClose");
     375    else if (kIOMessageServiceIsAttemptingOpen == messageType)
     376        VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsAttemptingOpen");
     377    else if (kIOMessageServiceWasClosed == messageType)
     378        VERBOSE(VB_RECORD, loc + "kIOMessageServiceWasClosed");
     379    else if (kIOMessageServiceBusyStateChange == messageType)
     380        VERBOSE(VB_RECORD, loc + "kIOMessageServiceBusyStateChange");
     381    else if (kIOMessageCanDevicePowerOff == messageType)
     382        VERBOSE(VB_RECORD, loc + "kIOMessageCanDevicePowerOff");
     383    else if (kIOMessageDeviceWillPowerOff == messageType)
     384        VERBOSE(VB_RECORD, loc + "kIOMessageDeviceWillPowerOff");
     385    else if (kIOMessageDeviceWillNotPowerOff == messageType)
     386        VERBOSE(VB_RECORD, loc + "kIOMessageDeviceWillNotPowerOff");
     387    else if (kIOMessageDeviceHasPoweredOn == messageType)
     388        VERBOSE(VB_RECORD, loc + "kIOMessageDeviceHasPoweredOn");
     389    else if (kIOMessageCanSystemPowerOff == messageType)
     390        VERBOSE(VB_RECORD, loc + "kIOMessageCanSystemPowerOff");
     391    else if (kIOMessageSystemWillPowerOff == messageType)
     392        VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillPowerOff");
     393    else if (kIOMessageSystemWillNotPowerOff == messageType)
     394        VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillNotPowerOff");
     395    else if (kIOMessageCanSystemSleep == messageType)
     396        VERBOSE(VB_RECORD, loc + "kIOMessageCanSystemSleep");
     397    else if (kIOMessageSystemWillSleep == messageType)
     398        VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillSleep");
     399    else if (kIOMessageSystemWillNotSleep == messageType)
     400        VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillNotSleep");
     401    else if (kIOMessageSystemHasPoweredOn == messageType)
     402        VERBOSE(VB_RECORD, loc + "kIOMessageSystemHasPoweredOn");
     403    else if (kIOMessageSystemWillRestart == messageType)
     404        VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillRestart");
     405    else
     406    {
     407        VERBOSE(VB_RECORD, loc + "unknown message 0x"
     408                <<hex<<messageType<<dec);
     409    }
     410}
  • libs/libmythtv/darwinfirewiredevice.h

     
     1#ifndef _DARWIN_FIREWIRE_DEVICE_H_
     2#define _DARWIN_FIREWIRE_DEVICE_H_
     3
     4#include "firewiredevice.h"
     5
     6class DFDPriv;
     7class DarwinAVCInfo;
     8
     9class DarwinFirewireDevice : public FirewireDevice
     10{
     11    friend void *dfd_controller_thunk(void *param);
     12    friend void dfd_update_device_list_item(DarwinFirewireDevice *dev,
     13                                       uint64_t guid, void *item);
     14    friend int dfd_no_data_notification(void *cb_data);
     15    friend void dfd_stream_msg(
     16        long unsigned int msg, long unsigned int param1,
     17        long unsigned int param2, void *callback_data);
     18    friend int dfd_tspacket_handler(
     19        uint tsPacketCount, uint32_t **ppBuf, void *callback_data);
     20
     21
     22  public:
     23    DarwinFirewireDevice(uint64_t guid, uint subunitid, uint speed);
     24    ~DarwinFirewireDevice();
     25
     26    virtual bool OpenPort(void);
     27    virtual bool ClosePort(void);
     28
     29    virtual void AddListener(TSDataListener*);
     30    virtual void RemoveListener(TSDataListener*);
     31
     32    // Gets
     33    virtual bool IsPortOpen(void) const;
     34
     35    // Statics
     36    static vector<AVCInfo> GetSTBList(void);
     37
     38  private:
     39    void StartController(void);
     40    void StopController(void);
     41
     42    bool OpenAVStream(void);
     43    bool CloseAVStream(void);
     44    bool IsAVStreamOpen(void) const;
     45
     46    bool StartStreaming(void);
     47    bool StopStreaming(void);
     48
     49    virtual bool SendAVCCommand(
     50        const vector<uint8_t> &cmd,
     51        vector<uint8_t>       &result,
     52        int                   /*retry_cnt*/);
     53
     54    bool UpdatePlugRegisterPrivate(
     55        uint plug_number, int fw_chan, int new_speed,
     56        bool add_plug, bool remove_plug);
     57    bool UpdatePlugRegister(
     58        uint plug_number, int fw_chan, int speed,
     59        bool add_plug, bool remove_plug, uint retry_cnt = 4);
     60
     61    void RunController(void);
     62    void BroadcastToListeners(const unsigned char *data, uint dataSize);
     63    void UpdateDeviceListItem(uint64_t guid, void *item);
     64    void PrintNoDataMessage(void);
     65    void ProcessStreamingMessage(
     66        uint32_t msg, uint32_t param1, uint32_t param2);
     67
     68    DarwinAVCInfo *GetInfoPtr(void);
     69    const DarwinAVCInfo *GetInfoPtr(void) const;
     70
     71    int GetMaxSpeed(void);
     72    bool IsSTBStreaming(uint *fw_channel = NULL);
     73
     74    vector<AVCInfo> GetSTBListPrivate(void);
     75
     76  private:
     77    uint     m_node;
     78    DFDPriv *m_priv;
     79};
     80
     81#endif // _DARWIN_FIREWIRE_DEVICE_H_
  • libs/libmythtv/darwinfirewirechannel.cpp

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

     
     1#ifndef _DARWIN_AVC_INFO_H_
     2#define _DARWIN_AVC_INFO_H_
     3
     4#ifdef USING_OSX_FIREWIRE
     5
     6// OS X headers
     7#undef always_inline
     8#include <IOKit/IOMessage.h>
     9#include <IOKit/IOKitLib.h>
     10#include <IOKit/firewire/IOFireWireLib.h>
     11#include <IOKit/firewire/IOFireWireLibIsoch.h>
     12#include <IOKit/firewire/IOFireWireFamilyCommon.h>
     13#include <IOKit/avc/IOFireWireAVCLib.h>
     14
     15// Qt headers
     16#include <qmap.h>
     17
     18// MythTV headers
     19#include "firewiredevice.h"
     20
     21class DarwinAVCInfo : public AVCInfo
     22{
     23  public:
     24    DarwinAVCInfo() :
     25        fw_node_ref(NULL), fw_device_ref(NULL),
     26        fw_service_ref(NULL), avc_service_ref(NULL),
     27        fw_device_notifier_ref(NULL),
     28        avc_handle(NULL), fw_handle(NULL)
     29    {
     30        memset(unit_table, 0xff, sizeof(unit_table));
     31    }
     32
     33    void Update(uint64_t _guid, IONotificationPortRef notify_port,
     34                CFRunLoopRef &thread_cf_ref, io_object_t obj);
     35
     36    bool Open(CFRunLoopRef &thread_cf_ref);
     37    void Close(void);
     38
     39    bool OpenAVCInterface(CFRunLoopRef &thread_cf_ref);
     40    void CloseAVCInterface(void);
     41
     42    bool OpenDeviceInterface(CFRunLoopRef &thread_cf_ref);
     43    void CloseDeviceInterface(void);
     44
     45    bool SendAVCCommand(
     46        const vector<uint8_t> &cmd,
     47        vector<uint8_t>       &result,
     48        int                   retry_cnt);
     49
     50    bool IsAVCInterfaceOpen(void) const
     51        { return avc_handle; }
     52
     53    bool IsOpen(void) const
     54        { return fw_handle; }
     55
     56  public:
     57    uint8_t      unit_table[32];
     58
     59    io_service_t fw_node_ref;     // parent of fw_device_ref
     60    io_service_t fw_device_ref;   // parent of fw_service_ref
     61    io_service_t fw_service_ref;  // parent of avc_service_ref
     62    io_service_t avc_service_ref;
     63
     64    io_object_t  fw_device_notifier_ref;
     65
     66    IOFireWireAVCLibUnitInterface **avc_handle;
     67    IOFireWireLibDeviceRef          fw_handle;
     68};
     69typedef QMap<uint64_t,DarwinAVCInfo*> avcinfo_list_t;
     70
     71#endif // USING_OSX_FIREWIRE
     72
     73#endif // _DARWIN_AVC_INFO_H_
  • libs/libmythtv/mpeg/streamlisteners.h

     
    3333class ServiceDescriptionTable;
    3434class DVBEventInformationTable;
    3535
     36class TSDataListener
     37{
     38  public:
     39    /// Callback function to add MPEG2 TS data
     40    virtual void AddData(const unsigned char *data, uint dataSize) = 0;
     41
     42  protected:
     43    virtual ~TSDataListener() { }
     44};
     45
    3646class MPEGStreamListener
    3747{
    3848  protected:
  • libs/libmythtv/darwinfirewirechannel.h

     
    1 /**
    2  *  DarwinFirewireChannel
    3  *  Copyright (c) 2005 by Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 
    8 #ifndef LIBMYTHTV_DARWINFIREWIRECHANNEL_H
    9 #define LIBMYTHTV_DARWINFIREWIRECHANNEL_H
    10 
    11 #include <qstring.h>
    12 #include "tv_rec.h"
    13 #include "firewirechannelbase.h"
    14 
    15 
    16 namespace AVS
    17 {
    18   class AVCDeviceController;
    19   class AVCDevice;
    20 }
    21 
    22 class DarwinFirewireChannel : public FirewireChannelBase
    23 {
    24   public:
    25     DarwinFirewireChannel(FireWireDBOptions const&, TVRec *parent);
    26 
    27     // Gets
    28     AVS::AVCDevice* GetAVCDevice() const;
    29 
    30     // Sets
    31     bool SetChannelByNumber(int channel);
    32 
    33   private:
    34     bool OpenFirewire();
    35     void CloseFirewire();
    36 
    37   private:
    38     AVS::AVCDeviceController* device_controller;
    39     AVS::AVCDevice* device;
    40 };
    41 
    42 #endif
  • libs/libmythtv/signalmonitor.cpp

     
    3434#   include "iptvchannel.h"
    3535#endif
    3636
     37#ifdef USING_FIREWIRE
     38#   include "firewiresignalmonitor.h"
     39#   include "firewirechannel.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        FirewireChannel *fc = dynamic_cast<FirewireChannel*>(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 "firewiredevice.h"
     12#include "util.h"
     13
     14class FirewireChannel;
     15
     16class FirewireSignalMonitor : public DTVSignalMonitor, public TSDataListener
     17{
     18    Q_OBJECT
     19
     20  public:
     21    FirewireSignalMonitor(int db_cardnum, FirewireChannel *_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

     
    1 /**
    2  *  FirewireRecorder
    3  *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 #ifndef LIBMYTHTV_DARWINFIREWIRERECORDER_H_
    8 #define LIBMYTHTV_DARWINFIREWIRERECORDER_H_
    9 
    10 #include "firewirerecorderbase.h"
    11 #include "darwinfirewirechannel.h"
    12 
    13 //#include <IOKit/IOReturn.h>
    14 //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
    15 
    16 typedef unsigned long UInt32;
    17 typedef int IOReturn;
    18 
    19 namespace AVS
    20 {
    21   class AVCDeviceController;
    22   class AVCDevice;
    23   class StringLogger;
    24   class AVCDeviceStream;
    25 }
    26 
    27 /** \class DarwinFirewireRecorder
    28  *  \brief This is a specialization of DTVRecorder used to
    29  *         handle DVB and ATSC streams from a firewire input.
    30  *
    31  *  \sa DTVRecorder
    32  */
    33 class DarwinFirewireRecorder : public FirewireRecorderBase
    34 {
    35   public:
    36     DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner);
    37     ~DarwinFirewireRecorder();
    38 
    39     bool Open(void);
    40 
    41     void SetOption(const QString &name, const QString &value);
    42     void SetOption(const QString &name, int value);
    43 
    44   private:
    45     void Close();
    46 
    47     void start();
    48     void stop();
    49     void no_data();
    50     bool grab_frames();
    51 
    52     static IOReturn MPEGNoData(void* pRefCon);
    53     static IOReturn tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf, void *pRefCon);
    54 
    55     AVS::AVCDevice* capture_device;
    56     AVS::StringLogger* message_log;
    57     AVS::AVCDeviceStream* video_stream;
    58 
    59     bool isopen;
    60 };
    61 
    62 #endif
  • libs/libmythtv/cardutil.cpp

     
    680680{
    681681    QString label = QString::null;
    682682
    683     if (cardtype == "FIREWIRE")
     683    if (cardtype == "DBOX2")
    684684    {
    685685        MSqlQuery query(MSqlQuery::InitCon());
    686686        query.prepare(
    687             "SELECT firewire_port, firewire_node "
    688             "FROM capturecard "
    689             "WHERE cardid = :CARDID");
    690         query.bindValue(":CARDID", cardid);
    691 
    692         if (!query.exec() || !query.isActive() || !query.next())
    693             label = "[ DB ERROR ]";
    694         else
    695             label = QString("[ FIREWIRE : Port %2 Node %3 ]")
    696                 .arg(query.value(0).toString())
    697                 .arg(query.value(1).toString());
    698  
    699     }
    700     else if (cardtype == "DBOX2")
    701     {
    702         MSqlQuery query(MSqlQuery::InitCon());
    703         query.prepare(
    704687            "SELECT dbox2_host, dbox2_port, dbox2_httpport "
    705688            "FROM capturecard "
    706689            "WHERE cardid = :CARDID");
  • libs/libmythtv/firewirechannel.h

     
    11/**
    22 *  FirewireChannel
    3  *  Copyright (c) 2005 by Jim Westfall
    4  *  SA3250HD support Copyright (c) 2005 by Matt Porter
     3 *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
    54 *  Distributed as part of MythTV under GPL v2 and later.
    65 */
    76
     7#ifndef _FIREWIRECHANNEL_H_
     8#define _FIREWIRECHANNEL_H_
    89
    9 #ifndef FIREWIRECHANNEL_H
    10 #define FIREWIRECHANNEL_H
    11 
    12 #include <qstring.h>
    1310#include "tv_rec.h"
    14 #include "firewirechannelbase.h"
    15 #include <libavc1394/avc1394.h>
     11#include "dtvchannel.h"
     12#include "firewiredevice.h"
    1613
    17 using namespace std;
    18 
    19 class FirewireChannel : public FirewireChannelBase
     14class FirewireChannel : public DTVChannel
    2015{
    2116  public:
    22     enum PowerState {
    23         On,
    24         Off,
    25         Failed
    26     };
     17    FirewireChannel(TVRec *parent, const QString &videodevice,
     18                    const FireWireDBOptions &firewire_opts);
     19    ~FirewireChannel() { Close(); }
    2720
    28     FirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent);
    29     ~FirewireChannel(void);
     21    // Commands
     22    virtual bool Open(void);
     23    virtual void Close(void);
     24    virtual bool SwitchToInput(const QString &inputname, const QString &chan);
     25    virtual bool SwitchToInput(int newcapchannel, bool setstarting);
    3026
    31     bool OpenFirewire(void);
    32     void CloseFirewire(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);
    3332
    3433    // Sets
    35     void SetExternalChanger(void);
    36     bool SetChannelByNumber(int channel);
     34    virtual bool SetChannelByString(const QString &chan);
     35    virtual bool SetChannelByNumber(int channel);
     36    virtual bool SetPowerState(bool on);
    3737
    3838    // Gets
    39     bool IsOpen(void) const { return isopen; }
    40     QString GetDevice(void) const
    41         { return QString("%1:%2").arg(fw_opts.port).arg(fw_opts.node); }
    42     PowerState GetPowerState(void);
     39    virtual bool IsOpen(void) const { return isopen; }
     40    virtual FirewireDevice::PowerState GetPowerState(void) const;
     41    virtual QString GetDevice(void) const;
     42    virtual FirewireDevice *GetFirewireDevice(void) { return device; }
    4343
    44   private:
     44  protected:
     45    QString            videodevice;
    4546    FireWireDBOptions  fw_opts;
    46     nodeid_t           fwnode;
    47     raw1394handle_t    fwhandle;
     47    FirewireDevice    *device;
     48    uint               current_channel;
     49    bool               isopen;
    4850};
    4951
    50 #endif
     52#endif // _FIREWIRECHANNEL_H_
  • libs/libmythtv/videosource.cpp

     
    88#include <sys/stat.h>
    99
    1010// C++ headers
    11 #include <iostream>
     11#include <algorithm>
     12using namespace std;
    1213
    1314// Qt headers
    1415#include <qapplication.h>
     
    3334#include "channelutil.h"
    3435#include "frequencies.h"
    3536#include "diseqcsettings.h"
     37#include "firewiredevice.h"
    3638
    3739#ifdef USING_DVB
    3840#include "dvbtypes.h"
     
    927929    };
    928930};
    929931
    930 class FirewireModel : public ComboBoxSetting, public CaptureCardDBStorage
     932class FirewireGUID : public ComboBoxSetting, public CaptureCardDBStorage
    931933{
    932934  public:
    933     FirewireModel(const CaptureCard &parent) :
     935    FirewireGUID(const CaptureCard &parent) :
    934936        ComboBoxSetting(this),
    935         CaptureCardDBStorage(this, parent, "firewire_model")
     937        CaptureCardDBStorage(this, parent, "videodevice")
    936938    {
    937         setLabel(QObject::tr("Cable box model"));
    938         addSelection(QObject::tr("Other"));
    939         addSelection("DCT-6200");
    940         addSelection("SA3250HD");
    941         addSelection("SA4200HD");
    942         QString help = QObject::tr(
    943             "Choose the model that most closely resembles your set top box. "
    944             "Depending on firmware revision SA4200HD may work better for a "
    945             "SA3250HD box.");
    946         setHelpText(help);
     939        setLabel(QObject::tr("GUID"));
     940        vector<AVCInfo> list = FirewireDevice::GetSTBList();
     941        for (uint i = 0; i < list.size(); i++)
     942        {
     943            QString guid = list[i].GetGUIDString();
     944            guid_to_avcinfo[guid] = list[i];
     945            addSelection(guid);
     946        }
    947947    }
     948
     949    AVCInfo GetAVCInfo(const QString &guid) const
     950        { return guid_to_avcinfo[guid]; }
     951
     952  private:
     953    QMap<QString,AVCInfo> guid_to_avcinfo;
    948954};
    949955
     956FirewireModel::FirewireModel(const CaptureCard  &parent,
     957                             const FirewireGUID *_guid) :
     958    ComboBoxSetting(this),
     959    CaptureCardDBStorage(this, parent, "firewire_model"),
     960    guid(_guid)
     961{
     962    setLabel(QObject::tr("Cable box model"));
     963    addSelection(QObject::tr("Generic"), "GENERIC");
     964    addSelection("DCT-6200");
     965    addSelection("DCT-6212");
     966    addSelection("DCT-6216");
     967    addSelection("SA3250HD");
     968    addSelection("SA4200HD");
     969    QString help = QObject::tr(
     970        "Choose the model that most closely resembles your set top box. "
     971        "Depending on firmware revision SA4200HD may work better for a "
     972        "SA3250HD box.");
     973    setHelpText(help);
     974}
     975
     976void FirewireModel::SetGUID(const QString &_guid)
     977{
     978    AVCInfo info = guid->GetAVCInfo(_guid);
     979    QString model = FirewireDevice::GetModelName(info.vendorid, info.modelid);
     980    setValue(max(getValueIndex(model), 0));
     981}
     982
     983void FirewireDesc::SetGUID(const QString &_guid)
     984{
     985    setLabel(tr("Description"));
     986
     987    QString name = guid->GetAVCInfo(_guid).product_name;
     988    name.replace("Scientific-Atlanta", "SA");
     989    name.replace(", Inc.", "");
     990    name.replace("Explorer(R)", "");
     991    name = name.simplifyWhiteSpace();
     992    setValue((name.isEmpty()) ? "" : name);
     993}
     994
    950995class FirewireConnection : public ComboBoxSetting, public CaptureCardDBStorage
    951996{
    952997  public:
     
    9601005    }
    9611006};
    9621007
    963 class FirewirePort : public SpinBoxSetting, public CaptureCardDBStorage
    964 {
    965   public:
    966     FirewirePort(const CaptureCard &parent) :
    967         SpinBoxSetting(this, 0, 63, 1),
    968         CaptureCardDBStorage(this, parent, "firewire_port")
    969     {
    970         setValue(0);
    971         setLabel(QObject::tr("IEEE-1394 Port"));
    972         setHelpText(QObject::tr("Firewire port on your firewire card."));
    973     }
    974 };
    975 
    976 class FirewireNode : public SpinBoxSetting, public CaptureCardDBStorage
    977 {
    978   public:
    979     FirewireNode(const CaptureCard &parent) :
    980         SpinBoxSetting(this, 0, 63, 1),
    981         CaptureCardDBStorage(this, parent, "firewire_node")
    982     {
    983         setValue(2);
    984         setLabel(QObject::tr("Node"));
    985         setHelpText(QObject::tr("Firewire node is the remote device."));
    986     }
    987 };
    988 
    9891008class FirewireSpeed : public ComboBoxSetting, public CaptureCardDBStorage
    9901009{
    9911010  public:
     
    9971016        addSelection(QObject::tr("100Mbps"),"0");
    9981017        addSelection(QObject::tr("200Mbps"),"1");
    9991018        addSelection(QObject::tr("400Mbps"),"2");
     1019        addSelection(QObject::tr("800Mbps"),"3");
    10001020    }
    10011021};
    10021022
     
    10181038  public:
    10191039    FirewireConfigurationGroup(CaptureCard& a_parent) :
    10201040        VerticalConfigurationGroup(false, true, false, false),
    1021         parent(a_parent)
     1041        parent(a_parent),
     1042        dev(new FirewireGUID(parent)),
     1043        desc(new FirewireDesc(dev)),
     1044        model(new FirewireModel(parent, dev))
    10221045    {
    1023         HorizontalConfigurationGroup *hg0 =
    1024             new HorizontalConfigurationGroup(false, false, true, true);
    1025         hg0->addChild(new FirewireModel(parent));
    1026         hg0->addChild(new FirewireConnection(parent));
    1027         addChild(hg0);
    1028         HorizontalConfigurationGroup *hg1 =
    1029             new HorizontalConfigurationGroup(false, false, true, true);
    1030         hg1->addChild(new FirewirePort(parent));
    1031         hg1->addChild(new FirewireNode(parent));
    1032         hg1->addChild(new FirewireSpeed(parent));
    1033         addChild(hg1);
    1034         addChild(new FirewireInput(parent));
     1046        addChild(dev);
     1047        addChild(desc);
     1048        addChild(model);
     1049
     1050#ifdef USING_LINUX_FIREWIRE
     1051        addChild(new FirewireConnection(parent));
     1052        addChild(new FirewireSpeed(parent));
     1053#endif // USING_LINUX_FIREWIRE
     1054
     1055        addChild(new ChannelTimeout(parent, 9000));
     1056
     1057        FirewireInput *defaultinput = new FirewireInput(parent);
     1058        defaultinput->setVisible(false);
     1059        addChild(defaultinput);
     1060
     1061        connect(dev,   SIGNAL(valueChanged(const QString&)),
     1062                model, SLOT(  SetGUID(     const QString&)));
     1063        connect(dev,   SIGNAL(valueChanged(const QString&)),
     1064                desc,  SLOT(  SetGUID(     const QString&)));
    10351065    };
     1066
    10361067  private:
    1037     CaptureCard &parent;
     1068    CaptureCard   &parent;
     1069    FirewireGUID  *dev;
     1070    FirewireDesc *desc;
     1071    FirewireModel *model;
    10381072};
    10391073
    10401074class DBOX2Port : public LineEditSetting, public CaptureCardDBStorage
     
    11861220        HDHRCardInput *defaultinput = new HDHRCardInput(parent);
    11871221        addChild(defaultinput);
    11881222        defaultinput->setVisible(false);
     1223
     1224        addChild(new SignalTimeout(parent, 1000));
     1225        addChild(new ChannelTimeout(parent, 3000));
    11891226    };
    11901227
    11911228  private:
  • libs/libmythtv/selectavcdevice.cpp

     
    1 /**
    2  *  SelectAVCDevice
    3  *  Copyright (c) 2006 by Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 #include "mythconfig.h"
    8 
    9 #ifdef CONFIG_DARWIN
    10 # include "mythcontext.h"
    11 # include "selectavcdevice.h"
    12 # undef always_inline
    13 # include <AVCVideoServices/AVCVideoServices.h>
    14 
    15 AVS::AVCDevice* SelectAVCDevice(
    16     AVS::AVCDeviceController* controller,
    17     bool (*filter)(AVS::AVCDevice*)
    18 )
    19 {
    20     VERBOSE(VB_GENERAL, QString("SelectAVCDevice:"));
    21 
    22     for (unsigned n = CFArrayGetCount(controller->avcDeviceArray),
    23              i = 0; i < n; ++i)
    24     {
    25         AVS::AVCDevice& d = *(AVS::AVCDevice*)CFArrayGetValueAtIndex(controller->avcDeviceArray, i);
    26 
    27         VERBOSE(
    28             VB_GENERAL,
    29             QString("SelectAVCDevice: %1, format: %2, attached: %3, type: %4")
    30                 .arg(d.deviceName)
    31                 .arg(d.isDVDevice ? "DV" : d.isMPEGDevice ? "MPEG2-TS" : "unknown")
    32                 .arg(d.isAttached ? "yes" : "no")
    33                 .arg(d.hasTapeSubunit ? "tape" : d.hasMonitorOrTunerSubunit ? "tuner" : "unknown")
    34         );
    35 
    36         if (filter(&d))
    37         {
    38             VERBOSE(VB_GENERAL, QString("SelectAVCDevice: FOUND"));
    39             return &d;
    40         }
    41     }
    42     VERBOSE(VB_GENERAL, QString("SelectAVCDevice: NOT FOUND"));
    43     return 0;
    44 }
    45 
    46 #endif // CONFIG_DARWIN
    47 
  • libs/libmythtv/firewirechannelbase.cpp

     
    1 /**
    2  *  FirewireChannelBase
    3  *  Copyright (c) 2005 by Jim Westfall Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 
    8 #include <iostream>
    9 #include "mythcontext.h"
    10 #include "firewirechannelbase.h"
    11 
    12 bool FirewireChannelBase::SetChannelByString(const QString &chan)
    13 {
    14     inputs[currentInputID]->startChanNum = chan;
    15     curchannelname = chan;
    16 
    17     InputMap::const_iterator it = inputs.find(currentInputID);
    18 
    19     if (!(*it)->externalChanger.isEmpty())
    20         return ChangeExternalChannel(chan);
    21 
    22     return isopen && SetChannelByNumber(chan.toInt());
    23 }
    24 
    25 bool FirewireChannelBase::Open()
    26 {
    27     if (!InitializeInputs())
    28         return false;
    29 
    30     InputMap::const_iterator it = inputs.find(currentInputID);
    31     if (!(*it)->externalChanger.isEmpty())
    32         return true;
    33 
    34     if (!isopen)
    35     {
    36         isopen = OpenFirewire();
    37         return isopen;
    38     }
    39     return true;
    40 }
    41 
    42 void FirewireChannelBase::Close()
    43 {
    44     if (isopen)
    45         CloseFirewire();
    46     isopen = false;
    47 }
    48    
    49 bool FirewireChannelBase::SwitchToInput(const QString &input,
    50                                         const QString &chan)
    51 {
    52     int inputNum = GetInputByName(input);
    53     if (inputNum < 0)
    54         return false;
    55 
    56     return SetChannelByString(chan);
    57 }
  • 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 "firewiredevice.h"
     11
     12class LFDPriv;
     13
     14class LinuxFirewireDevice : public FirewireDevice
     15{
     16    friend void *linux_firewire_device_streaming_thunk(void *param);
     17    friend int linux_firewire_device_tspacket_handler(
     18        unsigned char *tspacket, int len, uint dropped, void *callback_data);
     19
     20  public:
     21    LinuxFirewireDevice(uint64_t guid, uint subunitid,
     22                        uint speed, bool use_p2p,
     23                        uint av_buffer_size_in_bytes = 0);
     24    ~LinuxFirewireDevice();
     25
     26    // Commands
     27    virtual bool OpenPort(void);
     28    virtual bool ClosePort(void);
     29
     30    virtual void AddListener(TSDataListener*);
     31    virtual void RemoveListener(TSDataListener*);
     32
     33    // Gets
     34    virtual bool IsPortOpen(void) const;
     35
     36    // Statics
     37    static vector<AVCInfo> GetSTBList(void);
     38
     39    // Constants
     40    static const uint kBroadcastChannel;
     41    static const uint kConnectionP2P;
     42    static const uint kConnectionBroadcast;
     43    static const uint kMaxBufferedPackets;
     44
     45  private:
     46    bool GetPortAndNode(void);
     47
     48    bool OpenNode(void);
     49    bool CloseNode(void);
     50
     51    bool OpenAVStream(void);
     52    bool CloseAVStream(void);
     53
     54    bool OpenP2PNode(void);
     55    bool CloseP2PNode(void);
     56
     57    bool OpenBroadcastNode(void);
     58    bool CloseBroadcastNode(void);
     59
     60    bool StartStreaming(void);
     61    bool StopStreaming(void);
     62    bool StopStreamingLater(void);
     63
     64    bool ResetBus(void);
     65
     66    void RunStreaming(void);
     67    bool LoopIteration(uint timeout_in_msec);
     68    void PrintDropped(uint dropped_packets);
     69
     70    bool SetAVStreamBufferSize(uint size_in_bytes);
     71    bool SetAVStreamSpeed(uint speed);
     72
     73    bool IsNodeOpen(void) const;
     74    bool IsAVStreamOpen(void) const;
     75
     76    virtual bool SendAVCCommand(const vector<uint8_t> &cmd,
     77                                vector<uint8_t>       &result,
     78                                int                    retry_cnt);
     79
     80  private:
     81    int                      m_port;
     82    int                      m_node;
     83    uint                     m_bufsz;
     84    bool                     m_use_p2p;
     85    bool                     m_resetting;
     86    LFDPriv                 *m_priv;
     87};
     88
     89#endif // _LINUX_FIREWIRE_DEVICE_H_
  • libs/libmythtv/tv_rec.cpp

     
    4848#include "dbox2channel.h"
    4949#include "hdhrchannel.h"
    5050#include "iptvchannel.h"
     51#include "firewirechannel.h"
    5152
    5253#include "recorderbase.h"
    5354#include "NuppelVideoRecorder.h"
     
    5758#include "dbox2recorder.h"
    5859#include "hdhrrecorder.h"
    5960#include "iptvrecorder.h"
     61#include "firewirerecorder.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
     153        channel = new FirewireChannel(this, genOpt.videodev, fwOpt);
    166154        if (!channel->Open())
    167155            return false;
    168156        InitChannel(genOpt.defaultinput, startchannel);
     
    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 = new FirewireRecorder(this, GetFirewireChannel());
    844823#endif // USING_FIREWIRE
    845824    }
    846825    else if (genOpt.cardtype == "DBOX2")
     
    11141093#endif // USING_DVB
    11151094}
    11161095
     1096FirewireChannel *TVRec::GetFirewireChannel(void)
     1097{
     1098#ifdef USING_FIREWIRE
     1099    return dynamic_cast<FirewireChannel*>(channel);
     1100#else
     1101    return NULL;
     1102#endif // USING_FIREWIRE
     1103}
     1104
    11171105Channel *TVRec::GetV4LChannel(void)
    11181106{
    11191107#ifdef USING_V4L
     
    14181406        ""
    14191407        "       dvb_on_demand,    dvb_tuning_delay, "
    14201408        ""
    1421         "       firewire_port,    firewire_node,       firewire_speed,  "
    1422         "       firewire_model,   firewire_connection,                  "
     1409        "       firewire_speed,   firewire_model,      firewire_connection, "
    14231410        ""
    14241411        "       dbox2_port,       dbox2_host,          dbox2_httpport   "
    14251412        ""
     
    14791466
    14801467    // Firewire options
    14811468    uint fireoff = dvboff + 2;
    1482     firewire_opts.port        = query.value(fireoff + 0).toUInt();
    1483     firewire_opts.node        = query.value(fireoff + 1).toUInt();
    1484     firewire_opts.speed       = query.value(fireoff + 2).toUInt();
     1469    firewire_opts.speed       = query.value(fireoff + 0).toUInt();
    14851470
    1486     test = query.value(fireoff + 3).toString();
     1471    test = query.value(fireoff + 1).toString();
    14871472    if (test != QString::null)
    14881473        firewire_opts.model = QString::fromUtf8(test);
    14891474
    1490     firewire_opts.connection  = query.value(fireoff + 4).toUInt();
     1475    firewire_opts.connection  = query.value(fireoff + 2).toUInt();
    14911476
    14921477    // DBOX2/HDHomeRun options
    1493     uint dbox2off = fireoff + 5;
     1478    uint dbox2off = fireoff + 3;
    14941479    dbox2_opts.port = query.value(dbox2off + 0).toUInt();
    14951480
    14961481    test = query.value(dbox2off + 1).toString();
  • libs/libmythtv/tv_rec.h

     
    3535class DBox2Channel;
    3636class DTVChannel;
    3737class DVBChannel;
     38class FirewireChannel;
    3839class Channel;
    3940class HDHRChannel;
    4041
     
    8586class FireWireDBOptions
    8687{
    8788  public:
    88     FireWireDBOptions() :
    89         port(-1), node(-1), speed(-1), connection(-1), model("") {;}
    90        
    91     int port;
    92     int node;
     89    FireWireDBOptions() : speed(-1), connection(-1), model("") {;}
     90
    9391    int speed;
    9492    int connection;
    9593    QString model;
     
    261259    DTVChannel   *GetDTVChannel(void);
    262260    HDHRChannel  *GetHDHRChannel(void);
    263261    DVBChannel   *GetDVBChannel(void);
     262    FirewireChannel *GetFirewireChannel(void);
    264263    Channel      *GetV4LChannel(void);
    265264
    266265    bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
  • libs/libmythtv/selectavcdevice.h

     
    1 /**
    2  *  SelectAVCDevice
    3  *  Copyright (c) 2006 by Dave Abrahams
    4  *  Distributed as part of MythTV under GPL v2 and later.
    5  */
    6 
    7 #ifndef LIBMYTHTV_SELECTAVCDEVICE_H_
    8 # define LIBMYTHTV_SELECTAVCDEVICE_H_
    9 
    10 # include "mythconfig.h"
    11 
    12 # ifdef CONFIG_DARWIN
    13 #  undef always_inline
    14 #  include <AVCVideoServices/AVCVideoServices.h>
    15 
    16 AVS::AVCDevice* SelectAVCDevice(
    17     AVS::AVCDeviceController*,
    18     bool (*)(AVS::AVCDevice*)
    19 );
    20 
    21 # endif // CONFIG_DARWIN
    22 
    23 #endif LIBMYTHTV_SELECTAVCDEVICE_H_
    24 
  • 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// Qt headers
     15#include <qstring.h>
     16#include <qmutex.h>
     17
     18// MythTV headers
     19#include "streamlisteners.h"
     20
     21class TSPacket;
     22
     23class AVCInfo
     24{
     25  public:
     26    int      port;
     27    int      node;
     28    uint64_t guid;
     29    uint     specid;
     30    uint     vendorid;
     31    uint     modelid;
     32    uint     firmware_revision;
     33    QString  product_name;
     34
     35    AVCInfo();
     36    AVCInfo(const AVCInfo &o);
     37    AVCInfo &operator=(const AVCInfo &o);
     38
     39    QString GetGUIDString(void) const;
     40};
     41
     42class FirewireDevice
     43{
     44  public:
     45
     46    // Public enums
     47    typedef enum
     48    {
     49        kAVCPowerOn,
     50        kAVCPowerOff,
     51        kAVCPowerUnknown,
     52        kAVCPowerQueryFailed,
     53    } PowerState;
     54
     55    // AVC commands
     56    typedef enum
     57    {
     58        kAVCControlCommand         = 0x00,
     59        kAVCStatusInquiryCommand   = 0x01,
     60        kAVCSpecificInquiryCommand = 0x02,
     61        kAVCNotifyCommand          = 0x03,
     62        kAVCGeneralInquiryCommand  = 0x04,
     63
     64        kAVCNotImplementedStatus   = 0x08,
     65        kAVCAcceptedStatus         = 0x09,
     66        kAVCRejectedStatus         = 0x0a,
     67        kAVCInTransitionStatus     = 0x0b,
     68        kAVCImplementedStatus      = 0x0c,
     69        kAVCChangedStatus          = 0x0d,
     70
     71        kAVCInterimStatus          = 0x0f,
     72        kAVCResponseImplemented    = 0x0c,
     73    } IEEE1394Command;
     74
     75    // AVC unit addresses
     76    typedef enum
     77    {
     78        kAVCSubunitId0                = 0x00,
     79        kAVCSubunitId1                = 0x01,
     80        kAVCSubunitId2                = 0x02,
     81        kAVCSubunitId3                = 0x03,
     82        kAVCSubunitId4                = 0x04,
     83        kAVCSubunitIdExtended         = 0x05,
     84        kAVCSubunitIdIgnore           = 0x07,
     85
     86        kAVCSubunitTypeVideoMonitor   = (0x00 << 3),
     87        kAVCSubunitTypeAudio          = (0x01 << 3),
     88        kAVCSubunitTypePrinter        = (0x02 << 3),
     89        kAVCSubunitTypeDiscRecorder   = (0x03 << 3),
     90        kAVCSubunitTypeTapeRecorder   = (0x04 << 3),
     91        kAVCSubunitTypeTuner          = (0x05 << 3),
     92        kAVCSubunitTypeCA             = (0x06 << 3),
     93        kAVCSubunitTypeVideoCamera    = (0x07 << 3),
     94        kAVCSubunitTypePanel          = (0x09 << 3),
     95        kAVCSubunitTypeBulletinBoard  = (0x0a << 3),
     96        kAVCSubunitTypeCameraStorage  = (0x0b << 3),
     97        kAVCSubunitTypeMusic          = (0x0c << 3),
     98        kAVCSubunitTypeVendorUnique   = (0x1c << 3),
     99        kAVCSubunitTypeExtended       = (0x1e << 3),
     100        kAVCSubunitTypeUnit           = (0x1f << 3),
     101    } IEEE1394UnitAddress;
     102
     103    // AVC opcode
     104    typedef enum
     105    {
     106        // Unit
     107        kAVCUnitPlugInfoOpcode               = 0x02,
     108        kAVCUnitDigitalOutputOpcode          = 0x10,
     109        kAVCUnitDigitalInputOpcode           = 0x11,
     110        kAVCUnitChannelUsageOpcode           = 0x12,
     111        kAVCUnitOutputPlugSignalFormatOpcode = 0x18,
     112        kAVCUnitInputPlugSignalFormatOpcode  = 0x19,
     113        kAVCUnitConnectAVOpcode              = 0x20,
     114        kAVCUnitDisconnectAVOpcode           = 0x21,
     115        kAVCUnitConnectionsOpcode            = 0x22,
     116        kAVCUnitConnectOpcode                = 0x24,
     117        kAVCUnitDisconnectOpcode             = 0x25,
     118        kAVCUnitUnitInfoOpcode               = 0x30,
     119        kAVCUnitSubunitInfoOpcode            = 0x31,
     120        kAVCUnitSignalSourceOpcode           = 0x1a,
     121        kAVCUnitPowerOpcode                  = 0xb2,
     122
     123        // Common Unit + Subunit
     124        kAVCCommonOpenDescriptorOpcode       = 0x08,
     125        kAVCCommonReadDescriptorOpcode       = 0x09,
     126        kAVCCommonWriteDescriptorOpcode      = 0x0A,
     127        kAVCCommonSearchDescriptorOpcode     = 0x0B,
     128        kAVCCommonObjectNumberSelectOpcode   = 0x0D,
     129        kAVCCommonPowerOpcode                = 0xB2,
     130        kAVCCommonReserveOpcode              = 0x01,
     131        kAVCCommonPlugInfoOpcode             = 0x02,
     132        kAVCCommonVendorDependentOpcode      = 0x00,
     133
     134        // Panel
     135        kAVCPanelPassThrough                 = 0x7c,
     136    } IEEE1394Opcode;
     137
     138    // AVC param 0
     139    typedef enum
     140    {
     141        kAVCPowerStateOn           = 0x70,
     142        kAVCPowerStateOff          = 0x60,
     143        kAVCPowerStateQuery        = 0x7f,
     144    } IEEE1394UnitPowerParam0;
     145
     146    typedef enum
     147    {
     148        kAVCPanelKeySelect          = 0x00,
     149        kAVCPanelKeyUp              = 0x01,
     150        kAVCPanelKeyDown            = 0x02,
     151        kAVCPanelKeyLeft            = 0x03,
     152        kAVCPanelKeyRight           = 0x04,
     153        kAVCPanelKeyRightUp         = 0x05,
     154        kAVCPanelKeyRightDown       = 0x06,
     155        kAVCPanelKeyLeftUp          = 0x07,
     156        kAVCPanelKeyLeftDown        = 0x08,
     157        kAVCPanelKeyRootMenu        = 0x09,
     158        kAVCPanelKeySetupMenu       = 0x0A,
     159        kAVCPanelKeyContentsMenu    = 0x0B,
     160        kAVCPanelKeyFavoriteMenu    = 0x0C,
     161        kAVCPanelKeyExit            = 0x0D,
     162
     163        kAVCPanelKey0               = 0x20,
     164        kAVCPanelKey1               = 0x21,
     165        kAVCPanelKey2               = 0x22,
     166        kAVCPanelKey3               = 0x23,
     167        kAVCPanelKey4               = 0x24,
     168        kAVCPanelKey5               = 0x25,
     169        kAVCPanelKey6               = 0x26,
     170        kAVCPanelKey7               = 0x27,
     171        kAVCPanelKey8               = 0x28,
     172        kAVCPanelKey9               = 0x29,
     173        kAVCPanelKeyDot             = 0x2A,
     174        kAVCPanelKeyEnter           = 0x2B,
     175        kAVCPanelKeyClear           = 0x2C,
     176
     177        kAVCPanelKeyChannelUp       = 0x30,
     178        kAVCPanelKeyChannelDown     = 0x31,
     179        kAVCPanelKeyPreviousChannel = 0x32,
     180        kAVCPanelKeySoundSelect     = 0x33,
     181        kAVCPanelKeyInputSelect     = 0x34,
     182        kAVCPanelKeyDisplayInfo     = 0x35,
     183        kAVCPanelKeyHelp            = 0x36,
     184        kAVCPanelKeyPageUp          = 0x37,
     185        kAVCPanelKeyPageDown        = 0x38,
     186
     187        kAVCPanelKeyPower           = 0x40,
     188        kAVCPanelKeyVolumeUp        = 0x41,
     189        kAVCPanelKeyVolumeDown      = 0x42,
     190        kAVCPanelKeyMute            = 0x43,
     191        kAVCPanelKeyPlay            = 0x44,
     192        kAVCPanelKeyStop            = 0x45,
     193        kAVCPanelKeyPause           = 0x46,
     194        kAVCPanelKeyRecord          = 0x47,
     195        kAVCPanelKeyRewind          = 0x48,
     196        kAVCPanelKeyFastForward     = 0x49,
     197        kAVCPanelKeyEject           = 0x4a,
     198        kAVCPanelKeyForward         = 0x4b,
     199        kAVCPanelKeyBackward        = 0x4c,
     200
     201        kAVCPanelKeyAngle           = 0x50,
     202        kAVCPanelKeySubPicture      = 0x51,
     203
     204        kAVCPanelKeyTuneFunction    = 0x67,
     205
     206        kAVCPanelKeyPress           = 0x00,
     207        kAVCPanelKeyRelease         = 0x80,
     208
     209    } IEEE1394PanelPassThroughParam0;
     210
     211    virtual ~FirewireDevice() { }
     212
     213    // Commands
     214    virtual bool OpenPort(void) = 0;
     215    virtual bool ClosePort(void) = 0;
     216
     217    virtual void AddListener(TSDataListener*);
     218    virtual void RemoveListener(TSDataListener*);
     219
     220    // Sets
     221    virtual bool SetPowerState(bool on);
     222    virtual bool SetChannel(const QString &panel_model,
     223                            uint alt_method, uint channel);
     224
     225    // Gets
     226    virtual bool IsPortOpen(void) const = 0;
     227    bool IsSTBBufferCleared(void) const { return m_buffer_cleared; }
     228
     229    // non-const Gets
     230    virtual PowerState GetPowerState(void);
     231
     232    // Statics
     233    static inline bool IsSTBSupported(const QString &model);
     234    static QString GetModelName(uint vendorid, uint modelid);
     235    static vector<AVCInfo> GetSTBList(void);
     236    static bool IsSubunitType(
     237        const uint8_t unit_table[32], IEEE1394UnitAddress subunit_type);
     238    static QString GetSubunitInfoString(const uint8_t table[32]);
     239
     240  protected:
     241    FirewireDevice(uint64_t guid, uint subunitid, uint speed);
     242
     243    virtual bool SendAVCCommand(const vector<uint8_t> &cmd,
     244                                vector<uint8_t> &result,
     245                                int retry_cnt) = 0;
     246    bool GetSubunitInfo(uint8_t table[32]);
     247
     248    void SetLastChannel(uint channel);
     249    void ProcessPATPacket(const TSPacket&);
     250    virtual void BroadcastToListeners(
     251        const unsigned char *data, uint dataSize);
     252
     253    uint64_t                 m_guid;
     254    uint                     m_subunitid;
     255    uint                     m_speed;
     256    uint                     m_last_channel;
     257    uint                     m_last_crc;
     258    bool                     m_buffer_cleared;
     259
     260    uint                     m_open_port_cnt;
     261    vector<TSDataListener*>  m_listeners;
     262    mutable QMutex           m_lock;
     263
     264    /// Vendor ID + Model ID to FirewireDevice STB model string
     265    static QMap<uint64_t,QString> s_id_to_model;
     266    static QMutex                 s_static_lock;
     267};
     268
     269inline bool FirewireDevice::IsSTBSupported(const QString &panel_model)
     270{
     271    QString model = panel_model.upper();
     272    return ((model == "DCT-6200") ||
     273            (model == "DCT-6212") ||
     274            (model == "DCT-6216") ||
     275            (model == "SA3250HD") ||
     276            (model == "SA4200HD") ||
     277            (model == "GENERIC"));
     278}
     279
     280#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#include <cassert>
     15
     16// Linux headers
     17#include <libraw1394/raw1394.h>
     18#include <libraw1394/csr.h>
     19#include <libiec61883/iec61883.h>
     20#include <libavc1394/avc1394.h>
     21#include <libavc1394/rom1394.h>
     22
     23//#include <unistd.h>
     24//#include <string.h>
     25//#include <stdio.h>
     26//#include <stdlib.h>
     27#include <netinet/in.h>
     28
     29// C++ headers
     30#include <algorithm>
     31using namespace std;
     32
     33// Qt headers
     34#include <qdatetime.h>
     35
     36// MythTV headers
     37#include "linuxfirewiredevice.h"
     38#include "firewirerecorder.h"
     39#include "mythcontext.h"
     40
     41#define LOC      QString("LFireDev(%1:%2): ").arg(m_port).arg(m_node)
     42#define LOC_WARN QString("LFireDev(%1:%2), Warning: ").arg(m_port).arg(m_node)
     43#define LOC_ERR  QString("LFireDev(%1:%2), Error: ").arg(m_port).arg(m_node)
     44
     45class LFDPriv
     46{
     47  public:
     48    LFDPriv() :
     49        handle(0), avstream(0),
     50        channel(-1),
     51        is_p2p_node_open(false), is_bcast_node_open(false),
     52        is_streaming(false)
     53    {
     54        bzero(unit_table, sizeof(unit_table));
     55    }
     56
     57    raw1394handle_t  handle;
     58    iec61883_mpeg2_t avstream;
     59    uint8_t          unit_table[32];
     60    int              channel;
     61    int              open_node;
     62    bool             is_p2p_node_open;
     63    bool             is_bcast_node_open;
     64    bool             is_streaming;
     65    bool             is_streaming_running;
     66    QDateTime        stop_streaming_timer;
     67    pthread_t        streaming_thread;
     68    QMutex           start_stop_streaming_lock;
     69};
     70
     71const uint LinuxFirewireDevice::kBroadcastChannel    = 63;
     72const uint LinuxFirewireDevice::kConnectionP2P       = 0;
     73const uint LinuxFirewireDevice::kConnectionBroadcast = 1;
     74const uint LinuxFirewireDevice::kMaxBufferedPackets  = 2000;
     75
     76// callback function for libiec61883
     77int linux_firewire_device_tspacket_handler(
     78    unsigned char *tspacket, int len, uint dropped, void *callback_data);
     79static QString speed_to_string(uint speed);
     80static uint64_t get_guid(raw1394handle_t handle, nodeid_t node);
     81
     82LinuxFirewireDevice::LinuxFirewireDevice(
     83    uint64_t guid, uint subunitid,
     84    uint speed, bool use_p2p, uint av_buffer_size_in_bytes) :
     85    FirewireDevice(guid, subunitid, speed),
     86    m_port(-1),         m_node(-1),
     87    m_bufsz(av_buffer_size_in_bytes),
     88    m_use_p2p(use_p2p), m_resetting(false),
     89    m_priv(new LFDPriv())
     90{
     91    if (!m_bufsz)
     92        m_bufsz = gContext->GetNumSetting("HDRingbufferSize");
     93}
     94
     95LinuxFirewireDevice::~LinuxFirewireDevice()
     96{
     97    if (IsPortOpen())
     98    {
     99        VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port");
     100        while (IsPortOpen())
     101            ClosePort();
     102    }
     103
     104    if (m_priv)
     105    {
     106        delete m_priv;
     107        m_priv = NULL;
     108    }
     109}
     110
     111bool LinuxFirewireDevice::OpenPort(void)
     112{
     113    QMutexLocker locker(&m_lock);
     114
     115    VERBOSE(VB_RECORD, LOC + "OpenPort()");
     116
     117    if (m_priv->handle)
     118    {
     119        m_open_port_cnt++;
     120        return true;
     121    }
     122
     123    if (!GetPortAndNode())
     124        return false;
     125
     126    VERBOSE(VB_RECORD, LOC + "Getting raw1394 handle "<<(m_open_port_cnt-1));
     127    m_priv->handle = raw1394_new_handle_on_port(m_port);
     128
     129    if (!m_priv->handle)
     130    {
     131        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " +
     132                QString("port: %1").arg(m_port) + ENO);
     133
     134        return false;
     135    }
     136
     137    GetSubunitInfo(m_priv->unit_table);
     138    VERBOSE(VB_RECORD, LOC + GetSubunitInfoString(m_priv->unit_table));
     139
     140    if (!IsSubunitType(m_priv->unit_table, kAVCSubunitTypeTuner) ||
     141        !IsSubunitType(m_priv->unit_table, kAVCSubunitTypePanel))
     142    {
     143        VERBOSE(VB_IMPORTANT, LOC_ERR + QString("No STB at guid: 0x%1")
     144                .arg(m_guid,0,16));
     145
     146        ClosePort();
     147        return false;
     148    }
     149
     150    m_open_port_cnt++;
     151
     152    return true;
     153}
     154
     155bool LinuxFirewireDevice::ClosePort(void)
     156{
     157    QMutexLocker locker(&m_lock);
     158
     159    VERBOSE(VB_RECORD, LOC + "ClosePort()");
     160
     161    if (m_open_port_cnt < 1)
     162        return false;
     163
     164    m_open_port_cnt--;
     165
     166    if (m_open_port_cnt != 0)
     167        return true;
     168
     169    if (m_priv->handle)
     170    {
     171        if (IsNodeOpen())
     172            CloseNode();
     173
     174        VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle "<<m_open_port_cnt);
     175        raw1394_destroy_handle(m_priv->handle);
     176        m_priv->handle = NULL;
     177    }
     178
     179    return true;
     180}
     181
     182void LinuxFirewireDevice::AddListener(TSDataListener *listener)
     183{
     184    FirewireDevice::AddListener(listener);
     185
     186    QMutexLocker locker(&m_lock);
     187    if (!m_listeners.empty())
     188    {
     189        OpenNode();
     190        OpenAVStream();
     191        StartStreaming();
     192    }
     193}
     194
     195void LinuxFirewireDevice::RemoveListener(TSDataListener *listener)
     196{
     197    FirewireDevice::RemoveListener(listener);
     198
     199    QMutexLocker locker(&m_lock);
     200    if (m_listeners.empty())
     201    {
     202        StopStreaming();
     203        CloseAVStream();
     204        CloseNode();
     205    }
     206}
     207
     208bool LinuxFirewireDevice::SendAVCCommand(
     209    const vector<uint8_t>  &_cmd,
     210    vector<uint8_t>        &result,
     211    int                     retry_cnt)
     212{
     213    retry_cnt = (retry_cnt < 0) ? 2 : retry_cnt;
     214
     215    result.clear();
     216
     217    if (!m_priv->handle || (m_node < 0))
     218        return false;
     219
     220    vector<uint8_t> cmd = _cmd;
     221    while (cmd.size() & 0x3)
     222        cmd.push_back(0x00);
     223
     224    if (cmd.size() > 4096)
     225        return false;
     226
     227    uint32_t cmdbuf[1024];
     228    for (uint i = 0; i < cmd.size(); i+=4)
     229        cmdbuf[i>>2] = cmd[i]<<24 | cmd[i+1]<<16 | cmd[i+2]<<8 | cmd[i+3];
     230
     231    uint result_length = 0;
     232    uint32_t *ret = avc1394_transaction_block2(
     233        m_priv->handle, m_node, cmdbuf, (cmd.size() + 3) >> 2,
     234        &result_length, retry_cnt);
     235
     236    if (!ret)
     237        return false;
     238
     239    for (uint i = 0; i < result_length; i++)
     240    {
     241        result.push_back((ret[i]>>24) & 0xff);
     242        result.push_back((ret[i]>>16) & 0xff);
     243        result.push_back((ret[i]>>8)  & 0xff);
     244        result.push_back((ret[i])     & 0xff);
     245    }
     246
     247    avc1394_transaction_block_close(m_priv->handle);
     248
     249    return true;
     250}
     251
     252bool LinuxFirewireDevice::IsPortOpen(void) const
     253{
     254    QMutexLocker locker(&m_lock);
     255
     256    return m_priv->handle;
     257}
     258
     259///////////////////////////////////////////////////////////////////////////////
     260// Private methods
     261
     262bool LinuxFirewireDevice::GetPortAndNode(void)
     263{
     264    m_port = m_node = -1;
     265
     266    vector<AVCInfo> list = GetSTBList();
     267    for (uint i = 0; i < list.size(); i++)
     268    {
     269        if (list[i].guid == m_guid)
     270        {
     271            m_port = list[i].port;
     272            m_node = list[i].node;
     273            break;
     274        }
     275    }
     276
     277    bool ok = (m_port >= 0) && (m_node >= 0);
     278
     279    if (!ok)
     280    {
     281        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to find port and node " +
     282                QString("for guid: 0x%1").arg(m_guid,0,16));
     283    }
     284    else
     285    {
     286        VERBOSE(VB_RECORD, LOC + QString("port: %1, node: %2")
     287                .arg(m_port).arg(m_node));
     288    }
     289
     290    return ok;
     291}
     292
     293bool LinuxFirewireDevice::OpenNode(void)
     294{
     295    if (m_use_p2p)
     296        return OpenP2PNode();
     297    else
     298        return OpenBroadcastNode();
     299}
     300
     301bool LinuxFirewireDevice::CloseNode(void)
     302{
     303    if (m_priv->is_p2p_node_open)
     304        return CloseP2PNode();
     305
     306    if (m_priv->is_bcast_node_open)
     307        return CloseBroadcastNode();
     308
     309    return true;
     310}
     311
     312bool LinuxFirewireDevice::OpenP2PNode(void)
     313{
     314    if (m_priv->is_bcast_node_open)
     315        return false;
     316
     317    if (m_priv->is_p2p_node_open)
     318        return true;
     319
     320    VERBOSE(VB_RECORD, LOC + "Opening P2P connection");
     321
     322    m_priv->channel = m_node;
     323    if (iec61883_cmp_create_p2p_output(m_priv->handle, m_node | 0xffc0, 0,
     324                                       m_priv->channel, m_speed) != 0)
     325    {
     326        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create P2P connection");
     327
     328        m_priv->channel = -1;
     329        return false;
     330    }
     331
     332    m_priv->is_p2p_node_open = true;
     333
     334    return true;
     335}
     336
     337bool LinuxFirewireDevice::CloseP2PNode(void)
     338{
     339    if (m_priv->is_p2p_node_open && (m_priv->channel >= 0))
     340    {
     341        VERBOSE(VB_RECORD, LOC + "Closing P2P connection");
     342
     343        if (m_priv->avstream)
     344            CloseAVStream();
     345
     346        iec61883_cmp_disconnect(m_priv->handle, m_node | 0xffc0, 0,
     347                                raw1394_get_local_id(m_priv->handle),
     348                                -1, m_priv->channel, 0);
     349
     350        m_priv->channel = -1;
     351        m_priv->is_p2p_node_open = false;
     352    }
     353
     354    return true;
     355}
     356
     357bool LinuxFirewireDevice::OpenBroadcastNode(void)
     358{
     359    if (m_priv->is_p2p_node_open)
     360        return false;
     361
     362    if (m_priv->is_bcast_node_open)
     363        return true;
     364
     365    m_priv->channel = kBroadcastChannel - m_node;
     366
     367    VERBOSE(VB_RECORD, LOC + "Opening broadcast connection on " +
     368            QString("node %1, channel %2")
     369            .arg(m_node).arg(m_priv->channel));
     370
     371    if (m_priv->avstream)
     372        CloseAVStream();
     373
     374    int err = iec61883_cmp_create_bcast_output(
     375        m_priv->handle, m_node | 0xffc0, 0, m_priv->channel, m_speed);
     376
     377    if (err != 0)
     378    {
     379        VERBOSE(VB_IMPORTANT, LOC_ERR +
     380                "Failed to create Broadcast connection");
     381
     382        m_priv->channel = -1;
     383        return false;
     384    }
     385
     386    m_priv->is_bcast_node_open = true;
     387
     388    return true;
     389}
     390
     391bool LinuxFirewireDevice::CloseBroadcastNode(void)
     392{
     393    if (m_priv->is_bcast_node_open)
     394    {
     395        VERBOSE(VB_RECORD, LOC + "Closing broadcast connection");
     396
     397        m_priv->channel = -1;
     398        m_priv->is_bcast_node_open = false;
     399    }
     400    return true;
     401}
     402
     403bool LinuxFirewireDevice::OpenAVStream(void)
     404{
     405    VERBOSE(VB_RECORD, LOC + "OpenAVStream");
     406
     407    if (!IsNodeOpen() && !OpenNode())
     408        return false;
     409
     410    if (m_priv->avstream)
     411        return true;
     412
     413    VERBOSE(VB_RECORD, LOC + "Opening A/V stream object");
     414
     415    if (!m_priv->handle)
     416    {
     417        VERBOSE(VB_IMPORTANT, LOC +
     418                "Can not open AVStream without IEEE 1394 Port");
     419
     420        return false;
     421    }
     422
     423    m_priv->avstream = iec61883_mpeg2_recv_init(
     424        m_priv->handle, linux_firewire_device_tspacket_handler, this);
     425
     426    if (!m_priv->avstream)
     427    {
     428        VERBOSE(VB_IMPORTANT, LOC + "Unable to open AVStream" + ENO);
     429
     430        return false;
     431    }
     432
     433    iec61883_mpeg2_set_synch(m_priv->avstream, 1 /* sync on close */);
     434
     435    if (m_bufsz)
     436        SetAVStreamBufferSize(m_bufsz);
     437
     438    return true;
     439}
     440
     441bool LinuxFirewireDevice::CloseAVStream(void)
     442{
     443    if (!m_priv->avstream)
     444        return true;
     445
     446    VERBOSE(VB_RECORD, LOC + "Closing A/V stream object");
     447
     448    while (!m_resetting && m_listeners.size())
     449        RemoveListener(m_listeners[m_listeners.size() - 1]);
     450
     451    if (m_priv->is_streaming)
     452        StopStreaming();
     453
     454    iec61883_mpeg2_close(m_priv->avstream);
     455    m_priv->avstream = NULL;
     456
     457    return true;
     458}
     459
     460void *linux_firewire_device_streaming_thunk(void *param)
     461{
     462    LinuxFirewireDevice *mon = (LinuxFirewireDevice*) param;
     463    mon->RunStreaming();
     464    return NULL;
     465}
     466
     467void LinuxFirewireDevice::RunStreaming(void)
     468{
     469    VERBOSE(VB_RECORD, LOC + "RunStreaming -- start");
     470    m_lock.lock();
     471    m_priv->is_streaming_running = true;
     472
     473    uint no_data_cnt = 0;
     474    while (m_priv->is_streaming)
     475    {
     476        no_data_cnt = (LoopIteration(50)) ? 0 : no_data_cnt + 1;
     477
     478        if (m_priv->is_streaming && (no_data_cnt > 30))
     479        {
     480            no_data_cnt = 0;
     481
     482            iec61883_mpeg2_recv_stop(m_priv->avstream);
     483            raw1394_iso_recv_flush(m_priv->handle);
     484            m_priv->is_streaming = false;
     485            ResetBus();
     486            iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel);
     487            m_priv->is_streaming = true;
     488        }
     489    }
     490
     491    m_priv->is_streaming_running = false;
     492    m_lock.unlock();
     493    VERBOSE(VB_RECORD, LOC + "RunStreaming -- end");
     494}
     495
     496bool LinuxFirewireDevice::StartStreaming(void)
     497{
     498    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming");
     499    QMutexLocker locker(&m_priv->start_stop_streaming_lock);
     500    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- locked");
     501
     502    if (m_priv->is_streaming)
     503        return m_priv->is_streaming;
     504
     505    assert(!m_priv->is_streaming_running);
     506
     507    if (!IsAVStreamOpen() && !OpenAVStream())
     508        return false;
     509
     510    if (m_priv->channel < 0)
     511    {
     512        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming, no channel");
     513        return false;
     514    }
     515
     516    VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- really");
     517
     518    if (iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel) == 0)
     519    {
     520        m_priv->is_streaming = true;
     521
     522        pthread_create(&m_priv->streaming_thread, NULL,
     523                       linux_firewire_device_streaming_thunk, this);
     524
     525        m_lock.unlock();
     526        while (!m_priv->is_streaming_running)
     527            usleep(50);
     528        m_lock.lock();
     529    }
     530    else
     531    {
     532        VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming " + ENO);
     533    }
     534
     535    return m_priv->is_streaming;
     536}
     537
     538bool LinuxFirewireDevice::StopStreaming(void)
     539{
     540    VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming");
     541    QMutexLocker locker(&m_priv->start_stop_streaming_lock);
     542    VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- locked");
     543
     544    if (m_priv->is_streaming)
     545    {
     546        VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really");
     547
     548        m_priv->is_streaming = false;
     549
     550        VERBOSE(VB_RECORD, LOC + "Waiting for A/V streaming to stop");
     551        while (m_priv->is_streaming_running)
     552        {
     553            m_lock.unlock();
     554            usleep(50);
     555            m_lock.lock();
     556        }
     557
     558        VERBOSE(VB_RECORD, LOC + "Joining A/V streaming thread");
     559        pthread_join(m_priv->streaming_thread, NULL);
     560
     561        iec61883_mpeg2_recv_stop(m_priv->avstream);
     562
     563        raw1394_iso_recv_flush(m_priv->handle);
     564    }
     565
     566    VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming");
     567
     568    return true;
     569}
     570
     571bool LinuxFirewireDevice::StopStreamingLater(void)
     572{
     573    // TODO
     574    return true;
     575}
     576
     577bool LinuxFirewireDevice::SetAVStreamBufferSize(uint size_in_bytes)
     578{
     579    if (!m_priv->avstream)
     580        return false;
     581
     582    // Set buffered packets size
     583    uint   buffer_size      = max(size_in_bytes, 50 * TSPacket::SIZE);
     584    size_t buffered_packets = min(buffer_size / 4, kMaxBufferedPackets);
     585
     586    iec61883_mpeg2_set_buffers(m_priv->avstream, buffered_packets);
     587
     588    VERBOSE(VB_IMPORTANT, LOC +
     589            QString("Buffered packets %1 (%2 KB)")
     590            .arg(buffered_packets).arg(buffered_packets * 4));
     591
     592    return true;
     593}
     594
     595bool LinuxFirewireDevice::SetAVStreamSpeed(uint speed)
     596{
     597    if (!m_priv->avstream)
     598        return false;
     599
     600    uint curspeed = iec61883_mpeg2_get_speed(m_priv->avstream);
     601
     602    if (curspeed == speed)
     603    {
     604        m_speed = speed;
     605        return true;
     606    }
     607
     608    VERBOSE(VB_RECORD, LOC +
     609            QString("Changing Speed %1 -> %2")
     610            .arg(speed_to_string(curspeed))
     611            .arg(speed_to_string(m_speed)));
     612
     613    iec61883_mpeg2_set_speed(m_priv->avstream, speed);
     614
     615    if (speed == (uint)iec61883_mpeg2_get_speed(m_priv->avstream))
     616    {
     617        m_speed = speed;
     618        return true;
     619    }
     620
     621    VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set firewire speed.");
     622
     623    return false;
     624}
     625
     626bool LinuxFirewireDevice::IsNodeOpen(void) const
     627{
     628    return m_priv->is_p2p_node_open || m_priv->is_bcast_node_open;
     629}
     630
     631bool LinuxFirewireDevice::IsAVStreamOpen(void) const
     632{
     633    return m_priv->avstream;
     634}
     635
     636bool LinuxFirewireDevice::ResetBus(void)
     637{
     638    if (m_priv->is_streaming)
     639    {
     640        VERBOSE(VB_IMPORTANT, LOC_ERR +
     641                "ResetBus() can not be called while streaming");
     642    }
     643
     644    m_resetting = true;
     645    VERBOSE(VB_IMPORTANT, LOC + "ResetBus() -- begin");
     646
     647    bool open_node     = IsNodeOpen();
     648    bool open_avstream = IsAVStreamOpen();
     649
     650    CloseAVStream();
     651    CloseNode();
     652
     653    bool ok = (raw1394_reset_bus_new(m_priv->handle, RAW1394_LONG_RESET) == 0);
     654    if (!ok)
     655        VERBOSE(VB_IMPORTANT, LOC_ERR + "Bus Reset failed" + ENO);
     656
     657    if (open_node)
     658        ok &= OpenNode();
     659
     660    if (open_avstream)
     661        ok &= OpenAVStream();
     662
     663    VERBOSE(VB_IMPORTANT, LOC + "ResetBus() -- end");
     664    m_resetting = false;
     665
     666    return ok;
     667}
     668
     669bool LinuxFirewireDevice::LoopIteration(uint timeout_in_msec)
     670{
     671    if (m_resetting)
     672        return true;
     673
     674    int fwfd = raw1394_get_fd(m_priv->handle);
     675    if (fwfd < 0)
     676        return false;
     677
     678    struct timeval tv;
     679    fd_set rfds;
     680
     681    FD_ZERO(&rfds);
     682    FD_SET(fwfd, &rfds);
     683
     684    tv.tv_sec  = timeout_in_msec / 1000;
     685    tv.tv_usec = (timeout_in_msec % 1000) * 1000;
     686
     687    m_lock.unlock();
     688    if (select(fwfd + 1, &rfds, NULL, NULL, &tv) <= 0)
     689    {
     690        m_lock.lock();
     691        VERBOSE(VB_IMPORTANT, LOC + QString("No Input in %1 msec...")
     692                .arg(timeout_in_msec));
     693
     694        return false;
     695    }
     696    m_lock.lock();
     697
     698    int ret = raw1394_loop_iterate(m_priv->handle);
     699    if (ret)
     700    {
     701        VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " +
     702                QString("returned %1").arg(ret));
     703
     704        return false;
     705    }
     706
     707    return true;
     708}
     709
     710void LinuxFirewireDevice::PrintDropped(uint dropped_packets)
     711{
     712    if (dropped_packets == 1)
     713    {
     714        VERBOSE(VB_RECORD, LOC_ERR + "Dropped a TS packet");
     715    }
     716    else if (dropped_packets > 1)
     717    {
     718        VERBOSE(VB_RECORD, LOC_ERR +
     719                QString("Dropped %1 TS packets").arg(dropped_packets));
     720    }
     721}
     722
     723vector<AVCInfo> LinuxFirewireDevice::GetSTBList(void)
     724{
     725    vector<AVCInfo> list;
     726
     727    raw1394handle_t handle = raw1394_new_handle();
     728    if (!handle)
     729    {
     730        VERBOSE(VB_IMPORTANT, "Couldn't get handle" + ENO);
     731        return list;
     732    }
     733
     734    struct raw1394_portinfo port_info[16];
     735    int numcards = raw1394_get_port_info(handle, port_info, 16);
     736    if (numcards < 1)
     737    {
     738        raw1394_destroy_handle(handle);
     739        return list;
     740    }
     741
     742    for (int port = 0; port < numcards; port++)
     743    {
     744        if (raw1394_set_port(handle, port) < 0)
     745        {
     746            VERBOSE(VB_IMPORTANT, "Couldn't set port to " << port);
     747            continue;
     748        }
     749
     750        for (int node = 0; node < raw1394_get_nodecount(handle); node++)
     751        {
     752            AVCInfo info;
     753
     754            info.guid = get_guid(handle, 0xffc0 | node);
     755
     756            rom1394_directory dir;
     757            if (rom1394_get_directory(handle, node, &dir) < 0)
     758            {
     759                continue;
     760            }
     761            info.port     = port;
     762            info.node     = node;
     763            info.vendorid = dir.vendor_id;
     764            info.modelid  = dir.model_id;
     765            info.specid   = dir.unit_spec_id;
     766            info.firmware_revision = dir.unit_sw_version;
     767            info.product_name = QString("%1").arg(dir.label);
     768
     769            uint8_t unit_table[32];
     770           
     771            if (avc1394_subunit_info(handle, node, (uint32_t*)unit_table) < 0)
     772                memset(unit_table, 0xff, sizeof(unit_table));
     773
     774            if (IsSubunitType(unit_table, kAVCSubunitTypeTuner) &&
     775                IsSubunitType(unit_table, kAVCSubunitTypePanel))
     776            {
     777                list.push_back(info);
     778            }
     779        }
     780
     781        raw1394_destroy_handle(handle);
     782
     783        handle = raw1394_new_handle();
     784        if (!handle)
     785        {
     786            VERBOSE(VB_IMPORTANT, "Couldn't get handle "
     787                    "(after setting port "<<port<<")" + ENO);
     788            handle = NULL;
     789            break;
     790        }
     791
     792        numcards = raw1394_get_port_info(handle, port_info, 16);
     793    }
     794
     795    if (handle)
     796        raw1394_destroy_handle(handle);
     797
     798    return list;
     799}
     800
     801int linux_firewire_device_tspacket_handler(
     802    unsigned char *tspacket, int len, uint dropped, void *callback_data)
     803{
     804    LinuxFirewireDevice *fw = (LinuxFirewireDevice*) callback_data;
     805    if (!fw)
     806        return 0;
     807
     808    if (dropped)
     809        fw->PrintDropped(dropped);
     810
     811    if (len > 0)
     812        fw->BroadcastToListeners(tspacket, len);
     813
     814    return 1;
     815}
     816
     817static QString speed_to_string(uint speed)
     818{
     819    if (speed > RAW1394_ISO_SPEED_400)
     820        return QString("Invalid Speed (%1)").arg(speed);
     821
     822    static const uint speeds[] = { 100, 200, 400, };
     823    return QString("%1Mbps").arg(speeds[speed]);
     824}
     825
     826// get_guid copied from plugreport, Copyright 2002-2004 Dan Dennedy GPL v2+
     827#define PLUGREPORT_GUID_HI 0x0C
     828#define PLUGREPORT_GUID_LO 0x10
     829static uint64_t get_guid(raw1394handle_t handle, nodeid_t node)
     830{
     831    uint32_t quadlet;
     832    uint64_t offset;
     833    uint64_t guid = 0;
     834
     835    offset = CSR_REGISTER_BASE + CSR_CONFIG_ROM + PLUGREPORT_GUID_HI;
     836    raw1394_read(handle, node, offset, sizeof(uint32_t), &quadlet);
     837    quadlet = htonl(quadlet);
     838    guid = quadlet;
     839    guid <<= 32;
     840    offset = CSR_REGISTER_BASE + CSR_CONFIG_ROM + PLUGREPORT_GUID_LO;
     841    raw1394_read(handle, node, offset, sizeof(uint32_t), &quadlet);
     842    quadlet = htonl(quadlet);
     843    guid += quadlet;
     844
     845    return guid;
     846}
  • programs/mythbackend/backendutil.cpp

     
    22#ifdef CONFIG_DARWIN
    33#include <sys/param.h>
    44#include <sys/mount.h>
     5unsigned long long int abs(long long int v)
     6    { return (unsigned long long int) ((v < 0) ? -v : v); }
    57#elif __linux__
    68#include <sys/vfs.h>
    79#endif