Skip to content

Commit

Permalink
modify Key::Key to init all keys when no device is specified
Browse files Browse the repository at this point in the history
  • Loading branch information
916BGAI committed Nov 8, 2024
1 parent 677c892 commit 324b0d4
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 66 deletions.
8 changes: 4 additions & 4 deletions components/peripheral/include/maix_key.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ namespace maix::peripheral::key
* callback will be called with args key(key.Keys) and value(key.State).
* If set to null, you can get key value by read() function.
* This callback called in a standalone thread, so you can block a while in callback, and you should be carefully when operate shared data.
* @param open auto open device in constructor, if false, you need call open() to open device
* @param device The key device to use. Default is "/dev/input/event0".
* Set it to "/dev/input/powerkey" to use the power key on the MaixCam-Pro.
* @param open auto open device in constructor, if false, you need call open() to open device.
* @param device Specifies the input device to use. The default initializes all keys,
* for a specific device, provide the path (e.g., "/dev/input/device").
* @param long_press_time The duration (in milliseconds) from pressing the key to triggering the long press event. Default is 2000ms.
* @maixpy maix.peripheral.key.Key.__init__
* @maixcdk maix.peripheral.key.Key.Key
Expand Down Expand Up @@ -113,7 +113,7 @@ namespace maix::peripheral::key
int long_press_time(int press_time = -1);

private:
int _fd;
std::vector<int> _fds;
std::string _device;
std::function<void(int, int)> _callback;
void *_data;
Expand Down
95 changes: 65 additions & 30 deletions components/peripheral/port/linux/maix_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace maix::peripheral::key
int long_press_time;
bool read_thread_exit;
bool read_thread_need_exit;
std::vector<int> fds;
Key *key;
std::function<void(int, int)> callback;
};
Expand All @@ -81,19 +82,24 @@ namespace maix::peripheral::key
return;
}
ev.events = EPOLLIN;
ev.data.fd = data->fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, data->fd, &ev) < 0)
{
data->read_thread_exit = true;
log::error("epoll_ctl add failed: %s", strerror(errno));
return;
for (int fd : data->fds) {
if (fd > 0) {
ev.data.fd = fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
log::error("epoll_ctl add failed for fd %d: %s", fd, strerror(errno));
data->read_thread_exit = true;
close(epoll_fd);
return;
}
}
}
int fail_count = 0;
while (!data->read_thread_need_exit && !app::need_exit())
{
int nfds = epoll_wait(epoll_fd, &ev, 1, 200);
if (nfds > 0)
{
data->fd = ev.data.fd;
err::Err e = data->key->read(key, value);
if (e == err::Err::ERR_NONE)
{
Expand Down Expand Up @@ -134,7 +140,6 @@ namespace maix::peripheral::key
if(_key_defult_listener)
rm_default_listener();
this->_callback = callback;
this->_fd = -1;
this->_data = nullptr;
this->_device = "";
Port_Data *data = new Port_Data();
Expand Down Expand Up @@ -185,37 +190,49 @@ namespace maix::peripheral::key

err::Err Key::open()
{
if (this->_fd > 0)
if (this->_fds.size())
{
this->close();
}
bool is_open = false;
if(!this->_device.empty())
{
this->_fd = ::open(_device.c_str(), O_RDONLY);
if (this->_fd > 0)
int fd = ::open(_device.c_str(), O_RDONLY);
if (fd > 0) {
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
this->_fds.push_back(fd);
is_open = true;
}
}
if(!is_open)
{
this->_fd = ::open(KEY_DEVICE, O_RDONLY);
if (this->_fd < 0)
int fd = ::open(KEY_DEVICE, O_RDONLY);
if (fd < 0)
{
this->_fd = ::open(KEY_DEVICE2, O_RDONLY);
if (this->_fd < 0)
{
return err::Err::ERR_NOT_FOUND;
std::vector<std::string> key_devices = {{KEY_DEVICE2}};
for (const auto& device : key_devices) {
int fd = ::open(device.c_str(), O_RDONLY);
if (fd == -1) {
log::error(("Failed to open device: " + device).c_str());
this->_device = device;
return err::Err::ERR_NOT_FOUND;
}
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
this->_fds.push_back(fd);
}
} else {
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
this->_fds.push_back(fd);
}
}
// set non-blocking
int flags = fcntl(this->_fd, F_GETFL, 0);
fcntl(this->_fd, F_SETFL, flags | O_NONBLOCK);
if (this->_callback)
{
// new thread to read key
Port_Data *data = (Port_Data *)this->_data;
data->fd = this->_fd;
data->fds = this->_fds;
data->read_thread_exit = false;
data->read_thread_need_exit = false;
data->thread = new thread::Thread(_read_process, this->_data);
Expand All @@ -226,14 +243,25 @@ namespace maix::peripheral::key

err::Err Key::read(int &key, int &value)
{
if (this->_fd < 0)
Port_Data *data = (Port_Data *)this->_data;
if (this->_fds.size() == 0)
{
return err::Err::ERR_NOT_OPEN;
}
struct input_event ev;
int ret;
while (1)
{
int ret = ::read(this->_fd, &ev, sizeof(struct input_event));
if (this->_callback == nullptr) {
for (int fd : this->_fds)
{
ret = ::read(fd, &ev, sizeof(struct input_event));
if (ret > 0 && ev.code != 0)
break;
}
} else {
ret = ::read(data->fd, &ev, sizeof(struct input_event));
}
if (ret < 0)
{
if(errno == EAGAIN || errno == EWOULDBLOCK)
Expand Down Expand Up @@ -277,22 +305,29 @@ namespace maix::peripheral::key
{
Port_Data *data = (Port_Data *)this->_data;
data->read_thread_need_exit = true;
if (this->_fd > 0)

bool err = false;
for (int &fd : this->_fds)
{
int ret = ::close(this->_fd);
this->_fd = -1;
if (ret < 0)
if (fd > 0)
{
return err::Err::ERR_IO;
int ret = ::close(fd);
if (ret < 0)
{
log::error("Failed to close fd %d: %s", fd, strerror(errno));
err = true;
}
fd = -1;
}
}
this->_fd = -1;
return err::Err::ERR_NONE;

this->_fds.clear();
return err ? err::Err::ERR_IO : err::Err::ERR_NONE;
}

bool Key::is_opened()
{
return this->_fd > 0;
return this->_fds.size() > 0;
}

int Key::long_press_time(int press_time)
Expand Down
105 changes: 73 additions & 32 deletions components/peripheral/port/maixcam/maix_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace maix::peripheral::key
bool read_thread_need_exit;
bool powerkey_thread_exit;
bool powerkey_thread_need_exit;
std::vector<int> fds;
Key *key;
std::function<void(int, int)> callback;
};
Expand All @@ -91,19 +92,24 @@ namespace maix::peripheral::key
return;
}
ev.events = EPOLLIN;
ev.data.fd = data->fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, data->fd, &ev) < 0)
{
data->read_thread_exit = true;
log::error("epoll_ctl add failed: %s", strerror(errno));
return;
for (int fd : data->fds) {
if (fd > 0) {
ev.data.fd = fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
log::error("epoll_ctl add failed for fd %d: %s", fd, strerror(errno));
data->read_thread_exit = true;
close(epoll_fd);
return;
}
}
}
int fail_count = 0;
while (!data->read_thread_need_exit && !app::need_exit())
{
int nfds = epoll_wait(epoll_fd, &ev, 1, 200);
if (nfds > 0)
{
data->fd = ev.data.fd;
err::Err e = data->key->read(key, value);
if (e == err::Err::ERR_NONE)
{
Expand Down Expand Up @@ -303,7 +309,6 @@ namespace maix::peripheral::key
if(_key_defult_listener)
rm_default_listener();
this->_callback = callback;
this->_fd = -1;
this->_data = nullptr;
this->_device = device;
Port_Data *data = new Port_Data();
Expand All @@ -325,7 +330,9 @@ namespace maix::peripheral::key
data->key = this;
data->callback = callback;

if (sys::device_id() == "maixcam_pro" && !fs::exists(KEY_DEVICE1)) {
if (sys::device_id() == "maixcam_pro" &&
!fs::exists(KEY_DEVICE1) &&
(device == "" || device == KEY_DEVICE1)) {
log::info("%s: Init pmu power key.", sys::device_name().c_str());
_init_power_key((void*)data);
}
Expand Down Expand Up @@ -382,38 +389,54 @@ namespace maix::peripheral::key

err::Err Key::open()
{
if (this->_fd > 0)
if (this->_fds.size())
{
this->close();
}
bool is_open = false;
if(!this->_device.empty())
{
this->_fd = ::open(_device.c_str(), O_RDONLY);
if (this->_fd > 0)
int fd = ::open(_device.c_str(), O_RDONLY);
if (fd > 0) {
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
this->_fds.push_back(fd);
is_open = true;
}
}
if(!is_open)
{
this->_fd = ::open(KEY_DEVICE, O_RDONLY);
if (this->_fd < 0)
int fd = ::open(KEY_DEVICE, O_RDONLY);
if (fd < 0)
{
this->_fd = ::open(KEY_DEVICE0, O_RDONLY);
if (this->_fd < 0)
{
this->_device = KEY_DEVICE0;
return err::Err::ERR_NOT_FOUND;
std::vector<std::string> key_devices;
if (sys::device_id() == "maixcam_pro") {
key_devices = {KEY_DEVICE0, KEY_DEVICE1};
} else {
key_devices = {KEY_DEVICE0};
}
for (const auto& device : key_devices) {
int fd = ::open(device.c_str(), O_RDONLY);
if (fd == -1) {
log::error(("Failed to open device: " + device).c_str());
this->_device = device;
return err::Err::ERR_NOT_FOUND;
}
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
this->_fds.push_back(fd);
}
} else {
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
this->_fds.push_back(fd);
}
}
// set non-blocking
int flags = fcntl(this->_fd, F_GETFL, 0);
fcntl(this->_fd, F_SETFL, flags | O_NONBLOCK);
if (this->_callback)
{
// new thread to read key
Port_Data *data = (Port_Data *)this->_data;
data->fd = this->_fd;
data->fds = this->_fds;
data->read_thread_exit = false;
data->read_thread_need_exit = false;
data->thread = new thread::Thread(_read_process, this->_data);
Expand All @@ -424,14 +447,25 @@ namespace maix::peripheral::key

err::Err Key::read(int &key, int &value)
{
if (this->_fd < 0)
Port_Data *data = (Port_Data *)this->_data;
if (this->_fds.size() == 0)
{
return err::Err::ERR_NOT_OPEN;
}
struct input_event ev;
int ret;
while (1)
{
int ret = ::read(this->_fd, &ev, sizeof(struct input_event));
if (this->_callback == nullptr) {
for (int fd : this->_fds)
{
ret = ::read(fd, &ev, sizeof(struct input_event));
if (ret > 0 && ev.code != 0)
break;
}
} else {
ret = ::read(data->fd, &ev, sizeof(struct input_event));
}
if (ret < 0)
{
if(errno == EAGAIN || errno == EWOULDBLOCK)
Expand Down Expand Up @@ -478,22 +512,29 @@ namespace maix::peripheral::key
{
Port_Data *data = (Port_Data *)this->_data;
data->read_thread_need_exit = true;
if (this->_fd > 0)

bool err = false;
for (int &fd : this->_fds)
{
int ret = ::close(this->_fd);
this->_fd = -1;
if (ret < 0)
if (fd > 0)
{
return err::Err::ERR_IO;
int ret = ::close(fd);
if (ret < 0)
{
log::error("Failed to close fd %d: %s", fd, strerror(errno));
err = true;
}
fd = -1;
}
}
this->_fd = -1;
return err::Err::ERR_NONE;

this->_fds.clear();
return err ? err::Err::ERR_IO : err::Err::ERR_NONE;
}

bool Key::is_opened()
{
return this->_fd > 0;
return this->_fds.size() > 0;
}

int Key::long_press_time(int press_time)
Expand Down

0 comments on commit 324b0d4

Please sign in to comment.