2
0

dialdetector.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include <linux/input.h>
  2. #include <sys/epoll.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include "events.h"
  8. #include "timerfd.h"
  9. #include "tapi-port.h"
  10. #include "dialdetector.h"
  11. static const struct itimerspec dialdetector_timeout = {
  12. .it_value.tv_sec = 3,
  13. };
  14. static void dialdetector_note_digit(struct dialdetector *d, unsigned char digit)
  15. {
  16. printf("note digit: %d\n", d->num_digits);
  17. d->digits[d->num_digits] = digit;
  18. ++d->num_digits;
  19. }
  20. static void dialdetector_reset(struct dialdetector *d)
  21. {
  22. event_unregister(d->timer_fd);
  23. d->num_digits = 0;
  24. d->state = DIALDETECTOR_IDLE;
  25. }
  26. static bool dialdetector_timeout_event(int events, void *data)
  27. {
  28. char num[20];
  29. struct dialdetector *dialdetector = data;
  30. int i;
  31. for (i = 0; i < dialdetector->num_digits; ++i) {
  32. num[i] = '0' + dialdetector->digits[i];
  33. }
  34. num[i] = '\0';
  35. printf("Dialing: %s\n", num);
  36. dialdetector->dial_callback(dialdetector->port, dialdetector->num_digits,
  37. dialdetector->digits);
  38. dialdetector_reset(dialdetector);
  39. return false;
  40. }
  41. static void dialdetector_port_event(struct tapi_port *port,
  42. struct tapi_event *event, void *data)
  43. {
  44. struct dialdetector *d = data;
  45. printf("port event: %d %d\n", d->state, event->hook.on);
  46. switch (d->state) {
  47. case DIALDETECTOR_IDLE:
  48. if (event->type == TAPI_EVENT_TYPE_HOOK && event->hook.on == false) {
  49. d->state = DIALDETECTOR_WAIT_FOR_NUMBER;
  50. event_register(d->timer_fd, EPOLLIN, &d->timeout_cb);
  51. timerfd_settime(d->timer_fd, 0, &dialdetector_timeout, NULL);
  52. }
  53. break;
  54. case DIALDETECTOR_WAIT_FOR_NUMBER:
  55. case DIALDETECTOR_WAIT_FOR_NUMBER_TIMEOUT:
  56. switch (event->type) {
  57. case TAPI_EVENT_TYPE_HOOK:
  58. if (event->hook.on == true)
  59. dialdetector_reset(d);
  60. break;
  61. case TAPI_EVENT_TYPE_DTMF:
  62. if (d->state == DIALDETECTOR_WAIT_FOR_NUMBER)
  63. event_register(d->timer_fd, EPOLLIN, &d->timeout_cb);
  64. timerfd_settime(d->timer_fd, 0, &dialdetector_timeout, NULL);
  65. d->state = DIALDETECTOR_WAIT_FOR_NUMBER_TIMEOUT;
  66. dialdetector_note_digit(d, event->dtmf.code);
  67. break;
  68. default:
  69. break;
  70. }
  71. }
  72. }
  73. struct dialdetector *dialdetector_alloc(struct tapi_port *port)
  74. {
  75. struct dialdetector *dialdetector;
  76. dialdetector = malloc(sizeof(*dialdetector));
  77. dialdetector->timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
  78. dialdetector->port = port;
  79. dialdetector->num_digits = 0;
  80. dialdetector->state = DIALDETECTOR_IDLE;
  81. dialdetector->timeout_cb.callback = dialdetector_timeout_event;
  82. dialdetector->timeout_cb.data = dialdetector;
  83. dialdetector->port_listener.callback = dialdetector_port_event;
  84. dialdetector->port_listener.data = dialdetector;
  85. tapi_port_register_event(port, &dialdetector->port_listener);
  86. return dialdetector;
  87. }