Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Raspberry Pi detection out of board.py #299

Closed
4 changes: 1 addition & 3 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,7 @@ indent-string=' '
max-line-length=100

# Maximum number of lines in a module
#
# XXX: Reduce this number once Issue 296 is resolved.
max-module-lines=1050
max-module-lines=1000

# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
Expand Down
67 changes: 5 additions & 62 deletions adafruit_platformdetect/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
"""

import os
import re

try:
from typing import Optional
except ImportError:
pass

from adafruit_platformdetect.constants import boards, chips

from adafruit_platformdetect.boards import raspberrypi

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PlatformDetect.git"
Expand Down Expand Up @@ -64,7 +63,9 @@ def id(self) -> Optional[str]:
if chip_id == chips.H3:
board_id = self._armbian_id() or self._allwinner_variants_id()
elif chip_id == chips.BCM2XXX:
board_id = self._pi_id()
from adafruit_platformdetect.boards.raspberrypi import determine_board_id

board_id = determine_board_id(self.detector)
elif chip_id == chips.AM625X:
board_id = self._beaglebone_id()
elif chip_id == chips.AM33XX:
Expand Down Expand Up @@ -198,67 +199,9 @@ def id(self) -> Optional[str]:

# pylint: enable=invalid-name

def _pi_id(self) -> Optional[str]:
"""Try to detect id of a Raspberry Pi."""
# Check for Pi boards:
pi_rev_code = self._pi_rev_code()
if pi_rev_code:
from adafruit_platformdetect.revcodes import PiDecoder

try:
decoder = PiDecoder(pi_rev_code)
model = boards._PI_MODELS[decoder.type_raw]
if isinstance(model, dict):
model = model[decoder.revision]
return model
except ValueError:
pass
# We may be on a non-Raspbian OS, so try to lazily determine
# the version based on `get_device_model`
else:
pi_model = self.detector.get_device_model()
if pi_model:
pi_model = pi_model.upper().replace(" ", "_")
if "PLUS" in pi_model:
re_model = re.search(r"(RASPBERRY_PI_\d).*([AB]_*)(PLUS)", pi_model)
elif "CM" in pi_model: # untested for Compute Module
re_model = re.search(r"(RASPBERRY_PI_CM)(\d)", pi_model)
else: # untested for non-plus models
re_model = re.search(r"(RASPBERRY_PI_\d).*([AB])", pi_model)

if re_model:
pi_model = "".join(re_model.groups())
available_models = boards._PI_REV_CODES.keys()
for model in available_models:
if model == pi_model:
return model

return None

def _pi_rev_code(self) -> Optional[str]:
"""Attempt to find a Raspberry Pi revision code for this board."""
# 2708 is Pi 1
# 2709 is Pi 2
# 2835 is Pi 3 (or greater) on 4.9.x kernel
# Anything else is not a Pi.
if self.detector.chip.id != chips.BCM2XXX:
# Something else, not a Pi.
return None
rev = self.detector.get_cpuinfo_field("Revision")

if rev is not None:
return rev

try:
with open("/proc/device-tree/system/linux,revision", "rb") as revision:
rev_bytes = revision.read()

if rev_bytes[:1] == b"\x00":
rev_bytes = rev_bytes[1:]

return rev_bytes.hex()
except FileNotFoundError:
return None
return raspberrypi.determine_rev_code(self.detector)

# pylint: disable=no-self-use
def _beaglebone_id(self) -> Optional[str]:
Expand Down
85 changes: 85 additions & 0 deletions adafruit_platformdetect/boards/raspberrypi/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# SPDX-FileCopyrightText: 2021-2023 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT

"""Identify specific models and revisions of Raspberry Pi boards."""
import re

import adafruit_platformdetect.constants.boards as board_ids
import adafruit_platformdetect.constants.chips as chips_ids

try:
from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
from adafruit_platformdetect import Detector
except ImportError:
pass


# pylint: disable=protected-access
def determine_board_id(detector: "Detector") -> Optional[str]:
"""Try to detect id of a Raspberry Pi."""
# Check for Pi boards:
pi_rev_code = determine_rev_code(detector)
if pi_rev_code:
from adafruit_platformdetect.revcodes import PiDecoder

try:
decoder = PiDecoder(pi_rev_code)
model = board_ids._PI_MODELS[decoder.type_raw]
if isinstance(model, dict):
model = model[decoder.revision]
return model
except ValueError:
pass
# We may be on a non-Raspbian OS, so try to lazily determine
# the version based on `get_device_model`
else:
pi_model = detector.get_device_model()
if pi_model:
pi_model = pi_model.upper().replace(" ", "_")
if "PLUS" in pi_model:
re_model = re.search(r"(RASPBERRY_PI_\d).*([AB]_*)(PLUS)", pi_model)
elif "CM" in pi_model: # untested for Compute Module
re_model = re.search(r"(RASPBERRY_PI_CM)(\d)", pi_model)
else: # untested for non-plus models
re_model = re.search(r"(RASPBERRY_PI_\d).*([AB])", pi_model)

if re_model:
pi_model = "".join(re_model.groups())
available_models = board_ids._PI_REV_CODES.keys()
for model in available_models:
if model == pi_model:
return model

return None


# pylint: enable=protected-access


def determine_rev_code(detector: "Detector") -> Optional[str]:
"""Attempt to find a Raspberry Pi revision code for this board."""
# 2708 is Pi 1
# 2709 is Pi 2
# 2835 is Pi 3 (or greater) on 4.9.x kernel
# Anything else is not a Pi.
if detector.chip.id != chips_ids.BCM2XXX:
# Something else, not a Pi.
return None
rev = detector.get_cpuinfo_field("Revision")

if rev is not None:
return rev

try:
with open("/proc/device-tree/system/linux,revision", "rb") as revision:
rev_bytes = revision.read()

if rev_bytes[:1] == b"\x00":
rev_bytes = rev_bytes[1:]

return rev_bytes.hex()
except FileNotFoundError:
return None