[package] iwinfo: implement netlink scanning code, rework IE parsing code
[openwrt.git] / package / pjsip / patches / 0002-register-tapi.patch
1 From 455f6f2234a36aeeb97d3e05e9cbe3afad147341 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Sat, 28 Jan 2012 21:43:49 +0100
4 Subject: [PATCH 2/3] register tapi
5
6 ---
7  .../pjmedia/src/pjmedia-audiodev/audiodev.c        |    7 +
8  .../pjmedia/src/pjmedia-audiodev/tapi_dev.c        | 1300 ++++++++++++++++++++
9  2 files changed, 1307 insertions(+), 0 deletions(-)
10  create mode 100644 pjproject-1.12/pjmedia/src/pjmedia-audiodev/tapi_dev.c
11
12 diff --git a/pjmedia/src/pjmedia-audiodev/audiodev.c b/pjmedia/src/pjmedia-audiodev/audiodev.c
13 index 3b7e121..82b364c 100644
14 --- a/pjmedia/src/pjmedia-audiodev/audiodev.c
15 +++ b/pjmedia/src/pjmedia-audiodev/audiodev.c
16 @@ -98,6 +98,10 @@ pjmedia_aud_dev_factory* pjmedia_symb_mda_factory(pj_pool_factory *pf);
17  pjmedia_aud_dev_factory* pjmedia_null_audio_factory(pj_pool_factory *pf);
18  #endif
19  
20 +#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE
21 +pjmedia_aud_dev_factory* pjmedia_tapi_factory(pj_pool_factory *pf);
22 +#endif
23 +
24  #define MAX_DRIVERS    16
25  #define MAX_DEVS       64
26  
27 @@ -409,6 +413,9 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf)
28  #if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO
29      aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory;
30  #endif
31 +#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE
32 +    aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_tapi_factory;
33 +#endif
34  
35      /* Initialize each factory and build the device ID list */
36      for (i=0; i<aud_subsys.drv_cnt; ++i) {
37 diff --git a/pjmedia/src/pjmedia-audiodev/tapi_dev.c b/pjmedia/src/pjmedia-audiodev/tapi_dev.c
38 new file mode 100644
39 index 0000000..2c65a0d
40 --- /dev/null
41 +++ b/pjmedia/src/pjmedia-audiodev/tapi_dev.c
42 @@ -0,0 +1,1300 @@
43 +/******************************************************************************
44 +
45 +                               Copyright (c) 2010
46 +                            Lantiq Deutschland GmbH
47 +                     Am Campeon 3; 85579 Neubiberg, Germany
48 +
49 +  For licensing information, see the file 'LICENSE' in the root folder of
50 +  this software module.
51 +
52 +******************************************************************************/
53 +#include <pjmedia-audiodev/audiodev_imp.h>
54 +#include <pjmedia/errno.h>
55 +#include <pj/assert.h>
56 +#include <pj/pool.h>
57 +#include <pj/log.h>
58 +#include <pj/os.h>
59 +
60 +#if defined(PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE) && PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE
61 +
62 +/* Linux includes */
63 +#include <stdio.h>
64 +#include <string.h>
65 +#include <stdlib.h>
66 +#include <ctype.h>
67 +#include <sys/stat.h>
68 +#include <fcntl.h>
69 +#include <sys/types.h>
70 +#include <sys/ioctl.h>
71 +#include <sys/select.h>
72 +#include <sys/time.h>
73 +#include <unistd.h>
74 +#include <poll.h>
75 +
76 +/* TAPI includes */
77 +#include "drv_tapi_io.h"
78 +#include "vmmc_io.h"
79 +
80 +/* Maximum 2 devices */
81 +#define TAPI_AUDIO_PORT_NUM            2
82 +#define TAPI_BASE_NAME                 "TAPI"
83 +#define TAPI_LL_DEV_BASE_PATH          "/dev/vmmc"
84 +#define TAPI_LL_DEV_FIRMWARE_NAME      "/lib/firmware/danube_firmware.bin"
85 +#define TAPI_LL_BBD_NAME               "/lib/firmware/danube_bbd_fxs.bin"
86 +
87 +#define TAPI_LL_DEV_SELECT_TIMEOUT_MS          2000
88 +#define TAPI_LL_DEV_MAX_PACKET_SIZE            800
89 +#define TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE       12
90 +#define TAPI_LL_DEV_ENC_FRAME_LEN_MS           20
91 +#define TAPI_LL_DEV_ENC_SMPL_PER_SEC           8000
92 +#define TAPI_LL_DEV_ENC_BITS_PER_SMPLS         16
93 +#define TAPI_LL_DEV_ENC_SMPL_PER_FRAME         160
94 +#define TAPI_LL_DEV_ENC_BYTES_PER_FRAME                (TAPI_LL_DEV_ENC_SMPL_PER_FRAME * (TAPI_LL_DEV_ENC_BITS_PER_SMPLS / 8))
95 +
96 +#define THIS_FILE      "tapi_dev.c"
97 +
98 +/* Set to 1 to enable tracing */
99 +#if 1
100 +#      define TRACE_(expr)     PJ_LOG(1,expr)
101 +#else
102 +#      define TRACE_(expr)
103 +#endif
104 +
105 +pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM];
106 +
107 +typedef struct
108 +{
109 +       pj_int32_t dev_fd;
110 +       pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM];
111 +       pj_int8_t data2phone_map[TAPI_AUDIO_PORT_NUM];
112 +} tapi_ctx;
113 +
114 +struct tapi_aud_factory
115 +{
116 +       pjmedia_aud_dev_factory base;
117 +       pj_pool_t               *pool;
118 +       pj_pool_factory         *pf;
119 +       pj_uint32_t             dev_count;
120 +       pjmedia_aud_dev_info    *dev_info;
121 +       tapi_ctx                dev_ctx;
122 +};
123 +
124 +typedef struct tapi_aud_factory tapi_aud_factory_t;
125 +
126 +struct tapi_aud_stream
127 +{
128 +       pjmedia_aud_stream      base;
129 +       pj_pool_t               *pool;
130 +       pjmedia_aud_param       param;
131 +       pjmedia_aud_rec_cb      rec_cb;
132 +       pjmedia_aud_play_cb     play_cb;
133 +       void                    *user_data;
134 +
135 +       pj_thread_desc          thread_desc;
136 +       pj_thread_t             *thread;
137 +       tapi_ctx                *dev_ctx;
138 +       pj_uint8_t              run_flag;
139 +       pj_timestamp            timestamp;
140 +};
141 +
142 +typedef struct tapi_aud_stream tapi_aud_stream_t;
143 +
144 +/* Factory prototypes */
145 +static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
146 +static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
147 +static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f);
148 +static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,
149 +       unsigned index,
150 +       pjmedia_aud_dev_info *info);
151 +static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f,
152 +       unsigned index,
153 +       pjmedia_aud_param *param);
154 +static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f,
155 +       const pjmedia_aud_param *param,
156 +       pjmedia_aud_rec_cb rec_cb,
157 +       pjmedia_aud_play_cb play_cb,
158 +       void *user_data,
159 +       pjmedia_aud_stream **p_aud_strm);
160 +
161 +/* Stream prototypes */
162 +static pj_status_t stream_get_param(pjmedia_aud_stream *strm,
163 +       pjmedia_aud_param *param);
164 +static pj_status_t stream_get_cap(pjmedia_aud_stream *strm,
165 +       pjmedia_aud_dev_cap cap,
166 +       void *value);
167 +static pj_status_t stream_set_cap(pjmedia_aud_stream *strm,
168 +       pjmedia_aud_dev_cap cap,
169 +       const void *value);
170 +static pj_status_t stream_start(pjmedia_aud_stream *strm);
171 +static pj_status_t stream_stop(pjmedia_aud_stream *strm);
172 +static pj_status_t stream_destroy(pjmedia_aud_stream *strm);
173 +
174 +static pjmedia_aud_dev_factory_op tapi_fact_op =
175 +{
176 +       &factory_init,
177 +       &factory_destroy,
178 +       &factory_get_dev_count,
179 +       &factory_get_dev_info,
180 +       &factory_default_param,
181 +       &factory_create_stream
182 +};
183 +
184 +static pjmedia_aud_stream_op tapi_strm_op =
185 +{
186 +       &stream_get_param,
187 +       &stream_get_cap,
188 +       &stream_set_cap,
189 +       &stream_start,
190 +       &stream_stop,
191 +       &stream_destroy
192 +};
193 +
194 +/* TAPI configuration */
195 +static struct tapi_aud_stream streams[TAPI_AUDIO_PORT_NUM];
196 +
197 +void (*tapi_digit_callback)(pj_uint8_t port, pj_uint8_t digit) = NULL;
198 +void (*tapi_hook_callback)(pj_uint8_t port, pj_uint8_t event) = NULL;
199 +
200 +#define TAPI_TONE_LOCALE_NONE                  32
201 +#define TAPI_TONE_LOCALE_BUSY_CODE             33
202 +#define TAPI_TONE_LOCALE_CONGESTION_CODE       34
203 +#define TAPI_TONE_LOCALE_DIAL_CODE             35
204 +#define TAPI_TONE_LOCALE_RING_CODE             36
205 +#define TAPI_TONE_LOCALE_WAITING_CODE          37
206 +
207 +static pj_uint8_t tapi_channel_revert = 0;
208 +static pj_uint8_t tapi_cid_type = 0;
209 +static pj_uint8_t tapi_locale = 0;
210 +
211 +void tapi_revert_channels(void)
212 +{
213 +       tapi_channel_revert = 1;
214 +       PJ_LOG(3, (THIS_FILE, "using reverted configuration for TAPI channels"));
215 +}
216 +
217 +void tapi_cid_select(char *cid)
218 +{
219 +       if (!stricmp(cid, "telecordia")) {
220 +               tapi_cid_type = IFX_TAPI_CID_STD_TELCORDIA;
221 +               PJ_LOG(3, (THIS_FILE, "using TELECORDIA configuration for TAPI CID"));
222 +       } else if (!stricmp(cid, "etsi_fsk")) {
223 +               tapi_cid_type = IFX_TAPI_CID_STD_ETSI_FSK;
224 +               PJ_LOG(3, (THIS_FILE, "using ETSI FSK configuration for TAPI CID"));
225 +       } else if (!stricmp(cid, "etsi_dtmf")) {
226 +               tapi_cid_type = IFX_TAPI_CID_STD_ETSI_DTMF;
227 +               PJ_LOG(3, (THIS_FILE, "using ETSI DTMF configuration for TAPI CID"));
228 +       } else if (!stricmp(cid, "sin")) {
229 +               tapi_cid_type = IFX_TAPI_CID_STD_SIN;
230 +               PJ_LOG(3, (THIS_FILE, "using SIN CID configuration for TAPI CID"));
231 +       } else if (!stricmp(cid, "ntt")) {
232 +               tapi_cid_type = IFX_TAPI_CID_STD_NTT;
233 +               PJ_LOG(3, (THIS_FILE, "using NTT configuration for TAPI CID"));
234 +       } else if (!stricmp(cid, "kpn_dtmf")) {
235 +               tapi_cid_type = IFX_TAPI_CID_STD_KPN_DTMF;
236 +               PJ_LOG(3, (THIS_FILE, "using KPN DTMF configuration for TAPI CID"));
237 +       } else if (!stricmp(cid, "kpn_dtmf_fsk")) {
238 +               tapi_cid_type = IFX_TAPI_CID_STD_KPN_DTMF_FSK;
239 +               PJ_LOG(3, (THIS_FILE, "using KPN DTMF FSK configuration for TAPI CID"));
240 +       } 
241 +}
242 +
243 +void tapi_locale_select(char *country)
244 +{
245 +       IFX_TAPI_TONE_t tone;
246 +       pj_status_t status;
247 +       pj_uint8_t c;
248 +
249 +       tapi_locale = 1;
250 +
251 +       if (!stricmp(country, "croatia")) {
252 +               PJ_LOG(3, (THIS_FILE, "using localized tones for Croatia"));
253 +
254 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
255 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
256 +               tone.simple.index = TAPI_TONE_LOCALE_BUSY_CODE;
257 +               tone.simple.freqA = 425;
258 +               tone.simple.levelA = 0;
259 +               tone.simple.cadence[0] = 500;
260 +               tone.simple.cadence[1] = 500;
261 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
262 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
263 +               tone.simple.loop = 0;
264 +               tone.simple.pause = 0;
265 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
266 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
267 +                       if (status != PJ_SUCCESS)
268 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
269 +               }
270 +
271 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
272 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
273 +               tone.simple.index = TAPI_TONE_LOCALE_CONGESTION_CODE;
274 +               tone.simple.freqA = 425;
275 +               tone.simple.levelA = 0;
276 +               tone.simple.cadence[0] = 250;
277 +               tone.simple.cadence[1] = 250;
278 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
279 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
280 +               tone.simple.loop = 0;
281 +               tone.simple.pause = 0;
282 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
283 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
284 +                       if (status != PJ_SUCCESS)
285 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
286 +               }
287 +
288 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
289 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
290 +               tone.simple.index = TAPI_TONE_LOCALE_DIAL_CODE;
291 +               tone.simple.freqA = 425;
292 +               tone.simple.levelA = 0;
293 +               tone.simple.cadence[0] = 200;
294 +               tone.simple.cadence[1] = 300;
295 +               tone.simple.cadence[2] = 700;
296 +               tone.simple.cadence[3] = 800;
297 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
298 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
299 +               tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQA;
300 +               tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE;
301 +               tone.simple.loop = 0;
302 +               tone.simple.pause = 0;
303 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
304 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
305 +                       if (status != PJ_SUCCESS)
306 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
307 +               }
308 +
309 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
310 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
311 +               tone.simple.index = TAPI_TONE_LOCALE_RING_CODE;
312 +               tone.simple.freqA = 425;
313 +               tone.simple.levelA = 0;
314 +               tone.simple.cadence[0] = 1000;
315 +               tone.simple.cadence[1] = 4000;
316 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
317 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
318 +               tone.simple.loop = 0;
319 +               tone.simple.pause = 0;
320 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
321 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
322 +                       if (status != PJ_SUCCESS)
323 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
324 +               }
325 +
326 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
327 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
328 +               tone.simple.index = TAPI_TONE_LOCALE_WAITING_CODE;
329 +               tone.simple.freqA = 425;
330 +               tone.simple.levelA = 0;
331 +               tone.simple.cadence[0] = 300;
332 +               tone.simple.cadence[1] = 8000;
333 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
334 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
335 +               tone.simple.loop = 0;
336 +               tone.simple.pause = 0;
337 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
338 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
339 +                       if (status != PJ_SUCCESS)
340 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
341 +               }
342 +       } else if (!stricmp(country, "germany")) {
343 +               PJ_LOG(3, (THIS_FILE, "using localized tones for Germany"));
344 +
345 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
346 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
347 +               tone.simple.index = TAPI_TONE_LOCALE_BUSY_CODE;
348 +               tone.simple.freqA = 425;
349 +               tone.simple.levelA = 0;
350 +               tone.simple.cadence[0] = 480;
351 +               tone.simple.cadence[1] = 480;
352 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
353 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
354 +               tone.simple.loop = 0;
355 +               tone.simple.pause = 0;
356 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
357 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
358 +                       if (status != PJ_SUCCESS)
359 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
360 +               }
361 +
362 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
363 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
364 +               tone.simple.index = TAPI_TONE_LOCALE_CONGESTION_CODE;
365 +               tone.simple.freqA = 425;
366 +               tone.simple.levelA = 0;
367 +               tone.simple.cadence[0] = 240;
368 +               tone.simple.cadence[1] = 240;
369 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
370 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
371 +               tone.simple.loop = 0;
372 +               tone.simple.pause = 0;
373 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
374 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
375 +                       if (status != PJ_SUCCESS)
376 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
377 +               }
378 +
379 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
380 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
381 +               tone.simple.index = TAPI_TONE_LOCALE_DIAL_CODE;
382 +               tone.simple.freqA = 425;
383 +               tone.simple.levelA = 0;
384 +               tone.simple.cadence[0] = 1000;
385 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
386 +               tone.simple.loop = 0;
387 +               tone.simple.pause = 0;
388 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
389 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
390 +                       if (status != PJ_SUCCESS)
391 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
392 +               }
393 +
394 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
395 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
396 +               tone.simple.index = TAPI_TONE_LOCALE_RING_CODE;
397 +               tone.simple.freqA = 425;
398 +               tone.simple.levelA = 0;
399 +               tone.simple.cadence[0] = 1000;
400 +               tone.simple.cadence[1] = 4000;
401 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
402 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
403 +               tone.simple.loop = 0;
404 +               tone.simple.pause = 0;
405 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
406 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
407 +                       if (status != PJ_SUCCESS)
408 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
409 +               }
410 +
411 +               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
412 +               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
413 +               tone.simple.index = TAPI_TONE_LOCALE_WAITING_CODE;
414 +               tone.simple.freqA = 425;
415 +               tone.simple.levelA = 0;
416 +               tone.simple.cadence[0] = 200;
417 +               tone.simple.cadence[1] = 200;
418 +               tone.simple.cadence[2] = 200;
419 +               tone.simple.cadence[3] = 5000;
420 +               tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
421 +               tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
422 +               tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQA;
423 +               tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE;
424 +               tone.simple.loop = 0;
425 +               tone.simple.pause = 0;
426 +               for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
427 +                       status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
428 +                       if (status != PJ_SUCCESS)
429 +                               TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
430 +               }
431 +       }
432 +}
433 +
434 +static pj_int32_t
435 +tapi_dev_open(char* dev_path, const pj_int32_t ch_num)
436 +{
437 +       char devname[128] = { 0 };
438 +       pj_ansi_sprintf(devname,"%s%u%u", dev_path, 1, ch_num);
439 +       return open((const char*)devname, O_RDWR, 0644);
440 +}
441 +
442 +static pj_status_t
443 +tapi_dev_binary_buffer_create(const char *pPath, pj_uint8_t **ppBuf, pj_uint32_t *pBufSz)
444 +{
445 +       pj_status_t status = PJ_SUCCESS;
446 +       FILE *fd;
447 +       struct stat file_stat;
448 +
449 +       fd = fopen(pPath, "rb");
450 +       if (fd == NULL) {
451 +               TRACE_((THIS_FILE, "ERROR - binary file %s open failed!\n", pPath));
452 +               return PJ_EUNKNOWN;
453 +       }
454 +
455 +       if (stat(pPath, &file_stat) != 0) {
456 +               TRACE_((THIS_FILE, "ERROR - file %s statistics get failed!\n", pPath));
457 +               return PJ_EUNKNOWN;
458 +       }
459 +
460 +       *ppBuf = malloc(file_stat.st_size);
461 +       if (*ppBuf == NULL) {
462 +               TRACE_((THIS_FILE, "ERROR - binary file %s memory allocation failed!\n", pPath));
463 +               status = PJ_EUNKNOWN;
464 +               goto on_exit;
465 +       }
466 +
467 +       if (fread (*ppBuf, sizeof(pj_uint8_t), file_stat.st_size, fd) <= 0) {
468 +               TRACE_((THIS_FILE, "ERROR - file %s read failed!\n", pPath));
469 +               status = PJ_EUNKNOWN;
470 +               goto on_exit;
471 +       }
472 +
473 +       *pBufSz = file_stat.st_size;
474 +
475 +on_exit:
476 +       if (fd != NULL)
477 +               fclose(fd);
478 +
479 +       if (*ppBuf != NULL && status != PJ_SUCCESS)
480 +               free(*ppBuf);
481 +
482 +       return status;
483 +}
484 +
485 +static void
486 +tapi_dev_binary_buffer_delete(pj_uint8_t *pBuf)
487 +{
488 +       if (pBuf != NULL)
489 +               free(pBuf);
490 +}
491 +
492 +static pj_status_t
493 +tapi_dev_firmware_download(pj_int32_t fd, const char *pPath)
494 +{
495 +       pj_status_t status = PJ_SUCCESS;
496 +       pj_uint8_t *pFirmware = NULL;
497 +       pj_uint32_t binSz = 0;
498 +       VMMC_IO_INIT vmmc_io_init;
499 +
500 +       status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz);
501 +       if (status != PJ_SUCCESS) {
502 +               TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n"));
503 +               return PJ_EUNKNOWN;
504 +       }
505 +
506 +       memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT));
507 +       vmmc_io_init.pPRAMfw = pFirmware;
508 +       vmmc_io_init.pram_size = binSz;
509 +
510 +       status = ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init);
511 +       if (status != PJ_SUCCESS)
512 +               TRACE_((THIS_FILE, "ERROR - FIO_FW_DOWNLOAD ioctl failed!"));
513 +
514 +       tapi_dev_binary_buffer_delete(pFirmware);
515 +
516 +       return status;
517 +}
518 +
519 +/* NOT USED */
520 +#if 0
521 +static int
522 +tapi_dev_bbd_download(int fd, const char *pPath)
523 +{
524 +       int status = PJ_SUCCESS;
525 +       unsigned char *pFirmware = NULL;
526 +       unsigned int binSz = 0;
527 +       VMMC_DWLD_t bbd_data;
528 +
529 +
530 +       /* Create binary buffer */
531 +       status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz);
532 +       if (status != PJ_SUCCESS) {
533 +               TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n"));
534 +               return status;
535 +       }
536 +
537 +       /* Download Voice Firmware */
538 +       memset(&bbd_data, 0, sizeof(VMMC_DWLD_t));
539 +       bbd_data.buf = pFirmware;
540 +       bbd_data.size = binSz;
541 +
542 +       status = ioctl(fd, FIO_BBD_DOWNLOAD, &bbd_data);
543 +       if (status != PJ_SUCCESS) {
544 +               TRACE_((THIS_FILE, "ERROR - FIO_BBD_DOWNLOAD failed!\n"));
545 +       }
546 +
547 +       /* Delete binary buffer */
548 +       tapi_dev_binary_buffer_delete(pFirmware);
549 +
550 +       return status;
551 +}
552 +#endif
553 +
554 +static pj_status_t tapi_dev_start(tapi_aud_factory_t *f)
555 +{
556 +       pj_uint8_t c, hook_status;
557 +       IFX_TAPI_TONE_t tone;
558 +       IFX_TAPI_DEV_START_CFG_t tapistart;
559 +       IFX_TAPI_MAP_DATA_t datamap;
560 +       IFX_TAPI_ENC_CFG_t enc_cfg;
561 +       IFX_TAPI_LINE_VOLUME_t line_vol;
562 +       IFX_TAPI_WLEC_CFG_t lec_cfg;
563 +       IFX_TAPI_JB_CFG_t jb_cfg;
564 +       IFX_TAPI_CID_CFG_t cid_cfg;
565 +       pj_status_t status;
566 +
567 +       /* Open device */
568 +       f->dev_ctx.dev_fd = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, 0);
569 +
570 +       if (f->dev_ctx.dev_fd < 0) {
571 +               TRACE_((THIS_FILE, "ERROR - TAPI device open failed!"));
572 +               return PJ_EUNKNOWN;
573 +       }
574 +
575 +       for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
576 +               if (tapi_channel_revert)
577 +                       ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, c + 1);
578 +               else
579 +                       ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, TAPI_AUDIO_PORT_NUM - c);
580 +
581 +               if (f->dev_ctx.dev_fd < 0) {
582 +                       TRACE_((THIS_FILE, "ERROR - TAPI channel%d open failed!", c));
583 +                       return PJ_EUNKNOWN;
584 +               }
585 +               if (tapi_channel_revert)
586 +                       f->dev_ctx.data2phone_map[c] = c & 0x1 ? 1 : 0;
587 +               else
588 +                       f->dev_ctx.data2phone_map[c] = c & 0x1 ? 0 : 1;
589 +       }
590 +
591 +       status = tapi_dev_firmware_download(f->dev_ctx.dev_fd, TAPI_LL_DEV_FIRMWARE_NAME);
592 +       if (status != PJ_SUCCESS) {
593 +               TRACE_((THIS_FILE, "ERROR - Voice Firmware Download failed!"));
594 +               return PJ_EUNKNOWN;
595 +       }
596 +
597 +       /* Download coefficients */
598 +       /*
599 +       status = tapi_dev_bbd_download(f->dev_ctx.dev_fd, TAPI_LL_BBD_NAME);
600 +       if (status != PJ_SUCCESS) {
601 +               TRACE_((THIS_FILE, "ERROR - Voice Coefficients Download failed!"));
602 +               return PJ_EUNKNOWN;
603 +       }
604 +       */
605 +
606 +       memset(&tapistart, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t));
607 +       tapistart.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER;
608 +
609 +       /* Start TAPI */
610 +       status = ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_START, &tapistart);
611 +       if (status != PJ_SUCCESS) {
612 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_START ioctl failed"));
613 +               return PJ_EUNKNOWN;
614 +       }
615 +
616 +
617 +       /* OpenWrt default tone */
618 +       memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
619 +       tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
620 +       tone.simple.index = TAPI_TONE_LOCALE_NONE;
621 +       tone.simple.freqA = 400;
622 +       tone.simple.levelA = 0;
623 +       tone.simple.freqB = 450;
624 +       tone.simple.levelB = 0;
625 +       tone.simple.freqC = 550;
626 +       tone.simple.levelC = 0;
627 +       tone.simple.freqD = 600;
628 +       tone.simple.levelD = 0;
629 +       tone.simple.cadence[0] = 100;
630 +       tone.simple.cadence[1] = 150;
631 +       tone.simple.cadence[2] = 100;
632 +       tone.simple.cadence[3] = 150;
633 +       tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA | IFX_TAPI_TONE_FREQB;
634 +       tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
635 +       tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQC | IFX_TAPI_TONE_FREQD;
636 +       tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE;
637 +       tone.simple.loop = 0;
638 +       tone.simple.pause = 0;
639 +       for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
640 +               /* OpenWrt default tone */
641 +               status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
642 +               if (status != PJ_SUCCESS)
643 +                       TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
644 +
645 +               /* Perform mapping */
646 +               memset(&datamap, 0x0, sizeof(IFX_TAPI_MAP_DATA_t));
647 +               datamap.nDstCh = f->dev_ctx.data2phone_map[c];
648 +               datamap.nChType = IFX_TAPI_MAP_TYPE_PHONE;
649 +
650 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &datamap);
651 +               if (status != PJ_SUCCESS) {
652 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_MAP_DATA_ADD ioctl failed"));
653 +                       return PJ_EUNKNOWN;
654 +               }
655 +
656 +               /* Set Line feed */
657 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY);
658 +               if (status != PJ_SUCCESS) {
659 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed"));
660 +                       return PJ_EUNKNOWN;
661 +               }
662 +
663 +               /* Configure encoder for linear stream */
664 +               memset(&enc_cfg, 0x0, sizeof(IFX_TAPI_ENC_CFG_t));
665 +               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
666 +               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_LIN16_8;
667 +
668 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg);
669 +               if (status != PJ_SUCCESS) {
670 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_CFG_SET ioctl failed"));
671 +                       return PJ_EUNKNOWN;
672 +               }
673 +
674 +               /* Suppress TAPI volume, otherwise PJSIP starts autogeneration */
675 +               memset(&line_vol, 0, sizeof(line_vol));
676 +               line_vol.nGainRx = -8;
677 +               line_vol.nGainTx = -8;
678 +
679 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol);
680 +               if (status != PJ_SUCCESS) {
681 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_PHONE_VOLUME_SET ioctl failed"));
682 +                       return PJ_EUNKNOWN;
683 +               }
684 +
685 +               /* Configure line echo canceller */
686 +               memset(&lec_cfg, 0, sizeof(lec_cfg));
687 +               lec_cfg.nType = IFX_TAPI_WLEC_TYPE_NFE;
688 +               lec_cfg.bNlp = IFX_TAPI_LEC_NLP_OFF;
689 +
690 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_WLEC_PHONE_CFG_SET, &lec_cfg);
691 +               if (status != PJ_SUCCESS) {
692 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_WLEC_PHONE_CFG_SET ioctl failed"));
693 +                       return PJ_EUNKNOWN;
694 +               }
695 +
696 +               /* Configure jitter buffer */
697 +               memset(&jb_cfg, 0, sizeof(jb_cfg));
698 +               jb_cfg.nJbType = IFX_TAPI_JB_TYPE_ADAPTIVE;
699 +               jb_cfg.nPckAdpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
700 +               jb_cfg.nLocalAdpt = IFX_TAPI_JB_LOCAL_ADAPT_ON;
701 +               jb_cfg.nScaling = 0x10;
702 +               jb_cfg.nInitialSize = 0x2d0;
703 +               jb_cfg.nMinSize = 0x50;
704 +               jb_cfg.nMaxSize = 0x5a0;
705 +
706 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_JB_CFG_SET, &jb_cfg);
707 +               if (status != PJ_SUCCESS) {
708 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_JB_CFG_SET ioctl failed"));
709 +                       return PJ_EUNKNOWN;
710 +               }
711 +
712 +               /* Configure Caller ID type */
713 +               if (tapi_cid_type) {
714 +                       memset(&cid_cfg, 0, sizeof(cid_cfg));
715 +                       cid_cfg.nStandard = tapi_cid_type;
716 +                       status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cfg);
717 +                       if (status != PJ_SUCCESS) {
718 +                               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_CID_CFG_SET ioctl failed"));
719 +                               return PJ_EUNKNOWN;
720 +                       }
721 +               }
722 +
723 +               /* check hook status */
724 +               hook_status = 0;
725 +               status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_HOOK_STATUS_GET, &hook_status);
726 +               if (status != PJ_SUCCESS) {
727 +                       TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!"));
728 +                       return PJ_EUNKNOWN;
729 +               }
730 +
731 +               /* if off hook do initialization */
732 +               if (hook_status) {
733 +                       status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE);
734 +                       if (status != PJ_SUCCESS) {
735 +                               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
736 +                               return PJ_EUNKNOWN;
737 +                       }
738 +                       status = ioctl(c, IFX_TAPI_ENC_START, 0);
739 +                       if (status != PJ_SUCCESS) {
740 +                               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_START ioctl failed!"));
741 +                               return PJ_EUNKNOWN;
742 +                       }
743 +
744 +                       status = ioctl(c, IFX_TAPI_DEC_START, 0);
745 +                       if (status != PJ_SUCCESS) {
746 +                               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_START ioctl failed!"));
747 +                               return PJ_EUNKNOWN;
748 +                       }
749 +               }
750 +       }
751 +
752 +       return status;
753 +}
754 +
755 +static pj_status_t
756 +tapi_dev_stop(tapi_aud_factory_t *f)
757 +{
758 +       pj_status_t status = PJ_SUCCESS;
759 +       pj_uint8_t c;
760 +
761 +       if (ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0) != PJ_SUCCESS) {
762 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_STOP ioctl failed"));
763 +               status = PJ_EUNKNOWN;
764 +       }
765 +
766 +       close(f->dev_ctx.dev_fd);
767 +       for (c = TAPI_AUDIO_PORT_NUM; c > 0; c--)
768 +               close(f->dev_ctx.ch_fd[TAPI_AUDIO_PORT_NUM-c]);
769 +
770 +       return status;
771 +}
772 +
773 +static pj_status_t
774 +tapi_dev_codec_control(pj_int32_t fd, pj_uint8_t start)
775 +{
776 +       if (ioctl(fd, start ? IFX_TAPI_ENC_START : IFX_TAPI_ENC_STOP, 0) != PJ_SUCCESS) {
777 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_%s ioctl failed!",
778 +                       start ? "START" : "STOP"));
779 +               return PJ_EUNKNOWN;
780 +       }
781 +
782 +       if (ioctl(fd, start ? IFX_TAPI_DEC_START : IFX_TAPI_DEC_STOP, 0) != IFX_SUCCESS) {
783 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_%s ioctl failed!",
784 +                       start ? "START" : "STOP"));
785 +               return PJ_EUNKNOWN;
786 +       }
787 +
788 +       return PJ_SUCCESS;
789 +}
790 +
791 +static pj_status_t tapi_dev_event_on_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx)
792 +{
793 +       PJ_LOG(1,(THIS_FILE, "TAPI: ONHOOK"));
794 +
795 +       if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET,
796 +               IFX_TAPI_LINE_FEED_STANDBY) != PJ_SUCCESS) {
797 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
798 +               return PJ_EUNKNOWN;
799 +       }
800 +
801 +       /* enc/dec stop */
802 +       if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) {
803 +               TRACE_((THIS_FILE, "ERROR - codec start failed!"));
804 +               return PJ_EUNKNOWN;
805 +       }
806 +
807 +       return PJ_SUCCESS;
808 +}
809 +
810 +static pj_status_t tapi_dev_event_off_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx)
811 +{
812 +       PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK"));
813 +
814 +       if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET,
815 +               IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) {
816 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
817 +               return PJ_EUNKNOWN;
818 +       }
819 +
820 +       /* enc/dec stop */
821 +       if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) {
822 +               TRACE_((THIS_FILE, "ERROR - codec start failed!"));
823 +               return PJ_EUNKNOWN;
824 +       }
825 +
826 +       return PJ_SUCCESS;
827 +}
828 +
829 +static pj_status_t
830 +tapi_dev_event_digit(tapi_ctx *dev_ctx, pj_uint32_t dev_idx)
831 +{
832 +       PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK"));
833 +
834 +       if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET,
835 +                       IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) {
836 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
837 +               return PJ_EUNKNOWN;
838 +       }
839 +
840 +       /* enc/dec stop */
841 +       if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) {
842 +               TRACE_((THIS_FILE, "ERROR - codec start failed!"));
843 +               return PJ_EUNKNOWN;
844 +       }
845 +
846 +       return PJ_SUCCESS;
847 +}
848 +
849 +static pj_status_t
850 +tapi_dev_event_handler(tapi_aud_stream_t *stream)
851 +{
852 +       IFX_TAPI_EVENT_t tapiEvent;
853 +       tapi_ctx *dev_ctx = stream->dev_ctx;
854 +       pj_status_t status = PJ_SUCCESS;
855 +       unsigned int i;
856 +
857 +       for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) {
858 +               memset (&tapiEvent, 0, sizeof(tapiEvent));
859 +               tapiEvent.ch = dev_ctx->data2phone_map[i];
860 +               status = ioctl(dev_ctx->dev_fd, IFX_TAPI_EVENT_GET, &tapiEvent);
861 +
862 +               if ((status == PJ_SUCCESS) && (tapiEvent.id != IFX_TAPI_EVENT_NONE)) {
863 +                       switch(tapiEvent.id) {
864 +                       case IFX_TAPI_EVENT_FXS_ONHOOK:
865 +                               status = tapi_dev_event_on_hook(dev_ctx, i);
866 +                               if(tapi_hook_callback)
867 +                                       tapi_hook_callback(i, 0);
868 +                               break;
869 +                       case IFX_TAPI_EVENT_FXS_OFFHOOK:
870 +                               status = tapi_dev_event_off_hook(dev_ctx, i);
871 +                               if(tapi_hook_callback)
872 +                                       tapi_hook_callback(i, 1);
873 +                               break;
874 +                       case IFX_TAPI_EVENT_DTMF_DIGIT:
875 +                               if(tapi_digit_callback)
876 +                                       tapi_digit_callback(i, tapiEvent.data.dtmf.ascii);
877 +                               break;
878 +                       case IFX_TAPI_EVENT_COD_DEC_CHG:
879 +                       case IFX_TAPI_EVENT_TONE_GEN_END:
880 +                       case IFX_TAPI_EVENT_CID_TX_SEQ_END:
881 +                               break;
882 +                       default:
883 +                               PJ_LOG(1,(THIS_FILE, "unknown tapi event %08X", tapiEvent.id));
884 +                               break;
885 +                       }
886 +               }
887 +       }
888 +
889 +       return status;
890 +}
891 +
892 +static pj_status_t
893 +tapi_dev_data_handler(tapi_aud_stream_t *stream) {
894 +       pj_status_t status = PJ_SUCCESS;
895 +       tapi_ctx *dev_ctx = stream->dev_ctx;
896 +       pj_uint32_t dev_idx = stream->param.rec_id;
897 +       pj_uint8_t buf_rec[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0};
898 +       pj_uint8_t buf_play[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0};
899 +       pjmedia_frame frame_rec, frame_play;
900 +       pj_int32_t ret;
901 +
902 +       /* Get data from driver */
903 +       ret = read(dev_ctx->ch_fd[dev_idx], buf_rec, sizeof(buf_rec));
904 +       if (ret < 0) {
905 +               TRACE_((THIS_FILE, "ERROR - no data available from device!"));
906 +               return PJ_EUNKNOWN;
907 +       }
908 +
909 +       if (ret > 0) {
910 +               frame_rec.type = PJMEDIA_FRAME_TYPE_AUDIO;
911 +               frame_rec.buf = buf_rec + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE;
912 +               frame_rec.size = ret - TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE;
913 +               frame_rec.timestamp.u64 = stream->timestamp.u64;
914 +
915 +               status = stream->rec_cb(stream->user_data, &frame_rec);
916 +               if (status != PJ_SUCCESS)
917 +                       PJ_LOG(1, (THIS_FILE, "rec_cb() failed %d", status));
918 +
919 +               frame_play.type = PJMEDIA_FRAME_TYPE_AUDIO;
920 +               frame_play.buf = buf_play + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE;
921 +               frame_play.size = TAPI_LL_DEV_ENC_BYTES_PER_FRAME;
922 +               frame_play.timestamp.u64 = stream->timestamp.u64;
923 +
924 +               status = (*stream->play_cb)(stream->user_data, &frame_play);
925 +               if (status != PJ_SUCCESS) {
926 +                       PJ_LOG(1, (THIS_FILE, "play_cb() failed %d", status));
927 +               } else {
928 +                       memcpy(buf_play, buf_rec, TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE);
929 +
930 +                       ret = write(dev_ctx->ch_fd[dev_idx], buf_play, sizeof(buf_play));
931 +
932 +                       if (ret < 0) {
933 +                               PJ_LOG(1, (THIS_FILE, "ERROR - device data writing failed!"));
934 +                               return PJ_EUNKNOWN;
935 +                       }
936 +
937 +                       if (ret == 0) {
938 +                               PJ_LOG(1, (THIS_FILE, "ERROR - no data written to device!"));
939 +                               return PJ_EUNKNOWN;
940 +                       }
941 +               }
942 +
943 +               stream->timestamp.u64 += TAPI_LL_DEV_ENC_SMPL_PER_FRAME;
944 +       }
945 +
946 +       return PJ_SUCCESS;
947 +}
948 +
949 +static int
950 +PJ_THREAD_FUNC tapi_dev_thread(void *arg) {
951 +       tapi_ctx *dev_ctx = streams[0].dev_ctx;
952 +       pj_uint32_t sretval;
953 +       struct pollfd fds[3];
954 +
955 +       PJ_LOG(1,(THIS_FILE, "TAPI: thread starting..."));
956 +
957 +       streams[0].run_flag = 1;
958 +       streams[1].run_flag = 1;
959 +
960 +       fds[0].fd = dev_ctx->dev_fd;
961 +       fds[0].events = POLLIN;
962 +       fds[1].fd = dev_ctx->ch_fd[0];
963 +       fds[1].events = POLLIN;
964 +       fds[2].fd = dev_ctx->ch_fd[1];
965 +       fds[2].events = POLLIN;
966 +
967 +       while(1)
968 +       {
969 +               sretval = poll(fds, TAPI_AUDIO_PORT_NUM + 1, TAPI_LL_DEV_SELECT_TIMEOUT_MS);
970 +
971 +               if (!streams[0].run_flag && !streams[0].run_flag)
972 +                       break;
973 +               if (sretval <= 0)
974 +                       continue;
975 +
976 +               if (fds[0].revents == POLLIN) {
977 +                       if (tapi_dev_event_handler(&streams[0]) != PJ_SUCCESS) {
978 +                               PJ_LOG(1, (THIS_FILE, "TAPI: event hanldler failed"));
979 +                               break;
980 +                       }
981 +               }
982 +
983 +               if (fds[1].revents == POLLIN) {
984 +                       if (tapi_dev_data_handler(&streams[0]) != PJ_SUCCESS) {
985 +                               PJ_LOG(1, (THIS_FILE, "TAPI: data hanldler failed"));
986 +                               break;
987 +                       }
988 +               }
989 +
990 +               if (fds[2].revents == POLLIN) {
991 +                       if (tapi_dev_data_handler(&streams[1]) != PJ_SUCCESS) {
992 +                               PJ_LOG(1, (THIS_FILE, "TAPI: data hanldler failed"));
993 +                               break;
994 +                       }
995 +               }
996 +       }
997 +       PJ_LOG(1, (THIS_FILE, "TAPI: thread stopping..."));
998 +
999 +       return 0;
1000 +}
1001 +
1002 +/* Factory operations */
1003 +
1004 +pjmedia_aud_dev_factory*
1005 +pjmedia_tapi_factory(pj_pool_factory *pf) {
1006 +       struct tapi_aud_factory *f;
1007 +       pj_pool_t *pool;
1008 +
1009 +       TRACE_((THIS_FILE, "pjmedia_tapi_factory()"));
1010 +
1011 +       pool = pj_pool_create(pf, "tapi", 512, 512, NULL);
1012 +       f = PJ_POOL_ZALLOC_T(pool, struct tapi_aud_factory);
1013 +       f->pf = pf;
1014 +       f->pool = pool;
1015 +       f->base.op = &tapi_fact_op;
1016 +
1017 +       return &f->base;
1018 +}
1019 +
1020 +static pj_status_t
1021 +factory_init(pjmedia_aud_dev_factory *f)
1022 +{
1023 +       struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
1024 +       pj_uint8_t i;
1025 +
1026 +       TRACE_((THIS_FILE, "factory_init()"));
1027 +
1028 +       af->dev_count = TAPI_AUDIO_PORT_NUM;
1029 +       af->dev_info = (pjmedia_aud_dev_info*)
1030 +       pj_pool_calloc(af->pool, af->dev_count, sizeof(pjmedia_aud_dev_info));
1031 +       for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) {
1032 +               pj_ansi_sprintf(af->dev_info[i].name,"%s_%02d", TAPI_BASE_NAME, i);
1033 +               af->dev_info[i].input_count = af->dev_info[i].output_count = 1;
1034 +               af->dev_info[i].default_samples_per_sec = TAPI_LL_DEV_ENC_SMPL_PER_SEC;
1035 +               pj_ansi_strcpy(af->dev_info[i].driver, "/dev/vmmc");
1036 +               af->dev_info[i].caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING |
1037 +                       PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY |
1038 +                       PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY;
1039 +               af->dev_info[i].routes = PJMEDIA_AUD_DEV_ROUTE_DEFAULT ;
1040 +       }
1041 +       if (tapi_dev_start(af) != PJ_SUCCESS) {
1042 +               TRACE_((THIS_FILE, "ERROR - TAPI device init failed!"));
1043 +               return PJ_EUNKNOWN;
1044 +       }
1045 +
1046 +       return PJ_SUCCESS;
1047 +}
1048 +
1049 +static pj_status_t
1050 +factory_destroy(pjmedia_aud_dev_factory *f)
1051 +{
1052 +       struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
1053 +       pj_pool_t *pool;
1054 +       pj_status_t status = PJ_SUCCESS;
1055 +
1056 +       TRACE_((THIS_FILE, "factory_destroy()"));
1057 +
1058 +       if (tapi_dev_stop(af) != PJ_SUCCESS) {
1059 +               TRACE_((THIS_FILE, "ERROR - TAPI device stop failed!"));
1060 +               status = PJ_EUNKNOWN;
1061 +       }
1062 +       pool = af->pool;
1063 +       af->pool = NULL;
1064 +       pj_pool_release(pool);
1065 +
1066 +       return status;
1067 +}
1068 +
1069 +static unsigned
1070 +factory_get_dev_count(pjmedia_aud_dev_factory *f)
1071 +{
1072 +       struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
1073 +       TRACE_((THIS_FILE, "factory_get_dev_count()"));
1074 +
1075 +       return af->dev_count;
1076 +}
1077 +
1078 +static pj_status_t
1079 +factory_get_dev_info(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_dev_info *info)
1080 +{
1081 +       struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
1082 +
1083 +       TRACE_((THIS_FILE, "factory_get_dev_info()"));
1084 +       PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV);
1085 +
1086 +       pj_memcpy(info, &af->dev_info[index], sizeof(*info));
1087 +
1088 +       return PJ_SUCCESS;
1089 +}
1090 +
1091 +static pj_status_t
1092 +factory_default_param(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_param *param)
1093 +{
1094 +       struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
1095 +       struct pjmedia_aud_dev_info *di = &af->dev_info[index];
1096 +
1097 +       TRACE_((THIS_FILE, "factory_default_param."));
1098 +       PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV);
1099 +
1100 +       pj_bzero(param, sizeof(*param));
1101 +       if (di->input_count && di->output_count) {
1102 +               param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
1103 +               param->rec_id = index;
1104 +               param->play_id = index;
1105 +       } else if (di->input_count) {
1106 +               param->dir = PJMEDIA_DIR_CAPTURE;
1107 +               param->rec_id = index;
1108 +               param->play_id = PJMEDIA_AUD_INVALID_DEV;
1109 +       } else if (di->output_count) {
1110 +               param->dir = PJMEDIA_DIR_PLAYBACK;
1111 +               param->play_id = index;
1112 +               param->rec_id = PJMEDIA_AUD_INVALID_DEV;
1113 +       } else {
1114 +               return PJMEDIA_EAUD_INVDEV;
1115 +       }
1116 +
1117 +       param->clock_rate = TAPI_LL_DEV_ENC_SMPL_PER_SEC; //di->default_samples_per_sec;
1118 +       param->channel_count = 1;
1119 +       param->samples_per_frame = TAPI_LL_DEV_ENC_SMPL_PER_FRAME;
1120 +       param->bits_per_sample = TAPI_LL_DEV_ENC_BITS_PER_SMPLS;
1121 +       param->flags = PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE | di->caps;
1122 +       param->output_route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT;
1123 +
1124 +       return PJ_SUCCESS;
1125 +}
1126 +
1127 +
1128 +static pj_status_t
1129 +factory_create_stream(pjmedia_aud_dev_factory *f, const pjmedia_aud_param *param,
1130 +       pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb,
1131 +       void *user_data, pjmedia_aud_stream **p_aud_strm)
1132 +{
1133 +       struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
1134 +       pj_pool_t *pool;
1135 +       pj_status_t status;
1136 +       int id = param->rec_id;
1137 +       struct tapi_aud_stream *strm = &streams[param->rec_id];
1138 +       TRACE_((THIS_FILE, "factory_create_stream() rec_id:%d play_id:%d", param->rec_id, param->play_id));
1139 +
1140 +       /* Can only support 16bits per sample */
1141 +       PJ_ASSERT_RETURN(param->bits_per_sample == TAPI_LL_DEV_ENC_BITS_PER_SMPLS, PJ_EINVAL);
1142 +       PJ_ASSERT_RETURN(param->clock_rate == TAPI_LL_DEV_ENC_SMPL_PER_SEC, PJ_EINVAL);
1143 +       PJ_ASSERT_RETURN(param->samples_per_frame == TAPI_LL_DEV_ENC_SMPL_PER_FRAME, PJ_EINVAL);
1144 +
1145 +       /* Can only support bidirectional stream */
1146 +       PJ_ASSERT_RETURN(param->dir & PJMEDIA_DIR_CAPTURE_PLAYBACK, PJ_EINVAL);
1147 +
1148 +       if (id == 0) {
1149 +               /* Initialize our stream data */
1150 +               pool = pj_pool_create(af->pf, "tapi-dev", 1000, 1000, NULL);
1151 +               PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
1152 +
1153 +               strm->pool = pool;
1154 +       } else {
1155 +               pool = strm->pool = streams[0].pool;
1156 +       }
1157 +
1158 +       strm->rec_cb = rec_cb;
1159 +       strm->play_cb = play_cb;
1160 +       strm->user_data = user_data;
1161 +
1162 +       pj_memcpy(&strm->param, param, sizeof(*param));
1163 +
1164 +       if ((strm->param.flags & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) == 0) {
1165 +               strm->param.ext_fmt.id = PJMEDIA_FORMAT_L16;
1166 +       }
1167 +
1168 +       strm->timestamp.u64 = 0;
1169 +       strm->dev_ctx = &(af->dev_ctx);
1170 +
1171 +       /* Create and start the thread */
1172 +       if (id == 1) {
1173 +               status = pj_thread_create(pool, "tapi", &tapi_dev_thread, strm, 0, 0, &streams[0].thread);
1174 +               if (status != PJ_SUCCESS) {
1175 +                       stream_destroy(&strm->base);
1176 +                       return status;
1177 +               }
1178 +       }
1179 +
1180 +       /* Done */
1181 +       strm->base.op = &tapi_strm_op;
1182 +       *p_aud_strm = &strm->base;
1183 +
1184 +       return PJ_SUCCESS;
1185 +}
1186 +
1187 +static pj_status_t
1188 +stream_get_param(pjmedia_aud_stream *s, pjmedia_aud_param *pi)
1189 +{
1190 +       struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
1191 +
1192 +       PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
1193 +       pj_memcpy(pi, &strm->param, sizeof(*pi));
1194 +
1195 +       if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
1196 +                               &pi->output_vol) == PJ_SUCCESS)
1197 +               pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING;
1198 +
1199 +       if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY,
1200 +                               &pi->output_latency_ms) == PJ_SUCCESS)
1201 +               pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY;
1202 +
1203 +       if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY,
1204 +                               &pi->input_latency_ms) == PJ_SUCCESS)
1205 +               pi->flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY;
1206 +
1207 +       return PJ_SUCCESS;
1208 +}
1209 +
1210 +static pj_status_t
1211 +stream_get_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, void *pval)
1212 +{
1213 +       // struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
1214 +       return PJ_SUCCESS;
1215 +}
1216 +
1217 +static pj_status_t
1218 +stream_set_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, const void *pval)
1219 +{
1220 +       // struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
1221 +       return PJ_SUCCESS;
1222 +}
1223 +
1224 +static pj_status_t
1225 +stream_start(pjmedia_aud_stream *s)
1226 +{
1227 +       struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
1228 +       pj_uint32_t dev_idx;
1229 +
1230 +       TRACE_((THIS_FILE, "stream_start()"));
1231 +
1232 +       dev_idx = strm->param.rec_id;
1233 +
1234 +       return PJ_SUCCESS;
1235 +}
1236 +
1237 +static pj_status_t
1238 +stream_stop(pjmedia_aud_stream *s)
1239 +{
1240 +       struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
1241 +       tapi_ctx *dev_ctx = strm->dev_ctx;
1242 +       pj_uint32_t dev_idx;
1243 +
1244 +       TRACE_((THIS_FILE, "stream_stop()"));
1245 +       dev_idx = strm->param.rec_id;
1246 +
1247 +       if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) {
1248 +               TRACE_((THIS_FILE, "ERROR - codec start failed!"));
1249 +               return PJ_EUNKNOWN;
1250 +       }
1251 +
1252 +       return PJ_SUCCESS;
1253 +}
1254 +
1255 +static pj_status_t
1256 +stream_destroy(pjmedia_aud_stream *s)
1257 +{
1258 +       pj_status_t state = PJ_SUCCESS;
1259 +       struct tapi_aud_stream *stream = (struct tapi_aud_stream*)s;
1260 +       pj_pool_t *pool;
1261 +
1262 +       PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
1263 +       TRACE_((THIS_FILE, "stream_destroy()"));
1264 +
1265 +       stream_stop(&stream->base);
1266 +       stream->run_flag = 0;
1267 +
1268 +       if (stream->thread)
1269 +       {
1270 +               pj_thread_join(stream->thread);
1271 +               pj_thread_destroy(stream->thread);
1272 +               stream->thread = NULL;
1273 +       }
1274 +
1275 +       pool = stream->pool;
1276 +       pj_bzero(stream, sizeof(stream));
1277 +       pj_pool_release(pool);
1278 +
1279 +       return state;
1280 +}
1281 +
1282 +pj_status_t
1283 +tapi_hook_status(pj_uint8_t port, pj_int32_t *status)
1284 +{
1285 +       PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL);
1286 +
1287 +       if (ioctl(ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, status)
1288 +                       != PJ_SUCCESS) {
1289 +               TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!"));
1290 +               return PJ_EUNKNOWN;
1291 +       }
1292 +
1293 +       return PJ_SUCCESS;
1294 +}
1295 +
1296 +pj_status_t
1297 +tapi_ring(pj_uint8_t port, pj_uint8_t state, char *caller_number)
1298 +{
1299 +       PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL);
1300 +
1301 +       if (state) {
1302 +               if (tapi_cid_type && caller_number) {
1303 +                       IFX_TAPI_CID_MSG_t cid_msg;
1304 +                       IFX_TAPI_CID_MSG_ELEMENT_t cid_msg_el[1];
1305 +                       memset(&cid_msg, 0, sizeof(cid_msg));
1306 +                       memset(&cid_msg_el, 0, sizeof(cid_msg_el));
1307 +
1308 +                       cid_msg_el[0].string.elementType = IFX_TAPI_CID_ST_CLI;
1309 +                       cid_msg_el[0].string.len = strlen(caller_number);
1310 +                       strncpy(cid_msg_el[0].string.element, caller_number, sizeof(cid_msg_el[0].string.element));
1311 +
1312 +                       cid_msg.txMode = IFX_TAPI_CID_HM_ONHOOK;
1313 +                       cid_msg.messageType = IFX_TAPI_CID_MT_CSUP;
1314 +                       cid_msg.nMsgElements = 1;
1315 +                       cid_msg.message = cid_msg_el;
1316 +                       ioctl(ch_fd[port], IFX_TAPI_CID_TX_SEQ_START, &cid_msg);
1317 +               } else {
1318 +                       ioctl(ch_fd[port], IFX_TAPI_RING_START, 0);
1319 +               }
1320 +       } else {
1321 +               ioctl(ch_fd[port], IFX_TAPI_RING_STOP, 0);
1322 +       }
1323 +
1324 +       return PJ_SUCCESS;
1325 +}
1326 +
1327 +pj_status_t
1328 +tapi_tone(pj_uint8_t port, pj_uint8_t code)
1329 +{
1330 +       PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL);
1331 +
1332 +       if (tapi_locale && code)
1333 +               ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, code);
1334 +       else if (code)
1335 +               ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, TAPI_TONE_LOCALE_NONE);
1336 +       else
1337 +               ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, 0);
1338 +
1339 +       return PJ_SUCCESS;
1340 +}
1341 +
1342 +#endif /* PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE */
1343 -- 
1344 1.7.7.1
1345