You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
477 lines
10 KiB
477 lines
10 KiB
|
7 months ago
|
//-----------------------------------------------------------------------------
|
||
|
|
// COPYRIGHT (C) 2020 CHIPS&MEDIA INC. ALL RIGHTS RESERVED
|
||
|
|
//
|
||
|
|
// This file is distributed under BSD 3 clause and LGPL2.1 (dual license)
|
||
|
|
// SPDX License Identifier: BSD-3-Clause
|
||
|
|
// SPDX License Identifier: LGPL-2.1-only
|
||
|
|
//
|
||
|
|
// The entire notice above must be reproduced on all authorized copies.
|
||
|
|
//
|
||
|
|
// Description :
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
#include <malloc.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <stdarg.h>
|
||
|
|
#include <errno.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#ifndef __USE_GNU
|
||
|
|
#define __USE_GNU
|
||
|
|
#endif
|
||
|
|
#include <pthread.h>
|
||
|
|
#include <semaphore.h>
|
||
|
|
#include "vpuconfig.h"
|
||
|
|
#include "vdi_osal.h"
|
||
|
|
|
||
|
|
#include <time.h>
|
||
|
|
#include <termios.h>
|
||
|
|
static struct termios initial_settings, new_settings;
|
||
|
|
static int peek_character = -1;
|
||
|
|
|
||
|
|
#define ANSI_COLOR_ERR "\x1b[31m" // RED
|
||
|
|
#define ANSI_COLOR_TRACE "\x1b[32m" // GREEN
|
||
|
|
#define ANSI_COLOR_WARN "\x1b[33m" // YELLOW
|
||
|
|
#define ANSI_COLOR_BLUE "\x1b[34m" // BLUE
|
||
|
|
#define ANSI_COLOR_INFO ""
|
||
|
|
// For future
|
||
|
|
#define ANSI_COLOR_MAGENTA "\x1b[35m" // MAGENTA
|
||
|
|
#define ANSI_COLOR_CYAN "\x1b[36m" // CYAN
|
||
|
|
#define ANSI_COLOR_RESET "\x1b[0m" // RESET
|
||
|
|
|
||
|
|
static unsigned log_decor = LOG_HAS_TIME | LOG_HAS_FILE | LOG_HAS_MICRO_SEC |
|
||
|
|
LOG_HAS_NEWLINE |
|
||
|
|
LOG_HAS_SPACE | LOG_HAS_COLOR;
|
||
|
|
static int max_log_level = MAX_LOG_LEVEL;
|
||
|
|
static FILE *fpLog = NULL;
|
||
|
|
|
||
|
|
#if defined(SUPPORT_SW_UART) || defined(SUPPORT_SW_UART_V2)
|
||
|
|
static pthread_mutex_t s_log_mutex;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
void SetMaxLogLevel(int level)
|
||
|
|
{
|
||
|
|
max_log_level = level;
|
||
|
|
}
|
||
|
|
|
||
|
|
int GetMaxLogLevel()
|
||
|
|
{
|
||
|
|
return max_log_level;
|
||
|
|
}
|
||
|
|
|
||
|
|
void LogMsg(int level, const char *format, ...)
|
||
|
|
{
|
||
|
|
va_list ptr;
|
||
|
|
char logBuf[MAX_PRINT_LENGTH] = {0};
|
||
|
|
const char* prefix = "";
|
||
|
|
const char* postfix= "";
|
||
|
|
|
||
|
|
if (level > max_log_level)
|
||
|
|
return;
|
||
|
|
#if defined(SUPPORT_SW_UART) || defined(SUPPORT_SW_UART_V2)
|
||
|
|
pthread_mutex_lock(&s_log_mutex);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ((log_decor & LOG_HAS_COLOR)) {
|
||
|
|
postfix = ANSI_COLOR_RESET;
|
||
|
|
switch (level) {
|
||
|
|
case INFO: prefix = ANSI_COLOR_INFO; break;
|
||
|
|
case ERR: prefix = ANSI_COLOR_ERR "[ERROR]"; break;
|
||
|
|
case TRACE: prefix = ANSI_COLOR_TRACE; break;
|
||
|
|
case WARN: prefix = ANSI_COLOR_WARN"[WARN ]"; break;
|
||
|
|
default: prefix = ""; break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
va_start( ptr, format );
|
||
|
|
vsnprintf( logBuf, MAX_PRINT_LENGTH, format, ptr );
|
||
|
|
va_end(ptr);
|
||
|
|
|
||
|
|
#ifdef ANDROID
|
||
|
|
if (level == ERR) ALOGE("%s", logBuf);
|
||
|
|
else ALOGI("%s", logBuf);
|
||
|
|
fputs(logBuf, stderr);
|
||
|
|
#else
|
||
|
|
fputs(prefix, stderr);
|
||
|
|
fputs(logBuf, stderr);
|
||
|
|
fputs(postfix, stderr);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if ((log_decor & LOG_HAS_FILE) && fpLog)
|
||
|
|
{
|
||
|
|
osal_fwrite(logBuf, (Int32)strlen(logBuf), 1,fpLog);
|
||
|
|
osal_fflush(fpLog);
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(SUPPORT_SW_UART) || defined(SUPPORT_SW_UART_V2)
|
||
|
|
pthread_mutex_unlock(&s_log_mutex);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_init_keyboard()
|
||
|
|
{
|
||
|
|
tcgetattr(0,&initial_settings);
|
||
|
|
new_settings = initial_settings;
|
||
|
|
new_settings.c_lflag &= ~ICANON;
|
||
|
|
new_settings.c_lflag &= ~ECHO;
|
||
|
|
//new_settings.c_lflag &= ~ISIG;
|
||
|
|
new_settings.c_cc[VMIN] = 1;
|
||
|
|
new_settings.c_cc[VTIME] = 0;
|
||
|
|
tcsetattr(0, TCSANOW, &new_settings);
|
||
|
|
peek_character = -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_close_keyboard()
|
||
|
|
{
|
||
|
|
tcsetattr(0, TCSANOW, &initial_settings);
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_kbhit()
|
||
|
|
{
|
||
|
|
unsigned char ch;
|
||
|
|
int nread;
|
||
|
|
|
||
|
|
if (peek_character != -1) return 1;
|
||
|
|
new_settings.c_cc[VMIN]=0;
|
||
|
|
tcsetattr(0, TCSANOW, &new_settings);
|
||
|
|
nread = (Int32)read(0,&ch,1);
|
||
|
|
new_settings.c_cc[VMIN]=1;
|
||
|
|
tcsetattr(0, TCSANOW, &new_settings);
|
||
|
|
if(nread == 1)
|
||
|
|
{
|
||
|
|
peek_character = (int)ch;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_getch()
|
||
|
|
{
|
||
|
|
int val, nread;
|
||
|
|
char ch;
|
||
|
|
|
||
|
|
if(peek_character != -1)
|
||
|
|
{
|
||
|
|
val = peek_character;
|
||
|
|
peek_character = -1;
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
nread = (Int32)read(0, &ch, 1);
|
||
|
|
if (nread == 1)
|
||
|
|
return ch;
|
||
|
|
else
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_flush_ch(void)
|
||
|
|
{
|
||
|
|
fflush(stdout);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void * osal_memcpy(void * dst, const void * src, int count)
|
||
|
|
{
|
||
|
|
int devide_len = 0;
|
||
|
|
int remain_len = 0;
|
||
|
|
int i = 0;
|
||
|
|
|
||
|
|
devide_len = ( count / 8 ) * 8 ;
|
||
|
|
remain_len = count % 8 ;
|
||
|
|
|
||
|
|
memcpy(dst, src, (size_t)devide_len);
|
||
|
|
|
||
|
|
if(remain_len)
|
||
|
|
{
|
||
|
|
for( i = 0 ; i < remain_len ; i++)
|
||
|
|
{
|
||
|
|
*(unsigned char*)((unsigned char*)dst + devide_len + i) = *((unsigned char*)((unsigned char*)src + devide_len) + i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_memcmp(const void* src, const void* dst, int size)
|
||
|
|
{
|
||
|
|
return memcmp(src, dst, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
void * osal_memset(void *dst, int val, int count)
|
||
|
|
{
|
||
|
|
return memset(dst, val, count);
|
||
|
|
}
|
||
|
|
|
||
|
|
void * osal_malloc(int size)
|
||
|
|
{
|
||
|
|
// return malloc(size);
|
||
|
|
return (void *)memalign(4 ,size);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void * osal_realloc(void* ptr, int size)
|
||
|
|
{
|
||
|
|
return realloc(ptr, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_free(void *p)
|
||
|
|
{
|
||
|
|
free(p);//lint -e{424}
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_fflush(osal_file_t fp)
|
||
|
|
{
|
||
|
|
return fflush((FILE*)fp);
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_feof(osal_file_t fp)
|
||
|
|
{
|
||
|
|
return feof((FILE *)fp);
|
||
|
|
}
|
||
|
|
|
||
|
|
osal_file_t osal_fopen(const char * osal_file_tname, const char * mode)
|
||
|
|
{
|
||
|
|
return fopen(osal_file_tname, mode);
|
||
|
|
}
|
||
|
|
size_t osal_fwrite(const void * p, int size, int count, osal_file_t fp)
|
||
|
|
{
|
||
|
|
return fwrite(p, size, count, (FILE*)fp);
|
||
|
|
}
|
||
|
|
size_t osal_fread(void *p, int size, int count, osal_file_t fp)
|
||
|
|
{
|
||
|
|
return fread(p, size, count, (FILE*)fp);
|
||
|
|
}
|
||
|
|
|
||
|
|
long osal_ftell(osal_file_t fp)
|
||
|
|
{
|
||
|
|
return ftell((FILE*)fp);
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_fseek(osal_file_t fp, long offset, int origin)
|
||
|
|
{
|
||
|
|
return fseek((FILE*)fp, offset, origin);
|
||
|
|
}
|
||
|
|
int osal_fclose(osal_file_t fp)
|
||
|
|
{
|
||
|
|
return fclose((FILE*)fp); //lint !e482
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_fscanf(osal_file_t fp, const char * _Format, ...)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
|
||
|
|
va_list arglist;
|
||
|
|
va_start(arglist, _Format);
|
||
|
|
|
||
|
|
ret = vfscanf((FILE*)fp, _Format, arglist);
|
||
|
|
|
||
|
|
va_end(arglist);
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int osal_fprintf(osal_file_t fp, const char * _Format, ...)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
va_list arglist;
|
||
|
|
va_start(arglist, _Format);
|
||
|
|
|
||
|
|
ret = vfprintf((FILE*)fp, _Format, arglist);
|
||
|
|
|
||
|
|
va_end(arglist);
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_msleep(Uint32 millisecond)
|
||
|
|
{
|
||
|
|
usleep(millisecond*1000);
|
||
|
|
}
|
||
|
|
|
||
|
|
osal_thread_t osal_thread_create(void* (*start_routine)(void*), void* arg)
|
||
|
|
{
|
||
|
|
Int32 ret;
|
||
|
|
pthread_t* thread = (pthread_t*)osal_malloc(sizeof(pthread_t));
|
||
|
|
osal_thread_t handle = NULL;
|
||
|
|
|
||
|
|
if ((ret = pthread_create(thread, NULL, start_routine, arg)) != 0) {
|
||
|
|
osal_free(thread);
|
||
|
|
VLOG(ERR, "<%s:%d> Failed to pthread_create ret(%d)\n", __FUNCTION__, __LINE__, ret);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
handle = (osal_thread_t)thread;
|
||
|
|
}
|
||
|
|
|
||
|
|
return handle; //lint !e593
|
||
|
|
}
|
||
|
|
|
||
|
|
Int32 osal_thread_join(osal_thread_t thread, void** retval)
|
||
|
|
{
|
||
|
|
Int32 ret;
|
||
|
|
pthread_t pthreadHandle;
|
||
|
|
|
||
|
|
if (thread == NULL) {
|
||
|
|
VLOG(ERR, "%s:%d invalid thread handle\n", __FUNCTION__, __LINE__);
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
pthreadHandle = *(pthread_t*)thread;
|
||
|
|
|
||
|
|
if ((ret=pthread_join(pthreadHandle, retval)) != 0) {
|
||
|
|
osal_free(thread);
|
||
|
|
VLOG(ERR, "%s:%d Failed to pthread_join ret(%d)\n", __FUNCTION__, __LINE__, ret);
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
osal_free(thread);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Int32 osal_thread_timedjoin(osal_thread_t thread, void** retval, Uint32 millisecond)
|
||
|
|
{
|
||
|
|
Int32 ret;
|
||
|
|
pthread_t pthreadHandle;
|
||
|
|
struct timespec absTime;
|
||
|
|
|
||
|
|
if (thread == NULL) {
|
||
|
|
VLOG(ERR, "%s:%d invalid thread handle\n", __FUNCTION__, __LINE__);
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
pthreadHandle = *(pthread_t*)thread;
|
||
|
|
|
||
|
|
clock_gettime(CLOCK_REALTIME, &absTime);
|
||
|
|
absTime.tv_nsec += millisecond*1000000;
|
||
|
|
if (1000000000 < absTime.tv_nsec) {
|
||
|
|
absTime.tv_sec++;
|
||
|
|
absTime.tv_nsec -= 1000000000;
|
||
|
|
}
|
||
|
|
if ((ret=pthread_timedjoin_np(pthreadHandle, retval, &absTime)) == 0) {
|
||
|
|
osal_free(thread);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
else if (ret == ETIMEDOUT) {
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
osal_mutex_t osal_mutex_create(void)
|
||
|
|
{
|
||
|
|
pthread_mutex_t* mutex = (pthread_mutex_t*)osal_malloc(sizeof(pthread_mutex_t));
|
||
|
|
|
||
|
|
if (mutex == NULL) {
|
||
|
|
VLOG(ERR, "<%s:%d> failed to allocate memory\n", __FUNCTION__, __LINE__);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pthread_mutex_init(mutex, NULL) < 0) {
|
||
|
|
osal_free(mutex);
|
||
|
|
VLOG(ERR, "<%s:%d> failed to pthread_mutex_init() errno(%d)\n", __FUNCTION__, __LINE__, errno);
|
||
|
|
return NULL; //lint !e429
|
||
|
|
}
|
||
|
|
|
||
|
|
return (osal_mutex_t)mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_mutex_destroy(osal_mutex_t mutex)
|
||
|
|
{
|
||
|
|
Int32 ret;
|
||
|
|
|
||
|
|
if (mutex == NULL) {
|
||
|
|
VLOG(ERR, "<%s:%d> Invalid mutex handle\n", __FUNCTION__, __LINE__);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((ret=pthread_mutex_destroy((pthread_mutex_t*)mutex)) != 0) {
|
||
|
|
VLOG(ERR, "<%s:%d> Failed to pthread_mutex_destroy(). ret(%d)\n", __FUNCTION__, __LINE__, ret);
|
||
|
|
}
|
||
|
|
|
||
|
|
osal_free(mutex);
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL osal_mutex_lock(osal_mutex_t mutex)
|
||
|
|
{
|
||
|
|
Int32 ret;
|
||
|
|
|
||
|
|
if (mutex == NULL) {
|
||
|
|
VLOG(ERR, "<%s:%d> Invalid mutex handle\n", __FUNCTION__, __LINE__);
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((ret=pthread_mutex_lock((pthread_mutex_t*)mutex)) != 0) {
|
||
|
|
VLOG(ERR, "<%s:%d> Failed to pthread_mutex_lock() ret(%d)\n", __FUNCTION__, __LINE__, ret);
|
||
|
|
return FALSE; //lint !e454
|
||
|
|
}
|
||
|
|
|
||
|
|
return TRUE; //lint !e454
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL osal_mutex_unlock(osal_mutex_t mutex)
|
||
|
|
{
|
||
|
|
Int32 ret;
|
||
|
|
|
||
|
|
if (mutex == NULL) {
|
||
|
|
VLOG(ERR, "<%s:%d> Invalid mutex handle\n", __FUNCTION__, __LINE__);
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((ret=pthread_mutex_unlock((pthread_mutex_t*)mutex)) != 0) { //lint !e455
|
||
|
|
VLOG(ERR, "<%s:%d> Failed to pthread_mutex_unlock(). ret(%d)\n", __FUNCTION__, __LINE__, ret);
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
osal_sem_t osal_sem_init(Uint32 count)
|
||
|
|
{
|
||
|
|
sem_t* semaphore;
|
||
|
|
semaphore = (sem_t*)malloc(sizeof(sem_t));
|
||
|
|
if (sem_init(semaphore, 0, count) < 0) {
|
||
|
|
VLOG(INFO, "<%s:%d> Failed to sem_init\n", __FUNCTION__, __LINE__);
|
||
|
|
free(semaphore);
|
||
|
|
semaphore = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (osal_sem_t)semaphore;
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_sem_destroy(osal_sem_t sem)
|
||
|
|
{
|
||
|
|
sem_t* semaphore = (sem_t*)sem;
|
||
|
|
|
||
|
|
sem_destroy(semaphore);
|
||
|
|
|
||
|
|
free(semaphore);
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_sem_wait(osal_sem_t sem)
|
||
|
|
{
|
||
|
|
sem_t* semaphore = (sem_t*)sem;
|
||
|
|
|
||
|
|
sem_wait(semaphore);
|
||
|
|
}
|
||
|
|
|
||
|
|
void osal_sem_post(osal_sem_t sem)
|
||
|
|
{
|
||
|
|
sem_t* semaphore = (sem_t*)sem;
|
||
|
|
|
||
|
|
sem_post(semaphore);
|
||
|
|
}
|
||
|
|
|
||
|
|
Uint64 osal_gettime(void)
|
||
|
|
{
|
||
|
|
struct timespec tp;
|
||
|
|
|
||
|
|
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||
|
|
|
||
|
|
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
|
||
|
|
}
|
||
|
|
|