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> |
(...skipping 12 matching lines...) Expand all Loading... |
23 namespace { | 23 namespace { |
24 | 24 |
25 const char kInputSubsystem[] = "input"; | 25 const char kInputSubsystem[] = "input"; |
26 const float kMaxLinuxAxisValue = 32767.0; | 26 const float kMaxLinuxAxisValue = 32767.0; |
27 | 27 |
28 void CloseFileDescriptorIfValid(int fd) { | 28 void CloseFileDescriptorIfValid(int fd) { |
29 if (fd >= 0) | 29 if (fd >= 0) |
30 close(fd); | 30 close(fd); |
31 } | 31 } |
32 | 32 |
| 33 bool IsGamepad(udev_device* dev, int* index, std::string* path) { |
| 34 if (!udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK")) |
| 35 return false; |
| 36 |
| 37 const char* node_path = udev_device_get_devnode(dev); |
| 38 if (!node_path) |
| 39 return false; |
| 40 |
| 41 static const char kJoystickRoot[] = "/dev/input/js"; |
| 42 bool is_gamepad = StartsWithASCII(node_path, kJoystickRoot, true); |
| 43 if (!is_gamepad) |
| 44 return false; |
| 45 |
| 46 int tmp_idx = -1; |
| 47 const int base_len = sizeof(kJoystickRoot) - 1; |
| 48 base::StringPiece str(&node_path[base_len], strlen(node_path) - base_len); |
| 49 if (!base::StringToInt(str, &tmp_idx)) |
| 50 return false; |
| 51 if (tmp_idx < 0 || |
| 52 tmp_idx >= static_cast<int>(WebKit::WebGamepads::itemsLengthCap)) { |
| 53 return false; |
| 54 } |
| 55 *index = tmp_idx; |
| 56 *path = node_path; |
| 57 return true; |
| 58 } |
| 59 |
33 } // namespace | 60 } // namespace |
34 | 61 |
35 namespace content { | 62 namespace content { |
36 | 63 |
37 using WebKit::WebGamepad; | 64 using WebKit::WebGamepad; |
38 using WebKit::WebGamepads; | 65 using WebKit::WebGamepads; |
39 | 66 |
40 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { | 67 GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { |
41 for (size_t i = 0; i < arraysize(device_fds_); ++i) | 68 for (size_t i = 0; i < arraysize(device_fds_); ++i) |
42 device_fds_[i] = -1; | 69 device_fds_[i] = -1; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 udev_device* dev = udev_monitor_receive_device(monitor_); | 128 udev_device* dev = udev_monitor_receive_device(monitor_); |
102 if (!dev) | 129 if (!dev) |
103 return; | 130 return; |
104 RefreshDevice(dev); | 131 RefreshDevice(dev); |
105 udev_device_unref(dev); | 132 udev_device_unref(dev); |
106 } | 133 } |
107 | 134 |
108 void GamepadPlatformDataFetcherLinux::OnFileCanWriteWithoutBlocking(int fd) { | 135 void GamepadPlatformDataFetcherLinux::OnFileCanWriteWithoutBlocking(int fd) { |
109 } | 136 } |
110 | 137 |
111 bool GamepadPlatformDataFetcherLinux::IsGamepad(udev_device* dev, | |
112 int* index, | |
113 std::string* path) { | |
114 if (!udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK")) | |
115 return false; | |
116 | |
117 const char* node_path = udev_device_get_devnode(dev); | |
118 if (!node_path) | |
119 return false; | |
120 | |
121 static const char kJoystickRoot[] = "/dev/input/js"; | |
122 bool is_gamepad = StartsWithASCII(node_path, kJoystickRoot, true); | |
123 if (!is_gamepad) | |
124 return false; | |
125 | |
126 int tmp_idx = -1; | |
127 const int base_len = sizeof(kJoystickRoot) - 1; | |
128 base::StringPiece str(&node_path[base_len], strlen(node_path) - base_len); | |
129 if (!base::StringToInt(str, &tmp_idx)) | |
130 return false; | |
131 if (tmp_idx < 0 || tmp_idx >= static_cast<int>(WebGamepads::itemsLengthCap)) | |
132 return false; | |
133 *index = tmp_idx; | |
134 *path = node_path; | |
135 return true; | |
136 } | |
137 | |
138 // Used during enumeration, and monitor notifications. | 138 // Used during enumeration, and monitor notifications. |
139 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { | 139 void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { |
140 int index; | 140 int index; |
141 std::string node_path; | 141 std::string node_path; |
142 if (IsGamepad(dev, &index, &node_path)) { | 142 if (IsGamepad(dev, &index, &node_path)) { |
143 int& device_fd = device_fds_[index]; | 143 int& device_fd = device_fds_[index]; |
144 WebGamepad& pad = data_.items[index]; | 144 WebGamepad& pad = data_.items[index]; |
145 GamepadStandardMappingFunction& mapper = mappers_[index]; | 145 GamepadStandardMappingFunction& mapper = mappers_[index]; |
146 | 146 |
147 CloseFileDescriptorIfValid(device_fd); | 147 CloseFileDescriptorIfValid(device_fd); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 udev_enumerate_unref(enumerate); | 221 udev_enumerate_unref(enumerate); |
222 } | 222 } |
223 | 223 |
224 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { | 224 void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { |
225 // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/ | 225 // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/ |
226 if (index >= WebGamepads::itemsLengthCap) { | 226 if (index >= WebGamepads::itemsLengthCap) { |
227 CHECK(false); | 227 CHECK(false); |
228 return; | 228 return; |
229 } | 229 } |
230 | 230 |
231 int& fd = device_fds_[index]; | 231 const int& fd = device_fds_[index]; |
232 WebGamepad& pad = data_.items[index]; | 232 WebGamepad& pad = data_.items[index]; |
233 DCHECK_GE(fd, 0); | 233 DCHECK_GE(fd, 0); |
234 | 234 |
235 js_event event; | 235 js_event event; |
236 while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event)) > 0)) { | 236 while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event)) > 0)) { |
237 size_t item = event.number; | 237 size_t item = event.number; |
238 if (event.type & JS_EVENT_AXIS) { | 238 if (event.type & JS_EVENT_AXIS) { |
239 if (item >= WebGamepad::axesLengthCap) | 239 if (item >= WebGamepad::axesLengthCap) |
240 continue; | 240 continue; |
241 pad.axes[item] = event.value / kMaxLinuxAxisValue; | 241 pad.axes[item] = event.value / kMaxLinuxAxisValue; |
242 if (item >= pad.axesLength) | 242 if (item >= pad.axesLength) |
243 pad.axesLength = item + 1; | 243 pad.axesLength = item + 1; |
244 } else if (event.type & JS_EVENT_BUTTON) { | 244 } else if (event.type & JS_EVENT_BUTTON) { |
245 if (item >= WebGamepad::buttonsLengthCap) | 245 if (item >= WebGamepad::buttonsLengthCap) |
246 continue; | 246 continue; |
247 pad.buttons[item] = event.value ? 1.0 : 0.0; | 247 pad.buttons[item] = event.value ? 1.0 : 0.0; |
248 if (item >= pad.buttonsLength) | 248 if (item >= pad.buttonsLength) |
249 pad.buttonsLength = item + 1; | 249 pad.buttonsLength = item + 1; |
250 } | 250 } |
251 pad.timestamp = event.time; | 251 pad.timestamp = event.time; |
252 } | 252 } |
253 } | 253 } |
254 | 254 |
255 } // namespace content | 255 } // namespace content |
OLD | NEW |