| 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 void GetDevPropString(DEVINST handle, |
| 267 public: | 270 const DEVPROPKEY* devprop_key, |
| 268 static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; } | 271 std::string* out) { |
| 272 DEVPROPTYPE devprop_type; |
| 273 unsigned long buffer_size = 0; |
| 269 | 274 |
| 270 static void Free(HDEVINFO devinfo_set) { | 275 // Retrieve |buffer_size| and allocate buffer later for receiving data. |
| 271 SetupDiDestroyDeviceInfoList(devinfo_set); | 276 CONFIGRET cr = CM_Get_DevNode_Property(handle, devprop_key, &devprop_type, |
| 277 nullptr, &buffer_size, 0); |
| 278 if (cr != CR_BUFFER_SMALL) { |
| 279 // Here we print error codes in hex instead of using PrintHr() with |
| 280 // HRESULT_FROM_WIN32() and CM_MapCrToWin32Err(), since only a minor set of |
| 281 // CONFIGRET values are mapped to Win32 errors. Same for following VLOG()s. |
| 282 VLOG(1) << "CM_Get_DevNode_Property failed: CONFIGRET 0x" << std::hex << cr; |
| 283 return; |
| 272 } | 284 } |
| 273 }; | 285 if (devprop_type != DEVPROP_TYPE_STRING) { |
| 286 VLOG(1) << "CM_Get_DevNode_Property returns wrong data type, " |
| 287 << "expected DEVPROP_TYPE_STRING"; |
| 288 return; |
| 289 } |
| 274 | 290 |
| 275 using ScopedDeviceInfoList = | 291 std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]); |
| 276 base::ScopedGeneric<HDEVINFO, ScopedDeviceInfoListTraits>; | 292 |
| 293 // Receive property data. |
| 294 cr = CM_Get_DevNode_Property(handle, devprop_key, &devprop_type, buffer.get(), |
| 295 &buffer_size, 0); |
| 296 if (cr != CR_SUCCESS) |
| 297 VLOG(1) << "CM_Get_DevNode_Property failed: CONFIGRET 0x" << std::hex << cr; |
| 298 else |
| 299 *out = base::WideToUTF8(reinterpret_cast<base::char16*>(buffer.get())); |
| 300 } |
| 277 | 301 |
| 278 // Retrieves manufacturer (provider) and version information of underlying | 302 // Retrieves manufacturer (provider) and version information of underlying |
| 279 // device driver using Setup API, given device (interface) ID provided by WinRT. | 303 // device driver through PnP Configuration Manager, given device (interface) ID |
| 280 // |out_manufacturer| and |out_driver_version| won't be modified if retrieval | 304 // provided by WinRT. |out_manufacturer| and |out_driver_version| won't be |
| 281 // fails. Note that SetupDiBuildDriverInfoList() would block for a few hundred | 305 // modified if retrieval fails. |
| 282 // milliseconds so consider calling this function in an asynchronous manner. | |
| 283 // | 306 // |
| 284 // Device instance ID is extracted from device (interface) ID provided by WinRT | 307 // Device instance ID is extracted from device (interface) ID provided by WinRT |
| 285 // APIs, for example from the following interface ID: | 308 // APIs, for example from the following interface ID: |
| 286 // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b} | 309 // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b} |
| 287 // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002 | 310 // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002 |
| 311 // |
| 312 // However the extracted device instance ID represent a "software device" |
| 313 // provided by Microsoft, which is an interface on top of the hardware for each |
| 314 // input/output port. Therefore we further locate its parent device, which is |
| 315 // the actual hardware device, for driver information. |
| 288 void GetDriverInfoFromDeviceId(const std::string& dev_id, | 316 void GetDriverInfoFromDeviceId(const std::string& dev_id, |
| 289 std::string* out_manufacturer, | 317 std::string* out_manufacturer, |
| 290 std::string* out_driver_version) { | 318 std::string* out_driver_version) { |
| 291 base::string16 dev_instance_id = | 319 base::string16 dev_instance_id = |
| 292 base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43)); | 320 base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43)); |
| 293 base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id); | 321 base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id); |
| 294 | 322 |
| 295 ScopedDeviceInfoList devinfo_list( | 323 DEVINST dev_instance_handle; |
| 296 SetupDiCreateDeviceInfoList(nullptr, nullptr)); | 324 CONFIGRET cr = CM_Locate_DevNode(&dev_instance_handle, &dev_instance_id[0], |
| 297 if (!devinfo_list.is_valid()) { | 325 CM_LOCATE_DEVNODE_NORMAL); |
| 298 VLOG(1) << "SetupDiCreateDeviceInfoList failed: " | 326 if (cr != CR_SUCCESS) { |
| 299 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | 327 VLOG(1) << "CM_Locate_DevNode failed: CONFIGRET 0x" << std::hex << cr; |
| 300 return; | 328 return; |
| 301 } | 329 } |
| 302 | 330 |
| 303 SP_DEVINFO_DATA devinfo_data = {0}; | 331 DEVINST parent_handle; |
| 304 devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); | 332 cr = CM_Get_Parent(&parent_handle, dev_instance_handle, 0); |
| 305 SP_DRVINFO_DATA drvinfo_data = {0}; | 333 if (cr != CR_SUCCESS) { |
| 306 drvinfo_data.cbSize = sizeof(SP_DRVINFO_DATA); | 334 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; | 335 return; |
| 313 } | 336 } |
| 314 | 337 |
| 315 if (!SetupDiBuildDriverInfoList(devinfo_list.get(), &devinfo_data, | 338 GetDevPropString(parent_handle, &DEVPKEY_Device_DriverProvider, |
| 316 SPDIT_COMPATDRIVER)) { | 339 out_manufacturer); |
| 317 VLOG(1) << "SetupDiBuildDriverInfoList failed: " | 340 GetDevPropString(parent_handle, &DEVPKEY_Device_DriverVersion, |
| 318 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | 341 out_driver_version); |
| 319 return; | |
| 320 } | |
| 321 | |
| 322 // Assume only one entry in driver info list. | |
| 323 if (SetupDiEnumDriverInfo(devinfo_list.get(), &devinfo_data, | |
| 324 SPDIT_COMPATDRIVER, 0, &drvinfo_data)) { | |
| 325 *out_manufacturer = base::WideToUTF8(drvinfo_data.ProviderName); | |
| 326 | |
| 327 std::stringstream ss; | |
| 328 ss << (drvinfo_data.DriverVersion >> 48) << "." | |
| 329 << (drvinfo_data.DriverVersion >> 32 & 0xffff) << "." | |
| 330 << (drvinfo_data.DriverVersion >> 16 & 0xffff) << "." | |
| 331 << (drvinfo_data.DriverVersion & 0xffff); | |
| 332 *out_driver_version = ss.str(); | |
| 333 } else { | |
| 334 VLOG(1) << "SetupDiEnumDriverInfo failed: " | |
| 335 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | |
| 336 } | |
| 337 | |
| 338 if (!SetupDiDestroyDriverInfoList(devinfo_list.get(), &devinfo_data, | |
| 339 SPDIT_COMPATDRIVER)) | |
| 340 VLOG(1) << "SetupDiDestroyDriverInfoList failed: " | |
| 341 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); | |
| 342 } | 342 } |
| 343 | 343 |
| 344 // Tokens with value = 0 are considered invalid (as in <wrl/event.h>). | 344 // Tokens with value = 0 are considered invalid (as in <wrl/event.h>). |
| 345 const int64_t kInvalidTokenValue = 0; | 345 const int64_t kInvalidTokenValue = 0; |
| 346 | 346 |
| 347 template <typename InterfaceType> | 347 template <typename InterfaceType> |
| 348 struct MidiPort { | 348 struct MidiPort { |
| 349 MidiPort() = default; | 349 MidiPort() = default; |
| 350 | 350 |
| 351 uint32_t index; | 351 uint32_t index; |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 void MidiManagerWinrt::OnPortManagerReady() { | 1033 void MidiManagerWinrt::OnPortManagerReady() { |
| 1034 DCHECK(com_thread_checker_->CalledOnValidThread()); | 1034 DCHECK(com_thread_checker_->CalledOnValidThread()); |
| 1035 DCHECK(port_manager_ready_count_ < 2); | 1035 DCHECK(port_manager_ready_count_ < 2); |
| 1036 | 1036 |
| 1037 if (++port_manager_ready_count_ == 2) | 1037 if (++port_manager_ready_count_ == 2) |
| 1038 CompleteInitialization(Result::OK); | 1038 CompleteInitialization(Result::OK); |
| 1039 } | 1039 } |
| 1040 | 1040 |
| 1041 } // namespace midi | 1041 } // namespace midi |
| 1042 } // namespace media | 1042 } // namespace media |
| OLD | NEW |