MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
darwinfirewiredevice.cpp
Go to the documentation of this file.
1 
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 #include <CoreServices/CoreServices.h> // for EndianU32_BtoN() etc.
21 
22 // Std C++ headers
23 #include <algorithm>
24 #include <vector>
25 using namespace std;
26 
27 // MythTV headers
28 #include "darwinfirewiredevice.h"
29 #include "darwinavcinfo.h"
30 #include "mythlogging.h"
31 #include "mthread.h"
32 #include "mythtimer.h"
33 
34 // Apple Firewire example headers
35 #include <AVCVideoServices/StringLogger.h>
36 #include <AVCVideoServices/AVSShared.h>
37 #include <AVCVideoServices/MPEG2Receiver.h>
38 
39 // header not used because it also requires MPEG2Transmitter.h
40 //#include <AVCVideoServices/FireWireMPEG.h>
41 namespace AVS
42 {
43  IOReturn CreateMPEG2Receiver(
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 =
54  kNumReceiveSegments,
55  bool doIRMAllocations = false);
56  IOReturn DestroyMPEG2Receiver(MPEG2Receiver *pReceiver);
57 }
58 
59 #define LOC QString("DFireDev(%1): ").arg(guid_to_string(m_guid))
60 
61 #define kAnyAvailableIsochChannel 0xFFFFFFFF
62 #define kNoDataTimeout 300 /* msec */
63 #define kResetTimeout 1500 /* msec */
64 
65 static IOReturn dfd_tspacket_handler_thunk(
66  UInt32 tsPacketCount, UInt32 **ppBuf, void *callback_data);
67 static void dfd_update_device_list(void *dfd, io_iterator_t iterator);
68 static void dfd_streaming_log_message(char *pString);
69 void *dfd_controller_thunk(void *param);
70 void dfd_stream_msg(UInt32 msg, UInt32 param1,
71  UInt32 param2, void *callback_data);
72 int dfd_no_data_notification(void *callback_data);
73 
74 class DFDPriv
75 {
76  public:
77  DFDPriv() :
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)
82  {
83  logger = new AVS::StringLogger(dfd_streaming_log_message);
84  }
85 
87  {
88  avcinfo_list_t::iterator it = devices.begin();
89  for (; it != devices.end(); ++it)
90  delete (*it);
91  devices.clear();
92 
93  if (logger)
94  {
95  delete logger;
96  logger = NULL;
97  }
98  }
99 
100  pthread_t controller_thread;
103 
104  IONotificationPortRef notify_port;
105  CFRunLoopSourceRef notify_source;
106  io_iterator_t deviter;
107 
110  AVS::MPEG2Receiver *avstream;
111  AVS::StringLogger *logger;
115 
117 };
118 
120  uint64_t guid, uint subunitid, uint speed) :
121  FirewireDevice(guid, subunitid, speed),
122  m_local_node(-1), m_remote_node(-1), m_priv(new DFDPriv())
123 {
124 
125 
126 }
127 
129 {
130  if (IsPortOpen())
131  {
132  LOG(VB_GENERAL, LOG_ERR, LOC + "dtor called with open port");
133  while (IsPortOpen())
134  ClosePort();
135  }
136 
137  if (m_priv)
138  {
139  delete m_priv;
140  m_priv = NULL;
141  }
142 }
143 
145 {
146  m_priv->controller_thread_cf_ref = CFRunLoopGetCurrent();
147 
148  // Set up IEEE-1394 bus change notification
149  mach_port_t master_port;
150  int ret = IOMasterPort(bootstrap_port, &master_port);
151  if (kIOReturnSuccess == ret)
152  {
153  m_priv->notify_port = IONotificationPortCreate(master_port);
154  m_priv->notify_source = IONotificationPortGetRunLoopSource(
156 
157  CFRunLoopAddSource(m_priv->controller_thread_cf_ref,
159  kCFRunLoopDefaultMode);
160 
161  ret = IOServiceAddMatchingNotification(
162  m_priv->notify_port, kIOMatchedNotification,
163  IOServiceMatching("IOFireWireAVCUnit"),
165  }
166 
167  if (kIOReturnSuccess == ret)
169 
171 
172  if (kIOReturnSuccess == ret)
173  CFRunLoopRun();
174 
175  QMutexLocker locker(&m_lock); // ensure that controller_thread_running seen
176 
178 }
179 
181 {
182  m_lock.unlock();
183 
184  pthread_create(&m_priv->controller_thread, NULL,
185  dfd_controller_thunk, this);
186 
187  m_lock.lock();
189  {
190  m_lock.unlock();
191  usleep(5000);
192  m_lock.lock();
193  }
194 }
195 
197 {
199  return;
200 
201  if (m_priv->deviter)
202  {
203  IOObjectRelease(m_priv->deviter);
204  m_priv->deviter = NULL;
205  }
206 
207  if (m_priv->notify_source)
208  {
209  CFRunLoopSourceInvalidate(m_priv->notify_source);
210  m_priv->notify_source = NULL;
211  }
212 
213  if (m_priv->notify_port)
214  {
215  IONotificationPortDestroy(m_priv->notify_port);
216  m_priv->notify_port = NULL;
217  }
218 
219  CFRunLoopStop(m_priv->controller_thread_cf_ref);
220 
222  {
223  m_lock.unlock();
224  usleep(100 * 1000);
225  m_lock.lock();
226  }
227 }
228 
230 {
231  QMutexLocker locker(&m_lock);
232 
233  LOG(VB_RECORD, LOG_INFO, LOC + "OpenPort()");
234 
235  if (GetInfoPtr() && GetInfoPtr()->IsPortOpen())
236  {
237  m_open_port_cnt++;
238  return true;
239  }
240 
241  StartController();
242 
244  {
245  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to start firewire thread.");
246  return false;
247  }
248 
249  if (!GetInfoPtr())
250  {
251  LOG(VB_GENERAL, LOG_ERR, LOC + "No IEEE-1394 device with our GUID");
252 
253  StopController();
254  return false;
255  }
256 
257  LOG(VB_RECORD, LOG_INFO, LOC + "Opening AVC Device");
258  LOG(VB_RECORD, LOG_INFO, LOC + GetInfoPtr()->GetSubunitInfoString());
259 
260  if (!GetInfoPtr()->IsSubunitType(kAVCSubunitTypeTuner) ||
261  !GetInfoPtr()->IsSubunitType(kAVCSubunitTypePanel))
262  {
263  LOG(VB_GENERAL, LOG_ERR, LOC + QString("No STB at guid: 0x%1")
264  .arg(m_guid,0,16));
265 
266  StopController();
267  return false;
268  }
269 
271  if (!ok)
272  {
273  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to get handle for port");
274 
275  return false;
276  }
277 
278  // TODO FIXME -- these can change after a reset... (at least local)
279  if (!GetInfoPtr()->GetDeviceNodes(m_local_node, m_remote_node))
280  {
281  if (m_local_node < 0)
282  {
283  LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to query local node");
284  m_local_node = 0;
285  }
286 
287  if (m_remote_node < 0)
288  {
289  LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to query remote node");
290  m_remote_node = 0;
291  }
292  }
293 
294  m_open_port_cnt++;
295 
296  return true;
297 }
298 
300 {
301  QMutexLocker locker(&m_lock);
302 
303  LOG(VB_RECORD, LOG_INFO, LOC + "ClosePort()");
304 
305  if (m_open_port_cnt < 1)
306  return false;
307 
308  m_open_port_cnt--;
309 
310  if (m_open_port_cnt != 0)
311  return true;
312 
313  if (GetInfoPtr() && GetInfoPtr()->IsPortOpen())
314  {
315  LOG(VB_RECORD, LOG_INFO, LOC + "Closing AVC Device");
316 
317  GetInfoPtr()->ClosePort();
318  }
319 
320  StopController();
321  m_local_node = -1;
322  m_remote_node = -1;
323 
324  return true;
325 }
326 
328 {
329  if (IsAVStreamOpen())
330  return true;
331 
332  int max_speed = GetMaxSpeed();
333  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Max Speed: %1, Our speed: %2")
334  .arg(max_speed).arg(m_speed));
335  m_speed = min((uint)max_speed, m_speed);
336 
337  uint fwchan = 0;
338  bool streaming = IsSTBStreaming(&fwchan);
339  LOG(VB_GENERAL, LOG_INFO, LOC +
340  QString("STB is %1already streaming on fwchan: %2")
341  .arg(streaming?"":"not ").arg(fwchan));
342 
343  // TODO we should use the stream if it already exists,
344  // this is especially true if it is a broadcast stream...
345 
346  int ret = AVS::CreateMPEG2Receiver(
347  &m_priv->avstream,
349  dfd_stream_msg, this,
350  m_priv->logger /* StringLogger */,
351  GetInfoPtr()->fw_handle,
352  AVS::kCyclesPerReceiveSegment,
353  AVS::kNumReceiveSegments,
354  true /* p2p */);
355 
356  if (kIOReturnSuccess != ret)
357  {
358  LOG(VB_GENERAL, LOG_ERR, LOC + "Couldn't create A/V stream object");
359  return false;
360  }
361 
362  m_priv->avstream->registerNoDataNotificationCallback(
363  dfd_no_data_notification, this, kNoDataTimeout);
364 
365  return true;
366 }
367 
369 {
370  IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
371 
372  if ((*fw_handle)->version < 4)
373  {
374  // Just get the STB's info & assume we can handle it
375  io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
376 
377  FWAddress addr(0xffff, 0xf0000900, m_remote_node);
378  uint32_t val;
379  int ret = (*fw_handle)->ReadQuadlet(
380  fw_handle, dev, &addr, (UInt32*) &val, false, 0);
381  val = EndianU32_BtoN(val);
382 
383  return (ret == kIOReturnSuccess) ? (int)((val>>30) & 0x3) : -1;
384  }
385 
386  uint32_t generation = 0;
387  IOFWSpeed speed;
388  int ret = (*fw_handle)->GetBusGeneration(fw_handle, (UInt32*)&generation);
389  if (kIOReturnSuccess == ret)
390  {
391  ret = (*fw_handle)->GetSpeedBetweenNodes(
392  fw_handle, generation, m_remote_node, m_local_node, &speed) ;
393  }
394 
395  return (ret == kIOReturnSuccess) ? (int)speed : -1;
396 }
397 
399 {
400  IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
401  io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
402 
403  FWAddress addr(0xffff, 0xf0000904, m_remote_node);
404  uint32_t val;
405  int ret = (*fw_handle)->ReadQuadlet(
406  fw_handle, dev, &addr, (UInt32*) &val, false, 0);
407  val = EndianU32_BtoN(val);
408 
409  if (ret != kIOReturnSuccess)
410  return false;
411 
412  if (val & (kIOFWPCRBroadcast | kIOFWPCRP2PCount))
413  {
414  if (fw_channel)
415  *fw_channel = (val & kIOFWPCRChannel) >> kIOFWPCRChannelPhase;
416 
417  return true;
418  }
419 
420  return false;
421 }
422 
424 {
425  if (!m_priv->avstream)
426  return true;
427 
428  StopStreaming();
429 
430  LOG(VB_RECORD, LOG_INFO, LOC + "Destroying A/V stream object");
432  m_priv->avstream = NULL;
433 
434  return true;
435 }
436 
438 {
439  return m_priv->avstream;
440 }
441 
443 {
444  LOG(VB_GENERAL, LOG_DEBUG, LOC + "ResetBus() -- begin");
445 
446  if (!GetInfoPtr() || !GetInfoPtr()->fw_handle)
447  return false;
448 
449  IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
450  bool ok = (*fw_handle)->BusReset(fw_handle) == kIOReturnSuccess;
451 
452  if (!ok)
453  LOG(VB_GENERAL, LOG_ERR, LOC + "Bus Reset failed" + ENO);
454 
455  LOG(VB_GENERAL, LOG_DEBUG, LOC + "ResetBus() -- end");
456 
457  return ok;
458 }
459 
461 {
462  if (m_priv->is_streaming)
463  return m_priv->is_streaming;
464 
465  LOG(VB_RECORD, LOG_INFO, LOC + "Starting A/V streaming");
466 
467  if (!IsAVStreamOpen() && !OpenAVStream())
468  {
469  LOG(VB_GENERAL, LOG_ERR, LOC + "Starting A/V streaming: FAILED");
470  return false;
471  }
472 
473  m_priv->avstream->setReceiveIsochChannel(kAnyAvailableIsochChannel);
474  m_priv->avstream->setReceiveIsochSpeed((IOFWSpeed) m_speed);
475  int ret = m_priv->avstream->startReceive();
476 
477  m_priv->is_streaming = (kIOReturnSuccess == ret);
478 
479  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Starting A/V streaming: %1")
480  .arg((m_priv->is_streaming)?"success":"failure"));
481 
482  return m_priv->is_streaming;
483 }
484 
486 {
487  if (!m_priv->is_streaming)
488  return true;
489 
490  LOG(VB_RECORD, LOG_INFO, LOC + "Stopping A/V streaming");
491 
492  bool ok = (kIOReturnSuccess == m_priv->avstream->stopReceive());
493  m_priv->is_streaming = !ok;
494 
495  if (!ok)
496  {
497  LOG(VB_RECORD, LOG_ERR, LOC + "Failed to stop A/V streaming");
498  return false;
499  }
500 
501  LOG(VB_RECORD, LOG_INFO, LOC + "Stopped A/V streaming");
502  return true;
503 }
504 
505 bool DarwinFirewireDevice::SendAVCCommand(const vector<uint8_t> &cmd,
506  vector<uint8_t> &result,
507  int retry_cnt)
508 {
509  return GetInfoPtr()->SendAVCCommand(cmd, result, retry_cnt);
510 }
511 
513 {
514  QMutexLocker locker(&m_lock);
515 
516  if (!GetInfoPtr())
517  return false;
518 
519  return GetInfoPtr()->IsPortOpen();
520 }
521 
523 {
524  QMutexLocker locker(&m_lock);
525 
526  FirewireDevice::AddListener(listener);
527 
528  if (!m_listeners.empty())
529  StartStreaming();
530 }
531 
533 {
534  QMutexLocker locker(&m_lock);
535 
537 
538  if (m_priv->is_streaming && m_listeners.empty())
539  {
540  StopStreaming();
541  CloseAVStream();
542  }
543 }
544 
546  const unsigned char *data, uint dataSize)
547 {
548  QMutexLocker locker(&m_lock);
549  FirewireDevice::BroadcastToListeners(data, dataSize);
550 }
551 
553 {
555  {
556  int short_interval = kNoDataTimeout + (kNoDataTimeout>>1);
557  bool recent = m_priv->no_data_timer.elapsed() <= short_interval;
558  m_priv->no_data_cnt = (recent) ? m_priv->no_data_cnt + 1 : 1;
559  }
560  m_priv->no_data_timer_set = true;
562 
563  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No Input in %1 msecs")
564  .arg(m_priv->no_data_cnt * kNoDataTimeout));
565 
566  if (m_priv->no_data_cnt > (kResetTimeout / kNoDataTimeout))
567  {
568  m_priv->no_data_timer_set = false;
569  m_priv->no_data_cnt = 0;
570  ResetBus();
571  }
572 }
573 
575  uint32_t msg, uint32_t param1, uint32_t param2)
576 {
577  int plug_number = 0;
578 
579  if (AVS::kMpeg2ReceiverAllocateIsochPort == msg)
580  {
581  int speed = param1, fw_channel = param2;
582 
583  bool ok = UpdatePlugRegister(
584  plug_number, fw_channel, speed, true, false);
585 
586  LOG(VB_GENERAL, LOG_INFO, LOC + QString("AllocateIsochPort(%1,%2) %3")
587  .arg(fw_channel).arg(speed).arg(((ok)?"ok":"error")));
588  }
589  else if (AVS::kMpeg2ReceiverReleaseIsochPort == msg)
590  {
591  int ret = UpdatePlugRegister(plug_number, -1, -1, false, true);
592 
593  LOG(VB_GENERAL, LOG_INFO, LOC + QString("ReleaseIsochPort %1")
594  .arg((kIOReturnSuccess == ret)?"ok":"error"));
595  }
596  else if (AVS::kMpeg2ReceiverDCLOverrun == msg)
597  {
598  LOG(VB_GENERAL, LOG_ERR, LOC + "DCL Overrun");
599  }
600  else if (AVS::kMpeg2ReceiverReceivedBadPacket == msg)
601  {
602  LOG(VB_GENERAL, LOG_ERR, LOC + "Received Bad Packet");
603  }
604  else
605  {
606  LOG(VB_GENERAL, LOG_INFO, LOC +
607  QString("Streaming Message: %1").arg(msg));
608  }
609 }
610 
611 vector<AVCInfo> DarwinFirewireDevice::GetSTBList(void)
612 {
613  vector<AVCInfo> list;
614 
615  {
616  DarwinFirewireDevice dev(0,0,0);
617 
618  dev.m_lock.lock();
619  dev.StartController();
620  dev.m_lock.unlock();
621 
622  list = dev.GetSTBListPrivate();
623 
624  dev.m_lock.lock();
625  dev.StopController();
626  dev.m_lock.unlock();
627  }
628 
629  return list;
630 }
631 
633 {
634 #if 0
635  LOG(VB_GENERAL, LOG_DEBUG, LOC + "GetSTBListPrivate -- begin");
636 #endif
637  QMutexLocker locker(&m_lock);
638 #if 0
639  LOG(VB_GENERAL, LOG_DEBUG, LOC + "GetSTBListPrivate -- got lock");
640 #endif
641 
642  vector<AVCInfo> list;
643 
644  avcinfo_list_t::iterator it = m_priv->devices.begin();
645  for (; it != m_priv->devices.end(); ++it)
646  {
647  if ((*it)->IsSubunitType(kAVCSubunitTypeTuner) &&
648  (*it)->IsSubunitType(kAVCSubunitTypePanel))
649  {
650  list.push_back(*(*it));
651  }
652  }
653 
654 #if 0
655  LOG(VB_GENERAL, LOG_DEBUG, LOC + "GetSTBListPrivate -- end");
656 #endif
657  return list;
658 }
659 
660 void DarwinFirewireDevice::UpdateDeviceListItem(uint64_t guid, void *pitem)
661 {
662  QMutexLocker locker(&m_lock);
663 
664  avcinfo_list_t::iterator it = m_priv->devices.find(guid);
665 
666  if (it == m_priv->devices.end())
667  {
669 
670  LOG(VB_GENERAL, LOG_INFO, LOC +
671  QString("Adding 0x%1").arg(guid, 0, 16));
672 
673  m_priv->devices[guid] = ptr;
674  it = m_priv->devices.find(guid);
675  }
676 
677  io_object_t &item = *((io_object_t*) pitem);
678  if (it != m_priv->devices.end())
679  {
680  LOG(VB_GENERAL, LOG_INFO, LOC +
681  QString("Updating 0x%1").arg(guid, 0, 16));
682  (*it)->Update(guid, this, m_priv->notify_port,
684  }
685 }
686 
688 {
689  avcinfo_list_t::iterator it = m_priv->devices.find(m_guid);
690  return (it == m_priv->devices.end()) ? NULL : *it;
691 }
692 
694 {
695  avcinfo_list_t::iterator it = m_priv->devices.find(m_guid);
696  return (it == m_priv->devices.end()) ? NULL : *it;
697 }
698 
699 
701  uint plug_number, int new_fw_chan, int new_speed,
702  bool add_plug, bool remove_plug)
703 {
704  if (!GetInfoPtr())
705  return false;
706 
707  IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle;
708  if (!fw_handle)
709  return false;
710 
711  io_object_t dev = (*fw_handle)->GetDevice(fw_handle);
712 
713  // Read the register
714  uint low_addr = kPCRBaseAddress + 4 + (plug_number << 2);
715  FWAddress addr(0xffff, low_addr, m_remote_node);
716  uint32_t old_plug_val;
717  if (kIOReturnSuccess != (*fw_handle)->ReadQuadlet(
718  fw_handle, dev, &addr, (UInt32*) &old_plug_val, false, 0))
719  {
720  return false;
721  }
722  old_plug_val = EndianU32_BtoN(old_plug_val);
723 
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;
727 
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))
731  {
732  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Invalid Plug Count %1")
733  .arg(new_plug_cnt));
734  return false;
735  }
736 
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))
739  {
740  LOG(VB_GENERAL, LOG_WARNING, LOC +
741  "Ignoring FWChan change request, plug already open");
742 
743  new_fw_chan = old_fw_chan;
744  }
745 
746  new_speed = (new_speed >= 0) ? new_speed : old_speed;
747  if (old_plug_cnt && (new_speed != old_speed))
748  {
749  LOG(VB_GENERAL, LOG_WARNING, LOC +
750  "Ignoring speed change request, plug already open");
751 
752  new_speed = old_speed;
753  }
754 
755  uint32_t new_plug_val = old_plug_val;
756 
757  new_plug_val &= ~(0x3f<<24);
758  new_plug_val &= (remove_plug) ? ~kIOFWPCRBroadcast : ~0x0;
759  new_plug_val |= (new_plug_cnt & 0x3f) << 24;
760 
761  new_plug_val &= ~(0x3f<<16);
762  new_plug_val |= (new_fw_chan & 0x3F) << 16;
763 
764  new_plug_val &= ~(0x03<<14);
765  new_plug_val |= (new_speed & 0x03) << 14;
766 
767  old_plug_val = EndianU32_NtoB(old_plug_val);
768  new_plug_val = EndianU32_NtoB(new_plug_val);
769 
770  return (kIOReturnSuccess == (*fw_handle)->CompareSwap(
771  fw_handle, dev, &addr, old_plug_val, new_plug_val, false, 0));
772 }
773 
775 {
776  int plug_number = 0;
777  if (!GetInfoPtr())
778  return;
779 
780  int fw_channel = m_priv->actual_fwchan;
781  bool ok = UpdatePlugRegister(plug_number, fw_channel,
782  m_speed, true, false);
783  if (!ok)
784  {
785  ok = UpdatePlugRegister(plug_number, kAnyAvailableIsochChannel,
786  m_speed, true, false);
787  }
788 
789  if (!ok)
790  LOG(VB_GENERAL, LOG_ERR, LOC + "Reset: Failed to reconnect");
791  else
792  LOG(VB_RECORD, LOG_INFO, LOC + "Reset: Reconnected succesfully");
793 }
794 
796  uint plug_number, int fw_chan, int speed,
797  bool add_plug, bool remove_plug, uint retry_cnt)
798 {
799  if (!GetInfoPtr() || !GetInfoPtr()->fw_handle)
800  return false;
801 
802  bool ok = false;
803 
804  for (uint i = 0; (i < retry_cnt) && !ok; i++)
805  {
807  plug_number, fw_chan, speed, add_plug, remove_plug);
808  }
809 
810  m_priv->actual_fwchan = (ok) ? fw_chan : kAnyAvailableIsochChannel;
811 
812  return ok;
813 }
814 
816 {
817  QString loc = LOC + "HandleDeviceChange: ";
818 
819  if (kIOMessageServiceIsTerminated == messageType)
820  {
821  LOG(VB_RECORD, LOG_INFO, loc + "Disconnect");
822  // stop printing no data messages.. don't try to open
823  return;
824  }
825 
826  if (kIOMessageServiceIsAttemptingOpen == messageType)
827  {
828  LOG(VB_RECORD, LOG_INFO, loc + "Attempting open");
829  return;
830  }
831 
832  if (kIOMessageServiceWasClosed == messageType)
833  {
834  LOG(VB_RECORD, LOG_INFO, loc + "Device Closed");
835  // fill unit_table
836  return;
837  }
838 
839  if (kIOMessageServiceIsSuspended == messageType)
840  {
841  LOG(VB_RECORD, LOG_INFO, loc + "kIOMessageServiceIsSuspended");
842  // start of reset
843  return;
844  }
845 
846  if (kIOMessageServiceIsResumed == messageType)
847  {
848  // end of reset
849  HandleBusReset();
850  }
851 
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");
886  else
887  {
888  LOG(VB_RECORD, LOG_ERR, loc + QString("unknown message 0x%1")
889  .arg(messageType, 0, 16));
890  }
891 }
892 
893 // Various message callbacks.
894 
895 void *dfd_controller_thunk(void *callback_data)
896 {
897  MThread::ThreadSetup("DarwinController");
898  reinterpret_cast<DarwinFirewireDevice*>(callback_data)->RunController();
900  return NULL;
901 }
902 
904  DarwinFirewireDevice *dev, uint64_t guid, void *item)
905 {
906  dev->UpdateDeviceListItem(guid, item);
907 }
908 
909 int dfd_no_data_notification(void *callback_data)
910 {
911  reinterpret_cast<DarwinFirewireDevice*>(callback_data)->
912  ProcessNoDataMessage();
913 
914  return kIOReturnSuccess;
915 }
916 
917 void dfd_stream_msg(UInt32 msg, UInt32 param1,
918  UInt32 param2, void *callback_data)
919 {
920  reinterpret_cast<DarwinFirewireDevice*>(callback_data)->
921  ProcessStreamingMessage(msg, param1, param2);
922 }
923 
924 int dfd_tspacket_handler(uint tsPacketCount, uint32_t **ppBuf,
925  void *callback_data)
926 {
928  reinterpret_cast<DarwinFirewireDevice*>(callback_data);
929 
930  if (!fw)
931  return kIOReturnBadArgument;
932 
933  for (uint32_t i = 0; i < tsPacketCount; ++i)
934  fw->BroadcastToListeners((const unsigned char*) ppBuf[i], 188);
935 
936  return kIOReturnSuccess;
937 }
938 
940  UInt32 tsPacketCount, UInt32 **ppBuf, void *callback_data)
941 {
942  return dfd_tspacket_handler(
943  tsPacketCount, (uint32_t**)ppBuf, callback_data);
944 }
945 
946 static void dfd_update_device_list(void *dfd, io_iterator_t deviter)
947 {
948  DarwinFirewireDevice *dev = reinterpret_cast<DarwinFirewireDevice*>(dfd);
949 
950  io_object_t it = NULL;
951  while ((it = IOIteratorNext(deviter)))
952  {
953  uint64_t guid = 0;
954 
955  CFMutableDictionaryRef props;
956  int ret = IORegistryEntryCreateCFProperties(
957  it, &props, kCFAllocatorDefault, kNilOptions);
958 
959  if (kIOReturnSuccess == ret)
960  {
961  CFNumberRef GUIDDesc = (CFNumberRef)
962  CFDictionaryGetValue(props, CFSTR("GUID"));
963  CFNumberGetValue(GUIDDesc, kCFNumberSInt64Type, &guid);
964  CFRelease(props);
965  dfd_update_device_list_item(dev, guid, &it);
966  }
967  }
968 }
969 
970 static void dfd_streaming_log_message(char *msg)
971 {
972  LOG(VB_RECORD, LOG_INFO, QString("MPEG2Receiver: %1").arg(msg));
973 }