[ifxmips]
[openwrt.git] / package / libtapi / src / tapi-port.c
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <stdbool.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/epoll.h>
7 #include <unistd.h>
8
9 #include <linux/input.h>
10
11 #include "tapi-ioctl.h"
12 #include "tapi-device.h"
13 #include "tapi-port.h"
14
15 #include "events.h"
16 #include "list.h"
17
18 static void tapi_port_event_dispatch(struct tapi_port *port,
19         struct tapi_event *event)
20 {
21         struct tapi_port_event_listener *l;
22
23         list_for_each_entry(l, &port->event_listeners, head) {
24                 l->callback(port, event, l->data);
25         }
26 }
27
28 static bool tapi_port_input_event(int events, void *data)
29 {
30         struct tapi_port *port = data;
31         struct input_event event;
32         struct tapi_event tapi_event;
33         int ret;
34
35         ret = read(port->input_fd, &event, sizeof(event));
36         if (ret < 0) {
37                 fprintf(stderr, "Port %d failed to read from input device: %d\n",
38                         port->id, errno);
39                 return true;
40         }
41
42         if (!event.value)
43                 return true;
44
45         switch (event.code) {
46         case KEY_NUMERIC_0 ... KEY_NUMERIC_9:
47                 tapi_event.type = TAPI_EVENT_TYPE_DTMF;
48                 tapi_event.dtmf.code = event.code - KEY_NUMERIC_0;
49                 break;
50         case KEY_NUMERIC_POUND:
51                 tapi_event.type = TAPI_EVENT_TYPE_DTMF;
52                 tapi_event.dtmf.code = 10;
53                 break;
54         case KEY_NUMERIC_STAR:
55                 tapi_event.type = TAPI_EVENT_TYPE_DTMF;
56                 tapi_event.dtmf.code = 11;
57                 break;
58         case KEY_ESC:
59                 tapi_event.type = TAPI_EVENT_TYPE_HOOK;
60                 tapi_event.hook.on = true;
61                 break;
62         case KEY_ENTER:
63                 tapi_event.type = TAPI_EVENT_TYPE_HOOK;
64                 tapi_event.hook.on = false;
65                 break;
66         default:
67                 return true;
68         }
69
70         if (tapi_event.type == TAPI_EVENT_TYPE_DTMF)
71                 tapi_event.dtmf.time = event.time;
72
73         tapi_port_event_dispatch(port, &tapi_event);
74
75         return true;
76 }
77
78 int tapi_port_open(struct tapi_device *dev, unsigned int id, struct tapi_port *port)
79 {
80         int ret;
81         char path[100];
82
83         port->id = id;
84
85         snprintf(path, 100, "/dev/tapi%uP%u", dev->id, id);
86         port->fd = open(path, 0);
87         if (port->fd < 0) {
88                 printf("Failed to open %s: %d\n", path, errno);
89                 return errno;
90         }
91
92         snprintf(path, 100, "/dev/event%u", id);
93         port->input_fd = open(path, O_RDONLY);
94         if (port->input_fd < 0) {
95                 printf("Failed to open %s: %d\n", path, errno);
96                 return errno;
97         }
98
99         port->ep = ioctl(port->fd, TAPI_PORT_IOCTL_GET_ENDPOINT, 0);
100
101         INIT_LIST_HEAD(&port->event_listeners);
102
103         port->input_cb.callback = tapi_port_input_event;
104         port->input_cb.data = port;
105
106         return event_register(port->input_fd, EPOLLIN,
107                 &port->input_cb);
108 }
109
110 int tapi_port_set_ring(struct tapi_port *port, bool ring)
111 {
112         return ioctl(port->fd, TAPI_PORT_IOCTL_SET_RING, ring);
113 }
114
115 int tapi_port_register_event(struct tapi_port *port,
116         struct tapi_port_event_listener *cb)
117 {
118         list_add_tail(&cb->head, &port->event_listeners);
119         return 0;
120 }
121
122 void tapi_port_unregister_event(struct tapi_port *port,
123         struct tapi_port_event_listener *cb)
124 {
125         list_del(&cb->head);
126 }