Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2011, Kustaa Nyholm / SpareTimeLabs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
* contributors may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
package jtermios.linux;
import com.sun.jna.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import jtermios.JTermios;
import jtermios.Pollfd;
import jtermios.Termios;
import jtermios.TimeVal;
import static jtermios.JTermios.*;
import static jtermios.JTermios.JTermiosLogging.log;
public class JTermiosImpl implements jtermios.JTermios.JTermiosInterface {
private static String DEVICE_DIR_PATH = "/dev/";
static C_lib_DirectMapping m_ClibDM;
static C_lib m_Clib;
static NonDirectCLib m_ClibND;
static {
m_ClibND = (NonDirectCLib) Native.loadLibrary(Platform.C_LIBRARY_NAME, NonDirectCLib.class);
Native.register(C_lib_DirectMapping.class, NativeLibrary.getInstance(Platform.C_LIBRARY_NAME));
m_ClibDM = new C_lib_DirectMapping();
m_Clib = m_ClibDM;
}
private final static int TIOCGSERIAL = 0x0000541E;
private final static int TIOCSSERIAL = 0x0000541F;
private final static int ASYNC_SPD_MASK = 0x00001030;
private final static int ASYNC_SPD_CUST = 0x00000030;
private final static int[] m_BaudRates
= { //
50, 0000001, //
75, 0000002, //
110, 0000003, //
134, 0000004, //
150, 0000005, //
200, 0000006, //
300, 0000007, //
600, 0000010, //
1200, 0000011, //
1800, 0000012, //
2400, 0000013, //
4800, 0000014, //
9600, 0000015, //
19200, 0000016, //
38400, 0000017, //
57600, 0010001, //
115200, 0010002, //
230400, 0010003, //
460800, 0010004, //
500000, 0010005, //
576000, 0010006, //
921600, 0010007, //
1000000, 0010010, //
1152000, 0010011, //
1500000, 0010012, //
2000000, 0010013, //
2500000, 0010014, //
3000000, 0010015, //
3500000, 0010016, //
4000000, 0010017 //
};
public static class C_lib_DirectMapping implements C_lib {
native public int pipe(int[] fds);
native public int tcdrain(int fd);
native public void cfmakeraw(termios termios);
native public int fcntl(int fd, int cmd, int arg);
native public int ioctl(int fd, int cmd, int[] arg);
native public int ioctl(int fd, int cmd, serial_struct arg);
native public int open(String path, int flags);
native public int close(int fd);
native public int tcgetattr(int fd, termios termios);
native public int tcsetattr(int fd, int cmd, termios termios);
native public int cfsetispeed(termios termios, int i);
native public int cfsetospeed(termios termios, int i);
native public int cfgetispeed(termios termios);
native public int cfgetospeed(termios termios);
native public NativeSize write(int fd, byte[] buffer, NativeSize count);
native public NativeSize read(int fd, byte[] buffer, NativeSize count);
native public int tcflush(int fd, int qs);
native public void perror(String msg);
native public int tcsendbreak(int fd, int duration);
}
public interface C_lib extends com.sun.jna.Library {
public int pipe(int[] fds);
public int tcdrain(int fd);
public void cfmakeraw(termios termios);
public int fcntl(int fd, int cmd, int arg);
public int ioctl(int fd, int cmd, int[] arg);
public int ioctl(int fd, int cmd, serial_struct arg);
public int open(String path, int flags);
public int close(int fd);
public int tcgetattr(int fd, termios termios);
public int tcsetattr(int fd, int cmd, termios termios);
public int cfsetispeed(termios termios, int i);
public int cfsetospeed(termios termios, int i);
public int cfgetispeed(termios termios);
public int cfgetospeed(termios termios);
public NativeSize write(int fd, byte[] buffer, NativeSize count);
public NativeSize read(int fd, byte[] buffer, NativeSize count);
public int tcflush(int fd, int qs);
public void perror(String msg);
public int tcsendbreak(int fd, int duration);
}
public interface NonDirectCLib extends com.sun.jna.Library {
public int select(int n, fd_set read, fd_set write, fd_set error, timeval timeout);
public int poll(pollfd.ByReference pfds, int nfds, int timeout);
}
static public class timeval extends Structure {
public NativeLong tv_sec;
public NativeLong tv_usec;
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"tv_sec",//
"tv_usec"//
);
}
public timeval(jtermios.TimeVal timeout) {
tv_sec = new NativeLong(timeout.tv_sec);
tv_usec = new NativeLong(timeout.tv_usec);
}
}
static public class pollfd extends Structure {
public static class ByReference extends pollfd implements Structure.ByReference {
}
public int fd;
public short events;
public short revents;
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"fd",//
"events",//
"revents"//
);
}
public pollfd() {
}
public pollfd(Pollfd pfd) {
fd = pfd.fd;
events = pfd.events;
revents = pfd.revents;
}
}
static public class fd_set extends Structure implements FDSet {
private final static int NFBBITS = NativeLong.SIZE * 8;
private final static int fd_count = 1024;
public NativeLong[] fd_array = new NativeLong[(fd_count + NFBBITS - 1) / NFBBITS];
public fd_set() {
for (int i = 0; i < fd_array.length; ++i) {
fd_array[i] = new NativeLong();
}
}
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"fd_array"//
);
}
public void FD_SET(int fd) {
fd_array[fd / NFBBITS].setValue(fd_array[fd / NFBBITS].longValue() | (1L << (fd % NFBBITS)));
}
public boolean FD_ISSET(int fd) {
return (fd_array[fd / NFBBITS].longValue() & (1L << (fd % NFBBITS))) != 0;
}
public void FD_ZERO() {
for (NativeLong fd : fd_array) {
fd.setValue(0L);
}
}
public void FD_CLR(int fd) {
fd_array[fd / NFBBITS].setValue(fd_array[fd / NFBBITS].longValue() & ~(1L << (fd % NFBBITS)));
}
}
public static class serial_struct extends Structure {
public int type;
public int line;
public int port;
public int irq;
public int flags;
public int xmit_fifo_size;
public int custom_divisor;
public int baud_base;
public short close_delay;
public short io_type;
//public char io_type;
//public char reserved_char;
public int hub6;
public short closing_wait;
public short closing_wait2;
public Pointer iomem_base;
public short iomem_reg_shift;
public int port_high;
public NativeLong iomap_base;
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"type",//
"line",//
"port",//
"irq",//
"flags",//
"xmit_fifo_size",//
"custom_divisor",//
"baud_base",//
"close_delay",//
"io_type",//
//public char io_type;
//public char reserved_char;
"hub6",//
"closing_wait",//
"closing_wait2",//
"iomem_base",//
"iomem_reg_shift",//
"port_high",//
"iomap_base"//
);
}
};
static public 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];
public int c_ispeed;
public int c_ospeed;
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"c_iflag",//
"c_oflag",//
"c_cflag",//
"c_lflag",//
"c_line",//
"c_cc",//
"c_ispeed",//
"c_ospeed"//
);
}
public termios() {
}
public termios(jtermios.Termios t) {
c_iflag = t.c_iflag;
c_oflag = t.c_oflag;
c_cflag = t.c_cflag;
c_lflag = t.c_lflag;
System.arraycopy(t.c_cc, 0, c_cc, 0, t.c_cc.length);
c_ispeed = t.c_ispeed;
c_ospeed = t.c_ospeed;
}
public void update(jtermios.Termios t) {
t.c_iflag = c_iflag;
t.c_oflag = c_oflag;
t.c_cflag = c_cflag;
t.c_lflag = c_lflag;
System.arraycopy(c_cc, 0, t.c_cc, 0, t.c_cc.length);
t.c_ispeed = c_ispeed;
t.c_ospeed = c_ospeed;
}
}
public JTermiosImpl() {
log = log && log(1, "instantiating %s\n", getClass().getCanonicalName());
//linux/serial.h stuff
FIONREAD = 0x541B; // Looked up manually
//fcntl.h stuff
O_RDWR = 0x00000002;
O_NONBLOCK = 0x00000800;
O_NOCTTY = 0x00000100;
O_NDELAY = 0x00000800;
F_GETFL = 0x00000003;
F_SETFL = 0x00000004;
//errno.h stuff
EAGAIN = 11;
EACCES = 13;
EEXIST = 17;
EINTR = 4;
EINVAL = 22;
EIO = 5;
EISDIR = 21;
ELOOP = 40;
EMFILE = 24;
ENAMETOOLONG = 36;
ENFILE = 23;
ENOENT = 2;
ENOSR = 63;
ENOSPC = 28;
ENOTDIR = 20;
ENXIO = 6;
EOVERFLOW = 75;
EROFS = 30;
ENOTSUP = 95;
//termios.h stuff
TIOCM_RNG = 0x00000080;
TIOCM_CAR = 0x00000040;
IGNBRK = 0x00000001;
BRKINT = 0x00000002;
IGNPAR = 0x00000004;
PARMRK = 0x00000008;
INLCR = 0x00000040;
IGNCR = 0x00000080;
ICRNL = 0x00000100;
ECHONL = 0x00000040;
IEXTEN = 0x00008000;
CLOCAL = 0x00000800;
OPOST = 0x00000001;
VSTART = 0x00000008;
TCSANOW = 0x00000000;
VSTOP = 0x00000009;
VMIN = 0x00000006;
VTIME = 0x00000005;
VEOF = 0x00000004;
TIOCMGET = 0x00005415;
TIOCM_CTS = 0x00000020;
TIOCM_DSR = 0x00000100;
TIOCM_RI = 0x00000080;
TIOCM_CD = 0x00000040;
TIOCM_DTR = 0x00000002;
TIOCM_RTS = 0x00000004;
ICANON = 0x00000002;
ECHO = 0x00000008;
ECHOE = 0x00000010;
ISIG = 0x00000001;
TIOCMSET = 0x00005418;
IXON = 0x00000400;
IXOFF = 0x00001000;
IXANY = 0x00000800;
CRTSCTS = 0x80000000;
TCSADRAIN = 0x00000001;
INPCK = 0x00000010;
ISTRIP = 0x00000020;
CSIZE = 0x00000030;
TCIFLUSH = 0x00000000;
TCOFLUSH = 0x00000001;
TCIOFLUSH = 0x00000002;
CS5 = 0x00000000;
CS6 = 0x00000010;
CS7 = 0x00000020;
CS8 = 0x00000030;
CSTOPB = 0x00000040;
CREAD = 0x00000080;
PARENB = 0x00000100;
PARODD = 0x00000200;
B0 = 0;
B50 = 1;
B75 = 2;
B110 = 3;
B134 = 4;
B150 = 5;
B200 = 6;
B300 = 7;
B600 = 8;
B1200 = 9;
B1800 = 10;
B2400 = 11;
B4800 = 12;
B9600 = 13;
B19200 = 14;
B38400 = 15;
B57600 = 4097;
B115200 = 4098;
B230400 = 4099;
//poll.h stuff
POLLIN = 0x0001;
POLLPRI = 0x0002;
POLLOUT = 0x0004;
POLLERR = 0x0008;
POLLNVAL = 0x0020;
}
public int errno() {
return Native.getLastError();
}
public void cfmakeraw(Termios termios) {
termios t = new termios(termios);
m_Clib.cfmakeraw(t);
t.update(termios);
}
public int fcntl(int fd, int cmd, int arg) {
return m_Clib.fcntl(fd, cmd, arg);
}
public int tcdrain(int fd) {
return m_Clib.tcdrain(fd);
}
public int cfgetispeed(Termios termios) {
return m_Clib.cfgetispeed(new termios(termios));
}
public int cfgetospeed(Termios termios) {
return m_Clib.cfgetospeed(new termios(termios));
}
public int cfsetispeed(Termios termios, int speed) {
termios t = new termios(termios);
int ret = m_Clib.cfsetispeed(t, speed);
t.update(termios);
return ret;
}
public int cfsetospeed(Termios termios, int speed) {
termios t = new termios(termios);
int ret = m_Clib.cfsetospeed(t, speed);
t.update(termios);
return ret;
}
public int open(String s, int t) {
if (s != null && !s.startsWith("/")) {
s = DEVICE_DIR_PATH + s;
}
return m_Clib.open(s, t);
}
public int read(int fd, byte[] buffer, int len) {
return m_Clib.read(fd, buffer, new NativeSize(len)).intValue();
}
public int write(int fd, byte[] buffer, int len) {
return m_Clib.write(fd, buffer, new NativeSize(len)).intValue();
}
public int close(int fd) {
return m_Clib.close(fd);
}
public int tcflush(int fd, int b) {
return m_Clib.tcflush(fd, b);
}
public int tcgetattr(int fd, Termios termios) {
termios t = new termios();
int ret = m_Clib.tcgetattr(fd, t);
t.update(termios);
return ret;
}
public void perror(String msg) {
m_Clib.perror(msg);
}
public int tcsendbreak(int fd, int duration) {
// If duration is not zero, it sends zero-valued bits for duration*N seconds,
// where N is at least 0.25, and not more than 0.5.
return m_Clib.tcsendbreak(fd, duration / 250);
}
public int tcsetattr(int fd, int cmd, Termios termios) {
return m_Clib.tcsetattr(fd, cmd, new termios(termios));
}
public int select(int nfds, FDSet rfds, FDSet wfds, FDSet efds, TimeVal timeout) {
timeval tout = null;
if (timeout != null) {
tout = new timeval(timeout);
}
return m_ClibND.select(nfds, (fd_set) rfds, (fd_set) wfds, (fd_set) efds, tout);
}
public int poll(Pollfd fds[], int nfds, int timeout) {
if (nfds <= 0 || nfds > fds.length) {
throw new java.lang.IllegalArgumentException("nfds " + nfds + " must be <= fds.length " + fds.length);
}
pollfd.ByReference parampfds = new pollfd.ByReference();
pollfd[] pfds = (pollfd[]) parampfds.toArray(nfds);
for (int i = 0; i < nfds; i++) {
pfds[i].fd = fds[i].fd;
pfds[i].events = fds[i].events;
}
int ret = m_ClibND.poll(parampfds, nfds, timeout);
for (int i = 0; i < nfds; i++) {
fds[i].revents = pfds[i].revents;
}
return ret;
}
public boolean canPoll() {
return true;
}
public FDSet newFDSet() {
return new fd_set();
}
public int ioctl(int fd, int cmd, int... data) {
return m_Clib.ioctl(fd, cmd, data);
}
// This ioctl is Linux specific, so keep it private for now
private int ioctl(int fd, int cmd, serial_struct data) {
// Do the logging here as this does not go through the JTermios which normally does the logging
log = log && log(5, "> ioctl(%d,%d,%s)\n", fd, cmd, data);
int ret = m_Clib.ioctl(fd, cmd, data);
log = log && log(3, "< tcsetattr(%d,%d,%s) => %d\n", fd, cmd, data, ret);
return ret;
}
public String getPortNamePattern() {
// First we have to determine which serial drivers exist and which
// prefixes they use
final List prefixes = new ArrayList();
try {
BufferedReader drivers = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/tty/drivers"), "US-ASCII"));
String line;
while ((line = drivers.readLine()) != null) {
// /proc/tty/drivers contains the prefix in the second column
// and "serial" in the fifth
String[] parts = line.split(" +");
if (parts.length != 5) {
continue;
}
if (!"serial".equals(parts[4])) {
continue;
}
// Sanity check the prefix
if (!parts[1].startsWith("/dev/")) {
continue;
}
prefixes.add(parts[1].substring(5));
}
drivers.close();
} catch (IOException e) {
log = log && log(1, "failed to read /proc/tty/drivers\n");
prefixes.add("ttyS");
prefixes.add("ttyUSB");
prefixes.add("ttyACM");
}
// Now build the pattern from the known prefixes
StringBuilder pattern = new StringBuilder();
pattern.append('^');
boolean first = true;
for (String prefix : prefixes) {
if (first) {
first = false;
} else {
pattern.append('|');
}
pattern.append("(");
pattern.append(prefix);
pattern.append(".+)");
}
return pattern.toString();
}
public List getPortList() {
File dir = new File(DEVICE_DIR_PATH);
if (!dir.isDirectory()) {
log = log && log(1, "device directory %s does not exist\n", DEVICE_DIR_PATH);
return null;
}
String[] devs = dir.list();
LinkedList list = new LinkedList();
Pattern p = JTermios.getPortNamePattern(this);
if (devs != null) {
for (int i = 0; i < devs.length; i++) {
String s = devs[i];
if (p.matcher(s).matches()) {
list.add(s);
}
}
}
return list;
}
public void shutDown() {
}
public int setspeed(int fd, Termios termios, int speed) {
int c = speed;
int r;
for (int i = 0; i < m_BaudRates.length; i += 2) {
if (m_BaudRates[i] == speed) {
// found the baudrate from the table
// just in case custom divisor was in use, try to turn it off first
serial_struct ss = new serial_struct();
r = ioctl(fd, TIOCGSERIAL, ss);
if (r == 0) {
ss.flags &= ~ASYNC_SPD_MASK;
r = ioctl(fd, TIOCSSERIAL, ss);
}
// now set the speed with the constant from the table
c = m_BaudRates[i + 1];
if ((r = JTermios.cfsetispeed(termios, c)) != 0) {
return r;
}
if ((r = JTermios.cfsetospeed(termios, c)) != 0) {
return r;
}
if ((r = JTermios.tcsetattr(fd, TCSANOW, termios)) != 0) {
return r;
}
return 0;
}
}
// baudrate not defined in the table, try custom divisor approach
// configure port to use custom speed instead of 38400
serial_struct ss = new serial_struct();
if ((r = ioctl(fd, TIOCGSERIAL, ss)) != 0) {
return r;
}
ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
if (speed == 0) {
log = log && log(1, "unable to set custom baudrate %d \n", speed);
return -1;
}
ss.custom_divisor = (ss.baud_base + (speed / 2)) / speed;
if (ss.custom_divisor == 0) {
log = log && log(1, "unable to set custom baudrate %d (possible division by zero)\n", speed);
return -1;
}
int closestSpeed = ss.baud_base / ss.custom_divisor;
if (closestSpeed < speed * 98 / 100 || closestSpeed > speed * 102 / 100) {
log = log && log(1, "best available baudrate %d not close enough to requested %d \n", closestSpeed, speed);
return -1;
}
if ((r = ioctl(fd, TIOCSSERIAL, ss)) != 0) {
return r;
}
if ((r = JTermios.cfsetispeed(termios, B38400)) != 0) {
return r;
}
if ((r = JTermios.cfsetospeed(termios, B38400)) != 0) {
return r;
}
if ((r = JTermios.tcsetattr(fd, TCSANOW, termios)) != 0) {
return r;
}
return 0;
}
public int pipe(int[] fds) {
return m_Clib.pipe(fds);
}
}