主题 : android - HAL层 开发,操作硬件已不是问题 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 28534
精华: 0
发帖: 14
金钱: 70 两
威望: 14 点
贡献值: 0 点
综合积分: 28 分
注册时间: 2010-09-12
最后登录: 2012-02-12
楼主  发表于: 2011-11-02 15:02

 android - HAL层 开发,操作硬件已不是问题

        以前在android系统下怎样对硬件操作探讨了好久,因为android系统和LINUX系统有了很大的不同,对硬件操作比较麻烦。比如,文件系统的格式呀,打一个设备需要什么权限呀,总之很多问题。
       在MINI6410的手册上提到有对硬件的操作,但资料很少,只知调用其中的函数,不知其然,这是非常痛苦的。已是我决定自己搞一个出来()。从界面到内核的流程:

       界面:android---java编写
       界面接口函数:
          int     Open(String deviceName);
          int     Write(int fd, in char[] writeBuf, int len);
          int     Read(int fd,  out char[] readBuf,  int len);
          int     Ioctl(int fd, int cmd, in long[] arg);
          boolean Close(int fd);

       JNI层:为界面提供接口,调用HAL层的代码
       JNI层的接口函数:

      static jint jni_open(JNIEnv *env, jobject thiz, jstring deviceName);
     static jint jni_write(JNIEnv *env, jobject thiz, jint fd, jcharArray writeBuf, jint counts) ;
     static jint jni_read(JNIEnv *env, jobject thiz, jint fd,  jcharArray readBuf, jint counts) ;
     static jint jni_ioctl(JNIEnv *env, jobject thiz, jint fd, jint cmd, jlongArray arg);
     static jint jni_open(JNIEnv *env, jobject thiz, jstring deviceName);
     static jboolean jni_close(JNIEnv *env, jobject thiz, jint fd)  ;
   
     HAL层:操作硬件
    static int hal_write(char *write_buf, long buf_len);
    static int hal_read(char *read_buf, long buf_len); 
    static int hal_ioctl(int cmd, long *arg);
    static int hal_close(); 


   最终 JNI层编译出一个.SO文件放到/system/lib下
             HAL层编译出一个.SO文件放到/system/lib/hw下


   接下来,在HAL层操作硬件就像在LINUX下操作硬件一样了,(回家的感觉),下面给出一段操作串的程序
   #include <fcntl.h> 
#include <errno.h> 
#include <termios.h>
#include <stdio.h>

#include <pthread.h>
#include <sys/times.h>
#include <sys/select.h>
#include <assert.h>
#include <sys/types.h>
#include <cutils/atomic.h>  
#include <hardware/hardware.h> 
#include <hardware/overlay.h>
#include "serial.h"

//串口相关
struct termios serial_oldtio;
struct termios serial_newtio;
fd_set read_fds;
 
 /********************************************************************************
 **函数名称:
 **函数功能:
 **函数参数:
 **返 回 值:
 **********************************************************************************/
 static int set_serial_opts(int fd, int nSpeed, int nBits, char nEvent, int nStop)
 {
 int ret = -1;
 
 if (fd < 0)
  return -1;
 
 //将目前终端机参数保存到结构体变量flydvd_oldtio中
 if (tcgetattr(fd, &serial_oldtio) != 0)
 {
  //DLOGE("setupSerial");
  goto fail;
 }
 
 //结构体serial_newtio清0
 memset(&serial_newtio, 0, sizeof(serial_newtio));
   
 //设置串口参数
 serial_newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
 serial_newtio.c_oflag &= ~OPOST;
 serial_newtio.c_iflag &= ~(ICRNL | IGNCR);
 serial_newtio.c_cflag |= CLOCAL | CREAD;           //启动接收器
 serial_newtio.c_cflag &= ~CSIZE;
 serial_newtio.c_cc[VTIME] = 0;
 serial_newtio.c_cc[VMIN]  = 0;
 
 serial_newtio.c_cc[VINTR] = 0;
 serial_newtio.c_cc[VQUIT] = 0;
 serial_newtio.c_cc[VERASE] = 0;
 serial_newtio.c_cc[VKILL] = 0;
 serial_newtio.c_cc[VEOF] = 0;
 serial_newtio.c_cc[VTIME] = 1;
 serial_newtio.c_cc[VMIN] = 0;
 serial_newtio.c_cc[VSWTC] = 0;
 serial_newtio.c_cc[VSTART] = 0;
 serial_newtio.c_cc[VSTOP] = 0;
 serial_newtio.c_cc[VSUSP] = 0;
 serial_newtio.c_cc[VEOL] = 0;
 serial_newtio.c_cc[VREPRINT] = 0;
 serial_newtio.c_cc[VDISCARD] = 0;
 serial_newtio.c_cc[VWERASE] = 0;
 serial_newtio.c_cc[VLNEXT] = 0;
 serial_newtio.c_cc[VEOL2] = 0;

 
 switch (nBits)
 {
  case 7: serial_newtio.c_cflag |= CS7;break;
  case 8: serial_newtio.c_cflag |= CS8;break;
  default:
   serial_newtio.c_cflag |= CS8;break;
 }
 
 
 switch (nEvent)
 {
  case 'O':
   serial_newtio.c_cflag |= PARENB;
   serial_newtio.c_cflag |= PARODD;
   serial_newtio.c_iflag |= (INPCK|ISTRIP);
   break;
   
  case 'E':
   serial_newtio.c_cflag |= PARENB;
   serial_newtio.c_cflag &= ~PARODD;
   serial_newtio.c_iflag |= (INPCK|ISTRIP);
   break;
  
  case 'N':
   serial_newtio.c_cflag &= ~PARENB;
   break;
  
  default:
   serial_newtio.c_cflag &= ~PARENB;
   break;
 }
 
 switch (nSpeed)
 {
  case 9600:
   cfsetispeed(&serial_newtio, B9600);
   cfsetospeed(&serial_newtio, B9600);
   break;
  
  case 57600:
   cfsetispeed(&serial_newtio, B57600);
   cfsetospeed(&serial_newtio, B57600);
   break;
   
  case 115200:
   cfsetispeed(&serial_newtio, B115200);
   cfsetospeed(&serial_newtio, B115200);
   break;
   
  default:
   cfsetispeed(&serial_newtio, B9600);
   cfsetospeed(&serial_newtio, B9600);
   break;
 }
 
 if (nStop == 1)
  serial_newtio.c_cflag &= ~CSTOPB;
 else if (nStop == 2)
  serial_newtio.c_cflag = CSTOPB;
  
 //刷新在串口中的输入输出数据
 tcflush(fd, TCIFLUSH);
   
 //设置当前的的串口参数为flydvd_newtio
 if (tcsetattr(fd, TCSANOW, &serial_newtio) != 0)
 {
  //DLOGE("flydvd set error");
  goto fail;
 }
 
 ret = 0;
   
 fail:
  return ret;
 }
 
 /********************************************************************************
 **函数名称:
 **函数功能:
 **函数参数:
 **返 回 值:
 **********************************************************************************/
 int serial_write(int fd, unsigned char *buf, int len)
 {
 int ret = -1;
 
 if (fd < 0)
  return ret;
  
 //写入数据
 ret = write(fd, buf, len);
 if (ret > 0)
 {
  //DLOGI("flydvd_write OK");
 }
 else
 {
  //DLOGE("flydvd_write error");
 }
 
 return ret;
 }
 /********************************************************************************
 **函数名称:
 **函数功能:
 **函数参数:
 **返 回 值:
 **********************************************************************************/
 long serial_read(int fd, unsigned char *buf, int len)
 {
 long ret = -1;
 struct timeval tv_timeout;
 FD_SET(fd, &read_fds);
 tv_timeout.tv_sec = 1;
 tv_timeout.tv_usec = 0;
 switch (select(fd+1, &read_fds, NULL, NULL, &tv_timeout))
 {
  case -1:
   //DLOGE("select error");
   break;
    
  case 0:
   //DLOGE("select timeout");
   break;
    
  default:
   if (FD_ISSET(fd, &read_fds))
   {
    //读取数据
    ret = read(fd, buf, len);
    /*
    if (ret > 0)
    {  
     //DLOGD("DVD read %d bytes:", ret);
     //for (i=0; i<ret; i++)
     //{
      //DLOGD("%02X", read_buf);
     //}    
     return ret;
    }
    else
    {
     return -1;
     //continue;
     //DLOGD("flydvd not data to read ret is :%d", ret);
    }
    */
   }
   break; 
  }
  
 return ret;
 }
 
 /********************************************************************************
 **函数名称:
 **函数功能:
 **函数参数:
 **返 回 值:
 **********************************************************************************/
int serial_open(void)
{
 int fd = -1;
 int res = 0;
 pthread_t thread_id;
 
 fd = open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_NDELAY);
 if (fd > 0)    
 { 
  //DLOGI("flydvd com open OK");
 
  if (set_serial_opts(fd, 115200, 8, 'N', 1) == -1)
  {
   //DLOGE("set com opts error");
   return -1;
  }
  
  FD_ZERO(&read_fds);
 }
 
 return fd;
}
 /********************************************************************************
 **函数名称:
 **函数功能:
 **函数参数:
 **返 回 值:
 **********************************************************************************/
int serial_close(int fd)
{
 if (fd < 0)
  return -1;
  
 //恢复旧的端口参数
 tcsetattr(fd, TCSANOW, &serial_oldtio);
  
 //关闭串口
 if (!close(fd))
 {
  //DLOGI("flydvd_close ok"); 
  return 0;
 } 
 
 return -1;
}
 
看看,是不是和LINUX下操作一个串口一样呢!!




当然,我这个工程比较大,代码量很大,不能一一给大家展示,在此只能给大家一个思路,让大家从中了解原理


*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
贡献值: 71 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
1楼  发表于: 2011-11-02 16:24
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 28534
精华: 0
发帖: 14
金钱: 70 两
威望: 14 点
贡献值: 0 点
综合积分: 28 分
注册时间: 2010-09-12
最后登录: 2012-02-12
2楼  发表于: 2011-11-02 16:37



我这些都是参考网上的资料写出来的
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
贡献值: 71 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
3楼  发表于: 2011-11-02 16:57

 回 2楼(523回523回) 的帖子

欢迎你把你所参考的资料也分享出来,谢谢:)
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
joe
级别: 新手上路
UID: 18412
精华: 0
发帖: 9
金钱: 45 两
威望: 9 点
贡献值: 0 点
综合积分: 18 分
注册时间: 2010-04-09
最后登录: 2017-09-13
4楼  发表于: 2011-11-23 11:51
楼主可知如何绕过打开设备的权限问题。