📄 modemio.java
字号:
package net.sourceforge.gjtapi.raw.modem;
// NAME
// $RCSfile: ModemIO.java,v $
// DESCRIPTION
// [given below in javadoc format]
// DELTA
// $Revision: 1.3 $
// CREATED
// $Date: 2004/02/21 02:04:07 $
// COPYRIGHT
// Westhawk Ltd
// TO DO
//
import java.io.*;
import java.util.TooManyListenersException;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.comm.*;
/**
* A class which handles all of the IO for a Modem.
*
* This class works with modems connected to serial ports. Perhaps it should
* be an interface and implementation.
*
* @author <a href="mailto:ray@westhawk.co.uk">Ray Tran</a>
* @version $Revision: 1.3 $ $Date: 2004/02/21 02:04:07 $
*/
public class ModemIO implements SerialPortEventListener{
private static final String version_id =
"@(#)$Id: ModemIO.java,v 1.3 2004/02/21 02:04:07 rdeadman Exp $ Copyright Westhawk Ltd";
public static final int DLE = 0x10;
public static final int ETX = 0x03;
public static final int CR = 0x0c;
public static final int LF = 0x0a;
private static final int BUF_SIZE = 65536;
private static final int MARK_INVALID = -1;
public static final int TIMEOUT = -1;
public static final int GOOD_MATCH = 0;
public static final int BAD_MATCH = 1;
private SerialPort port = null;
private InputStream in;
private PrintStream out;
private byte[] buf;
private int writePos, readPos;
private int markPos = MARK_INVALID;
private int limit = MARK_INVALID;
private int limitCount;
private String lastMatch ="";
private ShieldHandler handler;
private Modem modem;
/**
* Constructor.
*
* @param portname - Name of SerialPort used for talking to the modem.
* @param modem - Reference back to the modem which we are the IO for
*/
public ModemIO(String portname, Modem modem) {
buf = new byte[BUF_SIZE];
writePos = readPos = 0;
this.modem = modem;
handler = new ShieldHandler();
Thread t = new Thread(handler);
t.start();
//First try to open a port to the modem
try {
CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portname);
port = (SerialPort) portID.open("ModemProvider", 5000);
port.setSerialPortParams(
115200,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE
);
//add ourself as a listener for certain events
port.notifyOnRingIndicator(true);
/*
port.notifyOnDataAvailable(true);
port.notifyOnBreakInterrupt(false);
port.notifyOnCarrierDetect(false);
port.notifyOnCTS(false);
port.notifyOnDSR(false);
port.notifyOnFramingError(false);
port.notifyOnOutputEmpty(false);
port.notifyOnOverrunError(false);
port.notifyOnParityError(false);
*/
port.addEventListener(this);
}catch (TooManyListenersException ex) {
System.err.println("Adding event listener to port (" +
portname + ") failed");
}catch (Exception ex) {
System.err.println("Can't open serial port (" + portname);
ex.printStackTrace();
}
if (port != null){
try{
port.enableReceiveTimeout(1000);
}catch (UnsupportedCommOperationException ex){
System.err.println("Can't set timeout on port(" + portname + ")");
}
try{
in = port.getInputStream();
out = new PrintStream(port.getOutputStream());
}catch (IOException ex){
System.err.println("IOException in ModemIO(" + port.getName() + ")");
ex.printStackTrace();
}
}
}
/**
* Try to read bytes into the circular buffer until the buffer is full, or
* no more bytes are available from the underlying device.
* If there is space in the buffer then we always try to read
* at least one byte, the read will timeout if nothing is available;
*
* @throws IOException
*/
private void fill() throws IOException{
//Don't bother if the buffer is nearly full
if (this.free() > 32 && in.available() > 0){
do{
int read = in.read();
if (read > -1){
//If we get a <DLE> we need to deal with it
if (read == DLE){
read = in.read();
//If the next char is <DLE> pass it thru otherwise
//handle it (quickly)
if (read != DLE){
if (read == -1){
//this really should NEVER happen!
break;
}
handleDLEShield((char)read);
}
}
buf[writePos++] = (byte)read;
if (writePos >= BUF_SIZE){
writePos = 0;
}
}
}while (in.available() > 0 && this.free() > 0);
}
}
/**
* Deals with <DLE> shielded characters.
* As a character may require time consuming processing a seperate
* thread does it to avoid slowing down the fill() loop.
*
* @param shielded - character read after the <DLE> character
*/
private void handleDLEShield(char shielded){
//System.err.println("<DLE>0x" + Integer.toHexString(shielded));
//Expect <DLE>s when the modem detects silence, <DLE>d when dialtone
handler.setShield(shielded);
}
/**
* Returns the number of bytes available to be read.
*
* @return int - the number of bytes available to be read.
* @see #free()
*/
public int available(){
int result;
if (readPos <= writePos){
result = writePos - readPos;
}else{
result = BUF_SIZE - readPos + writePos;
}
return result;
}
/**
* Returns the number of spaces available to be written in.
*
* @return int - the number of spaces available to be written in.
* @see #available()
*/
private int free(){
int result;
int comparePos = ((markPos == MARK_INVALID)?readPos:markPos);
if (comparePos <= writePos){
result = BUF_SIZE - writePos + comparePos - 1;
}else{
result = comparePos - writePos - 1;
}
return result;
}
/**
* Read the next byte from the buffer, re-filling if required.
*
* @return int - the next byte read from the buffer
* @throws IOException
*/
public int read() throws IOException{
int result = -1;
if (in != null && buf != null){
//if the buffer is nearly empty try to fill it
if (this.available() < 16){
fill();
}
if (readPos != writePos){
result = buf[readPos++] & 0xff;
//If we have read more bytes than readlimit since marking then
//clear the mark;
if (markPos != MARK_INVALID){
if (--limitCount == -1){
markPos = MARK_INVALID;
}
}
if (readPos >= BUF_SIZE){
readPos = 0;
}
}
}
return result;
}
public int read(byte[] data) throws IOException{
int result = 0;
int read;
for (int i=0, len = data.length; i<len; i++){
if ((read = read()) > -1){
data[i] = (byte)read;
}else{
result = i;
break;
}
}
return result;
}
public int read(byte[] data, int offs, int len) throws IOException{
int result = 0;
int read;
int limit = offs + len;
if (limit <= data.length){
for (int i=offs; i<len; i++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -