/* Copyright (c) The Processing Foundation 2015 Hardware 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 #include #include #include #include #include #include #include #include #include #include #include #include #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; }