安卓串口读写

来源:互联网 发布:淘宝历史价格查询插件 编辑:程序博客网 时间:2024/05/21 21:47
#include "methods_serial.h"
#include "log_utile.h"
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
struct fields_t {
jfieldID fd;
jmethodID post_event;
jclass class;
};
int fd;
static struct fields_t fields;
extern JavaVM *sVm;
static const char* TAG = "methods_serial";
static const char* CLASS_NAME = "com/midea/bb8/utiles/UartUtile";
pthread_t pthreadID;
static int getFd(JNIEnv* env, jobject thiz) {
return (*env)->GetIntField(env, thiz, fields.fd);
}


void notify(JNIEnv *env, char* msg, int len) {
jbyteArray array = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, array, 0, len, msg);
(*env)->CallStaticVoidMethod(env, fields.class, fields.post_event, array);
(*env)->DeleteLocalRef(env, array);
}
speed_t 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;
}
}


int flag_is_running;


//数据接收
void serial_recv(void* ptr) {
LOGD(TAG, "create read thread");
unsigned char buffer[1024];
fd_set readFds;
FD_ZERO(&readFds);
FD_SET(fd, &readFds);
struct timeval val;
val.tv_sec = 1;
val.tv_usec = 0;
JNIEnv* env = NULL;
(*sVm)->AttachCurrentThread(sVm, &env, NULL);
while (flag_is_running) {


select(fd + 1, &readFds, NULL, NULL, &val); //一直在监控串口
memset(buffer, 0, 1024);
int retval = 0;
retval = read(fd, buffer, 1024);
if (retval > 0) {
// LOGD(TAG, "r=%s,%d", buffer, retval);
notify(env, buffer, retval);
}
}


(*sVm)->DetachCurrentThread(sVm);
LOGD(TAG, "recv thread close");
}
/*
 * Class:
 * Method:    open
 * Signature: (Ljava/lang/String;I)I
 */
jint init(JNIEnv *env, jobject thiz, jstring path, jint baudrate) {
speed_t speed;
jint error = -1;


LOGD(TAG, "init native Check arguments");
/* Check arguments */
{
speed = getBaudrate(baudrate);
if (speed == -1) {
/* TODO: throw an exception */
LOGE(TAG, "Invalid baudrate");
return error;
}
}


LOGD(TAG, "init native Opening device!");
/* Opening device */
{
jboolean iscopy;
const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
LOGD(TAG, "Opening serial port %s", path_utf);
//      fd = open(path_utf, O_RDWR | O_DIRECT | O_SYNC);
fd = open(path_utf, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
LOGD(TAG, "open() fd = %d", fd);
(*env)->ReleaseStringUTFChars(env, path, path_utf);
if (fd == -1) {
/* Throw an exception */
LOGE(TAG, "Cannot open port %d", baudrate);
/* TODO: throw an exception */
return error;
}
}


LOGD(TAG, "init native Configure device!");
/* Configure device */
{
struct termios cfg;
if (tcgetattr(fd, &cfg)) {
LOGE(TAG, "Configure device tcgetattr() failed 1");
close(fd);
return error;
}


// cfmakeraw(&cfg);
// cfsetispeed(&cfg, speed);
// cfsetospeed(&cfg, speed);


memset(&cfg, 0, sizeof(struct termios));
cfg.c_iflag = IGNPAR;
cfg.c_cflag = speed | HUPCL | CS8 | CREAD | CLOCAL;
cfg.c_cc[VMIN] = 1;


if (tcsetattr(fd, TCSANOW, &cfg)) {
LOGE(TAG, "Configure device tcsetattr() failed 2");
close(fd);
/* TODO: throw an exception */
return error;
}
}
jclass serialPortClass = (*env)->GetObjectClass(env, thiz);
fields.fd = (*env)->GetFieldID(env, serialPortClass, "mFileDescriptor",
"I");
if (fields.fd == NULL) {
close(fd);
jniThrowException(env, "java/lang/RuntimeException",
"Can't find mFileDescriptor");
return error;
}
fields.post_event = (*env)->GetStaticMethodID(env, serialPortClass,
"postEventFromNative", "([B)V");
if (fields.post_event == NULL) {
close(fd);
jniThrowException(env, "java/lang/RuntimeException",
"Can't find FFMpegMediaPlayer.postEventFromNative");
return error;
}
fields.class = (jclass) (*env)->NewGlobalRef(env, serialPortClass);


flag_is_running = 1;


pthread_create(&pthreadID, NULL, (void *) serial_recv, NULL);
return fd;
}
/*
 * Class:
 * Method:    close
 * Signature: ()V
 */
jint release(JNIEnv * env, jobject thiz) {
flag_is_running = 0;
// int fd = getFd(env, thiz);
if (fd < 0)
return -1;
LOGD(TAG, "close(fd = %d)", fd);
(*env)->DeleteGlobalRef(env, fields.class);
close(fd);
pthread_join(pthreadID, NULL);
return fd;
}
/**
 * @brief serial_write              发送串口数据
 * @param fd                        串口句柄
 * @param buf                       需要发送的缓冲区
 * @param buf_size                  缓冲区大小
 * @return                          发送状态
 */
int serial_write(int fd, const unsigned char *buf, int buf_size) {
int towrite = 1024; //一次写入最大值
do {
int wrote;
if (towrite > buf_size) {
towrite = buf_size;
}
wrote = write(fd, buf, towrite);
if (wrote <= 0) {
return -2;
} else {
buf_size -= wrote;
buf += wrote;
}
} while (buf_size > 0);
return 0;
}
/**
 * 写串口
 */
jint write_serial(JNIEnv *env, jobject thiz, jbyteArray buf, jint len) {
signed char *pBuffer = (*env)->GetByteArrayElements(env, buf, NULL);
int fd = getFd(env, thiz);
if (fd < 0)
return -1;
serial_write(fd, (unsigned char*) pBuffer, len);


(*env)->ReleaseByteArrayElements(env, buf, pBuffer, 0);
return len;
}


/*
 * JNI registration.
 */
static JNINativeMethod methods[] = { { "native_open", "(Ljava/lang/String;I)I",
init }, { "native_write", "([BI)I", (void*) write_serial }, {
"native_close", "()I", (void*) release }, };


int register_serial_methods(JNIEnv *env) {
return jniRegisterNativeMethods(env, CLASS_NAME, methods,
sizeof(methods) / sizeof(methods[0]));
}
原创粉丝点击