This source file includes following definitions.
- zt_build_gains
- zt_open_range
- FIO_CONFIGURE_SPAN_FUNCTION
- FIO_CONFIGURE_FUNCTION
- FIO_OPEN_FUNCTION
- FIO_CLOSE_FUNCTION
- FIO_COMMAND_FUNCTION
- FIO_GET_ALARMS_FUNCTION
- FIO_WAIT_FUNCTION
- FIO_SPAN_POLL_EVENT_FUNCTION
- FIO_SPAN_NEXT_EVENT_FUNCTION
- FIO_READ_FUNCTION
- FIO_WRITE_FUNCTION
- FIO_CHANNEL_DESTROY_FUNCTION
- FIO_IO_LOAD_FUNCTION
- FIO_IO_UNLOAD_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include "private/ftdm_core.h"
36 #include "ftmod_zt.h"
37
38
39
40
41 static struct {
42 uint32_t codec_ms;
43 uint32_t wink_ms;
44 uint32_t flash_ms;
45 uint32_t eclevel;
46 uint32_t etlevel;
47 float rxgain;
48 float txgain;
49 } zt_globals;
50
51
52
53
54 struct ioctl_codes {
55 int GET_BLOCKSIZE;
56 int SET_BLOCKSIZE;
57 int FLUSH;
58 int SYNC;
59 int GET_PARAMS;
60 int SET_PARAMS;
61 int HOOK;
62 int GETEVENT;
63 int IOMUX;
64 int SPANSTAT;
65 int MAINT;
66 int GETCONF;
67 int SETCONF;
68 int CONFLINK;
69 int CONFDIAG;
70 int GETGAINS;
71 int SETGAINS;
72 int SPANCONFIG;
73 int CHANCONFIG;
74 int SET_BUFINFO;
75 int GET_BUFINFO;
76 int AUDIOMODE;
77 int ECHOCANCEL;
78 int HDLCRAWMODE;
79 int HDLCFCSMODE;
80 int SPECIFY;
81 int SETLAW;
82 int SETLINEAR;
83 int GETCONFMUTE;
84 int ECHOTRAIN;
85 int SETTXBITS;
86 int GETRXBITS;
87 };
88
89
90
91
92 static struct ioctl_codes zt_ioctl_codes = {
93 .GET_BLOCKSIZE = ZT_GET_BLOCKSIZE,
94 .SET_BLOCKSIZE = ZT_SET_BLOCKSIZE,
95 .FLUSH = ZT_FLUSH,
96 .SYNC = ZT_SYNC,
97 .GET_PARAMS = ZT_GET_PARAMS,
98 .SET_PARAMS = ZT_SET_PARAMS,
99 .HOOK = ZT_HOOK,
100 .GETEVENT = ZT_GETEVENT,
101 .IOMUX = ZT_IOMUX,
102 .SPANSTAT = ZT_SPANSTAT,
103 .MAINT = ZT_MAINT,
104 .GETCONF = ZT_GETCONF,
105 .SETCONF = ZT_SETCONF,
106 .CONFLINK = ZT_CONFLINK,
107 .CONFDIAG = ZT_CONFDIAG,
108 .GETGAINS = ZT_GETGAINS,
109 .SETGAINS = ZT_SETGAINS,
110 .SPANCONFIG = ZT_SPANCONFIG,
111 .CHANCONFIG = ZT_CHANCONFIG,
112 .SET_BUFINFO = ZT_SET_BUFINFO,
113 .GET_BUFINFO = ZT_GET_BUFINFO,
114 .AUDIOMODE = ZT_AUDIOMODE,
115 .ECHOCANCEL = ZT_ECHOCANCEL,
116 .HDLCRAWMODE = ZT_HDLCRAWMODE,
117 .HDLCFCSMODE = ZT_HDLCFCSMODE,
118 .SPECIFY = ZT_SPECIFY,
119 .SETLAW = ZT_SETLAW,
120 .SETLINEAR = ZT_SETLINEAR,
121 .GETCONFMUTE = ZT_GETCONFMUTE,
122 .ECHOTRAIN = ZT_ECHOTRAIN,
123 .SETTXBITS = ZT_SETTXBITS,
124 .GETRXBITS = ZT_GETRXBITS
125 };
126
127
128
129
130 static struct ioctl_codes dahdi_ioctl_codes = {
131 .GET_BLOCKSIZE = DAHDI_GET_BLOCKSIZE,
132 .SET_BLOCKSIZE = DAHDI_SET_BLOCKSIZE,
133 .FLUSH = DAHDI_FLUSH,
134 .SYNC = DAHDI_SYNC,
135 .GET_PARAMS = DAHDI_GET_PARAMS,
136 .SET_PARAMS = DAHDI_SET_PARAMS,
137 .HOOK = DAHDI_HOOK,
138 .GETEVENT = DAHDI_GETEVENT,
139 .IOMUX = DAHDI_IOMUX,
140 .SPANSTAT = DAHDI_SPANSTAT,
141 .MAINT = DAHDI_MAINT,
142 .GETCONF = DAHDI_GETCONF,
143 .SETCONF = DAHDI_SETCONF,
144 .CONFLINK = DAHDI_CONFLINK,
145 .CONFDIAG = DAHDI_CONFDIAG,
146 .GETGAINS = DAHDI_GETGAINS,
147 .SETGAINS = DAHDI_SETGAINS,
148 .SPANCONFIG = DAHDI_SPANCONFIG,
149 .CHANCONFIG = DAHDI_CHANCONFIG,
150 .SET_BUFINFO = DAHDI_SET_BUFINFO,
151 .GET_BUFINFO = DAHDI_GET_BUFINFO,
152 .AUDIOMODE = DAHDI_AUDIOMODE,
153 .ECHOCANCEL = DAHDI_ECHOCANCEL,
154 .HDLCRAWMODE = DAHDI_HDLCRAWMODE,
155 .HDLCFCSMODE = DAHDI_HDLCFCSMODE,
156 .SPECIFY = DAHDI_SPECIFY,
157 .SETLAW = DAHDI_SETLAW,
158 .SETLINEAR = DAHDI_SETLINEAR,
159 .GETCONFMUTE = DAHDI_GETCONFMUTE,
160 .ECHOTRAIN = DAHDI_ECHOTRAIN,
161 .SETTXBITS = DAHDI_SETTXBITS,
162 .GETRXBITS = DAHDI_GETRXBITS
163 };
164
165 #define ZT_INVALID_SOCKET -1
166 static struct ioctl_codes codes;
167 static const char *ctlpath = NULL;
168 static const char *chanpath = NULL;
169
170 static const char dahdi_ctlpath[] = "/dev/dahdi/ctl";
171 static const char dahdi_chanpath[] = "/dev/dahdi/channel";
172
173 static const char zt_ctlpath[] = "/dev/zap/ctl";
174 static const char zt_chanpath[] = "/dev/zap/channel";
175
176 static ftdm_socket_t CONTROL_FD = ZT_INVALID_SOCKET;
177
178 FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event);
179 FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event);
180
181
182
183
184
185
186
187
188 static void zt_build_gains(struct zt_gains *g, float rxgain, float txgain, int codec)
189 {
190 int j;
191 int k;
192 float linear_rxgain = pow(10.0, rxgain / 20.0);
193 float linear_txgain = pow(10.0, txgain / 20.0);
194
195 switch (codec) {
196 case FTDM_CODEC_ALAW:
197 for (j = 0; j < (sizeof(g->receive_gain) / sizeof(g->receive_gain[0])); j++) {
198 if (rxgain) {
199 k = (int) (((float) alaw_to_linear(j)) * linear_rxgain);
200 if (k > 32767) k = 32767;
201 if (k < -32767) k = -32767;
202 g->receive_gain[j] = linear_to_alaw(k);
203 } else {
204 g->receive_gain[j] = j;
205 }
206 if (txgain) {
207 k = (int) (((float) alaw_to_linear(j)) * linear_txgain);
208 if (k > 32767) k = 32767;
209 if (k < -32767) k = -32767;
210 g->transmit_gain[j] = linear_to_alaw(k);
211 } else {
212 g->transmit_gain[j] = j;
213 }
214 }
215 break;
216 case FTDM_CODEC_ULAW:
217 for (j = 0; j < (sizeof(g->receive_gain) / sizeof(g->receive_gain[0])); j++) {
218 if (rxgain) {
219 k = (int) (((float) ulaw_to_linear(j)) * linear_rxgain);
220 if (k > 32767) k = 32767;
221 if (k < -32767) k = -32767;
222 g->receive_gain[j] = linear_to_ulaw(k);
223 } else {
224 g->receive_gain[j] = j;
225 }
226 if (txgain) {
227 k = (int) (((float) ulaw_to_linear(j)) * linear_txgain);
228 if (k > 32767) k = 32767;
229 if (k < -32767) k = -32767;
230 g->transmit_gain[j] = linear_to_ulaw(k);
231 } else {
232 g->transmit_gain[j] = j;
233 }
234 }
235 break;
236 }
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250 static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, ftdm_chan_type_t type, char *name, char *number, unsigned char cas_bits)
251 {
252 unsigned configured = 0, x;
253 zt_params_t ztp;
254
255 memset(&ztp, 0, sizeof(ztp));
256
257 if (type == FTDM_CHAN_TYPE_CAS) {
258 ftdm_log(FTDM_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits);
259 }
260 for(x = start; x < end; x++) {
261 ftdm_channel_t *ftdmchan;
262 ftdm_socket_t sockfd = ZT_INVALID_SOCKET;
263 int len;
264
265 sockfd = open(chanpath, O_RDWR);
266 if (sockfd != ZT_INVALID_SOCKET && ftdm_span_add_channel(span, sockfd, type, &ftdmchan) == FTDM_SUCCESS) {
267
268 if (ioctl(sockfd, codes.SPECIFY, &x)) {
269 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s chan %d fd %d (%s)\n", chanpath, x, sockfd, strerror(errno));
270 close(sockfd);
271 continue;
272 }
273
274 if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
275 struct zt_bufferinfo binfo;
276 memset(&binfo, 0, sizeof(binfo));
277 binfo.txbufpolicy = 0;
278 binfo.rxbufpolicy = 0;
279 binfo.numbufs = 32;
280 binfo.bufsize = 1024;
281 if (ioctl(sockfd, codes.SET_BUFINFO, &binfo)) {
282 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd);
283 close(sockfd);
284 continue;
285 }
286 }
287
288 if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO) {
289 struct zt_chanconfig cc;
290 memset(&cc, 0, sizeof(cc));
291 cc.chan = cc.master = x;
292
293 switch(type) {
294 case FTDM_CHAN_TYPE_FXS:
295 {
296 switch(span->start_type) {
297 case FTDM_ANALOG_START_KEWL:
298 cc.sigtype = ZT_SIG_FXOKS;
299 break;
300 case FTDM_ANALOG_START_LOOP:
301 cc.sigtype = ZT_SIG_FXOLS;
302 break;
303 case FTDM_ANALOG_START_GROUND:
304 cc.sigtype = ZT_SIG_FXOGS;
305 break;
306 default:
307 break;
308 }
309 }
310 break;
311 case FTDM_CHAN_TYPE_FXO:
312 {
313 switch(span->start_type) {
314 case FTDM_ANALOG_START_KEWL:
315 cc.sigtype = ZT_SIG_FXSKS;
316 break;
317 case FTDM_ANALOG_START_LOOP:
318 cc.sigtype = ZT_SIG_FXSLS;
319 break;
320 case FTDM_ANALOG_START_GROUND:
321 cc.sigtype = ZT_SIG_FXSGS;
322 break;
323 default:
324 break;
325 }
326 }
327 break;
328 default:
329 break;
330 }
331
332 if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) {
333 ftdm_log(FTDM_LOG_WARNING, "this ioctl fails on older ftdmtel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno));
334 }
335 }
336
337 if (type == FTDM_CHAN_TYPE_CAS) {
338 struct zt_chanconfig cc;
339 memset(&cc, 0, sizeof(cc));
340 cc.chan = cc.master = x;
341 cc.sigtype = ZT_SIG_CAS;
342 cc.idlebits = cas_bits;
343 if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) {
344 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd, strerror(errno));
345 close(sockfd);
346 continue;
347 }
348 }
349
350 if (ftdmchan->type != FTDM_CHAN_TYPE_DQ921 && ftdmchan->type != FTDM_CHAN_TYPE_DQ931) {
351 len = zt_globals.codec_ms * 8;
352 if (ioctl(ftdmchan->sockfd, codes.SET_BLOCKSIZE, &len)) {
353 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s\n",
354 chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd, strerror(errno));
355 close(sockfd);
356 continue;
357 }
358
359 ftdmchan->packet_len = len;
360 ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8;
361
362 if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
363 ftdmchan->packet_len *= 2;
364 }
365 }
366
367 if (ioctl(sockfd, codes.GET_PARAMS, &ztp) < 0) {
368 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd);
369 close(sockfd);
370 continue;
371 }
372
373 if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
374 if (
375 (ztp.sig_type != ZT_SIG_HDLCRAW) &&
376 (ztp.sig_type != ZT_SIG_HDLCFCS) &&
377 (ztp.sig_type != ZT_SIG_HARDHDLC)
378 ) {
379 ftdm_log(FTDM_LOG_ERROR, "Failure configuring device %s as FreeTDM device %d:%d fd:%d, hardware signaling is not HDLC, fix your Zap/DAHDI configuration!\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd);
380 close(sockfd);
381 continue;
382 }
383 }
384
385 ftdm_log(FTDM_LOG_INFO, "configuring device %s channel %d as FreeTDM device %d:%d fd:%d\n", chanpath, x, ftdmchan->span_id, ftdmchan->chan_id, sockfd);
386
387 ftdmchan->rate = 8000;
388 ftdmchan->physical_span_id = ztp.span_no;
389 ftdmchan->physical_chan_id = ztp.chan_no;
390
391 if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO || type == FTDM_CHAN_TYPE_EM || type == FTDM_CHAN_TYPE_B) {
392 if (ztp.g711_type == ZT_G711_ALAW) {
393 ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_ALAW;
394 } else if (ztp.g711_type == ZT_G711_MULAW) {
395 ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_ULAW;
396 } else {
397 int type;
398
399 if (ftdmchan->span->trunk_type == FTDM_TRUNK_E1) {
400 type = FTDM_CODEC_ALAW;
401 } else {
402 type = FTDM_CODEC_ULAW;
403 }
404
405 ftdmchan->native_codec = ftdmchan->effective_codec = type;
406
407 }
408 }
409
410 ztp.wink_time = zt_globals.wink_ms;
411 ztp.flash_time = zt_globals.flash_ms;
412
413 if (ioctl(sockfd, codes.SET_PARAMS, &ztp) < 0) {
414 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd);
415 close(sockfd);
416 continue;
417 }
418
419 if (!ftdm_strlen_zero(name)) {
420 ftdm_copy_string(ftdmchan->chan_name, name, sizeof(ftdmchan->chan_name));
421 }
422 if (!ftdm_strlen_zero(number)) {
423 ftdm_copy_string(ftdmchan->chan_number, number, sizeof(ftdmchan->chan_number));
424 }
425 configured++;
426 } else {
427 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s\n", chanpath);
428 }
429 }
430
431
432
433 return configured;
434 }
435
436
437
438
439
440
441
442
443
444
445 static FIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span)
446 {
447
448 int items, i;
449 char *mydata, *item_list[10];
450 char *ch, *mx;
451 unsigned char cas_bits = 0;
452 int channo;
453 int top = 0;
454 unsigned configured = 0;
455
456 assert(str != NULL);
457
458
459 mydata = ftdm_strdup(str);
460 assert(mydata != NULL);
461
462
463 items = ftdm_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0])));
464
465 for(i = 0; i < items; i++) {
466 ch = item_list[i];
467
468 if (!(ch)) {
469 ftdm_log(FTDM_LOG_ERROR, "Invalid input\n");
470 continue;
471 }
472
473 channo = atoi(ch);
474
475 if (channo < 0) {
476 ftdm_log(FTDM_LOG_ERROR, "Invalid channel number %d\n", channo);
477 continue;
478 }
479
480 if ((mx = strchr(ch, '-'))) {
481 mx++;
482 top = atoi(mx) + 1;
483 } else {
484 top = channo + 1;
485 }
486
487
488 if (top < 0) {
489 ftdm_log(FTDM_LOG_ERROR, "Invalid range number %d\n", top);
490 continue;
491 }
492 if (FTDM_CHAN_TYPE_CAS == type && ftdm_config_get_cas_bits(ch, &cas_bits)) {
493 ftdm_log(FTDM_LOG_ERROR, "Failed to get CAS bits in CAS channel\n");
494 continue;
495 }
496 configured += zt_open_range(span, channo, top, type, name, number, cas_bits);
497
498 }
499
500 ftdm_safe_free(mydata);
501
502 return configured;
503
504 }
505
506
507
508
509
510
511
512
513
514 static FIO_CONFIGURE_FUNCTION(zt_configure)
515 {
516
517 int num;
518 float fnum;
519
520 if (!strcasecmp(category, "defaults")) {
521 if (!strcasecmp(var, "codec_ms")) {
522 num = atoi(val);
523 if (num < 10 || num > 60) {
524 ftdm_log(FTDM_LOG_WARNING, "invalid codec ms at line %d\n", lineno);
525 } else {
526 zt_globals.codec_ms = num;
527 }
528 } else if (!strcasecmp(var, "wink_ms")) {
529 num = atoi(val);
530 if (num < 50 || num > 3000) {
531 ftdm_log(FTDM_LOG_WARNING, "invalid wink ms at line %d\n", lineno);
532 } else {
533 zt_globals.wink_ms = num;
534 }
535 } else if (!strcasecmp(var, "flash_ms")) {
536 num = atoi(val);
537 if (num < 50 || num > 3000) {
538 ftdm_log(FTDM_LOG_WARNING, "invalid flash ms at line %d\n", lineno);
539 } else {
540 zt_globals.flash_ms = num;
541 }
542 } else if (!strcasecmp(var, "echo_cancel_level")) {
543 num = atoi(val);
544 if (num < 0 || num > 256) {
545 ftdm_log(FTDM_LOG_WARNING, "invalid echo can val at line %d\n", lineno);
546 } else {
547 zt_globals.eclevel = num;
548 }
549 } else if (!strcasecmp(var, "echo_train_level")) {
550 if (zt_globals.eclevel < 1) {
551 ftdm_log(FTDM_LOG_WARNING, "can't set echo train level without setting echo cancel level first at line %d\n", lineno);
552 } else {
553 num = atoi(val);
554 if (num < 0 || num > 256) {
555 ftdm_log(FTDM_LOG_WARNING, "invalid echo train val at line %d\n", lineno);
556 } else {
557 zt_globals.etlevel = num;
558 }
559 }
560 } else if (!strcasecmp(var, "rxgain")) {
561 fnum = (float)atof(val);
562 if (fnum < -100.0 || fnum > 100.0) {
563 ftdm_log(FTDM_LOG_WARNING, "invalid rxgain val at line %d\n", lineno);
564 } else {
565 zt_globals.rxgain = fnum;
566 ftdm_log(FTDM_LOG_INFO, "Setting rxgain val to %f\n", fnum);
567 }
568 } else if (!strcasecmp(var, "txgain")) {
569 fnum = (float)atof(val);
570 if (fnum < -100.0 || fnum > 100.0) {
571 ftdm_log(FTDM_LOG_WARNING, "invalid txgain val at line %d\n", lineno);
572 } else {
573 zt_globals.txgain = fnum;
574 ftdm_log(FTDM_LOG_INFO, "Setting txgain val to %f\n", fnum);
575 }
576 } else {
577 ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown setting '%s'\n", var);
578 }
579 }
580
581 return FTDM_SUCCESS;
582 }
583
584
585
586
587
588
589 static FIO_OPEN_FUNCTION(zt_open)
590 {
591 ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL);
592
593 if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) {
594 ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE;
595 } else {
596 int blocksize = zt_globals.codec_ms * (ftdmchan->rate / 1000);
597 int err;
598 if ((err = ioctl(ftdmchan->sockfd, codes.SET_BLOCKSIZE, &blocksize))) {
599 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
600 return FTDM_FAIL;
601 } else {
602 ftdmchan->effective_interval = ftdmchan->native_interval;
603 ftdmchan->packet_len = blocksize;
604 ftdmchan->native_codec = ftdmchan->effective_codec;
605 }
606
607 if (ftdmchan->type == FTDM_CHAN_TYPE_B) {
608 int one = 1;
609 if (ioctl(ftdmchan->sockfd, codes.AUDIOMODE, &one)) {
610 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
611 ftdm_log(FTDM_LOG_ERROR, "%s\n", ftdmchan->last_error);
612 return FTDM_FAIL;
613 }
614 }
615 if (zt_globals.rxgain || zt_globals.txgain) {
616 struct zt_gains gains;
617 memset(&gains, 0, sizeof(gains));
618
619 gains.chan_no = ftdmchan->physical_chan_id;
620 zt_build_gains(&gains, zt_globals.rxgain, zt_globals.txgain, ftdmchan->native_codec);
621
622 if (zt_globals.rxgain)
623 ftdm_log(FTDM_LOG_INFO, "Setting rxgain to %f on channel %d\n", zt_globals.rxgain, gains.chan_no);
624
625 if (zt_globals.txgain)
626 ftdm_log(FTDM_LOG_INFO, "Setting txgain to %f on channel %d\n", zt_globals.txgain, gains.chan_no);
627
628 if (ioctl(ftdmchan->sockfd, codes.SETGAINS, &gains) < 0) {
629 ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->sockfd);
630 }
631 }
632
633 if (zt_globals.eclevel >= 0) {
634 int len = zt_globals.eclevel;
635 if (len) {
636 ftdm_log(FTDM_LOG_INFO, "Setting echo cancel to %d taps for %d:%d\n", len, ftdmchan->span_id, ftdmchan->chan_id);
637 } else {
638 ftdm_log(FTDM_LOG_INFO, "Disable echo cancel for %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id);
639 }
640 if (ioctl(ftdmchan->sockfd, codes.ECHOCANCEL, &len)) {
641 ftdm_log(FTDM_LOG_WARNING, "Echo cancel not available for %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id);
642 } else if (zt_globals.etlevel > 0) {
643 len = zt_globals.etlevel;
644 if (ioctl(ftdmchan->sockfd, codes.ECHOTRAIN, &len)) {
645 ftdm_log(FTDM_LOG_WARNING, "Echo training not available for %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id);
646 }
647 }
648 }
649
650 }
651 return FTDM_SUCCESS;
652 }
653
654
655
656
657
658
659 static FIO_CLOSE_FUNCTION(zt_close)
660 {
661 return FTDM_SUCCESS;
662 }
663
664
665
666
667
668
669
670
671 static FIO_COMMAND_FUNCTION(zt_command)
672 {
673 zt_params_t ztp;
674 int err = 0;
675
676 memset(&ztp, 0, sizeof(ztp));
677
678 switch(command) {
679 case FTDM_COMMAND_ENABLE_ECHOCANCEL:
680 {
681 int level = FTDM_COMMAND_OBJ_INT;
682 err = ioctl(ftdmchan->sockfd, codes.ECHOCANCEL, &level);
683 FTDM_COMMAND_OBJ_INT = level;
684 }
685 case FTDM_COMMAND_DISABLE_ECHOCANCEL:
686 {
687 int level = 0;
688 err = ioctl(ftdmchan->sockfd, codes.ECHOCANCEL, &level);
689 FTDM_COMMAND_OBJ_INT = level;
690 }
691 break;
692 case FTDM_COMMAND_ENABLE_ECHOTRAIN:
693 {
694 int level = FTDM_COMMAND_OBJ_INT;
695 err = ioctl(ftdmchan->sockfd, codes.ECHOTRAIN, &level);
696 FTDM_COMMAND_OBJ_INT = level;
697 }
698 case FTDM_COMMAND_DISABLE_ECHOTRAIN:
699 {
700 int level = 0;
701 err = ioctl(ftdmchan->sockfd, codes.ECHOTRAIN, &level);
702 FTDM_COMMAND_OBJ_INT = level;
703 }
704 break;
705 case FTDM_COMMAND_OFFHOOK:
706 {
707 int command = ZT_OFFHOOK;
708 if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
709 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "OFFHOOK Failed");
710 return FTDM_FAIL;
711 }
712 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
713 }
714 break;
715 case FTDM_COMMAND_ONHOOK:
716 {
717 int command = ZT_ONHOOK;
718 if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
719 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed");
720 return FTDM_FAIL;
721 }
722 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
723 }
724 break;
725 case FTDM_COMMAND_FLASH:
726 {
727 int command = ZT_FLASH;
728 if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
729 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "FLASH Failed");
730 return FTDM_FAIL;
731 }
732 }
733 break;
734 case FTDM_COMMAND_WINK:
735 {
736 int command = ZT_WINK;
737 if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
738 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "WINK Failed");
739 return FTDM_FAIL;
740 }
741 }
742 break;
743 case FTDM_COMMAND_GENERATE_RING_ON:
744 {
745 int command = ZT_RING;
746 if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
747 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring Failed");
748 return FTDM_FAIL;
749 }
750 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
751 }
752 break;
753 case FTDM_COMMAND_GENERATE_RING_OFF:
754 {
755 int command = ZT_RINGOFF;
756 if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
757 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring-off failed");
758 return FTDM_FAIL;
759 }
760 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
761 }
762 break;
763 case FTDM_COMMAND_GET_INTERVAL:
764 {
765
766 if (!(err = ioctl(ftdmchan->sockfd, codes.GET_BLOCKSIZE, &ftdmchan->packet_len))) {
767 ftdmchan->native_interval = ftdmchan->packet_len / 8;
768 if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
769 ftdmchan->packet_len *= 2;
770 }
771 FTDM_COMMAND_OBJ_INT = ftdmchan->native_interval;
772 }
773 }
774 break;
775 case FTDM_COMMAND_SET_INTERVAL:
776 {
777 int interval = FTDM_COMMAND_OBJ_INT;
778 int len = interval * 8;
779
780 if (!(err = ioctl(ftdmchan->sockfd, codes.SET_BLOCKSIZE, &len))) {
781 ftdmchan->packet_len = len;
782 ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8;
783
784 if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
785 ftdmchan->packet_len *= 2;
786 }
787 }
788 }
789 break;
790 case FTDM_COMMAND_SET_CAS_BITS:
791 {
792 int bits = FTDM_COMMAND_OBJ_INT;
793 err = ioctl(ftdmchan->sockfd, codes.SETTXBITS, &bits);
794 }
795 break;
796 case FTDM_COMMAND_GET_CAS_BITS:
797 {
798 err = ioctl(ftdmchan->sockfd, codes.GETRXBITS, &ftdmchan->rx_cas_bits);
799 if (!err) {
800 FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits;
801 }
802 }
803 break;
804 case FTDM_COMMAND_FLUSH_TX_BUFFERS:
805 {
806 int flushmode = ZT_FLUSH_WRITE;
807 err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
808 }
809 break;
810 case FTDM_COMMAND_FLUSH_RX_BUFFERS:
811 {
812 int flushmode = ZT_FLUSH_READ;
813 err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
814 }
815 break;
816 case FTDM_COMMAND_FLUSH_BUFFERS:
817 {
818 int flushmode = ZT_FLUSH_BOTH;
819 err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
820 }
821 break;
822 default:
823 err = FTDM_NOTIMPL;
824 break;
825 };
826
827 if (err && err != FTDM_NOTIMPL) {
828 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
829 return FTDM_FAIL;
830 }
831
832
833 return err == 0 ? FTDM_SUCCESS : err;
834 }
835
836
837
838
839
840
841 static FIO_GET_ALARMS_FUNCTION(zt_get_alarms)
842 {
843 struct zt_spaninfo info;
844
845 memset(&info, 0, sizeof(info));
846 info.span_no = ftdmchan->physical_span_id;
847
848 if (ioctl(CONTROL_FD, codes.SPANSTAT, &info)) {
849 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ioctl failed (%s)", strerror(errno));
850 snprintf(ftdmchan->span->last_error, sizeof(ftdmchan->span->last_error), "ioctl failed (%s)", strerror(errno));
851 return FTDM_FAIL;
852 }
853
854 ftdmchan->alarm_flags = info.alarms;
855
856 return FTDM_SUCCESS;
857 }
858
859
860
861
862
863
864
865
866 static FIO_WAIT_FUNCTION(zt_wait)
867 {
868 int32_t inflags = 0;
869 int result;
870 struct pollfd pfds[1];
871
872 if (*flags & FTDM_READ) {
873 inflags |= POLLIN;
874 }
875
876 if (*flags & FTDM_WRITE) {
877 inflags |= POLLOUT;
878 }
879
880 if (*flags & FTDM_EVENTS) {
881 inflags |= POLLPRI;
882 }
883
884
885 memset(&pfds[0], 0, sizeof(pfds[0]));
886 pfds[0].fd = ftdmchan->sockfd;
887 pfds[0].events = inflags;
888 result = poll(pfds, 1, to);
889 *flags = 0;
890
891 if (pfds[0].revents & POLLERR) {
892 result = -1;
893 }
894
895 if (result > 0) {
896 inflags = pfds[0].revents;
897 }
898
899 *flags = FTDM_NO_FLAGS;
900
901 if (result < 0){
902 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Poll failed");
903 return FTDM_FAIL;
904 }
905
906 if (result == 0) {
907 return FTDM_TIMEOUT;
908 }
909
910 if (inflags & POLLIN) {
911 *flags |= FTDM_READ;
912 }
913
914 if (inflags & POLLOUT) {
915 *flags |= FTDM_WRITE;
916 }
917
918 if (inflags & POLLPRI) {
919 *flags |= FTDM_EVENTS;
920 }
921
922 return FTDM_SUCCESS;
923
924 }
925
926
927
928
929
930
931
932 FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event)
933 {
934 struct pollfd pfds[FTDM_MAX_CHANNELS_SPAN];
935 uint32_t i, j = 0, k = 0;
936 int r;
937
938 for(i = 1; i <= span->chan_count; i++) {
939 memset(&pfds[j], 0, sizeof(pfds[j]));
940 pfds[j].fd = span->channels[i]->sockfd;
941 pfds[j].events = POLLPRI;
942 j++;
943 }
944
945 r = poll(pfds, j, ms);
946
947 if (r == 0) {
948 return FTDM_TIMEOUT;
949 } else if (r < 0 || (pfds[i-1].revents & POLLERR)) {
950 snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
951 return FTDM_FAIL;
952 }
953
954 for(i = 1; i <= span->chan_count; i++) {
955 if (pfds[i-1].revents & POLLPRI) {
956 ftdm_set_flag(span->channels[i], FTDM_CHANNEL_EVENT);
957 span->channels[i]->last_event_time = ftdm_current_time_in_ms();
958 k++;
959 }
960 }
961
962 if (!k) {
963 snprintf(span->last_error, sizeof(span->last_error), "no matching descriptor");
964 }
965
966 return k ? FTDM_SUCCESS : FTDM_FAIL;
967 }
968
969
970
971
972
973
974
975 FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
976 {
977 uint32_t i, event_id = FTDM_OOB_INVALID;
978 zt_event_t zt_event_id = 0;
979
980 for(i = 1; i <= span->chan_count; i++) {
981 if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
982 ftdm_clear_flag(span->channels[i], FTDM_CHANNEL_EVENT);
983 if (ioctl(span->channels[i]->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
984 snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
985 return FTDM_FAIL;
986 }
987
988 switch(zt_event_id) {
989 case ZT_EVENT_RINGEROFF:
990 {
991 return FTDM_FAIL;
992 }
993 break;
994 case ZT_EVENT_RINGERON:
995 {
996 return FTDM_FAIL;
997 }
998 break;
999 case ZT_EVENT_RINGBEGIN:
1000 {
1001 event_id = FTDM_OOB_RING_START;
1002 }
1003 break;
1004 case ZT_EVENT_ONHOOK:
1005 {
1006 event_id = FTDM_OOB_ONHOOK;
1007 }
1008 break;
1009 case ZT_EVENT_WINKFLASH:
1010 {
1011 if (span->channels[i]->state == FTDM_CHANNEL_STATE_DOWN || span->channels[i]->state == FTDM_CHANNEL_STATE_DIALING) {
1012 event_id = FTDM_OOB_WINK;
1013 } else {
1014 event_id = FTDM_OOB_FLASH;
1015 }
1016 }
1017 break;
1018 case ZT_EVENT_RINGOFFHOOK:
1019 {
1020 if (span->channels[i]->type == FTDM_CHAN_TYPE_FXS || (span->channels[i]->type == FTDM_CHAN_TYPE_EM && span->channels[i]->state != FTDM_CHANNEL_STATE_UP)) {
1021 ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK);
1022 event_id = FTDM_OOB_OFFHOOK;
1023 } else if (span->channels[i]->type == FTDM_CHAN_TYPE_FXO) {
1024 event_id = FTDM_OOB_RING_START;
1025 } else {
1026 event_id = FTDM_OOB_NOOP;
1027 }
1028 }
1029 break;
1030 case ZT_EVENT_ALARM:
1031 {
1032 event_id = FTDM_OOB_ALARM_TRAP;
1033 }
1034 break;
1035 case ZT_EVENT_NOALARM:
1036 {
1037 event_id = FTDM_OOB_ALARM_CLEAR;
1038 }
1039 break;
1040 case ZT_EVENT_BITSCHANGED:
1041 {
1042 event_id = FTDM_OOB_CAS_BITS_CHANGE;
1043 int bits = 0;
1044 int err = ioctl(span->channels[i]->sockfd, codes.GETRXBITS, &bits);
1045 if (err) {
1046 return FTDM_FAIL;
1047 }
1048 span->channels[i]->rx_cas_bits = bits;
1049 }
1050 break;
1051 default:
1052 {
1053 ftdm_log(FTDM_LOG_WARNING, "Unhandled event %d for %d:%d\n", zt_event_id, span->span_id, i);
1054 event_id = FTDM_OOB_INVALID;
1055 }
1056 break;
1057 }
1058
1059 span->channels[i]->last_event_time = 0;
1060 span->event_header.e_type = FTDM_EVENT_OOB;
1061 span->event_header.enum_id = event_id;
1062 span->event_header.channel = span->channels[i];
1063 *event = &span->event_header;
1064 return FTDM_SUCCESS;
1065 }
1066 }
1067
1068 return FTDM_FAIL;
1069
1070 }
1071
1072
1073
1074
1075
1076
1077
1078
1079 static FIO_READ_FUNCTION(zt_read)
1080 {
1081 ftdm_ssize_t r = 0;
1082 int errs = 0;
1083
1084 while (errs++ < 30) {
1085 if ((r = read(ftdmchan->sockfd, data, *datalen)) > 0) {
1086 break;
1087 }
1088 ftdm_sleep(10);
1089 if (r == 0) {
1090 errs--;
1091 }
1092 }
1093
1094 if (r > 0) {
1095 *datalen = r;
1096 if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
1097 *datalen -= 2;
1098 }
1099 return FTDM_SUCCESS;
1100 }
1101
1102 return r == 0 ? FTDM_TIMEOUT : FTDM_FAIL;
1103 }
1104
1105
1106
1107
1108
1109
1110
1111
1112 static FIO_WRITE_FUNCTION(zt_write)
1113 {
1114 ftdm_ssize_t w = 0;
1115 ftdm_size_t bytes = *datalen;
1116
1117 if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
1118 memset(data+bytes, 0, 2);
1119 bytes += 2;
1120 }
1121
1122 w = write(ftdmchan->sockfd, data, bytes);
1123
1124 if (w >= 0) {
1125 *datalen = w;
1126 return FTDM_SUCCESS;
1127 }
1128
1129 return FTDM_FAIL;
1130 }
1131
1132
1133
1134
1135
1136
1137 static FIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy)
1138 {
1139 close(ftdmchan->sockfd);
1140 ftdmchan->sockfd = ZT_INVALID_SOCKET;
1141
1142 return FTDM_SUCCESS;
1143 }
1144
1145
1146
1147
1148 static ftdm_io_interface_t zt_interface;
1149
1150
1151
1152
1153
1154
1155 static FIO_IO_LOAD_FUNCTION(zt_init)
1156 {
1157 assert(fio != NULL);
1158 struct stat statbuf;
1159 memset(&zt_interface, 0, sizeof(zt_interface));
1160 memset(&zt_globals, 0, sizeof(zt_globals));
1161
1162 if (!stat(zt_ctlpath, &statbuf)) {
1163 ftdm_log(FTDM_LOG_NOTICE, "Using Zaptel control device\n");
1164 ctlpath = zt_ctlpath;
1165 chanpath = zt_chanpath;
1166 memcpy(&codes, &zt_ioctl_codes, sizeof(codes));
1167 } else if (!stat(dahdi_ctlpath, &statbuf)) {
1168 ftdm_log(FTDM_LOG_NOTICE, "Using DAHDI control device\n");
1169 ctlpath = dahdi_ctlpath;
1170 chanpath = dahdi_chanpath;
1171 memcpy(&codes, &dahdi_ioctl_codes, sizeof(codes));
1172 } else {
1173 ftdm_log(FTDM_LOG_ERROR, "No DAHDI or Zap control device found in /dev/\n");
1174 return FTDM_FAIL;
1175 }
1176 if ((CONTROL_FD = open(ctlpath, O_RDWR)) < 0) {
1177 ftdm_log(FTDM_LOG_ERROR, "Cannot open control device %s: %s\n", ctlpath, strerror(errno));
1178 return FTDM_FAIL;
1179 }
1180
1181 zt_globals.codec_ms = 20;
1182 zt_globals.wink_ms = 150;
1183 zt_globals.flash_ms = 750;
1184 zt_globals.eclevel = 0;
1185 zt_globals.etlevel = 0;
1186
1187 zt_interface.name = "zt";
1188 zt_interface.configure = zt_configure;
1189 zt_interface.configure_span = zt_configure_span;
1190 zt_interface.open = zt_open;
1191 zt_interface.close = zt_close;
1192 zt_interface.command = zt_command;
1193 zt_interface.wait = zt_wait;
1194 zt_interface.read = zt_read;
1195 zt_interface.write = zt_write;
1196 zt_interface.poll_event = zt_poll_event;
1197 zt_interface.next_event = zt_next_event;
1198 zt_interface.channel_destroy = zt_channel_destroy;
1199 zt_interface.get_alarms = zt_get_alarms;
1200 *fio = &zt_interface;
1201
1202 return FTDM_SUCCESS;
1203 }
1204
1205
1206
1207
1208
1209 static FIO_IO_UNLOAD_FUNCTION(zt_destroy)
1210 {
1211 close(CONTROL_FD);
1212 memset(&zt_interface, 0, sizeof(zt_interface));
1213 return FTDM_SUCCESS;
1214 }
1215
1216
1217
1218
1219 ftdm_module_t ftdm_module = {
1220 "zt",
1221 zt_init,
1222 zt_destroy,
1223 };
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234