// // Created by Matthew on 2023/12/27. // #include #include #include #include #include #include #include #include #include #include "GPIOControl.h" #ifdef _DEBUG #include #endif #define IOT_PARAM_WRITE 0xAE #define IOT_PARAM_READ 0xAF std::mutex GpioControl::m_locker; CSemaphore GpioControl::m_semaphore; std::vector GpioControl::m_items; std::thread GpioControl::m_thread; bool GpioControl::m_exitSignal = false; size_t GpioControl::turnOnImpl(const IOT_PARAM& param) { size_t references = 1; std::vector::iterator it; int res = 0; int fd = -1; fd = open(GPIO_NODE_MP, O_RDONLY); if( fd > 0 ) { res = ioctl(fd, IOT_PARAM_WRITE, ¶m); close(fd); // check res??? for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == param.cmd) { it->references++; it->closeTime = 0; references = it->references; break; } } if (it == m_items.end()) { ITEM item = {param.cmd, references, 0, 0}; m_items.push_back(item); } } return references; } void GpioControl::setInt(int cmd, int value) { IOT_PARAM param = { cmd, value, 0 }; // param.cmd = cmd; // param.value = value; int fd = open(GPIO_NODE_MP, O_RDONLY); if (fd > 0) { int res = ioctl(fd, IOT_PARAM_WRITE, ¶m); #ifdef _DEBUG ALOGI("setInt cmd=%d,value=%d,result=%d\r\n",param.cmd, param.value, param.result); #endif close(fd); } } int GpioControl::getInt(int cmd) { int fd = open(GPIO_NODE_MP, O_RDONLY); // LOGE("get_int fd=%d,cmd=%d\r\n",fd, cmd); if( fd > 0 ) { IOT_PARAM param; param.cmd = cmd; ioctl(fd, IOT_PARAM_READ, ¶m); #ifdef _DEBUG ALOGI("getInt cmd=%d,value=%d,result=%d\r\n",param.cmd, param.value, param.result); #endif close(fd); return param.value; } return -1; } void GpioControl::setLong(int cmd, long value) { int fd = open(GPIO_NODE_MP, O_RDONLY); IOT_PARAM param; param.cmd = cmd; param.value2 = value; // LOGE("set_long fd=%d,cmd=%d,value2=%ld\r\n",fd, param.cmd, param.value2); if( fd > 0 ) { ioctl(fd, IOT_PARAM_WRITE, ¶m); // LOGE("set_long22 cmd=%d,value2=%ld,result=%d\r\n",param.cmd, param.value2, param.result); close(fd); } } long GpioControl::getLong(int cmd) { int fd = open(GPIO_NODE_MP, O_RDONLY); // LOGE("get_long fd=%d,cmd=%d\r\n",fd, cmd); if( fd > 0 ) { IOT_PARAM param; param.cmd = cmd; ioctl(fd, IOT_PARAM_READ, ¶m); // LOGE("get_long22 cmd=%d,value2=%ld,result=%d\r\n",param.cmd, param.value2, param.result); close(fd); return param.value2; } return -1; } void GpioControl::setString(int cmd, const std::string& value) { IOT_PARAM param; int fd = open(GPIO_NODE_MP, O_RDONLY); int len = MAX_STRING_LEN < value.size() ? MAX_STRING_LEN : value.size(); param.cmd = cmd; memset(param.str, 0, MAX_STRING_LEN); memcpy(param.str, value.c_str(), len); // LOGE("set_string fd=%d,cmd=%d,str=%s\r\n",fd, param.cmd, param.str); if( fd > 0 ) { ioctl(fd, IOT_PARAM_WRITE, ¶m); // LOGE("set_string22 cmd=%d,str=%s,result=%d\r\n",param.cmd, param.str, param.result); close(fd); } return; } std::string GpioControl::getString(int cmd) { int fd = open(GPIO_NODE_MP, O_RDONLY); // LOGE("get_string fd=%d,cmd=%d\r\n",fd, cmd); if( fd > 0 ) { IOT_PARAM param; param.cmd = cmd; ioctl(fd, IOT_PARAM_READ, ¶m); // LOGE("get_string22 cmd=%d,str=%s,result=%d\r\n",param.cmd, param.str, param.result); close(fd); return std::string(param.str); } return ""; } /////////////////////////// Power Control ///////////////////////////////// size_t GpioControl::TurnOn(int cmd) { IOT_PARAM param = { cmd, 1, 0 }; // param.cmd = cmd; // param.value = value; m_locker.lock(); size_t ref = turnOnImpl(param); m_locker.unlock(); return ref; } size_t GpioControl::TurnOn(const std::vector& cmds) { IOT_PARAM param = { 0, 1, 0 }; // param.cmd = cmd; // param.value = value; std::vector::const_iterator it; m_locker.lock(); for (it = cmds.cbegin(); it != cmds.cend(); ++it) { param.cmd = *it; turnOnImpl(param); } m_locker.unlock(); return 0; } size_t GpioControl::TurnOff(int cmd, uint32_t delayedCloseTime/* = 0*/) { time_t ts = 0; if (delayedCloseTime > 0) { ts = time(NULL) + delayedCloseTime; } size_t ref = 0; std::vector::iterator it; m_locker.lock(); for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == cmd) { ref = it->references; it->closeCmds++; if (ts > it->closeTime) { it->closeTime = ts; } break; } } m_locker.unlock(); m_semaphore.release(); return 0; } size_t GpioControl::TurnOff(const std::vector& cmds, uint32_t delayedCloseTime/* = 0*/) { time_t ts = 0; if (delayedCloseTime > 0) { ts = time(NULL) + delayedCloseTime; } std::vector::iterator it; std::vector::const_iterator itCmd; m_locker.lock(); // turnOnImpl(param); for (itCmd = cmds.cbegin(); itCmd != cmds.end(); ++itCmd) { for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == *itCmd) { it->closeCmds++; if (ts > it->closeTime) { it->closeTime = ts; } break; } } } m_locker.unlock(); m_semaphore.release(); return 0; } size_t GpioControl::TurnOff(const std::vector >& cmds) { time_t ts = time(NULL); time_t ts2; std::vector::iterator it; std::vector >::const_iterator itCmd; m_locker.lock(); for (itCmd = cmds.cbegin(); itCmd != cmds.end(); ++itCmd) { for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == itCmd->first) { it->closeCmds++; if (itCmd->second != 0) { ts2 = itCmd->second + ts; if (ts2 > it->closeTime) { it->closeTime = ts2; } } break; } } } m_locker.unlock(); m_semaphore.release(); return 0; } void GpioControl::PowerControlThreadProc() { time_t ts = 0; std::vector::iterator it; std::vector items; time_t minDelayTime = 0; time_t delayTime = 0; int fd = -1; int res = -1; while(1) { // Check if there is close cmd ts = time(NULL); minDelayTime = std::numeric_limits::max(); m_locker.lock(); for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->references == 0 && it->closeCmds == 0 && it->closeTime == 0) { continue; } if (it->closeCmds > 0) { if (it->references <= it->closeCmds) { it->references = 0; } else { it->references -= it->closeCmds; } it->closeCmds = 0; } if (it->references == 0) { // Should turn off the power if ((it->closeTime == 0) || (it->closeTime <= ts)) { // close it directly setInt(it->cmd, 0); it->closeTime = 0; } else { // Check Time delayTime = ts - it->closeTime; if (delayTime < minDelayTime) { minDelayTime = delayTime; } } } } m_locker.unlock(); if (minDelayTime < std::numeric_limits::max()) { m_semaphore.try_acquire_for(std::chrono::seconds(1)); } else { m_semaphore.acquire(); } if (m_exitSignal) { break; } } } bool GpioControl::Startup() { // if (m_thread.) m_exitSignal = false; m_thread = std::thread(PowerControlThreadProc); #ifdef _DEBUG pthread_t nativeHandle = m_thread.native_handle(); pthread_setname_np(nativeHandle, "gpioclose"); #endif return true; } void GpioControl::Stop() { // Notify m_exitSignal = true; m_semaphore.release(); m_thread.detach(); }