文件透传used by poll

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值