diff options
Diffstat (limited to 'package/libtapi/src/dialdetector.c')
-rw-r--r-- | package/libtapi/src/dialdetector.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/package/libtapi/src/dialdetector.c b/package/libtapi/src/dialdetector.c new file mode 100644 index 0000000000..ff91b37aa2 --- /dev/null +++ b/package/libtapi/src/dialdetector.c @@ -0,0 +1,109 @@ +#include <linux/input.h> +#include <sys/epoll.h> +#include <stdint.h> +#include <stdbool.h> + + +#include <stdlib.h> +#include <stdio.h> + +#include "events.h" +#include "timerfd.h" + +#include "tapi-port.h" +#include "dialdetector.h" + +static const struct itimerspec dialdetector_timeout = { + .it_value.tv_sec = 3, +}; + +static void dialdetector_note_digit(struct dialdetector *d, unsigned char digit) +{ + printf("note digit: %d\n", d->num_digits); + d->digits[d->num_digits] = digit; + ++d->num_digits; +} + +static void dialdetector_reset(struct dialdetector *d) +{ + event_unregister(d->timer_fd); + d->num_digits = 0; + d->state = DIALDETECTOR_IDLE; +} + +static bool dialdetector_timeout_event(int events, void *data) +{ + char num[20]; + struct dialdetector *dialdetector = data; + int i; + + for (i = 0; i < dialdetector->num_digits; ++i) { + num[i] = '0' + dialdetector->digits[i]; + } + num[i] = '\0'; + + printf("Dialing: %s\n", num); + dialdetector->dial_callback(dialdetector->port, dialdetector->num_digits, + dialdetector->digits); + + dialdetector_reset(dialdetector); + + return false; +} + +static void dialdetector_port_event(struct tapi_port *port, + struct tapi_event *event, void *data) +{ + struct dialdetector *d = data; + + printf("port event: %d %d\n", d->state, event->hook.on); + + switch (d->state) { + case DIALDETECTOR_IDLE: + if (event->type == TAPI_EVENT_TYPE_HOOK && event->hook.on == false) { + d->state = DIALDETECTOR_WAIT_FOR_NUMBER; + event_register(d->timer_fd, EPOLLIN, &d->timeout_cb); + timerfd_settime(d->timer_fd, 0, &dialdetector_timeout, NULL); + } + break; + case DIALDETECTOR_WAIT_FOR_NUMBER: + case DIALDETECTOR_WAIT_FOR_NUMBER_TIMEOUT: + switch (event->type) { + case TAPI_EVENT_TYPE_HOOK: + if (event->hook.on == true) + dialdetector_reset(d); + break; + case TAPI_EVENT_TYPE_DTMF: + if (d->state == DIALDETECTOR_WAIT_FOR_NUMBER) + event_register(d->timer_fd, EPOLLIN, &d->timeout_cb); + timerfd_settime(d->timer_fd, 0, &dialdetector_timeout, NULL); + d->state = DIALDETECTOR_WAIT_FOR_NUMBER_TIMEOUT; + dialdetector_note_digit(d, event->dtmf.code); + break; + default: + break; + } + } +} + +struct dialdetector *dialdetector_alloc(struct tapi_port *port) +{ + struct dialdetector *dialdetector; + dialdetector = malloc(sizeof(*dialdetector)); + + dialdetector->timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); + dialdetector->port = port; + dialdetector->num_digits = 0; + dialdetector->state = DIALDETECTOR_IDLE; + + dialdetector->timeout_cb.callback = dialdetector_timeout_event; + dialdetector->timeout_cb.data = dialdetector; + + dialdetector->port_listener.callback = dialdetector_port_event; + dialdetector->port_listener.data = dialdetector; + + tapi_port_register_event(port, &dialdetector->port_listener); + + + return dialdetector; +} |