Browse Source

included a stripped down version of mmio to avoid python-periphery dependency

erpalma 5 years ago
parent
commit
41d58438ab
4 changed files with 122 additions and 3 deletions
  1. 1 1
      install.sh
  2. 1 1
      lenovo_fix.py
  3. 120 0
      mmio.py
  4. 0 1
      requirements.txt

+ 1 - 1
install.sh

@@ -20,7 +20,7 @@ echo "Copying systemd service file..."
 cp systemd/lenovo_fix.service /etc/systemd/system
 
 echo "Building virtualenv..."
-cp requirements.txt lenovo_fix.py "$INSTALL_DIR"
+cp requirements.txt lenovo_fix.py mmio.py "$INSTALL_DIR"
 cd "$INSTALL_DIR"
 virtualenv -p /usr/bin/python3 venv
 . venv/bin/activate

+ 1 - 1
lenovo_fix.py

@@ -10,8 +10,8 @@ import subprocess
 
 from collections import defaultdict
 from dbus.mainloop.glib import DBusGMainLoop
+from mmio import MMIO
 from multiprocessing import cpu_count
-from periphery import MMIO
 from threading import Event, Thread
 
 try:

+ 120 - 0
mmio.py

@@ -0,0 +1,120 @@
+'''
+Stripped down version from https://github.com/vsergeev/python-periphery/blob/master/periphery/mmio.py
+'''
+import mmap
+import os
+import struct
+import sys
+
+# Alias long to int on Python 3
+if sys.version_info[0] >= 3:
+    long = int
+
+
+class MMIOError(IOError):
+    """Base class for MMIO errors."""
+    pass
+
+
+class MMIO(object):
+    def __init__(self, physaddr, size):
+        """Instantiate an MMIO object and map the region of physical memory
+        specified by the address base `physaddr` and size `size` in bytes.
+        Args:
+            physaddr (int, long): base physical address of memory region.
+            size (int, long): size of memory region.
+        Returns:
+            MMIO: MMIO object.
+        Raises:
+            MMIOError: if an I/O or OS error occurs.
+            TypeError: if `physaddr` or `size` types are invalid.
+        """
+        self.mapping = None
+        self._open(physaddr, size)
+
+    def __del__(self):
+        self.close()
+
+    def __enter__(self):
+        pass
+
+    def __exit__(self, t, value, traceback):
+        self.close()
+
+    def _open(self, physaddr, size):
+        if not isinstance(physaddr, (int, long)):
+            raise TypeError("Invalid physaddr type, should be integer.")
+        if not isinstance(size, (int, long)):
+            raise TypeError("Invalid size type, should be integer.")
+
+        pagesize = os.sysconf(os.sysconf_names['SC_PAGESIZE'])
+
+        self._physaddr = physaddr
+        self._size = size
+        self._aligned_physaddr = physaddr - (physaddr % pagesize)
+        self._aligned_size = size + (physaddr - self._aligned_physaddr)
+
+        try:
+            fd = os.open("/dev/mem", os.O_RDWR | os.O_SYNC)
+        except OSError as e:
+            raise MMIOError(e.errno, "Opening /dev/mem: " + e.strerror)
+
+        try:
+            self.mapping = mmap.mmap(
+                fd,
+                self._aligned_size,
+                flags=mmap.MAP_SHARED,
+                prot=mmap.PROT_WRITE,
+                offset=self._aligned_physaddr)
+        except OSError as e:
+            raise MMIOError(e.errno, "Mapping /dev/mem: " + e.strerror)
+
+        try:
+            os.close(fd)
+        except OSError as e:
+            raise MMIOError(e.errno, "Closing /dev/mem: " + e.strerror)
+
+    # Methods
+
+    def _adjust_offset(self, offset):
+        return offset + (self._physaddr - self._aligned_physaddr)
+
+    def _validate_offset(self, offset, length):
+        if (offset + length) > self._aligned_size:
+            raise ValueError("Offset out of bounds.")
+
+    def write32(self, offset, value):
+        """Write 32-bits to the specified `offset` in bytes, relative to the
+        base physical address of the MMIO region.
+        Args:
+            offset (int, long): offset from base physical address, in bytes.
+            value (int, long): 32-bit value to write.
+        Raises:
+            TypeError: if `offset` or `value` type are invalid.
+            ValueError: if `offset` or `value` are out of bounds.
+        """
+        if not isinstance(offset, (int, long)):
+            raise TypeError("Invalid offset type, should be integer.")
+        if not isinstance(value, (int, long)):
+            raise TypeError("Invalid value type, should be integer.")
+        if value < 0 or value > 0xffffffff:
+            raise ValueError("Value out of bounds.")
+
+        offset = self._adjust_offset(offset)
+        self._validate_offset(offset, 4)
+        self.mapping[offset:offset + 4] = struct.pack("=L", value)
+
+    def close(self):
+        """Unmap the MMIO object's mapped physical memory."""
+        if self.mapping is None:
+            return
+
+        self.mapping.close()
+        self.mapping = None
+
+        self._fd = None
+
+    # String representation
+
+    def __str__(self):
+        return "MMIO 0x%08x (size=%d)" % (self.base, self.size)

+ 0 - 1
requirements.txt

@@ -2,4 +2,3 @@ configparser==3.5.0
 dbus-python==1.2.8
 psutil==5.4.6
 PyGObject==3.28.3
-python-periphery==1.1.1