public void connect(ConnectionData connectionData) {
    mLogger.debug("Connect");
    mConnectionData = connectionData;
    mState = State.INITIALIZED;

    addPacketListener(mPacketListener);

    // try to connect
    try {
      mDriver.connect(mConnectionData);
    } catch (IOException ioe) {
      mLogger.debug(ioe.getMessage());
      //            notifyConnectionFailed("Connection failed: " + ioe.getMessage());
      disconnect();
    } catch (IllegalArgumentException iae) {
      mLogger.debug(iae.getMessage());
      //            notifyConnectionFailed("Connection failed: " + iae.getMessage());
      disconnect();
    }

    if (mIncomingPacketHandlerThread == null) {
      IncomingPacketHandler iph = new IncomingPacketHandler();
      mIncomingPacketHandlerThread = new Thread(iph);
      mIncomingPacketHandlerThread.start();
    }

    if (mResendQueueHandlerThread == null) {
      ResendQueueHandler rqh = new ResendQueueHandler();
      mResendQueueHandlerThread = new Thread(rqh);
      mResendQueueHandlerThread.start();
    }
  }
  // def send_packet(self, pk, expected_reply=(), resend=False):
  public void sendPacket(CrtpPacket packet) {
    if (mDriver != null) {
      mDriver.sendPacket(packet);

      if (packet.getExpectedReply() != null && packet.getExpectedReply().length > 0) {
        // add packet to resend queue
        if (!mResendQueue.contains(packet)) {
          mResendQueue.add(packet);
        } else {
          mLogger.warn("Packet already exists in Queue.");
        }
      }
    }
  }
  public void disconnect() {
    if (mState != State.DISCONNECTED) {
      mLogger.debug("Disconnect");

      if (mDriver != null) {
        // Send commander packet with all values set to 0 before closing the connection
        sendPacket(new CommanderPacket(0, 0, 0, (char) 0));
        mDriver.disconnect();
        mDriver = null;
      }
      if (mIncomingPacketHandlerThread != null) {
        mIncomingPacketHandlerThread.interrupt();
      }
      if (mResendQueueHandlerThread != null) {
        mResendQueueHandlerThread.interrupt();
      }
      removePacketListener(mPacketListener);
      mState = State.DISCONNECTED;
    }
  }
  /** Start the connection setup by refreshing the TOCs */
  public void startConnectionSetup() {
    mLogger.info(
        "We are connected [" + mConnectionData.toString() + "], requesting connection setup...");

    mState = State.SETUP_FINISHED;
    // TODO: fix hacky-di-hack
    mDriver.notifySetupFinished();

    //        mParam = new Param(this);
    //        //must be defined first to be usable in Log TocFetchFinishedListener
    //        final TocFetchFinishedListener paramTocFetchFinishedListener = new
    // TocFetchFinishedListener() {
    //            public void tocFetchFinished() {
    //                //_param_toc_updated_cb(self):
    //                mLogger.info("Param TOC finished updating.");
    //                //mParam.requestUpdateOfAllParams();
    //                //TODO: should be set only after log, param, mems are all updated
    //                mState = State.SETUP_FINISHED;
    //                notifySetupFinished();
    //            }
    //        };
    //
    //        mLogg = new Logg(this);
    //        TocFetchFinishedListener loggTocFetchFinishedListener = new TocFetchFinishedListener()
    // {
    //            public void tocFetchFinished() {
    //                mLogger.info("Logg TOC finished updating.");
    //
    //                //after log toc has been fetched, fetch param toc
    //                mParam.refreshToc(paramTocFetchFinishedListener, mTocCache);
    //            }
    //        };
    //        //mLog.refreshToc(self._log_toc_updated_cb, self._toc_cache);
    //        mLogg.refreshToc(loggTocFetchFinishedListener, mTocCache);

    // TODO: self.mem.refresh(self._mems_updated_cb)
  }