aboutsummaryrefslogtreecommitdiff
path: root/src/gpio.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpio.erl')
-rw-r--r--src/gpio.erl82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/gpio.erl b/src/gpio.erl
new file mode 100644
index 0000000..99da9be
--- /dev/null
+++ b/src/gpio.erl
@@ -0,0 +1,82 @@
+%%% @author Guido Günther <agx@sigxcpu.org>
+%%% @copyright (C) 2016, Guido Günther
+%%% @doc
+%%% Read and write GPIO values from userspace
+%%%
+%%% @reference https://www.kernel.org/doc/Documentation/gpio/sysfs.txt
+%%% @end
+%%% License: LGLv3
+-module(gpio).
+
+-export([export/1,
+ get_exported/0,
+ get_direction/1,
+ read/1,
+ set_direction/2,
+ unexport/1,
+ write/2]).
+
+-define(GPIO_BASE, "/sys/class/gpio/").
+-define(GPIO_EXPORT, ?GPIO_BASE ++ "export").
+-define(GPIO_UNEXPORT, ?GPIO_BASE ++ "unexport").
+
+-type direction() :: in | out | low | high.
+-type pin() :: pos_integer().
+
+% @doc: write to GPIO pin
+-spec write(Pin::pin(), 0 | 1) -> ok | {error, any()}.
+write(Pin, Value) ->
+ Sysfs = pin_sysfs_path(Pin, value),
+ Out = io_lib:format("~p", [Value]),
+ file:write_file(Sysfs, Out).
+
+% @doc: read from GPIO pin
+-spec read(Pin::pin()) -> {ok, 0 | 1} | {error, atom()}.
+read(Pin) ->
+ Sysfs = pin_sysfs_path(Pin, value),
+ {ok, Data} = file:read_file(Sysfs),
+ case Data of
+ <<"0">> -> {ok, 0};
+ <<"1">> -> {ok, 1};
+ _-> {error, badval}
+ end.
+
+% @doc: export GPIO pin
+-spec export(Pin::pin()) -> ok | {error, any()}.
+export(Pin) ->
+ Out = io_lib:format("~p", [Pin]),
+ file:write_file(?GPIO_EXPORT, Out).
+
+% @doc: get list of exported GPIO pins
+-spec get_exported() -> {ok, list(pin())}.
+get_exported() ->
+ {ok, Files} = file:list_dir(?GPIO_BASE),
+ {ok, R} = re:compile("^gpio[0-9]+$"),
+ PinNames = [ X || X <- Files, nomatch /= re:run(X, R)],
+ {ok, [ Num || {Num, []} <-
+ [ string:to_integer(lists:nthtail(4, Pin)) || Pin <- PinNames ]]}.
+
+% @doc: unexport GPIO pin
+-spec unexport(Pin::pin()) -> ok | {error, any()}.
+unexport(Pin) ->
+ Out = io_lib:format("~p", [Pin]),
+ file:write_file(?GPIO_UNEXPORT, Out).
+
+% @doc: set GPIO pin direction
+-spec set_direction(Pin::pin(), D::direction()) -> ok | {error, any()}.
+set_direction(Pin, D) ->
+ Sysfs = pin_sysfs_path(Pin, direction),
+ Out = io_lib:format("~p", [D]),
+ file:write_file(Sysfs, Out).
+
+% @doc: get GPIO pin direction
+-spec get_direction(Pin::pin()) -> {ok, direction()} | {error, any()}.
+get_direction(Pin) ->
+ Sysfs = pin_sysfs_path(Pin, direction),
+ {ok, Data} = file:read_file(Sysfs),
+ {ok, list_to_atom(string:strip(binary:bin_to_list(Data), right, $\n))}.
+
+%% Private functions
+-spec pin_sysfs_path(Pin::pin(), atom() | binary()) -> string().
+pin_sysfs_path(Pin, File) ->
+ io_lib:format(?GPIO_BASE ++ "gpio~p/~p", [Pin, File]).