You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
520 lines
12 KiB
C++
520 lines
12 KiB
C++
//
|
|
// Created by Matthew on 2023/12/27.
|
|
//
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
|
|
#include <climits>
|
|
|
|
#include "GPIOControl.h"
|
|
#include <LogThread.h>
|
|
|
|
#ifdef _DEBUG
|
|
#include <AndroidHelper.h>
|
|
#endif
|
|
|
|
#define IOT_PARAM_WRITE 0xAE
|
|
#define IOT_PARAM_READ 0xAF
|
|
|
|
std::mutex GpioControl::m_locker;
|
|
CSemaphore GpioControl::m_semaphore;
|
|
std::vector<GpioControl::ITEM> GpioControl::m_items;
|
|
std::thread GpioControl::m_thread;
|
|
bool GpioControl::m_exitSignal = false;
|
|
bool GpioControl::m_cameraPowerStatus = false;
|
|
|
|
size_t GpioControl::turnOnImpl(const IOT_PARAM& param)
|
|
{
|
|
size_t oldRef = 0;
|
|
size_t references = 1;
|
|
std::vector<ITEM>::iterator it;
|
|
int res = 0;
|
|
int fd = -1;
|
|
time_t now = time(NULL);
|
|
|
|
// check res???
|
|
for (it = m_items.begin(); it != m_items.end(); ++it)
|
|
{
|
|
if (it->cmd == param.cmd)
|
|
{
|
|
oldRef = it->references;
|
|
it->references++;
|
|
// it->closeTime = 0;
|
|
references = it->references;
|
|
if(it->openTime == 0)
|
|
it->openTime = now;
|
|
SetCamerastatus(it->cmd, true);
|
|
break;
|
|
}
|
|
}
|
|
if (it == m_items.end())
|
|
{
|
|
oldRef = 0;
|
|
ITEM item = {param.cmd, references, 0, 0, now};
|
|
m_items.push_back(item);
|
|
SetCamerastatus(param.cmd, true);
|
|
}
|
|
|
|
if (oldRef == 0)
|
|
{
|
|
fd = open(GPIO_NODE_MP, O_RDONLY);
|
|
if( fd > 0 )
|
|
{
|
|
res = ioctl(fd, IOT_PARAM_WRITE, ¶m);
|
|
close(fd);
|
|
#ifdef OUTPUT_DBG_INFO
|
|
XYLOG(XYLOG_SEVERITY_INFO, "setInt cmd=%d,value=%d,result=%d",param.cmd, param.value, param.result);
|
|
#endif
|
|
|
|
}
|
|
#ifdef _DEBUG
|
|
ALOGI("PWR TurnOn cmd=%d,result=%d ref=%u\r\n",param.cmd, param.result, (uint32_t)references);
|
|
#endif
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
}
|
|
|
|
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);
|
|
close(fd);
|
|
#ifdef OUTPUT_DBG_INFO
|
|
int realVal = getInt(param.cmd);
|
|
XYLOG(XYLOG_SEVERITY_INFO, "setInt cmd=%d,value=%d,result=%d RealVal=%d",param.cmd, param.value, param.result, realVal);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
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",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<int>& cmds)
|
|
{
|
|
IOT_PARAM param = { 0, 1, 0 };
|
|
// param.cmd = cmd;
|
|
// param.value = value;
|
|
|
|
std::vector<int>::const_iterator it;
|
|
m_locker.lock();
|
|
for (it = cmds.cbegin(); it != cmds.cend(); ++it)
|
|
{
|
|
if (*it == 0)
|
|
{
|
|
continue;
|
|
}
|
|
param.cmd = *it;
|
|
turnOnImpl(param);
|
|
}
|
|
m_locker.unlock();
|
|
|
|
return 0;
|
|
}
|
|
|
|
size_t GpioControl::TurnOffImmediately(int cmd)
|
|
{
|
|
time_t ts = time(NULL);
|
|
size_t ref = 0;
|
|
std::vector<ITEM>::iterator it;
|
|
m_locker.lock();
|
|
for (it = m_items.begin(); it != m_items.end(); ++it)
|
|
{
|
|
if (it->cmd == cmd)
|
|
{
|
|
ref = it->references;
|
|
it->closeCmds++;
|
|
it->closeTime = ts;
|
|
break;
|
|
}
|
|
}
|
|
m_locker.unlock();
|
|
m_semaphore.release();
|
|
#ifdef _DEBUG
|
|
ALOGI("PWR TurnOffNow cmd=%d ref=%u", cmd, (uint32_t)ref);
|
|
#endif
|
|
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<ITEM>::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();
|
|
#ifdef _DEBUG
|
|
ALOGI("PWR TurnOff cmd=%d ref=%u", cmd, (uint32_t)ref);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
size_t GpioControl::TurnOff(const std::vector<int>& cmds, uint32_t delayedCloseTime/* = 0*/)
|
|
{
|
|
time_t ts = 0;
|
|
if (delayedCloseTime > 0)
|
|
{
|
|
ts = time(NULL) + delayedCloseTime;
|
|
}
|
|
std::vector<ITEM>::iterator it;
|
|
std::vector<int>::const_reverse_iterator itCmd;
|
|
m_locker.lock();
|
|
// turnOnImpl(param);
|
|
for (itCmd = cmds.crbegin(); itCmd != cmds.crend(); ++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<std::pair<int, uint32_t> >& cmds)
|
|
{
|
|
time_t ts = time(NULL);
|
|
time_t ts2;
|
|
std::vector<ITEM>::iterator it;
|
|
std::vector<std::pair<int, uint32_t> >::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;
|
|
}
|
|
bool GpioControl::SetCamerastatus(int cmd, bool status)
|
|
{
|
|
#ifdef USING_N938
|
|
if(cmd == CMD_SET_PIC1_POWER)
|
|
m_cameraPowerStatus = status;
|
|
#endif
|
|
#ifdef USING_PLZ
|
|
if(cmd == CMD_SET_PTZ_PWR_ENABLE)
|
|
{
|
|
m_cameraPowerStatus = status;
|
|
}
|
|
|
|
#endif
|
|
return true;
|
|
}
|
|
bool GpioControl::GetCamerastatus()
|
|
{
|
|
return m_cameraPowerStatus;
|
|
}
|
|
|
|
bool GpioControl::GetSelftestStatus(time_t wait_time)
|
|
{
|
|
int cmd = 0;
|
|
#ifdef USING_N938
|
|
cmd = CMD_SET_PIC1_POWER;
|
|
#endif
|
|
#ifdef USING_PLZ
|
|
cmd = CMD_SET_PTZ_PWR_ENABLE;
|
|
#endif
|
|
time_t now = time(NULL);
|
|
std::vector<ITEM>::iterator it;
|
|
for (it = m_items.begin(); it != m_items.end(); ++it)
|
|
{
|
|
if (it->cmd == cmd && it->openTime!=0 && (now - it->openTime >= wait_time))
|
|
{
|
|
return true;//自检完成
|
|
}
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
time_t GpioControl::GetSelfTestRemain(time_t wait_time)
|
|
{
|
|
int cmd = 0;
|
|
#ifdef USING_N938
|
|
cmd = CMD_SET_PIC1_POWER;
|
|
#endif
|
|
#ifdef USING_PLZ
|
|
cmd = CMD_SET_PTZ_PWR_ENABLE;
|
|
#endif
|
|
time_t now = time(NULL);
|
|
std::vector<ITEM>::iterator it;
|
|
for (it = m_items.begin(); it != m_items.end(); ++it)
|
|
{
|
|
if (it->cmd == cmd && it->openTime!=0 && (now - it->openTime <= wait_time))
|
|
{
|
|
time_t remaintime =wait_time - (now - it->openTime);
|
|
return remaintime;//自检完成
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void GpioControl::PowerControlThreadProc()
|
|
{
|
|
time_t ts = 0;
|
|
std::vector<ITEM>::iterator it;
|
|
std::vector<int> items;
|
|
time_t minDelayTime = 0;
|
|
time_t delayTime = 0;
|
|
int fd = -1;
|
|
int res = -1;
|
|
m_cameraPowerStatus = 0;
|
|
|
|
while(1)
|
|
{
|
|
// Check if there is close cmd
|
|
ts = time(NULL);
|
|
|
|
minDelayTime = std::numeric_limits<time_t>::max();
|
|
|
|
m_locker.lock();
|
|
for (it = m_items.begin(); it != m_items.end(); ++it)
|
|
{
|
|
if (it->references == 0 && it->closeCmds == 0 && it->closeTime == 0)
|
|
{
|
|
#ifdef _DEBUG
|
|
ALOGI("PWR THREAD cmd=%d ref=%u closeCmds=%u", it->cmd, (uint32_t)it->references, (uint32_t)it->closeCmds);
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
if (it->closeCmds > 0)
|
|
{
|
|
if (it->references <= it->closeCmds)
|
|
{
|
|
it->references = 0;
|
|
}
|
|
else
|
|
{
|
|
it->references -= it->closeCmds;
|
|
if(it->references < 0)
|
|
it->references = 0;
|
|
}
|
|
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;
|
|
it->openTime = 0;
|
|
#ifdef _DEBUG
|
|
ALOGI("PWR THREAD DO TurnOff cmd=%d", it->cmd);
|
|
#endif
|
|
SetCamerastatus(it->cmd, false);
|
|
}
|
|
else
|
|
{
|
|
// Check Time
|
|
delayTime = ts - it->closeTime;
|
|
if (delayTime < minDelayTime)
|
|
{
|
|
minDelayTime = delayTime;
|
|
}
|
|
}
|
|
}
|
|
#ifdef _DEBUG
|
|
ALOGI("PWR THREAD cmd=%d ref=%u closeCmds=%u", it->cmd, (uint32_t)it->references, (uint32_t)it->closeCmds);
|
|
#endif
|
|
}
|
|
m_locker.unlock();
|
|
|
|
if (minDelayTime < std::numeric_limits<time_t>::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();
|
|
}
|
|
|
|
|
|
|