android_serialport_api hacking

  1 /************************************************************************************
  2  *
  3  *                    android_serialport_api hacking
  4  *
  5  *  声明:
  6  *      1. 这是android_serialport_api的jni源代码解读;
  7  *      2. 源代码url: https://code.google.com/p/android-serialport-api/
  8  *      3. 可以从中知道JNI是如何查找类,创建对象,访问对象的属性等等内容;
  9  *
 10  *
 11  * Copyright 2009-2011 Cedric Priscal
 12  *
 13  * Licensed under the Apache License, Version 2.0 (the "License");
 14  * you may not use this file except in compliance with the License.
 15  * You may obtain a copy of the License at
 16  *
 17  * http://www.apache.org/licenses/LICENSE-2.0
 18  *
 19  * Unless required by applicable law or agreed to in writing, software
 20  * distributed under the License is distributed on an "AS IS" BASIS,
 21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 22  * See the License for the specific language governing permissions and
 23  * limitations under the License.
 24  *
 25  *
 26  *
 27  * 相关参考:
 28  *    1. 访问JAVA中的字段(jfieldID): http://www.cnblogs.com/lijunamneg/archive/2012/12/22/2829023.html
 29  *    2. JNIEnv解析: http://blog.csdn.net/freechao/article/details/7692239
 30  *    3. The Java™ Native Interface Programmer’s Guide and Specification
 31  *
 32  *****************************************************************************/
 33 
 34 #include <termios.h>
 35 #include <unistd.h>
 36 #include <sys/types.h>
 37 #include <sys/stat.h>
 38 #include <fcntl.h>
 39 #include <string.h>
 40 #include <jni.h>
 41 
 42 #include "SerialPort.h"
 43 
 44 #include "android/log.h"
 45 
 46 /**
 47  * 定义一些宏,方便写调试代码
 48  */
 49 static const char *TAG="serial_port";
 50 #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
 51 #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
 52 #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
 53 
 54 static speed_t getBaudrate(jint baudrate)
 55 {
 56     switch(baudrate) {
 57     case 0: return B0;
 58     case 50: return B50;
 59     case 75: return B75;
 60     case 110: return B110;
 61     case 134: return B134;
 62     case 150: return B150;
 63     case 200: return B200;
 64     case 300: return B300;
 65     case 600: return B600;
 66     case 1200: return B1200;
 67     case 1800: return B1800;
 68     case 2400: return B2400;
 69     case 4800: return B4800;
 70     case 9600: return B9600;
 71     case 19200: return B19200;
 72     case 38400: return B38400;
 73     case 57600: return B57600;
 74     case 115200: return B115200;
 75     case 230400: return B230400;
 76     case 460800: return B460800;
 77     case 500000: return B500000;
 78     case 576000: return B576000;
 79     case 921600: return B921600;
 80     case 1000000: return B1000000;
 81     case 1152000: return B1152000;
 82     case 1500000: return B1500000;
 83     case 2000000: return B2000000;
 84     case 2500000: return B2500000;
 85     case 3000000: return B3000000;
 86     case 3500000: return B3500000;
 87     case 4000000: return B4000000;
 88     default: return -1;
 89     }
 90 }
 91 
 92 /*
 93  * Class:     com_android_aplex_SerialPort
 94  * Method:    open
 95  * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
 96  */
 97 JNIEXPORT jobject JNICALL Java_com_android_aplex_SerialPort_open
 98   (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)
 99 {
100     
101     int fd;
102     speed_t speed;
103     jobject mFileDescriptor;    //保存文件描述符的对象引用
104 
105     // Check arguments 
106     {
107         speed = getBaudrate(baudrate);
108         if (speed == -1) {
109             // TODO: throw an exception 
110             LOGE("Invalid baudrate");
111             return NULL;
112         }
113     }
114 
115     // Opening device 
116     {
117         jboolean iscopy;
118         /**
119          * 将Java的字符串转换成C中的字符串
120          */
121         const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
122         LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
123         fd = open(path_utf, O_RDWR | flags);
124         LOGD("open() fd = %d", fd);
125         /**
126          * 和前面的GetStringUTFChars一对用法,相当于malloc和free
127          */
128         (*env)->ReleaseStringUTFChars(env, path, path_utf);
129         if (fd == -1)
130         {
131             // Throw an exception 
132             LOGE("Cannot open port");
133             // TODO: throw an exception 
134             return NULL;
135         }
136     }
137 
138     // Configure device 
139     {
140         struct termios cfg;
141         LOGD("Configuring serial port");
142         if (tcgetattr(fd, &cfg))
143         {
144             LOGE("tcgetattr() failed");
145             close(fd);
146             // TODO: throw an exception 
147             return NULL;
148         }
149 
150         cfmakeraw(&cfg);
151         cfsetispeed(&cfg, speed);
152         cfsetospeed(&cfg, speed);
153 
154         if (tcsetattr(fd, TCSANOW, &cfg))
155         {
156             LOGE("tcsetattr() failed");
157             close(fd);
158             // TODO: throw an exception 
159             return NULL;
160         }
161     }
162 
163     // Create a corresponding file descriptor 
164     {
165         /**
166          * Returns a reference to the named class or interface.
167          * 这个相当于在当前虚拟机加载的所有的类中找这个类:java/io/FileDescriptor
168          */
169         jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");
170         /**
171          * To obtain the method ID of a constructor, supply "<init>" as the method name and “V” as the return type.
172          * 获取类中的无参构造函数
173          */
174         jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V");
175         jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");
176         /**
177          * Constructs a new object. The method ID indicates which constructor method to invoke. This ID may be obtained by calling
178          * GetMethodID with "<init>" as the method name and “V” as the return type. The constructor must be defined in the class
179          * referred to by clazz, not one of its superclasses.
180          * 生成一个类对象
181          */
182         mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);
183         /**
184          * Sets the value of an instance field of an object. The obj reference must not be NULL.
185          * 设置对象的值
186          */
187         (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);
188     }
189 
190     return mFileDescriptor;
191     
192 }
193 
194 /*
195  * Class:     com_android_aplex_SerialPort
196  * Method:    close
197  * Signature: ()V
198  */
199 JNIEXPORT void JNICALL Java_com_android_aplex_SerialPort_close
200   (JNIEnv *env, jobject thiz)
201 {
202     /**
203      * Returns the class of an object. The obj reference must not be NULL.
204      * thiz为java层传入的对象,GetObjectClass相当于获得这个对象的类,名字取得不错
205      */
206     jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
207     /**
208      * FindClass initializes the class or interface it returns.
209      * 这个相当于在当前虚拟机加载的所有的类中找这个类:java/io/FileDescriptor
210      */
211     jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");
212     /**
213      * Returns the field ID for an instance field of a class
214      * 通过域名、域类型获取类对应的域ID号
215      */
216     jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
217     jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");
218     /**
219      * Returns the value of a field of an instance. The field to access is specified by a field ID.
220      * 通过对象对应域的ID号获取域对象,或者值
221      */
222     jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
223     jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
224 
225     LOGD("close(fd = %d)", descriptor);
226     close(descriptor);
227     
228 }

 

posted on 2015-04-25 16:37  zengjf  阅读(743)  评论(0编辑  收藏  举报

导航