summaryrefslogtreecommitdiff
path: root/components/dlink_bt/src/bt_listener.erl
blob: e6129de3579cc4e1e66aab900426c2ce2fe0cc1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
%%
%% Copyright (C) 2014, Jaguar Land Rover
%%
%% This program is licensed under the terms and conditions of the
%% Mozilla Public License, version 2.0.  The full text of the
%% Mozilla Public License is at https://www.mozilla.org/MPL/2.0/
%%

%% Setup a listen socket and manage connections to remote parties.
%% Can also retrieve connections by peer address.
-module(bt_listener).

-include_lib("lager/include/log.hrl").
-include_lib("rvi_common/include/rvi_common.hrl").
-export([start_link/1,
         add_listener/1,
         remove_listener/1]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([terminate/2]).

-record(st, {listeners = [],
	     acceptors = [],
	     cs = #component_spec{}
	    }).


start_link(Mode) ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, Mode, []).

add_listener(Channel) ->
    gen_server:call(?MODULE, {add_listener, Channel}).

remove_listener(Channel) ->
    gen_server:call(?MODULE, {remove_listener, Channel}).

init(Mode) ->

    {ok, #st {
	    listeners = [],
	    acceptors = [],
	    cs = rvi_common:set_value(bt_mode, Mode, rvi_common:get_component_specification())
	   }
    }.


handle_call({add_listener, Channel}, _From, #st{cs = CS} = St) ->
    ?info("bt_listener:add_listener(): Setting up listener on channel ~p", [ Channel]),

    Mode = rvi_common:get_value(bt_mode, bt, CS),
    case listen(Mode, Channel) of
        {ok, ListenRef} ->
	    ?info("bt_listener:add_listener(): ListenRef: ~p", [ ListenRef]),
	    {ok, ConnPid} = bt_connection:accept(Channel,
						 ListenRef,
						 Mode,
						 dlink_bt_rpc,
						 handle_socket,
						 CS),



     	    %%{ noreply, NSt} = handle_info({accept, ListenRef, Channel, ok}, St),

	    { reply,
	      ok,
	      St#st {
		acceptors = [ { Channel, ConnPid } | St#st.acceptors ],
		listeners = [ { ListenRef, Channel } | St#st.listeners ]
	       }
	    };

	Err ->
	    ?info("bt_listener:add_listener(): Failed: ~p", [ Err]),
	    {reply, Err, St}

    end;

handle_call({remove_listener, _Channel}, _From, State) ->
    ?warning("FIXME: bt_listener:remove_listener()"),
    {reply, ok, State};

handle_call(_Msg, _From, State) ->
    {reply, ignored, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info({accept, ListenRef, BTAddr, Channel, ok} , St) ->
    %% Fire up a new process to handle the
    %% future incoming connection.
    ?info("bt_listener:accept(): ListenRef: ~p", [ ListenRef]),
    ?info("bt_listener:accept(): Remote: ~p-~p", [BTAddr, Channel ]),

    %% Must fix multiple acceptors in bt_linux_drv.c
    %% {ok, ConnPid} = bt_connection:accept(Channel,
    %%  					 ListenRef,
    %%  					 dlink_bt_rpc,
    %% 					 handle_socket,
    %%  					 []),


    %% {noreply, St#st {acceptors = [ { Channel, ConnPid } | St#st.acceptors ]}};
    {noreply, St };

handle_info(_Msg, State) ->
    ?info("bt_listener:handle_info(): Unknown: ~p", [ _Msg]),

    {noreply, State}.

terminate(_Reason, _State) ->
    ok.


listen(bt, Channel) ->
    rfcomm:listen(Channel);
listen(tcp, Port) ->
    gen_tcp:listen(Port).