anchor.diff:      , request_event_async/2
       ] ).
   
  +% gen_server callbacks
  +-export(
  +    [ init/1, handle_call/3, handle_cast/2
  +    , handle_info/2, terminate/2, code_change/3
  +    ] ).
  +
   -include( "lurch_driver_protocol.hrl" ).
   
   -define( DRIVER_DIR, code:lib_dir( lurch, drivers ) ).
   -ifndef( TEST ).
   -define( DRIVER_TIMEOUT, 5000 ).
  +-define( CALL_TIMEOUT, 5100 ).
   -else.
   -define( DRIVER_TIMEOUT, 100 ).
  +-define( CALL_TIMEOUT, 200 ).
   -endif. % TEST
   
   -type msg_tag() :: reference().
  
positive.code: 
  -spec start( binary(), [ binary() ] ) -> { ok, pid() } | { error, term() }.
  start( Driver, Parameters ) ->
      { _, Tag } = From = from(),
      spawn( fun() -> enter_loop( Driver, Parameters, From ) end ),
      wait( Tag ).
  
  -spec start_link( binary(), [ binary() ] ) -> { ok, pid() } | { error, term() }.
  start_link( Driver, Parameters ) ->
      { _, Tag } = From = from(),
      spawn_link( fun() -> enter_loop( Driver, Parameters, From ) end ),
      wait( Tag ).
  
  -spec start_async( binary(), [ binary() ] ) -> { ok, msg_tag() }.
  start_async( Driver, Parameters ) ->
      { _, Tag } = From = from(),
      spawn_link( fun() -> enter_loop( Driver, Parameters, From ) end ),
      { ok, Tag }.
  
  -spec start_link_async( binary(), [ binary() ] ) -> { ok, msg_tag() }.
  start_link_async( Driver, Parameters ) ->
      { _, Tag } = From = from(),
      spawn_link( fun() -> enter_loop( Driver, Parameters, From ) end ),
      { ok, Tag }.
  
  -spec stop( pid() ) -> ok | { error, timeout }.
  stop( Pid ) ->
      { _, Tag } = From = from(),
      Pid ! { stop, From },
      wait( Tag ).
  
  -spec stop_async( pid() ) -> { ok, msg_tag() }.
  stop_async( Pid ) ->
      { _, Tag } = From = from(),
      Pid ! { stop, From },
      { ok, Tag }.
  
  -spec request_event( pid(), string() ) -> { ok, term() } | { error, timeout }.
  request_event( Pid, Event ) ->
      { _, Tag } = From = from(),
      Pid ! { { get_event,  Event }, From },
      wait( Tag ).
  
  -spec request_event_async( pid(), string() ) -> { ok, msg_tag() }.
  request_event_async( Pid, Event ) ->
      { _, Tag } = From = from(),
      Pid ! { { get_event, Event }, From },
      { ok, Tag }.
  
  
  %% ===================================================================
  %% Internal functions
  %% ===================================================================
  
  
  -spec from() -> { pid(), reference() }.
  from() ->
      { self(), make_ref() }.
  
  -spec wait( msg_tag() ) ->
      any() | { error, timeout }.
  wait( Tag ) ->
      receive
          { Result, Tag } -> Result
      after
          ?DRIVER_TIMEOUT -> { error, timeout }
      end.
  
  -spec enter_loop( string() | binary(),
                    [ string() | binary() ],
                    { pid(), msg_tag() } ) ->
      { ok, msg_tag() } | { { error, term() }, msg_tag() }.
  enter_loop( Driver, Parameters, { Pid, Tag } ) ->
      case start_driver( Driver, Parameters ) of
          { ok, Port } ->
              Pid ! { { ok, self() }, Tag },
              receive_loop( Port );
          Error ->
              Pid ! { Error, Tag }
      end.
  
  -spec receive_loop( port() ) -> { ok, msg_tag() }.
  receive_loop( Port ) ->
      receive
          { stop, { Pid, Tag } } ->
              stop_driver( Port ),
              Pid ! { ok, Tag };
  
          { { get_event, Event }, { Pid, Tag } } ->
              Pid ! { get_event( Port, Event ), Tag },
              receive_loop( Port )
      end.
  
  -spec start_driver( string() | binary(), [ string() | binary() ] ) ->
      { ok, port() } | { error, term() }.
  
negative.code: % @doc Provides communication mechanism to/from external driver
  
  -module( lurch_driver_port ).
  
  -behaviour( gen_server ).
  
  % API functions
  -export(
  