00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $");
00034
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include <fcntl.h>
00038 #include <math.h>
00039
00040 #include <dahdi/user.h>
00041
00042 #include "asterisk/module.h"
00043 #include "asterisk/timing.h"
00044 #include "asterisk/utils.h"
00045
00046 static void *timing_funcs_handle;
00047
00048 static int dahdi_timer_open(void);
00049 static void dahdi_timer_close(int handle);
00050 static int dahdi_timer_set_rate(int handle, unsigned int rate);
00051 static int dahdi_timer_ack(int handle, unsigned int quantity);
00052 static int dahdi_timer_enable_continuous(int handle);
00053 static int dahdi_timer_disable_continuous(int handle);
00054 static enum ast_timer_event dahdi_timer_get_event(int handle);
00055 static unsigned int dahdi_timer_get_max_rate(int handle);
00056
00057 static struct ast_timing_interface dahdi_timing = {
00058 .name = "DAHDI",
00059 .priority = 100,
00060 .timer_open = dahdi_timer_open,
00061 .timer_close = dahdi_timer_close,
00062 .timer_set_rate = dahdi_timer_set_rate,
00063 .timer_ack = dahdi_timer_ack,
00064 .timer_enable_continuous = dahdi_timer_enable_continuous,
00065 .timer_disable_continuous = dahdi_timer_disable_continuous,
00066 .timer_get_event = dahdi_timer_get_event,
00067 .timer_get_max_rate = dahdi_timer_get_max_rate,
00068 };
00069
00070 static int dahdi_timer_open(void)
00071 {
00072 return open("/dev/dahdi/timer", O_RDWR);
00073 }
00074
00075 static void dahdi_timer_close(int handle)
00076 {
00077 close(handle);
00078 }
00079
00080 static int dahdi_timer_set_rate(int handle, unsigned int rate)
00081 {
00082
00083
00084 unsigned int samples = roundf((8000.0 / ((float) rate)));
00085
00086 if (ioctl(handle, DAHDI_TIMERCONFIG, &samples)) {
00087 ast_log(LOG_ERROR, "Failed to configure DAHDI timing fd for %u sample timer ticks\n",
00088 samples);
00089 return -1;
00090 }
00091
00092 return 0;
00093 }
00094
00095 static int dahdi_timer_ack(int handle, unsigned int quantity)
00096 {
00097 return ioctl(handle, DAHDI_TIMERACK, &quantity) ? -1 : 0;
00098 }
00099
00100 static int dahdi_timer_enable_continuous(int handle)
00101 {
00102 int flags = 1;
00103
00104 return ioctl(handle, DAHDI_TIMERPING, &flags) ? -1 : 0;
00105 }
00106
00107 static int dahdi_timer_disable_continuous(int handle)
00108 {
00109 int flags = -1;
00110
00111 return ioctl(handle, DAHDI_TIMERPONG, &flags) ? -1 : 0;
00112 }
00113
00114 static enum ast_timer_event dahdi_timer_get_event(int handle)
00115 {
00116 int res;
00117 int event;
00118
00119 res = ioctl(handle, DAHDI_GETEVENT, &event);
00120
00121 if (res) {
00122 event = DAHDI_EVENT_TIMER_EXPIRED;
00123 }
00124
00125 switch (event) {
00126 case DAHDI_EVENT_TIMER_PING:
00127 return AST_TIMING_EVENT_CONTINUOUS;
00128 case DAHDI_EVENT_TIMER_EXPIRED:
00129 default:
00130 return AST_TIMING_EVENT_EXPIRED;
00131 }
00132 }
00133
00134 static unsigned int dahdi_timer_get_max_rate(int handle)
00135 {
00136 return 1000;
00137 }
00138
00139 #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"
00140
00141 static int dahdi_test_timer(void)
00142 {
00143 int fd;
00144 int x = 160;
00145
00146 fd = open("/dev/dahdi/timer", O_RDWR);
00147
00148 if (fd < 0) {
00149 return -1;
00150 }
00151
00152 if (ioctl(fd, DAHDI_TIMERCONFIG, &x)) {
00153 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);
00154 close(fd);
00155 return -1;
00156 }
00157
00158 if ((x = ast_wait_for_input(fd, 300)) < 0) {
00159 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);
00160 close(fd);
00161 return -1;
00162 }
00163
00164 if (!x) {
00165 const char dahdi_timer_error[] = {
00166 "Asterisk has detected a problem with your DAHDI configuration and will shutdown for your protection. You have options:"
00167 "\n\t1. You only have to compile DAHDI support into Asterisk if you need it. One option is to recompile without DAHDI support."
00168 "\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."
00169 "\n\t3. If you need DAHDI services, you must correctly configure DAHDI."
00170 };
00171 ast_log(LOG_ERROR, "%s\n" SEE_TIMING, dahdi_timer_error);
00172 usleep(100);
00173 close(fd);
00174 return -1;
00175 }
00176
00177 close(fd);
00178
00179 return 0;
00180 }
00181
00182 static int load_module(void)
00183 {
00184 if (dahdi_test_timer()) {
00185 return AST_MODULE_LOAD_DECLINE;
00186 }
00187
00188 return (timing_funcs_handle = ast_register_timing_interface(&dahdi_timing)) ?
00189 AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
00190 }
00191
00192 static int unload_module(void)
00193 {
00194 if (timing_funcs_handle) {
00195 return ast_unregister_timing_interface(timing_funcs_handle);
00196 }
00197
00198 return 0;
00199 }
00200
00201 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "DAHDI Timing Interface",
00202 .load = load_module,
00203 .unload = unload_module,
00204 .load_pri = AST_MODPRI_TIMING,
00205 );