MythTV  master
darwinavcinfo.cpp
Go to the documentation of this file.
1 
7 // Std C++ headers
8 #include <vector>
9 
10 // MythTV headers
12 #include "darwinfirewiredevice.h"
13 #include "darwinavcinfo.h"
14 
15 #ifndef kIOFireWireAVCLibUnitInterfaceID2
16 #define kIOFireWireAVCLibUnitInterfaceID2 \
17  CFUUIDGetConstantUUIDWithBytes( \
18  nullptr, \
19  0x85, 0xB5, 0xE9, 0x54, 0x0A, 0xEF, 0x11, 0xD8, \
20  0x8D, 0x19, 0x00, 0x03, 0x93, 0x91, 0x4A, 0xBA)
21 #endif
22 
23 static void dfd_device_change_msg(
24  void* /*dfd*/, io_service_t /*unused*/, natural_t messageType,
25  void* /*unused*/);
26 
27 void DarwinAVCInfo::Update(uint64_t _guid, DarwinFirewireDevice *dev,
28  IONotificationPortRef notify_port,
29  CFRunLoopRef &thread_cf_ref, io_object_t obj)
30 {
31  IOObjectRelease(fw_device_notifier_ref);
32  IOObjectRelease(fw_node_ref);
33  IOObjectRelease(fw_device_ref);
34  IOObjectRelease(fw_service_ref);
35  IOObjectRelease(avc_service_ref);
36 
37  avc_service_ref = obj;
38 
39  IORegistryEntryGetParentEntry(
40  avc_service_ref, kIOServicePlane, &fw_service_ref);
41  IORegistryEntryGetParentEntry(
42  fw_service_ref, kIOServicePlane, &fw_device_ref);
43  IORegistryEntryGetParentEntry(
44  fw_device_ref, kIOServicePlane, &fw_node_ref);
45 
46  if (notify_port)
47  {
48  IOServiceAddInterestNotification(
49  notify_port, obj, kIOGeneralInterest,
52  }
53 
54  if (m_guid == _guid)
55  return; // we're done
56 
57  m_guid = _guid;
58 
60  // get basic info
61 
62  CFMutableDictionaryRef props;
63  int ret = IORegistryEntryCreateCFProperties(
64  obj, &props, kCFAllocatorDefault, kNilOptions);
65  if (kIOReturnSuccess != ret)
66  return; // this is bad
67 
68  auto specDesc = (CFNumberRef)
69  CFDictionaryGetValue(props, CFSTR("Unit_Spec_ID"));
70  CFNumberGetValue(specDesc, kCFNumberSInt32Type, &m_specid);
71 
72  auto typeDesc = (CFNumberRef)
73  CFDictionaryGetValue(props, CFSTR("Unit_Type"));
74  CFNumberGetValue(typeDesc, kCFNumberSInt32Type, &m_modelid);
75 
76  auto vendorDesc = (CFNumberRef)
77  CFDictionaryGetValue(props, CFSTR("Vendor_ID"));
78  CFNumberGetValue(vendorDesc, kCFNumberSInt32Type, &m_vendorid);
79 
80  auto versionDesc = (CFNumberRef)
81  CFDictionaryGetValue(props, CFSTR("Unit_SW_Version"));
82  CFNumberGetValue(versionDesc, kCFNumberSInt32Type, &m_firmware_revision);
83 
84  auto tmp0 = (CFStringRef)
85  CFDictionaryGetValue(props, CFSTR("FireWire Product Name"));
86  if (tmp0)
87  {
88  char tmp1[1024];
89  memset(tmp1, 0, sizeof(tmp1));
90  CFStringGetCString(tmp0, tmp1, sizeof(tmp1) - sizeof(char),
91  kCFStringEncodingMacRoman);
92  m_product_name = QString("%1").arg(tmp1);
93  }
94 
95  CFRelease(props);
96 
98  // get subunit info
99 
100  LOG(VB_RECORD, LOG_INFO, QString("Scanning guid: 0x%1").arg(m_guid, 0, 16));
101 
102  bool wasOpen = IsAVCInterfaceOpen();
103  if (OpenAVCInterface(thread_cf_ref))
104  {
105  if (!GetSubunitInfo())
106  {
107  LOG(VB_GENERAL, LOG_ERR, "GetSubunitInfo failed");
108  }
109 
110  if (!wasOpen)
112  }
113 }
114 
116  const std::vector<uint8_t> &cmd,
117  std::vector<uint8_t> &result,
118  int /*retry_cnt*/)
119 {
120  result.clear();
121 
122  uint32_t result_length = 4096;
123  uint8_t response[4096];
124 
125  if (!avc_handle)
126  return false;
127 
128  int ret = (*avc_handle)->
129  AVCCommand(avc_handle, (const UInt8*) &cmd[0], cmd.size(),
130  response, (UInt32*) &result_length);
131 
132  if (ret != kIOReturnSuccess)
133  return false;
134 
135  if (result_length)
136  result.insert(result.end(), response, response + result_length);
137 
138  return true;
139 }
140 
141 bool DarwinAVCInfo::OpenPort(CFRunLoopRef &thread_cf_ref)
142 {
143  if (IsPortOpen())
144  return true;
145 
146  if (!OpenAVCInterface(thread_cf_ref))
147  return false;
148 
149  if (!OpenDeviceInterface(thread_cf_ref))
150  {
152  return false;
153  }
154 
155  return true;
156 }
157 
159 {
162  return true;
163 }
164 
165 bool DarwinAVCInfo::OpenAVCInterface(CFRunLoopRef &thread_cf_ref)
166 {
167  if (IsAVCInterfaceOpen())
168  return true;
169 
170  if (!avc_service_ref)
171  return false;
172 
173  IOCFPlugInInterface **input_plug;
174  int32_t dummy;
175  int ret = IOCreatePlugInInterfaceForService(
176  avc_service_ref, kIOFireWireAVCLibUnitTypeID, kIOCFPlugInInterfaceID,
177  &input_plug, (SInt32*) &dummy);
178 
179  if (kIOReturnSuccess != ret)
180  return false;
181 
182  // Try to get post-Jaguar interface
183  HRESULT err = (*input_plug)->QueryInterface(
184  input_plug, CFUUIDGetUUIDBytes(kIOFireWireAVCLibUnitInterfaceID2),
185  (void**) &avc_handle);
186 
187  // On failure, try Jaguar interface
188  if (S_OK != err)
189  {
190  err = (*input_plug)->QueryInterface(
191  input_plug, CFUUIDGetUUIDBytes(kIOFireWireAVCLibUnitInterfaceID),
192  (void**) &avc_handle);
193  }
194 
195  if (S_OK != err)
196  {
197  (*input_plug)->Release(input_plug);
198  return false;
199  }
200 
201  // Add avc_handle to the event loop
202  ret = (*avc_handle)->addCallbackDispatcherToRunLoop(
203  avc_handle, thread_cf_ref);
204 
205  (*input_plug)->Release(input_plug);
206 
207  if (kIOReturnSuccess != ret)
208  {
209  (*avc_handle)->Release(avc_handle);
210  avc_handle = nullptr;
211  return false;
212  }
213 
214  ret = (*avc_handle)->open(avc_handle);
215  if (kIOReturnSuccess != ret)
216  {
217  (*avc_handle)->Release(avc_handle);
218  avc_handle = nullptr;
219  return false;
220  }
221 
222  return true;
223 }
224 
226 {
227  if (!avc_handle)
228  return;
229 
230  (*avc_handle)->removeCallbackDispatcherFromRunLoop(avc_handle);
231  (*avc_handle)->close(avc_handle);
232  (*avc_handle)->Release(avc_handle);
233 
234  avc_handle = nullptr;
235 }
236 
237 bool DarwinAVCInfo::OpenDeviceInterface(CFRunLoopRef &thread_cf_ref)
238 {
239  if (fw_handle)
240  return true;
241 
242  if (!avc_handle)
243  return false;
244 
245  IOCFPlugInInterface **input_plug;
246  int32_t dummy;
247  int ret = IOCreatePlugInInterfaceForService(
248  fw_device_ref, kIOFireWireLibTypeID, kIOCFPlugInInterfaceID,
249  &input_plug, (SInt32*) &dummy);
250 
251  if (kIOReturnSuccess != ret)
252  return false;
253 
254  HRESULT err = (*input_plug)->QueryInterface(
255  input_plug, CFUUIDGetUUIDBytes(kIOFireWireNubInterfaceID),
256  (void**) &fw_handle);
257 
258  if (S_OK != err)
259  {
260  (*input_plug)->Release(input_plug);
261  return false;
262  }
263 
264  // Add fw_handle to the event loop
265  ret = (*fw_handle)->AddCallbackDispatcherToRunLoop(
266  fw_handle, thread_cf_ref);
267 
268  (*input_plug)->Release(input_plug);
269 
270  if (kIOReturnSuccess == ret)
271  {
272  // open the interface
273  ret = (*fw_handle)->OpenWithSessionRef(
274  fw_handle, (*avc_handle)->getSessionRef(avc_handle));
275  }
276 
277  if (kIOReturnSuccess != ret)
278  {
279  (*fw_handle)->Release(fw_handle);
280  fw_handle = nullptr;
281  return false;
282  }
283 
284  return true;
285 }
286 
288 {
289  if (!fw_handle)
290  return;
291 
292  (*fw_handle)->RemoveCallbackDispatcherFromRunLoop(fw_handle);
293  (*fw_handle)->Close(fw_handle);
294  (*fw_handle)->Release(fw_handle);
295 
296  fw_handle = nullptr;
297 }
298 
299 bool DarwinAVCInfo::GetDeviceNodes(int &local_node, int &remote_node)
300 {
301  uint32_t generation = 0;
302  uint16_t node = 0;
303  local_node = -1;
304  remote_node = -1;
305 
306  if ((*fw_handle)->version < 4)
307  {
308  if (kIOReturnSuccess == (*fw_handle)->GetGenerationAndNodeID(
309  fw_handle, (UInt32*) &generation, (UInt16*) &node))
310  {
311  remote_node = node;
312  }
313 
314  if (kIOReturnSuccess == (*fw_handle)->GetLocalNodeID(
315  fw_handle, (UInt16*) &node))
316  {
317  local_node = node;
318  }
319  }
320 
321  int ret = (*fw_handle)->GetBusGeneration(fw_handle, (UInt32*)&generation);
322  if (kIOReturnSuccess == ret)
323  {
324  if (kIOReturnSuccess == (*fw_handle)->GetLocalNodeIDWithGeneration(
325  fw_handle, generation, (UInt16*) &node))
326  {
327  local_node = node;
328  }
329 
330  if (kIOReturnSuccess == (*fw_handle)->GetRemoteNodeID(
331  fw_handle, generation, (UInt16*) &node))
332  {
333  remote_node = node;
334  }
335  }
336 
337  return (local_node >= 0) && (remote_node >= 0);
338 }
339 
341  void *dfd, io_service_t /*unused*/, natural_t messageType, void* /*unused*/)
342 {
343  auto *dev = reinterpret_cast<DarwinFirewireDevice*>(dfd);
344  dev->HandleDeviceChange(messageType);
345 }
DarwinAVCInfo::OpenDeviceInterface
bool OpenDeviceInterface(CFRunLoopRef &thread_cf_ref)
Definition: darwinavcinfo.cpp:237
DarwinAVCInfo::IsPortOpen
bool IsPortOpen(void) const
Definition: darwinavcinfo.h:51
DarwinAVCInfo::fw_device_ref
io_service_t fw_device_ref
Definition: darwinavcinfo.h:55
darwinfirewiredevice.h
DarwinAVCInfo::fw_device_notifier_ref
io_object_t fw_device_notifier_ref
Definition: darwinavcinfo.h:59
DarwinFirewireDevice
Definition: darwinfirewiredevice.h:10
DarwinAVCInfo::GetDeviceNodes
bool GetDeviceNodes(int &local_node, int &remote_node)
Definition: darwinavcinfo.cpp:299
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DarwinAVCInfo::IsAVCInterfaceOpen
bool IsAVCInterfaceOpen(void) const
Definition: darwinavcinfo.h:50
DarwinAVCInfo::OpenPort
bool OpenPort(CFRunLoopRef &thread_cf_ref)
Definition: darwinavcinfo.cpp:141
DarwinAVCInfo::avc_service_ref
io_service_t avc_service_ref
Definition: darwinavcinfo.h:57
mythlogging.h
AVCInfo::GetSubunitInfo
bool GetSubunitInfo(void)
Definition: avcinfo.cpp:32
AVCInfo::m_specid
uint m_specid
Definition: avcinfo.h:48
darwinavcinfo.h
DarwinAVCInfo::fw_node_ref
io_service_t fw_node_ref
Definition: darwinavcinfo.h:54
DarwinFirewireDevice::HandleDeviceChange
void HandleDeviceChange(uint messageType)
Definition: darwinfirewiredevice.cpp:811
AVCInfo::m_vendorid
uint m_vendorid
Definition: avcinfo.h:49
AVCInfo::m_product_name
QString m_product_name
Definition: avcinfo.h:52
DarwinAVCInfo::fw_service_ref
io_service_t fw_service_ref
Definition: darwinavcinfo.h:56
DarwinAVCInfo::Update
void Update(uint64_t _guid, DarwinFirewireDevice *dev, IONotificationPortRef notify_port, CFRunLoopRef &thread_cf_ref, io_object_t obj)
Definition: darwinavcinfo.cpp:27
AVCInfo::m_firmware_revision
uint m_firmware_revision
Definition: avcinfo.h:51
AVCInfo::m_modelid
uint m_modelid
Definition: avcinfo.h:50
DarwinAVCInfo::CloseAVCInterface
void CloseAVCInterface(void)
Definition: darwinavcinfo.cpp:225
DarwinAVCInfo::CloseDeviceInterface
void CloseDeviceInterface(void)
Definition: darwinavcinfo.cpp:287
AVCInfo::m_guid
uint64_t m_guid
Definition: avcinfo.h:47
dfd_device_change_msg
static void dfd_device_change_msg(void *, io_service_t, natural_t messageType, void *)
Definition: darwinavcinfo.cpp:340
kIOFireWireAVCLibUnitInterfaceID2
#define kIOFireWireAVCLibUnitInterfaceID2
DarwinFirewireChannel Copyright (c) 2006 by Daniel Kristjansson Distributed as part of MythTV under G...
Definition: darwinavcinfo.cpp:16
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
DarwinAVCInfo::OpenAVCInterface
bool OpenAVCInterface(CFRunLoopRef &thread_cf_ref)
Definition: darwinavcinfo.cpp:165
DarwinAVCInfo::SendAVCCommand
bool SendAVCCommand(const std::vector< uint8_t > &cmd, std::vector< uint8_t > &result, int retry_cnt) override
Definition: darwinavcinfo.cpp:115
DarwinAVCInfo::fw_handle
IOFireWireLibDeviceRef fw_handle
Definition: darwinavcinfo.h:62
DarwinAVCInfo::ClosePort
bool ClosePort(void)
Definition: darwinavcinfo.cpp:158
DarwinAVCInfo::avc_handle
IOFireWireAVCLibUnitInterface ** avc_handle
Definition: darwinavcinfo.h:61