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 #include <CoreServices/CoreServices.h>
35 #include <AVCVideoServices/StringLogger.h>
36 #include <AVCVideoServices/AVSShared.h>
37 #include <AVCVideoServices/MPEG2Receiver.h>
44 MPEG2Receiver **ppReceiver,
45 DataPushProc dataPushProcHandler,
46 void *pDataPushProcRefCon = nil,
47 MPEG2ReceiverMessageProc messageProcHandler = nil,
48 void *pMessageProcRefCon = nil,
49 StringLogger *stringLogger = nil,
50 IOFireWireLibNubRef nubInterface = nil,
51 unsigned int cyclesPerSegment =
52 kCyclesPerReceiveSegment,
53 unsigned int numSegments =
55 bool doIRMAllocations =
false);
59 #define LOC QString("DFireDev(%1): ").arg(guid_to_string(m_guid))
61 #define kAnyAvailableIsochChannel 0xFFFFFFFF
62 #define kNoDataTimeout 300
63 #define kResetTimeout 1500
66 UInt32 tsPacketCount, UInt32 **ppBuf,
void *callback_data);
71 UInt32 param2,
void *callback_data);
78 controller_thread_cf_ref(NULL), controller_thread_running(
false),
79 notify_port(NULL), notify_source(NULL), deviter(NULL),
80 actual_fwchan(-1), is_streaming(
false), avstream(NULL),
logger(NULL),
81 no_data_cnt(0), no_data_timer_set(
false)
88 avcinfo_list_t::iterator it = devices.begin();
89 for (; it != devices.end(); ++it)
120 uint64_t guid,
uint subunitid,
uint speed) :
122 m_local_node(-1), m_remote_node(-1), m_priv(new
DFDPriv())
132 LOG(VB_GENERAL, LOG_ERR,
LOC +
"dtor called with open port");
149 mach_port_t master_port;
150 int ret = IOMasterPort(bootstrap_port, &master_port);
151 if (kIOReturnSuccess == ret)
159 kCFRunLoopDefaultMode);
161 ret = IOServiceAddMatchingNotification(
163 IOServiceMatching(
"IOFireWireAVCUnit"),
167 if (kIOReturnSuccess == ret)
172 if (kIOReturnSuccess == ret)
175 QMutexLocker locker(&
m_lock);
231 QMutexLocker locker(&
m_lock);
233 LOG(VB_RECORD, LOG_INFO,
LOC +
"OpenPort()");
245 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unable to start firewire thread.");
251 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No IEEE-1394 device with our GUID");
257 LOG(VB_RECORD, LOG_INFO,
LOC +
"Opening AVC Device");
258 LOG(VB_RECORD, LOG_INFO,
LOC +
GetInfoPtr()->GetSubunitInfoString());
263 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"No STB at guid: 0x%1")
273 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unable to get handle for port");
283 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to query local node");
289 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to query remote node");
301 QMutexLocker locker(&
m_lock);
303 LOG(VB_RECORD, LOG_INFO,
LOC +
"ClosePort()");
315 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closing AVC Device");
333 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Max Speed: %1, Our speed: %2")
339 LOG(VB_GENERAL, LOG_INFO,
LOC +
340 QString(
"STB is %1already streaming on fwchan: %2")
341 .arg(streaming?
"":
"not ").arg(fwchan));
352 AVS::kCyclesPerReceiveSegment,
353 AVS::kNumReceiveSegments,
356 if (kIOReturnSuccess != ret)
358 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Couldn't create A/V stream object");
372 if ((*fw_handle)->version < 4)
375 io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
379 int ret = (*fw_handle)->ReadQuadlet(
380 fw_handle, dev, &addr, (UInt32*) &val,
false, 0);
381 val = EndianU32_BtoN(val);
383 return (ret == kIOReturnSuccess) ? (
int)((val>>30) & 0x3) : -1;
386 uint32_t generation = 0;
388 int ret = (*fw_handle)->GetBusGeneration(fw_handle, (UInt32*)&generation);
389 if (kIOReturnSuccess == ret)
391 ret = (*fw_handle)->GetSpeedBetweenNodes(
395 return (ret == kIOReturnSuccess) ? (
int)speed : -1;
401 io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
405 int ret = (*fw_handle)->ReadQuadlet(
406 fw_handle, dev, &addr, (UInt32*) &val,
false, 0);
407 val = EndianU32_BtoN(val);
409 if (ret != kIOReturnSuccess)
412 if (val & (kIOFWPCRBroadcast | kIOFWPCRP2PCount))
415 *fw_channel = (val & kIOFWPCRChannel) >> kIOFWPCRChannelPhase;
430 LOG(VB_RECORD, LOG_INFO,
LOC +
"Destroying A/V stream object");
444 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ResetBus() -- begin");
450 bool ok = (*fw_handle)->BusReset(fw_handle) == kIOReturnSuccess;
453 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bus Reset failed" + ENO);
455 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ResetBus() -- end");
465 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting A/V streaming");
469 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Starting A/V streaming: FAILED");
473 m_priv->
avstream->setReceiveIsochChannel(kAnyAvailableIsochChannel);
479 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Starting A/V streaming: %1")
490 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopping A/V streaming");
497 LOG(VB_RECORD, LOG_ERR,
LOC +
"Failed to stop A/V streaming");
501 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopped A/V streaming");
506 vector<uint8_t> &result,
514 QMutexLocker locker(&
m_lock);
524 QMutexLocker locker(&
m_lock);
534 QMutexLocker locker(&
m_lock);
546 const unsigned char *
data,
uint dataSize)
548 QMutexLocker locker(&
m_lock);
556 int short_interval = kNoDataTimeout + (kNoDataTimeout>>1);
563 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"No Input in %1 msecs")
575 uint32_t msg, uint32_t param1, uint32_t param2)
579 if (AVS::kMpeg2ReceiverAllocateIsochPort == msg)
581 int speed = param1, fw_channel = param2;
584 plug_number, fw_channel, speed,
true,
false);
586 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"AllocateIsochPort(%1,%2) %3")
587 .arg(fw_channel).arg(speed).arg(((ok)?
"ok":
"error")));
589 else if (AVS::kMpeg2ReceiverReleaseIsochPort == msg)
593 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"ReleaseIsochPort %1")
594 .arg((kIOReturnSuccess == ret)?
"ok":
"error"));
596 else if (AVS::kMpeg2ReceiverDCLOverrun == msg)
598 LOG(VB_GENERAL, LOG_ERR,
LOC +
"DCL Overrun");
600 else if (AVS::kMpeg2ReceiverReceivedBadPacket == msg)
602 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Received Bad Packet");
606 LOG(VB_GENERAL, LOG_INFO,
LOC +
607 QString(
"Streaming Message: %1").arg(msg));
613 vector<AVCInfo> list;
635 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"GetSTBListPrivate -- begin");
637 QMutexLocker locker(&
m_lock);
639 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"GetSTBListPrivate -- got lock");
642 vector<AVCInfo> list;
650 list.push_back(*(*it));
655 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"GetSTBListPrivate -- end");
662 QMutexLocker locker(&
m_lock);
670 LOG(VB_GENERAL, LOG_INFO,
LOC +
671 QString(
"Adding 0x%1").arg(guid, 0, 16));
677 io_object_t &item = *((io_object_t*) pitem);
680 LOG(VB_GENERAL, LOG_INFO,
LOC +
681 QString(
"Updating 0x%1").arg(guid, 0, 16));
701 uint plug_number,
int new_fw_chan,
int new_speed,
702 bool add_plug,
bool remove_plug)
711 io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
714 uint low_addr = kPCRBaseAddress + 4 + (plug_number << 2);
716 uint32_t old_plug_val;
717 if (kIOReturnSuccess != (*fw_handle)->ReadQuadlet(
718 fw_handle, dev, &addr, (UInt32*) &old_plug_val,
false, 0))
722 old_plug_val = EndianU32_BtoN(old_plug_val);
724 int old_plug_cnt = (old_plug_val >> 24) & 0x3f;
725 int old_fw_chan = (old_plug_val >> 16) & 0x3f;
726 int old_speed = (old_plug_val >> 14) & 0x03;
728 int new_plug_cnt = (
int) old_plug_cnt;
729 new_plug_cnt += ((add_plug) ? 1 : 0) - ((remove_plug) ? 1 : 0);
730 if ((new_plug_cnt > 0x3f) || (new_plug_cnt < 0))
732 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Invalid Plug Count %1")
737 new_fw_chan = (new_fw_chan >= 0) ? new_fw_chan : old_fw_chan;
738 if (old_plug_cnt && (new_fw_chan != old_fw_chan))
740 LOG(VB_GENERAL, LOG_WARNING,
LOC +
741 "Ignoring FWChan change request, plug already open");
743 new_fw_chan = old_fw_chan;
746 new_speed = (new_speed >= 0) ? new_speed : old_speed;
747 if (old_plug_cnt && (new_speed != old_speed))
749 LOG(VB_GENERAL, LOG_WARNING,
LOC +
750 "Ignoring speed change request, plug already open");
752 new_speed = old_speed;
755 uint32_t new_plug_val = old_plug_val;
757 new_plug_val &= ~(0x3f<<24);
758 new_plug_val &= (remove_plug) ? ~kIOFWPCRBroadcast : ~0
x0;
759 new_plug_val |= (new_plug_cnt & 0x3f) << 24;
761 new_plug_val &= ~(0x3f<<16);
762 new_plug_val |= (new_fw_chan & 0x3F) << 16;
764 new_plug_val &= ~(0x03<<14);
765 new_plug_val |= (new_speed & 0x03) << 14;
767 old_plug_val = EndianU32_NtoB(old_plug_val);
768 new_plug_val = EndianU32_NtoB(new_plug_val);
770 return (kIOReturnSuccess == (*fw_handle)->CompareSwap(
771 fw_handle, dev, &addr, old_plug_val, new_plug_val,
false, 0));
790 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Reset: Failed to reconnect");
792 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset: Reconnected succesfully");
796 uint plug_number,
int fw_chan,
int speed,
797 bool add_plug,
bool remove_plug,
uint retry_cnt)
804 for (
uint i = 0; (i < retry_cnt) && !ok; i++)
807 plug_number, fw_chan, speed, add_plug, remove_plug);
817 QString loc =
LOC +
"HandleDeviceChange: ";
819 if (kIOMessageServiceIsTerminated == messageType)
821 LOG(VB_RECORD, LOG_INFO, loc +
"Disconnect");
826 if (kIOMessageServiceIsAttemptingOpen == messageType)
828 LOG(VB_RECORD, LOG_INFO, loc +
"Attempting open");
832 if (kIOMessageServiceWasClosed == messageType)
834 LOG(VB_RECORD, LOG_INFO, loc +
"Device Closed");
839 if (kIOMessageServiceIsSuspended == messageType)
841 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsSuspended");
846 if (kIOMessageServiceIsResumed == messageType)
852 if (kIOMessageServiceIsTerminated == messageType)
853 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsTerminated");
854 else if (kIOMessageServiceIsRequestingClose == messageType)
855 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsRequestingClose");
856 else if (kIOMessageServiceIsAttemptingOpen == messageType)
857 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsAttemptingOpen");
858 else if (kIOMessageServiceWasClosed == messageType)
859 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceWasClosed");
860 else if (kIOMessageServiceBusyStateChange == messageType)
861 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceBusyStateChange");
862 else if (kIOMessageCanDevicePowerOff == messageType)
863 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageCanDevicePowerOff");
864 else if (kIOMessageDeviceWillPowerOff == messageType)
865 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageDeviceWillPowerOff");
866 else if (kIOMessageDeviceWillNotPowerOff == messageType)
867 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageDeviceWillNotPowerOff");
868 else if (kIOMessageDeviceHasPoweredOn == messageType)
869 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageDeviceHasPoweredOn");
870 else if (kIOMessageCanSystemPowerOff == messageType)
871 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageCanSystemPowerOff");
872 else if (kIOMessageSystemWillPowerOff == messageType)
873 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillPowerOff");
874 else if (kIOMessageSystemWillNotPowerOff == messageType)
875 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillNotPowerOff");
876 else if (kIOMessageCanSystemSleep == messageType)
877 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageCanSystemSleep");
878 else if (kIOMessageSystemWillSleep == messageType)
879 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillSleep");
880 else if (kIOMessageSystemWillNotSleep == messageType)
881 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillNotSleep");
882 else if (kIOMessageSystemHasPoweredOn == messageType)
883 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemHasPoweredOn");
884 else if (kIOMessageSystemWillRestart == messageType)
885 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillRestart");
888 LOG(VB_RECORD, LOG_ERR, loc + QString(
"unknown message 0x%1")
889 .arg(messageType, 0, 16));
912 ProcessNoDataMessage();
914 return kIOReturnSuccess;
918 UInt32 param2,
void *callback_data)
921 ProcessStreamingMessage(msg, param1, param2);
931 return kIOReturnBadArgument;
933 for (uint32_t i = 0; i < tsPacketCount; ++i)
936 return kIOReturnSuccess;
940 UInt32 tsPacketCount, UInt32 **ppBuf,
void *callback_data)
943 tsPacketCount, (uint32_t**)ppBuf, callback_data);
950 io_object_t it = NULL;
951 while ((it = IOIteratorNext(deviter)))
955 CFMutableDictionaryRef props;
956 int ret = IORegistryEntryCreateCFProperties(
957 it, &props, kCFAllocatorDefault, kNilOptions);
959 if (kIOReturnSuccess == ret)
961 CFNumberRef GUIDDesc = (CFNumberRef)
962 CFDictionaryGetValue(props, CFSTR(
"GUID"));
963 CFNumberGetValue(GUIDDesc, kCFNumberSInt64Type, &guid);
972 LOG(VB_RECORD, LOG_INFO, QString(
"MPEG2Receiver: %1").arg(msg));