Asterisk - The Open Source Telephony Project  18.5.0
res_timing_dahdi.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2008, Digium, Inc.
5  *
6  * Russell Bryant <[email protected]>
7  *
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.
13  *
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.
17  */
18 
19 /*!
20  * \file
21  * \author Russell Bryant <[email protected]>
22  *
23  * \brief DAHDI timing interface
24  */
25 
26 /*** MODULEINFO
27  <depend>dahdi</depend>
28  <support_level>core</support_level>
29  ***/
30 
31 #include "asterisk.h"
32 
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <math.h>
37 
38 #include <dahdi/user.h>
39 
40 #include "asterisk/module.h"
41 #include "asterisk/timing.h"
42 #include "asterisk/utils.h"
43 
44 static void *timing_funcs_handle;
45 
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);
55 
57  .name = "DAHDI",
58  .priority = 100,
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,
68 };
69 
70 struct dahdi_timer {
71  int fd;
72 };
73 
74 static void *dahdi_timer_open(void)
75 {
76  struct dahdi_timer *timer;
77 
78  if (!(timer = ast_calloc(1, sizeof(*timer)))) {
79  return NULL;
80  }
81 
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));
84  ast_free(timer);
85  return NULL;
86  }
87 
88  return timer;
89 }
90 
91 static void dahdi_timer_close(void *data)
92 {
93  struct dahdi_timer *timer = data;
94 
95  close(timer->fd);
96  ast_free(timer);
97 }
98 
99 static int dahdi_timer_set_rate(void *data, unsigned int rate)
100 {
101  struct dahdi_timer *timer = data;
102  int samples;
103 
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)));
107 
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",
110  samples);
111  return -1;
112  }
113 
114  return 0;
115 }
116 
117 static int dahdi_timer_ack(void *data, unsigned int quantity)
118 {
119  struct dahdi_timer *timer = data;
120 
121  return ioctl(timer->fd, DAHDI_TIMERACK, &quantity) ? -1 : 0;
122 }
123 
124 static int dahdi_timer_enable_continuous(void *data)
125 {
126  struct dahdi_timer *timer = data;
127  int flags = 1;
128 
129  return ioctl(timer->fd, DAHDI_TIMERPING, &flags) ? -1 : 0;
130 }
131 
132 static int dahdi_timer_disable_continuous(void *data)
133 {
134  struct dahdi_timer *timer = data;
135  int flags = -1;
136 
137  return ioctl(timer->fd, DAHDI_TIMERPONG, &flags) ? -1 : 0;
138 }
139 
140 static enum ast_timer_event dahdi_timer_get_event(void *data)
141 {
142  struct dahdi_timer *timer = data;
143  int res;
144  int event;
145 
146  res = ioctl(timer->fd, DAHDI_GETEVENT, &event);
147 
148  if (res) {
149  event = DAHDI_EVENT_TIMER_EXPIRED;
150  }
151 
152  switch (event) {
153  case DAHDI_EVENT_TIMER_PING:
155  case DAHDI_EVENT_TIMER_EXPIRED:
156  default:
158  }
159 }
160 
161 static unsigned int dahdi_timer_get_max_rate(void *data)
162 {
163  return 1000;
164 }
165 
166 static int dahdi_timer_fd(void *data)
167 {
168  struct dahdi_timer *timer = data;
169 
170  return timer->fd;
171 }
172 
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"
174 
175 static int dahdi_test_timer(void)
176 {
177  int fd;
178  int x = 160;
179 
180  fd = open("/dev/dahdi/timer", O_RDWR);
181 
182  if (fd < 0) {
183  return -1;
184  }
185 
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);
188  close(fd);
189  return -1;
190  }
191 
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);
194  close(fd);
195  return -1;
196  }
197 
198  if (!x) {
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."
204  };
205  ast_log(LOG_ERROR, "%s\n" SEE_TIMING, dahdi_timer_error);
206  usleep(100);
207  close(fd);
208  return -1;
209  }
210 
211  close(fd);
212 
213  return 0;
214 }
215 
216 static int load_module(void)
217 {
218  if (dahdi_test_timer()) {
220  }
221 
222  return (timing_funcs_handle = ast_register_timing_interface(&dahdi_timing)) ?
224 }
225 
226 static int unload_module(void)
227 {
228  if (timing_funcs_handle) {
230  }
231 
232  return 0;
233 }
234 
235 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "DAHDI Timing Interface",
236  .support_level = AST_MODULE_SUPPORT_CORE,
237  .load = load_module,
238  .unload = unload_module,
239  .load_pri = AST_MODPRI_TIMING,
240 );
const char * name
Definition: timing.h:70
Timing module interface.
Definition: timing.h:69
static int dahdi_timer_enable_continuous(void *data)
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_timing_interface dahdi_timing
int ast_unregister_timing_interface(void *handle)
Unregister a previously registered timing interface.
Definition: timing.c:104
ast_timer_event
Definition: timing.h:57
Definition: astman.c:222
static void dahdi_timer_close(void *data)
static int dahdi_timer_set_rate(void *data, unsigned int rate)
#define NULL
Definition: resample.c:96
static int dahdi_timer_disable_continuous(void *data)
static enum ast_timer_event dahdi_timer_get_event(void *data)
Utility functions.
#define ast_log
Definition: astobj2.c:42
static void * timing_funcs_handle
#define SEE_TIMING
static int dahdi_timer_ack(void *data, unsigned int quantity)
static int dahdi_timer_fd(void *data)
#define LOG_ERROR
Definition: logger.h:285
static void * dahdi_timer_open(void)
int errno
static int dahdi_test_timer(void)
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static unsigned int dahdi_timer_get_max_rate(void *data)
float roundf(float x)
#define ast_register_timing_interface(i)
Register a set of timing functions.
Definition: timing.h:95
int ast_wait_for_input(int fd, int ms)
Definition: main/utils.c:1519
static int load_module(void)
static int unload_module(void)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static struct ast_timer * timer
Definition: chan_iax2.c:360
Asterisk module definitions.
Timing source management.