project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp: Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem. sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately. sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades. sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for fastboot. Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
286 lines
7.7 KiB
C
286 lines
7.7 KiB
C
/*
|
|
* Copyright (c) 2022 rockchip
|
|
*
|
|
*/
|
|
#include "rk_event.h"
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <sys/epoll.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <linux/input.h>
|
|
|
|
#define DEV_PATH_MAX_LEN 128
|
|
|
|
typedef struct dev_info {
|
|
int dev_fd;
|
|
char *dev_path;
|
|
struct dev_info *dev_next;
|
|
}DEV_INFO;
|
|
|
|
typedef struct event_manager_t{
|
|
DEV_INFO *first;
|
|
DEV_INFO *last;
|
|
int dev_num;
|
|
}EVENT_MANAGER_T;
|
|
|
|
static int event_quit;
|
|
static pthread_t event_tid = 0;
|
|
static pthread_mutex_t event_mutex;
|
|
static int epoll_fd = -1;
|
|
struct epoll_event *evs = NULL, ev;
|
|
event_handler_t dev_event_handler = NULL;
|
|
static struct event_manager_t *event_manager = NULL;
|
|
|
|
int rk_event_register(char *dev_path) {
|
|
int ret;
|
|
if(event_tid) {
|
|
printf("event_register must befor event_listen_start\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!dev_path) {
|
|
printf("event_register fail,dev_path is null\n");
|
|
return -1;
|
|
}
|
|
|
|
if(epoll_fd < 0) {
|
|
pthread_mutex_init(&event_mutex, NULL);
|
|
if (!event_manager) {
|
|
event_manager = (struct event_manager_t *)malloc(sizeof(struct event_manager_t));
|
|
if(!event_manager) {
|
|
printf("malloc event_manager fail\n");
|
|
return -1;
|
|
} else {
|
|
memset(event_manager, 0, sizeof(struct event_manager_t));
|
|
event_manager->first = NULL;
|
|
event_manager->last = NULL;
|
|
event_manager->dev_num = 0;
|
|
}
|
|
}
|
|
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
|
if (epoll_fd < 0) {
|
|
printf("epoll create failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (event_manager->first) {
|
|
DEV_INFO *tmp = event_manager->first;
|
|
while (tmp != NULL) {
|
|
if(strcmp(dev_path, tmp->dev_path) == 0) {
|
|
printf("dev_path has been registered!\n");
|
|
return -1;
|
|
}
|
|
tmp = tmp->dev_next;
|
|
}
|
|
}
|
|
|
|
DEV_INFO *dev_elm = NULL;
|
|
dev_elm = (DEV_INFO *)malloc(sizeof(DEV_INFO));
|
|
if (!dev_elm) {
|
|
printf("malloc dev_info struct fail\n");
|
|
return -1;
|
|
}
|
|
memset(dev_elm, 0 ,sizeof(DEV_INFO));
|
|
dev_elm->dev_path = NULL;
|
|
dev_elm->dev_next = NULL;
|
|
|
|
dev_elm->dev_path = (char *)malloc(DEV_PATH_MAX_LEN);
|
|
if(!dev_elm->dev_path) {
|
|
printf("save dev_path fail\n");
|
|
goto fail;
|
|
}
|
|
memset(dev_elm->dev_path, 0, DEV_PATH_MAX_LEN);
|
|
strcpy(dev_elm->dev_path, dev_path);
|
|
|
|
dev_elm->dev_fd = open(dev_path, O_RDONLY | O_NONBLOCK);
|
|
if (dev_elm->dev_fd < 0) {
|
|
printf("failed open %s\n", dev_path);
|
|
if (dev_elm->dev_path) {
|
|
free(dev_elm->dev_path);
|
|
dev_elm->dev_path = NULL;
|
|
}
|
|
goto fail;
|
|
}
|
|
|
|
ev.data.fd = dev_elm->dev_fd;
|
|
ev.events = EPOLLIN | EPOLLET;
|
|
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, dev_elm->dev_fd, &ev);
|
|
if(ret == -1) {
|
|
printf("epoll_ctl fail errno: %s\n", strerror(errno));
|
|
if (dev_elm->dev_path) {
|
|
free(dev_elm->dev_path);
|
|
dev_elm->dev_path = NULL;
|
|
}
|
|
close(dev_elm->dev_fd);
|
|
goto fail;
|
|
}
|
|
|
|
if (event_manager->dev_num == 0) {
|
|
if(!event_manager->first) {
|
|
event_manager->first =
|
|
event_manager->last =
|
|
dev_elm;
|
|
event_manager->dev_num++;
|
|
}
|
|
} else if(event_manager->dev_num > 0) {
|
|
event_manager->last->dev_next = dev_elm;
|
|
event_manager->dev_num++;
|
|
event_manager->last = dev_elm;
|
|
}
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
if (dev_elm)
|
|
free(dev_elm);
|
|
return -1;
|
|
}
|
|
|
|
int rk_event_unregister(char *dev_path) {
|
|
if (!dev_path) {
|
|
printf("event_unregister fail,dev_path is null\n");
|
|
return -1;
|
|
}
|
|
|
|
if (event_manager->first) {
|
|
DEV_INFO *pre_tmp = NULL;
|
|
DEV_INFO *tmp = event_manager->first;
|
|
while (tmp != NULL) {
|
|
if(strcmp(dev_path, tmp->dev_path) == 0) {
|
|
pthread_mutex_lock(&event_mutex);
|
|
ev.data.fd = tmp->dev_fd;
|
|
ev.events = EPOLLIN;
|
|
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, tmp->dev_fd, &ev);
|
|
close(tmp->dev_fd);
|
|
if (event_manager->dev_num > 1) {
|
|
if(pre_tmp) {
|
|
if (tmp->dev_next == NULL) {
|
|
event_manager->last = pre_tmp;
|
|
event_manager->last->dev_next = NULL;
|
|
} else
|
|
pre_tmp->dev_next = tmp->dev_next;
|
|
}else
|
|
event_manager->first = tmp->dev_next;
|
|
}
|
|
if(tmp->dev_path)
|
|
free(tmp->dev_path);
|
|
if(tmp)
|
|
free(tmp);
|
|
event_manager->dev_num--;
|
|
if(event_manager->dev_num == 0)
|
|
event_manager->first =
|
|
event_manager->last =
|
|
NULL;
|
|
pthread_mutex_unlock(&event_mutex);
|
|
return 0;
|
|
}
|
|
pre_tmp = tmp;
|
|
tmp = tmp->dev_next;
|
|
}
|
|
}
|
|
printf("dev_path isn't registered\n");
|
|
return 0;
|
|
}
|
|
|
|
static int rk_event_read(struct epoll_event *ev) {
|
|
struct input_event input_ev;
|
|
while (read(ev->data.fd, &input_ev, sizeof(struct input_event)) > 0) {
|
|
if(!input_ev.type && !input_ev.value && !input_ev.code)
|
|
continue;
|
|
if(dev_event_handler)
|
|
dev_event_handler(&input_ev);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void *rk_event_recthread(void *arg) {
|
|
int ret, i;
|
|
|
|
while (event_quit == 0) {
|
|
ret = epoll_wait(epoll_fd, evs, event_manager->dev_num, -1);
|
|
for (i = 0; i < ret; i ++) {
|
|
if (evs[i].events & EPOLLIN)
|
|
rk_event_read(&evs[i]);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int rk_event_listen_start(event_handler_t handler) {
|
|
if (!handler) {
|
|
printf("rk_event_listen_start: handler is null\n");
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_lock(&event_mutex);
|
|
dev_event_handler = handler;
|
|
if (event_manager->dev_num > 0 && evs == NULL) {
|
|
evs = (struct epoll_event *)calloc(event_manager->dev_num, sizeof(struct epoll_event));
|
|
if(!evs) {
|
|
printf("calloc epoll_event array fail\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
event_quit = 0;
|
|
if (pthread_create(&event_tid, NULL,
|
|
rk_event_recthread, NULL)) {
|
|
printf("rk_event_recthread create failed!");
|
|
return -1;
|
|
}
|
|
pthread_mutex_unlock(&event_mutex);
|
|
return 0;
|
|
}
|
|
|
|
int rk_event_listen_stop(void) {
|
|
pthread_mutex_lock(&event_mutex);
|
|
epoll_fd = -1;
|
|
event_quit = 1;
|
|
dev_event_handler = NULL;
|
|
|
|
if(evs) {
|
|
free(evs);
|
|
evs = NULL;
|
|
}
|
|
|
|
if (event_manager->first) {
|
|
DEV_INFO *tmp = event_manager->first;
|
|
DEV_INFO *tmp_next = NULL;
|
|
while (tmp != NULL) {
|
|
tmp_next = tmp->dev_next;
|
|
close(tmp->dev_fd);
|
|
if(tmp->dev_path)
|
|
free(tmp->dev_path);
|
|
if(tmp)
|
|
free(tmp);
|
|
tmp = tmp_next;
|
|
event_manager->dev_num--;
|
|
}
|
|
}
|
|
if (event_manager) {
|
|
free(event_manager);
|
|
event_manager = NULL;
|
|
}
|
|
|
|
if (event_tid) {
|
|
pthread_cancel(event_tid);
|
|
if (pthread_join(event_tid, NULL)) {
|
|
printf("rk_event_recthread join failed!");
|
|
pthread_mutex_unlock(&event_mutex);
|
|
return -1;
|
|
}
|
|
event_tid = 0;
|
|
}
|
|
pthread_mutex_unlock(&event_mutex);
|
|
pthread_mutex_destroy(&event_mutex);
|
|
return 0;
|
|
}
|
|
|