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

Unified Diff: device/serial/serial_device_enumerator_win.cc

Issue 1357993002: Extracts more information from serial devices on Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rearranged imports to match style guide. Created 5 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 | « device/serial/serial.gyp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: device/serial/serial_device_enumerator_win.cc
diff --git a/device/serial/serial_device_enumerator_win.cc b/device/serial/serial_device_enumerator_win.cc
index 124c6b720466909d811e86384d65f2c616de8596..0d1e8f1831f1616929d2bb01b06888084443a0ab 100644
--- a/device/serial/serial_device_enumerator_win.cc
+++ b/device/serial/serial_device_enumerator_win.cc
@@ -6,14 +6,75 @@
#include <windows.h>
+#include <ntddser.h>
+#include <setupapi.h>
+
#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/win/registry.h"
+#include "third_party/re2/re2/re2.h"
namespace device {
+namespace {
+
+// Searches the specified device info for a property with the specified key,
+// assigns the result to value, and returns whether the operation was
+// successful.
+bool GetProperty(HDEVINFO dev_info,
+ SP_DEVINFO_DATA dev_info_data,
+ const int key,
+ std::string* value) {
+ // We don't know how much space the property's value will take up, so we call
+ // the property retrieval function once to fetch the size of the required
+ // value buffer, then again once we've allocated a sufficiently large buffer.
+ DWORD buffer_size = 0;
+ SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, key, nullptr,
+ nullptr, buffer_size, &buffer_size);
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ return false;
+
+ scoped_ptr<wchar_t[]> buffer(new wchar_t[buffer_size]);
+ if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, key, nullptr,
+ reinterpret_cast<PBYTE>(buffer.get()),
+ buffer_size, nullptr))
+ return false;
+
+ *value = base::WideToUTF8(buffer.get());
+ return true;
+}
+
+// Searches for the COM port in the device's friendly name, assigns its value to
+// com_port, and returns whether the operation was successful.
+bool GetCOMPort(const std::string friendly_name, std::string* com_port) {
+ return RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", com_port);
+}
+
+// Searches for the display name in the device's friendly name, assigns its
+// value to display_name, and returns whether the operation was successful.
+bool GetDisplayName(const std::string friendly_name,
+ std::string* display_name) {
+ return RE2::PartialMatch(friendly_name, "(.*) \\(COM[0-9]+\\)", display_name);
+}
+
+// Searches for the vendor ID in the device's hardware ID, assigns its value to
+// vendor_id, and returns whether the operation was successful.
+bool GetVendorID(const std::string hardware_id, uint32_t* vendor_id) {
+ std::string vendor_id_str;
+ return RE2::PartialMatch(hardware_id, "VID_([0-9]+)", &vendor_id_str) &&
+ base::HexStringToUInt(vendor_id_str, vendor_id);
+}
+
+// Searches for the product ID in the device's product ID, assigns its value to
+// product_id, and returns whether the operation was successful.
+bool GetProductID(const std::string hardware_id, uint32_t* product_id) {
+ std::string product_id_str;
+ return RE2::PartialMatch(hardware_id, "PID_([0-9]+)", &product_id_str) &&
+ base::HexStringToUInt(product_id_str, product_id);
+}
+
+} // namespace
+
// static
scoped_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create() {
return scoped_ptr<SerialDeviceEnumerator>(new SerialDeviceEnumeratorWin());
@@ -23,18 +84,53 @@ SerialDeviceEnumeratorWin::SerialDeviceEnumeratorWin() {}
SerialDeviceEnumeratorWin::~SerialDeviceEnumeratorWin() {}
-// TODO(rockot): Query the system for more information than just device paths.
-// This may or may not require using a different strategy than scanning the
-// registry location below.
mojo::Array<serial::DeviceInfoPtr> SerialDeviceEnumeratorWin::GetDevices() {
- base::win::RegistryValueIterator iter_key(
- HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
mojo::Array<serial::DeviceInfoPtr> devices(0);
- for (; iter_key.Valid(); ++iter_key) {
+
+ // Make a device interface query to find all serial devices.
+ HDEVINFO dev_info =
+ SetupDiGetClassDevs(&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, 0, 0,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ if (dev_info == INVALID_HANDLE_VALUE)
+ return devices.Pass();
+
+ SP_DEVINFO_DATA dev_info_data;
+ dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
+ std::string friendly_name, com_port;
+ // SPDRP_FRIENDLYNAME looks like "USB_SERIAL_PORT (COM3)".
+ if (!GetProperty(dev_info, dev_info_data, SPDRP_FRIENDLYNAME,
+ &friendly_name) ||
+ !GetCOMPort(friendly_name, &com_port))
+ // In Windows, the COM port is the path used to uniquely identify the
+ // serial device. If the COM can't be found, ignore the device.
+ continue;
+
serial::DeviceInfoPtr info(serial::DeviceInfo::New());
- info->path = base::UTF16ToASCII(iter_key.Value());
+ info->path = com_port;
+
+ std::string display_name;
+ if (GetDisplayName(friendly_name, &display_name))
+ info->display_name = display_name;
+
+ std::string hardware_id;
+ // SPDRP_HARDWAREID looks like "FTDIBUS\COMPORT&VID_0403&PID_6001".
+ if (GetProperty(dev_info, dev_info_data, SPDRP_HARDWAREID, &hardware_id)) {
+ uint32_t vendor_id, product_id;
+ if (GetVendorID(hardware_id, &vendor_id)) {
+ info->has_vendor_id = true;
+ info->vendor_id = vendor_id;
+ }
+ if (GetProductID(hardware_id, &product_id)) {
+ info->has_product_id = true;
+ info->product_id = product_id;
+ }
+ }
+
devices.push_back(info.Pass());
}
+
+ SetupDiDestroyDeviceInfoList(dev_info);
return devices.Pass();
}
« no previous file with comments | « device/serial/serial.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698