commit 2c5fbe219558e6c5e4996dc9081fb4c7edb33a33 Author: zhaohe Date: Sun Sep 3 18:27:31 2023 +0800 update diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..8587fbe --- /dev/null +++ b/.clang-format @@ -0,0 +1,5 @@ +# Defines the Chromium style for automatic reformatting. +# http://clang.llvm.org/docs/ClangFormatStyleOptions.html +Language: Cpp +BasedOnStyle: Google +ColumnLimit: 300 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a478c1f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "string_view": "cpp" + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..aab1d9e --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# README + + +``` + 用于将板子上的串口以网络透传出去。客户端通过tcp协议链接上之后,即可通过socket_fd直接和串口通信。 + +v1: + 1.支持基本功能 + 2.支持多个客户端同时链接服务器。多个客户端同时链接时,串口来消息,是以广播的形势发个各个Tcp客户端。 + +v1.1: + 1.修复占用CPU过高的BUG +``` + +``` +Usage: + net_tty.out /dev/ttyUSB0 115200 port + +``` \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..a51ea81 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +aarch64-linux-gnu-g++ zuart.cpp uart.cpp -o zuart.out -lpthread \ No newline at end of file diff --git a/uart.cpp b/uart.cpp new file mode 100644 index 0000000..90b16e3 --- /dev/null +++ b/uart.cpp @@ -0,0 +1,172 @@ + +/* + * uart.c + * + * Created on: Aug 5, 2019 + * Author: Cristian Fatu + * Implements basic UART functionality, over Uart Lite linux driver, using termios. + * After booting linux, a device like "/dev/ttyUL1" must be present. + * These functions work in both canonic and not canonic modes. + * In the canonic communication mode, the received chars can be retrieved by read only after \n is detected. + * In the non canonic communication mode, the received chars can be retrieved by read as they are received. + */ +#include "uart.hpp" + +#include +#include +#include +#include +#include +/* +Parameters: + struct UartDevice* dev - pointer to the UartDevice struct + unsigned char canonic - communication mode + 1 - canonic communication (chars are only received after \n is detected). + 0 - non canonic communication (chars are received as they arrive over UART). +Return value: + UART_FAILURE -1 failure + UART_SUCCESS 0 success +Description: + Initializes the UART device. + When calling the function, the device name (usually "/dev/ttyUL1") must be filled in dev->name and the baud rate must be filled in dev->rate. + The canonic function parameter indicates communication mode (canonic or not). + In the canonic communication mode, the received chars can be retrieved by read only after \n is detected. + In the non canonic communication mode, the received chars can be retrieved by read as they are received, as the non canonic mode is configured with no wait. +*/ +int uartStart(struct UartDevice* dev, unsigned char canonic) { + struct termios* tty; + int fd; + int rc; + + fd = open(dev->name, O_RDWR | O_NOCTTY); + if (fd < 0) { + printf("%s: failed to open file descriptor for file %s\r\n", __func__, dev->name); + return UART_FAILURE; + } + + tty = (struct termios*)calloc(1, sizeof(*dev->tty)); + if (!tty) { + printf("%s: failed to allocate tty instance\r\n", __func__); + return UART_FAILURE; + } + // memset(tty, 0, sizeof(struct termios)); + + /* + BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. + CRTSCTS : output hardware flow control (only used if the cable has + all necessary lines. See sect. 7 of Serial-HOWTO) + CS8 : 8n1 (8bit,no parity,1 stopbit) + CLOCAL : local connection, no modem contol + CREAD : enable receiving characters + */ + // tty->c_cflag = dev->rate | CRTSCTS | CS8 | CLOCAL | CREAD; + tty->c_cflag = dev->rate | CS8 | CLOCAL | CREAD; + if (canonic) { + // canonic + /* + IGNPAR : ignore bytes with parity errors + ICRNL : map CR to NL (otherwise a CR input on the other computer + will not terminate input) + otherwise make device raw (no other input processing) + */ + tty->c_iflag = IGNPAR | ICRNL; + /* + ICANON : enable canonical input + disable all echo functionality, and don't send signals to calling program + */ + tty->c_lflag = ICANON; + } else { + // not canonic + /* + IGNPAR : ignore bytes with parity errorsc_cc[VTIME] + */ + tty->c_iflag = IGNPAR; + /* set input mode (non-canonical, no echo,...) */ + tty->c_lflag = 0; + /* Do not wait for data */ + tty->c_cc[VTIME] = 10; /* inter-character timer unused */ + tty->c_cc[VMIN] = 0; /* blocking read until 5 chars received */ + } + + /* + Raw output. + */ + tty->c_oflag = 0; + + /* Flush port */ + tcflush(fd, TCIFLUSH); + + /* Apply attributes */ + rc = tcsetattr(fd, TCSANOW, tty); + if (rc) { + printf("%s: failed to set TCSANOW attr\r\n", __func__); + return UART_FAILURE; + } + + dev->fd = fd; + dev->tty = tty; + + return UART_SUCCESS; +} + +/* +Parameters: + struct UartDevice* dev - pointer to the UartDevice struct + char *data - pointer to the array of chars to be sent over UART + int size + positive value - number of chars to be sent over UART + -1 - indicates that all the chars until string terminator \0 will be sent +Return value: + number of chars sent over UART +Description: + This function sends a number of chars over UART. + If the size function parameter is -1 then all the characters until string terminator \0 will be sent. +*/ +int uartSend(struct UartDevice* dev, char* data, int size) { + int sent = 0; + if (size == -1) { + size = strlen(data); + } + sent = write(dev->fd, data, size); + +#ifdef DEBUG + printf("%s: sent %d characters\r\n", __func__, sent); +#endif + return sent; +} + +/* +Parameters: + struct UartDevice* dev - pointer to the UartDevice struct + char *data - pointer to the array of chars to hold the cars revceived over UART + int size_max - the maximum number of characters to be received +Return value: + number of chars received over UART +Description: + This function receives characters over UART. + In the canonic communication mode, the received chars will be retrieved by read only after \n is detected. + In the non canonic communication mode, the received chars will be retrieved by read as they are received, as the non canonic mode is configured with no wait. +*/ +int uartReceive(struct UartDevice* dev, char* data, int size_max) { + int received = 0; + +#ifdef DEBUG +// printf("%s: receiving characters %d\r\n", __func__, size_max); +#endif + received = read(dev->fd, data, size_max - 1); + data[received] = '\0'; + +#ifdef DEBUG +// if(received > 0) +// printf("%s: received %d characters\r\n", __func__, received); +// else +// printf("%s: r%d/%d\r\n", __func__, received, size_max); +#endif + return received; +} + +int uartStop(struct UartDevice* dev) { + free(dev->tty); + + return UART_SUCCESS; +} \ No newline at end of file diff --git a/uart.hpp b/uart.hpp new file mode 100644 index 0000000..66de474 --- /dev/null +++ b/uart.hpp @@ -0,0 +1,28 @@ +/* + * uart.h + * + * Created on: Aug 5, 2019 + * Author: cristian + */ + +#include +#include +#ifndef SRC_UART_H_ +#define SRC_UART_H_ +#define UART_FAILURE -1 +#define UART_SUCCESS 0 +// #define DEBUG +struct UartDevice { + char* name; + int rate; + + int fd; + struct termios* tty; +}; + +int uartStart(struct UartDevice* dev, unsigned char canonic); +int uartSend(struct UartDevice* dev, char* data, int size); +int uartReceive(struct UartDevice* dev, char* data, int size_max); +int uartStop(struct UartDevice* dev); + +#endif /* SRC_UART_H_ */ \ No newline at end of file diff --git a/zuart.cpp b/zuart.cpp new file mode 100644 index 0000000..941267f --- /dev/null +++ b/zuart.cpp @@ -0,0 +1,153 @@ + +#include +#include +#include +#include +#include +#include +#include +// +#include +#include +#include +#include +// +#include +#include +#include + +#include "uart.hpp" +using namespace std; +#define BACK_LOG 10 +#define MAX_RECV_SIZE 235 + +typedef struct { + int fd; + struct sockaddr_in client; +} tcpclient_t; +map g_baundmap = { + {"0", 0000000}, {"50", 0000001}, {"75", 0000002}, {"110", 0000003}, // + {"134", 0000004}, {"150", 0000005}, {"200", 0000006}, {"300", 0000007}, // + {"600", 0000010}, {"1200", 0000011}, {"1800", 0000012}, {"2400", 0000013}, // + {"4800", 0000014}, {"9600", 0000015}, {"19200", 0000016}, {"38400", 0000017}, // + {"57600", 0010001}, {"115200", 0010002}, {"230400", 0010003}, {"460800", 0010004}, // + {"500000", 0010005}, {"576000", 0010006}, {"921600", 0010007}, {"1000000", 0010010}, // + {"1152000", 0010011}, {"1500000", 0010012}, {"2000000", 0010013}, {"2500000", 0010014}, // + {"3000000", 0010015}, {"3500000", 0010016}, {"4000000", 0010017}, +}; +UartDevice g_uart_device = {0}; +void printf_buf(char *rx, ssize_t size) { + for (int i = 0; i < size; i++) { + printf("0x%02x,", rx[i]); + } + printf("\n"); +} + +void *uart_rx_thread_func(void *arg) { + char buff[4096]; + while (true) { + int ret = uartReceive(&g_uart_device, buff, 1024); // send the received text over UART + if (ret < 0) { + printf("uartReceive fail\n"); + exit(-1); + } + + // + if (ret > 0) { + printf("net<-uart: %d\n", ret); + printf_buf(buff, ret); + } + // + } + return NULL; +} + +int openuart(struct UartDevice *device, const char *devname, int rate) { + device->name = (char *)devname; + device->rate = rate; + + printf("UART open %s\n", device->name); + return uartStart(device, 0); +} + +static int strtohex(const char *str, uint8_t *hex) { + /** + * @brief + * str: 02 34 78 92 65 AF + */ + int len = strlen(str); + int i = 0; + int j = 0; + while (i < len) { + if (str[i] == ' ') { + i++; + continue; + } + char tmp[3] = {0}; + tmp[0] = str[i]; + tmp[1] = str[i + 1]; + hex[j] = strtol(tmp, NULL, 16); + i += 2; + j++; + } + if(j == 0){ + return 0; + } + return j-1; +} + +int main(int argc, char const *argv[]) { + /* code */ + //"net_uart /dev/ttyUSB0 115200 port" + + if (argc != 4) { + printf("Usage: %s /dev/ttyUSB0 115200 port\n", argv[0]); + return -1; + } + printf("device name:%s\n", argv[1]); + printf("baundrate :%s\n", argv[2]); + printf("port :%s\n", argv[3]); + + auto baundrate_find_result = g_baundmap.find(argv[2]); + if (baundrate_find_result == g_baundmap.end()) { + printf("unsupport baundrate\n"); + return -1; + // baundrate_find_result. + }; + + /** + * 打开串口 + */ + int rc = openuart(&g_uart_device, argv[1], baundrate_find_result->second); + if (rc) { + perror("open uart fail"); + exit(-1); + } + + pthread_t uart_rx_thread; + pthread_create(&uart_rx_thread, NULL, uart_rx_thread_func, NULL); + + while (true) { + char input[1024] = {0}; + uint8_t hex[1024] = {0}; + // scanf("%s", input); + fgets(input, 1024, stdin); + // printf("input:%s\n", input); + // 将输入的字符串转换为16进制 + + int nhex = strtohex(input, hex); + printf("tx:"); + printf_buf((char *)hex, nhex); + + // int ret = uartSend(&g_uart_device, input, strlen(input)); // send the received text over UART + int ret = uartSend(&g_uart_device, (char *)hex, nhex); // send the received text over UART + + if (ret < 0) { + printf("uartSend fail\n"); + } else { + printf("uartSend ok\n"); + } + } + + return 0; +} diff --git a/zuart.out b/zuart.out new file mode 100755 index 0000000..61c0997 Binary files /dev/null and b/zuart.out differ