Wed Jan 8 2020 09:49:49

Asterisk developer's documentation


res_adsi.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * Includes code and algorithms from the Zapata library.
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20 
21 /*! \file
22  *
23  * \brief ADSI support
24  *
25  * \author Mark Spencer <markster@digium.com>
26  *
27  * \note this module is required by app_voicemail and app_getcpeid
28  * \todo Move app_getcpeid into this module
29  * \todo Create a core layer so that app_voicemail does not require
30  * res_adsi to load
31  */
32 
33 /*** MODULEINFO
34  <support_level>core</support_level>
35  ***/
36 
37 #include "asterisk.h"
38 
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369323 $")
40 
41 #include <time.h>
42 #include <math.h>
43 
44 #include "asterisk/ulaw.h"
45 #include "asterisk/alaw.h"
46 #include "asterisk/callerid.h"
47 #include "asterisk/fskmodem.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/module.h"
50 #include "asterisk/config.h"
51 #include "asterisk/file.h"
52 #include "asterisk/adsi.h"
53 
54 #define DEFAULT_ADSI_MAX_RETRIES 3
55 
56 #define ADSI_MAX_INTRO 20
57 #define ADSI_MAX_SPEED_DIAL 6
58 
59 #define ADSI_FLAG_DATAMODE (1 << 8)
60 
62 
63 /* Asterisk ADSI button definitions */
64 #define ADSI_SPEED_DIAL 10 /* 10-15 are reserved for speed dial */
65 
66 static char intro[ADSI_MAX_INTRO][20];
67 static int aligns[ADSI_MAX_INTRO];
68 
69 #define SPEEDDIAL_MAX_LEN 20
71 
72 static int alignment = 0;
73 
74 static int adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version);
75 static int adsi_end_download(struct ast_channel *chan);
76 static int adsi_channel_restore(struct ast_channel *chan);
77 static int adsi_print(struct ast_channel *chan, char **lines, int *align, int voice);
78 static int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data);
79 static int adsi_unload_session(struct ast_channel *chan);
80 static int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype);
81 static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait);
82 static int adsi_read_encoded_dtmf(struct ast_channel *chan, unsigned char *buf, int maxlen);
83 static int adsi_connect_session(unsigned char *buf, unsigned char *fdn, int ver);
84 static int adsi_query_cpeid(unsigned char *buf);
85 static int adsi_query_cpeinfo(unsigned char *buf);
86 static int adsi_get_cpeid(struct ast_channel *chan, unsigned char *cpeid, int voice);
87 static int adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice);
88 static int adsi_download_connect(unsigned char *buf, char *service, unsigned char *fdn, unsigned char *sec, int ver);
89 static int adsi_disconnect_session(unsigned char *buf);
90 static int adsi_download_disconnect(unsigned char *buf);
91 static int adsi_data_mode(unsigned char *buf);
92 static int adsi_clear_soft_keys(unsigned char *buf);
93 static int adsi_clear_screen(unsigned char *buf);
94 static int adsi_voice_mode(unsigned char *buf, int when);
95 static int adsi_available(struct ast_channel *chan);
96 static int adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2);
97 static int adsi_set_line(unsigned char *buf, int page, int line);
98 static int adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data);
99 static int adsi_set_keys(unsigned char *buf, unsigned char *keys);
100 static int adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just);
101 static int adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2);
102 
103 static int adsi_generate(unsigned char *buf, int msgtype, unsigned char *msg, int msglen, int msgnum, int last, format_t codec)
104 {
105  int sum, x, bytes = 0;
106  /* Initial carrier (imaginary) */
107  float cr = 1.0, ci = 0.0, scont = 0.0;
108 
109  if (msglen > 255) {
110  msglen = 255;
111  }
112 
113  /* If first message, Send 150ms of MARK's */
114  if (msgnum == 1) {
115  for (x = 0; x < 150; x++) { /* was 150 */
117  }
118  }
119 
120  /* Put message type */
121  PUT_CLID(msgtype);
122  sum = msgtype;
123 
124  /* Put message length (plus one for the message number) */
125  PUT_CLID(msglen + 1);
126  sum += msglen + 1;
127 
128  /* Put message number */
129  PUT_CLID(msgnum);
130  sum += msgnum;
131 
132  /* Put actual message */
133  for (x = 0; x < msglen; x++) {
134  PUT_CLID(msg[x]);
135  sum += msg[x];
136  }
137 
138  /* Put 2's compliment of sum */
139  PUT_CLID(256-(sum & 0xff));
140 
141 #if 0
142  if (last) {
143  /* Put trailing marks */
144  for (x = 0; x < 50; x++) {
146  }
147  }
148 #endif
149  return bytes;
150 
151 }
152 
153 static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remain)
154 {
155  /* Sends carefully on a full duplex channel by using reading for
156  timing */
157  struct ast_frame *inf, outf;
158  int amt;
159 
160  /* Zero out our outgoing frame */
161  memset(&outf, 0, sizeof(outf));
162 
163  if (remain && *remain) {
164  amt = len;
165 
166  /* Send remainder if provided */
167  if (amt > *remain) {
168  amt = *remain;
169  } else {
170  *remain = *remain - amt;
171  }
172  outf.frametype = AST_FRAME_VOICE;
174  outf.data.ptr = buf;
175  outf.datalen = amt;
176  outf.samples = amt;
177  if (ast_write(chan, &outf)) {
178  ast_log(LOG_WARNING, "Failed to carefully write frame\n");
179  return -1;
180  }
181  /* Update pointers and lengths */
182  buf += amt;
183  len -= amt;
184  }
185 
186  while (len) {
187  amt = len;
188  /* If we don't get anything at all back in a second, forget
189  about it */
190  if (ast_waitfor(chan, 1000) < 1) {
191  return -1;
192  }
193  /* Detect hangup */
194  if (!(inf = ast_read(chan))) {
195  return -1;
196  }
197 
198  /* Drop any frames that are not voice */
199  if (inf->frametype != AST_FRAME_VOICE) {
200  ast_frfree(inf);
201  continue;
202  }
203 
204  if (inf->subclass.codec != AST_FORMAT_ULAW) {
205  ast_log(LOG_WARNING, "Channel not in ulaw?\n");
206  ast_frfree(inf);
207  return -1;
208  }
209  /* Send no more than they sent us */
210  if (amt > inf->datalen) {
211  amt = inf->datalen;
212  } else if (remain) {
213  *remain = inf->datalen - amt;
214  }
215  outf.frametype = AST_FRAME_VOICE;
217  outf.data.ptr = buf;
218  outf.datalen = amt;
219  outf.samples = amt;
220  if (ast_write(chan, &outf)) {
221  ast_log(LOG_WARNING, "Failed to carefully write frame\n");
222  ast_frfree(inf);
223  return -1;
224  }
225  /* Update pointers and lengths */
226  buf += amt;
227  len -= amt;
228  ast_frfree(inf);
229  }
230  return 0;
231 }
232 
233 static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype)
234 {
235  /* msglen must be no more than 256 bits, each */
236  unsigned char buf[24000 * 5];
237  int pos = 0, res, x, start = 0, retries = 0, waittime, rem = 0, def;
238  char ack[3];
239  struct ast_frame *f;
240 
241  if (chan->adsicpe == AST_ADSI_UNAVAILABLE) {
242  /* Don't bother if we know they don't support ADSI */
243  errno = ENOSYS;
244  return -1;
245  }
246 
247  while (retries < maxretries) {
248  if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) {
249  /* Generate CAS (no SAS) */
250  ast_gen_cas(buf, 0, 680, AST_FORMAT_ULAW);
251 
252  /* Send CAS */
253  if (adsi_careful_send(chan, buf, 680, NULL)) {
254  ast_log(LOG_WARNING, "Unable to send CAS\n");
255  }
256 
257  /* Wait For DTMF result */
258  waittime = 500;
259  for (;;) {
260  if (((res = ast_waitfor(chan, waittime)) < 1)) {
261  /* Didn't get back DTMF A in time */
262  ast_debug(1, "No ADSI CPE detected (%d)\n", res);
263  if (!chan->adsicpe) {
265  }
266  errno = ENOSYS;
267  return -1;
268  }
269  waittime = res;
270  if (!(f = ast_read(chan))) {
271  ast_debug(1, "Hangup in ADSI\n");
272  return -1;
273  }
274  if (f->frametype == AST_FRAME_DTMF) {
275  if (f->subclass.integer == 'A') {
276  /* Okay, this is an ADSI CPE. Note this for future reference, too */
277  if (!chan->adsicpe) {
278  chan->adsicpe = AST_ADSI_AVAILABLE;
279  }
280  break;
281  } else {
282  if (f->subclass.integer == 'D') {
283  ast_debug(1, "Off-hook capable CPE only, not ADSI\n");
284  } else {
285  ast_log(LOG_WARNING, "Unknown ADSI response '%c'\n", f->subclass.integer);
286  }
287  if (!chan->adsicpe) {
289  }
290  errno = ENOSYS;
291  ast_frfree(f);
292  return -1;
293  }
294  }
295  ast_frfree(f);
296  }
297 
298  ast_debug(1, "ADSI Compatible CPE Detected\n");
299  } else {
300  ast_debug(1, "Already in data mode\n");
301  }
302 
303  x = 0;
304  pos = 0;
305 #if 1
306  def= ast_channel_defer_dtmf(chan);
307 #endif
308  while ((x < 6) && msg[x]) {
309  if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], AST_FORMAT_ULAW)) < 0) {
310  ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name);
311  return -1;
312  }
313  ast_debug(1, "Message %d, of %d input bytes, %d output bytes\n", x + 1, msglen[x], res);
314  pos += res;
315  x++;
316  }
317 
318 
319  rem = 0;
320  res = adsi_careful_send(chan, buf, pos, &rem);
321  if (!def) {
323  }
324  if (res) {
325  return -1;
326  }
327 
328  ast_debug(1, "Sent total spill of %d bytes\n", pos);
329 
330  memset(ack, 0, sizeof(ack));
331  /* Get real result and check for hangup */
332  if ((res = ast_readstring(chan, ack, 2, 1000, 1000, "")) < 0) {
333  return -1;
334  }
335  if (ack[0] == 'D') {
336  ast_debug(1, "Acked up to message %d\n", atoi(ack + 1)); start += atoi(ack + 1);
337  if (start >= x) {
338  break;
339  } else {
340  retries++;
341  ast_debug(1, "Retransmitting (%d), from %d\n", retries, start + 1);
342  }
343  } else {
344  retries++;
345  ast_log(LOG_WARNING, "Unexpected response to ack: %s (retry %d)\n", ack, retries);
346  }
347  }
348  if (retries >= maxretries) {
349  ast_log(LOG_WARNING, "Maximum ADSI Retries (%d) exceeded\n", maxretries);
350  errno = ETIMEDOUT;
351  return -1;
352  }
353  return 0;
354 }
355 
356 static int adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
357 {
358  int bytes = 0;
359  unsigned char buf[256];
360  char ack[2];
361 
362  /* Setup the resident soft key stuff, a piece at a time */
363  /* Upload what scripts we can for voicemail ahead of time */
364  bytes += adsi_download_connect(buf + bytes, service, fdn, sec, version);
365  if (adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0)) {
366  return -1;
367  }
368  if (ast_readstring(chan, ack, 1, 10000, 10000, "")) {
369  return -1;
370  }
371  if (ack[0] == 'B') {
372  return 0;
373  }
374  ast_debug(1, "Download was denied by CPE\n");
375  return -1;
376 }
377 
378 static int adsi_end_download(struct ast_channel *chan)
379 {
380  int bytes = 0;
381  unsigned char buf[256];
382 
383  /* Setup the resident soft key stuff, a piece at a time */
384  /* Upload what scripts we can for voicemail ahead of time */
385  bytes += adsi_download_disconnect(buf + bytes);
386  if (adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0)) {
387  return -1;
388  }
389  return 0;
390 }
391 
392 static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
393 {
394  unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
395  int msglens[5], msgtypes[5], newdatamode = (chan->adsicpe & ADSI_FLAG_DATAMODE), res, x, writeformat = chan->writeformat, readformat = chan->readformat, waitforswitch = 0;
396 
397  for (x = 0; x < msglen; x += (msg[x+1]+2)) {
398  if (msg[x] == ADSI_SWITCH_TO_DATA) {
399  ast_debug(1, "Switch to data is sent!\n");
400  waitforswitch++;
401  newdatamode = ADSI_FLAG_DATAMODE;
402  }
403 
404  if (msg[x] == ADSI_SWITCH_TO_VOICE) {
405  ast_debug(1, "Switch to voice is sent!\n");
406  waitforswitch++;
407  newdatamode = 0;
408  }
409  }
410  msgs[0] = msg;
411 
412  msglens[0] = msglen;
413  msgtypes[0] = msgtype;
414 
415  if (msglen > 253) {
416  ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
417  return -1;
418  }
419 
420  ast_stopstream(chan);
421 
423  ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
424  return -1;
425  }
426 
428  ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
429  if (writeformat) {
430  if (ast_set_write_format(chan, writeformat)) {
431  ast_log(LOG_WARNING, "Unable to restore write format to %d\n", writeformat);
432  }
433  }
434  return -1;
435  }
436  res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);
437 
438  if (dowait) {
439  ast_debug(1, "Wait for switch is '%d'\n", waitforswitch);
440  while (waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) {
441  res = 0;
442  ast_debug(1, "Waiting for 'B'...\n");
443  }
444  }
445 
446  if (!res) {
447  chan->adsicpe = (chan->adsicpe & ~ADSI_FLAG_DATAMODE) | newdatamode;
448  }
449 
450  if (writeformat) {
451  ast_set_write_format(chan, writeformat);
452  }
453  if (readformat) {
454  ast_set_read_format(chan, readformat);
455  }
456 
457  if (!res) {
458  res = ast_safe_sleep(chan, 100 );
459  }
460  return res;
461 }
462 
463 static int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
464 {
465  return adsi_transmit_message_full(chan, msg, msglen, msgtype, 1);
466 }
467 
468 static inline int ccopy(unsigned char *dst, const unsigned char *src, int max)
469 {
470  int x = 0;
471  /* Carefully copy the requested data */
472  while ((x < max) && src[x] && (src[x] != 0xff)) {
473  dst[x] = src[x];
474  x++;
475  }
476  return x;
477 }
478 
479 static int adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
480 {
481  int bytes = 0;
482 
483  /* Abort if invalid key specified */
484  if ((key < 2) || (key > 33)) {
485  return -1;
486  }
487 
488  buf[bytes++] = ADSI_LOAD_SOFTKEY;
489  /* Reserve for length */
490  bytes++;
491  /* Which key */
492  buf[bytes++] = key;
493 
494  /* Carefully copy long label */
495  bytes += ccopy(buf + bytes, (const unsigned char *)llabel, 18);
496 
497  /* Place delimiter */
498  buf[bytes++] = 0xff;
499 
500  /* Short label */
501  bytes += ccopy(buf + bytes, (const unsigned char *)slabel, 7);
502 
503 
504  /* If specified, copy return string */
505  if (ret) {
506  /* Place delimiter */
507  buf[bytes++] = 0xff;
508  if (data) {
509  buf[bytes++] = ADSI_SWITCH_TO_DATA2;
510  }
511  /* Carefully copy return string */
512  bytes += ccopy(buf + bytes, (const unsigned char *)ret, 20);
513 
514  }
515  /* Replace parameter length */
516  buf[1] = bytes - 2;
517  return bytes;
518 }
519 
520 static int adsi_connect_session(unsigned char *buf, unsigned char *fdn, int ver)
521 {
522  int bytes = 0, x;
523 
524  /* Message type */
525  buf[bytes++] = ADSI_CONNECT_SESSION;
526 
527  /* Reserve space for length */
528  bytes++;
529 
530  if (fdn) {
531  for (x = 0; x < 4; x++) {
532  buf[bytes++] = fdn[x];
533  }
534  if (ver > -1) {
535  buf[bytes++] = ver & 0xff;
536  }
537  }
538 
539  buf[1] = bytes - 2;
540  return bytes;
541 
542 }
543 
544 static int adsi_download_connect(unsigned char *buf, char *service, unsigned char *fdn, unsigned char *sec, int ver)
545 {
546  int bytes = 0, x;
547 
548  /* Message type */
549  buf[bytes++] = ADSI_DOWNLOAD_CONNECT;
550 
551  /* Reserve space for length */
552  bytes++;
553 
554  /* Primary column */
555  bytes+= ccopy(buf + bytes, (unsigned char *)service, 18);
556 
557  /* Delimiter */
558  buf[bytes++] = 0xff;
559 
560  for (x = 0; x < 4; x++) {
561  buf[bytes++] = fdn[x];
562  }
563 
564  for (x = 0; x < 4; x++) {
565  buf[bytes++] = sec[x];
566  }
567 
568  buf[bytes++] = ver & 0xff;
569 
570  buf[1] = bytes - 2;
571 
572  return bytes;
573 
574 }
575 
576 static int adsi_disconnect_session(unsigned char *buf)
577 {
578  int bytes = 0;
579 
580  /* Message type */
581  buf[bytes++] = ADSI_DISC_SESSION;
582 
583  /* Reserve space for length */
584  bytes++;
585 
586  buf[1] = bytes - 2;
587  return bytes;
588 
589 }
590 
591 static int adsi_query_cpeid(unsigned char *buf)
592 {
593  int bytes = 0;
594  buf[bytes++] = ADSI_QUERY_CPEID;
595  /* Reserve space for length */
596  bytes++;
597  buf[1] = bytes - 2;
598  return bytes;
599 }
600 
601 static int adsi_query_cpeinfo(unsigned char *buf)
602 {
603  int bytes = 0;
604  buf[bytes++] = ADSI_QUERY_CONFIG;
605  /* Reserve space for length */
606  bytes++;
607  buf[1] = bytes - 2;
608  return bytes;
609 }
610 
611 static int adsi_read_encoded_dtmf(struct ast_channel *chan, unsigned char *buf, int maxlen)
612 {
613  int bytes = 0, res, gotstar = 0, pos = 0;
614  unsigned char current = 0;
615 
616  memset(buf, 0, maxlen);
617 
618  while (bytes <= maxlen) {
619  /* Wait up to a second for a digit */
620  if (!(res = ast_waitfordigit(chan, 1000))) {
621  break;
622  }
623  if (res == '*') {
624  gotstar = 1;
625  continue;
626  }
627  /* Ignore anything other than a digit */
628  if ((res < '0') || (res > '9')) {
629  continue;
630  }
631  res -= '0';
632  if (gotstar) {
633  res += 9;
634  }
635  if (pos) {
636  pos = 0;
637  buf[bytes++] = (res << 4) | current;
638  } else {
639  pos = 1;
640  current = res;
641  }
642  gotstar = 0;
643  }
644 
645  return bytes;
646 }
647 
648 static int adsi_get_cpeid(struct ast_channel *chan, unsigned char *cpeid, int voice)
649 {
650  unsigned char buf[256] = "";
651  int bytes = 0, res;
652 
653  bytes += adsi_data_mode(buf);
654  adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
655 
656  bytes = 0;
657  bytes += adsi_query_cpeid(buf);
658  adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
659 
660  /* Get response */
661  res = adsi_read_encoded_dtmf(chan, cpeid, 4);
662  if (res != 4) {
663  ast_log(LOG_WARNING, "Got %d bytes back of encoded DTMF, expecting 4\n", res);
664  res = 0;
665  } else {
666  res = 1;
667  }
668 
669  if (voice) {
670  bytes = 0;
671  bytes += adsi_voice_mode(buf, 0);
672  adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
673  /* Ignore the resulting DTMF B announcing it's in voice mode */
674  ast_waitfordigit(chan, 1000);
675  }
676  return res;
677 }
678 
679 static int adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice)
680 {
681  unsigned char buf[256] = "";
682  int bytes = 0, res;
683 
684  bytes += adsi_data_mode(buf);
685  adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
686 
687  bytes = 0;
688  bytes += adsi_query_cpeinfo(buf);
689  adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
690 
691  /* Get width */
692  if ((res = ast_readstring(chan, (char *) buf, 2, 1000, 500, "")) < 0) {
693  return res;
694  }
695  if (strlen((char *) buf) != 2) {
696  ast_log(LOG_WARNING, "Got %d bytes of width, expecting 2\n", res);
697  res = 0;
698  } else {
699  res = 1;
700  }
701  if (width) {
702  *width = atoi((char *) buf);
703  }
704  /* Get height */
705  memset(buf, 0, sizeof(buf));
706  if (res) {
707  if ((res = ast_readstring(chan, (char *) buf, 2, 1000, 500, "")) < 0) {
708  return res;
709  }
710  if (strlen((char *) buf) != 2) {
711  ast_log(LOG_WARNING, "Got %d bytes of height, expecting 2\n", res);
712  res = 0;
713  } else {
714  res = 1;
715  }
716  if (height) {
717  *height = atoi((char *) buf);
718  }
719  }
720  /* Get buttons */
721  memset(buf, 0, sizeof(buf));
722  if (res) {
723  if ((res = ast_readstring(chan, (char *) buf, 1, 1000, 500, "")) < 0) {
724  return res;
725  }
726  if (strlen((char *) buf) != 1) {
727  ast_log(LOG_WARNING, "Got %d bytes of buttons, expecting 1\n", res);
728  res = 0;
729  } else {
730  res = 1;
731  }
732  if (buttons) {
733  *buttons = atoi((char *) buf);
734  }
735  }
736  if (voice) {
737  bytes = 0;
738  bytes += adsi_voice_mode(buf, 0);
739  adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
740  /* Ignore the resulting DTMF B announcing it's in voice mode */
741  ast_waitfordigit(chan, 1000);
742  }
743  return res;
744 }
745 
746 static int adsi_data_mode(unsigned char *buf)
747 {
748  int bytes = 0;
749 
750  /* Message type */
751  buf[bytes++] = ADSI_SWITCH_TO_DATA;
752 
753  /* Reserve space for length */
754  bytes++;
755 
756  buf[1] = bytes - 2;
757  return bytes;
758 
759 }
760 
761 static int adsi_clear_soft_keys(unsigned char *buf)
762 {
763  int bytes = 0;
764 
765  /* Message type */
766  buf[bytes++] = ADSI_CLEAR_SOFTKEY;
767 
768  /* Reserve space for length */
769  bytes++;
770 
771  buf[1] = bytes - 2;
772  return bytes;
773 
774 }
775 
776 static int adsi_clear_screen(unsigned char *buf)
777 {
778  int bytes = 0;
779 
780  /* Message type */
781  buf[bytes++] = ADSI_CLEAR_SCREEN;
782 
783  /* Reserve space for length */
784  bytes++;
785 
786  buf[1] = bytes - 2;
787  return bytes;
788 
789 }
790 
791 static int adsi_voice_mode(unsigned char *buf, int when)
792 {
793  int bytes = 0;
794 
795  /* Message type */
796  buf[bytes++] = ADSI_SWITCH_TO_VOICE;
797 
798  /* Reserve space for length */
799  bytes++;
800 
801  buf[bytes++] = when & 0x7f;
802 
803  buf[1] = bytes - 2;
804  return bytes;
805 
806 }
807 
808 static int adsi_available(struct ast_channel *chan)
809 {
810  int cpe = chan->adsicpe & 0xff;
811  if ((cpe == AST_ADSI_AVAILABLE) ||
812  (cpe == AST_ADSI_UNKNOWN)) {
813  return 1;
814  }
815  return 0;
816 }
817 
818 static int adsi_download_disconnect(unsigned char *buf)
819 {
820  int bytes = 0;
821 
822  /* Message type */
823  buf[bytes++] = ADSI_DOWNLOAD_DISC;
824 
825  /* Reserve space for length */
826  bytes++;
827 
828  buf[1] = bytes - 2;
829  return bytes;
830 
831 }
832 
833 static int adsi_display(unsigned char *buf, int page, int line, int just, int wrap,
834  char *col1, char *col2)
835 {
836  int bytes = 0;
837 
838  /* Sanity check line number */
839 
840  if (page) {
841  if (line > 4) return -1;
842  } else {
843  if (line > 33) return -1;
844  }
845 
846  if (line < 1) {
847  return -1;
848  }
849  /* Parameter type */
850  buf[bytes++] = ADSI_LOAD_VIRTUAL_DISP;
851 
852  /* Reserve space for size */
853  bytes++;
854 
855  /* Page and wrap indicator */
856  buf[bytes++] = ((page & 0x1) << 7) | ((wrap & 0x1) << 6) | (line & 0x3f);
857 
858  /* Justification */
859  buf[bytes++] = (just & 0x3) << 5;
860 
861  /* Omit highlight mode definition */
862  buf[bytes++] = 0xff;
863 
864  /* Primary column */
865  bytes+= ccopy(buf + bytes, (unsigned char *)col1, 20);
866 
867  /* Delimiter */
868  buf[bytes++] = 0xff;
869 
870  /* Secondary column */
871  bytes += ccopy(buf + bytes, (unsigned char *)col2, 20);
872 
873  /* Update length */
874  buf[1] = bytes - 2;
875 
876  return bytes;
877 
878 }
879 
880 static int adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
881 {
882  int bytes = 0;
883 
884  if (page) {
885  if (line > 4) return -1;
886  } else {
887  if (line > 33) return -1;
888  }
889 
890  if (line < 1) {
891  return -1;
892  }
893 
894  buf[bytes++] = ADSI_INPUT_CONTROL;
895  bytes++;
896  buf[bytes++] = ((page & 1) << 7) | (line & 0x3f);
897  buf[bytes++] = ((display & 1) << 7) | ((just & 0x3) << 4) | (format & 0x7);
898 
899  buf[1] = bytes - 2;
900  return bytes;
901 }
902 
903 static int adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
904 {
905  int bytes = 0;
906 
907  if (ast_strlen_zero((char *) format1)) {
908  return -1;
909  }
910 
911  buf[bytes++] = ADSI_INPUT_FORMAT;
912  bytes++;
913  buf[bytes++] = ((dir & 1) << 7) | ((wrap & 1) << 6) | (num & 0x7);
914  bytes += ccopy(buf + bytes, (unsigned char *) format1, 20);
915  buf[bytes++] = 0xff;
916  if (!ast_strlen_zero(format2)) {
917  bytes += ccopy(buf + bytes, (unsigned char *) format2, 20);
918  }
919  buf[1] = bytes - 2;
920  return bytes;
921 }
922 
923 static int adsi_set_keys(unsigned char *buf, unsigned char *keys)
924 {
925  int bytes = 0, x;
926 
927  /* Message type */
928  buf[bytes++] = ADSI_INIT_SOFTKEY_LINE;
929  /* Space for size */
930  bytes++;
931  /* Key definitions */
932  for (x = 0; x < 6; x++) {
933  buf[bytes++] = (keys[x] & 0x3f) ? keys[x] : (keys[x] | 0x1);
934  }
935  buf[1] = bytes - 2;
936  return bytes;
937 }
938 
939 static int adsi_set_line(unsigned char *buf, int page, int line)
940 {
941  int bytes = 0;
942 
943  /* Sanity check line number */
944 
945  if (page) {
946  if (line > 4) return -1;
947  } else {
948  if (line > 33) return -1;
949  }
950 
951  if (line < 1) {
952  return -1;
953  }
954  /* Parameter type */
955  buf[bytes++] = ADSI_LINE_CONTROL;
956 
957  /* Reserve space for size */
958  bytes++;
959 
960  /* Page and line */
961  buf[bytes++] = ((page & 0x1) << 7) | (line & 0x3f);
962 
963  buf[1] = bytes - 2;
964  return bytes;
965 }
966 
967 static int total = 0;
968 static int speeds = 0;
969 
970 static int adsi_channel_restore(struct ast_channel *chan)
971 {
972  unsigned char dsp[256] = "", keyd[6] = "";
973  int bytes, x;
974 
975  /* Start with initial display setup */
976  bytes = 0;
977  bytes += adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1);
978 
979  /* Prepare key setup messages */
980 
981  if (speeds) {
982  for (x = 0; x < speeds; x++) {
983  keyd[x] = ADSI_SPEED_DIAL + x;
984  }
985  bytes += adsi_set_keys(dsp + bytes, keyd);
986  }
987  adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0);
988  return 0;
989 
990 }
991 
992 static int adsi_print(struct ast_channel *chan, char **lines, int *alignments, int voice)
993 {
994  unsigned char buf[4096];
995  int bytes = 0, res, x;
996 
997  for (x = 0; lines[x]; x++) {
998  bytes += adsi_display(buf + bytes, ADSI_INFO_PAGE, x+1, alignments[x], 0, lines[x], "");
999  }
1000  bytes += adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
1001  if (voice) {
1002  bytes += adsi_voice_mode(buf + bytes, 0);
1003  }
1004  res = adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
1005  if (voice) {
1006  /* Ignore the resulting DTMF B announcing it's in voice mode */
1007  ast_waitfordigit(chan, 1000);
1008  }
1009  return res;
1010 }
1011 
1012 static int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
1013 {
1014  unsigned char dsp[256] = "";
1015  int bytes = 0, res;
1016  char resp[2];
1017 
1018  /* Connect to session */
1019  bytes += adsi_connect_session(dsp + bytes, app, ver);
1020 
1021  if (data) {
1022  bytes += adsi_data_mode(dsp + bytes);
1023  }
1024 
1025  /* Prepare key setup messages */
1026  if (adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0)) {
1027  return -1;
1028  }
1029  if (app) {
1030  if ((res = ast_readstring(chan, resp, 1, 1200, 1200, "")) < 0) {
1031  return -1;
1032  }
1033  if (res) {
1034  ast_debug(1, "No response from CPE about version. Assuming not there.\n");
1035  return 0;
1036  }
1037  if (!strcmp(resp, "B")) {
1038  ast_debug(1, "CPE has script '%s' version %d already loaded\n", app, ver);
1039  return 1;
1040  } else if (!strcmp(resp, "A")) {
1041  ast_debug(1, "CPE hasn't script '%s' version %d already loaded\n", app, ver);
1042  } else {
1043  ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp);
1044  }
1045  } else
1046  return 1;
1047  return 0;
1048 
1049 }
1050 
1051 static int adsi_unload_session(struct ast_channel *chan)
1052 {
1053  unsigned char dsp[256] = "";
1054  int bytes = 0;
1055 
1056  /* Connect to session */
1057  bytes += adsi_disconnect_session(dsp + bytes);
1058  bytes += adsi_voice_mode(dsp + bytes, 0);
1059 
1060  /* Prepare key setup messages */
1061  if (adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0)) {
1062  return -1;
1063  }
1064 
1065  return 0;
1066 }
1067 
1068 static int str2align(const char *s)
1069 {
1070  if (!strncasecmp(s, "l", 1)) {
1071  return ADSI_JUST_LEFT;
1072  } else if (!strncasecmp(s, "r", 1)) {
1073  return ADSI_JUST_RIGHT;
1074  } else if (!strncasecmp(s, "i", 1)) {
1075  return ADSI_JUST_IND;
1076  } else {
1077  return ADSI_JUST_CENT;
1078  }
1079 }
1080 
1081 static void init_state(void)
1082 {
1083  int x;
1084 
1085  for (x = 0; x < ADSI_MAX_INTRO; x++) {
1086  aligns[x] = ADSI_JUST_CENT;
1087  }
1088  ast_copy_string(intro[0], "Welcome to the", sizeof(intro[0]));
1089  ast_copy_string(intro[1], "Asterisk", sizeof(intro[1]));
1090  ast_copy_string(intro[2], "Open Source PBX", sizeof(intro[2]));
1091  total = 3;
1092  speeds = 0;
1093  for (x = 3; x < ADSI_MAX_INTRO; x++) {
1094  intro[x][0] = '\0';
1095  }
1096  memset(speeddial, 0, sizeof(speeddial));
1097  alignment = ADSI_JUST_CENT;
1098 }
1099 
1100 static void adsi_load(int reload)
1101 {
1102  int x = 0;
1103  struct ast_config *conf = NULL;
1104  struct ast_variable *v;
1105  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1106  char *name, *sname;
1107  init_state();
1108 
1109  conf = ast_config_load("adsi.conf", config_flags);
1111  return;
1112  }
1113  for (v = ast_variable_browse(conf, "intro"); v; v = v->next) {
1114  if (!strcasecmp(v->name, "alignment")) {
1115  alignment = str2align(v->value);
1116  } else if (!strcasecmp(v->name, "greeting")) {
1117  if (x < ADSI_MAX_INTRO) {
1118  aligns[x] = alignment;
1119  ast_copy_string(intro[x], v->value, sizeof(intro[x]));
1120  x++;
1121  }
1122  } else if (!strcasecmp(v->name, "maxretries")) {
1123  if (atoi(v->value) > 0) {
1124  maxretries = atoi(v->value);
1125  }
1126  }
1127  }
1128  if (x) {
1129  total = x;
1130  }
1131 
1132  x = 0;
1133  for (v = ast_variable_browse(conf, "speeddial"); v; v = v->next) {
1134  char buf[3 * SPEEDDIAL_MAX_LEN];
1135  char *stringp = buf;
1136  ast_copy_string(buf, v->value, sizeof(buf));
1137  name = strsep(&stringp, ",");
1138  sname = strsep(&stringp, ",");
1139  if (!sname) {
1140  sname = name;
1141  }
1142  if (x < ADSI_MAX_SPEED_DIAL) {
1143  ast_copy_string(speeddial[x][0], v->name, sizeof(speeddial[x][0]));
1144  ast_copy_string(speeddial[x][1], name, 18);
1145  ast_copy_string(speeddial[x][2], sname, 7);
1146  x++;
1147  }
1148  }
1149  if (x) {
1150  speeds = x;
1151  }
1152  ast_config_destroy(conf);
1153 
1154  return;
1155 }
1156 
1157 static int reload(void)
1158 {
1159  adsi_load(1);
1160  return 0;
1161 }
1162 
1163 static struct adsi_funcs res_adsi_funcs = {
1165  .begin_download = adsi_begin_download,
1166  .end_download = adsi_end_download,
1167  .channel_restore = adsi_channel_restore,
1168  .print = adsi_print,
1169  .load_session = adsi_load_session,
1170  .unload_session = adsi_unload_session,
1171  .transmit_message = adsi_transmit_message,
1172  .transmit_message_full = adsi_transmit_message_full,
1173  .read_encoded_dtmf = adsi_read_encoded_dtmf,
1174  .connect_session = adsi_connect_session,
1175  .query_cpeid = adsi_query_cpeid,
1176  .query_cpeinfo = adsi_query_cpeinfo,
1177  .get_cpeid = adsi_get_cpeid,
1178  .get_cpeinfo = adsi_get_cpeinfo,
1179  .download_connect = adsi_download_connect,
1180  .disconnect_session = adsi_disconnect_session,
1181  .download_disconnect = adsi_download_disconnect,
1182  .data_mode = adsi_data_mode,
1183  .clear_soft_keys = adsi_clear_soft_keys,
1184  .clear_screen = adsi_clear_screen,
1185  .voice_mode = adsi_voice_mode,
1186  .available = adsi_available,
1187  .display = adsi_display,
1188  .set_line = adsi_set_line,
1189  .load_soft_key = adsi_load_soft_key,
1190  .set_keys = adsi_set_keys,
1191  .input_control = adsi_input_control,
1192  .input_format = adsi_input_format,
1193 };
1194 
1195 static int load_module(void)
1196 {
1197  adsi_load(0);
1198  ast_adsi_install_funcs(&res_adsi_funcs);
1199  return AST_MODULE_LOAD_SUCCESS;
1200 }
1201 
1202 static int unload_module(void)
1203 {
1204  /* Can't unload this once we're loaded */
1205  ast_adsi_install_funcs(NULL);
1206  return -1;
1207 }
1208 
1210  .load = load_module,
1211  .unload = unload_module,
1212  .reload = reload,
1213  .load_pri = AST_MODPRI_APP_DEPEND,
1214  );
static int adsi_query_cpeinfo(unsigned char *buf)
Definition: res_adsi.c:601
A-Law to Signed linear conversion.
#define ADSI_JUST_RIGHT
Definition: adsi.h:113
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
union ast_frame_subclass subclass
Definition: frame.h:146
#define ADSI_INFO_PAGE
Definition: adsi.h:106
Main Channel structure associated with a channel.
Definition: channel.h:742
static int adsi_disconnect_session(unsigned char *buf)
Definition: res_adsi.c:576
uint32_t version
Asterisk main include file. File version handling, generic pbx functions.
static int adsi_get_cpeid(struct ast_channel *chan, unsigned char *cpeid, int voice)
Definition: res_adsi.c:648
char * strsep(char **str, const char *delims)
static int load_module(void)
Definition: res_adsi.c:1195
static int adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Definition: res_adsi.c:903
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
format_t writeformat
Definition: channel.h:854
static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype)
Definition: res_adsi.c:233
static int adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice)
Definition: res_adsi.c:679
void * ptr
Definition: frame.h:160
#define ADSI_LOAD_SOFTKEY
Definition: adsi.h:36
#define ADSI_DISC_SESSION
Definition: adsi.h:41
#define ADSI_DOWNLOAD_DISC
Definition: adsi.h:66
static int adsi_clear_soft_keys(unsigned char *buf)
Definition: res_adsi.c:761
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static char intro[ADSI_MAX_INTRO][20]
Definition: res_adsi.c:66
static int adsi_set_keys(unsigned char *buf, unsigned char *keys)
Definition: res_adsi.c:923
static int adsi_clear_screen(unsigned char *buf)
Definition: res_adsi.c:776
#define AST_FRAME_DTMF
Definition: frame.h:128
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static int adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
Definition: res_adsi.c:356
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
static int adsi_print(struct ast_channel *chan, char **lines, int *align, int voice)
Definition: res_adsi.c:992
enum ast_cc_service_type service
Definition: chan_sip.c:821
static void adsi_load(int reload)
Definition: res_adsi.c:1100
Configuration File Parser.
static int adsi_end_download(struct ast_channel *chan)
Definition: res_adsi.c:378
for(;;)
Definition: ast_expr2.c:2460
#define ADSI_JUST_LEFT
Definition: adsi.h:112
static int ccopy(unsigned char *dst, const unsigned char *src, int max)
Definition: res_adsi.c:468
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
#define ADSI_QUERY_CONFIG
Definition: adsi.h:57
format_t codec
Definition: frame.h:137
ADSI Support (built upon Caller*ID)
#define ADSI_FLAG_DATAMODE
Definition: res_adsi.c:59
static int adsi_unload_session(struct ast_channel *chan)
Definition: res_adsi.c:1051
enum ast_channel_adsicpe adsicpe
Definition: channel.h:844
#define DEFAULT_ADSI_MAX_RETRIES
Definition: res_adsi.c:54
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int aligns[ADSI_MAX_INTRO]
Definition: res_adsi.c:67
int ast_channel_defer_dtmf(struct ast_channel *chan)
Defers DTMF so that you only read things like hangups and audio.
Definition: channel.c:1616
#define CONFIG_STATUS_FILEMISSING
Definition: config.h:50
#define AST_ADSI_VERSION
Definition: adsi.h:123
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
u-Law to Signed linear conversion
const char * value
Definition: config.h:79
static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
Definition: res_adsi.c:392
static const char app[]
Definition: app_adsiprog.c:49
General Asterisk PBX channel definitions.
static int adsi_available(struct ast_channel *chan)
Definition: res_adsi.c:808
const char * src
Definition: frame.h:158
void ast_channel_undefer_dtmf(struct ast_channel *chan)
Unset defer DTMF flag on channel.
Definition: channel.c:1628
static int adsi_read_encoded_dtmf(struct ast_channel *chan, unsigned char *buf, int maxlen)
Definition: res_adsi.c:611
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
static int speeds
Definition: res_adsi.c:968
int datalen
Definition: frame.h:148
static int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Definition: res_adsi.c:1012
#define ADSI_LINE_CONTROL
Definition: adsi.h:39
static int alignment
Definition: res_adsi.c:72
#define ADSI_INPUT_FORMAT
Definition: adsi.h:46
const char * name
Definition: config.h:77
#define ADSI_JUST_IND
Definition: adsi.h:115
static int str2align(const char *s)
Definition: res_adsi.c:1068
#define ADSI_DOWNLOAD_CONNECT
Definition: adsi.h:65
static int reload(void)
Definition: res_adsi.c:1157
#define ADSI_LOAD_VIRTUAL_DISP
Definition: adsi.h:38
static int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: res_adsi.c:463
int64_t format_t
Definition: frame_defs.h:32
static int adsi_generate(unsigned char *buf, int msgtype, unsigned char *msg, int msglen, int msgnum, int last, format_t codec)
Definition: res_adsi.c:103
static struct adsi_funcs res_adsi_funcs
Definition: res_adsi.c:1163
#define ADSI_MAX_SPEED_DIAL
Definition: res_adsi.c:57
static int maxretries
Definition: res_adsi.c:61
static int adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Definition: res_adsi.c:833
#define AST_FORMAT_ULAW
Definition: frame.h:246
static int adsi_connect_session(unsigned char *buf, unsigned char *fdn, int ver)
Definition: res_adsi.c:520
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int adsi_channel_restore(struct ast_channel *chan)
Definition: res_adsi.c:970
#define ADSI_CLEAR_SOFTKEY
Definition: adsi.h:44
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ADSI_SPEED_DIAL
Definition: res_adsi.c:64
unsigned int version
Definition: adsi.h:346
#define ADSI_SWITCH_TO_DATA2
Definition: adsi.h:87
static int adsi_data_mode(unsigned char *buf)
Definition: res_adsi.c:746
static int unload_module(void)
Definition: res_adsi.c:1202
int errno
static const char name[]
static int adsi_voice_mode(unsigned char *buf, int when)
Definition: res_adsi.c:791
int ast_gen_cas(unsigned char *outbuf, int sas, int len, format_t codec)
Generate a CAS (CPE Alert Signal) tone for &#39;n&#39; samples.
Definition: callerid.c:262
static int adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Definition: res_adsi.c:479
#define ADSI_SWITCH_TO_VOICE
Definition: adsi.h:43
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
#define ADSI_QUERY_CPEID
Definition: adsi.h:58
#define ADSI_MSG_DOWNLOAD
Definition: adsi.h:33
Structure used to handle boolean flags.
Definition: utils.h:200
void ast_adsi_install_funcs(const struct adsi_funcs *funcs)
Definition: adsi.c:340
static char speeddial[ADSI_MAX_SPEED_DIAL][3][SPEEDDIAL_MAX_LEN]
Definition: res_adsi.c:70
static int adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Definition: res_adsi.c:880
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
static int adsi_download_disconnect(unsigned char *buf)
Definition: res_adsi.c:818
#define PUT_CLID(byte)
Definition: callerid.h:304
#define PUT_CLID_MARKMS
Definition: callerid.h:289
static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remain)
Definition: res_adsi.c:153
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define ADSI_CLEAR_SCREEN
Definition: adsi.h:56
Data structure associated with a single frame of data.
Definition: frame.h:142
static int total
Definition: res_adsi.c:967
#define ADSI_MAX_INTRO
Definition: res_adsi.c:56
FSK Modem Support.
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_variable * next
Definition: config.h:82
#define ADSI_SWITCH_TO_DATA
Definition: adsi.h:42
#define ast_frfree(fr)
Definition: frame.h:583
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:5837
static int adsi_query_cpeid(unsigned char *buf)
Definition: res_adsi.c:591
static int adsi_set_line(unsigned char *buf, int page, int line)
Definition: res_adsi.c:939
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
static int adsi_download_connect(unsigned char *buf, char *service, unsigned char *fdn, unsigned char *sec, int ver)
Definition: res_adsi.c:544
#define ADSI_JUST_CENT
Definition: adsi.h:114
#define SPEEDDIAL_MAX_LEN
Definition: res_adsi.c:69
static void init_state(void)
Definition: res_adsi.c:1081
#define ADSI_INIT_SOFTKEY_LINE
Definition: adsi.h:37
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define ADSI_INPUT_CONTROL
Definition: adsi.h:45
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
#define ADSI_CONNECT_SESSION
Definition: adsi.h:50