OXYGENHUB
◆ main openmsx / src / serial / RS232Net.hh
3.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#ifndef RS232NET_HH
2
#define RS232NET_HH
3
4
#include "RS232Device.hh"
5
6
#include "BooleanSetting.hh"
7
#include "EventListener.hh"
8
#include "Socket.hh"
9
#include "StringSetting.hh"
10
11
#include "Poller.hh"
12
#include "circular_buffer.hh"
13
14
#include <atomic>
15
#include <cstdint>
16
#include <mutex>
17
#include <optional>
18
#include <span>
19
#include <thread>
20
21
namespace openmsx {
22
23
class EventDistributor;
24
class Scheduler;
25
class CommandController;
26
27
class RS232Net final : public RS232Device, private EventListener
28
{
29
public:
30
	// opaque structure describing an address for use with socket functions
31
	struct NetworkSocketAddress {
32
		int domain; // the address family (AF_INET, ...)
33
		socklen_t len; // the length of the socket address
34
		union {
35
			struct sockaddr generic;  // the generic type needed for calling the socket API
36
			struct sockaddr_in ipv4;  // an IPv4 socket address
37
			struct sockaddr_in6 ipv6; // an IPv6 socket address
38
		} address;
39
	};
40
41
public:
42
	RS232Net(EventDistributor& eventDistributor, Scheduler& scheduler,
43
	         CommandController& commandController);
44
	~RS232Net() override;
45
46
	// Pluggable
47
	void plugHelper(Connector& connector, EmuTime time) override;
48
	void unplugHelper(EmuTime time) override;
49
	[[nodiscard]] zstring_view getName() const override;
50
	[[nodiscard]] zstring_view getDescription() const override;
51
52
	// input
53
	void signal(EmuTime time) override;
54
55
	// output
56
	void recvByte(uint8_t value, EmuTime time) override;
57
58
	[[nodiscard]] std::optional<bool> getDSR(EmuTime time) const override;
59
	[[nodiscard]] std::optional<bool> getCTS(EmuTime time) const override;
60
	[[nodiscard]] std::optional<bool> getDCD(EmuTime time) const override;
61
	[[nodiscard]] std::optional<bool> getRI(EmuTime time) const override;
62
	void setDTR(bool status, EmuTime time) override;
63
	void setRTS(bool status, EmuTime time) override;
64
65
	template<typename Archive>
66
	void serialize(Archive& ar, unsigned version);
67
68
private:
69
	void run(); // loop of helper thread that reads from 'sockfd'
70
71
	// EventListener
72
	bool signalEvent(const Event& event) override;
73
74
	bool net_put(std::span<const char> buf);
75
	void open_socket(const NetworkSocketAddress& socket_address);
76
77
private:
78
	[[no_unique_address]] SocketActivator socketActivator;
79
	EventDistributor& eventDistributor;
80
	Scheduler& scheduler;
81
82
	// The value of these settings only matters at the time this device gets plugged in.
83
	// In other words: changing these settings only takes effect the next time the device gets plugged in.
84
	StringSetting rs232NetAddressSetting;
85
	BooleanSetting rs232NetUseIP232;
86
87
	std::thread thread; // receiving thread (reads from 'sockfd')
88
	std::mutex mutex; // to protect shared data between emulation and receiving thread
89
	std::optional<Poller> poller; // safe to use from main and receiver thread without extra locking
90
	cb_queue<char> queue; // read/written by both the main and the receiver thread. Must hold 'mutex' while doing so.
91
	std::atomic<SOCKET> sockfd; // read/written by both threads (use std::atomic as an alternative for locking)
92
93
	// These are written by the receiver thread and read by the main thread (use std::atomic as an alternative for locking)
94
	std::atomic<bool> DCD; // Data Carrier Detect input status
95
	std::atomic<bool> RI;  // Ring Indicator input status    TODO not yet used (write-only)
96
97
	// These are only accessed by the main thread (no need for locking)
98
	bool DTR; // Data Terminal Ready output status
99
	bool RTS; // Request To Send output status
100
101
	// This does not change while the receiving thread is running (no need for locking)
102
	bool IP232; // snapshot of 'rs232NetUseIP232' at the moment of plugging
103
};
104
105
} // namespace openmsx
106
107
#endif