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>
34 #include <AVCVideoServices/StringLogger.h>
35 #include <AVCVideoServices/AVSShared.h>
36 #include <AVCVideoServices/MPEG2Receiver.h>
43 MPEG2Receiver **ppReceiver,
44 DataPushProc dataPushProcHandler,
45 void *pDataPushProcRefCon = nil,
46 MPEG2ReceiverMessageProc messageProcHandler = nil,
47 void *pMessageProcRefCon = nil,
48 StringLogger *stringLogger = nil,
49 IOFireWireLibNubRef nubInterface = nil,
50 unsigned int cyclesPerSegment =
51 kCyclesPerReceiveSegment,
52 unsigned int numSegments =
54 bool doIRMAllocations =
false);
58 #define LOC QString("DFireDev(%1): ").arg(guid_to_string(m_guid))
60 #define kAnyAvailableIsochChannel 0xFFFFFFFF
65 UInt32 tsPacketCount, UInt32 **ppBuf,
void *callback_data);
70 UInt32 param2,
void *callback_data);
118 uint64_t guid,
uint subunitid,
uint speed) :
128 LOG(VB_GENERAL, LOG_ERR,
LOC +
"dtor called with open port");
145 mach_port_t master_port;
146 int ret = IOMasterPort(bootstrap_port, &master_port);
147 if (kIOReturnSuccess == ret)
155 kCFRunLoopDefaultMode);
157 ret = IOServiceAddMatchingNotification(
159 IOServiceMatching(
"IOFireWireAVCUnit"),
163 if (kIOReturnSuccess == ret)
168 if (kIOReturnSuccess == ret)
171 QMutexLocker locker(&
m_lock);
227 QMutexLocker locker(&
m_lock);
229 LOG(VB_RECORD, LOG_INFO,
LOC +
"OpenPort()");
241 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unable to start firewire thread.");
247 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No IEEE-1394 device with our GUID");
253 LOG(VB_RECORD, LOG_INFO,
LOC +
"Opening AVC Device");
259 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"No STB at guid: 0x%1")
269 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unable to get handle for port");
279 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to query local node");
285 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to query remote node");
297 QMutexLocker locker(&
m_lock);
299 LOG(VB_RECORD, LOG_INFO,
LOC +
"ClosePort()");
311 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closing AVC Device");
329 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Max Speed: %1, Our speed: %2")
335 LOG(VB_GENERAL, LOG_INFO,
LOC +
336 QString(
"STB is %1already streaming on fwchan: %2")
337 .arg(streaming?
"":
"not ").arg(fwchan));
348 AVS::kCyclesPerReceiveSegment,
349 AVS::kNumReceiveSegments,
352 if (kIOReturnSuccess != ret)
354 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Couldn't create A/V stream object");
368 if ((*fw_handle)->version < 4)
371 io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
375 int ret = (*fw_handle)->ReadQuadlet(
376 fw_handle, dev, &addr, (UInt32*) &val,
false, 0);
377 val = EndianU32_BtoN(val);
379 return (ret == kIOReturnSuccess) ? (int)((val>>30) & 0x3) : -1;
382 uint32_t generation = 0;
384 int ret = (*fw_handle)->GetBusGeneration(fw_handle, (UInt32*)&generation);
385 if (kIOReturnSuccess == ret)
387 ret = (*fw_handle)->GetSpeedBetweenNodes(
391 return (ret == kIOReturnSuccess) ? (int)speed : -1;
397 io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
401 int ret = (*fw_handle)->ReadQuadlet(
402 fw_handle, dev, &addr, (UInt32*) &val,
false, 0);
403 val = EndianU32_BtoN(val);
405 if (ret != kIOReturnSuccess)
408 if (val & (kIOFWPCRBroadcast | kIOFWPCRP2PCount))
411 *fw_channel = (val & kIOFWPCRChannel) >> kIOFWPCRChannelPhase;
426 LOG(VB_RECORD, LOG_INFO,
LOC +
"Destroying A/V stream object");
440 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ResetBus() -- begin");
446 bool ok = (*fw_handle)->BusReset(fw_handle) == kIOReturnSuccess;
449 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bus Reset failed" +
ENO);
451 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ResetBus() -- end");
461 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting A/V streaming");
465 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Starting A/V streaming: FAILED");
475 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Starting A/V streaming: %1")
486 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopping A/V streaming");
493 LOG(VB_RECORD, LOG_ERR,
LOC +
"Failed to stop A/V streaming");
497 LOG(VB_RECORD, LOG_INFO,
LOC +
"Stopped A/V streaming");
502 std::vector<uint8_t> &result,
510 QMutexLocker locker(&
m_lock);
520 QMutexLocker locker(&
m_lock);
530 QMutexLocker locker(&
m_lock);
542 const unsigned char *data,
uint dataSize)
544 QMutexLocker locker(&
m_lock);
559 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"No Input in %1 msecs")
571 uint32_t msg, uint32_t param1, uint32_t param2)
575 if (AVS::kMpeg2ReceiverAllocateIsochPort == msg)
578 int fw_channel = param2;
581 plug_number, fw_channel, speed,
true,
false);
583 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"AllocateIsochPort(%1,%2) %3")
584 .arg(fw_channel).arg(speed).arg(((ok)?
"ok":
"error")));
586 else if (AVS::kMpeg2ReceiverReleaseIsochPort == msg)
590 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"ReleaseIsochPort %1")
591 .arg((kIOReturnSuccess == ret)?
"ok":
"error"));
593 else if (AVS::kMpeg2ReceiverDCLOverrun == msg)
595 LOG(VB_GENERAL, LOG_ERR,
LOC +
"DCL Overrun");
597 else if (AVS::kMpeg2ReceiverReceivedBadPacket == msg)
599 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Received Bad Packet");
603 LOG(VB_GENERAL, LOG_INFO,
LOC +
604 QString(
"Streaming Message: %1").arg(msg));
610 std::vector<AVCInfo> list;
632 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"GetSTBListPrivate -- begin");
634 QMutexLocker locker(&
m_lock);
636 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"GetSTBListPrivate -- got lock");
639 std::vector<AVCInfo> list;
646 list.push_back(*dev);
651 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"GetSTBListPrivate -- end");
658 QMutexLocker locker(&
m_lock);
666 LOG(VB_GENERAL, LOG_INFO,
LOC +
667 QString(
"Adding 0x%1").arg(guid, 0, 16));
675 io_object_t &item = *((io_object_t*) pitem);
676 LOG(VB_GENERAL, LOG_INFO,
LOC +
677 QString(
"Updating 0x%1").arg(guid, 0, 16));
697 uint plug_number,
int new_fw_chan,
int new_speed,
698 bool add_plug,
bool remove_plug)
707 io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
710 uint low_addr = kPCRBaseAddress + 4 + (plug_number << 2);
712 uint32_t old_plug_val;
713 if (kIOReturnSuccess != (*fw_handle)->ReadQuadlet(
714 fw_handle, dev, &addr, (UInt32*) &old_plug_val,
false, 0))
718 old_plug_val = EndianU32_BtoN(old_plug_val);
720 int old_plug_cnt = (old_plug_val >> 24) & 0x3f;
721 int old_fw_chan = (old_plug_val >> 16) & 0x3f;
722 int old_speed = (old_plug_val >> 14) & 0x03;
724 int new_plug_cnt = (int) old_plug_cnt;
725 new_plug_cnt += ((add_plug) ? 1 : 0) - ((remove_plug) ? 1 : 0);
726 if ((new_plug_cnt > 0x3f) || (new_plug_cnt < 0))
728 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Invalid Plug Count %1")
733 new_fw_chan = (new_fw_chan >= 0) ? new_fw_chan : old_fw_chan;
734 if (old_plug_cnt && (new_fw_chan != old_fw_chan))
736 LOG(VB_GENERAL, LOG_WARNING,
LOC +
737 "Ignoring FWChan change request, plug already open");
739 new_fw_chan = old_fw_chan;
742 new_speed = (new_speed >= 0) ? new_speed : old_speed;
743 if (old_plug_cnt && (new_speed != old_speed))
745 LOG(VB_GENERAL, LOG_WARNING,
LOC +
746 "Ignoring speed change request, plug already open");
748 new_speed = old_speed;
751 uint32_t new_plug_val = old_plug_val;
753 new_plug_val &= ~(0x3f<<24);
754 new_plug_val &= (remove_plug) ? ~kIOFWPCRBroadcast : ~0
x0;
755 new_plug_val |= (new_plug_cnt & 0x3f) << 24;
757 new_plug_val &= ~(0x3f<<16);
758 new_plug_val |= (new_fw_chan & 0x3F) << 16;
760 new_plug_val &= ~(0x03<<14);
761 new_plug_val |= (new_speed & 0x03) << 14;
763 old_plug_val = EndianU32_NtoB(old_plug_val);
764 new_plug_val = EndianU32_NtoB(new_plug_val);
766 return (kIOReturnSuccess == (*fw_handle)->CompareSwap(
767 fw_handle, dev, &addr, old_plug_val, new_plug_val,
false, 0));
786 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Reset: Failed to reconnect");
788 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset: Reconnected succesfully");
792 uint plug_number,
int fw_chan,
int speed,
793 bool add_plug,
bool remove_plug,
uint retry_cnt)
800 for (
uint i = 0; (i < retry_cnt) && !ok; i++)
803 plug_number, fw_chan, speed, add_plug, remove_plug);
813 QString loc =
LOC +
"HandleDeviceChange: ";
815 if (kIOMessageServiceIsTerminated == messageType)
817 LOG(VB_RECORD, LOG_INFO, loc +
"Disconnect");
822 if (kIOMessageServiceIsAttemptingOpen == messageType)
824 LOG(VB_RECORD, LOG_INFO, loc +
"Attempting open");
828 if (kIOMessageServiceWasClosed == messageType)
830 LOG(VB_RECORD, LOG_INFO, loc +
"Device Closed");
835 if (kIOMessageServiceIsSuspended == messageType)
837 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsSuspended");
842 if (kIOMessageServiceIsResumed == messageType)
848 if (kIOMessageServiceIsTerminated == messageType)
849 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsTerminated");
850 else if (kIOMessageServiceIsRequestingClose == messageType)
851 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsRequestingClose");
852 else if (kIOMessageServiceIsAttemptingOpen == messageType)
853 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceIsAttemptingOpen");
854 else if (kIOMessageServiceWasClosed == messageType)
855 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceWasClosed");
856 else if (kIOMessageServiceBusyStateChange == messageType)
857 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageServiceBusyStateChange");
858 else if (kIOMessageCanDevicePowerOff == messageType)
859 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageCanDevicePowerOff");
860 else if (kIOMessageDeviceWillPowerOff == messageType)
861 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageDeviceWillPowerOff");
862 else if (kIOMessageDeviceWillNotPowerOff == messageType)
863 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageDeviceWillNotPowerOff");
864 else if (kIOMessageDeviceHasPoweredOn == messageType)
865 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageDeviceHasPoweredOn");
866 else if (kIOMessageCanSystemPowerOff == messageType)
867 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageCanSystemPowerOff");
868 else if (kIOMessageSystemWillPowerOff == messageType)
869 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillPowerOff");
870 else if (kIOMessageSystemWillNotPowerOff == messageType)
871 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillNotPowerOff");
872 else if (kIOMessageCanSystemSleep == messageType)
873 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageCanSystemSleep");
874 else if (kIOMessageSystemWillSleep == messageType)
875 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillSleep");
876 else if (kIOMessageSystemWillNotSleep == messageType)
877 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillNotSleep");
878 else if (kIOMessageSystemHasPoweredOn == messageType)
879 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemHasPoweredOn");
880 else if (kIOMessageSystemWillRestart == messageType)
881 LOG(VB_RECORD, LOG_INFO, loc +
"kIOMessageSystemWillRestart");
884 LOG(VB_RECORD, LOG_ERR, loc + QString(
"unknown message 0x%1")
885 .arg(messageType, 0, 16));
908 ProcessNoDataMessage();
910 return kIOReturnSuccess;
914 UInt32 param2,
void *callback_data)
917 ProcessStreamingMessage(msg, param1, param2);
925 return kIOReturnBadArgument;
927 for (uint32_t i = 0; i < tsPacketCount; ++i)
930 return kIOReturnSuccess;
934 UInt32 tsPacketCount, UInt32 **ppBuf,
void *callback_data)
937 tsPacketCount, (uint32_t**)ppBuf, callback_data);
945 while ((it = IOIteratorNext(deviter)))
949 CFMutableDictionaryRef props;
950 int ret = IORegistryEntryCreateCFProperties(
951 it, &props, kCFAllocatorDefault, kNilOptions);
953 if (kIOReturnSuccess == ret)
955 auto GUIDDesc = (CFNumberRef)
956 CFDictionaryGetValue(props, CFSTR(
"GUID"));
957 CFNumberGetValue(GUIDDesc, kCFNumberSInt64Type, &guid);
966 LOG(VB_RECORD, LOG_INFO, QString(
"MPEG2Receiver: %1").arg(msg));