MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
darwinavcinfo.cpp
Go to the documentation of this file.
1 
7 // Std C++ headers
8 #include <vector>
9 using namespace std;
10 
11 // MythTV headers
12 #include "darwinfirewiredevice.h"
13 #include "darwinavcinfo.h"
14 #include "mythlogging.h"
15 
16 #ifndef kIOFireWireAVCLibUnitInterfaceID2
17 #define kIOFireWireAVCLibUnitInterfaceID2 \
18  CFUUIDGetConstantUUIDWithBytes( \
19  NULL, \
20  0x85, 0xB5, 0xE9, 0x54, 0x0A, 0xEF, 0x11, 0xD8, \
21  0x8D, 0x19, 0x00, 0x03, 0x93, 0x91, 0x4A, 0xBA)
22 #endif
23 
24 static void dfd_device_change_msg(
25  void*, io_service_t, natural_t messageType, void*);
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,
51  &fw_device_notifier_ref);
52  }
53 
54  if (guid == _guid)
55  return; // we're done
56 
57  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  CFNumberRef specDesc = (CFNumberRef)
69  CFDictionaryGetValue(props, CFSTR("Unit_Spec_ID"));
70  CFNumberGetValue(specDesc, kCFNumberSInt32Type, &specid);
71 
72  CFNumberRef typeDesc = (CFNumberRef)
73  CFDictionaryGetValue(props, CFSTR("Unit_Type"));
74  CFNumberGetValue(typeDesc, kCFNumberSInt32Type, &modelid);
75 
76  CFNumberRef vendorDesc = (CFNumberRef)
77  CFDictionaryGetValue(props, CFSTR("Vendor_ID"));
78  CFNumberGetValue(vendorDesc, kCFNumberSInt32Type, &vendorid);
79 
80  CFNumberRef versionDesc = (CFNumberRef)
81  CFDictionaryGetValue(props, CFSTR("Unit_SW_Version"));
82  CFNumberGetValue(versionDesc, kCFNumberSInt32Type, &firmware_revision);
83 
84  CFStringRef 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  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(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)
111  CloseAVCInterface();
112  }
113 }
114 
116  const vector<uint8_t> &cmd,
117  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  {
151  CloseAVCInterface();
152  return false;
153  }
154 
155  return true;
156 }
157 
159 {
160  CloseDeviceInterface();
161  CloseAVCInterface();
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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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, natural_t messageType, void*)
342 {
343  DarwinFirewireDevice *dev =
344  reinterpret_cast<DarwinFirewireDevice*>(dfd);
345  dev->HandleDeviceChange(messageType);
346 }
void CloseAVCInterface(void)
bool OpenAVCInterface(CFRunLoopRef &thread_cf_ref)
void CloseDeviceInterface(void)
int dummy
Definition: programinfo.cpp:46
void Update(uint64_t _guid, DarwinFirewireDevice *dev, IONotificationPortRef notify_port, CFRunLoopRef &thread_cf_ref, io_object_t obj)
bool GetDeviceNodes(int &local_node, int &remote_node)
bool OpenDeviceInterface(CFRunLoopRef &thread_cf_ref)
void HandleDeviceChange(uint messageType)
return memset(s, c, len)
bool OpenPort(CFRunLoopRef &thread_cf_ref)
unsigned short uint16_t
Definition: iso6937tables.h:1
bool ClosePort(void)
typedef HRESULT(WINAPI *LPFNDSC)(LPGUID
virtual bool SendAVCCommand(const vector< uint8_t > &cmd, vector< uint8_t > &result, int retry_cnt)
static void dfd_device_change_msg(void *, io_service_t, natural_t messageType, void *)