#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
#include <errno.h>
#include "android/log.h"
static const char *TAG="serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
int fd;
static struct termios oldtio,newtio;
#define BAUDRATE 115200
static int getBaudrate(jint baudrate)
{
switch(baudrate) {
case 0: return B0;
case 50: return B50;
case 75: return B75;
case 110: return B110;
case 134: return B134;
case 150: return B150;
case 200: return B200;
case 300: return B300;
case 600: return B600;
case 1200: return B1200;
case 1800: return B1800;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
case 460800: return B460800;
case 500000: return B500000;
case 576000: return B576000;
case 921600: return B921600;
case 1000000: return B1000000;
case 1152000: return B1152000;
case 1500000: return B1500000;
case 2000000: return B2000000;
case 2500000: return B2500000;
case 3000000: return B3000000;
case 3500000: return B3500000;
case 4000000: return B4000000;
default: return -1;
}
}
/*
* Class: cedric_serial_SerialPort
* Method: open
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT jint Java_android_serialport_SerialPort_open
(JNIEnv *env, jobject thiz, jstring path, jint baudrate,jint dataBits, jint stopBits)
{
int speed;
char nEvent='N';
jobject mFileDescriptor;
/* Check arguments */
{
speed = getBaudrate(baudrate);
if (speed == -1) {
/* TODO: throw an exception */
//LOGE("Invalid baudrate");
return 0;
}
}
/* Opening device */
{
jboolean iscopy;
const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
//LOGD("Opening serial port %s", path_utf);
fd = open(path_utf, O_RDWR/* | O_NOCTTY | O_SYNC | O_DIRECT | O_NDELAY*/);
//LOGD("open() fd = %d", fd);
(*env)->ReleaseStringUTFChars(env, path, path_utf);
if (fd == -1)
{
/* Throw an exception */
//LOGE("Cannot open port");
//LOGE("Failed to open serial port %d(%s)",errno, strerror(errno));
/* TODO: throw an exception */
return 0;
}
}
if ( tcgetattr( fd,&oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
/*步骤一,设置字符大小*/
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
/*设置停止位*/
switch( dataBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
/*设置奇偶校验位*/
switch( nEvent )
{
case '0': //奇数
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': //偶数
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N': //无奇偶校验位
newtio.c_cflag &= ~PARENB;
break;
}
/*设置波特率*/
speed=getBaudrate(baudrate);
cfsetispeed(&newtio,speed );
cfsetospeed(&newtio, speed);
/*设置停止位*/
if( stopBits == 1 )
newtio.c_cflag &= ~CSTOPB;
else if ( stopBits == 2 )
newtio.c_cflag |= CSTOPB;
/*设置等待时间和最小接收字符*/
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
/*处理未接收字符*/
tcflush(fd,TCIFLUSH);
/*激活新配置*/
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
fcntl(fd, F_SETFL,0);
return fd;
}
/*write SerialPort data*/
jint Java_android_serialport_SerialPort_write(JNIEnv *env, jobject thiz,jint fd, jbyteArray data)
{
jbyte *buf=(*env)->GetByteArrayElements(env,data,NULL);
int lenght=(*env)->GetArrayLength(env,data);
int i;
for( i=0;i<lenght;i++)
{
write(fd,&buf[i],1);
usleep(100);
}
return 1;
}
/*read SerialPort data*/
JNIEXPORT jint Java_android_serialport_SerialPort_read(JNIEnv *env, jobject thiz,jint fd, jbyteArray data,jint len)
{
//new a "byte data[]"
//jclass byteArrCls=(*env)->FindClass(env,"[B");//B==byte
//data=(*env)->NewByteArray(env,len);
jbyte *buf=(*env)->GetByteArrayElements(env,data,NULL);
int i;
read(fd,buf,len);
tcflush(fd, TCIFLUSH);
(*env)->ReleaseByteArrayElements(env,data,buf,0);
return 1;
}
/*
* Class: cedric_serial_SerialPort
* Method: close
* Signature: ()V
*/
JNIEXPORT void Java_android_serialport_SerialPort_close
(JNIEnv *env, jobject thiz)
{
//LOGD("close(fd = %d)", fd);
close(fd);
}