fixes asterisk dependency
[openwrt/svn-archive/packages.git] / net / asterisk-1.8.x / src-lantiq / channels / chan_lantiq.c
1 /*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2012, Luka Perkov
5 * Copyright (C) 2012, John Crispin
6 * Copyright (C) 2012, Andrej Vlašić
7 * Copyright (C) 2012, Kaspar Schleiser for T-Labs
8 * (Deutsche Telekom Innovation Laboratories)
9 * Copyright (C) 2012, Mirko Vogt for T-Labs
10 * (Deutsche Telekom Innovation Laboratories)
11 *
12 * Luka Perkov <openwrt@lukaperkov.net>
13 * John Crispin <blogic@openwrt.org>
14 * Andrej Vlašić <andrej.vlasic0@gmail.com>
15 * Kaspar Schleiser <kaspar@schleiser.de>
16 * Mirko Vogt <mirko@openwrt.org>
17 *
18 * See http://www.asterisk.org for more information about
19 * the Asterisk project. Please do not directly contact
20 * any of the maintainers of this project for assistance;
21 * the project provides a web site, mailing lists and IRC
22 * channels for your use.
23 *
24 * This program is free software, distributed under the terms of
25 * the GNU General Public License Version 2. See the LICENSE file
26 * at the top of the source tree.
27 */
28
29 /*! \file
30 *
31 * \brief Asterisk channel line driver for Lantiq based TAPI boards
32 *
33 * \author Luka Perkov <openwrt@lukaperkov.net>
34 * \author John Crispin <blogic@openwrt.org>
35 * \author Andrej Vlašić <andrej.vlasic0@gmail.com>
36 * \author Kaspar Schleiser <kaspar@schleiser.de>
37 * \author Mirko Vogt <mirko@openwrt.org>
38 *
39 * \ingroup channel_drivers
40 */
41
42 #include "asterisk.h"
43
44 ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $")
45
46 #include <ctype.h>
47 #include <sys/socket.h>
48 #include <sys/time.h>
49 #include <arpa/inet.h>
50 #include <fcntl.h>
51 #include <sys/ioctl.h>
52 #include <signal.h>
53 #ifdef HAVE_LINUX_COMPILER_H
54 #include <linux/compiler.h>
55 #endif
56 #include <linux/telephony.h>
57
58 #include <asterisk/lock.h>
59 #include <asterisk/channel.h>
60 #include <asterisk/config.h>
61 #include <asterisk/module.h>
62 #include <asterisk/pbx.h>
63 #include <asterisk/utils.h>
64 #include <asterisk/callerid.h>
65 #include <asterisk/causes.h>
66 #include <asterisk/stringfields.h>
67 #include <asterisk/musiconhold.h>
68 #include <asterisk/sched.h>
69
70 #include "chan_phone.h"
71
72 /* Lantiq TAPI includes */
73 #include <drv_tapi/drv_tapi_io.h>
74 #include <drv_vmmc/vmmc_io.h>
75
76 #define RTP_HEADER_LEN 12
77
78 #define TAPI_AUDIO_PORT_NUM_MAX 2
79 #define TAPI_TONE_LOCALE_NONE 0 // for TAPI user defined use 32
80 #define TAPI_TONE_LOCALE_BUSY_CODE 27 // for TAPI user defined use 33
81 #define TAPI_TONE_LOCALE_CONGESTION_CODE 27 // for TAPI user defined use 34
82 #define TAPI_TONE_LOCALE_DIAL_CODE 25 // for TAPI user defined use 35
83 #define TAPI_TONE_LOCALE_RING_CODE 36
84 #define TAPI_TONE_LOCALE_WAITING_CODE 37
85
86 static const char config[] = "lantiq.conf";
87
88 static char firmware_filename[PATH_MAX] = "/lib/firmware/ifx_firmware.bin";
89 static char bbd_filename[PATH_MAX] = "/lib/firmware/ifx_bbd_fxs.bin";
90 static char base_path[PATH_MAX] = "/dev/vmmc";
91
92 /*
93 * The private structures of the Phone Jack channels are linked for selecting
94 * outgoing channels.
95 */
96 enum channel_state {
97 ONHOOK,
98 OFFHOOK,
99 DIALING,
100 INCALL,
101 CALL_ENDED,
102 RINGING,
103 UNKNOWN
104 };
105
106 static struct tapi_pvt {
107 struct ast_channel *owner; /* Channel we belong to, possibly NULL */
108 int port_id; /* Port number of this object, 0..n */
109 int channel_state;
110 char *context; /* this port's dialplan context */
111 char ext[AST_MAX_EXTENSION+1]; /* the extension this port is connecting*/
112 int dial_timer; /* timer handle for autodial timeout */
113 char dtmfbuf[AST_MAX_EXTENSION+1]; /* buffer holding dialed digits */
114 int dtmfbuf_len; /* lenght of dtmfbuf */
115 int rtp_timestamp; /* timestamp for RTP packets */
116 uint16_t rtp_seqno; /* Sequence nr for RTP packets */
117 } *iflist = NULL;
118
119 static struct tapi_ctx {
120 int dev_fd;
121 int channels;
122 int ch_fd[TAPI_AUDIO_PORT_NUM_MAX];
123 } dev_ctx;
124
125 static int ast_digit_begin(struct ast_channel *ast, char digit);
126 static int ast_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
127 static int ast_phone_call(struct ast_channel *ast, char *dest, int timeout);
128 static int ast_phone_hangup(struct ast_channel *ast);
129 static int ast_phone_answer(struct ast_channel *ast);
130 static struct ast_frame *ast_phone_read(struct ast_channel *ast);
131 static int ast_phone_write(struct ast_channel *ast, struct ast_frame *frame);
132 static struct ast_frame *ast_phone_exception(struct ast_channel *ast);
133 static int ast_phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
134 static int ast_phone_fixup(struct ast_channel *old, struct ast_channel *new);
135 static struct ast_channel *ast_phone_requester(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
136
137 static const struct ast_channel_tech tapi_tech = {
138 .type = "TAPI",
139 .description = "Lantiq TAPI Telephony API Driver",
140 .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A,
141 .send_digit_begin = ast_digit_begin,
142 .send_digit_end = ast_digit_end,
143 .call = ast_phone_call,
144 .hangup = ast_phone_hangup,
145 .answer = ast_phone_answer,
146 .read = ast_phone_read,
147 .write = ast_phone_write,
148 .exception = ast_phone_exception,
149 .indicate = ast_phone_indicate,
150 .fixup = ast_phone_fixup,
151 .requester = ast_phone_requester
152 };
153
154 /* Protect the interface list (of tapi_pvt's) */
155 AST_MUTEX_DEFINE_STATIC(iflock);
156
157 /*
158 * Protect the monitoring thread, so only one process can kill or start it, and
159 * not when it's doing something critical.
160 */
161 AST_MUTEX_DEFINE_STATIC(monlock);
162
163 /* Boolean value whether the monitoring thread shall continue. */
164 static unsigned int monitor;
165
166 /* The scheduling thread */
167 struct ast_sched_thread *sched_thread;
168
169 /*
170 * This is the thread for the monitor which checks for input on the channels
171 * which are not currently in use.
172 */
173 static pthread_t monitor_thread = AST_PTHREADT_NULL;
174
175
176 #define WORDS_BIGENDIAN
177 /* struct taken from some GPLed code by Mike Borella */
178 typedef struct rtp_header
179 {
180 #if defined(WORDS_BIGENDIAN)
181 uint8_t version:2, padding:1, extension:1, csrc_count:4;
182 #else
183 uint8_t csrc_count:4, extension:1, padding:1, version:2;
184 #endif
185 #if defined(WORDS_BIGENDIAN)
186 uint8_t marker:1, payload_type:7;
187 #else
188 uint8_t payload_type:7, marker:1;
189 #endif
190 uint16_t seqno;
191 uint32_t timestamp;
192 uint32_t ssrc;
193 } rtp_header_t;
194
195 static int tapi_dev_open(const char *dev_path, const int32_t ch_num)
196 {
197 char dev_name[FILENAME_MAX + 1];
198 memset(dev_name, 0, sizeof(dev_name));
199 snprintf(dev_name, FILENAME_MAX, "%s%u%u", dev_path, 1, ch_num);
200 return open((const char*)dev_name, O_RDWR, 0644);
201 }
202
203 static void tapi_ring(int c, int r)
204 {
205 uint8_t status;
206
207 if (r) {
208 status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_START, 0);
209 } else {
210 status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_STOP, 0);
211 }
212
213 if (status) {
214 ast_log(LOG_ERROR, "%s ioctl failed\n",
215 (r ? "IFX_TAPI_RING_START" : "IFX_TAPI_RING_STOP"));
216 }
217 }
218
219 static int tapi_play_tone(int c, int t)
220 {
221 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_LOCAL_PLAY, t)) {
222 ast_log(LOG_ERROR, "IFX_TAPI_TONE_LOCAL_PLAY ioctl failed\n");
223 return -1;
224 }
225
226 return 0;
227 }
228
229 static enum channel_state tapi_get_hookstatus(int port)
230 {
231 uint8_t status;
232
233 if (ioctl(dev_ctx.ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, &status)) {
234 ast_log(LOG_ERROR, "IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed\n");
235 return UNKNOWN;
236 }
237
238 if (status) {
239 return OFFHOOK;
240 } else {
241 return ONHOOK;
242 }
243 }
244
245 static int
246 tapi_dev_binary_buffer_create(const char *path, uint8_t **ppBuf, uint32_t *pBufSz)
247 {
248 FILE *fd;
249 struct stat file_stat;
250 int32_t status = 0;
251
252 fd = fopen(path, "rb");
253 if (fd == NULL) {
254 ast_log(LOG_ERROR, "binary file %s open failed\n", path);
255 return -1;
256 }
257
258 if (stat(path, &file_stat)) {
259 ast_log(LOG_ERROR, "file %s statistics get failed\n", path);
260 return -1;
261 }
262
263 *ppBuf = malloc(file_stat.st_size);
264 if (*ppBuf == NULL) {
265 ast_log(LOG_ERROR, "binary file %s memory allocation failed\n", path);
266 status = -1;
267 goto on_exit;
268 }
269
270 if (fread (*ppBuf, sizeof(uint8_t), file_stat.st_size, fd) <= 0) {
271 ast_log(LOG_ERROR, "file %s read failed\n", path);
272 status = -1;
273 goto on_exit;
274 }
275
276 *pBufSz = file_stat.st_size;
277
278 on_exit:
279 if (fd != NULL)
280 fclose(fd);
281
282 if (*ppBuf != NULL && status)
283 free(*ppBuf);
284
285 return status;
286 }
287
288 static void
289 tapi_dev_binary_buffer_delete(uint8_t *pBuf)
290 {
291 if (pBuf != NULL)
292 free(pBuf);
293 }
294
295 static int32_t
296 tapi_dev_firmware_download(int32_t fd, const char *path)
297 {
298 uint8_t *firmware = NULL;
299 uint32_t size = 0;
300 VMMC_IO_INIT vmmc_io_init;
301
302 if (tapi_dev_binary_buffer_create(path, &firmware, &size)) {
303 ast_log(LOG_ERROR, "binary buffer create failed!\n");
304 return -1;
305 }
306
307 memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT));
308 vmmc_io_init.pPRAMfw = firmware;
309 vmmc_io_init.pram_size = size;
310
311 if (ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init)) {
312 ast_log(LOG_ERROR, "FIO_FW_DOWNLOAD ioctl failed!\n");
313 return -1;
314 }
315
316 tapi_dev_binary_buffer_delete(firmware);
317
318 return 0;
319 }
320
321 static const char *state_string(enum channel_state s)
322 {
323 switch (s) {
324 case ONHOOK: return "ONHOOK";
325 case OFFHOOK: return "OFFHOOK";
326 case DIALING: return "DIALING";
327 case INCALL: return "INCALL";
328 case CALL_ENDED: return "CALL_ENDED";
329 case RINGING: return "RINGING";
330 default: return "UNKNOWN";
331 }
332 }
333
334 static const char *control_string(int c)
335 {
336 switch (c) {
337 case AST_CONTROL_HANGUP: return "Other end has hungup";
338 case AST_CONTROL_RING: return "Local ring";
339 case AST_CONTROL_RINGING: return "Remote end is ringing";
340 case AST_CONTROL_ANSWER: return "Remote end has answered";
341 case AST_CONTROL_BUSY: return "Remote end is busy";
342 case AST_CONTROL_TAKEOFFHOOK: return "Make it go off hook";
343 case AST_CONTROL_OFFHOOK: return "Line is off hook";
344 case AST_CONTROL_CONGESTION: return "Congestion (circuits busy)";
345 case AST_CONTROL_FLASH: return "Flash hook";
346 case AST_CONTROL_WINK: return "Wink";
347 case AST_CONTROL_OPTION: return "Set a low-level option";
348 case AST_CONTROL_RADIO_KEY: return "Key Radio";
349 case AST_CONTROL_RADIO_UNKEY: return "Un-Key Radio";
350 case AST_CONTROL_PROGRESS: return "Remote end is making Progress";
351 case AST_CONTROL_PROCEEDING: return "Remote end is proceeding";
352 case AST_CONTROL_HOLD: return "Hold";
353 case AST_CONTROL_UNHOLD: return "Unhold";
354 case AST_CONTROL_SRCUPDATE: return "Media Source Update";
355 case AST_CONTROL_CONNECTED_LINE: return "Connected Line";
356 case AST_CONTROL_REDIRECTING: return "Redirecting";
357 case AST_CONTROL_INCOMPLETE: return "Incomplete";
358 case -1: return "Stop tone";
359 default: return "Unknown";
360 }
361 }
362
363 static int ast_phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
364 {
365 ast_verb(3, "TAPI: phone indication \"%s\".\n", control_string(condition));
366 return 0;
367 }
368
369 static int ast_phone_fixup(struct ast_channel *old, struct ast_channel *new)
370 {
371 ast_debug(1, "TAPI: ast_phone_fixup()\n");
372 return 0;
373 }
374
375 static int ast_digit_begin(struct ast_channel *chan, char digit)
376 {
377 /* TODO: Modify this callback to let Asterisk support controlling the length of DTMF */
378 ast_debug(1, "TAPI: ast_digit_begin()\n");
379 return 0;
380 }
381
382 static int ast_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
383 {
384 ast_debug(1, "TAPI: ast_digit_end()\n");
385 return 0;
386 }
387
388 static int ast_phone_call(struct ast_channel *ast, char *dest, int timeout)
389 {
390 ast_debug(1, "TAPI: ast_phone_call()\n");
391
392 ast_mutex_lock(&iflock);
393
394 struct tapi_pvt *pvt = ast->tech_pvt;
395
396 ast_debug(1, "TAPI: ast_phone_call() state: %s\n", state_string(pvt->channel_state));
397
398 if (pvt->channel_state == ONHOOK) {
399 ast_debug(1, "TAPI: ast_phone_call(): port %i ringing.\n", pvt->port_id);
400 tapi_ring(pvt->port_id, 1);
401 pvt->channel_state = RINGING;
402
403 ast_setstate(ast, AST_STATE_RINGING);
404 ast_queue_control(ast, AST_CONTROL_RINGING);
405 } else {
406 ast_debug(1, "TAPI: ast_phone_call(): port %i busy.\n", pvt->port_id);
407 ast_setstate(ast, AST_STATE_BUSY);
408 ast_queue_control(ast, AST_CONTROL_BUSY);
409 }
410
411 ast_mutex_unlock(&iflock);
412
413 return 0;
414 }
415
416 static int ast_phone_hangup(struct ast_channel *ast)
417 {
418 ast_debug(1, "TAPI: ast_phone_hangup()\n");
419
420 struct tapi_pvt *pvt = ast->tech_pvt;
421
422 /* lock to prevent simultaneous access with do_monitor thread processing */
423 ast_mutex_lock(&iflock);
424
425 if (ast->_state == AST_STATE_RINGING) {
426 ast_debug(1, "TAPI: ast_phone_hangup(): ast->_state == AST_STATE_RINGING\n");
427 }
428
429 switch (pvt->channel_state) {
430 case RINGING:
431 case ONHOOK:
432 {
433 tapi_ring(pvt->port_id, 0);
434 pvt->channel_state = ONHOOK;
435 break;
436 }
437 default:
438 {
439 ast_debug(1, "TAPI: ast_phone_hangup(): we were hung up, play busy tone.\n");
440 pvt->channel_state = CALL_ENDED;
441 tapi_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
442 }
443 }
444
445 ast_setstate(ast, AST_STATE_DOWN);
446 ast_module_unref(ast_module_info->self);
447 ast->tech_pvt = NULL;
448 pvt->owner = NULL;
449
450 ast_mutex_unlock(&iflock);
451
452 return 0;
453 }
454
455 static int ast_phone_answer(struct ast_channel *ast)
456 {
457 ast_debug(1, "TAPI: ast_phone_answer()\n");
458 return 0;
459 }
460
461 static struct ast_frame * ast_phone_read(struct ast_channel *ast)
462 {
463 ast_debug(1, "TAPI: ast_phone_read()\n");
464 return NULL;
465 }
466
467 static int ast_phone_write(struct ast_channel *ast, struct ast_frame *frame)
468 {
469 ast_debug(1, "TAPI: ast_phone_write()\n");
470
471 char buf[2048];
472 struct tapi_pvt *pvt = ast->tech_pvt;
473 int ret = -1;
474 rtp_header_t *rtp_header = (rtp_header_t *) buf;
475
476 if(frame->frametype != AST_FRAME_VOICE) {
477 ast_debug(1, "TAPI: ast_phone_write(): unhandled frame type.\n");
478 return 0;
479 }
480
481 memset(buf, '\0', sizeof(rtp_header_t));
482 rtp_header->version = 2;
483 rtp_header->padding = 0;
484 rtp_header->extension = 0;
485 rtp_header->csrc_count = 0;
486 rtp_header->marker = 0;
487 rtp_header->timestamp = pvt->rtp_timestamp;
488 rtp_header->seqno = pvt->rtp_seqno++;
489 rtp_header->ssrc = 0;
490 rtp_header->payload_type = (uint8_t) frame->subclass.codec;
491
492 pvt->rtp_timestamp += 160;
493
494 memcpy(buf+RTP_HEADER_LEN, frame->data.ptr, frame->datalen);
495
496 ret = write(dev_ctx.ch_fd[pvt->port_id], buf, frame->datalen+RTP_HEADER_LEN);
497 if (ret <= 0) {
498 ast_debug(1, "TAPI: ast_phone_write(): error writing.\n");
499 return -1;
500 }
501
502 #ifdef TODO_DEVEL_INFO
503 ast_debug(1, "ast_phone_write(): size: %i version: %i padding: %i extension: %i csrc_count: %i\n"
504 "marker: %i payload_type: %s seqno: %i timestamp: %i ssrc: %i\n",
505 (int)ret,
506 (int)rtp_header->version,
507 (int)rtp_header->padding,
508 (int)rtp_header->extension,
509 (int)rtp_header->csrc_count,
510 (int)rtp_header->marker,
511 ast_codec2str(rtp_header->payload_type),
512 (int)rtp_header->seqno,
513 (int)rtp_header->timestamp,
514 (int)rtp_header->ssrc);
515 #endif
516
517 return 0;
518 }
519
520 static struct ast_frame * ast_phone_exception(struct ast_channel *ast)
521 {
522 ast_debug(1, "TAPI: ast_phone_exception()\n");
523 return NULL;
524 }
525
526 static int tapi_standby(int c)
527 {
528 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
529 ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
530 return -1;
531 }
532
533 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_STOP, 0)) {
534 ast_log(LOG_ERROR, "IFX_TAPI_ENC_STOP ioctl failed\n");
535 return -1;
536 }
537
538 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_STOP, 0)) {
539 ast_log(LOG_ERROR, "IFX_TAPI_DEC_STOP ioctl failed\n");
540 return -1;
541 }
542
543 return tapi_play_tone(c, TAPI_TONE_LOCALE_NONE);
544 }
545
546 static int tapi_end_dialing(int c)
547 {
548 ast_debug(1, "%s\n", __FUNCTION__);
549 struct tapi_pvt *pvt = &iflist[c];
550
551 if (pvt->dial_timer) {
552 ast_sched_thread_del(sched_thread, pvt->dial_timer);
553 pvt->dial_timer = 0;
554 }
555
556 if(pvt->owner) {
557 ast_hangup(pvt->owner);
558 }
559
560 return 0;
561 }
562
563 static int tapi_end_call(int c)
564 {
565 ast_debug(1, "%s\n", __FUNCTION__);
566
567 struct tapi_pvt *pvt = &iflist[c];
568
569 if(pvt->owner) {
570 ast_queue_hangup(pvt->owner);
571 }
572
573 return 0;
574 }
575
576 static struct ast_channel * tapi_channel(int state, int c, char *ext, char *ctx)
577 {
578 ast_debug(1, "tapi_channel()\n");
579
580 struct ast_channel *chan = NULL;
581
582 struct tapi_pvt *pvt = &iflist[c];
583
584 chan = ast_channel_alloc(1, state, NULL, NULL, "", ext, ctx, 0, c, "TAPI/%s", "1");
585
586 chan->tech = &tapi_tech;
587 chan->nativeformats = AST_FORMAT_ULAW;
588 chan->readformat = AST_FORMAT_ULAW;
589 chan->writeformat = AST_FORMAT_ULAW;
590 chan->tech_pvt = pvt;
591
592 pvt->owner = chan;
593
594 return chan;
595 }
596
597 static struct ast_channel * ast_phone_requester(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
598 {
599 char buf[BUFSIZ];
600
601 struct ast_channel *chan = NULL;
602 int port_id = -1;
603
604 ast_debug(1, "Asked to create a TAPI channel with formats: %s\n", ast_getformatname_multiple(buf, sizeof(buf), format));
605
606 if (ast_mutex_lock(&iflock)) {
607 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
608 return NULL;
609 }
610
611 /* check for correct data argument */
612 if (ast_strlen_zero(data)) {
613 ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
614 *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
615 return NULL;
616 }
617
618 /* get our port number */
619 port_id = atoi((char*) data);
620 if (port_id < 1 || port_id > dev_ctx.channels) {
621 ast_log(LOG_ERROR, "Unknown channel ID: \"%s\"\n", (char*) data);
622 *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
623 return NULL;
624 }
625
626 /* on asterisk user's side, we're using port 1-2.
627 * Here in non normal human's world, we begin
628 * counting at 0.
629 */
630 port_id -= 1;
631
632 chan = tapi_channel(AST_STATE_DOWN, port_id, NULL, NULL);
633
634 ast_mutex_unlock(&iflock);
635 return chan;
636 }
637
638 static int tapi_dev_data_handler(int c) {
639 char buf[BUFSIZ];
640 struct ast_frame frame = {0};
641
642 int res = read(dev_ctx.ch_fd[c], buf, sizeof(buf));
643 if (res <= 0) ast_debug(1, "%s: Read error: %i.\n", __FUNCTION__, res);
644
645 rtp_header_t *rtp = (rtp_header_t*) buf;
646
647 frame.src = "TAPI";
648 frame.frametype = AST_FRAME_VOICE;
649 frame.subclass.codec = rtp->payload_type;
650 frame.samples = res - RTP_HEADER_LEN;
651 frame.datalen = res - RTP_HEADER_LEN;
652 frame.data.ptr = buf + RTP_HEADER_LEN;
653
654 ast_mutex_lock(&iflock);
655 struct tapi_pvt *pvt = (struct tapi_pvt *) &iflist[c];
656 if (pvt->owner && (pvt->owner->_state == AST_STATE_UP)) {
657 if(!ast_channel_trylock(pvt->owner)) {
658 ast_queue_frame(pvt->owner, &frame);
659 ast_channel_unlock(pvt->owner);
660 }
661 }
662
663 ast_mutex_unlock(&iflock);
664
665 /* ast_debug(1, "tapi_dev_data_handler(): size: %i version: %i padding: %i extension: %i csrc_count: %i \n"
666 "marker: %i payload_type: %s seqno: %i timestamp: %i ssrc: %i\n",
667 (int)res,
668 (int)rtp->version,
669 (int)rtp->padding,
670 (int)rtp->extension,
671 (int)rtp->csrc_count,
672 (int)rtp->marker,
673 ast_codec2str(rtp->payload_type),
674 (int)rtp->seqno,
675 (int)rtp->timestamp,
676 (int)rtp->ssrc);
677 */
678 return 0;
679 }
680
681 static int accept_call(int c)
682 {
683 ast_debug(1, "%s: line %i\n", __FUNCTION__, __LINE__);
684
685 struct tapi_pvt *pvt = &iflist[c];
686
687 if (pvt->owner) {
688 struct ast_channel *chan = pvt->owner;
689
690 switch (chan->_state) {
691 case AST_STATE_RINGING:
692 {
693 ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
694 pvt->channel_state = INCALL;
695 break;
696 }
697 default:
698 {
699 ast_debug(1, "%s: line %i: unhandled state %s.\n", __FUNCTION__, __LINE__, ast_state2str(chan->_state));
700 }
701 }
702 }
703
704 return 0;
705 }
706
707 static int tapi_dev_event_hook(int c, int state)
708 {
709 ast_log(LOG_ERROR, "TAPI: channel %i %s hook.\n", c, state ? "on" : "off");
710
711 if (ast_mutex_lock(&iflock)) {
712 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
713 return -1;
714 }
715
716 int ret = -1;
717 if (state) {
718 switch (iflist[c].channel_state) {
719 case OFFHOOK:
720 ret = tapi_standby(c);
721 break;
722 case DIALING:
723 ret = tapi_end_dialing(c);
724 break;
725 case INCALL:
726 ret = tapi_end_call(c);
727 break;
728 case CALL_ENDED:
729 ret = tapi_standby(c); // TODO: are we sure for this ?
730 break;
731 default:
732 break;
733 }
734 iflist[c].channel_state = ONHOOK;
735 } else {
736 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE)) {
737 ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
738 goto out;
739 }
740
741 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_START, 0)) {
742 ast_log(LOG_ERROR, "IFX_TAPI_ENC_START ioctl failed\n");
743 goto out;
744 }
745
746 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_START, 0)) {
747 ast_log(LOG_ERROR, "IFX_TAPI_DEC_START ioctl failed\n");
748 goto out;
749 }
750
751 switch (iflist[c].channel_state) {
752 case RINGING:
753 ret = accept_call(c);
754 break;
755 default:
756 iflist[c].channel_state = OFFHOOK;
757 tapi_play_tone(c, TAPI_TONE_LOCALE_DIAL_CODE);
758 ret = 0;
759 break;
760 }
761
762 }
763
764 out:
765 ast_mutex_unlock(&iflock);
766
767 return ret;
768 }
769
770 static void tapi_reset_dtmfbuf(struct tapi_pvt *pvt)
771 {
772 pvt->dtmfbuf[0] = '\0';
773 pvt->dtmfbuf_len = 0;
774 pvt->ext[0] = '\0';
775 }
776
777 static void tapi_dial(struct tapi_pvt *pvt)
778 {
779 ast_debug(1, "TAPI: tapi_dial()\n");
780
781 struct ast_channel *chan = NULL;
782
783 ast_debug(1, "TAPI: tapi_dial(): user want's to dial %s.\n", pvt->dtmfbuf);
784
785 if (ast_exists_extension(NULL, pvt->context, pvt->dtmfbuf, 1, NULL)) {
786 ast_debug(1, "TAPI: tapi_dial(): Asterisk knows extension %s, dialing.\n", pvt->dtmfbuf);
787
788 strcpy(pvt->ext, pvt->dtmfbuf);
789
790 ast_verbose( VERBOSE_PREFIX_3 " extension exists, starting PBX %s\n", pvt->ext);
791
792 chan = tapi_channel(1, AST_STATE_UP, pvt->ext+1, pvt->context);
793 chan->tech_pvt = pvt;
794 pvt->owner = chan;
795
796 strcpy(chan->exten, pvt->ext);
797 ast_setstate(chan, AST_STATE_RING);
798 pvt->channel_state = INCALL;
799
800 if (ast_pbx_start(chan)) {
801 ast_log(LOG_WARNING, " Unable to start PBX on %s\n", chan->name);
802 ast_hangup(chan);
803 }
804 }
805 else {
806 ast_debug(1, "TAPI: tapi_dial(): no extension found.\n");
807
808 tapi_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
809 pvt->channel_state = CALL_ENDED;
810 }
811
812 tapi_reset_dtmfbuf(pvt);
813 }
814
815 static int tapi_event_dial_timeout(const void* data)
816 {
817 ast_debug(1, "TAPI: tapi_event_dial_timeout()\n");
818
819 struct tapi_pvt *pvt = (struct tapi_pvt *) data;
820 pvt->dial_timer = 0;
821
822 if (! pvt->channel_state == ONHOOK) {
823 tapi_dial(pvt);
824 } else {
825 ast_debug(1, "TAPI: tapi_event_dial_timeout(): dial timeout in state ONHOOK.\n");
826 }
827
828 return 0;
829 }
830
831
832 static void tapi_dev_event_digit(int c, char digit)
833 {
834 ast_debug(1, "TAPI: tapi_event_digit() port=%i digit=%c\n", port, digit);
835 if (ast_mutex_lock(&iflock)) {
836 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
837 return;
838 }
839
840 struct tapi_pvt *pvt = &iflist[c];
841
842 switch (pvt->channel_state) {
843 case OFFHOOK:
844 pvt->channel_state = DIALING;
845
846 tapi_play_tone(c, TAPI_TONE_LOCALE_NONE);
847
848 /* fall through */
849 case DIALING:
850 if (digit == '#') {
851 if (pvt->dial_timer) {
852 ast_sched_thread_del(sched_thread, pvt->dial_timer);
853 pvt->dial_timer = 0;
854 }
855
856 tapi_dial(pvt);
857 } else {
858 pvt->dtmfbuf[pvt->dtmfbuf_len] = digit;
859 pvt->dtmfbuf_len++;
860 pvt->dtmfbuf[pvt->dtmfbuf_len] = '\0';
861
862 /* setup autodial timer */
863 if (!pvt->dial_timer) {
864 ast_debug(1, "TAPI: tapi_dev_event_digit() setting new timer.\n");
865 pvt->dial_timer = ast_sched_thread_add(sched_thread, 2000, tapi_event_dial_timeout, (const void*) pvt);
866 } else {
867 ast_debug(1, "TAPI: tapi_dev_event_digit() replacing timer.\n");
868 struct sched_context *sched = ast_sched_thread_get_context(sched_thread);
869 AST_SCHED_REPLACE(pvt->dial_timer, sched, 2000, tapi_event_dial_timeout, (const void*) pvt);
870 }
871 }
872 break;
873 default:
874 ast_debug(1, "TAPI: tapi_dev_event_digit() unhandled state.\n");
875 break;
876 }
877
878 ast_mutex_unlock(&iflock);
879 return;
880 }
881
882 static void tapi_dev_event_handler(void)
883 {
884 IFX_TAPI_EVENT_t event;
885 unsigned int i;
886
887 for (i = 0; i < dev_ctx.channels ; i++) {
888 if (ast_mutex_lock(&iflock)) {
889 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
890 break;
891 }
892
893 memset (&event, 0, sizeof(event));
894 event.ch = i;
895 if (ioctl(dev_ctx.dev_fd, IFX_TAPI_EVENT_GET, &event))
896 continue;
897 if (event.id == IFX_TAPI_EVENT_NONE)
898 continue;
899 ast_mutex_unlock(&iflock);
900
901 switch(event.id) {
902 case IFX_TAPI_EVENT_FXS_ONHOOK:
903 tapi_dev_event_hook(i, 1);
904 break;
905 case IFX_TAPI_EVENT_FXS_OFFHOOK:
906 tapi_dev_event_hook(i, 0);
907 break;
908 case IFX_TAPI_EVENT_DTMF_DIGIT:
909 ast_log(LOG_ERROR, "ON CHANNEL %d DETECTED DTMF DIGIT: %c\n", i, (char)event.data.dtmf.ascii);
910 tapi_dev_event_digit(i, (char)event.data.dtmf.ascii);
911 break;
912 case IFX_TAPI_EVENT_PULSE_DIGIT:
913 if (event.data.pulse.digit == 0xB) {
914 ast_log(LOG_ERROR, "ON CHANNEL %d DETECTED PULSE DIGIT: %c\n", i, '0');
915 tapi_dev_event_digit(i, '0');
916 } else {
917 ast_log(LOG_ERROR, "ON CHANNEL %d DETECTED PULSE DIGIT: %c\n", i, '0' + (char)event.data.pulse.digit);
918 tapi_dev_event_digit(i, '0' + (char)event.data.pulse.digit);
919 }
920 break;
921 case IFX_TAPI_EVENT_COD_DEC_CHG:
922 case IFX_TAPI_EVENT_TONE_GEN_END:
923 case IFX_TAPI_EVENT_CID_TX_SEQ_END:
924 break;
925 default:
926 ast_log(LOG_ERROR, "Unable TAPI event %08X\n", event.id);
927 break;
928 }
929 }
930 }
931
932 static void *
933 tapi_events_monitor(void *data)
934 {
935 ast_verbose("TAPI thread started\n");
936
937 struct pollfd fds[3];
938
939 fds[0].fd = dev_ctx.dev_fd;
940 fds[0].events = POLLIN;
941 fds[1].fd = dev_ctx.ch_fd[0];
942 fds[1].events = POLLIN;
943 fds[2].fd = dev_ctx.ch_fd[1];
944 fds[2].events = POLLIN;
945
946 while (monitor) {
947 if (ast_mutex_lock(&monlock)) {
948 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
949 break;
950 }
951
952 if (poll(fds, dev_ctx.channels + 1, 2000) <= 0) {
953 ast_mutex_unlock(&monlock);
954 continue;
955 }
956
957 if (fds[0].revents & POLLIN) {
958 tapi_dev_event_handler();
959 }
960
961 ast_mutex_unlock(&monlock);
962
963 if ((fds[1].revents & POLLIN) && (tapi_dev_data_handler(0))) {
964 ast_verbose("TAPI: data handler failed\n");
965 break;
966 }
967
968 if ((fds[2].revents & POLLIN) && (tapi_dev_data_handler(1))) {
969 ast_verbose("TAPI: data handler failed\n");
970 break;
971 }
972 }
973
974 return NULL;
975 }
976
977 static int restart_monitor(void)
978 {
979 /* If we're supposed to be stopped -- stay stopped */
980 if (monitor_thread == AST_PTHREADT_STOP)
981 return 0;
982 if (ast_mutex_lock(&monlock)) {
983 ast_log(LOG_WARNING, "Unable to lock monitor\n");
984 return -1;
985 }
986 if (monitor_thread == pthread_self()) {
987 ast_mutex_unlock(&monlock);
988 ast_log(LOG_WARNING, "Cannot kill myself\n");
989 return -1;
990 }
991 if (monitor_thread != AST_PTHREADT_NULL) {
992 if (ast_mutex_lock(&iflock)) {
993 ast_mutex_unlock(&monlock);
994 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
995 return -1;
996 }
997 monitor = 0;
998 while (pthread_kill(monitor_thread, SIGURG) == 0)
999 sched_yield();
1000 pthread_join(monitor_thread, NULL);
1001 ast_mutex_unlock(&iflock);
1002 }
1003 monitor = 1;
1004 /* Start a new monitor */
1005 if (ast_pthread_create_background(&monitor_thread, NULL, tapi_events_monitor, NULL) < 0) {
1006 ast_mutex_unlock(&monlock);
1007 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
1008 return -1;
1009 }
1010 ast_mutex_unlock(&monlock);
1011 return 0;
1012 }
1013
1014 static int unload_module(void)
1015 {
1016 int c;
1017
1018 ast_channel_unregister(&tapi_tech);
1019
1020 if (!ast_mutex_lock(&iflock)) {
1021 // for (c = 0; c < dev_ctx.channels ; c++)
1022 // ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
1023 ast_mutex_unlock(&iflock);
1024 } else {
1025 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1026 return -1;
1027 }
1028
1029 if (!ast_mutex_lock(&monlock)) {
1030 if (monitor_thread > AST_PTHREADT_NULL) {
1031 monitor = 0;
1032 while (pthread_kill(monitor_thread, SIGURG) == 0)
1033 sched_yield();
1034 pthread_join(monitor_thread, NULL);
1035 }
1036 monitor_thread = AST_PTHREADT_STOP;
1037 ast_mutex_unlock(&monlock);
1038 } else {
1039 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1040 return -1;
1041 }
1042
1043 if (!ast_mutex_lock(&iflock)) {
1044 if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
1045 ast_log(LOG_WARNING, "IFX_TAPI_DEV_STOP ioctl failed\n");
1046 }
1047
1048 close(dev_ctx.dev_fd);
1049 for (c = 0; c < dev_ctx.channels ; c++) close(dev_ctx.ch_fd[c]);
1050
1051 ast_mutex_unlock(&iflock);
1052 } else {
1053 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1054 return -1;
1055 }
1056
1057 return 0;
1058 }
1059
1060 static struct tapi_pvt *tapi_init_pvt(struct tapi_pvt *pvt)
1061 {
1062 if (pvt) {
1063 pvt->owner = NULL;
1064 pvt->port_id = -1;
1065 pvt->channel_state = UNKNOWN;
1066 pvt->context = strdup("default");
1067 pvt->ext[0] = '\0';
1068 pvt->dial_timer = 0;
1069 pvt->dtmfbuf[0] = '\0';
1070 pvt->dtmfbuf_len = 0;
1071 } else {
1072 ast_log(LOG_ERROR, "%s line %i: cannot clear structure.\n", __FUNCTION__, __LINE__);
1073 }
1074
1075 return pvt;
1076 }
1077
1078 static int tapi_create_pvts(void)
1079 {
1080 int i;
1081
1082 iflist = ast_calloc(1, sizeof(struct tapi_pvt)*dev_ctx.channels);
1083
1084 if (iflist) {
1085 for (i=0 ; i<dev_ctx.channels ; i++) {
1086 tapi_init_pvt(&iflist[i]);
1087 iflist[i].port_id = i;
1088 }
1089 return 0;
1090 } else {
1091 ast_log(LOG_ERROR, "%s line %i: cannot allocate memory.\n", __FUNCTION__, __LINE__);
1092 return -1;
1093 }
1094 }
1095
1096 static int tapi_setup_rtp(int c)
1097 {
1098 /* Configure RTP payload type tables */
1099 IFX_TAPI_PKT_RTP_PT_CFG_t rtpPTConf;
1100
1101 memset((char*)&rtpPTConf, '\0', sizeof(rtpPTConf));
1102
1103 rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_MLAW] = AST_FORMAT_ULAW;
1104 rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_ALAW] = AST_FORMAT_ALAW;
1105 // rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_63] = AST_FORMAT_G723_1;
1106 // rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_53] = 4;
1107 // rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G729] = AST_FORMAT_G729A;
1108 // rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G722_64] = AST_FORMAT_G722;
1109
1110 rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_MLAW] = AST_FORMAT_ULAW;
1111 rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_ALAW] = AST_FORMAT_ALAW;
1112 // rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_63] = AST_FORMAT_G723_1;
1113 // rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_53] = AST_FORMAT_G723_1;
1114 // rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G729] = AST_FORMAT_G729A;
1115 // rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G722_64] = AST_FORMAT_G722;
1116
1117 int ret;
1118 if ((ret = ioctl(dev_ctx.ch_fd[c], IFX_TAPI_PKT_RTP_PT_CFG_SET, (IFX_int32_t) &rtpPTConf))) {
1119 ast_log(LOG_ERROR, "IFX_TAPI_PKT_RTP_PT_CFG_SET failed: ret=%i\n", ret);
1120 return -1;
1121 }
1122
1123 return 0;
1124 }
1125
1126 static int load_module(void)
1127 {
1128 struct ast_config *cfg;
1129 struct ast_variable *v;
1130 int txgain = 0;
1131 int rxgain = 0;
1132 int wlec_type = 0;
1133 int wlec_nlp = 0;
1134 int wlec_nbfe = 0;
1135 int wlec_nbne = 0;
1136 int wlec_wbne = 0;
1137 int jb_type = IFX_TAPI_JB_TYPE_ADAPTIVE;
1138 int jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
1139 int jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_DEFAULT;
1140 int jb_scaling = 0x10;
1141 int jb_initialsize = 0x2d0;
1142 int jb_minsize = 0x50;
1143 int jb_maxsize = 0x5a0;
1144 int cid_type = IFX_TAPI_CID_STD_TELCORDIA;
1145 int vad_type = IFX_TAPI_ENC_VAD_NOVAD;
1146 dev_ctx.channels = TAPI_AUDIO_PORT_NUM_MAX;
1147 struct ast_flags config_flags = { 0 };
1148
1149 if (!(sched_thread = ast_sched_thread_create())) {
1150 ast_log(LOG_ERROR, "Unable to create scheduler thread\n");
1151 return AST_MODULE_LOAD_FAILURE;
1152 }
1153
1154 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
1155 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
1156 return AST_MODULE_LOAD_DECLINE;
1157 }
1158
1159 /* We *must* have a config file otherwise stop immediately */
1160 if (!cfg) {
1161 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
1162 return AST_MODULE_LOAD_DECLINE;
1163 }
1164
1165 if (ast_mutex_lock(&iflock)) {
1166 ast_log(LOG_ERROR, "Unable to lock interface list.\n");
1167 return AST_MODULE_LOAD_FAILURE;
1168 }
1169
1170 for (v = ast_variable_browse(cfg, "interfaces"); v; v = v->next) {
1171 if (!strcasecmp(v->name, "channels")) {
1172 dev_ctx.channels = atoi(v->value);
1173 if (!dev_ctx.channels) {
1174 ast_log(LOG_ERROR, "Invalid value for channels in config %s\n", config);
1175 ast_config_destroy(cfg);
1176 return AST_MODULE_LOAD_DECLINE;
1177 }
1178 } else if (!strcasecmp(v->name, "firmwarefilename")) {
1179 ast_copy_string(firmware_filename, v->value, sizeof(firmware_filename));
1180 } else if (!strcasecmp(v->name, "bbdfilename")) {
1181 ast_copy_string(bbd_filename, v->value, sizeof(bbd_filename));
1182 } else if (!strcasecmp(v->name, "basepath")) {
1183 ast_copy_string(base_path, v->value, sizeof(base_path));
1184 }
1185 }
1186
1187 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
1188 if (!strcasecmp(v->name, "rxgain")) {
1189 rxgain = atoi(v->value);
1190 if (!rxgain) {
1191 rxgain = 0;
1192 ast_log(LOG_WARNING, "Invalid rxgain: %s, using default.\n", v->value);
1193 }
1194 } else if (!strcasecmp(v->name, "txgain")) {
1195 txgain = atoi(v->value);
1196 if (!txgain) {
1197 txgain = 0;
1198 ast_log(LOG_WARNING, "Invalid txgain: %s, using default.\n", v->value);
1199 }
1200 } else if (!strcasecmp(v->name, "echocancel")) {
1201 if (!strcasecmp(v->value, "off")) {
1202 wlec_type = IFX_TAPI_WLEC_TYPE_OFF;
1203 } else if (!strcasecmp(v->value, "nlec")) {
1204 wlec_type = IFX_TAPI_WLEC_TYPE_NE;
1205 if (!strcasecmp(v->name, "echocancelfixedwindowsize")) {
1206 wlec_nbne = atoi(v->value);
1207 }
1208 } else if (!strcasecmp(v->value, "wlec")) {
1209 wlec_type = IFX_TAPI_WLEC_TYPE_NFE;
1210 if (!strcasecmp(v->name, "echocancelnfemovingwindowsize")) {
1211 wlec_nbfe = atoi(v->value);
1212 } else if (!strcasecmp(v->name, "echocancelfixedwindowsize")) {
1213 wlec_nbne = atoi(v->value);
1214 } else if (!strcasecmp(v->name, "echocancelwidefixedwindowsize")) {
1215 wlec_wbne = atoi(v->value);
1216 }
1217 } else if (!strcasecmp(v->value, "nees")) {
1218 wlec_type = IFX_TAPI_WLEC_TYPE_NE_ES;
1219 } else if (!strcasecmp(v->value, "nfees")) {
1220 wlec_type = IFX_TAPI_WLEC_TYPE_NFE_ES;
1221 } else if (!strcasecmp(v->value, "es")) {
1222 wlec_type = IFX_TAPI_WLEC_TYPE_ES;
1223 } else {
1224 wlec_type = IFX_TAPI_WLEC_TYPE_OFF;
1225 ast_log(LOG_ERROR, "Unknown echo cancellation type '%s'\n", v->value);
1226 ast_config_destroy(cfg);
1227 return AST_MODULE_LOAD_DECLINE;
1228 }
1229 } else if (!strcasecmp(v->name, "echocancelnlp")) {
1230 if (!strcasecmp(v->value, "on")) {
1231 wlec_nlp = IFX_TAPI_WLEC_NLP_ON;
1232 } else if (!strcasecmp(v->value, "off")) {
1233 wlec_nlp = IFX_TAPI_WLEC_NLP_OFF;
1234 } else {
1235 ast_log(LOG_ERROR, "Unknown echo cancellation nlp '%s'\n", v->value);
1236 ast_config_destroy(cfg);
1237 return AST_MODULE_LOAD_DECLINE;
1238 }
1239 } else if (!strcasecmp(v->name, "jitterbuffertype")) {
1240 if (!strcasecmp(v->value, "fixed")) {
1241 jb_type = IFX_TAPI_JB_TYPE_FIXED;
1242 } else if (!strcasecmp(v->value, "adaptive")) {
1243 jb_type = IFX_TAPI_JB_TYPE_ADAPTIVE;
1244 jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_DEFAULT;
1245 if (!strcasecmp(v->name, "jitterbufferadaptation")) {
1246 if (!strcasecmp(v->value, "on")) {
1247 jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_ON;
1248 } else if (!strcasecmp(v->value, "off")) {
1249 jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_OFF;
1250 }
1251 } else if (!strcasecmp(v->name, "jitterbufferscalling")) {
1252 jb_scaling = atoi(v->value);
1253 } else if (!strcasecmp(v->name, "jitterbufferinitialsize")) {
1254 jb_initialsize = atoi(v->value);
1255 } else if (!strcasecmp(v->name, "jitterbufferminsize")) {
1256 jb_minsize = atoi(v->value);
1257 } else if (!strcasecmp(v->name, "jitterbuffermaxsize")) {
1258 jb_maxsize = atoi(v->value);
1259 }
1260 } else {
1261 ast_log(LOG_ERROR, "Unknown jitter buffer type '%s'\n", v->value);
1262 ast_config_destroy(cfg);
1263 return AST_MODULE_LOAD_DECLINE;
1264 }
1265 } else if (!strcasecmp(v->name, "jitterbufferpackettype")) {
1266 if (!strcasecmp(v->value, "voice")) {
1267 jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
1268 } else if (!strcasecmp(v->value, "data")) {
1269 jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_DATA;
1270 } else if (!strcasecmp(v->value, "datanorep")) {
1271 jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_DATA_NO_REP;
1272 } else {
1273 ast_log(LOG_ERROR, "Unknown jitter buffer packet adaptation type '%s'\n", v->value);
1274 ast_config_destroy(cfg);
1275 return AST_MODULE_LOAD_DECLINE;
1276 }
1277 } else if (!strcasecmp(v->name, "calleridtype")) {
1278 if (!strcasecmp(v->value, "telecordia")) {
1279 cid_type = IFX_TAPI_CID_STD_TELCORDIA;
1280 } else if (!strcasecmp(v->value, "etsifsk")) {
1281 cid_type = IFX_TAPI_CID_STD_ETSI_FSK;
1282 } else if (!strcasecmp(v->value, "etsidtmf")) {
1283 cid_type = IFX_TAPI_CID_STD_ETSI_DTMF;
1284 } else if (!strcasecmp(v->value, "sin")) {
1285 cid_type = IFX_TAPI_CID_STD_SIN;
1286 } else if (!strcasecmp(v->value, "ntt")) {
1287 cid_type = IFX_TAPI_CID_STD_NTT;
1288 } else if (!strcasecmp(v->value, "kpndtmf")) {
1289 cid_type = IFX_TAPI_CID_STD_KPN_DTMF;
1290 } else if (!strcasecmp(v->value, "kpndtmffsk")) {
1291 cid_type = IFX_TAPI_CID_STD_KPN_DTMF_FSK;
1292 } else {
1293 ast_log(LOG_ERROR, "Unknown caller id type '%s'\n", v->value);
1294 ast_config_destroy(cfg);
1295 return AST_MODULE_LOAD_DECLINE;
1296 }
1297 } else if (!strcasecmp(v->name, "voiceactivitydetection")) {
1298 if (!strcasecmp(v->value, "on")) {
1299 vad_type = IFX_TAPI_ENC_VAD_ON;
1300 } else if (!strcasecmp(v->value, "g711")) {
1301 vad_type = IFX_TAPI_ENC_VAD_G711;
1302 } else if (!strcasecmp(v->value, "cng")) {
1303 vad_type = IFX_TAPI_ENC_VAD_CNG_ONLY;
1304 } else if (!strcasecmp(v->value, "sc")) {
1305 vad_type = IFX_TAPI_ENC_VAD_SC_ONLY;
1306 } else {
1307 ast_log(LOG_ERROR, "Unknown voice activity detection value '%s'\n", v->value);
1308 ast_config_destroy(cfg);
1309 return AST_MODULE_LOAD_DECLINE;
1310 }
1311 }
1312 }
1313
1314 tapi_create_pvts();
1315
1316 ast_mutex_unlock(&iflock);
1317
1318 if (ast_channel_register(&tapi_tech)) {
1319 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
1320 ast_config_destroy(cfg);
1321 unload_module();
1322 return AST_MODULE_LOAD_FAILURE;
1323 }
1324 ast_config_destroy(cfg);
1325
1326 /* tapi */
1327 #ifdef TODO_TONES
1328 IFX_TAPI_TONE_t tone;
1329 #endif
1330 IFX_TAPI_DEV_START_CFG_t dev_start;
1331 IFX_TAPI_MAP_DATA_t map_data;
1332 IFX_TAPI_ENC_CFG_t enc_cfg;
1333 IFX_TAPI_LINE_VOLUME_t line_vol;
1334 IFX_TAPI_WLEC_CFG_t wlec_cfg;
1335 IFX_TAPI_JB_CFG_t jb_cfg;
1336 IFX_TAPI_CID_CFG_t cid_cfg;
1337 uint8_t c;
1338
1339 /* open device */
1340 dev_ctx.dev_fd = tapi_dev_open(base_path, 0);
1341
1342 if (dev_ctx.dev_fd < 0) {
1343 ast_log(LOG_ERROR, "tapi device open function failed\n");
1344 return AST_MODULE_LOAD_FAILURE;
1345 }
1346
1347 for (c = 0; c < dev_ctx.channels ; c++) {
1348 dev_ctx.ch_fd[c] = tapi_dev_open(base_path, c + 1);
1349
1350 if (dev_ctx.ch_fd[c] < 0) {
1351 ast_log(LOG_ERROR, "tapi channel %d open function failed\n", c);
1352 return AST_MODULE_LOAD_FAILURE;
1353 }
1354 }
1355
1356 if (tapi_dev_firmware_download(dev_ctx.dev_fd, firmware_filename)) {
1357 ast_log(LOG_ERROR, "voice firmware download failed\n");
1358 return AST_MODULE_LOAD_FAILURE;
1359 }
1360
1361 if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
1362 ast_log(LOG_ERROR, "IFX_TAPI_DEV_STOP ioctl failed\n");
1363 return AST_MODULE_LOAD_FAILURE;
1364 }
1365
1366 memset(&dev_start, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t));
1367 dev_start.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER;
1368
1369 /* Start TAPI */
1370 if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_START, &dev_start)) {
1371 ast_log(LOG_ERROR, "IFX_TAPI_DEV_START ioctl failed\n");
1372 return AST_MODULE_LOAD_FAILURE;
1373 }
1374
1375 for (c = 0; c < dev_ctx.channels ; c++) {
1376 /* tones */
1377 #ifdef TODO_TONES
1378 memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
1379 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
1380 ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
1381 return AST_MODULE_LOAD_FAILURE;
1382 }
1383 #endif
1384 /* ringing type */
1385 IFX_TAPI_RING_CFG_t ringingType;
1386 memset(&ringingType, 0, sizeof(IFX_TAPI_RING_CFG_t));
1387 ringingType.nMode = IFX_TAPI_RING_CFG_MODE_INTERNAL_BALANCED;
1388 ringingType.nSubmode = IFX_TAPI_RING_CFG_SUBMODE_DC_RNG_TRIP_FAST;
1389 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_CFG_SET, (IFX_int32_t) &ringingType)) {
1390 ast_log(LOG_ERROR, "IFX_TAPI_RING_CFG_SET failed\n");
1391 return AST_MODULE_LOAD_FAILURE;
1392 }
1393
1394 /* ring cadence */
1395 IFX_char_t data[15] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1396 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x00, 0x00, 0x00, 0x00, 0x00 };
1398
1399 IFX_TAPI_RING_CADENCE_t ringCadence;
1400 memset(&ringCadence, 0, sizeof(IFX_TAPI_RING_CADENCE_t));
1401 memcpy(&ringCadence.data, data, sizeof(data));
1402 ringCadence.nr = sizeof(data) * 8;
1403
1404 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_CADENCE_HR_SET, &ringCadence)) {
1405 ast_log(LOG_ERROR, "IFX_TAPI_RING_CADENCE_HR_SET failed\n");
1406 return AST_MODULE_LOAD_FAILURE;
1407 }
1408
1409 /* perform mapping */
1410 memset(&map_data, 0x0, sizeof(IFX_TAPI_MAP_DATA_t));
1411 map_data.nDstCh = c;
1412 map_data.nChType = IFX_TAPI_MAP_TYPE_PHONE;
1413
1414 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &map_data)) {
1415 ast_log(LOG_ERROR, "IFX_TAPI_MAP_DATA_ADD %d failed\n", c);
1416 return AST_MODULE_LOAD_FAILURE;
1417 }
1418
1419 /* set line feed */
1420 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
1421 ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET %d failed\n", c);
1422 return AST_MODULE_LOAD_FAILURE;
1423 }
1424
1425 /* Configure encoder */
1426 memset(&enc_cfg, 0x0, sizeof(IFX_TAPI_ENC_CFG_t));
1427 enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
1428 enc_cfg.nEncType = IFX_TAPI_COD_TYPE_MLAW;
1429
1430 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg)) {
1431 ast_log(LOG_ERROR, "IFX_TAPI_ENC_CFG_SET %d failed\n", c);
1432 return AST_MODULE_LOAD_FAILURE;
1433 }
1434
1435 /* set volume */
1436 memset(&line_vol, 0, sizeof(line_vol));
1437 line_vol.nGainRx = rxgain;
1438 line_vol.nGainTx = txgain;
1439
1440 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol)) {
1441 ast_log(LOG_ERROR, "IFX_TAPI_PHONE_VOLUME_SET %d failed\n", c);
1442 return AST_MODULE_LOAD_FAILURE;
1443 }
1444
1445 /* Configure line echo canceller */
1446 memset(&wlec_cfg, 0, sizeof(wlec_cfg));
1447 wlec_cfg.nType = wlec_type;
1448 wlec_cfg.bNlp = wlec_nlp;
1449 wlec_cfg.nNBFEwindow = wlec_nbfe;
1450 wlec_cfg.nNBNEwindow = wlec_nbne;
1451 wlec_cfg.nWBNEwindow = wlec_wbne;
1452
1453 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_WLEC_PHONE_CFG_SET, &wlec_cfg)) {
1454 ast_log(LOG_ERROR, "IFX_TAPI_WLEC_PHONE_CFG_SET %d failed\n", c);
1455 return AST_MODULE_LOAD_FAILURE;
1456 }
1457
1458 /* Configure jitter buffer */
1459 memset(&jb_cfg, 0, sizeof(jb_cfg));
1460 jb_cfg.nJbType = jb_type;
1461 jb_cfg.nPckAdpt = jb_pckadpt;
1462 jb_cfg.nLocalAdpt = jb_localadpt;
1463 jb_cfg.nScaling = jb_scaling;
1464 jb_cfg.nInitialSize = jb_initialsize;
1465 jb_cfg.nMinSize = jb_minsize;
1466 jb_cfg.nMaxSize = jb_maxsize;
1467
1468 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_JB_CFG_SET, &jb_cfg)) {
1469 ast_log(LOG_ERROR, "IFX_TAPI_JB_CFG_SET %d failed\n", c);
1470 return AST_MODULE_LOAD_FAILURE;
1471 }
1472
1473 /* Configure Caller ID type */
1474 memset(&cid_cfg, 0, sizeof(cid_cfg));
1475 cid_cfg.nStandard = cid_type;
1476
1477 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cfg)) {
1478 ast_log(LOG_ERROR, "IIFX_TAPI_CID_CFG_SET %d failed\n", c);
1479 return AST_MODULE_LOAD_FAILURE;
1480 }
1481
1482 /* Configure voice activity detection */
1483 if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_VAD_CFG_SET, vad_type)) {
1484 ast_log(LOG_ERROR, "IFX_TAPI_ENC_VAD_CFG_SET %d failed\n", c);
1485 return AST_MODULE_LOAD_FAILURE;
1486 }
1487
1488 /* Setup TAPI <-> Asterisk codec type mapping */
1489 if (tapi_setup_rtp(c)) {
1490 return AST_MODULE_LOAD_FAILURE;
1491 }
1492
1493 /* Set initial hook status */
1494 iflist[c].channel_state = tapi_get_hookstatus(c);
1495
1496 if (iflist[c].channel_state == UNKNOWN) {
1497 return AST_MODULE_LOAD_FAILURE;
1498 }
1499 }
1500
1501 restart_monitor();
1502 return AST_MODULE_LOAD_SUCCESS;
1503 }
1504
1505 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Lantiq TAPI Telephony API Support");