在常见的嵌入式外设中,串口通信是经常使用的一种通信机制,本篇文章给你带来,如何在Android系统中实现对串口设备的访问。
在Android中如何访问底层Linux的设备驱动,必然要用到HAL,即:硬件抽象层。关于HAL的概念及框架分析,请查看作者的下面几篇博文。
> 深入浅出 - Android系统移植与平台开发(七)- 初识HAL
http://blog.csdn.net/mr_raptor/article/details/8069588
> 深入浅出 - Android系统移植与平台开发(八)- HAL Stub框架分析
http://blog.csdn.net/mr_raptor/article/details/8074549
> 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析
http://blog.csdn.net/mr_raptor/article/details/8082360
1. 首先,我们先定义出串口的API类,即:SerialService,它为串口访问应用程序提示了两个API接口:read()和write()方法。
@serial_app\src\cn\com\farsight\SerialService\SerialService.java
- package cn.com.farsight.SerialService;
- import java.io.BufferedReader;
- import java.io.UnsupportedEncodingException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
-
- import android.util.Log;
-
- public class SerialService {
- private static final String TAG = "SerialService";
-
- private boolean isInitOk = false;
-
-
- static {
- Log.d(TAG, "System.loadLibrary()");
- System.loadLibrary("serial_runtime");
- }
-
-
- public SerialService(){
- Log.d(TAG, "SerialService()");
-
- isInitOk = _init();
- Log.d(TAG, "_init()");
- }
-
-
- public String read() {
- Log.d(TAG, "read()");
- if(!isInitOk)
- return "串口初始化失败,请确认已经连接串口设备。";
-
- byte[] data = new byte[128];
-
- _read(data, 128);
-
- String ret;
- try{
-
- ret = new String(data, "GBK");
- }catch(UnsupportedEncodingException e1) {
- return null;
- }
- return ret;
- }
-
-
- public int write(String s) {
- Log.d(TAG, "write()");
- int len;
- try{
-
- len = _write(s.getBytes("GBK"));
- }catch(UnsupportedEncodingException e1) {
- return -1;
- }
- return len;
- }
-
- private static native boolean _init();
- private static native int _read(byte[] data, int len);
- private static native int _write(byte[] data);
- }
2. 编写SerialService的运行时代码,即:cn_com_farsight_SerialService_SerialService.cpp,实现JNI调用函数:_init(),_read(),_write()。
串口硬件抽象层头文件:
@serial_hal\include\serial.h
- #include <hardware/hardware.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <cutils/log.h>
- #include <cutils/atomic.h>
-
- #define serial_HARDWARE_MODULE_ID "serial"
-
-
-
-
- struct serial_module_t {
- struct hw_module_t common;
-
- };
-
-
-
-
-
-
-
-
-
- struct serial_control_device_t {
- struct hw_device_t common;
-
-
- int (*serial_read_hal)(struct serial_control_device_t *dev, char *buf, int count);
-
- int (*serial_write_hal)(struct serial_control_device_t *dev, char *buf, int count);
-
- };
-
-
-
-
@serial_runtime\cn_com_farsight_SerialService_SerialService.cpp
下面的代码用到JNI部分知识点,详情请看:
> 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
http://blog.csdn.net/mr_raptor/article/details/8080606
- #include <hardware/hardware.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <errno.h>
- #include <cutils/log.h>
- #include <cutils/atomic.h>
- #include <sys/ioctl.h>
- #include <errno.h>
- #include <string.h>
- #include <dirent.h>
- #include "../include/serial.h"
-
- int fd;
-
- static int serial_device_close(struct hw_device_t* device)
- {
- LOGD("%s E", __func__);
- struct serial_control_device_t* ctx = (struct serial_control_device_t*)device;
- if (ctx) {
- free(ctx);
- }
- close(fd);
- LOGD("%s X", __func__);
- return 0;
- }
-
- static int serial_read_drv(struct serial_control_device_t *dev, char *buf, int count)
- {
- LOGD("%s E", __func__);
- int len = 0;
- len = read(fd, buf, count);
- if(len < 0)
- {
- perror("read");
- }
- LOGD("%s X", __func__);
- return len;
- }
-
- static int serial_write_drv(struct serial_control_device_t *dev, char *buf, int size)
- {
- LOGD("%s E", __func__);
- int len = write(fd, buf, size);
- if(len < 0)
- {
- perror("write");
- }
- LOGD("%s X", __func__);
- return len;
- }
-
- static int serial_device_open(const struct hw_module_t* module, const char* name,
- struct hw_device_t** device)
- {
- LOGD("%s E", __func__);
- struct serial_control_device_t *dev;
- struct termios opt;
-
- dev = (struct serial_control_device_t *)malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
-
-
- dev->common.tag= HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
- dev->common.module= module;
-
- dev->serial_read_hal = serial_read_drv;
-
- dev->serial_write_hal = serial_write_drv;
- *device= &dev->common;
-
-
- char devname[PATH_MAX];
- DIR *dir;
- struct dirent *de;
- dir = opendir("/dev");
- if(dir == NULL)
- return -1;
- strcpy(devname, "/dev");
- char * filename = devname + strlen(devname);
- *filename++ = '/';
- while((de = readdir(dir))) {
- if(de->d_name[0] == '.' || strncmp(de->d_name, "ttyUSB", 6))
- continue;
- strcpy(filename, de->d_name);
- if((fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY)) < 0)
- {
- LOGE("open error");
- return -1;
- }else {
- LOGD("open ok\n");
- break;
- }
- }
-
-
-
- tcgetattr(fd, &opt);
-
- cfsetispeed(&opt, B9600);
- cfsetospeed(&opt, B9600);
-
-
-
- opt.c_cflag |= (CLOCAL | CREAD);
-
- opt.c_cflag &= ~CSIZE;
- opt.c_cflag &= ~CRTSCTS;
- opt.c_cflag |= CS8;
-
-
-
-
-
-
- opt.c_iflag |= IGNPAR;
-
- opt.c_cflag &= ~CSTOPB;
-
- opt.c_oflag = 0;
- opt.c_lflag = 0;
-
- tcsetattr(fd, TCSANOW, &opt);
-
- LOGD("%s X", __func__);
-
- return 0;
- }
-
-
- static struct hw_module_methods_t serial_module_methods = {
- open: serial_device_open
- };
-
-
-
-
-
-
- const struct serial_module_t HAL_MODULE_INFO_SYM = {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: serial_HARDWARE_MODULE_ID,
-
- name: "serial HAL module",
- author: "farsight",
- methods: &serial_module_methods,
- },
-
- };
4. 相关代码下载:
http://download.csdn.net/detail/mr_raptor/7033385