📄 irlmp.java
字号:
/***************************************************************************** $Header: /cvsroot/jred/jred/src/com/synchrona/jred/IrLMP.java,v 1.5 2000/07/30 20:18:12 mpatters Exp $**** Copyright (C) 2000 Synchrona, Inc. All rights reserved.**** This file is part of JRed, a 100% Java implementation of the IrDA** infrared communications protocols.**** This file may be distributed under the terms of the Synchrona Public** License as defined by Synchrona, Inc. and appearing in the file** LICENSE included in the packaging of this file. The Synchrona Public** License is based on the Q Public License as defined by Troll Tech AS** of Norway; it differs only in its use of the courts of Florida, USA** rather than those of Oslo, Norway.***************************************************************************/ package com.synchrona.jred;import com.synchrona.jred.iIrLMPService;import com.synchrona.jred.IrIAS;import com.synchrona.jred.IrLMPConnection;import com.synchrona.jred.irlap.ConnectionInformation;import com.synchrona.jred.irlap.DiscoveryInformation;import com.synchrona.jred.irlap.iIrLAPListener;import com.synchrona.jred.irlap.IrLAPContext;import com.synchrona.util.Assert;import com.synchrona.util.Log;import com.synchrona.util.Utilities;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.Vector;import javax.swing.Timer;/**** Implement link management as defined in the IrLMP specification.*/public class IrLMP implements iIrLAPListener { public static final int DEFAULT_AUTO_DISCOVERY_INTERVAL = 300; public static final String AUTO_DISCOVERY_PROPERTY = "IrLMP.autoDiscovery"; public static final String AUTO_DISCOVERY_INTERVAL_PROPERTY = "IrLMP.autoDiscoveryInterval"; private static final byte OPCODE_CONNECT_REQUEST = (byte) 0x01; private static final byte OPCODE_CONNECT_CONFIRM = (byte) 0x81; private int _autoDiscoveryInterval; private Timer _autoDiscoveryTimer; private byte _irlapConnection; private IrLAPContext _irlap; private boolean _doAutoDiscovery; private Log _log; private Vector _services; //---------------------------------------------------------------- // User-level methods. //---------------------------------------------------------------- /** ** */ public IrLMP(Log log) throws Exception{ Assert.fail( log != null, "Log must not be null."); _log = log; _services = new Vector(10); // IAS is required, and serves at LSAP=0 per the IrLMP spec. IrIAS ias = IrIAS.getInstance(); ias.setLog(_log); _services.add(0, ias); configureAutoDiscovery(); } /** ** IrLMP allows multiple service providers (IrOBEX, IrCOMM, etc.) to ** listen to a single IrDA port, although only one service is ** active at a time. This method allows a new service to let IrLMP ** know that it's available. ** <B>This method is broken. It only adds IrOBEX, and does so at ** LSAP 5. This will change when IrIAS is augmented.</B> */ public void addService(iIrLMPService service) { for ( int i = 1; i < _services.capacity(); i++ ) { _services.add(service); } } /** ** Instructs IrLMP to enter a discovery sequence, by which other ** IrDA hosts can be found. */ public void discover() throws Exception { Assert.fail(_irlap != null, "No IrLAP instance."); if ( _irlap.isMediaBusy() ) { _log.debug("IrLMP", "The IrLAP layer is busy now."); } else { _irlap.startDiscovery(); } } /** ** Request a connection with a service on another IrDA host. ** If the request is granted, IrLMP invokes the connect() ** method of the IrLMPService that requested the connection. ** This method cannot be used unless a Host has identified ** itself to us in response to a discovery sequence initiated ** by us, or as a result of our identification to the Host ** during a discovery sequence initiated by the Host. public Connection requestConnection(Host host, int sourceLSAP, int destination LSAP) { return new Connection(this, sourceLSAP, destinationLSAP); } */ /** ** If you want IrLMP to be able to initiate things like discovery, ** it needs to hold a reference to an IrLAP instance. */ public void setIrLAPContext(IrLAPContext irlap) { _irlap = irlap; } /** ** An IrLMP service (IrOBEX, for instance) has agreed to a connect request ** from a host. */ public void connectConfirm(byte destination, byte source, byte [] userData) { _log.debug("IrLMP", "entered connectConfirm"); _log.debug("IrLMP", "destination: " + destination); _log.debug("IrLMP", "source: " + source); if ( null == _irlap ) { _log.error("IrLMP", "IrLAP is null"); return; } byte [] confirmMsg = new byte[255]; int confirmLength = 0; confirmMsg[confirmLength++] = (byte) (0x80 | destination); confirmMsg[confirmLength++] = source; confirmMsg[confirmLength++] = OPCODE_CONNECT_CONFIRM; confirmMsg[confirmLength++] = (byte) 0x00; // optional 0x00 if ( null != userData ) { _log.debug("IrLMP", "userData.length: " + userData.length); for ( int i = 0; i < userData.length; i++ ) { confirmMsg[confirmLength++] = userData[i]; } } try { _log.debug("IrLMP", "_irlapConnection: " + _irlapConnection); _log.debug("IrLMP", "confirmLength: " + confirmLength); _irlap.sendData(_irlapConnection, confirmMsg, 0, confirmLength); } catch ( Exception e ) { _log.debug("IrLMP", "(connectConfirm) " + e); } } //------------------------------------------------------------- // Implement iIrLAPListener //------------------------------------------------------------- /** ** The IrLAP layer has made a connection with another IrLAP layer. */ public void connectIndication(IrLAPContext context, ConnectionInformation info) { _log.debug("IrLMP", "connectIndication"); try { _irlapConnection = (byte) info.getConnection(); int remoteAddress = info.getRemoteAddress(); _log.debug("IrLMP", "_irlapConnection:" + _irlapConnection); _log.debug("IrLMP", "remoteAddress:" + remoteAddress); context.connectResponse(remoteAddress, _irlapConnection, info.getCommParameters()); } catch ( Exception e ) { _log.error("IrLMP", e.toString()); } } /** ** A host has sent data. */ public void dataIndication(IrLAPContext context, ConnectionInformation info, byte [] data) { _log.debug("IrLMP", "(dataIndication) data length: " + data.length); // high bit of first byte is set if this is a command boolean isCommand = (0 != (0x80 & data[0])); // destination (us) is the lower 7 bits of the first byte byte destination = (byte) (0x7F & data[0]); // source (them) is the lower 7 bits of the second byte byte source = (byte) (0x7F & data[1]); // opcode is the third byte byte opcode = data[2]; _log.debug("IrLMP", "isCommand: " + isCommand); _log.debug("IrLMP", "destination: " + Utilities.byteToString(destination)); _log.debug("IrLMP", "source: " + Utilities.byteToString(source)); _log.debug("IrLMP", "opcode: " + Utilities.byteToString(opcode)); //Assert.fail(destination >= 0, // "Destination must be >= zero: " + destination); //Assert.fail(destination < (_services.size() - 1), // "Destination exceeds number of registered services: " + destination); _log.debug("IrLMP", "retrieving service " + destination); iIrLMPService service = (iIrLMPService) _services.get(destination); if ( null == service ) { _log.error("IrLMP", "Destination service is null: " + destination); } _log.debug("IrLMP", "creating IrLMPConnection"); IrLMPConnection irlmpConn = new IrLMPConnection(this, destination, source, info); if ( isCommand ) { _log.debug("IrLMP", "processing command"); // the high bit of the 2nd (source) byte tells us if this is // a message confirming a connect request boolean isConfirm = (0 != (0x80 & data[2])); // we don't use the parameters right now. byte parameters = data[3]; // this is for debugging String message = "(unknown)"; switch ( opcode ) { case OPCODE_CONNECT_REQUEST: message = (isConfirm ? "Connect Confirmation" : "Connect"); // frame length - dest - source - opcode - reserved byte byte [] userData = null; if ( data.length > 4 ) { userData = new byte[data.length - 4]; for ( int i = 0; i < userData.length; i++ ) { userData[i] = data[i + 4]; } } _log.debug("IrLMP", "invoking service's connectRequest()"); service.connectRequest(this, destination, source, userData); break; case 2: message = "Disconnect"; break; case 3: message = (isConfirm ? "Access Mode (confirm)" : "Access Mode"); break; } } else { try { _log.debug("IrLMP", "invoking service's serviceRequest()"); service.serviceRequest(this, irlmpConn, data, 0, data.length); } catch ( Exception e ) { _log.error("IrLMP", "Caught this " + e); } } } /** ** A host has been discovered. */ public void discoveryIndication(IrLAPContext context, DiscoveryInformation discoveryInfo) { _log.debug("IrLMP", "Host discovered: " + discoveryInfo); } protected void sendData(int destination, int source, byte[] data, int offset, int length) throws Exception { _log.debug("IrLMP", "(sendData) destination: " + destination + " source: " + source); send(destination, source, data, offset, length); } /** ** Send data to a host to whom we are connected. */ public void send(int destination, int source, byte[] data, int offset, int length) throws Exception { _log.debug("IrLMP", "(send) destination: " + destination + " source: " + source); Assert.fail(null != _irlap, "IrLAP is null."); try { byte [] frame = new byte[2 + length]; frame[0] = (byte) destination; frame[1] = (byte) source; for ( int i = 0; i < length; i++ ) { frame[i + 2] = data[offset + i]; } _irlap.sendData(_irlapConnection, frame, 0, frame.length); } catch ( Exception e ) { _log.debug("IrLMP ", e.toString()); } } /** ** @param doAutoDiscovery Autodiscovery is enabled if this value is <CODE>true</CODE>. */ public void setAutoDiscovery(boolean doAutoDiscovery) { _doAutoDiscovery = doAutoDiscovery; if ( !_doAutoDiscovery && (null != _autoDiscoveryTimer) ) { _autoDiscoveryTimer.stop(); } else { _autoDiscoveryTimer.start(); } } /** ** Find out if IrLMP needs to automatically discover other hosts. */ private void configureAutoDiscovery() { _doAutoDiscovery = Boolean.getBoolean(AUTO_DISCOVERY_PROPERTY); _log.debug("IrLMP", "_doAutoDiscovery: " + _doAutoDiscovery); Integer interval = Integer.getInteger(AUTO_DISCOVERY_INTERVAL_PROPERTY); if ( null != interval ) { _autoDiscoveryInterval = interval.intValue(); } else { _log.debug("IrLMP", "autoDiscoveryInterval was undefined, using default (300s)"); _autoDiscoveryInterval = DEFAULT_AUTO_DISCOVERY_INTERVAL; } _log.debug("IrLMP", "_autoDiscoveryInterval: " + _autoDiscoveryInterval); if ( _doAutoDiscovery ) { _log.debug("IrLMP", "creating autoDiscoveryTimer"); _autoDiscoveryTimer = new Timer(_autoDiscoveryInterval * 1000, new ActionListener() { public void actionPerformed(ActionEvent event) { _log.debug("IrLMP", "autoDiscoveryTimer fired"); try { discover(); } catch ( Exception e ) { _log.error("IrLMP", e.toString()); } } }); _autoDiscoveryTimer.start(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -