Java/Network Protocol/Modem

Материал из Java эксперт
Перейти к: навигация, поиск

A tiny version of Ward Christensen"s MODEM program for UNIX

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; /**

* a tiny version of Ward Christensen"s MODEM program for UNIX. 
* Written ~ 1980 by Andrew Scott Beals. Last revised 1982.
* A.D. 2000 - dragged from the archives for use in Java Cookbook.
*
* @author C version by Andrew Scott Beals, sjobrg.andy%mit-oz@mit-mc.arpa.
* @author Java version by Ian F. Darwin, http://www.darwinsys.ru/
* $Id: TModem.java,v 1.10 2004/04/11 23:50:40 ian Exp $
*/

public class TModem {

 protected final byte CPMEOF = 26;    /* control/z */
 protected final int MAXERRORS = 10;    /* max times to retry one block */
 protected final int SECSIZE  = 128;    /* cpm sector, transmission block */
 protected final int SENTIMOUT = 30;    /* timeout time in send */
 protected final int  SLEEP  = 30;    /* timeout time in recv */
 /* Protocol characters used */
 protected final byte  SOH  = 1;  /* Start Of Header */
 protected final byte  EOT  = 4;  /* End Of Transmission */
 protected final byte  ACK  = 6;  /* ACKnowlege */
 protected final byte  NAK  = 0x15;  /* Negative AcKnowlege */
 protected InputStream inStream;
 protected OutputStream outStream;
 protected PrintWriter errStream;
 /** Construct a TModem */
 public TModem(InputStream is, OutputStream os, PrintWriter errs) {
   inStream = is;
   outStream = os;
   errStream = errs;
 }
 /** Construct a TModem with default files (stdin and stdout). */
 public TModem() {
   inStream = System.in;
   outStream = System.out;
   errStream = new PrintWriter(System.err);
 }
 /** A main program, for direct invocation. */
 public static void main(String[] argv) throws 
   IOException, InterruptedException {
   /* argc must == 2, i.e., `java TModem -s filename" */
   if (argv.length != 2) 
     usage();
   if (argv[0].charAt(0) != "-")
     usage();
   TModem tm = new TModem();
   tm.setStandalone(true);
   boolean OK = false;
   switch (argv[0].charAt(1)){
   case "r": 
     OK = tm.receive(argv[1]); 
     break;
   case "s": 
     OK = tm.send(argv[1]); 
     break;
   default: 
     usage();
   }
   System.out.print(OK?"Done OK":"Failed");
   System.exit(0);
 }
 /* give user minimal usage message */
 protected static void usage()
 {
   System.err.println("usage: TModem -r/-s file");
   // not errStream, not die(), since this is static.
   System.exit(1);
 }
 /** If we"re in a standalone app it is OK to System.exit() */
 protected boolean standalone = false;
 public void setStandalone(boolean is) {
   standalone = is;
 }
 public boolean isStandalone() {
   return standalone;
 }
 /** A flag used to communicate with inner class IOTimer */
 protected boolean gotChar;
 /** An inner class to provide a read timeout for alarms. */
 class IOTimer extends Thread {
   String message;
   long milliseconds;
   /** Construct an IO Timer */
   IOTimer(long sec, String mesg) {
     milliseconds = 1000 * sec;
     message = mesg;
   }
   
   public void run() {
       try {
       Thread.sleep(milliseconds);
     } catch (InterruptedException e) {
       // can"t happen
     }
     /** Implement the timer */
     if (!gotChar)
     errStream.println("Timed out waiting for " + message);
     try {
       die(1);
     } catch (Exception e1) {
       // TODO Auto-generated catch block
       e1.printStackTrace();
     }
   }
 }
 /*
  * send a file to the remote
  */
 public boolean send(String tfile) throws IOException, InterruptedException
 {
   char checksum, index, blocknumber, errorcount;
   byte character;
   byte[] sector = new byte[SECSIZE];
   int nbytes;
   DataInputStream foo;
   foo = new DataInputStream(new FileInputStream(tfile));
   errStream.println( "file open, ready to send");
   errorcount = 0;
   blocknumber = 1;
   // The C version uses "alarm()", a UNIX-only system call,
   // to detect if the read times out. Here we do detect it
   // by using a Thread, the IOTimer class defined above.
   gotChar = false;
   new IOTimer(SENTIMOUT, "NAK to start send").start();
   do {
     character = getchar();
     gotChar = true;
     if (character != NAK && errorcount < MAXERRORS)
       ++errorcount;
   } while (character != NAK && errorcount < MAXERRORS);
   errStream.println( "transmission beginning");
   if (errorcount == MAXERRORS) {
     xerror();
   }
   while ((nbytes=inStream.read(sector))!=0) {
     if (nbytes<SECSIZE)
       sector[nbytes]=CPMEOF;
     errorcount = 0;
     while (errorcount < MAXERRORS) {
       errStream.println( "{" + blocknumber + "} ");
       putchar(SOH);  /* here is our header */
       putchar(blocknumber);  /* the block number */
       putchar(~blocknumber);  /* & its complement */
       checksum = 0;
       for (index = 0; index < SECSIZE; index++) {
         putchar(sector[index]);
         checksum += sector[index];
       }
       putchar(checksum);  /* tell our checksum */
       if (getchar() != ACK)
         ++errorcount;
       else
         break;
     }
     if (errorcount == MAXERRORS)
       xerror();
     ++blocknumber;
   }
   boolean isAck = false;
   while (!isAck) {
     putchar(EOT);
     isAck = getchar() == ACK;
   }
   errStream.println( "Transmission complete.");
   return true;
 }
 /*
  * receive a file from the remote
  */
 public boolean receive(String tfile) throws IOException, InterruptedException
 {
   char checksum, index, blocknumber, errorcount;
   byte character;
   byte[] sector = new byte[SECSIZE];
   DataOutputStream foo;
   foo = new DataOutputStream(new FileOutputStream(tfile));
   System.out.println("you have " + SLEEP + " seconds...");
   /* wait for the user or remote to get his act together */
   gotChar = false;
   new IOTimer(SLEEP, "receive from remote").start(); 
   errStream.println("Starting receive...");
   putchar(NAK);
   errorcount = 0;
   blocknumber = 1;
   rxLoop:
   do { 
     character = getchar();
     gotChar = true;
     if (character != EOT) {
       try {
         byte not_ch;
         if (character != SOH) {
           errStream.println( "Not SOH");
           if (++errorcount < MAXERRORS)
             continue rxLoop;
           else
             xerror();
         }
         character = getchar();
         not_ch = (byte)(~getchar());
         errStream.println( "[" +  character + "] ");
         if (character != not_ch) {
           errStream.println( "Blockcounts not ~");
           ++errorcount;
           continue rxLoop;
         }
         if (character != blocknumber) {
           errStream.println( "Wrong blocknumber");
           ++errorcount;
           continue rxLoop;
         }
         checksum = 0;
         for (index = 0; index < SECSIZE; index++) {
           sector[index] = getchar();
           checksum += sector[index];
         }
         if (checksum != getchar()) {
           errStream.println( "Bad checksum");
           errorcount++;
           continue rxLoop;
         }
         putchar(ACK);
         blocknumber++;
         try {
           foo.write(sector);
         } catch (IOException e) {
           errStream.println("write failed, blocknumber " + blocknumber);
         }
       } finally {
       if (errorcount != 0)
         putchar(NAK);
     }
   }
   } while (character != EOT);
   foo.close();
   putchar(ACK);  /* tell the other end we accepted his EOT   */
   putchar(ACK);
   putchar(ACK);
   errStream.println("Receive Completed.");
   return true;
 }
 protected byte getchar() throws IOException {
   return (byte)inStream.read();
 }
 protected void putchar(int c) throws IOException {
   outStream.write(c);
 }
 protected void xerror()
 {
   errStream.println("too many errors...aborting");
   try {
     die(1);
   } catch (Exception e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
 }
 protected void die(int how) throws Exception
 {
   if (standalone)
     System.exit(how);
   else throw new Exception("Error code " + Integer.toString(how));
 }

}


      </source>
   
  
 
  



JModem - simple communications program

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.awt.BorderLayout; import java.awt.Font; import java.awt.event.KeyEvent; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; import java.util.Enumeration; import java.util.HashMap; import javax.rum.rumPortIdentifier; import javax.rum.PortInUseException; import javax.rum.SerialPort; import javax.rum.UnsupportedCommOperationException; import javax.swing.ButtonGroup; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; /**

* JModem - simple communications program.
* WARNING this file was built with the NetBeans Developer IDE
* and parts of it should not be modified with a text editor.
* @author    Ian F. Darwin, http://www.darwinsys.ru/
* @version   $Id: JModem.java,v 1.18 2004/04/11 23:50:40 ian Exp $
*/

public class JModem extends javax.swing.JFrame {

 /** The Model. */
 JMModel theModel;
 /** The TextArea */
 JTextArea theTextArea;
 /** The courier font for the text areas and fields. */
 protected Font plainFont;
 /** The valid baud rates (actually BPS rates). */
 private int[] baudot = { 9600, 19200, 38400, 57600, 115200 };
 /** The types of remote systems. */
 private String sysTypes[] = { "Unix", "DOS", "Other" };
 private int M_RECEIVE = -1, M_SEND = +1;
 private int xferDirection = M_RECEIVE;
 /** Constructor */
 public JModem() {
   theModel = new JMModel(this);
   initComponents();
   finishConstructor();
   pack();
 }
 /** This method is called from within the constructor to
  * initialize the form.
  * WARNING: Do NOT modify this code. The content of this method is
  * always regenerated by the FormEditor.
  */
 private void initComponents () {//GEN-BEGIN:initComponents
   setTitle ("JModem");
   addWindowListener (new java.awt.event.WindowAdapter () {
       public void windowClosing (java.awt.event.WindowEvent evt) {
         exitForm (evt);
       }
     }
   );
   getContentPane ().setLayout (new java.awt.BorderLayout ());
   jMenuBar1 = new javax.swing.JMenuBar ();
     fileMenu = new javax.swing.JMenu ();
     fileMenu.setText ("File");
       saveLogFileMenuItem = new javax.swing.JMenuItem ();
       saveLogFileMenuItem.setText ("Save Log");
       saveLogFileMenuItem.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             saveLogFileMenuItemActionPerformed (evt);
           }
         }
       );
       fileMenu.add(saveLogFileMenuItem);
       fileMenu.addSeparator();
       exitMenuItem = new javax.swing.JMenuItem ();
       exitMenuItem.setText ("Exit");
       exitMenuItem.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             exitMenuItemActionPerformed (evt);
           }
         }
       );
       fileMenu.add(exitMenuItem);
     jMenuBar1.add(fileMenu);
     helpMenu = new javax.swing.JMenu ();
     helpMenu.setText ("Help");
       helpAboutMenuItem = new javax.swing.JMenuItem ();
       helpAboutMenuItem.setText ("Item");
       helpAboutMenuItem.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             helpAboutMenuItemActionPerformed (evt);
           }
         }
       );
       helpMenu.add(helpAboutMenuItem);
     jMenuBar1.add(helpMenu);
   setJMenuBar(jMenuBar1);
   connectPanel = new javax.swing.JPanel ();
   connectPanel.setLayout (new java.awt.FlowLayout ());
     connectPanelLabel = new javax.swing.JLabel ();
     connectPanelLabel.setText ("Connection");
     connectPanelLabel.setForeground (java.awt.Color.red);
     connectPanel.add (connectPanelLabel);
     portsLabel = new javax.swing.JLabel ();
     portsLabel.setText ("Port:");
     connectPanel.add (portsLabel);
     portsComboBox = new javax.swing.JComboBox ();
     portsComboBox.addActionListener (new java.awt.event.ActionListener () {
         public void actionPerformed (java.awt.event.ActionEvent evt) {
           portsComboBoxActionPerformed (evt);
         }
       }
     );
     connectPanel.add (portsComboBox);
     buadLabel = new javax.swing.JLabel ();
     buadLabel.setText ("Speed");
     connectPanel.add (buadLabel);
     baudComboBox = new javax.swing.JComboBox ();
     baudComboBox.addActionListener (new java.awt.event.ActionListener () {
         public void actionPerformed (java.awt.event.ActionEvent evt) {
           baudComboBoxActionPerformed (evt);
         }
       }
     );
     connectPanel.add (baudComboBox);
     databitsPanel = new javax.swing.JPanel ();
     databitsPanel.setPreferredSize (new java.awt.Dimension(50, 50));
     databitsPanel.setMinimumSize (new java.awt.Dimension(0, 0));
     databitsPanel.setLayout (new javax.swing.BoxLayout (databitsPanel, 1));
       d7RadioButton = new javax.swing.JRadioButton ();
       d7RadioButton.setText ("7");
       databitsPanel.add (d7RadioButton);
       d8RadioButton = new javax.swing.JRadioButton ();
       d8RadioButton.setSelected (true);
       d8RadioButton.setText ("8");
       databitsPanel.add (d8RadioButton);
     connectPanel.add (databitsPanel);
     parityPanel = new javax.swing.JPanel ();
     parityPanel.setPreferredSize (new java.awt.Dimension(50, 50));
     parityPanel.setLayout (new javax.swing.BoxLayout (parityPanel, 1));
       pNoneRadioButton = new javax.swing.JRadioButton ();
       pNoneRadioButton.setSelected (true);
       pNoneRadioButton.setText ("None");
       pNoneRadioButton.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             pNoneRadioButtonActionPerformed (evt);
           }
         }
       );
       parityPanel.add (pNoneRadioButton);
       pEvenRadioButton = new javax.swing.JRadioButton ();
       pEvenRadioButton.setText ("Even");
       pEvenRadioButton.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             evenRadioButtonActionPerformed (evt);
           }
         }
       );
       parityPanel.add (pEvenRadioButton);
       pOddRadioButton = new javax.swing.JRadioButton ();
       pOddRadioButton.setText ("Odd");
       pOddRadioButton.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             oddRadioButtonActionPerformed (evt);
           }
         }
       );
       parityPanel.add (pOddRadioButton);
     connectPanel.add (parityPanel);
     sysTypeLabel = new javax.swing.JLabel ();
     sysTypeLabel.setText ("Remote:");
     connectPanel.add (sysTypeLabel);
     sysTypeComboBox = new javax.swing.JComboBox ();
     sysTypeComboBox.addActionListener (new java.awt.event.ActionListener () {
         public void actionPerformed (java.awt.event.ActionEvent evt) {
           sysTypeComboBoxActionPerformed (evt);
         }
       }
     );
     connectPanel.add (sysTypeComboBox);
     connectButton = new javax.swing.JButton ();
     connectButton.setText ("Connect");
     connectButton.addActionListener (new java.awt.event.ActionListener () {
         public void actionPerformed (java.awt.event.ActionEvent evt) {
           connectButtonActionPerformed (evt);
         }
       }
     );
     connectPanel.add (connectButton);
   getContentPane().add(connectPanel, BorderLayout.NORTH);
   xferPanel = new javax.swing.JPanel ();
   xferPanel.setLayout (new java.awt.FlowLayout ());
     xferPanelLabel = new javax.swing.JLabel ();
     xferPanelLabel.setText ("File Transfer");
     xferPanelLabel.setForeground (java.awt.Color.red);
     xferPanel.add (xferPanelLabel);
     jPanel6 = new javax.swing.JPanel ();
     jPanel6.setLayout (new javax.swing.BoxLayout (jPanel6, 1));
       sendRadioButton = new javax.swing.JRadioButton ();
       sendRadioButton.setSelected (true);
       sendRadioButton.setText ("Send");
       sendRadioButton.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             sendRadioButtonActionPerformed (evt);
           }
         }
       );
       jPanel6.add (sendRadioButton);
       recvRadioButton = new javax.swing.JRadioButton ();
       recvRadioButton.setText ("Receive");
       recvRadioButton.addActionListener (new java.awt.event.ActionListener () {
           public void actionPerformed (java.awt.event.ActionEvent evt) {
             recvRadioButtonActionPerformed (evt);
           }
         }
       );
       jPanel6.add (recvRadioButton);
     xferPanel.add (jPanel6);
     xferFilenameLabel = new javax.swing.JLabel ();
     xferFilenameLabel.setText ("Filename:");
     xferPanel.add (xferFilenameLabel);
     xferFileNameTF = new javax.swing.JTextField ();
     xferFileNameTF.setPreferredSize (new java.awt.Dimension(100, 20));
     xferPanel.add (xferFileNameTF);
     jPanel7 = new javax.swing.JPanel ();
     jPanel7.setLayout (new javax.swing.BoxLayout (jPanel7, 1));
       xferModeTextRadioButton = new javax.swing.JRadioButton ();
       xferModeTextRadioButton.setText ("Text");
       jPanel7.add (xferModeTextRadioButton);
       xferModeBinRadioButton = new javax.swing.JRadioButton ();
       xferModeBinRadioButton.setSelected (true);
       xferModeBinRadioButton.setText ("Binary");
       jPanel7.add (xferModeBinRadioButton);
     xferPanel.add (jPanel7);
     xferButton = new javax.swing.JButton ();
     xferButton.setText ("Transfer");
     xferButton.addActionListener (new java.awt.event.ActionListener () {
         public void actionPerformed (java.awt.event.ActionEvent evt) {
           xferButtonActionPerformed (evt);
         }
       }
     );
     xferPanel.add (xferButton);
   getContentPane ().add (xferPanel, BorderLayout.SOUTH);
 }//GEN-END:initComponents
 /** Save the session log to disk.
  */
 private void saveLogFileMenuItemActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveLogFileMenuItemActionPerformed
   theModel.saveLogFile();
 }//GEN-LAST:event_saveLogFileMenuItemActionPerformed
 private void helpAboutMenuItemActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_helpAboutMenuItemActionPerformed
   note("JModem 0.0 (c) 2000 Ian F. Darwin\nhttp://www.darwinsys.ru/");
 }//GEN-LAST:event_helpAboutMenuItemActionPerformed
 private void baudComboBoxActionPerformed (java.awt.event.ActionEvent evt) {
   // Add your handling code here:
 }
 private void portsComboBoxActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_portsComboBoxActionPerformed
   // Add your handling code here:
 }//GEN-LAST:event_portsComboBoxActionPerformed
 /** A TextArea subclass with funky keypress forwarding: send to
  * remote, not to local. This IS a terminal emulator, after all.
  */
 class MyTextArea extends JTextArea {
   MyTextArea(int r, int c) {
     super(r, c);
   }
   /** Handle local KeyEvents: send KeyTyped to the remote. */
   protected void processComponentKeyEvent(java.awt.event.KeyEvent evt) {
     if (evt.getID() != KeyEvent.KEY_TYPED)
       return;
     // send keystrokes to remote, for processing.
     // do nothing locally, to avoid user keystrokes appearing twice!
     if (theModel.state != JMModel.S_CONNECTED) {
       getToolkit().beep();  // or just connect()?
       return;
     }
     char ch = evt.getKeyChar();
     if (ch == "\n") {    // XX if systemtype == dos
       // sendChar("\r");
       theModel.sendChar("\n");
       return;
     }
     theModel.sendChar(ch);
   }
 }
 /** Finish the initializations. */
 private void finishConstructor() {
   // Create the textarea with a JScrollpane wrapping it.
   // Install it in Centre of the TextArea.
   theTextArea = new MyTextArea(20, 80);
   getContentPane().add(new JScrollPane(theTextArea), BorderLayout.CENTER);
   plainFont = new Font("courier", Font.PLAIN, 13);
   theTextArea.setFont(plainFont);
   xferFileNameTF.setFont(plainFont);
   theModel.populateComboBox();
   portsComboBox.setSelectedIndex(0);
   // Load up the baud rate combo box
   for (int i=0; i<baudot.length; i++) {
     baudComboBox.addItem(Integer.toString(baudot[i]));
   }
   baudComboBox.setSelectedIndex(0);
   // Load up the System Type combo box
   for (int i=0; i<sysTypes.length; i++) {
     sysTypeComboBox.addItem(sysTypes[i]);
   }
   sysTypeComboBox.setSelectedIndex(0);
   // put radio buttons into groups to enforce single-selection
   ButtonGroup b1 = new ButtonGroup();
   b1.add(d7RadioButton);
   b1.add(d8RadioButton);
   ButtonGroup b2 = new ButtonGroup();
   b2.add(pNoneRadioButton);
   b2.add(pEvenRadioButton);
   b2.add(pOddRadioButton);
   ButtonGroup b3 = new ButtonGroup();
   b3.add(sendRadioButton);
   b3.add(recvRadioButton);
   ButtonGroup b4 = new ButtonGroup();
   b4.add(xferModeTextRadioButton);
   b4.add(xferModeBinRadioButton);
   xferModeBinRadioButton.setEnabled(true);
 }
 private void recvRadioButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_recvRadioButtonActionPerformed
   xferDirection = M_RECEIVE;
 }//GEN-LAST:event_recvRadioButtonActionPerformed
 private void sendRadioButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendRadioButtonActionPerformed
   xferDirection = M_SEND;
 }//GEN-LAST:event_sendRadioButtonActionPerformed
 private void exitMenuItemActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
   System.exit(0);
 }//GEN-LAST:event_exitMenuItemActionPerformed
 private void sysTypeComboBoxActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sysTypeComboBoxActionPerformed
   // Add your handling code here:
 }//GEN-LAST:event_sysTypeComboBoxActionPerformed
 private void pNoneRadioButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pNoneRadioButtonActionPerformed
   // Add your handling code here:
 }//GEN-LAST:event_pNoneRadioButtonActionPerformed
 private void oddRadioButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_oddRadioButtonActionPerformed
   // Add your handling code here:
 }//GEN-LAST:event_oddRadioButtonActionPerformed
 private void evenRadioButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_evenRadioButtonActionPerformed
   // Add your handling code here:
 }//GEN-LAST:event_evenRadioButtonActionPerformed
 /** This method basically toggles between Connected mode and
  * disconnected mode.
  */
 private void connectButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed
   if (theModel.state == JMModel.S_CONNECTED) {
     theModel.disconnect();  // calls our disconnect() if OK
   } else {
     theModel.connect();    // calls our connect() if OK
   }
 }//GEN-LAST:event_connectButtonActionPerformed
 /** Show that we have connected to the serial port. */
 void connect() {
     connectButton.setText("Disconnect");
     theTextArea.setEditable(true);
     theTextArea.requestFocus();
 }
 /** Show that we have connected to the serial port. */
 void disconnect() {
     connectButton.setText("Connect");
     theTextArea.setEditable(false);
 }
 private void xferButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_xferButtonActionPerformed
   // Do the transfer, using TModem class.
   theModel.xfer();
 }//GEN-LAST:event_xferButtonActionPerformed
 /** Exit the Application */
 private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
   System.exit (0);
 }//GEN-LAST:event_exitForm

// Some of these must be package-level visibility for JMModel, // until we re-define the interface to that class a little... // Variables declaration - do not modify//GEN-BEGIN:variables

 private javax.swing.JPanel connectPanel;
 private javax.swing.JPanel xferPanel;
 private javax.swing.JLabel connectPanelLabel;
 private javax.swing.JLabel portsLabel;
 protected javax.swing.JComboBox portsComboBox;
 private javax.swing.JLabel buadLabel;
 protected javax.swing.JComboBox baudComboBox;
 private javax.swing.JPanel databitsPanel;
 private javax.swing.JPanel parityPanel;
 private javax.swing.JLabel sysTypeLabel;
 private javax.swing.JComboBox sysTypeComboBox;
 private javax.swing.JButton connectButton;
 private javax.swing.JRadioButton d7RadioButton;
 private javax.swing.JRadioButton d8RadioButton;
 private javax.swing.JRadioButton pNoneRadioButton;
 private javax.swing.JRadioButton pEvenRadioButton;
 private javax.swing.JRadioButton pOddRadioButton;
 private javax.swing.JLabel xferPanelLabel;
 private javax.swing.JPanel jPanel6;
 private javax.swing.JLabel xferFilenameLabel;
 private javax.swing.JTextField xferFileNameTF;
 private javax.swing.JPanel jPanel7;
 private javax.swing.JButton xferButton;
 private javax.swing.JRadioButton sendRadioButton;
 private javax.swing.JRadioButton recvRadioButton;
 private javax.swing.JRadioButton xferModeTextRadioButton;
 private javax.swing.JRadioButton xferModeBinRadioButton;
 private javax.swing.JMenuBar jMenuBar1;
 private javax.swing.JMenu fileMenu;
 private javax.swing.JMenu helpMenu;
 private javax.swing.JMenuItem saveLogFileMenuItem;
 private javax.swing.JMenuItem exitMenuItem;
 private javax.swing.JMenuItem helpAboutMenuItem;

// End of variables declaration//GEN-END:variables

 /** Tell if the user wants 7 or 8-bit words */
 public int getDataBits() {
   if (d7RadioButton.isSelected())
     return 7;
   if (d8RadioButton.isSelected())
     return 8;
   throw new IllegalStateException("No word size in radio button group");
 }
 /** Tell if the user wants even, odd, or no parity. */
 public int getParity() {
   if (pNoneRadioButton.isSelected()) return JMModel.PARITY_NONE;
   if (pEvenRadioButton.isSelected()) return JMModel.PARITY_EVEN;
   if (pOddRadioButton.isSelected())  return JMModel.PARITY_ODD;
   throw new IllegalStateException("No parity in radio button group");
 }
 /** Get the filename */
 public String getXferFileName() {
   return xferFileNameTF.getText();
 }
 /** "One if by send, two if receive" */
 public boolean isSend() {
   if (sendRadioButton.isSelected())
     return true;
   if (recvRadioButton.isSelected())
     return false;
   throw new IllegalStateException("No send/recv set in radio button group");
 }
 /** Convenience routine: Show a standard-form information dialog */
 void note(String message) {
   JOptionPane.showMessageDialog(this, message,
     "JModem Notice", JOptionPane.INFORMATION_MESSAGE);
   return;
 }
 /** Convenience routine: Show a standard-form error dialog */
 void err(String message) {
   JOptionPane.showMessageDialog(this, message,
     "JModem Error", JOptionPane.ERROR_MESSAGE);
   return;
 }
 /** Main: just create and show the application class. */
 public static void main(java.lang.String[] args) {
   new JModem().setVisible(true);
 }

} /**

* JMModel -- Communications I/O for JModem. No GUI stuff here.
* @author   Ian F. Darwin, http://www.darwinsys.ru/
* @version   $Id: JMModel.java,v 1.4 2004/04/11 23:50:40 ian Exp $
*/

class JMModel extends java.lang.Object {

 /** The View */
 JModem theGUI;
 /** The javax.ru.rumPort object in use */
 private SerialPort thePort;
 /** The input and output streams */
 private InputStream serialInput;
 private OutputStream serialOutput;
 /** The size of the static read buffer. */
 protected static final int BUFSIZE = 1024;
 /** A buffer for the read listener; preallocated once. */
 static byte[] buf = new byte[BUFSIZE];
 /** A Thread for reading from the remote. */
 protected Thread serialReadThread;
 /** A file transfer program */
 protected TModem xferProg;
 /** The state for disconnected and connected */
 static int S_DISCONNECTED = 0, S_CONNECTED = 1;
 /** The state, either disconnected or connected */
 int state = S_DISCONNECTED;
 /** The substate settings */
 static int S_INTERACT = 0, S_XFER = 1;
 /** The online state, either interactive or in xfer. Used by the
  * main reader thread to avoid reading data meant for the xfer program.
  */
 int submode = S_INTERACT;
 // Constants to hide the Comm API from our GUI.
 public final static int PARITY_NONE = SerialPort.PARITY_NONE;
 public final static int PARITY_EVEN = SerialPort.PARITY_EVEN;
 public final static int PARITY_ODD  = SerialPort.PARITY_ODD;
 private int[] baudot = { 9600, 19200, 38400, 57600, 115200 };
 private String sysTypes[] = { "Unix", "DOS", "Other" };
 protected HashMap portsIDmap = new HashMap();
 /** Constructor */
 public JMModel(JModem gui) {
   theGUI = gui;
 }
 protected String DEFAULT_LOG_FILE = "jmodemlog.txt";;
 /** Use normal java.io to save the JTextArea"s session log
  * into a file.
  */  
 public void saveLogFile() {
   String fileName = DEFAULT_LOG_FILE;
   try {
     Writer w = new FileWriter(fileName);
     theGUI.theTextArea.write(w);
     w.write("\r"); w.write("\n");  // in case last line is a prompt.
     w.close();
   } catch (IOException e) {
     theGUI.err("Error saving log file:\n" + e.toString());
     return;
   }
   theGUI.note("Session log saved to " + fileName);
 }
 /** Load the list of Serial Ports into the chooser.
  * This code is far too chummy with the innards of class JModem.
  */
 void populateComboBox() {
   // get list of ports available on this particular computer,
   // by calling static method in CommPortIdentifier.
   Enumeration pList = CommPortIdentifier.getPortIdentifiers();
   // Process the list of ports, putting serial ports into ComboBox
   while (pList.hasMoreElements()) {
     CommPortIdentifier cpi = (CommPortIdentifier)pList.nextElement();
     if (cpi.getPortType() == CommPortIdentifier.PORT_SERIAL) {
       theGUI.portsComboBox.addItem(cpi.getName());
       portsIDmap.put(cpi.getName(), cpi);
     }
   }
 }
 /** Connect to the chosen serial port, and set parameters. */
 void connect() {
   try {
     // Open the specified serial port
     CommPortIdentifier cpi = (CommPortIdentifier)portsIDmap.get(
     theGUI.portsComboBox.getSelectedItem());
     thePort = (SerialPort)cpi.open("JModem", 15*1000);
     // Set the serial port parameters.
     thePort.setSerialPortParams(
       baudot[theGUI.baudComboBox.getSelectedIndex()],    // baud
       theGUI.getDataBits() == 7 ?
       SerialPort.DATABITS_7 : SerialPort.DATABITS_8,
       SerialPort.STOPBITS_1,              // stop bits
       theGUI.getParity());              // parity
     thePort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN &
       SerialPort.FLOWCONTROL_RTSCTS_OUT);
   } catch (PortInUseException pue) {
     theGUI.err("Port in use: close other app, or use different port.");
     return;
   } catch (UnsupportedCommOperationException uoe) {
     theGUI.err("Unsupported options error: try different settings");
     return;
   }
   // Similar to "raw" mode: return when 1 or more chars available.
   try {
     thePort.enableReceiveThreshold(1);
     if (!thePort.isReceiveThresholdEnabled()) {
       theGUI.err("Could not set receive threshold");
       disconnect();
       return;
     }
     thePort.setInputBufferSize(buf.length);
   } catch (UnsupportedCommOperationException ev) {
     theGUI.err("Unable to set receive threshold in Comm API; port unusable.");
     disconnect();
     return;
   }
   // Get the streams
   try {
     serialInput = thePort.getInputStream();
   } catch (IOException e) {
     theGUI.err("Error getting input stream:\n" + e.toString());
     return;
   }
   try {
     serialOutput = thePort.getOutputStream();
   } catch (IOException e) {
     theGUI.err("Error getting output stream:\n" + e.toString());
     return;
   }
   // Now that we"re all set, create a Thread to read data from the remote
   serialReadThread = new Thread(new Runnable() {
   int nbytes = buf.length;
     public void run() {
       do {
         try {
           // If the xfer program is running, stay out of its way.
             if (submode == S_XFER) {
               delay(1000);
             continue;
           }
           nbytes = serialInput.read(buf, 0, buf.length);
         } catch (IOException ev) {
         theGUI.err("Error reading from remote:\n" + ev.toString());
         return;
         }
         // XXX need an appendChar() method in MyTextArea
         String tmp = new String(buf, 0, nbytes);
         theGUI.theTextArea.append(tmp);
         theGUI.theTextArea.setCaretPosition(
         theGUI.theTextArea.getText().length());
       } while (serialInput != null);
     }
   });
   serialReadThread.start();
   // Finally, tell rest of program, and user, that we"re online.
   state = S_CONNECTED;
   theGUI.connect();
 }
 /** Break our connection to the serial port. */
 void disconnect() {
   // Tell java.io we are done with the input and output
   try {
     serialReadThread.stop();  // IGNORE DEPRECATION WARNINGS; the Java
     // API still lacks a reliable termination method for Threads
     // that are blocked on e.g., local disk reads.
     serialInput.close();
     serialOutput.close();
     serialOutput = null;
   } catch (IOException e) {
     theGUI.err("IO Exception closing port:\n" + e.toString());
   }
   // Tell javax.rum we are done with the port.
   thePort.removeEventListener();
   thePort.close();
   // Discard TModem object, if present.
   xferProg = null;
   // Tell rest of program we are no longer online.
   state = S_DISCONNECTED;
   theGUI.disconnect();
 }
 /** Convenience routine, due to useless InterruptedException */
 public void delay(long milliseconds) {
   try {
     Thread.sleep(milliseconds);
   } catch (InterruptedException e) {
     // can"t happen
   }
 }
 /** Send one character to the remote */
 void sendChar(char ch) {
   if (state != S_CONNECTED)
     return;
   // System.err.println("--> " + ch);
   try {
     serialOutput.write(ch);
   } catch (IOException e) {
     theGUI.err("Output error on remote:\n" + e.toString() +
       "\nClosing connection.");
     disconnect();
   }
 }
 /** Send a String of characters to the remote. */
 private void sendString(String s) {
   if (state != S_CONNECTED)
     return;
   try {
     serialOutput.write(s.getBytes());
   } catch (IOException e) {
     theGUI.err("Output error on remote:\n" + e.toString() +
       "\nClosing connection.");
     disconnect();
   }
 }
 /** Do one complete file transfer, using TModem */
 public void xfer() {
   if (state != S_CONNECTED) {
     theGUI.err("Must be connected to do file transfers");
     return;
   }
   if (xferProg == null) {
     xferProg = new TModem(serialInput, serialOutput, 
       new PrintWriter(System.out)); // xerProg discarded in disconnect()
   }
   String fileName = theGUI.getXferFileName();
   if (fileName.length() == 0) {
     theGUI.err("Filename must be given");
     return;
   }
   // Do the transfer!  If we are sending, send a "tmodem -r" to
   // the other side; if receiving, send "tmodem -s" to ask it
   // to send the file.
   try {
     if (theGUI.isSend()) {
       if (!new File(fileName).canRead()) {
           theGUI.err("Can"t read file " + fileName + ".");
         return;
       }
       // Other end must "r"eceive what we send.
       sendString("tmodem -r " + fileName + "\r\n");
       delay(500);    // let command echo back to us
       submode = S_XFER;
       xferProg.send(fileName);
     } else {
       // Other end must send for us to receive.
       sendString("tmodem -s " + fileName + "\r\n");
       delay(500);    // let command echo back to us
       submode = S_XFER;
       xferProg.receive(fileName);
     }
   } catch (InterruptedException e) {
     theGUI.err("Timeout");
     return;
   } catch (IOException e) {
     theGUI.err("IO Exception in transfer:\n" + e);
     return;
   } catch (Exception ev) {
     theGUI.err("Protocol failure:\n" + ev);
     return;
   } finally {
     submode = S_INTERACT;
   }
   theGUI.note("File Transfer completed");
 }

}


/**

* a tiny version of Ward Christensen"s MODEM program for UNIX. 
* Written ~ 1980 by Andrew Scott Beals. Last revised 1982.
* A.D. 2000 - dragged from the archives for use in Java Cookbook.
*
* @author C version by Andrew Scott Beals, sjobrg.andy%mit-oz@mit-mc.arpa.
* @author Java version by Ian F. Darwin, ian@darwinsys.ru
* $Id: TModem.java,v 1.8 2000/03/02 03:40:50 ian Exp $
*/

class TModem {

   protected final byte CPMEOF = 26;       /* control/z */
   protected final int MAXERRORS = 10;     /* max times to retry one block */
   protected final int SECSIZE = 128;      /* cpm sector, transmission block */
   protected final int SENTIMOUT = 30;     /* timeout time in send */
   protected final int SLEEP   = 30;       /* timeout time in recv */
   /* Protocol characters used */
   protected final byte    SOH = 1;    /* Start Of Header */
   protected final byte    EOT = 4;    /* End Of Transmission */
   protected final byte    ACK = 6;    /* ACKnowlege */
   protected final byte    NAK = 0x15; /* Negative AcKnowlege */
   protected InputStream inStream;
   protected OutputStream outStream;
   protected PrintWriter errStream;
   /** Construct a TModem */
   public TModem(InputStream is, OutputStream os, PrintWriter errs) {
       inStream = is;
       outStream = os;
       errStream = errs;
   }
   /** Construct a TModem with default files (stdin and stdout). */
   public TModem() {
       inStream = System.in;
       outStream = System.out;
       errStream = new PrintWriter(System.err);
   }
   /** A main program, for direct invocation. */
   public static void main(String[] argv) throws 
       IOException, InterruptedException {
       /* argc must == 2, i.e., `java TModem -s filename" */
       if (argv.length != 2) 
           usage();
       if (argv[0].charAt(0) != "-")
           usage();
       TModem tm = new TModem();
       tm.setStandalone(true);
       boolean OK = false;
       switch (argv[0].charAt(1)){
       case "r": 
           OK = tm.receive(argv[1]); 
           break;
       case "s": 
           OK = tm.send(argv[1]); 
           break;
       default: 
           usage();
       }
       System.out.print(OK?"Done OK":"Failed");
       System.exit(0);
   }
   /* give user minimal usage message */
   protected static void usage()
   {
       System.err.println("usage: TModem -r/-s file");
       // not errStream, not die(), since this is static.
       System.exit(1);
   }
   /** If we"re in a standalone app it is OK to System.exit() */
   protected boolean standalone = false;
   public void setStandalone(boolean is) {
       standalone = is;
   }
   public boolean isStandalone() {
       return standalone;
   }
   /** A flag used to communicate with inner class IOTimer */
   protected boolean gotChar;
   /** An inner class to provide a read timeout for alarms. */
   class IOTimer extends Thread {
       String message;
       long milliseconds;
       /** Construct an IO Timer */
       IOTimer(long sec, String mesg) {
           milliseconds = 1000 * sec;
           message = mesg;
       }
       
       public void run() {
         try {
           Thread.sleep(milliseconds);
         } catch (InterruptedException e) {
           // can"t happen
         }
         /** Implement the timer */
         if (!gotChar)
           errStream.println("Timed out waiting for " + message);
           die(1);
       }
   }
   /*
    * send a file to the remote
    */
   public boolean send(String tfile) throws IOException, InterruptedException
   {
       char checksum, index, blocknumber, errorcount;
       byte character;
       byte[] sector = new byte[SECSIZE];
       int nbytes;
       DataInputStream foo;
       foo = new DataInputStream(new FileInputStream(tfile));
       errStream.println( "file open, ready to send");
       errorcount = 0;
       blocknumber = 1;
       // The C version uses "alarm()", a UNIX-only system call,
       // to detect if the read times out. Here we do detect it
       // by using a Thread, the IOTimer class defined above.
       gotChar = false;
       new IOTimer(SENTIMOUT, "NAK to start send").start();
       do {
           character = getchar();
           gotChar = true;
           if (character != NAK && errorcount < MAXERRORS)
               ++errorcount;
       } while (character != NAK && errorcount < MAXERRORS);
       errStream.println( "transmission beginning");
       if (errorcount == MAXERRORS) {
           xerror();
       }
       while ((nbytes=inStream.read(sector))!=0) {
           if (nbytes<SECSIZE)
               sector[nbytes]=CPMEOF;
           errorcount = 0;
           while (errorcount < MAXERRORS) {
               errStream.println( "{" + blocknumber + "} ");
               putchar(SOH);   /* here is our header */
               putchar(blocknumber);   /* the block number */
               putchar(~blocknumber);  /* & its complement */
               checksum = 0;
               for (index = 0; index < SECSIZE; index++) {
                   putchar(sector[index]);
                   checksum += sector[index];
               }
               putchar(checksum);  /* tell our checksum */
               if (getchar() != ACK)
                   ++errorcount;
               else
                   break;
           }
           if (errorcount == MAXERRORS)
               xerror();
           ++blocknumber;
       }
       boolean isAck = false;
       while (!isAck) {
           putchar(EOT);
           isAck = getchar() == ACK;
       }
       errStream.println( "Transmission complete.");
       return true;
   }
   /*
    * receive a file from the remote
    */
   public boolean receive(String tfile) throws IOException, InterruptedException
   {
       char checksum, index, blocknumber, errorcount;
       byte character;
       byte[] sector = new byte[SECSIZE];
       DataOutputStream foo;
       foo = new DataOutputStream(new FileOutputStream(tfile));
       System.out.println("you have " + SLEEP + " seconds...");
       /* wait for the user or remote to get his act together */
       gotChar = false;
       new IOTimer(SLEEP, "receive from remote").start(); 
       errStream.println("Starting receive...");
       putchar(NAK);
       errorcount = 0;
       blocknumber = 1;
       rxLoop:
       do { 
           character = getchar();
           gotChar = true;
           if (character != EOT) {
               try {
                   byte not_ch;
                   if (character != SOH) {
                       errStream.println( "Not SOH");
                       if (++errorcount < MAXERRORS)
                           continue rxLoop;
                       else
                           xerror();
                   }
                   character = getchar();
                   not_ch = (byte)(~getchar());
                   errStream.println( "[" +  character + "] ");
                   if (character != not_ch) {
                       errStream.println( "Blockcounts not ~");
                       ++errorcount;
                       continue rxLoop;
                   }
                   if (character != blocknumber) {
                       errStream.println( "Wrong blocknumber");
                       ++errorcount;
                       continue rxLoop;
                   }
                   checksum = 0;
                   for (index = 0; index < SECSIZE; index++) {
                       sector[index] = getchar();
                       checksum += sector[index];
                   }
                   if (checksum != getchar()) {
                       errStream.println( "Bad checksum");
                       errorcount++;
                       continue rxLoop;
                   }
                   putchar(ACK);
                   blocknumber++;
                   try {
                       foo.write(sector);
                   } catch (IOException e) {
                       errStream.println("write failed, blocknumber " + blocknumber);
                   }
               } finally {
               if (errorcount != 0)
                   putchar(NAK);
           }
       }
       } while (character != EOT);
       foo.close();
       putchar(ACK);   /* tell the other end we accepted his EOT   */
       putchar(ACK);
       putchar(ACK);
       errStream.println("Receive Completed.");
       return true;
   }
   protected byte getchar() throws IOException {
       return (byte)inStream.read();
   }
   protected void putchar(int c) throws IOException {
       outStream.write(c);
   }
   protected void xerror()
   {
       errStream.println("too many errors...aborting");
       die(1);
   }
   protected void die(int how)
   {
       if (standalone)
           System.exit(how);
       else 
         System.out.println(("Error code " + how));
   }

}


      </source>
   
  
 
  



Print to a serial port using Java Communications

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.awt.BorderLayout; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.Enumeration; import java.util.HashMap; import javax.rum.rumPort; import javax.rum.rumPortIdentifier; import javax.rum.NoSuchPortException; import javax.rum.ParallelPort; import javax.rum.PortInUseException; import javax.rum.SerialPort; import javax.rum.UnsupportedCommOperationException; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /**

* Print to a serial port using Java Communications.
*
* @author  Ian F. Darwin, http://www.darwinsys.ru/
 */

public class ParallelPrint extends CommPortOpen {

 protected static String inputFileName;
 public static void main(String[] argv)
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   if (argv.length != 1) {
     System.err.println("Usage: ParallelPrint filename");
     System.exit(1);
   }
   inputFileName = argv[0];
   new ParallelPrint(null).converse();
   System.exit(0);
 }
 /* Constructor */
 public ParallelPrint(JFrame f)
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   
   super(f);
 }
 /** 
  * Hold the (one-way) conversation. 
  */
 protected void converse() throws IOException {
   // Make a reader for the input file.
   BufferedReader file = new BufferedReader(
     new FileReader(inputFileName));
   String line;
   while ((line = file.readLine()) != null)
     os.println(line);
   // Finally, clean up.
   file.close();
   os.close();
 }

}

class CommPortOpen {

 /** How long to wait for the open to finish up. */
 public static final int TIMEOUTSECONDS = 30;
 /** The baud rate to use. */
 public static final int BAUD = 19200;
 /** The parent JFrame, for the chooser. */
 protected JFrame parent;
 /** The input stream */
 protected BufferedReader is;
 /** The output stream */
 protected PrintStream os;
 /** The chosen Port Identifier */
 CommPortIdentifier thePortID;
 /** The chosen Port itself */
 CommPort thePort;
 public static void main(String[] argv)
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   new CommPortOpen(null).converse();
   System.exit(0);
 }
 /* Constructor */
 public CommPortOpen(JFrame f)
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   
   // Use the PortChooser from before. Pop up the JDialog.
   PortChooser chooser = new PortChooser(null);
   String portName = null;
   do {
     chooser.setVisible(true);
     
     // Dialog done. Get the port name.
     portName = chooser.getSelectedName();
     if (portName == null)
       System.out.println("No port selected. Try again.\n");
   } while (portName == null);
   // Get the CommPortIdentifier.
   thePortID = chooser.getSelectedIdentifier();
   // Now actually open the port.
   // This form of openPort takes an Application Name and a timeout.
   // 
   System.out.println("Trying to open " + thePortID.getName() + "...");
   switch (thePortID.getPortType()) {
   case CommPortIdentifier.PORT_SERIAL:
     thePort = thePortID.open("DarwinSys DataComm",
       TIMEOUTSECONDS * 1000);
     SerialPort myPort = (SerialPort) thePort;
     // set up the serial port
     myPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8,
       SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
     break;
   case CommPortIdentifier.PORT_PARALLEL:
     thePort = thePortID.open("DarwinSys Printing",
       TIMEOUTSECONDS * 1000);
     ParallelPort pPort = (ParallelPort)thePort;
     // Tell API to pick "best available mode" - can fail!
     // myPort.setMode(ParallelPort.LPT_MODE_ANY);
     // Print what the mode is
     int mode = pPort.getMode();
     switch (mode) {
       case ParallelPort.LPT_MODE_ECP:
         System.out.println("Mode is: ECP");
         break;
       case ParallelPort.LPT_MODE_EPP:
         System.out.println("Mode is: EPP");
         break;
       case ParallelPort.LPT_MODE_NIBBLE:
         System.out.println("Mode is: Nibble Mode.");
         break;
       case ParallelPort.LPT_MODE_PS2:
         System.out.println("Mode is: Byte mode.");
         break;
       case ParallelPort.LPT_MODE_SPP:
         System.out.println("Mode is: Compatibility mode.");
         break;
       // ParallelPort.LPT_MODE_ANY is a "set only" mode;
       // tells the API to pick "best mode"; will report the
       // actual mode it selected.
       default:
         throw new IllegalStateException("Parallel mode " + 
           mode + " invalid.");
     }
     break;
   default:  // Neither parallel nor serial??
     throw new IllegalStateException("Unknown port type " + thePortID);
   }
   // Get the input and output streams
   // Printers can be write-only
   try {
     is = new BufferedReader(new InputStreamReader(thePort.getInputStream()));
   } catch (IOException e) {
     System.err.println("Can"t open input stream: write-only");
     is = null;
   }
   os = new PrintStream(thePort.getOutputStream(), true);
 }
 /** This method will be overridden by non-trivial subclasses
  * to hold a conversation. 
  */
 protected void converse() throws IOException {
   System.out.println("Ready to read and write port.");
   // Input/Output code not written -- must subclass.
   // Finally, clean up.
   if (is != null)
     is.close();
   os.close();
 }

} class PortChooser extends JDialog implements ItemListener {

 /** A mapping from names to CommPortIdentifiers. */
 protected HashMap map = new HashMap();
 /** The name of the choice the user made. */
 protected String selectedPortName;
 /** The CommPortIdentifier the user chose. */
 protected CommPortIdentifier selectedPortIdentifier;
 /** The JComboBox for serial ports */
 protected JComboBox serialPortsChoice;
 /** The JComboBox for parallel ports */
 protected JComboBox parallelPortsChoice;
 /** The JComboBox for anything else */
 protected JComboBox other;
 /** The SerialPort object */
 protected SerialPort ttya;
 /** To display the chosen */
 protected JLabel choice;
 /** Padding in the GUI */
 protected final int PAD = 5;
 /** This will be called from either of the JComboBoxen when the
  * user selects any given item.
  */
 public void itemStateChanged(ItemEvent e) {
   // Get the name
   selectedPortName = (String)((JComboBox)e.getSource()).getSelectedItem();
   // Get the given CommPortIdentifier
   selectedPortIdentifier = (CommPortIdentifier)map.get(selectedPortName);
   // Display the name.
   choice.setText(selectedPortName);
 }
 /* The public "getter" to retrieve the chosen port by name. */
 public String getSelectedName() {
   return selectedPortName;
 }
 /* The public "getter" to retrieve the selection by CommPortIdentifier. */
 public CommPortIdentifier getSelectedIdentifier() {
   return selectedPortIdentifier;
 }
 /** A test program to show up this chooser. */
 public static void main(String[] ap) {
   PortChooser c = new PortChooser(null);
   c.setVisible(true);  // blocking wait
   System.out.println("You chose " + c.getSelectedName() +
     " (known by " + c.getSelectedIdentifier() + ").");
   System.exit(0);
 }
 /** Construct a PortChooser --make the GUI and populate the ComboBoxes.
  */
 public PortChooser(JFrame parent) {
   super(parent, "Port Chooser", true);
   makeGUI();
   populate();
   finishGUI();
 }
 /** Build the GUI. You can ignore this for now if you have not
  * yet worked through the GUI chapter. Your mileage may vary.
  */
 protected void makeGUI() {
   Container cp = getContentPane();
   JPanel centerPanel = new JPanel();
   cp.add(BorderLayout.CENTER, centerPanel);
   centerPanel.setLayout(new GridLayout(0,2, PAD, PAD));
   centerPanel.add(new JLabel("Serial Ports", JLabel.RIGHT));
   serialPortsChoice = new JComboBox();
   centerPanel.add(serialPortsChoice);
   serialPortsChoice.setEnabled(false);
   centerPanel.add(new JLabel("Parallel Ports", JLabel.RIGHT));
   parallelPortsChoice = new JComboBox();
   centerPanel.add(parallelPortsChoice);
   parallelPortsChoice.setEnabled(false);
   centerPanel.add(new JLabel("Unknown Ports", JLabel.RIGHT));
   other = new JComboBox();
   centerPanel.add(other);
   other.setEnabled(false);
   centerPanel.add(new JLabel("Your choice:", JLabel.RIGHT));
   centerPanel.add(choice = new JLabel());
   JButton okButton;
   cp.add(BorderLayout.SOUTH, okButton = new JButton("OK"));
   okButton.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       PortChooser.this.dispose();
     }
   });
 }
 /** Populate the ComboBoxes by asking the Java Communications API
  * what ports it has.  Since the initial information comes from
  * a Properties file, it may not exactly reflect your hardware.
  */
 protected void populate() {
   // get list of ports available on this particular computer,
   // by calling static method in CommPortIdentifier.
   Enumeration pList = CommPortIdentifier.getPortIdentifiers();
   // Process the list, putting serial and parallel into ComboBoxes
   while (pList.hasMoreElements()) {
     CommPortIdentifier cpi = (CommPortIdentifier)pList.nextElement();
     // System.out.println("Port " + cpi.getName());
     map.put(cpi.getName(), cpi);
     if (cpi.getPortType() == CommPortIdentifier.PORT_SERIAL) {
       serialPortsChoice.setEnabled(true);
       serialPortsChoice.addItem(cpi.getName());
     } else if (cpi.getPortType() == CommPortIdentifier.PORT_PARALLEL) {
       parallelPortsChoice.setEnabled(true);
       parallelPortsChoice.addItem(cpi.getName());
     } else {
       other.setEnabled(true);
       other.addItem(cpi.getName());
     }
   }
   serialPortsChoice.setSelectedIndex(-1);
   parallelPortsChoice.setSelectedIndex(-1);
 }
 protected void finishGUI() {
   serialPortsChoice.addItemListener(this);
   parallelPortsChoice.addItemListener(this);
   other.addItemListener(this);
   pack();
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }

}


      </source>
   
  
 
  



Subclasses CommPortOpen and adds send/expect handling for dealing with Hayes-type modems

   <source lang="java">

import java.awt.BorderLayout; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.Enumeration; import java.util.HashMap; import javax.rum.rumPort; import javax.rum.rumPortIdentifier; import javax.rum.NoSuchPortException; import javax.rum.ParallelPort; import javax.rum.PortInUseException; import javax.rum.SerialPort; import javax.rum.UnsupportedCommOperationException; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /**

* Subclasses CommPortOpen and adds send/expect handling for dealing
* with Hayes-type modems.
*
* @author  Ian F. Darwin, http://www.darwinsys.ru/
*/
class CommPortModem extends CommPortOpen {
 /** The last line read from the serial port. */
 protected String response;
 /** A flag to control debugging output. */
 protected boolean debug = true;
 public CommPortModem(JFrame f)
   throws IOException, NoSuchPortException,PortInUseException,
     UnsupportedCommOperationException {
   super(f);
 }
 /** Send a line to a PC-style modem. Send \r\n, regardless of
  * what platform we"re on, instead of using println().
  */
 protected void send(String s) throws IOException {
   if (debug) {
     System.out.print(">>> ");
     System.out.print(s);
     System.out.println();
   }
   os.print(s);
   os.print("\r\n");
   // Expect the modem to echo the command.
   if (!expect(s)) {
     System.err.println("WARNING: Modem did not echo command.");
   }
   // The modem sends an extra blank line by way of a prompt.
   // Here we read and discard it.
   String junk = is.readLine();
   if (junk.length() != 0) {
     System.err.print("Warning: unexpected response: ");
     System.err.println(junk);
   }
 }
 /** Read a line, saving it in "response". 
  * @return true if the expected String is contained in the response, false if not.
  */
 protected boolean expect(String exp) throws IOException {
   response = is.readLine();
   if (debug) {
     System.out.print("<<< ");
     System.out.print(response);
     System.out.println();
   }
   return response.indexOf(exp) >= 0;
 }

} /**

* Dial a phone using the Java Communications Package.
*
* @author  Ian F. Darwin, http://www.darwinsys.ru/
*/

public class CommPortDial extends CommPortModem {

 protected static String number = "000-0000";
 public static void main(String[] ap)
   throws IOException, NoSuchPortException,PortInUseException,
     UnsupportedCommOperationException {
   if (ap.length == 1)
     number = ap[0];
   new CommPortDial().converse();
   System.exit(0);
 }
 public CommPortDial() 
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   super(null);
 }
 protected void converse() throws IOException {
   String resp;    // the modem response.
   // Send the reset command
   send("ATZ");
   expect("OK");
   send("ATDT" + number);
   expect("OK");
   try {
     Thread.sleep(5000);
   } catch (InterruptedException e) {
     // nothing to do
   }
   is.close();
   os.close();
 }

} class CommPortOpen {

 /** How long to wait for the open to finish up. */
 public static final int TIMEOUTSECONDS = 30;
 /** The baud rate to use. */
 public static final int BAUD = 19200;
 /** The parent JFrame, for the chooser. */
 protected JFrame parent;
 /** The input stream */
 protected BufferedReader is;
 /** The output stream */
 protected PrintStream os;
 /** The chosen Port Identifier */
 CommPortIdentifier thePortID;
 /** The chosen Port itself */
 CommPort thePort;
 public static void main(String[] argv)
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   new CommPortOpen(null).converse();
   System.exit(0);
 }
 /* Constructor */
 public CommPortOpen(JFrame f)
   throws IOException, NoSuchPortException, PortInUseException,
     UnsupportedCommOperationException {
   
   // Use the PortChooser from before. Pop up the JDialog.
   PortChooser chooser = new PortChooser(null);
   String portName = null;
   do {
     chooser.setVisible(true);
     
     // Dialog done. Get the port name.
     portName = chooser.getSelectedName();
     if (portName == null)
       System.out.println("No port selected. Try again.\n");
   } while (portName == null);
   // Get the CommPortIdentifier.
   thePortID = chooser.getSelectedIdentifier();
   // Now actually open the port.
   // This form of openPort takes an Application Name and a timeout.
   // 
   System.out.println("Trying to open " + thePortID.getName() + "...");
   switch (thePortID.getPortType()) {
   case CommPortIdentifier.PORT_SERIAL:
     thePort = thePortID.open("DarwinSys DataComm",
       TIMEOUTSECONDS * 1000);
     SerialPort myPort = (SerialPort) thePort;
     // set up the serial port
     myPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8,
       SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
     break;
   case CommPortIdentifier.PORT_PARALLEL:
     thePort = thePortID.open("DarwinSys Printing",
       TIMEOUTSECONDS * 1000);
     ParallelPort pPort = (ParallelPort)thePort;
     // Tell API to pick "best available mode" - can fail!
     // myPort.setMode(ParallelPort.LPT_MODE_ANY);
     // Print what the mode is
     int mode = pPort.getMode();
     switch (mode) {
       case ParallelPort.LPT_MODE_ECP:
         System.out.println("Mode is: ECP");
         break;
       case ParallelPort.LPT_MODE_EPP:
         System.out.println("Mode is: EPP");
         break;
       case ParallelPort.LPT_MODE_NIBBLE:
         System.out.println("Mode is: Nibble Mode.");
         break;
       case ParallelPort.LPT_MODE_PS2:
         System.out.println("Mode is: Byte mode.");
         break;
       case ParallelPort.LPT_MODE_SPP:
         System.out.println("Mode is: Compatibility mode.");
         break;
       // ParallelPort.LPT_MODE_ANY is a "set only" mode;
       // tells the API to pick "best mode"; will report the
       // actual mode it selected.
       default:
         throw new IllegalStateException("Parallel mode " + 
           mode + " invalid.");
     }
     break;
   default:  // Neither parallel nor serial??
     throw new IllegalStateException("Unknown port type " + thePortID);
   }
   // Get the input and output streams
   // Printers can be write-only
   try {
     is = new BufferedReader(new InputStreamReader(thePort.getInputStream()));
   } catch (IOException e) {
     System.err.println("Can"t open input stream: write-only");
     is = null;
   }
   os = new PrintStream(thePort.getOutputStream(), true);
 }
 /** This method will be overridden by non-trivial subclasses
  * to hold a conversation. 
  */
 protected void converse() throws IOException {
   System.out.println("Ready to read and write port.");
   // Input/Output code not written -- must subclass.
   // Finally, clean up.
   if (is != null)
     is.close();
   os.close();
 }

} class PortChooser extends JDialog implements ItemListener {

 /** A mapping from names to CommPortIdentifiers. */
 protected HashMap map = new HashMap();
 /** The name of the choice the user made. */
 protected String selectedPortName;
 /** The CommPortIdentifier the user chose. */
 protected CommPortIdentifier selectedPortIdentifier;
 /** The JComboBox for serial ports */
 protected JComboBox serialPortsChoice;
 /** The JComboBox for parallel ports */
 protected JComboBox parallelPortsChoice;
 /** The JComboBox for anything else */
 protected JComboBox other;
 /** The SerialPort object */
 protected SerialPort ttya;
 /** To display the chosen */
 protected JLabel choice;
 /** Padding in the GUI */
 protected final int PAD = 5;
 /** This will be called from either of the JComboBoxen when the
  * user selects any given item.
  */
 public void itemStateChanged(ItemEvent e) {
   // Get the name
   selectedPortName = (String)((JComboBox)e.getSource()).getSelectedItem();
   // Get the given CommPortIdentifier
   selectedPortIdentifier = (CommPortIdentifier)map.get(selectedPortName);
   // Display the name.
   choice.setText(selectedPortName);
 }
 /* The public "getter" to retrieve the chosen port by name. */
 public String getSelectedName() {
   return selectedPortName;
 }
 /* The public "getter" to retrieve the selection by CommPortIdentifier. */
 public CommPortIdentifier getSelectedIdentifier() {
   return selectedPortIdentifier;
 }
 /** A test program to show up this chooser. */
 public static void main(String[] ap) {
   PortChooser c = new PortChooser(null);
   c.setVisible(true);  // blocking wait
   System.out.println("You chose " + c.getSelectedName() +
     " (known by " + c.getSelectedIdentifier() + ").");
   System.exit(0);
 }
 /** Construct a PortChooser --make the GUI and populate the ComboBoxes.
  */
 public PortChooser(JFrame parent) {
   super(parent, "Port Chooser", true);
   makeGUI();
   populate();
   finishGUI();
 }
 /** Build the GUI. You can ignore this for now if you have not
  * yet worked through the GUI chapter. Your mileage may vary.
  */
 protected void makeGUI() {
   Container cp = getContentPane();
   JPanel centerPanel = new JPanel();
   cp.add(BorderLayout.CENTER, centerPanel);
   centerPanel.setLayout(new GridLayout(0,2, PAD, PAD));
   centerPanel.add(new JLabel("Serial Ports", JLabel.RIGHT));
   serialPortsChoice = new JComboBox();
   centerPanel.add(serialPortsChoice);
   serialPortsChoice.setEnabled(false);
   centerPanel.add(new JLabel("Parallel Ports", JLabel.RIGHT));
   parallelPortsChoice = new JComboBox();
   centerPanel.add(parallelPortsChoice);
   parallelPortsChoice.setEnabled(false);
   centerPanel.add(new JLabel("Unknown Ports", JLabel.RIGHT));
   other = new JComboBox();
   centerPanel.add(other);
   other.setEnabled(false);
   centerPanel.add(new JLabel("Your choice:", JLabel.RIGHT));
   centerPanel.add(choice = new JLabel());
   JButton okButton;
   cp.add(BorderLayout.SOUTH, okButton = new JButton("OK"));
   okButton.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       PortChooser.this.dispose();
     }
   });
 }
 /** Populate the ComboBoxes by asking the Java Communications API
  * what ports it has.  Since the initial information comes from
  * a Properties file, it may not exactly reflect your hardware.
  */
 protected void populate() {
   // get list of ports available on this particular computer,
   // by calling static method in CommPortIdentifier.
   Enumeration pList = CommPortIdentifier.getPortIdentifiers();
   // Process the list, putting serial and parallel into ComboBoxes
   while (pList.hasMoreElements()) {
     CommPortIdentifier cpi = (CommPortIdentifier)pList.nextElement();
     // System.out.println("Port " + cpi.getName());
     map.put(cpi.getName(), cpi);
     if (cpi.getPortType() == CommPortIdentifier.PORT_SERIAL) {
       serialPortsChoice.setEnabled(true);
       serialPortsChoice.addItem(cpi.getName());
     } else if (cpi.getPortType() == CommPortIdentifier.PORT_PARALLEL) {
       parallelPortsChoice.setEnabled(true);
       parallelPortsChoice.addItem(cpi.getName());
     } else {
       other.setEnabled(true);
       other.addItem(cpi.getName());
     }
   }
   serialPortsChoice.setSelectedIndex(-1);
   parallelPortsChoice.setSelectedIndex(-1);
 }
 protected void finishGUI() {
   serialPortsChoice.addItemListener(this);
   parallelPortsChoice.addItemListener(this);
   other.addItemListener(this);
   pack();
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }

}


      </source>