Index: device/hid/hid_service_win.cc |
diff --git a/device/hid/hid_service_win.cc b/device/hid/hid_service_win.cc |
index 234d37bce2c6a9c36ea4b24e6259532302fc4d5a..221c00eca4cf86d15ec7d86af9119046c667d249 100644 |
--- a/device/hid/hid_service_win.cc |
+++ b/device/hid/hid_service_win.cc |
@@ -28,7 +28,18 @@ |
namespace device { |
-HidServiceWin::HidServiceWin() : device_observer_(this) { |
+namespace { |
+ |
+void Noop() { |
+ // This function does nothing. |
+} |
+} |
+ |
+HidServiceWin::HidServiceWin( |
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) |
+ : device_observer_(this), |
+ file_task_runner_(file_task_runner), |
+ weak_factory_(this) { |
task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
DCHECK(task_runner_.get()); |
DeviceMonitorWin* device_monitor = |
@@ -36,7 +47,9 @@ HidServiceWin::HidServiceWin() : device_observer_(this) { |
if (device_monitor) { |
device_observer_.Add(device_monitor); |
} |
- DoInitialEnumeration(); |
+ file_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&HidServiceWin::InitialEnumerationFileThread, |
+ weak_factory_.GetWeakPtr(), task_runner_)); |
} |
void HidServiceWin::Connect(const HidDeviceId& device_id, |
@@ -64,7 +77,10 @@ void HidServiceWin::Connect(const HidDeviceId& device_id, |
HidServiceWin::~HidServiceWin() { |
} |
-void HidServiceWin::DoInitialEnumeration() { |
+// static |
+void HidServiceWin::InitialEnumerationFileThread( |
+ base::WeakPtr<HidServiceWin> service, |
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) { |
HDEVINFO device_info_set = |
SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, NULL, NULL, |
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); |
@@ -103,11 +119,13 @@ void HidServiceWin::DoInitialEnumeration() { |
std::string device_path( |
base::SysWideToUTF8(device_interface_detail_data->DevicePath)); |
DCHECK(base::IsStringASCII(device_path)); |
- OnDeviceAdded(base::StringToLowerASCII(device_path)); |
+ AddDeviceFileThread(service, task_runner, |
+ base::StringToLowerASCII(device_path)); |
} |
} |
- FirstEnumerationComplete(); |
+ task_runner->PostTask( |
+ FROM_HERE, base::Bind(&HidServiceWin::FirstEnumerationComplete, service)); |
} |
// static |
@@ -155,7 +173,11 @@ void HidServiceWin::CollectInfoFromValueCaps( |
} |
} |
-void HidServiceWin::OnDeviceAdded(const std::string& device_path) { |
+// static |
+void HidServiceWin::AddDeviceFileThread( |
+ base::WeakPtr<HidServiceWin> service, |
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
+ const std::string& device_path) { |
base::win::ScopedHandle device_handle(OpenDevice(device_path)); |
if (!device_handle.IsValid()) { |
return; |
@@ -220,25 +242,53 @@ void HidServiceWin::OnDeviceAdded(const std::string& device_path) { |
capabilities.NumberFeatureValueCaps, |
&collection_info); |
+ // 1023 characters plus NULL terminator is more than enough for a USB string |
+ // descriptor which is limited to 126 characters. |
+ wchar_t buffer[1024]; |
+ std::string product_name; |
+ if (HidD_GetProductString(device_handle.Get(), &buffer[0], sizeof(buffer))) { |
+ // NULL termination guaranteed by the API. |
+ product_name = base::SysWideToUTF8(buffer); |
+ } |
+ std::string serial_number; |
+ if (HidD_GetSerialNumberString(device_handle.Get(), &buffer[0], |
+ sizeof(buffer))) { |
+ // NULL termination guaranteed by the API. |
+ serial_number = base::SysWideToUTF8(buffer); |
+ } |
+ |
// This populates the HidDeviceInfo instance without a raw report descriptor. |
// The descriptor is unavailable on Windows because HID devices are exposed to |
// user-space as individual top-level collections. |
scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo( |
- device_path, attrib.VendorID, attrib.ProductID, |
- "", // TODO(reillyg): Get product name from Windows. |
- "", // TODO(reillyg): Get serial number from Windows. |
+ device_path, attrib.VendorID, attrib.ProductID, product_name, |
+ serial_number, |
kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 |
collection_info, max_input_report_size, max_output_report_size, |
max_feature_report_size)); |
HidD_FreePreparsedData(preparsed_data); |
- AddDevice(device_info); |
+ task_runner->PostTask( |
+ FROM_HERE, base::Bind(&HidServiceWin::AddDevice, service, device_info)); |
+} |
+ |
+void HidServiceWin::OnDeviceAdded(const std::string& device_path) { |
+ file_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&HidServiceWin::AddDeviceFileThread, |
+ weak_factory_.GetWeakPtr(), task_runner_, device_path)); |
} |
void HidServiceWin::OnDeviceRemoved(const std::string& device_path) { |
- RemoveDevice(device_path); |
+ // Execute a no-op closure on the file task runner to synchronize with any |
+ // devices that are still being enumerated. |
+ file_task_runner_->PostTaskAndReply( |
+ FROM_HERE, base::Bind(&Noop), |
+ base::Bind(&HidServiceWin::RemoveDevice, weak_factory_.GetWeakPtr(), |
+ device_path)); |
} |
+// static |
base::win::ScopedHandle HidServiceWin::OpenDevice( |
const std::string& device_path) { |
base::win::ScopedHandle file( |