Browse Source

first commit

develop
zhaohe 4 years ago
parent
commit
8cede72a8c
  1. 5
      .clang-format
  2. 0
      .gitignore
  3. 5
      .vscode/settings.json
  4. 1
      build.sh
  5. 204
      net_uart.cpp
  6. 0
      release/v1.0/aarch64/.mark
  7. BIN
      release/v1.0/aarch64/net_tty.out
  8. 172
      uart.cpp
  9. 28
      uart.hpp

5
.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

0
.gitignore

5
.vscode/settings.json

@ -0,0 +1,5 @@
{
"files.associations": {
"string_view": "cpp"
}
}

1
build.sh

@ -0,0 +1 @@
aarch64-linux-gnu-g++ net_uart.cpp uart.cpp -o net_tty.out -lpthread

204
net_uart.cpp

@ -0,0 +1,204 @@
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
//
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
//
#include <map>
#include <set>
#include <string>
#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<string, uint32_t> 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};
set<int> g_remote_client_fds;
int safe_write(int fd, char *buff, size_t len) {
int hassend = 0;
while (true) {
int send_this_time = write(fd, buff + hassend, len - hassend);
if (send_this_time == 0) {
continue;
}
if (send_this_time < 0) {
return send_this_time;
}
hassend += send_this_time;
if (hassend == len) {
break;
}
}
return len;
}
void printf_buf(char *rx, ssize_t size) {
for (int i = 0; i < size; i++) {
printf("0x%02x,", rx[i]);
}
printf("\n");
}
void *netclient_thread(void *arg) {
tcpclient_t *client = (tcpclient_t *)arg;
// while循环监听数据,接收到数据转发给串口
char buff[4096];
int n = 0;
while ((n = read(client->fd, buff, 4096)) >= 0) {
printf("net->uart: %d\n", n);
printf_buf(buff, n);
uartSend(&g_uart_device, buff, n);
}
printf("socket %d is closed by client-end\n", client->fd);
close(client->fd);
g_remote_client_fds.erase(client->fd);
free(client);
pthread_detach(pthread_self());
return NULL;
}
void *uart_rx_thread(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);
for (auto &clientfd : g_remote_client_fds) {
safe_write(clientfd, buff, ret);
}
}
//
}
return NULL;
}
int start_tcp_server(int port) {
int listenfd, connectfd;
struct sockaddr_in server;
struct sockaddr_in client;
pid_t childpid;
socklen_t addrlen;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1) {
perror("socker created failed");
exit(0);
}
int option;
option = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, option, &option, sizeof(option));
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
printf("bind......\n");
if (bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1) {
perror("Bind error!");
exit(1);
}
printf("listen......\n");
if (listen(listenfd, BACK_LOG) == -1) {
perror("listend error");
exit(1);
}
printf("waiting for clinet's request.....\n");
while (1) {
int n;
addrlen = sizeof(client);
connectfd = accept(listenfd, (struct sockaddr *)&client, &addrlen);
if (connectfd == -1) {
perror("accept error");
sleep(1);
continue;
}
printf("%s connect to me,connectfd == %d\n", inet_ntoa(client.sin_addr), connectfd);
g_remote_client_fds.insert(connectfd);
pthread_t pthread;
tcpclient_t *client = (tcpclient_t *)malloc(sizeof(tcpclient_t));
if (client == NULL) {
perror("malloc fail");
exit(-1);
}
client->fd = connectfd;
memcpy(&client->client, &client, sizeof(client->client));
pthread_create(&pthread, NULL, netclient_thread, (void *)client);
}
return 0;
}
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);
}
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, netclient_thread, NULL);
start_tcp_server(atoi(argv[3]));
return 0;
}

0
release/v1.0/aarch64/.mark

BIN
release/v1.0/aarch64/net_tty.out

172
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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
/*
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] = 0; /* 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;
}

28
uart.hpp

@ -0,0 +1,28 @@
/*
* uart.h
*
* Created on: Aug 5, 2019
* Author: cristian
*/
#include <termios.h>
#include <unistd.h>
#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_ */
Loading…
Cancel
Save