Browse Source

added explanation to `PermissionError` on `SpiDev.open()`

Fabian Peter Hammerle 3 years ago
parent
commit
751d6906ae
3 changed files with 36 additions and 1 deletions
  1. 2 0
      CHANGELOG.md
  2. 19 1
      cc1101/__init__.py
  3. 15 0
      tests/test_spi.py

+ 2 - 0
CHANGELOG.md

@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+### Added
+- added explanation to `PermissionError` on `SpiDev.open()`
 
 ## [2.1.0] - 2020-12-04
 ### Added

+ 19 - 1
cc1101/__init__.py

@@ -139,6 +139,13 @@ class CC1101:
 
     def __init__(self) -> None:
         self._spi = spidev.SpiDev()
+        self._spi_bus = 0
+        # > The BCM2835 core common to all Raspberry Pi devices has 3 SPI Controllers:
+        # > SPI0, with two hardware chip selects, [...]
+        # > SPI1, with three hardware chip selects, [...]
+        # > SPI2, also with three hardware chip selects, is only usable on a Compute Module [...]
+        # https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
+        self._spi_chip_select = 0
 
     @staticmethod
     def _log_chip_status_byte(chip_status: int) -> None:
@@ -432,7 +439,18 @@ class CC1101:
 
     def __enter__(self) -> "CC1101":
         # https://docs.python.org/3/reference/datamodel.html#object.__enter__
-        self._spi.open(0, 0)
+        try:
+            self._spi.open(self._spi_bus, self._spi_chip_select)
+        except PermissionError as exc:
+            raise PermissionError(
+                "Could not access /dev/spidev{}.{}".format(
+                    self._spi_bus, self._spi_chip_select
+                )
+                + "\nVerify that the current user has both read and write access."
+                + "\nOn some devices, like Raspberry Pis,"
+                + "\n\tsudo usermod -a -G spi $USER"
+                + "\nfollowed by a re-login grants sufficient permissions."
+            ) from exc
         self._spi.max_speed_hz = 55700  # empirical
         self._reset()
         partnum = self._read_status_register(StatusRegisterAddress.PARTNUM)

+ 15 - 0
tests/test_spi.py

@@ -17,6 +17,8 @@
 
 import unittest.mock
 
+import pytest
+
 import cc1101
 import cc1101.addresses
 import cc1101.options
@@ -75,3 +77,16 @@ def test___enter__(transceiver):
             set_pa_setting_mock.assert_called_once_with(1)
             disable_whitening_mock.assert_called_once_with()
             write_burst_mock.assert_called_once_with(0x18, [0b010100])
+
+
+@pytest.mark.parametrize("bus", [0, 1])
+@pytest.mark.parametrize("chip_select", [0, 2])
+def test___enter__permission_error(transceiver, bus, chip_select):
+    transceiver._spi.open.side_effect = PermissionError("[Errno 13] Permission denied")
+    transceiver._spi_bus = bus
+    transceiver._spi_chip_select = chip_select
+    with pytest.raises(
+        PermissionError, match=r"\s/dev/spidev{}.{}\s".format(bus, chip_select)
+    ):
+        with transceiver:
+            pass