| 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 |