From 50a88abf2f2467b6f1ebc423892177d59384da21 Mon Sep 17 00:00:00 2001
From: Martin Teichmann <martin.teichmann@xfel.eu>
Date: Thu, 18 Feb 2021 15:21:31 +0000
Subject: [PATCH] support serial connections

---
 ebpfcat/ebpfcat.py   |  1 +
 ebpfcat/serial.py    | 82 ++++++++++++++++++++++++++++++++++++++++++++
 ebpfcat/terminals.py | 20 +++++++++++
 3 files changed, 103 insertions(+)
 create mode 100644 ebpfcat/serial.py

diff --git a/ebpfcat/ebpfcat.py b/ebpfcat/ebpfcat.py
index 648243e..f39a805 100644
--- a/ebpfcat/ebpfcat.py
+++ b/ebpfcat/ebpfcat.py
@@ -321,6 +321,7 @@ class SyncGroup(SyncGroupBase):
             self.current_data = bytearray(data)
             for dev in self.devices:
                 dev.update()
+            await sleep(0)
 
     def start(self):
         self.allocate()
diff --git a/ebpfcat/serial.py b/ebpfcat/serial.py
new file mode 100644
index 0000000..98b9ef5
--- /dev/null
+++ b/ebpfcat/serial.py
@@ -0,0 +1,82 @@
+from asyncio import ensure_future, Event, Queue, StreamReader, gather
+from .ebpfcat import Device, TerminalVar
+
+
+class Serial(Device):
+    channel = TerminalVar()
+
+    def __init__(self, channel):
+        self.buffer = Queue()
+        self.channel = channel
+        self.data_arrived = Event()
+
+    def write(self, data):
+        self.buffer.put_nowait(data)
+
+    def connect(self):
+        self.task = ensure_future(self.run())
+        self.reader = StreamReader()
+        return self.reader, self
+
+    async def run(self):
+        while not self.channel.init_accept:
+            self.channel.init_request = True
+            await self.data_arrived.wait()
+        self.channel.init_request = False
+        while self.channel.init_accept:
+            await self.data_arrived.wait()
+
+        await gather(self.receive(), self.transmit())
+
+    async def receive(self):
+        ra = self.channel.receive_accept
+        while True:
+            rr = self.channel.receive_request
+            while rr == self.channel.receive_request:
+                self.channel.receive_accept = ra
+                await self.data_arrived.wait()
+            self.reader.feed_data(self.channel.in_string)
+            ra = not ra
+
+    async def transmit(self):
+        remainder = b""
+
+        async def inner():
+            nonlocal remainder
+            s = remainder
+            size = len(remainder)
+            while not self.buffer.empty() or size == 0:
+                if size + len(s) > 22:
+                    remainder = s[22-size:]
+                    yield s[:22-size]
+                    return
+                else:
+                    yield s
+                    size += len(s)
+                    s = await self.buffer.get()
+
+        while True:
+            ta = self.channel.transmit_accept
+            tr = self.channel.transmit_request
+            chunk = b"".join([s async for s in inner()])
+            while ta == self.channel.transmit_accept:
+                self.channel.out_string = chunk
+                self.channel.transmit_request = not tr
+                await self.data_arrived.wait()
+
+    def update(self):
+        self.data_arrived.set()
+        self.data_arrived.clear()
+
+    def get_chunk(self):
+        def inner():
+            size = 0
+            while size < 22 and len(self.buffer):
+                s = self.buffer.popleft()
+                if size + len(s) > 22:
+                    self.buffer.appendleft(s[22-size:])
+                    yield s[:22-size]
+                else:
+                    yield
+                l += len(s)
+        return b"".join(inner())
diff --git a/ebpfcat/terminals.py b/ebpfcat/terminals.py
index 620a434..060f734 100644
--- a/ebpfcat/terminals.py
+++ b/ebpfcat/terminals.py
@@ -32,3 +32,23 @@ class EK1814(EBPFTerminal):
     ch6 = PacketDesc((1, 0), 1)
     ch7 = PacketDesc((1, 0), 2)
     ch8 = PacketDesc((1, 0), 3)
+
+
+class EL6022(EBPFTerminal):
+    class Channel(Struct):
+        transmit_accept = PacketDesc((0, 0), 0)
+        receive_request = PacketDesc((0, 0), 1)
+        init_accept = PacketDesc((0, 0), 2)
+        status = PacketDesc((0, 0), "H")
+        in_string = PacketDesc((0, 1), "23p")
+        wkc1 = PacketDesc((0, 24), "H")
+
+        transmit_request = PacketDesc((1, 0), 0)
+        receive_accept = PacketDesc((1, 0), 1)
+        init_request = PacketDesc((1, 0), 2)
+        control = PacketDesc((1, 0), "H")
+        out_string = PacketDesc((1, 1), "23p")
+        wkc2 = PacketDesc((0, 24), "H")
+
+    channel1 = Channel(0, 0)
+    channel2 = Channel(24, 24)
-- 
GitLab