11 #include <sys/select.h>
16 #include <libraw1394/raw1394.h>
17 #include <libraw1394/csr.h>
18 #include <libiec61883/iec61883.h>
19 #include <libavc1394/avc1394.h>
20 #include <libavc1394/rom1394.h>
22 #include <netinet/in.h>
41 #define LOC QString("LFireDev(%1): ").arg(guid_to_string(m_guid))
55 for (
const auto & device : std::as_const(
m_devices))
115 unsigned char *tspacket,
int len,
uint dropped,
void *callback_data);
117 static bool has_data(
int fd, std::chrono::milliseconds msec);
120 raw1394handle_t handle,
uint generation);
123 uint64_t guid,
uint subunitid,
124 uint speed,
bool use_p2p,
uint av_buffer_size_in_bytes) :
126 m_bufsz(av_buffer_size_in_bytes),
127 m_useP2P(use_p2p), m_priv(new
LFDPriv())
141 LOG(VB_GENERAL, LOG_ERR,
LOC +
"ctor called with open port");
155 const QString loc =
LOC + QString(
"SignalReset(%1->%2)")
158 LOG(VB_GENERAL, LOG_INFO, loc);
161 raw1394_update_generation(
GetInfoPtr()->m_fwHandle, generation);
165 LOG(VB_GENERAL, LOG_INFO, loc +
": Updating device list -- begin");
167 LOG(VB_GENERAL, LOG_INFO, loc +
": Updating device list -- end");
175 const QString loc =
LOC +
"HandleBusReset";
182 LOG(VB_GENERAL, LOG_INFO, loc +
": Reconnecting P2P connection");
184 nodeid_t input = raw1394_get_local_id(
GetInfoPtr()->m_fwHandle);
186 int fwchan = iec61883_cmp_reconnect(
194 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bus Reset: Failed to reconnect");
198 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"FWChan changed %1->%2")
203 LOG(VB_GENERAL, LOG_INFO,
204 loc + QString(
": Reconnected fwchan: %1\n\t\t\toutput: 0x%2 "
206 .arg(fwchan).arg(
output,0,16).arg(input,0,16));
213 LOG(VB_RECORD, LOG_INFO, loc +
": Restarting broadcast connection on " +
214 QString(
"node %1, channel %2")
217 int err = iec61883_cmp_create_bcast_output(
224 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bus Reset : Failed to reconnect");
231 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Port Handler Thread");
233 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Port Handler Thread -- locked");
235 LOG(VB_RECORD, LOG_INFO,
LOC +
"OpenPort()");
237 QMutexLocker mlocker(&
m_lock);
239 LOG(VB_RECORD, LOG_INFO,
LOC +
"OpenPort() -- got lock");
256 raw1394_set_bus_reset_handler(
265 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Not an STB"));
275 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting port handler thread");
282 LOG(VB_RECORD, LOG_INFO,
LOC +
"Port handler thread started");
291 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopping Port Handler Thread");
293 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopping Port Handler Thread -- locked");
295 QMutexLocker mlocker(&
m_lock);
297 LOG(VB_RECORD, LOG_INFO,
LOC +
"ClosePort()");
315 LOG(VB_RECORD, LOG_INFO,
316 LOC +
"Waiting for port handler thread to stop");
327 LOG(VB_RECORD, LOG_INFO,
LOC +
"Joined port handler thread");
340 QMutexLocker locker(&
m_lock);
354 QMutexLocker locker(&
m_lock);
367 const std::vector<uint8_t> &cmd,
368 std::vector<uint8_t> &result,
376 QMutexLocker locker(&
m_lock);
415 LOG(VB_RECORD, LOG_INFO,
LOC +
"Opening P2P connection");
421 nodeid_t input = raw1394_get_local_id(
GetInfoPtr()->m_fwHandle);
429 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create P2P connection");
445 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closing P2P connection");
451 nodeid_t input = raw1394_get_local_id(
GetInfoPtr()->m_fwHandle);
453 iec61883_cmp_disconnect(
GetInfoPtr()->m_fwHandle,
483 LOG(VB_RECORD, LOG_INFO,
LOC +
"Opening broadcast connection on " +
484 QString(
"node %1, channel %2")
487 int err = iec61883_cmp_create_bcast_output(
494 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create Broadcast connection");
512 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closing broadcast connection");
524 LOG(VB_RECORD, LOG_INFO,
LOC +
"OpenAVStream");
528 LOG(VB_GENERAL, LOG_ERR,
LOC +
529 "Cannot open AVStream without open IEEE 1394 port");
540 LOG(VB_RECORD, LOG_INFO,
LOC +
"Opening A/V stream object");
547 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unable to open AVStream" +
ENO);
565 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closing A/V stream object");
581 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunPortHandler -- start");
583 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunPortHandler -- got first lock");
588 std::this_thread::sleep_for(2500us);
596 bool handle_reset = reset_timer_on &&
612 int fwfd = raw1394_get_fd(
GetInfoPtr()->m_fwHandle);
635 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"No Input in %1 msec...")
647 int ret = raw1394_loop_iterate(
GetInfoPtr()->m_fwHandle);
650 LOG(VB_GENERAL, LOG_ERR,
LOC +
"raw1394_loop_iterate" +
ENO);
658 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunPortHandler -- end");
671 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Starting A/V streaming, no channel");
675 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting A/V streaming -- really");
683 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Starting A/V streaming " +
ENO);
686 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting A/V streaming -- done");
695 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopping A/V streaming -- really");
701 raw1394_iso_recv_flush(
GetInfoPtr()->m_fwHandle);
704 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopped A/V streaming");
720 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Buffered packets %1 (%2 KB)")
721 .arg(buffered_packets).arg(buffered_packets * 4));
733 if (curspeed == speed)
739 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Changing Speed %1 -> %2")
751 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to set firewire speed.");
768 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ResetBus() -- begin");
772 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Bus Reset disabled" +
ENO);
773 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ResetBus() -- end");
777 bool ok = (raw1394_reset_bus_new(
GetInfoPtr()->m_fwHandle,
778 RAW1394_LONG_RESET) == 0);
780 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bus Reset failed" +
ENO);
782 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ResetBus() -- end");
789 if (dropped_packets == 1)
791 LOG(VB_RECORD, LOG_ERR,
LOC +
"Dropped a TS packet");
793 else if (dropped_packets > 1)
795 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Dropped %1 TS packets")
796 .arg(dropped_packets));
802 std::vector<AVCInfo> list;
815 LOG(VB_GENERAL, LOG_DEBUG,
"GetSTBListPrivate -- begin");
817 QMutexLocker locker(&
m_lock);
819 LOG(VB_GENERAL, LOG_DEBUG,
"GetSTBListPrivate -- got lock");
822 std::vector<AVCInfo> list;
829 list.push_back(*device);
834 LOG(VB_GENERAL, LOG_DEBUG,
"GetSTBListPrivate -- end");
850 item.
m_handle = raw1394_new_handle();
853 LOG(VB_GENERAL, LOG_ERR, QString(
"LinuxFirewireDevice: ") +
854 "Couldn't get handle" +
ENO);
858 std::array<raw1394_portinfo,16> port_info {};
859 int numcards = raw1394_get_port_info(item.m_handle, port_info.data(),
863 raw1394_destroy_handle(item.m_handle);
867 std::map<uint64_t,bool> guid_online;
868 for (
int port = 0; port < numcards; port++)
870 if (raw1394_set_port(item.m_handle, port) < 0)
872 LOG(VB_GENERAL, LOG_ERR, QString(
"LinuxFirewireDevice: "
873 "Couldn't set port to %1").arg(port));
877 for (
int node = 0; node < raw1394_get_nodecount(item.m_handle); node++)
881 guid = rom1394_get_guid(item.m_handle, node);
885 guid_online[guid] =
true;
888 raw1394_destroy_handle(item.m_handle);
890 item.m_handle = raw1394_new_handle();
893 LOG(VB_GENERAL, LOG_ERR, QString(
"LinuxFirewireDevice: ") +
894 "Couldn't get handle " +
895 QString(
"(after setting port %1").arg(port) +
ENO);
896 item.m_handle =
nullptr;
900 numcards = raw1394_get_port_info(item.m_handle, port_info.data(),
906 raw1394_destroy_handle(item.m_handle);
907 item.m_handle =
nullptr;
914 if (!guid_online[it.key()])
929 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Adding 0x%1").arg(guid,0,16));
938 LOG(VB_RECORD, LOG_INFO,
939 LOC + QString(
"Updating 0x%1 port: %2 node: %3")
965 unsigned char *tspacket,
int len,
uint dropped,
void *callback_data)
975 fw->BroadcastToListeners(tspacket, len);
980 static bool has_data(
int fd, std::chrono::milliseconds msec)
986 struct timeval tv {};
987 tv.tv_sec = msec.count() / 1000;
988 tv.tv_usec = (msec.count() % 1000) * 1000;
990 int ready = select(fd + 1, &rfds,
nullptr,
nullptr, &tv);
993 LOG(VB_GENERAL, LOG_ERR,
"LFireDev: Select Error" +
ENO);
1001 return QString(
"Invalid Speed (%1)").arg(speed);
1003 static constexpr std::array<const uint,4> kSpeeds { 100, 200, 400, 800 };
1004 return QString(
"%1Mbps").arg(kSpeeds[speed]);
1008 raw1394handle_t handle,
unsigned int generation)
1015 (*it)->SignalReset(generation);