public void send(final byte[] frame, final boolean waitForCon)
		throws KNXPortClosedException, KNXAckTimeoutException, InterruptedException
	{
		final boolean group = (frame[3] & 0x80) == 0x80;
		KNXAddress dst = null;
		if (group) {
			dst = new GroupAddress(new byte[] { frame[6], frame[7] });
			addresses.add(dst);
		}

		try {
			final byte[] data = toUartServices(cEmiToTP1(frame));
			if (logger.isLoggable(LogLevel.TRACE))
				logger.trace("UART services " + DataUnitBuilder.toHex(data, " "));
			req = (byte[]) frame.clone();
			final long start = System.nanoTime();
			synchronized (enterIdleLock) {
				if (!idle)
					enterIdleLock.wait();
			}
			if (logger.isLoggable(LogLevel.TRACE)) {
				logger.trace("UART ready for sending after " + (System.nanoTime() - start) / 1000 + " us");
				logger.trace("write UART services, " + (waitForCon ? "waiting for .con" : "non-blocking"));
			}
			os.write(data);
			state = ConPending;
			if (!waitForCon)
				return;
			if (waitForCon())
				return;
			throw new KNXAckTimeoutException("no ACK for L-Data.con");
		}
		catch (final InterruptedIOException e) {
			throw new InterruptedException(e.getMessage());
		}
		catch (final IOException e) {
			close();
			throw new KNXPortClosedException("I/O error", portId, e);
		}
		finally {
			req = null;
			addresses.remove(dst);
		}
	}