#include <stdio.h> | |
#include <stdlib.h> | |
#include <fcntl.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <termios.h> | |
#include <unistd.h> | |
#include <stdint.h> | |
#include <sys/ioctl.h> | |
#include <dlfcn.h> | |
#include "gsw_uart.h" | |
#ifndef LOG_ERR_LEVEL | |
#define LOG_ERR_LEVEL 3 /* error conditions */ | |
#endif | |
#ifndef LOG_WARN_LEVEL | |
#define LOG_WARN_LEVEL 4 /* warning conditions */ | |
#endif | |
#ifndef LOG_INFO_LEVEL | |
#define LOG_INFO_LEVEL 6 /* informational */ | |
#endif | |
#ifndef LOG_DEBUG_LEVEL | |
#define LOG_DEBUG_LEVEL 7 /* debug-level messages */ | |
#endif | |
#ifndef LOG_VERBOSE_LEVEL | |
#define LOG_VERBOSE_LEVEL 8 | |
#endif | |
#define GSW_UART "[HAL][GSW_UART]" | |
#define LOGV(fmt, args ...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_VERBOSE_LEVEL, "%s#%s: "GSW_UART"" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGI(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: "GSW_UART"" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGD(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_DEBUG_LEVEL, "%s#%s: "GSW_UART"" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGW(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_WARN_LEVEL, "%s#%s: "GSW_UART"" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGE(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_ERR_LEVEL, "%s#%s: "GSW_UART"" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
typedef void (*mbtk_log)(int level, const char *format,...); | |
static mbtk_log fun_ptr_log = NULL; | |
void *dlHandle_uart = NULL; | |
char *lynqLib_uart = "/lib/libmbtk_lib.so"; | |
static int handle() | |
{ | |
if(dlHandle_uart == NULL || fun_ptr_log == NULL) | |
{ | |
dlHandle_uart = dlopen(lynqLib_uart, RTLD_NOW); | |
fun_ptr_log = (mbtk_log)dlsym(dlHandle_uart, "mbtk_log"); | |
if(fun_ptr_log == NULL || dlHandle_uart == NULL) | |
{ | |
return GSW_HAL_FAIL; | |
} | |
} | |
return GSW_HAL_SUCCESS; | |
} | |
int32_t gsw_uart_open_ex(int8_t *port, gsw_hal_uart_baudrate baudrate, uint32_t bits, int8_t parity, uint32_t stop) | |
{ | |
if (handle()) | |
return GSW_HAL_FAIL; | |
int fd = -1; | |
if((fd = open((const char *)port, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) | |
{ | |
LOGE("open %s failed - %d", port, errno); | |
return -1; | |
} | |
LOGD("Open %s success.", port); | |
/* set newtio */ | |
struct termios newtio; | |
memset(&newtio, 0, sizeof(newtio)); | |
if (tcflush(fd, TCIOFLUSH) < 0) { | |
LOGE("Could not flush uart port"); | |
return -1; | |
} | |
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ | |
newtio.c_cc[VMIN] = 0; /* blocking read until 5 chars received */ | |
/* c_iflag 输入模式 */ | |
newtio.c_iflag &= ~(ICRNL | INLCR); | |
newtio.c_iflag &= ~(IXON | IXOFF | IXANY); | |
// /* c_lflag 本地模式 */ | |
newtio.c_cflag &= ~ INPCK; | |
newtio.c_cflag |= (CLOCAL | CREAD); | |
// /* c_lflag 本地模式 */ | |
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); | |
/* c_oflag 输出模式 */ | |
newtio.c_oflag &= ~ OPOST; | |
newtio.c_oflag &= ~(ONLCR | OCRNL); | |
/* c_cflag 控制模式 */ | |
newtio.c_cflag &= ~ CSIZE; | |
newtio.c_cflag |= CS8; | |
newtio.c_cflag &= ~ CSTOPB; | |
newtio.c_cflag &= ~ PARENB; | |
switch(baudrate) | |
{ | |
case GSW_HAL_BAUDRATE_1200: | |
cfsetospeed(&newtio, B1200); | |
cfsetispeed(&newtio, B1200); | |
break; | |
case GSW_HAL_BAUDRATE_1800: | |
cfsetospeed(&newtio, B1800); | |
cfsetispeed(&newtio, B1800); | |
break; | |
case GSW_HAL_BAUDRATE_4800: | |
cfsetospeed(&newtio, B4800); | |
cfsetispeed(&newtio, B4800); | |
break; | |
case GSW_HAL_BAUDRATE_9600: | |
cfsetospeed(&newtio, B9600); | |
cfsetispeed(&newtio, B9600); | |
break; | |
case GSW_HAL_BAUDRATE_19200: | |
cfsetospeed(&newtio, B19200); | |
cfsetispeed(&newtio, B19200); | |
break; | |
case GSW_HAL_BAUDRATE_38400: | |
cfsetospeed(&newtio, B38400); | |
cfsetispeed(&newtio, B38400); | |
break; | |
case GSW_HAL_BAUDRATE_57600: | |
cfsetospeed(&newtio, B57600); | |
cfsetispeed(&newtio, B57600); | |
break; | |
case GSW_HAL_BAUDRATE_115200: | |
cfsetospeed(&newtio, B115200); | |
cfsetispeed(&newtio, B115200); | |
break; | |
case GSW_HAL_BAUDRATE_230400: | |
cfsetospeed(&newtio, B230400); | |
cfsetispeed(&newtio, B230400); | |
break; | |
case GSW_HAL_BAUDRATE_460800: | |
cfsetospeed(&newtio, B460800); | |
cfsetispeed(&newtio, B460800); | |
break; | |
case GSW_HAL_BAUDRATE_500000: | |
cfsetospeed(&newtio, B500000); | |
cfsetispeed(&newtio, B500000); | |
break; | |
case GSW_HAL_BAUDRATE_576000: | |
cfsetospeed(&newtio, B576000); | |
cfsetispeed(&newtio, B576000); | |
break; | |
case GSW_HAL_BAUDRATE_921600: | |
cfsetospeed(&newtio, B921600); | |
cfsetispeed(&newtio, B921600); | |
break; | |
default: | |
cfsetospeed(&newtio, B115200); | |
cfsetispeed(&newtio, B115200); | |
break; | |
} | |
switch(bits) | |
{ | |
case CS5: | |
newtio.c_cflag &= ~CSIZE; | |
newtio.c_cflag |= CS5; | |
break; | |
case CS6: | |
newtio.c_cflag &= ~CSIZE; | |
newtio.c_cflag |= CS6; | |
break; | |
case CS7: | |
newtio.c_cflag &= ~CSIZE; | |
newtio.c_cflag |= CS7; | |
break; | |
case CS8: | |
newtio.c_cflag &= ~CSIZE; | |
newtio.c_cflag |= CS8; | |
break; | |
default: | |
LOGD("No set databit."); | |
break; | |
} | |
if(stop == 2) { | |
newtio.c_cflag |= CSTOPB; | |
} else { | |
newtio.c_cflag &= ~CSTOPB; | |
} | |
switch (parity) | |
{ | |
case '1':// 奇校验 | |
newtio.c_cflag |= PARENB; | |
newtio.c_cflag |= PARODD; | |
break; | |
case '2':// 偶校验 | |
newtio.c_cflag |= PARENB; | |
newtio.c_cflag &= ~PARODD; | |
break; | |
case '0':// 无奇偶校验 | |
newtio.c_cflag &= ~PARENB; | |
break; | |
default: | |
LOGD("No set parity."); | |
break; | |
} | |
if (tcsetattr(fd, TCSANOW, &newtio) < 0) { | |
LOGE("Can't set port setting"); | |
return -1; | |
} | |
return fd; | |
} | |
int32_t gsw_uart_flush(int32_t fd) | |
{ | |
if (tcflush(fd, TCIOFLUSH) < 0) | |
{ | |
return GSW_HAL_FAIL; | |
} | |
return GSW_HAL_SUCCESS; | |
} | |
int32_t gsw_uart_read(int32_t fd, uint8_t *buffer, uint32_t len, int32_t timeout_ms) | |
{ | |
if (handle()) | |
return GSW_HAL_FAIL; | |
int flags = fcntl(fd, F_GETFL); // 获取当前状态标志 | |
if (flags == -1) | |
{ | |
perror("fcntl get"); | |
return GSW_HAL_FAIL; | |
} | |
struct termios newtio; | |
if (tcgetattr(fd, &newtio) < 0) { | |
perror("tcgetattr failed"); | |
return -1; | |
} | |
if (timeout_ms == 0) | |
{ | |
flags |= O_NONBLOCK; // 设置非阻塞标志 | |
fcntl(fd, F_SETFL, flags); | |
newtio.c_cc[VMIN] = 0; | |
newtio.c_cc[VTIME] = 0; | |
} | |
else if (timeout_ms == 1) | |
{ | |
flags &= ~O_NONBLOCK; // 清除非阻塞标志 | |
fcntl(fd, F_SETFL, flags); | |
newtio.c_cc[VMIN] = 1; | |
newtio.c_cc[VTIME] = timeout_ms/100; | |
} | |
else | |
{ | |
flags &= ~O_NONBLOCK; // 清除非阻塞标志 | |
fcntl(fd, F_SETFL, flags); | |
newtio.c_cc[VMIN] = 0; | |
newtio.c_cc[VTIME] = timeout_ms/100; | |
} | |
if(timeout_ms != 0) | |
LOGI("%s :VMIN = %d ;VTIME = %d\n",__func__,newtio.c_cc[VMIN],newtio.c_cc[VTIME]); | |
if (tcsetattr(fd, TCSANOW, &newtio) != 0) | |
{ | |
perror("tcsetattr"); | |
return -1; | |
} | |
//gsw_uart_flush(fd); | |
int data_len = read(fd, buffer, len); | |
if (data_len < 0) | |
{ | |
if(errno == EAGAIN || errno == EWOULDBLOCK) | |
return 0; | |
else | |
return GSW_HAL_FAIL; | |
} | |
return data_len; | |
} | |
int32_t gsw_uart_write(int32_t fd, const uint8_t *buffer, uint32_t len) | |
{ | |
//gsw_uart_flush(fd); | |
if (write(fd, buffer, len) < 0) | |
{ | |
return GSW_HAL_FAIL; | |
} | |
return GSW_HAL_SUCCESS; | |
} | |
int32_t gsw_uart_ioctl(int32_t fd, uint32_t cmd, void *pvalue) | |
{ | |
if (handle()) | |
return GSW_HAL_FAIL; | |
if (fd < 0 || pvalue == NULL) | |
{ | |
LOGE("Invalid file descriptor"); | |
return GSW_HAL_FAIL; | |
} | |
if (ioctl(fd, cmd, pvalue) < 0) | |
{ | |
LOGE("Could not set DCB,error:%d, %s\n",errno, strerror(errno)); | |
return GSW_HAL_FAIL; | |
} | |
return GSW_HAL_SUCCESS; | |
} | |
int32_t gsw_uart_close(int32_t fd) | |
{ | |
if (fd <= 0) | |
return GSW_HAL_FAIL; | |
//gsw_uart_flush(fd); | |
close(fd); | |
return GSW_HAL_SUCCESS; | |
} | |