/*
* Copyright (c) 2011 - 2014 United ID.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.unitedid.yhsm.internal;
import jssc.SerialPort;
import jssc.SerialPortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import static org.unitedid.yhsm.utility.Utils.concatAllArrays;
public class DeviceHandler {
/** Logger */
private final Logger log = LoggerFactory.getLogger(DeviceHandler.class);
/** The YubiHSM device */
private SerialPort device;
private int readBytes = 0;
private int writtenBytes = 0;
private float timeout = 0.5f;
/**
* Constructor
*
* @param deviceName the YubiHSM device name
*/
DeviceHandler(String deviceName) throws YubiHSMErrorException {
device = new SerialPort(deviceName);
try {
device.openPort();
device.setParams(
SerialPort.BAUDRATE_115200,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE
);
device.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
} catch (SerialPortException e) {
throw new YubiHSMErrorException("Failed to open device " + deviceName, e);
}
}
public void write(byte[] data) {
try {
writtenBytes += data.length;
device.writeBytes(data);
} catch (SerialPortException e) {
e.printStackTrace();
}
}
public byte[] read(int readNumBytes) {
byte[] data = new byte[readNumBytes];
try {
data = device.readBytes(readNumBytes);
readBytes += data.length;
} catch (SerialPortException e) {
e.printStackTrace();
}
return data;
}
public int available() {
try {
return device.getInputBufferBytesCount();
} catch (SerialPortException e) {
e.printStackTrace();
}
return 0;
}
public boolean drain() {
byte[] buffer = new byte[0];
while(available() > 0) {
byte[] b = read(1);
if ((char)b[0] == '\r') {
log.info("Drained: {}", new String(buffer, 0, buffer.length)); //TODO: Do we really need to log this? If not the loop can be simplified.
buffer = new byte[0];
} else {
buffer = concatAllArrays(buffer, b);
}
}
return true;
}
public void flush() throws IOException {
try {
device.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);
} catch (SerialPortException e) {
e.printStackTrace();
}
}
public float getTimeout() {
return timeout;
}
public void setTimeout(float timeout) {
this.timeout = timeout;
}
public int getReadBytes() {
return readBytes;
}
public int getWrittenBytes() {
return writtenBytes;
}
public String getPortName() {
return device.getPortName();
}
public Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}
protected void finalize() throws Throwable {
try {
device.closePort();
} finally {
super.finalize();
}
}
}