lib/gpio/sysfs.ex

# SPDX-FileCopyrightText: 2023 Frank Hunleth
#
# SPDX-License-Identifier: Apache-2.0

defmodule Circuits.GPIO.Sysfs do
  @moduledoc """
  Circuits.GPIO backend that uses the Linux sysfs for controlling GPIOs
  """
  @behaviour Circuits.GPIO.Backend

  alias Circuits.GPIO.Backend
  alias Circuits.GPIO.Handle
  alias Circuits.GPIO.Nif

  defstruct [:ref]

  @impl Backend
  def open(pin_spec, direction, options) do
    value = Keyword.fetch!(options, :initial_value)
    pull_mode = Keyword.fetch!(options, :pull_mode)

    with {:ok, ref} <- Nif.open(pin_spec, direction, value, pull_mode) do
      {:ok, %__MODULE__{ref: ref}}
    end
  end

  @impl Backend
  def info() do
    Nif.info() |> Map.put(:name, __MODULE__)
  end

  defimpl Handle do
    @impl Handle
    def read(%Circuits.GPIO.Sysfs{ref: ref}) do
      Nif.read(ref)
    end

    @impl Handle
    def write(%Circuits.GPIO.Sysfs{ref: ref}, value) do
      Nif.write(ref, value)
    end

    @impl Handle
    def set_direction(%Circuits.GPIO.Sysfs{ref: ref}, pin_direction) do
      Nif.set_direction(ref, pin_direction)
    end

    @impl Handle
    def set_pull_mode(%Circuits.GPIO.Sysfs{ref: ref}, pull_mode) do
      Nif.set_pull_mode(ref, pull_mode)
    end

    @impl Handle
    def set_interrupts(%Circuits.GPIO.Sysfs{ref: ref}, trigger, options) do
      suppress_glitches = Keyword.get(options, :suppress_glitches, true)

      receiver =
        case Keyword.get(options, :receiver) do
          pid when is_pid(pid) -> pid
          name when is_atom(name) -> Process.whereis(name) || self()
          _ -> self()
        end

      Nif.set_interrupts(ref, trigger, suppress_glitches, receiver)
    end

    @impl Handle
    def close(%Circuits.GPIO.Sysfs{ref: ref}) do
      Nif.close(ref)
    end

    @impl Handle
    def info(%Circuits.GPIO.Sysfs{ref: ref}) do
      %{pin_spec: Nif.pin(ref)}
    end
  end
end