%% Copyright (c) 2011, Michael Santos %% 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.