/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2016 by Amaury Pouly * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #ifndef __HWSTUB_VIRTUAL_HPP__ #define __HWSTUB_VIRTUAL_HPP__ #include "hwstub.hpp" #include namespace hwstub { namespace virt { class hardware; /** Virtual context * * A virtual context hosts a number of virtual devices. * This kind of contexts is mostly useful for testing/debugging purposes */ class context : public hwstub::context { protected: context(); public: virtual ~context(); /** Create a virtual context. */ static std::shared_ptr create(); /** To ease creation, the context can be given a specification of the initial * device list using the following format: * dev1;dev2;... * At the moment the only format support for devi is: * dummy(Device name) */ static std::shared_ptr create_spec(const std::string& spec, std::string *error = nullptr); /** Connect a device to the context. Return false if device is already connected, * and true otherwise. This method is thread-safe. */ bool connect(std::shared_ptr hw); /** Disconnect a device from the context. Return false if device is not connected, * and true otheriwse. This method is thread-safe. */ bool disconnect(std::shared_ptr hw); protected: /* NOTE ctx_dev_t = hardware* */ std::shared_ptr from_ctx_dev(ctx_dev_t dev); ctx_dev_t to_ctx_dev(std::shared_ptr& dev); virtual error fetch_device_list(std::vector& list, void*& ptr); virtual void destroy_device_list(void *ptr); virtual error create_device(ctx_dev_t dev, std::shared_ptr& hwdev); virtual bool match_device(ctx_dev_t dev, std::shared_ptr hwdev); std::vector> m_hwlist; /* List of connected hardware */ }; /** Virtual hardware device (server/provider side) * * This base class represents a virtual piece of hardware that is being accessed * by the context. Users of virtual contexts must inherit from this class and * implement the requests. All requests are guaranteed to be serialize at the device * level so there is no need to care about concurrency issues */ class hardware : public std::enable_shared_from_this { public: hardware(); virtual ~hardware(); virtual error read_dev(uint32_t addr, void *buf, size_t& sz, bool atomic) = 0; virtual error write_dev(uint32_t addr, const void *buf, size_t& sz, bool atomic) = 0; virtual error get_dev_desc(uint16_t desc, void *buf, size_t& buf_sz) = 0; virtual error get_dev_log(void *buf, size_t& buf_sz) = 0; virtual error exec_dev(uint32_t addr, uint16_t flags) = 0; virtual size_t get_buffer_size() = 0; }; /** Dummy implementation of an hardware. * * This dummy hardware will fail all operations except getting descriptors. * The device description can be customised */ class dummy_hardware : public hardware { public: dummy_hardware(const std::string& name); virtual ~dummy_hardware(); virtual error read_dev(uint32_t addr, void *buf, size_t& sz, bool atomic); virtual error write_dev(uint32_t addr, const void *buf, size_t& sz, bool atomic); virtual error get_dev_desc(uint16_t desc, void *buf, size_t& buf_sz); virtual error get_dev_log(void *buf, size_t& buf_sz); virtual error exec_dev(uint32_t addr, uint16_t flags); virtual size_t get_buffer_size(); protected: struct hwstub_version_desc_t m_desc_version; struct hwstub_layout_desc_t m_desc_layout; struct hwstub_target_desc_t m_desc_target; }; /** Virtual device (client/user side) * * Device based on virtual device. */ class device : public hwstub::device { friend class context; /* for ctor */ protected: device(std::shared_ptr ctx, std::shared_ptr dev); public: virtual ~device(); /** Get native device (possibly null) */ std::shared_ptr native_device(); protected: virtual error open_dev(std::shared_ptr& handle); virtual bool has_multiple_open() const; std::weak_ptr m_hwdev; /* pointer to hardware */ }; /** Virtual handle * * Handle based on virtual device. */ class handle : public hwstub::handle { friend class device; /* for ctor */ protected: handle(std::shared_ptr dev); public: virtual ~handle(); protected: virtual error read_dev(uint32_t addr, void *buf, size_t& sz, bool atomic); virtual error write_dev(uint32_t addr, const void *buf, size_t& sz, bool atomic); virtual error get_dev_desc(uint16_t desc, void *buf, size_t& buf_sz); virtual error get_dev_log(void *buf, size_t& buf_sz); virtual error exec_dev(uint32_t addr, uint16_t flags); virtual error cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], const void *out_data, size_t out_size, void *in_data, size_t *in_size); virtual error status() const; virtual size_t get_buffer_size(); std::weak_ptr m_hwdev; /* pointer to hardware */ }; } // namespace virt } // namespace hwstub #endif /* __HWSTUB_VIRTUAL_HPP__ */