r"""Read data from the endpoint.

        This method is used to receive data from the device. The endpoint
        parameter corresponds to the bEndpointAddress member whose endpoint
        you want to communicate with. The size_or_buffer parameter either
        tells how many bytes you want to read or supplies the buffer to
        receive the data (it *must* be an object of the type array).

        The timeout is specified in miliseconds.

        If the size_or_buffer parameter is the number of bytes to read, the
        method returns an array object with the data read. If the
        size_or_buffer parameter is an array object, it returns the number
        of bytes actually read.

def read(self, endpoint, size_or_buffer, timeout = None):
        r"""Read data from the endpoint.

        This method is used to receive data from the device. The endpoint
        parameter corresponds to the bEndpointAddress member whose endpoint
        you want to communicate with. The size_or_buffer parameter either
        tells how many bytes you want to read or supplies the buffer to
        receive the data (it *must* be an object of the type array).

        The timeout is specified in miliseconds.

        If the size_or_buffer parameter is the number of bytes to read, the
        method returns an array object with the data read. If the
        size_or_buffer parameter is an array object, it returns the number
        of bytes actually read.
        """
        backend = self._ctx.backend

        fn_map = {
                    util.ENDPOINT_TYPE_BULK:backend.bulk_read,
                    util.ENDPOINT_TYPE_INTR:backend.intr_read,
                    util.ENDPOINT_TYPE_ISO:backend.iso_read
                }

        intf, ep = self._ctx.setup_request(self, endpoint)
        fn = fn_map[util.endpoint_type(ep.bmAttributes)]

        if isinstance(size_or_buffer, array.array):
            buff = size_or_buffer
        else: # here we consider it is a integer
            buff = util.create_buffer(size_or_buffer)

        ret = fn(
                self._ctx.handle,
                ep.bEndpointAddress,
                intf.bInterfaceNumber,
                buff,
                self.__get_timeout(timeout))

        if isinstance(size_or_buffer, array.array):
            return ret
        elif ret != len(buff) * buff.itemsize:
            return buff[:ret]
        else:
            return buff