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
3 // found in the LICENSE file.
5 #include "device/hid/hid_service.h"
7 #include "base/at_exit.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/stl_util.h"
12 #include "components/device_event_log/device_event_log.h"
14 #if defined(OS_LINUX) && defined(USE_UDEV)
15 #include "device/hid/hid_service_linux.h"
16 #elif defined(OS_MACOSX)
17 #include "device/hid/hid_service_mac.h"
19 #include "device/hid/hid_service_win.h"
26 HidService
* g_service
;
29 void HidService::Observer::OnDeviceAdded(
30 scoped_refptr
<HidDeviceInfo
> device_info
) {
33 void HidService::Observer::OnDeviceRemoved(
34 scoped_refptr
<HidDeviceInfo
> device_info
) {
37 void HidService::Observer::OnDeviceRemovedCleanup(
38 scoped_refptr
<HidDeviceInfo
> device_info
) {
41 HidService
* HidService::GetInstance(
42 scoped_refptr
<base::SingleThreadTaskRunner
> file_task_runner
) {
43 if (g_service
== NULL
) {
44 #if defined(OS_LINUX) && defined(USE_UDEV)
45 g_service
= new HidServiceLinux(file_task_runner
);
46 #elif defined(OS_MACOSX)
47 g_service
= new HidServiceMac(file_task_runner
);
49 g_service
= new HidServiceWin(file_task_runner
);
51 if (g_service
!= nullptr) {
52 base::AtExitManager::RegisterTask(base::Bind(
53 &base::DeletePointer
<HidService
>, base::Unretained(g_service
)));
59 void HidService::SetInstanceForTest(HidService
* instance
) {
62 base::AtExitManager::RegisterTask(base::Bind(&base::DeletePointer
<HidService
>,
63 base::Unretained(g_service
)));
66 void HidService::GetDevices(const GetDevicesCallback
& callback
) {
67 DCHECK(thread_checker_
.CalledOnValidThread());
68 if (enumeration_ready_
) {
69 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
70 for (const auto& map_entry
: devices_
) {
71 devices
.push_back(map_entry
.second
);
73 base::MessageLoop::current()->PostTask(FROM_HERE
,
74 base::Bind(callback
, devices
));
76 pending_enumerations_
.push_back(callback
);
80 void HidService::AddObserver(HidService::Observer
* observer
) {
81 observer_list_
.AddObserver(observer
);
84 void HidService::RemoveObserver(HidService::Observer
* observer
) {
85 observer_list_
.RemoveObserver(observer
);
88 // Fills in the device info struct of the given device_id.
89 scoped_refptr
<HidDeviceInfo
> HidService::GetDeviceInfo(
90 const HidDeviceId
& device_id
) const {
91 DCHECK(thread_checker_
.CalledOnValidThread());
92 DeviceMap::const_iterator it
= devices_
.find(device_id
);
93 if (it
== devices_
.end()) {
99 HidService::HidService() : enumeration_ready_(false) {
102 HidService::~HidService() {
103 DCHECK(thread_checker_
.CalledOnValidThread());
106 void HidService::AddDevice(scoped_refptr
<HidDeviceInfo
> device_info
) {
107 DCHECK(thread_checker_
.CalledOnValidThread());
108 if (!ContainsKey(devices_
, device_info
->device_id())) {
109 devices_
[device_info
->device_id()] = device_info
;
111 HID_LOG(USER
) << "HID device "
112 << (enumeration_ready_
? "added" : "detected")
113 << ": vendorId=" << device_info
->vendor_id()
114 << ", productId=" << device_info
->product_id() << ", name='"
115 << device_info
->product_name() << "', serial='"
116 << device_info
->serial_number() << "', deviceId='"
117 << device_info
->device_id() << "'";
119 if (enumeration_ready_
) {
120 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceAdded(device_info
));
125 void HidService::RemoveDevice(const HidDeviceId
& device_id
) {
126 DCHECK(thread_checker_
.CalledOnValidThread());
127 DeviceMap::iterator it
= devices_
.find(device_id
);
128 if (it
!= devices_
.end()) {
129 HID_LOG(USER
) << "HID device removed: deviceId='" << device_id
<< "'";
131 scoped_refptr
<HidDeviceInfo
> device
= it
->second
;
132 if (enumeration_ready_
) {
133 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceRemoved(device
));
136 if (enumeration_ready_
) {
137 FOR_EACH_OBSERVER(Observer
, observer_list_
,
138 OnDeviceRemovedCleanup(device
));
143 void HidService::FirstEnumerationComplete() {
144 enumeration_ready_
= true;
146 if (!pending_enumerations_
.empty()) {
147 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
148 for (const auto& map_entry
: devices_
) {
149 devices
.push_back(map_entry
.second
);
152 for (const GetDevicesCallback
& callback
: pending_enumerations_
) {
153 callback
.Run(devices
);
155 pending_enumerations_
.clear();
159 } // namespace device