今天遇到一个客户想用uart和本地socket跟carplay进行对接,通过uart交互指令,通过本地socket对接iap数据。
这里的uart就是伪终端,这是第一次接触伪终端。
部分函数说明:
1、open("/dev/ptmx", O_RDWR | O_NOCTTY );
返回值就是伪终端主设备的文件描述符
2、grantpt函数:在伪终端从设备可被使用之前,必须设置它的权限,使得应用程序可以访问它。它把从设备节点的用户ID设置为调用者的实际用户ID, 设置其组ID为一非指定值,通常是可以访问该终端设备的组。将权限设置为:对单个所有者是读写,对组所有者是写(0620)。参数是伪终端主设备的文件描述符
3、unlockpt函数:用于准予对伪终端从设备的访问,从而允许应用程序打开该设备。阻止其他进程打开从设备,使得建立该设备的应用程序有机会在使用主、从设备之前正确地初始化这些设备。参数是伪终端主设备的文件描述符
4、ptsname或者ptsname_r函数:使用伪终端主设备的文件描述符,找到伪终端从设备的路径名。
5、unlink:删除文件
6、symlink(name_slave, dev)建立软链接。例如:通过ptsname或者ptsname_r函数可以得到从设备的路径名,比如/dev/pts/0。然后给从设备建立一个软链接/dev/bt_serial,这样其他程序就可以直接打开/dev/bt_serial和主设备通信了
7、伪终端是有回显功能的,所以write数据后,自己还能read到,要关闭回显功能需要下面的代码
struct termios sg;
tcgetattr(fd, &sg);
sg.c_lflag &= ~ECHO;
tcsetattr(fd,TCSAFLUSH,&sg);
打开uart的代码如下:
static int bt_for_zj_uart_open(char *dev)
{
int fd = -1;
char name_slave[50]={0};
char buffer[100] = {0};
struct termios sg;
printf("start\n");
fd = open("/dev/ptmx", O_RDWR | O_NOCTTY );
if( fd >= 0 )
{
if (grantpt(fd))
{
printf("grantpt failed errno(%d): %s\n", errno, strerror(errno));
close(fd);
return -1;
}
if (unlockpt(fd))
{
printf("unlockpt failed errno(%d): %s\n", errno, strerror(errno));
close(fd);
return -1;
}
if(ptsname_r(fd, name_slave, sizeof(name_slave))!=0)
{
printf("ptsname_r failed errno(%d): %s\n", errno, strerror(errno));
close(fd);
return -1;
}
printf("grantpt name_slave:%s\n",name_slave);
unlink(dev);
if (symlink(name_slave, dev) != 0)
{
printf("symlink failed errno(%d): %s\n", errno, strerror(errno));
close(fd);
return -1;
}
sprintf(buffer, "chmod 777 %s", name_slave);
system(buffer);
tcgetattr(fd, &sg);
sg.c_lflag &= ~ECHO;
tcsetattr(fd,TCSAFLUSH,&sg);
printf("%s fd=%d\n", buffer, fd);
return fd;
}else{
printf("failed!!!\n");
return -1;
}
}