zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Eclipse “cannot be resolved to a type” error
    Hadoop作业提交分析(三)
    Hadoop作业提交分析(五)
    Hadoop作业提交分析(一)
    An Idiot Computer Story
    基于ASP.NET的comet简单实现
    火车票余票查询小助手(windows 7 gadget)
    Div+CSS+JQuery轻松实现选项卡"选项卡"
    jQuery+Div Simple menu
    Visual Studio 2010 cannot goto definition
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/4456140.html
Copyright © 2011-2022 走看看