Move release/1
from Conn
to it's own protocol.
This commit is contained in:
parent
b5181189ef
commit
a40af03ff5
15 changed files with 133 additions and 38 deletions
|
@ -23,12 +23,18 @@ defmodule Wafer.Conn do
|
|||
with {:ok, conn} <- Driver.acquire(bus_name: bus, address: address),
|
||||
do: {:ok, %HTS221{conn: conn}}
|
||||
end
|
||||
|
||||
def release(%HTS221{conn: conn}), do: Driver.release(conn)
|
||||
end
|
||||
```
|
||||
"""
|
||||
|
||||
defmacro __using__(_env) do
|
||||
quote do
|
||||
@behaviour Wafer.Conn
|
||||
end
|
||||
|
||||
Protocol.assert_impl!(Wafer.Release, __MODULE__)
|
||||
end
|
||||
|
||||
@type t :: any
|
||||
@type options :: [option]
|
||||
@type option :: {atom, any}
|
||||
|
@ -37,9 +43,4 @@ defmodule Wafer.Conn do
|
|||
Acquire a connection to a peripheral using the provided driver.
|
||||
"""
|
||||
@callback acquire(options) :: {:ok, t} | {:error, reason :: any}
|
||||
|
||||
@doc """
|
||||
Release all resources associated with this connection.
|
||||
"""
|
||||
@callback release(module) :: :ok | {:error, reason :: any}
|
||||
end
|
||||
|
|
|
@ -36,14 +36,19 @@ defmodule Wafer.Driver.Circuits.GPIO do
|
|||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Wafer.Release, for: Wafer.Driver.Circuits.GPIO do
|
||||
alias Wafer.Driver.Circuits.GPIO.Wrapper
|
||||
alias Wafer.Driver.Circuits.GPIO
|
||||
|
||||
@doc """
|
||||
Release all resources related to this GPIO pin connection.
|
||||
|
||||
Note that other connections may still be using the pin.
|
||||
"""
|
||||
@spec release(t) :: :ok | {:error, reason :: any}
|
||||
def release(%__MODULE__{ref: ref} = _conn) when is_reference(ref), do: Wrapper.close(ref)
|
||||
@spec release(GPIO.t()) :: :ok | {:error, reason :: any}
|
||||
def release(%GPIO{ref: ref} = _conn) when is_reference(ref), do: Wrapper.close(ref)
|
||||
end
|
||||
|
||||
defimpl Wafer.GPIO, for: Wafer.Driver.Circuits.GPIO do
|
||||
|
|
|
@ -38,9 +38,17 @@ defmodule Wafer.Driver.Circuits.I2C do
|
|||
{:error, reason}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@spec release(t) :: :ok | {:error, reason :: any}
|
||||
def release(%__MODULE__{ref: ref} = _conn), do: Wrapper.close(ref)
|
||||
defimpl Wafer.Release, for: Wafer.Driver.Circuits.I2C do
|
||||
alias Wafer.Driver.Circuits.I2C.Wrapper
|
||||
alias Wafer.Driver.Circuits.I2C
|
||||
|
||||
@doc """
|
||||
Release all resources associated with this device.
|
||||
"""
|
||||
@spec release(I2C.t()) :: :ok | {:error, reason :: any}
|
||||
def release(%I2C{ref: ref} = _conn), do: Wrapper.close(ref)
|
||||
end
|
||||
|
||||
defimpl Wafer.Chip, for: Wafer.Driver.Circuits.I2C do
|
||||
|
|
|
@ -34,12 +34,17 @@ defmodule Wafer.Driver.Circuits.SPI do
|
|||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Wafer.Release, for: Wafer.Driver.Circuits.SPI do
|
||||
alias Wafer.Driver.Circuits.SPI.Wrapper
|
||||
alias Wafer.Driver.Circuits.SPI
|
||||
|
||||
@doc """
|
||||
Close the SPI bus connection.
|
||||
"""
|
||||
@spec release(t) :: :ok | {:error, reason :: any}
|
||||
def release(%__MODULE__{ref: ref} = _conn) when is_reference(ref), do: Wrapper.close(ref)
|
||||
@spec release(SPI.t()) :: :ok | {:error, reason :: any}
|
||||
def release(%SPI{ref: ref} = _conn) when is_reference(ref), do: Wrapper.close(ref)
|
||||
end
|
||||
|
||||
defimpl Wafer.SPI, for: Wafer.Driver.Circuits.SPI do
|
||||
|
|
|
@ -35,14 +35,19 @@ defmodule Wafer.Driver.ElixirALE.GPIO do
|
|||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Wafer.Release, for: Wafer.Driver.ElixirALE.GPIO do
|
||||
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
|
||||
alias Wafer.Driver.ElixirALE.GPIO
|
||||
|
||||
@doc """
|
||||
Release all resources related to this GPIO pin connection.
|
||||
|
||||
Note that other connections may still be using the pin.
|
||||
"""
|
||||
@spec release(t) :: :ok | {:error, reason :: any}
|
||||
def release(%__MODULE__{pid: pid} = _conn), do: Wrapper.release(pid)
|
||||
@spec release(GPIO.t()) :: :ok | {:error, reason :: any}
|
||||
def release(%GPIO{pid: pid} = _conn), do: Wrapper.release(pid)
|
||||
end
|
||||
|
||||
defimpl Wafer.GPIO, for: Wafer.Driver.ElixirALE.GPIO do
|
||||
|
|
|
@ -38,9 +38,17 @@ defmodule Wafer.Driver.ElixirALE.I2C do
|
|||
{:error, reason}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@spec release(t) :: :ok | {:error, reason :: any}
|
||||
def release(%__MODULE__{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
|
||||
defimpl Wafer.Release, for: Wafer.Driver.ElixirALE.I2C do
|
||||
alias Wafer.Driver.ElixirALE.I2C.Wrapper
|
||||
alias Wafer.Driver.ElixirALE.I2C
|
||||
|
||||
@doc """
|
||||
Release all resources associated with this I2C device.
|
||||
"""
|
||||
@spec release(I2C.t()) :: :ok | {:error, reason :: any}
|
||||
def release(%I2C{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
|
||||
end
|
||||
|
||||
defimpl Wafer.Chip, for: Wafer.Driver.ElixirALE.I2C do
|
||||
|
|
|
@ -35,12 +35,17 @@ defmodule Wafer.Driver.ElixirALE.SPI do
|
|||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Wafer.Release, for: Wafer.Driver.ElixirALE.SPI do
|
||||
alias Wafer.Driver.ElixirALE.SPI.Wrapper
|
||||
alias Wafer.Driver.ElixirALE.SPI
|
||||
|
||||
@doc """
|
||||
Close the SPI bus connection.
|
||||
"""
|
||||
@spec release(t) :: :ok | {:error, reason :: any}
|
||||
def release(%__MODULE__{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
|
||||
@spec release(SPI.t()) :: :ok | {:error, reason :: any}
|
||||
def release(%SPI{pid: pid} = _conn) when is_pid(pid), do: Wrapper.release(pid)
|
||||
end
|
||||
|
||||
defimpl Wafer.SPI, for: Wafer.Driver.ElixirALE.SPI do
|
||||
|
|
|
@ -22,9 +22,6 @@ defmodule Wafer.Driver.Fake do
|
|||
{:ok, %__MODULE__{opts: opts}}
|
||||
end
|
||||
|
||||
@impl Wafer.Conn
|
||||
def release(%__MODULE__{}), do: :ok
|
||||
|
||||
defp emit_warning do
|
||||
:wafer
|
||||
|> Application.get_env(__MODULE__)
|
||||
|
@ -32,6 +29,10 @@ defmodule Wafer.Driver.Fake do
|
|||
end
|
||||
end
|
||||
|
||||
defimpl Wafer.Release, for: Wafer.Driver.Fake do
|
||||
def release(%Wafer.Driver.Fake{}), do: :ok
|
||||
end
|
||||
|
||||
defimpl Wafer.Chip, for: Wafer.Driver.Fake do
|
||||
import Wafer.Guards
|
||||
|
||||
|
|
55
lib/wafer/release.ex
Normal file
55
lib/wafer/release.ex
Normal file
|
@ -0,0 +1,55 @@
|
|||
defprotocol Wafer.Release do
|
||||
alias Wafer.Conn
|
||||
|
||||
@moduledoc """
|
||||
A protocol for releasing connections. The opposite of `Conn`'s `acquire/1`.
|
||||
|
||||
## Deriving
|
||||
|
||||
If you're implementing your own `Conn` type that simply delegates to one of
|
||||
the lower level drivers that you can derive this protocol automatically:
|
||||
|
||||
```elixir
|
||||
defstruct MyConn do
|
||||
@derive Wafer.Release
|
||||
defstruct [:conn]
|
||||
end
|
||||
```
|
||||
|
||||
If your type uses a key other than `conn` for the inner connection you can specify it while deriving:
|
||||
|
||||
```elixir
|
||||
defstruct MyConn do
|
||||
@derive {Wafer.Release, key: :pin_conn}
|
||||
defstruct [:pin_conn]
|
||||
end
|
||||
```
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Release all resources associated with the connection. Usually in preparation
|
||||
for shutdown.
|
||||
"""
|
||||
@spec release(Conn.t()) :: :ok
|
||||
def release(conn)
|
||||
end
|
||||
|
||||
defimpl Wafer.Release, for: Any do
|
||||
defmacro __deriving__(module, struct, options) do
|
||||
key = Keyword.get(options, :key, :conn)
|
||||
|
||||
unless Map.has_key?(struct, key) do
|
||||
raise(
|
||||
"Unable to derive `Wafer.Release` for `#{module}`: key `#{inspect(key)}` not present in struct."
|
||||
)
|
||||
end
|
||||
|
||||
quote do
|
||||
defimpl Wafer.Release, for: unquote(module) do
|
||||
def release(%{unquote(key) => inner_conn}), do: Wafer.Release.release(inner_conn)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def release(unknown), do: {:error, "`Wafer.Release` not implemented for #{inspect(unknown)}"}
|
||||
end
|
|
@ -5,6 +5,7 @@ defmodule WaferDriverCircuits.GPIOTest do
|
|||
alias Wafer.Driver.Circuits.GPIO.Dispatcher, as: Dispatcher
|
||||
alias Wafer.Driver.Circuits.GPIO.Wrapper
|
||||
alias Wafer.GPIO, as: GPIO
|
||||
alias Wafer.Release, as: Release
|
||||
@moduledoc false
|
||||
|
||||
describe "acquire/1" do
|
||||
|
@ -25,7 +26,7 @@ defmodule WaferDriverCircuits.GPIOTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "release/1" do
|
||||
describe "Release.release/1" do
|
||||
test "closes the pin" do
|
||||
conn = conn()
|
||||
|
||||
|
@ -35,7 +36,7 @@ defmodule WaferDriverCircuits.GPIOTest do
|
|||
:ok
|
||||
end)
|
||||
|
||||
assert :ok = Subject.release(conn)
|
||||
assert :ok = Release.release(conn)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule WaferCircuits.I2CTest do
|
|||
alias Wafer.Chip
|
||||
alias Wafer.Driver.Circuits.I2C, as: Subject
|
||||
alias Wafer.Driver.Circuits.I2C.Wrapper
|
||||
alias Wafer.I2C
|
||||
alias Wafer.{Release, I2C}
|
||||
@moduledoc false
|
||||
|
||||
describe "acquire/1" do
|
||||
|
@ -72,7 +72,7 @@ defmodule WaferCircuits.I2CTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "release/1" do
|
||||
describe "Release.release/1" do
|
||||
test "closes the bus connection" do
|
||||
conn = conn()
|
||||
|
||||
|
@ -82,7 +82,7 @@ defmodule WaferCircuits.I2CTest do
|
|||
:ok
|
||||
end)
|
||||
|
||||
assert :ok = Subject.release(conn)
|
||||
assert :ok = Release.release(conn)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ defmodule WaferCircuits.SPITest do
|
|||
use Mimic
|
||||
alias Wafer.Driver.Circuits.SPI, as: Subject
|
||||
alias Wafer.Driver.Circuits.SPI.Wrapper
|
||||
alias Wafer.SPI
|
||||
alias Wafer.{Release, SPI}
|
||||
@moduledoc false
|
||||
|
||||
describe "acquire/1" do
|
||||
|
@ -23,7 +23,7 @@ defmodule WaferCircuits.SPITest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "release/1" do
|
||||
describe "Release.release/1" do
|
||||
test "closes the bus connection" do
|
||||
conn = conn()
|
||||
|
||||
|
@ -33,7 +33,7 @@ defmodule WaferCircuits.SPITest do
|
|||
:ok
|
||||
end)
|
||||
|
||||
assert :ok = Subject.release(conn)
|
||||
assert :ok = Release.release(conn)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ defmodule WaferDriverElixirALE.GPIOTest do
|
|||
alias Wafer.Driver.ElixirALE.GPIO.Dispatcher, as: Dispatcher
|
||||
alias Wafer.Driver.ElixirALE.GPIO.Wrapper
|
||||
alias Wafer.GPIO, as: GPIO
|
||||
alias Wafer.Release, as: Release
|
||||
@moduledoc false
|
||||
|
||||
describe "acquire/1" do
|
||||
|
@ -25,7 +26,7 @@ defmodule WaferDriverElixirALE.GPIOTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "release/1" do
|
||||
describe "Release.release/1" do
|
||||
test "closes the pin" do
|
||||
conn = conn()
|
||||
|
||||
|
@ -35,7 +36,7 @@ defmodule WaferDriverElixirALE.GPIOTest do
|
|||
:ok
|
||||
end)
|
||||
|
||||
assert :ok = Subject.release(conn)
|
||||
assert :ok = Release.release(conn)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule WaferElixirALE.I2CTest do
|
|||
alias Wafer.Chip
|
||||
alias Wafer.Driver.ElixirALE.I2C, as: Subject
|
||||
alias Wafer.Driver.ElixirALE.I2C.Wrapper
|
||||
alias Wafer.I2C
|
||||
alias Wafer.{Release, I2C}
|
||||
@moduledoc false
|
||||
|
||||
describe "acquire/1" do
|
||||
|
@ -75,7 +75,7 @@ defmodule WaferElixirALE.I2CTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "release/1" do
|
||||
describe "Release.release/1" do
|
||||
test "closes the bus connection" do
|
||||
conn = conn()
|
||||
|
||||
|
@ -85,7 +85,7 @@ defmodule WaferElixirALE.I2CTest do
|
|||
:ok
|
||||
end)
|
||||
|
||||
assert :ok = Subject.release(conn)
|
||||
assert :ok = Release.release(conn)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ defmodule WaferElixirALE.SPITest do
|
|||
use Mimic
|
||||
alias Wafer.Driver.ElixirALE.SPI, as: Subject
|
||||
alias Wafer.Driver.ElixirALE.SPI.Wrapper
|
||||
alias Wafer.SPI
|
||||
alias Wafer.{Release, SPI}
|
||||
@moduledoc false
|
||||
|
||||
describe "acquire/1" do
|
||||
|
@ -24,7 +24,7 @@ defmodule WaferElixirALE.SPITest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "release/1" do
|
||||
describe "Release.release/1" do
|
||||
test "closes the bus connection" do
|
||||
conn = conn()
|
||||
|
||||
|
@ -34,7 +34,7 @@ defmodule WaferElixirALE.SPITest do
|
|||
:ok
|
||||
end)
|
||||
|
||||
assert :ok = Subject.release(conn)
|
||||
assert :ok = Release.release(conn)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue