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"
24 void HidService::Observer::OnDeviceAdded(
25 scoped_refptr
<HidDeviceInfo
> device_info
) {
28 void HidService::Observer::OnDeviceRemoved(
29 scoped_refptr
<HidDeviceInfo
> device_info
) {
32 void HidService::Observer::OnDeviceRemovedCleanup(
33 scoped_refptr
<HidDeviceInfo
> device_info
) {
36 scoped_ptr
<HidService
> HidService::Create(
37 scoped_refptr
<base::SingleThreadTaskRunner
> file_task_runner
) {
38 #if defined(OS_LINUX) && defined(USE_UDEV)
39 return make_scoped_ptr(new HidServiceLinux(file_task_runner
));
40 #elif defined(OS_MACOSX)
41 return make_scoped_ptr(new HidServiceMac(file_task_runner
));
43 return make_scoped_ptr(new HidServiceWin(file_task_runner
));
49 void HidService::GetDevices(const GetDevicesCallback
& callback
) {
50 DCHECK(thread_checker_
.CalledOnValidThread());
51 if (enumeration_ready_
) {
52 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
53 for (const auto& map_entry
: devices_
) {
54 devices
.push_back(map_entry
.second
);
56 base::MessageLoop::current()->PostTask(FROM_HERE
,
57 base::Bind(callback
, devices
));
59 pending_enumerations_
.push_back(callback
);
63 void HidService::AddObserver(HidService::Observer
* observer
) {
64 observer_list_
.AddObserver(observer
);
67 void HidService::RemoveObserver(HidService::Observer
* observer
) {
68 observer_list_
.RemoveObserver(observer
);
71 // Fills in the device info struct of the given device_id.
72 scoped_refptr
<HidDeviceInfo
> HidService::GetDeviceInfo(
73 const HidDeviceId
& device_id
) const {
74 DCHECK(thread_checker_
.CalledOnValidThread());
75 DeviceMap::const_iterator it
= devices_
.find(device_id
);
76 if (it
== devices_
.end()) {
82 HidService::HidService() : enumeration_ready_(false) {
85 HidService::~HidService() {
86 DCHECK(thread_checker_
.CalledOnValidThread());
89 void HidService::AddDevice(scoped_refptr
<HidDeviceInfo
> device_info
) {
90 DCHECK(thread_checker_
.CalledOnValidThread());
91 if (!ContainsKey(devices_
, device_info
->device_id())) {
92 devices_
[device_info
->device_id()] = device_info
;
94 HID_LOG(USER
) << "HID device "
95 << (enumeration_ready_
? "added" : "detected")
96 << ": vendorId=" << device_info
->vendor_id()
97 << ", productId=" << device_info
->product_id() << ", name='"
98 << device_info
->product_name() << "', serial='"
99 << device_info
->serial_number() << "', deviceId='"
100 << device_info
->device_id() << "'";
102 if (enumeration_ready_
) {
103 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceAdded(device_info
));
108 void HidService::RemoveDevice(const HidDeviceId
& device_id
) {
109 DCHECK(thread_checker_
.CalledOnValidThread());
110 DeviceMap::iterator it
= devices_
.find(device_id
);
111 if (it
!= devices_
.end()) {
112 HID_LOG(USER
) << "HID device removed: deviceId='" << device_id
<< "'";
114 scoped_refptr
<HidDeviceInfo
> device
= it
->second
;
115 if (enumeration_ready_
) {
116 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceRemoved(device
));
119 if (enumeration_ready_
) {
120 FOR_EACH_OBSERVER(Observer
, observer_list_
,
121 OnDeviceRemovedCleanup(device
));
126 void HidService::FirstEnumerationComplete() {
127 enumeration_ready_
= true;
129 if (!pending_enumerations_
.empty()) {
130 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
131 for (const auto& map_entry
: devices_
) {
132 devices
.push_back(map_entry
.second
);
135 for (const GetDevicesCallback
& callback
: pending_enumerations_
) {
136 callback
.Run(devices
);
138 pending_enumerations_
.clear();
142 } // namespace device