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