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
#include
#include
#include
#include
#include
#include
#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