aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/examples/uds_dist/src/uds.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/examples/uds_dist/src/uds.erl')
-rw-r--r--lib/kernel/examples/uds_dist/src/uds.erl166
1 files changed, 166 insertions, 0 deletions
diff --git a/lib/kernel/examples/uds_dist/src/uds.erl b/lib/kernel/examples/uds_dist/src/uds.erl
new file mode 100644
index 0000000000..ae1a78c44b
--- /dev/null
+++ b/lib/kernel/examples/uds_dist/src/uds.erl
@@ -0,0 +1,166 @@
+-module(uds).
+
+-export([listen/1, connect/1, accept/1, send/2, recv/1, close/1,
+ get_port/1, get_status_counters/1, set_mode/2, controlling_process/2,
+ tick/1, get_creation/1]).
+
+-define(decode(A,B,C,D), (((A) bsl 24) bor
+ ((B) bsl 16) bor ((C) bsl 8) bor (D))).
+-define(encode(N), [(((N) bsr 24) band 16#FF), (((N) bsr 16) band 16#FF),
+ (((N) bsr 8) band 16#FF), ((N) band 16#FF)]).
+-define(check_server(), case whereis(uds_server) of
+ undefined ->
+ exit(uds_server_not_started);
+ _ ->
+ ok
+ end).
+
+listen(Name) ->
+ ?check_server(),
+ command(port(),$L,Name).
+
+
+connect(Name) ->
+ ?check_server(),
+ command(port(),$C,Name).
+
+accept(Port) ->
+ ?check_server(),
+ case control(Port,$N) of
+ {ok, N} ->
+ command(port(),$A,N);
+ Else ->
+ Else
+ end.
+
+send(Port,Data) ->
+ ?check_server(),
+ command(Port, $S, Data).
+
+recv(Port) ->
+ ?check_server(),
+ command(Port, $R, []).
+
+close(Port) ->
+ ?check_server(),
+ (catch unlink(Port)), %% Avoids problem with trap exits.
+ case (catch erlang:port_close(Port)) of
+ {'EXIT', Reason} ->
+ {error, closed};
+ _ ->
+ ok
+ end.
+
+get_port(Port) ->
+ ?check_server(),
+ {ok,Port}.
+
+get_status_counters(Port) ->
+ ?check_server(),
+ case control(Port, $S) of
+ {ok, {C0, C1, C2}} ->
+ {ok, C0, C1, C2};
+ Other ->
+ Other
+ end.
+
+get_creation(Port) ->
+ ?check_server(),
+ case control(Port, $R) of
+ {ok, [A]} ->
+ A;
+ Else ->
+ Else
+ end.
+
+
+set_mode(Port, command) ->
+ ?check_server(),
+ control(Port,$C);
+set_mode(Port,intermediate) ->
+ ?check_server(),
+ control(Port,$I);
+set_mode(Port,data) ->
+ ?check_server(),
+ control(Port,$D).
+
+tick(Port) ->
+ ?check_server(),
+ control(Port,$T).
+
+controlling_process(Port, Pid) ->
+ ?check_server(),
+ case (catch erlang:port_connect(Port, Pid)) of
+ true ->
+ (catch unlink(Port)),
+ ok;
+ {'EXIT', {badarg, _}} ->
+ {error, closed};
+ Else ->
+ exit({unexpected_driver_response, Else})
+ end.
+
+
+control(Port, Command) ->
+ case (catch erlang:port_control(Port, Command, [])) of
+ [0] ->
+ ok;
+ [0,A] ->
+ {ok, [A]};
+ [0,A,B,C,D] ->
+ {ok, [A,B,C,D]};
+ [0,A1,B1,C1,D1,A2,B2,C2,D2,A3,B3,C3,D3] ->
+ {ok, {?decode(A1,B1,C1,D1),?decode(A2,B2,C2,D2),
+ ?decode(A3,B3,C3,D3)}};
+ [1|Error] ->
+ exit({error, list_to_atom(Error)});
+ {'EXIT', {badarg, _}} ->
+ {error, closed};
+ Else ->
+ exit({unexpected_driver_response, Else})
+ end.
+
+
+command(Port, Command, Parameters) ->
+ SavedTrapExit = process_flag(trap_exit,true),
+ case (catch erlang:port_command(Port,[Command | Parameters])) of
+ true ->
+ receive
+ {Port, {data, [Command, $o, $k]}} ->
+ process_flag(trap_exit,SavedTrapExit),
+ {ok, Port};
+ {Port, {data, [Command |T]}} ->
+ process_flag(trap_exit,SavedTrapExit),
+ {ok, T};
+ {Port, Else} ->
+ process_flag(trap_exit,SavedTrapExit),
+ exit({unexpected_driver_response, Else});
+ {'EXIT', Port, normal} ->
+ process_flag(trap_exit,SavedTrapExit),
+ {error, closed};
+ {'EXIT', Port, Error} ->
+ process_flag(trap_exit,SavedTrapExit),
+ exit(Error)
+ end;
+ {'EXIT', {badarg, _}} ->
+ process_flag(trap_exit,SavedTrapExit),
+ {error, closed};
+ Unexpected ->
+ process_flag(trap_exit,SavedTrapExit),
+ exit({unexpected_driver_response, Unexpected})
+ end.
+
+port() ->
+ SavedTrapExit = process_flag(trap_exit,true),
+ case open_port({spawn, "uds_drv"},[]) of
+ P when port(P) ->
+ process_flag(trap_exit,SavedTrapExit),
+ P;
+ {'EXIT',Error} ->
+ process_flag(trap_exit,SavedTrapExit),
+ exit(Error);
+ Else ->
+ process_flag(trap_exit,SavedTrapExit),
+ exit({unexpected_driver_response, Else})
+ end.
+