blob: cb35c9e89341bf578a9feebdd4f34a2ea6c7d25c [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <base/logging.h>
#include <cstddef>
#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include "touch_keyboard/haptic/ff_driver.h"
namespace {
// This value drive the vibrator at max strength.
constexpr int kMaxDriverInput = 0x7f;
}
namespace touch_keyboard {
FFDriver::FFDriver() : fd_ {-1} {}
FFDriver::~FFDriver() {
CloseFDIfValid();
}
// Try to open the device, will return false if failed.
bool FFDriver::Init(const std::string& device_path) {
// Close the fd if previously inited.
CloseFDIfValid();
fd_ = open(device_path.c_str(), O_RDWR | O_CLOEXEC);
if (fd_ == -1) {
PLOG(ERROR) << "Fail to open haptic device";
return false;
}
return true;
}
int FFDriver::UploadEffect(float magnitude, int time_ms) {
if (fd_ == -1) {
PLOG(ERROR) << "Cannot upload effect cause FFDriver is not inited";
return -1;
}
struct ff_effect effect;
// Set up the effect with parameters.
effect.type = FF_RUMBLE;
effect.id = -1;
effect.u.rumble.strong_magnitude =
static_cast<int>(magnitude * kMaxDriverInput);
effect.u.rumble.weak_magnitude = 0;
effect.replay.length = time_ms;
effect.replay.delay = 0;
if (ioctl(fd_, EVIOCSFF, &effect) == -1) {
PLOG(ERROR) << "Fail to upload effect";
return -1;
}
return effect.id;
}
bool FFDriver::PlayEffect(int id) {
if (fd_ == -1) {
PLOG(ERROR) << "Cannot play effect cause FFDriver is not inited";
return false;
}
if (id < 0) {
PLOG(ERROR) << "Invalid effect id";
return false;
}
struct input_event play;
memset(&play, 0, sizeof(play));
play.type = EV_FF;
play.code = id;
play.value = 1;
if (write(fd_, (const void*) &play, sizeof(play)) != sizeof(play)) {
PLOG(ERROR) << "Fail to play effect";
return false;
}
return true;
}
void FFDriver::CloseFDIfValid() {
if (fd_ != -1) {
close(fd_);
}
}
} // namespace touch_keyboard