1 #include <linux/input.h>
14 #include "tapi-port.h"
15 #include "dialdetector.h"
17 static const struct itimerspec dialdetector_timeout
= {
21 static const struct itimerspec dialdetector_impulse_timeout
= {
22 .it_value
.tv_nsec
= 200000000,
25 static void dialdetector_note_digit(struct dialdetector
*d
, unsigned char digit
)
27 printf("note digit: %d\n", d
->num_digits
);
29 d
->digits
[d
->num_digits
] = digit
;
32 timerfd_settime(d
->timer_fd
, 0, &dialdetector_timeout
, NULL
);
33 d
->dial_state
= DIALDETECTOR_DIAL_WAIT_TIMEOUT
;
36 static void dialdetector_reset(struct dialdetector
*d
)
40 d
->dial_state
= DIALDETECTOR_DIAL_WAIT
;
41 d
->port_state
= DIALDETECTOR_PORT_INACTIVE
;
44 static bool dialdetector_timeout_event(int events
, void *data
)
47 struct dialdetector
*dialdetector
= data
;
51 read(dialdetector
->timer_fd
, &tmp
, sizeof(tmp
));
53 for (i
= 0; i
< dialdetector
->num_digits
; ++i
) {
54 num
[i
] = '0' + dialdetector
->digits
[i
];
58 dialdetector
->dial_callback(dialdetector
->port
, dialdetector
->num_digits
,
59 dialdetector
->digits
);
61 dialdetector_reset(dialdetector
);
66 static bool dialdetector_impulse_timeout_cb(int events
, void *data
)
68 struct dialdetector
*d
= data
;
71 read(d
->impulse_timer_fd
, &tmp
, sizeof(tmp
));
73 if (d
->port_state
== DIALDETECTOR_PORT_ACTIVE_DOWN
) {
74 d
->port_state
= DIALDETECTOR_PORT_INACTIVE
;
76 printf("impulse: %d\n", d
->impulses
);
78 dialdetector_note_digit(d
, d
->impulses
< 10 ? d
->impulses
: 0);
85 static void dialdetector_port_event(struct tapi_port
*port
,
86 struct tapi_event
*event
, void *data
)
88 struct dialdetector
*d
= data
;
90 printf("port event: %d %d\n", d
->port_state
, event
->hook
.on
);
92 switch (d
->port_state
) {
93 case DIALDETECTOR_PORT_INACTIVE
:
94 if (event
->type
== TAPI_EVENT_TYPE_HOOK
&& event
->hook
.on
== false)
95 d
->port_state
= DIALDETECTOR_PORT_ACTIVE
;
97 case DIALDETECTOR_PORT_ACTIVE
:
98 switch (event
->type
) {
99 case TAPI_EVENT_TYPE_HOOK
:
100 if (event
->hook
.on
== true) {
101 d
->port_state
= DIALDETECTOR_PORT_ACTIVE_DOWN
;
102 timerfd_settime(d
->impulse_timer_fd
, 0, &dialdetector_impulse_timeout
, NULL
);
105 case TAPI_EVENT_TYPE_DTMF
:
106 dialdetector_note_digit(d
, event
->dtmf
.code
);
110 case DIALDETECTOR_PORT_ACTIVE_DOWN
:
111 if (event
->type
== TAPI_EVENT_TYPE_HOOK
&& event
->hook
.on
== false) {
112 timerfd_settime(d
->timer_fd
, 0, &dialdetector_timeout
, NULL
);
114 d
->port_state
= DIALDETECTOR_PORT_ACTIVE
;
120 struct dialdetector
*dialdetector_alloc(struct tapi_port
*port
)
122 struct dialdetector
*dialdetector
;
123 dialdetector
= malloc(sizeof(*dialdetector
));
125 dialdetector
->timer_fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
126 dialdetector
->impulse_timer_fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
127 dialdetector
->port
= port
;
128 dialdetector
->num_digits
= 0;
129 dialdetector
->impulses
= 0;
130 dialdetector
->dial_state
= DIALDETECTOR_DIAL_WAIT
;
131 dialdetector
->port_state
= DIALDETECTOR_PORT_INACTIVE
;
133 dialdetector
->timeout_cb
.callback
= dialdetector_timeout_event
;
134 dialdetector
->timeout_cb
.data
= dialdetector
;
135 dialdetector
->impulse_cb
.callback
= dialdetector_impulse_timeout_cb
;
136 dialdetector
->impulse_cb
.data
= dialdetector
;
138 dialdetector
->port_listener
.callback
= dialdetector_port_event
;
139 dialdetector
->port_listener
.data
= dialdetector
;
141 tapi_port_register_event(port
, &dialdetector
->port_listener
);
143 event_register(dialdetector
->impulse_timer_fd
, EPOLLIN
,
144 &dialdetector
->impulse_cb
);
145 event_register(dialdetector
->timer_fd
, EPOLLIN
, &dialdetector
->timeout_cb
);