Skip to content

Commit

Permalink
Add I/O library for Raspberry Pi and similar Linux-based micro computers
Browse files Browse the repository at this point in the history
  • Loading branch information
gohai committed Oct 11, 2015
1 parent 68397e8 commit 5643287
Show file tree
Hide file tree
Showing 16 changed files with 1,827 additions and 0 deletions.
32 changes: 32 additions & 0 deletions java/libraries/io/build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<project name="Processing I/O Library" default="build">

<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="library/io.jar" />
</target>

<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../../../core/library/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />

<mkdir dir="bin" />
<javac source="1.7"
target="1.7"
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../../../core/library/core.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
../../mode/jdtCompilerAdapter.jar" />
</javac>
</target>

<target name="build" depends="compile" description="Build I/O library">
<jar basedir="bin" destfile="library/io.jar" />
</target>
</project>
2 changes: 2 additions & 0 deletions java/libraries/io/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name = I/O
version = 1
1 change: 1 addition & 0 deletions java/libraries/io/library/export.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = I/O for Raspberry Pi and other Linux-based computers
Binary file not shown.
Binary file not shown.
Binary file not shown.
17 changes: 17 additions & 0 deletions java/libraries/io/src/native/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
TARGET := libprocessing-io.so
OBJS := impl.o
CC := gcc

CFLAGS := -std=c99 -fPIC -g
CFLAGS += -I$(shell dirname $(shell realpath $(shell which javac)))/../include
CFLAGS += -I$(shell dirname $(shell realpath $(shell which javac)))/../include/linux
LDFLAGS := -shared

$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@

iface.h:
javah -classpath .. -o iface.h processing.io.NativeInterface

clean:
rm -f $(TARGET) $(OBJS)
85 changes: 85 additions & 0 deletions java/libraries/io/src/native/iface.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

241 changes: 241 additions & 0 deletions java/libraries/io/src/native/impl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/*
Copyright (c) The Processing Foundation 2015
I/O library developed by Gottfried Haider as part of GSOC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/

#include <errno.h>
#include <fcntl.h>
#include <jni.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/spi/spidev.h>
#include <poll.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <unistd.h>
#include "iface.h"


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_openDevice
(JNIEnv *env, jclass cls, jstring _fn)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_RDWR);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
} else {
return file;
}
}


JNIEXPORT jstring JNICALL Java_processing_io_NativeInterface_getError
(JNIEnv *env, jclass cls, jint _errno)
{
char *msg = strerror(abs(_errno));
if (msg) {
return (*env)->NewStringUTF(env, msg);
} else {
return NULL;
}
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_closeDevice
(JNIEnv *env, jclass cls, jint handle)
{
if (close(handle) < 0) {
return -errno;
} else {
return 0;
}
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_readFile
(JNIEnv *env, jclass cls, jstring _fn, jbyteArray _in)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_RDONLY);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
}

jbyte *in = (*env)->GetByteArrayElements(env, _in, NULL);
int len = read(file, in, (*env)->GetArrayLength(env, _in));
if (len < 0) {
len = -errno;
}
(*env)->ReleaseByteArrayElements(env, _in, in, 0);

close(file);
return len;
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_writeFile
(JNIEnv *env, jclass cls, jstring _fn, jbyteArray _out)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_WRONLY);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
}

jbyte *out = (*env)->GetByteArrayElements(env, _out, JNI_FALSE);
int len = write(file, out, (*env)->GetArrayLength(env, _out));
if (len < 0) {
len = -errno;
}
(*env)->ReleaseByteArrayElements(env, _out, out, JNI_ABORT);

close(file);
return len;
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_pollDevice
(JNIEnv *env, jclass cls, jstring _fn, jint timeout)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_RDONLY|O_NONBLOCK);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
}

// dummy read
char tmp;
while (0 < read(file, &tmp, 1));

struct pollfd fds[1];
memset(fds, 0, sizeof(fds));
fds[0].fd = file;
fds[0].events = POLLPRI|POLLERR;

// and wait
int ret = poll(fds, 1, timeout);
close(file);

if (ret < 0) {
return -errno;
} else if (ret == 0) {
// timeout
return 0;
} else if (fds[0].revents & POLLPRI) {
// interrupt
return 1;
} else {
// POLLERR?
return -ENOMSG;
}
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_transferI2c
(JNIEnv *env, jclass cls, jint handle, jint slave, jbyteArray _out, jbyteArray _in)
{
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg msgs[2];
jbyte *out, *in;

packets.msgs = msgs;

msgs[0].addr = slave;
msgs[0].flags = 0;
msgs[0].len = (*env)->GetArrayLength(env, _out);
out = (*env)->GetByteArrayElements(env, _out, NULL);
msgs[0].buf = out;
if (_in != NULL) {
in = (*env)->GetByteArrayElements(env, _in, NULL);
msgs[1].addr = slave;
msgs[1].flags = I2C_M_RD; // I2C_M_RECV_LEN is not supported
msgs[1].len = (*env)->GetArrayLength(env, _in);
msgs[1].buf = in;
packets.nmsgs = 2;
} else {
packets.nmsgs = 1;
}

int ret = ioctl(handle, I2C_RDWR, &packets);
if (ret < 0) {
ret = -errno;
}

(*env)->ReleaseByteArrayElements(env, _out, out, JNI_ABORT);
if (_in != NULL) {
(*env)->ReleaseByteArrayElements(env, _in, in, 0);
}

return ret;
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_setSpiSettings
(JNIEnv *env, jclass cls, jint handle, jint _maxSpeed, jint dataOrder, jint mode)
{
uint8_t tmp;
uint32_t maxSpeed;

tmp = (uint8_t)mode;
int ret = ioctl(handle, SPI_IOC_WR_MODE, &tmp);
if (ret < 0) {
return ret;
}

tmp = (uint8_t)dataOrder;
ret = ioctl(handle, SPI_IOC_WR_LSB_FIRST, &tmp);
if (ret < 0) {
return ret;
}

maxSpeed = (uint32_t)_maxSpeed;
ret = ioctl(handle, SPI_IOC_WR_MAX_SPEED_HZ, &maxSpeed);
if (ret < 0) {
return ret;
}

return 0;
}


JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_transferSpi
(JNIEnv *env, jclass cls, jint handle, jbyteArray _out, jbyteArray _in)
{
jbyte* out = (*env)->GetByteArrayElements(env, _out, NULL);
jbyte* in = (*env)->GetByteArrayElements(env, _in, NULL);

struct spi_ioc_transfer xfer = {
.tx_buf = (unsigned long)out,
.rx_buf = (unsigned long)in,
.len = MIN((*env)->GetArrayLength(env, _out), (*env)->GetArrayLength(env, _in)),
};

int ret = ioctl(handle, SPI_IOC_MESSAGE(1), &xfer);

(*env)->ReleaseByteArrayElements(env, _out, out, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, _in, in, 0);

return ret;
}
Loading

0 comments on commit 5643287

Please sign in to comment.