2 * Asterisk -- An open source telephony toolkit.
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)
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>
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.
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.
31 * \brief Asterisk channel line driver for Lantiq based TAPI boards
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>
39 * \ingroup channel_drivers
44 ASTERISK_FILE_VERSION(__FILE__
, "$Revision: xxx $")
47 #include <sys/socket.h>
49 #include <arpa/inet.h>
51 #include <sys/ioctl.h>
53 #ifdef HAVE_LINUX_COMPILER_H
54 #include <linux/compiler.h>
56 #include <linux/telephony.h>
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>
70 #include "chan_phone.h"
72 /* Lantiq TAPI includes */
73 #include <drv_tapi/drv_tapi_io.h>
74 #include <drv_vmmc/vmmc_io.h>
76 #define RTP_HEADER_LEN 12
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
86 static const char config
[] = "lantiq.conf";
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";
93 * The private structures of the Phone Jack channels are linked for selecting
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 */
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 */
119 static struct tapi_ctx
{
122 int ch_fd
[TAPI_AUDIO_PORT_NUM_MAX
];
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
);
137 static const struct ast_channel_tech tapi_tech
= {
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
154 /* Protect the interface list (of tapi_pvt's) */
155 AST_MUTEX_DEFINE_STATIC(iflock
);
158 * Protect the monitoring thread, so only one process can kill or start it, and
159 * not when it's doing something critical.
161 AST_MUTEX_DEFINE_STATIC(monlock
);
163 /* Boolean value whether the monitoring thread shall continue. */
164 static unsigned int monitor
;
166 /* The scheduling thread */
167 struct ast_sched_thread
*sched_thread
;
170 * This is the thread for the monitor which checks for input on the channels
171 * which are not currently in use.
173 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
176 #define WORDS_BIGENDIAN
177 /* struct taken from some GPLed code by Mike Borella */
178 typedef struct rtp_header
180 #if defined(WORDS_BIGENDIAN)
181 uint8_t version
:2, padding
:1, extension
:1, csrc_count
:4;
183 uint8_t csrc_count
:4, extension
:1, padding
:1, version
:2;
185 #if defined(WORDS_BIGENDIAN)
186 uint8_t marker
:1, payload_type
:7;
188 uint8_t payload_type
:7, marker
:1;
195 static int tapi_dev_open(const char *dev_path
, const int32_t ch_num
)
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);
203 static void tapi_ring(int c
, int r
)
208 status
= (uint8_t) ioctl(dev_ctx
.ch_fd
[c
], IFX_TAPI_RING_START
, 0);
210 status
= (uint8_t) ioctl(dev_ctx
.ch_fd
[c
], IFX_TAPI_RING_STOP
, 0);
214 ast_log(LOG_ERROR
, "%s ioctl failed\n",
215 (r
? "IFX_TAPI_RING_START" : "IFX_TAPI_RING_STOP"));
219 static int tapi_play_tone(int c
, int t
)
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");
229 static enum channel_state
tapi_get_hookstatus(int port
)
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");
246 tapi_dev_binary_buffer_create(const char *path
, uint8_t **ppBuf
, uint32_t *pBufSz
)
249 struct stat file_stat
;
252 fd
= fopen(path
, "rb");
254 ast_log(LOG_ERROR
, "binary file %s open failed\n", path
);
258 if (stat(path
, &file_stat
)) {
259 ast_log(LOG_ERROR
, "file %s statistics get failed\n", path
);
263 *ppBuf
= malloc(file_stat
.st_size
);
264 if (*ppBuf
== NULL
) {
265 ast_log(LOG_ERROR
, "binary file %s memory allocation failed\n", path
);
270 if (fread (*ppBuf
, sizeof(uint8_t), file_stat
.st_size
, fd
) <= 0) {
271 ast_log(LOG_ERROR
, "file %s read failed\n", path
);
276 *pBufSz
= file_stat
.st_size
;
282 if (*ppBuf
!= NULL
&& status
)
289 tapi_dev_binary_buffer_delete(uint8_t *pBuf
)
296 tapi_dev_firmware_download(int32_t fd
, const char *path
)
298 uint8_t *firmware
= NULL
;
300 VMMC_IO_INIT vmmc_io_init
;
302 if (tapi_dev_binary_buffer_create(path
, &firmware
, &size
)) {
303 ast_log(LOG_ERROR
, "binary buffer create failed!\n");
307 memset(&vmmc_io_init
, 0, sizeof(VMMC_IO_INIT
));
308 vmmc_io_init
.pPRAMfw
= firmware
;
309 vmmc_io_init
.pram_size
= size
;
311 if (ioctl(fd
, FIO_FW_DOWNLOAD
, &vmmc_io_init
)) {
312 ast_log(LOG_ERROR
, "FIO_FW_DOWNLOAD ioctl failed!\n");
316 tapi_dev_binary_buffer_delete(firmware
);
321 static const char *state_string(enum channel_state 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";
334 static const char *control_string(int 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";
363 static int ast_phone_indicate(struct ast_channel
*chan
, int condition
, const void *data
, size_t datalen
)
365 ast_verb(3, "TAPI: phone indication \"%s\".\n", control_string(condition
));
369 static int ast_phone_fixup(struct ast_channel
*old
, struct ast_channel
*new)
371 ast_debug(1, "TAPI: ast_phone_fixup()\n");
375 static int ast_digit_begin(struct ast_channel
*chan
, char digit
)
377 /* TODO: Modify this callback to let Asterisk support controlling the length of DTMF */
378 ast_debug(1, "TAPI: ast_digit_begin()\n");
382 static int ast_digit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
)
384 ast_debug(1, "TAPI: ast_digit_end()\n");
388 static int ast_phone_call(struct ast_channel
*ast
, char *dest
, int timeout
)
390 ast_debug(1, "TAPI: ast_phone_call()\n");
392 ast_mutex_lock(&iflock
);
394 struct tapi_pvt
*pvt
= ast
->tech_pvt
;
396 ast_debug(1, "TAPI: ast_phone_call() state: %s\n", state_string(pvt
->channel_state
));
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
;
403 ast_setstate(ast
, AST_STATE_RINGING
);
404 ast_queue_control(ast
, AST_CONTROL_RINGING
);
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
);
411 ast_mutex_unlock(&iflock
);
416 static int ast_phone_hangup(struct ast_channel
*ast
)
418 ast_debug(1, "TAPI: ast_phone_hangup()\n");
420 struct tapi_pvt
*pvt
= ast
->tech_pvt
;
422 /* lock to prevent simultaneous access with do_monitor thread processing */
423 ast_mutex_lock(&iflock
);
425 if (ast
->_state
== AST_STATE_RINGING
) {
426 ast_debug(1, "TAPI: ast_phone_hangup(): ast->_state == AST_STATE_RINGING\n");
429 switch (pvt
->channel_state
) {
433 tapi_ring(pvt
->port_id
, 0);
434 pvt
->channel_state
= ONHOOK
;
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
);
445 ast_setstate(ast
, AST_STATE_DOWN
);
446 ast_module_unref(ast_module_info
->self
);
447 ast
->tech_pvt
= NULL
;
450 ast_mutex_unlock(&iflock
);
455 static int ast_phone_answer(struct ast_channel
*ast
)
457 ast_debug(1, "TAPI: ast_phone_answer()\n");
461 static struct ast_frame
* ast_phone_read(struct ast_channel
*ast
)
463 ast_debug(1, "TAPI: ast_phone_read()\n");
467 static int ast_phone_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
469 ast_debug(1, "TAPI: ast_phone_write()\n");
472 struct tapi_pvt
*pvt
= ast
->tech_pvt
;
474 rtp_header_t
*rtp_header
= (rtp_header_t
*) buf
;
476 if(frame
->frametype
!= AST_FRAME_VOICE
) {
477 ast_debug(1, "TAPI: ast_phone_write(): unhandled frame type.\n");
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
;
492 pvt
->rtp_timestamp
+= 160;
494 memcpy(buf
+RTP_HEADER_LEN
, frame
->data
.ptr
, frame
->datalen
);
496 ret
= write(dev_ctx
.ch_fd
[pvt
->port_id
], buf
, frame
->datalen
+RTP_HEADER_LEN
);
498 ast_debug(1, "TAPI: ast_phone_write(): error writing.\n");
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",
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
);
520 static struct ast_frame
* ast_phone_exception(struct ast_channel
*ast
)
522 ast_debug(1, "TAPI: ast_phone_exception()\n");
526 static int tapi_standby(int c
)
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");
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");
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");
543 return tapi_play_tone(c
, TAPI_TONE_LOCALE_NONE
);
546 static int tapi_end_dialing(int c
)
548 ast_debug(1, "%s\n", __FUNCTION__
);
549 struct tapi_pvt
*pvt
= &iflist
[c
];
551 if (pvt
->dial_timer
) {
552 ast_sched_thread_del(sched_thread
, pvt
->dial_timer
);
557 ast_hangup(pvt
->owner
);
563 static int tapi_end_call(int c
)
565 ast_debug(1, "%s\n", __FUNCTION__
);
567 struct tapi_pvt
*pvt
= &iflist
[c
];
570 ast_queue_hangup(pvt
->owner
);
576 static struct ast_channel
* tapi_channel(int state
, int c
, char *ext
, char *ctx
)
578 ast_debug(1, "tapi_channel()\n");
580 struct ast_channel
*chan
= NULL
;
582 struct tapi_pvt
*pvt
= &iflist
[c
];
584 chan
= ast_channel_alloc(1, state
, NULL
, NULL
, "", ext
, ctx
, 0, c
, "TAPI/%s", "1");
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
;
597 static struct ast_channel
* ast_phone_requester(const char *type
, format_t format
, const struct ast_channel
*requestor
, void *data
, int *cause
)
601 struct ast_channel
*chan
= NULL
;
604 ast_debug(1, "Asked to create a TAPI channel with formats: %s\n", ast_getformatname_multiple(buf
, sizeof(buf
), format
));
606 if (ast_mutex_lock(&iflock
)) {
607 ast_log(LOG_WARNING
, "Unable to lock the monitor\n");
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
;
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
;
626 /* on asterisk user's side, we're using port 1-2.
627 * Here in non normal human's world, we begin
632 chan
= tapi_channel(AST_STATE_DOWN
, port_id
, NULL
, NULL
);
634 ast_mutex_unlock(&iflock
);
638 static int tapi_dev_data_handler(int c
) {
640 struct ast_frame frame
= {0};
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
);
645 rtp_header_t
*rtp
= (rtp_header_t
*) buf
;
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
;
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
);
663 ast_mutex_unlock(&iflock
);
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",
671 (int)rtp->csrc_count,
673 ast_codec2str(rtp->payload_type),
681 static int accept_call(int c
)
683 ast_debug(1, "%s: line %i\n", __FUNCTION__
, __LINE__
);
685 struct tapi_pvt
*pvt
= &iflist
[c
];
688 struct ast_channel
*chan
= pvt
->owner
;
690 switch (chan
->_state
) {
691 case AST_STATE_RINGING
:
693 ast_queue_control(pvt
->owner
, AST_CONTROL_ANSWER
);
694 pvt
->channel_state
= INCALL
;
699 ast_debug(1, "%s: line %i: unhandled state %s.\n", __FUNCTION__
, __LINE__
, ast_state2str(chan
->_state
));
707 static int tapi_dev_event_hook(int c
, int state
)
709 ast_log(LOG_ERROR
, "TAPI: channel %i %s hook.\n", c
, state
? "on" : "off");
711 if (ast_mutex_lock(&iflock
)) {
712 ast_log(LOG_WARNING
, "Unable to lock the monitor\n");
718 switch (iflist
[c
].channel_state
) {
720 ret
= tapi_standby(c
);
723 ret
= tapi_end_dialing(c
);
726 ret
= tapi_end_call(c
);
729 ret
= tapi_standby(c
); // TODO: are we sure for this ?
734 iflist
[c
].channel_state
= ONHOOK
;
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");
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");
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");
751 switch (iflist
[c
].channel_state
) {
753 ret
= accept_call(c
);
756 iflist
[c
].channel_state
= OFFHOOK
;
757 tapi_play_tone(c
, TAPI_TONE_LOCALE_DIAL_CODE
);
765 ast_mutex_unlock(&iflock
);
770 static void tapi_reset_dtmfbuf(struct tapi_pvt
*pvt
)
772 pvt
->dtmfbuf
[0] = '\0';
773 pvt
->dtmfbuf_len
= 0;
777 static void tapi_dial(struct tapi_pvt
*pvt
)
779 ast_debug(1, "TAPI: tapi_dial()\n");
781 struct ast_channel
*chan
= NULL
;
783 ast_debug(1, "TAPI: tapi_dial(): user want's to dial %s.\n", pvt
->dtmfbuf
);
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
);
788 strcpy(pvt
->ext
, pvt
->dtmfbuf
);
790 ast_verbose( VERBOSE_PREFIX_3
" extension exists, starting PBX %s\n", pvt
->ext
);
792 chan
= tapi_channel(1, AST_STATE_UP
, pvt
->ext
+1, pvt
->context
);
793 chan
->tech_pvt
= pvt
;
796 strcpy(chan
->exten
, pvt
->ext
);
797 ast_setstate(chan
, AST_STATE_RING
);
798 pvt
->channel_state
= INCALL
;
800 if (ast_pbx_start(chan
)) {
801 ast_log(LOG_WARNING
, " Unable to start PBX on %s\n", chan
->name
);
806 ast_debug(1, "TAPI: tapi_dial(): no extension found.\n");
808 tapi_play_tone(pvt
->port_id
, TAPI_TONE_LOCALE_BUSY_CODE
);
809 pvt
->channel_state
= CALL_ENDED
;
812 tapi_reset_dtmfbuf(pvt
);
815 static int tapi_event_dial_timeout(const void* data
)
817 ast_debug(1, "TAPI: tapi_event_dial_timeout()\n");
819 struct tapi_pvt
*pvt
= (struct tapi_pvt
*) data
;
822 if (! pvt
->channel_state
== ONHOOK
) {
825 ast_debug(1, "TAPI: tapi_event_dial_timeout(): dial timeout in state ONHOOK.\n");
832 static void tapi_dev_event_digit(int c
, char digit
)
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");
840 struct tapi_pvt
*pvt
= &iflist
[c
];
842 switch (pvt
->channel_state
) {
844 pvt
->channel_state
= DIALING
;
846 tapi_play_tone(c
, TAPI_TONE_LOCALE_NONE
);
851 if (pvt
->dial_timer
) {
852 ast_sched_thread_del(sched_thread
, pvt
->dial_timer
);
858 pvt
->dtmfbuf
[pvt
->dtmfbuf_len
] = digit
;
860 pvt
->dtmfbuf
[pvt
->dtmfbuf_len
] = '\0';
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
);
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
);
874 ast_debug(1, "TAPI: tapi_dev_event_digit() unhandled state.\n");
878 ast_mutex_unlock(&iflock
);
882 static void tapi_dev_event_handler(void)
884 IFX_TAPI_EVENT_t event
;
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");
893 memset (&event
, 0, sizeof(event
));
895 if (ioctl(dev_ctx
.dev_fd
, IFX_TAPI_EVENT_GET
, &event
))
897 if (event
.id
== IFX_TAPI_EVENT_NONE
)
899 ast_mutex_unlock(&iflock
);
902 case IFX_TAPI_EVENT_FXS_ONHOOK
:
903 tapi_dev_event_hook(i
, 1);
905 case IFX_TAPI_EVENT_FXS_OFFHOOK
:
906 tapi_dev_event_hook(i
, 0);
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
);
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');
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
);
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
:
926 ast_log(LOG_ERROR
, "Unable TAPI event %08X\n", event
.id
);
933 tapi_events_monitor(void *data
)
935 ast_verbose("TAPI thread started\n");
937 struct pollfd fds
[3];
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
;
947 if (ast_mutex_lock(&monlock
)) {
948 ast_log(LOG_WARNING
, "Unable to lock the monitor\n");
952 if (poll(fds
, dev_ctx
.channels
+ 1, 2000) <= 0) {
953 ast_mutex_unlock(&monlock
);
957 if (fds
[0].revents
& POLLIN
) {
958 tapi_dev_event_handler();
961 ast_mutex_unlock(&monlock
);
963 if ((fds
[1].revents
& POLLIN
) && (tapi_dev_data_handler(0))) {
964 ast_verbose("TAPI: data handler failed\n");
968 if ((fds
[2].revents
& POLLIN
) && (tapi_dev_data_handler(1))) {
969 ast_verbose("TAPI: data handler failed\n");
977 static int restart_monitor(void)
979 /* If we're supposed to be stopped -- stay stopped */
980 if (monitor_thread
== AST_PTHREADT_STOP
)
982 if (ast_mutex_lock(&monlock
)) {
983 ast_log(LOG_WARNING
, "Unable to lock monitor\n");
986 if (monitor_thread
== pthread_self()) {
987 ast_mutex_unlock(&monlock
);
988 ast_log(LOG_WARNING
, "Cannot kill myself\n");
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");
998 while (pthread_kill(monitor_thread
, SIGURG
) == 0)
1000 pthread_join(monitor_thread
, NULL
);
1001 ast_mutex_unlock(&iflock
);
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");
1010 ast_mutex_unlock(&monlock
);
1014 static int unload_module(void)
1018 ast_channel_unregister(&tapi_tech
);
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
);
1025 ast_log(LOG_WARNING
, "Unable to lock the monitor\n");
1029 if (!ast_mutex_lock(&monlock
)) {
1030 if (monitor_thread
> AST_PTHREADT_NULL
) {
1032 while (pthread_kill(monitor_thread
, SIGURG
) == 0)
1034 pthread_join(monitor_thread
, NULL
);
1036 monitor_thread
= AST_PTHREADT_STOP
;
1037 ast_mutex_unlock(&monlock
);
1039 ast_log(LOG_WARNING
, "Unable to lock the monitor\n");
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");
1048 close(dev_ctx
.dev_fd
);
1049 for (c
= 0; c
< dev_ctx
.channels
; c
++) close(dev_ctx
.ch_fd
[c
]);
1051 ast_mutex_unlock(&iflock
);
1053 ast_log(LOG_WARNING
, "Unable to lock the monitor\n");
1060 static struct tapi_pvt
*tapi_init_pvt(struct tapi_pvt
*pvt
)
1065 pvt
->channel_state
= UNKNOWN
;
1066 pvt
->context
= strdup("default");
1068 pvt
->dial_timer
= 0;
1069 pvt
->dtmfbuf
[0] = '\0';
1070 pvt
->dtmfbuf_len
= 0;
1072 ast_log(LOG_ERROR
, "%s line %i: cannot clear structure.\n", __FUNCTION__
, __LINE__
);
1078 static int tapi_create_pvts(void)
1082 iflist
= ast_calloc(1, sizeof(struct tapi_pvt
)*dev_ctx
.channels
);
1085 for (i
=0 ; i
<dev_ctx
.channels
; i
++) {
1086 tapi_init_pvt(&iflist
[i
]);
1087 iflist
[i
].port_id
= i
;
1091 ast_log(LOG_ERROR
, "%s line %i: cannot allocate memory.\n", __FUNCTION__
, __LINE__
);
1096 static int tapi_setup_rtp(int c
)
1098 /* Configure RTP payload type tables */
1099 IFX_TAPI_PKT_RTP_PT_CFG_t rtpPTConf
;
1101 memset((char*)&rtpPTConf
, '\0', sizeof(rtpPTConf
));
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;
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;
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
);
1126 static int load_module(void)
1128 struct ast_config
*cfg
;
1129 struct ast_variable
*v
;
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 };
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
;
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
;
1159 /* We *must* have a config file otherwise stop immediately */
1161 ast_log(LOG_ERROR
, "Unable to load config %s\n", config
);
1162 return AST_MODULE_LOAD_DECLINE
;
1165 if (ast_mutex_lock(&iflock
)) {
1166 ast_log(LOG_ERROR
, "Unable to lock interface list.\n");
1167 return AST_MODULE_LOAD_FAILURE
;
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
;
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
));
1187 for (v
= ast_variable_browse(cfg
, "general"); v
; v
= v
->next
) {
1188 if (!strcasecmp(v
->name
, "rxgain")) {
1189 rxgain
= atoi(v
->value
);
1192 ast_log(LOG_WARNING
, "Invalid rxgain: %s, using default.\n", v
->value
);
1194 } else if (!strcasecmp(v
->name
, "txgain")) {
1195 txgain
= atoi(v
->value
);
1198 ast_log(LOG_WARNING
, "Invalid txgain: %s, using default.\n", v
->value
);
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
);
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
);
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
;
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
;
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
;
1235 ast_log(LOG_ERROR
, "Unknown echo cancellation nlp '%s'\n", v
->value
);
1236 ast_config_destroy(cfg
);
1237 return AST_MODULE_LOAD_DECLINE
;
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
;
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
);
1261 ast_log(LOG_ERROR
, "Unknown jitter buffer type '%s'\n", v
->value
);
1262 ast_config_destroy(cfg
);
1263 return AST_MODULE_LOAD_DECLINE
;
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
;
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
;
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
;
1293 ast_log(LOG_ERROR
, "Unknown caller id type '%s'\n", v
->value
);
1294 ast_config_destroy(cfg
);
1295 return AST_MODULE_LOAD_DECLINE
;
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
;
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
;
1316 ast_mutex_unlock(&iflock
);
1318 if (ast_channel_register(&tapi_tech
)) {
1319 ast_log(LOG_ERROR
, "Unable to register channel class 'Phone'\n");
1320 ast_config_destroy(cfg
);
1322 return AST_MODULE_LOAD_FAILURE
;
1324 ast_config_destroy(cfg
);
1328 IFX_TAPI_TONE_t tone
;
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
;
1340 dev_ctx
.dev_fd
= tapi_dev_open(base_path
, 0);
1342 if (dev_ctx
.dev_fd
< 0) {
1343 ast_log(LOG_ERROR
, "tapi device open function failed\n");
1344 return AST_MODULE_LOAD_FAILURE
;
1347 for (c
= 0; c
< dev_ctx
.channels
; c
++) {
1348 dev_ctx
.ch_fd
[c
] = tapi_dev_open(base_path
, c
+ 1);
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
;
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
;
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
;
1366 memset(&dev_start
, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t
));
1367 dev_start
.nMode
= IFX_TAPI_INIT_MODE_VOICE_CODER
;
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
;
1375 for (c
= 0; c
< dev_ctx
.channels
; c
++) {
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
;
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
;
1395 IFX_char_t data
[15] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1396 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x00, 0x00, 0x00, 0x00, 0x00 };
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;
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
;
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
;
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
;
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
;
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
;
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
;
1436 memset(&line_vol
, 0, sizeof(line_vol
));
1437 line_vol
.nGainRx
= rxgain
;
1438 line_vol
.nGainTx
= txgain
;
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
;
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
;
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
;
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
;
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
;
1473 /* Configure Caller ID type */
1474 memset(&cid_cfg
, 0, sizeof(cid_cfg
));
1475 cid_cfg
.nStandard
= cid_type
;
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
;
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
;
1488 /* Setup TAPI <-> Asterisk codec type mapping */
1489 if (tapi_setup_rtp(c
)) {
1490 return AST_MODULE_LOAD_FAILURE
;
1493 /* Set initial hook status */
1494 iflist
[c
].channel_state
= tapi_get_hookstatus(c
);
1496 if (iflist
[c
].channel_state
== UNKNOWN
) {
1497 return AST_MODULE_LOAD_FAILURE
;
1502 return AST_MODULE_LOAD_SUCCESS
;
1505 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Lantiq TAPI Telephony API Support");