diff --git a/ebpfcat/ethercat.py b/ebpfcat/ethercat.py index 6a2353b64b88e174077fa99a0b34dca31d3c02dc..43542628e24972d23e3880e9dc59d349154da2d8 100644 --- a/ebpfcat/ethercat.py +++ b/ebpfcat/ethercat.py @@ -565,6 +565,19 @@ class Terminal: busy, data = await self.read(0x502, "H4x8s") return data + async def eeprom_write_one(self, start, data): + """read 2 bytes from the eeprom at `start`""" + while (await self.read(0x502, "H"))[0] & 0x8000: + pass + busy = 0x1000 + while busy & 0xff00: + await self.write(0x502, "HIH", 0x201, start, data) + busy = 0x8000 + while busy & 0x8000: + busy, = await self.read(0x502, "H") + print(f"busy {busy:X}") + await self.write(0x502, "H", 0) + async def read_eeprom(self): """read the entire eeprom""" async def get_data(size): diff --git a/ebpfcat/scripts.py b/ebpfcat/scripts.py index 887bcbe0ad37beaec48cf618ac14f66f1286a771..4a2ecd06c623756b7355845638ca5721d4bf0c81 100644 --- a/ebpfcat/scripts.py +++ b/ebpfcat/scripts.py @@ -1,6 +1,7 @@ from argparse import ArgumentParser import asyncio from functools import wraps +from hashlib import sha1 from struct import unpack import sys @@ -84,3 +85,56 @@ async def info(): await t.parse_pdos() for (idx, subidx), (sm, pos, fmt) in t.pdos.items(): print(f"{idx:4X}:{subidx:02X} {sm} {pos} {fmt}") + + +def encode(name): + r = int.from_bytes(sha1(name.encode("ascii")).digest(), "little") + return r % 0xffffffff + 1 + +@entrypoint +async def eeprom(): + parser = ArgumentParser( + prog = "ec-eeprom", + description = "Read and write the eeprom") + + parser.add_argument("interface") + parser.add_argument("-t", "--terminal", type=int) + parser.add_argument("-r", "--read", action="store_true") + parser.add_argument("-w", "--write", type=int) + parser.add_argument("-n", "--name", type=str) + parser.add_argument("-c", "--check", type=str) + args = parser.parse_args() + + ec = EtherCat(args.interface) + await ec.connect() + + if args.terminal is None: + return + terminals = range(await ec.count()) + else: + # former terminal: don't listen! + # this does not work with all terminals, dunno why + await ec.roundtrip(ECCmd.FPRW, 7, 0x10, "H", 0) + terminals = [args.terminal] + + t = Terminal() + t.ec = ec + await t.initialize(-args.terminal, 7) + + if args.read or args.check is not None: + r, = unpack("<4xI", await t.eeprom_read_one(0xc)) + if args.check is not None: + c = encode(args.check) + print(f"{r:8X} {c:8X} {r == c}") + else: + print(f"{r:8X} {r}") + + w = None + if args.write is not None: + w = args.write + elif args.name is not None: + w = encode(args.name) + print(f"{w:8X} {w}") + if w is not None: + await t.eeprom_write_one(0xe, w & 0xffff) + await t.eeprom_write_one(0xf, w >> 16) diff --git a/pyproject.toml b/pyproject.toml index 995d3a93148669770bc8c9e9a5789b7200803e19..c111152ce976c0a11a18b1bcd99b645dee93d938 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,3 +6,4 @@ dependencies = [] [project.scripts] ec-scanbus = "ebpfcat.scripts:scanbus" ec-info = "ebpfcat.scripts:info" +ec-eeprom = "ebpfcat.scripts:eeprom"