/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.linux.gpio;
import java.io.IOException;
import org.eclipse.kura.gpio.KuraClosedDeviceException;
import org.eclipse.kura.gpio.KuraGPIODeviceException;
import org.eclipse.kura.gpio.KuraGPIODirection;
import org.eclipse.kura.gpio.KuraGPIOMode;
import org.eclipse.kura.gpio.KuraGPIOPin;
import org.eclipse.kura.gpio.KuraGPIOTrigger;
import org.eclipse.kura.gpio.KuraUnavailableDeviceException;
import org.eclipse.kura.gpio.PinStatusListener;
import jdk.dio.ClosedDeviceException;
import jdk.dio.DeviceConfig;
import jdk.dio.DeviceManager;
import jdk.dio.DeviceNotFoundException;
import jdk.dio.InvalidDeviceConfigException;
import jdk.dio.UnavailableDeviceException;
import jdk.dio.UnsupportedDeviceTypeException;
import jdk.dio.gpio.GPIOPin;
import jdk.dio.gpio.GPIOPinConfig;
import jdk.dio.gpio.PinEvent;
import jdk.dio.gpio.PinListener;
public class JdkDioPin implements KuraGPIOPin {
private GPIOPin thePin;
private final int pinIndex;
private String pinName = null;
private KuraGPIODirection direction = null;
private KuraGPIOMode mode = null;
private KuraGPIOTrigger trigger = null;
PinStatusListener localListener;
public JdkDioPin(int pinIndex) {
super();
this.pinIndex = pinIndex;
}
public JdkDioPin(int pinIndex, String pinName, KuraGPIODirection direction, KuraGPIOMode mode,
KuraGPIOTrigger trigger) {
super();
this.pinIndex = pinIndex;
this.pinName = pinName;
this.direction = direction;
this.mode = mode;
this.trigger = trigger;
}
public static JdkDioPin parseFromProperty(Object key, String property) {
try {
int index = Integer.parseInt((String) key);
String[] tokens = property.split(",");
String name = getValueByToken("name", tokens);
String deviceType = getValueByToken("deviceType", tokens);
if ("gpio.GPIOPin".equals(deviceType.trim())) {
KuraGPIODirection d = parseDirection(getValueByToken("direction", tokens));
KuraGPIOMode m = parseMode(getValueByToken("mode", tokens));
KuraGPIOTrigger t = parseTrigger(getValueByToken("trigger", tokens));
return new JdkDioPin(index, name, d, m, t);
}
} catch (Exception e) {
// Invalid property. Not a GPIO Pin
return null;
}
return null;
}
private static String getValueByToken(String token, String[] tokens) {
try {
for (String e : tokens) {
String[] elements = e.split(":");
if (elements[0].trim().equals(token)) {
return elements[1];
}
}
} catch (Exception e) {
return null;
}
return null;
}
@Override
public void setValue(boolean active) throws KuraClosedDeviceException, KuraUnavailableDeviceException, IOException {
try {
this.thePin.setValue(active);
} catch (UnavailableDeviceException ex) {
throw new KuraUnavailableDeviceException(ex, this.pinName != null ? this.pinName : this.pinIndex);
} catch (ClosedDeviceException ex) {
throw new KuraClosedDeviceException(ex, this.pinName != null ? this.pinName : this.pinIndex);
}
}
@Override
public boolean getValue() throws KuraUnavailableDeviceException, KuraClosedDeviceException, IOException {
try {
return this.thePin.getValue();
} catch (UnavailableDeviceException e) {
throw new KuraUnavailableDeviceException(e, this.pinName != null ? this.pinName : this.pinIndex);
} catch (ClosedDeviceException e) {
throw new KuraClosedDeviceException(e, this.pinName != null ? this.pinName : this.pinIndex);
}
}
@Override
public void addPinStatusListener(PinStatusListener listener) throws KuraClosedDeviceException, IOException {
this.localListener = listener;
try {
this.thePin.setInputListener(this.privateListener);
} catch (ClosedDeviceException e) {
throw new KuraClosedDeviceException(e, this.pinName != null ? this.pinName : this.pinIndex);
}
}
@Override
public void removePinStatusListener(PinStatusListener listener) throws KuraClosedDeviceException, IOException {
this.localListener = null;
try {
this.thePin.setInputListener(null);
} catch (ClosedDeviceException e) {
throw new KuraClosedDeviceException(e, this.pinName != null ? this.pinName : this.pinIndex);
}
}
@Override
public void open() throws KuraGPIODeviceException, KuraUnavailableDeviceException, IOException {
if (this.direction != null) {
GPIOPinConfig config = new GPIOPinConfig(DeviceConfig.DEFAULT, getPinIndex(), getDirectionInternal(),
getModeInternal(), getTriggerInternal(), false);
try {
this.thePin = DeviceManager.open(GPIOPin.class, config);
} catch (InvalidDeviceConfigException e) {
throw new KuraGPIODeviceException(e, getPinIndex());
} catch (UnsupportedDeviceTypeException e) {
throw new KuraGPIODeviceException(e, getPinIndex());
} catch (DeviceNotFoundException e) {
throw new KuraGPIODeviceException(e, getPinIndex());
} catch (UnavailableDeviceException e) {
throw new KuraUnavailableDeviceException(e, getPinIndex());
}
} else {
try {
this.thePin = DeviceManager.open(getPinIndex());
} catch (InvalidDeviceConfigException e) {
throw new KuraGPIODeviceException(e, getPinIndex());
} catch (UnsupportedDeviceTypeException e) {
throw new KuraGPIODeviceException(e, getPinIndex());
} catch (DeviceNotFoundException e) {
throw new KuraGPIODeviceException(e, getPinIndex());
} catch (UnavailableDeviceException e) {
throw new KuraUnavailableDeviceException(e, getPinIndex());
}
}
}
@Override
public void close() throws IOException {
if (this.localListener != null) {
try {
removePinStatusListener(this.localListener);
} catch (Exception ex) {
// Do nothing
}
}
if (this.thePin != null && this.thePin.isOpen()) {
this.thePin.close();
}
}
private final PinListener privateListener = new PinListener() {
@Override
public void valueChanged(PinEvent pinEvent) {
if (JdkDioPin.this.localListener != null) {
JdkDioPin.this.localListener.pinStatusChange(pinEvent.getValue());
}
}
};
private int getPinIndex() {
return this.pinIndex;
}
private int getDirectionInternal() {
switch (this.direction) {
case INPUT:
return GPIOPinConfig.DIR_INPUT_ONLY;
case OUTPUT:
return GPIOPinConfig.DIR_OUTPUT_ONLY;
default:
return -1;
}
}
private static KuraGPIODirection parseDirection(String d) {
try {
switch (Integer.decode(d)) {
case GPIOPinConfig.DIR_BOTH_INIT_INPUT:
case GPIOPinConfig.DIR_INPUT_ONLY:
return KuraGPIODirection.INPUT;
case GPIOPinConfig.DIR_BOTH_INIT_OUTPUT:
case GPIOPinConfig.DIR_OUTPUT_ONLY:
return KuraGPIODirection.OUTPUT;
default:
return KuraGPIODirection.OUTPUT;
}
} catch (Exception e) {
}
return KuraGPIODirection.OUTPUT;
}
private static KuraGPIOMode parseMode(String m) {
try {
switch (Integer.decode(m)) {
case GPIOPinConfig.MODE_INPUT_PULL_DOWN:
return KuraGPIOMode.INPUT_PULL_DOWN;
case GPIOPinConfig.MODE_INPUT_PULL_UP:
return KuraGPIOMode.INPUT_PULL_UP;
case GPIOPinConfig.MODE_OUTPUT_OPEN_DRAIN:
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
case GPIOPinConfig.MODE_OUTPUT_PUSH_PULL:
return KuraGPIOMode.OUTPUT_PUSH_PULL;
default:
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
}
} catch (Exception e) {
}
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
}
private static KuraGPIOTrigger parseTrigger(String t) {
try {
switch (Integer.decode(t)) {
case GPIOPinConfig.TRIGGER_BOTH_EDGES:
return KuraGPIOTrigger.BOTH_EDGES;
case GPIOPinConfig.TRIGGER_BOTH_LEVELS:
return KuraGPIOTrigger.BOTH_LEVELS;
case GPIOPinConfig.TRIGGER_FALLING_EDGE:
return KuraGPIOTrigger.FALLING_EDGE;
case GPIOPinConfig.TRIGGER_HIGH_LEVEL:
return KuraGPIOTrigger.HIGH_LEVEL;
case GPIOPinConfig.TRIGGER_LOW_LEVEL:
return KuraGPIOTrigger.LOW_LEVEL;
case GPIOPinConfig.TRIGGER_NONE:
return KuraGPIOTrigger.NONE;
case GPIOPinConfig.TRIGGER_RISING_EDGE:
return KuraGPIOTrigger.RAISING_EDGE;
default:
return KuraGPIOTrigger.NONE;
}
} catch (Exception e) {
}
return KuraGPIOTrigger.NONE;
}
private int getModeInternal() {
switch (this.mode) {
case INPUT_PULL_DOWN:
return GPIOPinConfig.MODE_INPUT_PULL_DOWN;
case INPUT_PULL_UP:
return GPIOPinConfig.MODE_INPUT_PULL_UP;
case OUTPUT_OPEN_DRAIN:
return GPIOPinConfig.MODE_OUTPUT_OPEN_DRAIN;
case OUTPUT_PUSH_PULL:
return GPIOPinConfig.MODE_OUTPUT_PUSH_PULL;
default:
return -1;
}
}
private int getTriggerInternal() {
switch (this.trigger) {
case BOTH_EDGES:
return GPIOPinConfig.TRIGGER_BOTH_EDGES;
case BOTH_LEVELS:
return GPIOPinConfig.TRIGGER_BOTH_LEVELS;
case FALLING_EDGE:
return GPIOPinConfig.TRIGGER_FALLING_EDGE;
case HIGH_LEVEL:
return GPIOPinConfig.TRIGGER_HIGH_LEVEL;
case LOW_LEVEL:
return GPIOPinConfig.TRIGGER_LOW_LEVEL;
case NONE:
return GPIOPinConfig.TRIGGER_NONE;
case RAISING_EDGE:
return GPIOPinConfig.TRIGGER_RISING_EDGE;
default:
return -1;
}
}
@Override
public KuraGPIODirection getDirection() {
return this.direction;
}
@Override
public KuraGPIOMode getMode() {
return this.mode;
}
@Override
public KuraGPIOTrigger getTrigger() {
return this.trigger;
}
@Override
public String getName() {
return this.pinName != null ? this.pinName : String.valueOf(this.pinIndex);
}
@Override
public int getIndex() {
return this.pinIndex;
}
@Override
public boolean isOpen() {
return this.thePin != null ? this.thePin.isOpen() : false;
}
@Override
public String toString() {
return "JdkDioPin [pinIndex=" + this.pinIndex + ", pinName=" + this.pinName + "]";
}
}