1 /*
2  * Copyright (C) 2021 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 #pragma once
17 
18 #include <fcntl.h>
19 #include <linux/gpio.h>
20 #include <log/log.h>
21 
22 #include <map>
23 
24 #include "Vibrator.h"
25 #include "utils.h"
26 
27 namespace aidl {
28 namespace android {
29 namespace hardware {
30 namespace vibrator {
31 
32 class VibMgrHwApi : public Vibrator::HwGPIO {
33   private:
34     const uint32_t DEBUG_GPI_PIN = UINT16_MAX;
35     const uint32_t DEBUG_GPI_PIN_SHIFT = UINT16_MAX;
36     std::string mPropertyPrefix;
37     uint32_t mGPIOPin;
38     uint32_t mGPIOShift;
39     struct gpiohandle_request mRq;
40 
41   public:
Create()42     static std::unique_ptr<VibMgrHwApi> Create() {
43         auto hwapi = std::unique_ptr<VibMgrHwApi>(new VibMgrHwApi());
44         return hwapi;
45     }
getGPIO()46     bool getGPIO() override {
47         auto propertyPrefix = std::getenv("PROPERTY_PREFIX");
48 
49         if (propertyPrefix != NULL) {
50             mPropertyPrefix = std::string(propertyPrefix);
51         } else {
52             ALOGE("GetGPIO: Failed get property prefix!");
53             return false;
54         }
55         mGPIOPin = utils::getProperty(mPropertyPrefix + "gpio.num", DEBUG_GPI_PIN);
56         if (mGPIOPin == DEBUG_GPI_PIN) {
57             ALOGE("GetGPIO: Failed to get the GPIO num: %s", strerror(errno));
58             return false;
59         }
60         mGPIOShift = utils::getProperty(mPropertyPrefix + "gpio.shift", DEBUG_GPI_PIN_SHIFT);
61 
62         if (mGPIOShift == DEBUG_GPI_PIN_SHIFT) {
63             ALOGE("GetGPIO: Failed to get the GPIO shift num: %s", strerror(errno));
64             return false;
65         }
66 
67         return true;
68     }
initGPIO()69     bool initGPIO() override {
70         const auto gpio_dev = std::string() + "/dev/gpiochip" + std::to_string(mGPIOPin);
71         int fd = open(gpio_dev.c_str(), O_CREAT | O_WRONLY, 0777);
72         if (fd < 0) {
73             ALOGE("InitGPIO: Unable to open gpio dev: %s", strerror(errno));
74             return false;
75         }
76 
77         mRq.lineoffsets[0] = mGPIOShift;
78         mRq.lines = 1;
79         mRq.flags = GPIOHANDLE_REQUEST_OUTPUT;
80 
81         int ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &mRq);
82         if (ret == -1) {
83             ALOGE("InitGPIO: Unable to line handle from ioctl : %s", strerror(errno));
84             close(fd);
85             return false;
86         }
87         if (close(fd) == -1) {
88             ALOGE("Failed to close GPIO char dev");
89             return false;
90         }
91         // Reset gpio status to LOW
92         struct gpiohandle_data data;
93         data.values[0] = 0;
94 
95         ret = ioctl(mRq.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
96         if (ret == -1) {
97             ALOGE("InitGPIO: Unable to set line value using ioctl : %s", strerror(errno));
98             close(mRq.fd);
99             return false;
100         }
101         return true;
102     }
setGPIOOutput(bool value)103     bool setGPIOOutput(bool value) override {
104         struct gpiohandle_data data;
105         data.values[0] = value;
106 
107         int ret = ioctl(mRq.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
108         if (ret == -1) {
109             ALOGE("SetTrigger: Unable to set line value using ioctl : %s", strerror(errno));
110             close(mRq.fd);
111             return false;
112         }
113 
114         return true;
115     }
debug(int fd)116     void debug(int fd) override { ALOGD("Debug: %d", fd); }
117 
118   private:
VibMgrHwApi()119     VibMgrHwApi() { ALOGD("Constructor"); }
120 };
121 
122 }  // namespace vibrator
123 }  // namespace hardware
124 }  // namespace android
125 }  // namespace aidl
126