def connect(self, **options):
        """Connect with a contactless target or become connected as a
        contactless target. The calling thread is blocked until a
        single activation and deactivation has completed or a callback
        function supplied as the keyword argument ``terminate``
        returned True. The result of the terminate function also
        applies to the loop run after activation, so the example below
        will make :meth:`~connect()` return after 10 seconds from
        either waiting for a peer device or when connected. ::

        >>> import nfc, time
        >>> clf = nfc.ContactlessFrontend('usb')
        >>> after5s = lambda: time.time() - started > 5
        >>> started = time.time(); clf.connect(llcp={}, terminate=after5s)

        Connect options are given as keyword arguments with dictionary
        values. Possible options are:
        
        * ``rdwr={key: value, ...}`` - options for reader/writer operation
        * ``llcp={key: value, ...}`` - options for peer to peer mode operation
        * ``card={key: value, ...}`` - options for card emulation operation

        **Reader/Writer Options**

        'targets': sequence
          A list of target specifications with each target of either
          type :class:`~nfc.clf.TTA`, :class:`~nfc.clf.TTB`, or
          :class:`~nfc.clf.TTF`. A default set is choosen if 'targets'
          is not provided.
          
        'on-startup': function
          A function that will be called with the list of targets
          (from 'targets') to search for. Must return a list of
          targets or :const:`None`. Only the targets returned are
          finally considered.
          
        'on-connect': function
          A function object that will be called with an activated
          :class:`~nfc.tag.Tag` object.
        
        >>> import nfc
        >>> def connected(tag):
        ...     print tag
        ...     return True
        ...
        >>> clf = nfc.ContactlessFrontend()
        >>> clf.connect(rdwr={'on-connect': connected})
        Type3Tag IDm=01010501b00ac30b PMm=03014b024f4993ff SYS=12fc
        True
        
        **Peer To Peer Options**

        'on-startup': function
          A function that is called before an attempt is made to
          establish peer to peer communication. The function receives
          the initialized :class:`~nfc.llcp.llc.LogicalLinkController`
          instance as parameter, which may then be used to allocate
          and bind communication sockets for service applications. The
          return value must be either the
          :class:`~nfc.llcp.llc.LogicalLinkController` instance or
          :const:`None` to effectively remove llcp from the options
          considered.
          
        'on-connect': function
          A function that is be called when peer to peer communication
          was established. The function receives the connected
          :class:`~nfc.llcp.llc.LogicalLinkController` instance as
          parameter, which may then be used to allocate communication
          sockets with
          :meth:`~nfc.llcp.llc.LogicalLinkController.socket` and spawn
          working threads to perform communication. The callback must
          return more or less immediately with :const:`True` unless
          the logical link controller run loop is handled within the
          callback.
          
        'role': string
          Defines which role the local LLC shall take for the data
          exchange protocol activation. Possible values are
          'initiator' and 'target'.  The default is to alternate
          between both roles until communication is established.
          
        'miu': integer
          Defines the maximum information unit size that will be
          supported and announced to the remote LLC. The default value
          is 128.
          
        'lto': integer
          Defines the link timeout value (in milliseconds) that will
          be announced to the remote LLC. The default value is 100
          milliseconds.
          
        'agf': boolean
          Defines if the local LLC performs PDU aggregation and may
          thus send Aggregated Frame (AGF) PDUs to the remote LLC. The
          dafault is to use aggregation.
        
        >>> import nfc
        >>> import threading
        >>> def worker(socket):
        ...     socket.sendto("Hi there!", address=16)
        ...     socket.close()
        ...
        >>> def connected(llc):
        ...     socket = llc.socket(nfc.llcp.LOGICAL_DATA_LINK)
        ...     threading.Thread(target=worker, args=(socket,)).start()
        ...     return True
        ...
        >>> clf = nfc.ContactlessFrontend()
        >>> clf.connect(llcp={'on-connect': connected})
        
        **Card Emulation Options**

        'targets': sequence
          A list of target specifications with each target of either
          type :class:`~nfc.clf.TTA`, :class:`~nfc.clf.TTB`, or
          :class:`~nfc.clf.TTF`. The list of targets is processed
          sequentially. Defaults to an empty list.
          
        'on-startup': function
          A function that will be called with the list of targets
          (from 'targets') to emulate. Must return a list of one
          target choosen or :const:`None`.
          
        'on-connect': function
          A function that will be called with an activated
          :class:`~nfc.tag.TagEmulation` instance as first parameter and
          the first command received as the second parameter.

        'on-release': function A function that will be called when the
          activated tag has been released by it's Initiator, basically
          that is when the tag has been removed from the Initiator's
          RF field.

        'timeout': integer
          The timeout in seconds to wait for for each target to become
          initialized. The default value is 1 second.

        >>> import nfc
        >>>
        >>> def connected(tag, command):
        ...     print tag
        ...     print str(command).encode("hex")
        ...
        >>> clf = nfc.ContactlessFrontend()
        >>> idm = bytearray.fromhex("01010501b00ac30b")
        >>> pmm = bytearray.fromhex("03014b024f4993ff")
        >>> sys = bytearray.fromhex("12fc")
        >>> target = nfc.clf.TTF(212, idm, pmm, sys)
        >>> clf.connect(card={'targets': [target], 'on-connect': connected})
        Type3TagEmulation IDm=01010501b00ac30b PMm=03014b024f4993ff SYS=12fc
        100601010501b00ac30b010b00018000
        True
        
        Connect returns :const:`None` if no options were to execute,
        :const:`False` if interrupted by a :exc:`KeyboardInterrupt`,
        or :const:`True` if terminated normally and the 'on-connect'
        callback function had returned :const:`True`. If the
        'on-connect' callback had returned :const:`False` the return
        value of connect() is the same parameters as were provided to
        the callback function.

        Connect raises :exc:`IOError(errno.ENODEV)` if called before a
        contactless reader was opened.
        """
        if self.dev is None:
            raise IOError(errno.ENODEV, os.strerror(errno.ENODEV))
        
        log.debug("connect({0})".format(options))

        terminate = options.get('terminate', lambda: False)
        rdwr_options = options.get('rdwr')
        llcp_options = options.get('llcp')
        card_options = options.get('card')

        if isinstance(rdwr_options, dict):
            rdwr_options.setdefault('targets', [
                    TTA(br=106, cfg=None, uid=None), TTB(br=106),
                    TTF(br=424, idm=None, pmm=None, sys=None),
                    TTF(br=212, idm=None, pmm=None, sys=None)])
            if 'on-startup' in rdwr_options:
                targets = rdwr_options.get('targets')
                targets = rdwr_options['on-startup'](self, targets)
                if targets is None: rdwr_options = None
                else: rdwr_options['targets'] = targets
            if rdwr_options is not None:
                if not 'on-connect' in rdwr_options:
                    rdwr_options['on-connect'] = lambda tag: True
        elif rdwr_options is not None:
            raise TypeError("argument *rdrw* must be a dictionary")
        
        if isinstance(llcp_options, dict):
            llc = nfc.llcp.llc.LogicalLinkController(
                recv_miu=llcp_options.get('miu', 128),
                send_lto=llcp_options.get('lto', 100),
                send_agf=llcp_options.get('agf', True),
                symm_log=llcp_options.get('symm-log', True))
            if 'on-startup' in llcp_options:
                llc = llcp_options['on-startup'](self, llc)
                if llc is None: llcp_options = None
            if llcp_options is not None:
                if not 'on-connect' in llcp_options:
                    llcp_options['on-connect'] = lambda llc: True
        elif llcp_options is not None:
            raise TypeError("argument *llcp* must be a dictionary")

        if isinstance(card_options, dict):
            if 'on-startup' in card_options:
                targets = card_options.get('targets', [])
                targets = card_options['on-startup'](self, targets)
                if targets is None: card_options = None
                else: card_options['targets'] = targets
            if card_options is not None:
                if not card_options.get('targets'):
                    log.error("a target must be specified to connect as tag")
                    return None
                if not 'on-connect' in card_options:
                    card_options['on-connect'] = lambda tag, command: True
        elif card_options is not None:
            raise TypeError("argument *card* must be a dictionary")

        some_options = rdwr_options or llcp_options or card_options
        if not some_options:
            log.warning("no options left to connect")
            return None
        
        try:
            while not terminate():
                if llcp_options:
                    result = self._llcp_connect(llcp_options, llc, terminate)
                    if bool(result) is True: return result
                if rdwr_options:
                    result = self._rdwr_connect(rdwr_options, terminate)
                    if bool(result) is True: return result
                if card_options:
                    result = self._card_connect(card_options, terminate)
                    if bool(result) is True: return result
        except KeyboardInterrupt as error:
            log.debug(error)
            return False
        except __HOLE__ as error:
            log.error(error)
            return False
dataset/ETHPy150Open javgh/greenaddress-pos-tools/nfc/clf.py/ContactlessFrontend.connect