嵌入式linux 控制台,嵌入式Linux 下 通用 console(控制台)的实现
前言:
当我们使用嵌入式linux 进行开发时,kernel 跑起来之后,我们希望能通过串口(标准输入、输出),在应用程序正在运行的过程中,进行一些调试工作,例如,对CPU一些寄存进行调整,以观测调整以后的结果,并且,当我们无法把我们的应用程序放在后台运行,那么我们就需要实现一个基础的控制台。
下文中的控制台,虽然简单,但完备的支持 上 下 左 右 backspace del 常用控制台操作,使用 上 下 键可以浏览已经输入过的命令(类似 doskey 这样的功能),支持 光标 左右移动 修改命令
一般我们在 main 函数最后 都会做 while(TRUE) sleep(1000) 这样 阻塞住主线程,用这个控制台的实现,替换这个过程,则应用程序可增加控制台应用功能,各部分的具体实现如下:
调用代码(main.c):
#include
#include "app_console.h"
intmain(intargc,char*argv[])
{
// 之前的应用代码
....
....
....
App_Console_Start();
return0;
}
控制台头文件(app_console.h)
#ifndef __APP_CONSOLE_H__
#define __APP_CONSOLE_H__
#ifdef __cplusplus
extern"C"
{
#endif
#include "type_def.h"
voidApp_Console_Start();
#ifdef __cplusplus
}
#endif
#endif
控制台C文件(app_console.c)
#include "app_console.h"
#include "ctype.h"
#include "unistd.h"
#include "app_test.h"
// 说明
// read write 使用的是 POSIX 的标准文件读写函数
// unistd.h 包含了 STDIN_FILENO 等文件描述符的定义
// ctype.h 包含了 isprint 函数的声明
// 经过仔细考虑,决定不支持 ESC 键,因为ESC 键的键值为 0x1b 与 上下左右的键值重复
// 但可以考虑按2下ESC清除本行输入
// 对不可打印字符的处理仅限于以下已经列出的宏定义
// change:
// 放弃对 double ESC 的支持,因为可能出现按了 ESC 又按了 方向键 的情况
// 则用户输入编码为 '/x1b' '/x1b' '[' 'A' (按了ESC 又按了上键)
// change:
// 为了将应用与控制台应用剥离,则将 #define MAX_CMD_LEN 512 房到 app_test.h 中定义
// 二维数组作为参数进行传递时,需要明确第二个维度的大小,否则编译器无法正确定位地址
#define KEY_BACKSPACE '/x08' // back space
#define KEY_DEL '/x7F' // del
#define KEY_ENTER '/x0A' // 回车
// 以下为 0x1b 开头的键值
//#define KEY_DOUBLEESC "/x1B/x1B"// ESC
//#define KEY_ARROW_UP "/x1B[A" // 上
//#define KEY_ARROW_DOWN "/x1B[B" // 下
//#define KEY_ARROW_LEFT "/x1B[D" // 左
//#define KEY_ARROW_RIGHT "/x1B[C" // 右
typedefenum
{
WKS_WAIT,
WKS_RECV1B,
WKS_UDLR,
}T_WaitKeyState;
#define MAX_CMD_HISTORY 32
#define MAX_PAR_COUNT 16
staticcharszPrompt[] = {"TR_Console> "};
staticT_WaitKeyState waitKeyState = WKS_WAIT;
staticcharszCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LEN];
staticcharszCmdNow[MAX_CMD_LEN] = {0};
staticUINT32nCmdIndex = 0;
staticUINT32nCmdCursor = 0;
staticUINT32nCmdInputCount = 0;
staticUINT32nCmdInputCursor = 0;
staticvoidApp_Console_ParseCmd(constchar* pCmd);
staticUINT32App_Console_ReadInput(char*input)
{
U32 nRead=0;
structpollfd p;
structtermio term,term_old;
/* Get control of the terminal */
ioctl(STDIN_FILENO,TCGETA,(void*)&term);
term_old = term;
term.c_lflag &= ~ICANON;
term.c_lflag &= ~ECHO;
ioctl(STDIN_FILENO,TCSETAW,(void*)&term);
/* Get event we want to know */
p.fd = STDIN_FILENO;
p.events = POLLIN;
/* If we receive one thing, get the byte now */
if(poll(&p,1,-1)>0)
{
if(p.revents==POLLIN)
{
nRead=read(STDIN_FILENO,input,1);
}
}
/* Purge the byte */
/* tcflush(0,TCIOFLUSH); */
/* Leave control */
ioctl(STDIN_FILENO,TCSETAW,(void*)&term_old);
return(nRead);
}
staticvoidApp_Console_BSChar()
{
charszTemp[3];
szTemp[0] ='/b';
szTemp[1] =' ';
szTemp[2] ='/b';
write(STDOUT_FILENO,szTemp,3);
}
staticvoidApp_Console_OnPrintChar(charinput)
{
if(nCmdInputCount == MAX_CMD_LEN)return;
if(nCmdInputCursor
{
charszTemp[MAX_CMD_LEN] = {0};
char* pCmd = szCmdNow;
intnBackCount = nCmdInputCount-nCmdInputCursor;
szTemp[0] = input;
memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);
write(STDOUT_FILENO,szTemp,nBackCount+1);
memcpy(&pCmd[nCmdInputCursor],&szTemp,nBackCount+1);
memset(szTemp,'/b',nBackCount);
write(STDOUT_FILENO,szTemp,nBackCount);
}
else
{
write(STDOUT_FILENO,&input,1);
szCmdNow[nCmdInputCount] = input;
}
nCmdInputCursor++;
nCmdInputCount++;
}
staticvoidApp_Console_OnBackspace()
{
if(nCmdInputCursor > 0)
{
if(nCmdInputCursor == nCmdInputCount)// 光标在末尾
App_Console_BSChar();
else// 光标不在末尾
{
charszTemp[MAX_CMD_LEN] = {0};
char* pCmd = szCmdNow;
intnBackCount = nCmdInputCount-nCmdInputCursor;
szTemp[0] ='/b';
memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);
szTemp[nBackCount+1] =' ';
write(STDOUT_FILENO,szTemp,nBackCount+2);
memcpy(&pCmd[nCmdInputCursor-1],&szTemp[1],nBackCount);
memset(szTemp,'/b',nBackCount+1);
write(STDOUT_FILENO,szTemp,nBackCount+1);
}
nCmdInputCount --;
nCmdInputCursor--;
}
}
staticvoidApp_Console_OnDel()
{
if(nCmdInputCursor
{
charszTemp[MAX_CMD_LEN] = {0};
char* pCmd = szCmdNow;
intnBackCount = nCmdInputCount-nCmdInputCursor-1;
memcpy(szTemp,&pCmd[nCmdInputCursor+1],nBackCount);
szTemp[nBackCount] =' ';
write(STDOUT_FILENO,szTemp,nBackCount+1);
memcpy(&pCmd[nCmdInputCursor],szTemp,nBackCount);
memset(szTemp,'/b',nBackCount+1);
write(STDOUT_FILENO,szTemp,nBackCount+1);
nCmdInputCount--;
}
}
staticvoidApp_Console_OnDoubleEsc()
{
if(nCmdInputCount > 0)
{
char* pCmd = szCmdNow;
// 将光标移动到最末尾
while(nCmdInputCursor
{
write(STDOUT_FILENO,&pCmd[nCmdInputCursor],1);
nCmdInputCursor++;
}
// 清除所有输入的数据
inti=0;
for(i=0;i
nCmdInputCount = 0;
nCmdInputCursor = 0;
}
}
staticvoidApp_Console_OnUp()
{
if(nCmdCursor == 0)return;
nCmdCursor --;
// 清除掉现在所有的输入
App_Console_OnDoubleEsc();
char* pCmdHistory = &szCmdHistory[nCmdCursor][0];
memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);
nCmdInputCount = strlen(szCmdNow);
nCmdInputCursor= nCmdInputCount;
write(STDOUT_FILENO,szCmdNow,nCmdInputCount);
}
staticvoidApp_Console_OnDown()
{
if(nCmdCursor >= (nCmdIndex-1))return;
nCmdCursor ++;
// 清除掉现在所有的输入
App_Console_OnDoubleEsc();
char* pCmdHistory = &szCmdHistory[nCmdCursor][0];
memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);
nCmdInputCount = strlen(szCmdNow);
nCmdInputCursor= nCmdInputCount;
write(STDOUT_FILENO,szCmdNow,nCmdInputCount);
}
staticvoidApp_Console_OnLeft()
{
if(nCmdInputCursor > 0)
{
charc ='/b';
write(STDOUT_FILENO,&c,1);
nCmdInputCursor--;
}
}
staticvoidApp_Console_OnRight()
{
if(nCmdInputCursor
{
char* pCmd = szCmdNow;
charc = pCmd[nCmdInputCursor];
write(STDOUT_FILENO,&c,1);
nCmdInputCursor++;
}
}
staticvoidApp_Console_OnEnter()
{
szCmdNow[nCmdInputCount] ='/0';
charszTemp[] = {"/r/n"};
write(STDOUT_FILENO,szTemp,strlen(szTemp));
nCmdInputCount = 0;
nCmdInputCursor = 0;
if(strlen(szCmdNow) == 0)return;
if(nCmdIndex == MAX_CMD_HISTORY)// 命令队列满了,移动
{
charszTempCmd[MAX_CMD_HISTORY][MAX_CMD_LEN];
memcpy(szTempCmd,&szCmdHistory[1][0],MAX_CMD_LEN*(MAX_CMD_HISTORY-1));
memcpy(szCmdHistory,szTempCmd,MAX_CMD_LEN*(MAX_CMD_HISTORY-1));
nCmdIndex = MAX_CMD_HISTORY-1;
nCmdCursor = nCmdIndex;
}
memcpy(szCmdHistory[nCmdIndex],szCmdNow,MAX_CMD_LEN);
nCmdIndex++;
nCmdCursor = nCmdIndex;
// 解析命令
App_Console_ParseCmd(szCmdNow);
}
staticvoidApp_Console_CmdLoop()
{
BOOLbGetEnter = FALSE;
while(TRUE)
{
// 读取一个console输入
UINT32nReturn = 0;
charinput;
nReturn = App_Console_ReadInput (&input);
if(nReturn > 0)
{
switch(waitKeyState)
{
caseWKS_WAIT :
if(isprint(input))// 可打印字符
App_Console_OnPrintChar(input);
else
{
if(input == KEY_BACKSPACE)
App_Console_OnBackspace();
elseif(input == KEY_DEL)
App_Console_OnDel();
elseif(input == KEY_ENTER)
{
App_Console_OnEnter();
bGetEnter = TRUE;
}
elseif(input =='/x1b')
waitKeyState = WKS_RECV1B;
else
waitKeyState = WKS_WAIT;
}
break;
caseWKS_RECV1B:
if(input =='/x1b')// 按了ESC 又按了方向键,或者是 ESC
{
//App_Console_OnDoubleEsc();
waitKeyState = WKS_RECV1B;
}
else
if(input =='[')//可能为 上下左右 4个键
waitKeyState = WKS_UDLR;
else//下面的情况为 按了 ESC 键之后,按了其他的键的处理
{
if(isprint(input)) App_Console_OnPrintChar(input);
waitKeyState = WKS_WAIT;
}
break;
caseWKS_UDLR:
if(input =='A')// 上
App_Console_OnUp();
elseif(input =='B')// 下
App_Console_OnDown();
elseif(input =='D')// 左
App_Console_OnLeft();
elseif(input =='C')// 右
App_Console_OnRight();
else
{
if(isprint(input)) App_Console_OnPrintChar(input);
}
waitKeyState = WKS_WAIT;
break;
default:
break;
}
}
if(bGetEnter)
{
break;
}
}
}
voidApp_Console_Start()
{
// 清空 sdtout 缓冲
fflush(stdout);
fflush(stdin);
charszTemp[] = {"/r/nStart TR Console.../r/n/r/n"};
write(STDOUT_FILENO,szTemp,strlen(szTemp));
while(TRUE)
{
write(STDOUT_FILENO,szPrompt,strlen(szPrompt));
App_Console_CmdLoop();
}
}
// 解析命令
staticvoidApp_Console_ParseCmd(constchar* pCmd)
{
intlength = strlen(pCmd);
// 全部转小写
inti=0;
charszTempCmd[MAX_CMD_LEN];
for(i=0; i
// 将输入的命令各个 part 分开
charszPart[MAX_PAR_COUNT][MAX_CMD_LEN];
intnPartCount = 0;
intnPartCursor = 0;
intnCmdCursor = 0;
memset(szPart,0,sizeof(szPart));
while(TRUE)
{
if(nCmdCursor == length)
{
if(nPartCursor > 0)
{
nPartCount++;
nPartCursor = 0;
}
break;
}
if( (szTempCmd[nCmdCursor] ==',') || (szTempCmd[nCmdCursor] ==' ') )// part 分割符
{
szPart[nPartCount][nPartCursor] ='/0';
nPartCount++;
nPartCursor = 0;
}
else
{
szPart[nPartCount][nPartCursor] = szTempCmd[nCmdCursor];
nPartCursor++;
}
nCmdCursor++;
}
App_Test_OnCmd(szPart,nPartCount);
}#include "app_console.h"
#include "ctype.h"
#include "unistd.h"
#include "app_test.h"
// 说明
// read write 使用的是 POSIX 的标准文件读写函数
// unistd.h 包含了 STDIN_FILENO 等文件描述符的定义
// ctype.h 包含了 isprint 函数的声明
// 经过仔细考虑,决定不支持 ESC 键,因为ESC 键的键值为 0x1b 与 上下左右的键值重复
// 但可以考虑按2下ESC清除本行输入
// 对不可打印字符的处理仅限于以下已经列出的宏定义
// change:
// 放弃对 double ESC 的支持,因为可能出现按了 ESC 又按了 方向键 的情况
// 则用户输入编码为 '/x1b' '/x1b' '[' 'A' (按了ESC 又按了上键)
// change:
// 为了将应用与控制台应用剥离,则将 #define MAX_CMD_LEN 512 房到 app_test.h 中定义
// 二维数组作为参数进行传递时,需要明确第二个维度的大小,否则编译器无法正确定位地址
#define KEY_BACKSPACE '/x08' // back space
#define KEY_DEL '/x7F' // del
#define KEY_ENTER '/x0A' // 回车
// 以下为 0x1b 开头的键值
//#define KEY_DOUBLEESC "/x1B/x1B"// ESC
//#define KEY_ARROW_UP "/x1B[A" // 上
//#define KEY_ARROW_DOWN "/x1B[B" // 下
//#define KEY_ARROW_LEFT "/x1B[D" // 左
//#define KEY_ARROW_RIGHT "/x1B[C" // 右
typedef enum
{
WKS_WAIT,
WKS_RECV1B,
WKS_UDLR,
}T_WaitKeyState;
#define MAX_CMD_HISTORY 32
#define MAX_PAR_COUNT 16
static char szPrompt[] = {"TR_Console> "};
static T_WaitKeyState waitKeyState = WKS_WAIT;
static char szCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LEN];
static char szCmdNow[MAX_CMD_LEN] = {0};
static UINT32 nCmdIndex = 0;
static UINT32 nCmdCursor = 0;
static UINT32 nCmdInputCount = 0;
static UINT32 nCmdInputCursor = 0;
static void App_Console_ParseCmd(const char* pCmd);
static UINT32 App_Console_ReadInput(char *input)
{
U32 nRead=0;
struct pollfd p;
struct termio term,term_old;
/* Get control of the terminal */
ioctl(STDIN_FILENO,TCGETA,(void *)&term);
term_old = term;
term.c_lflag &= ~ICANON;
term.c_lflag &= ~ECHO;
ioctl(STDIN_FILENO,TCSETAW,(void *)&term);
/* Get event we want to know */
p.fd = STDIN_FILENO;
p.events = POLLIN;
/* If we receive one thing, get the byte now */
if (poll(&p,1,-1)>0)
{
if (p.revents==POLLIN)
{
nRead=read(STDIN_FILENO,input,1);
}
}
/* Purge the byte */
/* tcflush(0,TCIOFLUSH); */
/* Leave control */
ioctl(STDIN_FILENO,TCSETAW,(void *)&term_old);
return(nRead);
}
static void App_Console_BSChar()
{
char szTemp[3];
szTemp[0] = '/b';
szTemp[1] = ' ';
szTemp[2] = '/b';
write(STDOUT_FILENO,szTemp,3);
}
static void App_Console_OnPrintChar(char input)
{
if(nCmdInputCount == MAX_CMD_LEN) return;
if(nCmdInputCursor < nCmdInputCount) // 光标不在末尾
{
char szTemp[MAX_CMD_LEN] = {0};
char* pCmd = szCmdNow;
int nBackCount = nCmdInputCount-nCmdInputCursor;
szTemp[0] = input;
memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);
write(STDOUT_FILENO,szTemp,nBackCount+1);
memcpy(&pCmd[nCmdInputCursor],&szTemp,nBackCount+1);
memset(szTemp,'/b',nBackCount);
write(STDOUT_FILENO,szTemp,nBackCount);
}
else
{
write(STDOUT_FILENO,&input,1);
szCmdNow[nCmdInputCount] = input;
}
nCmdInputCursor++;
nCmdInputCount++;
}
static void App_Console_OnBackspace()
{
if(nCmdInputCursor > 0)
{
if(nCmdInputCursor == nCmdInputCount) // 光标在末尾
App_Console_BSChar();
else// 光标不在末尾
{
char szTemp[MAX_CMD_LEN] = {0};
char* pCmd = szCmdNow;
int nBackCount = nCmdInputCount-nCmdInputCursor;
szTemp[0] = '/b';
memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);
szTemp[nBackCount+1] = ' ';
write(STDOUT_FILENO,szTemp,nBackCount+2);
memcpy(&pCmd[nCmdInputCursor-1],&szTemp[1],nBackCount);
memset(szTemp,'/b',nBackCount+1);
write(STDOUT_FILENO,szTemp,nBackCount+1);
}
nCmdInputCount --;
nCmdInputCursor--;
}
}
static void App_Console_OnDel()
{
if(nCmdInputCursor < nCmdInputCount) // 光标不在末尾
{
char szTemp[MAX_CMD_LEN] = {0};
char* pCmd = szCmdNow;
int nBackCount = nCmdInputCount-nCmdInputCursor-1;
memcpy(szTemp,&pCmd[nCmdInputCursor+1],nBackCount);
szTemp[nBackCount] = ' ';
write(STDOUT_FILENO,szTemp,nBackCount+1);
memcpy(&pCmd[nCmdInputCursor],szTemp,nBackCount);
memset(szTemp,'/b',nBackCount+1);
write(STDOUT_FILENO,szTemp,nBackCount+1);
nCmdInputCount--;
}
}
static void App_Console_OnDoubleEsc()
{
if(nCmdInputCount > 0)
{
char* pCmd = szCmdNow;
// 将光标移动到最末尾
while(nCmdInputCursor < nCmdInputCount)
{
write(STDOUT_FILENO,&pCmd[nCmdInputCursor],1);
nCmdInputCursor++;
}
// 清除所有输入的数据
int i=0;
for(i=0;i
nCmdInputCount = 0;
nCmdInputCursor = 0;
}
}
static void App_Console_OnUp()
{
if(nCmdCursor == 0) return;
nCmdCursor --;
// 清除掉现在所有的输入
App_Console_OnDoubleEsc();
char* pCmdHistory = &szCmdHistory[nCmdCursor][0];
memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);
nCmdInputCount = strlen(szCmdNow);
nCmdInputCursor= nCmdInputCount;
write(STDOUT_FILENO,szCmdNow,nCmdInputCount);
}
static void App_Console_OnDown()
{
if(nCmdCursor >= (nCmdIndex-1)) return;
nCmdCursor ++;
// 清除掉现在所有的输入
App_Console_OnDoubleEsc();
char* pCmdHistory = &szCmdHistory[nCmdCursor][0];
memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);
nCmdInputCount = strlen(szCmdNow);
nCmdInputCursor= nCmdInputCount;
write(STDOUT_FILENO,szCmdNow,nCmdInputCount);
}
static void App_Console_OnLeft()
{
if(nCmdInputCursor > 0)
{
char c = '/b';
write(STDOUT_FILENO,&c,1);
nCmdInputCursor--;
}
}
static void App_Console_OnRight()
{
if(nCmdInputCursor < nCmdInputCount)
{
char* pCmd = szCmdNow;
char c = pCmd[nCmdInputCursor];
write(STDOUT_FILENO,&c,1);
nCmdInputCursor++;
}
}
static void App_Console_OnEnter()
{
szCmdNow[nCmdInputCount] = '/0';
char szTemp[] = {"/r/n"};
write(STDOUT_FILENO,szTemp,strlen(szTemp));
nCmdInputCount = 0;
nCmdInputCursor = 0;
if(strlen(szCmdNow) == 0) return;
if(nCmdIndex == MAX_CMD_HISTORY) // 命令队列满了,移动
{
char szTempCmd[MAX_CMD_HISTORY][MAX_CMD_LEN];
memcpy(szTempCmd,&szCmdHistory[1][0],MAX_CMD_LEN*(MAX_CMD_HISTORY-1));
memcpy(szCmdHistory,szTempCmd,MAX_CMD_LEN*(MAX_CMD_HISTORY-1));
nCmdIndex = MAX_CMD_HISTORY-1;
nCmdCursor = nCmdIndex;
}
memcpy(szCmdHistory[nCmdIndex],szCmdNow,MAX_CMD_LEN);
nCmdIndex++;
nCmdCursor = nCmdIndex;
// 解析命令
App_Console_ParseCmd(szCmdNow);
}
static void App_Console_CmdLoop()
{
BOOL bGetEnter = FALSE;
while(TRUE)
{
// 读取一个console输入
UINT32 nReturn = 0;
char input;
nReturn = App_Console_ReadInput (&input);
if(nReturn > 0)
{
switch(waitKeyState)
{
case WKS_WAIT :
if(isprint(input))// 可打印字符
App_Console_OnPrintChar(input);
else
{
if(input == KEY_BACKSPACE)
App_Console_OnBackspace();
else if(input == KEY_DEL)
App_Console_OnDel();
else if(input == KEY_ENTER)
{
App_Console_OnEnter();
bGetEnter = TRUE;
}
else if(input == '/x1b')
waitKeyState = WKS_RECV1B;
else
waitKeyState = WKS_WAIT;
}
break;
case WKS_RECV1B:
if(input == '/x1b') // 按了ESC 又按了方向键,或者是 ESC
{
//App_Console_OnDoubleEsc();
waitKeyState = WKS_RECV1B;
}
else
if(input == '[') //可能为 上下左右 4个键
waitKeyState = WKS_UDLR;
else//下面的情况为 按了 ESC 键之后,按了其他的键的处理
{
if(isprint(input)) App_Console_OnPrintChar(input);
waitKeyState = WKS_WAIT;
}
break;
case WKS_UDLR:
if(input == 'A')// 上
App_Console_OnUp();
else if(input == 'B')// 下
App_Console_OnDown();
else if(input == 'D')// 左
App_Console_OnLeft();
else if(input == 'C')// 右
App_Console_OnRight();
else
{
if(isprint(input)) App_Console_OnPrintChar(input);
}
waitKeyState = WKS_WAIT;
break;
default:
break;
}
}
if(bGetEnter)
{
break;
}
}
}
void App_Console_Start()
{
// 清空 sdtout 缓冲
fflush(stdout);
fflush(stdin);
char szTemp[] = {"/r/nStart TR Console.../r/n/r/n"};
write(STDOUT_FILENO,szTemp,strlen(szTemp));
while(TRUE)
{
write(STDOUT_FILENO,szPrompt,strlen(szPrompt));
App_Console_CmdLoop();
}
}
// 解析命令
static void App_Console_ParseCmd(const char* pCmd)
{
int length = strlen(pCmd);
// 全部转小写
int i=0;
char szTempCmd[MAX_CMD_LEN];
for (i=0; i < length; i++) szTempCmd[i] = tolower(pCmd[i]);
// 将输入的命令各个 part 分开
char szPart[MAX_PAR_COUNT][MAX_CMD_LEN];
int nPartCount = 0;
int nPartCursor = 0;
int nCmdCursor = 0;
memset(szPart,0,sizeof(szPart));
while(TRUE)
{
if(nCmdCursor == length)
{
if(nPartCursor > 0)
{
nPartCount++;
nPartCursor = 0;
}
break;
}
if( (szTempCmd[nCmdCursor] == ',') || (szTempCmd[nCmdCursor] == ' ') ) // part 分割符
{
szPart[nPartCount][nPartCursor] = '/0';
nPartCount++;
nPartCursor = 0;
}
else
{
szPart[nPartCount][nPartCursor] = szTempCmd[nCmdCursor];
nPartCursor++;
}
nCmdCursor++;
}
App_Test_OnCmd(szPart,nPartCount);
}
命令实现头文件(app_test.h)
#ifndef __APP_TEST_H__
#define __APP_TEST_H__
#ifdef __cplusplus
extern"C"
{
#endif
#include "type_def.h"
#define MAX_CMD_LEN 512
voidApp_Test_OnCmd(charszPart[][MAX_CMD_LEN],intnPartCount);
#ifdef __cplusplus
}
#endif
#endif#ifndef __APP_TEST_H__
#define __APP_TEST_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "type_def.h"
#define MAX_CMD_LEN 512
void App_Test_OnCmd(char szPart[][MAX_CMD_LEN],int nPartCount);
#ifdef __cplusplus
}
#endif
#endif
命令实现c文件(app_test.c)
#include "app_test.h"
#include "stapp_main.h"
#include "app_qam.h"
#include "api_av.h"
#include "api_video.h"
#include "api_audio.h"
#include "api_pcr.h"
staticvoidApp_Test_OnHelp();
staticvoidApp_Test_OnWriteReg8(charszPart[][MAX_CMD_LEN],intnPartCount);
staticvoidApp_Test_OnReadReg8(charszPart[][MAX_CMD_LEN],intnPartCount);
staticvoidApp_Test_OnQamConnect(charszPart[][MAX_CMD_LEN],intnPartCount);
staticvoidApp_Test_OnAVPlayMpeg(charszPart[][MAX_CMD_LEN],intnPartCount);
staticvoidApp_Test_OnAVStop();
staticvoidApp_Test_OnVolumeSet(charszPart[][MAX_CMD_LEN],intnPartCount);
staticvoidApp_Test_OnMute();
staticvoidApp_Test_OnUnmute();
staticvoidApp_Test_OnDENCRegDum();
staticvoidApp_Test_OnDENCRegSet(charszPart[][MAX_CMD_LEN],intnPartCount);
voidApp_Test_OnCmd(charszPart[][MAX_CMD_LEN],intnPartCount)
{
// 这里处理私有的命令
if(nPartCount == 0)return;
if( strcmp(szPart[0],"help") == 0)
{
App_Test_OnHelp();
}
elseif( strcmp(szPart[0],"writereg8") == 0)
{
if(nPartCount > 2) App_Test_OnWriteReg8(szPart,nPartCount);
}
elseif( strcmp(szPart[0],"readreg8") == 0)
{
if(nPartCount > 1) App_Test_OnReadReg8(szPart,nPartCount);
}
elseif( strcmp(szPart[0],"qamconnect") == 0)
{
if(nPartCount > 1) App_Test_OnQamConnect(szPart,nPartCount);
}
elseif( strcmp(szPart[0],"avplaympeg") == 0)
{
if(nPartCount > 1) App_Test_OnAVPlayMpeg(szPart,nPartCount);
}
elseif( strcmp(szPart[0],"avstop") == 0)
{
App_Test_OnAVStop();
}
elseif( strcmp(szPart[0],"volumeset") == 0)
{
if(nPartCount > 1) App_Test_OnVolumeSet(szPart,nPartCount);
}
elseif( strcmp(szPart[0],"mute") == 0)
{
App_Test_OnMute();
}
elseif( strcmp(szPart[0],"unmute") == 0)
{
App_Test_OnUnmute();
}
elseif( strcmp(szPart[0],"dencregdump") == 0)
{
App_Test_OnDENCRegDum();
}
elseif( strcmp(szPart[0],"dencregset") == 0)
{
if(nPartCount > 1) App_Test_OnDENCRegSet(szPart,nPartCount);
}
}
staticvoidApp_Test_OnHelp()
{
printf("**************************************************************/n");
printf("* Help PARAM MUST 0 MAX 0 Eg. help/n");
printf("* WriteReg8 PARAM MUST 2 MAX 2 Eg. WriteReg8 0x1920C114 128/n");
printf("* ReadReg8 PARAM MUST 1 MAX 1 Eg. ReadReg8 0x1920C114/n");
printf("* QamConnect PARAM MUST 1 MAX 3 Eg. QamConnect 546000/n");
printf("* AVPlayMpeg PARAM MUST 1 MAX 3 Eg. AVPlayMpeg 64 63 32/n");
printf("* AVStop PARAM MUST 0 MAX 0 Eg. AVStop/n");
printf("* VolumeSet PARAM MUST 1 MAX 1 Eg. VolumeSet 63/n");
printf("* Mute PARAM MUST 0 MAX 0 Eg. Mute/n");
printf("* Unmute PARAM MUST 0 MAX 0 Eg. Unmute/n");
printf("* DENCRegDump PARAM MUST 0 MAX 0 Eg. DENCRegDump/n");
printf("* DENCRegSet PARAM MUST 1 MAX 1 Eg. DENCRegSet 1/n");
printf("*************************************************************/n");
}
staticvoidApp_Test_OnWriteReg8(charszPart[][MAX_CMD_LEN],intnPartCount)
{
char* pAddress = &szPart[1][0];
char* pValue = &szPart[2][0];
DWORDdwAddress = 0;
UINT8 nValue = atoi(pValue);
sscanf(pAddress,"0x%08x",&dwAddress);
SYS_WriteRegDev8(dwAddress,nValue);
}
staticvoidApp_Test_OnQamConnect(charszPart[][MAX_CMD_LEN],intnPartCount)
{
char* pFreq = &szPart[1][0];
UINT32nFreq = atoi(pFreq);
UINT32nSymbolRate = 6875;
T_DMD_Modulation nQAMMode = QAM_64;
if(nPartCount > 2)
{
char* pSymbolRate = &szPart[2][0];
nSymbolRate = atoi(pSymbolRate);
}
if(nPartCount > 3)
{
char* pQAMMode = &szPart[3][0];
nQAMMode = atoi(pQAMMode);
}
App_Qam_Locking(TRUE,nFreq,nSymbolRate,nQAMMode);
}
staticvoidApp_Test_OnAVPlayMpeg(charszPart[][MAX_CMD_LEN],intnPartCount)
{
UINT16 nVideoPid = 0xFFFF;
UINT16 nAudioPid = 0xFFFF;
UINT16 nPcrPid = 0xFFFF;
char* pAudioPid = &szPart[1][0];
nAudioPid = atoi(pAudioPid);
if(nPartCount > 2)
{
char* pVideoPid = &szPart[2][0];
nVideoPid = atoi(pVideoPid);
}
if(nPartCount > 3)
{
char* pPcr = &szPart[3][0];
nPcrPid = atoi(pPcr);
}
Api_Av_Stop();
Api_Av_Start(nAudioPid,STREAMTYPE_MP2A,nVideoPid,STREAMTYPE_MP2V,nPcrPid);
}
staticvoidApp_Test_OnVolumeSet(charszPart[][MAX_CMD_LEN],intnPartCount)
{
UINT16 nVolume = 0;
char* pVolume = &szPart[1][0];
nVolume = atoi(pVolume);
Api_Audio_Volume_Set(nVolume);
}
staticvoidApp_Test_OnMute()
{
Api_Audio_Mute();
}
staticvoidApp_Test_OnUnmute()
{
Api_Audio_Unmute();
}
staticvoidApp_Test_OnAVStop()
{
Api_Av_Stop();
}
staticvoidApp_Test_OnDENCRegDum()
{
printf("* Brightness 0x1920C114 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C114));
printf("* Contrast 0x1920C118 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C118));
printf("* Saturation 0x1920C11c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C11c));
printf("* CHROMA_COEF0 0x1920C120 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C120));
printf("* CHROMA_COEF1 0x1920C124 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C124));
printf("* CHROMA_COEF2 0x1920C128 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C128));
printf("* CHROMA_COEF3 0x1920C12c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C12c));
printf("* CHROMA_COEF4 0x1920C130 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C130));
printf("* CHROMA_COEF5 0x1920C134 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C134));
printf("* CHROMA_COEF6 0x1920C138 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C138));
printf("* CHROMA_COEF7 0x1920C13c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C13c));
printf("* CHROMA_COEF8 0x1920C140 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C140));
printf("* LUM_COEF0 0x1920C148 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C148));
printf("* LUM_COEF1 0x1920C14c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C14c));
printf("* LUM_COEF2 0x1920C150 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C150));
printf("* LUM_COEF3 0x1920C154 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C154));
printf("* LUM_COEF4 0x1920C158 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C158));
printf("* LUM_COEF5 0x1920C15c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C15c));
printf("* LUM_COEF6 0x1920C160 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C160));
printf("* LUM_COEF7 0x1920C164 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C164));
printf("* LUM_COEF8 0x1920C168 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C168));
printf("* LUM_COEF9 0x1920C16c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C16c));
printf("* CFG9 0x1920C144 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C144));
}
staticvoidApp_Test_OnDENCRegSet(charszPart[][MAX_CMD_LEN],intnPartCount)
{
UINT16 nScheme = 1;
char* pScheme = &szPart[1][0];
nScheme = atoi(pScheme);
switch(nScheme)
{
case1:
break;
case2:
break;
case3:
break;
case4:
break;
default:
break;
}
}
staticvoidApp_Test_OnReadReg8(charszPart[][MAX_CMD_LEN],intnPartCount)
{
char* pAddress = &szPart[1][0];
DWORDdwAddress = 0;
sscanf(pAddress,"0x%08x",&dwAddress);
printf("* 0x%08x value is 0x%02x/n",dwAddress,SYS_ReadRegDev8(dwAddress));
}
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)