【Android】串口通信
jni部分SerialPort.c
JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open (JNIEnv *env, jobject thiz, jstring path, jint baudrate) { int fd; speed_t speed; jobject mFileDescriptor; /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == -1) { /* TODO: throw an exception */ LOGE("Invalid baudrate"); return NULL; } } /* 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_DIRECT | O_SYNC); fd = open(path_utf, O_RDWR | O_SYNC); 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; } } /* 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_serialport_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); }Java代码部分
SerialPort.java
/* * Copyright 2009 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. */ package android.serialport; 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; import android.util.Log; 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) throws SecurityException, IOException { Log.i("chw", "SerialPort ---> SerialPort"); /* 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 777 " + device.getAbsolutePath() + "\n" //+ "exit\n"; String cmd = "chmod 777 /dev/s3c_serial0" + "\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(); }*/ try { String command = "chmod 777 " + device.getAbsolutePath(); Log.i("chw", "command = " + command + "\ndevice.getAbsolutePath = " + device.getAbsolutePath()); Runtime runtime = Runtime.getRuntime(); Process proc = runtime.exec(command); } catch (IOException e) { Log.i("chw","chmod fail!! !!"); e.printStackTrace(); throw new SecurityException(); } Log.i("chw", "Get serial port read/write permission"); } mFd = open(device.getAbsolutePath(), baudrate); 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() { Log.i("chw", "SerialPort ---> getInputStream"); return mFileInputStream; } public OutputStream getOutputStream() { Log.i("chw", "SerialPort ---> getOutputStream"); return mFileOutputStream; } // JNI private native static FileDescriptor open(String path, int baudrate); public native void close(); static { Log.i("chw", "SerialPort ---> loadLibrary"); System.loadLibrary("serial_port"); } }
SerialPortFinder.java
/* * Copyright 2009 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. */ package android.serialport; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; import java.util.Iterator; import java.util.Vector; import android.util.Log; public class SerialPortFinder { public class Driver { public Driver(String name, String root) { Log.i("chw", "SerialPortFinder ---> Driver"); mDriverName = name; mDeviceRoot = root; } private String mDriverName; private String mDeviceRoot; Vector<File> mDevices = null; public Vector<File> getDevices() { Log.i("chw", "SerialPortFinder ---> getDevices"); if (mDevices == null) { mDevices = new Vector<File>(); File dev = new File("/dev"); File[] files = dev.listFiles(); int i; for (i=0; i<files.length; i++) { if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) { Log.d(TAG, "Found new device: " + files[i]); mDevices.add(files[i]); } } } return mDevices; } public String getName() { Log.i("chw", "SerialPortFinder ---> getName"); return mDriverName; } } private static final String TAG = "SerialPort"; private Vector<Driver> mDrivers = null; Vector<Driver> getDrivers() throws IOException { Log.i("chw", "SerialPortFinder ---> getDrivers"); if (mDrivers == null) { mDrivers = new Vector<Driver>(); LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers")); String l; while((l = r.readLine()) != null) { String[] w = l.split(" +"); if ((w.length == 5) && (w[4].equals("serial"))) { Log.d(TAG, "Found new driver: " + w[1]); mDrivers.add(new Driver(w[0], w[1])); } } r.close(); } return mDrivers; } public String[] getAllDevices() { Log.i("chw", "SerialPortFinder ---> getAllDevices"); Vector<String> devices = new Vector<String>(); // Parse each driver Iterator<Driver> itdriv; try { itdriv = getDrivers().iterator(); while(itdriv.hasNext()) { Driver driver = itdriv.next(); Iterator<File> itdev = driver.getDevices().iterator(); while(itdev.hasNext()) { String device = itdev.next().getName(); String value = String.format("%s (%s)", device, driver.getName()); devices.add(value); } } } catch (IOException e) { e.printStackTrace(); } return devices.toArray(new String[devices.size()]); } public String[] getAllDevicesPath() { Log.i("chw", "SerialPortFinder ---> getAllDevicesPath"); Vector<String> devices = new Vector<String>(); // Parse each driver Iterator<Driver> itdriv; try { itdriv = getDrivers().iterator(); while(itdriv.hasNext()) { Driver driver = itdriv.next(); Iterator<File> itdev = driver.getDevices().iterator(); while(itdev.hasNext()) { String device = itdev.next().getAbsolutePath(); devices.add(device); } } } catch (IOException e) { e.printStackTrace(); } return devices.toArray(new String[devices.size()]); } }