Android原生串口源码学习

1. 涉及到的文件

framework下的:
./base/tests/SerialChat/src/com/android/serialchat/SerialChat.java 测试类

主要以下几个文件:
1. ./base/core/java/android/hardware/SerialManager.java
2. ./base/services/java/com/android/server/SerialService.java
3. ./base/core/java/android/hardware/SerialPort.java
4. ./base/core/jni/android_hardware_SerialPort.cpp
5. ./base/services/jni/com_android_server_SerialService.cpp

还有一个aidl文件

2. 从测试类开始

主要是以下调用:

private SerialManager mSerialManager = (SerialManager)getSystemService(Context.SERIAL_SERVICE);
String[] ports = mSerialManager.getSerialPorts();
private SerialPort mSerialPort = mSerialManager.openSerialPort(ports[0], 115200);

2.1.获取服务类

2.2调用方法:getSerialPorts,

即从xml文件中得到设置的字符串.

2.3.打开串口:

public class SerialManager {
    public String[] getSerialPorts() {        
    	return mService.getSerialPorts();        
    }
    
    public SerialPort openSerialPort(String name, int speed) {
            ParcelFileDescriptor pfd = mService.openSerialPort(name);
            if (pfd != null) {
                SerialPort port = new SerialPort(name);
                port.open(pfd, speed);
                return port;
            } 
    }
}

其中:

2.3.1 openSerialPort打开串口,得到描述符

private final ISerialManager mService;
ParcelFileDescriptor pfd = mService.openSerialPort(name);

会调用到服务程序SerialService:
./base/services/java/com/android/server/SerialService.java


public class SerialService extends ISerialManager.Stub {
    public ParcelFileDescriptor openSerialPort(String path) {
        for (int i = 0; i < mSerialPorts.length; i++) {
            if (mSerialPorts[i].equals(path)) {
                return native_open(path);
            }
        }
    }
    private native ParcelFileDescriptor native_open(String path);
}

进而调用native方法,返回一个串口的文件描述符:

  • ./base/services/jni/com_android_server_SerialService.cpp:
  • com/android/server/SerialService :
static jobject android_server_SerialService_open(JNIEnv *env, jobject thiz, jstring path)
{
    const char *pathStr = env->GetStringUTFChars(path, NULL);
    int fd = open(pathStr, O_RDWR | O_NOCTTY);
    if (fd < 0) {
        ALOGE("could not open %s", pathStr);
        env->ReleaseStringUTFChars(path, pathStr);
        return NULL;
    }
    env->ReleaseStringUTFChars(path, pathStr);
    jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
    if (fileDescriptor == NULL) {
        return NULL;
    }
    return env->NewObject(gParcelFileDescriptorOffsets.mClass,
        gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
}


static JNINativeMethod method_table[] = {
    { "native_open",                "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
                                    (void*)android_server_SerialService_open },
};

2.3.2. 构造SerialPort对象

SerialPort port = new SerialPort(name);
port.open(pfd, speed);
public class SerialPort {
	public void open(ParcelFileDescriptor pfd, int speed) throws IOException {
	        native_open(pfd.getFileDescriptor(), speed);
	        mFileDescriptor = pfd;
	}
	private native void native_open(FileDescriptor pfd, int speed) throws IOException;
}

调用JNI:

  • android/hardware/SerialPort
  • {“native_open”, “(Ljava/io/FileDescriptor;I)V”, (void *)android_hardware_SerialPort_open},
android_hardware_SerialPort_open(JNIEnv *env, jobject thiz, jobject fileDescriptor, jint speed)
{
	int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
	//	将fd设置到context field,后面读写要用
	env->SetIntField(thiz, field_context, fd);
	//设置波特率等参数,串口的常规操作
	tcsetattr(fd, TCSANOW, &tio);
    tcflush(fd, TCIFLUSH);
}

3.总结调用流程:

private SerialManager mSerialManager;
  ./base/core/java/android/hardware/SerialManager.java
     public SerialPort openSerialPort(String name, int speed)

        mService.openSerialPort(name);//通过名字得到fd
                /*服务进程:*/
                ./base/services/java/com/android/server/SerialService.java
                ParcelFileDescriptor openSerialPort(String path)
                native_open(path);
                ./base/services/jni/com_android_server_SerialService.cpp
                com/android/server/SerialService
                  native_open : android_server_SerialService_open(JNIEnv *env, jobject thiz, jstring path)

        SerialPort port = new SerialPort(name);
        port.open(pfd, speed);
                  native_open(pfd.getFileDescriptor(), speed);
                  ./base/core/jni/android_hardware_SerialPort.cpp
                  android/hardware/SerialPort
                    native_open: android_hardware_SerialPort_open(JNIEnv *env, jobject thiz, jobject fileDescriptor, jint speed) 

后续的读写就是用拿到的服务进程的fd去操作了.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值