2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2008, Digium, Inc.
6 * Russell Bryant <russell@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \author Russell Bryant <russell@digium.com>
23 * \brief DAHDI timing interface
27 <depend>dahdi</depend>
28 <support_level>core</support_level>
33 #include <sys/types.h>
38 #include <dahdi/user.h>
40 #include "asterisk/module.h"
41 #include "asterisk/timing.h"
42 #include "asterisk/utils.h"
44 static void *timing_funcs_handle;
46 static void *dahdi_timer_open(void);
47 static void dahdi_timer_close(void *data);
48 static int dahdi_timer_set_rate(void *data, unsigned int rate);
49 static int dahdi_timer_ack(void *data, unsigned int quantity);
50 static int dahdi_timer_enable_continuous(void *data);
51 static int dahdi_timer_disable_continuous(void *data);
52 static enum ast_timer_event dahdi_timer_get_event(void *data);
53 static unsigned int dahdi_timer_get_max_rate(void *data);
54 static int dahdi_timer_fd(void *data);
56 static struct ast_timing_interface dahdi_timing = {
59 .timer_open = dahdi_timer_open,
60 .timer_close = dahdi_timer_close,
61 .timer_set_rate = dahdi_timer_set_rate,
62 .timer_ack = dahdi_timer_ack,
63 .timer_enable_continuous = dahdi_timer_enable_continuous,
64 .timer_disable_continuous = dahdi_timer_disable_continuous,
65 .timer_get_event = dahdi_timer_get_event,
66 .timer_get_max_rate = dahdi_timer_get_max_rate,
67 .timer_fd = dahdi_timer_fd,
74 static void *dahdi_timer_open(void)
76 struct dahdi_timer *timer;
78 if (!(timer = ast_calloc(1, sizeof(*timer)))) {
82 if ((timer->fd = open("/dev/dahdi/timer", O_RDWR)) < 0) {
83 ast_log(LOG_ERROR, "Failed to create dahdi timer: %s\n", strerror(errno));
91 static void dahdi_timer_close(void *data)
93 struct dahdi_timer *timer = data;
99 static int dahdi_timer_set_rate(void *data, unsigned int rate)
101 struct dahdi_timer *timer = data;
104 /* DAHDI timers are configured using a number of samples,
105 * based on an 8 kHz sample rate. */
106 samples = (unsigned int) roundf((8000.0 / ((float) rate)));
108 if (ioctl(timer->fd, DAHDI_TIMERCONFIG, &samples)) {
109 ast_log(LOG_ERROR, "Failed to configure DAHDI timing fd for %d sample timer ticks\n",
117 static int dahdi_timer_ack(void *data, unsigned int quantity)
119 struct dahdi_timer *timer = data;
121 return ioctl(timer->fd, DAHDI_TIMERACK, &quantity) ? -1 : 0;
124 static int dahdi_timer_enable_continuous(void *data)
126 struct dahdi_timer *timer = data;
129 return ioctl(timer->fd, DAHDI_TIMERPING, &flags) ? -1 : 0;
132 static int dahdi_timer_disable_continuous(void *data)
134 struct dahdi_timer *timer = data;
137 return ioctl(timer->fd, DAHDI_TIMERPONG, &flags) ? -1 : 0;
140 static enum ast_timer_event dahdi_timer_get_event(void *data)
142 struct dahdi_timer *timer = data;
146 res = ioctl(timer->fd, DAHDI_GETEVENT, &event);
149 event = DAHDI_EVENT_TIMER_EXPIRED;
153 case DAHDI_EVENT_TIMER_PING:
154 return AST_TIMING_EVENT_CONTINUOUS;
155 case DAHDI_EVENT_TIMER_EXPIRED:
157 return AST_TIMING_EVENT_EXPIRED;
161 static unsigned int dahdi_timer_get_max_rate(void *data)
166 static int dahdi_timer_fd(void *data)
168 struct dahdi_timer *timer = data;
173 #define SEE_TIMING "For more information on Asterisk timing modules, including ways to potentially fix this problem, please see https://wiki.asterisk.org/wiki/display/AST/Timing+Interfaces\n"
175 static int dahdi_test_timer(void)
180 fd = open("/dev/dahdi/timer", O_RDWR);
186 if (ioctl(fd, DAHDI_TIMERCONFIG, &x)) {
187 ast_log(LOG_ERROR, "You have DAHDI built and drivers loaded, but the DAHDI timer test failed to set DAHDI_TIMERCONFIG to %d.\n" SEE_TIMING, x);
192 if ((x = ast_wait_for_input(fd, 300)) < 0) {
193 ast_log(LOG_ERROR, "You have DAHDI built and drivers loaded, but the DAHDI timer could not be polled during the DAHDI timer test.\n" SEE_TIMING);
199 const char dahdi_timer_error[] = {
200 "Asterisk has detected a problem with your DAHDI configuration and will shutdown for your protection. You have options:"
201 "\n\t1. You only have to compile DAHDI support into Asterisk if you need it. One option is to recompile without DAHDI support."
202 "\n\t2. You only have to load DAHDI drivers if you want to take advantage of DAHDI services. One option is to unload DAHDI modules if you don't need them."
203 "\n\t3. If you need DAHDI services, you must correctly configure DAHDI."
205 ast_log(LOG_ERROR, "%s\n" SEE_TIMING, dahdi_timer_error);
216 static int load_module(void)
218 if (dahdi_test_timer()) {
219 return AST_MODULE_LOAD_DECLINE;
222 return (timing_funcs_handle = ast_register_timing_interface(&dahdi_timing)) ?
223 AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
226 static int unload_module(void)
228 if (timing_funcs_handle) {
229 return ast_unregister_timing_interface(timing_funcs_handle);
235 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "DAHDI Timing Interface",
236 .support_level = AST_MODULE_SUPPORT_CORE,
238 .unload = unload_module,
239 .load_pri = AST_MODPRI_TIMING,