#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#define PDBG printf
#define PERR printf
#define PRINT printf
#define PARAM_SPEED "-s"
#define PARAM_A_DEV "-a"
#define PARAM_B_DEV "-b"
#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
struct app_data_t {
char * adev;
char * bdev;
int afd;
int bfd;
int speed;
struct termios atio;
struct termios btio;
};
struct speed_map {
speed_t speed;
int value;
} speeds[] = {
{B50, 50},
{B75, 75},
{B110, 110},
{B134, 134},
{B150, 150},
{B200, 200},
{B300, 300},
{B600, 600},
{B1200, 1200},
{B1800, 1800},
{B2400, 2400},
{B4800, 4800},
{B9600, 9600},
{B19200, 19200},
{B38400, 38400},
{B57600, 57600},
{B115200, 115200},
{B230400, 230400},
{B460800, 460800},
};
speed_t tty_value_to_baud(int value)
{
int i = 0;
while(i < ARRAY_SIZE(speeds)) {
if(value = speeds[i].value) {
return speeds[i].speed;
}
i++;
}
return (speed_t)-1;
}
static void usage()
{
PRINT("Usage:\n");
PRINT("\ttty_trans [%s baud_rate] %s acm_dev %s bp_dev\n",
PARAM_SPEED, PARAM_A_DEV, PARAM_B_DEV);
}
/******************************************************************
* /data/tty_trans: -s 115200 -a /dev/ttyGS0 -b /dev/ttyUSB0
* get the speed and dev names
*/
static int parse_param( int argc, char **argv, struct app_data_t *app)
{
int i;
memset(app, 0, sizeof(struct app_data_t));
for(i = 1; i < argc; i++) {
if(strcmp(argv[i], "--help") == 0) {
usage();
exit(0);
} else if (strcmp(argv[i], PARAM_SPEED) == 0) {
i++;
if(i >= argc) {
return -1;
}
app->speed = strtol(argv[i], NULL, 10);
} else if (strcmp(argv[i], PARAM_A_DEV) == 0) {
i++;
if(i >= argc) {
return -1;
}
app->adev = argv[i];
} else if (strcmp(argv[i], PARAM_B_DEV) == 0) {
i++;
if(i >= argc) {
return -1;
}
app->bdev = argv[i];
} else {
return -1;
}
}
if(app->bdev == NULL || app->adev == NULL) {
return -1;
}
PDBG("acm dev:%s, bp dev:%s, speed:%d\n", app->adev, app->bdev, app->speed);
return 0;
}
static int set_tty_mod(int fd, struct termios *oldt, int speed)
{
struct termios tio;
tcgetattr(fd, oldt);
tio = *oldt;
cfmakeraw(&tio);
if(speed)
cfsetspeed(&tio, tty_value_to_baud(speed));
return tcsetattr(fd, TCSAFLUSH, &tio);
}
/******************************************************************
* open and set the set_tty_mod
*
*/
static int init_app(struct app_data_t *app)
{
int ret = 0;
app->afd = open(app->adev, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(app->afd < 0) {
PERR("Can't open : %s\n", app->adev);
return -1;
}
ret = set_tty_mod(app->afd, &app->atio, app->speed);
if(ret) {
PERR("%s: set tty mode failed\n", app->adev);
goto err_a_mod;
}
app->bfd = open(app->bdev, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(app->bfd < 0) {
PERR("Can't open : %s\n", app->bdev);
ret = -1;
goto err_b_open;
}
ret = set_tty_mod(app->bfd, &app->btio, app->speed);
if(ret) {
PERR("%s: set tty mode failed\n", app->bdev);
goto err_b_mod;
}
return 0;
err_b_mod:
close(app->bfd);
err_b_open:
tcsetattr(app->afd, TCSAFLUSH, &app->atio);
err_a_mod:
close(app->afd);
return ret;
}
static void close_app(struct app_data_t *app)
{
tcsetattr(app->bfd, TCSAFLUSH, &app->btio);
close(app->bfd);
tcsetattr(app->afd, TCSAFLUSH, &app->atio);
close(app->afd);
}
static int safe_read(int fd, void *buf, size_t count)
{
int n;
do {
n = read(fd, buf, count);
} while (n < 0 && errno == EINTR);
return n;
}
static int full_write(int fd, void *buf, int len)
{
int cc;
int total;
total = 0;
while (len) {
cc = write(fd, buf, len);
if (cc < 0) {
if(errno == EINTR)
continue;
if (total) {
/* we already wrote some! */
/* user can do another write to know the error code */
return total;
}
return cc; /* write() returns -1 on failure. */
}
total += cc;
buf = ((const char *)buf) + cc;
len -= cc;
}
return total;
}
static void run_app(struct app_data_t *app)
{
struct pollfd pfd[2];
int ret = 0;
pfd[0].fd = app->afd;
pfd[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
pfd[1].fd = app->bfd;
pfd[1].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
while(1) {
int rfd;
int wfd;
ret = poll(pfd, 2, -1);
if(ret < 0){
if(errno == EINTR || errno == ENOMEM)
continue;
else
break;
}
if(pfd[0].revents) {/*return event*/
if(!(pfd[0].revents & POLLIN))
return;
rfd = app->afd;
wfd = app->bfd;
} else if(pfd[1].revents) {
if(!(pfd[1].revents & POLLIN))
return;
rfd = app->bfd;
wfd = app->afd;
} else {
rfd = wfd = -1;
}
if(rfd >= 0 && wfd >=0) {
char buf[128];
int len;
len = safe_read(rfd, buf, sizeof(buf));
if(len > 0) {
len = full_write(wfd, buf, len);
if(len < 0)
return;
} else {
return;
}
}
}
}
/******************************************************************
*
*/
int main(int argc, char **argv)
{
struct app_data_t app;
int ret = 0;
/*
*/
ret = parse_param(argc, argv, &app);
if(ret) {
PERR("Invalid args!\n\n");
usage();
return -1;
}
ret = init_app(&app);
if(ret) {
PERR("init_app failed\n");
return -1;
}
run_app(&app);
close_app(&app);
return 0;
}
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#define PDBG printf
#define PERR printf
#define PRINT printf
#define PARAM_SPEED "-s"
#define PARAM_A_DEV "-a"
#define PARAM_B_DEV "-b"
#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
struct app_data_t {
char * adev;
char * bdev;
int afd;
int bfd;
int speed;
struct termios atio;
struct termios btio;
};
struct speed_map {
speed_t speed;
int value;
} speeds[] = {
{B50, 50},
{B75, 75},
{B110, 110},
{B134, 134},
{B150, 150},
{B200, 200},
{B300, 300},
{B600, 600},
{B1200, 1200},
{B1800, 1800},
{B2400, 2400},
{B4800, 4800},
{B9600, 9600},
{B19200, 19200},
{B38400, 38400},
{B57600, 57600},
{B115200, 115200},
{B230400, 230400},
{B460800, 460800},
};
speed_t tty_value_to_baud(int value)
{
int i = 0;
while(i < ARRAY_SIZE(speeds)) {
if(value = speeds[i].value) {
return speeds[i].speed;
}
i++;
}
return (speed_t)-1;
}
static void usage()
{
PRINT("Usage:\n");
PRINT("\ttty_trans [%s baud_rate] %s acm_dev %s bp_dev\n",
PARAM_SPEED, PARAM_A_DEV, PARAM_B_DEV);
}
/******************************************************************
* /data/tty_trans: -s 115200 -a /dev/ttyGS0 -b /dev/ttyUSB0
* get the speed and dev names
*/
static int parse_param( int argc, char **argv, struct app_data_t *app)
{
int i;
memset(app, 0, sizeof(struct app_data_t));
for(i = 1; i < argc; i++) {
if(strcmp(argv[i], "--help") == 0) {
usage();
exit(0);
} else if (strcmp(argv[i], PARAM_SPEED) == 0) {
i++;
if(i >= argc) {
return -1;
}
app->speed = strtol(argv[i], NULL, 10);
} else if (strcmp(argv[i], PARAM_A_DEV) == 0) {
i++;
if(i >= argc) {
return -1;
}
app->adev = argv[i];
} else if (strcmp(argv[i], PARAM_B_DEV) == 0) {
i++;
if(i >= argc) {
return -1;
}
app->bdev = argv[i];
} else {
return -1;
}
}
if(app->bdev == NULL || app->adev == NULL) {
return -1;
}
PDBG("acm dev:%s, bp dev:%s, speed:%d\n", app->adev, app->bdev, app->speed);
return 0;
}
static int set_tty_mod(int fd, struct termios *oldt, int speed)
{
struct termios tio;
tcgetattr(fd, oldt);
tio = *oldt;
cfmakeraw(&tio);
if(speed)
cfsetspeed(&tio, tty_value_to_baud(speed));
return tcsetattr(fd, TCSAFLUSH, &tio);
}
/******************************************************************
* open and set the set_tty_mod
*
*/
static int init_app(struct app_data_t *app)
{
int ret = 0;
app->afd = open(app->adev, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(app->afd < 0) {
PERR("Can't open : %s\n", app->adev);
return -1;
}
ret = set_tty_mod(app->afd, &app->atio, app->speed);
if(ret) {
PERR("%s: set tty mode failed\n", app->adev);
goto err_a_mod;
}
app->bfd = open(app->bdev, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(app->bfd < 0) {
PERR("Can't open : %s\n", app->bdev);
ret = -1;
goto err_b_open;
}
ret = set_tty_mod(app->bfd, &app->btio, app->speed);
if(ret) {
PERR("%s: set tty mode failed\n", app->bdev);
goto err_b_mod;
}
return 0;
err_b_mod:
close(app->bfd);
err_b_open:
tcsetattr(app->afd, TCSAFLUSH, &app->atio);
err_a_mod:
close(app->afd);
return ret;
}
static void close_app(struct app_data_t *app)
{
tcsetattr(app->bfd, TCSAFLUSH, &app->btio);
close(app->bfd);
tcsetattr(app->afd, TCSAFLUSH, &app->atio);
close(app->afd);
}
static int safe_read(int fd, void *buf, size_t count)
{
int n;
do {
n = read(fd, buf, count);
} while (n < 0 && errno == EINTR);
return n;
}
static int full_write(int fd, void *buf, int len)
{
int cc;
int total;
total = 0;
while (len) {
cc = write(fd, buf, len);
if (cc < 0) {
if(errno == EINTR)
continue;
if (total) {
/* we already wrote some! */
/* user can do another write to know the error code */
return total;
}
return cc; /* write() returns -1 on failure. */
}
total += cc;
buf = ((const char *)buf) + cc;
len -= cc;
}
return total;
}
static void run_app(struct app_data_t *app)
{
struct pollfd pfd[2];
int ret = 0;
pfd[0].fd = app->afd;
pfd[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
pfd[1].fd = app->bfd;
pfd[1].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
while(1) {
int rfd;
int wfd;
ret = poll(pfd, 2, -1);
if(ret < 0){
if(errno == EINTR || errno == ENOMEM)
continue;
else
break;
}
if(pfd[0].revents) {/*return event*/
if(!(pfd[0].revents & POLLIN))
return;
rfd = app->afd;
wfd = app->bfd;
} else if(pfd[1].revents) {
if(!(pfd[1].revents & POLLIN))
return;
rfd = app->bfd;
wfd = app->afd;
} else {
rfd = wfd = -1;
}
if(rfd >= 0 && wfd >=0) {
char buf[128];
int len;
len = safe_read(rfd, buf, sizeof(buf));
if(len > 0) {
len = full_write(wfd, buf, len);
if(len < 0)
return;
} else {
return;
}
}
}
}
/******************************************************************
*
*/
int main(int argc, char **argv)
{
struct app_data_t app;
int ret = 0;
/*
*/
ret = parse_param(argc, argv, &app);
if(ret) {
PERR("Invalid args!\n\n");
usage();
return -1;
}
ret = init_app(&app);
if(ret) {
PERR("init_app failed\n");
return -1;
}
run_app(&app);
close_app(&app);
return 0;
}