def _read_frame(self, length):
        """Read a response frame from the PN532 of at most length bytes in size.
        Returns the data inside the frame if found, otherwise raises an exception
        if there is an error parsing the frame.  Note that less than length bytes
        might be returned!
        """
        # Read frame with expected length of data.
        response = self._read_data(length+8)
        logger.debug('Read frame: 0x{0}'.format(binascii.hexlify(response)))
        # Check frame starts with 0x01 and then has 0x00FF (preceeded by optional
        # zeros).
        if response[0] != 0x01:
            raise RuntimeError('Response frame does not start with 0x01!')
        # Swallow all the 0x00 values that preceed 0xFF.
        offset = 1
        while response[offset] == 0x00:
            offset += 1
            if offset >= len(response):
                raise RuntimeError('Response frame preamble does not contain 0x00FF!')
        if response[offset] != 0xFF:
            raise RuntimeError('Response frame preamble does not contain 0x00FF!')
        offset += 1
        if offset >= len(response):
                raise RuntimeError('Response contains no data!')
        # Check length & length checksum match.
        frame_len = response[offset]
        if (frame_len + response[offset+1]) & 0xFF != 0:
            raise RuntimeError('Response length checksum did not match length!')
        # Check frame checksum value matches bytes.
        checksum = reduce(self._uint8_add, response[offset+2:offset+2+frame_len+1], 0)
        if checksum != 0:
            raise RuntimeError('Response checksum did not match expected value!')
        # Return frame data.
        return response[offset+2:offset+2+frame_len]
Read a response frame from the PN532 of at most length bytes in size.
        Returns the data inside the frame if found, otherwise raises an exception
        if there is an error parsing the frame.  Note that less than length bytes
        might be returned!