OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/gamepad/platform_data_fetcher_linux.h" | 5 #include "content/browser/gamepad/platform_data_fetcher_linux.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <libudev.h> | 8 #include <libudev.h> |
9 #include <linux/joystick.h> | 9 #include <linux/joystick.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <sys/stat.h> | 11 #include <sys/stat.h> |
12 #include <sys/types.h> | 12 #include <sys/types.h> |
13 #include <unistd.h> | 13 #include <unistd.h> |
14 | 14 |
15 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
16 #include "base/eintr_wrapper.h" | 16 #include "base/eintr_wrapper.h" |
17 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
18 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
20 #include "base/stringprintf.h" | 20 #include "base/stringprintf.h" |
21 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
| 22 #include "content/browser/udev_linux.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 const char kInputSubsystem[] = "input"; | 26 const char kInputSubsystem[] = "input"; |
26 const char kUsbSubsystem[] = "usb"; | 27 const char kUsbSubsystem[] = "usb"; |
27 const char kUsbDeviceType[] = "usb_device"; | 28 const char kUsbDeviceType[] = "usb_device"; |
28 const float kMaxLinuxAxisValue = 32767.0; | 29 const float kMaxLinuxAxisValue = 32767.0; |
29 | 30 |
30 void CloseFileDescriptorIfValid(int fd) { | 31 void CloseFileDescriptorIfValid(int fd) { |
31 if (fd >= 0) | 32 if (fd >= 0) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 namespace content { | 65 namespace content { |
65 | 66 |
66 using WebKit::WebGamepad; | 67 using WebKit::WebGamepad; |
67 using WebKit::WebGamepads; | 68 using WebKit::WebGamepads; |
68 | 69 |
69 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { | 70 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { |
70 for (size_t i = 0; i < arraysize(device_fds_); ++i) | 71 for (size_t i = 0; i < arraysize(device_fds_); ++i) |
71 device_fds_[i] = -1; | 72 device_fds_[i] = -1; |
72 memset(mappers_, 0, sizeof(mappers_)); | 73 memset(mappers_, 0, sizeof(mappers_)); |
73 | 74 |
74 udev_ = udev_new(); | 75 std::vector<UdevLinux::UdevMonitorFilter> filters; |
75 CHECK(udev_); | 76 filters.push_back( |
76 | 77 content::UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL)); |
77 monitor_ = udev_monitor_new_from_netlink(udev_, "udev"); | 78 udev_.reset( |
78 CHECK(monitor_); | 79 new UdevLinux(filters, |
79 int ret = udev_monitor_filter_add_match_subsystem_devtype(monitor_, | 80 base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice, |
80 kInputSubsystem, | 81 base::Unretained(this)))); |
81 NULL); | |
82 CHECK_EQ(0, ret); | |
83 ret = udev_monitor_enable_receiving(monitor_); | |
84 CHECK_EQ(0, ret); | |
85 monitor_fd_ = udev_monitor_get_fd(monitor_); | |
86 CHECK_GE(monitor_fd_, 0); | |
87 bool success = MessageLoopForIO::current()->WatchFileDescriptor(monitor_fd_, | |
88 true, MessageLoopForIO::WATCH_READ, &monitor_watcher_, this); | |
89 CHECK(success); | |
90 | 82 |
91 EnumerateDevices(); | 83 EnumerateDevices(); |
92 } | 84 } |
93 | 85 |
94 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { | 86 GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { |
95 monitor_watcher_.StopWatchingFileDescriptor(); | |
96 udev_monitor_unref(monitor_); | |
97 udev_unref(udev_); | |
98 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) | 87 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) |
99 CloseFileDescriptorIfValid(device_fds_[i]); | 88 CloseFileDescriptorIfValid(device_fds_[i]); |
100 } | 89 } |
101 | 90 |
102 void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { | 91 void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { |
103 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); | 92 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); |
104 | 93 |
105 data_.length = WebGamepads::itemsLengthCap; | 94 data_.length = WebGamepads::itemsLengthCap; |
106 | 95 |
107 // Update our internal state. | 96 // Update our internal state. |
108 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { | 97 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
109 if (device_fds_[i] >= 0) { | 98 if (device_fds_[i] >= 0) { |
110 ReadDeviceData(i); | 99 ReadDeviceData(i); |
111 } | 100 } |
112 } | 101 } |
113 | 102 |
114 // Copy to the current state to the output buffer, using the mapping | 103 // Copy to the current state to the output buffer, using the mapping |
115 // function, if there is one available. | 104 // function, if there is one available. |
116 pads->length = data_.length; | 105 pads->length = data_.length; |
117 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { | 106 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
118 if (mappers_[i]) | 107 if (mappers_[i]) |
119 mappers_[i](data_.items[i], &pads->items[i]); | 108 mappers_[i](data_.items[i], &pads->items[i]); |
120 else | 109 else |
121 pads->items[i] = data_.items[i]; | 110 pads->items[i] = data_.items[i]; |
122 } | 111 } |
123 } | 112 } |
124 | 113 |
125 void GamepadPlatformDataFetcherLinux::OnFileCanReadWithoutBlocking(int fd) { | |
126 // Events occur when devices attached to the system are added, removed, or | |
127 // change state. udev_monitor_receive_device() will return a device object | |
128 // representing the device which changed and what type of change occured. | |
129 DCHECK_EQ(monitor_fd_, fd); | |
130 udev_device* dev = udev_monitor_receive_device(monitor_); | |
131 if (!dev) | |
132 return; | |
133 RefreshDevice(dev); | |
134 udev_device_unref(dev); | |
135 } | |
136 | |
137 void GamepadPlatformDataFetcherLinux::OnFileCanWriteWithoutBlocking(int fd) { | |
138 } | |
139 | |
140 // Used during enumeration, and monitor notifications. | 114 // Used during enumeration, and monitor notifications. |
141 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { | 115 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { |
142 int index; | 116 int index; |
143 std::string node_path; | 117 std::string node_path; |
144 if (IsGamepad(dev, &index, &node_path)) { | 118 if (IsGamepad(dev, &index, &node_path)) { |
145 int& device_fd = device_fds_[index]; | 119 int& device_fd = device_fds_[index]; |
146 WebGamepad& pad = data_.items[index]; | 120 WebGamepad& pad = data_.items[index]; |
147 GamepadStandardMappingFunction& mapper = mappers_[index]; | 121 GamepadStandardMappingFunction& mapper = mappers_[index]; |
148 | 122 |
149 CloseFileDescriptorIfValid(device_fd); | 123 CloseFileDescriptorIfValid(device_fd); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id); | 190 TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id); |
217 string16 tmp16 = UTF8ToUTF16(id); | 191 string16 tmp16 = UTF8ToUTF16(id); |
218 memset(pad.id, 0, sizeof(pad.id)); | 192 memset(pad.id, 0, sizeof(pad.id)); |
219 tmp16.copy(pad.id, arraysize(pad.id) - 1); | 193 tmp16.copy(pad.id, arraysize(pad.id) - 1); |
220 | 194 |
221 pad.connected = true; | 195 pad.connected = true; |
222 } | 196 } |
223 } | 197 } |
224 | 198 |
225 void GamepadPlatformDataFetcherLinux::EnumerateDevices() { | 199 void GamepadPlatformDataFetcherLinux::EnumerateDevices() { |
226 udev_enumerate* enumerate = udev_enumerate_new(udev_); | 200 udev_enumerate* enumerate = udev_enumerate_new(udev_->udev_handle()); |
227 if (!enumerate) | 201 if (!enumerate) |
228 return; | 202 return; |
229 int ret = udev_enumerate_add_match_subsystem(enumerate, kInputSubsystem); | 203 int ret = udev_enumerate_add_match_subsystem(enumerate, kInputSubsystem); |
230 if (ret != 0) | 204 if (ret != 0) |
231 return; | 205 return; |
232 ret = udev_enumerate_scan_devices(enumerate); | 206 ret = udev_enumerate_scan_devices(enumerate); |
233 if (ret != 0) | 207 if (ret != 0) |
234 return; | 208 return; |
235 | 209 |
236 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); | 210 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); |
237 for (udev_list_entry* dev_list_entry = devices; | 211 for (udev_list_entry* dev_list_entry = devices; |
238 dev_list_entry != NULL; | 212 dev_list_entry != NULL; |
239 dev_list_entry = udev_list_entry_get_next(dev_list_entry)) { | 213 dev_list_entry = udev_list_entry_get_next(dev_list_entry)) { |
240 // Get the filename of the /sys entry for the device and create a | 214 // Get the filename of the /sys entry for the device and create a |
241 // udev_device object (dev) representing it | 215 // udev_device object (dev) representing it |
242 const char* path = udev_list_entry_get_name(dev_list_entry); | 216 const char* path = udev_list_entry_get_name(dev_list_entry); |
243 udev_device* dev = udev_device_new_from_syspath(udev_, path); | 217 udev_device* dev = udev_device_new_from_syspath(udev_->udev_handle(), path); |
244 if (!dev) | 218 if (!dev) |
245 continue; | 219 continue; |
246 RefreshDevice(dev); | 220 RefreshDevice(dev); |
247 udev_device_unref(dev); | 221 udev_device_unref(dev); |
248 } | 222 } |
249 // Free the enumerator object | 223 // Free the enumerator object |
250 udev_enumerate_unref(enumerate); | 224 udev_enumerate_unref(enumerate); |
251 } | 225 } |
252 | 226 |
253 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { | 227 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { |
(...skipping 21 matching lines...) Expand all Loading... |
275 continue; | 249 continue; |
276 pad.buttons[item] = event.value ? 1.0 : 0.0; | 250 pad.buttons[item] = event.value ? 1.0 : 0.0; |
277 if (item >= pad.buttonsLength) | 251 if (item >= pad.buttonsLength) |
278 pad.buttonsLength = item + 1; | 252 pad.buttonsLength = item + 1; |
279 } | 253 } |
280 pad.timestamp = event.time; | 254 pad.timestamp = event.time; |
281 } | 255 } |
282 } | 256 } |
283 | 257 |
284 } // namespace content | 258 } // namespace content |
OLD | NEW |