#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "device/gamepad/gamepad_device_linux.h"
#include <fcntl.h>
#include <limits.h>
#include <linux/hidraw.h>
#include <linux/input.h>
#include <linux/joystick.h>
#include <sys/ioctl.h>
#include <string_view>
#include "base/containers/fixed_flat_set.h"
#include "base/functional/callback_helpers.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "device/gamepad/dualshock4_controller.h"
#include "device/gamepad/gamepad_data_fetcher.h"
#include "device/gamepad/hid_haptic_gamepad.h"
#include "device/gamepad/hid_writer_linux.h"
#include "device/gamepad/xbox_hid_controller.h"
#include "device/udev_linux/udev.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/permission_broker/permission_broker_client.h"
#endif
namespace device {
namespace {
const char kInputSubsystem[] = …;
const char kUsbSubsystem[] = …;
const char kUsbDeviceType[] = …;
const float kMaxLinuxAxisValue = …;
const int kInvalidEffectId = …;
const uint16_t kRumbleMagnitudeMax = …;
const size_t kSpecialKeys[] = …;
const size_t kSpecialKeysLen = …;
#define LONG_BITS …
#define BITS_TO_LONGS(x) …
static inline bool test_bit(int bit, const unsigned long* data) { … }
GamepadBusType GetEvdevBusType(const base::ScopedFD& fd) { … }
bool HasRumbleCapability(const base::ScopedFD& fd) { … }
size_t CheckSpecialKeys(const base::ScopedFD& fd,
std::vector<bool>* has_special_key) { … }
bool GetHidrawDevinfo(const base::ScopedFD& fd,
GamepadBusType* bus_type,
std::string* product_name,
uint16_t* vendor_id,
uint16_t* product_id) { … }
int StoreRumbleEffect(const base::ScopedFD& fd,
int effect_id,
uint16_t duration,
uint16_t start_delay,
uint16_t strong_magnitude,
uint16_t weak_magnitude) { … }
void DestroyEffect(const base::ScopedFD& fd, int effect_id) { … }
bool StartOrStopEffect(const base::ScopedFD& fd, int effect_id, bool do_start) { … }
uint16_t HexStringToUInt16WithDefault(std::string_view input,
uint16_t default_value) { … }
#if BUILDFLAG(IS_CHROMEOS)
void OnOpenPathSuccess(
chromeos::PermissionBrokerClient::OpenPathCallback callback,
scoped_refptr<base::SequencedTaskRunner> polling_runner,
base::ScopedFD fd) {
polling_runner->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), std::move(fd)));
}
void OnOpenPathError(
chromeos::PermissionBrokerClient::OpenPathCallback callback,
scoped_refptr<base::SequencedTaskRunner> polling_runner,
const std::string& error_name,
const std::string& error_message) {
polling_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), base::ScopedFD()));
}
void OpenPathWithPermissionBroker(
const std::string& path,
chromeos::PermissionBrokerClient::OpenPathCallback callback,
scoped_refptr<base::SequencedTaskRunner> polling_runner) {
auto* client = chromeos::PermissionBrokerClient::Get();
DCHECK(client) << "Could not get permission broker client.";
auto split_callback = base::SplitOnceCallback(std::move(callback));
auto success_callback = base::BindOnce(
&OnOpenPathSuccess, std::move(split_callback.first), polling_runner);
auto error_callback = base::BindOnce(
&OnOpenPathError, std::move(split_callback.second), polling_runner);
client->OpenPath(path, std::move(success_callback),
std::move(error_callback));
}
#endif
std::string_view ToStringView(const char* str) { … }
}
GamepadDeviceLinux::GamepadDeviceLinux(
const std::string& syspath_prefix,
scoped_refptr<base::SequencedTaskRunner> dbus_runner)
: … { … }
GamepadDeviceLinux::~GamepadDeviceLinux() = default;
void GamepadDeviceLinux::DoShutdown() { … }
bool GamepadDeviceLinux::IsEmpty() const { … }
bool GamepadDeviceLinux::SupportsVibration() const { … }
void GamepadDeviceLinux::ReadPadState(Gamepad* pad) { … }
bool GamepadDeviceLinux::ReadJoydevState(Gamepad* pad) { … }
void GamepadDeviceLinux::InitializeEvdevSpecialKeys() { … }
bool GamepadDeviceLinux::ReadEvdevSpecialKeys(Gamepad* pad) { … }
GamepadStandardMappingFunction GamepadDeviceLinux::GetMappingFunction() const { … }
bool GamepadDeviceLinux::IsSameDevice(const UdevGamepadLinux& pad_info) { … }
bool GamepadDeviceLinux::OpenJoydevNode(const UdevGamepadLinux& pad_info,
udev_device* device) { … }
void GamepadDeviceLinux::CloseJoydevNode() { … }
bool GamepadDeviceLinux::OpenEvdevNode(const UdevGamepadLinux& pad_info) { … }
void GamepadDeviceLinux::CloseEvdevNode() { … }
void GamepadDeviceLinux::OpenHidrawNode(const UdevGamepadLinux& pad_info,
OpenDeviceNodeCallback callback) { … }
void GamepadDeviceLinux::OnOpenHidrawNodeComplete(
OpenDeviceNodeCallback callback,
base::ScopedFD fd) { … }
void GamepadDeviceLinux::InitializeHidraw(base::ScopedFD fd) { … }
void GamepadDeviceLinux::CloseHidrawNode() { … }
void GamepadDeviceLinux::SetVibration(
mojom::GamepadEffectParametersPtr params) { … }
void GamepadDeviceLinux::SetZeroVibration() { … }
base::WeakPtr<AbstractHapticGamepad> GamepadDeviceLinux::GetWeakPtr() { … }
}