From: Melissa LeBlanc-Williams Date: Sat, 16 Dec 2023 00:38:23 +0000 (-0800) Subject: Add support for libgpiod 2.x X-Git-Tag: 8.28.0~1^2~1 X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/commitdiff_plain/7e23a369d8f0f8964f2fb28b0cf6bf3603233721 Add support for libgpiod 2.x --- diff --git a/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/__init__.py b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/libgpiod_pin_1_x.py b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/libgpiod_pin_1_x.py new file mode 100644 index 0000000..f040a7f --- /dev/null +++ b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/libgpiod_pin_1_x.py @@ -0,0 +1,127 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +"""A Pin class for use with libgpiod 1.x.""" +import gpiod + + +# pylint: disable=too-many-branches,too-many-statements +class Pin: + """Pins dont exist in CPython so...lets make our own!""" + + IN = 0 + OUT = 1 + LOW = 0 + HIGH = 1 + PULL_NONE = 0 + PULL_UP = 1 + PULL_DOWN = 2 + _CONSUMER = "adafruit_blinka" + + id = None + _value = LOW + _mode = IN + + def __init__(self, pin_id): + self.id = pin_id + if isinstance(pin_id, tuple): + self._num = int(pin_id[1]) + if hasattr(gpiod, "Chip"): + self._chip = gpiod.Chip(str(pin_id[0]), gpiod.Chip.OPEN_BY_NUMBER) + else: + self._chip = gpiod.chip(str(pin_id[0]), gpiod.chip.OPEN_BY_NUMBER) + else: + self._num = int(pin_id) + if hasattr(gpiod, "Chip"): + self._chip = gpiod.Chip("gpiochip0", gpiod.Chip.OPEN_BY_NAME) + else: + self._chip = gpiod.chip("gpiochip0", gpiod.chip.OPEN_BY_NAME) + self._line = None + + def __repr__(self): + return str(self.id) + + def __eq__(self, other): + return self.id == other + + def init(self, mode=IN, pull=None): + """Initialize the Pin""" + if not self._line: + self._line = self._chip.get_line(int(self._num)) + # print("init line: ", self.id, self._line) + + if mode is not None: + if mode == self.IN: + flags = 0 + self._line.release() + if pull is not None: + if pull == self.PULL_UP: + if hasattr(gpiod, "LINE_REQ_FLAG_BIAS_PULL_UP"): + flags |= gpiod.LINE_REQ_FLAG_BIAS_PULL_UP + else: + raise NotImplementedError( + "Internal pullups not supported in this version of libgpiod, " + "use physical resistor instead!" + ) + elif pull == self.PULL_DOWN: + if hasattr(gpiod, "line") and hasattr( + gpiod, "LINE_REQ_FLAG_BIAS_PULL_DOWN" + ): + flags |= gpiod.LINE_REQ_FLAG_BIAS_PULL_DOWN + else: + raise NotImplementedError( + "Internal pulldowns not supported in this version of libgpiod, " + "use physical resistor instead!" + ) + elif pull == self.PULL_NONE: + if hasattr(gpiod, "line") and hasattr( + gpiod, "LINE_REQ_FLAG_BIAS_DISABLE" + ): + flags |= gpiod.LINE_REQ_FLAG_BIAS_DISABLE + else: + raise NotImplementedError( + "Internal pulldowns not supported in this version of libgpiod, " + "use physical resistor instead!" + ) + else: + raise RuntimeError(f"Invalid pull for pin: {self.id}") + + self._mode = self.IN + self._line.release() + if hasattr(gpiod, "LINE_REQ_DIR_IN"): + self._line.request( + consumer=self._CONSUMER, type=gpiod.LINE_REQ_DIR_IN, flags=flags + ) + else: + config = gpiod.line_request() + config.consumer = self._CONSUMER + config.request_type = gpiod.line_request.DIRECTION_INPUT + self._line.request(config) + + elif mode == self.OUT: + if pull is not None: + raise RuntimeError("Cannot set pull resistor on output") + self._mode = self.OUT + self._line.release() + if hasattr(gpiod, "LINE_REQ_DIR_OUT"): + self._line.request( + consumer=self._CONSUMER, type=gpiod.LINE_REQ_DIR_OUT + ) + else: + config = gpiod.line_request() + config.consumer = self._CONSUMER + config.request_type = gpiod.line_request.DIRECTION_OUTPUT + self._line.request(config) + else: + raise RuntimeError("Invalid mode for pin: %s" % self.id) + + def value(self, val=None): + """Set or return the Pin Value""" + if val is None: + return self._line.get_value() + + if val in (self.LOW, self.HIGH): + self._value = val + self._line.set_value(val) + return None + raise RuntimeError("Invalid value for pin") diff --git a/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/libgpiod_pin_2_x.py b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/libgpiod_pin_2_x.py new file mode 100644 index 0000000..9f12d9d --- /dev/null +++ b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod/libgpiod_pin_2_x.py @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +"""A Pin class for use with libgpiod 2.x.""" +import gpiod + + +# pylint: disable=too-many-branches,too-many-statements +class Pin: + """Pins dont exist in CPython so...lets make our own!""" + + IN = 0 + OUT = 1 + LOW = 0 + HIGH = 1 + PULL_NONE = 0 + PULL_UP = 1 + PULL_DOWN = 2 + _CONSUMER = "adafruit_blinka" + + id = None + _value = LOW + _mode = IN + + _value_map = (gpiod.line.Value.INACTIVE, gpiod.line.Value.ACTIVE) + + def __init__(self, pin_id): + self.id = pin_id + chip_id = 0 + if isinstance(pin_id, tuple): + chip_id, self._num = pin_id + if isinstance(chip_id, int): + chip_id = f"/dev/gpiochip{chip_id}" + self._chip = gpiod.Chip(chip_id) + self._line_request = None + + def __del__(self): + if self._line_request: + self._line_request.release() + + def __repr__(self): + return str(self.id) + + def __eq__(self, other): + return self.id == other + + def init(self, mode=IN, pull=None): + """Initialize the Pin""" + # Input, + if not self._line_request: + self._line_request = self._chip.request_lines( + config={int(self._num): None}, + consumer=self._CONSUMER, + ) + # print("init line: ", self.id, self._line) + + if mode is not None: + line_config = gpiod.LineSettings() + if mode == self.IN: + line_config.direction = gpiod.line.Direction.INPUT + if pull is not None: + if pull == self.PULL_UP: + line_config.bias = gpiod.line.Bias.PULL_UP + elif pull == self.PULL_DOWN: + line_config.bias = gpiod.line.Bias.PULL_DOWN + elif pull == self.PULL_NONE: + line_config.bias = gpiod.line.Bias.DISABLED + else: + raise RuntimeError(f"Invalid pull for pin: {self.id}") + + self._mode = self.IN + self._line_request.reconfigure_lines( + { + int(self._num): line_config, + } + ) + elif mode == self.OUT: + if pull is not None: + raise RuntimeError("Cannot set pull resistor on output") + self._mode = self.OUT + line_config.direction = gpiod.line.Direction.OUTPUT + self._line_request.reconfigure_lines( + { + int(self._num): line_config, + } + ) + else: + raise RuntimeError("Invalid mode for pin: %s" % self.id) + + def value(self, val=None): + """Set or return the Pin Value""" + if val is None: + return bool(self._value_map.index(self._line_request.get_value(self._num))) + + if val in (self.LOW, self.HIGH): + self._value = val + self._line_request.set_value(self._num, self._value_map[int(val)]) + return None + raise RuntimeError("Invalid value for pin") diff --git a/src/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py index b7953e1..d495524 100644 --- a/src/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py +++ b/src/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py @@ -10,124 +10,13 @@ except ImportError: "https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/master/libgpiod.sh" ) from ImportError - -# pylint: disable=too-many-branches,too-many-statements -class Pin: - """Pins dont exist in CPython so...lets make our own!""" - - IN = 0 - OUT = 1 - LOW = 0 - HIGH = 1 - PULL_NONE = 0 - PULL_UP = 1 - PULL_DOWN = 2 - _CONSUMER = "adafruit_blinka" - - id = None - _value = LOW - _mode = IN - - def __init__(self, pin_id): - self.id = pin_id - if isinstance(pin_id, tuple): - self._num = int(pin_id[1]) - if hasattr(gpiod, "Chip"): - self._chip = gpiod.Chip(str(pin_id[0]), gpiod.Chip.OPEN_BY_NUMBER) - else: - self._chip = gpiod.chip(str(pin_id[0]), gpiod.chip.OPEN_BY_NUMBER) - else: - self._num = int(pin_id) - if hasattr(gpiod, "Chip"): - self._chip = gpiod.Chip("gpiochip0", gpiod.Chip.OPEN_BY_NAME) - else: - self._chip = gpiod.chip("gpiochip0", gpiod.chip.OPEN_BY_NAME) - self._line = None - - def __repr__(self): - return str(self.id) - - def __eq__(self, other): - return self.id == other - - def init(self, mode=IN, pull=None): - """Initialize the Pin""" - if not self._line: - self._line = self._chip.get_line(int(self._num)) - # print("init line: ", self.id, self._line) - - if mode is not None: - if mode == self.IN: - flags = 0 - self._line.release() - if pull is not None: - if pull == self.PULL_UP: - if hasattr(gpiod, "LINE_REQ_FLAG_BIAS_PULL_UP"): - flags |= gpiod.LINE_REQ_FLAG_BIAS_PULL_UP - else: - raise NotImplementedError( - "Internal pullups not supported in this version of libgpiod, " - "use physical resistor instead!" - ) - elif pull == self.PULL_DOWN: - if hasattr(gpiod, "line") and hasattr( - gpiod, "LINE_REQ_FLAG_BIAS_PULL_DOWN" - ): - flags |= gpiod.LINE_REQ_FLAG_BIAS_PULL_DOWN - else: - raise NotImplementedError( - "Internal pulldowns not supported in this version of libgpiod, " - "use physical resistor instead!" - ) - elif pull == self.PULL_NONE: - if hasattr(gpiod, "line") and hasattr( - gpiod, "LINE_REQ_FLAG_BIAS_DISABLE" - ): - flags |= gpiod.LINE_REQ_FLAG_BIAS_DISABLE - else: - raise NotImplementedError( - "Internal pulldowns not supported in this version of libgpiod, " - "use physical resistor instead!" - ) - else: - raise RuntimeError(f"Invalid pull for pin: {self.id}") - - self._mode = self.IN - self._line.release() - if hasattr(gpiod, "LINE_REQ_DIR_IN"): - self._line.request( - consumer=self._CONSUMER, type=gpiod.LINE_REQ_DIR_IN, flags=flags - ) - else: - config = gpiod.line_request() - config.consumer = self._CONSUMER - config.request_type = gpiod.line_request.DIRECTION_INPUT - self._line.request(config) - - elif mode == self.OUT: - if pull is not None: - raise RuntimeError("Cannot set pull resistor on output") - self._mode = self.OUT - self._line.release() - if hasattr(gpiod, "LINE_REQ_DIR_OUT"): - self._line.request( - consumer=self._CONSUMER, type=gpiod.LINE_REQ_DIR_OUT - ) - else: - config = gpiod.line_request() - config.consumer = self._CONSUMER - config.request_type = gpiod.line_request.DIRECTION_OUTPUT - self._line.request(config) - else: - raise RuntimeError("Invalid mode for pin: %s" % self.id) - - def value(self, val=None): - """Set or return the Pin Value""" - if val is None: - return self._line.get_value() - - if val in (self.LOW, self.HIGH): - self._value = val - self._line.set_value(val) - return None - raise RuntimeError("Invalid value for pin") +# Versions 1.5.4 and earlier have no __version__ attribute +if hasattr(gpiod, "__version__"): + version = gpiod.__version__ +else: + version = "1.x" + +if version.startswith("1."): + from .libgpiod.libgpiod_pin_1_x import Pin # pylint: disable=unused-import +else: + from .libgpiod.libgpiod_pin_2_x import Pin # pylint: disable=unused-import