Android通过JNI操作串口《二》

来源:互联网 发布:windows自动更新有用吗 编辑:程序博客网 时间:2024/05/20 07:15

3.    JNI实现类

#include"JNIHelp.h"

#include"android_runtime/AndroidRuntime.h"

#include<utils/misc.h>

#include<utils/Log.h>

#include<utils/threads.h>

#include<pthread.h>

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<string.h>

#include<utils/Log.h>

#include<sys/ioctl.h>

#include<termios.h>

 

#include"com_notioni_uart_manager_TtyNativeControl.h"

 

usingnamespace android;

 

structfields_t{

   jfieldID   tty;

   jmethodID  post_event;

};

staticfields_t fields;

JavaVM* g_JavaVM;

 

#define TTY_DEVICE "/dev/ttyS2"

 

#define LOG_TAG "TtyNativeControl"

#define RECEIVE_DATA_INDEX (1)

 

#define POST_EVENT()

staticint mTtyfd = -1;

staticint mOpen = 0;

 

/**

 * class Listener

 */

classJNIMyObserver{

public:

   JNIMyObserver(JNIEnv* env,jobject thiz,jobject weak_thiz);

   ~JNIMyObserver();

   voidOnEvent(constchar* buffer,int length,int what);

private:

   JNIMyObserver();

   jclass mClass;

   jobject mObject;

   Mutex mLock;

};

JNIMyObserver::JNIMyObserver(JNIEnv* env,jobject thiz,jobject weak_thiz){

   jclass clazz = env->GetObjectClass(thiz);

   if(clazz == NULL){

   // jniThrowException(env,"java/lang/Exception",NULL);

      LOGE("clazz is null");

      return;

   }

   mClass = (jclass)env->NewGlobalRef(clazz);

   mObject = env->NewGlobalRef(weak_thiz);

   LOGW("mClass=%d",mClass);

   LOGW("mObject=%d",mObject);

}

JNIMyObserver::~JNIMyObserver(){

   JNIEnv *env = AndroidRuntime::getJNIEnv();

   env->DeleteGlobalRef(mObject);

   env->DeleteGlobalRef(mClass);

}

voidJNIMyObserver::OnEvent(constchar* buffer,int length,int what){

   LOGW("OnEvent");

   Mutex::Autolock _l(mLock);

   if(NULL == g_JavaVM){

      LOGE("JNIObserver::Event g_JavaVM is NULL");

      return;

   }

   bool isAttacked =false;

   /*

    * 创建env指针

    */

   JNIEnv* env;

   bool status = (g_JavaVM->GetEnv((void**) &env,JNI_VERSION_1_4) != JNI_OK);

   if(status){

      g_JavaVM->AttachCurrentThread(&env,NULL);

   }

   /*

    * 创建JAVA byte[]数组

    */

   jbyteArray obj = NULL;

   if(buffer !=NULL && buffer != 0){

       const jbyte* data =reinterpret_cast<const jbyte*>(buffer);

      obj = env->NewByteArray(length);

      env->SetByteArrayRegion(obj,0,length,data);

   }

   env->CallStaticVoidMethod(mClass,fields.post_event,mObject,what,0,0,obj);

   if(obj){

      env->DeleteLocalRef(obj);

   }

   if(isAttacked){

      g_JavaVM->DetachCurrentThread();//分离线程

   }

 

}

/**

 * class Listener end -----------------

 */

 

 

 

 

 

JNIMyObserver* listener;

/*

 * setup

 */

staticvoid JNICALL com_notioni_uart_manager_TtyNativeControl_native_setup(JNIEnv *env,jobject clazz,jobject weak_this){

   LOGW("com_notioni_uart_manager_TtyNativeControl_native_setup");

   env->GetJavaVM(&g_JavaVM);

   if(listener != NULL){

      delete listener;

   }

   listener = new JNIMyObserver(env,clazz,weak_this);

}

/*

 * _openTty

 */

staticint JNICALL com_notioni_uart_manager_TtyNativeControl__openTty(JNIEnv *env,jobject clazz){

   LOGW("com_notioni_uart_manager_TtyNativeControl__openTty");

   mTtyfd = open(TTY_DEVICE,O_RDWR|O_NONBLOCK);//读写方式

   if(mTtyfd < 0){

      LOGE("mTtyfd open failure");

      return -1;

   }

   if(fcntl(mTtyfd,F_SETFL,0)<0){//恢复串口为堵塞状态

      LOGE("mTtyfd fcntl failure");

   }

// if(isatty(STDIN_FILENO)==0){//测试是否为中断设备,非0即使终端设备

//    LOGE("standard inputs is not a terminal device");

// }else{

//    LOGE("isatty success");

// }

   mOpen = 1;

   LOGW("open device success");

   return 1;

}

/*

 * _closeTty

 */

staticint JNICALL com_notioni_uart_manager_TtyNativeControl__closeTty(JNIEnv *env,jobject clazz){

   LOGW("com_notioni_uart_manager_TtyNativeControl__closeTty");

   if(mTtyfd < 0){

      LOGE("mTtyfd open failure ,non't close");

      return -1;

   }

   mOpen = 0;

   sleep(2);//等待线程退出

   int c = close(mTtyfd);

   if(c < 0){

      LOGE("mTtyfd close failure");

      return -1;

   }

   LOGW("close device success");

   return 1;

}

 

/*

 * _sendMsgToTty

 */

staticint JNICALL com_notioni_uart_manager_TtyNativeControl__sendMsgToTty(JNIEnv *env,jobject clazz,jbyteArray data){//byte[]

   LOGW("com_notioni_uart_manager_TtyNativeControl__sendMsgToTty");

    //jbyte * arrayBody = env->GetByteArrayElements(data,0); jsize theArrayLengthJ = env->GetArrayLength(data); BYTE * starter = (BYTE *)arrayBody;

   if(mTtyfd < 0){

      LOGE("mTtyfd open failure ,non't write");

      return -1;

   }

 

   jbyte* arrayData = (jbyte*)env->GetByteArrayElements(data,0);

   jsize arrayLength = env->GetArrayLength(data);

   char* byteData = (char*)arrayData;

   int len = (int)arrayLength;

   LOGW("write data len:%d",len);

   int re = write(mTtyfd,byteData,len);

   if(re == -1){

      LOGE("write device error");

   }

   return re;

}

 

/*

 *线程Run

 */

void*threadreadTtyData(void* arg){

   LOGW("run read data");

   if(!(arg)){

      return NULL;

   }

   char* buf =newchar[200];

   int result = 0,ret;

   fd_set readfd;

   structtimeval timeout;

   while(mOpen){

      timeout.tv_sec = 2;//设定超时秒数

      timeout.tv_usec = 0;//设定超时毫秒数

 

      FD_ZERO(&readfd);//清空集合

      FD_SET(mTtyfd,&readfd);///*把要检测的句柄mTtyfd加入到集合里 */

      ret = select(mTtyfd+1,&readfd,NULL,NULL,&timeout);/*检测我们上面设置到集合readfd里的句柄是否有可读信息 */

 

      switch(ret){

      case -1:/*这说明select函数出错 */

          result = -1;

          LOGE("mTtyfd read failure");

          break;

      case 0:/*说明在我们设定的时间值5秒加0毫秒的时间内,mTty的状态没有发生变化 */

          break;

      default:/*说明等待时间还未到5秒加0毫秒,mTty的状态发生了变化*/

          if(FD_ISSET(mTtyfd,&readfd)){/*先判断一下mTty这外被监视的句柄是否真的变成可读的了 */

             int len = read(mTtyfd,buf,sizeof(buf));

             /**发送数据**/

             if(!(arg))break;

             JNIMyObserver *l =static_cast<JNIMyObserver *>(arg);

             l->OnEvent(buf,len,RECEIVE_DATA_INDEX);

             memset(buf,0,sizeof(buf));

          }

          break;

      }

      if(result == -1){

          break;

      }

   }

   if(buf != NULL){

      delete buf;

      buf = NULL;

   }

   LOGE("stop run!");

   return NULL;

}

/*

 * _receiveMsgFromTty

 */

staticvoid JNICALL com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty(JNIEnv *env,jobject clazz){

   LOGW("com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty");

   if(mTtyfd < 0){

      LOGE("mTtyfd open failure ,non't read");

      return ;

   }

   pthread_t id;

   int ret;

   ret = pthread_create(&id,NULL,threadreadTtyData,listener);

   if(ret != 0){

      LOGE("create receiver thread failure ");

   }else{

      LOGW("create read data thred success");

   }

   

}

 

 

/**

 *设置串口数据,校验位,速率,停止位

 * @param nBits类型 int数据位取值78

 * @param nEvent类型 char 校验类型取值N ,E, O,,S

 * @param mSpeed类型int 速率取值 2400,4800,9600,115200

 * @param mStop类型int 停止位取值1或者 2

 */

intset_opt(int nBits,char nEvent,int nSpeed,int nStop){

   LOGW("set_opt:nBits=%d,nEvent=%c,nSpeed=%d,nStop=%d",nBits,nEvent,nSpeed,nStop);

   structtermios newtio,oldtio;

   if(tcgetattr(mTtyfd,&oldtio) != 0){

      LOGE("setup serial failure");

      return -1;

   }

   bzero(&newtio,sizeof(newtio));

//c_cflag标志可以定义CLOCALCREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。CLOCALCREAD通常总是被是能的

   newtio.c_cflag |=CLOCAL|CREAD;

   //newtio.c_cflag &=~CSIZE;

 

   switch(nBits){//设置数据位数

   case 7:

      newtio.c_cflag &=~CSIZE;

      newtio.c_cflag |=CS7;

      break;

   case 8:

      newtio.c_cflag &=~CSIZE;

      newtio.c_cflag |=CS8;

      break;

   default:

      LOGW("nBits:%d,invalidparam",nBits);

      break;

   }

 

   switch(nEvent){//设置校验位

   case'O':

      newtio.c_cflag |=PARENB;//enable parity checking

      newtio.c_cflag |=PARODD;//奇校验位

      newtio.c_iflag |=(INPCK|ISTRIP);

      //options.c_iflag |= INPCK;//Disable parity checking

      break;

   case'E':

      newtio.c_cflag|=PARENB;//

      newtio.c_cflag&=~PARODD;//偶校验位

      newtio.c_iflag|=(INPCK|ISTRIP);

      //options.c_iflag |= INPCK;//Disable parity checking

      break;

   case'N':

      newtio.c_cflag &=~PARENB;//清除校验位

      //options.c_iflag &=~INPCK;//Enable parity checking

      break;

   //case 'S':

   // options.c_cflag &= ~PARENB;//清除校验位

   // options.c_cflag &=~CSTOPB;

   // options.c_iflag |=INPCK;//Disable parity checking

   // break;

   default:

      LOGW("nEvent:%c,invalidparam",nEvent);

      break;

   }

   switch(nSpeed){//设置速率

   case 2400:

      LOGW("B2400:%d",B2400);

      cfsetispeed(&newtio,B2400);

      cfsetospeed(&newtio,B2400);

      break;

   case 4800:

      LOGW("B4800:%d",B4800);

      cfsetispeed(&newtio,B4800);

      cfsetospeed(&newtio,B4800);

      break;

   case 9600:

      LOGW("B9600:%d",B9600);

      cfsetispeed(&newtio,B9600);

      cfsetospeed(&newtio,B9600);

      break;

   case 115200:

      LOGW("B115200:%d",B115200);

      cfsetispeed(&newtio,B115200);

      cfsetospeed(&newtio,B115200);

      break;

   default:

      cfsetispeed(&newtio,B9600);

      cfsetospeed(&newtio,B9600);

      

      LOGW("nSpeed:%d,invalidparam",nSpeed);

      break;

   }

 

   switch(nStop){//设置停止位

   case 1:

      newtio.c_cflag &= ~CSTOPB;

      break;

   case 2:

      newtio.c_cflag |= CSTOPB;

      break;

   default:

      LOGW("nStop:%d,invalidparam",nStop);

      break;

   }

 

   newtio.c_cc[VTIME] = 0;//设置等待时间

   newtio.c_cc[VMIN] = 0;//设置最小接收字符

   tcflush(mTtyfd,TCIFLUSH);

   if(tcsetattr(mTtyfd,TCSANOW,&newtio) != 0){

      LOGE("options set error");

      return -1;

   }

   return 1;

}

 

/*

 * _configTty

*/

staticint JNICALL com_notioni_uart_manager_TtyNativeControl__configTty(JNIEnv *env,jobject clazz,int nBits,jchar nEvent,int nSpeed,int nStop){

   LOGW("com_notioni_uart_manager_TtyNativeControl__configTty");

   return set_opt(nBits,nEvent,nSpeed,nStop);

}

 

intset_mode(int nMode,int showLog){

   LOGW("set_mode:nMode%d,nshowLog=%d",nMode,showLog);

   structtermios options;

   if(tcgetattr(mTtyfd,&options) != 0){

      LOGE("setup serial failure");

      return -1;

   }

   intresult = 1;

   if(nMode != 0){

      if(nMode ==1){

          options.c_lflag &=~(ICANON | ECHO | ECHOE | ISIG);//input

          options.c_oflag &=~OPOST;//out put

      }elseif(nMode == 2){

          options.c_lflag |=(ICANON | ECHO | ECHOE | ISIG);//input

          options.c_oflag |=OPOST;//out put

      }

      if(tcsetattr(mTtyfd,TCSANOW,&options) != 0){

          LOGE("tcsetattr device fail");

          result = -1;

      }

   }

   if(showLog == 1){

          LOGI("options c_cflag.CS7:%d,CS8:%d",options.c_cflag & CS7,options.c_cflag & CS8);

          LOGI("options c_cflag.PARENB:%d,PARODD:%d",options.c_cflag & PARENB,options.c_cflag & PARODD);

          LOGI("options c_iflag.INPCK%d,ISTRIP:%d",options.c_iflag & INPCK,options.c_iflag & ISTRIP);

          LOGI("option c_ispeed:%d,c_ospeed:%d",cfgetispeed(&options) ,cfgetospeed(&options));

          LOGI("options c_cflag.CSTOPB:%d,",options.c_cflag & CSTOPB);

          LOGI("options c_cc.VTIME:%d,VMIN:%d",options.c_cc[VTIME],options.c_cc[VMIN]);

          LOGI("options c_cflag.CLOCAL:%d,CREAD:%d",options.c_cflag & CLOCAL,options.c_cflag&CREAD);

          LOGI("options c_lflag.ICANON:%d,ECHO:%d,ECHOE:%d,ISIG:%d",options.c_lflag & ICANON,options.c_lflag&ECHO,options.c_lflag&ECHOE,options.c_lflag&ISIG);

          LOGI("options c_oflag.OPOST:%d,",options.c_oflag &OPOST);

      }

   returnresult;

}

staticint JNICALL com_notioni_uart_manager_TtyNativeControl__setMode(JNIEnv *env,jobject clazz,int nMode,int showLog){

   LOGW("com_notioni_uart_manager_TtyNativeControl__setMode");

   return set_mode(nMode,showLog);

}

 

 

static JNINativeMethod method_table[] = {

      {"native_setup","(Ljava/lang/Object;)V",(void *)com_notioni_uart_manager_TtyNativeControl_native_setup},

      {"_openTty","()I",(void *)com_notioni_uart_manager_TtyNativeControl__openTty},

      {"_closeTty","()I",(void *)com_notioni_uart_manager_TtyNativeControl__closeTty},

 

      {"_sendMsgToTty","([B)I",(void *)com_notioni_uart_manager_TtyNativeControl__sendMsgToTty},

      {"_receiveMsgFromTty","()V",(void *)com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty},

      {"_configTty","(ICII)I",(void *)com_notioni_uart_manager_TtyNativeControl__configTty},

      {"_setMode","(II)I",(void *)com_notioni_uart_manager_TtyNativeControl__setMode},

};

 

staticconstchar* classPathName="com/notioni/uart/manager/TtyNativeControl";

staticintregister_com_notioni_uart_manager_TtyNativeControl(JNIEnv *env){

   LOGW("register_com_notioni_uart_manager_TtyNativeControl");

   jclass clazz;

   clazz = env->FindClass(classPathName);

   if(clazz == NULL){

      return -1;

   }

   fields.post_event = env->GetStaticMethodID(clazz,"postEventFromNative",

          "(Ljava/lang/Object;IIILjava/lang/Object;)V");

   if(fields.post_event == NULL){

      LOGE("Can't findcom/notioni/uart/manager.postEventFromNative");

      return -1;

   }

   return AndroidRuntime::registerNativeMethods(env,classPathName,method_table,NELEM(method_table));

}

 

jintJNI_OnLoad(JavaVM* vm,void* reserved){

   LOGW("JNI_OnLoad");

   JNIEnv* env = NULL;

   jint result = -1;

   if(vm->GetEnv((void**)&env,JNI_VERSION_1_4) != JNI_OK){

      goto bail;

   }

   LOGW("registermothod");

   assert(env != NULL);

   if(register_com_notioni_uart_manager_TtyNativeControl(env) < 0){

      goto bail;

   }

   return JNI_VERSION_1_4;

bail:

   return result;

}


0 0
原创粉丝点击