Source code for pihat.eeprom.device
"""EEPROM device"""
from contextlib import contextmanager, nullcontext
from dataclasses import dataclass, field, InitVar
from pathlib import Path
import time
from typing import List, Optional
import pkg_resources
from .file import EepromFile
__all__ = [
'EepromDeviceOverlay',
'EepromDevice',
]
DEFAULT_BUS = 99
[docs]@dataclass
class EepromDeviceOverlay:
"""EEPROM devicetree overlay"""
bus: int = DEFAULT_BUS
autocreate: bool = True
autoremove: bool = False
timeout: float = 2.0
interval: float = 0.1
_ctx: List = field(init=False, repr=False, default_factory=list)
@property
def name(self):
"""Overlay name"""
return 'ideeprom%d' % self.bus
@property
def data(self):
"""Overlay devicetree blob"""
return pkg_resources.resource_string(__name__, '%s.dtbo' % self.name)
@property
def directory(self):
"""Overlay directory"""
return Path('/sys/kernel/config/device-tree/overlays/%s' % self.name)
@property
def dtbo(self):
"""Overlay file"""
return self.directory / 'dtbo'
@property
def eeprom(self):
"""EEPROM device path"""
return Path('/sys/class/i2c-adapter/i2c-%d/%d-0050/eeprom' %
(self.bus, self.bus))
[docs] def wait(self):
"""Wait for EEPROM device to exist"""
expired = time.time() + self.timeout
while time.time() < expired:
if self.eeprom.exists():
break
time.sleep(self.interval)
[docs] def install(self):
"""Install overlay"""
self.directory.mkdir(exist_ok=True)
with self.dtbo.open('wb') as fh:
fh.write(self.data)
self.wait()
[docs] def remove(self):
"""Remove overlay"""
if self.directory.exists():
self.directory.rmdir()
def __enter__(self):
install = self.autocreate and not self.eeprom.exists()
if install:
self.install()
self._ctx.append(install)
return self.eeprom
def __exit__(self, exc_type, exc_val, exc_tb):
installed = self._ctx.pop()
if installed and self.autoremove:
self.remove()
[docs]@dataclass
class EepromDevice(EepromFile):
"""EEPROM stored in an i2c EEPROM device"""
bus: InitVar[Optional[int]] = field(default=None, compare=False)
overlay: EepromDeviceOverlay = field(default_factory=EepromDeviceOverlay,
compare=False)
autouuid: bool = field(default=True, compare=False)
def __post_init__(self, bus):
# pylint: disable=assigning-non-slot
if bus is not None:
self.overlay.bus = bus
[docs] @contextmanager
def open(self, file=None, mode=None):
cm = (self.overlay if file is None and self.file is None else
nullcontext(file))
with cm as inner_file, super().open(inner_file, mode) as ctx:
yield ctx