OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/midi/midi_manager_winrt.h" | 5 #include "media/midi/midi_manager_winrt.h" |
6 | 6 |
7 // TODO(shaochuan): Remove this once clang supports uuid syntax in <robuffer.h>. | 7 // TODO(shaochuan): Remove this once clang supports uuid syntax in <robuffer.h>. |
8 // https://reviews.llvm.org/D23895 | 8 // https://reviews.llvm.org/D23895 |
9 namespace Windows { | 9 namespace Windows { |
10 namespace Storage { | 10 namespace Storage { |
11 namespace Streams { | 11 namespace Streams { |
12 #pragma warning(disable : 4467) | 12 #pragma warning(disable : 4467) |
13 struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da")) | 13 struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da")) |
14 IBufferByteAccess; | 14 IBufferByteAccess; |
15 } | 15 } |
16 } | 16 } |
17 } | 17 } |
18 | 18 |
19 #include <initguid.h> // Required by <devpkey.h> | |
20 | |
21 #include <cfgmgr32.h> | |
19 #include <comdef.h> | 22 #include <comdef.h> |
23 #include <devpkey.h> | |
20 #include <robuffer.h> | 24 #include <robuffer.h> |
21 #include <setupapi.h> | |
22 #include <windows.devices.enumeration.h> | 25 #include <windows.devices.enumeration.h> |
23 #include <windows.devices.midi.h> | 26 #include <windows.devices.midi.h> |
24 #include <wrl/event.h> | 27 #include <wrl/event.h> |
25 | 28 |
26 #include <iomanip> | 29 #include <iomanip> |
27 #include <unordered_map> | 30 #include <unordered_map> |
28 #include <unordered_set> | 31 #include <unordered_set> |
29 | 32 |
30 #include "base/bind.h" | 33 #include "base/bind.h" |
31 #include "base/lazy_instance.h" | 34 #include "base/lazy_instance.h" |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 bool IsMicrosoftSynthesizer(IDeviceInformation* info) { | 259 bool IsMicrosoftSynthesizer(IDeviceInformation* info) { |
257 auto midi_synthesizer_statics = | 260 auto midi_synthesizer_statics = |
258 WrlStaticsFactory<IMidiSynthesizerStatics, | 261 WrlStaticsFactory<IMidiSynthesizerStatics, |
259 RuntimeClass_Windows_Devices_Midi_MidiSynthesizer>(); | 262 RuntimeClass_Windows_Devices_Midi_MidiSynthesizer>(); |
260 boolean result = FALSE; | 263 boolean result = FALSE; |
261 HRESULT hr = midi_synthesizer_statics->IsSynthesizer(info, &result); | 264 HRESULT hr = midi_synthesizer_statics->IsSynthesizer(info, &result); |
262 VLOG_IF(1, FAILED(hr)) << "IsSynthesizer failed: " << PrintHr(hr); | 265 VLOG_IF(1, FAILED(hr)) << "IsSynthesizer failed: " << PrintHr(hr); |
263 return result != FALSE; | 266 return result != FALSE; |
264 } | 267 } |
265 | 268 |
266 class ScopedDeviceInfoListTraits { | 269 // This is the maximum string length in driver INF files. |
Takashi Toyoshima
2016/09/07 09:22:34
If you know an official document about this magic
Shao-Chuan Lee
2016/09/08 06:23:30
Now retrieving buffer size from CM_Get_DevNode_Pro
| |
267 public: | 270 const size_t kMaxDevicePropertyLength = 4096; |
268 static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; } | |
269 | |
270 static void Free(HDEVINFO devinfo_set) { | |
271 SetupDiDestroyDeviceInfoList(devinfo_set); | |
272 } | |
273 }; | |
274 | |
275 using ScopedDeviceInfoList = | |
276 base::ScopedGeneric<HDEVINFO, ScopedDeviceInfoListTraits>; | |
277 | 271 |
278 // Retrieves manufacturer (provider) and version information of underlying | 272 // Retrieves manufacturer (provider) and version information of underlying |
279 // device driver using Setup API, given device (interface) ID provided by WinRT. | 273 // device driver through PnP Configuration Manager, given device (interface) ID |
280 // |out_manufacturer| and |out_driver_version| won't be modified if retrieval | 274 // provided by WinRT. |out_manufacturer| and |out_driver_version| won't be |
281 // fails. Note that SetupDiBuildDriverInfoList() would block for a few hundred | 275 // modified if retrieval fails. |
282 // milliseconds so consider calling this function in an asynchronous manner. | |
283 // | 276 // |
284 // Device instance ID is extracted from device (interface) ID provided by WinRT | 277 // Device instance ID is extracted from device (interface) ID provided by WinRT |
285 // APIs, for example from the following interface ID: | 278 // APIs, for example from the following interface ID: |
286 // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b} | 279 // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b} |
287 // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002 | 280 // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002 |
281 // | |
282 // However the extracted device instance ID represent a "software device" | |
283 // provided by Microsoft, which is an interface on top of the hardware for each | |
284 // input/output port. Therefore we further locate its parent device, which is | |
285 // the actual hardware device, for driver information. | |
288 void GetDriverInfoFromDeviceId(const std::string& dev_id, | 286 void GetDriverInfoFromDeviceId(const std::string& dev_id, |
289 std::string* out_manufacturer, | 287 std::string* out_manufacturer, |
290 std::string* out_driver_version) { | 288 std::string* out_driver_version) { |
291 base::string16 dev_instance_id = | 289 base::string16 dev_instance_id = |
292 base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43)); | 290 base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43)); |
293 base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id); | 291 base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id); |
294 | 292 |
295 ScopedDeviceInfoList devinfo_list( | 293 DEVINST dev_instance_handle; |
296 SetupDiCreateDeviceInfoList(nullptr, nullptr)); | 294 CONFIGRET cr = CM_Locate_DevNode(&dev_instance_handle, &dev_instance_id[0], |
297 if (!devinfo_list.is_valid()) { | 295 CM_LOCATE_DEVNODE_NORMAL); |
298 VLOG(1) << "SetupDiCreateDeviceInfoList failed: " | 296 if (cr != CR_SUCCESS) { |
299 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | 297 VLOG(1) << "CM_Locate_DevNode failed: CONFIGRET 0x" << std::hex << cr; |
Takashi Toyoshima
2016/09/07 09:22:34
Hum.... another kind of error code again :/
CM_Map
Shao-Chuan Lee
2016/09/08 06:23:30
Tried this and found only a few error codes are ma
Takashi Toyoshima
2016/09/09 05:17:41
So could you left what you tried and why you do li
Shao-Chuan Lee
2016/09/09 05:44:47
Done.
| |
300 return; | 298 return; |
301 } | 299 } |
302 | 300 |
303 SP_DEVINFO_DATA devinfo_data = {0}; | 301 DEVINST parent_handle; |
304 devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); | 302 cr = CM_Get_Parent(&parent_handle, dev_instance_handle, 0); |
305 SP_DRVINFO_DATA drvinfo_data = {0}; | 303 if (cr != CR_SUCCESS) { |
306 drvinfo_data.cbSize = sizeof(SP_DRVINFO_DATA); | 304 VLOG(1) << "CM_Get_Parent failed: CONFIGRET 0x" << std::hex << cr; |
307 | |
308 if (!SetupDiOpenDeviceInfo(devinfo_list.get(), dev_instance_id.c_str(), | |
309 nullptr, 0, &devinfo_data)) { | |
310 VLOG(1) << "SetupDiOpenDeviceInfo failed: " | |
311 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | |
312 return; | 305 return; |
313 } | 306 } |
314 | 307 |
315 if (!SetupDiBuildDriverInfoList(devinfo_list.get(), &devinfo_data, | 308 DEVPROPTYPE devprop_type; |
316 SPDIT_COMPATDRIVER)) { | 309 base::char16 buffer[kMaxDevicePropertyLength]; |
317 VLOG(1) << "SetupDiBuildDriverInfoList failed: " | 310 unsigned long buffer_size = sizeof(buffer); |
318 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | |
319 return; | |
320 } | |
321 | 311 |
322 // Assume only one entry in driver info list. | 312 cr = CM_Get_DevNode_Property(parent_handle, &DEVPKEY_Device_DriverProvider, |
323 if (SetupDiEnumDriverInfo(devinfo_list.get(), &devinfo_data, | 313 &devprop_type, reinterpret_cast<BYTE*>(buffer), |
324 SPDIT_COMPATDRIVER, 0, &drvinfo_data)) { | 314 &buffer_size, 0); |
325 *out_manufacturer = base::WideToUTF8(drvinfo_data.ProviderName); | 315 if (cr != CR_SUCCESS) |
316 VLOG(1) << "CM_Get_DevNode_Property failed: CONFIGRET 0x" << std::hex << cr; | |
317 else if (devprop_type != DEVPROP_TYPE_STRING) | |
318 VLOG(1) << "CM_Get_DevNode_Property returns wrong data type, " | |
319 << "expected DEVPROP_TYPE_STRING."; | |
320 else | |
321 *out_manufacturer = base::WideToUTF8(buffer); | |
326 | 322 |
327 std::stringstream ss; | 323 buffer_size = sizeof(buffer); |
328 ss << (drvinfo_data.DriverVersion >> 48) << "." | 324 cr = CM_Get_DevNode_Property(parent_handle, &DEVPKEY_Device_DriverVersion, |
329 << (drvinfo_data.DriverVersion >> 32 & 0xffff) << "." | 325 &devprop_type, reinterpret_cast<BYTE*>(buffer), |
330 << (drvinfo_data.DriverVersion >> 16 & 0xffff) << "." | 326 &buffer_size, 0); |
331 << (drvinfo_data.DriverVersion & 0xffff); | 327 if (cr != CR_SUCCESS) |
332 *out_driver_version = ss.str(); | 328 VLOG(1) << "CM_Get_DevNode_Property failed: CONFIGRET 0x" << std::hex << cr; |
333 } else { | 329 else if (devprop_type != DEVPROP_TYPE_STRING) |
334 VLOG(1) << "SetupDiEnumDriverInfo failed: " | 330 VLOG(1) << "CM_Get_DevNode_Property returns wrong data type, " |
335 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | 331 << "expected DEVPROP_TYPE_STRING."; |
336 } | 332 else |
337 | 333 *out_driver_version = base::WideToUTF8(buffer); |
338 if (!SetupDiDestroyDriverInfoList(devinfo_list.get(), &devinfo_data, | |
339 SPDIT_COMPATDRIVER)) | |
340 VLOG(1) << "SetupDiDestroyDriverInfoList failed: " | |
341 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | |
342 } | 334 } |
343 | 335 |
344 // Tokens with value = 0 are considered invalid (as in <wrl/event.h>). | 336 // Tokens with value = 0 are considered invalid (as in <wrl/event.h>). |
345 const int64_t kInvalidTokenValue = 0; | 337 const int64_t kInvalidTokenValue = 0; |
346 | 338 |
347 template <typename InterfaceType> | 339 template <typename InterfaceType> |
348 struct MidiPort { | 340 struct MidiPort { |
349 MidiPort() = default; | 341 MidiPort() = default; |
350 | 342 |
351 uint32_t index; | 343 uint32_t index; |
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1033 void MidiManagerWinrt::OnPortManagerReady() { | 1025 void MidiManagerWinrt::OnPortManagerReady() { |
1034 DCHECK(com_thread_checker_->CalledOnValidThread()); | 1026 DCHECK(com_thread_checker_->CalledOnValidThread()); |
1035 DCHECK(port_manager_ready_count_ < 2); | 1027 DCHECK(port_manager_ready_count_ < 2); |
1036 | 1028 |
1037 if (++port_manager_ready_count_ == 2) | 1029 if (++port_manager_ready_count_ == 2) |
1038 CompleteInitialization(Result::OK); | 1030 CompleteInitialization(Result::OK); |
1039 } | 1031 } |
1040 | 1032 |
1041 } // namespace midi | 1033 } // namespace midi |
1042 } // namespace media | 1034 } // namespace media |
OLD | NEW |