AS SerialPort 编译依赖库
一.
1.1.新建工程 选择Native C++
1.1.
a.SerialPort.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | /* * Copyright 2009-2011 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <jni.h> #include "SerialPort.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; int xh_baudrate; #define TIOCSRS485 0x542F struct xh_serial_rs485 { unsigned long flags; /* RS485 feature flags */ unsigned long delay_rts_before_send; /* Delay before send (milliseconds) */ unsigned long delay_rts_after_send; /* Delay after send (milliseconds) */ }; static 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 ; } } /** * 设置串口数据,校验位,速率,停止位 * @param nBits 类型 int数据位 取值 位7或8 * @param nEvent 类型 char 校验类型 取值N ,E, O,,S * @param mStop 类型 int 停止位 取值1 或者 2 */ int set_opt(jint nBits, jchar nEvent, jint nStop,jint baudrate) { LOGE( "set_opt:nBits=%d,nEvent=%c,nStop=%d" , nBits, nEvent, nStop); struct termios newtio; speed_t speed; if (tcgetattr(fd, & newtio) != 0 ) { LOGE( "setup serial failure" ); return - 1 ; } /*波特率 */ { speed = getBaudrate(baudrate); if (speed == - 1 ) { /* TODO: throw an exception */ LOGE( "Invalid baudrate" ); return NULL; } } bzero( & newtio, sizeof(newtio)); //c_cflag标志可以定义CLOCAL和CREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。CLOCAL和CREAD通常总是被是能的 newtio.c_cflag |= CLOCAL | CREAD; cfmakeraw(&newtio); //设置波特率 cfsetispeed(&newtio, speed); cfsetospeed(&newtio, speed); 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 : break ; } switch (nEvent) //设置校验位 { case 'O' : newtio.c_cflag |= PARENB; //enable parity checking newtio.c_cflag |= PARODD; //奇校验位 newtio.c_iflag |= (INPCK ); break ; case 'E' : newtio.c_cflag |= PARENB; // newtio.c_cflag &= ~PARODD; //偶校验位 newtio.c_iflag |= (INPCK); break ; case 'N' : newtio.c_cflag &= ~PARENB; //清除校验位 break ; default : break ; } newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ newtio.c_oflag &= ~OPOST; /*Output*/ switch (nStop) //设置停止位 { case 1 : newtio.c_cflag &= ~CSTOPB; break ; case 2 : newtio.c_cflag |= CSTOPB; break ; default : // LOGW("nStop:%d,invalid param", nStop); break ; } newtio.c_cc[VTIME] = 100 ; //设置等待时间 newtio.c_cc[VMIN] = 0 ; //设置最小接收字符 tcflush(fd, TCIFLUSH); if (tcsetattr(fd, TCSANOW, & newtio) != 0 ) { LOGE( "options set error" ); return - 1 ; } LOGE( "options set success" ); return 1 ; } /* * Class: android_serialport_SerialPort * Method: open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */ JNIEXPORT jobject JNICALL Java_android_1serialport_1api_SerialPort_open (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint databits, jint stopbits, jchar parity) { LOGE( "Java_android_1serialport_1api_SerialPort_open\n" ); jobject mFileDescriptor; speed_t speed; xh_baudrate=baudrate; /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == - 1 ) { /* TODO: throw an exception */ LOGE( "Invalid baudrate" ); return NULL; } } /* Opening device */ { jint flags = 0 ; jboolean iscopy; const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); LOGD( "Opening serial port %s with flags 0x%x" , path_utf, O_RDWR | flags); fd = open(path_utf, O_RDWR | O_NONBLOCK); //fd=fd; LOGD( "open() fd = %d" , fd); (*env)->ReleaseStringUTFChars(env, path, path_utf); if (fd == - 1 ) { /* Throw an exception */ LOGE( "Cannot open port" ); /* TODO: throw an exception */ return NULL; } } /* Configure device */ { struct termios cfg; LOGD( "Configuring serial port" ); if (tcgetattr(fd, &cfg)) { LOGE( "tcgetattr() failed" ); close(fd); /* TODO: throw an exception */ return NULL; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { LOGE( "tcsetattr() failed" ); close(fd); /* TODO: throw an exception */ return NULL; } } //配置校验位 停止位等等 //set_opt(databits, parity, stopbits,baudrate); /* Create a corresponding file descriptor */ { jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor" ); jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>" , "()V" ); jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor" , "I" ); mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd); } return mFileDescriptor; } /* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close (JNIEnv *env, jobject thiz) { jclass SerialPortClass = (*env)->GetObjectClass(env, thiz); jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor" ); jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd" , "Ljava/io/FileDescriptor;" ); jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor" , "I" ); jobject mFd = (*env)->GetObjectField(env, thiz, mFdID); jint descriptor = (*env)->GetIntField(env, mFd, descriptorID); LOGD( "close(fd = %d)" , descriptor); close(descriptor); } /* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_write_1rs485_1length (JNIEnv *env, jobject thiz, jint count) { struct xh_serial_rs485 rs485conf; LOGD( "count= %d xh_baudrate = %d \n" , count,xh_baudrate); rs485conf.delay_rts_after_send = (( 10 * count * 1000 ) / xh_baudrate) + 1 ; ioctl (fd, TIOCSRS485, &rs485conf); } |
b.SerialPort.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class android_serialport_api_SerialPort */ #ifndef _Included_android_serialport_api_SerialPort #define _Included_android_serialport_api_SerialPort #ifdef __cplusplus extern "C" { #endif /* * Class: android_serialport_api_SerialPort * Method: open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */ JNIEXPORT jobject JNICALL Java_android_1serialport_1api_SerialPort_open (JNIEnv *, jclass, jstring, jint, jint,jint,jchar); /* * Class: android_serialport_api_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_write_rs485_length (JNIEnv *, jint); #ifdef __cplusplus } #endif #endif |
c.CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | # For more information about using CMake with Android Studio, read the # documentation: https: //d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.10 . 2 ) # Declares and names the project. project( "serialport" ) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. SerialPort # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). SerialPort.c) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default , you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. SerialPort # Links the target library to the log library # included in the NDK. ${log-lib}) |
E:\GatsbyDevelop\AndroidStuido\GatsbyASCode\GSerialPort\app\build\intermediates\cmake\debug\obj\arm64-v8a 下生成so文件
工程
1.3.
android_serialport_api
a.SerialPort.java 这个类主要用来加载SO文件 通过JNI的方式打开关闭串口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | package android_serialport_api; import android.util.Log; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class SerialPort { private static final String TAG = "SerialPort" ; /* * Do not remove or rename the field mFd: it is used by native method close(); */ private FileDescriptor mFd; private FileInputStream mFileInputStream; private FileOutputStream mFileOutputStream; public SerialPort(File device, int baudrate, int dataBits, int stopBits, char parity) throws SecurityException, IOException { /* Check access permission */ if (!device.canRead() || !device.canWrite()) { try { /* Missing read/write permission, trying to chmod the file */ Process su; su = Runtime.getRuntime().exec( "/system/bin/su" ); String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n" ; su.getOutputStream().write(cmd.getBytes()); if ((su.waitFor() != 0 ) || !device.canRead() || !device.canWrite()) { throw new SecurityException(); } } catch (Exception e) { e.printStackTrace(); throw new SecurityException(); } } mFd = open(device.getAbsolutePath(), baudrate, dataBits, stopBits, parity); if (mFd == null ) { Log.e(TAG, "native open returns null" ); throw new IOException(); } mFileInputStream = new FileInputStream(mFd); mFileOutputStream = new FileOutputStream(mFd); } // Getters and setters public InputStream getInputStream() { return mFileInputStream; } public OutputStream getOutputStream() { return mFileOutputStream; } public void Write_Rs485_Length( int count) { write_rs485_length(count); } // JNI(调用java本地接口,实现串口的打开和关闭) /**串口有五个重要的参数:串口设备名,波特率,检验位,数据位,停止位 其中检验位一般默认位NONE,数据位一般默认为8,停止位默认为1*/ /** * @param path 串口设备的据对路径 * @param baudrate 波特率 * @param dataBits 数据位 * @param stopBits 停止位 * @param parity 校验位 */ private native static FileDescriptor open(String path, int baudrate, int dataBits, int stopBits, char parity); public native void close(); public native void write_rs485_length( int count); static { //加载jni下的C文件库 System.loadLibrary( "serial_port" ); } } |
b.SerialPortFinder.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | /* * Copyright 2009-2011 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <jni.h> #include "SerialPort.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; int xh_baudrate; #define TIOCSRS485 0x542F struct xh_serial_rs485 { unsigned long flags; /* RS485 feature flags */ unsigned long delay_rts_before_send; /* Delay before send (milliseconds) */ unsigned long delay_rts_after_send; /* Delay after send (milliseconds) */ }; static 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 ; } } /** * 设置串口数据,校验位,速率,停止位 * @param nBits 类型 int数据位 取值 位7或8 * @param nEvent 类型 char 校验类型 取值N ,E, O,,S * @param mStop 类型 int 停止位 取值1 或者 2 */ int set_opt(jint nBits, jchar nEvent, jint nStop,jint baudrate) { LOGE( "set_opt:nBits=%d,nEvent=%c,nStop=%d" , nBits, nEvent, nStop); struct termios newtio; speed_t speed; if (tcgetattr(fd, & newtio) != 0 ) { LOGE( "setup serial failure" ); return - 1 ; } /*波特率 */ { speed = getBaudrate(baudrate); if (speed == - 1 ) { /* TODO: throw an exception */ LOGE( "Invalid baudrate" ); return NULL; } } bzero( & newtio, sizeof(newtio)); //c_cflag标志可以定义CLOCAL和CREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。CLOCAL和CREAD通常总是被是能的 newtio.c_cflag |= CLOCAL | CREAD; cfmakeraw(&newtio); //设置波特率 cfsetispeed(&newtio, speed); cfsetospeed(&newtio, speed); 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 : break ; } switch (nEvent) //设置校验位 { case 'O' : newtio.c_cflag |= PARENB; //enable parity checking newtio.c_cflag |= PARODD; //奇校验位 newtio.c_iflag |= (INPCK ); break ; case 'E' : newtio.c_cflag |= PARENB; // newtio.c_cflag &= ~PARODD; //偶校验位 newtio.c_iflag |= (INPCK); break ; case 'N' : newtio.c_cflag &= ~PARENB; //清除校验位 break ; default : break ; } newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ newtio.c_oflag &= ~OPOST; /*Output*/ switch (nStop) //设置停止位 { case 1 : newtio.c_cflag &= ~CSTOPB; break ; case 2 : newtio.c_cflag |= CSTOPB; break ; default : // LOGW("nStop:%d,invalid param", nStop); break ; } newtio.c_cc[VTIME] = 100 ; //设置等待时间 newtio.c_cc[VMIN] = 0 ; //设置最小接收字符 tcflush(fd, TCIFLUSH); if (tcsetattr(fd, TCSANOW, & newtio) != 0 ) { LOGE( "options set error" ); return - 1 ; } LOGE( "options set success" ); return 1 ; } /* * Class: android_serialport_SerialPort * Method: open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */ JNIEXPORT jobject JNICALL Java_android_1serialport_1api_SerialPort_open (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint databits, jint stopbits, jchar parity) { LOGE( "Java_android_1serialport_1api_SerialPort_open\n" ); jobject mFileDescriptor; speed_t speed; xh_baudrate=baudrate; /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == - 1 ) { /* TODO: throw an exception */ LOGE( "Invalid baudrate" ); return NULL; } } /* Opening device */ { jint flags = 0 ; jboolean iscopy; const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); LOGD( "Opening serial port %s with flags 0x%x" , path_utf, O_RDWR | flags); fd = open(path_utf, O_RDWR | O_NONBLOCK); //fd=fd; LOGD( "open() fd = %d" , fd); (*env)->ReleaseStringUTFChars(env, path, path_utf); if (fd == - 1 ) { /* Throw an exception */ LOGE( "Cannot open port" ); /* TODO: throw an exception */ return NULL; } } /* Configure device */ { struct termios cfg; LOGD( "Configuring serial port" ); if (tcgetattr(fd, &cfg)) { LOGE( "tcgetattr() failed" ); close(fd); /* TODO: throw an exception */ return NULL; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { LOGE( "tcsetattr() failed" ); close(fd); /* TODO: throw an exception */ return NULL; } } //配置校验位 停止位等等 //set_opt(databits, parity, stopbits,baudrate); /* Create a corresponding file descriptor */ { jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor" ); jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>" , "()V" ); jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor" , "I" ); mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd); } return mFileDescriptor; } /* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close (JNIEnv *env, jobject thiz) { jclass SerialPortClass = (*env)->GetObjectClass(env, thiz); jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor" ); jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd" , "Ljava/io/FileDescriptor;" ); jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor" , "I" ); jobject mFd = (*env)->GetObjectField(env, thiz, mFdID); jint descriptor = (*env)->GetIntField(env, mFd, descriptorID); LOGD( "close(fd = %d)" , descriptor); close(descriptor); } /* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */ JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_write_1rs485_1length (JNIEnv *env, jobject thiz, jint count) { struct xh_serial_rs485 rs485conf; LOGD( "count= %d xh_baudrate = %d \n" , count,xh_baudrate); rs485conf.delay_rts_after_send = (( 10 * count * 1000 ) / xh_baudrate) + 1 ; ioctl (fd, TIOCSRS485, &rs485conf); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】