[ifxmips]
[openwrt/svn-archive/archive.git] / package / libtapi / src / tapi-session.c
1 #include <stdlib.h>
2 #include <stdbool.h>
3 #include <stdint.h>
4
5 #include "tapi-device.h"
6 #include "tapi-port.h"
7 #include "tapi-session.h"
8
9 enum tapi_session_port_state {
10 TAPI_SESSION_PORT_STATE_IDLE,
11 TAPI_SESSION_PORT_STATE_RINGING,
12 TAPI_SESSION_PORT_STATE_ACTIVE,
13 };
14
15 struct tapi_session_port {
16 struct tapi_port *port;
17 struct tapi_port_event_listener event_listener;
18
19 enum tapi_session_port_state state;
20 };
21
22 struct tapi_session {
23 struct tapi_device *dev;
24 struct tapi_session_port caller;
25 struct tapi_session_port callee;
26
27 bool active;
28 unsigned int link;
29
30 void (*release)(struct tapi_session *session, void *data);
31 };
32
33 static void tapi_session_terminate(struct tapi_session *session)
34 {
35 if (session->active) {
36 tapi_link_enable(session->dev, session->link);
37 tapi_sync(session->dev);
38 tapi_link_free(session->dev, session->link);
39 }
40
41 switch (session->callee.state) {
42 case TAPI_SESSION_PORT_STATE_RINGING:
43 tapi_port_set_ring(session->callee.port, false);
44 break;
45 default:
46 break;
47 }
48
49 session->active = false;
50 }
51
52 static void tapi_session_caller_event(struct tapi_port *port,
53 struct tapi_event *event, void *data)
54 {
55 struct tapi_session *session = data;
56
57 if (event->type != TAPI_EVENT_TYPE_HOOK)
58 return;
59
60 if (event->hook.on) {
61 tapi_session_terminate(session);
62 }
63 }
64
65 static void tapi_session_callee_event(struct tapi_port *port,
66 struct tapi_event *event, void *data)
67 {
68 struct tapi_session *session = data;
69
70 if (event->type != TAPI_EVENT_TYPE_HOOK)
71 return;
72
73 if (event->hook.on) {
74 if (session->callee.state == TAPI_SESSION_PORT_STATE_ACTIVE) {
75 tapi_session_terminate(session);
76 }
77 } else {
78 if (session->callee.state == TAPI_SESSION_PORT_STATE_RINGING) {
79 tapi_port_set_ring(session->callee.port, false);
80 session->link = tapi_link_alloc(session->dev,
81 session->caller.port->ep, session->callee.port->ep);
82 session->callee.state = TAPI_SESSION_PORT_STATE_ACTIVE;
83 tapi_link_enable(session->dev, session->link);
84 tapi_sync(session->dev);
85 session->active = true;
86 }
87 }
88 }
89
90 struct tapi_session *tapi_session_alloc(struct tapi_device *dev,
91 struct tapi_port *caller, struct tapi_port *callee,
92 void (*release)(struct tapi_session *session, void *data), void *release_data)
93 {
94 struct tapi_session *session;
95 struct tapi_session_port *session_port;
96
97 session = malloc(sizeof(*session));
98
99 session->dev = dev;
100
101 session->callee.port = callee;
102 session->callee.state = TAPI_SESSION_PORT_STATE_RINGING;
103 session->callee.event_listener.callback = tapi_session_callee_event;
104 session->callee.event_listener.data = session;
105 tapi_port_register_event(callee, &session->callee.event_listener);
106
107 session->caller.port = caller;
108 session->caller.state = TAPI_SESSION_PORT_STATE_ACTIVE;
109 session->caller.event_listener.callback = tapi_session_caller_event;
110 session->caller.event_listener.data = session;
111 tapi_port_register_event(caller, &session->caller.event_listener);
112
113 tapi_port_set_ring(callee, true);
114 }
115
116 void tapi_session_free(struct tapi_session *session)
117 {
118 tapi_session_terminate(session);
119 tapi_port_register_event(session->callee.port, &session->callee.event_listener);
120 tapi_port_register_event(session->caller.port, &session->caller.event_listener);
121 free(session);
122 }