1

我正在将一个 linux 应用程序移植到在 beagle 板上运行的 android 上。

我的应用程序必须访问串行端口(发送/接收)。是否可以使用应用程序读取/写入串行端口,除非 android 是“root”的?

4

2 回答 2

2

检查此页面:http ://code.google.com/p/android-serialport-api/

如果我正确理解了您的问题,这应该是您要查找的内容。

希望我有所帮助。

于 2010-07-13T09:12:04.433 回答
0

我为 Android 编写了一个SerialPortChannel类。它使用JNA

// Copyright 2015 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
// www.source-code.biz, www.inventec.ch/chdh
//
// This module is multi-licensed and may be used under the terms of any of the following licenses:
//
//  LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html
//  EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal
//
// Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind.
//
// Home page: http://www.source-code.biz/snippets/java/SerialPortChannel

package biz.source_code.utils;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.LastErrorException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;

/**
* A serial port channel for Android.
*
* <p>This class uses JNA to access a serial port device (TTY) of the Android operating system.
*/
public class SerialPortChannel implements ByteChannel {

private boolean            isOpen;
private int                fileHandle;
private FileDescriptor     fileDescriptor;
private FileInputStream    rxStream;
private FileOutputStream   txStream;
private FileChannel        rxChannel;
private FileChannel        txChannel;

/**
* Creates a serial port channel.
*
* @param fileName
*   The file name of the serial port device, e.g. "/dev/ttyO2".
* @param baudRate
*   The baud rate for the serial port, e.g. 9600.
* @param blocking
*   <code>true</code> for blocking i/o or <code>false</code> for non-blocking i/o.
*/
public SerialPortChannel (String fileName, int baudRate, boolean blocking) throws IOException {
   staticInit();
   try {
      open(fileName, baudRate, blocking); }
    finally {
      if (!isOpen) {
         close2(); }}}

private void open (String fileName, int baudRate, boolean blocking) throws IOException {
   int mode = LibcDefs.O_RDWR | (blocking ? 0 : LibcDefs.O_NONBLOCK);
   fileHandle = libc.open(fileName, mode);
   fileDescriptor = createFileDescriptor(fileHandle);
   configureSerialPort(baudRate);
   rxStream = new FileInputStream(fileDescriptor);
   txStream = new FileOutputStream(fileDescriptor);
   rxChannel = rxStream.getChannel();
   txChannel = txStream.getChannel();
   isOpen = true; }

private void configureSerialPort (int baudRate) throws IOException {
   termios cfg = new termios();
   LibcDefs.tcgetattr(fileHandle, cfg);
   LibcDefs.cfmakeraw(cfg);
   int baudRateCode = encodeBaudRate(baudRate);
   LibcDefs.cfsetospeed(cfg, baudRateCode);
   LibcDefs.tcsetattr(fileHandle, cfg); }

@Override public boolean isOpen() {
   return isOpen; }

@Override public void close() throws IOException {
   if (!isOpen) {
      return; }
   isOpen = false;
   close2(); }

private void close2() throws IOException {
   if (fileHandle != 0) {
      libc.close(fileHandle); }
   if (rxStream != null) {
      rxStream.close(); }
   if (txStream != null) {
      txStream.close(); }}

@Override public int read (ByteBuffer buf) throws IOException {
   return rxChannel.read(buf); }

public int read (byte[] buf) throws IOException {
   return read(ByteBuffer.wrap(buf)); }

@Override public int write (ByteBuffer buf) throws IOException {
   return txChannel.write(buf); }

public int write (byte[] buf, int pos, int len) throws IOException {
   return write(ByteBuffer.wrap(buf, pos, len)); }

public int write (byte[] buf) throws IOException {
   return write(buf, 0, buf.length); }

private static int encodeBaudRate (int baudRate) {
   switch (baudRate) {
      case 0:       return 0000000;
      case 50:      return 0000001;
      case 75:      return 0000002;
      case 110:     return 0000003;
      case 134:     return 0000004;
      case 150:     return 0000005;
      case 200:     return 0000006;
      case 300:     return 0000007;
      case 600:     return 0000010;
      case 1200:    return 0000011;
      case 1800:    return 0000012;
      case 2400:    return 0000013;
      case 4800:    return 0000014;
      case 9600:    return 0000015;
      case 19200:   return 0000016;
      case 38400:   return 0000017;
      case 57600:   return 0010001;
      case 115200:  return 0010002;
      case 230400:  return 0010003;
      case 460800:  return 0010004;
      case 500000:  return 0010005;
      case 576000:  return 0010006;
      case 921600:  return 0010007;
      case 1000000: return 0010010;
      case 1152000: return 0010011;
      case 1500000: return 0010012;
      case 2000000: return 0010013;
      case 2500000: return 0010014;
      case 3000000: return 0010015;
      case 3500000: return 0010016;
      case 4000000: return 0010017;
      default: throw new IllegalArgumentException("Unsupported baud rate " + baudRate + "."); }}

//------------------------------------------------------------------------------

private static Libc     libc;
private static Method   fileDescriptorSetInt;
private static boolean  staticInitDone;

private static interface Libc extends Library {

   // fcntl.h
   int open(String path, int mode) throws LastErrorException;

   // unistd.h
   int close(int fileHandle) throws LastErrorException;
   int ioctl(int fileHandle, int request, Pointer p) throws LastErrorException; }

private static class LibcDefs {

   // fcntl.h
   static final int O_RDWR     = 00000002;
   static final int O_NONBLOCK = 00004000;

   // ioctls.h
   static final int TCGETS = 0x5401;                       // for ARM and X86, Mips is 0x540d
   static final int TCSETS = 0x5402;

   // termios.h
   static final int IGNBRK = 0000001;
   static final int BRKINT = 0000002;
   static final int PARMRK = 0000010;
   static final int ISTRIP = 0000040;
   static final int INLCR  = 0000100;
   static final int IGNCR  = 0000200;
   static final int ICRNL  = 0000400;
   static final int IXON   = 0002000;
   static final int OPOST  = 0000001;
   static final int ISIG   = 0000001;
   static final int ICANON = 0000002;
   static final int ECHO   = 0000010;
   static final int ECHONL = 0000100;
   static final int IEXTEN = 0100000;
   static final int CBAUD  = 0010017;
   static final int CSIZE  = 0000060;
   static final int PARENB = 0000400;
   static final int CS8    = 0000060;
   private static void tcgetattr (int fileHandle, termios cfg) throws IOException {
      if (libc.ioctl(fileHandle, TCGETS, cfg.getPointer()) != 0) {
         throw new IOException("tcgetattr failed."); }
      cfg.read(); }
   private static void tcsetattr (int fileHandle, termios cfg) throws IOException {
      cfg.write();
      if (libc.ioctl(fileHandle, TCSETS, cfg.getPointer()) != 0) {
         throw new IOException("tcsetattr failed."); }}
   private static void cfmakeraw (termios cfg) {
      cfg.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
      cfg.c_oflag &= ~OPOST;
      cfg.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
      cfg.c_cflag &= ~(CSIZE|PARENB);
      cfg.c_cflag |= CS8; }
   private static void cfsetospeed (termios cfg, int baudRateCode) {
      cfg.c_cflag = (cfg.c_cflag & ~CBAUD) | (baudRateCode & CBAUD); }}

private static class termios extends Structure {
   public int c_iflag;
   public int c_oflag;
   public int c_cflag;
   public int c_lflag;
   public byte c_line;
   public byte[] c_cc = new byte[32];                      // actual length depends on platform (currently 19 for ARM and X86, 23 for Mips)
   @Override protected List<?> getFieldOrder() {
      return Arrays.asList("c_iflag", "c_oflag", "c_cflag", "c_lflag", "c_line", "c_cc"); }}

private static synchronized void staticInit() {
   if (staticInitDone) {
      return; }
   libc = (Libc)Native.loadLibrary("c", Libc.class);
   try {
      fileDescriptorSetInt = FileDescriptor.class.getDeclaredMethod("setInt$", int.class); }
    catch (Exception e) {
       throw new RuntimeException(e); }
   staticInitDone = true; }

// This method is Android-specific and does not work with the normal Java runtime library.
private static FileDescriptor createFileDescriptor (int fileHandle) {
   FileDescriptor fileDescriptor = new FileDescriptor();
   try {
      fileDescriptorSetInt.invoke(fileDescriptor, fileHandle); }
    catch (Exception e) {
      throw new RuntimeException(e); }
   return fileDescriptor; }

}
于 2015-05-10T19:59:47.503 回答