123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2008, Digium, Inc.
- *
- * Russell Bryant <russell@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
- /*!
- * \file
- * \author Russell Bryant <russell@digium.com>
- *
- * \brief DAHDI timing interface
- */
- /*** MODULEINFO
- <depend>dahdi</depend>
- <support_level>core</support_level>
- ***/
- #include "asterisk.h"
- ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <math.h>
- #include <dahdi/user.h>
- #include "asterisk/module.h"
- #include "asterisk/timing.h"
- #include "asterisk/utils.h"
- static void *timing_funcs_handle;
- static void *dahdi_timer_open(void);
- static void dahdi_timer_close(void *data);
- static int dahdi_timer_set_rate(void *data, unsigned int rate);
- static int dahdi_timer_ack(void *data, unsigned int quantity);
- static int dahdi_timer_enable_continuous(void *data);
- static int dahdi_timer_disable_continuous(void *data);
- static enum ast_timer_event dahdi_timer_get_event(void *data);
- static unsigned int dahdi_timer_get_max_rate(void *data);
- static int dahdi_timer_fd(void *data);
- static struct ast_timing_interface dahdi_timing = {
- .name = "DAHDI",
- .priority = 100,
- .timer_open = dahdi_timer_open,
- .timer_close = dahdi_timer_close,
- .timer_set_rate = dahdi_timer_set_rate,
- .timer_ack = dahdi_timer_ack,
- .timer_enable_continuous = dahdi_timer_enable_continuous,
- .timer_disable_continuous = dahdi_timer_disable_continuous,
- .timer_get_event = dahdi_timer_get_event,
- .timer_get_max_rate = dahdi_timer_get_max_rate,
- .timer_fd = dahdi_timer_fd,
- };
- struct dahdi_timer {
- int fd;
- };
- static void *dahdi_timer_open(void)
- {
- struct dahdi_timer *timer;
- if (!(timer = ast_calloc(1, sizeof(*timer)))) {
- return NULL;
- }
- if ((timer->fd = open("/dev/dahdi/timer", O_RDWR)) < 0) {
- ast_log(LOG_ERROR, "Failed to create dahdi timer: %s\n", strerror(errno));
- ast_free(timer);
- return NULL;
- }
- return timer;
- }
- static void dahdi_timer_close(void *data)
- {
- struct dahdi_timer *timer = data;
- close(timer->fd);
- ast_free(timer);
- }
- static int dahdi_timer_set_rate(void *data, unsigned int rate)
- {
- struct dahdi_timer *timer = data;
- int samples;
- /* DAHDI timers are configured using a number of samples,
- * based on an 8 kHz sample rate. */
- samples = (unsigned int) roundf((8000.0 / ((float) rate)));
- if (ioctl(timer->fd, DAHDI_TIMERCONFIG, &samples)) {
- ast_log(LOG_ERROR, "Failed to configure DAHDI timing fd for %d sample timer ticks\n",
- samples);
- return -1;
- }
- return 0;
- }
- static int dahdi_timer_ack(void *data, unsigned int quantity)
- {
- struct dahdi_timer *timer = data;
- return ioctl(timer->fd, DAHDI_TIMERACK, &quantity) ? -1 : 0;
- }
- static int dahdi_timer_enable_continuous(void *data)
- {
- struct dahdi_timer *timer = data;
- int flags = 1;
- return ioctl(timer->fd, DAHDI_TIMERPING, &flags) ? -1 : 0;
- }
- static int dahdi_timer_disable_continuous(void *data)
- {
- struct dahdi_timer *timer = data;
- int flags = -1;
- return ioctl(timer->fd, DAHDI_TIMERPONG, &flags) ? -1 : 0;
- }
- static enum ast_timer_event dahdi_timer_get_event(void *data)
- {
- struct dahdi_timer *timer = data;
- int res;
- int event;
- res = ioctl(timer->fd, DAHDI_GETEVENT, &event);
- if (res) {
- event = DAHDI_EVENT_TIMER_EXPIRED;
- }
- switch (event) {
- case DAHDI_EVENT_TIMER_PING:
- return AST_TIMING_EVENT_CONTINUOUS;
- case DAHDI_EVENT_TIMER_EXPIRED:
- default:
- return AST_TIMING_EVENT_EXPIRED;
- }
- }
- static unsigned int dahdi_timer_get_max_rate(void *data)
- {
- return 1000;
- }
- static int dahdi_timer_fd(void *data)
- {
- struct dahdi_timer *timer = data;
- return timer->fd;
- }
- #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"
- static int dahdi_test_timer(void)
- {
- int fd;
- int x = 160;
-
- fd = open("/dev/dahdi/timer", O_RDWR);
- if (fd < 0) {
- return -1;
- }
- if (ioctl(fd, DAHDI_TIMERCONFIG, &x)) {
- 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);
- close(fd);
- return -1;
- }
- if ((x = ast_wait_for_input(fd, 300)) < 0) {
- 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);
- close(fd);
- return -1;
- }
- if (!x) {
- const char dahdi_timer_error[] = {
- "Asterisk has detected a problem with your DAHDI configuration and will shutdown for your protection. You have options:"
- "\n\t1. You only have to compile DAHDI support into Asterisk if you need it. One option is to recompile without DAHDI support."
- "\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."
- "\n\t3. If you need DAHDI services, you must correctly configure DAHDI."
- };
- ast_log(LOG_ERROR, "%s\n" SEE_TIMING, dahdi_timer_error);
- usleep(100);
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
- static int load_module(void)
- {
- if (dahdi_test_timer()) {
- return AST_MODULE_LOAD_DECLINE;
- }
- return (timing_funcs_handle = ast_register_timing_interface(&dahdi_timing)) ?
- AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
- }
- static int unload_module(void)
- {
- if (timing_funcs_handle) {
- return ast_unregister_timing_interface(timing_funcs_handle);
- }
- return 0;
- }
- AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "DAHDI Timing Interface",
- .support_level = AST_MODULE_SUPPORT_CORE,
- .load = load_module,
- .unload = unload_module,
- .load_pri = AST_MODPRI_TIMING,
- );
|