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 HidService
* HidService::GetInstance(
38 scoped_refptr
<base::SingleThreadTaskRunner
> file_task_runner
) {
39 if (g_service
== NULL
) {
40 #if defined(OS_LINUX) && defined(USE_UDEV)
41 g_service
= new HidServiceLinux(file_task_runner
);
42 #elif defined(OS_MACOSX)
43 g_service
= new HidServiceMac(file_task_runner
);
45 g_service
= new HidServiceWin(file_task_runner
);
47 if (g_service
!= nullptr) {
48 base::AtExitManager::RegisterTask(base::Bind(
49 &base::DeletePointer
<HidService
>, base::Unretained(g_service
)));
55 void HidService::SetInstanceForTest(HidService
* instance
) {
58 base::AtExitManager::RegisterTask(base::Bind(&base::DeletePointer
<HidService
>,
59 base::Unretained(g_service
)));
62 void HidService::GetDevices(const GetDevicesCallback
& callback
) {
63 DCHECK(thread_checker_
.CalledOnValidThread());
64 if (enumeration_ready_
) {
65 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
66 for (const auto& map_entry
: devices_
) {
67 devices
.push_back(map_entry
.second
);
69 base::MessageLoop::current()->PostTask(FROM_HERE
,
70 base::Bind(callback
, devices
));
72 pending_enumerations_
.push_back(callback
);
76 void HidService::AddObserver(HidService::Observer
* observer
) {
77 observer_list_
.AddObserver(observer
);
80 void HidService::RemoveObserver(HidService::Observer
* observer
) {
81 observer_list_
.RemoveObserver(observer
);
84 // Fills in the device info struct of the given device_id.
85 scoped_refptr
<HidDeviceInfo
> HidService::GetDeviceInfo(
86 const HidDeviceId
& device_id
) const {
87 DCHECK(thread_checker_
.CalledOnValidThread());
88 DeviceMap::const_iterator it
= devices_
.find(device_id
);
89 if (it
== devices_
.end()) {
95 HidService::HidService() : enumeration_ready_(false) {
98 HidService::~HidService() {
99 DCHECK(thread_checker_
.CalledOnValidThread());
102 void HidService::AddDevice(scoped_refptr
<HidDeviceInfo
> device_info
) {
103 DCHECK(thread_checker_
.CalledOnValidThread());
104 if (!ContainsKey(devices_
, device_info
->device_id())) {
105 devices_
[device_info
->device_id()] = device_info
;
107 HID_LOG(USER
) << "HID device "
108 << (enumeration_ready_
? "added" : "detected")
109 << ": vendorId = " << device_info
->vendor_id()
110 << ", productId = " << device_info
->product_id()
111 << ", deviceId = '" << device_info
->device_id() << "'";
113 if (enumeration_ready_
) {
114 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceAdded(device_info
));
119 void HidService::RemoveDevice(const HidDeviceId
& device_id
) {
120 DCHECK(thread_checker_
.CalledOnValidThread());
121 DeviceMap::iterator it
= devices_
.find(device_id
);
122 if (it
!= devices_
.end()) {
123 HID_LOG(USER
) << "HID device removed: deviceId = '" << device_id
<< "'";
125 if (enumeration_ready_
) {
126 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceRemoved(it
->second
));
132 void HidService::FirstEnumerationComplete() {
133 enumeration_ready_
= true;
135 if (!pending_enumerations_
.empty()) {
136 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
137 for (const auto& map_entry
: devices_
) {
138 devices
.push_back(map_entry
.second
);
141 for (const GetDevicesCallback
& callback
: pending_enumerations_
) {
142 callback
.Run(devices
);
144 pending_enumerations_
.clear();
148 } // namespace device