blob: c86e99c2443441c489e5d739291736135fbfa5ac [file] [log] [blame]
Caleb Connollyc445fab2021-08-11 14:42:57 +01001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef ANDROID_HARDWARE_VIBRATOR_V1_1_VIBRATOR_H
17#define ANDROID_HARDWARE_VIBRATOR_V1_1_VIBRATOR_H
18
19#include <android/hardware/vibrator/1.1/IVibrator.h>
20#include <hidl/Status.h>
21
22#include <linux/input.h>
23
24#include <fstream>
Caleb Connolly542816b2021-08-12 15:31:07 +010025#include <map>
Caleb Connollyc445fab2021-08-11 14:42:57 +010026
27// Borrowed from linuxconsole/utils/bitmaskros.h
28/* Number of bits for 1 unsigned char */
29#define nBitsPerUchar (sizeof(unsigned char) * 8)
30/* Index=Offset of given bit in 1 unsigned char */
31#define bitOffsetInUchar(bit) ((bit)%nBitsPerUchar)
32/* Index=Offset of the unsigned char associated to the bit
33 * at the given index=offset
34 */
35#define ucharIndexForBit(bit) ((bit)/nBitsPerUchar)
36/* Test the bit with given index=offset in an unsigned char array */
37#define testBit(bit, array) ((array[ucharIndexForBit(bit)] >> bitOffsetInUchar(bit)) & 1)
38
Caleb Connolly542816b2021-08-12 15:31:07 +010039/*
40 * Builder for ff_effect struct.
41 * We don't bother using weak_magnitude here as most hardware
42 * doesn't have any way to differentiate strong / weak haptics
43 */
44#define FF_EFFECT(rumbleStrenth) \
45 { \
46 .type = FF_RUMBLE, \
47 .id = -1, \
48 .direction = 0, \
49 .trigger = { .button = 0, .interval = 0, }, \
50 .replay = { .length = 0, .delay = 0, }, \
51 .u = { \
52 .rumble = { \
53 .strong_magnitude = rumbleStrenth, \
54 .weak_magnitude = 0, \
55 }, \
56 }, \
57 }
58
Caleb Connollyc445fab2021-08-11 14:42:57 +010059namespace android {
60namespace hardware {
61namespace vibrator {
62namespace V1_1 {
63namespace implementation {
64
65class Vibrator : public IVibrator {
66public:
Caleb Connolly542816b2021-08-12 15:31:07 +010067 Vibrator(std::string mInputDevPath);
Caleb Connollyc445fab2021-08-11 14:42:57 +010068
Caleb Connolly542816b2021-08-12 15:31:07 +010069 // Methods from ::android::hardware::vibrator::V1_0::IVibrator follow.
70 using Status = ::android::hardware::vibrator::V1_0::Status;
71 Return<Status> on(uint32_t timeoutMs) override;
72 Return<Status> off() override;
73 Return<bool> supportsAmplitudeControl() override;
74 Return<Status> setAmplitude(uint8_t amplitude) override;
Caleb Connollyc445fab2021-08-11 14:42:57 +010075
Caleb Connolly542816b2021-08-12 15:31:07 +010076 using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength;
77 Return<void> perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb)
78 override;
79 Return<void> perform_1_1(Effect_1_1 effect, EffectStrength strength, perform_cb _hidl_cb)
80 override;
Caleb Connollyc445fab2021-08-11 14:42:57 +010081
82private:
Caleb Connolly542816b2021-08-12 15:31:07 +010083 ~Vibrator();
84 void uploadEffectToKernel(struct ff_effect*);
85 void deleteEffectFromKernel(struct ff_effect*);
86 int openInputDev();
87 template <typename T>
88 Return<void> performWrapper(T effect, EffectStrength strength, perform_cb _hidl_cb);
89 Return<void> performEffect(Effect_1_1 effect, EffectStrength strength, perform_cb _hidl_cb);
90 std::string mInputDevPath;
91 int mfd;
92 int mActiveEffectId;
Caleb Connolly9cf6ac12021-10-29 20:36:23 +010093 // If the haptics device path is invalid
94 // the just stub all behaviour. Otherwise
95 // the device will fail to boot because the haptics
96 // service keeps crashing.
97 bool mIsStub;
Caleb Connolly542816b2021-08-12 15:31:07 +010098 // Look up table of effects by type and strength
99 std::map<int, struct ff_effect> mEffects;
Caleb Connollyc445fab2021-08-11 14:42:57 +0100100
101};
102
103} // namespace implementation
104} // namespace V1_1
105} // namespace vibrator
106} // namespace hardware
107} // namespace android
108
109class FileDescGuard {
Caleb Connolly542816b2021-08-12 15:31:07 +0100110 public:
111 FileDescGuard(int fd) : m_fd(fd) {}
Caleb Connollyc445fab2021-08-11 14:42:57 +0100112
Caleb Connolly542816b2021-08-12 15:31:07 +0100113 ~FileDescGuard() {
114 if (close(m_fd) != 0)
115 {
116 ALOGE("CA:: Failed to close fd %d, errno = %d", m_fd, errno);
117 }
118 }
119 private:
120 int m_fd = -1;
Caleb Connollyc445fab2021-08-11 14:42:57 +0100121};
122
123#endif // ANDROID_HARDWARE_VIBRATOR_V1_1_VIBRATOR_H