Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: media/midi/midi_manager_winrt.cc

Issue 2318953002: Replace Setup API with PnP Configuration Manager in MidiManagerWinrt (Closed)
Patch Set: dynamically allocate devprop buffer Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« media/midi/BUILD.gn ('K') | « media/midi/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 VLOG(1) << "CM_Get_DevNode_Property failed: CONFIGRET 0x" << std::hex << cr;
280 return;
272 } 281 }
273 }; 282 if (devprop_type != DEVPROP_TYPE_STRING) {
283 VLOG(1) << "CM_Get_DevNode_Property returns wrong data type, "
284 << "expected DEVPROP_TYPE_STRING";
285 return;
286 }
274 287
275 using ScopedDeviceInfoList = 288 std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
276 base::ScopedGeneric<HDEVINFO, ScopedDeviceInfoListTraits>; 289
290 // Receive property data.
291 cr = CM_Get_DevNode_Property(handle, devprop_key, &devprop_type, buffer.get(),
292 &buffer_size, 0);
293 if (cr != CR_SUCCESS)
294 VLOG(1) << "CM_Get_DevNode_Property failed: CONFIGRET 0x" << std::hex << cr;
295 else
296 *out = base::WideToUTF8(reinterpret_cast<base::char16*>(buffer.get()));
297 }
277 298
278 // Retrieves manufacturer (provider) and version information of underlying 299 // Retrieves manufacturer (provider) and version information of underlying
279 // device driver using Setup API, given device (interface) ID provided by WinRT. 300 // device driver through PnP Configuration Manager, given device (interface) ID
280 // |out_manufacturer| and |out_driver_version| won't be modified if retrieval 301 // provided by WinRT. |out_manufacturer| and |out_driver_version| won't be
281 // fails. Note that SetupDiBuildDriverInfoList() would block for a few hundred 302 // modified if retrieval fails.
282 // milliseconds so consider calling this function in an asynchronous manner.
283 // 303 //
284 // Device instance ID is extracted from device (interface) ID provided by WinRT 304 // Device instance ID is extracted from device (interface) ID provided by WinRT
285 // APIs, for example from the following interface ID: 305 // APIs, for example from the following interface ID:
286 // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b} 306 // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b}
287 // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002 307 // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002
308 //
309 // However the extracted device instance ID represent a "software device"
310 // provided by Microsoft, which is an interface on top of the hardware for each
311 // input/output port. Therefore we further locate its parent device, which is
312 // the actual hardware device, for driver information.
288 void GetDriverInfoFromDeviceId(const std::string& dev_id, 313 void GetDriverInfoFromDeviceId(const std::string& dev_id,
289 std::string* out_manufacturer, 314 std::string* out_manufacturer,
290 std::string* out_driver_version) { 315 std::string* out_driver_version) {
291 base::string16 dev_instance_id = 316 base::string16 dev_instance_id =
292 base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43)); 317 base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43));
293 base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id); 318 base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id);
294 319
295 ScopedDeviceInfoList devinfo_list( 320 DEVINST dev_instance_handle;
296 SetupDiCreateDeviceInfoList(nullptr, nullptr)); 321 CONFIGRET cr = CM_Locate_DevNode(&dev_instance_handle, &dev_instance_id[0],
297 if (!devinfo_list.is_valid()) { 322 CM_LOCATE_DEVNODE_NORMAL);
298 VLOG(1) << "SetupDiCreateDeviceInfoList failed: " 323 if (cr != CR_SUCCESS) {
299 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); 324 VLOG(1) << "CM_Locate_DevNode failed: CONFIGRET 0x" << std::hex << cr;
300 return; 325 return;
301 } 326 }
302 327
303 SP_DEVINFO_DATA devinfo_data = {0}; 328 DEVINST parent_handle;
304 devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); 329 cr = CM_Get_Parent(&parent_handle, dev_instance_handle, 0);
305 SP_DRVINFO_DATA drvinfo_data = {0}; 330 if (cr != CR_SUCCESS) {
306 drvinfo_data.cbSize = sizeof(SP_DRVINFO_DATA); 331 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; 332 return;
313 } 333 }
314 334
315 if (!SetupDiBuildDriverInfoList(devinfo_list.get(), &devinfo_data, 335 GetDevPropString(parent_handle, &DEVPKEY_Device_DriverProvider,
316 SPDIT_COMPATDRIVER)) { 336 out_manufacturer);
317 VLOG(1) << "SetupDiBuildDriverInfoList failed: " 337 GetDevPropString(parent_handle, &DEVPKEY_Device_DriverVersion,
318 << PrintHr(HRESULT_FROM_WIN32(GetLastError())); 338 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 } 339 }
343 340
344 // Tokens with value = 0 are considered invalid (as in <wrl/event.h>). 341 // Tokens with value = 0 are considered invalid (as in <wrl/event.h>).
345 const int64_t kInvalidTokenValue = 0; 342 const int64_t kInvalidTokenValue = 0;
346 343
347 template <typename InterfaceType> 344 template <typename InterfaceType>
348 struct MidiPort { 345 struct MidiPort {
349 MidiPort() = default; 346 MidiPort() = default;
350 347
351 uint32_t index; 348 uint32_t index;
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 void MidiManagerWinrt::OnPortManagerReady() { 1030 void MidiManagerWinrt::OnPortManagerReady() {
1034 DCHECK(com_thread_checker_->CalledOnValidThread()); 1031 DCHECK(com_thread_checker_->CalledOnValidThread());
1035 DCHECK(port_manager_ready_count_ < 2); 1032 DCHECK(port_manager_ready_count_ < 2);
1036 1033
1037 if (++port_manager_ready_count_ == 2) 1034 if (++port_manager_ready_count_ == 2)
1038 CompleteInitialization(Result::OK); 1035 CompleteInitialization(Result::OK);
1039 } 1036 }
1040 1037
1041 } // namespace midi 1038 } // namespace midi
1042 } // namespace media 1039 } // namespace media
OLDNEW
« media/midi/BUILD.gn ('K') | « media/midi/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698