android 5.1 设备上使用 usb2com 时 【 tcgetattr() failed 】 错误问题解决

1 篇文章 0 订阅

先利用Android 源码编译一个小测试程序:

//test_tty.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <stdbool.h>
#include <termios.h>

//#include <cutils/Log.h>
//#include <utils/Log.h>

//#define  LOG_TAG    "test_tty"

#define READLENTH 256

int uartOpen(char *uartDevicePath,int speed,int dataWidth,int nstopBit)
{
	//Info
	int fd=-1;
	struct termios new_cfg,old_cfg; 
	printf("uart path=%s\n",uartDevicePath);  


	//open device
	fd=open(uartDevicePath,O_RDWR | O_NOCTTY );
    if(fd==-1){
        printf("open failed!\n");
        return -1;
    }


	//preserve the old configuration
    if(tcgetattr(fd,&old_cfg)!=0){
        printf("Old config preserve failed!\n");
        return -1;
    }


	//set mode
	new_cfg.c_cflag |=CLOCAL |CREAD;


	//set baudrate
	switch(speed){
		case 1800:{
			cfsetispeed(&new_cfg,B1800);
			cfsetospeed(&new_cfg,B1800);
		}break;
	case 2400:{
	   cfsetispeed(&new_cfg,B2400);
	   cfsetospeed(&new_cfg,B2400);
	}break;
	  case 4800:{
	   cfsetispeed(&new_cfg,B4800);
	   cfsetospeed(&new_cfg,B4800);
	}break;
	  case 9600:{
	   cfsetispeed(&new_cfg,B9600);
	   cfsetospeed(&new_cfg,B9600);
	}break;
	  case 19200:{
	   cfsetispeed(&new_cfg,B19200);
	   cfsetospeed(&new_cfg,B19200);
	  }break;
	  case 38400:{
	   cfsetispeed(&new_cfg,B38400);
	   cfsetospeed(&new_cfg,B38400);
	}break;
	  case 57600:{
	   cfsetispeed(&new_cfg,B57600);
	   cfsetospeed(&new_cfg,B57600);
	}break;
	  case 115200:{
	   cfsetispeed(&new_cfg,B115200);
	   cfsetospeed(&new_cfg,B115200);
	}break;
	  default:{
	  cfsetispeed(&new_cfg,B115200);
	  cfsetospeed(&new_cfg,B115200);
	  }break;
	}
	//set size of data
	new_cfg.c_cflag &=~CSIZE;
	switch(dataWidth){
		case 5:{
			new_cfg.c_cflag |=CS5;
		}break;
		case 6:{
			new_cfg.c_cflag |=CS6;
		}break;
		case 7:{
			new_cfg.c_cflag |=CS7;
		}break;
		case 8:{
			new_cfg.c_cflag |=CS8;
		}break;
		default :{
			new_cfg.c_cflag |=CS8;
		}break;
	}
	//set stopbit
	if(nstopBit == 2)
		new_cfg.c_cflag |=(CSTOPB);
	else if(nstopBit == 1)
		new_cfg.c_cflag &=~(CSTOPB);
	
	//set waittime out
	new_cfg.c_cc[VTIME]=80;  // n * 100ms 
	new_cfg.c_cc[VMIN]=0;
	
	//start
	if(-1==tcsetattr(fd,TCSANOW,&new_cfg)){
		printf("Uart setting failed!\n");
		return -1;
	}

	return fd;
}
int main(int argc, char *argv[])
{
    char buff[READLENTH] = {'\0'};
    int nread = 0;
    char path[20] = "/dev/ttyUSB0"; 
    


    int fd = 0;
    
    if(argc==2){
        printf("%s\n", argv[1]);
        memset(path, 0, strlen(path));
        memcpy(path, argv[1], strlen(argv[1]));
    }

    fd = uartOpen(path, 115200, 8, 1);
    if(fd<0){
	    printf("open error .....\n");
        return -1;
    }
	printf("runing .....\n");

    if(  (nread = read(fd, buff, READLENTH)) > 0 ){
         buff[nread+1] = '\0';
            printf("\nLen: %d\n",nread); 
            printf("str: %s\n", buff);

    }else{
        printf("read no data..\n");
    }

	close(fd);
	
    return 0;
}

//android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#LOCAL_C_INCLUDES :=$(LOCAL_PATH)/include

LOCAL_MODULE := test_tty

LOCAL_SRC_FILES := test_tty.c

LOCAL_LDLIBS := -llog

include $(BUILD_EXECUTABLE)

如何编译参考: http://www.cnblogs.com/7725657/p/5546249.html

注意,测试代码默认打开使用 /dev/ttyUSB0,如果是其它设备节点, 需要指定  ./test_tty /dev/ttyUSBx 。运行效果是,代码会阻塞在read处,8s超时后返回。


一切正常,将这个代码用jni封装给上层用时发现报错: 

uART setting failed!

查看设备节点权限,发现 0666 没毛病。多次尝试未解决。于是去找其它代码。
然后找到了google 的 serialport-demo ,先试的apk,安装后发现可以正常使用,然后编译源码安装后,居然报错 (tcgetattr() failed)好神奇,开始怀疑编译环境的问题。 什么
serialport-demo的相关下载地址:
源码下载地址:  https://github.com/cepr/android-serialport-api   
apk 下载地址: https://code.google.com/archive/p/android-serialport-api/downloads


在找 tcgetattr() failed  解决办法时,幸运的找到了这篇文章: https://stackoverflow.com/questions/44805009/android-native-open-serial-port   根据这篇文章找到了这篇博客:http://m.blog.csdn.net/caojengineer/article/details/51838394  ,然后明白termios.h file which has changed after Android 19 or Android 21.  解决办法,就是把csdn这边博文里面的termios.h 文件copy 到jni 的目录下,重新编译一下so 。然后运行 ok ....


修改后的工程目录结构如下:


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值