代码之家  ›  专栏  ›  技术社区  ›  Dhanesh

Android Beagleboard串口编程

  •  1
  • Dhanesh  · 技术社区  · 16 年前

    我的应用程序必须访问串行端口(send/recv)。 是否可以使用应用程序读/写serialport,除非android是“root”版本?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Tim Cooper    14 年前

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

    如果我正确理解你的问题,这应该是你想要的。

        2
  •  0
  •   Christian d'Heureuse    11 年前

    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; }
    
    }