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

Side by Side 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: 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 unified diff | Download patch
« no previous file with comments | « device/serial/serial.gyp ('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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "device/serial/serial_device_enumerator_win.h" 5 #include "device/serial/serial_device_enumerator_win.h"
6 6
7 // This has to be included before windows.h.
8 #include "third_party/re2/re2/re2.h"
9
7 #include <windows.h> 10 #include <windows.h>
11 #include <ntddser.h>
12 #include <setupapi.h>
8 13
9 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_util.h" 15 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/registry.h"
14 17
15 namespace device { 18 namespace device {
16 19
20 namespace {
21
22 // Searches the specified device info for a property with the specified key,
23 // assigns the result to value, and returns whether the operation was
24 // successful.
25 bool GetProperty(HDEVINFO dev_info,
26 SP_DEVINFO_DATA dev_info_data,
27 const int key,
28 std::string* value) {
29 // We don't know how much space the property's value will take up, so we call
30 // the property retrieval function once to fetch the size of the required
31 // value buffer, then again once we've allocated a sufficiently large buffer.
32 scoped_ptr<wchar_t[]> buffer;
33 DWORD buffer_size = 0;
34 while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, key, NULL,
35 (PBYTE)buffer.get(), buffer_size,
Ken Rockot(use gerrit already) 2015/09/23 17:30:18 buffer.get() is always nullptr here. Why not just
charliea (OOO until 10-5) 2015/09/28 13:22:53 Yea, the way that this was written with the while
36 &buffer_size)) {
37 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
38 buffer.reset(new wchar_t[buffer_size]);
39 else
40 return false;
41 }
42
43 *value = base::WideToUTF8(buffer.get());
44 return true;
45 }
46
47 // Searches for the COM port in the device's friendly name, assigns its value to
48 // com_port, and returns whether the operation was successful.
49 bool GetCOMPort(const std::string friendly_name, std::string* com_port) {
50 return RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", com_port);
51 }
52
53 // Searches for the display name in the device's friendly name, assigns its
54 // value to display_name, and returns whether the operation was successful.
55 bool GetDisplayName(const std::string friendly_name,
56 std::string* display_name) {
57 return RE2::PartialMatch(friendly_name, "(.*) \\(COM[0-9]+\\)", display_name);
58 }
59
60 // Searches for the vendor ID in the device's hardware ID, assigns its value to
61 // vendor_id, and returns whether the operation was successful.
62 bool GetVendorID(const std::string hardware_id, uint32_t* vendor_id) {
63 std::string vendor_id_str;
64 return RE2::PartialMatch(hardware_id, "VID_([0-9]+)", &vendor_id_str) &&
65 base::HexStringToUInt(vendor_id_str, vendor_id);
66 }
67
68 // Searches for the product ID in the device's product ID, assigns its value to
69 // product_id, and returns whether the operation was successful.
70 bool GetProductID(const std::string hardware_id, uint32_t* product_id) {
71 std::string product_id_str;
72 return RE2::PartialMatch(hardware_id, "PID_([0-9]+)", &product_id_str) &&
73 base::HexStringToUInt(product_id_str, product_id);
74 }
75
76 } // namespace
77
17 // static 78 // static
18 scoped_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create() { 79 scoped_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create() {
19 return scoped_ptr<SerialDeviceEnumerator>(new SerialDeviceEnumeratorWin()); 80 return scoped_ptr<SerialDeviceEnumerator>(new SerialDeviceEnumeratorWin());
20 } 81 }
21 82
22 SerialDeviceEnumeratorWin::SerialDeviceEnumeratorWin() {} 83 SerialDeviceEnumeratorWin::SerialDeviceEnumeratorWin() {}
23 84
24 SerialDeviceEnumeratorWin::~SerialDeviceEnumeratorWin() {} 85 SerialDeviceEnumeratorWin::~SerialDeviceEnumeratorWin() {}
25 86
26 // TODO(rockot): Query the system for more information than just device paths.
27 // This may or may not require using a different strategy than scanning the
28 // registry location below.
29 mojo::Array<serial::DeviceInfoPtr> SerialDeviceEnumeratorWin::GetDevices() { 87 mojo::Array<serial::DeviceInfoPtr> SerialDeviceEnumeratorWin::GetDevices() {
30 base::win::RegistryValueIterator iter_key(
31 HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
32 mojo::Array<serial::DeviceInfoPtr> devices(0); 88 mojo::Array<serial::DeviceInfoPtr> devices(0);
33 for (; iter_key.Valid(); ++iter_key) { 89
90 // Make a device interface query to find all serial devices.
91 HDEVINFO dev_info =
92 SetupDiGetClassDevs(&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, 0, 0,
93 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
94 if (dev_info == INVALID_HANDLE_VALUE)
95 return devices.Pass();
96
97 SP_DEVINFO_DATA dev_info_data;
98 dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
99 for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
100 std::string friendly_name, com_port;
101 // SPDRP_FRIENDLYNAME looks like "USB_SERIAL_PORT (COM3)".
102 if (!GetProperty(dev_info, dev_info_data, SPDRP_FRIENDLYNAME,
103 &friendly_name) ||
104 !GetCOMPort(friendly_name, &com_port))
105 // In Windows, the COM port is the path used to uniquely identify the
106 // serial device. If the COM can't be found, ignore the device.
107 continue;
108
34 serial::DeviceInfoPtr info(serial::DeviceInfo::New()); 109 serial::DeviceInfoPtr info(serial::DeviceInfo::New());
35 info->path = base::UTF16ToASCII(iter_key.Value()); 110 info->path = com_port;
111
112 std::string display_name;
113 if (GetDisplayName(friendly_name, &display_name))
114 info->display_name = display_name;
115
116 std::string hardware_id;
117 // SPDRP_HARDWAREID looks like "FTDIBUS\COMPORT&VID_0403&PID_6001".
118 if (GetProperty(dev_info, dev_info_data, SPDRP_HARDWAREID, &hardware_id)) {
119 uint32_t vendor_id, product_id;
120 if (GetVendorID(hardware_id, &vendor_id)) {
121 info->has_vendor_id = true;
122 info->vendor_id = vendor_id;
123 }
124 if (GetProductID(hardware_id, &product_id)) {
125 info->has_product_id = true;
126 info->product_id = product_id;
127 }
128 }
129
36 devices.push_back(info.Pass()); 130 devices.push_back(info.Pass());
37 } 131 }
132
133 SetupDiDestroyDeviceInfoList(dev_info);
38 return devices.Pass(); 134 return devices.Pass();
39 } 135 }
40 136
41 } // namespace device 137 } // namespace device
OLDNEW
« 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