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

Unified Diff: media/midi/midi_manager_winrt.cc

Issue 2309253002: Retrieve driver information in WinRT WebMIDI backend (Closed)
Patch Set: comments, SetupDiEnumDriverInfo fail log 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/midi/midi_manager_winrt.cc
diff --git a/media/midi/midi_manager_winrt.cc b/media/midi/midi_manager_winrt.cc
index a5141a6ce4d00681f98c1479ff5c25480f69b860..35e5ffa3853f3c51d012feef14f5564d5ba91dd6 100644
--- a/media/midi/midi_manager_winrt.cc
+++ b/media/midi/midi_manager_winrt.cc
@@ -18,6 +18,7 @@ struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da"))
#include <comdef.h>
#include <robuffer.h>
+#include <setupapi.h>
#include <windows.devices.enumeration.h>
#include <windows.devices.midi.h>
#include <wrl/event.h>
@@ -29,6 +30,7 @@ struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da"))
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/scoped_generic.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -261,6 +263,83 @@ bool IsMicrosoftSynthesizer(IDeviceInformation* info) {
return result != FALSE;
}
+class ScopedDeviceInfoListTraits {
+ public:
+ static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
+
+ static void Free(HDEVINFO devinfo_set) {
+ SetupDiDestroyDeviceInfoList(devinfo_set);
+ }
+};
+
+using ScopedDeviceInfoList =
+ base::ScopedGeneric<HDEVINFO, ScopedDeviceInfoListTraits>;
+
+// Retrieves manufacturer (provider) and version information of underlying
+// device driver using Setup API, given device (interface) ID provided by WinRT.
+// |out_manufacturer| and |out_driver_version| won't be modified if retrieval
+// fails. Note that SetupDiBuildDriverInfoList() would block for a few hundred
+// milliseconds so consider calling this function in an asynchronous manner.
+void GetDriverInfoFromDeviceId(const std::string& dev_id,
+ std::string* out_manufacturer,
+ std::string* out_driver_version) {
+ // Extract device instance ID from device (interface) ID provided by WinRT
+ // APIs, for example from the following interface ID:
+ // \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b}
Takashi Toyoshima 2016/09/06 07:11:08 Ah, this comment line is over the 80 characters li
+ // we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002
+ base::string16 dev_instance_id =
+ base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43));
+ base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id);
+
+ ScopedDeviceInfoList devinfo_list(
+ SetupDiCreateDeviceInfoList(nullptr, nullptr));
+ if (!devinfo_list.is_valid()) {
+ VLOG(1) << "SetupDiCreateDeviceInfoList failed: "
+ << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
+ return;
+ }
+
+ SP_DEVINFO_DATA devinfo_data = {0};
+ devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ SP_DRVINFO_DATA drvinfo_data = {0};
+ drvinfo_data.cbSize = sizeof(SP_DRVINFO_DATA);
+
+ if (!SetupDiOpenDeviceInfo(devinfo_list.get(), dev_instance_id.c_str(),
+ nullptr, 0, &devinfo_data)) {
+ VLOG(1) << "SetupDiOpenDeviceInfo failed: "
+ << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
+ return;
+ }
+
+ if (!SetupDiBuildDriverInfoList(devinfo_list.get(), &devinfo_data,
+ SPDIT_COMPATDRIVER)) {
+ VLOG(1) << "SetupDiBuildDriverInfoList failed: "
+ << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
+ return;
+ }
+
+ // Assume only one entry in driver info list.
+ if (SetupDiEnumDriverInfo(devinfo_list.get(), &devinfo_data,
+ SPDIT_COMPATDRIVER, 0, &drvinfo_data)) {
+ *out_manufacturer = base::WideToUTF8(drvinfo_data.ProviderName);
+
+ std::stringstream ss;
+ ss << (drvinfo_data.DriverVersion >> 48) << "."
+ << (drvinfo_data.DriverVersion >> 32 & 0xffff) << "."
+ << (drvinfo_data.DriverVersion >> 16 & 0xffff) << "."
+ << (drvinfo_data.DriverVersion & 0xffff);
+ *out_driver_version = ss.str();
+ } else {
+ VLOG(1) << "SetupDiEnumDriverInfo failed: "
+ << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
+ }
+
+ if (!SetupDiDestroyDriverInfoList(devinfo_list.get(), &devinfo_data,
+ SPDIT_COMPATDRIVER))
+ VLOG(1) << "SetupDiDestroyDriverInfoList failed: "
+ << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
+}
+
// Tokens with value = 0 are considered invalid (as in <wrl/event.h>).
const int64_t kInvalidTokenValue = 0;
@@ -594,10 +673,11 @@ class MidiManagerWinrt::MidiPortManager {
MidiPort<InterfaceType>* port = GetPortByDeviceId(dev_id);
if (port == nullptr) {
- // TODO(crbug.com/642604): Fill in manufacturer and driver version.
- AddPort(MidiPortInfo(dev_id, std::string("Manufacturer"),
- port_names_[dev_id], std::string("DriverVersion"),
- MIDI_PORT_OPENED));
+ std::string manufacturer = "Unknown", driver_version = "Unknown";
+ GetDriverInfoFromDeviceId(dev_id, &manufacturer, &driver_version);
+
+ AddPort(MidiPortInfo(dev_id, manufacturer, port_names_[dev_id],
+ driver_version, MIDI_PORT_OPENED));
port = new MidiPort<InterfaceType>;
port->index = static_cast<uint32_t>(port_ids_.size());
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698