Files
hisi_SS524V100_SDK/mpp/sample/uart2net_mesh/ctrl_pnl.c
T

402 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h> // gettimeofday
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include "serial.h"
#include "uartinf.h"
#include <stdbool.h>
#define RECV_PORT 12000 // UDP接收端口
#define SEND_PORT 12001 // 发送端口(UART转NET)
/* ===================== 网络帧协议定义 ===================== */
#define NET_FRAME_LEN 32 /* 收/发报文固定长度 */
#define NET_TAIL 0xBB /* 帧尾 */
#define PAYLOAD_LEN 30 /* 帧长度 byte0..29 */
#define BYTE_MODE 30 /* 接收帧 mode 字段偏移(0-4) */
#define BYTE_TAIL 31 /* 接收帧帧尾偏移 */
#define CHECKSUM_END 30 /* 校验和覆盖 byte0..byte30(含) */
#define NET_FRAME_MAX_LEN 256 /* recvfrom 缓冲大小 */
#define BYTE_NOSIG0 25 /* byte25 = 视频流0无信号标志(1=无信号,0=有信号) */
#define BYTE_NOSIG1 26 /* byte26 = 视频流1无信号标志(1=无信号,0=有信号) */
#define BYTE_RSSI1 28 /* 信号包=RSSI1;设备包=哨兵 */
#define BYTE_RSSI2 29 /* 信号包=RSSI2;设备包=哨兵 */
#define SIG_MARK 0x5A /* 设备包 byte28/29 哨兵值 */
#define SIGNAL_INTERVAL_MS 100 /* 独立信号包发送间隔(ms) */
#define FRAME_HEAD 0x11 /* 上行帧帧头(byte0),面板校验要求 */
#define FRAME_TAIL 0x22 /* 上行帧帧尾(byte30),面板校验要求 */
#define FRAME_HEAD_TX 0xAA /* 下行帧帧头(byte0),设备→面板 */
/* ===================== 共享内存 ===================== */
#define SHM_MSG_NAME "/video_switch"
#define SHM_MODE_IDX 0 /* switch_mode -> shm[0](即 switch_video[0]) */
static int *shm_msg = NULL;
char _rx_data[200];
static int socket_descriptor;
static struct sockaddr_in address;
bool first = false;
int socket_descriptor_recv;
struct sockaddr_in address_recv;
pthread_attr_t attr;
pthread_t pkts_thread;
/* 打开共享内存 /param.txt(由 lc6600_uart 进程写入 RSSI) */
static int *param_memory_open(void) {
int fd = shm_open("/param.txt", O_RDWR, 0777);
if (fd < 0) {
fd = shm_open("/param.txt", O_RDWR | O_CREAT, 0777);
if (fd < 0) { perror("shm_open /param.txt"); return NULL; }
if (ftruncate(fd, 4096) == -1) { perror("ftruncate /param.txt"); return NULL; }
}
int *retval = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (retval == MAP_FAILED) { perror("mmap /param.txt"); return NULL; }
return retval;
}
static int *switch_memory_open(void) {
char buf[128];
int fd;
sprintf(buf, SHM_MSG_NAME);
fd = shm_open(buf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(fd < 0) { perror("shm_open"); exit(1); }
if (ftruncate(fd, 4096) == -1) { perror("ftruncate"); exit(1); }
int *retval = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
return retval;
}
/* 读 GPIO71(0/1),失败返回默认值 1 */
static int read_gpio72(void)
{
char val = 0;
int fd = open("/sys/class/gpio/gpio71/value", O_RDONLY);
if (fd < 0)
return 0; /* 失败默认 0 */
if (read(fd, &val, 1) != 1) {
close(fd);
return 0; /* 失败默认 0 */
}
close(fd);
return (val == '0') ? 1 : 0; /* 反相:GPIO=1 → 0,GPIO=0 → 1 */
}
static long elapsed_ms(struct timeval *start, struct timeval *end)
{
return (end->tv_sec - start->tv_sec) * 1000L
+ (end->tv_usec - start->tv_usec) / 1000L;
}
int init_net_recv(int port){
int i;
struct timeval tv;
bzero(&address_recv,sizeof(struct sockaddr_in));
address_recv.sin_family=AF_INET;
address_recv.sin_addr.s_addr=htonl(INADDR_ANY);
address_recv.sin_port=htons(port);
socket_descriptor_recv=socket(AF_INET,SOCK_DGRAM,0);//IPV4
tv.tv_sec = 2;
tv.tv_usec = 0;
if (setsockopt(socket_descriptor_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
printf("socket option SO_RCVTIMEO not support\n");
return -1;
}
if (bind(socket_descriptor_recv, (struct sockaddr *)&address_recv, sizeof(struct sockaddr_in)) < 0)
{
perror("bind");
exit(1);
}
return 0;
}
int udp_init(char *ip, int port){
bzero(&address,sizeof(address));
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr(ip);
address.sin_port=htons(port);
socket_descriptor=socket(AF_INET,SOCK_DGRAM,0);//IPV4
return 0;
}
#if 0
void *net_recv(void *arg)
{
int i;
struct sockaddr_in clientAddr;
int len = sizeof(clientAddr);
int ret;
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (setsockopt(socket_descriptor_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
printf("socket option SO_RCVTIMEO not support\n");
//return -1;
}
char buffer_cmd[200];
while(1){
i = recvfrom(socket_descriptor_recv, buffer_cmd, 200, 0, (struct sockaddr*)&clientAddr, &len);
if(i>0){
uart_write_len(ROUTE_UART,buffer_cmd,i);
}
else{
printf(" time_out to receive data\n");
}
}
}
#endif
#if 1
void *net_recv(void *arg)
{
int i, k;
struct sockaddr_in clientAddr;
socklen_t len;
struct timeval tv;
char buffer_cmd[NET_FRAME_MAX_LEN];
char frame_out[NET_FRAME_MAX_LEN];
int sum;
unsigned char checksum;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (setsockopt(socket_descriptor_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
printf("socket option SO_RCVTIMEO not support\n");
while (1) {
len = sizeof(clientAddr); /* 每次循环重置,recvfrom 会改写 len */
i = recvfrom(socket_descriptor_recv, buffer_cmd, NET_FRAME_MAX_LEN, 0,
(struct sockaddr*)&clientAddr, &len);
if (i <= 0) {
printf(" time_out to receive data\n");
continue;
}
if (i != NET_FRAME_LEN) {
printf("bad frame len=%d\n", i);
continue;
}
/* 帧尾校验 */
if ((unsigned char)buffer_cmd[BYTE_TAIL] != NET_TAIL) {
printf("bad tail=%02x\n", (unsigned char)buffer_cmd[BYTE_TAIL]);
continue;
}
/* 解析 mode -> 写共享内存 */
if (shm_msg) {
static int last_mode = -1;
int mode = (unsigned char)buffer_cmd[BYTE_MODE];
if (mode <= 4) {
if (mode != last_mode) {
shm_msg[SHM_MODE_IDX] = mode; //写入共享内存 viode_switch
last_mode = mode;
printf("write shm: mode=%d\n", mode);
}
}
else {
printf("filed mode=%d\n", mode);
}
}
/* 构造下行帧:byte0=0xAA 帧头,byte1..29 原样,byte30=0xBB 帧尾 */
frame_out[0] = FRAME_HEAD_TX; /* [0] 帧头 0xAA */
memcpy(frame_out + 1, buffer_cmd + 1, PAYLOAD_LEN - 1); /* [1..29] 原样 */
frame_out[PAYLOAD_LEN] = NET_TAIL; /* [30] 帧尾 0xBB */
/* 校验和 = byte0..byte30 求和取低8位,写入 byte31 */
sum = 0;
for (k = 0; k <= CHECKSUM_END; k++)
sum += (unsigned char)frame_out[k];
checksum = sum & 0xFF;
frame_out[PAYLOAD_LEN + 1] = checksum; /* [31] 校验和 */
#if 0
/* 打印发出的包 */
printf(" send to uart %d bytes:", NET_FRAME_LEN);
for (k = 0; k < NET_FRAME_LEN; k++)
printf(" %02x", (unsigned char)frame_out[k]);
printf("\n");
#endif
uart_write_len(ROUTE_UART, frame_out, NET_FRAME_LEN); //发送给串口
}
return NULL;
}
#endif
int pthread_init()
{
int ret;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
ret = pthread_create(&pkts_thread, &attr, net_recv, NULL);
pthread_attr_destroy(&attr);
if(ret){
printf("create pthread1 error\n");
return 1;
}
}
int main (int argc, char *argv[])
{
int n_read;
int i;
int count=0;
int *buffer_param;
char buffer_send[100];
int buffer_len;
struct timeval tv_sig = {0, 0}, tv_now;
char sig_frame[NET_FRAME_LEN];
n_read = uart_init(ROUTE_UART, "/dev/ttyAMA4", 115200, 'N');
if(n_read <=0 ) {
printf("open /dev/ttyAMA4 failed\n");
return -1;
}
// udp_init(argv[1], atoi(argv[2]));
// init_net_recv(atoi(argv[3]));
udp_init("127.0.0.1", SEND_PORT); // 发送目标:本机回环 12001
init_net_recv(RECV_PORT); // 接收:0.0.0.0:12000(INADDR_ANY)
shm_msg = switch_memory_open();
buffer_param = param_memory_open();
pthread_init();
while(1){
n_read = uart_read(ROUTE_UART, _rx_data);
if(n_read > 0 ){
int k, sum = 0;
/* 收包校验:完整 32 字节帧,帧头 0x11、帧尾 0x22、byte31 校验和正确,否则丢弃 */
if (n_read < NET_FRAME_LEN) {
printf("drop bad frame: len=%d\n", n_read);
continue;
}
if ((unsigned char)_rx_data[0] != FRAME_HEAD ||
(unsigned char)_rx_data[CHECKSUM_END] != FRAME_TAIL) {
printf("drop bad frame: head=%02x tail=%02x\n",
(unsigned char)_rx_data[0], (unsigned char)_rx_data[CHECKSUM_END]);
continue;
}
for (k = 0; k <= CHECKSUM_END; k++)
sum += (unsigned char)_rx_data[k];
if ((unsigned char)_rx_data[31] != (sum & 0xFF)) {
printf("drop bad frame: checksum=%02x expect=%02x\n",
(unsigned char)_rx_data[31], (unsigned char)(sum & 0xFF));
continue;
}
/* byte28/29 固定哨兵值,RSSI 改由独立信号包承载 */
_rx_data[BYTE_RSSI1] = (char)SIG_MARK;
_rx_data[BYTE_RSSI2] = (char)SIG_MARK;
/* 和校验:byte0..byte30 求和取低 8 位,写入 byte31 */
sum = 0;
for (k = 0; k <= CHECKSUM_END; k++)
sum += (unsigned char)_rx_data[k];
_rx_data[31] = (char)(sum & 0xFF);
sendto(socket_descriptor, _rx_data, NET_FRAME_LEN, 0, (struct sockaddr *)&address, sizeof(address));
}
/* 独立信号包:与串口数据无关,每 SIGNAL_INTERVAL_MS 发一次;其余字节填 0 */
gettimeofday(&tv_now, NULL);
if (tv_sig.tv_sec == 0 || elapsed_ms(&tv_sig, &tv_now) >= SIGNAL_INTERVAL_MS) {
int k, sum = 0;
memset(sig_frame, 0, NET_FRAME_LEN);
sig_frame[0] = (char)FRAME_HEAD; /* byte0 = 0x11 */
/* byte25/26 = 视频流0/1无信号,byte27 = GPIO */
sig_frame[BYTE_NOSIG0] = (shm_msg && shm_msg[2] == 0x55) ? 1 : 0;
sig_frame[BYTE_NOSIG1] = (shm_msg && shm_msg[3] == 0x55) ? 1 : 0;
sig_frame[27] = (char)read_gpio72();
if (buffer_param) {
sig_frame[BYTE_RSSI1] = (char)buffer_param[1];
sig_frame[BYTE_RSSI2] = (char)buffer_param[2];
//打印发出的信号值
printf("signal: RSSI1=%d RSSI2=%d\n", buffer_param[1], buffer_param[2]);
}
sig_frame[PAYLOAD_LEN] = (char)FRAME_TAIL; /* byte30 = 0x22 */
for (k = 0; k <= CHECKSUM_END; k++)
sum += (unsigned char)sig_frame[k];
sig_frame[CHECKSUM_END + 1] = (char)(sum & 0xFF);
sendto(socket_descriptor, sig_frame, NET_FRAME_LEN, 0, (struct sockaddr *)&address, sizeof(address));
tv_sig = tv_now;
}
}
}