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"
13 #if defined(OS_LINUX) && defined(USE_UDEV)
14 #include "device/hid/hid_service_linux.h"
15 #elif defined(OS_MACOSX)
16 #include "device/hid/hid_service_mac.h"
18 #include "device/hid/hid_service_win.h"
25 HidService
* g_service
;
28 void HidService::Observer::OnDeviceAdded(
29 scoped_refptr
<HidDeviceInfo
> device_info
) {
32 void HidService::Observer::OnDeviceRemoved(
33 scoped_refptr
<HidDeviceInfo
> device_info
) {
36 HidService
* HidService::GetInstance(
37 scoped_refptr
<base::SingleThreadTaskRunner
> file_task_runner
) {
38 if (g_service
== NULL
) {
39 #if defined(OS_LINUX) && defined(USE_UDEV)
40 g_service
= new HidServiceLinux(file_task_runner
);
41 #elif defined(OS_MACOSX)
42 g_service
= new HidServiceMac(file_task_runner
);
44 g_service
= new HidServiceWin();
46 if (g_service
!= nullptr) {
47 base::AtExitManager::RegisterTask(base::Bind(
48 &base::DeletePointer
<HidService
>, base::Unretained(g_service
)));
54 void HidService::SetInstanceForTest(HidService
* instance
) {
57 base::AtExitManager::RegisterTask(base::Bind(&base::DeletePointer
<HidService
>,
58 base::Unretained(g_service
)));
61 void HidService::GetDevices(const GetDevicesCallback
& callback
) {
62 DCHECK(thread_checker_
.CalledOnValidThread());
63 if (enumeration_ready_
) {
64 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
65 for (const auto& map_entry
: devices_
) {
66 devices
.push_back(map_entry
.second
);
68 base::MessageLoop::current()->PostTask(FROM_HERE
,
69 base::Bind(callback
, devices
));
71 pending_enumerations_
.push_back(callback
);
75 void HidService::AddObserver(HidService::Observer
* observer
) {
76 observer_list_
.AddObserver(observer
);
79 void HidService::RemoveObserver(HidService::Observer
* observer
) {
80 observer_list_
.RemoveObserver(observer
);
83 // Fills in the device info struct of the given device_id.
84 scoped_refptr
<HidDeviceInfo
> HidService::GetDeviceInfo(
85 const HidDeviceId
& device_id
) const {
86 DCHECK(thread_checker_
.CalledOnValidThread());
87 DeviceMap::const_iterator it
= devices_
.find(device_id
);
88 if (it
== devices_
.end()) {
94 HidService::HidService() : enumeration_ready_(false) {
97 HidService::~HidService() {
98 DCHECK(thread_checker_
.CalledOnValidThread());
101 void HidService::AddDevice(scoped_refptr
<HidDeviceInfo
> device_info
) {
102 DCHECK(thread_checker_
.CalledOnValidThread());
103 if (!ContainsKey(devices_
, device_info
->device_id())) {
104 devices_
[device_info
->device_id()] = device_info
;
106 if (enumeration_ready_
) {
107 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceAdded(device_info
));
112 void HidService::RemoveDevice(const HidDeviceId
& device_id
) {
113 DCHECK(thread_checker_
.CalledOnValidThread());
114 DeviceMap::iterator it
= devices_
.find(device_id
);
115 if (it
!= devices_
.end()) {
116 if (enumeration_ready_
) {
117 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnDeviceRemoved(it
->second
));
123 void HidService::FirstEnumerationComplete() {
124 enumeration_ready_
= true;
126 if (!pending_enumerations_
.empty()) {
127 std::vector
<scoped_refptr
<HidDeviceInfo
>> devices
;
128 for (const auto& map_entry
: devices_
) {
129 devices
.push_back(map_entry
.second
);
132 for (const GetDevicesCallback
& callback
: pending_enumerations_
) {
133 callback
.Run(devices
);
135 pending_enumerations_
.clear();
139 } // namespace device