Skip to content

Instantly share code, notes, and snippets.

@msantos
Created September 22, 2011 15:28
Show Gist options
  • Select an option

  • Save msantos/1235063 to your computer and use it in GitHub Desktop.

Select an option

Save msantos/1235063 to your computer and use it in GitHub Desktop.

Revisions

  1. msantos created this gist Sep 22, 2011.
    215 changes: 215 additions & 0 deletions serctl.erl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,215 @@
    %% Copyright (c) 2011, Michael Santos <michael.santos@gmail.com>
    %% All rights reserved.
    %%
    %% Redistribution and use in source and binary forms, with or without
    %% modification, are permitted provided that the following conditions
    %% are met:
    %%
    %% Redistributions of source code must retain the above copyright
    %% notice, this list of conditions and the following disclaimer.
    %%
    %% Redistributions in binary form must reproduce the above copyright
    %% notice, this list of conditions and the following disclaimer in the
    %% documentation and/or other materials provided with the distribution.
    %%
    %% Neither the name of the author nor the names of its contributors
    %% may be used to endorse or promote products derived from this software
    %% without specific prior written permission.
    %%
    %% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    %% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    %% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
    %% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    %% COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    %% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    %% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    %% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    %% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    %% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
    %% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    %% POSSIBILITY OF SUCH DAMAGE.
    -module(serctl).
    -include("serctl.hrl").

    -export([
    open/1,
    close/1,

    read/2,
    write/2,

    tcgetattr/1,
    tcsetattr/3,

    cfsetispeed/2,
    cfsetospeed/2,

    termios/1, termios/2
    ]).
    -export([
    init/0
    ]).


    -on_load(on_load/0).


    %%--------------------------------------------------------------------
    %%% NIF Stubs
    %%--------------------------------------------------------------------
    init() ->
    on_load().

    on_load() ->
    erlang:load_nif(progname(), []).

    open(_) ->
    erlang:error(not_implemented).

    close(_) ->
    erlang:error(not_implemented).

    read(_,_) ->
    erlang:error(not_implemented).

    write(_,_) ->
    erlang:error(not_implemented).

    tcgetattr(_) ->
    erlang:error(not_implemented).

    tcsetattr(_,_,_) ->
    erlang:error(not_implemented).

    cfsetispeed(_,_) ->
    erlang:error(not_implemented).

    cfsetospeed(_,_) ->
    erlang:error(not_implemented).


    %%--------------------------------------------------------------------
    %%% API
    %%--------------------------------------------------------------------
    termios(Attr) ->
    termios(os(), Attr).

    termios(linux, <<
    Iflag:?UINT32, % input mode flags
    Oflag:?UINT32, % output mode flags
    Cflag:?UINT32, % control mode flags
    Lflag:?UINT32, % local mode flags
    Line:8, % line discipline
    Cc:?NCCS_LINUX/bytes, % control characters
    Rest/binary>>) ->
    Pad = pad(1+byte_size(Cc)),
    <<
    _:Pad,
    Ispeed:?UINT32, % input speed
    Ospeed:?UINT32 % output speed
    >> = Rest,
    #termios{
    iflag = Iflag,
    oflag = Oflag,
    cflag = Cflag,
    lflag = Lflag,
    line = Line,
    cc = Cc,
    ispeed = Ispeed,
    ospeed = Ospeed
    };
    termios(bsd, <<
    Iflag:?UINT32, % input mode flags
    Oflag:?UINT32, % output mode flags
    Cflag:?UINT32, % control mode flags
    Lflag:?UINT32, % local mode flags
    Line:8, % line discipline
    Cc:?NCCS_BSD/bytes, % control characters
    Rest/binary
    >>) ->
    Pad = pad(1+byte_size(Cc)),
    <<
    _:Pad,
    Ispeed:?UINT32, % input speed
    Ospeed:?UINT32 % output speed
    >> = Rest,
    #termios{
    iflag = Iflag,
    oflag = Oflag,
    cflag = Cflag,
    lflag = Lflag,
    line = Line,
    cc = Cc,
    ispeed = Ispeed,
    ospeed = Ospeed
    };
    termios(linux, #termios{
    iflag = Iflag,
    oflag = Oflag,
    cflag = Cflag,
    lflag = Lflag,
    line = Line,
    cc = Cc,
    ispeed = Ispeed,
    ospeed = Ospeed
    }) when byte_size(Cc) == ?NCCS_LINUX ->
    Pad = pad(1+?NCCS_LINUX),
    <<
    Iflag:?UINT32BE,
    Oflag:?UINT32BE,
    Cflag:?UINT32BE,
    Lflag:?UINT32BE,
    Line:8,
    Cc/bytes,
    0:Pad,
    Ispeed:?UINT32BE,
    Ospeed:?UINT32BE
    >>;
    termios(bsd, #termios{
    iflag = Iflag,
    oflag = Oflag,
    cflag = Cflag,
    lflag = Lflag,
    line = Line,
    cc = Cc,
    ispeed = Ispeed,
    ospeed = Ospeed
    }) when byte_size(Cc) == ?NCCS_BSD ->
    Pad = pad(1+?NCCS_BSD),
    <<
    Iflag:?UINT32BE,
    Oflag:?UINT32BE,
    Cflag:?UINT32BE,
    Lflag:?UINT32BE,
    Line:8,
    Cc/bytes,
    0:Pad,
    Ispeed:?UINT32BE,
    Ospeed:?UINT32BE
    >>.


    %%--------------------------------------------------------------------
    %%% Internal functions
    %%--------------------------------------------------------------------
    progname() ->
    filename:join([
    filename:dirname(code:which(?MODULE)),
    "..",
    "priv",
    ?MODULE
    ]).

    os() ->
    case os:type() of
    {unix, linux} -> linux;
    {unix, darwin} -> bsd;
    {unix, freebsd} -> bsd;
    {unix, netbsd} -> bsd;
    {unix, openbsd} -> bsd
    end.

    % Returns pad size in *bits*
    pad(N) ->
    Size = erlang:system_info({wordsize, internal}),
    (Size - (N rem Size)) * 8.