⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tosserial.java

📁 tinyos2.0版本驱动
💻 JAVA
字号:
//$Id: TOSSerial.java,v 1.6 2007/05/24 19:55:12 rincon Exp $/* "Copyright (c) 2000-2003 The Regents of the University of California.   * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement * is hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. *  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." *///@author Cory Sharp <cssharp@eecs.berkeley.edu>package net.tinyos.comm;import java.io.*;import java.util.*;import java.util.regex.*;public class TOSSerial extends NativeSerial implements SerialPort {  /**   * Inner Class to handle serial event dispatching   *    */  class EventDispatcher extends Thread {    private boolean m_run;    private boolean busy;    /**     * Constructor     *      */    public EventDispatcher() {      busy = false;      m_run = true;    }    /**     * Start waiting for events     *      */    public void open() {      synchronized (this) {        m_run = true;        this.notify();      }    }    /**     * Stop waiting for events     * Here's the deal: we're running a thread here that is calling     * a function waitForEvent() in the toscomm driver.  We're now waiting for      * two events: DATA_AVAILABLE and OUTPUT_EMPTY.  If you call cancelWait(),      * nothing happens until the waitForEvent() returns by getting an event      * anyway, so if our node isn't generating bytes on its own, we need to     * force it to make an event so we can get out of that function to avoid     * a driver crash.     *      * Previously, it never returned because there were no events.  Now we     * make an event by adding notifyOn(OUTPUT_EMPTY) and then writing a      * standard 0x7E sync byte to the serial port and let it tell us that      * an event occured.         *      * When the waitForEvent() function finally exits, we are then able to      * tell it, "Oh yea, while you're at it, cancelWait()".  Finally, the     * EventDispatcher is in a state where the driver is not sitting around     * waiting for an event to occur. At that point, we can shut down the     * NativeSerial by calling super.close() elsewhere.      *      * As far as I can tell, this is the only way to make this work without     * modifying the actual toscomm driver.     *      * The only other trick I can see to this is sometimes you can't connect     * immediately after you disconnect.. I added a wait(500) after a disconnect     * more toward my application layer to prevent my app from trying to     * reconnect immediately. My JUnit tests, for example, disconnect and     * reconnect very rapidly as you would expect.      */    public void close() {      m_run = false;            synchronized (this) {        while (busy) {          write(0x7E);          cancelWait();          try {            // Wait for the waitForEvent() done event, if it doesn't work after            // 500 ms, then we try generating that OUTPUT_EMPTY event again.            wait(500);          } catch (InterruptedException e) {            e.printStackTrace();          }        }      }    }    /**     * Dispatch the event if it really occured     *      * @param event     */    private void dispatch_event(int event) {      if (didEventOccur(event)) {        SerialPortEvent ev = new SerialPortEvent(TOSSerial.this, event);        synchronized (m_listeners) {          Iterator i = m_listeners.iterator();          while (i.hasNext())            ((SerialPortListener) i.next()).serialEvent(ev);        }      }    }    public void run() {      while (true) {        synchronized (this) {          while (!m_run) {            try {              busy = false;              synchronized (this) {                this.notify();              }              this.wait();            } catch (InterruptedException e) {              e.printStackTrace();            }          }        }        busy = true;        if (waitForEvent()) {          dispatch_event(SerialPortEvent.DATA_AVAILABLE);          dispatch_event(SerialPortEvent.OUTPUT_EMPTY);        }      }    }  }  /**   * Inner Serial Input Stream Class   *    */  class SerialInputStream extends InputStream {    ByteQueue bq = new ByteQueue(128);    protected void gather() {      int navail = TOSSerial.this.available();      if (navail > 0) {        byte buffer[] = new byte[navail];        bq.push_back(buffer, 0, TOSSerial.this.read(buffer, 0, navail));      }    }    public int read() {      gather();      return bq.pop_front();    }    public int read(byte[] b) {      gather();      return bq.pop_front(b);    }    public int read(byte[] b, int off, int len) {      gather();      return bq.pop_front(b, off, len);    }    public int available() {      gather();      return bq.available();    }  }  /**   * Inner Serial Output Stream Class   *    */  class SerialOutputStream extends OutputStream {    public void write(int b) {      TOSSerial.this.write(b);    }    public void write(byte[] b) {      TOSSerial.this.write(b, 0, b.length);    }    public void write(byte[] b, int off, int len) {      int nwritten = 0;      while (nwritten < len)        nwritten += TOSSerial.this.write(b, nwritten, len - nwritten);    }  }  private SerialInputStream m_in;  private SerialOutputStream m_out;  private Vector m_listeners = new Vector();  private EventDispatcher m_dispatch;  static String map_portname(String mapstr, String portname) {    // mapstr is of the form "from1=to1:from2=to2"    // If "from", "to", and "portname" all end port numbers, then the ports in    // "from" and "to" are used as a bias for the port in "portname", appended    // to the "to" string (without its original terminating digits). If more    // than one port mapping matches, the one with the smallest non-negative    // port number wins.    // For instance, if    // mapstr="com1=COM1:com10=\\.\COM10"    // then    // com1 => COM1    // com3 => COM3    // com10 => \\.\COM10    // com12 => \\.\COM12    // or if    // mapstr="com1=/dev/ttyS0:usb1=/dev/ttyS100"    // then    // com1 => /dev/ttyS0    // com3 => /dev/ttyS2    // usb1 => /dev/ttyS100    // usb3 => /dev/ttyS102    String maps[] = mapstr.split(":");    Pattern pkv = Pattern.compile("(.*?)=(.*?)");    Pattern pnum = Pattern.compile("(.*\\D)(\\d+)");    Matcher mport = pnum.matcher(portname);    int match_distance = -1;    String str_port_to = null;    for (int i = 0; i < maps.length; i++) {      Matcher mkv = pkv.matcher(maps[i]);      if (mkv.matches()) {        Matcher mfrom = pnum.matcher(mkv.group(1));        Matcher mto = pnum.matcher(mkv.group(2));        if (mfrom.matches() && mto.matches() && mport.matches()            && mfrom.group(1).equalsIgnoreCase(mport.group(1))) {          int nfrom = Integer.parseInt(mfrom.group(2));          int nto = Integer.parseInt(mto.group(2));          int nport_from = Integer.parseInt(mport.group(2));          int nport_to = nport_from - nfrom + nto;          int ndist = nport_from - nfrom;          if ((ndist >= 0)              && ((ndist < match_distance) || (match_distance == -1))) {            match_distance = ndist;            str_port_to = mto.group(1) + nport_to;          }        } else if (mkv.group(1).equalsIgnoreCase(portname)) {          match_distance = 0;          str_port_to = mkv.group(2);        }      }    }    return (str_port_to == null) ? portname : str_port_to;  }  /**   * Real Constructor of TOSSerial   *    * @param portname   */  public TOSSerial(String portname) {    super(map_portname(NativeSerial.getTOSCommMap(), portname));    m_in = new SerialInputStream();    m_out = new SerialOutputStream();    m_dispatch = new EventDispatcher();    m_dispatch.start();  }  /**   * Open the serial port connection   */  public boolean open() {    if (m_dispatch != null) {      m_dispatch.open();    }    return super.open();  }  /**   * Close the serial port connection   */  public void close() {    if (m_dispatch != null) {      m_dispatch.close();    }    super.close();  }  public void addListener(SerialPortListener l) {    synchronized (m_listeners) {      if (!m_listeners.contains(l))        m_listeners.add(l);    }  }  public void removeListener(SerialPortListener l) {    synchronized (m_listeners) {      m_listeners.remove(l);    }  }  public InputStream getInputStream() {    return m_in;  }  public OutputStream getOutputStream() {    return m_out;  }  /**   * Finalize the serial port connection, do not expect to open it again   */  public void finalize() {    // Be careful what you call here. The object may never have been    // created, so the underlying C++ object may not exist, and there's    // insufficient guarding to avoid a core dump. If you call other    // methods than super.close() or super.finalize(), be sure to    // add an if (swigCptr != 0) guard in NativeSerial.java.    if (m_dispatch != null) {      m_dispatch.close();    }    /*     * try { if (m_dispatch != null) { m_dispatch.join(); } } catch     * (InterruptedException e) { }     */    super.close();    try {      if (m_in != null) {        m_in.close();      }      if (m_out != null) {        m_out.close();      }    } catch (IOException e) {    }    m_dispatch = null;    m_in = null;    m_out = null;    super.finalize();  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -