Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/meson_videoserver/vscfuse/v4l2-controls-ext.cpp
T

729 lines
21 KiB
C++

/*
* Copyright (C) 2024 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vsc_fuse.h"
#include "BinderClient.h"
#include <thread>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/prctl.h>
#include <android/log.h>
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
#include <dirent.h>
#include "vsc_func.h"
int writeSys(const char *path, const char *val) {
int fd, size;
if ((fd = open(path, O_RDWR)) < 0) {
printf("writeSys, open %s fail.", path);
return -1;
}
size = strlen(val);
if (write(fd, val, size) != size) {
printf("writeSys, write %d size error: %s\n", size, strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}
int readSys(const char *path, char *buf, int count) {
int fd, len;
if ( NULL == buf ) {
printf("buf is NULL");
return -1;
}
if ((fd = open(path, O_RDONLY)) < 0) {
printf("readSys, open %s error(%s)", path, strerror (errno));
return -1;
}
len = read(fd, buf, count);
if (len < 0) {
printf("read %s error, %s\n", path, strerror(errno));
goto exit;
}
int i , j;
for (i = 0, j = 0; i <= len -1; i++) {
//change '\0' to 0x20(spacing), otherwise the string buffer will be cut off ,if the last char is '\0' should not replace it
if (0x0 == buf[i] && i < len - 1) {
buf[i] = 0x20;
}
/* delete all the character of '\n' */
if (0x0a != buf[i]) {
buf[j++] = buf[i];
}
}
buf[j] = 0x0;
//LOGI("read %s, result length:%d, val:%s\n", path, len, buf);
exit:
close(fd);
return len;
}
int v4l2_ext_set_vsc_frame_delay(fuse_req_t req, int value)
{
int valArray[3];
valArray[0] = value;
if (value < 0)
return -1;
writeSys("/sys/class/video_composer/vd_set_frame_delay", (const char*)valArray);
return 0;
}
int v4l2_ext_get_vsc_frame_delay(fuse_req_t req, int *value)
{
int valArray[3];
int count = 0;
readSys("/sys/class/video_composer/vd_set_frame_delay", (char*)valArray, count);
*value = valArray[0];
return 0;
}
int v4l2_ext_set_vsc_limited_win_ratio(fuse_req_t req, const void *ptr)
{
/* We want to know the scaler performance for window setting.
(VSC GetLimitedWindow) If SOC can support any video size
(there isn't any limitation on in window setting), this function
Just returns 0x0. If SOC has some limitation, this function
returns the limited value. This function gets the Min/Max that
can be scaling setting.
*/
return 0;
}
int v4l2_ext_get_vsc_limited_win_ratio(fuse_req_t req, struct v4l2_ext_vsc_scaler_ratio *ratio)
{
/* We want to know the scaler performance for window setting.
(VSC GetLimitedWindow) If SOC can support any video size
(there isn't any limitation on in window setting), this function
Just returns 0x0. If SOC has some limitation, this function
returns the limited value. This function gets the Min/Max that
can be scaling setting.
*/
ratio->h_scaleup_ratio = 0;
ratio->v_scaleup_ratio = 0;
ratio->h_scaledown_ratio = 0;
ratio->v_scaledown_ratio = 0;
return 0;
}
int v4l2_ext_set_vsc_occupation_sub_scaler(struct fuse_file_info *fi, int value)
{
/* After confirmation, this interface does not perform any operation */
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (!file || value < 0 || value > 2)
return -1;
file->data.occupation_sub_scaler = value;
return 0;
}
int v4l2_ext_get_vsc_occupation_sub_scaler(struct fuse_file_info *fi, int *value)
{
/* After confirmation, this interface does not perform any operation */
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file)
*value = file->data.occupation_sub_scaler;
return 0;
}
int v4l2_ext_set_vsc_pattern(fuse_req_t req, const void *ptr)
{
enum v4l2_ext_vsc_pattern *type = (enum v4l2_ext_vsc_pattern *)ptr;
if (*type == V4L2_EXT_VSC_PATTERN_SCALER) {
writeSys("/sys/class/video/video_test_pattern", "0 1 0xff0000");
writeSys("/sys/class/video/video_test_pattern", "0 1 0xff00");
writeSys("/sys/class/video/video_test_pattern", "0 1 0xff");
writeSys("/sys/class/video/video_test_pattern", "0 0 0xff");
} else if (*type == V4L2_EXT_VSC_PATTERN_DISPLAY) {
writeSys("/sys/class/video/postblend_test_pattern", "1 0xff0000");
writeSys("/sys/class/video/postblend_test_pattern", "1 0xff00");
writeSys("/sys/class/video/postblend_test_pattern", "1 0xff");
writeSys("/sys/class/video/postblend_test_pattern", "0 0xff");
}
return 0;
}
int v4l2_ext_get_vsc_pattern(fuse_req_t req, enum v4l2_ext_vsc_pattern *type)
{
/* There is no need to implement the get function at present */
return 0;
}
int v4l2_ext_set_vsc_pixel_color_info(fuse_req_t req, const void *ptr)
{
/* Dump YUV data is required, and the pointer is obtained. This function will be improved later */
return 0;
}
int v4l2_ext_get_vsc_pixel_color_info(fuse_req_t req, struct v4l2_ext_vsc_pixel_color_info *info)
{
info->r.h = 2160;
info->r.w = 3840;
info->r.x = 0;
info->r.y = 0;
info->p_data = NULL;
info->compat_data = 0;
info->sizer = 0;
info->format = V4L2_EXT_VSC_COLOR_PIXEL_FORMAT_YUV;
info->depth = V4L2_EXT_VSC_COLOR_PIXEL_8BIT;
return 0;
}
int v4l2_ext_set_vsc_rgb444(struct fuse_file_info *fi, int value)
{
/* After discussion, VPP postblond output only supports rgb444 */
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (!file || value > 1 || value < 0)
return -1;
file->data.rgb444 = value;
return 0;
}
int v4l2_ext_get_vsc_rgb444(struct fuse_file_info *fi, int *value)
{
/* After discussion, VPP postblond output only supports rgb444 */
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file)
*value = file->data.rgb444;
return 0;
}
int v4l2_ext_set_vsc_win_region(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_win_region *win = (struct v4l2_ext_vsc_win_region *)ptr;
int response = 0;
if (!file || win->rotation > V4L2_EXT_VSC_ROTATE_VFLIP)
return -1;
if (file->binder.get())
response = file->binder->setOriginalResolution(file->display_id, file->scaler_id, win);
return response;
}
int v4l2_ext_get_vsc_win_region(struct fuse_file_info *fi, struct v4l2_ext_vsc_win_region *win)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getWinRegion(file->display_id, file->scaler_id, win);
return response;
}
int v4l2_ext_set_vsc_orbit_window(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_orbit_window *win = (struct v4l2_ext_vsc_orbit_window *)ptr;
if (file->binder.get())
return file->binder->setOrbitWindow(file->display_id, file->scaler_id, win);
return 0;
}
int v4l2_ext_set_vsc_orbit_move(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_orbit_move *orbitMove = (struct v4l2_ext_vsc_orbit_move *)ptr;
if (file->binder.get())
return file->binder->setOrbitMove(file->display_id, file->scaler_id, orbitMove);
return 0;
}
int v4l2_ext_set_vsc_zorder(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_zorder *z = (struct v4l2_ext_vsc_zorder *)ptr;
int response = 0;
if (file->binder.get())
response = file->binder->setZorder(file->display_id, file->scaler_id, z);
return response;
}
int v4l2_ext_get_vsc_zorder(struct fuse_file_info *fi, struct v4l2_ext_vsc_zorder *z)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getZorder(file->display_id, file->scaler_id, z);
return response;
}
int v4l2_ext_set_vsc_win_prop(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_win_prop *prop = (struct v4l2_ext_vsc_win_prop *)ptr;
int response = 0;
if (prop->win_mode > V4L2_EXT_VSC_WIN_MODE_PBP ||
prop->mirror_mode > V4L2_EXT_VSC_MIRROR_MODE_OFF ||
prop->mem_type > V4L2_EXT_VSC_MEMORY_TYPE_MULTI)
return -1;
if (file->binder.get())
response = file->binder->setWinProp(file->display_id, file->scaler_id, prop);
return response;
}
int v4l2_ext_get_vsc_win_prop(struct fuse_file_info *fi, struct v4l2_ext_vsc_win_prop *prop)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getWinProp(file->display_id, file->scaler_id, prop);
return response;
}
int v4l2_ext_set_hdr_type(struct fuse_file_info *fi, int value)
{
if (value > V4L2_EXT_VSC_HDR_TYPE_HDR_RESERVED3 || value < 0)
return -1;
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
enum v4l2_ext_vsc_hdr_type hdr = (enum v4l2_ext_vsc_hdr_type)value;
int response = 0;
if (file->binder.get())
response = file->binder->setHdrType(file->display_id, hdr);
return response;
}
int v4l2_ext_get_hdr_type(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getHdrType(file->display_id, (enum v4l2_ext_vsc_hdr_type *)value);
return response;
}
int v4l2_ext_set_vsc_connect_info(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_connect_info *info = (struct v4l2_ext_vsc_connect_info *)ptr;
int response = 0;
if (info->in.src > V4L2_EXT_VSC_INPUT_SRC_DP ||
info->out > V4L2_EXT_VSC_DEST_AVE)
return -1;
if (file->binder.get())
response = file->binder->setConnectInfo(file->display_id, file->scaler_id, file->index, info);
return response;
}
int v4l2_ext_get_vsc_connect_info(struct fuse_file_info *fi, struct v4l2_ext_vsc_connect_info *info)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getConnectInfo(file->display_id, file->scaler_id, info);
return response;
}
int v4l2_ext_set_vsc_freeze(struct fuse_file_info *fi, int value)
{
if (value != 0 && value != 1)
return -1;
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->setFreeze(file->display_id, file->scaler_id, value);
return response;
}
int v4l2_ext_get_vsc_freeze(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getFreeze(file->display_id, file->scaler_id, value);
return response;
}
int v4l2_ext_set_vsc_freeze_frame_buffer(struct fuse_file_info *fi, int value)
{
if (value != 0 && value != 1)
return -1;
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->setFreezeFrameBuffer(file->display_id, file->scaler_id, value);
return response;
}
int v4l2_ext_get_vsc_freeze_frame_buffer(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getFreezeFrameBuffer(file->display_id, file->scaler_id, value);
return response;
}
int v4l2_ext_set_vsc_adaptive_stream(struct fuse_file_info *fi, int value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (!file || value < 0 || value > 2)
return -1;
file->data.adaptive_stream = value;
return 0;
}
int v4l2_ext_get_vsc_adaptive_stream(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file)
*value = file->data.adaptive_stream;
return 0;
}
int v4l2_ext_set_vsc_aspectratio_policy(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_vsc_aspectratio_policy *policy =
(struct v4l2_ext_vsc_aspectratio_policy *)ptr;
int response = 0;
if (file->binder.get())
response = file->binder->setAspectratio(file->display_id, file->scaler_id, policy);
file->data.policy = *policy;
return response;
}
int v4l2_ext_get_vsc_aspectratio_policy(struct fuse_file_info *fi,
struct v4l2_ext_vsc_aspectratio_policy *policy)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file)
*policy = file->data.policy;
return 0;
}
int v4l2_cid_set_bg_color(struct fuse_file_info *fi, int value)
{
if (value > V4L2_EXT_VSC_WIN_COLOR_GRAY || value < 0)
return -1;
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
enum v4l2_ext_vsc_win_color color = (enum v4l2_ext_vsc_win_color)value;
int response = 0;
if (file->binder.get())
response = file->binder->setBgColor(file->display_id, file->scaler_id, color);
return response;
}
int v4l2_cid_get_bg_color(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
int response = 0;
if (file->binder.get())
response = file->binder->getBgColor(file->display_id, (enum v4l2_ext_vsc_win_color *)value);
return response;
}
int v4l2_ext_set_hdmitx_timing_info(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_hdmitx_timing_info *info = (struct v4l2_ext_hdmitx_timing_info *)ptr;
if (file->binder.get())
return file->binder->setHdmitxTiming(file->display_id, info);
return 0;
}
int v4l2_ext_get_hdmitx_timing_info(struct fuse_file_info *fi, struct v4l2_ext_hdmitx_timing_info *info)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxTiming(file->display_id, info);
return 0;
}
int v4l2_cid_get_hdmitx_connection(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxConnection(file->display_id, value);
return 0;
}
int v4l2_ext_set_hdmitx_color_attr(struct fuse_file_info *fi, const void *ptr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
struct v4l2_ext_hdmitx_color_attr *attr = (struct v4l2_ext_hdmitx_color_attr *)ptr;
if (file->binder.get())
return file->binder->setHdmitxColor(file->display_id, attr);
return 0;
}
int v4l2_ext_get_hdmitx_color_attr(struct fuse_file_info *fi,
struct v4l2_ext_hdmitx_color_attr *attr)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxColor(file->display_id, attr);
return 0;
}
int v4l2_cid_get_hdmitx_hdr_mode(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxHdrType(file->display_id, value);
return 0;
}
int v4l2_cid_get_hdmitx_hdcp_version(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxHdcpVersion(file->display_id, value);
return 0;
}
int v4l2_cid_set_hdmitx_hdr_policy(struct fuse_file_info *fi, int value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->setHdmitxHdrPolicy(file->display_id, value);
return 0;
}
int v4l2_cid_get_hdmitx_hdr_policy(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxHdrPolicy(file->display_id, value);
return 0;
}
int v4l2_cid_set_hdmitx_av_mute(struct fuse_file_info *fi, int value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->setHdmitxAvMute(file->display_id, value);
return 0;
}
int v4l2_cid_set_hdmitx_hdcp_auth(struct fuse_file_info *fi, int value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->setHdmitxHdcpAuth(file->display_id, value);
return 0;
}
int v4l2_cid_get_hdmitx_hdcp_status(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxHdcpStatus(file->display_id, value);
return 0;
}
int v4l2_cid_get_hdmitx_edid(struct fuse_file_info *fi, unsigned char *dat)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file->binder.get())
return file->binder->getHdmitxRawEdid(file->display_id, dat);
return 0;
}
int v4l2_ext_get_device_capability(fuse_req_t req, struct v4l2_ext_vsc_device_capability *capability)
{
capability->num_planes = 2;
return 0;
}
int v4l2_ext_get_scan_mode(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
char val[80] = { 0 };
int mode = 0;
if (readSys("/sys/class/video_composer/di_vsc_scan_mode", val, sizeof(val)) >= 0) {
if (sscanf(val, "current di_vsc_scan_mode is %d.", &mode) == 1) {
*value = mode;
return 0;
}
}
if (file)
*value = file->data.scan_mode;
return 0;
}
int v4l2_ext_set_scan_mode(struct fuse_file_info *fi, int value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
char val[3] = { 0 };
if (!file || value > V4L2_EXT_VSC_SCAN_MODE_INTER_FIELD)
return -1;
file->data.scan_mode = value;
sprintf(val, "%d", value);
return writeSys("/sys/class/video_composer/di_vsc_scan_mode", val);
}
int v4l2_ext_get_pixed_to_pixed(struct fuse_file_info *fi, int *value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (file)
*value = file->data.pixel_to_pixel;
return 0;
}
int v4l2_ext_set_pixed_to_pixed(struct fuse_file_info *fi, int value)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (!file)
return -1;
file->data.pixel_to_pixel = value;
return 0;
}
void v4l2_ext_set_subscribe_state(
struct fuse_file_info *fi, int id, bool state)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (!file)
return;
for (int i = 0; i < file->subscribe_size; i++) {
if (id == file->subscribeInfo[i].event_id)
file->subscribeInfo[i].state = state;
}
}
bool v4l2_ext_get_subscribe_state(video_scaler_file_t *info, int id)
{
if (info->scaler_id >= VT_SCALER_MAX)
return false;
for (int i = 0; i < info->subscribe_size; i++) {
if (id == info->subscribeInfo[i].event_id) {
return info->subscribeInfo[i].state;
}
}
return false;
}
int v4l2_ext_set_event(video_scaler_file_t *info, struct v4l2_event *event)
{
if (!info)
return -1;
pthread_mutex_lock(&info->mutex);
if (info->pollHandle) {
if (v4l2_ext_get_subscribe_state(info, event->id)) {
memcpy(&info->receiveEvent, event, sizeof(struct v4l2_event));
info->poll_status = true;
fuse_lowlevel_notify_poll(info->pollHandle);
}
}
pthread_mutex_unlock(&info->mutex);
return 0;
}
int v4l2_ext_get_event(struct fuse_file_info *fi, struct v4l2_event *event)
{
video_scaler_file_t *file = (video_scaler_file_t *)fi->fh;
if (!file)
return -1;
memcpy(event, &file->receiveEvent, sizeof(struct v4l2_event));
return 0;
}
VSC_EXT_FUNC_LIST