Initial import of NFC GNSS SDK project
This commit is contained in:
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Author: Chandra Mohan C (willvalab@gmail.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style license that can be found
|
||||
* in the LICENSE file.
|
||||
*
|
||||
**-----------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "./uartshConfig.h"
|
||||
#include "./uartsh.h"
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
#define HISTORY_COUNT (UARTSH_CONFIG_COMMAND_HISTORY_COUNT + 1)
|
||||
|
||||
#define KEY_BS 0X08
|
||||
#define KEY_DEL 0X7F
|
||||
#define KEY_ESC_SEQ1 0X1B
|
||||
#define KEY_SPECIAL_UP 'A'
|
||||
#define KEY_SPECIAL_DOWN 'B'
|
||||
#define KEY_SPECIAL_LEFT 'D'
|
||||
#define KEY_SPECIAL_RIGHT 'C'
|
||||
#define KEY_ESC_SEQ2 '['
|
||||
#define KEY_ESC_SEQ3 '3'
|
||||
#define KEY_ESC_SEQ4 '~'
|
||||
|
||||
#define FLAG_ESC_SEQ1 1
|
||||
#define FLAG_ESC_SEQ2 2
|
||||
#define FLAG_ESC_SEQ3 3
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
struct UartshEditBuffer
|
||||
{
|
||||
int cCount;
|
||||
char buffer[UARTSH_CONFIG_COMMAND_STRING_SIZE];
|
||||
};
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
#include "hal_api.h"
|
||||
|
||||
#define UARTSH_DEFAULT_TIMEOUT 60000
|
||||
#define UARTSH_CMD_TIMEOUT 60000*2
|
||||
|
||||
|
||||
void *g_uartsh_mutex = NULL;
|
||||
|
||||
static int uart_putchar(sh_cust_type_t *cust_sh, int charx)
|
||||
{
|
||||
return cust_sh->write_func(cust_sh->handler,(unsigned char *)&charx,1,100);
|
||||
}
|
||||
|
||||
static char uart_getchar(sh_cust_type_t *cust_sh)
|
||||
{
|
||||
char charx=0;
|
||||
int ret;
|
||||
|
||||
do{
|
||||
if(cust_sh->run_flag==1){
|
||||
break;
|
||||
}
|
||||
ret=cust_sh->read_func(cust_sh->handler,(unsigned char *)&charx,1,100);
|
||||
if(ret==1){
|
||||
//cust_sh->time_out_uptime = hal_os_up_time_ms();
|
||||
break;
|
||||
}
|
||||
if(ret<0){
|
||||
hal_os_task_sleep_ms(100);
|
||||
}else{
|
||||
hal_os_task_sleep_ms(10);
|
||||
}
|
||||
|
||||
if((cust_sh->timeout_enable)&&(hal_os_up_time_ms() - cust_sh->time_out_uptime > cust_sh->time_out)){
|
||||
cust_sh->run_flag = 1;
|
||||
break;
|
||||
}
|
||||
}while(ret!=1);
|
||||
|
||||
return charx;
|
||||
}
|
||||
|
||||
void uartsh_puts(sh_cust_type_t *cust_sh, char const* s)
|
||||
{
|
||||
if(cust_sh->handler==NULL)return;
|
||||
#if 0
|
||||
char c = 0;
|
||||
|
||||
while( (c = *s++) )
|
||||
{
|
||||
uart_putchar(c);
|
||||
}
|
||||
#else
|
||||
int len = strlen(s);
|
||||
if(s[len-2]!='\r' && s[len-1]== '\n'){
|
||||
cust_sh->write_func(cust_sh->handler,(unsigned char *)s,strlen(s)-1,1000);
|
||||
cust_sh->write_func(cust_sh->handler,(unsigned char *)"\r\n",2,1000);
|
||||
}else{
|
||||
cust_sh->write_func(cust_sh->handler,(unsigned char *)s,strlen(s),1000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int uartsh_printf(sh_cust_type_t *cust_sh, const char *fmt, ...)
|
||||
{
|
||||
char buf[512]={0};
|
||||
int len=0;
|
||||
|
||||
if(cust_sh->handler==NULL)return -1;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf,sizeof(buf)-1,fmt,ap);
|
||||
va_end(ap);
|
||||
len = strlen(buf);
|
||||
if(buf[len-2]!='\r' && buf[len-1]== '\n'){
|
||||
cust_sh->write_func(cust_sh->handler,(unsigned char *)buf,len-1,1000);
|
||||
uartsh_puts(cust_sh,"\r\n");
|
||||
}else{
|
||||
cust_sh->write_func(cust_sh->handler,(unsigned char *)buf,len,1000);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
static inline void handleDeleteKey(sh_cust_type_t *cust_sh, struct UartshEditBuffer* pEditBuffer,
|
||||
size_t* pCursor)
|
||||
{
|
||||
unsigned int cursor = *pCursor;
|
||||
|
||||
if( cursor < pEditBuffer->cCount )
|
||||
{
|
||||
int b = (pEditBuffer->cCount - cursor);
|
||||
memcpy(&pEditBuffer->buffer[cursor],
|
||||
&pEditBuffer->buffer[cursor + 1],
|
||||
b);
|
||||
pEditBuffer->buffer[--pEditBuffer->cCount] = '\0';
|
||||
|
||||
uart_putchar(cust_sh,' ');
|
||||
uart_putchar(cust_sh,'\b');
|
||||
uartsh_puts(cust_sh,&pEditBuffer->buffer[cursor]);
|
||||
uart_putchar(cust_sh,' ');
|
||||
while(b--)
|
||||
uart_putchar(cust_sh,'\b');
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
unsigned int uartsh_gets(sh_cust_type_t *cust_sh, char** input)
|
||||
{
|
||||
static struct UartshEditBuffer editBuffer[HISTORY_COUNT] = { { 0, }, };
|
||||
static int bufferIndex = 0;
|
||||
static int bufferIndexMax = 0;
|
||||
|
||||
if( editBuffer[bufferIndex].cCount )
|
||||
{
|
||||
if( bufferIndexMax < (HISTORY_COUNT - 1) )
|
||||
bufferIndexMax++;
|
||||
|
||||
bufferIndex++;
|
||||
if( bufferIndex > bufferIndexMax )
|
||||
bufferIndex = 0;
|
||||
}
|
||||
|
||||
struct UartshEditBuffer* pEditBuffer = &editBuffer[bufferIndex];
|
||||
pEditBuffer->cCount = 0;
|
||||
pEditBuffer->buffer[0] = '\0';
|
||||
|
||||
int hi = bufferIndex;
|
||||
size_t cursor = 0;
|
||||
char specialKey = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
char c = (char) uart_getchar(cust_sh);
|
||||
if(cust_sh->run_flag==1){
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if (UARTSH_CONFIG_END_CHAR & UARTSH_END_CHAR_CR)
|
||||
if( c == '\r' )
|
||||
{
|
||||
#if (UARTSH_CONFIG_END_CHAR == UARTSH_END_CHAR_CRLF)
|
||||
c = (char) uart_getchar(cust_sh);
|
||||
if( c != '\n')
|
||||
continue;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#elif (UARTSH_CONFIG_END_CHAR & UARTSH_END_CHAR_LF)
|
||||
if( c == '\n' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch( specialKey )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
specialKey = 0;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case KEY_ESC_SEQ1:
|
||||
{
|
||||
specialKey = FLAG_ESC_SEQ1;
|
||||
} break;
|
||||
|
||||
case UARTSH_CONFIG_KEY_BACKSPACE:
|
||||
{
|
||||
if( cursor )
|
||||
{
|
||||
cursor--;
|
||||
int b = (pEditBuffer->cCount - cursor);
|
||||
memcpy(&pEditBuffer->buffer[cursor],
|
||||
&pEditBuffer->buffer[cursor + 1],
|
||||
b);
|
||||
pEditBuffer->buffer[--pEditBuffer->cCount] = '\0';
|
||||
|
||||
uart_putchar(cust_sh,'\b');
|
||||
uartsh_puts(cust_sh,&pEditBuffer->buffer[cursor]);
|
||||
uart_putchar(cust_sh,' ');
|
||||
while(b--)
|
||||
uart_putchar(cust_sh,'\b');
|
||||
}
|
||||
} break;
|
||||
|
||||
#if (UARTSH_CONFIG_KEY_BACKSPACE != UARTSH_DELETE_KEY)
|
||||
case KEY_DEL:
|
||||
{
|
||||
handleDeleteKey(cust_sh, pEditBuffer, &cursor );
|
||||
} break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
//only alphabets and special characters allowed
|
||||
if( (c >= 0x20) && (c <= 0x7e) )
|
||||
{
|
||||
if( pEditBuffer->cCount < (UARTSH_CONFIG_COMMAND_STRING_SIZE - 1) )
|
||||
{
|
||||
// insertion
|
||||
int i = pEditBuffer->cCount;
|
||||
while( i > cursor )
|
||||
{
|
||||
pEditBuffer->buffer[i] = pEditBuffer->buffer[i - 1];
|
||||
i--;
|
||||
}
|
||||
|
||||
pEditBuffer->buffer[cursor] = c;
|
||||
pEditBuffer->cCount++;
|
||||
pEditBuffer->buffer[pEditBuffer->cCount] = '\0';
|
||||
uartsh_puts(cust_sh,&pEditBuffer->buffer[cursor]);
|
||||
cursor++;
|
||||
|
||||
i = (pEditBuffer->cCount - cursor);
|
||||
while(i--)
|
||||
uart_putchar(cust_sh,'\b');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case FLAG_ESC_SEQ1:
|
||||
{
|
||||
specialKey = 0;
|
||||
|
||||
if( c == KEY_ESC_SEQ2 )
|
||||
specialKey = FLAG_ESC_SEQ2;
|
||||
}break;
|
||||
|
||||
case FLAG_ESC_SEQ2:
|
||||
{
|
||||
specialKey = 0;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case KEY_SPECIAL_UP:
|
||||
{
|
||||
while( cursor-- )
|
||||
uart_putchar(cust_sh,'\b');
|
||||
|
||||
int oldCount = pEditBuffer->cCount;
|
||||
|
||||
hi--;
|
||||
if( hi < 0 )
|
||||
hi = bufferIndexMax;
|
||||
|
||||
if( hi == bufferIndex )
|
||||
{
|
||||
pEditBuffer->cCount = 0;
|
||||
pEditBuffer->buffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pEditBuffer->cCount = editBuffer[hi].cCount;
|
||||
memcpy(pEditBuffer->buffer, editBuffer[hi].buffer, (pEditBuffer->cCount + 1));
|
||||
}
|
||||
|
||||
uartsh_puts(cust_sh,pEditBuffer->buffer);
|
||||
cursor = pEditBuffer->cCount;
|
||||
|
||||
if( oldCount > pEditBuffer->cCount )
|
||||
{
|
||||
int move = (oldCount - pEditBuffer->cCount);
|
||||
while( move-- )
|
||||
uart_putchar(cust_sh,' ');
|
||||
move = (oldCount - pEditBuffer->cCount);
|
||||
while( move-- )
|
||||
uart_putchar(cust_sh,'\b');
|
||||
}
|
||||
} break;
|
||||
|
||||
case KEY_SPECIAL_DOWN:
|
||||
{
|
||||
while( cursor-- )
|
||||
uart_putchar(cust_sh,'\b');
|
||||
|
||||
int oldCount = pEditBuffer->cCount;
|
||||
|
||||
hi++;
|
||||
if( hi > bufferIndexMax )
|
||||
hi = 0;
|
||||
|
||||
if( hi == bufferIndex )
|
||||
{
|
||||
pEditBuffer->cCount = 0;
|
||||
pEditBuffer->buffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pEditBuffer->cCount = editBuffer[hi].cCount;
|
||||
memcpy(pEditBuffer->buffer, editBuffer[hi].buffer, (pEditBuffer->cCount + 1));
|
||||
}
|
||||
|
||||
uartsh_puts(cust_sh,pEditBuffer->buffer);
|
||||
cursor = pEditBuffer->cCount;
|
||||
|
||||
if( oldCount > pEditBuffer->cCount )
|
||||
{
|
||||
int move = (oldCount - pEditBuffer->cCount);
|
||||
while( move-- )
|
||||
uart_putchar(cust_sh,' ');
|
||||
move = (oldCount - pEditBuffer->cCount);
|
||||
while( move-- )
|
||||
uart_putchar(cust_sh,'\b');
|
||||
}
|
||||
} break;
|
||||
|
||||
case KEY_SPECIAL_LEFT:
|
||||
{
|
||||
if( cursor )
|
||||
{
|
||||
uart_putchar(cust_sh,'\b');
|
||||
cursor--;
|
||||
}
|
||||
} break;
|
||||
|
||||
case KEY_SPECIAL_RIGHT:
|
||||
{
|
||||
if( cursor < pEditBuffer->cCount )
|
||||
{
|
||||
uart_putchar(cust_sh,pEditBuffer->buffer[cursor++]);
|
||||
}
|
||||
} break;
|
||||
|
||||
case KEY_ESC_SEQ3:
|
||||
{
|
||||
specialKey = FLAG_ESC_SEQ3;
|
||||
} break;
|
||||
}
|
||||
}break;
|
||||
|
||||
case FLAG_ESC_SEQ3:
|
||||
{
|
||||
specialKey = 0;
|
||||
|
||||
// deletion
|
||||
if( c == KEY_ESC_SEQ4 )
|
||||
{
|
||||
handleDeleteKey(cust_sh, pEditBuffer, &cursor );
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
//fflush(stdout);
|
||||
}
|
||||
|
||||
uartsh_puts(cust_sh,"\r\n");
|
||||
|
||||
// copy current buffer to next buffer only if current buffer has content
|
||||
if( pEditBuffer->cCount )
|
||||
{
|
||||
// as caller uses strtok passed buffer will be spoiled
|
||||
// copies current edit buffer's content to next buffer and passes to caller
|
||||
// next call makes use of passed buffer for editing
|
||||
int bi = (bufferIndex + 1);
|
||||
if( bi > (HISTORY_COUNT - 1) )
|
||||
bi = 0;
|
||||
|
||||
#if (HISTORY_COUNT >= 2) // as total buffer is 1, no point in copying to itself
|
||||
memcpy(editBuffer[bi].buffer, pEditBuffer->buffer, (pEditBuffer->cCount + 1));
|
||||
#endif
|
||||
|
||||
*input = editBuffer[bi].buffer;
|
||||
}
|
||||
|
||||
return pEditBuffer->cCount;
|
||||
}
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
int uartshTokenize(char commandString[], char const tokens[], int argcMax, char* argv[])
|
||||
{
|
||||
int argc = 0;
|
||||
char* token = strtok(commandString, tokens);
|
||||
while(token != NULL)
|
||||
{
|
||||
argv[argc++] = token;
|
||||
if( argc >= argcMax )
|
||||
break;
|
||||
|
||||
token = strtok(NULL, tokens);
|
||||
}
|
||||
|
||||
return argc;
|
||||
}
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
UartshCommandHandler uartshGetHandler(UartshCommand cmdlist[], char command[])
|
||||
{
|
||||
int commandLength = strlen(command);
|
||||
|
||||
int index = 0;
|
||||
while( cmdlist[index].name != NULL )
|
||||
{
|
||||
int appNameSize = strlen(cmdlist[index].name);
|
||||
|
||||
// extra check to ensure command length is exactly matching app length
|
||||
if( commandLength == appNameSize )
|
||||
{
|
||||
if( 0 == strncmp(command, cmdlist[index].name, appNameSize) )
|
||||
{
|
||||
return cmdlist[index].handler;
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
void uartsh_thread_cb(void *args)
|
||||
{
|
||||
char* argv[UARTSH_CONFIG_ARGC_MAX] = { 0, };
|
||||
int argc = 0;
|
||||
int first_flag = 0;
|
||||
sh_cust_type_t *cust_sh = args;
|
||||
|
||||
UartshCommand *cmdlist = cust_sh->cmd_list;
|
||||
|
||||
cust_sh->time_out = UARTSH_DEFAULT_TIMEOUT;
|
||||
cust_sh->time_out_uptime = hal_os_up_time_ms();
|
||||
|
||||
cust_sh->handler = cust_sh->open_func(cust_sh->port,cust_sh->configbuf);
|
||||
if(!cust_sh->handler){
|
||||
RLOGD("sh %s open error",cust_sh->name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RLOGD("shell %s runing",cust_sh->name);
|
||||
cust_sh->run_flag = 0;
|
||||
while(cust_sh->run_flag==0)
|
||||
{
|
||||
if(first_flag==1){
|
||||
//uartsh_puts(cust_sh,"\r\n");
|
||||
uartsh_printf(cust_sh,"cmd# ");
|
||||
}
|
||||
|
||||
first_flag=1;
|
||||
|
||||
char* commandString = NULL;
|
||||
int commandStringLength = 0;
|
||||
if( 0 == (commandStringLength = uartsh_gets(cust_sh,&commandString)) )
|
||||
continue;
|
||||
|
||||
if(cust_sh->run_flag==1){
|
||||
break;
|
||||
}
|
||||
|
||||
//uartsh_puts(cust_sh,commandString);
|
||||
argc = uartshTokenize(commandString, " \n", UARTSH_CONFIG_ARGC_MAX, argv);
|
||||
uartsh_puts(cust_sh,"\r\n");
|
||||
|
||||
size_t commandLength = strlen(argv[0]);
|
||||
if( 1 == argc )
|
||||
{
|
||||
if( commandLength == 4 )
|
||||
{
|
||||
if( 0 == strncmp("help", argv[0], 5) )
|
||||
{
|
||||
if( NULL == cmdlist )
|
||||
{
|
||||
uartsh_puts(cust_sh,"No commands found\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
uartsh_puts(cust_sh,"Supported commands are below:\r\n\n");
|
||||
int index = 0;
|
||||
while( cmdlist[index].name != NULL )
|
||||
{
|
||||
uartsh_puts(cust_sh," ");
|
||||
uartsh_puts(cust_sh,cmdlist[index++].name);
|
||||
uartsh_puts(cust_sh,"\r\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if( 0 == strncmp("exit", argv[0], 4) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( NULL == cmdlist )
|
||||
continue;
|
||||
|
||||
UartshCommandHandler handler = uartshGetHandler(cmdlist, argv[0]);
|
||||
if( NULL == handler ){
|
||||
RLOGD("\r\nUNKNOWN CMD\r\n");
|
||||
uartsh_puts(cust_sh,"\r\nUNKNOWN\r\n");
|
||||
//break;
|
||||
}else{
|
||||
RLOGD("\r\nEXEC CMD:%s\r\n", argv[0]);
|
||||
|
||||
if(g_uartsh_mutex==NULL){
|
||||
g_uartsh_mutex = hal_os_mutex_create();
|
||||
}
|
||||
hal_os_mutex_lock(g_uartsh_mutex);
|
||||
int myret = handler(cust_sh,argc, argv);
|
||||
if( myret != 0 ){
|
||||
uartsh_printf(cust_sh,"\r\nERROR %d\r\n",myret);
|
||||
}else{
|
||||
uartsh_printf(cust_sh,"\r\nOK\r\n");
|
||||
}
|
||||
|
||||
cust_sh->time_out_uptime = hal_os_up_time_ms();
|
||||
|
||||
cust_sh->time_out = UARTSH_CMD_TIMEOUT;
|
||||
|
||||
hal_os_mutex_unlock(g_uartsh_mutex);
|
||||
}
|
||||
|
||||
hal_os_task_sleep_ms(1);
|
||||
}
|
||||
|
||||
exit:
|
||||
if(cust_sh->handler){
|
||||
cust_sh->close_func(cust_sh->handler);
|
||||
}
|
||||
cust_sh->handler=NULL;
|
||||
cust_sh->run_flag =2;
|
||||
RLOGD("shell %s exit!", cust_sh->name);
|
||||
hal_os_task_destroy(&cust_sh->thread);
|
||||
}
|
||||
|
||||
int uartshInit(sh_cust_type_t *cust_sh)
|
||||
{
|
||||
|
||||
cust_sh->thread = hal_os_task_create(cust_sh->name,HAL_OS_TASK_PRIORITY_NORMAL,10*1024,uartsh_thread_cb,cust_sh);
|
||||
if(!cust_sh->thread){
|
||||
RLOGE("shthread thread error");
|
||||
cust_sh->run_flag = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uartshExit(sh_cust_type_t *cust_sh)
|
||||
{
|
||||
uint64_t start_ms = hal_os_up_time_ms();
|
||||
if(cust_sh->run_flag!=0)return -1;
|
||||
|
||||
cust_sh->run_flag=1;
|
||||
while (cust_sh->run_flag!=2)
|
||||
{
|
||||
if(hal_os_up_time_ms()-start_ms>10000)
|
||||
{
|
||||
cust_sh->run_flag = 1;
|
||||
return -1;
|
||||
}
|
||||
hal_os_task_sleep_ms(10);
|
||||
}
|
||||
cust_sh->run_flag=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uartshRunning(sh_cust_type_t *cust_sh)
|
||||
{
|
||||
if(cust_sh->run_flag==0 || cust_sh->run_flag==-1){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user