text: """
  Copyright 2016 ARM Limited
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  """
  
  # python 3 compatibility
  # pylint: disable=superfluous-parens
  
  import logging
  
  from serial.serialutil import SerialException
  from mbed_flasher.flashers.enhancedserial import EnhancedSerial
  from mbed_flasher.common import Common, ResetError
  from mbed_flasher.return_codes import EXIT_CODE_SUCCESS
  from mbed_flasher.return_codes import EXIT_CODE_COULD_NOT_MAP_TARGET_ID_TO_DEVICE
  from mbed_flasher.return_codes import EXIT_CODE_IMPLEMENTATION_MISSING
  from mbed_flasher.return_codes import EXIT_CODE_PYOCD_MISSING
  from mbed_flasher.return_codes import EXIT_CODE_PYOCD_RESET_FAILED
  from mbed_flasher.return_codes import EXIT_CODE_MISUSE_CMD
  from mbed_flasher.return_codes import EXIT_CODE_SERIAL_PORT_OPEN_FAILED
  from mbed_flasher.return_codes import EXIT_CODE_SERIAL_RESET_FAILED
  from mbed_flasher.return_codes import EXIT_CODE_TARGET_ID_MISSING
  
  
  class Reset(object):
      """ Reset object, which manages reset for given devices
      """
      _flashers = []
  
      def __init__(self, logger=None):
          self.logger = logger if logger else logging.getLogger("mbed-flasher")
          self._flashers = self.__get_flashers()
  
      def get_available_device_mapping(self):
          """
          Get available devices
          :return: list of devices
          """
          return Common(self.logger).get_available_device_mapping(self._flashers)
  
      @staticmethod
      def __get_flashers():
          """
          :return: available flashers
          """
          from mbed_flasher.flashers import AvailableFlashers
          return AvailableFlashers
  
      def reset_board(self, serial_port):
          """
          :param serial_port: serial port
          :return: return exit code if failed
          """
          try:
              port = EnhancedSerial(serial_port)
          except SerialException as err:
              self.logger.info("reset could not be sent")
              self.logger.error(err)
              # SerialException.message is type "string"
              # pylint: disable=no-member
              if err.message.find('could not open port') != -1:
                  self.logger.error(
                      "Reset could not be given. Close your Serial connection to device.")
  
              raise ResetError(message="Reset failed",
                               return_code=EXIT_CODE_SERIAL_PORT_OPEN_FAILED)
  
          port.baudrate = 115200
          port.timeout = 1
          port.xonxoff = False
          port.rtscts = False
          port.flushInput()
          port.flushOutput()
  
          if port:
              self.logger.info("sendBreak to device to reboot")
              result = port.safe_send_break()
              if result:
                  self.logger.info("reset completed")
              else:
                  raise ResetError(message="Reset failed",
                                   return_code=EXIT_CODE_SERIAL_RESET_FAILED)
  
          port.close()
  
      def reset(self, target_id=None, method=None):
          """Reset (mbed) device
          :param target_id: target_id
          :param method: method for reset i.e. simple, pyocd or edbg
          """
          if target_id is None:
              raise ResetError(message="Target ID is missing",
                               return_code=EXIT_CODE_TARGET_ID_MISSING)
  
          self.logger.info("Starting reset for target_id %s", target_id)
          self.logger.info("Method for reset: %s", method)
          available_devices = Common(self.logger).get_available_device_mapping(
              self._flashers, target_id)
  
          targets_to_reset = self.prepare_target_to_reset(target_id, available_devices)
  
          if len(targets_to_reset) <= 0:
              msg = "Could not map given target_id(s) to available devices"
              self.logger.error(msg)
              raise ResetError(message=msg, return_code=EXIT_CODE_COULD_NOT_MAP_TARGET_ID_TO_DEVICE)
  
          for item in targets_to_reset:
              if method == 'simple' and 'serial_port' in item:
                  self.reset_board(item['serial_port'])
              elif method == 'pyocd':
                  return self.try_pyocd_reset(item)
              elif method == 'edbg':
                  raise ResetError(message="egdb not supported",
                                   return_code=EXIT_CODE_IMPLEMENTATION_MISSING)
              else:
                  raise ResetError(message="Selected method {} not supported".format(method),
                                   return_code=EXIT_CODE_MISUSE_CMD)
  
          return EXIT_CODE_SUCCESS
  
      @staticmethod
      def prepare_target_to_reset(target_id, available_devices):
          """
          prepare target to reset
          """
          targets_to_reset = []
  
          if isinstance(target_id, list):
              for target in target_id:
                  for device in available_devices:
                      if target == device['target_id'] and \
                                      device not in targets_to_reset:
                          targets_to_reset.append(device)
          else:
              if target_id == 'all':
                  targets_to_reset = available_devices
              elif len(target_id) <= 48:
                  for device in available_devices:
                      if (target_id == device['target_id'] or
                              device['target_id'].startswith(target_id)) and \
                                      device not in targets_to_reset:
                          targets_to_reset.append(device)
          return targets_to_reset
  
      def try_pyocd_reset(self, item):
          """
          try pyOCD reset
          """
          try:
              from pyOCD.board import MbedBoard
          except ImportError:
              raise ResetError(message="pyOCD is not installed",
                               return_code=EXIT_CODE_PYOCD_MISSING)
  
          try:
              with MbedBoard.chooseBoard(board_id=item["target_id"]) \
                      as board:
                  self.logger.info("resetting device")
                  ocd_target = board.target
                  ocd_target.reset()
                  self.logger.info("reset completed")
              return EXIT_CODE_SUCCESS
          except AttributeError as err:
              self.logger.error("PyOCD reset failed: %s.", err)
              self.logger.error("tid=%s", item["target_id"])
              raise ResetError(message="PyOCD reset failed",
                               return_code=EXIT_CODE_PYOCD_RESET_FAILED)
  