现在的位置: 首页 > 综合 > 正文

linux用户层串口操作

2013年10月26日 ⁄ 综合 ⁄ 共 7066字 ⁄ 字号 评论关闭

1、宏定义

#defien N_HW_BFG    25      //线路规程编号

/* Paramaters to set the baud rate*/

#define BOTHER          0x00001000    

#define ARM_NCCS     19

#define TCGETS2         __IOR('T', 0x2A, struct termios2)

#define  TCSETS2        __IOW(‘T’, 0x2B, struct termios2)

/*sysfs节点路径*/

#define  INSTALL_SYSTEM_ENTRY    "/sys/devices/platform/hw-ps/install"

#define  DEV_NAME_SYSTEM              "/sys/devices/paltform/hw-ps/dev_name"

#define  BAUD_RATE_SYSTEM             "/sys/devices/paltform/hw-ps/baud_rate" 

#define  FLOW_CTRL_SYSTEM             "/sys/devices/paltform/hw-ps/flow_cntrl" 

2、STRUCT定义

/* Termios structure for setting the second baud rate*/

struct termios2 {

        tcflag_t c_iflag;         /* input mode flags */

        tcflag_t c_oflag;        /* output mode flags */

        tcflag_t c_cflag;        /* control mode flags */

        tcflag_t c_lflag;         /* local mode flags */

        cc_t c_line;                /* line discipline */

        cc_t c_cc[ARM_NCCS];            /* control characters */

        speed_t c_ispeed;       /* input speed */

        speed_t c_ospeed;      /* output speed */

};

 3、程序

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <poll.h>
#include "octty.h"

/* File descriptor for the UART device*/
int uart_fd;

static inline void close_uart(void)
{
 if (uart_fd == -1)
  return;

    OCTTY_DBG(" %s",__func__);
 close(uart_fd);
 uart_fd = -1;
}

/* Function to set the default baud rate
 *
 * The default baud rate of 115200 is set to the UART from the host side
 * by making a call to this function.This function is also called before
 * making a call to set the custom baud rate
 */
static int set_baud_rate()
{
 struct termios hisi;

    OCTTY_DBG(" %s",__func__);

 tcflush(uart_fd, TCIOFLUSH);

 /* Get the attributes of UART */
 if (tcgetattr(uart_fd, &hisi) < 0) {
  OCTTY_ERR(" Can't get port settings");
  return -1;
 }

 /* Change the UART attributes before
  * setting the default baud rate*/
 cfmakeraw(&hisi);

 hisi.c_cflag |= CLOCAL;
 hisi.c_cflag &= ~CRTSCTS;

 /* Set the attributes of UART after making
  * the above changes
  */
 tcsetattr(uart_fd, TCSANOW, &hisi);

 /* Set the actual default baud rate */
 cfsetospeed(&hisi, B115200);
 cfsetispeed(&hisi, B115200);
 tcsetattr(uart_fd, TCSANOW, &hisi);

 tcflush(uart_fd, TCIOFLUSH);
 OCTTY_DBG(" set_baud_rate() done");

 return 0;
}

/* Function to set the UART custom baud rate.
 *
 * The UART baud rate has already been
 * set to default value 115200 before calling this function.
 * The baud rate is then changed to custom baud rate by this function*/
static int change_baud_rate(int second_baud_rate, unsigned char flow_ctrl)
{
 struct termios hisi;
 struct termios2 hisi2;

    OCTTY_DBG(" %s",__func__);

 /* Get the attributes of UART */
 if (tcgetattr(uart_fd, &hisi) < 0) {
  OCTTY_ERR(" Can't get port settings");
  return -1;
 }

 /* Flush non-transmitted output data,
  * non-read input data or both*/
 tcflush(uart_fd, TCIOFLUSH);

 /*Set the UART flow control */
 if (flow_ctrl)
  hisi.c_cflag |= CRTSCTS;
 else
  hisi.c_cflag &= ~CRTSCTS;

 /*
  * Set the parameters associated with the UART
  * The change will occur immediately by using TCSANOW
  */
 if (tcsetattr(uart_fd, TCSANOW, &hisi) < 0) {
  OCTTY_ERR(" Can't set port settings");
  return -1;
 }

 tcflush(uart_fd, TCIOFLUSH);

 /*Set the actual baud rate */
 ioctl(uart_fd, TCGETS2, &hisi2);
 hisi2.c_cflag &= ~CBAUD;
 hisi2.c_cflag |= BOTHER;
 hisi2.c_ospeed = second_baud_rate;
 ioctl(uart_fd, TCSETS2, &hisi2);

 OCTTY_DBG(" change_baud_rate() done");
 return 0;
}

/*
 * Handling the Signals sent from the Kernel Init Manager.
 * After receiving the indication from rfkill subsystem, configure the
 * baud rate, flow control and Install the N_TI_WL line discipline
 */
int hisi_config_uart(unsigned char install)
{
 int ldisc, len, fd;
 unsigned char uart_dev_name[32];
 unsigned long second_baud_rate;
 unsigned int flow_ctrl;
 unsigned char buf[32];

    OCTTY_DBG(" %s",__func__);

 if ('1' == install) {
  OCTTY_DBG("install set to 1");

  memset(buf, 0, 32);
  fd = open(DEV_NAME_SYSFS, O_RDONLY);
  if (fd < 0) {
   OCTTY_ERR("Can't open %s", DEV_NAME_SYSFS);
   return -1;
  }
  len = read(fd, buf, 32);
  if (len < 0) {
   OCTTY_ERR("read err (%s)", strerror(errno));
   close(fd);
   return len;
  }
  sscanf((const char*)buf, "%s", uart_dev_name);
  close(fd);

  memset(buf, 0, 32);
  fd = open(BAUD_RATE_SYSFS, O_RDONLY);
  if (fd < 0) {
   OCTTY_ERR("Can't open %s", BAUD_RATE_SYSFS);
   return -1;
  }
  len = read(fd, buf, 32);
  if (len < 0) {
   OCTTY_ERR("read err (%s)", strerror(errno));
   close(fd);
   return len;
  }
  close(fd);
  sscanf((const char*)buf, "%ld", &second_baud_rate);

  memset(buf, 0, 32);
  fd = open(FLOW_CTRL_SYSFS, O_RDONLY);
  if (fd < 0) {
   OCTTY_ERR("Can't open %s", FLOW_CTRL_SYSFS);
   close(fd);
   return -1;
  }
  len = read(fd, buf, 32);
  if (len < 0) {
   OCTTY_ERR("read err (%s)", strerror(errno));
   close(fd);
   return len;
  }
  close(fd);
  sscanf((const char*)buf, "%u", &flow_ctrl);

  if (uart_fd != -1) {
   OCTTY_ERR("opening %s, while already open", uart_dev_name);
   close_uart();
  }

  uart_fd = open((const char*) uart_dev_name, O_RDWR|O_NOCTTY);
  if (uart_fd < 0) {
   OCTTY_ERR(" Can't open %s", uart_dev_name);
   return -1;
  }
  /*
   * Set only the default baud rate.
   * This will set the baud rate to default 115200
   */
  if (set_baud_rate() < 0) {
   OCTTY_ERR(" set_baudrate() failed");
   close_uart();
   return -1;
  }

  fcntl(uart_fd, F_SETFL,fcntl(uart_fd, F_GETFL) | O_NONBLOCK);
  /* Set only thecustom baud rate */
  if (second_baud_rate != 115200) {
   /* Writing the change speed command to the UART
    * This will change the UART speed at the controller
    * side
    */

   /* Set the second baud rate at the host side */
   if (change_baud_rate(second_baud_rate, flow_ctrl) < 0) {
    OCTTY_ERR(" change_baud_rate() failed");
    close_uart();
    return -1;
   }
  }

  /* After the UART speed has been changed, the IOCTL is
   * is called to set the line discipline to N_HW_BFG
   */
  ldisc = N_HW_BFG;
  /* 选择线路规程 */
  if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0) {  
   OCTTY_ERR(" Can't set line discipline");
   close_uart();
   return -1;
  }
  OCTTY_DBG(" Have installed N_HW_BFG Line displine");
 }
 else {
  OCTTY_DBG(" Un-Installed N_HW_BFG Line displine");
  /* UNINSTALL_N_TI_WL - When the Signal is received from KIM */
  /* closing UART fd */
  close_uart();
  uart_fd = -1;
 }
 return 0;
}

/*****************************************************************************/
int main()
{
 int hw_fd,err;
 struct pollfd   pfd;
 unsigned char install;

 err = 0;
    uart_fd = -1;

    OCTTY_DBG(" %s",__func__);

 /* rfkill device's open/poll/read */
 hw_fd = open(INSTALL_SYSFS_ENTRY, O_RDONLY);
 if (hw_fd < 0) {
  OCTTY_ERR("unable to open %s (%s)", INSTALL_SYSFS_ENTRY,
    strerror(errno));
  return -1;
 }

    while(1)
    {
     err = read(hw_fd, &install, 1);
     if ((err > 0) && (install == '1')) {
      OCTTY_ERR("install already set");
     }
     memset(&pfd, 0, sizeof(pfd));
     pfd.fd = hw_fd;
     /* sysfs entries can only break poll for following events */
     pfd.events = POLLERR | POLLHUP;

        while (1) {
      pfd.revents = 0;
      err = poll(&pfd, 1, -1);
      if (err < 0 && errno == EINTR)
      {
       continue;
      }
      if (err)
      {
       break;
      }
     }
     close(hw_fd);
     hw_fd = open(INSTALL_SYSFS_ENTRY, O_RDONLY);
     if (hw_fd < 0) {
      OCTTY_ERR("re-opening %s failed: %s", INSTALL_SYSFS_ENTRY,
              strerror(errno));
      return -1;
     }
     err = read(hw_fd, &install, 1);
     if (err <= 0) {
      OCTTY_ERR("reading %s failed: %s", INSTALL_SYSFS_ENTRY,
        strerror(errno));
            return -1;
     }
     hisi_config_uart(install);
    }
 close(hw_fd);
 return 0;
}

4、makefile文件

OBJ=octty.o
BIN=octty
CC=arm-linux-gcc
C_FLAGS=-g -Wall
LD_FLAGS= -static

$(BIN):$(OBJ)
 $(CC) -o $@ $^ $(LD_FLAGS)

.c.o:
 $(CC) -c -o $@ $< $(C_FLAGS)

clean:
 rm -rf $(BIN)
 rm -rf *.o

install:$(BIN)
 adb push $(BIN) /

.PHONY: clean install

 

 

 

 

 

 

 

抱歉!评论已关闭.