jtermios.macosx.JTermiosImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of filo-firmata Show documentation
Show all versions of filo-firmata Show documentation
FiloFirmata is a client library for the Firmata protocol used with hardware project boards.
/*
* 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);
}
}