Connects to the J-Link emulator (defaults to USB).

        If ``serial_no`` and ``ip_addr`` are both given, this function will
        connect to the J-Link over TCP/IP.

        Args:
          self (JLink): the ``JLink`` instance
          serial_no (int): serial number of the J-Link
          ip_addr (str): IP address and port of the J-Link (e.g. 192.168.1.1:80)

        Returns:
          ``None``

        Raises:
          JLinkException: if fails to open (i.e. if device is unplugged)
          TypeError: if ``serial_no`` is present, but not ``int`` coercible.
          AttributeError: if ``serial_no`` and ``ip_addr`` are both ``None``.

def open(self, serial_no=None, ip_addr=None):
        """Connects to the J-Link emulator (defaults to USB).

        If ``serial_no`` and ``ip_addr`` are both given, this function will
        connect to the J-Link over TCP/IP.

        Args:
          self (JLink): the ``JLink`` instance
          serial_no (int): serial number of the J-Link
          ip_addr (str): IP address and port of the J-Link (e.g. 192.168.1.1:80)

        Returns:
          ``None``

        Raises:
          JLinkException: if fails to open (i.e. if device is unplugged)
          TypeError: if ``serial_no`` is present, but not ``int`` coercible.
          AttributeError: if ``serial_no`` and ``ip_addr`` are both ``None``.
        """

        # For some reason, the J-Link driver complains if this isn't called
        # first (may have something to do with it trying to establish a
        # connection).  Without this call, it will log an error stating
        #        NET_WriteRead(): USB communication not locked
        #        PID0017A8C (): Lock count error (decrement)
        self.close()

        if ip_addr is not None:
            addr, port = ip_addr.rsplit(':', 1)
            if serial_no is None:
                result = self._dll.JLINKARM_SelectIP(addr.encode(), int(port))
                if result == 1:
                    raise errors.JLinkException('Could not connect to emulator at %s.' % ip_addr)
            else:
                # Note: No return code when selecting IP by serial number.
                self._dll.JLINKARM_EMU_SelectIPBySN(int(serial_no))

        elif serial_no is not None:
            result = self._dll.JLINKARM_EMU_SelectByUSBSN(int(serial_no))
            if result < 0:
                raise errors.JLinkException('No emulator with serial number %s found.' % serial_no)

        else:
            # The original method of connecting to USB0-3 via
            # JLINKARM_SelectUSB has been obsolesced, however its use is
            # preserved here to simplify workflows using one emulator:
            result = self._dll.JLINKARM_SelectUSB(0)
            if result != 0:
                raise errors.JlinkException('Could not connect to default emulator.')

        # Acquire the lock for the J-Link being opened only if the serial
        # number was passed in, otherwise skip it here.  Note that the lock
        # must be acquired before calling 'JLINKARM_OpenEx()', otherwise the
        # call will fail on Windows.
        if serial_no is not None:
            self._lock = jlock.JLock(serial_no)
            if not self._lock.acquire():
                raise errors.JLinkException('J-Link is already open.')

        result = self._dll.JLINKARM_OpenEx(self.log_handler, self.error_handler)
        result = ctypes.cast(result, ctypes.c_char_p).value
        if result is not None:
            raise errors.JLinkException(result.decode())

        # Configuration of the J-Link DLL.  These are configuration steps that
        # have to be done after 'open()'.  The unsecure hook is only supported
        # on versions greater than V4.98a.
        unsecure_hook = self._unsecure_hook
        if unsecure_hook is not None and hasattr(self._dll, 'JLINK_SetHookUnsecureDialog'):
            func = enums.JLinkFunctions.UNSECURE_HOOK_PROTOTYPE(unsecure_hook)
            self._dll.JLINK_SetHookUnsecureDialog(func)

        return None