jtermios.macosx.JTermiosImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of purejavacomm Show documentation
Show all versions of purejavacomm Show documentation
PureJavaComm is an Application Programmin Interface (API) for accessing serial ports from Java. PureJavaComm aims to be a drop-in replacement for Sun's (now Oracle) abandoned JavaComm and an easier to deploy alternative to RXTX.
/*
* 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.macosx;
import com.sun.jna.*;
import java.io.File;
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 int IOSSIOSPEED = 0x80045402;
private static String DEVICE_DIR_PATH = "/dev/";
static C_lib_DirectMapping m_ClibDM;
static C_lib m_Clib;
// static NonDirectCLib m_ClibND;
static {
Native.setPreserveLastError(true);
// 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;
}
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, NativeLong cmd);
native public int ioctl(int fd, NativeLong cmd, int arg);
native public int ioctl(int fd, NativeLong cmd, int[] 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, NativeLong i);
native public int cfsetospeed(termios termios, NativeLong i);
native public NativeLong cfgetispeed(termios termios);
native public NativeLong 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);
native public int select(int n, fd_set read, fd_set write, fd_set error, timeval timeout);
}
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, NativeLong cmd, int[] 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, NativeLong i);
public int cfsetospeed(termios termios, NativeLong i);
public NativeLong cfgetispeed(termios termios);
public NativeLong 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 int select(int n, fd_set read, fd_set write, fd_set error, timeval timeout);
}
// public interface NonDirectCLib extends com.sun.jna.Library {
//
// public int ioctl(int fd, NativeLong cmd, NativeLong[] arg);
//
// // 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 = 32;
private final static int fd_count = 1024;
public int[] fd_array = new int[(fd_count + NFBBITS - 1) / NFBBITS];
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"fd_array"//
);
}
public void FD_SET(int fd) {
fd_array[fd / NFBBITS] |= (1 << (fd % NFBBITS));
}
public boolean FD_ISSET(int fd) {
return (fd_array[fd / NFBBITS] & (1 << (fd % NFBBITS))) != 0;
}
public void FD_ZERO() {
Arrays.fill(fd_array, 0);
}
public void FD_CLR(int fd) {
fd_array[fd / NFBBITS] &= ~(1 << (fd % NFBBITS));
}
}
static public class termios extends Structure {
public NativeLong c_iflag;
public NativeLong c_oflag;
public NativeLong c_cflag;
public NativeLong c_lflag;
public byte[] c_cc = new byte[20];
public NativeLong c_ispeed;
public NativeLong c_ospeed;
@Override
protected List getFieldOrder() {
return Arrays.asList(//
"c_iflag",//
"c_oflag",//
"c_cflag",//
"c_lflag",//
"c_cc",//
"c_ispeed",//
"c_ospeed"//
);
}
public termios() {
}
public termios(jtermios.Termios t) {
c_iflag.setValue(t.c_iflag);
c_oflag.setValue(t.c_oflag);
c_cflag.setValue(t.c_cflag);
c_lflag.setValue(t.c_lflag);
System.arraycopy(t.c_cc, 0, c_cc, 0, Math.min(t.c_cc.length, c_cc.length));
c_ispeed.setValue(t.c_ispeed);
c_ospeed.setValue(t.c_ospeed);
}
public void update(jtermios.Termios t) {
t.c_iflag = c_iflag.intValue();
t.c_oflag = c_oflag.intValue();
t.c_cflag = c_cflag.intValue();
t.c_lflag = c_lflag.intValue();
System.arraycopy(c_cc, 0, t.c_cc, 0, Math.min(t.c_cc.length, c_cc.length));
t.c_ispeed = c_ispeed.intValue();
t.c_ospeed = c_ospeed.intValue();
}
}
public JTermiosImpl() {
log = log && log(1, "instantiating %s\n", getClass().getCanonicalName());
}
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)).intValue();
}
public int cfgetospeed(Termios termios) {
return m_Clib.cfgetospeed(new termios(termios)).intValue();
}
public int cfsetispeed(Termios termios, int speed) {
termios t = new termios(termios);
int ret = m_Clib.cfsetispeed(t, new NativeLong(speed));
t.update(termios);
return ret;
}
public int cfsetospeed(Termios termios, int speed) {
termios t = new termios(termios);
int ret = m_Clib.cfsetospeed(t, new NativeLong(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_Clib.select(nfds, (fd_set) rfds, (fd_set) wfds, (fd_set) efds, tout);
}
public int poll(Pollfd fds[], int nfds, int timeout) {
throw new UnsupportedOperationException("Poll not supported");
}
public boolean canPoll() {
return false;
}
public FDSet newFDSet() {
return new fd_set();
}
public int ioctl(int fd, int cmd, int... data) {
// At this time, all ioctl commands we have defined are either no parameter or 4 byte parameter.
return m_Clib.ioctl(fd, new NativeLong(0xFFFFFFFFL & cmd), data);
}
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 String getPortNamePattern() {
return "^(tty\\.|cu\\.).*";
}
public void shutDown() {
}
public int setspeed(int fd, Termios termios, int speed) {
int r;
r = cfsetispeed(termios, speed);
if (r == 0)
r = cfsetospeed(termios, speed);
if (r == 0)
r = tcsetattr(fd, TCSANOW, termios);
if (r != 0) {
// Darell Tan had patched RXTX with this sequence, so lets try this
if (cfsetispeed(termios, B9600) == 0 && cfsetospeed(termios, B9600) == 0 && tcsetattr(fd, TCSANOW, termios) == 0)
r = ioctl(fd, IOSSIOSPEED, speed);
}
return r;
}
public int pipe(int[] fds) {
return m_Clib.pipe(fds);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy