private boolean readFrame() throws IOException
		{
			final int len = is.read();
			final byte[] buf = new byte[len + 4];
			// read rest of frame, check header, ctrl, and end tag
			final int read = is.read(buf);
			if (read == len + 4 && (buf[0] & 0xff) == len && (buf[1] & 0xff) == START
					&& (buf[len + 3] & 0xff) == END) {
				final byte chk = buf[buf.length - 2];
				if (!checkCtrlField(buf[2] & 0xff, chk))
					return false;

				if (checksum(buf, 2, len) != chk)
					logger.warn("invalid checksum in frame " + DataUnitBuilder.toHex(buf, " "));
				else {
					sendAck();
					lastChecksum = chk;
					rcvFrameCount ^= FRAMECOUNT_BIT;
					final byte[] ldata = new byte[len - 1];
					for (int i = 0; i < ldata.length; ++i)
						ldata[i] = buf[3 + i];

					fireFrameReceived(ldata);
					return true;
				}
			}
			else
				logger.warn("invalid frame, discarded " + read + " bytes: "
						+ DataUnitBuilder.toHex(buf, " "));
			return false;
		}