"""
Emulating different virtual devices like keyboard, display, disks...
"""
import importlib
from ..interfaces import IMachineWorker
from ..mm import VirtualMemoryPage
[docs]class Device(IMachineWorker):
"""
Base class for all devices. Serves more like an API description.
:param ducky.machine.Machine machine: VM this device belongs to.
:param str klass: device family (input, output, snapshot, ...)
:param str name: device name. Maps directly to a section of config
file that hosts setup for this device.
"""
def __init__(self, machine, klass, name):
super(Device, self).__init__()
self.machine = machine
self.klass = klass
self.name = name
self.logger = machine.LOGGER
self.master = None
@staticmethod
[docs] def create_from_config(machine, config, section):
"""
Create new instance, configured exactly as requested by configuration file.
:param ducky.machine.Machine machine: VM this device belongs to.
:param ducky.config.MachineConfig config: configuration file.
:param str section: name of config section with this device's setup.
"""
raise NotImplementedError()
@staticmethod
[docs] def create_hdt_entries(logger, config, section):
"""
Create ``HDT`` entries for this device, based on configuration file.
:param logging.Logger logger: logger to use for logging.
:param ducky.config.MachineConfig config: configuration file.
:param str section: name of config section with this device's setup.
:rtype: ``list`` of :py:class:`ducky.hdt.HDTEntry`
:returns: list of ``HDT`` entries. This list is then appended to entries
of other devices.
"""
return []
[docs] def boot(self):
self.logger.debug('%s.boot', self.__class__.__name__)
pass
[docs] def halt(self):
self.logger.debug('%s.halt', self.__class__.__name__)
pass
[docs] def is_slave(self):
return self.master is not None
[docs] def get_master(self):
return self.master
[docs]class DeviceFrontend(Device):
"""
Frontend is a special component of a device, that interfaces communication
channels from user and internal queues.
"""
[docs] def set_backend(self, device):
"""
Set backend counterpart.
:param ducky.devices.DeviceFrontend device: backend part.
"""
self.backend = device
[docs]class DeviceBackend(Device):
"""
Backend is a special component of a device, which is connected to internal
queues, and processes events in the queue, originating from user via its
frontend counterpart.
"""
[docs] def set_frontend(self, device):
"""
Set frontend counterpart.
:param ducky.device.DeviceFrontend device: frontend part.
"""
self.frontend = device
[docs]class MMIOMemoryPage(VirtualMemoryPage):
"""
Memory page, suited for memory-mapped IO, supported by a device driver.
:param ducky.devices.Device device: device instance, backing this memory
page.
"""
def __init__(self, device, *args, **kwargs):
super(MMIOMemoryPage, self).__init__(*args, **kwargs)
self._device = device
[docs]def get_driver(driver_class):
"""
Get Python class, implementing device driver, by its name.
:param str driver_class: path to a class, e.g. ``ducky.devices.rtc.RTC``.
:returns: driver class.
"""
driver = driver_class.split('.')
driver_module = importlib.import_module('.'.join(driver[0:-1]))
driver_class = getattr(driver_module, driver[-1])
return driver_class