rk3288 开机动态切换lvds屏幕显示(一)

 前言

        当前功能主要适用于多lvds屏幕的android系统使用,当前我使用的是rk3288 android7.1.2系统,做这个功能主要是公司使用的lvds屏幕比较多,各个项目之间对系统的改动并不是很大,大部分都是换一个屏幕,为了不用制作多余系统,所以开发此功能

 概述

        当前lvds屏幕动态切换主要是通过U盘来实现,首先系统正常启动后,插入U盘,系统添加服务读取U盘中关于屏幕参数的标志,将标志数据写入misc分区指定位置,完成后拔出U盘,重启系统,系统重新启动后,在uboot中读取屏幕标志,获取标志后查找设备树关于lvds屏幕配置节点,修改指定节点完成新屏幕的适配工作,等待内核启动后,会从设备树中加载新的屏幕参数。

一、添加U盘读取服务

1、服务实现

system/core/lcdservice/lcdservice.c

/* monitor the /mnt/external_sd/rk_lcd_parameters.   */
/* if the parameters has been changed, and then update the lcdparamers.  */
/* the parameters will work after reboot. */
/* [email protected] */
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <termio.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <cutils/properties.h>
#include <sys/utsname.h>
#include <cutils/list.h>
#include <cutils/log.h>
#include <cutils/sockets.h>
#include <sys/reboot.h>
#include <cutils/iosched_policy.h>

#define LOG_TAG "LcdParamService"

typedef     unsigned short    uint16;
typedef     unsigned long     uint32;
typedef     unsigned char     uint8;


#define LCD_PARAMETE_FILE_PATH         "busybox find  /mnt/media_rw/ -name rk_lcd_screen"
#define MISC_PARTITIOM_NODE_PATH         "/dev/block/platform/ff0f0000.dwmmc/by-name/misc"
/*#define MISC_PARTITIOM_NODE_PATH         "data/oem"*/

/*#define RKNAND_GET_VENDOR_SECTOR0       _IOW('v', 16, unsigned int)*/
/*#define RKNAND_STORE_VENDOR_SECTOR0     _IOW('v', 17, unsigned int)*/


#define RKNAND_SYS_STORGAE_DATA_LEN 4096  //oem size
/*#define VENDOR_SECTOR_OP_TAG        0x444E4556 // "VEND"*/

#define POLY    0xEDB88320L              //CRC stand
#define CONFIG_NUM  26

static char misc_lvds[100] = {0};
static char primary[100] = {0};
static char extend[100] = {0};
static char hwrotation[100] = {0};

char *strreplace(char *s, char old, char new)
{
    for (; *s; ++s)
        if (*s == old)
            *s = new;
    return s;
}

/*
 *去除字符串左端空格
 */
char *strtriml(char *pstr)
{
    int i = 0,j;
    j = strlen(pstr) - 1;
    while (isspace(pstr[i]) && (i <= j))
        i++;
    if (0<i)
        strcpy(pstr, &pstr[i]);
    return pstr;
}

/*
 *去除字符串右端空格
 */
char *strtrimr(char *pstr)
{
    int i;
    i = strlen(pstr) - 1;
    while (isspace(pstr[i]) && (i >= 0))
        pstr[i--] = '\0';
    return pstr;
}

/*
 *去除字符串两端空格
 */
char *strtrim(char *pstr)
{
    char *p;
    p = strtrimr(pstr);
    return strtriml(p);
}


char *strdelchr(char *pstr, int chr)
{
    int i = 0;
    int l = 0;
    int ll = 0;
   ll = l = strlen(pstr);

    while(i < l)
    {
        if(pstr[i] == chr)
        {
            memmove((pstr + i), (pstr + i + 1), (ll - i -1));
            pstr[ll - 1] = '\0';
            ll--;
        }
        i++;
    }
    /*     for(i = 0; i < l; i++) */
    /* { */
    /* if(pstr[i] == chr) */
    /* { */
    /* memmove((pstr + i), (pstr + i + 1), (l - i -1)); */
    /* pstr[l - 1] = '\0'; */
    /* break; */
    /* } */
    /* } */
    return pstr;
}


void strrmspace(char * str)
{
    char *p1, *p2;
    char ch;
    p1 = str; //first pointer
    p2 = str;  // second pointer to the remaining string
    if (p1==NULL) return;
    while (*p1)
    {
        if (*p1 != ' ')
        {
            ch = *p1;
            *p2 = ch;
            p1++;
            p2++;
        }
        else
        {
            p1++;
        }
    }
    *p2 = '\0';
}

char *get_misc_data(char *misc_buf, int length,int offset)
{
    if (misc_buf == NULL || length <= 0)
    {
        return NULL;
    }

    int ret = -1;
    int sys_fd = -1;
    char *p = NULL;

    if (0 != access(MISC_PARTITIOM_NODE_PATH, R_OK | W_OK)){
        ALOGE("access fail!!!\n");
        return -1;
    }

    sys_fd = open(MISC_PARTITIOM_NODE_PATH, O_RDONLY);
    if (sys_fd < 0)
    {
        ALOGE("fopen err %s err=%d\n",MISC_PARTITIOM_NODE_PATH, sys_fd);
        return -1;
    }

    ret = lseek(sys_fd,offset,SEEK_SET);
    ret = read(sys_fd,misc_buf, length);
    if (ret < 0)
    {
        ALOGE("read err %s err=%d\n",MISC_PARTITIOM_NODE_PATH, sys_fd);
        return NULL;
    }

    p = strstr(misc_buf, "--wipe");
    if(p == NULL)
        return NULL;

    *p = 0;

    return misc_buf;
}

char * set_misc_data(char *lvds_buf, int length, int offset)
{
    if (lvds_buf == NULL || length <= 0)
    {
        return NULL;
    }

    char misc_buf[100] = {0};
    int ret = -1;
    strcpy(misc_buf, lvds_buf);
    strcat(misc_buf, "--wipe");

    if (0 != access(MISC_PARTITIOM_NODE_PATH, R_OK | W_OK)){
        ALOGE("access fail!!!\n");
        return NULL;
    }

    int sys_fd = open(MISC_PARTITIOM_NODE_PATH, O_RDWR);
    if (sys_fd < 0)
    {
        ALOGE("fopen err %s err=%d\n",MISC_PARTITIOM_NODE_PATH, sys_fd);
        return NULL;
    }

    ret = lseek(sys_fd,offset,SEEK_SET);
    ret = write(sys_fd, misc_buf, length);
    if (ret < 0)
    {
        ALOGE("read err %s err=%d\n",MISC_PARTITIOM_NODE_PATH, sys_fd);
        return NULL;
    }

    return lvds_buf;
}

char *get_file_path(char *path, int path_len)
{
    char lcdparameter_buf[100] = {0};
    FILE *stream = popen(LCD_PARAMETE_FILE_PATH, "r");
    int ret = -1;
    if (stream == NULL) {
        return NULL;
    }
    ret = fread( lcdparameter_buf, sizeof(char), sizeof(lcdparameter_buf), stream);
    if(ret < 0)
        return NULL;
    strreplace(lcdparameter_buf,'\n','\0');
    pclose(stream);
    memset(path, 0, path_len);
    strcpy(path,lcdparameter_buf);

    return path;
}

int update_misc_data(char *property, int offset)
{
    char lcdparameter_buf[100] = {0};
    char buf[100] = {0};
    char file_property[100] = {0};
    char *p = NULL;
    int ret = -1;
    FILE *fp = NULL;
    char *path = NULL;

    path = get_file_path(lcdparameter_buf, sizeof(lcdparameter_buf));
    if(path == NULL) {
        return -1;
    }
    fp = fopen(lcdparameter_buf, "r");
    if(fp == NULL)
    {
        ALOGE("open file error : lcdparameter_buf %s \n",lcdparameter_buf);
        return -1;
    }

    memset(file_property,0,sizeof(file_property));
    while (fgets(buf,sizeof(buf),fp)) {
        if((strlen(buf) !=0) && (strstr(buf,"#") == NULL)) {
            if (strstr(buf,property)) {
                strreplace(buf,'\r','\0');
                strreplace(buf,'\n','\0');
                memcpy(file_property,buf,sizeof(buf));
                break;
            }
        }
    }
    ALOGD("file hwrotation = %s -- %d \n",file_property, __LINE__);

    if(strcmp(property,"hwrotation") == 0) {
        if (strcmp(hwrotation, file_property)!= 0) {
            ret = set_misc_data(file_property, sizeof(file_property), offset);
            if (ret == -1) {
                ALOGE("update misc hwrotation failed\r\n");
                return -1;
            }
            strcpy(hwrotation, file_property);
        }
    } else if (strcmp(property,"primary") == 0) {
        if (strcmp(primary, file_property) != 0) {
            ret = set_misc_data(file_property, sizeof(file_property), offset);
            if (ret == -1) {
                ALOGE("update misc hwrotation failed\r\n");
                return -1;
            }
            strcpy(primary, file_property);
        }
    } else if (strcmp(property,"extend") == 0) {
        if (strcmp(extend, file_property) != 0) {
            ret = set_misc_data(file_property, sizeof(file_property), offset);
            if (ret == -1) {
                ALOGE("update misc hwrotation failed\r\n");
                return -1;
            }
            strcpy(extend, file_property);
        }
    } else if (strcmp(property, "lvds_parameter") == 0) {
        if (strcmp(misc_lvds, file_property) != 0) {
            ret = set_misc_data(file_property, sizeof(file_property), offset);
            if (ret == -1) {
                ALOGE("update misc hwrotation failed\r\n");
                return -1;
            }
            strcpy(misc_lvds, file_property);
            sync();
            reboot(RB_AUTOBOOT);
        }
    } else {
        return -1;
    }

    return 0;
}

int update_system_property(char *property)
{
    if(property == NULL) {
        return -1;
    }

    char buf[100] = {0};
    char sys_property[100] = {0};
    char cmd[100] = {0};
    char *p = NULL;
    FILE *fp = NULL;
    char get_property[100] = {0};
    char set_property[100] = {0};
    if ((strlen(hwrotation) ==0 ) || (strlen(primary) == 0) || (strlen(extend) == 0) || (strlen(misc_lvds) == 0)) {
        if (strcmp(property,"hwrotation") == 0) {
            get_misc_data(hwrotation, sizeof(hwrotation), 1536);
            ALOGE("hwrotation = %s\n", hwrotation);
        } else if (strcmp(property,"primary") == 0) {
            get_misc_data(primary, sizeof(primary), 2048);
            ALOGE("primary = %s\n", primary);
        } else if (strcmp(property,"extend") == 0) {
            get_misc_data(extend, sizeof(extend), 2560);
            ALOGE("extend = %s\n", extend);
        } else if (strcmp(property,"lvds_parameter") == 0) {
            get_misc_data(misc_lvds, sizeof(misc_lvds), 1024);
            ALOGE("misc_lvds = %s\n", misc_lvds);
        }
    }

    if (strcmp(property,"primary") == 0) {
        strcpy(get_property, "getprop persist.hwc.device.primary");
        strcpy(buf,primary);
        strcpy(set_property, "setprop persist.hwc.device.primary");
    } else if (strcmp(property,"extend") == 0) {
        strcpy(get_property, "getprop persist.hwc.device.extend");
        strcpy(buf,extend);
        strcpy(set_property, "setprop persist.hwc.device.extend");
    } else if (strcmp(property,"hwrotation") == 0) {
        strcpy(get_property, "getprop persist.sf.hwrotation");
        strcpy(buf,hwrotation);
        strcpy(set_property, "setprop persist.sf.hwrotation");
    } else {
        return -1;
    }

    p = strstr(buf, "=");
    if (p == NULL)
        return -1;

    fp = popen(get_property,"r");
    if (fp == NULL)
    {
        ALOGE("getprop file open error !\n");
        return -1;
    }
    fread(sys_property, sizeof(char), sizeof(sys_property), fp);
    strreplace(sys_property,'\r','\0');
    strreplace(sys_property,'\n','\0');
    pclose(fp);
    if (strcmp(sys_property, p+1) != 0) {
        sprintf(cmd,"%s %s", set_property, p+1);
        ALOGD(" cmd = %s\n",cmd);
        system(cmd);
    } else {
        return -1;
    }

    return 0;
}

int main(void)
{
    ALOGE("V5 TEST\n");
    get_misc_data(hwrotation, sizeof(hwrotation), 1536);
    ALOGE("hwrotation = %s\n", hwrotation);
    get_misc_data(primary, sizeof(primary), 2048);
    ALOGE("primary = %s\n", primary);
    get_misc_data(extend, sizeof(extend), 2560);
    ALOGE("extend = %s\n", extend);
    get_misc_data(misc_lvds, sizeof(misc_lvds), 1024);
    ALOGE("misc_lvds = %s\n", misc_lvds);
    while(1)
    {
        update_misc_data("hwrotation", 1536);
        update_system_property("hwrotation");
        update_misc_data("primary", 2048);
        update_system_property("primary");
        update_misc_data("extend", 2560);
        update_system_property("extend");
        update_misc_data("lvds_parameter", 1024);
        usleep(1000000);
    }
    return 0;
}

该服务主要实现读取U盘中rk_lcd_screen文件,并将屏幕标志写入misc分区指定位置,同时还实现修改屏幕默认显示方向和主副显示屏幕设置。

2、添加服务编译

system/core/lcdservice/Android.mk


LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_FORCE_STATIC_EXECUTABLE := true

LOCAL_SRC_FILES:= \
    lcdservice.c

LOCAL_C_INCLUDES += bionic \
$(call include-path-for, libhardware_legacy)/hardware_legacy

LOCAL_MODULE:=lcdservice

LOCAL_MODULE_TAGS := optional

LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc liblog

LOCAL_SHARED_LIBRARIES := libhardware_legacy libnetutils liblog

include $(BUILD_EXECUTABLE)

device/rockchip/rk3288/device.mk

     Lightning \
-    SoundRecorder
+    SoundRecorder \
+    lcdparamservice

3、添加系统服务

device/rockchip/common/init.rk30board.rc

+service lcdservice /system/bin/lcdservice
+    class main

android服务添加需要对服务的SELinux权限做处理,具体操作可参考其他人写的android服务SELinux权限处理文档。

Guess you like

Origin blog.csdn.net/qq_32645109/article/details/121338840