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